use std::future::Future; use chrono::{DateTime, Utc}; use zeroclaw::config::Config as ZeroClawConfig; use zeroclaw::cron::{self, CronJob, CronRun, JobType, Schedule, SessionTarget}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct CronExecutionResult { pub job_id: String, pub success: bool, pub output: String, } pub fn configure_embedded_cron(config: &mut ZeroClawConfig) { config.cron.enabled = true; config.cron.catch_up_on_startup = false; config.scheduler.enabled = false; config.scheduler.max_concurrent = 1; config.scheduler.max_tasks = config.scheduler.max_tasks.max(1); } pub fn add_agent_job( config: &ZeroClawConfig, name: Option, schedule: Schedule, prompt: &str, allowed_tools: Option>, ) -> anyhow::Result { cron::add_agent_job( config, name, schedule, prompt, SessionTarget::Isolated, None, None, false, allowed_tools, ) } pub fn list_jobs(config: &ZeroClawConfig) -> anyhow::Result> { cron::list_jobs(config) } pub fn list_runs( config: &ZeroClawConfig, job_id: &str, limit: usize, ) -> anyhow::Result> { cron::list_runs(config, job_id, limit) } pub async fn run_due_jobs( config: &ZeroClawConfig, now: DateTime, mut runner: F, ) -> anyhow::Result> where F: FnMut(&CronJob) -> Fut, Fut: Future>, { let jobs = cron::due_jobs(config, now)?; let mut results = Vec::with_capacity(jobs.len()); for job in jobs { if !matches!(job.job_type, JobType::Agent) { anyhow::bail!( "unsupported cron job type in sgclaw compat: {:?}", job.job_type ); } let started_at = Utc::now(); let (success, output) = match runner(&job).await { Ok(output) => (true, output), Err(err) => (false, err.to_string()), }; let finished_at = Utc::now(); let duration_ms = (finished_at - started_at).num_milliseconds(); cron::record_run( config, &job.id, started_at, finished_at, if success { "ok" } else { "error" }, Some(&output), duration_ms, )?; cron::reschedule_after_run(config, &job, success, &output)?; results.push(CronExecutionResult { job_id: job.id, success, output, }); } Ok(results) }