gitdataai/libs/agent/tool/call.rs
2026-04-14 19:02:01 +08:00

109 lines
2.6 KiB
Rust

//! 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::Value> {
serde_json::from_str(&self.arguments)
}
pub fn parse_args<T: serde::de::DeserializeOwned>(&self) -> serde_json::Result<T> {
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<T: Serialize>(value: T) -> Self {
Self::Ok(serde_json::to_value(value).unwrap_or(serde_json::Value::Null))
}
pub fn error(message: impl Into<String>) -> 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<serde_json::Error> 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<String>) -> Self {
Self {
call,
result: ToolResult::Error(message.into()),
}
}
pub fn from_result(call: ToolCall, result: ToolResult) -> Self {
Self { call, result }
}
}