* Executes multiple tool calls in parallel and updates state. * Per Gemini docs, all function calls from a single response should be executed * together, with one model message containing all function calls and one user * message containing all function responses.
( functionCallParts: Part[], request: ProviderRequest, state: ExecutionState, forcedTools: string[], logger: ReturnType<typeof createLogger> )
| 95 | * message containing all function responses. |
| 96 | */ |
| 97 | async function executeToolCallsBatch( |
| 98 | functionCallParts: Part[], |
| 99 | request: ProviderRequest, |
| 100 | state: ExecutionState, |
| 101 | forcedTools: string[], |
| 102 | logger: ReturnType<typeof createLogger> |
| 103 | ): Promise<{ success: boolean; state: ExecutionState }> { |
| 104 | if (functionCallParts.length === 0) { |
| 105 | return { success: false, state } |
| 106 | } |
| 107 | |
| 108 | const executionPromises = functionCallParts.map(async (part) => { |
| 109 | const toolCallStartTime = Date.now() |
| 110 | const functionCall = part.functionCall! |
| 111 | const toolName = functionCall.name ?? '' |
| 112 | const args = (functionCall.args ?? {}) as Record<string, unknown> |
| 113 | |
| 114 | const tool = request.tools?.find((t) => t.id === toolName) |
| 115 | if (!tool) { |
| 116 | logger.warn(`Tool ${toolName} not found in registry, skipping`) |
| 117 | return { |
| 118 | success: false, |
| 119 | part, |
| 120 | toolName, |
| 121 | args, |
| 122 | resultContent: { error: true, message: `Tool ${toolName} not found`, tool: toolName }, |
| 123 | toolParams: {}, |
| 124 | startTime: toolCallStartTime, |
| 125 | endTime: Date.now(), |
| 126 | duration: Date.now() - toolCallStartTime, |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | try { |
| 131 | const { toolParams, executionParams } = prepareToolExecution(tool, args, request) |
| 132 | const result = await executeTool(toolName, executionParams, { |
| 133 | signal: request.abortSignal, |
| 134 | }) |
| 135 | const toolCallEndTime = Date.now() |
| 136 | const duration = toolCallEndTime - toolCallStartTime |
| 137 | |
| 138 | const resultContent: Record<string, unknown> = result.success |
| 139 | ? ensureStructResponse(result.output) |
| 140 | : { error: true, message: result.error || 'Tool execution failed', tool: toolName } |
| 141 | |
| 142 | return { |
| 143 | success: result.success, |
| 144 | part, |
| 145 | toolName, |
| 146 | args, |
| 147 | resultContent, |
| 148 | toolParams, |
| 149 | result, |
| 150 | startTime: toolCallStartTime, |
| 151 | endTime: toolCallEndTime, |
| 152 | duration, |
| 153 | } |
| 154 | } catch (error) { |
no test coverage detected