use async_trait::async_trait;
use rucora_core::error::ToolError;
use rucora_core::tool::Tool;
use serde_json::{Value, json};
struct EchoTool;
#[async_trait]
impl Tool for EchoTool {
fn name(&self) -> &str {
"echo"
}
fn input_schema(&self) -> Value {
json!({
"type": "object",
"properties": {
"text": {"type": "string"}
},
"required": ["text"]
})
}
async fn call(&self, input: Value) -> Result<Value, ToolError> {
let text = input
.get("text")
.and_then(|v| v.as_str())
.ok_or_else(|| ToolError::Message("missing field: text".to_string()))?;
Ok(json!({"success": true, "output": text}))
}
}
#[tokio::test]
async fn tool_contract_should_have_non_empty_name() {
let t = EchoTool;
assert!(!t.name().trim().is_empty());
}
#[tokio::test]
async fn tool_contract_call_should_return_json_value_or_tool_error() {
let t = EchoTool;
let ok = t.call(json!({"text": "hi"})).await.unwrap();
assert_eq!(ok.get("success").and_then(|v| v.as_bool()), Some(true));
let err = t.call(json!({})).await.unwrap_err();
match err {
ToolError::Message(msg) => assert!(msg.contains("text")),
_ => panic!("unexpected ToolError variant"),
}
}