(backend UseChatBackend, stopReason *uctypes.WaveStopReason, chatOpts uctypes.WaveChatOpts, sseHandler *sse.SSEHandlerCh, metrics *uctypes.AIMetrics)
| 327 | } |
| 328 | |
| 329 | func processAllToolCalls(backend UseChatBackend, stopReason *uctypes.WaveStopReason, chatOpts uctypes.WaveChatOpts, sseHandler *sse.SSEHandlerCh, metrics *uctypes.AIMetrics) { |
| 330 | // Create and send all data-tooluse packets at the beginning |
| 331 | for i := range stopReason.ToolCalls { |
| 332 | toolCall := &stopReason.ToolCalls[i] |
| 333 | // Create toolUseData from the tool call input |
| 334 | var argsJSON string |
| 335 | if toolCall.Input != nil { |
| 336 | argsBytes, err := json.Marshal(toolCall.Input) |
| 337 | if err == nil { |
| 338 | argsJSON = string(argsBytes) |
| 339 | } |
| 340 | } |
| 341 | toolUseData := aiutil.CreateToolUseData(toolCall.ID, toolCall.Name, argsJSON, chatOpts) |
| 342 | stopReason.ToolCalls[i].ToolUseData = &toolUseData |
| 343 | log.Printf("AI data-tooluse %s\n", toolCall.ID) |
| 344 | _ = sseHandler.AiMsgData("data-tooluse", toolCall.ID, toolUseData) |
| 345 | updateToolUseDataInChat(backend, chatOpts, toolCall.ID, toolUseData) |
| 346 | if toolUseData.Approval == uctypes.ApprovalNeedsApproval { |
| 347 | RegisterToolApproval(toolCall.ID, sseHandler) |
| 348 | } |
| 349 | } |
| 350 | // At this point, all ToolCalls are guaranteed to have non-nil ToolUseData |
| 351 | |
| 352 | var toolResults []uctypes.AIToolResult |
| 353 | for _, toolCall := range stopReason.ToolCalls { |
| 354 | if sseHandler.Err() != nil { |
| 355 | log.Printf("AI tool processing stopped: %v\n", sseHandler.Err()) |
| 356 | break |
| 357 | } |
| 358 | result := processToolCall(backend, toolCall, chatOpts, sseHandler, metrics) |
| 359 | toolResults = append(toolResults, result) |
| 360 | } |
| 361 | |
| 362 | // Cleanup: unregister approvals, remove incomplete/canceled tool calls, and filter results |
| 363 | var filteredResults []uctypes.AIToolResult |
| 364 | for i, toolCall := range stopReason.ToolCalls { |
| 365 | UnregisterToolApproval(toolCall.ID) |
| 366 | hasResult := i < len(toolResults) |
| 367 | shouldRemove := !hasResult || (toolCall.ToolUseData != nil && toolCall.ToolUseData.Approval == uctypes.ApprovalCanceled) |
| 368 | if shouldRemove { |
| 369 | backend.RemoveToolUseCall(chatOpts.ChatId, toolCall.ID) |
| 370 | } else if hasResult { |
| 371 | filteredResults = append(filteredResults, toolResults[i]) |
| 372 | } |
| 373 | } |
| 374 | |
| 375 | if len(filteredResults) > 0 { |
| 376 | toolResultMsgs, err := backend.ConvertToolResultsToNativeChatMessage(filteredResults) |
| 377 | if err != nil { |
| 378 | log.Printf("Failed to convert tool results to native chat messages: %v", err) |
| 379 | } else { |
| 380 | for _, msg := range toolResultMsgs { |
| 381 | if err := chatstore.DefaultChatStore.PostMessage(chatOpts.ChatId, &chatOpts.Config, msg); err != nil { |
| 382 | log.Printf("Failed to post tool result message: %v", err) |
| 383 | } |
| 384 | } |
| 385 | } |
| 386 | } |
no test coverage detected