poe-code 4.0.69 → 4.0.70

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poe-code",
3
- "version": "4.0.69",
3
+ "version": "4.0.70",
4
4
  "description": "CLI tool to configure Poe API for developer workflows.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -8,9 +8,10 @@ export function createReplayableRandom(options = {}) {
8
8
  const hasLoopState = typeof snapshot?.loopIterations === "object" &&
9
9
  snapshot.loopIterations !== null &&
10
10
  Object.keys(snapshot.loopIterations).length > 0;
11
- const replaysFromStart = Array.isArray(snapshot?.pendingAwaits) &&
12
- snapshot.pendingAwaits.length > 0 &&
13
- (snapshot.replay !== undefined || !hasLoopState);
11
+ const replaysFromStart = snapshot?.replay !== undefined ||
12
+ (Array.isArray(snapshot?.pendingAwaits) &&
13
+ snapshot.pendingAwaits.length > 0 &&
14
+ !hasLoopState);
14
15
  initialState = replaysFromStart
15
16
  ? (saved.initialState ?? saved.seed)
16
17
  : (saved.resumeState ?? saved.state);
@@ -10,7 +10,7 @@ import { type InterpreterResult, type LoopIterationSnapshot } from "./interp/int
10
10
  import { type ModuleRegistry } from "./modules/registry.js";
11
11
  import { type OtelSink } from "./observability/otel.js";
12
12
  import type { SnapshotBackend } from "./snapshot/backend.js";
13
- import type { ReplayData } from "./snapshot/replay-data.js";
13
+ import { type ReplayData } from "./snapshot/replay-data.js";
14
14
  export type RunOptions = {
15
15
  bindings?: Record<string, CallerInjectedBinding>;
16
16
  budget?: Budget;
@@ -39,6 +39,7 @@ export type RunSnapshot = SafeJSSnapshot & {
39
39
  clock?: RunClockSnapshot;
40
40
  hostCalls?: HostCallRecord[];
41
41
  replay?: HostCallReplay;
42
+ replayError?: string;
42
43
  promiseReplay?: PromiseReplaySnapshot;
43
44
  initialInputs?: ReplayData;
44
45
  loopIterations?: Record<string, LoopIterationSnapshot>;
@@ -27,6 +27,7 @@ import { DUMP_FORMAT_VERSION } from "./snapshot/dump-format.js";
27
27
  import { createSnapshotScheduler } from "./snapshot/scheduler.js";
28
28
  import { UnsnapshotableValueError } from "./snapshot/serialize.js";
29
29
  import { prepareReplayInputs } from "./snapshot/replay-inputs.js";
30
+ import { MissingReplayCapabilityError } from "./snapshot/replay-data.js";
30
31
  export class UnhandledRejectionError extends Error {
31
32
  reason;
32
33
  constructor(reason, span) {
@@ -248,17 +249,32 @@ export function run(source, options = {}) {
248
249
  scope: executionScope,
249
250
  snapshot: interpreterSnapshot
250
251
  });
252
+ await throwIfReturnedPromiseRejected(result);
253
+ await throwIfUnhandledPromiseRejected(promiseTracker);
251
254
  await activeSnapshotScheduler.finish();
255
+ let replay;
256
+ let replayError;
257
+ try {
258
+ replay = hostCalls.snapshotReplay();
259
+ }
260
+ catch (error) {
261
+ if (!(error instanceof MissingReplayCapabilityError))
262
+ throw error;
263
+ replayError = error.message;
264
+ }
252
265
  const snapshot = createRunSnapshot({
253
266
  bindings: executionScope.snapshot().bindings,
254
267
  clock: options.clock,
255
268
  hostCalls: hostCalls.snapshot(),
269
+ replay,
270
+ initialInputs: initialInputs.snapshot,
271
+ promiseReplay: promiseReplay.snapshot(),
256
272
  random,
257
273
  sourceHash
258
274
  });
275
+ if (replayError !== undefined)
276
+ snapshot.replayError = replayError;
259
277
  dumpController.finalize(snapshot);
260
- await throwIfReturnedPromiseRejected(result);
261
- await throwIfUnhandledPromiseRejected(promiseTracker);
262
278
  return {
263
279
  ...result,
264
280
  snapshot
@@ -4,6 +4,13 @@ import { getSandboxArgumentEntries, isSandboxArguments } from "../interp/argumen
4
4
  import { serializeArguments } from "./arguments.js";
5
5
  const SKIP_VALUE = Symbol("SafeJS.skip-dump-value");
6
6
  export function serializeSafeJSSnapshot(snapshot) {
7
+ const replayError = Object.getOwnPropertyDescriptor(snapshot, "replayError");
8
+ if (replayError !== undefined) {
9
+ const reason = "value" in replayError && typeof replayError.value === "string"
10
+ ? replayError.value
11
+ : "missing resume capability";
12
+ throw new TypeError(`Snapshot is not replayable: ${reason}`);
13
+ }
7
14
  for (const [key, value] of getEnumerableDataEntries(snapshot)) {
8
15
  if (key !== "version" && key !== "sourceHash" && key !== "heap") {
9
16
  assertSnapshotGraphDepth(value, key);
@@ -140,7 +140,12 @@ export function dump(result) {
140
140
  return controller.requestSnapshot();
141
141
  }
142
142
  if (hasSnapshot(result)) {
143
- return Promise.resolve(serializeRunSnapshot(result.snapshot));
143
+ try {
144
+ return Promise.resolve(serializeRunSnapshot(result.snapshot));
145
+ }
146
+ catch (error) {
147
+ return Promise.reject(error);
148
+ }
144
149
  }
145
150
  return Promise.resolve(result).then((resolved) => {
146
151
  if (!hasSnapshot(resolved)) {
@@ -49,6 +49,8 @@ export type ReplayData = {
49
49
  root: Atom;
50
50
  nodes: DataNode[];
51
51
  };
52
+ export declare class MissingReplayCapabilityError extends TypeError {
53
+ }
52
54
  export declare function encodeReplayData(value: SandboxValue, options?: {
53
55
  identifyCapability?: (value: SandboxClosure, path: readonly string[]) => string | undefined;
54
56
  captureCapabilityProperties?: boolean;
@@ -2,6 +2,8 @@ import { MAX_DATA_DEPTH } from "../graph-depth.js";
2
2
  import { createSandboxArguments, createSandboxClosure, createSandboxMap, createSandboxRegex, createSandboxSet, isSandboxArguments, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet } from "../interp/values.js";
3
3
  import { serializeArguments } from "./arguments.js";
4
4
  import { validateArgumentsProperties, validateSnapshotData } from "./validation.js";
5
+ export class MissingReplayCapabilityError extends TypeError {
6
+ }
5
7
  export function encodeReplayData(value, options = {}) {
6
8
  const nodes = [];
7
9
  const seen = new WeakMap();
@@ -31,12 +33,12 @@ export function encodeReplayData(value, options = {}) {
31
33
  if (isSandboxClosure(entry)) {
32
34
  capabilityId = options.identifyCapability?.(entry, path);
33
35
  if (typeof capabilityId !== "string" || capabilityId.length === 0)
34
- throw new TypeError("A callable needs an explicit resume capability.");
36
+ throw new MissingReplayCapabilityError("A callable needs an explicit resume capability.");
35
37
  if (!options.captureCapabilityProperties)
36
38
  return { tag: "capability", id: capabilityId };
37
39
  }
38
40
  if (typeof entry !== "object" || isSandboxPromise(entry) || isSandboxGenerator(entry)) {
39
- throw new TypeError("A host result containing a callable or live execution state needs an explicit resume capability.");
41
+ throw new MissingReplayCapabilityError("A host result containing a callable or live execution state needs an explicit resume capability.");
40
42
  }
41
43
  const existing = seen.get(entry);
42
44
  if (existing !== undefined)
@@ -50,6 +50,13 @@ export function validateDumpEnvelope(snapshot) {
50
50
  fail("unsupportedVersion", "$.version", `expected ${DUMP_FORMAT_VERSION}`);
51
51
  }
52
52
  requireNonEmptyString(root.sourceHash, "$.sourceHash", limits);
53
+ const replayError = Object.getOwnPropertyDescriptor(root, "replayError");
54
+ if (replayError !== undefined) {
55
+ if (!("value" in replayError))
56
+ fail("invalidType", "$.replayError", "must be a data property");
57
+ const reason = requireNonEmptyString(replayError.value, "$.replayError", limits);
58
+ fail("invalidState", "$.replayError", `snapshot is not replayable: ${reason}`);
59
+ }
53
60
  const state = {
54
61
  allowFunctions: true,
55
62
  allowUndefined: true,