codetether_agent/tool/
mod.rs1pub mod bash;
6pub mod batch;
7pub mod codesearch;
8pub mod edit;
9pub mod file;
10pub mod invalid;
11pub mod lsp;
12pub mod multiedit;
13pub mod patch;
14pub mod plan;
15pub mod prd;
16pub mod question;
17pub mod ralph;
18pub mod rlm;
19pub mod search;
20pub mod skill;
21pub mod task;
22pub mod todo;
23pub mod webfetch;
24pub mod websearch;
25
26use anyhow::Result;
27use async_trait::async_trait;
28use serde::{Deserialize, Serialize};
29use serde_json::Value;
30use std::collections::HashMap;
31use std::sync::Arc;
32
33use crate::provider::Provider;
34
35#[async_trait]
37pub trait Tool: Send + Sync {
38 fn id(&self) -> &str;
40
41 fn name(&self) -> &str;
43
44 fn description(&self) -> &str;
46
47 fn parameters(&self) -> Value;
49
50 async fn execute(&self, args: Value) -> Result<ToolResult>;
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct ToolResult {
57 pub output: String,
58 pub success: bool,
59 #[serde(default)]
60 pub metadata: HashMap<String, Value>,
61}
62
63impl ToolResult {
64 pub fn success(output: impl Into<String>) -> Self {
65 Self {
66 output: output.into(),
67 success: true,
68 metadata: HashMap::new(),
69 }
70 }
71
72 pub fn error(message: impl Into<String>) -> Self {
73 Self {
74 output: message.into(),
75 success: false,
76 metadata: HashMap::new(),
77 }
78 }
79
80 pub fn with_metadata(mut self, key: impl Into<String>, value: Value) -> Self {
81 self.metadata.insert(key.into(), value);
82 self
83 }
84}
85
86pub struct ToolRegistry {
88 tools: HashMap<String, Arc<dyn Tool>>,
89}
90
91impl ToolRegistry {
92 pub fn new() -> Self {
93 Self {
94 tools: HashMap::new(),
95 }
96 }
97
98 pub fn register(&mut self, tool: Arc<dyn Tool>) {
100 self.tools.insert(tool.id().to_string(), tool);
101 }
102
103 pub fn get(&self, id: &str) -> Option<Arc<dyn Tool>> {
105 self.tools.get(id).cloned()
106 }
107
108 pub fn list(&self) -> Vec<&str> {
110 self.tools.keys().map(|s| s.as_str()).collect()
111 }
112
113 pub fn definitions(&self) -> Vec<crate::provider::ToolDefinition> {
115 self.tools
116 .values()
117 .map(|t| crate::provider::ToolDefinition {
118 name: t.id().to_string(),
119 description: t.description().to_string(),
120 parameters: t.parameters(),
121 })
122 .collect()
123 }
124
125 pub fn with_defaults() -> Self {
127 let mut registry = Self::new();
128
129 registry.register(Arc::new(file::ReadTool::new()));
130 registry.register(Arc::new(file::WriteTool::new()));
131 registry.register(Arc::new(file::ListTool::new()));
132 registry.register(Arc::new(file::GlobTool::new()));
133 registry.register(Arc::new(search::GrepTool::new()));
134 registry.register(Arc::new(edit::EditTool::new()));
135 registry.register(Arc::new(bash::BashTool::new()));
136 registry.register(Arc::new(lsp::LspTool::new()));
137 registry.register(Arc::new(webfetch::WebFetchTool::new()));
138 registry.register(Arc::new(multiedit::MultiEditTool::new()));
139 registry.register(Arc::new(websearch::WebSearchTool::new()));
140 registry.register(Arc::new(codesearch::CodeSearchTool::new()));
141 registry.register(Arc::new(patch::ApplyPatchTool::new()));
142 registry.register(Arc::new(todo::TodoReadTool::new()));
143 registry.register(Arc::new(todo::TodoWriteTool::new()));
144 registry.register(Arc::new(question::QuestionTool::new()));
145 registry.register(Arc::new(task::TaskTool::new()));
146 registry.register(Arc::new(plan::PlanEnterTool::new()));
147 registry.register(Arc::new(plan::PlanExitTool::new()));
148 registry.register(Arc::new(skill::SkillTool::new()));
149 registry.register(Arc::new(rlm::RlmTool::new()));
150 registry.register(Arc::new(ralph::RalphTool::new()));
151 registry.register(Arc::new(prd::PrdTool::new()));
152 registry.register(Arc::new(invalid::InvalidTool::new()));
154
155 registry
156 }
157
158 pub fn with_provider(provider: Arc<dyn Provider>, model: String) -> Self {
160 let mut registry = Self::new();
161
162 registry.register(Arc::new(file::ReadTool::new()));
163 registry.register(Arc::new(file::WriteTool::new()));
164 registry.register(Arc::new(file::ListTool::new()));
165 registry.register(Arc::new(file::GlobTool::new()));
166 registry.register(Arc::new(search::GrepTool::new()));
167 registry.register(Arc::new(edit::EditTool::new()));
168 registry.register(Arc::new(bash::BashTool::new()));
169 registry.register(Arc::new(lsp::LspTool::new()));
170 registry.register(Arc::new(webfetch::WebFetchTool::new()));
171 registry.register(Arc::new(multiedit::MultiEditTool::new()));
172 registry.register(Arc::new(websearch::WebSearchTool::new()));
173 registry.register(Arc::new(codesearch::CodeSearchTool::new()));
174 registry.register(Arc::new(patch::ApplyPatchTool::new()));
175 registry.register(Arc::new(todo::TodoReadTool::new()));
176 registry.register(Arc::new(todo::TodoWriteTool::new()));
177 registry.register(Arc::new(question::QuestionTool::new()));
178 registry.register(Arc::new(task::TaskTool::new()));
179 registry.register(Arc::new(plan::PlanEnterTool::new()));
180 registry.register(Arc::new(plan::PlanExitTool::new()));
181 registry.register(Arc::new(skill::SkillTool::new()));
182 registry.register(Arc::new(rlm::RlmTool::new()));
183 registry.register(Arc::new(ralph::RalphTool::with_provider(provider, model)));
185 registry.register(Arc::new(prd::PrdTool::new()));
186 registry.register(Arc::new(invalid::InvalidTool::new()));
188
189 registry
190 }
191
192 pub fn with_defaults_arc() -> Arc<Self> {
196 let mut registry = Self::with_defaults();
197
198 let batch_tool = Arc::new(batch::BatchTool::new());
200 registry.register(batch_tool.clone());
201
202 let registry = Arc::new(registry);
204
205 batch_tool.set_registry(Arc::downgrade(®istry));
207
208 registry
209 }
210
211 #[allow(dead_code)]
215 pub fn with_provider_arc(provider: Arc<dyn Provider>, model: String) -> Arc<Self> {
216 let mut registry = Self::with_provider(provider, model);
217
218 let batch_tool = Arc::new(batch::BatchTool::new());
220 registry.register(batch_tool.clone());
221
222 let registry = Arc::new(registry);
224
225 batch_tool.set_registry(Arc::downgrade(®istry));
227
228 registry
229 }
230}
231
232impl Default for ToolRegistry {
233 fn default() -> Self {
234 Self::with_defaults()
235 }
236}