use descry_tool_core::{call_tool, tool_names, ToolContext, ToolError};
use descry_tool_macros::tool;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
#[derive(Deserialize, JsonSchema)]
struct AddParams {
a: i32,
b: i32,
}
#[derive(Serialize, JsonSchema)]
struct AddOutput {
result: i32,
}
#[tool(
name = "add",
description = "Add two numbers"
)]
async fn add(_ctx: Arc<ToolContext>, params: AddParams) -> Result<AddOutput, ToolError> {
Ok(AddOutput {
result: params.a + params.b,
})
}
#[derive(Deserialize, JsonSchema)]
struct SubtractParams {
a: i32,
b: i32,
}
#[derive(Serialize, JsonSchema)]
struct SubtractOutput {
result: i32,
}
#[tool(
name = "subtract",
description = "Subtract two numbers"
)]
async fn subtract(_ctx: Arc<ToolContext>, params: SubtractParams) -> Result<SubtractOutput, ToolError> {
Ok(SubtractOutput {
result: params.a - params.b,
})
}
#[derive(Deserialize, JsonSchema)]
struct DivideParams {
dividend: i32,
divisor: i32,
}
#[derive(Serialize, JsonSchema)]
struct DivideOutput {
quotient: i32,
remainder: i32,
}
#[tool(
name = "divide",
description = "Divide two integers with remainder"
)]
async fn divide(_ctx: Arc<ToolContext>, params: DivideParams) -> Result<DivideOutput, ToolError> {
if params.divisor == 0 {
return Err(ToolError::invalid_params("Divisor cannot be zero"));
}
Ok(DivideOutput {
quotient: params.dividend / params.divisor,
remainder: params.dividend % params.divisor,
})
}
#[tokio::main]
async fn main() {
println!("=== Descry 2.0 Complete Example ===\n");
let names = tool_names();
println!("Registered tools: {:?}", names);
println!("Tool count: {}\n", names.len());
let ctx = Arc::new(ToolContext::new());
println!("Testing add(10, 5)...");
match call_tool("add", serde_json::json!({"a": 10, "b": 5}), ctx.clone()).await {
Ok(result) => println!("Result: {}\n", serde_json::to_string(&result).unwrap()),
Err(e) => eprintln!("Error: {}\n", e),
}
println!("Testing subtract(10, 5)...");
match call_tool("subtract", serde_json::json!({"a": 10, "b": 5}), ctx.clone()).await {
Ok(result) => println!("Result: {}\n", serde_json::to_string(&result).unwrap()),
Err(e) => eprintln!("Error: {}\n", e),
}
println!("Testing divide(17, 5)...");
match call_tool("divide", serde_json::json!({"dividend": 17, "divisor": 5}), ctx.clone()).await {
Ok(result) => println!("Result: {}\n", serde_json::to_string(&result).unwrap()),
Err(e) => eprintln!("Error: {}\n", e),
}
println!("Testing divide(10, 0) [should fail]...");
match call_tool("divide", serde_json::json!({"dividend": 10, "divisor": 0}), ctx.clone()).await {
Ok(result) => println!("Result: {}\n", serde_json::to_string(&result).unwrap()),
Err(e) => println!("Expected error: {}\n", e),
}
println!("Testing nonexistent tool [should fail]...");
match call_tool("power", serde_json::json!({}), ctx).await {
Ok(result) => println!("Result: {}\n", serde_json::to_string(&result).unwrap()),
Err(e) => println!("Expected error: {}\n", e),
}
for name in &["add", "subtract", "divide"] {
if let Some(schema) = descry_tool_core::get_tool_schema(name) {
println!("Schema for '{}':", name);
println!(" Title: {}", schema.get("title").unwrap().as_str().unwrap());
println!(" Properties: {:?}", schema.get("properties").unwrap().as_object().unwrap().keys().collect::<Vec<_>>());
}
}
}