Skip to content

Commit f104cff

Browse files
Sg312claude
andcommitted
fix(copilot): failed tool calls must surface their error in terminal data
A failed handler result that carried a defined-but-empty output (the app-tool executor's 'Tool not found' ships output: {}) won the priority race in getToolCallTerminalData, so the resume payload's data — the only thing the model reads — was a bare {} with the error text dropped. The search agent retried run_code 20+ times blind against a stale server because every failure rendered as empty instead of 'Tool not found'. Failed calls now always carry error in their terminal data: merged into object outputs, wrapped alongside non-object outputs, preserved when the output already has an error field. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent e4200af commit f104cff

1 file changed

Lines changed: 21 additions & 5 deletions

File tree

apps/sim/lib/copilot/request/tool-call-state.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,30 @@ export function getToolCallTerminalData(
6060
toolCall: Pick<ToolCallState, 'id' | 'status' | 'result' | 'error'>
6161
): unknown {
6262
const output = getToolCallStateOutput(toolCall)
63+
const failed = !isSuccessfulToolCallStatus(toolCall.status as TerminalToolCallStatus)
64+
6365
if (output !== undefined) {
64-
return output
66+
if (!failed) {
67+
return output
68+
}
69+
/**
70+
* A failed call must always surface its error in the terminal data — this
71+
* is what the model reads on resume. Handlers can fail with an
72+
* empty-but-defined output (the app-tool executor's "Tool not found" ships
73+
* `output: {}`), and preferring that output rendered failures as bare `{}`,
74+
* so the model retried blind instead of reacting to the error.
75+
*/
76+
const error =
77+
typeof toolCall.error === 'string' && toolCall.error.length > 0
78+
? toolCall.error
79+
: 'Tool failed without an error message'
80+
if (output && typeof output === 'object' && !Array.isArray(output)) {
81+
return 'error' in output ? output : { ...output, error }
82+
}
83+
return { output, error }
6584
}
6685

67-
if (
68-
toolCall.status === MothershipStreamV1ToolOutcome.success ||
69-
toolCall.status === MothershipStreamV1ToolOutcome.skipped
70-
) {
86+
if (!failed) {
7187
return undefined
7288
}
7389

0 commit comments

Comments
 (0)