Skip to main content

ai_agent/tools/
cron.rs

1// Source: /data/home/swei/claudecode/openclaudecode/src/utils/cron.ts
2//! Cron scheduled task tools.
3//!
4//! Provides tools for managing scheduled tasks.
5
6use crate::types::*;
7
8/// CronCreate tool - create a scheduled task
9pub struct CronCreateTool;
10
11impl CronCreateTool {
12    pub fn new() -> Self {
13        Self
14    }
15
16    pub fn input_schema(&self) -> ToolInputSchema {
17        ToolInputSchema {
18            schema_type: "object".to_string(),
19            properties: serde_json::json!({
20                "cron": {
21                    "type": "string",
22                    "description": "Standard 5-field cron expression in local time: 'M H DoM Mon DoW' (e.g., '*/5 * * * *' = every 5 minutes, '0 9 * * 1-5' = weekdays at 9am)"
23                },
24                "prompt": {
25                    "type": "string",
26                    "description": "The prompt to enqueue at each fire time"
27                },
28                "recurring": {
29                    "type": "boolean",
30                    "description": "true (default) = fire on every cron match until deleted or auto-expired after 7 days. false = fire once at the next match, then auto-delete"
31                },
32                "durable": {
33                    "type": "boolean",
34                    "description": "true = persist to .ai/scheduled_tasks.json and survive restarts. false (default) = in-memory only, dies when this Claude session ends"
35                }
36            }),
37            required: Some(vec!["cron".to_string(), "prompt".to_string()]),
38        }
39    }
40
41    pub async fn execute(
42        &self,
43        input: serde_json::Value,
44        _context: &ToolContext,
45    ) -> Result<ToolResult, crate::error::AgentError> {
46        let cron = input["cron"].as_str().unwrap_or("");
47        let prompt = input["prompt"].as_str().unwrap_or("");
48        let recurring = input["recurring"].as_bool().unwrap_or(true);
49        let durable = input["durable"].as_bool().unwrap_or(false);
50
51        let response = format!(
52            "Scheduled task created:\nCron: {}\nPrompt: {}\nRecurring: {}\nDurable: {}\nNote: Full implementation would persist and execute this scheduled task.",
53            cron, prompt, recurring, durable
54        );
55
56        Ok(ToolResult {
57            result_type: "text".to_string(),
58            tool_use_id: "cron_create".to_string(),
59            content: response,
60            is_error: Some(false),
61        })
62    }
63}
64
65impl Default for CronCreateTool {
66    fn default() -> Self {
67        Self::new()
68    }
69}
70
71/// CronDelete tool - delete a scheduled task
72pub struct CronDeleteTool;
73
74impl CronDeleteTool {
75    pub fn new() -> Self {
76        Self
77    }
78
79    pub fn input_schema(&self) -> ToolInputSchema {
80        ToolInputSchema {
81            schema_type: "object".to_string(),
82            properties: serde_json::json!({
83                "id": {
84                    "type": "string",
85                    "description": "Job ID returned by CronCreate"
86                }
87            }),
88            required: Some(vec!["id".to_string()]),
89        }
90    }
91
92    pub async fn execute(
93        &self,
94        input: serde_json::Value,
95        _context: &ToolContext,
96    ) -> Result<ToolResult, crate::error::AgentError> {
97        let id = input["id"].as_str().unwrap_or("");
98
99        let response = format!("Scheduled task '{}' deleted.", id);
100
101        Ok(ToolResult {
102            result_type: "text".to_string(),
103            tool_use_id: "cron_delete".to_string(),
104            content: response,
105            is_error: Some(false),
106        })
107    }
108}
109
110impl Default for CronDeleteTool {
111    fn default() -> Self {
112        Self::new()
113    }
114}
115
116/// CronList tool - list all scheduled tasks
117pub struct CronListTool;
118
119impl CronListTool {
120    pub fn new() -> Self {
121        Self
122    }
123
124    pub fn input_schema(&self) -> ToolInputSchema {
125        ToolInputSchema {
126            schema_type: "object".to_string(),
127            properties: serde_json::json!({}),
128            required: None,
129        }
130    }
131
132    pub async fn execute(
133        &self,
134        _input: serde_json::Value,
135        _context: &ToolContext,
136    ) -> Result<ToolResult, crate::error::AgentError> {
137        let response = "Scheduled tasks:\n- (none)".to_string();
138
139        Ok(ToolResult {
140            result_type: "text".to_string(),
141            tool_use_id: "cron_list".to_string(),
142            content: response,
143            is_error: Some(false),
144        })
145    }
146}
147
148impl Default for CronListTool {
149    fn default() -> Self {
150        Self::new()
151    }
152}
153
154#[cfg(test)]
155mod tests {
156    use super::*;
157
158    #[test]
159    fn test_cron_create_schema() {
160        let tool = CronCreateTool::new();
161        let schema = tool.input_schema();
162        assert!(schema.properties.get("cron").is_some());
163        assert!(schema.properties.get("prompt").is_some());
164    }
165
166    #[test]
167    fn test_cron_delete_schema() {
168        let tool = CronDeleteTool::new();
169        let schema = tool.input_schema();
170        assert!(schema.properties.get("id").is_some());
171    }
172
173    #[test]
174    fn test_cron_list_schema() {
175        let tool = CronListTool::new();
176        let schema = tool.input_schema();
177        assert_eq!(schema.schema_type, "object");
178    }
179}