Skip to main content

synaptic_tools/
lib.rs

1pub mod brave;
2pub mod calculator;
3pub mod duckduckgo;
4mod handle_error;
5pub mod jina_reader;
6mod parallel_executor;
7mod return_direct;
8pub mod wikipedia;
9
10pub use brave::BraveSearchTool;
11pub use calculator::CalculatorTool;
12pub use duckduckgo::DuckDuckGoTool;
13pub use handle_error::HandleErrorTool;
14pub use jina_reader::JinaReaderTool;
15pub use parallel_executor::ParallelToolExecutor;
16pub use return_direct::ReturnDirectTool;
17pub use wikipedia::WikipediaTool;
18
19use std::{
20    collections::HashMap,
21    sync::{Arc, RwLock},
22};
23
24use synaptic_core::{SynapticError, Tool};
25
26/// Thread-safe registry for tool definitions and implementations, backed by `Arc<RwLock<HashMap>>`.
27#[derive(Default, Clone)]
28pub struct ToolRegistry {
29    inner: Arc<RwLock<HashMap<String, Arc<dyn Tool>>>>,
30}
31
32impl ToolRegistry {
33    pub fn new() -> Self {
34        Self::default()
35    }
36
37    pub fn register(&self, tool: Arc<dyn Tool>) -> Result<(), SynapticError> {
38        let mut guard = self
39            .inner
40            .write()
41            .map_err(|e| SynapticError::Tool(format!("registry lock poisoned: {e}")))?;
42        guard.insert(tool.name().to_string(), tool);
43        Ok(())
44    }
45
46    pub fn get(&self, name: &str) -> Option<Arc<dyn Tool>> {
47        let guard = self.inner.read().ok()?;
48        guard.get(name).cloned()
49    }
50}
51
52/// Executes tool calls sequentially, looking up tools in a `ToolRegistry`.
53#[derive(Clone)]
54pub struct SerialToolExecutor {
55    registry: ToolRegistry,
56}
57
58impl SerialToolExecutor {
59    pub fn new(registry: ToolRegistry) -> Self {
60        Self { registry }
61    }
62
63    pub async fn execute(
64        &self,
65        tool_name: &str,
66        args: serde_json::Value,
67    ) -> Result<serde_json::Value, SynapticError> {
68        let tool = self
69            .registry
70            .get(tool_name)
71            .ok_or_else(|| SynapticError::ToolNotFound(tool_name.to_string()))?;
72        tool.call(args).await
73    }
74}