pulse-sandbox 0.0.1-alpha.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.
@@ -0,0 +1,56 @@
1
+ import z from 'zod';
2
+
3
+ type JsExecutionErrorCode = 'TIMEOUT' | 'OOM' | 'RUNTIME_ERROR' | 'POLICY_BLOCKED' | 'INTERNAL';
4
+ interface JsExecutionError {
5
+ code: JsExecutionErrorCode;
6
+ message: string;
7
+ }
8
+ interface JsExecutionRequest {
9
+ code: string;
10
+ input?: unknown;
11
+ timeoutMs?: number;
12
+ }
13
+ interface JsExecutionResult {
14
+ ok: boolean;
15
+ result?: unknown;
16
+ stdout: string;
17
+ stderr: string;
18
+ error?: JsExecutionError;
19
+ durationMs: number;
20
+ outputTruncated: boolean;
21
+ }
22
+ interface JsExecutor {
23
+ execute(request: JsExecutionRequest): Promise<JsExecutionResult>;
24
+ }
25
+ interface JsExecutorOptions {
26
+ timeoutMs?: number;
27
+ memoryLimitMb?: number;
28
+ maxOutputChars?: number;
29
+ maxCodeLength?: number;
30
+ }
31
+ interface RunJsToolInput {
32
+ code: string;
33
+ input?: unknown;
34
+ timeoutMs?: number;
35
+ }
36
+ type RunJsToolOutput = JsExecutionResult;
37
+ interface RunJsToolOptions {
38
+ executor: JsExecutor;
39
+ name?: string;
40
+ description?: string;
41
+ }
42
+
43
+ declare function createJsExecutor(options?: JsExecutorOptions): JsExecutor;
44
+
45
+ declare function createRunJsTool(options: RunJsToolOptions): {
46
+ name: string;
47
+ description: string;
48
+ inputSchema: z.ZodObject<{
49
+ code: z.ZodString;
50
+ input: z.ZodOptional<z.ZodAny>;
51
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
52
+ }, z.core.$strip>;
53
+ execute: (input: RunJsToolInput) => Promise<RunJsToolOutput>;
54
+ };
55
+
56
+ export { type JsExecutionError, type JsExecutionErrorCode, type JsExecutionRequest, type JsExecutionResult, type JsExecutor, type JsExecutorOptions, type RunJsToolInput, type RunJsToolOptions, type RunJsToolOutput, createJsExecutor, createRunJsTool };
package/dist/index.js ADDED
@@ -0,0 +1,313 @@
1
+ // src/executor.ts
2
+ import { fork } from "child_process";
3
+ import { existsSync } from "fs";
4
+ import { createRequire } from "module";
5
+ import path from "path";
6
+ import { fileURLToPath } from "url";
7
+ var DEFAULT_TIMEOUT_MS = 2e3;
8
+ var DEFAULT_MEMORY_LIMIT_MB = 64;
9
+ var DEFAULT_MAX_OUTPUT_CHARS = 2e4;
10
+ var DEFAULT_MAX_CODE_LENGTH = 2e4;
11
+ function toErrorMessage(error) {
12
+ if (error instanceof Error) {
13
+ return error.message;
14
+ }
15
+ return String(error);
16
+ }
17
+ function appendWithLimit(buffer, chunk, maxChars) {
18
+ const merged = buffer + chunk;
19
+ if (merged.length <= maxChars) {
20
+ return { value: merged, truncated: false };
21
+ }
22
+ return {
23
+ value: merged.slice(0, maxChars),
24
+ truncated: true
25
+ };
26
+ }
27
+ function clampText(value, maxChars) {
28
+ if (value.length <= maxChars) {
29
+ return { value, truncated: false };
30
+ }
31
+ return {
32
+ value: value.slice(0, maxChars),
33
+ truncated: true
34
+ };
35
+ }
36
+ function mergeText(first, second) {
37
+ if (!first) {
38
+ return second;
39
+ }
40
+ if (!second) {
41
+ return first;
42
+ }
43
+ return `${first}
44
+ ${second}`;
45
+ }
46
+ function inferExitErrorCode(signal, stderr) {
47
+ if (signal === "SIGABRT" || /heap out of memory/i.test(stderr)) {
48
+ return "OOM";
49
+ }
50
+ return "INTERNAL";
51
+ }
52
+ function createErrorResult(startedAt, stdout, stderr, errorCode, errorMessage, outputTruncated) {
53
+ return {
54
+ ok: false,
55
+ stdout,
56
+ stderr,
57
+ durationMs: Date.now() - startedAt,
58
+ outputTruncated,
59
+ error: {
60
+ code: errorCode,
61
+ message: errorMessage
62
+ }
63
+ };
64
+ }
65
+ function resolveRunnerPath() {
66
+ const requireForResolve = createRequire(import.meta.url);
67
+ const localDir = path.dirname(fileURLToPath(import.meta.url));
68
+ const localCandidates = [path.join(localDir, "runner.js"), path.join(localDir, "runner.cjs")];
69
+ for (const candidate of localCandidates) {
70
+ if (existsSync(candidate)) {
71
+ return candidate;
72
+ }
73
+ }
74
+ try {
75
+ const packageEntryPath = requireForResolve.resolve("pulse-sandbox");
76
+ const packageDir = path.dirname(packageEntryPath);
77
+ const packageCandidates = [path.join(packageDir, "runner.js"), path.join(packageDir, "runner.cjs")];
78
+ for (const candidate of packageCandidates) {
79
+ if (existsSync(candidate)) {
80
+ return candidate;
81
+ }
82
+ }
83
+ } catch {
84
+ }
85
+ return localCandidates[0];
86
+ }
87
+ function createJsExecutor(options = {}) {
88
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
89
+ const memoryLimitMb = options.memoryLimitMb ?? DEFAULT_MEMORY_LIMIT_MB;
90
+ const maxOutputChars = options.maxOutputChars ?? DEFAULT_MAX_OUTPUT_CHARS;
91
+ const maxCodeLength = options.maxCodeLength ?? DEFAULT_MAX_CODE_LENGTH;
92
+ return {
93
+ async execute(request) {
94
+ const startedAt = Date.now();
95
+ const effectiveTimeoutMs = request.timeoutMs ?? timeoutMs;
96
+ if (!Number.isInteger(effectiveTimeoutMs) || effectiveTimeoutMs <= 0) {
97
+ return createErrorResult(
98
+ startedAt,
99
+ "",
100
+ "",
101
+ "POLICY_BLOCKED",
102
+ "timeoutMs must be a positive integer.",
103
+ false
104
+ );
105
+ }
106
+ if (!request.code || request.code.trim().length === 0) {
107
+ return createErrorResult(
108
+ startedAt,
109
+ "",
110
+ "",
111
+ "POLICY_BLOCKED",
112
+ "code must be a non-empty string.",
113
+ false
114
+ );
115
+ }
116
+ if (request.code.length > maxCodeLength) {
117
+ return createErrorResult(
118
+ startedAt,
119
+ "",
120
+ "",
121
+ "POLICY_BLOCKED",
122
+ `code exceeds maxCodeLength (${maxCodeLength}).`,
123
+ false
124
+ );
125
+ }
126
+ const runnerPath = resolveRunnerPath();
127
+ return new Promise((resolve) => {
128
+ let child;
129
+ let finished = false;
130
+ let timedOut = false;
131
+ let stdoutBuffer = "";
132
+ let stderrBuffer = "";
133
+ let streamTruncated = false;
134
+ const finish = (result) => {
135
+ if (finished) {
136
+ return;
137
+ }
138
+ finished = true;
139
+ resolve(result);
140
+ };
141
+ try {
142
+ child = fork(runnerPath, {
143
+ stdio: ["ignore", "pipe", "pipe", "ipc"],
144
+ serialization: "advanced",
145
+ execArgv: [`--max-old-space-size=${memoryLimitMb}`]
146
+ });
147
+ } catch (error) {
148
+ finish(
149
+ createErrorResult(
150
+ startedAt,
151
+ "",
152
+ "",
153
+ "INTERNAL",
154
+ `Failed to start sandbox process: ${toErrorMessage(error)}`,
155
+ false
156
+ )
157
+ );
158
+ return;
159
+ }
160
+ const timeoutHandle = setTimeout(() => {
161
+ if (finished) {
162
+ return;
163
+ }
164
+ timedOut = true;
165
+ child?.kill("SIGKILL");
166
+ }, effectiveTimeoutMs);
167
+ const collectStreamChunk = (source, chunk) => {
168
+ const currentBuffer = source === "stdout" ? stdoutBuffer : stderrBuffer;
169
+ const next = appendWithLimit(currentBuffer, chunk, maxOutputChars);
170
+ if (next.truncated) {
171
+ streamTruncated = true;
172
+ }
173
+ if (source === "stdout") {
174
+ stdoutBuffer = next.value;
175
+ return;
176
+ }
177
+ stderrBuffer = next.value;
178
+ };
179
+ child.stdout?.on("data", (chunk) => {
180
+ collectStreamChunk("stdout", String(chunk));
181
+ });
182
+ child.stderr?.on("data", (chunk) => {
183
+ collectStreamChunk("stderr", String(chunk));
184
+ });
185
+ child.once("error", (error) => {
186
+ clearTimeout(timeoutHandle);
187
+ finish(
188
+ createErrorResult(
189
+ startedAt,
190
+ stdoutBuffer,
191
+ stderrBuffer,
192
+ "INTERNAL",
193
+ `Sandbox process error: ${toErrorMessage(error)}`,
194
+ streamTruncated
195
+ )
196
+ );
197
+ });
198
+ child.once("message", (message) => {
199
+ clearTimeout(timeoutHandle);
200
+ const mergedStdout = mergeText(message.stdout, stdoutBuffer);
201
+ const mergedStderr = mergeText(message.stderr, stderrBuffer);
202
+ const clampedStdout = clampText(mergedStdout, maxOutputChars);
203
+ const clampedStderr = clampText(mergedStderr, maxOutputChars);
204
+ const outputTruncated = message.outputTruncated || streamTruncated || clampedStdout.truncated || clampedStderr.truncated;
205
+ if (message.type === "success") {
206
+ finish({
207
+ ok: true,
208
+ result: message.result,
209
+ stdout: clampedStdout.value,
210
+ stderr: clampedStderr.value,
211
+ durationMs: Date.now() - startedAt,
212
+ outputTruncated
213
+ });
214
+ if (child.connected) {
215
+ child.disconnect();
216
+ }
217
+ return;
218
+ }
219
+ finish(
220
+ createErrorResult(
221
+ startedAt,
222
+ clampedStdout.value,
223
+ clampedStderr.value,
224
+ message.errorCode,
225
+ message.errorMessage,
226
+ outputTruncated
227
+ )
228
+ );
229
+ if (child.connected) {
230
+ child.disconnect();
231
+ }
232
+ });
233
+ child.once("exit", (_code, signal) => {
234
+ clearTimeout(timeoutHandle);
235
+ if (finished) {
236
+ return;
237
+ }
238
+ if (timedOut) {
239
+ finish(
240
+ createErrorResult(
241
+ startedAt,
242
+ stdoutBuffer,
243
+ stderrBuffer,
244
+ "TIMEOUT",
245
+ `Execution timed out after ${effectiveTimeoutMs}ms.`,
246
+ streamTruncated
247
+ )
248
+ );
249
+ return;
250
+ }
251
+ const errorCode = inferExitErrorCode(signal, stderrBuffer);
252
+ finish(
253
+ createErrorResult(
254
+ startedAt,
255
+ stdoutBuffer,
256
+ stderrBuffer,
257
+ errorCode,
258
+ "Sandbox process exited unexpectedly.",
259
+ streamTruncated
260
+ )
261
+ );
262
+ });
263
+ const payload = {
264
+ code: request.code,
265
+ input: request.input,
266
+ maxOutputChars
267
+ };
268
+ try {
269
+ child.send(payload);
270
+ } catch (error) {
271
+ clearTimeout(timeoutHandle);
272
+ child.kill("SIGKILL");
273
+ finish(
274
+ createErrorResult(
275
+ startedAt,
276
+ stdoutBuffer,
277
+ stderrBuffer,
278
+ "INTERNAL",
279
+ `Failed to send payload to sandbox: ${toErrorMessage(error)}`,
280
+ streamTruncated
281
+ )
282
+ );
283
+ }
284
+ });
285
+ }
286
+ };
287
+ }
288
+
289
+ // src/tool.ts
290
+ import z from "zod";
291
+ var DEFAULT_TOOL_NAME = "run_js";
292
+ var DEFAULT_TOOL_DESCRIPTION = "Execute JavaScript in an isolated sandbox process. Returns result, stdout, stderr, and execution metadata.";
293
+ function createRunJsTool(options) {
294
+ const name = options.name ?? DEFAULT_TOOL_NAME;
295
+ const description = options.description ?? DEFAULT_TOOL_DESCRIPTION;
296
+ return {
297
+ name,
298
+ description,
299
+ inputSchema: z.object({
300
+ code: z.string().describe("JavaScript source code to execute in sandbox."),
301
+ input: z.any().optional().describe("Optional input object exposed as global `input` in sandbox."),
302
+ timeoutMs: z.number().int().positive().optional().describe("Optional timeout in milliseconds. Defaults to executor timeout.")
303
+ }),
304
+ execute: async (input) => {
305
+ return options.executor.execute(input);
306
+ }
307
+ };
308
+ }
309
+ export {
310
+ createJsExecutor,
311
+ createRunJsTool
312
+ };
313
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/executor.ts","../src/tool.ts"],"sourcesContent":["import { fork, type ChildProcess } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport type {\n JsExecutionErrorCode,\n JsExecutionRequest,\n JsExecutionResult,\n JsExecutor,\n JsExecutorOptions\n} from './types.js';\n\ninterface RunnerRequest {\n code: string;\n input: unknown;\n maxOutputChars: number;\n}\n\ninterface RunnerSuccessMessage {\n type: 'success';\n result: unknown;\n stdout: string;\n stderr: string;\n outputTruncated: boolean;\n}\n\ninterface RunnerErrorMessage {\n type: 'error';\n errorCode: 'RUNTIME_ERROR' | 'INTERNAL';\n errorMessage: string;\n stdout: string;\n stderr: string;\n outputTruncated: boolean;\n}\n\ntype RunnerMessage = RunnerSuccessMessage | RunnerErrorMessage;\n\nconst DEFAULT_TIMEOUT_MS = 2_000;\nconst DEFAULT_MEMORY_LIMIT_MB = 64;\nconst DEFAULT_MAX_OUTPUT_CHARS = 20_000;\nconst DEFAULT_MAX_CODE_LENGTH = 20_000;\n\nfunction toErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n return String(error);\n}\n\nfunction appendWithLimit(buffer: string, chunk: string, maxChars: number): { value: string; truncated: boolean } {\n const merged = buffer + chunk;\n\n if (merged.length <= maxChars) {\n return { value: merged, truncated: false };\n }\n\n return {\n value: merged.slice(0, maxChars),\n truncated: true\n };\n}\n\nfunction clampText(value: string, maxChars: number): { value: string; truncated: boolean } {\n if (value.length <= maxChars) {\n return { value, truncated: false };\n }\n\n return {\n value: value.slice(0, maxChars),\n truncated: true\n };\n}\n\nfunction mergeText(first: string, second: string): string {\n if (!first) {\n return second;\n }\n\n if (!second) {\n return first;\n }\n\n return `${first}\\n${second}`;\n}\n\nfunction inferExitErrorCode(signal: NodeJS.Signals | null, stderr: string): JsExecutionErrorCode {\n if (signal === 'SIGABRT' || /heap out of memory/i.test(stderr)) {\n return 'OOM';\n }\n\n return 'INTERNAL';\n}\n\nfunction createErrorResult(\n startedAt: number,\n stdout: string,\n stderr: string,\n errorCode: JsExecutionErrorCode,\n errorMessage: string,\n outputTruncated: boolean\n): JsExecutionResult {\n return {\n ok: false,\n stdout,\n stderr,\n durationMs: Date.now() - startedAt,\n outputTruncated,\n error: {\n code: errorCode,\n message: errorMessage\n }\n };\n}\n\nfunction resolveRunnerPath(): string {\n const requireForResolve = createRequire(import.meta.url);\n const localDir = path.dirname(fileURLToPath(import.meta.url));\n const localCandidates = [path.join(localDir, 'runner.js'), path.join(localDir, 'runner.cjs')];\n\n for (const candidate of localCandidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n try {\n const packageEntryPath = requireForResolve.resolve('pulse-sandbox');\n const packageDir = path.dirname(packageEntryPath);\n const packageCandidates = [path.join(packageDir, 'runner.js'), path.join(packageDir, 'runner.cjs')];\n\n for (const candidate of packageCandidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n } catch {\n // Ignore and fall through to final fallback.\n }\n\n return localCandidates[0];\n}\n\nexport function createJsExecutor(options: JsExecutorOptions = {}): JsExecutor {\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const memoryLimitMb = options.memoryLimitMb ?? DEFAULT_MEMORY_LIMIT_MB;\n const maxOutputChars = options.maxOutputChars ?? DEFAULT_MAX_OUTPUT_CHARS;\n const maxCodeLength = options.maxCodeLength ?? DEFAULT_MAX_CODE_LENGTH;\n\n return {\n async execute(request: JsExecutionRequest): Promise<JsExecutionResult> {\n const startedAt = Date.now();\n const effectiveTimeoutMs = request.timeoutMs ?? timeoutMs;\n\n if (!Number.isInteger(effectiveTimeoutMs) || effectiveTimeoutMs <= 0) {\n return createErrorResult(\n startedAt,\n '',\n '',\n 'POLICY_BLOCKED',\n 'timeoutMs must be a positive integer.',\n false\n );\n }\n\n if (!request.code || request.code.trim().length === 0) {\n return createErrorResult(\n startedAt,\n '',\n '',\n 'POLICY_BLOCKED',\n 'code must be a non-empty string.',\n false\n );\n }\n\n if (request.code.length > maxCodeLength) {\n return createErrorResult(\n startedAt,\n '',\n '',\n 'POLICY_BLOCKED',\n `code exceeds maxCodeLength (${maxCodeLength}).`,\n false\n );\n }\n\n const runnerPath = resolveRunnerPath();\n\n return new Promise<JsExecutionResult>((resolve) => {\n let child: ChildProcess | undefined;\n let finished = false;\n let timedOut = false;\n let stdoutBuffer = '';\n let stderrBuffer = '';\n let streamTruncated = false;\n\n const finish = (result: JsExecutionResult): void => {\n if (finished) {\n return;\n }\n\n finished = true;\n resolve(result);\n };\n\n try {\n child = fork(runnerPath, {\n stdio: ['ignore', 'pipe', 'pipe', 'ipc'],\n serialization: 'advanced',\n execArgv: [`--max-old-space-size=${memoryLimitMb}`]\n });\n } catch (error) {\n finish(\n createErrorResult(\n startedAt,\n '',\n '',\n 'INTERNAL',\n `Failed to start sandbox process: ${toErrorMessage(error)}`,\n false\n )\n );\n return;\n }\n\n const timeoutHandle = setTimeout(() => {\n if (finished) {\n return;\n }\n\n timedOut = true;\n child?.kill('SIGKILL');\n }, effectiveTimeoutMs);\n\n const collectStreamChunk = (source: 'stdout' | 'stderr', chunk: string): void => {\n const currentBuffer = source === 'stdout' ? stdoutBuffer : stderrBuffer;\n const next = appendWithLimit(currentBuffer, chunk, maxOutputChars);\n\n if (next.truncated) {\n streamTruncated = true;\n }\n\n if (source === 'stdout') {\n stdoutBuffer = next.value;\n return;\n }\n\n stderrBuffer = next.value;\n };\n\n child.stdout?.on('data', (chunk: Buffer | string) => {\n collectStreamChunk('stdout', String(chunk));\n });\n\n child.stderr?.on('data', (chunk: Buffer | string) => {\n collectStreamChunk('stderr', String(chunk));\n });\n\n child.once('error', (error) => {\n clearTimeout(timeoutHandle);\n finish(\n createErrorResult(\n startedAt,\n stdoutBuffer,\n stderrBuffer,\n 'INTERNAL',\n `Sandbox process error: ${toErrorMessage(error)}`,\n streamTruncated\n )\n );\n });\n\n child.once('message', (message: RunnerMessage) => {\n clearTimeout(timeoutHandle);\n\n const mergedStdout = mergeText(message.stdout, stdoutBuffer);\n const mergedStderr = mergeText(message.stderr, stderrBuffer);\n\n const clampedStdout = clampText(mergedStdout, maxOutputChars);\n const clampedStderr = clampText(mergedStderr, maxOutputChars);\n const outputTruncated =\n message.outputTruncated ||\n streamTruncated ||\n clampedStdout.truncated ||\n clampedStderr.truncated;\n\n if (message.type === 'success') {\n finish({\n ok: true,\n result: message.result,\n stdout: clampedStdout.value,\n stderr: clampedStderr.value,\n durationMs: Date.now() - startedAt,\n outputTruncated\n });\n if (child.connected) {\n child.disconnect();\n }\n return;\n }\n\n finish(\n createErrorResult(\n startedAt,\n clampedStdout.value,\n clampedStderr.value,\n message.errorCode,\n message.errorMessage,\n outputTruncated\n )\n );\n if (child.connected) {\n child.disconnect();\n }\n });\n\n child.once('exit', (_code, signal) => {\n clearTimeout(timeoutHandle);\n\n if (finished) {\n return;\n }\n\n if (timedOut) {\n finish(\n createErrorResult(\n startedAt,\n stdoutBuffer,\n stderrBuffer,\n 'TIMEOUT',\n `Execution timed out after ${effectiveTimeoutMs}ms.`,\n streamTruncated\n )\n );\n return;\n }\n\n const errorCode = inferExitErrorCode(signal, stderrBuffer);\n finish(\n createErrorResult(\n startedAt,\n stdoutBuffer,\n stderrBuffer,\n errorCode,\n 'Sandbox process exited unexpectedly.',\n streamTruncated\n )\n );\n });\n\n const payload: RunnerRequest = {\n code: request.code,\n input: request.input,\n maxOutputChars\n };\n\n try {\n child.send(payload);\n } catch (error) {\n clearTimeout(timeoutHandle);\n child.kill('SIGKILL');\n finish(\n createErrorResult(\n startedAt,\n stdoutBuffer,\n stderrBuffer,\n 'INTERNAL',\n `Failed to send payload to sandbox: ${toErrorMessage(error)}`,\n streamTruncated\n )\n );\n }\n });\n }\n };\n}\n","import z from 'zod';\n\nimport type { RunJsToolInput, RunJsToolOptions, RunJsToolOutput } from './types.js';\n\nconst DEFAULT_TOOL_NAME = 'run_js';\nconst DEFAULT_TOOL_DESCRIPTION =\n 'Execute JavaScript in an isolated sandbox process. Returns result, stdout, stderr, and execution metadata.';\n\nexport function createRunJsTool(options: RunJsToolOptions) {\n const name = options.name ?? DEFAULT_TOOL_NAME;\n const description = options.description ?? DEFAULT_TOOL_DESCRIPTION;\n\n return {\n name,\n description,\n inputSchema: z.object({\n code: z.string().describe('JavaScript source code to execute in sandbox.'),\n input: z.any().optional().describe('Optional input object exposed as global `input` in sandbox.'),\n timeoutMs: z\n .number()\n .int()\n .positive()\n .optional()\n .describe('Optional timeout in milliseconds. Defaults to executor timeout.')\n }),\n execute: async (input: RunJsToolInput): Promise<RunJsToolOutput> => {\n return options.executor.execute(input);\n }\n };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/runner.js ADDED
@@ -0,0 +1,188 @@
1
+ // src/runner.ts
2
+ import vm from "vm";
3
+ import { inspect } from "util";
4
+ function toErrorMessage(error) {
5
+ if (error instanceof Error) {
6
+ return error.stack ?? error.message;
7
+ }
8
+ return String(error);
9
+ }
10
+ function appendWithLimit(buffer, chunk, maxChars) {
11
+ const merged = buffer + chunk;
12
+ if (merged.length <= maxChars) {
13
+ return { value: merged, truncated: false };
14
+ }
15
+ return {
16
+ value: merged.slice(0, maxChars),
17
+ truncated: true
18
+ };
19
+ }
20
+ function formatLogArgs(args) {
21
+ return args.map((arg) => {
22
+ if (typeof arg === "string") {
23
+ return arg;
24
+ }
25
+ return inspect(arg, {
26
+ depth: 4,
27
+ breakLength: 120,
28
+ compact: true,
29
+ maxArrayLength: 100
30
+ });
31
+ }).join(" ");
32
+ }
33
+ function createConsoleProxy(append) {
34
+ return {
35
+ log: (...args) => append("stdout", `${formatLogArgs(args)}
36
+ `),
37
+ info: (...args) => append("stdout", `${formatLogArgs(args)}
38
+ `),
39
+ warn: (...args) => append("stderr", `${formatLogArgs(args)}
40
+ `),
41
+ error: (...args) => append("stderr", `${formatLogArgs(args)}
42
+ `),
43
+ debug: (...args) => append("stdout", `${formatLogArgs(args)}
44
+ `),
45
+ trace: (...args) => append("stderr", `${formatLogArgs(args)}
46
+ `),
47
+ dir: (item) => append("stdout", `${inspect(item)}
48
+ `),
49
+ dirxml: (item) => append("stdout", `${inspect(item)}
50
+ `),
51
+ assert: (condition, ...args) => {
52
+ if (!condition) {
53
+ append("stderr", `${formatLogArgs(args.length ? args : ["Assertion failed"])}
54
+ `);
55
+ }
56
+ },
57
+ clear: () => {
58
+ },
59
+ count: () => {
60
+ },
61
+ countReset: () => {
62
+ },
63
+ group: (...args) => append("stdout", `${formatLogArgs(args)}
64
+ `),
65
+ groupCollapsed: (...args) => append("stdout", `${formatLogArgs(args)}
66
+ `),
67
+ groupEnd: () => {
68
+ },
69
+ table: (tabularData) => append("stdout", `${inspect(tabularData, { depth: 3 })}
70
+ `),
71
+ time: () => {
72
+ },
73
+ timeLog: (...args) => append("stdout", `${formatLogArgs(args)}
74
+ `),
75
+ timeEnd: (...args) => append("stdout", `${formatLogArgs(args)}
76
+ `),
77
+ timeStamp: () => {
78
+ },
79
+ profile: () => {
80
+ },
81
+ profileEnd: () => {
82
+ }
83
+ };
84
+ }
85
+ function buildSandbox(input, consoleProxy) {
86
+ const sandbox = {
87
+ input,
88
+ console: consoleProxy,
89
+ fetch: void 0,
90
+ WebSocket: void 0,
91
+ EventSource: void 0,
92
+ require: void 0,
93
+ process: void 0,
94
+ module: void 0,
95
+ exports: void 0,
96
+ Buffer: void 0,
97
+ setTimeout,
98
+ clearTimeout,
99
+ setInterval,
100
+ clearInterval
101
+ };
102
+ sandbox.globalThis = sandbox;
103
+ sandbox.global = sandbox;
104
+ return vm.createContext(sandbox, {
105
+ codeGeneration: {
106
+ strings: false,
107
+ wasm: false
108
+ }
109
+ });
110
+ }
111
+ async function executeInSandbox(payload) {
112
+ let stdout = "";
113
+ let stderr = "";
114
+ let outputTruncated = false;
115
+ const append = (stream, text) => {
116
+ if (stream === "stdout") {
117
+ const next2 = appendWithLimit(stdout, text, payload.maxOutputChars);
118
+ stdout = next2.value;
119
+ if (next2.truncated) {
120
+ outputTruncated = true;
121
+ }
122
+ return;
123
+ }
124
+ const next = appendWithLimit(stderr, text, payload.maxOutputChars);
125
+ stderr = next.value;
126
+ if (next.truncated) {
127
+ outputTruncated = true;
128
+ }
129
+ };
130
+ try {
131
+ const consoleProxy = createConsoleProxy(append);
132
+ const context = buildSandbox(payload.input, consoleProxy);
133
+ const wrappedCode = `'use strict';
134
+ (async () => {
135
+ ${payload.code}
136
+ })()`;
137
+ const script = new vm.Script(wrappedCode, { filename: "pulse-sandbox-user-code.js" });
138
+ const result = await script.runInContext(context);
139
+ return {
140
+ type: "success",
141
+ result,
142
+ stdout,
143
+ stderr,
144
+ outputTruncated
145
+ };
146
+ } catch (error) {
147
+ append("stderr", `${toErrorMessage(error)}
148
+ `);
149
+ return {
150
+ type: "error",
151
+ errorCode: "RUNTIME_ERROR",
152
+ errorMessage: toErrorMessage(error),
153
+ stdout,
154
+ stderr,
155
+ outputTruncated
156
+ };
157
+ }
158
+ }
159
+ function sendAndExit(message, exitCode) {
160
+ if (!process.send) {
161
+ process.exit(exitCode);
162
+ return;
163
+ }
164
+ process.send(message, (error) => {
165
+ if (error) {
166
+ process.exit(1);
167
+ return;
168
+ }
169
+ process.exit(exitCode);
170
+ });
171
+ }
172
+ process.once("message", async (payload) => {
173
+ try {
174
+ const result = await executeInSandbox(payload);
175
+ sendAndExit(result, 0);
176
+ } catch (error) {
177
+ const fallback = {
178
+ type: "error",
179
+ errorCode: "INTERNAL",
180
+ errorMessage: toErrorMessage(error),
181
+ stdout: "",
182
+ stderr: toErrorMessage(error),
183
+ outputTruncated: false
184
+ };
185
+ sendAndExit(fallback, 1);
186
+ }
187
+ });
188
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runner.ts"],"sourcesContent":["import vm from 'vm';\nimport { inspect } from 'util';\n\ninterface RunnerRequest {\n code: string;\n input: unknown;\n maxOutputChars: number;\n}\n\ninterface RunnerSuccessMessage {\n type: 'success';\n result: unknown;\n stdout: string;\n stderr: string;\n outputTruncated: boolean;\n}\n\ninterface RunnerErrorMessage {\n type: 'error';\n errorCode: 'RUNTIME_ERROR' | 'INTERNAL';\n errorMessage: string;\n stdout: string;\n stderr: string;\n outputTruncated: boolean;\n}\n\ntype RunnerMessage = RunnerSuccessMessage | RunnerErrorMessage;\n\nfunction toErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.stack ?? error.message;\n }\n\n return String(error);\n}\n\nfunction appendWithLimit(buffer: string, chunk: string, maxChars: number): { value: string; truncated: boolean } {\n const merged = buffer + chunk;\n\n if (merged.length <= maxChars) {\n return { value: merged, truncated: false };\n }\n\n return {\n value: merged.slice(0, maxChars),\n truncated: true\n };\n}\n\nfunction formatLogArgs(args: unknown[]): string {\n return args\n .map((arg) => {\n if (typeof arg === 'string') {\n return arg;\n }\n\n return inspect(arg, {\n depth: 4,\n breakLength: 120,\n compact: true,\n maxArrayLength: 100\n });\n })\n .join(' ');\n}\n\nfunction createConsoleProxy(\n append: (stream: 'stdout' | 'stderr', text: string) => void\n): Console {\n return {\n log: (...args: unknown[]) => append('stdout', `${formatLogArgs(args)}\\n`),\n info: (...args: unknown[]) => append('stdout', `${formatLogArgs(args)}\\n`),\n warn: (...args: unknown[]) => append('stderr', `${formatLogArgs(args)}\\n`),\n error: (...args: unknown[]) => append('stderr', `${formatLogArgs(args)}\\n`),\n debug: (...args: unknown[]) => append('stdout', `${formatLogArgs(args)}\\n`),\n trace: (...args: unknown[]) => append('stderr', `${formatLogArgs(args)}\\n`),\n dir: (item: unknown) => append('stdout', `${inspect(item)}\\n`),\n dirxml: (item: unknown) => append('stdout', `${inspect(item)}\\n`),\n assert: (condition: unknown, ...args: unknown[]) => {\n if (!condition) {\n append('stderr', `${formatLogArgs(args.length ? args : ['Assertion failed'])}\\n`);\n }\n },\n clear: () => {},\n count: () => {},\n countReset: () => {},\n group: (...args: unknown[]) => append('stdout', `${formatLogArgs(args)}\\n`),\n groupCollapsed: (...args: unknown[]) => append('stdout', `${formatLogArgs(args)}\\n`),\n groupEnd: () => {},\n table: (tabularData: unknown) => append('stdout', `${inspect(tabularData, { depth: 3 })}\\n`),\n time: () => {},\n timeLog: (...args: unknown[]) => append('stdout', `${formatLogArgs(args)}\\n`),\n timeEnd: (...args: unknown[]) => append('stdout', `${formatLogArgs(args)}\\n`),\n timeStamp: () => {},\n profile: () => {},\n profileEnd: () => {}\n } as unknown as Console;\n}\n\nfunction buildSandbox(input: unknown, consoleProxy: Console): vm.Context {\n const sandbox: Record<string, unknown> = {\n input,\n console: consoleProxy,\n fetch: undefined,\n WebSocket: undefined,\n EventSource: undefined,\n require: undefined,\n process: undefined,\n module: undefined,\n exports: undefined,\n Buffer: undefined,\n setTimeout,\n clearTimeout,\n setInterval,\n clearInterval\n };\n\n sandbox.globalThis = sandbox;\n sandbox.global = sandbox;\n\n return vm.createContext(sandbox, {\n codeGeneration: {\n strings: false,\n wasm: false\n }\n });\n}\n\nasync function executeInSandbox(payload: RunnerRequest): Promise<RunnerMessage> {\n let stdout = '';\n let stderr = '';\n let outputTruncated = false;\n\n const append = (stream: 'stdout' | 'stderr', text: string): void => {\n if (stream === 'stdout') {\n const next = appendWithLimit(stdout, text, payload.maxOutputChars);\n stdout = next.value;\n if (next.truncated) {\n outputTruncated = true;\n }\n return;\n }\n\n const next = appendWithLimit(stderr, text, payload.maxOutputChars);\n stderr = next.value;\n if (next.truncated) {\n outputTruncated = true;\n }\n };\n\n try {\n const consoleProxy = createConsoleProxy(append);\n const context = buildSandbox(payload.input, consoleProxy);\n const wrappedCode = `'use strict';\\n(async () => {\\n${payload.code}\\n})()`;\n const script = new vm.Script(wrappedCode, { filename: 'pulse-sandbox-user-code.js' });\n const result = await script.runInContext(context);\n\n return {\n type: 'success',\n result,\n stdout,\n stderr,\n outputTruncated\n };\n } catch (error) {\n append('stderr', `${toErrorMessage(error)}\\n`);\n\n return {\n type: 'error',\n errorCode: 'RUNTIME_ERROR',\n errorMessage: toErrorMessage(error),\n stdout,\n stderr,\n outputTruncated\n };\n }\n}\n\nfunction sendAndExit(message: RunnerMessage, exitCode: number): void {\n if (!process.send) {\n process.exit(exitCode);\n return;\n }\n\n process.send(message, (error) => {\n if (error) {\n process.exit(1);\n return;\n }\n\n process.exit(exitCode);\n });\n}\n\nprocess.once('message', async (payload: RunnerRequest) => {\n try {\n const result = await executeInSandbox(payload);\n sendAndExit(result, 0);\n } catch (error) {\n const fallback: RunnerErrorMessage = {\n type: 'error',\n errorCode: 'INTERNAL',\n errorMessage: toErrorMessage(error),\n stdout: '',\n stderr: toErrorMessage(error),\n outputTruncated: false\n };\n\n sendAndExit(fallback, 1);\n }\n});\n"],"mappings":"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","names":["next"]}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "pulse-sandbox",
3
+ "version": "0.0.1-alpha.0",
4
+ "description": "Sandboxed JavaScript runtime and engine tool adapter for Pulse Coder",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "scripts": {
18
+ "build": "tsup",
19
+ "dev": "tsup --watch",
20
+ "test": "vitest",
21
+ "typecheck": "tsc --noEmit"
22
+ },
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "dependencies": {
27
+ "zod": "^4.3.6"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^25.0.10",
31
+ "tsup": "^8.0.0",
32
+ "typescript": "^5.0.0",
33
+ "vitest": "^1.0.0"
34
+ }
35
+ }