use crate::error::{AgentError, Result};
use async_trait::async_trait;
use serde_json::Value;
use std::collections::HashMap;
use std::sync::Arc;
#[async_trait]
pub trait Tool: Send + Sync {
fn name(&self) -> &str;
fn description(&self) -> &str;
async fn execute(&self, params: Value) -> Result<Value>;
}
#[derive(Clone)]
pub struct ToolRegistry {
tools: Arc<HashMap<String, Arc<dyn Tool>>>,
}
impl ToolRegistry {
pub fn new() -> Self {
Self {
tools: Arc::new(HashMap::new()),
}
}
pub fn register(mut self, tool: Arc<dyn Tool>) -> Self {
let tools = Arc::make_mut(&mut self.tools);
tools.insert(tool.name().to_string(), tool);
self
}
pub fn get(&self, name: &str) -> Option<Arc<dyn Tool>> {
self.tools.get(name).cloned()
}
pub async fn execute(&self, name: &str, params: Value) -> Result<Value> {
let tool = self.get(name)
.ok_or_else(|| AgentError::ToolNotFound(name.to_string()))?;
tool.execute(params).await
.map_err(|e| AgentError::ToolExecutionFailed(e.to_string()))
}
pub fn list_tools(&self) -> Vec<(String, String)> {
self.tools.iter()
.map(|(name, tool)| (name.clone(), tool.description().to_string()))
.collect()
}
}
impl Default for ToolRegistry {
fn default() -> Self {
Self::new()
}
}