sandbox 3.0.0-beta.1 → 3.0.0-beta.11

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.
@@ -3164,15 +3164,16 @@ const timeout = import_cjs$24.option({
3164
3164
  //#endregion
3165
3165
  //#region src/args/vcpus.ts
3166
3166
  var import_cjs$23 = /* @__PURE__ */ __toESM(require_cjs());
3167
+ const vcpusType = import_cjs$23.extendType(import_cjs$23.number, {
3168
+ displayName: "COUNT",
3169
+ async from(n) {
3170
+ if (!Number.isInteger(n) || n < 1) throw new Error(`Invalid vCPU count: ${n}. Must be a positive integer.`);
3171
+ return n;
3172
+ }
3173
+ });
3167
3174
  const vcpus = import_cjs$23.option({
3168
3175
  long: "vcpus",
3169
- type: import_cjs$23.optional(import_cjs$23.extendType(import_cjs$23.number, {
3170
- displayName: "COUNT",
3171
- async from(n) {
3172
- if (!Number.isInteger(n) || n < 1) throw new Error(`Invalid vCPU count: ${n}. Must be a positive integer.`);
3173
- return n;
3174
- }
3175
- })),
3176
+ type: import_cjs$23.optional(vcpusType),
3176
3177
  description: "Number of vCPUs to allocate (each vCPU includes 2048 MB of memory)"
3177
3178
  });
3178
3179
 
@@ -7426,7 +7427,7 @@ const scope = {
7426
7427
 
7427
7428
  //#endregion
7428
7429
  //#region package.json
7429
- var version = "3.0.0-beta.1";
7430
+ var version = "3.0.0-beta.11";
7430
7431
 
7431
7432
  //#endregion
7432
7433
  //#region src/error.ts
@@ -11250,16 +11251,23 @@ var import_ms$3 = /* @__PURE__ */ __toESM(require_ms());
11250
11251
  const debug$2 = createDebugger("sandbox:timeout");
11251
11252
  const BUFFER = (0, import_ms$3.default)("10 seconds");
11252
11253
  async function extendSandboxTimeoutPeriodically(sandbox, signal) {
11253
- const nextTick = sandbox.createdAt.getTime() + sandbox.timeout;
11254
+ const session = sandbox.currentSession();
11255
+ const timeout$1 = session.timeout;
11256
+ if (timeout$1 == null) return;
11257
+ const nextTick = session.createdAt.getTime() + timeout$1;
11254
11258
  debug$2(`next tick: ${new Date(nextTick).toISOString()}`);
11255
11259
  while (!signal.aborted) {
11256
- const timeout$1 = sandbox.createdAt.getTime() + sandbox.timeout - Date.now() - BUFFER;
11257
- if (timeout$1 > 2e3) {
11258
- debug$2(`sleeping for ${timeout$1}ms until next timeout extension`);
11259
- await setTimeout$1(timeout$1, null, { signal });
11260
+ const currentTimeout = session.timeout;
11261
+ if (currentTimeout == null) return;
11262
+ const sleepMs = session.createdAt.getTime() + currentTimeout - Date.now() - BUFFER;
11263
+ if (sleepMs > 2e3) {
11264
+ debug$2(`sleeping for ${sleepMs}ms until next timeout extension`);
11265
+ await setTimeout$1(sleepMs, null, { signal });
11260
11266
  }
11261
11267
  await sandbox.extendTimeout((0, import_ms$3.default)("5 minutes"));
11262
- const nextTick$1 = sandbox.createdAt.getTime() + sandbox.timeout;
11268
+ const updatedTimeout = session.timeout;
11269
+ if (updatedTimeout == null) return;
11270
+ const nextTick$1 = session.createdAt.getTime() + updatedTimeout;
11263
11271
  debug$2(`extended sandbox timeout by 5 minutes. next tick: ${new Date(nextTick$1).toISOString()}`);
11264
11272
  }
11265
11273
  }
@@ -11387,11 +11395,16 @@ async function startInteractiveShell(options) {
11387
11395
  await setupSandboxEnvironment(options.sandbox, progress);
11388
11396
  progress.text = "Booting up interactive listener...";
11389
11397
  command$1 = await startServerCommand(options.sandbox, listener, options.execution, options.sudo, options.envVars, options.cwd);
11398
+ debug$1("startServerCommand completed, cmdId=%s, interactivePort=%s", command$1.cmdId, options.sandbox.interactivePort);
11390
11399
  const waitForProcess = _usingCtx3.u(createAbortController("Connection established successfully"));
11391
11400
  listener.connection.then(() => {
11401
+ debug$1("listener.connection resolved");
11392
11402
  waitForProcess.abort();
11393
11403
  });
11394
- connect$1(command$1, listener, waitForProcess.signal).catch(waitForProcess.ignoreInterruptions);
11404
+ connect$1(command$1, listener, waitForProcess.signal).catch((err$1) => {
11405
+ if (waitForProcess.signal.aborted) return;
11406
+ listener.stdoutStream.destroy(err$1 instanceof Error ? err$1 : new Error(String(err$1)));
11407
+ });
11395
11408
  await Promise.all([throwIfCommandPrematurelyExited(command$1, waitForProcess.signal), attach({
11396
11409
  sandbox: options.sandbox,
11397
11410
  progress,
@@ -11494,6 +11507,7 @@ async function connect$1(command$1, listener, signal) {
11494
11507
  const stderrStream = _usingCtx5.u(getStderrStream());
11495
11508
  for await (const chunk of logs) if (chunk.stream === "stdout") listener.stdoutStream.write(chunk.data);
11496
11509
  else stderrStream.write(chunk.data);
11510
+ listener.stdoutStream.end();
11497
11511
  } catch (_) {
11498
11512
  _usingCtx5.e = _;
11499
11513
  } finally {
@@ -11766,6 +11780,12 @@ const args$2 = {
11766
11780
  type: ObjectFromKeyValue,
11767
11781
  description: "Default environment variables for sandbox commands"
11768
11782
  }),
11783
+ tags: import_cjs$14.multioption({
11784
+ long: "tag",
11785
+ short: "t",
11786
+ type: ObjectFromKeyValue,
11787
+ description: "Key-value tags to associate with the sandbox (e.g. --tag env=staging)"
11788
+ }),
11769
11789
  ...networkPolicyArgs,
11770
11790
  scope
11771
11791
  };
@@ -11777,7 +11797,7 @@ const create = import_cjs$14.command({
11777
11797
  description: "Create and connect to a sandbox without a network access",
11778
11798
  command: `sandbox run --network-policy=none --connect`
11779
11799
  }],
11780
- async handler({ name, nonPersistent, ports, scope: scope$1, runtime: runtime$1, timeout: timeout$1, vcpus: vcpus$1, silent, snapshot: snapshot$1, connect: connect$2, envVars, networkPolicy: networkPolicyMode$1, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 }) {
11800
+ async handler({ name, nonPersistent, ports, scope: scope$1, runtime: runtime$1, timeout: timeout$1, vcpus: vcpus$1, silent, snapshot: snapshot$1, connect: connect$2, envVars, tags, networkPolicy: networkPolicyMode$1, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 }) {
11781
11801
  const networkPolicy$1 = buildNetworkPolicy({
11782
11802
  networkPolicy: networkPolicyMode$1,
11783
11803
  allowedDomains: allowedDomains$1,
@@ -11786,6 +11806,7 @@ const create = import_cjs$14.command({
11786
11806
  });
11787
11807
  const persistent = !nonPersistent;
11788
11808
  const resources = vcpus$1 ? { vcpus: vcpus$1 } : void 0;
11809
+ const tagsObj = Object.keys(tags).length > 0 ? tags : void 0;
11789
11810
  const spinner = silent ? void 0 : ora("Creating sandbox...").start();
11790
11811
  const sandbox = snapshot$1 ? await sandboxClient.create({
11791
11812
  name,
@@ -11801,6 +11822,7 @@ const create = import_cjs$14.command({
11801
11822
  resources,
11802
11823
  networkPolicy: networkPolicy$1,
11803
11824
  env: envVars,
11825
+ tags: tagsObj,
11804
11826
  persistent,
11805
11827
  __interactive: true
11806
11828
  }) : await sandboxClient.create({
@@ -11814,6 +11836,7 @@ const create = import_cjs$14.command({
11814
11836
  resources,
11815
11837
  networkPolicy: networkPolicy$1,
11816
11838
  env: envVars,
11839
+ tags: tagsObj,
11817
11840
  persistent,
11818
11841
  __interactive: true
11819
11842
  });
@@ -11875,13 +11898,18 @@ const args$1 = {
11875
11898
  removeAfterUse: import_cjs$13.flag({
11876
11899
  long: "rm",
11877
11900
  description: "Automatically remove the sandbox when the command exits."
11901
+ }),
11902
+ stopAfterUse: import_cjs$13.flag({
11903
+ long: "stop",
11904
+ description: "Stop the sandbox when the command exits."
11878
11905
  })
11879
11906
  };
11880
11907
  const run = import_cjs$13.command({
11881
11908
  name: "run",
11882
11909
  description: "Create and run a command in a sandbox",
11883
11910
  args: args$1,
11884
- async handler({ removeAfterUse, ...rest$1 }) {
11911
+ async handler({ removeAfterUse, stopAfterUse, ...rest$1 }) {
11912
+ if (removeAfterUse && stopAfterUse) throw new Error("--rm and --stop are mutually exclusive.");
11885
11913
  let sandbox;
11886
11914
  if (rest$1.name) try {
11887
11915
  sandbox = await sandboxClient.get({
@@ -11893,10 +11921,16 @@ const run = import_cjs$13.command({
11893
11921
  __includeSystemRoutes: true
11894
11922
  });
11895
11923
  } catch (error) {
11896
- if (error instanceof StyledError && error.cause instanceof APIError && error.cause.response.status === 404) sandbox = await create.handler({ ...rest$1 });
11924
+ if (error instanceof StyledError && error.cause instanceof APIError && error.cause.response.status === 404) sandbox = await create.handler({
11925
+ ...rest$1,
11926
+ nonPersistent: rest$1.nonPersistent || removeAfterUse
11927
+ });
11897
11928
  else throw error;
11898
11929
  }
11899
- else sandbox = await create.handler({ ...rest$1 });
11930
+ else sandbox = await create.handler({
11931
+ ...rest$1,
11932
+ nonPersistent: rest$1.nonPersistent || removeAfterUse
11933
+ });
11900
11934
  try {
11901
11935
  await exec.handler({
11902
11936
  ...rest$1,
@@ -11904,6 +11938,7 @@ const run = import_cjs$13.command({
11904
11938
  });
11905
11939
  } finally {
11906
11940
  if (removeAfterUse) await sandbox.delete();
11941
+ if (stopAfterUse) await sandbox.stop();
11907
11942
  }
11908
11943
  }
11909
11944
  });
@@ -11929,25 +11964,47 @@ const list = import_cjs$12.command({
11929
11964
  }),
11930
11965
  sortBy: import_cjs$12.option({
11931
11966
  long: "sort-by",
11932
- description: "Sort sandboxes by field. Options: createdAt (default), name",
11933
- type: import_cjs$12.optional(import_cjs$12.oneOf(["createdAt", "name"]))
11967
+ description: "Sort sandboxes by field. Options: createdAt (default), name, statusUpdatedAt",
11968
+ type: import_cjs$12.optional(import_cjs$12.oneOf([
11969
+ "createdAt",
11970
+ "name",
11971
+ "statusUpdatedAt"
11972
+ ]))
11973
+ }),
11974
+ sortOrder: import_cjs$12.option({
11975
+ long: "sort-order",
11976
+ description: "Sort order. Options: asc, desc (default)",
11977
+ type: import_cjs$12.optional(import_cjs$12.oneOf(["asc", "desc"]))
11978
+ }),
11979
+ tags: import_cjs$12.multioption({
11980
+ long: "tag",
11981
+ description: "Filter sandboxes by tag. Format: \"key=value\"",
11982
+ type: ObjectFromKeyValue
11934
11983
  }),
11935
11984
  scope
11936
11985
  },
11937
- async handler({ scope: { token: token$1, team: team$1, project: project$1 }, all, namePrefix, sortBy }) {
11986
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, all, namePrefix, sortBy, sortOrder, tags }) {
11987
+ if (namePrefix) {
11988
+ if (sortBy && sortBy !== "name") {
11989
+ console.error(source_default.red("Error: --sort-by must be 'name' when using --name-prefix"));
11990
+ return;
11991
+ }
11992
+ sortBy = "name";
11993
+ }
11938
11994
  const sandboxes = await (async () => {
11939
11995
  try {
11940
11996
  var _usingCtx$1 = _usingCtx();
11941
11997
  const _spinner$1 = _usingCtx$1.u(acquireRelease(() => ora("Fetching sandboxes...").start(), (s$1) => s$1.stop()));
11942
- const { json } = await sandboxClient.list({
11998
+ let { sandboxes: sandboxes$1 } = await sandboxClient.list({
11943
11999
  token: token$1,
11944
12000
  teamId: team$1,
11945
12001
  projectId: project$1,
11946
- limit: 100,
12002
+ limit: 50,
11947
12003
  ...namePrefix && { namePrefix },
11948
- ...sortBy && { sortBy }
12004
+ ...sortBy && { sortBy },
12005
+ ...sortOrder && { sortOrder },
12006
+ ...Object.keys(tags).length > 0 && { tags }
11949
12007
  });
11950
- let sandboxes$1 = json.sandboxes;
11951
12008
  if (!all) sandboxes$1 = sandboxes$1.filter((x) => x.status === "running");
11952
12009
  return sandboxes$1;
11953
12010
  } catch (_) {
@@ -11967,11 +12024,12 @@ const list = import_cjs$12.command({
11967
12024
  color: (s$1) => SandboxStatusColor[s$1.status] ?? source_default.reset
11968
12025
  },
11969
12026
  CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
11970
- MEMORY: { value: (s$1) => memoryFormatter.format(s$1.memory) },
11971
- VCPUS: { value: (s$1) => s$1.vcpus },
11972
- RUNTIME: { value: (s$1) => s$1.runtime },
11973
- TIMEOUT: { value: (s$1) => timeAgo(s$1.createdAt + s$1.timeout) },
11974
- SNAPSHOT: { value: (s$1) => s$1.currentSnapshotId ?? "-" }
12027
+ MEMORY: { value: (s$1) => s$1.memory != null ? memoryFormatter.format(s$1.memory) : "-" },
12028
+ VCPUS: { value: (s$1) => s$1.vcpus ?? "-" },
12029
+ RUNTIME: { value: (s$1) => s$1.runtime ?? "-" },
12030
+ TIMEOUT: { value: (s$1) => s$1.timeout != null ? timeAgo(s$1.createdAt + s$1.timeout) : "-" },
12031
+ SNAPSHOT: { value: (s$1) => s$1.currentSnapshotId ?? "-" },
12032
+ TAGS: { value: (s$1) => s$1.tags && Object.keys(s$1.tags).length > 0 ? Object.entries(s$1.tags).map(([k, v]) => `${k}:${v}`).join(", ") : "-" }
11975
12033
  };
11976
12034
  if (all) {
11977
12035
  columns.CPU = { value: (s$1) => s$1.totalActiveCpuDurationMs ? formatRunDuration(s$1.totalActiveCpuDurationMs) : "-" };
@@ -14313,9 +14371,9 @@ const stop = import_cjs$10.command({
14313
14371
  scope
14314
14372
  },
14315
14373
  async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandboxName: sandboxName$1, sandboxNames }) {
14316
- await new Listr(Array.from(new Set([sandboxName$1, ...sandboxNames]), (sandboxName$2) => {
14374
+ const tasks = Array.from(new Set([sandboxName$1, ...sandboxNames]), (sandboxName$2) => {
14317
14375
  return {
14318
- title: `Stopping sandbox ${sandboxName$2}`,
14376
+ title: `Stopping active session from ${sandboxName$2}`,
14319
14377
  async task() {
14320
14378
  await (await sandboxClient.get({
14321
14379
  token: token$1,
@@ -14325,7 +14383,12 @@ const stop = import_cjs$10.command({
14325
14383
  })).stop();
14326
14384
  }
14327
14385
  };
14328
- }), { concurrent: true }).run();
14386
+ });
14387
+ try {
14388
+ await new Listr(tasks, { concurrent: true }).run();
14389
+ } catch {
14390
+ process.exitCode = 1;
14391
+ }
14329
14392
  }
14330
14393
  });
14331
14394
 
@@ -14345,14 +14408,10 @@ const remove = import_cjs$9.command({
14345
14408
  type: sandboxName,
14346
14409
  description: "more sandboxes to remove"
14347
14410
  }),
14348
- preserveSnapshots: import_cjs$9.flag({
14349
- long: "preserve-snapshots",
14350
- description: "Keep snapshots when removing the sandbox"
14351
- }),
14352
14411
  scope
14353
14412
  },
14354
- async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandboxName: sandboxName$1, sandboxNames, preserveSnapshots }) {
14355
- await new Listr(Array.from(new Set([sandboxName$1, ...sandboxNames]), (name) => ({
14413
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandboxName: sandboxName$1, sandboxNames }) {
14414
+ const tasks = Array.from(new Set([sandboxName$1, ...sandboxNames]), (name) => ({
14356
14415
  title: `Removing sandbox ${name}`,
14357
14416
  async task() {
14358
14417
  await (await sandboxClient.get({
@@ -14360,9 +14419,14 @@ const remove = import_cjs$9.command({
14360
14419
  teamId: team$1,
14361
14420
  projectId: project$1,
14362
14421
  name
14363
- })).delete({ preserveSnapshots });
14422
+ })).delete();
14364
14423
  }
14365
- })), { concurrent: true }).run();
14424
+ }));
14425
+ try {
14426
+ await new Listr(tasks, { concurrent: true }).run();
14427
+ } catch {
14428
+ process.exitCode = 1;
14429
+ }
14366
14430
  }
14367
14431
  });
14368
14432
 
@@ -14531,19 +14595,33 @@ const list$2 = import_cjs$4.command({
14531
14595
  name: "list",
14532
14596
  aliases: ["ls"],
14533
14597
  description: "List snapshots for the specified account and project.",
14534
- args: { scope },
14535
- async handler({ scope: { token: token$1, team: team$1, project: project$1 } }) {
14598
+ args: {
14599
+ scope,
14600
+ name: import_cjs$4.option({
14601
+ type: import_cjs$4.optional(sandboxName),
14602
+ long: "name",
14603
+ description: "Filter snapshots by sandbox."
14604
+ }),
14605
+ sortOrder: import_cjs$4.option({
14606
+ long: "sort-order",
14607
+ description: "Sort order. Options: asc, desc (default)",
14608
+ type: import_cjs$4.optional(import_cjs$4.oneOf(["asc", "desc"]))
14609
+ })
14610
+ },
14611
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, name, sortOrder }) {
14536
14612
  const snapshots$1 = await (async () => {
14537
14613
  try {
14538
14614
  var _usingCtx$1 = _usingCtx();
14539
14615
  const _spinner$1 = _usingCtx$1.u(acquireRelease(() => ora("Fetching snapshots...").start(), (s$1) => s$1.stop()));
14540
- const { json } = await snapshotClient.list({
14616
+ const { snapshots: snapshots$2 } = await snapshotClient.list({
14541
14617
  token: token$1,
14542
14618
  teamId: team$1,
14543
14619
  projectId: project$1,
14544
- limit: 100
14620
+ name,
14621
+ limit: 50,
14622
+ ...sortOrder && { sortOrder }
14545
14623
  });
14546
- return json.snapshots;
14624
+ return snapshots$2;
14547
14625
  } catch (_) {
14548
14626
  _usingCtx$1.e = _;
14549
14627
  } finally {
@@ -14561,7 +14639,7 @@ const list$2 = import_cjs$4.command({
14561
14639
  CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
14562
14640
  EXPIRATION: { value: (s$1) => s$1.status === "deleted" ? source_default.gray.dim("deleted") : timeAgo(s$1.expiresAt) },
14563
14641
  SIZE: { value: (s$1) => formatBytes(s$1.sizeBytes) },
14564
- ["SOURCE SESSION"]: { value: (s$1) => s$1.sourceSandboxId }
14642
+ ["SOURCE SESSION"]: { value: (s$1) => s$1.sourceSessionId }
14565
14643
  }
14566
14644
  }));
14567
14645
  }
@@ -14604,7 +14682,7 @@ const get = import_cjs$4.command({
14604
14682
  CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
14605
14683
  EXPIRATION: { value: (s$1) => s$1.status === "deleted" ? source_default.gray.dim("deleted") : timeAgo(s$1.expiresAt) },
14606
14684
  SIZE: { value: (s$1) => formatBytes(s$1.sizeBytes) },
14607
- ["SOURCE SESSION"]: { value: (s$1) => s$1.sourceSandboxId }
14685
+ ["SOURCE SESSION"]: { value: (s$1) => s$1.sourceSessionId }
14608
14686
  }
14609
14687
  }));
14610
14688
  }
@@ -14625,7 +14703,7 @@ const remove$1 = import_cjs$4.command({
14625
14703
  scope
14626
14704
  },
14627
14705
  async handler({ scope: { team: team$1, token: token$1, project: project$1 }, snapshotId: snapshotId$1, snapshotIds }) {
14628
- await new Listr(Array.from(new Set([snapshotId$1, ...snapshotIds]), (snapshotId$2) => {
14706
+ const tasks = Array.from(new Set([snapshotId$1, ...snapshotIds]), (snapshotId$2) => {
14629
14707
  return {
14630
14708
  title: `Deleting snapshot ${snapshotId$2}`,
14631
14709
  async task() {
@@ -14639,7 +14717,12 @@ const remove$1 = import_cjs$4.command({
14639
14717
  await snapshot$1.delete();
14640
14718
  }
14641
14719
  };
14642
- }), { concurrent: true }).run();
14720
+ });
14721
+ try {
14722
+ await new Listr(tasks, { concurrent: true }).run();
14723
+ } catch {
14724
+ process.exitCode = 1;
14725
+ }
14643
14726
  }
14644
14727
  });
14645
14728
  const snapshots = (0, import_cjs$5.subcommands)({
@@ -14667,45 +14750,66 @@ const list$1 = import_cjs$2.command({
14667
14750
  aliases: ["ls"],
14668
14751
  description: "List sessions from a sandbox",
14669
14752
  args: {
14753
+ all: import_cjs$2.flag({
14754
+ long: "all",
14755
+ short: "a",
14756
+ description: "Show all sessions (default shows just running)"
14757
+ }),
14670
14758
  sandbox: import_cjs$2.positional({
14671
14759
  type: sandboxName,
14672
14760
  description: "Sandbox name to list sessions for"
14673
14761
  }),
14762
+ sortOrder: import_cjs$2.option({
14763
+ long: "sort-order",
14764
+ description: "Sort order. Options: asc, desc (default)",
14765
+ type: import_cjs$2.optional(import_cjs$2.oneOf(["asc", "desc"]))
14766
+ }),
14674
14767
  scope
14675
14768
  },
14676
- async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name }) {
14769
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, all, sandbox: name, sortOrder }) {
14677
14770
  const sandbox = await sandboxClient.get({
14678
14771
  name,
14679
14772
  projectId: project$1,
14680
14773
  teamId: team$1,
14681
14774
  token: token$1
14682
14775
  });
14683
- const sessions$1 = (await (async () => {
14776
+ let { sessions: sessions$1 } = await (async () => {
14684
14777
  try {
14685
14778
  var _usingCtx$1 = _usingCtx();
14686
14779
  const _spinner$1 = _usingCtx$1.u(acquireRelease(() => ora("Fetching sessions...").start(), (s$1) => s$1.stop()));
14687
- return sandbox.listSessions();
14780
+ return sandbox.listSessions({ ...sortOrder && { sortOrder } });
14688
14781
  } catch (_) {
14689
14782
  _usingCtx$1.e = _;
14690
14783
  } finally {
14691
14784
  _usingCtx$1.d();
14692
14785
  }
14693
- })()).json.sandboxes;
14786
+ })();
14787
+ if (!all) sessions$1 = sessions$1.filter((x) => x.status === "running");
14788
+ const memoryFormatter = new Intl.NumberFormat(void 0, {
14789
+ style: "unit",
14790
+ unit: "megabyte"
14791
+ });
14792
+ const columns = {
14793
+ ID: { value: (s$1) => s$1.id },
14794
+ STATUS: {
14795
+ value: (s$1) => s$1.status,
14796
+ color: (s$1) => SessionStatusColor[s$1.status] ?? source_default.reset
14797
+ },
14798
+ CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
14799
+ MEMORY: { value: (s$1) => memoryFormatter.format(s$1.memory) },
14800
+ VCPUS: { value: (s$1) => s$1.vcpus },
14801
+ RUNTIME: { value: (s$1) => s$1.runtime },
14802
+ TIMEOUT: { value: (s$1) => timeAgo(s$1.createdAt + s$1.timeout) },
14803
+ DURATION: { value: (s$1) => s$1.duration ? formatRunDuration(s$1.duration) : "-" },
14804
+ SNAPSHOT: { value: (s$1) => s$1.sourceSnapshotId ?? "-" }
14805
+ };
14806
+ if (all) {
14807
+ columns.CPU = { value: (s$1) => s$1.activeCpuDurationMs ? formatRunDuration(s$1.activeCpuDurationMs) : "-" };
14808
+ columns["NETWORK (OUT/IN)"] = { value: (s$1) => s$1.networkTransfer?.egress || s$1.networkTransfer?.ingress ? `${formatBytes(s$1.networkTransfer?.egress ?? 0)} / ${formatBytes(s$1.networkTransfer?.ingress ?? 0)}` : "- / -" };
14809
+ }
14694
14810
  console.log(table({
14695
14811
  rows: sessions$1,
14696
- columns: {
14697
- ID: { value: (s$1) => s$1.id },
14698
- STATUS: {
14699
- value: (s$1) => s$1.status,
14700
- color: (s$1) => SessionStatusColor[s$1.status] ?? source_default.reset
14701
- },
14702
- CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
14703
- MEMORY: { value: (s$1) => s$1.memory },
14704
- VCPUS: { value: (s$1) => s$1.vcpus },
14705
- RUNTIME: { value: (s$1) => s$1.runtime },
14706
- TIMEOUT: { value: (s$1) => timeAgo(s$1.createdAt + s$1.timeout) },
14707
- DURATION: { value: (s$1) => s$1.duration ? formatRunDuration(s$1.duration) : "-" }
14708
- }
14812
+ columns
14709
14813
  }));
14710
14814
  }
14711
14815
  });
@@ -14729,37 +14833,54 @@ const SessionStatusColor = {
14729
14833
  var import_cjs$1 = /* @__PURE__ */ __toESM(require_cjs());
14730
14834
  init_source();
14731
14835
  var import_ms = /* @__PURE__ */ __toESM(require_ms());
14732
- const setCommand = import_cjs$1.command({
14733
- name: "set",
14734
- description: "Update the configuration of a sandbox",
14836
+ const vcpusCommand = import_cjs$1.command({
14837
+ name: "vcpus",
14838
+ description: "Update the vCPU count of a sandbox",
14735
14839
  args: {
14736
14840
  sandbox: import_cjs$1.positional({
14737
14841
  type: sandboxName,
14738
14842
  description: "Sandbox name to update"
14739
14843
  }),
14740
- vcpus,
14741
- runtime: import_cjs$1.option({
14742
- long: "runtime",
14743
- type: import_cjs$1.optional(runtimeType),
14744
- description: "Runtime to use: node22, node24, or python3.13"
14844
+ count: import_cjs$1.positional({
14845
+ type: vcpusType,
14846
+ description: "Number of vCPUs to allocate (each vCPU includes 2048 MB of memory)"
14847
+ }),
14848
+ scope
14849
+ },
14850
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name, count }) {
14851
+ const sandbox = await sandboxClient.get({
14852
+ name,
14853
+ projectId: project$1,
14854
+ teamId: team$1,
14855
+ token: token$1
14856
+ });
14857
+ const spinner = ora("Updating sandbox configuration...").start();
14858
+ try {
14859
+ await sandbox.update({ resources: { vcpus: count } });
14860
+ spinner.stop();
14861
+ process.stderr.write("✅ Configuration updated for sandbox " + source_default.cyan(name) + "\n");
14862
+ process.stderr.write(source_default.dim(" ╰ ") + "vcpus: " + source_default.cyan(count) + "\n");
14863
+ } catch (error) {
14864
+ spinner.stop();
14865
+ throw error;
14866
+ }
14867
+ }
14868
+ });
14869
+ const timeoutCommand = import_cjs$1.command({
14870
+ name: "timeout",
14871
+ description: "Update the timeout of a sandbox (will be applied to all new sessions)",
14872
+ args: {
14873
+ sandbox: import_cjs$1.positional({
14874
+ type: sandboxName,
14875
+ description: "Sandbox name to update"
14745
14876
  }),
14746
- timeout: import_cjs$1.option({
14747
- long: "timeout",
14748
- type: import_cjs$1.optional(Duration),
14877
+ duration: import_cjs$1.positional({
14878
+ type: Duration,
14749
14879
  description: "The maximum duration a sandbox can run for. Example: 5m, 1h"
14750
14880
  }),
14751
- ...networkPolicyArgs,
14752
14881
  scope
14753
14882
  },
14754
- async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name, vcpus: vcpus$1, runtime: runtime$1, timeout: timeout$1, networkPolicy: networkPolicyMode$1, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 }) {
14755
- const hasNetworkPolicyArgs = networkPolicyMode$1 !== void 0 || allowedDomains$1.length > 0 || allowedCIDRs$1.length > 0 || deniedCIDRs$1.length > 0;
14756
- if (vcpus$1 === void 0 && runtime$1 === void 0 && timeout$1 === void 0 && !hasNetworkPolicyArgs) throw new Error([`At least one option must be provided.`, `${source_default.bold("hint:")} Use --vcpus, --runtime, --timeout, or --network-policy to update the sandbox configuration.`].join("\n"));
14757
- const networkPolicy$1 = hasNetworkPolicyArgs ? buildNetworkPolicy({
14758
- networkPolicy: networkPolicyMode$1,
14759
- allowedDomains: allowedDomains$1,
14760
- allowedCIDRs: allowedCIDRs$1,
14761
- deniedCIDRs: deniedCIDRs$1
14762
- }) : void 0;
14883
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name, duration }) {
14763
14884
  const sandbox = await sandboxClient.get({
14764
14885
  name,
14765
14886
  projectId: project$1,
@@ -14768,21 +14889,54 @@ const setCommand = import_cjs$1.command({
14768
14889
  });
14769
14890
  const spinner = ora("Updating sandbox configuration...").start();
14770
14891
  try {
14771
- await sandbox.update({
14772
- ...vcpus$1 !== void 0 && { resources: { vcpus: vcpus$1 } },
14773
- ...runtime$1 !== void 0 && { runtime: runtime$1 },
14774
- ...timeout$1 !== void 0 && { timeout: (0, import_ms.default)(timeout$1) },
14775
- ...networkPolicy$1 !== void 0 && { networkPolicy: networkPolicy$1 }
14776
- });
14777
- spinner.succeed("Configuration updated for sandbox " + source_default.cyan(name));
14892
+ await sandbox.update({ timeout: (0, import_ms.default)(duration) });
14893
+ spinner.stop();
14894
+ process.stderr.write("✅ Configuration updated for sandbox " + source_default.cyan(name) + "\n");
14895
+ process.stderr.write(source_default.dim(" ╰ ") + "timeout: " + source_default.cyan(duration) + "\n");
14778
14896
  } catch (error) {
14779
14897
  spinner.stop();
14780
14898
  throw error;
14781
14899
  }
14782
14900
  }
14783
14901
  });
14784
- const getCommand = import_cjs$1.command({
14785
- name: "get",
14902
+ const persistentCommand = import_cjs$1.command({
14903
+ name: "persistent",
14904
+ description: "Enable or disable automatic restore of the filesystem between sessions",
14905
+ args: {
14906
+ sandbox: import_cjs$1.positional({
14907
+ type: sandboxName,
14908
+ description: "Sandbox name to update"
14909
+ }),
14910
+ value: import_cjs$1.positional({
14911
+ type: {
14912
+ ...import_cjs$1.oneOf(["true", "false"]),
14913
+ displayName: "true|false"
14914
+ },
14915
+ description: "Enable or disable automatic restore of the filesystem between sessions"
14916
+ }),
14917
+ scope
14918
+ },
14919
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name, value }) {
14920
+ const sandbox = await sandboxClient.get({
14921
+ name,
14922
+ projectId: project$1,
14923
+ teamId: team$1,
14924
+ token: token$1
14925
+ });
14926
+ const spinner = ora("Updating sandbox configuration...").start();
14927
+ try {
14928
+ await sandbox.update({ persistent: value === "true" });
14929
+ spinner.stop();
14930
+ process.stderr.write("✅ Configuration updated for sandbox " + source_default.cyan(name) + "\n");
14931
+ process.stderr.write(source_default.dim(" ╰ ") + "persistent: " + source_default.cyan(value) + "\n");
14932
+ } catch (error) {
14933
+ spinner.stop();
14934
+ throw error;
14935
+ }
14936
+ }
14937
+ });
14938
+ const listCommand = import_cjs$1.command({
14939
+ name: "list",
14786
14940
  description: "Display the current configuration of a sandbox",
14787
14941
  args: {
14788
14942
  sandbox: import_cjs$1.positional({
@@ -14808,30 +14962,28 @@ const getCommand = import_cjs$1.command({
14808
14962
  _usingCtx$1.d();
14809
14963
  }
14810
14964
  })();
14811
- const memoryFormatter = new Intl.NumberFormat(void 0, {
14812
- style: "unit",
14813
- unit: "megabyte"
14814
- });
14965
+ const networkPolicy$1 = typeof sandbox.networkPolicy === "string" ? sandbox.networkPolicy : "restricted";
14966
+ const tagsDisplay = sandbox.tags && Object.keys(sandbox.tags).length > 0 ? Object.entries(sandbox.tags).map(([k, v]) => `${k}=${v}`).join(", ") : "-";
14815
14967
  const rows = [
14816
14968
  {
14817
- field: "Runtime",
14818
- value: sandbox.runtime
14969
+ field: "vCPUs",
14970
+ value: String(sandbox.vcpus ?? "-")
14819
14971
  },
14820
14972
  {
14821
- field: "vCPUs",
14822
- value: String(sandbox.vcpus)
14973
+ field: "Timeout",
14974
+ value: sandbox.timeout != null ? (0, import_ms.default)(sandbox.timeout, { long: true }) : "-"
14823
14975
  },
14824
14976
  {
14825
- field: "Memory",
14826
- value: memoryFormatter.format(sandbox.memory)
14977
+ field: "Persistent",
14978
+ value: String(sandbox.persistent)
14827
14979
  },
14828
14980
  {
14829
- field: "Timeout",
14830
- value: (0, import_ms.default)(sandbox.timeout, { long: true })
14981
+ field: "Network policy",
14982
+ value: String(networkPolicy$1)
14831
14983
  },
14832
14984
  {
14833
- field: "Region",
14834
- value: sandbox.region
14985
+ field: "Tags",
14986
+ value: tagsDisplay
14835
14987
  }
14836
14988
  ];
14837
14989
  console.log(table({
@@ -14848,8 +15000,7 @@ const getCommand = import_cjs$1.command({
14848
15000
  });
14849
15001
  const networkPolicyCommand = import_cjs$1.command({
14850
15002
  name: "network-policy",
14851
- description: `Update the network policy of a sandbox.
14852
- This will fully override the previous configuration.`,
15003
+ description: `Update the network policy of a sandbox`,
14853
15004
  args: {
14854
15005
  sandbox: import_cjs$1.positional({ type: sandboxName }),
14855
15006
  ...networkPolicyArgs,
@@ -14861,7 +15012,6 @@ const networkPolicyCommand = import_cjs$1.command({
14861
15012
  scope
14862
15013
  },
14863
15014
  async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: sandboxName$1, networkPolicy: networkPolicyFlag, mode: modeFlag, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 }) {
14864
- process.stderr.write(source_default.yellow("Warning: 'config network-policy' is deprecated. Use 'config set --network-policy=...' instead.\n"));
14865
15015
  const networkPolicyMode$1 = resolveMode(networkPolicyFlag, modeFlag);
14866
15016
  if (networkPolicyMode$1 === void 0 && allowedDomains$1.length === 0 && allowedCIDRs$1.length === 0 && deniedCIDRs$1.length === 0) throw new Error(`Network policy mode or custom rules must be set.`);
14867
15017
  const networkPolicy$1 = buildNetworkPolicy({
@@ -14878,10 +15028,10 @@ const networkPolicyCommand = import_cjs$1.command({
14878
15028
  });
14879
15029
  const spinner = ora("Updating network policy...").start();
14880
15030
  try {
14881
- const response = await sandbox.updateNetworkPolicy(networkPolicy$1);
15031
+ await sandbox.update({ networkPolicy: networkPolicy$1 });
14882
15032
  spinner.stop();
14883
15033
  process.stderr.write("✅ Network policy updated for sandbox " + source_default.cyan(sandbox.name) + "\n");
14884
- const mode = typeof response === "string" ? response : "restricted";
15034
+ const mode = typeof networkPolicy$1 === "string" ? networkPolicy$1 : "restricted";
14885
15035
  process.stderr.write(source_default.dim(" ╰ ") + "mode: " + source_default.cyan(mode) + "\n");
14886
15036
  } catch (error) {
14887
15037
  spinner.stop();
@@ -14889,13 +15039,58 @@ const networkPolicyCommand = import_cjs$1.command({
14889
15039
  }
14890
15040
  }
14891
15041
  });
15042
+ const tagsCommand = import_cjs$1.command({
15043
+ name: "tags",
15044
+ description: "Update the tags of a sandbox. Replaces all existing tags with the provided tags.",
15045
+ args: {
15046
+ sandbox: import_cjs$1.positional({
15047
+ type: sandboxName,
15048
+ description: "Sandbox name to update"
15049
+ }),
15050
+ tags: import_cjs$1.multioption({
15051
+ long: "tag",
15052
+ short: "t",
15053
+ type: ObjectFromKeyValue,
15054
+ description: "Key-value tags to set (e.g. --tag env=staging). Omit to clear all tags."
15055
+ }),
15056
+ scope
15057
+ },
15058
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name, tags }) {
15059
+ const sandbox = await sandboxClient.get({
15060
+ name,
15061
+ projectId: project$1,
15062
+ teamId: team$1,
15063
+ token: token$1
15064
+ });
15065
+ const tagsObj = Object.keys(tags).length > 0 ? tags : {};
15066
+ const spinner = ora("Updating sandbox tags...").start();
15067
+ try {
15068
+ await sandbox.update({ tags: tagsObj });
15069
+ spinner.stop();
15070
+ process.stderr.write("✅ Tags updated for sandbox " + source_default.cyan(name) + "\n");
15071
+ const entries$1 = Object.entries(tagsObj);
15072
+ if (entries$1.length === 0) process.stderr.write(source_default.dim(" ╰ ") + "all tags cleared\n");
15073
+ else for (let i = 0; i < entries$1.length; i++) {
15074
+ const [k, v] = entries$1[i];
15075
+ const prefix$1 = i === entries$1.length - 1 ? source_default.dim(" ╰ ") : source_default.dim(" │ ");
15076
+ process.stderr.write(prefix$1 + source_default.cyan(k) + "=" + source_default.cyan(v) + "\n");
15077
+ }
15078
+ } catch (error) {
15079
+ spinner.stop();
15080
+ throw error;
15081
+ }
15082
+ }
15083
+ });
14892
15084
  const config = import_cjs$1.subcommands({
14893
15085
  name: "config",
14894
15086
  description: "View and update sandbox configuration",
14895
15087
  cmds: {
14896
- set: setCommand,
14897
- get: getCommand,
14898
- "network-policy": networkPolicyCommand
15088
+ list: listCommand,
15089
+ vcpus: vcpusCommand,
15090
+ timeout: timeoutCommand,
15091
+ persistent: persistentCommand,
15092
+ "network-policy": networkPolicyCommand,
15093
+ tags: tagsCommand
14899
15094
  }
14900
15095
  });
14901
15096
 
@@ -14942,4 +15137,4 @@ const app = (opts) => (0, import_cjs.subcommands)({
14942
15137
 
14943
15138
  //#endregion
14944
15139
  export { source_exports as a, init_source as i, StyledError as n, require_cjs as r, app as t };
14945
- //# sourceMappingURL=app-AqqXdE-N.mjs.map
15140
+ //# sourceMappingURL=app-CwTzygZR.mjs.map