@norman-else/dsh-claude 0.1.25 → 0.1.26
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 +30 -4
- package/lib/client.js +1667 -184
- package/lib/client.js.map +1 -1
- package/lib/{command-bridge-B48egrCr.mjs → command-bridge-vyZoEeEO.mjs} +2 -2
- package/lib/command-bridge-vyZoEeEO.mjs.map +1 -0
- package/lib/{events-BhU0iJUi.mjs → events-CY6V9oQ4.mjs} +5 -3
- package/lib/events-CY6V9oQ4.mjs.map +1 -0
- package/lib/index.mjs +486 -126
- package/lib/index.mjs.map +1 -1
- package/lib/{preset-installer-Bzw8tuGI.mjs → preset-installer-BMRaIHLu.mjs} +2 -2
- package/lib/preset-installer-BMRaIHLu.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
|
@@ -20,7 +20,9 @@ window.__ModuleLoader__.load({
|
|
|
20
20
|
const CLAUDE_REVIEW_COMMENT_PATH = "/plugins/dsh-claude/review-comments";
|
|
21
21
|
const CLAUDE_REPOSITORY_FEEDBACK_PATH = "/plugins/dsh-claude/repository/feedback";
|
|
22
22
|
const CLAUDE_REPOSITORY_STATUS_PATH = "/plugins/dsh-claude/repository/status";
|
|
23
|
+
const CLAUDE_REPOSITORY_FILE_PATH = "/plugins/dsh-claude/repository/file";
|
|
23
24
|
const CLAUDE_JIRA_PATH = "/plugins/dsh-claude/jira";
|
|
25
|
+
const CLAUDE_ASK_PATH = "/plugins/dsh-claude/ask";
|
|
24
26
|
//#endregion
|
|
25
27
|
//#region src/client/task-projection.ts
|
|
26
28
|
/** Tasks UI is reserved for detached work and genuine Claude subagents. */
|
|
@@ -751,16 +753,33 @@ window.__ModuleLoader__.load({
|
|
|
751
753
|
const tasksPanel = {
|
|
752
754
|
display: "flex",
|
|
753
755
|
flexDirection: "column",
|
|
754
|
-
width: "calc(100% - 16px)",
|
|
755
|
-
height: "calc(100% - 16px)",
|
|
756
756
|
minWidth: 0,
|
|
757
|
-
margin: 8,
|
|
758
757
|
overflow: "hidden",
|
|
759
758
|
border: "1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 16%, transparent))",
|
|
760
759
|
borderRadius: 12,
|
|
761
760
|
background: "var(--dsw-alias-bg-layer-1)",
|
|
762
761
|
boxShadow: "0 4px 16px color-mix(in srgb, #000 12%, transparent)"
|
|
763
762
|
};
|
|
763
|
+
const detailsCardClass = "dshClaudeDetailsCard";
|
|
764
|
+
/**
|
|
765
|
+
* Geometry shared by every details-column card. Lives in a stylesheet rather
|
|
766
|
+
* than inline so the DSH Desktop macOS shell can be special-cased: its
|
|
767
|
+
* "advanced" frame floats a 32px opaque caption/drag row over the top of the
|
|
768
|
+
* conversation and details columns, 12px of which lands inside the column and
|
|
769
|
+
* used to cover the card's top border and corners.
|
|
770
|
+
*/
|
|
771
|
+
const detailsCardCss = `
|
|
772
|
+
.${detailsCardClass} {
|
|
773
|
+
box-sizing: border-box;
|
|
774
|
+
width: calc(100% - 16px);
|
|
775
|
+
height: calc(100% - 16px);
|
|
776
|
+
margin: 8px;
|
|
777
|
+
}
|
|
778
|
+
.dshDesktopFrame[data-desktop-mode="advanced"][data-desktop-platform="darwin"] .dshDesktopDetailsSurface .${detailsCardClass} {
|
|
779
|
+
height: calc(100% - 28px);
|
|
780
|
+
margin-top: 20px;
|
|
781
|
+
}
|
|
782
|
+
`;
|
|
764
783
|
const tasksHeader = {
|
|
765
784
|
boxSizing: "border-box",
|
|
766
785
|
height: 58,
|
|
@@ -1131,7 +1150,7 @@ window.__ModuleLoader__.load({
|
|
|
1131
1150
|
background: "transparent",
|
|
1132
1151
|
color: "inherit",
|
|
1133
1152
|
font: "inherit",
|
|
1134
|
-
fontSize:
|
|
1153
|
+
fontSize: 13,
|
|
1135
1154
|
lineHeight: "18px",
|
|
1136
1155
|
cursor: "pointer"
|
|
1137
1156
|
};
|
|
@@ -1178,7 +1197,7 @@ window.__ModuleLoader__.load({
|
|
|
1178
1197
|
background: "transparent",
|
|
1179
1198
|
color: "var(--dsw-alias-label-primary)",
|
|
1180
1199
|
font: "inherit",
|
|
1181
|
-
fontSize:
|
|
1200
|
+
fontSize: 13,
|
|
1182
1201
|
lineHeight: "18px"
|
|
1183
1202
|
};
|
|
1184
1203
|
const heroBranchList = {
|
|
@@ -1190,8 +1209,8 @@ window.__ModuleLoader__.load({
|
|
|
1190
1209
|
};
|
|
1191
1210
|
const heroBranchItem = {
|
|
1192
1211
|
width: "100%",
|
|
1193
|
-
height:
|
|
1194
|
-
minHeight:
|
|
1212
|
+
height: 36,
|
|
1213
|
+
minHeight: 36,
|
|
1195
1214
|
display: "flex",
|
|
1196
1215
|
alignItems: "center",
|
|
1197
1216
|
gap: 8,
|
|
@@ -1201,7 +1220,7 @@ window.__ModuleLoader__.load({
|
|
|
1201
1220
|
background: "transparent",
|
|
1202
1221
|
color: "var(--dsw-alias-label-primary)",
|
|
1203
1222
|
font: "inherit",
|
|
1204
|
-
fontSize:
|
|
1223
|
+
fontSize: 13,
|
|
1205
1224
|
lineHeight: "18px",
|
|
1206
1225
|
textAlign: "left",
|
|
1207
1226
|
cursor: "pointer"
|
|
@@ -1215,11 +1234,11 @@ window.__ModuleLoader__.load({
|
|
|
1215
1234
|
whiteSpace: "nowrap"
|
|
1216
1235
|
};
|
|
1217
1236
|
const heroBranchEmpty = {
|
|
1218
|
-
height:
|
|
1237
|
+
height: 36,
|
|
1219
1238
|
display: "grid",
|
|
1220
1239
|
placeItems: "center",
|
|
1221
1240
|
color: "var(--dsw-alias-label-tertiary)",
|
|
1222
|
-
fontSize:
|
|
1241
|
+
fontSize: 13
|
|
1223
1242
|
};
|
|
1224
1243
|
const heroRepositoryDivider = {
|
|
1225
1244
|
width: 1,
|
|
@@ -1239,7 +1258,7 @@ window.__ModuleLoader__.load({
|
|
|
1239
1258
|
background: "transparent",
|
|
1240
1259
|
color: "var(--dsw-alias-label-secondary)",
|
|
1241
1260
|
font: "inherit",
|
|
1242
|
-
fontSize:
|
|
1261
|
+
fontSize: 13,
|
|
1243
1262
|
lineHeight: "18px",
|
|
1244
1263
|
whiteSpace: "nowrap",
|
|
1245
1264
|
cursor: "pointer",
|
|
@@ -1332,6 +1351,10 @@ window.__ModuleLoader__.load({
|
|
|
1332
1351
|
lineHeight: "18px",
|
|
1333
1352
|
overflowWrap: "anywhere"
|
|
1334
1353
|
};
|
|
1354
|
+
const heroWorktreeProgressContext = {
|
|
1355
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
1356
|
+
fontWeight: 500
|
|
1357
|
+
};
|
|
1335
1358
|
const heroWorktreeProgressDismiss = {
|
|
1336
1359
|
width: 24,
|
|
1337
1360
|
height: 24,
|
|
@@ -1691,6 +1714,14 @@ window.__ModuleLoader__.load({
|
|
|
1691
1714
|
borderRadius: 999,
|
|
1692
1715
|
background: "currentColor"
|
|
1693
1716
|
};
|
|
1717
|
+
const repositoryGlyph = {
|
|
1718
|
+
width: 16,
|
|
1719
|
+
height: 16,
|
|
1720
|
+
flex: "none",
|
|
1721
|
+
display: "grid",
|
|
1722
|
+
placeItems: "center",
|
|
1723
|
+
color: "var(--dsw-alias-label-tertiary)"
|
|
1724
|
+
};
|
|
1694
1725
|
const repositoryItemSuccess = { color: "var(--dsw-alias-state-success-primary)" };
|
|
1695
1726
|
const repositoryItemWarning = { color: "var(--dsw-alias-state-warning-primary, #d69e2e)" };
|
|
1696
1727
|
const repositoryItemError = { color: "var(--dsw-alias-state-error-primary)" };
|
|
@@ -1909,19 +1940,77 @@ window.__ModuleLoader__.load({
|
|
|
1909
1940
|
fontWeight: 650,
|
|
1910
1941
|
cursor: "pointer"
|
|
1911
1942
|
};
|
|
1943
|
+
/** Ticket summaries need room; the branch menu's 280px truncates them badly. */
|
|
1944
|
+
const heroTicketMenu = { width: 420 };
|
|
1912
1945
|
const heroTicketKey = {
|
|
1913
1946
|
flex: "none",
|
|
1914
|
-
color: "var(--dsw-alias-label-
|
|
1915
|
-
fontSize:
|
|
1947
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
1948
|
+
fontSize: 12,
|
|
1916
1949
|
fontWeight: 650,
|
|
1917
1950
|
letterSpacing: .2
|
|
1918
1951
|
};
|
|
1952
|
+
const heroTicketChips = {
|
|
1953
|
+
display: "flex",
|
|
1954
|
+
flexWrap: "wrap",
|
|
1955
|
+
alignItems: "center",
|
|
1956
|
+
gap: 6,
|
|
1957
|
+
padding: "2px 2px 6px",
|
|
1958
|
+
borderBottom: "1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 12%, transparent))"
|
|
1959
|
+
};
|
|
1960
|
+
const heroTicketChip = {
|
|
1961
|
+
display: "inline-flex",
|
|
1962
|
+
alignItems: "center",
|
|
1963
|
+
gap: 4,
|
|
1964
|
+
padding: "2px 4px 2px 8px",
|
|
1965
|
+
border: "1px solid color-mix(in srgb, var(--dsw-static-blue-450) 40%, transparent)",
|
|
1966
|
+
borderRadius: 999,
|
|
1967
|
+
background: "color-mix(in srgb, var(--dsw-static-blue-450) 12%, transparent)",
|
|
1968
|
+
color: "var(--dsw-alias-label-primary)",
|
|
1969
|
+
fontSize: 12,
|
|
1970
|
+
fontWeight: 600,
|
|
1971
|
+
letterSpacing: .2
|
|
1972
|
+
};
|
|
1973
|
+
const heroTicketChipRemove = {
|
|
1974
|
+
width: 16,
|
|
1975
|
+
height: 16,
|
|
1976
|
+
display: "grid",
|
|
1977
|
+
placeItems: "center",
|
|
1978
|
+
padding: 0,
|
|
1979
|
+
border: "none",
|
|
1980
|
+
borderRadius: 999,
|
|
1981
|
+
background: "transparent",
|
|
1982
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1983
|
+
fontSize: 12,
|
|
1984
|
+
lineHeight: 1,
|
|
1985
|
+
cursor: "pointer"
|
|
1986
|
+
};
|
|
1987
|
+
const heroTicketChipsClear = {
|
|
1988
|
+
padding: "2px 4px",
|
|
1989
|
+
border: "none",
|
|
1990
|
+
background: "transparent",
|
|
1991
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1992
|
+
fontSize: 12,
|
|
1993
|
+
cursor: "pointer"
|
|
1994
|
+
};
|
|
1995
|
+
const heroTicketCheckbox = {
|
|
1996
|
+
width: 15,
|
|
1997
|
+
height: 15,
|
|
1998
|
+
boxSizing: "border-box",
|
|
1999
|
+
display: "grid",
|
|
2000
|
+
placeItems: "center",
|
|
2001
|
+
flex: "none",
|
|
2002
|
+
border: "1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 16%, transparent))",
|
|
2003
|
+
borderRadius: 4,
|
|
2004
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
2005
|
+
color: "var(--dsw-alias-label-on-accent, #fff)",
|
|
2006
|
+
transition: "border-color 120ms ease, background 120ms ease"
|
|
2007
|
+
};
|
|
1919
2008
|
const heroTicketStatus = {
|
|
1920
2009
|
flex: "none",
|
|
1921
|
-
maxWidth:
|
|
2010
|
+
maxWidth: 110,
|
|
1922
2011
|
overflow: "hidden",
|
|
1923
2012
|
color: "var(--dsw-alias-label-tertiary)",
|
|
1924
|
-
fontSize:
|
|
2013
|
+
fontSize: 12,
|
|
1925
2014
|
textOverflow: "ellipsis",
|
|
1926
2015
|
whiteSpace: "nowrap"
|
|
1927
2016
|
};
|
|
@@ -2008,6 +2097,197 @@ window.__ModuleLoader__.load({
|
|
|
2008
2097
|
fontSize: 13,
|
|
2009
2098
|
textAlign: "center"
|
|
2010
2099
|
};
|
|
2100
|
+
const askSurfaceBorder = "1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 16%, transparent))";
|
|
2101
|
+
const askSurfaceShadow = "var(--dsw-shadow-lv3, 0 8px 24px color-mix(in srgb, #000 24%, transparent))";
|
|
2102
|
+
/** Painted through CSS.highlights while the follow-up popup is open. */
|
|
2103
|
+
const askHighlightCss = `
|
|
2104
|
+
::highlight(dsh-claude-ask) {
|
|
2105
|
+
background-color: color-mix(in srgb, var(--dsw-static-blue-450) 30%, transparent);
|
|
2106
|
+
color: inherit;
|
|
2107
|
+
}
|
|
2108
|
+
`;
|
|
2109
|
+
const askToolbar = {
|
|
2110
|
+
position: "fixed",
|
|
2111
|
+
zIndex: 2e3,
|
|
2112
|
+
pointerEvents: "auto",
|
|
2113
|
+
display: "inline-flex",
|
|
2114
|
+
alignItems: "center",
|
|
2115
|
+
gap: 2,
|
|
2116
|
+
padding: 3,
|
|
2117
|
+
border: askSurfaceBorder,
|
|
2118
|
+
borderRadius: 9,
|
|
2119
|
+
background: "var(--dsw-alias-bg-layer-1)",
|
|
2120
|
+
color: "var(--dsw-alias-label-primary)",
|
|
2121
|
+
boxShadow: askSurfaceShadow
|
|
2122
|
+
};
|
|
2123
|
+
const askPopup = {
|
|
2124
|
+
position: "fixed",
|
|
2125
|
+
zIndex: 2e3,
|
|
2126
|
+
pointerEvents: "auto",
|
|
2127
|
+
boxSizing: "border-box",
|
|
2128
|
+
display: "flex",
|
|
2129
|
+
flexDirection: "column",
|
|
2130
|
+
gap: 10,
|
|
2131
|
+
padding: 12,
|
|
2132
|
+
border: askSurfaceBorder,
|
|
2133
|
+
borderRadius: 12,
|
|
2134
|
+
background: "var(--dsw-alias-bg-layer-1)",
|
|
2135
|
+
color: "var(--dsw-alias-label-primary)",
|
|
2136
|
+
boxShadow: askSurfaceShadow,
|
|
2137
|
+
fontSize: 13,
|
|
2138
|
+
lineHeight: "20px"
|
|
2139
|
+
};
|
|
2140
|
+
const askQuote = {
|
|
2141
|
+
flex: "none",
|
|
2142
|
+
display: "-webkit-box",
|
|
2143
|
+
WebkitLineClamp: 3,
|
|
2144
|
+
WebkitBoxOrient: "vertical",
|
|
2145
|
+
margin: 0,
|
|
2146
|
+
padding: "6px 10px",
|
|
2147
|
+
overflow: "hidden",
|
|
2148
|
+
borderLeft: "3px solid color-mix(in srgb, var(--dsw-static-blue-450) 60%, transparent)",
|
|
2149
|
+
borderRadius: 6,
|
|
2150
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
2151
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
2152
|
+
fontSize: 12,
|
|
2153
|
+
lineHeight: "18px",
|
|
2154
|
+
whiteSpace: "pre-wrap",
|
|
2155
|
+
wordBreak: "break-word"
|
|
2156
|
+
};
|
|
2157
|
+
const askQuestion = {
|
|
2158
|
+
flex: "none",
|
|
2159
|
+
margin: 0,
|
|
2160
|
+
color: "var(--dsw-alias-label-primary)",
|
|
2161
|
+
fontWeight: 600,
|
|
2162
|
+
whiteSpace: "pre-wrap",
|
|
2163
|
+
wordBreak: "break-word"
|
|
2164
|
+
};
|
|
2165
|
+
const askTextarea = {
|
|
2166
|
+
width: "100%",
|
|
2167
|
+
minHeight: 64,
|
|
2168
|
+
boxSizing: "border-box",
|
|
2169
|
+
padding: "8px 10px",
|
|
2170
|
+
border: askSurfaceBorder,
|
|
2171
|
+
borderRadius: 8,
|
|
2172
|
+
outline: "none",
|
|
2173
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
2174
|
+
color: "var(--dsw-alias-label-primary)",
|
|
2175
|
+
font: "inherit",
|
|
2176
|
+
fontSize: 13,
|
|
2177
|
+
lineHeight: "20px",
|
|
2178
|
+
resize: "vertical"
|
|
2179
|
+
};
|
|
2180
|
+
const askActions = {
|
|
2181
|
+
flex: "none",
|
|
2182
|
+
display: "flex",
|
|
2183
|
+
alignItems: "center",
|
|
2184
|
+
justifyContent: "flex-end",
|
|
2185
|
+
gap: 6
|
|
2186
|
+
};
|
|
2187
|
+
const askAnswer = {
|
|
2188
|
+
flex: "1 1 auto",
|
|
2189
|
+
minHeight: 0,
|
|
2190
|
+
overflowY: "auto",
|
|
2191
|
+
padding: "2px 2px 0",
|
|
2192
|
+
wordBreak: "break-word"
|
|
2193
|
+
};
|
|
2194
|
+
const askButton = {
|
|
2195
|
+
minHeight: 26,
|
|
2196
|
+
padding: "3px 10px",
|
|
2197
|
+
border: askSurfaceBorder,
|
|
2198
|
+
borderRadius: 7,
|
|
2199
|
+
outline: "none",
|
|
2200
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
2201
|
+
color: "var(--dsw-alias-label-primary)",
|
|
2202
|
+
font: "inherit",
|
|
2203
|
+
fontSize: 12,
|
|
2204
|
+
lineHeight: "18px",
|
|
2205
|
+
fontWeight: 600,
|
|
2206
|
+
cursor: "pointer"
|
|
2207
|
+
};
|
|
2208
|
+
const askPrimaryButton = {
|
|
2209
|
+
border: "1px solid transparent",
|
|
2210
|
+
background: "var(--dsw-static-blue-450)",
|
|
2211
|
+
color: "var(--dsw-alias-label-on-accent, #fff)"
|
|
2212
|
+
};
|
|
2213
|
+
const askThinkingRow = {
|
|
2214
|
+
width: "100%",
|
|
2215
|
+
display: "flex",
|
|
2216
|
+
alignItems: "baseline",
|
|
2217
|
+
gap: 6,
|
|
2218
|
+
margin: "0 0 8px",
|
|
2219
|
+
padding: 0,
|
|
2220
|
+
border: "none",
|
|
2221
|
+
outline: "none",
|
|
2222
|
+
background: "transparent",
|
|
2223
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
2224
|
+
font: "inherit",
|
|
2225
|
+
fontSize: 12,
|
|
2226
|
+
lineHeight: "18px",
|
|
2227
|
+
textAlign: "left",
|
|
2228
|
+
cursor: "pointer"
|
|
2229
|
+
};
|
|
2230
|
+
const askThinkingLabel = {
|
|
2231
|
+
flex: "none",
|
|
2232
|
+
fontWeight: 600
|
|
2233
|
+
};
|
|
2234
|
+
const askThinkingPreview = {
|
|
2235
|
+
minWidth: 0,
|
|
2236
|
+
flex: 1,
|
|
2237
|
+
overflow: "hidden",
|
|
2238
|
+
textOverflow: "ellipsis",
|
|
2239
|
+
whiteSpace: "nowrap"
|
|
2240
|
+
};
|
|
2241
|
+
const askThinkingFull = {
|
|
2242
|
+
minWidth: 0,
|
|
2243
|
+
flex: 1,
|
|
2244
|
+
maxHeight: 200,
|
|
2245
|
+
overflowY: "auto",
|
|
2246
|
+
whiteSpace: "pre-wrap",
|
|
2247
|
+
wordBreak: "break-word"
|
|
2248
|
+
};
|
|
2249
|
+
const askToolRow = {
|
|
2250
|
+
display: "flex",
|
|
2251
|
+
alignItems: "baseline",
|
|
2252
|
+
gap: 6,
|
|
2253
|
+
margin: "2px 0 6px",
|
|
2254
|
+
minWidth: 0,
|
|
2255
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
2256
|
+
fontSize: 12,
|
|
2257
|
+
lineHeight: "18px"
|
|
2258
|
+
};
|
|
2259
|
+
const askToolGlyph = {
|
|
2260
|
+
flex: "none",
|
|
2261
|
+
width: 14,
|
|
2262
|
+
textAlign: "center",
|
|
2263
|
+
color: "var(--dsw-static-blue-450)"
|
|
2264
|
+
};
|
|
2265
|
+
const askToolGlyphDone = { color: "var(--dsw-alias-state-success-primary)" };
|
|
2266
|
+
const askToolGlyphError = { color: "var(--dsw-alias-state-error-primary)" };
|
|
2267
|
+
const askToolName = {
|
|
2268
|
+
flex: "none",
|
|
2269
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
2270
|
+
fontWeight: 600
|
|
2271
|
+
};
|
|
2272
|
+
const askToolSummary = {
|
|
2273
|
+
minWidth: 0,
|
|
2274
|
+
flex: 1,
|
|
2275
|
+
overflow: "hidden",
|
|
2276
|
+
fontFamily: "var(--dsw-font-family-code, ui-monospace, monospace)",
|
|
2277
|
+
fontSize: 11,
|
|
2278
|
+
textOverflow: "ellipsis",
|
|
2279
|
+
whiteSpace: "nowrap"
|
|
2280
|
+
};
|
|
2281
|
+
const askStatus = {
|
|
2282
|
+
marginRight: "auto",
|
|
2283
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
2284
|
+
fontSize: 12
|
|
2285
|
+
};
|
|
2286
|
+
const askError = {
|
|
2287
|
+
margin: 0,
|
|
2288
|
+
color: "var(--dsw-alias-state-error-primary)",
|
|
2289
|
+
fontSize: 12
|
|
2290
|
+
};
|
|
2011
2291
|
const repositoryMergeTrigger = {
|
|
2012
2292
|
flex: "none",
|
|
2013
2293
|
display: "inline-flex",
|
|
@@ -2231,10 +2511,7 @@ window.__ModuleLoader__.load({
|
|
|
2231
2511
|
const diffPanel = {
|
|
2232
2512
|
display: "flex",
|
|
2233
2513
|
flexDirection: "column",
|
|
2234
|
-
width: "calc(100% - 16px)",
|
|
2235
|
-
height: "calc(100% - 16px)",
|
|
2236
2514
|
minWidth: 0,
|
|
2237
|
-
margin: 8,
|
|
2238
2515
|
overflow: "hidden",
|
|
2239
2516
|
border: "1px solid var(--dsw-alias-border-l2, color-mix(in srgb, currentColor 16%, transparent))",
|
|
2240
2517
|
borderRadius: 12,
|
|
@@ -2349,26 +2626,41 @@ window.__ModuleLoader__.load({
|
|
|
2349
2626
|
background: "var(--dsw-alias-bg-layer-1)",
|
|
2350
2627
|
color: "var(--dsw-alias-label-primary)",
|
|
2351
2628
|
font: "inherit",
|
|
2352
|
-
fontSize:
|
|
2629
|
+
fontSize: 13,
|
|
2630
|
+
lineHeight: "20px",
|
|
2353
2631
|
textAlign: "left",
|
|
2354
2632
|
cursor: "pointer"
|
|
2355
2633
|
};
|
|
2356
2634
|
const diffFilePath = {
|
|
2357
2635
|
minWidth: 0,
|
|
2358
2636
|
flex: 1,
|
|
2637
|
+
display: "flex",
|
|
2638
|
+
alignItems: "baseline",
|
|
2639
|
+
overflow: "hidden"
|
|
2640
|
+
};
|
|
2641
|
+
/** Directory part: truncated from the left so the nearest folders stay visible. */
|
|
2642
|
+
const diffFileDir = {
|
|
2643
|
+
minWidth: 0,
|
|
2359
2644
|
overflow: "hidden",
|
|
2360
2645
|
textOverflow: "ellipsis",
|
|
2646
|
+
whiteSpace: "nowrap",
|
|
2647
|
+
direction: "rtl",
|
|
2648
|
+
textAlign: "left",
|
|
2649
|
+
color: "var(--dsw-alias-label-tertiary)"
|
|
2650
|
+
};
|
|
2651
|
+
const diffFileName = {
|
|
2652
|
+
flex: "none",
|
|
2653
|
+
fontWeight: 650,
|
|
2361
2654
|
whiteSpace: "nowrap"
|
|
2362
2655
|
};
|
|
2363
2656
|
const diffFileStats = {
|
|
2364
2657
|
flex: "none",
|
|
2365
2658
|
display: "inline-flex",
|
|
2366
2659
|
gap: 4,
|
|
2367
|
-
fontSize:
|
|
2660
|
+
fontSize: 13,
|
|
2368
2661
|
fontWeight: 650
|
|
2369
2662
|
};
|
|
2370
2663
|
const diffCode = {
|
|
2371
|
-
minWidth: "max-content",
|
|
2372
2664
|
padding: "4px 0 8px",
|
|
2373
2665
|
background: "var(--dsw-alias-bg-base)",
|
|
2374
2666
|
fontFamily: "var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Consolas, monospace)",
|
|
@@ -2378,7 +2670,12 @@ window.__ModuleLoader__.load({
|
|
|
2378
2670
|
const diffLine = {
|
|
2379
2671
|
minHeight: 17,
|
|
2380
2672
|
display: "flex",
|
|
2381
|
-
whiteSpace: "pre"
|
|
2673
|
+
whiteSpace: "pre-wrap",
|
|
2674
|
+
overflowWrap: "anywhere"
|
|
2675
|
+
};
|
|
2676
|
+
const diffLineText = {
|
|
2677
|
+
flex: 1,
|
|
2678
|
+
minWidth: 0
|
|
2382
2679
|
};
|
|
2383
2680
|
const diffLineNumber = {
|
|
2384
2681
|
width: 38,
|
|
@@ -2408,6 +2705,40 @@ window.__ModuleLoader__.load({
|
|
|
2408
2705
|
color: "var(--dsw-alias-label-tertiary)",
|
|
2409
2706
|
fontStyle: "italic"
|
|
2410
2707
|
};
|
|
2708
|
+
const diffLineSelected = {
|
|
2709
|
+
background: "color-mix(in srgb, var(--dsw-static-blue-450) 14%, transparent)",
|
|
2710
|
+
boxShadow: "inset 2px 0 0 var(--dsw-static-blue-450)"
|
|
2711
|
+
};
|
|
2712
|
+
/** Sits where the comment button, line number and marker would be so the label aligns with code. */
|
|
2713
|
+
const diffGapControls = {
|
|
2714
|
+
width: 84,
|
|
2715
|
+
flex: "none",
|
|
2716
|
+
boxSizing: "border-box",
|
|
2717
|
+
display: "inline-flex",
|
|
2718
|
+
alignItems: "center",
|
|
2719
|
+
justifyContent: "flex-end",
|
|
2720
|
+
gap: 2,
|
|
2721
|
+
paddingRight: 6
|
|
2722
|
+
};
|
|
2723
|
+
const diffGapButton = {
|
|
2724
|
+
width: 20,
|
|
2725
|
+
height: 18,
|
|
2726
|
+
display: "grid",
|
|
2727
|
+
placeItems: "center",
|
|
2728
|
+
padding: 0,
|
|
2729
|
+
border: "none",
|
|
2730
|
+
borderRadius: 4,
|
|
2731
|
+
background: "transparent",
|
|
2732
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
2733
|
+
font: "inherit",
|
|
2734
|
+
cursor: "pointer"
|
|
2735
|
+
};
|
|
2736
|
+
const diffCommentRange = {
|
|
2737
|
+
marginBottom: 6,
|
|
2738
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
2739
|
+
fontSize: 12,
|
|
2740
|
+
fontWeight: 600
|
|
2741
|
+
};
|
|
2411
2742
|
const diffLineContext = { color: "var(--dsw-alias-label-secondary)" };
|
|
2412
2743
|
const diffNotice = {
|
|
2413
2744
|
margin: 10,
|
|
@@ -2781,11 +3112,12 @@ window.__ModuleLoader__.load({
|
|
|
2781
3112
|
const clearFinished = () => setDismissedSettledIds((previous) => /* @__PURE__ */ new Set([...previous, ...tasks.filter((task) => task.status !== "running").map((task) => task.taskId)]));
|
|
2782
3113
|
if (!projection.owned) return null;
|
|
2783
3114
|
return /* @__PURE__ */ jsxs("div", {
|
|
3115
|
+
className: detailsCardClass,
|
|
2784
3116
|
style: tasksPanel,
|
|
2785
3117
|
children: [
|
|
2786
|
-
/* @__PURE__ */
|
|
3118
|
+
/* @__PURE__ */ jsxs("style", {
|
|
2787
3119
|
"data-dsh-claude-panel-icon-styles": true,
|
|
2788
|
-
children: panelIconButtonCss
|
|
3120
|
+
children: [detailsCardCss, panelIconButtonCss]
|
|
2789
3121
|
}),
|
|
2790
3122
|
/* @__PURE__ */ jsxs("div", {
|
|
2791
3123
|
style: tasksHeader,
|
|
@@ -3018,7 +3350,7 @@ window.__ModuleLoader__.load({
|
|
|
3018
3350
|
const MAX_REVIEW_COMMENTS = 50;
|
|
3019
3351
|
const MAX_REVIEW_COMMENT_CHARS = 2e3;
|
|
3020
3352
|
const MAX_TRANSCRIPT_CHARS = 64e3;
|
|
3021
|
-
function record$
|
|
3353
|
+
function record$7(value) {
|
|
3022
3354
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3023
3355
|
}
|
|
3024
3356
|
function nonNegativeInteger(value) {
|
|
@@ -3028,18 +3360,18 @@ window.__ModuleLoader__.load({
|
|
|
3028
3360
|
return value === void 0 || typeof value === "string" && value.length <= MAX_REPOSITORY_TEXT_CHARS;
|
|
3029
3361
|
}
|
|
3030
3362
|
function validateRepository(value) {
|
|
3031
|
-
const repository = record$
|
|
3363
|
+
const repository = record$7(value);
|
|
3032
3364
|
if (repository === void 0 || ![
|
|
3033
3365
|
"ready",
|
|
3034
3366
|
"not-repository",
|
|
3035
3367
|
"unavailable"
|
|
3036
3368
|
].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
3369
|
if (repository.diff !== void 0) {
|
|
3038
|
-
const diff = record$
|
|
3370
|
+
const diff = record$7(repository.diff);
|
|
3039
3371
|
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
3372
|
}
|
|
3041
3373
|
if (repository.pullRequest === void 0) return true;
|
|
3042
|
-
const pullRequest = record$
|
|
3374
|
+
const pullRequest = record$7(repository.pullRequest);
|
|
3043
3375
|
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
3376
|
"open",
|
|
3045
3377
|
"closed",
|
|
@@ -3064,24 +3396,24 @@ window.__ModuleLoader__.load({
|
|
|
3064
3396
|
}
|
|
3065
3397
|
/** Validate the public route envelope before publishing it to UI components. */
|
|
3066
3398
|
function parseClaudeClientProjection(value) {
|
|
3067
|
-
const input = record$
|
|
3399
|
+
const input = record$7(value);
|
|
3068
3400
|
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
3401
|
for (const item of input.commands) {
|
|
3070
|
-
const command = record$
|
|
3402
|
+
const command = record$7(item);
|
|
3071
3403
|
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
3404
|
}
|
|
3073
3405
|
for (const item of input.activities) {
|
|
3074
|
-
const activity = record$
|
|
3406
|
+
const activity = record$7(item);
|
|
3075
3407
|
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
3408
|
}
|
|
3077
|
-
if (input.contextUsage !== void 0 && record$
|
|
3078
|
-
const tasks = input.tasks === void 0 ? void 0 : record$
|
|
3409
|
+
if (input.contextUsage !== void 0 && record$7(input.contextUsage) === void 0) throw new Error("invalid Claude context projection");
|
|
3410
|
+
const tasks = input.tasks === void 0 ? void 0 : record$7(input.tasks);
|
|
3079
3411
|
if (tasks !== void 0 && !Array.isArray(tasks.tasks)) throw new Error("invalid Claude tasks projection");
|
|
3080
3412
|
if (input.repository !== void 0 && !validateRepository(input.repository)) throw new Error("invalid Claude repository projection");
|
|
3081
3413
|
if (input.reviewComments !== void 0) {
|
|
3082
3414
|
if (!Array.isArray(input.reviewComments) || input.reviewComments.length > MAX_REVIEW_COMMENTS) throw new Error("invalid Claude review comment projection");
|
|
3083
3415
|
for (const item of input.reviewComments) {
|
|
3084
|
-
const comment = record$
|
|
3416
|
+
const comment = record$7(item);
|
|
3085
3417
|
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
3418
|
}
|
|
3087
3419
|
}
|
|
@@ -3279,7 +3611,7 @@ window.__ModuleLoader__.load({
|
|
|
3279
3611
|
} catch {
|
|
3280
3612
|
return;
|
|
3281
3613
|
}
|
|
3282
|
-
const event = record$
|
|
3614
|
+
const event = record$7(value);
|
|
3283
3615
|
if (event === void 0 || typeof event.type !== "string") return;
|
|
3284
3616
|
try {
|
|
3285
3617
|
switch (event.type) {
|
|
@@ -3538,7 +3870,7 @@ window.__ModuleLoader__.load({
|
|
|
3538
3870
|
return value;
|
|
3539
3871
|
}
|
|
3540
3872
|
}
|
|
3541
|
-
function record$
|
|
3873
|
+
function record$6(value) {
|
|
3542
3874
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3543
3875
|
}
|
|
3544
3876
|
function text(value) {
|
|
@@ -3552,7 +3884,7 @@ window.__ModuleLoader__.load({
|
|
|
3552
3884
|
if (typeof value === "string") return value;
|
|
3553
3885
|
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
3554
3886
|
if (Array.isArray(value)) return value.map(displayValue).join(", ");
|
|
3555
|
-
return record$
|
|
3887
|
+
return record$6(value) === void 0 ? String(value) : Object.entries(value).map(([key, item]) => `${key}: ${displayValue(item)}`).join("\n");
|
|
3556
3888
|
}
|
|
3557
3889
|
function Section({ title, children }) {
|
|
3558
3890
|
return /* @__PURE__ */ jsxs("section", {
|
|
@@ -3622,15 +3954,15 @@ window.__ModuleLoader__.load({
|
|
|
3622
3954
|
function ToolPresentation({ tool, t }) {
|
|
3623
3955
|
const inputValue = parsedValue(tool.input);
|
|
3624
3956
|
const outputValue = parsedValue(tool.output);
|
|
3625
|
-
const input = record$
|
|
3626
|
-
const output = record$
|
|
3957
|
+
const input = record$6(inputValue);
|
|
3958
|
+
const output = record$6(outputValue);
|
|
3627
3959
|
const outputTitle = tool.isError === true ? t("toolError") : t("toolOutput");
|
|
3628
3960
|
if (tool.diffs !== void 0) return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DiffBlock, { diffs: [...tool.diffs] }), /* @__PURE__ */ jsx(TextDetail, {
|
|
3629
3961
|
title: outputTitle,
|
|
3630
3962
|
value: typeof outputValue === "string" ? outputValue : void 0
|
|
3631
3963
|
})] });
|
|
3632
3964
|
if (tool.toolName === "Read") {
|
|
3633
|
-
const file = record$
|
|
3965
|
+
const file = record$6(output?.file);
|
|
3634
3966
|
const path = text(file?.filePath) ?? text(input?.file_path);
|
|
3635
3967
|
const content = text(file?.content) ?? (typeof outputValue === "string" ? outputValue : void 0);
|
|
3636
3968
|
const offset = numberValue(input?.offset) ?? 1;
|
|
@@ -3828,7 +4160,7 @@ window.__ModuleLoader__.load({
|
|
|
3828
4160
|
if (code !== void 0) this.code = code;
|
|
3829
4161
|
}
|
|
3830
4162
|
};
|
|
3831
|
-
function record$
|
|
4163
|
+
function record$5(value) {
|
|
3832
4164
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3833
4165
|
}
|
|
3834
4166
|
async function call(path, init) {
|
|
@@ -3836,7 +4168,7 @@ window.__ModuleLoader__.load({
|
|
|
3836
4168
|
credentials: "same-origin",
|
|
3837
4169
|
...init
|
|
3838
4170
|
});
|
|
3839
|
-
const body = record$
|
|
4171
|
+
const body = record$5(await response.json());
|
|
3840
4172
|
if (!response.ok) throw new JiraClientError(typeof body?.message === "string" ? body.message : "Jira is unavailable.", typeof body?.error === "string" ? body.error : void 0);
|
|
3841
4173
|
if (body === void 0) throw new JiraClientError("Invalid Jira response.");
|
|
3842
4174
|
return body;
|
|
@@ -3877,7 +4209,7 @@ window.__ModuleLoader__.load({
|
|
|
3877
4209
|
if (!Array.isArray(body.tickets)) throw new JiraClientError("Invalid Jira search response.");
|
|
3878
4210
|
const tickets = [];
|
|
3879
4211
|
for (const item of body.tickets) {
|
|
3880
|
-
const ticket = record$
|
|
4212
|
+
const ticket = record$5(item);
|
|
3881
4213
|
if (ticket === void 0 || typeof ticket.key !== "string" || typeof ticket.summary !== "string" || typeof ticket.url !== "string") continue;
|
|
3882
4214
|
tickets.push(ticket);
|
|
3883
4215
|
}
|
|
@@ -4580,33 +4912,33 @@ window.__ModuleLoader__.load({
|
|
|
4580
4912
|
if (commit !== void 0) this.commit = commit;
|
|
4581
4913
|
}
|
|
4582
4914
|
};
|
|
4583
|
-
function record$
|
|
4915
|
+
function record$4(value) {
|
|
4584
4916
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
4585
4917
|
}
|
|
4586
4918
|
async function response$1(pending) {
|
|
4587
4919
|
const result = await pending;
|
|
4588
4920
|
const body = await result.json();
|
|
4589
4921
|
if (!result.ok) {
|
|
4590
|
-
const error = record$
|
|
4922
|
+
const error = record$4(body);
|
|
4591
4923
|
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
4924
|
}
|
|
4593
4925
|
return body;
|
|
4594
4926
|
}
|
|
4595
4927
|
function preview(value) {
|
|
4596
|
-
const input = record$
|
|
4928
|
+
const input = record$4(value);
|
|
4597
4929
|
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
4930
|
for (const file of input.files) {
|
|
4599
|
-
const item = record$
|
|
4931
|
+
const item = record$4(file);
|
|
4600
4932
|
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
4933
|
}
|
|
4602
4934
|
for (const commit of input.unpushedCommits) {
|
|
4603
|
-
const item = record$
|
|
4935
|
+
const item = record$4(commit);
|
|
4604
4936
|
if (item === void 0 || typeof item.hash !== "string" || typeof item.subject !== "string") throw new Error("Invalid repository action commit.");
|
|
4605
4937
|
}
|
|
4606
4938
|
return input;
|
|
4607
4939
|
}
|
|
4608
4940
|
function result(value) {
|
|
4609
|
-
const input = record$
|
|
4941
|
+
const input = record$4(value);
|
|
4610
4942
|
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
4943
|
return input;
|
|
4612
4944
|
}
|
|
@@ -4622,7 +4954,7 @@ window.__ModuleLoader__.load({
|
|
|
4622
4954
|
})));
|
|
4623
4955
|
}
|
|
4624
4956
|
async function generateCommitMessage(sessionId, fingerprint, signal) {
|
|
4625
|
-
const value = record$
|
|
4957
|
+
const value = record$4(await response$1(fetch(endpoint("/message", sessionId), {
|
|
4626
4958
|
method: "POST",
|
|
4627
4959
|
credentials: "same-origin",
|
|
4628
4960
|
headers: {
|
|
@@ -4655,16 +4987,16 @@ window.__ModuleLoader__.load({
|
|
|
4655
4987
|
"saving-worktree",
|
|
4656
4988
|
"switching-branch"
|
|
4657
4989
|
]);
|
|
4658
|
-
function record$
|
|
4990
|
+
function record$3(value) {
|
|
4659
4991
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
4660
4992
|
}
|
|
4661
4993
|
function setupResult(value) {
|
|
4662
|
-
const item = record$
|
|
4994
|
+
const item = record$3(value);
|
|
4663
4995
|
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
4996
|
return item;
|
|
4665
4997
|
}
|
|
4666
4998
|
function parseRepositorySetupEvent(line, onProgress) {
|
|
4667
|
-
const event = record$
|
|
4999
|
+
const event = record$3(JSON.parse(line));
|
|
4668
5000
|
if (event?.type === "progress" && typeof event.stage === "string" && HOST_STAGES.has(event.stage)) {
|
|
4669
5001
|
onProgress(event.stage);
|
|
4670
5002
|
return;
|
|
@@ -4766,6 +5098,21 @@ window.__ModuleLoader__.load({
|
|
|
4766
5098
|
if (body.mode !== "worktree" && body.mode !== "checkout" || typeof body.root !== "string" || typeof body.branch !== "string") throw new Error("Invalid repository cleanup response.");
|
|
4767
5099
|
return body;
|
|
4768
5100
|
}
|
|
5101
|
+
/** Lines [from, to] of a working-tree file plus its total line count, for expanding unmodified diff context. */
|
|
5102
|
+
async function loadRepositoryFileLines(cwd, path, from, to, signal) {
|
|
5103
|
+
const query = `cwd=${encodeURIComponent(cwd)}&path=${encodeURIComponent(path)}&from=${from}&to=${to}`;
|
|
5104
|
+
const body = await response(fetch(`${CLAUDE_REPOSITORY_FILE_PATH}?${query}`, {
|
|
5105
|
+
method: "GET",
|
|
5106
|
+
credentials: "same-origin",
|
|
5107
|
+
headers: { accept: "application/json" },
|
|
5108
|
+
...signal === void 0 ? {} : { signal }
|
|
5109
|
+
}));
|
|
5110
|
+
if (!Array.isArray(body.lines) || typeof body.total !== "number") throw new Error("Invalid repository file response.");
|
|
5111
|
+
return {
|
|
5112
|
+
lines: body.lines.map(String),
|
|
5113
|
+
total: body.total
|
|
5114
|
+
};
|
|
5115
|
+
}
|
|
4769
5116
|
async function loadRepositoryStatusFor(cwd, signal) {
|
|
4770
5117
|
const body = await response(fetch(`${CLAUDE_REPOSITORY_STATUS_PATH}?cwd=${encodeURIComponent(cwd)}`, {
|
|
4771
5118
|
method: "GET",
|
|
@@ -4778,7 +5125,7 @@ window.__ModuleLoader__.load({
|
|
|
4778
5125
|
}
|
|
4779
5126
|
//#endregion
|
|
4780
5127
|
//#region src/client/pr-feedback-api.ts
|
|
4781
|
-
function record$
|
|
5128
|
+
function record$2(value) {
|
|
4782
5129
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
4783
5130
|
}
|
|
4784
5131
|
async function loadJson(path, sessionId, pullNumber, signal) {
|
|
@@ -4788,7 +5135,7 @@ window.__ModuleLoader__.load({
|
|
|
4788
5135
|
headers: { accept: "application/json" },
|
|
4789
5136
|
...signal === void 0 ? {} : { signal }
|
|
4790
5137
|
});
|
|
4791
|
-
const body = record$
|
|
5138
|
+
const body = record$2(await response.json());
|
|
4792
5139
|
if (!response.ok) throw new Error(typeof body?.message === "string" ? body.message : "Pull request feedback is unavailable.");
|
|
4793
5140
|
if (body === void 0) throw new Error("Invalid pull request feedback response.");
|
|
4794
5141
|
return body;
|
|
@@ -4798,7 +5145,7 @@ window.__ModuleLoader__.load({
|
|
|
4798
5145
|
if (!Array.isArray(body.comments)) throw new Error("Invalid pull request comments response.");
|
|
4799
5146
|
const comments = [];
|
|
4800
5147
|
for (const item of body.comments) {
|
|
4801
|
-
const input = record$
|
|
5148
|
+
const input = record$2(item);
|
|
4802
5149
|
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
5150
|
comments.push(input);
|
|
4804
5151
|
}
|
|
@@ -4809,7 +5156,7 @@ window.__ModuleLoader__.load({
|
|
|
4809
5156
|
if (!Array.isArray(body.checks)) throw new Error("Invalid pull request checks response.");
|
|
4810
5157
|
const checks = [];
|
|
4811
5158
|
for (const item of body.checks) {
|
|
4812
|
-
const input = record$
|
|
5159
|
+
const input = record$2(item);
|
|
4813
5160
|
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
5161
|
checks.push(input);
|
|
4815
5162
|
}
|
|
@@ -4908,6 +5255,63 @@ window.__ModuleLoader__.load({
|
|
|
4908
5255
|
})]
|
|
4909
5256
|
});
|
|
4910
5257
|
}
|
|
5258
|
+
/** Icon-only status: the tone carries the state, the full label lives in the tooltip and accessible name. */
|
|
5259
|
+
function StatusGlyph({ label, tone, children }) {
|
|
5260
|
+
const toneStyle = tone === "success" ? repositoryItemSuccess : tone === "warning" ? repositoryItemWarning : tone === "error" ? repositoryItemError : {};
|
|
5261
|
+
return /* @__PURE__ */ jsx(Tooltip, {
|
|
5262
|
+
label,
|
|
5263
|
+
side: "top",
|
|
5264
|
+
delayMs: 250,
|
|
5265
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
5266
|
+
role: "img",
|
|
5267
|
+
"aria-label": label,
|
|
5268
|
+
style: {
|
|
5269
|
+
...repositoryGlyph,
|
|
5270
|
+
...toneStyle
|
|
5271
|
+
},
|
|
5272
|
+
children
|
|
5273
|
+
})
|
|
5274
|
+
});
|
|
5275
|
+
}
|
|
5276
|
+
function ChecksGlyph({ state }) {
|
|
5277
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
5278
|
+
width: "14",
|
|
5279
|
+
height: "14",
|
|
5280
|
+
viewBox: "0 0 14 14",
|
|
5281
|
+
fill: "none",
|
|
5282
|
+
stroke: "currentColor",
|
|
5283
|
+
strokeWidth: "1.5",
|
|
5284
|
+
strokeLinecap: "round",
|
|
5285
|
+
strokeLinejoin: "round",
|
|
5286
|
+
"aria-hidden": "true",
|
|
5287
|
+
children: [/* @__PURE__ */ jsx("circle", {
|
|
5288
|
+
cx: "7",
|
|
5289
|
+
cy: "7",
|
|
5290
|
+
r: "5.5"
|
|
5291
|
+
}), 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", {
|
|
5292
|
+
d: "M4.6 7h.01M7 7h.01M9.4 7h.01",
|
|
5293
|
+
strokeWidth: "2"
|
|
5294
|
+
})]
|
|
5295
|
+
});
|
|
5296
|
+
}
|
|
5297
|
+
function ReviewGlyph() {
|
|
5298
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
5299
|
+
width: "14",
|
|
5300
|
+
height: "14",
|
|
5301
|
+
viewBox: "0 0 14 14",
|
|
5302
|
+
fill: "none",
|
|
5303
|
+
stroke: "currentColor",
|
|
5304
|
+
strokeWidth: "1.5",
|
|
5305
|
+
strokeLinecap: "round",
|
|
5306
|
+
strokeLinejoin: "round",
|
|
5307
|
+
"aria-hidden": "true",
|
|
5308
|
+
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", {
|
|
5309
|
+
cx: "7",
|
|
5310
|
+
cy: "7",
|
|
5311
|
+
r: "1.8"
|
|
5312
|
+
})]
|
|
5313
|
+
});
|
|
5314
|
+
}
|
|
4911
5315
|
function PullRequestIcon({ size = 16, merged = false }) {
|
|
4912
5316
|
if (merged) return /* @__PURE__ */ jsxs("svg", {
|
|
4913
5317
|
width: size,
|
|
@@ -5233,9 +5637,10 @@ window.__ModuleLoader__.load({
|
|
|
5233
5637
|
"aria-expanded": open,
|
|
5234
5638
|
"aria-label": t("repositoryChecksOpen"),
|
|
5235
5639
|
onClick: toggle,
|
|
5236
|
-
children: /* @__PURE__ */ jsx(
|
|
5640
|
+
children: /* @__PURE__ */ jsx(StatusGlyph, {
|
|
5237
5641
|
label: t("repositoryChecks_failing"),
|
|
5238
|
-
tone: "error"
|
|
5642
|
+
tone: "error",
|
|
5643
|
+
children: /* @__PURE__ */ jsx(ChecksGlyph, { state: "failing" })
|
|
5239
5644
|
})
|
|
5240
5645
|
}), open ? /* @__PURE__ */ jsxs("span", {
|
|
5241
5646
|
role: "dialog",
|
|
@@ -5857,13 +6262,15 @@ window.__ModuleLoader__.load({
|
|
|
5857
6262
|
pullNumber: pullRequest.number,
|
|
5858
6263
|
t,
|
|
5859
6264
|
...submitPrompt === void 0 ? {} : { submitPrompt }
|
|
5860
|
-
}) : pullRequest.checks === "none" ? null : /* @__PURE__ */ jsx(
|
|
6265
|
+
}) : pullRequest.checks === "none" ? null : /* @__PURE__ */ jsx(StatusGlyph, {
|
|
5861
6266
|
label: t(`repositoryChecks_${pullRequest.checks}`),
|
|
5862
|
-
tone: pullRequest.checks === "passing" ? "success" : "warning"
|
|
6267
|
+
tone: pullRequest.checks === "passing" ? "success" : "warning",
|
|
6268
|
+
children: /* @__PURE__ */ jsx(ChecksGlyph, { state: pullRequest.checks })
|
|
5863
6269
|
}),
|
|
5864
|
-
pullRequest.review === "none" ? null : /* @__PURE__ */ jsx(
|
|
6270
|
+
pullRequest.review === "none" ? null : /* @__PURE__ */ jsx(StatusGlyph, {
|
|
5865
6271
|
label: t(`repositoryReview_${pullRequest.review}`),
|
|
5866
|
-
tone: pullRequest.review === "approved" ? "success" : pullRequest.review === "changes-requested" ? "error" : "neutral"
|
|
6272
|
+
tone: pullRequest.review === "approved" ? "success" : pullRequest.review === "changes-requested" ? "error" : "neutral",
|
|
6273
|
+
children: /* @__PURE__ */ jsx(ReviewGlyph, {})
|
|
5867
6274
|
}),
|
|
5868
6275
|
/* @__PURE__ */ jsx(AutoFixControl, {
|
|
5869
6276
|
sessionId,
|
|
@@ -5892,7 +6299,7 @@ window.__ModuleLoader__.load({
|
|
|
5892
6299
|
}
|
|
5893
6300
|
//#endregion
|
|
5894
6301
|
//#region src/client/review-comment-api.ts
|
|
5895
|
-
function record(value) {
|
|
6302
|
+
function record$1(value) {
|
|
5896
6303
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
5897
6304
|
}
|
|
5898
6305
|
async function post(path, sessionId, body) {
|
|
@@ -5907,13 +6314,13 @@ window.__ModuleLoader__.load({
|
|
|
5907
6314
|
});
|
|
5908
6315
|
const value = await response.json();
|
|
5909
6316
|
if (!response.ok) {
|
|
5910
|
-
const error = record(value);
|
|
6317
|
+
const error = record$1(value);
|
|
5911
6318
|
throw new Error(typeof error?.message === "string" ? error.message : "Review comment request failed.");
|
|
5912
6319
|
}
|
|
5913
6320
|
return value;
|
|
5914
6321
|
}
|
|
5915
6322
|
async function addReviewComment(sessionId, comment) {
|
|
5916
|
-
const created = record(record(await post("", sessionId, comment))?.comment);
|
|
6323
|
+
const created = record$1(record$1(await post("", sessionId, comment))?.comment);
|
|
5917
6324
|
if (created === void 0 || typeof created.id !== "string") throw new Error("Invalid review comment response.");
|
|
5918
6325
|
return created;
|
|
5919
6326
|
}
|
|
@@ -5926,7 +6333,15 @@ window.__ModuleLoader__.load({
|
|
|
5926
6333
|
//#endregion
|
|
5927
6334
|
//#region src/client/ClaudeReviewComments.tsx
|
|
5928
6335
|
function reviewCommentChipLabel(comment) {
|
|
5929
|
-
return `${comment.path.split("/").at(-1) ?? comment.path}:${comment.line}`;
|
|
6336
|
+
return `${comment.path.split("/").at(-1) ?? comment.path}:${comment.startLine === void 0 ? comment.line : `${comment.startLine}-${comment.line}`}`;
|
|
6337
|
+
}
|
|
6338
|
+
/** "Line 12" / "Lines 10–12", with the old-side variant when the comment sits on removed code. */
|
|
6339
|
+
function commentLineLabel(comment, t) {
|
|
6340
|
+
if (comment.startLine !== void 0) return t(comment.side === "old" ? "reviewCommentOldRange" : "reviewCommentNewRange", {
|
|
6341
|
+
start: comment.startLine,
|
|
6342
|
+
end: comment.line
|
|
6343
|
+
});
|
|
6344
|
+
return t(comment.side === "old" ? "reviewCommentOldSide" : "reviewCommentNewSide", { line: comment.line });
|
|
5930
6345
|
}
|
|
5931
6346
|
function CommentIcon() {
|
|
5932
6347
|
return /* @__PURE__ */ jsx("svg", {
|
|
@@ -5992,7 +6407,7 @@ window.__ModuleLoader__.load({
|
|
|
5992
6407
|
children: [
|
|
5993
6408
|
comment.path,
|
|
5994
6409
|
" · ",
|
|
5995
|
-
comment
|
|
6410
|
+
commentLineLabel(comment, t)
|
|
5996
6411
|
]
|
|
5997
6412
|
}), /* @__PURE__ */ jsx("p", {
|
|
5998
6413
|
style: reviewCommentHoverText,
|
|
@@ -6101,17 +6516,41 @@ window.__ModuleLoader__.load({
|
|
|
6101
6516
|
let oldLine = 0;
|
|
6102
6517
|
let newLine = 0;
|
|
6103
6518
|
let previousOldEnd;
|
|
6519
|
+
let previousNewEnd = 0;
|
|
6520
|
+
let expandable = false;
|
|
6104
6521
|
for (const line of lines) {
|
|
6105
6522
|
const hunk = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/u.exec(line);
|
|
6106
6523
|
if (hunk !== null) {
|
|
6107
6524
|
const nextOld = Number(hunk[1]);
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6525
|
+
const nextNew = Number(hunk[3]);
|
|
6526
|
+
const oldCount = Number(hunk[2] ?? 1);
|
|
6527
|
+
const newCount = Number(hunk[4] ?? 1);
|
|
6528
|
+
if (previousOldEnd === void 0) {
|
|
6529
|
+
expandable = oldCount > 0 && newCount > 0;
|
|
6530
|
+
if (expandable && nextOld > 1) numbered.push({
|
|
6531
|
+
line: "",
|
|
6532
|
+
kind: "collapsed",
|
|
6533
|
+
gap: {
|
|
6534
|
+
oldStart: 1,
|
|
6535
|
+
newStart: 1,
|
|
6536
|
+
count: nextOld - 1,
|
|
6537
|
+
position: "top"
|
|
6538
|
+
}
|
|
6539
|
+
});
|
|
6540
|
+
} else if (nextOld > previousOldEnd) numbered.push({
|
|
6541
|
+
line: "",
|
|
6542
|
+
kind: "collapsed",
|
|
6543
|
+
gap: {
|
|
6544
|
+
oldStart: previousOldEnd,
|
|
6545
|
+
newStart: previousNewEnd,
|
|
6546
|
+
count: nextOld - previousOldEnd,
|
|
6547
|
+
position: "middle"
|
|
6548
|
+
}
|
|
6111
6549
|
});
|
|
6112
6550
|
oldLine = nextOld;
|
|
6113
|
-
newLine =
|
|
6114
|
-
previousOldEnd = nextOld +
|
|
6551
|
+
newLine = nextNew;
|
|
6552
|
+
previousOldEnd = nextOld + oldCount;
|
|
6553
|
+
previousNewEnd = nextNew + newCount;
|
|
6115
6554
|
numbered.push({
|
|
6116
6555
|
line,
|
|
6117
6556
|
kind: "hunk"
|
|
@@ -6143,8 +6582,76 @@ window.__ModuleLoader__.load({
|
|
|
6143
6582
|
newLine += 1;
|
|
6144
6583
|
}
|
|
6145
6584
|
}
|
|
6585
|
+
if (expandable && previousOldEnd !== void 0) numbered.push({
|
|
6586
|
+
line: "",
|
|
6587
|
+
kind: "collapsed",
|
|
6588
|
+
gap: {
|
|
6589
|
+
oldStart: previousOldEnd,
|
|
6590
|
+
newStart: previousNewEnd,
|
|
6591
|
+
position: "bottom"
|
|
6592
|
+
}
|
|
6593
|
+
});
|
|
6146
6594
|
return numbered;
|
|
6147
6595
|
}
|
|
6596
|
+
/**
|
|
6597
|
+
* Splice revealed working-tree lines (keyed by new-side line number) into the
|
|
6598
|
+
* collapsed gaps. Expansion only ever grows a gap's edges, so each gap is a
|
|
6599
|
+
* top run + remaining gap + bottom run; `total` (file line count) turns the
|
|
6600
|
+
* open-ended tail gap into a bounded one.
|
|
6601
|
+
*/
|
|
6602
|
+
function expandDiffRows(rows, revealed, total) {
|
|
6603
|
+
const out = [];
|
|
6604
|
+
for (const row of rows) {
|
|
6605
|
+
const gap = row.gap;
|
|
6606
|
+
if (row.kind !== "collapsed" || gap === void 0) {
|
|
6607
|
+
out.push(row);
|
|
6608
|
+
continue;
|
|
6609
|
+
}
|
|
6610
|
+
const count = gap.count ?? (total === void 0 ? void 0 : Math.max(0, total - gap.newStart + 1));
|
|
6611
|
+
const context = (offset) => ({
|
|
6612
|
+
line: ` ${revealed.get(gap.newStart + offset) ?? ""}`,
|
|
6613
|
+
kind: "context",
|
|
6614
|
+
oldLine: gap.oldStart + offset,
|
|
6615
|
+
newLine: gap.newStart + offset
|
|
6616
|
+
});
|
|
6617
|
+
let top = 0;
|
|
6618
|
+
while ((count === void 0 || top < count) && revealed.has(gap.newStart + top)) top += 1;
|
|
6619
|
+
let bottom = 0;
|
|
6620
|
+
if (count !== void 0) while (bottom < count - top && revealed.has(gap.newStart + count - 1 - bottom)) bottom += 1;
|
|
6621
|
+
for (let offset = 0; offset < top; offset += 1) out.push(context(offset));
|
|
6622
|
+
const remaining = count === void 0 ? void 0 : count - top - bottom;
|
|
6623
|
+
if (remaining === void 0 || remaining > 0) out.push({
|
|
6624
|
+
...row,
|
|
6625
|
+
gap: {
|
|
6626
|
+
...gap,
|
|
6627
|
+
oldStart: gap.oldStart + top,
|
|
6628
|
+
newStart: gap.newStart + top,
|
|
6629
|
+
...remaining === void 0 ? {} : { count: remaining }
|
|
6630
|
+
}
|
|
6631
|
+
});
|
|
6632
|
+
if (count !== void 0) for (let offset = count - bottom; offset < count; offset += 1) out.push(context(offset));
|
|
6633
|
+
}
|
|
6634
|
+
return out;
|
|
6635
|
+
}
|
|
6636
|
+
/**
|
|
6637
|
+
* Anchor for a drag from row `from` to row `to`: every commentable row in
|
|
6638
|
+
* between on the same side as the first row, collapsed to its first/last line.
|
|
6639
|
+
*/
|
|
6640
|
+
function rangeCommentAnchor(anchors, from, to) {
|
|
6641
|
+
const side = anchors[from]?.side;
|
|
6642
|
+
if (side === void 0) return void 0;
|
|
6643
|
+
const lines = anchors.slice(Math.min(from, to), Math.max(from, to) + 1).flatMap((anchor) => anchor?.side === side ? [anchor.line] : []);
|
|
6644
|
+
const line = Math.max(...lines);
|
|
6645
|
+
const startLine = Math.min(...lines);
|
|
6646
|
+
return startLine < line ? {
|
|
6647
|
+
line,
|
|
6648
|
+
side,
|
|
6649
|
+
startLine
|
|
6650
|
+
} : {
|
|
6651
|
+
line,
|
|
6652
|
+
side
|
|
6653
|
+
};
|
|
6654
|
+
}
|
|
6148
6655
|
/** Which working-tree line a comment on this rendered diff row refers to. */
|
|
6149
6656
|
function commentAnchorForLine(entry) {
|
|
6150
6657
|
if (entry.kind === "add" || entry.kind === "context") return entry.newLine === void 0 ? void 0 : {
|
|
@@ -6156,22 +6663,32 @@ window.__ModuleLoader__.load({
|
|
|
6156
6663
|
side: "old"
|
|
6157
6664
|
};
|
|
6158
6665
|
}
|
|
6159
|
-
function DiffLine({ entry, addLabel, onComment }) {
|
|
6160
|
-
const style = entry.kind === "add" ? diffLineAdd : entry.kind === "delete" ? diffLineDelete : entry.kind === "hunk"
|
|
6666
|
+
function DiffLine({ entry, addLabel, selected, onComment, onDragStart, onDragEnter }) {
|
|
6667
|
+
const style = entry.kind === "add" ? diffLineAdd : entry.kind === "delete" ? diffLineDelete : entry.kind === "hunk" ? diffLineHunk : diffLineContext;
|
|
6161
6668
|
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
6669
|
return /* @__PURE__ */ jsxs("div", {
|
|
6163
6670
|
className: diffLineRowClass,
|
|
6164
6671
|
style: {
|
|
6165
6672
|
...diffLine,
|
|
6166
|
-
...style
|
|
6673
|
+
...style,
|
|
6674
|
+
...selected ? diffLineSelected : {}
|
|
6167
6675
|
},
|
|
6676
|
+
onPointerEnter: onDragEnter,
|
|
6168
6677
|
children: [
|
|
6169
6678
|
/* @__PURE__ */ jsx("button", {
|
|
6170
6679
|
type: "button",
|
|
6171
6680
|
className: diffCommentButtonClass,
|
|
6172
6681
|
disabled: onComment === void 0,
|
|
6173
6682
|
"aria-label": addLabel,
|
|
6174
|
-
|
|
6683
|
+
onPointerDown: (event) => {
|
|
6684
|
+
if (event.button !== 0 || onDragStart === void 0) return;
|
|
6685
|
+
event.preventDefault();
|
|
6686
|
+
if (event.currentTarget.hasPointerCapture?.(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);
|
|
6687
|
+
onDragStart();
|
|
6688
|
+
},
|
|
6689
|
+
onClick: (event) => {
|
|
6690
|
+
if (event.detail === 0) onComment?.();
|
|
6691
|
+
},
|
|
6175
6692
|
children: "+"
|
|
6176
6693
|
}),
|
|
6177
6694
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -6180,14 +6697,105 @@ window.__ModuleLoader__.load({
|
|
|
6180
6697
|
}),
|
|
6181
6698
|
/* @__PURE__ */ jsx("span", {
|
|
6182
6699
|
style: diffLineMarker,
|
|
6183
|
-
children: entry.kind === "add" ? "+" : entry.kind === "delete" ? "−" :
|
|
6700
|
+
children: entry.kind === "add" ? "+" : entry.kind === "delete" ? "−" : " "
|
|
6184
6701
|
}),
|
|
6185
|
-
/* @__PURE__ */ jsx("span", {
|
|
6702
|
+
/* @__PURE__ */ jsx("span", {
|
|
6703
|
+
style: diffLineText,
|
|
6704
|
+
children: entry.line.slice(entry.kind === "hunk" ? 0 : 1)
|
|
6705
|
+
})
|
|
6186
6706
|
]
|
|
6187
6707
|
});
|
|
6188
6708
|
}
|
|
6189
|
-
function
|
|
6709
|
+
function ChevronGlyph({ direction }) {
|
|
6710
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
6711
|
+
width: "14",
|
|
6712
|
+
height: "14",
|
|
6713
|
+
viewBox: "0 0 14 14",
|
|
6714
|
+
fill: "none",
|
|
6715
|
+
stroke: "currentColor",
|
|
6716
|
+
strokeWidth: "1.5",
|
|
6717
|
+
strokeLinecap: "round",
|
|
6718
|
+
strokeLinejoin: "round",
|
|
6719
|
+
"aria-hidden": "true",
|
|
6720
|
+
children: /* @__PURE__ */ jsx("path", { d: direction === "up" ? "M3 8.5l4-4 4 4" : "M3 5.5l4 4 4-4" })
|
|
6721
|
+
});
|
|
6722
|
+
}
|
|
6723
|
+
/** "N unmodified lines" separator with GitHub-style expanders: ↑ above the first hunk, ↑↓ between hunks, ↓ after the last. */
|
|
6724
|
+
function DiffGapRow({ gap, t, busy, onExpand }) {
|
|
6725
|
+
const button = (direction) => /* @__PURE__ */ jsx("button", {
|
|
6726
|
+
type: "button",
|
|
6727
|
+
style: diffGapButton,
|
|
6728
|
+
disabled: busy || onExpand === void 0,
|
|
6729
|
+
"aria-label": t(direction === "up" ? "diffExpandUp" : "diffExpandDown"),
|
|
6730
|
+
title: t(direction === "up" ? "diffExpandUp" : "diffExpandDown"),
|
|
6731
|
+
onClick: () => onExpand?.(gap, direction),
|
|
6732
|
+
children: /* @__PURE__ */ jsx(ChevronGlyph, { direction })
|
|
6733
|
+
});
|
|
6734
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
6735
|
+
style: {
|
|
6736
|
+
...diffLine,
|
|
6737
|
+
...diffLineHunk
|
|
6738
|
+
},
|
|
6739
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
6740
|
+
style: diffGapControls,
|
|
6741
|
+
children: [gap.position === "bottom" ? null : button("up"), gap.position === "top" ? null : button("down")]
|
|
6742
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
6743
|
+
style: diffLineText,
|
|
6744
|
+
children: gap.count === void 0 ? t("diffUnmodifiedTail") : t("diffUnmodifiedLines", { count: gap.count })
|
|
6745
|
+
})]
|
|
6746
|
+
});
|
|
6747
|
+
}
|
|
6748
|
+
function DiffFileSection({ file, root, initiallyOpen, t, comments, ghComments, editorAnchor, editorNode, onOpenEditor, onRemoveComment }) {
|
|
6190
6749
|
const [open, setOpen] = useState(initiallyOpen);
|
|
6750
|
+
const [revealed, setRevealed] = useState(() => /* @__PURE__ */ new Map());
|
|
6751
|
+
const [total, setTotal] = useState();
|
|
6752
|
+
const [expanding, setExpanding] = useState(false);
|
|
6753
|
+
const [drag, setDrag] = useState();
|
|
6754
|
+
const rows = useMemo(() => expandDiffRows(numberDiffLines(file.lines), revealed, total), [
|
|
6755
|
+
file.lines,
|
|
6756
|
+
revealed,
|
|
6757
|
+
total
|
|
6758
|
+
]);
|
|
6759
|
+
const anchors = useMemo(() => rows.map(commentAnchorForLine), [rows]);
|
|
6760
|
+
const slash = file.path.lastIndexOf("/");
|
|
6761
|
+
const directory = slash < 0 ? "" : file.path.slice(0, slash + 1);
|
|
6762
|
+
const name = file.path.slice(slash + 1);
|
|
6763
|
+
const expand = (gap, direction) => {
|
|
6764
|
+
if (root === void 0 || expanding) return;
|
|
6765
|
+
const span = gap.count ?? 20;
|
|
6766
|
+
const size = Math.min(20, span);
|
|
6767
|
+
const from = direction === "down" ? gap.newStart : gap.newStart + span - size;
|
|
6768
|
+
setExpanding(true);
|
|
6769
|
+
loadRepositoryFileLines(root, file.path, from, from + size - 1).then((result) => {
|
|
6770
|
+
setRevealed((previous) => {
|
|
6771
|
+
const next = new Map(previous);
|
|
6772
|
+
result.lines.forEach((text, offset) => next.set(from + offset, text));
|
|
6773
|
+
return next;
|
|
6774
|
+
});
|
|
6775
|
+
setTotal(result.total);
|
|
6776
|
+
}, () => void 0).finally(() => setExpanding(false));
|
|
6777
|
+
};
|
|
6778
|
+
useEffect(() => {
|
|
6779
|
+
if (drag === void 0) return;
|
|
6780
|
+
const finish = () => {
|
|
6781
|
+
setDrag(void 0);
|
|
6782
|
+
const anchor = rangeCommentAnchor(anchors, drag.start, drag.end);
|
|
6783
|
+
if (anchor !== void 0) onOpenEditor(anchor);
|
|
6784
|
+
};
|
|
6785
|
+
window.addEventListener("pointerup", finish);
|
|
6786
|
+
window.addEventListener("pointercancel", finish);
|
|
6787
|
+
return () => {
|
|
6788
|
+
window.removeEventListener("pointerup", finish);
|
|
6789
|
+
window.removeEventListener("pointercancel", finish);
|
|
6790
|
+
};
|
|
6791
|
+
}, [
|
|
6792
|
+
anchors,
|
|
6793
|
+
drag,
|
|
6794
|
+
onOpenEditor
|
|
6795
|
+
]);
|
|
6796
|
+
const dragLow = drag === void 0 ? void 0 : Math.min(drag.start, drag.end);
|
|
6797
|
+
const dragHigh = drag === void 0 ? void 0 : Math.max(drag.start, drag.end);
|
|
6798
|
+
const dragSide = drag === void 0 ? void 0 : anchors[drag.start]?.side;
|
|
6191
6799
|
return /* @__PURE__ */ jsxs("section", {
|
|
6192
6800
|
style: diffFile,
|
|
6193
6801
|
children: [/* @__PURE__ */ jsxs("button", {
|
|
@@ -6203,9 +6811,16 @@ window.__ModuleLoader__.load({
|
|
|
6203
6811
|
},
|
|
6204
6812
|
children: "›"
|
|
6205
6813
|
}),
|
|
6206
|
-
/* @__PURE__ */
|
|
6814
|
+
/* @__PURE__ */ jsxs("span", {
|
|
6207
6815
|
style: diffFilePath,
|
|
6208
|
-
|
|
6816
|
+
title: file.path,
|
|
6817
|
+
children: [directory === "" ? null : /* @__PURE__ */ jsx("span", {
|
|
6818
|
+
style: diffFileDir,
|
|
6819
|
+
children: `\u202A${directory}\u202C`
|
|
6820
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
6821
|
+
style: diffFileName,
|
|
6822
|
+
children: name
|
|
6823
|
+
})]
|
|
6209
6824
|
}),
|
|
6210
6825
|
/* @__PURE__ */ jsxs("span", {
|
|
6211
6826
|
style: diffFileStats,
|
|
@@ -6220,22 +6835,39 @@ window.__ModuleLoader__.load({
|
|
|
6220
6835
|
]
|
|
6221
6836
|
}), open ? /* @__PURE__ */ jsx("div", {
|
|
6222
6837
|
style: diffCode,
|
|
6223
|
-
children:
|
|
6224
|
-
|
|
6838
|
+
children: rows.map((entry, index) => {
|
|
6839
|
+
if (entry.kind === "collapsed" && entry.gap !== void 0) return /* @__PURE__ */ jsx(DiffGapRow, {
|
|
6840
|
+
gap: entry.gap,
|
|
6841
|
+
t,
|
|
6842
|
+
busy: expanding,
|
|
6843
|
+
onExpand: root === void 0 ? void 0 : expand
|
|
6844
|
+
}, `gap:${entry.gap.newStart}`);
|
|
6845
|
+
const anchor = anchors[index];
|
|
6225
6846
|
const lineComments = anchor === void 0 ? [] : comments.filter((comment) => comment.line === anchor.line && comment.side === anchor.side);
|
|
6226
6847
|
const ghLineComments = anchor === void 0 ? [] : ghComments.filter((comment) => comment.line === anchor.line && comment.side === anchor.side);
|
|
6227
6848
|
const editorOpen = anchor !== void 0 && editorAnchor !== void 0 && editorAnchor.line === anchor.line && editorAnchor.side === anchor.side;
|
|
6849
|
+
const inDrag = dragLow !== void 0 && dragHigh !== void 0 && index >= dragLow && index <= dragHigh && anchor?.side === dragSide;
|
|
6850
|
+
const inEditorRange = anchor !== void 0 && editorAnchor !== void 0 && editorAnchor.side === anchor.side && anchor.line <= editorAnchor.line && anchor.line >= (editorAnchor.startLine ?? editorAnchor.line);
|
|
6228
6851
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6229
6852
|
/* @__PURE__ */ jsx(DiffLine, {
|
|
6230
6853
|
entry,
|
|
6231
6854
|
addLabel: t("reviewCommentAdd"),
|
|
6232
|
-
|
|
6855
|
+
selected: inDrag || inEditorRange,
|
|
6856
|
+
onComment: anchor === void 0 ? void 0 : () => onOpenEditor(anchor),
|
|
6857
|
+
onDragStart: anchor === void 0 ? void 0 : () => setDrag({
|
|
6858
|
+
start: index,
|
|
6859
|
+
end: index
|
|
6860
|
+
}),
|
|
6861
|
+
onDragEnter: drag === void 0 ? void 0 : () => setDrag((current) => current === void 0 ? current : {
|
|
6862
|
+
...current,
|
|
6863
|
+
end: index
|
|
6864
|
+
})
|
|
6233
6865
|
}),
|
|
6234
6866
|
lineComments.map((comment) => /* @__PURE__ */ jsxs("div", {
|
|
6235
6867
|
style: diffCommentBlock,
|
|
6236
6868
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
6237
6869
|
style: diffCommentCardMeta,
|
|
6238
|
-
children: [/* @__PURE__ */ jsx("span", { children: comment
|
|
6870
|
+
children: [/* @__PURE__ */ jsx("span", { children: commentLineLabel(comment, t) }), /* @__PURE__ */ jsx("button", {
|
|
6239
6871
|
type: "button",
|
|
6240
6872
|
style: reviewCommentChipRemove,
|
|
6241
6873
|
"aria-label": t("reviewCommentRemove"),
|
|
@@ -6478,6 +7110,7 @@ window.__ModuleLoader__.load({
|
|
|
6478
7110
|
const created = await addReviewComment(sessionId, {
|
|
6479
7111
|
path: commentEditor.path,
|
|
6480
7112
|
line: commentEditor.line,
|
|
7113
|
+
...commentEditor.startLine === void 0 ? {} : { startLine: commentEditor.startLine },
|
|
6481
7114
|
side: commentEditor.side,
|
|
6482
7115
|
text: commentDraft.trim()
|
|
6483
7116
|
});
|
|
@@ -6564,6 +7197,10 @@ window.__ModuleLoader__.load({
|
|
|
6564
7197
|
const commentEditorNode = commentEditor === void 0 ? null : /* @__PURE__ */ jsxs("div", {
|
|
6565
7198
|
style: diffCommentBlock,
|
|
6566
7199
|
children: [
|
|
7200
|
+
/* @__PURE__ */ jsx("div", {
|
|
7201
|
+
style: diffCommentRange,
|
|
7202
|
+
children: commentLineLabel(commentEditor, t)
|
|
7203
|
+
}),
|
|
6567
7204
|
/* @__PURE__ */ jsx("textarea", {
|
|
6568
7205
|
className: diffCommentTextareaClass,
|
|
6569
7206
|
style: diffCommentTextarea,
|
|
@@ -6601,12 +7238,14 @@ window.__ModuleLoader__.load({
|
|
|
6601
7238
|
/* @__PURE__ */ jsxs("style", {
|
|
6602
7239
|
"data-dsh-claude-repository-modal-styles": true,
|
|
6603
7240
|
children: [
|
|
7241
|
+
detailsCardCss,
|
|
6604
7242
|
diffModalCss,
|
|
6605
7243
|
panelIconButtonCss,
|
|
6606
7244
|
diffCommentCss
|
|
6607
7245
|
]
|
|
6608
7246
|
}),
|
|
6609
7247
|
/* @__PURE__ */ jsxs("div", {
|
|
7248
|
+
className: detailsCardClass,
|
|
6610
7249
|
style: {
|
|
6611
7250
|
...diffPanel,
|
|
6612
7251
|
...maximized ? diffPanelMaximized : {}
|
|
@@ -6728,6 +7367,7 @@ window.__ModuleLoader__.load({
|
|
|
6728
7367
|
children: t("diffEmpty")
|
|
6729
7368
|
}) : files.map((file, index) => /* @__PURE__ */ jsx(DiffFileSection, {
|
|
6730
7369
|
file,
|
|
7370
|
+
root: repository.root,
|
|
6731
7371
|
initiallyOpen: index === 0,
|
|
6732
7372
|
t,
|
|
6733
7373
|
comments: reviewComments.filter((comment) => comment.path === file.path),
|
|
@@ -7146,10 +7786,28 @@ window.__ModuleLoader__.load({
|
|
|
7146
7786
|
}
|
|
7147
7787
|
//#endregion
|
|
7148
7788
|
//#region src/client/ClaudePullRequestsPanel.tsx
|
|
7789
|
+
const NO_WORKSPACE_STATE = {};
|
|
7790
|
+
const NO_WORKSPACES = {
|
|
7791
|
+
subscribe: () => () => {},
|
|
7792
|
+
getSnapshot: () => NO_WORKSPACE_STATE
|
|
7793
|
+
};
|
|
7149
7794
|
const OVERVIEW_REFRESH_MS = 3e4;
|
|
7150
|
-
/**
|
|
7151
|
-
|
|
7152
|
-
|
|
7795
|
+
/** What a running session is blocked on: the latest permission or question
|
|
7796
|
+
* activity that is still in its started phase. */
|
|
7797
|
+
function overviewAttention(activities) {
|
|
7798
|
+
for (let index = activities.length - 1; index >= 0; index -= 1) {
|
|
7799
|
+
const activity = activities[index];
|
|
7800
|
+
if (activity === void 0 || activity.kind !== "permission" && activity.kind !== "question") continue;
|
|
7801
|
+
return activity.phase === "started" ? activity.kind : void 0;
|
|
7802
|
+
}
|
|
7803
|
+
}
|
|
7804
|
+
/** Claude sessions worth listing: rows still in the host list (byId keeps
|
|
7805
|
+
* deleted and breadcrumb rows), non-blank, non-subagent, with a checkout;
|
|
7806
|
+
* running first. */
|
|
7807
|
+
function claudeSessionRows(state, archivedSessionIds = []) {
|
|
7808
|
+
const rows = state.ids === void 0 ? Object.values(state.byId) : state.ids.map((id) => state.byId[id]);
|
|
7809
|
+
const archived = new Set(archivedSessionIds);
|
|
7810
|
+
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
7811
|
}
|
|
7154
7812
|
function Badge({ label, tone = "neutral" }) {
|
|
7155
7813
|
const toneStyle = tone === "success" ? repositoryItemSuccess : tone === "warning" ? repositoryItemWarning : tone === "error" ? repositoryItemError : tone === "merged" ? { color: "#a78bfa" } : {};
|
|
@@ -7170,9 +7828,27 @@ window.__ModuleLoader__.load({
|
|
|
7170
7828
|
function repositoryName(remote) {
|
|
7171
7829
|
return remote?.split("/").at(-1);
|
|
7172
7830
|
}
|
|
7173
|
-
function
|
|
7831
|
+
function OverviewAttention({ source, running, t }) {
|
|
7832
|
+
const snapshot = useSyncExternalStore(source.subscribe, source.getSnapshot, source.getSnapshot);
|
|
7833
|
+
const attention = running ? overviewAttention(snapshot.activities) : void 0;
|
|
7834
|
+
const usage = snapshot.contextUsage;
|
|
7835
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
7836
|
+
attention === "permission" ? /* @__PURE__ */ jsx(Badge, {
|
|
7837
|
+
label: t("overviewNeedsPermission"),
|
|
7838
|
+
tone: "warning"
|
|
7839
|
+
}) : null,
|
|
7840
|
+
attention === "question" ? /* @__PURE__ */ jsx(Badge, {
|
|
7841
|
+
label: t("overviewNeedsAnswer"),
|
|
7842
|
+
tone: "warning"
|
|
7843
|
+
}) : null,
|
|
7844
|
+
usage === void 0 ? null : /* @__PURE__ */ jsx("span", { children: t("overviewContextUsage", { percentage: usage.percentage }) })
|
|
7845
|
+
] });
|
|
7846
|
+
}
|
|
7847
|
+
function ClaudePullRequestsPanel({ t, closeDetails, openSession, loadStatus, sessions, workspaces, projectionFor }) {
|
|
7174
7848
|
const snapshot = useSyncExternalStore(sessions.subscribe, sessions.getSnapshot, sessions.getSnapshot);
|
|
7175
|
-
const
|
|
7849
|
+
const workspaceStore = workspaces ?? NO_WORKSPACES;
|
|
7850
|
+
const workspaceState = useSyncExternalStore(workspaceStore.subscribe, workspaceStore.getSnapshot, workspaceStore.getSnapshot);
|
|
7851
|
+
const rows = useMemo(() => claudeSessionRows(snapshot, workspaceState.archivedSessionIds ?? []), [snapshot, workspaceState]);
|
|
7176
7852
|
const cwdKey = useMemo(() => [...new Set(rows.map((row) => row.cwd ?? ""))].sort().join("\0"), [rows]);
|
|
7177
7853
|
const [statuses, setStatuses] = useState({});
|
|
7178
7854
|
useEffect(() => {
|
|
@@ -7195,11 +7871,12 @@ window.__ModuleLoader__.load({
|
|
|
7195
7871
|
};
|
|
7196
7872
|
}, [cwdKey, loadStatus]);
|
|
7197
7873
|
return /* @__PURE__ */ jsxs("div", {
|
|
7874
|
+
className: detailsCardClass,
|
|
7198
7875
|
style: tasksPanel,
|
|
7199
7876
|
children: [
|
|
7200
|
-
/* @__PURE__ */
|
|
7877
|
+
/* @__PURE__ */ jsxs("style", {
|
|
7201
7878
|
"data-dsh-claude-overview-styles": true,
|
|
7202
|
-
children: panelIconButtonCss
|
|
7879
|
+
children: [detailsCardCss, panelIconButtonCss]
|
|
7203
7880
|
}),
|
|
7204
7881
|
/* @__PURE__ */ jsxs("header", {
|
|
7205
7882
|
style: tasksHeader,
|
|
@@ -7267,7 +7944,12 @@ window.__ModuleLoader__.load({
|
|
|
7267
7944
|
autoFixEnabled(row.id) ? /* @__PURE__ */ jsx(Badge, {
|
|
7268
7945
|
label: t("overviewAutoFix"),
|
|
7269
7946
|
tone: "success"
|
|
7270
|
-
}) : null
|
|
7947
|
+
}) : null,
|
|
7948
|
+
projectionFor === void 0 ? null : /* @__PURE__ */ jsx(OverviewAttention, {
|
|
7949
|
+
source: projectionFor(row.id),
|
|
7950
|
+
running: row.running === true,
|
|
7951
|
+
t
|
|
7952
|
+
})
|
|
7271
7953
|
]
|
|
7272
7954
|
})]
|
|
7273
7955
|
}, row.id);
|
|
@@ -7277,6 +7959,602 @@ window.__ModuleLoader__.load({
|
|
|
7277
7959
|
});
|
|
7278
7960
|
}
|
|
7279
7961
|
//#endregion
|
|
7962
|
+
//#region src/client/ask-api.ts
|
|
7963
|
+
function record(value) {
|
|
7964
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
7965
|
+
}
|
|
7966
|
+
function parseAskEvent(line) {
|
|
7967
|
+
const event = record(JSON.parse(line));
|
|
7968
|
+
if (event?.type === "delta" && typeof event.text === "string") return {
|
|
7969
|
+
type: "delta",
|
|
7970
|
+
text: event.text
|
|
7971
|
+
};
|
|
7972
|
+
if (event?.type === "thinking" && typeof event.text === "string") return {
|
|
7973
|
+
type: "thinking",
|
|
7974
|
+
text: event.text
|
|
7975
|
+
};
|
|
7976
|
+
if (event?.type === "status" && typeof event.text === "string") return {
|
|
7977
|
+
type: "status",
|
|
7978
|
+
text: event.text
|
|
7979
|
+
};
|
|
7980
|
+
if (event?.type === "tool" && typeof event.id === "string" && (event.phase === "start" || event.phase === "input" || event.phase === "done")) return {
|
|
7981
|
+
type: "tool",
|
|
7982
|
+
id: event.id,
|
|
7983
|
+
phase: event.phase,
|
|
7984
|
+
...typeof event.name === "string" ? { name: event.name } : {},
|
|
7985
|
+
...typeof event.summary === "string" ? { summary: event.summary } : {},
|
|
7986
|
+
...event.error === true ? { error: true } : {}
|
|
7987
|
+
};
|
|
7988
|
+
if (event?.type === "done") return { type: "done" };
|
|
7989
|
+
if (event?.type === "error") return {
|
|
7990
|
+
type: "error",
|
|
7991
|
+
message: typeof event.message === "string" ? event.message : "The question could not be answered."
|
|
7992
|
+
};
|
|
7993
|
+
throw new Error("Invalid ask stream event.");
|
|
7994
|
+
}
|
|
7995
|
+
/** Stream an answer about selected reply text; resolves when the answer completes. */
|
|
7996
|
+
async function askAboutSelection(sessionId, request, onProgress, signal) {
|
|
7997
|
+
const response = await fetch(`${CLAUDE_ASK_PATH}?sessionId=${encodeURIComponent(sessionId)}`, {
|
|
7998
|
+
method: "POST",
|
|
7999
|
+
credentials: "same-origin",
|
|
8000
|
+
headers: {
|
|
8001
|
+
accept: "application/x-ndjson",
|
|
8002
|
+
"content-type": "application/json"
|
|
8003
|
+
},
|
|
8004
|
+
body: JSON.stringify(request),
|
|
8005
|
+
...signal === void 0 ? {} : { signal }
|
|
8006
|
+
});
|
|
8007
|
+
if (!response.ok) {
|
|
8008
|
+
const body = record(await response.json().catch(() => void 0));
|
|
8009
|
+
throw new Error(typeof body?.message === "string" ? body.message : "The question could not be sent.");
|
|
8010
|
+
}
|
|
8011
|
+
if (response.body === null) throw new Error("The answer stream is unavailable.");
|
|
8012
|
+
const reader = response.body.getReader();
|
|
8013
|
+
const decoder = new TextDecoder();
|
|
8014
|
+
let buffer = "";
|
|
8015
|
+
let finished = false;
|
|
8016
|
+
const handle = (line) => {
|
|
8017
|
+
if (line.trim().length === 0) return;
|
|
8018
|
+
const event = parseAskEvent(line);
|
|
8019
|
+
if (event.type === "delta") onProgress({
|
|
8020
|
+
type: "text",
|
|
8021
|
+
text: event.text
|
|
8022
|
+
});
|
|
8023
|
+
else if (event.type === "thinking") onProgress({
|
|
8024
|
+
type: "thinking",
|
|
8025
|
+
text: event.text
|
|
8026
|
+
});
|
|
8027
|
+
else if (event.type === "status") onProgress({
|
|
8028
|
+
type: "status",
|
|
8029
|
+
text: event.text
|
|
8030
|
+
});
|
|
8031
|
+
else if (event.type === "tool") onProgress(event);
|
|
8032
|
+
else if (event.type === "done") finished = true;
|
|
8033
|
+
else throw new Error(event.message);
|
|
8034
|
+
};
|
|
8035
|
+
while (true) {
|
|
8036
|
+
const chunk = await reader.read();
|
|
8037
|
+
buffer += decoder.decode(chunk.value, { stream: !chunk.done });
|
|
8038
|
+
const lines = buffer.split("\n");
|
|
8039
|
+
buffer = lines.pop() ?? "";
|
|
8040
|
+
for (const line of lines) handle(line);
|
|
8041
|
+
if (chunk.done) break;
|
|
8042
|
+
}
|
|
8043
|
+
handle(buffer);
|
|
8044
|
+
if (!finished) throw new Error("The answer ended unexpectedly.");
|
|
8045
|
+
}
|
|
8046
|
+
//#endregion
|
|
8047
|
+
//#region src/client/ClaudeSelectionAsk.tsx
|
|
8048
|
+
const CHAT_NODE = "[data-chat-flow-kind]";
|
|
8049
|
+
const USER_KIND = "user";
|
|
8050
|
+
const MAX_SELECTION_CHARS = 8e3;
|
|
8051
|
+
const MAX_CONTEXT_CHARS = 16e3;
|
|
8052
|
+
const POPUP_WIDTH = 560;
|
|
8053
|
+
const POPUP_ESTIMATED_HEIGHT = 320;
|
|
8054
|
+
const TOOLBAR_WIDTH = 64;
|
|
8055
|
+
const HIGHLIGHT_NAME = "dsh-claude-ask";
|
|
8056
|
+
function appendAnswerBlock(blocks, progress) {
|
|
8057
|
+
if (progress.type === "text") {
|
|
8058
|
+
const last = blocks.at(-1);
|
|
8059
|
+
if (last?.kind === "text") return [...blocks.slice(0, -1), {
|
|
8060
|
+
kind: "text",
|
|
8061
|
+
text: last.text + progress.text
|
|
8062
|
+
}];
|
|
8063
|
+
return [...blocks, {
|
|
8064
|
+
kind: "text",
|
|
8065
|
+
text: progress.text
|
|
8066
|
+
}];
|
|
8067
|
+
}
|
|
8068
|
+
if (progress.type !== "tool") return blocks;
|
|
8069
|
+
const index = blocks.findIndex((block) => block.kind === "tool" && block.id === progress.id);
|
|
8070
|
+
if (index < 0) {
|
|
8071
|
+
if (progress.phase === "done") return blocks;
|
|
8072
|
+
return [...blocks, {
|
|
8073
|
+
kind: "tool",
|
|
8074
|
+
id: progress.id,
|
|
8075
|
+
name: progress.name ?? "tool",
|
|
8076
|
+
state: "running",
|
|
8077
|
+
...progress.summary === void 0 ? {} : { summary: progress.summary }
|
|
8078
|
+
}];
|
|
8079
|
+
}
|
|
8080
|
+
const current = blocks[index];
|
|
8081
|
+
const next = {
|
|
8082
|
+
...current,
|
|
8083
|
+
...progress.name === void 0 ? {} : { name: progress.name },
|
|
8084
|
+
...progress.summary === void 0 ? {} : { summary: progress.summary },
|
|
8085
|
+
state: progress.phase === "done" ? progress.error === true ? "error" : "done" : current.state
|
|
8086
|
+
};
|
|
8087
|
+
return [
|
|
8088
|
+
...blocks.slice(0, index),
|
|
8089
|
+
next,
|
|
8090
|
+
...blocks.slice(index + 1)
|
|
8091
|
+
];
|
|
8092
|
+
}
|
|
8093
|
+
function answerText(blocks) {
|
|
8094
|
+
return blocks.filter((block) => block.kind === "text").map((block) => block.text.trim()).filter((text) => text.length > 0).join("\n\n");
|
|
8095
|
+
}
|
|
8096
|
+
function rectOf(range) {
|
|
8097
|
+
const rect = range.getBoundingClientRect();
|
|
8098
|
+
return {
|
|
8099
|
+
top: rect.top,
|
|
8100
|
+
left: rect.left,
|
|
8101
|
+
width: rect.width,
|
|
8102
|
+
bottom: rect.bottom
|
|
8103
|
+
};
|
|
8104
|
+
}
|
|
8105
|
+
/** Read the current selection when it sits inside an assistant reply. */
|
|
8106
|
+
function selectionInfoOf(selection, sessionId) {
|
|
8107
|
+
if (sessionId === void 0 || selection === null || selection.isCollapsed || selection.rangeCount === 0) return void 0;
|
|
8108
|
+
const range = selection.getRangeAt(0);
|
|
8109
|
+
const hostOf = (node) => {
|
|
8110
|
+
return (node instanceof Element ? node : node?.parentElement ?? null)?.closest(CHAT_NODE) ?? null;
|
|
8111
|
+
};
|
|
8112
|
+
const host = hostOf(range.startContainer) ?? hostOf(range.endContainer);
|
|
8113
|
+
if (host === null || host.dataset.chatFlowKind === USER_KIND) return void 0;
|
|
8114
|
+
const text = selection.toString().trim();
|
|
8115
|
+
if (text.length === 0) return void 0;
|
|
8116
|
+
return {
|
|
8117
|
+
text: text.slice(0, MAX_SELECTION_CHARS),
|
|
8118
|
+
context: (host.textContent ?? "").trim().slice(0, MAX_CONTEXT_CHARS),
|
|
8119
|
+
rect: rectOf(range),
|
|
8120
|
+
range: range.cloneRange()
|
|
8121
|
+
};
|
|
8122
|
+
}
|
|
8123
|
+
function toolbarPosition(rect, viewportWidth) {
|
|
8124
|
+
return {
|
|
8125
|
+
top: Math.max(8, rect.top - 40),
|
|
8126
|
+
left: Math.min(Math.max(8, rect.left + rect.width / 2 - TOOLBAR_WIDTH / 2), Math.max(8, viewportWidth - TOOLBAR_WIDTH - 8))
|
|
8127
|
+
};
|
|
8128
|
+
}
|
|
8129
|
+
/** Pick the side with room once, when the popup opens: below the selection
|
|
8130
|
+
* unless the space there is short and above is roomier. */
|
|
8131
|
+
function popupSide(rect, viewportHeight) {
|
|
8132
|
+
const roomBelow = viewportHeight - rect.bottom - 16;
|
|
8133
|
+
const roomAbove = rect.top - 16;
|
|
8134
|
+
return roomBelow >= POPUP_ESTIMATED_HEIGHT || roomBelow >= roomAbove ? "below" : "above";
|
|
8135
|
+
}
|
|
8136
|
+
/** Anchor on the chosen side so streamed content grows away from the text and
|
|
8137
|
+
* scrolls inside the popup instead of running off screen. */
|
|
8138
|
+
function popupPlacement(rect, side, viewportWidth, viewportHeight) {
|
|
8139
|
+
const width = Math.min(POPUP_WIDTH, viewportWidth - 16);
|
|
8140
|
+
const left = Math.min(Math.max(8, rect.left), Math.max(8, viewportWidth - width - 8));
|
|
8141
|
+
const cap = Math.round(viewportHeight * .7);
|
|
8142
|
+
if (side === "below") {
|
|
8143
|
+
const top = Math.max(8, rect.bottom + 8);
|
|
8144
|
+
return {
|
|
8145
|
+
top,
|
|
8146
|
+
left,
|
|
8147
|
+
width,
|
|
8148
|
+
maxHeight: Math.max(120, Math.min(cap, viewportHeight - top - 8))
|
|
8149
|
+
};
|
|
8150
|
+
}
|
|
8151
|
+
const bottom = Math.max(8, viewportHeight - rect.top + 8);
|
|
8152
|
+
return {
|
|
8153
|
+
bottom,
|
|
8154
|
+
left,
|
|
8155
|
+
width,
|
|
8156
|
+
maxHeight: Math.max(120, Math.min(cap, viewportHeight - bottom - 8))
|
|
8157
|
+
};
|
|
8158
|
+
}
|
|
8159
|
+
function CopyIcon() {
|
|
8160
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
8161
|
+
width: "14",
|
|
8162
|
+
height: "14",
|
|
8163
|
+
viewBox: "0 0 16 16",
|
|
8164
|
+
fill: "none",
|
|
8165
|
+
stroke: "currentColor",
|
|
8166
|
+
strokeWidth: "1.5",
|
|
8167
|
+
strokeLinecap: "round",
|
|
8168
|
+
strokeLinejoin: "round",
|
|
8169
|
+
"aria-hidden": "true",
|
|
8170
|
+
children: [/* @__PURE__ */ jsx("rect", {
|
|
8171
|
+
x: "5.5",
|
|
8172
|
+
y: "5.5",
|
|
8173
|
+
width: "8",
|
|
8174
|
+
height: "8",
|
|
8175
|
+
rx: "1.5"
|
|
8176
|
+
}), /* @__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" })]
|
|
8177
|
+
});
|
|
8178
|
+
}
|
|
8179
|
+
function AskIcon() {
|
|
8180
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
8181
|
+
width: "14",
|
|
8182
|
+
height: "14",
|
|
8183
|
+
viewBox: "0 0 16 16",
|
|
8184
|
+
fill: "none",
|
|
8185
|
+
stroke: "currentColor",
|
|
8186
|
+
strokeWidth: "1.5",
|
|
8187
|
+
strokeLinecap: "round",
|
|
8188
|
+
strokeLinejoin: "round",
|
|
8189
|
+
"aria-hidden": "true",
|
|
8190
|
+
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" })]
|
|
8191
|
+
});
|
|
8192
|
+
}
|
|
8193
|
+
function CheckIcon() {
|
|
8194
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
8195
|
+
width: "14",
|
|
8196
|
+
height: "14",
|
|
8197
|
+
viewBox: "0 0 16 16",
|
|
8198
|
+
fill: "none",
|
|
8199
|
+
stroke: "currentColor",
|
|
8200
|
+
strokeWidth: "1.8",
|
|
8201
|
+
strokeLinecap: "round",
|
|
8202
|
+
strokeLinejoin: "round",
|
|
8203
|
+
"aria-hidden": "true",
|
|
8204
|
+
children: /* @__PURE__ */ jsx("path", { d: "m3.5 8.5 3 3 6-7" })
|
|
8205
|
+
});
|
|
8206
|
+
}
|
|
8207
|
+
/** Selection toolbar over assistant replies: copy, or ask a follow-up whose
|
|
8208
|
+
* answer streams into a popup rendered with the Host Markdown renderer. */
|
|
8209
|
+
function ClaudeSelectionAsk({ t, currentSessionId, ownsSession, insertIntoChat }) {
|
|
8210
|
+
const [selection, setSelection] = useState();
|
|
8211
|
+
const [open, setOpen] = useState(false);
|
|
8212
|
+
const [question, setQuestion] = useState("");
|
|
8213
|
+
const [blocks, setBlocks] = useState([]);
|
|
8214
|
+
const answer = answerText(blocks);
|
|
8215
|
+
const [thinking, setThinking] = useState("");
|
|
8216
|
+
const [thinkingOpen, setThinkingOpen] = useState(false);
|
|
8217
|
+
const [started, setStarted] = useState(false);
|
|
8218
|
+
const [phase, setPhase] = useState("idle");
|
|
8219
|
+
const [error, setError] = useState();
|
|
8220
|
+
const [copied, setCopied] = useState();
|
|
8221
|
+
const [rect, setRect] = useState();
|
|
8222
|
+
const [side, setSide] = useState("below");
|
|
8223
|
+
const popupRef = useRef(null);
|
|
8224
|
+
const toolbarRef = useRef(null);
|
|
8225
|
+
const controller = useRef();
|
|
8226
|
+
const openRef = useRef(false);
|
|
8227
|
+
openRef.current = open;
|
|
8228
|
+
const close = useCallback(() => {
|
|
8229
|
+
controller.current?.abort();
|
|
8230
|
+
controller.current = void 0;
|
|
8231
|
+
setOpen(false);
|
|
8232
|
+
setSelection(void 0);
|
|
8233
|
+
setQuestion("");
|
|
8234
|
+
setBlocks([]);
|
|
8235
|
+
setThinking("");
|
|
8236
|
+
setThinkingOpen(false);
|
|
8237
|
+
setStarted(false);
|
|
8238
|
+
setPhase("idle");
|
|
8239
|
+
setError(void 0);
|
|
8240
|
+
setCopied(void 0);
|
|
8241
|
+
}, []);
|
|
8242
|
+
useEffect(() => {
|
|
8243
|
+
if (typeof document === "undefined") return;
|
|
8244
|
+
let timer;
|
|
8245
|
+
const update = () => {
|
|
8246
|
+
if (openRef.current) return;
|
|
8247
|
+
const sessionId = currentSessionId();
|
|
8248
|
+
if (sessionId === void 0 || !ownsSession(sessionId)) {
|
|
8249
|
+
setSelection(void 0);
|
|
8250
|
+
return;
|
|
8251
|
+
}
|
|
8252
|
+
const info = selectionInfoOf(document.getSelection(), sessionId);
|
|
8253
|
+
setSelection(info === void 0 ? void 0 : {
|
|
8254
|
+
sessionId,
|
|
8255
|
+
...info
|
|
8256
|
+
});
|
|
8257
|
+
};
|
|
8258
|
+
const schedule = () => {
|
|
8259
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
8260
|
+
timer = setTimeout(update, 120);
|
|
8261
|
+
};
|
|
8262
|
+
const onKey = (event) => {
|
|
8263
|
+
if (event.key === "Escape") close();
|
|
8264
|
+
};
|
|
8265
|
+
const onPointerDown = (event) => {
|
|
8266
|
+
if (!(event.target instanceof Node)) return;
|
|
8267
|
+
if (popupRef.current?.contains(event.target) === true || toolbarRef.current?.contains(event.target) === true) return;
|
|
8268
|
+
if (openRef.current) close();
|
|
8269
|
+
};
|
|
8270
|
+
document.addEventListener("selectionchange", schedule);
|
|
8271
|
+
document.addEventListener("mouseup", schedule);
|
|
8272
|
+
document.addEventListener("keydown", onKey);
|
|
8273
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
8274
|
+
return () => {
|
|
8275
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
8276
|
+
document.removeEventListener("selectionchange", schedule);
|
|
8277
|
+
document.removeEventListener("mouseup", schedule);
|
|
8278
|
+
document.removeEventListener("keydown", onKey);
|
|
8279
|
+
document.removeEventListener("pointerdown", onPointerDown);
|
|
8280
|
+
};
|
|
8281
|
+
}, [
|
|
8282
|
+
close,
|
|
8283
|
+
currentSessionId,
|
|
8284
|
+
ownsSession
|
|
8285
|
+
]);
|
|
8286
|
+
useEffect(() => () => controller.current?.abort(), []);
|
|
8287
|
+
useEffect(() => {
|
|
8288
|
+
setRect(selection?.rect);
|
|
8289
|
+
if (selection === void 0) return;
|
|
8290
|
+
let frame;
|
|
8291
|
+
const reposition = () => {
|
|
8292
|
+
if (frame !== void 0) return;
|
|
8293
|
+
frame = requestAnimationFrame(() => {
|
|
8294
|
+
frame = void 0;
|
|
8295
|
+
const next = rectOf(selection.range);
|
|
8296
|
+
if (next.width === 0 && next.bottom === next.top) return;
|
|
8297
|
+
setRect(next);
|
|
8298
|
+
});
|
|
8299
|
+
};
|
|
8300
|
+
document.addEventListener("scroll", reposition, true);
|
|
8301
|
+
window.addEventListener("resize", reposition);
|
|
8302
|
+
return () => {
|
|
8303
|
+
if (frame !== void 0) cancelAnimationFrame(frame);
|
|
8304
|
+
document.removeEventListener("scroll", reposition, true);
|
|
8305
|
+
window.removeEventListener("resize", reposition);
|
|
8306
|
+
};
|
|
8307
|
+
}, [selection]);
|
|
8308
|
+
useEffect(() => {
|
|
8309
|
+
if (!open || selection === void 0) return;
|
|
8310
|
+
const runtime = globalThis;
|
|
8311
|
+
const registry = runtime.CSS?.highlights;
|
|
8312
|
+
if (registry === void 0 || runtime.Highlight === void 0) return;
|
|
8313
|
+
registry.set(HIGHLIGHT_NAME, new runtime.Highlight(selection.range));
|
|
8314
|
+
return () => {
|
|
8315
|
+
registry.delete(HIGHLIGHT_NAME);
|
|
8316
|
+
};
|
|
8317
|
+
}, [open, selection]);
|
|
8318
|
+
useEffect(() => {
|
|
8319
|
+
if (copied === void 0) return;
|
|
8320
|
+
const timer = setTimeout(() => setCopied(void 0), 1200);
|
|
8321
|
+
return () => clearTimeout(timer);
|
|
8322
|
+
}, [copied]);
|
|
8323
|
+
if (selection === void 0 || rect === void 0) return /* @__PURE__ */ jsx("span", {
|
|
8324
|
+
"data-dsh-claude-selection-ask": "armed",
|
|
8325
|
+
hidden: true
|
|
8326
|
+
});
|
|
8327
|
+
const copy = (text, what) => {
|
|
8328
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
8329
|
+
setCopied(what);
|
|
8330
|
+
}, () => void 0);
|
|
8331
|
+
};
|
|
8332
|
+
const submit = () => {
|
|
8333
|
+
if (question.trim().length === 0 || phase === "answering") return;
|
|
8334
|
+
controller.current?.abort();
|
|
8335
|
+
const aborter = new AbortController();
|
|
8336
|
+
controller.current = aborter;
|
|
8337
|
+
setBlocks([]);
|
|
8338
|
+
setThinking("");
|
|
8339
|
+
setThinkingOpen(false);
|
|
8340
|
+
setStarted(false);
|
|
8341
|
+
setError(void 0);
|
|
8342
|
+
setPhase("answering");
|
|
8343
|
+
askAboutSelection(selection.sessionId, {
|
|
8344
|
+
selection: selection.text,
|
|
8345
|
+
context: selection.context,
|
|
8346
|
+
question
|
|
8347
|
+
}, (progress) => {
|
|
8348
|
+
if (progress.type === "status") setStarted(true);
|
|
8349
|
+
else if (progress.type === "thinking") setThinking((current) => current + progress.text);
|
|
8350
|
+
else setBlocks((current) => appendAnswerBlock(current, progress));
|
|
8351
|
+
}, aborter.signal).then(() => {
|
|
8352
|
+
if (!aborter.signal.aborted) setPhase("done");
|
|
8353
|
+
}, (reason) => {
|
|
8354
|
+
if (aborter.signal.aborted) return;
|
|
8355
|
+
setError(reason instanceof Error ? reason.message : t("askFailed"));
|
|
8356
|
+
setPhase("done");
|
|
8357
|
+
});
|
|
8358
|
+
};
|
|
8359
|
+
const viewportWidth = typeof window === "undefined" ? 1280 : window.innerWidth;
|
|
8360
|
+
const viewportHeight = typeof window === "undefined" ? 800 : window.innerHeight;
|
|
8361
|
+
if (!open) {
|
|
8362
|
+
const position = toolbarPosition(rect, viewportWidth);
|
|
8363
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
8364
|
+
ref: toolbarRef,
|
|
8365
|
+
role: "toolbar",
|
|
8366
|
+
"aria-label": t("askToolbar"),
|
|
8367
|
+
style: {
|
|
8368
|
+
...askToolbar,
|
|
8369
|
+
top: position.top,
|
|
8370
|
+
left: position.left
|
|
8371
|
+
},
|
|
8372
|
+
children: [
|
|
8373
|
+
/* @__PURE__ */ jsx("style", {
|
|
8374
|
+
"data-dsh-claude-ask-styles": true,
|
|
8375
|
+
children: panelIconButtonCss
|
|
8376
|
+
}),
|
|
8377
|
+
/* @__PURE__ */ jsx(Tooltip, {
|
|
8378
|
+
label: copied === "selection" ? t("askCopied") : t("copyTooltip"),
|
|
8379
|
+
side: "top",
|
|
8380
|
+
delayMs: 300,
|
|
8381
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
8382
|
+
type: "button",
|
|
8383
|
+
className: panelIconButtonClass,
|
|
8384
|
+
"aria-label": t("copyTooltip"),
|
|
8385
|
+
onMouseDown: (event) => {
|
|
8386
|
+
event.preventDefault();
|
|
8387
|
+
},
|
|
8388
|
+
onClick: () => {
|
|
8389
|
+
copy(selection.text, "selection");
|
|
8390
|
+
},
|
|
8391
|
+
children: copied === "selection" ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {})
|
|
8392
|
+
})
|
|
8393
|
+
}),
|
|
8394
|
+
/* @__PURE__ */ jsx(Tooltip, {
|
|
8395
|
+
label: t("askTooltip"),
|
|
8396
|
+
side: "top",
|
|
8397
|
+
delayMs: 300,
|
|
8398
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
8399
|
+
type: "button",
|
|
8400
|
+
className: panelIconButtonClass,
|
|
8401
|
+
"aria-label": t("askTooltip"),
|
|
8402
|
+
onMouseDown: (event) => {
|
|
8403
|
+
event.preventDefault();
|
|
8404
|
+
},
|
|
8405
|
+
onClick: () => {
|
|
8406
|
+
setSide(popupSide(rect, viewportHeight));
|
|
8407
|
+
setOpen(true);
|
|
8408
|
+
},
|
|
8409
|
+
children: /* @__PURE__ */ jsx(AskIcon, {})
|
|
8410
|
+
})
|
|
8411
|
+
})
|
|
8412
|
+
]
|
|
8413
|
+
});
|
|
8414
|
+
}
|
|
8415
|
+
const placement = popupPlacement(rect, side, viewportWidth, viewportHeight);
|
|
8416
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
8417
|
+
ref: popupRef,
|
|
8418
|
+
role: "dialog",
|
|
8419
|
+
"aria-label": t("askTooltip"),
|
|
8420
|
+
style: {
|
|
8421
|
+
...askPopup,
|
|
8422
|
+
...placement
|
|
8423
|
+
},
|
|
8424
|
+
children: [
|
|
8425
|
+
/* @__PURE__ */ jsxs("style", {
|
|
8426
|
+
"data-dsh-claude-ask-styles": true,
|
|
8427
|
+
children: [panelIconButtonCss, askHighlightCss]
|
|
8428
|
+
}),
|
|
8429
|
+
/* @__PURE__ */ jsx("p", {
|
|
8430
|
+
style: askQuote,
|
|
8431
|
+
children: selection.text
|
|
8432
|
+
}),
|
|
8433
|
+
phase === "idle" ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("textarea", {
|
|
8434
|
+
autoFocus: true,
|
|
8435
|
+
value: question,
|
|
8436
|
+
placeholder: t("askPlaceholder"),
|
|
8437
|
+
style: askTextarea,
|
|
8438
|
+
onChange: (event) => {
|
|
8439
|
+
setQuestion(event.currentTarget.value);
|
|
8440
|
+
},
|
|
8441
|
+
onKeyDown: (event) => {
|
|
8442
|
+
if (event.key === "Enter" && !event.shiftKey && !event.nativeEvent.isComposing) {
|
|
8443
|
+
event.preventDefault();
|
|
8444
|
+
submit();
|
|
8445
|
+
}
|
|
8446
|
+
}
|
|
8447
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
8448
|
+
style: askActions,
|
|
8449
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
8450
|
+
type: "button",
|
|
8451
|
+
style: askButton,
|
|
8452
|
+
onClick: close,
|
|
8453
|
+
children: t("askClose")
|
|
8454
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
8455
|
+
type: "button",
|
|
8456
|
+
style: {
|
|
8457
|
+
...askButton,
|
|
8458
|
+
...askPrimaryButton
|
|
8459
|
+
},
|
|
8460
|
+
disabled: question.trim().length === 0,
|
|
8461
|
+
onClick: submit,
|
|
8462
|
+
children: t("askSubmit")
|
|
8463
|
+
})]
|
|
8464
|
+
})] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
8465
|
+
/* @__PURE__ */ jsx("p", {
|
|
8466
|
+
style: askQuestion,
|
|
8467
|
+
children: question
|
|
8468
|
+
}),
|
|
8469
|
+
/* @__PURE__ */ jsxs("div", {
|
|
8470
|
+
style: askAnswer,
|
|
8471
|
+
children: [
|
|
8472
|
+
thinking.length === 0 ? null : /* @__PURE__ */ jsxs("button", {
|
|
8473
|
+
type: "button",
|
|
8474
|
+
style: askThinkingRow,
|
|
8475
|
+
"aria-expanded": thinkingOpen,
|
|
8476
|
+
onClick: () => {
|
|
8477
|
+
setThinkingOpen((value) => !value);
|
|
8478
|
+
},
|
|
8479
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
8480
|
+
style: askThinkingLabel,
|
|
8481
|
+
children: phase === "answering" && answer.length === 0 ? t("askThinkingLive") : t("askThinkingLabel")
|
|
8482
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
8483
|
+
style: thinkingOpen ? askThinkingFull : askThinkingPreview,
|
|
8484
|
+
children: thinkingOpen ? thinking : thinking.trimEnd().split("\n").filter((line) => line.trim().length > 0).at(-1)
|
|
8485
|
+
})]
|
|
8486
|
+
}),
|
|
8487
|
+
blocks.length === 0 && thinking.length === 0 && error === void 0 ? /* @__PURE__ */ jsx("span", {
|
|
8488
|
+
style: askStatus,
|
|
8489
|
+
children: started ? t("askThinking") : t("askStarting")
|
|
8490
|
+
}) : null,
|
|
8491
|
+
blocks.map((block, index) => block.kind === "text" ? /* @__PURE__ */ jsx(MarkdownText, {
|
|
8492
|
+
text: block.text,
|
|
8493
|
+
streaming: phase === "answering" && index === blocks.length - 1
|
|
8494
|
+
}, `text-${index}`) : /* @__PURE__ */ jsxs("div", {
|
|
8495
|
+
style: askToolRow,
|
|
8496
|
+
children: [
|
|
8497
|
+
/* @__PURE__ */ jsx("span", {
|
|
8498
|
+
style: {
|
|
8499
|
+
...askToolGlyph,
|
|
8500
|
+
...block.state === "error" ? askToolGlyphError : block.state === "done" ? askToolGlyphDone : {}
|
|
8501
|
+
},
|
|
8502
|
+
"aria-hidden": "true",
|
|
8503
|
+
children: block.state === "running" ? "…" : block.state === "done" ? "✓" : "×"
|
|
8504
|
+
}),
|
|
8505
|
+
/* @__PURE__ */ jsx("span", {
|
|
8506
|
+
style: askToolName,
|
|
8507
|
+
children: block.name
|
|
8508
|
+
}),
|
|
8509
|
+
block.summary === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
8510
|
+
style: askToolSummary,
|
|
8511
|
+
children: block.summary
|
|
8512
|
+
})
|
|
8513
|
+
]
|
|
8514
|
+
}, block.id)),
|
|
8515
|
+
error === void 0 ? null : /* @__PURE__ */ jsx("p", {
|
|
8516
|
+
role: "alert",
|
|
8517
|
+
style: askError,
|
|
8518
|
+
children: error
|
|
8519
|
+
})
|
|
8520
|
+
]
|
|
8521
|
+
}),
|
|
8522
|
+
/* @__PURE__ */ jsxs("div", {
|
|
8523
|
+
style: askActions,
|
|
8524
|
+
children: [
|
|
8525
|
+
answer.length === 0 ? null : /* @__PURE__ */ jsx("button", {
|
|
8526
|
+
type: "button",
|
|
8527
|
+
style: askButton,
|
|
8528
|
+
onClick: () => {
|
|
8529
|
+
copy(answer, "answer");
|
|
8530
|
+
},
|
|
8531
|
+
children: copied === "answer" ? t("askCopied") : t("askCopyAnswer")
|
|
8532
|
+
}),
|
|
8533
|
+
answer.length === 0 || insertIntoChat === void 0 ? null : /* @__PURE__ */ jsx("button", {
|
|
8534
|
+
type: "button",
|
|
8535
|
+
style: askButton,
|
|
8536
|
+
onClick: () => {
|
|
8537
|
+
insertIntoChat(selection.sessionId, `> ${selection.text.replaceAll("\n", "\n> ")}\n\n**${question}**\n\n${answer}`);
|
|
8538
|
+
close();
|
|
8539
|
+
},
|
|
8540
|
+
children: t("askSendToChat")
|
|
8541
|
+
}),
|
|
8542
|
+
/* @__PURE__ */ jsx("button", {
|
|
8543
|
+
type: "button",
|
|
8544
|
+
style: {
|
|
8545
|
+
...askButton,
|
|
8546
|
+
...askPrimaryButton
|
|
8547
|
+
},
|
|
8548
|
+
onClick: close,
|
|
8549
|
+
children: t("askClose")
|
|
8550
|
+
})
|
|
8551
|
+
]
|
|
8552
|
+
})
|
|
8553
|
+
] })
|
|
8554
|
+
]
|
|
8555
|
+
});
|
|
8556
|
+
}
|
|
8557
|
+
//#endregion
|
|
7280
8558
|
//#region src/client/hero-dom-bridge.ts
|
|
7281
8559
|
const PORTAL_ATTRIBUTE = "data-dsh-claude-hero-controls";
|
|
7282
8560
|
function normalizedText(element) {
|
|
@@ -7347,6 +8625,10 @@ window.__ModuleLoader__.load({
|
|
|
7347
8625
|
const normalized = query.trim().toLocaleLowerCase();
|
|
7348
8626
|
return normalized.length === 0 ? branches : branches.filter((branch) => branch.toLocaleLowerCase().includes(normalized));
|
|
7349
8627
|
}
|
|
8628
|
+
/** Toggle a ticket's membership in the multi-select, keyed by ticket key. */
|
|
8629
|
+
function toggleTicketSelection(tickets, ticket) {
|
|
8630
|
+
return tickets.some((item) => item.key === ticket.key) ? tickets.filter((item) => item.key !== ticket.key) : [...tickets, ticket];
|
|
8631
|
+
}
|
|
7350
8632
|
function branchMenuNavigationIndex(current, count, key) {
|
|
7351
8633
|
if (count <= 0) return 0;
|
|
7352
8634
|
if (key === "Home") return 0;
|
|
@@ -7377,7 +8659,7 @@ window.__ModuleLoader__.load({
|
|
|
7377
8659
|
function progressLabelKey(stage) {
|
|
7378
8660
|
return PROGRESS_LABEL_KEYS[stage];
|
|
7379
8661
|
}
|
|
7380
|
-
function WorktreeProgressCard({ stage, error, t, onDismiss }) {
|
|
8662
|
+
function WorktreeProgressCard({ stage, error, context, t, onDismiss }) {
|
|
7381
8663
|
const current = WORKTREE_PROGRESS_STAGES.indexOf(stage);
|
|
7382
8664
|
const visible = WORKTREE_PROGRESS_STAGES.slice(0, Math.max(0, current) + 1);
|
|
7383
8665
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -7421,9 +8703,12 @@ window.__ModuleLoader__.load({
|
|
|
7421
8703
|
}),
|
|
7422
8704
|
/* @__PURE__ */ jsxs("div", {
|
|
7423
8705
|
style: heroWorktreeProgressCopy,
|
|
7424
|
-
children: [/* @__PURE__ */
|
|
8706
|
+
children: [/* @__PURE__ */ jsxs("strong", {
|
|
7425
8707
|
style: heroWorktreeProgressTitle,
|
|
7426
|
-
children: error === void 0 ? t("repositoryProgressTitle") : t("repositoryProgressFailed")
|
|
8708
|
+
children: [error === void 0 ? t("repositoryProgressTitle") : t("repositoryProgressFailed"), context === void 0 ? null : /* @__PURE__ */ jsxs("span", {
|
|
8709
|
+
style: heroWorktreeProgressContext,
|
|
8710
|
+
children: [" ", context]
|
|
8711
|
+
})]
|
|
7427
8712
|
}), /* @__PURE__ */ jsx("span", {
|
|
7428
8713
|
style: heroWorktreeProgressCurrent,
|
|
7429
8714
|
children: error ?? t(progressLabelKey(stage))
|
|
@@ -7470,7 +8755,7 @@ window.__ModuleLoader__.load({
|
|
|
7470
8755
|
})]
|
|
7471
8756
|
});
|
|
7472
8757
|
}
|
|
7473
|
-
function ClaudeHeroRepositoryCapsule({ branches, selected, worktree, busy, menuOpen, worktreeLabel, searchPlaceholder, emptySearchLabel, onMenuOpenChange, onSelect, onWorktreeChange }) {
|
|
8758
|
+
function ClaudeHeroRepositoryCapsule({ branches, selected, worktree, busy, menuOpen, worktreeLabel, searchPlaceholder, emptySearchLabel, worktreeLocked = false, onMenuOpenChange, onSelect, onWorktreeChange }) {
|
|
7474
8759
|
const pickerRef = useRef(null);
|
|
7475
8760
|
const searchRef = useRef(null);
|
|
7476
8761
|
const optionRefs = useRef([]);
|
|
@@ -7599,11 +8884,11 @@ window.__ModuleLoader__.load({
|
|
|
7599
8884
|
/* @__PURE__ */ jsxs("button", {
|
|
7600
8885
|
type: "button",
|
|
7601
8886
|
role: "checkbox",
|
|
7602
|
-
"aria-checked": worktree,
|
|
7603
|
-
disabled: busy,
|
|
8887
|
+
"aria-checked": worktreeLocked || worktree,
|
|
8888
|
+
disabled: busy || worktreeLocked,
|
|
7604
8889
|
style: {
|
|
7605
8890
|
...heroWorktreeToggle,
|
|
7606
|
-
...worktree || worktreeHovered ? heroWorktreeToggleActive : {},
|
|
8891
|
+
...worktreeLocked || worktree || worktreeHovered ? heroWorktreeToggleActive : {},
|
|
7607
8892
|
...worktreeFocused ? heroWorktreeToggleFocused : {}
|
|
7608
8893
|
},
|
|
7609
8894
|
onMouseEnter: () => {
|
|
@@ -7612,8 +8897,8 @@ window.__ModuleLoader__.load({
|
|
|
7612
8897
|
onMouseLeave: () => {
|
|
7613
8898
|
setWorktreeHovered(false);
|
|
7614
8899
|
},
|
|
7615
|
-
onFocus: () => {
|
|
7616
|
-
setWorktreeFocused(
|
|
8900
|
+
onFocus: (event) => {
|
|
8901
|
+
setWorktreeFocused(event.currentTarget.matches(":focus-visible"));
|
|
7617
8902
|
},
|
|
7618
8903
|
onBlur: () => {
|
|
7619
8904
|
setWorktreeFocused(false);
|
|
@@ -7625,9 +8910,9 @@ window.__ModuleLoader__.load({
|
|
|
7625
8910
|
"aria-hidden": "true",
|
|
7626
8911
|
style: {
|
|
7627
8912
|
...heroWorktreeCheckbox,
|
|
7628
|
-
...worktree ? heroWorktreeCheckboxChecked : {}
|
|
8913
|
+
...worktreeLocked || worktree ? heroWorktreeCheckboxChecked : {}
|
|
7629
8914
|
},
|
|
7630
|
-
children: worktree ? /* @__PURE__ */ jsx("svg", {
|
|
8915
|
+
children: worktreeLocked || worktree ? /* @__PURE__ */ jsx("svg", {
|
|
7631
8916
|
viewBox: "0 0 12 12",
|
|
7632
8917
|
style: heroWorktreeCheckboxIcon,
|
|
7633
8918
|
children: /* @__PURE__ */ jsx("path", {
|
|
@@ -7644,7 +8929,7 @@ window.__ModuleLoader__.load({
|
|
|
7644
8929
|
]
|
|
7645
8930
|
});
|
|
7646
8931
|
}
|
|
7647
|
-
function ClaudeHeroRepositoryControls({ sessionId, useSessions, useWorkspaces, input, t, prepare }) {
|
|
8932
|
+
function ClaudeHeroRepositoryControls({ sessionId, useSessions, useWorkspaces, input, t, prepare, prepareMany }) {
|
|
7648
8933
|
const cwd = useSessions((state) => state.byId[sessionId]?.cwd);
|
|
7649
8934
|
const workspacePath = useWorkspaces((state) => state.items.find((item) => item.sessionIds.includes(sessionId))?.path);
|
|
7650
8935
|
const [portal, setPortal] = useState();
|
|
@@ -7657,7 +8942,9 @@ window.__ModuleLoader__.load({
|
|
|
7657
8942
|
const [progressError, setProgressError] = useState();
|
|
7658
8943
|
const [error, setError] = useState();
|
|
7659
8944
|
const [jiraConnected, setJiraConnected] = useState(false);
|
|
7660
|
-
const [
|
|
8945
|
+
const [tickets, setTickets] = useState([]);
|
|
8946
|
+
const [batchProgress, setBatchProgress] = useState();
|
|
8947
|
+
const [batchDone, setBatchDone] = useState();
|
|
7661
8948
|
const [ticketMenuOpen, setTicketMenuOpen] = useState(false);
|
|
7662
8949
|
const [ticketQuery, setTicketQuery] = useState("");
|
|
7663
8950
|
const [ticketResults, setTicketResults] = useState();
|
|
@@ -7706,7 +8993,9 @@ window.__ModuleLoader__.load({
|
|
|
7706
8993
|
setProgressStage(void 0);
|
|
7707
8994
|
setProgressError(void 0);
|
|
7708
8995
|
setError(void 0);
|
|
7709
|
-
|
|
8996
|
+
setTickets([]);
|
|
8997
|
+
setBatchProgress(void 0);
|
|
8998
|
+
setBatchDone(void 0);
|
|
7710
8999
|
setTicketMenuOpen(false);
|
|
7711
9000
|
setTicketQuery("");
|
|
7712
9001
|
setTicketResults(void 0);
|
|
@@ -7728,19 +9017,46 @@ window.__ModuleLoader__.load({
|
|
|
7728
9017
|
sessionId
|
|
7729
9018
|
]);
|
|
7730
9019
|
const availableBranches = branches === void 0 ? [] : repositoryBranchOptions(branches);
|
|
7731
|
-
const changed = branches !== void 0 && selected.length > 0 && (worktree ||
|
|
9020
|
+
const changed = branches !== void 0 && selected.length > 0 && (worktree || tickets.length > 0 || selected !== branches.current);
|
|
7732
9021
|
useEffect(() => {
|
|
7733
9022
|
if (!changed || portal === void 0 || busy) return;
|
|
7734
9023
|
const submit = (event) => {
|
|
7735
|
-
if (pendingRef.current || input.draft.trim().length === 0 &&
|
|
9024
|
+
if (pendingRef.current || input.draft.trim().length === 0 && tickets.length === 0) return;
|
|
7736
9025
|
if (!(event instanceof KeyboardEvent ? shouldInterceptKey(event) : shouldInterceptClick(event))) return;
|
|
7737
9026
|
event.preventDefault();
|
|
7738
9027
|
event.stopPropagation();
|
|
7739
9028
|
pendingRef.current = true;
|
|
7740
9029
|
setBusy(true);
|
|
7741
9030
|
setProgressError(void 0);
|
|
7742
|
-
setProgressStage(worktree ? "inspecting" : void 0);
|
|
7743
9031
|
setError(void 0);
|
|
9032
|
+
setBatchDone(void 0);
|
|
9033
|
+
if (tickets.length > 1) {
|
|
9034
|
+
const total = tickets.length;
|
|
9035
|
+
setBatchProgress({
|
|
9036
|
+
ticketKey: tickets[0]?.key ?? "",
|
|
9037
|
+
index: 0,
|
|
9038
|
+
total,
|
|
9039
|
+
stage: "inspecting"
|
|
9040
|
+
});
|
|
9041
|
+
setProgressStage("inspecting");
|
|
9042
|
+
prepareMany(branches.root, selected, tickets, (progress) => {
|
|
9043
|
+
setBatchProgress(progress);
|
|
9044
|
+
setProgressStage(progress.stage);
|
|
9045
|
+
}).then(() => {
|
|
9046
|
+
setBatchDone(total);
|
|
9047
|
+
setBatchProgress(void 0);
|
|
9048
|
+
setProgressStage(void 0);
|
|
9049
|
+
setTickets([]);
|
|
9050
|
+
}, (reason) => {
|
|
9051
|
+
setProgressError(reason instanceof Error ? reason.message : String(reason));
|
|
9052
|
+
}).finally(() => {
|
|
9053
|
+
pendingRef.current = false;
|
|
9054
|
+
setBusy(false);
|
|
9055
|
+
});
|
|
9056
|
+
return;
|
|
9057
|
+
}
|
|
9058
|
+
const ticket = tickets[0];
|
|
9059
|
+
setProgressStage(worktree ? "inspecting" : void 0);
|
|
7744
9060
|
prepare(branches.root, selected, worktree, (stage) => {
|
|
7745
9061
|
if (worktree) setProgressStage(stage);
|
|
7746
9062
|
}, ticket).catch((reason) => {
|
|
@@ -7765,8 +9081,9 @@ window.__ModuleLoader__.load({
|
|
|
7765
9081
|
input.draft,
|
|
7766
9082
|
portal,
|
|
7767
9083
|
prepare,
|
|
9084
|
+
prepareMany,
|
|
7768
9085
|
selected,
|
|
7769
|
-
|
|
9086
|
+
tickets,
|
|
7770
9087
|
worktree
|
|
7771
9088
|
]);
|
|
7772
9089
|
useEffect(() => {
|
|
@@ -7815,8 +9132,13 @@ window.__ModuleLoader__.load({
|
|
|
7815
9132
|
document.removeEventListener("pointerdown", closeOnOutsidePointer);
|
|
7816
9133
|
};
|
|
7817
9134
|
}, [ticketMenuOpen]);
|
|
7818
|
-
const
|
|
7819
|
-
|
|
9135
|
+
const toggleTicket = (next) => {
|
|
9136
|
+
setTickets((current) => toggleTicketSelection(current, next));
|
|
9137
|
+
setError(void 0);
|
|
9138
|
+
setBatchDone(void 0);
|
|
9139
|
+
};
|
|
9140
|
+
const clearTickets = () => {
|
|
9141
|
+
setTickets([]);
|
|
7820
9142
|
setError(void 0);
|
|
7821
9143
|
setTicketMenuOpen(false);
|
|
7822
9144
|
};
|
|
@@ -7836,6 +9158,7 @@ window.__ModuleLoader__.load({
|
|
|
7836
9158
|
worktreeLabel: t("repositoryWorktree"),
|
|
7837
9159
|
searchPlaceholder: t("repositoryBranchSearch"),
|
|
7838
9160
|
emptySearchLabel: t("repositoryBranchSearchEmpty"),
|
|
9161
|
+
worktreeLocked: tickets.length > 1,
|
|
7839
9162
|
onMenuOpenChange: setMenuOpen,
|
|
7840
9163
|
onSelect: (branch) => {
|
|
7841
9164
|
setSelected(branch);
|
|
@@ -7866,78 +9189,115 @@ window.__ModuleLoader__.load({
|
|
|
7866
9189
|
/* @__PURE__ */ jsx(TicketIcon, {}),
|
|
7867
9190
|
/* @__PURE__ */ jsx("span", {
|
|
7868
9191
|
style: heroBranchName,
|
|
7869
|
-
children:
|
|
9192
|
+
children: tickets.length === 0 ? t("heroTicket") : tickets.length === 1 ? tickets[0]?.key : t("heroTicketCount", { count: tickets.length })
|
|
7870
9193
|
}),
|
|
7871
9194
|
/* @__PURE__ */ jsx(IconChevronDownOutline14, {})
|
|
7872
9195
|
]
|
|
7873
9196
|
}), ticketMenuOpen ? /* @__PURE__ */ jsxs("span", {
|
|
7874
9197
|
role: "menu",
|
|
7875
|
-
style:
|
|
9198
|
+
style: {
|
|
9199
|
+
...heroBranchMenu,
|
|
9200
|
+
...heroTicketMenu
|
|
9201
|
+
},
|
|
7876
9202
|
onKeyDown: (event) => {
|
|
7877
9203
|
if (event.key === "Escape") {
|
|
7878
9204
|
event.preventDefault();
|
|
7879
9205
|
setTicketMenuOpen(false);
|
|
7880
9206
|
}
|
|
7881
9207
|
},
|
|
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
|
-
|
|
9208
|
+
children: [
|
|
9209
|
+
/* @__PURE__ */ jsxs("label", {
|
|
9210
|
+
style: heroBranchSearch,
|
|
9211
|
+
children: [/* @__PURE__ */ jsx(IconSearchOutline16, {}), /* @__PURE__ */ jsx("input", {
|
|
9212
|
+
ref: ticketSearchRef,
|
|
9213
|
+
type: "search",
|
|
9214
|
+
value: ticketQuery,
|
|
9215
|
+
placeholder: t("heroTicketSearch"),
|
|
9216
|
+
"aria-label": t("heroTicketSearch"),
|
|
9217
|
+
style: heroBranchSearchInput,
|
|
9218
|
+
onChange: (event) => {
|
|
9219
|
+
setTicketQuery(event.currentTarget.value);
|
|
9220
|
+
}
|
|
9221
|
+
})]
|
|
9222
|
+
}),
|
|
9223
|
+
tickets.length === 0 ? null : /* @__PURE__ */ jsxs("span", {
|
|
9224
|
+
style: heroTicketChips,
|
|
9225
|
+
children: [tickets.map((item) => /* @__PURE__ */ jsxs("span", {
|
|
9226
|
+
style: heroTicketChip,
|
|
9227
|
+
children: [item.key, /* @__PURE__ */ jsx("button", {
|
|
9228
|
+
type: "button",
|
|
9229
|
+
style: heroTicketChipRemove,
|
|
9230
|
+
"aria-label": t("heroTicketRemove", { key: item.key }),
|
|
9231
|
+
onClick: () => {
|
|
9232
|
+
toggleTicket(item);
|
|
9233
|
+
},
|
|
9234
|
+
children: "×"
|
|
9235
|
+
})]
|
|
9236
|
+
}, item.key)), tickets.length > 1 ? /* @__PURE__ */ jsx("button", {
|
|
9237
|
+
type: "button",
|
|
9238
|
+
style: heroTicketChipsClear,
|
|
9239
|
+
onClick: clearTickets,
|
|
7912
9240
|
children: t("heroTicketNone")
|
|
9241
|
+
}) : null]
|
|
9242
|
+
}),
|
|
9243
|
+
/* @__PURE__ */ jsx("span", {
|
|
9244
|
+
style: heroBranchList,
|
|
9245
|
+
children: ticketError !== void 0 ? /* @__PURE__ */ jsx("span", {
|
|
9246
|
+
style: heroBranchEmpty,
|
|
9247
|
+
children: ticketError
|
|
9248
|
+
}) : ticketResults === void 0 ? /* @__PURE__ */ jsx("span", {
|
|
9249
|
+
style: heroBranchEmpty,
|
|
9250
|
+
children: t("heroTicketLoading")
|
|
9251
|
+
}) : ticketResults.length === 0 ? /* @__PURE__ */ jsx("span", {
|
|
9252
|
+
style: heroBranchEmpty,
|
|
9253
|
+
children: t("heroTicketEmpty")
|
|
9254
|
+
}) : ticketResults.map((item) => {
|
|
9255
|
+
const picked = tickets.some((entry) => entry.key === item.key);
|
|
9256
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
9257
|
+
type: "button",
|
|
9258
|
+
role: "menuitemcheckbox",
|
|
9259
|
+
"aria-checked": picked,
|
|
9260
|
+
style: heroBranchItem,
|
|
9261
|
+
onClick: () => {
|
|
9262
|
+
toggleTicket(item);
|
|
9263
|
+
},
|
|
9264
|
+
children: [
|
|
9265
|
+
/* @__PURE__ */ jsx("span", {
|
|
9266
|
+
"aria-hidden": "true",
|
|
9267
|
+
style: {
|
|
9268
|
+
...heroTicketCheckbox,
|
|
9269
|
+
...picked ? heroWorktreeCheckboxChecked : {}
|
|
9270
|
+
},
|
|
9271
|
+
children: picked ? /* @__PURE__ */ jsx("svg", {
|
|
9272
|
+
viewBox: "0 0 12 12",
|
|
9273
|
+
style: heroWorktreeCheckboxIcon,
|
|
9274
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
9275
|
+
d: "m2.5 6.2 2.1 2.1 4.9-5",
|
|
9276
|
+
fill: "none",
|
|
9277
|
+
stroke: "currentColor",
|
|
9278
|
+
strokeLinecap: "round",
|
|
9279
|
+
strokeLinejoin: "round",
|
|
9280
|
+
strokeWidth: "1.8"
|
|
9281
|
+
})
|
|
9282
|
+
}) : null
|
|
9283
|
+
}),
|
|
9284
|
+
/* @__PURE__ */ jsx("span", {
|
|
9285
|
+
style: heroTicketKey,
|
|
9286
|
+
children: item.key
|
|
9287
|
+
}),
|
|
9288
|
+
/* @__PURE__ */ jsx("span", {
|
|
9289
|
+
style: heroBranchItemName,
|
|
9290
|
+
children: item.summary
|
|
9291
|
+
}),
|
|
9292
|
+
item.status === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
9293
|
+
style: heroTicketStatus,
|
|
9294
|
+
children: item.status
|
|
9295
|
+
})
|
|
9296
|
+
]
|
|
9297
|
+
}, item.key);
|
|
7913
9298
|
})
|
|
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
|
-
})]
|
|
9299
|
+
})
|
|
9300
|
+
]
|
|
7941
9301
|
}) : null]
|
|
7942
9302
|
})
|
|
7943
9303
|
}),
|
|
@@ -7945,14 +9305,21 @@ window.__ModuleLoader__.load({
|
|
|
7945
9305
|
role: "alert",
|
|
7946
9306
|
style: heroRepositoryError,
|
|
7947
9307
|
children: error
|
|
9308
|
+
}),
|
|
9309
|
+
batchDone === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
9310
|
+
role: "status",
|
|
9311
|
+
style: heroRepositoryStatus,
|
|
9312
|
+
children: t("heroBatchStarted", { count: batchDone })
|
|
7948
9313
|
})
|
|
7949
9314
|
] }), progressStage === void 0 || !busy && progressError === void 0 ? null : /* @__PURE__ */ jsx(WorktreeProgressCard, {
|
|
7950
9315
|
stage: progressStage,
|
|
7951
9316
|
...progressError === void 0 ? {} : { error: progressError },
|
|
9317
|
+
...batchProgress === void 0 ? {} : { context: `${batchProgress.ticketKey} · ${batchProgress.index + 1}/${batchProgress.total}` },
|
|
7952
9318
|
t,
|
|
7953
9319
|
onDismiss: () => {
|
|
7954
9320
|
setProgressStage(void 0);
|
|
7955
9321
|
setProgressError(void 0);
|
|
9322
|
+
setBatchProgress(void 0);
|
|
7956
9323
|
}
|
|
7957
9324
|
})]
|
|
7958
9325
|
}), portal);
|
|
@@ -8436,7 +9803,10 @@ window.__ModuleLoader__.load({
|
|
|
8436
9803
|
heroTicketSearch: "搜索 ticket 或输入 key…",
|
|
8437
9804
|
heroTicketLoading: "搜索中…",
|
|
8438
9805
|
heroTicketEmpty: "没有匹配的 ticket",
|
|
8439
|
-
heroTicketNone: "
|
|
9806
|
+
heroTicketNone: "清除已选 ticket",
|
|
9807
|
+
heroTicketRemove: "移除 {key}",
|
|
9808
|
+
heroTicketCount: "{count} 个 ticket",
|
|
9809
|
+
heroBatchStarted: "已为 {count} 个 ticket 各自创建 Worktree 会话并开工",
|
|
8440
9810
|
heroTicketNotConnected: "请先在 Settings 中连接 Jira",
|
|
8441
9811
|
heroTicketFailed: "Ticket 搜索失败",
|
|
8442
9812
|
jiraTitle: "Jira",
|
|
@@ -8456,14 +9826,31 @@ window.__ModuleLoader__.load({
|
|
|
8456
9826
|
cleanupTitle: "清理已合并分支",
|
|
8457
9827
|
cleanupDescription: "删除 worktree 与本地分支并移除对应 workspace;普通 checkout 则切回 base 分支并删除已合并分支。",
|
|
8458
9828
|
cleanupCompleted: "已清理 {branch}",
|
|
8459
|
-
overviewOpen: "
|
|
8460
|
-
overviewTitle: "
|
|
8461
|
-
overviewBody: "所有 Claude
|
|
9829
|
+
overviewOpen: "打开 Claude 会话看板",
|
|
9830
|
+
overviewTitle: "会话看板",
|
|
9831
|
+
overviewBody: "所有 Claude 会话的运行状态、分支与 PR",
|
|
8462
9832
|
overviewEmpty: "没有正在进行的 Claude 会话",
|
|
8463
9833
|
overviewNoPr: "无 PR",
|
|
8464
9834
|
overviewRunning: "运行中",
|
|
9835
|
+
overviewNeedsPermission: "等待权限确认",
|
|
9836
|
+
overviewNeedsAnswer: "等待回答",
|
|
9837
|
+
overviewContextUsage: "上下文 {percentage}%",
|
|
8465
9838
|
overviewAutoFix: "Auto fix 已开启",
|
|
8466
9839
|
overviewLoading: "读取中…",
|
|
9840
|
+
askToolbar: "选中文本操作",
|
|
9841
|
+
askTooltip: "针对选中内容追问",
|
|
9842
|
+
copyTooltip: "复制",
|
|
9843
|
+
askCopied: "已复制",
|
|
9844
|
+
askPlaceholder: "针对选中内容提问…",
|
|
9845
|
+
askSubmit: "发送",
|
|
9846
|
+
askStarting: "正在启动 Claude…",
|
|
9847
|
+
askThinking: "思考中…",
|
|
9848
|
+
askThinkingLive: "思考中 ·",
|
|
9849
|
+
askThinkingLabel: "Think ·",
|
|
9850
|
+
askCopyAnswer: "复制回答",
|
|
9851
|
+
askSendToChat: "转发到对话",
|
|
9852
|
+
askClose: "关闭",
|
|
9853
|
+
askFailed: "提问失败",
|
|
8467
9854
|
reviewCommentAdd: "添加行评论",
|
|
8468
9855
|
reviewCommentPlaceholder: "请求更改",
|
|
8469
9856
|
reviewCommentSubmit: "注释",
|
|
@@ -8474,7 +9861,13 @@ window.__ModuleLoader__.load({
|
|
|
8474
9861
|
reviewCommentsSend: "发送评论",
|
|
8475
9862
|
reviewCommentsSendDraft: "请处理以上代码评论。",
|
|
8476
9863
|
reviewCommentOldSide: "旧代码第 {line} 行",
|
|
8477
|
-
reviewCommentNewSide: "第 {line} 行"
|
|
9864
|
+
reviewCommentNewSide: "第 {line} 行",
|
|
9865
|
+
reviewCommentOldRange: "旧代码第 {start}–{end} 行",
|
|
9866
|
+
reviewCommentNewRange: "第 {start}–{end} 行",
|
|
9867
|
+
diffUnmodifiedLines: "{count} 行未修改",
|
|
9868
|
+
diffUnmodifiedTail: "文件末尾之前还有未修改的行",
|
|
9869
|
+
diffExpandUp: "向上展开",
|
|
9870
|
+
diffExpandDown: "向下展开"
|
|
8478
9871
|
};
|
|
8479
9872
|
const en = {
|
|
8480
9873
|
nav: "Claude Code",
|
|
@@ -8707,7 +10100,10 @@ window.__ModuleLoader__.load({
|
|
|
8707
10100
|
heroTicketSearch: "Search tickets or enter a key…",
|
|
8708
10101
|
heroTicketLoading: "Searching…",
|
|
8709
10102
|
heroTicketEmpty: "No matching tickets",
|
|
8710
|
-
heroTicketNone: "
|
|
10103
|
+
heroTicketNone: "Clear selected tickets",
|
|
10104
|
+
heroTicketRemove: "Remove {key}",
|
|
10105
|
+
heroTicketCount: "{count} tickets",
|
|
10106
|
+
heroBatchStarted: "Kicked off {count} tickets, each in its own worktree session",
|
|
8711
10107
|
heroTicketNotConnected: "Connect Jira in Settings first",
|
|
8712
10108
|
heroTicketFailed: "Ticket search failed",
|
|
8713
10109
|
jiraTitle: "Jira",
|
|
@@ -8727,14 +10123,31 @@ window.__ModuleLoader__.load({
|
|
|
8727
10123
|
cleanupTitle: "Clean up merged branch",
|
|
8728
10124
|
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
10125
|
cleanupCompleted: "Cleaned up {branch}",
|
|
8730
|
-
overviewOpen: "
|
|
8731
|
-
overviewTitle: "
|
|
8732
|
-
overviewBody: "
|
|
10126
|
+
overviewOpen: "Open the Claude session board",
|
|
10127
|
+
overviewTitle: "Session board",
|
|
10128
|
+
overviewBody: "Run state, branch, and pull request across Claude sessions",
|
|
8733
10129
|
overviewEmpty: "No active Claude sessions",
|
|
8734
10130
|
overviewNoPr: "No PR",
|
|
8735
10131
|
overviewRunning: "Running",
|
|
10132
|
+
overviewNeedsPermission: "Awaiting approval",
|
|
10133
|
+
overviewNeedsAnswer: "Awaiting answer",
|
|
10134
|
+
overviewContextUsage: "Context {percentage}%",
|
|
8736
10135
|
overviewAutoFix: "Auto fix on",
|
|
8737
10136
|
overviewLoading: "Loading…",
|
|
10137
|
+
askToolbar: "Selection actions",
|
|
10138
|
+
askTooltip: "Ask about this",
|
|
10139
|
+
copyTooltip: "Copy",
|
|
10140
|
+
askCopied: "Copied",
|
|
10141
|
+
askPlaceholder: "Ask about the selected text…",
|
|
10142
|
+
askSubmit: "Ask",
|
|
10143
|
+
askStarting: "Starting Claude…",
|
|
10144
|
+
askThinking: "Thinking…",
|
|
10145
|
+
askThinkingLive: "Thinking ·",
|
|
10146
|
+
askThinkingLabel: "Think ·",
|
|
10147
|
+
askCopyAnswer: "Copy answer",
|
|
10148
|
+
askSendToChat: "Send to chat",
|
|
10149
|
+
askClose: "Close",
|
|
10150
|
+
askFailed: "The question could not be answered",
|
|
8738
10151
|
reviewCommentAdd: "Add line comment",
|
|
8739
10152
|
reviewCommentPlaceholder: "Request changes",
|
|
8740
10153
|
reviewCommentSubmit: "Comment",
|
|
@@ -8745,7 +10158,13 @@ window.__ModuleLoader__.load({
|
|
|
8745
10158
|
reviewCommentsSend: "Send comments",
|
|
8746
10159
|
reviewCommentsSendDraft: "Please address the attached review comments.",
|
|
8747
10160
|
reviewCommentOldSide: "Old line {line}",
|
|
8748
|
-
reviewCommentNewSide: "Line {line}"
|
|
10161
|
+
reviewCommentNewSide: "Line {line}",
|
|
10162
|
+
reviewCommentOldRange: "Old lines {start}–{end}",
|
|
10163
|
+
reviewCommentNewRange: "Lines {start}–{end}",
|
|
10164
|
+
diffUnmodifiedLines: "{count} unmodified lines",
|
|
10165
|
+
diffUnmodifiedTail: "More unmodified lines below",
|
|
10166
|
+
diffExpandUp: "Expand up",
|
|
10167
|
+
diffExpandDown: "Expand down"
|
|
8749
10168
|
};
|
|
8750
10169
|
//#endregion
|
|
8751
10170
|
//#region src/client/index.tsx
|
|
@@ -8880,7 +10299,9 @@ window.__ModuleLoader__.load({
|
|
|
8880
10299
|
sessions.open(id);
|
|
8881
10300
|
},
|
|
8882
10301
|
loadStatus: loadRepositoryStatusFor,
|
|
8883
|
-
sessions: sessions.list
|
|
10302
|
+
sessions: sessions.list,
|
|
10303
|
+
...workspaces === void 0 ? {} : { workspaces: workspaces.list },
|
|
10304
|
+
projectionFor: (id) => projections.source(id)
|
|
8884
10305
|
})
|
|
8885
10306
|
}, ClaudePullRequestsPanel);
|
|
8886
10307
|
} catch {
|
|
@@ -9014,6 +10435,22 @@ window.__ModuleLoader__.load({
|
|
|
9014
10435
|
};
|
|
9015
10436
|
}
|
|
9016
10437
|
}, ClaudeRepositoryStatus));
|
|
10438
|
+
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
10439
|
+
name: "shell.overlay",
|
|
10440
|
+
id: "claude-selection-ask",
|
|
10441
|
+
locale: namespace
|
|
10442
|
+
}, () => /* @__PURE__ */ jsx(ClaudeSelectionAsk, {
|
|
10443
|
+
t,
|
|
10444
|
+
currentSessionId: () => sessions?.list.getSnapshot().current,
|
|
10445
|
+
ownsSession: (sessionId) => projections.source(sessionId).getSnapshot().owned,
|
|
10446
|
+
...sessions === void 0 || conversation === void 0 ? {} : { insertIntoChat: (sessionId, text) => {
|
|
10447
|
+
const scope = sessions.scope(sessionId);
|
|
10448
|
+
if (scope === void 0) return;
|
|
10449
|
+
const input = conversation.input.for(scope);
|
|
10450
|
+
const current = input.state.getSnapshot().draft;
|
|
10451
|
+
input.setDraft(current.trim() === "" ? text : `${current}\n\n${text}`);
|
|
10452
|
+
} }
|
|
10453
|
+
})));
|
|
9017
10454
|
if (sessions !== void 0 && conversation !== void 0) ctx.slots.inject("conversation.input.dock", () => ctx.slots.register({
|
|
9018
10455
|
name: "conversation.input.dock",
|
|
9019
10456
|
id: "queue",
|
|
@@ -9077,6 +10514,52 @@ window.__ModuleLoader__.load({
|
|
|
9077
10514
|
targetInput.submit();
|
|
9078
10515
|
sourceInput.setDraft("");
|
|
9079
10516
|
for (const imageId of imageIds) sourceInput.removeImage(imageId);
|
|
10517
|
+
},
|
|
10518
|
+
prepareMany: async (cwd, branch, tickets, onProgress) => {
|
|
10519
|
+
const sourceScope = sessions.scope(sourceSessionId);
|
|
10520
|
+
if (sourceScope === void 0) throw new Error(t("repositorySessionUnavailable"));
|
|
10521
|
+
const sourceInput = conversation.input.for(sourceScope);
|
|
10522
|
+
const rawDraft = sourceInput.state.getSnapshot().draft;
|
|
10523
|
+
const failures = [];
|
|
10524
|
+
for (const [index, ticket] of tickets.entries()) {
|
|
10525
|
+
const report = (stage) => {
|
|
10526
|
+
onProgress({
|
|
10527
|
+
ticketKey: ticket.key,
|
|
10528
|
+
index,
|
|
10529
|
+
total: tickets.length,
|
|
10530
|
+
stage
|
|
10531
|
+
});
|
|
10532
|
+
};
|
|
10533
|
+
try {
|
|
10534
|
+
report("inspecting");
|
|
10535
|
+
const prepared = await prepareRepository(cwd, branch, true, ticket.key, report);
|
|
10536
|
+
assignJiraTicket(ticket.key).catch((reason) => {
|
|
10537
|
+
console.warn(`dsh-claude: could not assign ${ticket.key}: ${reason instanceof Error ? reason.message : String(reason)}`);
|
|
10538
|
+
});
|
|
10539
|
+
report("creating-workspace");
|
|
10540
|
+
const workspace = await workspaces.create({ path: prepared.path });
|
|
10541
|
+
report("starting-session");
|
|
10542
|
+
const targetSessionId = await workspaces.connectWorkspace(workspace.workspaceId);
|
|
10543
|
+
const targetScope = sessions.scope(targetSessionId);
|
|
10544
|
+
if (targetScope === void 0) throw new Error(t("repositorySessionUnavailable"));
|
|
10545
|
+
const presetResponse = await connection.api.agentPresets.select({
|
|
10546
|
+
sessionId: targetSessionId,
|
|
10547
|
+
agentPreset: "claude"
|
|
10548
|
+
});
|
|
10549
|
+
if (!presetResponse.result.ok) throw new Error(presetResponse.result.error.message);
|
|
10550
|
+
sessions.noteAgentPreset(targetSessionId, presetResponse.result.value.agentPreset);
|
|
10551
|
+
const targetInput = conversation.input.for(targetScope);
|
|
10552
|
+
report("transferring-draft");
|
|
10553
|
+
targetInput.setDraft(rawDraft.trim() === "" ? ticketPrompt(ticket) : `${rawDraft.trimEnd()}\n\n${ticketContext(ticket)}`);
|
|
10554
|
+
if (prepared.leaseId !== void 0) await bindRepositoryLease(prepared.leaseId, targetSessionId);
|
|
10555
|
+
report("submitting");
|
|
10556
|
+
targetInput.submit();
|
|
10557
|
+
} catch (cause) {
|
|
10558
|
+
failures.push(`${ticket.key}: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
10559
|
+
}
|
|
10560
|
+
}
|
|
10561
|
+
if (failures.length < tickets.length) sourceInput.setDraft("");
|
|
10562
|
+
if (failures.length > 0) throw new Error(failures.join(" · "));
|
|
9080
10563
|
}
|
|
9081
10564
|
})
|
|
9082
10565
|
}, ClaudeHeroRepositoryControls));
|