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