1use std::future::Future;
20use std::sync::Arc;
21
22use fcommon::BoxFuture;
23use fprovider::ToolDefinition;
24
25use crate::{ToolError, ToolExecutionContext};
26
27pub type ToolFuture<'a, T> = BoxFuture<'a, T>;
28
29pub trait Tool: Send + Sync {
30 fn definition(&self) -> ToolDefinition;
31
32 fn invoke<'a>(
33 &'a self,
34 args_json: &'a str,
35 context: &'a ToolExecutionContext,
36 ) -> ToolFuture<'a, Result<String, ToolError>>;
37}
38
39type ToolHandler = dyn Fn(String, ToolExecutionContext) -> ToolFuture<'static, Result<String, ToolError>>
40 + Send
41 + Sync;
42
43pub struct FunctionTool {
44 definition: ToolDefinition,
45 handler: Arc<ToolHandler>,
46}
47
48impl FunctionTool {
49 pub fn new<F, Fut>(definition: ToolDefinition, handler: F) -> Self
50 where
51 F: Fn(String, ToolExecutionContext) -> Fut + Send + Sync + 'static,
52 Fut: Future<Output = Result<String, ToolError>> + Send + 'static,
53 {
54 let handler: Arc<ToolHandler> =
55 Arc::new(move |args_json, context| Box::pin(handler(args_json, context)));
56
57 Self {
58 definition,
59 handler,
60 }
61 }
62}
63
64impl Tool for FunctionTool {
65 fn definition(&self) -> ToolDefinition {
66 self.definition.clone()
67 }
68
69 fn invoke<'a>(
70 &'a self,
71 args_json: &'a str,
72 context: &'a ToolExecutionContext,
73 ) -> ToolFuture<'a, Result<String, ToolError>> {
74 let args_json = args_json.to_string();
75 let context = context.clone();
76 (self.handler)(args_json, context)
77 }
78}