use super::{Tool, ToolDefinition}; use anyhow::Result; use serde_json::Value; use std::process::Command; pub struct BashTool; impl Tool for BashTool { fn definition(&self) -> ToolDefinition { ToolDefinition { name: "bash".to_string(), description: "Execute a bash command and return its output.".to_string(), parameters: serde_json::json!({ "type": "object", "properties": { "command": { "type": "string", "description": "The bash command to execute" } }, "required": ["command"] }), } } fn execute(&self, args: &Value) -> Result { let command = args["command"] .as_str() .ok_or_else(|| anyhow::anyhow!("Missing 'command' argument"))?; let output = Command::new("bash") .arg("-c") .arg(command) .output()?; let stdout = String::from_utf8_lossy(&output.stdout); let stderr = String::from_utf8_lossy(&output.stderr); let mut result = String::new(); if !stdout.is_empty() { result.push_str(&stdout); } if !stderr.is_empty() { if !result.is_empty() { result.push('\n'); } result.push_str("STDERR:\n"); result.push_str(&stderr); } if !output.status.success() { result.push_str(&format!("\nExit code: {}", output.status.code().unwrap_or(-1))); } Ok(result) } }