vv_agent/tools/
public_tool.rs1use serde_json::Value;
2use std::time::Duration;
3
4use crate::checkpoint::ToolIdempotency;
5use crate::tools::{
6 ToolApprovalRule, ToolEnablementContext, ToolEnablementRule, ToolHandler, ToolSpec,
7};
8use crate::types::ToolExecutionResult;
9
10pub trait Tool: Send + Sync {
11 fn name(&self) -> &str;
12 fn description(&self) -> &str;
13 fn parameters_schema(&self) -> &Value;
14
15 fn strict_schema(&self) -> bool {
16 true
17 }
18
19 fn exposure(&self) -> crate::tools::ToolExposure {
20 crate::tools::ToolExposure::Direct
21 }
22
23 fn timeout(&self) -> Option<Duration> {
24 None
25 }
26
27 fn approval_rule(&self) -> ToolApprovalRule {
28 ToolApprovalRule::default()
29 }
30
31 fn idempotency(&self) -> ToolIdempotency {
32 ToolIdempotency::Unknown
33 }
34
35 fn is_enabled(&self, _context: &ToolEnablementContext) -> bool {
36 true
37 }
38
39 fn as_tool_spec(&self) -> ToolSpec;
40}
41
42#[derive(Clone)]
43pub struct StaticTool {
44 name: String,
45 description: String,
46 parameters_schema: Value,
47 handler: ToolHandler,
48 enablement: ToolEnablementRule,
49 idempotency: ToolIdempotency,
50}
51
52impl StaticTool {
53 pub fn new(
54 name: impl Into<String>,
55 description: impl Into<String>,
56 parameters_schema: Value,
57 handler: ToolHandler,
58 ) -> Self {
59 Self {
60 name: name.into(),
61 description: description.into(),
62 parameters_schema,
63 handler,
64 enablement: ToolEnablementRule::default(),
65 idempotency: ToolIdempotency::Unknown,
66 }
67 }
68
69 pub fn with_enabled(mut self, enabled: bool) -> Self {
70 self.enablement = ToolEnablementRule::Static(enabled);
71 self
72 }
73
74 pub fn with_enabled_if<F>(mut self, predicate: F) -> Self
75 where
76 F: Fn(&ToolEnablementContext) -> bool + Send + Sync + 'static,
77 {
78 self.enablement = ToolEnablementRule::predicate(predicate);
79 self
80 }
81
82 pub fn with_idempotency(mut self, idempotency: ToolIdempotency) -> Self {
83 self.idempotency = idempotency;
84 self
85 }
86}
87
88impl Tool for StaticTool {
89 fn name(&self) -> &str {
90 &self.name
91 }
92
93 fn description(&self) -> &str {
94 &self.description
95 }
96
97 fn parameters_schema(&self) -> &Value {
98 &self.parameters_schema
99 }
100
101 fn is_enabled(&self, context: &ToolEnablementContext) -> bool {
102 self.enablement.is_enabled(context)
103 }
104
105 fn idempotency(&self) -> ToolIdempotency {
106 self.idempotency
107 }
108
109 fn as_tool_spec(&self) -> ToolSpec {
110 let mut spec = ToolSpec::new(
111 self.name.clone(),
112 self.description.clone(),
113 self.handler.clone(),
114 );
115 spec.schema = serde_json::json!({
116 "type": "function",
117 "function": {
118 "name": self.name,
119 "description": self.description,
120 "parameters": self.parameters_schema,
121 "strict": self.strict_schema(),
122 }
123 });
124 spec.strict_schema = self.strict_schema();
125 spec.exposure = self.exposure();
126 spec.timeout = self.timeout();
127 spec.approval = self.approval_rule();
128 spec.idempotency = self.idempotency();
129 spec
130 }
131}
132
133impl<F> From<(String, String, Value, F)> for StaticTool
134where
135 F: Fn(&mut crate::tools::ToolContext, &crate::types::ToolArguments) -> ToolExecutionResult
136 + Send
137 + Sync
138 + 'static,
139{
140 fn from(value: (String, String, Value, F)) -> Self {
141 Self::new(value.0, value.1, value.2, std::sync::Arc::new(value.3))
142 }
143}