@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/INSTALL.md +55 -55
- package/LICENSE +21 -21
- package/cordis.patch.yml +12 -12
- package/legacy-preset/agent.cordis.yml +11 -11
- package/legacy-preset/preset.yml +4 -4
- package/lib/bin.mjs +0 -0
- package/lib/bin.mjs.map +1 -1
- package/lib/client.d.ts +4 -0
- package/lib/client.js +176 -33
- package/lib/client.js.map +1 -1
- package/lib/index.mjs +217 -57
- package/lib/index.mjs.map +1 -1
- package/lib/presenters-BBoM1Ju1.mjs.map +1 -1
- package/lib/preset-installer-loenwnLS.mjs.map +1 -1
- package/lib/preset-route.mjs.map +1 -1
- package/package.json +195 -189
- package/preset/claude/agent.cordis.yml +11 -11
- package/preset/claude/preset.yml +4 -4
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, {
|
|
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
|
-
/**
|
|
6896
|
-
|
|
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)
|
|
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 ||
|
|
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(
|
|
7832
|
-
|
|
7833
|
-
|
|
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
|
-
/**
|
|
15275
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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);
|