#[cfg(feature = "android")]
pub mod android;
pub mod approval;
pub mod binary_plugin;
pub mod cron;
pub mod custom;
pub mod delegate;
pub mod filesystem;
pub mod git;
pub mod gsheets;
pub mod hardware;
pub mod http_request;
pub mod longterm_memory;
pub mod mcp;
pub mod memory;
pub mod message;
pub mod pdf_read;
pub mod plugin;
pub mod project;
pub mod r8r;
mod registry;
pub mod reminder;
#[cfg(feature = "screenshot")]
pub mod screenshot;
pub mod shell;
pub mod skills_install;
pub mod skills_search;
pub mod spawn;
pub mod stripe;
pub mod transcribe;
mod types;
pub mod web;
pub mod whatsapp;
#[cfg(feature = "android")]
pub use android::AndroidTool;
pub use binary_plugin::BinaryPluginTool;
pub use custom::CustomTool;
pub use delegate::DelegateTool;
pub use git::GitTool;
pub use gsheets::GoogleSheetsTool;
pub use hardware::HardwareTool;
pub use http_request::HttpRequestTool;
pub use longterm_memory::LongTermMemoryTool;
pub use memory::{MemoryGetTool, MemorySearchTool};
pub use message::MessageTool;
pub use pdf_read::PdfReadTool;
pub use project::ProjectTool;
pub use r8r::R8rTool;
pub use registry::ToolRegistry;
pub use reminder::ReminderTool;
#[cfg(feature = "screenshot")]
pub use screenshot::WebScreenshotTool;
pub use skills_install::InstallSkillTool;
pub use skills_search::FindSkillsTool;
pub use stripe::StripeTool;
pub use transcribe::TranscribeTool;
pub use types::{Tool, ToolCategory, ToolContext, ToolOutput};
pub use web::{is_blocked_host, resolve_and_check_host, WebFetchTool, WebSearchTool};
pub use whatsapp::WhatsAppTool;
use async_trait::async_trait;
use serde_json::Value;
use crate::error::Result;
pub struct EchoTool;
#[async_trait]
impl Tool for EchoTool {
fn name(&self) -> &str {
"echo"
}
fn description(&self) -> &str {
"Echoes back the provided message"
}
fn compact_description(&self) -> &str {
"Echo message"
}
fn parameters(&self) -> Value {
serde_json::json!({
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "The message to echo"
}
},
"required": ["message"]
})
}
async fn execute(&self, args: Value, _ctx: &ToolContext) -> Result<ToolOutput> {
let message = args
.get("message")
.and_then(|v| v.as_str())
.unwrap_or("(no message)");
Ok(ToolOutput::llm_only(message))
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_echo_tool_name() {
let tool = EchoTool;
assert_eq!(tool.name(), "echo");
}
#[test]
fn test_echo_tool_description() {
let tool = EchoTool;
assert_eq!(tool.description(), "Echoes back the provided message");
}
#[test]
fn test_echo_tool_parameters() {
let tool = EchoTool;
let params = tool.parameters();
assert!(params.is_object());
assert_eq!(params["type"], "object");
assert!(params["properties"]["message"].is_object());
assert_eq!(params["properties"]["message"]["type"], "string");
}
#[tokio::test]
async fn test_echo_tool_execute() {
let tool = EchoTool;
let ctx = ToolContext::new();
let result = tool
.execute(json!({"message": "Hello, World!"}), &ctx)
.await;
assert!(result.is_ok());
assert_eq!(result.unwrap().for_llm, "Hello, World!");
}
#[tokio::test]
async fn test_echo_tool_execute_no_message() {
let tool = EchoTool;
let ctx = ToolContext::new();
let result = tool.execute(json!({}), &ctx).await;
assert!(result.is_ok());
assert_eq!(result.unwrap().for_llm, "(no message)");
}
#[tokio::test]
async fn test_echo_tool_execute_empty_string() {
let tool = EchoTool;
let ctx = ToolContext::new();
let result = tool.execute(json!({"message": ""}), &ctx).await;
assert!(result.is_ok());
assert_eq!(result.unwrap().for_llm, "");
}
#[tokio::test]
async fn test_echo_tool_execute_with_context() {
let tool = EchoTool;
let ctx = ToolContext::new()
.with_channel("telegram", "123")
.with_workspace("/tmp");
let result = tool.execute(json!({"message": "test"}), &ctx).await;
assert!(result.is_ok());
assert_eq!(result.unwrap().for_llm, "test");
}
#[tokio::test]
async fn test_echo_tool_execute_unicode() {
let tool = EchoTool;
let ctx = ToolContext::new();
let result = tool.execute(json!({"message": "Hello World"}), &ctx).await;
assert!(result.is_ok());
assert_eq!(result.unwrap().for_llm, "Hello World");
}
#[tokio::test]
async fn test_echo_tool_execute_special_chars() {
let tool = EchoTool;
let ctx = ToolContext::new();
let result = tool
.execute(json!({"message": "Line1\nLine2\tTab"}), &ctx)
.await;
assert!(result.is_ok());
assert_eq!(result.unwrap().for_llm, "Line1\nLine2\tTab");
}
#[test]
fn test_echo_compact_description() {
let tool = EchoTool;
assert_eq!(tool.compact_description(), "Echo message");
assert!(tool.compact_description().len() < tool.description().len());
}
}