Skip to main content

hyper_agent_ai/
tool_registry.rs

1use motosan_chat_tool::{Tool, ToolContext, ToolDef, ToolResult, Value};
2use std::collections::HashMap;
3use std::sync::Arc;
4use tokio::sync::RwLock;
5
6pub struct ToolRegistry {
7    inner: Arc<RwLock<HashMap<String, Arc<dyn Tool>>>>,
8}
9
10impl ToolRegistry {
11    pub fn new() -> Self {
12        Self {
13            inner: Arc::new(RwLock::new(HashMap::new())),
14        }
15    }
16
17    pub async fn register(&self, tool: Arc<dyn Tool>) {
18        let def = tool.def();
19        self.inner.write().await.insert(def.name.clone(), tool);
20    }
21
22    pub async fn get(&self, name: &str) -> Option<Arc<dyn Tool>> {
23        self.inner.read().await.get(name).cloned()
24    }
25
26    pub async fn list(&self) -> Vec<ToolDef> {
27        self.inner.read().await.values().map(|t| t.def()).collect()
28    }
29
30    pub async fn execute(&self, name: &str, input: Value, ctx: ToolContext) -> Option<ToolResult> {
31        let tool = self.get(name).await?;
32        Some(tool.call(input, &ctx).await)
33    }
34}
35
36impl Default for ToolRegistry {
37    fn default() -> Self {
38        Self::new()
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45    use crate::tools::DoNothingTool;
46
47    #[tokio::test]
48    async fn register_and_list() {
49        let registry = ToolRegistry::new();
50        registry.register(Arc::new(DoNothingTool)).await;
51        let tools = registry.list().await;
52        assert_eq!(tools.len(), 1);
53        assert_eq!(tools[0].name, "do_nothing");
54    }
55
56    #[tokio::test]
57    async fn get_returns_none_for_unknown() {
58        let registry = ToolRegistry::new();
59        assert!(registry.get("nonexistent").await.is_none());
60    }
61}