use std::path::PathBuf;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use tokio_util::sync::CancellationToken;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ToolSpec {
pub name: String,
pub description: String,
pub parameters: serde_json::Value,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ToolOutput {
pub content: String,
pub is_error: bool,
}
impl ToolOutput {
pub fn ok(content: impl Into<String>) -> Self {
Self {
content: content.into(),
is_error: false,
}
}
pub fn err(content: impl Into<String>) -> Self {
Self {
content: content.into(),
is_error: true,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ToolConcurrency {
ReadOnly,
Exclusive,
}
#[derive(Debug, Clone)]
pub struct ToolContext {
pub cwd: PathBuf,
pub allowed_roots: Vec<PathBuf>,
pub read_only_roots: Vec<PathBuf>,
pub group_folder: String,
pub chat_jid: String,
pub is_main: bool,
pub ipc_dir: PathBuf,
pub cancel: CancellationToken,
}
#[async_trait]
pub trait Tool: Send + Sync {
fn spec(&self) -> ToolSpec;
fn concurrency(&self) -> ToolConcurrency {
ToolConcurrency::Exclusive
}
async fn call(&self, args: serde_json::Value, ctx: &ToolContext) -> ToolOutput;
}