Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
65 changes: 43 additions & 22 deletions packages/opencode/src/session/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,42 +325,62 @@ 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
})
if (result) {
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 +1317,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