| 282 | } |
| 283 | |
| 284 | export class DefaultToolInvoker implements ToolInvoker { |
| 285 | constructor(private catalog: ToolCatalog) {} |
| 286 | |
| 287 | async invoke( |
| 288 | toolName: string, |
| 289 | args: Record<string, unknown>, |
| 290 | opts: InvokeOptions, |
| 291 | ): Promise<void> { |
| 292 | const resolved = this.catalog.resolve(toolName); |
| 293 | const session = opts.renderSession ?? createRenderSession('text'); |
| 294 | const resolvedOpts = { ...opts, renderSession: session }; |
| 295 | |
| 296 | if (resolved.ambiguous) { |
| 297 | emitExplicitRuntimeError({ |
| 298 | session, |
| 299 | handlerContext: opts.handlerContext, |
| 300 | onStructuredOutput: opts.onStructuredOutput, |
| 301 | code: 'AMBIGUOUS_TOOL', |
| 302 | message: `Ambiguous tool name: Multiple tools match '${toolName}'. Use one of:\n- ${resolved.ambiguous.join('\n- ')}`, |
| 303 | }); |
| 304 | return; |
| 305 | } |
| 306 | |
| 307 | if (resolved.notFound || !resolved.tool) { |
| 308 | emitExplicitRuntimeError({ |
| 309 | session, |
| 310 | handlerContext: opts.handlerContext, |
| 311 | onStructuredOutput: opts.onStructuredOutput, |
| 312 | code: 'TOOL_NOT_FOUND', |
| 313 | message: `Tool not found: Unknown tool '${toolName}'. Run 'xcodebuildmcp tools' to see available tools.`, |
| 314 | }); |
| 315 | return; |
| 316 | } |
| 317 | |
| 318 | return this.executeTool(resolved.tool, args, resolvedOpts); |
| 319 | } |
| 320 | |
| 321 | async invokeDirect( |
| 322 | tool: ToolDefinition, |
| 323 | args: Record<string, unknown>, |
| 324 | opts: InvokeOptions, |
| 325 | ): Promise<void> { |
| 326 | const session = opts.renderSession ?? createRenderSession('text'); |
| 327 | return this.executeTool(tool, args, { ...opts, renderSession: session }); |
| 328 | } |
| 329 | |
| 330 | private async invokeViaDaemon<TResult>( |
| 331 | opts: InvokeOptions, |
| 332 | invoke: (client: DaemonClient) => Promise<TResult>, |
| 333 | context: { |
| 334 | label: string; |
| 335 | errorTitle: string; |
| 336 | captureInfraErrorMetric: (error: unknown) => void; |
| 337 | captureInvocationMetric: (outcome: SentryToolInvocationOutcome) => void; |
| 338 | consumeResult: (result: TResult) => void; |
| 339 | postProcessParams: { |
| 340 | tool: ToolDefinition; |
| 341 | catalog: ToolCatalog; |
nothing calls this directly
no outgoing calls
no test coverage detected