sandbox 3.0.0-beta.1 → 3.0.0-beta.10

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.10";
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,40 @@ 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 }) {
11938
11987
  const sandboxes = await (async () => {
11939
11988
  try {
11940
11989
  var _usingCtx$1 = _usingCtx();
11941
11990
  const _spinner$1 = _usingCtx$1.u(acquireRelease(() => ora("Fetching sandboxes...").start(), (s$1) => s$1.stop()));
11942
- const { json } = await sandboxClient.list({
11991
+ let { sandboxes: sandboxes$1 } = await sandboxClient.list({
11943
11992
  token: token$1,
11944
11993
  teamId: team$1,
11945
11994
  projectId: project$1,
11946
- limit: 100,
11995
+ limit: 50,
11947
11996
  ...namePrefix && { namePrefix },
11948
- ...sortBy && { sortBy }
11997
+ ...sortBy && { sortBy },
11998
+ ...sortOrder && { sortOrder },
11999
+ ...Object.keys(tags).length > 0 && { tags }
11949
12000
  });
11950
- let sandboxes$1 = json.sandboxes;
11951
12001
  if (!all) sandboxes$1 = sandboxes$1.filter((x) => x.status === "running");
11952
12002
  return sandboxes$1;
11953
12003
  } catch (_) {
@@ -11967,11 +12017,12 @@ const list = import_cjs$12.command({
11967
12017
  color: (s$1) => SandboxStatusColor[s$1.status] ?? source_default.reset
11968
12018
  },
11969
12019
  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 ?? "-" }
12020
+ MEMORY: { value: (s$1) => s$1.memory != null ? memoryFormatter.format(s$1.memory) : "-" },
12021
+ VCPUS: { value: (s$1) => s$1.vcpus ?? "-" },
12022
+ RUNTIME: { value: (s$1) => s$1.runtime ?? "-" },
12023
+ TIMEOUT: { value: (s$1) => s$1.timeout != null ? timeAgo(s$1.createdAt + s$1.timeout) : "-" },
12024
+ SNAPSHOT: { value: (s$1) => s$1.currentSnapshotId ?? "-" },
12025
+ 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
12026
  };
11976
12027
  if (all) {
11977
12028
  columns.CPU = { value: (s$1) => s$1.totalActiveCpuDurationMs ? formatRunDuration(s$1.totalActiveCpuDurationMs) : "-" };
@@ -14313,9 +14364,9 @@ const stop = import_cjs$10.command({
14313
14364
  scope
14314
14365
  },
14315
14366
  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) => {
14367
+ const tasks = Array.from(new Set([sandboxName$1, ...sandboxNames]), (sandboxName$2) => {
14317
14368
  return {
14318
- title: `Stopping sandbox ${sandboxName$2}`,
14369
+ title: `Stopping active session from ${sandboxName$2}`,
14319
14370
  async task() {
14320
14371
  await (await sandboxClient.get({
14321
14372
  token: token$1,
@@ -14325,7 +14376,12 @@ const stop = import_cjs$10.command({
14325
14376
  })).stop();
14326
14377
  }
14327
14378
  };
14328
- }), { concurrent: true }).run();
14379
+ });
14380
+ try {
14381
+ await new Listr(tasks, { concurrent: true }).run();
14382
+ } catch {
14383
+ process.exitCode = 1;
14384
+ }
14329
14385
  }
14330
14386
  });
14331
14387
 
@@ -14345,14 +14401,10 @@ const remove = import_cjs$9.command({
14345
14401
  type: sandboxName,
14346
14402
  description: "more sandboxes to remove"
14347
14403
  }),
14348
- preserveSnapshots: import_cjs$9.flag({
14349
- long: "preserve-snapshots",
14350
- description: "Keep snapshots when removing the sandbox"
14351
- }),
14352
14404
  scope
14353
14405
  },
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) => ({
14406
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandboxName: sandboxName$1, sandboxNames }) {
14407
+ const tasks = Array.from(new Set([sandboxName$1, ...sandboxNames]), (name) => ({
14356
14408
  title: `Removing sandbox ${name}`,
14357
14409
  async task() {
14358
14410
  await (await sandboxClient.get({
@@ -14360,9 +14412,14 @@ const remove = import_cjs$9.command({
14360
14412
  teamId: team$1,
14361
14413
  projectId: project$1,
14362
14414
  name
14363
- })).delete({ preserveSnapshots });
14415
+ })).delete();
14364
14416
  }
14365
- })), { concurrent: true }).run();
14417
+ }));
14418
+ try {
14419
+ await new Listr(tasks, { concurrent: true }).run();
14420
+ } catch {
14421
+ process.exitCode = 1;
14422
+ }
14366
14423
  }
14367
14424
  });
14368
14425
 
@@ -14531,19 +14588,33 @@ const list$2 = import_cjs$4.command({
14531
14588
  name: "list",
14532
14589
  aliases: ["ls"],
14533
14590
  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 } }) {
14591
+ args: {
14592
+ scope,
14593
+ name: import_cjs$4.option({
14594
+ type: import_cjs$4.optional(sandboxName),
14595
+ long: "name",
14596
+ description: "Filter snapshots by sandbox."
14597
+ }),
14598
+ sortOrder: import_cjs$4.option({
14599
+ long: "sort-order",
14600
+ description: "Sort order. Options: asc, desc (default)",
14601
+ type: import_cjs$4.optional(import_cjs$4.oneOf(["asc", "desc"]))
14602
+ })
14603
+ },
14604
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, name, sortOrder }) {
14536
14605
  const snapshots$1 = await (async () => {
14537
14606
  try {
14538
14607
  var _usingCtx$1 = _usingCtx();
14539
14608
  const _spinner$1 = _usingCtx$1.u(acquireRelease(() => ora("Fetching snapshots...").start(), (s$1) => s$1.stop()));
14540
- const { json } = await snapshotClient.list({
14609
+ const { snapshots: snapshots$2 } = await snapshotClient.list({
14541
14610
  token: token$1,
14542
14611
  teamId: team$1,
14543
14612
  projectId: project$1,
14544
- limit: 100
14613
+ name,
14614
+ limit: 50,
14615
+ ...sortOrder && { sortOrder }
14545
14616
  });
14546
- return json.snapshots;
14617
+ return snapshots$2;
14547
14618
  } catch (_) {
14548
14619
  _usingCtx$1.e = _;
14549
14620
  } finally {
@@ -14561,7 +14632,7 @@ const list$2 = import_cjs$4.command({
14561
14632
  CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
14562
14633
  EXPIRATION: { value: (s$1) => s$1.status === "deleted" ? source_default.gray.dim("deleted") : timeAgo(s$1.expiresAt) },
14563
14634
  SIZE: { value: (s$1) => formatBytes(s$1.sizeBytes) },
14564
- ["SOURCE SESSION"]: { value: (s$1) => s$1.sourceSandboxId }
14635
+ ["SOURCE SESSION"]: { value: (s$1) => s$1.sourceSessionId }
14565
14636
  }
14566
14637
  }));
14567
14638
  }
@@ -14604,7 +14675,7 @@ const get = import_cjs$4.command({
14604
14675
  CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
14605
14676
  EXPIRATION: { value: (s$1) => s$1.status === "deleted" ? source_default.gray.dim("deleted") : timeAgo(s$1.expiresAt) },
14606
14677
  SIZE: { value: (s$1) => formatBytes(s$1.sizeBytes) },
14607
- ["SOURCE SESSION"]: { value: (s$1) => s$1.sourceSandboxId }
14678
+ ["SOURCE SESSION"]: { value: (s$1) => s$1.sourceSessionId }
14608
14679
  }
14609
14680
  }));
14610
14681
  }
@@ -14625,7 +14696,7 @@ const remove$1 = import_cjs$4.command({
14625
14696
  scope
14626
14697
  },
14627
14698
  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) => {
14699
+ const tasks = Array.from(new Set([snapshotId$1, ...snapshotIds]), (snapshotId$2) => {
14629
14700
  return {
14630
14701
  title: `Deleting snapshot ${snapshotId$2}`,
14631
14702
  async task() {
@@ -14639,7 +14710,12 @@ const remove$1 = import_cjs$4.command({
14639
14710
  await snapshot$1.delete();
14640
14711
  }
14641
14712
  };
14642
- }), { concurrent: true }).run();
14713
+ });
14714
+ try {
14715
+ await new Listr(tasks, { concurrent: true }).run();
14716
+ } catch {
14717
+ process.exitCode = 1;
14718
+ }
14643
14719
  }
14644
14720
  });
14645
14721
  const snapshots = (0, import_cjs$5.subcommands)({
@@ -14667,45 +14743,66 @@ const list$1 = import_cjs$2.command({
14667
14743
  aliases: ["ls"],
14668
14744
  description: "List sessions from a sandbox",
14669
14745
  args: {
14746
+ all: import_cjs$2.flag({
14747
+ long: "all",
14748
+ short: "a",
14749
+ description: "Show all sessions (default shows just running)"
14750
+ }),
14670
14751
  sandbox: import_cjs$2.positional({
14671
14752
  type: sandboxName,
14672
14753
  description: "Sandbox name to list sessions for"
14673
14754
  }),
14755
+ sortOrder: import_cjs$2.option({
14756
+ long: "sort-order",
14757
+ description: "Sort order. Options: asc, desc (default)",
14758
+ type: import_cjs$2.optional(import_cjs$2.oneOf(["asc", "desc"]))
14759
+ }),
14674
14760
  scope
14675
14761
  },
14676
- async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name }) {
14762
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, all, sandbox: name, sortOrder }) {
14677
14763
  const sandbox = await sandboxClient.get({
14678
14764
  name,
14679
14765
  projectId: project$1,
14680
14766
  teamId: team$1,
14681
14767
  token: token$1
14682
14768
  });
14683
- const sessions$1 = (await (async () => {
14769
+ let { sessions: sessions$1 } = await (async () => {
14684
14770
  try {
14685
14771
  var _usingCtx$1 = _usingCtx();
14686
14772
  const _spinner$1 = _usingCtx$1.u(acquireRelease(() => ora("Fetching sessions...").start(), (s$1) => s$1.stop()));
14687
- return sandbox.listSessions();
14773
+ return sandbox.listSessions({ ...sortOrder && { sortOrder } });
14688
14774
  } catch (_) {
14689
14775
  _usingCtx$1.e = _;
14690
14776
  } finally {
14691
14777
  _usingCtx$1.d();
14692
14778
  }
14693
- })()).json.sandboxes;
14779
+ })();
14780
+ if (!all) sessions$1 = sessions$1.filter((x) => x.status === "running");
14781
+ const memoryFormatter = new Intl.NumberFormat(void 0, {
14782
+ style: "unit",
14783
+ unit: "megabyte"
14784
+ });
14785
+ const columns = {
14786
+ ID: { value: (s$1) => s$1.id },
14787
+ STATUS: {
14788
+ value: (s$1) => s$1.status,
14789
+ color: (s$1) => SessionStatusColor[s$1.status] ?? source_default.reset
14790
+ },
14791
+ CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
14792
+ MEMORY: { value: (s$1) => memoryFormatter.format(s$1.memory) },
14793
+ VCPUS: { value: (s$1) => s$1.vcpus },
14794
+ RUNTIME: { value: (s$1) => s$1.runtime },
14795
+ TIMEOUT: { value: (s$1) => timeAgo(s$1.createdAt + s$1.timeout) },
14796
+ DURATION: { value: (s$1) => s$1.duration ? formatRunDuration(s$1.duration) : "-" },
14797
+ SNAPSHOT: { value: (s$1) => s$1.sourceSnapshotId ?? "-" }
14798
+ };
14799
+ if (all) {
14800
+ columns.CPU = { value: (s$1) => s$1.activeCpuDurationMs ? formatRunDuration(s$1.activeCpuDurationMs) : "-" };
14801
+ 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)}` : "- / -" };
14802
+ }
14694
14803
  console.log(table({
14695
14804
  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
- }
14805
+ columns
14709
14806
  }));
14710
14807
  }
14711
14808
  });
@@ -14729,37 +14826,54 @@ const SessionStatusColor = {
14729
14826
  var import_cjs$1 = /* @__PURE__ */ __toESM(require_cjs());
14730
14827
  init_source();
14731
14828
  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",
14829
+ const vcpusCommand = import_cjs$1.command({
14830
+ name: "vcpus",
14831
+ description: "Update the vCPU count of a sandbox",
14735
14832
  args: {
14736
14833
  sandbox: import_cjs$1.positional({
14737
14834
  type: sandboxName,
14738
14835
  description: "Sandbox name to update"
14739
14836
  }),
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"
14837
+ count: import_cjs$1.positional({
14838
+ type: vcpusType,
14839
+ description: "Number of vCPUs to allocate (each vCPU includes 2048 MB of memory)"
14745
14840
  }),
14746
- timeout: import_cjs$1.option({
14747
- long: "timeout",
14748
- type: import_cjs$1.optional(Duration),
14841
+ scope
14842
+ },
14843
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name, count }) {
14844
+ const sandbox = await sandboxClient.get({
14845
+ name,
14846
+ projectId: project$1,
14847
+ teamId: team$1,
14848
+ token: token$1
14849
+ });
14850
+ const spinner = ora("Updating sandbox configuration...").start();
14851
+ try {
14852
+ await sandbox.update({ resources: { vcpus: count } });
14853
+ spinner.stop();
14854
+ process.stderr.write("✅ Configuration updated for sandbox " + source_default.cyan(name) + "\n");
14855
+ process.stderr.write(source_default.dim(" ╰ ") + "vcpus: " + source_default.cyan(count) + "\n");
14856
+ } catch (error) {
14857
+ spinner.stop();
14858
+ throw error;
14859
+ }
14860
+ }
14861
+ });
14862
+ const timeoutCommand = import_cjs$1.command({
14863
+ name: "timeout",
14864
+ description: "Update the timeout of a sandbox (will be applied to all new sessions)",
14865
+ args: {
14866
+ sandbox: import_cjs$1.positional({
14867
+ type: sandboxName,
14868
+ description: "Sandbox name to update"
14869
+ }),
14870
+ duration: import_cjs$1.positional({
14871
+ type: Duration,
14749
14872
  description: "The maximum duration a sandbox can run for. Example: 5m, 1h"
14750
14873
  }),
14751
- ...networkPolicyArgs,
14752
14874
  scope
14753
14875
  },
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;
14876
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name, duration }) {
14763
14877
  const sandbox = await sandboxClient.get({
14764
14878
  name,
14765
14879
  projectId: project$1,
@@ -14768,21 +14882,54 @@ const setCommand = import_cjs$1.command({
14768
14882
  });
14769
14883
  const spinner = ora("Updating sandbox configuration...").start();
14770
14884
  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));
14885
+ await sandbox.update({ timeout: (0, import_ms.default)(duration) });
14886
+ spinner.stop();
14887
+ process.stderr.write("✅ Configuration updated for sandbox " + source_default.cyan(name) + "\n");
14888
+ process.stderr.write(source_default.dim(" ╰ ") + "timeout: " + source_default.cyan(duration) + "\n");
14778
14889
  } catch (error) {
14779
14890
  spinner.stop();
14780
14891
  throw error;
14781
14892
  }
14782
14893
  }
14783
14894
  });
14784
- const getCommand = import_cjs$1.command({
14785
- name: "get",
14895
+ const persistentCommand = import_cjs$1.command({
14896
+ name: "persistent",
14897
+ description: "Enable or disable automatic restore of the filesystem between sessions",
14898
+ args: {
14899
+ sandbox: import_cjs$1.positional({
14900
+ type: sandboxName,
14901
+ description: "Sandbox name to update"
14902
+ }),
14903
+ value: import_cjs$1.positional({
14904
+ type: {
14905
+ ...import_cjs$1.oneOf(["true", "false"]),
14906
+ displayName: "true|false"
14907
+ },
14908
+ description: "Enable or disable automatic restore of the filesystem between sessions"
14909
+ }),
14910
+ scope
14911
+ },
14912
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name, value }) {
14913
+ const sandbox = await sandboxClient.get({
14914
+ name,
14915
+ projectId: project$1,
14916
+ teamId: team$1,
14917
+ token: token$1
14918
+ });
14919
+ const spinner = ora("Updating sandbox configuration...").start();
14920
+ try {
14921
+ await sandbox.update({ persistent: value === "true" });
14922
+ spinner.stop();
14923
+ process.stderr.write("✅ Configuration updated for sandbox " + source_default.cyan(name) + "\n");
14924
+ process.stderr.write(source_default.dim(" ╰ ") + "persistent: " + source_default.cyan(value) + "\n");
14925
+ } catch (error) {
14926
+ spinner.stop();
14927
+ throw error;
14928
+ }
14929
+ }
14930
+ });
14931
+ const listCommand = import_cjs$1.command({
14932
+ name: "list",
14786
14933
  description: "Display the current configuration of a sandbox",
14787
14934
  args: {
14788
14935
  sandbox: import_cjs$1.positional({
@@ -14808,30 +14955,28 @@ const getCommand = import_cjs$1.command({
14808
14955
  _usingCtx$1.d();
14809
14956
  }
14810
14957
  })();
14811
- const memoryFormatter = new Intl.NumberFormat(void 0, {
14812
- style: "unit",
14813
- unit: "megabyte"
14814
- });
14958
+ const networkPolicy$1 = typeof sandbox.networkPolicy === "string" ? sandbox.networkPolicy : "restricted";
14959
+ const tagsDisplay = sandbox.tags && Object.keys(sandbox.tags).length > 0 ? Object.entries(sandbox.tags).map(([k, v]) => `${k}=${v}`).join(", ") : "-";
14815
14960
  const rows = [
14816
14961
  {
14817
- field: "Runtime",
14818
- value: sandbox.runtime
14962
+ field: "vCPUs",
14963
+ value: String(sandbox.vcpus ?? "-")
14819
14964
  },
14820
14965
  {
14821
- field: "vCPUs",
14822
- value: String(sandbox.vcpus)
14966
+ field: "Timeout",
14967
+ value: sandbox.timeout != null ? (0, import_ms.default)(sandbox.timeout, { long: true }) : "-"
14823
14968
  },
14824
14969
  {
14825
- field: "Memory",
14826
- value: memoryFormatter.format(sandbox.memory)
14970
+ field: "Persistent",
14971
+ value: String(sandbox.persistent)
14827
14972
  },
14828
14973
  {
14829
- field: "Timeout",
14830
- value: (0, import_ms.default)(sandbox.timeout, { long: true })
14974
+ field: "Network policy",
14975
+ value: String(networkPolicy$1)
14831
14976
  },
14832
14977
  {
14833
- field: "Region",
14834
- value: sandbox.region
14978
+ field: "Tags",
14979
+ value: tagsDisplay
14835
14980
  }
14836
14981
  ];
14837
14982
  console.log(table({
@@ -14848,8 +14993,7 @@ const getCommand = import_cjs$1.command({
14848
14993
  });
14849
14994
  const networkPolicyCommand = import_cjs$1.command({
14850
14995
  name: "network-policy",
14851
- description: `Update the network policy of a sandbox.
14852
- This will fully override the previous configuration.`,
14996
+ description: `Update the network policy of a sandbox`,
14853
14997
  args: {
14854
14998
  sandbox: import_cjs$1.positional({ type: sandboxName }),
14855
14999
  ...networkPolicyArgs,
@@ -14861,7 +15005,6 @@ const networkPolicyCommand = import_cjs$1.command({
14861
15005
  scope
14862
15006
  },
14863
15007
  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
15008
  const networkPolicyMode$1 = resolveMode(networkPolicyFlag, modeFlag);
14866
15009
  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
15010
  const networkPolicy$1 = buildNetworkPolicy({
@@ -14878,10 +15021,10 @@ const networkPolicyCommand = import_cjs$1.command({
14878
15021
  });
14879
15022
  const spinner = ora("Updating network policy...").start();
14880
15023
  try {
14881
- const response = await sandbox.updateNetworkPolicy(networkPolicy$1);
15024
+ await sandbox.update({ networkPolicy: networkPolicy$1 });
14882
15025
  spinner.stop();
14883
15026
  process.stderr.write("✅ Network policy updated for sandbox " + source_default.cyan(sandbox.name) + "\n");
14884
- const mode = typeof response === "string" ? response : "restricted";
15027
+ const mode = typeof networkPolicy$1 === "string" ? networkPolicy$1 : "restricted";
14885
15028
  process.stderr.write(source_default.dim(" ╰ ") + "mode: " + source_default.cyan(mode) + "\n");
14886
15029
  } catch (error) {
14887
15030
  spinner.stop();
@@ -14889,13 +15032,58 @@ const networkPolicyCommand = import_cjs$1.command({
14889
15032
  }
14890
15033
  }
14891
15034
  });
15035
+ const tagsCommand = import_cjs$1.command({
15036
+ name: "tags",
15037
+ description: "Update the tags of a sandbox. Replaces all existing tags with the provided tags.",
15038
+ args: {
15039
+ sandbox: import_cjs$1.positional({
15040
+ type: sandboxName,
15041
+ description: "Sandbox name to update"
15042
+ }),
15043
+ tags: import_cjs$1.multioption({
15044
+ long: "tag",
15045
+ short: "t",
15046
+ type: ObjectFromKeyValue,
15047
+ description: "Key-value tags to set (e.g. --tag env=staging). Omit to clear all tags."
15048
+ }),
15049
+ scope
15050
+ },
15051
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name, tags }) {
15052
+ const sandbox = await sandboxClient.get({
15053
+ name,
15054
+ projectId: project$1,
15055
+ teamId: team$1,
15056
+ token: token$1
15057
+ });
15058
+ const tagsObj = Object.keys(tags).length > 0 ? tags : {};
15059
+ const spinner = ora("Updating sandbox tags...").start();
15060
+ try {
15061
+ await sandbox.update({ tags: tagsObj });
15062
+ spinner.stop();
15063
+ process.stderr.write("✅ Tags updated for sandbox " + source_default.cyan(name) + "\n");
15064
+ const entries$1 = Object.entries(tagsObj);
15065
+ if (entries$1.length === 0) process.stderr.write(source_default.dim(" ╰ ") + "all tags cleared\n");
15066
+ else for (let i = 0; i < entries$1.length; i++) {
15067
+ const [k, v] = entries$1[i];
15068
+ const prefix$1 = i === entries$1.length - 1 ? source_default.dim(" ╰ ") : source_default.dim(" │ ");
15069
+ process.stderr.write(prefix$1 + source_default.cyan(k) + "=" + source_default.cyan(v) + "\n");
15070
+ }
15071
+ } catch (error) {
15072
+ spinner.stop();
15073
+ throw error;
15074
+ }
15075
+ }
15076
+ });
14892
15077
  const config = import_cjs$1.subcommands({
14893
15078
  name: "config",
14894
15079
  description: "View and update sandbox configuration",
14895
15080
  cmds: {
14896
- set: setCommand,
14897
- get: getCommand,
14898
- "network-policy": networkPolicyCommand
15081
+ list: listCommand,
15082
+ vcpus: vcpusCommand,
15083
+ timeout: timeoutCommand,
15084
+ persistent: persistentCommand,
15085
+ "network-policy": networkPolicyCommand,
15086
+ tags: tagsCommand
14899
15087
  }
14900
15088
  });
14901
15089
 
@@ -14942,4 +15130,4 @@ const app = (opts) => (0, import_cjs.subcommands)({
14942
15130
 
14943
15131
  //#endregion
14944
15132
  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
15133
+ //# sourceMappingURL=app-BAkG8Wcx.mjs.map