@norman-else/dsh-claude 0.1.25 → 0.1.27
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 +50 -7
- package/lib/client.js +2159 -424
- package/lib/client.js.map +1 -1
- package/lib/{command-bridge-B48egrCr.mjs → command-bridge-BYj0VF4J.mjs} +2 -2
- package/lib/command-bridge-BYj0VF4J.mjs.map +1 -0
- package/lib/{events-BhU0iJUi.mjs → events-lDt9nTUw.mjs} +6 -3
- package/lib/events-lDt9nTUw.mjs.map +1 -0
- package/lib/index.d.mts +4 -0
- package/lib/index.mjs +657 -137
- package/lib/index.mjs.map +1 -1
- package/lib/{preset-installer-Bzw8tuGI.mjs → preset-installer-CPOH9lAr.mjs} +2 -2
- package/lib/preset-installer-CPOH9lAr.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-B48egrCr.mjs.map +0 -1
- package/lib/events-BhU0iJUi.mjs.map +0 -1
- package/lib/preset-installer-Bzw8tuGI.mjs.map +0 -1
package/lib/client.js
CHANGED
|
@@ -12,6 +12,7 @@ window.__ModuleLoader__.load({
|
|
|
12
12
|
const TASK_TOOL_NAMES = /* @__PURE__ */ new Set(["Task", "Agent"]);
|
|
13
13
|
const CLAUDE_DOCTOR_PATH = "/plugins/dsh-claude/doctor";
|
|
14
14
|
const CLAUDE_UPDATE_CHECK_PATH = "/plugins/dsh-claude/update/check";
|
|
15
|
+
const CLAUDE_USAGE_PATH = "/plugins/dsh-claude/usage";
|
|
15
16
|
const CLAUDE_UPDATE_PATH = "/plugins/dsh-claude/update";
|
|
16
17
|
const CLAUDE_PROJECTION_PATH = "/plugins/dsh-claude/projection";
|
|
17
18
|
const CLAUDE_GLOBAL_SETTINGS_PATH = "/plugins/dsh-claude/settings/global";
|
|
@@ -20,7 +21,9 @@ window.__ModuleLoader__.load({
|
|
|
20
21
|
const CLAUDE_REVIEW_COMMENT_PATH = "/plugins/dsh-claude/review-comments";
|
|
21
22
|
const CLAUDE_REPOSITORY_FEEDBACK_PATH = "/plugins/dsh-claude/repository/feedback";
|
|
22
23
|
const CLAUDE_REPOSITORY_STATUS_PATH = "/plugins/dsh-claude/repository/status";
|
|
24
|
+
const CLAUDE_REPOSITORY_FILE_PATH = "/plugins/dsh-claude/repository/file";
|
|
23
25
|
const CLAUDE_JIRA_PATH = "/plugins/dsh-claude/jira";
|
|
26
|
+
const CLAUDE_ASK_PATH = "/plugins/dsh-claude/ask";
|
|
24
27
|
//#endregion
|
|
25
28
|
//#region src/client/task-projection.ts
|
|
26
29
|
/** Tasks UI is reserved for detached work and genuine Claude subagents. */
|
|
@@ -711,6 +714,63 @@ window.__ModuleLoader__.load({
|
|
|
711
714
|
fontWeight: 700,
|
|
712
715
|
textAlign: "center"
|
|
713
716
|
};
|
|
717
|
+
const settingHint = {
|
|
718
|
+
display: "inline-grid",
|
|
719
|
+
placeItems: "center",
|
|
720
|
+
width: 14,
|
|
721
|
+
height: 14,
|
|
722
|
+
marginLeft: 6,
|
|
723
|
+
verticalAlign: "text-top",
|
|
724
|
+
borderRadius: "50%",
|
|
725
|
+
border: "1px solid currentColor",
|
|
726
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
727
|
+
fontSize: 9,
|
|
728
|
+
fontWeight: 600,
|
|
729
|
+
lineHeight: 1,
|
|
730
|
+
cursor: "help",
|
|
731
|
+
userSelect: "none"
|
|
732
|
+
};
|
|
733
|
+
const planUsageMeter = {
|
|
734
|
+
display: "flex",
|
|
735
|
+
alignItems: "center",
|
|
736
|
+
gap: 10,
|
|
737
|
+
minWidth: 0
|
|
738
|
+
};
|
|
739
|
+
const planUsageTrack = {
|
|
740
|
+
flex: "1 1 auto",
|
|
741
|
+
height: 6,
|
|
742
|
+
minWidth: 60,
|
|
743
|
+
borderRadius: 3,
|
|
744
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
745
|
+
overflow: "hidden"
|
|
746
|
+
};
|
|
747
|
+
const planUsageFill = {
|
|
748
|
+
display: "block",
|
|
749
|
+
height: "100%",
|
|
750
|
+
borderRadius: 3,
|
|
751
|
+
transition: "width 200ms ease"
|
|
752
|
+
};
|
|
753
|
+
const planUsageMeta = {
|
|
754
|
+
flex: "0 0 auto",
|
|
755
|
+
fontSize: 12,
|
|
756
|
+
whiteSpace: "nowrap"
|
|
757
|
+
};
|
|
758
|
+
/** Bar colour, plus a matching text colour once a window is worth noticing.
|
|
759
|
+
* Below the warning threshold the reading stays quiet: accent bar, muted text. */
|
|
760
|
+
function planUsageTone(utilization) {
|
|
761
|
+
if (utilization !== void 0 && utilization >= 90) return {
|
|
762
|
+
fill: "var(--dsw-alias-state-error-primary)",
|
|
763
|
+
text: "var(--dsw-alias-state-error-primary)"
|
|
764
|
+
};
|
|
765
|
+
if (utilization !== void 0 && utilization >= 75) return {
|
|
766
|
+
fill: "var(--dsw-alias-state-warning-primary, #d69e2e)",
|
|
767
|
+
text: "var(--dsw-alias-state-warning-primary, #d69e2e)"
|
|
768
|
+
};
|
|
769
|
+
return {
|
|
770
|
+
fill: utilization === void 0 ? "transparent" : "var(--dsw-static-blue-450)",
|
|
771
|
+
text: "var(--dsw-alias-label-tertiary)"
|
|
772
|
+
};
|
|
773
|
+
}
|
|
714
774
|
const settingsActions = {
|
|
715
775
|
display: "flex",
|
|
716
776
|
flexWrap: "wrap",
|
|
@@ -751,16 +811,33 @@ window.__ModuleLoader__.load({
|
|
|
751
811
|
const tasksPanel = {
|
|
752
812
|
display: "flex",
|
|
753
813
|
flexDirection: "column",
|
|
754
|
-
width: "calc(100% - 16px)",
|
|
755
|
-
height: "calc(100% - 16px)",
|
|
756
814
|
minWidth: 0,
|
|
757
|
-
margin: 8,
|
|
758
815
|
overflow: "hidden",
|
|
759
816
|
border: "1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 16%, transparent))",
|
|
760
817
|
borderRadius: 12,
|
|
761
818
|
background: "var(--dsw-alias-bg-layer-1)",
|
|
762
819
|
boxShadow: "0 4px 16px color-mix(in srgb, #000 12%, transparent)"
|
|
763
820
|
};
|
|
821
|
+
const detailsCardClass = "dshClaudeDetailsCard";
|
|
822
|
+
/**
|
|
823
|
+
* Geometry shared by every details-column card. Lives in a stylesheet rather
|
|
824
|
+
* than inline so the DSH Desktop macOS shell can be special-cased: its
|
|
825
|
+
* "advanced" frame floats a 32px opaque caption/drag row over the top of the
|
|
826
|
+
* conversation and details columns, 12px of which lands inside the column and
|
|
827
|
+
* used to cover the card's top border and corners.
|
|
828
|
+
*/
|
|
829
|
+
const detailsCardCss = `
|
|
830
|
+
.${detailsCardClass} {
|
|
831
|
+
box-sizing: border-box;
|
|
832
|
+
width: calc(100% - 16px);
|
|
833
|
+
height: calc(100% - 16px);
|
|
834
|
+
margin: 8px;
|
|
835
|
+
}
|
|
836
|
+
.dshDesktopFrame[data-desktop-mode="advanced"][data-desktop-platform="darwin"] .dshDesktopDetailsSurface .${detailsCardClass} {
|
|
837
|
+
height: calc(100% - 28px);
|
|
838
|
+
margin-top: 20px;
|
|
839
|
+
}
|
|
840
|
+
`;
|
|
764
841
|
const tasksHeader = {
|
|
765
842
|
boxSizing: "border-box",
|
|
766
843
|
height: 58,
|
|
@@ -1131,7 +1208,7 @@ window.__ModuleLoader__.load({
|
|
|
1131
1208
|
background: "transparent",
|
|
1132
1209
|
color: "inherit",
|
|
1133
1210
|
font: "inherit",
|
|
1134
|
-
fontSize:
|
|
1211
|
+
fontSize: 13,
|
|
1135
1212
|
lineHeight: "18px",
|
|
1136
1213
|
cursor: "pointer"
|
|
1137
1214
|
};
|
|
@@ -1178,7 +1255,7 @@ window.__ModuleLoader__.load({
|
|
|
1178
1255
|
background: "transparent",
|
|
1179
1256
|
color: "var(--dsw-alias-label-primary)",
|
|
1180
1257
|
font: "inherit",
|
|
1181
|
-
fontSize:
|
|
1258
|
+
fontSize: 13,
|
|
1182
1259
|
lineHeight: "18px"
|
|
1183
1260
|
};
|
|
1184
1261
|
const heroBranchList = {
|
|
@@ -1190,8 +1267,8 @@ window.__ModuleLoader__.load({
|
|
|
1190
1267
|
};
|
|
1191
1268
|
const heroBranchItem = {
|
|
1192
1269
|
width: "100%",
|
|
1193
|
-
height:
|
|
1194
|
-
minHeight:
|
|
1270
|
+
height: 36,
|
|
1271
|
+
minHeight: 36,
|
|
1195
1272
|
display: "flex",
|
|
1196
1273
|
alignItems: "center",
|
|
1197
1274
|
gap: 8,
|
|
@@ -1201,7 +1278,7 @@ window.__ModuleLoader__.load({
|
|
|
1201
1278
|
background: "transparent",
|
|
1202
1279
|
color: "var(--dsw-alias-label-primary)",
|
|
1203
1280
|
font: "inherit",
|
|
1204
|
-
fontSize:
|
|
1281
|
+
fontSize: 13,
|
|
1205
1282
|
lineHeight: "18px",
|
|
1206
1283
|
textAlign: "left",
|
|
1207
1284
|
cursor: "pointer"
|
|
@@ -1215,11 +1292,11 @@ window.__ModuleLoader__.load({
|
|
|
1215
1292
|
whiteSpace: "nowrap"
|
|
1216
1293
|
};
|
|
1217
1294
|
const heroBranchEmpty = {
|
|
1218
|
-
height:
|
|
1295
|
+
height: 36,
|
|
1219
1296
|
display: "grid",
|
|
1220
1297
|
placeItems: "center",
|
|
1221
1298
|
color: "var(--dsw-alias-label-tertiary)",
|
|
1222
|
-
fontSize:
|
|
1299
|
+
fontSize: 13
|
|
1223
1300
|
};
|
|
1224
1301
|
const heroRepositoryDivider = {
|
|
1225
1302
|
width: 1,
|
|
@@ -1239,7 +1316,7 @@ window.__ModuleLoader__.load({
|
|
|
1239
1316
|
background: "transparent",
|
|
1240
1317
|
color: "var(--dsw-alias-label-secondary)",
|
|
1241
1318
|
font: "inherit",
|
|
1242
|
-
fontSize:
|
|
1319
|
+
fontSize: 13,
|
|
1243
1320
|
lineHeight: "18px",
|
|
1244
1321
|
whiteSpace: "nowrap",
|
|
1245
1322
|
cursor: "pointer",
|
|
@@ -1332,6 +1409,10 @@ window.__ModuleLoader__.load({
|
|
|
1332
1409
|
lineHeight: "18px",
|
|
1333
1410
|
overflowWrap: "anywhere"
|
|
1334
1411
|
};
|
|
1412
|
+
const heroWorktreeProgressContext = {
|
|
1413
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
1414
|
+
fontWeight: 500
|
|
1415
|
+
};
|
|
1335
1416
|
const heroWorktreeProgressDismiss = {
|
|
1336
1417
|
width: 24,
|
|
1337
1418
|
height: 24,
|
|
@@ -1691,6 +1772,14 @@ window.__ModuleLoader__.load({
|
|
|
1691
1772
|
borderRadius: 999,
|
|
1692
1773
|
background: "currentColor"
|
|
1693
1774
|
};
|
|
1775
|
+
const repositoryGlyph = {
|
|
1776
|
+
width: 16,
|
|
1777
|
+
height: 16,
|
|
1778
|
+
flex: "none",
|
|
1779
|
+
display: "grid",
|
|
1780
|
+
placeItems: "center",
|
|
1781
|
+
color: "var(--dsw-alias-label-tertiary)"
|
|
1782
|
+
};
|
|
1694
1783
|
const repositoryItemSuccess = { color: "var(--dsw-alias-state-success-primary)" };
|
|
1695
1784
|
const repositoryItemWarning = { color: "var(--dsw-alias-state-warning-primary, #d69e2e)" };
|
|
1696
1785
|
const repositoryItemError = { color: "var(--dsw-alias-state-error-primary)" };
|
|
@@ -1909,19 +1998,77 @@ window.__ModuleLoader__.load({
|
|
|
1909
1998
|
fontWeight: 650,
|
|
1910
1999
|
cursor: "pointer"
|
|
1911
2000
|
};
|
|
2001
|
+
/** Ticket summaries need room; the branch menu's 280px truncates them badly. */
|
|
2002
|
+
const heroTicketMenu = { width: 420 };
|
|
1912
2003
|
const heroTicketKey = {
|
|
1913
2004
|
flex: "none",
|
|
1914
|
-
color: "var(--dsw-alias-label-
|
|
1915
|
-
fontSize:
|
|
2005
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
2006
|
+
fontSize: 12,
|
|
1916
2007
|
fontWeight: 650,
|
|
1917
2008
|
letterSpacing: .2
|
|
1918
2009
|
};
|
|
2010
|
+
const heroTicketChips = {
|
|
2011
|
+
display: "flex",
|
|
2012
|
+
flexWrap: "wrap",
|
|
2013
|
+
alignItems: "center",
|
|
2014
|
+
gap: 6,
|
|
2015
|
+
padding: "2px 2px 6px",
|
|
2016
|
+
borderBottom: "1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 12%, transparent))"
|
|
2017
|
+
};
|
|
2018
|
+
const heroTicketChip = {
|
|
2019
|
+
display: "inline-flex",
|
|
2020
|
+
alignItems: "center",
|
|
2021
|
+
gap: 4,
|
|
2022
|
+
padding: "2px 4px 2px 8px",
|
|
2023
|
+
border: "1px solid color-mix(in srgb, var(--dsw-static-blue-450) 40%, transparent)",
|
|
2024
|
+
borderRadius: 999,
|
|
2025
|
+
background: "color-mix(in srgb, var(--dsw-static-blue-450) 12%, transparent)",
|
|
2026
|
+
color: "var(--dsw-alias-label-primary)",
|
|
2027
|
+
fontSize: 12,
|
|
2028
|
+
fontWeight: 600,
|
|
2029
|
+
letterSpacing: .2
|
|
2030
|
+
};
|
|
2031
|
+
const heroTicketChipRemove = {
|
|
2032
|
+
width: 16,
|
|
2033
|
+
height: 16,
|
|
2034
|
+
display: "grid",
|
|
2035
|
+
placeItems: "center",
|
|
2036
|
+
padding: 0,
|
|
2037
|
+
border: "none",
|
|
2038
|
+
borderRadius: 999,
|
|
2039
|
+
background: "transparent",
|
|
2040
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
2041
|
+
fontSize: 12,
|
|
2042
|
+
lineHeight: 1,
|
|
2043
|
+
cursor: "pointer"
|
|
2044
|
+
};
|
|
2045
|
+
const heroTicketChipsClear = {
|
|
2046
|
+
padding: "2px 4px",
|
|
2047
|
+
border: "none",
|
|
2048
|
+
background: "transparent",
|
|
2049
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
2050
|
+
fontSize: 12,
|
|
2051
|
+
cursor: "pointer"
|
|
2052
|
+
};
|
|
2053
|
+
const heroTicketCheckbox = {
|
|
2054
|
+
width: 15,
|
|
2055
|
+
height: 15,
|
|
2056
|
+
boxSizing: "border-box",
|
|
2057
|
+
display: "grid",
|
|
2058
|
+
placeItems: "center",
|
|
2059
|
+
flex: "none",
|
|
2060
|
+
border: "1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 16%, transparent))",
|
|
2061
|
+
borderRadius: 4,
|
|
2062
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
2063
|
+
color: "var(--dsw-alias-label-on-accent, #fff)",
|
|
2064
|
+
transition: "border-color 120ms ease, background 120ms ease"
|
|
2065
|
+
};
|
|
1919
2066
|
const heroTicketStatus = {
|
|
1920
2067
|
flex: "none",
|
|
1921
|
-
maxWidth:
|
|
2068
|
+
maxWidth: 110,
|
|
1922
2069
|
overflow: "hidden",
|
|
1923
2070
|
color: "var(--dsw-alias-label-tertiary)",
|
|
1924
|
-
fontSize:
|
|
2071
|
+
fontSize: 12,
|
|
1925
2072
|
textOverflow: "ellipsis",
|
|
1926
2073
|
whiteSpace: "nowrap"
|
|
1927
2074
|
};
|
|
@@ -2008,6 +2155,197 @@ window.__ModuleLoader__.load({
|
|
|
2008
2155
|
fontSize: 13,
|
|
2009
2156
|
textAlign: "center"
|
|
2010
2157
|
};
|
|
2158
|
+
const askSurfaceBorder = "1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 16%, transparent))";
|
|
2159
|
+
const askSurfaceShadow = "var(--dsw-shadow-lv3, 0 8px 24px color-mix(in srgb, #000 24%, transparent))";
|
|
2160
|
+
/** Painted through CSS.highlights while the follow-up popup is open. */
|
|
2161
|
+
const askHighlightCss = `
|
|
2162
|
+
::highlight(dsh-claude-ask) {
|
|
2163
|
+
background-color: color-mix(in srgb, var(--dsw-static-blue-450) 30%, transparent);
|
|
2164
|
+
color: inherit;
|
|
2165
|
+
}
|
|
2166
|
+
`;
|
|
2167
|
+
const askToolbar = {
|
|
2168
|
+
position: "fixed",
|
|
2169
|
+
zIndex: 2e3,
|
|
2170
|
+
pointerEvents: "auto",
|
|
2171
|
+
display: "inline-flex",
|
|
2172
|
+
alignItems: "center",
|
|
2173
|
+
gap: 2,
|
|
2174
|
+
padding: 3,
|
|
2175
|
+
border: askSurfaceBorder,
|
|
2176
|
+
borderRadius: 9,
|
|
2177
|
+
background: "var(--dsw-alias-bg-layer-1)",
|
|
2178
|
+
color: "var(--dsw-alias-label-primary)",
|
|
2179
|
+
boxShadow: askSurfaceShadow
|
|
2180
|
+
};
|
|
2181
|
+
const askPopup = {
|
|
2182
|
+
position: "fixed",
|
|
2183
|
+
zIndex: 2e3,
|
|
2184
|
+
pointerEvents: "auto",
|
|
2185
|
+
boxSizing: "border-box",
|
|
2186
|
+
display: "flex",
|
|
2187
|
+
flexDirection: "column",
|
|
2188
|
+
gap: 10,
|
|
2189
|
+
padding: 12,
|
|
2190
|
+
border: askSurfaceBorder,
|
|
2191
|
+
borderRadius: 12,
|
|
2192
|
+
background: "var(--dsw-alias-bg-layer-1)",
|
|
2193
|
+
color: "var(--dsw-alias-label-primary)",
|
|
2194
|
+
boxShadow: askSurfaceShadow,
|
|
2195
|
+
fontSize: 13,
|
|
2196
|
+
lineHeight: "20px"
|
|
2197
|
+
};
|
|
2198
|
+
const askQuote = {
|
|
2199
|
+
flex: "none",
|
|
2200
|
+
display: "-webkit-box",
|
|
2201
|
+
WebkitLineClamp: 3,
|
|
2202
|
+
WebkitBoxOrient: "vertical",
|
|
2203
|
+
margin: 0,
|
|
2204
|
+
padding: "6px 10px",
|
|
2205
|
+
overflow: "hidden",
|
|
2206
|
+
borderLeft: "3px solid color-mix(in srgb, var(--dsw-static-blue-450) 60%, transparent)",
|
|
2207
|
+
borderRadius: 6,
|
|
2208
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
2209
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
2210
|
+
fontSize: 12,
|
|
2211
|
+
lineHeight: "18px",
|
|
2212
|
+
whiteSpace: "pre-wrap",
|
|
2213
|
+
wordBreak: "break-word"
|
|
2214
|
+
};
|
|
2215
|
+
const askQuestion = {
|
|
2216
|
+
flex: "none",
|
|
2217
|
+
margin: 0,
|
|
2218
|
+
color: "var(--dsw-alias-label-primary)",
|
|
2219
|
+
fontWeight: 600,
|
|
2220
|
+
whiteSpace: "pre-wrap",
|
|
2221
|
+
wordBreak: "break-word"
|
|
2222
|
+
};
|
|
2223
|
+
const askTextarea = {
|
|
2224
|
+
width: "100%",
|
|
2225
|
+
minHeight: 64,
|
|
2226
|
+
boxSizing: "border-box",
|
|
2227
|
+
padding: "8px 10px",
|
|
2228
|
+
border: askSurfaceBorder,
|
|
2229
|
+
borderRadius: 8,
|
|
2230
|
+
outline: "none",
|
|
2231
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
2232
|
+
color: "var(--dsw-alias-label-primary)",
|
|
2233
|
+
font: "inherit",
|
|
2234
|
+
fontSize: 13,
|
|
2235
|
+
lineHeight: "20px",
|
|
2236
|
+
resize: "vertical"
|
|
2237
|
+
};
|
|
2238
|
+
const askActions = {
|
|
2239
|
+
flex: "none",
|
|
2240
|
+
display: "flex",
|
|
2241
|
+
alignItems: "center",
|
|
2242
|
+
justifyContent: "flex-end",
|
|
2243
|
+
gap: 6
|
|
2244
|
+
};
|
|
2245
|
+
const askAnswer = {
|
|
2246
|
+
flex: "1 1 auto",
|
|
2247
|
+
minHeight: 0,
|
|
2248
|
+
overflowY: "auto",
|
|
2249
|
+
padding: "2px 2px 0",
|
|
2250
|
+
wordBreak: "break-word"
|
|
2251
|
+
};
|
|
2252
|
+
const askButton = {
|
|
2253
|
+
minHeight: 26,
|
|
2254
|
+
padding: "3px 10px",
|
|
2255
|
+
border: askSurfaceBorder,
|
|
2256
|
+
borderRadius: 7,
|
|
2257
|
+
outline: "none",
|
|
2258
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
2259
|
+
color: "var(--dsw-alias-label-primary)",
|
|
2260
|
+
font: "inherit",
|
|
2261
|
+
fontSize: 12,
|
|
2262
|
+
lineHeight: "18px",
|
|
2263
|
+
fontWeight: 600,
|
|
2264
|
+
cursor: "pointer"
|
|
2265
|
+
};
|
|
2266
|
+
const askPrimaryButton = {
|
|
2267
|
+
border: "1px solid transparent",
|
|
2268
|
+
background: "var(--dsw-static-blue-450)",
|
|
2269
|
+
color: "var(--dsw-alias-label-on-accent, #fff)"
|
|
2270
|
+
};
|
|
2271
|
+
const askThinkingRow = {
|
|
2272
|
+
width: "100%",
|
|
2273
|
+
display: "flex",
|
|
2274
|
+
alignItems: "baseline",
|
|
2275
|
+
gap: 6,
|
|
2276
|
+
margin: "0 0 8px",
|
|
2277
|
+
padding: 0,
|
|
2278
|
+
border: "none",
|
|
2279
|
+
outline: "none",
|
|
2280
|
+
background: "transparent",
|
|
2281
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
2282
|
+
font: "inherit",
|
|
2283
|
+
fontSize: 12,
|
|
2284
|
+
lineHeight: "18px",
|
|
2285
|
+
textAlign: "left",
|
|
2286
|
+
cursor: "pointer"
|
|
2287
|
+
};
|
|
2288
|
+
const askThinkingLabel = {
|
|
2289
|
+
flex: "none",
|
|
2290
|
+
fontWeight: 600
|
|
2291
|
+
};
|
|
2292
|
+
const askThinkingPreview = {
|
|
2293
|
+
minWidth: 0,
|
|
2294
|
+
flex: 1,
|
|
2295
|
+
overflow: "hidden",
|
|
2296
|
+
textOverflow: "ellipsis",
|
|
2297
|
+
whiteSpace: "nowrap"
|
|
2298
|
+
};
|
|
2299
|
+
const askThinkingFull = {
|
|
2300
|
+
minWidth: 0,
|
|
2301
|
+
flex: 1,
|
|
2302
|
+
maxHeight: 200,
|
|
2303
|
+
overflowY: "auto",
|
|
2304
|
+
whiteSpace: "pre-wrap",
|
|
2305
|
+
wordBreak: "break-word"
|
|
2306
|
+
};
|
|
2307
|
+
const askToolRow = {
|
|
2308
|
+
display: "flex",
|
|
2309
|
+
alignItems: "baseline",
|
|
2310
|
+
gap: 6,
|
|
2311
|
+
margin: "2px 0 6px",
|
|
2312
|
+
minWidth: 0,
|
|
2313
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
2314
|
+
fontSize: 12,
|
|
2315
|
+
lineHeight: "18px"
|
|
2316
|
+
};
|
|
2317
|
+
const askToolGlyph = {
|
|
2318
|
+
flex: "none",
|
|
2319
|
+
width: 14,
|
|
2320
|
+
textAlign: "center",
|
|
2321
|
+
color: "var(--dsw-static-blue-450)"
|
|
2322
|
+
};
|
|
2323
|
+
const askToolGlyphDone = { color: "var(--dsw-alias-state-success-primary)" };
|
|
2324
|
+
const askToolGlyphError = { color: "var(--dsw-alias-state-error-primary)" };
|
|
2325
|
+
const askToolName = {
|
|
2326
|
+
flex: "none",
|
|
2327
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
2328
|
+
fontWeight: 600
|
|
2329
|
+
};
|
|
2330
|
+
const askToolSummary = {
|
|
2331
|
+
minWidth: 0,
|
|
2332
|
+
flex: 1,
|
|
2333
|
+
overflow: "hidden",
|
|
2334
|
+
fontFamily: "var(--dsw-font-family-code, ui-monospace, monospace)",
|
|
2335
|
+
fontSize: 11,
|
|
2336
|
+
textOverflow: "ellipsis",
|
|
2337
|
+
whiteSpace: "nowrap"
|
|
2338
|
+
};
|
|
2339
|
+
const askStatus = {
|
|
2340
|
+
marginRight: "auto",
|
|
2341
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
2342
|
+
fontSize: 12
|
|
2343
|
+
};
|
|
2344
|
+
const askError = {
|
|
2345
|
+
margin: 0,
|
|
2346
|
+
color: "var(--dsw-alias-state-error-primary)",
|
|
2347
|
+
fontSize: 12
|
|
2348
|
+
};
|
|
2011
2349
|
const repositoryMergeTrigger = {
|
|
2012
2350
|
flex: "none",
|
|
2013
2351
|
display: "inline-flex",
|
|
@@ -2037,8 +2375,11 @@ window.__ModuleLoader__.load({
|
|
|
2037
2375
|
flex: none;
|
|
2038
2376
|
display: grid;
|
|
2039
2377
|
place-items: center;
|
|
2040
|
-
|
|
2041
|
-
|
|
2378
|
+
/* Stay on the line-number row: a wrapped line makes the flex row taller, and
|
|
2379
|
+
centering would float the button into the middle of the wrapped block.
|
|
2380
|
+
The margin centers the 18px button inside the first 22px line box. */
|
|
2381
|
+
align-self: flex-start;
|
|
2382
|
+
margin: 2px 2px 0;
|
|
2042
2383
|
padding: 0;
|
|
2043
2384
|
border: none;
|
|
2044
2385
|
border-radius: 4px;
|
|
@@ -2231,10 +2572,7 @@ window.__ModuleLoader__.load({
|
|
|
2231
2572
|
const diffPanel = {
|
|
2232
2573
|
display: "flex",
|
|
2233
2574
|
flexDirection: "column",
|
|
2234
|
-
width: "calc(100% - 16px)",
|
|
2235
|
-
height: "calc(100% - 16px)",
|
|
2236
2575
|
minWidth: 0,
|
|
2237
|
-
margin: 8,
|
|
2238
2576
|
overflow: "hidden",
|
|
2239
2577
|
border: "1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 16%, transparent))",
|
|
2240
2578
|
borderRadius: 12,
|
|
@@ -2349,26 +2687,41 @@ window.__ModuleLoader__.load({
|
|
|
2349
2687
|
background: "var(--dsw-alias-bg-layer-1)",
|
|
2350
2688
|
color: "var(--dsw-alias-label-primary)",
|
|
2351
2689
|
font: "inherit",
|
|
2352
|
-
fontSize:
|
|
2690
|
+
fontSize: 13,
|
|
2691
|
+
lineHeight: "20px",
|
|
2353
2692
|
textAlign: "left",
|
|
2354
2693
|
cursor: "pointer"
|
|
2355
2694
|
};
|
|
2356
2695
|
const diffFilePath = {
|
|
2357
2696
|
minWidth: 0,
|
|
2358
2697
|
flex: 1,
|
|
2698
|
+
display: "flex",
|
|
2699
|
+
alignItems: "baseline",
|
|
2700
|
+
overflow: "hidden"
|
|
2701
|
+
};
|
|
2702
|
+
/** Directory part: truncated from the left so the nearest folders stay visible. */
|
|
2703
|
+
const diffFileDir = {
|
|
2704
|
+
minWidth: 0,
|
|
2359
2705
|
overflow: "hidden",
|
|
2360
2706
|
textOverflow: "ellipsis",
|
|
2707
|
+
whiteSpace: "nowrap",
|
|
2708
|
+
direction: "rtl",
|
|
2709
|
+
textAlign: "left",
|
|
2710
|
+
color: "var(--dsw-alias-label-tertiary)"
|
|
2711
|
+
};
|
|
2712
|
+
const diffFileName = {
|
|
2713
|
+
flex: "none",
|
|
2714
|
+
fontWeight: 650,
|
|
2361
2715
|
whiteSpace: "nowrap"
|
|
2362
2716
|
};
|
|
2363
2717
|
const diffFileStats = {
|
|
2364
2718
|
flex: "none",
|
|
2365
2719
|
display: "inline-flex",
|
|
2366
2720
|
gap: 4,
|
|
2367
|
-
fontSize:
|
|
2721
|
+
fontSize: 13,
|
|
2368
2722
|
fontWeight: 650
|
|
2369
2723
|
};
|
|
2370
2724
|
const diffCode = {
|
|
2371
|
-
minWidth: "max-content",
|
|
2372
2725
|
padding: "4px 0 8px",
|
|
2373
2726
|
background: "var(--dsw-alias-bg-base)",
|
|
2374
2727
|
fontFamily: "var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Consolas, monospace)",
|
|
@@ -2378,7 +2731,12 @@ window.__ModuleLoader__.load({
|
|
|
2378
2731
|
const diffLine = {
|
|
2379
2732
|
minHeight: 17,
|
|
2380
2733
|
display: "flex",
|
|
2381
|
-
whiteSpace: "pre"
|
|
2734
|
+
whiteSpace: "pre-wrap",
|
|
2735
|
+
overflowWrap: "anywhere"
|
|
2736
|
+
};
|
|
2737
|
+
const diffLineText = {
|
|
2738
|
+
flex: 1,
|
|
2739
|
+
minWidth: 0
|
|
2382
2740
|
};
|
|
2383
2741
|
const diffLineNumber = {
|
|
2384
2742
|
width: 38,
|
|
@@ -2408,6 +2766,40 @@ window.__ModuleLoader__.load({
|
|
|
2408
2766
|
color: "var(--dsw-alias-label-tertiary)",
|
|
2409
2767
|
fontStyle: "italic"
|
|
2410
2768
|
};
|
|
2769
|
+
const diffLineSelected = {
|
|
2770
|
+
background: "color-mix(in srgb, var(--dsw-static-blue-450) 14%, transparent)",
|
|
2771
|
+
boxShadow: "inset 2px 0 0 var(--dsw-static-blue-450)"
|
|
2772
|
+
};
|
|
2773
|
+
/** Sits where the comment button, line number and marker would be so the label aligns with code. */
|
|
2774
|
+
const diffGapControls = {
|
|
2775
|
+
width: 84,
|
|
2776
|
+
flex: "none",
|
|
2777
|
+
boxSizing: "border-box",
|
|
2778
|
+
display: "inline-flex",
|
|
2779
|
+
alignItems: "center",
|
|
2780
|
+
justifyContent: "flex-end",
|
|
2781
|
+
gap: 2,
|
|
2782
|
+
paddingRight: 6
|
|
2783
|
+
};
|
|
2784
|
+
const diffGapButton = {
|
|
2785
|
+
width: 20,
|
|
2786
|
+
height: 18,
|
|
2787
|
+
display: "grid",
|
|
2788
|
+
placeItems: "center",
|
|
2789
|
+
padding: 0,
|
|
2790
|
+
border: "none",
|
|
2791
|
+
borderRadius: 4,
|
|
2792
|
+
background: "transparent",
|
|
2793
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
2794
|
+
font: "inherit",
|
|
2795
|
+
cursor: "pointer"
|
|
2796
|
+
};
|
|
2797
|
+
const diffCommentRange = {
|
|
2798
|
+
marginBottom: 6,
|
|
2799
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
2800
|
+
fontSize: 12,
|
|
2801
|
+
fontWeight: 600
|
|
2802
|
+
};
|
|
2411
2803
|
const diffLineContext = { color: "var(--dsw-alias-label-secondary)" };
|
|
2412
2804
|
const diffNotice = {
|
|
2413
2805
|
margin: 10,
|
|
@@ -2781,11 +3173,12 @@ window.__ModuleLoader__.load({
|
|
|
2781
3173
|
const clearFinished = () => setDismissedSettledIds((previous) => /* @__PURE__ */ new Set([...previous, ...tasks.filter((task) => task.status !== "running").map((task) => task.taskId)]));
|
|
2782
3174
|
if (!projection.owned) return null;
|
|
2783
3175
|
return /* @__PURE__ */ jsxs("div", {
|
|
3176
|
+
className: detailsCardClass,
|
|
2784
3177
|
style: tasksPanel,
|
|
2785
3178
|
children: [
|
|
2786
|
-
/* @__PURE__ */
|
|
3179
|
+
/* @__PURE__ */ jsxs("style", {
|
|
2787
3180
|
"data-dsh-claude-panel-icon-styles": true,
|
|
2788
|
-
children: panelIconButtonCss
|
|
3181
|
+
children: [detailsCardCss, panelIconButtonCss]
|
|
2789
3182
|
}),
|
|
2790
3183
|
/* @__PURE__ */ jsxs("div", {
|
|
2791
3184
|
style: tasksHeader,
|
|
@@ -3018,7 +3411,7 @@ window.__ModuleLoader__.load({
|
|
|
3018
3411
|
const MAX_REVIEW_COMMENTS = 50;
|
|
3019
3412
|
const MAX_REVIEW_COMMENT_CHARS = 2e3;
|
|
3020
3413
|
const MAX_TRANSCRIPT_CHARS = 64e3;
|
|
3021
|
-
function record$
|
|
3414
|
+
function record$7(value) {
|
|
3022
3415
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3023
3416
|
}
|
|
3024
3417
|
function nonNegativeInteger(value) {
|
|
@@ -3028,18 +3421,18 @@ window.__ModuleLoader__.load({
|
|
|
3028
3421
|
return value === void 0 || typeof value === "string" && value.length <= MAX_REPOSITORY_TEXT_CHARS;
|
|
3029
3422
|
}
|
|
3030
3423
|
function validateRepository(value) {
|
|
3031
|
-
const repository = record$
|
|
3424
|
+
const repository = record$7(value);
|
|
3032
3425
|
if (repository === void 0 || ![
|
|
3033
3426
|
"ready",
|
|
3034
3427
|
"not-repository",
|
|
3035
3428
|
"unavailable"
|
|
3036
3429
|
].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;
|
|
3037
3430
|
if (repository.diff !== void 0) {
|
|
3038
|
-
const diff = record$
|
|
3431
|
+
const diff = record$7(repository.diff);
|
|
3039
3432
|
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;
|
|
3040
3433
|
}
|
|
3041
3434
|
if (repository.pullRequest === void 0) return true;
|
|
3042
|
-
const pullRequest = record$
|
|
3435
|
+
const pullRequest = record$7(repository.pullRequest);
|
|
3043
3436
|
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 || ![
|
|
3044
3437
|
"open",
|
|
3045
3438
|
"closed",
|
|
@@ -3064,24 +3457,24 @@ window.__ModuleLoader__.load({
|
|
|
3064
3457
|
}
|
|
3065
3458
|
/** Validate the public route envelope before publishing it to UI components. */
|
|
3066
3459
|
function parseClaudeClientProjection(value) {
|
|
3067
|
-
const input = record$
|
|
3460
|
+
const input = record$7(value);
|
|
3068
3461
|
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");
|
|
3069
3462
|
for (const item of input.commands) {
|
|
3070
|
-
const command = record$
|
|
3463
|
+
const command = record$7(item);
|
|
3071
3464
|
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");
|
|
3072
3465
|
}
|
|
3073
3466
|
for (const item of input.activities) {
|
|
3074
|
-
const activity = record$
|
|
3467
|
+
const activity = record$7(item);
|
|
3075
3468
|
if (activity === void 0 || !nonNegativeInteger(activity.turn) || !nonNegativeInteger(activity.step) || !nonNegativeInteger(activity.ordinal) || typeof activity.kind !== "string") throw new Error("invalid Claude sidecar activity");
|
|
3076
3469
|
}
|
|
3077
|
-
if (input.contextUsage !== void 0 && record$
|
|
3078
|
-
const tasks = input.tasks === void 0 ? void 0 : record$
|
|
3470
|
+
if (input.contextUsage !== void 0 && record$7(input.contextUsage) === void 0) throw new Error("invalid Claude context projection");
|
|
3471
|
+
const tasks = input.tasks === void 0 ? void 0 : record$7(input.tasks);
|
|
3079
3472
|
if (tasks !== void 0 && !Array.isArray(tasks.tasks)) throw new Error("invalid Claude tasks projection");
|
|
3080
3473
|
if (input.repository !== void 0 && !validateRepository(input.repository)) throw new Error("invalid Claude repository projection");
|
|
3081
3474
|
if (input.reviewComments !== void 0) {
|
|
3082
3475
|
if (!Array.isArray(input.reviewComments) || input.reviewComments.length > MAX_REVIEW_COMMENTS) throw new Error("invalid Claude review comment projection");
|
|
3083
3476
|
for (const item of input.reviewComments) {
|
|
3084
|
-
const comment = record$
|
|
3477
|
+
const comment = record$7(item);
|
|
3085
3478
|
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");
|
|
3086
3479
|
}
|
|
3087
3480
|
}
|
|
@@ -3279,7 +3672,7 @@ window.__ModuleLoader__.load({
|
|
|
3279
3672
|
} catch {
|
|
3280
3673
|
return;
|
|
3281
3674
|
}
|
|
3282
|
-
const event = record$
|
|
3675
|
+
const event = record$7(value);
|
|
3283
3676
|
if (event === void 0 || typeof event.type !== "string") return;
|
|
3284
3677
|
try {
|
|
3285
3678
|
switch (event.type) {
|
|
@@ -3538,7 +3931,7 @@ window.__ModuleLoader__.load({
|
|
|
3538
3931
|
return value;
|
|
3539
3932
|
}
|
|
3540
3933
|
}
|
|
3541
|
-
function record$
|
|
3934
|
+
function record$6(value) {
|
|
3542
3935
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3543
3936
|
}
|
|
3544
3937
|
function text(value) {
|
|
@@ -3552,7 +3945,7 @@ window.__ModuleLoader__.load({
|
|
|
3552
3945
|
if (typeof value === "string") return value;
|
|
3553
3946
|
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
3554
3947
|
if (Array.isArray(value)) return value.map(displayValue).join(", ");
|
|
3555
|
-
return record$
|
|
3948
|
+
return record$6(value) === void 0 ? String(value) : Object.entries(value).map(([key, item]) => `${key}: ${displayValue(item)}`).join("\n");
|
|
3556
3949
|
}
|
|
3557
3950
|
function Section({ title, children }) {
|
|
3558
3951
|
return /* @__PURE__ */ jsxs("section", {
|
|
@@ -3622,15 +4015,15 @@ window.__ModuleLoader__.load({
|
|
|
3622
4015
|
function ToolPresentation({ tool, t }) {
|
|
3623
4016
|
const inputValue = parsedValue(tool.input);
|
|
3624
4017
|
const outputValue = parsedValue(tool.output);
|
|
3625
|
-
const input = record$
|
|
3626
|
-
const output = record$
|
|
4018
|
+
const input = record$6(inputValue);
|
|
4019
|
+
const output = record$6(outputValue);
|
|
3627
4020
|
const outputTitle = tool.isError === true ? t("toolError") : t("toolOutput");
|
|
3628
4021
|
if (tool.diffs !== void 0) return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DiffBlock, { diffs: [...tool.diffs] }), /* @__PURE__ */ jsx(TextDetail, {
|
|
3629
4022
|
title: outputTitle,
|
|
3630
4023
|
value: typeof outputValue === "string" ? outputValue : void 0
|
|
3631
4024
|
})] });
|
|
3632
4025
|
if (tool.toolName === "Read") {
|
|
3633
|
-
const file = record$
|
|
4026
|
+
const file = record$6(output?.file);
|
|
3634
4027
|
const path = text(file?.filePath) ?? text(input?.file_path);
|
|
3635
4028
|
const content = text(file?.content) ?? (typeof outputValue === "string" ? outputValue : void 0);
|
|
3636
4029
|
const offset = numberValue(input?.offset) ?? 1;
|
|
@@ -3828,7 +4221,7 @@ window.__ModuleLoader__.load({
|
|
|
3828
4221
|
if (code !== void 0) this.code = code;
|
|
3829
4222
|
}
|
|
3830
4223
|
};
|
|
3831
|
-
function record$
|
|
4224
|
+
function record$5(value) {
|
|
3832
4225
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3833
4226
|
}
|
|
3834
4227
|
async function call(path, init) {
|
|
@@ -3836,7 +4229,7 @@ window.__ModuleLoader__.load({
|
|
|
3836
4229
|
credentials: "same-origin",
|
|
3837
4230
|
...init
|
|
3838
4231
|
});
|
|
3839
|
-
const body = record$
|
|
4232
|
+
const body = record$5(await response.json());
|
|
3840
4233
|
if (!response.ok) throw new JiraClientError(typeof body?.message === "string" ? body.message : "Jira is unavailable.", typeof body?.error === "string" ? body.error : void 0);
|
|
3841
4234
|
if (body === void 0) throw new JiraClientError("Invalid Jira response.");
|
|
3842
4235
|
return body;
|
|
@@ -3877,7 +4270,7 @@ window.__ModuleLoader__.load({
|
|
|
3877
4270
|
if (!Array.isArray(body.tickets)) throw new JiraClientError("Invalid Jira search response.");
|
|
3878
4271
|
const tickets = [];
|
|
3879
4272
|
for (const item of body.tickets) {
|
|
3880
|
-
const ticket = record$
|
|
4273
|
+
const ticket = record$5(item);
|
|
3881
4274
|
if (ticket === void 0 || typeof ticket.key !== "string" || typeof ticket.summary !== "string" || typeof ticket.url !== "string") continue;
|
|
3882
4275
|
tickets.push(ticket);
|
|
3883
4276
|
}
|
|
@@ -4086,6 +4479,183 @@ window.__ModuleLoader__.load({
|
|
|
4086
4479
|
}) : null]
|
|
4087
4480
|
});
|
|
4088
4481
|
}
|
|
4482
|
+
/** Fixed windows carry a translated label; server-named model buckets (e.g.
|
|
4483
|
+
* 'Fable') arrive with their own `label` and are shown verbatim. */
|
|
4484
|
+
const TRANSLATED_WINDOWS = /* @__PURE__ */ new Set([
|
|
4485
|
+
"five_hour",
|
|
4486
|
+
"seven_day",
|
|
4487
|
+
"seven_day_opus",
|
|
4488
|
+
"seven_day_sonnet"
|
|
4489
|
+
]);
|
|
4490
|
+
/** Per-setting label and the effect note that used to sit as a standalone
|
|
4491
|
+
* paragraph under the card; it now hangs off the label as a hover hint. */
|
|
4492
|
+
const SETTING_COPY = {
|
|
4493
|
+
outputStyle: {
|
|
4494
|
+
label: "outputStyle",
|
|
4495
|
+
hint: "globalSettingsNewSession"
|
|
4496
|
+
},
|
|
4497
|
+
worktreeBranchPrefix: {
|
|
4498
|
+
label: "worktreeBranchPrefix",
|
|
4499
|
+
hint: "worktreeBranchPrefixEffect"
|
|
4500
|
+
},
|
|
4501
|
+
maxProcesses: {
|
|
4502
|
+
label: "maxProcessesSetting",
|
|
4503
|
+
hint: "maxProcessesEffect"
|
|
4504
|
+
},
|
|
4505
|
+
idleTimeoutMinutes: {
|
|
4506
|
+
label: "idleTimeoutSetting",
|
|
4507
|
+
hint: "idleTimeoutEffect"
|
|
4508
|
+
}
|
|
4509
|
+
};
|
|
4510
|
+
/** '?' badge that reveals a setting's effect note on hover or keyboard focus. */
|
|
4511
|
+
function SettingHint({ text, label }) {
|
|
4512
|
+
return /* @__PURE__ */ jsx(Tooltip, {
|
|
4513
|
+
label: text,
|
|
4514
|
+
side: "top",
|
|
4515
|
+
delayMs: 150,
|
|
4516
|
+
maxWidth: 320,
|
|
4517
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
4518
|
+
role: "note",
|
|
4519
|
+
tabIndex: 0,
|
|
4520
|
+
"aria-label": `${label}: ${text}`,
|
|
4521
|
+
style: settingHint,
|
|
4522
|
+
children: "?"
|
|
4523
|
+
})
|
|
4524
|
+
});
|
|
4525
|
+
}
|
|
4526
|
+
function isPlanUsageReport(value) {
|
|
4527
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
4528
|
+
const report = value;
|
|
4529
|
+
return typeof report.available === "boolean" && typeof report.fetchedAt === "number" && Array.isArray(report.windows) && report.windows.every((entry) => typeof entry === "object" && entry !== null && typeof entry.id === "string");
|
|
4530
|
+
}
|
|
4531
|
+
/** Coarse duration for a reset countdown or a fetch age: minutes below an
|
|
4532
|
+
* hour, then hours, then days. Never negative — a passed reset reads '0m'. */
|
|
4533
|
+
function durationLabel(milliseconds) {
|
|
4534
|
+
const minutes = Math.max(0, Math.round(milliseconds / 6e4));
|
|
4535
|
+
if (minutes < 60) return `${minutes}m`;
|
|
4536
|
+
const hours = Math.floor(minutes / 60);
|
|
4537
|
+
if (hours < 24) return minutes % 60 === 0 ? `${hours}h` : `${hours}h ${minutes % 60}m`;
|
|
4538
|
+
return `${Math.floor(hours / 24)}d`;
|
|
4539
|
+
}
|
|
4540
|
+
function PlanUsageMeter({ window: usageWindow, t, now }) {
|
|
4541
|
+
const used = usageWindow.utilization;
|
|
4542
|
+
const tone = planUsageTone(used);
|
|
4543
|
+
const resetsIn = usageWindow.resetsAt === void 0 ? void 0 : Date.parse(usageWindow.resetsAt);
|
|
4544
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
4545
|
+
style: planUsageMeter,
|
|
4546
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
4547
|
+
style: planUsageTrack,
|
|
4548
|
+
children: /* @__PURE__ */ jsx("span", { style: {
|
|
4549
|
+
...planUsageFill,
|
|
4550
|
+
width: `${used ?? 0}%`,
|
|
4551
|
+
background: tone.fill
|
|
4552
|
+
} })
|
|
4553
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
4554
|
+
style: {
|
|
4555
|
+
...planUsageMeta,
|
|
4556
|
+
color: tone.text
|
|
4557
|
+
},
|
|
4558
|
+
children: [used === void 0 ? "—" : t("planUsageUsed", { percent: Math.round(used) }), resetsIn === void 0 || !Number.isFinite(resetsIn) ? null : ` · ${t("planUsageResets", { age: durationLabel(resetsIn - now) })}`]
|
|
4559
|
+
})]
|
|
4560
|
+
});
|
|
4561
|
+
}
|
|
4562
|
+
/** Fetch the plan usage report; POST forces the backend to re-read it. */
|
|
4563
|
+
async function loadPlanUsage(refresh) {
|
|
4564
|
+
const response = await fetch(CLAUDE_USAGE_PATH, {
|
|
4565
|
+
method: refresh ? "POST" : "GET",
|
|
4566
|
+
credentials: "same-origin",
|
|
4567
|
+
headers: { accept: "application/json" }
|
|
4568
|
+
});
|
|
4569
|
+
const payload = await response.json();
|
|
4570
|
+
if (!response.ok) {
|
|
4571
|
+
const message = typeof payload === "object" && payload !== null && "error" in payload && typeof payload.error === "string" ? payload.error : `HTTP ${response.status}`;
|
|
4572
|
+
throw new Error(message);
|
|
4573
|
+
}
|
|
4574
|
+
if (!isPlanUsageReport(payload)) throw new Error("Invalid plan usage response");
|
|
4575
|
+
return payload;
|
|
4576
|
+
}
|
|
4577
|
+
function PlanUsageCard({ t, load }) {
|
|
4578
|
+
const [report, setReport] = useState();
|
|
4579
|
+
const [busy, setBusy] = useState(false);
|
|
4580
|
+
const [error, setError] = useState();
|
|
4581
|
+
const request = useCallback(async (refresh) => {
|
|
4582
|
+
setBusy(true);
|
|
4583
|
+
setError(void 0);
|
|
4584
|
+
try {
|
|
4585
|
+
setReport(await load(refresh));
|
|
4586
|
+
} catch (cause) {
|
|
4587
|
+
setError(cause instanceof Error ? cause.message : String(cause));
|
|
4588
|
+
} finally {
|
|
4589
|
+
setBusy(false);
|
|
4590
|
+
}
|
|
4591
|
+
}, [load]);
|
|
4592
|
+
useEffect(() => {
|
|
4593
|
+
request(false);
|
|
4594
|
+
}, [request]);
|
|
4595
|
+
const now = Date.now();
|
|
4596
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
4597
|
+
style: settingsCard,
|
|
4598
|
+
children: [
|
|
4599
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4600
|
+
style: settingsCardHeader,
|
|
4601
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
|
|
4602
|
+
style: settingsSectionHeading,
|
|
4603
|
+
children: t("planUsage")
|
|
4604
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
4605
|
+
style: settingsBody,
|
|
4606
|
+
children: t("planUsageBody")
|
|
4607
|
+
})] }), /* @__PURE__ */ jsx("button", {
|
|
4608
|
+
type: "button",
|
|
4609
|
+
style: button,
|
|
4610
|
+
disabled: busy,
|
|
4611
|
+
onClick: () => {
|
|
4612
|
+
request(true);
|
|
4613
|
+
},
|
|
4614
|
+
children: busy ? t("planUsageRefreshing") : t("planUsageRefresh")
|
|
4615
|
+
})]
|
|
4616
|
+
}),
|
|
4617
|
+
report === void 0 ? /* @__PURE__ */ jsx("p", {
|
|
4618
|
+
style: notice,
|
|
4619
|
+
children: busy ? t("planUsageLoading") : t("planUsageNever")
|
|
4620
|
+
}) : report.windows.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
4621
|
+
style: notice,
|
|
4622
|
+
children: report.fetchedAt === 0 ? t("planUsageNever") : t("planUsageUnavailable")
|
|
4623
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
4624
|
+
style: diagnosticGrid,
|
|
4625
|
+
children: [report.subscription === void 0 ? null : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
|
|
4626
|
+
style: diagnosticLabel,
|
|
4627
|
+
children: t("planUsageSubscription")
|
|
4628
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
4629
|
+
style: diagnosticValue,
|
|
4630
|
+
children: report.subscription
|
|
4631
|
+
})] }), report.windows.flatMap((usageWindow) => [/* @__PURE__ */ jsx("span", {
|
|
4632
|
+
style: diagnosticLabel,
|
|
4633
|
+
children: usageWindow.label ?? (TRANSLATED_WINDOWS.has(usageWindow.id) ? t(`planWindow_${usageWindow.id}`) : usageWindow.id)
|
|
4634
|
+
}, `${usageWindow.id}-label`), /* @__PURE__ */ jsx(PlanUsageMeter, {
|
|
4635
|
+
window: usageWindow,
|
|
4636
|
+
t,
|
|
4637
|
+
now
|
|
4638
|
+
}, `${usageWindow.id}-meter`)])]
|
|
4639
|
+
}),
|
|
4640
|
+
report !== void 0 && report.fetchedAt > 0 ? /* @__PURE__ */ jsx("p", {
|
|
4641
|
+
style: notice,
|
|
4642
|
+
children: t("planUsageUpdated", { age: durationLabel(now - report.fetchedAt) })
|
|
4643
|
+
}) : null,
|
|
4644
|
+
error === void 0 ? null : /* @__PURE__ */ jsxs("p", {
|
|
4645
|
+
role: "alert",
|
|
4646
|
+
style: {
|
|
4647
|
+
...notice,
|
|
4648
|
+
color: "var(--dsw-alias-state-error-primary)"
|
|
4649
|
+
},
|
|
4650
|
+
children: [
|
|
4651
|
+
t("planUsageError"),
|
|
4652
|
+
": ",
|
|
4653
|
+
error
|
|
4654
|
+
]
|
|
4655
|
+
})
|
|
4656
|
+
]
|
|
4657
|
+
});
|
|
4658
|
+
}
|
|
4089
4659
|
function ClaudeCodeSettings({ t }) {
|
|
4090
4660
|
const [report, setReport] = useState();
|
|
4091
4661
|
const [error, setError] = useState();
|
|
@@ -4290,6 +4860,10 @@ window.__ModuleLoader__.load({
|
|
|
4290
4860
|
})
|
|
4291
4861
|
]
|
|
4292
4862
|
}),
|
|
4863
|
+
/* @__PURE__ */ jsx(PlanUsageCard, {
|
|
4864
|
+
t,
|
|
4865
|
+
load: loadPlanUsage
|
|
4866
|
+
}),
|
|
4293
4867
|
/* @__PURE__ */ jsxs("section", {
|
|
4294
4868
|
style: settingsCard,
|
|
4295
4869
|
children: [
|
|
@@ -4303,37 +4877,31 @@ window.__ModuleLoader__.load({
|
|
|
4303
4877
|
globalSettings === void 0 ? /* @__PURE__ */ jsx("p", {
|
|
4304
4878
|
style: notice,
|
|
4305
4879
|
children: t("globalSettingsLoading")
|
|
4306
|
-
}) : globalSettings.settings.map((setting) =>
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
style:
|
|
4310
|
-
children:
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
}
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
}
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
children: t("worktreeBranchPrefixEffect")
|
|
4332
|
-
}) : null,
|
|
4333
|
-
globalSettings?.settings.some((setting) => setting.key === "maxProcesses") === true ? /* @__PURE__ */ jsx("p", {
|
|
4334
|
-
style: notice,
|
|
4335
|
-
children: t("limitsSettingEffect")
|
|
4336
|
-
}) : null,
|
|
4880
|
+
}) : globalSettings.settings.map((setting) => {
|
|
4881
|
+
const copy = SETTING_COPY[setting.key];
|
|
4882
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4883
|
+
style: diagnosticGrid,
|
|
4884
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
4885
|
+
style: diagnosticLabel,
|
|
4886
|
+
children: [copy === void 0 ? setting.key : t(copy.label), copy === void 0 ? null : /* @__PURE__ */ jsx(SettingHint, {
|
|
4887
|
+
text: t(copy.hint),
|
|
4888
|
+
label: t("settingHint")
|
|
4889
|
+
})]
|
|
4890
|
+
}), setting.kind === "select" ? /* @__PURE__ */ jsx(GlobalSettingSelect, {
|
|
4891
|
+
setting,
|
|
4892
|
+
disabled: globalSettingsBusy,
|
|
4893
|
+
onChange: (nextValue) => {
|
|
4894
|
+
requestGlobalSettings({ [setting.key]: nextValue });
|
|
4895
|
+
}
|
|
4896
|
+
}) : /* @__PURE__ */ jsx(GlobalSettingText, {
|
|
4897
|
+
setting,
|
|
4898
|
+
disabled: globalSettingsBusy,
|
|
4899
|
+
onChange: (nextValue) => {
|
|
4900
|
+
requestGlobalSettings({ [setting.key]: nextValue });
|
|
4901
|
+
}
|
|
4902
|
+
})]
|
|
4903
|
+
}, setting.key);
|
|
4904
|
+
}),
|
|
4337
4905
|
globalSettingsError === void 0 ? null : /* @__PURE__ */ jsxs("p", {
|
|
4338
4906
|
role: "alert",
|
|
4339
4907
|
style: {
|
|
@@ -4580,33 +5148,33 @@ window.__ModuleLoader__.load({
|
|
|
4580
5148
|
if (commit !== void 0) this.commit = commit;
|
|
4581
5149
|
}
|
|
4582
5150
|
};
|
|
4583
|
-
function record$
|
|
5151
|
+
function record$4(value) {
|
|
4584
5152
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
4585
5153
|
}
|
|
4586
5154
|
async function response$1(pending) {
|
|
4587
5155
|
const result = await pending;
|
|
4588
5156
|
const body = await result.json();
|
|
4589
5157
|
if (!result.ok) {
|
|
4590
|
-
const error = record$
|
|
5158
|
+
const error = record$4(body);
|
|
4591
5159
|
throw new RepositoryActionClientError(typeof error?.message === "string" ? error.message : "Repository action failed.", typeof error?.error === "string" ? error.error : void 0, typeof error?.commit === "string" ? error.commit : void 0);
|
|
4592
5160
|
}
|
|
4593
5161
|
return body;
|
|
4594
5162
|
}
|
|
4595
5163
|
function preview(value) {
|
|
4596
|
-
const input = record$
|
|
5164
|
+
const input = record$4(value);
|
|
4597
5165
|
if (input === void 0 || typeof input.root !== "string" || typeof input.branch !== "string" || typeof input.head !== "string" || typeof input.fingerprint !== "string" || !Array.isArray(input.files) || typeof input.patch !== "string" || typeof input.truncated !== "boolean" || typeof input.hasStaged !== "boolean" || typeof input.hasUnstaged !== "boolean" || typeof input.hasUntracked !== "boolean" || input.upstream !== void 0 && typeof input.upstream !== "string" || !Array.isArray(input.unpushedCommits) || typeof input.unpushedTruncated !== "boolean") throw new Error("Invalid repository action preview.");
|
|
4598
5166
|
for (const file of input.files) {
|
|
4599
|
-
const item = record$
|
|
5167
|
+
const item = record$4(file);
|
|
4600
5168
|
if (item === void 0 || typeof item.path !== "string" || typeof item.staged !== "boolean" || typeof item.unstaged !== "boolean" || typeof item.untracked !== "boolean") throw new Error("Invalid repository action file.");
|
|
4601
5169
|
}
|
|
4602
5170
|
for (const commit of input.unpushedCommits) {
|
|
4603
|
-
const item = record$
|
|
5171
|
+
const item = record$4(commit);
|
|
4604
5172
|
if (item === void 0 || typeof item.hash !== "string" || typeof item.subject !== "string") throw new Error("Invalid repository action commit.");
|
|
4605
5173
|
}
|
|
4606
5174
|
return input;
|
|
4607
5175
|
}
|
|
4608
5176
|
function result(value) {
|
|
4609
|
-
const input = record$
|
|
5177
|
+
const input = record$4(value);
|
|
4610
5178
|
if (input === void 0 || typeof input.commit !== "string" || typeof input.pushed !== "boolean" || input.pullRequestUrl !== void 0 && typeof input.pullRequestUrl !== "string" || input.conflicts !== void 0 && (!Array.isArray(input.conflicts) || input.conflicts.some((item) => typeof item !== "string"))) throw new Error("Invalid repository action result.");
|
|
4611
5179
|
return input;
|
|
4612
5180
|
}
|
|
@@ -4622,7 +5190,7 @@ window.__ModuleLoader__.load({
|
|
|
4622
5190
|
})));
|
|
4623
5191
|
}
|
|
4624
5192
|
async function generateCommitMessage(sessionId, fingerprint, signal) {
|
|
4625
|
-
const value = record$
|
|
5193
|
+
const value = record$4(await response$1(fetch(endpoint("/message", sessionId), {
|
|
4626
5194
|
method: "POST",
|
|
4627
5195
|
credentials: "same-origin",
|
|
4628
5196
|
headers: {
|
|
@@ -4655,16 +5223,16 @@ window.__ModuleLoader__.load({
|
|
|
4655
5223
|
"saving-worktree",
|
|
4656
5224
|
"switching-branch"
|
|
4657
5225
|
]);
|
|
4658
|
-
function record$
|
|
5226
|
+
function record$3(value) {
|
|
4659
5227
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
4660
5228
|
}
|
|
4661
5229
|
function setupResult(value) {
|
|
4662
|
-
const item = record$
|
|
5230
|
+
const item = record$3(value);
|
|
4663
5231
|
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
5232
|
return item;
|
|
4665
5233
|
}
|
|
4666
5234
|
function parseRepositorySetupEvent(line, onProgress) {
|
|
4667
|
-
const event = record$
|
|
5235
|
+
const event = record$3(JSON.parse(line));
|
|
4668
5236
|
if (event?.type === "progress" && typeof event.stage === "string" && HOST_STAGES.has(event.stage)) {
|
|
4669
5237
|
onProgress(event.stage);
|
|
4670
5238
|
return;
|
|
@@ -4685,12 +5253,15 @@ window.__ModuleLoader__.load({
|
|
|
4685
5253
|
}
|
|
4686
5254
|
return body;
|
|
4687
5255
|
}
|
|
5256
|
+
/** A wedged host must surface as an error; the hero has no other way out of its loading state. */
|
|
5257
|
+
const BRANCH_LOAD_TIMEOUT_MS = 15e3;
|
|
4688
5258
|
function loadRepositoryBranches(cwd, signal) {
|
|
5259
|
+
const timeout = AbortSignal.timeout(BRANCH_LOAD_TIMEOUT_MS);
|
|
4689
5260
|
return response(fetch(`${CLAUDE_REPOSITORY_SETUP_PATH}/branches?cwd=${encodeURIComponent(cwd)}`, {
|
|
4690
5261
|
method: "GET",
|
|
4691
5262
|
credentials: "same-origin",
|
|
4692
5263
|
headers: { accept: "application/json" },
|
|
4693
|
-
|
|
5264
|
+
signal: signal === void 0 ? timeout : AbortSignal.any([signal, timeout])
|
|
4694
5265
|
}));
|
|
4695
5266
|
}
|
|
4696
5267
|
async function prepareRepository(cwd, branch, worktree, branchName, onProgress = () => {}) {
|
|
@@ -4766,6 +5337,21 @@ window.__ModuleLoader__.load({
|
|
|
4766
5337
|
if (body.mode !== "worktree" && body.mode !== "checkout" || typeof body.root !== "string" || typeof body.branch !== "string") throw new Error("Invalid repository cleanup response.");
|
|
4767
5338
|
return body;
|
|
4768
5339
|
}
|
|
5340
|
+
/** Lines [from, to] of a working-tree file plus its total line count, for expanding unmodified diff context. */
|
|
5341
|
+
async function loadRepositoryFileLines(cwd, path, from, to, signal) {
|
|
5342
|
+
const query = `cwd=${encodeURIComponent(cwd)}&path=${encodeURIComponent(path)}&from=${from}&to=${to}`;
|
|
5343
|
+
const body = await response(fetch(`${CLAUDE_REPOSITORY_FILE_PATH}?${query}`, {
|
|
5344
|
+
method: "GET",
|
|
5345
|
+
credentials: "same-origin",
|
|
5346
|
+
headers: { accept: "application/json" },
|
|
5347
|
+
...signal === void 0 ? {} : { signal }
|
|
5348
|
+
}));
|
|
5349
|
+
if (!Array.isArray(body.lines) || typeof body.total !== "number") throw new Error("Invalid repository file response.");
|
|
5350
|
+
return {
|
|
5351
|
+
lines: body.lines.map(String),
|
|
5352
|
+
total: body.total
|
|
5353
|
+
};
|
|
5354
|
+
}
|
|
4769
5355
|
async function loadRepositoryStatusFor(cwd, signal) {
|
|
4770
5356
|
const body = await response(fetch(`${CLAUDE_REPOSITORY_STATUS_PATH}?cwd=${encodeURIComponent(cwd)}`, {
|
|
4771
5357
|
method: "GET",
|
|
@@ -4778,7 +5364,7 @@ window.__ModuleLoader__.load({
|
|
|
4778
5364
|
}
|
|
4779
5365
|
//#endregion
|
|
4780
5366
|
//#region src/client/pr-feedback-api.ts
|
|
4781
|
-
function record$
|
|
5367
|
+
function record$2(value) {
|
|
4782
5368
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
4783
5369
|
}
|
|
4784
5370
|
async function loadJson(path, sessionId, pullNumber, signal) {
|
|
@@ -4788,7 +5374,7 @@ window.__ModuleLoader__.load({
|
|
|
4788
5374
|
headers: { accept: "application/json" },
|
|
4789
5375
|
...signal === void 0 ? {} : { signal }
|
|
4790
5376
|
});
|
|
4791
|
-
const body = record$
|
|
5377
|
+
const body = record$2(await response.json());
|
|
4792
5378
|
if (!response.ok) throw new Error(typeof body?.message === "string" ? body.message : "Pull request feedback is unavailable.");
|
|
4793
5379
|
if (body === void 0) throw new Error("Invalid pull request feedback response.");
|
|
4794
5380
|
return body;
|
|
@@ -4798,7 +5384,7 @@ window.__ModuleLoader__.load({
|
|
|
4798
5384
|
if (!Array.isArray(body.comments)) throw new Error("Invalid pull request comments response.");
|
|
4799
5385
|
const comments = [];
|
|
4800
5386
|
for (const item of body.comments) {
|
|
4801
|
-
const input = record$
|
|
5387
|
+
const input = record$2(item);
|
|
4802
5388
|
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
5389
|
comments.push(input);
|
|
4804
5390
|
}
|
|
@@ -4809,7 +5395,7 @@ window.__ModuleLoader__.load({
|
|
|
4809
5395
|
if (!Array.isArray(body.checks)) throw new Error("Invalid pull request checks response.");
|
|
4810
5396
|
const checks = [];
|
|
4811
5397
|
for (const item of body.checks) {
|
|
4812
|
-
const input = record$
|
|
5398
|
+
const input = record$2(item);
|
|
4813
5399
|
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;
|
|
4814
5400
|
checks.push(input);
|
|
4815
5401
|
}
|
|
@@ -4882,29 +5468,60 @@ window.__ModuleLoader__.load({
|
|
|
4882
5468
|
}
|
|
4883
5469
|
//#endregion
|
|
4884
5470
|
//#region src/client/ClaudeRepositoryStatus.tsx
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
/** Whether the newest quota update in the activity feed reports a blocked state. */
|
|
4888
|
-
function rateLimitBlocked(activities) {
|
|
4889
|
-
for (let index = activities.length - 1; index >= 0; index -= 1) {
|
|
4890
|
-
const title = activities[index]?.title;
|
|
4891
|
-
if (title?.startsWith(RATE_LIMIT_TITLE_PREFIX) === true) return title === RATE_LIMIT_BLOCKING_TITLE;
|
|
4892
|
-
}
|
|
4893
|
-
return false;
|
|
4894
|
-
}
|
|
4895
|
-
function StatusItem({ label, tone = "neutral" }) {
|
|
5471
|
+
/** Icon-only status: the tone carries the state, the full label lives in the tooltip and accessible name. */
|
|
5472
|
+
function StatusGlyph({ label, tone, children }) {
|
|
4896
5473
|
const toneStyle = tone === "success" ? repositoryItemSuccess : tone === "warning" ? repositoryItemWarning : tone === "error" ? repositoryItemError : {};
|
|
4897
|
-
return /* @__PURE__ */
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
5474
|
+
return /* @__PURE__ */ jsx(Tooltip, {
|
|
5475
|
+
label,
|
|
5476
|
+
side: "top",
|
|
5477
|
+
delayMs: 250,
|
|
5478
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
5479
|
+
role: "img",
|
|
5480
|
+
"aria-label": label,
|
|
5481
|
+
style: {
|
|
5482
|
+
...repositoryGlyph,
|
|
5483
|
+
...toneStyle
|
|
5484
|
+
},
|
|
5485
|
+
children
|
|
5486
|
+
})
|
|
5487
|
+
});
|
|
5488
|
+
}
|
|
5489
|
+
function ChecksGlyph({ state }) {
|
|
5490
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
5491
|
+
width: "14",
|
|
5492
|
+
height: "14",
|
|
5493
|
+
viewBox: "0 0 14 14",
|
|
5494
|
+
fill: "none",
|
|
5495
|
+
stroke: "currentColor",
|
|
5496
|
+
strokeWidth: "1.5",
|
|
5497
|
+
strokeLinecap: "round",
|
|
5498
|
+
strokeLinejoin: "round",
|
|
5499
|
+
"aria-hidden": "true",
|
|
5500
|
+
children: [/* @__PURE__ */ jsx("circle", {
|
|
5501
|
+
cx: "7",
|
|
5502
|
+
cy: "7",
|
|
5503
|
+
r: "5.5"
|
|
5504
|
+
}), state === "passing" ? /* @__PURE__ */ jsx("path", { d: "M4.5 7.2l1.8 1.8 3.2-3.6" }) : state === "failing" ? /* @__PURE__ */ jsx("path", { d: "M5 5l4 4M9 5l-4 4" }) : /* @__PURE__ */ jsx("path", {
|
|
5505
|
+
d: "M4.6 7h.01M7 7h.01M9.4 7h.01",
|
|
5506
|
+
strokeWidth: "2"
|
|
5507
|
+
})]
|
|
5508
|
+
});
|
|
5509
|
+
}
|
|
5510
|
+
function ReviewGlyph() {
|
|
5511
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
5512
|
+
width: "14",
|
|
5513
|
+
height: "14",
|
|
5514
|
+
viewBox: "0 0 14 14",
|
|
5515
|
+
fill: "none",
|
|
5516
|
+
stroke: "currentColor",
|
|
5517
|
+
strokeWidth: "1.5",
|
|
5518
|
+
strokeLinecap: "round",
|
|
5519
|
+
strokeLinejoin: "round",
|
|
5520
|
+
"aria-hidden": "true",
|
|
5521
|
+
children: [/* @__PURE__ */ jsx("path", { d: "M1.5 7s2-3.5 5.5-3.5S12.5 7 12.5 7s-2 3.5-5.5 3.5S1.5 7 1.5 7Z" }), /* @__PURE__ */ jsx("circle", {
|
|
5522
|
+
cx: "7",
|
|
5523
|
+
cy: "7",
|
|
5524
|
+
r: "1.8"
|
|
4908
5525
|
})]
|
|
4909
5526
|
});
|
|
4910
5527
|
}
|
|
@@ -5233,9 +5850,10 @@ window.__ModuleLoader__.load({
|
|
|
5233
5850
|
"aria-expanded": open,
|
|
5234
5851
|
"aria-label": t("repositoryChecksOpen"),
|
|
5235
5852
|
onClick: toggle,
|
|
5236
|
-
children: /* @__PURE__ */ jsx(
|
|
5853
|
+
children: /* @__PURE__ */ jsx(StatusGlyph, {
|
|
5237
5854
|
label: t("repositoryChecks_failing"),
|
|
5238
|
-
tone: "error"
|
|
5855
|
+
tone: "error",
|
|
5856
|
+
children: /* @__PURE__ */ jsx(ChecksGlyph, { state: "failing" })
|
|
5239
5857
|
})
|
|
5240
5858
|
}), open ? /* @__PURE__ */ jsxs("span", {
|
|
5241
5859
|
role: "dialog",
|
|
@@ -5745,25 +6363,17 @@ window.__ModuleLoader__.load({
|
|
|
5745
6363
|
const aheadCount = repository.ahead ?? 0;
|
|
5746
6364
|
const pushable = repository.remote !== void 0 && repository.detached !== true && (aheadCount > 0 || repository.upstream === false);
|
|
5747
6365
|
const hasDiff = repository.diff !== void 0 && (repository.diff.additions > 0 || repository.diff.deletions > 0);
|
|
5748
|
-
const rateLimited = rateLimitBlocked(projection.activities);
|
|
5749
6366
|
if (repository.status !== "ready") return /* @__PURE__ */ jsx("div", {
|
|
5750
6367
|
style: repositoryBarFrame,
|
|
5751
6368
|
children: /* @__PURE__ */ jsxs("div", {
|
|
5752
6369
|
style: repositoryBar,
|
|
5753
|
-
children: [
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
children: repository.status === "not-repository" ? t("repositoryNotGit") : t("repositoryUnavailable")
|
|
5761
|
-
}),
|
|
5762
|
-
rateLimited ? /* @__PURE__ */ jsx(StatusItem, {
|
|
5763
|
-
label: t("repositoryRateLimited"),
|
|
5764
|
-
tone: "warning"
|
|
5765
|
-
}) : null
|
|
5766
|
-
]
|
|
6370
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
6371
|
+
style: repositoryPrIcon,
|
|
6372
|
+
children: /* @__PURE__ */ jsx(PullRequestIcon, {})
|
|
6373
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
6374
|
+
style: repositoryPrimary,
|
|
6375
|
+
children: repository.status === "not-repository" ? t("repositoryNotGit") : t("repositoryUnavailable")
|
|
6376
|
+
})]
|
|
5767
6377
|
})
|
|
5768
6378
|
});
|
|
5769
6379
|
return /* @__PURE__ */ jsx("div", {
|
|
@@ -5810,81 +6420,76 @@ window.__ModuleLoader__.load({
|
|
|
5810
6420
|
}) : null,
|
|
5811
6421
|
/* @__PURE__ */ jsxs("span", {
|
|
5812
6422
|
style: repositoryStatusItems,
|
|
5813
|
-
children: [
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
children: [
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
pullRequest === void 0 ? null : merged ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
|
|
5838
|
-
style: repositoryMergedStatus,
|
|
5839
|
-
children: [
|
|
5840
|
-
/* @__PURE__ */ jsx("span", {
|
|
5841
|
-
style: repositoryMergedDot,
|
|
5842
|
-
"aria-hidden": "true"
|
|
5843
|
-
}),
|
|
5844
|
-
t("repositoryState_merged"),
|
|
5845
|
-
mergedAge === void 0 ? null : /* @__PURE__ */ jsxs("span", {
|
|
5846
|
-
style: repositoryMergedAge,
|
|
5847
|
-
children: ["· ", t("repositoryMergedAgo", { age: mergedAge })]
|
|
5848
|
-
})
|
|
5849
|
-
]
|
|
5850
|
-
}), /* @__PURE__ */ jsx(CleanupControl, {
|
|
5851
|
-
repository,
|
|
5852
|
-
t,
|
|
5853
|
-
...deleteWorkspace === void 0 ? {} : { deleteWorkspace }
|
|
5854
|
-
})] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
5855
|
-
pullRequest.checks === "failing" ? /* @__PURE__ */ jsx(FailingChecksControl, {
|
|
5856
|
-
sessionId,
|
|
5857
|
-
pullNumber: pullRequest.number,
|
|
5858
|
-
t,
|
|
5859
|
-
...submitPrompt === void 0 ? {} : { submitPrompt }
|
|
5860
|
-
}) : pullRequest.checks === "none" ? null : /* @__PURE__ */ jsx(StatusItem, {
|
|
5861
|
-
label: t(`repositoryChecks_${pullRequest.checks}`),
|
|
5862
|
-
tone: pullRequest.checks === "passing" ? "success" : "warning"
|
|
5863
|
-
}),
|
|
5864
|
-
pullRequest.review === "none" ? null : /* @__PURE__ */ jsx(StatusItem, {
|
|
5865
|
-
label: t(`repositoryReview_${pullRequest.review}`),
|
|
5866
|
-
tone: pullRequest.review === "approved" ? "success" : pullRequest.review === "changes-requested" ? "error" : "neutral"
|
|
5867
|
-
}),
|
|
5868
|
-
/* @__PURE__ */ jsx(AutoFixControl, {
|
|
5869
|
-
sessionId,
|
|
5870
|
-
repository,
|
|
5871
|
-
running,
|
|
5872
|
-
t,
|
|
5873
|
-
...submitPrompt === void 0 ? {} : { submitPrompt }
|
|
5874
|
-
}),
|
|
5875
|
-
/* @__PURE__ */ jsx(UpdateBranchControl, {
|
|
5876
|
-
sessionId,
|
|
5877
|
-
repository,
|
|
5878
|
-
t,
|
|
5879
|
-
...submitPrompt === void 0 ? {} : { submitPrompt }
|
|
6423
|
+
children: [hasDiff || pushable ? /* @__PURE__ */ jsxs("button", {
|
|
6424
|
+
type: "button",
|
|
6425
|
+
style: {
|
|
6426
|
+
...diffTrigger,
|
|
6427
|
+
...merged ? diffTriggerMuted : {}
|
|
6428
|
+
},
|
|
6429
|
+
onClick: openDiff,
|
|
6430
|
+
"aria-label": t("diffOpen"),
|
|
6431
|
+
children: [hasDiff && repository.diff !== void 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
|
|
6432
|
+
style: merged ? diffAddMuted : diffAdd,
|
|
6433
|
+
children: ["+", repository.diff.additions]
|
|
6434
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
6435
|
+
style: merged ? diffDeleteMuted : diffDelete,
|
|
6436
|
+
children: ["−", repository.diff.deletions]
|
|
6437
|
+
})] }) : null, pushable ? /* @__PURE__ */ jsxs("span", {
|
|
6438
|
+
style: merged ? diffAheadMuted : diffAhead,
|
|
6439
|
+
children: ["↑", aheadCount > 0 ? aheadCount : ""]
|
|
6440
|
+
}) : null]
|
|
6441
|
+
}) : null, pullRequest === void 0 ? null : merged ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
|
|
6442
|
+
style: repositoryMergedStatus,
|
|
6443
|
+
children: [
|
|
6444
|
+
/* @__PURE__ */ jsx("span", {
|
|
6445
|
+
style: repositoryMergedDot,
|
|
6446
|
+
"aria-hidden": "true"
|
|
5880
6447
|
}),
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
t
|
|
6448
|
+
t("repositoryState_merged"),
|
|
6449
|
+
mergedAge === void 0 ? null : /* @__PURE__ */ jsxs("span", {
|
|
6450
|
+
style: repositoryMergedAge,
|
|
6451
|
+
children: ["· ", t("repositoryMergedAgo", { age: mergedAge })]
|
|
5885
6452
|
})
|
|
5886
|
-
]
|
|
5887
|
-
|
|
6453
|
+
]
|
|
6454
|
+
}), /* @__PURE__ */ jsx(CleanupControl, {
|
|
6455
|
+
repository,
|
|
6456
|
+
t,
|
|
6457
|
+
...deleteWorkspace === void 0 ? {} : { deleteWorkspace }
|
|
6458
|
+
})] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
6459
|
+
pullRequest.checks === "failing" ? /* @__PURE__ */ jsx(FailingChecksControl, {
|
|
6460
|
+
sessionId,
|
|
6461
|
+
pullNumber: pullRequest.number,
|
|
6462
|
+
t,
|
|
6463
|
+
...submitPrompt === void 0 ? {} : { submitPrompt }
|
|
6464
|
+
}) : pullRequest.checks === "none" ? null : /* @__PURE__ */ jsx(StatusGlyph, {
|
|
6465
|
+
label: t(`repositoryChecks_${pullRequest.checks}`),
|
|
6466
|
+
tone: pullRequest.checks === "passing" ? "success" : "warning",
|
|
6467
|
+
children: /* @__PURE__ */ jsx(ChecksGlyph, { state: pullRequest.checks })
|
|
6468
|
+
}),
|
|
6469
|
+
pullRequest.review === "none" ? null : /* @__PURE__ */ jsx(StatusGlyph, {
|
|
6470
|
+
label: t(`repositoryReview_${pullRequest.review}`),
|
|
6471
|
+
tone: pullRequest.review === "approved" ? "success" : pullRequest.review === "changes-requested" ? "error" : "neutral",
|
|
6472
|
+
children: /* @__PURE__ */ jsx(ReviewGlyph, {})
|
|
6473
|
+
}),
|
|
6474
|
+
/* @__PURE__ */ jsx(AutoFixControl, {
|
|
6475
|
+
sessionId,
|
|
6476
|
+
repository,
|
|
6477
|
+
running,
|
|
6478
|
+
t,
|
|
6479
|
+
...submitPrompt === void 0 ? {} : { submitPrompt }
|
|
6480
|
+
}),
|
|
6481
|
+
/* @__PURE__ */ jsx(UpdateBranchControl, {
|
|
6482
|
+
sessionId,
|
|
6483
|
+
repository,
|
|
6484
|
+
t,
|
|
6485
|
+
...submitPrompt === void 0 ? {} : { submitPrompt }
|
|
6486
|
+
}),
|
|
6487
|
+
/* @__PURE__ */ jsx(MergePullRequestControl, {
|
|
6488
|
+
sessionId,
|
|
6489
|
+
repository,
|
|
6490
|
+
t
|
|
6491
|
+
})
|
|
6492
|
+
] })]
|
|
5888
6493
|
})
|
|
5889
6494
|
]
|
|
5890
6495
|
})
|
|
@@ -5892,7 +6497,7 @@ window.__ModuleLoader__.load({
|
|
|
5892
6497
|
}
|
|
5893
6498
|
//#endregion
|
|
5894
6499
|
//#region src/client/review-comment-api.ts
|
|
5895
|
-
function record(value) {
|
|
6500
|
+
function record$1(value) {
|
|
5896
6501
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
5897
6502
|
}
|
|
5898
6503
|
async function post(path, sessionId, body) {
|
|
@@ -5907,13 +6512,13 @@ window.__ModuleLoader__.load({
|
|
|
5907
6512
|
});
|
|
5908
6513
|
const value = await response.json();
|
|
5909
6514
|
if (!response.ok) {
|
|
5910
|
-
const error = record(value);
|
|
6515
|
+
const error = record$1(value);
|
|
5911
6516
|
throw new Error(typeof error?.message === "string" ? error.message : "Review comment request failed.");
|
|
5912
6517
|
}
|
|
5913
6518
|
return value;
|
|
5914
6519
|
}
|
|
5915
6520
|
async function addReviewComment(sessionId, comment) {
|
|
5916
|
-
const created = record(record(await post("", sessionId, comment))?.comment);
|
|
6521
|
+
const created = record$1(record$1(await post("", sessionId, comment))?.comment);
|
|
5917
6522
|
if (created === void 0 || typeof created.id !== "string") throw new Error("Invalid review comment response.");
|
|
5918
6523
|
return created;
|
|
5919
6524
|
}
|
|
@@ -5926,7 +6531,15 @@ window.__ModuleLoader__.load({
|
|
|
5926
6531
|
//#endregion
|
|
5927
6532
|
//#region src/client/ClaudeReviewComments.tsx
|
|
5928
6533
|
function reviewCommentChipLabel(comment) {
|
|
5929
|
-
return `${comment.path.split("/").at(-1) ?? comment.path}:${comment.line}`;
|
|
6534
|
+
return `${comment.path.split("/").at(-1) ?? comment.path}:${comment.startLine === void 0 ? comment.line : `${comment.startLine}-${comment.line}`}`;
|
|
6535
|
+
}
|
|
6536
|
+
/** "Line 12" / "Lines 10–12", with the old-side variant when the comment sits on removed code. */
|
|
6537
|
+
function commentLineLabel(comment, t) {
|
|
6538
|
+
if (comment.startLine !== void 0) return t(comment.side === "old" ? "reviewCommentOldRange" : "reviewCommentNewRange", {
|
|
6539
|
+
start: comment.startLine,
|
|
6540
|
+
end: comment.line
|
|
6541
|
+
});
|
|
6542
|
+
return t(comment.side === "old" ? "reviewCommentOldSide" : "reviewCommentNewSide", { line: comment.line });
|
|
5930
6543
|
}
|
|
5931
6544
|
function CommentIcon() {
|
|
5932
6545
|
return /* @__PURE__ */ jsx("svg", {
|
|
@@ -5992,7 +6605,7 @@ window.__ModuleLoader__.load({
|
|
|
5992
6605
|
children: [
|
|
5993
6606
|
comment.path,
|
|
5994
6607
|
" · ",
|
|
5995
|
-
comment
|
|
6608
|
+
commentLineLabel(comment, t)
|
|
5996
6609
|
]
|
|
5997
6610
|
}), /* @__PURE__ */ jsx("p", {
|
|
5998
6611
|
style: reviewCommentHoverText,
|
|
@@ -6101,17 +6714,41 @@ window.__ModuleLoader__.load({
|
|
|
6101
6714
|
let oldLine = 0;
|
|
6102
6715
|
let newLine = 0;
|
|
6103
6716
|
let previousOldEnd;
|
|
6717
|
+
let previousNewEnd = 0;
|
|
6718
|
+
let expandable = false;
|
|
6104
6719
|
for (const line of lines) {
|
|
6105
6720
|
const hunk = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/u.exec(line);
|
|
6106
6721
|
if (hunk !== null) {
|
|
6107
6722
|
const nextOld = Number(hunk[1]);
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6723
|
+
const nextNew = Number(hunk[3]);
|
|
6724
|
+
const oldCount = Number(hunk[2] ?? 1);
|
|
6725
|
+
const newCount = Number(hunk[4] ?? 1);
|
|
6726
|
+
if (previousOldEnd === void 0) {
|
|
6727
|
+
expandable = oldCount > 0 && newCount > 0;
|
|
6728
|
+
if (expandable && nextOld > 1) numbered.push({
|
|
6729
|
+
line: "",
|
|
6730
|
+
kind: "collapsed",
|
|
6731
|
+
gap: {
|
|
6732
|
+
oldStart: 1,
|
|
6733
|
+
newStart: 1,
|
|
6734
|
+
count: nextOld - 1,
|
|
6735
|
+
position: "top"
|
|
6736
|
+
}
|
|
6737
|
+
});
|
|
6738
|
+
} else if (nextOld > previousOldEnd) numbered.push({
|
|
6739
|
+
line: "",
|
|
6740
|
+
kind: "collapsed",
|
|
6741
|
+
gap: {
|
|
6742
|
+
oldStart: previousOldEnd,
|
|
6743
|
+
newStart: previousNewEnd,
|
|
6744
|
+
count: nextOld - previousOldEnd,
|
|
6745
|
+
position: "middle"
|
|
6746
|
+
}
|
|
6111
6747
|
});
|
|
6112
6748
|
oldLine = nextOld;
|
|
6113
|
-
newLine =
|
|
6114
|
-
previousOldEnd = nextOld +
|
|
6749
|
+
newLine = nextNew;
|
|
6750
|
+
previousOldEnd = nextOld + oldCount;
|
|
6751
|
+
previousNewEnd = nextNew + newCount;
|
|
6115
6752
|
numbered.push({
|
|
6116
6753
|
line,
|
|
6117
6754
|
kind: "hunk"
|
|
@@ -6143,8 +6780,76 @@ window.__ModuleLoader__.load({
|
|
|
6143
6780
|
newLine += 1;
|
|
6144
6781
|
}
|
|
6145
6782
|
}
|
|
6783
|
+
if (expandable && previousOldEnd !== void 0) numbered.push({
|
|
6784
|
+
line: "",
|
|
6785
|
+
kind: "collapsed",
|
|
6786
|
+
gap: {
|
|
6787
|
+
oldStart: previousOldEnd,
|
|
6788
|
+
newStart: previousNewEnd,
|
|
6789
|
+
position: "bottom"
|
|
6790
|
+
}
|
|
6791
|
+
});
|
|
6146
6792
|
return numbered;
|
|
6147
6793
|
}
|
|
6794
|
+
/**
|
|
6795
|
+
* Splice revealed working-tree lines (keyed by new-side line number) into the
|
|
6796
|
+
* collapsed gaps. Expansion only ever grows a gap's edges, so each gap is a
|
|
6797
|
+
* top run + remaining gap + bottom run; `total` (file line count) turns the
|
|
6798
|
+
* open-ended tail gap into a bounded one.
|
|
6799
|
+
*/
|
|
6800
|
+
function expandDiffRows(rows, revealed, total) {
|
|
6801
|
+
const out = [];
|
|
6802
|
+
for (const row of rows) {
|
|
6803
|
+
const gap = row.gap;
|
|
6804
|
+
if (row.kind !== "collapsed" || gap === void 0) {
|
|
6805
|
+
out.push(row);
|
|
6806
|
+
continue;
|
|
6807
|
+
}
|
|
6808
|
+
const count = gap.count ?? (total === void 0 ? void 0 : Math.max(0, total - gap.newStart + 1));
|
|
6809
|
+
const context = (offset) => ({
|
|
6810
|
+
line: ` ${revealed.get(gap.newStart + offset) ?? ""}`,
|
|
6811
|
+
kind: "context",
|
|
6812
|
+
oldLine: gap.oldStart + offset,
|
|
6813
|
+
newLine: gap.newStart + offset
|
|
6814
|
+
});
|
|
6815
|
+
let top = 0;
|
|
6816
|
+
while ((count === void 0 || top < count) && revealed.has(gap.newStart + top)) top += 1;
|
|
6817
|
+
let bottom = 0;
|
|
6818
|
+
if (count !== void 0) while (bottom < count - top && revealed.has(gap.newStart + count - 1 - bottom)) bottom += 1;
|
|
6819
|
+
for (let offset = 0; offset < top; offset += 1) out.push(context(offset));
|
|
6820
|
+
const remaining = count === void 0 ? void 0 : count - top - bottom;
|
|
6821
|
+
if (remaining === void 0 || remaining > 0) out.push({
|
|
6822
|
+
...row,
|
|
6823
|
+
gap: {
|
|
6824
|
+
...gap,
|
|
6825
|
+
oldStart: gap.oldStart + top,
|
|
6826
|
+
newStart: gap.newStart + top,
|
|
6827
|
+
...remaining === void 0 ? {} : { count: remaining }
|
|
6828
|
+
}
|
|
6829
|
+
});
|
|
6830
|
+
if (count !== void 0) for (let offset = count - bottom; offset < count; offset += 1) out.push(context(offset));
|
|
6831
|
+
}
|
|
6832
|
+
return out;
|
|
6833
|
+
}
|
|
6834
|
+
/**
|
|
6835
|
+
* Anchor for a drag from row `from` to row `to`: every commentable row in
|
|
6836
|
+
* between on the same side as the first row, collapsed to its first/last line.
|
|
6837
|
+
*/
|
|
6838
|
+
function rangeCommentAnchor(anchors, from, to) {
|
|
6839
|
+
const side = anchors[from]?.side;
|
|
6840
|
+
if (side === void 0) return void 0;
|
|
6841
|
+
const lines = anchors.slice(Math.min(from, to), Math.max(from, to) + 1).flatMap((anchor) => anchor?.side === side ? [anchor.line] : []);
|
|
6842
|
+
const line = Math.max(...lines);
|
|
6843
|
+
const startLine = Math.min(...lines);
|
|
6844
|
+
return startLine < line ? {
|
|
6845
|
+
line,
|
|
6846
|
+
side,
|
|
6847
|
+
startLine
|
|
6848
|
+
} : {
|
|
6849
|
+
line,
|
|
6850
|
+
side
|
|
6851
|
+
};
|
|
6852
|
+
}
|
|
6148
6853
|
/** Which working-tree line a comment on this rendered diff row refers to. */
|
|
6149
6854
|
function commentAnchorForLine(entry) {
|
|
6150
6855
|
if (entry.kind === "add" || entry.kind === "context") return entry.newLine === void 0 ? void 0 : {
|
|
@@ -6156,22 +6861,32 @@ window.__ModuleLoader__.load({
|
|
|
6156
6861
|
side: "old"
|
|
6157
6862
|
};
|
|
6158
6863
|
}
|
|
6159
|
-
function DiffLine({ entry, addLabel, onComment }) {
|
|
6160
|
-
const style = entry.kind === "add" ? diffLineAdd : entry.kind === "delete" ? diffLineDelete : entry.kind === "hunk"
|
|
6864
|
+
function DiffLine({ entry, addLabel, selected, onComment, onDragStart, onDragEnter }) {
|
|
6865
|
+
const style = entry.kind === "add" ? diffLineAdd : entry.kind === "delete" ? diffLineDelete : entry.kind === "hunk" ? diffLineHunk : diffLineContext;
|
|
6161
6866
|
const lineNumber = entry.oldLine === void 0 && entry.newLine === void 0 ? "" : entry.oldLine === void 0 ? String(entry.newLine) : entry.newLine === void 0 ? String(entry.oldLine) : String(entry.newLine);
|
|
6162
6867
|
return /* @__PURE__ */ jsxs("div", {
|
|
6163
6868
|
className: diffLineRowClass,
|
|
6164
6869
|
style: {
|
|
6165
6870
|
...diffLine,
|
|
6166
|
-
...style
|
|
6871
|
+
...style,
|
|
6872
|
+
...selected ? diffLineSelected : {}
|
|
6167
6873
|
},
|
|
6874
|
+
onPointerEnter: onDragEnter,
|
|
6168
6875
|
children: [
|
|
6169
6876
|
/* @__PURE__ */ jsx("button", {
|
|
6170
6877
|
type: "button",
|
|
6171
6878
|
className: diffCommentButtonClass,
|
|
6172
6879
|
disabled: onComment === void 0,
|
|
6173
6880
|
"aria-label": addLabel,
|
|
6174
|
-
|
|
6881
|
+
onPointerDown: (event) => {
|
|
6882
|
+
if (event.button !== 0 || onDragStart === void 0) return;
|
|
6883
|
+
event.preventDefault();
|
|
6884
|
+
if (event.currentTarget.hasPointerCapture?.(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);
|
|
6885
|
+
onDragStart();
|
|
6886
|
+
},
|
|
6887
|
+
onClick: (event) => {
|
|
6888
|
+
if (event.detail === 0) onComment?.();
|
|
6889
|
+
},
|
|
6175
6890
|
children: "+"
|
|
6176
6891
|
}),
|
|
6177
6892
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -6180,14 +6895,105 @@ window.__ModuleLoader__.load({
|
|
|
6180
6895
|
}),
|
|
6181
6896
|
/* @__PURE__ */ jsx("span", {
|
|
6182
6897
|
style: diffLineMarker,
|
|
6183
|
-
children: entry.kind === "add" ? "+" : entry.kind === "delete" ? "−" :
|
|
6898
|
+
children: entry.kind === "add" ? "+" : entry.kind === "delete" ? "−" : " "
|
|
6184
6899
|
}),
|
|
6185
|
-
/* @__PURE__ */ jsx("span", {
|
|
6900
|
+
/* @__PURE__ */ jsx("span", {
|
|
6901
|
+
style: diffLineText,
|
|
6902
|
+
children: entry.line.slice(entry.kind === "hunk" ? 0 : 1)
|
|
6903
|
+
})
|
|
6186
6904
|
]
|
|
6187
6905
|
});
|
|
6188
6906
|
}
|
|
6189
|
-
function
|
|
6907
|
+
function ChevronGlyph({ direction }) {
|
|
6908
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
6909
|
+
width: "14",
|
|
6910
|
+
height: "14",
|
|
6911
|
+
viewBox: "0 0 14 14",
|
|
6912
|
+
fill: "none",
|
|
6913
|
+
stroke: "currentColor",
|
|
6914
|
+
strokeWidth: "1.5",
|
|
6915
|
+
strokeLinecap: "round",
|
|
6916
|
+
strokeLinejoin: "round",
|
|
6917
|
+
"aria-hidden": "true",
|
|
6918
|
+
children: /* @__PURE__ */ jsx("path", { d: direction === "up" ? "M3 8.5l4-4 4 4" : "M3 5.5l4 4 4-4" })
|
|
6919
|
+
});
|
|
6920
|
+
}
|
|
6921
|
+
/** "N unmodified lines" separator with GitHub-style expanders: ↑ above the first hunk, ↑↓ between hunks, ↓ after the last. */
|
|
6922
|
+
function DiffGapRow({ gap, t, busy, onExpand }) {
|
|
6923
|
+
const button = (direction) => /* @__PURE__ */ jsx("button", {
|
|
6924
|
+
type: "button",
|
|
6925
|
+
style: diffGapButton,
|
|
6926
|
+
disabled: busy || onExpand === void 0,
|
|
6927
|
+
"aria-label": t(direction === "up" ? "diffExpandUp" : "diffExpandDown"),
|
|
6928
|
+
title: t(direction === "up" ? "diffExpandUp" : "diffExpandDown"),
|
|
6929
|
+
onClick: () => onExpand?.(gap, direction),
|
|
6930
|
+
children: /* @__PURE__ */ jsx(ChevronGlyph, { direction })
|
|
6931
|
+
});
|
|
6932
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
6933
|
+
style: {
|
|
6934
|
+
...diffLine,
|
|
6935
|
+
...diffLineHunk
|
|
6936
|
+
},
|
|
6937
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
6938
|
+
style: diffGapControls,
|
|
6939
|
+
children: [gap.position === "bottom" ? null : button("up"), gap.position === "top" ? null : button("down")]
|
|
6940
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
6941
|
+
style: diffLineText,
|
|
6942
|
+
children: gap.count === void 0 ? t("diffUnmodifiedTail") : t("diffUnmodifiedLines", { count: gap.count })
|
|
6943
|
+
})]
|
|
6944
|
+
});
|
|
6945
|
+
}
|
|
6946
|
+
function DiffFileSection({ file, root, initiallyOpen, t, comments, ghComments, editorAnchor, editorNode, onOpenEditor, onRemoveComment }) {
|
|
6190
6947
|
const [open, setOpen] = useState(initiallyOpen);
|
|
6948
|
+
const [revealed, setRevealed] = useState(() => /* @__PURE__ */ new Map());
|
|
6949
|
+
const [total, setTotal] = useState();
|
|
6950
|
+
const [expanding, setExpanding] = useState(false);
|
|
6951
|
+
const [drag, setDrag] = useState();
|
|
6952
|
+
const rows = useMemo(() => expandDiffRows(numberDiffLines(file.lines), revealed, total), [
|
|
6953
|
+
file.lines,
|
|
6954
|
+
revealed,
|
|
6955
|
+
total
|
|
6956
|
+
]);
|
|
6957
|
+
const anchors = useMemo(() => rows.map(commentAnchorForLine), [rows]);
|
|
6958
|
+
const slash = file.path.lastIndexOf("/");
|
|
6959
|
+
const directory = slash < 0 ? "" : file.path.slice(0, slash + 1);
|
|
6960
|
+
const name = file.path.slice(slash + 1);
|
|
6961
|
+
const expand = (gap, direction) => {
|
|
6962
|
+
if (root === void 0 || expanding) return;
|
|
6963
|
+
const span = gap.count ?? 20;
|
|
6964
|
+
const size = Math.min(20, span);
|
|
6965
|
+
const from = direction === "down" ? gap.newStart : gap.newStart + span - size;
|
|
6966
|
+
setExpanding(true);
|
|
6967
|
+
loadRepositoryFileLines(root, file.path, from, from + size - 1).then((result) => {
|
|
6968
|
+
setRevealed((previous) => {
|
|
6969
|
+
const next = new Map(previous);
|
|
6970
|
+
result.lines.forEach((text, offset) => next.set(from + offset, text));
|
|
6971
|
+
return next;
|
|
6972
|
+
});
|
|
6973
|
+
setTotal(result.total);
|
|
6974
|
+
}, () => void 0).finally(() => setExpanding(false));
|
|
6975
|
+
};
|
|
6976
|
+
useEffect(() => {
|
|
6977
|
+
if (drag === void 0) return;
|
|
6978
|
+
const finish = () => {
|
|
6979
|
+
setDrag(void 0);
|
|
6980
|
+
const anchor = rangeCommentAnchor(anchors, drag.start, drag.end);
|
|
6981
|
+
if (anchor !== void 0) onOpenEditor(anchor);
|
|
6982
|
+
};
|
|
6983
|
+
window.addEventListener("pointerup", finish);
|
|
6984
|
+
window.addEventListener("pointercancel", finish);
|
|
6985
|
+
return () => {
|
|
6986
|
+
window.removeEventListener("pointerup", finish);
|
|
6987
|
+
window.removeEventListener("pointercancel", finish);
|
|
6988
|
+
};
|
|
6989
|
+
}, [
|
|
6990
|
+
anchors,
|
|
6991
|
+
drag,
|
|
6992
|
+
onOpenEditor
|
|
6993
|
+
]);
|
|
6994
|
+
const dragLow = drag === void 0 ? void 0 : Math.min(drag.start, drag.end);
|
|
6995
|
+
const dragHigh = drag === void 0 ? void 0 : Math.max(drag.start, drag.end);
|
|
6996
|
+
const dragSide = drag === void 0 ? void 0 : anchors[drag.start]?.side;
|
|
6191
6997
|
return /* @__PURE__ */ jsxs("section", {
|
|
6192
6998
|
style: diffFile,
|
|
6193
6999
|
children: [/* @__PURE__ */ jsxs("button", {
|
|
@@ -6203,9 +7009,16 @@ window.__ModuleLoader__.load({
|
|
|
6203
7009
|
},
|
|
6204
7010
|
children: "›"
|
|
6205
7011
|
}),
|
|
6206
|
-
/* @__PURE__ */
|
|
7012
|
+
/* @__PURE__ */ jsxs("span", {
|
|
6207
7013
|
style: diffFilePath,
|
|
6208
|
-
|
|
7014
|
+
title: file.path,
|
|
7015
|
+
children: [directory === "" ? null : /* @__PURE__ */ jsx("span", {
|
|
7016
|
+
style: diffFileDir,
|
|
7017
|
+
children: `\u202A${directory}\u202C`
|
|
7018
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
7019
|
+
style: diffFileName,
|
|
7020
|
+
children: name
|
|
7021
|
+
})]
|
|
6209
7022
|
}),
|
|
6210
7023
|
/* @__PURE__ */ jsxs("span", {
|
|
6211
7024
|
style: diffFileStats,
|
|
@@ -6220,22 +7033,39 @@ window.__ModuleLoader__.load({
|
|
|
6220
7033
|
]
|
|
6221
7034
|
}), open ? /* @__PURE__ */ jsx("div", {
|
|
6222
7035
|
style: diffCode,
|
|
6223
|
-
children:
|
|
6224
|
-
|
|
7036
|
+
children: rows.map((entry, index) => {
|
|
7037
|
+
if (entry.kind === "collapsed" && entry.gap !== void 0) return /* @__PURE__ */ jsx(DiffGapRow, {
|
|
7038
|
+
gap: entry.gap,
|
|
7039
|
+
t,
|
|
7040
|
+
busy: expanding,
|
|
7041
|
+
onExpand: root === void 0 ? void 0 : expand
|
|
7042
|
+
}, `gap:${entry.gap.newStart}`);
|
|
7043
|
+
const anchor = anchors[index];
|
|
6225
7044
|
const lineComments = anchor === void 0 ? [] : comments.filter((comment) => comment.line === anchor.line && comment.side === anchor.side);
|
|
6226
7045
|
const ghLineComments = anchor === void 0 ? [] : ghComments.filter((comment) => comment.line === anchor.line && comment.side === anchor.side);
|
|
6227
7046
|
const editorOpen = anchor !== void 0 && editorAnchor !== void 0 && editorAnchor.line === anchor.line && editorAnchor.side === anchor.side;
|
|
7047
|
+
const inDrag = dragLow !== void 0 && dragHigh !== void 0 && index >= dragLow && index <= dragHigh && anchor?.side === dragSide;
|
|
7048
|
+
const inEditorRange = anchor !== void 0 && editorAnchor !== void 0 && editorAnchor.side === anchor.side && anchor.line <= editorAnchor.line && anchor.line >= (editorAnchor.startLine ?? editorAnchor.line);
|
|
6228
7049
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6229
7050
|
/* @__PURE__ */ jsx(DiffLine, {
|
|
6230
7051
|
entry,
|
|
6231
7052
|
addLabel: t("reviewCommentAdd"),
|
|
6232
|
-
|
|
7053
|
+
selected: inDrag || inEditorRange,
|
|
7054
|
+
onComment: anchor === void 0 ? void 0 : () => onOpenEditor(anchor),
|
|
7055
|
+
onDragStart: anchor === void 0 ? void 0 : () => setDrag({
|
|
7056
|
+
start: index,
|
|
7057
|
+
end: index
|
|
7058
|
+
}),
|
|
7059
|
+
onDragEnter: drag === void 0 ? void 0 : () => setDrag((current) => current === void 0 ? current : {
|
|
7060
|
+
...current,
|
|
7061
|
+
end: index
|
|
7062
|
+
})
|
|
6233
7063
|
}),
|
|
6234
7064
|
lineComments.map((comment) => /* @__PURE__ */ jsxs("div", {
|
|
6235
7065
|
style: diffCommentBlock,
|
|
6236
7066
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
6237
7067
|
style: diffCommentCardMeta,
|
|
6238
|
-
children: [/* @__PURE__ */ jsx("span", { children: comment
|
|
7068
|
+
children: [/* @__PURE__ */ jsx("span", { children: commentLineLabel(comment, t) }), /* @__PURE__ */ jsx("button", {
|
|
6239
7069
|
type: "button",
|
|
6240
7070
|
style: reviewCommentChipRemove,
|
|
6241
7071
|
"aria-label": t("reviewCommentRemove"),
|
|
@@ -6478,6 +7308,7 @@ window.__ModuleLoader__.load({
|
|
|
6478
7308
|
const created = await addReviewComment(sessionId, {
|
|
6479
7309
|
path: commentEditor.path,
|
|
6480
7310
|
line: commentEditor.line,
|
|
7311
|
+
...commentEditor.startLine === void 0 ? {} : { startLine: commentEditor.startLine },
|
|
6481
7312
|
side: commentEditor.side,
|
|
6482
7313
|
text: commentDraft.trim()
|
|
6483
7314
|
});
|
|
@@ -6564,6 +7395,10 @@ window.__ModuleLoader__.load({
|
|
|
6564
7395
|
const commentEditorNode = commentEditor === void 0 ? null : /* @__PURE__ */ jsxs("div", {
|
|
6565
7396
|
style: diffCommentBlock,
|
|
6566
7397
|
children: [
|
|
7398
|
+
/* @__PURE__ */ jsx("div", {
|
|
7399
|
+
style: diffCommentRange,
|
|
7400
|
+
children: commentLineLabel(commentEditor, t)
|
|
7401
|
+
}),
|
|
6567
7402
|
/* @__PURE__ */ jsx("textarea", {
|
|
6568
7403
|
className: diffCommentTextareaClass,
|
|
6569
7404
|
style: diffCommentTextarea,
|
|
@@ -6601,12 +7436,14 @@ window.__ModuleLoader__.load({
|
|
|
6601
7436
|
/* @__PURE__ */ jsxs("style", {
|
|
6602
7437
|
"data-dsh-claude-repository-modal-styles": true,
|
|
6603
7438
|
children: [
|
|
7439
|
+
detailsCardCss,
|
|
6604
7440
|
diffModalCss,
|
|
6605
7441
|
panelIconButtonCss,
|
|
6606
7442
|
diffCommentCss
|
|
6607
7443
|
]
|
|
6608
7444
|
}),
|
|
6609
7445
|
/* @__PURE__ */ jsxs("div", {
|
|
7446
|
+
className: detailsCardClass,
|
|
6610
7447
|
style: {
|
|
6611
7448
|
...diffPanel,
|
|
6612
7449
|
...maximized ? diffPanelMaximized : {}
|
|
@@ -6728,6 +7565,7 @@ window.__ModuleLoader__.load({
|
|
|
6728
7565
|
children: t("diffEmpty")
|
|
6729
7566
|
}) : files.map((file, index) => /* @__PURE__ */ jsx(DiffFileSection, {
|
|
6730
7567
|
file,
|
|
7568
|
+
root: repository.root,
|
|
6731
7569
|
initiallyOpen: index === 0,
|
|
6732
7570
|
t,
|
|
6733
7571
|
comments: reviewComments.filter((comment) => comment.path === file.path),
|
|
@@ -7146,10 +7984,28 @@ window.__ModuleLoader__.load({
|
|
|
7146
7984
|
}
|
|
7147
7985
|
//#endregion
|
|
7148
7986
|
//#region src/client/ClaudePullRequestsPanel.tsx
|
|
7987
|
+
const NO_WORKSPACE_STATE = {};
|
|
7988
|
+
const NO_WORKSPACES = {
|
|
7989
|
+
subscribe: () => () => {},
|
|
7990
|
+
getSnapshot: () => NO_WORKSPACE_STATE
|
|
7991
|
+
};
|
|
7149
7992
|
const OVERVIEW_REFRESH_MS = 3e4;
|
|
7150
|
-
/**
|
|
7151
|
-
|
|
7152
|
-
|
|
7993
|
+
/** What a running session is blocked on: the latest permission or question
|
|
7994
|
+
* activity that is still in its started phase. */
|
|
7995
|
+
function overviewAttention(activities) {
|
|
7996
|
+
for (let index = activities.length - 1; index >= 0; index -= 1) {
|
|
7997
|
+
const activity = activities[index];
|
|
7998
|
+
if (activity === void 0 || activity.kind !== "permission" && activity.kind !== "question") continue;
|
|
7999
|
+
return activity.phase === "started" ? activity.kind : void 0;
|
|
8000
|
+
}
|
|
8001
|
+
}
|
|
8002
|
+
/** Claude sessions worth listing: rows still in the host list (byId keeps
|
|
8003
|
+
* deleted and breadcrumb rows), non-blank, non-subagent, with a checkout;
|
|
8004
|
+
* running first. */
|
|
8005
|
+
function claudeSessionRows(state, archivedSessionIds = []) {
|
|
8006
|
+
const rows = state.ids === void 0 ? Object.values(state.byId) : state.ids.map((id) => state.byId[id]);
|
|
8007
|
+
const archived = new Set(archivedSessionIds);
|
|
8008
|
+
return rows.filter((row) => row !== void 0 && row.agentPreset === "claude" && row.blank !== true && row.origin !== "subagent" && !archived.has(row.id) && 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
8009
|
}
|
|
7154
8010
|
function Badge({ label, tone = "neutral" }) {
|
|
7155
8011
|
const toneStyle = tone === "success" ? repositoryItemSuccess : tone === "warning" ? repositoryItemWarning : tone === "error" ? repositoryItemError : tone === "merged" ? { color: "#a78bfa" } : {};
|
|
@@ -7167,112 +8023,732 @@ window.__ModuleLoader__.load({
|
|
|
7167
8023
|
})]
|
|
7168
8024
|
});
|
|
7169
8025
|
}
|
|
7170
|
-
function repositoryName(remote) {
|
|
7171
|
-
return remote?.split("/").at(-1);
|
|
7172
|
-
}
|
|
7173
|
-
function
|
|
7174
|
-
const snapshot = useSyncExternalStore(
|
|
7175
|
-
const
|
|
7176
|
-
const
|
|
7177
|
-
|
|
8026
|
+
function repositoryName(remote) {
|
|
8027
|
+
return remote?.split("/").at(-1);
|
|
8028
|
+
}
|
|
8029
|
+
function OverviewAttention({ source, running, t }) {
|
|
8030
|
+
const snapshot = useSyncExternalStore(source.subscribe, source.getSnapshot, source.getSnapshot);
|
|
8031
|
+
const attention = running ? overviewAttention(snapshot.activities) : void 0;
|
|
8032
|
+
const usage = snapshot.contextUsage;
|
|
8033
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
8034
|
+
attention === "permission" ? /* @__PURE__ */ jsx(Badge, {
|
|
8035
|
+
label: t("overviewNeedsPermission"),
|
|
8036
|
+
tone: "warning"
|
|
8037
|
+
}) : null,
|
|
8038
|
+
attention === "question" ? /* @__PURE__ */ jsx(Badge, {
|
|
8039
|
+
label: t("overviewNeedsAnswer"),
|
|
8040
|
+
tone: "warning"
|
|
8041
|
+
}) : null,
|
|
8042
|
+
usage === void 0 ? null : /* @__PURE__ */ jsx("span", { children: t("overviewContextUsage", { percentage: usage.percentage }) })
|
|
8043
|
+
] });
|
|
8044
|
+
}
|
|
8045
|
+
function ClaudePullRequestsPanel({ t, closeDetails, openSession, loadStatus, sessions, workspaces, projectionFor }) {
|
|
8046
|
+
const snapshot = useSyncExternalStore(sessions.subscribe, sessions.getSnapshot, sessions.getSnapshot);
|
|
8047
|
+
const workspaceStore = workspaces ?? NO_WORKSPACES;
|
|
8048
|
+
const workspaceState = useSyncExternalStore(workspaceStore.subscribe, workspaceStore.getSnapshot, workspaceStore.getSnapshot);
|
|
8049
|
+
const rows = useMemo(() => claudeSessionRows(snapshot, workspaceState.archivedSessionIds ?? []), [snapshot, workspaceState]);
|
|
8050
|
+
const cwdKey = useMemo(() => [...new Set(rows.map((row) => row.cwd ?? ""))].sort().join("\0"), [rows]);
|
|
8051
|
+
const [statuses, setStatuses] = useState({});
|
|
8052
|
+
useEffect(() => {
|
|
8053
|
+
const cwds = cwdKey.length === 0 ? [] : cwdKey.split("\0");
|
|
8054
|
+
if (cwds.length === 0) return;
|
|
8055
|
+
const controller = new AbortController();
|
|
8056
|
+
const refresh = () => {
|
|
8057
|
+
for (const cwd of cwds) loadStatus(cwd, controller.signal).then((status) => {
|
|
8058
|
+
if (!controller.signal.aborted) setStatuses((previous) => ({
|
|
8059
|
+
...previous,
|
|
8060
|
+
[cwd]: status
|
|
8061
|
+
}));
|
|
8062
|
+
}, () => void 0);
|
|
8063
|
+
};
|
|
8064
|
+
refresh();
|
|
8065
|
+
const timer = setInterval(refresh, OVERVIEW_REFRESH_MS);
|
|
8066
|
+
return () => {
|
|
8067
|
+
controller.abort();
|
|
8068
|
+
clearInterval(timer);
|
|
8069
|
+
};
|
|
8070
|
+
}, [cwdKey, loadStatus]);
|
|
8071
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
8072
|
+
className: detailsCardClass,
|
|
8073
|
+
style: tasksPanel,
|
|
8074
|
+
children: [
|
|
8075
|
+
/* @__PURE__ */ jsxs("style", {
|
|
8076
|
+
"data-dsh-claude-overview-styles": true,
|
|
8077
|
+
children: [detailsCardCss, panelIconButtonCss]
|
|
8078
|
+
}),
|
|
8079
|
+
/* @__PURE__ */ jsxs("header", {
|
|
8080
|
+
style: tasksHeader,
|
|
8081
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("span", {
|
|
8082
|
+
style: tasksHeading,
|
|
8083
|
+
children: t("overviewTitle")
|
|
8084
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
8085
|
+
style: tasksTurnMeta,
|
|
8086
|
+
children: t("overviewBody")
|
|
8087
|
+
})] }), /* @__PURE__ */ jsx("button", {
|
|
8088
|
+
type: "button",
|
|
8089
|
+
className: panelIconButtonClass,
|
|
8090
|
+
"aria-label": t("diffClose"),
|
|
8091
|
+
onClick: closeDetails,
|
|
8092
|
+
children: /* @__PURE__ */ jsx(IconCloseOutline16, {})
|
|
8093
|
+
})]
|
|
8094
|
+
}),
|
|
8095
|
+
/* @__PURE__ */ jsx("div", {
|
|
8096
|
+
style: overviewBody,
|
|
8097
|
+
children: rows.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
8098
|
+
style: overviewEmpty,
|
|
8099
|
+
children: t("overviewEmpty")
|
|
8100
|
+
}) : rows.map((row) => {
|
|
8101
|
+
const repository = row.cwd === void 0 ? void 0 : statuses[row.cwd];
|
|
8102
|
+
const pullRequest = repository?.pullRequest;
|
|
8103
|
+
const branch = repository?.status === "ready" ? repository.detached === true ? t("repositoryDetached") : repository.branch ?? t("repositoryUnknownBranch") : repository === void 0 ? t("overviewLoading") : t("repositoryUnavailable");
|
|
8104
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
8105
|
+
type: "button",
|
|
8106
|
+
style: overviewRow,
|
|
8107
|
+
onClick: () => {
|
|
8108
|
+
openSession(row.id);
|
|
8109
|
+
},
|
|
8110
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
8111
|
+
style: overviewRowTop,
|
|
8112
|
+
children: [
|
|
8113
|
+
row.running === true ? /* @__PURE__ */ jsx("span", {
|
|
8114
|
+
style: overviewRunningDot,
|
|
8115
|
+
"aria-label": t("overviewRunning")
|
|
8116
|
+
}) : null,
|
|
8117
|
+
/* @__PURE__ */ jsx("span", {
|
|
8118
|
+
style: overviewTitle,
|
|
8119
|
+
children: row.displayTitle ?? row.id
|
|
8120
|
+
}),
|
|
8121
|
+
pullRequest === void 0 ? /* @__PURE__ */ jsx(Badge, { label: t("overviewNoPr") }) : /* @__PURE__ */ jsx(Badge, {
|
|
8122
|
+
label: `#${pullRequest.number} · ${t(`repositoryState_${pullRequest.state}`)}`,
|
|
8123
|
+
tone: pullRequest.state === "merged" ? "merged" : pullRequest.state === "open" ? "success" : "neutral"
|
|
8124
|
+
})
|
|
8125
|
+
]
|
|
8126
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
8127
|
+
style: overviewMeta,
|
|
8128
|
+
children: [
|
|
8129
|
+
repositoryName(repository?.remote) === void 0 ? null : /* @__PURE__ */ jsx("span", { children: repositoryName(repository?.remote) }),
|
|
8130
|
+
/* @__PURE__ */ jsx("span", {
|
|
8131
|
+
style: overviewBranch,
|
|
8132
|
+
children: branch
|
|
8133
|
+
}),
|
|
8134
|
+
pullRequest?.state === "open" && pullRequest.checks !== "none" ? /* @__PURE__ */ jsx(Badge, {
|
|
8135
|
+
label: t(`repositoryChecks_${pullRequest.checks}`),
|
|
8136
|
+
tone: pullRequest.checks === "passing" ? "success" : pullRequest.checks === "failing" ? "error" : "warning"
|
|
8137
|
+
}) : null,
|
|
8138
|
+
pullRequest?.state === "open" && pullRequest.review !== "none" ? /* @__PURE__ */ jsx(Badge, {
|
|
8139
|
+
label: t(`repositoryReview_${pullRequest.review}`),
|
|
8140
|
+
tone: pullRequest.review === "approved" ? "success" : pullRequest.review === "changes-requested" ? "error" : "neutral"
|
|
8141
|
+
}) : null,
|
|
8142
|
+
autoFixEnabled(row.id) ? /* @__PURE__ */ jsx(Badge, {
|
|
8143
|
+
label: t("overviewAutoFix"),
|
|
8144
|
+
tone: "success"
|
|
8145
|
+
}) : null,
|
|
8146
|
+
projectionFor === void 0 ? null : /* @__PURE__ */ jsx(OverviewAttention, {
|
|
8147
|
+
source: projectionFor(row.id),
|
|
8148
|
+
running: row.running === true,
|
|
8149
|
+
t
|
|
8150
|
+
})
|
|
8151
|
+
]
|
|
8152
|
+
})]
|
|
8153
|
+
}, row.id);
|
|
8154
|
+
})
|
|
8155
|
+
})
|
|
8156
|
+
]
|
|
8157
|
+
});
|
|
8158
|
+
}
|
|
8159
|
+
//#endregion
|
|
8160
|
+
//#region src/client/ask-api.ts
|
|
8161
|
+
function record(value) {
|
|
8162
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
8163
|
+
}
|
|
8164
|
+
function parseAskEvent(line) {
|
|
8165
|
+
const event = record(JSON.parse(line));
|
|
8166
|
+
if (event?.type === "delta" && typeof event.text === "string") return {
|
|
8167
|
+
type: "delta",
|
|
8168
|
+
text: event.text
|
|
8169
|
+
};
|
|
8170
|
+
if (event?.type === "thinking" && typeof event.text === "string") return {
|
|
8171
|
+
type: "thinking",
|
|
8172
|
+
text: event.text
|
|
8173
|
+
};
|
|
8174
|
+
if (event?.type === "status" && typeof event.text === "string") return {
|
|
8175
|
+
type: "status",
|
|
8176
|
+
text: event.text
|
|
8177
|
+
};
|
|
8178
|
+
if (event?.type === "tool" && typeof event.id === "string" && (event.phase === "start" || event.phase === "input" || event.phase === "done")) return {
|
|
8179
|
+
type: "tool",
|
|
8180
|
+
id: event.id,
|
|
8181
|
+
phase: event.phase,
|
|
8182
|
+
...typeof event.name === "string" ? { name: event.name } : {},
|
|
8183
|
+
...typeof event.summary === "string" ? { summary: event.summary } : {},
|
|
8184
|
+
...event.error === true ? { error: true } : {}
|
|
8185
|
+
};
|
|
8186
|
+
if (event?.type === "done") return { type: "done" };
|
|
8187
|
+
if (event?.type === "error") return {
|
|
8188
|
+
type: "error",
|
|
8189
|
+
message: typeof event.message === "string" ? event.message : "The question could not be answered."
|
|
8190
|
+
};
|
|
8191
|
+
throw new Error("Invalid ask stream event.");
|
|
8192
|
+
}
|
|
8193
|
+
/** Stream an answer about selected reply text; resolves when the answer completes. */
|
|
8194
|
+
async function askAboutSelection(sessionId, request, onProgress, signal) {
|
|
8195
|
+
const response = await fetch(`${CLAUDE_ASK_PATH}?sessionId=${encodeURIComponent(sessionId)}`, {
|
|
8196
|
+
method: "POST",
|
|
8197
|
+
credentials: "same-origin",
|
|
8198
|
+
headers: {
|
|
8199
|
+
accept: "application/x-ndjson",
|
|
8200
|
+
"content-type": "application/json"
|
|
8201
|
+
},
|
|
8202
|
+
body: JSON.stringify(request),
|
|
8203
|
+
...signal === void 0 ? {} : { signal }
|
|
8204
|
+
});
|
|
8205
|
+
if (!response.ok) {
|
|
8206
|
+
const body = record(await response.json().catch(() => void 0));
|
|
8207
|
+
throw new Error(typeof body?.message === "string" ? body.message : "The question could not be sent.");
|
|
8208
|
+
}
|
|
8209
|
+
if (response.body === null) throw new Error("The answer stream is unavailable.");
|
|
8210
|
+
const reader = response.body.getReader();
|
|
8211
|
+
const decoder = new TextDecoder();
|
|
8212
|
+
let buffer = "";
|
|
8213
|
+
let finished = false;
|
|
8214
|
+
const handle = (line) => {
|
|
8215
|
+
if (line.trim().length === 0) return;
|
|
8216
|
+
const event = parseAskEvent(line);
|
|
8217
|
+
if (event.type === "delta") onProgress({
|
|
8218
|
+
type: "text",
|
|
8219
|
+
text: event.text
|
|
8220
|
+
});
|
|
8221
|
+
else if (event.type === "thinking") onProgress({
|
|
8222
|
+
type: "thinking",
|
|
8223
|
+
text: event.text
|
|
8224
|
+
});
|
|
8225
|
+
else if (event.type === "status") onProgress({
|
|
8226
|
+
type: "status",
|
|
8227
|
+
text: event.text
|
|
8228
|
+
});
|
|
8229
|
+
else if (event.type === "tool") onProgress(event);
|
|
8230
|
+
else if (event.type === "done") finished = true;
|
|
8231
|
+
else throw new Error(event.message);
|
|
8232
|
+
};
|
|
8233
|
+
while (true) {
|
|
8234
|
+
const chunk = await reader.read();
|
|
8235
|
+
buffer += decoder.decode(chunk.value, { stream: !chunk.done });
|
|
8236
|
+
const lines = buffer.split("\n");
|
|
8237
|
+
buffer = lines.pop() ?? "";
|
|
8238
|
+
for (const line of lines) handle(line);
|
|
8239
|
+
if (chunk.done) break;
|
|
8240
|
+
}
|
|
8241
|
+
handle(buffer);
|
|
8242
|
+
if (!finished) throw new Error("The answer ended unexpectedly.");
|
|
8243
|
+
}
|
|
8244
|
+
//#endregion
|
|
8245
|
+
//#region src/client/ClaudeSelectionAsk.tsx
|
|
8246
|
+
const CHAT_NODE = "[data-chat-flow-kind]";
|
|
8247
|
+
const USER_KIND = "user";
|
|
8248
|
+
const MAX_SELECTION_CHARS = 8e3;
|
|
8249
|
+
const MAX_CONTEXT_CHARS = 16e3;
|
|
8250
|
+
const POPUP_WIDTH = 560;
|
|
8251
|
+
const POPUP_ESTIMATED_HEIGHT = 320;
|
|
8252
|
+
const TOOLBAR_WIDTH = 64;
|
|
8253
|
+
const HIGHLIGHT_NAME = "dsh-claude-ask";
|
|
8254
|
+
function appendAnswerBlock(blocks, progress) {
|
|
8255
|
+
if (progress.type === "text") {
|
|
8256
|
+
const last = blocks.at(-1);
|
|
8257
|
+
if (last?.kind === "text") return [...blocks.slice(0, -1), {
|
|
8258
|
+
kind: "text",
|
|
8259
|
+
text: last.text + progress.text
|
|
8260
|
+
}];
|
|
8261
|
+
return [...blocks, {
|
|
8262
|
+
kind: "text",
|
|
8263
|
+
text: progress.text
|
|
8264
|
+
}];
|
|
8265
|
+
}
|
|
8266
|
+
if (progress.type !== "tool") return blocks;
|
|
8267
|
+
const index = blocks.findIndex((block) => block.kind === "tool" && block.id === progress.id);
|
|
8268
|
+
if (index < 0) {
|
|
8269
|
+
if (progress.phase === "done") return blocks;
|
|
8270
|
+
return [...blocks, {
|
|
8271
|
+
kind: "tool",
|
|
8272
|
+
id: progress.id,
|
|
8273
|
+
name: progress.name ?? "tool",
|
|
8274
|
+
state: "running",
|
|
8275
|
+
...progress.summary === void 0 ? {} : { summary: progress.summary }
|
|
8276
|
+
}];
|
|
8277
|
+
}
|
|
8278
|
+
const current = blocks[index];
|
|
8279
|
+
const next = {
|
|
8280
|
+
...current,
|
|
8281
|
+
...progress.name === void 0 ? {} : { name: progress.name },
|
|
8282
|
+
...progress.summary === void 0 ? {} : { summary: progress.summary },
|
|
8283
|
+
state: progress.phase === "done" ? progress.error === true ? "error" : "done" : current.state
|
|
8284
|
+
};
|
|
8285
|
+
return [
|
|
8286
|
+
...blocks.slice(0, index),
|
|
8287
|
+
next,
|
|
8288
|
+
...blocks.slice(index + 1)
|
|
8289
|
+
];
|
|
8290
|
+
}
|
|
8291
|
+
function answerText(blocks) {
|
|
8292
|
+
return blocks.filter((block) => block.kind === "text").map((block) => block.text.trim()).filter((text) => text.length > 0).join("\n\n");
|
|
8293
|
+
}
|
|
8294
|
+
function rectOf(range) {
|
|
8295
|
+
const rect = range.getBoundingClientRect();
|
|
8296
|
+
return {
|
|
8297
|
+
top: rect.top,
|
|
8298
|
+
left: rect.left,
|
|
8299
|
+
width: rect.width,
|
|
8300
|
+
bottom: rect.bottom
|
|
8301
|
+
};
|
|
8302
|
+
}
|
|
8303
|
+
/** Read the current selection when it sits inside an assistant reply. */
|
|
8304
|
+
function selectionInfoOf(selection, sessionId) {
|
|
8305
|
+
if (sessionId === void 0 || selection === null || selection.isCollapsed || selection.rangeCount === 0) return void 0;
|
|
8306
|
+
const range = selection.getRangeAt(0);
|
|
8307
|
+
const hostOf = (node) => {
|
|
8308
|
+
return (node instanceof Element ? node : node?.parentElement ?? null)?.closest(CHAT_NODE) ?? null;
|
|
8309
|
+
};
|
|
8310
|
+
const host = hostOf(range.startContainer) ?? hostOf(range.endContainer);
|
|
8311
|
+
if (host === null || host.dataset.chatFlowKind === USER_KIND) return void 0;
|
|
8312
|
+
const text = selection.toString().trim();
|
|
8313
|
+
if (text.length === 0) return void 0;
|
|
8314
|
+
return {
|
|
8315
|
+
text: text.slice(0, MAX_SELECTION_CHARS),
|
|
8316
|
+
context: (host.textContent ?? "").trim().slice(0, MAX_CONTEXT_CHARS),
|
|
8317
|
+
rect: rectOf(range),
|
|
8318
|
+
range: range.cloneRange()
|
|
8319
|
+
};
|
|
8320
|
+
}
|
|
8321
|
+
function toolbarPosition(rect, viewportWidth) {
|
|
8322
|
+
return {
|
|
8323
|
+
top: Math.max(8, rect.top - 40),
|
|
8324
|
+
left: Math.min(Math.max(8, rect.left + rect.width / 2 - TOOLBAR_WIDTH / 2), Math.max(8, viewportWidth - TOOLBAR_WIDTH - 8))
|
|
8325
|
+
};
|
|
8326
|
+
}
|
|
8327
|
+
/** Pick the side with room once, when the popup opens: below the selection
|
|
8328
|
+
* unless the space there is short and above is roomier. */
|
|
8329
|
+
function popupSide(rect, viewportHeight) {
|
|
8330
|
+
const roomBelow = viewportHeight - rect.bottom - 16;
|
|
8331
|
+
const roomAbove = rect.top - 16;
|
|
8332
|
+
return roomBelow >= POPUP_ESTIMATED_HEIGHT || roomBelow >= roomAbove ? "below" : "above";
|
|
8333
|
+
}
|
|
8334
|
+
/** Anchor on the chosen side so streamed content grows away from the text and
|
|
8335
|
+
* scrolls inside the popup instead of running off screen. */
|
|
8336
|
+
function popupPlacement(rect, side, viewportWidth, viewportHeight) {
|
|
8337
|
+
const width = Math.min(POPUP_WIDTH, viewportWidth - 16);
|
|
8338
|
+
const left = Math.min(Math.max(8, rect.left), Math.max(8, viewportWidth - width - 8));
|
|
8339
|
+
const cap = Math.round(viewportHeight * .7);
|
|
8340
|
+
if (side === "below") {
|
|
8341
|
+
const top = Math.max(8, rect.bottom + 8);
|
|
8342
|
+
return {
|
|
8343
|
+
top,
|
|
8344
|
+
left,
|
|
8345
|
+
width,
|
|
8346
|
+
maxHeight: Math.max(120, Math.min(cap, viewportHeight - top - 8))
|
|
8347
|
+
};
|
|
8348
|
+
}
|
|
8349
|
+
const bottom = Math.max(8, viewportHeight - rect.top + 8);
|
|
8350
|
+
return {
|
|
8351
|
+
bottom,
|
|
8352
|
+
left,
|
|
8353
|
+
width,
|
|
8354
|
+
maxHeight: Math.max(120, Math.min(cap, viewportHeight - bottom - 8))
|
|
8355
|
+
};
|
|
8356
|
+
}
|
|
8357
|
+
function CopyIcon() {
|
|
8358
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
8359
|
+
width: "14",
|
|
8360
|
+
height: "14",
|
|
8361
|
+
viewBox: "0 0 16 16",
|
|
8362
|
+
fill: "none",
|
|
8363
|
+
stroke: "currentColor",
|
|
8364
|
+
strokeWidth: "1.5",
|
|
8365
|
+
strokeLinecap: "round",
|
|
8366
|
+
strokeLinejoin: "round",
|
|
8367
|
+
"aria-hidden": "true",
|
|
8368
|
+
children: [/* @__PURE__ */ jsx("rect", {
|
|
8369
|
+
x: "5.5",
|
|
8370
|
+
y: "5.5",
|
|
8371
|
+
width: "8",
|
|
8372
|
+
height: "8",
|
|
8373
|
+
rx: "1.5"
|
|
8374
|
+
}), /* @__PURE__ */ jsx("path", { d: "M10.5 5.5V3.5a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2" })]
|
|
8375
|
+
});
|
|
8376
|
+
}
|
|
8377
|
+
function AskIcon() {
|
|
8378
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
8379
|
+
width: "14",
|
|
8380
|
+
height: "14",
|
|
8381
|
+
viewBox: "0 0 16 16",
|
|
8382
|
+
fill: "none",
|
|
8383
|
+
stroke: "currentColor",
|
|
8384
|
+
strokeWidth: "1.5",
|
|
8385
|
+
strokeLinecap: "round",
|
|
8386
|
+
strokeLinejoin: "round",
|
|
8387
|
+
"aria-hidden": "true",
|
|
8388
|
+
children: [/* @__PURE__ */ jsx("path", { d: "M2.75 2.75h10.5a1 1 0 0 1 1 1v6.5a1 1 0 0 1-1 1H8.2l-3.2 2.9v-2.9H2.75a1 1 0 0 1-1-1v-6.5a1 1 0 0 1 1-1Z" }), /* @__PURE__ */ jsx("path", { d: "M6.4 6.3a1.6 1.6 0 1 1 2.3 1.5c-.5.3-.7.6-.7 1.1M8 10.6h.01" })]
|
|
8389
|
+
});
|
|
8390
|
+
}
|
|
8391
|
+
function CheckIcon() {
|
|
8392
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
8393
|
+
width: "14",
|
|
8394
|
+
height: "14",
|
|
8395
|
+
viewBox: "0 0 16 16",
|
|
8396
|
+
fill: "none",
|
|
8397
|
+
stroke: "currentColor",
|
|
8398
|
+
strokeWidth: "1.8",
|
|
8399
|
+
strokeLinecap: "round",
|
|
8400
|
+
strokeLinejoin: "round",
|
|
8401
|
+
"aria-hidden": "true",
|
|
8402
|
+
children: /* @__PURE__ */ jsx("path", { d: "m3.5 8.5 3 3 6-7" })
|
|
8403
|
+
});
|
|
8404
|
+
}
|
|
8405
|
+
/** Selection toolbar over assistant replies: copy, or ask a follow-up whose
|
|
8406
|
+
* answer streams into a popup rendered with the Host Markdown renderer. */
|
|
8407
|
+
function ClaudeSelectionAsk({ t, currentSessionId, ownsSession, insertIntoChat }) {
|
|
8408
|
+
const [selection, setSelection] = useState();
|
|
8409
|
+
const [open, setOpen] = useState(false);
|
|
8410
|
+
const [question, setQuestion] = useState("");
|
|
8411
|
+
const [blocks, setBlocks] = useState([]);
|
|
8412
|
+
const answer = answerText(blocks);
|
|
8413
|
+
const [thinking, setThinking] = useState("");
|
|
8414
|
+
const [thinkingOpen, setThinkingOpen] = useState(false);
|
|
8415
|
+
const [started, setStarted] = useState(false);
|
|
8416
|
+
const [phase, setPhase] = useState("idle");
|
|
8417
|
+
const [error, setError] = useState();
|
|
8418
|
+
const [copied, setCopied] = useState();
|
|
8419
|
+
const [rect, setRect] = useState();
|
|
8420
|
+
const [side, setSide] = useState("below");
|
|
8421
|
+
const popupRef = useRef(null);
|
|
8422
|
+
const toolbarRef = useRef(null);
|
|
8423
|
+
const controller = useRef();
|
|
8424
|
+
const openRef = useRef(false);
|
|
8425
|
+
openRef.current = open;
|
|
8426
|
+
const close = useCallback(() => {
|
|
8427
|
+
controller.current?.abort();
|
|
8428
|
+
controller.current = void 0;
|
|
8429
|
+
setOpen(false);
|
|
8430
|
+
setSelection(void 0);
|
|
8431
|
+
setQuestion("");
|
|
8432
|
+
setBlocks([]);
|
|
8433
|
+
setThinking("");
|
|
8434
|
+
setThinkingOpen(false);
|
|
8435
|
+
setStarted(false);
|
|
8436
|
+
setPhase("idle");
|
|
8437
|
+
setError(void 0);
|
|
8438
|
+
setCopied(void 0);
|
|
8439
|
+
}, []);
|
|
7178
8440
|
useEffect(() => {
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
const
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
8441
|
+
if (typeof document === "undefined") return;
|
|
8442
|
+
let timer;
|
|
8443
|
+
const update = () => {
|
|
8444
|
+
if (openRef.current) return;
|
|
8445
|
+
const sessionId = currentSessionId();
|
|
8446
|
+
if (sessionId === void 0 || !ownsSession(sessionId)) {
|
|
8447
|
+
setSelection(void 0);
|
|
8448
|
+
return;
|
|
8449
|
+
}
|
|
8450
|
+
const info = selectionInfoOf(document.getSelection(), sessionId);
|
|
8451
|
+
setSelection(info === void 0 ? void 0 : {
|
|
8452
|
+
sessionId,
|
|
8453
|
+
...info
|
|
8454
|
+
});
|
|
7189
8455
|
};
|
|
7190
|
-
|
|
7191
|
-
|
|
8456
|
+
const schedule = () => {
|
|
8457
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
8458
|
+
timer = setTimeout(update, 120);
|
|
8459
|
+
};
|
|
8460
|
+
const onKey = (event) => {
|
|
8461
|
+
if (event.key === "Escape") close();
|
|
8462
|
+
};
|
|
8463
|
+
const onPointerDown = (event) => {
|
|
8464
|
+
if (!(event.target instanceof Node)) return;
|
|
8465
|
+
if (popupRef.current?.contains(event.target) === true || toolbarRef.current?.contains(event.target) === true) return;
|
|
8466
|
+
if (openRef.current) close();
|
|
8467
|
+
};
|
|
8468
|
+
document.addEventListener("selectionchange", schedule);
|
|
8469
|
+
document.addEventListener("mouseup", schedule);
|
|
8470
|
+
document.addEventListener("keydown", onKey);
|
|
8471
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
7192
8472
|
return () => {
|
|
7193
|
-
|
|
7194
|
-
|
|
8473
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
8474
|
+
document.removeEventListener("selectionchange", schedule);
|
|
8475
|
+
document.removeEventListener("mouseup", schedule);
|
|
8476
|
+
document.removeEventListener("keydown", onKey);
|
|
8477
|
+
document.removeEventListener("pointerdown", onPointerDown);
|
|
7195
8478
|
};
|
|
7196
|
-
}, [
|
|
8479
|
+
}, [
|
|
8480
|
+
close,
|
|
8481
|
+
currentSessionId,
|
|
8482
|
+
ownsSession
|
|
8483
|
+
]);
|
|
8484
|
+
useEffect(() => () => controller.current?.abort(), []);
|
|
8485
|
+
useEffect(() => {
|
|
8486
|
+
setRect(selection?.rect);
|
|
8487
|
+
if (selection === void 0) return;
|
|
8488
|
+
let frame;
|
|
8489
|
+
const reposition = () => {
|
|
8490
|
+
if (frame !== void 0) return;
|
|
8491
|
+
frame = requestAnimationFrame(() => {
|
|
8492
|
+
frame = void 0;
|
|
8493
|
+
const next = rectOf(selection.range);
|
|
8494
|
+
if (next.width === 0 && next.bottom === next.top) return;
|
|
8495
|
+
setRect(next);
|
|
8496
|
+
});
|
|
8497
|
+
};
|
|
8498
|
+
document.addEventListener("scroll", reposition, true);
|
|
8499
|
+
window.addEventListener("resize", reposition);
|
|
8500
|
+
return () => {
|
|
8501
|
+
if (frame !== void 0) cancelAnimationFrame(frame);
|
|
8502
|
+
document.removeEventListener("scroll", reposition, true);
|
|
8503
|
+
window.removeEventListener("resize", reposition);
|
|
8504
|
+
};
|
|
8505
|
+
}, [selection]);
|
|
8506
|
+
useEffect(() => {
|
|
8507
|
+
if (!open || selection === void 0) return;
|
|
8508
|
+
const runtime = globalThis;
|
|
8509
|
+
const registry = runtime.CSS?.highlights;
|
|
8510
|
+
if (registry === void 0 || runtime.Highlight === void 0) return;
|
|
8511
|
+
registry.set(HIGHLIGHT_NAME, new runtime.Highlight(selection.range));
|
|
8512
|
+
return () => {
|
|
8513
|
+
registry.delete(HIGHLIGHT_NAME);
|
|
8514
|
+
};
|
|
8515
|
+
}, [open, selection]);
|
|
8516
|
+
useEffect(() => {
|
|
8517
|
+
if (copied === void 0) return;
|
|
8518
|
+
const timer = setTimeout(() => setCopied(void 0), 1200);
|
|
8519
|
+
return () => clearTimeout(timer);
|
|
8520
|
+
}, [copied]);
|
|
8521
|
+
if (selection === void 0 || rect === void 0) return /* @__PURE__ */ jsx("span", {
|
|
8522
|
+
"data-dsh-claude-selection-ask": "armed",
|
|
8523
|
+
hidden: true
|
|
8524
|
+
});
|
|
8525
|
+
const copy = (text, what) => {
|
|
8526
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
8527
|
+
setCopied(what);
|
|
8528
|
+
}, () => void 0);
|
|
8529
|
+
};
|
|
8530
|
+
const submit = () => {
|
|
8531
|
+
if (question.trim().length === 0 || phase === "answering") return;
|
|
8532
|
+
controller.current?.abort();
|
|
8533
|
+
const aborter = new AbortController();
|
|
8534
|
+
controller.current = aborter;
|
|
8535
|
+
setBlocks([]);
|
|
8536
|
+
setThinking("");
|
|
8537
|
+
setThinkingOpen(false);
|
|
8538
|
+
setStarted(false);
|
|
8539
|
+
setError(void 0);
|
|
8540
|
+
setPhase("answering");
|
|
8541
|
+
askAboutSelection(selection.sessionId, {
|
|
8542
|
+
selection: selection.text,
|
|
8543
|
+
context: selection.context,
|
|
8544
|
+
question
|
|
8545
|
+
}, (progress) => {
|
|
8546
|
+
if (progress.type === "status") setStarted(true);
|
|
8547
|
+
else if (progress.type === "thinking") setThinking((current) => current + progress.text);
|
|
8548
|
+
else setBlocks((current) => appendAnswerBlock(current, progress));
|
|
8549
|
+
}, aborter.signal).then(() => {
|
|
8550
|
+
if (!aborter.signal.aborted) setPhase("done");
|
|
8551
|
+
}, (reason) => {
|
|
8552
|
+
if (aborter.signal.aborted) return;
|
|
8553
|
+
setError(reason instanceof Error ? reason.message : t("askFailed"));
|
|
8554
|
+
setPhase("done");
|
|
8555
|
+
});
|
|
8556
|
+
};
|
|
8557
|
+
const viewportWidth = typeof window === "undefined" ? 1280 : window.innerWidth;
|
|
8558
|
+
const viewportHeight = typeof window === "undefined" ? 800 : window.innerHeight;
|
|
8559
|
+
if (!open) {
|
|
8560
|
+
const position = toolbarPosition(rect, viewportWidth);
|
|
8561
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
8562
|
+
ref: toolbarRef,
|
|
8563
|
+
role: "toolbar",
|
|
8564
|
+
"aria-label": t("askToolbar"),
|
|
8565
|
+
style: {
|
|
8566
|
+
...askToolbar,
|
|
8567
|
+
top: position.top,
|
|
8568
|
+
left: position.left
|
|
8569
|
+
},
|
|
8570
|
+
children: [
|
|
8571
|
+
/* @__PURE__ */ jsx("style", {
|
|
8572
|
+
"data-dsh-claude-ask-styles": true,
|
|
8573
|
+
children: panelIconButtonCss
|
|
8574
|
+
}),
|
|
8575
|
+
/* @__PURE__ */ jsx(Tooltip, {
|
|
8576
|
+
label: copied === "selection" ? t("askCopied") : t("copyTooltip"),
|
|
8577
|
+
side: "top",
|
|
8578
|
+
delayMs: 300,
|
|
8579
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
8580
|
+
type: "button",
|
|
8581
|
+
className: panelIconButtonClass,
|
|
8582
|
+
"aria-label": t("copyTooltip"),
|
|
8583
|
+
onMouseDown: (event) => {
|
|
8584
|
+
event.preventDefault();
|
|
8585
|
+
},
|
|
8586
|
+
onClick: () => {
|
|
8587
|
+
copy(selection.text, "selection");
|
|
8588
|
+
},
|
|
8589
|
+
children: copied === "selection" ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {})
|
|
8590
|
+
})
|
|
8591
|
+
}),
|
|
8592
|
+
/* @__PURE__ */ jsx(Tooltip, {
|
|
8593
|
+
label: t("askTooltip"),
|
|
8594
|
+
side: "top",
|
|
8595
|
+
delayMs: 300,
|
|
8596
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
8597
|
+
type: "button",
|
|
8598
|
+
className: panelIconButtonClass,
|
|
8599
|
+
"aria-label": t("askTooltip"),
|
|
8600
|
+
onMouseDown: (event) => {
|
|
8601
|
+
event.preventDefault();
|
|
8602
|
+
},
|
|
8603
|
+
onClick: () => {
|
|
8604
|
+
setSide(popupSide(rect, viewportHeight));
|
|
8605
|
+
setOpen(true);
|
|
8606
|
+
},
|
|
8607
|
+
children: /* @__PURE__ */ jsx(AskIcon, {})
|
|
8608
|
+
})
|
|
8609
|
+
})
|
|
8610
|
+
]
|
|
8611
|
+
});
|
|
8612
|
+
}
|
|
8613
|
+
const placement = popupPlacement(rect, side, viewportWidth, viewportHeight);
|
|
7197
8614
|
return /* @__PURE__ */ jsxs("div", {
|
|
7198
|
-
|
|
8615
|
+
ref: popupRef,
|
|
8616
|
+
role: "dialog",
|
|
8617
|
+
"aria-label": t("askTooltip"),
|
|
8618
|
+
style: {
|
|
8619
|
+
...askPopup,
|
|
8620
|
+
...placement
|
|
8621
|
+
},
|
|
7199
8622
|
children: [
|
|
7200
|
-
/* @__PURE__ */
|
|
7201
|
-
"data-dsh-claude-
|
|
7202
|
-
children: panelIconButtonCss
|
|
8623
|
+
/* @__PURE__ */ jsxs("style", {
|
|
8624
|
+
"data-dsh-claude-ask-styles": true,
|
|
8625
|
+
children: [panelIconButtonCss, askHighlightCss]
|
|
7203
8626
|
}),
|
|
7204
|
-
/* @__PURE__ */
|
|
7205
|
-
style:
|
|
7206
|
-
children:
|
|
7207
|
-
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
|
|
8627
|
+
/* @__PURE__ */ jsx("p", {
|
|
8628
|
+
style: askQuote,
|
|
8629
|
+
children: selection.text
|
|
8630
|
+
}),
|
|
8631
|
+
phase === "idle" ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("textarea", {
|
|
8632
|
+
autoFocus: true,
|
|
8633
|
+
value: question,
|
|
8634
|
+
placeholder: t("askPlaceholder"),
|
|
8635
|
+
style: askTextarea,
|
|
8636
|
+
onChange: (event) => {
|
|
8637
|
+
setQuestion(event.currentTarget.value);
|
|
8638
|
+
},
|
|
8639
|
+
onKeyDown: (event) => {
|
|
8640
|
+
if (event.key === "Enter" && !event.shiftKey && !event.nativeEvent.isComposing) {
|
|
8641
|
+
event.preventDefault();
|
|
8642
|
+
submit();
|
|
8643
|
+
}
|
|
8644
|
+
}
|
|
8645
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
8646
|
+
style: askActions,
|
|
8647
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
7213
8648
|
type: "button",
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
|
|
8649
|
+
style: askButton,
|
|
8650
|
+
onClick: close,
|
|
8651
|
+
children: t("askClose")
|
|
8652
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
8653
|
+
type: "button",
|
|
8654
|
+
style: {
|
|
8655
|
+
...askButton,
|
|
8656
|
+
...askPrimaryButton
|
|
8657
|
+
},
|
|
8658
|
+
disabled: question.trim().length === 0,
|
|
8659
|
+
onClick: submit,
|
|
8660
|
+
children: t("askSubmit")
|
|
7218
8661
|
})]
|
|
7219
|
-
}),
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7225
|
-
|
|
7226
|
-
|
|
7227
|
-
|
|
7228
|
-
|
|
7229
|
-
|
|
7230
|
-
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
|
|
7235
|
-
|
|
7236
|
-
|
|
8662
|
+
})] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
8663
|
+
/* @__PURE__ */ jsx("p", {
|
|
8664
|
+
style: askQuestion,
|
|
8665
|
+
children: question
|
|
8666
|
+
}),
|
|
8667
|
+
/* @__PURE__ */ jsxs("div", {
|
|
8668
|
+
style: askAnswer,
|
|
8669
|
+
children: [
|
|
8670
|
+
thinking.length === 0 ? null : /* @__PURE__ */ jsxs("button", {
|
|
8671
|
+
type: "button",
|
|
8672
|
+
style: askThinkingRow,
|
|
8673
|
+
"aria-expanded": thinkingOpen,
|
|
8674
|
+
onClick: () => {
|
|
8675
|
+
setThinkingOpen((value) => !value);
|
|
8676
|
+
},
|
|
8677
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
8678
|
+
style: askThinkingLabel,
|
|
8679
|
+
children: phase === "answering" && answer.length === 0 ? t("askThinkingLive") : t("askThinkingLabel")
|
|
8680
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
8681
|
+
style: thinkingOpen ? askThinkingFull : askThinkingPreview,
|
|
8682
|
+
children: thinkingOpen ? thinking : thinking.trimEnd().split("\n").filter((line) => line.trim().length > 0).at(-1)
|
|
8683
|
+
})]
|
|
8684
|
+
}),
|
|
8685
|
+
blocks.length === 0 && thinking.length === 0 && error === void 0 ? /* @__PURE__ */ jsx("span", {
|
|
8686
|
+
style: askStatus,
|
|
8687
|
+
children: started ? t("askThinking") : t("askStarting")
|
|
8688
|
+
}) : null,
|
|
8689
|
+
blocks.map((block, index) => block.kind === "text" ? /* @__PURE__ */ jsx(MarkdownText, {
|
|
8690
|
+
text: block.text,
|
|
8691
|
+
streaming: phase === "answering" && index === blocks.length - 1
|
|
8692
|
+
}, `text-${index}`) : /* @__PURE__ */ jsxs("div", {
|
|
8693
|
+
style: askToolRow,
|
|
7237
8694
|
children: [
|
|
7238
|
-
row.running === true ? /* @__PURE__ */ jsx("span", {
|
|
7239
|
-
style: overviewRunningDot,
|
|
7240
|
-
"aria-label": t("overviewRunning")
|
|
7241
|
-
}) : null,
|
|
7242
8695
|
/* @__PURE__ */ jsx("span", {
|
|
7243
|
-
style:
|
|
7244
|
-
|
|
8696
|
+
style: {
|
|
8697
|
+
...askToolGlyph,
|
|
8698
|
+
...block.state === "error" ? askToolGlyphError : block.state === "done" ? askToolGlyphDone : {}
|
|
8699
|
+
},
|
|
8700
|
+
"aria-hidden": "true",
|
|
8701
|
+
children: block.state === "running" ? "…" : block.state === "done" ? "✓" : "×"
|
|
7245
8702
|
}),
|
|
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
8703
|
/* @__PURE__ */ jsx("span", {
|
|
7256
|
-
style:
|
|
7257
|
-
children:
|
|
8704
|
+
style: askToolName,
|
|
8705
|
+
children: block.name
|
|
7258
8706
|
}),
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
})
|
|
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
|
|
8707
|
+
block.summary === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
8708
|
+
style: askToolSummary,
|
|
8709
|
+
children: block.summary
|
|
8710
|
+
})
|
|
7271
8711
|
]
|
|
7272
|
-
})
|
|
7273
|
-
|
|
8712
|
+
}, block.id)),
|
|
8713
|
+
error === void 0 ? null : /* @__PURE__ */ jsx("p", {
|
|
8714
|
+
role: "alert",
|
|
8715
|
+
style: askError,
|
|
8716
|
+
children: error
|
|
8717
|
+
})
|
|
8718
|
+
]
|
|
8719
|
+
}),
|
|
8720
|
+
/* @__PURE__ */ jsxs("div", {
|
|
8721
|
+
style: askActions,
|
|
8722
|
+
children: [
|
|
8723
|
+
answer.length === 0 ? null : /* @__PURE__ */ jsx("button", {
|
|
8724
|
+
type: "button",
|
|
8725
|
+
style: askButton,
|
|
8726
|
+
onClick: () => {
|
|
8727
|
+
copy(answer, "answer");
|
|
8728
|
+
},
|
|
8729
|
+
children: copied === "answer" ? t("askCopied") : t("askCopyAnswer")
|
|
8730
|
+
}),
|
|
8731
|
+
answer.length === 0 || insertIntoChat === void 0 ? null : /* @__PURE__ */ jsx("button", {
|
|
8732
|
+
type: "button",
|
|
8733
|
+
style: askButton,
|
|
8734
|
+
onClick: () => {
|
|
8735
|
+
insertIntoChat(selection.sessionId, `> ${selection.text.replaceAll("\n", "\n> ")}\n\n**${question}**\n\n${answer}`);
|
|
8736
|
+
close();
|
|
8737
|
+
},
|
|
8738
|
+
children: t("askSendToChat")
|
|
8739
|
+
}),
|
|
8740
|
+
/* @__PURE__ */ jsx("button", {
|
|
8741
|
+
type: "button",
|
|
8742
|
+
style: {
|
|
8743
|
+
...askButton,
|
|
8744
|
+
...askPrimaryButton
|
|
8745
|
+
},
|
|
8746
|
+
onClick: close,
|
|
8747
|
+
children: t("askClose")
|
|
8748
|
+
})
|
|
8749
|
+
]
|
|
7274
8750
|
})
|
|
7275
|
-
})
|
|
8751
|
+
] })
|
|
7276
8752
|
]
|
|
7277
8753
|
});
|
|
7278
8754
|
}
|
|
@@ -7310,9 +8786,15 @@ window.__ModuleLoader__.load({
|
|
|
7310
8786
|
row = row.parentElement;
|
|
7311
8787
|
}
|
|
7312
8788
|
}
|
|
8789
|
+
/** Reuse the row's existing portal even when the host moved a node between it
|
|
8790
|
+
* and the seat: a fresh element would change React's portal identity and
|
|
8791
|
+
* restart (and abort) every effect keyed on it. */
|
|
7313
8792
|
function ensureClaudeHeroPortal(seat) {
|
|
7314
|
-
const
|
|
7315
|
-
if (
|
|
8793
|
+
const existing = seat.parentElement?.querySelector(`:scope > [${PORTAL_ATTRIBUTE}]`) ?? null;
|
|
8794
|
+
if (existing !== null) {
|
|
8795
|
+
if (existing.previousElementSibling !== seat) seat.insertAdjacentElement("afterend", existing);
|
|
8796
|
+
return existing;
|
|
8797
|
+
}
|
|
7316
8798
|
const portal = document.createElement("span");
|
|
7317
8799
|
portal.setAttribute(PORTAL_ATTRIBUTE, "");
|
|
7318
8800
|
seat.insertAdjacentElement("afterend", portal);
|
|
@@ -7347,12 +8829,18 @@ window.__ModuleLoader__.load({
|
|
|
7347
8829
|
const normalized = query.trim().toLocaleLowerCase();
|
|
7348
8830
|
return normalized.length === 0 ? branches : branches.filter((branch) => branch.toLocaleLowerCase().includes(normalized));
|
|
7349
8831
|
}
|
|
8832
|
+
/** Toggle a ticket's membership in the multi-select, keyed by ticket key. */
|
|
8833
|
+
function toggleTicketSelection(tickets, ticket) {
|
|
8834
|
+
return tickets.some((item) => item.key === ticket.key) ? tickets.filter((item) => item.key !== ticket.key) : [...tickets, ticket];
|
|
8835
|
+
}
|
|
7350
8836
|
function branchMenuNavigationIndex(current, count, key) {
|
|
7351
8837
|
if (count <= 0) return 0;
|
|
7352
8838
|
if (key === "Home") return 0;
|
|
7353
8839
|
if (key === "End") return count - 1;
|
|
7354
8840
|
return (current + (key === "ArrowDown" ? 1 : -1) + count) % count;
|
|
7355
8841
|
}
|
|
8842
|
+
const BRANCH_LOAD_RETRIES = 2;
|
|
8843
|
+
const BRANCH_LOAD_RETRY_MS = 1e3;
|
|
7356
8844
|
const WORKTREE_PROGRESS_STAGES = [
|
|
7357
8845
|
"inspecting",
|
|
7358
8846
|
"fetching",
|
|
@@ -7377,7 +8865,7 @@ window.__ModuleLoader__.load({
|
|
|
7377
8865
|
function progressLabelKey(stage) {
|
|
7378
8866
|
return PROGRESS_LABEL_KEYS[stage];
|
|
7379
8867
|
}
|
|
7380
|
-
function WorktreeProgressCard({ stage, error, t, onDismiss }) {
|
|
8868
|
+
function WorktreeProgressCard({ stage, error, context, t, onDismiss }) {
|
|
7381
8869
|
const current = WORKTREE_PROGRESS_STAGES.indexOf(stage);
|
|
7382
8870
|
const visible = WORKTREE_PROGRESS_STAGES.slice(0, Math.max(0, current) + 1);
|
|
7383
8871
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -7421,9 +8909,12 @@ window.__ModuleLoader__.load({
|
|
|
7421
8909
|
}),
|
|
7422
8910
|
/* @__PURE__ */ jsxs("div", {
|
|
7423
8911
|
style: heroWorktreeProgressCopy,
|
|
7424
|
-
children: [/* @__PURE__ */
|
|
8912
|
+
children: [/* @__PURE__ */ jsxs("strong", {
|
|
7425
8913
|
style: heroWorktreeProgressTitle,
|
|
7426
|
-
children: error === void 0 ? t("repositoryProgressTitle") : t("repositoryProgressFailed")
|
|
8914
|
+
children: [error === void 0 ? t("repositoryProgressTitle") : t("repositoryProgressFailed"), context === void 0 ? null : /* @__PURE__ */ jsxs("span", {
|
|
8915
|
+
style: heroWorktreeProgressContext,
|
|
8916
|
+
children: [" ", context]
|
|
8917
|
+
})]
|
|
7427
8918
|
}), /* @__PURE__ */ jsx("span", {
|
|
7428
8919
|
style: heroWorktreeProgressCurrent,
|
|
7429
8920
|
children: error ?? t(progressLabelKey(stage))
|
|
@@ -7470,7 +8961,7 @@ window.__ModuleLoader__.load({
|
|
|
7470
8961
|
})]
|
|
7471
8962
|
});
|
|
7472
8963
|
}
|
|
7473
|
-
function ClaudeHeroRepositoryCapsule({ branches, selected, worktree, busy, menuOpen, worktreeLabel, searchPlaceholder, emptySearchLabel, onMenuOpenChange, onSelect, onWorktreeChange }) {
|
|
8964
|
+
function ClaudeHeroRepositoryCapsule({ branches, selected, worktree, busy, menuOpen, worktreeLabel, searchPlaceholder, emptySearchLabel, worktreeLocked = false, onMenuOpenChange, onSelect, onWorktreeChange }) {
|
|
7474
8965
|
const pickerRef = useRef(null);
|
|
7475
8966
|
const searchRef = useRef(null);
|
|
7476
8967
|
const optionRefs = useRef([]);
|
|
@@ -7599,11 +9090,11 @@ window.__ModuleLoader__.load({
|
|
|
7599
9090
|
/* @__PURE__ */ jsxs("button", {
|
|
7600
9091
|
type: "button",
|
|
7601
9092
|
role: "checkbox",
|
|
7602
|
-
"aria-checked": worktree,
|
|
7603
|
-
disabled: busy,
|
|
9093
|
+
"aria-checked": worktreeLocked || worktree,
|
|
9094
|
+
disabled: busy || worktreeLocked,
|
|
7604
9095
|
style: {
|
|
7605
9096
|
...heroWorktreeToggle,
|
|
7606
|
-
...worktree || worktreeHovered ? heroWorktreeToggleActive : {},
|
|
9097
|
+
...worktreeLocked || worktree || worktreeHovered ? heroWorktreeToggleActive : {},
|
|
7607
9098
|
...worktreeFocused ? heroWorktreeToggleFocused : {}
|
|
7608
9099
|
},
|
|
7609
9100
|
onMouseEnter: () => {
|
|
@@ -7612,8 +9103,8 @@ window.__ModuleLoader__.load({
|
|
|
7612
9103
|
onMouseLeave: () => {
|
|
7613
9104
|
setWorktreeHovered(false);
|
|
7614
9105
|
},
|
|
7615
|
-
onFocus: () => {
|
|
7616
|
-
setWorktreeFocused(
|
|
9106
|
+
onFocus: (event) => {
|
|
9107
|
+
setWorktreeFocused(event.currentTarget.matches(":focus-visible"));
|
|
7617
9108
|
},
|
|
7618
9109
|
onBlur: () => {
|
|
7619
9110
|
setWorktreeFocused(false);
|
|
@@ -7625,9 +9116,9 @@ window.__ModuleLoader__.load({
|
|
|
7625
9116
|
"aria-hidden": "true",
|
|
7626
9117
|
style: {
|
|
7627
9118
|
...heroWorktreeCheckbox,
|
|
7628
|
-
...worktree ? heroWorktreeCheckboxChecked : {}
|
|
9119
|
+
...worktreeLocked || worktree ? heroWorktreeCheckboxChecked : {}
|
|
7629
9120
|
},
|
|
7630
|
-
children: worktree ? /* @__PURE__ */ jsx("svg", {
|
|
9121
|
+
children: worktreeLocked || worktree ? /* @__PURE__ */ jsx("svg", {
|
|
7631
9122
|
viewBox: "0 0 12 12",
|
|
7632
9123
|
style: heroWorktreeCheckboxIcon,
|
|
7633
9124
|
children: /* @__PURE__ */ jsx("path", {
|
|
@@ -7644,7 +9135,7 @@ window.__ModuleLoader__.load({
|
|
|
7644
9135
|
]
|
|
7645
9136
|
});
|
|
7646
9137
|
}
|
|
7647
|
-
function ClaudeHeroRepositoryControls({ sessionId, useSessions, useWorkspaces, input, t, prepare }) {
|
|
9138
|
+
function ClaudeHeroRepositoryControls({ sessionId, useSessions, useWorkspaces, input, t, prepare, prepareMany }) {
|
|
7648
9139
|
const cwd = useSessions((state) => state.byId[sessionId]?.cwd);
|
|
7649
9140
|
const workspacePath = useWorkspaces((state) => state.items.find((item) => item.sessionIds.includes(sessionId))?.path);
|
|
7650
9141
|
const [portal, setPortal] = useState();
|
|
@@ -7657,7 +9148,9 @@ window.__ModuleLoader__.load({
|
|
|
7657
9148
|
const [progressError, setProgressError] = useState();
|
|
7658
9149
|
const [error, setError] = useState();
|
|
7659
9150
|
const [jiraConnected, setJiraConnected] = useState(false);
|
|
7660
|
-
const [
|
|
9151
|
+
const [tickets, setTickets] = useState([]);
|
|
9152
|
+
const [batchProgress, setBatchProgress] = useState();
|
|
9153
|
+
const [batchDone, setBatchDone] = useState();
|
|
7661
9154
|
const [ticketMenuOpen, setTicketMenuOpen] = useState(false);
|
|
7662
9155
|
const [ticketQuery, setTicketQuery] = useState("");
|
|
7663
9156
|
const [ticketResults, setTicketResults] = useState();
|
|
@@ -7706,21 +9199,35 @@ window.__ModuleLoader__.load({
|
|
|
7706
9199
|
setProgressStage(void 0);
|
|
7707
9200
|
setProgressError(void 0);
|
|
7708
9201
|
setError(void 0);
|
|
7709
|
-
|
|
9202
|
+
setTickets([]);
|
|
9203
|
+
setBatchProgress(void 0);
|
|
9204
|
+
setBatchDone(void 0);
|
|
7710
9205
|
setTicketMenuOpen(false);
|
|
7711
9206
|
setTicketQuery("");
|
|
7712
9207
|
setTicketResults(void 0);
|
|
7713
9208
|
setTicketError(void 0);
|
|
7714
9209
|
if (portal === void 0 || path === void 0) return;
|
|
7715
9210
|
const controller = new AbortController();
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
9211
|
+
let timer;
|
|
9212
|
+
const load = (remaining) => {
|
|
9213
|
+
loadRepositoryBranches(path, controller.signal).then((value) => {
|
|
9214
|
+
setBranches(value);
|
|
9215
|
+
setSelected(value.current ?? value.branches[0] ?? "");
|
|
9216
|
+
}, (reason) => {
|
|
9217
|
+
if (controller.signal.aborted) return;
|
|
9218
|
+
if (remaining > 0) {
|
|
9219
|
+
timer = setTimeout(() => {
|
|
9220
|
+
load(remaining - 1);
|
|
9221
|
+
}, BRANCH_LOAD_RETRY_MS);
|
|
9222
|
+
return;
|
|
9223
|
+
}
|
|
9224
|
+
setError(reason instanceof Error ? reason.message : String(reason));
|
|
9225
|
+
});
|
|
9226
|
+
};
|
|
9227
|
+
load(BRANCH_LOAD_RETRIES);
|
|
7722
9228
|
return () => {
|
|
7723
9229
|
controller.abort();
|
|
9230
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
7724
9231
|
};
|
|
7725
9232
|
}, [
|
|
7726
9233
|
portal,
|
|
@@ -7728,19 +9235,46 @@ window.__ModuleLoader__.load({
|
|
|
7728
9235
|
sessionId
|
|
7729
9236
|
]);
|
|
7730
9237
|
const availableBranches = branches === void 0 ? [] : repositoryBranchOptions(branches);
|
|
7731
|
-
const changed = branches !== void 0 && selected.length > 0 && (worktree ||
|
|
9238
|
+
const changed = branches !== void 0 && selected.length > 0 && (worktree || tickets.length > 0 || selected !== branches.current);
|
|
7732
9239
|
useEffect(() => {
|
|
7733
9240
|
if (!changed || portal === void 0 || busy) return;
|
|
7734
9241
|
const submit = (event) => {
|
|
7735
|
-
if (pendingRef.current || input.draft.trim().length === 0 &&
|
|
9242
|
+
if (pendingRef.current || input.draft.trim().length === 0 && tickets.length === 0) return;
|
|
7736
9243
|
if (!(event instanceof KeyboardEvent ? shouldInterceptKey(event) : shouldInterceptClick(event))) return;
|
|
7737
9244
|
event.preventDefault();
|
|
7738
9245
|
event.stopPropagation();
|
|
7739
9246
|
pendingRef.current = true;
|
|
7740
9247
|
setBusy(true);
|
|
7741
9248
|
setProgressError(void 0);
|
|
7742
|
-
setProgressStage(worktree ? "inspecting" : void 0);
|
|
7743
9249
|
setError(void 0);
|
|
9250
|
+
setBatchDone(void 0);
|
|
9251
|
+
if (tickets.length > 1) {
|
|
9252
|
+
const total = tickets.length;
|
|
9253
|
+
setBatchProgress({
|
|
9254
|
+
ticketKey: tickets[0]?.key ?? "",
|
|
9255
|
+
index: 0,
|
|
9256
|
+
total,
|
|
9257
|
+
stage: "inspecting"
|
|
9258
|
+
});
|
|
9259
|
+
setProgressStage("inspecting");
|
|
9260
|
+
prepareMany(branches.root, selected, tickets, (progress) => {
|
|
9261
|
+
setBatchProgress(progress);
|
|
9262
|
+
setProgressStage(progress.stage);
|
|
9263
|
+
}).then(() => {
|
|
9264
|
+
setBatchDone(total);
|
|
9265
|
+
setBatchProgress(void 0);
|
|
9266
|
+
setProgressStage(void 0);
|
|
9267
|
+
setTickets([]);
|
|
9268
|
+
}, (reason) => {
|
|
9269
|
+
setProgressError(reason instanceof Error ? reason.message : String(reason));
|
|
9270
|
+
}).finally(() => {
|
|
9271
|
+
pendingRef.current = false;
|
|
9272
|
+
setBusy(false);
|
|
9273
|
+
});
|
|
9274
|
+
return;
|
|
9275
|
+
}
|
|
9276
|
+
const ticket = tickets[0];
|
|
9277
|
+
setProgressStage(worktree ? "inspecting" : void 0);
|
|
7744
9278
|
prepare(branches.root, selected, worktree, (stage) => {
|
|
7745
9279
|
if (worktree) setProgressStage(stage);
|
|
7746
9280
|
}, ticket).catch((reason) => {
|
|
@@ -7765,8 +9299,9 @@ window.__ModuleLoader__.load({
|
|
|
7765
9299
|
input.draft,
|
|
7766
9300
|
portal,
|
|
7767
9301
|
prepare,
|
|
9302
|
+
prepareMany,
|
|
7768
9303
|
selected,
|
|
7769
|
-
|
|
9304
|
+
tickets,
|
|
7770
9305
|
worktree
|
|
7771
9306
|
]);
|
|
7772
9307
|
useEffect(() => {
|
|
@@ -7815,8 +9350,13 @@ window.__ModuleLoader__.load({
|
|
|
7815
9350
|
document.removeEventListener("pointerdown", closeOnOutsidePointer);
|
|
7816
9351
|
};
|
|
7817
9352
|
}, [ticketMenuOpen]);
|
|
7818
|
-
const
|
|
7819
|
-
|
|
9353
|
+
const toggleTicket = (next) => {
|
|
9354
|
+
setTickets((current) => toggleTicketSelection(current, next));
|
|
9355
|
+
setError(void 0);
|
|
9356
|
+
setBatchDone(void 0);
|
|
9357
|
+
};
|
|
9358
|
+
const clearTickets = () => {
|
|
9359
|
+
setTickets([]);
|
|
7820
9360
|
setError(void 0);
|
|
7821
9361
|
setTicketMenuOpen(false);
|
|
7822
9362
|
};
|
|
@@ -7836,6 +9376,7 @@ window.__ModuleLoader__.load({
|
|
|
7836
9376
|
worktreeLabel: t("repositoryWorktree"),
|
|
7837
9377
|
searchPlaceholder: t("repositoryBranchSearch"),
|
|
7838
9378
|
emptySearchLabel: t("repositoryBranchSearchEmpty"),
|
|
9379
|
+
worktreeLocked: tickets.length > 1,
|
|
7839
9380
|
onMenuOpenChange: setMenuOpen,
|
|
7840
9381
|
onSelect: (branch) => {
|
|
7841
9382
|
setSelected(branch);
|
|
@@ -7866,78 +9407,115 @@ window.__ModuleLoader__.load({
|
|
|
7866
9407
|
/* @__PURE__ */ jsx(TicketIcon, {}),
|
|
7867
9408
|
/* @__PURE__ */ jsx("span", {
|
|
7868
9409
|
style: heroBranchName,
|
|
7869
|
-
children:
|
|
9410
|
+
children: tickets.length === 0 ? t("heroTicket") : tickets.length === 1 ? tickets[0]?.key : t("heroTicketCount", { count: tickets.length })
|
|
7870
9411
|
}),
|
|
7871
9412
|
/* @__PURE__ */ jsx(IconChevronDownOutline14, {})
|
|
7872
9413
|
]
|
|
7873
9414
|
}), ticketMenuOpen ? /* @__PURE__ */ jsxs("span", {
|
|
7874
9415
|
role: "menu",
|
|
7875
|
-
style:
|
|
9416
|
+
style: {
|
|
9417
|
+
...heroBranchMenu,
|
|
9418
|
+
...heroTicketMenu
|
|
9419
|
+
},
|
|
7876
9420
|
onKeyDown: (event) => {
|
|
7877
9421
|
if (event.key === "Escape") {
|
|
7878
9422
|
event.preventDefault();
|
|
7879
9423
|
setTicketMenuOpen(false);
|
|
7880
9424
|
}
|
|
7881
9425
|
},
|
|
7882
|
-
children: [
|
|
7883
|
-
|
|
7884
|
-
|
|
7885
|
-
|
|
7886
|
-
|
|
7887
|
-
|
|
7888
|
-
|
|
7889
|
-
|
|
7890
|
-
|
|
7891
|
-
|
|
7892
|
-
|
|
7893
|
-
|
|
7894
|
-
|
|
7895
|
-
|
|
7896
|
-
|
|
7897
|
-
|
|
7898
|
-
style:
|
|
7899
|
-
children:
|
|
7900
|
-
|
|
7901
|
-
|
|
7902
|
-
|
|
7903
|
-
|
|
7904
|
-
|
|
7905
|
-
|
|
7906
|
-
|
|
7907
|
-
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
9426
|
+
children: [
|
|
9427
|
+
/* @__PURE__ */ jsxs("label", {
|
|
9428
|
+
style: heroBranchSearch,
|
|
9429
|
+
children: [/* @__PURE__ */ jsx(IconSearchOutline16, {}), /* @__PURE__ */ jsx("input", {
|
|
9430
|
+
ref: ticketSearchRef,
|
|
9431
|
+
type: "search",
|
|
9432
|
+
value: ticketQuery,
|
|
9433
|
+
placeholder: t("heroTicketSearch"),
|
|
9434
|
+
"aria-label": t("heroTicketSearch"),
|
|
9435
|
+
style: heroBranchSearchInput,
|
|
9436
|
+
onChange: (event) => {
|
|
9437
|
+
setTicketQuery(event.currentTarget.value);
|
|
9438
|
+
}
|
|
9439
|
+
})]
|
|
9440
|
+
}),
|
|
9441
|
+
tickets.length === 0 ? null : /* @__PURE__ */ jsxs("span", {
|
|
9442
|
+
style: heroTicketChips,
|
|
9443
|
+
children: [tickets.map((item) => /* @__PURE__ */ jsxs("span", {
|
|
9444
|
+
style: heroTicketChip,
|
|
9445
|
+
children: [item.key, /* @__PURE__ */ jsx("button", {
|
|
9446
|
+
type: "button",
|
|
9447
|
+
style: heroTicketChipRemove,
|
|
9448
|
+
"aria-label": t("heroTicketRemove", { key: item.key }),
|
|
9449
|
+
onClick: () => {
|
|
9450
|
+
toggleTicket(item);
|
|
9451
|
+
},
|
|
9452
|
+
children: "×"
|
|
9453
|
+
})]
|
|
9454
|
+
}, item.key)), tickets.length > 1 ? /* @__PURE__ */ jsx("button", {
|
|
9455
|
+
type: "button",
|
|
9456
|
+
style: heroTicketChipsClear,
|
|
9457
|
+
onClick: clearTickets,
|
|
7912
9458
|
children: t("heroTicketNone")
|
|
9459
|
+
}) : null]
|
|
9460
|
+
}),
|
|
9461
|
+
/* @__PURE__ */ jsx("span", {
|
|
9462
|
+
style: heroBranchList,
|
|
9463
|
+
children: ticketError !== void 0 ? /* @__PURE__ */ jsx("span", {
|
|
9464
|
+
style: heroBranchEmpty,
|
|
9465
|
+
children: ticketError
|
|
9466
|
+
}) : ticketResults === void 0 ? /* @__PURE__ */ jsx("span", {
|
|
9467
|
+
style: heroBranchEmpty,
|
|
9468
|
+
children: t("heroTicketLoading")
|
|
9469
|
+
}) : ticketResults.length === 0 ? /* @__PURE__ */ jsx("span", {
|
|
9470
|
+
style: heroBranchEmpty,
|
|
9471
|
+
children: t("heroTicketEmpty")
|
|
9472
|
+
}) : ticketResults.map((item) => {
|
|
9473
|
+
const picked = tickets.some((entry) => entry.key === item.key);
|
|
9474
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
9475
|
+
type: "button",
|
|
9476
|
+
role: "menuitemcheckbox",
|
|
9477
|
+
"aria-checked": picked,
|
|
9478
|
+
style: heroBranchItem,
|
|
9479
|
+
onClick: () => {
|
|
9480
|
+
toggleTicket(item);
|
|
9481
|
+
},
|
|
9482
|
+
children: [
|
|
9483
|
+
/* @__PURE__ */ jsx("span", {
|
|
9484
|
+
"aria-hidden": "true",
|
|
9485
|
+
style: {
|
|
9486
|
+
...heroTicketCheckbox,
|
|
9487
|
+
...picked ? heroWorktreeCheckboxChecked : {}
|
|
9488
|
+
},
|
|
9489
|
+
children: picked ? /* @__PURE__ */ jsx("svg", {
|
|
9490
|
+
viewBox: "0 0 12 12",
|
|
9491
|
+
style: heroWorktreeCheckboxIcon,
|
|
9492
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
9493
|
+
d: "m2.5 6.2 2.1 2.1 4.9-5",
|
|
9494
|
+
fill: "none",
|
|
9495
|
+
stroke: "currentColor",
|
|
9496
|
+
strokeLinecap: "round",
|
|
9497
|
+
strokeLinejoin: "round",
|
|
9498
|
+
strokeWidth: "1.8"
|
|
9499
|
+
})
|
|
9500
|
+
}) : null
|
|
9501
|
+
}),
|
|
9502
|
+
/* @__PURE__ */ jsx("span", {
|
|
9503
|
+
style: heroTicketKey,
|
|
9504
|
+
children: item.key
|
|
9505
|
+
}),
|
|
9506
|
+
/* @__PURE__ */ jsx("span", {
|
|
9507
|
+
style: heroBranchItemName,
|
|
9508
|
+
children: item.summary
|
|
9509
|
+
}),
|
|
9510
|
+
item.status === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
9511
|
+
style: heroTicketStatus,
|
|
9512
|
+
children: item.status
|
|
9513
|
+
})
|
|
9514
|
+
]
|
|
9515
|
+
}, item.key);
|
|
7913
9516
|
})
|
|
7914
|
-
})
|
|
7915
|
-
|
|
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
|
-
})]
|
|
9517
|
+
})
|
|
9518
|
+
]
|
|
7941
9519
|
}) : null]
|
|
7942
9520
|
})
|
|
7943
9521
|
}),
|
|
@@ -7945,14 +9523,21 @@ window.__ModuleLoader__.load({
|
|
|
7945
9523
|
role: "alert",
|
|
7946
9524
|
style: heroRepositoryError,
|
|
7947
9525
|
children: error
|
|
9526
|
+
}),
|
|
9527
|
+
batchDone === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
9528
|
+
role: "status",
|
|
9529
|
+
style: heroRepositoryStatus,
|
|
9530
|
+
children: t("heroBatchStarted", { count: batchDone })
|
|
7948
9531
|
})
|
|
7949
9532
|
] }), progressStage === void 0 || !busy && progressError === void 0 ? null : /* @__PURE__ */ jsx(WorktreeProgressCard, {
|
|
7950
9533
|
stage: progressStage,
|
|
7951
9534
|
...progressError === void 0 ? {} : { error: progressError },
|
|
9535
|
+
...batchProgress === void 0 ? {} : { context: `${batchProgress.ticketKey} · ${batchProgress.index + 1}/${batchProgress.total}` },
|
|
7952
9536
|
t,
|
|
7953
9537
|
onDismiss: () => {
|
|
7954
9538
|
setProgressStage(void 0);
|
|
7955
9539
|
setProgressError(void 0);
|
|
9540
|
+
setBatchProgress(void 0);
|
|
7956
9541
|
}
|
|
7957
9542
|
})]
|
|
7958
9543
|
}), portal);
|
|
@@ -8042,7 +9627,7 @@ window.__ModuleLoader__.load({
|
|
|
8042
9627
|
//#endregion
|
|
8043
9628
|
//#region src/client/details-resize.ts
|
|
8044
9629
|
const DETAILS_MIN_WIDTH = 300;
|
|
8045
|
-
const DETAILS_DEFAULT_WIDTH =
|
|
9630
|
+
const DETAILS_DEFAULT_WIDTH = 720;
|
|
8046
9631
|
const DETAILS_MAX_RATIO = .5;
|
|
8047
9632
|
const DRAG_THRESHOLD = 4;
|
|
8048
9633
|
function clampDetailsWidth(width, frameWidth) {
|
|
@@ -8243,14 +9828,16 @@ window.__ModuleLoader__.load({
|
|
|
8243
9828
|
globalSettings: "Claude Code 设置",
|
|
8244
9829
|
globalSettingsBody: "修改受支持的 Claude Code 与插件设置;其他字段会被保留。",
|
|
8245
9830
|
globalSettingsLoading: "正在加载全局设置…",
|
|
8246
|
-
globalSettingsNewSession: "
|
|
9831
|
+
globalSettingsNewSession: "修改仅对新建 Claude 会话生效。",
|
|
8247
9832
|
globalSettingsError: "全局设置保存失败",
|
|
8248
9833
|
outputStyle: "Output Style",
|
|
8249
9834
|
worktreeBranchPrefix: "Worktree 分支前缀",
|
|
8250
9835
|
worktreeBranchPrefixEffect: "分支前缀修改会应用于之后自动创建的 Worktree 分支;显式指定的完整分支名不会被修改。",
|
|
8251
9836
|
maxProcessesSetting: "Claude 进程上限",
|
|
8252
9837
|
idleTimeoutSetting: "闲置回收时长(分钟)",
|
|
8253
|
-
|
|
9838
|
+
maxProcessesEffect: "进程上限在下次启动 Claude 进程时生效。留空或非法值会被拒绝。",
|
|
9839
|
+
idleTimeoutEffect: "闲置回收时长在下一次回合结束后生效。留空或非法值会被拒绝。",
|
|
9840
|
+
settingHint: "查看说明",
|
|
8254
9841
|
pluginUpdate: "插件更新",
|
|
8255
9842
|
pluginUpdateBody: "检查 npm 上的新版本。只有可唯一识别的 npm 安装才能直接更新;本地开发链接不会被替换。",
|
|
8256
9843
|
updateNotChecked: "尚未检查更新。",
|
|
@@ -8288,7 +9875,22 @@ window.__ModuleLoader__.load({
|
|
|
8288
9875
|
tasksViewActivity: "查看活动",
|
|
8289
9876
|
tasksHideActivity: "收起活动",
|
|
8290
9877
|
tasksRunningCount: "{count} 个运行中任务",
|
|
8291
|
-
|
|
9878
|
+
planUsage: "账号额度",
|
|
9879
|
+
planUsageBody: "当前 Claude 订阅的用量窗口,来自 Claude Code 的 /usage 数据。会话空闲时自动刷新,也可随时手动刷新。",
|
|
9880
|
+
planUsageLoading: "读取中…",
|
|
9881
|
+
planUsageRefresh: "刷新额度",
|
|
9882
|
+
planUsageRefreshing: "刷新中…",
|
|
9883
|
+
planUsageUnavailable: "此账号没有订阅额度(API key、Bedrock、Vertex 等不受套餐限流)。",
|
|
9884
|
+
planUsageNever: "尚未获取额度数据,运行一次对话或点击刷新。",
|
|
9885
|
+
planUsageError: "额度读取失败",
|
|
9886
|
+
planUsageSubscription: "订阅",
|
|
9887
|
+
planUsageUpdated: "更新于 {age}前",
|
|
9888
|
+
planUsageResets: "{age}后重置",
|
|
9889
|
+
planUsageUsed: "已用 {percent}%",
|
|
9890
|
+
planWindow_five_hour: "5 小时",
|
|
9891
|
+
planWindow_seven_day: "全部模型 · 每周",
|
|
9892
|
+
planWindow_seven_day_opus: "Opus · 每周",
|
|
9893
|
+
planWindow_seven_day_sonnet: "Sonnet · 每周",
|
|
8292
9894
|
tasksTurnRunning: "{count} 个任务执行中",
|
|
8293
9895
|
tasksTurnCompleted: "{count} 个任务已完成",
|
|
8294
9896
|
tasksTurnFailed: "{failed} 个任务失败,{completed} 个已完成",
|
|
@@ -8436,7 +10038,10 @@ window.__ModuleLoader__.load({
|
|
|
8436
10038
|
heroTicketSearch: "搜索 ticket 或输入 key…",
|
|
8437
10039
|
heroTicketLoading: "搜索中…",
|
|
8438
10040
|
heroTicketEmpty: "没有匹配的 ticket",
|
|
8439
|
-
heroTicketNone: "
|
|
10041
|
+
heroTicketNone: "清除已选 ticket",
|
|
10042
|
+
heroTicketRemove: "移除 {key}",
|
|
10043
|
+
heroTicketCount: "{count} 个 ticket",
|
|
10044
|
+
heroBatchStarted: "已为 {count} 个 ticket 各自创建 Worktree 会话并开工",
|
|
8440
10045
|
heroTicketNotConnected: "请先在 Settings 中连接 Jira",
|
|
8441
10046
|
heroTicketFailed: "Ticket 搜索失败",
|
|
8442
10047
|
jiraTitle: "Jira",
|
|
@@ -8456,14 +10061,31 @@ window.__ModuleLoader__.load({
|
|
|
8456
10061
|
cleanupTitle: "清理已合并分支",
|
|
8457
10062
|
cleanupDescription: "删除 worktree 与本地分支并移除对应 workspace;普通 checkout 则切回 base 分支并删除已合并分支。",
|
|
8458
10063
|
cleanupCompleted: "已清理 {branch}",
|
|
8459
|
-
overviewOpen: "
|
|
8460
|
-
overviewTitle: "
|
|
8461
|
-
overviewBody: "所有 Claude
|
|
10064
|
+
overviewOpen: "打开 Claude 会话看板",
|
|
10065
|
+
overviewTitle: "会话看板",
|
|
10066
|
+
overviewBody: "所有 Claude 会话的运行状态、分支与 PR",
|
|
8462
10067
|
overviewEmpty: "没有正在进行的 Claude 会话",
|
|
8463
10068
|
overviewNoPr: "无 PR",
|
|
8464
10069
|
overviewRunning: "运行中",
|
|
10070
|
+
overviewNeedsPermission: "等待权限确认",
|
|
10071
|
+
overviewNeedsAnswer: "等待回答",
|
|
10072
|
+
overviewContextUsage: "上下文 {percentage}%",
|
|
8465
10073
|
overviewAutoFix: "Auto fix 已开启",
|
|
8466
10074
|
overviewLoading: "读取中…",
|
|
10075
|
+
askToolbar: "选中文本操作",
|
|
10076
|
+
askTooltip: "针对选中内容追问",
|
|
10077
|
+
copyTooltip: "复制",
|
|
10078
|
+
askCopied: "已复制",
|
|
10079
|
+
askPlaceholder: "针对选中内容提问…",
|
|
10080
|
+
askSubmit: "发送",
|
|
10081
|
+
askStarting: "正在启动 Claude…",
|
|
10082
|
+
askThinking: "思考中…",
|
|
10083
|
+
askThinkingLive: "思考中 ·",
|
|
10084
|
+
askThinkingLabel: "Think ·",
|
|
10085
|
+
askCopyAnswer: "复制回答",
|
|
10086
|
+
askSendToChat: "转发到对话",
|
|
10087
|
+
askClose: "关闭",
|
|
10088
|
+
askFailed: "提问失败",
|
|
8467
10089
|
reviewCommentAdd: "添加行评论",
|
|
8468
10090
|
reviewCommentPlaceholder: "请求更改",
|
|
8469
10091
|
reviewCommentSubmit: "注释",
|
|
@@ -8474,7 +10096,13 @@ window.__ModuleLoader__.load({
|
|
|
8474
10096
|
reviewCommentsSend: "发送评论",
|
|
8475
10097
|
reviewCommentsSendDraft: "请处理以上代码评论。",
|
|
8476
10098
|
reviewCommentOldSide: "旧代码第 {line} 行",
|
|
8477
|
-
reviewCommentNewSide: "第 {line} 行"
|
|
10099
|
+
reviewCommentNewSide: "第 {line} 行",
|
|
10100
|
+
reviewCommentOldRange: "旧代码第 {start}–{end} 行",
|
|
10101
|
+
reviewCommentNewRange: "第 {start}–{end} 行",
|
|
10102
|
+
diffUnmodifiedLines: "{count} 行未修改",
|
|
10103
|
+
diffUnmodifiedTail: "文件末尾之前还有未修改的行",
|
|
10104
|
+
diffExpandUp: "向上展开",
|
|
10105
|
+
diffExpandDown: "向下展开"
|
|
8478
10106
|
};
|
|
8479
10107
|
const en = {
|
|
8480
10108
|
nav: "Claude Code",
|
|
@@ -8514,14 +10142,16 @@ window.__ModuleLoader__.load({
|
|
|
8514
10142
|
globalSettings: "Claude Code settings",
|
|
8515
10143
|
globalSettingsBody: "Modify supported Claude Code and plugin settings while preserving every other field.",
|
|
8516
10144
|
globalSettingsLoading: "Loading global settings…",
|
|
8517
|
-
globalSettingsNewSession: "
|
|
10145
|
+
globalSettingsNewSession: "Changes apply only to new Claude sessions.",
|
|
8518
10146
|
globalSettingsError: "Global settings save failed",
|
|
8519
10147
|
outputStyle: "Output Style",
|
|
8520
10148
|
worktreeBranchPrefix: "Worktree branch prefix",
|
|
8521
10149
|
worktreeBranchPrefixEffect: "Prefix changes apply to subsequently generated Worktree branches. Explicit full branch names remain unchanged.",
|
|
8522
10150
|
maxProcessesSetting: "Claude process limit",
|
|
8523
10151
|
idleTimeoutSetting: "Idle timeout (minutes)",
|
|
8524
|
-
|
|
10152
|
+
maxProcessesEffect: "The process limit applies when the next Claude process is admitted. Blank or invalid values are rejected.",
|
|
10153
|
+
idleTimeoutEffect: "The idle timeout applies after the next completed turn. Blank or invalid values are rejected.",
|
|
10154
|
+
settingHint: "Show details",
|
|
8525
10155
|
pluginUpdate: "Plugin updates",
|
|
8526
10156
|
pluginUpdateBody: "Check npm for new releases. Only a uniquely identified npm installation can update in place; local development links are never replaced.",
|
|
8527
10157
|
updateNotChecked: "Updates have not been checked yet.",
|
|
@@ -8559,7 +10189,22 @@ window.__ModuleLoader__.load({
|
|
|
8559
10189
|
tasksViewActivity: "View activity",
|
|
8560
10190
|
tasksHideActivity: "Hide activity",
|
|
8561
10191
|
tasksRunningCount: "{count} running task(s)",
|
|
8562
|
-
|
|
10192
|
+
planUsage: "Plan usage",
|
|
10193
|
+
planUsageBody: "Utilization windows for the signed-in Claude subscription, from Claude Code's /usage data. Refreshes whenever a session goes idle, and on demand.",
|
|
10194
|
+
planUsageLoading: "Loading…",
|
|
10195
|
+
planUsageRefresh: "Refresh usage",
|
|
10196
|
+
planUsageRefreshing: "Refreshing…",
|
|
10197
|
+
planUsageUnavailable: "This account has no plan limits (API key, Bedrock, and Vertex sessions are not rate limited by a subscription).",
|
|
10198
|
+
planUsageNever: "No usage data yet — run a turn or refresh.",
|
|
10199
|
+
planUsageError: "Usage lookup failed",
|
|
10200
|
+
planUsageSubscription: "Subscription",
|
|
10201
|
+
planUsageUpdated: "Updated {age} ago",
|
|
10202
|
+
planUsageResets: "Resets in {age}",
|
|
10203
|
+
planUsageUsed: "{percent}% used",
|
|
10204
|
+
planWindow_five_hour: "5-hour",
|
|
10205
|
+
planWindow_seven_day: "All models · weekly",
|
|
10206
|
+
planWindow_seven_day_opus: "Opus · weekly",
|
|
10207
|
+
planWindow_seven_day_sonnet: "Sonnet · weekly",
|
|
8563
10208
|
tasksTurnRunning: "{count} task(s) running",
|
|
8564
10209
|
tasksTurnCompleted: "{count} task(s) completed",
|
|
8565
10210
|
tasksTurnFailed: "{failed} failed, {completed} completed",
|
|
@@ -8707,7 +10352,10 @@ window.__ModuleLoader__.load({
|
|
|
8707
10352
|
heroTicketSearch: "Search tickets or enter a key…",
|
|
8708
10353
|
heroTicketLoading: "Searching…",
|
|
8709
10354
|
heroTicketEmpty: "No matching tickets",
|
|
8710
|
-
heroTicketNone: "
|
|
10355
|
+
heroTicketNone: "Clear selected tickets",
|
|
10356
|
+
heroTicketRemove: "Remove {key}",
|
|
10357
|
+
heroTicketCount: "{count} tickets",
|
|
10358
|
+
heroBatchStarted: "Kicked off {count} tickets, each in its own worktree session",
|
|
8711
10359
|
heroTicketNotConnected: "Connect Jira in Settings first",
|
|
8712
10360
|
heroTicketFailed: "Ticket search failed",
|
|
8713
10361
|
jiraTitle: "Jira",
|
|
@@ -8727,14 +10375,31 @@ window.__ModuleLoader__.load({
|
|
|
8727
10375
|
cleanupTitle: "Clean up merged branch",
|
|
8728
10376
|
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
10377
|
cleanupCompleted: "Cleaned up {branch}",
|
|
8730
|
-
overviewOpen: "
|
|
8731
|
-
overviewTitle: "
|
|
8732
|
-
overviewBody: "
|
|
10378
|
+
overviewOpen: "Open the Claude session board",
|
|
10379
|
+
overviewTitle: "Session board",
|
|
10380
|
+
overviewBody: "Run state, branch, and pull request across Claude sessions",
|
|
8733
10381
|
overviewEmpty: "No active Claude sessions",
|
|
8734
10382
|
overviewNoPr: "No PR",
|
|
8735
10383
|
overviewRunning: "Running",
|
|
10384
|
+
overviewNeedsPermission: "Awaiting approval",
|
|
10385
|
+
overviewNeedsAnswer: "Awaiting answer",
|
|
10386
|
+
overviewContextUsage: "Context {percentage}%",
|
|
8736
10387
|
overviewAutoFix: "Auto fix on",
|
|
8737
10388
|
overviewLoading: "Loading…",
|
|
10389
|
+
askToolbar: "Selection actions",
|
|
10390
|
+
askTooltip: "Ask about this",
|
|
10391
|
+
copyTooltip: "Copy",
|
|
10392
|
+
askCopied: "Copied",
|
|
10393
|
+
askPlaceholder: "Ask about the selected text…",
|
|
10394
|
+
askSubmit: "Ask",
|
|
10395
|
+
askStarting: "Starting Claude…",
|
|
10396
|
+
askThinking: "Thinking…",
|
|
10397
|
+
askThinkingLive: "Thinking ·",
|
|
10398
|
+
askThinkingLabel: "Think ·",
|
|
10399
|
+
askCopyAnswer: "Copy answer",
|
|
10400
|
+
askSendToChat: "Send to chat",
|
|
10401
|
+
askClose: "Close",
|
|
10402
|
+
askFailed: "The question could not be answered",
|
|
8738
10403
|
reviewCommentAdd: "Add line comment",
|
|
8739
10404
|
reviewCommentPlaceholder: "Request changes",
|
|
8740
10405
|
reviewCommentSubmit: "Comment",
|
|
@@ -8745,7 +10410,13 @@ window.__ModuleLoader__.load({
|
|
|
8745
10410
|
reviewCommentsSend: "Send comments",
|
|
8746
10411
|
reviewCommentsSendDraft: "Please address the attached review comments.",
|
|
8747
10412
|
reviewCommentOldSide: "Old line {line}",
|
|
8748
|
-
reviewCommentNewSide: "Line {line}"
|
|
10413
|
+
reviewCommentNewSide: "Line {line}",
|
|
10414
|
+
reviewCommentOldRange: "Old lines {start}–{end}",
|
|
10415
|
+
reviewCommentNewRange: "Lines {start}–{end}",
|
|
10416
|
+
diffUnmodifiedLines: "{count} unmodified lines",
|
|
10417
|
+
diffUnmodifiedTail: "More unmodified lines below",
|
|
10418
|
+
diffExpandUp: "Expand up",
|
|
10419
|
+
diffExpandDown: "Expand down"
|
|
8749
10420
|
};
|
|
8750
10421
|
//#endregion
|
|
8751
10422
|
//#region src/client/index.tsx
|
|
@@ -8880,7 +10551,9 @@ window.__ModuleLoader__.load({
|
|
|
8880
10551
|
sessions.open(id);
|
|
8881
10552
|
},
|
|
8882
10553
|
loadStatus: loadRepositoryStatusFor,
|
|
8883
|
-
sessions: sessions.list
|
|
10554
|
+
sessions: sessions.list,
|
|
10555
|
+
...workspaces === void 0 ? {} : { workspaces: workspaces.list },
|
|
10556
|
+
projectionFor: (id) => projections.source(id)
|
|
8884
10557
|
})
|
|
8885
10558
|
}, ClaudePullRequestsPanel);
|
|
8886
10559
|
} catch {
|
|
@@ -9014,6 +10687,22 @@ window.__ModuleLoader__.load({
|
|
|
9014
10687
|
};
|
|
9015
10688
|
}
|
|
9016
10689
|
}, ClaudeRepositoryStatus));
|
|
10690
|
+
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
10691
|
+
name: "shell.overlay",
|
|
10692
|
+
id: "claude-selection-ask",
|
|
10693
|
+
locale: namespace
|
|
10694
|
+
}, () => /* @__PURE__ */ jsx(ClaudeSelectionAsk, {
|
|
10695
|
+
t,
|
|
10696
|
+
currentSessionId: () => sessions?.list.getSnapshot().current,
|
|
10697
|
+
ownsSession: (sessionId) => projections.source(sessionId).getSnapshot().owned,
|
|
10698
|
+
...sessions === void 0 || conversation === void 0 ? {} : { insertIntoChat: (sessionId, text) => {
|
|
10699
|
+
const scope = sessions.scope(sessionId);
|
|
10700
|
+
if (scope === void 0) return;
|
|
10701
|
+
const input = conversation.input.for(scope);
|
|
10702
|
+
const current = input.state.getSnapshot().draft;
|
|
10703
|
+
input.setDraft(current.trim() === "" ? text : `${current}\n\n${text}`);
|
|
10704
|
+
} }
|
|
10705
|
+
})));
|
|
9017
10706
|
if (sessions !== void 0 && conversation !== void 0) ctx.slots.inject("conversation.input.dock", () => ctx.slots.register({
|
|
9018
10707
|
name: "conversation.input.dock",
|
|
9019
10708
|
id: "queue",
|
|
@@ -9077,6 +10766,52 @@ window.__ModuleLoader__.load({
|
|
|
9077
10766
|
targetInput.submit();
|
|
9078
10767
|
sourceInput.setDraft("");
|
|
9079
10768
|
for (const imageId of imageIds) sourceInput.removeImage(imageId);
|
|
10769
|
+
},
|
|
10770
|
+
prepareMany: async (cwd, branch, tickets, onProgress) => {
|
|
10771
|
+
const sourceScope = sessions.scope(sourceSessionId);
|
|
10772
|
+
if (sourceScope === void 0) throw new Error(t("repositorySessionUnavailable"));
|
|
10773
|
+
const sourceInput = conversation.input.for(sourceScope);
|
|
10774
|
+
const rawDraft = sourceInput.state.getSnapshot().draft;
|
|
10775
|
+
const failures = [];
|
|
10776
|
+
for (const [index, ticket] of tickets.entries()) {
|
|
10777
|
+
const report = (stage) => {
|
|
10778
|
+
onProgress({
|
|
10779
|
+
ticketKey: ticket.key,
|
|
10780
|
+
index,
|
|
10781
|
+
total: tickets.length,
|
|
10782
|
+
stage
|
|
10783
|
+
});
|
|
10784
|
+
};
|
|
10785
|
+
try {
|
|
10786
|
+
report("inspecting");
|
|
10787
|
+
const prepared = await prepareRepository(cwd, branch, true, ticket.key, report);
|
|
10788
|
+
assignJiraTicket(ticket.key).catch((reason) => {
|
|
10789
|
+
console.warn(`dsh-claude: could not assign ${ticket.key}: ${reason instanceof Error ? reason.message : String(reason)}`);
|
|
10790
|
+
});
|
|
10791
|
+
report("creating-workspace");
|
|
10792
|
+
const workspace = await workspaces.create({ path: prepared.path });
|
|
10793
|
+
report("starting-session");
|
|
10794
|
+
const targetSessionId = await workspaces.connectWorkspace(workspace.workspaceId);
|
|
10795
|
+
const targetScope = sessions.scope(targetSessionId);
|
|
10796
|
+
if (targetScope === void 0) throw new Error(t("repositorySessionUnavailable"));
|
|
10797
|
+
const presetResponse = await connection.api.agentPresets.select({
|
|
10798
|
+
sessionId: targetSessionId,
|
|
10799
|
+
agentPreset: "claude"
|
|
10800
|
+
});
|
|
10801
|
+
if (!presetResponse.result.ok) throw new Error(presetResponse.result.error.message);
|
|
10802
|
+
sessions.noteAgentPreset(targetSessionId, presetResponse.result.value.agentPreset);
|
|
10803
|
+
const targetInput = conversation.input.for(targetScope);
|
|
10804
|
+
report("transferring-draft");
|
|
10805
|
+
targetInput.setDraft(rawDraft.trim() === "" ? ticketPrompt(ticket) : `${rawDraft.trimEnd()}\n\n${ticketContext(ticket)}`);
|
|
10806
|
+
if (prepared.leaseId !== void 0) await bindRepositoryLease(prepared.leaseId, targetSessionId);
|
|
10807
|
+
report("submitting");
|
|
10808
|
+
targetInput.submit();
|
|
10809
|
+
} catch (cause) {
|
|
10810
|
+
failures.push(`${ticket.key}: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
10811
|
+
}
|
|
10812
|
+
}
|
|
10813
|
+
if (failures.length < tickets.length) sourceInput.setDraft("");
|
|
10814
|
+
if (failures.length > 0) throw new Error(failures.join(" · "));
|
|
9080
10815
|
}
|
|
9081
10816
|
})
|
|
9082
10817
|
}, ClaudeHeroRepositoryControls));
|