@norman-else/dsh-claude 0.1.36 → 0.1.38

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
@@ -3630,7 +3630,7 @@ window.__ModuleLoader__.load({
3630
3630
  `body[data-ds-dark-theme] .${CLAUDE_MARKDOWN_SCOPE}{`,
3631
3631
  palette(PIERRE_DARK, "#1a1a19", "#1a1a19", INLINE_FILL_DARK),
3632
3632
  "}",
3633
- `.${CLAUDE_MARKDOWN_SCOPE} :not(pre)>code{color:${CLAY_EMPHASIZED};border-radius:4px;padding:1px 2px}`,
3633
+ `.${CLAUDE_MARKDOWN_SCOPE} :not(pre)>code{color:${CLAY_EMPHASIZED};border-radius:4px;padding:1px 2px;font-size:1.05em!important}`,
3634
3634
  `body[data-ds-dark-theme] .${CLAUDE_MARKDOWN_SCOPE} :not(pre)>code{color:${CLAY}}`,
3635
3635
  `.${CLAUDE_MARKDOWN_SCOPE} [class*="bannerWrap"]{position:absolute;top:0;right:0;z-index:7;background:transparent;border-radius:0}`,
3636
3636
  `.${CLAUDE_MARKDOWN_SCOPE} [class*="banner"]:not([class*="bannerWrap"]){background:transparent;padding:6px 8px}`,
@@ -4578,6 +4578,7 @@ window.__ModuleLoader__.load({
4578
4578
  ".dsh-claude-transcript-text{color:var(--dsw-alias-label-primary);font-size:15px;line-height:24px;overflow-wrap:anywhere}",
4579
4579
  ".dsh-claude-tool-group-native{overflow:visible}",
4580
4580
  ".dsh-claude-tool-group-native>.dsh-claude-flow-row{padding:0}",
4581
+ ".dsh-claude-flow-row .dsh-claude-tool-stats{margin-left:8px}",
4581
4582
  ".dsh-claude-tool-list{max-height:min(420px,calc(100vh - 320px));overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;margin-top:4px;border:1px solid var(--dsw-alias-border-l1, color-mix(in srgb, currentColor 12%, transparent));border-radius:10px;scrollbar-gutter:stable}",
4582
4583
  ".dsh-claude-tool-item{border-top:1px solid var(--dsw-alias-border-l1, color-mix(in srgb, currentColor 12%, transparent))}",
4583
4584
  ".dsh-claude-tool-item:first-child{border-top:0}",
@@ -4816,13 +4817,36 @@ window.__ModuleLoader__.load({
4816
4817
  if (!Array.isArray(value)) return [];
4817
4818
  return value.filter((item) => typeof item === "string");
4818
4819
  }
4820
+ /** The diff card's chrome, which primitives 0.1.2 moved onto the caller.
4821
+ *
4822
+ * The card reads `labels.copy` while it builds, so omitting them throws
4823
+ * mid-render -- and React answers by tearing down the whole conversation, not
4824
+ * the one tool row.
4825
+ *
4826
+ * The aria strings deliberately repeat the visible ones: both already say
4827
+ * exactly what the control does. */
4828
+ function diffBlockLabels(t) {
4829
+ const expand = (hidden) => t("diffCardExpand", { count: hidden });
4830
+ return {
4831
+ copy: t("markdownCopy"),
4832
+ copied: t("markdownCopied"),
4833
+ collapse: t("diffCardCollapse"),
4834
+ collapseAria: t("diffCardCollapse"),
4835
+ expand,
4836
+ expandAria: expand,
4837
+ files: (count) => t("diffCardFiles", { count })
4838
+ };
4839
+ }
4819
4840
  function ToolPresentation({ tool, t }) {
4820
4841
  const inputValue = parsedValue(tool.input);
4821
4842
  const outputValue = parsedValue(tool.output);
4822
4843
  const input = record$6(inputValue);
4823
4844
  const output = record$6(outputValue);
4824
4845
  const outputTitle = tool.isError === true ? t("toolError") : t("toolOutput");
4825
- if (tool.diffs !== void 0) return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DiffBlock, { diffs: [...tool.diffs] }), /* @__PURE__ */ jsx(TextDetail, {
4846
+ if (tool.diffs !== void 0) return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DiffBlock, {
4847
+ diffs: [...tool.diffs],
4848
+ labels: diffBlockLabels(t)
4849
+ }), /* @__PURE__ */ jsx(TextDetail, {
4826
4850
  title: outputTitle,
4827
4851
  value: typeof outputValue === "string" ? outputValue : void 0
4828
4852
  })] });
@@ -6555,10 +6579,14 @@ window.__ModuleLoader__.load({
6555
6579
  const HOST_STAGES = /* @__PURE__ */ new Set([
6556
6580
  "inspecting",
6557
6581
  "fetching",
6582
+ "summarizing",
6558
6583
  "creating-worktree",
6559
6584
  "saving-worktree",
6560
6585
  "switching-branch"
6561
6586
  ]);
6587
+ /** The draft only has to describe the work; the host truncates it again before
6588
+ * summarizing, and the setup route caps the whole body at 16 KiB. */
6589
+ const MAX_INTENT_CHARS = 2e3;
6562
6590
  function record$3(value) {
6563
6591
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
6564
6592
  }
@@ -6594,7 +6622,7 @@ window.__ModuleLoader__.load({
6594
6622
  throw error;
6595
6623
  }
6596
6624
  }
6597
- async function prepareRepository(cwd, branch, worktree, branchName, onProgress = () => {}) {
6625
+ async function prepareRepository(cwd, branch, worktree, branchName, onProgress = () => {}, intent) {
6598
6626
  const carrier = new AbortController();
6599
6627
  try {
6600
6628
  const reader = await pluginNdjson(CLAUDE_REPOSITORY_SETUP_PATH, carrier.signal, {
@@ -6603,7 +6631,8 @@ window.__ModuleLoader__.load({
6603
6631
  cwd,
6604
6632
  branch,
6605
6633
  worktree,
6606
- ...branchName === void 0 ? {} : { branchName }
6634
+ ...branchName === void 0 ? {} : { branchName },
6635
+ ...intent === void 0 || intent.trim().length === 0 ? {} : { intent: intent.slice(0, MAX_INTENT_CHARS) }
6607
6636
  }
6608
6637
  });
6609
6638
  const decoder = new TextDecoder();
@@ -6645,6 +6674,12 @@ window.__ModuleLoader__.load({
6645
6674
  if (body.mode !== "worktree" && body.mode !== "checkout" || typeof body.root !== "string" || typeof body.branch !== "string") throw new Error("Invalid repository cleanup response.");
6646
6675
  return body;
6647
6676
  }
6677
+ /** Ask the Host to reconcile worktrees against the workspace registry now.
6678
+ * Deleting a workspace only touches the registry, so this kick is what makes
6679
+ * the worktree and its sessions go without waiting out the sweep interval. */
6680
+ async function sweepWorktrees() {
6681
+ await pluginWrite(`${CLAUDE_REPOSITORY_SETUP_PATH}/sweep`, "fast");
6682
+ }
6648
6683
  /** Lines [from, to] of a working-tree file plus its total line count, for expanding unmodified diff context. */
6649
6684
  async function loadRepositoryFileLines(cwd, path, from, to, signal) {
6650
6685
  const body = await pluginRead(CLAUDE_REPOSITORY_FILE_PATH, "git", signal, { query: {
@@ -6892,10 +6927,40 @@ window.__ModuleLoader__.load({
6892
6927
  const CLAUDE_SCOPED_CSS_VARIABLES = ["--dsh-composer-card-max-width"];
6893
6928
  /** Marks the bar the scoped-property probe measures. */
6894
6929
  const CLAUDE_COMPOSER_BAR_ATTRIBUTE = "data-dsh-claude-composer-bar";
6895
- /** One line per service the Host no longer provides; empty when all resolve. */
6896
- function claudeBootCheckFindings(input) {
6930
+ /** Methods this plugin calls on the Host services it injects.
6931
+ *
6932
+ * A service that still resolves but has lost a method is the drift the
6933
+ * service list above cannot see: Desktop 0.1.2 moved `connectWorkspace` off
6934
+ * `workspaces` onto a new service, and the worktree flow went on registering
6935
+ * itself and only broke once a user ran it. Naming the methods here turns
6936
+ * that into a boot-time line. Methods with a runtime fallback stay out. */
6937
+ const CLAUDE_REQUIRED_SERVICE_METHODS = {
6938
+ sessions: [
6939
+ "scope",
6940
+ "open",
6941
+ "binding"
6942
+ ],
6943
+ workspaces: [
6944
+ "create",
6945
+ "delete",
6946
+ "archiveSession"
6947
+ ],
6948
+ uiConversation: ["binding"],
6949
+ uiSession: ["provide"],
6950
+ inputTriggers: ["registerSource"]
6951
+ };
6952
+ /** One line per service the Host no longer provides, or provides without a
6953
+ * method this plugin calls on it; empty when everything resolves. */
6954
+ function claudeBootCheckFindings(input, methods = CLAUDE_REQUIRED_SERVICE_METHODS) {
6897
6955
  const findings = [];
6898
- for (const name of input.services) if (input.resolve(name) === void 0) findings.push(`service "${name}" is declared in inject but the Host does not provide it`);
6956
+ for (const name of input.services) {
6957
+ const service = input.resolve(name);
6958
+ if (service === void 0) {
6959
+ findings.push(`service "${name}" is declared in inject but the Host does not provide it`);
6960
+ continue;
6961
+ }
6962
+ for (const method of methods[name] ?? []) if (typeof service[method] !== "function") findings.push(`service "${name}" no longer provides ${method}(); the features calling it are broken`);
6963
+ }
6899
6964
  return findings;
6900
6965
  }
6901
6966
  /** One line per scoped custom property the measured element cannot see.
@@ -7339,6 +7404,14 @@ window.__ModuleLoader__.load({
7339
7404
  }) : null]
7340
7405
  });
7341
7406
  }
7407
+ /** The trigger only shows on a clean branch that is behind its base -- but a
7408
+ * conflicted rebase leaves the tree dirty on a detached HEAD, so an open
7409
+ * dialog (and its resolve button) has to outlive that. */
7410
+ function updateBranchMounted(repository, dialogOpen) {
7411
+ const pullRequest = repository.pullRequest;
7412
+ if (pullRequest?.baseBranch === void 0) return false;
7413
+ return dialogOpen || pullRequest.state === "open" && repository.detached !== true && repository.dirty !== true && (repository.baseBehind ?? 0) > 0;
7414
+ }
7342
7415
  function UpdateBranchControl({ sessionId, repository, t, report, submitPrompt }) {
7343
7416
  const [dialog, setDialog] = useState();
7344
7417
  const [method, setMethod] = useState("rebase");
@@ -7347,7 +7420,8 @@ window.__ModuleLoader__.load({
7347
7420
  const base = pullRequest?.baseBranch;
7348
7421
  const behind = repository.baseBehind ?? 0;
7349
7422
  useEffect(() => () => controller.current?.abort(), []);
7350
- if (pullRequest === void 0 || pullRequest.state !== "open" || base === void 0 || repository.detached === true || repository.dirty === true || behind <= 0) return null;
7423
+ if (pullRequest === void 0 || base === void 0) return null;
7424
+ if (!updateBranchMounted(repository, dialog !== void 0)) return null;
7351
7425
  const openDialog = () => {
7352
7426
  controller.current?.abort();
7353
7427
  setDialog({
@@ -7828,9 +7902,15 @@ window.__ModuleLoader__.load({
7828
7902
  style: repositoryRemote,
7829
7903
  children: repositoryName$1(repository.remote)
7830
7904
  }),
7831
- /* @__PURE__ */ jsx("span", {
7832
- style: repositoryBranch,
7833
- children: branch
7905
+ /* @__PURE__ */ jsx(Tooltip, {
7906
+ label: branch,
7907
+ side: "top",
7908
+ delayMs: 250,
7909
+ maxWidth: 420,
7910
+ children: /* @__PURE__ */ jsx("span", {
7911
+ style: repositoryBranch,
7912
+ children: branch
7913
+ })
7834
7914
  }),
7835
7915
  repository.worktree === true ? /* @__PURE__ */ jsx("span", {
7836
7916
  style: repositoryWorktree,
@@ -8022,7 +8102,9 @@ window.__ModuleLoader__.load({
8022
8102
  children: comment.text
8023
8103
  })]
8024
8104
  }),
8025
- openDelayMs: 250
8105
+ openDelayMs: 250,
8106
+ copyLabel: t("markdownCopy"),
8107
+ copiedLabel: t("markdownCopied")
8026
8108
  });
8027
8109
  }
8028
8110
  /** Pending review comments docked above the composer; drained by the next user turn. */
@@ -14091,7 +14173,7 @@ window.__ModuleLoader__.load({
14091
14173
  * @returns the preset id, or undefined when neither source carries one.
14092
14174
  */
14093
14175
  function sessionRowPreset(row) {
14094
- return row?.agentPreset ?? row?.projectionValues?.agentPreset;
14176
+ return row?.agentPreset ?? row?.projectionValues?.agentPreset ?? void 0;
14095
14177
  }
14096
14178
  //#endregion
14097
14179
  //#region src/client/ClaudePullRequestsPanel.tsx
@@ -15271,13 +15353,37 @@ window.__ModuleLoader__.load({
15271
15353
  function directChildContaining(parent, descendant) {
15272
15354
  return Array.from(parent.children).find((child) => child === descendant || child.contains(descendant));
15273
15355
  }
15274
- /** Locate rc.8's hero preset seat without relying on hashed CSS module names. */
15275
- function locateClaudePresetSeat(root = document) {
15356
+ /** The hero's preset buttons: menu buttons without an `aria-label`, which is
15357
+ * what separates the preset seat from the labelled workspace picker. The
15358
+ * portal's own branch trigger answers that description too, so it is excluded
15359
+ * -- counting it made the row look like it held two staged presets from the
15360
+ * moment these controls mounted. */
15361
+ function heroPresetButtons(root) {
15276
15362
  const heroes = Array.from(root.querySelectorAll(HERO_SELECTOR));
15277
15363
  if (heroes.length !== 1) return void 0;
15278
15364
  const hero = heroes[0];
15279
15365
  if (hero === void 0) return void 0;
15280
- const presetButtons = Array.from(hero.querySelectorAll("button[aria-haspopup=\"menu\"]")).filter((button) => button.getAttribute("aria-label") === null && isClaudePresetText(normalizedText(button)));
15366
+ return {
15367
+ hero,
15368
+ presets: Array.from(hero.querySelectorAll("button[aria-haspopup=\"menu\"]")).filter((button) => button.getAttribute("aria-label") === null && button.closest(`[${PORTAL_ATTRIBUTE}]`) === null)
15369
+ };
15370
+ }
15371
+ /** True once the hero has settled on a preset that is not Claude.
15372
+ * `locateClaudePresetSeat` reports that the same way it reports a hero
15373
+ * mid-render -- by missing -- so without this the retention rule below reads a
15374
+ * deliberate switch away from Claude as a re-render and leaves the controls up. */
15375
+ function showsOtherPresetSeat(root = document) {
15376
+ const found = heroPresetButtons(root);
15377
+ if (found === void 0 || found.presets.length !== 1) return false;
15378
+ const preset = found.presets[0];
15379
+ return preset !== void 0 && !isClaudePresetText(normalizedText(preset));
15380
+ }
15381
+ /** Locate rc.8's hero preset seat without relying on hashed CSS module names. */
15382
+ function locateClaudePresetSeat(root = document) {
15383
+ const found = heroPresetButtons(root);
15384
+ if (found === void 0) return void 0;
15385
+ const { hero } = found;
15386
+ const presetButtons = found.presets.filter((button) => isClaudePresetText(normalizedText(button)));
15281
15387
  if (presetButtons.length !== 1) return void 0;
15282
15388
  const preset = presetButtons[0];
15283
15389
  if (preset === void 0) return void 0;
@@ -15322,10 +15428,15 @@ window.__ModuleLoader__.load({
15322
15428
  }
15323
15429
  //#endregion
15324
15430
  //#region src/client/ClaudeHeroRepositoryControls.tsx
15431
+ /** The host composer was a textarea through rc.8 and is a Lexical
15432
+ * contenteditable from 0.1.2 on, so match the composer seat rather than the
15433
+ * element type: an element-type check silently stops intercepting Enter, and
15434
+ * the capsule's branch and Worktree choices go nowhere. */
15325
15435
  function shouldInterceptKey(event) {
15326
15436
  if (event.key !== "Enter" || event.shiftKey || event.repeat || event.isComposing) return false;
15327
15437
  const target = event.target;
15328
- return target instanceof HTMLTextAreaElement && target.closest("[data-phase=\"hero\"]") !== null;
15438
+ if (!(target instanceof Element)) return false;
15439
+ return target.closest("textarea, [data-composer-input]") !== null && target.closest("[data-phase=\"hero\"]") !== null;
15329
15440
  }
15330
15441
  function shouldInterceptClick(event) {
15331
15442
  const target = event.target;
@@ -15361,6 +15472,7 @@ window.__ModuleLoader__.load({
15361
15472
  const WORKTREE_PROGRESS_STAGES = [
15362
15473
  "inspecting",
15363
15474
  "fetching",
15475
+ "summarizing",
15364
15476
  "creating-worktree",
15365
15477
  "saving-worktree",
15366
15478
  "creating-workspace",
@@ -15371,6 +15483,7 @@ window.__ModuleLoader__.load({
15371
15483
  const PROGRESS_LABEL_KEYS = {
15372
15484
  inspecting: "repositoryProgress_inspecting",
15373
15485
  fetching: "repositoryProgress_fetching",
15486
+ summarizing: "repositoryProgress_summarizing",
15374
15487
  "creating-worktree": "repositoryProgress_creating-worktree",
15375
15488
  "saving-worktree": "repositoryProgress_saving-worktree",
15376
15489
  "switching-branch": "repositoryProgress_switching-branch",
@@ -15729,7 +15842,7 @@ window.__ModuleLoader__.load({
15729
15842
  scheduled = false;
15730
15843
  const target = locateClaudePresetSeat();
15731
15844
  if (target === void 0) {
15732
- if (retainsClaudeHeroPortal(current)) return;
15845
+ if (retainsClaudeHeroPortal(current) && !showsOtherPresetSeat()) return;
15733
15846
  current = void 0;
15734
15847
  removeClaudeHeroPortals();
15735
15848
  setPortal(void 0);
@@ -17050,6 +17163,7 @@ window.__ModuleLoader__.load({
17050
17163
  repositoryProgressDismiss: "关闭 Worktree 进度",
17051
17164
  repositoryProgress_inspecting: "检查仓库和分支",
17052
17165
  repositoryProgress_fetching: "刷新远程引用",
17166
+ repositoryProgress_summarizing: "总结需求生成分支名",
17053
17167
  "repositoryProgress_creating-worktree": "创建分支和 Worktree",
17054
17168
  "repositoryProgress_saving-worktree": "保存 Worktree 状态",
17055
17169
  "repositoryProgress_switching-branch": "切换本地分支",
@@ -17107,6 +17221,9 @@ window.__ModuleLoader__.load({
17107
17221
  diffCommentNext: "下一条评论",
17108
17222
  diffCommentPosition: "第 {index} 条,共 {total} 条",
17109
17223
  diffCommentCounter: "{index}/{total}",
17224
+ diffCardExpand: "展开其余 {count} 行",
17225
+ diffCardCollapse: "收起",
17226
+ diffCardFiles: "{count} 个文件",
17110
17227
  diffExpandAll: "展开全部文件",
17111
17228
  diffCollapseAll: "收起全部文件",
17112
17229
  diffRestore: "还原 Diff 面板",
@@ -17423,6 +17540,7 @@ window.__ModuleLoader__.load({
17423
17540
  repositoryProgressDismiss: "Dismiss Worktree progress",
17424
17541
  repositoryProgress_inspecting: "Checking repository and branch",
17425
17542
  repositoryProgress_fetching: "Refreshing remote references",
17543
+ repositoryProgress_summarizing: "Naming the branch after the request",
17426
17544
  "repositoryProgress_creating-worktree": "Creating branch and Worktree",
17427
17545
  "repositoryProgress_saving-worktree": "Saving Worktree state",
17428
17546
  "repositoryProgress_switching-branch": "Switching local branch",
@@ -17480,6 +17598,9 @@ window.__ModuleLoader__.load({
17480
17598
  diffCommentNext: "Next comment",
17481
17599
  diffCommentPosition: "Comment {index} of {total}",
17482
17600
  diffCommentCounter: "{index}/{total}",
17601
+ diffCardExpand: "Show {count} more lines",
17602
+ diffCardCollapse: "Show less",
17603
+ diffCardFiles: "{count} files",
17483
17604
  diffExpandAll: "Expand all files",
17484
17605
  diffCollapseAll: "Collapse all files",
17485
17606
  diffRestore: "Restore diff panel",
@@ -17680,6 +17801,17 @@ window.__ModuleLoader__.load({
17680
17801
  "conversation",
17681
17802
  "connection"
17682
17803
  ];
17804
+ /** Resolve one session's composer facade.
17805
+ *
17806
+ * `sessions.scope()` returns the client runtime's AgentContext, and the
17807
+ * conversation package -- a release ahead of the runtime in the graph the Host
17808
+ * itself ships -- types `input.for` against a Context whose `remote` has since
17809
+ * gained `$stream` and `$host`. It is the same object at runtime; only the two
17810
+ * declarations disagree, and they disagree inside the Host too, so the cast
17811
+ * lives here once instead of at all nine call sites. */
17812
+ function sessionInput(conversation, scope) {
17813
+ return conversation.input.for(scope);
17814
+ }
17683
17815
  function apply(ctx) {
17684
17816
  const namespace = "settings.claude-code";
17685
17817
  const diagnostics = createClaudeDiagnosticsReporter();
@@ -17705,6 +17837,17 @@ window.__ModuleLoader__.load({
17705
17837
  ctx.effect(() => ctx.inputTriggers.registerSource(createClaudeCommandSource(ctx, projections)), "dsh-claude: Claude slash source");
17706
17838
  const sessions = ctx.get("sessions");
17707
17839
  const workspaces = ctx.get("workspaces");
17840
+ const uiWorkspace = ctx.get("uiWorkspace");
17841
+ const connectWorkspace = uiWorkspace?.connectWorkspace?.bind(uiWorkspace) ?? (typeof workspaces?.connectWorkspace === "function" ? workspaces.connectWorkspace.bind(workspaces) : void 0);
17842
+ if (workspaces !== void 0) ctx.effect(() => {
17843
+ let known = new Set(workspaces.list.getSnapshot().items.map((item) => item.workspaceId));
17844
+ return workspaces.list.subscribe(() => {
17845
+ const next = new Set(workspaces.list.getSnapshot().items.map((item) => item.workspaceId));
17846
+ const removed = [...known].some((id) => !next.has(id));
17847
+ known = next;
17848
+ if (removed) sweepWorktrees().catch(() => void 0);
17849
+ });
17850
+ }, "dsh-claude: worktree sweep on workspace deletion");
17708
17851
  const conversation = ctx.get("conversation");
17709
17852
  const connection = ctx.get("connection");
17710
17853
  const remote = ctx.get("remote");
@@ -17716,7 +17859,7 @@ window.__ModuleLoader__.load({
17716
17859
  return (draft, mode = "append") => {
17717
17860
  const scope = sessions.scope(sessionId);
17718
17861
  if (scope === void 0) return false;
17719
- const input = conversation.input.for(scope);
17862
+ const input = sessionInput(conversation, scope);
17720
17863
  const current = input.state.getSnapshot().draft;
17721
17864
  if (current.trim() === "") input.setDraft(draft);
17722
17865
  else if (mode === "append") input.setDraft(`${current}\n\n${draft}`);
@@ -17962,7 +18105,7 @@ window.__ModuleLoader__.load({
17962
18105
  ...sessions === void 0 || conversation === void 0 ? {} : { submitWith: (fallbackDraft) => {
17963
18106
  const scope = sessions.scope(sessionId);
17964
18107
  if (scope === void 0) return;
17965
- const input = conversation.input.for(scope);
18108
+ const input = sessionInput(conversation, scope);
17966
18109
  if (input.state.getSnapshot().draft.trim() === "") input.setDraft(fallbackDraft);
17967
18110
  input.submit();
17968
18111
  } }
@@ -18000,7 +18143,7 @@ window.__ModuleLoader__.load({
18000
18143
  ...sessions === void 0 || conversation === void 0 ? {} : { insertIntoChat: (sessionId, text) => {
18001
18144
  const scope = sessions.scope(sessionId);
18002
18145
  if (scope === void 0) return;
18003
- const input = conversation.input.for(scope);
18146
+ const input = sessionInput(conversation, scope);
18004
18147
  const current = input.state.getSnapshot().draft;
18005
18148
  input.setDraft(current.trim() === "" ? text : `${current}\n\n${text}`);
18006
18149
  } }
@@ -18062,7 +18205,7 @@ window.__ModuleLoader__.load({
18062
18205
  ...conversation === void 0 ? {} : { setDraft: (sessionId, text) => {
18063
18206
  const scope = sessions.scope(sessionId);
18064
18207
  if (scope === void 0) return;
18065
- conversation.input.for(scope).setDraft(text);
18208
+ sessionInput(conversation, scope).setDraft(text);
18066
18209
  } }
18067
18210
  };
18068
18211
  ctx.slots.inject("shell.overlay", () => ctx.slots.register({
@@ -18084,12 +18227,12 @@ window.__ModuleLoader__.load({
18084
18227
  t,
18085
18228
  updateQueue: (itemId, action) => target.updateQueue(itemId, action),
18086
18229
  notify: (level, text) => {
18087
- if (scope !== void 0) conversation.input.for(scope).notify(level, text);
18230
+ if (scope !== void 0) sessionInput(conversation, scope).notify(level, text);
18088
18231
  }
18089
18232
  };
18090
18233
  }
18091
18234
  }, ClaudeQueueDock));
18092
- if (sessions !== void 0 && workspaces !== void 0 && conversation !== void 0 && connection !== void 0 && remote !== void 0) {
18235
+ if (sessions !== void 0 && workspaces !== void 0 && connectWorkspace !== void 0 && conversation !== void 0 && connection !== void 0 && remote !== void 0) {
18093
18236
  /** Attach a prepared worktree to its session without blocking the flow. */
18094
18237
  const bindLease = (leaseId, targetSessionId) => {
18095
18238
  if (leaseId === void 0) return;
@@ -18107,11 +18250,11 @@ window.__ModuleLoader__.load({
18107
18250
  prepare: async (cwd, branch, useWorktree, onProgress, ticket) => {
18108
18251
  const sourceScope = sessions.scope(sourceSessionId);
18109
18252
  if (sourceScope === void 0) throw new Error(t("repositorySessionUnavailable"));
18110
- const sourceInput = conversation.input.for(sourceScope);
18253
+ const sourceInput = sessionInput(conversation, sourceScope);
18111
18254
  const rawDraft = sourceInput.state.getSnapshot().draft;
18112
18255
  const draft = ticket === void 0 ? rawDraft : rawDraft.trim() === "" ? ticketPrompt(ticket) : `${rawDraft.trimEnd()}\n\n${ticketContext(ticket)}`;
18113
18256
  const imageIds = sourceInput.state.getSnapshot().imageIds;
18114
- const prepared = await prepareRepository(cwd, branch, useWorktree, ticket?.key, onProgress);
18257
+ const prepared = await prepareRepository(cwd, branch, useWorktree, ticket?.key, onProgress, ticket === void 0 ? draft : void 0);
18115
18258
  if (ticket !== void 0) assignJiraTicket(ticket.key).catch((reason) => {
18116
18259
  console.warn(`dsh-claude: could not assign ${ticket.key}: ${reason instanceof Error ? reason.message : String(reason)}`);
18117
18260
  });
@@ -18123,13 +18266,13 @@ window.__ModuleLoader__.load({
18123
18266
  onProgress("creating-workspace");
18124
18267
  const workspace = await workspaces.create({ path: prepared.path });
18125
18268
  onProgress("starting-session");
18126
- const targetSessionId = await workspaces.connectWorkspace(workspace.workspaceId);
18269
+ const targetSessionId = await connectWorkspace(workspace.workspaceId);
18127
18270
  const targetScope = sessions.scope(targetSessionId);
18128
18271
  if (targetScope === void 0) throw new Error(t("repositorySessionUnavailable"));
18129
18272
  const presetResponse = await remote.agentPresets.select(targetSessionId, "claude");
18130
18273
  if (!presetResponse.ok) throw new Error(presetResponse.error.message);
18131
- sessions.noteAgentPreset(targetSessionId, presetResponse.value);
18132
- const targetInput = conversation.input.for(targetScope);
18274
+ sessions.noteAgentPreset?.(targetSessionId, presetResponse.value);
18275
+ const targetInput = sessionInput(conversation, targetScope);
18133
18276
  onProgress("transferring-draft");
18134
18277
  if (imageIds.length > 0 && !targetInput.addImages(imageIds)) throw new Error(t("repositoryDraftTransferFailed"));
18135
18278
  if (draft !== "") targetInput.setDraft(draft);
@@ -18143,7 +18286,7 @@ window.__ModuleLoader__.load({
18143
18286
  prepareMany: async (cwd, branch, tickets, onProgress) => {
18144
18287
  const sourceScope = sessions.scope(sourceSessionId);
18145
18288
  if (sourceScope === void 0) throw new Error(t("repositorySessionUnavailable"));
18146
- const sourceInput = conversation.input.for(sourceScope);
18289
+ const sourceInput = sessionInput(conversation, sourceScope);
18147
18290
  const rawDraft = sourceInput.state.getSnapshot().draft;
18148
18291
  const failures = [];
18149
18292
  for (const [index, ticket] of tickets.entries()) {
@@ -18164,13 +18307,13 @@ window.__ModuleLoader__.load({
18164
18307
  report("creating-workspace");
18165
18308
  const workspace = await workspaces.create({ path: prepared.path });
18166
18309
  report("starting-session");
18167
- const targetSessionId = await workspaces.connectWorkspace(workspace.workspaceId);
18310
+ const targetSessionId = await connectWorkspace(workspace.workspaceId);
18168
18311
  const targetScope = sessions.scope(targetSessionId);
18169
18312
  if (targetScope === void 0) throw new Error(t("repositorySessionUnavailable"));
18170
18313
  const presetResponse = await remote.agentPresets.select(targetSessionId, "claude");
18171
18314
  if (!presetResponse.ok) throw new Error(presetResponse.error.message);
18172
- sessions.noteAgentPreset(targetSessionId, presetResponse.value);
18173
- const targetInput = conversation.input.for(targetScope);
18315
+ sessions.noteAgentPreset?.(targetSessionId, presetResponse.value);
18316
+ const targetInput = sessionInput(conversation, targetScope);
18174
18317
  report("transferring-draft");
18175
18318
  targetInput.setDraft(rawDraft.trim() === "" ? ticketPrompt(ticket) : `${rawDraft.trimEnd()}\n\n${ticketContext(ticket)}`);
18176
18319
  bindLease(prepared.leaseId, targetSessionId);