@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.
Files changed (169) hide show
  1. package/dist/cli/main.d.ts +5 -0
  2. package/dist/cli/main.d.ts.map +1 -0
  3. package/dist/cli/main.js +1343 -0
  4. package/dist/cli/nodeTaskRunner.d.ts +16 -0
  5. package/dist/cli/nodeTaskRunner.d.ts.map +1 -0
  6. package/dist/cli/nodeTaskRunner.js +46 -0
  7. package/dist/index.d.ts +10 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +25 -0
  10. package/dist/runner/env.d.ts +58 -0
  11. package/dist/runner/env.d.ts.map +1 -0
  12. package/dist/runner/env.js +113 -0
  13. package/dist/runner/index.d.ts +3 -0
  14. package/dist/runner/index.d.ts.map +1 -0
  15. package/dist/runner/index.js +18 -0
  16. package/dist/runner/nodeRunner.d.ts +60 -0
  17. package/dist/runner/nodeRunner.d.ts.map +1 -0
  18. package/dist/runner/nodeRunner.js +354 -0
  19. package/dist/runtime/commitEffectResult.d.ts +3 -0
  20. package/dist/runtime/commitEffectResult.d.ts.map +1 -0
  21. package/dist/runtime/commitEffectResult.js +172 -0
  22. package/dist/runtime/constants.d.ts +2 -0
  23. package/dist/runtime/constants.d.ts.map +1 -0
  24. package/dist/runtime/constants.js +5 -0
  25. package/dist/runtime/createRun.d.ts +3 -0
  26. package/dist/runtime/createRun.d.ts.map +1 -0
  27. package/dist/runtime/createRun.js +81 -0
  28. package/dist/runtime/errorUtils.d.ts +10 -0
  29. package/dist/runtime/errorUtils.d.ts.map +1 -0
  30. package/dist/runtime/errorUtils.js +42 -0
  31. package/dist/runtime/exceptions.d.ts +45 -0
  32. package/dist/runtime/exceptions.d.ts.map +1 -0
  33. package/dist/runtime/exceptions.js +99 -0
  34. package/dist/runtime/index.d.ts +12 -0
  35. package/dist/runtime/index.d.ts.map +1 -0
  36. package/dist/runtime/index.js +34 -0
  37. package/dist/runtime/instrumentation.d.ts +6 -0
  38. package/dist/runtime/instrumentation.d.ts.map +1 -0
  39. package/dist/runtime/instrumentation.js +14 -0
  40. package/dist/runtime/intrinsics/breakpoint.d.ts +4 -0
  41. package/dist/runtime/intrinsics/breakpoint.d.ts.map +1 -0
  42. package/dist/runtime/intrinsics/breakpoint.js +42 -0
  43. package/dist/runtime/intrinsics/index.d.ts +7 -0
  44. package/dist/runtime/intrinsics/index.d.ts.map +1 -0
  45. package/dist/runtime/intrinsics/index.js +15 -0
  46. package/dist/runtime/intrinsics/orchestratorTask.d.ts +4 -0
  47. package/dist/runtime/intrinsics/orchestratorTask.d.ts.map +1 -0
  48. package/dist/runtime/intrinsics/orchestratorTask.js +28 -0
  49. package/dist/runtime/intrinsics/parallel.d.ts +5 -0
  50. package/dist/runtime/intrinsics/parallel.d.ts.map +1 -0
  51. package/dist/runtime/intrinsics/parallel.js +45 -0
  52. package/dist/runtime/intrinsics/sleep.d.ts +4 -0
  53. package/dist/runtime/intrinsics/sleep.d.ts.map +1 -0
  54. package/dist/runtime/intrinsics/sleep.js +70 -0
  55. package/dist/runtime/intrinsics/task.d.ts +20 -0
  56. package/dist/runtime/intrinsics/task.d.ts.map +1 -0
  57. package/dist/runtime/intrinsics/task.js +237 -0
  58. package/dist/runtime/invocation/hashInvocationKey.d.ts +12 -0
  59. package/dist/runtime/invocation/hashInvocationKey.d.ts.map +1 -0
  60. package/dist/runtime/invocation/hashInvocationKey.js +12 -0
  61. package/dist/runtime/invocation/index.d.ts +3 -0
  62. package/dist/runtime/invocation/index.d.ts.map +1 -0
  63. package/dist/runtime/invocation/index.js +5 -0
  64. package/dist/runtime/orchestrateIteration.d.ts +3 -0
  65. package/dist/runtime/orchestrateIteration.d.ts.map +1 -0
  66. package/dist/runtime/orchestrateIteration.js +195 -0
  67. package/dist/runtime/processContext.d.ts +19 -0
  68. package/dist/runtime/processContext.d.ts.map +1 -0
  69. package/dist/runtime/processContext.js +55 -0
  70. package/dist/runtime/replay/createReplayEngine.d.ts +31 -0
  71. package/dist/runtime/replay/createReplayEngine.d.ts.map +1 -0
  72. package/dist/runtime/replay/createReplayEngine.js +82 -0
  73. package/dist/runtime/replay/effectIndex.d.ts +34 -0
  74. package/dist/runtime/replay/effectIndex.d.ts.map +1 -0
  75. package/dist/runtime/replay/effectIndex.js +241 -0
  76. package/dist/runtime/replay/index.d.ts +7 -0
  77. package/dist/runtime/replay/index.d.ts.map +1 -0
  78. package/dist/runtime/replay/index.js +19 -0
  79. package/dist/runtime/replay/replayCursor.d.ts +7 -0
  80. package/dist/runtime/replay/replayCursor.d.ts.map +1 -0
  81. package/dist/runtime/replay/replayCursor.js +22 -0
  82. package/dist/runtime/replay/stateCache.d.ts +48 -0
  83. package/dist/runtime/replay/stateCache.d.ts.map +1 -0
  84. package/dist/runtime/replay/stateCache.js +211 -0
  85. package/dist/runtime/types.d.ts +147 -0
  86. package/dist/runtime/types.d.ts.map +1 -0
  87. package/dist/runtime/types.js +2 -0
  88. package/dist/storage/atomic.d.ts +2 -0
  89. package/dist/storage/atomic.d.ts.map +1 -0
  90. package/dist/storage/atomic.js +54 -0
  91. package/dist/storage/cleanup.d.ts +4 -0
  92. package/dist/storage/cleanup.d.ts.map +1 -0
  93. package/dist/storage/cleanup.js +96 -0
  94. package/dist/storage/clock.d.ts +6 -0
  95. package/dist/storage/clock.d.ts.map +1 -0
  96. package/dist/storage/clock.js +29 -0
  97. package/dist/storage/createRunDir.d.ts +6 -0
  98. package/dist/storage/createRunDir.d.ts.map +1 -0
  99. package/dist/storage/createRunDir.js +59 -0
  100. package/dist/storage/index.d.ts +9 -0
  101. package/dist/storage/index.d.ts.map +1 -0
  102. package/dist/storage/index.js +28 -0
  103. package/dist/storage/journal.d.ts +4 -0
  104. package/dist/storage/journal.d.ts.map +1 -0
  105. package/dist/storage/journal.js +103 -0
  106. package/dist/storage/lock.d.ts +5 -0
  107. package/dist/storage/lock.d.ts.map +1 -0
  108. package/dist/storage/lock.js +41 -0
  109. package/dist/storage/paths.d.ts +19 -0
  110. package/dist/storage/paths.d.ts.map +1 -0
  111. package/dist/storage/paths.js +46 -0
  112. package/dist/storage/runFiles.d.ts +5 -0
  113. package/dist/storage/runFiles.d.ts.map +1 -0
  114. package/dist/storage/runFiles.js +39 -0
  115. package/dist/storage/snapshotState.d.ts +10 -0
  116. package/dist/storage/snapshotState.d.ts.map +1 -0
  117. package/dist/storage/snapshotState.js +15 -0
  118. package/dist/storage/storeTaskArtifacts.d.ts +6 -0
  119. package/dist/storage/storeTaskArtifacts.d.ts.map +1 -0
  120. package/dist/storage/storeTaskArtifacts.js +58 -0
  121. package/dist/storage/tasks.d.ts +17 -0
  122. package/dist/storage/tasks.d.ts.map +1 -0
  123. package/dist/storage/tasks.js +82 -0
  124. package/dist/storage/types.d.ts +112 -0
  125. package/dist/storage/types.d.ts.map +1 -0
  126. package/dist/storage/types.js +2 -0
  127. package/dist/storage/ulids.d.ts +11 -0
  128. package/dist/storage/ulids.d.ts.map +1 -0
  129. package/dist/storage/ulids.js +25 -0
  130. package/dist/tasks/batching.d.ts +29 -0
  131. package/dist/tasks/batching.d.ts.map +1 -0
  132. package/dist/tasks/batching.js +66 -0
  133. package/dist/tasks/context.d.ts +11 -0
  134. package/dist/tasks/context.d.ts.map +1 -0
  135. package/dist/tasks/context.js +181 -0
  136. package/dist/tasks/defineTask.d.ts +9 -0
  137. package/dist/tasks/defineTask.d.ts.map +1 -0
  138. package/dist/tasks/defineTask.js +58 -0
  139. package/dist/tasks/index.d.ts +8 -0
  140. package/dist/tasks/index.d.ts.map +1 -0
  141. package/dist/tasks/index.js +23 -0
  142. package/dist/tasks/kinds/index.d.ts +7 -0
  143. package/dist/tasks/kinds/index.d.ts.map +1 -0
  144. package/dist/tasks/kinds/index.js +333 -0
  145. package/dist/tasks/registry.d.ts +53 -0
  146. package/dist/tasks/registry.d.ts.map +1 -0
  147. package/dist/tasks/registry.js +145 -0
  148. package/dist/tasks/serializer.d.ts +60 -0
  149. package/dist/tasks/serializer.d.ts.map +1 -0
  150. package/dist/tasks/serializer.js +193 -0
  151. package/dist/tasks/types.d.ts +148 -0
  152. package/dist/tasks/types.d.ts.map +1 -0
  153. package/dist/tasks/types.js +2 -0
  154. package/dist/test-fixtures/kinds/index.d.ts +56 -0
  155. package/dist/test-fixtures/kinds/index.d.ts.map +1 -0
  156. package/dist/test-fixtures/kinds/index.js +44 -0
  157. package/dist/testing/deterministic.d.ts +90 -0
  158. package/dist/testing/deterministic.d.ts.map +1 -0
  159. package/dist/testing/deterministic.js +449 -0
  160. package/dist/testing/index.d.ts +4 -0
  161. package/dist/testing/index.d.ts.map +1 -0
  162. package/dist/testing/index.js +23 -0
  163. package/dist/testing/runHarness.d.ts +64 -0
  164. package/dist/testing/runHarness.d.ts.map +1 -0
  165. package/dist/testing/runHarness.js +161 -0
  166. package/dist/testing/snapshots.d.ts +17 -0
  167. package/dist/testing/snapshots.d.ts.map +1 -0
  168. package/dist/testing/snapshots.js +24 -0
  169. package/package.json +35 -0
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createReplayEngine = createReplayEngine;
4
+ const runFiles_1 = require("../../storage/runFiles");
5
+ const effectIndex_1 = require("./effectIndex");
6
+ const replayCursor_1 = require("./replayCursor");
7
+ const processContext_1 = require("../processContext");
8
+ const constants_1 = require("../constants");
9
+ const exceptions_1 = require("../exceptions");
10
+ const stateCache_1 = require("./stateCache");
11
+ async function createReplayEngine(options) {
12
+ const metadata = await (0, runFiles_1.readRunMetadata)(options.runDir);
13
+ ensureCompatibleLayout(metadata.layoutVersion, options.runDir);
14
+ const inputs = await (0, runFiles_1.readRunInputs)(options.runDir);
15
+ const effectIndex = await (0, effectIndex_1.buildEffectIndex)({ runDir: options.runDir });
16
+ const { snapshot: stateCacheSnapshot, rebuildMeta: stateRebuild } = await resolveStateCacheSnapshot({
17
+ runDir: options.runDir,
18
+ effectIndex,
19
+ });
20
+ const replayCursor = new replayCursor_1.ReplayCursor();
21
+ const processId = metadata.processId ?? metadata.request ?? metadata.runId;
22
+ const { context, internalContext } = (0, processContext_1.createProcessContext)({
23
+ runId: metadata.runId,
24
+ runDir: options.runDir,
25
+ processId,
26
+ effectIndex,
27
+ replayCursor,
28
+ now: options.now,
29
+ logger: options.logger,
30
+ });
31
+ return {
32
+ runId: metadata.runId,
33
+ runDir: options.runDir,
34
+ metadata,
35
+ inputs,
36
+ effectIndex,
37
+ replayCursor,
38
+ context,
39
+ internalContext,
40
+ stateCache: stateCacheSnapshot,
41
+ stateRebuild,
42
+ };
43
+ }
44
+ async function resolveStateCacheSnapshot({ runDir, effectIndex, }) {
45
+ let existingSnapshot = null;
46
+ let corrupted = false;
47
+ try {
48
+ existingSnapshot = await (0, stateCache_1.readStateCache)(runDir);
49
+ }
50
+ catch {
51
+ corrupted = true;
52
+ }
53
+ if (corrupted || !existingSnapshot) {
54
+ const reason = corrupted ? "corrupt_cache" : "missing_cache";
55
+ const rebuilt = await (0, stateCache_1.rebuildStateCache)(runDir, { effectIndex, reason });
56
+ return { snapshot: rebuilt, rebuildMeta: { reason, previous: null } };
57
+ }
58
+ const journalHead = effectIndex.getJournalHead() ?? null;
59
+ if (!(0, stateCache_1.journalHeadsEqual)(existingSnapshot.journalHead, journalHead)) {
60
+ const rebuilt = await (0, stateCache_1.rebuildStateCache)(runDir, {
61
+ effectIndex,
62
+ reason: "journal_mismatch",
63
+ });
64
+ return {
65
+ snapshot: rebuilt,
66
+ rebuildMeta: { reason: "journal_mismatch", previous: existingSnapshot.journalHead ?? null },
67
+ };
68
+ }
69
+ return { snapshot: existingSnapshot, rebuildMeta: null };
70
+ }
71
+ function ensureCompatibleLayout(layoutVersion, runDir) {
72
+ if (!layoutVersion) {
73
+ throw new exceptions_1.RunFailedError("Run metadata is missing layoutVersion", { runDir });
74
+ }
75
+ if (layoutVersion !== constants_1.replaySchemaVersion) {
76
+ throw new exceptions_1.RunFailedError("Run layout version is not supported by this runtime", {
77
+ expected: constants_1.replaySchemaVersion,
78
+ actual: layoutVersion,
79
+ runDir,
80
+ });
81
+ }
82
+ }
@@ -0,0 +1,34 @@
1
+ import { JournalEvent } from "../../storage/types";
2
+ import { EffectRecord } from "../types";
3
+ export interface BuildEffectIndexOptions {
4
+ runDir: string;
5
+ events?: JournalEvent[];
6
+ }
7
+ export declare class EffectIndex {
8
+ private readonly runDir;
9
+ private readonly byInvocation;
10
+ private readonly byEffectId;
11
+ private journalHead?;
12
+ private initialized;
13
+ private constructor();
14
+ static build(options: BuildEffectIndexOptions): Promise<EffectIndex>;
15
+ private applyEvents;
16
+ applyEvent(event: JournalEvent, expectedSeq?: number): void;
17
+ getByInvocation(invocationKey: string): EffectRecord | undefined;
18
+ getByEffectId(effectId: string): EffectRecord | undefined;
19
+ listEffects(): EffectRecord[];
20
+ listPendingEffects(): EffectRecord[];
21
+ getJournalHead(): {
22
+ seq: number;
23
+ ulid: string;
24
+ } | undefined;
25
+ private validateSequence;
26
+ private handleEffectRequested;
27
+ private handleEffectResolved;
28
+ private expectObject;
29
+ private expectString;
30
+ private expectOptionalString;
31
+ private normalizeLabelArray;
32
+ }
33
+ export declare function buildEffectIndex(options: BuildEffectIndexOptions): Promise<EffectIndex>;
34
+ //# sourceMappingURL=effectIndex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effectIndex.d.ts","sourceRoot":"","sources":["../../../src/runtime/replay/effectIndex.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,YAAY,EAAuC,MAAM,UAAU,CAAC;AAG7E,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC;CACzB;AA0BD,qBAAa,WAAW;IAMF,OAAO,CAAC,QAAQ,CAAC,MAAM;IAL3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAmC;IAChE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmC;IAC9D,OAAO,CAAC,WAAW,CAAC,CAAgC;IACpD,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO;WAEM,KAAK,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC;IAQ1E,OAAO,CAAC,WAAW;IAOnB,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE,MAAM;IAsBpD,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIhE,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIzD,WAAW,IAAI,YAAY,EAAE;IAI7B,kBAAkB,IAAI,YAAY,EAAE;IAIpC,cAAc;aA1De,MAAM;cAAQ,MAAM;;IA8DjD,OAAO,CAAC,gBAAgB;IA2CxB,OAAO,CAAC,qBAAqB;IAmC7B,OAAO,CAAC,oBAAoB;IAoC5B,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,mBAAmB;CAkB5B;AA2BD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC,CAE7F"}
@@ -0,0 +1,241 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EffectIndex = void 0;
4
+ exports.buildEffectIndex = buildEffectIndex;
5
+ const journal_1 = require("../../storage/journal");
6
+ const exceptions_1 = require("../exceptions");
7
+ const errorUtils_1 = require("../errorUtils");
8
+ class EffectIndex {
9
+ runDir;
10
+ byInvocation = new Map();
11
+ byEffectId = new Map();
12
+ journalHead;
13
+ initialized = false;
14
+ constructor(runDir) {
15
+ this.runDir = runDir;
16
+ }
17
+ static async build(options) {
18
+ const events = options.events ?? (await loadJournalSafe(options.runDir));
19
+ const index = new EffectIndex(options.runDir);
20
+ index.applyEvents(events);
21
+ index.initialized = true;
22
+ return index;
23
+ }
24
+ applyEvents(events) {
25
+ events.forEach((event, idx) => {
26
+ const expectedSeq = idx + 1;
27
+ this.applyEvent(event, expectedSeq);
28
+ });
29
+ }
30
+ applyEvent(event, expectedSeq) {
31
+ this.validateSequence(event, expectedSeq);
32
+ const type = event.type;
33
+ switch (type) {
34
+ case "RUN_CREATED":
35
+ case "RUN_COMPLETED":
36
+ case "RUN_FAILED":
37
+ return;
38
+ case "EFFECT_REQUESTED":
39
+ this.handleEffectRequested(event);
40
+ return;
41
+ case "EFFECT_RESOLVED":
42
+ this.handleEffectResolved(event);
43
+ return;
44
+ default:
45
+ throw new exceptions_1.RunFailedError(`Unknown journal event type '${event.type}'`, {
46
+ path: event.path,
47
+ seq: event.seq,
48
+ });
49
+ }
50
+ }
51
+ getByInvocation(invocationKey) {
52
+ return this.byInvocation.get(invocationKey);
53
+ }
54
+ getByEffectId(effectId) {
55
+ return this.byEffectId.get(effectId);
56
+ }
57
+ listEffects() {
58
+ return Array.from(this.byEffectId.values());
59
+ }
60
+ listPendingEffects() {
61
+ return this.listEffects().filter((record) => record.status === "requested");
62
+ }
63
+ getJournalHead() {
64
+ return this.journalHead;
65
+ }
66
+ validateSequence(event, expectedSeq) {
67
+ if (!Number.isFinite(event.seq) || event.seq <= 0) {
68
+ throw new exceptions_1.RunFailedError(`Invalid journal sequence number in ${event.filename}`, {
69
+ path: event.path,
70
+ });
71
+ }
72
+ if (typeof event.ulid !== "string" || !event.ulid) {
73
+ throw new exceptions_1.RunFailedError(`Invalid ULID on journal event ${event.filename}`, {
74
+ path: event.path,
75
+ });
76
+ }
77
+ if (!this.journalHead) {
78
+ if (event.seq !== (expectedSeq ?? 1)) {
79
+ throw new exceptions_1.RunFailedError(`Journal seq mismatch at ${event.filename} (expected 1, got ${event.seq})`, {
80
+ path: event.path,
81
+ });
82
+ }
83
+ this.journalHead = { seq: event.seq, ulid: event.ulid };
84
+ return;
85
+ }
86
+ const nextSeq = this.journalHead.seq + 1;
87
+ const shouldMatch = expectedSeq ?? nextSeq;
88
+ if (event.seq !== shouldMatch) {
89
+ throw new exceptions_1.RunFailedError(`Journal sequence gap detected at ${event.filename} (expected ${shouldMatch}, got ${event.seq})`, { path: event.path });
90
+ }
91
+ if (event.seq <= this.journalHead.seq) {
92
+ throw new exceptions_1.RunFailedError(`Journal sequence regression at ${event.filename} (prev ${this.journalHead.seq}, got ${event.seq})`, { path: event.path });
93
+ }
94
+ if (event.ulid <= this.journalHead.ulid) {
95
+ throw new exceptions_1.RunFailedError(`Journal ULID order regression at ${event.filename} (${event.ulid} <= ${this.journalHead.ulid})`, { path: event.path });
96
+ }
97
+ this.journalHead = { seq: event.seq, ulid: event.ulid };
98
+ }
99
+ handleEffectRequested(event) {
100
+ const payload = this.expectObject(event, "EFFECT_REQUESTED");
101
+ const effectId = this.expectString(payload.effectId, "effectId", event);
102
+ const invocationKey = this.expectString(payload.invocationKey, "invocationKey", event);
103
+ const stepId = this.expectString(payload.stepId, "stepId", event);
104
+ const taskId = this.expectString(payload.taskId, "taskId", event);
105
+ const taskDefRef = this.expectString(payload.taskDefRef, "taskDefRef", event);
106
+ const inputsRef = this.expectOptionalString(payload.inputsRef, "inputsRef", event);
107
+ const labels = this.normalizeLabelArray(payload.labels, event);
108
+ if (this.byEffectId.has(effectId)) {
109
+ throw new exceptions_1.RunFailedError(`Duplicate effectId detected: ${effectId}`, { path: event.path });
110
+ }
111
+ if (this.byInvocation.has(invocationKey)) {
112
+ throw new exceptions_1.RunFailedError(`Duplicate invocation key detected: ${invocationKey}`, {
113
+ path: event.path,
114
+ });
115
+ }
116
+ const record = {
117
+ effectId,
118
+ invocationKey,
119
+ invocationHash: payload.invocationHash,
120
+ stepId,
121
+ taskId,
122
+ status: "requested",
123
+ kind: payload.kind,
124
+ label: payload.label,
125
+ labels,
126
+ taskDefRef,
127
+ inputsRef,
128
+ requestedAt: event.recordedAt,
129
+ };
130
+ this.byInvocation.set(record.invocationKey, record);
131
+ this.byEffectId.set(record.effectId, record);
132
+ }
133
+ handleEffectResolved(event) {
134
+ const payload = this.expectObject(event, "EFFECT_RESOLVED");
135
+ const effectId = this.expectString(payload.effectId, "effectId", event);
136
+ if (!payload.status) {
137
+ throw new exceptions_1.RunFailedError("Malformed EFFECT_RESOLVED event missing status", { path: event.path });
138
+ }
139
+ if (payload.status !== "ok" && payload.status !== "error") {
140
+ throw new exceptions_1.RunFailedError(`Unknown EFFECT_RESOLVED status '${payload.status}'`, { path: event.path });
141
+ }
142
+ if (payload.resultRef && typeof payload.resultRef !== "string") {
143
+ throw new exceptions_1.RunFailedError("Malformed EFFECT_RESOLVED event resultRef", { path: event.path });
144
+ }
145
+ if (payload.stdoutRef && typeof payload.stdoutRef !== "string") {
146
+ throw new exceptions_1.RunFailedError("Malformed EFFECT_RESOLVED stdoutRef", { path: event.path });
147
+ }
148
+ if (payload.stderrRef && typeof payload.stderrRef !== "string") {
149
+ throw new exceptions_1.RunFailedError("Malformed EFFECT_RESOLVED stderrRef", { path: event.path });
150
+ }
151
+ const record = this.byEffectId.get(effectId);
152
+ if (!record) {
153
+ throw new exceptions_1.RunFailedError(`EFFECT_RESOLVED references unknown effectId ${effectId}`, {
154
+ path: event.path,
155
+ });
156
+ }
157
+ if (record.status !== "requested") {
158
+ throw new exceptions_1.RunFailedError(`Effect ${effectId} already resolved`, { path: event.path });
159
+ }
160
+ const status = payload.status === "ok" ? "resolved_ok" : "resolved_error";
161
+ record.status = status;
162
+ record.resultRef = payload.resultRef;
163
+ record.error = payload.error;
164
+ record.stdoutRef = payload.stdoutRef;
165
+ record.stderrRef = payload.stderrRef;
166
+ record.resolvedAt = event.recordedAt;
167
+ }
168
+ expectObject(event, type) {
169
+ if (!event?.data || typeof event.data !== "object") {
170
+ throw new exceptions_1.RunFailedError(`Malformed ${type} event payload`, { path: event.path });
171
+ }
172
+ return event.data;
173
+ }
174
+ expectString(value, field, event) {
175
+ if (typeof value !== "string" || value.length === 0) {
176
+ throw new exceptions_1.RunFailedError(`Malformed journal event missing ${field}`, {
177
+ path: event.path,
178
+ });
179
+ }
180
+ return value;
181
+ }
182
+ expectOptionalString(value, field, event) {
183
+ if (value === undefined)
184
+ return undefined;
185
+ if (typeof value !== "string" || value.length === 0) {
186
+ throw new exceptions_1.RunFailedError(`Malformed journal event ${field}`, {
187
+ path: event.path,
188
+ });
189
+ }
190
+ return value;
191
+ }
192
+ normalizeLabelArray(value, event) {
193
+ if (value === undefined)
194
+ return undefined;
195
+ if (!Array.isArray(value)) {
196
+ throw new exceptions_1.RunFailedError("Malformed EFFECT_REQUESTED labels payload", { path: event.path });
197
+ }
198
+ const seen = new Set();
199
+ const labels = [];
200
+ for (const entry of value) {
201
+ if (typeof entry !== "string") {
202
+ throw new exceptions_1.RunFailedError("Malformed EFFECT_REQUESTED labels entry", { path: event.path });
203
+ }
204
+ const trimmed = entry.trim();
205
+ if (!trimmed || seen.has(trimmed))
206
+ continue;
207
+ seen.add(trimmed);
208
+ labels.push(trimmed);
209
+ }
210
+ return labels.length ? labels : undefined;
211
+ }
212
+ }
213
+ exports.EffectIndex = EffectIndex;
214
+ async function loadJournalSafe(runDir) {
215
+ try {
216
+ return await (0, journal_1.loadJournal)(runDir);
217
+ }
218
+ catch (error) {
219
+ throw normalizeJournalError(error, runDir);
220
+ }
221
+ }
222
+ function normalizeJournalError(error, runDir) {
223
+ if (error instanceof exceptions_1.RunFailedError)
224
+ return error;
225
+ const err = error;
226
+ if (err?.code === "JOURNAL_PARSE_FAILED") {
227
+ return new exceptions_1.RunFailedError("Failed to parse journal event", {
228
+ path: err.path,
229
+ runDir,
230
+ error: err.message,
231
+ });
232
+ }
233
+ const serialized = (0, errorUtils_1.serializeUnknownError)(err);
234
+ return new exceptions_1.RunFailedError("Failed to load journal for replay", {
235
+ runDir,
236
+ error: serialized,
237
+ });
238
+ }
239
+ async function buildEffectIndex(options) {
240
+ return EffectIndex.build(options);
241
+ }
@@ -0,0 +1,7 @@
1
+ export { ReplayCursor } from "./replayCursor";
2
+ export { EffectIndex, buildEffectIndex } from "./effectIndex";
3
+ export { createReplayEngine } from "./createReplayEngine";
4
+ export type { ReplayEngine, CreateReplayEngineOptions } from "./createReplayEngine";
5
+ export { STATE_CACHE_SCHEMA_VERSION, createStateCacheSnapshot, journalHeadsEqual, normalizeJournalHead, normalizeSnapshot, readStateCache, rebuildStateCache, writeStateCache, } from "./stateCache";
6
+ export type { StateCacheSnapshot, StateCacheJournalHead, DerivedEffectSummary } from "./stateCache";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/replay/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,EACxB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.writeStateCache = exports.rebuildStateCache = exports.readStateCache = exports.normalizeSnapshot = exports.normalizeJournalHead = exports.journalHeadsEqual = exports.createStateCacheSnapshot = exports.STATE_CACHE_SCHEMA_VERSION = exports.createReplayEngine = exports.buildEffectIndex = exports.EffectIndex = exports.ReplayCursor = void 0;
4
+ var replayCursor_1 = require("./replayCursor");
5
+ Object.defineProperty(exports, "ReplayCursor", { enumerable: true, get: function () { return replayCursor_1.ReplayCursor; } });
6
+ var effectIndex_1 = require("./effectIndex");
7
+ Object.defineProperty(exports, "EffectIndex", { enumerable: true, get: function () { return effectIndex_1.EffectIndex; } });
8
+ Object.defineProperty(exports, "buildEffectIndex", { enumerable: true, get: function () { return effectIndex_1.buildEffectIndex; } });
9
+ var createReplayEngine_1 = require("./createReplayEngine");
10
+ Object.defineProperty(exports, "createReplayEngine", { enumerable: true, get: function () { return createReplayEngine_1.createReplayEngine; } });
11
+ var stateCache_1 = require("./stateCache");
12
+ Object.defineProperty(exports, "STATE_CACHE_SCHEMA_VERSION", { enumerable: true, get: function () { return stateCache_1.STATE_CACHE_SCHEMA_VERSION; } });
13
+ Object.defineProperty(exports, "createStateCacheSnapshot", { enumerable: true, get: function () { return stateCache_1.createStateCacheSnapshot; } });
14
+ Object.defineProperty(exports, "journalHeadsEqual", { enumerable: true, get: function () { return stateCache_1.journalHeadsEqual; } });
15
+ Object.defineProperty(exports, "normalizeJournalHead", { enumerable: true, get: function () { return stateCache_1.normalizeJournalHead; } });
16
+ Object.defineProperty(exports, "normalizeSnapshot", { enumerable: true, get: function () { return stateCache_1.normalizeSnapshot; } });
17
+ Object.defineProperty(exports, "readStateCache", { enumerable: true, get: function () { return stateCache_1.readStateCache; } });
18
+ Object.defineProperty(exports, "rebuildStateCache", { enumerable: true, get: function () { return stateCache_1.rebuildStateCache; } });
19
+ Object.defineProperty(exports, "writeStateCache", { enumerable: true, get: function () { return stateCache_1.writeStateCache; } });
@@ -0,0 +1,7 @@
1
+ export declare class ReplayCursor {
2
+ private counter;
3
+ nextStepId(): string;
4
+ peekNextStepId(): string;
5
+ get value(): number;
6
+ }
7
+ //# sourceMappingURL=replayCursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replayCursor.d.ts","sourceRoot":"","sources":["../../../src/runtime/replay/replayCursor.ts"],"names":[],"mappings":"AAGA,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAK;IAEpB,UAAU,IAAI,MAAM;IAKpB,cAAc,IAAI,MAAM;IAIxB,IAAI,KAAK,IAAI,MAAM,CAElB;CACF"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReplayCursor = void 0;
4
+ const STEP_PREFIX = "S";
5
+ const STEP_WIDTH = 6;
6
+ class ReplayCursor {
7
+ counter = 0;
8
+ nextStepId() {
9
+ this.counter += 1;
10
+ return formatStepId(this.counter);
11
+ }
12
+ peekNextStepId() {
13
+ return formatStepId(this.counter + 1);
14
+ }
15
+ get value() {
16
+ return this.counter;
17
+ }
18
+ }
19
+ exports.ReplayCursor = ReplayCursor;
20
+ function formatStepId(value) {
21
+ return `${STEP_PREFIX}${Math.max(value, 0).toString().padStart(STEP_WIDTH, "0")}`;
22
+ }
@@ -0,0 +1,48 @@
1
+ import { EffectIndex } from "./effectIndex";
2
+ import { EffectStatus } from "../types";
3
+ export declare const STATE_CACHE_SCHEMA_VERSION = "2026.01.state-cache";
4
+ export interface StateCacheJournalHead {
5
+ seq: number;
6
+ ulid: string;
7
+ checksum?: string;
8
+ }
9
+ export interface DerivedEffectSummary {
10
+ effectId: string;
11
+ invocationKey: string;
12
+ status: EffectStatus;
13
+ kind?: string;
14
+ label?: string;
15
+ taskId?: string;
16
+ stepId?: string;
17
+ requestedAt?: string;
18
+ resolvedAt?: string;
19
+ }
20
+ export interface StateCacheSnapshot {
21
+ schemaVersion: string;
22
+ savedAt: string;
23
+ journalHead?: StateCacheJournalHead | null;
24
+ stateVersion: number;
25
+ effectsByInvocation: Record<string, DerivedEffectSummary>;
26
+ pendingEffectsByKind: Record<string, number>;
27
+ rebuildReason?: string | null;
28
+ }
29
+ export interface CreateStateCacheSnapshotOptions {
30
+ journalHead?: StateCacheJournalHead | null;
31
+ savedAt?: string;
32
+ schemaVersion?: string;
33
+ stateVersion?: number;
34
+ effectsByInvocation?: Record<string, DerivedEffectSummary>;
35
+ pendingEffectsByKind?: Record<string, number>;
36
+ rebuildReason?: string | null;
37
+ }
38
+ export declare function readStateCache(runDir: string): Promise<StateCacheSnapshot | null>;
39
+ export declare function writeStateCache(runDir: string, snapshot: StateCacheSnapshot): Promise<void>;
40
+ export declare function journalHeadsEqual(a?: StateCacheJournalHead | null, b?: StateCacheJournalHead | null): boolean;
41
+ export declare function createStateCacheSnapshot(journalHeadOrOptions?: StateCacheJournalHead | null | CreateStateCacheSnapshotOptions): StateCacheSnapshot;
42
+ export declare function normalizeJournalHead(raw: unknown): StateCacheJournalHead | null | undefined;
43
+ export declare function normalizeSnapshot(raw: unknown): StateCacheSnapshot;
44
+ export declare function rebuildStateCache(runDir: string, opts?: {
45
+ effectIndex?: EffectIndex;
46
+ reason?: string;
47
+ }): Promise<StateCacheSnapshot>;
48
+ //# sourceMappingURL=stateCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateCache.d.ts","sourceRoot":"","sources":["../../../src/runtime/replay/stateCache.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAoB,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAgB,YAAY,EAAE,MAAM,UAAU,CAAC;AAGtD,eAAO,MAAM,0BAA0B,wBAAwB,CAAC;AAEhE,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAC1D,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,+BAA+B;IAC9C,WAAW,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAC3D,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAavF;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAKjG;AAED,wBAAgB,iBAAiB,CAC/B,CAAC,CAAC,EAAE,qBAAqB,GAAG,IAAI,EAChC,CAAC,CAAC,EAAE,qBAAqB,GAAG,IAAI,GAC/B,OAAO,CAMT;AAED,wBAAgB,wBAAwB,CACtC,oBAAoB,CAAC,EAAE,qBAAqB,GAAG,IAAI,GAAG,+BAA+B,GACpF,kBAAkB,CAcpB;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,qBAAqB,GAAG,IAAI,GAAG,SAAS,CAU3F;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CA2BlE;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,WAAW,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACpD,OAAO,CAAC,kBAAkB,CAAC,CAmB7B"}