pub mod approval;
pub mod cron;
pub mod delegate;
pub mod filesystem;
pub mod gsheets;
pub mod longterm_memory;
pub mod mcp;
pub mod memory;
pub mod message;
pub mod plugin;
pub mod r8r;
mod registry;
pub mod shell;
pub mod spawn;
mod types;
pub mod web;
pub mod whatsapp;
pub use delegate::DelegateTool;
pub use gsheets::GoogleSheetsTool;
pub use longterm_memory::LongTermMemoryTool;
pub use memory::{MemoryGetTool, MemorySearchTool};
pub use message::MessageTool;
pub use r8r::R8rTool;
pub use registry::ToolRegistry;
pub use types::{Tool, ToolContext};
pub use web::{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 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<String> {
let message = args
.get("message")
.and_then(|v| v.as_str())
.unwrap_or("(no message)");
Ok(message.to_string())
}
}
#[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(), "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(), "(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(), "");
}
#[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(), "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(), "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(), "Line1\nLine2\tTab");
}
}