sandbox 2.5.6 → 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.
@@ -478,7 +478,7 @@ var init_source = __esm({ "../../node_modules/.pnpm/chalk@5.6.0/node_modules/cha
478
478
  var require_didYouMean_1_2_1 = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/didyoumean@1.2.2/node_modules/didyoumean/didYouMean-1.2.1.js": ((exports, module) => {
479
479
  (function() {
480
480
  "use strict";
481
- function didYouMean(str, list$2, key) {
481
+ function didYouMean(str, list$3, key) {
482
482
  if (!str) return null;
483
483
  if (!didYouMean.caseSensitive) str = str.toLowerCase();
484
484
  var thresholdRelative = didYouMean.threshold === null ? null : didYouMean.threshold * str.length, thresholdAbsolute = didYouMean.thresholdAbsolute, winningVal;
@@ -486,9 +486,9 @@ var require_didYouMean_1_2_1 = /* @__PURE__ */ __commonJS$1({ "../../node_module
486
486
  else if (thresholdRelative !== null) winningVal = thresholdRelative;
487
487
  else if (thresholdAbsolute !== null) winningVal = thresholdAbsolute;
488
488
  else winningVal = null;
489
- var winner, candidate, testCandidate, val, i, len = list$2.length;
489
+ var winner, candidate, testCandidate, val, i, len = list$3.length;
490
490
  for (i = 0; i < len; i++) {
491
- candidate = list$2[i];
491
+ candidate = list$3[i];
492
492
  if (key) candidate = candidate[key];
493
493
  if (!candidate) continue;
494
494
  if (!didYouMean.caseSensitive) testCandidate = candidate.toLowerCase();
@@ -496,7 +496,7 @@ var require_didYouMean_1_2_1 = /* @__PURE__ */ __commonJS$1({ "../../node_module
496
496
  val = getEditDistance(str, testCandidate, winningVal);
497
497
  if (winningVal === null || val < winningVal) {
498
498
  winningVal = val;
499
- if (key && didYouMean.returnWinningObject) winner = list$2[i];
499
+ if (key && didYouMean.returnWinningObject) winner = list$3[i];
500
500
  else winner = candidate;
501
501
  if (didYouMean.returnFirstMatch) return winner;
502
502
  }
@@ -1446,7 +1446,7 @@ var require_subcommands = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pn
1446
1446
  return mod && mod.__esModule ? mod : { "default": mod };
1447
1447
  };
1448
1448
  Object.defineProperty(exports, "__esModule", { value: true });
1449
- exports.subcommands = subcommands$2;
1449
+ exports.subcommands = subcommands$3;
1450
1450
  const chalk_1$3 = __importDefault$4((init_source(), __toCommonJS$3(source_exports)));
1451
1451
  const didyoumean_1 = __importDefault$4(require_didYouMean_1_2_1());
1452
1452
  const Result$7 = __importStar$7(require_Result());
@@ -1456,7 +1456,7 @@ var require_subcommands = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pn
1456
1456
  /**
1457
1457
  * Combine multiple `command`s into one
1458
1458
  */
1459
- function subcommands$2(config$1) {
1459
+ function subcommands$3(config$1) {
1460
1460
  const circuitbreaker = (0, circuitbreaker_1$1.createCircuitBreaker)(!!config$1.version);
1461
1461
  const subcommand = (0, positional_1$1.positional)({
1462
1462
  displayName: "subcommand",
@@ -2997,17 +2997,18 @@ var require_cjs = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/cmd-t
2997
2997
 
2998
2998
  //#endregion
2999
2999
  //#region src/args/runtime.ts
3000
- var import_cjs$23 = /* @__PURE__ */ __toESM(require_cjs());
3001
- const runtime = import_cjs$23.option({
3000
+ var import_cjs$26 = /* @__PURE__ */ __toESM(require_cjs());
3001
+ const runtimeType = {
3002
+ ...import_cjs$26.oneOf([
3003
+ "node22",
3004
+ "node24",
3005
+ "python3.13"
3006
+ ]),
3007
+ displayName: "runtime"
3008
+ };
3009
+ const runtime = import_cjs$26.option({
3002
3010
  long: "runtime",
3003
- type: {
3004
- ...import_cjs$23.oneOf([
3005
- "node22",
3006
- "node24",
3007
- "python3.13"
3008
- ]),
3009
- displayName: "runtime"
3010
- },
3011
+ type: runtimeType,
3011
3012
  defaultValue: () => "node24",
3012
3013
  defaultValueIsSerializable: true
3013
3014
  });
@@ -3099,13 +3100,13 @@ var require_ms = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/ms@2.1
3099
3100
  * @return {String}
3100
3101
  * @api private
3101
3102
  */
3102
- function fmtShort(ms$3) {
3103
- var msAbs = Math.abs(ms$3);
3104
- if (msAbs >= d) return Math.round(ms$3 / d) + "d";
3105
- if (msAbs >= h) return Math.round(ms$3 / h) + "h";
3106
- if (msAbs >= m) return Math.round(ms$3 / m) + "m";
3107
- if (msAbs >= s) return Math.round(ms$3 / s) + "s";
3108
- return ms$3 + "ms";
3103
+ function fmtShort(ms$4) {
3104
+ var msAbs = Math.abs(ms$4);
3105
+ if (msAbs >= d) return Math.round(ms$4 / d) + "d";
3106
+ if (msAbs >= h) return Math.round(ms$4 / h) + "h";
3107
+ if (msAbs >= m) return Math.round(ms$4 / m) + "m";
3108
+ if (msAbs >= s) return Math.round(ms$4 / s) + "s";
3109
+ return ms$4 + "ms";
3109
3110
  }
3110
3111
  /**
3111
3112
  * Long format for `ms`.
@@ -3114,28 +3115,28 @@ var require_ms = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/ms@2.1
3114
3115
  * @return {String}
3115
3116
  * @api private
3116
3117
  */
3117
- function fmtLong(ms$3) {
3118
- var msAbs = Math.abs(ms$3);
3119
- if (msAbs >= d) return plural(ms$3, msAbs, d, "day");
3120
- if (msAbs >= h) return plural(ms$3, msAbs, h, "hour");
3121
- if (msAbs >= m) return plural(ms$3, msAbs, m, "minute");
3122
- if (msAbs >= s) return plural(ms$3, msAbs, s, "second");
3123
- return ms$3 + " ms";
3118
+ function fmtLong(ms$4) {
3119
+ var msAbs = Math.abs(ms$4);
3120
+ if (msAbs >= d) return plural(ms$4, msAbs, d, "day");
3121
+ if (msAbs >= h) return plural(ms$4, msAbs, h, "hour");
3122
+ if (msAbs >= m) return plural(ms$4, msAbs, m, "minute");
3123
+ if (msAbs >= s) return plural(ms$4, msAbs, s, "second");
3124
+ return ms$4 + " ms";
3124
3125
  }
3125
3126
  /**
3126
3127
  * Pluralization helper.
3127
3128
  */
3128
- function plural(ms$3, msAbs, n, name) {
3129
+ function plural(ms$4, msAbs, n, name) {
3129
3130
  var isPlural = msAbs >= n * 1.5;
3130
- return Math.round(ms$3 / n) + " " + name + (isPlural ? "s" : "");
3131
+ return Math.round(ms$4 / n) + " " + name + (isPlural ? "s" : "");
3131
3132
  }
3132
3133
  }) });
3133
3134
 
3134
3135
  //#endregion
3135
3136
  //#region src/types/duration.ts
3136
- var import_cjs$22 = require_cjs();
3137
+ var import_cjs$25 = require_cjs();
3137
3138
  init_source();
3138
- const Duration = (0, import_cjs$22.extendType)(import_cjs$22.string, {
3139
+ const Duration = (0, import_cjs$25.extendType)(import_cjs$25.string, {
3139
3140
  displayName: "num UNIT",
3140
3141
  description: "A duration, e.g. 5m, 10s, 1h",
3141
3142
  async from(string$1) {
@@ -3151,8 +3152,8 @@ const Duration = (0, import_cjs$22.extendType)(import_cjs$22.string, {
3151
3152
 
3152
3153
  //#endregion
3153
3154
  //#region src/args/timeout.ts
3154
- var import_cjs$21 = /* @__PURE__ */ __toESM(require_cjs());
3155
- const timeout = import_cjs$21.option({
3155
+ var import_cjs$24 = /* @__PURE__ */ __toESM(require_cjs());
3156
+ const timeout = import_cjs$24.option({
3156
3157
  long: "timeout",
3157
3158
  type: Duration,
3158
3159
  description: "The maximum duration a sandbox can run for. Example: 5m, 1h",
@@ -3162,16 +3163,17 @@ const timeout = import_cjs$21.option({
3162
3163
 
3163
3164
  //#endregion
3164
3165
  //#region src/args/vcpus.ts
3165
- var import_cjs$20 = /* @__PURE__ */ __toESM(require_cjs());
3166
- const vcpus = import_cjs$20.option({
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
+ });
3174
+ const vcpus = import_cjs$23.option({
3167
3175
  long: "vcpus",
3168
- type: import_cjs$20.optional(import_cjs$20.extendType(import_cjs$20.number, {
3169
- displayName: "COUNT",
3170
- async from(n) {
3171
- if (!Number.isInteger(n) || n < 1) throw new Error(`Invalid vCPU count: ${n}. Must be a positive integer.`);
3172
- return n;
3173
- }
3174
- })),
3176
+ type: import_cjs$23.optional(vcpusType),
3175
3177
  description: "Number of vCPUs to allocate (each vCPU includes 2048 MB of memory)"
3176
3178
  });
3177
3179
 
@@ -6950,10 +6952,10 @@ function _usingCtx() {
6950
6952
 
6951
6953
  //#endregion
6952
6954
  //#region src/commands/login.ts
6953
- var import_cjs$19 = /* @__PURE__ */ __toESM(require_cjs());
6955
+ var import_cjs$22 = /* @__PURE__ */ __toESM(require_cjs());
6954
6956
  init_source();
6955
6957
  const debug$5 = createDebugger("sandbox:login");
6956
- const login = import_cjs$19.command({
6958
+ const login = import_cjs$22.command({
6957
6959
  name: "login",
6958
6960
  description: "Log in to the Sandbox CLI",
6959
6961
  args: {},
@@ -7163,15 +7165,15 @@ var require_dist = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/@ver
7163
7165
 
7164
7166
  //#endregion
7165
7167
  //#region src/args/auth.ts
7166
- var import_cjs$18 = /* @__PURE__ */ __toESM(require_cjs());
7168
+ var import_cjs$21 = /* @__PURE__ */ __toESM(require_cjs());
7167
7169
  init_source();
7168
7170
  var import_dist = require_dist();
7169
7171
  const debug$4 = createDebugger("sandbox:args:auth");
7170
- const token = import_cjs$18.option({
7172
+ const token = import_cjs$21.option({
7171
7173
  long: "token",
7172
7174
  description: "A Vercel authentication token. If not provided, will use the token stored in your system from `VERCEL_AUTH_TOKEN` or will start a log in process.",
7173
7175
  type: {
7174
- ...import_cjs$18.string,
7176
+ ...import_cjs$21.string,
7175
7177
  displayName: "pat_or_oidc",
7176
7178
  defaultValueIsSerializable: false,
7177
7179
  onMissing: async () => {
@@ -7314,29 +7316,29 @@ async function inferFromToken(token$1, requestedTeam) {
7314
7316
 
7315
7317
  //#endregion
7316
7318
  //#region src/args/scope.ts
7317
- var import_cjs$17 = /* @__PURE__ */ __toESM(require_cjs());
7319
+ var import_cjs$20 = /* @__PURE__ */ __toESM(require_cjs());
7318
7320
  init_source();
7319
- const project = import_cjs$17.option({
7321
+ const project = import_cjs$20.option({
7320
7322
  long: "project",
7321
7323
  type: {
7322
- ...import_cjs$17.optional(import_cjs$17.string),
7324
+ ...import_cjs$20.optional(import_cjs$20.string),
7323
7325
  displayName: "my-project"
7324
7326
  },
7325
7327
  description: "The project name or ID to associate with the command. Can be inferred from VERCEL_OIDC_TOKEN."
7326
7328
  });
7327
7329
  /** Parser for the `--team` option. */
7328
- const teamParser = import_cjs$17.option({
7330
+ const teamParser = import_cjs$20.option({
7329
7331
  long: "team",
7330
7332
  type: {
7331
- ...import_cjs$17.optional(import_cjs$17.string),
7333
+ ...import_cjs$20.optional(import_cjs$20.string),
7332
7334
  displayName: "my-team"
7333
7335
  }
7334
7336
  });
7335
7337
  /** Parser for the `--scope` option. */
7336
- const scopeParser = import_cjs$17.option({
7338
+ const scopeParser = import_cjs$20.option({
7337
7339
  long: "scope",
7338
7340
  type: {
7339
- ...import_cjs$17.optional(import_cjs$17.string),
7341
+ ...import_cjs$20.optional(import_cjs$20.string),
7340
7342
  displayName: "my-team"
7341
7343
  },
7342
7344
  description: "The scope/team to associate with the command. Can be inferred from VERCEL_OIDC_TOKEN. [alias: --team]"
@@ -7425,7 +7427,7 @@ const scope = {
7425
7427
 
7426
7428
  //#endregion
7427
7429
  //#region package.json
7428
- var version = "2.5.6";
7430
+ var version = "3.0.0-beta.10";
7429
7431
 
7430
7432
  //#endregion
7431
7433
  //#region src/error.ts
@@ -7446,6 +7448,7 @@ init_source();
7446
7448
  const sandboxClient = {
7447
7449
  get: (params) => withErrorHandling(Sandbox.get({
7448
7450
  fetch: fetchWithUserAgent,
7451
+ resume: false,
7449
7452
  ...params
7450
7453
  })),
7451
7454
  create: (params) => withErrorHandling(Sandbox.create({
@@ -7515,9 +7518,9 @@ async function writeResponseToTemp({ response, text }) {
7515
7518
 
7516
7519
  //#endregion
7517
7520
  //#region src/args/snapshot-id.ts
7518
- var import_cjs$16 = /* @__PURE__ */ __toESM(require_cjs());
7521
+ var import_cjs$19 = /* @__PURE__ */ __toESM(require_cjs());
7519
7522
  init_source();
7520
- const snapshotId = import_cjs$16.extendType(import_cjs$16.string, {
7523
+ const snapshotId = import_cjs$19.extendType(import_cjs$19.string, {
7521
7524
  displayName: "snapshot_id",
7522
7525
  description: "The ID of the snapshot",
7523
7526
  async from(s$1) {
@@ -7527,16 +7530,16 @@ const snapshotId = import_cjs$16.extendType(import_cjs$16.string, {
7527
7530
  });
7528
7531
 
7529
7532
  //#endregion
7530
- //#region src/args/sandbox-id.ts
7531
- var import_cjs$15 = /* @__PURE__ */ __toESM(require_cjs());
7533
+ //#region src/args/sandbox-name.ts
7534
+ var import_cjs$18 = /* @__PURE__ */ __toESM(require_cjs());
7532
7535
  init_source();
7533
- const sandboxId = import_cjs$15.extendType(import_cjs$15.string, {
7534
- displayName: "sandbox_id",
7535
- description: "The ID of the sandbox to execute the command in",
7536
+ const sandboxName = import_cjs$18.extendType(import_cjs$18.string, {
7537
+ displayName: "name",
7538
+ description: "The name of the sandbox",
7536
7539
  async from(s$1) {
7537
- if (!s$1.startsWith("sbx_")) throw new Error([
7538
- `Malformed sandbox ID: "${s$1}".`,
7539
- `${source_default.bold("hint:")} Sandbox IDs must start with 'sbx_' (e.g., sbx_abc123def456).`,
7540
+ if (!s$1 || s$1.trim().length === 0) throw new Error([
7541
+ `Sandbox name cannot be empty.`,
7542
+ `${source_default.bold("hint:")} Provide a sandbox name.`,
7540
7543
  "╰▶ run `sandbox list` to see available sandboxes."
7541
7544
  ].join("\n"));
7542
7545
  return s$1;
@@ -7579,13 +7582,13 @@ var require_buffer_util = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pn
7579
7582
  * @return {Buffer} The resulting buffer
7580
7583
  * @public
7581
7584
  */
7582
- function concat$1(list$2, totalLength) {
7583
- if (list$2.length === 0) return EMPTY_BUFFER$3;
7584
- if (list$2.length === 1) return list$2[0];
7585
+ function concat$1(list$3, totalLength) {
7586
+ if (list$3.length === 0) return EMPTY_BUFFER$3;
7587
+ if (list$3.length === 1) return list$3[0];
7585
7588
  const target = Buffer.allocUnsafe(totalLength);
7586
7589
  let offset = 0;
7587
- for (let i = 0; i < list$2.length; i++) {
7588
- const buf = list$2[i];
7590
+ for (let i = 0; i < list$3.length; i++) {
7591
+ const buf = list$3[i];
7589
7592
  target.set(buf, offset);
7590
7593
  offset += buf.length;
7591
7594
  }
@@ -9154,13 +9157,13 @@ var require_sender = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/ws
9154
9157
  * @param {Function} [cb] Callback
9155
9158
  * @private
9156
9159
  */
9157
- sendFrame(list$2, cb) {
9158
- if (list$2.length === 2) {
9160
+ sendFrame(list$3, cb) {
9161
+ if (list$3.length === 2) {
9159
9162
  this._socket.cork();
9160
- this._socket.write(list$2[0]);
9161
- this._socket.write(list$2[1], cb);
9163
+ this._socket.write(list$3[0]);
9164
+ this._socket.write(list$3[1], cb);
9162
9165
  this._socket.uncork();
9163
- } else this._socket.write(list$2[0], cb);
9166
+ } else this._socket.write(list$3[0], cb);
9164
9167
  }
9165
9168
  };
9166
9169
  module.exports = Sender$2;
@@ -11244,20 +11247,27 @@ function printCommand(command$1, args$4) {
11244
11247
 
11245
11248
  //#endregion
11246
11249
  //#region src/interactive-shell/extend-sandbox-timeout.ts
11247
- var import_ms$2 = /* @__PURE__ */ __toESM(require_ms());
11250
+ var import_ms$3 = /* @__PURE__ */ __toESM(require_ms());
11248
11251
  const debug$2 = createDebugger("sandbox:timeout");
11249
- const BUFFER = (0, import_ms$2.default)("10 seconds");
11252
+ const BUFFER = (0, import_ms$3.default)("10 seconds");
11250
11253
  async function extendSandboxTimeoutPeriodically(sandbox, signal) {
11251
- 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;
11252
11258
  debug$2(`next tick: ${new Date(nextTick).toISOString()}`);
11253
11259
  while (!signal.aborted) {
11254
- const timeout$1 = sandbox.createdAt.getTime() + sandbox.timeout - Date.now() - BUFFER;
11255
- if (timeout$1 > 2e3) {
11256
- debug$2(`sleeping for ${timeout$1}ms until next timeout extension`);
11257
- await setTimeout$1(timeout$1, null, { signal });
11258
- }
11259
- await sandbox.extendTimeout((0, import_ms$2.default)("5 minutes"));
11260
- const nextTick$1 = sandbox.createdAt.getTime() + sandbox.timeout;
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 });
11266
+ }
11267
+ await sandbox.extendTimeout((0, import_ms$3.default)("5 minutes"));
11268
+ const updatedTimeout = session.timeout;
11269
+ if (updatedTimeout == null) return;
11270
+ const nextTick$1 = session.createdAt.getTime() + updatedTimeout;
11261
11271
  debug$2(`extended sandbox timeout by 5 minutes. next tick: ${new Date(nextTick$1).toISOString()}`);
11262
11272
  }
11263
11273
  }
@@ -11385,11 +11395,16 @@ async function startInteractiveShell(options) {
11385
11395
  await setupSandboxEnvironment(options.sandbox, progress);
11386
11396
  progress.text = "Booting up interactive listener...";
11387
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);
11388
11399
  const waitForProcess = _usingCtx3.u(createAbortController("Connection established successfully"));
11389
11400
  listener.connection.then(() => {
11401
+ debug$1("listener.connection resolved");
11390
11402
  waitForProcess.abort();
11391
11403
  });
11392
- 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
+ });
11393
11408
  await Promise.all([throwIfCommandPrematurelyExited(command$1, waitForProcess.signal), attach({
11394
11409
  sandbox: options.sandbox,
11395
11410
  progress,
@@ -11455,7 +11470,7 @@ async function attach({ progress, listener, printCommand: printCommand$1, sandbo
11455
11470
  });
11456
11471
  extensionController.abort("client disconnected");
11457
11472
  client.close();
11458
- console.error(source_default.dim(`\n╰▶ connection to ▲ ${sandbox.sandboxId} closed.`));
11473
+ console.error(source_default.dim(`\n╰▶ connection to ▲ ${sandbox.name} closed.`));
11459
11474
  } catch (_) {
11460
11475
  _usingCtx4.e = _;
11461
11476
  } finally {
@@ -11492,6 +11507,7 @@ async function connect$1(command$1, listener, signal) {
11492
11507
  const stderrStream = _usingCtx5.u(getStderrStream());
11493
11508
  for await (const chunk of logs) if (chunk.stream === "stdout") listener.stdoutStream.write(chunk.data);
11494
11509
  else stderrStream.write(chunk.data);
11510
+ listener.stdoutStream.end();
11495
11511
  } catch (_) {
11496
11512
  _usingCtx5.e = _;
11497
11513
  } finally {
@@ -11522,9 +11538,9 @@ function getStderrStream() {
11522
11538
 
11523
11539
  //#endregion
11524
11540
  //#region src/args/key-value-pair.ts
11525
- var import_cjs$14 = /* @__PURE__ */ __toESM(require_cjs());
11541
+ var import_cjs$17 = /* @__PURE__ */ __toESM(require_cjs());
11526
11542
  init_source();
11527
- const KeyValuePair = import_cjs$14.extendType(import_cjs$14.string, {
11543
+ const KeyValuePair = import_cjs$17.extendType(import_cjs$17.string, {
11528
11544
  displayName: "key=value",
11529
11545
  async from(input) {
11530
11546
  if (!input.includes("=")) return {
@@ -11538,7 +11554,7 @@ const KeyValuePair = import_cjs$14.extendType(import_cjs$14.string, {
11538
11554
  };
11539
11555
  }
11540
11556
  });
11541
- const ObjectFromKeyValue = import_cjs$14.extendType(import_cjs$14.array(KeyValuePair), { async from(input) {
11557
+ const ObjectFromKeyValue = import_cjs$17.extendType(import_cjs$17.array(KeyValuePair), { async from(input) {
11542
11558
  const obj = Object.create(null);
11543
11559
  const missingVars = [];
11544
11560
  for (const { key, value } of input) if (value === void 0) missingVars.push(key);
@@ -11552,27 +11568,27 @@ const ObjectFromKeyValue = import_cjs$14.extendType(import_cjs$14.array(KeyValue
11552
11568
 
11553
11569
  //#endregion
11554
11570
  //#region src/commands/exec.ts
11555
- var import_cjs$13 = /* @__PURE__ */ __toESM(require_cjs());
11571
+ var import_cjs$16 = /* @__PURE__ */ __toESM(require_cjs());
11556
11572
  init_source();
11557
11573
  const args$3 = {
11558
- sandbox: import_cjs$13.positional({ type: sandboxId }),
11559
- command: import_cjs$13.positional({
11574
+ sandbox: import_cjs$16.positional({ type: sandboxName }),
11575
+ command: import_cjs$16.positional({
11560
11576
  displayName: "command",
11561
11577
  description: "The executable to invoke"
11562
11578
  }),
11563
- args: import_cjs$13.rest({
11579
+ args: import_cjs$16.rest({
11564
11580
  displayName: "args",
11565
11581
  description: "arguments to pass to the command"
11566
11582
  }),
11567
- asSudo: import_cjs$13.flag({
11583
+ asSudo: import_cjs$16.flag({
11568
11584
  long: "sudo",
11569
11585
  description: "Give extended privileges to the command."
11570
11586
  }),
11571
- interactive: import_cjs$13.flag({
11587
+ interactive: import_cjs$16.flag({
11572
11588
  long: "interactive",
11573
11589
  short: "i",
11574
11590
  description: "Run the command in a secure interactive shell",
11575
- type: import_cjs$13.extendType(import_cjs$13.boolean, {
11591
+ type: import_cjs$16.extendType(import_cjs$16.boolean, {
11576
11592
  defaultValue() {
11577
11593
  return false;
11578
11594
  },
@@ -11582,22 +11598,22 @@ const args$3 = {
11582
11598
  }
11583
11599
  })
11584
11600
  }),
11585
- skipExtendingTimeout: import_cjs$13.flag({
11601
+ skipExtendingTimeout: import_cjs$16.flag({
11586
11602
  long: "no-extend-timeout",
11587
11603
  description: "Do not extend the sandbox timeout while running an interactive command. Only affects interactive executions."
11588
11604
  }),
11589
- tty: import_cjs$13.flag({
11605
+ tty: import_cjs$16.flag({
11590
11606
  long: "tty",
11591
11607
  short: "t",
11592
11608
  description: "Allocate a tty for an interactive command. This is a no-op."
11593
11609
  }),
11594
- cwd: import_cjs$13.option({
11610
+ cwd: import_cjs$16.option({
11595
11611
  long: "workdir",
11596
11612
  short: "w",
11597
11613
  description: "The working directory to run the command in",
11598
- type: import_cjs$13.optional(import_cjs$13.string)
11614
+ type: import_cjs$16.optional(import_cjs$16.string)
11599
11615
  }),
11600
- envVars: import_cjs$13.multioption({
11616
+ envVars: import_cjs$16.multioption({
11601
11617
  long: "env",
11602
11618
  short: "e",
11603
11619
  type: ObjectFromKeyValue,
@@ -11605,28 +11621,18 @@ const args$3 = {
11605
11621
  }),
11606
11622
  scope
11607
11623
  };
11608
- const exec = import_cjs$13.command({
11624
+ const exec = import_cjs$16.command({
11609
11625
  name: "exec",
11610
11626
  description: "Execute a command in an existing sandbox",
11611
11627
  args: args$3,
11612
- async handler({ command: command$1, cwd, args: args$4, asSudo, sandbox: sandboxId$1, scope: { token: token$1, team: team$1, project: project$1 }, interactive, envVars, skipExtendingTimeout }) {
11613
- const sandbox = typeof sandboxId$1 !== "string" ? sandboxId$1 : await sandboxClient.get({
11614
- sandboxId: sandboxId$1,
11628
+ async handler({ command: command$1, cwd, args: args$4, asSudo, sandbox: sandboxName$1, scope: { token: token$1, team: team$1, project: project$1 }, interactive, envVars, skipExtendingTimeout }) {
11629
+ const sandbox = typeof sandboxName$1 !== "string" ? sandboxName$1 : await sandboxClient.get({
11630
+ name: sandboxName$1,
11615
11631
  projectId: project$1,
11616
11632
  teamId: team$1,
11617
11633
  token: token$1,
11618
11634
  __includeSystemRoutes: true
11619
11635
  });
11620
- if (!["pending", "running"].includes(sandbox.status)) {
11621
- console.error([
11622
- `Sandbox ${sandbox.sandboxId} is not available (status: ${sandbox.status}).`,
11623
- `${source_default.bold("hint:")} Only 'pending' or 'running' sandboxes can execute commands.`,
11624
- "├▶ Use `sandbox list` to check sandbox status.",
11625
- "╰▶ Use `sandbox create` to create a new sandbox."
11626
- ].join("\n"));
11627
- process.exitCode = 1;
11628
- return;
11629
- }
11630
11636
  if (!interactive) {
11631
11637
  console.error(printCommand(command$1, args$4));
11632
11638
  const result = await sandbox.runCommand({
@@ -11652,9 +11658,9 @@ const exec = import_cjs$13.command({
11652
11658
 
11653
11659
  //#endregion
11654
11660
  //#region src/args/network-policy.ts
11655
- var import_cjs$12 = /* @__PURE__ */ __toESM(require_cjs());
11661
+ var import_cjs$15 = /* @__PURE__ */ __toESM(require_cjs());
11656
11662
  init_source();
11657
- const networkPolicyMode = import_cjs$12.extendType(import_cjs$12.string, {
11663
+ const networkPolicyMode = import_cjs$15.extendType(import_cjs$15.string, {
11658
11664
  displayName: "MODE",
11659
11665
  async from(value) {
11660
11666
  const validModes = ["allow-all", "deny-all"];
@@ -11662,28 +11668,28 @@ const networkPolicyMode = import_cjs$12.extendType(import_cjs$12.string, {
11662
11668
  return value;
11663
11669
  }
11664
11670
  });
11665
- const networkPolicy = import_cjs$12.option({
11671
+ const networkPolicy = import_cjs$15.option({
11666
11672
  long: "network-policy",
11667
11673
  description: `Network policy mode: "allow-all" or "deny-all"
11668
11674
  - allow-all: sandbox can access any website/domain
11669
11675
  - deny-all: sandbox has no network access
11670
11676
  Omit this option and use --allowed-domain / --allowed-cidr / --denied-cidr for custom policies.`,
11671
- type: import_cjs$12.optional(networkPolicyMode)
11677
+ type: import_cjs$15.optional(networkPolicyMode)
11672
11678
  });
11673
- const allowedDomains = import_cjs$12.multioption({
11679
+ const allowedDomains = import_cjs$15.multioption({
11674
11680
  long: "allowed-domain",
11675
11681
  description: `Domain to allow traffic to (creates a custom network policy). Supports "*" for wildcards for a segment (e.g. '*.vercel.com', 'www.*.com'). If used as the first segment, will match any subdomain.`,
11676
- type: import_cjs$12.array(import_cjs$12.string)
11682
+ type: import_cjs$15.array(import_cjs$15.string)
11677
11683
  });
11678
- const allowedCIDRs = import_cjs$12.multioption({
11684
+ const allowedCIDRs = import_cjs$15.multioption({
11679
11685
  long: "allowed-cidr",
11680
11686
  description: `CIDR to allow traffic to (creates a custom network policy). Takes precedence over 'allowed-domain'.`,
11681
- type: import_cjs$12.array(import_cjs$12.string)
11687
+ type: import_cjs$15.array(import_cjs$15.string)
11682
11688
  });
11683
- const deniedCIDRs = import_cjs$12.multioption({
11689
+ const deniedCIDRs = import_cjs$15.multioption({
11684
11690
  long: "denied-cidr",
11685
11691
  description: `CIDR to deny traffic to (creates a custom network policy). Takes precedence over allowed domains/CIDRs.`,
11686
- type: import_cjs$12.array(import_cjs$12.string)
11692
+ type: import_cjs$15.array(import_cjs$15.string)
11687
11693
  });
11688
11694
  const networkPolicyArgs = {
11689
11695
  networkPolicy,
@@ -11722,18 +11728,27 @@ function buildNetworkPolicy(args$4) {
11722
11728
 
11723
11729
  //#endregion
11724
11730
  //#region src/commands/create.ts
11725
- var import_cjs$11 = /* @__PURE__ */ __toESM(require_cjs());
11726
- var import_ms$1 = /* @__PURE__ */ __toESM(require_ms());
11731
+ var import_cjs$14 = /* @__PURE__ */ __toESM(require_cjs());
11732
+ var import_ms$2 = /* @__PURE__ */ __toESM(require_ms());
11727
11733
  init_source();
11728
11734
  const args$2 = {
11735
+ name: import_cjs$14.option({
11736
+ long: "name",
11737
+ description: "A user-chosen name for the sandbox. It must be unique per project.",
11738
+ type: import_cjs$14.optional(import_cjs$14.string)
11739
+ }),
11740
+ nonPersistent: import_cjs$14.flag({
11741
+ long: "non-persistent",
11742
+ description: "Disable automatic restore of the filesystem between sessions."
11743
+ }),
11729
11744
  runtime,
11730
11745
  timeout,
11731
11746
  vcpus,
11732
- ports: import_cjs$11.multioption({
11747
+ ports: import_cjs$14.multioption({
11733
11748
  long: "publish-port",
11734
11749
  short: "p",
11735
11750
  description: "Publish sandbox port(s) to DOMAIN.vercel.run",
11736
- type: import_cjs$11.array(import_cjs$11.extendType(import_cjs$11.number, {
11751
+ type: import_cjs$14.array(import_cjs$14.extendType(import_cjs$14.number, {
11737
11752
  displayName: "PORT",
11738
11753
  async from(number) {
11739
11754
  if (number < 1024 || number > 65535) throw new Error([
@@ -11745,30 +11760,36 @@ const args$2 = {
11745
11760
  }
11746
11761
  }))
11747
11762
  }),
11748
- silent: import_cjs$11.flag({
11763
+ silent: import_cjs$14.flag({
11749
11764
  long: "silent",
11750
- description: "Don't write sandbox ID to stdout"
11765
+ description: "Don't write sandbox name to stdout"
11751
11766
  }),
11752
- snapshot: import_cjs$11.option({
11767
+ snapshot: import_cjs$14.option({
11753
11768
  long: "snapshot",
11754
11769
  short: "s",
11755
11770
  description: "Start the sandbox from a snapshot ID",
11756
- type: import_cjs$11.optional(snapshotId)
11771
+ type: import_cjs$14.optional(snapshotId)
11757
11772
  }),
11758
- connect: import_cjs$11.flag({
11773
+ connect: import_cjs$14.flag({
11759
11774
  long: "connect",
11760
11775
  description: "Start an interactive shell session after creating the sandbox"
11761
11776
  }),
11762
- envVars: import_cjs$11.multioption({
11777
+ envVars: import_cjs$14.multioption({
11763
11778
  long: "env",
11764
11779
  short: "e",
11765
11780
  type: ObjectFromKeyValue,
11766
11781
  description: "Default environment variables for sandbox commands"
11767
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
+ }),
11768
11789
  ...networkPolicyArgs,
11769
11790
  scope
11770
11791
  };
11771
- const create = import_cjs$11.command({
11792
+ const create = import_cjs$14.command({
11772
11793
  name: "create",
11773
11794
  description: "Create a sandbox in the specified account and project.",
11774
11795
  args: args$2,
@@ -11776,16 +11797,19 @@ const create = import_cjs$11.command({
11776
11797
  description: "Create and connect to a sandbox without a network access",
11777
11798
  command: `sandbox run --network-policy=none --connect`
11778
11799
  }],
11779
- async handler({ 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 }) {
11780
11801
  const networkPolicy$1 = buildNetworkPolicy({
11781
11802
  networkPolicy: networkPolicyMode$1,
11782
11803
  allowedDomains: allowedDomains$1,
11783
11804
  allowedCIDRs: allowedCIDRs$1,
11784
11805
  deniedCIDRs: deniedCIDRs$1
11785
11806
  });
11807
+ const persistent = !nonPersistent;
11786
11808
  const resources = vcpus$1 ? { vcpus: vcpus$1 } : void 0;
11809
+ const tagsObj = Object.keys(tags).length > 0 ? tags : void 0;
11787
11810
  const spinner = silent ? void 0 : ora("Creating sandbox...").start();
11788
11811
  const sandbox = snapshot$1 ? await sandboxClient.create({
11812
+ name,
11789
11813
  source: {
11790
11814
  type: "snapshot",
11791
11815
  snapshotId: snapshot$1
@@ -11794,21 +11818,26 @@ const create = import_cjs$11.command({
11794
11818
  projectId: scope$1.project,
11795
11819
  token: scope$1.token,
11796
11820
  ports,
11797
- timeout: (0, import_ms$1.default)(timeout$1),
11821
+ timeout: (0, import_ms$2.default)(timeout$1),
11798
11822
  resources,
11799
11823
  networkPolicy: networkPolicy$1,
11800
11824
  env: envVars,
11825
+ tags: tagsObj,
11826
+ persistent,
11801
11827
  __interactive: true
11802
11828
  }) : await sandboxClient.create({
11829
+ name,
11803
11830
  teamId: scope$1.team,
11804
11831
  projectId: scope$1.project,
11805
11832
  token: scope$1.token,
11806
11833
  ports,
11807
11834
  runtime: runtime$1,
11808
- timeout: (0, import_ms$1.default)(timeout$1),
11835
+ timeout: (0, import_ms$2.default)(timeout$1),
11809
11836
  resources,
11810
11837
  networkPolicy: networkPolicy$1,
11811
11838
  env: envVars,
11839
+ tags: tagsObj,
11840
+ persistent,
11812
11841
  __interactive: true
11813
11842
  });
11814
11843
  spinner?.stop();
@@ -11823,7 +11852,7 @@ const create = import_cjs$11.command({
11823
11852
  const projectDisplay = scope$1.projectSlug ?? scope$1.project;
11824
11853
  const hasPorts = routes.length > 0;
11825
11854
  process.stderr.write("✅ Sandbox ");
11826
- process.stdout.write(source_default.cyan(sandbox.sandboxId));
11855
+ process.stdout.write(source_default.cyan(sandbox.name));
11827
11856
  process.stderr.write(" created.\n");
11828
11857
  process.stderr.write(source_default.dim(" │ ") + "team: " + source_default.cyan(teamDisplay) + "\n");
11829
11858
  if (hasPorts) {
@@ -11862,60 +11891,113 @@ function omit(obj, ...keys) {
11862
11891
 
11863
11892
  //#endregion
11864
11893
  //#region src/commands/run.ts
11865
- var import_cjs$10 = /* @__PURE__ */ __toESM(require_cjs());
11894
+ var import_cjs$13 = /* @__PURE__ */ __toESM(require_cjs());
11866
11895
  const args$1 = {
11867
11896
  ...args$2,
11868
11897
  ...omit(args$3, "sandbox"),
11869
- removeAfterUse: import_cjs$10.flag({
11898
+ removeAfterUse: import_cjs$13.flag({
11870
11899
  long: "rm",
11871
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."
11872
11905
  })
11873
11906
  };
11874
- const run = import_cjs$10.command({
11907
+ const run = import_cjs$13.command({
11875
11908
  name: "run",
11876
11909
  description: "Create and run a command in a sandbox",
11877
11910
  args: args$1,
11878
- async handler({ removeAfterUse, ...rest$1 }) {
11879
- const sandbox = await create.handler({ ...rest$1 });
11911
+ async handler({ removeAfterUse, stopAfterUse, ...rest$1 }) {
11912
+ if (removeAfterUse && stopAfterUse) throw new Error("--rm and --stop are mutually exclusive.");
11913
+ let sandbox;
11914
+ if (rest$1.name) try {
11915
+ sandbox = await sandboxClient.get({
11916
+ name: rest$1.name,
11917
+ projectId: rest$1.scope.project,
11918
+ teamId: rest$1.scope.team,
11919
+ token: rest$1.scope.token,
11920
+ resume: true,
11921
+ __includeSystemRoutes: true
11922
+ });
11923
+ } catch (error) {
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
+ });
11928
+ else throw error;
11929
+ }
11930
+ else sandbox = await create.handler({
11931
+ ...rest$1,
11932
+ nonPersistent: rest$1.nonPersistent || removeAfterUse
11933
+ });
11880
11934
  try {
11881
11935
  await exec.handler({
11882
11936
  ...rest$1,
11883
11937
  sandbox
11884
11938
  });
11885
11939
  } finally {
11886
- if (removeAfterUse) await sandbox.stop();
11940
+ if (removeAfterUse) await sandbox.delete();
11941
+ if (stopAfterUse) await sandbox.stop();
11887
11942
  }
11888
11943
  }
11889
11944
  });
11890
11945
 
11891
11946
  //#endregion
11892
11947
  //#region src/commands/list.ts
11893
- var import_cjs$9 = /* @__PURE__ */ __toESM(require_cjs());
11948
+ var import_cjs$12 = /* @__PURE__ */ __toESM(require_cjs());
11894
11949
  init_source();
11895
- const list = import_cjs$9.command({
11950
+ const list = import_cjs$12.command({
11896
11951
  name: "list",
11897
11952
  aliases: ["ls"],
11898
11953
  description: "List all sandboxes for the specified account and project.",
11899
11954
  args: {
11900
- all: import_cjs$9.flag({
11955
+ all: import_cjs$12.flag({
11901
11956
  long: "all",
11902
11957
  short: "a",
11903
11958
  description: "Show all sandboxes (default shows just running)"
11904
11959
  }),
11960
+ namePrefix: import_cjs$12.option({
11961
+ long: "name-prefix",
11962
+ description: "Filter sandboxes by name prefix",
11963
+ type: import_cjs$12.optional(import_cjs$12.string)
11964
+ }),
11965
+ sortBy: import_cjs$12.option({
11966
+ long: "sort-by",
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
11983
+ }),
11905
11984
  scope
11906
11985
  },
11907
- async handler({ scope: { token: token$1, team: team$1, project: project$1 }, all }) {
11986
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, all, namePrefix, sortBy, sortOrder, tags }) {
11908
11987
  const sandboxes = await (async () => {
11909
11988
  try {
11910
11989
  var _usingCtx$1 = _usingCtx();
11911
11990
  const _spinner$1 = _usingCtx$1.u(acquireRelease(() => ora("Fetching sandboxes...").start(), (s$1) => s$1.stop()));
11912
- const { json } = await sandboxClient.list({
11991
+ let { sandboxes: sandboxes$1 } = await sandboxClient.list({
11913
11992
  token: token$1,
11914
11993
  teamId: team$1,
11915
11994
  projectId: project$1,
11916
- limit: 100
11995
+ limit: 50,
11996
+ ...namePrefix && { namePrefix },
11997
+ ...sortBy && { sortBy },
11998
+ ...sortOrder && { sortOrder },
11999
+ ...Object.keys(tags).length > 0 && { tags }
11917
12000
  });
11918
- let sandboxes$1 = json.sandboxes;
11919
12001
  if (!all) sandboxes$1 = sandboxes$1.filter((x) => x.status === "running");
11920
12002
  return sandboxes$1;
11921
12003
  } catch (_) {
@@ -11929,21 +12011,22 @@ const list = import_cjs$9.command({
11929
12011
  unit: "megabyte"
11930
12012
  });
11931
12013
  const columns = {
11932
- ID: { value: (s$1) => s$1.id },
12014
+ NAME: { value: (s$1) => s$1.name },
11933
12015
  STATUS: {
11934
12016
  value: (s$1) => s$1.status,
11935
12017
  color: (s$1) => SandboxStatusColor[s$1.status] ?? source_default.reset
11936
12018
  },
11937
12019
  CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
11938
- MEMORY: { value: (s$1) => memoryFormatter.format(s$1.memory) },
11939
- VCPUS: { value: (s$1) => s$1.vcpus },
11940
- RUNTIME: { value: (s$1) => s$1.runtime },
11941
- TIMEOUT: { value: (s$1) => timeAgo(s$1.createdAt + s$1.timeout) },
11942
- SNAPSHOT: { value: (s$1) => s$1.sourceSnapshotId ?? "-" }
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(", ") : "-" }
11943
12026
  };
11944
12027
  if (all) {
11945
- columns.CPU = { value: (s$1) => s$1.activeCpuDurationMs ? formatRunDuration(s$1.activeCpuDurationMs) : "-" };
11946
- columns["NETWORK (OUT/IN)"] = { value: (s$1) => s$1.networkTransfer ? `${formatBytes(s$1.networkTransfer.egress)} / ${formatBytes(s$1.networkTransfer.ingress)}` : "- / -" };
12028
+ columns.CPU = { value: (s$1) => s$1.totalActiveCpuDurationMs ? formatRunDuration(s$1.totalActiveCpuDurationMs) : "-" };
12029
+ columns["NETWORK (OUT/IN)"] = { value: (s$1) => s$1.totalEgressBytes || s$1.totalIngressBytes ? `${formatBytes(s$1.totalEgressBytes ?? 0)} / ${formatBytes(s$1.totalIngressBytes ?? 0)}` : "- / -" };
11947
12030
  }
11948
12031
  console.log(table({
11949
12032
  rows: sandboxes,
@@ -11963,8 +12046,8 @@ const SandboxStatusColor = {
11963
12046
 
11964
12047
  //#endregion
11965
12048
  //#region src/commands/connect.ts
11966
- var import_cjs$8 = /* @__PURE__ */ __toESM(require_cjs());
11967
- const connect = import_cjs$8.command({
12049
+ var import_cjs$11 = /* @__PURE__ */ __toESM(require_cjs());
12050
+ const connect = import_cjs$11.command({
11968
12051
  name: "connect",
11969
12052
  aliases: ["ssh", "shell"],
11970
12053
  description: "Start an interactive shell in an existing sandbox",
@@ -14265,42 +14348,84 @@ var Listr = class {
14265
14348
 
14266
14349
  //#endregion
14267
14350
  //#region src/commands/stop.ts
14268
- var import_cjs$7 = /* @__PURE__ */ __toESM(require_cjs());
14269
- const stop = import_cjs$7.command({
14351
+ var import_cjs$10 = /* @__PURE__ */ __toESM(require_cjs());
14352
+ const stop = import_cjs$10.command({
14270
14353
  name: "stop",
14271
- aliases: ["rm", "remove"],
14272
- description: "Stop one or more running sandboxes",
14354
+ description: "Stop the current session of one or more sandboxes",
14273
14355
  args: {
14274
- sandboxId: import_cjs$7.positional({
14275
- type: sandboxId,
14276
- description: "a sandbox ID to stop"
14356
+ sandboxName: import_cjs$10.positional({
14357
+ type: sandboxName,
14358
+ description: "A sandbox name to stop"
14277
14359
  }),
14278
- sandboxIds: import_cjs$7.restPositionals({
14279
- type: sandboxId,
14280
- description: "more sandboxes to stop"
14360
+ sandboxNames: import_cjs$10.restPositionals({
14361
+ type: sandboxName,
14362
+ description: "More sandboxes to stop"
14281
14363
  }),
14282
14364
  scope
14283
14365
  },
14284
- async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandboxId: sandboxId$1, sandboxIds }) {
14285
- await new Listr(Array.from(new Set([sandboxId$1, ...sandboxIds]), (sandboxId$2) => {
14366
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandboxName: sandboxName$1, sandboxNames }) {
14367
+ const tasks = Array.from(new Set([sandboxName$1, ...sandboxNames]), (sandboxName$2) => {
14286
14368
  return {
14287
- title: `Stopping sandbox ${sandboxId$2}`,
14369
+ title: `Stopping active session from ${sandboxName$2}`,
14288
14370
  async task() {
14289
14371
  await (await sandboxClient.get({
14290
14372
  token: token$1,
14291
14373
  teamId: team$1,
14292
14374
  projectId: project$1,
14293
- sandboxId: sandboxId$2
14375
+ name: sandboxName$2
14294
14376
  })).stop();
14295
14377
  }
14296
14378
  };
14297
- }), { concurrent: true }).run();
14379
+ });
14380
+ try {
14381
+ await new Listr(tasks, { concurrent: true }).run();
14382
+ } catch {
14383
+ process.exitCode = 1;
14384
+ }
14385
+ }
14386
+ });
14387
+
14388
+ //#endregion
14389
+ //#region src/commands/remove.ts
14390
+ var import_cjs$9 = /* @__PURE__ */ __toESM(require_cjs());
14391
+ const remove = import_cjs$9.command({
14392
+ name: "remove",
14393
+ aliases: ["rm"],
14394
+ description: "Permanently remove one or more sandboxes",
14395
+ args: {
14396
+ sandboxName: import_cjs$9.positional({
14397
+ type: sandboxName,
14398
+ description: "a sandbox name to remove"
14399
+ }),
14400
+ sandboxNames: import_cjs$9.restPositionals({
14401
+ type: sandboxName,
14402
+ description: "more sandboxes to remove"
14403
+ }),
14404
+ scope
14405
+ },
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) => ({
14408
+ title: `Removing sandbox ${name}`,
14409
+ async task() {
14410
+ await (await sandboxClient.get({
14411
+ token: token$1,
14412
+ teamId: team$1,
14413
+ projectId: project$1,
14414
+ name
14415
+ })).delete();
14416
+ }
14417
+ }));
14418
+ try {
14419
+ await new Listr(tasks, { concurrent: true }).run();
14420
+ } catch {
14421
+ process.exitCode = 1;
14422
+ }
14298
14423
  }
14299
14424
  });
14300
14425
 
14301
14426
  //#endregion
14302
14427
  //#region src/commands/cp.ts
14303
- var import_cjs$6 = /* @__PURE__ */ __toESM(require_cjs());
14428
+ var import_cjs$8 = /* @__PURE__ */ __toESM(require_cjs());
14304
14429
  init_source();
14305
14430
  const parseLocalOrRemotePath = async (input) => {
14306
14431
  const parts = input.split(":");
@@ -14308,12 +14433,12 @@ const parseLocalOrRemotePath = async (input) => {
14308
14433
  const [id, path$1] = parts;
14309
14434
  if (!id || !path$1) throw new Error([
14310
14435
  `Invalid copy path format: "${input}".`,
14311
- `${source_default.bold("hint:")} Expected format: SANDBOX_ID:PATH (e.g., sbx_abc123:/home/user/file.txt).`,
14436
+ `${source_default.bold("hint:")} Expected format: SANDBOX_NAME:PATH (e.g., my-sandbox:/home/user/file.txt).`,
14312
14437
  "╰▶ Local paths should not contain colons."
14313
14438
  ].join("\n"));
14314
14439
  return {
14315
14440
  type: "remote",
14316
- sandboxId: await sandboxId.from(id),
14441
+ sandboxName: await sandboxName.from(id),
14317
14442
  path: path$1
14318
14443
  };
14319
14444
  }
@@ -14322,20 +14447,20 @@ const parseLocalOrRemotePath = async (input) => {
14322
14447
  path: input
14323
14448
  };
14324
14449
  };
14325
- const localOrRemote = import_cjs$6.extendType(import_cjs$6.string, { from: parseLocalOrRemotePath });
14326
- const cp = import_cjs$6.command({
14450
+ const localOrRemote = import_cjs$8.extendType(import_cjs$8.string, { from: parseLocalOrRemotePath });
14451
+ const cp = import_cjs$8.command({
14327
14452
  name: "copy",
14328
14453
  description: "Copy files between your local filesystem and a remote sandbox",
14329
14454
  aliases: ["cp"],
14330
14455
  args: {
14331
- source: import_cjs$6.positional({
14456
+ source: import_cjs$8.positional({
14332
14457
  displayName: `src`,
14333
- description: `The source file to copy from local file system, or or a sandbox_id:path from a remote sandbox`,
14458
+ description: `The source file to copy from local file system, or a sandbox_name:path from a remote sandbox`,
14334
14459
  type: localOrRemote
14335
14460
  }),
14336
- dest: import_cjs$6.positional({
14461
+ dest: import_cjs$8.positional({
14337
14462
  displayName: `dst`,
14338
- description: `The destination file to copy to local file system, or or a sandbox_id:path to a remote sandbox`,
14463
+ description: `The destination file to copy to local file system, or a sandbox_name:path to a remote sandbox`,
14339
14464
  type: localOrRemote
14340
14465
  }),
14341
14466
  scope
@@ -14349,7 +14474,7 @@ const cp = import_cjs$6.command({
14349
14474
  });
14350
14475
  else {
14351
14476
  const file = await (await sandboxClient.get({
14352
- sandboxId: source.sandboxId,
14477
+ name: source.sandboxName,
14353
14478
  teamId: scope$1.team,
14354
14479
  token: scope$1.token,
14355
14480
  projectId: scope$1.project
@@ -14359,14 +14484,14 @@ const cp = import_cjs$6.command({
14359
14484
  if (!sourceFile) {
14360
14485
  if (source.type === "remote") {
14361
14486
  const dir = path.dirname(source.path);
14362
- spinner.fail([`File not found: ${source.path} in sandbox ${source.sandboxId}.`, `${source_default.bold("hint:")} Verify the file path exists using \`sandbox exec ${source.sandboxId} ls ${dir}\`.`].join("\n"));
14487
+ spinner.fail([`File not found: ${source.path} in sandbox ${source.sandboxName}.`, `${source_default.bold("hint:")} Verify the file path exists using \`sandbox exec ${source.sandboxName} ls ${dir}\`.`].join("\n"));
14363
14488
  } else spinner.fail(`Source file (${source.path}) not found.`);
14364
14489
  return;
14365
14490
  }
14366
14491
  spinner.text = `Writing to destination file (${dest.path})...`;
14367
14492
  if (dest.type === "local") await fs.writeFile(dest.path, sourceFile);
14368
14493
  else await (await sandboxClient.get({
14369
- sandboxId: dest.sandboxId,
14494
+ name: dest.sandboxName,
14370
14495
  teamId: scope$1.team,
14371
14496
  projectId: scope$1.project,
14372
14497
  token: scope$1.token
@@ -14380,10 +14505,10 @@ const cp = import_cjs$6.command({
14380
14505
 
14381
14506
  //#endregion
14382
14507
  //#region src/commands/logout.ts
14383
- var import_cjs$5 = /* @__PURE__ */ __toESM(require_cjs());
14508
+ var import_cjs$7 = /* @__PURE__ */ __toESM(require_cjs());
14384
14509
  init_source();
14385
14510
  const debug = createDebugger("sandbox:logout");
14386
- const logout = import_cjs$5.command({
14511
+ const logout = import_cjs$7.command({
14387
14512
  name: "logout",
14388
14513
  description: "Log out of the Sandbox CLI",
14389
14514
  args: {},
@@ -14402,45 +14527,45 @@ const logout = import_cjs$5.command({
14402
14527
 
14403
14528
  //#endregion
14404
14529
  //#region src/commands/snapshot.ts
14405
- var import_cjs$4 = /* @__PURE__ */ __toESM(require_cjs());
14530
+ var import_cjs$6 = /* @__PURE__ */ __toESM(require_cjs());
14406
14531
  init_source();
14407
- var import_ms = /* @__PURE__ */ __toESM(require_ms());
14532
+ var import_ms$1 = /* @__PURE__ */ __toESM(require_ms());
14408
14533
  const args = {
14409
- stop: import_cjs$4.flag({
14534
+ stop: import_cjs$6.flag({
14410
14535
  long: "stop",
14411
14536
  description: "Confirm that the sandbox will be stopped when snapshotting"
14412
14537
  }),
14413
- silent: import_cjs$4.flag({
14538
+ silent: import_cjs$6.flag({
14414
14539
  long: "silent",
14415
14540
  description: "Don't write snapshot ID to stdout"
14416
14541
  }),
14417
- expiration: import_cjs$4.option({
14542
+ expiration: import_cjs$6.option({
14418
14543
  long: "expiration",
14419
- type: import_cjs$4.optional(Duration),
14544
+ type: import_cjs$6.optional(Duration),
14420
14545
  description: "The expiration time of the snapshot. Use 0 for no expiration."
14421
14546
  }),
14422
- sandbox: import_cjs$4.positional({ type: sandboxId }),
14547
+ sandbox: import_cjs$6.positional({ type: sandboxName }),
14423
14548
  scope
14424
14549
  };
14425
- const snapshot = import_cjs$4.command({
14550
+ const snapshot = import_cjs$6.command({
14426
14551
  name: "snapshot",
14427
14552
  description: "Take a snapshot of the filesystem of a sandbox",
14428
14553
  args,
14429
- async handler({ sandbox: sandboxId$1, stop: stop$1, scope: { token: token$1, team: team$1, project: project$1 }, silent, expiration }) {
14554
+ async handler({ sandbox: sandboxName$1, stop: stop$1, scope: { token: token$1, team: team$1, project: project$1 }, silent, expiration }) {
14430
14555
  if (!stop$1) {
14431
- console.error(["Snapshotting a sandbox will automatically stop it.", `${source_default.bold("hint:")} Confirm with --stop to continue.`].join("\n"));
14556
+ console.error(["Snapshotting will stop the current session of this sandbox.", `${source_default.bold("hint:")} Confirm with --stop to continue.`].join("\n"));
14432
14557
  process.exitCode = 1;
14433
14558
  return;
14434
14559
  }
14435
- const sandbox = typeof sandboxId$1 !== "string" ? sandboxId$1 : await sandboxClient.get({
14436
- sandboxId: sandboxId$1,
14560
+ const sandbox = typeof sandboxName$1 !== "string" ? sandboxName$1 : await sandboxClient.get({
14561
+ name: sandboxName$1,
14437
14562
  projectId: project$1,
14438
14563
  teamId: team$1,
14439
14564
  token: token$1
14440
14565
  });
14441
14566
  if (!["running"].includes(sandbox.status)) {
14442
14567
  console.error([
14443
- `Sandbox ${sandbox.sandboxId} is not available (status: ${sandbox.status}).`,
14568
+ `Sandbox ${sandbox.name} is not available (status: ${sandbox.status}).`,
14444
14569
  `${source_default.bold("hint:")} Only 'running' sandboxes can be snapshotted.`,
14445
14570
  "├▶ Use `sandbox list` to check sandbox status.",
14446
14571
  "╰▶ Use `sandbox create` to create a new sandbox."
@@ -14449,33 +14574,47 @@ const snapshot = import_cjs$4.command({
14449
14574
  return;
14450
14575
  }
14451
14576
  const spinner = silent ? void 0 : ora("Creating snapshot...").start();
14452
- const snapshot$1 = await sandbox.snapshot({ expiration: expiration === void 0 ? void 0 : (0, import_ms.default)(expiration) });
14577
+ const snapshot$1 = await sandbox.snapshot({ expiration: expiration === void 0 ? void 0 : (0, import_ms$1.default)(expiration) });
14453
14578
  spinner?.succeed(`Snapshot ${snapshot$1.snapshotId} created.`);
14454
14579
  }
14455
14580
  });
14456
14581
 
14457
14582
  //#endregion
14458
14583
  //#region src/commands/snapshots.ts
14459
- var import_cjs$2 = /* @__PURE__ */ __toESM(require_cjs());
14460
- var import_cjs$3 = require_cjs();
14584
+ var import_cjs$4 = /* @__PURE__ */ __toESM(require_cjs());
14585
+ var import_cjs$5 = require_cjs();
14461
14586
  init_source();
14462
- const list$1 = import_cjs$2.command({
14587
+ const list$2 = import_cjs$4.command({
14463
14588
  name: "list",
14464
14589
  aliases: ["ls"],
14465
14590
  description: "List snapshots for the specified account and project.",
14466
- args: { scope },
14467
- 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 }) {
14468
14605
  const snapshots$1 = await (async () => {
14469
14606
  try {
14470
14607
  var _usingCtx$1 = _usingCtx();
14471
14608
  const _spinner$1 = _usingCtx$1.u(acquireRelease(() => ora("Fetching snapshots...").start(), (s$1) => s$1.stop()));
14472
- const { json } = await snapshotClient.list({
14609
+ const { snapshots: snapshots$2 } = await snapshotClient.list({
14473
14610
  token: token$1,
14474
14611
  teamId: team$1,
14475
14612
  projectId: project$1,
14476
- limit: 100
14613
+ name,
14614
+ limit: 50,
14615
+ ...sortOrder && { sortOrder }
14477
14616
  });
14478
- return json.snapshots;
14617
+ return snapshots$2;
14479
14618
  } catch (_) {
14480
14619
  _usingCtx$1.e = _;
14481
14620
  } finally {
@@ -14493,19 +14632,19 @@ const list$1 = import_cjs$2.command({
14493
14632
  CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
14494
14633
  EXPIRATION: { value: (s$1) => s$1.status === "deleted" ? source_default.gray.dim("deleted") : timeAgo(s$1.expiresAt) },
14495
14634
  SIZE: { value: (s$1) => formatBytes(s$1.sizeBytes) },
14496
- ["SOURCE SANDBOX"]: { value: (s$1) => s$1.sourceSandboxId }
14635
+ ["SOURCE SESSION"]: { value: (s$1) => s$1.sourceSessionId }
14497
14636
  }
14498
14637
  }));
14499
14638
  }
14500
14639
  });
14501
- const get = import_cjs$2.command({
14640
+ const get = import_cjs$4.command({
14502
14641
  name: "get",
14503
14642
  description: "Get details of a snapshot.",
14504
14643
  args: {
14505
14644
  scope,
14506
- snapshotId: import_cjs$2.positional({
14645
+ snapshotId: import_cjs$4.positional({
14507
14646
  type: snapshotId,
14508
- description: "snapshot ID to retrieve"
14647
+ description: "Snapshot ID to retrieve"
14509
14648
  })
14510
14649
  },
14511
14650
  async handler({ scope: { token: token$1, team: team$1, project: project$1 }, snapshotId: id }) {
@@ -14536,28 +14675,28 @@ const get = import_cjs$2.command({
14536
14675
  CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
14537
14676
  EXPIRATION: { value: (s$1) => s$1.status === "deleted" ? source_default.gray.dim("deleted") : timeAgo(s$1.expiresAt) },
14538
14677
  SIZE: { value: (s$1) => formatBytes(s$1.sizeBytes) },
14539
- ["SOURCE SANDBOX"]: { value: (s$1) => s$1.sourceSandboxId }
14678
+ ["SOURCE SESSION"]: { value: (s$1) => s$1.sourceSessionId }
14540
14679
  }
14541
14680
  }));
14542
14681
  }
14543
14682
  });
14544
- const remove = import_cjs$2.command({
14683
+ const remove$1 = import_cjs$4.command({
14545
14684
  name: "delete",
14546
14685
  aliases: ["rm", "remove"],
14547
14686
  description: "Delete one or more snapshots.",
14548
14687
  args: {
14549
- snapshotId: import_cjs$2.positional({
14688
+ snapshotId: import_cjs$4.positional({
14550
14689
  type: snapshotId,
14551
- description: "snapshot ID to delete"
14690
+ description: "Snapshot ID to delete"
14552
14691
  }),
14553
- snapshotIds: import_cjs$2.restPositionals({
14692
+ snapshotIds: import_cjs$4.restPositionals({
14554
14693
  type: snapshotId,
14555
14694
  description: "More snapshots IDs to delete"
14556
14695
  }),
14557
14696
  scope
14558
14697
  },
14559
14698
  async handler({ scope: { team: team$1, token: token$1, project: project$1 }, snapshotId: snapshotId$1, snapshotIds }) {
14560
- await new Listr(Array.from(new Set([snapshotId$1, ...snapshotIds]), (snapshotId$2) => {
14699
+ const tasks = Array.from(new Set([snapshotId$1, ...snapshotIds]), (snapshotId$2) => {
14561
14700
  return {
14562
14701
  title: `Deleting snapshot ${snapshotId$2}`,
14563
14702
  async task() {
@@ -14571,16 +14710,21 @@ const remove = import_cjs$2.command({
14571
14710
  await snapshot$1.delete();
14572
14711
  }
14573
14712
  };
14574
- }), { concurrent: true }).run();
14713
+ });
14714
+ try {
14715
+ await new Listr(tasks, { concurrent: true }).run();
14716
+ } catch {
14717
+ process.exitCode = 1;
14718
+ }
14575
14719
  }
14576
14720
  });
14577
- const snapshots = (0, import_cjs$3.subcommands)({
14721
+ const snapshots = (0, import_cjs$5.subcommands)({
14578
14722
  name: "snapshots",
14579
14723
  description: "Manage sandbox snapshots",
14580
14724
  cmds: {
14581
- list: list$1,
14725
+ list: list$2,
14582
14726
  get,
14583
- delete: remove
14727
+ delete: remove$1
14584
14728
  }
14585
14729
  });
14586
14730
  const SnapshotStatusColor = new Map([
@@ -14589,16 +14733,269 @@ const SnapshotStatusColor = new Map([
14589
14733
  ["failed", source_default.red]
14590
14734
  ]);
14591
14735
 
14736
+ //#endregion
14737
+ //#region src/commands/sessions.ts
14738
+ var import_cjs$2 = /* @__PURE__ */ __toESM(require_cjs());
14739
+ var import_cjs$3 = require_cjs();
14740
+ init_source();
14741
+ const list$1 = import_cjs$2.command({
14742
+ name: "list",
14743
+ aliases: ["ls"],
14744
+ description: "List sessions from a sandbox",
14745
+ args: {
14746
+ all: import_cjs$2.flag({
14747
+ long: "all",
14748
+ short: "a",
14749
+ description: "Show all sessions (default shows just running)"
14750
+ }),
14751
+ sandbox: import_cjs$2.positional({
14752
+ type: sandboxName,
14753
+ description: "Sandbox name to list sessions for"
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
+ }),
14760
+ scope
14761
+ },
14762
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, all, sandbox: name, sortOrder }) {
14763
+ const sandbox = await sandboxClient.get({
14764
+ name,
14765
+ projectId: project$1,
14766
+ teamId: team$1,
14767
+ token: token$1
14768
+ });
14769
+ let { sessions: sessions$1 } = await (async () => {
14770
+ try {
14771
+ var _usingCtx$1 = _usingCtx();
14772
+ const _spinner$1 = _usingCtx$1.u(acquireRelease(() => ora("Fetching sessions...").start(), (s$1) => s$1.stop()));
14773
+ return sandbox.listSessions({ ...sortOrder && { sortOrder } });
14774
+ } catch (_) {
14775
+ _usingCtx$1.e = _;
14776
+ } finally {
14777
+ _usingCtx$1.d();
14778
+ }
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
+ }
14803
+ console.log(table({
14804
+ rows: sessions$1,
14805
+ columns
14806
+ }));
14807
+ }
14808
+ });
14809
+ const sessions = (0, import_cjs$3.subcommands)({
14810
+ name: "sessions",
14811
+ description: "Manage sandbox sessions",
14812
+ cmds: { list: list$1 }
14813
+ });
14814
+ const SessionStatusColor = {
14815
+ running: source_default.cyan,
14816
+ failed: source_default.red,
14817
+ stopped: source_default.gray.dim,
14818
+ stopping: source_default.gray,
14819
+ pending: source_default.magenta,
14820
+ snapshotting: source_default.blue,
14821
+ aborted: source_default.gray.dim
14822
+ };
14823
+
14592
14824
  //#endregion
14593
14825
  //#region src/commands/config.ts
14594
14826
  var import_cjs$1 = /* @__PURE__ */ __toESM(require_cjs());
14595
14827
  init_source();
14828
+ var import_ms = /* @__PURE__ */ __toESM(require_ms());
14829
+ const vcpusCommand = import_cjs$1.command({
14830
+ name: "vcpus",
14831
+ description: "Update the vCPU count of a sandbox",
14832
+ args: {
14833
+ sandbox: import_cjs$1.positional({
14834
+ type: sandboxName,
14835
+ description: "Sandbox name to update"
14836
+ }),
14837
+ count: import_cjs$1.positional({
14838
+ type: vcpusType,
14839
+ description: "Number of vCPUs to allocate (each vCPU includes 2048 MB of memory)"
14840
+ }),
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,
14872
+ description: "The maximum duration a sandbox can run for. Example: 5m, 1h"
14873
+ }),
14874
+ scope
14875
+ },
14876
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name, duration }) {
14877
+ const sandbox = await sandboxClient.get({
14878
+ name,
14879
+ projectId: project$1,
14880
+ teamId: team$1,
14881
+ token: token$1
14882
+ });
14883
+ const spinner = ora("Updating sandbox configuration...").start();
14884
+ try {
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");
14889
+ } catch (error) {
14890
+ spinner.stop();
14891
+ throw error;
14892
+ }
14893
+ }
14894
+ });
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",
14933
+ description: "Display the current configuration of a sandbox",
14934
+ args: {
14935
+ sandbox: import_cjs$1.positional({
14936
+ type: sandboxName,
14937
+ description: "Sandbox name to inspect"
14938
+ }),
14939
+ scope
14940
+ },
14941
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name }) {
14942
+ const sandbox = await (async () => {
14943
+ try {
14944
+ var _usingCtx$1 = _usingCtx();
14945
+ const _spinner$1 = _usingCtx$1.u(acquireRelease(() => ora("Fetching sandbox configuration...").start(), (s$1) => s$1.stop()));
14946
+ return sandboxClient.get({
14947
+ name,
14948
+ projectId: project$1,
14949
+ teamId: team$1,
14950
+ token: token$1
14951
+ });
14952
+ } catch (_) {
14953
+ _usingCtx$1.e = _;
14954
+ } finally {
14955
+ _usingCtx$1.d();
14956
+ }
14957
+ })();
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(", ") : "-";
14960
+ const rows = [
14961
+ {
14962
+ field: "vCPUs",
14963
+ value: String(sandbox.vcpus ?? "-")
14964
+ },
14965
+ {
14966
+ field: "Timeout",
14967
+ value: sandbox.timeout != null ? (0, import_ms.default)(sandbox.timeout, { long: true }) : "-"
14968
+ },
14969
+ {
14970
+ field: "Persistent",
14971
+ value: String(sandbox.persistent)
14972
+ },
14973
+ {
14974
+ field: "Network policy",
14975
+ value: String(networkPolicy$1)
14976
+ },
14977
+ {
14978
+ field: "Tags",
14979
+ value: tagsDisplay
14980
+ }
14981
+ ];
14982
+ console.log(table({
14983
+ rows,
14984
+ columns: {
14985
+ FIELD: {
14986
+ value: (r) => r.field,
14987
+ color: () => source_default.bold
14988
+ },
14989
+ VALUE: { value: (r) => r.value }
14990
+ }
14991
+ }));
14992
+ }
14993
+ });
14596
14994
  const networkPolicyCommand = import_cjs$1.command({
14597
14995
  name: "network-policy",
14598
- description: `Update the network policy of a sandbox.
14599
- This will fully override the previous configuration.`,
14996
+ description: `Update the network policy of a sandbox`,
14600
14997
  args: {
14601
- sandbox: import_cjs$1.positional({ type: sandboxId }),
14998
+ sandbox: import_cjs$1.positional({ type: sandboxName }),
14602
14999
  ...networkPolicyArgs,
14603
15000
  mode: import_cjs$1.option({
14604
15001
  long: "mode",
@@ -14607,7 +15004,7 @@ const networkPolicyCommand = import_cjs$1.command({
14607
15004
  }),
14608
15005
  scope
14609
15006
  },
14610
- async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: sandboxId$1, networkPolicy: networkPolicyFlag, mode: modeFlag, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 }) {
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 }) {
14611
15008
  const networkPolicyMode$1 = resolveMode(networkPolicyFlag, modeFlag);
14612
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.`);
14613
15010
  const networkPolicy$1 = buildNetworkPolicy({
@@ -14616,28 +15013,18 @@ const networkPolicyCommand = import_cjs$1.command({
14616
15013
  allowedCIDRs: allowedCIDRs$1,
14617
15014
  deniedCIDRs: deniedCIDRs$1
14618
15015
  });
14619
- const sandbox = typeof sandboxId$1 !== "string" ? sandboxId$1 : await sandboxClient.get({
14620
- sandboxId: sandboxId$1,
15016
+ const sandbox = typeof sandboxName$1 !== "string" ? sandboxName$1 : await sandboxClient.get({
15017
+ name: sandboxName$1,
14621
15018
  projectId: project$1,
14622
15019
  teamId: team$1,
14623
15020
  token: token$1
14624
15021
  });
14625
- if (!["pending", "running"].includes(sandbox.status)) {
14626
- console.error([
14627
- `Sandbox ${sandbox.sandboxId} is not available (status: ${sandbox.status}).`,
14628
- `${source_default.bold("hint:")} Only 'pending' or 'running' sandboxes can execute commands.`,
14629
- "├▶ Use `sandbox list` to check sandbox status.",
14630
- "╰▶ Use `sandbox create` to create a new sandbox."
14631
- ].join("\n"));
14632
- process.exitCode = 1;
14633
- return;
14634
- }
14635
15022
  const spinner = ora("Updating network policy...").start();
14636
15023
  try {
14637
- const response = await sandbox.updateNetworkPolicy(networkPolicy$1);
15024
+ await sandbox.update({ networkPolicy: networkPolicy$1 });
14638
15025
  spinner.stop();
14639
- process.stderr.write("✅ Network policy updated for sandbox " + source_default.cyan(sandbox.sandboxId) + "\n");
14640
- const mode = typeof response === "string" ? response : "restricted";
15026
+ process.stderr.write("✅ Network policy updated for sandbox " + source_default.cyan(sandbox.name) + "\n");
15027
+ const mode = typeof networkPolicy$1 === "string" ? networkPolicy$1 : "restricted";
14641
15028
  process.stderr.write(source_default.dim(" ╰ ") + "mode: " + source_default.cyan(mode) + "\n");
14642
15029
  } catch (error) {
14643
15030
  spinner.stop();
@@ -14645,10 +15032,59 @@ const networkPolicyCommand = import_cjs$1.command({
14645
15032
  }
14646
15033
  }
14647
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
+ });
14648
15077
  const config = import_cjs$1.subcommands({
14649
15078
  name: "config",
14650
- description: "Update a sandbox configuration",
14651
- cmds: { "network-policy": networkPolicyCommand }
15079
+ description: "View and update sandbox configuration",
15080
+ cmds: {
15081
+ list: listCommand,
15082
+ vcpus: vcpusCommand,
15083
+ timeout: timeoutCommand,
15084
+ persistent: persistentCommand,
15085
+ "network-policy": networkPolicyCommand,
15086
+ tags: tagsCommand
15087
+ }
14652
15088
  });
14653
15089
 
14654
15090
  //#endregion
@@ -14666,9 +15102,11 @@ const app = (opts) => (0, import_cjs.subcommands)({
14666
15102
  exec,
14667
15103
  connect,
14668
15104
  stop,
15105
+ remove,
14669
15106
  run,
14670
15107
  snapshot,
14671
15108
  snapshots,
15109
+ sessions,
14672
15110
  ...!opts?.withoutAuth && {
14673
15111
  login,
14674
15112
  logout
@@ -14685,11 +15123,11 @@ const app = (opts) => (0, import_cjs.subcommands)({
14685
15123
  },
14686
15124
  {
14687
15125
  description: "Execute command in an existing sandbox",
14688
- command: `sandbox exec <sandbox-id> -- npm test`
15126
+ command: `sandbox exec <name> -- npm test`
14689
15127
  }
14690
15128
  ]
14691
15129
  });
14692
15130
 
14693
15131
  //#endregion
14694
15132
  export { source_exports as a, init_source as i, StyledError as n, require_cjs as r, app as t };
14695
- //# sourceMappingURL=app-_Rz223Ac.mjs.map
15133
+ //# sourceMappingURL=app-BAkG8Wcx.mjs.map