agent_code_lib/tools/
sleep_tool.rs1use async_trait::async_trait;
7use serde_json::json;
8use std::time::Duration;
9
10use super::{Tool, ToolContext, ToolResult};
11use crate::error::ToolError;
12
13const MAX_SLEEP_MS: u64 = 300_000;
15
16pub struct SleepTool;
17
18#[async_trait]
19impl Tool for SleepTool {
20 fn name(&self) -> &'static str {
21 "Sleep"
22 }
23
24 fn description(&self) -> &'static str {
25 "Pause execution for a specified number of milliseconds (max 5 minutes)."
26 }
27
28 fn input_schema(&self) -> serde_json::Value {
29 json!({
30 "type": "object",
31 "required": ["duration_ms"],
32 "properties": {
33 "duration_ms": {
34 "type": "integer",
35 "description": "Duration to sleep in milliseconds (max 300000)"
36 }
37 }
38 })
39 }
40
41 fn is_read_only(&self) -> bool {
42 true
43 }
44
45 fn is_concurrency_safe(&self) -> bool {
46 true
47 }
48
49 async fn call(
50 &self,
51 input: serde_json::Value,
52 ctx: &ToolContext,
53 ) -> Result<ToolResult, ToolError> {
54 let ms = input
55 .get("duration_ms")
56 .and_then(|v| v.as_u64())
57 .ok_or_else(|| ToolError::InvalidInput("'duration_ms' is required".into()))?;
58
59 let ms = ms.min(MAX_SLEEP_MS);
60
61 tokio::select! {
62 _ = tokio::time::sleep(Duration::from_millis(ms)) => {
63 Ok(ToolResult::success(format!("Slept for {ms}ms")))
64 }
65 _ = ctx.cancel.cancelled() => {
66 Err(ToolError::Cancelled)
67 }
68 }
69 }
70}