sandbox 3.0.1 → 3.1.0

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.
@@ -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$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";
3105
+ function fmtShort(ms$7) {
3106
+ var msAbs = Math.abs(ms$7);
3107
+ if (msAbs >= d) return Math.round(ms$7 / d) + "d";
3108
+ if (msAbs >= h) return Math.round(ms$7 / h) + "h";
3109
+ if (msAbs >= m) return Math.round(ms$7 / m) + "m";
3110
+ if (msAbs >= s) return Math.round(ms$7 / s) + "s";
3111
+ return ms$7 + "ms";
3112
3112
  }
3113
3113
  /**
3114
3114
  * Long format for `ms`.
@@ -3117,20 +3117,20 @@ 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$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";
3120
+ function fmtLong(ms$7) {
3121
+ var msAbs = Math.abs(ms$7);
3122
+ if (msAbs >= d) return plural(ms$7, msAbs, d, "day");
3123
+ if (msAbs >= h) return plural(ms$7, msAbs, h, "hour");
3124
+ if (msAbs >= m) return plural(ms$7, msAbs, m, "minute");
3125
+ if (msAbs >= s) return plural(ms$7, msAbs, s, "second");
3126
+ return ms$7 + " ms";
3127
3127
  }
3128
3128
  /**
3129
3129
  * Pluralization helper.
3130
3130
  */
3131
- function plural(ms$6, msAbs, n, name) {
3131
+ function plural(ms$7, msAbs, n, name) {
3132
3132
  var isPlural = msAbs >= n * 1.5;
3133
- return Math.round(ms$6 / n) + " " + name + (isPlural ? "s" : "");
3133
+ return Math.round(ms$7 / n) + " " + name + (isPlural ? "s" : "");
3134
3134
  }
3135
3135
  }) });
3136
3136
 
@@ -7290,7 +7290,7 @@ const scope = {
7290
7290
 
7291
7291
  //#endregion
7292
7292
  //#region package.json
7293
- var version = "3.0.1";
7293
+ var version = "3.1.0";
7294
7294
 
7295
7295
  //#endregion
7296
7296
  //#region src/error.ts
@@ -11190,9 +11190,9 @@ function printCommand(command$1, args$5) {
11190
11190
 
11191
11191
  //#endregion
11192
11192
  //#region src/interactive-shell/extend-sandbox-timeout.ts
11193
- var import_ms$5 = /* @__PURE__ */ __toESM(require_ms());
11193
+ var import_ms$6 = /* @__PURE__ */ __toESM(require_ms());
11194
11194
  const debug$2 = createDebugger("sandbox:timeout");
11195
- const BUFFER = (0, import_ms$5.default)("10 seconds");
11195
+ const BUFFER = (0, import_ms$6.default)("10 seconds");
11196
11196
  async function extendSandboxTimeoutPeriodically(sandbox, signal) {
11197
11197
  const session = sandbox.currentSession();
11198
11198
  const timeout$1 = session.timeout;
@@ -11207,7 +11207,7 @@ async function extendSandboxTimeoutPeriodically(sandbox, signal) {
11207
11207
  debug$2(`sleeping for ${sleepMs}ms until next timeout extension`);
11208
11208
  await setTimeout$1(sleepMs, null, { signal });
11209
11209
  }
11210
- await sandbox.extendTimeout((0, import_ms$5.default)("5 minutes"));
11210
+ await sandbox.extendTimeout((0, import_ms$6.default)("5 minutes"));
11211
11211
  const updatedTimeout = session.timeout;
11212
11212
  if (updatedTimeout == null) return;
11213
11213
  const nextTick$1 = session.createdAt.getTime() + updatedTimeout;
@@ -11383,11 +11383,13 @@ async function attach({ progress, listener, printCommand: printCommand$1, sandbo
11383
11383
  const url = `wss://${sandbox.domain(sandbox.interactivePort).replace(/^https?:\/\//, "")}`;
11384
11384
  debug$1("Connecting to WebSocket URL:", url);
11385
11385
  const stdoutPipe = messageReader(process.stdout);
11386
- const client = details.createClient(url);
11387
- client.addEventListener("message", async ({ data }) => {
11388
- stdoutPipe.next(data);
11386
+ const client = await openWithRetry(() => {
11387
+ const c$1 = details.createClient(url);
11388
+ c$1.addEventListener("message", async ({ data }) => {
11389
+ stdoutPipe.next(data);
11390
+ });
11391
+ return c$1;
11389
11392
  });
11390
- await client.waitForOpen();
11391
11393
  progress.stop();
11392
11394
  const extensionController = _usingCtx4.u(createAbortController("stopped extensions"));
11393
11395
  if (!skipExtendingTimeout) extendSandboxTimeoutPeriodically(sandbox, extensionController.signal).catch(extensionController.ignoreInterruptions);
@@ -11457,6 +11459,37 @@ async function connect$1(command$1, listener, signal) {
11457
11459
  _usingCtx5.d();
11458
11460
  }
11459
11461
  }
11462
+ async function openWithRetry(create$1) {
11463
+ return retry(async (_bail, attempt) => {
11464
+ const client = create$1();
11465
+ try {
11466
+ await withTimeout(client.waitForOpen(), 2500);
11467
+ return client;
11468
+ } catch (err$1) {
11469
+ debug$1("WebSocket open attempt %d failed: %o", attempt, err$1);
11470
+ try {
11471
+ client.close();
11472
+ } catch (closeErr) {
11473
+ debug$1("WebSocket close after failed open errored: %o", closeErr);
11474
+ }
11475
+ throw err$1;
11476
+ }
11477
+ }, {
11478
+ retries: 2,
11479
+ minTimeout: 500,
11480
+ factor: 0
11481
+ });
11482
+ }
11483
+ function withTimeout(promise, ms$7) {
11484
+ promise.catch(() => {});
11485
+ let timer;
11486
+ const timeout$1 = new Promise((_, reject) => {
11487
+ timer = setTimeout(() => reject(/* @__PURE__ */ new Error(`Operation timed out after ${ms$7}ms`)), ms$7);
11488
+ });
11489
+ return Promise.race([promise, timeout$1]).finally(() => {
11490
+ if (timer) clearTimeout(timer);
11491
+ });
11492
+ }
11460
11493
  function getStderrStream() {
11461
11494
  return acquireRelease(() => {
11462
11495
  if (INTERACTIVE_BIN_OUTPUT) {
@@ -11512,6 +11545,7 @@ const ObjectFromKeyValue = import_cjs$18.extendType(import_cjs$18.array(KeyValue
11512
11545
  //#endregion
11513
11546
  //#region src/commands/exec.ts
11514
11547
  var import_cjs$17 = /* @__PURE__ */ __toESM(require_cjs());
11548
+ var import_ms$5 = /* @__PURE__ */ __toESM(require_ms());
11515
11549
  init_source();
11516
11550
  const args$4 = {
11517
11551
  sandbox: import_cjs$17.positional({ type: sandboxName }),
@@ -11562,13 +11596,19 @@ const args$4 = {
11562
11596
  type: ObjectFromKeyValue,
11563
11597
  description: "Environment variables to set for the command"
11564
11598
  }),
11599
+ timeout: import_cjs$17.option({
11600
+ long: "timeout",
11601
+ type: import_cjs$17.optional(Duration),
11602
+ description: "Maximum duration to wait for the command (e.g. 30s, 5m). On expiry the process is killed with SIGKILL. Cannot be combined with --interactive."
11603
+ }),
11565
11604
  scope
11566
11605
  };
11567
11606
  const exec = import_cjs$17.command({
11568
11607
  name: "exec",
11569
11608
  description: "Execute a command in an existing sandbox",
11570
11609
  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 }) {
11610
+ 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, timeout: timeout$1 }) {
11611
+ if (interactive && timeout$1) throw new Error(["--timeout cannot be combined with --interactive.", `${source_default.bold("hint:")} Remove one of the two flags. Interactive sessions do not enforce a command timeout.`].join("\n"));
11572
11612
  const sandbox = typeof sandboxName$1 !== "string" ? sandboxName$1 : await sandboxClient.get({
11573
11613
  name: sandboxName$1,
11574
11614
  projectId: project$1,
@@ -11585,8 +11625,10 @@ const exec = import_cjs$17.command({
11585
11625
  stdout: process.stdout,
11586
11626
  sudo: asSudo,
11587
11627
  cwd,
11588
- env: envVars
11628
+ env: envVars,
11629
+ timeoutMs: timeout$1 ? (0, import_ms$5.default)(timeout$1) : void 0
11589
11630
  });
11631
+ if (timeout$1 && result.exitCode === 137) console.error(`${source_default.yellow("Command was killed (SIGKILL, exit code 137)")}.`);
11590
11632
  process.exitCode = result.exitCode;
11591
11633
  } else await startInteractiveShell({
11592
11634
  sandbox,
@@ -11856,7 +11898,8 @@ const create = import_cjs$15.command({
11856
11898
  command: "sh",
11857
11899
  interactive: true,
11858
11900
  tty: true,
11859
- sandbox
11901
+ sandbox,
11902
+ timeout: void 0
11860
11903
  });
11861
11904
  return sandbox;
11862
11905
  }
@@ -11977,7 +12020,8 @@ const fork = import_cjs$14.command({
11977
12020
  command: "sh",
11978
12021
  interactive: true,
11979
12022
  tty: true,
11980
- sandbox
12023
+ sandbox,
12024
+ timeout: void 0
11981
12025
  });
11982
12026
  return sandbox;
11983
12027
  }
@@ -11996,7 +12040,7 @@ function omit(obj, ...keys) {
11996
12040
  var import_cjs$13 = /* @__PURE__ */ __toESM(require_cjs());
11997
12041
  const args$1 = {
11998
12042
  ...args$3,
11999
- ...omit(args$4, "sandbox"),
12043
+ ...omit(args$4, "sandbox", "timeout"),
12000
12044
  removeAfterUse: import_cjs$13.flag({
12001
12045
  long: "rm",
12002
12046
  description: "Automatically remove the sandbox when the command exits."
@@ -12036,7 +12080,8 @@ const run = import_cjs$13.command({
12036
12080
  try {
12037
12081
  await exec.handler({
12038
12082
  ...rest$1,
12039
- sandbox
12083
+ sandbox,
12084
+ timeout: void 0
12040
12085
  });
12041
12086
  } finally {
12042
12087
  if (removeAfterUse) await sandbox.delete();
@@ -14765,10 +14810,10 @@ const snapshot = import_cjs$6.command({
14765
14810
  init_source();
14766
14811
  function formatExpires(expiresAt) {
14767
14812
  if (expiresAt === void 0) return source_default.gray("never");
14768
- const ms$6 = expiresAt - Date.now();
14769
- if (ms$6 <= 0) return source_default.red("expired");
14813
+ const ms$7 = expiresAt - Date.now();
14814
+ if (ms$7 <= 0) return source_default.red("expired");
14770
14815
  const formatted = timeAgo(expiresAt);
14771
- return ms$6 <= 3600 * 1e3 ? source_default.red(formatted) : source_default.green(formatted);
14816
+ return ms$7 <= 3600 * 1e3 ? source_default.red(formatted) : source_default.green(formatted);
14772
14817
  }
14773
14818
  function renderNode(id, expiresAt, isCurrent) {
14774
14819
  const bullet = isCurrent ? source_default.magenta.bold("●") : source_default.magenta("●");
@@ -14783,11 +14828,11 @@ function renderSiblings(siblings, count) {
14783
14828
  const remaining = totalCount - 1 - shown.length;
14784
14829
  for (let i = 0; i < shown.length; i++) {
14785
14830
  const connector = i === shown.length - 1 && remaining <= 0 ? "╰──" : "├──";
14786
- lines.push(`│ ${connector} ${source_default.gray(shown[i].sourceSessionId)}`);
14831
+ lines.push(`│ ${connector} ${source_default.gray(shown[i].id)}`);
14787
14832
  }
14788
14833
  if (remaining > 0) {
14789
14834
  const suffix = hasPlus ? "+" : "";
14790
- lines.push(`│ ╰── ${source_default.gray(`+${remaining}${suffix} more sandboxes`)}`);
14835
+ lines.push(`│ ╰── ${source_default.gray(`+${remaining}${suffix} more snapshots`)}`);
14791
14836
  }
14792
14837
  return lines;
14793
14838
  }
@@ -14805,7 +14850,7 @@ function renderSnapshotTree(params) {
14805
14850
  if (descendantNodes.length > 0) for (const node of [...descendantNodes].reverse()) pushNode(node, false);
14806
14851
  if (!hideCurrent) {
14807
14852
  const { currentSnapshotId: id, currentSnapshotExpiresAt } = params;
14808
- pushNode(ancestors.snapshots.find((n) => n.snapshot.id === id) ?? descendants.snapshots.find((n) => n.snapshot.id === id) ?? {
14853
+ pushNode(params.current ?? ancestors.snapshots.find((n) => n.snapshot.id === id) ?? descendants.snapshots.find((n) => n.snapshot.id === id) ?? {
14809
14854
  snapshot: {
14810
14855
  id,
14811
14856
  sourceSessionId: "",
@@ -15097,7 +15142,8 @@ const tree = import_cjs$4.command({
15097
15142
  currentSnap,
15098
15143
  currentSnapshotId,
15099
15144
  ancestors,
15100
- descendants
15145
+ descendants,
15146
+ current: ancestors.anchor ?? descendants.anchor
15101
15147
  };
15102
15148
  } catch (_) {
15103
15149
  _usingCtx5.e = _;
@@ -15113,7 +15159,8 @@ const tree = import_cjs$4.command({
15113
15159
  currentSnapshotId: result.currentSnapshotId,
15114
15160
  currentSnapshotExpiresAt: result.currentSnap.expiresAt?.getTime(),
15115
15161
  ancestors: result.ancestors,
15116
- descendants: result.descendants
15162
+ descendants: result.descendants,
15163
+ current: result.current
15117
15164
  }));
15118
15165
  const limitArg = limit !== void 0 ? ` --limit ${limit}` : "";
15119
15166
  if (result.ancestors.pagination.next !== null) console.log(`\nMore ancestors: sandbox snapshots tree ${name} --sort-order desc${limitArg} --cursor ${result.ancestors.pagination.next}`);
@@ -15825,4 +15872,4 @@ const app = (opts) => (0, import_cjs.subcommands)({
15825
15872
 
15826
15873
  //#endregion
15827
15874
  export { source_exports as a, init_source as i, StyledError as n, require_cjs as r, app as t };
15828
- //# sourceMappingURL=app-C3bsrMUR.mjs.map
15875
+ //# sourceMappingURL=app-CUphjb1B.mjs.map