diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index 76162c79780..4781b0c47b1 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -160,6 +160,7 @@ export namespace MessageV2 { prompt: z.string(), description: z.string(), agent: z.string(), + command: z.string().optional(), }) export type SubtaskPart = z.infer diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index e71162d0b5d..e63d54787f2 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -325,42 +325,60 @@ export namespace SessionPrompt { prompt: task.prompt, description: task.description, subagent_type: task.agent, + command: task.command, }, time: { start: Date.now(), }, }, })) as MessageV2.ToolPart + const taskArgs = { + prompt: task.prompt, + description: task.description, + subagent_type: task.agent, + command: task.command, + } + await Plugin.trigger( + "tool.execute.before", + { + tool: "task", + sessionID, + callID: part.id, + }, + { args: taskArgs }, + ) let executionError: Error | undefined const result = await taskTool - .execute( - { - prompt: task.prompt, - description: task.description, - subagent_type: task.agent, - }, - { - agent: task.agent, - messageID: assistantMessage.id, - sessionID: sessionID, - abort, - async metadata(input) { - await Session.updatePart({ - ...part, - type: "tool", - state: { - ...part.state, - ...input, - }, - } satisfies MessageV2.ToolPart) - }, + .execute(taskArgs, { + agent: task.agent, + messageID: assistantMessage.id, + sessionID: sessionID, + abort, + async metadata(input) { + await Session.updatePart({ + ...part, + type: "tool", + state: { + ...part.state, + ...input, + }, + } satisfies MessageV2.ToolPart) }, - ) + }) .catch((error) => { executionError = error log.error("subtask execution failed", { error, agent: task.agent, description: task.description }) return undefined }) + await Plugin.trigger( + "tool.execute.after", + { + tool: "task", + sessionID, + callID: part.id, + }, + result, + ) assistantMessage.finish = "tool-calls" assistantMessage.time.completed = Date.now() await Session.updateMessage(assistantMessage) @@ -1297,6 +1315,7 @@ export namespace SessionPrompt { type: "subtask" as const, agent: agent.name, description: command.description ?? "", + command: input.command, // TODO: how can we make task tool accept a more complex input? prompt: await resolvePromptParts(template).then((x) => x.find((y) => y.type === "text")?.text ?? ""), }, diff --git a/packages/opencode/src/tool/task.ts b/packages/opencode/src/tool/task.ts index fdbae41dd08..bc93f497a91 100644 --- a/packages/opencode/src/tool/task.ts +++ b/packages/opencode/src/tool/task.ts @@ -26,6 +26,7 @@ export const TaskTool = Tool.define("task", async () => { prompt: z.string().describe("The task for the agent to perform"), subagent_type: z.string().describe("The type of specialized agent to use for this task"), session_id: z.string().describe("Existing Task session to continue").optional(), + command: z.string().describe("The command that triggered this task").optional(), }), async execute(params, ctx) { const agent = await Agent.get(params.subagent_type) diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index ca8d25fd517..00f209c6d88 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -417,6 +417,7 @@ export type Part = prompt: string description: string agent: string + command?: string } | ReasoningPart | FilePart @@ -1600,6 +1601,7 @@ export type SubtaskPartInput = { prompt: string description: string agent: string + command?: string } export type Command = {