sandbox 3.0.0-beta.2 → 3.0.0-beta.21

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