@norman-else/dsh-claude 0.1.48 → 0.1.49

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.
package/lib/bin.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { i as parseClaudeVersion, n as ensureManagedPreset, r as removeManagedPreset } from "./preset-installer-C4TTNV9L.mjs";
3
- import { access } from "node:fs/promises";
2
+ import { i as parseClaudeVersion, n as ensureManagedPreset, r as removeManagedPreset } from "./preset-installer-Cj637ucf.mjs";
4
3
  import { delimiter, isAbsolute, join } from "node:path";
4
+ import { access } from "node:fs/promises";
5
5
  import { constants } from "node:fs";
6
6
  import { homedir } from "node:os";
7
7
  import { scrubbedParentEnv } from "@deepseek-ai/dsh-subprocess";
package/lib/client.d.ts CHANGED
@@ -229,6 +229,9 @@ declare const en: {
229
229
  readonly presetHeaderHint: "The agent preset this session runs";
230
230
  readonly diffRepository: "Repository";
231
231
  readonly repositoryLinked: "Linked repository: changed by this session";
232
+ readonly linkedMore: "{count} more linked repositories";
233
+ readonly linkedShowAll: "Show all";
234
+ readonly linkedCollapse: "Collapse linked repositories";
232
235
  readonly linkedRepositoryPrompt: "The following concerns the linked repository at {root} (branch {branch}), not this session's own checkout.";
233
236
  readonly diffFiles: "{count} modified file(s)";
234
237
  readonly diffFilesShort: "{count} files";
package/lib/client.js CHANGED
@@ -1957,14 +1957,59 @@ window.__ModuleLoader__.load({
1957
1957
  borderColor: "color-mix(in srgb, #a78bfa 35%, transparent)",
1958
1958
  background: "color-mix(in srgb, #a78bfa 5%, var(--dsw-alias-bg-layer-1))"
1959
1959
  };
1960
+ /** The linked bars as one stack, the fold control floating centred above. */
1961
+ const linkedStack = { position: "relative" };
1962
+ /** Two chevron glyphs stacked into one double chevron: 14px tall in all,
1963
+ * the second pulled up over the first. */
1964
+ const linkedFoldGlyph = {
1965
+ display: "flex",
1966
+ flexDirection: "column",
1967
+ alignItems: "center",
1968
+ height: 14,
1969
+ marginTop: 2
1970
+ };
1971
+ const linkedFoldGlyphClass = "dshClaudeLinkedFoldGlyph";
1972
+ /** The second chevron rides 7px up over the first. */
1973
+ const linkedFoldGlyphCss = `
1974
+ .${linkedFoldGlyphClass} > svg + svg { margin-top: -7px; }
1975
+ `;
1976
+ /** The fold control, drawn to the Host's jump-to-latest recipe exactly: a
1977
+ * 34px circle on the floating fill, no border of its own -- the stroke is
1978
+ * the elevation's, set through the same variable the Host sets -- and the
1979
+ * circle asked for by name, since the Host's theme rounds as squircles.
1980
+ * Where it sits comes from the component. Holds only the double chevron;
1981
+ * the count lives in its tooltip. */
1982
+ const linkedFoldChip = {
1983
+ position: "absolute",
1984
+ zIndex: 8,
1985
+ boxSizing: "border-box",
1986
+ display: "flex",
1987
+ alignItems: "center",
1988
+ justifyContent: "center",
1989
+ width: 34,
1990
+ height: 34,
1991
+ padding: 0,
1992
+ border: 0,
1993
+ borderRadius: 100,
1994
+ cornerShape: "round",
1995
+ "--dsw-elevation-stroke-color": "var(--dsw-alias-border-l3)",
1996
+ background: "var(--dsw-alias-button-floating-fill)",
1997
+ color: "var(--dsw-alias-label-primary)",
1998
+ boxShadow: "var(--dsw-elevation-panel)",
1999
+ font: "inherit",
2000
+ cursor: "pointer",
2001
+ transition: "right .15s ease"
2002
+ };
2003
+ /** The folded count beside the chevrons. */
1960
2004
  /** A checkout the session wrote into besides its own: lighter, dashed, and
1961
- * stacked above the session bar so it reads as attached rather than primary. */
2005
+ * stacked above the session bar so it reads as attached rather than primary.
2006
+ * It keeps the bar's opaque fill: the dock floats over the end of the
2007
+ * transcript, and a transparent bar let the prose show through. */
1962
2008
  const repositoryBarLinked = {
1963
2009
  marginBottom: 6,
1964
2010
  minHeight: 34,
1965
2011
  padding: "5px 11px",
1966
2012
  borderStyle: "dashed",
1967
- background: "transparent",
1968
2013
  boxShadow: "none",
1969
2014
  color: "var(--dsw-alias-label-secondary)"
1970
2015
  };
@@ -2100,9 +2145,11 @@ window.__ModuleLoader__.load({
2100
2145
  color: "var(--dsw-alias-label-tertiary)",
2101
2146
  fontWeight: 500
2102
2147
  };
2148
+ /** The repository name reads whole while there is room; it is the first
2149
+ * thing to give way when the controls need it, and never wider than its text. */
2103
2150
  const repositoryRemote = {
2104
2151
  minWidth: 0,
2105
- maxWidth: 116,
2152
+ flex: "0 1 auto",
2106
2153
  overflow: "hidden",
2107
2154
  color: "var(--dsw-alias-label-tertiary)",
2108
2155
  fontSize: 12,
@@ -9561,9 +9608,15 @@ window.__ModuleLoader__.load({
9561
9608
  repository,
9562
9609
  t
9563
9610
  }),
9564
- /* @__PURE__ */ jsx("span", {
9565
- style: repositoryRemote,
9566
- children: repositoryLabel(repository)
9611
+ /* @__PURE__ */ jsx(Tooltip, {
9612
+ label: repository.remote ?? repositoryLabel(repository),
9613
+ side: "top",
9614
+ delayMs: 250,
9615
+ maxWidth: 420,
9616
+ children: /* @__PURE__ */ jsx("span", {
9617
+ style: repositoryRemote,
9618
+ children: repositoryLabel(repository)
9619
+ })
9567
9620
  }),
9568
9621
  /* @__PURE__ */ jsx(Tooltip, {
9569
9622
  label: branch,
@@ -9592,24 +9645,141 @@ window.__ModuleLoader__.load({
9592
9645
  ]
9593
9646
  });
9594
9647
  }
9648
+ const linkedExpanded = /* @__PURE__ */ new Map();
9649
+ /** Where the Host's jump-to-latest button sits relative to the linked
9650
+ * stack, remembered from the last time it was on screen: the seat the fold
9651
+ * control takes while the Host's button is away. Until it has been seen
9652
+ * once, the Host's own geometry: 16px in from the column's edge, 16px above
9653
+ * the composer. */
9654
+ let hostSeat = {
9655
+ top: -50,
9656
+ rightInset: 16
9657
+ };
9658
+ const HOST_JUMP_GAP = 8;
9659
+ /** The fold control's place: the Host's seat, or 8px left of the Host's
9660
+ * button while that is showing. Found by the Host's class stem; one cheap
9661
+ * query and two rects per DOM change or resize, on the next frame. */
9662
+ function useHostJumpSeat(stack) {
9663
+ const [seat, setSeat] = useState({
9664
+ shown: false,
9665
+ top: hostSeat.top,
9666
+ right: hostSeat.rightInset
9667
+ });
9668
+ useEffect(() => {
9669
+ if (typeof document === "undefined" || typeof MutationObserver === "undefined") return;
9670
+ let frame;
9671
+ const check = () => {
9672
+ frame = void 0;
9673
+ const native = document.querySelector("button[class*=\"toBottom\"]");
9674
+ const frameRect = stack.current?.getBoundingClientRect();
9675
+ if (native === null || frameRect === void 0) {
9676
+ setSeat({
9677
+ shown: false,
9678
+ top: hostSeat.top,
9679
+ right: hostSeat.rightInset
9680
+ });
9681
+ return;
9682
+ }
9683
+ const rect = native.getBoundingClientRect();
9684
+ if (rect.width > 0) hostSeat = {
9685
+ top: rect.top - frameRect.top,
9686
+ rightInset: frameRect.right - rect.right
9687
+ };
9688
+ setSeat({
9689
+ shown: true,
9690
+ top: hostSeat.top,
9691
+ right: frameRect.right - rect.left + HOST_JUMP_GAP
9692
+ });
9693
+ };
9694
+ const schedule = () => {
9695
+ if (frame === void 0) frame = requestAnimationFrame(check);
9696
+ };
9697
+ check();
9698
+ const observer = new MutationObserver(schedule);
9699
+ observer.observe(document.body, {
9700
+ childList: true,
9701
+ subtree: true
9702
+ });
9703
+ window.addEventListener("resize", schedule);
9704
+ return () => {
9705
+ observer.disconnect();
9706
+ window.removeEventListener("resize", schedule);
9707
+ if (frame !== void 0) cancelAnimationFrame(frame);
9708
+ };
9709
+ }, [stack]);
9710
+ return seat;
9711
+ }
9712
+ /** The fold control floats above the dock in the Host's jump-to-latest seat,
9713
+ * stepping left of that button while the Host shows it: a circle holding a
9714
+ * double chevron, down while folded and up once open. The count and the
9715
+ * words live in its tooltip and accessible name. */
9716
+ function LinkedFoldChip({ sessionId, hidden, expanded, onToggle, t, seat }) {
9717
+ const label = expanded ? t("linkedCollapse") : `${t("linkedMore", { count: hidden })} · ${t("linkedShowAll")}`;
9718
+ return /* @__PURE__ */ jsx(Tooltip, {
9719
+ label,
9720
+ side: "top",
9721
+ delayMs: 250,
9722
+ children: /* @__PURE__ */ jsx("button", {
9723
+ type: "button",
9724
+ style: {
9725
+ ...linkedFoldChip,
9726
+ top: seat.top,
9727
+ right: seat.right
9728
+ },
9729
+ "aria-expanded": expanded,
9730
+ "aria-label": label,
9731
+ "data-dsh-claude-linked-fold": sessionId,
9732
+ onClick: onToggle,
9733
+ children: /* @__PURE__ */ jsx("span", {
9734
+ className: linkedFoldGlyphClass,
9735
+ style: linkedFoldGlyph,
9736
+ "aria-hidden": "true",
9737
+ children: expanded ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(IconChevronUpOutline14, {}), /* @__PURE__ */ jsx(IconChevronUpOutline14, {})] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(IconChevronDownOutline14, {}), /* @__PURE__ */ jsx(IconChevronDownOutline14, {})] })
9738
+ })
9739
+ })
9740
+ });
9741
+ }
9595
9742
  function ClaudeRepositoryStatus({ sessionId, useSessions, useClaudeProjection, t, openDiff, submitPrompt, openOverview, deleteWorkspace }) {
9596
9743
  const blank = useSessions((value) => value.byId[sessionId]?.blank === true);
9597
9744
  const running = useSessions((value) => value.byId[sessionId]?.running === true);
9598
9745
  const projection = useClaudeProjection((value) => value);
9599
9746
  const repository = projection.repository;
9600
9747
  const { toast, report } = useActionToast();
9748
+ const [expanded, setExpanded] = useState(() => linkedExpanded.get(sessionId) ?? false);
9749
+ useEffect(() => {
9750
+ setExpanded(linkedExpanded.get(sessionId) ?? false);
9751
+ }, [sessionId]);
9752
+ const stackRef = useRef(null);
9753
+ const seat = useHostJumpSeat(stackRef);
9601
9754
  if (blank || !projection.owned || repository === void 0) return null;
9602
9755
  const branch = branchLabel(repository, t);
9603
9756
  const merged = repository.pullRequest?.state === "merged";
9604
- const linked = (projection.repositories ?? []).map((item) => /* @__PURE__ */ jsx(LinkedRepositoryBar, {
9605
- sessionId,
9606
- repository: item,
9607
- running,
9608
- t,
9609
- openDiff,
9610
- report,
9611
- ...submitPrompt === void 0 ? {} : { submitPrompt }
9612
- }, item.root ?? `${item.remote ?? item.cwd}#${item.pullRequest?.number ?? ""}`));
9757
+ const all = projection.repositories ?? [];
9758
+ const shown = expanded ? all : all.slice(0, 3);
9759
+ const linked = all.length === 0 ? null : /* @__PURE__ */ jsxs("div", {
9760
+ ref: stackRef,
9761
+ style: linkedStack,
9762
+ children: [all.length > 3 ? /* @__PURE__ */ jsx(LinkedFoldChip, {
9763
+ sessionId,
9764
+ hidden: all.length - 3,
9765
+ expanded,
9766
+ seat,
9767
+ t,
9768
+ onToggle: () => {
9769
+ const next = !expanded;
9770
+ setExpanded(next);
9771
+ linkedExpanded.set(sessionId, next);
9772
+ }
9773
+ }) : null, shown.map((item) => /* @__PURE__ */ jsx(LinkedRepositoryBar, {
9774
+ sessionId,
9775
+ repository: item,
9776
+ running,
9777
+ t,
9778
+ openDiff,
9779
+ report,
9780
+ ...submitPrompt === void 0 ? {} : { submitPrompt }
9781
+ }, item.root ?? `${item.remote ?? item.cwd}#${item.pullRequest?.number ?? ""}`))]
9782
+ });
9613
9783
  if (repository.status !== "ready") return /* @__PURE__ */ jsxs("div", {
9614
9784
  style: repositoryBarFrame,
9615
9785
  [CLAUDE_COMPOSER_BAR_ATTRIBUTE]: "",
@@ -9628,9 +9798,9 @@ window.__ModuleLoader__.load({
9628
9798
  style: repositoryBarFrame,
9629
9799
  [CLAUDE_COMPOSER_BAR_ATTRIBUTE]: "",
9630
9800
  children: [
9631
- /* @__PURE__ */ jsx("style", {
9801
+ /* @__PURE__ */ jsxs("style", {
9632
9802
  "data-dsh-claude-repository-bar-styles": true,
9633
- children: repositoryAutoFixCss
9803
+ children: [repositoryAutoFixCss, linkedFoldGlyphCss]
9634
9804
  }),
9635
9805
  toast,
9636
9806
  linked,
@@ -9662,9 +9832,15 @@ window.__ModuleLoader__.load({
9662
9832
  repository,
9663
9833
  t
9664
9834
  }),
9665
- repository.remote === void 0 ? null : /* @__PURE__ */ jsx("span", {
9666
- style: repositoryRemote,
9667
- children: repositoryName(repository.remote)
9835
+ repository.remote === void 0 ? null : /* @__PURE__ */ jsx(Tooltip, {
9836
+ label: repository.remote,
9837
+ side: "top",
9838
+ delayMs: 250,
9839
+ maxWidth: 420,
9840
+ children: /* @__PURE__ */ jsx("span", {
9841
+ style: repositoryRemote,
9842
+ children: repositoryName(repository.remote)
9843
+ })
9668
9844
  }),
9669
9845
  /* @__PURE__ */ jsx(Tooltip, {
9670
9846
  label: branch,
@@ -19025,6 +19201,9 @@ window.__ModuleLoader__.load({
19025
19201
  presetHeaderHint: "当前会话运行的 Agent 预设",
19026
19202
  diffRepository: "仓库",
19027
19203
  repositoryLinked: "关联仓库:本会话改动过",
19204
+ linkedMore: "还有 {count} 个关联仓库",
19205
+ linkedShowAll: "全部展开",
19206
+ linkedCollapse: "收起关联仓库",
19028
19207
  linkedRepositoryPrompt: "以下内容针对关联仓库 {root}(分支 {branch}),不是本会话自己的仓库。",
19029
19208
  diffFiles: "{count} 个已修改文件",
19030
19209
  diffFilesShort: "{count} 个文件",
@@ -19466,6 +19645,9 @@ window.__ModuleLoader__.load({
19466
19645
  presetHeaderHint: "The agent preset this session runs",
19467
19646
  diffRepository: "Repository",
19468
19647
  repositoryLinked: "Linked repository: changed by this session",
19648
+ linkedMore: "{count} more linked repositories",
19649
+ linkedShowAll: "Show all",
19650
+ linkedCollapse: "Collapse linked repositories",
19469
19651
  linkedRepositoryPrompt: "The following concerns the linked repository at {root} (branch {branch}), not this session's own checkout.",
19470
19652
  diffFiles: "{count} modified file(s)",
19471
19653
  diffFilesShort: "{count} files",