sandbox 3.0.0-beta.2 → 3.0.0-beta.20

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.
@@ -15,7 +15,7 @@ import childProcess, { execFile } from "node:child_process";
15
15
  import fs, { constants, writeFile } from "node:fs/promises";
16
16
  import fs$1, { createWriteStream } from "node:fs";
17
17
  import * as Auth from "@vercel/sandbox/dist/auth/index.js";
18
- import { OAuth, getAuth, pollForToken, updateAuthConfig } from "@vercel/sandbox/dist/auth/index.js";
18
+ import { OAuth, getAuth, inferScope, pollForToken, updateAuthConfig } from "@vercel/sandbox/dist/auth/index.js";
19
19
  import { EOL } from "os";
20
20
  import { z } from "zod/v4";
21
21
  import { z as z$1 } from "zod";
@@ -295,30 +295,30 @@ var init_supports_color = __esm({ "../../node_modules/.pnpm/chalk@5.6.0/node_mod
295
295
 
296
296
  //#endregion
297
297
  //#region ../../node_modules/.pnpm/chalk@5.6.0/node_modules/chalk/source/utilities.js
298
- function stringReplaceAll(string$1, substring, replacer) {
299
- let index = string$1.indexOf(substring);
300
- if (index === -1) return string$1;
298
+ function stringReplaceAll(string$2, substring, replacer) {
299
+ let index = string$2.indexOf(substring);
300
+ if (index === -1) return string$2;
301
301
  const substringLength = substring.length;
302
302
  let endIndex = 0;
303
303
  let returnValue = "";
304
304
  do {
305
- returnValue += string$1.slice(endIndex, index) + substring + replacer;
305
+ returnValue += string$2.slice(endIndex, index) + substring + replacer;
306
306
  endIndex = index + substringLength;
307
- index = string$1.indexOf(substring, endIndex);
307
+ index = string$2.indexOf(substring, endIndex);
308
308
  } while (index !== -1);
309
- returnValue += string$1.slice(endIndex);
309
+ returnValue += string$2.slice(endIndex);
310
310
  return returnValue;
311
311
  }
312
- function stringEncaseCRLFWithFirstIndex(string$1, prefix$1, postfix, index) {
312
+ function stringEncaseCRLFWithFirstIndex(string$2, prefix$1, postfix, index) {
313
313
  let endIndex = 0;
314
314
  let returnValue = "";
315
315
  do {
316
- const gotCR = string$1[index - 1] === "\r";
317
- returnValue += string$1.slice(endIndex, gotCR ? index - 1 : index) + prefix$1 + (gotCR ? "\r\n" : "\n") + postfix;
316
+ const gotCR = string$2[index - 1] === "\r";
317
+ returnValue += string$2.slice(endIndex, gotCR ? index - 1 : index) + prefix$1 + (gotCR ? "\r\n" : "\n") + postfix;
318
318
  endIndex = index + 1;
319
- index = string$1.indexOf("\n", endIndex);
319
+ index = string$2.indexOf("\n", endIndex);
320
320
  } while (index !== -1);
321
- returnValue += string$1.slice(endIndex);
321
+ returnValue += string$2.slice(endIndex);
322
322
  return returnValue;
323
323
  }
324
324
  var init_utilities = __esm({ "../../node_modules/.pnpm/chalk@5.6.0/node_modules/chalk/source/utilities.js": (() => {}) });
@@ -454,18 +454,18 @@ var init_source = __esm({ "../../node_modules/.pnpm/chalk@5.6.0/node_modules/cha
454
454
  builder[IS_EMPTY] = _isEmpty;
455
455
  return builder;
456
456
  };
457
- applyStyle = (self, string$1) => {
458
- if (self.level <= 0 || !string$1) return self[IS_EMPTY] ? "" : string$1;
457
+ applyStyle = (self, string$2) => {
458
+ if (self.level <= 0 || !string$2) return self[IS_EMPTY] ? "" : string$2;
459
459
  let styler = self[STYLER];
460
- if (styler === void 0) return string$1;
460
+ if (styler === void 0) return string$2;
461
461
  const { openAll, closeAll } = styler;
462
- if (string$1.includes("\x1B")) while (styler !== void 0) {
463
- string$1 = stringReplaceAll(string$1, styler.close, styler.open);
462
+ if (string$2.includes("\x1B")) while (styler !== void 0) {
463
+ string$2 = stringReplaceAll(string$2, styler.close, styler.open);
464
464
  styler = styler.parent;
465
465
  }
466
- const lfIndex = string$1.indexOf("\n");
467
- if (lfIndex !== -1) string$1 = stringEncaseCRLFWithFirstIndex(string$1, closeAll, openAll, lfIndex);
468
- return openAll + string$1 + closeAll;
466
+ const lfIndex = string$2.indexOf("\n");
467
+ if (lfIndex !== -1) string$2 = stringEncaseCRLFWithFirstIndex(string$2, closeAll, openAll, lfIndex);
468
+ return openAll + string$2 + closeAll;
469
469
  };
470
470
  Object.defineProperties(createChalk.prototype, styles);
471
471
  chalk = createChalk();
@@ -689,7 +689,7 @@ var require_type = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/cmd-
689
689
  exports.identity = void 0;
690
690
  exports.typeDef = typeDef;
691
691
  exports.fromFn = fromFn;
692
- exports.extendType = extendType$1;
692
+ exports.extendType = extendType$2;
693
693
  var from_1 = require_from();
694
694
  Object.defineProperty(exports, "identity", {
695
695
  enumerable: true,
@@ -721,7 +721,7 @@ var require_type = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/cmd-
721
721
  * @param base A base type from `InputA` to `OutputA`
722
722
  * @param nextTypeOrDecodingFunction Either an entire `Type<OutputA, AnyOutput>` or just a decoding function from `OutputA` to any type
723
723
  */
724
- function extendType$1(base, nextTypeOrDecodingFunction) {
724
+ function extendType$2(base, nextTypeOrDecodingFunction) {
725
725
  const { defaultValue: _defaultValue, onMissing: _onMissing, from: _from, ...t1WithoutDefault } = base;
726
726
  const t2Object = typeDef(nextTypeOrDecodingFunction);
727
727
  const t2From = fromFn(nextTypeOrDecodingFunction);
@@ -2200,8 +2200,8 @@ var require_tokenizer = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm
2200
2200
  tokens.push(token$1);
2201
2201
  overallIndex += token$1.raw.length;
2202
2202
  };
2203
- for (const [stringIndex, string$1] of (0, utils_1.enumerate)(strings)) {
2204
- const chars = [...string$1];
2203
+ for (const [stringIndex, string$2] of (0, utils_1.enumerate)(strings)) {
2204
+ const chars = [...string$2];
2205
2205
  for (let i = 0; i < chars.length; i++) if (chars[i] === "-" && chars[i + 1] === "-") {
2206
2206
  push$1({
2207
2207
  type: "longPrefix",
@@ -2997,16 +2997,16 @@ 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$26 = /* @__PURE__ */ __toESM(require_cjs());
3000
+ var import_cjs$27 = /* @__PURE__ */ __toESM(require_cjs());
3001
3001
  const runtimeType = {
3002
- ...import_cjs$26.oneOf([
3002
+ ...import_cjs$27.oneOf([
3003
3003
  "node22",
3004
3004
  "node24",
3005
3005
  "python3.13"
3006
3006
  ]),
3007
3007
  displayName: "runtime"
3008
3008
  };
3009
- const runtime = import_cjs$26.option({
3009
+ const runtime = import_cjs$27.option({
3010
3010
  long: "runtime",
3011
3011
  type: runtimeType,
3012
3012
  defaultValue: () => "node24",
@@ -3134,15 +3134,15 @@ var require_ms = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/ms@2.1
3134
3134
 
3135
3135
  //#endregion
3136
3136
  //#region src/types/duration.ts
3137
- var import_cjs$25 = require_cjs();
3137
+ var import_cjs$26 = require_cjs();
3138
3138
  init_source();
3139
- const Duration = (0, import_cjs$25.extendType)(import_cjs$25.string, {
3139
+ const Duration = (0, import_cjs$26.extendType)(import_cjs$26.string, {
3140
3140
  displayName: "num UNIT",
3141
3141
  description: "A duration, e.g. 5m, 10s, 1h",
3142
- async from(string$1) {
3143
- const match$1 = string$1.match(/^(\d+) ?(ms|milliseconds?|msecs?|s(?:econds?)?|m(?:inutes?)?|h(?:ours?)?|d(?:ays?)?)?$/);
3142
+ async from(string$2) {
3143
+ const match$1 = string$2.match(/^(\d+) ?(ms|milliseconds?|msecs?|s(?:econds?)?|m(?:inutes?)?|h(?:ours?)?|d(?:ays?)?)?$/);
3144
3144
  if (!match$1) throw new Error([
3145
- `Malformed duration: "${string$1}".`,
3145
+ `Malformed duration: "${string$2}".`,
3146
3146
  `${source_default.bold("hint:")} Use a number followed by a unit: s (seconds), m (minutes), h (hours), d (days).`,
3147
3147
  "╰▶ Examples: 30s, 5m, 2h, 1d"
3148
3148
  ].join("\n"));
@@ -3152,28 +3152,28 @@ const Duration = (0, import_cjs$25.extendType)(import_cjs$25.string, {
3152
3152
 
3153
3153
  //#endregion
3154
3154
  //#region src/args/timeout.ts
3155
- var import_cjs$24 = /* @__PURE__ */ __toESM(require_cjs());
3156
- const timeout = import_cjs$24.option({
3155
+ var import_cjs$25 = /* @__PURE__ */ __toESM(require_cjs());
3156
+ const timeout = import_cjs$25.option({
3157
3157
  long: "timeout",
3158
3158
  type: Duration,
3159
- description: "The maximum duration a sandbox can run for. Example: 5m, 1h",
3159
+ description: "The maximum duration a sandbox can run for. Example: 5m, 30m",
3160
3160
  defaultValue: () => "5 minutes",
3161
3161
  defaultValueIsSerializable: true
3162
3162
  });
3163
3163
 
3164
3164
  //#endregion
3165
3165
  //#region src/args/vcpus.ts
3166
- var import_cjs$23 = /* @__PURE__ */ __toESM(require_cjs());
3167
- const vcpusType = import_cjs$23.extendType(import_cjs$23.number, {
3166
+ var import_cjs$24 = /* @__PURE__ */ __toESM(require_cjs());
3167
+ const vcpusType = import_cjs$24.extendType(import_cjs$24.number, {
3168
3168
  displayName: "COUNT",
3169
3169
  async from(n) {
3170
3170
  if (!Number.isInteger(n) || n < 1) throw new Error(`Invalid vCPU count: ${n}. Must be a positive integer.`);
3171
3171
  return n;
3172
3172
  }
3173
3173
  });
3174
- const vcpus = import_cjs$23.option({
3174
+ const vcpus = import_cjs$24.option({
3175
3175
  long: "vcpus",
3176
- type: import_cjs$23.optional(vcpusType),
3176
+ type: import_cjs$24.optional(vcpusType),
3177
3177
  description: "Number of vCPUs to allocate (each vCPU includes 2048 MB of memory)"
3178
3178
  });
3179
3179
 
@@ -3242,7 +3242,7 @@ const formatDistanceLocale = {
3242
3242
  other: "almost {{count}} years"
3243
3243
  }
3244
3244
  };
3245
- const formatDistance$1 = (token$1, count, options) => {
3245
+ const formatDistance = (token$1, count, options) => {
3246
3246
  let result;
3247
3247
  const tokenValue = formatDistanceLocale[token$1];
3248
3248
  if (typeof tokenValue === "string") result = tokenValue;
@@ -3573,10 +3573,10 @@ const localize = {
3573
3573
  //#endregion
3574
3574
  //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/locale/_lib/buildMatchFn.js
3575
3575
  function buildMatchFn(args$4) {
3576
- return (string$1, options = {}) => {
3576
+ return (string$2, options = {}) => {
3577
3577
  const width = options.width;
3578
3578
  const matchPattern = width && args$4.matchPatterns[width] || args$4.matchPatterns[args$4.defaultMatchWidth];
3579
- const matchResult = string$1.match(matchPattern);
3579
+ const matchResult = string$2.match(matchPattern);
3580
3580
  if (!matchResult) return null;
3581
3581
  const matchedString = matchResult[0];
3582
3582
  const parsePatterns = width && args$4.parsePatterns[width] || args$4.parsePatterns[args$4.defaultParseWidth];
@@ -3584,7 +3584,7 @@ function buildMatchFn(args$4) {
3584
3584
  let value;
3585
3585
  value = args$4.valueCallback ? args$4.valueCallback(key) : key;
3586
3586
  value = options.valueCallback ? options.valueCallback(value) : value;
3587
- const rest$1 = string$1.slice(matchedString.length);
3587
+ const rest$1 = string$2.slice(matchedString.length);
3588
3588
  return {
3589
3589
  value,
3590
3590
  rest: rest$1
@@ -3601,15 +3601,15 @@ function findIndex(array$1, predicate) {
3601
3601
  //#endregion
3602
3602
  //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/locale/_lib/buildMatchPatternFn.js
3603
3603
  function buildMatchPatternFn(args$4) {
3604
- return (string$1, options = {}) => {
3605
- const matchResult = string$1.match(args$4.matchPattern);
3604
+ return (string$2, options = {}) => {
3605
+ const matchResult = string$2.match(args$4.matchPattern);
3606
3606
  if (!matchResult) return null;
3607
3607
  const matchedString = matchResult[0];
3608
- const parseResult = string$1.match(args$4.parsePattern);
3608
+ const parseResult = string$2.match(args$4.parsePattern);
3609
3609
  if (!parseResult) return null;
3610
3610
  let value = args$4.valueCallback ? args$4.valueCallback(parseResult[0]) : parseResult[0];
3611
3611
  value = options.valueCallback ? options.valueCallback(value) : value;
3612
- const rest$1 = string$1.slice(matchedString.length);
3612
+ const rest$1 = string$2.slice(matchedString.length);
3613
3613
  return {
3614
3614
  value,
3615
3615
  rest: rest$1
@@ -3764,7 +3764,7 @@ const match = {
3764
3764
  */
3765
3765
  const enUS = {
3766
3766
  code: "en-US",
3767
- formatDistance: formatDistance$1,
3767
+ formatDistance,
3768
3768
  formatLong,
3769
3769
  formatRelative,
3770
3770
  localize,
@@ -3782,6 +3782,15 @@ function getDefaultOptions() {
3782
3782
  return defaultOptions;
3783
3783
  }
3784
3784
 
3785
+ //#endregion
3786
+ //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/_lib/getRoundingMethod.js
3787
+ function getRoundingMethod(method) {
3788
+ return (number) => {
3789
+ const result = (method ? Math[method] : Math.trunc)(number);
3790
+ return result === 0 ? 0 : result;
3791
+ };
3792
+ }
3793
+
3785
3794
  //#endregion
3786
3795
  //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/constants.js
3787
3796
  /**
@@ -3815,6 +3824,18 @@ const daysInYear = 365.2425;
3815
3824
  const maxTime = Math.pow(10, 8) * 24 * 60 * 60 * 1e3;
3816
3825
  /**
3817
3826
  * @constant
3827
+ * @name millisecondsInMinute
3828
+ * @summary Milliseconds in 1 minute
3829
+ */
3830
+ const millisecondsInMinute = 6e4;
3831
+ /**
3832
+ * @constant
3833
+ * @name minutesInYear
3834
+ * @summary Minutes in 1 year.
3835
+ */
3836
+ const minutesInYear = 525600;
3837
+ /**
3838
+ * @constant
3818
3839
  * @name minutesInMonth
3819
3840
  * @summary Minutes in 1 month.
3820
3841
  */
@@ -4031,277 +4052,31 @@ function compareAsc(dateLeft, dateRight) {
4031
4052
  }
4032
4053
 
4033
4054
  //#endregion
4034
- //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/differenceInCalendarMonths.js
4035
- /**
4036
- * The {@link differenceInCalendarMonths} function options.
4037
- */
4038
- /**
4039
- * @name differenceInCalendarMonths
4040
- * @category Month Helpers
4041
- * @summary Get the number of calendar months between the given dates.
4042
- *
4043
- * @description
4044
- * Get the number of calendar months between the given dates.
4045
- *
4046
- * @param laterDate - The later date
4047
- * @param earlierDate - The earlier date
4048
- * @param options - An object with options
4049
- *
4050
- * @returns The number of calendar months
4051
- *
4052
- * @example
4053
- * // How many calendar months are between 31 January 2014 and 1 September 2014?
4054
- * const result = differenceInCalendarMonths(
4055
- * new Date(2014, 8, 1),
4056
- * new Date(2014, 0, 31)
4057
- * )
4058
- * //=> 8
4059
- */
4060
- function differenceInCalendarMonths(laterDate, earlierDate, options) {
4061
- const [laterDate_, earlierDate_] = normalizeDates(options?.in, laterDate, earlierDate);
4062
- const yearsDiff = laterDate_.getFullYear() - earlierDate_.getFullYear();
4063
- const monthsDiff = laterDate_.getMonth() - earlierDate_.getMonth();
4064
- return yearsDiff * 12 + monthsDiff;
4065
- }
4066
-
4067
- //#endregion
4068
- //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/endOfDay.js
4069
- /**
4070
- * The {@link endOfDay} function options.
4071
- */
4072
- /**
4073
- * @name endOfDay
4074
- * @category Day Helpers
4075
- * @summary Return the end of a day for the given date.
4076
- *
4077
- * @description
4078
- * Return the end of a day for the given date.
4079
- * The result will be in the local timezone.
4080
- *
4081
- * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
4082
- * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
4083
- *
4084
- * @param date - The original date
4085
- * @param options - An object with options
4086
- *
4087
- * @returns The end of a day
4088
- *
4089
- * @example
4090
- * // The end of a day for 2 September 2014 11:55:00:
4091
- * const result = endOfDay(new Date(2014, 8, 2, 11, 55, 0))
4092
- * //=> Tue Sep 02 2014 23:59:59.999
4093
- */
4094
- function endOfDay(date, options) {
4095
- const _date = toDate(date, options?.in);
4096
- _date.setHours(23, 59, 59, 999);
4097
- return _date;
4098
- }
4099
-
4100
- //#endregion
4101
- //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/endOfMonth.js
4102
- /**
4103
- * The {@link endOfMonth} function options.
4104
- */
4105
- /**
4106
- * @name endOfMonth
4107
- * @category Month Helpers
4108
- * @summary Return the end of a month for the given date.
4109
- *
4110
- * @description
4111
- * Return the end of a month for the given date.
4112
- * The result will be in the local timezone.
4113
- *
4114
- * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
4115
- * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
4116
- *
4117
- * @param date - The original date
4118
- * @param options - An object with options
4119
- *
4120
- * @returns The end of a month
4121
- *
4122
- * @example
4123
- * // The end of a month for 2 September 2014 11:55:00:
4124
- * const result = endOfMonth(new Date(2014, 8, 2, 11, 55, 0))
4125
- * //=> Tue Sep 30 2014 23:59:59.999
4126
- */
4127
- function endOfMonth(date, options) {
4128
- const _date = toDate(date, options?.in);
4129
- const month = _date.getMonth();
4130
- _date.setFullYear(_date.getFullYear(), month + 1, 0);
4131
- _date.setHours(23, 59, 59, 999);
4132
- return _date;
4133
- }
4134
-
4135
- //#endregion
4136
- //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/isLastDayOfMonth.js
4137
- /**
4138
- * @name isLastDayOfMonth
4139
- * @category Month Helpers
4140
- * @summary Is the given date the last day of a month?
4141
- *
4142
- * @description
4143
- * Is the given date the last day of a month?
4144
- *
4145
- * @param date - The date to check
4146
- * @param options - An object with options
4147
- *
4148
- * @returns The date is the last day of a month
4149
- *
4150
- * @example
4151
- * // Is 28 February 2014 the last day of a month?
4152
- * const result = isLastDayOfMonth(new Date(2014, 1, 28))
4153
- * //=> true
4154
- */
4155
- function isLastDayOfMonth(date, options) {
4156
- const _date = toDate(date, options?.in);
4157
- return +endOfDay(_date, options) === +endOfMonth(_date, options);
4158
- }
4159
-
4160
- //#endregion
4161
- //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/differenceInMonths.js
4162
- /**
4163
- * The {@link differenceInMonths} function options.
4164
- */
4165
- /**
4166
- * @name differenceInMonths
4167
- * @category Month Helpers
4168
- * @summary Get the number of full months between the given dates.
4169
- *
4170
- * @param laterDate - The later date
4171
- * @param earlierDate - The earlier date
4172
- * @param options - An object with options
4173
- *
4174
- * @returns The number of full months
4175
- *
4176
- * @example
4177
- * // How many full months are between 31 January 2014 and 1 September 2014?
4178
- * const result = differenceInMonths(new Date(2014, 8, 1), new Date(2014, 0, 31))
4179
- * //=> 7
4180
- */
4181
- function differenceInMonths(laterDate, earlierDate, options) {
4182
- const [laterDate_, workingLaterDate, earlierDate_] = normalizeDates(options?.in, laterDate, laterDate, earlierDate);
4183
- const sign = compareAsc(workingLaterDate, earlierDate_);
4184
- const difference = Math.abs(differenceInCalendarMonths(workingLaterDate, earlierDate_));
4185
- if (difference < 1) return 0;
4186
- if (workingLaterDate.getMonth() === 1 && workingLaterDate.getDate() > 27) workingLaterDate.setDate(30);
4187
- workingLaterDate.setMonth(workingLaterDate.getMonth() - sign * difference);
4188
- let isLastMonthNotFull = compareAsc(workingLaterDate, earlierDate_) === -sign;
4189
- if (isLastDayOfMonth(laterDate_) && difference === 1 && compareAsc(laterDate_, earlierDate_) === 1) isLastMonthNotFull = false;
4190
- const result = sign * (difference - +isLastMonthNotFull);
4191
- return result === 0 ? 0 : result;
4192
- }
4193
-
4194
- //#endregion
4195
- //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/_lib/getRoundingMethod.js
4196
- function getRoundingMethod(method) {
4197
- return (number) => {
4198
- const result = (method ? Math[method] : Math.trunc)(number);
4199
- return result === 0 ? 0 : result;
4200
- };
4201
- }
4202
-
4203
- //#endregion
4204
- //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/differenceInMilliseconds.js
4055
+ //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/formatDistanceStrict.js
4205
4056
  /**
4206
- * @name differenceInMilliseconds
4207
- * @category Millisecond Helpers
4208
- * @summary Get the number of milliseconds between the given dates.
4209
- *
4210
- * @description
4211
- * Get the number of milliseconds between the given dates.
4212
- *
4213
- * @param laterDate - The later date
4214
- * @param earlierDate - The earlier date
4215
- *
4216
- * @returns The number of milliseconds
4217
- *
4218
- * @example
4219
- * // How many milliseconds are between
4220
- * // 2 July 2014 12:30:20.600 and 2 July 2014 12:30:21.700?
4221
- * const result = differenceInMilliseconds(
4222
- * new Date(2014, 6, 2, 12, 30, 21, 700),
4223
- * new Date(2014, 6, 2, 12, 30, 20, 600)
4224
- * )
4225
- * //=> 1100
4057
+ * The {@link formatDistanceStrict} function options.
4226
4058
  */
4227
- function differenceInMilliseconds(laterDate, earlierDate) {
4228
- return +toDate(laterDate) - +toDate(earlierDate);
4229
- }
4230
-
4231
- //#endregion
4232
- //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/differenceInSeconds.js
4233
4059
  /**
4234
- * The {@link differenceInSeconds} function options.
4060
+ * The unit used to format the distance in {@link formatDistanceStrict}.
4235
4061
  */
4236
4062
  /**
4237
- * @name differenceInSeconds
4238
- * @category Second Helpers
4239
- * @summary Get the number of seconds between the given dates.
4240
- *
4241
- * @description
4242
- * Get the number of seconds between the given dates.
4243
- *
4244
- * @param laterDate - The later date
4245
- * @param earlierDate - The earlier date
4246
- * @param options - An object with options.
4247
- *
4248
- * @returns The number of seconds
4249
- *
4250
- * @example
4251
- * // How many seconds are between
4252
- * // 2 July 2014 12:30:07.999 and 2 July 2014 12:30:20.000?
4253
- * const result = differenceInSeconds(
4254
- * new Date(2014, 6, 2, 12, 30, 20, 0),
4255
- * new Date(2014, 6, 2, 12, 30, 7, 999)
4256
- * )
4257
- * //=> 12
4258
- */
4259
- function differenceInSeconds(laterDate, earlierDate, options) {
4260
- const diff = differenceInMilliseconds(laterDate, earlierDate) / 1e3;
4261
- return getRoundingMethod(options?.roundingMethod)(diff);
4262
- }
4263
-
4264
- //#endregion
4265
- //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/formatDistance.js
4266
- /**
4267
- * The {@link formatDistance} function options.
4268
- */
4269
- /**
4270
- * @name formatDistance
4063
+ * @name formatDistanceStrict
4271
4064
  * @category Common Helpers
4272
4065
  * @summary Return the distance between the given dates in words.
4273
4066
  *
4274
4067
  * @description
4275
- * Return the distance between the given dates in words.
4068
+ * Return the distance between the given dates in words, using strict units.
4069
+ * This is like `formatDistance`, but does not use helpers like 'almost', 'over',
4070
+ * 'less than' and the like.
4276
4071
  *
4277
- * | Distance between dates | Result |
4278
- * |-------------------------------------------------------------------|---------------------|
4279
- * | 0 ... 30 secs | less than a minute |
4280
- * | 30 secs ... 1 min 30 secs | 1 minute |
4281
- * | 1 min 30 secs ... 44 mins 30 secs | [2..44] minutes |
4282
- * | 44 mins ... 30 secs ... 89 mins 30 secs | about 1 hour |
4283
- * | 89 mins 30 secs ... 23 hrs 59 mins 30 secs | about [2..24] hours |
4284
- * | 23 hrs 59 mins 30 secs ... 41 hrs 59 mins 30 secs | 1 day |
4285
- * | 41 hrs 59 mins 30 secs ... 29 days 23 hrs 59 mins 30 secs | [2..30] days |
4286
- * | 29 days 23 hrs 59 mins 30 secs ... 44 days 23 hrs 59 mins 30 secs | about 1 month |
4287
- * | 44 days 23 hrs 59 mins 30 secs ... 59 days 23 hrs 59 mins 30 secs | about 2 months |
4288
- * | 59 days 23 hrs 59 mins 30 secs ... 1 yr | [2..12] months |
4289
- * | 1 yr ... 1 yr 3 months | about 1 year |
4290
- * | 1 yr 3 months ... 1 yr 9 month s | over 1 year |
4291
- * | 1 yr 9 months ... 2 yrs | almost 2 years |
4292
- * | N yrs ... N yrs 3 months | about N years |
4293
- * | N yrs 3 months ... N yrs 9 months | over N years |
4294
- * | N yrs 9 months ... N+1 yrs | almost N+1 years |
4295
- *
4296
- * With `options.includeSeconds == true`:
4297
- * | Distance between dates | Result |
4298
- * |------------------------|----------------------|
4299
- * | 0 secs ... 5 secs | less than 5 seconds |
4300
- * | 5 secs ... 10 secs | less than 10 seconds |
4301
- * | 10 secs ... 20 secs | less than 20 seconds |
4302
- * | 20 secs ... 40 secs | half a minute |
4303
- * | 40 secs ... 60 secs | less than a minute |
4304
- * | 60 secs ... 90 secs | 1 minute |
4072
+ * | Distance between dates | Result |
4073
+ * |------------------------|---------------------|
4074
+ * | 0 ... 59 secs | [0..59] seconds |
4075
+ * | 1 ... 59 mins | [1..59] minutes |
4076
+ * | 1 ... 23 hrs | [1..23] hours |
4077
+ * | 1 ... 29 days | [1..29] days |
4078
+ * | 1 ... 11 months | [1..11] months |
4079
+ * | 1 ... N years | [1..N] years |
4305
4080
  *
4306
4081
  * @param laterDate - The date
4307
4082
  * @param earlierDate - The date to compare with
@@ -4311,43 +4086,59 @@ function differenceInSeconds(laterDate, earlierDate, options) {
4311
4086
  *
4312
4087
  * @throws `date` must not be Invalid Date
4313
4088
  * @throws `baseDate` must not be Invalid Date
4089
+ * @throws `options.unit` must be 'second', 'minute', 'hour', 'day', 'month' or 'year'
4314
4090
  * @throws `options.locale` must contain `formatDistance` property
4315
4091
  *
4316
4092
  * @example
4317
4093
  * // What is the distance between 2 July 2014 and 1 January 2015?
4318
- * const result = formatDistance(new Date(2014, 6, 2), new Date(2015, 0, 1))
4094
+ * const result = formatDistanceStrict(new Date(2014, 6, 2), new Date(2015, 0, 2))
4319
4095
  * //=> '6 months'
4320
4096
  *
4321
4097
  * @example
4322
4098
  * // What is the distance between 1 January 2015 00:00:15
4323
- * // and 1 January 2015 00:00:00, including seconds?
4324
- * const result = formatDistance(
4099
+ * // and 1 January 2015 00:00:00?
4100
+ * const result = formatDistanceStrict(
4325
4101
  * new Date(2015, 0, 1, 0, 0, 15),
4326
- * new Date(2015, 0, 1, 0, 0, 0),
4327
- * { includeSeconds: true }
4102
+ * new Date(2015, 0, 1, 0, 0, 0)
4328
4103
  * )
4329
- * //=> 'less than 20 seconds'
4104
+ * //=> '15 seconds'
4330
4105
  *
4331
4106
  * @example
4332
4107
  * // What is the distance from 1 January 2016
4333
4108
  * // to 1 January 2015, with a suffix?
4334
- * const result = formatDistance(new Date(2015, 0, 1), new Date(2016, 0, 1), {
4109
+ * const result = formatDistanceStrict(new Date(2015, 0, 1), new Date(2016, 0, 1), {
4335
4110
  * addSuffix: true
4336
4111
  * })
4337
- * //=> 'about 1 year ago'
4112
+ * //=> '1 year ago'
4113
+ *
4114
+ * @example
4115
+ * // What is the distance from 1 January 2016
4116
+ * // to 1 January 2015, in minutes?
4117
+ * const result = formatDistanceStrict(new Date(2016, 0, 1), new Date(2015, 0, 1), {
4118
+ * unit: 'minute'
4119
+ * })
4120
+ * //=> '525600 minutes'
4121
+ *
4122
+ * @example
4123
+ * // What is the distance from 1 January 2015
4124
+ * // to 28 January 2015, in months, rounded up?
4125
+ * const result = formatDistanceStrict(new Date(2015, 0, 28), new Date(2015, 0, 1), {
4126
+ * unit: 'month',
4127
+ * roundingMethod: 'ceil'
4128
+ * })
4129
+ * //=> '1 month'
4338
4130
  *
4339
4131
  * @example
4340
4132
  * // What is the distance between 1 August 2016 and 1 January 2015 in Esperanto?
4341
4133
  * import { eoLocale } from 'date-fns/locale/eo'
4342
- * const result = formatDistance(new Date(2016, 7, 1), new Date(2015, 0, 1), {
4134
+ * const result = formatDistanceStrict(new Date(2016, 7, 1), new Date(2015, 0, 1), {
4343
4135
  * locale: eoLocale
4344
4136
  * })
4345
- * //=> 'pli ol 1 jaro'
4137
+ * //=> '1 jaro'
4346
4138
  */
4347
- function formatDistance(laterDate, earlierDate, options) {
4139
+ function formatDistanceStrict(laterDate, earlierDate, options) {
4348
4140
  const defaultOptions$1 = getDefaultOptions();
4349
4141
  const locale = options?.locale ?? defaultOptions$1.locale ?? enUS;
4350
- const minutesInAlmostTwoDays = 2520;
4351
4142
  const comparison = compareAsc(laterDate, earlierDate);
4352
4143
  if (isNaN(comparison)) throw new RangeError("Invalid time value");
4353
4144
  const localizeOptions = Object.assign({}, options, {
@@ -4355,41 +4146,37 @@ function formatDistance(laterDate, earlierDate, options) {
4355
4146
  comparison
4356
4147
  });
4357
4148
  const [laterDate_, earlierDate_] = normalizeDates(options?.in, ...comparison > 0 ? [earlierDate, laterDate] : [laterDate, earlierDate]);
4358
- const seconds = differenceInSeconds(earlierDate_, laterDate_);
4359
- const offsetInSeconds = (getTimezoneOffsetInMilliseconds(earlierDate_) - getTimezoneOffsetInMilliseconds(laterDate_)) / 1e3;
4360
- const minutes = Math.round((seconds - offsetInSeconds) / 60);
4361
- let months;
4362
- if (minutes < 2) if (options?.includeSeconds) if (seconds < 5) return locale.formatDistance("lessThanXSeconds", 5, localizeOptions);
4363
- else if (seconds < 10) return locale.formatDistance("lessThanXSeconds", 10, localizeOptions);
4364
- else if (seconds < 20) return locale.formatDistance("lessThanXSeconds", 20, localizeOptions);
4365
- else if (seconds < 40) return locale.formatDistance("halfAMinute", 0, localizeOptions);
4366
- else if (seconds < 60) return locale.formatDistance("lessThanXMinutes", 1, localizeOptions);
4367
- else return locale.formatDistance("xMinutes", 1, localizeOptions);
4368
- else if (minutes === 0) return locale.formatDistance("lessThanXMinutes", 1, localizeOptions);
4369
- else return locale.formatDistance("xMinutes", minutes, localizeOptions);
4370
- else if (minutes < 45) return locale.formatDistance("xMinutes", minutes, localizeOptions);
4371
- else if (minutes < 90) return locale.formatDistance("aboutXHours", 1, localizeOptions);
4372
- else if (minutes < minutesInDay) {
4373
- const hours = Math.round(minutes / 60);
4374
- return locale.formatDistance("aboutXHours", hours, localizeOptions);
4375
- } else if (minutes < minutesInAlmostTwoDays) return locale.formatDistance("xDays", 1, localizeOptions);
4376
- else if (minutes < minutesInMonth) {
4377
- const days = Math.round(minutes / minutesInDay);
4149
+ const roundingMethod = getRoundingMethod(options?.roundingMethod ?? "round");
4150
+ const milliseconds = earlierDate_.getTime() - laterDate_.getTime();
4151
+ const minutes = milliseconds / millisecondsInMinute;
4152
+ const dstNormalizedMinutes = (milliseconds - (getTimezoneOffsetInMilliseconds(earlierDate_) - getTimezoneOffsetInMilliseconds(laterDate_))) / millisecondsInMinute;
4153
+ const defaultUnit = options?.unit;
4154
+ let unit;
4155
+ if (!defaultUnit) if (minutes < 1) unit = "second";
4156
+ else if (minutes < 60) unit = "minute";
4157
+ else if (minutes < minutesInDay) unit = "hour";
4158
+ else if (dstNormalizedMinutes < minutesInMonth) unit = "day";
4159
+ else if (dstNormalizedMinutes < minutesInYear) unit = "month";
4160
+ else unit = "year";
4161
+ else unit = defaultUnit;
4162
+ if (unit === "second") {
4163
+ const seconds = roundingMethod(milliseconds / 1e3);
4164
+ return locale.formatDistance("xSeconds", seconds, localizeOptions);
4165
+ } else if (unit === "minute") {
4166
+ const roundedMinutes = roundingMethod(minutes);
4167
+ return locale.formatDistance("xMinutes", roundedMinutes, localizeOptions);
4168
+ } else if (unit === "hour") {
4169
+ const hours = roundingMethod(minutes / 60);
4170
+ return locale.formatDistance("xHours", hours, localizeOptions);
4171
+ } else if (unit === "day") {
4172
+ const days = roundingMethod(dstNormalizedMinutes / minutesInDay);
4378
4173
  return locale.formatDistance("xDays", days, localizeOptions);
4379
- } else if (minutes < minutesInMonth * 2) {
4380
- months = Math.round(minutes / minutesInMonth);
4381
- return locale.formatDistance("aboutXMonths", months, localizeOptions);
4382
- }
4383
- months = differenceInMonths(earlierDate_, laterDate_);
4384
- if (months < 12) {
4385
- const nearestMonth = Math.round(minutes / minutesInMonth);
4386
- return locale.formatDistance("xMonths", nearestMonth, localizeOptions);
4174
+ } else if (unit === "month") {
4175
+ const months = roundingMethod(dstNormalizedMinutes / minutesInMonth);
4176
+ return months === 12 && defaultUnit !== "month" ? locale.formatDistance("xYears", 1, localizeOptions) : locale.formatDistance("xMonths", months, localizeOptions);
4387
4177
  } else {
4388
- const monthsSinceStartOfYear = months % 12;
4389
- const years = Math.trunc(months / 12);
4390
- if (monthsSinceStartOfYear < 3) return locale.formatDistance("aboutXYears", years, localizeOptions);
4391
- else if (monthsSinceStartOfYear < 9) return locale.formatDistance("overXYears", years, localizeOptions);
4392
- else return locale.formatDistance("almostXYears", years + 1, localizeOptions);
4178
+ const years = roundingMethod(dstNormalizedMinutes / minutesInYear);
4179
+ return locale.formatDistance("xYears", years, localizeOptions);
4393
4180
  }
4394
4181
  }
4395
4182
 
@@ -4421,7 +4208,7 @@ function formatBytes(bytes) {
4421
4208
  }
4422
4209
  function timeAgo(date) {
4423
4210
  if (date === void 0) return "-";
4424
- return formatDistance(date, /* @__PURE__ */ new Date(), { addSuffix: true }).replace("about ", "").replace("less than ", "");
4211
+ return formatDistanceStrict(date, /* @__PURE__ */ new Date(), { addSuffix: true });
4425
4212
  }
4426
4213
  function table(opts) {
4427
4214
  const titles = Object.keys(opts.columns);
@@ -4447,6 +4234,19 @@ function formatRunDuration(d$1) {
4447
4234
  if (d$1 < 1e3) return `${d$1}ms`;
4448
4235
  return `${d$1 / 1e3}s`;
4449
4236
  }
4237
+ function formatNextCursorHint(cursor) {
4238
+ const args$4 = process.argv.slice(2);
4239
+ const filtered = [];
4240
+ for (let i = 0; i < args$4.length; i++) {
4241
+ if (args$4[i] === "--cursor") {
4242
+ i++;
4243
+ continue;
4244
+ }
4245
+ if (args$4[i].startsWith("--cursor=")) continue;
4246
+ filtered.push(args$4[i]);
4247
+ }
4248
+ return `\nMore results: sandbox ${filtered.join(" ")} --cursor ${cursor}`;
4249
+ }
4450
4250
 
4451
4251
  //#endregion
4452
4252
  //#region ../../node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.js
@@ -4651,7 +4451,7 @@ async function defaultBrowser$1(_execFileAsync = execFileAsync$1) {
4651
4451
  //#endregion
4652
4452
  //#region ../../node_modules/.pnpm/default-browser@5.2.1/node_modules/default-browser/index.js
4653
4453
  const execFileAsync = promisify(execFile);
4654
- const titleize = (string$1) => string$1.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase());
4454
+ const titleize = (string$2) => string$2.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase());
4655
4455
  async function defaultBrowser() {
4656
4456
  if (process$1.platform === "darwin") {
4657
4457
  const id = await defaultBrowserId();
@@ -6509,9 +6309,9 @@ function ansiRegex({ onlyFirst = false } = {}) {
6509
6309
  //#endregion
6510
6310
  //#region ../../node_modules/.pnpm/strip-ansi@7.1.0/node_modules/strip-ansi/index.js
6511
6311
  const regex = ansiRegex();
6512
- function stripAnsi(string$1) {
6513
- if (typeof string$1 !== "string") throw new TypeError(`Expected a \`string\`, got \`${typeof string$1}\``);
6514
- return string$1.replace(regex, "");
6312
+ function stripAnsi(string$2) {
6313
+ if (typeof string$2 !== "string") throw new TypeError(`Expected a \`string\`, got \`${typeof string$2}\``);
6314
+ return string$2.replace(regex, "");
6515
6315
  }
6516
6316
 
6517
6317
  //#endregion
@@ -6890,7 +6690,7 @@ function createAbortController(reason) {
6890
6690
  signal: controller.signal,
6891
6691
  ignoreInterruptions: ignoreAbortErrors(controller.signal)
6892
6692
  };
6893
- }, (c) => c.abort(reason));
6693
+ }, (c$1) => c$1.abort(reason));
6894
6694
  }
6895
6695
 
6896
6696
  //#endregion
@@ -6952,10 +6752,10 @@ function _usingCtx() {
6952
6752
 
6953
6753
  //#endregion
6954
6754
  //#region src/commands/login.ts
6955
- var import_cjs$22 = /* @__PURE__ */ __toESM(require_cjs());
6755
+ var import_cjs$23 = /* @__PURE__ */ __toESM(require_cjs());
6956
6756
  init_source();
6957
6757
  const debug$5 = createDebugger("sandbox:login");
6958
- const login = import_cjs$22.command({
6758
+ const login = import_cjs$23.command({
6959
6759
  name: "login",
6960
6760
  description: "Log in to the Sandbox CLI",
6961
6761
  args: {},
@@ -7019,7 +6819,15 @@ const login = import_cjs$22.command({
7019
6819
  if (error) {
7020
6820
  spinner.fail(`${source_default.red("error:")} ${error.message}`);
7021
6821
  process.exitCode = 1;
7022
- } else spinner.succeed(`${source_default.cyan("Congratulations!")} You are now signed in.`);
6822
+ } else {
6823
+ spinner.succeed(`${source_default.cyan("Congratulations!")} You are now signed in.`);
6824
+ const auth = getAuth();
6825
+ if (auth?.token) try {
6826
+ const { teamId, teamSlug, projectId, projectSlug } = await inferScope({ token: auth.token });
6827
+ process.stderr.write(source_default.dim(" │ ") + "team: " + source_default.cyan(teamSlug ?? teamId) + "\n");
6828
+ process.stderr.write(source_default.dim(" ╰ ") + "project: " + source_default.cyan(projectSlug ?? projectId) + "\n");
6829
+ } catch {}
6830
+ }
7023
6831
  } catch (_) {
7024
6832
  _usingCtx$1.e = _;
7025
6833
  } finally {
@@ -7165,15 +6973,15 @@ var require_dist = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/@ver
7165
6973
 
7166
6974
  //#endregion
7167
6975
  //#region src/args/auth.ts
7168
- var import_cjs$21 = /* @__PURE__ */ __toESM(require_cjs());
6976
+ var import_cjs$22 = /* @__PURE__ */ __toESM(require_cjs());
7169
6977
  init_source();
7170
6978
  var import_dist = require_dist();
7171
6979
  const debug$4 = createDebugger("sandbox:args:auth");
7172
- const token = import_cjs$21.option({
6980
+ const token = import_cjs$22.option({
7173
6981
  long: "token",
7174
6982
  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.",
7175
6983
  type: {
7176
- ...import_cjs$21.string,
6984
+ ...import_cjs$22.string,
7177
6985
  displayName: "pat_or_oidc",
7178
6986
  defaultValueIsSerializable: false,
7179
6987
  onMissing: async () => {
@@ -7244,8 +7052,8 @@ const ProjectConfiguration = jsonCodec(z.object({
7244
7052
  function readProjectConfiguration(cwd) {
7245
7053
  try {
7246
7054
  const pathname = path.join(cwd, ".vercel", "project.json");
7247
- const string$1 = fs$1.readFileSync(pathname, "utf8");
7248
- return ProjectConfiguration.decode(string$1);
7055
+ const string$2 = fs$1.readFileSync(pathname, "utf8");
7056
+ return ProjectConfiguration.decode(string$2);
7249
7057
  } catch {
7250
7058
  return null;
7251
7059
  }
@@ -7254,7 +7062,7 @@ function readProjectConfiguration(cwd) {
7254
7062
  //#endregion
7255
7063
  //#region src/util/infer-scope.ts
7256
7064
  const debug$3 = createDebugger("sandbox:scope");
7257
- async function inferScope({ token: token$1, team: team$1 }) {
7065
+ async function inferScope$1({ token: token$1, team: team$1 }) {
7258
7066
  const jwt = z.jwt().safeParse(token$1);
7259
7067
  if (jwt.success) {
7260
7068
  debug$3("trying to infer scope from OIDC JWT");
@@ -7302,43 +7110,43 @@ async function inferFromJwt(jwt) {
7302
7110
  };
7303
7111
  }
7304
7112
  async function inferFromToken(token$1, requestedTeam) {
7305
- const { teamId, projectId } = await Auth.inferScope({
7113
+ const { teamId, teamSlug, projectId, projectSlug } = await Auth.inferScope({
7306
7114
  token: token$1,
7307
7115
  teamId: requestedTeam
7308
7116
  });
7309
7117
  return {
7310
7118
  owner: teamId,
7311
7119
  project: projectId,
7312
- ownerSlug: teamId,
7313
- projectSlug: projectId
7120
+ ownerSlug: teamSlug ?? teamId,
7121
+ projectSlug: projectSlug ?? projectId
7314
7122
  };
7315
7123
  }
7316
7124
 
7317
7125
  //#endregion
7318
7126
  //#region src/args/scope.ts
7319
- var import_cjs$20 = /* @__PURE__ */ __toESM(require_cjs());
7127
+ var import_cjs$21 = /* @__PURE__ */ __toESM(require_cjs());
7320
7128
  init_source();
7321
- const project = import_cjs$20.option({
7129
+ const project = import_cjs$21.option({
7322
7130
  long: "project",
7323
7131
  type: {
7324
- ...import_cjs$20.optional(import_cjs$20.string),
7132
+ ...import_cjs$21.optional(import_cjs$21.string),
7325
7133
  displayName: "my-project"
7326
7134
  },
7327
7135
  description: "The project name or ID to associate with the command. Can be inferred from VERCEL_OIDC_TOKEN."
7328
7136
  });
7329
7137
  /** Parser for the `--team` option. */
7330
- const teamParser = import_cjs$20.option({
7138
+ const teamParser = import_cjs$21.option({
7331
7139
  long: "team",
7332
7140
  type: {
7333
- ...import_cjs$20.optional(import_cjs$20.string),
7141
+ ...import_cjs$21.optional(import_cjs$21.string),
7334
7142
  displayName: "my-team"
7335
7143
  }
7336
7144
  });
7337
7145
  /** Parser for the `--scope` option. */
7338
- const scopeParser = import_cjs$20.option({
7146
+ const scopeParser = import_cjs$21.option({
7339
7147
  long: "scope",
7340
7148
  type: {
7341
- ...import_cjs$20.optional(import_cjs$20.string),
7149
+ ...import_cjs$21.optional(import_cjs$21.string),
7342
7150
  displayName: "my-team"
7343
7151
  },
7344
7152
  description: "The scope/team to associate with the command. Can be inferred from VERCEL_OIDC_TOKEN. [alias: --team]"
@@ -7381,7 +7189,7 @@ const scope = {
7381
7189
  let projectSlug;
7382
7190
  let teamSlug;
7383
7191
  if (typeof projectId.value === "undefined" || typeof teamId.value === "undefined") try {
7384
- const scope$1 = await inferScope({
7192
+ const scope$1 = await inferScope$1({
7385
7193
  token: t.value,
7386
7194
  team: teamId.value
7387
7195
  });
@@ -7427,7 +7235,7 @@ const scope = {
7427
7235
 
7428
7236
  //#endregion
7429
7237
  //#region package.json
7430
- var version = "3.0.0-beta.2";
7238
+ var version = "3.0.0-beta.20";
7431
7239
 
7432
7240
  //#endregion
7433
7241
  //#region src/error.ts
@@ -7518,9 +7326,9 @@ async function writeResponseToTemp({ response, text }) {
7518
7326
 
7519
7327
  //#endregion
7520
7328
  //#region src/args/snapshot-id.ts
7521
- var import_cjs$19 = /* @__PURE__ */ __toESM(require_cjs());
7329
+ var import_cjs$20 = /* @__PURE__ */ __toESM(require_cjs());
7522
7330
  init_source();
7523
- const snapshotId = import_cjs$19.extendType(import_cjs$19.string, {
7331
+ const snapshotId = import_cjs$20.extendType(import_cjs$20.string, {
7524
7332
  displayName: "snapshot_id",
7525
7333
  description: "The ID of the snapshot",
7526
7334
  async from(s$1) {
@@ -7531,9 +7339,9 @@ const snapshotId = import_cjs$19.extendType(import_cjs$19.string, {
7531
7339
 
7532
7340
  //#endregion
7533
7341
  //#region src/args/sandbox-name.ts
7534
- var import_cjs$18 = /* @__PURE__ */ __toESM(require_cjs());
7342
+ var import_cjs$19 = /* @__PURE__ */ __toESM(require_cjs());
7535
7343
  init_source();
7536
- const sandboxName = import_cjs$18.extendType(import_cjs$18.string, {
7344
+ const sandboxName = import_cjs$19.extendType(import_cjs$19.string, {
7537
7345
  displayName: "name",
7538
7346
  description: "The name of the sandbox",
7539
7347
  async from(s$1) {
@@ -11251,16 +11059,23 @@ var import_ms$3 = /* @__PURE__ */ __toESM(require_ms());
11251
11059
  const debug$2 = createDebugger("sandbox:timeout");
11252
11060
  const BUFFER = (0, import_ms$3.default)("10 seconds");
11253
11061
  async function extendSandboxTimeoutPeriodically(sandbox, signal) {
11254
- const nextTick = sandbox.createdAt.getTime() + sandbox.timeout;
11062
+ const session = sandbox.currentSession();
11063
+ const timeout$1 = session.timeout;
11064
+ if (timeout$1 == null) return;
11065
+ const nextTick = session.createdAt.getTime() + timeout$1;
11255
11066
  debug$2(`next tick: ${new Date(nextTick).toISOString()}`);
11256
11067
  while (!signal.aborted) {
11257
- const timeout$1 = sandbox.createdAt.getTime() + sandbox.timeout - Date.now() - BUFFER;
11258
- if (timeout$1 > 2e3) {
11259
- debug$2(`sleeping for ${timeout$1}ms until next timeout extension`);
11260
- await setTimeout$1(timeout$1, null, { signal });
11068
+ const currentTimeout = session.timeout;
11069
+ if (currentTimeout == null) return;
11070
+ const sleepMs = session.createdAt.getTime() + currentTimeout - Date.now() - BUFFER;
11071
+ if (sleepMs > 2e3) {
11072
+ debug$2(`sleeping for ${sleepMs}ms until next timeout extension`);
11073
+ await setTimeout$1(sleepMs, null, { signal });
11261
11074
  }
11262
11075
  await sandbox.extendTimeout((0, import_ms$3.default)("5 minutes"));
11263
- const nextTick$1 = sandbox.createdAt.getTime() + sandbox.timeout;
11076
+ const updatedTimeout = session.timeout;
11077
+ if (updatedTimeout == null) return;
11078
+ const nextTick$1 = session.createdAt.getTime() + updatedTimeout;
11264
11079
  debug$2(`extended sandbox timeout by 5 minutes. next tick: ${new Date(nextTick$1).toISOString()}`);
11265
11080
  }
11266
11081
  }
@@ -11388,11 +11203,16 @@ async function startInteractiveShell(options) {
11388
11203
  await setupSandboxEnvironment(options.sandbox, progress);
11389
11204
  progress.text = "Booting up interactive listener...";
11390
11205
  command$1 = await startServerCommand(options.sandbox, listener, options.execution, options.sudo, options.envVars, options.cwd);
11206
+ debug$1("startServerCommand completed, cmdId=%s, interactivePort=%s", command$1.cmdId, options.sandbox.interactivePort);
11391
11207
  const waitForProcess = _usingCtx3.u(createAbortController("Connection established successfully"));
11392
11208
  listener.connection.then(() => {
11209
+ debug$1("listener.connection resolved");
11393
11210
  waitForProcess.abort();
11394
11211
  });
11395
- connect$1(command$1, listener, waitForProcess.signal).catch(waitForProcess.ignoreInterruptions);
11212
+ connect$1(command$1, listener, waitForProcess.signal).catch((err$1) => {
11213
+ if (waitForProcess.signal.aborted) return;
11214
+ listener.stdoutStream.destroy(err$1 instanceof Error ? err$1 : new Error(String(err$1)));
11215
+ });
11396
11216
  await Promise.all([throwIfCommandPrematurelyExited(command$1, waitForProcess.signal), attach({
11397
11217
  sandbox: options.sandbox,
11398
11218
  progress,
@@ -11495,6 +11315,7 @@ async function connect$1(command$1, listener, signal) {
11495
11315
  const stderrStream = _usingCtx5.u(getStderrStream());
11496
11316
  for await (const chunk of logs) if (chunk.stream === "stdout") listener.stdoutStream.write(chunk.data);
11497
11317
  else stderrStream.write(chunk.data);
11318
+ listener.stdoutStream.end();
11498
11319
  } catch (_) {
11499
11320
  _usingCtx5.e = _;
11500
11321
  } finally {
@@ -11525,9 +11346,9 @@ function getStderrStream() {
11525
11346
 
11526
11347
  //#endregion
11527
11348
  //#region src/args/key-value-pair.ts
11528
- var import_cjs$17 = /* @__PURE__ */ __toESM(require_cjs());
11349
+ var import_cjs$18 = /* @__PURE__ */ __toESM(require_cjs());
11529
11350
  init_source();
11530
- const KeyValuePair = import_cjs$17.extendType(import_cjs$17.string, {
11351
+ const KeyValuePair = import_cjs$18.extendType(import_cjs$18.string, {
11531
11352
  displayName: "key=value",
11532
11353
  async from(input) {
11533
11354
  if (!input.includes("=")) return {
@@ -11541,7 +11362,7 @@ const KeyValuePair = import_cjs$17.extendType(import_cjs$17.string, {
11541
11362
  };
11542
11363
  }
11543
11364
  });
11544
- const ObjectFromKeyValue = import_cjs$17.extendType(import_cjs$17.array(KeyValuePair), { async from(input) {
11365
+ const ObjectFromKeyValue = import_cjs$18.extendType(import_cjs$18.array(KeyValuePair), { async from(input) {
11545
11366
  const obj = Object.create(null);
11546
11367
  const missingVars = [];
11547
11368
  for (const { key, value } of input) if (value === void 0) missingVars.push(key);
@@ -11555,27 +11376,27 @@ const ObjectFromKeyValue = import_cjs$17.extendType(import_cjs$17.array(KeyValue
11555
11376
 
11556
11377
  //#endregion
11557
11378
  //#region src/commands/exec.ts
11558
- var import_cjs$16 = /* @__PURE__ */ __toESM(require_cjs());
11379
+ var import_cjs$17 = /* @__PURE__ */ __toESM(require_cjs());
11559
11380
  init_source();
11560
11381
  const args$3 = {
11561
- sandbox: import_cjs$16.positional({ type: sandboxName }),
11562
- command: import_cjs$16.positional({
11382
+ sandbox: import_cjs$17.positional({ type: sandboxName }),
11383
+ command: import_cjs$17.positional({
11563
11384
  displayName: "command",
11564
11385
  description: "The executable to invoke"
11565
11386
  }),
11566
- args: import_cjs$16.rest({
11387
+ args: import_cjs$17.rest({
11567
11388
  displayName: "args",
11568
11389
  description: "arguments to pass to the command"
11569
11390
  }),
11570
- asSudo: import_cjs$16.flag({
11391
+ asSudo: import_cjs$17.flag({
11571
11392
  long: "sudo",
11572
11393
  description: "Give extended privileges to the command."
11573
11394
  }),
11574
- interactive: import_cjs$16.flag({
11395
+ interactive: import_cjs$17.flag({
11575
11396
  long: "interactive",
11576
11397
  short: "i",
11577
11398
  description: "Run the command in a secure interactive shell",
11578
- type: import_cjs$16.extendType(import_cjs$16.boolean, {
11399
+ type: import_cjs$17.extendType(import_cjs$17.boolean, {
11579
11400
  defaultValue() {
11580
11401
  return false;
11581
11402
  },
@@ -11585,22 +11406,22 @@ const args$3 = {
11585
11406
  }
11586
11407
  })
11587
11408
  }),
11588
- skipExtendingTimeout: import_cjs$16.flag({
11409
+ skipExtendingTimeout: import_cjs$17.flag({
11589
11410
  long: "no-extend-timeout",
11590
11411
  description: "Do not extend the sandbox timeout while running an interactive command. Only affects interactive executions."
11591
11412
  }),
11592
- tty: import_cjs$16.flag({
11413
+ tty: import_cjs$17.flag({
11593
11414
  long: "tty",
11594
11415
  short: "t",
11595
11416
  description: "Allocate a tty for an interactive command. This is a no-op."
11596
11417
  }),
11597
- cwd: import_cjs$16.option({
11418
+ cwd: import_cjs$17.option({
11598
11419
  long: "workdir",
11599
11420
  short: "w",
11600
11421
  description: "The working directory to run the command in",
11601
- type: import_cjs$16.optional(import_cjs$16.string)
11422
+ type: import_cjs$17.optional(import_cjs$17.string)
11602
11423
  }),
11603
- envVars: import_cjs$16.multioption({
11424
+ envVars: import_cjs$17.multioption({
11604
11425
  long: "env",
11605
11426
  short: "e",
11606
11427
  type: ObjectFromKeyValue,
@@ -11608,7 +11429,7 @@ const args$3 = {
11608
11429
  }),
11609
11430
  scope
11610
11431
  };
11611
- const exec = import_cjs$16.command({
11432
+ const exec = import_cjs$17.command({
11612
11433
  name: "exec",
11613
11434
  description: "Execute a command in an existing sandbox",
11614
11435
  args: args$3,
@@ -11645,9 +11466,9 @@ const exec = import_cjs$16.command({
11645
11466
 
11646
11467
  //#endregion
11647
11468
  //#region src/args/network-policy.ts
11648
- var import_cjs$15 = /* @__PURE__ */ __toESM(require_cjs());
11469
+ var import_cjs$16 = /* @__PURE__ */ __toESM(require_cjs());
11649
11470
  init_source();
11650
- const networkPolicyMode = import_cjs$15.extendType(import_cjs$15.string, {
11471
+ const networkPolicyMode = import_cjs$16.extendType(import_cjs$16.string, {
11651
11472
  displayName: "MODE",
11652
11473
  async from(value) {
11653
11474
  const validModes = ["allow-all", "deny-all"];
@@ -11655,28 +11476,28 @@ const networkPolicyMode = import_cjs$15.extendType(import_cjs$15.string, {
11655
11476
  return value;
11656
11477
  }
11657
11478
  });
11658
- const networkPolicy = import_cjs$15.option({
11479
+ const networkPolicy = import_cjs$16.option({
11659
11480
  long: "network-policy",
11660
11481
  description: `Network policy mode: "allow-all" or "deny-all"
11661
11482
  - allow-all: sandbox can access any website/domain
11662
11483
  - deny-all: sandbox has no network access
11663
11484
  Omit this option and use --allowed-domain / --allowed-cidr / --denied-cidr for custom policies.`,
11664
- type: import_cjs$15.optional(networkPolicyMode)
11485
+ type: import_cjs$16.optional(networkPolicyMode)
11665
11486
  });
11666
- const allowedDomains = import_cjs$15.multioption({
11487
+ const allowedDomains = import_cjs$16.multioption({
11667
11488
  long: "allowed-domain",
11668
11489
  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.`,
11669
- type: import_cjs$15.array(import_cjs$15.string)
11490
+ type: import_cjs$16.array(import_cjs$16.string)
11670
11491
  });
11671
- const allowedCIDRs = import_cjs$15.multioption({
11492
+ const allowedCIDRs = import_cjs$16.multioption({
11672
11493
  long: "allowed-cidr",
11673
11494
  description: `CIDR to allow traffic to (creates a custom network policy). Takes precedence over 'allowed-domain'.`,
11674
- type: import_cjs$15.array(import_cjs$15.string)
11495
+ type: import_cjs$16.array(import_cjs$16.string)
11675
11496
  });
11676
- const deniedCIDRs = import_cjs$15.multioption({
11497
+ const deniedCIDRs = import_cjs$16.multioption({
11677
11498
  long: "denied-cidr",
11678
11499
  description: `CIDR to deny traffic to (creates a custom network policy). Takes precedence over allowed domains/CIDRs.`,
11679
- type: import_cjs$15.array(import_cjs$15.string)
11500
+ type: import_cjs$16.array(import_cjs$16.string)
11680
11501
  });
11681
11502
  const networkPolicyArgs = {
11682
11503
  networkPolicy,
@@ -11713,6 +11534,18 @@ function buildNetworkPolicy(args$4) {
11713
11534
  return networkPolicy$1 ?? "allow-all";
11714
11535
  }
11715
11536
 
11537
+ //#endregion
11538
+ //#region src/types/snapshot-expiration.ts
11539
+ var import_cjs$15 = require_cjs();
11540
+ const SnapshotExpiration = (0, import_cjs$15.extendType)(import_cjs$15.string, {
11541
+ displayName: "DURATION|none",
11542
+ description: "A duration (e.g. 7d, 30d) or \"none\" for no expiration",
11543
+ async from(value) {
11544
+ if (value === "none") return "0";
11545
+ return Duration.from(value);
11546
+ }
11547
+ });
11548
+
11716
11549
  //#endregion
11717
11550
  //#region src/commands/create.ts
11718
11551
  var import_cjs$14 = /* @__PURE__ */ __toESM(require_cjs());
@@ -11767,6 +11600,17 @@ const args$2 = {
11767
11600
  type: ObjectFromKeyValue,
11768
11601
  description: "Default environment variables for sandbox commands"
11769
11602
  }),
11603
+ tags: import_cjs$14.multioption({
11604
+ long: "tag",
11605
+ short: "t",
11606
+ type: ObjectFromKeyValue,
11607
+ description: "Key-value tags to associate with the sandbox (e.g. --tag env=staging)"
11608
+ }),
11609
+ snapshotExpiration: import_cjs$14.option({
11610
+ long: "snapshot-expiration",
11611
+ type: import_cjs$14.optional(SnapshotExpiration),
11612
+ description: "Default snapshot expiration. Use \"none\" or 0 for no expiration. Example: 7d, 30d"
11613
+ }),
11770
11614
  ...networkPolicyArgs,
11771
11615
  scope
11772
11616
  };
@@ -11778,7 +11622,7 @@ const create = import_cjs$14.command({
11778
11622
  description: "Create and connect to a sandbox without a network access",
11779
11623
  command: `sandbox run --network-policy=none --connect`
11780
11624
  }],
11781
- 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 }) {
11625
+ 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, snapshotExpiration, networkPolicy: networkPolicyMode$1, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 }) {
11782
11626
  const networkPolicy$1 = buildNetworkPolicy({
11783
11627
  networkPolicy: networkPolicyMode$1,
11784
11628
  allowedDomains: allowedDomains$1,
@@ -11787,6 +11631,7 @@ const create = import_cjs$14.command({
11787
11631
  });
11788
11632
  const persistent = !nonPersistent;
11789
11633
  const resources = vcpus$1 ? { vcpus: vcpus$1 } : void 0;
11634
+ const tagsObj = Object.keys(tags).length > 0 ? tags : void 0;
11790
11635
  const spinner = silent ? void 0 : ora("Creating sandbox...").start();
11791
11636
  const sandbox = snapshot$1 ? await sandboxClient.create({
11792
11637
  name,
@@ -11802,7 +11647,9 @@ const create = import_cjs$14.command({
11802
11647
  resources,
11803
11648
  networkPolicy: networkPolicy$1,
11804
11649
  env: envVars,
11650
+ tags: tagsObj,
11805
11651
  persistent,
11652
+ snapshotExpiration: snapshotExpiration ? (0, import_ms$2.default)(snapshotExpiration) : void 0,
11806
11653
  __interactive: true
11807
11654
  }) : await sandboxClient.create({
11808
11655
  name,
@@ -11815,7 +11662,9 @@ const create = import_cjs$14.command({
11815
11662
  resources,
11816
11663
  networkPolicy: networkPolicy$1,
11817
11664
  env: envVars,
11665
+ tags: tagsObj,
11818
11666
  persistent,
11667
+ snapshotExpiration: snapshotExpiration ? (0, import_ms$2.default)(snapshotExpiration) : void 0,
11819
11668
  __interactive: true
11820
11669
  });
11821
11670
  spinner?.stop();
@@ -11876,13 +11725,18 @@ const args$1 = {
11876
11725
  removeAfterUse: import_cjs$13.flag({
11877
11726
  long: "rm",
11878
11727
  description: "Automatically remove the sandbox when the command exits."
11728
+ }),
11729
+ stopAfterUse: import_cjs$13.flag({
11730
+ long: "stop",
11731
+ description: "Stop the sandbox when the command exits."
11879
11732
  })
11880
11733
  };
11881
11734
  const run = import_cjs$13.command({
11882
11735
  name: "run",
11883
11736
  description: "Create and run a command in a sandbox",
11884
11737
  args: args$1,
11885
- async handler({ removeAfterUse, ...rest$1 }) {
11738
+ async handler({ removeAfterUse, stopAfterUse, ...rest$1 }) {
11739
+ if (removeAfterUse && stopAfterUse) throw new Error("--rm and --stop are mutually exclusive.");
11886
11740
  let sandbox;
11887
11741
  if (rest$1.name) try {
11888
11742
  sandbox = await sandboxClient.get({
@@ -11894,10 +11748,16 @@ const run = import_cjs$13.command({
11894
11748
  __includeSystemRoutes: true
11895
11749
  });
11896
11750
  } catch (error) {
11897
- if (error instanceof StyledError && error.cause instanceof APIError && error.cause.response.status === 404) sandbox = await create.handler({ ...rest$1 });
11751
+ if (error instanceof StyledError && error.cause instanceof APIError && error.cause.response.status === 404) sandbox = await create.handler({
11752
+ ...rest$1,
11753
+ nonPersistent: rest$1.nonPersistent || removeAfterUse
11754
+ });
11898
11755
  else throw error;
11899
11756
  }
11900
- else sandbox = await create.handler({ ...rest$1 });
11757
+ else sandbox = await create.handler({
11758
+ ...rest$1,
11759
+ nonPersistent: rest$1.nonPersistent || removeAfterUse
11760
+ });
11901
11761
  try {
11902
11762
  await exec.handler({
11903
11763
  ...rest$1,
@@ -11905,6 +11765,7 @@ const run = import_cjs$13.command({
11905
11765
  });
11906
11766
  } finally {
11907
11767
  if (removeAfterUse) await sandbox.delete();
11768
+ if (stopAfterUse) await sandbox.stop();
11908
11769
  }
11909
11770
  }
11910
11771
  });
@@ -11930,33 +11791,65 @@ const list = import_cjs$12.command({
11930
11791
  }),
11931
11792
  sortBy: import_cjs$12.option({
11932
11793
  long: "sort-by",
11933
- description: "Sort sandboxes by field. Options: createdAt (default), name",
11934
- type: import_cjs$12.optional(import_cjs$12.oneOf(["createdAt", "name"]))
11794
+ description: "Sort sandboxes by field. Options: createdAt (default), name, statusUpdatedAt",
11795
+ type: import_cjs$12.optional(import_cjs$12.oneOf([
11796
+ "createdAt",
11797
+ "name",
11798
+ "statusUpdatedAt"
11799
+ ]))
11800
+ }),
11801
+ sortOrder: import_cjs$12.option({
11802
+ long: "sort-order",
11803
+ description: "Sort order. Options: asc, desc (default)",
11804
+ type: import_cjs$12.optional(import_cjs$12.oneOf(["asc", "desc"]))
11805
+ }),
11806
+ tags: import_cjs$12.multioption({
11807
+ long: "tag",
11808
+ description: "Filter sandboxes by tag. Format: \"key=value\"",
11809
+ type: ObjectFromKeyValue
11810
+ }),
11811
+ limit: import_cjs$12.option({
11812
+ long: "limit",
11813
+ description: "Maximum number of sandboxes per page (default 50).",
11814
+ type: import_cjs$12.optional(import_cjs$12.number)
11815
+ }),
11816
+ cursor: import_cjs$12.option({
11817
+ long: "cursor",
11818
+ description: "Pagination cursor from a previous 'More results' hint.",
11819
+ type: import_cjs$12.optional(import_cjs$12.string)
11935
11820
  }),
11936
11821
  scope
11937
11822
  },
11938
- async handler({ scope: { token: token$1, team: team$1, project: project$1 }, all, namePrefix, sortBy }) {
11939
- const sandboxes = await (async () => {
11823
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, all, namePrefix, sortBy, sortOrder, tags, limit, cursor }) {
11824
+ if (namePrefix) {
11825
+ if (sortBy && sortBy !== "name") {
11826
+ console.error(source_default.red("Error: --sort-by must be 'name' when using --name-prefix"));
11827
+ return;
11828
+ }
11829
+ sortBy = "name";
11830
+ }
11831
+ const { sandboxes, pagination } = await (async () => {
11940
11832
  try {
11941
11833
  var _usingCtx$1 = _usingCtx();
11942
11834
  const _spinner$1 = _usingCtx$1.u(acquireRelease(() => ora("Fetching sandboxes...").start(), (s$1) => s$1.stop()));
11943
- const { json } = await sandboxClient.list({
11835
+ return sandboxClient.list({
11944
11836
  token: token$1,
11945
11837
  teamId: team$1,
11946
11838
  projectId: project$1,
11947
- limit: 100,
11839
+ limit: limit ?? 50,
11840
+ ...cursor && { cursor },
11948
11841
  ...namePrefix && { namePrefix },
11949
- ...sortBy && { sortBy }
11842
+ ...sortBy && { sortBy },
11843
+ ...sortOrder && { sortOrder },
11844
+ ...Object.keys(tags).length > 0 && { tags }
11950
11845
  });
11951
- let sandboxes$1 = json.sandboxes;
11952
- if (!all) sandboxes$1 = sandboxes$1.filter((x) => x.status === "running");
11953
- return sandboxes$1;
11954
11846
  } catch (_) {
11955
11847
  _usingCtx$1.e = _;
11956
11848
  } finally {
11957
11849
  _usingCtx$1.d();
11958
11850
  }
11959
11851
  })();
11852
+ const displayedSandboxes = all ? sandboxes : sandboxes.filter((x) => x.status === "running");
11960
11853
  const memoryFormatter = new Intl.NumberFormat(void 0, {
11961
11854
  style: "unit",
11962
11855
  unit: "megabyte"
@@ -11968,20 +11861,22 @@ const list = import_cjs$12.command({
11968
11861
  color: (s$1) => SandboxStatusColor[s$1.status] ?? source_default.reset
11969
11862
  },
11970
11863
  CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
11971
- MEMORY: { value: (s$1) => memoryFormatter.format(s$1.memory) },
11972
- VCPUS: { value: (s$1) => s$1.vcpus },
11973
- RUNTIME: { value: (s$1) => s$1.runtime },
11974
- TIMEOUT: { value: (s$1) => timeAgo(s$1.createdAt + s$1.timeout) },
11975
- SNAPSHOT: { value: (s$1) => s$1.currentSnapshotId ?? "-" }
11864
+ MEMORY: { value: (s$1) => s$1.memory != null ? memoryFormatter.format(s$1.memory) : "-" },
11865
+ VCPUS: { value: (s$1) => s$1.vcpus ?? "-" },
11866
+ RUNTIME: { value: (s$1) => s$1.runtime ?? "-" },
11867
+ TIMEOUT: { value: (s$1) => s$1.timeout != null ? timeAgo(s$1.createdAt + s$1.timeout) : "-" },
11868
+ SNAPSHOT: { value: (s$1) => s$1.currentSnapshotId ?? "-" },
11869
+ 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(", ") : "-" }
11976
11870
  };
11977
11871
  if (all) {
11978
11872
  columns.CPU = { value: (s$1) => s$1.totalActiveCpuDurationMs ? formatRunDuration(s$1.totalActiveCpuDurationMs) : "-" };
11979
11873
  columns["NETWORK (OUT/IN)"] = { value: (s$1) => s$1.totalEgressBytes || s$1.totalIngressBytes ? `${formatBytes(s$1.totalEgressBytes ?? 0)} / ${formatBytes(s$1.totalIngressBytes ?? 0)}` : "- / -" };
11980
11874
  }
11981
11875
  console.log(table({
11982
- rows: sandboxes,
11876
+ rows: displayedSandboxes,
11983
11877
  columns
11984
11878
  }));
11879
+ if (pagination.next !== null) console.log(formatNextCursorHint(pagination.next));
11985
11880
  }
11986
11881
  });
11987
11882
  const SandboxStatusColor = {
@@ -12013,6 +11908,106 @@ const connect = import_cjs$11.command({
12013
11908
  }
12014
11909
  });
12015
11910
 
11911
+ //#endregion
11912
+ //#region src/commands/stop.ts
11913
+ var import_cjs$10 = /* @__PURE__ */ __toESM(require_cjs());
11914
+ init_source();
11915
+ function c(label, value) {
11916
+ return {
11917
+ label,
11918
+ value
11919
+ };
11920
+ }
11921
+ /** Visible width of a cell (label + value, no ANSI). */
11922
+ function cellWidth(cell) {
11923
+ return cell ? cell.label.length + cell.value.length : 0;
11924
+ }
11925
+ /** Print rows as a tree with column-aligned label: value pairs. */
11926
+ function printTree(rows) {
11927
+ const widths = [];
11928
+ for (const row of rows) for (let i = 0; i < row.length; i++) widths[i] = Math.max(widths[i] ?? 0, cellWidth(row[i]));
11929
+ for (let r = 0; r < rows.length; r++) {
11930
+ const prefix$1 = r === rows.length - 1 ? source_default.dim(" ╰ ") : source_default.dim(" │ ");
11931
+ const line = rows[r].map((cell, i) => {
11932
+ if (!cell) return " ".repeat(widths[i]);
11933
+ const pad = widths[i] - cell.label.length - cell.value.length;
11934
+ return cell.label + source_default.cyan(cell.value) + " ".repeat(Math.max(0, pad));
11935
+ }).join(" ").trimEnd();
11936
+ process.stderr.write(prefix$1 + line + "\n");
11937
+ }
11938
+ }
11939
+ function printStopResult(name, sandbox, sessionSnapshot) {
11940
+ process.stderr.write(source_default.green("✔") + " Sandbox stopped.\n");
11941
+ const snapshot$1 = sessionSnapshot.snapshot;
11942
+ printTree([
11943
+ [
11944
+ c("sandbox: ", name),
11945
+ sandbox.totalActiveCpuDurationMs != null ? c("active cpu: ", formatRunDuration(sandbox.totalActiveCpuDurationMs)) : null,
11946
+ sandbox.memory != null ? c("mem: ", `${sandbox.memory} MB`) : null,
11947
+ sandbox.totalDurationMs != null ? c("duration: ", formatRunDuration(sandbox.totalDurationMs)) : null,
11948
+ sandbox.totalIngressBytes != null ? c("ingress: ", formatBytes(sandbox.totalIngressBytes)) : null,
11949
+ sandbox.totalEgressBytes != null ? c("egress: ", formatBytes(sandbox.totalEgressBytes)) : null
11950
+ ],
11951
+ [
11952
+ c("session: ", sessionSnapshot.id),
11953
+ sessionSnapshot.activeCpuDurationMs != null ? c("active cpu: ", formatRunDuration(sessionSnapshot.activeCpuDurationMs)) : null,
11954
+ c("mem: ", `${sessionSnapshot.memory} MB`),
11955
+ sessionSnapshot.duration != null ? c("duration: ", formatRunDuration(sessionSnapshot.duration)) : null,
11956
+ sessionSnapshot.networkTransfer ? c("ingress: ", formatBytes(sessionSnapshot.networkTransfer.ingress)) : null,
11957
+ sessionSnapshot.networkTransfer ? c("egress: ", formatBytes(sessionSnapshot.networkTransfer.egress)) : null
11958
+ ],
11959
+ ...snapshot$1 ? [[
11960
+ c("snapshot: ", snapshot$1.id),
11961
+ c("size: ", formatBytes(snapshot$1.sizeBytes)),
11962
+ c("expires: ", snapshot$1.expiresAt ? timeAgo(snapshot$1.expiresAt) : "never")
11963
+ ]] : []
11964
+ ]);
11965
+ }
11966
+ const stop = import_cjs$10.command({
11967
+ name: "stop",
11968
+ description: "Stop the current session of one or more sandboxes",
11969
+ args: {
11970
+ sandboxName: import_cjs$10.positional({
11971
+ type: sandboxName,
11972
+ description: "A sandbox name to stop"
11973
+ }),
11974
+ sandboxNames: import_cjs$10.restPositionals({
11975
+ type: sandboxName,
11976
+ description: "More sandboxes to stop"
11977
+ }),
11978
+ scope
11979
+ },
11980
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandboxName: sandboxName$1, sandboxNames }) {
11981
+ const names = Array.from(new Set([sandboxName$1, ...sandboxNames]));
11982
+ const spinner = ora({
11983
+ text: names.length === 1 ? `Stopping ${names[0]}` : `Stopping ${names.length} sandboxes`,
11984
+ stream: process.stderr
11985
+ }).start();
11986
+ const results = await Promise.allSettled(names.map(async (name) => {
11987
+ const sandbox = await sandboxClient.get({
11988
+ token: token$1,
11989
+ teamId: team$1,
11990
+ projectId: project$1,
11991
+ name
11992
+ });
11993
+ return {
11994
+ name,
11995
+ sandbox,
11996
+ sessionSnapshot: await sandbox.stop()
11997
+ };
11998
+ }));
11999
+ spinner.stop();
12000
+ for (const result of results) if (result.status === "fulfilled") {
12001
+ const { name, sandbox, sessionSnapshot } = result.value;
12002
+ printStopResult(name, sandbox, sessionSnapshot);
12003
+ } else {
12004
+ const error = result.reason;
12005
+ process.stderr.write(source_default.red("✖") + ` ${error.message ?? error}\n`);
12006
+ process.exitCode = 1;
12007
+ }
12008
+ }
12009
+ });
12010
+
12016
12011
  //#endregion
12017
12012
  //#region ../../node_modules/.pnpm/eventemitter3@5.0.1/node_modules/eventemitter3/index.js
12018
12013
  var require_eventemitter3 = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/eventemitter3@5.0.1/node_modules/eventemitter3/index.js": ((exports, module) => {
@@ -12264,9 +12259,9 @@ const isDumbTerminal = env.TERM === "dumb";
12264
12259
  const isCompatibleTerminal = tty$1 && tty$1.isatty && tty$1.isatty(1) && env.TERM && !isDumbTerminal;
12265
12260
  const isCI = "CI" in env && ("GITHUB_ACTIONS" in env || "GITLAB_CI" in env || "CIRCLECI" in env);
12266
12261
  const isColorSupported = !isDisabled && (isForced || isWindows && !isDumbTerminal || isCompatibleTerminal || isCI);
12267
- const replaceClose = (index, string$1, close, replace, head = string$1.substring(0, index) + replace, tail = string$1.substring(index + close.length), next = tail.indexOf(close)) => head + (next < 0 ? tail : replaceClose(next, tail, close, replace));
12268
- const clearBleed = (index, string$1, open$1, close, replace) => index < 0 ? open$1 + string$1 + close : open$1 + replaceClose(index, string$1, close, replace) + close;
12269
- const filterEmpty = (open$1, close, replace = open$1, at = open$1.length + 1) => (string$1) => string$1 || !(string$1 === "" || string$1 === void 0) ? clearBleed(("" + string$1).indexOf(close, at), string$1, open$1, close, replace) : "";
12262
+ const replaceClose = (index, string$2, close, replace, head = string$2.substring(0, index) + replace, tail = string$2.substring(index + close.length), next = tail.indexOf(close)) => head + (next < 0 ? tail : replaceClose(next, tail, close, replace));
12263
+ const clearBleed = (index, string$2, open$1, close, replace) => index < 0 ? open$1 + string$2 + close : open$1 + replaceClose(index, string$2, close, replace) + close;
12264
+ const filterEmpty = (open$1, close, replace = open$1, at = open$1.length + 1) => (string$2) => string$2 || !(string$2 === "" || string$2 === void 0) ? clearBleed(("" + string$2).indexOf(close, at), string$2, open$1, close, replace) : "";
12270
12265
  const init = (open$1, close, replace) => filterEmpty(`\x1b[${open$1}m`, `\x1b[${close}m`, replace);
12271
12266
  const colors = {
12272
12267
  reset: init(0, 0),
@@ -12625,8 +12620,8 @@ function cleanseAnsi(chunk) {
12625
12620
  * @see {@link https://www.npmjs.com/package/colorette}
12626
12621
  */
12627
12622
  const color = createColors();
12628
- function indent(string$1, count) {
12629
- return string$1.replace(/^(?!\s*$)/gm, " ".repeat(count));
12623
+ function indent(string$2, count) {
12624
+ return string$2.replace(/^(?!\s*$)/gm, " ".repeat(count));
12630
12625
  }
12631
12626
  const FIGURES_MAIN = {
12632
12627
  warning: "⚠",
@@ -14296,40 +14291,6 @@ var Listr = class {
14296
14291
  }
14297
14292
  };
14298
14293
 
14299
- //#endregion
14300
- //#region src/commands/stop.ts
14301
- var import_cjs$10 = /* @__PURE__ */ __toESM(require_cjs());
14302
- const stop = import_cjs$10.command({
14303
- name: "stop",
14304
- description: "Stop the current session of one or more sandboxes",
14305
- args: {
14306
- sandboxName: import_cjs$10.positional({
14307
- type: sandboxName,
14308
- description: "A sandbox name to stop"
14309
- }),
14310
- sandboxNames: import_cjs$10.restPositionals({
14311
- type: sandboxName,
14312
- description: "More sandboxes to stop"
14313
- }),
14314
- scope
14315
- },
14316
- async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandboxName: sandboxName$1, sandboxNames }) {
14317
- await new Listr(Array.from(new Set([sandboxName$1, ...sandboxNames]), (sandboxName$2) => {
14318
- return {
14319
- title: `Stopping sandbox ${sandboxName$2}`,
14320
- async task() {
14321
- await (await sandboxClient.get({
14322
- token: token$1,
14323
- teamId: team$1,
14324
- projectId: project$1,
14325
- name: sandboxName$2
14326
- })).stop();
14327
- }
14328
- };
14329
- }), { concurrent: true }).run();
14330
- }
14331
- });
14332
-
14333
14294
  //#endregion
14334
14295
  //#region src/commands/remove.ts
14335
14296
  var import_cjs$9 = /* @__PURE__ */ __toESM(require_cjs());
@@ -14346,14 +14307,10 @@ const remove = import_cjs$9.command({
14346
14307
  type: sandboxName,
14347
14308
  description: "more sandboxes to remove"
14348
14309
  }),
14349
- preserveSnapshots: import_cjs$9.flag({
14350
- long: "preserve-snapshots",
14351
- description: "Keep snapshots when removing the sandbox"
14352
- }),
14353
14310
  scope
14354
14311
  },
14355
- async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandboxName: sandboxName$1, sandboxNames, preserveSnapshots }) {
14356
- await new Listr(Array.from(new Set([sandboxName$1, ...sandboxNames]), (name) => ({
14312
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandboxName: sandboxName$1, sandboxNames }) {
14313
+ const tasks = Array.from(new Set([sandboxName$1, ...sandboxNames]), (name) => ({
14357
14314
  title: `Removing sandbox ${name}`,
14358
14315
  async task() {
14359
14316
  await (await sandboxClient.get({
@@ -14361,9 +14318,14 @@ const remove = import_cjs$9.command({
14361
14318
  teamId: team$1,
14362
14319
  projectId: project$1,
14363
14320
  name
14364
- })).delete({ preserveSnapshots });
14321
+ })).delete();
14365
14322
  }
14366
- })), { concurrent: true }).run();
14323
+ }));
14324
+ try {
14325
+ await new Listr(tasks, { concurrent: true }).run();
14326
+ } catch {
14327
+ process.exitCode = 1;
14328
+ }
14367
14329
  }
14368
14330
  });
14369
14331
 
@@ -14532,19 +14494,43 @@ const list$2 = import_cjs$4.command({
14532
14494
  name: "list",
14533
14495
  aliases: ["ls"],
14534
14496
  description: "List snapshots for the specified account and project.",
14535
- args: { scope },
14536
- async handler({ scope: { token: token$1, team: team$1, project: project$1 } }) {
14537
- const snapshots$1 = await (async () => {
14497
+ args: {
14498
+ scope,
14499
+ name: import_cjs$4.option({
14500
+ type: import_cjs$4.optional(sandboxName),
14501
+ long: "name",
14502
+ description: "Filter snapshots by sandbox."
14503
+ }),
14504
+ sortOrder: import_cjs$4.option({
14505
+ long: "sort-order",
14506
+ description: "Sort order. Options: asc, desc (default)",
14507
+ type: import_cjs$4.optional(import_cjs$4.oneOf(["asc", "desc"]))
14508
+ }),
14509
+ limit: import_cjs$4.option({
14510
+ long: "limit",
14511
+ description: "Maximum number of snapshots per page (default 50).",
14512
+ type: import_cjs$4.optional(import_cjs$4.number)
14513
+ }),
14514
+ cursor: import_cjs$4.option({
14515
+ long: "cursor",
14516
+ description: "Pagination cursor from a previous 'More results' hint.",
14517
+ type: import_cjs$4.optional(import_cjs$4.string)
14518
+ })
14519
+ },
14520
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, name, sortOrder, limit, cursor }) {
14521
+ const { snapshots: snapshots$1, pagination } = await (async () => {
14538
14522
  try {
14539
14523
  var _usingCtx$1 = _usingCtx();
14540
14524
  const _spinner$1 = _usingCtx$1.u(acquireRelease(() => ora("Fetching snapshots...").start(), (s$1) => s$1.stop()));
14541
- const { json } = await snapshotClient.list({
14525
+ return snapshotClient.list({
14542
14526
  token: token$1,
14543
14527
  teamId: team$1,
14544
14528
  projectId: project$1,
14545
- limit: 100
14529
+ name,
14530
+ limit: limit ?? 50,
14531
+ ...cursor && { cursor },
14532
+ ...sortOrder && { sortOrder }
14546
14533
  });
14547
- return json.snapshots;
14548
14534
  } catch (_) {
14549
14535
  _usingCtx$1.e = _;
14550
14536
  } finally {
@@ -14562,9 +14548,10 @@ const list$2 = import_cjs$4.command({
14562
14548
  CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
14563
14549
  EXPIRATION: { value: (s$1) => s$1.status === "deleted" ? source_default.gray.dim("deleted") : timeAgo(s$1.expiresAt) },
14564
14550
  SIZE: { value: (s$1) => formatBytes(s$1.sizeBytes) },
14565
- ["SOURCE SESSION"]: { value: (s$1) => s$1.sourceSandboxId }
14551
+ ["SOURCE SESSION"]: { value: (s$1) => s$1.sourceSessionId }
14566
14552
  }
14567
14553
  }));
14554
+ if (pagination.next !== null) console.log(formatNextCursorHint(pagination.next));
14568
14555
  }
14569
14556
  });
14570
14557
  const get = import_cjs$4.command({
@@ -14605,7 +14592,7 @@ const get = import_cjs$4.command({
14605
14592
  CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
14606
14593
  EXPIRATION: { value: (s$1) => s$1.status === "deleted" ? source_default.gray.dim("deleted") : timeAgo(s$1.expiresAt) },
14607
14594
  SIZE: { value: (s$1) => formatBytes(s$1.sizeBytes) },
14608
- ["SOURCE SESSION"]: { value: (s$1) => s$1.sourceSandboxId }
14595
+ ["SOURCE SESSION"]: { value: (s$1) => s$1.sourceSessionId }
14609
14596
  }
14610
14597
  }));
14611
14598
  }
@@ -14626,7 +14613,7 @@ const remove$1 = import_cjs$4.command({
14626
14613
  scope
14627
14614
  },
14628
14615
  async handler({ scope: { team: team$1, token: token$1, project: project$1 }, snapshotId: snapshotId$1, snapshotIds }) {
14629
- await new Listr(Array.from(new Set([snapshotId$1, ...snapshotIds]), (snapshotId$2) => {
14616
+ const tasks = Array.from(new Set([snapshotId$1, ...snapshotIds]), (snapshotId$2) => {
14630
14617
  return {
14631
14618
  title: `Deleting snapshot ${snapshotId$2}`,
14632
14619
  async task() {
@@ -14640,7 +14627,12 @@ const remove$1 = import_cjs$4.command({
14640
14627
  await snapshot$1.delete();
14641
14628
  }
14642
14629
  };
14643
- }), { concurrent: true }).run();
14630
+ });
14631
+ try {
14632
+ await new Listr(tasks, { concurrent: true }).run();
14633
+ } catch {
14634
+ process.exitCode = 1;
14635
+ }
14644
14636
  }
14645
14637
  });
14646
14638
  const snapshots = (0, import_cjs$5.subcommands)({
@@ -14668,46 +14660,82 @@ const list$1 = import_cjs$2.command({
14668
14660
  aliases: ["ls"],
14669
14661
  description: "List sessions from a sandbox",
14670
14662
  args: {
14663
+ all: import_cjs$2.flag({
14664
+ long: "all",
14665
+ short: "a",
14666
+ description: "Show all sessions (default shows just running)"
14667
+ }),
14671
14668
  sandbox: import_cjs$2.positional({
14672
14669
  type: sandboxName,
14673
14670
  description: "Sandbox name to list sessions for"
14674
14671
  }),
14672
+ sortOrder: import_cjs$2.option({
14673
+ long: "sort-order",
14674
+ description: "Sort order. Options: asc, desc (default)",
14675
+ type: import_cjs$2.optional(import_cjs$2.oneOf(["asc", "desc"]))
14676
+ }),
14677
+ limit: import_cjs$2.option({
14678
+ long: "limit",
14679
+ description: "Maximum number of sessions per page (default 50).",
14680
+ type: import_cjs$2.optional(import_cjs$2.number)
14681
+ }),
14682
+ cursor: import_cjs$2.option({
14683
+ long: "cursor",
14684
+ description: "Pagination cursor from a previous 'More results' hint.",
14685
+ type: import_cjs$2.optional(import_cjs$2.string)
14686
+ }),
14675
14687
  scope
14676
14688
  },
14677
- async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name }) {
14689
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, all, sandbox: name, sortOrder, limit, cursor }) {
14678
14690
  const sandbox = await sandboxClient.get({
14679
14691
  name,
14680
14692
  projectId: project$1,
14681
14693
  teamId: team$1,
14682
14694
  token: token$1
14683
14695
  });
14684
- const sessions$1 = (await (async () => {
14696
+ const { sessions: sessions$1, pagination } = await (async () => {
14685
14697
  try {
14686
14698
  var _usingCtx$1 = _usingCtx();
14687
14699
  const _spinner$1 = _usingCtx$1.u(acquireRelease(() => ora("Fetching sessions...").start(), (s$1) => s$1.stop()));
14688
- return sandbox.listSessions();
14700
+ return sandbox.listSessions({
14701
+ limit: limit ?? 50,
14702
+ ...cursor && { cursor },
14703
+ ...sortOrder && { sortOrder }
14704
+ });
14689
14705
  } catch (_) {
14690
14706
  _usingCtx$1.e = _;
14691
14707
  } finally {
14692
14708
  _usingCtx$1.d();
14693
14709
  }
14694
- })()).json.sandboxes;
14710
+ })();
14711
+ const displayedSessions = all ? sessions$1 : sessions$1.filter((x) => x.status === "running");
14712
+ const memoryFormatter = new Intl.NumberFormat(void 0, {
14713
+ style: "unit",
14714
+ unit: "megabyte"
14715
+ });
14716
+ const columns = {
14717
+ ID: { value: (s$1) => s$1.id },
14718
+ STATUS: {
14719
+ value: (s$1) => s$1.status,
14720
+ color: (s$1) => SessionStatusColor[s$1.status] ?? source_default.reset
14721
+ },
14722
+ CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
14723
+ MEMORY: { value: (s$1) => memoryFormatter.format(s$1.memory) },
14724
+ VCPUS: { value: (s$1) => s$1.vcpus },
14725
+ RUNTIME: { value: (s$1) => s$1.runtime },
14726
+ TIMEOUT: { value: (s$1) => timeAgo(s$1.createdAt + s$1.timeout) },
14727
+ DURATION: { value: (s$1) => s$1.duration ? formatRunDuration(s$1.duration) : "-" },
14728
+ SNAPSHOT: { value: (s$1) => s$1.sourceSnapshotId ?? "-" }
14729
+ };
14730
+ if (all) {
14731
+ columns.CPU = { value: (s$1) => s$1.activeCpuDurationMs ? formatRunDuration(s$1.activeCpuDurationMs) : "-" };
14732
+ 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)}` : "- / -" };
14733
+ }
14695
14734
  console.log(table({
14696
- rows: sessions$1,
14697
- columns: {
14698
- ID: { value: (s$1) => s$1.id },
14699
- STATUS: {
14700
- value: (s$1) => s$1.status,
14701
- color: (s$1) => SessionStatusColor[s$1.status] ?? source_default.reset
14702
- },
14703
- CREATED: { value: (s$1) => timeAgo(s$1.createdAt) },
14704
- MEMORY: { value: (s$1) => s$1.memory },
14705
- VCPUS: { value: (s$1) => s$1.vcpus },
14706
- RUNTIME: { value: (s$1) => s$1.runtime },
14707
- TIMEOUT: { value: (s$1) => timeAgo(s$1.createdAt + s$1.timeout) },
14708
- DURATION: { value: (s$1) => s$1.duration ? formatRunDuration(s$1.duration) : "-" }
14709
- }
14735
+ rows: displayedSessions,
14736
+ columns
14710
14737
  }));
14738
+ if (pagination.next !== null) console.log(formatNextCursorHint(pagination.next));
14711
14739
  }
14712
14740
  });
14713
14741
  const sessions = (0, import_cjs$3.subcommands)({
@@ -14832,6 +14860,74 @@ const persistentCommand = import_cjs$1.command({
14832
14860
  }
14833
14861
  }
14834
14862
  });
14863
+ const snapshotExpirationCommand = import_cjs$1.command({
14864
+ name: "snapshot-expiration",
14865
+ description: "Update the default snapshot expiration of a sandbox",
14866
+ args: {
14867
+ sandbox: import_cjs$1.positional({
14868
+ type: sandboxName,
14869
+ description: "Sandbox name to update"
14870
+ }),
14871
+ duration: import_cjs$1.positional({
14872
+ type: SnapshotExpiration,
14873
+ description: "Snapshot expiration duration (e.g. 7d, 30d) or \"none\" for no expiration"
14874
+ }),
14875
+ scope
14876
+ },
14877
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name, duration }) {
14878
+ const sandbox = await sandboxClient.get({
14879
+ name,
14880
+ projectId: project$1,
14881
+ teamId: team$1,
14882
+ token: token$1
14883
+ });
14884
+ const spinner = ora("Updating sandbox configuration...").start();
14885
+ try {
14886
+ await sandbox.update({ snapshotExpiration: (0, import_ms.default)(duration) });
14887
+ spinner.stop();
14888
+ const display = (0, import_ms.default)(duration) === 0 ? "none" : duration;
14889
+ process.stderr.write("✅ Configuration updated for sandbox " + source_default.cyan(name) + "\n");
14890
+ process.stderr.write(source_default.dim(" ╰ ") + "snapshot-expiration: " + source_default.cyan(display) + "\n");
14891
+ } catch (error) {
14892
+ spinner.stop();
14893
+ throw error;
14894
+ }
14895
+ }
14896
+ });
14897
+ const currentSnapshotCommand = import_cjs$1.command({
14898
+ name: "current-snapshot",
14899
+ description: "Update the current snapshot of a sandbox",
14900
+ args: {
14901
+ sandbox: import_cjs$1.positional({
14902
+ type: sandboxName,
14903
+ description: "Sandbox name to update"
14904
+ }),
14905
+ snapshotId: import_cjs$1.positional({
14906
+ type: snapshotId,
14907
+ description: "Snapshot ID to set as the current snapshot"
14908
+ }),
14909
+ scope
14910
+ },
14911
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name, snapshotId: snapshotId$1 }) {
14912
+ const sandbox = await sandboxClient.get({
14913
+ name,
14914
+ projectId: project$1,
14915
+ teamId: team$1,
14916
+ token: token$1
14917
+ });
14918
+ const spinner = ora("Updating sandbox configuration...").start();
14919
+ try {
14920
+ await sandbox.update({ currentSnapshotId: snapshotId$1 });
14921
+ spinner.stop();
14922
+ process.stderr.write("✅ Configuration updated for sandbox " + source_default.cyan(name) + "\n");
14923
+ process.stderr.write(source_default.dim(" ╰ ") + "current-snapshot: " + source_default.cyan(snapshotId$1) + "\n");
14924
+ } catch (error) {
14925
+ spinner.stop();
14926
+ if (error instanceof APIError && error.response.status === 404) throw new StyledError(`Snapshot '${snapshotId$1}' was not found or does not belong to this project.`, error);
14927
+ throw error;
14928
+ }
14929
+ }
14930
+ });
14835
14931
  const listCommand = import_cjs$1.command({
14836
14932
  name: "list",
14837
14933
  description: "Display the current configuration of a sandbox",
@@ -14860,14 +14956,15 @@ const listCommand = import_cjs$1.command({
14860
14956
  }
14861
14957
  })();
14862
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(", ") : "-";
14863
14960
  const rows = [
14864
14961
  {
14865
14962
  field: "vCPUs",
14866
- value: String(sandbox.vcpus)
14963
+ value: String(sandbox.vcpus ?? "-")
14867
14964
  },
14868
14965
  {
14869
14966
  field: "Timeout",
14870
- value: (0, import_ms.default)(sandbox.timeout, { long: true })
14967
+ value: sandbox.timeout != null ? (0, import_ms.default)(sandbox.timeout, { long: true }) : "-"
14871
14968
  },
14872
14969
  {
14873
14970
  field: "Persistent",
@@ -14876,6 +14973,18 @@ const listCommand = import_cjs$1.command({
14876
14973
  {
14877
14974
  field: "Network policy",
14878
14975
  value: String(networkPolicy$1)
14976
+ },
14977
+ {
14978
+ field: "Snapshot expiration",
14979
+ value: sandbox.snapshotExpiration != null && sandbox.snapshotExpiration > 0 ? (0, import_ms.default)(sandbox.snapshotExpiration, { long: true }) : sandbox.snapshotExpiration === 0 ? "none" : "-"
14980
+ },
14981
+ {
14982
+ field: "Current snapshot",
14983
+ value: sandbox.currentSnapshotId ?? "-"
14984
+ },
14985
+ {
14986
+ field: "Tags",
14987
+ value: tagsDisplay
14879
14988
  }
14880
14989
  ];
14881
14990
  console.log(table({
@@ -14931,6 +15040,48 @@ const networkPolicyCommand = import_cjs$1.command({
14931
15040
  }
14932
15041
  }
14933
15042
  });
15043
+ const tagsCommand = import_cjs$1.command({
15044
+ name: "tags",
15045
+ description: "Update the tags of a sandbox. Replaces all existing tags with the provided tags.",
15046
+ args: {
15047
+ sandbox: import_cjs$1.positional({
15048
+ type: sandboxName,
15049
+ description: "Sandbox name to update"
15050
+ }),
15051
+ tags: import_cjs$1.multioption({
15052
+ long: "tag",
15053
+ short: "t",
15054
+ type: ObjectFromKeyValue,
15055
+ description: "Key-value tags to set (e.g. --tag env=staging). Omit to clear all tags."
15056
+ }),
15057
+ scope
15058
+ },
15059
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandbox: name, tags }) {
15060
+ const sandbox = await sandboxClient.get({
15061
+ name,
15062
+ projectId: project$1,
15063
+ teamId: team$1,
15064
+ token: token$1
15065
+ });
15066
+ const tagsObj = Object.keys(tags).length > 0 ? tags : {};
15067
+ const spinner = ora("Updating sandbox tags...").start();
15068
+ try {
15069
+ await sandbox.update({ tags: tagsObj });
15070
+ spinner.stop();
15071
+ process.stderr.write("✅ Tags updated for sandbox " + source_default.cyan(name) + "\n");
15072
+ const entries$1 = Object.entries(tagsObj);
15073
+ if (entries$1.length === 0) process.stderr.write(source_default.dim(" ╰ ") + "all tags cleared\n");
15074
+ else for (let i = 0; i < entries$1.length; i++) {
15075
+ const [k, v] = entries$1[i];
15076
+ const prefix$1 = i === entries$1.length - 1 ? source_default.dim(" ╰ ") : source_default.dim(" │ ");
15077
+ process.stderr.write(prefix$1 + source_default.cyan(k) + "=" + source_default.cyan(v) + "\n");
15078
+ }
15079
+ } catch (error) {
15080
+ spinner.stop();
15081
+ throw error;
15082
+ }
15083
+ }
15084
+ });
14934
15085
  const config = import_cjs$1.subcommands({
14935
15086
  name: "config",
14936
15087
  description: "View and update sandbox configuration",
@@ -14939,7 +15090,10 @@ const config = import_cjs$1.subcommands({
14939
15090
  vcpus: vcpusCommand,
14940
15091
  timeout: timeoutCommand,
14941
15092
  persistent: persistentCommand,
14942
- "network-policy": networkPolicyCommand
15093
+ "network-policy": networkPolicyCommand,
15094
+ "snapshot-expiration": snapshotExpirationCommand,
15095
+ "current-snapshot": currentSnapshotCommand,
15096
+ tags: tagsCommand
14943
15097
  }
14944
15098
  });
14945
15099
 
@@ -14986,4 +15140,4 @@ const app = (opts) => (0, import_cjs.subcommands)({
14986
15140
 
14987
15141
  //#endregion
14988
15142
  export { source_exports as a, init_source as i, StyledError as n, require_cjs as r, app as t };
14989
- //# sourceMappingURL=app-BbpAiciu.mjs.map
15143
+ //# sourceMappingURL=app-DfdLC3Kn.mjs.map