@grackle-ai/core 0.79.0 → 0.79.1

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.
@@ -1,13 +1,14 @@
1
1
  /**
2
- * CronManager periodic ticker that fires due schedules.
2
+ * Cron reconciliation phase fires due schedules on each tick.
3
3
  *
4
- * Runs as a background interval on the server, checking the schedule store
5
- * for due entries on each tick and spawning tasks for them.
4
+ * Extracted from the former CronManager so it can plug into the
5
+ * ReconciliationManager as one of several ordered phases.
6
6
  */
7
7
  import type { ScheduleRow, EnvironmentRow, TaskRow } from "@grackle-ai/database";
8
8
  import type { GrackleEventType } from "./event-bus.js";
9
- /** Dependencies injected into CronManager for testability (NFR-4). */
10
- export interface CronManagerDeps {
9
+ import type { ReconciliationPhase } from "./reconciliation-manager.js";
10
+ /** Dependencies injected into the cron phase for testability. */
11
+ export interface CronPhaseDeps {
11
12
  /** Query the schedule store for due entries. */
12
13
  getDueSchedules: () => ScheduleRow[];
13
14
  /** Advance a schedule after firing (update lastRunAt, nextRunAt, runCount). */
@@ -40,28 +41,10 @@ export interface CronManagerDeps {
40
41
  isEnvironmentConnected: (environmentId: string) => boolean;
41
42
  }
42
43
  /**
43
- * Periodic cron manager that checks for due schedules and fires them.
44
+ * Create a ReconciliationPhase that fires due schedules.
45
+ *
46
+ * @param deps - Injected dependencies
47
+ * @returns A phase to register with ReconciliationManager
44
48
  */
45
- export declare class CronManager {
46
- private readonly deps;
47
- private readonly checkIntervalMs;
48
- private timer;
49
- private ticking;
50
- private tickPromise;
51
- /**
52
- * @param deps - Injected dependencies
53
- * @param checkIntervalMs - How often to check for due schedules (default 10s)
54
- */
55
- constructor(deps: CronManagerDeps, checkIntervalMs?: number);
56
- /** Start the periodic ticker. */
57
- start(): void;
58
- /** Stop the ticker and await any in-flight tick. */
59
- stop(): Promise<void>;
60
- /** Attempt a tick, skipping if a previous tick is still in-flight. */
61
- private tryTick;
62
- /** Execute one tick: query due schedules and fire each. */
63
- private tick;
64
- /** Fire a single schedule: create task, start session, advance. */
65
- private fireSchedule;
66
- }
67
- //# sourceMappingURL=cron-manager.d.ts.map
49
+ export declare function createCronPhase(deps: CronPhaseDeps): ReconciliationPhase;
50
+ //# sourceMappingURL=cron-phase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron-phase.d.ts","sourceRoot":"","sources":["../src/cron-phase.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAGvE,iEAAiE;AACjE,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,eAAe,EAAE,MAAM,WAAW,EAAE,CAAC;IACrC,+EAA+E;IAC/E,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5E,2CAA2C;IAC3C,UAAU,EAAE,CACV,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,aAAa,EAAE,MAAM,EACrB,YAAY,CAAC,EAAE,MAAM,EACrB,YAAY,CAAC,EAAE,OAAO,EACtB,gBAAgB,CAAC,EAAE,MAAM,KACtB,IAAI,CAAC;IACV,wCAAwC;IACxC,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,yEAAyE;IACzE,gBAAgB,EAAE,CAChB,EAAE,EAAE,SAAS,EACb,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KACrE,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACjC,2BAA2B;IAC3B,IAAI,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACzE,4DAA4D;IAC5D,6BAA6B,EAAE,MAAM,cAAc,GAAG,SAAS,CAAC;IAChE,+BAA+B;IAC/B,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACtF,0DAA0D;IAC1D,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,GAAG,SAAS,CAAC;IAC7C,mEAAmE;IAEnE,kBAAkB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACrF,4CAA4C;IAC5C,sBAAsB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC;CAC5D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,mBAAmB,CAcxE"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Cron reconciliation phase — fires due schedules on each tick.
3
+ *
4
+ * Extracted from the former CronManager so it can plug into the
5
+ * ReconciliationManager as one of several ordered phases.
6
+ */
7
+ import { v4 as uuidv4 } from "uuid";
8
+ import { logger } from "./logger.js";
9
+ import { computeNextRunAt } from "./schedule-expression.js";
10
+ import { ROOT_TASK_ID } from "@grackle-ai/common";
11
+ /**
12
+ * Create a ReconciliationPhase that fires due schedules.
13
+ *
14
+ * @param deps - Injected dependencies
15
+ * @returns A phase to register with ReconciliationManager
16
+ */
17
+ export function createCronPhase(deps) {
18
+ return {
19
+ name: "cron",
20
+ execute: async () => {
21
+ const due = deps.getDueSchedules();
22
+ if (due.length === 0) {
23
+ return;
24
+ }
25
+ logger.debug({ count: due.length }, "Cron phase: due schedules");
26
+ for (const schedule of due) {
27
+ await fireSchedule(deps, schedule);
28
+ }
29
+ },
30
+ };
31
+ }
32
+ /** Fire a single schedule: create task, start session, advance. */
33
+ async function fireSchedule(deps, schedule) {
34
+ const now = new Date().toISOString();
35
+ let nextRunAt;
36
+ try {
37
+ // Anchor to the schedule's lastRunAt (not current time) to prevent drift
38
+ nextRunAt = computeNextRunAt(schedule.scheduleExpression, schedule.lastRunAt ?? undefined);
39
+ }
40
+ catch (err) {
41
+ logger.error({ scheduleId: schedule.id, scheduleExpression: schedule.scheduleExpression, err }, "Cron phase: failed to compute nextRunAt; disabling schedule");
42
+ // Disable the schedule to prevent error loop on every tick
43
+ deps.setScheduleEnabled(schedule.id, false, null);
44
+ return;
45
+ }
46
+ try {
47
+ // Resolve environment — check connectivity before creating tasks to avoid orphan tasks
48
+ let environmentId;
49
+ if (schedule.environmentId) {
50
+ // Explicit environment: verify it's connected before creating a task
51
+ if (!deps.isEnvironmentConnected(schedule.environmentId)) {
52
+ logger.warn({ scheduleId: schedule.id, environmentId: schedule.environmentId }, "Schedule fire skipped: specified environment not connected");
53
+ deps.advanceSchedule(schedule.id, now, nextRunAt);
54
+ return;
55
+ }
56
+ environmentId = schedule.environmentId;
57
+ }
58
+ else {
59
+ // Auto-select first connected environment
60
+ const env = deps.findFirstConnectedEnvironment();
61
+ if (!env) {
62
+ logger.warn({ scheduleId: schedule.id }, "Schedule fire skipped: no connected environment");
63
+ deps.advanceSchedule(schedule.id, now, nextRunAt);
64
+ return;
65
+ }
66
+ environmentId = env.id;
67
+ }
68
+ // Validate persona exists
69
+ const persona = deps.getPersona(schedule.personaId);
70
+ if (!persona) {
71
+ logger.warn({ scheduleId: schedule.id, personaId: schedule.personaId }, "Schedule fire skipped: persona not found");
72
+ deps.advanceSchedule(schedule.id, now, nextRunAt);
73
+ return;
74
+ }
75
+ // Create task
76
+ const taskId = uuidv4();
77
+ const taskTitle = `${schedule.title} @ ${now}`;
78
+ const parentTaskId = schedule.parentTaskId || ROOT_TASK_ID;
79
+ deps.createTask(taskId, schedule.workspaceId || undefined, taskTitle, schedule.description, [], // no dependencies
80
+ "", // no workspace slug
81
+ parentTaskId, false, // canDecompose
82
+ schedule.personaId);
83
+ deps.setTaskScheduleId(taskId, schedule.id);
84
+ // Fetch the created task for startTaskSession
85
+ const task = deps.getTask(taskId);
86
+ if (!task) {
87
+ logger.error({ scheduleId: schedule.id, taskId }, "Schedule fire failed: created task not found");
88
+ deps.advanceSchedule(schedule.id, now, nextRunAt);
89
+ return;
90
+ }
91
+ // Start the task session
92
+ const error = await deps.startTaskSession(undefined, task, {
93
+ environmentId,
94
+ personaId: schedule.personaId,
95
+ });
96
+ // Advance schedule regardless of session start outcome
97
+ deps.advanceSchedule(schedule.id, now, nextRunAt);
98
+ if (error) {
99
+ logger.warn({ scheduleId: schedule.id, taskId, error }, "Schedule fire: task created but session start failed");
100
+ return;
101
+ }
102
+ // Emit event only on successful fire
103
+ deps.emit("schedule.fired", {
104
+ scheduleId: schedule.id,
105
+ taskId,
106
+ firedAt: now,
107
+ });
108
+ logger.info({ scheduleId: schedule.id, taskId, title: schedule.title }, "Schedule fired");
109
+ }
110
+ catch (err) {
111
+ logger.error({ scheduleId: schedule.id, err }, "Schedule fire failed with exception");
112
+ // Still advance to prevent retry storms
113
+ deps.advanceSchedule(schedule.id, now, nextRunAt);
114
+ }
115
+ }
116
+ //# sourceMappingURL=cron-phase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron-phase.js","sourceRoot":"","sources":["../src/cron-phase.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  * Find the first connected environment, preferring local adapters.
3
3
  *
4
4
  * Extracted from the root task boot listener in server/src/index.ts
5
- * so that CronManager and other server-internal code can reuse the logic.
5
+ * so that the cron phase and other server-internal code can reuse the logic.
6
6
  */
7
7
  import { type EnvironmentRow } from "@grackle-ai/database";
8
8
  /**
@@ -2,7 +2,7 @@
2
2
  * Find the first connected environment, preferring local adapters.
3
3
  *
4
4
  * Extracted from the root task boot listener in server/src/index.ts
5
- * so that CronManager and other server-internal code can reuse the logic.
5
+ * so that the cron phase and other server-internal code can reuse the logic.
6
6
  */
7
7
  import { envRegistry } from "@grackle-ai/database";
8
8
  /**
package/dist/index.d.ts CHANGED
@@ -10,8 +10,10 @@ export { attemptReconnects, resetReconnectState } from "./auto-reconnect.js";
10
10
  export { pushToEnv } from "./token-push.js";
11
11
  export { computeTaskStatus } from "./compute-task-status.js";
12
12
  export { isKnowledgeEnabled, initKnowledge } from "./knowledge-init.js";
13
- export { CronManager } from "./cron-manager.js";
14
- export type { CronManagerDeps } from "./cron-manager.js";
13
+ export { ReconciliationManager } from "./reconciliation-manager.js";
14
+ export type { ReconciliationPhase } from "./reconciliation-manager.js";
15
+ export { createCronPhase } from "./cron-phase.js";
16
+ export type { CronPhaseDeps } from "./cron-phase.js";
15
17
  export { findFirstConnectedEnvironment } from "./find-connected-environment.js";
16
18
  export { validateExpression, computeNextRunAt } from "./schedule-expression.js";
17
19
  export { checkVersionStatus, clearVersionCache, type VersionStatus } from "./version-check.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,EACL,eAAe,EAAE,UAAU,EAC3B,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAC/D,cAAc,EAAE,aAAa,GAC9B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAGzD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGxE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGhF,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAG/F,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,EACL,eAAe,EAAE,UAAU,EAC3B,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAC/D,cAAc,EAAE,aAAa,GAC9B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAGzD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,YAAY,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGhF,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAG/F,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -17,8 +17,9 @@ export { pushToEnv } from "./token-push.js";
17
17
  export { computeTaskStatus } from "./compute-task-status.js";
18
18
  // ─── Knowledge ─────────────────────────────────────────────
19
19
  export { isKnowledgeEnabled, initKnowledge } from "./knowledge-init.js";
20
- // ─── Cron / Scheduling ────────────────────────────────────
21
- export { CronManager } from "./cron-manager.js";
20
+ // ─── Reconciliation / Scheduling ──────────────────────────
21
+ export { ReconciliationManager } from "./reconciliation-manager.js";
22
+ export { createCronPhase } from "./cron-phase.js";
22
23
  export { findFirstConnectedEnvironment } from "./find-connected-environment.js";
23
24
  export { validateExpression, computeNextRunAt } from "./schedule-expression.js";
24
25
  // ─── Version Check ────────────────────────────────────────
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,8DAA8D;AAC9D,OAAO,EACL,eAAe,EAAE,UAAU,EAC3B,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAC/D,cAAc,EAAE,aAAa,GAC9B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,8DAA8D;AAC9D,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEjD,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtD,8DAA8D;AAC9D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElE,8DAA8D;AAC9D,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,8DAA8D;AAC9D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAExE,6DAA6D;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEhF,6DAA6D;AAC7D,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAsB,MAAM,oBAAoB,CAAC;AAE/F,8DAA8D;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,8DAA8D;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,8DAA8D;AAC9D,OAAO,EACL,eAAe,EAAE,UAAU,EAC3B,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAC/D,cAAc,EAAE,aAAa,GAC9B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,8DAA8D;AAC9D,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEjD,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtD,8DAA8D;AAC9D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElE,8DAA8D;AAC9D,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,8DAA8D;AAC9D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAExE,6DAA6D;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEhF,6DAA6D;AAC7D,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAsB,MAAM,oBAAoB,CAAC;AAE/F,8DAA8D;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,8DAA8D;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * ReconciliationManager — periodic ticker that runs ordered phases on each tick.
3
+ *
4
+ * Generalized from CronManager to support pluggable phases (cron, dispatch,
5
+ * stall detection, etc.) in a single background loop.
6
+ */
7
+ /** A named async phase that runs during each reconciliation tick. */
8
+ export interface ReconciliationPhase {
9
+ /** Short name for logging (e.g. "cron", "dispatch"). */
10
+ name: string;
11
+ /** Execute the phase. Errors are caught by the manager — they don't abort the tick. */
12
+ execute: () => Promise<void>;
13
+ }
14
+ /**
15
+ * Periodic reconciliation manager that runs ordered phases on a configurable interval.
16
+ */
17
+ export declare class ReconciliationManager {
18
+ private readonly phases;
19
+ private readonly tickIntervalMs;
20
+ private timer;
21
+ private ticking;
22
+ private tickPromise;
23
+ /**
24
+ * @param phases - Ordered list of phases to run on each tick
25
+ * @param tickIntervalMs - Override tick interval (default: GRACKLE_RECONCILIATION_TICK_MS env var or 10s)
26
+ */
27
+ constructor(phases: ReconciliationPhase[], tickIntervalMs?: number);
28
+ /** Start the periodic ticker. */
29
+ start(): void;
30
+ /** Stop the ticker and await any in-flight tick. */
31
+ stop(): Promise<void>;
32
+ /** Attempt a tick, skipping if a previous tick is still in-flight. */
33
+ private tryTick;
34
+ /** Execute one tick: run each phase sequentially, isolating errors. */
35
+ private tick;
36
+ }
37
+ //# sourceMappingURL=reconciliation-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconciliation-manager.d.ts","sourceRoot":"","sources":["../src/reconciliation-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,qEAAqE;AACrE,MAAM,WAAW,mBAAmB;IAClC,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;GAEG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,KAAK,CAA6C;IAC1D,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,WAAW,CAA4B;IAE/C;;;OAGG;gBACgB,MAAM,EAAE,mBAAmB,EAAE,EAAE,cAAc,CAAC,EAAE,MAAM;IAwBzE,iCAAiC;IAC1B,KAAK,IAAI,IAAI;IAepB,oDAAoD;IACvC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAWlC,sEAAsE;YACxD,OAAO;IAgBrB,uEAAuE;YACzD,IAAI;CASnB"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * ReconciliationManager — periodic ticker that runs ordered phases on each tick.
3
+ *
4
+ * Generalized from CronManager to support pluggable phases (cron, dispatch,
5
+ * stall detection, etc.) in a single background loop.
6
+ */
7
+ import { logger } from "./logger.js";
8
+ /** Default tick interval in milliseconds. */
9
+ const DEFAULT_TICK_INTERVAL_MS = 10_000;
10
+ /**
11
+ * Periodic reconciliation manager that runs ordered phases on a configurable interval.
12
+ */
13
+ export class ReconciliationManager {
14
+ phases;
15
+ tickIntervalMs;
16
+ timer;
17
+ ticking = false;
18
+ tickPromise;
19
+ /**
20
+ * @param phases - Ordered list of phases to run on each tick
21
+ * @param tickIntervalMs - Override tick interval (default: GRACKLE_RECONCILIATION_TICK_MS env var or 10s)
22
+ */
23
+ constructor(phases, tickIntervalMs) {
24
+ this.phases = phases;
25
+ if (tickIntervalMs !== undefined) {
26
+ this.tickIntervalMs = tickIntervalMs;
27
+ }
28
+ else {
29
+ const envRaw = process.env.GRACKLE_RECONCILIATION_TICK_MS;
30
+ if (envRaw !== undefined && envRaw !== "") {
31
+ const parsed = parseInt(envRaw, 10);
32
+ if (Number.isFinite(parsed) && parsed > 0) {
33
+ this.tickIntervalMs = parsed;
34
+ }
35
+ else {
36
+ logger.warn({ envValue: envRaw, default: DEFAULT_TICK_INTERVAL_MS }, "Invalid GRACKLE_RECONCILIATION_TICK_MS; falling back to default");
37
+ this.tickIntervalMs = DEFAULT_TICK_INTERVAL_MS;
38
+ }
39
+ }
40
+ else {
41
+ this.tickIntervalMs = DEFAULT_TICK_INTERVAL_MS;
42
+ }
43
+ }
44
+ }
45
+ /** Start the periodic ticker. */
46
+ start() {
47
+ if (this.timer) {
48
+ return;
49
+ }
50
+ logger.info({ intervalMs: this.tickIntervalMs, phases: this.phases.map((p) => p.name) }, "ReconciliationManager started");
51
+ this.timer = setInterval(() => {
52
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
53
+ this.tryTick();
54
+ }, this.tickIntervalMs);
55
+ this.timer.unref();
56
+ }
57
+ /** Stop the ticker and await any in-flight tick. */
58
+ async stop() {
59
+ if (this.timer) {
60
+ clearInterval(this.timer);
61
+ this.timer = undefined;
62
+ }
63
+ if (this.tickPromise) {
64
+ await this.tickPromise;
65
+ }
66
+ logger.info("ReconciliationManager stopped");
67
+ }
68
+ /** Attempt a tick, skipping if a previous tick is still in-flight. */
69
+ async tryTick() {
70
+ if (this.ticking) {
71
+ return;
72
+ }
73
+ this.ticking = true;
74
+ this.tickPromise = this.tick();
75
+ try {
76
+ await this.tickPromise;
77
+ }
78
+ catch (err) {
79
+ logger.error({ err }, "ReconciliationManager tick failed");
80
+ }
81
+ finally {
82
+ this.ticking = false;
83
+ this.tickPromise = undefined;
84
+ }
85
+ }
86
+ /** Execute one tick: run each phase sequentially, isolating errors. */
87
+ async tick() {
88
+ for (const phase of this.phases) {
89
+ try {
90
+ await phase.execute();
91
+ }
92
+ catch (err) {
93
+ logger.error({ err, phase: phase.name }, "Reconciliation phase '%s' failed", phase.name);
94
+ }
95
+ }
96
+ }
97
+ }
98
+ //# sourceMappingURL=reconciliation-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconciliation-manager.js","sourceRoot":"","sources":["../src/reconciliation-manager.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grackle-ai/core",
3
- "version": "0.79.0",
3
+ "version": "0.79.1",
4
4
  "description": "Core gRPC business logic for Grackle — RPC handlers, event system, streaming, session lifecycle",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -37,12 +37,12 @@
37
37
  "ulid": "^2.3.0",
38
38
  "uuid": "^11.0.0",
39
39
  "ws": "^8.0.0",
40
- "@grackle-ai/adapter-sdk": "0.79.0",
41
- "@grackle-ai/common": "0.79.0",
42
- "@grackle-ai/database": "0.79.0",
43
- "@grackle-ai/knowledge": "0.79.0",
44
- "@grackle-ai/auth": "0.79.0",
45
- "@grackle-ai/prompt": "0.79.0"
40
+ "@grackle-ai/adapter-sdk": "0.79.1",
41
+ "@grackle-ai/auth": "0.79.1",
42
+ "@grackle-ai/common": "0.79.1",
43
+ "@grackle-ai/knowledge": "0.79.1",
44
+ "@grackle-ai/database": "0.79.1",
45
+ "@grackle-ai/prompt": "0.79.1"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@rushstack/heft": "1.2.7",
@@ -1 +0,0 @@
1
- {"version":3,"file":"cron-manager.d.ts","sourceRoot":"","sources":["../src/cron-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAMvD,sEAAsE;AACtE,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,eAAe,EAAE,MAAM,WAAW,EAAE,CAAC;IACrC,+EAA+E;IAC/E,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5E,2CAA2C;IAC3C,UAAU,EAAE,CACV,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,aAAa,EAAE,MAAM,EACrB,YAAY,CAAC,EAAE,MAAM,EACrB,YAAY,CAAC,EAAE,OAAO,EACtB,gBAAgB,CAAC,EAAE,MAAM,KACtB,IAAI,CAAC;IACV,wCAAwC;IACxC,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,yEAAyE;IACzE,gBAAgB,EAAE,CAChB,EAAE,EAAE,SAAS,EACb,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KACrE,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACjC,2BAA2B;IAC3B,IAAI,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACzE,4DAA4D;IAC5D,6BAA6B,EAAE,MAAM,cAAc,GAAG,SAAS,CAAC;IAChE,+BAA+B;IAC/B,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACtF,0DAA0D;IAC1D,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,GAAG,SAAS,CAAC;IAC7C,mEAAmE;IAEnE,kBAAkB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACrF,4CAA4C;IAC5C,sBAAsB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC;CAC5D;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkB;IACvC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,KAAK,CAA6C;IAC1D,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,WAAW,CAA4B;IAE/C;;;OAGG;gBACgB,IAAI,EAAE,eAAe,EAAE,eAAe,CAAC,EAAE,MAAM;IAKlE,iCAAiC;IAC1B,KAAK,IAAI,IAAI;IAepB,oDAAoD;IACvC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAWlC,sEAAsE;YACxD,OAAO;IAgBrB,2DAA2D;YAC7C,IAAI;IAWlB,mEAAmE;YACrD,YAAY;CAyH3B"}
@@ -1,167 +0,0 @@
1
- /**
2
- * CronManager — periodic ticker that fires due schedules.
3
- *
4
- * Runs as a background interval on the server, checking the schedule store
5
- * for due entries on each tick and spawning tasks for them.
6
- */
7
- import { v4 as uuidv4 } from "uuid";
8
- import { logger } from "./logger.js";
9
- import { computeNextRunAt } from "./schedule-expression.js";
10
- import { ROOT_TASK_ID } from "@grackle-ai/common";
11
- /** Default tick interval in milliseconds. */
12
- const DEFAULT_CHECK_INTERVAL_MS = 10_000;
13
- /**
14
- * Periodic cron manager that checks for due schedules and fires them.
15
- */
16
- export class CronManager {
17
- deps;
18
- checkIntervalMs;
19
- timer;
20
- ticking = false;
21
- tickPromise;
22
- /**
23
- * @param deps - Injected dependencies
24
- * @param checkIntervalMs - How often to check for due schedules (default 10s)
25
- */
26
- constructor(deps, checkIntervalMs) {
27
- this.deps = deps;
28
- this.checkIntervalMs = checkIntervalMs ?? DEFAULT_CHECK_INTERVAL_MS;
29
- }
30
- /** Start the periodic ticker. */
31
- start() {
32
- if (this.timer) {
33
- return;
34
- }
35
- logger.info({ intervalMs: this.checkIntervalMs }, "CronManager started");
36
- this.timer = setInterval(() => {
37
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
38
- this.tryTick();
39
- }, this.checkIntervalMs);
40
- this.timer.unref();
41
- }
42
- /** Stop the ticker and await any in-flight tick. */
43
- async stop() {
44
- if (this.timer) {
45
- clearInterval(this.timer);
46
- this.timer = undefined;
47
- }
48
- if (this.tickPromise) {
49
- await this.tickPromise;
50
- }
51
- logger.info("CronManager stopped");
52
- }
53
- /** Attempt a tick, skipping if a previous tick is still in-flight. */
54
- async tryTick() {
55
- if (this.ticking) {
56
- return;
57
- }
58
- this.ticking = true;
59
- this.tickPromise = this.tick();
60
- try {
61
- await this.tickPromise;
62
- }
63
- catch (err) {
64
- logger.error({ err }, "CronManager tick failed");
65
- }
66
- finally {
67
- this.ticking = false;
68
- this.tickPromise = undefined;
69
- }
70
- }
71
- /** Execute one tick: query due schedules and fire each. */
72
- async tick() {
73
- const due = this.deps.getDueSchedules();
74
- if (due.length === 0) {
75
- return;
76
- }
77
- logger.debug({ count: due.length }, "CronManager tick: due schedules");
78
- for (const schedule of due) {
79
- await this.fireSchedule(schedule);
80
- }
81
- }
82
- /** Fire a single schedule: create task, start session, advance. */
83
- async fireSchedule(schedule) {
84
- const now = new Date().toISOString();
85
- let nextRunAt;
86
- try {
87
- // Anchor to the schedule's lastRunAt (not current time) to prevent drift
88
- nextRunAt = computeNextRunAt(schedule.scheduleExpression, schedule.lastRunAt ?? undefined);
89
- }
90
- catch (err) {
91
- logger.error({ scheduleId: schedule.id, scheduleExpression: schedule.scheduleExpression, err }, "CronManager: failed to compute nextRunAt; disabling schedule");
92
- // Disable the schedule to prevent error loop on every tick
93
- this.deps.setScheduleEnabled(schedule.id, false, null);
94
- return;
95
- }
96
- try {
97
- // Resolve environment — check connectivity before creating tasks to avoid orphan tasks
98
- let environmentId;
99
- if (schedule.environmentId) {
100
- // Explicit environment: verify it's connected before creating a task
101
- if (!this.deps.isEnvironmentConnected(schedule.environmentId)) {
102
- logger.warn({ scheduleId: schedule.id, environmentId: schedule.environmentId }, "Schedule fire skipped: specified environment not connected");
103
- this.deps.advanceSchedule(schedule.id, now, nextRunAt);
104
- return;
105
- }
106
- environmentId = schedule.environmentId;
107
- }
108
- else {
109
- // Auto-select first connected environment
110
- const env = this.deps.findFirstConnectedEnvironment();
111
- if (!env) {
112
- logger.warn({ scheduleId: schedule.id }, "Schedule fire skipped: no connected environment");
113
- this.deps.advanceSchedule(schedule.id, now, nextRunAt);
114
- return;
115
- }
116
- environmentId = env.id;
117
- }
118
- // Validate persona exists
119
- const persona = this.deps.getPersona(schedule.personaId);
120
- if (!persona) {
121
- logger.warn({ scheduleId: schedule.id, personaId: schedule.personaId }, "Schedule fire skipped: persona not found");
122
- this.deps.advanceSchedule(schedule.id, now, nextRunAt);
123
- return;
124
- }
125
- // Create task
126
- const taskId = uuidv4();
127
- const taskTitle = `${schedule.title} @ ${now}`;
128
- const parentTaskId = schedule.parentTaskId || ROOT_TASK_ID;
129
- this.deps.createTask(taskId, schedule.workspaceId || undefined, taskTitle, schedule.description, [], // no dependencies
130
- "", // no workspace slug
131
- parentTaskId, false, // canDecompose
132
- schedule.personaId);
133
- this.deps.setTaskScheduleId(taskId, schedule.id);
134
- // Fetch the created task for startTaskSession
135
- const task = this.deps.getTask(taskId);
136
- if (!task) {
137
- logger.error({ scheduleId: schedule.id, taskId }, "Schedule fire failed: created task not found");
138
- this.deps.advanceSchedule(schedule.id, now, nextRunAt);
139
- return;
140
- }
141
- // Start the task session
142
- const error = await this.deps.startTaskSession(undefined, task, {
143
- environmentId,
144
- personaId: schedule.personaId,
145
- });
146
- // Advance schedule regardless of session start outcome
147
- this.deps.advanceSchedule(schedule.id, now, nextRunAt);
148
- if (error) {
149
- logger.warn({ scheduleId: schedule.id, taskId, error }, "Schedule fire: task created but session start failed");
150
- return;
151
- }
152
- // Emit event only on successful fire
153
- this.deps.emit("schedule.fired", {
154
- scheduleId: schedule.id,
155
- taskId,
156
- firedAt: now,
157
- });
158
- logger.info({ scheduleId: schedule.id, taskId, title: schedule.title }, "Schedule fired");
159
- }
160
- catch (err) {
161
- logger.error({ scheduleId: schedule.id, err }, "Schedule fire failed with exception");
162
- // Still advance to prevent retry storms
163
- this.deps.advanceSchedule(schedule.id, now, nextRunAt);
164
- }
165
- }
166
- }
167
- //# sourceMappingURL=cron-manager.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cron-manager.js","sourceRoot":"","sources":["../src/cron-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG5D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,6CAA6C;AAC7C,MAAM,yBAAyB,GAAW,MAAM,CAAC;AA2CjD;;GAEG;AACH,MAAM,OAAO,WAAW;IACL,IAAI,CAAkB;IACtB,eAAe,CAAS;IACjC,KAAK,CAA6C;IAClD,OAAO,GAAY,KAAK,CAAC;IACzB,WAAW,CAA4B;IAE/C;;;OAGG;IACH,YAAmB,IAAqB,EAAE,eAAwB;QAChE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,eAAe,GAAG,eAAe,IAAI,yBAAyB,CAAC;IACtE,CAAC;IAED,iCAAiC;IAC1B,KAAK;QACV,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QACD,MAAM,CAAC,IAAI,CACT,EAAE,UAAU,EAAE,IAAI,CAAC,eAAe,EAAE,EACpC,qBAAqB,CACtB,CAAC;QACF,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;YAC5B,mEAAmE;YACnE,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,oDAAoD;IAC7C,KAAK,CAAC,IAAI;QACf,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACzB,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,MAAM,IAAI,CAAC,WAAW,CAAC;QACzB,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACrC,CAAC;IAED,sEAAsE;IAC9D,KAAK,CAAC,OAAO;QACnB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,WAAW,CAAC;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,yBAAyB,CAAC,CAAC;QACnD,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YACrB,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,2DAA2D;IACnD,KAAK,CAAC,IAAI;QAChB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;QACxC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,iCAAiC,CAAC,CAAC;QACvE,KAAK,MAAM,QAAQ,IAAI,GAAG,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,mEAAmE;IAC3D,KAAK,CAAC,YAAY,CAAC,QAAqB;QAC9C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAErC,IAAI,SAAiB,CAAC;QACtB,IAAI,CAAC;YACH,yEAAyE;YACzE,SAAS,GAAG,gBAAgB,CAAC,QAAQ,CAAC,kBAAkB,EAAE,QAAQ,CAAC,SAAS,IAAI,SAAS,CAAC,CAAC;QAC7F,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CACV,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,kBAAkB,EAAE,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE,EACjF,8DAA8D,CAC/D,CAAC;YACF,2DAA2D;YAC3D,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,uFAAuF;YACvF,IAAI,aAAiC,CAAC;YACtC,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;gBAC3B,qEAAqE;gBACrE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;oBAC9D,MAAM,CAAC,IAAI,CACT,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,aAAa,EAAE,QAAQ,CAAC,aAAa,EAAE,EAClE,4DAA4D,CAC7D,CAAC;oBACF,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;oBACvD,OAAO;gBACT,CAAC;gBACD,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC;YACzC,CAAC;iBAAM,CAAC;gBACN,0CAA0C;gBAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,6BAA6B,EAAE,CAAC;gBACtD,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,MAAM,CAAC,IAAI,CACT,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,EAC3B,iDAAiD,CAClD,CAAC;oBACF,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;oBACvD,OAAO;gBACT,CAAC;gBACD,aAAa,GAAG,GAAG,CAAC,EAAE,CAAC;YACzB,CAAC;YAED,0BAA0B;YAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YACzD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,CAAC,IAAI,CACT,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,EAC1D,0CAA0C,CAC3C,CAAC;gBACF,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;gBACvD,OAAO;YACT,CAAC;YAED,cAAc;YACd,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;YACxB,MAAM,SAAS,GAAG,GAAG,QAAQ,CAAC,KAAK,MAAM,GAAG,EAAE,CAAC;YAC/C,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY,IAAI,YAAY,CAAC;YAC3D,IAAI,CAAC,IAAI,CAAC,UAAU,CAClB,MAAM,EACN,QAAQ,CAAC,WAAW,IAAI,SAAS,EACjC,SAAS,EACT,QAAQ,CAAC,WAAW,EACpB,EAAE,EAAE,kBAAkB;YACtB,EAAE,EAAE,oBAAoB;YACxB,YAAY,EACZ,KAAK,EAAE,eAAe;YACtB,QAAQ,CAAC,SAAS,CACnB,CAAC;YACF,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YAEjD,8CAA8C;YAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACvC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,CAAC,KAAK,CACV,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,EACnC,8CAA8C,CAC/C,CAAC;gBACF,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;gBACvD,OAAO;YACT,CAAC;YAED,yBAAyB;YACzB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,EAAE;gBAC9D,aAAa;gBACb,SAAS,EAAE,QAAQ,CAAC,SAAS;aAC9B,CAAC,CAAC;YAEH,uDAAuD;YACvD,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;YAEvD,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,CAAC,IAAI,CACT,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAC1C,sDAAsD,CACvD,CAAC;gBACF,OAAO;YACT,CAAC;YAED,qCAAqC;YACrC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;gBAC/B,UAAU,EAAE,QAAQ,CAAC,EAAE;gBACvB,MAAM;gBACN,OAAO,EAAE,GAAG;aACb,CAAC,CAAC;YAEH,MAAM,CAAC,IAAI,CACT,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,EAC1D,gBAAgB,CACjB,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CACV,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,EAChC,qCAAqC,CACtC,CAAC;YACF,wCAAwC;YACxC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;CACF"}