//! Scheduled task commands //! //! Tasks are backed by kernel triggers (Schedule type). //! The SchedulerService checks every 60 seconds for due triggers. use serde::{Deserialize, Serialize}; use tauri::State; use super::KernelState; // ============================================================ // Scheduled Task Commands // ============================================================ /// Request to create a scheduled task (maps to kernel trigger) #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CreateScheduledTaskRequest { pub name: String, pub schedule: String, pub schedule_type: String, pub target: Option, pub description: Option, pub enabled: Option, } /// Target for a scheduled task #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ScheduledTaskTarget { #[serde(rename = "type")] pub target_type: String, pub id: String, } /// Response for scheduled task creation #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ScheduledTaskResponse { pub id: String, pub name: String, pub schedule: String, pub status: String, } /// Create a scheduled task (backed by kernel TriggerManager) /// /// Tasks are automatically executed by the SchedulerService which checks /// every 60 seconds for due triggers. // @reserved: scheduled task management // @connected #[tauri::command] pub async fn scheduled_task_create( state: State<'_, KernelState>, request: CreateScheduledTaskRequest, ) -> Result { let kernel_lock = state.lock().await; let kernel = kernel_lock.as_ref() .ok_or_else(|| "Kernel not initialized".to_string())?; // Build TriggerConfig from request let trigger_type = match request.schedule_type.as_str() { "cron" | "schedule" => zclaw_hands::TriggerType::Schedule { cron: request.schedule.clone(), }, "interval" => zclaw_hands::TriggerType::Schedule { cron: request.schedule.clone(), // interval as simplified cron }, "once" => zclaw_hands::TriggerType::Schedule { cron: request.schedule.clone(), }, _ => return Err(format!("Unsupported schedule type: {}", request.schedule_type)), }; let target_id = request.target.as_ref().map(|t| t.id.clone()).unwrap_or_default(); let task_id = format!("sched_{}", chrono::Utc::now().timestamp_millis()); let config = zclaw_hands::TriggerConfig { id: task_id.clone(), name: request.name.clone(), hand_id: target_id, trigger_type, enabled: request.enabled.unwrap_or(true), max_executions_per_hour: 60, }; let entry = kernel.create_trigger(config).await .map_err(|e| format!("Failed to create scheduled task: {}", e))?; Ok(ScheduledTaskResponse { id: entry.config.id, name: entry.config.name, schedule: request.schedule, status: "active".to_string(), }) } /// List all scheduled tasks (kernel triggers of Schedule type) // @reserved: scheduled task management // @connected #[tauri::command] pub async fn scheduled_task_list( state: State<'_, KernelState>, ) -> Result, String> { let kernel_lock = state.lock().await; let kernel = kernel_lock.as_ref() .ok_or_else(|| "Kernel not initialized".to_string())?; let triggers = kernel.list_triggers().await; let tasks: Vec = triggers .into_iter() .filter(|t| matches!(t.config.trigger_type, zclaw_hands::TriggerType::Schedule { .. })) .map(|t| { let schedule = match t.config.trigger_type { zclaw_hands::TriggerType::Schedule { cron } => cron, _ => String::new(), }; ScheduledTaskResponse { id: t.config.id, name: t.config.name, schedule, status: if t.config.enabled { "active".to_string() } else { "paused".to_string() }, } }) .collect(); Ok(tasks) }