فهرست منبع

hack to return tool call errors back to model

Dax Raad 6 ماه پیش
والد
کامیت
0a42068fbb

+ 16 - 0
packages/opencode/src/session/index.ts

@@ -13,6 +13,7 @@ import {
   type ModelMessage,
   type ModelMessage,
   stepCountIs,
   stepCountIs,
   type StreamTextResult,
   type StreamTextResult,
+  InvalidToolInputError,
 } from "ai"
 } from "ai"
 
 
 import PROMPT_INITIALIZE from "../session/prompt/initialize.txt"
 import PROMPT_INITIALIZE from "../session/prompt/initialize.txt"
@@ -869,7 +870,21 @@ export namespace Session {
           messages,
           messages,
         }
         }
       },
       },
+      async experimental_repairToolCall(input) {
+        if (InvalidToolInputError.isInstance(input.error)) {
+          return {
+            ...input.toolCall,
+            input: JSON.stringify({
+              tool: input.toolCall.toolName,
+              error: input.error.message,
+            }),
+            toolName: "invalid",
+          }
+        }
+        return null
+      },
       maxRetries: 3,
       maxRetries: 3,
+      activeTools: Object.keys(tools).filter((x) => x !== "invalid"),
       maxOutputTokens: outputLimit,
       maxOutputTokens: outputLimit,
       abortSignal: abort.signal,
       abortSignal: abort.signal,
       stopWhen: stepCountIs(1000),
       stopWhen: stepCountIs(1000),
@@ -962,6 +977,7 @@ export namespace Session {
                 if (match) {
                 if (match) {
                   const part = await updatePart({
                   const part = await updatePart({
                     ...match,
                     ...match,
+                    tool: value.toolName,
                     state: {
                     state: {
                       status: "running",
                       status: "running",
                       input: value.input,
                       input: value.input,

+ 17 - 0
packages/opencode/src/tool/invalid.ts

@@ -0,0 +1,17 @@
+import { z } from "zod"
+import { Tool } from "./tool"
+
+export const InvalidTool = Tool.define("invalid", {
+  description: "Do not use",
+  parameters: z.object({
+    tool: z.string(),
+    error: z.string(),
+  }),
+  async execute(params) {
+    return {
+      title: "Invalid Tool",
+      output: `The arguments provided to the tool are invalid: ${params.error}`,
+      metadata: {},
+    }
+  },
+})

+ 2 - 0
packages/opencode/src/tool/registry.ts

@@ -10,9 +10,11 @@ import { TaskTool } from "./task"
 import { TodoWriteTool, TodoReadTool } from "./todo"
 import { TodoWriteTool, TodoReadTool } from "./todo"
 import { WebFetchTool } from "./webfetch"
 import { WebFetchTool } from "./webfetch"
 import { WriteTool } from "./write"
 import { WriteTool } from "./write"
+import { InvalidTool } from "./invalid"
 
 
 export namespace ToolRegistry {
 export namespace ToolRegistry {
   const ALL = [
   const ALL = [
+    InvalidTool,
     BashTool,
     BashTool,
     EditTool,
     EditTool,
     WebFetchTool,
     WebFetchTool,

+ 6 - 0
packages/tui/internal/components/chat/message.go

@@ -555,6 +555,8 @@ func renderToolName(name string) string {
 	switch name {
 	switch name {
 	case "webfetch":
 	case "webfetch":
 		return "Fetch"
 		return "Fetch"
+	case "invalid":
+		return "Invalid"
 	default:
 	default:
 		normalizedName := name
 		normalizedName := name
 		if after, ok := strings.CutPrefix(name, "opencode_"); ok {
 		if after, ok := strings.CutPrefix(name, "opencode_"); ok {
@@ -657,6 +659,10 @@ func renderToolTitle(
 		title = getTodoTitle(toolCall)
 		title = getTodoTitle(toolCall)
 	case "todoread":
 	case "todoread":
 		return "Plan"
 		return "Plan"
+	case "invalid":
+		if actualTool, ok := toolArgsMap["tool"].(string); ok {
+			title = renderToolName(actualTool)
+		}
 	default:
 	default:
 		toolName := renderToolName(toolCall.Tool)
 		toolName := renderToolName(toolCall.Tool)
 		title = fmt.Sprintf("%s %s", toolName, toolArgs)
 		title = fmt.Sprintf("%s %s", toolName, toolArgs)