//! Tool call and result types. use serde::{Deserialize, Serialize}; /// A single tool invocation requested by the AI model. #[derive(Debug, Clone)] pub struct ToolCall { pub id: String, pub name: String, pub arguments: String, } impl ToolCall { pub fn arguments_json(&self) -> serde_json::Result { serde_json::from_str(&self.arguments) } pub fn parse_args(&self) -> serde_json::Result { serde_json::from_str(&self.arguments) } } /// The result of executing a tool call. #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum ToolResult { /// Successful result with a JSON value. Ok(serde_json::Value), /// Error result with an error message. Error(String), } impl ToolResult { pub fn ok(value: T) -> Self { Self::Ok(serde_json::to_value(value).unwrap_or(serde_json::Value::Null)) } pub fn error(message: impl Into) -> Self { Self::Error(message.into()) } pub fn is_error(&self) -> bool { matches!(self, Self::Error(_)) } } /// Errors that can occur during tool execution. #[derive(Debug, thiserror::Error)] pub enum ToolError { #[error("tool not found: {0}")] NotFound(String), #[error("argument parse error: {0}")] ParseError(String), #[error("execution error: {0}")] ExecutionError(String), #[error("recursion limit exceeded (max depth: {max_depth})")] RecursionLimitExceeded { max_depth: u32 }, #[error("max tool calls exceeded: {0}")] MaxToolCallsExceeded(usize), #[error("internal error: {0}")] Internal(String), } impl ToolError { pub fn into_result(self) -> ToolResult { ToolResult::Error(self.to_string()) } } impl From for ToolError { fn from(e: serde_json::Error) -> Self { Self::ParseError(e.to_string()) } } /// A completed tool call with its result, ready to be sent back to the AI. #[derive(Debug, Clone)] pub struct ToolCallResult { /// The original tool call. pub call: ToolCall, /// The execution result. pub result: ToolResult, } impl ToolCallResult { pub fn ok(call: ToolCall, value: serde_json::Value) -> Self { Self { call, result: ToolResult::Ok(value), } } pub fn error(call: ToolCall, message: impl Into) -> Self { Self { call, result: ToolResult::Error(message.into()), } } pub fn from_result(call: ToolCall, result: ToolResult) -> Self { Self { call, result } } }