ai-agent-sdk 0.5.0

Idiomatic agent sdk inspired by the claude code source leak
Documentation
//! Cron scheduled task tools.
//!
//! Provides tools for managing scheduled tasks.

use crate::types::*;

/// CronCreate tool - create a scheduled task
pub struct CronCreateTool;

impl CronCreateTool {
    pub fn new() -> Self {
        Self
    }

    pub fn input_schema(&self) -> ToolInputSchema {
        ToolInputSchema {
            schema_type: "object".to_string(),
            properties: serde_json::json!({
                "cron": {
                    "type": "string",
                    "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)"
                },
                "prompt": {
                    "type": "string",
                    "description": "The prompt to enqueue at each fire time"
                },
                "recurring": {
                    "type": "boolean",
                    "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"
                },
                "durable": {
                    "type": "boolean",
                    "description": "true = persist to .ai/scheduled_tasks.json and survive restarts. false (default) = in-memory only, dies when this Claude session ends"
                }
            }),
            required: Some(vec!["cron".to_string(), "prompt".to_string()]),
        }
    }

    pub async fn execute(&self, input: serde_json::Value, _context: &ToolContext) -> Result<ToolResult, crate::error::AgentError> {
        let cron = input["cron"].as_str().unwrap_or("");
        let prompt = input["prompt"].as_str().unwrap_or("");
        let recurring = input["recurring"].as_bool().unwrap_or(true);
        let durable = input["durable"].as_bool().unwrap_or(false);

        let response = format!(
            "Scheduled task created:\nCron: {}\nPrompt: {}\nRecurring: {}\nDurable: {}\nNote: Full implementation would persist and execute this scheduled task.",
            cron, prompt, recurring, durable
        );

        Ok(ToolResult {
            result_type: "text".to_string(),
            tool_use_id: "cron_create".to_string(),
            content: response,
            is_error: Some(false),
        })
    }
}

impl Default for CronCreateTool {
    fn default() -> Self {
        Self::new()
    }
}

/// CronDelete tool - delete a scheduled task
pub struct CronDeleteTool;

impl CronDeleteTool {
    pub fn new() -> Self {
        Self
    }

    pub fn input_schema(&self) -> ToolInputSchema {
        ToolInputSchema {
            schema_type: "object".to_string(),
            properties: serde_json::json!({
                "id": {
                    "type": "string",
                    "description": "Job ID returned by CronCreate"
                }
            }),
            required: Some(vec!["id".to_string()]),
        }
    }

    pub async fn execute(&self, input: serde_json::Value, _context: &ToolContext) -> Result<ToolResult, crate::error::AgentError> {
        let id = input["id"].as_str().unwrap_or("");

        let response = format!("Scheduled task '{}' deleted.", id);

        Ok(ToolResult {
            result_type: "text".to_string(),
            tool_use_id: "cron_delete".to_string(),
            content: response,
            is_error: Some(false),
        })
    }
}

impl Default for CronDeleteTool {
    fn default() -> Self {
        Self::new()
    }
}

/// CronList tool - list all scheduled tasks
pub struct CronListTool;

impl CronListTool {
    pub fn new() -> Self {
        Self
    }

    pub fn input_schema(&self) -> ToolInputSchema {
        ToolInputSchema {
            schema_type: "object".to_string(),
            properties: serde_json::json!({}),
            required: None,
        }
    }

    pub async fn execute(&self, _input: serde_json::Value, _context: &ToolContext) -> Result<ToolResult, crate::error::AgentError> {
        let response = "Scheduled tasks:\n- (none)".to_string();

        Ok(ToolResult {
            result_type: "text".to_string(),
            tool_use_id: "cron_list".to_string(),
            content: response,
            is_error: Some(false),
        })
    }
}

impl Default for CronListTool {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_cron_create_schema() {
        let tool = CronCreateTool::new();
        let schema = tool.input_schema();
        assert!(schema.properties.get("cron").is_some());
        assert!(schema.properties.get("prompt").is_some());
    }

    #[test]
    fn test_cron_delete_schema() {
        let tool = CronDeleteTool::new();
        let schema = tool.input_schema();
        assert!(schema.properties.get("id").is_some());
    }

    #[test]
    fn test_cron_list_schema() {
        let tool = CronListTool::new();
        let schema = tool.input_schema();
        assert_eq!(schema.schema_type, "object");
    }
}