| 10 | namespace ai { |
| 11 | |
| 12 | ToolResult ToolExecutor::execute_tool(const ToolCall& tool_call, |
| 13 | const ToolSet& tools, |
| 14 | const Messages& messages) { |
| 15 | // Validate tool call |
| 16 | if (!tool_call.is_valid()) { |
| 17 | return ToolResult( |
| 18 | tool_call.id, tool_call.tool_name, tool_call.arguments, |
| 19 | std::string("Invalid tool call: missing required fields")); |
| 20 | } |
| 21 | |
| 22 | // Check if tool exists |
| 23 | auto tool_it = tools.find(tool_call.tool_name); |
| 24 | if (tool_it == tools.end()) { |
| 25 | return ToolResult( |
| 26 | tool_call.id, tool_call.tool_name, tool_call.arguments, |
| 27 | std::string("Tool not found: '" + tool_call.tool_name + "'")); |
| 28 | } |
| 29 | |
| 30 | const Tool& tool = tool_it->second; |
| 31 | |
| 32 | // Validate arguments against schema |
| 33 | if (!validate_tool_call(tool_call, tool)) { |
| 34 | return ToolResult( |
| 35 | tool_call.id, tool_call.tool_name, tool_call.arguments, |
| 36 | std::string("Invalid arguments for tool '" + tool_call.tool_name + |
| 37 | "': " + tool_call.arguments.dump())); |
| 38 | } |
| 39 | |
| 40 | // Check if tool has execution function |
| 41 | if (!tool.has_execute()) { |
| 42 | // Tool has no execution function - return the call for forwarding to client |
| 43 | return ToolResult( |
| 44 | tool_call.id, tool_call.tool_name, tool_call.arguments, |
| 45 | JsonValue(std::string( |
| 46 | "Tool call forwarded to client (no execute function)"))); |
| 47 | } |
| 48 | |
| 49 | // Create execution context |
| 50 | ToolExecutionContext context; |
| 51 | context.tool_call_id = tool_call.id; |
| 52 | context.messages = messages; |
| 53 | |
| 54 | try { |
| 55 | if (tool.is_async()) { |
| 56 | return execute_async_tool(tool_call, tool, context); |
| 57 | } else { |
| 58 | return execute_sync_tool(tool_call, tool, context); |
| 59 | } |
| 60 | } catch (const std::exception& e) { |
| 61 | // Return error result instead of throwing to allow graceful handling |
| 62 | return ToolResult( |
| 63 | tool_call.id, tool_call.tool_name, tool_call.arguments, |
| 64 | std::string("Tool execution failed: " + std::string(e.what()))); |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | std::vector<ToolResult> ToolExecutor::execute_tools( |
| 69 | const std::vector<ToolCall>& tool_calls, |
nothing calls this directly
no test coverage detected