use anyhow::Error;
use std::pin::Pin;
pub trait Tool: Send + Sync {
fn name(&self) -> &str;
fn description(&self) -> &str;
fn invoke(&self, input: &str) -> Pin<Box<dyn std::future::Future<Output = Result<String, Error>> + Send + '_>>;
fn as_any(&self) -> &dyn std::any::Any;
}
pub trait Toolkit {
fn tools(&self) -> Vec<Box<dyn Tool>>;
}
pub struct ExampleTool {
name: String,
description: String,
}
impl ExampleTool {
pub fn new(name: String, description: String) -> Self {
Self {
name,
description,
}
}
}
impl Tool for ExampleTool {
fn name(&self) -> &str {
&self.name
}
fn description(&self) -> &str {
&self.description
}
fn invoke(&self, input: &str) -> Pin<Box<dyn std::future::Future<Output = Result<String, Error>> + Send + '_>> {
let input_str = input.to_string();
let name = self.name.clone();
Box::pin(async move {
Ok(format!("Tool {} received input: {}", name, input_str))
})
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
pub struct ExampleToolkit {
tools: Vec<Box<dyn Tool>>,
}
impl ExampleToolkit {
pub fn new() -> Self {
let tools: Vec<Box<dyn Tool>> = Vec::new();
Self {
tools,
}
}
pub fn add_tool(&mut self, tool: Box<dyn Tool>) {
self.tools.push(tool);
}
}
impl Toolkit for ExampleToolkit {
fn tools(&self) -> Vec<Box<dyn Tool>> {
Vec::new()
}
}
impl Clone for ExampleToolkit {
fn clone(&self) -> Self {
let mut toolkit = ExampleToolkit::new();
for tool in &self.tools {
let name = tool.name();
let description = tool.description();
let new_tool = Box::new(ExampleTool::new(name.to_string(), description.to_string()));
toolkit.add_tool(new_tool);
}
toolkit
}
}