isol8 0.4.2 → 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/dist/index.js CHANGED
@@ -146,7 +146,8 @@ var DEFAULT_CONFIG = {
146
146
  autoPrune: true,
147
147
  maxContainerAgeMs: 3600000
148
148
  },
149
- dependencies: {}
149
+ dependencies: {},
150
+ debug: false
150
151
  };
151
152
  function loadConfig(cwd) {
152
153
  const searchPaths = [
@@ -180,7 +181,8 @@ function mergeConfig(defaults, overrides) {
180
181
  dependencies: {
181
182
  ...defaults.dependencies,
182
183
  ...overrides.dependencies
183
- }
184
+ },
185
+ debug: overrides.debug ?? defaults.debug
184
186
  };
185
187
  }
186
188
  // src/engine/docker.ts
@@ -192,9 +194,12 @@ import Docker from "dockerode";
192
194
  var adapters = new Map;
193
195
  var extensionMap = new Map;
194
196
  var RuntimeRegistry = {
195
- register(adapter) {
197
+ register(adapter, aliases = []) {
196
198
  adapters.set(adapter.name, adapter);
197
199
  extensionMap.set(adapter.getFileExtension(), adapter);
200
+ for (const ext of aliases) {
201
+ extensionMap.set(ext, adapter);
202
+ }
198
203
  },
199
204
  get(name) {
200
205
  const adapter = adapters.get(name);
@@ -280,7 +285,7 @@ var NodeAdapter = {
280
285
  return ["node", "-e", code];
281
286
  },
282
287
  getFileExtension() {
283
- return ".js";
288
+ return ".mjs";
284
289
  }
285
290
  };
286
291
 
@@ -301,11 +306,34 @@ var PythonAdapter = {
301
306
 
302
307
  // src/runtime/index.ts
303
308
  RuntimeRegistry.register(PythonAdapter);
304
- RuntimeRegistry.register(NodeAdapter);
309
+ RuntimeRegistry.register(NodeAdapter, [".js", ".cjs"]);
305
310
  RuntimeRegistry.register(BunAdapter);
306
311
  RuntimeRegistry.register(bashAdapter);
307
312
  RuntimeRegistry.register(DenoAdapter);
308
313
 
314
+ // src/utils/logger.ts
315
+ class Logger {
316
+ debugMode = false;
317
+ setDebug(enabled) {
318
+ this.debugMode = enabled;
319
+ }
320
+ debug(...args) {
321
+ if (this.debugMode) {
322
+ console.log("[DEBUG]", ...args);
323
+ }
324
+ }
325
+ info(...args) {
326
+ console.log(...args);
327
+ }
328
+ warn(...args) {
329
+ console.warn("[WARN]", ...args);
330
+ }
331
+ error(...args) {
332
+ console.error("[ERROR]", ...args);
333
+ }
334
+ }
335
+ var logger = new Logger;
336
+
309
337
  // src/engine/concurrency.ts
310
338
  class Semaphore {
311
339
  max;
@@ -414,26 +442,32 @@ class ContainerPool {
414
442
  ...this.createOptions,
415
443
  Image: image
416
444
  });
445
+ logger.debug(`[Pool] Container ${container.id} created for image: ${image}`);
417
446
  await container.start();
447
+ logger.debug(`[Pool] Container ${container.id} started`);
418
448
  return container;
419
449
  }
420
450
  replenish(image) {
421
451
  if (this.replenishing.has(image)) {
452
+ logger.debug(`[Pool] Replenishment for ${image} already in progress`);
422
453
  return;
423
454
  }
424
455
  this.replenishing.add(image);
456
+ logger.debug(`[Pool] Starting background replenishment for image: ${image}`);
425
457
  const promise = this.createContainer(image).then((container) => {
426
458
  const pool = this.pools.get(image) ?? [];
427
459
  if (pool.length < this.poolSize) {
428
460
  pool.push({ container, createdAt: Date.now() });
429
461
  this.pools.set(image, pool);
462
+ logger.debug(`[Pool] Replenished container ${container.id} added to pool for ${image}. Pool size: ${pool.length}`);
430
463
  } else {
464
+ logger.debug(`[Pool] Replenished container ${container.id} not needed (pool for ${image} is full), destroying`);
431
465
  container.remove({ force: true }).catch((err) => {
432
- console.error(`[Pool] Error destroying unneeded replenished container ${container.id}:`, err);
466
+ logger.error(`[Pool] Error destroying unneeded replenished container ${container.id}:`, err);
433
467
  });
434
468
  }
435
469
  }).catch((err) => {
436
- console.error(`[Pool] Error during replenishment for ${image}:`, err);
470
+ logger.error(`[Pool] Error during replenishment for ${image}:`, err);
437
471
  }).finally(() => {
438
472
  this.replenishing.delete(image);
439
473
  this.pendingReplenishments.delete(promise);
@@ -632,7 +666,7 @@ function getInstallCommand(runtime, packages) {
632
666
  }
633
667
  async function installPackages(container, runtime, packages) {
634
668
  const cmd = getInstallCommand(runtime, packages);
635
- console.error(`[DEBUG] Installing packages: ${JSON.stringify(cmd)}`);
669
+ logger.debug(`Installing packages: ${JSON.stringify(cmd)}`);
636
670
  const env = [
637
671
  "PATH=/sandbox/.local/bin:/sandbox/.npm-global/bin:/sandbox/.bun-global/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"
638
672
  ];
@@ -696,6 +730,7 @@ class DockerIsol8 {
696
730
  semaphore;
697
731
  sandboxSize;
698
732
  tmpSize;
733
+ persist;
699
734
  container = null;
700
735
  persistentRuntime = null;
701
736
  pool = null;
@@ -715,6 +750,10 @@ class DockerIsol8 {
715
750
  this.semaphore = new Semaphore(maxConcurrent);
716
751
  this.sandboxSize = options.sandboxSize ?? "512m";
717
752
  this.tmpSize = options.tmpSize ?? "256m";
753
+ this.persist = options.persist ?? false;
754
+ if (options.debug) {
755
+ logger.setDebug(true);
756
+ }
718
757
  }
719
758
  async start() {}
720
759
  async stop() {
@@ -790,7 +829,8 @@ class DockerIsol8 {
790
829
  if (this.network === "filtered") {
791
830
  await startProxy(container, this.networkFilter);
792
831
  }
793
- const filePath = `${SANDBOX_WORKDIR}/main${adapter.getFileExtension()}`;
832
+ const ext = req.fileExtension ?? adapter.getFileExtension();
833
+ const filePath = `${SANDBOX_WORKDIR}/main${ext}`;
794
834
  await writeFileViaExec(container, filePath, req.code);
795
835
  if (req.installPackages?.length) {
796
836
  await installPackages(container, req.runtime, req.installPackages);
@@ -821,9 +861,13 @@ class DockerIsol8 {
821
861
  const execStream = await exec.start({ Tty: false });
822
862
  yield* this.streamExecOutput(execStream, exec, container, timeoutMs);
823
863
  } finally {
824
- try {
825
- await container.remove({ force: true });
826
- } catch {}
864
+ if (this.persist) {
865
+ logger.debug(`[Persist] Leaving container running for inspection: ${container.id}`);
866
+ } else {
867
+ try {
868
+ await container.remove({ force: true });
869
+ } catch {}
870
+ }
827
871
  }
828
872
  } finally {
829
873
  this.semaphore.release();
@@ -864,7 +908,8 @@ class DockerIsol8 {
864
908
  if (this.network === "filtered") {
865
909
  await startProxy(container, this.networkFilter);
866
910
  }
867
- const filePath = `${SANDBOX_WORKDIR}/main${adapter.getFileExtension()}`;
911
+ const ext = req.fileExtension ?? adapter.getFileExtension();
912
+ const filePath = `${SANDBOX_WORKDIR}/main${ext}`;
868
913
  await writeFileViaExec(container, filePath, req.code);
869
914
  if (req.installPackages?.length) {
870
915
  await installPackages(container, req.runtime, req.installPackages);
@@ -910,7 +955,11 @@ class DockerIsol8 {
910
955
  ...req.outputPaths ? { files: await this.retrieveFiles(container, req.outputPaths) } : {}
911
956
  };
912
957
  } finally {
913
- await this.pool.release(container, image);
958
+ if (this.persist) {
959
+ logger.debug(`[Persist] Leaving container running for inspection: ${container.id}`);
960
+ } else {
961
+ await this.pool.release(container, image);
962
+ }
914
963
  }
915
964
  }
916
965
  async executePersistent(req) {
@@ -921,7 +970,8 @@ class DockerIsol8 {
921
970
  } else if (this.persistentRuntime?.name !== adapter.name) {
922
971
  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.`);
923
972
  }
924
- const filePath = `${SANDBOX_WORKDIR}/exec_${Date.now()}${adapter.getFileExtension()}`;
973
+ const ext = req.fileExtension ?? adapter.getFileExtension();
974
+ const filePath = `${SANDBOX_WORKDIR}/exec_${Date.now()}${ext}`;
925
975
  if (this.readonlyRootFs) {
926
976
  await writeFileViaExec(this.container, filePath, req.code);
927
977
  } else {
@@ -1383,7 +1433,7 @@ function createServer(options) {
1383
1433
  // package.json
1384
1434
  var package_default = {
1385
1435
  name: "isol8",
1386
- version: "0.4.1",
1436
+ version: "0.4.3",
1387
1437
  description: "Secure code execution engine for AI agents",
1388
1438
  author: "Illusion47586",
1389
1439
  license: "MIT",
@@ -1501,4 +1551,4 @@ export {
1501
1551
  BunAdapter
1502
1552
  };
1503
1553
 
1504
- //# debugId=B16E985AABF04C9E64756E2164756E21
1554
+ //# debugId=BFAE8F3A0F89B57E64756E2164756E21