@mcploom/codexec-isolated-vm 0.1.3 → 0.2.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 CHANGED
@@ -4,14 +4,12 @@
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/%40mcploom%2Fcodexec--isolated--vm?style=flat-square)](https://www.npmjs.com/package/@mcploom/codexec-isolated-vm)
6
6
  [![License](https://img.shields.io/github/license/aallam/mcploom?style=flat-square)](https://github.com/aallam/mcploom/blob/main/LICENSE)
7
- [![Examples](https://img.shields.io/badge/examples-codexec-0ea5e9?style=flat-square)](https://github.com/aallam/mcploom/tree/main/examples)
8
- [![CI](https://img.shields.io/github/actions/workflow/status/aallam/mcploom/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/aallam/mcploom/actions/workflows/ci.yml)
9
7
 
10
8
  ## Choose `isolated-vm` When
11
9
 
12
10
  - you explicitly want the `isolated-vm` runtime instead of QuickJS
13
11
  - your environment can support the native addon install
14
- - you are prepared to run Node 20+ with `--no-node-snapshot`
12
+ - you are prepared to run Node 22+ with `--no-node-snapshot`
15
13
 
16
14
  If you want the simpler default backend, use [`@mcploom/codexec-quickjs`](https://www.npmjs.com/package/@mcploom/codexec-quickjs) instead.
17
15
 
@@ -19,6 +17,7 @@ If you want the simpler default backend, use [`@mcploom/codexec-quickjs`](https:
19
17
 
20
18
  - [Basic provider execution on `isolated-vm`](https://github.com/aallam/mcploom/blob/main/examples/codexec-isolated-vm-basic.ts)
21
19
  - [QuickJS-based codexec examples for the shared API surface](https://github.com/aallam/mcploom/blob/main/examples/codexec-basic.ts)
20
+ - [Worker-backed QuickJS example for the alternate transport-backed path](https://github.com/aallam/mcploom/blob/main/examples/codexec-worker.ts)
22
21
  - [Full examples index](https://github.com/aallam/mcploom/tree/main/examples)
23
22
 
24
23
  ## Install
@@ -29,9 +28,10 @@ npm install @mcploom/codexec @mcploom/codexec-isolated-vm
29
28
 
30
29
  ## Requirements
31
30
 
32
- - Node 20+ must run with `--no-node-snapshot`
31
+ - Node 22+ must run with `--no-node-snapshot`
33
32
  - the optional `isolated-vm` native dependency must install successfully in the host environment
34
33
  - native-addon failures are surfaced when `IsolatedVmExecutor` is constructed or used
34
+ - advanced consumers can import the reusable runner from `@mcploom/codexec-isolated-vm/runner`
35
35
 
36
36
  ## Security Notes
37
37
 
@@ -40,6 +40,12 @@ npm install @mcploom/codexec @mcploom/codexec-isolated-vm
40
40
  - This package is still in-process execution. It should not be marketed or relied on as a hard security boundary for hostile code.
41
41
  - Providers remain the real capability boundary. If a tool is dangerous, guest code can invoke it.
42
42
 
43
+ ## Architecture Docs
44
+
45
+ - [Codexec architecture overview](https://github.com/aallam/mcploom/blob/main/docs/architecture/codexec-overview.md)
46
+ - [Codexec executors](https://github.com/aallam/mcploom/blob/main/docs/architecture/codexec-executors.md)
47
+ - [Codexec MCP adapters and protocol](https://github.com/aallam/mcploom/blob/main/docs/architecture/codexec-mcp-and-protocol.md)
48
+
43
49
  ## Usage
44
50
 
45
51
  ```ts
package/dist/index.cjs CHANGED
@@ -1,363 +1,42 @@
1
- let node_crypto = require("node:crypto");
1
+ const require_runner = require('./runner-cprbphYc.cjs');
2
2
  let __mcploom_codexec = require("@mcploom/codexec");
3
3
 
4
4
  //#region src/isolatedVmExecutor.ts
5
- const DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;
6
- const DEFAULT_TIMEOUT_MS = 5e3;
7
- const DEFAULT_MAX_LOG_LINES = 100;
8
- const DEFAULT_MAX_LOG_CHARS = 64e3;
9
- let cachedModulePromise;
10
- function createExecutionContext(signal, providerName, safeToolName, originalToolName) {
11
- return {
12
- originalToolName,
13
- providerName,
14
- safeToolName,
15
- signal
16
- };
17
- }
18
- function hasRequiredNodeFlag() {
19
- const execArgv = process.execArgv.join(" ");
20
- const nodeOptions = process.env.NODE_OPTIONS ?? "";
21
- return execArgv.includes("--no-node-snapshot") || nodeOptions.includes("--no-node-snapshot");
22
- }
23
- function isKnownErrorCode(value) {
24
- return value === "timeout" || value === "memory_limit" || value === "validation_error" || value === "tool_error" || value === "runtime_error" || value === "serialization_error" || value === "internal_error";
25
- }
26
- function normalizeThrownMessage(error) {
27
- if (error instanceof Error) return error.message;
28
- if (typeof error === "object" && error !== null && "message" in error) {
29
- const message = error.message;
30
- if (typeof message === "string") return message;
31
- }
32
- return String(error);
33
- }
34
- function truncateLogs(logs, maxLogLines, maxLogChars) {
35
- const limitedLines = logs.slice(0, maxLogLines);
36
- let remainingChars = maxLogChars;
37
- const truncated = [];
38
- for (const line of limitedLines) {
39
- if (remainingChars <= 0) break;
40
- if (line.length <= remainingChars) {
41
- truncated.push(line);
42
- remainingChars -= line.length;
43
- continue;
44
- }
45
- truncated.push(line.slice(0, remainingChars));
46
- break;
47
- }
48
- return truncated;
49
- }
50
- function formatLogValue(value) {
51
- if (typeof value === "string") return value;
52
- if (value === void 0) return "undefined";
53
- try {
54
- return JSON.stringify(value);
55
- } catch {
56
- return String(value);
57
- }
58
- }
59
- function formatConsoleLine(values) {
60
- return values.map((value) => formatLogValue(value)).join(" ");
61
- }
62
- function toJsonValue(value, message) {
63
- if (value === void 0) return;
64
- const jsonValue = JSON.stringify(value);
65
- if (jsonValue === void 0) throw new __mcploom_codexec.ExecuteFailure("serialization_error", message);
66
- try {
67
- return JSON.parse(jsonValue);
68
- } catch {
69
- throw new __mcploom_codexec.ExecuteFailure("serialization_error", message);
70
- }
71
- }
72
- function toTransferableValue(ivm, value) {
73
- const normalizedValue = toJsonValue(value, "Host value is not JSON-serializable");
74
- if (normalizedValue === null || normalizedValue === void 0 || typeof normalizedValue === "string" || typeof normalizedValue === "number" || typeof normalizedValue === "boolean") return normalizedValue;
75
- return new ivm.ExternalCopy(normalizedValue).copyInto({ release: true });
76
- }
77
- function toExecuteError(error, deadline) {
78
- if (typeof error === "object" && error !== null && "code" in error && "message" in error && isKnownErrorCode(error.code) && typeof error.message === "string") return {
79
- code: error.code,
80
- message: error.message
81
- };
82
- if ((0, __mcploom_codexec.isExecuteFailure)(error)) return {
83
- code: error.code,
84
- message: error.message
85
- };
86
- const message = normalizeThrownMessage(error);
87
- const normalizedMessage = message.toLowerCase();
88
- if (Date.now() > deadline || normalizedMessage.includes("timed out") || normalizedMessage.includes("time limit")) return {
89
- code: "timeout",
90
- message: "Execution timed out"
91
- };
92
- if (normalizedMessage.includes("memory limit") || normalizedMessage.includes("out of memory")) return {
93
- code: "memory_limit",
94
- message
95
- };
96
- if (normalizedMessage.includes("could not be cloned") || normalizedMessage.includes("non-transferable") || normalizedMessage.includes("not json-serializable")) return {
97
- code: "serialization_error",
98
- message
99
- };
100
- return {
101
- code: "runtime_error",
102
- message
103
- };
104
- }
105
- function toMemoryLimitMb(memoryLimitBytes) {
106
- return Math.max(8, Math.ceil(memoryLimitBytes / (1024 * 1024)));
107
- }
108
- function remainingTime(deadline) {
109
- return Math.max(0, deadline - Date.now());
110
- }
111
- async function runWithDeadline(operation, deadline, signal) {
112
- if (signal.aborted || Date.now() > deadline) throw new __mcploom_codexec.ExecuteFailure("timeout", "Execution timed out");
113
- const timeoutMs = remainingTime(deadline);
114
- if (timeoutMs <= 0) throw new __mcploom_codexec.ExecuteFailure("timeout", "Execution timed out");
115
- let timeoutId;
116
- return await new Promise((resolve, reject) => {
117
- const onAbort = () => {
118
- reject(new __mcploom_codexec.ExecuteFailure("timeout", "Execution timed out"));
119
- };
120
- signal.addEventListener("abort", onAbort, { once: true });
121
- timeoutId = setTimeout(() => {
122
- signal.removeEventListener("abort", onAbort);
123
- reject(new __mcploom_codexec.ExecuteFailure("timeout", "Execution timed out"));
124
- }, timeoutMs);
125
- operation.then((value) => {
126
- signal.removeEventListener("abort", onAbort);
127
- if (timeoutId) clearTimeout(timeoutId);
128
- resolve(value);
129
- }, (error) => {
130
- signal.removeEventListener("abort", onAbort);
131
- if (timeoutId) clearTimeout(timeoutId);
132
- reject(error);
133
- });
134
- });
135
- }
136
- async function loadDefaultModule() {
137
- cachedModulePromise ??= import("isolated-vm").then((loaded) => {
138
- return "default" in loaded ? loaded.default : loaded;
139
- });
140
- return cachedModulePromise;
141
- }
142
- function createBootstrapSource(providers, hostErrorPrefix, timeoutMs) {
143
- const lines = [
144
- `const __MCP_HOST_ERROR_PREFIX = ${JSON.stringify(hostErrorPrefix)};`,
145
- `const __MCP_HOST_ERROR_KEY = ${JSON.stringify(`${hostErrorPrefix}key`)};`,
146
- "const __mcpCreateTrustedError = (code, message) => ({",
147
- " [__MCP_HOST_ERROR_KEY]: true,",
148
- " code,",
149
- " message,",
150
- "});",
151
- "const __mcpNormalizeTrustedError = (error) => {",
152
- " if (error && typeof error === 'object' && error[__MCP_HOST_ERROR_KEY] === true && typeof error.code === 'string' && typeof error.message === 'string') {",
153
- " return __mcpCreateTrustedError(error.code, error.message);",
154
- " }",
155
- " if (error && typeof error.message === 'string' && error.message.startsWith(__MCP_HOST_ERROR_PREFIX)) {",
156
- " try {",
157
- " const payload = JSON.parse(error.message.slice(__MCP_HOST_ERROR_PREFIX.length));",
158
- " if (payload && typeof payload.code === 'string' && typeof payload.message === 'string') {",
159
- " return __mcpCreateTrustedError(payload.code, payload.message);",
160
- " }",
161
- " } catch {}",
162
- " }",
163
- " return null;",
164
- "};",
165
- "const __mcpNormalizeGuestError = (error) => {",
166
- " const trusted = __mcpNormalizeTrustedError(error);",
167
- " if (trusted) {",
168
- " return trusted;",
169
- " }",
170
- " if (error && typeof error.message === 'string') {",
171
- " return { code: 'runtime_error', message: error.message };",
172
- " }",
173
- " return { code: 'runtime_error', message: String(error) };",
174
- "};",
175
- "const __mcpNormalizeHostError = (error) => {",
176
- " const trusted = __mcpNormalizeTrustedError(error);",
177
- " if (trusted) {",
178
- " return trusted;",
179
- " }",
180
- " if (error && typeof error === 'object' && typeof error.code === 'string' && typeof error.message === 'string') {",
181
- " return __mcpCreateTrustedError(error.code, error.message);",
182
- " }",
183
- " return __mcpNormalizeGuestError(error);",
184
- "};",
185
- "const __mcpRaiseNormalizedError = (error) => {",
186
- " throw __mcpNormalizeHostError(error);",
187
- "};",
188
- "const __mcpToJsonValue = (value) => {",
189
- " if (typeof value === 'undefined') {",
190
- " return undefined;",
191
- " }",
192
- " const json = JSON.stringify(value);",
193
- " if (typeof json === 'undefined') {",
194
- " throw __mcpCreateTrustedError(",
195
- " 'serialization_error',",
196
- " 'Guest code returned a non-serializable value'",
197
- " );",
198
- " }",
199
- " return JSON.parse(json);",
200
- "};",
201
- "globalThis.console = {",
202
- " log: (...args) => __mcp_console_log(...args),",
203
- " info: (...args) => __mcp_console_info(...args),",
204
- " warn: (...args) => __mcp_console_warn(...args),",
205
- " error: (...args) => __mcp_console_error(...args),",
206
- "};"
207
- ];
208
- for (const provider of providers) {
209
- lines.push(`globalThis.${provider.name} = {};`);
210
- for (const safeToolName of Object.keys(provider.tools)) {
211
- const hostReferenceName = `__mcp_tool_${provider.name}_${safeToolName}`;
212
- lines.push(`globalThis.${provider.name}.${safeToolName} = async (input) => {`, " try {", ` return await ${hostReferenceName}.applySyncPromise(undefined, [input], { arguments: { copy: true }, timeout: ${timeoutMs} });`, " } catch (error) {", " __mcpRaiseNormalizedError(error);", " }", "};");
213
- }
214
- }
215
- return lines.join("\n");
216
- }
217
- function createExecutionSource(code) {
218
- return [
219
- `const __mcpUserFunction = (${(0, __mcploom_codexec.normalizeCode)(code)});`,
220
- "return (async () => {",
221
- " try {",
222
- " const value = await __mcpUserFunction();",
223
- " return { ok: true, value: __mcpToJsonValue(value) };",
224
- " } catch (error) {",
225
- " return { ok: false, error: __mcpNormalizeGuestError(error) };",
226
- " }",
227
- "})();"
228
- ].join("\n");
229
- }
230
- function setConsoleBindings(context, logs) {
231
- const jail = context.global;
232
- jail.setSync("__mcp_console_log", (...args) => {
233
- logs.push(formatConsoleLine(args));
234
- });
235
- jail.setSync("__mcp_console_info", (...args) => {
236
- logs.push(formatConsoleLine(args));
237
- });
238
- jail.setSync("__mcp_console_warn", (...args) => {
239
- logs.push(formatConsoleLine(args));
240
- });
241
- jail.setSync("__mcp_console_error", (...args) => {
242
- logs.push(formatConsoleLine(args));
243
- });
244
- }
245
- function setProviderBindings(ivm, context, providers, signal, deadline, hostErrorPrefix) {
246
- const jail = context.global;
247
- for (const provider of providers) for (const [safeToolName, descriptor] of Object.entries(provider.tools)) {
248
- const hostReferenceName = `__mcp_tool_${provider.name}_${safeToolName}`;
249
- jail.setSync(hostReferenceName, async (input) => {
250
- const executionContext = createExecutionContext(signal, provider.name, safeToolName, descriptor.originalName);
251
- try {
252
- const normalizedInput = input === void 0 ? void 0 : toJsonValue(input, "Guest code passed a non-serializable tool input");
253
- const pendingExecution = Promise.resolve(descriptor.execute(normalizedInput, executionContext));
254
- pendingExecution.catch(() => {});
255
- return toTransferableValue(ivm, await runWithDeadline(pendingExecution, deadline, signal));
256
- } catch (error) {
257
- const executeError = toExecuteError(error, deadline);
258
- throw new Error(`${hostErrorPrefix}${JSON.stringify(executeError)}`, { cause: error });
259
- }
260
- }, { reference: true });
261
- }
262
- }
263
5
  /**
264
6
  * isolated-vm-backed executor for one-shot sandboxed JavaScript runs.
265
7
  */
266
8
  var IsolatedVmExecutor = class {
267
- loadModule;
268
- maxLogChars;
269
- maxLogLines;
270
- memoryLimitBytes;
271
- timeoutMs;
9
+ options;
272
10
  /**
273
11
  * Creates an isolated-vm executor with one-shot runtime limits and host bridging configuration.
274
12
  */
275
13
  constructor(options = {}) {
276
- this.loadModule = async () => {
277
- return options.loadModule ? await options.loadModule() : await loadDefaultModule();
278
- };
279
- this.maxLogChars = options.maxLogChars ?? DEFAULT_MAX_LOG_CHARS;
280
- this.maxLogLines = options.maxLogLines ?? DEFAULT_MAX_LOG_LINES;
281
- this.memoryLimitBytes = options.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES;
282
- this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
14
+ this.options = options;
283
15
  }
284
16
  /**
285
17
  * Executes JavaScript against the provided tool namespaces in a fresh isolated-vm context.
286
18
  */
287
- async execute(code, providers) {
288
- const startedAt = Date.now();
289
- const deadline = startedAt + this.timeoutMs;
290
- const logs = [];
19
+ async execute(code, providers, options = {}) {
20
+ if (options.signal?.aborted) return (0, __mcploom_codexec.createTimeoutExecuteResult)();
291
21
  const abortController = new AbortController();
292
- const hostErrorPrefix = `__MCP_CODE_EXEC_HOST_ERROR__${(0, node_crypto.randomUUID)()}:`;
293
- if (Number.parseInt(process.versions.node.split(".")[0] ?? "0", 10) >= 20 && !hasRequiredNodeFlag()) return {
294
- durationMs: Date.now() - startedAt,
295
- error: {
296
- code: "internal_error",
297
- message: "isolated-vm requires Node to run with --no-node-snapshot on Node 20+"
298
- },
299
- logs,
300
- ok: false
22
+ const onToolCall = (0, __mcploom_codexec.createToolCallDispatcher)(providers, abortController.signal);
23
+ const onAbort = () => {
24
+ abortController.abort();
301
25
  };
302
- let catastrophicErrorMessage;
303
- let isolate;
304
- let context;
26
+ options.signal?.addEventListener("abort", onAbort, { once: true });
305
27
  try {
306
- const ivm = await this.loadModule();
307
- isolate = new ivm.Isolate({
308
- memoryLimit: toMemoryLimitMb(this.memoryLimitBytes),
309
- onCatastrophicError: (message) => {
310
- catastrophicErrorMessage = message;
311
- abortController.abort();
312
- }
313
- });
314
- context = await isolate.createContext();
315
- setConsoleBindings(context, logs);
316
- setProviderBindings(ivm, context, providers, abortController.signal, deadline, hostErrorPrefix);
317
- await context.eval(createBootstrapSource(providers, hostErrorPrefix, this.timeoutMs), { timeout: this.timeoutMs });
318
- const execution = await context.evalClosure(createExecutionSource(code), [], {
319
- timeout: this.timeoutMs,
320
- result: {
321
- copy: true,
322
- promise: true
323
- }
28
+ return await require_runner.runIsolatedVmSession({
29
+ abortController,
30
+ code,
31
+ onToolCall,
32
+ providers: (0, __mcploom_codexec.extractProviderManifests)(providers)
33
+ }, {
34
+ ...this.options,
35
+ ...options
324
36
  });
325
- if (catastrophicErrorMessage) return {
326
- durationMs: Date.now() - startedAt,
327
- error: {
328
- code: "internal_error",
329
- message: `isolated-vm catastrophic error: ${catastrophicErrorMessage}`
330
- },
331
- logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
332
- ok: false
333
- };
334
- if (!execution.ok) return {
335
- durationMs: Date.now() - startedAt,
336
- error: toExecuteError(execution.error, deadline),
337
- logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
338
- ok: false
339
- };
340
- return {
341
- durationMs: Date.now() - startedAt,
342
- logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
343
- ok: true,
344
- result: execution.value
345
- };
346
- } catch (error) {
347
- const executeError = catastrophicErrorMessage !== void 0 ? {
348
- code: "internal_error",
349
- message: `isolated-vm catastrophic error: ${catastrophicErrorMessage}`
350
- } : toExecuteError(error, deadline);
351
- return {
352
- durationMs: Date.now() - startedAt,
353
- error: executeError,
354
- logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
355
- ok: false
356
- };
357
37
  } finally {
38
+ options.signal?.removeEventListener("abort", onAbort);
358
39
  abortController.abort();
359
- context?.release?.();
360
- isolate?.dispose();
361
40
  }
362
41
  }
363
42
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["cachedModulePromise: Promise<IsolatedVmModule> | undefined","truncated: string[]","ExecuteFailure","timeoutId: ReturnType<typeof setTimeout> | undefined","logs: string[]","catastrophicErrorMessage: string | undefined","isolate: IsolatedVmIsolate | undefined","context: IsolatedVmContext | undefined"],"sources":["../src/isolatedVmExecutor.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport {\n ExecuteFailure,\n isExecuteFailure,\n normalizeCode,\n} from \"@mcploom/codexec\";\nimport type {\n ExecuteError,\n ExecuteResult,\n Executor,\n ResolvedToolProvider,\n ToolExecutionContext,\n} from \"@mcploom/codexec\";\n\nimport type { IsolatedVmExecutorOptions } from \"./types\";\n\ntype IsolatedVmExternalCopyInstance = {\n copyInto: (options?: { release?: boolean; transferIn?: boolean }) => unknown;\n release?: () => void;\n};\n\ntype IsolatedVmReferenceInstance = {\n setSync: (\n property: string,\n value: unknown,\n options?: Record<string, unknown>,\n ) => void;\n};\n\ntype IsolatedVmContext = {\n eval: (code: string, options?: Record<string, unknown>) => Promise<unknown>;\n evalClosure: (\n code: string,\n args?: unknown[],\n options?: Record<string, unknown>,\n ) => Promise<unknown>;\n global: IsolatedVmReferenceInstance;\n release?: () => void;\n};\n\ntype IsolatedVmIsolate = {\n createContext: () => Promise<IsolatedVmContext>;\n dispose: () => void;\n};\n\ntype IsolatedVmModule = {\n ExternalCopy: new (\n value: unknown,\n options?: Record<string, unknown>,\n ) => IsolatedVmExternalCopyInstance;\n Isolate: new (options?: {\n inspector?: boolean;\n memoryLimit?: number;\n onCatastrophicError?: (message: string) => void;\n }) => IsolatedVmIsolate;\n};\n\ntype GuestExecutionEnvelope =\n | {\n ok: true;\n value: unknown;\n }\n | {\n error: {\n code?: string;\n message?: string;\n };\n ok: false;\n };\n\nconst DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;\nconst DEFAULT_TIMEOUT_MS = 5000;\nconst DEFAULT_MAX_LOG_LINES = 100;\nconst DEFAULT_MAX_LOG_CHARS = 64_000;\nlet cachedModulePromise: Promise<IsolatedVmModule> | undefined;\n\nfunction createExecutionContext(\n signal: AbortSignal,\n providerName: string,\n safeToolName: string,\n originalToolName: string,\n): ToolExecutionContext {\n return {\n originalToolName,\n providerName,\n safeToolName,\n signal,\n };\n}\n\nfunction hasRequiredNodeFlag(): boolean {\n const execArgv = process.execArgv.join(\" \");\n const nodeOptions = process.env.NODE_OPTIONS ?? \"\";\n return (\n execArgv.includes(\"--no-node-snapshot\") ||\n nodeOptions.includes(\"--no-node-snapshot\")\n );\n}\n\nfunction isKnownErrorCode(value: unknown): value is ExecuteError[\"code\"] {\n return (\n value === \"timeout\" ||\n value === \"memory_limit\" ||\n value === \"validation_error\" ||\n value === \"tool_error\" ||\n value === \"runtime_error\" ||\n value === \"serialization_error\" ||\n value === \"internal_error\"\n );\n}\n\nfunction normalizeThrownMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n if (typeof error === \"object\" && error !== null && \"message\" in error) {\n const message = (error as { message?: unknown }).message;\n if (typeof message === \"string\") {\n return message;\n }\n }\n\n return String(error);\n}\n\nfunction truncateLogs(\n logs: string[],\n maxLogLines: number,\n maxLogChars: number,\n): string[] {\n const limitedLines = logs.slice(0, maxLogLines);\n let remainingChars = maxLogChars;\n const truncated: string[] = [];\n\n for (const line of limitedLines) {\n if (remainingChars <= 0) {\n break;\n }\n\n if (line.length <= remainingChars) {\n truncated.push(line);\n remainingChars -= line.length;\n continue;\n }\n\n truncated.push(line.slice(0, remainingChars));\n break;\n }\n\n return truncated;\n}\n\nfunction formatLogValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (value === undefined) {\n return \"undefined\";\n }\n\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction formatConsoleLine(values: unknown[]): string {\n return values.map((value) => formatLogValue(value)).join(\" \");\n}\n\nfunction toJsonValue(value: unknown, message: string): unknown {\n if (value === undefined) {\n return undefined;\n }\n\n const jsonValue = JSON.stringify(value);\n\n if (jsonValue === undefined) {\n throw new ExecuteFailure(\"serialization_error\", message);\n }\n\n try {\n return JSON.parse(jsonValue) as unknown;\n } catch {\n throw new ExecuteFailure(\"serialization_error\", message);\n }\n}\n\nfunction toTransferableValue(ivm: IsolatedVmModule, value: unknown): unknown {\n const normalizedValue = toJsonValue(\n value,\n \"Host value is not JSON-serializable\",\n );\n\n if (\n normalizedValue === null ||\n normalizedValue === undefined ||\n typeof normalizedValue === \"string\" ||\n typeof normalizedValue === \"number\" ||\n typeof normalizedValue === \"boolean\"\n ) {\n return normalizedValue;\n }\n\n const copy = new ivm.ExternalCopy(normalizedValue);\n return copy.copyInto({ release: true });\n}\n\nfunction toExecuteError(error: unknown, deadline: number): ExecuteError {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n \"message\" in error &&\n isKnownErrorCode((error as { code?: unknown }).code) &&\n typeof (error as { message?: unknown }).message === \"string\"\n ) {\n return {\n code: (error as { code: ExecuteError[\"code\"] }).code,\n message: (error as { message: string }).message,\n };\n }\n\n if (isExecuteFailure(error)) {\n return {\n code: error.code,\n message: error.message,\n };\n }\n\n const message = normalizeThrownMessage(error);\n const normalizedMessage = message.toLowerCase();\n\n if (\n Date.now() > deadline ||\n normalizedMessage.includes(\"timed out\") ||\n normalizedMessage.includes(\"time limit\")\n ) {\n return {\n code: \"timeout\",\n message: \"Execution timed out\",\n };\n }\n\n if (\n normalizedMessage.includes(\"memory limit\") ||\n normalizedMessage.includes(\"out of memory\")\n ) {\n return {\n code: \"memory_limit\",\n message,\n };\n }\n\n if (\n normalizedMessage.includes(\"could not be cloned\") ||\n normalizedMessage.includes(\"non-transferable\") ||\n normalizedMessage.includes(\"not json-serializable\")\n ) {\n return {\n code: \"serialization_error\",\n message,\n };\n }\n\n return {\n code: \"runtime_error\",\n message,\n };\n}\n\nfunction toMemoryLimitMb(memoryLimitBytes: number): number {\n return Math.max(8, Math.ceil(memoryLimitBytes / (1024 * 1024)));\n}\n\nfunction remainingTime(deadline: number): number {\n return Math.max(0, deadline - Date.now());\n}\n\nasync function runWithDeadline<T>(\n operation: Promise<T>,\n deadline: number,\n signal: AbortSignal,\n): Promise<T> {\n if (signal.aborted || Date.now() > deadline) {\n throw new ExecuteFailure(\"timeout\", \"Execution timed out\");\n }\n\n const timeoutMs = remainingTime(deadline);\n if (timeoutMs <= 0) {\n throw new ExecuteFailure(\"timeout\", \"Execution timed out\");\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n return await new Promise<T>((resolve, reject) => {\n const onAbort = () => {\n reject(new ExecuteFailure(\"timeout\", \"Execution timed out\"));\n };\n\n signal.addEventListener(\"abort\", onAbort, { once: true });\n timeoutId = setTimeout(() => {\n signal.removeEventListener(\"abort\", onAbort);\n reject(new ExecuteFailure(\"timeout\", \"Execution timed out\"));\n }, timeoutMs);\n\n void operation.then(\n (value) => {\n signal.removeEventListener(\"abort\", onAbort);\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n resolve(value);\n },\n (error) => {\n signal.removeEventListener(\"abort\", onAbort);\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n reject(error);\n },\n );\n });\n}\n\nasync function loadDefaultModule(): Promise<IsolatedVmModule> {\n cachedModulePromise ??= import(\"isolated-vm\").then((loaded) => {\n const candidate = (\n \"default\" in loaded ? loaded.default : loaded\n ) as unknown;\n return candidate as IsolatedVmModule;\n });\n\n return cachedModulePromise;\n}\n\nfunction createBootstrapSource(\n providers: ResolvedToolProvider[],\n hostErrorPrefix: string,\n timeoutMs: number,\n): string {\n const lines = [\n `const __MCP_HOST_ERROR_PREFIX = ${JSON.stringify(hostErrorPrefix)};`,\n `const __MCP_HOST_ERROR_KEY = ${JSON.stringify(`${hostErrorPrefix}key`)};`,\n \"const __mcpCreateTrustedError = (code, message) => ({\",\n \" [__MCP_HOST_ERROR_KEY]: true,\",\n \" code,\",\n \" message,\",\n \"});\",\n \"const __mcpNormalizeTrustedError = (error) => {\",\n \" if (error && typeof error === 'object' && error[__MCP_HOST_ERROR_KEY] === true && typeof error.code === 'string' && typeof error.message === 'string') {\",\n \" return __mcpCreateTrustedError(error.code, error.message);\",\n \" }\",\n \" if (error && typeof error.message === 'string' && error.message.startsWith(__MCP_HOST_ERROR_PREFIX)) {\",\n \" try {\",\n \" const payload = JSON.parse(error.message.slice(__MCP_HOST_ERROR_PREFIX.length));\",\n \" if (payload && typeof payload.code === 'string' && typeof payload.message === 'string') {\",\n \" return __mcpCreateTrustedError(payload.code, payload.message);\",\n \" }\",\n \" } catch {}\",\n \" }\",\n \" return null;\",\n \"};\",\n \"const __mcpNormalizeGuestError = (error) => {\",\n \" const trusted = __mcpNormalizeTrustedError(error);\",\n \" if (trusted) {\",\n \" return trusted;\",\n \" }\",\n \" if (error && typeof error.message === 'string') {\",\n \" return { code: 'runtime_error', message: error.message };\",\n \" }\",\n \" return { code: 'runtime_error', message: String(error) };\",\n \"};\",\n \"const __mcpNormalizeHostError = (error) => {\",\n \" const trusted = __mcpNormalizeTrustedError(error);\",\n \" if (trusted) {\",\n \" return trusted;\",\n \" }\",\n \" if (error && typeof error === 'object' && typeof error.code === 'string' && typeof error.message === 'string') {\",\n \" return __mcpCreateTrustedError(error.code, error.message);\",\n \" }\",\n \" return __mcpNormalizeGuestError(error);\",\n \"};\",\n \"const __mcpRaiseNormalizedError = (error) => {\",\n \" throw __mcpNormalizeHostError(error);\",\n \"};\",\n \"const __mcpToJsonValue = (value) => {\",\n \" if (typeof value === 'undefined') {\",\n \" return undefined;\",\n \" }\",\n \" const json = JSON.stringify(value);\",\n \" if (typeof json === 'undefined') {\",\n \" throw __mcpCreateTrustedError(\",\n \" 'serialization_error',\",\n \" 'Guest code returned a non-serializable value'\",\n \" );\",\n \" }\",\n \" return JSON.parse(json);\",\n \"};\",\n \"globalThis.console = {\",\n \" log: (...args) => __mcp_console_log(...args),\",\n \" info: (...args) => __mcp_console_info(...args),\",\n \" warn: (...args) => __mcp_console_warn(...args),\",\n \" error: (...args) => __mcp_console_error(...args),\",\n \"};\",\n ];\n\n for (const provider of providers) {\n lines.push(`globalThis.${provider.name} = {};`);\n\n for (const safeToolName of Object.keys(provider.tools)) {\n const hostReferenceName = `__mcp_tool_${provider.name}_${safeToolName}`;\n lines.push(\n `globalThis.${provider.name}.${safeToolName} = async (input) => {`,\n \" try {\",\n ` return await ${hostReferenceName}.applySyncPromise(undefined, [input], { arguments: { copy: true }, timeout: ${timeoutMs} });`,\n \" } catch (error) {\",\n \" __mcpRaiseNormalizedError(error);\",\n \" }\",\n \"};\",\n );\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction createExecutionSource(code: string): string {\n const executableSource = normalizeCode(code);\n\n return [\n `const __mcpUserFunction = (${executableSource});`,\n \"return (async () => {\",\n \" try {\",\n \" const value = await __mcpUserFunction();\",\n \" return { ok: true, value: __mcpToJsonValue(value) };\",\n \" } catch (error) {\",\n \" return { ok: false, error: __mcpNormalizeGuestError(error) };\",\n \" }\",\n \"})();\",\n ].join(\"\\n\");\n}\n\nfunction setConsoleBindings(context: IsolatedVmContext, logs: string[]): void {\n const jail = context.global;\n jail.setSync(\"__mcp_console_log\", (...args: unknown[]) => {\n logs.push(formatConsoleLine(args));\n });\n jail.setSync(\"__mcp_console_info\", (...args: unknown[]) => {\n logs.push(formatConsoleLine(args));\n });\n jail.setSync(\"__mcp_console_warn\", (...args: unknown[]) => {\n logs.push(formatConsoleLine(args));\n });\n jail.setSync(\"__mcp_console_error\", (...args: unknown[]) => {\n logs.push(formatConsoleLine(args));\n });\n}\n\nfunction setProviderBindings(\n ivm: IsolatedVmModule,\n context: IsolatedVmContext,\n providers: ResolvedToolProvider[],\n signal: AbortSignal,\n deadline: number,\n hostErrorPrefix: string,\n): void {\n const jail = context.global;\n\n for (const provider of providers) {\n for (const [safeToolName, descriptor] of Object.entries(provider.tools)) {\n const hostReferenceName = `__mcp_tool_${provider.name}_${safeToolName}`;\n\n jail.setSync(\n hostReferenceName,\n async (input: unknown) => {\n const executionContext = createExecutionContext(\n signal,\n provider.name,\n safeToolName,\n descriptor.originalName,\n );\n\n try {\n const normalizedInput =\n input === undefined\n ? undefined\n : toJsonValue(\n input,\n \"Guest code passed a non-serializable tool input\",\n );\n const pendingExecution = Promise.resolve(\n descriptor.execute(normalizedInput, executionContext),\n );\n\n pendingExecution.catch(() => {\n // The deadline path may settle first; keep late provider rejections from\n // surfacing as unhandled promise rejections after timeout/abort.\n });\n const result = await runWithDeadline(\n pendingExecution,\n deadline,\n signal,\n );\n\n return toTransferableValue(ivm, result);\n } catch (error) {\n const executeError = toExecuteError(error, deadline);\n throw new Error(\n `${hostErrorPrefix}${JSON.stringify(executeError)}`,\n {\n cause: error,\n },\n );\n }\n },\n { reference: true },\n );\n }\n }\n}\n\n/**\n * isolated-vm-backed executor for one-shot sandboxed JavaScript runs.\n */\nexport class IsolatedVmExecutor implements Executor {\n private readonly loadModule: () => Promise<IsolatedVmModule>;\n private readonly maxLogChars: number;\n private readonly maxLogLines: number;\n private readonly memoryLimitBytes: number;\n private readonly timeoutMs: number;\n\n /**\n * Creates an isolated-vm executor with one-shot runtime limits and host bridging configuration.\n */\n constructor(options: IsolatedVmExecutorOptions = {}) {\n this.loadModule = async () => {\n const loaded = options.loadModule\n ? await options.loadModule()\n : await loadDefaultModule();\n return loaded as IsolatedVmModule;\n };\n this.maxLogChars = options.maxLogChars ?? DEFAULT_MAX_LOG_CHARS;\n this.maxLogLines = options.maxLogLines ?? DEFAULT_MAX_LOG_LINES;\n this.memoryLimitBytes =\n options.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n }\n\n /**\n * Executes JavaScript against the provided tool namespaces in a fresh isolated-vm context.\n */\n async execute(\n code: string,\n providers: ResolvedToolProvider[],\n ): Promise<ExecuteResult> {\n const startedAt = Date.now();\n const deadline = startedAt + this.timeoutMs;\n const logs: string[] = [];\n const abortController = new AbortController();\n const hostErrorPrefix = `__MCP_CODE_EXEC_HOST_ERROR__${randomUUID()}:`;\n const nodeMajorVersion = Number.parseInt(\n process.versions.node.split(\".\")[0] ?? \"0\",\n 10,\n );\n\n if (nodeMajorVersion >= 20 && !hasRequiredNodeFlag()) {\n return {\n durationMs: Date.now() - startedAt,\n error: {\n code: \"internal_error\",\n message:\n \"isolated-vm requires Node to run with --no-node-snapshot on Node 20+\",\n },\n logs,\n ok: false,\n };\n }\n\n let catastrophicErrorMessage: string | undefined;\n let isolate: IsolatedVmIsolate | undefined;\n let context: IsolatedVmContext | undefined;\n\n try {\n const ivm = await this.loadModule();\n isolate = new ivm.Isolate({\n memoryLimit: toMemoryLimitMb(this.memoryLimitBytes),\n onCatastrophicError: (message) => {\n catastrophicErrorMessage = message;\n abortController.abort();\n },\n });\n context = await isolate.createContext();\n\n setConsoleBindings(context, logs);\n setProviderBindings(\n ivm,\n context,\n providers,\n abortController.signal,\n deadline,\n hostErrorPrefix,\n );\n await context.eval(\n createBootstrapSource(providers, hostErrorPrefix, this.timeoutMs),\n {\n timeout: this.timeoutMs,\n },\n );\n\n const execution = (await context.evalClosure(\n createExecutionSource(code),\n [],\n {\n timeout: this.timeoutMs,\n result: { copy: true, promise: true },\n },\n )) as GuestExecutionEnvelope;\n\n if (catastrophicErrorMessage) {\n return {\n durationMs: Date.now() - startedAt,\n error: {\n code: \"internal_error\",\n message: `isolated-vm catastrophic error: ${catastrophicErrorMessage}`,\n },\n logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),\n ok: false,\n };\n }\n\n if (!execution.ok) {\n return {\n durationMs: Date.now() - startedAt,\n error: toExecuteError(execution.error, deadline),\n logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),\n ok: false,\n };\n }\n\n return {\n durationMs: Date.now() - startedAt,\n logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),\n ok: true,\n result: execution.value,\n };\n } catch (error) {\n const executeError =\n catastrophicErrorMessage !== undefined\n ? {\n code: \"internal_error\" as const,\n message: `isolated-vm catastrophic error: ${catastrophicErrorMessage}`,\n }\n : toExecuteError(error, deadline);\n\n return {\n durationMs: Date.now() - startedAt,\n error: executeError,\n logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),\n ok: false,\n };\n } finally {\n abortController.abort();\n context?.release?.();\n isolate?.dispose();\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["runIsolatedVmSession"],"sources":["../src/isolatedVmExecutor.ts"],"sourcesContent":["import {\n createTimeoutExecuteResult,\n createToolCallDispatcher,\n extractProviderManifests,\n type ExecutionOptions,\n type ExecuteResult,\n type Executor,\n type ResolvedToolProvider,\n} from \"@mcploom/codexec\";\n\nimport { runIsolatedVmSession } from \"./runner/index\";\nimport type { IsolatedVmExecutorOptions } from \"./types\";\n\n/**\n * isolated-vm-backed executor for one-shot sandboxed JavaScript runs.\n */\nexport class IsolatedVmExecutor implements Executor {\n private readonly options: IsolatedVmExecutorOptions;\n\n /**\n * Creates an isolated-vm executor with one-shot runtime limits and host bridging configuration.\n */\n constructor(options: IsolatedVmExecutorOptions = {}) {\n this.options = options;\n }\n\n /**\n * Executes JavaScript against the provided tool namespaces in a fresh isolated-vm context.\n */\n async execute(\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n ): Promise<ExecuteResult> {\n if (options.signal?.aborted) {\n return createTimeoutExecuteResult();\n }\n\n const abortController = new AbortController();\n const onToolCall = createToolCallDispatcher(providers, abortController.signal);\n const onAbort = () => {\n abortController.abort();\n };\n\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n try {\n return await runIsolatedVmSession(\n {\n abortController,\n code,\n onToolCall,\n providers: extractProviderManifests(providers),\n },\n {\n ...this.options,\n ...options,\n },\n );\n } finally {\n options.signal?.removeEventListener(\"abort\", onAbort);\n abortController.abort();\n }\n }\n}\n"],"mappings":";;;;;;;AAgBA,IAAa,qBAAb,MAAoD;CAClD,AAAiB;;;;CAKjB,YAAY,UAAqC,EAAE,EAAE;AACnD,OAAK,UAAU;;;;;CAMjB,MAAM,QACJ,MACA,WACA,UAA4B,EAAE,EACN;AACxB,MAAI,QAAQ,QAAQ,QAClB,2DAAmC;EAGrC,MAAM,kBAAkB,IAAI,iBAAiB;EAC7C,MAAM,6DAAsC,WAAW,gBAAgB,OAAO;EAC9E,MAAM,gBAAgB;AACpB,mBAAgB,OAAO;;AAGzB,UAAQ,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,MAAM,CAAC;AAElE,MAAI;AACF,UAAO,MAAMA,oCACX;IACE;IACA;IACA;IACA,2DAAoC,UAAU;IAC/C,EACD;IACE,GAAG,KAAK;IACR,GAAG;IACJ,CACF;YACO;AACR,WAAQ,QAAQ,oBAAoB,SAAS,QAAQ;AACrD,mBAAgB,OAAO"}
package/dist/index.d.cts CHANGED
@@ -1,32 +1,13 @@
1
- import { ExecuteResult, Executor, ResolvedToolProvider } from "@mcploom/codexec";
1
+ import { t as IsolatedVmExecutorOptions } from "./types-BmvPk-t5.cjs";
2
+ import { ExecuteResult, ExecutionOptions, Executor, ResolvedToolProvider } from "@mcploom/codexec";
2
3
 
3
- //#region src/types.d.ts
4
- /**
5
- * Options for constructing an {@link IsolatedVmExecutor}.
6
- */
7
- interface IsolatedVmExecutorOptions {
8
- /** Optional isolated-vm module loader override for tests or custom builds. */
9
- loadModule?: () => Promise<unknown> | unknown;
10
- /** Maximum total characters preserved across captured log lines. */
11
- maxLogChars?: number;
12
- /** Maximum number of captured log lines returned in the result. */
13
- maxLogLines?: number;
14
- /** Guest memory limit in bytes. */
15
- memoryLimitBytes?: number;
16
- /** Wall-clock execution timeout in milliseconds. */
17
- timeoutMs?: number;
18
- }
19
- //#endregion
20
4
  //#region src/isolatedVmExecutor.d.ts
5
+
21
6
  /**
22
7
  * isolated-vm-backed executor for one-shot sandboxed JavaScript runs.
23
8
  */
24
9
  declare class IsolatedVmExecutor implements Executor {
25
- private readonly loadModule;
26
- private readonly maxLogChars;
27
- private readonly maxLogLines;
28
- private readonly memoryLimitBytes;
29
- private readonly timeoutMs;
10
+ private readonly options;
30
11
  /**
31
12
  * Creates an isolated-vm executor with one-shot runtime limits and host bridging configuration.
32
13
  */
@@ -34,7 +15,7 @@ declare class IsolatedVmExecutor implements Executor {
34
15
  /**
35
16
  * Executes JavaScript against the provided tool namespaces in a fresh isolated-vm context.
36
17
  */
37
- execute(code: string, providers: ResolvedToolProvider[]): Promise<ExecuteResult>;
18
+ execute(code: string, providers: ResolvedToolProvider[], options?: ExecutionOptions): Promise<ExecuteResult>;
38
19
  }
39
20
  //#endregion
40
21
  export { IsolatedVmExecutor, type IsolatedVmExecutorOptions };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/isolatedVmExecutor.ts"],"sourcesContent":[],"mappings":";;;;;;AAGiB,UAAA,yBAAA,CAEI;;qBAAA;;EC4gBR,WAAA,CAAA,EAAA,MAAA;EAUU;EAmBR,WAAA,CAAA,EAAA,MAAA;EACF;EAAR,gBAAA,CAAA,EAAA,MAAA;EA9BsC;EAAQ,SAAA,CAAA,EAAA,MAAA;;;;;AD9gBnD;;cC8gBa,kBAAA,YAA8B;;EAA9B,iBAAA,WAAmB;EAUT,iBAAA,WAAA;EAmBR,iBAAA,gBAAA;EACF,iBAAA,SAAA;EAAR;;;wBApBkB;;;;mCAmBR,yBACV,QAAQ"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/isolatedVmExecutor.ts"],"sourcesContent":[],"mappings":";;;;;;;AAgBA;AAMuB,cANV,kBAAA,YAA8B,QAMpB,CAAA;EASR,iBAAA,OAAA;EACF;;;EAhB8B,WAAA,CAAA,OAAA,CAAA,EAMpB,yBANoB;EAAQ;;;mCAepC,kCACF,mBACR,QAAQ"}
package/dist/index.d.ts CHANGED
@@ -1,32 +1,13 @@
1
- import { ExecuteResult, Executor, ResolvedToolProvider } from "@mcploom/codexec";
1
+ import { t as IsolatedVmExecutorOptions } from "./types-CkMlkJam.js";
2
+ import { ExecuteResult, ExecutionOptions, Executor, ResolvedToolProvider } from "@mcploom/codexec";
2
3
 
3
- //#region src/types.d.ts
4
- /**
5
- * Options for constructing an {@link IsolatedVmExecutor}.
6
- */
7
- interface IsolatedVmExecutorOptions {
8
- /** Optional isolated-vm module loader override for tests or custom builds. */
9
- loadModule?: () => Promise<unknown> | unknown;
10
- /** Maximum total characters preserved across captured log lines. */
11
- maxLogChars?: number;
12
- /** Maximum number of captured log lines returned in the result. */
13
- maxLogLines?: number;
14
- /** Guest memory limit in bytes. */
15
- memoryLimitBytes?: number;
16
- /** Wall-clock execution timeout in milliseconds. */
17
- timeoutMs?: number;
18
- }
19
- //#endregion
20
4
  //#region src/isolatedVmExecutor.d.ts
5
+
21
6
  /**
22
7
  * isolated-vm-backed executor for one-shot sandboxed JavaScript runs.
23
8
  */
24
9
  declare class IsolatedVmExecutor implements Executor {
25
- private readonly loadModule;
26
- private readonly maxLogChars;
27
- private readonly maxLogLines;
28
- private readonly memoryLimitBytes;
29
- private readonly timeoutMs;
10
+ private readonly options;
30
11
  /**
31
12
  * Creates an isolated-vm executor with one-shot runtime limits and host bridging configuration.
32
13
  */
@@ -34,7 +15,7 @@ declare class IsolatedVmExecutor implements Executor {
34
15
  /**
35
16
  * Executes JavaScript against the provided tool namespaces in a fresh isolated-vm context.
36
17
  */
37
- execute(code: string, providers: ResolvedToolProvider[]): Promise<ExecuteResult>;
18
+ execute(code: string, providers: ResolvedToolProvider[], options?: ExecutionOptions): Promise<ExecuteResult>;
38
19
  }
39
20
  //#endregion
40
21
  export { IsolatedVmExecutor, type IsolatedVmExecutorOptions };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/isolatedVmExecutor.ts"],"sourcesContent":[],"mappings":";;;;;;AAGiB,UAAA,yBAAA,CAEI;;qBAAA;;EC4gBR,WAAA,CAAA,EAAA,MAAA;EAUU;EAmBR,WAAA,CAAA,EAAA,MAAA;EACF;EAAR,gBAAA,CAAA,EAAA,MAAA;EA9BsC;EAAQ,SAAA,CAAA,EAAA,MAAA;;;;;AD9gBnD;;cC8gBa,kBAAA,YAA8B;;EAA9B,iBAAA,WAAmB;EAUT,iBAAA,WAAA;EAmBR,iBAAA,gBAAA;EACF,iBAAA,SAAA;EAAR;;;wBApBkB;;;;mCAmBR,yBACV,QAAQ"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/isolatedVmExecutor.ts"],"sourcesContent":[],"mappings":";;;;;;;AAgBA;AAMuB,cANV,kBAAA,YAA8B,QAMpB,CAAA;EASR,iBAAA,OAAA;EACF;;;EAhB8B,WAAA,CAAA,OAAA,CAAA,EAMpB,yBANoB;EAAQ;;;mCAepC,kCACF,mBACR,QAAQ"}