poe-code 10.0.3 → 11.0.0
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/commands/harness.js +27 -1
- package/dist/cli/commands/harness.js.map +1 -1
- package/dist/index.js +1125 -888
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/agent-harness/dist/loader/run.js +4 -1
- package/packages/safejs/dist/chunks/{chunk-MRH5YDMR.js → chunk-ARFGEQTM.js} +213 -51
- package/packages/safejs/dist/chunks/chunk-ARFGEQTM.js.map +7 -0
- package/packages/safejs/dist/chunks/{chunk-A2XBEN3H.js → chunk-DKXGPEOM.js} +182 -133
- package/packages/safejs/dist/chunks/{chunk-A2XBEN3H.js.map → chunk-DKXGPEOM.js.map} +3 -3
- package/packages/safejs/dist/cli.js +51 -2
- package/packages/safejs/dist/cli.js.map +2 -2
- package/packages/safejs/dist/core.js +1 -1
- package/packages/safejs/dist/index.d.ts +3 -0
- package/packages/safejs/dist/index.js +8 -2
- package/packages/safejs/dist/index.js.map +1 -1
- package/packages/safejs/dist/interp/interpreter.js +73 -127
- package/packages/safejs/dist/interp/scope.js +3 -3
- package/packages/safejs/dist/migrate.d.ts +33 -0
- package/packages/safejs/dist/migrate.js +70 -0
- package/packages/safejs/dist/migration-file.d.ts +55 -0
- package/packages/safejs/dist/migration-file.js +79 -0
- package/packages/safejs/dist/restore.d.ts +2 -0
- package/packages/safejs/dist/restore.js +2 -0
- package/packages/safejs/dist/run.js +18 -2
- package/packages/safejs/dist/snapshot/dump-format.d.ts +1 -1
- package/packages/safejs/dist/snapshot/dump-format.js +1 -1
- package/packages/safejs/dist/snapshot/migration.d.ts +34 -0
- package/packages/safejs/dist/snapshot/migration.js +92 -0
- package/packages/safejs/dist/snapshot/validation.js +0 -4
- package/packages/safejs/dist/chunks/chunk-MRH5YDMR.js.map +0 -7
|
@@ -28,7 +28,7 @@ import { DUMP_FORMAT_VERSION, EXECUTION_SEMANTICS } from "./snapshot/dump-format
|
|
|
28
28
|
import { createSnapshotScheduler } from "./snapshot/scheduler.js";
|
|
29
29
|
import { UnsnapshotableValueError } from "./snapshot/serialize.js";
|
|
30
30
|
import { prepareReplayInputs } from "./snapshot/replay-inputs.js";
|
|
31
|
-
import { MissingReplayCapabilityError } from "./snapshot/replay-data.js";
|
|
31
|
+
import { decodeReplayData, MissingReplayCapabilityError } from "./snapshot/replay-data.js";
|
|
32
32
|
export class UnhandledRejectionError extends Error {
|
|
33
33
|
reason;
|
|
34
34
|
constructor(reason, span) {
|
|
@@ -122,6 +122,17 @@ export function run(source, options = {}) {
|
|
|
122
122
|
}),
|
|
123
123
|
...createRegexGlobals()
|
|
124
124
|
};
|
|
125
|
+
const importMeta = deepCopyToSandbox(options.importMeta ?? {});
|
|
126
|
+
if (restoredSnapshot?.migration !== undefined) {
|
|
127
|
+
if (Object.hasOwn(importMeta, "migration"))
|
|
128
|
+
throw new TypeError("import.meta.migration is reserved for migrated checkpoint state.");
|
|
129
|
+
Object.defineProperty(importMeta, "migration", {
|
|
130
|
+
value: decodeReplayData(restoredSnapshot.migration.state),
|
|
131
|
+
enumerable: true,
|
|
132
|
+
configurable: true,
|
|
133
|
+
writable: true
|
|
134
|
+
});
|
|
135
|
+
}
|
|
125
136
|
const initialInputs = prepareReplayInputs({
|
|
126
137
|
bindings: callerBindings,
|
|
127
138
|
imports: resolveModuleImports(module, options.modules, {
|
|
@@ -133,7 +144,7 @@ export function run(source, options = {}) {
|
|
|
133
144
|
entryPointArgs: options.entryPointArgs === undefined
|
|
134
145
|
? undefined
|
|
135
146
|
: deepCopyToSandbox([...options.entryPointArgs]),
|
|
136
|
-
importMeta
|
|
147
|
+
importMeta
|
|
137
148
|
}, restoredSnapshot?.initialInputs, (promise, id) => {
|
|
138
149
|
if (promise !== undefined)
|
|
139
150
|
observeSandboxPromise(promise);
|
|
@@ -173,6 +184,7 @@ export function run(source, options = {}) {
|
|
|
173
184
|
});
|
|
174
185
|
snapshotScheduler = activeSnapshotScheduler;
|
|
175
186
|
createFailureSnapshot = () => createRunSnapshot({
|
|
187
|
+
migration: restoredSnapshot?.migration,
|
|
176
188
|
bindings: executionScope.snapshot().bindings,
|
|
177
189
|
clock: options.clock,
|
|
178
190
|
hostCalls: hostCalls.snapshot(),
|
|
@@ -198,6 +210,7 @@ export function run(source, options = {}) {
|
|
|
198
210
|
}
|
|
199
211
|
const interpreterSnapshot = yieldPoint.snapshot();
|
|
200
212
|
snapshot = createRunSnapshot({
|
|
213
|
+
migration: restoredSnapshot?.migration,
|
|
201
214
|
bindings: interpreterSnapshot.bindings,
|
|
202
215
|
clock: options.clock,
|
|
203
216
|
hostCalls: hostCalls.snapshot(),
|
|
@@ -241,6 +254,7 @@ export function run(source, options = {}) {
|
|
|
241
254
|
}
|
|
242
255
|
const interpreterSnapshot = yieldPoint.snapshot();
|
|
243
256
|
snapshot = createRunSnapshot({
|
|
257
|
+
migration: restoredSnapshot?.migration,
|
|
244
258
|
bindings: interpreterSnapshot.bindings,
|
|
245
259
|
clock: options.clock,
|
|
246
260
|
hostCalls: hostCalls.snapshot(),
|
|
@@ -278,6 +292,7 @@ export function run(source, options = {}) {
|
|
|
278
292
|
replayError = error.message;
|
|
279
293
|
}
|
|
280
294
|
const snapshot = createRunSnapshot({
|
|
295
|
+
migration: restoredSnapshot?.migration,
|
|
281
296
|
bindings: executionScope.snapshot().bindings,
|
|
282
297
|
clock: options.clock,
|
|
283
298
|
hostCalls: hostCalls.snapshot(),
|
|
@@ -441,6 +456,7 @@ function createRunSnapshot(input) {
|
|
|
441
456
|
version: DUMP_FORMAT_VERSION,
|
|
442
457
|
executionSemantics: EXECUTION_SEMANTICS,
|
|
443
458
|
sourceHash: input.sourceHash,
|
|
459
|
+
...(input.migration === undefined ? {} : { migration: structuredClone(input.migration) }),
|
|
444
460
|
bindings: input.bindings,
|
|
445
461
|
clock: input.clock?.snapshot(),
|
|
446
462
|
...(input.hostCalls === undefined || input.hostCalls.length === 0
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const DUMP_FORMAT_VERSION = 1;
|
|
2
|
-
export const EXECUTION_SEMANTICS = "jobs-
|
|
2
|
+
export const EXECUTION_SEMANTICS = "jobs-v6";
|
|
3
3
|
import { assertSnapshotGraphDepth } from "../graph-depth.js";
|
|
4
4
|
import { sandboxErrorTypes } from "../error/shape.js";
|
|
5
5
|
import { getSandboxArgumentEntries, isSandboxArguments } from "../interp/arguments.js";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type HostCallReplay } from "../interp/host-call.js";
|
|
2
|
+
import { type ReplayData } from "./replay-data.js";
|
|
3
|
+
export type SnapshotMigrationResolution = {
|
|
4
|
+
callId: string;
|
|
5
|
+
disposition: "not-performed";
|
|
6
|
+
} | {
|
|
7
|
+
callId: string;
|
|
8
|
+
disposition: "fulfilled";
|
|
9
|
+
value: unknown;
|
|
10
|
+
} | {
|
|
11
|
+
callId: string;
|
|
12
|
+
disposition: "rejected";
|
|
13
|
+
reason: unknown;
|
|
14
|
+
};
|
|
15
|
+
export type SnapshotMigrationReconciliation = {
|
|
16
|
+
checkpointDigest: string;
|
|
17
|
+
quiescent: boolean;
|
|
18
|
+
calls: SnapshotMigrationResolution[];
|
|
19
|
+
};
|
|
20
|
+
export type SnapshotMigration = {
|
|
21
|
+
version: 1;
|
|
22
|
+
state: ReplayData;
|
|
23
|
+
history: Array<{
|
|
24
|
+
sourceHash: string;
|
|
25
|
+
targetSourceHash: string;
|
|
26
|
+
executionSemantics: string;
|
|
27
|
+
replay: HostCallReplay;
|
|
28
|
+
reconciliation: SnapshotMigrationReconciliation;
|
|
29
|
+
}>;
|
|
30
|
+
};
|
|
31
|
+
export declare function validateMigrationSemantics(value: unknown): asserts value is string;
|
|
32
|
+
export declare function validateMigrationJournal(sourceHash: string, replay: unknown, hostCalls?: unknown): HostCallReplay;
|
|
33
|
+
export declare function validateMigrationReconciliation(value: unknown, checkpointDigest: string, calls: HostCallReplay["calls"]): asserts value is SnapshotMigrationReconciliation;
|
|
34
|
+
export declare function validateSnapshotMigration(value: unknown, sourceHash: string): SnapshotMigration | undefined;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { HostCallJournal } from "../interp/host-call.js";
|
|
2
|
+
import { decodeReplayData } from "./replay-data.js";
|
|
3
|
+
import { validateSnapshotData } from "./validation.js";
|
|
4
|
+
export function validateMigrationSemantics(value) {
|
|
5
|
+
if (!["jobs-v1", "jobs-v2", "jobs-v3", "jobs-v4", "jobs-v5", "jobs-v6"].includes(value))
|
|
6
|
+
throw new TypeError("Migration requires a supported execution-semantics marker (jobs-v1 through jobs-v6).");
|
|
7
|
+
}
|
|
8
|
+
export function validateMigrationJournal(sourceHash, replay, hostCalls = []) {
|
|
9
|
+
if (replay === undefined)
|
|
10
|
+
throw new TypeError("Migration requires a complete host replay journal.");
|
|
11
|
+
if (!Array.isArray(hostCalls))
|
|
12
|
+
throw new TypeError("Invalid migration hostCalls.");
|
|
13
|
+
const journal = new HostCallJournal(sourceHash, hostCalls, undefined, replay);
|
|
14
|
+
try {
|
|
15
|
+
const restored = journal.snapshotReplay();
|
|
16
|
+
for (const call of restored.calls) {
|
|
17
|
+
if (["created", "running"].includes(call.lifecycle) && call.outcome !== undefined)
|
|
18
|
+
throw new TypeError("Unresolved migration calls cannot contain a recorded outcome.");
|
|
19
|
+
for (const callback of call.callbacks ?? []) {
|
|
20
|
+
if (!call.functions?.includes(callback.id))
|
|
21
|
+
throw new TypeError("Migration callback has no registered source function.");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return restored;
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
journal.dispose();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function validateMigrationReconciliation(value, checkpointDigest, calls) {
|
|
31
|
+
validateSnapshotData(value);
|
|
32
|
+
const receipt = value;
|
|
33
|
+
if (receipt === null ||
|
|
34
|
+
typeof receipt !== "object" ||
|
|
35
|
+
receipt.checkpointDigest !== checkpointDigest ||
|
|
36
|
+
!isCheckpointDigest(receipt.checkpointDigest))
|
|
37
|
+
throw new TypeError("Migration reconciliation must identify this exact checkpoint digest.");
|
|
38
|
+
if (receipt.quiescent !== true)
|
|
39
|
+
throw new TypeError("Migration requires explicit host confirmation that execution, operations, and callbacks are quiescent.");
|
|
40
|
+
if (!Array.isArray(receipt.calls))
|
|
41
|
+
throw new TypeError("Migration reconciliation calls must be an array.");
|
|
42
|
+
const pending = new Map(calls
|
|
43
|
+
.filter((call) => !["settled", "consumed"].includes(call.lifecycle))
|
|
44
|
+
.map((call) => [call.id, call]));
|
|
45
|
+
for (const resolution of receipt.calls) {
|
|
46
|
+
if (resolution === null || typeof resolution !== "object" || !pending.has(resolution.callId))
|
|
47
|
+
throw new TypeError("Migration contains an unknown or duplicate call resolution.");
|
|
48
|
+
if (!["not-performed", "fulfilled", "rejected"].includes(resolution.disposition) ||
|
|
49
|
+
(resolution.disposition === "fulfilled" && !Object.hasOwn(resolution, "value")) ||
|
|
50
|
+
(resolution.disposition === "rejected" && !Object.hasOwn(resolution, "reason")))
|
|
51
|
+
throw new TypeError("Migration call resolution requires a reconciled outcome or confirmed non-performance.");
|
|
52
|
+
pending.delete(resolution.callId);
|
|
53
|
+
}
|
|
54
|
+
if (pending.size > 0)
|
|
55
|
+
throw new TypeError(`Migration requires external reconciliation for: ${[...pending.keys()].join(", ")}`);
|
|
56
|
+
}
|
|
57
|
+
export function validateSnapshotMigration(value, sourceHash) {
|
|
58
|
+
if (value === undefined)
|
|
59
|
+
return undefined;
|
|
60
|
+
validateSnapshotData(value);
|
|
61
|
+
const migration = value;
|
|
62
|
+
if (migration === null ||
|
|
63
|
+
typeof migration !== "object" ||
|
|
64
|
+
migration.version !== 1 ||
|
|
65
|
+
!Array.isArray(migration.history) ||
|
|
66
|
+
migration.history.length === 0)
|
|
67
|
+
throw new TypeError("Invalid snapshot migration history.");
|
|
68
|
+
decodeReplayData(migration.state);
|
|
69
|
+
let previousTarget;
|
|
70
|
+
for (const entry of migration.history) {
|
|
71
|
+
if (entry === null ||
|
|
72
|
+
typeof entry !== "object" ||
|
|
73
|
+
typeof entry.sourceHash !== "string" ||
|
|
74
|
+
entry.sourceHash.length === 0 ||
|
|
75
|
+
typeof entry.targetSourceHash !== "string" ||
|
|
76
|
+
entry.targetSourceHash.length === 0 ||
|
|
77
|
+
(previousTarget !== undefined && previousTarget !== entry.sourceHash))
|
|
78
|
+
throw new TypeError("Invalid snapshot migration ancestry.");
|
|
79
|
+
validateMigrationSemantics(entry.executionSemantics);
|
|
80
|
+
const replay = validateMigrationJournal(entry.sourceHash, entry.replay);
|
|
81
|
+
validateMigrationReconciliation(entry.reconciliation, entry.reconciliation?.checkpointDigest, replay.calls);
|
|
82
|
+
previousTarget = entry.targetSourceHash;
|
|
83
|
+
}
|
|
84
|
+
if (previousTarget !== sourceHash)
|
|
85
|
+
throw new TypeError("Migration ancestry does not match the target source.");
|
|
86
|
+
return migration;
|
|
87
|
+
}
|
|
88
|
+
function isCheckpointDigest(value) {
|
|
89
|
+
return (typeof value === "string" &&
|
|
90
|
+
value.length === 64 &&
|
|
91
|
+
[...value].every((character) => "0123456789abcdef".includes(character)));
|
|
92
|
+
}
|
|
@@ -481,10 +481,6 @@ function validateGenericValue(value, path, depth, state) {
|
|
|
481
481
|
requireString(value, path, state.limits);
|
|
482
482
|
state.dataSize += value.length;
|
|
483
483
|
}
|
|
484
|
-
else if (typeof value === "number") {
|
|
485
|
-
if (Number.isInteger(value) && !Number.isSafeInteger(value))
|
|
486
|
-
fail("invalidValue", path, "integer must be safe");
|
|
487
|
-
}
|
|
488
484
|
else if (Array.isArray(value)) {
|
|
489
485
|
if (value.length > state.limits.maxEntries)
|
|
490
486
|
fail("budgetExceeded", path, "array is too large");
|