1use crate::types::ToolDefinition;
2use async_trait::async_trait;
3use anyhow::{Result, anyhow};
4use std::collections::HashMap;
5use std::sync::Arc;
6
7#[async_trait]
8pub trait Tool: Send + Sync {
9 fn name(&self) -> &str;
10 fn description(&self) -> Option<&str>;
11 fn parameters(&self) -> serde_json::Value;
12 async fn call(&self, arguments: serde_json::Value) -> Result<serde_json::Value>;
13}
14
15pub struct ToolRegistry {
16 tools: HashMap<String, Arc<dyn Tool>>,
17}
18
19impl ToolRegistry {
20 pub fn new() -> Self {
21 Self {
22 tools: HashMap::new(),
23 }
24 }
25
26 pub fn register(&mut self, tool: Arc<dyn Tool>) {
27 let name = tool.name().to_string();
28 self.tools.insert(name, tool);
29 }
30
31 pub fn get(&self, name: &str) -> Option<&Arc<dyn Tool>> {
32 self.tools.get(name)
33 }
34
35 pub fn list(&self) -> Vec<ToolDefinition> {
36 self.tools.values().map(|t| ToolDefinition {
37 name: t.name().to_string(),
38 description: t.description().map(|s| s.to_string()),
39 parameters: t.parameters(),
40 }).collect()
41 }
42
43 pub async fn call_tool(&self, name: &str, arguments: serde_json::Value) -> Result<serde_json::Value> {
44 let tool = self.get(name).ok_or_else(|| anyhow!("Tool {} not found", name))?;
45 tool.call(arguments).await
46 }
47}