isol8 0.4.3 → 0.5.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/README.md CHANGED
@@ -104,6 +104,8 @@ isol8 run script.py --host http://server:3000 --key my-api-key
104
104
  | `--out <file>` | Write stdout to file | — |
105
105
  | `--no-stream` | Disable real-time output streaming | `false` |
106
106
  | `--persistent` | Keep container alive between runs | `false` |
107
+ | `--persist` | Keep container after execution for inspection/debugging | `false` |
108
+ | `--debug` | Enable debug logging for internal engine operations | `false` |
107
109
  | `--timeout <ms>` | Execution timeout in milliseconds | `30000` |
108
110
  | `--memory <limit>` | Memory limit (e.g. `512m`, `1g`) | `512m` |
109
111
  | `--cpu <limit>` | CPU limit as fraction (e.g. `0.5`, `2.0`) | `1.0` |
package/dist/cli.js CHANGED
@@ -54798,7 +54798,8 @@ function mergeConfig(defaults, overrides) {
54798
54798
  dependencies: {
54799
54799
  ...defaults.dependencies,
54800
54800
  ...overrides.dependencies
54801
- }
54801
+ },
54802
+ debug: overrides.debug ?? defaults.debug
54802
54803
  };
54803
54804
  }
54804
54805
  var DEFAULT_CONFIG;
@@ -54821,7 +54822,8 @@ var init_config = __esm(() => {
54821
54822
  autoPrune: true,
54822
54823
  maxContainerAgeMs: 3600000
54823
54824
  },
54824
- dependencies: {}
54825
+ dependencies: {},
54826
+ debug: false
54825
54827
  };
54826
54828
  });
54827
54829
 
@@ -54978,6 +54980,37 @@ var init_runtime = __esm(() => {
54978
54980
  RuntimeRegistry.register(DenoAdapter);
54979
54981
  });
54980
54982
 
54983
+ // src/utils/logger.ts
54984
+ var exports_logger = {};
54985
+ __export(exports_logger, {
54986
+ logger: () => logger
54987
+ });
54988
+
54989
+ class Logger {
54990
+ debugMode = false;
54991
+ setDebug(enabled) {
54992
+ this.debugMode = enabled;
54993
+ }
54994
+ debug(...args) {
54995
+ if (this.debugMode) {
54996
+ console.log("[DEBUG]", ...args);
54997
+ }
54998
+ }
54999
+ info(...args) {
55000
+ console.log(...args);
55001
+ }
55002
+ warn(...args) {
55003
+ console.warn("[WARN]", ...args);
55004
+ }
55005
+ error(...args) {
55006
+ console.error("[ERROR]", ...args);
55007
+ }
55008
+ }
55009
+ var logger;
55010
+ var init_logger = __esm(() => {
55011
+ logger = new Logger;
55012
+ });
55013
+
54981
55014
  // src/engine/concurrency.ts
54982
55015
  class Semaphore {
54983
55016
  max;
@@ -55086,26 +55119,32 @@ class ContainerPool {
55086
55119
  ...this.createOptions,
55087
55120
  Image: image
55088
55121
  });
55122
+ logger.debug(`[Pool] Container ${container.id} created for image: ${image}`);
55089
55123
  await container.start();
55124
+ logger.debug(`[Pool] Container ${container.id} started`);
55090
55125
  return container;
55091
55126
  }
55092
55127
  replenish(image) {
55093
55128
  if (this.replenishing.has(image)) {
55129
+ logger.debug(`[Pool] Replenishment for ${image} already in progress`);
55094
55130
  return;
55095
55131
  }
55096
55132
  this.replenishing.add(image);
55133
+ logger.debug(`[Pool] Starting background replenishment for image: ${image}`);
55097
55134
  const promise = this.createContainer(image).then((container) => {
55098
55135
  const pool = this.pools.get(image) ?? [];
55099
55136
  if (pool.length < this.poolSize) {
55100
55137
  pool.push({ container, createdAt: Date.now() });
55101
55138
  this.pools.set(image, pool);
55139
+ logger.debug(`[Pool] Replenished container ${container.id} added to pool for ${image}. Pool size: ${pool.length}`);
55102
55140
  } else {
55141
+ logger.debug(`[Pool] Replenished container ${container.id} not needed (pool for ${image} is full), destroying`);
55103
55142
  container.remove({ force: true }).catch((err) => {
55104
- console.error(`[Pool] Error destroying unneeded replenished container ${container.id}:`, err);
55143
+ logger.error(`[Pool] Error destroying unneeded replenished container ${container.id}:`, err);
55105
55144
  });
55106
55145
  }
55107
55146
  }).catch((err) => {
55108
- console.error(`[Pool] Error during replenishment for ${image}:`, err);
55147
+ logger.error(`[Pool] Error during replenishment for ${image}:`, err);
55109
55148
  }).finally(() => {
55110
55149
  this.replenishing.delete(image);
55111
55150
  this.pendingReplenishments.delete(promise);
@@ -55113,6 +55152,9 @@ class ContainerPool {
55113
55152
  this.pendingReplenishments.add(promise);
55114
55153
  }
55115
55154
  }
55155
+ var init_pool = __esm(() => {
55156
+ init_logger();
55157
+ });
55116
55158
 
55117
55159
  // src/engine/utils.ts
55118
55160
  var exports_utils = {};
@@ -55309,7 +55351,7 @@ function getInstallCommand(runtime, packages) {
55309
55351
  }
55310
55352
  async function installPackages(container, runtime, packages) {
55311
55353
  const cmd = getInstallCommand(runtime, packages);
55312
- console.error(`[DEBUG] Installing packages: ${JSON.stringify(cmd)}`);
55354
+ logger.debug(`Installing packages: ${JSON.stringify(cmd)}`);
55313
55355
  const env2 = [
55314
55356
  "PATH=/sandbox/.local/bin:/sandbox/.npm-global/bin:/sandbox/.bun-global/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"
55315
55357
  ];
@@ -55373,6 +55415,7 @@ class DockerIsol8 {
55373
55415
  semaphore;
55374
55416
  sandboxSize;
55375
55417
  tmpSize;
55418
+ persist;
55376
55419
  container = null;
55377
55420
  persistentRuntime = null;
55378
55421
  pool = null;
@@ -55392,6 +55435,10 @@ class DockerIsol8 {
55392
55435
  this.semaphore = new Semaphore(maxConcurrent);
55393
55436
  this.sandboxSize = options.sandboxSize ?? "512m";
55394
55437
  this.tmpSize = options.tmpSize ?? "256m";
55438
+ this.persist = options.persist ?? false;
55439
+ if (options.debug) {
55440
+ logger.setDebug(true);
55441
+ }
55395
55442
  }
55396
55443
  async start() {}
55397
55444
  async stop() {
@@ -55499,9 +55546,13 @@ class DockerIsol8 {
55499
55546
  const execStream = await exec.start({ Tty: false });
55500
55547
  yield* this.streamExecOutput(execStream, exec, container, timeoutMs);
55501
55548
  } finally {
55502
- try {
55503
- await container.remove({ force: true });
55504
- } catch {}
55549
+ if (this.persist) {
55550
+ logger.debug(`[Persist] Leaving container running for inspection: ${container.id}`);
55551
+ } else {
55552
+ try {
55553
+ await container.remove({ force: true });
55554
+ } catch {}
55555
+ }
55505
55556
  }
55506
55557
  } finally {
55507
55558
  this.semaphore.release();
@@ -55589,7 +55640,11 @@ class DockerIsol8 {
55589
55640
  ...req.outputPaths ? { files: await this.retrieveFiles(container, req.outputPaths) } : {}
55590
55641
  };
55591
55642
  } finally {
55592
- await this.pool.release(container, image);
55643
+ if (this.persist) {
55644
+ logger.debug(`[Persist] Leaving container running for inspection: ${container.id}`);
55645
+ } else {
55646
+ await this.pool.release(container, image);
55647
+ }
55593
55648
  }
55594
55649
  }
55595
55650
  async executePersistent(req) {
@@ -55889,6 +55944,8 @@ class DockerIsol8 {
55889
55944
  var import_dockerode, SANDBOX_WORKDIR = "/sandbox", MAX_OUTPUT_BYTES, PROXY_PORT = 8118, PROXY_STARTUP_TIMEOUT_MS = 5000, PROXY_POLL_INTERVAL_MS = 100;
55890
55945
  var init_docker = __esm(() => {
55891
55946
  init_runtime();
55947
+ init_logger();
55948
+ init_pool();
55892
55949
  import_dockerode = __toESM(require_docker(), 1);
55893
55950
  MAX_OUTPUT_BYTES = 1024 * 1024;
55894
55951
  });
@@ -61231,7 +61288,7 @@ program2.command("setup").description("Check Docker and build isol8 images").opt
61231
61288
  console.log(`
61232
61289
  [DONE] Setup complete!`);
61233
61290
  });
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) => {
61291
+ 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").option("--debug", "Enable debug logging").option("--persist", "Keep container running after execution for inspection").action(async (file, opts) => {
61235
61292
  const { code, runtime, engineOptions, engine, stdinData, fileExtension } = await resolveRunInput(file, opts);
61236
61293
  const cleanup = async () => {
61237
61294
  await engine.stop();
@@ -61492,8 +61549,14 @@ async function resolveRunInput(file, opts) {
61492
61549
  ...opts.pidsLimit ? { pidsLimit: Number.parseInt(opts.pidsLimit, 10) } : {},
61493
61550
  ...opts.writable ? { readonlyRootFs: false } : {},
61494
61551
  ...opts.maxOutput ? { maxOutputSize: Number.parseInt(opts.maxOutput, 10) } : {},
61495
- ...opts.tmpSize ? { tmpSize: opts.tmpSize } : {}
61552
+ ...opts.tmpSize ? { tmpSize: opts.tmpSize } : {},
61553
+ debug: opts.debug ?? config.debug,
61554
+ persist: opts.persist ?? false
61496
61555
  };
61556
+ if (engineOptions.debug) {
61557
+ const { logger: logger2 } = await Promise.resolve().then(() => (init_logger(), exports_logger));
61558
+ logger2.setDebug(true);
61559
+ }
61497
61560
  let fileExtension;
61498
61561
  if (file) {
61499
61562
  const ext = file.substring(file.lastIndexOf("."));
@@ -61534,4 +61597,4 @@ if (!process.argv.slice(2).length) {
61534
61597
  }
61535
61598
  program2.parse();
61536
61599
 
61537
- //# debugId=E455279A70D3A2C764756E2164756E21
61600
+ //# debugId=9AD6B80BEBAE034064756E2164756E21