Browse Source

plugin(hook): add task tool execution hooks and command context tracking (#5642)

Spoon 2 months ago
parent
commit
b8a8fb0de6

+ 1 - 0
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<typeof SubtaskPart>
 

+ 41 - 22
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)
@@ -1323,6 +1341,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 ?? ""),
             },

+ 1 - 0
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)

+ 2 - 0
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 = {