fix(background-task): disambiguate background output task ids

This commit is contained in:
YeonGyu-Kim
2026-05-10 14:29:37 +09:00
parent e92f81eba9
commit 50699e3af1
7 changed files with 108 additions and 7 deletions
@@ -65,4 +65,46 @@ describe("createBackgroundOutput metadata", () => {
clearPendingStore()
})
test("explains when a session id is passed as the background task id", async () => {
// #given
const task: BackgroundTask = {
id: "bg-real-task",
sessionId: "ses-child-task",
parentSessionId: "main-1",
parentMessageId: "msg-1",
description: "background task",
prompt: "do work",
agent: "test-agent",
status: "completed",
}
const manager: BackgroundOutputManager = {
getTask: id => (id === task.id ? task : undefined),
}
const client: BackgroundOutputClient = {
session: {
messages: async () => ({ data: [] }),
},
}
const tool = createBackgroundOutput(manager, client)
const context = {
sessionID: "test-session",
messageID: "test-message",
agent: "test-agent",
directory: projectDir,
worktree: projectDir,
abort: new AbortController().signal,
metadata: () => {},
ask: async () => {},
callID: "call-1",
} satisfies ToolContextWithCallID
// #when
const output = await tool.execute({ task_id: "ses-child-task" }, context)
// #then
expect(output).toContain("background_output expects a background task ID")
expect(output).toContain("bg_")
expect(output).toContain('session_read(session_id="ses-child-task")')
})
})
@@ -36,6 +36,22 @@ function appendTimeoutNote(output: string, timeoutMs: number): string {
return `${output}\n\n> **Timed out waiting** after ${timeoutMs}ms. Task is still running; showing latest available output.`
}
function isSessionId(value: string): boolean {
return /^ses[_-]/.test(value)
}
function formatTaskNotFoundMessage(taskId: string): string {
if (!isSessionId(taskId)) {
return `Task not found: ${taskId}`
}
return `Task not found: ${taskId}
background_output expects a background task ID such as \`bg_...\`, not a session ID.
Use the \`background_task_id\` / \`Background Task ID\` from the task launch output or completion notification.
To inspect this session directly, use \`session_read(session_id="${taskId}")\`, \`session_info\`, or \`session_search\`.`
}
export function createBackgroundOutput(manager: BackgroundOutputManager, client: BackgroundOutputClient): ToolDefinition {
return tool({
description: BACKGROUND_OUTPUT_DESCRIPTION,
@@ -60,7 +76,7 @@ export function createBackgroundOutput(manager: BackgroundOutputManager, client:
const ctx = toolContext as ToolContextWithMetadata
const task = manager.getTask(args.task_id)
if (!task) {
return `Task not found: ${args.task_id}`
return formatTaskNotFoundMessage(args.task_id)
}
const meta = {