pub mod async_tool;
pub use async_tool::AsyncTool;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use crate::TypeError;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentToolDefinition {
pub name: String,
pub description: String,
pub parameters: serde_json::Value, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolCall {
pub tool_name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub call_id: Option<String>,
pub arguments: serde_json::Value,
}
#[derive(Debug)]
pub struct ToolRegistry {
tools: HashMap<String, Box<dyn Tool + Send + Sync>>,
async_tools: HashMap<String, Arc<dyn AsyncTool>>,
}
pub trait Tool: Send + Sync + std::fmt::Debug {
fn name(&self) -> &str;
fn description(&self) -> &str;
fn parameter_schema(&self) -> serde_json::Value;
fn execute(&self, args: serde_json::Value) -> Result<serde_json::Value, TypeError>;
}
impl ToolRegistry {
pub fn new() -> Self {
Self {
tools: HashMap::new(),
async_tools: HashMap::new(),
}
}
pub fn register_tool(&mut self, tool: Box<dyn Tool + Send + Sync>) {
self.tools.insert(tool.name().to_string(), tool);
}
pub fn register_async_tool(&mut self, tool: Arc<dyn AsyncTool>) {
self.async_tools.insert(tool.name().to_string(), tool);
}
pub fn execute(&self, call: &ToolCall) -> Result<serde_json::Value, TypeError> {
self.tools
.get(&call.tool_name)
.ok_or_else(|| TypeError::Error(format!("Tool {} not found", call.tool_name)))?
.execute(call.arguments.clone())
}
pub fn get_definitions(&self) -> Vec<AgentToolDefinition> {
self.tools
.values()
.map(|tool| AgentToolDefinition {
name: tool.name().to_string(),
description: tool.description().to_string(),
parameters: tool.parameter_schema(),
})
.collect()
}
pub fn get_all_definitions(&self) -> Vec<AgentToolDefinition> {
let mut defs: Vec<AgentToolDefinition> = self
.tools
.values()
.map(|tool| AgentToolDefinition {
name: tool.name().to_string(),
description: tool.description().to_string(),
parameters: tool.parameter_schema(),
})
.collect();
for tool in self.async_tools.values() {
defs.push(AgentToolDefinition {
name: tool.name().to_string(),
description: tool.description().to_string(),
parameters: tool.parameter_schema(),
});
}
defs
}
pub fn get_async_tool(&self, name: &str) -> Option<Arc<dyn AsyncTool>> {
self.async_tools.get(name).cloned()
}
pub fn has_sync_tool(&self, name: &str) -> bool {
self.tools.contains_key(name)
}
pub fn len(&self) -> usize {
self.tools.len() + self.async_tools.len()
}
pub fn is_empty(&self) -> bool {
self.tools.is_empty() && self.async_tools.is_empty()
}
}
impl Default for ToolRegistry {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug)]
pub struct ToolCallInfo {
pub name: String,
pub arguments: serde_json::Value,
pub call_id: Option<String>,
pub result: Option<serde_json::Value>,
}