summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-08-04 11:59:42 -0400
committerDax Raad <[email protected]>2025-08-04 12:15:24 -0400
commit0a42068fbbc40f3b5f2ad0eb01f0382d5bafa29c (patch)
tree611b36402c7074e63152caadc2c6a69f9e807414 /packages
parentb05decc572733d37e50d73af0659c78bfe3774d3 (diff)
downloadopencode-0a42068fbbc40f3b5f2ad0eb01f0382d5bafa29c.tar.gz
opencode-0a42068fbbc40f3b5f2ad0eb01f0382d5bafa29c.zip
hack to return tool call errors back to model
Diffstat (limited to 'packages')
-rw-r--r--packages/opencode/src/session/index.ts16
-rw-r--r--packages/opencode/src/tool/invalid.ts17
-rw-r--r--packages/opencode/src/tool/registry.ts2
-rw-r--r--packages/tui/internal/components/chat/message.go6
4 files changed, 41 insertions, 0 deletions
diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts
index 01df6da74..63c135492 100644
--- a/packages/opencode/src/session/index.ts
+++ b/packages/opencode/src/session/index.ts
@@ -13,6 +13,7 @@ import {
type ModelMessage,
stepCountIs,
type StreamTextResult,
+ InvalidToolInputError,
} from "ai"
import PROMPT_INITIALIZE from "../session/prompt/initialize.txt"
@@ -869,7 +870,21 @@ export namespace Session {
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,
+ activeTools: Object.keys(tools).filter((x) => x !== "invalid"),
maxOutputTokens: outputLimit,
abortSignal: abort.signal,
stopWhen: stepCountIs(1000),
@@ -962,6 +977,7 @@ export namespace Session {
if (match) {
const part = await updatePart({
...match,
+ tool: value.toolName,
state: {
status: "running",
input: value.input,
diff --git a/packages/opencode/src/tool/invalid.ts b/packages/opencode/src/tool/invalid.ts
new file mode 100644
index 000000000..4695f1b74
--- /dev/null
+++ b/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: {},
+ }
+ },
+})
diff --git a/packages/opencode/src/tool/registry.ts b/packages/opencode/src/tool/registry.ts
index 497d10785..d33965546 100644
--- a/packages/opencode/src/tool/registry.ts
+++ b/packages/opencode/src/tool/registry.ts
@@ -10,9 +10,11 @@ import { TaskTool } from "./task"
import { TodoWriteTool, TodoReadTool } from "./todo"
import { WebFetchTool } from "./webfetch"
import { WriteTool } from "./write"
+import { InvalidTool } from "./invalid"
export namespace ToolRegistry {
const ALL = [
+ InvalidTool,
BashTool,
EditTool,
WebFetchTool,
diff --git a/packages/tui/internal/components/chat/message.go b/packages/tui/internal/components/chat/message.go
index 29920efdd..f320a3fa3 100644
--- a/packages/tui/internal/components/chat/message.go
+++ b/packages/tui/internal/components/chat/message.go
@@ -555,6 +555,8 @@ func renderToolName(name string) string {
switch name {
case "webfetch":
return "Fetch"
+ case "invalid":
+ return "Invalid"
default:
normalizedName := name
if after, ok := strings.CutPrefix(name, "opencode_"); ok {
@@ -657,6 +659,10 @@ func renderToolTitle(
title = getTodoTitle(toolCall)
case "todoread":
return "Plan"
+ case "invalid":
+ if actualTool, ok := toolArgsMap["tool"].(string); ok {
+ title = renderToolName(actualTool)
+ }
default:
toolName := renderToolName(toolCall.Tool)
title = fmt.Sprintf("%s %s", toolName, toolArgs)