@norman-else/dsh-claude 0.1.23 → 0.1.25
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/README.md +82 -82
- 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 +1 -1
- package/lib/bin.mjs.map +1 -1
- package/lib/client.d.ts +44 -0
- package/lib/client.js +1375 -187
- package/lib/client.js.map +1 -1
- package/lib/{command-bridge-Br25ODdm.mjs → command-bridge-B48egrCr.mjs} +2 -2
- package/lib/command-bridge-B48egrCr.mjs.map +1 -0
- package/lib/{events-DhrAr5gh.mjs → events-BhU0iJUi.mjs} +4 -2
- package/lib/events-BhU0iJUi.mjs.map +1 -0
- package/lib/index.mjs +501 -105
- package/lib/index.mjs.map +1 -1
- package/lib/{preset-installer-B_Cb0RG6.mjs → preset-installer-Bzw8tuGI.mjs} +2 -2
- package/lib/preset-installer-Bzw8tuGI.mjs.map +1 -0
- package/lib/preset-route.mjs +2 -2
- package/lib/preset-route.mjs.map +1 -1
- package/package.json +181 -181
- package/preset/claude/agent.cordis.yml +11 -11
- package/preset/claude/preset.yml +4 -4
- package/lib/command-bridge-Br25ODdm.mjs.map +0 -1
- package/lib/events-DhrAr5gh.mjs.map +0 -1
- package/lib/preset-installer-B_Cb0RG6.mjs.map +0 -1
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 { DiffBlock, DisclosureRow, HoverCard, IconApiOutline14, IconBranchOutline16, IconCheckOutline14, IconChevronDownOutline14, IconCloseOutline16, IconFullscreenOutline16, IconSearchOutline16, IconThinkOutline14, MarkdownText, Menu, Modal, StateDot, Tooltip } = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
7
|
+
var { DiffBlock, DisclosureRow, HoverCard, IconApiOutline14, IconBranchOutline16, IconCheckOutline14, IconCheckOutline16, IconChevronDownOutline14, IconChevronUpOutline14, IconCloseOutline16, IconEditOutline16, IconFullscreenOutline16, IconQueueOutline14, IconSearchOutline16, IconSendOutline14, IconThinkOutline14, IconTrashOutline16, MarkdownText, Menu, Modal, StateDot, Tooltip } = 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
|
|
@@ -19,6 +19,8 @@ window.__ModuleLoader__.load({
|
|
|
19
19
|
const CLAUDE_REPOSITORY_ACTION_PATH = "/plugins/dsh-claude/repository/action";
|
|
20
20
|
const CLAUDE_REVIEW_COMMENT_PATH = "/plugins/dsh-claude/review-comments";
|
|
21
21
|
const CLAUDE_REPOSITORY_FEEDBACK_PATH = "/plugins/dsh-claude/repository/feedback";
|
|
22
|
+
const CLAUDE_REPOSITORY_STATUS_PATH = "/plugins/dsh-claude/repository/status";
|
|
23
|
+
const CLAUDE_JIRA_PATH = "/plugins/dsh-claude/jira";
|
|
22
24
|
//#endregion
|
|
23
25
|
//#region src/client/task-projection.ts
|
|
24
26
|
/** Tasks UI is reserved for detached work and genuine Claude subagents. */
|
|
@@ -712,6 +714,8 @@ window.__ModuleLoader__.load({
|
|
|
712
714
|
const settingsActions = {
|
|
713
715
|
display: "flex",
|
|
714
716
|
flexWrap: "wrap",
|
|
717
|
+
alignItems: "center",
|
|
718
|
+
justifyContent: "flex-end",
|
|
715
719
|
gap: 8
|
|
716
720
|
};
|
|
717
721
|
const notice = {
|
|
@@ -1411,8 +1415,93 @@ window.__ModuleLoader__.load({
|
|
|
1411
1415
|
lineHeight: "22px",
|
|
1412
1416
|
textAlign: "left"
|
|
1413
1417
|
};
|
|
1418
|
+
const queueBar = {
|
|
1419
|
+
width: "100%",
|
|
1420
|
+
minWidth: 0,
|
|
1421
|
+
boxSizing: "border-box",
|
|
1422
|
+
display: "flex",
|
|
1423
|
+
flexDirection: "column",
|
|
1424
|
+
padding: "3px 6px 3px 11px",
|
|
1425
|
+
border: "1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 16%, transparent))",
|
|
1426
|
+
borderRadius: 11,
|
|
1427
|
+
background: "var(--dsw-alias-bg-layer-1)",
|
|
1428
|
+
color: "var(--dsw-alias-label-primary)",
|
|
1429
|
+
boxShadow: "0 1px 2px color-mix(in srgb, var(--dsw-alias-label-primary) 4%, transparent)",
|
|
1430
|
+
font: "inherit",
|
|
1431
|
+
fontSize: 13,
|
|
1432
|
+
lineHeight: "20px"
|
|
1433
|
+
};
|
|
1434
|
+
const queueHeader = {
|
|
1435
|
+
width: "100%",
|
|
1436
|
+
minHeight: 30,
|
|
1437
|
+
display: "flex",
|
|
1438
|
+
alignItems: "center",
|
|
1439
|
+
gap: 8,
|
|
1440
|
+
padding: "2px 0",
|
|
1441
|
+
border: "none",
|
|
1442
|
+
outline: "none",
|
|
1443
|
+
background: "transparent",
|
|
1444
|
+
color: "inherit",
|
|
1445
|
+
font: "inherit",
|
|
1446
|
+
fontSize: 13,
|
|
1447
|
+
textAlign: "left",
|
|
1448
|
+
cursor: "pointer"
|
|
1449
|
+
};
|
|
1450
|
+
const queueLead = {
|
|
1451
|
+
flex: "none",
|
|
1452
|
+
display: "grid",
|
|
1453
|
+
placeItems: "center",
|
|
1454
|
+
color: "var(--dsw-alias-label-tertiary)"
|
|
1455
|
+
};
|
|
1456
|
+
const queueCount = {
|
|
1457
|
+
minWidth: 0,
|
|
1458
|
+
flex: 1,
|
|
1459
|
+
fontWeight: 550
|
|
1460
|
+
};
|
|
1461
|
+
const queueList = {
|
|
1462
|
+
maxHeight: 180,
|
|
1463
|
+
margin: 0,
|
|
1464
|
+
padding: 0,
|
|
1465
|
+
listStyle: "none",
|
|
1466
|
+
overflowY: "auto"
|
|
1467
|
+
};
|
|
1468
|
+
const queueRow = {
|
|
1469
|
+
minHeight: 30,
|
|
1470
|
+
display: "flex",
|
|
1471
|
+
alignItems: "center",
|
|
1472
|
+
gap: 8
|
|
1473
|
+
};
|
|
1474
|
+
const queueRowDivider = { borderTop: "1px solid var(--dsw-alias-border-l1, color-mix(in srgb, currentColor 12%, transparent))" };
|
|
1475
|
+
const queuePreview = {
|
|
1476
|
+
minWidth: 0,
|
|
1477
|
+
flex: 1,
|
|
1478
|
+
overflow: "hidden",
|
|
1479
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
1480
|
+
textOverflow: "ellipsis",
|
|
1481
|
+
whiteSpace: "nowrap"
|
|
1482
|
+
};
|
|
1483
|
+
const queueEditor = {
|
|
1484
|
+
minWidth: 0,
|
|
1485
|
+
flex: 1,
|
|
1486
|
+
height: 26,
|
|
1487
|
+
boxSizing: "border-box",
|
|
1488
|
+
padding: "0 8px",
|
|
1489
|
+
border: "1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 16%, transparent))",
|
|
1490
|
+
borderRadius: 6,
|
|
1491
|
+
outline: "none",
|
|
1492
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
1493
|
+
color: "var(--dsw-alias-label-primary)",
|
|
1494
|
+
font: "inherit",
|
|
1495
|
+
fontSize: 13
|
|
1496
|
+
};
|
|
1497
|
+
const queueActions = {
|
|
1498
|
+
flex: "none",
|
|
1499
|
+
display: "inline-flex",
|
|
1500
|
+
alignItems: "center",
|
|
1501
|
+
gap: 2
|
|
1502
|
+
};
|
|
1414
1503
|
const repositoryBarMerged = {
|
|
1415
|
-
borderColor: "color-mix(in srgb, #a78bfa
|
|
1504
|
+
borderColor: "color-mix(in srgb, #a78bfa 35%, transparent)",
|
|
1416
1505
|
background: "color-mix(in srgb, #a78bfa 5%, var(--dsw-alias-bg-layer-1))"
|
|
1417
1506
|
};
|
|
1418
1507
|
const repositoryPrIcon = {
|
|
@@ -1820,6 +1909,105 @@ window.__ModuleLoader__.load({
|
|
|
1820
1909
|
fontWeight: 650,
|
|
1821
1910
|
cursor: "pointer"
|
|
1822
1911
|
};
|
|
1912
|
+
const heroTicketKey = {
|
|
1913
|
+
flex: "none",
|
|
1914
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1915
|
+
fontSize: 11,
|
|
1916
|
+
fontWeight: 650,
|
|
1917
|
+
letterSpacing: .2
|
|
1918
|
+
};
|
|
1919
|
+
const heroTicketStatus = {
|
|
1920
|
+
flex: "none",
|
|
1921
|
+
maxWidth: 90,
|
|
1922
|
+
overflow: "hidden",
|
|
1923
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1924
|
+
fontSize: 11,
|
|
1925
|
+
textOverflow: "ellipsis",
|
|
1926
|
+
whiteSpace: "nowrap"
|
|
1927
|
+
};
|
|
1928
|
+
const settingsLink = {
|
|
1929
|
+
color: "var(--dsw-static-blue-450)",
|
|
1930
|
+
fontSize: 12,
|
|
1931
|
+
textDecoration: "none",
|
|
1932
|
+
marginRight: "auto"
|
|
1933
|
+
};
|
|
1934
|
+
const repositoryPrIconButton = {
|
|
1935
|
+
padding: 0,
|
|
1936
|
+
border: "none",
|
|
1937
|
+
outline: "none",
|
|
1938
|
+
background: "transparent",
|
|
1939
|
+
font: "inherit",
|
|
1940
|
+
cursor: "pointer"
|
|
1941
|
+
};
|
|
1942
|
+
const overviewBody = {
|
|
1943
|
+
flex: 1,
|
|
1944
|
+
minHeight: 0,
|
|
1945
|
+
display: "flex",
|
|
1946
|
+
flexDirection: "column",
|
|
1947
|
+
gap: 6,
|
|
1948
|
+
padding: 10,
|
|
1949
|
+
overflowY: "auto"
|
|
1950
|
+
};
|
|
1951
|
+
const overviewRow = {
|
|
1952
|
+
width: "100%",
|
|
1953
|
+
minWidth: 0,
|
|
1954
|
+
boxSizing: "border-box",
|
|
1955
|
+
display: "flex",
|
|
1956
|
+
flexDirection: "column",
|
|
1957
|
+
gap: 4,
|
|
1958
|
+
padding: "8px 10px",
|
|
1959
|
+
border: "1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 16%, transparent))",
|
|
1960
|
+
borderRadius: 10,
|
|
1961
|
+
outline: "none",
|
|
1962
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
1963
|
+
color: "var(--dsw-alias-label-primary)",
|
|
1964
|
+
font: "inherit",
|
|
1965
|
+
textAlign: "left",
|
|
1966
|
+
cursor: "pointer"
|
|
1967
|
+
};
|
|
1968
|
+
const overviewRowTop = {
|
|
1969
|
+
display: "flex",
|
|
1970
|
+
alignItems: "center",
|
|
1971
|
+
gap: 8,
|
|
1972
|
+
minWidth: 0
|
|
1973
|
+
};
|
|
1974
|
+
const overviewTitle = {
|
|
1975
|
+
minWidth: 0,
|
|
1976
|
+
flex: 1,
|
|
1977
|
+
overflow: "hidden",
|
|
1978
|
+
fontSize: 13,
|
|
1979
|
+
fontWeight: 600,
|
|
1980
|
+
textOverflow: "ellipsis",
|
|
1981
|
+
whiteSpace: "nowrap"
|
|
1982
|
+
};
|
|
1983
|
+
const overviewMeta = {
|
|
1984
|
+
display: "flex",
|
|
1985
|
+
alignItems: "center",
|
|
1986
|
+
gap: 8,
|
|
1987
|
+
minWidth: 0,
|
|
1988
|
+
overflow: "hidden",
|
|
1989
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1990
|
+
fontSize: 12,
|
|
1991
|
+
whiteSpace: "nowrap"
|
|
1992
|
+
};
|
|
1993
|
+
const overviewBranch = {
|
|
1994
|
+
minWidth: 0,
|
|
1995
|
+
overflow: "hidden",
|
|
1996
|
+
textOverflow: "ellipsis"
|
|
1997
|
+
};
|
|
1998
|
+
const overviewRunningDot = {
|
|
1999
|
+
width: 7,
|
|
2000
|
+
height: 7,
|
|
2001
|
+
flex: "none",
|
|
2002
|
+
borderRadius: 999,
|
|
2003
|
+
background: "var(--dsw-static-blue-450)"
|
|
2004
|
+
};
|
|
2005
|
+
const overviewEmpty = {
|
|
2006
|
+
padding: 16,
|
|
2007
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
2008
|
+
fontSize: 13,
|
|
2009
|
+
textAlign: "center"
|
|
2010
|
+
};
|
|
1823
2011
|
const repositoryMergeTrigger = {
|
|
1824
2012
|
flex: "none",
|
|
1825
2013
|
display: "inline-flex",
|
|
@@ -2830,7 +3018,7 @@ window.__ModuleLoader__.load({
|
|
|
2830
3018
|
const MAX_REVIEW_COMMENTS = 50;
|
|
2831
3019
|
const MAX_REVIEW_COMMENT_CHARS = 2e3;
|
|
2832
3020
|
const MAX_TRANSCRIPT_CHARS = 64e3;
|
|
2833
|
-
function record$
|
|
3021
|
+
function record$6(value) {
|
|
2834
3022
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
2835
3023
|
}
|
|
2836
3024
|
function nonNegativeInteger(value) {
|
|
@@ -2840,18 +3028,18 @@ window.__ModuleLoader__.load({
|
|
|
2840
3028
|
return value === void 0 || typeof value === "string" && value.length <= MAX_REPOSITORY_TEXT_CHARS;
|
|
2841
3029
|
}
|
|
2842
3030
|
function validateRepository(value) {
|
|
2843
|
-
const repository = record$
|
|
3031
|
+
const repository = record$6(value);
|
|
2844
3032
|
if (repository === void 0 || ![
|
|
2845
3033
|
"ready",
|
|
2846
3034
|
"not-repository",
|
|
2847
3035
|
"unavailable"
|
|
2848
3036
|
].includes(String(repository.status)) || typeof repository.cwd !== "string" || repository.cwd.length > MAX_REPOSITORY_TEXT_CHARS || !optionalBoundedString(repository.root) || !optionalBoundedString(repository.branch) || !optionalBoundedString(repository.remote) || repository.detached !== void 0 && typeof repository.detached !== "boolean" || repository.worktree !== void 0 && typeof repository.worktree !== "boolean" || repository.dirty !== void 0 && typeof repository.dirty !== "boolean" || repository.upstream !== void 0 && typeof repository.upstream !== "boolean" || repository.ahead !== void 0 && !nonNegativeInteger(repository.ahead) || repository.behind !== void 0 && !nonNegativeInteger(repository.behind)) return false;
|
|
2849
3037
|
if (repository.diff !== void 0) {
|
|
2850
|
-
const diff = record$
|
|
3038
|
+
const diff = record$6(repository.diff);
|
|
2851
3039
|
if (diff === void 0 || !nonNegativeInteger(diff.additions) || !nonNegativeInteger(diff.deletions) || !nonNegativeInteger(diff.files) || typeof diff.truncated !== "boolean" || diff.patch !== void 0 && (typeof diff.patch !== "string" || diff.patch.length > MAX_DIFF_CHARS)) return false;
|
|
2852
3040
|
}
|
|
2853
3041
|
if (repository.pullRequest === void 0) return true;
|
|
2854
|
-
const pullRequest = record$
|
|
3042
|
+
const pullRequest = record$6(repository.pullRequest);
|
|
2855
3043
|
if (pullRequest === void 0 || !Number.isSafeInteger(pullRequest.number) || Number(pullRequest.number) <= 0 || typeof pullRequest.title !== "string" || pullRequest.title.length > MAX_REPOSITORY_TEXT_CHARS || typeof pullRequest.url !== "string" || pullRequest.url.length > MAX_REPOSITORY_TEXT_CHARS || ![
|
|
2856
3044
|
"open",
|
|
2857
3045
|
"closed",
|
|
@@ -2876,24 +3064,24 @@ window.__ModuleLoader__.load({
|
|
|
2876
3064
|
}
|
|
2877
3065
|
/** Validate the public route envelope before publishing it to UI components. */
|
|
2878
3066
|
function parseClaudeClientProjection(value) {
|
|
2879
|
-
const input = record$
|
|
3067
|
+
const input = record$6(value);
|
|
2880
3068
|
if (input === void 0 || input.schemaVersion !== 1 || !nonNegativeInteger(input.revision) || typeof input.owned !== "boolean" || !Array.isArray(input.commands) || input.commands.length > MAX_COMMANDS || !Array.isArray(input.activities) || input.activities.length > MAX_ACTIVITIES) throw new Error("invalid Claude sidecar projection");
|
|
2881
3069
|
for (const item of input.commands) {
|
|
2882
|
-
const command = record$
|
|
3070
|
+
const command = record$6(item);
|
|
2883
3071
|
if (command === void 0 || typeof command.publicName !== "string" || typeof command.claudeName !== "string" || typeof command.description !== "string" || command.hint !== void 0 && typeof command.hint !== "string" || typeof command.prefixed !== "boolean") throw new Error("invalid Claude command projection");
|
|
2884
3072
|
}
|
|
2885
3073
|
for (const item of input.activities) {
|
|
2886
|
-
const activity = record$
|
|
3074
|
+
const activity = record$6(item);
|
|
2887
3075
|
if (activity === void 0 || !nonNegativeInteger(activity.turn) || !nonNegativeInteger(activity.step) || !nonNegativeInteger(activity.ordinal) || typeof activity.kind !== "string") throw new Error("invalid Claude sidecar activity");
|
|
2888
3076
|
}
|
|
2889
|
-
if (input.contextUsage !== void 0 && record$
|
|
2890
|
-
const tasks = input.tasks === void 0 ? void 0 : record$
|
|
3077
|
+
if (input.contextUsage !== void 0 && record$6(input.contextUsage) === void 0) throw new Error("invalid Claude context projection");
|
|
3078
|
+
const tasks = input.tasks === void 0 ? void 0 : record$6(input.tasks);
|
|
2891
3079
|
if (tasks !== void 0 && !Array.isArray(tasks.tasks)) throw new Error("invalid Claude tasks projection");
|
|
2892
3080
|
if (input.repository !== void 0 && !validateRepository(input.repository)) throw new Error("invalid Claude repository projection");
|
|
2893
3081
|
if (input.reviewComments !== void 0) {
|
|
2894
3082
|
if (!Array.isArray(input.reviewComments) || input.reviewComments.length > MAX_REVIEW_COMMENTS) throw new Error("invalid Claude review comment projection");
|
|
2895
3083
|
for (const item of input.reviewComments) {
|
|
2896
|
-
const comment = record$
|
|
3084
|
+
const comment = record$6(item);
|
|
2897
3085
|
if (comment === void 0 || typeof comment.id !== "string" || comment.id.length === 0 || comment.id.length > 128 || typeof comment.path !== "string" || comment.path.length === 0 || comment.path.length > MAX_REPOSITORY_TEXT_CHARS || !nonNegativeInteger(comment.line) || comment.side !== "old" && comment.side !== "new" || typeof comment.text !== "string" || comment.text.length > MAX_REVIEW_COMMENT_CHARS) throw new Error("invalid Claude review comment projection");
|
|
2898
3086
|
}
|
|
2899
3087
|
}
|
|
@@ -3091,7 +3279,7 @@ window.__ModuleLoader__.load({
|
|
|
3091
3279
|
} catch {
|
|
3092
3280
|
return;
|
|
3093
3281
|
}
|
|
3094
|
-
const event = record$
|
|
3282
|
+
const event = record$6(value);
|
|
3095
3283
|
if (event === void 0 || typeof event.type !== "string") return;
|
|
3096
3284
|
try {
|
|
3097
3285
|
switch (event.type) {
|
|
@@ -3350,7 +3538,7 @@ window.__ModuleLoader__.load({
|
|
|
3350
3538
|
return value;
|
|
3351
3539
|
}
|
|
3352
3540
|
}
|
|
3353
|
-
function record$
|
|
3541
|
+
function record$5(value) {
|
|
3354
3542
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3355
3543
|
}
|
|
3356
3544
|
function text(value) {
|
|
@@ -3364,7 +3552,7 @@ window.__ModuleLoader__.load({
|
|
|
3364
3552
|
if (typeof value === "string") return value;
|
|
3365
3553
|
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
3366
3554
|
if (Array.isArray(value)) return value.map(displayValue).join(", ");
|
|
3367
|
-
return record$
|
|
3555
|
+
return record$5(value) === void 0 ? String(value) : Object.entries(value).map(([key, item]) => `${key}: ${displayValue(item)}`).join("\n");
|
|
3368
3556
|
}
|
|
3369
3557
|
function Section({ title, children }) {
|
|
3370
3558
|
return /* @__PURE__ */ jsxs("section", {
|
|
@@ -3434,15 +3622,15 @@ window.__ModuleLoader__.load({
|
|
|
3434
3622
|
function ToolPresentation({ tool, t }) {
|
|
3435
3623
|
const inputValue = parsedValue(tool.input);
|
|
3436
3624
|
const outputValue = parsedValue(tool.output);
|
|
3437
|
-
const input = record$
|
|
3438
|
-
const output = record$
|
|
3625
|
+
const input = record$5(inputValue);
|
|
3626
|
+
const output = record$5(outputValue);
|
|
3439
3627
|
const outputTitle = tool.isError === true ? t("toolError") : t("toolOutput");
|
|
3440
3628
|
if (tool.diffs !== void 0) return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DiffBlock, { diffs: [...tool.diffs] }), /* @__PURE__ */ jsx(TextDetail, {
|
|
3441
3629
|
title: outputTitle,
|
|
3442
3630
|
value: typeof outputValue === "string" ? outputValue : void 0
|
|
3443
3631
|
})] });
|
|
3444
3632
|
if (tool.toolName === "Read") {
|
|
3445
|
-
const file = record$
|
|
3633
|
+
const file = record$5(output?.file);
|
|
3446
3634
|
const path = text(file?.filePath) ?? text(input?.file_path);
|
|
3447
3635
|
const content = text(file?.content) ?? (typeof outputValue === "string" ? outputValue : void 0);
|
|
3448
3636
|
const offset = numberValue(input?.offset) ?? 1;
|
|
@@ -3631,6 +3819,89 @@ window.__ModuleLoader__.load({
|
|
|
3631
3819
|
});
|
|
3632
3820
|
}
|
|
3633
3821
|
//#endregion
|
|
3822
|
+
//#region src/client/jira-api.ts
|
|
3823
|
+
var JiraClientError = class extends Error {
|
|
3824
|
+
code;
|
|
3825
|
+
constructor(message, code) {
|
|
3826
|
+
super(message);
|
|
3827
|
+
this.name = "JiraClientError";
|
|
3828
|
+
if (code !== void 0) this.code = code;
|
|
3829
|
+
}
|
|
3830
|
+
};
|
|
3831
|
+
function record$4(value) {
|
|
3832
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3833
|
+
}
|
|
3834
|
+
async function call(path, init) {
|
|
3835
|
+
const response = await fetch(`${CLAUDE_JIRA_PATH}${path}`, {
|
|
3836
|
+
credentials: "same-origin",
|
|
3837
|
+
...init
|
|
3838
|
+
});
|
|
3839
|
+
const body = record$4(await response.json());
|
|
3840
|
+
if (!response.ok) throw new JiraClientError(typeof body?.message === "string" ? body.message : "Jira is unavailable.", typeof body?.error === "string" ? body.error : void 0);
|
|
3841
|
+
if (body === void 0) throw new JiraClientError("Invalid Jira response.");
|
|
3842
|
+
return body;
|
|
3843
|
+
}
|
|
3844
|
+
function status(body) {
|
|
3845
|
+
if (typeof body.connected !== "boolean") throw new JiraClientError("Invalid Jira status response.");
|
|
3846
|
+
return body;
|
|
3847
|
+
}
|
|
3848
|
+
async function loadJiraStatus(signal) {
|
|
3849
|
+
return status(await call("/status", {
|
|
3850
|
+
method: "GET",
|
|
3851
|
+
headers: { accept: "application/json" },
|
|
3852
|
+
...signal === void 0 ? {} : { signal }
|
|
3853
|
+
}));
|
|
3854
|
+
}
|
|
3855
|
+
async function connectJira(input) {
|
|
3856
|
+
return status(await call("/connect", {
|
|
3857
|
+
method: "POST",
|
|
3858
|
+
headers: {
|
|
3859
|
+
accept: "application/json",
|
|
3860
|
+
"content-type": "application/json"
|
|
3861
|
+
},
|
|
3862
|
+
body: JSON.stringify(input)
|
|
3863
|
+
}));
|
|
3864
|
+
}
|
|
3865
|
+
async function disconnectJira() {
|
|
3866
|
+
await call("/disconnect", {
|
|
3867
|
+
method: "POST",
|
|
3868
|
+
headers: { accept: "application/json" }
|
|
3869
|
+
});
|
|
3870
|
+
}
|
|
3871
|
+
async function searchJiraTickets(query, signal) {
|
|
3872
|
+
const body = await call(`/search?query=${encodeURIComponent(query)}`, {
|
|
3873
|
+
method: "GET",
|
|
3874
|
+
headers: { accept: "application/json" },
|
|
3875
|
+
...signal === void 0 ? {} : { signal }
|
|
3876
|
+
});
|
|
3877
|
+
if (!Array.isArray(body.tickets)) throw new JiraClientError("Invalid Jira search response.");
|
|
3878
|
+
const tickets = [];
|
|
3879
|
+
for (const item of body.tickets) {
|
|
3880
|
+
const ticket = record$4(item);
|
|
3881
|
+
if (ticket === void 0 || typeof ticket.key !== "string" || typeof ticket.summary !== "string" || typeof ticket.url !== "string") continue;
|
|
3882
|
+
tickets.push(ticket);
|
|
3883
|
+
}
|
|
3884
|
+
return tickets;
|
|
3885
|
+
}
|
|
3886
|
+
async function assignJiraTicket(key) {
|
|
3887
|
+
await call("/assign", {
|
|
3888
|
+
method: "POST",
|
|
3889
|
+
headers: {
|
|
3890
|
+
accept: "application/json",
|
|
3891
|
+
"content-type": "application/json"
|
|
3892
|
+
},
|
|
3893
|
+
body: JSON.stringify({ key })
|
|
3894
|
+
});
|
|
3895
|
+
}
|
|
3896
|
+
/** Draft seeded into the composer when a session starts from a ticket. */
|
|
3897
|
+
function ticketPrompt(ticket) {
|
|
3898
|
+
return `Work on Jira ticket ${ticket.key}: ${ticket.summary}\n${ticket.url}\n\nRead the ticket, implement what it asks for, and reference ${ticket.key} in the commit and pull request.`;
|
|
3899
|
+
}
|
|
3900
|
+
/** Appended to a user-written draft so the session still knows its ticket. */
|
|
3901
|
+
function ticketContext(ticket) {
|
|
3902
|
+
return `This task is for Jira ticket ${ticket.key}: ${ticket.summary}\n${ticket.url}\n\nRead the ticket for full context and reference ${ticket.key} in the commit and pull request.`;
|
|
3903
|
+
}
|
|
3904
|
+
//#endregion
|
|
3634
3905
|
//#region src/client/ClaudeCodeSettings.tsx
|
|
3635
3906
|
function isPluginUpdateStatus(value) {
|
|
3636
3907
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
@@ -3825,6 +4096,49 @@ window.__ModuleLoader__.load({
|
|
|
3825
4096
|
const [globalSettings, setGlobalSettings] = useState();
|
|
3826
4097
|
const [globalSettingsError, setGlobalSettingsError] = useState();
|
|
3827
4098
|
const [globalSettingsBusy, setGlobalSettingsBusy] = useState(false);
|
|
4099
|
+
const [jiraStatus, setJiraStatus] = useState();
|
|
4100
|
+
const [jiraError, setJiraError] = useState();
|
|
4101
|
+
const [jiraBusy, setJiraBusy] = useState(false);
|
|
4102
|
+
const [jiraSite, setJiraSite] = useState("");
|
|
4103
|
+
const [jiraEmail, setJiraEmail] = useState("");
|
|
4104
|
+
const [jiraToken, setJiraToken] = useState("");
|
|
4105
|
+
useEffect(() => {
|
|
4106
|
+
const controller = new AbortController();
|
|
4107
|
+
loadJiraStatus(controller.signal).then(setJiraStatus, (reason) => {
|
|
4108
|
+
if (!controller.signal.aborted) setJiraError(reason instanceof Error ? reason.message : String(reason));
|
|
4109
|
+
});
|
|
4110
|
+
return () => {
|
|
4111
|
+
controller.abort();
|
|
4112
|
+
};
|
|
4113
|
+
}, []);
|
|
4114
|
+
const connectJiraNow = async () => {
|
|
4115
|
+
setJiraBusy(true);
|
|
4116
|
+
setJiraError(void 0);
|
|
4117
|
+
try {
|
|
4118
|
+
setJiraStatus(await connectJira({
|
|
4119
|
+
siteUrl: jiraSite,
|
|
4120
|
+
email: jiraEmail,
|
|
4121
|
+
apiToken: jiraToken
|
|
4122
|
+
}));
|
|
4123
|
+
setJiraToken("");
|
|
4124
|
+
} catch (cause) {
|
|
4125
|
+
setJiraError(cause instanceof Error ? cause.message : String(cause));
|
|
4126
|
+
} finally {
|
|
4127
|
+
setJiraBusy(false);
|
|
4128
|
+
}
|
|
4129
|
+
};
|
|
4130
|
+
const disconnectJiraNow = async () => {
|
|
4131
|
+
setJiraBusy(true);
|
|
4132
|
+
setJiraError(void 0);
|
|
4133
|
+
try {
|
|
4134
|
+
await disconnectJira();
|
|
4135
|
+
setJiraStatus({ connected: false });
|
|
4136
|
+
} catch (cause) {
|
|
4137
|
+
setJiraError(cause instanceof Error ? cause.message : String(cause));
|
|
4138
|
+
} finally {
|
|
4139
|
+
setJiraBusy(false);
|
|
4140
|
+
}
|
|
4141
|
+
};
|
|
3828
4142
|
const refresh = useCallback(async () => {
|
|
3829
4143
|
setBusy(true);
|
|
3830
4144
|
setError(void 0);
|
|
@@ -4037,28 +4351,144 @@ window.__ModuleLoader__.load({
|
|
|
4037
4351
|
/* @__PURE__ */ jsxs("section", {
|
|
4038
4352
|
style: settingsCard,
|
|
4039
4353
|
children: [
|
|
4040
|
-
/* @__PURE__ */ jsxs("div", {
|
|
4041
|
-
style:
|
|
4042
|
-
children:
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4354
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4355
|
+
style: settingsCardHeader,
|
|
4356
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
|
|
4357
|
+
style: settingsSectionHeading,
|
|
4358
|
+
children: t("jiraTitle")
|
|
4359
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
4360
|
+
style: settingsBody,
|
|
4361
|
+
children: t("jiraBody")
|
|
4362
|
+
})] }), jiraStatus?.connected === true ? /* @__PURE__ */ jsx("button", {
|
|
4363
|
+
type: "button",
|
|
4364
|
+
style: button,
|
|
4365
|
+
disabled: jiraBusy,
|
|
4366
|
+
onClick: () => {
|
|
4367
|
+
disconnectJiraNow();
|
|
4368
|
+
},
|
|
4369
|
+
children: t("jiraDisconnect")
|
|
4370
|
+
}) : null]
|
|
4371
|
+
}),
|
|
4372
|
+
jiraStatus === void 0 && jiraError === void 0 ? /* @__PURE__ */ jsx("p", {
|
|
4048
4373
|
style: notice,
|
|
4049
|
-
children: t("
|
|
4050
|
-
}) :
|
|
4374
|
+
children: t("jiraLoading")
|
|
4375
|
+
}) : null,
|
|
4376
|
+
jiraStatus?.connected === true ? /* @__PURE__ */ jsxs("div", {
|
|
4051
4377
|
style: diagnosticGrid,
|
|
4052
|
-
children: [
|
|
4053
|
-
|
|
4378
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
4379
|
+
style: diagnosticLabel,
|
|
4380
|
+
children: t("jiraConnected")
|
|
4381
|
+
}), /* @__PURE__ */ jsxs("span", { children: [
|
|
4382
|
+
jiraStatus.siteUrl,
|
|
4383
|
+
" · ",
|
|
4384
|
+
jiraStatus.displayName ?? jiraStatus.email
|
|
4385
|
+
] })]
|
|
4386
|
+
}) : jiraStatus === void 0 ? null : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
4387
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4388
|
+
style: diagnosticGrid,
|
|
4389
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
4054
4390
|
style: diagnosticLabel,
|
|
4055
|
-
children: t("
|
|
4056
|
-
}),
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4391
|
+
children: t("jiraSite")
|
|
4392
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
4393
|
+
type: "url",
|
|
4394
|
+
value: jiraSite,
|
|
4395
|
+
placeholder: t("jiraSitePlaceholder"),
|
|
4396
|
+
disabled: jiraBusy,
|
|
4397
|
+
style: settingTextInput,
|
|
4398
|
+
onChange: (event) => {
|
|
4399
|
+
setJiraSite(event.currentTarget.value);
|
|
4400
|
+
}
|
|
4401
|
+
})]
|
|
4402
|
+
}),
|
|
4403
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4404
|
+
style: diagnosticGrid,
|
|
4405
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
4406
|
+
style: diagnosticLabel,
|
|
4407
|
+
children: t("jiraEmail")
|
|
4408
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
4409
|
+
type: "email",
|
|
4410
|
+
value: jiraEmail,
|
|
4411
|
+
disabled: jiraBusy,
|
|
4412
|
+
style: settingTextInput,
|
|
4413
|
+
onChange: (event) => {
|
|
4414
|
+
setJiraEmail(event.currentTarget.value);
|
|
4415
|
+
}
|
|
4416
|
+
})]
|
|
4417
|
+
}),
|
|
4418
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4419
|
+
style: diagnosticGrid,
|
|
4420
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
4421
|
+
style: diagnosticLabel,
|
|
4422
|
+
children: t("jiraToken")
|
|
4423
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
4424
|
+
type: "password",
|
|
4425
|
+
value: jiraToken,
|
|
4426
|
+
disabled: jiraBusy,
|
|
4427
|
+
autoComplete: "off",
|
|
4428
|
+
style: settingTextInput,
|
|
4429
|
+
onChange: (event) => {
|
|
4430
|
+
setJiraToken(event.currentTarget.value);
|
|
4431
|
+
}
|
|
4432
|
+
})]
|
|
4433
|
+
}),
|
|
4434
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4435
|
+
style: settingsActions,
|
|
4436
|
+
children: [/* @__PURE__ */ jsx("a", {
|
|
4437
|
+
href: "https://id.atlassian.com/manage-profile/security/api-tokens",
|
|
4438
|
+
target: "_blank",
|
|
4439
|
+
rel: "noopener noreferrer",
|
|
4440
|
+
style: settingsLink,
|
|
4441
|
+
children: t("jiraTokenHelp")
|
|
4442
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
4443
|
+
type: "button",
|
|
4444
|
+
style: primaryButton,
|
|
4445
|
+
disabled: jiraBusy || jiraSite.trim() === "" || jiraEmail.trim() === "" || jiraToken.trim() === "",
|
|
4446
|
+
onClick: () => {
|
|
4447
|
+
connectJiraNow();
|
|
4448
|
+
},
|
|
4449
|
+
children: jiraBusy ? t("jiraConnecting") : t("jiraConnect")
|
|
4450
|
+
})]
|
|
4451
|
+
})
|
|
4452
|
+
] }),
|
|
4453
|
+
jiraError === void 0 ? null : /* @__PURE__ */ jsxs("p", {
|
|
4454
|
+
role: "alert",
|
|
4455
|
+
style: {
|
|
4456
|
+
...notice,
|
|
4457
|
+
color: "var(--dsw-alias-state-error-primary)"
|
|
4458
|
+
},
|
|
4459
|
+
children: [
|
|
4460
|
+
t("jiraError"),
|
|
4461
|
+
": ",
|
|
4462
|
+
jiraError
|
|
4463
|
+
]
|
|
4464
|
+
})
|
|
4465
|
+
]
|
|
4466
|
+
}),
|
|
4467
|
+
/* @__PURE__ */ jsxs("section", {
|
|
4468
|
+
style: settingsCard,
|
|
4469
|
+
children: [
|
|
4470
|
+
/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
|
|
4471
|
+
style: settingsSectionHeading,
|
|
4472
|
+
children: t("pluginUpdate")
|
|
4473
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
4474
|
+
style: settingsBody,
|
|
4475
|
+
children: t("pluginUpdateBody")
|
|
4476
|
+
})] }),
|
|
4477
|
+
updateStatus === void 0 ? /* @__PURE__ */ jsx("p", {
|
|
4478
|
+
style: notice,
|
|
4479
|
+
children: t("updateNotChecked")
|
|
4480
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
4481
|
+
style: diagnosticGrid,
|
|
4482
|
+
children: [
|
|
4483
|
+
/* @__PURE__ */ jsx("span", {
|
|
4484
|
+
style: diagnosticLabel,
|
|
4485
|
+
children: t("installedVersion")
|
|
4486
|
+
}),
|
|
4487
|
+
/* @__PURE__ */ jsx("span", {
|
|
4488
|
+
style: diagnosticValue,
|
|
4489
|
+
children: updateStatus.currentVersion
|
|
4490
|
+
}),
|
|
4491
|
+
/* @__PURE__ */ jsx("span", {
|
|
4062
4492
|
style: diagnosticLabel,
|
|
4063
4493
|
children: t("installSource")
|
|
4064
4494
|
}),
|
|
@@ -4217,8 +4647,138 @@ window.__ModuleLoader__.load({
|
|
|
4217
4647
|
})).then(result);
|
|
4218
4648
|
}
|
|
4219
4649
|
//#endregion
|
|
4220
|
-
//#region src/client/
|
|
4650
|
+
//#region src/client/repository-setup-api.ts
|
|
4651
|
+
const HOST_STAGES = /* @__PURE__ */ new Set([
|
|
4652
|
+
"inspecting",
|
|
4653
|
+
"fetching",
|
|
4654
|
+
"creating-worktree",
|
|
4655
|
+
"saving-worktree",
|
|
4656
|
+
"switching-branch"
|
|
4657
|
+
]);
|
|
4221
4658
|
function record$2(value) {
|
|
4659
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
4660
|
+
}
|
|
4661
|
+
function setupResult(value) {
|
|
4662
|
+
const item = record$2(value);
|
|
4663
|
+
if (item === void 0 || item.mode !== "checkout" && item.mode !== "worktree" || typeof item.root !== "string" || typeof item.path !== "string" || typeof item.branch !== "string" || item.leaseId !== void 0 && typeof item.leaseId !== "string") return void 0;
|
|
4664
|
+
return item;
|
|
4665
|
+
}
|
|
4666
|
+
function parseRepositorySetupEvent(line, onProgress) {
|
|
4667
|
+
const event = record$2(JSON.parse(line));
|
|
4668
|
+
if (event?.type === "progress" && typeof event.stage === "string" && HOST_STAGES.has(event.stage)) {
|
|
4669
|
+
onProgress(event.stage);
|
|
4670
|
+
return;
|
|
4671
|
+
}
|
|
4672
|
+
if (event?.type === "complete") {
|
|
4673
|
+
const result = setupResult(event.result);
|
|
4674
|
+
if (result !== void 0) return result;
|
|
4675
|
+
}
|
|
4676
|
+
if (event?.type === "error" && typeof event.message === "string") throw new Error(event.message);
|
|
4677
|
+
throw new Error("Invalid repository setup progress response.");
|
|
4678
|
+
}
|
|
4679
|
+
async function response(pending) {
|
|
4680
|
+
const result = await pending;
|
|
4681
|
+
const body = await result.json();
|
|
4682
|
+
if (!result.ok) {
|
|
4683
|
+
const error = body;
|
|
4684
|
+
throw new Error(error.message ?? error.error ?? "Repository setup failed.");
|
|
4685
|
+
}
|
|
4686
|
+
return body;
|
|
4687
|
+
}
|
|
4688
|
+
function loadRepositoryBranches(cwd, signal) {
|
|
4689
|
+
return response(fetch(`${CLAUDE_REPOSITORY_SETUP_PATH}/branches?cwd=${encodeURIComponent(cwd)}`, {
|
|
4690
|
+
method: "GET",
|
|
4691
|
+
credentials: "same-origin",
|
|
4692
|
+
headers: { accept: "application/json" },
|
|
4693
|
+
...signal === void 0 ? {} : { signal }
|
|
4694
|
+
}));
|
|
4695
|
+
}
|
|
4696
|
+
async function prepareRepository(cwd, branch, worktree, branchName, onProgress = () => {}) {
|
|
4697
|
+
const result = await fetch(CLAUDE_REPOSITORY_SETUP_PATH, {
|
|
4698
|
+
method: "POST",
|
|
4699
|
+
credentials: "same-origin",
|
|
4700
|
+
headers: {
|
|
4701
|
+
accept: "application/x-ndjson",
|
|
4702
|
+
"content-type": "application/json"
|
|
4703
|
+
},
|
|
4704
|
+
body: JSON.stringify({
|
|
4705
|
+
cwd,
|
|
4706
|
+
branch,
|
|
4707
|
+
worktree,
|
|
4708
|
+
...branchName === void 0 ? {} : { branchName }
|
|
4709
|
+
})
|
|
4710
|
+
});
|
|
4711
|
+
if (!result.ok) {
|
|
4712
|
+
const body = await result.json();
|
|
4713
|
+
throw new Error(body.message ?? body.error ?? "Repository setup failed.");
|
|
4714
|
+
}
|
|
4715
|
+
if (result.body === null) throw new Error("Repository setup progress stream is unavailable.");
|
|
4716
|
+
const reader = result.body.getReader();
|
|
4717
|
+
const decoder = new TextDecoder();
|
|
4718
|
+
let buffer = "";
|
|
4719
|
+
let completed;
|
|
4720
|
+
while (true) {
|
|
4721
|
+
const chunk = await reader.read();
|
|
4722
|
+
buffer += decoder.decode(chunk.value, { stream: !chunk.done });
|
|
4723
|
+
const lines = buffer.split("\n");
|
|
4724
|
+
buffer = lines.pop() ?? "";
|
|
4725
|
+
for (const line of lines) {
|
|
4726
|
+
if (line.trim().length === 0) continue;
|
|
4727
|
+
const value = parseRepositorySetupEvent(line, onProgress);
|
|
4728
|
+
if (value !== void 0) completed = value;
|
|
4729
|
+
}
|
|
4730
|
+
if (chunk.done) break;
|
|
4731
|
+
}
|
|
4732
|
+
if (buffer.trim().length > 0) {
|
|
4733
|
+
const value = parseRepositorySetupEvent(buffer, onProgress);
|
|
4734
|
+
if (value !== void 0) completed = value;
|
|
4735
|
+
}
|
|
4736
|
+
if (completed === void 0) throw new Error("Repository setup progress ended before completion.");
|
|
4737
|
+
return completed;
|
|
4738
|
+
}
|
|
4739
|
+
async function bindRepositoryLease(leaseId, sessionId) {
|
|
4740
|
+
await response(fetch(`${CLAUDE_REPOSITORY_SETUP_PATH}/bind`, {
|
|
4741
|
+
method: "POST",
|
|
4742
|
+
credentials: "same-origin",
|
|
4743
|
+
headers: {
|
|
4744
|
+
accept: "application/json",
|
|
4745
|
+
"content-type": "application/json"
|
|
4746
|
+
},
|
|
4747
|
+
body: JSON.stringify({
|
|
4748
|
+
leaseId,
|
|
4749
|
+
sessionId
|
|
4750
|
+
})
|
|
4751
|
+
}));
|
|
4752
|
+
}
|
|
4753
|
+
async function cleanupMergedRepository(path, baseBranch) {
|
|
4754
|
+
const body = await response(fetch(`${CLAUDE_REPOSITORY_SETUP_PATH}/cleanup`, {
|
|
4755
|
+
method: "POST",
|
|
4756
|
+
credentials: "same-origin",
|
|
4757
|
+
headers: {
|
|
4758
|
+
accept: "application/json",
|
|
4759
|
+
"content-type": "application/json"
|
|
4760
|
+
},
|
|
4761
|
+
body: JSON.stringify({
|
|
4762
|
+
path,
|
|
4763
|
+
baseBranch
|
|
4764
|
+
})
|
|
4765
|
+
}));
|
|
4766
|
+
if (body.mode !== "worktree" && body.mode !== "checkout" || typeof body.root !== "string" || typeof body.branch !== "string") throw new Error("Invalid repository cleanup response.");
|
|
4767
|
+
return body;
|
|
4768
|
+
}
|
|
4769
|
+
async function loadRepositoryStatusFor(cwd, signal) {
|
|
4770
|
+
const body = await response(fetch(`${CLAUDE_REPOSITORY_STATUS_PATH}?cwd=${encodeURIComponent(cwd)}`, {
|
|
4771
|
+
method: "GET",
|
|
4772
|
+
credentials: "same-origin",
|
|
4773
|
+
headers: { accept: "application/json" },
|
|
4774
|
+
...signal === void 0 ? {} : { signal }
|
|
4775
|
+
}));
|
|
4776
|
+
if (typeof body.status !== "string" || typeof body.cwd !== "string") throw new Error("Invalid repository status response.");
|
|
4777
|
+
return body;
|
|
4778
|
+
}
|
|
4779
|
+
//#endregion
|
|
4780
|
+
//#region src/client/pr-feedback-api.ts
|
|
4781
|
+
function record$1(value) {
|
|
4222
4782
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
4223
4783
|
}
|
|
4224
4784
|
async function loadJson(path, sessionId, pullNumber, signal) {
|
|
@@ -4228,7 +4788,7 @@ window.__ModuleLoader__.load({
|
|
|
4228
4788
|
headers: { accept: "application/json" },
|
|
4229
4789
|
...signal === void 0 ? {} : { signal }
|
|
4230
4790
|
});
|
|
4231
|
-
const body = record$
|
|
4791
|
+
const body = record$1(await response.json());
|
|
4232
4792
|
if (!response.ok) throw new Error(typeof body?.message === "string" ? body.message : "Pull request feedback is unavailable.");
|
|
4233
4793
|
if (body === void 0) throw new Error("Invalid pull request feedback response.");
|
|
4234
4794
|
return body;
|
|
@@ -4238,7 +4798,7 @@ window.__ModuleLoader__.load({
|
|
|
4238
4798
|
if (!Array.isArray(body.comments)) throw new Error("Invalid pull request comments response.");
|
|
4239
4799
|
const comments = [];
|
|
4240
4800
|
for (const item of body.comments) {
|
|
4241
|
-
const input = record$
|
|
4801
|
+
const input = record$1(item);
|
|
4242
4802
|
if (input === void 0 || typeof input.id !== "number" || typeof input.path !== "string" || typeof input.author !== "string" || typeof input.body !== "string" || typeof input.url !== "string" || input.side !== "new" && input.side !== "old" || input.line !== void 0 && typeof input.line !== "number") continue;
|
|
4243
4803
|
comments.push(input);
|
|
4244
4804
|
}
|
|
@@ -4249,7 +4809,7 @@ window.__ModuleLoader__.load({
|
|
|
4249
4809
|
if (!Array.isArray(body.checks)) throw new Error("Invalid pull request checks response.");
|
|
4250
4810
|
const checks = [];
|
|
4251
4811
|
for (const item of body.checks) {
|
|
4252
|
-
const input = record$
|
|
4812
|
+
const input = record$1(item);
|
|
4253
4813
|
if (input === void 0 || typeof input.name !== "string" || input.link !== void 0 && typeof input.link !== "string" || input.description !== void 0 && typeof input.description !== "string" || input.log !== void 0 && typeof input.log !== "string") continue;
|
|
4254
4814
|
checks.push(input);
|
|
4255
4815
|
}
|
|
@@ -4410,7 +4970,7 @@ window.__ModuleLoader__.load({
|
|
|
4410
4970
|
]
|
|
4411
4971
|
});
|
|
4412
4972
|
}
|
|
4413
|
-
function repositoryName(remote) {
|
|
4973
|
+
function repositoryName$1(remote) {
|
|
4414
4974
|
return remote?.split("/").at(-1);
|
|
4415
4975
|
}
|
|
4416
4976
|
function relativeAge(value) {
|
|
@@ -4447,7 +5007,7 @@ window.__ModuleLoader__.load({
|
|
|
4447
5007
|
/* @__PURE__ */ jsxs("span", {
|
|
4448
5008
|
style: repositoryPrHoverRepo,
|
|
4449
5009
|
children: [
|
|
4450
|
-
repositoryName(repository.remote),
|
|
5010
|
+
repositoryName$1(repository.remote),
|
|
4451
5011
|
" #",
|
|
4452
5012
|
pullRequest.number,
|
|
4453
5013
|
pullRequest.baseBranch === void 0 ? "" : ` → ${pullRequest.baseBranch}`
|
|
@@ -4897,6 +5457,112 @@ window.__ModuleLoader__.load({
|
|
|
4897
5457
|
})
|
|
4898
5458
|
] });
|
|
4899
5459
|
}
|
|
5460
|
+
/** After a merge: remove the worktree (or switch a plain checkout back to
|
|
5461
|
+
* base), delete the merged branch, and drop the DSH workspace. */
|
|
5462
|
+
function CleanupControl({ repository, t, deleteWorkspace }) {
|
|
5463
|
+
const [dialog, setDialog] = useState();
|
|
5464
|
+
const pullRequest = repository.pullRequest;
|
|
5465
|
+
const base = pullRequest?.baseBranch;
|
|
5466
|
+
useEffect(() => {
|
|
5467
|
+
if (dialog?.done === void 0) return;
|
|
5468
|
+
const timer = setTimeout(() => setDialog(void 0), 1500);
|
|
5469
|
+
return () => clearTimeout(timer);
|
|
5470
|
+
}, [dialog?.done]);
|
|
5471
|
+
if (pullRequest?.state !== "merged" || base === void 0 || repository.root === void 0 || repository.detached === true) return null;
|
|
5472
|
+
const root = repository.root;
|
|
5473
|
+
const closeDialog = () => {
|
|
5474
|
+
if (dialog?.submitting !== true) setDialog(void 0);
|
|
5475
|
+
};
|
|
5476
|
+
const confirm = () => {
|
|
5477
|
+
setDialog({ submitting: true });
|
|
5478
|
+
cleanupMergedRepository(root, base).then(async (result) => {
|
|
5479
|
+
if (result.mode === "worktree" && deleteWorkspace !== void 0) await deleteWorkspace();
|
|
5480
|
+
setDialog({
|
|
5481
|
+
submitting: false,
|
|
5482
|
+
done: result.branch
|
|
5483
|
+
});
|
|
5484
|
+
}, (reason) => {
|
|
5485
|
+
setDialog({
|
|
5486
|
+
submitting: false,
|
|
5487
|
+
error: reason instanceof Error ? reason.message : t("diffActionFailed")
|
|
5488
|
+
});
|
|
5489
|
+
});
|
|
5490
|
+
};
|
|
5491
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
5492
|
+
/* @__PURE__ */ jsx("button", {
|
|
5493
|
+
type: "button",
|
|
5494
|
+
style: repositoryUpdateTrigger,
|
|
5495
|
+
title: t("cleanupTitle"),
|
|
5496
|
+
onClick: () => {
|
|
5497
|
+
setDialog({ submitting: false });
|
|
5498
|
+
},
|
|
5499
|
+
children: t("cleanupButton")
|
|
5500
|
+
}),
|
|
5501
|
+
dialog === void 0 ? null : /* @__PURE__ */ jsx("style", {
|
|
5502
|
+
"data-dsh-claude-repository-modal-styles": true,
|
|
5503
|
+
children: diffModalCss
|
|
5504
|
+
}),
|
|
5505
|
+
/* @__PURE__ */ jsx(Modal, {
|
|
5506
|
+
className: "dshClaudeRepositoryActionModal",
|
|
5507
|
+
contentClassName: "dshClaudeRepositoryActionModalContent",
|
|
5508
|
+
open: dialog !== void 0,
|
|
5509
|
+
onClose: closeDialog,
|
|
5510
|
+
title: t("cleanupTitle"),
|
|
5511
|
+
closeLabel: t("diffCancel"),
|
|
5512
|
+
description: t("cleanupDescription"),
|
|
5513
|
+
footer: /* @__PURE__ */ jsxs("div", {
|
|
5514
|
+
style: diffModalFooter,
|
|
5515
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
5516
|
+
type: "button",
|
|
5517
|
+
style: {
|
|
5518
|
+
...button,
|
|
5519
|
+
...diffModalButton
|
|
5520
|
+
},
|
|
5521
|
+
disabled: dialog?.submitting === true,
|
|
5522
|
+
onClick: closeDialog,
|
|
5523
|
+
children: dialog?.done === void 0 ? t("diffCancel") : t("diffDone")
|
|
5524
|
+
}), dialog?.done === void 0 ? /* @__PURE__ */ jsx("button", {
|
|
5525
|
+
type: "button",
|
|
5526
|
+
style: {
|
|
5527
|
+
...primaryButton,
|
|
5528
|
+
...diffModalButton
|
|
5529
|
+
},
|
|
5530
|
+
disabled: dialog?.submitting === true,
|
|
5531
|
+
onClick: confirm,
|
|
5532
|
+
children: dialog?.submitting === true ? t("diffSubmitting") : t("diffConfirm")
|
|
5533
|
+
}) : null]
|
|
5534
|
+
}),
|
|
5535
|
+
children: dialog === void 0 ? null : /* @__PURE__ */ jsxs("div", {
|
|
5536
|
+
style: diffModalBody,
|
|
5537
|
+
children: [
|
|
5538
|
+
/* @__PURE__ */ jsxs("div", {
|
|
5539
|
+
style: diffModalMeta,
|
|
5540
|
+
children: [/* @__PURE__ */ jsxs("strong", {
|
|
5541
|
+
style: diffModalMetaText,
|
|
5542
|
+
children: [
|
|
5543
|
+
repository.branch ?? t("repositoryUnknownBranch"),
|
|
5544
|
+
" → ",
|
|
5545
|
+
base
|
|
5546
|
+
]
|
|
5547
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
5548
|
+
style: diffModalFileState,
|
|
5549
|
+
children: repository.worktree === true ? t("repositoryWorktree") : t("repositoryLocal")
|
|
5550
|
+
})]
|
|
5551
|
+
}),
|
|
5552
|
+
dialog.done === void 0 ? null : /* @__PURE__ */ jsx("p", {
|
|
5553
|
+
style: diffModalSuccess,
|
|
5554
|
+
children: t("cleanupCompleted", { branch: dialog.done })
|
|
5555
|
+
}),
|
|
5556
|
+
dialog.error === void 0 ? null : /* @__PURE__ */ jsx("p", {
|
|
5557
|
+
role: "alert",
|
|
5558
|
+
style: diffModalError,
|
|
5559
|
+
children: dialog.error
|
|
5560
|
+
})
|
|
5561
|
+
]
|
|
5562
|
+
})
|
|
5563
|
+
})
|
|
5564
|
+
] });
|
|
5565
|
+
}
|
|
4900
5566
|
const MERGE_METHODS = [
|
|
4901
5567
|
"merge",
|
|
4902
5568
|
"squash",
|
|
@@ -5066,7 +5732,7 @@ window.__ModuleLoader__.load({
|
|
|
5066
5732
|
})
|
|
5067
5733
|
] });
|
|
5068
5734
|
}
|
|
5069
|
-
function ClaudeRepositoryStatus({ sessionId, useSessions, useClaudeProjection, t, openDiff, submitPrompt }) {
|
|
5735
|
+
function ClaudeRepositoryStatus({ sessionId, useSessions, useClaudeProjection, t, openDiff, submitPrompt, openOverview, deleteWorkspace }) {
|
|
5070
5736
|
const blank = useSessions((value) => value.byId[sessionId]?.blank === true);
|
|
5071
5737
|
const running = useSessions((value) => value.byId[sessionId]?.running === true);
|
|
5072
5738
|
const projection = useClaudeProjection((value) => value);
|
|
@@ -5108,12 +5774,23 @@ window.__ModuleLoader__.load({
|
|
|
5108
5774
|
...merged ? repositoryBarMerged : {}
|
|
5109
5775
|
},
|
|
5110
5776
|
children: [
|
|
5111
|
-
/* @__PURE__ */ jsx("span", {
|
|
5777
|
+
openOverview === void 0 ? /* @__PURE__ */ jsx("span", {
|
|
5112
5778
|
style: {
|
|
5113
5779
|
...repositoryPrIcon,
|
|
5114
5780
|
...merged ? repositoryPrIconMerged : {}
|
|
5115
5781
|
},
|
|
5116
5782
|
children: /* @__PURE__ */ jsx(PullRequestIcon, { merged })
|
|
5783
|
+
}) : /* @__PURE__ */ jsx("button", {
|
|
5784
|
+
type: "button",
|
|
5785
|
+
style: {
|
|
5786
|
+
...repositoryPrIcon,
|
|
5787
|
+
...merged ? repositoryPrIconMerged : {},
|
|
5788
|
+
...repositoryPrIconButton
|
|
5789
|
+
},
|
|
5790
|
+
"aria-label": t("overviewOpen"),
|
|
5791
|
+
title: t("overviewOpen"),
|
|
5792
|
+
onClick: openOverview,
|
|
5793
|
+
children: /* @__PURE__ */ jsx(PullRequestIcon, { merged })
|
|
5117
5794
|
}),
|
|
5118
5795
|
/* @__PURE__ */ jsx(PullRequestLink, {
|
|
5119
5796
|
repository,
|
|
@@ -5121,7 +5798,7 @@ window.__ModuleLoader__.load({
|
|
|
5121
5798
|
}),
|
|
5122
5799
|
repository.remote === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
5123
5800
|
style: repositoryRemote,
|
|
5124
|
-
children: repositoryName(repository.remote)
|
|
5801
|
+
children: repositoryName$1(repository.remote)
|
|
5125
5802
|
}),
|
|
5126
5803
|
/* @__PURE__ */ jsx("span", {
|
|
5127
5804
|
style: repositoryBranch,
|
|
@@ -5157,7 +5834,7 @@ window.__ModuleLoader__.load({
|
|
|
5157
5834
|
children: ["↑", aheadCount > 0 ? aheadCount : ""]
|
|
5158
5835
|
}) : null]
|
|
5159
5836
|
}) : null,
|
|
5160
|
-
pullRequest === void 0 ? null : merged ? /* @__PURE__ */ jsxs("span", {
|
|
5837
|
+
pullRequest === void 0 ? null : merged ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
|
|
5161
5838
|
style: repositoryMergedStatus,
|
|
5162
5839
|
children: [
|
|
5163
5840
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -5170,7 +5847,11 @@ window.__ModuleLoader__.load({
|
|
|
5170
5847
|
children: ["· ", t("repositoryMergedAgo", { age: mergedAge })]
|
|
5171
5848
|
})
|
|
5172
5849
|
]
|
|
5173
|
-
})
|
|
5850
|
+
}), /* @__PURE__ */ jsx(CleanupControl, {
|
|
5851
|
+
repository,
|
|
5852
|
+
t,
|
|
5853
|
+
...deleteWorkspace === void 0 ? {} : { deleteWorkspace }
|
|
5854
|
+
})] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
5174
5855
|
pullRequest.checks === "failing" ? /* @__PURE__ */ jsx(FailingChecksControl, {
|
|
5175
5856
|
sessionId,
|
|
5176
5857
|
pullNumber: pullRequest.number,
|
|
@@ -5211,7 +5892,7 @@ window.__ModuleLoader__.load({
|
|
|
5211
5892
|
}
|
|
5212
5893
|
//#endregion
|
|
5213
5894
|
//#region src/client/review-comment-api.ts
|
|
5214
|
-
function record
|
|
5895
|
+
function record(value) {
|
|
5215
5896
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
5216
5897
|
}
|
|
5217
5898
|
async function post(path, sessionId, body) {
|
|
@@ -5226,13 +5907,13 @@ window.__ModuleLoader__.load({
|
|
|
5226
5907
|
});
|
|
5227
5908
|
const value = await response.json();
|
|
5228
5909
|
if (!response.ok) {
|
|
5229
|
-
const error = record
|
|
5910
|
+
const error = record(value);
|
|
5230
5911
|
throw new Error(typeof error?.message === "string" ? error.message : "Review comment request failed.");
|
|
5231
5912
|
}
|
|
5232
5913
|
return value;
|
|
5233
5914
|
}
|
|
5234
5915
|
async function addReviewComment(sessionId, comment) {
|
|
5235
|
-
const created = record
|
|
5916
|
+
const created = record(record(await post("", sessionId, comment))?.comment);
|
|
5236
5917
|
if (created === void 0 || typeof created.id !== "string") throw new Error("Invalid review comment response.");
|
|
5237
5918
|
return created;
|
|
5238
5919
|
}
|
|
@@ -6301,7 +6982,298 @@ window.__ModuleLoader__.load({
|
|
|
6301
6982
|
background: "var(--dsw-alias-bg-base)",
|
|
6302
6983
|
pointerEvents: bounds === void 0 ? "none" : "auto"
|
|
6303
6984
|
},
|
|
6304
|
-
children
|
|
6985
|
+
children
|
|
6986
|
+
});
|
|
6987
|
+
}
|
|
6988
|
+
//#endregion
|
|
6989
|
+
//#region src/client/ClaudeQueueDock.tsx
|
|
6990
|
+
/** Replaces the Host queue strip (same slot cell, lower priority) with one
|
|
6991
|
+
* styled like the repository status bar. Behaviour mirrors the Host strip:
|
|
6992
|
+
* one row inline, several rows behind a collapsible count, edit/remove/steer. */
|
|
6993
|
+
function ClaudeQueueDock({ useSession, t, updateQueue, notify }) {
|
|
6994
|
+
const inbox = useSession((session) => session.queue);
|
|
6995
|
+
const queue = useMemo(() => inbox.filter((row) => row.placement === "queued"), [inbox]);
|
|
6996
|
+
const running = useSession((session) => session.running);
|
|
6997
|
+
const mutable = useSession((session) => session.subagent === null);
|
|
6998
|
+
const [editing, setEditing] = useState();
|
|
6999
|
+
const [busy, setBusy] = useState();
|
|
7000
|
+
const [collapsed, setCollapsed] = useState(true);
|
|
7001
|
+
const listId = useId();
|
|
7002
|
+
useEffect(() => {
|
|
7003
|
+
if (queue.length === 0 && !collapsed) setCollapsed(true);
|
|
7004
|
+
if (editing !== void 0 && (!mutable || !queue.some((row) => row.id === editing.id))) setEditing(void 0);
|
|
7005
|
+
}, [
|
|
7006
|
+
collapsed,
|
|
7007
|
+
editing,
|
|
7008
|
+
mutable,
|
|
7009
|
+
queue
|
|
7010
|
+
]);
|
|
7011
|
+
if (queue.length === 0) return null;
|
|
7012
|
+
const interacting = mutable && (editing !== void 0 || busy !== void 0);
|
|
7013
|
+
const expanded = !collapsed || interacting;
|
|
7014
|
+
const listVisible = queue.length === 1 || expanded;
|
|
7015
|
+
const apply = async (id, action, failure) => {
|
|
7016
|
+
setBusy(id);
|
|
7017
|
+
try {
|
|
7018
|
+
await updateQueue(id, action);
|
|
7019
|
+
return true;
|
|
7020
|
+
} catch {
|
|
7021
|
+
notify("error", failure);
|
|
7022
|
+
return false;
|
|
7023
|
+
} finally {
|
|
7024
|
+
setBusy((current) => current === id ? void 0 : current);
|
|
7025
|
+
}
|
|
7026
|
+
};
|
|
7027
|
+
const saveEdit = async () => {
|
|
7028
|
+
if (editing === void 0 || editing.text.trim() === "") return;
|
|
7029
|
+
if (await apply(editing.id, {
|
|
7030
|
+
kind: "edit",
|
|
7031
|
+
content: [{
|
|
7032
|
+
type: "text",
|
|
7033
|
+
text: editing.text
|
|
7034
|
+
}]
|
|
7035
|
+
}, t("queueEditFailed"))) setEditing(void 0);
|
|
7036
|
+
};
|
|
7037
|
+
const action = (label, icon, onClick, disabled, hint) => /* @__PURE__ */ jsx(Tooltip, {
|
|
7038
|
+
label: hint ?? label,
|
|
7039
|
+
side: "bottom",
|
|
7040
|
+
delayMs: 400,
|
|
7041
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
7042
|
+
type: "button",
|
|
7043
|
+
className: panelIconButtonClass,
|
|
7044
|
+
"aria-label": label,
|
|
7045
|
+
disabled,
|
|
7046
|
+
onClick,
|
|
7047
|
+
children: icon
|
|
7048
|
+
})
|
|
7049
|
+
});
|
|
7050
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
7051
|
+
style: repositoryBarFrame,
|
|
7052
|
+
"data-claude-queue-dock": "",
|
|
7053
|
+
children: [/* @__PURE__ */ jsx("style", {
|
|
7054
|
+
"data-dsh-claude-queue-styles": true,
|
|
7055
|
+
children: panelIconButtonCss
|
|
7056
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
7057
|
+
style: queueBar,
|
|
7058
|
+
children: [queue.length > 1 ? /* @__PURE__ */ jsxs("button", {
|
|
7059
|
+
type: "button",
|
|
7060
|
+
style: queueHeader,
|
|
7061
|
+
"aria-controls": listId,
|
|
7062
|
+
"aria-expanded": expanded,
|
|
7063
|
+
disabled: interacting,
|
|
7064
|
+
onClick: () => {
|
|
7065
|
+
setCollapsed((value) => !value);
|
|
7066
|
+
},
|
|
7067
|
+
children: [
|
|
7068
|
+
/* @__PURE__ */ jsx("span", {
|
|
7069
|
+
style: queueLead,
|
|
7070
|
+
"aria-hidden": "true",
|
|
7071
|
+
children: /* @__PURE__ */ jsx(IconQueueOutline14, {})
|
|
7072
|
+
}),
|
|
7073
|
+
/* @__PURE__ */ jsx("span", {
|
|
7074
|
+
style: queueCount,
|
|
7075
|
+
children: t("queueCount", { n: queue.length })
|
|
7076
|
+
}),
|
|
7077
|
+
/* @__PURE__ */ jsx("span", {
|
|
7078
|
+
style: queueLead,
|
|
7079
|
+
"aria-hidden": "true",
|
|
7080
|
+
children: expanded ? /* @__PURE__ */ jsx(IconChevronDownOutline14, {}) : /* @__PURE__ */ jsx(IconChevronUpOutline14, {})
|
|
7081
|
+
})
|
|
7082
|
+
]
|
|
7083
|
+
}) : null, /* @__PURE__ */ jsx("ul", {
|
|
7084
|
+
id: listId,
|
|
7085
|
+
style: queueList,
|
|
7086
|
+
hidden: !listVisible,
|
|
7087
|
+
children: listVisible ? queue.map((row, index) => /* @__PURE__ */ jsxs("li", {
|
|
7088
|
+
style: {
|
|
7089
|
+
...queueRow,
|
|
7090
|
+
...index > 0 ? queueRowDivider : {}
|
|
7091
|
+
},
|
|
7092
|
+
children: [
|
|
7093
|
+
queue.length === 1 ? /* @__PURE__ */ jsx("span", {
|
|
7094
|
+
style: queueLead,
|
|
7095
|
+
"aria-hidden": "true",
|
|
7096
|
+
children: /* @__PURE__ */ jsx(IconQueueOutline14, {})
|
|
7097
|
+
}) : null,
|
|
7098
|
+
editing?.id === row.id ? /* @__PURE__ */ jsx("input", {
|
|
7099
|
+
autoFocus: true,
|
|
7100
|
+
style: queueEditor,
|
|
7101
|
+
"aria-label": t("queueEdit"),
|
|
7102
|
+
value: editing.text,
|
|
7103
|
+
onChange: (event) => {
|
|
7104
|
+
setEditing({
|
|
7105
|
+
id: row.id,
|
|
7106
|
+
text: event.currentTarget.value
|
|
7107
|
+
});
|
|
7108
|
+
},
|
|
7109
|
+
onKeyDown: (event) => {
|
|
7110
|
+
if (event.key === "Escape") setEditing(void 0);
|
|
7111
|
+
else if (event.key === "Enter" && !event.nativeEvent.isComposing) {
|
|
7112
|
+
event.preventDefault();
|
|
7113
|
+
saveEdit();
|
|
7114
|
+
}
|
|
7115
|
+
}
|
|
7116
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
7117
|
+
style: queuePreview,
|
|
7118
|
+
children: row.preview
|
|
7119
|
+
}),
|
|
7120
|
+
mutable ? /* @__PURE__ */ jsx("span", {
|
|
7121
|
+
style: queueActions,
|
|
7122
|
+
children: editing?.id === row.id ? /* @__PURE__ */ jsxs(Fragment$1, { children: [action(t("queueSave"), /* @__PURE__ */ jsx(IconCheckOutline16, { size: 14 }), () => {
|
|
7123
|
+
saveEdit();
|
|
7124
|
+
}, busy !== void 0 || editing.text.trim() === ""), action(t("queueCancelEdit"), /* @__PURE__ */ jsx(IconCloseOutline16, { size: 14 }), () => {
|
|
7125
|
+
setEditing(void 0);
|
|
7126
|
+
}, busy !== void 0)] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
7127
|
+
action(t("queueEdit"), /* @__PURE__ */ jsx(IconEditOutline16, { size: 14 }), () => {
|
|
7128
|
+
if (row.text !== null) setEditing({
|
|
7129
|
+
id: row.id,
|
|
7130
|
+
text: row.text
|
|
7131
|
+
});
|
|
7132
|
+
}, busy !== void 0 || row.text === null, row.text === null ? t("queueEditUnsupported") : void 0),
|
|
7133
|
+
action(t("queueRemove"), /* @__PURE__ */ jsx(IconTrashOutline16, { size: 14 }), () => {
|
|
7134
|
+
apply(row.id, { kind: "remove" }, t("queueRemoveFailed"));
|
|
7135
|
+
}, busy !== void 0),
|
|
7136
|
+
action(t("queueSteer"), /* @__PURE__ */ jsx(IconSendOutline14, {}), () => {
|
|
7137
|
+
apply(row.id, { kind: "steer" }, t("queueSteerFailed"));
|
|
7138
|
+
}, busy !== void 0 || !running, running ? void 0 : t("queueSteerUnavailable"))
|
|
7139
|
+
] })
|
|
7140
|
+
}) : null
|
|
7141
|
+
]
|
|
7142
|
+
}, row.id)) : null
|
|
7143
|
+
})]
|
|
7144
|
+
})]
|
|
7145
|
+
});
|
|
7146
|
+
}
|
|
7147
|
+
//#endregion
|
|
7148
|
+
//#region src/client/ClaudePullRequestsPanel.tsx
|
|
7149
|
+
const OVERVIEW_REFRESH_MS = 3e4;
|
|
7150
|
+
/** Claude sessions worth listing: non-blank, with a checkout; running first. */
|
|
7151
|
+
function claudeSessionRows(byId) {
|
|
7152
|
+
return Object.values(byId).filter((row) => row !== void 0 && row.agentPreset === "claude" && row.blank !== true && typeof row.cwd === "string").sort((left, right) => Number(right.running === true) - Number(left.running === true) || (left.displayTitle ?? left.id).localeCompare(right.displayTitle ?? right.id));
|
|
7153
|
+
}
|
|
7154
|
+
function Badge({ label, tone = "neutral" }) {
|
|
7155
|
+
const toneStyle = tone === "success" ? repositoryItemSuccess : tone === "warning" ? repositoryItemWarning : tone === "error" ? repositoryItemError : tone === "merged" ? { color: "#a78bfa" } : {};
|
|
7156
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
7157
|
+
style: {
|
|
7158
|
+
...repositoryItem,
|
|
7159
|
+
...toneStyle
|
|
7160
|
+
},
|
|
7161
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
7162
|
+
style: repositoryItemDot,
|
|
7163
|
+
"aria-hidden": "true"
|
|
7164
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
7165
|
+
style: repositoryItemLabel,
|
|
7166
|
+
children: label
|
|
7167
|
+
})]
|
|
7168
|
+
});
|
|
7169
|
+
}
|
|
7170
|
+
function repositoryName(remote) {
|
|
7171
|
+
return remote?.split("/").at(-1);
|
|
7172
|
+
}
|
|
7173
|
+
function ClaudePullRequestsPanel({ t, closeDetails, openSession, loadStatus, sessions }) {
|
|
7174
|
+
const snapshot = useSyncExternalStore(sessions.subscribe, sessions.getSnapshot, sessions.getSnapshot);
|
|
7175
|
+
const rows = useMemo(() => claudeSessionRows(snapshot.byId), [snapshot.byId]);
|
|
7176
|
+
const cwdKey = useMemo(() => [...new Set(rows.map((row) => row.cwd ?? ""))].sort().join("\0"), [rows]);
|
|
7177
|
+
const [statuses, setStatuses] = useState({});
|
|
7178
|
+
useEffect(() => {
|
|
7179
|
+
const cwds = cwdKey.length === 0 ? [] : cwdKey.split("\0");
|
|
7180
|
+
if (cwds.length === 0) return;
|
|
7181
|
+
const controller = new AbortController();
|
|
7182
|
+
const refresh = () => {
|
|
7183
|
+
for (const cwd of cwds) loadStatus(cwd, controller.signal).then((status) => {
|
|
7184
|
+
if (!controller.signal.aborted) setStatuses((previous) => ({
|
|
7185
|
+
...previous,
|
|
7186
|
+
[cwd]: status
|
|
7187
|
+
}));
|
|
7188
|
+
}, () => void 0);
|
|
7189
|
+
};
|
|
7190
|
+
refresh();
|
|
7191
|
+
const timer = setInterval(refresh, OVERVIEW_REFRESH_MS);
|
|
7192
|
+
return () => {
|
|
7193
|
+
controller.abort();
|
|
7194
|
+
clearInterval(timer);
|
|
7195
|
+
};
|
|
7196
|
+
}, [cwdKey, loadStatus]);
|
|
7197
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
7198
|
+
style: tasksPanel,
|
|
7199
|
+
children: [
|
|
7200
|
+
/* @__PURE__ */ jsx("style", {
|
|
7201
|
+
"data-dsh-claude-overview-styles": true,
|
|
7202
|
+
children: panelIconButtonCss
|
|
7203
|
+
}),
|
|
7204
|
+
/* @__PURE__ */ jsxs("header", {
|
|
7205
|
+
style: tasksHeader,
|
|
7206
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("span", {
|
|
7207
|
+
style: tasksHeading,
|
|
7208
|
+
children: t("overviewTitle")
|
|
7209
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
7210
|
+
style: tasksTurnMeta,
|
|
7211
|
+
children: t("overviewBody")
|
|
7212
|
+
})] }), /* @__PURE__ */ jsx("button", {
|
|
7213
|
+
type: "button",
|
|
7214
|
+
className: panelIconButtonClass,
|
|
7215
|
+
"aria-label": t("diffClose"),
|
|
7216
|
+
onClick: closeDetails,
|
|
7217
|
+
children: /* @__PURE__ */ jsx(IconCloseOutline16, {})
|
|
7218
|
+
})]
|
|
7219
|
+
}),
|
|
7220
|
+
/* @__PURE__ */ jsx("div", {
|
|
7221
|
+
style: overviewBody,
|
|
7222
|
+
children: rows.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
7223
|
+
style: overviewEmpty,
|
|
7224
|
+
children: t("overviewEmpty")
|
|
7225
|
+
}) : rows.map((row) => {
|
|
7226
|
+
const repository = row.cwd === void 0 ? void 0 : statuses[row.cwd];
|
|
7227
|
+
const pullRequest = repository?.pullRequest;
|
|
7228
|
+
const branch = repository?.status === "ready" ? repository.detached === true ? t("repositoryDetached") : repository.branch ?? t("repositoryUnknownBranch") : repository === void 0 ? t("overviewLoading") : t("repositoryUnavailable");
|
|
7229
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
7230
|
+
type: "button",
|
|
7231
|
+
style: overviewRow,
|
|
7232
|
+
onClick: () => {
|
|
7233
|
+
openSession(row.id);
|
|
7234
|
+
},
|
|
7235
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
7236
|
+
style: overviewRowTop,
|
|
7237
|
+
children: [
|
|
7238
|
+
row.running === true ? /* @__PURE__ */ jsx("span", {
|
|
7239
|
+
style: overviewRunningDot,
|
|
7240
|
+
"aria-label": t("overviewRunning")
|
|
7241
|
+
}) : null,
|
|
7242
|
+
/* @__PURE__ */ jsx("span", {
|
|
7243
|
+
style: overviewTitle,
|
|
7244
|
+
children: row.displayTitle ?? row.id
|
|
7245
|
+
}),
|
|
7246
|
+
pullRequest === void 0 ? /* @__PURE__ */ jsx(Badge, { label: t("overviewNoPr") }) : /* @__PURE__ */ jsx(Badge, {
|
|
7247
|
+
label: `#${pullRequest.number} · ${t(`repositoryState_${pullRequest.state}`)}`,
|
|
7248
|
+
tone: pullRequest.state === "merged" ? "merged" : pullRequest.state === "open" ? "success" : "neutral"
|
|
7249
|
+
})
|
|
7250
|
+
]
|
|
7251
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
7252
|
+
style: overviewMeta,
|
|
7253
|
+
children: [
|
|
7254
|
+
repositoryName(repository?.remote) === void 0 ? null : /* @__PURE__ */ jsx("span", { children: repositoryName(repository?.remote) }),
|
|
7255
|
+
/* @__PURE__ */ jsx("span", {
|
|
7256
|
+
style: overviewBranch,
|
|
7257
|
+
children: branch
|
|
7258
|
+
}),
|
|
7259
|
+
pullRequest?.state === "open" && pullRequest.checks !== "none" ? /* @__PURE__ */ jsx(Badge, {
|
|
7260
|
+
label: t(`repositoryChecks_${pullRequest.checks}`),
|
|
7261
|
+
tone: pullRequest.checks === "passing" ? "success" : pullRequest.checks === "failing" ? "error" : "warning"
|
|
7262
|
+
}) : null,
|
|
7263
|
+
pullRequest?.state === "open" && pullRequest.review !== "none" ? /* @__PURE__ */ jsx(Badge, {
|
|
7264
|
+
label: t(`repositoryReview_${pullRequest.review}`),
|
|
7265
|
+
tone: pullRequest.review === "approved" ? "success" : pullRequest.review === "changes-requested" ? "error" : "neutral"
|
|
7266
|
+
}) : null,
|
|
7267
|
+
autoFixEnabled(row.id) ? /* @__PURE__ */ jsx(Badge, {
|
|
7268
|
+
label: t("overviewAutoFix"),
|
|
7269
|
+
tone: "success"
|
|
7270
|
+
}) : null
|
|
7271
|
+
]
|
|
7272
|
+
})]
|
|
7273
|
+
}, row.id);
|
|
7274
|
+
})
|
|
7275
|
+
})
|
|
7276
|
+
]
|
|
6305
7277
|
});
|
|
6306
7278
|
}
|
|
6307
7279
|
//#endregion
|
|
@@ -6350,110 +7322,6 @@ window.__ModuleLoader__.load({
|
|
|
6350
7322
|
for (const portal of root.querySelectorAll(`[${PORTAL_ATTRIBUTE}]`)) portal.remove();
|
|
6351
7323
|
}
|
|
6352
7324
|
//#endregion
|
|
6353
|
-
//#region src/client/repository-setup-api.ts
|
|
6354
|
-
const HOST_STAGES = /* @__PURE__ */ new Set([
|
|
6355
|
-
"inspecting",
|
|
6356
|
-
"fetching",
|
|
6357
|
-
"creating-worktree",
|
|
6358
|
-
"saving-worktree",
|
|
6359
|
-
"switching-branch"
|
|
6360
|
-
]);
|
|
6361
|
-
function record(value) {
|
|
6362
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
6363
|
-
}
|
|
6364
|
-
function setupResult(value) {
|
|
6365
|
-
const item = record(value);
|
|
6366
|
-
if (item === void 0 || item.mode !== "checkout" && item.mode !== "worktree" || typeof item.root !== "string" || typeof item.path !== "string" || typeof item.branch !== "string" || item.leaseId !== void 0 && typeof item.leaseId !== "string") return void 0;
|
|
6367
|
-
return item;
|
|
6368
|
-
}
|
|
6369
|
-
function parseRepositorySetupEvent(line, onProgress) {
|
|
6370
|
-
const event = record(JSON.parse(line));
|
|
6371
|
-
if (event?.type === "progress" && typeof event.stage === "string" && HOST_STAGES.has(event.stage)) {
|
|
6372
|
-
onProgress(event.stage);
|
|
6373
|
-
return;
|
|
6374
|
-
}
|
|
6375
|
-
if (event?.type === "complete") {
|
|
6376
|
-
const result = setupResult(event.result);
|
|
6377
|
-
if (result !== void 0) return result;
|
|
6378
|
-
}
|
|
6379
|
-
if (event?.type === "error" && typeof event.message === "string") throw new Error(event.message);
|
|
6380
|
-
throw new Error("Invalid repository setup progress response.");
|
|
6381
|
-
}
|
|
6382
|
-
async function response(pending) {
|
|
6383
|
-
const result = await pending;
|
|
6384
|
-
const body = await result.json();
|
|
6385
|
-
if (!result.ok) {
|
|
6386
|
-
const error = body;
|
|
6387
|
-
throw new Error(error.message ?? error.error ?? "Repository setup failed.");
|
|
6388
|
-
}
|
|
6389
|
-
return body;
|
|
6390
|
-
}
|
|
6391
|
-
function loadRepositoryBranches(cwd, signal) {
|
|
6392
|
-
return response(fetch(`${CLAUDE_REPOSITORY_SETUP_PATH}/branches?cwd=${encodeURIComponent(cwd)}`, {
|
|
6393
|
-
method: "GET",
|
|
6394
|
-
credentials: "same-origin",
|
|
6395
|
-
headers: { accept: "application/json" },
|
|
6396
|
-
...signal === void 0 ? {} : { signal }
|
|
6397
|
-
}));
|
|
6398
|
-
}
|
|
6399
|
-
async function prepareRepository(cwd, branch, worktree, branchName, onProgress = () => {}) {
|
|
6400
|
-
const result = await fetch(CLAUDE_REPOSITORY_SETUP_PATH, {
|
|
6401
|
-
method: "POST",
|
|
6402
|
-
credentials: "same-origin",
|
|
6403
|
-
headers: {
|
|
6404
|
-
accept: "application/x-ndjson",
|
|
6405
|
-
"content-type": "application/json"
|
|
6406
|
-
},
|
|
6407
|
-
body: JSON.stringify({
|
|
6408
|
-
cwd,
|
|
6409
|
-
branch,
|
|
6410
|
-
worktree,
|
|
6411
|
-
...branchName === void 0 ? {} : { branchName }
|
|
6412
|
-
})
|
|
6413
|
-
});
|
|
6414
|
-
if (!result.ok) {
|
|
6415
|
-
const body = await result.json();
|
|
6416
|
-
throw new Error(body.message ?? body.error ?? "Repository setup failed.");
|
|
6417
|
-
}
|
|
6418
|
-
if (result.body === null) throw new Error("Repository setup progress stream is unavailable.");
|
|
6419
|
-
const reader = result.body.getReader();
|
|
6420
|
-
const decoder = new TextDecoder();
|
|
6421
|
-
let buffer = "";
|
|
6422
|
-
let completed;
|
|
6423
|
-
while (true) {
|
|
6424
|
-
const chunk = await reader.read();
|
|
6425
|
-
buffer += decoder.decode(chunk.value, { stream: !chunk.done });
|
|
6426
|
-
const lines = buffer.split("\n");
|
|
6427
|
-
buffer = lines.pop() ?? "";
|
|
6428
|
-
for (const line of lines) {
|
|
6429
|
-
if (line.trim().length === 0) continue;
|
|
6430
|
-
const value = parseRepositorySetupEvent(line, onProgress);
|
|
6431
|
-
if (value !== void 0) completed = value;
|
|
6432
|
-
}
|
|
6433
|
-
if (chunk.done) break;
|
|
6434
|
-
}
|
|
6435
|
-
if (buffer.trim().length > 0) {
|
|
6436
|
-
const value = parseRepositorySetupEvent(buffer, onProgress);
|
|
6437
|
-
if (value !== void 0) completed = value;
|
|
6438
|
-
}
|
|
6439
|
-
if (completed === void 0) throw new Error("Repository setup progress ended before completion.");
|
|
6440
|
-
return completed;
|
|
6441
|
-
}
|
|
6442
|
-
async function bindRepositoryLease(leaseId, sessionId) {
|
|
6443
|
-
await response(fetch(`${CLAUDE_REPOSITORY_SETUP_PATH}/bind`, {
|
|
6444
|
-
method: "POST",
|
|
6445
|
-
credentials: "same-origin",
|
|
6446
|
-
headers: {
|
|
6447
|
-
accept: "application/json",
|
|
6448
|
-
"content-type": "application/json"
|
|
6449
|
-
},
|
|
6450
|
-
body: JSON.stringify({
|
|
6451
|
-
leaseId,
|
|
6452
|
-
sessionId
|
|
6453
|
-
})
|
|
6454
|
-
}));
|
|
6455
|
-
}
|
|
6456
|
-
//#endregion
|
|
6457
7325
|
//#region src/client/ClaudeHeroRepositoryControls.tsx
|
|
6458
7326
|
function shouldInterceptKey(event) {
|
|
6459
7327
|
if (event.key !== "Enter" || event.shiftKey || event.repeat || event.isComposing) return false;
|
|
@@ -6585,6 +7453,23 @@ window.__ModuleLoader__.load({
|
|
|
6585
7453
|
})]
|
|
6586
7454
|
});
|
|
6587
7455
|
}
|
|
7456
|
+
function TicketIcon() {
|
|
7457
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
7458
|
+
width: "16",
|
|
7459
|
+
height: "16",
|
|
7460
|
+
viewBox: "0 0 16 16",
|
|
7461
|
+
fill: "none",
|
|
7462
|
+
stroke: "currentColor",
|
|
7463
|
+
strokeWidth: "1.5",
|
|
7464
|
+
strokeLinecap: "round",
|
|
7465
|
+
strokeLinejoin: "round",
|
|
7466
|
+
"aria-hidden": "true",
|
|
7467
|
+
children: [/* @__PURE__ */ jsx("path", { d: "M2.5 5.5a1 1 0 0 1 1-1h9a1 1 0 0 1 1 1v1.2a1.3 1.3 0 0 0 0 2.6v1.2a1 1 0 0 1-1 1h-9a1 1 0 0 1-1-1V9.3a1.3 1.3 0 0 0 0-2.6V5.5Z" }), /* @__PURE__ */ jsx("path", {
|
|
7468
|
+
d: "M6.5 4.5v7",
|
|
7469
|
+
strokeDasharray: "1.5 1.5"
|
|
7470
|
+
})]
|
|
7471
|
+
});
|
|
7472
|
+
}
|
|
6588
7473
|
function ClaudeHeroRepositoryCapsule({ branches, selected, worktree, busy, menuOpen, worktreeLabel, searchPlaceholder, emptySearchLabel, onMenuOpenChange, onSelect, onWorktreeChange }) {
|
|
6589
7474
|
const pickerRef = useRef(null);
|
|
6590
7475
|
const searchRef = useRef(null);
|
|
@@ -6771,6 +7656,14 @@ window.__ModuleLoader__.load({
|
|
|
6771
7656
|
const [progressStage, setProgressStage] = useState();
|
|
6772
7657
|
const [progressError, setProgressError] = useState();
|
|
6773
7658
|
const [error, setError] = useState();
|
|
7659
|
+
const [jiraConnected, setJiraConnected] = useState(false);
|
|
7660
|
+
const [ticket, setTicket] = useState();
|
|
7661
|
+
const [ticketMenuOpen, setTicketMenuOpen] = useState(false);
|
|
7662
|
+
const [ticketQuery, setTicketQuery] = useState("");
|
|
7663
|
+
const [ticketResults, setTicketResults] = useState();
|
|
7664
|
+
const [ticketError, setTicketError] = useState();
|
|
7665
|
+
const ticketPickerRef = useRef(null);
|
|
7666
|
+
const ticketSearchRef = useRef(null);
|
|
6774
7667
|
const pendingRef = useRef(false);
|
|
6775
7668
|
const path = workspacePath ?? cwd;
|
|
6776
7669
|
useEffect(() => {
|
|
@@ -6813,6 +7706,11 @@ window.__ModuleLoader__.load({
|
|
|
6813
7706
|
setProgressStage(void 0);
|
|
6814
7707
|
setProgressError(void 0);
|
|
6815
7708
|
setError(void 0);
|
|
7709
|
+
setTicket(void 0);
|
|
7710
|
+
setTicketMenuOpen(false);
|
|
7711
|
+
setTicketQuery("");
|
|
7712
|
+
setTicketResults(void 0);
|
|
7713
|
+
setTicketError(void 0);
|
|
6816
7714
|
if (portal === void 0 || path === void 0) return;
|
|
6817
7715
|
const controller = new AbortController();
|
|
6818
7716
|
loadRepositoryBranches(path, controller.signal).then((value) => {
|
|
@@ -6830,11 +7728,11 @@ window.__ModuleLoader__.load({
|
|
|
6830
7728
|
sessionId
|
|
6831
7729
|
]);
|
|
6832
7730
|
const availableBranches = branches === void 0 ? [] : repositoryBranchOptions(branches);
|
|
6833
|
-
const changed = branches !== void 0 && selected.length > 0 && (worktree || selected !== branches.current);
|
|
7731
|
+
const changed = branches !== void 0 && selected.length > 0 && (worktree || ticket !== void 0 || selected !== branches.current);
|
|
6834
7732
|
useEffect(() => {
|
|
6835
7733
|
if (!changed || portal === void 0 || busy) return;
|
|
6836
7734
|
const submit = (event) => {
|
|
6837
|
-
if (pendingRef.current || input.draft.trim().length === 0) return;
|
|
7735
|
+
if (pendingRef.current || input.draft.trim().length === 0 && ticket === void 0) return;
|
|
6838
7736
|
if (!(event instanceof KeyboardEvent ? shouldInterceptKey(event) : shouldInterceptClick(event))) return;
|
|
6839
7737
|
event.preventDefault();
|
|
6840
7738
|
event.stopPropagation();
|
|
@@ -6845,7 +7743,7 @@ window.__ModuleLoader__.load({
|
|
|
6845
7743
|
setError(void 0);
|
|
6846
7744
|
prepare(branches.root, selected, worktree, (stage) => {
|
|
6847
7745
|
if (worktree) setProgressStage(stage);
|
|
6848
|
-
}).catch((reason) => {
|
|
7746
|
+
}, ticket).catch((reason) => {
|
|
6849
7747
|
const message = reason instanceof Error ? reason.message : String(reason);
|
|
6850
7748
|
if (worktree) setProgressError(message);
|
|
6851
7749
|
else setError(message);
|
|
@@ -6868,38 +7766,187 @@ window.__ModuleLoader__.load({
|
|
|
6868
7766
|
portal,
|
|
6869
7767
|
prepare,
|
|
6870
7768
|
selected,
|
|
7769
|
+
ticket,
|
|
6871
7770
|
worktree
|
|
6872
7771
|
]);
|
|
7772
|
+
useEffect(() => {
|
|
7773
|
+
const controller = new AbortController();
|
|
7774
|
+
loadJiraStatus(controller.signal).then((status) => {
|
|
7775
|
+
setJiraConnected(status.connected);
|
|
7776
|
+
}, () => {
|
|
7777
|
+
if (!controller.signal.aborted) setJiraConnected(false);
|
|
7778
|
+
});
|
|
7779
|
+
return () => {
|
|
7780
|
+
controller.abort();
|
|
7781
|
+
};
|
|
7782
|
+
}, [sessionId]);
|
|
7783
|
+
useEffect(() => {
|
|
7784
|
+
if (!ticketMenuOpen) return;
|
|
7785
|
+
const controller = new AbortController();
|
|
7786
|
+
const timer = setTimeout(() => {
|
|
7787
|
+
setTicketError(void 0);
|
|
7788
|
+
searchJiraTickets(ticketQuery, controller.signal).then(setTicketResults, (reason) => {
|
|
7789
|
+
if (controller.signal.aborted) return;
|
|
7790
|
+
setTicketResults([]);
|
|
7791
|
+
setTicketError(reason instanceof JiraClientError && reason.code === "not-connected" ? t("heroTicketNotConnected") : reason instanceof Error ? reason.message : t("heroTicketFailed"));
|
|
7792
|
+
});
|
|
7793
|
+
}, ticketQuery.length === 0 ? 0 : 300);
|
|
7794
|
+
return () => {
|
|
7795
|
+
clearTimeout(timer);
|
|
7796
|
+
controller.abort();
|
|
7797
|
+
};
|
|
7798
|
+
}, [
|
|
7799
|
+
t,
|
|
7800
|
+
ticketMenuOpen,
|
|
7801
|
+
ticketQuery
|
|
7802
|
+
]);
|
|
7803
|
+
useEffect(() => {
|
|
7804
|
+
if (!ticketMenuOpen) {
|
|
7805
|
+
setTicketQuery("");
|
|
7806
|
+
setTicketResults(void 0);
|
|
7807
|
+
return;
|
|
7808
|
+
}
|
|
7809
|
+
ticketSearchRef.current?.focus();
|
|
7810
|
+
const closeOnOutsidePointer = (event) => {
|
|
7811
|
+
if (event.target instanceof Node && ticketPickerRef.current?.contains(event.target) !== true) setTicketMenuOpen(false);
|
|
7812
|
+
};
|
|
7813
|
+
document.addEventListener("pointerdown", closeOnOutsidePointer);
|
|
7814
|
+
return () => {
|
|
7815
|
+
document.removeEventListener("pointerdown", closeOnOutsidePointer);
|
|
7816
|
+
};
|
|
7817
|
+
}, [ticketMenuOpen]);
|
|
7818
|
+
const chooseTicket = (next) => {
|
|
7819
|
+
setTicket(next);
|
|
7820
|
+
setError(void 0);
|
|
7821
|
+
setTicketMenuOpen(false);
|
|
7822
|
+
};
|
|
6873
7823
|
if (portal === void 0 || path === void 0) return null;
|
|
6874
7824
|
return createPortal(/* @__PURE__ */ jsxs("span", {
|
|
6875
7825
|
style: heroRepositoryControls,
|
|
6876
7826
|
children: [branches === void 0 ? /* @__PURE__ */ jsx("span", {
|
|
6877
7827
|
style: heroRepositoryStatus,
|
|
6878
7828
|
children: error ?? t("repositoryBranchesLoading")
|
|
6879
|
-
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
7829
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
7830
|
+
/* @__PURE__ */ jsx(ClaudeHeroRepositoryCapsule, {
|
|
7831
|
+
branches: availableBranches,
|
|
7832
|
+
selected,
|
|
7833
|
+
worktree,
|
|
7834
|
+
busy,
|
|
7835
|
+
menuOpen,
|
|
7836
|
+
worktreeLabel: t("repositoryWorktree"),
|
|
7837
|
+
searchPlaceholder: t("repositoryBranchSearch"),
|
|
7838
|
+
emptySearchLabel: t("repositoryBranchSearchEmpty"),
|
|
7839
|
+
onMenuOpenChange: setMenuOpen,
|
|
7840
|
+
onSelect: (branch) => {
|
|
7841
|
+
setSelected(branch);
|
|
7842
|
+
setMenuOpen(false);
|
|
7843
|
+
setError(void 0);
|
|
7844
|
+
},
|
|
7845
|
+
onWorktreeChange: (checked) => {
|
|
7846
|
+
setWorktree(checked);
|
|
7847
|
+
setError(void 0);
|
|
7848
|
+
}
|
|
7849
|
+
}),
|
|
7850
|
+
!jiraConnected ? null : /* @__PURE__ */ jsx("span", {
|
|
7851
|
+
style: heroRepositoryCapsule,
|
|
7852
|
+
children: /* @__PURE__ */ jsxs("span", {
|
|
7853
|
+
ref: ticketPickerRef,
|
|
7854
|
+
style: heroBranchPicker,
|
|
7855
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
7856
|
+
type: "button",
|
|
7857
|
+
style: heroBranchTrigger,
|
|
7858
|
+
"aria-expanded": ticketMenuOpen,
|
|
7859
|
+
"aria-label": t("heroTicketMenu"),
|
|
7860
|
+
title: t("heroTicketMenu"),
|
|
7861
|
+
disabled: busy,
|
|
7862
|
+
onClick: () => {
|
|
7863
|
+
setTicketMenuOpen(!ticketMenuOpen);
|
|
7864
|
+
},
|
|
7865
|
+
children: [
|
|
7866
|
+
/* @__PURE__ */ jsx(TicketIcon, {}),
|
|
7867
|
+
/* @__PURE__ */ jsx("span", {
|
|
7868
|
+
style: heroBranchName,
|
|
7869
|
+
children: ticket === void 0 ? t("heroTicket") : ticket.key
|
|
7870
|
+
}),
|
|
7871
|
+
/* @__PURE__ */ jsx(IconChevronDownOutline14, {})
|
|
7872
|
+
]
|
|
7873
|
+
}), ticketMenuOpen ? /* @__PURE__ */ jsxs("span", {
|
|
7874
|
+
role: "menu",
|
|
7875
|
+
style: heroBranchMenu,
|
|
7876
|
+
onKeyDown: (event) => {
|
|
7877
|
+
if (event.key === "Escape") {
|
|
7878
|
+
event.preventDefault();
|
|
7879
|
+
setTicketMenuOpen(false);
|
|
7880
|
+
}
|
|
7881
|
+
},
|
|
7882
|
+
children: [/* @__PURE__ */ jsxs("label", {
|
|
7883
|
+
style: heroBranchSearch,
|
|
7884
|
+
children: [/* @__PURE__ */ jsx(IconSearchOutline16, {}), /* @__PURE__ */ jsx("input", {
|
|
7885
|
+
ref: ticketSearchRef,
|
|
7886
|
+
type: "search",
|
|
7887
|
+
value: ticketQuery,
|
|
7888
|
+
placeholder: t("heroTicketSearch"),
|
|
7889
|
+
"aria-label": t("heroTicketSearch"),
|
|
7890
|
+
style: heroBranchSearchInput,
|
|
7891
|
+
onChange: (event) => {
|
|
7892
|
+
setTicketQuery(event.currentTarget.value);
|
|
7893
|
+
}
|
|
7894
|
+
})]
|
|
7895
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
7896
|
+
style: heroBranchList,
|
|
7897
|
+
children: ticketError !== void 0 ? /* @__PURE__ */ jsx("span", {
|
|
7898
|
+
style: heroBranchEmpty,
|
|
7899
|
+
children: ticketError
|
|
7900
|
+
}) : ticketResults === void 0 ? /* @__PURE__ */ jsx("span", {
|
|
7901
|
+
style: heroBranchEmpty,
|
|
7902
|
+
children: t("heroTicketLoading")
|
|
7903
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [ticket === void 0 ? null : /* @__PURE__ */ jsx("button", {
|
|
7904
|
+
type: "button",
|
|
7905
|
+
role: "menuitem",
|
|
7906
|
+
style: heroBranchItem,
|
|
7907
|
+
onClick: () => {
|
|
7908
|
+
chooseTicket(void 0);
|
|
7909
|
+
},
|
|
7910
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
7911
|
+
style: heroBranchItemName,
|
|
7912
|
+
children: t("heroTicketNone")
|
|
7913
|
+
})
|
|
7914
|
+
}), ticketResults.length === 0 ? /* @__PURE__ */ jsx("span", {
|
|
7915
|
+
style: heroBranchEmpty,
|
|
7916
|
+
children: t("heroTicketEmpty")
|
|
7917
|
+
}) : ticketResults.map((item) => /* @__PURE__ */ jsxs("button", {
|
|
7918
|
+
type: "button",
|
|
7919
|
+
role: "menuitem",
|
|
7920
|
+
"aria-current": item.key === ticket?.key ? "true" : void 0,
|
|
7921
|
+
style: heroBranchItem,
|
|
7922
|
+
onClick: () => {
|
|
7923
|
+
chooseTicket(item);
|
|
7924
|
+
},
|
|
7925
|
+
children: [
|
|
7926
|
+
/* @__PURE__ */ jsx("span", {
|
|
7927
|
+
style: heroTicketKey,
|
|
7928
|
+
children: item.key
|
|
7929
|
+
}),
|
|
7930
|
+
/* @__PURE__ */ jsx("span", {
|
|
7931
|
+
style: heroBranchItemName,
|
|
7932
|
+
children: item.summary
|
|
7933
|
+
}),
|
|
7934
|
+
item.status === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
7935
|
+
style: heroTicketStatus,
|
|
7936
|
+
children: item.status
|
|
7937
|
+
})
|
|
7938
|
+
]
|
|
7939
|
+
}, item.key))] })
|
|
7940
|
+
})]
|
|
7941
|
+
}) : null]
|
|
7942
|
+
})
|
|
7943
|
+
}),
|
|
7944
|
+
error === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
7945
|
+
role: "alert",
|
|
7946
|
+
style: heroRepositoryError,
|
|
7947
|
+
children: error
|
|
7948
|
+
})
|
|
7949
|
+
] }), progressStage === void 0 || !busy && progressError === void 0 ? null : /* @__PURE__ */ jsx(WorktreeProgressCard, {
|
|
6903
7950
|
stage: progressStage,
|
|
6904
7951
|
...progressError === void 0 ? {} : { error: progressError },
|
|
6905
7952
|
t,
|
|
@@ -7373,6 +8420,50 @@ window.__ModuleLoader__.load({
|
|
|
7373
8420
|
prCommentsSend: "让 Claude 处理 GitHub 上的 PR 评论",
|
|
7374
8421
|
autoFixLabel: "Auto fix",
|
|
7375
8422
|
autoFixTitle: "自动监听这个 PR 的 review 评论与 CI 失败,交给 Claude 修复并推送,直到全部通过;取消勾选即停止。",
|
|
8423
|
+
queueCount: "{n} 条排队消息",
|
|
8424
|
+
queueEdit: "编辑",
|
|
8425
|
+
queueEditUnsupported: "包含非文本内容,无法编辑",
|
|
8426
|
+
queueSave: "保存",
|
|
8427
|
+
queueCancelEdit: "取消编辑",
|
|
8428
|
+
queueRemove: "删除",
|
|
8429
|
+
queueSteer: "插入当前回合",
|
|
8430
|
+
queueSteerUnavailable: "没有正在运行的回合",
|
|
8431
|
+
queueEditFailed: "排队消息编辑失败。",
|
|
8432
|
+
queueRemoveFailed: "排队消息删除失败。",
|
|
8433
|
+
queueSteerFailed: "排队消息插入失败。",
|
|
8434
|
+
heroTicket: "Ticket",
|
|
8435
|
+
heroTicketMenu: "选择 Jira ticket",
|
|
8436
|
+
heroTicketSearch: "搜索 ticket 或输入 key…",
|
|
8437
|
+
heroTicketLoading: "搜索中…",
|
|
8438
|
+
heroTicketEmpty: "没有匹配的 ticket",
|
|
8439
|
+
heroTicketNone: "不关联 ticket",
|
|
8440
|
+
heroTicketNotConnected: "请先在 Settings 中连接 Jira",
|
|
8441
|
+
heroTicketFailed: "Ticket 搜索失败",
|
|
8442
|
+
jiraTitle: "Jira",
|
|
8443
|
+
jiraBody: "连接 Jira Cloud 后,新会话可以直接从 ticket 开工:分支按 ticket key 命名,输入框预填 ticket 简报,worktree 创建后自动把 ticket 分配给你。",
|
|
8444
|
+
jiraSite: "站点地址",
|
|
8445
|
+
jiraSitePlaceholder: "https://your-team.atlassian.net",
|
|
8446
|
+
jiraEmail: "账号邮箱",
|
|
8447
|
+
jiraToken: "API Token",
|
|
8448
|
+
jiraTokenHelp: "在 Atlassian 创建 API Token",
|
|
8449
|
+
jiraConnect: "连接",
|
|
8450
|
+
jiraConnecting: "正在验证…",
|
|
8451
|
+
jiraDisconnect: "断开连接",
|
|
8452
|
+
jiraConnected: "已连接",
|
|
8453
|
+
jiraLoading: "正在读取 Jira 状态…",
|
|
8454
|
+
jiraError: "Jira 操作失败",
|
|
8455
|
+
cleanupButton: "Clean up",
|
|
8456
|
+
cleanupTitle: "清理已合并分支",
|
|
8457
|
+
cleanupDescription: "删除 worktree 与本地分支并移除对应 workspace;普通 checkout 则切回 base 分支并删除已合并分支。",
|
|
8458
|
+
cleanupCompleted: "已清理 {branch}",
|
|
8459
|
+
overviewOpen: "查看所有 Claude 会话的 Pull Request",
|
|
8460
|
+
overviewTitle: "Pull requests",
|
|
8461
|
+
overviewBody: "所有 Claude 会话的分支与 PR 状态",
|
|
8462
|
+
overviewEmpty: "没有正在进行的 Claude 会话",
|
|
8463
|
+
overviewNoPr: "无 PR",
|
|
8464
|
+
overviewRunning: "运行中",
|
|
8465
|
+
overviewAutoFix: "Auto fix 已开启",
|
|
8466
|
+
overviewLoading: "读取中…",
|
|
7376
8467
|
reviewCommentAdd: "添加行评论",
|
|
7377
8468
|
reviewCommentPlaceholder: "请求更改",
|
|
7378
8469
|
reviewCommentSubmit: "注释",
|
|
@@ -7600,6 +8691,50 @@ window.__ModuleLoader__.load({
|
|
|
7600
8691
|
prCommentsSend: "Have Claude address the GitHub pull request comments",
|
|
7601
8692
|
autoFixLabel: "Auto fix",
|
|
7602
8693
|
autoFixTitle: "Watch this pull request for review comments and failing checks, hand them to Claude to fix and push until everything passes; uncheck to stop.",
|
|
8694
|
+
queueCount: "{n} queued messages",
|
|
8695
|
+
queueEdit: "Edit",
|
|
8696
|
+
queueEditUnsupported: "Contains non-text content and cannot be edited",
|
|
8697
|
+
queueSave: "Save",
|
|
8698
|
+
queueCancelEdit: "Cancel edit",
|
|
8699
|
+
queueRemove: "Remove",
|
|
8700
|
+
queueSteer: "Steer into the running turn",
|
|
8701
|
+
queueSteerUnavailable: "No running turn to steer into",
|
|
8702
|
+
queueEditFailed: "The queued message could not be edited.",
|
|
8703
|
+
queueRemoveFailed: "The queued message could not be removed.",
|
|
8704
|
+
queueSteerFailed: "The queued message could not be steered.",
|
|
8705
|
+
heroTicket: "Ticket",
|
|
8706
|
+
heroTicketMenu: "Pick a Jira ticket",
|
|
8707
|
+
heroTicketSearch: "Search tickets or enter a key…",
|
|
8708
|
+
heroTicketLoading: "Searching…",
|
|
8709
|
+
heroTicketEmpty: "No matching tickets",
|
|
8710
|
+
heroTicketNone: "No ticket",
|
|
8711
|
+
heroTicketNotConnected: "Connect Jira in Settings first",
|
|
8712
|
+
heroTicketFailed: "Ticket search failed",
|
|
8713
|
+
jiraTitle: "Jira",
|
|
8714
|
+
jiraBody: "Connect Jira Cloud to start new sessions from a ticket: the branch is named after the ticket key, the composer is seeded with the ticket brief, and the ticket is assigned to you once the worktree exists.",
|
|
8715
|
+
jiraSite: "Site URL",
|
|
8716
|
+
jiraSitePlaceholder: "https://your-team.atlassian.net",
|
|
8717
|
+
jiraEmail: "Account email",
|
|
8718
|
+
jiraToken: "API token",
|
|
8719
|
+
jiraTokenHelp: "Create an API token at Atlassian",
|
|
8720
|
+
jiraConnect: "Connect",
|
|
8721
|
+
jiraConnecting: "Verifying…",
|
|
8722
|
+
jiraDisconnect: "Disconnect",
|
|
8723
|
+
jiraConnected: "Connected",
|
|
8724
|
+
jiraLoading: "Loading Jira status…",
|
|
8725
|
+
jiraError: "Jira request failed",
|
|
8726
|
+
cleanupButton: "Clean up",
|
|
8727
|
+
cleanupTitle: "Clean up merged branch",
|
|
8728
|
+
cleanupDescription: "Remove the worktree and local branch and delete the workspace; a plain checkout switches back to the base branch and deletes the merged branch.",
|
|
8729
|
+
cleanupCompleted: "Cleaned up {branch}",
|
|
8730
|
+
overviewOpen: "Show pull requests across Claude sessions",
|
|
8731
|
+
overviewTitle: "Pull requests",
|
|
8732
|
+
overviewBody: "Branch and pull request state across Claude sessions",
|
|
8733
|
+
overviewEmpty: "No active Claude sessions",
|
|
8734
|
+
overviewNoPr: "No PR",
|
|
8735
|
+
overviewRunning: "Running",
|
|
8736
|
+
overviewAutoFix: "Auto fix on",
|
|
8737
|
+
overviewLoading: "Loading…",
|
|
7603
8738
|
reviewCommentAdd: "Add line comment",
|
|
7604
8739
|
reviewCommentPlaceholder: "Request changes",
|
|
7605
8740
|
reviewCommentSubmit: "Comment",
|
|
@@ -7730,6 +8865,31 @@ window.__ModuleLoader__.load({
|
|
|
7730
8865
|
layout?.openDetails();
|
|
7731
8866
|
disposeExpandedDetailsResize = enableExpandedDetailsResize();
|
|
7732
8867
|
};
|
|
8868
|
+
const openOverviewPanel = (sessionId) => {
|
|
8869
|
+
if (sessions === void 0) return;
|
|
8870
|
+
closePluginDetails();
|
|
8871
|
+
try {
|
|
8872
|
+
disposePluginDetails = ctx.slots.register({
|
|
8873
|
+
name: "details",
|
|
8874
|
+
priority: -10,
|
|
8875
|
+
locale: namespace,
|
|
8876
|
+
inject: () => ({
|
|
8877
|
+
t,
|
|
8878
|
+
closeDetails: closePluginDetails,
|
|
8879
|
+
openSession: (id) => {
|
|
8880
|
+
sessions.open(id);
|
|
8881
|
+
},
|
|
8882
|
+
loadStatus: loadRepositoryStatusFor,
|
|
8883
|
+
sessions: sessions.list
|
|
8884
|
+
})
|
|
8885
|
+
}, ClaudePullRequestsPanel);
|
|
8886
|
+
} catch {
|
|
8887
|
+
return;
|
|
8888
|
+
}
|
|
8889
|
+
detailsSessionId = sessionId;
|
|
8890
|
+
layout?.openDetails();
|
|
8891
|
+
disposeExpandedDetailsResize = enableExpandedDetailsResize();
|
|
8892
|
+
};
|
|
7733
8893
|
const openDiffPanel = (sessionId) => {
|
|
7734
8894
|
closePluginDetails();
|
|
7735
8895
|
detailsSessionId = sessionId;
|
|
@@ -7845,10 +9005,33 @@ window.__ModuleLoader__.load({
|
|
|
7845
9005
|
return {
|
|
7846
9006
|
t,
|
|
7847
9007
|
openDiff: () => openDiffPanel(sessionId),
|
|
7848
|
-
...submitPrompt === void 0 ? {} : { submitPrompt }
|
|
9008
|
+
...submitPrompt === void 0 ? {} : { submitPrompt },
|
|
9009
|
+
...sessions === void 0 ? {} : { openOverview: () => openOverviewPanel(sessionId) },
|
|
9010
|
+
...workspaces === void 0 ? {} : { deleteWorkspace: async () => {
|
|
9011
|
+
const workspace = workspaces.list.getSnapshot().items.find((item) => item.sessionIds.includes(sessionId));
|
|
9012
|
+
if (workspace !== void 0) await workspaces.delete(workspace.workspaceId);
|
|
9013
|
+
} }
|
|
7849
9014
|
};
|
|
7850
9015
|
}
|
|
7851
9016
|
}, ClaudeRepositoryStatus));
|
|
9017
|
+
if (sessions !== void 0 && conversation !== void 0) ctx.slots.inject("conversation.input.dock", () => ctx.slots.register({
|
|
9018
|
+
name: "conversation.input.dock",
|
|
9019
|
+
id: "queue",
|
|
9020
|
+
order: 20,
|
|
9021
|
+
priority: -10,
|
|
9022
|
+
locale: namespace,
|
|
9023
|
+
inject: (sessionId) => {
|
|
9024
|
+
const scope = sessions.scope(sessionId);
|
|
9025
|
+
const target = (scope === void 0 ? void 0 : scope.get("conversation")) ?? conversation;
|
|
9026
|
+
return {
|
|
9027
|
+
t,
|
|
9028
|
+
updateQueue: (itemId, action) => target.updateQueue(itemId, action),
|
|
9029
|
+
notify: (level, text) => {
|
|
9030
|
+
if (scope !== void 0) conversation.input.for(scope).notify(level, text);
|
|
9031
|
+
}
|
|
9032
|
+
};
|
|
9033
|
+
}
|
|
9034
|
+
}, ClaudeQueueDock));
|
|
7852
9035
|
if (sessions !== void 0 && workspaces !== void 0 && conversation !== void 0 && connection !== void 0) ctx.slots.inject("conversation.input.dock", () => ctx.slots.register({
|
|
7853
9036
|
name: "conversation.input.dock",
|
|
7854
9037
|
id: "claude-hero-repository-controls",
|
|
@@ -7856,14 +9039,19 @@ window.__ModuleLoader__.load({
|
|
|
7856
9039
|
locale: namespace,
|
|
7857
9040
|
inject: (sourceSessionId) => ({
|
|
7858
9041
|
t,
|
|
7859
|
-
prepare: async (cwd, branch, useWorktree, onProgress) => {
|
|
9042
|
+
prepare: async (cwd, branch, useWorktree, onProgress, ticket) => {
|
|
7860
9043
|
const sourceScope = sessions.scope(sourceSessionId);
|
|
7861
9044
|
if (sourceScope === void 0) throw new Error(t("repositorySessionUnavailable"));
|
|
7862
9045
|
const sourceInput = conversation.input.for(sourceScope);
|
|
7863
|
-
const
|
|
9046
|
+
const rawDraft = sourceInput.state.getSnapshot().draft;
|
|
9047
|
+
const draft = ticket === void 0 ? rawDraft : rawDraft.trim() === "" ? ticketPrompt(ticket) : `${rawDraft.trimEnd()}\n\n${ticketContext(ticket)}`;
|
|
7864
9048
|
const imageIds = sourceInput.state.getSnapshot().imageIds;
|
|
7865
|
-
const prepared = await prepareRepository(cwd, branch, useWorktree,
|
|
9049
|
+
const prepared = await prepareRepository(cwd, branch, useWorktree, ticket?.key, onProgress);
|
|
9050
|
+
if (ticket !== void 0) assignJiraTicket(ticket.key).catch((reason) => {
|
|
9051
|
+
console.warn(`dsh-claude: could not assign ${ticket.key}: ${reason instanceof Error ? reason.message : String(reason)}`);
|
|
9052
|
+
});
|
|
7866
9053
|
if (prepared.mode === "checkout") {
|
|
9054
|
+
if (draft !== rawDraft) sourceInput.setDraft(draft);
|
|
7867
9055
|
sourceInput.submit();
|
|
7868
9056
|
return;
|
|
7869
9057
|
}
|