@elizaos/plugin-scheduling 2.0.3-beta.5 → 2.0.3-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/anchors/anchor-registry.d.ts +33 -0
  2. package/dist/anchors/anchor-registry.d.ts.map +1 -0
  3. package/dist/anchors/anchor-registry.js +129 -0
  4. package/dist/anchors/anchor-registry.js.map +1 -0
  5. package/dist/dispatch-types.d.ts +28 -0
  6. package/dist/dispatch-types.d.ts.map +1 -0
  7. package/dist/dispatch-types.js +1 -0
  8. package/dist/dispatch-types.js.map +1 -0
  9. package/dist/index.d.ts +5 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +18 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/plugin.d.ts +17 -0
  14. package/dist/plugin.d.ts.map +1 -0
  15. package/dist/plugin.js +8 -0
  16. package/dist/plugin.js.map +1 -0
  17. package/dist/scheduled-task/completion-check-registry.d.ts +19 -0
  18. package/dist/scheduled-task/completion-check-registry.d.ts.map +1 -0
  19. package/dist/scheduled-task/completion-check-registry.js +113 -0
  20. package/dist/scheduled-task/completion-check-registry.js.map +1 -0
  21. package/dist/scheduled-task/consolidation-policy.d.ts +51 -0
  22. package/dist/scheduled-task/consolidation-policy.d.ts.map +1 -0
  23. package/dist/scheduled-task/consolidation-policy.js +154 -0
  24. package/dist/scheduled-task/consolidation-policy.js.map +1 -0
  25. package/dist/scheduled-task/due.d.ts +19 -0
  26. package/dist/scheduled-task/due.d.ts.map +1 -0
  27. package/dist/scheduled-task/due.js +349 -0
  28. package/dist/scheduled-task/due.js.map +1 -0
  29. package/dist/scheduled-task/escalation.d.ts +55 -0
  30. package/dist/scheduled-task/escalation.d.ts.map +1 -0
  31. package/dist/scheduled-task/escalation.js +99 -0
  32. package/dist/scheduled-task/escalation.js.map +1 -0
  33. package/dist/scheduled-task/gate-registry.d.ts +18 -0
  34. package/dist/scheduled-task/gate-registry.d.ts.map +1 -0
  35. package/dist/scheduled-task/gate-registry.js +244 -0
  36. package/dist/scheduled-task/gate-registry.js.map +1 -0
  37. package/dist/scheduled-task/index.d.ts +20 -0
  38. package/dist/scheduled-task/index.d.ts.map +1 -0
  39. package/dist/scheduled-task/index.js +83 -0
  40. package/dist/scheduled-task/index.js.map +1 -0
  41. package/dist/scheduled-task/next-fire-at.d.ts +40 -0
  42. package/dist/scheduled-task/next-fire-at.d.ts.map +1 -0
  43. package/dist/scheduled-task/next-fire-at.js +202 -0
  44. package/dist/scheduled-task/next-fire-at.js.map +1 -0
  45. package/dist/scheduled-task/runner.d.ts +263 -0
  46. package/dist/scheduled-task/runner.d.ts.map +1 -0
  47. package/dist/scheduled-task/runner.js +721 -0
  48. package/dist/scheduled-task/runner.js.map +1 -0
  49. package/dist/scheduled-task/state-log.d.ts +56 -0
  50. package/dist/scheduled-task/state-log.d.ts.map +1 -0
  51. package/dist/scheduled-task/state-log.js +87 -0
  52. package/dist/scheduled-task/state-log.js.map +1 -0
  53. package/dist/scheduled-task/types.d.ts +368 -0
  54. package/dist/scheduled-task/types.d.ts.map +1 -0
  55. package/dist/scheduled-task/types.js +14 -0
  56. package/dist/scheduled-task/types.js.map +1 -0
  57. package/package.json +5 -5
@@ -0,0 +1,202 @@
1
+ import { computeNextCronRunAtMs } from "@elizaos/core";
2
+ const MINUTE_MS = 6e4;
3
+ function parseIsoMs(value) {
4
+ if (typeof value !== "string" || value.length === 0) return null;
5
+ const parsed = Date.parse(value);
6
+ return Number.isFinite(parsed) ? parsed : null;
7
+ }
8
+ function minutesFromHHMM(value) {
9
+ if (!value) return null;
10
+ const match = /^([01]\d|2[0-3]):([0-5]\d)$/.exec(value);
11
+ if (!match) return null;
12
+ return Number(match[1]) * 60 + Number(match[2]);
13
+ }
14
+ function localParts(date, timeZone) {
15
+ const formatter = new Intl.DateTimeFormat("en-US", {
16
+ timeZone,
17
+ year: "numeric",
18
+ month: "2-digit",
19
+ day: "2-digit",
20
+ hour: "2-digit",
21
+ minute: "2-digit",
22
+ hour12: false
23
+ });
24
+ const parts = formatter.formatToParts(date);
25
+ const read = (type) => Number(parts.find((part) => part.type === type)?.value ?? 0);
26
+ return {
27
+ year: read("year"),
28
+ month: read("month"),
29
+ day: read("day"),
30
+ hour: read("hour") % 24,
31
+ minute: read("minute")
32
+ };
33
+ }
34
+ function localHHMMToIso(now, hhmm, timeZone) {
35
+ const minutes = minutesFromHHMM(hhmm);
36
+ if (minutes === null) return null;
37
+ const parts = localParts(now, timeZone);
38
+ const hour = Math.floor(minutes / 60);
39
+ const minute = minutes % 60;
40
+ const localAsUtc = Date.UTC(
41
+ parts.year,
42
+ parts.month - 1,
43
+ parts.day,
44
+ hour,
45
+ minute
46
+ );
47
+ const offsetFormatter = new Intl.DateTimeFormat("en-US", {
48
+ timeZone,
49
+ timeZoneName: "longOffset",
50
+ year: "numeric",
51
+ month: "2-digit",
52
+ day: "2-digit",
53
+ hour: "2-digit",
54
+ minute: "2-digit",
55
+ hour12: false
56
+ });
57
+ const offsetParts = offsetFormatter.formatToParts(new Date(localAsUtc));
58
+ const offsetValue = offsetParts.find((part) => part.type === "timeZoneName")?.value ?? "GMT";
59
+ const offsetMatch = /GMT([+-]\d{1,2})(?::?(\d{2}))?/.exec(offsetValue);
60
+ let offsetMinutes = 0;
61
+ if (offsetMatch) {
62
+ const sign = offsetMatch[1]?.startsWith("-") ? -1 : 1;
63
+ const hours = Math.abs(Number.parseInt(offsetMatch[1] ?? "0", 10));
64
+ const minutesPart = Number.parseInt(offsetMatch[2] ?? "0", 10);
65
+ offsetMinutes = sign * (hours * 60 + minutesPart);
66
+ }
67
+ return new Date(localAsUtc - offsetMinutes * MINUTE_MS).toISOString();
68
+ }
69
+ function nextWindowStartIso(windowKey, context) {
70
+ const facts = context.ownerFacts;
71
+ const timeZone = facts.timezone ?? "UTC";
72
+ const morningStart = facts.morningWindow?.start;
73
+ const eveningStart = facts.eveningWindow?.start;
74
+ const eveningEnd = facts.eveningWindow?.end;
75
+ let candidates = [];
76
+ switch (windowKey) {
77
+ case "morning":
78
+ candidates = [localHHMMToIso(context.now, morningStart, timeZone) ?? ""];
79
+ break;
80
+ case "afternoon":
81
+ candidates = [
82
+ localHHMMToIso(context.now, facts.morningWindow?.end, timeZone) ?? ""
83
+ ];
84
+ break;
85
+ case "evening":
86
+ candidates = [localHHMMToIso(context.now, eveningStart, timeZone) ?? ""];
87
+ break;
88
+ case "night":
89
+ candidates = [
90
+ localHHMMToIso(context.now, eveningEnd, timeZone) ?? "",
91
+ localHHMMToIso(context.now, "00:00", timeZone) ?? ""
92
+ ];
93
+ break;
94
+ case "morning_or_night":
95
+ candidates = [
96
+ localHHMMToIso(context.now, morningStart, timeZone) ?? "",
97
+ localHHMMToIso(context.now, eveningEnd, timeZone) ?? ""
98
+ ];
99
+ break;
100
+ case "morning_or_evening":
101
+ candidates = [
102
+ localHHMMToIso(context.now, morningStart, timeZone) ?? "",
103
+ localHHMMToIso(context.now, eveningStart, timeZone) ?? ""
104
+ ];
105
+ break;
106
+ default:
107
+ return null;
108
+ }
109
+ const nowMs = context.now.getTime();
110
+ const upcoming = candidates.map((iso) => parseIsoMs(iso)).filter((ms) => ms !== null);
111
+ if (upcoming.length === 0) return null;
112
+ const future = upcoming.find((ms) => ms >= nowMs);
113
+ if (future !== void 0) return new Date(future).toISOString();
114
+ const earliest = Math.min(...upcoming);
115
+ return new Date(earliest + 24 * 60 * MINUTE_MS).toISOString();
116
+ }
117
+ async function nextAnchorIso(trigger, context) {
118
+ const ownerFacts = context.ownerFacts;
119
+ const registryAnchor = context.anchors?.get(trigger.anchorKey);
120
+ if (typeof registryAnchor?.resolve === "function") {
121
+ const resolved = await registryAnchor.resolve({
122
+ nowIso: context.now.toISOString(),
123
+ ownerFacts
124
+ });
125
+ if (resolved?.atIso && Number.isFinite(Date.parse(resolved.atIso))) {
126
+ return new Date(
127
+ Date.parse(resolved.atIso) + trigger.offsetMinutes * MINUTE_MS
128
+ ).toISOString();
129
+ }
130
+ }
131
+ const timeZone = ownerFacts.timezone ?? "UTC";
132
+ let baseIso = null;
133
+ if (trigger.anchorKey === "wake.confirmed" || trigger.anchorKey === "wake.observed" || trigger.anchorKey === "morning.start") {
134
+ baseIso = localHHMMToIso(
135
+ context.now,
136
+ ownerFacts.morningWindow?.start,
137
+ timeZone
138
+ );
139
+ } else if (trigger.anchorKey === "bedtime.target") {
140
+ baseIso = localHHMMToIso(context.now, ownerFacts.eveningWindow?.end, timeZone) ?? localHHMMToIso(context.now, "22:30", timeZone);
141
+ } else if (trigger.anchorKey === "night.start") {
142
+ baseIso = localHHMMToIso(
143
+ context.now,
144
+ ownerFacts.eveningWindow?.start,
145
+ timeZone
146
+ );
147
+ } else if (trigger.anchorKey === "lunch.start") {
148
+ baseIso = localHHMMToIso(context.now, "12:00", timeZone);
149
+ }
150
+ if (!baseIso) return null;
151
+ return new Date(
152
+ Date.parse(baseIso) + trigger.offsetMinutes * MINUTE_MS
153
+ ).toISOString();
154
+ }
155
+ async function computeNextFireAt(task, context) {
156
+ const trigger = task.trigger;
157
+ switch (trigger.kind) {
158
+ case "once": {
159
+ if (task.state.firedAt) return null;
160
+ const at = Date.parse(trigger.atIso);
161
+ if (!Number.isFinite(at)) return null;
162
+ return new Date(at).toISOString();
163
+ }
164
+ case "cron": {
165
+ const lastFire = parseIsoMs(task.state.firedAt);
166
+ const baseMs = lastFire !== null && lastFire >= context.now.getTime() ? lastFire : context.now.getTime();
167
+ const nextMs = computeNextCronRunAtMs(
168
+ trigger.expression,
169
+ baseMs,
170
+ trigger.tz
171
+ );
172
+ return nextMs === null ? null : new Date(nextMs).toISOString();
173
+ }
174
+ case "interval": {
175
+ if (!Number.isFinite(trigger.everyMinutes) || trigger.everyMinutes <= 0) {
176
+ return null;
177
+ }
178
+ const fromMs = parseIsoMs(trigger.from);
179
+ const untilMs = parseIsoMs(trigger.until);
180
+ const lastFireMs = parseIsoMs(task.state.firedAt);
181
+ const candidateMs = lastFireMs !== null ? lastFireMs + trigger.everyMinutes * MINUTE_MS : fromMs ?? context.now.getTime();
182
+ if (untilMs !== null && candidateMs > untilMs) return null;
183
+ return new Date(candidateMs).toISOString();
184
+ }
185
+ case "relative_to_anchor":
186
+ return nextAnchorIso(trigger, context);
187
+ case "during_window":
188
+ return nextWindowStartIso(trigger.windowKey, context);
189
+ case "event":
190
+ case "manual":
191
+ case "after_task":
192
+ return null;
193
+ default: {
194
+ const _exhaustive = trigger;
195
+ return null;
196
+ }
197
+ }
198
+ }
199
+ export {
200
+ computeNextFireAt
201
+ };
202
+ //# sourceMappingURL=next-fire-at.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/scheduled-task/next-fire-at.ts"],"sourcesContent":["/**\n * Computes the indexed `next_fire_at` timestamp for a `ScheduledTask`.\n *\n * The scheduler tick (`processDueScheduledTasks`) filters by this column to\n * avoid scanning every row in `life_scheduled_tasks` once per minute. The\n * value is approximate — it is a \"next candidate fire time\" that the\n * authoritative `isScheduledTaskDue` re-evaluates per task. Triggers that\n * wake on external signals (`event`, `manual`, `after_task`) leave it NULL.\n *\n * Computed for: `once`, `cron`, `interval`, `relative_to_anchor`,\n * `during_window`.\n *\n * Computed by the runner on every state mutation that can change the\n * upcoming fire time: `schedule()`, `apply(\"snooze\")`, `apply(\"edit\")`, and\n * the post-fire/post-skip persistence in `fire()`.\n */\n\nimport { computeNextCronRunAtMs } from \"@elizaos/core\";\n\nimport type { AnchorRegistry } from \"../anchors/anchor-registry.js\";\nimport type {\n OwnerFactsView,\n ScheduledTask,\n ScheduledTaskTrigger,\n} from \"./types.js\";\n\nconst MINUTE_MS = 60_000;\n\nexport interface ComputeNextFireAtContext {\n now: Date;\n ownerFacts: OwnerFactsView;\n anchors?: AnchorRegistry | null;\n}\n\nfunction parseIsoMs(value: unknown): number | null {\n if (typeof value !== \"string\" || value.length === 0) return null;\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : null;\n}\n\nfunction minutesFromHHMM(value: string | undefined): number | null {\n if (!value) return null;\n const match = /^([01]\\d|2[0-3]):([0-5]\\d)$/.exec(value);\n if (!match) return null;\n return Number(match[1]) * 60 + Number(match[2]);\n}\n\nfunction localParts(\n date: Date,\n timeZone: string,\n): { year: number; month: number; day: number; hour: number; minute: number } {\n const formatter = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false,\n });\n const parts = formatter.formatToParts(date);\n const read = (type: string): number =>\n Number(parts.find((part) => part.type === type)?.value ?? 0);\n return {\n year: read(\"year\"),\n month: read(\"month\"),\n day: read(\"day\"),\n hour: read(\"hour\") % 24,\n minute: read(\"minute\"),\n };\n}\n\nfunction localHHMMToIso(\n now: Date,\n hhmm: string | undefined,\n timeZone: string,\n): string | null {\n const minutes = minutesFromHHMM(hhmm);\n if (minutes === null) return null;\n const parts = localParts(now, timeZone);\n const hour = Math.floor(minutes / 60);\n const minute = minutes % 60;\n const localAsUtc = Date.UTC(\n parts.year,\n parts.month - 1,\n parts.day,\n hour,\n minute,\n );\n const offsetFormatter = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n timeZoneName: \"longOffset\",\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false,\n });\n const offsetParts = offsetFormatter.formatToParts(new Date(localAsUtc));\n const offsetValue =\n offsetParts.find((part) => part.type === \"timeZoneName\")?.value ?? \"GMT\";\n const offsetMatch = /GMT([+-]\\d{1,2})(?::?(\\d{2}))?/.exec(offsetValue);\n let offsetMinutes = 0;\n if (offsetMatch) {\n const sign = offsetMatch[1]?.startsWith(\"-\") ? -1 : 1;\n const hours = Math.abs(Number.parseInt(offsetMatch[1] ?? \"0\", 10));\n const minutesPart = Number.parseInt(offsetMatch[2] ?? \"0\", 10);\n offsetMinutes = sign * (hours * 60 + minutesPart);\n }\n return new Date(localAsUtc - offsetMinutes * MINUTE_MS).toISOString();\n}\n\nfunction nextWindowStartIso(\n windowKey: string,\n context: ComputeNextFireAtContext,\n): string | null {\n const facts = context.ownerFacts;\n const timeZone = facts.timezone ?? \"UTC\";\n const morningStart = facts.morningWindow?.start;\n const eveningStart = facts.eveningWindow?.start;\n const eveningEnd = facts.eveningWindow?.end;\n let candidates: string[] = [];\n switch (windowKey) {\n case \"morning\":\n candidates = [localHHMMToIso(context.now, morningStart, timeZone) ?? \"\"];\n break;\n case \"afternoon\":\n candidates = [\n localHHMMToIso(context.now, facts.morningWindow?.end, timeZone) ?? \"\",\n ];\n break;\n case \"evening\":\n candidates = [localHHMMToIso(context.now, eveningStart, timeZone) ?? \"\"];\n break;\n case \"night\":\n candidates = [\n localHHMMToIso(context.now, eveningEnd, timeZone) ?? \"\",\n localHHMMToIso(context.now, \"00:00\", timeZone) ?? \"\",\n ];\n break;\n case \"morning_or_night\":\n candidates = [\n localHHMMToIso(context.now, morningStart, timeZone) ?? \"\",\n localHHMMToIso(context.now, eveningEnd, timeZone) ?? \"\",\n ];\n break;\n case \"morning_or_evening\":\n candidates = [\n localHHMMToIso(context.now, morningStart, timeZone) ?? \"\",\n localHHMMToIso(context.now, eveningStart, timeZone) ?? \"\",\n ];\n break;\n default:\n return null;\n }\n const nowMs = context.now.getTime();\n const upcoming = candidates\n .map((iso) => parseIsoMs(iso))\n .filter((ms): ms is number => ms !== null);\n if (upcoming.length === 0) return null;\n const future = upcoming.find((ms) => ms >= nowMs);\n if (future !== undefined) return new Date(future).toISOString();\n // All today's window-starts are in the past; bump to same local-HHMM\n // tomorrow. The runner re-computes after each fire, so we only need a\n // coarse \"tomorrow morning\" candidate here.\n const earliest = Math.min(...upcoming);\n return new Date(earliest + 24 * 60 * MINUTE_MS).toISOString();\n}\n\nasync function nextAnchorIso(\n trigger: Extract<ScheduledTaskTrigger, { kind: \"relative_to_anchor\" }>,\n context: ComputeNextFireAtContext,\n): Promise<string | null> {\n const ownerFacts = context.ownerFacts;\n const registryAnchor = context.anchors?.get(trigger.anchorKey) as\n | {\n resolve?: (\n ctx: unknown,\n ) => Promise<{ atIso: string } | null> | { atIso: string } | null;\n }\n | null\n | undefined;\n if (typeof registryAnchor?.resolve === \"function\") {\n const resolved = await registryAnchor.resolve({\n nowIso: context.now.toISOString(),\n ownerFacts,\n });\n if (resolved?.atIso && Number.isFinite(Date.parse(resolved.atIso))) {\n return new Date(\n Date.parse(resolved.atIso) + trigger.offsetMinutes * MINUTE_MS,\n ).toISOString();\n }\n }\n\n const timeZone = ownerFacts.timezone ?? \"UTC\";\n let baseIso: string | null = null;\n if (\n trigger.anchorKey === \"wake.confirmed\" ||\n trigger.anchorKey === \"wake.observed\" ||\n trigger.anchorKey === \"morning.start\"\n ) {\n baseIso = localHHMMToIso(\n context.now,\n ownerFacts.morningWindow?.start,\n timeZone,\n );\n } else if (trigger.anchorKey === \"bedtime.target\") {\n baseIso =\n localHHMMToIso(context.now, ownerFacts.eveningWindow?.end, timeZone) ??\n localHHMMToIso(context.now, \"22:30\", timeZone);\n } else if (trigger.anchorKey === \"night.start\") {\n baseIso = localHHMMToIso(\n context.now,\n ownerFacts.eveningWindow?.start,\n timeZone,\n );\n } else if (trigger.anchorKey === \"lunch.start\") {\n baseIso = localHHMMToIso(context.now, \"12:00\", timeZone);\n }\n if (!baseIso) return null;\n return new Date(\n Date.parse(baseIso) + trigger.offsetMinutes * MINUTE_MS,\n ).toISOString();\n}\n\n/**\n * Compute the next-fire-at timestamp for a task. Returns null when the\n * trigger does not have a wall-clock fire time (event/manual/after_task)\n * or when the inputs cannot be resolved (e.g. unknown anchor key).\n *\n * The function is async because anchor resolution may consult the runtime\n * anchor registry (e.g. `wake.confirmed` reads the latest activity signal).\n *\n * Inputs:\n * - `task`: must have its current `trigger` and (post-fire) `state.firedAt`.\n * - `context.now`: clock used for forward-projecting cron/interval/window.\n *\n * Outputs an ISO string, never a Date — the caller writes directly to a\n * Postgres timestamp column.\n */\nexport async function computeNextFireAt(\n task: Pick<ScheduledTask, \"trigger\" | \"state\" | \"metadata\">,\n context: ComputeNextFireAtContext,\n): Promise<string | null> {\n const trigger = task.trigger;\n switch (trigger.kind) {\n case \"once\": {\n if (task.state.firedAt) return null;\n const at = Date.parse(trigger.atIso);\n if (!Number.isFinite(at)) return null;\n return new Date(at).toISOString();\n }\n case \"cron\": {\n const lastFire = parseIsoMs(task.state.firedAt);\n const baseMs =\n lastFire !== null && lastFire >= context.now.getTime()\n ? lastFire\n : context.now.getTime();\n const nextMs = computeNextCronRunAtMs(\n trigger.expression,\n baseMs,\n trigger.tz,\n );\n return nextMs === null ? null : new Date(nextMs).toISOString();\n }\n case \"interval\": {\n if (!Number.isFinite(trigger.everyMinutes) || trigger.everyMinutes <= 0) {\n return null;\n }\n const fromMs = parseIsoMs(trigger.from);\n const untilMs = parseIsoMs(trigger.until);\n const lastFireMs = parseIsoMs(task.state.firedAt);\n const candidateMs =\n lastFireMs !== null\n ? lastFireMs + trigger.everyMinutes * MINUTE_MS\n : (fromMs ?? context.now.getTime());\n if (untilMs !== null && candidateMs > untilMs) return null;\n return new Date(candidateMs).toISOString();\n }\n case \"relative_to_anchor\":\n return nextAnchorIso(trigger, context);\n case \"during_window\":\n return nextWindowStartIso(trigger.windowKey, context);\n case \"event\":\n case \"manual\":\n case \"after_task\":\n return null;\n default: {\n const _exhaustive: never = trigger;\n return null;\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,263 @@
1
+ /**
2
+ * ScheduledTaskRunner.
3
+ *
4
+ * Cross-agent invariants enforced here:
5
+ * - The runner does NOT pattern-match on `promptInstructions`.
6
+ * - `acknowledged` is non-terminal; `pipeline.onComplete` only fires on
7
+ * `completed`.
8
+ * - Snooze RESETS the ladder.
9
+ * - Global pause skips tasks with `respectsGlobalPause: true`.
10
+ * - `shouldFire` is always an array; empty / missing arrays are treated as
11
+ * "no gates → allow".
12
+ * - `idempotencyKey` deduplicates schedules.
13
+ * - `pipeline.onSkip` wins over `completionCheck.followupAfterMinutes` when
14
+ * both are set.
15
+ */
16
+ import type { DispatchResult } from "../dispatch-types.js";
17
+ import type { CompletionCheckRegistry } from "./completion-check-registry.js";
18
+ import type { AnchorRegistry, ConsolidationRegistry } from "./consolidation-policy.js";
19
+ import { type EscalationLadderRegistry } from "./escalation.js";
20
+ import type { TaskGateRegistry } from "./gate-registry.js";
21
+ import { type ScheduledTaskLogStore } from "./state-log.js";
22
+ import { type ActivitySignalBusView, type GlobalPauseView, type OwnerFactsView, type ScheduledTask, type ScheduledTaskFilter, type ScheduledTaskRunner, type SubjectStoreView, type TaskExecutionProfile } from "./types.js";
23
+ /**
24
+ * Typed error thrown by `runner.schedule()` when an `escalation.steps[].channelKey`
25
+ * does not match a registered channel in the host runtime's `ChannelRegistry`.
26
+ * The runner stays decoupled from the channel registry implementation; the
27
+ * caller injects a `channelKeys()` lookup via {@link ScheduledTaskRunnerDeps}.
28
+ */
29
+ export declare class ChannelKeyError extends Error {
30
+ readonly channelKey: string;
31
+ readonly available: readonly string[];
32
+ readonly code = "channel_key_unknown";
33
+ constructor(channelKey: string, available: readonly string[]);
34
+ }
35
+ /**
36
+ * Options the runner passes to `store.upsert` to keep the indexed
37
+ * `next_fire_at` column in sync with the task's current trigger and state.
38
+ *
39
+ * The store does not compute this itself — the runner computes the value
40
+ * using the active anchor / owner-facts / now references and forwards it
41
+ * here. The repository writes a Postgres `timestamp with time zone`
42
+ * (NULL for triggers without a wall-clock fire time).
43
+ */
44
+ export interface ScheduledTaskUpsertOptions {
45
+ nextFireAtIso: string | null;
46
+ }
47
+ /**
48
+ * Outcome of the atomic fire-claim. Exactly one parallel call resolves to
49
+ * `"fired"` for a given `(taskId, status="scheduled")` row; concurrent
50
+ * callers see `"raced"` because the UPDATE … WHERE status='scheduled' clause
51
+ * matches zero rows after the first wins.
52
+ *
53
+ * `task` on the `"fired"` branch carries the post-claim state (status =
54
+ * "fired", `firedAt` set to the claim instant, `nextFireAt` cleared so the
55
+ * scheduler tick will not re-pick it up before the next mutation).
56
+ */
57
+ export type ScheduledTaskClaimResult = {
58
+ kind: "fired";
59
+ task: ScheduledTask;
60
+ } | {
61
+ kind: "raced";
62
+ };
63
+ export interface ScheduledTaskStore {
64
+ upsert(task: ScheduledTask, options?: ScheduledTaskUpsertOptions): Promise<void>;
65
+ /**
66
+ * Atomically transition a row from `state.status === "scheduled"` to
67
+ * `"fired"`, returning the resulting row. Returns `{ kind: "raced" }`
68
+ * when zero rows matched — either because the task is already past
69
+ * `scheduled` (another tick claimed it) or the id no longer exists.
70
+ *
71
+ * The store is the only place where the read-mutate-write becomes
72
+ * atomic; the runner's previous read-then-upsert pattern was racy
73
+ * across parallel ticks. See `LifeOpsRepository.claimScheduledTaskForFire`.
74
+ */
75
+ claimForFire(args: {
76
+ taskId: string;
77
+ firedAtIso: string;
78
+ }): Promise<ScheduledTaskClaimResult>;
79
+ get(taskId: string): Promise<ScheduledTask | null>;
80
+ findByIdempotencyKey(key: string): Promise<ScheduledTask | null>;
81
+ list(filter?: ScheduledTaskFilter): Promise<ScheduledTask[]>;
82
+ delete(taskId: string): Promise<void>;
83
+ }
84
+ export declare function createInMemoryScheduledTaskStore(): ScheduledTaskStore;
85
+ export interface ScheduledTaskDispatchRecord {
86
+ taskId: string;
87
+ firedAtIso: string;
88
+ channelKey: string;
89
+ intensity?: "soft" | "normal" | "urgent";
90
+ promptInstructions: string;
91
+ contextRequest: ScheduledTask["contextRequest"];
92
+ consolidationBatchId?: string;
93
+ output?: ScheduledTask["output"];
94
+ }
95
+ export interface ScheduledTaskDispatcher {
96
+ dispatch(record: ScheduledTaskDispatchRecord): Promise<DispatchResult | undefined>;
97
+ }
98
+ /**
99
+ * Test-only no-op dispatcher. Production code MUST inject
100
+ * `createProductionScheduledTaskDispatcher` via runtime-wiring; the runner
101
+ * factory requires a dispatcher and there is no silent fallback. Exported only
102
+ * so tests can construct a runner without touching the channel layer.
103
+ *
104
+ * @internal
105
+ */
106
+ export declare const TestNoopScheduledTaskDispatcher: ScheduledTaskDispatcher;
107
+ export interface ScheduledTaskRunnerDeps {
108
+ agentId: string;
109
+ store: ScheduledTaskStore;
110
+ logStore: ScheduledTaskLogStore;
111
+ gates: TaskGateRegistry;
112
+ completionChecks: CompletionCheckRegistry;
113
+ ladders: EscalationLadderRegistry;
114
+ anchors: AnchorRegistry;
115
+ consolidation: ConsolidationRegistry;
116
+ ownerFacts: () => OwnerFactsView | Promise<OwnerFactsView>;
117
+ globalPause: GlobalPauseView;
118
+ activity: ActivitySignalBusView;
119
+ subjectStore: SubjectStoreView;
120
+ dispatcher: ScheduledTaskDispatcher;
121
+ /**
122
+ * Lookup of registered `ChannelRegistry` keys. When supplied, `schedule()`
123
+ * validates each `escalation.steps[].channelKey` against this set and
124
+ * throws {@link ChannelKeyError} on miss. Decoupled from the channels
125
+ * module to keep the spine free of channel-layer dependencies.
126
+ */
127
+ channelKeys?: () => ReadonlySet<string>;
128
+ /**
129
+ * Returns the set of `TaskExecutionProfile` values the current host can
130
+ * actually run. The runner consults this AFTER the atomic fire-claim but
131
+ * BEFORE dispatch: if `task.executionProfile` is not in the set, dispatch
132
+ * is rewritten to `notify-only` and a `"substituted"` state-log row is
133
+ * recorded. Default (when not provided): all four profiles available —
134
+ * appropriate for tests and Node desktop. Mobile / Capacitor callers
135
+ * inject a real probe from
136
+ * `@elizaos/app-core/services/local-inference/host-capabilities`.
137
+ */
138
+ hostCapabilities?: () => ReadonlySet<TaskExecutionProfile>;
139
+ /** Override for tests. */
140
+ newTaskId?: () => string;
141
+ /** Override for tests. */
142
+ now?: () => Date;
143
+ }
144
+ /**
145
+ * Public read view of `metadata.escalationCursor`.
146
+ *
147
+ * The cursor is the runner's persistence channel for the snooze-resets-ladder
148
+ * rule. Consumers that need to surface "currently on step N of escalation"
149
+ * read it through {@link ScheduledTaskRunnerExtras.getEscalationCursor} so
150
+ * they don't reach into the metadata namespace directly.
151
+ *
152
+ * - `stepIndex` follows the {@link EscalationCursor} convention: `-1` means
153
+ * the task was fired but no escalation step has been dispatched yet;
154
+ * `0..n` is the index into the resolved ladder's `steps`.
155
+ * - `lastFiredAt` is the ISO of the most recent dispatch (or the initial
156
+ * task fire when `stepIndex === -1`).
157
+ * - `channelKey` is resolved from the effective ladder. For `stepIndex === -1`
158
+ * we surface the first step's channel when the ladder has steps, falling
159
+ * back to `"in_app"` when the ladder is empty.
160
+ */
161
+ export interface EscalationCursorView {
162
+ stepIndex: number;
163
+ lastFiredAt: string;
164
+ channelKey: string;
165
+ }
166
+ /**
167
+ * Strict result of a single `fire()` attempt. Callers should exhaustively
168
+ * switch on `kind`.
169
+ *
170
+ * - `fired` — the task transitioned to `"fired"` (or was deferred via
171
+ * `gate.defer`, reopened for a recurrence, etc.) and the dispatcher ran.
172
+ * `task` is the post-mutation state.
173
+ * - `raced` — another tick atomically claimed this task first. Caller drops
174
+ * the attempt silently; the winning tick's dispatch is authoritative.
175
+ * - `skipped` — the task was skipped without dispatch: global-pause active,
176
+ * a gate denied, or the task was already terminal and not eligible for
177
+ * recurrence refire.
178
+ * - `dispatch_failed` — the atomic claim succeeded but the dispatcher threw.
179
+ * The runner persists the row as `"failed"` and writes a failed state-log
180
+ * entry so history does not strand the task as successfully fired.
181
+ */
182
+ export type ScheduledTaskFireResult = {
183
+ kind: "fired";
184
+ task: ScheduledTask;
185
+ } | {
186
+ kind: "raced";
187
+ taskId: string;
188
+ } | {
189
+ kind: "skipped";
190
+ task: ScheduledTask;
191
+ reason: string;
192
+ } | {
193
+ kind: "dispatch_failed";
194
+ task: ScheduledTask;
195
+ error: Error;
196
+ };
197
+ export interface ScheduledTaskRunnerExtras {
198
+ /**
199
+ * Convenience wrapper around {@link ScheduledTaskRunnerExtras.fireWithResult}
200
+ * that flattens the discriminated union into a `ScheduledTask`. Returns
201
+ * the post-fire task on `fired` / `skipped` / `dispatch_failed`, and the
202
+ * still-`scheduled` task on `raced` (so legacy callers that re-read see
203
+ * the unmodified row). The strict-fire callsite — `processDueScheduledTasks`
204
+ * — uses `fireWithResult` directly.
205
+ *
206
+ * Exposed for tests so we can assert behavior deterministically without
207
+ * waiting on a real timer, and for legacy actions that only want the
208
+ * task back.
209
+ */
210
+ fire(taskId: string, args?: {
211
+ eventPayload?: unknown;
212
+ allowTerminalRefire?: boolean;
213
+ }): Promise<ScheduledTask>;
214
+ /**
215
+ * Strict fire-attempt. Returns the {@link ScheduledTaskFireResult}
216
+ * discriminated union; callers must exhaustively switch on `kind`. This
217
+ * is the path the scheduler tick uses so the `raced` outcome (another
218
+ * tick claimed the same row first) is observable instead of silently
219
+ * collapsed into a "fired" return.
220
+ */
221
+ fireWithResult(taskId: string, args?: {
222
+ eventPayload?: unknown;
223
+ allowTerminalRefire?: boolean;
224
+ }): Promise<ScheduledTaskFireResult>;
225
+ /**
226
+ * Re-evaluate completion for a fired task (e.g. user_replied_within
227
+ * scenarios, late inbounds). The runner consults its registered
228
+ * completion-check and may transition the task to `completed`.
229
+ */
230
+ evaluateCompletion(taskId: string, signal: {
231
+ acknowledged?: boolean;
232
+ repliedAtIso?: string;
233
+ }): Promise<ScheduledTask>;
234
+ /**
235
+ * Run the nightly rollup pass on the state-log. Default retention is 90
236
+ * days.
237
+ */
238
+ rolloverStateLog(opts?: {
239
+ retentionDays?: number;
240
+ }): Promise<{
241
+ rolledUp: number;
242
+ deletedRaw: number;
243
+ }>;
244
+ /**
245
+ * Return all gates registered (for the dev-registries endpoint).
246
+ */
247
+ inspectRegistries(): {
248
+ gates: string[];
249
+ completionChecks: string[];
250
+ ladders: string[];
251
+ anchors: string[];
252
+ consolidationPolicies: string[];
253
+ };
254
+ /**
255
+ * Read the public view of `metadata.escalationCursor` for a task. Returns
256
+ * `null` when the task is not found or has no cursor recorded yet.
257
+ */
258
+ getEscalationCursor(taskId: string): Promise<EscalationCursorView | null>;
259
+ }
260
+ export interface ScheduledTaskRunnerHandle extends ScheduledTaskRunner, ScheduledTaskRunnerExtras {
261
+ }
262
+ export declare function createScheduledTaskRunner(deps: ScheduledTaskRunnerDeps): ScheduledTaskRunnerHandle;
263
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/scheduled-task/runner.ts"],"names":[],"mappings":"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"}