diff --git a/src/tools/background-task/create-background-output.ts b/src/tools/background-task/create-background-output.ts index c498ddbf..0999aa27 100644 --- a/src/tools/background-task/create-background-output.ts +++ b/src/tools/background-task/create-background-output.ts @@ -1,4 +1,6 @@ import { tool, type ToolDefinition } from "@opencode-ai/plugin" +import type { BackgroundTask } from "../../features/background-agent" +import { storeToolMetadata } from "../../features/tool-metadata-store" import type { BackgroundOutputArgs } from "./types" import type { BackgroundOutputClient, BackgroundOutputManager } from "./clients" import { BACKGROUND_OUTPUT_DESCRIPTION } from "./constants" @@ -7,6 +9,28 @@ import { formatFullSession } from "./full-session-format" import { formatTaskResult } from "./task-result-format" import { formatTaskStatus } from "./task-status-format" +const SISYPHUS_JUNIOR_AGENT = "sisyphus-junior" + +type ToolContextWithMetadata = { + sessionID: string + metadata?: (input: { title?: string; metadata?: Record }) => void + callID?: string + callId?: string + call_id?: string +} + +function resolveToolCallID(ctx: ToolContextWithMetadata): string | undefined { + if (typeof ctx.callID === "string" && ctx.callID.trim() !== "") return ctx.callID + if (typeof ctx.callId === "string" && ctx.callId.trim() !== "") return ctx.callId + if (typeof ctx.call_id === "string" && ctx.call_id.trim() !== "") return ctx.call_id + return undefined +} + +function formatResolvedTitle(task: BackgroundTask): string { + const label = task.agent === SISYPHUS_JUNIOR_AGENT && task.category ? task.category : task.agent + return `${label} - ${task.description}` +} + export function createBackgroundOutput(manager: BackgroundOutputManager, client: BackgroundOutputClient): ToolDefinition { return tool({ description: BACKGROUND_OUTPUT_DESCRIPTION, @@ -26,13 +50,31 @@ export function createBackgroundOutput(manager: BackgroundOutputManager, client: include_tool_results: tool.schema.boolean().optional().describe("Include tool results in full_session output (default: false)"), thinking_max_chars: tool.schema.number().optional().describe("Max characters for thinking content (default: 2000)"), }, - async execute(args: BackgroundOutputArgs) { + async execute(args: BackgroundOutputArgs, toolContext) { try { + const ctx = toolContext as ToolContextWithMetadata const task = manager.getTask(args.task_id) if (!task) { return `Task not found: ${args.task_id}` } + const meta = { + title: formatResolvedTitle(task), + metadata: { + task_id: task.id, + agent: task.agent, + category: task.category, + description: task.description, + sessionId: task.sessionID ?? "pending", + } as Record, + } + ctx.metadata?.(meta) + + const callID = resolveToolCallID(ctx) + if (callID) { + storeToolMetadata(ctx.sessionID, callID, meta) + } + if (args.full_session === true) { return await formatFullSession(task, client, { includeThinking: args.include_thinking === true,