( toolId: string, params: Record<string, unknown>, context: ToolExecutionContext )
| 40 | } |
| 41 | |
| 42 | export async function executeTool( |
| 43 | toolId: string, |
| 44 | params: Record<string, unknown>, |
| 45 | context: ToolExecutionContext |
| 46 | ): Promise<ToolExecutionResult> { |
| 47 | // Client-routed tools (e.g. run_workflow) are normally executed in the browser and never |
| 48 | // reach this point in interactive mode. In headless mode (Mothership block, no browser) there |
| 49 | // is no client to delegate to, so fall back to the registered server-side handler when one |
| 50 | // exists — otherwise the call would route to executeAppTool and throw "Tool not found". |
| 51 | const canUseRegisteredHandler = |
| 52 | isKnownTool(toolId) && |
| 53 | (isSimExecuted(toolId) || (isClientExecuted(toolId) && hasHandler(toolId))) |
| 54 | if (!canUseRegisteredHandler) { |
| 55 | const appParams = buildAppToolParams(toolId, params, context) |
| 56 | return executeAppTool(toolId, appParams) |
| 57 | } |
| 58 | |
| 59 | if (context.abortSignal?.aborted) { |
| 60 | logger.warn('Tool execution skipped: abort signal already set', { |
| 61 | toolId, |
| 62 | abortReason: context.abortSignal.reason ?? 'unknown', |
| 63 | }) |
| 64 | return { success: false, error: 'Execution aborted: abort signal was set before tool started' } |
| 65 | } |
| 66 | |
| 67 | const handler = handlerRegistry.get(toolId) |
| 68 | if (!handler) { |
| 69 | logger.warn('No handler registered for tool', { toolId }) |
| 70 | return { success: false, error: `No handler for tool: ${toolId}` } |
| 71 | } |
| 72 | |
| 73 | try { |
| 74 | return await handler(params, context) |
| 75 | } catch (error) { |
| 76 | const message = toError(error).message |
| 77 | logger.error('Tool execution failed', { |
| 78 | toolId, |
| 79 | error: message, |
| 80 | abortSignalAborted: context.abortSignal?.aborted ?? false, |
| 81 | }) |
| 82 | return { success: false, error: message } |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | async function executeToolBatch( |
| 87 | toolCalls: ToolCallDescriptor[], |
no test coverage detected