@norman-else/dsh-claude 0.1.24 → 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 +33 -0
- package/lib/client.js +1085 -181
- 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
|
@@ -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 = {
|
|
@@ -1497,7 +1501,7 @@ window.__ModuleLoader__.load({
|
|
|
1497
1501
|
gap: 2
|
|
1498
1502
|
};
|
|
1499
1503
|
const repositoryBarMerged = {
|
|
1500
|
-
borderColor: "color-mix(in srgb, #a78bfa
|
|
1504
|
+
borderColor: "color-mix(in srgb, #a78bfa 35%, transparent)",
|
|
1501
1505
|
background: "color-mix(in srgb, #a78bfa 5%, var(--dsw-alias-bg-layer-1))"
|
|
1502
1506
|
};
|
|
1503
1507
|
const repositoryPrIcon = {
|
|
@@ -1905,6 +1909,105 @@ window.__ModuleLoader__.load({
|
|
|
1905
1909
|
fontWeight: 650,
|
|
1906
1910
|
cursor: "pointer"
|
|
1907
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
|
+
};
|
|
1908
2011
|
const repositoryMergeTrigger = {
|
|
1909
2012
|
flex: "none",
|
|
1910
2013
|
display: "inline-flex",
|
|
@@ -2915,7 +3018,7 @@ window.__ModuleLoader__.load({
|
|
|
2915
3018
|
const MAX_REVIEW_COMMENTS = 50;
|
|
2916
3019
|
const MAX_REVIEW_COMMENT_CHARS = 2e3;
|
|
2917
3020
|
const MAX_TRANSCRIPT_CHARS = 64e3;
|
|
2918
|
-
function record$
|
|
3021
|
+
function record$6(value) {
|
|
2919
3022
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
2920
3023
|
}
|
|
2921
3024
|
function nonNegativeInteger(value) {
|
|
@@ -2925,18 +3028,18 @@ window.__ModuleLoader__.load({
|
|
|
2925
3028
|
return value === void 0 || typeof value === "string" && value.length <= MAX_REPOSITORY_TEXT_CHARS;
|
|
2926
3029
|
}
|
|
2927
3030
|
function validateRepository(value) {
|
|
2928
|
-
const repository = record$
|
|
3031
|
+
const repository = record$6(value);
|
|
2929
3032
|
if (repository === void 0 || ![
|
|
2930
3033
|
"ready",
|
|
2931
3034
|
"not-repository",
|
|
2932
3035
|
"unavailable"
|
|
2933
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;
|
|
2934
3037
|
if (repository.diff !== void 0) {
|
|
2935
|
-
const diff = record$
|
|
3038
|
+
const diff = record$6(repository.diff);
|
|
2936
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;
|
|
2937
3040
|
}
|
|
2938
3041
|
if (repository.pullRequest === void 0) return true;
|
|
2939
|
-
const pullRequest = record$
|
|
3042
|
+
const pullRequest = record$6(repository.pullRequest);
|
|
2940
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 || ![
|
|
2941
3044
|
"open",
|
|
2942
3045
|
"closed",
|
|
@@ -2961,24 +3064,24 @@ window.__ModuleLoader__.load({
|
|
|
2961
3064
|
}
|
|
2962
3065
|
/** Validate the public route envelope before publishing it to UI components. */
|
|
2963
3066
|
function parseClaudeClientProjection(value) {
|
|
2964
|
-
const input = record$
|
|
3067
|
+
const input = record$6(value);
|
|
2965
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");
|
|
2966
3069
|
for (const item of input.commands) {
|
|
2967
|
-
const command = record$
|
|
3070
|
+
const command = record$6(item);
|
|
2968
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");
|
|
2969
3072
|
}
|
|
2970
3073
|
for (const item of input.activities) {
|
|
2971
|
-
const activity = record$
|
|
3074
|
+
const activity = record$6(item);
|
|
2972
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");
|
|
2973
3076
|
}
|
|
2974
|
-
if (input.contextUsage !== void 0 && record$
|
|
2975
|
-
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);
|
|
2976
3079
|
if (tasks !== void 0 && !Array.isArray(tasks.tasks)) throw new Error("invalid Claude tasks projection");
|
|
2977
3080
|
if (input.repository !== void 0 && !validateRepository(input.repository)) throw new Error("invalid Claude repository projection");
|
|
2978
3081
|
if (input.reviewComments !== void 0) {
|
|
2979
3082
|
if (!Array.isArray(input.reviewComments) || input.reviewComments.length > MAX_REVIEW_COMMENTS) throw new Error("invalid Claude review comment projection");
|
|
2980
3083
|
for (const item of input.reviewComments) {
|
|
2981
|
-
const comment = record$
|
|
3084
|
+
const comment = record$6(item);
|
|
2982
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");
|
|
2983
3086
|
}
|
|
2984
3087
|
}
|
|
@@ -3176,7 +3279,7 @@ window.__ModuleLoader__.load({
|
|
|
3176
3279
|
} catch {
|
|
3177
3280
|
return;
|
|
3178
3281
|
}
|
|
3179
|
-
const event = record$
|
|
3282
|
+
const event = record$6(value);
|
|
3180
3283
|
if (event === void 0 || typeof event.type !== "string") return;
|
|
3181
3284
|
try {
|
|
3182
3285
|
switch (event.type) {
|
|
@@ -3435,7 +3538,7 @@ window.__ModuleLoader__.load({
|
|
|
3435
3538
|
return value;
|
|
3436
3539
|
}
|
|
3437
3540
|
}
|
|
3438
|
-
function record$
|
|
3541
|
+
function record$5(value) {
|
|
3439
3542
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3440
3543
|
}
|
|
3441
3544
|
function text(value) {
|
|
@@ -3449,7 +3552,7 @@ window.__ModuleLoader__.load({
|
|
|
3449
3552
|
if (typeof value === "string") return value;
|
|
3450
3553
|
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
3451
3554
|
if (Array.isArray(value)) return value.map(displayValue).join(", ");
|
|
3452
|
-
return record$
|
|
3555
|
+
return record$5(value) === void 0 ? String(value) : Object.entries(value).map(([key, item]) => `${key}: ${displayValue(item)}`).join("\n");
|
|
3453
3556
|
}
|
|
3454
3557
|
function Section({ title, children }) {
|
|
3455
3558
|
return /* @__PURE__ */ jsxs("section", {
|
|
@@ -3519,15 +3622,15 @@ window.__ModuleLoader__.load({
|
|
|
3519
3622
|
function ToolPresentation({ tool, t }) {
|
|
3520
3623
|
const inputValue = parsedValue(tool.input);
|
|
3521
3624
|
const outputValue = parsedValue(tool.output);
|
|
3522
|
-
const input = record$
|
|
3523
|
-
const output = record$
|
|
3625
|
+
const input = record$5(inputValue);
|
|
3626
|
+
const output = record$5(outputValue);
|
|
3524
3627
|
const outputTitle = tool.isError === true ? t("toolError") : t("toolOutput");
|
|
3525
3628
|
if (tool.diffs !== void 0) return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DiffBlock, { diffs: [...tool.diffs] }), /* @__PURE__ */ jsx(TextDetail, {
|
|
3526
3629
|
title: outputTitle,
|
|
3527
3630
|
value: typeof outputValue === "string" ? outputValue : void 0
|
|
3528
3631
|
})] });
|
|
3529
3632
|
if (tool.toolName === "Read") {
|
|
3530
|
-
const file = record$
|
|
3633
|
+
const file = record$5(output?.file);
|
|
3531
3634
|
const path = text(file?.filePath) ?? text(input?.file_path);
|
|
3532
3635
|
const content = text(file?.content) ?? (typeof outputValue === "string" ? outputValue : void 0);
|
|
3533
3636
|
const offset = numberValue(input?.offset) ?? 1;
|
|
@@ -3716,6 +3819,89 @@ window.__ModuleLoader__.load({
|
|
|
3716
3819
|
});
|
|
3717
3820
|
}
|
|
3718
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
|
|
3719
3905
|
//#region src/client/ClaudeCodeSettings.tsx
|
|
3720
3906
|
function isPluginUpdateStatus(value) {
|
|
3721
3907
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
@@ -3910,6 +4096,49 @@ window.__ModuleLoader__.load({
|
|
|
3910
4096
|
const [globalSettings, setGlobalSettings] = useState();
|
|
3911
4097
|
const [globalSettingsError, setGlobalSettingsError] = useState();
|
|
3912
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
|
+
};
|
|
3913
4142
|
const refresh = useCallback(async () => {
|
|
3914
4143
|
setBusy(true);
|
|
3915
4144
|
setError(void 0);
|
|
@@ -4119,6 +4348,122 @@ window.__ModuleLoader__.load({
|
|
|
4119
4348
|
})
|
|
4120
4349
|
]
|
|
4121
4350
|
}),
|
|
4351
|
+
/* @__PURE__ */ jsxs("section", {
|
|
4352
|
+
style: settingsCard,
|
|
4353
|
+
children: [
|
|
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", {
|
|
4373
|
+
style: notice,
|
|
4374
|
+
children: t("jiraLoading")
|
|
4375
|
+
}) : null,
|
|
4376
|
+
jiraStatus?.connected === true ? /* @__PURE__ */ jsxs("div", {
|
|
4377
|
+
style: diagnosticGrid,
|
|
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", {
|
|
4390
|
+
style: diagnosticLabel,
|
|
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
|
+
}),
|
|
4122
4467
|
/* @__PURE__ */ jsxs("section", {
|
|
4123
4468
|
style: settingsCard,
|
|
4124
4469
|
children: [
|
|
@@ -4302,31 +4647,161 @@ window.__ModuleLoader__.load({
|
|
|
4302
4647
|
})).then(result);
|
|
4303
4648
|
}
|
|
4304
4649
|
//#endregion
|
|
4305
|
-
//#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
|
+
]);
|
|
4306
4658
|
function record$2(value) {
|
|
4307
|
-
return
|
|
4659
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
4308
4660
|
}
|
|
4309
|
-
|
|
4310
|
-
const
|
|
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)}`, {
|
|
4311
4690
|
method: "GET",
|
|
4312
4691
|
credentials: "same-origin",
|
|
4313
4692
|
headers: { accept: "application/json" },
|
|
4314
4693
|
...signal === void 0 ? {} : { signal }
|
|
4315
|
-
});
|
|
4316
|
-
const body = record$2(await response.json());
|
|
4317
|
-
if (!response.ok) throw new Error(typeof body?.message === "string" ? body.message : "Pull request feedback is unavailable.");
|
|
4318
|
-
if (body === void 0) throw new Error("Invalid pull request feedback response.");
|
|
4319
|
-
return body;
|
|
4694
|
+
}));
|
|
4320
4695
|
}
|
|
4321
|
-
async function
|
|
4322
|
-
const
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
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) {
|
|
4782
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
4783
|
+
}
|
|
4784
|
+
async function loadJson(path, sessionId, pullNumber, signal) {
|
|
4785
|
+
const response = await fetch(`${CLAUDE_REPOSITORY_FEEDBACK_PATH}${path}?sessionId=${encodeURIComponent(sessionId)}&number=${pullNumber}`, {
|
|
4786
|
+
method: "GET",
|
|
4787
|
+
credentials: "same-origin",
|
|
4788
|
+
headers: { accept: "application/json" },
|
|
4789
|
+
...signal === void 0 ? {} : { signal }
|
|
4790
|
+
});
|
|
4791
|
+
const body = record$1(await response.json());
|
|
4792
|
+
if (!response.ok) throw new Error(typeof body?.message === "string" ? body.message : "Pull request feedback is unavailable.");
|
|
4793
|
+
if (body === void 0) throw new Error("Invalid pull request feedback response.");
|
|
4794
|
+
return body;
|
|
4795
|
+
}
|
|
4796
|
+
async function loadPullRequestComments(sessionId, pullNumber, signal) {
|
|
4797
|
+
const body = await loadJson("/comments", sessionId, pullNumber, signal);
|
|
4798
|
+
if (!Array.isArray(body.comments)) throw new Error("Invalid pull request comments response.");
|
|
4799
|
+
const comments = [];
|
|
4800
|
+
for (const item of body.comments) {
|
|
4801
|
+
const input = record$1(item);
|
|
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;
|
|
4803
|
+
comments.push(input);
|
|
4804
|
+
}
|
|
4330
4805
|
return comments;
|
|
4331
4806
|
}
|
|
4332
4807
|
async function loadFailingChecks(sessionId, pullNumber, signal) {
|
|
@@ -4334,7 +4809,7 @@ window.__ModuleLoader__.load({
|
|
|
4334
4809
|
if (!Array.isArray(body.checks)) throw new Error("Invalid pull request checks response.");
|
|
4335
4810
|
const checks = [];
|
|
4336
4811
|
for (const item of body.checks) {
|
|
4337
|
-
const input = record$
|
|
4812
|
+
const input = record$1(item);
|
|
4338
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;
|
|
4339
4814
|
checks.push(input);
|
|
4340
4815
|
}
|
|
@@ -4495,7 +4970,7 @@ window.__ModuleLoader__.load({
|
|
|
4495
4970
|
]
|
|
4496
4971
|
});
|
|
4497
4972
|
}
|
|
4498
|
-
function repositoryName(remote) {
|
|
4973
|
+
function repositoryName$1(remote) {
|
|
4499
4974
|
return remote?.split("/").at(-1);
|
|
4500
4975
|
}
|
|
4501
4976
|
function relativeAge(value) {
|
|
@@ -4532,7 +5007,7 @@ window.__ModuleLoader__.load({
|
|
|
4532
5007
|
/* @__PURE__ */ jsxs("span", {
|
|
4533
5008
|
style: repositoryPrHoverRepo,
|
|
4534
5009
|
children: [
|
|
4535
|
-
repositoryName(repository.remote),
|
|
5010
|
+
repositoryName$1(repository.remote),
|
|
4536
5011
|
" #",
|
|
4537
5012
|
pullRequest.number,
|
|
4538
5013
|
pullRequest.baseBranch === void 0 ? "" : ` → ${pullRequest.baseBranch}`
|
|
@@ -4982,6 +5457,112 @@ window.__ModuleLoader__.load({
|
|
|
4982
5457
|
})
|
|
4983
5458
|
] });
|
|
4984
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
|
+
}
|
|
4985
5566
|
const MERGE_METHODS = [
|
|
4986
5567
|
"merge",
|
|
4987
5568
|
"squash",
|
|
@@ -5151,7 +5732,7 @@ window.__ModuleLoader__.load({
|
|
|
5151
5732
|
})
|
|
5152
5733
|
] });
|
|
5153
5734
|
}
|
|
5154
|
-
function ClaudeRepositoryStatus({ sessionId, useSessions, useClaudeProjection, t, openDiff, submitPrompt }) {
|
|
5735
|
+
function ClaudeRepositoryStatus({ sessionId, useSessions, useClaudeProjection, t, openDiff, submitPrompt, openOverview, deleteWorkspace }) {
|
|
5155
5736
|
const blank = useSessions((value) => value.byId[sessionId]?.blank === true);
|
|
5156
5737
|
const running = useSessions((value) => value.byId[sessionId]?.running === true);
|
|
5157
5738
|
const projection = useClaudeProjection((value) => value);
|
|
@@ -5193,12 +5774,23 @@ window.__ModuleLoader__.load({
|
|
|
5193
5774
|
...merged ? repositoryBarMerged : {}
|
|
5194
5775
|
},
|
|
5195
5776
|
children: [
|
|
5196
|
-
/* @__PURE__ */ jsx("span", {
|
|
5777
|
+
openOverview === void 0 ? /* @__PURE__ */ jsx("span", {
|
|
5197
5778
|
style: {
|
|
5198
5779
|
...repositoryPrIcon,
|
|
5199
5780
|
...merged ? repositoryPrIconMerged : {}
|
|
5200
5781
|
},
|
|
5201
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 })
|
|
5202
5794
|
}),
|
|
5203
5795
|
/* @__PURE__ */ jsx(PullRequestLink, {
|
|
5204
5796
|
repository,
|
|
@@ -5206,7 +5798,7 @@ window.__ModuleLoader__.load({
|
|
|
5206
5798
|
}),
|
|
5207
5799
|
repository.remote === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
5208
5800
|
style: repositoryRemote,
|
|
5209
|
-
children: repositoryName(repository.remote)
|
|
5801
|
+
children: repositoryName$1(repository.remote)
|
|
5210
5802
|
}),
|
|
5211
5803
|
/* @__PURE__ */ jsx("span", {
|
|
5212
5804
|
style: repositoryBranch,
|
|
@@ -5242,7 +5834,7 @@ window.__ModuleLoader__.load({
|
|
|
5242
5834
|
children: ["↑", aheadCount > 0 ? aheadCount : ""]
|
|
5243
5835
|
}) : null]
|
|
5244
5836
|
}) : null,
|
|
5245
|
-
pullRequest === void 0 ? null : merged ? /* @__PURE__ */ jsxs("span", {
|
|
5837
|
+
pullRequest === void 0 ? null : merged ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
|
|
5246
5838
|
style: repositoryMergedStatus,
|
|
5247
5839
|
children: [
|
|
5248
5840
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -5255,7 +5847,11 @@ window.__ModuleLoader__.load({
|
|
|
5255
5847
|
children: ["· ", t("repositoryMergedAgo", { age: mergedAge })]
|
|
5256
5848
|
})
|
|
5257
5849
|
]
|
|
5258
|
-
})
|
|
5850
|
+
}), /* @__PURE__ */ jsx(CleanupControl, {
|
|
5851
|
+
repository,
|
|
5852
|
+
t,
|
|
5853
|
+
...deleteWorkspace === void 0 ? {} : { deleteWorkspace }
|
|
5854
|
+
})] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
5259
5855
|
pullRequest.checks === "failing" ? /* @__PURE__ */ jsx(FailingChecksControl, {
|
|
5260
5856
|
sessionId,
|
|
5261
5857
|
pullNumber: pullRequest.number,
|
|
@@ -5296,7 +5892,7 @@ window.__ModuleLoader__.load({
|
|
|
5296
5892
|
}
|
|
5297
5893
|
//#endregion
|
|
5298
5894
|
//#region src/client/review-comment-api.ts
|
|
5299
|
-
function record
|
|
5895
|
+
function record(value) {
|
|
5300
5896
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
5301
5897
|
}
|
|
5302
5898
|
async function post(path, sessionId, body) {
|
|
@@ -5311,13 +5907,13 @@ window.__ModuleLoader__.load({
|
|
|
5311
5907
|
});
|
|
5312
5908
|
const value = await response.json();
|
|
5313
5909
|
if (!response.ok) {
|
|
5314
|
-
const error = record
|
|
5910
|
+
const error = record(value);
|
|
5315
5911
|
throw new Error(typeof error?.message === "string" ? error.message : "Review comment request failed.");
|
|
5316
5912
|
}
|
|
5317
5913
|
return value;
|
|
5318
5914
|
}
|
|
5319
5915
|
async function addReviewComment(sessionId, comment) {
|
|
5320
|
-
const created = record
|
|
5916
|
+
const created = record(record(await post("", sessionId, comment))?.comment);
|
|
5321
5917
|
if (created === void 0 || typeof created.id !== "string") throw new Error("Invalid review comment response.");
|
|
5322
5918
|
return created;
|
|
5323
5919
|
}
|
|
@@ -6549,6 +7145,138 @@ window.__ModuleLoader__.load({
|
|
|
6549
7145
|
});
|
|
6550
7146
|
}
|
|
6551
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
|
+
]
|
|
7277
|
+
});
|
|
7278
|
+
}
|
|
7279
|
+
//#endregion
|
|
6552
7280
|
//#region src/client/hero-dom-bridge.ts
|
|
6553
7281
|
const PORTAL_ATTRIBUTE = "data-dsh-claude-hero-controls";
|
|
6554
7282
|
function normalizedText(element) {
|
|
@@ -6594,110 +7322,6 @@ window.__ModuleLoader__.load({
|
|
|
6594
7322
|
for (const portal of root.querySelectorAll(`[${PORTAL_ATTRIBUTE}]`)) portal.remove();
|
|
6595
7323
|
}
|
|
6596
7324
|
//#endregion
|
|
6597
|
-
//#region src/client/repository-setup-api.ts
|
|
6598
|
-
const HOST_STAGES = /* @__PURE__ */ new Set([
|
|
6599
|
-
"inspecting",
|
|
6600
|
-
"fetching",
|
|
6601
|
-
"creating-worktree",
|
|
6602
|
-
"saving-worktree",
|
|
6603
|
-
"switching-branch"
|
|
6604
|
-
]);
|
|
6605
|
-
function record(value) {
|
|
6606
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
6607
|
-
}
|
|
6608
|
-
function setupResult(value) {
|
|
6609
|
-
const item = record(value);
|
|
6610
|
-
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;
|
|
6611
|
-
return item;
|
|
6612
|
-
}
|
|
6613
|
-
function parseRepositorySetupEvent(line, onProgress) {
|
|
6614
|
-
const event = record(JSON.parse(line));
|
|
6615
|
-
if (event?.type === "progress" && typeof event.stage === "string" && HOST_STAGES.has(event.stage)) {
|
|
6616
|
-
onProgress(event.stage);
|
|
6617
|
-
return;
|
|
6618
|
-
}
|
|
6619
|
-
if (event?.type === "complete") {
|
|
6620
|
-
const result = setupResult(event.result);
|
|
6621
|
-
if (result !== void 0) return result;
|
|
6622
|
-
}
|
|
6623
|
-
if (event?.type === "error" && typeof event.message === "string") throw new Error(event.message);
|
|
6624
|
-
throw new Error("Invalid repository setup progress response.");
|
|
6625
|
-
}
|
|
6626
|
-
async function response(pending) {
|
|
6627
|
-
const result = await pending;
|
|
6628
|
-
const body = await result.json();
|
|
6629
|
-
if (!result.ok) {
|
|
6630
|
-
const error = body;
|
|
6631
|
-
throw new Error(error.message ?? error.error ?? "Repository setup failed.");
|
|
6632
|
-
}
|
|
6633
|
-
return body;
|
|
6634
|
-
}
|
|
6635
|
-
function loadRepositoryBranches(cwd, signal) {
|
|
6636
|
-
return response(fetch(`${CLAUDE_REPOSITORY_SETUP_PATH}/branches?cwd=${encodeURIComponent(cwd)}`, {
|
|
6637
|
-
method: "GET",
|
|
6638
|
-
credentials: "same-origin",
|
|
6639
|
-
headers: { accept: "application/json" },
|
|
6640
|
-
...signal === void 0 ? {} : { signal }
|
|
6641
|
-
}));
|
|
6642
|
-
}
|
|
6643
|
-
async function prepareRepository(cwd, branch, worktree, branchName, onProgress = () => {}) {
|
|
6644
|
-
const result = await fetch(CLAUDE_REPOSITORY_SETUP_PATH, {
|
|
6645
|
-
method: "POST",
|
|
6646
|
-
credentials: "same-origin",
|
|
6647
|
-
headers: {
|
|
6648
|
-
accept: "application/x-ndjson",
|
|
6649
|
-
"content-type": "application/json"
|
|
6650
|
-
},
|
|
6651
|
-
body: JSON.stringify({
|
|
6652
|
-
cwd,
|
|
6653
|
-
branch,
|
|
6654
|
-
worktree,
|
|
6655
|
-
...branchName === void 0 ? {} : { branchName }
|
|
6656
|
-
})
|
|
6657
|
-
});
|
|
6658
|
-
if (!result.ok) {
|
|
6659
|
-
const body = await result.json();
|
|
6660
|
-
throw new Error(body.message ?? body.error ?? "Repository setup failed.");
|
|
6661
|
-
}
|
|
6662
|
-
if (result.body === null) throw new Error("Repository setup progress stream is unavailable.");
|
|
6663
|
-
const reader = result.body.getReader();
|
|
6664
|
-
const decoder = new TextDecoder();
|
|
6665
|
-
let buffer = "";
|
|
6666
|
-
let completed;
|
|
6667
|
-
while (true) {
|
|
6668
|
-
const chunk = await reader.read();
|
|
6669
|
-
buffer += decoder.decode(chunk.value, { stream: !chunk.done });
|
|
6670
|
-
const lines = buffer.split("\n");
|
|
6671
|
-
buffer = lines.pop() ?? "";
|
|
6672
|
-
for (const line of lines) {
|
|
6673
|
-
if (line.trim().length === 0) continue;
|
|
6674
|
-
const value = parseRepositorySetupEvent(line, onProgress);
|
|
6675
|
-
if (value !== void 0) completed = value;
|
|
6676
|
-
}
|
|
6677
|
-
if (chunk.done) break;
|
|
6678
|
-
}
|
|
6679
|
-
if (buffer.trim().length > 0) {
|
|
6680
|
-
const value = parseRepositorySetupEvent(buffer, onProgress);
|
|
6681
|
-
if (value !== void 0) completed = value;
|
|
6682
|
-
}
|
|
6683
|
-
if (completed === void 0) throw new Error("Repository setup progress ended before completion.");
|
|
6684
|
-
return completed;
|
|
6685
|
-
}
|
|
6686
|
-
async function bindRepositoryLease(leaseId, sessionId) {
|
|
6687
|
-
await response(fetch(`${CLAUDE_REPOSITORY_SETUP_PATH}/bind`, {
|
|
6688
|
-
method: "POST",
|
|
6689
|
-
credentials: "same-origin",
|
|
6690
|
-
headers: {
|
|
6691
|
-
accept: "application/json",
|
|
6692
|
-
"content-type": "application/json"
|
|
6693
|
-
},
|
|
6694
|
-
body: JSON.stringify({
|
|
6695
|
-
leaseId,
|
|
6696
|
-
sessionId
|
|
6697
|
-
})
|
|
6698
|
-
}));
|
|
6699
|
-
}
|
|
6700
|
-
//#endregion
|
|
6701
7325
|
//#region src/client/ClaudeHeroRepositoryControls.tsx
|
|
6702
7326
|
function shouldInterceptKey(event) {
|
|
6703
7327
|
if (event.key !== "Enter" || event.shiftKey || event.repeat || event.isComposing) return false;
|
|
@@ -6829,6 +7453,23 @@ window.__ModuleLoader__.load({
|
|
|
6829
7453
|
})]
|
|
6830
7454
|
});
|
|
6831
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
|
+
}
|
|
6832
7473
|
function ClaudeHeroRepositoryCapsule({ branches, selected, worktree, busy, menuOpen, worktreeLabel, searchPlaceholder, emptySearchLabel, onMenuOpenChange, onSelect, onWorktreeChange }) {
|
|
6833
7474
|
const pickerRef = useRef(null);
|
|
6834
7475
|
const searchRef = useRef(null);
|
|
@@ -7015,6 +7656,14 @@ window.__ModuleLoader__.load({
|
|
|
7015
7656
|
const [progressStage, setProgressStage] = useState();
|
|
7016
7657
|
const [progressError, setProgressError] = useState();
|
|
7017
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);
|
|
7018
7667
|
const pendingRef = useRef(false);
|
|
7019
7668
|
const path = workspacePath ?? cwd;
|
|
7020
7669
|
useEffect(() => {
|
|
@@ -7057,6 +7706,11 @@ window.__ModuleLoader__.load({
|
|
|
7057
7706
|
setProgressStage(void 0);
|
|
7058
7707
|
setProgressError(void 0);
|
|
7059
7708
|
setError(void 0);
|
|
7709
|
+
setTicket(void 0);
|
|
7710
|
+
setTicketMenuOpen(false);
|
|
7711
|
+
setTicketQuery("");
|
|
7712
|
+
setTicketResults(void 0);
|
|
7713
|
+
setTicketError(void 0);
|
|
7060
7714
|
if (portal === void 0 || path === void 0) return;
|
|
7061
7715
|
const controller = new AbortController();
|
|
7062
7716
|
loadRepositoryBranches(path, controller.signal).then((value) => {
|
|
@@ -7074,11 +7728,11 @@ window.__ModuleLoader__.load({
|
|
|
7074
7728
|
sessionId
|
|
7075
7729
|
]);
|
|
7076
7730
|
const availableBranches = branches === void 0 ? [] : repositoryBranchOptions(branches);
|
|
7077
|
-
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);
|
|
7078
7732
|
useEffect(() => {
|
|
7079
7733
|
if (!changed || portal === void 0 || busy) return;
|
|
7080
7734
|
const submit = (event) => {
|
|
7081
|
-
if (pendingRef.current || input.draft.trim().length === 0) return;
|
|
7735
|
+
if (pendingRef.current || input.draft.trim().length === 0 && ticket === void 0) return;
|
|
7082
7736
|
if (!(event instanceof KeyboardEvent ? shouldInterceptKey(event) : shouldInterceptClick(event))) return;
|
|
7083
7737
|
event.preventDefault();
|
|
7084
7738
|
event.stopPropagation();
|
|
@@ -7089,7 +7743,7 @@ window.__ModuleLoader__.load({
|
|
|
7089
7743
|
setError(void 0);
|
|
7090
7744
|
prepare(branches.root, selected, worktree, (stage) => {
|
|
7091
7745
|
if (worktree) setProgressStage(stage);
|
|
7092
|
-
}).catch((reason) => {
|
|
7746
|
+
}, ticket).catch((reason) => {
|
|
7093
7747
|
const message = reason instanceof Error ? reason.message : String(reason);
|
|
7094
7748
|
if (worktree) setProgressError(message);
|
|
7095
7749
|
else setError(message);
|
|
@@ -7112,38 +7766,187 @@ window.__ModuleLoader__.load({
|
|
|
7112
7766
|
portal,
|
|
7113
7767
|
prepare,
|
|
7114
7768
|
selected,
|
|
7769
|
+
ticket,
|
|
7115
7770
|
worktree
|
|
7116
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
|
+
};
|
|
7117
7823
|
if (portal === void 0 || path === void 0) return null;
|
|
7118
7824
|
return createPortal(/* @__PURE__ */ jsxs("span", {
|
|
7119
7825
|
style: heroRepositoryControls,
|
|
7120
7826
|
children: [branches === void 0 ? /* @__PURE__ */ jsx("span", {
|
|
7121
7827
|
style: heroRepositoryStatus,
|
|
7122
7828
|
children: error ?? t("repositoryBranchesLoading")
|
|
7123
|
-
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
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, {
|
|
7147
7950
|
stage: progressStage,
|
|
7148
7951
|
...progressError === void 0 ? {} : { error: progressError },
|
|
7149
7952
|
t,
|
|
@@ -7628,6 +8431,39 @@ window.__ModuleLoader__.load({
|
|
|
7628
8431
|
queueEditFailed: "排队消息编辑失败。",
|
|
7629
8432
|
queueRemoveFailed: "排队消息删除失败。",
|
|
7630
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: "读取中…",
|
|
7631
8467
|
reviewCommentAdd: "添加行评论",
|
|
7632
8468
|
reviewCommentPlaceholder: "请求更改",
|
|
7633
8469
|
reviewCommentSubmit: "注释",
|
|
@@ -7866,6 +8702,39 @@ window.__ModuleLoader__.load({
|
|
|
7866
8702
|
queueEditFailed: "The queued message could not be edited.",
|
|
7867
8703
|
queueRemoveFailed: "The queued message could not be removed.",
|
|
7868
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…",
|
|
7869
8738
|
reviewCommentAdd: "Add line comment",
|
|
7870
8739
|
reviewCommentPlaceholder: "Request changes",
|
|
7871
8740
|
reviewCommentSubmit: "Comment",
|
|
@@ -7996,6 +8865,31 @@ window.__ModuleLoader__.load({
|
|
|
7996
8865
|
layout?.openDetails();
|
|
7997
8866
|
disposeExpandedDetailsResize = enableExpandedDetailsResize();
|
|
7998
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
|
+
};
|
|
7999
8893
|
const openDiffPanel = (sessionId) => {
|
|
8000
8894
|
closePluginDetails();
|
|
8001
8895
|
detailsSessionId = sessionId;
|
|
@@ -8111,7 +9005,12 @@ window.__ModuleLoader__.load({
|
|
|
8111
9005
|
return {
|
|
8112
9006
|
t,
|
|
8113
9007
|
openDiff: () => openDiffPanel(sessionId),
|
|
8114
|
-
...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
|
+
} }
|
|
8115
9014
|
};
|
|
8116
9015
|
}
|
|
8117
9016
|
}, ClaudeRepositoryStatus));
|
|
@@ -8140,14 +9039,19 @@ window.__ModuleLoader__.load({
|
|
|
8140
9039
|
locale: namespace,
|
|
8141
9040
|
inject: (sourceSessionId) => ({
|
|
8142
9041
|
t,
|
|
8143
|
-
prepare: async (cwd, branch, useWorktree, onProgress) => {
|
|
9042
|
+
prepare: async (cwd, branch, useWorktree, onProgress, ticket) => {
|
|
8144
9043
|
const sourceScope = sessions.scope(sourceSessionId);
|
|
8145
9044
|
if (sourceScope === void 0) throw new Error(t("repositorySessionUnavailable"));
|
|
8146
9045
|
const sourceInput = conversation.input.for(sourceScope);
|
|
8147
|
-
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)}`;
|
|
8148
9048
|
const imageIds = sourceInput.state.getSnapshot().imageIds;
|
|
8149
|
-
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
|
+
});
|
|
8150
9053
|
if (prepared.mode === "checkout") {
|
|
9054
|
+
if (draft !== rawDraft) sourceInput.setDraft(draft);
|
|
8151
9055
|
sourceInput.submit();
|
|
8152
9056
|
return;
|
|
8153
9057
|
}
|