@grackle-ai/plugin-core 0.96.3
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/codespace-handlers.d.ts +6 -0
- package/dist/codespace-handlers.d.ts.map +1 -0
- package/dist/codespace-handlers.js +66 -0
- package/dist/codespace-handlers.js.map +1 -0
- package/dist/cron-phase.d.ts +46 -0
- package/dist/cron-phase.d.ts.map +1 -0
- package/dist/cron-phase.js +88 -0
- package/dist/cron-phase.js.map +1 -0
- package/dist/dispatch-phase.d.ts +46 -0
- package/dist/dispatch-phase.d.ts.map +1 -0
- package/dist/dispatch-phase.js +99 -0
- package/dist/dispatch-phase.js.map +1 -0
- package/dist/environment-handlers.d.ts +16 -0
- package/dist/environment-handlers.d.ts.map +1 -0
- package/dist/environment-handlers.js +255 -0
- package/dist/environment-handlers.js.map +1 -0
- package/dist/environment-reconciliation.d.ts +35 -0
- package/dist/environment-reconciliation.d.ts.map +1 -0
- package/dist/environment-reconciliation.js +74 -0
- package/dist/environment-reconciliation.js.map +1 -0
- package/dist/escalation-handlers.d.ts +8 -0
- package/dist/escalation-handlers.d.ts.map +1 -0
- package/dist/escalation-handlers.js +60 -0
- package/dist/escalation-handlers.js.map +1 -0
- package/dist/finding-handlers.d.ts +8 -0
- package/dist/finding-handlers.d.ts.map +1 -0
- package/dist/finding-handlers.js +38 -0
- package/dist/finding-handlers.js.map +1 -0
- package/dist/grpc-proto-converters.d.ts +31 -0
- package/dist/grpc-proto-converters.d.ts.map +1 -0
- package/dist/grpc-proto-converters.js +222 -0
- package/dist/grpc-proto-converters.js.map +1 -0
- package/dist/grpc-service.d.ts +21 -0
- package/dist/grpc-service.d.ts.map +1 -0
- package/dist/grpc-service.js +50 -0
- package/dist/grpc-service.js.map +1 -0
- package/dist/grpc-shared.d.ts +22 -0
- package/dist/grpc-shared.d.ts.map +1 -0
- package/dist/grpc-shared.js +68 -0
- package/dist/grpc-shared.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/knowledge-handlers.d.ts +12 -0
- package/dist/knowledge-handlers.d.ts.map +1 -0
- package/dist/knowledge-handlers.js +149 -0
- package/dist/knowledge-handlers.js.map +1 -0
- package/dist/lifecycle-cleanup.d.ts +13 -0
- package/dist/lifecycle-cleanup.d.ts.map +1 -0
- package/dist/lifecycle-cleanup.js +35 -0
- package/dist/lifecycle-cleanup.js.map +1 -0
- package/dist/lifecycle.d.ts +28 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +132 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/orphan-phase.d.ts +27 -0
- package/dist/orphan-phase.d.ts.map +1 -0
- package/dist/orphan-phase.js +69 -0
- package/dist/orphan-phase.js.map +1 -0
- package/dist/persona-handlers.d.ts +12 -0
- package/dist/persona-handlers.d.ts.map +1 -0
- package/dist/persona-handlers.js +156 -0
- package/dist/persona-handlers.js.map +1 -0
- package/dist/root-task-boot.d.ts +67 -0
- package/dist/root-task-boot.d.ts.map +1 -0
- package/dist/root-task-boot.js +234 -0
- package/dist/root-task-boot.js.map +1 -0
- package/dist/schedule-expression.d.ts +43 -0
- package/dist/schedule-expression.d.ts.map +1 -0
- package/dist/schedule-expression.js +105 -0
- package/dist/schedule-expression.js.map +1 -0
- package/dist/schedule-handlers.d.ts +12 -0
- package/dist/schedule-handlers.d.ts.map +1 -0
- package/dist/schedule-handlers.js +122 -0
- package/dist/schedule-handlers.js.map +1 -0
- package/dist/session-handlers.d.ts +40 -0
- package/dist/session-handlers.d.ts.map +1 -0
- package/dist/session-handlers.js +610 -0
- package/dist/session-handlers.js.map +1 -0
- package/dist/settings-handlers.d.ts +10 -0
- package/dist/settings-handlers.d.ts.map +1 -0
- package/dist/settings-handlers.js +80 -0
- package/dist/settings-handlers.js.map +1 -0
- package/dist/signals/escalation-auto.d.ts +20 -0
- package/dist/signals/escalation-auto.d.ts.map +1 -0
- package/dist/signals/escalation-auto.js +126 -0
- package/dist/signals/escalation-auto.js.map +1 -0
- package/dist/signals/orphan-reparent.d.ts +31 -0
- package/dist/signals/orphan-reparent.d.ts.map +1 -0
- package/dist/signals/orphan-reparent.js +175 -0
- package/dist/signals/orphan-reparent.js.map +1 -0
- package/dist/signals/sigchld.d.ts +12 -0
- package/dist/signals/sigchld.d.ts.map +1 -0
- package/dist/signals/sigchld.js +177 -0
- package/dist/signals/sigchld.js.map +1 -0
- package/dist/task-handlers.d.ts +22 -0
- package/dist/task-handlers.d.ts.map +1 -0
- package/dist/task-handlers.js +517 -0
- package/dist/task-handlers.js.map +1 -0
- package/dist/test-utils/integration-setup.d.ts +11 -0
- package/dist/test-utils/integration-setup.d.ts.map +1 -0
- package/dist/test-utils/integration-setup.js +26 -0
- package/dist/test-utils/integration-setup.js.map +1 -0
- package/dist/test-utils/mock-database.d.ts +152 -0
- package/dist/test-utils/mock-database.d.ts.map +1 -0
- package/dist/test-utils/mock-database.js +169 -0
- package/dist/test-utils/mock-database.js.map +1 -0
- package/dist/token-handlers.d.ts +12 -0
- package/dist/token-handlers.d.ts.map +1 -0
- package/dist/token-handlers.js +85 -0
- package/dist/token-handlers.js.map +1 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/dist/utils/format-gh-error.d.ts +6 -0
- package/dist/utils/format-gh-error.d.ts.map +1 -0
- package/dist/utils/format-gh-error.js +30 -0
- package/dist/utils/format-gh-error.js.map +1 -0
- package/dist/workspace-handlers.d.ts +16 -0
- package/dist/workspace-handlers.d.ts.map +1 -0
- package/dist/workspace-handlers.js +146 -0
- package/dist/workspace-handlers.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Root task boot with reanimate-first strategy and exponential backoff.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from the inline closure in `server/src/index.ts` so it can be
|
|
5
|
+
* unit tested. Follows the dependency-injection pattern established by
|
|
6
|
+
* `cron-phase.ts`.
|
|
7
|
+
*
|
|
8
|
+
* On each invocation (triggered by `environment.changed` events):
|
|
9
|
+
* 1. Checks if the root task is already running — if so, tracks stability.
|
|
10
|
+
* 2. If not running, attempts to reanimate the most recent session (preserving
|
|
11
|
+
* conversation history) before falling back to a fresh spawn.
|
|
12
|
+
* 3. Applies exponential backoff after consecutive failures to prevent
|
|
13
|
+
* crash-loop resource waste.
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
import { ROOT_TASK_ID, ROOT_TASK_INITIAL_PROMPT, TASK_STATUS } from "@grackle-ai/common";
|
|
18
|
+
import { logger } from "@grackle-ai/core";
|
|
19
|
+
// ─── Constants ──────────────────────────────────────────────
|
|
20
|
+
/** Initial delay before the first retry after a failed boot (milliseconds). */
|
|
21
|
+
const BOOT_INITIAL_DELAY_MS = 1_000;
|
|
22
|
+
/** Multiplier for exponential backoff between boot retries. */
|
|
23
|
+
const BOOT_BACKOFF_MULTIPLIER = 2;
|
|
24
|
+
/** Maximum delay between boot retries (milliseconds). */
|
|
25
|
+
const BOOT_MAX_DELAY_MS = 60_000;
|
|
26
|
+
/** Maximum consecutive boot failures before giving up until server restart. */
|
|
27
|
+
const BOOT_MAX_FAILURES = 10;
|
|
28
|
+
/** Minimum time a session must survive (ms) to be considered stable and reset backoff. */
|
|
29
|
+
const BOOT_STABLE_THRESHOLD_MS = 30_000;
|
|
30
|
+
// ─── State ──────────────────────────────────────────────────
|
|
31
|
+
/** Create a fresh backoff state. */
|
|
32
|
+
function createInitialState() {
|
|
33
|
+
return {
|
|
34
|
+
failures: 0,
|
|
35
|
+
lastFailureAt: 0,
|
|
36
|
+
inProgress: false,
|
|
37
|
+
lastSessionStartedAt: 0,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// ─── Public API ─────────────────────────────────────────────
|
|
41
|
+
/**
|
|
42
|
+
* Create the root task boot handler.
|
|
43
|
+
*
|
|
44
|
+
* Returns a callable async function that can be wired to `environment.changed`
|
|
45
|
+
* event subscriptions. Each call checks whether the root task needs starting
|
|
46
|
+
* and applies reanimate-first + exponential backoff logic.
|
|
47
|
+
*
|
|
48
|
+
* Each call creates independent backoff state (not shared across calls).
|
|
49
|
+
*
|
|
50
|
+
* @param deps - Injected dependencies for testability.
|
|
51
|
+
* @returns An async function to call on each `environment.changed` event.
|
|
52
|
+
*/
|
|
53
|
+
export function createRootTaskBoot(deps) {
|
|
54
|
+
return createRootTaskBootHandler(deps, createInitialState());
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Create the root task boot subscriber.
|
|
58
|
+
*
|
|
59
|
+
* Creates independent backoff state (not shared with other factory calls)
|
|
60
|
+
* and subscribes to `environment.changed` and `setting.changed` events.
|
|
61
|
+
* Returns a Disposable that unsubscribes the handler.
|
|
62
|
+
*
|
|
63
|
+
* @param ctx - Plugin context providing event-bus access.
|
|
64
|
+
* @param deps - Injected dependencies for testability.
|
|
65
|
+
* @returns A Disposable that unsubscribes the handler.
|
|
66
|
+
*/
|
|
67
|
+
export function createRootTaskBootSubscriber(ctx, deps) {
|
|
68
|
+
const bootState = createInitialState();
|
|
69
|
+
const tryBoot = createRootTaskBootHandler(deps, bootState);
|
|
70
|
+
const unsubscribe = ctx.subscribe((event) => {
|
|
71
|
+
if (event.type === "environment.changed") {
|
|
72
|
+
tryBoot().catch(() => { });
|
|
73
|
+
}
|
|
74
|
+
// Also try when onboarding completes — the environment is already
|
|
75
|
+
// connected but boot was deferred until the user chose a runtime.
|
|
76
|
+
if (event.type === "setting.changed") {
|
|
77
|
+
const payload = event.payload;
|
|
78
|
+
if (payload.key === "onboarding_completed" && payload.value === "true") {
|
|
79
|
+
tryBoot().catch(() => { });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
return {
|
|
84
|
+
dispose() {
|
|
85
|
+
unsubscribe();
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// ─── Internal ───────────────────────────────────────────────
|
|
90
|
+
/**
|
|
91
|
+
* Create an async boot handler that uses the given backoff state.
|
|
92
|
+
* Shared implementation for both {@link createRootTaskBoot} and
|
|
93
|
+
* {@link createRootTaskBootSubscriber}.
|
|
94
|
+
*/
|
|
95
|
+
function createRootTaskBootHandler(deps, s) {
|
|
96
|
+
return async () => {
|
|
97
|
+
// Guard: prevent concurrent boot attempts
|
|
98
|
+
if (s.inProgress) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
s.inProgress = true;
|
|
102
|
+
try {
|
|
103
|
+
await attemptBoot(deps, s);
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
recordFailure(s);
|
|
107
|
+
logger.warn({ err }, "Root task boot failed with unexpected exception");
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
s.inProgress = false; // eslint-disable-line require-atomic-updates -- single-threaded, flag guards re-entry
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/** Core boot logic — separated from the guard/error wrapper for clarity. */
|
|
115
|
+
async function attemptBoot(deps, s) {
|
|
116
|
+
// 0. Don't auto-start before onboarding — the user hasn't chosen their
|
|
117
|
+
// runtime yet, so the root task would launch with the default "claude-code".
|
|
118
|
+
if (deps.isOnboarded && !deps.isOnboarded()) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
// 1. Look up root task
|
|
122
|
+
const rootTask = deps.getTask(ROOT_TASK_ID);
|
|
123
|
+
if (!rootTask) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
// 2. Check if already working
|
|
127
|
+
const sessions = deps.listSessionsForTask(ROOT_TASK_ID);
|
|
128
|
+
const { status } = deps.computeTaskStatus(rootTask.status, sessions);
|
|
129
|
+
if (status === TASK_STATUS.WORKING) {
|
|
130
|
+
checkStabilityReset(s);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
// 2b. Crash-loop detection: if we recently started a session but the task
|
|
134
|
+
// is no longer working before the stability threshold, count it as a failure.
|
|
135
|
+
// This catches the case where startTaskSession succeeded but the session
|
|
136
|
+
// crashed shortly after (the main crash-loop scenario from issue #959).
|
|
137
|
+
if (s.lastSessionStartedAt > 0) {
|
|
138
|
+
const sinceLastStart = Date.now() - s.lastSessionStartedAt;
|
|
139
|
+
if (sinceLastStart < BOOT_STABLE_THRESHOLD_MS) {
|
|
140
|
+
// Session crashed before reaching stability — record as failure
|
|
141
|
+
if (s.lastFailureAt < s.lastSessionStartedAt) {
|
|
142
|
+
// Only record once per start (guard against multiple environment.changed events)
|
|
143
|
+
recordFailure(s);
|
|
144
|
+
logger.info({ survivedMs: sinceLastStart, failures: s.failures }, "Root task session crashed before stability threshold — recording failure");
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
// Session survived past stability threshold but is now stopped — reset backoff
|
|
149
|
+
resetBackoff(s, sinceLastStart);
|
|
150
|
+
}
|
|
151
|
+
s.lastSessionStartedAt = 0;
|
|
152
|
+
}
|
|
153
|
+
// 3. Find connected environment
|
|
154
|
+
const connectedEnv = deps.findFirstConnectedEnvironment();
|
|
155
|
+
if (!connectedEnv) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
// 4. Check backoff
|
|
159
|
+
if (s.failures >= BOOT_MAX_FAILURES) {
|
|
160
|
+
// Log only once when the threshold is first reached to avoid spam
|
|
161
|
+
if (s.failures === BOOT_MAX_FAILURES) {
|
|
162
|
+
logger.error({ failures: s.failures }, "Root task boot exhausted all retries (%d failures) — giving up until server restart", s.failures);
|
|
163
|
+
}
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (s.failures > 0) {
|
|
167
|
+
const delay = Math.min(BOOT_INITIAL_DELAY_MS * Math.pow(BOOT_BACKOFF_MULTIPLIER, s.failures - 1), BOOT_MAX_DELAY_MS);
|
|
168
|
+
const elapsed = Date.now() - s.lastFailureAt;
|
|
169
|
+
if (elapsed < delay) {
|
|
170
|
+
return; // backoff not elapsed yet
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// 5. Reanimate-first: try to resume the latest session
|
|
174
|
+
let booted = false;
|
|
175
|
+
const latestSession = deps.getLatestSessionForTask(ROOT_TASK_ID);
|
|
176
|
+
if (latestSession?.runtimeSessionId) {
|
|
177
|
+
try {
|
|
178
|
+
deps.reanimateAgent(latestSession.id);
|
|
179
|
+
booted = true;
|
|
180
|
+
logger.info({ sessionId: latestSession.id, environmentId: latestSession.environmentId }, "Root task reanimated existing session");
|
|
181
|
+
}
|
|
182
|
+
catch (reanimateErr) {
|
|
183
|
+
logger.info({ sessionId: latestSession.id, err: reanimateErr }, "Root task reanimate failed — falling back to fresh spawn");
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// 6. Fresh spawn (fallback)
|
|
187
|
+
if (!booted) {
|
|
188
|
+
const err = await deps.startTaskSession(rootTask, {
|
|
189
|
+
environmentId: connectedEnv.id,
|
|
190
|
+
notes: ROOT_TASK_INITIAL_PROMPT,
|
|
191
|
+
});
|
|
192
|
+
if (err) {
|
|
193
|
+
recordFailure(s);
|
|
194
|
+
logger.warn({ err }, "Root task auto-start failed");
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
logger.info({ environmentId: connectedEnv.id }, "Root task auto-started (fresh spawn)");
|
|
198
|
+
}
|
|
199
|
+
// 7. Track session start time for stability detection
|
|
200
|
+
s.lastSessionStartedAt = Date.now(); // eslint-disable-line require-atomic-updates -- single-threaded
|
|
201
|
+
}
|
|
202
|
+
/** Record a boot failure: increment counter and timestamp. */
|
|
203
|
+
function recordFailure(s) {
|
|
204
|
+
s.failures++;
|
|
205
|
+
s.lastFailureAt = Date.now();
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* If the root task has been WORKING long enough (past the stability threshold),
|
|
209
|
+
* reset the backoff counter. Called when we detect the task is already running.
|
|
210
|
+
*/
|
|
211
|
+
function checkStabilityReset(s) {
|
|
212
|
+
if (s.failures === 0) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (s.lastSessionStartedAt > 0) {
|
|
216
|
+
const elapsed = Date.now() - s.lastSessionStartedAt;
|
|
217
|
+
if (elapsed >= BOOT_STABLE_THRESHOLD_MS) {
|
|
218
|
+
resetBackoff(s, elapsed);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
// Task is WORKING but we didn't start it (e.g., session recovery
|
|
223
|
+
// reanimated it externally). Begin tracking stability from now so
|
|
224
|
+
// backoff can eventually reset — otherwise MAX_FAILURES is permanent.
|
|
225
|
+
s.lastSessionStartedAt = Date.now();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/** Zero out the backoff state after a session has proven stable. */
|
|
229
|
+
function resetBackoff(s, survivedMs) {
|
|
230
|
+
logger.info({ survivedMs, previousFailures: s.failures }, "Root task session stable — resetting backoff");
|
|
231
|
+
s.failures = 0;
|
|
232
|
+
s.lastFailureAt = 0;
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=root-task-boot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-task-boot.js","sourceRoot":"","sources":["../src/root-task-boot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schedule expression parsing and next-run-time computation.
|
|
3
|
+
*
|
|
4
|
+
* Supports two formats:
|
|
5
|
+
* - **Interval shorthand**: `"<number><unit>"` where unit is s/m/h/d (min 10s)
|
|
6
|
+
* - **Cron expressions**: Standard 5-field cron syntax via `cron-parser`
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Parse an interval shorthand expression to milliseconds.
|
|
10
|
+
*
|
|
11
|
+
* @param expr - e.g. "30s", "5m", "1h", "1d"
|
|
12
|
+
* @returns Duration in milliseconds
|
|
13
|
+
* @throws If the expression is invalid or below the minimum (10s)
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseDuration(expr: string): number;
|
|
16
|
+
/**
|
|
17
|
+
* Detect whether an expression is interval shorthand (vs. cron).
|
|
18
|
+
*
|
|
19
|
+
* @param expr - Schedule expression string
|
|
20
|
+
* @returns true if the expression matches interval shorthand format
|
|
21
|
+
*/
|
|
22
|
+
export declare function isIntervalExpression(expr: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Compute the next run time for a schedule expression.
|
|
25
|
+
*
|
|
26
|
+
* For intervals: if `lastRunAt + interval` is in the future, use that (prevents
|
|
27
|
+
* drift). Otherwise use `now + interval` (prevents burst-firing after downtime).
|
|
28
|
+
*
|
|
29
|
+
* For cron: next occurrence after now.
|
|
30
|
+
*
|
|
31
|
+
* @param expr - Schedule expression (interval or cron)
|
|
32
|
+
* @param lastRunAt - ISO timestamp of the last fire (undefined for first fire)
|
|
33
|
+
* @returns ISO timestamp of the next fire
|
|
34
|
+
*/
|
|
35
|
+
export declare function computeNextRunAt(expr: string, lastRunAt?: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Validate a schedule expression. Throws if invalid.
|
|
38
|
+
*
|
|
39
|
+
* @param expr - Schedule expression to validate
|
|
40
|
+
* @throws If the expression is neither valid interval shorthand nor valid cron
|
|
41
|
+
*/
|
|
42
|
+
export declare function validateExpression(expr: string): void;
|
|
43
|
+
//# sourceMappingURL=schedule-expression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-expression.d.ts","sourceRoot":"","sources":["../src/schedule-expression.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAcH;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmBlD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAwBzE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAmBrD"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schedule expression parsing and next-run-time computation.
|
|
3
|
+
*
|
|
4
|
+
* Supports two formats:
|
|
5
|
+
* - **Interval shorthand**: `"<number><unit>"` where unit is s/m/h/d (min 10s)
|
|
6
|
+
* - **Cron expressions**: Standard 5-field cron syntax via `cron-parser`
|
|
7
|
+
*/
|
|
8
|
+
import cronParser from "cron-parser";
|
|
9
|
+
const INTERVAL_RE = /^(\d+)([smhd])$/;
|
|
10
|
+
const MINIMUM_INTERVAL_MS = 10_000; // 10 seconds
|
|
11
|
+
const UNIT_TO_MS = {
|
|
12
|
+
s: 1_000,
|
|
13
|
+
m: 60_000,
|
|
14
|
+
h: 3_600_000,
|
|
15
|
+
d: 86_400_000,
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Parse an interval shorthand expression to milliseconds.
|
|
19
|
+
*
|
|
20
|
+
* @param expr - e.g. "30s", "5m", "1h", "1d"
|
|
21
|
+
* @returns Duration in milliseconds
|
|
22
|
+
* @throws If the expression is invalid or below the minimum (10s)
|
|
23
|
+
*/
|
|
24
|
+
export function parseDuration(expr) {
|
|
25
|
+
const match = INTERVAL_RE.exec(expr);
|
|
26
|
+
if (!match) {
|
|
27
|
+
throw new Error(`Invalid interval expression: "${expr}". Expected format: <number><s|m|h|d> (e.g. "30s", "5m")`);
|
|
28
|
+
}
|
|
29
|
+
const value = parseInt(match[1], 10);
|
|
30
|
+
const unit = match[2];
|
|
31
|
+
const ms = value * UNIT_TO_MS[unit];
|
|
32
|
+
if (ms <= 0) {
|
|
33
|
+
throw new Error(`Interval must be positive: "${expr}"`);
|
|
34
|
+
}
|
|
35
|
+
if (ms < MINIMUM_INTERVAL_MS) {
|
|
36
|
+
throw new Error(`Interval "${expr}" (${ms}ms) is below the minimum of ${MINIMUM_INTERVAL_MS}ms (10s)`);
|
|
37
|
+
}
|
|
38
|
+
return ms;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Detect whether an expression is interval shorthand (vs. cron).
|
|
42
|
+
*
|
|
43
|
+
* @param expr - Schedule expression string
|
|
44
|
+
* @returns true if the expression matches interval shorthand format
|
|
45
|
+
*/
|
|
46
|
+
export function isIntervalExpression(expr) {
|
|
47
|
+
return INTERVAL_RE.test(expr);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Compute the next run time for a schedule expression.
|
|
51
|
+
*
|
|
52
|
+
* For intervals: if `lastRunAt + interval` is in the future, use that (prevents
|
|
53
|
+
* drift). Otherwise use `now + interval` (prevents burst-firing after downtime).
|
|
54
|
+
*
|
|
55
|
+
* For cron: next occurrence after now.
|
|
56
|
+
*
|
|
57
|
+
* @param expr - Schedule expression (interval or cron)
|
|
58
|
+
* @param lastRunAt - ISO timestamp of the last fire (undefined for first fire)
|
|
59
|
+
* @returns ISO timestamp of the next fire
|
|
60
|
+
*/
|
|
61
|
+
export function computeNextRunAt(expr, lastRunAt) {
|
|
62
|
+
const now = Date.now();
|
|
63
|
+
if (isIntervalExpression(expr)) {
|
|
64
|
+
const intervalMs = parseDuration(expr);
|
|
65
|
+
const nowPlusInterval = now + intervalMs;
|
|
66
|
+
if (lastRunAt) {
|
|
67
|
+
const lastRunMs = new Date(lastRunAt).getTime();
|
|
68
|
+
const anchored = lastRunMs + intervalMs;
|
|
69
|
+
// Anchored: use lastRunAt + interval if it's in the future (prevents drift).
|
|
70
|
+
// If it's in the past (server was down), cap to now + interval (prevents burst).
|
|
71
|
+
if (anchored > now) {
|
|
72
|
+
return new Date(anchored).toISOString();
|
|
73
|
+
}
|
|
74
|
+
return new Date(nowPlusInterval).toISOString();
|
|
75
|
+
}
|
|
76
|
+
return new Date(nowPlusInterval).toISOString();
|
|
77
|
+
}
|
|
78
|
+
// Cron expression: compute next occurrence after now
|
|
79
|
+
const interval = cronParser.parseExpression(expr, { utc: true });
|
|
80
|
+
return interval.next().toISOString();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Validate a schedule expression. Throws if invalid.
|
|
84
|
+
*
|
|
85
|
+
* @param expr - Schedule expression to validate
|
|
86
|
+
* @throws If the expression is neither valid interval shorthand nor valid cron
|
|
87
|
+
*/
|
|
88
|
+
export function validateExpression(expr) {
|
|
89
|
+
if (!expr) {
|
|
90
|
+
throw new Error("Schedule expression cannot be empty");
|
|
91
|
+
}
|
|
92
|
+
if (isIntervalExpression(expr)) {
|
|
93
|
+
// parseDuration validates format and minimum
|
|
94
|
+
parseDuration(expr);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
// Try to parse as cron
|
|
98
|
+
try {
|
|
99
|
+
cronParser.parseExpression(expr, { utc: true });
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
throw new Error(`Invalid schedule expression: "${expr}". Must be interval shorthand (e.g. "30s", "5m") or 5-field cron (e.g. "0 9 * * MON")`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=schedule-expression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-expression.js","sourceRoot":"","sources":["../src/schedule-expression.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { grackle } from "@grackle-ai/common";
|
|
2
|
+
/** Create a new schedule. */
|
|
3
|
+
export declare function createSchedule(req: grackle.CreateScheduleRequest): Promise<grackle.Schedule>;
|
|
4
|
+
/** List all schedules, optionally filtered by workspace. */
|
|
5
|
+
export declare function listSchedules(req: grackle.ListSchedulesRequest): Promise<grackle.ScheduleList>;
|
|
6
|
+
/** Get a schedule by ID. */
|
|
7
|
+
export declare function getSchedule(req: grackle.ScheduleId): Promise<grackle.Schedule>;
|
|
8
|
+
/** Update an existing schedule. */
|
|
9
|
+
export declare function updateSchedule(req: grackle.UpdateScheduleRequest): Promise<grackle.Schedule>;
|
|
10
|
+
/** Delete a schedule by ID. */
|
|
11
|
+
export declare function deleteSchedule(req: grackle.ScheduleId): Promise<grackle.Empty>;
|
|
12
|
+
//# sourceMappingURL=schedule-handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-handlers.d.ts","sourceRoot":"","sources":["../src/schedule-handlers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAO7C,6BAA6B;AAC7B,wBAAsB,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CA2ClG;AAED,4DAA4D;AAC5D,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAKpG;AAED,4BAA4B;AAC5B,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAMpF;AAED,mCAAmC;AACnC,wBAAsB,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CA6DlG;AAED,+BAA+B;AAC/B,wBAAsB,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAIpF"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { ConnectError, Code } from "@connectrpc/connect";
|
|
2
|
+
import { create } from "@bufbuild/protobuf";
|
|
3
|
+
import { grackle } from "@grackle-ai/common";
|
|
4
|
+
import { personaStore, scheduleStore } from "@grackle-ai/database";
|
|
5
|
+
import { v4 as uuid } from "uuid";
|
|
6
|
+
import { validateExpression, computeNextRunAt } from "./schedule-expression.js";
|
|
7
|
+
import { emit } from "@grackle-ai/core";
|
|
8
|
+
import { scheduleRowToProto } from "./grpc-proto-converters.js";
|
|
9
|
+
/** Create a new schedule. */
|
|
10
|
+
export async function createSchedule(req) {
|
|
11
|
+
const title = req.title.trim();
|
|
12
|
+
const expr = req.scheduleExpression.trim();
|
|
13
|
+
const personaId = req.personaId.trim();
|
|
14
|
+
if (!title) {
|
|
15
|
+
throw new ConnectError("title is required", Code.InvalidArgument);
|
|
16
|
+
}
|
|
17
|
+
if (!expr) {
|
|
18
|
+
throw new ConnectError("schedule_expression is required", Code.InvalidArgument);
|
|
19
|
+
}
|
|
20
|
+
if (!personaId) {
|
|
21
|
+
throw new ConnectError("persona_id is required", Code.InvalidArgument);
|
|
22
|
+
}
|
|
23
|
+
// Validate persona exists
|
|
24
|
+
const persona = personaStore.getPersona(personaId);
|
|
25
|
+
if (!persona) {
|
|
26
|
+
throw new ConnectError(`Persona not found: ${personaId}`, Code.NotFound);
|
|
27
|
+
}
|
|
28
|
+
// Validate expression
|
|
29
|
+
try {
|
|
30
|
+
validateExpression(expr);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
throw new ConnectError(err instanceof Error ? err.message : "Invalid schedule expression", Code.InvalidArgument);
|
|
34
|
+
}
|
|
35
|
+
const id = uuid();
|
|
36
|
+
const nextRunAt = computeNextRunAt(expr);
|
|
37
|
+
scheduleStore.createSchedule(id, title, req.description, expr, personaId, req.environmentId, req.workspaceId, req.parentTaskId, nextRunAt);
|
|
38
|
+
emit("schedule.created", { scheduleId: id });
|
|
39
|
+
const row = scheduleStore.getSchedule(id);
|
|
40
|
+
return scheduleRowToProto(row);
|
|
41
|
+
}
|
|
42
|
+
/** List all schedules, optionally filtered by workspace. */
|
|
43
|
+
export async function listSchedules(req) {
|
|
44
|
+
const rows = scheduleStore.listSchedules(req.workspaceId || undefined);
|
|
45
|
+
return create(grackle.ScheduleListSchema, {
|
|
46
|
+
schedules: rows.map(scheduleRowToProto),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/** Get a schedule by ID. */
|
|
50
|
+
export async function getSchedule(req) {
|
|
51
|
+
const row = scheduleStore.getSchedule(req.id);
|
|
52
|
+
if (!row) {
|
|
53
|
+
throw new ConnectError(`Schedule not found: ${req.id}`, Code.NotFound);
|
|
54
|
+
}
|
|
55
|
+
return scheduleRowToProto(row);
|
|
56
|
+
}
|
|
57
|
+
/** Update an existing schedule. */
|
|
58
|
+
export async function updateSchedule(req) {
|
|
59
|
+
const existing = scheduleStore.getSchedule(req.id);
|
|
60
|
+
if (!existing) {
|
|
61
|
+
throw new ConnectError(`Schedule not found: ${req.id}`, Code.NotFound);
|
|
62
|
+
}
|
|
63
|
+
const update = {};
|
|
64
|
+
if (req.title !== undefined && req.title.trim() !== "") {
|
|
65
|
+
update.title = req.title.trim();
|
|
66
|
+
}
|
|
67
|
+
if (req.description !== undefined) {
|
|
68
|
+
update.description = req.description;
|
|
69
|
+
}
|
|
70
|
+
if (req.personaId !== undefined && req.personaId.trim() !== "") {
|
|
71
|
+
const trimmedPersonaId = req.personaId.trim();
|
|
72
|
+
const persona = personaStore.getPersona(trimmedPersonaId);
|
|
73
|
+
if (!persona) {
|
|
74
|
+
throw new ConnectError(`Persona not found: ${trimmedPersonaId}`, Code.NotFound);
|
|
75
|
+
}
|
|
76
|
+
update.personaId = trimmedPersonaId;
|
|
77
|
+
}
|
|
78
|
+
if (req.environmentId !== undefined) {
|
|
79
|
+
update.environmentId = req.environmentId;
|
|
80
|
+
}
|
|
81
|
+
// Handle schedule expression change
|
|
82
|
+
let expressionChanged = false;
|
|
83
|
+
if (req.scheduleExpression !== undefined && req.scheduleExpression !== "") {
|
|
84
|
+
const expr = req.scheduleExpression.trim();
|
|
85
|
+
try {
|
|
86
|
+
validateExpression(expr);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
throw new ConnectError(err instanceof Error ? err.message : "Invalid schedule expression", Code.InvalidArgument);
|
|
90
|
+
}
|
|
91
|
+
update.scheduleExpression = expr;
|
|
92
|
+
expressionChanged = true;
|
|
93
|
+
}
|
|
94
|
+
// Handle enable/disable
|
|
95
|
+
if (req.enabled !== undefined) {
|
|
96
|
+
update.enabled = req.enabled;
|
|
97
|
+
if (req.enabled) {
|
|
98
|
+
const expr = update.scheduleExpression ?? existing.scheduleExpression;
|
|
99
|
+
update.nextRunAt = computeNextRunAt(expr);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
update.nextRunAt = null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else if (expressionChanged) {
|
|
106
|
+
// Recompute nextRunAt when expression changes (if currently enabled)
|
|
107
|
+
if (existing.enabled) {
|
|
108
|
+
update.nextRunAt = computeNextRunAt(update.scheduleExpression);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
scheduleStore.updateSchedule(req.id, update);
|
|
112
|
+
emit("schedule.updated", { scheduleId: req.id });
|
|
113
|
+
const row = scheduleStore.getSchedule(req.id);
|
|
114
|
+
return scheduleRowToProto(row);
|
|
115
|
+
}
|
|
116
|
+
/** Delete a schedule by ID. */
|
|
117
|
+
export async function deleteSchedule(req) {
|
|
118
|
+
scheduleStore.deleteSchedule(req.id);
|
|
119
|
+
emit("schedule.deleted", { scheduleId: req.id });
|
|
120
|
+
return create(grackle.EmptySchema, {});
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=schedule-handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-handlers.js","sourceRoot":"","sources":["../src/schedule-handlers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { grackle } from "@grackle-ai/common";
|
|
2
|
+
/** Spawn a new agent session in the given environment. */
|
|
3
|
+
export declare function spawnAgent(req: grackle.SpawnRequest): Promise<grackle.Session>;
|
|
4
|
+
/** Resume a previously suspended agent session. */
|
|
5
|
+
export declare function resumeAgent(req: grackle.ResumeRequest): Promise<grackle.Session>;
|
|
6
|
+
/** Send text input to a running session. */
|
|
7
|
+
export declare function sendInput(req: grackle.InputMessage): Promise<grackle.Empty>;
|
|
8
|
+
/** Kill (or gracefully stop) an agent session. */
|
|
9
|
+
export declare function killAgent(req: grackle.KillAgentRequest): Promise<grackle.Empty>;
|
|
10
|
+
/** Get aggregated usage stats for a session, task, task tree, workspace, or environment. */
|
|
11
|
+
export declare function getUsage(req: grackle.GetUsageRequest): Promise<grackle.UsageStats>;
|
|
12
|
+
/** Wait for a message on a synchronous pipe subscription. */
|
|
13
|
+
export declare function waitForPipe(req: grackle.WaitForPipeRequest): Promise<grackle.WaitForPipeResponse>;
|
|
14
|
+
/** Write a message to a pipe fd. */
|
|
15
|
+
export declare function writeToFd(req: grackle.WriteToFdRequest): Promise<grackle.Empty>;
|
|
16
|
+
/** Close a pipe file descriptor, optionally stopping child sessions. */
|
|
17
|
+
export declare function closeFd(req: grackle.CloseFdRequest): Promise<grackle.CloseFdResponse>;
|
|
18
|
+
/** Get all open file descriptors for a session. */
|
|
19
|
+
export declare function getSessionFds(req: grackle.SessionId): grackle.SessionFds;
|
|
20
|
+
/** Create a new named stream. Creator gets an rw/async subscription. */
|
|
21
|
+
export declare function createStream(req: grackle.CreateStreamRequest): Promise<grackle.CreateStreamResponse>;
|
|
22
|
+
/** Attach another session to a stream the caller holds an fd on. */
|
|
23
|
+
export declare function attachStream(req: grackle.AttachStreamRequest): Promise<grackle.AttachStreamResponse>;
|
|
24
|
+
/** List all active IPC streams with subscriber details and message buffer depth. */
|
|
25
|
+
export declare function listStreams(): Promise<grackle.ListStreamsResponse>;
|
|
26
|
+
/** List sessions with optional filters. */
|
|
27
|
+
export declare function listSessions(req: grackle.SessionFilter): Promise<grackle.SessionList>;
|
|
28
|
+
/** Get a session by ID. */
|
|
29
|
+
export declare function getSession(req: grackle.SessionId): Promise<grackle.Session>;
|
|
30
|
+
/** Get all events recorded for a session. */
|
|
31
|
+
export declare function getSessionEvents(req: grackle.SessionId): Promise<grackle.SessionEventList>;
|
|
32
|
+
/** Get all sessions for a task. */
|
|
33
|
+
export declare function getTaskSessions(req: grackle.TaskId): Promise<grackle.SessionList>;
|
|
34
|
+
/** Stream session events as they occur. */
|
|
35
|
+
export declare function streamSession(req: grackle.SessionId): AsyncGenerator<grackle.SessionEvent>;
|
|
36
|
+
/** Stream all session events across all sessions. */
|
|
37
|
+
export declare function streamAll(): AsyncGenerator<grackle.SessionEvent>;
|
|
38
|
+
/** Stream domain events (replaces WebSocket event broadcasting). */
|
|
39
|
+
export declare function streamEvents(): AsyncGenerator<grackle.ServerEvent>;
|
|
40
|
+
//# sourceMappingURL=session-handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-handlers.d.ts","sourceRoot":"","sources":["../src/session-handlers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAa,MAAM,oBAAoB,CAAC;AAuCxD,0DAA0D;AAC1D,wBAAsB,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAkMpF;AAED,mDAAmD;AACnD,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAItF;AAED,4CAA4C;AAC5C,wBAAsB,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAoCjF;AAED,kDAAkD;AAClD,wBAAsB,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAoCrF;AAED,4FAA4F;AAC5F,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CA0CxF;AAED,6DAA6D;AAC7D,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAsCvG;AAED,oCAAoC;AACpC,wBAAsB,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAyCrF;AAED,wEAAwE;AACxE,wBAAsB,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAwD3F;AAED,mDAAmD;AACnD,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,UAAU,CAuBxE;AA6CD,wEAAwE;AACxE,wBAAsB,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,CA4B1G;AAED,oEAAoE;AACpE,wBAAsB,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,CA2C1G;AAED,oFAAoF;AACpF,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAuBxE;AAED,2CAA2C;AAC3C,wBAAsB,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAK3F;AAED,2BAA2B;AAC3B,wBAAsB,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAMjF;AAED,6CAA6C;AAC7C,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAwBhG;AAED,mCAAmC;AACnC,wBAAsB,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAQvF;AAED,2CAA2C;AAC3C,wBAAuB,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,GAAG,cAAc,CAAC,OAAO,CAAC,YAAY,CAAC,CASjG;AAED,qDAAqD;AACrD,wBAAuB,SAAS,IAAI,cAAc,CAAC,OAAO,CAAC,YAAY,CAAC,CASvE;AAED,oEAAoE;AACpE,wBAAuB,YAAY,IAAI,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC,CAiBzE"}
|