@relayflows/sdk 2.0.0
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/dist/authored-flow-error.d.ts +9 -0
- package/dist/authored-flow-error.d.ts.map +1 -0
- package/dist/authored-flow-error.js +13 -0
- package/dist/authored-flow-error.js.map +1 -0
- package/dist/authored-flow-executor.d.ts +28 -0
- package/dist/authored-flow-executor.d.ts.map +1 -0
- package/dist/authored-flow-executor.js +203 -0
- package/dist/authored-flow-executor.js.map +1 -0
- package/dist/authored-flow-lifecycle.d.ts +61 -0
- package/dist/authored-flow-lifecycle.d.ts.map +1 -0
- package/dist/authored-flow-lifecycle.js +284 -0
- package/dist/authored-flow-lifecycle.js.map +1 -0
- package/dist/authored-flow-loader.d.ts +7 -0
- package/dist/authored-flow-loader.d.ts.map +1 -0
- package/dist/authored-flow-loader.js +39 -0
- package/dist/authored-flow-loader.js.map +1 -0
- package/dist/authored-flow-operation.d.ts +43 -0
- package/dist/authored-flow-operation.d.ts.map +1 -0
- package/dist/authored-flow-operation.js +176 -0
- package/dist/authored-flow-operation.js.map +1 -0
- package/dist/authored-flow.d.ts +12 -0
- package/dist/authored-flow.d.ts.map +1 -0
- package/dist/authored-flow.js +13 -0
- package/dist/authored-flow.js.map +1 -0
- package/dist/authored-promise-graph.d.ts +67 -0
- package/dist/authored-promise-graph.d.ts.map +1 -0
- package/dist/authored-promise-graph.js +206 -0
- package/dist/authored-promise-graph.js.map +1 -0
- package/dist/backlog-picker.d.ts +55 -0
- package/dist/backlog-picker.d.ts.map +1 -0
- package/dist/backlog-picker.js +117 -0
- package/dist/backlog-picker.js.map +1 -0
- package/dist/canonical.d.ts +18 -0
- package/dist/canonical.d.ts.map +1 -0
- package/dist/canonical.js +55 -0
- package/dist/canonical.js.map +1 -0
- package/dist/cli/check.d.ts +30 -0
- package/dist/cli/check.d.ts.map +1 -0
- package/dist/cli/check.js +324 -0
- package/dist/cli/check.js.map +1 -0
- package/dist/cli/direct-run.d.ts +3 -0
- package/dist/cli/direct-run.d.ts.map +1 -0
- package/dist/cli/direct-run.js +69 -0
- package/dist/cli/direct-run.js.map +1 -0
- package/dist/cli/hn-monitor.d.ts +107 -0
- package/dist/cli/hn-monitor.d.ts.map +1 -0
- package/dist/cli/hn-monitor.js +220 -0
- package/dist/cli/hn-monitor.js.map +1 -0
- package/dist/cli/interruptible-sleep.d.ts +13 -0
- package/dist/cli/interruptible-sleep.d.ts.map +1 -0
- package/dist/cli/interruptible-sleep.js +31 -0
- package/dist/cli/interruptible-sleep.js.map +1 -0
- package/dist/cli/run.d.ts +54 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +316 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/tick-runner.d.ts +151 -0
- package/dist/cli/tick-runner.d.ts.map +1 -0
- package/dist/cli/tick-runner.js +258 -0
- package/dist/cli/tick-runner.js.map +1 -0
- package/dist/cli-adapter.d.ts +29 -0
- package/dist/cli-adapter.d.ts.map +1 -0
- package/dist/cli-adapter.js +92 -0
- package/dist/cli-adapter.js.map +1 -0
- package/dist/cli-executable.d.ts +3 -0
- package/dist/cli-executable.d.ts.map +1 -0
- package/dist/cli-executable.js +10 -0
- package/dist/cli-executable.js.map +1 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +348 -0
- package/dist/cli.js.map +1 -0
- package/dist/compile.d.ts +42 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +515 -0
- package/dist/compile.js.map +1 -0
- package/dist/demo-hn-monitor.d.ts +2 -0
- package/dist/demo-hn-monitor.d.ts.map +1 -0
- package/dist/demo-hn-monitor.js +118 -0
- package/dist/demo-hn-monitor.js.map +1 -0
- package/dist/dir-watcher-poller.d.ts +73 -0
- package/dist/dir-watcher-poller.d.ts.map +1 -0
- package/dist/dir-watcher-poller.js +80 -0
- package/dist/dir-watcher-poller.js.map +1 -0
- package/dist/direct-input.d.ts +10 -0
- package/dist/direct-input.d.ts.map +1 -0
- package/dist/direct-input.js +61 -0
- package/dist/direct-input.js.map +1 -0
- package/dist/failure-kinds.d.ts +25 -0
- package/dist/failure-kinds.d.ts.map +1 -0
- package/dist/failure-kinds.js +64 -0
- package/dist/failure-kinds.js.map +1 -0
- package/dist/gate-contract.d.ts +24 -0
- package/dist/gate-contract.d.ts.map +1 -0
- package/dist/gate-contract.js +50 -0
- package/dist/gate-contract.js.map +1 -0
- package/dist/hn-poller.d.ts +50 -0
- package/dist/hn-poller.d.ts.map +1 -0
- package/dist/hn-poller.js +79 -0
- package/dist/hn-poller.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/journal-client.d.ts +122 -0
- package/dist/journal-client.d.ts.map +1 -0
- package/dist/journal-client.js +277 -0
- package/dist/journal-client.js.map +1 -0
- package/dist/json-schema-bound.d.ts +7 -0
- package/dist/json-schema-bound.d.ts.map +1 -0
- package/dist/json-schema-bound.js +353 -0
- package/dist/json-schema-bound.js.map +1 -0
- package/dist/json-schema.d.ts +5 -0
- package/dist/json-schema.d.ts.map +1 -0
- package/dist/json-schema.js +72 -0
- package/dist/json-schema.js.map +1 -0
- package/dist/json-value.d.ts +6 -0
- package/dist/json-value.d.ts.map +1 -0
- package/dist/json-value.js +94 -0
- package/dist/json-value.js.map +1 -0
- package/dist/model-name.d.ts +7 -0
- package/dist/model-name.d.ts.map +1 -0
- package/dist/model-name.js +21 -0
- package/dist/model-name.js.map +1 -0
- package/dist/output-schema.d.ts +8 -0
- package/dist/output-schema.d.ts.map +1 -0
- package/dist/output-schema.js +28 -0
- package/dist/output-schema.js.map +1 -0
- package/dist/preflight.d.ts +80 -0
- package/dist/preflight.d.ts.map +1 -0
- package/dist/preflight.js +361 -0
- package/dist/preflight.js.map +1 -0
- package/dist/protocol.d.ts +359 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +15 -0
- package/dist/protocol.js.map +1 -0
- package/dist/spec.d.ts +294 -0
- package/dist/spec.d.ts.map +1 -0
- package/dist/spec.js +13 -0
- package/dist/spec.js.map +1 -0
- package/dist/step-dependencies.d.ts +2 -0
- package/dist/step-dependencies.d.ts.map +1 -0
- package/dist/step-dependencies.js +88 -0
- package/dist/step-dependencies.js.map +1 -0
- package/dist/step-fields.d.ts +17 -0
- package/dist/step-fields.d.ts.map +1 -0
- package/dist/step-fields.js +32 -0
- package/dist/step-fields.js.map +1 -0
- package/dist/tick-source.d.ts +205 -0
- package/dist/tick-source.d.ts.map +1 -0
- package/dist/tick-source.js +234 -0
- package/dist/tick-source.js.map +1 -0
- package/dist/unknown-keys.d.ts +7 -0
- package/dist/unknown-keys.d.ts.map +1 -0
- package/dist/unknown-keys.js +47 -0
- package/dist/unknown-keys.js.map +1 -0
- package/dist/validate.d.ts +7 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +458 -0
- package/dist/validate.js.map +1 -0
- package/dist/work-package-consumer.d.ts +33 -0
- package/dist/work-package-consumer.d.ts.map +1 -0
- package/dist/work-package-consumer.js +44 -0
- package/dist/work-package-consumer.js.map +1 -0
- package/dist/work-package-validator.d.ts +15 -0
- package/dist/work-package-validator.d.ts.map +1 -0
- package/dist/work-package-validator.js +72 -0
- package/dist/work-package-validator.js.map +1 -0
- package/dist/worker-cli.d.ts +16 -0
- package/dist/worker-cli.d.ts.map +1 -0
- package/dist/worker-cli.js +77 -0
- package/dist/worker-cli.js.map +1 -0
- package/dist/worker.d.ts +57 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +129 -0
- package/dist/worker.js.map +1 -0
- package/dist/wrapper-runtime.d.ts +10 -0
- package/dist/wrapper-runtime.d.ts.map +1 -0
- package/dist/wrapper-runtime.js +83 -0
- package/dist/wrapper-runtime.js.map +1 -0
- package/dist/wrapper-session.d.ts +16 -0
- package/dist/wrapper-session.d.ts.map +1 -0
- package/dist/wrapper-session.js +244 -0
- package/dist/wrapper-session.js.map +1 -0
- package/package.json +50 -0
- package/src/authored-flow-error.ts +31 -0
- package/src/authored-flow-executor.ts +365 -0
- package/src/authored-flow-lifecycle.ts +344 -0
- package/src/authored-flow-loader.ts +44 -0
- package/src/authored-flow-operation.ts +252 -0
- package/src/authored-flow.ts +21 -0
- package/src/authored-promise-graph.ts +196 -0
- package/src/backlog-picker.ts +153 -0
- package/src/canonical.ts +57 -0
- package/src/cli/check.ts +391 -0
- package/src/cli/direct-run.ts +86 -0
- package/src/cli/hn-monitor.ts +286 -0
- package/src/cli/interruptible-sleep.ts +27 -0
- package/src/cli/run.ts +439 -0
- package/src/cli/tick-runner.ts +378 -0
- package/src/cli-adapter.ts +115 -0
- package/src/cli-executable.ts +12 -0
- package/src/cli.ts +364 -0
- package/src/compile.ts +573 -0
- package/src/demo-hn-monitor.ts +132 -0
- package/src/dir-watcher-poller.ts +122 -0
- package/src/direct-input.ts +69 -0
- package/src/failure-kinds.ts +77 -0
- package/src/gate-contract.ts +72 -0
- package/src/hn-poller.ts +104 -0
- package/src/index.ts +195 -0
- package/src/journal-client.ts +379 -0
- package/src/json-schema-bound.ts +357 -0
- package/src/json-schema.ts +65 -0
- package/src/json-value.ts +110 -0
- package/src/model-name.ts +20 -0
- package/src/output-schema.ts +33 -0
- package/src/preflight.ts +482 -0
- package/src/protocol.ts +364 -0
- package/src/spec.ts +343 -0
- package/src/step-dependencies.ts +100 -0
- package/src/step-fields.ts +36 -0
- package/src/tick-source.ts +334 -0
- package/src/unknown-keys.ts +52 -0
- package/src/validate.ts +503 -0
- package/src/work-package-consumer.ts +73 -0
- package/src/work-package-validator.ts +90 -0
- package/src/worker-cli.ts +110 -0
- package/src/worker.ts +150 -0
- package/src/wrapper-runtime.ts +93 -0
- package/src/wrapper-session.ts +287 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `flows tick start` — drive a scheduled relayflow.
|
|
3
|
+
*
|
|
4
|
+
* A sibling of `hn-monitor.ts`, not a new species: a public function that
|
|
5
|
+
* composes the primitives directly — connect journal → hello → loop
|
|
6
|
+
* `emitDueTicks` → drain on abort → close. The differences from hn-monitor are
|
|
7
|
+
* only the ones the grid forces.
|
|
8
|
+
*
|
|
9
|
+
* ## Why the cursor is persisted, and why that is the whole point
|
|
10
|
+
*
|
|
11
|
+
* `emitDueTicks` starts a FRESH cursor at the current slot:
|
|
12
|
+
*
|
|
13
|
+
* const firstDue = cursor.lastEmittedSlot === undefined
|
|
14
|
+
* ? currentSlot
|
|
15
|
+
* : cursor.lastEmittedSlot + 1;
|
|
16
|
+
*
|
|
17
|
+
* That is right for a schedule's first ever poll — a new hourly schedule must
|
|
18
|
+
* not backfill from the epoch. But it means an in-memory-only cursor makes a
|
|
19
|
+
* restart SKIP every slot between shutdown and restart, silently. The dedupe
|
|
20
|
+
* key `(schedule_id, scheduled_for_ms)` makes re-delivery of a slot harmless,
|
|
21
|
+
* so a lost cursor cannot double-fire; nothing in the primitive protects
|
|
22
|
+
* against the skip. The runner is where that is either handled or lost, so it
|
|
23
|
+
* persists the cursor and reloads it on start.
|
|
24
|
+
*
|
|
25
|
+
* The distinction the file keeps: "no cursor on disk" means first run, start
|
|
26
|
+
* at the current slot. "A cursor on disk behind the grid" means catch up, and
|
|
27
|
+
* report anything past `maxCatchUp` as skipped. Conflating the two either
|
|
28
|
+
* backfills a new schedule from 1970 or silently drops a restart's arrears.
|
|
29
|
+
*
|
|
30
|
+
* ## Why a skip must reach the operator
|
|
31
|
+
*
|
|
32
|
+
* `skippedSlots` and `TickEmitError` exist because a skip that is only a
|
|
33
|
+
* return value is a skip that a `throw` can discard. `emitDueTicks` guarantees
|
|
34
|
+
* the accounting survives its own failure; this runner is the consumer that
|
|
35
|
+
* makes it visible. A skipped slot is real scheduled work that did not run.
|
|
36
|
+
*/
|
|
37
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
38
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
39
|
+
import { JournalClient } from '../journal-client.js';
|
|
40
|
+
import { DEFAULT_MAX_CATCH_UP, TickEmitError, assertTickScheduleValid, emitDueTicks, scheduledForMs, slotFor, } from '../tick-source.js';
|
|
41
|
+
import { sleepInterruptible } from './interruptible-sleep.js';
|
|
42
|
+
/** How often to look for due slots when the caller does not say. */
|
|
43
|
+
const DEFAULT_POLL_INTERVAL_MS = 15_000;
|
|
44
|
+
/** Connect and handshake. Both steps, or neither. */
|
|
45
|
+
async function defaultConnectClient(socketPath) {
|
|
46
|
+
const client = new JournalClient(socketPath);
|
|
47
|
+
await client.connect();
|
|
48
|
+
await client.hello('flows-tick-runner');
|
|
49
|
+
return client;
|
|
50
|
+
}
|
|
51
|
+
/** Absolute path to the state file for one schedule. */
|
|
52
|
+
export function tickStatePath(dataDir, scheduleId) {
|
|
53
|
+
return join(dataDir, 'tick-state', `${encodeURIComponent(scheduleId)}.json`);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Load the durable cursor, distinguishing "no state" from "state behind the
|
|
57
|
+
* grid". A missing file is a first run and must start at the current slot; a
|
|
58
|
+
* present file must be honoured however far behind it is, so the arrears are
|
|
59
|
+
* either caught up or reported.
|
|
60
|
+
*
|
|
61
|
+
* A malformed or foreign-schedule state file is a hard error rather than a
|
|
62
|
+
* silent reset: resetting would convert an operator's corrupted file into a
|
|
63
|
+
* silent skip of everything since the last good emit, which is the failure
|
|
64
|
+
* this runner exists to prevent.
|
|
65
|
+
*/
|
|
66
|
+
export async function loadTickState(path, scheduleId) {
|
|
67
|
+
let raw;
|
|
68
|
+
try {
|
|
69
|
+
raw = await readFile(path, 'utf8');
|
|
70
|
+
}
|
|
71
|
+
catch (cause) {
|
|
72
|
+
if (cause.code === 'ENOENT') {
|
|
73
|
+
return { scheduleId, skippedSlots: [] };
|
|
74
|
+
}
|
|
75
|
+
throw cause;
|
|
76
|
+
}
|
|
77
|
+
let parsed;
|
|
78
|
+
try {
|
|
79
|
+
parsed = JSON.parse(raw);
|
|
80
|
+
}
|
|
81
|
+
catch (cause) {
|
|
82
|
+
throw new Error(`tick state at ${path} is not valid JSON`, { cause });
|
|
83
|
+
}
|
|
84
|
+
if (typeof parsed !== 'object' || parsed === null) {
|
|
85
|
+
throw new Error(`tick state at ${path} is not an object`);
|
|
86
|
+
}
|
|
87
|
+
const state = parsed;
|
|
88
|
+
if (state.scheduleId !== scheduleId) {
|
|
89
|
+
throw new Error(`tick state at ${path} belongs to schedule ${String(state.scheduleId)}, not ${scheduleId}`);
|
|
90
|
+
}
|
|
91
|
+
if (state.lastEmittedSlot !== undefined && !Number.isInteger(state.lastEmittedSlot)) {
|
|
92
|
+
throw new Error(`tick state at ${path} has a non-integer lastEmittedSlot`);
|
|
93
|
+
}
|
|
94
|
+
// Fail closed rather than coerce. `Array.isArray(...) ? ... : []` silently
|
|
95
|
+
// turned a malformed value into "no slots were skipped" — which is the exact
|
|
96
|
+
// claim this runner exists to make trustworthy. A state file that cannot say
|
|
97
|
+
// what it missed must stop the runner, not quietly report that it missed
|
|
98
|
+
// nothing.
|
|
99
|
+
if (state.skippedSlots !== undefined && !Array.isArray(state.skippedSlots)) {
|
|
100
|
+
throw new Error(`tick state at ${path} has a non-array skippedSlots`);
|
|
101
|
+
}
|
|
102
|
+
if (state.skippedSlots?.some((slot) => !Number.isInteger(slot))) {
|
|
103
|
+
throw new Error(`tick state at ${path} has a non-integer entry in skippedSlots`);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
scheduleId,
|
|
107
|
+
...(state.lastEmittedSlot === undefined ? {} : { lastEmittedSlot: state.lastEmittedSlot }),
|
|
108
|
+
...(state.lastEmittedAtMs === undefined ? {} : { lastEmittedAtMs: state.lastEmittedAtMs }),
|
|
109
|
+
skippedSlots: state.skippedSlots ?? [],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Persist the cursor. Written to a temp file and renamed, so a crash mid-write
|
|
114
|
+
* leaves the previous good state rather than a truncated file — a truncated
|
|
115
|
+
* file would be a hard error on next start, which is safe but needlessly
|
|
116
|
+
* blocks a runner that had a perfectly good cursor a moment earlier.
|
|
117
|
+
*/
|
|
118
|
+
export async function saveTickState(path, state) {
|
|
119
|
+
await mkdir(dirname(path), { recursive: true });
|
|
120
|
+
const temp = `${path}.tmp`;
|
|
121
|
+
await writeFile(temp, `${JSON.stringify(state, null, 2)}\n`, 'utf8');
|
|
122
|
+
const { rename } = await import('node:fs/promises');
|
|
123
|
+
await rename(temp, path);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Run `flows tick start`. Returns 0 on clean shutdown, 1 on a fatal error.
|
|
127
|
+
*
|
|
128
|
+
* Fatal means: the schedule is invalid, the state file is unreadable or
|
|
129
|
+
* belongs to another schedule, the journal cannot be reached, or a submit
|
|
130
|
+
* failed. A submit failure is fatal by design — `emitDueTicks` leaves the slot
|
|
131
|
+
* due, so retrying is the next poll's job, but a runner that swallows journal
|
|
132
|
+
* failures and keeps looping is the silent-zero this is meant to prevent.
|
|
133
|
+
*/
|
|
134
|
+
export async function runTickRunner(args, io) {
|
|
135
|
+
const now = args.now ?? Date.now;
|
|
136
|
+
const pollIntervalMs = args.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
137
|
+
// Refuse a bad grid BEFORE connecting. A runner that attaches and only then
|
|
138
|
+
// discovers `--interval-ms` was 1.5 has already told the operator it started.
|
|
139
|
+
try {
|
|
140
|
+
assertTickScheduleValid(args.schedule, now());
|
|
141
|
+
}
|
|
142
|
+
catch (cause) {
|
|
143
|
+
io.stderr(`REFUSED [invalid_schedule] ${cause.message}`);
|
|
144
|
+
return 1;
|
|
145
|
+
}
|
|
146
|
+
if (!Number.isInteger(pollIntervalMs) || pollIntervalMs <= 0) {
|
|
147
|
+
io.stderr('REFUSED [invalid_schedule] pollIntervalMs must be a positive integer');
|
|
148
|
+
return 1;
|
|
149
|
+
}
|
|
150
|
+
const specPath = isAbsolute(args.specPath) ? args.specPath : resolve(args.specPath);
|
|
151
|
+
const statePath = args.statePath ?? tickStatePath(args.dataDir, args.schedule.scheduleId);
|
|
152
|
+
let spec;
|
|
153
|
+
let state;
|
|
154
|
+
try {
|
|
155
|
+
spec = JSON.parse(await readFile(specPath, 'utf8'));
|
|
156
|
+
state = await loadTickState(statePath, args.schedule.scheduleId);
|
|
157
|
+
}
|
|
158
|
+
catch (cause) {
|
|
159
|
+
io.stderr(`REFUSED [invalid_state] ${cause.message}`);
|
|
160
|
+
return 1;
|
|
161
|
+
}
|
|
162
|
+
const resuming = state.lastEmittedSlot !== undefined;
|
|
163
|
+
const cursor = resuming ? { lastEmittedSlot: state.lastEmittedSlot } : {};
|
|
164
|
+
const socketPath = join(args.dataDir, 'relayflowd.sock');
|
|
165
|
+
let client;
|
|
166
|
+
try {
|
|
167
|
+
client = args.connectClient
|
|
168
|
+
? await args.connectClient(socketPath)
|
|
169
|
+
: await defaultConnectClient(socketPath);
|
|
170
|
+
}
|
|
171
|
+
catch (cause) {
|
|
172
|
+
io.stderr(`TICK_RUNNER_FAILED ${cause.constructor.name}: ${cause.message}`);
|
|
173
|
+
return 1;
|
|
174
|
+
}
|
|
175
|
+
let exitCode = 0;
|
|
176
|
+
try {
|
|
177
|
+
const startSlot = slotFor(args.schedule, now());
|
|
178
|
+
io.stdout(resuming
|
|
179
|
+
? `TICK_RUNNER schedule=${args.schedule.scheduleId} resuming from slot ${String(state.lastEmittedSlot)}; current slot ${startSlot}`
|
|
180
|
+
: `TICK_RUNNER schedule=${args.schedule.scheduleId} first run; starting at slot ${startSlot}`);
|
|
181
|
+
let polls = 0;
|
|
182
|
+
while (!(args.signal?.aborted ?? false)) {
|
|
183
|
+
if (args.maxPolls !== undefined && polls >= args.maxPolls)
|
|
184
|
+
break;
|
|
185
|
+
polls += 1;
|
|
186
|
+
const report = await pollOnce(spec, client, args.schedule, cursor, now());
|
|
187
|
+
// Persist before reporting. The cursor is the thing a restart depends
|
|
188
|
+
// on; losing it costs slots, whereas losing a log line costs a message.
|
|
189
|
+
if (report.emittedSlots.length > 0) {
|
|
190
|
+
state.lastEmittedSlot = cursor.lastEmittedSlot;
|
|
191
|
+
state.lastEmittedAtMs = now();
|
|
192
|
+
}
|
|
193
|
+
if (report.skippedSlots.length > 0) {
|
|
194
|
+
state.skippedSlots.push(...report.skippedSlots);
|
|
195
|
+
}
|
|
196
|
+
if (report.emittedSlots.length > 0 || report.skippedSlots.length > 0) {
|
|
197
|
+
await saveTickState(statePath, state);
|
|
198
|
+
}
|
|
199
|
+
for (const slot of report.skippedSlots) {
|
|
200
|
+
// Loud, per slot, with the instant it stood for. A count would let a
|
|
201
|
+
// reader skim past "3 skipped"; an instant is a thing an operator can
|
|
202
|
+
// go and look for in the journal and fail to find.
|
|
203
|
+
io.stderr(`TICK_SKIPPED schedule=${args.schedule.scheduleId} slot=${slot} scheduled_for_ms=${scheduledForMs(args.schedule, slot)} — past maxCatchUp=${args.schedule.maxCatchUp ?? DEFAULT_MAX_CATCH_UP}; this scheduled work did NOT run`);
|
|
204
|
+
}
|
|
205
|
+
for (const slot of report.emittedSlots) {
|
|
206
|
+
io.stdout(`TICK_EMITTED schedule=${args.schedule.scheduleId} slot=${slot} scheduled_for_ms=${scheduledForMs(args.schedule, slot)}`);
|
|
207
|
+
}
|
|
208
|
+
if (report.failure !== undefined) {
|
|
209
|
+
const failure = report.failure;
|
|
210
|
+
const name = failure instanceof Error ? failure.constructor.name : typeof failure;
|
|
211
|
+
const message = failure instanceof Error ? failure.message : String(failure);
|
|
212
|
+
io.stderr(`TICK_RUNNER_FAILED ${name}: ${message}`);
|
|
213
|
+
return 1;
|
|
214
|
+
}
|
|
215
|
+
if (args.signal?.aborted ?? false)
|
|
216
|
+
break;
|
|
217
|
+
if (args.maxPolls !== undefined && polls >= args.maxPolls)
|
|
218
|
+
break;
|
|
219
|
+
await sleepInterruptible(pollIntervalMs, args.signal);
|
|
220
|
+
}
|
|
221
|
+
io.stdout(`TICK_RUNNER_STOPPED schedule=${args.schedule.scheduleId} polls=${polls}`);
|
|
222
|
+
}
|
|
223
|
+
catch (cause) {
|
|
224
|
+
const name = cause instanceof Error ? cause.constructor.name : typeof cause;
|
|
225
|
+
io.stderr(`TICK_RUNNER_FAILED ${name}: ${cause.message}`);
|
|
226
|
+
exitCode = 1;
|
|
227
|
+
}
|
|
228
|
+
finally {
|
|
229
|
+
client.close();
|
|
230
|
+
}
|
|
231
|
+
return exitCode;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* One poll. Normalises the two shapes `emitDueTicks` can produce — a result,
|
|
235
|
+
* or a `TickEmitError` carrying the partial result — into one report, so the
|
|
236
|
+
* caller has exactly one accounting path and cannot handle the success case
|
|
237
|
+
* and forget the failure case.
|
|
238
|
+
*/
|
|
239
|
+
async function pollOnce(spec, sink, schedule, cursor, nowMs) {
|
|
240
|
+
try {
|
|
241
|
+
const result = await emitDueTicks(spec, sink, { schedule, cursor, nowMs });
|
|
242
|
+
return { emittedSlots: result.emittedSlots, skippedSlots: result.skippedSlots };
|
|
243
|
+
}
|
|
244
|
+
catch (cause) {
|
|
245
|
+
if (cause instanceof TickEmitError) {
|
|
246
|
+
// The partial accounting travelled with the failure. Surface it, then
|
|
247
|
+
// let the caller treat the failure as fatal — the unemitted slots are
|
|
248
|
+
// still due, because `emitDueTicks` only advances on success.
|
|
249
|
+
return {
|
|
250
|
+
emittedSlots: cause.emittedSlots,
|
|
251
|
+
skippedSlots: cause.skippedSlots,
|
|
252
|
+
failure: cause.cause ?? cause,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
return { emittedSlots: [], skippedSlots: [], failure: cause };
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=tick-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tick-runner.js","sourceRoot":"","sources":["../../src/cli/tick-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type CliAdapterKind = 'claude' | 'codex' | 'relayflows-wrapper-v1';
|
|
2
|
+
export interface CliInvocation {
|
|
3
|
+
args: string[];
|
|
4
|
+
timeoutMs: number;
|
|
5
|
+
/** Set only for wrapper readiness probes; raw providers receive a model flag. */
|
|
6
|
+
modelEnv?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface CliAdapterIdentification {
|
|
9
|
+
invocation: CliInvocation;
|
|
10
|
+
expectedStdout?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const WRAPPER_IDENTIFY_ARG = "--relayflows-adapter-v1";
|
|
13
|
+
export declare const WRAPPER_IDENTIFY_TOKEN = "relayflows-agent-cli-v1";
|
|
14
|
+
export declare const WRAPPER_EXECUTE_TOKEN = "relayflows-agent-cli-v1-execute";
|
|
15
|
+
/** Select a closed adapter from the resolved executable's basename. */
|
|
16
|
+
export declare function cliAdapterKind(executable: string): CliAdapterKind;
|
|
17
|
+
/** Prove the adapter command shape before classifying an auth failure. */
|
|
18
|
+
export declare function adapterIdentification(kind: CliAdapterKind): CliAdapterIdentification;
|
|
19
|
+
export declare function authenticationProbe(kind: CliAdapterKind): CliInvocation;
|
|
20
|
+
/**
|
|
21
|
+
* A provider model probe is a real, noninteractive model round trip. The
|
|
22
|
+
* wrapper protocol keeps its established auth-status shape and receives the
|
|
23
|
+
* exact model through its explicitly identified environment contract.
|
|
24
|
+
*/
|
|
25
|
+
export declare function modelReadinessProbe(kind: CliAdapterKind, model: string): CliInvocation;
|
|
26
|
+
/** Build the actual worker argv; this is shared contract, not probe-only lore. */
|
|
27
|
+
export declare function agentExecution(kind: CliAdapterKind, instruction: string, model?: string): CliInvocation;
|
|
28
|
+
export declare function displayInvocation(cli: string, invocation: CliInvocation): string;
|
|
29
|
+
//# sourceMappingURL=cli-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-adapter.d.ts","sourceRoot":"","sources":["../src/cli-adapter.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,GAAG,uBAAuB,CAAC;AAE1E,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,aAAa,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,oBAAoB,4BAA4B,CAAC;AAC9D,eAAO,MAAM,sBAAsB,4BAA4B,CAAC;AAChE,eAAO,MAAM,qBAAqB,oCAAoC,CAAC;AAIvE,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CAKjE;AAED,0EAA0E;AAC1E,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,cAAc,GAAG,wBAAwB,CAWpF;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,cAAc,GAAG,aAAa,CAGvE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,CAwBtF;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAC5B,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,MAAM,GACb,aAAa,CAkBf;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,GAAG,MAAM,CAKhF"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { basename } from 'node:path';
|
|
2
|
+
export const WRAPPER_IDENTIFY_ARG = '--relayflows-adapter-v1';
|
|
3
|
+
export const WRAPPER_IDENTIFY_TOKEN = 'relayflows-agent-cli-v1';
|
|
4
|
+
export const WRAPPER_EXECUTE_TOKEN = 'relayflows-agent-cli-v1-execute';
|
|
5
|
+
const MODEL_PROBE_PROMPT = 'Reply with exactly RELAYFLOWS_MODEL_READY and nothing else.';
|
|
6
|
+
/** Select a closed adapter from the resolved executable's basename. */
|
|
7
|
+
export function cliAdapterKind(executable) {
|
|
8
|
+
const name = basename(executable).replace(/\.exe$/i, '');
|
|
9
|
+
if (name === 'claude')
|
|
10
|
+
return 'claude';
|
|
11
|
+
if (name === 'codex')
|
|
12
|
+
return 'codex';
|
|
13
|
+
return 'relayflows-wrapper-v1';
|
|
14
|
+
}
|
|
15
|
+
/** Prove the adapter command shape before classifying an auth failure. */
|
|
16
|
+
export function adapterIdentification(kind) {
|
|
17
|
+
if (kind === 'claude') {
|
|
18
|
+
return { invocation: { args: ['auth', 'status', '--help'], timeoutMs: 10_000 } };
|
|
19
|
+
}
|
|
20
|
+
if (kind === 'codex') {
|
|
21
|
+
return { invocation: { args: ['login', 'status', '--help'], timeoutMs: 10_000 } };
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
invocation: { args: [WRAPPER_IDENTIFY_ARG], timeoutMs: 10_000 },
|
|
25
|
+
expectedStdout: WRAPPER_IDENTIFY_TOKEN,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function authenticationProbe(kind) {
|
|
29
|
+
if (kind === 'codex')
|
|
30
|
+
return { args: ['login', 'status'], timeoutMs: 10_000 };
|
|
31
|
+
return { args: ['auth', 'status'], timeoutMs: 10_000 };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A provider model probe is a real, noninteractive model round trip. The
|
|
35
|
+
* wrapper protocol keeps its established auth-status shape and receives the
|
|
36
|
+
* exact model through its explicitly identified environment contract.
|
|
37
|
+
*/
|
|
38
|
+
export function modelReadinessProbe(kind, model) {
|
|
39
|
+
if (kind === 'claude') {
|
|
40
|
+
return {
|
|
41
|
+
args: [
|
|
42
|
+
'-p', '--model', model, '--tools', '', '--no-session-persistence',
|
|
43
|
+
MODEL_PROBE_PROMPT,
|
|
44
|
+
],
|
|
45
|
+
timeoutMs: 60_000,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (kind === 'codex') {
|
|
49
|
+
return {
|
|
50
|
+
args: [
|
|
51
|
+
'exec', '--ephemeral', '--sandbox', 'read-only', '--skip-git-repo-check',
|
|
52
|
+
'--model', model, MODEL_PROBE_PROMPT,
|
|
53
|
+
],
|
|
54
|
+
timeoutMs: 60_000,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
args: ['auth', 'status'],
|
|
59
|
+
timeoutMs: 60_000,
|
|
60
|
+
modelEnv: model,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** Build the actual worker argv; this is shared contract, not probe-only lore. */
|
|
64
|
+
export function agentExecution(kind, instruction, model) {
|
|
65
|
+
if (kind === 'claude') {
|
|
66
|
+
return {
|
|
67
|
+
args: ['-p', ...(model === undefined ? [] : ['--model', model]), instruction],
|
|
68
|
+
timeoutMs: 0,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (kind === 'codex') {
|
|
72
|
+
return {
|
|
73
|
+
args: [
|
|
74
|
+
'exec', '--ephemeral', '--skip-git-repo-check',
|
|
75
|
+
...(model === undefined ? [] : ['--model', model]),
|
|
76
|
+
instruction,
|
|
77
|
+
],
|
|
78
|
+
timeoutMs: 0,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
throw new Error('custom wrapper execution requires the runAgentCli same-process session');
|
|
82
|
+
}
|
|
83
|
+
export function displayInvocation(cli, invocation) {
|
|
84
|
+
const command = [cli, ...invocation.args].map(shellDisplayWord).join(' ');
|
|
85
|
+
return invocation.modelEnv === undefined
|
|
86
|
+
? command
|
|
87
|
+
: `RELAYFLOW_MODEL=${shellDisplayWord(invocation.modelEnv)} ${command}`;
|
|
88
|
+
}
|
|
89
|
+
function shellDisplayWord(word) {
|
|
90
|
+
return /^[A-Za-z0-9_./:-]+$/.test(word) ? word : JSON.stringify(word);
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=cli-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-adapter.js","sourceRoot":"","sources":["../src/cli-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAgBrC,MAAM,CAAC,MAAM,oBAAoB,GAAG,yBAAyB,CAAC;AAC9D,MAAM,CAAC,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;AAChE,MAAM,CAAC,MAAM,qBAAqB,GAAG,iCAAiC,CAAC;AAEvE,MAAM,kBAAkB,GAAG,6DAA6D,CAAC;AAEzF,uEAAuE;AACvE,MAAM,UAAU,cAAc,CAAC,UAAkB;IAC/C,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACzD,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IACvC,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,OAAO,CAAC;IACrC,OAAO,uBAAuB,CAAC;AACjC,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,qBAAqB,CAAC,IAAoB;IACxD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC;IACnF,CAAC;IACD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC;IACpF,CAAC;IACD,OAAO;QACL,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,oBAAoB,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE;QAC/D,cAAc,EAAE,sBAAsB;KACvC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAoB;IACtD,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAC9E,OAAO,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;AACzD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAoB,EAAE,KAAa;IACrE,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO;YACL,IAAI,EAAE;gBACJ,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,0BAA0B;gBACjE,kBAAkB;aACnB;YACD,SAAS,EAAE,MAAM;SAClB,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO;YACL,IAAI,EAAE;gBACJ,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,uBAAuB;gBACxE,SAAS,EAAE,KAAK,EAAE,kBAAkB;aACrC;YACD,SAAS,EAAE,MAAM;SAClB,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;QACxB,SAAS,EAAE,MAAM;QACjB,QAAQ,EAAE,KAAK;KAChB,CAAC;AACJ,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,cAAc,CAC5B,IAAoB,EACpB,WAAmB,EACnB,KAAc;IAEd,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO;YACL,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC;YAC7E,SAAS,EAAE,CAAC;SACb,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO;YACL,IAAI,EAAE;gBACJ,MAAM,EAAE,aAAa,EAAE,uBAAuB;gBAC9C,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBAClD,WAAW;aACZ;YACD,SAAS,EAAE,CAAC;SACb,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;AAC5F,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW,EAAE,UAAyB;IACtE,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1E,OAAO,UAAU,CAAC,QAAQ,KAAK,SAAS;QACtC,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,mBAAmB,gBAAgB,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,OAAO,EAAE,CAAC;AAC5E,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY;IACpC,OAAO,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACxE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-executable.d.ts","sourceRoot":"","sources":["../src/cli-executable.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { runCli } from './cli.js';
|
|
3
|
+
async function main() {
|
|
4
|
+
process.exitCode = await runCli(process.argv.slice(2));
|
|
5
|
+
}
|
|
6
|
+
void main().catch((error) => {
|
|
7
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
8
|
+
process.exitCode = 1;
|
|
9
|
+
});
|
|
10
|
+
//# sourceMappingURL=cli-executable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-executable.js","sourceRoot":"","sources":["../src/cli-executable.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IACnC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
export type { CheckInputDiagnostic, CheckReport } from './cli/check.js';
|
|
3
|
+
export interface CliIo {
|
|
4
|
+
stdout(line: string): void;
|
|
5
|
+
stderr(line: string): void;
|
|
6
|
+
}
|
|
7
|
+
type CliExitCode = 0 | 1 | 2 | 3;
|
|
8
|
+
export declare function runCli(args: readonly string[], io?: CliIo): Promise<CliExitCode>;
|
|
9
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAoBA,YAAY,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAExE,MAAM,WAAW,KAAK;IACpB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,KAAK,WAAW,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AA0BjC,wBAAsB,MAAM,CAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,GAAE,KAAkB,GACrB,OAAO,CAAC,WAAW,CAAC,CAoEtB"}
|