diff --git a/src/tools/delegate-task/background-task.test.ts b/src/tools/delegate-task/background-task.test.ts new file mode 100644 index 00000000..cc87586f --- /dev/null +++ b/src/tools/delegate-task/background-task.test.ts @@ -0,0 +1,108 @@ +const bunTest = require("bun:test") +const describeFn = bunTest.describe +const testFn = bunTest.test +const expectFn = bunTest.expect +const beforeEachFn = bunTest.beforeEach +const afterEachFn = bunTest.afterEach + +const { executeBackgroundTask } = require("./background-task") +const { __setTimingConfig, __resetTimingConfig } = require("./timing") + +describeFn("executeBackgroundTask output/session metadata compatibility", () => { + beforeEachFn(() => { + //#given - reduce waiting to keep tests fast + __setTimingConfig({ + WAIT_FOR_SESSION_INTERVAL_MS: 1, + WAIT_FOR_SESSION_TIMEOUT_MS: 2, + }) + }) + + afterEachFn(() => { + __resetTimingConfig() + }) + + testFn("does not emit synthetic pending session metadata when session id is unresolved", async () => { + //#given - launched task without resolved subagent session id + const metadataCalls: any[] = [] + const manager = { + launch: async () => ({ + id: "bg_unresolved", + sessionID: undefined, + description: "Unresolved session", + agent: "explore", + status: "running", + }), + getTask: () => undefined, + } + + const result = await executeBackgroundTask( + { + description: "Unresolved session", + prompt: "check", + run_in_background: true, + load_skills: [], + }, + { + sessionID: "ses_parent", + callID: "call_1", + metadata: async (value: any) => metadataCalls.push(value), + abort: new AbortController().signal, + }, + { manager }, + { sessionID: "ses_parent", messageID: "msg_1" }, + "explore", + undefined, + undefined, + undefined, + ) + + //#then - output and metadata should avoid fake session markers + expectFn(result).not.toContain("") + expectFn(result).not.toContain("session_id: undefined") + expectFn(result).not.toContain("session_id: pending") + expectFn(metadataCalls).toHaveLength(1) + expectFn("sessionId" in metadataCalls[0].metadata).toBe(false) + }) + + testFn("emits task metadata session_id when real session id is available", async () => { + //#given - launched task with resolved subagent session id + const metadataCalls: any[] = [] + const manager = { + launch: async () => ({ + id: "bg_resolved", + sessionID: "ses_sub_123", + description: "Resolved session", + agent: "explore", + status: "running", + }), + getTask: () => ({ sessionID: "ses_sub_123" }), + } + + const result = await executeBackgroundTask( + { + description: "Resolved session", + prompt: "check", + run_in_background: true, + load_skills: [], + }, + { + sessionID: "ses_parent", + callID: "call_2", + metadata: async (value: any) => metadataCalls.push(value), + abort: new AbortController().signal, + }, + { manager }, + { sessionID: "ses_parent", messageID: "msg_2" }, + "explore", + undefined, + undefined, + undefined, + ) + + //#then - output and metadata should include canonical session linkage + expectFn(result).toContain("") + expectFn(result).toContain("session_id: ses_sub_123") + expectFn(metadataCalls).toHaveLength(1) + expectFn(metadataCalls[0].metadata.sessionId).toBe("ses_sub_123") + }) +}) diff --git a/src/tools/delegate-task/background-task.ts b/src/tools/delegate-task/background-task.ts index c01538a5..6aad94ea 100644 --- a/src/tools/delegate-task/background-task.ts +++ b/src/tools/delegate-task/background-task.ts @@ -56,25 +56,31 @@ export async function executeBackgroundTask( SessionCategoryRegistry.register(sessionId, args.category) } + const metadata = { + prompt: args.prompt, + agent: task.agent, + category: args.category, + load_skills: args.load_skills, + description: args.description, + run_in_background: args.run_in_background, + command: args.command, + ...(sessionId ? { sessionId } : {}), + ...(categoryModel ? { model: { providerID: categoryModel.providerID, modelID: categoryModel.modelID } } : {}), + } + const unstableMeta = { title: args.description, - metadata: { - prompt: args.prompt, - agent: task.agent, - category: args.category, - load_skills: args.load_skills, - description: args.description, - run_in_background: args.run_in_background, - sessionId: sessionId ?? "pending", - command: args.command, - model: categoryModel ? { providerID: categoryModel.providerID, modelID: categoryModel.modelID } : undefined, - }, + metadata, } await ctx.metadata?.(unstableMeta) if (ctx.callID) { storeToolMetadata(ctx.sessionID, ctx.callID, unstableMeta) } + const taskMetadataBlock = sessionId + ? `\n\n\nsession_id: ${sessionId}\n` + : "" + return `Background task launched. Task ID: ${task.id} @@ -82,11 +88,7 @@ Description: ${task.description} Agent: ${task.agent}${args.category ? ` (category: ${args.category})` : ""} Status: ${task.status} -System notifies on completion. Use \`background_output\` with task_id="${task.id}" to check. - - -session_id: ${sessionId} -` +System notifies on completion. Use \`background_output\` with task_id="${task.id}" to check.${taskMetadataBlock}` } catch (error) { return formatDetailedError(error, { operation: "Launch background task",