agent_commander/tools/
mod.rs1pub mod agent;
5pub mod claude;
6pub mod codex;
7pub mod gemini;
8pub mod opencode;
9pub mod qwen;
10pub(crate) mod shell;
11
12use std::collections::HashMap;
13
14pub use agent::{AgentBuildOptions, AgentTool, AgentUsage, ErrorResult};
15pub use claude::{ClaudeBuildOptions, ClaudeTool, ClaudeUsage};
16pub use codex::{CodexBuildOptions, CodexTool, CodexUsage};
17pub use gemini::{GeminiBuildOptions, GeminiErrorResult, GeminiTool, GeminiUsage};
18pub use opencode::{OpencodeBuildOptions, OpencodeTool, OpencodeUsage};
19pub use qwen::{QwenBuildOptions, QwenErrorResult, QwenTool, QwenUsage};
20
21pub trait Tool {
23 fn name(&self) -> &'static str;
24 fn display_name(&self) -> &'static str;
25 fn executable(&self) -> &'static str;
26 fn supports_json_output(&self) -> bool;
27 fn supports_json_input(&self) -> bool;
28 fn supports_system_prompt(&self) -> bool;
29 fn supports_resume(&self) -> bool;
30 fn default_model(&self) -> &'static str;
31}
32
33impl Tool for ClaudeTool {
34 fn name(&self) -> &'static str {
35 self.name
36 }
37 fn display_name(&self) -> &'static str {
38 self.display_name
39 }
40 fn executable(&self) -> &'static str {
41 self.executable
42 }
43 fn supports_json_output(&self) -> bool {
44 self.supports_json_output
45 }
46 fn supports_json_input(&self) -> bool {
47 self.supports_json_input
48 }
49 fn supports_system_prompt(&self) -> bool {
50 self.supports_system_prompt
51 }
52 fn supports_resume(&self) -> bool {
53 self.supports_resume
54 }
55 fn default_model(&self) -> &'static str {
56 self.default_model
57 }
58}
59
60impl Tool for CodexTool {
61 fn name(&self) -> &'static str {
62 self.name
63 }
64 fn display_name(&self) -> &'static str {
65 self.display_name
66 }
67 fn executable(&self) -> &'static str {
68 self.executable
69 }
70 fn supports_json_output(&self) -> bool {
71 self.supports_json_output
72 }
73 fn supports_json_input(&self) -> bool {
74 self.supports_json_input
75 }
76 fn supports_system_prompt(&self) -> bool {
77 self.supports_system_prompt
78 }
79 fn supports_resume(&self) -> bool {
80 self.supports_resume
81 }
82 fn default_model(&self) -> &'static str {
83 self.default_model
84 }
85}
86
87impl Tool for OpencodeTool {
88 fn name(&self) -> &'static str {
89 self.name
90 }
91 fn display_name(&self) -> &'static str {
92 self.display_name
93 }
94 fn executable(&self) -> &'static str {
95 self.executable
96 }
97 fn supports_json_output(&self) -> bool {
98 self.supports_json_output
99 }
100 fn supports_json_input(&self) -> bool {
101 self.supports_json_input
102 }
103 fn supports_system_prompt(&self) -> bool {
104 self.supports_system_prompt
105 }
106 fn supports_resume(&self) -> bool {
107 self.supports_resume
108 }
109 fn default_model(&self) -> &'static str {
110 self.default_model
111 }
112}
113
114impl Tool for AgentTool {
115 fn name(&self) -> &'static str {
116 self.name
117 }
118 fn display_name(&self) -> &'static str {
119 self.display_name
120 }
121 fn executable(&self) -> &'static str {
122 self.executable
123 }
124 fn supports_json_output(&self) -> bool {
125 self.supports_json_output
126 }
127 fn supports_json_input(&self) -> bool {
128 self.supports_json_input
129 }
130 fn supports_system_prompt(&self) -> bool {
131 self.supports_system_prompt
132 }
133 fn supports_resume(&self) -> bool {
134 self.supports_resume
135 }
136 fn default_model(&self) -> &'static str {
137 self.default_model
138 }
139}
140
141impl Tool for GeminiTool {
142 fn name(&self) -> &'static str {
143 self.name
144 }
145 fn display_name(&self) -> &'static str {
146 self.display_name
147 }
148 fn executable(&self) -> &'static str {
149 self.executable
150 }
151 fn supports_json_output(&self) -> bool {
152 self.supports_json_output
153 }
154 fn supports_json_input(&self) -> bool {
155 self.supports_json_input
156 }
157 fn supports_system_prompt(&self) -> bool {
158 self.supports_system_prompt
159 }
160 fn supports_resume(&self) -> bool {
161 self.supports_resume
162 }
163 fn default_model(&self) -> &'static str {
164 self.default_model
165 }
166}
167
168impl Tool for QwenTool {
169 fn name(&self) -> &'static str {
170 self.name
171 }
172 fn display_name(&self) -> &'static str {
173 self.display_name
174 }
175 fn executable(&self) -> &'static str {
176 self.executable
177 }
178 fn supports_json_output(&self) -> bool {
179 self.supports_json_output
180 }
181 fn supports_json_input(&self) -> bool {
182 self.supports_json_input
183 }
184 fn supports_system_prompt(&self) -> bool {
185 self.supports_system_prompt
186 }
187 fn supports_resume(&self) -> bool {
188 self.supports_resume
189 }
190 fn default_model(&self) -> &'static str {
191 self.default_model
192 }
193}
194
195pub struct ToolRegistry {
197 tools: HashMap<&'static str, Box<dyn Tool + Send + Sync>>,
198}
199
200impl Default for ToolRegistry {
201 fn default() -> Self {
202 Self::new()
203 }
204}
205
206impl ToolRegistry {
207 pub fn new() -> Self {
209 let mut tools: HashMap<&'static str, Box<dyn Tool + Send + Sync>> = HashMap::new();
210 tools.insert("claude", Box::new(ClaudeTool::default()));
211 tools.insert("codex", Box::new(CodexTool::default()));
212 tools.insert("opencode", Box::new(OpencodeTool::default()));
213 tools.insert("agent", Box::new(AgentTool::default()));
214 tools.insert("gemini", Box::new(GeminiTool::default()));
215 tools.insert("qwen", Box::new(QwenTool::default()));
216 Self { tools }
217 }
218
219 pub fn get(&self, name: &str) -> Option<&(dyn Tool + Send + Sync)> {
221 self.tools.get(name).map(|t| t.as_ref())
222 }
223
224 pub fn is_supported(&self, name: &str) -> bool {
226 self.tools.contains_key(name)
227 }
228
229 pub fn list(&self) -> Vec<&'static str> {
231 self.tools.keys().copied().collect()
232 }
233}
234
235pub fn get_tool(tool_name: &str) -> Result<Box<dyn Tool + Send + Sync>, String> {
243 match tool_name {
244 "claude" => Ok(Box::new(ClaudeTool::default())),
245 "codex" => Ok(Box::new(CodexTool::default())),
246 "opencode" => Ok(Box::new(OpencodeTool::default())),
247 "agent" => Ok(Box::new(AgentTool::default())),
248 "gemini" => Ok(Box::new(GeminiTool::default())),
249 "qwen" => Ok(Box::new(QwenTool::default())),
250 _ => Err(format!(
251 "Unknown tool: {}. Available tools: claude, codex, opencode, agent, gemini, qwen",
252 tool_name
253 )),
254 }
255}
256
257pub fn list_tools() -> Vec<&'static str> {
259 vec!["claude", "codex", "opencode", "agent", "gemini", "qwen"]
260}
261
262pub fn is_tool_supported(tool_name: &str) -> bool {
270 ["claude", "codex", "opencode", "agent", "gemini", "qwen"].contains(&tool_name)
271}
272
273