@earendil-works/pi-codemode 1.2.0 → 1.3.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/README.md +22 -4
- package/dist/runtime/execution.d.ts +1 -1
- package/dist/runtime/execution.d.ts.map +1 -1
- package/dist/runtime/execution.js +2 -2
- package/dist/runtime/execution.js.map +1 -1
- package/dist/runtime/host.d.ts.map +1 -1
- package/dist/runtime/host.js +25 -11
- package/dist/runtime/host.js.map +1 -1
- package/dist/types.d.ts +18 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,6 +59,24 @@ await sandbox.close();
|
|
|
59
59
|
|
|
60
60
|
`memoryLimitBytes` caps the VM's heap. Allocations beyond it fail inside the script as `InternalError: out of memory`.
|
|
61
61
|
|
|
62
|
+
Aborts, timeouts, and `close()` request worker termination without waiting for the worker to exit. On Bun, a built-in such as a long `String.prototype.indexOf` may not poll QuickJS's interrupt handler, so its worker can keep computing until the built-in returns. Stopping unrefs the worker after requesting termination, because `terminate()` refs it internally. This does not guarantee computation has stopped. On Bun 1.4.0, a pending `terminate()` can still delay host process exit despite `unref()`; cancellation results and `close()` do not wait for it.
|
|
63
|
+
|
|
64
|
+
Hosts that limit concurrency can track actual worker lifetime with `onWorkerStarted(exited)`, called for each worker started by `execute()` or `start()`. Its promise resolves when that worker exits, not when the script result settles:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const workers = new Set<Promise<void>>();
|
|
68
|
+
const sandbox = new CodemodeSandbox({
|
|
69
|
+
onWorkerStarted(exited) {
|
|
70
|
+
workers.add(exited);
|
|
71
|
+
void exited.then(() => workers.delete(exited));
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Keep a concurrency slot occupied until `exited` resolves. `close()` does not wait for these promises.
|
|
77
|
+
|
|
78
|
+
To enforce an admission limit, pass `acquireWorker()`. It runs synchronously after WASM loading, immediately before each worker is created. Throw to reject the execution without starting a worker; otherwise return a release callback. The sandbox calls it once on actual worker exit or if the worker constructor fails. Share reservation state across sandbox instances, and do not release it when a script result settles.
|
|
79
|
+
|
|
62
80
|
## Store
|
|
63
81
|
|
|
64
82
|
`store`/`load` let scripts keep values across executions. The sandbox does not persist anything itself: pass the current values as `options.store`, and a successful result reports what the script changed as `result.storeWrites` (`{ set, delete }`). Failed executions report no writes.
|
|
@@ -167,7 +185,7 @@ Bind the class with `script_name`. Binding a class exported from the agent's own
|
|
|
167
185
|
}
|
|
168
186
|
```
|
|
169
187
|
|
|
170
|
-
Then replace the sandbox. Tools, options other than `wasm` and `
|
|
188
|
+
Then replace the sandbox. Tools, options other than the worker-specific `wasm`, `workerUrl`, `acquireWorker`, and `onWorkerStarted`, and results stay the same:
|
|
171
189
|
|
|
172
190
|
```ts
|
|
173
191
|
import type { CodemodeSandboxDurableObject } from "@earendil-works/pi-codemode/cloudflare";
|
|
@@ -331,8 +349,8 @@ A run has no deadline unless `timeoutMs` is given. Result numbers must run 1, 2,
|
|
|
331
349
|
| kind | meaning |
|
|
332
350
|
| --------- | --------------------------------------------------------------------------- |
|
|
333
351
|
| `script` | the script threw or failed to parse; `stack` points at `codemode.js:<line>` |
|
|
334
|
-
| `timeout` | the deadline expired or the interrupt budget ran out;
|
|
335
|
-
| `aborted` | `options.signal` fired or `close()` was called;
|
|
352
|
+
| `timeout` | the deadline expired or the interrupt budget ran out; VM shutdown was requested |
|
|
353
|
+
| `aborted` | `options.signal` fired or `close()` was called; VM shutdown was requested |
|
|
336
354
|
| `sandbox` | the VM or its transport failed, for example a wasm trap, a missing worker file, or a failed remote |
|
|
337
355
|
|
|
338
356
|
`result.output` holds the text and image items in the order the script produced them, also for failed executions. The host keeps all of it until the script ends, so output is limited to `MAX_OUTPUT_CHARS` (16 Mi) characters of text and base64 image data and `MAX_OUTPUT_ITEMS` (100000) items. Past either limit the script fails with a `RangeError`, even if it catches the error. `result.calls` lists every tool call with `status: "ok" | "error" | "cancelled"`. A call that is still running when the script returns (not awaited) is aborted through the tool's `signal` and reported as `cancelled`.
|
|
@@ -351,6 +369,6 @@ The worker keeps script execution off the host thread: QuickJS runs synchronousl
|
|
|
351
369
|
|
|
352
370
|
## Runtime notes
|
|
353
371
|
|
|
354
|
-
-
|
|
372
|
+
- Node and Bun support memory limits, interrupts, and a catchable `RangeError` for deep recursion (QuickJS's stack guard is enabled; without it the wasm stack overflows and traps). Bun may delay worker exit during non-interruptible built-ins; results do not wait for exit.
|
|
355
373
|
- Stack traces use QuickJS frames (`at f (codemode.js:2:31)`), prefixed with `Name: message` like V8. The wrapper prefix shares line 1 with the script, so line numbers are exact; column numbers on line 1 are shifted.
|
|
356
374
|
- QuickJS is an interpreter. Glue code and filtering tool results are fast enough; heavy computation is slower than in V8.
|
|
@@ -10,7 +10,7 @@ export interface VmEvents {
|
|
|
10
10
|
/** The host's handle on a running VM. */
|
|
11
11
|
export interface VmChannel {
|
|
12
12
|
post(message: HostToWorkerMessage): void;
|
|
13
|
-
/**
|
|
13
|
+
/** Requests VM shutdown. Called once; may resolve before a worker or remote VM actually exits. */
|
|
14
14
|
stop(): Promise<void>;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["../../src/runtime/execution.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAMX,aAAa,EACb,sBAAsB,EAGtB,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,0BAA0B,EAE1B,YAAY,EACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,KAAK,mBAAmB,EAExB,KAAK,WAAW,EAEhB,MAAM,eAAe,CAAC;AAgBvB,4DAA4D;AAC5D,MAAM,WAAW,QAAQ;IACxB,kGAAkG;IAClG,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,gGAAgG;IAChG,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;CACpC;AAED,yCAAyC;AACzC,MAAM,WAAW,SAAS;IACzB,IAAI,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACzC,
|
|
1
|
+
{"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["../../src/runtime/execution.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAMX,aAAa,EACb,sBAAsB,EAGtB,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,0BAA0B,EAE1B,YAAY,EACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,KAAK,mBAAmB,EAExB,KAAK,WAAW,EAEhB,MAAM,eAAe,CAAC;AAgBvB,4DAA4D;AAC5D,MAAM,WAAW,QAAQ;IACxB,kGAAkG;IAClG,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,gGAAgG;IAChG,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;CACpC;AAED,yCAAyC;AACzC,MAAM,WAAW,SAAS;IACzB,IAAI,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACzC,kGAAkG;IAClG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,KAAK,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAEjG,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEnD;AA6WD;;;;;;;;GAQG;AACH,qBAAa,mBAAmB;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmC;IAC/D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmC;IACjE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,MAAM,CAAS;IAEvB,YAAY,OAAO,EAAE,0BAA0B,EAAE,MAAM,EAAE,UAAU,EAOlE;IAED,iEAAiE;IACjE,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAGrC;IAED,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpC;IAED,IAAI,KAAK,IAAI,YAAY,EAAE,CAE1B;IAED,IAAI,OAAO,IAAI,YAAY,EAAE,CAE5B;IAED;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,cAAc,CAAC,CAgBnF;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAoC5D;IAED,8FAA8F;IACxF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAG3B;CACD"}
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* results go back through {@link VmChannel.post}. Replies produced before the launcher has
|
|
15
15
|
* returned its channel are queued and flushed when it arrives.
|
|
16
16
|
* 3. The first terminal event wins: `done`, `crash`, a launcher failure, the deadline, or an abort.
|
|
17
|
-
* `finish()` aborts pending tool calls,
|
|
18
|
-
*
|
|
17
|
+
* `finish()` aborts pending tool calls, asks the channel to stop, and resolves the result once
|
|
18
|
+
* that request completes. A worker or remote VM may exit later. Later events are ignored.
|
|
19
19
|
*
|
|
20
20
|
* The launcher, not this class, is responsible for actually stopping a running VM: a worker is
|
|
21
21
|
* terminated, an in-thread VM is interrupted and disposed, and a remote VM is told to stop at its
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution.js","sourceRoot":"","sources":["../../src/runtime/execution.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Host side of an execution, shared by every place a VM can run.\n *\n * The host owns everything the script must not influence: the tool table, call records, output,\n * the deadline, the caller's abort signal, and the decoding of what the VM reports. The VM itself\n * runs somewhere a {@link VmLauncher} decides: a worker thread (`CodemodeSandbox`), the calling\n * thread (`InlineCodemodeSandbox`), or another isolate reached over RPC (`RemoteCodemodeSandbox`).\n * The two sides only exchange the messages in `protocol.ts`, so the launchers differ in transport\n * and termination, not in behavior.\n *\n * Lifecycle of one execution:\n * 1. The constructor arms the deadline and abort listener, then asks the launcher for a channel.\n * 2. Messages from the VM arrive through {@link VmEvents.message}; tool calls run here and their\n * results go back through {@link VmChannel.post}. Replies produced before the launcher has\n * returned its channel are queued and flushed when it arrives.\n * 3. The first terminal event wins: `done`, `crash`, a launcher failure, the deadline, or an abort.\n * `finish()` aborts pending tool calls, stops the channel, and resolves the result once the\n * channel reports it stopped. Later events are ignored.\n *\n * The launcher, not this class, is responsible for actually stopping a running VM: a worker is\n * terminated, an in-thread VM is interrupted and disposed, and a remote VM is told to stop at its\n * next exchange.\n */\nimport { toCodemodeIdentifier } from \"../identifier.ts\";\nimport type {\n\tCodemodeCall,\n\tCodemodeCallStatus,\n\tCodemodeDeclaredGlobal,\n\tCodemodeDeclaredTool,\n\tCodemodeDuring,\n\tCodemodeError,\n\tCodemodeExecuteOptions,\n\tCodemodeOutcome,\n\tCodemodeOutputItem,\n\tCodemodeResult,\n\tCodemodeRun,\n\tCodemodeRunOptions,\n\tCodemodeSandboxBaseOptions,\n\tCodemodeStoreWrites,\n\tCodemodeTool,\n} from \"../types.ts\";\nimport {\n\ttype HostToWorkerMessage,\n\tisWorkerToHostMessage,\n\ttype VmStartData,\n\ttype WorkerToHostMessage,\n} from \"./protocol.ts\";\n\nconst DEFAULT_TIMEOUT_MS = 300_000;\nconst IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\nconst RESERVED_GLOBALS: ReadonlySet<string> = new Set([\n\t\"tools\",\n\t\"ALL_TOOLS\",\n\t\"console\",\n\t\"text\",\n\t\"image\",\n\t\"exit\",\n\t\"globalThis\",\n\t\"store\",\n\t\"load\",\n]);\n\n/** Callbacks a launcher uses to report what its VM does. */\nexport interface VmEvents {\n\t/** A message from the VM. Validated here, so launchers can pass through anything they receive. */\n\tmessage(message: unknown): void;\n\t/** The VM failed or stopped outside the bridge, for example a worker exit or a remote error. */\n\tfailure(error: CodemodeError): void;\n}\n\n/** The host's handle on a running VM. */\nexport interface VmChannel {\n\tpost(message: HostToWorkerMessage): void;\n\t/** Stops the VM. Called once, after the execution has its result. */\n\tstop(): Promise<void>;\n}\n\n/**\n * Starts a VM for one execution. Rejections become `sandbox` errors with the rejection's message.\n * The VM may start reporting messages before the returned promise settles.\n */\nexport type VmLauncher = (data: VmStartData, events: VmEvents) => VmChannel | Promise<VmChannel>;\n\nexport function errorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction serializeStore(store: Readonly<Record<string, unknown>> | undefined): Record<string, string> {\n\tconst serialized: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(store ?? {})) {\n\t\tconst json = JSON.stringify(value);\n\t\tif (json !== undefined) serialized[key] = json;\n\t}\n\treturn serialized;\n}\n\n/**\n * The prelude that serializes values for the host runs in the same VM as the script, so a script\n * that patches built-ins (for example `Array.prototype.toJSON`) can make it send malformed data.\n * Payloads that do not decode throw this error, and the execution fails as a sandbox error.\n */\nclass BridgeError extends Error {}\n\nfunction parseBridgeJson(json: string, what: string): unknown {\n\ttry {\n\t\treturn JSON.parse(json);\n\t} catch {\n\t\tthrow new BridgeError(`${what} is not valid JSON`);\n\t}\n}\n\nfunction parseStoreWrites(json: string): CodemodeStoreWrites {\n\tconst entries = parseBridgeJson(json, \"store writes\");\n\tif (!Array.isArray(entries)) throw new BridgeError(\"store writes are not an array\");\n\tconst writes: CodemodeStoreWrites = { set: {}, delete: [] };\n\tfor (const entry of entries) {\n\t\tif (\n\t\t\t!Array.isArray(entry) ||\n\t\t\ttypeof entry[0] !== \"string\" ||\n\t\t\t(entry.length === 2 ? typeof entry[1] !== \"string\" : entry.length !== 1)\n\t\t) {\n\t\t\tthrow new BridgeError(\"store writes contain a malformed entry\");\n\t\t}\n\t\tconst [key, value] = entry as [string, string?];\n\t\tif (value === undefined) writes.delete.push(key);\n\t\telse writes.set[key] = parseBridgeJson(value, `store value for ${JSON.stringify(key)}`);\n\t}\n\treturn writes;\n}\n\nfunction parseScriptError(json: string): CodemodeError {\n\tconst parsed = parseBridgeJson(json, \"script error\");\n\tif (typeof parsed !== \"object\" || parsed === null) throw new BridgeError(\"script error is not an object\");\n\tconst { name, message, stack } = parsed as Record<string, unknown>;\n\tif (\n\t\ttypeof message !== \"string\" ||\n\t\t(name !== undefined && typeof name !== \"string\") ||\n\t\t(stack !== undefined && typeof stack !== \"string\")\n\t) {\n\t\tthrow new BridgeError(\"script error is malformed\");\n\t}\n\treturn { kind: \"script\", name, message, stack };\n}\n\ninterface PendingCall {\n\trecord: CodemodeCall | undefined;\n\tstartedAt: number;\n\tcontroller: AbortController;\n}\n\n/** Checks global names: identifiers or `namespace.member`, not shadowing a built-in global or each other. */\nfunction checkGlobals(globals: readonly CodemodeDeclaredGlobal[]): void {\n\tconst names = new Set<string>();\n\tconst namespaces = new Set<string>();\n\tfor (const global of globals) {\n\t\tconst parts = global.name.split(\".\");\n\t\tif (parts.length > 2 || !parts.every((part) => IDENTIFIER.test(part)) || RESERVED_GLOBALS.has(parts[0])) {\n\t\t\tthrow new Error(`Invalid global name \"${global.name}\"`);\n\t\t}\n\t\tif (names.has(global.name)) throw new Error(`Global \"${global.name}\" is already registered`);\n\t\tif (parts.length === 2) namespaces.add(parts[0]);\n\t\tnames.add(global.name);\n\t}\n\tfor (const name of namespaces) {\n\t\tif (names.has(name)) throw new Error(`Global \"${name}\" conflicts with the namespace \"${name}\"`);\n\t}\n}\n\n/** Callbacks of a host-controlled run: its calls go to the caller, which answers them with `deliver()`. */\ntype Control = Pick<CodemodeRunOptions, \"onStarted\" | \"onCall\" | \"onIdle\">;\n\ninterface ExecutionOptions {\n\tcode: string;\n\ttools: readonly CodemodeDeclaredTool[];\n\tglobals: readonly CodemodeDeclaredGlobal[];\n\t/** Run the script's calls; unused when `control` is set. */\n\texecutors: { tools: ReadonlyMap<string, CodemodeTool>; globals: ReadonlyMap<string, CodemodeTool> };\n\ttimeoutMs: number;\n\tsignal: AbortSignal | undefined;\n\tmemoryLimitBytes: number | undefined;\n\tstore: Record<string, string>;\n\tdeterministic?: { startedAt: number; seed: number };\n\tcontrol?: Control;\n\tlaunch: VmLauncher;\n}\n\n/** One script run in its own VM. */\nclass Execution {\n\treadonly promise: Promise<CodemodeResult>;\n\tprivate resolveResult!: (result: CodemodeResult) => void;\n\tprivate channel: VmChannel | undefined;\n\t/** Replies produced before the launcher returned the channel. */\n\tprivate unsent: HostToWorkerMessage[] = [];\n\tprivate readonly executors: ExecutionOptions[\"executors\"];\n\tprivate readonly control: Control | undefined;\n\t/** Result numbers `deliver()` used. */\n\tprivate readonly delivered = new Set<number>();\n\tprivate readonly signal: AbortSignal | undefined;\n\tprivate readonly timer: ReturnType<typeof setTimeout> | undefined;\n\tprivate readonly output: CodemodeOutputItem[] = [];\n\tprivate readonly calls: CodemodeCall[] = [];\n\tprivate readonly pending = new Map<number, PendingCall>();\n\t/** Whether the execution has its outcome. */\n\tfinished = false;\n\n\tconstructor(options: ExecutionOptions) {\n\t\tthis.promise = new Promise<CodemodeResult>((resolve) => {\n\t\t\tthis.resolveResult = resolve;\n\t\t});\n\t\tthis.executors = options.executors;\n\t\tthis.control = options.control;\n\t\tthis.signal = options.signal;\n\n\t\tif (Number.isFinite(options.timeoutMs)) {\n\t\t\tthis.timer = setTimeout(() => {\n\t\t\t\tthis.finish({ kind: \"timeout\", message: `Execution timed out after ${options.timeoutMs} ms` });\n\t\t\t}, options.timeoutMs);\n\t\t}\n\n\t\tif (options.signal) {\n\t\t\tif (options.signal.aborted) {\n\t\t\t\tthis.onAbort();\n\t\t\t} else {\n\t\t\t\toptions.signal.addEventListener(\"abort\", this.onAbort, { once: true });\n\t\t\t}\n\t\t}\n\t\tif (this.finished) return;\n\n\t\tconst data: VmStartData = {\n\t\t\tcode: options.code,\n\t\t\ttools: options.tools.map((tool) => ({\n\t\t\t\tname: tool.name,\n\t\t\t\tjsName: tool.jsName ?? toCodemodeIdentifier(tool.name),\n\t\t\t\tdescription: tool.description ?? \"\",\n\t\t\t})),\n\t\t\tglobals: options.globals.map((global) => ({ name: global.name, spread: global.spread === true })),\n\t\t\tmemoryLimitBytes: options.memoryLimitBytes,\n\t\t\tstore: options.store,\n\t\t\t...(options.deterministic ? { deterministic: options.deterministic } : {}),\n\t\t};\n\t\tconst events: VmEvents = {\n\t\t\tmessage: (message) => this.receive(message),\n\t\t\tfailure: (error) => this.finish(error),\n\t\t};\n\t\tnew Promise<VmChannel>((resolve) => resolve(options.launch(data, events))).then(\n\t\t\t(channel) => {\n\t\t\t\tif (this.finished) {\n\t\t\t\t\tvoid channel.stop().catch(() => undefined);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.channel = channel;\n\t\t\t\tfor (const message of this.unsent.splice(0)) channel.post(message);\n\t\t\t},\n\t\t\t(error: unknown) => {\n\t\t\t\tthis.finish({ kind: \"sandbox\", message: errorMessage(error) });\n\t\t\t},\n\t\t);\n\t}\n\n\t/** `CodemodeRun.deliver()`. */\n\tdeliver(seq: number, now: number, id: number, outcome: CodemodeOutcome): void {\n\t\tif (this.finished) return;\n\t\tif (!Number.isFinite(now)) throw new Error(`The clock value of result ${seq} is not a finite number`);\n\t\tif (!Number.isInteger(seq) || seq < 1 || this.delivered.has(seq)) {\n\t\t\tthrow new Error(`Result number ${seq} is not a positive integer used once`);\n\t\t}\n\t\tconst pending = this.pending.get(id);\n\t\tif (pending === undefined) throw new Error(`Call ${id} is not waiting for a result`);\n\t\tif (!outcome.ok && outcome.properties !== undefined) {\n\t\t\tconst { properties } = outcome;\n\t\t\tif (typeof properties !== \"object\" || properties === null || Array.isArray(properties)) {\n\t\t\t\tthrow new Error(`The properties of result ${seq} are not an object`);\n\t\t\t}\n\t\t}\n\t\t// Serialized before anything is recorded, so a value JSON cannot hold leaves the call waiting for another answer.\n\t\tconst payload = outcome.ok\n\t\t\t? outcome.value === undefined\n\t\t\t\t? undefined\n\t\t\t\t: JSON.stringify(outcome.value)\n\t\t\t: outcome.message;\n\t\tconst properties =\n\t\t\t!outcome.ok && outcome.properties !== undefined ? JSON.stringify(outcome.properties) : undefined;\n\t\tthis.delivered.add(seq);\n\t\tthis.pending.delete(id);\n\t\tif (pending.record) {\n\t\t\tpending.record.status = outcome.ok ? \"ok\" : \"error\";\n\t\t\tpending.record.durationMs = performance.now() - pending.startedAt;\n\t\t}\n\t\tthis.post({\n\t\t\ttype: \"result\",\n\t\t\tid,\n\t\t\tok: outcome.ok,\n\t\t\tpayload,\n\t\t\tseq,\n\t\t\tnow,\n\t\t\t...(properties === undefined ? {} : { properties }),\n\t\t});\n\t}\n\n\tabort(message: string): Promise<CodemodeResult> {\n\t\tthis.finish({ kind: \"aborted\", message });\n\t\treturn this.promise;\n\t}\n\n\tprivate readonly onAbort = (): void => {\n\t\tconst reason: unknown = this.signal?.reason;\n\t\tthis.finish({ kind: \"aborted\", message: reason instanceof Error ? reason.message : \"Execution aborted\" });\n\t};\n\n\tprivate post(message: HostToWorkerMessage): void {\n\t\tif (this.channel) this.channel.post(message);\n\t\telse this.unsent.push(message);\n\t}\n\n\t/** An exception here would escape into the launcher's transport and leave the execution unsettled. */\n\tprivate receive(message: unknown): void {\n\t\ttry {\n\t\t\tthis.handleMessage(message);\n\t\t} catch (error) {\n\t\t\tthis.finish({\n\t\t\t\tkind: \"sandbox\",\n\t\t\t\tmessage:\n\t\t\t\t\terror instanceof BridgeError\n\t\t\t\t\t\t? `Sandbox bridge broken: ${error.message}. The script may have modified built-ins such as a prototype's toJSON.`\n\t\t\t\t\t\t: `Sandbox host failed: ${errorMessage(error)}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate handleMessage(message: unknown): void {\n\t\tif (this.finished) return;\n\t\tif (!isWorkerToHostMessage(message)) throw new BridgeError(\"unknown message from the worker\");\n\t\tswitch (message.type) {\n\t\t\tcase \"output\":\n\t\t\t\tthis.output.push(message.item);\n\t\t\t\tbreak;\n\t\t\tcase \"call\":\n\t\t\t\tif (this.pending.has(message.id)) throw new BridgeError(`duplicate call id ${message.id}`);\n\t\t\t\tif (this.control) this.forwardCall(message, this.control);\n\t\t\t\telse void this.handleCall(message);\n\t\t\t\tbreak;\n\t\t\tcase \"started\":\n\t\t\t\tthis.control?.onStarted?.(message.fingerprint);\n\t\t\t\tbreak;\n\t\t\tcase \"idle\":\n\t\t\t\tthis.control?.onIdle?.(message.seq, message.issued);\n\t\t\t\tbreak;\n\t\t\tcase \"done\":\n\t\t\t\tthis.handleDone(message);\n\t\t\t\tbreak;\n\t\t\tcase \"crash\":\n\t\t\t\tthis.finish({ kind: \"sandbox\", message: message.message });\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate handleDone(message: Extract<WorkerToHostMessage, { type: \"done\" }>): void {\n\t\t// Decode everything before finish(), which must not throw once it starts.\n\t\tif (!message.ok) {\n\t\t\tthis.finish(parseScriptError(message.error), undefined, undefined, message.during);\n\t\t\treturn;\n\t\t}\n\t\tconst value = message.value === undefined ? undefined : parseBridgeJson(message.value, \"return value\");\n\t\tthis.finish(undefined, value, parseStoreWrites(message.writes), message.during);\n\t}\n\n\t/** A host-controlled run: record the call and hand it to the caller, which answers with `deliver()`. */\n\tprivate forwardCall(message: Extract<WorkerToHostMessage, { type: \"call\" }>, control: Control): void {\n\t\tconst { id, name, target } = message;\n\t\tconst args = message.args === undefined ? undefined : parseBridgeJson(message.args, \"call arguments\");\n\t\tconst record: CodemodeCall | undefined =\n\t\t\ttarget === \"tool\" ? { name, status: \"cancelled\", durationMs: 0 } : undefined;\n\t\tif (record) this.calls.push(record);\n\t\tthis.pending.set(id, { record, startedAt: performance.now(), controller: new AbortController() });\n\t\tcontrol.onCall({ id, target, name, args });\n\t}\n\n\tprivate async handleCall(message: Extract<WorkerToHostMessage, { type: \"call\" }>): Promise<void> {\n\t\tconst { id, name } = message;\n\t\tconst isTool = message.target === \"tool\";\n\t\tconst record: CodemodeCall | undefined = isTool ? { name, status: \"cancelled\", durationMs: 0 } : undefined;\n\t\tif (record) this.calls.push(record);\n\t\tconst pending: PendingCall = { record, startedAt: performance.now(), controller: new AbortController() };\n\t\tthis.pending.set(id, pending);\n\n\t\tlet status: CodemodeCallStatus;\n\t\tlet reply: HostToWorkerMessage;\n\t\ttry {\n\t\t\tconst tool = (isTool ? this.executors.tools : this.executors.globals).get(name);\n\t\t\tif (!tool) throw new Error(`Unknown ${isTool ? \"tool\" : \"global\"} \"${name}\"`);\n\t\t\tconst args: unknown = message.args === undefined ? undefined : JSON.parse(message.args);\n\t\t\tconst value = await tool.execute(args, { signal: pending.controller.signal });\n\t\t\treply = { type: \"result\", id, ok: true, payload: value === undefined ? undefined : JSON.stringify(value) };\n\t\t\tstatus = \"ok\";\n\t\t} catch (error) {\n\t\t\treply = { type: \"result\", id, ok: false, payload: errorMessage(error) };\n\t\t\tstatus = \"error\";\n\t\t}\n\n\t\t// Already cancelled by finish(): the record keeps \"cancelled\" and the\n\t\t// VM is gone or going.\n\t\tif (!this.pending.delete(id)) return;\n\t\tif (record) {\n\t\t\trecord.status = status;\n\t\t\trecord.durationMs = performance.now() - pending.startedAt;\n\t\t}\n\t\tthis.post(reply);\n\t}\n\n\tprivate finish(\n\t\terror: CodemodeError | undefined,\n\t\tvalue?: unknown,\n\t\twrites?: CodemodeStoreWrites,\n\t\tduring?: CodemodeDuring,\n\t): void {\n\t\tif (this.finished) return;\n\t\tthis.finished = true;\n\t\tclearTimeout(this.timer);\n\t\tthis.signal?.removeEventListener(\"abort\", this.onAbort);\n\n\t\tconst now = performance.now();\n\t\tfor (const pending of this.pending.values()) {\n\t\t\tif (pending.record) pending.record.durationMs = now - pending.startedAt;\n\t\t\tpending.controller.abort();\n\t\t}\n\t\tthis.pending.clear();\n\t\tthis.unsent = [];\n\n\t\tconst ended = during === undefined ? {} : { during: { seq: during.seq, issued: during.issued } };\n\t\tconst result: CodemodeResult = error\n\t\t\t? { ok: false, error, output: this.output, calls: this.calls, ...ended }\n\t\t\t: {\n\t\t\t\t\tok: true,\n\t\t\t\t\tvalue,\n\t\t\t\t\toutput: this.output,\n\t\t\t\t\tcalls: this.calls,\n\t\t\t\t\tstoreWrites: writes ?? { set: {}, delete: [] },\n\t\t\t\t\t...ended,\n\t\t\t\t};\n\t\tif (!this.channel) {\n\t\t\tthis.resolveResult(result);\n\t\t\treturn;\n\t\t}\n\t\tthis.channel\n\t\t\t.stop()\n\t\t\t.catch(() => undefined)\n\t\t\t.then(() => this.resolveResult(result));\n\t}\n}\n\n/**\n * Tool table, defaults, and in-flight executions; the behavior every sandbox shares. Subclasses\n * only choose where the VM runs by passing a {@link VmLauncher}.\n *\n * The script sees `tools.<name>(args)` for every registered tool, `ALL_TOOLS`, the output helpers\n * `text`, `image`, `exit`, and `console.*`, `store`/`load`, and the configured globals; nothing\n * else (no timers, `fetch`, `process`, `require`, modules). Each `execute()` gets its own VM; the\n * sandbox only holds the tool table and defaults. `close()` aborts in-flight executions.\n */\nexport class CodemodeSandboxBase {\n\tprivate readonly toolsByName = new Map<string, CodemodeTool>();\n\tprivate readonly globalsByName = new Map<string, CodemodeTool>();\n\tprivate readonly timeoutMs: number;\n\tprivate readonly memoryLimitBytes: number | undefined;\n\tprivate readonly launch: VmLauncher;\n\tprivate readonly running = new Set<Execution>();\n\tprivate closed = false;\n\n\tconstructor(options: CodemodeSandboxBaseOptions, launch: VmLauncher) {\n\t\tthis.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\t\tthis.memoryLimitBytes = options.memoryLimitBytes;\n\t\tthis.launch = launch;\n\t\tfor (const tool of options.tools ?? []) this.registerTool(tool);\n\t\tcheckGlobals(options.globals ?? []);\n\t\tfor (const global of options.globals ?? []) this.globalsByName.set(global.name, global);\n\t}\n\n\t/** Throws if a tool with the same name is already registered. */\n\tregisterTool(tool: CodemodeTool): void {\n\t\tif (this.toolsByName.has(tool.name)) throw new Error(`Tool \"${tool.name}\" is already registered`);\n\t\tthis.toolsByName.set(tool.name, tool);\n\t}\n\n\tunregisterTool(name: string): boolean {\n\t\treturn this.toolsByName.delete(name);\n\t}\n\n\tget tools(): CodemodeTool[] {\n\t\treturn [...this.toolsByName.values()];\n\t}\n\n\tget globals(): CodemodeTool[] {\n\t\treturn [...this.globalsByName.values()];\n\t}\n\n\t/**\n\t * `code` is an async function body: `return` and top-level `await` work.\n\t * Never rejects for script failures; those come back as `{ ok: false }`.\n\t * The script can use `store(key, value)` and `load(key)` on `options.store`.\n\t */\n\texecute(code: string, options: CodemodeExecuteOptions = {}): Promise<CodemodeResult> {\n\t\tif (this.closed) return Promise.reject(new Error(\"Sandbox is closed\"));\n\t\tconst tools = new Map(this.toolsByName);\n\t\tconst execution = new Execution({\n\t\t\tcode,\n\t\t\ttools: [...tools.values()],\n\t\t\tglobals: [...this.globalsByName.values()],\n\t\t\texecutors: { tools, globals: this.globalsByName },\n\t\t\ttimeoutMs: options.timeoutMs ?? this.timeoutMs,\n\t\t\tsignal: options.signal,\n\t\t\tmemoryLimitBytes: this.memoryLimitBytes,\n\t\t\tstore: serializeStore(options.store),\n\t\t\tlaunch: this.launch,\n\t\t});\n\t\tthis.running.add(execution);\n\t\treturn execution.promise.finally(() => this.running.delete(execution));\n\t}\n\n\t/**\n\t * Run `code` deterministically, with the caller answering its calls: the same script, start time, seed, tools,\n\t * globals, and store, answered with the same results in the same `seq` order, makes the same calls with the same\n\t * arguments and produces the same output, on any VM with the same fingerprint. A host can therefore replay it\n\t * after a restart. The VM runs in UTC, its clock reads `startedAt` and then the `now` of the result being\n\t * processed, its randomness comes from `seed`, and `WeakRef` and `FinalizationRegistry` do not exist.\n\t *\n\t * The sandbox's own tools and globals are not used: the run declares its own, and every call goes to\n\t * `options.onCall`. Never rejects for script failures; abort through `options.signal` to end the run with an\n\t * error the script cannot catch.\n\t */\n\tstart(code: string, options: CodemodeRunOptions): CodemodeRun {\n\t\tif (this.closed) throw new Error(\"Sandbox is closed\");\n\t\tif (!Number.isFinite(options.startedAt) || options.startedAt < 0) {\n\t\t\tthrow new Error(\"startedAt must be a non-negative number of milliseconds since the epoch\");\n\t\t}\n\t\tif (!Number.isInteger(options.seed) || options.seed < 0 || options.seed > 0xffffffff) {\n\t\t\tthrow new Error(\"seed must be a 32-bit unsigned integer\");\n\t\t}\n\t\tconst tools = options.tools ?? [];\n\t\tif (new Set(tools.map((tool) => tool.name)).size !== tools.length) throw new Error(\"Tool names must be unique\");\n\t\tconst scriptNames = tools.map((tool) => tool.jsName ?? toCodemodeIdentifier(tool.name));\n\t\tif (new Set(scriptNames).size !== tools.length) throw new Error(\"Tool script names must be unique\");\n\t\tconst globals = options.globals ?? [];\n\t\tcheckGlobals(globals);\n\t\tconst execution = new Execution({\n\t\t\tcode,\n\t\t\ttools,\n\t\t\tglobals,\n\t\t\texecutors: { tools: new Map(), globals: new Map() },\n\t\t\ttimeoutMs: options.timeoutMs ?? Number.POSITIVE_INFINITY,\n\t\t\tsignal: options.signal,\n\t\t\tmemoryLimitBytes: this.memoryLimitBytes,\n\t\t\tstore: serializeStore(options.store),\n\t\t\tdeterministic: { startedAt: options.startedAt, seed: options.seed },\n\t\t\tcontrol: { onStarted: options.onStarted, onCall: options.onCall, onIdle: options.onIdle },\n\t\t\tlaunch: this.launch,\n\t\t});\n\t\tthis.running.add(execution);\n\t\tconst result = execution.promise.finally(() => this.running.delete(execution));\n\t\treturn {\n\t\t\tresult,\n\t\t\tdeliver: (seq, now, id, outcome) => execution.deliver(seq, now, id, outcome),\n\t\t\tget finished() {\n\t\t\t\treturn execution.finished;\n\t\t\t},\n\t\t};\n\t}\n\n\t/** Aborts in-flight executions (they resolve with `kind: \"aborted\"`) and rejects new ones. */\n\tasync close(): Promise<void> {\n\t\tthis.closed = true;\n\t\tawait Promise.all([...this.running].map((execution) => execution.abort(\"Sandbox closed\")));\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"execution.js","sourceRoot":"","sources":["../../src/runtime/execution.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Host side of an execution, shared by every place a VM can run.\n *\n * The host owns everything the script must not influence: the tool table, call records, output,\n * the deadline, the caller's abort signal, and the decoding of what the VM reports. The VM itself\n * runs somewhere a {@link VmLauncher} decides: a worker thread (`CodemodeSandbox`), the calling\n * thread (`InlineCodemodeSandbox`), or another isolate reached over RPC (`RemoteCodemodeSandbox`).\n * The two sides only exchange the messages in `protocol.ts`, so the launchers differ in transport\n * and termination, not in behavior.\n *\n * Lifecycle of one execution:\n * 1. The constructor arms the deadline and abort listener, then asks the launcher for a channel.\n * 2. Messages from the VM arrive through {@link VmEvents.message}; tool calls run here and their\n * results go back through {@link VmChannel.post}. Replies produced before the launcher has\n * returned its channel are queued and flushed when it arrives.\n * 3. The first terminal event wins: `done`, `crash`, a launcher failure, the deadline, or an abort.\n * `finish()` aborts pending tool calls, asks the channel to stop, and resolves the result once\n * that request completes. A worker or remote VM may exit later. Later events are ignored.\n *\n * The launcher, not this class, is responsible for actually stopping a running VM: a worker is\n * terminated, an in-thread VM is interrupted and disposed, and a remote VM is told to stop at its\n * next exchange.\n */\nimport { toCodemodeIdentifier } from \"../identifier.ts\";\nimport type {\n\tCodemodeCall,\n\tCodemodeCallStatus,\n\tCodemodeDeclaredGlobal,\n\tCodemodeDeclaredTool,\n\tCodemodeDuring,\n\tCodemodeError,\n\tCodemodeExecuteOptions,\n\tCodemodeOutcome,\n\tCodemodeOutputItem,\n\tCodemodeResult,\n\tCodemodeRun,\n\tCodemodeRunOptions,\n\tCodemodeSandboxBaseOptions,\n\tCodemodeStoreWrites,\n\tCodemodeTool,\n} from \"../types.ts\";\nimport {\n\ttype HostToWorkerMessage,\n\tisWorkerToHostMessage,\n\ttype VmStartData,\n\ttype WorkerToHostMessage,\n} from \"./protocol.ts\";\n\nconst DEFAULT_TIMEOUT_MS = 300_000;\nconst IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\nconst RESERVED_GLOBALS: ReadonlySet<string> = new Set([\n\t\"tools\",\n\t\"ALL_TOOLS\",\n\t\"console\",\n\t\"text\",\n\t\"image\",\n\t\"exit\",\n\t\"globalThis\",\n\t\"store\",\n\t\"load\",\n]);\n\n/** Callbacks a launcher uses to report what its VM does. */\nexport interface VmEvents {\n\t/** A message from the VM. Validated here, so launchers can pass through anything they receive. */\n\tmessage(message: unknown): void;\n\t/** The VM failed or stopped outside the bridge, for example a worker exit or a remote error. */\n\tfailure(error: CodemodeError): void;\n}\n\n/** The host's handle on a running VM. */\nexport interface VmChannel {\n\tpost(message: HostToWorkerMessage): void;\n\t/** Requests VM shutdown. Called once; may resolve before a worker or remote VM actually exits. */\n\tstop(): Promise<void>;\n}\n\n/**\n * Starts a VM for one execution. Rejections become `sandbox` errors with the rejection's message.\n * The VM may start reporting messages before the returned promise settles.\n */\nexport type VmLauncher = (data: VmStartData, events: VmEvents) => VmChannel | Promise<VmChannel>;\n\nexport function errorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction serializeStore(store: Readonly<Record<string, unknown>> | undefined): Record<string, string> {\n\tconst serialized: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(store ?? {})) {\n\t\tconst json = JSON.stringify(value);\n\t\tif (json !== undefined) serialized[key] = json;\n\t}\n\treturn serialized;\n}\n\n/**\n * The prelude that serializes values for the host runs in the same VM as the script, so a script\n * that patches built-ins (for example `Array.prototype.toJSON`) can make it send malformed data.\n * Payloads that do not decode throw this error, and the execution fails as a sandbox error.\n */\nclass BridgeError extends Error {}\n\nfunction parseBridgeJson(json: string, what: string): unknown {\n\ttry {\n\t\treturn JSON.parse(json);\n\t} catch {\n\t\tthrow new BridgeError(`${what} is not valid JSON`);\n\t}\n}\n\nfunction parseStoreWrites(json: string): CodemodeStoreWrites {\n\tconst entries = parseBridgeJson(json, \"store writes\");\n\tif (!Array.isArray(entries)) throw new BridgeError(\"store writes are not an array\");\n\tconst writes: CodemodeStoreWrites = { set: {}, delete: [] };\n\tfor (const entry of entries) {\n\t\tif (\n\t\t\t!Array.isArray(entry) ||\n\t\t\ttypeof entry[0] !== \"string\" ||\n\t\t\t(entry.length === 2 ? typeof entry[1] !== \"string\" : entry.length !== 1)\n\t\t) {\n\t\t\tthrow new BridgeError(\"store writes contain a malformed entry\");\n\t\t}\n\t\tconst [key, value] = entry as [string, string?];\n\t\tif (value === undefined) writes.delete.push(key);\n\t\telse writes.set[key] = parseBridgeJson(value, `store value for ${JSON.stringify(key)}`);\n\t}\n\treturn writes;\n}\n\nfunction parseScriptError(json: string): CodemodeError {\n\tconst parsed = parseBridgeJson(json, \"script error\");\n\tif (typeof parsed !== \"object\" || parsed === null) throw new BridgeError(\"script error is not an object\");\n\tconst { name, message, stack } = parsed as Record<string, unknown>;\n\tif (\n\t\ttypeof message !== \"string\" ||\n\t\t(name !== undefined && typeof name !== \"string\") ||\n\t\t(stack !== undefined && typeof stack !== \"string\")\n\t) {\n\t\tthrow new BridgeError(\"script error is malformed\");\n\t}\n\treturn { kind: \"script\", name, message, stack };\n}\n\ninterface PendingCall {\n\trecord: CodemodeCall | undefined;\n\tstartedAt: number;\n\tcontroller: AbortController;\n}\n\n/** Checks global names: identifiers or `namespace.member`, not shadowing a built-in global or each other. */\nfunction checkGlobals(globals: readonly CodemodeDeclaredGlobal[]): void {\n\tconst names = new Set<string>();\n\tconst namespaces = new Set<string>();\n\tfor (const global of globals) {\n\t\tconst parts = global.name.split(\".\");\n\t\tif (parts.length > 2 || !parts.every((part) => IDENTIFIER.test(part)) || RESERVED_GLOBALS.has(parts[0])) {\n\t\t\tthrow new Error(`Invalid global name \"${global.name}\"`);\n\t\t}\n\t\tif (names.has(global.name)) throw new Error(`Global \"${global.name}\" is already registered`);\n\t\tif (parts.length === 2) namespaces.add(parts[0]);\n\t\tnames.add(global.name);\n\t}\n\tfor (const name of namespaces) {\n\t\tif (names.has(name)) throw new Error(`Global \"${name}\" conflicts with the namespace \"${name}\"`);\n\t}\n}\n\n/** Callbacks of a host-controlled run: its calls go to the caller, which answers them with `deliver()`. */\ntype Control = Pick<CodemodeRunOptions, \"onStarted\" | \"onCall\" | \"onIdle\">;\n\ninterface ExecutionOptions {\n\tcode: string;\n\ttools: readonly CodemodeDeclaredTool[];\n\tglobals: readonly CodemodeDeclaredGlobal[];\n\t/** Run the script's calls; unused when `control` is set. */\n\texecutors: { tools: ReadonlyMap<string, CodemodeTool>; globals: ReadonlyMap<string, CodemodeTool> };\n\ttimeoutMs: number;\n\tsignal: AbortSignal | undefined;\n\tmemoryLimitBytes: number | undefined;\n\tstore: Record<string, string>;\n\tdeterministic?: { startedAt: number; seed: number };\n\tcontrol?: Control;\n\tlaunch: VmLauncher;\n}\n\n/** One script run in its own VM. */\nclass Execution {\n\treadonly promise: Promise<CodemodeResult>;\n\tprivate resolveResult!: (result: CodemodeResult) => void;\n\tprivate channel: VmChannel | undefined;\n\t/** Replies produced before the launcher returned the channel. */\n\tprivate unsent: HostToWorkerMessage[] = [];\n\tprivate readonly executors: ExecutionOptions[\"executors\"];\n\tprivate readonly control: Control | undefined;\n\t/** Result numbers `deliver()` used. */\n\tprivate readonly delivered = new Set<number>();\n\tprivate readonly signal: AbortSignal | undefined;\n\tprivate readonly timer: ReturnType<typeof setTimeout> | undefined;\n\tprivate readonly output: CodemodeOutputItem[] = [];\n\tprivate readonly calls: CodemodeCall[] = [];\n\tprivate readonly pending = new Map<number, PendingCall>();\n\t/** Whether the execution has its outcome. */\n\tfinished = false;\n\n\tconstructor(options: ExecutionOptions) {\n\t\tthis.promise = new Promise<CodemodeResult>((resolve) => {\n\t\t\tthis.resolveResult = resolve;\n\t\t});\n\t\tthis.executors = options.executors;\n\t\tthis.control = options.control;\n\t\tthis.signal = options.signal;\n\n\t\tif (Number.isFinite(options.timeoutMs)) {\n\t\t\tthis.timer = setTimeout(() => {\n\t\t\t\tthis.finish({ kind: \"timeout\", message: `Execution timed out after ${options.timeoutMs} ms` });\n\t\t\t}, options.timeoutMs);\n\t\t}\n\n\t\tif (options.signal) {\n\t\t\tif (options.signal.aborted) {\n\t\t\t\tthis.onAbort();\n\t\t\t} else {\n\t\t\t\toptions.signal.addEventListener(\"abort\", this.onAbort, { once: true });\n\t\t\t}\n\t\t}\n\t\tif (this.finished) return;\n\n\t\tconst data: VmStartData = {\n\t\t\tcode: options.code,\n\t\t\ttools: options.tools.map((tool) => ({\n\t\t\t\tname: tool.name,\n\t\t\t\tjsName: tool.jsName ?? toCodemodeIdentifier(tool.name),\n\t\t\t\tdescription: tool.description ?? \"\",\n\t\t\t})),\n\t\t\tglobals: options.globals.map((global) => ({ name: global.name, spread: global.spread === true })),\n\t\t\tmemoryLimitBytes: options.memoryLimitBytes,\n\t\t\tstore: options.store,\n\t\t\t...(options.deterministic ? { deterministic: options.deterministic } : {}),\n\t\t};\n\t\tconst events: VmEvents = {\n\t\t\tmessage: (message) => this.receive(message),\n\t\t\tfailure: (error) => this.finish(error),\n\t\t};\n\t\tnew Promise<VmChannel>((resolve) => resolve(options.launch(data, events))).then(\n\t\t\t(channel) => {\n\t\t\t\tif (this.finished) {\n\t\t\t\t\tvoid channel.stop().catch(() => undefined);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.channel = channel;\n\t\t\t\tfor (const message of this.unsent.splice(0)) channel.post(message);\n\t\t\t},\n\t\t\t(error: unknown) => {\n\t\t\t\tthis.finish({ kind: \"sandbox\", message: errorMessage(error) });\n\t\t\t},\n\t\t);\n\t}\n\n\t/** `CodemodeRun.deliver()`. */\n\tdeliver(seq: number, now: number, id: number, outcome: CodemodeOutcome): void {\n\t\tif (this.finished) return;\n\t\tif (!Number.isFinite(now)) throw new Error(`The clock value of result ${seq} is not a finite number`);\n\t\tif (!Number.isInteger(seq) || seq < 1 || this.delivered.has(seq)) {\n\t\t\tthrow new Error(`Result number ${seq} is not a positive integer used once`);\n\t\t}\n\t\tconst pending = this.pending.get(id);\n\t\tif (pending === undefined) throw new Error(`Call ${id} is not waiting for a result`);\n\t\tif (!outcome.ok && outcome.properties !== undefined) {\n\t\t\tconst { properties } = outcome;\n\t\t\tif (typeof properties !== \"object\" || properties === null || Array.isArray(properties)) {\n\t\t\t\tthrow new Error(`The properties of result ${seq} are not an object`);\n\t\t\t}\n\t\t}\n\t\t// Serialized before anything is recorded, so a value JSON cannot hold leaves the call waiting for another answer.\n\t\tconst payload = outcome.ok\n\t\t\t? outcome.value === undefined\n\t\t\t\t? undefined\n\t\t\t\t: JSON.stringify(outcome.value)\n\t\t\t: outcome.message;\n\t\tconst properties =\n\t\t\t!outcome.ok && outcome.properties !== undefined ? JSON.stringify(outcome.properties) : undefined;\n\t\tthis.delivered.add(seq);\n\t\tthis.pending.delete(id);\n\t\tif (pending.record) {\n\t\t\tpending.record.status = outcome.ok ? \"ok\" : \"error\";\n\t\t\tpending.record.durationMs = performance.now() - pending.startedAt;\n\t\t}\n\t\tthis.post({\n\t\t\ttype: \"result\",\n\t\t\tid,\n\t\t\tok: outcome.ok,\n\t\t\tpayload,\n\t\t\tseq,\n\t\t\tnow,\n\t\t\t...(properties === undefined ? {} : { properties }),\n\t\t});\n\t}\n\n\tabort(message: string): Promise<CodemodeResult> {\n\t\tthis.finish({ kind: \"aborted\", message });\n\t\treturn this.promise;\n\t}\n\n\tprivate readonly onAbort = (): void => {\n\t\tconst reason: unknown = this.signal?.reason;\n\t\tthis.finish({ kind: \"aborted\", message: reason instanceof Error ? reason.message : \"Execution aborted\" });\n\t};\n\n\tprivate post(message: HostToWorkerMessage): void {\n\t\tif (this.channel) this.channel.post(message);\n\t\telse this.unsent.push(message);\n\t}\n\n\t/** An exception here would escape into the launcher's transport and leave the execution unsettled. */\n\tprivate receive(message: unknown): void {\n\t\ttry {\n\t\t\tthis.handleMessage(message);\n\t\t} catch (error) {\n\t\t\tthis.finish({\n\t\t\t\tkind: \"sandbox\",\n\t\t\t\tmessage:\n\t\t\t\t\terror instanceof BridgeError\n\t\t\t\t\t\t? `Sandbox bridge broken: ${error.message}. The script may have modified built-ins such as a prototype's toJSON.`\n\t\t\t\t\t\t: `Sandbox host failed: ${errorMessage(error)}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate handleMessage(message: unknown): void {\n\t\tif (this.finished) return;\n\t\tif (!isWorkerToHostMessage(message)) throw new BridgeError(\"unknown message from the worker\");\n\t\tswitch (message.type) {\n\t\t\tcase \"output\":\n\t\t\t\tthis.output.push(message.item);\n\t\t\t\tbreak;\n\t\t\tcase \"call\":\n\t\t\t\tif (this.pending.has(message.id)) throw new BridgeError(`duplicate call id ${message.id}`);\n\t\t\t\tif (this.control) this.forwardCall(message, this.control);\n\t\t\t\telse void this.handleCall(message);\n\t\t\t\tbreak;\n\t\t\tcase \"started\":\n\t\t\t\tthis.control?.onStarted?.(message.fingerprint);\n\t\t\t\tbreak;\n\t\t\tcase \"idle\":\n\t\t\t\tthis.control?.onIdle?.(message.seq, message.issued);\n\t\t\t\tbreak;\n\t\t\tcase \"done\":\n\t\t\t\tthis.handleDone(message);\n\t\t\t\tbreak;\n\t\t\tcase \"crash\":\n\t\t\t\tthis.finish({ kind: \"sandbox\", message: message.message });\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate handleDone(message: Extract<WorkerToHostMessage, { type: \"done\" }>): void {\n\t\t// Decode everything before finish(), which must not throw once it starts.\n\t\tif (!message.ok) {\n\t\t\tthis.finish(parseScriptError(message.error), undefined, undefined, message.during);\n\t\t\treturn;\n\t\t}\n\t\tconst value = message.value === undefined ? undefined : parseBridgeJson(message.value, \"return value\");\n\t\tthis.finish(undefined, value, parseStoreWrites(message.writes), message.during);\n\t}\n\n\t/** A host-controlled run: record the call and hand it to the caller, which answers with `deliver()`. */\n\tprivate forwardCall(message: Extract<WorkerToHostMessage, { type: \"call\" }>, control: Control): void {\n\t\tconst { id, name, target } = message;\n\t\tconst args = message.args === undefined ? undefined : parseBridgeJson(message.args, \"call arguments\");\n\t\tconst record: CodemodeCall | undefined =\n\t\t\ttarget === \"tool\" ? { name, status: \"cancelled\", durationMs: 0 } : undefined;\n\t\tif (record) this.calls.push(record);\n\t\tthis.pending.set(id, { record, startedAt: performance.now(), controller: new AbortController() });\n\t\tcontrol.onCall({ id, target, name, args });\n\t}\n\n\tprivate async handleCall(message: Extract<WorkerToHostMessage, { type: \"call\" }>): Promise<void> {\n\t\tconst { id, name } = message;\n\t\tconst isTool = message.target === \"tool\";\n\t\tconst record: CodemodeCall | undefined = isTool ? { name, status: \"cancelled\", durationMs: 0 } : undefined;\n\t\tif (record) this.calls.push(record);\n\t\tconst pending: PendingCall = { record, startedAt: performance.now(), controller: new AbortController() };\n\t\tthis.pending.set(id, pending);\n\n\t\tlet status: CodemodeCallStatus;\n\t\tlet reply: HostToWorkerMessage;\n\t\ttry {\n\t\t\tconst tool = (isTool ? this.executors.tools : this.executors.globals).get(name);\n\t\t\tif (!tool) throw new Error(`Unknown ${isTool ? \"tool\" : \"global\"} \"${name}\"`);\n\t\t\tconst args: unknown = message.args === undefined ? undefined : JSON.parse(message.args);\n\t\t\tconst value = await tool.execute(args, { signal: pending.controller.signal });\n\t\t\treply = { type: \"result\", id, ok: true, payload: value === undefined ? undefined : JSON.stringify(value) };\n\t\t\tstatus = \"ok\";\n\t\t} catch (error) {\n\t\t\treply = { type: \"result\", id, ok: false, payload: errorMessage(error) };\n\t\t\tstatus = \"error\";\n\t\t}\n\n\t\t// Already cancelled by finish(): the record keeps \"cancelled\" and the\n\t\t// VM is gone or going.\n\t\tif (!this.pending.delete(id)) return;\n\t\tif (record) {\n\t\t\trecord.status = status;\n\t\t\trecord.durationMs = performance.now() - pending.startedAt;\n\t\t}\n\t\tthis.post(reply);\n\t}\n\n\tprivate finish(\n\t\terror: CodemodeError | undefined,\n\t\tvalue?: unknown,\n\t\twrites?: CodemodeStoreWrites,\n\t\tduring?: CodemodeDuring,\n\t): void {\n\t\tif (this.finished) return;\n\t\tthis.finished = true;\n\t\tclearTimeout(this.timer);\n\t\tthis.signal?.removeEventListener(\"abort\", this.onAbort);\n\n\t\tconst now = performance.now();\n\t\tfor (const pending of this.pending.values()) {\n\t\t\tif (pending.record) pending.record.durationMs = now - pending.startedAt;\n\t\t\tpending.controller.abort();\n\t\t}\n\t\tthis.pending.clear();\n\t\tthis.unsent = [];\n\n\t\tconst ended = during === undefined ? {} : { during: { seq: during.seq, issued: during.issued } };\n\t\tconst result: CodemodeResult = error\n\t\t\t? { ok: false, error, output: this.output, calls: this.calls, ...ended }\n\t\t\t: {\n\t\t\t\t\tok: true,\n\t\t\t\t\tvalue,\n\t\t\t\t\toutput: this.output,\n\t\t\t\t\tcalls: this.calls,\n\t\t\t\t\tstoreWrites: writes ?? { set: {}, delete: [] },\n\t\t\t\t\t...ended,\n\t\t\t\t};\n\t\tif (!this.channel) {\n\t\t\tthis.resolveResult(result);\n\t\t\treturn;\n\t\t}\n\t\tthis.channel\n\t\t\t.stop()\n\t\t\t.catch(() => undefined)\n\t\t\t.then(() => this.resolveResult(result));\n\t}\n}\n\n/**\n * Tool table, defaults, and in-flight executions; the behavior every sandbox shares. Subclasses\n * only choose where the VM runs by passing a {@link VmLauncher}.\n *\n * The script sees `tools.<name>(args)` for every registered tool, `ALL_TOOLS`, the output helpers\n * `text`, `image`, `exit`, and `console.*`, `store`/`load`, and the configured globals; nothing\n * else (no timers, `fetch`, `process`, `require`, modules). Each `execute()` gets its own VM; the\n * sandbox only holds the tool table and defaults. `close()` aborts in-flight executions.\n */\nexport class CodemodeSandboxBase {\n\tprivate readonly toolsByName = new Map<string, CodemodeTool>();\n\tprivate readonly globalsByName = new Map<string, CodemodeTool>();\n\tprivate readonly timeoutMs: number;\n\tprivate readonly memoryLimitBytes: number | undefined;\n\tprivate readonly launch: VmLauncher;\n\tprivate readonly running = new Set<Execution>();\n\tprivate closed = false;\n\n\tconstructor(options: CodemodeSandboxBaseOptions, launch: VmLauncher) {\n\t\tthis.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\t\tthis.memoryLimitBytes = options.memoryLimitBytes;\n\t\tthis.launch = launch;\n\t\tfor (const tool of options.tools ?? []) this.registerTool(tool);\n\t\tcheckGlobals(options.globals ?? []);\n\t\tfor (const global of options.globals ?? []) this.globalsByName.set(global.name, global);\n\t}\n\n\t/** Throws if a tool with the same name is already registered. */\n\tregisterTool(tool: CodemodeTool): void {\n\t\tif (this.toolsByName.has(tool.name)) throw new Error(`Tool \"${tool.name}\" is already registered`);\n\t\tthis.toolsByName.set(tool.name, tool);\n\t}\n\n\tunregisterTool(name: string): boolean {\n\t\treturn this.toolsByName.delete(name);\n\t}\n\n\tget tools(): CodemodeTool[] {\n\t\treturn [...this.toolsByName.values()];\n\t}\n\n\tget globals(): CodemodeTool[] {\n\t\treturn [...this.globalsByName.values()];\n\t}\n\n\t/**\n\t * `code` is an async function body: `return` and top-level `await` work.\n\t * Never rejects for script failures; those come back as `{ ok: false }`.\n\t * The script can use `store(key, value)` and `load(key)` on `options.store`.\n\t */\n\texecute(code: string, options: CodemodeExecuteOptions = {}): Promise<CodemodeResult> {\n\t\tif (this.closed) return Promise.reject(new Error(\"Sandbox is closed\"));\n\t\tconst tools = new Map(this.toolsByName);\n\t\tconst execution = new Execution({\n\t\t\tcode,\n\t\t\ttools: [...tools.values()],\n\t\t\tglobals: [...this.globalsByName.values()],\n\t\t\texecutors: { tools, globals: this.globalsByName },\n\t\t\ttimeoutMs: options.timeoutMs ?? this.timeoutMs,\n\t\t\tsignal: options.signal,\n\t\t\tmemoryLimitBytes: this.memoryLimitBytes,\n\t\t\tstore: serializeStore(options.store),\n\t\t\tlaunch: this.launch,\n\t\t});\n\t\tthis.running.add(execution);\n\t\treturn execution.promise.finally(() => this.running.delete(execution));\n\t}\n\n\t/**\n\t * Run `code` deterministically, with the caller answering its calls: the same script, start time, seed, tools,\n\t * globals, and store, answered with the same results in the same `seq` order, makes the same calls with the same\n\t * arguments and produces the same output, on any VM with the same fingerprint. A host can therefore replay it\n\t * after a restart. The VM runs in UTC, its clock reads `startedAt` and then the `now` of the result being\n\t * processed, its randomness comes from `seed`, and `WeakRef` and `FinalizationRegistry` do not exist.\n\t *\n\t * The sandbox's own tools and globals are not used: the run declares its own, and every call goes to\n\t * `options.onCall`. Never rejects for script failures; abort through `options.signal` to end the run with an\n\t * error the script cannot catch.\n\t */\n\tstart(code: string, options: CodemodeRunOptions): CodemodeRun {\n\t\tif (this.closed) throw new Error(\"Sandbox is closed\");\n\t\tif (!Number.isFinite(options.startedAt) || options.startedAt < 0) {\n\t\t\tthrow new Error(\"startedAt must be a non-negative number of milliseconds since the epoch\");\n\t\t}\n\t\tif (!Number.isInteger(options.seed) || options.seed < 0 || options.seed > 0xffffffff) {\n\t\t\tthrow new Error(\"seed must be a 32-bit unsigned integer\");\n\t\t}\n\t\tconst tools = options.tools ?? [];\n\t\tif (new Set(tools.map((tool) => tool.name)).size !== tools.length) throw new Error(\"Tool names must be unique\");\n\t\tconst scriptNames = tools.map((tool) => tool.jsName ?? toCodemodeIdentifier(tool.name));\n\t\tif (new Set(scriptNames).size !== tools.length) throw new Error(\"Tool script names must be unique\");\n\t\tconst globals = options.globals ?? [];\n\t\tcheckGlobals(globals);\n\t\tconst execution = new Execution({\n\t\t\tcode,\n\t\t\ttools,\n\t\t\tglobals,\n\t\t\texecutors: { tools: new Map(), globals: new Map() },\n\t\t\ttimeoutMs: options.timeoutMs ?? Number.POSITIVE_INFINITY,\n\t\t\tsignal: options.signal,\n\t\t\tmemoryLimitBytes: this.memoryLimitBytes,\n\t\t\tstore: serializeStore(options.store),\n\t\t\tdeterministic: { startedAt: options.startedAt, seed: options.seed },\n\t\t\tcontrol: { onStarted: options.onStarted, onCall: options.onCall, onIdle: options.onIdle },\n\t\t\tlaunch: this.launch,\n\t\t});\n\t\tthis.running.add(execution);\n\t\tconst result = execution.promise.finally(() => this.running.delete(execution));\n\t\treturn {\n\t\t\tresult,\n\t\t\tdeliver: (seq, now, id, outcome) => execution.deliver(seq, now, id, outcome),\n\t\t\tget finished() {\n\t\t\t\treturn execution.finished;\n\t\t\t},\n\t\t};\n\t}\n\n\t/** Aborts in-flight executions (they resolve with `kind: \"aborted\"`) and rejects new ones. */\n\tasync close(): Promise<void> {\n\t\tthis.closed = true;\n\t\tawait Promise.all([...this.running].map((execution) => execution.abort(\"Sandbox closed\")));\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/runtime/host.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAE,mBAAmB,EAAiC,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/runtime/host.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAE,mBAAmB,EAAiC,MAAM,gBAAgB,CAAC;AAyEpF;;;;;;GAMG;AACH,qBAAa,eAAgB,SAAQ,mBAAmB;IACvD,YAAY,OAAO,GAAE,sBAA2B,EAE/C;CACD"}
|
package/dist/runtime/host.js
CHANGED
|
@@ -10,26 +10,31 @@ function defaultWorkerUrl() {
|
|
|
10
10
|
* termination simple: a runaway script, including one that only spins the microtask queue, is
|
|
11
11
|
* killed with `terminate()` and cannot poison a later run. Before terminating, the host sets a
|
|
12
12
|
* shared interrupt flag that the VM polls, because Bun's `terminate()` cannot stop a thread that
|
|
13
|
-
* is spinning in wasm.
|
|
13
|
+
* is spinning in wasm. Stopping requests termination without waiting for exit: some built-ins do
|
|
14
|
+
* not poll the flag, so on Bun a worker can outlive the script's result.
|
|
14
15
|
*/
|
|
15
|
-
function workerLauncher(
|
|
16
|
+
function workerLauncher(options) {
|
|
16
17
|
return async (data, events) => {
|
|
17
18
|
let module;
|
|
18
19
|
try {
|
|
19
|
-
module = await (wasm ?? loadQuickJSWasm());
|
|
20
|
+
module = await (options.wasm ?? loadQuickJSWasm());
|
|
20
21
|
}
|
|
21
22
|
catch (error) {
|
|
22
23
|
throw new Error(`Failed to load QuickJS: ${errorMessage(error)}`);
|
|
23
24
|
}
|
|
24
25
|
const interrupt = new SharedArrayBuffer(4);
|
|
25
26
|
const workerData = { ...data, wasm: module, interrupt };
|
|
27
|
+
const releaseWorker = options.acquireWorker?.();
|
|
26
28
|
let worker;
|
|
27
29
|
try {
|
|
28
|
-
worker = new Worker(workerUrl, { workerData });
|
|
30
|
+
worker = new Worker(options.workerUrl ?? defaultWorkerUrl(), { workerData });
|
|
29
31
|
}
|
|
30
32
|
catch (error) {
|
|
33
|
+
releaseWorker?.();
|
|
31
34
|
throw new Error(`Failed to start worker: ${errorMessage(error)}`);
|
|
32
35
|
}
|
|
36
|
+
if (releaseWorker)
|
|
37
|
+
worker.once("exit", releaseWorker);
|
|
33
38
|
worker.on("message", (message) => {
|
|
34
39
|
// Node 24/26 --watch leaks dependency reports onto the worker channel (nodejs/node#65044).
|
|
35
40
|
if (typeof message === "object" &&
|
|
@@ -48,13 +53,22 @@ function workerLauncher(wasm, workerUrl) {
|
|
|
48
53
|
worker.on("exit", (code) => {
|
|
49
54
|
events.failure({ kind: "sandbox", message: `Worker exited with code ${code} before the script settled` });
|
|
50
55
|
});
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
const stop = async () => {
|
|
57
|
+
Atomics.store(new Int32Array(interrupt), 0, 1);
|
|
58
|
+
// A non-interruptible built-in can delay Bun's terminate() until it returns (#10748).
|
|
59
|
+
// Do not hold up the result while that worker exits.
|
|
60
|
+
void worker.terminate().catch(() => undefined);
|
|
61
|
+
// terminate() refs the worker internally; unref it after requesting termination.
|
|
62
|
+
worker.unref();
|
|
57
63
|
};
|
|
64
|
+
try {
|
|
65
|
+
options.onWorkerStarted?.(new Promise((resolve) => worker.once("exit", () => resolve())));
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
void stop();
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
return { post: (message) => worker.postMessage(message), stop };
|
|
58
72
|
};
|
|
59
73
|
}
|
|
60
74
|
/**
|
|
@@ -66,7 +80,7 @@ function workerLauncher(wasm, workerUrl) {
|
|
|
66
80
|
*/
|
|
67
81
|
export class CodemodeSandbox extends CodemodeSandboxBase {
|
|
68
82
|
constructor(options = {}) {
|
|
69
|
-
super(options, workerLauncher(options
|
|
83
|
+
super(options, workerLauncher(options));
|
|
70
84
|
}
|
|
71
85
|
}
|
|
72
86
|
//# sourceMappingURL=host.js.map
|
package/dist/runtime/host.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/runtime/host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAA2B,eAAe,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAmB,MAAM,gBAAgB,CAAC;AAGpF,SAAS,gBAAgB;IACxB,8EAA8E;IAC9E,OAAO,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAClG,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/runtime/host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAA2B,eAAe,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAmB,MAAM,gBAAgB,CAAC;AAGpF,SAAS,gBAAgB;IACxB,8EAA8E;IAC9E,OAAO,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAClG,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,cAAc,CAAC,OAA+B;IACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;QAC7B,IAAI,MAA0B,CAAC;QAC/B,IAAI,CAAC;YACJ,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,eAAe,EAAE,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,2BAA2B,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,UAAU,GAAe,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QACpE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;QAChD,IAAI,MAAc,CAAC;QACnB,IAAI,CAAC;YACJ,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,IAAI,gBAAgB,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QAC9E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,aAAa,EAAE,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,2BAA2B,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,aAAa;YAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QACtD,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAAgB,EAAE,EAAE;YACzC,2FAA2F;YAC3F,IACC,OAAO,OAAO,KAAK,QAAQ;gBAC3B,OAAO,KAAK,IAAI;gBAChB,CAAC,cAAc,IAAI,OAAO,IAAI,eAAe,IAAI,OAAO,CAAC;gBAEzD,OAAO;YACR,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAc,EAAE,EAAE;YACrC,MAAM,CAAC,OAAO,CAAC;gBACd,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;gBACrD,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC;aAC5B,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAC1B,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,2BAA2B,IAAI,4BAA4B,EAAE,CAAC,CAAC;QAC3G,CAAC,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,KAAK,IAAmB,EAAE;YACtC,OAAO,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/C,sFAAsF;YACtF,qDAAqD;YACrD,KAAK,MAAM,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC/C,iFAAiF;YACjF,MAAM,CAAC,KAAK,EAAE,CAAC;QAChB,CAAC,CAAC;QACF,IAAI,CAAC;YACJ,OAAO,CAAC,eAAe,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QACjG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,KAAK,IAAI,EAAE,CAAC;YACZ,MAAM,KAAK,CAAC;QACb,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC;IACjE,CAAC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,eAAgB,SAAQ,mBAAmB;IACvD,YAAY,OAAO,GAA2B,EAAE;QAC/C,KAAK,CAAC,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACzC,CAAC;CACD","sourcesContent":["import { Worker } from \"node:worker_threads\";\nimport type { CodemodeSandboxOptions } from \"../types.ts\";\nimport { type CodemodeWasmModule, loadQuickJSWasm } from \"../wasm.ts\";\nimport { CodemodeSandboxBase, errorMessage, type VmLauncher } from \"./execution.ts\";\nimport type { WorkerData } from \"./protocol.ts\";\n\nfunction defaultWorkerUrl(): URL {\n\t// `.ts` when running from source (tests, tsx), `.js` from the published dist.\n\treturn new URL(import.meta.url.endsWith(\".ts\") ? \"./worker.ts\" : \"./worker.js\", import.meta.url);\n}\n\n/**\n * Each execution gets its own worker thread and QuickJS VM. A fresh worker per run keeps\n * termination simple: a runaway script, including one that only spins the microtask queue, is\n * killed with `terminate()` and cannot poison a later run. Before terminating, the host sets a\n * shared interrupt flag that the VM polls, because Bun's `terminate()` cannot stop a thread that\n * is spinning in wasm. Stopping requests termination without waiting for exit: some built-ins do\n * not poll the flag, so on Bun a worker can outlive the script's result.\n */\nfunction workerLauncher(options: CodemodeSandboxOptions): VmLauncher {\n\treturn async (data, events) => {\n\t\tlet module: CodemodeWasmModule;\n\t\ttry {\n\t\t\tmodule = await (options.wasm ?? loadQuickJSWasm());\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Failed to load QuickJS: ${errorMessage(error)}`);\n\t\t}\n\t\tconst interrupt = new SharedArrayBuffer(4);\n\t\tconst workerData: WorkerData = { ...data, wasm: module, interrupt };\n\t\tconst releaseWorker = options.acquireWorker?.();\n\t\tlet worker: Worker;\n\t\ttry {\n\t\t\tworker = new Worker(options.workerUrl ?? defaultWorkerUrl(), { workerData });\n\t\t} catch (error) {\n\t\t\treleaseWorker?.();\n\t\t\tthrow new Error(`Failed to start worker: ${errorMessage(error)}`);\n\t\t}\n\t\tif (releaseWorker) worker.once(\"exit\", releaseWorker);\n\t\tworker.on(\"message\", (message: unknown) => {\n\t\t\t// Node 24/26 --watch leaks dependency reports onto the worker channel (nodejs/node#65044).\n\t\t\tif (\n\t\t\t\ttypeof message === \"object\" &&\n\t\t\t\tmessage !== null &&\n\t\t\t\t(\"watch:import\" in message || \"watch:require\" in message)\n\t\t\t)\n\t\t\t\treturn;\n\t\t\tevents.message(message);\n\t\t});\n\t\tworker.on(\"error\", (error: unknown) => {\n\t\t\tevents.failure({\n\t\t\t\tkind: \"sandbox\",\n\t\t\t\tname: error instanceof Error ? error.name : undefined,\n\t\t\t\tmessage: errorMessage(error),\n\t\t\t});\n\t\t});\n\t\tworker.on(\"exit\", (code) => {\n\t\t\tevents.failure({ kind: \"sandbox\", message: `Worker exited with code ${code} before the script settled` });\n\t\t});\n\t\tconst stop = async (): Promise<void> => {\n\t\t\tAtomics.store(new Int32Array(interrupt), 0, 1);\n\t\t\t// A non-interruptible built-in can delay Bun's terminate() until it returns (#10748).\n\t\t\t// Do not hold up the result while that worker exits.\n\t\t\tvoid worker.terminate().catch(() => undefined);\n\t\t\t// terminate() refs the worker internally; unref it after requesting termination.\n\t\t\tworker.unref();\n\t\t};\n\t\ttry {\n\t\t\toptions.onWorkerStarted?.(new Promise<void>((resolve) => worker.once(\"exit\", () => resolve())));\n\t\t} catch (error) {\n\t\t\tvoid stop();\n\t\t\tthrow error;\n\t\t}\n\t\treturn { post: (message) => worker.postMessage(message), stop };\n\t};\n}\n\n/**\n * Runs JavaScript in a QuickJS VM (a separate wasm instance) inside a worker thread. The worker\n * keeps script execution off the host thread: QuickJS runs synchronously, so a spinning script on\n * the host thread would block its event loop. Requires `node:worker_threads` (Node or Bun); see\n * `InlineCodemodeSandbox` and `RemoteCodemodeSandbox` in `@earendil-works/pi-codemode/portable`\n * for other runtimes.\n */\nexport class CodemodeSandbox extends CodemodeSandboxBase {\n\tconstructor(options: CodemodeSandboxOptions = {}) {\n\t\tsuper(options, workerLauncher(options));\n\t}\n}\n"]}
|
package/dist/types.d.ts
CHANGED
|
@@ -61,11 +61,11 @@ export type CodemodeErrorKind =
|
|
|
61
61
|
/** The script threw or failed to parse. `name` and `stack` come from the script's error. */
|
|
62
62
|
"script"
|
|
63
63
|
/**
|
|
64
|
-
* The overall deadline expired, or a VM on the calling thread used up its interrupt budget.
|
|
65
|
-
* was
|
|
64
|
+
* The overall deadline expired, or a VM on the calling thread used up its interrupt budget.
|
|
65
|
+
* The execution ended and the VM was asked to stop; a worker or remote VM may still be computing.
|
|
66
66
|
*/
|
|
67
67
|
| "timeout"
|
|
68
|
-
/** The caller's signal fired or the sandbox was closed. The VM was
|
|
68
|
+
/** The caller's signal fired or the sandbox was closed. The execution ended and the VM was asked to stop. */
|
|
69
69
|
| "aborted"
|
|
70
70
|
/**
|
|
71
71
|
* The VM or its transport failed outside the script's control (for example a wasm trap, a missing
|
|
@@ -140,6 +140,20 @@ export interface CodemodeSandboxOptions extends CodemodeSandboxBaseOptions {
|
|
|
140
140
|
* specifier of an embedded build entrypoint; other hosts usually use a URL.
|
|
141
141
|
*/
|
|
142
142
|
workerUrl?: string | URL;
|
|
143
|
+
/**
|
|
144
|
+
* Synchronously reserves capacity immediately before creating each worker, after loading wasm.
|
|
145
|
+
* Throw to deny admission without starting a worker. Return a release callback, called once if
|
|
146
|
+
* worker construction fails or when the worker actually exits, not when the result settles.
|
|
147
|
+
* The release callback must not throw. Reservations can be shared across sandbox instances.
|
|
148
|
+
*/
|
|
149
|
+
acquireWorker?(): () => void;
|
|
150
|
+
/**
|
|
151
|
+
* Called once for each worker started by execute() or start(). `exited` resolves when that worker
|
|
152
|
+
* actually exits, which may be after the result and close() settle: on Bun a non-interruptible
|
|
153
|
+
* built-in can delay termination. Use it to keep the worker counted against host concurrency
|
|
154
|
+
* limits until it exits. A thrown callback error fails the execution and requests worker termination.
|
|
155
|
+
*/
|
|
156
|
+
onWorkerStarted?(exited: Promise<void>): void;
|
|
143
157
|
}
|
|
144
158
|
/** A call the script made in a {@link CodemodeSandboxBase.start} run, answered with `CodemodeRun.deliver()`. */
|
|
145
159
|
export interface CodemodeHostCall {
|
|
@@ -208,7 +222,7 @@ export interface CodemodeRun {
|
|
|
208
222
|
readonly result: Promise<CodemodeResult>;
|
|
209
223
|
/**
|
|
210
224
|
* Whether the run has its outcome: the script ended, timed out, or failed, or the run was aborted. Set when that is
|
|
211
|
-
* decided, before `result` settles
|
|
225
|
+
* decided, before `result` settles; calls can no longer be answered. It does not mean the VM has exited.
|
|
212
226
|
*/
|
|
213
227
|
readonly finished: boolean;
|
|
214
228
|
/**
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEpD,MAAM,WAAW,mBAAmB;IACnC;;;OAGG;IACH,MAAM,EAAE,WAAW,CAAC;CACpB;AAED,qGAAqG;AACrG,MAAM,MAAM,kBAAkB,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC;AAEtE,MAAM,WAAW,YAAY;IAC5B;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,iGAAiG;IACjG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,0FAA0F;IAC1F,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,gGAAgG;IAChG,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CACjF;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAC3B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,IAAI,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,OAAO,GAAG,WAAW,CAAC;AAE9D,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,iBAAiB;AAC5B,4FAA4F;AAC1F,QAAQ;AACV;;;GAGG;GACD,SAAS;AACX
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { CodemodeWasmModule } from \"./wasm.ts\";\n\nexport interface CodemodeToolContext {\n\t/**\n\t * Aborted when the script finishes (including unawaited calls), the\n\t * execution times out, the caller aborts, or the sandbox is closed.\n\t */\n\tsignal: AbortSignal;\n}\n\n/** A JSON Schema document. Only used to render declarations; values are not validated against it. */\nexport type CodemodeJsonSchema = { [key: string]: unknown } | boolean;\n\nexport interface CodemodeTool {\n\t/**\n\t * The script calls tools as `tools.<id>(args)`, where `<id>` is the name with characters that\n\t * are not valid in identifiers replaced by `_` (see `toCodemodeIdentifier`), and also as\n\t * `tools[\"<name>\"](args)`. Globals are called as `<name>(args)` and must be identifiers, or\n\t * `<namespace>.<member>`, which groups them into a frozen namespace object.\n\t */\n\tname: string;\n\t/** Shown as a doc comment in {@link renderDeclarations}, and listed in `ALL_TOOLS` for tools. */\n\tdescription?: string;\n\t/** Schema of the single argument. Rendered as the parameter type; `unknown` when omitted. */\n\tinputSchema?: CodemodeJsonSchema;\n\t/** Schema of the resolved value. Rendered as the promise type; `unknown` when omitted. */\n\toutputSchema?: CodemodeJsonSchema;\n\t/** Globals only: `execute` receives all call arguments as an array instead of the first one. */\n\tspread?: boolean;\n\t/**\n\t * Globals only: TypeScript parameter list and return type for {@link renderDeclarations}, for\n\t * example `(type: string, id?: string): Promise<Model[]>`. Replaces the rendering from the schemas.\n\t */\n\tsignature?: string;\n\t/**\n\t * `args` is whatever the script passed, after a JSON round trip. The return\n\t * value must be JSON-serializable; a thrown error surfaces in the script as\n\t * an `Error` with the same message.\n\t */\n\texecute(args: unknown, context: CodemodeToolContext): Promise<unknown> | unknown;\n}\n\n/**\n * One item of the script's output, in the order the script produced it: `text()` and `console.*`\n * produce text items, with `console: true` for `console.*`, and `image()` image items. `data` is base64.\n */\nexport type CodemodeOutputItem =\n\t| { type: \"text\"; text: string; console?: true }\n\t| { type: \"image\"; data: string; mimeType: string };\n\nexport type CodemodeCallStatus = \"ok\" | \"error\" | \"cancelled\";\n\nexport interface CodemodeCall {\n\tname: string;\n\tstatus: CodemodeCallStatus;\n\tdurationMs: number;\n}\n\nexport type CodemodeErrorKind =\n\t/** The script threw or failed to parse. `name` and `stack` come from the script's error. */\n\t| \"script\"\n\t/**\n\t * The overall deadline expired, or a VM on the calling thread used up its interrupt budget. The VM\n\t * was stopped.\n\t */\n\t| \"timeout\"\n\t/** The caller's signal fired or the sandbox was closed. The VM was stopped. */\n\t| \"aborted\"\n\t/**\n\t * The VM or its transport failed outside the script's control (for example a wasm trap, a missing\n\t * worker file, or a remote sandbox that failed).\n\t */\n\t| \"sandbox\";\n\nexport interface CodemodeError {\n\tkind: CodemodeErrorKind;\n\tname?: string;\n\tmessage: string;\n\tstack?: string;\n}\n\n/** Keys the script changed with `store()`. Only successful executions report writes. */\nexport interface CodemodeStoreWrites {\n\tset: Record<string, unknown>;\n\t/** Keys stored as `undefined`. */\n\tdelete: string[];\n}\n\n/**\n * `output` is kept for failed executions too, up to the failure. `exit()` completes with `value: undefined`.\n * `during`: in a {@link CodemodeSandboxBase.start} run that the script itself ended (it returned, threw, or exited),\n * the result being processed when it did.\n */\nexport type CodemodeResult =\n\t| {\n\t\t\tok: true;\n\t\t\tvalue: unknown;\n\t\t\toutput: CodemodeOutputItem[];\n\t\t\tcalls: CodemodeCall[];\n\t\t\tstoreWrites: CodemodeStoreWrites;\n\t\t\tduring?: CodemodeDuring;\n\t }\n\t| {\n\t\t\tok: false;\n\t\t\terror: CodemodeError;\n\t\t\toutput: CodemodeOutputItem[];\n\t\t\tcalls: CodemodeCall[];\n\t\t\tduring?: CodemodeDuring;\n\t };\n\n/** Options every sandbox accepts, wherever its VM runs. */\nexport interface CodemodeSandboxBaseOptions {\n\ttools?: CodemodeTool[];\n\t/**\n\t * Functions exposed as top-level identifiers instead of on `tools`, for host helpers such as\n\t * attaching an image to the result. They behave like tools (JSON round trip, promise result)\n\t * but are not recorded in `result.calls`. Names must be identifiers and may not shadow the\n\t * built-in globals (`tools`, `ALL_TOOLS`, `console`, `text`, `image`, `exit`, `store`, `load`).\n\t */\n\tglobals?: CodemodeTool[];\n\t/**\n\t * Overall deadline per execution, including time spent in tools. `Infinity` disables the\n\t * deadline; the execution then only ends when the script settles or is aborted.\n\t * Default: 300000.\n\t */\n\ttimeoutMs?: number;\n\t/**\n\t * Maximum memory the QuickJS VM may allocate. Allocations beyond it fail inside the script as\n\t * `InternalError: out of memory`. Default: no limit beyond wasm32's 4 GiB address space.\n\t */\n\tmemoryLimitBytes?: number;\n}\n\n/** Options of `CodemodeSandbox`, which runs each VM in a Node or Bun worker thread. */\nexport interface CodemodeSandboxOptions extends CodemodeSandboxBaseOptions {\n\t/**\n\t * Compiled `quickjs-wasi/quickjs.wasm`, usually from {@link loadQuickJSWasm}. Default:\n\t * `loadQuickJSWasm()`, the file in the installed `quickjs-wasi` package. Pass it when that file\n\t * is not on disk, for example in a Bun compiled executable.\n\t */\n\twasm?: CodemodeWasmModule | Promise<CodemodeWasmModule>;\n\t/**\n\t * Worker entry that imports `@earendil-works/pi-codemode/worker`. Default: this package's own\n\t * worker file. Pass it when this package is bundled, since the default is resolved relative to\n\t * the module that creates the sandbox. Bun compiled executables require the relative string\n\t * specifier of an embedded build entrypoint; other hosts usually use a URL.\n\t */\n\tworkerUrl?: string | URL;\n}\n\n/** A call the script made in a {@link CodemodeSandboxBase.start} run, answered with `CodemodeRun.deliver()`. */\nexport interface CodemodeHostCall {\n\t/** The VM's own number for the call, `1`, `2`, ... in the order the script made its calls (tools and globals). */\n\tid: number;\n\ttarget: \"tool\" | \"global\";\n\tname: string;\n\t/** What the script passed, after a JSON round trip; for spread globals the argument list. */\n\targs: unknown;\n}\n\n/** A tool as a {@link CodemodeSandboxBase.start} run's script sees it: `tools.<name>` and its `ALL_TOOLS` entry. */\nexport interface CodemodeDeclaredTool {\n\tname: string;\n\t/**\n\t * The identifier the script uses, `tools.<jsName>`. Default: `toCodemodeIdentifier(name)`. A host that replays a run\n\t * passes the one the run started with, so a changed mapping cannot rename a tool under a resumed script.\n\t */\n\tjsName?: string;\n\tdescription?: string;\n}\n\n/** A global as a {@link CodemodeSandboxBase.start} run's script sees it; the same names as `globals` allow. */\nexport interface CodemodeDeclaredGlobal {\n\tname: string;\n\tspread?: boolean;\n}\n\n/**\n * A call's answer. A rejection becomes an `Error` with `message` in the script, carrying the own properties of\n * `properties` (JSON values; `name`, `message`, and `stack` are ignored), for example `{ structuredOutput }`.\n */\nexport type CodemodeOutcome =\n\t| { ok: true; value: unknown }\n\t| { ok: false; message: string; properties?: Record<string, unknown> };\n\n/** In a {@link CodemodeSandboxBase.start} run: the result the VM was processing when the script finished, 0 for its first run, and the calls issued by then. */\nexport interface CodemodeDuring {\n\tseq: number;\n\tissued: number;\n}\n\nexport interface CodemodeRunOptions {\n\t/** The VM clock's start, in ms since the epoch: `Date.now()` until the first result arrives. */\n\tstartedAt: number;\n\t/** Seeds `Math.random()` and the VM's other randomness. A 32-bit unsigned integer. */\n\tseed: number;\n\ttools?: CodemodeDeclaredTool[];\n\tglobals?: CodemodeDeclaredGlobal[];\n\tstore?: Readonly<Record<string, unknown>>;\n\tsignal?: AbortSignal;\n\t/** Deadline of this run in ms. Default: none (not the sandbox's default). */\n\ttimeoutMs?: number;\n\t/** The VM's fingerprint, before the script runs and before any of its calls. */\n\tonStarted?(fingerprint: string): void;\n\t/** The script made a call. Answer it with `CodemodeRun.deliver()`, now or later. */\n\tonCall(call: CodemodeHostCall): void;\n\t/**\n\t * The VM processed result `seq` (`0`: the script's first run, before any result) and waits again, having issued\n\t * `issued` calls in total.\n\t */\n\tonIdle?(seq: number, issued: number): void;\n}\n\n/** A running {@link CodemodeSandboxBase.start} execution. */\nexport interface CodemodeRun {\n\treadonly result: Promise<CodemodeResult>;\n\t/**\n\t * Whether the run has its outcome: the script ended, timed out, or failed, or the run was aborted. Set when that is\n\t * decided, before `result` settles (which waits for the VM to stop); calls can no longer be answered.\n\t */\n\treadonly finished: boolean;\n\t/**\n\t * Answer call `id` as result number `seq`. Results are numbered 1, 2, ... without gaps, and the VM applies them\n\t * strictly in that order, whatever order they arrive in: after a gap it waits for the missing number. While it\n\t * processes this one, its clock reads `now` (ms since the epoch), or the previous value if `now` is earlier.\n\t * Throws for a call that is not waiting for an answer, a `seq` used before, or a `now` that is not finite.\n\t */\n\tdeliver(seq: number, now: number, id: number, outcome: CodemodeOutcome): void;\n}\n\nexport interface CodemodeExecuteOptions {\n\tsignal?: AbortSignal;\n\t/** Overrides the sandbox default for this execution. */\n\ttimeoutMs?: number;\n\t/**\n\t * Values the script reads with `load(key)`. Must be JSON-serializable. The script's own\n\t * `store()` calls come back as `result.storeWrites`; persisting them is up to the caller.\n\t */\n\tstore?: Readonly<Record<string, unknown>>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { CodemodeWasmModule } from \"./wasm.ts\";\n\nexport interface CodemodeToolContext {\n\t/**\n\t * Aborted when the script finishes (including unawaited calls), the\n\t * execution times out, the caller aborts, or the sandbox is closed.\n\t */\n\tsignal: AbortSignal;\n}\n\n/** A JSON Schema document. Only used to render declarations; values are not validated against it. */\nexport type CodemodeJsonSchema = { [key: string]: unknown } | boolean;\n\nexport interface CodemodeTool {\n\t/**\n\t * The script calls tools as `tools.<id>(args)`, where `<id>` is the name with characters that\n\t * are not valid in identifiers replaced by `_` (see `toCodemodeIdentifier`), and also as\n\t * `tools[\"<name>\"](args)`. Globals are called as `<name>(args)` and must be identifiers, or\n\t * `<namespace>.<member>`, which groups them into a frozen namespace object.\n\t */\n\tname: string;\n\t/** Shown as a doc comment in {@link renderDeclarations}, and listed in `ALL_TOOLS` for tools. */\n\tdescription?: string;\n\t/** Schema of the single argument. Rendered as the parameter type; `unknown` when omitted. */\n\tinputSchema?: CodemodeJsonSchema;\n\t/** Schema of the resolved value. Rendered as the promise type; `unknown` when omitted. */\n\toutputSchema?: CodemodeJsonSchema;\n\t/** Globals only: `execute` receives all call arguments as an array instead of the first one. */\n\tspread?: boolean;\n\t/**\n\t * Globals only: TypeScript parameter list and return type for {@link renderDeclarations}, for\n\t * example `(type: string, id?: string): Promise<Model[]>`. Replaces the rendering from the schemas.\n\t */\n\tsignature?: string;\n\t/**\n\t * `args` is whatever the script passed, after a JSON round trip. The return\n\t * value must be JSON-serializable; a thrown error surfaces in the script as\n\t * an `Error` with the same message.\n\t */\n\texecute(args: unknown, context: CodemodeToolContext): Promise<unknown> | unknown;\n}\n\n/**\n * One item of the script's output, in the order the script produced it: `text()` and `console.*`\n * produce text items, with `console: true` for `console.*`, and `image()` image items. `data` is base64.\n */\nexport type CodemodeOutputItem =\n\t| { type: \"text\"; text: string; console?: true }\n\t| { type: \"image\"; data: string; mimeType: string };\n\nexport type CodemodeCallStatus = \"ok\" | \"error\" | \"cancelled\";\n\nexport interface CodemodeCall {\n\tname: string;\n\tstatus: CodemodeCallStatus;\n\tdurationMs: number;\n}\n\nexport type CodemodeErrorKind =\n\t/** The script threw or failed to parse. `name` and `stack` come from the script's error. */\n\t| \"script\"\n\t/**\n\t * The overall deadline expired, or a VM on the calling thread used up its interrupt budget.\n\t * The execution ended and the VM was asked to stop; a worker or remote VM may still be computing.\n\t */\n\t| \"timeout\"\n\t/** The caller's signal fired or the sandbox was closed. The execution ended and the VM was asked to stop. */\n\t| \"aborted\"\n\t/**\n\t * The VM or its transport failed outside the script's control (for example a wasm trap, a missing\n\t * worker file, or a remote sandbox that failed).\n\t */\n\t| \"sandbox\";\n\nexport interface CodemodeError {\n\tkind: CodemodeErrorKind;\n\tname?: string;\n\tmessage: string;\n\tstack?: string;\n}\n\n/** Keys the script changed with `store()`. Only successful executions report writes. */\nexport interface CodemodeStoreWrites {\n\tset: Record<string, unknown>;\n\t/** Keys stored as `undefined`. */\n\tdelete: string[];\n}\n\n/**\n * `output` is kept for failed executions too, up to the failure. `exit()` completes with `value: undefined`.\n * `during`: in a {@link CodemodeSandboxBase.start} run that the script itself ended (it returned, threw, or exited),\n * the result being processed when it did.\n */\nexport type CodemodeResult =\n\t| {\n\t\t\tok: true;\n\t\t\tvalue: unknown;\n\t\t\toutput: CodemodeOutputItem[];\n\t\t\tcalls: CodemodeCall[];\n\t\t\tstoreWrites: CodemodeStoreWrites;\n\t\t\tduring?: CodemodeDuring;\n\t }\n\t| {\n\t\t\tok: false;\n\t\t\terror: CodemodeError;\n\t\t\toutput: CodemodeOutputItem[];\n\t\t\tcalls: CodemodeCall[];\n\t\t\tduring?: CodemodeDuring;\n\t };\n\n/** Options every sandbox accepts, wherever its VM runs. */\nexport interface CodemodeSandboxBaseOptions {\n\ttools?: CodemodeTool[];\n\t/**\n\t * Functions exposed as top-level identifiers instead of on `tools`, for host helpers such as\n\t * attaching an image to the result. They behave like tools (JSON round trip, promise result)\n\t * but are not recorded in `result.calls`. Names must be identifiers and may not shadow the\n\t * built-in globals (`tools`, `ALL_TOOLS`, `console`, `text`, `image`, `exit`, `store`, `load`).\n\t */\n\tglobals?: CodemodeTool[];\n\t/**\n\t * Overall deadline per execution, including time spent in tools. `Infinity` disables the\n\t * deadline; the execution then only ends when the script settles or is aborted.\n\t * Default: 300000.\n\t */\n\ttimeoutMs?: number;\n\t/**\n\t * Maximum memory the QuickJS VM may allocate. Allocations beyond it fail inside the script as\n\t * `InternalError: out of memory`. Default: no limit beyond wasm32's 4 GiB address space.\n\t */\n\tmemoryLimitBytes?: number;\n}\n\n/** Options of `CodemodeSandbox`, which runs each VM in a Node or Bun worker thread. */\nexport interface CodemodeSandboxOptions extends CodemodeSandboxBaseOptions {\n\t/**\n\t * Compiled `quickjs-wasi/quickjs.wasm`, usually from {@link loadQuickJSWasm}. Default:\n\t * `loadQuickJSWasm()`, the file in the installed `quickjs-wasi` package. Pass it when that file\n\t * is not on disk, for example in a Bun compiled executable.\n\t */\n\twasm?: CodemodeWasmModule | Promise<CodemodeWasmModule>;\n\t/**\n\t * Worker entry that imports `@earendil-works/pi-codemode/worker`. Default: this package's own\n\t * worker file. Pass it when this package is bundled, since the default is resolved relative to\n\t * the module that creates the sandbox. Bun compiled executables require the relative string\n\t * specifier of an embedded build entrypoint; other hosts usually use a URL.\n\t */\n\tworkerUrl?: string | URL;\n\t/**\n\t * Synchronously reserves capacity immediately before creating each worker, after loading wasm.\n\t * Throw to deny admission without starting a worker. Return a release callback, called once if\n\t * worker construction fails or when the worker actually exits, not when the result settles.\n\t * The release callback must not throw. Reservations can be shared across sandbox instances.\n\t */\n\tacquireWorker?(): () => void;\n\t/**\n\t * Called once for each worker started by execute() or start(). `exited` resolves when that worker\n\t * actually exits, which may be after the result and close() settle: on Bun a non-interruptible\n\t * built-in can delay termination. Use it to keep the worker counted against host concurrency\n\t * limits until it exits. A thrown callback error fails the execution and requests worker termination.\n\t */\n\tonWorkerStarted?(exited: Promise<void>): void;\n}\n\n/** A call the script made in a {@link CodemodeSandboxBase.start} run, answered with `CodemodeRun.deliver()`. */\nexport interface CodemodeHostCall {\n\t/** The VM's own number for the call, `1`, `2`, ... in the order the script made its calls (tools and globals). */\n\tid: number;\n\ttarget: \"tool\" | \"global\";\n\tname: string;\n\t/** What the script passed, after a JSON round trip; for spread globals the argument list. */\n\targs: unknown;\n}\n\n/** A tool as a {@link CodemodeSandboxBase.start} run's script sees it: `tools.<name>` and its `ALL_TOOLS` entry. */\nexport interface CodemodeDeclaredTool {\n\tname: string;\n\t/**\n\t * The identifier the script uses, `tools.<jsName>`. Default: `toCodemodeIdentifier(name)`. A host that replays a run\n\t * passes the one the run started with, so a changed mapping cannot rename a tool under a resumed script.\n\t */\n\tjsName?: string;\n\tdescription?: string;\n}\n\n/** A global as a {@link CodemodeSandboxBase.start} run's script sees it; the same names as `globals` allow. */\nexport interface CodemodeDeclaredGlobal {\n\tname: string;\n\tspread?: boolean;\n}\n\n/**\n * A call's answer. A rejection becomes an `Error` with `message` in the script, carrying the own properties of\n * `properties` (JSON values; `name`, `message`, and `stack` are ignored), for example `{ structuredOutput }`.\n */\nexport type CodemodeOutcome =\n\t| { ok: true; value: unknown }\n\t| { ok: false; message: string; properties?: Record<string, unknown> };\n\n/** In a {@link CodemodeSandboxBase.start} run: the result the VM was processing when the script finished, 0 for its first run, and the calls issued by then. */\nexport interface CodemodeDuring {\n\tseq: number;\n\tissued: number;\n}\n\nexport interface CodemodeRunOptions {\n\t/** The VM clock's start, in ms since the epoch: `Date.now()` until the first result arrives. */\n\tstartedAt: number;\n\t/** Seeds `Math.random()` and the VM's other randomness. A 32-bit unsigned integer. */\n\tseed: number;\n\ttools?: CodemodeDeclaredTool[];\n\tglobals?: CodemodeDeclaredGlobal[];\n\tstore?: Readonly<Record<string, unknown>>;\n\tsignal?: AbortSignal;\n\t/** Deadline of this run in ms. Default: none (not the sandbox's default). */\n\ttimeoutMs?: number;\n\t/** The VM's fingerprint, before the script runs and before any of its calls. */\n\tonStarted?(fingerprint: string): void;\n\t/** The script made a call. Answer it with `CodemodeRun.deliver()`, now or later. */\n\tonCall(call: CodemodeHostCall): void;\n\t/**\n\t * The VM processed result `seq` (`0`: the script's first run, before any result) and waits again, having issued\n\t * `issued` calls in total.\n\t */\n\tonIdle?(seq: number, issued: number): void;\n}\n\n/** A running {@link CodemodeSandboxBase.start} execution. */\nexport interface CodemodeRun {\n\treadonly result: Promise<CodemodeResult>;\n\t/**\n\t * Whether the run has its outcome: the script ended, timed out, or failed, or the run was aborted. Set when that is\n\t * decided, before `result` settles; calls can no longer be answered. It does not mean the VM has exited.\n\t */\n\treadonly finished: boolean;\n\t/**\n\t * Answer call `id` as result number `seq`. Results are numbered 1, 2, ... without gaps, and the VM applies them\n\t * strictly in that order, whatever order they arrive in: after a gap it waits for the missing number. While it\n\t * processes this one, its clock reads `now` (ms since the epoch), or the previous value if `now` is earlier.\n\t * Throws for a call that is not waiting for an answer, a `seq` used before, or a `now` that is not finite.\n\t */\n\tdeliver(seq: number, now: number, id: number, outcome: CodemodeOutcome): void;\n}\n\nexport interface CodemodeExecuteOptions {\n\tsignal?: AbortSignal;\n\t/** Overrides the sandbox default for this execution. */\n\ttimeoutMs?: number;\n\t/**\n\t * Values the script reads with `load(key)`. Must be JSON-serializable. The script's own\n\t * `store()` calls come back as `result.storeWrites`; persisting them is up to the caller.\n\t */\n\tstore?: Readonly<Record<string, unknown>>;\n}\n"]}
|