Files
ai-agent/backend/schemas/cron.py
Gabriel Vidal 2119af66d5 refactor(schemas): split backend/schemas.py into a schemas/ package
One module per API area (base, files, activity, skills, conversations,
notifications, forms, search, plans, projects, services, misc, diff, cron,
agents) on a shared base.Schema; __init__.py re-exports every model so
handlers keep writing schemas.<Name>. OpenAPI output is byte-identical.
PlanSummary lives in conversations.py to keep the module graph a DAG.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-06 23:55:47 +02:00

78 lines
2.6 KiB
Python

"""Cron jobs (``backend/cron.py``)."""
from __future__ import annotations
from typing import Optional
from .base import Schema
__all__ = [
"CronRun",
"CronRunConfig",
"CronJob",
"CronJobsResponse",
"CronPromptFile",
]
class CronRun(Schema):
"""One recorded firing of a cron job — the history mapping's entry enriched
with the conversation id the session landed on (once its transcript
synced), so the UI can link straight to it."""
at: str
sessionId: str
conversationId: Optional[str] = None
class CronRunConfig(Schema):
"""How a job's firings are launched, read out of the prompt file's YAML
frontmatter (``cron.run_config``). Every field is optional: None means the
key isn't set and the spawn path's own default applies."""
# "claude" (the claude CLI) or "pi" (the pi.dev runner).
harness: Optional[str] = None
# A `--model` value: a family alias ("sonnet") or a full model id.
model: Optional[str] = None
# `--effort` level (low|medium|high|xhigh|max); "" = explicitly no flag.
effort: Optional[str] = None
# False ⇒ run with extended thinking off; None ⇒ the CLI's own default.
thinking: Optional[bool] = None
# The Claude account the run bills ("personal"/"work", see accounts.py);
# None ⇒ routed like any spawn (cwd rule, else the default account).
account: Optional[str] = None
class CronJob(Schema):
id: str
name: str
# 5-field cron expression (min hour dom mon dow), container-local time.
schedule: str
# Markdown prompt file under .claude/agents/ — its content is the prompt
# each firing spawns a session with (leading YAML frontmatter stripped),
# and its frontmatter is what `runConfig` is read from.
promptFile: str
enabled: bool
# Legacy per-job model, kept as the fallback when the frontmatter sets none.
model: Optional[str] = None
# The runner the firings go to: None = the lab's own sidecar, else a paired
# worker's id (offline at fire time ⇒ the firing is recorded as an error).
worker: Optional[str] = None
# The resolved run config from the prompt file's frontmatter.
runConfig: Optional[CronRunConfig] = None
createdAt: Optional[str] = None
lastStatus: Optional[str] = None
# Next fire time (local ISO minute); None when disabled or never.
nextRun: Optional[str] = None
# The stored history: {ISO timestamp: sessionId}.
history: dict[str, str]
# `history` enriched + sorted newest-first for rendering.
runs: list[CronRun]
class CronJobsResponse(Schema):
jobs: list[CronJob]
class CronPromptFile(Schema):
path: str
content: str
exists: bool