shadok-ai 0.3.102 → 0.3.103
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.
- package/README.md +1 -0
- package/context/scheduler-skill/SKILL.md +32 -2
- package/context/scheduler-skill/scripts/schedule.mjs +30 -3
- package/context/scheduler-skill/test/schedule.test.mjs +18 -0
- package/dist/crons.d.ts +43 -2
- package/dist/crons.js +73 -1
- package/dist/crons.js.map +1 -1
- package/dist/server.js +42 -12
- package/dist/server.js.map +1 -1
- package/dist/telegram.js +15 -2
- package/dist/telegram.js.map +1 -1
- package/package.json +1 -1
- package/public/index.html +38 -7
package/README.md
CHANGED
|
@@ -128,6 +128,7 @@ topics* (and *Delete messages* so `/secret` can scrub values), then in the group
|
|
|
128
128
|
| `/restart` | respawn the agent in place (e.g. to pick up new secrets) |
|
|
129
129
|
| `/profiles` · `/list` | list profiles · list bindings |
|
|
130
130
|
| `/cron every 30m <prompt>` · `/cron daily 09:00 <prompt>` | schedule a recurring prompt on this agent |
|
|
131
|
+
| `/cron once 2026-08-25T08:42 <prompt>` | fire it **once** on that date, then the schedule is left disabled and marked `(fired)` |
|
|
131
132
|
| `/cron list` · `/cron on\|off\|del <id>` | manage them (`<id>` accepts the printed 8-char prefix) |
|
|
132
133
|
| `/secrets` · `/secret KEY value` · `/unsecret KEY` | the secret vault |
|
|
133
134
|
| `/update` | fetch `@latest` and respawn |
|
|
@@ -61,9 +61,34 @@ node scripts/schedule.mjs tz [<zone>|-]
|
|
|
61
61
|
node scripts/schedule.mjs env
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
`<spec>`: `every:30m` · `every:2h` · `daily:09:00`.
|
|
64
|
+
`<spec>`: `every:30m` · `every:2h` · `daily:09:00` · `once:2026-08-25T08:42`.
|
|
65
65
|
|
|
66
|
-
###
|
|
66
|
+
### One-shot — a reminder on a given date
|
|
67
|
+
|
|
68
|
+
`once:<YYYY-MM-DDTHH:MM>` fires **exactly once**, then the schedule is left in
|
|
69
|
+
the list disabled and marked `(fired)` — so you can see it ran, and delete it
|
|
70
|
+
when you want.
|
|
71
|
+
|
|
72
|
+
Use it whenever the user asks to be reminded or warned **on a date** ("warn Alex
|
|
73
|
+
on the 25th", "remind me on Monday morning"). Do NOT reach for the harness's own
|
|
74
|
+
one-shot scheduler for that: it lives in the agent's process and dies with it,
|
|
75
|
+
whereas this one is on disk and survives a restart, an auto-update, and a
|
|
76
|
+
container recreate.
|
|
77
|
+
|
|
78
|
+
Two behaviours worth knowing:
|
|
79
|
+
|
|
80
|
+
- A date already in the past is **refused**, not silently accepted.
|
|
81
|
+
- A slot missed while the server was down still fires **late**, at the next
|
|
82
|
+
tick. A reminder arriving late beats a reminder that vanished — the prompt
|
|
83
|
+
carries its own date, so say in it what it is about and when it was for.
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
node scripts/schedule.mjs add \
|
|
87
|
+
--schedule once:2026-08-25T08:42 \
|
|
88
|
+
--prompt "REMINDER — Alex is back today. Two documents have been stuck in generation since 18/08: …"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Timezone — read this before scheduling a `daily` or a `once`
|
|
67
92
|
|
|
68
93
|
A `daily` runs at that wall-clock time **in a timezone**, and the default is
|
|
69
94
|
whatever the SERVER's machine is set to. On a machine running in UTC,
|
|
@@ -78,6 +103,11 @@ When the user names an hour and you're not sure the server sits in their
|
|
|
78
103
|
timezone, check with `tz` first — `list` shows the zone next to each schedule.
|
|
79
104
|
An interval (`every:30m`) is a duration, so it has no timezone.
|
|
80
105
|
|
|
106
|
+
A `once` date is read in that same timezone at CREATION and stored as an
|
|
107
|
+
absolute instant. Changing the instance timezone afterwards realigns the
|
|
108
|
+
`daily` schedules but **not** a `once` — its instant was already arbitrated.
|
|
109
|
+
So check `tz` BEFORE scheduling a dated reminder, not after.
|
|
110
|
+
|
|
81
111
|
### Example — guarded monitoring (near-zero tokens)
|
|
82
112
|
|
|
83
113
|
```
|
|
@@ -50,12 +50,23 @@ async function api(ctx, method, path, body) {
|
|
|
50
50
|
return raw ? JSON.parse(raw) : {};
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
/** `every:30m` · `every:2h` · `every:45` · `daily:09:00`
|
|
53
|
+
/** `every:30m` · `every:2h` · `every:45` · `daily:09:00` · `once:2026-08-25T08:42`
|
|
54
|
+
* → the API's schedule. */
|
|
54
55
|
export function parseSchedule(spec) {
|
|
55
56
|
const s = String(spec).trim().toLowerCase();
|
|
56
57
|
const bad = () => {
|
|
57
|
-
throw new UsageError(
|
|
58
|
+
throw new UsageError(
|
|
59
|
+
`bad schedule '${spec}' (use every:30m, every:2h, daily:09:00, or once:2026-08-25T08:42)`,
|
|
60
|
+
);
|
|
58
61
|
};
|
|
62
|
+
if (s.startsWith("once:")) {
|
|
63
|
+
// Sent as written: the instant depends on the cron's timezone, which only
|
|
64
|
+
// the server knows. Parsing it here too would be a second truth, and the
|
|
65
|
+
// server already answers with a precise message on an unreadable date.
|
|
66
|
+
const at = s.slice(5).trim();
|
|
67
|
+
if (!at) bad();
|
|
68
|
+
return { kind: "once", at };
|
|
69
|
+
}
|
|
59
70
|
if (s.startsWith("every:")) {
|
|
60
71
|
const m = /^(\d+)([hm]?)$/.exec(s.slice(6));
|
|
61
72
|
// Python raised on a non-numeric value; JS would quietly make it NaN and
|
|
@@ -76,6 +87,19 @@ const pad = (n) => String(n).padStart(2, "0");
|
|
|
76
87
|
|
|
77
88
|
export function label(s, tz) {
|
|
78
89
|
if (s.kind === "interval") return `every ${s.everyMin}m`;
|
|
90
|
+
if (s.kind === "once") {
|
|
91
|
+
// `at` comes back from the server as an absolute ms epoch, so it is read in
|
|
92
|
+
// the cron's zone — otherwise "once 06:42" doesn't say 6:42 WHERE, the same
|
|
93
|
+
// trap as a bare daily but worse, because a date does not come round again.
|
|
94
|
+
const p = new Intl.DateTimeFormat("en-CA", {
|
|
95
|
+
timeZone: tz || undefined,
|
|
96
|
+
hour12: false,
|
|
97
|
+
year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit",
|
|
98
|
+
}).formatToParts(new Date(s.at));
|
|
99
|
+
const f = Object.fromEntries(p.filter((x) => x.type !== "literal").map((x) => [x.type, x.value]));
|
|
100
|
+
const hour = pad(Number(f.hour) % 24); // some ICU builds render midnight as "24"
|
|
101
|
+
return `once ${f.year}-${f.month}-${f.day} ${hour}:${f.minute}` + (tz ? ` (${tz})` : "");
|
|
102
|
+
}
|
|
79
103
|
// The timezone is always shown: a bare "daily 09:00" doesn't say 9am WHERE,
|
|
80
104
|
// and that is exactly what makes a UTC server look on time.
|
|
81
105
|
return `daily ${pad(s.hour)}:${pad(s.minute)}` + (tz ? ` (${tz})` : "");
|
|
@@ -135,7 +159,10 @@ async function cmdList(ctx) {
|
|
|
135
159
|
if (!mine.length) return console.log("(no schedule on this channel)");
|
|
136
160
|
const tzinfo = await api(ctx, "GET", "/timezone");
|
|
137
161
|
for (const c of mine) {
|
|
138
|
-
|
|
162
|
+
// A spent one-shot is not "paused": it fired. Saying paused suggests that
|
|
163
|
+
// resuming it would run it again.
|
|
164
|
+
const spent = c.schedule?.kind === "once" && c.lastRun;
|
|
165
|
+
const flags = (c.enabled ? "" : spent ? " (fired)" : " (paused)") + (c.check ? " +guard" : "");
|
|
139
166
|
const tz = c.tz || tzinfo.timezone || tzinfo.system;
|
|
140
167
|
console.log(`[${String(c.id).slice(0, 8)}] ${label(c.schedule, tz)}${flags}\n ${String(c.prompt).slice(0, 100)}`);
|
|
141
168
|
}
|
|
@@ -150,3 +150,21 @@ test("an API error is reported, not swallowed", async () => {
|
|
|
150
150
|
assert.notEqual(res.code, 0);
|
|
151
151
|
assert.match(res.err, /API error 500/);
|
|
152
152
|
});
|
|
153
|
+
|
|
154
|
+
test("parseSchedule passes a one-shot date through for the server to resolve", () => {
|
|
155
|
+
// Deliberately NOT parsed here: the instant depends on the cron's timezone,
|
|
156
|
+
// which only the server knows. Two parsers would be two truths.
|
|
157
|
+
assert.deepEqual(parseSchedule("once:2026-08-25T08:42"), { kind: "once", at: "2026-08-25t08:42" });
|
|
158
|
+
assert.deepEqual(parseSchedule(" ONCE:2026-08-25T08:42 "), { kind: "once", at: "2026-08-25t08:42" });
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test("parseSchedule still refuses garbage, and names once in the message", () => {
|
|
162
|
+
assert.throws(() => parseSchedule("once:"), /bad schedule/);
|
|
163
|
+
assert.throws(() => parseSchedule("nonsense"), /once:2026-08-25T08:42/);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test("label reads a one-shot instant in the cron's timezone", () => {
|
|
167
|
+
const at = Date.UTC(2026, 7, 25, 6, 42); // 08:42 in Paris (CEST)
|
|
168
|
+
assert.equal(label({ kind: "once", at }, "Europe/Paris"), "once 2026-08-25 08:42 (Europe/Paris)");
|
|
169
|
+
assert.equal(label({ kind: "once", at }, "UTC"), "once 2026-08-25 06:42 (UTC)");
|
|
170
|
+
});
|
package/dist/crons.d.ts
CHANGED
|
@@ -12,6 +12,19 @@ export type CronSchedule = {
|
|
|
12
12
|
kind: "daily";
|
|
13
13
|
hour: number;
|
|
14
14
|
minute: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* One-shot: fires once at an ABSOLUTE instant, then the cron is spent.
|
|
18
|
+
*
|
|
19
|
+
* Stored as an epoch and not as a wall clock + tz on purpose. A `daily` is a
|
|
20
|
+
* RULE, re-read every day, so changing the default timezone must move it
|
|
21
|
+
* (that is what `primeCrons` does). A one-shot is an instant already
|
|
22
|
+
* arbitrated at creation — moving it under the user because a global setting
|
|
23
|
+
* changed would be the surprise, not the service.
|
|
24
|
+
*/
|
|
25
|
+
| {
|
|
26
|
+
kind: "once";
|
|
27
|
+
at: number;
|
|
15
28
|
};
|
|
16
29
|
export interface Cron {
|
|
17
30
|
id: string;
|
|
@@ -114,8 +127,8 @@ export declare const CRON_MAX_RETRIES = 3;
|
|
|
114
127
|
* `nextRun` is ALWAYS in the future, which is what keeps the "advance nextRun
|
|
115
128
|
* before firing" anti-double-fire invariant intact.
|
|
116
129
|
*/
|
|
117
|
-
export declare function nextRunAfterFailure(nowMs: number, scheduledNextMs: number, attempts: number): {
|
|
118
|
-
nextRun: number;
|
|
130
|
+
export declare function nextRunAfterFailure(nowMs: number, scheduledNextMs: number | null, attempts: number): {
|
|
131
|
+
nextRun: number | null;
|
|
119
132
|
retrying: boolean;
|
|
120
133
|
attempts: number;
|
|
121
134
|
};
|
|
@@ -125,8 +138,36 @@ export declare function nextRunAfterFailure(nowMs: number, scheduledNextMs: numb
|
|
|
125
138
|
* time zone. Absent → the machine's local time (historical behaviour).
|
|
126
139
|
*/
|
|
127
140
|
export declare function nextRunFor(s: CronSchedule, fromMs: number, tz?: string | null): number;
|
|
141
|
+
/**
|
|
142
|
+
* What firing does to a cron's OWN schedule state, applied the instant it is
|
|
143
|
+
* fired (before the delivery is even attempted).
|
|
144
|
+
*
|
|
145
|
+
* A recurring cron advances to its next slot — that is what stops a long run
|
|
146
|
+
* from double-firing. A one-shot cannot: advancing lands on the same fixed
|
|
147
|
+
* instant, so it would fire forever. It is DISABLED instead, which is a
|
|
148
|
+
* stronger guarantee and reuses a state `cronTick`, `primeCrons` and
|
|
149
|
+
* `GET /channels` already skip. A transient delivery failure re-arms it — see
|
|
150
|
+
* `nextRunAfterFailure` with a null slot.
|
|
151
|
+
*/
|
|
152
|
+
export declare function stateAfterFire(s: CronSchedule, nowMs: number, tz?: string | null): {
|
|
153
|
+
enabled: boolean;
|
|
154
|
+
nextRun?: number;
|
|
155
|
+
};
|
|
128
156
|
/** Is this an IANA zone identifier the bundled ICU knows? */
|
|
129
157
|
export declare function isValidTimeZone(tz: string): boolean;
|
|
158
|
+
/**
|
|
159
|
+
* Read a human date into the absolute instant a one-shot fires at.
|
|
160
|
+
*
|
|
161
|
+
* Two shapes, on purpose. A bare "2026-08-25T08:42" is a WALL CLOCK: it means
|
|
162
|
+
* 08:42 where the cron lives, so it is resolved through `tz` — that is what the
|
|
163
|
+
* web form, the CLI and Telegram all produce. A string carrying an explicit
|
|
164
|
+
* offset (or Z) is already absolute and `tz` must NOT shift it; parsing that
|
|
165
|
+
* one as a wall clock would move a correct instant by the offset.
|
|
166
|
+
*
|
|
167
|
+
* Returns null on anything it cannot read — never a guessed date. A reminder
|
|
168
|
+
* silently scheduled for the wrong day is worse than a refused one.
|
|
169
|
+
*/
|
|
170
|
+
export declare function onceAt(tz: string, text: string): number | null;
|
|
130
171
|
/** Validate + normalize a raw schedule object; null if invalid. */
|
|
131
172
|
export declare function normalizeSchedule(raw: any): CronSchedule | null;
|
|
132
173
|
/** The machine's zone — the fallback when nothing is configured. */
|
package/dist/crons.js
CHANGED
|
@@ -78,7 +78,9 @@ export function nextRunAfterFailure(nowMs, scheduledNextMs, attempts) {
|
|
|
78
78
|
// The normal slot comes first (short intervals, or a daily cron whose next
|
|
79
79
|
// run is imminent): retrying would fire twice in a row for nothing, and it
|
|
80
80
|
// must never push a run PAST its own schedule.
|
|
81
|
-
|
|
81
|
+
// A one-shot passes `null`: it has no next slot, so nothing caps the retry —
|
|
82
|
+
// giving up on it would simply lose the reminder.
|
|
83
|
+
if (scheduledNextMs !== null && candidate >= scheduledNextMs)
|
|
82
84
|
return giveUp;
|
|
83
85
|
return { nextRun: candidate, retrying: true, attempts: attempts + 1 };
|
|
84
86
|
}
|
|
@@ -88,6 +90,11 @@ export function nextRunAfterFailure(nowMs, scheduledNextMs, attempts) {
|
|
|
88
90
|
* time zone. Absent → the machine's local time (historical behaviour).
|
|
89
91
|
*/
|
|
90
92
|
export function nextRunFor(s, fromMs, tz) {
|
|
93
|
+
// A one-shot never rolls forward: its instant is fixed, and returning it even
|
|
94
|
+
// when it is already past is what lets a fire missed during a restart still
|
|
95
|
+
// be caught up by `cronTick` (a past `nextRun` is due, not skipped).
|
|
96
|
+
if (s.kind === "once")
|
|
97
|
+
return s.at;
|
|
91
98
|
if (s.kind === "interval") {
|
|
92
99
|
const step = Math.max(1, Math.floor(s.everyMin)) * 60_000;
|
|
93
100
|
return fromMs + step;
|
|
@@ -111,6 +118,22 @@ export function nextRunFor(s, fromMs, tz) {
|
|
|
111
118
|
}
|
|
112
119
|
return t;
|
|
113
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* What firing does to a cron's OWN schedule state, applied the instant it is
|
|
123
|
+
* fired (before the delivery is even attempted).
|
|
124
|
+
*
|
|
125
|
+
* A recurring cron advances to its next slot — that is what stops a long run
|
|
126
|
+
* from double-firing. A one-shot cannot: advancing lands on the same fixed
|
|
127
|
+
* instant, so it would fire forever. It is DISABLED instead, which is a
|
|
128
|
+
* stronger guarantee and reuses a state `cronTick`, `primeCrons` and
|
|
129
|
+
* `GET /channels` already skip. A transient delivery failure re-arms it — see
|
|
130
|
+
* `nextRunAfterFailure` with a null slot.
|
|
131
|
+
*/
|
|
132
|
+
export function stateAfterFire(s, nowMs, tz) {
|
|
133
|
+
if (s.kind === "once")
|
|
134
|
+
return { enabled: false, nextRun: undefined };
|
|
135
|
+
return { enabled: true, nextRun: nextRunFor(s, nowMs, tz) };
|
|
136
|
+
}
|
|
114
137
|
/** Is this an IANA zone identifier the bundled ICU knows? */
|
|
115
138
|
export function isValidTimeZone(tz) {
|
|
116
139
|
if (!tz || typeof tz !== "string")
|
|
@@ -165,6 +188,44 @@ function instantOfWallClock(tz, y, mo, d, h, mi) {
|
|
|
165
188
|
};
|
|
166
189
|
return naive - offsetAt(naive - offsetAt(naive));
|
|
167
190
|
}
|
|
191
|
+
/** Days in a Gregorian month — so "2026-02-31" is refused instead of rolling
|
|
192
|
+
* over into March in silence. */
|
|
193
|
+
function daysInMonth(y, mo) {
|
|
194
|
+
return new Date(Date.UTC(y, mo, 0)).getUTCDate();
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Read a human date into the absolute instant a one-shot fires at.
|
|
198
|
+
*
|
|
199
|
+
* Two shapes, on purpose. A bare "2026-08-25T08:42" is a WALL CLOCK: it means
|
|
200
|
+
* 08:42 where the cron lives, so it is resolved through `tz` — that is what the
|
|
201
|
+
* web form, the CLI and Telegram all produce. A string carrying an explicit
|
|
202
|
+
* offset (or Z) is already absolute and `tz` must NOT shift it; parsing that
|
|
203
|
+
* one as a wall clock would move a correct instant by the offset.
|
|
204
|
+
*
|
|
205
|
+
* Returns null on anything it cannot read — never a guessed date. A reminder
|
|
206
|
+
* silently scheduled for the wrong day is worse than a refused one.
|
|
207
|
+
*/
|
|
208
|
+
export function onceAt(tz, text) {
|
|
209
|
+
const raw = (text ?? "").trim();
|
|
210
|
+
if (!raw)
|
|
211
|
+
return null;
|
|
212
|
+
if (/(?:Z|[+-]\d{2}:?\d{2})$/i.test(raw)) {
|
|
213
|
+
const t = Date.parse(raw);
|
|
214
|
+
return Number.isFinite(t) ? t : null;
|
|
215
|
+
}
|
|
216
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})[Tt ](\d{2}):(\d{2})(?::\d{2})?$/.exec(raw);
|
|
217
|
+
if (!m)
|
|
218
|
+
return null;
|
|
219
|
+
const [y, mo, d, h, mi] = m.slice(1).map(Number);
|
|
220
|
+
if (mo < 1 || mo > 12)
|
|
221
|
+
return null;
|
|
222
|
+
if (d < 1 || d > daysInMonth(y, mo))
|
|
223
|
+
return null;
|
|
224
|
+
if (h > 23 || mi > 59)
|
|
225
|
+
return null;
|
|
226
|
+
const zone = isValidTimeZone(tz) ? tz : systemTimeZone();
|
|
227
|
+
return instantOfWallClock(zone, y, mo, d, h, mi);
|
|
228
|
+
}
|
|
168
229
|
/** Validate + normalize a raw schedule object; null if invalid. */
|
|
169
230
|
export function normalizeSchedule(raw) {
|
|
170
231
|
if (!raw || typeof raw !== "object")
|
|
@@ -173,6 +234,11 @@ export function normalizeSchedule(raw) {
|
|
|
173
234
|
const everyMin = Number(raw.everyMin);
|
|
174
235
|
return Number.isFinite(everyMin) && everyMin >= 1 ? { kind: "interval", everyMin: Math.floor(everyMin) } : null;
|
|
175
236
|
}
|
|
237
|
+
if (raw.kind === "once") {
|
|
238
|
+
// `at` arrives as a string from an HTTP body often enough to accept one.
|
|
239
|
+
const at = Number(raw.at);
|
|
240
|
+
return Number.isFinite(at) && at > 0 ? { kind: "once", at: Math.floor(at) } : null;
|
|
241
|
+
}
|
|
176
242
|
if (raw.kind === "daily") {
|
|
177
243
|
const hour = Number(raw.hour);
|
|
178
244
|
const minute = Number(raw.minute);
|
|
@@ -215,6 +281,12 @@ export function cronTimeZone(c) {
|
|
|
215
281
|
* assume (a bare "daily at 09:00" does not say 09:00 where).
|
|
216
282
|
*/
|
|
217
283
|
export function scheduleLabel(s, tz) {
|
|
284
|
+
if (s.kind === "once") {
|
|
285
|
+
const zone = tz || systemTimeZone();
|
|
286
|
+
const w = wallClockIn(zone, s.at);
|
|
287
|
+
const p2 = (n) => String(n).padStart(2, "0");
|
|
288
|
+
return `once at ${w.year}-${p2(w.month)}-${p2(w.day)} ${p2(w.hour)}:${p2(w.minute)} (${zone})`;
|
|
289
|
+
}
|
|
218
290
|
if (s.kind === "interval") {
|
|
219
291
|
if (s.everyMin % 60 === 0)
|
|
220
292
|
return `every ${s.everyMin / 60}h`;
|
package/dist/crons.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crons.js","sourceRoot":"","sources":["../src/crons.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"crons.js","sourceRoot":"","sources":["../src/crons.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA6EzC;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAA4B,EAC5B,SAAiB,EACjB,WAAmB;IAEnB,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;IAC3D,OAAO;QACL,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,WAAW;QACnC,OAAO,EAAE,EAAE,EAAE,OAAO,IAAI,IAAI;QAC5B,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,IAAI;QAC1B,IAAI,EAAE,EAAE,EAAE,IAAI,IAAI,IAAI;QACtB,KAAK,EAAE,CAAC,CAAC,EAAE;KACZ,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAE3C,+EAA+E;AAC/E,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,gBAAgB,IAAI,IAAI,EAAE,CAAC;AACnE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACnF,CAAC;AAaD;;;;yDAIyD;AACzD,MAAM,SAAS,GAA6B,IAAI,GAAG,CAAc,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEjH,MAAM,UAAU,WAAW,CAAC,MAAmB;IAC7C,OAAO,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,wEAAwE;AACxE,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,GAAG,MAAM,CAAC;AAC/C,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAElC;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAa,EACb,eAA8B,EAC9B,QAAgB;IAEhB,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IAC1E,yDAAyD;IACzD,IAAI,QAAQ,IAAI,gBAAgB;QAAE,OAAO,MAAM,CAAC;IAChD,MAAM,SAAS,GAAG,KAAK,GAAG,mBAAmB,CAAC;IAC9C,2EAA2E;IAC3E,2EAA2E;IAC3E,+CAA+C;IAC/C,6EAA6E;IAC7E,kDAAkD;IAClD,IAAI,eAAe,KAAK,IAAI,IAAI,SAAS,IAAI,eAAe;QAAE,OAAO,MAAM,CAAC;IAC5E,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,GAAG,CAAC,EAAE,CAAC;AACxE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,CAAe,EAAE,MAAc,EAAE,EAAkB;IAC5E,8EAA8E;IAC9E,4EAA4E;IAC5E,qEAAqE;IACrE,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IACnC,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC;QAC1D,OAAO,MAAM,GAAG,IAAI,CAAC;IACvB,CAAC;IACD,IAAI,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,EAAE,CAAC;QAChC,0EAA0E;QAC1E,wEAAwE;QACxE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACtC,IAAI,IAAI,CAAC,OAAO,EAAE,IAAI,MAAM;YAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;IACD,MAAM,KAAK,GAAG,aAAa,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACxC,IAAI,CAAC,GAAG,kBAAkB,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IAC7E,IAAI,CAAC,IAAI,MAAM,EAAE,CAAC;QAChB,wEAAwE;QACxE,kDAAkD;QAClD,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC;QAC3E,CAAC,GAAG,kBAAkB,CAAC,EAAE,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,EAAE,CAAC,WAAW,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IAC3G,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAC5B,CAAe,EACf,KAAa,EACb,EAAkB;IAElB,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IACrE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,eAAe,CAAC,EAAU;IACxC,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAChD,IAAI,CAAC;QACH,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,qDAAqD;AACrD,SAAS,WAAW,CAAC,EAAU,EAAE,IAAY;IAC3C,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;QAC7C,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,SAAS;KAClB,CAAC,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACjC,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;YAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC/E,mEAAmE;IACnE,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;IACzB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,+DAA+D;AAC/D,SAAS,aAAa,CAAC,EAAU,EAAE,IAAY;IAC7C,MAAM,CAAC,GAAG,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAChC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;AAC9C,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,kBAAkB,CAAC,EAAU,EAAE,CAAS,EAAE,EAAU,EAAE,CAAS,EAAE,CAAS,EAAE,EAAU;IAC7F,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAE,EAAE;QAC9B,MAAM,CAAC,GAAG,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;IAC/E,CAAC,CAAC;IACF,OAAO,KAAK,GAAG,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;AACnD,CAAC;AAED;kCACkC;AAClC,SAAS,WAAW,CAAC,CAAS,EAAE,EAAU;IACxC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;AACnD,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,MAAM,CAAC,EAAU,EAAE,IAAY;IAC7C,MAAM,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,0BAA0B,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1B,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvC,CAAC;IACD,MAAM,CAAC,GAAG,0DAA0D,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/E,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACjD,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACjD,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,IAAI,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC;IACzD,OAAO,kBAAkB,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AACnD,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,iBAAiB,CAAC,GAAQ;IACxC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACjD,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtC,OAAO,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAClH,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACxB,yEAAyE;QACzE,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC1B,OAAO,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACrF,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,EAAE;YAAE,OAAO,IAAI,CAAC;QAClE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,EAAE;YAAE,OAAO,IAAI,CAAC;QACxE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACzC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ,IAAI,KAAK,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC,QAAQ,CAAC;IAClC,MAAM,EAAE,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACrD,OAAO,EAAE,IAAI,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,CAAmB;IAC9C,IAAI,CAAC,CAAC,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;QAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IAC/C,OAAO,eAAe,EAAE,IAAI,cAAc,EAAE,CAAC;AAC/C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,CAAe,EAAE,EAAW;IACxD,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,EAAE,IAAI,cAAc,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAClC,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACrD,OAAO,WAAW,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,GAAG,CAAC;IACjG,CAAC;IACD,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,QAAQ,GAAG,EAAE,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC,CAAC,QAAQ,GAAG,EAAE,GAAG,CAAC;QAC9D,OAAO,SAAS,CAAC,CAAC,QAAQ,GAAG,CAAC;IAChC,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;IACvF,OAAO,YAAY,IAAI,KAAK,EAAE,IAAI,cAAc,EAAE,GAAG,CAAC;AACxD,CAAC;AAED,SAAS,SAAS;IAChB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;IACxD,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;QAC3D,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACrG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,CAAC,GAAG,SAAS,EAAE,CAAC;IACtB,IAAI,CAAC;QACH,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;AACH,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,UAAU,CAAC,IAAU;IACnC,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,SAAS,CAAC,IAAI,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,SAAS,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;AACpD,CAAC;AAMD;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,MAAc;IACxD,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IACzD,qEAAqE;IACrE,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;IAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IAC5E,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IACpF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AACtC,CAAC"}
|
package/dist/server.js
CHANGED
|
@@ -27,7 +27,7 @@ import { getUsage } from "./usage.js";
|
|
|
27
27
|
import { loadChannels, loadGroups, saveGroups, upsertChannel, removeChannel, mergeClientChannels, loadTgGroup, saveTgGroup, isHomeChannel, homeAdoptionTarget, } from "./channels.js";
|
|
28
28
|
import { startTelegram, renameTelegramTopic, closeTelegramTopic, probeToken, isStalePreface, announceLoggedOut, resetLoggedOutNotice, attachmentPrompt, pasteFileName, MEDIA_DIR, } from "./telegram.js";
|
|
29
29
|
import { migrateTgBindings } from "./channels.js";
|
|
30
|
-
import { loadCrons, saveCrons, upsertCron, removeCron, resolveCronId, resolveCronTarget, nextRunFor, nextRunAfterFailure, isTransient, CRON_MAX_RETRIES, markCronPrompt, normalizeSchedule, scheduleLabel, cronTimeZone, defaultTimeZone, systemTimeZone, isValidTimeZone, } from "./crons.js";
|
|
30
|
+
import { loadCrons, saveCrons, upsertCron, removeCron, resolveCronId, resolveCronTarget, nextRunFor, nextRunAfterFailure, isTransient, CRON_MAX_RETRIES, markCronPrompt, normalizeSchedule, onceAt, stateAfterFire, scheduleLabel, cronTimeZone, defaultTimeZone, systemTimeZone, isValidTimeZone, } from "./crons.js";
|
|
31
31
|
import { linkRefusal, markAgentPrompt, notificationText, } from "./kinship.js";
|
|
32
32
|
import { loadConfig, saveConfig, telegramConfig, applyTelegramPatch, titleForCwd, setTitleForCwd, themeForCwd, setThemeForCwd, } from "./config.js";
|
|
33
33
|
import { secretsFor, secretNames, setSecret, deleteSecret, secretWriteVerdict } from "./secrets.js";
|
|
@@ -396,13 +396,19 @@ function settleCron(id, outcome, reason, detail) {
|
|
|
396
396
|
saveCrons(list);
|
|
397
397
|
return;
|
|
398
398
|
}
|
|
399
|
-
// `nextRun` was already advanced to the next normal slot before firing
|
|
400
|
-
|
|
399
|
+
// `nextRun` was already advanced to the next normal slot before firing — a
|
|
400
|
+
// one-shot has none, and passes null so nothing caps its retries.
|
|
401
|
+
const once = c.schedule.kind === "once";
|
|
402
|
+
const slot = once ? null : (c.nextRun ?? nextRunFor(c.schedule, Date.now(), cronTimeZone(c)));
|
|
401
403
|
const r = nextRunAfterFailure(Date.now(), slot, c.retries ?? 0);
|
|
402
|
-
c.nextRun = r.nextRun;
|
|
404
|
+
c.nextRun = r.nextRun ?? undefined;
|
|
403
405
|
c.retries = r.attempts;
|
|
406
|
+
// `cronTick` disabled it before the fire; a transient loss must put it back,
|
|
407
|
+
// otherwise a channel that was merely busy eats the reminder for good.
|
|
408
|
+
if (once)
|
|
409
|
+
c.enabled = r.retrying;
|
|
404
410
|
console.log(r.retrying
|
|
405
|
-
? `${cronTag(c)} skipped: ${reason}, retry in ${Math.round((r.nextRun - Date.now()) / 60_000)}m (${r.attempts}/${CRON_MAX_RETRIES})`
|
|
411
|
+
? `${cronTag(c)} skipped: ${reason}, retry in ${Math.round(((r.nextRun ?? Date.now()) - Date.now()) / 60_000)}m (${r.attempts}/${CRON_MAX_RETRIES})`
|
|
406
412
|
: `${cronTag(c)} skipped: ${reason}, giving up until next slot`);
|
|
407
413
|
saveCrons(list);
|
|
408
414
|
}
|
|
@@ -426,7 +432,12 @@ function cronTick() {
|
|
|
426
432
|
// scheduled by settleCron is always in the future, so it can't re-trigger
|
|
427
433
|
// a run that is still going.
|
|
428
434
|
c.lastRun = now;
|
|
429
|
-
|
|
435
|
+
// A recurring cron advances to its next slot; a one-shot cannot (its
|
|
436
|
+
// instant is fixed) and is disabled instead — a stronger anti-double-fire
|
|
437
|
+
// guarantee, and a state every consumer already skips.
|
|
438
|
+
const st = stateAfterFire(c.schedule, now, cronTimeZone(c));
|
|
439
|
+
c.enabled = st.enabled;
|
|
440
|
+
c.nextRun = st.nextRun;
|
|
430
441
|
changed = true;
|
|
431
442
|
if (cronsFiring.has(c.id))
|
|
432
443
|
continue;
|
|
@@ -803,12 +814,10 @@ app.post("/crons", (req, res) => {
|
|
|
803
814
|
const b = req.body ?? {};
|
|
804
815
|
const sessionId = String(b.sessionId ?? "").trim();
|
|
805
816
|
const prompt = String(b.prompt ?? "").trim();
|
|
806
|
-
const schedule = normalizeSchedule(b.schedule);
|
|
807
|
-
if (!sessionId || !prompt || !schedule)
|
|
808
|
-
return res.status(400).json({ error: "sessionId, prompt and a valid schedule are required" });
|
|
809
817
|
const existing = b.id ? loadCrons().find((c) => c.id === b.id) : undefined;
|
|
810
|
-
|
|
811
|
-
|
|
818
|
+
// The zone is resolved BEFORE the schedule: a one-shot dated as a wall clock
|
|
819
|
+
// ("2026-08-25T08:42") means nothing without it.
|
|
820
|
+
//
|
|
812
821
|
// Explicit zone: refused when invalid rather than silently ignored — a
|
|
813
822
|
// "Europe/Pariss" falling back to the machine's zone would produce exactly
|
|
814
823
|
// the silent shift this is meant to remove.
|
|
@@ -816,6 +825,27 @@ app.post("/crons", (req, res) => {
|
|
|
816
825
|
if (rawTz && !isValidTimeZone(rawTz))
|
|
817
826
|
return res.status(400).json({ error: `unknown timezone '${rawTz}'` });
|
|
818
827
|
const tz = rawTz || existing?.tz;
|
|
828
|
+
const zone = cronTimeZone({ tz });
|
|
829
|
+
let rawSchedule = b.schedule;
|
|
830
|
+
if (rawSchedule?.kind === "once" && typeof rawSchedule.at === "string" && !/^\d+$/.test(rawSchedule.at.trim())) {
|
|
831
|
+
const at = onceAt(zone, rawSchedule.at);
|
|
832
|
+
if (at == null)
|
|
833
|
+
return res.status(400).json({ error: `unreadable date '${rawSchedule.at}' — use YYYY-MM-DDTHH:MM` });
|
|
834
|
+
rawSchedule = { kind: "once", at };
|
|
835
|
+
}
|
|
836
|
+
const schedule = normalizeSchedule(rawSchedule);
|
|
837
|
+
if (!sessionId || !prompt || !schedule)
|
|
838
|
+
return res.status(400).json({ error: "sessionId, prompt and a valid schedule are required" });
|
|
839
|
+
// An instant already past is refused rather than stored: it would fire within
|
|
840
|
+
// the second, which is not what anyone means by writing a date.
|
|
841
|
+
if (schedule.kind === "once" && schedule.at <= Date.now())
|
|
842
|
+
return res.status(400).json({ error: `that instant is already past (${scheduleLabel(schedule, zone)})` });
|
|
843
|
+
const enabled = typeof b.enabled === "boolean"
|
|
844
|
+
? b.enabled
|
|
845
|
+
: schedule.kind === "once"
|
|
846
|
+
? true // re-arm: a spent one-shot being re-edited is enabled:false
|
|
847
|
+
: (existing?.enabled ?? true);
|
|
848
|
+
const check = typeof b.check === "string" && b.check.trim() ? String(b.check).trim() : undefined;
|
|
819
849
|
const cron = {
|
|
820
850
|
id: existing?.id ?? randomUUID(),
|
|
821
851
|
sessionId,
|
|
@@ -825,7 +855,7 @@ app.post("/crons", (req, res) => {
|
|
|
825
855
|
...(check ? { check } : {}),
|
|
826
856
|
...(tz ? { tz } : {}),
|
|
827
857
|
lastRun: existing?.lastRun,
|
|
828
|
-
nextRun: enabled ? nextRunFor(schedule, Date.now(),
|
|
858
|
+
nextRun: enabled ? nextRunFor(schedule, Date.now(), zone) : undefined,
|
|
829
859
|
};
|
|
830
860
|
upsertCron(cron);
|
|
831
861
|
res.json({ ...cron, timezone: cronTimeZone(cron) });
|