@norman-else/dsh-claude 0.1.47 → 0.1.48

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/client.js CHANGED
@@ -4,7 +4,7 @@ window.__ModuleLoader__.load({
4
4
  var module = { exports: {} };
5
5
  module.exports;
6
6
  var { Fragment, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } = require("react");
7
- var { Button, DiffBlock, DisclosureRow, HoverCard, IconAgentPresetOutline16, IconApiOutline14, IconBranchOutline16, IconCheckOutline14, IconCheckOutline16, IconChevronDownOutline14, IconChevronRightOutline14, IconChevronUpOutline14, IconCloseOutline16, IconEditOutline16, IconFullscreenOutline16, IconListPenOutline16, IconLoadingOutline16, IconQueueOutline14, IconRefreshOutline14, IconRefreshOutline16, IconRightUpOutline14, IconSearchOutline16, IconSendOutline14, IconSparkle16, IconThinkOutline14, IconTrashOutline16, MarkdownText, Menu, Modal, StateDot, Toast, Tooltip, useDismissOnOutsidePointer } = require("@deepseek-ai/dsh-client-ui-primitives");
7
+ var { Button, DiffBlock, DisclosureRow, HoverCard, IconAgentPresetOutline16, IconApiOutline14, IconBranchOutline16, IconCheckOutline14, IconCheckOutline16, IconChevronDownOutline14, IconChevronRightOutline14, IconChevronUpOutline14, IconCloseOutline16, IconEditOutline16, IconListPenOutline16, IconLoadingOutline16, IconQueueOutline14, IconRefreshOutline14, IconRefreshOutline16, IconRightUpOutline14, IconSearchOutline16, IconSendOutline14, IconSparkle16, IconThinkOutline14, IconTrashOutline16, MarkdownText, Menu, Modal, StateDot, Toast, Tooltip, useDismissOnOutsidePointer } = require("@deepseek-ai/dsh-client-ui-primitives");
8
8
  var { Fragment: Fragment$1, jsx, jsxs } = require("react/jsx-runtime");
9
9
  var { createPortal } = require("react-dom");
10
10
  /** Claude's subagent dispatch tools; rendered as plugin-owned group cards
@@ -2211,28 +2211,38 @@ window.__ModuleLoader__.load({
2211
2211
  background: "transparent",
2212
2212
  color: "var(--dsw-alias-label-tertiary)"
2213
2213
  };
2214
- const repositoryAutoFix = {
2215
- width: 26,
2216
- minHeight: 26,
2217
- flex: "none",
2218
- display: "inline-flex",
2219
- alignItems: "center",
2220
- justifyContent: "center",
2221
- padding: 0,
2222
- border: "1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 16%, transparent))",
2223
- borderRadius: 7,
2224
- outline: "none",
2225
- background: "var(--dsw-alias-bg-layer-2)",
2226
- color: "var(--dsw-alias-label-tertiary)",
2227
- font: "inherit",
2228
- lineHeight: "18px",
2229
- cursor: "pointer"
2230
- };
2231
- const repositoryAutoFixActive = {
2232
- borderColor: "color-mix(in srgb, var(--dsw-static-blue-450) 45%, transparent)",
2233
- background: "color-mix(in srgb, var(--dsw-static-blue-450) 12%, transparent)",
2234
- color: "var(--dsw-static-blue-450)"
2235
- };
2214
+ const repositoryAutoFixClass = "dshClaudeAutoFix";
2215
+ /** The switch is styled entirely from a stylesheet: its base look, its on
2216
+ * state off `aria-checked`, its ring off `:focus-visible`. Nothing is set
2217
+ * inline, because an inline border, background or colour would outrank the
2218
+ * on-state rule and the switch would toggle without ever looking switched. */
2219
+ const repositoryAutoFixCss = `
2220
+ .${repositoryAutoFixClass} {
2221
+ width: 26px;
2222
+ min-height: 26px;
2223
+ flex: none;
2224
+ display: inline-flex;
2225
+ align-items: center;
2226
+ justify-content: center;
2227
+ padding: 0;
2228
+ border: 1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 16%, transparent));
2229
+ border-radius: 7px;
2230
+ outline: none;
2231
+ background: var(--dsw-alias-bg-layer-2);
2232
+ color: var(--dsw-alias-label-tertiary);
2233
+ font: inherit;
2234
+ line-height: 18px;
2235
+ cursor: pointer;
2236
+ }
2237
+ .${repositoryAutoFixClass}:focus-visible {
2238
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--dsw-static-blue-450) 28%, transparent);
2239
+ }
2240
+ .${repositoryAutoFixClass}[aria-checked="true"] {
2241
+ border-color: var(--dsw-static-blue-450);
2242
+ background: var(--dsw-static-blue-450);
2243
+ color: var(--dsw-alias-label-on-accent, #fff);
2244
+ }
2245
+ `;
2236
2246
  const repositoryUpdateTrigger = {
2237
2247
  flex: "none",
2238
2248
  display: "inline-flex",
@@ -3234,11 +3244,6 @@ window.__ModuleLoader__.load({
3234
3244
  background: "var(--dsw-alias-bg-layer-1)",
3235
3245
  boxShadow: "0 4px 16px color-mix(in srgb, #000 12%, transparent)"
3236
3246
  };
3237
- const diffPanelMaximized = {
3238
- width: "100%",
3239
- height: "100%",
3240
- margin: 0
3241
- };
3242
3247
  const diffHeader = {
3243
3248
  boxSizing: "border-box",
3244
3249
  height: 49,
@@ -4453,7 +4458,7 @@ window.__ModuleLoader__.load({
4453
4458
  "merge",
4454
4459
  "cherry-pick",
4455
4460
  "revert"
4456
- ].includes(String(repository.operation)) || repository.conflicts !== void 0 && (!Array.isArray(repository.conflicts) || repository.conflicts.length > MAX_CONFLICT_PATHS || repository.conflicts.some((path) => typeof path !== "string" || path.length > MAX_REPOSITORY_TEXT_CHARS))) return false;
4461
+ ].includes(String(repository.operation)) || repository.pullRequestOnly !== void 0 && typeof repository.pullRequestOnly !== "boolean" || repository.conflicts !== void 0 && (!Array.isArray(repository.conflicts) || repository.conflicts.length > MAX_CONFLICT_PATHS || repository.conflicts.some((path) => typeof path !== "string" || path.length > MAX_REPOSITORY_TEXT_CHARS))) return false;
4457
4462
  if (repository.diff !== void 0) {
4458
4463
  const diff = record$7(repository.diff);
4459
4464
  if (diff === void 0 || !nonNegativeInteger(diff.additions) || !nonNegativeInteger(diff.deletions) || !nonNegativeInteger(diff.files) || typeof diff.truncated !== "boolean" || diff.elided !== void 0 && !(Array.isArray(diff.elided) && diff.elided.length <= 1e3 && diff.elided.every((item) => typeof item === "string")) || diff.patch !== void 0 && (typeof diff.patch !== "string" || diff.patch.length > MAX_DIFF_CHARS)) return false;
@@ -6072,8 +6077,8 @@ window.__ModuleLoader__.load({
6072
6077
  }
6073
6078
  return users;
6074
6079
  }
6075
- async function loadFailingChecks(sessionId, pullNumber, signal) {
6076
- const body = await loadJson("/checks", sessionId, pullNumber, signal);
6080
+ async function loadFailingChecks(sessionId, pullNumber, signal, root) {
6081
+ const body = await loadJson("/checks", sessionId, pullNumber, signal, root);
6077
6082
  if (!Array.isArray(body.checks)) throw new Error("Invalid pull request checks response.");
6078
6083
  const checks = [];
6079
6084
  for (const item of body.checks) {
@@ -7602,18 +7607,6 @@ window.__ModuleLoader__.load({
7602
7607
  toolUseId: key.slice(cut + 1)
7603
7608
  };
7604
7609
  }
7605
- /** Restore-from-maximized: four corners pulling inward. Mirrors the diff
7606
- * panel's own, which the primitives set has no counterpart for. */
7607
- function RestorePanelIcon$1() {
7608
- return /* @__PURE__ */ jsx("svg", {
7609
- width: "16",
7610
- height: "16",
7611
- viewBox: "0 0 16 16",
7612
- fill: "currentColor",
7613
- "aria-hidden": "true",
7614
- children: /* @__PURE__ */ jsx("path", { d: "M1.5 5h3V2h1.4v4.4H1.5V5Zm9.9-3h1.4v3h3v1.4h-4.4V2ZM1.5 9.6h4.4V14H4.5v-3h-3V9.6Zm9.9 0h4.4V11h-3v3h-1.4V9.6Z" })
7615
- });
7616
- }
7617
7610
  /** Card and rows reproduce the primitives' menu surface, like the session
7618
7611
  * menu next door: r7, inverted hairline, shadow-lv3, 2px inset. */
7619
7612
  const PICKER_CSS = [
@@ -7662,7 +7655,7 @@ window.__ModuleLoader__.load({
7662
7655
  /** The plan behind an `ExitPlanMode` approval, as the document it was written
7663
7656
  * as. The decision itself stays with the Host's approval dialog; this panel
7664
7657
  * is where the plan is actually read, under the reader's own prose palette. */
7665
- function ClaudePlanPanel({ useClaudeProjection, t, sessionId, closeDetails, maximized, toggleMaximized, submitChanges = sendPlanForChanges }) {
7658
+ function ClaudePlanPanel({ useClaudeProjection, t, sessionId, closeDetails, submitChanges = sendPlanForChanges }) {
7666
7659
  const markdownLabels = useClaudeMarkdownLabels(t);
7667
7660
  const owned = useClaudeProjection((projection) => projection.owned);
7668
7661
  const reviews = planReviews(useClaudeProjection((projection) => projection.activities));
@@ -7754,10 +7747,7 @@ window.__ModuleLoader__.load({
7754
7747
  });
7755
7748
  return /* @__PURE__ */ jsxs("div", {
7756
7749
  className: detailsCardClass,
7757
- style: {
7758
- ...tasksPanel,
7759
- ...maximized ? diffPanelMaximized : {}
7760
- },
7750
+ style: tasksPanel,
7761
7751
  children: [
7762
7752
  /* @__PURE__ */ jsxs("style", {
7763
7753
  "data-dsh-claude-panel-icon-styles": true,
@@ -7833,21 +7823,15 @@ window.__ModuleLoader__.load({
7833
7823
  style: badge(review.state),
7834
7824
  children: t(STATE_LABEL[review.state])
7835
7825
  })]
7836
- }), /* @__PURE__ */ jsxs("div", {
7826
+ }), /* @__PURE__ */ jsx("div", {
7837
7827
  style: planHeaderEnd,
7838
- children: [/* @__PURE__ */ jsx("button", {
7839
- type: "button",
7840
- className: panelIconButtonClass,
7841
- "aria-label": maximized ? t("planRestore") : t("planMaximize"),
7842
- onClick: toggleMaximized,
7843
- children: maximized ? /* @__PURE__ */ jsx(RestorePanelIcon$1, {}) : /* @__PURE__ */ jsx(IconFullscreenOutline16, {})
7844
- }), /* @__PURE__ */ jsx("button", {
7828
+ children: /* @__PURE__ */ jsx("button", {
7845
7829
  type: "button",
7846
7830
  className: panelIconButtonClass,
7847
7831
  "aria-label": t("planClose"),
7848
7832
  onClick: closeDetails,
7849
7833
  children: /* @__PURE__ */ jsx(IconCloseOutline16, {})
7850
- })]
7834
+ })
7851
7835
  })]
7852
7836
  }),
7853
7837
  /* @__PURE__ */ jsx("div", {
@@ -8228,10 +8212,16 @@ window.__ModuleLoader__.load({
8228
8212
  sessionId
8229
8213
  } });
8230
8214
  }
8231
- async function cleanupMergedRepository(path, baseBranch) {
8215
+ /** `branch` names the merged branch when the checkout is no longer on it (a
8216
+ * linked pull request whose clone is back on base). Without a pull request
8217
+ * there is no base, and `requirePushed` has the Host refuse a branch whose
8218
+ * commits are on no remote. */
8219
+ async function cleanupMergedRepository(path, baseBranch, branch, requirePushed) {
8232
8220
  const body = await pluginWrite(`${CLAUDE_REPOSITORY_SETUP_PATH}/cleanup`, "remote", void 0, { json: {
8233
8221
  path,
8234
- baseBranch
8222
+ ...baseBranch === void 0 ? {} : { baseBranch },
8223
+ ...branch === void 0 ? {} : { branch },
8224
+ ...requirePushed === true ? { requirePushed: true } : {}
8235
8225
  } });
8236
8226
  if (body.mode !== "worktree" && body.mode !== "checkout" || typeof body.root !== "string" || typeof body.branch !== "string") throw new Error("Invalid repository cleanup response.");
8237
8227
  return body;
@@ -8599,24 +8589,32 @@ window.__ModuleLoader__.load({
8599
8589
  }
8600
8590
  /** Watches an open pull request and hands new review comments and failing
8601
8591
  * CI runs to Claude automatically until the user switches it off. */
8602
- function AutoFixControl({ sessionId, repository, running, t, submitPrompt }) {
8592
+ /** A prompt about a linked checkout says which one, so Claude does not
8593
+ * apply it to the session's own. */
8594
+ function linkedPreamble(repository, root, t) {
8595
+ return root === void 0 ? "" : `${t("linkedRepositoryPrompt", {
8596
+ root,
8597
+ branch: repository.branch ?? ""
8598
+ })}\n\n`;
8599
+ }
8600
+ function AutoFixControl({ sessionId, repository, root, running, t, submitPrompt }) {
8603
8601
  const pullRequest = repository.pullRequest;
8604
8602
  const open = pullRequest?.state === "open";
8605
8603
  const number = pullRequest?.number;
8606
8604
  const checks = pullRequest?.checks;
8607
- const [enabled, setEnabled] = useState(() => autoFixEnabled(sessionId));
8608
- const [focused, setFocused] = useState(false);
8605
+ const scope = root === void 0 ? sessionId : `${sessionId}#${root}`;
8606
+ const [enabled, setEnabled] = useState(() => autoFixEnabled(scope));
8609
8607
  useEffect(() => {
8610
- setEnabled(autoFixEnabled(sessionId));
8611
- }, [sessionId]);
8608
+ setEnabled(autoFixEnabled(scope));
8609
+ }, [scope]);
8612
8610
  useEffect(() => {
8613
8611
  if (!enabled || !open || running || number === void 0 || submitPrompt === void 0) return;
8614
8612
  let cancelled = false;
8615
8613
  const tick = async () => {
8616
- const [comments, failing] = await Promise.all([loadPullRequestThreads(sessionId, number).catch(() => []), checks === "failing" ? loadFailingChecks(sessionId, number).catch(() => []) : Promise.resolve([])]);
8614
+ const [comments, failing] = await Promise.all([loadPullRequestThreads(sessionId, number, void 0, root).catch(() => []), checks === "failing" ? loadFailingChecks(sessionId, number, void 0, root).catch(() => []) : Promise.resolve([])]);
8617
8615
  if (cancelled) return;
8618
- const plan = planAutoFix(autoFixMemory(sessionId), comments, failing);
8619
- if (plan.prompt !== void 0 && submitPrompt(plan.prompt, "idle")) rememberAutoFix(sessionId, plan.memory);
8616
+ const plan = planAutoFix(autoFixMemory(scope), comments, failing);
8617
+ if (plan.prompt !== void 0 && submitPrompt(`${linkedPreamble(repository, root, t)}${plan.prompt}`, "idle")) rememberAutoFix(scope, plan.memory);
8620
8618
  };
8621
8619
  tick();
8622
8620
  const timer = setInterval(() => {
@@ -8631,15 +8629,19 @@ window.__ModuleLoader__.load({
8631
8629
  enabled,
8632
8630
  number,
8633
8631
  open,
8632
+ repository,
8633
+ root,
8634
8634
  running,
8635
+ scope,
8635
8636
  sessionId,
8636
- submitPrompt
8637
+ submitPrompt,
8638
+ t
8637
8639
  ]);
8638
8640
  if (!open || submitPrompt === void 0) return null;
8639
8641
  const toggle = () => {
8640
8642
  const next = !enabled;
8641
8643
  setEnabled(next);
8642
- setAutoFixEnabled(sessionId, next);
8644
+ setAutoFixEnabled(scope, next);
8643
8645
  };
8644
8646
  return /* @__PURE__ */ jsx(Tooltip, {
8645
8647
  label: `${t("autoFixLabel")} · ${t("autoFixTitle")}`,
@@ -8649,19 +8651,9 @@ window.__ModuleLoader__.load({
8649
8651
  children: /* @__PURE__ */ jsx("button", {
8650
8652
  type: "button",
8651
8653
  role: "switch",
8654
+ className: repositoryAutoFixClass,
8652
8655
  "aria-checked": enabled,
8653
8656
  "aria-label": t("autoFixLabel"),
8654
- style: {
8655
- ...repositoryAutoFix,
8656
- ...enabled ? repositoryAutoFixActive : {},
8657
- ...focused ? heroWorktreeToggleFocused : {}
8658
- },
8659
- onFocus: () => {
8660
- setFocused(true);
8661
- },
8662
- onBlur: () => {
8663
- setFocused(false);
8664
- },
8665
8657
  onClick: (event) => {
8666
8658
  toggle();
8667
8659
  event.currentTarget.blur();
@@ -8681,7 +8673,8 @@ window.__ModuleLoader__.load({
8681
8673
  })
8682
8674
  });
8683
8675
  }
8684
- function FailingChecksControl({ sessionId, pullNumber, t, submitPrompt }) {
8676
+ function FailingChecksControl({ sessionId, repository, root, t, submitPrompt }) {
8677
+ const pullNumber = repository.pullRequest.number;
8685
8678
  const [open, setOpen] = useState(false);
8686
8679
  const [loading, setLoading] = useState(false);
8687
8680
  const [checks, setChecks] = useState([]);
@@ -8708,7 +8701,7 @@ window.__ModuleLoader__.load({
8708
8701
  controller.current = aborter;
8709
8702
  setLoading(true);
8710
8703
  setError(void 0);
8711
- loadFailingChecks(sessionId, pullNumber, aborter.signal).then((value) => {
8704
+ loadFailingChecks(sessionId, pullNumber, aborter.signal, root).then((value) => {
8712
8705
  setChecks(value);
8713
8706
  setLoading(false);
8714
8707
  }, (reason) => {
@@ -8774,7 +8767,7 @@ window.__ModuleLoader__.load({
8774
8767
  type: "button",
8775
8768
  style: repositoryChecksFix,
8776
8769
  onClick: () => {
8777
- submitPrompt(composeChecksPrompt(checks));
8770
+ submitPrompt(`${linkedPreamble(repository, root, t)}${composeChecksPrompt(checks)}`);
8778
8771
  setOpen(false);
8779
8772
  },
8780
8773
  children: t("checksCardFix")
@@ -8787,7 +8780,7 @@ window.__ModuleLoader__.load({
8787
8780
  * hides every other control on this bar, and the update-branch dialog that
8788
8781
  * started it takes its conflict list along when it closes -- so this one is
8789
8782
  * mounted from repository state instead, and survives being dismissed. */
8790
- function ConflictControl({ sessionId, repository, t, report, submitPrompt }) {
8783
+ function ConflictControl({ sessionId, repository, root, t, report, submitPrompt }) {
8791
8784
  const [dialog, setDialog] = useState();
8792
8785
  const operation = repository.operation;
8793
8786
  if (operation === void 0) return null;
@@ -8809,7 +8802,7 @@ window.__ModuleLoader__.load({
8809
8802
  message: "",
8810
8803
  includeUnstaged: false,
8811
8804
  push: dialog.push
8812
- }).then((result) => {
8805
+ }, root).then((result) => {
8813
8806
  if (result.conflicts !== void 0 && result.conflicts.length > 0) {
8814
8807
  setDialog({
8815
8808
  ...pending,
@@ -8911,7 +8904,7 @@ window.__ModuleLoader__.load({
8911
8904
  type: "button",
8912
8905
  style: diffModalConflictResolve,
8913
8906
  onClick: () => {
8914
- submitPrompt(composeConflictsPrompt(conflicts, operation, repository.pullRequest?.baseBranch));
8907
+ submitPrompt(`${linkedPreamble(repository, root, t)}${composeConflictsPrompt(conflicts, operation, repository.pullRequest?.baseBranch)}`);
8915
8908
  closeDialog();
8916
8909
  },
8917
8910
  children: t("conflictResolve")
@@ -8954,7 +8947,7 @@ window.__ModuleLoader__.load({
8954
8947
  if (pullRequest?.baseBranch === void 0) return false;
8955
8948
  return dialogOpen || pullRequest.state === "open" && repository.detached !== true && repository.dirty !== true && (repository.baseBehind ?? 0) > 0;
8956
8949
  }
8957
- function UpdateBranchControl({ sessionId, repository, t, report, submitPrompt }) {
8950
+ function UpdateBranchControl({ sessionId, repository, root, t, report, submitPrompt }) {
8958
8951
  const [dialog, setDialog] = useState();
8959
8952
  const [method, setMethod] = useState("rebase");
8960
8953
  const controller = useRef();
@@ -8972,7 +8965,7 @@ window.__ModuleLoader__.load({
8972
8965
  });
8973
8966
  const aborter = new AbortController();
8974
8967
  controller.current = aborter;
8975
- loadRepositoryActionPreview(sessionId, aborter.signal).then((preview) => {
8968
+ loadRepositoryActionPreview(sessionId, aborter.signal, root).then((preview) => {
8976
8969
  setDialog({
8977
8970
  loading: false,
8978
8971
  submitting: false,
@@ -9006,7 +8999,7 @@ window.__ModuleLoader__.load({
9006
8999
  includeUnstaged: false,
9007
9000
  baseBranch: base,
9008
9001
  mergeMethod: method
9009
- }).then((result) => {
9002
+ }, root).then((result) => {
9010
9003
  if (result.conflicts !== void 0 && result.conflicts.length > 0) {
9011
9004
  setDialog({
9012
9005
  ...pending,
@@ -9117,7 +9110,7 @@ window.__ModuleLoader__.load({
9117
9110
  type: "button",
9118
9111
  style: diffModalConflictResolve,
9119
9112
  onClick: () => {
9120
- submitPrompt(composeConflictsPrompt(dialog.conflicts ?? [], method, base));
9113
+ submitPrompt(`${linkedPreamble(repository, root, t)}${composeConflictsPrompt(dialog.conflicts ?? [], method, base)}`);
9121
9114
  closeDialog();
9122
9115
  },
9123
9116
  children: t("diffUpdateBranchResolve")
@@ -9140,14 +9133,17 @@ window.__ModuleLoader__.load({
9140
9133
  const [dialog, setDialog] = useState();
9141
9134
  const pullRequest = repository.pullRequest;
9142
9135
  const base = pullRequest?.baseBranch;
9143
- if (pullRequest?.state !== "merged" || base === void 0 || repository.root === void 0 || repository.detached === true) return null;
9136
+ const merged = pullRequest?.state === "merged" && base !== void 0;
9137
+ const unmerged = pullRequest === void 0 && repository.worktree === true && repository.dirty !== true;
9138
+ if (!merged && !unmerged || repository.root === void 0 || repository.detached === true) return null;
9144
9139
  const root = repository.root;
9145
9140
  const closeDialog = () => {
9146
9141
  if (dialog?.submitting !== true) setDialog(void 0);
9147
9142
  };
9148
9143
  const confirm = () => {
9149
9144
  setDialog({ submitting: true });
9150
- cleanupMergedRepository(root, base).then(async (result) => {
9145
+ const named = repository.pullRequestOnly === true || unmerged ? repository.branch : void 0;
9146
+ cleanupMergedRepository(root, base, named, unmerged).then(async (result) => {
9151
9147
  report(t("cleanupCompleted", { branch: result.branch }));
9152
9148
  setDialog(void 0);
9153
9149
  if (result.mode === "worktree" && deleteWorkspace !== void 0) await deleteWorkspace();
@@ -9179,7 +9175,7 @@ window.__ModuleLoader__.load({
9179
9175
  onClose: closeDialog,
9180
9176
  title: t("cleanupTitle"),
9181
9177
  closeLabel: t("diffCancel"),
9182
- description: t("cleanupDescription"),
9178
+ description: t(unmerged ? "cleanupDescriptionUnmerged" : "cleanupDescription"),
9183
9179
  footer: /* @__PURE__ */ jsxs("div", {
9184
9180
  style: diffModalFooter,
9185
9181
  children: [/* @__PURE__ */ jsx("button", {
@@ -9208,11 +9204,7 @@ window.__ModuleLoader__.load({
9208
9204
  style: diffModalMeta,
9209
9205
  children: [/* @__PURE__ */ jsxs("strong", {
9210
9206
  style: diffModalMetaText,
9211
- children: [
9212
- repository.branch ?? t("repositoryUnknownBranch"),
9213
- " → ",
9214
- base
9215
- ]
9207
+ children: [repository.branch ?? t("repositoryUnknownBranch"), base === void 0 ? "" : ` → ${base}`]
9216
9208
  }), /* @__PURE__ */ jsx("span", {
9217
9209
  style: diffModalFileState,
9218
9210
  children: repository.worktree === true ? t("repositoryWorktree") : t("repositoryLocal")
@@ -9231,7 +9223,7 @@ window.__ModuleLoader__.load({
9231
9223
  "squash",
9232
9224
  "rebase"
9233
9225
  ];
9234
- function MergePullRequestControl({ sessionId, repository, t, report }) {
9226
+ function MergePullRequestControl({ sessionId, repository, root, t, report }) {
9235
9227
  const [menuOpen, setMenuOpen] = useState(false);
9236
9228
  const [dialog, setDialog] = useState();
9237
9229
  const controller = useRef();
@@ -9249,7 +9241,7 @@ window.__ModuleLoader__.load({
9249
9241
  });
9250
9242
  const aborter = new AbortController();
9251
9243
  controller.current = aborter;
9252
- loadRepositoryActionPreview(sessionId, aborter.signal).then((preview) => {
9244
+ loadRepositoryActionPreview(sessionId, aborter.signal, root).then((preview) => {
9253
9245
  setDialog((current) => ({
9254
9246
  method,
9255
9247
  admin: current?.admin ?? false,
@@ -9286,8 +9278,9 @@ window.__ModuleLoader__.load({
9286
9278
  message: "",
9287
9279
  includeUnstaged: false,
9288
9280
  mergeMethod: dialog.method,
9289
- ...dialog.admin ? { admin: true } : {}
9290
- }).then(() => {
9281
+ ...dialog.admin ? { admin: true } : {},
9282
+ ...root === void 0 ? {} : { pullNumber: pullRequest.number }
9283
+ }, root).then(() => {
9291
9284
  report(t("diffMergeCompleted", { number: pullRequest.number }));
9292
9285
  setDialog(void 0);
9293
9286
  }, (error) => {
@@ -9415,12 +9408,121 @@ window.__ModuleLoader__.load({
9415
9408
  children: [/* @__PURE__ */ jsx("path", { d: "M6.8 9.2a3 3 0 0 0 4.2 0l2-2a3 3 0 0 0-4.2-4.2l-1 1" }), /* @__PURE__ */ jsx("path", { d: "M9.2 6.8a3 3 0 0 0-4.2 0l-2 2a3 3 0 0 0 4.2 4.2l1-1" })]
9416
9409
  });
9417
9410
  }
9411
+ /** Everything to the right of the branch: the diff counts and the pull
9412
+ * request's controls. One row for the session checkout and each linked one;
9413
+ * `root` scopes the requests to a linked checkout. */
9414
+ function RepositoryControls({ sessionId, repository, root, running, t, report, openDiff, submitPrompt, deleteWorkspace }) {
9415
+ const pullRequest = repository.pullRequest;
9416
+ const merged = pullRequest?.state === "merged";
9417
+ const mergedAge = merged ? relativeAge(pullRequest.mergedAt) : void 0;
9418
+ const aheadCount = repository.ahead ?? 0;
9419
+ const pushable = repository.remote !== void 0 && repository.detached !== true && (aheadCount > 0 || repository.upstream === false);
9420
+ const hasDiff = repository.diff !== void 0 && (repository.diff.additions > 0 || repository.diff.deletions > 0);
9421
+ const actionable = repository.pullRequestOnly !== true || root !== void 0;
9422
+ const prompt = submitPrompt === void 0 ? {} : { submitPrompt };
9423
+ return /* @__PURE__ */ jsxs("span", {
9424
+ style: repositoryStatusItems,
9425
+ children: [
9426
+ /* @__PURE__ */ jsx(ConflictControl, {
9427
+ sessionId,
9428
+ repository,
9429
+ root,
9430
+ t,
9431
+ report,
9432
+ ...prompt
9433
+ }),
9434
+ hasDiff || pushable ? /* @__PURE__ */ jsxs("button", {
9435
+ type: "button",
9436
+ style: {
9437
+ ...diffTrigger,
9438
+ ...merged ? diffTriggerMuted : {}
9439
+ },
9440
+ onClick: openDiff,
9441
+ "aria-label": t("diffOpen"),
9442
+ children: [hasDiff && repository.diff !== void 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
9443
+ style: merged ? diffAddMuted : diffAdd,
9444
+ children: ["+", repository.diff.additions]
9445
+ }), /* @__PURE__ */ jsxs("span", {
9446
+ style: merged ? diffDeleteMuted : diffDelete,
9447
+ children: ["−", repository.diff.deletions]
9448
+ })] }) : null, pushable ? /* @__PURE__ */ jsxs("span", {
9449
+ style: merged ? diffAheadMuted : diffAhead,
9450
+ children: ["↑", aheadCount > 0 ? aheadCount : ""]
9451
+ }) : null]
9452
+ }) : null,
9453
+ pullRequest === void 0 ? null : merged ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
9454
+ style: repositoryMergedStatus,
9455
+ children: [
9456
+ /* @__PURE__ */ jsx("span", {
9457
+ style: repositoryMergedDot,
9458
+ "aria-hidden": "true"
9459
+ }),
9460
+ t("repositoryState_merged"),
9461
+ mergedAge === void 0 ? null : /* @__PURE__ */ jsxs("span", {
9462
+ style: repositoryMergedAge,
9463
+ children: ["· ", t("repositoryMergedAgo", { age: mergedAge })]
9464
+ })
9465
+ ]
9466
+ }), /* @__PURE__ */ jsx(CleanupControl, {
9467
+ repository,
9468
+ t,
9469
+ report,
9470
+ ...deleteWorkspace === void 0 ? {} : { deleteWorkspace }
9471
+ })] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
9472
+ pullRequest.checks === "failing" && actionable ? /* @__PURE__ */ jsx(FailingChecksControl, {
9473
+ sessionId,
9474
+ repository: {
9475
+ ...repository,
9476
+ pullRequest
9477
+ },
9478
+ root,
9479
+ t,
9480
+ ...prompt
9481
+ }) : pullRequest.checks === "none" ? null : /* @__PURE__ */ jsx(StatusGlyph, {
9482
+ label: t(`repositoryChecks_${pullRequest.checks}`),
9483
+ tone: pullRequest.checks === "passing" ? "success" : pullRequest.checks === "failing" ? "error" : "warning",
9484
+ children: /* @__PURE__ */ jsx(ChecksGlyph, { state: pullRequest.checks })
9485
+ }),
9486
+ pullRequest.review === "none" ? null : /* @__PURE__ */ jsx(StatusGlyph, {
9487
+ label: t(`repositoryReview_${pullRequest.review}`),
9488
+ tone: pullRequest.review === "approved" ? "success" : pullRequest.review === "changes-requested" ? "error" : "neutral",
9489
+ children: /* @__PURE__ */ jsx(ReviewGlyph, {})
9490
+ }),
9491
+ actionable ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
9492
+ /* @__PURE__ */ jsx(AutoFixControl, {
9493
+ sessionId,
9494
+ repository,
9495
+ root,
9496
+ running,
9497
+ t,
9498
+ ...prompt
9499
+ }),
9500
+ /* @__PURE__ */ jsx(UpdateBranchControl, {
9501
+ sessionId,
9502
+ repository,
9503
+ root,
9504
+ t,
9505
+ report,
9506
+ ...prompt
9507
+ }),
9508
+ /* @__PURE__ */ jsx(MergePullRequestControl, {
9509
+ sessionId,
9510
+ repository,
9511
+ root,
9512
+ t,
9513
+ report
9514
+ })
9515
+ ] }) : null
9516
+ ] })
9517
+ ]
9518
+ });
9519
+ }
9418
9520
  /** A checkout the session wrote into besides its own, stacked above the
9419
9521
  * session bar so that one stays put next to the composer. The same readout
9420
- * as the session bar, minus the controls that act on the session (auto-fix, update,
9421
- * merge, cleanup), which live with the checkout the session was opened on. */
9422
- function LinkedRepositoryBar({ repository, t, openDiff, report }) {
9423
- const key = repository.root ?? repository.cwd;
9522
+ * and controls as the session bar, scoped to that checkout; only the
9523
+ * workspace deletion after a clean-up stays with the session's own. */
9524
+ function LinkedRepositoryBar({ sessionId, repository, running, t, openDiff, report, submitPrompt }) {
9525
+ const key = repository.root ?? `${repository.remote ?? repository.cwd}#${repository.pullRequest?.number ?? ""}`;
9424
9526
  if (repository.status !== "ready") return /* @__PURE__ */ jsxs("div", {
9425
9527
  style: {
9426
9528
  ...repositoryBar,
@@ -9441,9 +9543,7 @@ window.__ModuleLoader__.load({
9441
9543
  })]
9442
9544
  });
9443
9545
  const branch = branchLabel(repository, t);
9444
- const pullRequest = repository.pullRequest;
9445
- const merged = pullRequest?.state === "merged";
9446
- const hasDiff = repository.diff !== void 0 && (repository.diff.additions > 0 || repository.diff.deletions > 0);
9546
+ const merged = repository.pullRequest?.state === "merged";
9447
9547
  return /* @__PURE__ */ jsxs("div", {
9448
9548
  style: {
9449
9549
  ...repositoryBar,
@@ -9479,42 +9579,15 @@ window.__ModuleLoader__.load({
9479
9579
  style: repositoryWorktree,
9480
9580
  children: t("repositoryWorktree")
9481
9581
  }) : null,
9482
- /* @__PURE__ */ jsxs("span", {
9483
- style: repositoryStatusItems,
9484
- children: [hasDiff && repository.diff !== void 0 ? /* @__PURE__ */ jsxs("button", {
9485
- type: "button",
9486
- style: {
9487
- ...diffTrigger,
9488
- ...merged ? diffTriggerMuted : {}
9489
- },
9490
- onClick: () => openDiff(repository.root),
9491
- "aria-label": t("diffOpen"),
9492
- children: [/* @__PURE__ */ jsxs("span", {
9493
- style: merged ? diffAddMuted : diffAdd,
9494
- children: ["+", repository.diff.additions]
9495
- }), /* @__PURE__ */ jsxs("span", {
9496
- style: merged ? diffDeleteMuted : diffDelete,
9497
- children: ["−", repository.diff.deletions]
9498
- })]
9499
- }) : null, pullRequest === void 0 ? null : merged ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
9500
- style: repositoryMergedStatus,
9501
- children: [/* @__PURE__ */ jsx("span", {
9502
- style: repositoryMergedDot,
9503
- "aria-hidden": "true"
9504
- }), t("repositoryState_merged")]
9505
- }), /* @__PURE__ */ jsx(CleanupControl, {
9506
- repository,
9507
- t,
9508
- report
9509
- })] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [pullRequest.checks === "none" ? null : /* @__PURE__ */ jsx(StatusGlyph, {
9510
- label: t(`repositoryChecks_${pullRequest.checks}`),
9511
- tone: pullRequest.checks === "passing" ? "success" : pullRequest.checks === "failing" ? "error" : "warning",
9512
- children: /* @__PURE__ */ jsx(ChecksGlyph, { state: pullRequest.checks })
9513
- }), pullRequest.review === "none" ? null : /* @__PURE__ */ jsx(StatusGlyph, {
9514
- label: t(`repositoryReview_${pullRequest.review}`),
9515
- tone: pullRequest.review === "approved" ? "success" : pullRequest.review === "changes-requested" ? "error" : "neutral",
9516
- children: /* @__PURE__ */ jsx(ReviewGlyph, {})
9517
- })] })]
9582
+ /* @__PURE__ */ jsx(RepositoryControls, {
9583
+ sessionId,
9584
+ repository,
9585
+ root: repository.root,
9586
+ running,
9587
+ t,
9588
+ report,
9589
+ openDiff: () => openDiff(repository.root),
9590
+ ...submitPrompt === void 0 ? {} : { submitPrompt }
9518
9591
  })
9519
9592
  ]
9520
9593
  });
@@ -9527,18 +9600,16 @@ window.__ModuleLoader__.load({
9527
9600
  const { toast, report } = useActionToast();
9528
9601
  if (blank || !projection.owned || repository === void 0) return null;
9529
9602
  const branch = branchLabel(repository, t);
9530
- const pullRequest = repository.pullRequest;
9531
- const merged = pullRequest?.state === "merged";
9532
- const mergedAge = merged ? relativeAge(pullRequest.mergedAt) : void 0;
9533
- const aheadCount = repository.ahead ?? 0;
9534
- const pushable = repository.remote !== void 0 && repository.detached !== true && (aheadCount > 0 || repository.upstream === false);
9535
- const hasDiff = repository.diff !== void 0 && (repository.diff.additions > 0 || repository.diff.deletions > 0);
9603
+ const merged = repository.pullRequest?.state === "merged";
9536
9604
  const linked = (projection.repositories ?? []).map((item) => /* @__PURE__ */ jsx(LinkedRepositoryBar, {
9605
+ sessionId,
9537
9606
  repository: item,
9607
+ running,
9538
9608
  t,
9539
9609
  openDiff,
9540
- report
9541
- }, item.root ?? item.cwd));
9610
+ report,
9611
+ ...submitPrompt === void 0 ? {} : { submitPrompt }
9612
+ }, item.root ?? `${item.remote ?? item.cwd}#${item.pullRequest?.number ?? ""}`));
9542
9613
  if (repository.status !== "ready") return /* @__PURE__ */ jsxs("div", {
9543
9614
  style: repositoryBarFrame,
9544
9615
  [CLAUDE_COMPOSER_BAR_ATTRIBUTE]: "",
@@ -9557,6 +9628,10 @@ window.__ModuleLoader__.load({
9557
9628
  style: repositoryBarFrame,
9558
9629
  [CLAUDE_COMPOSER_BAR_ATTRIBUTE]: "",
9559
9630
  children: [
9631
+ /* @__PURE__ */ jsx("style", {
9632
+ "data-dsh-claude-repository-bar-styles": true,
9633
+ children: repositoryAutoFixCss
9634
+ }),
9560
9635
  toast,
9561
9636
  linked,
9562
9637
  /* @__PURE__ */ jsxs("div", {
@@ -9605,91 +9680,15 @@ window.__ModuleLoader__.load({
9605
9680
  style: repositoryWorktree,
9606
9681
  children: t("repositoryWorktree")
9607
9682
  }) : null,
9608
- /* @__PURE__ */ jsxs("span", {
9609
- style: repositoryStatusItems,
9610
- children: [
9611
- /* @__PURE__ */ jsx(ConflictControl, {
9612
- sessionId,
9613
- repository,
9614
- t,
9615
- report,
9616
- ...submitPrompt === void 0 ? {} : { submitPrompt }
9617
- }),
9618
- hasDiff || pushable ? /* @__PURE__ */ jsxs("button", {
9619
- type: "button",
9620
- style: {
9621
- ...diffTrigger,
9622
- ...merged ? diffTriggerMuted : {}
9623
- },
9624
- onClick: () => openDiff(),
9625
- "aria-label": t("diffOpen"),
9626
- children: [hasDiff && repository.diff !== void 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
9627
- style: merged ? diffAddMuted : diffAdd,
9628
- children: ["+", repository.diff.additions]
9629
- }), /* @__PURE__ */ jsxs("span", {
9630
- style: merged ? diffDeleteMuted : diffDelete,
9631
- children: ["−", repository.diff.deletions]
9632
- })] }) : null, pushable ? /* @__PURE__ */ jsxs("span", {
9633
- style: merged ? diffAheadMuted : diffAhead,
9634
- children: ["↑", aheadCount > 0 ? aheadCount : ""]
9635
- }) : null]
9636
- }) : null,
9637
- pullRequest === void 0 ? null : merged ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
9638
- style: repositoryMergedStatus,
9639
- children: [
9640
- /* @__PURE__ */ jsx("span", {
9641
- style: repositoryMergedDot,
9642
- "aria-hidden": "true"
9643
- }),
9644
- t("repositoryState_merged"),
9645
- mergedAge === void 0 ? null : /* @__PURE__ */ jsxs("span", {
9646
- style: repositoryMergedAge,
9647
- children: ["· ", t("repositoryMergedAgo", { age: mergedAge })]
9648
- })
9649
- ]
9650
- }), /* @__PURE__ */ jsx(CleanupControl, {
9651
- repository,
9652
- t,
9653
- report,
9654
- ...deleteWorkspace === void 0 ? {} : { deleteWorkspace }
9655
- })] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
9656
- pullRequest.checks === "failing" ? /* @__PURE__ */ jsx(FailingChecksControl, {
9657
- sessionId,
9658
- pullNumber: pullRequest.number,
9659
- t,
9660
- ...submitPrompt === void 0 ? {} : { submitPrompt }
9661
- }) : pullRequest.checks === "none" ? null : /* @__PURE__ */ jsx(StatusGlyph, {
9662
- label: t(`repositoryChecks_${pullRequest.checks}`),
9663
- tone: pullRequest.checks === "passing" ? "success" : "warning",
9664
- children: /* @__PURE__ */ jsx(ChecksGlyph, { state: pullRequest.checks })
9665
- }),
9666
- pullRequest.review === "none" ? null : /* @__PURE__ */ jsx(StatusGlyph, {
9667
- label: t(`repositoryReview_${pullRequest.review}`),
9668
- tone: pullRequest.review === "approved" ? "success" : pullRequest.review === "changes-requested" ? "error" : "neutral",
9669
- children: /* @__PURE__ */ jsx(ReviewGlyph, {})
9670
- }),
9671
- /* @__PURE__ */ jsx(AutoFixControl, {
9672
- sessionId,
9673
- repository,
9674
- running,
9675
- t,
9676
- ...submitPrompt === void 0 ? {} : { submitPrompt }
9677
- }),
9678
- /* @__PURE__ */ jsx(UpdateBranchControl, {
9679
- sessionId,
9680
- repository,
9681
- t,
9682
- report,
9683
- ...submitPrompt === void 0 ? {} : { submitPrompt }
9684
- }),
9685
- /* @__PURE__ */ jsx(MergePullRequestControl, {
9686
- sessionId,
9687
- repository,
9688
- t,
9689
- report
9690
- })
9691
- ] })
9692
- ]
9683
+ /* @__PURE__ */ jsx(RepositoryControls, {
9684
+ sessionId,
9685
+ repository,
9686
+ running,
9687
+ t,
9688
+ report,
9689
+ openDiff: () => openDiff(),
9690
+ ...submitPrompt === void 0 ? {} : { submitPrompt },
9691
+ ...deleteWorkspace === void 0 ? {} : { deleteWorkspace }
9693
9692
  })
9694
9693
  ]
9695
9694
  })
@@ -15072,24 +15071,15 @@ window.__ModuleLoader__.load({
15072
15071
  "update-branch": ready && hasOpenPullRequest && repository?.dirty !== true && (repository?.baseBehind ?? 0) > 0
15073
15072
  };
15074
15073
  }
15075
- function RestorePanelIcon() {
15076
- return /* @__PURE__ */ jsx("svg", {
15077
- width: "16",
15078
- height: "16",
15079
- viewBox: "0 0 16 16",
15080
- fill: "currentColor",
15081
- "aria-hidden": "true",
15082
- children: /* @__PURE__ */ jsx("path", { d: "M1.5 5h3V2h1.4v4.4H1.5V5Zm9.9-3h1.4v3h3v1.4h-4.4V2ZM1.5 9.6h4.4V14H4.5v-3h-3V9.6Zm9.9 0h4.4V11h-3v3h-1.4V9.6Z" })
15083
- });
15084
- }
15085
15074
  function hasChanges(repository) {
15086
15075
  return (repository?.diff?.additions ?? 0) > 0 || (repository?.diff?.deletions ?? 0) > 0;
15087
15076
  }
15088
- /** The checkouts a session can show: its own first, then the ones it wrote into. */
15077
+ /** The checkouts a session can show: its own first, then the ones it wrote
15078
+ * into. A linked pull request with no local checkout has no diff to show. */
15089
15079
  function panelRepositories(projection) {
15090
- return [projection.repository, ...projection.repositories ?? []].filter((item) => item !== void 0);
15080
+ return [projection.repository, ...(projection.repositories ?? []).filter((item) => item.diff !== void 0)].filter((item) => item !== void 0);
15091
15081
  }
15092
- function ClaudeDiffPanel({ useClaudeProjection, t, sessionId, maximized, closeDetails, toggleMaximized, submitPrompt, initialRoot }) {
15082
+ function ClaudeDiffPanel({ useClaudeProjection, t, sessionId, closeDetails, submitPrompt, initialRoot }) {
15093
15083
  const projection = useClaudeProjection((value) => value);
15094
15084
  const repositories = useMemo(() => panelRepositories(projection), [projection]);
15095
15085
  const [selectedRoot, setSelectedRoot] = useState(() => initialRoot ?? (hasChanges(projection.repository) ? void 0 : repositories.find(hasChanges)?.root));
@@ -15518,10 +15508,7 @@ window.__ModuleLoader__.load({
15518
15508
  }),
15519
15509
  /* @__PURE__ */ jsxs("div", {
15520
15510
  className: detailsCardClass,
15521
- style: {
15522
- ...diffPanel,
15523
- ...maximized ? diffPanelMaximized : {}
15524
- },
15511
+ style: diffPanel,
15525
15512
  children: [
15526
15513
  /* @__PURE__ */ jsxs("header", {
15527
15514
  style: diffHeader,
@@ -15645,13 +15632,6 @@ window.__ModuleLoader__.load({
15645
15632
  children: /* @__PURE__ */ jsx("path", { d: "M2.75 2.75h10.5a1 1 0 0 1 1 1v6.5a1 1 0 0 1-1 1H8.2l-3.2 2.9v-2.9H2.75a1 1 0 0 1-1-1v-6.5a1 1 0 0 1 1-1Z" })
15646
15633
  }), openThreadCount]
15647
15634
  }) : null,
15648
- /* @__PURE__ */ jsx("button", {
15649
- type: "button",
15650
- className: panelIconButtonClass,
15651
- "aria-label": maximized ? t("diffRestore") : t("diffMaximize"),
15652
- onClick: toggleMaximized,
15653
- children: maximized ? /* @__PURE__ */ jsx(RestorePanelIcon, {}) : /* @__PURE__ */ jsx(IconFullscreenOutline16, {})
15654
- }),
15655
15635
  /* @__PURE__ */ jsx("button", {
15656
15636
  type: "button",
15657
15637
  className: panelIconButtonClass,
@@ -15711,7 +15691,7 @@ window.__ModuleLoader__.load({
15711
15691
  children: t("diffEmpty")
15712
15692
  }) : files.map((file, index) => /* @__PURE__ */ jsx(DiffFileSection, {
15713
15693
  file,
15714
- root: repository.root,
15694
+ root: repository.pullRequestOnly === true ? void 0 : repository.root,
15715
15695
  open: fileOpen(file.path, index),
15716
15696
  onOpenChange: (open) => {
15717
15697
  setFileOpen(file.path, open);
@@ -15901,9 +15881,9 @@ window.__ModuleLoader__.load({
15901
15881
  * focuses that tab and re-delivers the navigation params, so a second "show
15902
15882
  * tasks" press for another turn lands in the same tab.
15903
15883
  *
15904
- * The Host owns fullscreen and closing now, so the maximized overlays this
15905
- * package used to draw are gone: a panel's maximize button toggles the
15906
- * sidebar's own expanded mode, and its close button closes the tab.
15884
+ * The Host owns fullscreen and closing now: the sidebar chrome carries its
15885
+ * own fullscreen toggle, so the panels draw none, and a panel's close button
15886
+ * closes its tab.
15907
15887
  */
15908
15888
  const CLAUDE_TAB_KINDS = {
15909
15889
  diff: "claude-diff",
@@ -15916,7 +15896,7 @@ window.__ModuleLoader__.load({
15916
15896
  #byKey = /* @__PURE__ */ new Map();
15917
15897
  #listeners = /* @__PURE__ */ new Map();
15918
15898
  static key(kind, sessionId) {
15919
- return `${kind}${sessionId}`;
15899
+ return `${kind}\0${sessionId}`;
15920
15900
  }
15921
15901
  tabId(kind, sessionId) {
15922
15902
  return this.#byKey.get(TabOccupancy.key(kind, sessionId));
@@ -15963,27 +15943,22 @@ window.__ModuleLoader__.load({
15963
15943
  closeDetails: useCallback(() => {
15964
15944
  actions.close();
15965
15945
  }, [actions]),
15966
- maximized: info.sidebar.fullscreen,
15967
15946
  params: info.tab.navigation.params ?? {}
15968
15947
  };
15969
15948
  }
15970
- function ClaudeDiffTab({ useTabInfo, noteTab, toggleMaximized, ...panel }) {
15971
- const { closeDetails, maximized, params } = useClaudeTab(useTabInfo, noteTab);
15949
+ function ClaudeDiffTab({ useTabInfo, noteTab, ...panel }) {
15950
+ const { closeDetails, params } = useClaudeTab(useTabInfo, noteTab);
15972
15951
  return /* @__PURE__ */ jsx(ClaudeDiffPanel, {
15973
15952
  ...panel,
15974
15953
  closeDetails,
15975
- maximized,
15976
- toggleMaximized,
15977
15954
  ...params.initialRoot === void 0 ? {} : { initialRoot: params.initialRoot }
15978
15955
  });
15979
15956
  }
15980
- function ClaudePlanTab({ useTabInfo, noteTab, toggleMaximized, ...panel }) {
15981
- const { closeDetails, maximized } = useClaudeTab(useTabInfo, noteTab);
15957
+ function ClaudePlanTab({ useTabInfo, noteTab, ...panel }) {
15958
+ const { closeDetails } = useClaudeTab(useTabInfo, noteTab);
15982
15959
  return /* @__PURE__ */ jsx(ClaudePlanPanel, {
15983
15960
  ...panel,
15984
- closeDetails,
15985
- maximized,
15986
- toggleMaximized
15961
+ closeDetails
15987
15962
  });
15988
15963
  }
15989
15964
  function ClaudeTasksTab({ useTabInfo, noteTab, ...panel }) {
@@ -16007,15 +15982,9 @@ window.__ModuleLoader__.load({
16007
15982
  function registerClaudeSidebarTabs(ctx, options) {
16008
15983
  const { t, namespace } = options;
16009
15984
  const occupancy = new TabOccupancy();
16010
- const toggleMaximized = () => {
16011
- ctx.sidebarRight.toggleExpanded();
16012
- };
16013
- const faceFor = (kind, sessionId) => ({
16014
- noteTab: (tabId) => {
16015
- occupancy.note(kind, sessionId, tabId);
16016
- },
16017
- toggleMaximized
16018
- });
15985
+ const faceFor = (kind, sessionId) => ({ noteTab: (tabId) => {
15986
+ occupancy.note(kind, sessionId, tabId);
15987
+ } });
16019
15988
  const titles = {
16020
15989
  [CLAUDE_TAB_KINDS.diff]: () => t("diffTabTitle"),
16021
15990
  [CLAUDE_TAB_KINDS.plan]: () => t("planPanelTitle"),
@@ -19022,8 +18991,6 @@ window.__ModuleLoader__.load({
19022
18991
  planPanelTitle: "Plan",
19023
18992
  planClose: "关闭方案面板",
19024
18993
  planOpen: "查看方案",
19025
- planMaximize: "最大化方案面板",
19026
- planRestore: "还原方案面板",
19027
18994
  planNth: "{index} / {total}",
19028
18995
  planHistory: "本会话的方案",
19029
18996
  planNotePlaceholder: "写下要改的地方,Enter 记一条,⌘/Ctrl+Enter 发送",
@@ -19058,12 +19025,12 @@ window.__ModuleLoader__.load({
19058
19025
  presetHeaderHint: "当前会话运行的 Agent 预设",
19059
19026
  diffRepository: "仓库",
19060
19027
  repositoryLinked: "关联仓库:本会话改动过",
19028
+ linkedRepositoryPrompt: "以下内容针对关联仓库 {root}(分支 {branch}),不是本会话自己的仓库。",
19061
19029
  diffFiles: "{count} 个已修改文件",
19062
19030
  diffFilesShort: "{count} 个文件",
19063
19031
  diffTruncated: "Diff 超出安全显示上限。请在终端中查看完整内容。",
19064
19032
  diffEmpty: "没有可显示的 tracked 文件改动",
19065
19033
  diffElided: "{count} 个文件过大未展示:{files}",
19066
- diffMaximize: "最大化 Diff 面板",
19067
19034
  diffCommentPrevious: "上一条评论",
19068
19035
  diffCommentNext: "下一条评论",
19069
19036
  diffCommentPosition: "第 {index} 条,共 {total} 条",
@@ -19073,7 +19040,6 @@ window.__ModuleLoader__.load({
19073
19040
  diffCardFiles: "{count} 个文件",
19074
19041
  diffExpandAll: "展开全部文件",
19075
19042
  diffCollapseAll: "收起全部文件",
19076
- diffRestore: "还原 Diff 面板",
19077
19043
  diffCommit: "Commit",
19078
19044
  diffCommitMenu: "打开提交操作菜单",
19079
19045
  diffCommitPush: "Commit & Push…",
@@ -19186,6 +19152,7 @@ window.__ModuleLoader__.load({
19186
19152
  cleanupTitle: "清理已合并分支",
19187
19153
  cleanupDescription: "删除 worktree 与本地分支,并归档对应 workspace 的会话后移除 workspace;普通 checkout 则切回 base 分支并删除已合并分支。",
19188
19154
  cleanupCompleted: "已清理 {branch}",
19155
+ cleanupDescriptionUnmerged: "这个 worktree 没有对应的 PR。删除 worktree 与本地分支,并归档对应 workspace 的会话后移除 workspace;分支上有任何未推送到远端的提交时会拒绝。",
19189
19156
  overviewOpen: "打开 Claude 会话看板",
19190
19157
  overviewTitle: "会话看板",
19191
19158
  overviewBody: "所有 Claude 会话的运行状态、分支与 PR",
@@ -19465,8 +19432,6 @@ window.__ModuleLoader__.load({
19465
19432
  planPanelTitle: "Plan",
19466
19433
  planClose: "Close plan panel",
19467
19434
  planOpen: "View plan",
19468
- planMaximize: "Maximize plan panel",
19469
- planRestore: "Restore plan panel",
19470
19435
  planNth: "{index} / {total}",
19471
19436
  planHistory: "Plans in this session",
19472
19437
  planNotePlaceholder: "What should change? Enter files a note, ⌘/Ctrl+Enter sends",
@@ -19501,12 +19466,12 @@ window.__ModuleLoader__.load({
19501
19466
  presetHeaderHint: "The agent preset this session runs",
19502
19467
  diffRepository: "Repository",
19503
19468
  repositoryLinked: "Linked repository: changed by this session",
19469
+ linkedRepositoryPrompt: "The following concerns the linked repository at {root} (branch {branch}), not this session's own checkout.",
19504
19470
  diffFiles: "{count} modified file(s)",
19505
19471
  diffFilesShort: "{count} files",
19506
19472
  diffTruncated: "The diff exceeds the safe display limit. Use the terminal to inspect the complete content.",
19507
19473
  diffEmpty: "No tracked file changes to display",
19508
19474
  diffElided: "Skipped {count} oversized file(s): {files}",
19509
- diffMaximize: "Maximize diff panel",
19510
19475
  diffCommentPrevious: "Previous comment",
19511
19476
  diffCommentNext: "Next comment",
19512
19477
  diffCommentPosition: "Comment {index} of {total}",
@@ -19516,7 +19481,6 @@ window.__ModuleLoader__.load({
19516
19481
  diffCardFiles: "{count} files",
19517
19482
  diffExpandAll: "Expand all files",
19518
19483
  diffCollapseAll: "Collapse all files",
19519
- diffRestore: "Restore diff panel",
19520
19484
  diffCommit: "Commit",
19521
19485
  diffCommitMenu: "Open commit actions",
19522
19486
  diffCommitPush: "Commit & Push…",
@@ -19629,6 +19593,7 @@ window.__ModuleLoader__.load({
19629
19593
  cleanupTitle: "Clean up merged branch",
19630
19594
  cleanupDescription: "Remove the worktree and local branch, then archive the workspace sessions and delete the workspace; a plain checkout switches back to the base branch and deletes the merged branch.",
19631
19595
  cleanupCompleted: "Cleaned up {branch}",
19596
+ cleanupDescriptionUnmerged: "This worktree has no pull request. Remove the worktree and local branch, then archive the workspace sessions and delete the workspace; refused while the branch holds commits that are on no remote.",
19632
19597
  overviewOpen: "Open the Claude session board",
19633
19598
  overviewTitle: "Session board",
19634
19599
  overviewBody: "Run state, branch, and pull request across Claude sessions",