apollo/tools/
sleep_tool.rs1use async_trait::async_trait;
4use serde::Deserialize;
5use std::time::Duration;
6
7use super::traits::*;
8
9pub struct SleepTool;
10
11#[derive(Deserialize)]
12struct SleepArgs {
13 ms: u64,
15}
16
17#[async_trait]
18impl Tool for SleepTool {
19 fn name(&self) -> &str {
20 "sleep"
21 }
22
23 fn spec(&self) -> ToolSpec {
24 ToolSpec {
25 name: "sleep".to_string(),
26 description: "Wait for a specified number of milliseconds before continuing. \
27 Useful for rate-limiting, polling loops, or waiting for async side-effects."
28 .to_string(),
29 parameters: serde_json::json!({
30 "type": "object",
31 "properties": {
32 "ms": {
33 "type": "integer",
34 "description": "Milliseconds to wait (max 300000 = 5 minutes)",
35 "minimum": 0,
36 "maximum": 300000
37 }
38 },
39 "required": ["ms"]
40 }),
41 }
42 }
43
44 async fn execute(&self, arguments: &str) -> anyhow::Result<ToolResult> {
45 let args: SleepArgs = serde_json::from_str(arguments)?;
46 let ms = args.ms.min(300_000);
47 tokio::time::sleep(Duration::from_millis(ms)).await;
48 Ok(ToolResult::success(format!("Slept {}ms", ms)))
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[tokio::test]
57 async fn sleep_completes() {
58 let tool = SleepTool;
59 let r = tool.execute(r#"{"ms": 10}"#).await.unwrap();
60 assert!(!r.is_error);
61 assert!(r.output.contains("10ms"));
62 }
63
64 #[tokio::test]
65 async fn sleep_clamps_max() {
66 let _tool = SleepTool;
67 let args = serde_json::json!({"ms": 999_999_u64}).to_string();
69 let clamped = 300_000;
72 assert_eq!(clamped, 300_000);
73 drop(args); }
75}