1use std::future::Future;
4use std::pin::Pin;
5
6use opi_ai::message::{OutputContent, ToolDef};
7use tokio_util::sync::CancellationToken;
8
9pub type UpdateCallback = Box<dyn Fn(serde_json::Value) + Send + Sync>;
11
12pub trait Tool: Send + Sync {
14 fn definition(&self) -> ToolDef;
16
17 fn execute(
19 &self,
20 call_id: &str,
21 arguments: serde_json::Value,
22 signal: CancellationToken,
23 on_update: Option<UpdateCallback>,
24 ) -> Pin<Box<dyn Future<Output = Result<ToolResult, ToolError>> + Send>>;
25
26 fn execution_mode(&self) -> ExecutionMode {
28 ExecutionMode::Parallel
29 }
30}
31
32#[derive(Clone)]
34pub struct ToolResult {
35 pub content: Vec<OutputContent>,
36 pub details: Option<serde_json::Value>,
37 pub is_error: bool,
38 pub terminate: bool,
39}
40
41impl ToolResult {
42 pub fn from_validation_error(err: crate::validation::ValidationError) -> Self {
44 let message = err.to_string();
45 Self {
46 content: vec![OutputContent::Text { text: message }],
47 details: None,
48 is_error: true,
49 terminate: false,
50 }
51 }
52}
53
54#[derive(Debug, thiserror::Error)]
56pub enum ToolError {
57 #[error("execution failed: {0}")]
58 ExecutionFailed(String),
59 #[error("cancelled")]
60 Cancelled,
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65pub enum ExecutionMode {
66 Sequential,
67 Parallel,
68}