fix: return Error objects from invokeFunctionTool and create error invocations (#5351) * fix: return Error objects from invokeFunctionTool and create error invocations invokeFunctionTool previously called .toString() on caught errors, converting them to plain strings. This made the instanceof Error check in invokeFunctionTools dead code. Changes: - Return Error objects directly from invokeFunctionTool - Create error invocations with error: true flag when tools fail - Record failed stealth tools in stealthCalls - Preserve signature/reasoning on error invocations - Add error field to ToolInvocation typedef * fix: use Error.toString to avoid behavioral changes --------- Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>

b89293418d085f0e1522892dd65a9ca7da218177

Xiangzhe <32761048+xz-dev@users.noreply.github.com>

Signed
1 files changed, +20 -4Showing whitespace changes
public/scripts/tool-calling.js+20 -4
@@ -21,11 +21,12 @@ import { isTrueBoolean } from './utils.js';
2121 * @property {string} result - The result of the tool invocation.
2222 * @property {string?} signature - The thought signature associated with the tool invocation.
2323 * @property {string?} reasoning - The plaintext reasoning associated with this tool call turn.
24+ * @property {boolean} [error] - Whether the tool invocation failed.
2425 */
2526
2627/**
2728 * @typedef {object} ToolInvocationResult
2829 * @property {ToolInvocation[]} invocations Successful toolTool invocations (both successful and failed)
2930 * @property {Error[]} errors Errors that occurred during tool invocation
3031 * @property {string[]} stealthCalls Names of stealth tools that were invoked
3132 */
@@ -336,10 +337,10 @@ export class ToolManager {
336337
337338 if (error instanceof Error) {
338339 error.cause = name;
339340 return error.toString();
340341 }
341342
342343 return new Error('Unknown error occurred while invoking the tool.', { cause: name }).toString();
343344 }
344345 }
345346
@@ -796,9 +797,23 @@ export class ToolManager {
796797 toastr.clear(toast);
797798 console.log('[ToolManager] Function tool result:', result);
798799
799- // Save a successful invocation
800+ // Handle tool errors — still create an invocation so the LLM sees the failure
800801 if (toolResult instanceof Error) {
801802 result.errors.push(toolResult);
803+ if (isStealth) {
804+ result.stealthCalls.push(name);
805+ } else {
806+ result.invocations.push({
807+ id,
808+ displayName,
809+ name,
810+ parameters: stringify(parameters),
811+ result: toolResult.toString(),
812+ error: true,
813+ signature: toolCall.signature || null,
814+ reasoning: reasoningText || null,
815+ });
816+ }
802817 continue;
803818 }
804819
@@ -814,6 +829,7 @@ export class ToolManager {
814829 name,
815830 parameters: stringify(parameters),
816831 result: toolResult,
832+ error: false,
817833 signature: toolCall.signature || null,
818834 reasoning: reasoningText || null,
819835 };