@earendil-works/pi-codemode 0.0.1 → 0.99.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.
Files changed (42) hide show
  1. package/README.md +184 -1
  2. package/dist/declarations.d.ts +53 -0
  3. package/dist/declarations.d.ts.map +1 -0
  4. package/dist/declarations.js +330 -0
  5. package/dist/declarations.js.map +1 -0
  6. package/dist/identifier.d.ts +6 -0
  7. package/dist/identifier.d.ts.map +1 -0
  8. package/dist/identifier.js +13 -0
  9. package/dist/identifier.js.map +1 -0
  10. package/dist/index.d.ts +8 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +7 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/runtime/host.d.ts +35 -0
  15. package/dist/runtime/host.d.ts.map +1 -0
  16. package/dist/runtime/host.js +314 -0
  17. package/dist/runtime/host.js.map +1 -0
  18. package/dist/runtime/prelude-source.d.ts +31 -0
  19. package/dist/runtime/prelude-source.d.ts.map +1 -0
  20. package/dist/runtime/prelude-source.js +322 -0
  21. package/dist/runtime/prelude-source.js.map +1 -0
  22. package/dist/runtime/protocol.d.ts +69 -0
  23. package/dist/runtime/protocol.d.ts.map +1 -0
  24. package/dist/runtime/protocol.js +10 -0
  25. package/dist/runtime/protocol.js.map +1 -0
  26. package/dist/runtime/worker.d.ts +2 -0
  27. package/dist/runtime/worker.d.ts.map +1 -0
  28. package/dist/runtime/worker.js +137 -0
  29. package/dist/runtime/worker.js.map +1 -0
  30. package/dist/source.d.ts +35 -0
  31. package/dist/source.d.ts.map +1 -0
  32. package/dist/source.js +92 -0
  33. package/dist/source.js.map +1 -0
  34. package/dist/types.d.ts +136 -0
  35. package/dist/types.d.ts.map +1 -0
  36. package/dist/types.js +2 -0
  37. package/dist/types.js.map +1 -0
  38. package/dist/wasm.d.ts +12 -0
  39. package/dist/wasm.d.ts.map +1 -0
  40. package/dist/wasm.js +24 -0
  41. package/dist/wasm.js.map +1 -0
  42. package/package.json +54 -4
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The identifier a script uses for a tool: characters that are not valid in a JavaScript
3
+ * identifier become `_`. `mcp__docs__search` stays as is, `my-tool` becomes `my_tool`.
4
+ */
5
+ export function toCodemodeIdentifier(name) {
6
+ let identifier = "";
7
+ for (const char of name) {
8
+ const valid = identifier === "" ? /^[A-Za-z_$]$/.test(char) : /^[A-Za-z0-9_$]$/.test(char);
9
+ identifier += valid ? char : "_";
10
+ }
11
+ return identifier === "" ? "_" : identifier;
12
+ }
13
+ //# sourceMappingURL=identifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identifier.js","sourceRoot":"","sources":["../src/identifier.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAChD,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3F,UAAU,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;IAClC,CAAC;IACD,OAAO,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC;AAC7C,CAAC","sourcesContent":["/**\n * The identifier a script uses for a tool: characters that are not valid in a JavaScript\n * identifier become `_`. `mcp__docs__search` stays as is, `my-tool` becomes `my_tool`.\n */\nexport function toCodemodeIdentifier(name: string): string {\n\tlet identifier = \"\";\n\tfor (const char of name) {\n\t\tconst valid = identifier === \"\" ? /^[A-Za-z_$]$/.test(char) : /^[A-Za-z0-9_$]$/.test(char);\n\t\tidentifier += valid ? char : \"_\";\n\t}\n\treturn identifier === \"\" ? \"_\" : identifier;\n}\n"]}
@@ -0,0 +1,8 @@
1
+ export { DEFAULT_INPUT_SCHEMA_MAX_CHARS, MCP_TYPESCRIPT_PREAMBLE, mcpStructuredContentSchema, type RenderDeclarationsOptions, renderDeclarations, renderToolSample, renderToolSignature, schemaToType, } from "./declarations.ts";
2
+ export { toCodemodeIdentifier } from "./identifier.ts";
3
+ export { CodemodeSandbox } from "./runtime/host.ts";
4
+ export { MAX_STORE_TOTAL_CHARS, MAX_STORE_VALUE_CHARS } from "./runtime/prelude-source.ts";
5
+ export { CODEMODE_OPTIONS_PREFIX, CODEMODE_SOURCE_GRAMMAR, CodemodeSourceError, type CodemodeSourceOptions, type ParsedCodemodeSource, parseCodemodeSource, } from "./source.ts";
6
+ export type { CodemodeCall, CodemodeCallStatus, CodemodeError, CodemodeErrorKind, CodemodeExecuteOptions, CodemodeJsonSchema, CodemodeOutputItem, CodemodeResult, CodemodeSandboxOptions, CodemodeStoreWrites, CodemodeTool, CodemodeToolContext, } from "./types.ts";
7
+ export { type CodemodeWasmModule, loadQuickJSWasm } from "./wasm.ts";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,8BAA8B,EAC9B,uBAAuB,EACvB,0BAA0B,EAC1B,KAAK,yBAAyB,EAC9B,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,GACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAC3F,OAAO,EACN,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACnB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,mBAAmB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EACX,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,sBAAsB,EACtB,mBAAmB,EACnB,YAAY,EACZ,mBAAmB,GACnB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,kBAAkB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export { DEFAULT_INPUT_SCHEMA_MAX_CHARS, MCP_TYPESCRIPT_PREAMBLE, mcpStructuredContentSchema, renderDeclarations, renderToolSample, renderToolSignature, schemaToType, } from "./declarations.js";
2
+ export { toCodemodeIdentifier } from "./identifier.js";
3
+ export { CodemodeSandbox } from "./runtime/host.js";
4
+ export { MAX_STORE_TOTAL_CHARS, MAX_STORE_VALUE_CHARS } from "./runtime/prelude-source.js";
5
+ export { CODEMODE_OPTIONS_PREFIX, CODEMODE_SOURCE_GRAMMAR, CodemodeSourceError, parseCodemodeSource, } from "./source.js";
6
+ export { loadQuickJSWasm } from "./wasm.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,8BAA8B,EAC9B,uBAAuB,EACvB,0BAA0B,EAE1B,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,GACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAC3F,OAAO,EACN,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EAGnB,mBAAmB,GACnB,MAAM,aAAa,CAAC;AAerB,OAAO,EAA2B,eAAe,EAAE,MAAM,WAAW,CAAC","sourcesContent":["export {\n\tDEFAULT_INPUT_SCHEMA_MAX_CHARS,\n\tMCP_TYPESCRIPT_PREAMBLE,\n\tmcpStructuredContentSchema,\n\ttype RenderDeclarationsOptions,\n\trenderDeclarations,\n\trenderToolSample,\n\trenderToolSignature,\n\tschemaToType,\n} from \"./declarations.ts\";\nexport { toCodemodeIdentifier } from \"./identifier.ts\";\nexport { CodemodeSandbox } from \"./runtime/host.ts\";\nexport { MAX_STORE_TOTAL_CHARS, MAX_STORE_VALUE_CHARS } from \"./runtime/prelude-source.ts\";\nexport {\n\tCODEMODE_OPTIONS_PREFIX,\n\tCODEMODE_SOURCE_GRAMMAR,\n\tCodemodeSourceError,\n\ttype CodemodeSourceOptions,\n\ttype ParsedCodemodeSource,\n\tparseCodemodeSource,\n} from \"./source.ts\";\nexport type {\n\tCodemodeCall,\n\tCodemodeCallStatus,\n\tCodemodeError,\n\tCodemodeErrorKind,\n\tCodemodeExecuteOptions,\n\tCodemodeJsonSchema,\n\tCodemodeOutputItem,\n\tCodemodeResult,\n\tCodemodeSandboxOptions,\n\tCodemodeStoreWrites,\n\tCodemodeTool,\n\tCodemodeToolContext,\n} from \"./types.ts\";\nexport { type CodemodeWasmModule, loadQuickJSWasm } from \"./wasm.ts\";\n"]}
@@ -0,0 +1,35 @@
1
+ import type { CodemodeExecuteOptions, CodemodeResult, CodemodeSandboxOptions, CodemodeTool } from "../types.ts";
2
+ /**
3
+ * Runs JavaScript in a QuickJS VM (a separate wasm instance) inside a worker
4
+ * thread. The script sees `tools.<name>(args)` for every registered tool, `ALL_TOOLS`,
5
+ * the output helpers `text`, `image`, `exit`, and `console.*`, `store`/`load`, and the
6
+ * configured globals; nothing else (no timers, `fetch`, `process`, `require`, modules).
7
+ *
8
+ * Each `execute()` gets its own worker and VM; the sandbox only holds the tool
9
+ * table and defaults. `close()` aborts in-flight executions.
10
+ */
11
+ export declare class CodemodeSandbox {
12
+ private readonly toolsByName;
13
+ private readonly globalsByName;
14
+ private readonly timeoutMs;
15
+ private readonly memoryLimitBytes;
16
+ private readonly wasm;
17
+ private readonly workerUrl;
18
+ private readonly running;
19
+ private closed;
20
+ constructor(options?: CodemodeSandboxOptions);
21
+ /** Throws if a tool with the same name is already registered. */
22
+ registerTool(tool: CodemodeTool): void;
23
+ unregisterTool(name: string): boolean;
24
+ get tools(): CodemodeTool[];
25
+ get globals(): CodemodeTool[];
26
+ /**
27
+ * `code` is an async function body: `return` and top-level `await` work.
28
+ * Never rejects for script failures; those come back as `{ ok: false }`.
29
+ * The script can use `store(key, value)` and `load(key)` on `options.store`.
30
+ */
31
+ execute(code: string, options?: CodemodeExecuteOptions): Promise<CodemodeResult>;
32
+ /** Aborts in-flight executions (they resolve with `kind: "aborted"`) and rejects new ones. */
33
+ close(): Promise<void>;
34
+ }
35
+ //# sourceMappingURL=host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/runtime/host.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAIX,sBAAsB,EAEtB,cAAc,EACd,sBAAsB,EAEtB,YAAY,EACZ,MAAM,aAAa,CAAC;AAuQrB;;;;;;;;GAQG;AACH,qBAAa,eAAe;IAC3B,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,IAAI,CAA+D;IACpF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAM;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,MAAM,CAAS;IAEvB,YAAY,OAAO,GAAE,sBAA2B,EAmB/C;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,CAenF;IAED,8FAA8F;IACxF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAG3B;CACD"}
@@ -0,0 +1,314 @@
1
+ import { Worker } from "node:worker_threads";
2
+ import { toCodemodeIdentifier } from "../identifier.js";
3
+ import { loadQuickJSWasm } from "../wasm.js";
4
+ import { isWorkerToHostMessage, } from "./protocol.js";
5
+ const DEFAULT_TIMEOUT_MS = 300_000;
6
+ const IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
7
+ const RESERVED_GLOBALS = new Set([
8
+ "tools",
9
+ "ALL_TOOLS",
10
+ "console",
11
+ "text",
12
+ "image",
13
+ "exit",
14
+ "globalThis",
15
+ "store",
16
+ "load",
17
+ ]);
18
+ function errorMessage(error) {
19
+ return error instanceof Error ? error.message : String(error);
20
+ }
21
+ function serializeStore(store) {
22
+ const serialized = {};
23
+ for (const [key, value] of Object.entries(store ?? {})) {
24
+ const json = JSON.stringify(value);
25
+ if (json !== undefined)
26
+ serialized[key] = json;
27
+ }
28
+ return serialized;
29
+ }
30
+ function parseStoreWrites(json) {
31
+ const writes = { set: {}, delete: [] };
32
+ for (const [key, value] of JSON.parse(json)) {
33
+ if (value === undefined)
34
+ writes.delete.push(key);
35
+ else
36
+ writes.set[key] = JSON.parse(value);
37
+ }
38
+ return writes;
39
+ }
40
+ function defaultWorkerUrl() {
41
+ // `.ts` when running from source (tests, tsx), `.js` from the published dist.
42
+ return new URL(import.meta.url.endsWith(".ts") ? "./worker.ts" : "./worker.js", import.meta.url);
43
+ }
44
+ /**
45
+ * One script run in its own worker and QuickJS VM. A fresh worker per run keeps
46
+ * termination simple: a runaway script, including one that only spins the
47
+ * microtask queue, is killed with `terminate()` and cannot poison a later run.
48
+ */
49
+ class Execution {
50
+ promise;
51
+ resolveResult;
52
+ worker;
53
+ interrupt = new SharedArrayBuffer(4);
54
+ tools;
55
+ globals;
56
+ signal;
57
+ timer;
58
+ output = [];
59
+ calls = [];
60
+ pending = new Map();
61
+ finished = false;
62
+ constructor(options) {
63
+ this.promise = new Promise((resolve) => {
64
+ this.resolveResult = resolve;
65
+ });
66
+ this.tools = options.tools;
67
+ this.globals = options.globals;
68
+ this.signal = options.signal;
69
+ if (Number.isFinite(options.timeoutMs)) {
70
+ this.timer = setTimeout(() => {
71
+ this.finish({ kind: "timeout", message: `Execution timed out after ${options.timeoutMs} ms` });
72
+ }, options.timeoutMs);
73
+ }
74
+ if (options.signal) {
75
+ if (options.signal.aborted) {
76
+ this.onAbort();
77
+ }
78
+ else {
79
+ options.signal.addEventListener("abort", this.onAbort, { once: true });
80
+ }
81
+ }
82
+ options.wasm.then((wasm) => this.start(options, wasm), (error) => {
83
+ this.finish({ kind: "sandbox", message: `Failed to load QuickJS: ${errorMessage(error)}` });
84
+ });
85
+ }
86
+ abort(message) {
87
+ this.finish({ kind: "aborted", message });
88
+ return this.promise;
89
+ }
90
+ start(options, wasm) {
91
+ if (this.finished)
92
+ return;
93
+ const workerData = {
94
+ code: options.code,
95
+ tools: [...options.tools.values()].map((tool) => ({
96
+ name: tool.name,
97
+ jsName: toCodemodeIdentifier(tool.name),
98
+ description: tool.description ?? "",
99
+ })),
100
+ globals: [...options.globals.values()].map((global) => ({
101
+ name: global.name,
102
+ spread: global.spread === true,
103
+ })),
104
+ wasm,
105
+ memoryLimitBytes: options.memoryLimitBytes,
106
+ store: options.store,
107
+ interrupt: this.interrupt,
108
+ };
109
+ let worker;
110
+ try {
111
+ worker = new Worker(options.workerUrl, { workerData });
112
+ }
113
+ catch (error) {
114
+ this.finish({ kind: "sandbox", message: `Failed to start worker: ${errorMessage(error)}` });
115
+ return;
116
+ }
117
+ this.worker = worker;
118
+ worker.on("message", (message) => this.handleMessage(message));
119
+ worker.on("error", (error) => {
120
+ this.finish({
121
+ kind: "sandbox",
122
+ name: error instanceof Error ? error.name : undefined,
123
+ message: errorMessage(error),
124
+ });
125
+ });
126
+ worker.on("exit", (code) => {
127
+ this.finish({ kind: "sandbox", message: `Worker exited with code ${code} before the script settled` });
128
+ });
129
+ }
130
+ onAbort = () => {
131
+ const reason = this.signal?.reason;
132
+ this.finish({ kind: "aborted", message: reason instanceof Error ? reason.message : "Execution aborted" });
133
+ };
134
+ post(message) {
135
+ this.worker?.postMessage(message);
136
+ }
137
+ handleMessage(message) {
138
+ if (this.finished || !isWorkerToHostMessage(message))
139
+ return;
140
+ switch (message.type) {
141
+ case "output":
142
+ this.output.push(message.item);
143
+ break;
144
+ case "call":
145
+ void this.handleCall(message);
146
+ break;
147
+ case "done":
148
+ this.handleDone(message);
149
+ break;
150
+ case "crash":
151
+ this.finish({ kind: "sandbox", message: message.message });
152
+ break;
153
+ }
154
+ }
155
+ handleDone(message) {
156
+ if (!message.ok) {
157
+ const parsed = JSON.parse(message.error);
158
+ this.finish({ kind: "script", ...parsed });
159
+ return;
160
+ }
161
+ this.finish(undefined, message.value === undefined ? undefined : JSON.parse(message.value), message.writes);
162
+ }
163
+ async handleCall(message) {
164
+ const { id, name } = message;
165
+ const isTool = message.target === "tool";
166
+ const record = isTool ? { name, status: "cancelled", durationMs: 0 } : undefined;
167
+ if (record)
168
+ this.calls.push(record);
169
+ const pending = { record, startedAt: performance.now(), controller: new AbortController() };
170
+ this.pending.set(id, pending);
171
+ let status;
172
+ let reply;
173
+ try {
174
+ const tool = (isTool ? this.tools : this.globals).get(name);
175
+ if (!tool)
176
+ throw new Error(`Unknown ${isTool ? "tool" : "global"} "${name}"`);
177
+ const args = message.args === undefined ? undefined : JSON.parse(message.args);
178
+ const value = await tool.execute(args, { signal: pending.controller.signal });
179
+ reply = { type: "result", id, ok: true, payload: value === undefined ? undefined : JSON.stringify(value) };
180
+ status = "ok";
181
+ }
182
+ catch (error) {
183
+ reply = { type: "result", id, ok: false, payload: errorMessage(error) };
184
+ status = "error";
185
+ }
186
+ // Already cancelled by finish(): the record keeps "cancelled" and the
187
+ // worker is gone or going.
188
+ if (!this.pending.delete(id))
189
+ return;
190
+ if (record) {
191
+ record.status = status;
192
+ record.durationMs = performance.now() - pending.startedAt;
193
+ }
194
+ this.post(reply);
195
+ }
196
+ finish(error, value, writes) {
197
+ if (this.finished)
198
+ return;
199
+ this.finished = true;
200
+ clearTimeout(this.timer);
201
+ this.signal?.removeEventListener("abort", this.onAbort);
202
+ const now = performance.now();
203
+ for (const pending of this.pending.values()) {
204
+ if (pending.record)
205
+ pending.record.durationMs = now - pending.startedAt;
206
+ pending.controller.abort();
207
+ }
208
+ this.pending.clear();
209
+ const result = error
210
+ ? { ok: false, error, output: this.output, calls: this.calls }
211
+ : {
212
+ ok: true,
213
+ value,
214
+ output: this.output,
215
+ calls: this.calls,
216
+ storeWrites: writes === undefined ? { set: {}, delete: [] } : parseStoreWrites(writes),
217
+ };
218
+ if (!this.worker) {
219
+ this.resolveResult(result);
220
+ return;
221
+ }
222
+ Atomics.store(new Int32Array(this.interrupt), 0, 1);
223
+ this.worker
224
+ .terminate()
225
+ .catch(() => undefined)
226
+ .then(() => this.resolveResult(result));
227
+ }
228
+ }
229
+ /**
230
+ * Runs JavaScript in a QuickJS VM (a separate wasm instance) inside a worker
231
+ * thread. The script sees `tools.<name>(args)` for every registered tool, `ALL_TOOLS`,
232
+ * the output helpers `text`, `image`, `exit`, and `console.*`, `store`/`load`, and the
233
+ * configured globals; nothing else (no timers, `fetch`, `process`, `require`, modules).
234
+ *
235
+ * Each `execute()` gets its own worker and VM; the sandbox only holds the tool
236
+ * table and defaults. `close()` aborts in-flight executions.
237
+ */
238
+ export class CodemodeSandbox {
239
+ toolsByName = new Map();
240
+ globalsByName = new Map();
241
+ timeoutMs;
242
+ memoryLimitBytes;
243
+ wasm;
244
+ workerUrl;
245
+ running = new Set();
246
+ closed = false;
247
+ constructor(options = {}) {
248
+ this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
249
+ this.memoryLimitBytes = options.memoryLimitBytes;
250
+ this.wasm = options.wasm;
251
+ this.workerUrl = options.workerUrl ?? defaultWorkerUrl();
252
+ for (const tool of options.tools ?? [])
253
+ this.registerTool(tool);
254
+ const namespaces = new Set();
255
+ for (const global of options.globals ?? []) {
256
+ const parts = global.name.split(".");
257
+ if (parts.length > 2 || !parts.every((part) => IDENTIFIER.test(part)) || RESERVED_GLOBALS.has(parts[0])) {
258
+ throw new Error(`Invalid global name "${global.name}"`);
259
+ }
260
+ if (this.globalsByName.has(global.name))
261
+ throw new Error(`Global "${global.name}" is already registered`);
262
+ if (parts.length === 2)
263
+ namespaces.add(parts[0]);
264
+ this.globalsByName.set(global.name, global);
265
+ }
266
+ for (const name of namespaces) {
267
+ if (this.globalsByName.has(name))
268
+ throw new Error(`Global "${name}" conflicts with the namespace "${name}"`);
269
+ }
270
+ }
271
+ /** Throws if a tool with the same name is already registered. */
272
+ registerTool(tool) {
273
+ if (this.toolsByName.has(tool.name))
274
+ throw new Error(`Tool "${tool.name}" is already registered`);
275
+ this.toolsByName.set(tool.name, tool);
276
+ }
277
+ unregisterTool(name) {
278
+ return this.toolsByName.delete(name);
279
+ }
280
+ get tools() {
281
+ return [...this.toolsByName.values()];
282
+ }
283
+ get globals() {
284
+ return [...this.globalsByName.values()];
285
+ }
286
+ /**
287
+ * `code` is an async function body: `return` and top-level `await` work.
288
+ * Never rejects for script failures; those come back as `{ ok: false }`.
289
+ * The script can use `store(key, value)` and `load(key)` on `options.store`.
290
+ */
291
+ execute(code, options = {}) {
292
+ if (this.closed)
293
+ return Promise.reject(new Error("Sandbox is closed"));
294
+ const execution = new Execution({
295
+ code,
296
+ tools: new Map(this.toolsByName),
297
+ globals: this.globalsByName,
298
+ timeoutMs: options.timeoutMs ?? this.timeoutMs,
299
+ signal: options.signal,
300
+ memoryLimitBytes: this.memoryLimitBytes,
301
+ store: serializeStore(options.store),
302
+ wasm: this.wasm === undefined ? loadQuickJSWasm() : Promise.resolve(this.wasm),
303
+ workerUrl: this.workerUrl,
304
+ });
305
+ this.running.add(execution);
306
+ return execution.promise.finally(() => this.running.delete(execution));
307
+ }
308
+ /** Aborts in-flight executions (they resolve with `kind: "aborted"`) and rejects new ones. */
309
+ async close() {
310
+ this.closed = true;
311
+ await Promise.all([...this.running].map((execution) => execution.abort("Sandbox closed")));
312
+ }
313
+ }
314
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/runtime/host.ts"],"names":[],"mappings":"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","sourcesContent":["import { Worker } from \"node:worker_threads\";\nimport { toCodemodeIdentifier } from \"../identifier.ts\";\nimport type {\n\tCodemodeCall,\n\tCodemodeCallStatus,\n\tCodemodeError,\n\tCodemodeExecuteOptions,\n\tCodemodeOutputItem,\n\tCodemodeResult,\n\tCodemodeSandboxOptions,\n\tCodemodeStoreWrites,\n\tCodemodeTool,\n} from \"../types.ts\";\nimport { type CodemodeWasmModule, loadQuickJSWasm } from \"../wasm.ts\";\nimport {\n\ttype HostToWorkerMessage,\n\tisWorkerToHostMessage,\n\ttype WorkerData,\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\nfunction 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\nfunction parseStoreWrites(json: string): CodemodeStoreWrites {\n\tconst writes: CodemodeStoreWrites = { set: {}, delete: [] };\n\tfor (const [key, value] of JSON.parse(json) as [string, string?][]) {\n\t\tif (value === undefined) writes.delete.push(key);\n\t\telse writes.set[key] = JSON.parse(value);\n\t}\n\treturn writes;\n}\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\ninterface PendingCall {\n\trecord: CodemodeCall | undefined;\n\tstartedAt: number;\n\tcontroller: AbortController;\n}\n\ninterface ExecutionOptions {\n\tcode: string;\n\ttools: ReadonlyMap<string, CodemodeTool>;\n\tglobals: ReadonlyMap<string, CodemodeTool>;\n\ttimeoutMs: number;\n\tsignal: AbortSignal | undefined;\n\tmemoryLimitBytes: number | undefined;\n\tstore: Record<string, string>;\n\twasm: Promise<CodemodeWasmModule>;\n\tworkerUrl: URL;\n}\n\n/**\n * One script run in its own worker and QuickJS VM. A fresh worker per run keeps\n * termination simple: a runaway script, including one that only spins the\n * microtask queue, is killed with `terminate()` and cannot poison a later run.\n */\nclass Execution {\n\treadonly promise: Promise<CodemodeResult>;\n\tprivate resolveResult!: (result: CodemodeResult) => void;\n\tprivate worker: Worker | undefined;\n\tprivate readonly interrupt = new SharedArrayBuffer(4);\n\tprivate readonly tools: ReadonlyMap<string, CodemodeTool>;\n\tprivate readonly globals: ReadonlyMap<string, CodemodeTool>;\n\tprivate readonly signal: AbortSignal | undefined;\n\tprivate readonly timer: NodeJS.Timeout | undefined;\n\tprivate readonly output: CodemodeOutputItem[] = [];\n\tprivate readonly calls: CodemodeCall[] = [];\n\tprivate readonly pending = new Map<number, PendingCall>();\n\tprivate finished = 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.tools = options.tools;\n\t\tthis.globals = options.globals;\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\n\t\toptions.wasm.then(\n\t\t\t(wasm) => this.start(options, wasm),\n\t\t\t(error: unknown) => {\n\t\t\t\tthis.finish({ kind: \"sandbox\", message: `Failed to load QuickJS: ${errorMessage(error)}` });\n\t\t\t},\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 start(options: ExecutionOptions, wasm: CodemodeWasmModule): void {\n\t\tif (this.finished) return;\n\t\tconst workerData: WorkerData = {\n\t\t\tcode: options.code,\n\t\t\ttools: [...options.tools.values()].map((tool) => ({\n\t\t\t\tname: tool.name,\n\t\t\t\tjsName: toCodemodeIdentifier(tool.name),\n\t\t\t\tdescription: tool.description ?? \"\",\n\t\t\t})),\n\t\t\tglobals: [...options.globals.values()].map((global) => ({\n\t\t\t\tname: global.name,\n\t\t\t\tspread: global.spread === true,\n\t\t\t})),\n\t\t\twasm,\n\t\t\tmemoryLimitBytes: options.memoryLimitBytes,\n\t\t\tstore: options.store,\n\t\t\tinterrupt: this.interrupt,\n\t\t};\n\t\tlet worker: Worker;\n\t\ttry {\n\t\t\tworker = new Worker(options.workerUrl, { workerData });\n\t\t} catch (error) {\n\t\t\tthis.finish({ kind: \"sandbox\", message: `Failed to start worker: ${errorMessage(error)}` });\n\t\t\treturn;\n\t\t}\n\t\tthis.worker = worker;\n\t\tworker.on(\"message\", (message: unknown) => this.handleMessage(message));\n\t\tworker.on(\"error\", (error: unknown) => {\n\t\t\tthis.finish({\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\tthis.finish({ kind: \"sandbox\", message: `Worker exited with code ${code} before the script settled` });\n\t\t});\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\tthis.worker?.postMessage(message);\n\t}\n\n\tprivate handleMessage(message: unknown): void {\n\t\tif (this.finished || !isWorkerToHostMessage(message)) return;\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\tvoid this.handleCall(message);\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\tif (!message.ok) {\n\t\t\tconst parsed = JSON.parse(message.error) as Omit<CodemodeError, \"kind\">;\n\t\t\tthis.finish({ kind: \"script\", ...parsed });\n\t\t\treturn;\n\t\t}\n\t\tthis.finish(undefined, message.value === undefined ? undefined : JSON.parse(message.value), message.writes);\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.tools : this.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// worker 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(error: CodemodeError | undefined, value?: unknown, writes?: string): 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\n\t\tconst result: CodemodeResult = error\n\t\t\t? { ok: false, error, output: this.output, calls: this.calls }\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 === undefined ? { set: {}, delete: [] } : parseStoreWrites(writes),\n\t\t\t\t};\n\t\tif (!this.worker) {\n\t\t\tthis.resolveResult(result);\n\t\t\treturn;\n\t\t}\n\t\tAtomics.store(new Int32Array(this.interrupt), 0, 1);\n\t\tthis.worker\n\t\t\t.terminate()\n\t\t\t.catch(() => undefined)\n\t\t\t.then(() => this.resolveResult(result));\n\t}\n}\n\n/**\n * Runs JavaScript in a QuickJS VM (a separate wasm instance) inside a worker\n * thread. The script sees `tools.<name>(args)` for every registered tool, `ALL_TOOLS`,\n * the output helpers `text`, `image`, `exit`, and `console.*`, `store`/`load`, and the\n * configured globals; nothing else (no timers, `fetch`, `process`, `require`, modules).\n *\n * Each `execute()` gets its own worker and VM; the sandbox only holds the tool\n * table and defaults. `close()` aborts in-flight executions.\n */\nexport class CodemodeSandbox {\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 wasm: CodemodeWasmModule | Promise<CodemodeWasmModule> | undefined;\n\tprivate readonly workerUrl: URL;\n\tprivate readonly running = new Set<Execution>();\n\tprivate closed = false;\n\n\tconstructor(options: CodemodeSandboxOptions = {}) {\n\t\tthis.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\t\tthis.memoryLimitBytes = options.memoryLimitBytes;\n\t\tthis.wasm = options.wasm;\n\t\tthis.workerUrl = options.workerUrl ?? defaultWorkerUrl();\n\t\tfor (const tool of options.tools ?? []) this.registerTool(tool);\n\t\tconst namespaces = new Set<string>();\n\t\tfor (const global of options.globals ?? []) {\n\t\t\tconst parts = global.name.split(\".\");\n\t\t\tif (parts.length > 2 || !parts.every((part) => IDENTIFIER.test(part)) || RESERVED_GLOBALS.has(parts[0])) {\n\t\t\t\tthrow new Error(`Invalid global name \"${global.name}\"`);\n\t\t\t}\n\t\t\tif (this.globalsByName.has(global.name)) throw new Error(`Global \"${global.name}\" is already registered`);\n\t\t\tif (parts.length === 2) namespaces.add(parts[0]);\n\t\t\tthis.globalsByName.set(global.name, global);\n\t\t}\n\t\tfor (const name of namespaces) {\n\t\t\tif (this.globalsByName.has(name)) throw new Error(`Global \"${name}\" conflicts with the namespace \"${name}\"`);\n\t\t}\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 execution = new Execution({\n\t\t\tcode,\n\t\t\ttools: new Map(this.toolsByName),\n\t\t\tglobals: 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\twasm: this.wasm === undefined ? loadQuickJSWasm() : Promise.resolve(this.wasm),\n\t\t\tworkerUrl: this.workerUrl,\n\t\t});\n\t\tthis.running.add(execution);\n\t\treturn execution.promise.finally(() => this.running.delete(execution));\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"]}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * JavaScript evaluated inside the QuickJS VM before the script runs.
3
+ *
4
+ * The VM is its own wasm instance, so nothing here guards a realm boundary.
5
+ * The prelude keeps the host bridge in a closure so the script cannot call it
6
+ * directly, and builds `tools`, `ALL_TOOLS`, the output helpers (`text`, `image`,
7
+ * `exit`, `console`), and globals on top of it. Tool arguments and results cross
8
+ * as JSON strings and are parsed on this side.
9
+ *
10
+ * Output helpers: `text(value)` appends a text item (non-strings are
11
+ * JSON-stringified), `image(urlOrItem)` appends an image from a base64 `data:` URL, an
12
+ * `{ image_url }` object, or an MCP `ImageContent` block, and `exit()` ends the script
13
+ * successfully. `console.*` appends text items like `text()`.
14
+ *
15
+ * `store(key, value)` and `load(key)` are synchronous: they work on a snapshot of
16
+ * JSON text passed in as `storeJson`, and the keys the script wrote are reported
17
+ * with a successful "done".
18
+ *
19
+ * Evaluates to a function `(bridge, toolsJson, globalsJson, storeJson) => { settle, run, stalled }`.
20
+ * `toolsJson` lists `{ name, jsName, description }`: `tools[jsName]` and `tools[name]` call the
21
+ * tool, and `ALL_TOOLS` lists `{ name: jsName, description }`.
22
+ * `stalled()` reports a script that has not finished while no host call is pending: with no timers
23
+ * or I/O in the VM, nothing can ever resume it.
24
+ * `globalsJson` lists `{ name, spread }`; `a.b` names are grouped into a frozen `a` object.
25
+ * `bridge(kind, a, b, c)` with kind "call" or "global" (id, name, argsJson),
26
+ * "output" ("text", text) or ("image", data, mimeType), or "done" (ok, valueJsonOrErrorJson, writesJson).
27
+ */
28
+ export declare const MAX_STORE_VALUE_CHARS: number;
29
+ export declare const MAX_STORE_TOTAL_CHARS: number;
30
+ export declare const PRELUDE_SOURCE: string;
31
+ //# sourceMappingURL=prelude-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prelude-source.d.ts","sourceRoot":"","sources":["../../src/runtime/prelude-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,qBAAqB,QAAa,CAAC;AAChD,eAAO,MAAM,qBAAqB,QAAc,CAAC;AAKjD,eAAO,MAAM,cAAc,EAAE,MAkS1B,CAAC"}