sandbox 3.0.0-beta.23 → 3.0.0-beta.24

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.
@@ -7290,7 +7290,7 @@ const scope = {
7290
7290
 
7291
7291
  //#endregion
7292
7292
  //#region package.json
7293
- var version = "3.0.0-beta.23";
7293
+ var version = "3.0.0-beta.24";
7294
7294
 
7295
7295
  //#endregion
7296
7296
  //#region src/error.ts
@@ -7332,6 +7332,10 @@ const snapshotClient = {
7332
7332
  fromSandbox: (name, opts) => withErrorHandling(() => Snapshot.fromSandbox(name, {
7333
7333
  fetch: fetchWithUserAgent,
7334
7334
  ...opts
7335
+ })),
7336
+ tree: (params) => withErrorHandling(() => Snapshot.tree({
7337
+ fetch: fetchWithUserAgent,
7338
+ ...params
7335
7339
  }))
7336
7340
  };
7337
7341
  const fetchWithUserAgent = (input, init$1) => {
@@ -14587,6 +14591,75 @@ const snapshot = import_cjs$6.command({
14587
14591
  }
14588
14592
  });
14589
14593
 
14594
+ //#endregion
14595
+ //#region src/util/snapshot-tree.ts
14596
+ init_source();
14597
+ function formatExpires(expiresAt) {
14598
+ if (expiresAt === void 0) return source_default.gray("never");
14599
+ const ms$4 = expiresAt - Date.now();
14600
+ if (ms$4 <= 0) return source_default.red("expired");
14601
+ const formatted = timeAgo(expiresAt);
14602
+ return ms$4 <= 3600 * 1e3 ? source_default.red(formatted) : source_default.green(formatted);
14603
+ }
14604
+ function renderNode(id, expiresAt, isCurrent) {
14605
+ const bullet = isCurrent ? source_default.magenta.bold("●") : source_default.magenta("●");
14606
+ const suffix = isCurrent ? ` ${source_default.green("◂ current")}` : "";
14607
+ return `${bullet} ${source_default.yellow(id)} expires: ${formatExpires(expiresAt)}${suffix}`;
14608
+ }
14609
+ function renderSiblings(siblings, count) {
14610
+ const lines = [];
14611
+ const shown = siblings.slice(0, 5);
14612
+ const totalCount = parseInt(count, 10);
14613
+ const hasPlus = count.endsWith("+");
14614
+ const remaining = totalCount - 1 - shown.length;
14615
+ for (let i = 0; i < shown.length; i++) {
14616
+ const connector = i === shown.length - 1 && remaining <= 0 ? "╰──" : "├──";
14617
+ lines.push(`│ ${connector} ${source_default.gray(shown[i].sourceSessionId)}`);
14618
+ }
14619
+ if (remaining > 0) {
14620
+ const suffix = hasPlus ? "+" : "";
14621
+ lines.push(`│ ╰── ${source_default.gray(`+${remaining}${suffix} more sandboxes`)}`);
14622
+ }
14623
+ return lines;
14624
+ }
14625
+ function renderSnapshotTree(params) {
14626
+ const { ancestors, descendants } = params;
14627
+ const hideCurrent = params.hideCurrent === true;
14628
+ const currentSnapshotId = hideCurrent ? void 0 : params.currentSnapshotId;
14629
+ const lines = [];
14630
+ const pushNode = (node, isCurrent) => {
14631
+ lines.push("│");
14632
+ lines.push(renderNode(node.snapshot.id, node.snapshot.expiresAt, isCurrent));
14633
+ if (node.siblings.length > 0) lines.push(...renderSiblings(node.siblings, node.count));
14634
+ };
14635
+ const descendantNodes = descendants.snapshots.filter((n) => n.snapshot.id !== currentSnapshotId);
14636
+ if (descendantNodes.length > 0) for (const node of [...descendantNodes].reverse()) pushNode(node, false);
14637
+ if (!hideCurrent) {
14638
+ const { currentSnapshotId: id, currentSnapshotExpiresAt } = params;
14639
+ pushNode(ancestors.snapshots.find((n) => n.snapshot.id === id) ?? descendants.snapshots.find((n) => n.snapshot.id === id) ?? {
14640
+ snapshot: {
14641
+ id,
14642
+ sourceSessionId: "",
14643
+ expiresAt: currentSnapshotExpiresAt
14644
+ },
14645
+ siblings: [],
14646
+ count: "1"
14647
+ }, true);
14648
+ }
14649
+ const ancestorNodes = ancestors.snapshots.filter((n) => n.snapshot.id !== currentSnapshotId);
14650
+ for (const node of ancestorNodes) pushNode(node, false);
14651
+ if (!hideCurrent) {
14652
+ const lastAncestor = ancestorNodes[ancestorNodes.length - 1];
14653
+ if (ancestors.pagination.next === null) {
14654
+ if (lastAncestor && !lastAncestor.snapshot.parentId || ancestorNodes.length === 0) {
14655
+ lines.push("│");
14656
+ lines.push(`${source_default.white("○")} ${source_default.gray("(root)")}`);
14657
+ }
14658
+ }
14659
+ }
14660
+ return lines.join("\n");
14661
+ }
14662
+
14590
14663
  //#endregion
14591
14664
  //#region src/commands/snapshots.ts
14592
14665
  var import_cjs$4 = /* @__PURE__ */ __toESM(require_cjs());
@@ -14737,12 +14810,154 @@ const remove$1 = import_cjs$4.command({
14737
14810
  }
14738
14811
  }
14739
14812
  });
14813
+ const tree = import_cjs$4.command({
14814
+ name: "tree",
14815
+ description: "Show the snapshot ancestry tree for a sandbox.",
14816
+ args: {
14817
+ scope,
14818
+ sandboxName: import_cjs$4.positional({
14819
+ type: sandboxName,
14820
+ description: "Sandbox name"
14821
+ }),
14822
+ sortOrder: import_cjs$4.option({
14823
+ long: "sort-order",
14824
+ description: "Sort order. Options: asc, desc (default). 'desc' walks ancestors, 'asc' walks descendants. Requires --cursor.",
14825
+ type: import_cjs$4.optional(import_cjs$4.oneOf(["asc", "desc"]))
14826
+ }),
14827
+ limit: import_cjs$4.option({
14828
+ long: "limit",
14829
+ description: "Maximum number of snapshots per page (1–10, default 10).",
14830
+ type: import_cjs$4.optional(import_cjs$4.number)
14831
+ }),
14832
+ cursor: import_cjs$4.option({
14833
+ long: "cursor",
14834
+ description: "Pagination cursor from a previous 'More ancestors' or 'More descendants' hint.",
14835
+ type: import_cjs$4.optional(import_cjs$4.string)
14836
+ })
14837
+ },
14838
+ async handler({ scope: { token: token$1, team: team$1, project: project$1 }, sandboxName: name, sortOrder, limit, cursor }) {
14839
+ if (limit !== void 0 && (limit < 1 || limit > 10)) {
14840
+ console.error(source_default.red("Error: --limit must be between 1 and 10."));
14841
+ process.exitCode = 1;
14842
+ return;
14843
+ }
14844
+ if (sortOrder !== void 0 && !cursor) {
14845
+ console.error(source_default.red("Error: --sort-order requires --cursor."));
14846
+ process.exitCode = 1;
14847
+ return;
14848
+ }
14849
+ const pageLimit = limit ?? 10;
14850
+ if (cursor) {
14851
+ const effectiveSortOrder = sortOrder ?? "desc";
14852
+ const page = await (async () => {
14853
+ try {
14854
+ var _usingCtx4 = _usingCtx();
14855
+ const _spinner$1 = _usingCtx4.u(acquireRelease(() => ora("Fetching snapshot tree...").start(), (s$1) => s$1.stop()));
14856
+ return snapshotClient.tree({
14857
+ snapshotId: cursor,
14858
+ sortOrder: effectiveSortOrder,
14859
+ limit: pageLimit,
14860
+ token: token$1,
14861
+ teamId: team$1,
14862
+ projectId: project$1
14863
+ });
14864
+ } catch (_) {
14865
+ _usingCtx4.e = _;
14866
+ } finally {
14867
+ _usingCtx4.d();
14868
+ }
14869
+ })();
14870
+ const ancestors = effectiveSortOrder === "desc" ? page : {
14871
+ snapshots: [],
14872
+ pagination: {
14873
+ count: 0,
14874
+ next: null
14875
+ }
14876
+ };
14877
+ const descendants = effectiveSortOrder === "asc" ? page : {
14878
+ snapshots: [],
14879
+ pagination: {
14880
+ count: 0,
14881
+ next: null
14882
+ }
14883
+ };
14884
+ console.log(renderSnapshotTree({
14885
+ hideCurrent: true,
14886
+ ancestors,
14887
+ descendants
14888
+ }));
14889
+ if (page.pagination.next !== null) console.log(formatNextCursorHint(page.pagination.next));
14890
+ return;
14891
+ }
14892
+ const result = await (async () => {
14893
+ try {
14894
+ var _usingCtx5 = _usingCtx();
14895
+ const _spinner$1 = _usingCtx5.u(acquireRelease(() => ora("Fetching snapshot tree...").start(), (s$1) => s$1.stop()));
14896
+ const currentSnapshotId = (await sandboxClient.get({
14897
+ name,
14898
+ token: token$1,
14899
+ teamId: team$1,
14900
+ projectId: project$1
14901
+ })).currentSnapshotId;
14902
+ if (!currentSnapshotId) return null;
14903
+ const [currentSnap, ancestors, descendants] = await Promise.all([
14904
+ snapshotClient.get({
14905
+ snapshotId: currentSnapshotId,
14906
+ token: token$1,
14907
+ teamId: team$1,
14908
+ projectId: project$1
14909
+ }),
14910
+ snapshotClient.tree({
14911
+ snapshotId: currentSnapshotId,
14912
+ sortOrder: "desc",
14913
+ limit: pageLimit,
14914
+ token: token$1,
14915
+ teamId: team$1,
14916
+ projectId: project$1
14917
+ }),
14918
+ snapshotClient.tree({
14919
+ snapshotId: currentSnapshotId,
14920
+ sortOrder: "asc",
14921
+ limit: pageLimit,
14922
+ token: token$1,
14923
+ teamId: team$1,
14924
+ projectId: project$1
14925
+ })
14926
+ ]);
14927
+ return {
14928
+ currentSnap,
14929
+ currentSnapshotId,
14930
+ ancestors,
14931
+ descendants
14932
+ };
14933
+ } catch (_) {
14934
+ _usingCtx5.e = _;
14935
+ } finally {
14936
+ _usingCtx5.d();
14937
+ }
14938
+ })();
14939
+ if (!result) {
14940
+ console.log(source_default.yellow("No snapshots found for this sandbox."));
14941
+ return;
14942
+ }
14943
+ console.log(renderSnapshotTree({
14944
+ currentSnapshotId: result.currentSnapshotId,
14945
+ currentSnapshotExpiresAt: result.currentSnap.expiresAt?.getTime(),
14946
+ ancestors: result.ancestors,
14947
+ descendants: result.descendants
14948
+ }));
14949
+ const limitArg = limit !== void 0 ? ` --limit ${limit}` : "";
14950
+ if (result.ancestors.pagination.next !== null) console.log(`\nMore ancestors: sandbox snapshots tree ${name} --sort-order desc${limitArg} --cursor ${result.ancestors.pagination.next}`);
14951
+ if (result.descendants.pagination.next !== null) console.log(`More descendants: sandbox snapshots tree ${name} --sort-order asc${limitArg} --cursor ${result.descendants.pagination.next}`);
14952
+ }
14953
+ });
14740
14954
  const snapshots = (0, import_cjs$5.subcommands)({
14741
14955
  name: "snapshots",
14742
14956
  description: "Manage sandbox snapshots",
14743
14957
  cmds: {
14744
14958
  list: list$2,
14745
14959
  get,
14960
+ tree,
14746
14961
  delete: remove$1
14747
14962
  }
14748
14963
  });
@@ -15386,4 +15601,4 @@ const app = (opts) => (0, import_cjs.subcommands)({
15386
15601
 
15387
15602
  //#endregion
15388
15603
  export { source_exports as a, init_source as i, StyledError as n, require_cjs as r, app as t };
15389
- //# sourceMappingURL=app-BjVyEIk1.mjs.map
15604
+ //# sourceMappingURL=app-CpryW0ai.mjs.map