From f147109da7ca709c8c6c269a59c61d44601eb0a6 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 12 Nov 2025 10:52:12 +0100 Subject: [PATCH] Fix coding agent tools to return error content instead of throwing Tools now resolve with error messages in content blocks rather than rejecting the promise. This matches the expected behavior where tools always return a result, with errors indicated in the text content. - read: Return error content for missing files - edit: Return error content for missing files, text not found, multiple matches - bash: Return error content for command failures, timeouts, and aborts - All tools now include required details field in error results --- packages/coding-agent/src/tools/bash.ts | 11 ++++++--- packages/coding-agent/src/tools/edit.ts | 33 ++++++++++++++++--------- packages/coding-agent/src/tools/read.ts | 5 +++- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/packages/coding-agent/src/tools/bash.ts b/packages/coding-agent/src/tools/bash.ts index d34b5d77..4fdb8619 100644 --- a/packages/coding-agent/src/tools/bash.ts +++ b/packages/coding-agent/src/tools/bash.ts @@ -13,7 +13,7 @@ export const bashTool: AgentTool = { "Execute a bash command in the current working directory. Returns stdout and stderr. Commands run with a 30 second timeout.", parameters: bashSchema, execute: async (_toolCallId: string, { command }: { command: string }, signal?: AbortSignal) => { - return new Promise((resolve, reject) => { + return new Promise((resolve, _reject) => { const child = spawn("sh", ["-c", command], { detached: true, stdio: ["ignore", "pipe", "pipe"], @@ -67,7 +67,7 @@ export const bashTool: AgentTool = { } if (output) output += "\n\n"; output += "Command aborted"; - reject(new Error(output)); + resolve({ content: [{ type: "text", text: `Command failed\n\n${output}` }], details: undefined }); return; } @@ -80,7 +80,7 @@ export const bashTool: AgentTool = { } if (output) output += "\n\n"; output += "Command timed out after 30 seconds"; - reject(new Error(output)); + resolve({ content: [{ type: "text", text: `Command failed\n\n${output}` }], details: undefined }); return; } @@ -93,7 +93,10 @@ export const bashTool: AgentTool = { if (code !== 0 && code !== null) { if (output) output += "\n\n"; - reject(new Error(`${output}Command exited with code ${code}`)); + resolve({ + content: [{ type: "text", text: `Command failed\n\n${output}Command exited with code ${code}` }], + details: undefined, + }); } else { resolve({ content: [{ type: "text", text: output || "(no output)" }], details: undefined }); } diff --git a/packages/coding-agent/src/tools/edit.ts b/packages/coding-agent/src/tools/edit.ts index 3d5832f4..ead1a8dd 100644 --- a/packages/coding-agent/src/tools/edit.ts +++ b/packages/coding-agent/src/tools/edit.ts @@ -66,7 +66,10 @@ export const editTool: AgentTool = { if (signal) { signal.removeEventListener("abort", onAbort); } - reject(new Error(`File not found: ${path}`)); + resolve({ + content: [{ type: "text", text: `Error: File not found: ${path}` }], + details: undefined, + }); return; } @@ -88,11 +91,15 @@ export const editTool: AgentTool = { if (signal) { signal.removeEventListener("abort", onAbort); } - reject( - new Error( - `Could not find the exact text in ${path}. The old text must match exactly including all whitespace and newlines.`, - ), - ); + resolve({ + content: [ + { + type: "text", + text: `Error: Could not find the exact text in ${path}. The old text must match exactly including all whitespace and newlines.`, + }, + ], + details: undefined, + }); return; } @@ -103,11 +110,15 @@ export const editTool: AgentTool = { if (signal) { signal.removeEventListener("abort", onAbort); } - reject( - new Error( - `Found ${occurrences} occurrences of the text in ${path}. The text must be unique. Please provide more context to make it unique.`, - ), - ); + resolve({ + content: [ + { + type: "text", + text: `Error: Found ${occurrences} occurrences of the text in ${path}. The text must be unique. Please provide more context to make it unique.`, + }, + ], + details: undefined, + }); return; } diff --git a/packages/coding-agent/src/tools/read.ts b/packages/coding-agent/src/tools/read.ts index 6ffe69e9..cfaf1954 100644 --- a/packages/coding-agent/src/tools/read.ts +++ b/packages/coding-agent/src/tools/read.ts @@ -82,7 +82,10 @@ export const readTool: AgentTool = { if (signal) { signal.removeEventListener("abort", onAbort); } - reject(new Error(`File not found: ${path}`)); + resolve({ + content: [{ type: "text", text: `Error: File not found: ${path}` }], + details: undefined, + }); return; }