sandbox 3.0.0-beta.25 → 3.0.0-beta.26

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.
@@ -2998,9 +2998,9 @@ var require_cjs = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/cmd-t
2998
2998
 
2999
2999
  //#endregion
3000
3000
  //#region src/args/runtime.ts
3001
- var import_cjs$28 = /* @__PURE__ */ __toESM(require_cjs());
3001
+ var import_cjs$30 = /* @__PURE__ */ __toESM(require_cjs());
3002
3002
  const runtimeType = {
3003
- ...import_cjs$28.oneOf([
3003
+ ...import_cjs$30.oneOf([
3004
3004
  "node22",
3005
3005
  "node24",
3006
3006
  "node26",
@@ -3008,7 +3008,7 @@ const runtimeType = {
3008
3008
  ]),
3009
3009
  displayName: "runtime"
3010
3010
  };
3011
- const runtime = import_cjs$28.option({
3011
+ const runtime = import_cjs$30.option({
3012
3012
  long: "runtime",
3013
3013
  type: runtimeType,
3014
3014
  defaultValue: () => "node24",
@@ -3102,13 +3102,13 @@ var require_ms = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/ms@2.1
3102
3102
  * @return {String}
3103
3103
  * @api private
3104
3104
  */
3105
- function fmtShort(ms$4) {
3106
- var msAbs = Math.abs(ms$4);
3107
- if (msAbs >= d) return Math.round(ms$4 / d) + "d";
3108
- if (msAbs >= h) return Math.round(ms$4 / h) + "h";
3109
- if (msAbs >= m) return Math.round(ms$4 / m) + "m";
3110
- if (msAbs >= s) return Math.round(ms$4 / s) + "s";
3111
- return ms$4 + "ms";
3105
+ function fmtShort(ms$6) {
3106
+ var msAbs = Math.abs(ms$6);
3107
+ if (msAbs >= d) return Math.round(ms$6 / d) + "d";
3108
+ if (msAbs >= h) return Math.round(ms$6 / h) + "h";
3109
+ if (msAbs >= m) return Math.round(ms$6 / m) + "m";
3110
+ if (msAbs >= s) return Math.round(ms$6 / s) + "s";
3111
+ return ms$6 + "ms";
3112
3112
  }
3113
3113
  /**
3114
3114
  * Long format for `ms`.
@@ -3117,28 +3117,28 @@ var require_ms = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/ms@2.1
3117
3117
  * @return {String}
3118
3118
  * @api private
3119
3119
  */
3120
- function fmtLong(ms$4) {
3121
- var msAbs = Math.abs(ms$4);
3122
- if (msAbs >= d) return plural(ms$4, msAbs, d, "day");
3123
- if (msAbs >= h) return plural(ms$4, msAbs, h, "hour");
3124
- if (msAbs >= m) return plural(ms$4, msAbs, m, "minute");
3125
- if (msAbs >= s) return plural(ms$4, msAbs, s, "second");
3126
- return ms$4 + " ms";
3120
+ function fmtLong(ms$6) {
3121
+ var msAbs = Math.abs(ms$6);
3122
+ if (msAbs >= d) return plural(ms$6, msAbs, d, "day");
3123
+ if (msAbs >= h) return plural(ms$6, msAbs, h, "hour");
3124
+ if (msAbs >= m) return plural(ms$6, msAbs, m, "minute");
3125
+ if (msAbs >= s) return plural(ms$6, msAbs, s, "second");
3126
+ return ms$6 + " ms";
3127
3127
  }
3128
3128
  /**
3129
3129
  * Pluralization helper.
3130
3130
  */
3131
- function plural(ms$4, msAbs, n, name) {
3131
+ function plural(ms$6, msAbs, n, name) {
3132
3132
  var isPlural = msAbs >= n * 1.5;
3133
- return Math.round(ms$4 / n) + " " + name + (isPlural ? "s" : "");
3133
+ return Math.round(ms$6 / n) + " " + name + (isPlural ? "s" : "");
3134
3134
  }
3135
3135
  }) });
3136
3136
 
3137
3137
  //#endregion
3138
3138
  //#region src/types/duration.ts
3139
- var import_cjs$27 = require_cjs();
3139
+ var import_cjs$29 = require_cjs();
3140
3140
  init_source();
3141
- const Duration = (0, import_cjs$27.extendType)(import_cjs$27.string, {
3141
+ const Duration = (0, import_cjs$29.extendType)(import_cjs$29.string, {
3142
3142
  displayName: "num UNIT",
3143
3143
  description: "A duration, e.g. 5m, 10s, 1h",
3144
3144
  async from(string$2) {
@@ -3154,8 +3154,8 @@ const Duration = (0, import_cjs$27.extendType)(import_cjs$27.string, {
3154
3154
 
3155
3155
  //#endregion
3156
3156
  //#region src/args/timeout.ts
3157
- var import_cjs$26 = /* @__PURE__ */ __toESM(require_cjs());
3158
- const timeout = import_cjs$26.option({
3157
+ var import_cjs$28 = /* @__PURE__ */ __toESM(require_cjs());
3158
+ const timeout = import_cjs$28.option({
3159
3159
  long: "timeout",
3160
3160
  type: Duration,
3161
3161
  description: "The maximum duration a sandbox can run for. Example: 5m, 30m",
@@ -3165,17 +3165,17 @@ const timeout = import_cjs$26.option({
3165
3165
 
3166
3166
  //#endregion
3167
3167
  //#region src/args/vcpus.ts
3168
- var import_cjs$25 = /* @__PURE__ */ __toESM(require_cjs());
3169
- const vcpusType = import_cjs$25.extendType(import_cjs$25.number, {
3168
+ var import_cjs$27 = /* @__PURE__ */ __toESM(require_cjs());
3169
+ const vcpusType = import_cjs$27.extendType(import_cjs$27.number, {
3170
3170
  displayName: "COUNT",
3171
3171
  async from(n) {
3172
3172
  if (!Number.isInteger(n) || n < 1) throw new Error(`Invalid vCPU count: ${n}. Must be a positive integer.`);
3173
3173
  return n;
3174
3174
  }
3175
3175
  });
3176
- const vcpus = import_cjs$25.option({
3176
+ const vcpus = import_cjs$27.option({
3177
3177
  long: "vcpus",
3178
- type: import_cjs$25.optional(vcpusType),
3178
+ type: import_cjs$27.optional(vcpusType),
3179
3179
  description: "Number of vCPUs to allocate (each vCPU includes 2048 MB of memory)"
3180
3180
  });
3181
3181
 
@@ -3257,10 +3257,10 @@ const formatDistance = (token$1, count, options) => {
3257
3257
 
3258
3258
  //#endregion
3259
3259
  //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/locale/_lib/buildFormatLongFn.js
3260
- function buildFormatLongFn(args$4) {
3260
+ function buildFormatLongFn(args$5) {
3261
3261
  return (options = {}) => {
3262
- const width = options.width ? String(options.width) : args$4.defaultWidth;
3263
- return args$4.formats[width] || args$4.formats[args$4.defaultWidth];
3262
+ const width = options.width ? String(options.width) : args$5.defaultWidth;
3263
+ return args$5.formats[width] || args$5.formats[args$5.defaultWidth];
3264
3264
  };
3265
3265
  }
3266
3266
 
@@ -3344,20 +3344,20 @@ const formatRelative = (token$1, _date, _baseDate, _options$1) => formatRelative
3344
3344
  /**
3345
3345
  * The tuple of localized month values. The first element represents January.
3346
3346
  */
3347
- function buildLocalizeFn(args$4) {
3347
+ function buildLocalizeFn(args$5) {
3348
3348
  return (value, options) => {
3349
3349
  const context = options?.context ? String(options.context) : "standalone";
3350
3350
  let valuesArray;
3351
- if (context === "formatting" && args$4.formattingValues) {
3352
- const defaultWidth = args$4.defaultFormattingWidth || args$4.defaultWidth;
3351
+ if (context === "formatting" && args$5.formattingValues) {
3352
+ const defaultWidth = args$5.defaultFormattingWidth || args$5.defaultWidth;
3353
3353
  const width = options?.width ? String(options.width) : defaultWidth;
3354
- valuesArray = args$4.formattingValues[width] || args$4.formattingValues[defaultWidth];
3354
+ valuesArray = args$5.formattingValues[width] || args$5.formattingValues[defaultWidth];
3355
3355
  } else {
3356
- const defaultWidth = args$4.defaultWidth;
3357
- const width = options?.width ? String(options.width) : args$4.defaultWidth;
3358
- valuesArray = args$4.values[width] || args$4.values[defaultWidth];
3356
+ const defaultWidth = args$5.defaultWidth;
3357
+ const width = options?.width ? String(options.width) : args$5.defaultWidth;
3358
+ valuesArray = args$5.values[width] || args$5.values[defaultWidth];
3359
3359
  }
3360
- const index = args$4.argumentCallback ? args$4.argumentCallback(value) : value;
3360
+ const index = args$5.argumentCallback ? args$5.argumentCallback(value) : value;
3361
3361
  return valuesArray[index];
3362
3362
  };
3363
3363
  }
@@ -3574,17 +3574,17 @@ const localize = {
3574
3574
 
3575
3575
  //#endregion
3576
3576
  //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/locale/_lib/buildMatchFn.js
3577
- function buildMatchFn(args$4) {
3577
+ function buildMatchFn(args$5) {
3578
3578
  return (string$2, options = {}) => {
3579
3579
  const width = options.width;
3580
- const matchPattern = width && args$4.matchPatterns[width] || args$4.matchPatterns[args$4.defaultMatchWidth];
3580
+ const matchPattern = width && args$5.matchPatterns[width] || args$5.matchPatterns[args$5.defaultMatchWidth];
3581
3581
  const matchResult = string$2.match(matchPattern);
3582
3582
  if (!matchResult) return null;
3583
3583
  const matchedString = matchResult[0];
3584
- const parsePatterns = width && args$4.parsePatterns[width] || args$4.parsePatterns[args$4.defaultParseWidth];
3584
+ const parsePatterns = width && args$5.parsePatterns[width] || args$5.parsePatterns[args$5.defaultParseWidth];
3585
3585
  const key = Array.isArray(parsePatterns) ? findIndex(parsePatterns, (pattern) => pattern.test(matchedString)) : findKey(parsePatterns, (pattern) => pattern.test(matchedString));
3586
3586
  let value;
3587
- value = args$4.valueCallback ? args$4.valueCallback(key) : key;
3587
+ value = args$5.valueCallback ? args$5.valueCallback(key) : key;
3588
3588
  value = options.valueCallback ? options.valueCallback(value) : value;
3589
3589
  const rest$1 = string$2.slice(matchedString.length);
3590
3590
  return {
@@ -3602,14 +3602,14 @@ function findIndex(array$1, predicate) {
3602
3602
 
3603
3603
  //#endregion
3604
3604
  //#region ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/locale/_lib/buildMatchPatternFn.js
3605
- function buildMatchPatternFn(args$4) {
3605
+ function buildMatchPatternFn(args$5) {
3606
3606
  return (string$2, options = {}) => {
3607
- const matchResult = string$2.match(args$4.matchPattern);
3607
+ const matchResult = string$2.match(args$5.matchPattern);
3608
3608
  if (!matchResult) return null;
3609
3609
  const matchedString = matchResult[0];
3610
- const parseResult = string$2.match(args$4.parsePattern);
3610
+ const parseResult = string$2.match(args$5.parsePattern);
3611
3611
  if (!parseResult) return null;
3612
- let value = args$4.valueCallback ? args$4.valueCallback(parseResult[0]) : parseResult[0];
3612
+ let value = args$5.valueCallback ? args$5.valueCallback(parseResult[0]) : parseResult[0];
3613
3613
  value = options.valueCallback ? options.valueCallback(value) : value;
3614
3614
  const rest$1 = string$2.slice(matchedString.length);
3615
3615
  return {
@@ -4237,15 +4237,15 @@ function formatRunDuration(d$1) {
4237
4237
  return `${d$1 / 1e3}s`;
4238
4238
  }
4239
4239
  function formatNextCursorHint(cursor) {
4240
- const args$4 = process.argv.slice(2);
4240
+ const args$5 = process.argv.slice(2);
4241
4241
  const filtered = [];
4242
- for (let i = 0; i < args$4.length; i++) {
4243
- if (args$4[i] === "--cursor") {
4242
+ for (let i = 0; i < args$5.length; i++) {
4243
+ if (args$5[i] === "--cursor") {
4244
4244
  i++;
4245
4245
  continue;
4246
4246
  }
4247
- if (args$4[i].startsWith("--cursor=")) continue;
4248
- filtered.push(args$4[i]);
4247
+ if (args$5[i].startsWith("--cursor=")) continue;
4248
+ filtered.push(args$5[i]);
4249
4249
  }
4250
4250
  return `\nMore results: sandbox ${filtered.join(" ")} --cursor ${cursor}`;
4251
4251
  }
@@ -6754,10 +6754,10 @@ function _usingCtx() {
6754
6754
 
6755
6755
  //#endregion
6756
6756
  //#region src/commands/login.ts
6757
- var import_cjs$24 = /* @__PURE__ */ __toESM(require_cjs());
6757
+ var import_cjs$26 = /* @__PURE__ */ __toESM(require_cjs());
6758
6758
  init_source();
6759
6759
  const debug$6 = createDebugger("sandbox:login");
6760
- const login = import_cjs$24.command({
6760
+ const login = import_cjs$26.command({
6761
6761
  name: "login",
6762
6762
  description: "Log in to the Sandbox CLI",
6763
6763
  args: {},
@@ -6975,7 +6975,7 @@ var require_dist = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/@ver
6975
6975
 
6976
6976
  //#endregion
6977
6977
  //#region src/args/auth.ts
6978
- var import_cjs$23 = /* @__PURE__ */ __toESM(require_cjs());
6978
+ var import_cjs$25 = /* @__PURE__ */ __toESM(require_cjs());
6979
6979
  init_source();
6980
6980
  var import_dist = require_dist();
6981
6981
  const debug$5 = createDebugger("sandbox:args:auth");
@@ -6992,11 +6992,11 @@ function isTokenFresh() {
6992
6992
  function markTokenAsFresh() {
6993
6993
  freshTokenAcquiredAt = Date.now();
6994
6994
  }
6995
- const token = import_cjs$23.option({
6995
+ const token = import_cjs$25.option({
6996
6996
  long: "token",
6997
6997
  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.",
6998
6998
  type: {
6999
- ...import_cjs$23.string,
6999
+ ...import_cjs$25.string,
7000
7000
  displayName: "pat_or_oidc",
7001
7001
  defaultValueIsSerializable: false,
7002
7002
  onMissing: async () => {
@@ -7179,29 +7179,29 @@ function getAuthFailureStatus(error) {
7179
7179
 
7180
7180
  //#endregion
7181
7181
  //#region src/args/scope.ts
7182
- var import_cjs$22 = /* @__PURE__ */ __toESM(require_cjs());
7182
+ var import_cjs$24 = /* @__PURE__ */ __toESM(require_cjs());
7183
7183
  init_source();
7184
- const project = import_cjs$22.option({
7184
+ const project = import_cjs$24.option({
7185
7185
  long: "project",
7186
7186
  type: {
7187
- ...import_cjs$22.optional(import_cjs$22.string),
7187
+ ...import_cjs$24.optional(import_cjs$24.string),
7188
7188
  displayName: "my-project"
7189
7189
  },
7190
7190
  description: "The project name or ID to associate with the command. Can be inferred from VERCEL_OIDC_TOKEN."
7191
7191
  });
7192
7192
  /** Parser for the `--team` option. */
7193
- const teamParser = import_cjs$22.option({
7193
+ const teamParser = import_cjs$24.option({
7194
7194
  long: "team",
7195
7195
  type: {
7196
- ...import_cjs$22.optional(import_cjs$22.string),
7196
+ ...import_cjs$24.optional(import_cjs$24.string),
7197
7197
  displayName: "my-team"
7198
7198
  }
7199
7199
  });
7200
7200
  /** Parser for the `--scope` option. */
7201
- const scopeParser = import_cjs$22.option({
7201
+ const scopeParser = import_cjs$24.option({
7202
7202
  long: "scope",
7203
7203
  type: {
7204
- ...import_cjs$22.optional(import_cjs$22.string),
7204
+ ...import_cjs$24.optional(import_cjs$24.string),
7205
7205
  displayName: "my-team"
7206
7206
  },
7207
7207
  description: "The scope/team to associate with the command. Can be inferred from VERCEL_OIDC_TOKEN. [alias: --team]"
@@ -7290,7 +7290,7 @@ const scope = {
7290
7290
 
7291
7291
  //#endregion
7292
7292
  //#region package.json
7293
- var version = "3.0.0-beta.25";
7293
+ var version = "3.0.0-beta.26";
7294
7294
 
7295
7295
  //#endregion
7296
7296
  //#region src/error.ts
@@ -7318,6 +7318,10 @@ const sandboxClient = {
7318
7318
  fetch: fetchWithUserAgent,
7319
7319
  ...params
7320
7320
  })),
7321
+ fork: (params) => withErrorHandling(() => Sandbox.fork({
7322
+ fetch: fetchWithUserAgent,
7323
+ ...params
7324
+ })),
7321
7325
  list: (params) => withErrorHandling(() => Sandbox.list({
7322
7326
  fetch: fetchWithUserAgent,
7323
7327
  ...params
@@ -7329,10 +7333,6 @@ const snapshotClient = {
7329
7333
  ...params
7330
7334
  })),
7331
7335
  get: (params) => withErrorHandling(() => Snapshot.get({ ...params })),
7332
- fromSandbox: (name, opts) => withErrorHandling(() => Snapshot.fromSandbox(name, {
7333
- fetch: fetchWithUserAgent,
7334
- ...opts
7335
- })),
7336
7336
  tree: (params) => withErrorHandling(() => Snapshot.tree({
7337
7337
  fetch: fetchWithUserAgent,
7338
7338
  ...params
@@ -7389,9 +7389,9 @@ async function writeResponseToTemp({ response, text }) {
7389
7389
 
7390
7390
  //#endregion
7391
7391
  //#region src/args/snapshot-id.ts
7392
- var import_cjs$21 = /* @__PURE__ */ __toESM(require_cjs());
7392
+ var import_cjs$23 = /* @__PURE__ */ __toESM(require_cjs());
7393
7393
  init_source();
7394
- const snapshotId = import_cjs$21.extendType(import_cjs$21.string, {
7394
+ const snapshotId = import_cjs$23.extendType(import_cjs$23.string, {
7395
7395
  displayName: "snapshot_id",
7396
7396
  description: "The ID of the snapshot",
7397
7397
  async from(s$1) {
@@ -7401,10 +7401,82 @@ const snapshotId = import_cjs$21.extendType(import_cjs$21.string, {
7401
7401
  });
7402
7402
 
7403
7403
  //#endregion
7404
- //#region src/args/sandbox-name.ts
7404
+ //#region src/args/ports.ts
7405
+ var import_cjs$22 = /* @__PURE__ */ __toESM(require_cjs());
7406
+ init_source();
7407
+ const publishPorts = import_cjs$22.multioption({
7408
+ long: "publish-port",
7409
+ short: "p",
7410
+ description: "Publish sandbox port(s) to DOMAIN.vercel.run",
7411
+ type: import_cjs$22.array(import_cjs$22.extendType(import_cjs$22.number, {
7412
+ displayName: "PORT",
7413
+ async from(number) {
7414
+ if (!Number.isInteger(number) || number < 1024 || number > 65535) throw new Error([
7415
+ `Invalid port: ${number}.`,
7416
+ `${source_default.bold("hint:")} Ports must be integers between 1024-65535 (privileged ports 0-1023 are reserved).`,
7417
+ "Examples: 3000, 8443"
7418
+ ].join("\n"));
7419
+ return number;
7420
+ }
7421
+ }))
7422
+ });
7423
+
7424
+ //#endregion
7425
+ //#region src/types/snapshot-expiration.ts
7426
+ var import_cjs$21 = require_cjs();
7427
+ const SnapshotExpiration = (0, import_cjs$21.extendType)(import_cjs$21.string, {
7428
+ displayName: "DURATION|none",
7429
+ description: "A duration (e.g. 7d, 30d) or \"none\" for no expiration",
7430
+ async from(value) {
7431
+ if (value === "none") return "0";
7432
+ return Duration.from(value);
7433
+ }
7434
+ });
7435
+
7436
+ //#endregion
7437
+ //#region src/args/snapshot-retention.ts
7405
7438
  var import_cjs$20 = /* @__PURE__ */ __toESM(require_cjs());
7439
+ const snapshotExpiration = import_cjs$20.option({
7440
+ long: "snapshot-expiration",
7441
+ type: import_cjs$20.optional(SnapshotExpiration),
7442
+ description: "Default snapshot expiration. Use \"none\" or 0 for no expiration. Example: 7d, 30d"
7443
+ });
7444
+ const keepLastSnapshots = import_cjs$20.option({
7445
+ long: "keep-last-snapshots",
7446
+ type: import_cjs$20.optional(import_cjs$20.extendType(import_cjs$20.number, {
7447
+ displayName: "COUNT",
7448
+ async from(n) {
7449
+ if (!Number.isInteger(n) || n < 1 || n > 10) throw new Error(`Invalid --keep-last-snapshots value: ${n}. Must be an integer between 1 and 10.`);
7450
+ return n;
7451
+ }
7452
+ })),
7453
+ description: "Keep only the N most recent snapshots of this sandbox (1-10)."
7454
+ });
7455
+ const keepLastSnapshotsFor = import_cjs$20.option({
7456
+ long: "keep-last-snapshots-for",
7457
+ type: import_cjs$20.optional(SnapshotExpiration),
7458
+ description: "Expiration applied to kept snapshots. Use \"none\" or 0 for no expiration. Example: 7d, 30d"
7459
+ });
7460
+ const deleteEvictedSnapshots = import_cjs$20.option({
7461
+ long: "delete-evicted-snapshots",
7462
+ type: import_cjs$20.optional({
7463
+ ...import_cjs$20.oneOf(["true", "false"]),
7464
+ displayName: "true|false"
7465
+ }),
7466
+ description: "When \"true\" (the default), evicted snapshots are deleted immediately; when \"false\", they keep the default expiration."
7467
+ });
7468
+ const snapshotRetentionArgs = {
7469
+ snapshotExpiration,
7470
+ keepLastSnapshots,
7471
+ keepLastSnapshotsFor,
7472
+ deleteEvictedSnapshots
7473
+ };
7474
+
7475
+ //#endregion
7476
+ //#region src/args/sandbox-name.ts
7477
+ var import_cjs$19 = /* @__PURE__ */ __toESM(require_cjs());
7406
7478
  init_source();
7407
- const sandboxName = import_cjs$20.extendType(import_cjs$20.string, {
7479
+ const sandboxName = import_cjs$19.extendType(import_cjs$19.string, {
7408
7480
  displayName: "name",
7409
7481
  description: "The name of the sandbox",
7410
7482
  async from(s$1) {
@@ -11112,15 +11184,15 @@ async function waitForOpen(ws) {
11112
11184
  //#endregion
11113
11185
  //#region src/util/print-command.ts
11114
11186
  init_source();
11115
- function printCommand(command$1, args$4) {
11116
- return source_default.gray(source_default.dim("$ ") + [command$1, ...args$4].join(" "));
11187
+ function printCommand(command$1, args$5) {
11188
+ return source_default.gray(source_default.dim("$ ") + [command$1, ...args$5].join(" "));
11117
11189
  }
11118
11190
 
11119
11191
  //#endregion
11120
11192
  //#region src/interactive-shell/extend-sandbox-timeout.ts
11121
- var import_ms$3 = /* @__PURE__ */ __toESM(require_ms());
11193
+ var import_ms$5 = /* @__PURE__ */ __toESM(require_ms());
11122
11194
  const debug$2 = createDebugger("sandbox:timeout");
11123
- const BUFFER = (0, import_ms$3.default)("10 seconds");
11195
+ const BUFFER = (0, import_ms$5.default)("10 seconds");
11124
11196
  async function extendSandboxTimeoutPeriodically(sandbox, signal) {
11125
11197
  const session = sandbox.currentSession();
11126
11198
  const timeout$1 = session.timeout;
@@ -11135,7 +11207,7 @@ async function extendSandboxTimeoutPeriodically(sandbox, signal) {
11135
11207
  debug$2(`sleeping for ${sleepMs}ms until next timeout extension`);
11136
11208
  await setTimeout$1(sleepMs, null, { signal });
11137
11209
  }
11138
- await sandbox.extendTimeout((0, import_ms$3.default)("5 minutes"));
11210
+ await sandbox.extendTimeout((0, import_ms$5.default)("5 minutes"));
11139
11211
  const updatedTimeout = session.timeout;
11140
11212
  if (updatedTimeout == null) return;
11141
11213
  const nextTick$1 = session.createdAt.getTime() + updatedTimeout;
@@ -11409,9 +11481,9 @@ function getStderrStream() {
11409
11481
 
11410
11482
  //#endregion
11411
11483
  //#region src/args/key-value-pair.ts
11412
- var import_cjs$19 = /* @__PURE__ */ __toESM(require_cjs());
11484
+ var import_cjs$18 = /* @__PURE__ */ __toESM(require_cjs());
11413
11485
  init_source();
11414
- const KeyValuePair = import_cjs$19.extendType(import_cjs$19.string, {
11486
+ const KeyValuePair = import_cjs$18.extendType(import_cjs$18.string, {
11415
11487
  displayName: "key=value",
11416
11488
  async from(input) {
11417
11489
  if (!input.includes("=")) return {
@@ -11425,7 +11497,7 @@ const KeyValuePair = import_cjs$19.extendType(import_cjs$19.string, {
11425
11497
  };
11426
11498
  }
11427
11499
  });
11428
- const ObjectFromKeyValue = import_cjs$19.extendType(import_cjs$19.array(KeyValuePair), { async from(input) {
11500
+ const ObjectFromKeyValue = import_cjs$18.extendType(import_cjs$18.array(KeyValuePair), { async from(input) {
11429
11501
  const obj = Object.create(null);
11430
11502
  const missingVars = [];
11431
11503
  for (const { key, value } of input) if (value === void 0) missingVars.push(key);
@@ -11439,27 +11511,27 @@ const ObjectFromKeyValue = import_cjs$19.extendType(import_cjs$19.array(KeyValue
11439
11511
 
11440
11512
  //#endregion
11441
11513
  //#region src/commands/exec.ts
11442
- var import_cjs$18 = /* @__PURE__ */ __toESM(require_cjs());
11514
+ var import_cjs$17 = /* @__PURE__ */ __toESM(require_cjs());
11443
11515
  init_source();
11444
- const args$3 = {
11445
- sandbox: import_cjs$18.positional({ type: sandboxName }),
11446
- command: import_cjs$18.positional({
11516
+ const args$4 = {
11517
+ sandbox: import_cjs$17.positional({ type: sandboxName }),
11518
+ command: import_cjs$17.positional({
11447
11519
  displayName: "command",
11448
11520
  description: "The executable to invoke"
11449
11521
  }),
11450
- args: import_cjs$18.rest({
11522
+ args: import_cjs$17.rest({
11451
11523
  displayName: "args",
11452
11524
  description: "arguments to pass to the command"
11453
11525
  }),
11454
- asSudo: import_cjs$18.flag({
11526
+ asSudo: import_cjs$17.flag({
11455
11527
  long: "sudo",
11456
11528
  description: "Give extended privileges to the command."
11457
11529
  }),
11458
- interactive: import_cjs$18.flag({
11530
+ interactive: import_cjs$17.flag({
11459
11531
  long: "interactive",
11460
11532
  short: "i",
11461
11533
  description: "Run the command in a secure interactive shell",
11462
- type: import_cjs$18.extendType(import_cjs$18.boolean, {
11534
+ type: import_cjs$17.extendType(import_cjs$17.boolean, {
11463
11535
  defaultValue() {
11464
11536
  return false;
11465
11537
  },
@@ -11469,22 +11541,22 @@ const args$3 = {
11469
11541
  }
11470
11542
  })
11471
11543
  }),
11472
- skipExtendingTimeout: import_cjs$18.flag({
11544
+ skipExtendingTimeout: import_cjs$17.flag({
11473
11545
  long: "no-extend-timeout",
11474
11546
  description: "Do not extend the sandbox timeout while running an interactive command. Only affects interactive executions."
11475
11547
  }),
11476
- tty: import_cjs$18.flag({
11548
+ tty: import_cjs$17.flag({
11477
11549
  long: "tty",
11478
11550
  short: "t",
11479
11551
  description: "Allocate a tty for an interactive command. This is a no-op."
11480
11552
  }),
11481
- cwd: import_cjs$18.option({
11553
+ cwd: import_cjs$17.option({
11482
11554
  long: "workdir",
11483
11555
  short: "w",
11484
11556
  description: "The working directory to run the command in",
11485
- type: import_cjs$18.optional(import_cjs$18.string)
11557
+ type: import_cjs$17.optional(import_cjs$17.string)
11486
11558
  }),
11487
- envVars: import_cjs$18.multioption({
11559
+ envVars: import_cjs$17.multioption({
11488
11560
  long: "env",
11489
11561
  short: "e",
11490
11562
  type: ObjectFromKeyValue,
@@ -11492,11 +11564,11 @@ const args$3 = {
11492
11564
  }),
11493
11565
  scope
11494
11566
  };
11495
- const exec = import_cjs$18.command({
11567
+ const exec = import_cjs$17.command({
11496
11568
  name: "exec",
11497
11569
  description: "Execute a command in an existing sandbox",
11498
- args: args$3,
11499
- async handler({ command: command$1, cwd, args: args$4, asSudo, sandbox: sandboxName$1, scope: { token: token$1, team: team$1, project: project$1 }, interactive, envVars, skipExtendingTimeout }) {
11570
+ args: args$4,
11571
+ async handler({ command: command$1, cwd, args: args$5, asSudo, sandbox: sandboxName$1, scope: { token: token$1, team: team$1, project: project$1 }, interactive, envVars, skipExtendingTimeout }) {
11500
11572
  const sandbox = typeof sandboxName$1 !== "string" ? sandboxName$1 : await sandboxClient.get({
11501
11573
  name: sandboxName$1,
11502
11574
  projectId: project$1,
@@ -11505,10 +11577,10 @@ const exec = import_cjs$18.command({
11505
11577
  __includeSystemRoutes: true
11506
11578
  });
11507
11579
  if (!interactive) {
11508
- console.error(printCommand(command$1, args$4));
11580
+ console.error(printCommand(command$1, args$5));
11509
11581
  const result = await sandbox.runCommand({
11510
11582
  cmd: command$1,
11511
- args: args$4,
11583
+ args: args$5,
11512
11584
  stderr: process.stderr,
11513
11585
  stdout: process.stdout,
11514
11586
  sudo: asSudo,
@@ -11519,7 +11591,7 @@ const exec = import_cjs$18.command({
11519
11591
  } else await startInteractiveShell({
11520
11592
  sandbox,
11521
11593
  cwd,
11522
- execution: [command$1, ...args$4],
11594
+ execution: [command$1, ...args$5],
11523
11595
  envVars,
11524
11596
  sudo: asSudo,
11525
11597
  skipExtendingTimeout
@@ -11529,9 +11601,9 @@ const exec = import_cjs$18.command({
11529
11601
 
11530
11602
  //#endregion
11531
11603
  //#region src/args/network-policy.ts
11532
- var import_cjs$17 = /* @__PURE__ */ __toESM(require_cjs());
11604
+ var import_cjs$16 = /* @__PURE__ */ __toESM(require_cjs());
11533
11605
  init_source();
11534
- const networkPolicyMode = import_cjs$17.extendType(import_cjs$17.string, {
11606
+ const networkPolicyMode = import_cjs$16.extendType(import_cjs$16.string, {
11535
11607
  displayName: "MODE",
11536
11608
  async from(value) {
11537
11609
  const validModes = ["allow-all", "deny-all"];
@@ -11539,28 +11611,28 @@ const networkPolicyMode = import_cjs$17.extendType(import_cjs$17.string, {
11539
11611
  return value;
11540
11612
  }
11541
11613
  });
11542
- const networkPolicy = import_cjs$17.option({
11614
+ const networkPolicy = import_cjs$16.option({
11543
11615
  long: "network-policy",
11544
11616
  description: `Network policy mode: "allow-all" or "deny-all"
11545
11617
  - allow-all: sandbox can access any website/domain
11546
11618
  - deny-all: sandbox has no network access
11547
11619
  Omit this option and use --allowed-domain / --allowed-cidr / --denied-cidr for custom policies.`,
11548
- type: import_cjs$17.optional(networkPolicyMode)
11620
+ type: import_cjs$16.optional(networkPolicyMode)
11549
11621
  });
11550
- const allowedDomains = import_cjs$17.multioption({
11622
+ const allowedDomains = import_cjs$16.multioption({
11551
11623
  long: "allowed-domain",
11552
11624
  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.`,
11553
- type: import_cjs$17.array(import_cjs$17.string)
11625
+ type: import_cjs$16.array(import_cjs$16.string)
11554
11626
  });
11555
- const allowedCIDRs = import_cjs$17.multioption({
11627
+ const allowedCIDRs = import_cjs$16.multioption({
11556
11628
  long: "allowed-cidr",
11557
11629
  description: `CIDR to allow traffic to (creates a custom network policy). Takes precedence over 'allowed-domain'.`,
11558
- type: import_cjs$17.array(import_cjs$17.string)
11630
+ type: import_cjs$16.array(import_cjs$16.string)
11559
11631
  });
11560
- const deniedCIDRs = import_cjs$17.multioption({
11632
+ const deniedCIDRs = import_cjs$16.multioption({
11561
11633
  long: "denied-cidr",
11562
11634
  description: `CIDR to deny traffic to (creates a custom network policy). Takes precedence over allowed domains/CIDRs.`,
11563
- type: import_cjs$17.array(import_cjs$17.string)
11635
+ type: import_cjs$16.array(import_cjs$16.string)
11564
11636
  });
11565
11637
  const networkPolicyArgs = {
11566
11638
  networkPolicy,
@@ -11583,8 +11655,8 @@ function resolveMode(networkPolicy$1, mode) {
11583
11655
  /**
11584
11656
  * Builds a NetworkPolicy from CLI arguments.
11585
11657
  */
11586
- function buildNetworkPolicy(args$4) {
11587
- const { networkPolicy: networkPolicy$1, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 } = args$4;
11658
+ function buildNetworkPolicy(args$5) {
11659
+ const { networkPolicy: networkPolicy$1, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 } = args$5;
11588
11660
  const hasListOptions = allowedDomains$1.length > 0 || allowedCIDRs$1.length > 0 || deniedCIDRs$1.length > 0;
11589
11661
  if (networkPolicy$1 && hasListOptions) throw new Error([`Cannot combine --network-policy=${networkPolicy$1} with --allowed-domain, --allowed-cidr, or --denied-cidr.`, `${source_default.bold("hint:")} Use --allowed-domain / --allowed-cidr / --denied-cidr without --network-policy for custom policies.`].join("\n"));
11590
11662
  if (hasListOptions) return {
@@ -11598,50 +11670,74 @@ function buildNetworkPolicy(args$4) {
11598
11670
  }
11599
11671
 
11600
11672
  //#endregion
11601
- //#region src/types/snapshot-expiration.ts
11602
- var import_cjs$16 = require_cjs();
11603
- const SnapshotExpiration = (0, import_cjs$16.extendType)(import_cjs$16.string, {
11604
- displayName: "DURATION|none",
11605
- description: "A duration (e.g. 7d, 30d) or \"none\" for no expiration",
11606
- async from(value) {
11607
- if (value === "none") return "0";
11608
- return Duration.from(value);
11609
- }
11610
- });
11673
+ //#region src/util/keep-last-snapshots.ts
11674
+ var import_ms$4 = /* @__PURE__ */ __toESM(require_ms());
11675
+ init_source();
11676
+ /**
11677
+ * Validates the `--keep-last-snapshots*` flag combination and builds the
11678
+ * payload object that the SDK expects, or returns `undefined` when no
11679
+ * retention policy was configured.
11680
+ *
11681
+ * Throws when `--keep-last-snapshots-for` or `--delete-evicted-snapshots` are
11682
+ * passed without `--keep-last-snapshots`.
11683
+ */
11684
+ function buildKeepLastSnapshotsPayload(input) {
11685
+ const { keepLastSnapshots: keepLastSnapshots$1, keepLastSnapshotsFor: keepLastSnapshotsFor$1, deleteEvictedSnapshots: deleteEvictedSnapshots$1 } = input;
11686
+ if (keepLastSnapshots$1 === void 0 && (keepLastSnapshotsFor$1 !== void 0 || deleteEvictedSnapshots$1 !== void 0)) throw new Error(["--keep-last-snapshots-for and --delete-evicted-snapshots require --keep-last-snapshots.", `${source_default.bold("hint:")} Pass --keep-last-snapshots <count> to enable the retention policy.`].join("\n"));
11687
+ if (keepLastSnapshots$1 === void 0) return;
11688
+ return {
11689
+ count: keepLastSnapshots$1,
11690
+ expiration: keepLastSnapshotsFor$1 !== void 0 ? (0, import_ms$4.default)(keepLastSnapshotsFor$1) : void 0,
11691
+ deleteEvicted: deleteEvictedSnapshots$1 !== void 0 ? deleteEvictedSnapshots$1 === "true" : void 0
11692
+ };
11693
+ }
11611
11694
 
11612
11695
  //#endregion
11613
- //#region src/args/ports.ts
11614
- var import_cjs$15 = /* @__PURE__ */ __toESM(require_cjs());
11696
+ //#region src/util/print-sandbox-summary.ts
11615
11697
  init_source();
11616
- const publishPorts = import_cjs$15.multioption({
11617
- long: "publish-port",
11618
- short: "p",
11619
- description: "Publish sandbox port(s) to DOMAIN.vercel.run",
11620
- type: import_cjs$15.array(import_cjs$15.extendType(import_cjs$15.number, {
11621
- displayName: "PORT",
11622
- async from(number) {
11623
- if (!Number.isInteger(number) || number < 1024 || number > 65535) throw new Error([
11624
- `Invalid port: ${number}.`,
11625
- `${source_default.bold("hint:")} Ports must be integers between 1024-65535 (privileged ports 0-1023 are reserved).`,
11626
- "Examples: 3000, 8443"
11627
- ].join("\n"));
11628
- return number;
11629
- }
11630
- }))
11631
- });
11698
+ /**
11699
+ * Print the "✅ Sandbox <name> <action>." summary that the create and fork
11700
+ * commands emit after a successful creation, including project/team and any
11701
+ * published port routes.
11702
+ *
11703
+ * - The sandbox name is written to stdout, everything else to stderr — so
11704
+ * `sandbox create | xargs -I {} sandbox exec {} -- ...` keeps working.
11705
+ * - Pass `action: "created"` for create, or `action: \`forked from ${chalk.cyan(source)}\``
11706
+ * for fork.
11707
+ */
11708
+ function printSandboxSummary(opts) {
11709
+ const { sandbox, scope: scope$1, action } = opts;
11710
+ const teamDisplay = scope$1.teamSlug ?? scope$1.team;
11711
+ const projectDisplay = scope$1.projectSlug ?? scope$1.project;
11712
+ const routes = sandbox.routes.filter((x) => x.port !== sandbox.interactivePort);
11713
+ const hasPorts = routes.length > 0;
11714
+ process.stderr.write("✅ Sandbox ");
11715
+ process.stdout.write(source_default.cyan(sandbox.name));
11716
+ process.stderr.write(" " + action + ".\n");
11717
+ process.stderr.write(source_default.dim(" │ ") + "team: " + source_default.cyan(teamDisplay) + "\n");
11718
+ if (hasPorts) {
11719
+ process.stderr.write(source_default.dim(" │ ") + "project: " + source_default.cyan(projectDisplay) + "\n");
11720
+ process.stderr.write(source_default.dim(" │ ") + "ports:\n");
11721
+ for (let i = 0; i < routes.length; i++) {
11722
+ const route = routes[i];
11723
+ const prefix$1 = i === routes.length - 1 ? source_default.dim(" ╰ ") : source_default.dim(" │ ");
11724
+ process.stderr.write(prefix$1 + "• " + route.port + " -> " + source_default.cyan(route.url) + "\n");
11725
+ }
11726
+ } else process.stderr.write(source_default.dim(" ╰ ") + "project: " + source_default.cyan(projectDisplay) + "\n");
11727
+ }
11632
11728
 
11633
11729
  //#endregion
11634
11730
  //#region src/commands/create.ts
11635
- var import_cjs$14 = /* @__PURE__ */ __toESM(require_cjs());
11636
- var import_ms$2 = /* @__PURE__ */ __toESM(require_ms());
11731
+ var import_cjs$15 = /* @__PURE__ */ __toESM(require_cjs());
11732
+ var import_ms$3 = /* @__PURE__ */ __toESM(require_ms());
11637
11733
  init_source();
11638
- const args$2 = {
11639
- name: import_cjs$14.option({
11734
+ const args$3 = {
11735
+ name: import_cjs$15.option({
11640
11736
  long: "name",
11641
11737
  description: "A user-chosen name for the sandbox. It must be unique per project.",
11642
- type: import_cjs$14.optional(import_cjs$14.string)
11738
+ type: import_cjs$15.optional(import_cjs$15.string)
11643
11739
  }),
11644
- nonPersistent: import_cjs$14.flag({
11740
+ nonPersistent: import_cjs$15.flag({
11645
11741
  long: "non-persistent",
11646
11742
  description: "Disable automatic restore of the filesystem between sessions."
11647
11743
  }),
@@ -11649,117 +11745,77 @@ const args$2 = {
11649
11745
  timeout,
11650
11746
  vcpus,
11651
11747
  ports: publishPorts,
11652
- silent: import_cjs$14.flag({
11748
+ silent: import_cjs$15.flag({
11653
11749
  long: "silent",
11654
11750
  description: "Don't write sandbox name to stdout"
11655
11751
  }),
11656
- snapshot: import_cjs$14.option({
11752
+ snapshot: import_cjs$15.option({
11657
11753
  long: "snapshot",
11658
11754
  short: "s",
11659
11755
  description: "Start the sandbox from a snapshot ID",
11660
- type: import_cjs$14.optional(snapshotId)
11756
+ type: import_cjs$15.optional(snapshotId)
11661
11757
  }),
11662
- sandboxSnapshot: import_cjs$14.option({
11663
- long: "sandbox-snapshot",
11664
- description: "Start the sandbox from another sandbox's current snapshot",
11665
- type: import_cjs$14.optional(sandboxName)
11666
- }),
11667
- connect: import_cjs$14.flag({
11758
+ connect: import_cjs$15.flag({
11668
11759
  long: "connect",
11669
11760
  description: "Start an interactive shell session after creating the sandbox"
11670
11761
  }),
11671
- envVars: import_cjs$14.multioption({
11762
+ envVars: import_cjs$15.multioption({
11672
11763
  long: "env",
11673
11764
  short: "e",
11674
11765
  type: ObjectFromKeyValue,
11675
11766
  description: "Default environment variables for sandbox commands"
11676
11767
  }),
11677
- tags: import_cjs$14.multioption({
11768
+ tags: import_cjs$15.multioption({
11678
11769
  long: "tag",
11679
11770
  short: "t",
11680
11771
  type: ObjectFromKeyValue,
11681
11772
  description: "Key-value tags to associate with the sandbox (e.g. --tag env=staging)"
11682
11773
  }),
11683
- snapshotExpiration: import_cjs$14.option({
11684
- long: "snapshot-expiration",
11685
- type: import_cjs$14.optional(SnapshotExpiration),
11686
- description: "Default snapshot expiration. Use \"none\" or 0 for no expiration. Example: 7d, 30d"
11687
- }),
11688
- keepLastSnapshots: import_cjs$14.option({
11689
- long: "keep-last-snapshots",
11690
- type: import_cjs$14.optional(import_cjs$14.extendType(import_cjs$14.number, {
11691
- displayName: "COUNT",
11692
- async from(n) {
11693
- if (!Number.isInteger(n) || n < 1 || n > 10) throw new Error(`Invalid --keep-last-snapshots value: ${n}. Must be an integer between 1 and 10.`);
11694
- return n;
11695
- }
11696
- })),
11697
- description: "Keep only the N most recent snapshots of this sandbox (1-10)."
11698
- }),
11699
- keepLastSnapshotsFor: import_cjs$14.option({
11700
- long: "keep-last-snapshots-for",
11701
- type: import_cjs$14.optional(SnapshotExpiration),
11702
- description: "Expiration applied to kept snapshots. Use \"none\" or 0 for no expiration. Example: 7d, 30d"
11703
- }),
11704
- deleteEvictedSnapshots: import_cjs$14.option({
11705
- long: "delete-evicted-snapshots",
11706
- type: import_cjs$14.optional({
11707
- ...import_cjs$14.oneOf(["true", "false"]),
11708
- displayName: "true|false"
11709
- }),
11710
- description: "When \"true\" (the default), evicted snapshots are deleted immediately; when \"false\", they keep the default expiration."
11711
- }),
11774
+ ...snapshotRetentionArgs,
11712
11775
  ...networkPolicyArgs,
11713
11776
  scope
11714
11777
  };
11715
- const create = import_cjs$14.command({
11778
+ const create = import_cjs$15.command({
11716
11779
  name: "create",
11717
11780
  description: "Create a sandbox in the specified account and project.",
11718
- args: args$2,
11781
+ args: args$3,
11719
11782
  examples: [{
11720
11783
  description: "Create and connect to a sandbox without a network access",
11721
11784
  command: `sandbox run --network-policy=none --connect`
11722
11785
  }],
11723
- async handler({ name, nonPersistent, ports, scope: scope$1, runtime: runtime$1, timeout: timeout$1, vcpus: vcpus$1, silent, snapshot: snapshot$1, sandboxSnapshot, connect: connect$2, envVars, tags, snapshotExpiration, keepLastSnapshots, keepLastSnapshotsFor, deleteEvictedSnapshots, networkPolicy: networkPolicyMode$1, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 }) {
11724
- if (snapshot$1 && sandboxSnapshot) throw new Error([`Cannot use --snapshot and --sandbox-snapshot together.`, `${source_default.bold("hint:")} Pick one source for the new sandbox.`].join("\n"));
11786
+ 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: snapshotExpiration$1, keepLastSnapshots: keepLastSnapshots$1, keepLastSnapshotsFor: keepLastSnapshotsFor$1, deleteEvictedSnapshots: deleteEvictedSnapshots$1, networkPolicy: networkPolicyMode$1, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 }) {
11725
11787
  const networkPolicy$1 = buildNetworkPolicy({
11726
11788
  networkPolicy: networkPolicyMode$1,
11727
11789
  allowedDomains: allowedDomains$1,
11728
11790
  allowedCIDRs: allowedCIDRs$1,
11729
11791
  deniedCIDRs: deniedCIDRs$1
11730
11792
  });
11731
- if (keepLastSnapshots === void 0 && (keepLastSnapshotsFor !== void 0 || deleteEvictedSnapshots !== void 0)) throw new Error(["--keep-last-snapshots-for and --delete-evicted-snapshots require --keep-last-snapshots.", `${source_default.bold("hint:")} Pass --keep-last-snapshots <count> to enable the retention policy.`].join("\n"));
11732
- const keepLastSnapshotsPayload = keepLastSnapshots !== void 0 ? {
11733
- count: keepLastSnapshots,
11734
- expiration: keepLastSnapshotsFor !== void 0 ? (0, import_ms$2.default)(keepLastSnapshotsFor) : void 0,
11735
- deleteEvicted: deleteEvictedSnapshots !== void 0 ? deleteEvictedSnapshots === "true" : void 0
11736
- } : void 0;
11793
+ const keepLastSnapshotsPayload = buildKeepLastSnapshotsPayload({
11794
+ keepLastSnapshots: keepLastSnapshots$1,
11795
+ keepLastSnapshotsFor: keepLastSnapshotsFor$1,
11796
+ deleteEvictedSnapshots: deleteEvictedSnapshots$1
11797
+ });
11737
11798
  const persistent = !nonPersistent;
11738
11799
  const resources = vcpus$1 ? { vcpus: vcpus$1 } : void 0;
11739
11800
  const tagsObj = Object.keys(tags).length > 0 ? tags : void 0;
11740
- const resolvedSnapshot = snapshot$1 ?? (sandboxSnapshot ? await snapshotClient.fromSandbox(sandboxSnapshot, {
11741
- teamId: scope$1.team,
11742
- projectId: scope$1.project,
11743
- token: scope$1.token
11744
- }) : void 0);
11745
11801
  const spinner = silent ? void 0 : ora("Creating sandbox...").start();
11746
- const sandbox = resolvedSnapshot ? await sandboxClient.create({
11802
+ const sandbox = snapshot$1 ? await sandboxClient.create({
11747
11803
  name,
11748
11804
  source: {
11749
11805
  type: "snapshot",
11750
- snapshotId: resolvedSnapshot
11806
+ snapshotId: snapshot$1
11751
11807
  },
11752
11808
  teamId: scope$1.team,
11753
11809
  projectId: scope$1.project,
11754
11810
  token: scope$1.token,
11755
11811
  ports,
11756
- timeout: (0, import_ms$2.default)(timeout$1),
11812
+ timeout: (0, import_ms$3.default)(timeout$1),
11757
11813
  resources,
11758
11814
  networkPolicy: networkPolicy$1,
11759
11815
  env: envVars,
11760
11816
  tags: tagsObj,
11761
11817
  persistent,
11762
- snapshotExpiration: snapshotExpiration ? (0, import_ms$2.default)(snapshotExpiration) : void 0,
11818
+ snapshotExpiration: snapshotExpiration$1 ? (0, import_ms$3.default)(snapshotExpiration$1) : void 0,
11763
11819
  keepLastSnapshots: keepLastSnapshotsPayload,
11764
11820
  __interactive: true
11765
11821
  }) : await sandboxClient.create({
@@ -11769,13 +11825,13 @@ const create = import_cjs$14.command({
11769
11825
  token: scope$1.token,
11770
11826
  ports,
11771
11827
  runtime: runtime$1,
11772
- timeout: (0, import_ms$2.default)(timeout$1),
11828
+ timeout: (0, import_ms$3.default)(timeout$1),
11773
11829
  resources,
11774
11830
  networkPolicy: networkPolicy$1,
11775
11831
  env: envVars,
11776
11832
  tags: tagsObj,
11777
11833
  persistent,
11778
- snapshotExpiration: snapshotExpiration ? (0, import_ms$2.default)(snapshotExpiration) : void 0,
11834
+ snapshotExpiration: snapshotExpiration$1 ? (0, import_ms$3.default)(snapshotExpiration$1) : void 0,
11779
11835
  keepLastSnapshots: keepLastSnapshotsPayload,
11780
11836
  __interactive: true
11781
11837
  });
@@ -11785,25 +11841,132 @@ const create = import_cjs$14.command({
11785
11841
  `${source_default.bold("hint:")} This is an internal error. Please try again.`,
11786
11842
  "╰▶ Report this issue: https://github.com/vercel/sandbox/issues"
11787
11843
  ].join("\n"));
11788
- const routes = sandbox.routes.filter((x) => x.port !== sandbox.interactivePort);
11789
- if (!silent) {
11790
- const teamDisplay = scope$1.teamSlug ?? scope$1.team;
11791
- const projectDisplay = scope$1.projectSlug ?? scope$1.project;
11792
- const hasPorts = routes.length > 0;
11793
- process.stderr.write("✅ Sandbox ");
11794
- process.stdout.write(source_default.cyan(sandbox.name));
11795
- process.stderr.write(" created.\n");
11796
- process.stderr.write(source_default.dim(" │ ") + "team: " + source_default.cyan(teamDisplay) + "\n");
11797
- if (hasPorts) {
11798
- process.stderr.write(source_default.dim(" │ ") + "project: " + source_default.cyan(projectDisplay) + "\n");
11799
- process.stderr.write(source_default.dim(" │ ") + "ports:\n");
11800
- for (let i = 0; i < routes.length; i++) {
11801
- const route = routes[i];
11802
- const prefix$1 = i === routes.length - 1 ? source_default.dim(" ╰ ") : source_default.dim(" │ ");
11803
- process.stderr.write(prefix$1 + "• " + route.port + " -> " + source_default.cyan(route.url) + "\n");
11804
- }
11805
- } else process.stderr.write(source_default.dim(" ╰ ") + "project: " + source_default.cyan(projectDisplay) + "\n");
11806
- }
11844
+ if (!silent) printSandboxSummary({
11845
+ sandbox,
11846
+ scope: scope$1,
11847
+ action: "created"
11848
+ });
11849
+ if (connect$2) await exec.handler({
11850
+ scope: scope$1,
11851
+ asSudo: false,
11852
+ args: [],
11853
+ cwd: void 0,
11854
+ skipExtendingTimeout: false,
11855
+ envVars: {},
11856
+ command: "sh",
11857
+ interactive: true,
11858
+ tty: true,
11859
+ sandbox
11860
+ });
11861
+ return sandbox;
11862
+ }
11863
+ });
11864
+
11865
+ //#endregion
11866
+ //#region src/commands/fork.ts
11867
+ var import_cjs$14 = /* @__PURE__ */ __toESM(require_cjs());
11868
+ var import_ms$2 = /* @__PURE__ */ __toESM(require_ms());
11869
+ init_source();
11870
+ const args$2 = {
11871
+ source: import_cjs$14.positional({
11872
+ displayName: "source",
11873
+ description: "Name of the source sandbox to fork from.",
11874
+ type: sandboxName
11875
+ }),
11876
+ name: import_cjs$14.option({
11877
+ long: "name",
11878
+ description: "A user-chosen name for the forked sandbox. Must be unique per project.",
11879
+ type: import_cjs$14.optional(import_cjs$14.string)
11880
+ }),
11881
+ nonPersistent: import_cjs$14.flag({
11882
+ long: "non-persistent",
11883
+ description: "Disable automatic restore of the filesystem between sessions."
11884
+ }),
11885
+ timeout: import_cjs$14.option({
11886
+ long: "timeout",
11887
+ type: import_cjs$14.optional(Duration),
11888
+ description: "Override the maximum sandbox runtime (inherited from source if omitted). Example: 5m, 30m"
11889
+ }),
11890
+ vcpus,
11891
+ ports: publishPorts,
11892
+ silent: import_cjs$14.flag({
11893
+ long: "silent",
11894
+ description: "Don't write sandbox name to stdout"
11895
+ }),
11896
+ connect: import_cjs$14.flag({
11897
+ long: "connect",
11898
+ description: "Start an interactive shell session after creating the forked sandbox"
11899
+ }),
11900
+ envVars: import_cjs$14.multioption({
11901
+ long: "env",
11902
+ short: "e",
11903
+ type: ObjectFromKeyValue,
11904
+ description: "Environment variables to set on the fork. Env vars from the source sandbox are not copied (encrypted server-side)."
11905
+ }),
11906
+ tags: import_cjs$14.multioption({
11907
+ long: "tag",
11908
+ short: "t",
11909
+ type: ObjectFromKeyValue,
11910
+ description: "Key-value tags to associate with the fork. When provided, fully replaces the tags copied from the source (no per-key merge)."
11911
+ }),
11912
+ ...snapshotRetentionArgs,
11913
+ ...networkPolicyArgs,
11914
+ scope
11915
+ };
11916
+ const fork = import_cjs$14.command({
11917
+ name: "fork",
11918
+ description: "Fork an existing sandbox into a new one. Copies config (cpu, timeout, network policy, tags, etc.) from the source sandbox; env vars are NOT copied and must be re-supplied via --env.",
11919
+ args: args$2,
11920
+ examples: [{
11921
+ description: "Fork a sandbox with all config copied from the source",
11922
+ command: `sandbox fork my-source`
11923
+ }, {
11924
+ description: "Fork with a specific name and overridden vcpus",
11925
+ command: `sandbox fork my-source --name my-forked-sandbox --vcpus 4`
11926
+ }],
11927
+ async handler({ source, name, nonPersistent, ports, scope: scope$1, timeout: timeout$1, vcpus: vcpus$1, silent, connect: connect$2, envVars, tags, snapshotExpiration: snapshotExpiration$1, keepLastSnapshots: keepLastSnapshots$1, keepLastSnapshotsFor: keepLastSnapshotsFor$1, deleteEvictedSnapshots: deleteEvictedSnapshots$1, networkPolicy: networkPolicyMode$1, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 }) {
11928
+ const networkPolicy$1 = networkPolicyMode$1 !== void 0 || allowedDomains$1.length > 0 || allowedCIDRs$1.length > 0 || deniedCIDRs$1.length > 0 ? buildNetworkPolicy({
11929
+ networkPolicy: networkPolicyMode$1,
11930
+ allowedDomains: allowedDomains$1,
11931
+ allowedCIDRs: allowedCIDRs$1,
11932
+ deniedCIDRs: deniedCIDRs$1
11933
+ }) : void 0;
11934
+ const keepLastSnapshotsPayload = buildKeepLastSnapshotsPayload({
11935
+ keepLastSnapshots: keepLastSnapshots$1,
11936
+ keepLastSnapshotsFor: keepLastSnapshotsFor$1,
11937
+ deleteEvictedSnapshots: deleteEvictedSnapshots$1
11938
+ });
11939
+ const tagsObj = Object.keys(tags).length > 0 ? tags : void 0;
11940
+ const envObj = Object.keys(envVars).length > 0 ? envVars : void 0;
11941
+ const spinner = silent ? void 0 : ora(`Forking sandbox ${source_default.cyan(source)}...`).start();
11942
+ const sandbox = await sandboxClient.fork({
11943
+ sourceSandbox: source,
11944
+ teamId: scope$1.team,
11945
+ projectId: scope$1.project,
11946
+ token: scope$1.token,
11947
+ ...name !== void 0 && { name },
11948
+ ...ports.length > 0 && { ports },
11949
+ ...timeout$1 !== void 0 && { timeout: (0, import_ms$2.default)(timeout$1) },
11950
+ ...vcpus$1 !== void 0 && { resources: { vcpus: vcpus$1 } },
11951
+ ...networkPolicy$1 !== void 0 && { networkPolicy: networkPolicy$1 },
11952
+ ...envObj !== void 0 && { env: envObj },
11953
+ ...tagsObj !== void 0 && { tags: tagsObj },
11954
+ ...nonPersistent && { persistent: false },
11955
+ ...snapshotExpiration$1 !== void 0 && { snapshotExpiration: (0, import_ms$2.default)(snapshotExpiration$1) },
11956
+ ...keepLastSnapshotsPayload !== void 0 && { keepLastSnapshots: keepLastSnapshotsPayload },
11957
+ __interactive: true
11958
+ });
11959
+ spinner?.stop();
11960
+ if (!sandbox.interactivePort) throw new Error([
11961
+ `Sandbox forked but interactive port is missing.`,
11962
+ `${source_default.bold("hint:")} This is an internal error. Please try again.`,
11963
+ "╰▶ Report this issue: https://github.com/vercel/sandbox/issues"
11964
+ ].join("\n"));
11965
+ if (!silent) printSandboxSummary({
11966
+ sandbox,
11967
+ scope: scope$1,
11968
+ action: `forked from ${source_default.cyan(source)}`
11969
+ });
11807
11970
  if (connect$2) await exec.handler({
11808
11971
  scope: scope$1,
11809
11972
  asSudo: false,
@@ -11832,8 +11995,8 @@ function omit(obj, ...keys) {
11832
11995
  //#region src/commands/run.ts
11833
11996
  var import_cjs$13 = /* @__PURE__ */ __toESM(require_cjs());
11834
11997
  const args$1 = {
11835
- ...args$2,
11836
- ...omit(args$3, "sandbox"),
11998
+ ...args$3,
11999
+ ...omit(args$4, "sandbox"),
11837
12000
  removeAfterUse: import_cjs$13.flag({
11838
12001
  long: "rm",
11839
12002
  description: "Automatically remove the sandbox when the command exits."
@@ -12008,14 +12171,14 @@ const connect = import_cjs$11.command({
12008
12171
  name: "connect",
12009
12172
  aliases: ["ssh", "shell"],
12010
12173
  description: "Start an interactive shell in an existing sandbox",
12011
- args: omit(args$3, "command", "args", "interactive", "tty"),
12012
- async handler(args$4) {
12174
+ args: omit(args$4, "command", "args", "interactive", "tty"),
12175
+ async handler(args$5) {
12013
12176
  return exec.handler({
12014
12177
  command: "sh",
12015
12178
  args: [],
12016
12179
  interactive: true,
12017
12180
  tty: true,
12018
- ...args$4
12181
+ ...args$5
12019
12182
  });
12020
12183
  }
12021
12184
  });
@@ -12242,7 +12405,7 @@ var require_eventemitter3 = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.
12242
12405
  EventEmitter$1.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
12243
12406
  var evt = prefix ? prefix + event : event;
12244
12407
  if (!this._events[evt]) return false;
12245
- var listeners = this._events[evt], len = arguments.length, args$4, i;
12408
+ var listeners = this._events[evt], len = arguments.length, args$5, i;
12246
12409
  if (listeners.fn) {
12247
12410
  if (listeners.once) this.removeListener(event, listeners.fn, void 0, true);
12248
12411
  switch (len) {
@@ -12253,8 +12416,8 @@ var require_eventemitter3 = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.
12253
12416
  case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
12254
12417
  case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
12255
12418
  }
12256
- for (i = 1, args$4 = new Array(len - 1); i < len; i++) args$4[i - 1] = arguments[i];
12257
- listeners.fn.apply(listeners.context, args$4);
12419
+ for (i = 1, args$5 = new Array(len - 1); i < len; i++) args$5[i - 1] = arguments[i];
12420
+ listeners.fn.apply(listeners.context, args$5);
12258
12421
  } else {
12259
12422
  var length = listeners.length, j;
12260
12423
  for (i = 0; i < length; i++) {
@@ -12273,8 +12436,8 @@ var require_eventemitter3 = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.
12273
12436
  listeners[i].fn.call(listeners[i].context, a1, a2, a3);
12274
12437
  break;
12275
12438
  default:
12276
- if (!args$4) for (j = 1, args$4 = new Array(len - 1); j < len; j++) args$4[j - 1] = arguments[j];
12277
- listeners[i].fn.apply(listeners[i].context, args$4);
12439
+ if (!args$5) for (j = 1, args$5 = new Array(len - 1); j < len; j++) args$5[j - 1] = arguments[j];
12440
+ listeners[i].fn.apply(listeners[i].context, args$5);
12278
12441
  }
12279
12442
  }
12280
12443
  }
@@ -12687,8 +12850,8 @@ var EventManager = class {
12687
12850
  constructor() {
12688
12851
  this.emitter = new eventemitter3_default();
12689
12852
  }
12690
- emit(dispatch, args$4) {
12691
- this.emitter.emit(dispatch, args$4);
12853
+ emit(dispatch, args$5) {
12854
+ this.emitter.emit(dispatch, args$5);
12692
12855
  }
12693
12856
  on(dispatch, handler) {
12694
12857
  this.emitter.addListener(dispatch, handler);
@@ -12840,9 +13003,9 @@ var ListrLogger = class {
12840
13003
  if (!message) return message;
12841
13004
  return this.applyFormat(`[${message}]`, options);
12842
13005
  }
12843
- splat(...args$4) {
12844
- const message = args$4.shift() ?? "";
12845
- return args$4.length === 0 ? message : splat(message, args$4);
13006
+ splat(...args$5) {
13007
+ const message = args$5.shift() ?? "";
13008
+ return args$5.length === 0 ? message : splat(message, args$5);
12846
13009
  }
12847
13010
  suffix(message, ...suffixes) {
12848
13011
  suffixes.filter(Boolean).forEach((suffix) => {
@@ -12924,12 +13087,12 @@ var ProcessOutputBuffer = class {
12924
13087
  get length() {
12925
13088
  return this.buffer.length;
12926
13089
  }
12927
- write(data, ...args$4) {
12928
- const callback = args$4[args$4.length - 1];
13090
+ write(data, ...args$5) {
13091
+ const callback = args$5[args$5.length - 1];
12929
13092
  this.buffer.push({
12930
13093
  time: Date.now(),
12931
13094
  stream: this.options?.stream,
12932
- entry: this.decoder.write(typeof data === "string" ? Buffer.from(data, typeof args$4[0] === "string" ? args$4[0] : void 0) : Buffer.from(data))
13095
+ entry: this.decoder.write(typeof data === "string" ? Buffer.from(data, typeof args$5[0] === "string" ? args$5[0] : void 0) : Buffer.from(data))
12933
13096
  });
12934
13097
  if (this.options?.limit) this.buffer = this.buffer.slice(-this.options.limit);
12935
13098
  if (typeof callback === "function") callback();
@@ -12957,8 +13120,8 @@ var ProcessOutputStream = class {
12957
13120
  this.buffer.reset();
12958
13121
  return buffer;
12959
13122
  }
12960
- write(...args$4) {
12961
- return this.method.apply(this.stream, args$4);
13123
+ write(...args$5) {
13124
+ return this.method.apply(this.stream, args$5);
12962
13125
  }
12963
13126
  };
12964
13127
  /**
@@ -13821,8 +13984,8 @@ function getRenderer(options) {
13821
13984
  * If the value itself is a function it will evaluate it with the passed in arguments,
13822
13985
  * elsewise it will directly return itself.
13823
13986
  */
13824
- function assertFunctionOrSelf(functionOrSelf, ...args$4) {
13825
- if (typeof functionOrSelf === "function") return functionOrSelf(...args$4);
13987
+ function assertFunctionOrSelf(functionOrSelf, ...args$5) {
13988
+ if (typeof functionOrSelf === "function") return functionOrSelf(...args$5);
13826
13989
  else return functionOrSelf;
13827
13990
  }
13828
13991
  const clone = (0, import_rfdc.default)({ circles: true });
@@ -14602,10 +14765,10 @@ const snapshot = import_cjs$6.command({
14602
14765
  init_source();
14603
14766
  function formatExpires(expiresAt) {
14604
14767
  if (expiresAt === void 0) return source_default.gray("never");
14605
- const ms$4 = expiresAt - Date.now();
14606
- if (ms$4 <= 0) return source_default.red("expired");
14768
+ const ms$6 = expiresAt - Date.now();
14769
+ if (ms$6 <= 0) return source_default.red("expired");
14607
14770
  const formatted = timeAgo(expiresAt);
14608
- return ms$4 <= 3600 * 1e3 ? source_default.red(formatted) : source_default.green(formatted);
14771
+ return ms$6 <= 3600 * 1e3 ? source_default.red(formatted) : source_default.green(formatted);
14609
14772
  }
14610
14773
  function renderNode(id, expiresAt, isCurrent) {
14611
14774
  const bullet = isCurrent ? source_default.magenta.bold("●") : source_default.magenta("●");
@@ -15584,11 +15747,11 @@ const tagsCommand = import_cjs$1.command({
15584
15747
  }
15585
15748
  }
15586
15749
  });
15587
- function formatKeepLastSnapshots(keepLastSnapshots) {
15588
- if (!keepLastSnapshots) return "-";
15589
- const parts = [`count=${keepLastSnapshots.count}`];
15590
- if (keepLastSnapshots.expiration !== void 0) parts.push(`for=${keepLastSnapshots.expiration === 0 ? "none" : (0, import_ms.default)(keepLastSnapshots.expiration, { long: true })}`);
15591
- if (keepLastSnapshots.deleteEvicted !== void 0) parts.push(`delete-evicted-snapshots=${keepLastSnapshots.deleteEvicted}`);
15750
+ function formatKeepLastSnapshots(keepLastSnapshots$1) {
15751
+ if (!keepLastSnapshots$1) return "-";
15752
+ const parts = [`count=${keepLastSnapshots$1.count}`];
15753
+ if (keepLastSnapshots$1.expiration !== void 0) parts.push(`for=${keepLastSnapshots$1.expiration === 0 ? "none" : (0, import_ms.default)(keepLastSnapshots$1.expiration, { long: true })}`);
15754
+ if (keepLastSnapshots$1.deleteEvicted !== void 0) parts.push(`delete-evicted-snapshots=${keepLastSnapshots$1.deleteEvicted}`);
15592
15755
  return parts.join(", ");
15593
15756
  }
15594
15757
  function formatPorts(sandbox) {
@@ -15628,6 +15791,7 @@ const app = (opts) => (0, import_cjs.subcommands)({
15628
15791
  cmds: {
15629
15792
  list,
15630
15793
  create,
15794
+ fork,
15631
15795
  config,
15632
15796
  copy: cp,
15633
15797
  exec,
@@ -15661,4 +15825,4 @@ const app = (opts) => (0, import_cjs.subcommands)({
15661
15825
 
15662
15826
  //#endregion
15663
15827
  export { source_exports as a, init_source as i, StyledError as n, require_cjs as r, app as t };
15664
- //# sourceMappingURL=app-BdOGNXsw.mjs.map
15828
+ //# sourceMappingURL=app-jQvr1S8n.mjs.map