1pub mod batch;
2pub mod file;
3pub mod glob;
4pub mod grep;
5pub mod multiedit;
6pub mod patch;
7pub mod shell;
8pub mod web;
9
10use crate::provider::ToolDefinition;
11
12pub trait Tool: Send + Sync {
13 fn name(&self) -> &str;
14 fn description(&self) -> &str;
15 fn input_schema(&self) -> serde_json::Value;
16 fn execute(&self, input: serde_json::Value) -> anyhow::Result<String>;
17}
18
19pub struct ToolRegistry {
20 tools: Vec<Box<dyn Tool>>,
21}
22
23impl ToolRegistry {
24 pub fn new() -> Self {
25 ToolRegistry { tools: Vec::new() }
26 }
27
28 pub fn register(&mut self, tool: Box<dyn Tool>) {
29 self.tools.push(tool);
30 }
31
32 pub fn register_many(&mut self, tools: Vec<Box<dyn Tool>>) {
33 self.tools.extend(tools);
34 }
35
36 pub fn definitions(&self) -> Vec<ToolDefinition> {
37 self.tools
38 .iter()
39 .map(|t| ToolDefinition {
40 name: t.name().to_string(),
41 description: t.description().to_string(),
42 input_schema: t.input_schema(),
43 })
44 .collect()
45 }
46
47 pub fn definitions_filtered(
51 &self,
52 filter: &std::collections::HashMap<String, bool>,
53 ) -> Vec<ToolDefinition> {
54 if filter.is_empty() {
55 return self.definitions();
56 }
57 self.tools
58 .iter()
59 .filter(|t| filter.get(t.name()).copied().unwrap_or(true))
60 .map(|t| ToolDefinition {
61 name: t.name().to_string(),
62 description: t.description().to_string(),
63 input_schema: t.input_schema(),
64 })
65 .collect()
66 }
67
68 pub fn execute(&self, name: &str, input: serde_json::Value) -> anyhow::Result<String> {
69 for tool in &self.tools {
70 if tool.name() == name {
71 tracing::debug!("Executing tool: {}", name);
72 return tool.execute(input);
73 }
74 }
75 anyhow::bail!("Unknown tool: {}", name)
76 }
77
78 pub fn tool_count(&self) -> usize {
79 self.tools.len()
80 }
81
82 pub fn default_tools() -> Self {
83 let mut registry = Self::new();
84 registry.register(Box::new(file::ReadFileTool));
85 registry.register(Box::new(file::WriteFileTool));
86 registry.register(Box::new(file::ListDirectoryTool));
87 registry.register(Box::new(file::SearchFilesTool));
88 registry.register(Box::new(shell::RunCommandTool));
89 registry.register(Box::new(glob::GlobTool));
90 registry.register(Box::new(grep::GrepTool));
91 registry.register(Box::new(web::WebFetchTool));
92 registry.register(Box::new(patch::ApplyPatchTool));
93 registry.register(Box::new(multiedit::MultiEditTool));
94 registry.register(Box::new(batch::BatchTool));
95 registry
96 }
97}
98
99impl Default for ToolRegistry {
100 fn default() -> Self {
101 Self::new()
102 }
103}