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