1use oxi_agent::{AgentTool, AgentToolResult, ToolContext, ToolError};
4use serde_json::Value;
5use std::sync::Arc;
6
7pub type ToolHandler =
9 Arc<dyn Fn(Value, &ToolContext) -> Result<AgentToolResult, ToolError> + Send + Sync>;
10
11pub type AsyncToolHandler = Arc<
13 dyn Fn(
14 Value,
15 &ToolContext,
16 ) -> std::pin::Pin<
17 Box<dyn std::future::Future<Output = Result<AgentToolResult, ToolError>> + Send>,
18 > + Send
19 + Sync,
20>;
21
22pub struct ClosureTool {
27 name: String,
28 description: String,
29 schema: Value,
30 handler: AsyncToolHandler,
31}
32
33impl ClosureTool {
34 pub fn new_sync(
38 name: impl Into<String>,
39 description: impl Into<String>,
40 schema: Value,
41 handler: impl Fn(Value, &ToolContext) -> Result<AgentToolResult, ToolError>
42 + Send
43 + Sync
44 + 'static,
45 ) -> Self {
46 #[allow(clippy::type_complexity)]
47 let handler_arc: Arc<
48 dyn Fn(Value, &ToolContext) -> Result<AgentToolResult, ToolError> + Send + Sync,
49 > = Arc::new(handler);
50 Self {
51 name: name.into(),
52 description: description.into(),
53 schema,
54 handler: Arc::new(move |params, ctx| {
55 let result = handler_arc(params, ctx);
56 Box::pin(async move { result })
57 }),
58 }
59 }
60
61 pub fn new_async(
65 name: impl Into<String>,
66 description: impl Into<String>,
67 schema: Value,
68 handler: impl Fn(
69 Value,
70 &ToolContext,
71 ) -> std::pin::Pin<
72 Box<dyn std::future::Future<Output = Result<AgentToolResult, ToolError>> + Send>,
73 > + Send
74 + Sync
75 + 'static,
76 ) -> Self {
77 Self {
78 name: name.into(),
79 description: description.into(),
80 schema,
81 handler: Arc::new(handler),
82 }
83 }
84}
85
86#[async_trait::async_trait]
87impl AgentTool for ClosureTool {
88 fn name(&self) -> &str {
89 &self.name
90 }
91
92 fn label(&self) -> &str {
93 &self.name
94 }
95
96 fn description(&self) -> &str {
97 &self.description
98 }
99
100 fn parameters_schema(&self) -> Value {
101 self.schema.clone()
102 }
103
104 async fn execute(
105 &self,
106 _tool_call_id: &str,
107 params: Value,
108 _signal: Option<tokio::sync::oneshot::Receiver<()>>,
109 ctx: &ToolContext,
110 ) -> Result<AgentToolResult, ToolError> {
111 (self.handler)(params, ctx).await
112 }
113}