use anyhow::Result;
use async_trait::async_trait;
use serde_json::Value;
use std::collections::HashMap;
use crate::query::ToolDefinition;
#[derive(Debug, Clone)]
pub struct ToolOutput {
pub content: String,
pub is_error: bool,
}
impl ToolOutput {
pub fn success(content: impl Into<String>) -> Self {
Self {
content: content.into(),
is_error: false,
}
}
pub fn error(content: impl Into<String>) -> Self {
Self {
content: content.into(),
is_error: true,
}
}
}
#[async_trait]
pub trait Tool: Send + Sync {
fn name(&self) -> &str;
fn description(&self) -> &str;
fn parameters_schema(&self) -> Value;
async fn execute(&self, input: Value) -> Result<ToolOutput>;
}
pub struct ToolRegistry {
tools: HashMap<String, Box<dyn Tool>>,
}
impl ToolRegistry {
pub fn new() -> Self {
Self {
tools: HashMap::new(),
}
}
pub fn register(&mut self, tool: Box<dyn Tool>) {
let name = tool.name().to_string();
self.tools.insert(name, tool);
}
pub fn get(&self, name: &str) -> Option<&dyn Tool> {
self.tools.get(name).map(|t| t.as_ref())
}
pub async fn execute(&self, name: &str, input: Value) -> Result<ToolOutput> {
match self.tools.get(name) {
Some(tool) => tool.execute(input).await,
None => Ok(ToolOutput::error(format!("Unknown tool: {}", name))),
}
}
pub fn definitions(&self) -> Vec<ToolDefinition> {
self.tools
.values()
.map(|tool| ToolDefinition {
name: tool.name().to_string(),
description: tool.description().to_string(),
input_schema: tool.parameters_schema(),
})
.collect()
}
pub fn tool_names(&self) -> Vec<&str> {
self.tools.keys().map(|k| k.as_str()).collect()
}
}
impl Default for ToolRegistry {
fn default() -> Self {
Self::new()
}
}
pub mod bash;
pub mod task_manager;
pub mod file_ops;
pub mod glob_search;
pub mod grep_search;
pub mod read_file;
pub mod write_file;
pub mod edit_file;
pub mod tech_query;
pub mod web_search;
pub mod web_fetch;