isol8 0.4.1 → 0.4.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 CHANGED
@@ -11,8 +11,9 @@ Secure code execution engine for AI agents. Run untrusted Python, Node.js, Bun,
11
11
  - **Security first** — read-only rootfs, `no-new-privileges`, PID/memory/CPU limits
12
12
  - **Network control** — `none` (default), `host`, or `filtered` (HTTP/HTTPS proxy with regex whitelist/blacklist)
13
13
  - **File I/O** — upload files into and download files from sandboxes
14
- - **Runtime packages** — install pip/npm/bun packages on-the-fly via `installPackages`
15
- - **Secret masking** — environment variables are scrubbed from output
14
+ - **Runtime packages** — install pip/npm/bun packages on-the-fly (`--install`)
15
+ - **Modern Node.js** — defaults to ESM (`.mjs`), supports CommonJS (`.cjs`)
16
+ - **Secret masking** — environment variables are scrubbed from output
16
17
  - **Output truncation** — prevents runaway stdout (default 1MB cap)
17
18
  - **Remote mode** — run an HTTP server and execute from anywhere
18
19
  - **Embeddable** — use as a TypeScript library in your own project
package/dist/cli.js CHANGED
@@ -54831,9 +54831,12 @@ var init_adapter = __esm(() => {
54831
54831
  adapters = new Map;
54832
54832
  extensionMap = new Map;
54833
54833
  RuntimeRegistry = {
54834
- register(adapter) {
54834
+ register(adapter, aliases = []) {
54835
54835
  adapters.set(adapter.name, adapter);
54836
54836
  extensionMap.set(adapter.getFileExtension(), adapter);
54837
+ for (const ext of aliases) {
54838
+ extensionMap.set(ext, adapter);
54839
+ }
54837
54840
  },
54838
54841
  get(name) {
54839
54842
  const adapter = adapters.get(name);
@@ -54931,7 +54934,7 @@ var init_node = __esm(() => {
54931
54934
  return ["node", "-e", code];
54932
54935
  },
54933
54936
  getFileExtension() {
54934
- return ".js";
54937
+ return ".mjs";
54935
54938
  }
54936
54939
  };
54937
54940
  });
@@ -54969,7 +54972,7 @@ var init_runtime = __esm(() => {
54969
54972
  init_node();
54970
54973
  init_python();
54971
54974
  RuntimeRegistry.register(PythonAdapter);
54972
- RuntimeRegistry.register(NodeAdapter);
54975
+ RuntimeRegistry.register(NodeAdapter, [".js", ".cjs"]);
54973
54976
  RuntimeRegistry.register(BunAdapter);
54974
54977
  RuntimeRegistry.register(bashAdapter);
54975
54978
  RuntimeRegistry.register(DenoAdapter);
@@ -55464,7 +55467,8 @@ class DockerIsol8 {
55464
55467
  if (this.network === "filtered") {
55465
55468
  await startProxy(container, this.networkFilter);
55466
55469
  }
55467
- const filePath = `${SANDBOX_WORKDIR}/main${adapter.getFileExtension()}`;
55470
+ const ext = req.fileExtension ?? adapter.getFileExtension();
55471
+ const filePath = `${SANDBOX_WORKDIR}/main${ext}`;
55468
55472
  await writeFileViaExec(container, filePath, req.code);
55469
55473
  if (req.installPackages?.length) {
55470
55474
  await installPackages(container, req.runtime, req.installPackages);
@@ -55538,7 +55542,8 @@ class DockerIsol8 {
55538
55542
  if (this.network === "filtered") {
55539
55543
  await startProxy(container, this.networkFilter);
55540
55544
  }
55541
- const filePath = `${SANDBOX_WORKDIR}/main${adapter.getFileExtension()}`;
55545
+ const ext = req.fileExtension ?? adapter.getFileExtension();
55546
+ const filePath = `${SANDBOX_WORKDIR}/main${ext}`;
55542
55547
  await writeFileViaExec(container, filePath, req.code);
55543
55548
  if (req.installPackages?.length) {
55544
55549
  await installPackages(container, req.runtime, req.installPackages);
@@ -55595,7 +55600,8 @@ class DockerIsol8 {
55595
55600
  } else if (this.persistentRuntime?.name !== adapter.name) {
55596
55601
  throw new Error(`Cannot switch runtime from "${this.persistentRuntime?.name}" to "${adapter.name}". Each persistent container supports a single runtime. Create a new Isol8 instance for a different runtime.`);
55597
55602
  }
55598
- const filePath = `${SANDBOX_WORKDIR}/exec_${Date.now()}${adapter.getFileExtension()}`;
55603
+ const ext = req.fileExtension ?? adapter.getFileExtension();
55604
+ const filePath = `${SANDBOX_WORKDIR}/exec_${Date.now()}${ext}`;
55599
55605
  if (this.readonlyRootFs) {
55600
55606
  await writeFileViaExec(this.container, filePath, req.code);
55601
55607
  } else {
@@ -61226,7 +61232,7 @@ program2.command("setup").description("Check Docker and build isol8 images").opt
61226
61232
  [DONE] Setup complete!`);
61227
61233
  });
61228
61234
  program2.command("run").description("Execute code in isol8").argument("[file]", "Script file to execute").option("-e, --eval <code>", "Execute inline code string").option("-r, --runtime <name>", "Force runtime (python, node, bun, deno, bash)").option("--net <mode>", "Network mode: none, host, filtered", "none").option("--allow <regex>", "Whitelist regex for filtered mode (repeatable)", collect, []).option("--deny <regex>", "Blacklist regex for filtered mode (repeatable)", collect, []).option("--out <file>", "Write output to file").option("--persistent", "Use persistent container").option("--timeout <ms>", "Execution timeout in milliseconds").option("--memory <limit>", "Memory limit (e.g. 512m, 1g)").option("--cpu <limit>", "CPU limit as fraction (e.g. 0.5, 2.0)").option("--image <name>", "Override Docker image").option("--pids-limit <n>", "Maximum number of processes").option("--writable", "Disable read-only root filesystem").option("--max-output <bytes>", "Maximum output size in bytes").option("--secret <KEY=VALUE>", "Secret env var (repeatable, values masked)", collect, []).option("--sandbox-size <size>", "Sandbox tmpfs size (e.g. 128m)").option("--tmp-size <size>", "Tmp tmpfs size (e.g. 256m, 512m)").option("--stdin <data>", "Data to pipe to stdin").option("--install <package>", "Install package for runtime (repeatable)", collect, []).option("--host <url>", "Execute on remote server").option("--key <key>", "API key for remote server").option("--no-stream", "Disable real-time output streaming").action(async (file, opts) => {
61229
- const { code, runtime, engineOptions, engine, stdinData } = await resolveRunInput(file, opts);
61235
+ const { code, runtime, engineOptions, engine, stdinData, fileExtension } = await resolveRunInput(file, opts);
61230
61236
  const cleanup = async () => {
61231
61237
  await engine.stop();
61232
61238
  process.exit(0);
@@ -61234,6 +61240,7 @@ program2.command("run").description("Execute code in isol8").argument("[file]",
61234
61240
  process.on("SIGINT", cleanup);
61235
61241
  process.on("SIGTERM", cleanup);
61236
61242
  const spinner = ora("Starting execution...").start();
61243
+ let exitCode = 0;
61237
61244
  try {
61238
61245
  await engine.start();
61239
61246
  spinner.text = "Running code...";
@@ -61242,7 +61249,8 @@ program2.command("run").description("Execute code in isol8").argument("[file]",
61242
61249
  runtime,
61243
61250
  timeoutMs: engineOptions.timeoutMs,
61244
61251
  ...stdinData ? { stdin: stdinData } : {},
61245
- ...opts.install.length > 0 ? { installPackages: opts.install } : {}
61252
+ ...opts.install.length > 0 ? { installPackages: opts.install } : {},
61253
+ fileExtension
61246
61254
  };
61247
61255
  if (opts.stream !== false) {
61248
61256
  spinner.stop();
@@ -61254,11 +61262,11 @@ program2.command("run").description("Execute code in isol8").argument("[file]",
61254
61262
  process.stderr.write(event.data);
61255
61263
  } else if (event.type === "exit") {
61256
61264
  if (event.data !== "0") {
61257
- process.exit(Number.parseInt(event.data, 10));
61265
+ exitCode = Number.parseInt(event.data, 10);
61258
61266
  }
61259
61267
  } else if (event.type === "error") {
61260
61268
  console.error(`[ERR] ${event.data}`);
61261
- process.exit(1);
61269
+ exitCode = 1;
61262
61270
  }
61263
61271
  }
61264
61272
  } else {
@@ -61278,16 +61286,19 @@ program2.command("run").description("Execute code in isol8").argument("[file]",
61278
61286
  console.error(`[INFO] Output written to ${opts.out}`);
61279
61287
  }
61280
61288
  if (result.exitCode !== 0) {
61281
- process.exit(result.exitCode);
61289
+ exitCode = result.exitCode;
61282
61290
  }
61283
61291
  }
61284
61292
  } catch (err) {
61285
61293
  spinner.stop();
61286
61294
  throw err;
61287
61295
  } finally {
61288
- await engine.stop();
61296
+ const cleanupPromise = engine.stop();
61297
+ const timeoutPromise = new Promise((resolve3) => setTimeout(resolve3, 5000));
61298
+ await Promise.race([cleanupPromise, timeoutPromise]);
61289
61299
  process.off("SIGINT", cleanup);
61290
61300
  process.off("SIGTERM", cleanup);
61301
+ process.exit(exitCode);
61291
61302
  }
61292
61303
  });
61293
61304
  program2.command("serve").description("Start the isol8 remote server").option("-p, --port <port>", "Port to listen on", "3000").option("-k, --key <key>", "API key for authentication").action(async (opts) => {
@@ -61481,9 +61492,15 @@ async function resolveRunInput(file, opts) {
61481
61492
  ...opts.pidsLimit ? { pidsLimit: Number.parseInt(opts.pidsLimit, 10) } : {},
61482
61493
  ...opts.writable ? { readonlyRootFs: false } : {},
61483
61494
  ...opts.maxOutput ? { maxOutputSize: Number.parseInt(opts.maxOutput, 10) } : {},
61484
- ...opts.sandboxSize ? { sandboxSize: opts.sandboxSize } : {},
61485
61495
  ...opts.tmpSize ? { tmpSize: opts.tmpSize } : {}
61486
61496
  };
61497
+ let fileExtension;
61498
+ if (file) {
61499
+ const ext = file.substring(file.lastIndexOf("."));
61500
+ if (ext) {
61501
+ fileExtension = ext;
61502
+ }
61503
+ }
61487
61504
  const secrets = {};
61488
61505
  for (const s of opts.secret ?? []) {
61489
61506
  const idx = s.indexOf("=");
@@ -61506,7 +61523,7 @@ async function resolveRunInput(file, opts) {
61506
61523
  } else {
61507
61524
  engine = new DockerIsol8(engineOptions, config.maxConcurrent);
61508
61525
  }
61509
- return { code, runtime, engineOptions, engine, stdinData };
61526
+ return { code, runtime, engineOptions, engine, stdinData, fileExtension };
61510
61527
  }
61511
61528
  function collect(value, previous) {
61512
61529
  return previous.concat([value]);
@@ -61517,4 +61534,4 @@ if (!process.argv.slice(2).length) {
61517
61534
  }
61518
61535
  program2.parse();
61519
61536
 
61520
- //# debugId=AF05A942A56C65F664756E2164756E21
61537
+ //# debugId=E455279A70D3A2C764756E2164756E21