@mcploom/codexec-isolated-vm 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mouaad Aallam
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # @mcploom/codexec-isolated-vm
2
+
3
+ `isolated-vm` executor package for `@mcploom/codexec`.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @mcploom/codexec @mcploom/codexec-isolated-vm
9
+ ```
10
+
11
+ It implements the shared `Executor` contract from `@mcploom/codexec`, so it can be used anywhere the QuickJS package can be used.
12
+
13
+ ## Requirements
14
+
15
+ - Node 20+ must run with `--no-node-snapshot`
16
+ - the optional `isolated-vm` native dependency must install successfully in the host environment
17
+ - native-addon failures are surfaced only when `IsolatedVmExecutor` is used
18
+
19
+ ## Usage
20
+
21
+ ```ts
22
+ import { resolveProvider } from "@mcploom/codexec";
23
+ import { IsolatedVmExecutor } from "@mcploom/codexec-isolated-vm";
24
+
25
+ const provider = resolveProvider({
26
+ tools: {
27
+ echo: {
28
+ execute: async (input) => input,
29
+ },
30
+ },
31
+ });
32
+
33
+ const executor = new IsolatedVmExecutor();
34
+ const result = await executor.execute("await codemode.echo({ ok: true })", [
35
+ provider,
36
+ ]);
37
+ ```
38
+
39
+ This package is verified through the opt-in workspace flow:
40
+
41
+ ```bash
42
+ npm run verify:isolated-vm
43
+ ```
44
+
45
+ `isolated-vm` is not documented here as a hard security boundary. If the workload is hostile or process stability matters more than in-process performance, prefer process isolation around the executor.
package/dist/index.cjs ADDED
@@ -0,0 +1,340 @@
1
+ let __mcploom_codexec = require("@mcploom/codexec");
2
+
3
+ //#region src/isolatedVmExecutor.ts
4
+ const DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;
5
+ const DEFAULT_TIMEOUT_MS = 5e3;
6
+ const DEFAULT_MAX_LOG_LINES = 100;
7
+ const DEFAULT_MAX_LOG_CHARS = 64e3;
8
+ const HOST_ERROR_PREFIX = "__MCP_CODE_EXEC_HOST_ERROR__";
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, timeoutMs) {
143
+ const lines = [
144
+ `const __MCP_HOST_ERROR_PREFIX = ${JSON.stringify(HOST_ERROR_PREFIX)};`,
145
+ "const __mcpNormalizeError = (error) => {",
146
+ " if (error && typeof error === 'object' && typeof error.code === 'string' && typeof error.message === 'string') {",
147
+ " return { code: error.code, message: error.message };",
148
+ " }",
149
+ " if (error && typeof error.message === 'string' && error.message.startsWith(__MCP_HOST_ERROR_PREFIX)) {",
150
+ " try {",
151
+ " const payload = JSON.parse(error.message.slice(__MCP_HOST_ERROR_PREFIX.length));",
152
+ " if (payload && typeof payload.code === 'string' && typeof payload.message === 'string') {",
153
+ " return payload;",
154
+ " }",
155
+ " } catch {}",
156
+ " }",
157
+ " if (error && typeof error.message === 'string') {",
158
+ " return { code: 'runtime_error', message: error.message };",
159
+ " }",
160
+ " return { code: 'runtime_error', message: String(error) };",
161
+ "};",
162
+ "const __mcpRaiseNormalizedError = (error) => {",
163
+ " const normalized = __mcpNormalizeError(error);",
164
+ " const wrapped = new Error(normalized.message);",
165
+ " wrapped.code = normalized.code;",
166
+ " throw wrapped;",
167
+ "};",
168
+ "const __mcpToJsonValue = (value) => {",
169
+ " if (typeof value === 'undefined') {",
170
+ " return undefined;",
171
+ " }",
172
+ " const json = JSON.stringify(value);",
173
+ " if (typeof json === 'undefined') {",
174
+ " const error = new Error('Guest code returned a non-serializable value');",
175
+ " error.code = 'serialization_error';",
176
+ " throw error;",
177
+ " }",
178
+ " return JSON.parse(json);",
179
+ "};",
180
+ "globalThis.console = {",
181
+ " log: (...args) => __mcp_console_log(...args),",
182
+ " info: (...args) => __mcp_console_info(...args),",
183
+ " warn: (...args) => __mcp_console_warn(...args),",
184
+ " error: (...args) => __mcp_console_error(...args),",
185
+ "};"
186
+ ];
187
+ for (const provider of providers) {
188
+ lines.push(`globalThis.${provider.name} = {};`);
189
+ for (const safeToolName of Object.keys(provider.tools)) {
190
+ const hostReferenceName = `__mcp_tool_${provider.name}_${safeToolName}`;
191
+ lines.push(`globalThis.${provider.name}.${safeToolName} = async (input) => {`, " try {", ` return await ${hostReferenceName}.applySyncPromise(undefined, [input], { arguments: { copy: true }, timeout: ${timeoutMs} });`, " } catch (error) {", " __mcpRaiseNormalizedError(error);", " }", "};");
192
+ }
193
+ }
194
+ return lines.join("\n");
195
+ }
196
+ function createExecutionSource(code) {
197
+ return [
198
+ `const __mcpUserFunction = (${(0, __mcploom_codexec.normalizeCode)(code)});`,
199
+ "return (async () => {",
200
+ " try {",
201
+ " const value = await __mcpUserFunction();",
202
+ " return { ok: true, value: __mcpToJsonValue(value) };",
203
+ " } catch (error) {",
204
+ " return { ok: false, error: __mcpNormalizeError(error) };",
205
+ " }",
206
+ "})();"
207
+ ].join("\n");
208
+ }
209
+ function setConsoleBindings(context, logs) {
210
+ const jail = context.global;
211
+ jail.setSync("__mcp_console_log", (...args) => {
212
+ logs.push(formatConsoleLine(args));
213
+ });
214
+ jail.setSync("__mcp_console_info", (...args) => {
215
+ logs.push(formatConsoleLine(args));
216
+ });
217
+ jail.setSync("__mcp_console_warn", (...args) => {
218
+ logs.push(formatConsoleLine(args));
219
+ });
220
+ jail.setSync("__mcp_console_error", (...args) => {
221
+ logs.push(formatConsoleLine(args));
222
+ });
223
+ }
224
+ function setProviderBindings(ivm, context, providers, signal, deadline) {
225
+ const jail = context.global;
226
+ for (const provider of providers) for (const [safeToolName, descriptor] of Object.entries(provider.tools)) {
227
+ const hostReferenceName = `__mcp_tool_${provider.name}_${safeToolName}`;
228
+ jail.setSync(hostReferenceName, async (input) => {
229
+ const executionContext = createExecutionContext(signal, provider.name, safeToolName, descriptor.originalName);
230
+ try {
231
+ const normalizedInput = input === void 0 ? void 0 : toJsonValue(input, "Guest code passed a non-serializable tool input");
232
+ return toTransferableValue(ivm, await runWithDeadline(Promise.resolve(descriptor.execute(normalizedInput, executionContext)), deadline, signal));
233
+ } catch (error) {
234
+ const executeError = toExecuteError(error, deadline);
235
+ throw new Error(`${HOST_ERROR_PREFIX}${JSON.stringify(executeError)}`, { cause: error });
236
+ }
237
+ }, { reference: true });
238
+ }
239
+ }
240
+ /**
241
+ * isolated-vm-backed executor for one-shot sandboxed JavaScript runs.
242
+ */
243
+ var IsolatedVmExecutor = class {
244
+ loadModule;
245
+ maxLogChars;
246
+ maxLogLines;
247
+ memoryLimitBytes;
248
+ timeoutMs;
249
+ constructor(options = {}) {
250
+ this.loadModule = async () => {
251
+ return options.loadModule ? await options.loadModule() : await loadDefaultModule();
252
+ };
253
+ this.maxLogChars = options.maxLogChars ?? DEFAULT_MAX_LOG_CHARS;
254
+ this.maxLogLines = options.maxLogLines ?? DEFAULT_MAX_LOG_LINES;
255
+ this.memoryLimitBytes = options.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES;
256
+ this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
257
+ }
258
+ /**
259
+ * Executes JavaScript against the provided tool namespaces in a fresh isolated-vm context.
260
+ */
261
+ async execute(code, providers) {
262
+ const startedAt = Date.now();
263
+ const deadline = startedAt + this.timeoutMs;
264
+ const logs = [];
265
+ const abortController = new AbortController();
266
+ if (Number.parseInt(process.versions.node.split(".")[0] ?? "0", 10) >= 20 && !hasRequiredNodeFlag()) return {
267
+ durationMs: Date.now() - startedAt,
268
+ error: {
269
+ code: "internal_error",
270
+ message: "isolated-vm requires Node to run with --no-node-snapshot on Node 20+"
271
+ },
272
+ logs,
273
+ ok: false
274
+ };
275
+ let catastrophicErrorMessage;
276
+ let isolate;
277
+ let context;
278
+ try {
279
+ const ivm = await this.loadModule();
280
+ isolate = new ivm.Isolate({
281
+ memoryLimit: toMemoryLimitMb(this.memoryLimitBytes),
282
+ onCatastrophicError: (message) => {
283
+ catastrophicErrorMessage = message;
284
+ abortController.abort();
285
+ }
286
+ });
287
+ context = await isolate.createContext();
288
+ setConsoleBindings(context, logs);
289
+ setProviderBindings(ivm, context, providers, abortController.signal, deadline);
290
+ await context.eval(createBootstrapSource(providers, this.timeoutMs), { timeout: this.timeoutMs });
291
+ const execution = await context.evalClosure(createExecutionSource(code), [], {
292
+ timeout: this.timeoutMs,
293
+ result: {
294
+ copy: true,
295
+ promise: true
296
+ }
297
+ });
298
+ if (catastrophicErrorMessage) return {
299
+ durationMs: Date.now() - startedAt,
300
+ error: {
301
+ code: "internal_error",
302
+ message: `isolated-vm catastrophic error: ${catastrophicErrorMessage}`
303
+ },
304
+ logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
305
+ ok: false
306
+ };
307
+ if (!execution.ok) return {
308
+ durationMs: Date.now() - startedAt,
309
+ error: toExecuteError(execution.error, deadline),
310
+ logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
311
+ ok: false
312
+ };
313
+ return {
314
+ durationMs: Date.now() - startedAt,
315
+ logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
316
+ ok: true,
317
+ result: execution.value
318
+ };
319
+ } catch (error) {
320
+ const executeError = catastrophicErrorMessage !== void 0 ? {
321
+ code: "internal_error",
322
+ message: `isolated-vm catastrophic error: ${catastrophicErrorMessage}`
323
+ } : toExecuteError(error, deadline);
324
+ return {
325
+ durationMs: Date.now() - startedAt,
326
+ error: executeError,
327
+ logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
328
+ ok: false
329
+ };
330
+ } finally {
331
+ abortController.abort();
332
+ context?.release?.();
333
+ isolate?.dispose();
334
+ }
335
+ }
336
+ };
337
+
338
+ //#endregion
339
+ exports.IsolatedVmExecutor = IsolatedVmExecutor;
340
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +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 {\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;\nconst HOST_ERROR_PREFIX = \"__MCP_CODE_EXEC_HOST_ERROR__\";\n\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 timeoutMs: number,\n): string {\n const lines = [\n `const __MCP_HOST_ERROR_PREFIX = ${JSON.stringify(HOST_ERROR_PREFIX)};`,\n \"const __mcpNormalizeError = (error) => {\",\n \" if (error && typeof error === 'object' && typeof error.code === 'string' && typeof error.message === 'string') {\",\n \" return { code: error.code, message: 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 payload;\",\n \" }\",\n \" } catch {}\",\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 __mcpRaiseNormalizedError = (error) => {\",\n \" const normalized = __mcpNormalizeError(error);\",\n \" const wrapped = new Error(normalized.message);\",\n \" wrapped.code = normalized.code;\",\n \" throw wrapped;\",\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 \" const error = new Error('Guest code returned a non-serializable value');\",\n \" error.code = 'serialization_error';\",\n \" throw error;\",\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: __mcpNormalizeError(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): 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 result = await runWithDeadline(\n Promise.resolve(\n descriptor.execute(normalizedInput, executionContext),\n ),\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 `${HOST_ERROR_PREFIX}${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 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 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 );\n await context.eval(createBootstrapSource(providers, this.timeoutMs), {\n timeout: this.timeoutMs,\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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"}
@@ -0,0 +1,38 @@
1
+ import { ExecuteResult, Executor, ResolvedToolProvider } from "@mcploom/codexec";
2
+
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
+ //#region src/isolatedVmExecutor.d.ts
21
+ /**
22
+ * isolated-vm-backed executor for one-shot sandboxed JavaScript runs.
23
+ */
24
+ 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;
30
+ constructor(options?: IsolatedVmExecutorOptions);
31
+ /**
32
+ * Executes JavaScript against the provided tool namespaces in a fresh isolated-vm context.
33
+ */
34
+ execute(code: string, providers: ResolvedToolProvider[]): Promise<ExecuteResult>;
35
+ }
36
+ //#endregion
37
+ export { IsolatedVmExecutor, type IsolatedVmExecutorOptions };
38
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/isolatedVmExecutor.ts"],"sourcesContent":[],"mappings":";;;;;;AAGiB,UAAA,yBAAA,CAEI;;qBAAA;;EC+eR,WAAA,CAAA,EAAA,MAAA;EAOU;EAmBR,WAAA,CAAA,EAAA,MAAA;EACF;EAAR,gBAAA,CAAA,EAAA,MAAA;EA3BsC;EAAQ,SAAA,CAAA,EAAA,MAAA;;;;;ADjfnD;;cCifa,kBAAA,YAA8B;;EAA9B,iBAAA,WAAmB;EAOT,iBAAA,WAAA;EAmBR,iBAAA,gBAAA;EACF,iBAAA,SAAA;EAAR,WAAA,CAAA,OAAA,CAAA,EApBkB,yBAoBlB;EA3BsC;;;mCA0B5B,yBACV,QAAQ"}
@@ -0,0 +1,38 @@
1
+ import { ExecuteResult, Executor, ResolvedToolProvider } from "@mcploom/codexec";
2
+
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
+ //#region src/isolatedVmExecutor.d.ts
21
+ /**
22
+ * isolated-vm-backed executor for one-shot sandboxed JavaScript runs.
23
+ */
24
+ 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;
30
+ constructor(options?: IsolatedVmExecutorOptions);
31
+ /**
32
+ * Executes JavaScript against the provided tool namespaces in a fresh isolated-vm context.
33
+ */
34
+ execute(code: string, providers: ResolvedToolProvider[]): Promise<ExecuteResult>;
35
+ }
36
+ //#endregion
37
+ export { IsolatedVmExecutor, type IsolatedVmExecutorOptions };
38
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/isolatedVmExecutor.ts"],"sourcesContent":[],"mappings":";;;;;;AAGiB,UAAA,yBAAA,CAEI;;qBAAA;;EC+eR,WAAA,CAAA,EAAA,MAAA;EAOU;EAmBR,WAAA,CAAA,EAAA,MAAA;EACF;EAAR,gBAAA,CAAA,EAAA,MAAA;EA3BsC;EAAQ,SAAA,CAAA,EAAA,MAAA;;;;;ADjfnD;;cCifa,kBAAA,YAA8B;;EAA9B,iBAAA,WAAmB;EAOT,iBAAA,WAAA;EAmBR,iBAAA,gBAAA;EACF,iBAAA,SAAA;EAAR,WAAA,CAAA,OAAA,CAAA,EApBkB,yBAoBlB;EA3BsC;;;mCA0B5B,yBACV,QAAQ"}
package/dist/index.js ADDED
@@ -0,0 +1,340 @@
1
+ import { ExecuteFailure, isExecuteFailure, normalizeCode } from "@mcploom/codexec";
2
+
3
+ //#region src/isolatedVmExecutor.ts
4
+ const DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;
5
+ const DEFAULT_TIMEOUT_MS = 5e3;
6
+ const DEFAULT_MAX_LOG_LINES = 100;
7
+ const DEFAULT_MAX_LOG_CHARS = 64e3;
8
+ const HOST_ERROR_PREFIX = "__MCP_CODE_EXEC_HOST_ERROR__";
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 ExecuteFailure("serialization_error", message);
66
+ try {
67
+ return JSON.parse(jsonValue);
68
+ } catch {
69
+ throw new 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 (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 ExecuteFailure("timeout", "Execution timed out");
113
+ const timeoutMs = remainingTime(deadline);
114
+ if (timeoutMs <= 0) throw new ExecuteFailure("timeout", "Execution timed out");
115
+ let timeoutId;
116
+ return await new Promise((resolve, reject) => {
117
+ const onAbort = () => {
118
+ reject(new ExecuteFailure("timeout", "Execution timed out"));
119
+ };
120
+ signal.addEventListener("abort", onAbort, { once: true });
121
+ timeoutId = setTimeout(() => {
122
+ signal.removeEventListener("abort", onAbort);
123
+ reject(new 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, timeoutMs) {
143
+ const lines = [
144
+ `const __MCP_HOST_ERROR_PREFIX = ${JSON.stringify(HOST_ERROR_PREFIX)};`,
145
+ "const __mcpNormalizeError = (error) => {",
146
+ " if (error && typeof error === 'object' && typeof error.code === 'string' && typeof error.message === 'string') {",
147
+ " return { code: error.code, message: error.message };",
148
+ " }",
149
+ " if (error && typeof error.message === 'string' && error.message.startsWith(__MCP_HOST_ERROR_PREFIX)) {",
150
+ " try {",
151
+ " const payload = JSON.parse(error.message.slice(__MCP_HOST_ERROR_PREFIX.length));",
152
+ " if (payload && typeof payload.code === 'string' && typeof payload.message === 'string') {",
153
+ " return payload;",
154
+ " }",
155
+ " } catch {}",
156
+ " }",
157
+ " if (error && typeof error.message === 'string') {",
158
+ " return { code: 'runtime_error', message: error.message };",
159
+ " }",
160
+ " return { code: 'runtime_error', message: String(error) };",
161
+ "};",
162
+ "const __mcpRaiseNormalizedError = (error) => {",
163
+ " const normalized = __mcpNormalizeError(error);",
164
+ " const wrapped = new Error(normalized.message);",
165
+ " wrapped.code = normalized.code;",
166
+ " throw wrapped;",
167
+ "};",
168
+ "const __mcpToJsonValue = (value) => {",
169
+ " if (typeof value === 'undefined') {",
170
+ " return undefined;",
171
+ " }",
172
+ " const json = JSON.stringify(value);",
173
+ " if (typeof json === 'undefined') {",
174
+ " const error = new Error('Guest code returned a non-serializable value');",
175
+ " error.code = 'serialization_error';",
176
+ " throw error;",
177
+ " }",
178
+ " return JSON.parse(json);",
179
+ "};",
180
+ "globalThis.console = {",
181
+ " log: (...args) => __mcp_console_log(...args),",
182
+ " info: (...args) => __mcp_console_info(...args),",
183
+ " warn: (...args) => __mcp_console_warn(...args),",
184
+ " error: (...args) => __mcp_console_error(...args),",
185
+ "};"
186
+ ];
187
+ for (const provider of providers) {
188
+ lines.push(`globalThis.${provider.name} = {};`);
189
+ for (const safeToolName of Object.keys(provider.tools)) {
190
+ const hostReferenceName = `__mcp_tool_${provider.name}_${safeToolName}`;
191
+ lines.push(`globalThis.${provider.name}.${safeToolName} = async (input) => {`, " try {", ` return await ${hostReferenceName}.applySyncPromise(undefined, [input], { arguments: { copy: true }, timeout: ${timeoutMs} });`, " } catch (error) {", " __mcpRaiseNormalizedError(error);", " }", "};");
192
+ }
193
+ }
194
+ return lines.join("\n");
195
+ }
196
+ function createExecutionSource(code) {
197
+ return [
198
+ `const __mcpUserFunction = (${normalizeCode(code)});`,
199
+ "return (async () => {",
200
+ " try {",
201
+ " const value = await __mcpUserFunction();",
202
+ " return { ok: true, value: __mcpToJsonValue(value) };",
203
+ " } catch (error) {",
204
+ " return { ok: false, error: __mcpNormalizeError(error) };",
205
+ " }",
206
+ "})();"
207
+ ].join("\n");
208
+ }
209
+ function setConsoleBindings(context, logs) {
210
+ const jail = context.global;
211
+ jail.setSync("__mcp_console_log", (...args) => {
212
+ logs.push(formatConsoleLine(args));
213
+ });
214
+ jail.setSync("__mcp_console_info", (...args) => {
215
+ logs.push(formatConsoleLine(args));
216
+ });
217
+ jail.setSync("__mcp_console_warn", (...args) => {
218
+ logs.push(formatConsoleLine(args));
219
+ });
220
+ jail.setSync("__mcp_console_error", (...args) => {
221
+ logs.push(formatConsoleLine(args));
222
+ });
223
+ }
224
+ function setProviderBindings(ivm, context, providers, signal, deadline) {
225
+ const jail = context.global;
226
+ for (const provider of providers) for (const [safeToolName, descriptor] of Object.entries(provider.tools)) {
227
+ const hostReferenceName = `__mcp_tool_${provider.name}_${safeToolName}`;
228
+ jail.setSync(hostReferenceName, async (input) => {
229
+ const executionContext = createExecutionContext(signal, provider.name, safeToolName, descriptor.originalName);
230
+ try {
231
+ const normalizedInput = input === void 0 ? void 0 : toJsonValue(input, "Guest code passed a non-serializable tool input");
232
+ return toTransferableValue(ivm, await runWithDeadline(Promise.resolve(descriptor.execute(normalizedInput, executionContext)), deadline, signal));
233
+ } catch (error) {
234
+ const executeError = toExecuteError(error, deadline);
235
+ throw new Error(`${HOST_ERROR_PREFIX}${JSON.stringify(executeError)}`, { cause: error });
236
+ }
237
+ }, { reference: true });
238
+ }
239
+ }
240
+ /**
241
+ * isolated-vm-backed executor for one-shot sandboxed JavaScript runs.
242
+ */
243
+ var IsolatedVmExecutor = class {
244
+ loadModule;
245
+ maxLogChars;
246
+ maxLogLines;
247
+ memoryLimitBytes;
248
+ timeoutMs;
249
+ constructor(options = {}) {
250
+ this.loadModule = async () => {
251
+ return options.loadModule ? await options.loadModule() : await loadDefaultModule();
252
+ };
253
+ this.maxLogChars = options.maxLogChars ?? DEFAULT_MAX_LOG_CHARS;
254
+ this.maxLogLines = options.maxLogLines ?? DEFAULT_MAX_LOG_LINES;
255
+ this.memoryLimitBytes = options.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES;
256
+ this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
257
+ }
258
+ /**
259
+ * Executes JavaScript against the provided tool namespaces in a fresh isolated-vm context.
260
+ */
261
+ async execute(code, providers) {
262
+ const startedAt = Date.now();
263
+ const deadline = startedAt + this.timeoutMs;
264
+ const logs = [];
265
+ const abortController = new AbortController();
266
+ if (Number.parseInt(process.versions.node.split(".")[0] ?? "0", 10) >= 20 && !hasRequiredNodeFlag()) return {
267
+ durationMs: Date.now() - startedAt,
268
+ error: {
269
+ code: "internal_error",
270
+ message: "isolated-vm requires Node to run with --no-node-snapshot on Node 20+"
271
+ },
272
+ logs,
273
+ ok: false
274
+ };
275
+ let catastrophicErrorMessage;
276
+ let isolate;
277
+ let context;
278
+ try {
279
+ const ivm = await this.loadModule();
280
+ isolate = new ivm.Isolate({
281
+ memoryLimit: toMemoryLimitMb(this.memoryLimitBytes),
282
+ onCatastrophicError: (message) => {
283
+ catastrophicErrorMessage = message;
284
+ abortController.abort();
285
+ }
286
+ });
287
+ context = await isolate.createContext();
288
+ setConsoleBindings(context, logs);
289
+ setProviderBindings(ivm, context, providers, abortController.signal, deadline);
290
+ await context.eval(createBootstrapSource(providers, this.timeoutMs), { timeout: this.timeoutMs });
291
+ const execution = await context.evalClosure(createExecutionSource(code), [], {
292
+ timeout: this.timeoutMs,
293
+ result: {
294
+ copy: true,
295
+ promise: true
296
+ }
297
+ });
298
+ if (catastrophicErrorMessage) return {
299
+ durationMs: Date.now() - startedAt,
300
+ error: {
301
+ code: "internal_error",
302
+ message: `isolated-vm catastrophic error: ${catastrophicErrorMessage}`
303
+ },
304
+ logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
305
+ ok: false
306
+ };
307
+ if (!execution.ok) return {
308
+ durationMs: Date.now() - startedAt,
309
+ error: toExecuteError(execution.error, deadline),
310
+ logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
311
+ ok: false
312
+ };
313
+ return {
314
+ durationMs: Date.now() - startedAt,
315
+ logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
316
+ ok: true,
317
+ result: execution.value
318
+ };
319
+ } catch (error) {
320
+ const executeError = catastrophicErrorMessage !== void 0 ? {
321
+ code: "internal_error",
322
+ message: `isolated-vm catastrophic error: ${catastrophicErrorMessage}`
323
+ } : toExecuteError(error, deadline);
324
+ return {
325
+ durationMs: Date.now() - startedAt,
326
+ error: executeError,
327
+ logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
328
+ ok: false
329
+ };
330
+ } finally {
331
+ abortController.abort();
332
+ context?.release?.();
333
+ isolate?.dispose();
334
+ }
335
+ }
336
+ };
337
+
338
+ //#endregion
339
+ export { IsolatedVmExecutor };
340
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["cachedModulePromise: Promise<IsolatedVmModule> | undefined","truncated: string[]","timeoutId: ReturnType<typeof setTimeout> | undefined","logs: string[]","catastrophicErrorMessage: string | undefined","isolate: IsolatedVmIsolate | undefined","context: IsolatedVmContext | undefined"],"sources":["../src/isolatedVmExecutor.ts"],"sourcesContent":["import {\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;\nconst HOST_ERROR_PREFIX = \"__MCP_CODE_EXEC_HOST_ERROR__\";\n\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 timeoutMs: number,\n): string {\n const lines = [\n `const __MCP_HOST_ERROR_PREFIX = ${JSON.stringify(HOST_ERROR_PREFIX)};`,\n \"const __mcpNormalizeError = (error) => {\",\n \" if (error && typeof error === 'object' && typeof error.code === 'string' && typeof error.message === 'string') {\",\n \" return { code: error.code, message: 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 payload;\",\n \" }\",\n \" } catch {}\",\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 __mcpRaiseNormalizedError = (error) => {\",\n \" const normalized = __mcpNormalizeError(error);\",\n \" const wrapped = new Error(normalized.message);\",\n \" wrapped.code = normalized.code;\",\n \" throw wrapped;\",\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 \" const error = new Error('Guest code returned a non-serializable value');\",\n \" error.code = 'serialization_error';\",\n \" throw error;\",\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: __mcpNormalizeError(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): 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 result = await runWithDeadline(\n Promise.resolve(\n descriptor.execute(normalizedInput, executionContext),\n ),\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 `${HOST_ERROR_PREFIX}${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 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 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 );\n await context.eval(createBootstrapSource(providers, this.timeoutMs), {\n timeout: this.timeoutMs,\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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"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@mcploom/codexec-isolated-vm",
3
+ "version": "0.1.0",
4
+ "description": "isolated-vm executor for the mcploom codexec core package.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "engines": {
8
+ "node": ">=20"
9
+ },
10
+ "main": "./dist/index.cjs",
11
+ "module": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js",
17
+ "require": "./dist/index.cjs"
18
+ }
19
+ },
20
+ "sideEffects": false,
21
+ "files": [
22
+ "dist",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "scripts": {
27
+ "build": "tsdown"
28
+ },
29
+ "keywords": [
30
+ "mcp",
31
+ "model-context-protocol",
32
+ "isolated-vm",
33
+ "sandbox",
34
+ "code-execution"
35
+ ],
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/aallam/mcploom.git",
39
+ "directory": "packages/codexec-isolated-vm"
40
+ },
41
+ "homepage": "https://github.com/aallam/mcploom/tree/main/packages/codexec-isolated-vm#readme",
42
+ "bugs": "https://github.com/aallam/mcploom/issues",
43
+ "dependencies": {
44
+ "@mcploom/codexec": "^0.1.0"
45
+ },
46
+ "optionalDependencies": {
47
+ "isolated-vm": "^6.0.1"
48
+ }
49
+ }