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
1 change: 1 addition & 0 deletions packages/opencode/src/session/message-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<typeof SubtaskPart>

Expand Down
63 changes: 41 additions & 22 deletions packages/opencode/src/session/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 ?? ""),
},
Expand Down
1 change: 1 addition & 0 deletions packages/opencode/src/tool/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions packages/sdk/js/src/v2/gen/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ export type Part =
prompt: string
description: string
agent: string
command?: string
}
| ReasoningPart
| FilePart
Expand Down Expand Up @@ -1600,6 +1601,7 @@ export type SubtaskPartInput = {
prompt: string
description: string
agent: string
command?: string
}

export type Command = {
Expand Down
Loading