diff --git a/nanobot/agent/tools/cron.py b/nanobot/agent/tools/cron.py index f8e737b..6efccf0 100644 --- a/nanobot/agent/tools/cron.py +++ b/nanobot/agent/tools/cron.py @@ -147,7 +147,41 @@ class CronTool(Tool): jobs = self._cron.list_jobs() if not jobs: return "No scheduled jobs." - lines = [f"- {j.name} (id: {j.id}, {j.schedule.kind})" for j in jobs] + lines = [] + for j in jobs: + s = j.schedule + if s.kind == "cron": + timing = f"cron: {s.expr}" + if s.tz: + timing += f" ({s.tz})" + elif s.kind == "every" and s.every_ms: + secs = s.every_ms // 1000 + if secs >= 3600: + timing = f"every {secs // 3600}h" + elif secs >= 60: + timing = f"every {secs // 60}m" + else: + timing = f"every {secs}s" + elif s.kind == "at" and s.at_ms: + from datetime import datetime, timezone + dt = datetime.fromtimestamp(s.at_ms / 1000, tz=timezone.utc) + timing = f"at {dt.isoformat()}" + else: + timing = s.kind + status = "enabled" if j.enabled else "disabled" + parts = [f"- {j.name} (id: {j.id}, {timing}, {status})"] + if j.state.last_run_at_ms: + from datetime import datetime, timezone + last_dt = datetime.fromtimestamp(j.state.last_run_at_ms / 1000, tz=timezone.utc) + last_info = f" Last run: {last_dt.isoformat()} — {j.state.last_status or 'unknown'}" + if j.state.last_error: + last_info += f" ({j.state.last_error})" + parts.append(last_info) + if j.state.next_run_at_ms: + from datetime import datetime, timezone + next_dt = datetime.fromtimestamp(j.state.next_run_at_ms / 1000, tz=timezone.utc) + parts.append(f" Next run: {next_dt.isoformat()}") + lines.append("\n".join(parts)) return "Scheduled jobs:\n" + "\n".join(lines) def _remove_job(self, job_id: str | None) -> str: