返回 JoyAI-Echo
types.py
1 """Cron types."""
2
3 from dataclasses import dataclass, field
4 from typing import Literal
5
6
7 @dataclass
8 class CronSchedule:
9 """Schedule definition for a cron job."""
10 kind: Literal["at", "every", "cron"]
11 # For "at": timestamp in ms
12 at_ms: int | None = None
13 # For "every": interval in ms
14 every_ms: int | None = None
15 # For "cron": cron expression (e.g. "0 9 * * *")
16 expr: str | None = None
17 # Timezone for cron expressions
18 tz: str | None = None
19
20
21 @dataclass
22 class CronPayload:
23 """What to do when the job runs."""
24 kind: Literal["system_event", "agent_turn"] = "agent_turn"
25 message: str = ""
26 # Deliver response to channel
27 deliver: bool = False
28 channel: str | None = None # e.g. "whatsapp"
29 to: str | None = None # e.g. phone number
30
31
32 @dataclass
33 class CronRunRecord:
34 """A single execution record for a cron job."""
35 run_at_ms: int
36 status: Literal["ok", "error", "skipped"]
37 duration_ms: int = 0
38 error: str | None = None
39
40
41 @dataclass
42 class CronJobState:
43 """Runtime state of a job."""
44 next_run_at_ms: int | None = None
45 last_run_at_ms: int | None = None
46 last_status: Literal["ok", "error", "skipped"] | None = None
47 last_error: str | None = None
48 run_history: list[CronRunRecord] = field(default_factory=list)
49
50
51 @dataclass
52 class CronJob:
53 """A scheduled job."""
54 id: str
55 name: str
56 enabled: bool = True
57 schedule: CronSchedule = field(default_factory=lambda: CronSchedule(kind="every"))
58 payload: CronPayload = field(default_factory=CronPayload)
59 state: CronJobState = field(default_factory=CronJobState)
60 created_at_ms: int = 0
61 updated_at_ms: int = 0
62 delete_after_run: bool = False
63
64 @classmethod
65 def from_dict(cls, kwargs: dict):
66 state_kwargs = dict(kwargs.get("state", {}))
67 state_kwargs["run_history"] = [
68 record if isinstance(record, CronRunRecord) else CronRunRecord(**record)
69 for record in state_kwargs.get("run_history", [])
70 ]
71 kwargs["schedule"] = CronSchedule(**kwargs.get("schedule", {"kind": "every"}))
72 kwargs["payload"] = CronPayload(**kwargs.get("payload", {}))
73 kwargs["state"] = CronJobState(**state_kwargs)
74 return cls(**kwargs)
75
76
77 @dataclass
78 class CronStore:
79 """Persistent store for cron jobs."""
80 version: int = 1
81 jobs: list[CronJob] = field(default_factory=list)
82
82 lines PYTHON