pub mod brave;
pub mod calculator;
pub mod duckduckgo;
pub mod filter;
mod handle_error;
pub mod jina_reader;
mod parallel_executor;
mod return_direct;
pub mod wikipedia;
pub use brave::BraveSearchTool;
pub use calculator::CalculatorTool;
pub use duckduckgo::DuckDuckGoTool;
pub use filter::{
AllowListFilter, CompositeFilter, DenyListFilter, FilterContext, StateMachineFilter, ToolFilter,
};
pub use handle_error::HandleErrorTool;
pub use jina_reader::JinaReaderTool;
pub use parallel_executor::ParallelToolExecutor;
pub use return_direct::ReturnDirectTool;
pub use wikipedia::WikipediaTool;
use std::{
collections::HashMap,
sync::{Arc, RwLock},
};
use synaptic_core::{SynapticError, Tool};
#[derive(Default, Clone)]
pub struct ToolRegistry {
inner: Arc<RwLock<HashMap<String, Arc<dyn Tool>>>>,
}
impl ToolRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn register(&self, tool: Arc<dyn Tool>) -> Result<(), SynapticError> {
let mut guard = self
.inner
.write()
.map_err(|e| SynapticError::Tool(format!("registry lock poisoned: {e}")))?;
guard.insert(tool.name().to_string(), tool);
Ok(())
}
pub fn get(&self, name: &str) -> Option<Arc<dyn Tool>> {
let guard = self.inner.read().ok()?;
guard.get(name).cloned()
}
}
#[derive(Clone)]
pub struct SerialToolExecutor {
registry: ToolRegistry,
}
impl SerialToolExecutor {
pub fn new(registry: ToolRegistry) -> Self {
Self { registry }
}
pub async fn execute(
&self,
tool_name: &str,
args: serde_json::Value,
) -> Result<serde_json::Value, SynapticError> {
let tool = self
.registry
.get(tool_name)
.ok_or_else(|| SynapticError::ToolNotFound(tool_name.to_string()))?;
tool.call(args).await
}
}