use std::sync::Arc;
use crate::traits::tool::ErasedTool;
pub trait ToolRegistry: Send + Sync {
fn get_tools(&self) -> Vec<Arc<dyn ErasedTool>>;
fn find_tool(&self, name: &str) -> Option<Arc<dyn ErasedTool>> {
self.get_tools()
.into_iter()
.find(|t| t.schema().name == name)
}
fn register(&self, _tool: Arc<dyn ErasedTool>) -> bool {
false
}
fn unregister(&self, _name: &str) -> bool {
false
}
fn set_enabled(&self, _name: &str, _enabled: bool) -> bool {
false
}
fn is_enabled(&self, name: &str) -> bool {
self.find_tool(name).is_some()
}
fn len(&self) -> usize {
self.get_tools().len()
}
fn is_empty(&self) -> bool {
self.len() == 0
}
}
pub struct SimpleRegistry {
tools: Vec<Arc<dyn ErasedTool>>,
}
impl SimpleRegistry {
#[must_use]
pub fn new(tools: Vec<Arc<dyn ErasedTool>>) -> Self {
Self { tools }
}
}
impl ToolRegistry for SimpleRegistry {
fn get_tools(&self) -> Vec<Arc<dyn ErasedTool>> {
self.tools.clone()
}
fn find_tool(&self, name: &str) -> Option<Arc<dyn ErasedTool>> {
self.tools.iter().find(|t| t.schema().name == name).cloned()
}
fn len(&self) -> usize {
self.tools.len()
}
fn is_empty(&self) -> bool {
self.tools.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tool_registry_is_object_safe() {
let registry = SimpleRegistry::new(vec![]);
let _: Arc<dyn ToolRegistry> = Arc::new(registry);
}
#[test]
fn test_simple_registry_empty() {
let registry = SimpleRegistry::new(vec![]);
assert!(registry.is_empty());
assert_eq!(registry.len(), 0);
assert_eq!(registry.get_tools().len(), 0);
assert!(registry.find_tool("nonexistent").is_none());
}
#[test]
fn test_simple_registry_is_read_only() {
let registry = SimpleRegistry::new(vec![]);
assert!(!registry.register(Arc::new(DummyTool)));
assert!(!registry.unregister("dummy"));
assert!(!registry.set_enabled("dummy", false));
}
#[test]
fn test_simple_registry_with_tools() {
let tool: Arc<dyn ErasedTool> = Arc::new(DummyTool);
let registry = SimpleRegistry::new(vec![tool]);
assert_eq!(registry.len(), 1);
assert!(!registry.is_empty());
assert!(registry.find_tool("dummy_tool").is_some());
assert!(registry.find_tool("nonexistent").is_none());
assert!(registry.is_enabled("dummy_tool"));
assert!(!registry.is_enabled("nonexistent"));
}
struct DummyTool;
#[async_trait::async_trait]
impl ErasedTool for DummyTool {
fn name(&self) -> &str {
"dummy_tool"
}
fn description(&self) -> &str {
"A test tool"
}
fn schema(&self) -> crate::traits::tool::ToolSchema {
crate::traits::tool::ToolSchema {
name: "dummy_tool".to_string(),
description: "A test tool".to_string(),
parameters: serde_json::json!({"type": "object", "properties": {}}),
}
}
async fn execute_json(
&self,
_input: serde_json::Value,
) -> crate::Result<serde_json::Value> {
Ok(serde_json::json!("ok"))
}
}
}