* @brief Records a tool-use request and dispatches per safety tag. */
| 475 | * @brief Records a tool-use request and dispatches per safety tag. |
| 476 | */ |
| 477 | void AI::Conversation::onToolCallRequested(const QString& callId, |
| 478 | const QString& requestedName, |
| 479 | const QJsonObject& arguments, |
| 480 | const QJsonObject& extras) |
| 481 | { |
| 482 | if (m_cancelled) |
| 483 | return; |
| 484 | |
| 485 | const QString name = m_dispatcher->canonicalToolName(requestedName); |
| 486 | ++m_toolCallCount; |
| 487 | if (m_toolCallCount > kMaxToolCalls) { |
| 488 | qCWarning(serialStudioAI) << "Tool-call budget exceeded; forcing summary"; |
| 489 | m_summaryForced = true; |
| 490 | |
| 491 | m_pendingToolUseBlocks.append(makeToolUseBlock(callId, name, arguments, extras)); |
| 492 | |
| 493 | QJsonObject denial; |
| 494 | denial[QStringLiteral("error")] = |
| 495 | tr("Tool-call budget reached for this turn; no further tools will run."); |
| 496 | recordToolResult(callId, name, denial); |
| 497 | updateToolCallCard(callId, CallStatus::Blocked, denial); |
| 498 | return; |
| 499 | } |
| 500 | |
| 501 | m_pendingToolUseBlocks.append(makeToolUseBlock(callId, name, arguments, extras)); |
| 502 | |
| 503 | ++m_outstandingToolResults; |
| 504 | |
| 505 | if (dispatchMetaTool(callId, name, arguments)) |
| 506 | return; |
| 507 | |
| 508 | dispatchByCallSafety(callId, name, arguments); |
| 509 | } |
| 510 | |
| 511 | /** |
| 512 | * @brief Auto-handles meta-tool calls; returns true when consumed. |
nothing calls this directly
no test coverage detected