Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions apps/worker/src/run-task/__tests__/run-task.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export type FastAgentReaction = {

export type LaunchFastAgentTask = (params: {
prompt: string;
images?: string[];
environmentId: string | null;
model?: string | null;
parentSessionId: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,12 @@ import { z } from "zod"
import { invoke } from "../roomote-fast-tool-bridge.js"

export default {
description: "Delegate new repository or workspace execution work to a Roomote task, optionally using an exact deployment-enabled model ID from the system prompt.",
description: "Delegate new repository or workspace execution work to a Roomote task, optionally using an exact deployment-enabled model ID. Current-turn images are attached only when includeImages is true.",
args: {
prompt: z.string().min(1).describe("Complete task instruction"),
environmentId: z.string().nullable().optional().describe(${JSON.stringify(`Exact environment ID from the system prompt; omit, pass null, or pass "${ALL_REPOSITORIES}" to run against all active repositories`)}),
model: z.string().min(1).nullable().optional().describe("Exact deployment-enabled model ID; omit or pass null to use the deployment default"),
includeImages: z.boolean().optional().describe("Set true to attach supported images from the active conversation turn; defaults to false"),
kickoffMessage: z.string().min(1).describe("Brief user-facing description of the work now underway; do not mention delegation, launching, or queue state"),
},
execute: (args, context) => invoke("launch_task", args, context),
Expand All @@ -297,10 +298,11 @@ import { z } from "zod"
import { invoke } from "../roomote-fast-tool-bridge.js"

export default {
description: "Send a new instruction to an active or resumable task delegated by this Fast conversation.",
description: "Send a new instruction to an active or resumable task delegated by this Fast conversation. Current-turn images are attached only when includeImages is true.",
args: {
taskId: z.string().nullable().optional(),
message: z.string().min(1),
includeImages: z.boolean().optional().describe("Set true to attach supported images from the active conversation turn; defaults to false"),
},
execute: (args, context) => invoke("send_task_message", args, context),
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ ${formatIntegrationsForPrompt(availableIntegrations)}
- An acknowledgement or progress update does not end the turn. Continue using native tools, then post a closeout or clarification.
- Before calling a deployment MCP tool other than Roomote custom automation management, or canceling a task on a human-authored turn, first post a brief acknowledgement. The runtime rejects those calls until an acknowledgement or progress update has been delivered. Platform events are exempt. Sending a task message is also exempt so steering is not delayed behind a user-visible reply.
- "launch_task" behaves like a normal tool. Do not send a separate acknowledgement before it. Include a brief "kickoffMessage" describing the user's work now underway; the runtime automatically posts that kickoff and task link as a progress artifact for each launch. The kickoff acknowledges the request, but it is not the only communication expected while longer work continues.
- Set "includeImages" on "launch_task" to true only when supported images from the active conversation turn are relevant to the coding task. Omit it otherwise; images are not attached by default.
- If the answer is immediate, call the closeout tool directly.
${reactionGuidance}
- Prefer one direct closeout over an acknowledgement followed immediately by the same answer.
Expand Down Expand Up @@ -219,7 +220,7 @@ ${reactionGuidance}
- Use "launch_task" for new independent repository or workspace work when external inspection, editing, execution, or validation is required, regardless of whether the message is phrased as a question, request, or declarative feedback. Existing active tasks do not block a new independent task.
- You may launch multiple independent tasks in one turn. Each successful launch posts its own kickoff automatically, and the turn remains open for more tools.
- Set "model" on "launch_task" only to an exact ID from Available Delegated Task Models when a specific model is useful or requested. Omit it to use the deployment default. Never invent or abbreviate model IDs.
- Use "send_task_message" when an active or resumable task is listed above and the user clearly gives that task a new instruction. Call it immediately, before an acknowledgement or other user-visible response, so the instruction reaches the task without an extra inference round. A resumable settled task continues under the same task identity. Set "taskId" when needed; with exactly one listed task, omit it or use null. Afterward, post a concise closeout confirming the outcome when useful.
- Use "send_task_message" when an active or resumable task is listed above and the user clearly gives that task a new instruction. Call it immediately, before an acknowledgement or other user-visible response, so the instruction reaches the task without an extra inference round. Set "includeImages" to true only when supported images from the active conversation turn are relevant to that instruction; omit it otherwise. A resumable settled task continues under the same task identity. Set "taskId" when needed; with exactly one listed task, omit it or use null. Afterward, post a concise closeout confirming the outcome when useful.
- Use \`roomote_manage_tasks\` to inspect tasks in this deployment. Use "get_summary" for current status and failures, "get_messages" for transcript details, and "get_compute_logs" for runtime output when supported. Keep using "launch_task", "send_task_message", or "cancel_task" for task changes so Fast conversation kickoff and follow-up behavior is preserved.
- Use \`roomote_get_chat_message_context\` or \`roomote_get_chat_channel_messages\` for additional chat context. Pass the target channel or message reference required by the native tool schema. Slack channel history defaults to the previous 24 hours when \`oldest\` is omitted.
- Never send conversational acknowledgements to a task. "Okay", "cool", "thanks", status questions, and similar conversation are addressed to you. Use a user-visible chat tool.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,13 @@ const launchTaskArgsSchema = z.object({
prompt: z.string().trim().min(1),
environmentId: z.string().trim().min(1).nullable().optional(),
model: z.string().trim().min(1).nullable().optional(),
includeImages: z.boolean().optional().default(false),
kickoffMessage: z.string().trim().min(1),
});
const taskMessageArgsSchema = z.object({
taskId: z.string().trim().min(1).nullable().optional(),
message: z.string().trim().min(1),
includeImages: z.boolean().optional().default(false),
});
const taskIdArgsSchema = z.object({
taskId: z.string().trim().min(1).nullable().optional(),
Expand Down Expand Up @@ -1601,6 +1603,7 @@ export async function answerFastAgentQuestion({
args.prompt,
args.environmentId ?? null,
args.model ?? null,
args.includeImages,
])}`;
if (completedTaskActions.has(signature)) {
return {
Expand Down Expand Up @@ -1635,6 +1638,7 @@ export async function answerFastAgentQuestion({
throwIfTurnCancelled();
const result = await adapter.launchTask({
prompt: args.prompt,
...(args.includeImages && images.length > 0 ? { images } : {}),
environmentId: args.environmentId ?? null,
model: args.model ?? null,
parentSessionId: session.id,
Expand Down Expand Up @@ -1667,7 +1671,11 @@ export async function answerFastAgentQuestion({
throwIfTurnCancelled();
const result = await sendFastAgentTaskMessage(
{ userId, apiBaseUrl },
{ taskId: target.taskId, message: args.message },
{
taskId: target.taskId,
message: args.message,
...(args.includeImages && images.length > 0 ? { images } : {}),
},
);
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,27 @@ export function createFastAgentTaskLauncher(
): LaunchFastAgentTask {
return async ({
prompt,
images,
environmentId,
model,
parentSessionId,
postKickoff,
}) => {
const task = await params.buildTask({
const builtTask = await params.buildTask({
prompt,
environmentId,
model,
parentSessionId,
});
const task = images?.length
? {
...builtTask,
payload: {
...builtTask.payload,
images,
},
}
: builtTask;
let taskUrl: string | undefined;
let preparedTaskRun: { id: number; taskId: string } | undefined;

Expand Down
Loading
Loading