@mcploom/codexec-isolated-vm 0.1.2 → 0.1.3
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 +1 -1
- package/dist/index.cjs +47 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +47 -20
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ npm install @mcploom/codexec @mcploom/codexec-isolated-vm
|
|
|
36
36
|
## Security Notes
|
|
37
37
|
|
|
38
38
|
- Each execution gets a fresh `isolated-vm` context with JSON-only tool and result boundaries.
|
|
39
|
-
-
|
|
39
|
+
- In the default deployment model, provider definitions are controlled by the host application, while hostile users control guest code and tool inputs.
|
|
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
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
let node_crypto = require("node:crypto");
|
|
1
2
|
let __mcploom_codexec = require("@mcploom/codexec");
|
|
2
3
|
|
|
3
4
|
//#region src/isolatedVmExecutor.ts
|
|
@@ -5,7 +6,6 @@ const DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;
|
|
|
5
6
|
const DEFAULT_TIMEOUT_MS = 5e3;
|
|
6
7
|
const DEFAULT_MAX_LOG_LINES = 100;
|
|
7
8
|
const DEFAULT_MAX_LOG_CHARS = 64e3;
|
|
8
|
-
const HOST_ERROR_PREFIX = "__MCP_CODE_EXEC_HOST_ERROR__";
|
|
9
9
|
let cachedModulePromise;
|
|
10
10
|
function createExecutionContext(signal, providerName, safeToolName, originalToolName) {
|
|
11
11
|
return {
|
|
@@ -139,31 +139,51 @@ async function loadDefaultModule() {
|
|
|
139
139
|
});
|
|
140
140
|
return cachedModulePromise;
|
|
141
141
|
}
|
|
142
|
-
function createBootstrapSource(providers, timeoutMs) {
|
|
142
|
+
function createBootstrapSource(providers, hostErrorPrefix, timeoutMs) {
|
|
143
143
|
const lines = [
|
|
144
|
-
`const __MCP_HOST_ERROR_PREFIX = ${JSON.stringify(
|
|
145
|
-
|
|
146
|
-
"
|
|
147
|
-
"
|
|
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);",
|
|
148
154
|
" }",
|
|
149
155
|
" if (error && typeof error.message === 'string' && error.message.startsWith(__MCP_HOST_ERROR_PREFIX)) {",
|
|
150
156
|
" try {",
|
|
151
157
|
" const payload = JSON.parse(error.message.slice(__MCP_HOST_ERROR_PREFIX.length));",
|
|
152
158
|
" if (payload && typeof payload.code === 'string' && typeof payload.message === 'string') {",
|
|
153
|
-
" return payload;",
|
|
159
|
+
" return __mcpCreateTrustedError(payload.code, payload.message);",
|
|
154
160
|
" }",
|
|
155
161
|
" } catch {}",
|
|
156
162
|
" }",
|
|
163
|
+
" return null;",
|
|
164
|
+
"};",
|
|
165
|
+
"const __mcpNormalizeGuestError = (error) => {",
|
|
166
|
+
" const trusted = __mcpNormalizeTrustedError(error);",
|
|
167
|
+
" if (trusted) {",
|
|
168
|
+
" return trusted;",
|
|
169
|
+
" }",
|
|
157
170
|
" if (error && typeof error.message === 'string') {",
|
|
158
171
|
" return { code: 'runtime_error', message: error.message };",
|
|
159
172
|
" }",
|
|
160
173
|
" return { code: 'runtime_error', message: String(error) };",
|
|
161
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
|
+
"};",
|
|
162
185
|
"const __mcpRaiseNormalizedError = (error) => {",
|
|
163
|
-
"
|
|
164
|
-
" const wrapped = new Error(normalized.message);",
|
|
165
|
-
" wrapped.code = normalized.code;",
|
|
166
|
-
" throw wrapped;",
|
|
186
|
+
" throw __mcpNormalizeHostError(error);",
|
|
167
187
|
"};",
|
|
168
188
|
"const __mcpToJsonValue = (value) => {",
|
|
169
189
|
" if (typeof value === 'undefined') {",
|
|
@@ -171,9 +191,10 @@ function createBootstrapSource(providers, timeoutMs) {
|
|
|
171
191
|
" }",
|
|
172
192
|
" const json = JSON.stringify(value);",
|
|
173
193
|
" if (typeof json === 'undefined') {",
|
|
174
|
-
"
|
|
175
|
-
"
|
|
176
|
-
"
|
|
194
|
+
" throw __mcpCreateTrustedError(",
|
|
195
|
+
" 'serialization_error',",
|
|
196
|
+
" 'Guest code returned a non-serializable value'",
|
|
197
|
+
" );",
|
|
177
198
|
" }",
|
|
178
199
|
" return JSON.parse(json);",
|
|
179
200
|
"};",
|
|
@@ -201,7 +222,7 @@ function createExecutionSource(code) {
|
|
|
201
222
|
" const value = await __mcpUserFunction();",
|
|
202
223
|
" return { ok: true, value: __mcpToJsonValue(value) };",
|
|
203
224
|
" } catch (error) {",
|
|
204
|
-
" return { ok: false, error:
|
|
225
|
+
" return { ok: false, error: __mcpNormalizeGuestError(error) };",
|
|
205
226
|
" }",
|
|
206
227
|
"})();"
|
|
207
228
|
].join("\n");
|
|
@@ -221,7 +242,7 @@ function setConsoleBindings(context, logs) {
|
|
|
221
242
|
logs.push(formatConsoleLine(args));
|
|
222
243
|
});
|
|
223
244
|
}
|
|
224
|
-
function setProviderBindings(ivm, context, providers, signal, deadline) {
|
|
245
|
+
function setProviderBindings(ivm, context, providers, signal, deadline, hostErrorPrefix) {
|
|
225
246
|
const jail = context.global;
|
|
226
247
|
for (const provider of providers) for (const [safeToolName, descriptor] of Object.entries(provider.tools)) {
|
|
227
248
|
const hostReferenceName = `__mcp_tool_${provider.name}_${safeToolName}`;
|
|
@@ -229,10 +250,12 @@ function setProviderBindings(ivm, context, providers, signal, deadline) {
|
|
|
229
250
|
const executionContext = createExecutionContext(signal, provider.name, safeToolName, descriptor.originalName);
|
|
230
251
|
try {
|
|
231
252
|
const normalizedInput = input === void 0 ? void 0 : toJsonValue(input, "Guest code passed a non-serializable tool input");
|
|
232
|
-
|
|
253
|
+
const pendingExecution = Promise.resolve(descriptor.execute(normalizedInput, executionContext));
|
|
254
|
+
pendingExecution.catch(() => {});
|
|
255
|
+
return toTransferableValue(ivm, await runWithDeadline(pendingExecution, deadline, signal));
|
|
233
256
|
} catch (error) {
|
|
234
257
|
const executeError = toExecuteError(error, deadline);
|
|
235
|
-
throw new Error(`${
|
|
258
|
+
throw new Error(`${hostErrorPrefix}${JSON.stringify(executeError)}`, { cause: error });
|
|
236
259
|
}
|
|
237
260
|
}, { reference: true });
|
|
238
261
|
}
|
|
@@ -246,6 +269,9 @@ var IsolatedVmExecutor = class {
|
|
|
246
269
|
maxLogLines;
|
|
247
270
|
memoryLimitBytes;
|
|
248
271
|
timeoutMs;
|
|
272
|
+
/**
|
|
273
|
+
* Creates an isolated-vm executor with one-shot runtime limits and host bridging configuration.
|
|
274
|
+
*/
|
|
249
275
|
constructor(options = {}) {
|
|
250
276
|
this.loadModule = async () => {
|
|
251
277
|
return options.loadModule ? await options.loadModule() : await loadDefaultModule();
|
|
@@ -263,6 +289,7 @@ var IsolatedVmExecutor = class {
|
|
|
263
289
|
const deadline = startedAt + this.timeoutMs;
|
|
264
290
|
const logs = [];
|
|
265
291
|
const abortController = new AbortController();
|
|
292
|
+
const hostErrorPrefix = `__MCP_CODE_EXEC_HOST_ERROR__${(0, node_crypto.randomUUID)()}:`;
|
|
266
293
|
if (Number.parseInt(process.versions.node.split(".")[0] ?? "0", 10) >= 20 && !hasRequiredNodeFlag()) return {
|
|
267
294
|
durationMs: Date.now() - startedAt,
|
|
268
295
|
error: {
|
|
@@ -286,8 +313,8 @@ var IsolatedVmExecutor = class {
|
|
|
286
313
|
});
|
|
287
314
|
context = await isolate.createContext();
|
|
288
315
|
setConsoleBindings(context, logs);
|
|
289
|
-
setProviderBindings(ivm, context, providers, abortController.signal, deadline);
|
|
290
|
-
await context.eval(createBootstrapSource(providers, this.timeoutMs), { timeout: this.timeoutMs });
|
|
316
|
+
setProviderBindings(ivm, context, providers, abortController.signal, deadline, hostErrorPrefix);
|
|
317
|
+
await context.eval(createBootstrapSource(providers, hostErrorPrefix, this.timeoutMs), { timeout: this.timeoutMs });
|
|
291
318
|
const execution = await context.evalClosure(createExecutionSource(code), [], {
|
|
292
319
|
timeout: this.timeoutMs,
|
|
293
320
|
result: {
|
package/dist/index.cjs.map
CHANGED
|
@@ -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 {\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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"}
|
|
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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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -27,6 +27,9 @@ declare class IsolatedVmExecutor implements Executor {
|
|
|
27
27
|
private readonly maxLogLines;
|
|
28
28
|
private readonly memoryLimitBytes;
|
|
29
29
|
private readonly timeoutMs;
|
|
30
|
+
/**
|
|
31
|
+
* Creates an isolated-vm executor with one-shot runtime limits and host bridging configuration.
|
|
32
|
+
*/
|
|
30
33
|
constructor(options?: IsolatedVmExecutorOptions);
|
|
31
34
|
/**
|
|
32
35
|
* Executes JavaScript against the provided tool namespaces in a fresh isolated-vm context.
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/isolatedVmExecutor.ts"],"sourcesContent":[],"mappings":";;;;;;AAGiB,UAAA,yBAAA,CAEI;;qBAAA;;
|
|
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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,9 @@ declare class IsolatedVmExecutor implements Executor {
|
|
|
27
27
|
private readonly maxLogLines;
|
|
28
28
|
private readonly memoryLimitBytes;
|
|
29
29
|
private readonly timeoutMs;
|
|
30
|
+
/**
|
|
31
|
+
* Creates an isolated-vm executor with one-shot runtime limits and host bridging configuration.
|
|
32
|
+
*/
|
|
30
33
|
constructor(options?: IsolatedVmExecutorOptions);
|
|
31
34
|
/**
|
|
32
35
|
* Executes JavaScript against the provided tool namespaces in a fresh isolated-vm context.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/isolatedVmExecutor.ts"],"sourcesContent":[],"mappings":";;;;;;AAGiB,UAAA,yBAAA,CAEI;;qBAAA;;
|
|
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"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import { ExecuteFailure, isExecuteFailure, normalizeCode } from "@mcploom/codexec";
|
|
2
3
|
|
|
3
4
|
//#region src/isolatedVmExecutor.ts
|
|
@@ -5,7 +6,6 @@ const DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;
|
|
|
5
6
|
const DEFAULT_TIMEOUT_MS = 5e3;
|
|
6
7
|
const DEFAULT_MAX_LOG_LINES = 100;
|
|
7
8
|
const DEFAULT_MAX_LOG_CHARS = 64e3;
|
|
8
|
-
const HOST_ERROR_PREFIX = "__MCP_CODE_EXEC_HOST_ERROR__";
|
|
9
9
|
let cachedModulePromise;
|
|
10
10
|
function createExecutionContext(signal, providerName, safeToolName, originalToolName) {
|
|
11
11
|
return {
|
|
@@ -139,31 +139,51 @@ async function loadDefaultModule() {
|
|
|
139
139
|
});
|
|
140
140
|
return cachedModulePromise;
|
|
141
141
|
}
|
|
142
|
-
function createBootstrapSource(providers, timeoutMs) {
|
|
142
|
+
function createBootstrapSource(providers, hostErrorPrefix, timeoutMs) {
|
|
143
143
|
const lines = [
|
|
144
|
-
`const __MCP_HOST_ERROR_PREFIX = ${JSON.stringify(
|
|
145
|
-
|
|
146
|
-
"
|
|
147
|
-
"
|
|
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);",
|
|
148
154
|
" }",
|
|
149
155
|
" if (error && typeof error.message === 'string' && error.message.startsWith(__MCP_HOST_ERROR_PREFIX)) {",
|
|
150
156
|
" try {",
|
|
151
157
|
" const payload = JSON.parse(error.message.slice(__MCP_HOST_ERROR_PREFIX.length));",
|
|
152
158
|
" if (payload && typeof payload.code === 'string' && typeof payload.message === 'string') {",
|
|
153
|
-
" return payload;",
|
|
159
|
+
" return __mcpCreateTrustedError(payload.code, payload.message);",
|
|
154
160
|
" }",
|
|
155
161
|
" } catch {}",
|
|
156
162
|
" }",
|
|
163
|
+
" return null;",
|
|
164
|
+
"};",
|
|
165
|
+
"const __mcpNormalizeGuestError = (error) => {",
|
|
166
|
+
" const trusted = __mcpNormalizeTrustedError(error);",
|
|
167
|
+
" if (trusted) {",
|
|
168
|
+
" return trusted;",
|
|
169
|
+
" }",
|
|
157
170
|
" if (error && typeof error.message === 'string') {",
|
|
158
171
|
" return { code: 'runtime_error', message: error.message };",
|
|
159
172
|
" }",
|
|
160
173
|
" return { code: 'runtime_error', message: String(error) };",
|
|
161
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
|
+
"};",
|
|
162
185
|
"const __mcpRaiseNormalizedError = (error) => {",
|
|
163
|
-
"
|
|
164
|
-
" const wrapped = new Error(normalized.message);",
|
|
165
|
-
" wrapped.code = normalized.code;",
|
|
166
|
-
" throw wrapped;",
|
|
186
|
+
" throw __mcpNormalizeHostError(error);",
|
|
167
187
|
"};",
|
|
168
188
|
"const __mcpToJsonValue = (value) => {",
|
|
169
189
|
" if (typeof value === 'undefined') {",
|
|
@@ -171,9 +191,10 @@ function createBootstrapSource(providers, timeoutMs) {
|
|
|
171
191
|
" }",
|
|
172
192
|
" const json = JSON.stringify(value);",
|
|
173
193
|
" if (typeof json === 'undefined') {",
|
|
174
|
-
"
|
|
175
|
-
"
|
|
176
|
-
"
|
|
194
|
+
" throw __mcpCreateTrustedError(",
|
|
195
|
+
" 'serialization_error',",
|
|
196
|
+
" 'Guest code returned a non-serializable value'",
|
|
197
|
+
" );",
|
|
177
198
|
" }",
|
|
178
199
|
" return JSON.parse(json);",
|
|
179
200
|
"};",
|
|
@@ -201,7 +222,7 @@ function createExecutionSource(code) {
|
|
|
201
222
|
" const value = await __mcpUserFunction();",
|
|
202
223
|
" return { ok: true, value: __mcpToJsonValue(value) };",
|
|
203
224
|
" } catch (error) {",
|
|
204
|
-
" return { ok: false, error:
|
|
225
|
+
" return { ok: false, error: __mcpNormalizeGuestError(error) };",
|
|
205
226
|
" }",
|
|
206
227
|
"})();"
|
|
207
228
|
].join("\n");
|
|
@@ -221,7 +242,7 @@ function setConsoleBindings(context, logs) {
|
|
|
221
242
|
logs.push(formatConsoleLine(args));
|
|
222
243
|
});
|
|
223
244
|
}
|
|
224
|
-
function setProviderBindings(ivm, context, providers, signal, deadline) {
|
|
245
|
+
function setProviderBindings(ivm, context, providers, signal, deadline, hostErrorPrefix) {
|
|
225
246
|
const jail = context.global;
|
|
226
247
|
for (const provider of providers) for (const [safeToolName, descriptor] of Object.entries(provider.tools)) {
|
|
227
248
|
const hostReferenceName = `__mcp_tool_${provider.name}_${safeToolName}`;
|
|
@@ -229,10 +250,12 @@ function setProviderBindings(ivm, context, providers, signal, deadline) {
|
|
|
229
250
|
const executionContext = createExecutionContext(signal, provider.name, safeToolName, descriptor.originalName);
|
|
230
251
|
try {
|
|
231
252
|
const normalizedInput = input === void 0 ? void 0 : toJsonValue(input, "Guest code passed a non-serializable tool input");
|
|
232
|
-
|
|
253
|
+
const pendingExecution = Promise.resolve(descriptor.execute(normalizedInput, executionContext));
|
|
254
|
+
pendingExecution.catch(() => {});
|
|
255
|
+
return toTransferableValue(ivm, await runWithDeadline(pendingExecution, deadline, signal));
|
|
233
256
|
} catch (error) {
|
|
234
257
|
const executeError = toExecuteError(error, deadline);
|
|
235
|
-
throw new Error(`${
|
|
258
|
+
throw new Error(`${hostErrorPrefix}${JSON.stringify(executeError)}`, { cause: error });
|
|
236
259
|
}
|
|
237
260
|
}, { reference: true });
|
|
238
261
|
}
|
|
@@ -246,6 +269,9 @@ var IsolatedVmExecutor = class {
|
|
|
246
269
|
maxLogLines;
|
|
247
270
|
memoryLimitBytes;
|
|
248
271
|
timeoutMs;
|
|
272
|
+
/**
|
|
273
|
+
* Creates an isolated-vm executor with one-shot runtime limits and host bridging configuration.
|
|
274
|
+
*/
|
|
249
275
|
constructor(options = {}) {
|
|
250
276
|
this.loadModule = async () => {
|
|
251
277
|
return options.loadModule ? await options.loadModule() : await loadDefaultModule();
|
|
@@ -263,6 +289,7 @@ var IsolatedVmExecutor = class {
|
|
|
263
289
|
const deadline = startedAt + this.timeoutMs;
|
|
264
290
|
const logs = [];
|
|
265
291
|
const abortController = new AbortController();
|
|
292
|
+
const hostErrorPrefix = `__MCP_CODE_EXEC_HOST_ERROR__${randomUUID()}:`;
|
|
266
293
|
if (Number.parseInt(process.versions.node.split(".")[0] ?? "0", 10) >= 20 && !hasRequiredNodeFlag()) return {
|
|
267
294
|
durationMs: Date.now() - startedAt,
|
|
268
295
|
error: {
|
|
@@ -286,8 +313,8 @@ var IsolatedVmExecutor = class {
|
|
|
286
313
|
});
|
|
287
314
|
context = await isolate.createContext();
|
|
288
315
|
setConsoleBindings(context, logs);
|
|
289
|
-
setProviderBindings(ivm, context, providers, abortController.signal, deadline);
|
|
290
|
-
await context.eval(createBootstrapSource(providers, this.timeoutMs), { timeout: this.timeoutMs });
|
|
316
|
+
setProviderBindings(ivm, context, providers, abortController.signal, deadline, hostErrorPrefix);
|
|
317
|
+
await context.eval(createBootstrapSource(providers, hostErrorPrefix, this.timeoutMs), { timeout: this.timeoutMs });
|
|
291
318
|
const execution = await context.evalClosure(createExecutionSource(code), [], {
|
|
292
319
|
timeout: this.timeoutMs,
|
|
293
320
|
result: {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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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"}
|
|
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 { 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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcploom/codexec-isolated-vm",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "isolated-vm executor for the mcploom codexec core package.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"homepage": "https://github.com/aallam/mcploom/tree/main/packages/codexec-isolated-vm#readme",
|
|
42
42
|
"bugs": "https://github.com/aallam/mcploom/issues",
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@mcploom/codexec": "^0.2.
|
|
44
|
+
"@mcploom/codexec": "^0.2.2"
|
|
45
45
|
},
|
|
46
46
|
"optionalDependencies": {
|
|
47
47
|
"isolated-vm": "^6.0.1"
|