use crate::{World, error::ToolError};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
#[non_exhaustive]
pub enum ToolRisk {
ReadOnly,
Idempotent,
Destructive,
Network,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolSchema {
pub name: String,
pub description: String,
pub input: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolResult {
pub ok: bool,
pub content: serde_json::Value,
pub trace: Option<String>,
}
#[async_trait]
pub trait Tool: Send + Sync + 'static {
fn name(&self) -> &str;
fn schema(&self) -> &ToolSchema;
fn risk(&self) -> ToolRisk;
async fn invoke(
&self,
args: serde_json::Value,
world: &mut World,
) -> Result<ToolResult, ToolError>;
}
pub struct ToolEntry {
pub factory: fn() -> Arc<dyn Tool>,
}
inventory::collect!(ToolEntry);
pub fn iter_macro_tools() -> impl Iterator<Item = Arc<dyn Tool>> {
inventory::iter::<ToolEntry>().map(|e| (e.factory)())
}