@a5c-ai/babysitter-sdk 0.0.16
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/cli/main.d.ts +5 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +1343 -0
- package/dist/cli/nodeTaskRunner.d.ts +16 -0
- package/dist/cli/nodeTaskRunner.d.ts.map +1 -0
- package/dist/cli/nodeTaskRunner.js +46 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/runner/env.d.ts +58 -0
- package/dist/runner/env.d.ts.map +1 -0
- package/dist/runner/env.js +113 -0
- package/dist/runner/index.d.ts +3 -0
- package/dist/runner/index.d.ts.map +1 -0
- package/dist/runner/index.js +18 -0
- package/dist/runner/nodeRunner.d.ts +60 -0
- package/dist/runner/nodeRunner.d.ts.map +1 -0
- package/dist/runner/nodeRunner.js +354 -0
- package/dist/runtime/commitEffectResult.d.ts +3 -0
- package/dist/runtime/commitEffectResult.d.ts.map +1 -0
- package/dist/runtime/commitEffectResult.js +172 -0
- package/dist/runtime/constants.d.ts +2 -0
- package/dist/runtime/constants.d.ts.map +1 -0
- package/dist/runtime/constants.js +5 -0
- package/dist/runtime/createRun.d.ts +3 -0
- package/dist/runtime/createRun.d.ts.map +1 -0
- package/dist/runtime/createRun.js +81 -0
- package/dist/runtime/errorUtils.d.ts +10 -0
- package/dist/runtime/errorUtils.d.ts.map +1 -0
- package/dist/runtime/errorUtils.js +42 -0
- package/dist/runtime/exceptions.d.ts +45 -0
- package/dist/runtime/exceptions.d.ts.map +1 -0
- package/dist/runtime/exceptions.js +99 -0
- package/dist/runtime/index.d.ts +12 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +34 -0
- package/dist/runtime/instrumentation.d.ts +6 -0
- package/dist/runtime/instrumentation.d.ts.map +1 -0
- package/dist/runtime/instrumentation.js +14 -0
- package/dist/runtime/intrinsics/breakpoint.d.ts +4 -0
- package/dist/runtime/intrinsics/breakpoint.d.ts.map +1 -0
- package/dist/runtime/intrinsics/breakpoint.js +42 -0
- package/dist/runtime/intrinsics/index.d.ts +7 -0
- package/dist/runtime/intrinsics/index.d.ts.map +1 -0
- package/dist/runtime/intrinsics/index.js +15 -0
- package/dist/runtime/intrinsics/orchestratorTask.d.ts +4 -0
- package/dist/runtime/intrinsics/orchestratorTask.d.ts.map +1 -0
- package/dist/runtime/intrinsics/orchestratorTask.js +28 -0
- package/dist/runtime/intrinsics/parallel.d.ts +5 -0
- package/dist/runtime/intrinsics/parallel.d.ts.map +1 -0
- package/dist/runtime/intrinsics/parallel.js +45 -0
- package/dist/runtime/intrinsics/sleep.d.ts +4 -0
- package/dist/runtime/intrinsics/sleep.d.ts.map +1 -0
- package/dist/runtime/intrinsics/sleep.js +70 -0
- package/dist/runtime/intrinsics/task.d.ts +20 -0
- package/dist/runtime/intrinsics/task.d.ts.map +1 -0
- package/dist/runtime/intrinsics/task.js +237 -0
- package/dist/runtime/invocation/hashInvocationKey.d.ts +12 -0
- package/dist/runtime/invocation/hashInvocationKey.d.ts.map +1 -0
- package/dist/runtime/invocation/hashInvocationKey.js +12 -0
- package/dist/runtime/invocation/index.d.ts +3 -0
- package/dist/runtime/invocation/index.d.ts.map +1 -0
- package/dist/runtime/invocation/index.js +5 -0
- package/dist/runtime/orchestrateIteration.d.ts +3 -0
- package/dist/runtime/orchestrateIteration.d.ts.map +1 -0
- package/dist/runtime/orchestrateIteration.js +195 -0
- package/dist/runtime/processContext.d.ts +19 -0
- package/dist/runtime/processContext.d.ts.map +1 -0
- package/dist/runtime/processContext.js +55 -0
- package/dist/runtime/replay/createReplayEngine.d.ts +31 -0
- package/dist/runtime/replay/createReplayEngine.d.ts.map +1 -0
- package/dist/runtime/replay/createReplayEngine.js +82 -0
- package/dist/runtime/replay/effectIndex.d.ts +34 -0
- package/dist/runtime/replay/effectIndex.d.ts.map +1 -0
- package/dist/runtime/replay/effectIndex.js +241 -0
- package/dist/runtime/replay/index.d.ts +7 -0
- package/dist/runtime/replay/index.d.ts.map +1 -0
- package/dist/runtime/replay/index.js +19 -0
- package/dist/runtime/replay/replayCursor.d.ts +7 -0
- package/dist/runtime/replay/replayCursor.d.ts.map +1 -0
- package/dist/runtime/replay/replayCursor.js +22 -0
- package/dist/runtime/replay/stateCache.d.ts +48 -0
- package/dist/runtime/replay/stateCache.d.ts.map +1 -0
- package/dist/runtime/replay/stateCache.js +211 -0
- package/dist/runtime/types.d.ts +147 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +2 -0
- package/dist/storage/atomic.d.ts +2 -0
- package/dist/storage/atomic.d.ts.map +1 -0
- package/dist/storage/atomic.js +54 -0
- package/dist/storage/cleanup.d.ts +4 -0
- package/dist/storage/cleanup.d.ts.map +1 -0
- package/dist/storage/cleanup.js +96 -0
- package/dist/storage/clock.d.ts +6 -0
- package/dist/storage/clock.d.ts.map +1 -0
- package/dist/storage/clock.js +29 -0
- package/dist/storage/createRunDir.d.ts +6 -0
- package/dist/storage/createRunDir.d.ts.map +1 -0
- package/dist/storage/createRunDir.js +59 -0
- package/dist/storage/index.d.ts +9 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +28 -0
- package/dist/storage/journal.d.ts +4 -0
- package/dist/storage/journal.d.ts.map +1 -0
- package/dist/storage/journal.js +103 -0
- package/dist/storage/lock.d.ts +5 -0
- package/dist/storage/lock.d.ts.map +1 -0
- package/dist/storage/lock.js +41 -0
- package/dist/storage/paths.d.ts +19 -0
- package/dist/storage/paths.d.ts.map +1 -0
- package/dist/storage/paths.js +46 -0
- package/dist/storage/runFiles.d.ts +5 -0
- package/dist/storage/runFiles.d.ts.map +1 -0
- package/dist/storage/runFiles.js +39 -0
- package/dist/storage/snapshotState.d.ts +10 -0
- package/dist/storage/snapshotState.d.ts.map +1 -0
- package/dist/storage/snapshotState.js +15 -0
- package/dist/storage/storeTaskArtifacts.d.ts +6 -0
- package/dist/storage/storeTaskArtifacts.d.ts.map +1 -0
- package/dist/storage/storeTaskArtifacts.js +58 -0
- package/dist/storage/tasks.d.ts +17 -0
- package/dist/storage/tasks.d.ts.map +1 -0
- package/dist/storage/tasks.js +82 -0
- package/dist/storage/types.d.ts +112 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +2 -0
- package/dist/storage/ulids.d.ts +11 -0
- package/dist/storage/ulids.d.ts.map +1 -0
- package/dist/storage/ulids.js +25 -0
- package/dist/tasks/batching.d.ts +29 -0
- package/dist/tasks/batching.d.ts.map +1 -0
- package/dist/tasks/batching.js +66 -0
- package/dist/tasks/context.d.ts +11 -0
- package/dist/tasks/context.d.ts.map +1 -0
- package/dist/tasks/context.js +181 -0
- package/dist/tasks/defineTask.d.ts +9 -0
- package/dist/tasks/defineTask.d.ts.map +1 -0
- package/dist/tasks/defineTask.js +58 -0
- package/dist/tasks/index.d.ts +8 -0
- package/dist/tasks/index.d.ts.map +1 -0
- package/dist/tasks/index.js +23 -0
- package/dist/tasks/kinds/index.d.ts +7 -0
- package/dist/tasks/kinds/index.d.ts.map +1 -0
- package/dist/tasks/kinds/index.js +333 -0
- package/dist/tasks/registry.d.ts +53 -0
- package/dist/tasks/registry.d.ts.map +1 -0
- package/dist/tasks/registry.js +145 -0
- package/dist/tasks/serializer.d.ts +60 -0
- package/dist/tasks/serializer.d.ts.map +1 -0
- package/dist/tasks/serializer.js +193 -0
- package/dist/tasks/types.d.ts +148 -0
- package/dist/tasks/types.d.ts.map +1 -0
- package/dist/tasks/types.js +2 -0
- package/dist/test-fixtures/kinds/index.d.ts +56 -0
- package/dist/test-fixtures/kinds/index.d.ts.map +1 -0
- package/dist/test-fixtures/kinds/index.js +44 -0
- package/dist/testing/deterministic.d.ts +90 -0
- package/dist/testing/deterministic.d.ts.map +1 -0
- package/dist/testing/deterministic.js +449 -0
- package/dist/testing/index.d.ts +4 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +23 -0
- package/dist/testing/runHarness.d.ts +64 -0
- package/dist/testing/runHarness.d.ts.map +1 -0
- package/dist/testing/runHarness.js +161 -0
- package/dist/testing/snapshots.d.ts +17 -0
- package/dist/testing/snapshots.d.ts.map +1 -0
- package/dist/testing/snapshots.js +24 -0
- package/package.json +35 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.STATE_CACHE_SCHEMA_VERSION = void 0;
|
|
4
|
+
exports.readStateCache = readStateCache;
|
|
5
|
+
exports.writeStateCache = writeStateCache;
|
|
6
|
+
exports.journalHeadsEqual = journalHeadsEqual;
|
|
7
|
+
exports.createStateCacheSnapshot = createStateCacheSnapshot;
|
|
8
|
+
exports.normalizeJournalHead = normalizeJournalHead;
|
|
9
|
+
exports.normalizeSnapshot = normalizeSnapshot;
|
|
10
|
+
exports.rebuildStateCache = rebuildStateCache;
|
|
11
|
+
const fs_1 = require("fs");
|
|
12
|
+
const paths_1 = require("../../storage/paths");
|
|
13
|
+
const atomic_1 = require("../../storage/atomic");
|
|
14
|
+
const effectIndex_1 = require("./effectIndex");
|
|
15
|
+
const clock_1 = require("../../storage/clock");
|
|
16
|
+
exports.STATE_CACHE_SCHEMA_VERSION = "2026.01.state-cache";
|
|
17
|
+
async function readStateCache(runDir) {
|
|
18
|
+
const stateFile = (0, paths_1.getStateFile)(runDir);
|
|
19
|
+
try {
|
|
20
|
+
const raw = await fs_1.promises.readFile(stateFile, "utf8");
|
|
21
|
+
const parsed = JSON.parse(raw);
|
|
22
|
+
return normalizeSnapshot(parsed);
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
const err = error;
|
|
26
|
+
if (err.code === "ENOENT") {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function writeStateCache(runDir, snapshot) {
|
|
33
|
+
const stateDir = (0, paths_1.getStateDir)(runDir);
|
|
34
|
+
await fs_1.promises.mkdir(stateDir, { recursive: true });
|
|
35
|
+
const stateFile = (0, paths_1.getStateFile)(runDir);
|
|
36
|
+
await (0, atomic_1.writeFileAtomic)(stateFile, JSON.stringify(snapshot, null, 2) + "\n");
|
|
37
|
+
}
|
|
38
|
+
function journalHeadsEqual(a, b) {
|
|
39
|
+
if (!a && !b)
|
|
40
|
+
return true;
|
|
41
|
+
if (!a || !b)
|
|
42
|
+
return false;
|
|
43
|
+
if (a.seq !== b.seq || a.ulid !== b.ulid)
|
|
44
|
+
return false;
|
|
45
|
+
if (a.checksum && b.checksum && a.checksum !== b.checksum)
|
|
46
|
+
return false;
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
function createStateCacheSnapshot(journalHeadOrOptions) {
|
|
50
|
+
const options = journalHeadOrOptions && isJournalHeadLike(journalHeadOrOptions)
|
|
51
|
+
? { journalHead: journalHeadOrOptions }
|
|
52
|
+
: journalHeadOrOptions ?? {};
|
|
53
|
+
return {
|
|
54
|
+
schemaVersion: options.schemaVersion ?? exports.STATE_CACHE_SCHEMA_VERSION,
|
|
55
|
+
savedAt: options.savedAt ?? (0, clock_1.getClockIsoString)(),
|
|
56
|
+
journalHead: options.journalHead ?? null,
|
|
57
|
+
stateVersion: options.stateVersion ?? 0,
|
|
58
|
+
effectsByInvocation: options.effectsByInvocation ?? {},
|
|
59
|
+
pendingEffectsByKind: options.pendingEffectsByKind ?? {},
|
|
60
|
+
rebuildReason: options.rebuildReason ?? null,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function normalizeJournalHead(raw) {
|
|
64
|
+
if (raw === null || raw === undefined)
|
|
65
|
+
return raw;
|
|
66
|
+
if (!isPlainObject(raw))
|
|
67
|
+
return undefined;
|
|
68
|
+
const seq = Number(raw.seq);
|
|
69
|
+
const ulid = raw.ulid;
|
|
70
|
+
if (!Number.isFinite(seq) || typeof ulid !== "string" || !ulid) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
const checksum = typeof raw.checksum === "string" && raw.checksum ? raw.checksum : undefined;
|
|
74
|
+
return { seq, ulid, checksum };
|
|
75
|
+
}
|
|
76
|
+
function normalizeSnapshot(raw) {
|
|
77
|
+
if (!isPlainObject(raw)) {
|
|
78
|
+
throw new Error("Invalid state cache snapshot");
|
|
79
|
+
}
|
|
80
|
+
const journalHead = raw.journalHead === null ? null : normalizeJournalHead(raw.journalHead ?? undefined) ?? null;
|
|
81
|
+
const effectsByInvocation = normalizeEffectSummaryMap(raw.effectsByInvocation);
|
|
82
|
+
const pendingEffectsByKind = normalizePendingEffects(raw.pendingEffectsByKind);
|
|
83
|
+
const savedAt = typeof raw.savedAt === "string" ? raw.savedAt : (0, clock_1.getClockIsoString)();
|
|
84
|
+
const rebuildReason = raw.rebuildReason === null
|
|
85
|
+
? null
|
|
86
|
+
: typeof raw.rebuildReason === "string"
|
|
87
|
+
? raw.rebuildReason
|
|
88
|
+
: null;
|
|
89
|
+
const stateVersion = typeof raw.stateVersion === "number" && Number.isFinite(raw.stateVersion) ? raw.stateVersion : 0;
|
|
90
|
+
return createStateCacheSnapshot({
|
|
91
|
+
schemaVersion: typeof raw.schemaVersion === "string" ? raw.schemaVersion : exports.STATE_CACHE_SCHEMA_VERSION,
|
|
92
|
+
savedAt,
|
|
93
|
+
journalHead,
|
|
94
|
+
stateVersion,
|
|
95
|
+
effectsByInvocation,
|
|
96
|
+
pendingEffectsByKind,
|
|
97
|
+
rebuildReason,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
async function rebuildStateCache(runDir, opts) {
|
|
101
|
+
const effectIndex = opts?.effectIndex ??
|
|
102
|
+
(await (0, effectIndex_1.buildEffectIndex)({
|
|
103
|
+
runDir,
|
|
104
|
+
}));
|
|
105
|
+
const journalHead = effectIndex.getJournalHead() ?? null;
|
|
106
|
+
const stateVersion = journalHead?.seq ?? 0;
|
|
107
|
+
const effectsByInvocation = deriveEffectsByInvocation(effectIndex);
|
|
108
|
+
const pendingEffectsByKind = derivePendingByKind(effectIndex);
|
|
109
|
+
const snapshot = createStateCacheSnapshot({
|
|
110
|
+
journalHead,
|
|
111
|
+
stateVersion,
|
|
112
|
+
effectsByInvocation,
|
|
113
|
+
pendingEffectsByKind,
|
|
114
|
+
rebuildReason: opts?.reason ?? null,
|
|
115
|
+
});
|
|
116
|
+
await writeStateCache(runDir, snapshot);
|
|
117
|
+
return snapshot;
|
|
118
|
+
}
|
|
119
|
+
function deriveEffectsByInvocation(effectIndex) {
|
|
120
|
+
const summaries = {};
|
|
121
|
+
effectIndex.listEffects().forEach((record) => {
|
|
122
|
+
summaries[record.invocationKey] = summarizeEffect(record);
|
|
123
|
+
});
|
|
124
|
+
return summaries;
|
|
125
|
+
}
|
|
126
|
+
function summarizeEffect(record) {
|
|
127
|
+
const summary = {
|
|
128
|
+
effectId: record.effectId,
|
|
129
|
+
invocationKey: record.invocationKey,
|
|
130
|
+
status: record.status,
|
|
131
|
+
};
|
|
132
|
+
if (record.kind)
|
|
133
|
+
summary.kind = record.kind;
|
|
134
|
+
if (record.label)
|
|
135
|
+
summary.label = record.label;
|
|
136
|
+
if (record.taskId)
|
|
137
|
+
summary.taskId = record.taskId;
|
|
138
|
+
if (record.stepId)
|
|
139
|
+
summary.stepId = record.stepId;
|
|
140
|
+
if (record.requestedAt)
|
|
141
|
+
summary.requestedAt = record.requestedAt;
|
|
142
|
+
if (record.resolvedAt)
|
|
143
|
+
summary.resolvedAt = record.resolvedAt;
|
|
144
|
+
return summary;
|
|
145
|
+
}
|
|
146
|
+
function derivePendingByKind(effectIndex) {
|
|
147
|
+
const totals = {};
|
|
148
|
+
effectIndex.listPendingEffects().forEach((record) => {
|
|
149
|
+
const key = record.kind ?? "unknown";
|
|
150
|
+
totals[key] = (totals[key] ?? 0) + 1;
|
|
151
|
+
});
|
|
152
|
+
return totals;
|
|
153
|
+
}
|
|
154
|
+
function normalizeEffectSummaryMap(raw) {
|
|
155
|
+
if (!isPlainObject(raw))
|
|
156
|
+
return {};
|
|
157
|
+
const summaries = {};
|
|
158
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
159
|
+
const summary = normalizeDerivedEffectSummary(value);
|
|
160
|
+
if (summary) {
|
|
161
|
+
summaries[key] = summary;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return summaries;
|
|
165
|
+
}
|
|
166
|
+
function normalizeDerivedEffectSummary(raw) {
|
|
167
|
+
if (!isPlainObject(raw))
|
|
168
|
+
return undefined;
|
|
169
|
+
const effectId = typeof raw.effectId === "string" ? raw.effectId : undefined;
|
|
170
|
+
const invocationKey = typeof raw.invocationKey === "string" ? raw.invocationKey : undefined;
|
|
171
|
+
const status = isEffectStatus(raw.status) ? raw.status : undefined;
|
|
172
|
+
if (!effectId || !invocationKey || !status) {
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
const summary = { effectId, invocationKey, status };
|
|
176
|
+
if (typeof raw.kind === "string")
|
|
177
|
+
summary.kind = raw.kind;
|
|
178
|
+
if (typeof raw.label === "string")
|
|
179
|
+
summary.label = raw.label;
|
|
180
|
+
if (typeof raw.taskId === "string")
|
|
181
|
+
summary.taskId = raw.taskId;
|
|
182
|
+
if (typeof raw.stepId === "string")
|
|
183
|
+
summary.stepId = raw.stepId;
|
|
184
|
+
if (typeof raw.requestedAt === "string")
|
|
185
|
+
summary.requestedAt = raw.requestedAt;
|
|
186
|
+
if (typeof raw.resolvedAt === "string")
|
|
187
|
+
summary.resolvedAt = raw.resolvedAt;
|
|
188
|
+
return summary;
|
|
189
|
+
}
|
|
190
|
+
function normalizePendingEffects(raw) {
|
|
191
|
+
if (!isPlainObject(raw))
|
|
192
|
+
return {};
|
|
193
|
+
const totals = {};
|
|
194
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
195
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
196
|
+
totals[key] = value;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return totals;
|
|
200
|
+
}
|
|
201
|
+
function isPlainObject(value) {
|
|
202
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
203
|
+
}
|
|
204
|
+
function isEffectStatus(value) {
|
|
205
|
+
return value === "requested" || value === "resolved_ok" || value === "resolved_error";
|
|
206
|
+
}
|
|
207
|
+
function isJournalHeadLike(value) {
|
|
208
|
+
if (!isPlainObject(value))
|
|
209
|
+
return false;
|
|
210
|
+
return Number.isFinite(value.seq) && typeof value.ulid === "string" && value.ulid.length > 0;
|
|
211
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { JsonRecord, RunMetadata } from "../storage/types";
|
|
2
|
+
import type { DefinedTask, TaskDef, TaskInvokeOptions } from "../tasks/types";
|
|
3
|
+
import type { StateCacheJournalHead } from "./replay/stateCache";
|
|
4
|
+
export type { DefinedTask, TaskBuildContext, TaskDef, TaskInvokeOptions } from "../tasks/types";
|
|
5
|
+
export type { StateCacheJournalHead } from "./replay/stateCache";
|
|
6
|
+
export type ProcessLogger = (...args: any[]) => void;
|
|
7
|
+
export type EffectStatus = "requested" | "resolved_ok" | "resolved_error";
|
|
8
|
+
export interface SerializedEffectError {
|
|
9
|
+
name?: string;
|
|
10
|
+
message?: string;
|
|
11
|
+
stack?: string;
|
|
12
|
+
data?: unknown;
|
|
13
|
+
}
|
|
14
|
+
export interface EffectRecord {
|
|
15
|
+
effectId: string;
|
|
16
|
+
invocationKey: string;
|
|
17
|
+
invocationHash?: string;
|
|
18
|
+
stepId: string;
|
|
19
|
+
taskId: string;
|
|
20
|
+
status: EffectStatus;
|
|
21
|
+
kind?: string;
|
|
22
|
+
label?: string;
|
|
23
|
+
labels?: string[];
|
|
24
|
+
taskDefRef?: string;
|
|
25
|
+
inputsRef?: string;
|
|
26
|
+
resultRef?: string;
|
|
27
|
+
error?: SerializedEffectError;
|
|
28
|
+
stdoutRef?: string;
|
|
29
|
+
stderrRef?: string;
|
|
30
|
+
requestedAt?: string;
|
|
31
|
+
resolvedAt?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface EffectSchedulerHints {
|
|
34
|
+
pendingCount?: number;
|
|
35
|
+
parallelGroupId?: string;
|
|
36
|
+
sleepUntilEpochMs?: number;
|
|
37
|
+
}
|
|
38
|
+
export interface EffectAction {
|
|
39
|
+
effectId: string;
|
|
40
|
+
invocationKey: string;
|
|
41
|
+
kind: string;
|
|
42
|
+
label?: string;
|
|
43
|
+
labels?: string[];
|
|
44
|
+
taskDef: TaskDef;
|
|
45
|
+
taskId?: string;
|
|
46
|
+
stepId?: string;
|
|
47
|
+
taskDefRef?: string;
|
|
48
|
+
inputsRef?: string;
|
|
49
|
+
requestedAt?: string;
|
|
50
|
+
schedulerHints?: EffectSchedulerHints;
|
|
51
|
+
}
|
|
52
|
+
export interface CreateRunOptions {
|
|
53
|
+
runsDir: string;
|
|
54
|
+
runId?: string;
|
|
55
|
+
process: {
|
|
56
|
+
processId: string;
|
|
57
|
+
importPath: string;
|
|
58
|
+
exportName?: string;
|
|
59
|
+
};
|
|
60
|
+
request?: string;
|
|
61
|
+
inputs?: unknown;
|
|
62
|
+
processRevision?: string;
|
|
63
|
+
layoutVersion?: string;
|
|
64
|
+
metadata?: JsonRecord;
|
|
65
|
+
lockOwner?: string;
|
|
66
|
+
}
|
|
67
|
+
export interface CreateRunResult {
|
|
68
|
+
runId: string;
|
|
69
|
+
runDir: string;
|
|
70
|
+
metadata: RunMetadata;
|
|
71
|
+
}
|
|
72
|
+
export interface ParallelHelpers {
|
|
73
|
+
all<T>(thunks: Array<() => T | Promise<T>>): Promise<T[]>;
|
|
74
|
+
map<TItem, TOut>(items: TItem[], fn: (item: TItem) => TOut | Promise<TOut>): Promise<TOut[]>;
|
|
75
|
+
}
|
|
76
|
+
export interface ProcessContext {
|
|
77
|
+
now(): Date;
|
|
78
|
+
task<TArgs, TResult>(task: DefinedTask<TArgs, TResult>, args: TArgs, options?: TaskInvokeOptions): Promise<TResult>;
|
|
79
|
+
breakpoint<T = unknown>(payload: T, options?: {
|
|
80
|
+
label?: string;
|
|
81
|
+
}): Promise<void>;
|
|
82
|
+
sleepUntil(target: string | number, options?: {
|
|
83
|
+
label?: string;
|
|
84
|
+
}): Promise<void>;
|
|
85
|
+
orchestratorTask<TArgs = unknown, TResult = unknown>(payload: TArgs, options?: {
|
|
86
|
+
label?: string;
|
|
87
|
+
}): Promise<TResult>;
|
|
88
|
+
parallel: ParallelHelpers;
|
|
89
|
+
log?: ProcessLogger;
|
|
90
|
+
}
|
|
91
|
+
export interface OrchestrateOptions {
|
|
92
|
+
runDir: string;
|
|
93
|
+
process?: {
|
|
94
|
+
importPath: string;
|
|
95
|
+
exportName?: string;
|
|
96
|
+
};
|
|
97
|
+
inputs?: unknown;
|
|
98
|
+
now?: Date | (() => Date);
|
|
99
|
+
context?: Record<string, unknown>;
|
|
100
|
+
logger?: ProcessLogger;
|
|
101
|
+
}
|
|
102
|
+
export interface IterationMetadata {
|
|
103
|
+
stateVersion?: number;
|
|
104
|
+
stateRebuilt?: boolean;
|
|
105
|
+
stateRebuildReason?: string | null;
|
|
106
|
+
pendingEffectsByKind?: Record<string, number>;
|
|
107
|
+
journalHead?: StateCacheJournalHead | null;
|
|
108
|
+
}
|
|
109
|
+
export type IterationResult = {
|
|
110
|
+
status: "completed";
|
|
111
|
+
output: unknown;
|
|
112
|
+
metadata?: IterationMetadata;
|
|
113
|
+
} | {
|
|
114
|
+
status: "waiting";
|
|
115
|
+
nextActions: EffectAction[];
|
|
116
|
+
metadata?: IterationMetadata;
|
|
117
|
+
} | {
|
|
118
|
+
status: "failed";
|
|
119
|
+
error: unknown;
|
|
120
|
+
metadata?: IterationMetadata;
|
|
121
|
+
};
|
|
122
|
+
export interface CommitEffectResultOptions {
|
|
123
|
+
runDir: string;
|
|
124
|
+
effectId: string;
|
|
125
|
+
invocationKey?: string;
|
|
126
|
+
logger?: ProcessLogger;
|
|
127
|
+
result: {
|
|
128
|
+
status: "ok" | "error";
|
|
129
|
+
value?: unknown;
|
|
130
|
+
error?: unknown;
|
|
131
|
+
stdout?: string;
|
|
132
|
+
stderr?: string;
|
|
133
|
+
stdoutRef?: string;
|
|
134
|
+
stderrRef?: string;
|
|
135
|
+
startedAt?: string;
|
|
136
|
+
finishedAt?: string;
|
|
137
|
+
metadata?: JsonRecord;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
export interface CommitEffectResultArtifacts {
|
|
141
|
+
resultRef: string;
|
|
142
|
+
stdoutRef?: string;
|
|
143
|
+
stderrRef?: string;
|
|
144
|
+
startedAt?: string;
|
|
145
|
+
finishedAt?: string;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomic.d.ts","sourceRoot":"","sources":["../../src/storage/atomic.ts"],"names":[],"mappings":"AAcA,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,SAAI,iBAiC3F"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.writeFileAtomic = writeFileAtomic;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const RETRYABLE_ERRORS = new Set(["EBUSY", "ETXTBSY", "EPERM", "EACCES"]);
|
|
10
|
+
async function fsyncPath(targetPath) {
|
|
11
|
+
const handle = await fs_1.promises.open(targetPath, "r");
|
|
12
|
+
try {
|
|
13
|
+
await handle.sync();
|
|
14
|
+
}
|
|
15
|
+
finally {
|
|
16
|
+
await handle.close();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async function writeFileAtomic(targetPath, data, retries = 3) {
|
|
20
|
+
await fs_1.promises.mkdir(path_1.default.dirname(targetPath), { recursive: true });
|
|
21
|
+
const tempPath = `${targetPath}.tmp-${process.pid}-${Date.now()}`;
|
|
22
|
+
const handle = await fs_1.promises.open(tempPath, "w");
|
|
23
|
+
try {
|
|
24
|
+
if (typeof data === "string") {
|
|
25
|
+
await handle.writeFile(data, "utf8");
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
await handle.writeFile(data);
|
|
29
|
+
}
|
|
30
|
+
await handle.sync();
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
await handle.close();
|
|
34
|
+
}
|
|
35
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
36
|
+
try {
|
|
37
|
+
await fs_1.promises.rename(tempPath, targetPath);
|
|
38
|
+
await fsyncPath(path_1.default.dirname(targetPath));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
const err = error;
|
|
43
|
+
if (err.code === "ENOENT") {
|
|
44
|
+
await fs_1.promises.writeFile(targetPath, data);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (attempt === retries || !err.code || !RETRYABLE_ERRORS.has(err.code)) {
|
|
48
|
+
await fs_1.promises.rm(tempPath, { force: true });
|
|
49
|
+
throw err;
|
|
50
|
+
}
|
|
51
|
+
await new Promise((resolve) => setTimeout(resolve, (attempt + 1) * 25));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { DiskUsageReport, OrphanedBlobInfo } from "./types";
|
|
2
|
+
export declare function getDiskUsage(runsRoot: string, runId: string): Promise<DiskUsageReport>;
|
|
3
|
+
export declare function findOrphanedBlobs(runsRoot: string, runId: string): Promise<OrphanedBlobInfo[]>;
|
|
4
|
+
//# sourceMappingURL=cleanup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/storage/cleanup.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAwB5D,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAU5F;AAED,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA6CpG"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getDiskUsage = getDiskUsage;
|
|
7
|
+
exports.findOrphanedBlobs = findOrphanedBlobs;
|
|
8
|
+
const fs_1 = require("fs");
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const paths_1 = require("./paths");
|
|
11
|
+
async function dirSize(dir) {
|
|
12
|
+
try {
|
|
13
|
+
const entries = await fs_1.promises.readdir(dir, { withFileTypes: true });
|
|
14
|
+
let total = 0;
|
|
15
|
+
for (const entry of entries) {
|
|
16
|
+
const full = path_1.default.join(dir, entry.name);
|
|
17
|
+
if (entry.isDirectory()) {
|
|
18
|
+
total += await dirSize(full);
|
|
19
|
+
}
|
|
20
|
+
else if (entry.isFile()) {
|
|
21
|
+
const stat = await fs_1.promises.stat(full);
|
|
22
|
+
total += stat.size;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return total;
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
const error = err;
|
|
29
|
+
if (error.code === "ENOENT")
|
|
30
|
+
return 0;
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function getDiskUsage(runsRoot, runId) {
|
|
35
|
+
const runDir = (0, paths_1.getRunDir)(runsRoot, runId);
|
|
36
|
+
const [journal, tasks, blobs, state] = await Promise.all([
|
|
37
|
+
dirSize((0, paths_1.getJournalDir)(runDir)),
|
|
38
|
+
dirSize((0, paths_1.getTasksDir)(runDir)),
|
|
39
|
+
dirSize((0, paths_1.getBlobsDir)(runDir)),
|
|
40
|
+
dirSize((0, paths_1.getStateDir)(runDir)),
|
|
41
|
+
]);
|
|
42
|
+
const total = journal + tasks + blobs + state;
|
|
43
|
+
return { totalBytes: total, journalBytes: journal, tasksBytes: tasks, blobsBytes: blobs, stateBytes: state };
|
|
44
|
+
}
|
|
45
|
+
async function findOrphanedBlobs(runsRoot, runId) {
|
|
46
|
+
const runDir = (0, paths_1.getRunDir)(runsRoot, runId);
|
|
47
|
+
const blobsDir = (0, paths_1.getBlobsDir)(runDir);
|
|
48
|
+
const referenced = new Set();
|
|
49
|
+
const tasksDir = (0, paths_1.getTasksDir)(runDir);
|
|
50
|
+
try {
|
|
51
|
+
const effects = await fs_1.promises.readdir(tasksDir, { withFileTypes: true });
|
|
52
|
+
for (const effectEntry of effects) {
|
|
53
|
+
if (!effectEntry.isDirectory())
|
|
54
|
+
continue;
|
|
55
|
+
const artifactsPath = path_1.default.join(tasksDir, effectEntry.name, "artifacts.json");
|
|
56
|
+
try {
|
|
57
|
+
const data = await fs_1.promises.readFile(artifactsPath, "utf8");
|
|
58
|
+
const artifacts = JSON.parse(data);
|
|
59
|
+
for (const artifact of artifacts) {
|
|
60
|
+
if (artifact.storedAt.startsWith("blobs/")) {
|
|
61
|
+
referenced.add(path_1.default.basename(artifact.storedAt));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
const error = err;
|
|
67
|
+
if (error.code !== "ENOENT")
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
const error = err;
|
|
74
|
+
if (error.code !== "ENOENT")
|
|
75
|
+
throw err;
|
|
76
|
+
}
|
|
77
|
+
const orphaned = [];
|
|
78
|
+
try {
|
|
79
|
+
const blobs = await fs_1.promises.readdir(blobsDir, { withFileTypes: true });
|
|
80
|
+
for (const blob of blobs) {
|
|
81
|
+
if (!blob.isFile())
|
|
82
|
+
continue;
|
|
83
|
+
if (!referenced.has(blob.name)) {
|
|
84
|
+
const full = path_1.default.join(blobsDir, blob.name);
|
|
85
|
+
const stat = await fs_1.promises.stat(full);
|
|
86
|
+
orphaned.push({ hash: blob.name, bytes: stat.size, path: `blobs/${blob.name}` });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
const error = err;
|
|
92
|
+
if (error.code !== "ENOENT")
|
|
93
|
+
throw err;
|
|
94
|
+
}
|
|
95
|
+
return orphaned;
|
|
96
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type ClockProvider = () => Date;
|
|
2
|
+
export declare function getClockDate(): Date;
|
|
3
|
+
export declare function getClockIsoString(): string;
|
|
4
|
+
export declare function setClockForTests(provider: ClockProvider): void;
|
|
5
|
+
export declare function resetClock(): void;
|
|
6
|
+
//# sourceMappingURL=clock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../../src/storage/clock.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC;AAQvC,wBAAgB,YAAY,IAAI,IAAI,CAMnC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,QAKvD;AAED,wBAAgB,UAAU,SAEzB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getClockDate = getClockDate;
|
|
4
|
+
exports.getClockIsoString = getClockIsoString;
|
|
5
|
+
exports.setClockForTests = setClockForTests;
|
|
6
|
+
exports.resetClock = resetClock;
|
|
7
|
+
function systemClock() {
|
|
8
|
+
return new Date();
|
|
9
|
+
}
|
|
10
|
+
let activeClock = systemClock;
|
|
11
|
+
function getClockDate() {
|
|
12
|
+
const current = activeClock();
|
|
13
|
+
if (!(current instanceof Date)) {
|
|
14
|
+
throw new Error("Clock provider must return a Date instance");
|
|
15
|
+
}
|
|
16
|
+
return new Date(current.getTime());
|
|
17
|
+
}
|
|
18
|
+
function getClockIsoString() {
|
|
19
|
+
return getClockDate().toISOString();
|
|
20
|
+
}
|
|
21
|
+
function setClockForTests(provider) {
|
|
22
|
+
if (typeof provider !== "function") {
|
|
23
|
+
throw new Error("setClockForTests requires a function");
|
|
24
|
+
}
|
|
25
|
+
activeClock = provider;
|
|
26
|
+
}
|
|
27
|
+
function resetClock() {
|
|
28
|
+
activeClock = systemClock;
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createRunDir.d.ts","sourceRoot":"","sources":["../../src/storage/createRunDir.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAyB,WAAW,EAAE,MAAM,SAAS,CAAC;AAkBlF,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB;;;GAkC9D"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createRunDir = createRunDir;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const paths_1 = require("./paths");
|
|
10
|
+
const atomic_1 = require("./atomic");
|
|
11
|
+
const clock_1 = require("./clock");
|
|
12
|
+
const GITIGNORE_CONTENT = `state/\ntasks/*/artifacts/\nblobs/\norphaned/\n`;
|
|
13
|
+
async function createRunDir(options) {
|
|
14
|
+
const runDir = (0, paths_1.getRunDir)(options.runsRoot, options.runId);
|
|
15
|
+
await fs_1.promises.mkdir(runDir, { recursive: true });
|
|
16
|
+
await Promise.all([
|
|
17
|
+
fs_1.promises.mkdir((0, paths_1.getJournalDir)(runDir), { recursive: true }),
|
|
18
|
+
fs_1.promises.mkdir((0, paths_1.getTasksDir)(runDir), { recursive: true }),
|
|
19
|
+
fs_1.promises.mkdir((0, paths_1.getBlobsDir)(runDir), { recursive: true }),
|
|
20
|
+
fs_1.promises.mkdir((0, paths_1.getStateDir)(runDir), { recursive: true }),
|
|
21
|
+
fs_1.promises.mkdir(path_1.default.join(runDir, paths_1.ORPHANED_DIR), { recursive: true }),
|
|
22
|
+
fs_1.promises.mkdir(path_1.default.join(runDir, paths_1.PROCESS_DIR), { recursive: true }),
|
|
23
|
+
]);
|
|
24
|
+
await (0, atomic_1.writeFileAtomic)(path_1.default.join(runDir, ".gitignore"), GITIGNORE_CONTENT);
|
|
25
|
+
const layoutVersion = options.layoutVersion ?? paths_1.DEFAULT_LAYOUT_VERSION;
|
|
26
|
+
const entrypoint = resolveEntrypoint(options);
|
|
27
|
+
const createdAt = (0, clock_1.getClockIsoString)();
|
|
28
|
+
const metadata = {
|
|
29
|
+
runId: options.runId,
|
|
30
|
+
request: options.request,
|
|
31
|
+
processId: options.processId ?? options.request ?? options.runId,
|
|
32
|
+
entrypoint,
|
|
33
|
+
processPath: entrypoint.importPath,
|
|
34
|
+
processRevision: options.processRevision,
|
|
35
|
+
layoutVersion,
|
|
36
|
+
createdAt,
|
|
37
|
+
};
|
|
38
|
+
if (options.extraMetadata) {
|
|
39
|
+
Object.assign(metadata, options.extraMetadata);
|
|
40
|
+
}
|
|
41
|
+
await (0, atomic_1.writeFileAtomic)(path_1.default.join(runDir, paths_1.RUN_METADATA_FILE), JSON.stringify(metadata, null, 2) + "\n");
|
|
42
|
+
if (options.inputs !== undefined) {
|
|
43
|
+
await (0, atomic_1.writeFileAtomic)(path_1.default.join(runDir, paths_1.INPUTS_FILE), JSON.stringify(options.inputs, null, 2) + "\n");
|
|
44
|
+
}
|
|
45
|
+
return { runDir, metadata };
|
|
46
|
+
}
|
|
47
|
+
function resolveEntrypoint(options) {
|
|
48
|
+
if (options.entrypoint?.importPath) {
|
|
49
|
+
return {
|
|
50
|
+
importPath: options.entrypoint.importPath,
|
|
51
|
+
exportName: options.entrypoint.exportName ?? "process",
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const importPath = options.processPath ?? "./process.js";
|
|
55
|
+
return {
|
|
56
|
+
importPath,
|
|
57
|
+
exportName: "process",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { createRunDir } from "./createRunDir";
|
|
2
|
+
export { appendEvent, loadJournal } from "./journal";
|
|
3
|
+
export { snapshotState } from "./snapshotState";
|
|
4
|
+
export { storeTaskArtifacts } from "./storeTaskArtifacts";
|
|
5
|
+
export { getDiskUsage, findOrphanedBlobs } from "./cleanup";
|
|
6
|
+
export { acquireRunLock, releaseRunLock, readRunLock } from "./lock";
|
|
7
|
+
export { readRunMetadata, readRunInputs, writeRunOutput } from "./runFiles";
|
|
8
|
+
export { writeTaskDefinition, readTaskDefinition, readTaskResult, writeTaskResult, } from "./tasks";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,eAAe,GAChB,MAAM,SAAS,CAAC"}
|