1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use thiserror::Error;
4
5pub mod bash;
6pub mod read;
7pub mod skill;
8pub mod write;
9
10pub use bash::BashTool;
11pub use read::ReadTool;
12pub use skill::SkillTool;
13pub use write::WriteTool;
14
15#[derive(Debug, Error)]
16pub enum ToolError {
17 #[error("Execution error: {0}")]
18 ExecutionError(String),
19
20 #[error("Invalid parameters: {0}")]
21 InvalidParameters(String),
22
23 #[error("Tool not found: {0}")]
24 NotFound(String),
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct ToolResult {
29 pub success: bool,
30 pub output: String,
31 pub error: Option<String>,
32}
33
34#[derive(Debug, Clone)]
35pub struct ToolDefinition {
36 pub name: String,
37 pub description: String,
38 pub parameters: serde_json::Value,
39}
40
41#[derive(Clone)]
42pub enum ToolBox {
43 Bash(BashTool),
44 Read(ReadTool),
45 Write(WriteTool),
46 Skill(SkillTool),
47}
48
49impl ToolBox {
50 pub fn definition(&self) -> ToolDefinition {
51 match self {
52 ToolBox::Bash(t) => t.definition(),
53 ToolBox::Read(t) => t.definition(),
54 ToolBox::Write(t) => t.definition(),
55 ToolBox::Skill(t) => t.definition(),
56 }
57 }
58
59 pub async fn execute(&self, params: serde_json::Value) -> Result<ToolResult, ToolError> {
60 match self {
61 ToolBox::Bash(t) => t.execute(params).await,
62 ToolBox::Read(t) => t.execute(params).await,
63 ToolBox::Write(t) => t.execute(params).await,
64 ToolBox::Skill(t) => t.execute(params).await,
65 }
66 }
67}
68
69pub struct ToolRegistry {
70 tools: HashMap<String, ToolBox>,
71}
72
73impl ToolRegistry {
74 pub fn new() -> Self {
75 Self {
76 tools: HashMap::new(),
77 }
78 }
79
80 pub fn register(&mut self, tool: ToolBox) {
81 let def = tool.definition();
82 self.tools.insert(def.name.clone(), tool);
83 }
84
85 pub fn get(&self, name: &str) -> Option<&ToolBox> {
86 self.tools.get(name)
87 }
88
89 pub fn list(&self) -> Vec<ToolDefinition> {
90 self.tools.values().map(|t| t.definition()).collect()
91 }
92
93 pub fn names(&self) -> Vec<String> {
94 self.tools.keys().cloned().collect()
95 }
96
97 pub fn skill_catalog(&self) -> Option<String> {
99 for tool in self.tools.values() {
100 if let ToolBox::Skill(skill_tool) = tool {
101 let catalog = skill_tool.skill_catalog();
102 if !catalog.is_empty() {
103 return Some(catalog);
104 }
105 }
106 }
107 None
108 }
109}
110
111impl Default for ToolRegistry {
112 fn default() -> Self {
113 Self::new()
114 }
115}