1use crate::{World, error::ToolError};
2use async_trait::async_trait;
3use serde::{Deserialize, Serialize};
4use std::sync::Arc;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10#[serde(rename_all = "kebab-case")]
11#[non_exhaustive]
12pub enum ToolRisk {
13 ReadOnly,
15 Idempotent,
17 Destructive,
19 Network,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct ToolSchema {
25 pub name: String,
26 pub description: String,
27 pub input: serde_json::Value,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct ToolResult {
33 pub ok: bool,
34 pub content: serde_json::Value,
35 pub trace: Option<String>,
37}
38
39#[async_trait]
40pub trait Tool: Send + Sync + 'static {
41 fn name(&self) -> &str;
42 fn schema(&self) -> &ToolSchema;
43 fn risk(&self) -> ToolRisk;
44 async fn invoke(
45 &self,
46 args: serde_json::Value,
47 world: &mut World,
48 ) -> Result<ToolResult, ToolError>;
49}
50
51pub struct ToolEntry {
53 pub factory: fn() -> Arc<dyn Tool>,
54}
55
56inventory::collect!(ToolEntry);
57
58pub fn iter_macro_tools() -> impl Iterator<Item = Arc<dyn Tool>> {
59 inventory::iter::<ToolEntry>().map(|e| (e.factory)())
60}