Skip to main content

skill_tools/
lib.rs

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    /// Return the skill metadata catalog from the SkillTool (if registered).
98    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}