1use crate::{CallbackContext, EventActions, MemoryEntry, Result};
2use async_trait::async_trait;
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::sync::Arc;
6
7#[async_trait]
8pub trait Tool: Send + Sync {
9 fn name(&self) -> &str;
10 fn description(&self) -> &str;
11
12 fn enhanced_description(&self) -> String {
17 self.description().to_string()
18 }
19
20 fn is_long_running(&self) -> bool {
24 false
25 }
26 fn parameters_schema(&self) -> Option<Value> {
27 None
28 }
29 fn response_schema(&self) -> Option<Value> {
30 None
31 }
32
33 fn required_scopes(&self) -> &[&str] {
47 &[]
48 }
49
50 async fn execute(&self, ctx: Arc<dyn ToolContext>, args: Value) -> Result<Value>;
51}
52
53#[async_trait]
54pub trait ToolContext: CallbackContext {
55 fn function_call_id(&self) -> &str;
56 fn actions(&self) -> EventActions;
58 fn set_actions(&self, actions: EventActions);
60 async fn search_memory(&self, query: &str) -> Result<Vec<MemoryEntry>>;
61
62 fn user_scopes(&self) -> Vec<String> {
69 vec![]
70 }
71}
72
73#[derive(Debug, Clone)]
90pub struct RetryBudget {
91 pub max_retries: u32,
94 pub delay: std::time::Duration,
96}
97
98impl RetryBudget {
99 pub fn new(max_retries: u32, delay: std::time::Duration) -> Self {
106 Self { max_retries, delay }
107 }
108}
109
110#[async_trait]
111pub trait Toolset: Send + Sync {
112 fn name(&self) -> &str;
113 async fn tools(&self, ctx: Arc<dyn crate::ReadonlyContext>) -> Result<Vec<Arc<dyn Tool>>>;
114}
115
116#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
118pub enum ValidationMode {
119 #[default]
121 Strict,
122 Permissive,
124}
125
126pub trait ToolRegistry: Send + Sync {
131 fn resolve(&self, tool_name: &str) -> Option<Arc<dyn Tool>>;
134
135 fn available_tools(&self) -> Vec<String> {
137 vec![]
138 }
139}
140
141pub type ToolPredicate = Box<dyn Fn(&dyn Tool) -> bool + Send + Sync>;
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146 use crate::{Content, EventActions, ReadonlyContext, RunConfig};
147 use std::sync::Mutex;
148
149 struct TestTool {
150 name: String,
151 }
152
153 #[allow(dead_code)]
154 struct TestContext {
155 content: Content,
156 config: RunConfig,
157 actions: Mutex<EventActions>,
158 }
159
160 impl TestContext {
161 fn new() -> Self {
162 Self {
163 content: Content::new("user"),
164 config: RunConfig::default(),
165 actions: Mutex::new(EventActions::default()),
166 }
167 }
168 }
169
170 #[async_trait]
171 impl ReadonlyContext for TestContext {
172 fn invocation_id(&self) -> &str {
173 "test"
174 }
175 fn agent_name(&self) -> &str {
176 "test"
177 }
178 fn user_id(&self) -> &str {
179 "user"
180 }
181 fn app_name(&self) -> &str {
182 "app"
183 }
184 fn session_id(&self) -> &str {
185 "session"
186 }
187 fn branch(&self) -> &str {
188 ""
189 }
190 fn user_content(&self) -> &Content {
191 &self.content
192 }
193 }
194
195 #[async_trait]
196 impl CallbackContext for TestContext {
197 fn artifacts(&self) -> Option<Arc<dyn crate::Artifacts>> {
198 None
199 }
200 }
201
202 #[async_trait]
203 impl ToolContext for TestContext {
204 fn function_call_id(&self) -> &str {
205 "call-123"
206 }
207 fn actions(&self) -> EventActions {
208 self.actions.lock().unwrap().clone()
209 }
210 fn set_actions(&self, actions: EventActions) {
211 *self.actions.lock().unwrap() = actions;
212 }
213 async fn search_memory(&self, _query: &str) -> Result<Vec<crate::MemoryEntry>> {
214 Ok(vec![])
215 }
216 }
217
218 #[async_trait]
219 impl Tool for TestTool {
220 fn name(&self) -> &str {
221 &self.name
222 }
223
224 fn description(&self) -> &str {
225 "test tool"
226 }
227
228 async fn execute(&self, _ctx: Arc<dyn ToolContext>, _args: Value) -> Result<Value> {
229 Ok(Value::String("result".to_string()))
230 }
231 }
232
233 #[test]
234 fn test_tool_trait() {
235 let tool = TestTool { name: "test".to_string() };
236 assert_eq!(tool.name(), "test");
237 assert_eq!(tool.description(), "test tool");
238 assert!(!tool.is_long_running());
239 }
240
241 #[tokio::test]
242 async fn test_tool_execute() {
243 let tool = TestTool { name: "test".to_string() };
244 let ctx = Arc::new(TestContext::new()) as Arc<dyn ToolContext>;
245 let result = tool.execute(ctx, Value::Null).await.unwrap();
246 assert_eq!(result, Value::String("result".to_string()));
247 }
248}