@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,449 @@
|
|
|
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.withDeterministicIds = withDeterministicIds;
|
|
7
|
+
exports.withFixedClock = withFixedClock;
|
|
8
|
+
exports.createTempDeterministicRun = createTempDeterministicRun;
|
|
9
|
+
exports.snapshotRunState = snapshotRunState;
|
|
10
|
+
exports.installFixedClock = installFixedClock;
|
|
11
|
+
exports.installDeterministicUlids = installDeterministicUlids;
|
|
12
|
+
exports.createDeterministicRunHarness = createDeterministicRunHarness;
|
|
13
|
+
const fs_1 = require("fs");
|
|
14
|
+
const os_1 = __importDefault(require("os"));
|
|
15
|
+
const path_1 = __importDefault(require("path"));
|
|
16
|
+
const journal_1 = require("../storage/journal");
|
|
17
|
+
const createRunDir_1 = require("../storage/createRunDir");
|
|
18
|
+
const ulids_1 = require("../storage/ulids");
|
|
19
|
+
const clock_1 = require("../storage/clock");
|
|
20
|
+
const stateCache_1 = require("../runtime/replay/stateCache");
|
|
21
|
+
const CROCKFORD_BASE32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
22
|
+
const DEFAULT_CLOCK_START_MS = Date.UTC(2025, 0, 1, 0, 0, 0, 0);
|
|
23
|
+
const DEFAULT_CLOCK_STEP_MS = 1000;
|
|
24
|
+
const TEMP_RUN_PREFIX = "babysitter-deterministic-run-";
|
|
25
|
+
const DEFAULT_DETERMINISTIC_RUN_ID = "det-run-0001";
|
|
26
|
+
async function withDeterministicIds(sequence, fn) {
|
|
27
|
+
if (!Array.isArray(sequence) || sequence.length === 0) {
|
|
28
|
+
throw new Error("withDeterministicIds requires a non-empty sequence");
|
|
29
|
+
}
|
|
30
|
+
const handle = installDeterministicUlids({ preset: sequence });
|
|
31
|
+
handle.apply();
|
|
32
|
+
try {
|
|
33
|
+
return await fn();
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
handle.restore();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function withFixedClock(sequenceOrValue, fn) {
|
|
40
|
+
const handle = installFixedClock({ sequence: sequenceOrValue });
|
|
41
|
+
handle.apply();
|
|
42
|
+
try {
|
|
43
|
+
return await fn();
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
handle.restore();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function createTempDeterministicRun(options) {
|
|
50
|
+
if (!options.processSource || !options.processSource.trim()) {
|
|
51
|
+
throw new Error("createTempDeterministicRun requires processSource contents");
|
|
52
|
+
}
|
|
53
|
+
const runsRoot = await fs_1.promises.mkdtemp(path_1.default.join(os_1.default.tmpdir(), TEMP_RUN_PREFIX));
|
|
54
|
+
const runId = options.runId ?? DEFAULT_DETERMINISTIC_RUN_ID;
|
|
55
|
+
const request = options.request ?? "deterministic-test";
|
|
56
|
+
const clock = installFixedClock(options.clock !== undefined ? { sequence: options.clock } : undefined);
|
|
57
|
+
const ulids = installDeterministicUlids(options.ulids && options.ulids.length > 0 ? { preset: options.ulids } : undefined);
|
|
58
|
+
clock.apply();
|
|
59
|
+
ulids.apply();
|
|
60
|
+
let restored = false;
|
|
61
|
+
function restoreProviders() {
|
|
62
|
+
if (restored)
|
|
63
|
+
return;
|
|
64
|
+
restored = true;
|
|
65
|
+
try {
|
|
66
|
+
ulids.restore();
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
clock.restore();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function cleanupRoot() {
|
|
73
|
+
restoreProviders();
|
|
74
|
+
await fs_1.promises.rm(runsRoot, { recursive: true, force: true });
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const processPath = await writeProcessFixture(runsRoot, runId, options.processSource);
|
|
78
|
+
const { runDir } = await (0, createRunDir_1.createRunDir)({
|
|
79
|
+
runsRoot,
|
|
80
|
+
runId,
|
|
81
|
+
request,
|
|
82
|
+
processPath,
|
|
83
|
+
inputs: options.inputs,
|
|
84
|
+
});
|
|
85
|
+
await (0, journal_1.appendEvent)({
|
|
86
|
+
runDir,
|
|
87
|
+
eventType: "RUN_CREATED",
|
|
88
|
+
event: { runId, request },
|
|
89
|
+
});
|
|
90
|
+
return {
|
|
91
|
+
runDir,
|
|
92
|
+
restore: restoreProviders,
|
|
93
|
+
async cleanup() {
|
|
94
|
+
await cleanupRoot();
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
await cleanupRoot().catch(() => undefined);
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async function snapshotRunState(runDir) {
|
|
104
|
+
const events = await (0, journal_1.loadJournal)(runDir);
|
|
105
|
+
const journal = events.map((event) => ({
|
|
106
|
+
seq: event.seq,
|
|
107
|
+
ulid: event.ulid,
|
|
108
|
+
recordedAt: event.recordedAt,
|
|
109
|
+
type: event.type,
|
|
110
|
+
data: event.data,
|
|
111
|
+
}));
|
|
112
|
+
const state = await (0, stateCache_1.readStateCache)(runDir);
|
|
113
|
+
const stateSummary = state
|
|
114
|
+
? {
|
|
115
|
+
savedAt: state.savedAt,
|
|
116
|
+
stateVersion: state.stateVersion,
|
|
117
|
+
journalHead: state.journalHead ?? null,
|
|
118
|
+
pendingEffectsByKind: state.pendingEffectsByKind,
|
|
119
|
+
effectsByInvocation: state.effectsByInvocation,
|
|
120
|
+
rebuildReason: state.rebuildReason ?? null,
|
|
121
|
+
}
|
|
122
|
+
: null;
|
|
123
|
+
return { journal, state: stateSummary };
|
|
124
|
+
}
|
|
125
|
+
function installFixedClock(options) {
|
|
126
|
+
const controller = createClockController(options);
|
|
127
|
+
let depth = 0;
|
|
128
|
+
let release = null;
|
|
129
|
+
function apply() {
|
|
130
|
+
depth += 1;
|
|
131
|
+
if (depth === 1) {
|
|
132
|
+
release = applyClockController(controller);
|
|
133
|
+
}
|
|
134
|
+
return () => {
|
|
135
|
+
if (depth === 0) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
depth -= 1;
|
|
139
|
+
if (depth === 0 && release) {
|
|
140
|
+
release();
|
|
141
|
+
release = null;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function restore() {
|
|
146
|
+
depth = 0;
|
|
147
|
+
if (release) {
|
|
148
|
+
release();
|
|
149
|
+
release = null;
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
(0, clock_1.resetClock)();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
now: () => controller.now(),
|
|
157
|
+
advance: (ms) => controller.advance(ms),
|
|
158
|
+
reset: () => controller.reset(),
|
|
159
|
+
timestamp: () => controller.timestamp(),
|
|
160
|
+
apply,
|
|
161
|
+
restore,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function installDeterministicUlids(options) {
|
|
165
|
+
const issued = [];
|
|
166
|
+
const controller = createUlidController(options);
|
|
167
|
+
let depth = 0;
|
|
168
|
+
let release = null;
|
|
169
|
+
function next() {
|
|
170
|
+
const value = controller.next();
|
|
171
|
+
issued.push(value);
|
|
172
|
+
return value;
|
|
173
|
+
}
|
|
174
|
+
function apply() {
|
|
175
|
+
depth += 1;
|
|
176
|
+
if (depth === 1) {
|
|
177
|
+
(0, ulids_1.setUlidFactoryForTests)(() => next());
|
|
178
|
+
release = () => {
|
|
179
|
+
(0, ulids_1.resetUlidFactory)();
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
return () => {
|
|
183
|
+
if (depth === 0) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
depth -= 1;
|
|
187
|
+
if (depth === 0 && release) {
|
|
188
|
+
release();
|
|
189
|
+
release = null;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function restore() {
|
|
194
|
+
depth = 0;
|
|
195
|
+
if (release) {
|
|
196
|
+
release();
|
|
197
|
+
release = null;
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
(0, ulids_1.resetUlidFactory)();
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
issued,
|
|
205
|
+
next,
|
|
206
|
+
reset() {
|
|
207
|
+
issued.length = 0;
|
|
208
|
+
controller.reset();
|
|
209
|
+
},
|
|
210
|
+
apply,
|
|
211
|
+
restore,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
async function createDeterministicRunHarness(options) {
|
|
215
|
+
if (!options.processPath && !options.processSource) {
|
|
216
|
+
throw new Error("createDeterministicRunHarness requires processPath or processSource");
|
|
217
|
+
}
|
|
218
|
+
const runsRoot = await fs_1.promises.mkdtemp(path_1.default.join(os_1.default.tmpdir(), TEMP_RUN_PREFIX));
|
|
219
|
+
const runId = options.runId ?? DEFAULT_DETERMINISTIC_RUN_ID;
|
|
220
|
+
const request = options.request ?? "deterministic-test";
|
|
221
|
+
const clock = installFixedClock(options.clock);
|
|
222
|
+
const ulids = installDeterministicUlids(options.ulids);
|
|
223
|
+
clock.apply();
|
|
224
|
+
ulids.apply();
|
|
225
|
+
let cleanedUp = false;
|
|
226
|
+
async function cleanupRoot() {
|
|
227
|
+
if (cleanedUp)
|
|
228
|
+
return;
|
|
229
|
+
cleanedUp = true;
|
|
230
|
+
try {
|
|
231
|
+
ulids.restore();
|
|
232
|
+
}
|
|
233
|
+
finally {
|
|
234
|
+
clock.restore();
|
|
235
|
+
}
|
|
236
|
+
await fs_1.promises.rm(runsRoot, { recursive: true, force: true });
|
|
237
|
+
}
|
|
238
|
+
try {
|
|
239
|
+
const processPath = options.processPath ?? (await writeProcessFixture(runsRoot, runId, options.processSource));
|
|
240
|
+
const entrypoint = options.exportName || !options.processSource
|
|
241
|
+
? {
|
|
242
|
+
importPath: processPath,
|
|
243
|
+
exportName: options.exportName ?? "process",
|
|
244
|
+
}
|
|
245
|
+
: undefined;
|
|
246
|
+
const { runDir } = await (0, createRunDir_1.createRunDir)({
|
|
247
|
+
runsRoot,
|
|
248
|
+
runId,
|
|
249
|
+
request,
|
|
250
|
+
processPath,
|
|
251
|
+
entrypoint,
|
|
252
|
+
inputs: options.inputs,
|
|
253
|
+
});
|
|
254
|
+
await (0, journal_1.appendEvent)({
|
|
255
|
+
runDir,
|
|
256
|
+
eventType: "RUN_CREATED",
|
|
257
|
+
event: { runId, request },
|
|
258
|
+
});
|
|
259
|
+
return {
|
|
260
|
+
runId,
|
|
261
|
+
runDir,
|
|
262
|
+
runsRoot,
|
|
263
|
+
clock,
|
|
264
|
+
ulids,
|
|
265
|
+
async cleanup() {
|
|
266
|
+
await cleanupRoot();
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
await cleanupRoot().catch(() => undefined);
|
|
272
|
+
throw error;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function createClockController(options) {
|
|
276
|
+
if (options?.sequence !== undefined) {
|
|
277
|
+
const sequence = normalizeClockSequence(options.sequence);
|
|
278
|
+
return createSequenceClockController(sequence);
|
|
279
|
+
}
|
|
280
|
+
const start = resolveClockStart(options?.start);
|
|
281
|
+
const stepMs = options?.stepMs ?? DEFAULT_CLOCK_STEP_MS;
|
|
282
|
+
return createTickingClockController(start, stepMs);
|
|
283
|
+
}
|
|
284
|
+
function createSequenceClockController(sequence) {
|
|
285
|
+
if (sequence.length === 0) {
|
|
286
|
+
throw new Error("Clock sequence must include at least one entry");
|
|
287
|
+
}
|
|
288
|
+
let index = 0;
|
|
289
|
+
function currentIndex() {
|
|
290
|
+
return Math.min(index, sequence.length - 1);
|
|
291
|
+
}
|
|
292
|
+
function clone(date) {
|
|
293
|
+
return new Date(date.getTime());
|
|
294
|
+
}
|
|
295
|
+
return {
|
|
296
|
+
issue() {
|
|
297
|
+
const value = clone(sequence[currentIndex()]);
|
|
298
|
+
if (index < sequence.length - 1) {
|
|
299
|
+
index += 1;
|
|
300
|
+
}
|
|
301
|
+
return value;
|
|
302
|
+
},
|
|
303
|
+
now() {
|
|
304
|
+
return clone(sequence[currentIndex()]);
|
|
305
|
+
},
|
|
306
|
+
advance() {
|
|
307
|
+
if (index < sequence.length - 1) {
|
|
308
|
+
index += 1;
|
|
309
|
+
}
|
|
310
|
+
return clone(sequence[currentIndex()]);
|
|
311
|
+
},
|
|
312
|
+
reset() {
|
|
313
|
+
index = 0;
|
|
314
|
+
},
|
|
315
|
+
timestamp() {
|
|
316
|
+
return sequence[currentIndex()].getTime();
|
|
317
|
+
},
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
function createTickingClockController(startMs, stepMs) {
|
|
321
|
+
if (!Number.isFinite(stepMs) || stepMs <= 0) {
|
|
322
|
+
throw new Error("stepMs must be a positive finite number");
|
|
323
|
+
}
|
|
324
|
+
const initial = startMs;
|
|
325
|
+
let current = startMs;
|
|
326
|
+
return {
|
|
327
|
+
issue() {
|
|
328
|
+
const value = new Date(current);
|
|
329
|
+
current += stepMs;
|
|
330
|
+
return value;
|
|
331
|
+
},
|
|
332
|
+
now() {
|
|
333
|
+
return new Date(current);
|
|
334
|
+
},
|
|
335
|
+
advance(ms = stepMs) {
|
|
336
|
+
if (!Number.isFinite(ms)) {
|
|
337
|
+
throw new Error("advance requires a finite number of milliseconds");
|
|
338
|
+
}
|
|
339
|
+
current += ms;
|
|
340
|
+
return new Date(current);
|
|
341
|
+
},
|
|
342
|
+
reset() {
|
|
343
|
+
current = initial;
|
|
344
|
+
},
|
|
345
|
+
timestamp() {
|
|
346
|
+
return current;
|
|
347
|
+
},
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
function applyClockController(controller) {
|
|
351
|
+
(0, clock_1.setClockForTests)(() => controller.issue());
|
|
352
|
+
return () => {
|
|
353
|
+
(0, clock_1.resetClock)();
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
function createUlidController(options) {
|
|
357
|
+
if (options?.preset && options.preset.length > 0) {
|
|
358
|
+
return createPresetUlidController(options.preset);
|
|
359
|
+
}
|
|
360
|
+
const epochMs = options?.epochMs ?? DEFAULT_CLOCK_START_MS;
|
|
361
|
+
const incrementMs = options?.incrementMs ?? DEFAULT_CLOCK_STEP_MS;
|
|
362
|
+
const randomnessSeed = options?.randomnessSeed ?? 0;
|
|
363
|
+
return createRollingUlidController(epochMs, incrementMs, randomnessSeed);
|
|
364
|
+
}
|
|
365
|
+
function createPresetUlidController(preset) {
|
|
366
|
+
let index = 0;
|
|
367
|
+
return {
|
|
368
|
+
next() {
|
|
369
|
+
const value = preset[index];
|
|
370
|
+
if (value === undefined) {
|
|
371
|
+
throw new Error("Deterministic ULID preset exhausted");
|
|
372
|
+
}
|
|
373
|
+
index += 1;
|
|
374
|
+
return value;
|
|
375
|
+
},
|
|
376
|
+
reset() {
|
|
377
|
+
index = 0;
|
|
378
|
+
},
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
function createRollingUlidController(epochMs, incrementMs, randomnessSeed) {
|
|
382
|
+
let tick = 0;
|
|
383
|
+
return {
|
|
384
|
+
next() {
|
|
385
|
+
const timestamp = epochMs + tick * incrementMs;
|
|
386
|
+
const timePart = encodeBase32(timestamp, 10);
|
|
387
|
+
const randomPart = encodeBase32(randomnessSeed + tick, 16);
|
|
388
|
+
tick += 1;
|
|
389
|
+
return `${timePart}${randomPart}`;
|
|
390
|
+
},
|
|
391
|
+
reset() {
|
|
392
|
+
tick = 0;
|
|
393
|
+
},
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
async function writeProcessFixture(runsRoot, runId, source) {
|
|
397
|
+
if (!source.trim()) {
|
|
398
|
+
throw new Error("processSource must be non-empty");
|
|
399
|
+
}
|
|
400
|
+
const processDir = path_1.default.join(runsRoot, "processes");
|
|
401
|
+
await fs_1.promises.mkdir(processDir, { recursive: true });
|
|
402
|
+
const processPath = path_1.default.join(processDir, `${runId}.mjs`);
|
|
403
|
+
await fs_1.promises.writeFile(processPath, source, "utf8");
|
|
404
|
+
return processPath;
|
|
405
|
+
}
|
|
406
|
+
function normalizeClockSequence(input) {
|
|
407
|
+
if (Array.isArray(input)) {
|
|
408
|
+
if (input.length === 0) {
|
|
409
|
+
throw new Error("Clock sequence must not be empty");
|
|
410
|
+
}
|
|
411
|
+
return input.map(toClockDate);
|
|
412
|
+
}
|
|
413
|
+
return [toClockDate(input)];
|
|
414
|
+
}
|
|
415
|
+
function toClockDate(value) {
|
|
416
|
+
if (value instanceof Date) {
|
|
417
|
+
return new Date(value.getTime());
|
|
418
|
+
}
|
|
419
|
+
if (typeof value === "number") {
|
|
420
|
+
if (!Number.isFinite(value)) {
|
|
421
|
+
throw new Error("Clock numeric value must be finite");
|
|
422
|
+
}
|
|
423
|
+
return new Date(value);
|
|
424
|
+
}
|
|
425
|
+
if (typeof value === "string") {
|
|
426
|
+
const parsed = Date.parse(value);
|
|
427
|
+
if (!Number.isFinite(parsed)) {
|
|
428
|
+
throw new Error(`Invalid clock string: ${value}`);
|
|
429
|
+
}
|
|
430
|
+
return new Date(parsed);
|
|
431
|
+
}
|
|
432
|
+
throw new Error("Invalid clock value");
|
|
433
|
+
}
|
|
434
|
+
function resolveClockStart(start) {
|
|
435
|
+
if (start === undefined) {
|
|
436
|
+
return DEFAULT_CLOCK_START_MS;
|
|
437
|
+
}
|
|
438
|
+
return toClockDate(start).getTime();
|
|
439
|
+
}
|
|
440
|
+
function encodeBase32(value, length) {
|
|
441
|
+
let remaining = Math.max(0, Math.floor(value));
|
|
442
|
+
let out = "";
|
|
443
|
+
while (out.length < length) {
|
|
444
|
+
const idx = remaining % 32;
|
|
445
|
+
out = CROCKFORD_BASE32[idx] + out;
|
|
446
|
+
remaining = Math.floor(remaining / 32);
|
|
447
|
+
}
|
|
448
|
+
return out.slice(-length);
|
|
449
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.readStateSnapshot = exports.readJournalSnapshot = exports.captureRunSnapshot = void 0;
|
|
18
|
+
__exportStar(require("./runHarness"), exports);
|
|
19
|
+
__exportStar(require("./deterministic"), exports);
|
|
20
|
+
var snapshots_1 = require("./snapshots");
|
|
21
|
+
Object.defineProperty(exports, "captureRunSnapshot", { enumerable: true, get: function () { return snapshots_1.captureRunSnapshot; } });
|
|
22
|
+
Object.defineProperty(exports, "readJournalSnapshot", { enumerable: true, get: function () { return snapshots_1.readJournalSnapshot; } });
|
|
23
|
+
Object.defineProperty(exports, "readStateSnapshot", { enumerable: true, get: function () { return snapshots_1.readStateSnapshot; } });
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { EffectAction, IterationMetadata, IterationResult, ProcessLogger, EffectSchedulerHints } from "../runtime/types";
|
|
2
|
+
import type { JsonRecord } from "../storage/types";
|
|
3
|
+
import type { DeterministicUlidHandle, FixedClockHandle } from "./deterministic";
|
|
4
|
+
export interface FakeActionSuccess {
|
|
5
|
+
status: "ok";
|
|
6
|
+
value?: unknown;
|
|
7
|
+
stdout?: string;
|
|
8
|
+
stderr?: string;
|
|
9
|
+
metadata?: JsonRecord;
|
|
10
|
+
startedAt?: string;
|
|
11
|
+
finishedAt?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface FakeActionError {
|
|
14
|
+
status: "error";
|
|
15
|
+
error: unknown;
|
|
16
|
+
stdout?: string;
|
|
17
|
+
stderr?: string;
|
|
18
|
+
metadata?: JsonRecord;
|
|
19
|
+
startedAt?: string;
|
|
20
|
+
finishedAt?: string;
|
|
21
|
+
}
|
|
22
|
+
export type FakeActionResolution = FakeActionSuccess | FakeActionError;
|
|
23
|
+
export type FakeActionResolver = ((action: EffectAction) => FakeActionResolution | undefined | Promise<FakeActionResolution | undefined>);
|
|
24
|
+
export interface RunToCompletionWithFakeRunnerOptions {
|
|
25
|
+
runDir: string;
|
|
26
|
+
resolve: FakeActionResolver;
|
|
27
|
+
maxIterations?: number;
|
|
28
|
+
logger?: ProcessLogger;
|
|
29
|
+
onIteration?: (iteration: IterationResult) => void | Promise<void>;
|
|
30
|
+
now?: Date | (() => Date);
|
|
31
|
+
clock?: FixedClockHandle;
|
|
32
|
+
ulids?: DeterministicUlidHandle;
|
|
33
|
+
}
|
|
34
|
+
export interface ExecutedFakeAction {
|
|
35
|
+
action: EffectAction;
|
|
36
|
+
resolution: FakeActionResolution;
|
|
37
|
+
}
|
|
38
|
+
export interface RunToCompletionResult {
|
|
39
|
+
status: "completed" | "failed" | "waiting";
|
|
40
|
+
output?: unknown;
|
|
41
|
+
error?: unknown;
|
|
42
|
+
pending?: EffectAction[];
|
|
43
|
+
metadata: IterationMetadata | null;
|
|
44
|
+
iterations: number;
|
|
45
|
+
executed: ExecutedFakeAction[];
|
|
46
|
+
executionLog: HarnessIterationLogEntry[];
|
|
47
|
+
}
|
|
48
|
+
export interface HarnessIterationLogEntry {
|
|
49
|
+
iteration: number;
|
|
50
|
+
status: IterationResult["status"];
|
|
51
|
+
metadata: IterationMetadata | null;
|
|
52
|
+
pending: HarnessActionSnapshot[];
|
|
53
|
+
executed: HarnessActionSnapshot[];
|
|
54
|
+
}
|
|
55
|
+
export interface HarnessActionSnapshot {
|
|
56
|
+
effectId: string;
|
|
57
|
+
invocationKey: string;
|
|
58
|
+
taskId?: string;
|
|
59
|
+
stepId?: string;
|
|
60
|
+
kind?: string;
|
|
61
|
+
schedulerHints?: EffectSchedulerHints;
|
|
62
|
+
}
|
|
63
|
+
export declare function runToCompletionWithFakeRunner(options: RunToCompletionWithFakeRunnerOptions): Promise<RunToCompletionResult>;
|
|
64
|
+
//# sourceMappingURL=runHarness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runHarness.d.ts","sourceRoot":"","sources":["../../src/testing/runHarness.ts"],"names":[],"mappings":"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"}
|