@mcploom/codexec-isolated-vm 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,363 +1,42 @@
1
- import { randomUUID } from "node:crypto";
2
- import { ExecuteFailure, isExecuteFailure, normalizeCode } from "@mcploom/codexec";
1
+ import { t as runIsolatedVmSession } from "./runner-Dbq2FDWK.js";
2
+ import { createTimeoutExecuteResult, createToolCallDispatcher, extractProviderManifests } from "@mcploom/codexec";
3
3
 
4
4
  //#region src/isolatedVmExecutor.ts
5
- const DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;
6
- const DEFAULT_TIMEOUT_MS = 5e3;
7
- const DEFAULT_MAX_LOG_LINES = 100;
8
- const DEFAULT_MAX_LOG_CHARS = 64e3;
9
- let cachedModulePromise;
10
- function createExecutionContext(signal, providerName, safeToolName, originalToolName) {
11
- return {
12
- originalToolName,
13
- providerName,
14
- safeToolName,
15
- signal
16
- };
17
- }
18
- function hasRequiredNodeFlag() {
19
- const execArgv = process.execArgv.join(" ");
20
- const nodeOptions = process.env.NODE_OPTIONS ?? "";
21
- return execArgv.includes("--no-node-snapshot") || nodeOptions.includes("--no-node-snapshot");
22
- }
23
- function isKnownErrorCode(value) {
24
- return value === "timeout" || value === "memory_limit" || value === "validation_error" || value === "tool_error" || value === "runtime_error" || value === "serialization_error" || value === "internal_error";
25
- }
26
- function normalizeThrownMessage(error) {
27
- if (error instanceof Error) return error.message;
28
- if (typeof error === "object" && error !== null && "message" in error) {
29
- const message = error.message;
30
- if (typeof message === "string") return message;
31
- }
32
- return String(error);
33
- }
34
- function truncateLogs(logs, maxLogLines, maxLogChars) {
35
- const limitedLines = logs.slice(0, maxLogLines);
36
- let remainingChars = maxLogChars;
37
- const truncated = [];
38
- for (const line of limitedLines) {
39
- if (remainingChars <= 0) break;
40
- if (line.length <= remainingChars) {
41
- truncated.push(line);
42
- remainingChars -= line.length;
43
- continue;
44
- }
45
- truncated.push(line.slice(0, remainingChars));
46
- break;
47
- }
48
- return truncated;
49
- }
50
- function formatLogValue(value) {
51
- if (typeof value === "string") return value;
52
- if (value === void 0) return "undefined";
53
- try {
54
- return JSON.stringify(value);
55
- } catch {
56
- return String(value);
57
- }
58
- }
59
- function formatConsoleLine(values) {
60
- return values.map((value) => formatLogValue(value)).join(" ");
61
- }
62
- function toJsonValue(value, message) {
63
- if (value === void 0) return;
64
- const jsonValue = JSON.stringify(value);
65
- if (jsonValue === void 0) throw new 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, hostErrorPrefix, timeoutMs) {
143
- const lines = [
144
- `const __MCP_HOST_ERROR_PREFIX = ${JSON.stringify(hostErrorPrefix)};`,
145
- `const __MCP_HOST_ERROR_KEY = ${JSON.stringify(`${hostErrorPrefix}key`)};`,
146
- "const __mcpCreateTrustedError = (code, message) => ({",
147
- " [__MCP_HOST_ERROR_KEY]: true,",
148
- " code,",
149
- " message,",
150
- "});",
151
- "const __mcpNormalizeTrustedError = (error) => {",
152
- " if (error && typeof error === 'object' && error[__MCP_HOST_ERROR_KEY] === true && typeof error.code === 'string' && typeof error.message === 'string') {",
153
- " return __mcpCreateTrustedError(error.code, error.message);",
154
- " }",
155
- " if (error && typeof error.message === 'string' && error.message.startsWith(__MCP_HOST_ERROR_PREFIX)) {",
156
- " try {",
157
- " const payload = JSON.parse(error.message.slice(__MCP_HOST_ERROR_PREFIX.length));",
158
- " if (payload && typeof payload.code === 'string' && typeof payload.message === 'string') {",
159
- " return __mcpCreateTrustedError(payload.code, payload.message);",
160
- " }",
161
- " } catch {}",
162
- " }",
163
- " return null;",
164
- "};",
165
- "const __mcpNormalizeGuestError = (error) => {",
166
- " const trusted = __mcpNormalizeTrustedError(error);",
167
- " if (trusted) {",
168
- " return trusted;",
169
- " }",
170
- " if (error && typeof error.message === 'string') {",
171
- " return { code: 'runtime_error', message: error.message };",
172
- " }",
173
- " return { code: 'runtime_error', message: String(error) };",
174
- "};",
175
- "const __mcpNormalizeHostError = (error) => {",
176
- " const trusted = __mcpNormalizeTrustedError(error);",
177
- " if (trusted) {",
178
- " return trusted;",
179
- " }",
180
- " if (error && typeof error === 'object' && typeof error.code === 'string' && typeof error.message === 'string') {",
181
- " return __mcpCreateTrustedError(error.code, error.message);",
182
- " }",
183
- " return __mcpNormalizeGuestError(error);",
184
- "};",
185
- "const __mcpRaiseNormalizedError = (error) => {",
186
- " throw __mcpNormalizeHostError(error);",
187
- "};",
188
- "const __mcpToJsonValue = (value) => {",
189
- " if (typeof value === 'undefined') {",
190
- " return undefined;",
191
- " }",
192
- " const json = JSON.stringify(value);",
193
- " if (typeof json === 'undefined') {",
194
- " throw __mcpCreateTrustedError(",
195
- " 'serialization_error',",
196
- " 'Guest code returned a non-serializable value'",
197
- " );",
198
- " }",
199
- " return JSON.parse(json);",
200
- "};",
201
- "globalThis.console = {",
202
- " log: (...args) => __mcp_console_log(...args),",
203
- " info: (...args) => __mcp_console_info(...args),",
204
- " warn: (...args) => __mcp_console_warn(...args),",
205
- " error: (...args) => __mcp_console_error(...args),",
206
- "};"
207
- ];
208
- for (const provider of providers) {
209
- lines.push(`globalThis.${provider.name} = {};`);
210
- for (const safeToolName of Object.keys(provider.tools)) {
211
- const hostReferenceName = `__mcp_tool_${provider.name}_${safeToolName}`;
212
- lines.push(`globalThis.${provider.name}.${safeToolName} = async (input) => {`, " try {", ` return await ${hostReferenceName}.applySyncPromise(undefined, [input], { arguments: { copy: true }, timeout: ${timeoutMs} });`, " } catch (error) {", " __mcpRaiseNormalizedError(error);", " }", "};");
213
- }
214
- }
215
- return lines.join("\n");
216
- }
217
- function createExecutionSource(code) {
218
- return [
219
- `const __mcpUserFunction = (${normalizeCode(code)});`,
220
- "return (async () => {",
221
- " try {",
222
- " const value = await __mcpUserFunction();",
223
- " return { ok: true, value: __mcpToJsonValue(value) };",
224
- " } catch (error) {",
225
- " return { ok: false, error: __mcpNormalizeGuestError(error) };",
226
- " }",
227
- "})();"
228
- ].join("\n");
229
- }
230
- function setConsoleBindings(context, logs) {
231
- const jail = context.global;
232
- jail.setSync("__mcp_console_log", (...args) => {
233
- logs.push(formatConsoleLine(args));
234
- });
235
- jail.setSync("__mcp_console_info", (...args) => {
236
- logs.push(formatConsoleLine(args));
237
- });
238
- jail.setSync("__mcp_console_warn", (...args) => {
239
- logs.push(formatConsoleLine(args));
240
- });
241
- jail.setSync("__mcp_console_error", (...args) => {
242
- logs.push(formatConsoleLine(args));
243
- });
244
- }
245
- function setProviderBindings(ivm, context, providers, signal, deadline, hostErrorPrefix) {
246
- const jail = context.global;
247
- for (const provider of providers) for (const [safeToolName, descriptor] of Object.entries(provider.tools)) {
248
- const hostReferenceName = `__mcp_tool_${provider.name}_${safeToolName}`;
249
- jail.setSync(hostReferenceName, async (input) => {
250
- const executionContext = createExecutionContext(signal, provider.name, safeToolName, descriptor.originalName);
251
- try {
252
- const normalizedInput = input === void 0 ? void 0 : toJsonValue(input, "Guest code passed a non-serializable tool input");
253
- const pendingExecution = Promise.resolve(descriptor.execute(normalizedInput, executionContext));
254
- pendingExecution.catch(() => {});
255
- return toTransferableValue(ivm, await runWithDeadline(pendingExecution, deadline, signal));
256
- } catch (error) {
257
- const executeError = toExecuteError(error, deadline);
258
- throw new Error(`${hostErrorPrefix}${JSON.stringify(executeError)}`, { cause: error });
259
- }
260
- }, { reference: true });
261
- }
262
- }
263
5
  /**
264
6
  * isolated-vm-backed executor for one-shot sandboxed JavaScript runs.
265
7
  */
266
8
  var IsolatedVmExecutor = class {
267
- loadModule;
268
- maxLogChars;
269
- maxLogLines;
270
- memoryLimitBytes;
271
- timeoutMs;
9
+ options;
272
10
  /**
273
11
  * Creates an isolated-vm executor with one-shot runtime limits and host bridging configuration.
274
12
  */
275
13
  constructor(options = {}) {
276
- this.loadModule = async () => {
277
- return options.loadModule ? await options.loadModule() : await loadDefaultModule();
278
- };
279
- this.maxLogChars = options.maxLogChars ?? DEFAULT_MAX_LOG_CHARS;
280
- this.maxLogLines = options.maxLogLines ?? DEFAULT_MAX_LOG_LINES;
281
- this.memoryLimitBytes = options.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES;
282
- this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
14
+ this.options = options;
283
15
  }
284
16
  /**
285
17
  * Executes JavaScript against the provided tool namespaces in a fresh isolated-vm context.
286
18
  */
287
- async execute(code, providers) {
288
- const startedAt = Date.now();
289
- const deadline = startedAt + this.timeoutMs;
290
- const logs = [];
19
+ async execute(code, providers, options = {}) {
20
+ if (options.signal?.aborted) return createTimeoutExecuteResult();
291
21
  const abortController = new AbortController();
292
- const hostErrorPrefix = `__MCP_CODE_EXEC_HOST_ERROR__${randomUUID()}:`;
293
- if (Number.parseInt(process.versions.node.split(".")[0] ?? "0", 10) >= 20 && !hasRequiredNodeFlag()) return {
294
- durationMs: Date.now() - startedAt,
295
- error: {
296
- code: "internal_error",
297
- message: "isolated-vm requires Node to run with --no-node-snapshot on Node 20+"
298
- },
299
- logs,
300
- ok: false
22
+ const onToolCall = createToolCallDispatcher(providers, abortController.signal);
23
+ const onAbort = () => {
24
+ abortController.abort();
301
25
  };
302
- let catastrophicErrorMessage;
303
- let isolate;
304
- let context;
26
+ options.signal?.addEventListener("abort", onAbort, { once: true });
305
27
  try {
306
- const ivm = await this.loadModule();
307
- isolate = new ivm.Isolate({
308
- memoryLimit: toMemoryLimitMb(this.memoryLimitBytes),
309
- onCatastrophicError: (message) => {
310
- catastrophicErrorMessage = message;
311
- abortController.abort();
312
- }
313
- });
314
- context = await isolate.createContext();
315
- setConsoleBindings(context, logs);
316
- setProviderBindings(ivm, context, providers, abortController.signal, deadline, hostErrorPrefix);
317
- await context.eval(createBootstrapSource(providers, hostErrorPrefix, this.timeoutMs), { timeout: this.timeoutMs });
318
- const execution = await context.evalClosure(createExecutionSource(code), [], {
319
- timeout: this.timeoutMs,
320
- result: {
321
- copy: true,
322
- promise: true
323
- }
28
+ return await runIsolatedVmSession({
29
+ abortController,
30
+ code,
31
+ onToolCall,
32
+ providers: extractProviderManifests(providers)
33
+ }, {
34
+ ...this.options,
35
+ ...options
324
36
  });
325
- if (catastrophicErrorMessage) return {
326
- durationMs: Date.now() - startedAt,
327
- error: {
328
- code: "internal_error",
329
- message: `isolated-vm catastrophic error: ${catastrophicErrorMessage}`
330
- },
331
- logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
332
- ok: false
333
- };
334
- if (!execution.ok) return {
335
- durationMs: Date.now() - startedAt,
336
- error: toExecuteError(execution.error, deadline),
337
- logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
338
- ok: false
339
- };
340
- return {
341
- durationMs: Date.now() - startedAt,
342
- logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
343
- ok: true,
344
- result: execution.value
345
- };
346
- } catch (error) {
347
- const executeError = catastrophicErrorMessage !== void 0 ? {
348
- code: "internal_error",
349
- message: `isolated-vm catastrophic error: ${catastrophicErrorMessage}`
350
- } : toExecuteError(error, deadline);
351
- return {
352
- durationMs: Date.now() - startedAt,
353
- error: executeError,
354
- logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),
355
- ok: false
356
- };
357
37
  } finally {
38
+ options.signal?.removeEventListener("abort", onAbort);
358
39
  abortController.abort();
359
- context?.release?.();
360
- isolate?.dispose();
361
40
  }
362
41
  }
363
42
  };
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 { randomUUID } from \"node:crypto\";\n\nimport {\n ExecuteFailure,\n isExecuteFailure,\n normalizeCode,\n} from \"@mcploom/codexec\";\nimport type {\n ExecuteError,\n ExecuteResult,\n Executor,\n ResolvedToolProvider,\n ToolExecutionContext,\n} from \"@mcploom/codexec\";\n\nimport type { IsolatedVmExecutorOptions } from \"./types\";\n\ntype IsolatedVmExternalCopyInstance = {\n copyInto: (options?: { release?: boolean; transferIn?: boolean }) => unknown;\n release?: () => void;\n};\n\ntype IsolatedVmReferenceInstance = {\n setSync: (\n property: string,\n value: unknown,\n options?: Record<string, unknown>,\n ) => void;\n};\n\ntype IsolatedVmContext = {\n eval: (code: string, options?: Record<string, unknown>) => Promise<unknown>;\n evalClosure: (\n code: string,\n args?: unknown[],\n options?: Record<string, unknown>,\n ) => Promise<unknown>;\n global: IsolatedVmReferenceInstance;\n release?: () => void;\n};\n\ntype IsolatedVmIsolate = {\n createContext: () => Promise<IsolatedVmContext>;\n dispose: () => void;\n};\n\ntype IsolatedVmModule = {\n ExternalCopy: new (\n value: unknown,\n options?: Record<string, unknown>,\n ) => IsolatedVmExternalCopyInstance;\n Isolate: new (options?: {\n inspector?: boolean;\n memoryLimit?: number;\n onCatastrophicError?: (message: string) => void;\n }) => IsolatedVmIsolate;\n};\n\ntype GuestExecutionEnvelope =\n | {\n ok: true;\n value: unknown;\n }\n | {\n error: {\n code?: string;\n message?: string;\n };\n ok: false;\n };\n\nconst DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;\nconst DEFAULT_TIMEOUT_MS = 5000;\nconst DEFAULT_MAX_LOG_LINES = 100;\nconst DEFAULT_MAX_LOG_CHARS = 64_000;\nlet cachedModulePromise: Promise<IsolatedVmModule> | undefined;\n\nfunction createExecutionContext(\n signal: AbortSignal,\n providerName: string,\n safeToolName: string,\n originalToolName: string,\n): ToolExecutionContext {\n return {\n originalToolName,\n providerName,\n safeToolName,\n signal,\n };\n}\n\nfunction hasRequiredNodeFlag(): boolean {\n const execArgv = process.execArgv.join(\" \");\n const nodeOptions = process.env.NODE_OPTIONS ?? \"\";\n return (\n execArgv.includes(\"--no-node-snapshot\") ||\n nodeOptions.includes(\"--no-node-snapshot\")\n );\n}\n\nfunction isKnownErrorCode(value: unknown): value is ExecuteError[\"code\"] {\n return (\n value === \"timeout\" ||\n value === \"memory_limit\" ||\n value === \"validation_error\" ||\n value === \"tool_error\" ||\n value === \"runtime_error\" ||\n value === \"serialization_error\" ||\n value === \"internal_error\"\n );\n}\n\nfunction normalizeThrownMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n if (typeof error === \"object\" && error !== null && \"message\" in error) {\n const message = (error as { message?: unknown }).message;\n if (typeof message === \"string\") {\n return message;\n }\n }\n\n return String(error);\n}\n\nfunction truncateLogs(\n logs: string[],\n maxLogLines: number,\n maxLogChars: number,\n): string[] {\n const limitedLines = logs.slice(0, maxLogLines);\n let remainingChars = maxLogChars;\n const truncated: string[] = [];\n\n for (const line of limitedLines) {\n if (remainingChars <= 0) {\n break;\n }\n\n if (line.length <= remainingChars) {\n truncated.push(line);\n remainingChars -= line.length;\n continue;\n }\n\n truncated.push(line.slice(0, remainingChars));\n break;\n }\n\n return truncated;\n}\n\nfunction formatLogValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (value === undefined) {\n return \"undefined\";\n }\n\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction formatConsoleLine(values: unknown[]): string {\n return values.map((value) => formatLogValue(value)).join(\" \");\n}\n\nfunction toJsonValue(value: unknown, message: string): unknown {\n if (value === undefined) {\n return undefined;\n }\n\n const jsonValue = JSON.stringify(value);\n\n if (jsonValue === undefined) {\n throw new ExecuteFailure(\"serialization_error\", message);\n }\n\n try {\n return JSON.parse(jsonValue) as unknown;\n } catch {\n throw new ExecuteFailure(\"serialization_error\", message);\n }\n}\n\nfunction toTransferableValue(ivm: IsolatedVmModule, value: unknown): unknown {\n const normalizedValue = toJsonValue(\n value,\n \"Host value is not JSON-serializable\",\n );\n\n if (\n normalizedValue === null ||\n normalizedValue === undefined ||\n typeof normalizedValue === \"string\" ||\n typeof normalizedValue === \"number\" ||\n typeof normalizedValue === \"boolean\"\n ) {\n return normalizedValue;\n }\n\n const copy = new ivm.ExternalCopy(normalizedValue);\n return copy.copyInto({ release: true });\n}\n\nfunction toExecuteError(error: unknown, deadline: number): ExecuteError {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n \"message\" in error &&\n isKnownErrorCode((error as { code?: unknown }).code) &&\n typeof (error as { message?: unknown }).message === \"string\"\n ) {\n return {\n code: (error as { code: ExecuteError[\"code\"] }).code,\n message: (error as { message: string }).message,\n };\n }\n\n if (isExecuteFailure(error)) {\n return {\n code: error.code,\n message: error.message,\n };\n }\n\n const message = normalizeThrownMessage(error);\n const normalizedMessage = message.toLowerCase();\n\n if (\n Date.now() > deadline ||\n normalizedMessage.includes(\"timed out\") ||\n normalizedMessage.includes(\"time limit\")\n ) {\n return {\n code: \"timeout\",\n message: \"Execution timed out\",\n };\n }\n\n if (\n normalizedMessage.includes(\"memory limit\") ||\n normalizedMessage.includes(\"out of memory\")\n ) {\n return {\n code: \"memory_limit\",\n message,\n };\n }\n\n if (\n normalizedMessage.includes(\"could not be cloned\") ||\n normalizedMessage.includes(\"non-transferable\") ||\n normalizedMessage.includes(\"not json-serializable\")\n ) {\n return {\n code: \"serialization_error\",\n message,\n };\n }\n\n return {\n code: \"runtime_error\",\n message,\n };\n}\n\nfunction toMemoryLimitMb(memoryLimitBytes: number): number {\n return Math.max(8, Math.ceil(memoryLimitBytes / (1024 * 1024)));\n}\n\nfunction remainingTime(deadline: number): number {\n return Math.max(0, deadline - Date.now());\n}\n\nasync function runWithDeadline<T>(\n operation: Promise<T>,\n deadline: number,\n signal: AbortSignal,\n): Promise<T> {\n if (signal.aborted || Date.now() > deadline) {\n throw new ExecuteFailure(\"timeout\", \"Execution timed out\");\n }\n\n const timeoutMs = remainingTime(deadline);\n if (timeoutMs <= 0) {\n throw new ExecuteFailure(\"timeout\", \"Execution timed out\");\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n return await new Promise<T>((resolve, reject) => {\n const onAbort = () => {\n reject(new ExecuteFailure(\"timeout\", \"Execution timed out\"));\n };\n\n signal.addEventListener(\"abort\", onAbort, { once: true });\n timeoutId = setTimeout(() => {\n signal.removeEventListener(\"abort\", onAbort);\n reject(new ExecuteFailure(\"timeout\", \"Execution timed out\"));\n }, timeoutMs);\n\n void operation.then(\n (value) => {\n signal.removeEventListener(\"abort\", onAbort);\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n resolve(value);\n },\n (error) => {\n signal.removeEventListener(\"abort\", onAbort);\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n reject(error);\n },\n );\n });\n}\n\nasync function loadDefaultModule(): Promise<IsolatedVmModule> {\n cachedModulePromise ??= import(\"isolated-vm\").then((loaded) => {\n const candidate = (\n \"default\" in loaded ? loaded.default : loaded\n ) as unknown;\n return candidate as IsolatedVmModule;\n });\n\n return cachedModulePromise;\n}\n\nfunction createBootstrapSource(\n providers: ResolvedToolProvider[],\n hostErrorPrefix: string,\n timeoutMs: number,\n): string {\n const lines = [\n `const __MCP_HOST_ERROR_PREFIX = ${JSON.stringify(hostErrorPrefix)};`,\n `const __MCP_HOST_ERROR_KEY = ${JSON.stringify(`${hostErrorPrefix}key`)};`,\n \"const __mcpCreateTrustedError = (code, message) => ({\",\n \" [__MCP_HOST_ERROR_KEY]: true,\",\n \" code,\",\n \" message,\",\n \"});\",\n \"const __mcpNormalizeTrustedError = (error) => {\",\n \" if (error && typeof error === 'object' && error[__MCP_HOST_ERROR_KEY] === true && typeof error.code === 'string' && typeof error.message === 'string') {\",\n \" return __mcpCreateTrustedError(error.code, error.message);\",\n \" }\",\n \" if (error && typeof error.message === 'string' && error.message.startsWith(__MCP_HOST_ERROR_PREFIX)) {\",\n \" try {\",\n \" const payload = JSON.parse(error.message.slice(__MCP_HOST_ERROR_PREFIX.length));\",\n \" if (payload && typeof payload.code === 'string' && typeof payload.message === 'string') {\",\n \" return __mcpCreateTrustedError(payload.code, payload.message);\",\n \" }\",\n \" } catch {}\",\n \" }\",\n \" return null;\",\n \"};\",\n \"const __mcpNormalizeGuestError = (error) => {\",\n \" const trusted = __mcpNormalizeTrustedError(error);\",\n \" if (trusted) {\",\n \" return trusted;\",\n \" }\",\n \" if (error && typeof error.message === 'string') {\",\n \" return { code: 'runtime_error', message: error.message };\",\n \" }\",\n \" return { code: 'runtime_error', message: String(error) };\",\n \"};\",\n \"const __mcpNormalizeHostError = (error) => {\",\n \" const trusted = __mcpNormalizeTrustedError(error);\",\n \" if (trusted) {\",\n \" return trusted;\",\n \" }\",\n \" if (error && typeof error === 'object' && typeof error.code === 'string' && typeof error.message === 'string') {\",\n \" return __mcpCreateTrustedError(error.code, error.message);\",\n \" }\",\n \" return __mcpNormalizeGuestError(error);\",\n \"};\",\n \"const __mcpRaiseNormalizedError = (error) => {\",\n \" throw __mcpNormalizeHostError(error);\",\n \"};\",\n \"const __mcpToJsonValue = (value) => {\",\n \" if (typeof value === 'undefined') {\",\n \" return undefined;\",\n \" }\",\n \" const json = JSON.stringify(value);\",\n \" if (typeof json === 'undefined') {\",\n \" throw __mcpCreateTrustedError(\",\n \" 'serialization_error',\",\n \" 'Guest code returned a non-serializable value'\",\n \" );\",\n \" }\",\n \" return JSON.parse(json);\",\n \"};\",\n \"globalThis.console = {\",\n \" log: (...args) => __mcp_console_log(...args),\",\n \" info: (...args) => __mcp_console_info(...args),\",\n \" warn: (...args) => __mcp_console_warn(...args),\",\n \" error: (...args) => __mcp_console_error(...args),\",\n \"};\",\n ];\n\n for (const provider of providers) {\n lines.push(`globalThis.${provider.name} = {};`);\n\n for (const safeToolName of Object.keys(provider.tools)) {\n const hostReferenceName = `__mcp_tool_${provider.name}_${safeToolName}`;\n lines.push(\n `globalThis.${provider.name}.${safeToolName} = async (input) => {`,\n \" try {\",\n ` return await ${hostReferenceName}.applySyncPromise(undefined, [input], { arguments: { copy: true }, timeout: ${timeoutMs} });`,\n \" } catch (error) {\",\n \" __mcpRaiseNormalizedError(error);\",\n \" }\",\n \"};\",\n );\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction createExecutionSource(code: string): string {\n const executableSource = normalizeCode(code);\n\n return [\n `const __mcpUserFunction = (${executableSource});`,\n \"return (async () => {\",\n \" try {\",\n \" const value = await __mcpUserFunction();\",\n \" return { ok: true, value: __mcpToJsonValue(value) };\",\n \" } catch (error) {\",\n \" return { ok: false, error: __mcpNormalizeGuestError(error) };\",\n \" }\",\n \"})();\",\n ].join(\"\\n\");\n}\n\nfunction setConsoleBindings(context: IsolatedVmContext, logs: string[]): void {\n const jail = context.global;\n jail.setSync(\"__mcp_console_log\", (...args: unknown[]) => {\n logs.push(formatConsoleLine(args));\n });\n jail.setSync(\"__mcp_console_info\", (...args: unknown[]) => {\n logs.push(formatConsoleLine(args));\n });\n jail.setSync(\"__mcp_console_warn\", (...args: unknown[]) => {\n logs.push(formatConsoleLine(args));\n });\n jail.setSync(\"__mcp_console_error\", (...args: unknown[]) => {\n logs.push(formatConsoleLine(args));\n });\n}\n\nfunction setProviderBindings(\n ivm: IsolatedVmModule,\n context: IsolatedVmContext,\n providers: ResolvedToolProvider[],\n signal: AbortSignal,\n deadline: number,\n hostErrorPrefix: string,\n): void {\n const jail = context.global;\n\n for (const provider of providers) {\n for (const [safeToolName, descriptor] of Object.entries(provider.tools)) {\n const hostReferenceName = `__mcp_tool_${provider.name}_${safeToolName}`;\n\n jail.setSync(\n hostReferenceName,\n async (input: unknown) => {\n const executionContext = createExecutionContext(\n signal,\n provider.name,\n safeToolName,\n descriptor.originalName,\n );\n\n try {\n const normalizedInput =\n input === undefined\n ? undefined\n : toJsonValue(\n input,\n \"Guest code passed a non-serializable tool input\",\n );\n const pendingExecution = Promise.resolve(\n descriptor.execute(normalizedInput, executionContext),\n );\n\n pendingExecution.catch(() => {\n // The deadline path may settle first; keep late provider rejections from\n // surfacing as unhandled promise rejections after timeout/abort.\n });\n const result = await runWithDeadline(\n pendingExecution,\n deadline,\n signal,\n );\n\n return toTransferableValue(ivm, result);\n } catch (error) {\n const executeError = toExecuteError(error, deadline);\n throw new Error(\n `${hostErrorPrefix}${JSON.stringify(executeError)}`,\n {\n cause: error,\n },\n );\n }\n },\n { reference: true },\n );\n }\n }\n}\n\n/**\n * isolated-vm-backed executor for one-shot sandboxed JavaScript runs.\n */\nexport class IsolatedVmExecutor implements Executor {\n private readonly loadModule: () => Promise<IsolatedVmModule>;\n private readonly maxLogChars: number;\n private readonly maxLogLines: number;\n private readonly memoryLimitBytes: number;\n private readonly timeoutMs: number;\n\n /**\n * Creates an isolated-vm executor with one-shot runtime limits and host bridging configuration.\n */\n constructor(options: IsolatedVmExecutorOptions = {}) {\n this.loadModule = async () => {\n const loaded = options.loadModule\n ? await options.loadModule()\n : await loadDefaultModule();\n return loaded as IsolatedVmModule;\n };\n this.maxLogChars = options.maxLogChars ?? DEFAULT_MAX_LOG_CHARS;\n this.maxLogLines = options.maxLogLines ?? DEFAULT_MAX_LOG_LINES;\n this.memoryLimitBytes =\n options.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n }\n\n /**\n * Executes JavaScript against the provided tool namespaces in a fresh isolated-vm context.\n */\n async execute(\n code: string,\n providers: ResolvedToolProvider[],\n ): Promise<ExecuteResult> {\n const startedAt = Date.now();\n const deadline = startedAt + this.timeoutMs;\n const logs: string[] = [];\n const abortController = new AbortController();\n const hostErrorPrefix = `__MCP_CODE_EXEC_HOST_ERROR__${randomUUID()}:`;\n const nodeMajorVersion = Number.parseInt(\n process.versions.node.split(\".\")[0] ?? \"0\",\n 10,\n );\n\n if (nodeMajorVersion >= 20 && !hasRequiredNodeFlag()) {\n return {\n durationMs: Date.now() - startedAt,\n error: {\n code: \"internal_error\",\n message:\n \"isolated-vm requires Node to run with --no-node-snapshot on Node 20+\",\n },\n logs,\n ok: false,\n };\n }\n\n let catastrophicErrorMessage: string | undefined;\n let isolate: IsolatedVmIsolate | undefined;\n let context: IsolatedVmContext | undefined;\n\n try {\n const ivm = await this.loadModule();\n isolate = new ivm.Isolate({\n memoryLimit: toMemoryLimitMb(this.memoryLimitBytes),\n onCatastrophicError: (message) => {\n catastrophicErrorMessage = message;\n abortController.abort();\n },\n });\n context = await isolate.createContext();\n\n setConsoleBindings(context, logs);\n setProviderBindings(\n ivm,\n context,\n providers,\n abortController.signal,\n deadline,\n hostErrorPrefix,\n );\n await context.eval(\n createBootstrapSource(providers, hostErrorPrefix, this.timeoutMs),\n {\n timeout: this.timeoutMs,\n },\n );\n\n const execution = (await context.evalClosure(\n createExecutionSource(code),\n [],\n {\n timeout: this.timeoutMs,\n result: { copy: true, promise: true },\n },\n )) as GuestExecutionEnvelope;\n\n if (catastrophicErrorMessage) {\n return {\n durationMs: Date.now() - startedAt,\n error: {\n code: \"internal_error\",\n message: `isolated-vm catastrophic error: ${catastrophicErrorMessage}`,\n },\n logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),\n ok: false,\n };\n }\n\n if (!execution.ok) {\n return {\n durationMs: Date.now() - startedAt,\n error: toExecuteError(execution.error, deadline),\n logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),\n ok: false,\n };\n }\n\n return {\n durationMs: Date.now() - startedAt,\n logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),\n ok: true,\n result: execution.value,\n };\n } catch (error) {\n const executeError =\n catastrophicErrorMessage !== undefined\n ? {\n code: \"internal_error\" as const,\n message: `isolated-vm catastrophic error: ${catastrophicErrorMessage}`,\n }\n : toExecuteError(error, deadline);\n\n return {\n durationMs: Date.now() - startedAt,\n error: executeError,\n logs: truncateLogs(logs, this.maxLogLines, this.maxLogChars),\n ok: false,\n };\n } finally {\n abortController.abort();\n context?.release?.();\n isolate?.dispose();\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/isolatedVmExecutor.ts"],"sourcesContent":["import {\n createTimeoutExecuteResult,\n createToolCallDispatcher,\n extractProviderManifests,\n type ExecutionOptions,\n type ExecuteResult,\n type Executor,\n type ResolvedToolProvider,\n} from \"@mcploom/codexec\";\n\nimport { runIsolatedVmSession } from \"./runner/index\";\nimport type { IsolatedVmExecutorOptions } from \"./types\";\n\n/**\n * isolated-vm-backed executor for one-shot sandboxed JavaScript runs.\n */\nexport class IsolatedVmExecutor implements Executor {\n private readonly options: IsolatedVmExecutorOptions;\n\n /**\n * Creates an isolated-vm executor with one-shot runtime limits and host bridging configuration.\n */\n constructor(options: IsolatedVmExecutorOptions = {}) {\n this.options = options;\n }\n\n /**\n * Executes JavaScript against the provided tool namespaces in a fresh isolated-vm context.\n */\n async execute(\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n ): Promise<ExecuteResult> {\n if (options.signal?.aborted) {\n return createTimeoutExecuteResult();\n }\n\n const abortController = new AbortController();\n const onToolCall = createToolCallDispatcher(providers, abortController.signal);\n const onAbort = () => {\n abortController.abort();\n };\n\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n try {\n return await runIsolatedVmSession(\n {\n abortController,\n code,\n onToolCall,\n providers: extractProviderManifests(providers),\n },\n {\n ...this.options,\n ...options,\n },\n );\n } finally {\n options.signal?.removeEventListener(\"abort\", onAbort);\n abortController.abort();\n }\n }\n}\n"],"mappings":";;;;;;;AAgBA,IAAa,qBAAb,MAAoD;CAClD,AAAiB;;;;CAKjB,YAAY,UAAqC,EAAE,EAAE;AACnD,OAAK,UAAU;;;;;CAMjB,MAAM,QACJ,MACA,WACA,UAA4B,EAAE,EACN;AACxB,MAAI,QAAQ,QAAQ,QAClB,QAAO,4BAA4B;EAGrC,MAAM,kBAAkB,IAAI,iBAAiB;EAC7C,MAAM,aAAa,yBAAyB,WAAW,gBAAgB,OAAO;EAC9E,MAAM,gBAAgB;AACpB,mBAAgB,OAAO;;AAGzB,UAAQ,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,MAAM,CAAC;AAElE,MAAI;AACF,UAAO,MAAM,qBACX;IACE;IACA;IACA;IACA,WAAW,yBAAyB,UAAU;IAC/C,EACD;IACE,GAAG,KAAK;IACR,GAAG;IACJ,CACF;YACO;AACR,WAAQ,QAAQ,oBAAoB,SAAS,QAAQ;AACrD,mBAAgB,OAAO"}
@@ -0,0 +1,3 @@
1
+ const require_runner = require('../runner-cprbphYc.cjs');
2
+
3
+ exports.runIsolatedVmSession = require_runner.runIsolatedVmSession;
@@ -0,0 +1,100 @@
1
+ import { t as IsolatedVmExecutorOptions } from "../types-BmvPk-t5.cjs";
2
+
3
+ //#region ../codexec/src/types.d.ts
4
+
5
+ /**
6
+ * Stable error codes returned by executors and wrapped tool calls.
7
+ */
8
+ type ExecuteErrorCode = "timeout" | "memory_limit" | "validation_error" | "tool_error" | "runtime_error" | "serialization_error" | "internal_error";
9
+ /**
10
+ * Structured execution failure returned in {@link ExecuteResult}.
11
+ */
12
+ interface ExecuteError {
13
+ /** Machine-readable error category. */
14
+ code: ExecuteErrorCode;
15
+ /** Human-readable failure message. */
16
+ message: string;
17
+ }
18
+ /**
19
+ * Structured result returned by every executor invocation.
20
+ */
21
+ type ExecuteResult<T = unknown> = {
22
+ durationMs: number;
23
+ logs: string[];
24
+ ok: true;
25
+ result: T;
26
+ } | {
27
+ durationMs: number;
28
+ error: ExecuteError;
29
+ logs: string[];
30
+ ok: false;
31
+ };
32
+ //#endregion
33
+ //#region ../codexec/src/runner.d.ts
34
+ /**
35
+ * Transport-safe metadata for one exposed tool.
36
+ */
37
+ interface ProviderToolManifest {
38
+ description?: string;
39
+ originalName: string;
40
+ safeName: string;
41
+ }
42
+ /**
43
+ * Namespace manifest shared with runner implementations.
44
+ */
45
+ interface ProviderManifest {
46
+ name: string;
47
+ tools: Record<string, ProviderToolManifest>;
48
+ types: string;
49
+ }
50
+ /**
51
+ * Execution limits forwarded to runner implementations.
52
+ */
53
+ interface ExecutorRuntimeOptions {
54
+ maxLogChars?: number;
55
+ maxLogLines?: number;
56
+ memoryLimitBytes?: number;
57
+ timeoutMs?: number;
58
+ }
59
+ /**
60
+ * Tool invocation request emitted from a runner.
61
+ */
62
+ interface ToolCall {
63
+ input: unknown;
64
+ providerName: string;
65
+ safeToolName: string;
66
+ }
67
+ /**
68
+ * Trusted host response to a tool invocation request.
69
+ */
70
+ type ToolCallResult = {
71
+ ok: true;
72
+ result: unknown;
73
+ } | {
74
+ error: ExecuteError;
75
+ ok: false;
76
+ };
77
+ //#endregion
78
+ //#region src/runner/index.d.ts
79
+ /**
80
+ * Input required to run one isolated-vm-backed execution session.
81
+ */
82
+ interface IsolatedVmSessionRequest {
83
+ abortController?: AbortController;
84
+ code: string;
85
+ onStarted?: () => void;
86
+ onToolCall: (call: ToolCall) => Promise<ToolCallResult> | ToolCallResult;
87
+ providers: ProviderManifest[];
88
+ signal?: AbortSignal;
89
+ }
90
+ /**
91
+ * Options controlling one isolated-vm-backed execution session.
92
+ */
93
+ type IsolatedVmSessionOptions = IsolatedVmExecutorOptions & ExecutorRuntimeOptions;
94
+ /**
95
+ * Runs one isolated-vm-backed execution session using a runner-style tool callback.
96
+ */
97
+ declare function runIsolatedVmSession(request: IsolatedVmSessionRequest, options?: IsolatedVmSessionOptions): Promise<ExecuteResult>;
98
+ //#endregion
99
+ export { IsolatedVmSessionOptions, IsolatedVmSessionRequest, runIsolatedVmSession };
100
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../../codexec/src/types.ts","../../../codexec/src/runner.ts","../../src/runner/index.ts"],"sourcesContent":[],"mappings":";;;;ACcA;AASA;AASA;AAiBiB,KDlCL,gBAAA,GCkCa,SAAA,GAAA,cAAA,GAAA,kBAAA,GAAA,YAAA,GAAA,eAAA,GAAA,qBAAA,GAAA,gBAAA;AASzB;;;UD/BiB,YAAA;EE0DA;EACG,IAAA,EFzDZ,gBEyDY;EAGC;EAAqB,OAAA,EAAA,MAAA;;;;;AAEpB,KFtDV,aEsDU,CAAA,IAAA,OAAA,CAAA,GAAA;EAMV,UAAA,EAAA,MAAA;EAqXU,IAAA,EAAA,MAAA,EAAA;EACX,EAAA,EAAA,IAAA;EACA,MAAA,EF9aG,CE8aH;CACA,GAAA;EAAR,UAAA,EAAA,MAAA;EAAO,KAAA,EF3aG,YE2aH;;;;;;;;AF1cV;AAYiB,UCbA,oBAAA,CDeT;EAQI,WAAA,CAAA,EAAA,MAAa;;;;ACvBzB;AASA;AASA;AAiBiB,UA1BA,gBAAA,CA0BQ;EASb,IAAA,EAAA,MAAA;SAjCH,eAAe;;;AC4DxB;;;AAI0C,UDzDzB,sBAAA,CCyDyB;EAAR,WAAA,CAAA,EAAA,MAAA;EAA0B,WAAA,CAAA,EAAA,MAAA;EAC/C,gBAAA,CAAA,EAAA,MAAA;EACF,SAAA,CAAA,EAAA,MAAA;;;;;UD1CM,QAAA;;;;;;;;KASL,cAAA;;;;SAMC;;;;;;ADjDb;AAYA;AAUY,UEgDK,wBAAA,CFvCJ;oBEwCO;;;EDxEH,UAAA,EAAA,CAAA,IAAA,EC2EI,QD3EgB,EAAA,GC2EH,OD3EG,CC2EK,cD3EL,CAAA,GC2EuB,cD3EvB;EASpB,SAAA,ECmEJ,gBDnEoB,EAAA;EAShB,MAAA,CAAA,EC2DN,WD3DM;AAiBjB;AASA;;;KCuCY,wBAAA,GAA2B,4BACrC;AAbF;;;AAI0C,iBA6XpB,oBAAA,CA7XoB,OAAA,EA8X/B,wBA9X+B,EAAA,OAAA,CAAA,EA+X/B,wBA/X+B,CAAA,EAgYvC,OAhYuC,CAgY/B,aAhY+B,CAAA"}
@@ -0,0 +1,100 @@
1
+ import { t as IsolatedVmExecutorOptions } from "../types-CkMlkJam.js";
2
+
3
+ //#region ../codexec/src/types.d.ts
4
+
5
+ /**
6
+ * Stable error codes returned by executors and wrapped tool calls.
7
+ */
8
+ type ExecuteErrorCode = "timeout" | "memory_limit" | "validation_error" | "tool_error" | "runtime_error" | "serialization_error" | "internal_error";
9
+ /**
10
+ * Structured execution failure returned in {@link ExecuteResult}.
11
+ */
12
+ interface ExecuteError {
13
+ /** Machine-readable error category. */
14
+ code: ExecuteErrorCode;
15
+ /** Human-readable failure message. */
16
+ message: string;
17
+ }
18
+ /**
19
+ * Structured result returned by every executor invocation.
20
+ */
21
+ type ExecuteResult<T = unknown> = {
22
+ durationMs: number;
23
+ logs: string[];
24
+ ok: true;
25
+ result: T;
26
+ } | {
27
+ durationMs: number;
28
+ error: ExecuteError;
29
+ logs: string[];
30
+ ok: false;
31
+ };
32
+ //#endregion
33
+ //#region ../codexec/src/runner.d.ts
34
+ /**
35
+ * Transport-safe metadata for one exposed tool.
36
+ */
37
+ interface ProviderToolManifest {
38
+ description?: string;
39
+ originalName: string;
40
+ safeName: string;
41
+ }
42
+ /**
43
+ * Namespace manifest shared with runner implementations.
44
+ */
45
+ interface ProviderManifest {
46
+ name: string;
47
+ tools: Record<string, ProviderToolManifest>;
48
+ types: string;
49
+ }
50
+ /**
51
+ * Execution limits forwarded to runner implementations.
52
+ */
53
+ interface ExecutorRuntimeOptions {
54
+ maxLogChars?: number;
55
+ maxLogLines?: number;
56
+ memoryLimitBytes?: number;
57
+ timeoutMs?: number;
58
+ }
59
+ /**
60
+ * Tool invocation request emitted from a runner.
61
+ */
62
+ interface ToolCall {
63
+ input: unknown;
64
+ providerName: string;
65
+ safeToolName: string;
66
+ }
67
+ /**
68
+ * Trusted host response to a tool invocation request.
69
+ */
70
+ type ToolCallResult = {
71
+ ok: true;
72
+ result: unknown;
73
+ } | {
74
+ error: ExecuteError;
75
+ ok: false;
76
+ };
77
+ //#endregion
78
+ //#region src/runner/index.d.ts
79
+ /**
80
+ * Input required to run one isolated-vm-backed execution session.
81
+ */
82
+ interface IsolatedVmSessionRequest {
83
+ abortController?: AbortController;
84
+ code: string;
85
+ onStarted?: () => void;
86
+ onToolCall: (call: ToolCall) => Promise<ToolCallResult> | ToolCallResult;
87
+ providers: ProviderManifest[];
88
+ signal?: AbortSignal;
89
+ }
90
+ /**
91
+ * Options controlling one isolated-vm-backed execution session.
92
+ */
93
+ type IsolatedVmSessionOptions = IsolatedVmExecutorOptions & ExecutorRuntimeOptions;
94
+ /**
95
+ * Runs one isolated-vm-backed execution session using a runner-style tool callback.
96
+ */
97
+ declare function runIsolatedVmSession(request: IsolatedVmSessionRequest, options?: IsolatedVmSessionOptions): Promise<ExecuteResult>;
98
+ //#endregion
99
+ export { IsolatedVmSessionOptions, IsolatedVmSessionRequest, runIsolatedVmSession };
100
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../codexec/src/types.ts","../../../codexec/src/runner.ts","../../src/runner/index.ts"],"sourcesContent":[],"mappings":";;;;ACcA;AASA;AASA;AAiBiB,KDlCL,gBAAA,GCkCa,SAAA,GAAA,cAAA,GAAA,kBAAA,GAAA,YAAA,GAAA,eAAA,GAAA,qBAAA,GAAA,gBAAA;AASzB;;;UD/BiB,YAAA;EE0DA;EACG,IAAA,EFzDZ,gBEyDY;EAGC;EAAqB,OAAA,EAAA,MAAA;;;;;AAEpB,KFtDV,aEsDU,CAAA,IAAA,OAAA,CAAA,GAAA;EAMV,UAAA,EAAA,MAAA;EAqXU,IAAA,EAAA,MAAA,EAAA;EACX,EAAA,EAAA,IAAA;EACA,MAAA,EF9aG,CE8aH;CACA,GAAA;EAAR,UAAA,EAAA,MAAA;EAAO,KAAA,EF3aG,YE2aH;;;;;;;;AF1cV;AAYiB,UCbA,oBAAA,CDeT;EAQI,WAAA,CAAA,EAAA,MAAa;;;;ACvBzB;AASA;AASA;AAiBiB,UA1BA,gBAAA,CA0BQ;EASb,IAAA,EAAA,MAAA;SAjCH,eAAe;;;AC4DxB;;;AAI0C,UDzDzB,sBAAA,CCyDyB;EAAR,WAAA,CAAA,EAAA,MAAA;EAA0B,WAAA,CAAA,EAAA,MAAA;EAC/C,gBAAA,CAAA,EAAA,MAAA;EACF,SAAA,CAAA,EAAA,MAAA;;;;;UD1CM,QAAA;;;;;;;;KASL,cAAA;;;;SAMC;;;;;;ADjDb;AAYA;AAUY,UEgDK,wBAAA,CFvCJ;oBEwCO;;;EDxEH,UAAA,EAAA,CAAA,IAAA,EC2EI,QD3EgB,EAAA,GC2EH,OD3EG,CC2EK,cD3EL,CAAA,GC2EuB,cD3EvB;EASpB,SAAA,ECmEJ,gBDnEoB,EAAA;EAShB,MAAA,CAAA,EC2DN,WD3DM;AAiBjB;AASA;;;KCuCY,wBAAA,GAA2B,4BACrC;AAbF;;;AAI0C,iBA6XpB,oBAAA,CA7XoB,OAAA,EA8X/B,wBA9X+B,EAAA,OAAA,CAAA,EA+X/B,wBA/X+B,CAAA,EAgYvC,OAhYuC,CAgY/B,aAhY+B,CAAA"}
@@ -0,0 +1,3 @@
1
+ import { t as runIsolatedVmSession } from "../runner-Dbq2FDWK.js";
2
+
3
+ export { runIsolatedVmSession };