flavor-code 1.4.0-beta.10 → 1.4.0-beta.12
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/README.md +4 -1
- package/README.zh-CN.md +4 -1
- package/dist/{app-SMIB6P23.js → app-F44LTVBV.js} +509 -133
- package/dist/{chunk-EXOSMO57.js → chunk-7YFHRORG.js} +2 -3
- package/dist/{chunk-BYHO2CA5.js → chunk-AOOVLNX4.js} +8 -6
- package/dist/{chunk-UO4DLWU5.js → chunk-G7CY3S5B.js} +1 -1
- package/dist/{chunk-XMRKRPNC.js → chunk-VMQWXQEC.js} +2 -1
- package/dist/{claude-ink-6EZHF64C.js → claude-ink-JZXNSAQS.js} +1 -1
- package/dist/cli-main.js +6 -6
- package/dist/config/schema.d.ts +2 -0
- package/dist/desktop/main.js +9 -8
- package/dist/desktop-renderer/assets/index-BM9ugkh9.js +154 -0
- package/dist/desktop-renderer/assets/{interactive-terminal-DestMQ2z.js → interactive-terminal-1agnYY5L.js} +1 -1
- package/dist/desktop-renderer/index.html +1 -1
- package/dist/{load-EW56Q2MM.js → load-UPOG3XQR.js} +1 -1
- package/dist/models/openai.d.ts +4 -2
- package/dist/sdk/index.js +3 -3
- package/package.json +1 -1
- package/dist/desktop-renderer/assets/index-RNe5Gtum.js +0 -154
|
@@ -19,9 +19,9 @@ import {
|
|
|
19
19
|
thinkingWindow,
|
|
20
20
|
transcriptReducer,
|
|
21
21
|
withTimeout
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-AOOVLNX4.js";
|
|
23
23
|
import "./chunk-N5MXHJKD.js";
|
|
24
|
-
import "./chunk-
|
|
24
|
+
import "./chunk-7YFHRORG.js";
|
|
25
25
|
import {
|
|
26
26
|
Box_default,
|
|
27
27
|
ClockContext,
|
|
@@ -34,13 +34,15 @@ import {
|
|
|
34
34
|
instances_default,
|
|
35
35
|
osc,
|
|
36
36
|
shiftAnchor,
|
|
37
|
+
stringWidth,
|
|
37
38
|
stripAnsi,
|
|
38
39
|
useStdout,
|
|
39
40
|
use_app_default,
|
|
40
41
|
use_input_default
|
|
41
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-VMQWXQEC.js";
|
|
42
43
|
import {
|
|
43
|
-
execFileNoThrow
|
|
44
|
+
execFileNoThrow,
|
|
45
|
+
getGraphemeSegmenter
|
|
44
46
|
} from "./chunk-ZJCAQXA7.js";
|
|
45
47
|
import "./chunk-S32JRDZK.js";
|
|
46
48
|
|
|
@@ -969,7 +971,13 @@ function wrapPromptInput(input, codePointCursor, options) {
|
|
|
969
971
|
// src/ui/task-progress.tsx
|
|
970
972
|
import { useRef as useRef3 } from "react";
|
|
971
973
|
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
972
|
-
function TaskStatusLine({
|
|
974
|
+
function TaskStatusLine({
|
|
975
|
+
block,
|
|
976
|
+
interactive,
|
|
977
|
+
textWidth,
|
|
978
|
+
maxTextLines,
|
|
979
|
+
showRoleBadge = true
|
|
980
|
+
}) {
|
|
973
981
|
const running = block.state === "running";
|
|
974
982
|
const { stdout } = useStdout();
|
|
975
983
|
const foreground = interactive && (block.activity === "model" || block.task?.role === "main");
|
|
@@ -982,6 +990,8 @@ function TaskStatusLine({ block, interactive }) {
|
|
|
982
990
|
const elapsed = block.startedAt === void 0 ? startedAt.current === void 0 ? 0 : Math.max(0, time - startedAt.current) : Math.max(0, Date.now() - block.startedAt);
|
|
983
991
|
const presentation = statusPresentation(block, elapsed, foreground);
|
|
984
992
|
const { metaColor, metaLabel, statusLabel, statusColor, text } = presentation;
|
|
993
|
+
const badge = showRoleBadge ? presentation.badge : void 0;
|
|
994
|
+
const badgeColor = presentation.badgeColor;
|
|
985
995
|
let before = text;
|
|
986
996
|
let after = "";
|
|
987
997
|
if (statusLabel !== void 0) {
|
|
@@ -1007,14 +1017,26 @@ function TaskStatusLine({ block, interactive }) {
|
|
|
1007
1017
|
thinkingScroll.current = { start: state.start, lastTime: time };
|
|
1008
1018
|
return state.text;
|
|
1009
1019
|
})() : void 0;
|
|
1020
|
+
const textSegments = [
|
|
1021
|
+
{ text: `${presentation.glyph} `, color: presentation.color },
|
|
1022
|
+
...badge ? [{ text: `${badge} `, color: badgeColor }] : [],
|
|
1023
|
+
{ text: before, color: presentation.color },
|
|
1024
|
+
...statusLabel === void 0 ? [] : [
|
|
1025
|
+
{ text: " \xB7 ", color: presentation.color },
|
|
1026
|
+
{ text: statusLabel, color: statusColor ?? presentation.color }
|
|
1027
|
+
],
|
|
1028
|
+
...after ? [{ text: after, color: presentation.color }] : [],
|
|
1029
|
+
...metaLabel === void 0 ? [] : [{ text: ` ${metaLabel}`, color: metaColor ?? "ansi:blackBright" }]
|
|
1030
|
+
];
|
|
1031
|
+
const boundedText = textWidth === void 0 || maxTextLines === void 0 ? void 0 : limitTaskTextSegments(textSegments, textWidth, maxTextLines).segments;
|
|
1010
1032
|
return /* @__PURE__ */ jsxs2(Box_default, { flexDirection: "column", width: "100%", children: [
|
|
1011
|
-
/* @__PURE__ */
|
|
1033
|
+
/* @__PURE__ */ jsx3(Box_default, { ref, flexDirection: "row", width: "100%", children: boundedText === void 0 ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1012
1034
|
/* @__PURE__ */ jsxs2(Text, { ...presentation.color === void 0 ? {} : { color: presentation.color }, children: [
|
|
1013
1035
|
presentation.glyph,
|
|
1014
1036
|
" "
|
|
1015
1037
|
] }),
|
|
1016
|
-
|
|
1017
|
-
|
|
1038
|
+
badge ? /* @__PURE__ */ jsxs2(Text, { color: badgeColor, children: [
|
|
1039
|
+
badge,
|
|
1018
1040
|
" "
|
|
1019
1041
|
] }) : null,
|
|
1020
1042
|
/* @__PURE__ */ jsx3(Text, { ...presentation.color === void 0 ? {} : { color: presentation.color }, children: before }),
|
|
@@ -1027,10 +1049,69 @@ function TaskStatusLine({ block, interactive }) {
|
|
|
1027
1049
|
" ",
|
|
1028
1050
|
metaLabel
|
|
1029
1051
|
] })
|
|
1030
|
-
] }),
|
|
1052
|
+
] }) : /* @__PURE__ */ jsx3(Text, { children: boundedText.map((segment, index) => /* @__PURE__ */ jsx3(Text, { ...segment.color === void 0 ? {} : { color: segment.color }, children: segment.text }, index)) }) }),
|
|
1031
1053
|
thinkingLine === void 0 ? null : /* @__PURE__ */ jsx3(ThinkingLineView, { text: thinkingLine })
|
|
1032
1054
|
] });
|
|
1033
1055
|
}
|
|
1056
|
+
function limitTaskTextSegments(segments, width, maxLines = 3) {
|
|
1057
|
+
const lineWidth = Math.max(3, Math.floor(width));
|
|
1058
|
+
const lineLimit = Math.max(1, Math.floor(maxLines));
|
|
1059
|
+
const lines = [[]];
|
|
1060
|
+
const widths = [0];
|
|
1061
|
+
let truncated = false;
|
|
1062
|
+
outer: for (let segmentIndex = 0; segmentIndex < segments.length; segmentIndex += 1) {
|
|
1063
|
+
const segment = segments[segmentIndex];
|
|
1064
|
+
for (const { segment: grapheme } of getGraphemeSegmenter().segment(segment.text)) {
|
|
1065
|
+
if (grapheme === "\n" || grapheme === "\r" || grapheme === "\r\n") {
|
|
1066
|
+
if (lines.length >= lineLimit) {
|
|
1067
|
+
truncated = true;
|
|
1068
|
+
break outer;
|
|
1069
|
+
}
|
|
1070
|
+
lines.push([]);
|
|
1071
|
+
widths.push(0);
|
|
1072
|
+
continue;
|
|
1073
|
+
}
|
|
1074
|
+
const glyphWidth = stringWidth(grapheme);
|
|
1075
|
+
const lineIndex = lines.length - 1;
|
|
1076
|
+
if (glyphWidth > 0 && widths[lineIndex] + glyphWidth > lineWidth && lines[lineIndex].length > 0) {
|
|
1077
|
+
if (lines.length >= lineLimit) {
|
|
1078
|
+
truncated = true;
|
|
1079
|
+
break outer;
|
|
1080
|
+
}
|
|
1081
|
+
lines.push([]);
|
|
1082
|
+
widths.push(0);
|
|
1083
|
+
}
|
|
1084
|
+
const target = lines.length - 1;
|
|
1085
|
+
lines[target].push({ value: grapheme, width: glyphWidth, segmentIndex });
|
|
1086
|
+
widths[target] = widths[target] + glyphWidth;
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
if (truncated) {
|
|
1090
|
+
const lastIndex = lines.length - 1;
|
|
1091
|
+
const last = lines[lastIndex];
|
|
1092
|
+
while (last.length > 0 && widths[lastIndex] > lineWidth - 3) {
|
|
1093
|
+
widths[lastIndex] = widths[lastIndex] - last.pop().width;
|
|
1094
|
+
}
|
|
1095
|
+
while (last.length > 0 && /^\s$/u.test(last.at(-1).value)) {
|
|
1096
|
+
widths[lastIndex] = widths[lastIndex] - last.pop().width;
|
|
1097
|
+
}
|
|
1098
|
+
last.push({ value: "...", width: 3, segmentIndex: last.at(-1)?.segmentIndex ?? 0 });
|
|
1099
|
+
}
|
|
1100
|
+
const output = [];
|
|
1101
|
+
const append = (value, segmentIndex) => {
|
|
1102
|
+
const previous = output.at(-1);
|
|
1103
|
+
if (previous?.segmentIndex === segmentIndex) previous.text += value;
|
|
1104
|
+
else output.push({ text: value, color: segments[segmentIndex]?.color, segmentIndex });
|
|
1105
|
+
};
|
|
1106
|
+
lines.forEach((line, lineIndex) => {
|
|
1107
|
+
if (lineIndex > 0) append("\n", line[0]?.segmentIndex ?? output.at(-1)?.segmentIndex ?? 0);
|
|
1108
|
+
for (const token of line) append(token.value, token.segmentIndex);
|
|
1109
|
+
});
|
|
1110
|
+
return {
|
|
1111
|
+
truncated,
|
|
1112
|
+
segments: output.map(({ text, color }) => ({ text, ...color === void 0 ? {} : { color } }))
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1034
1115
|
var THINKING_RAIL = "#416f84";
|
|
1035
1116
|
var THINKING_TEXT = "#91a0a8";
|
|
1036
1117
|
function ThinkingLineView({ text }) {
|
|
@@ -1039,13 +1120,16 @@ function ThinkingLineView({ text }) {
|
|
|
1039
1120
|
/* @__PURE__ */ jsx3(Text, { color: THINKING_TEXT, wrap: "truncate-end", children: text })
|
|
1040
1121
|
] });
|
|
1041
1122
|
}
|
|
1042
|
-
var SPLIT_TRACK_MIN_COLUMNS =
|
|
1123
|
+
var SPLIT_TRACK_MIN_COLUMNS = 96;
|
|
1124
|
+
var SPLIT_TRACK_GUTTER_COLUMNS = 3;
|
|
1125
|
+
var SPLIT_TRACK_MAIN_RATIO = 0.44;
|
|
1043
1126
|
function TaskProgressPanel({
|
|
1044
1127
|
blocks,
|
|
1045
1128
|
interactive,
|
|
1046
1129
|
maxHeight = 8,
|
|
1047
1130
|
columns = 80,
|
|
1048
|
-
|
|
1131
|
+
mainScrollRef,
|
|
1132
|
+
subagentScrollRef,
|
|
1049
1133
|
onHoverChange
|
|
1050
1134
|
}) {
|
|
1051
1135
|
if (blocks.length === 0 || maxHeight <= 0) return null;
|
|
@@ -1054,54 +1138,210 @@ function TaskProgressPanel({
|
|
|
1054
1138
|
const hasTasks = taskBlocks.length > 0;
|
|
1055
1139
|
const hasSubagents = subagentBlocks.length > 0;
|
|
1056
1140
|
const split = hasTasks && hasSubagents && columns >= SPLIT_TRACK_MIN_COLUMNS;
|
|
1057
|
-
|
|
1141
|
+
const hoverProps = (track) => ({
|
|
1142
|
+
onMouseEnter: () => onHoverChange?.(track)
|
|
1143
|
+
});
|
|
1144
|
+
return /* @__PURE__ */ jsx3(
|
|
1058
1145
|
Box_default,
|
|
1059
1146
|
{
|
|
1060
1147
|
flexDirection: "column",
|
|
1061
1148
|
flexShrink: 0,
|
|
1062
1149
|
width: "100%",
|
|
1063
1150
|
maxHeight,
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1151
|
+
onMouseLeave: () => onHoverChange?.(null),
|
|
1152
|
+
children: split ? /* @__PURE__ */ jsx3(
|
|
1153
|
+
SplitTracks,
|
|
1154
|
+
{
|
|
1155
|
+
taskBlocks,
|
|
1156
|
+
subagentBlocks,
|
|
1157
|
+
interactive,
|
|
1158
|
+
height: maxHeight,
|
|
1159
|
+
columns,
|
|
1160
|
+
mainScrollRef,
|
|
1161
|
+
subagentScrollRef,
|
|
1162
|
+
hoverProps
|
|
1163
|
+
}
|
|
1164
|
+
) : hasTasks && hasSubagents ? /* @__PURE__ */ jsx3(
|
|
1165
|
+
StackedTracks,
|
|
1166
|
+
{
|
|
1167
|
+
taskBlocks,
|
|
1168
|
+
subagentBlocks,
|
|
1169
|
+
interactive,
|
|
1170
|
+
height: maxHeight,
|
|
1171
|
+
columns,
|
|
1172
|
+
mainScrollRef,
|
|
1173
|
+
subagentScrollRef,
|
|
1174
|
+
hoverProps
|
|
1175
|
+
}
|
|
1176
|
+
) : /* @__PURE__ */ jsx3(
|
|
1177
|
+
SingleTrack,
|
|
1178
|
+
{
|
|
1179
|
+
role: hasTasks ? "main" : "subagent",
|
|
1180
|
+
blocks: hasTasks ? taskBlocks : subagentBlocks,
|
|
1181
|
+
interactive,
|
|
1182
|
+
height: maxHeight,
|
|
1183
|
+
width: columns,
|
|
1184
|
+
scrollRef: hasTasks ? mainScrollRef : subagentScrollRef,
|
|
1185
|
+
hoverProps
|
|
1186
|
+
}
|
|
1187
|
+
)
|
|
1087
1188
|
}
|
|
1088
1189
|
);
|
|
1089
1190
|
}
|
|
1090
|
-
function
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1191
|
+
function SplitTracks({
|
|
1192
|
+
taskBlocks,
|
|
1193
|
+
subagentBlocks,
|
|
1194
|
+
interactive,
|
|
1195
|
+
height,
|
|
1196
|
+
columns,
|
|
1197
|
+
mainScrollRef,
|
|
1198
|
+
subagentScrollRef,
|
|
1199
|
+
hoverProps
|
|
1200
|
+
}) {
|
|
1201
|
+
const contentHeight = Math.max(0, height - 1);
|
|
1202
|
+
const availableWidth = columns - SPLIT_TRACK_GUTTER_COLUMNS;
|
|
1203
|
+
const leftWidth = Math.max(1, Math.floor(availableWidth * SPLIT_TRACK_MAIN_RATIO));
|
|
1204
|
+
const rightWidth = Math.max(1, availableWidth - leftWidth);
|
|
1205
|
+
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1206
|
+
/* @__PURE__ */ jsxs2(Box_default, { flexDirection: "row", width: "100%", children: [
|
|
1207
|
+
/* @__PURE__ */ jsx3(Box_default, { width: leftWidth, ...hoverProps("main"), children: /* @__PURE__ */ jsx3(TrackHeader, { role: "main", count: taskBlocks.length, width: leftWidth }) }),
|
|
1208
|
+
/* @__PURE__ */ jsx3(Text, { color: "ansi:white", children: "\u2500\u252C\u2500" }),
|
|
1209
|
+
/* @__PURE__ */ jsx3(Box_default, { width: rightWidth, ...hoverProps("subagent"), children: /* @__PURE__ */ jsx3(TrackHeader, { role: "subagent", count: subagentBlocks.length, width: rightWidth }) })
|
|
1210
|
+
] }),
|
|
1211
|
+
contentHeight <= 0 ? null : /* @__PURE__ */ jsxs2(Box_default, { flexDirection: "row", width: "100%", height: contentHeight, children: [
|
|
1212
|
+
/* @__PURE__ */ jsx3(Box_default, { width: leftWidth, minWidth: 0, flexDirection: "column", ...hoverProps("main"), children: /* @__PURE__ */ jsx3(
|
|
1213
|
+
TrackScrollBox,
|
|
1214
|
+
{
|
|
1215
|
+
ref: mainScrollRef,
|
|
1216
|
+
blocks: taskBlocks,
|
|
1217
|
+
interactive,
|
|
1218
|
+
height: contentHeight,
|
|
1219
|
+
width: leftWidth,
|
|
1220
|
+
maxTextLines: 2
|
|
1221
|
+
}
|
|
1222
|
+
) }),
|
|
1223
|
+
/* @__PURE__ */ jsx3(TrackDivider, { height: contentHeight }),
|
|
1224
|
+
/* @__PURE__ */ jsx3(Box_default, { width: rightWidth, minWidth: 0, flexDirection: "column", ...hoverProps("subagent"), children: /* @__PURE__ */ jsx3(
|
|
1225
|
+
TrackScrollBox,
|
|
1226
|
+
{
|
|
1227
|
+
ref: subagentScrollRef,
|
|
1228
|
+
blocks: subagentBlocks,
|
|
1229
|
+
interactive,
|
|
1230
|
+
height: contentHeight,
|
|
1231
|
+
width: rightWidth,
|
|
1232
|
+
maxTextLines: 2
|
|
1233
|
+
}
|
|
1234
|
+
) })
|
|
1235
|
+
] })
|
|
1095
1236
|
] });
|
|
1096
1237
|
}
|
|
1097
|
-
function
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1238
|
+
function StackedTracks({
|
|
1239
|
+
taskBlocks,
|
|
1240
|
+
subagentBlocks,
|
|
1241
|
+
interactive,
|
|
1242
|
+
height,
|
|
1243
|
+
columns,
|
|
1244
|
+
mainScrollRef,
|
|
1245
|
+
subagentScrollRef,
|
|
1246
|
+
hoverProps
|
|
1247
|
+
}) {
|
|
1248
|
+
if (height <= 1) {
|
|
1249
|
+
return /* @__PURE__ */ jsx3(Box_default, { ...hoverProps("main"), children: /* @__PURE__ */ jsx3(TrackHeader, { role: "main", count: taskBlocks.length, width: columns }) });
|
|
1250
|
+
}
|
|
1251
|
+
const mainHeight = Math.ceil(height / 2);
|
|
1252
|
+
const subagentHeight = Math.floor(height / 2);
|
|
1253
|
+
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1254
|
+
/* @__PURE__ */ jsx3(
|
|
1255
|
+
SingleTrack,
|
|
1256
|
+
{
|
|
1257
|
+
role: "main",
|
|
1258
|
+
blocks: taskBlocks,
|
|
1259
|
+
interactive,
|
|
1260
|
+
height: mainHeight,
|
|
1261
|
+
width: columns,
|
|
1262
|
+
scrollRef: mainScrollRef,
|
|
1263
|
+
hoverProps
|
|
1264
|
+
}
|
|
1265
|
+
),
|
|
1266
|
+
/* @__PURE__ */ jsx3(
|
|
1267
|
+
SingleTrack,
|
|
1268
|
+
{
|
|
1269
|
+
role: "subagent",
|
|
1270
|
+
blocks: subagentBlocks,
|
|
1271
|
+
interactive,
|
|
1272
|
+
height: subagentHeight,
|
|
1273
|
+
width: columns,
|
|
1274
|
+
scrollRef: subagentScrollRef,
|
|
1275
|
+
hoverProps
|
|
1276
|
+
}
|
|
1277
|
+
)
|
|
1278
|
+
] });
|
|
1279
|
+
}
|
|
1280
|
+
function SingleTrack({
|
|
1281
|
+
role,
|
|
1282
|
+
blocks,
|
|
1283
|
+
interactive,
|
|
1284
|
+
height,
|
|
1285
|
+
width,
|
|
1286
|
+
scrollRef,
|
|
1287
|
+
hoverProps
|
|
1288
|
+
}) {
|
|
1289
|
+
const contentHeight = Math.max(0, height - 1);
|
|
1290
|
+
return /* @__PURE__ */ jsxs2(Box_default, { flexDirection: "column", width: "100%", height, ...hoverProps(role), children: [
|
|
1291
|
+
/* @__PURE__ */ jsx3(TrackHeader, { role, count: blocks.length, width }),
|
|
1292
|
+
contentHeight <= 0 ? null : /* @__PURE__ */ jsx3(
|
|
1293
|
+
TrackScrollBox,
|
|
1294
|
+
{
|
|
1295
|
+
ref: scrollRef,
|
|
1296
|
+
blocks,
|
|
1297
|
+
interactive,
|
|
1298
|
+
height: contentHeight,
|
|
1299
|
+
width,
|
|
1300
|
+
maxTextLines: 3
|
|
1301
|
+
}
|
|
1302
|
+
)
|
|
1101
1303
|
] });
|
|
1102
1304
|
}
|
|
1103
|
-
function
|
|
1104
|
-
|
|
1305
|
+
function TrackScrollBox({
|
|
1306
|
+
ref,
|
|
1307
|
+
blocks,
|
|
1308
|
+
interactive,
|
|
1309
|
+
height,
|
|
1310
|
+
width,
|
|
1311
|
+
maxTextLines
|
|
1312
|
+
}) {
|
|
1313
|
+
return /* @__PURE__ */ jsx3(
|
|
1314
|
+
ScrollBox_default,
|
|
1315
|
+
{
|
|
1316
|
+
...ref === void 0 ? {} : { ref },
|
|
1317
|
+
flexDirection: "column",
|
|
1318
|
+
flexShrink: 1,
|
|
1319
|
+
width: "100%",
|
|
1320
|
+
height,
|
|
1321
|
+
maxHeight: height,
|
|
1322
|
+
paddingX: 1,
|
|
1323
|
+
children: blocks.map((block) => /* @__PURE__ */ jsx3(
|
|
1324
|
+
TaskStatusLine,
|
|
1325
|
+
{
|
|
1326
|
+
block,
|
|
1327
|
+
interactive,
|
|
1328
|
+
textWidth: Math.max(3, width - 2),
|
|
1329
|
+
maxTextLines,
|
|
1330
|
+
showRoleBadge: false
|
|
1331
|
+
},
|
|
1332
|
+
block.id
|
|
1333
|
+
))
|
|
1334
|
+
}
|
|
1335
|
+
);
|
|
1336
|
+
}
|
|
1337
|
+
function TrackHeader({ role, count, width }) {
|
|
1338
|
+
const label = role === "main" ? `task plan (${count})` : `subagents (${count})`;
|
|
1339
|
+
const prefix = `\u2500\u2500 ${label} `;
|
|
1340
|
+
const line = prefix.length >= width ? prefix.slice(0, Math.max(0, width)) : `${prefix}${"\u2500".repeat(width - prefix.length)}`;
|
|
1341
|
+
return /* @__PURE__ */ jsx3(Text, { color: "ansi:white", wrap: "truncate-end", children: line });
|
|
1342
|
+
}
|
|
1343
|
+
function TrackDivider({ height }) {
|
|
1344
|
+
return /* @__PURE__ */ jsx3(Box_default, { flexDirection: "column", width: SPLIT_TRACK_GUTTER_COLUMNS, flexShrink: 0, children: Array.from({ length: height }, (_, index) => /* @__PURE__ */ jsx3(Text, { color: "ansi:white", children: " \u2502 " }, index)) });
|
|
1105
1345
|
}
|
|
1106
1346
|
|
|
1107
1347
|
// src/ui/file-diff-style.ts
|
|
@@ -1117,6 +1357,12 @@ function fileDiffLineStyle(kind) {
|
|
|
1117
1357
|
}
|
|
1118
1358
|
|
|
1119
1359
|
// src/ui/slash-completion.ts
|
|
1360
|
+
var CANDIDATE_KIND_PRIORITY = {
|
|
1361
|
+
skill: 0,
|
|
1362
|
+
plugin: 0,
|
|
1363
|
+
command: 1,
|
|
1364
|
+
tool: 2
|
|
1365
|
+
};
|
|
1120
1366
|
function slashCandidatePresentation(selected) {
|
|
1121
1367
|
return {
|
|
1122
1368
|
marker: selected ? "\u203A " : " ",
|
|
@@ -1177,6 +1423,8 @@ function deriveSlashCompletion(input, cursor, candidates, selectedIndex, visible
|
|
|
1177
1423
|
const leftPrefix = left.name.toLowerCase().startsWith(normalized);
|
|
1178
1424
|
const rightPrefix = right.name.toLowerCase().startsWith(normalized);
|
|
1179
1425
|
if (leftPrefix !== rightPrefix) return leftPrefix ? -1 : 1;
|
|
1426
|
+
const kindPriority = CANDIDATE_KIND_PRIORITY[left.kind] - CANDIDATE_KIND_PRIORITY[right.kind];
|
|
1427
|
+
if (kindPriority !== 0) return kindPriority;
|
|
1180
1428
|
return left.name.localeCompare(right.name);
|
|
1181
1429
|
});
|
|
1182
1430
|
if (items.length === 0) return null;
|
|
@@ -1656,21 +1904,63 @@ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-run
|
|
|
1656
1904
|
var HISTORY_CAP = 200;
|
|
1657
1905
|
var BUILTIN_SLASH_CANDIDATES = MVP_COMMANDS.map((name) => ({ name, description: COMMAND_DESCRIPTIONS[name] }));
|
|
1658
1906
|
var PROMPT_HORIZONTAL_PADDING = 1;
|
|
1907
|
+
function clonePromptDraft(state) {
|
|
1908
|
+
return {
|
|
1909
|
+
...state,
|
|
1910
|
+
pastedBlocks: [...state.pastedBlocks],
|
|
1911
|
+
imageAttachments: [...state.imageAttachments]
|
|
1912
|
+
};
|
|
1913
|
+
}
|
|
1914
|
+
var PromptEditHistory = class {
|
|
1915
|
+
constructor(limit = 100) {
|
|
1916
|
+
this.limit = limit;
|
|
1917
|
+
}
|
|
1918
|
+
limit;
|
|
1919
|
+
#undo = [];
|
|
1920
|
+
#redo = [];
|
|
1921
|
+
record(previous, next) {
|
|
1922
|
+
if (previous.text === next.text && previous.pastedBlocks === next.pastedBlocks && previous.imageAttachments === next.imageAttachments) return;
|
|
1923
|
+
this.#undo.push(clonePromptDraft(previous));
|
|
1924
|
+
if (this.#undo.length > this.limit) this.#undo.shift();
|
|
1925
|
+
this.#redo.length = 0;
|
|
1926
|
+
}
|
|
1927
|
+
undo(current) {
|
|
1928
|
+
const previous = this.#undo.pop();
|
|
1929
|
+
if (previous === void 0) return void 0;
|
|
1930
|
+
this.#redo.push(clonePromptDraft(current));
|
|
1931
|
+
return clonePromptDraft(previous);
|
|
1932
|
+
}
|
|
1933
|
+
redo(current) {
|
|
1934
|
+
const next = this.#redo.pop();
|
|
1935
|
+
if (next === void 0) return void 0;
|
|
1936
|
+
this.#undo.push(clonePromptDraft(current));
|
|
1937
|
+
return clonePromptDraft(next);
|
|
1938
|
+
}
|
|
1939
|
+
reset() {
|
|
1940
|
+
this.#undo.length = 0;
|
|
1941
|
+
this.#redo.length = 0;
|
|
1942
|
+
}
|
|
1943
|
+
};
|
|
1944
|
+
function promptHistoryAction(character, key, platform = process.platform) {
|
|
1945
|
+
const modifier = platform === "darwin" ? key.super : key.ctrl;
|
|
1946
|
+
if (!modifier || character.toLowerCase() !== "z") return null;
|
|
1947
|
+
return key.shift ? "redo" : "undo";
|
|
1948
|
+
}
|
|
1949
|
+
function isCopyShortcut(character, key, platform = process.platform) {
|
|
1950
|
+
return character.toLowerCase() === "c" && (platform === "darwin" ? key.super : key.ctrl);
|
|
1951
|
+
}
|
|
1659
1952
|
function removeLastCliImageOnBackspace(input, cursor, images) {
|
|
1660
1953
|
if (input.length === 0 && cursor === 0 && images.length > 0) {
|
|
1661
1954
|
return { handled: true, images: images.slice(0, -1) };
|
|
1662
1955
|
}
|
|
1663
1956
|
return { handled: false, images: [...images] };
|
|
1664
1957
|
}
|
|
1665
|
-
function prepareCliSubmission(input, images
|
|
1958
|
+
function prepareCliSubmission(input, images) {
|
|
1666
1959
|
const entered = input.trim();
|
|
1667
1960
|
if (entered.length === 0 && images.length === 0) return { kind: "empty" };
|
|
1668
1961
|
if (images.length > 0 && entered.startsWith("/")) {
|
|
1669
1962
|
return { kind: "error", message: "Image attachments cannot be used with slash commands." };
|
|
1670
1963
|
}
|
|
1671
|
-
if (images.length > 0 && activeSession) {
|
|
1672
|
-
return { kind: "error", message: "Images can only be attached to a new prompt." };
|
|
1673
|
-
}
|
|
1674
1964
|
const text = entered || "Analyze the attached image(s).";
|
|
1675
1965
|
if (images.length === 0) return { kind: "ready", text, displayText: text };
|
|
1676
1966
|
const content = [{ type: "text", text }, ...images];
|
|
@@ -1694,45 +1984,91 @@ function resolvePromptDelivery(activeSession, key, input) {
|
|
|
1694
1984
|
}
|
|
1695
1985
|
return { delivery: promptDelivery(activeSession, key), prompt: input };
|
|
1696
1986
|
}
|
|
1697
|
-
|
|
1698
|
-
|
|
1987
|
+
function cloneQueuedPrompt(prompt) {
|
|
1988
|
+
return {
|
|
1989
|
+
text: prompt.text,
|
|
1990
|
+
displayText: prompt.displayText,
|
|
1991
|
+
...prompt.content === void 0 ? {} : { content: [...prompt.content] }
|
|
1992
|
+
};
|
|
1993
|
+
}
|
|
1994
|
+
function normalizeQueuedPrompt(prompt) {
|
|
1995
|
+
if (typeof prompt === "string") {
|
|
1996
|
+
const text2 = prompt.trim();
|
|
1997
|
+
return text2.length === 0 ? void 0 : { text: text2, displayText: text2 };
|
|
1998
|
+
}
|
|
1999
|
+
const text = prompt.text.trim();
|
|
2000
|
+
if (text.length === 0) return void 0;
|
|
2001
|
+
const displayText = prompt.displayText.trim() || text;
|
|
2002
|
+
return cloneQueuedPrompt({
|
|
2003
|
+
text,
|
|
2004
|
+
displayText,
|
|
2005
|
+
...prompt.content === void 0 ? {} : { content: prompt.content }
|
|
2006
|
+
});
|
|
2007
|
+
}
|
|
2008
|
+
function queuedPromptLabel(prompt) {
|
|
2009
|
+
const imageCount = prompt.content?.filter((block) => block.type === "image").length ?? 0;
|
|
2010
|
+
const text = prompt.text.replace(/\s+/gu, " ").trim();
|
|
2011
|
+
if (imageCount === 0) return text;
|
|
2012
|
+
return `${text} \xB7 ${imageCount} ${imageCount === 1 ? "image" : "images"}`;
|
|
2013
|
+
}
|
|
2014
|
+
function restoreQueuedPrompt(prompt) {
|
|
2015
|
+
const imageAttachments = prompt.content?.filter(
|
|
2016
|
+
(block) => block.type === "image"
|
|
2017
|
+
) ?? [];
|
|
2018
|
+
return {
|
|
2019
|
+
text: prompt.text,
|
|
2020
|
+
cursor: [...prompt.text].length,
|
|
2021
|
+
pastedBlocks: [],
|
|
2022
|
+
imageAttachments
|
|
2023
|
+
};
|
|
2024
|
+
}
|
|
2025
|
+
var PendingPromptQueue = class {
|
|
2026
|
+
#values = [];
|
|
1699
2027
|
get value() {
|
|
1700
|
-
|
|
2028
|
+
const value = this.#values.at(-1);
|
|
2029
|
+
return value === void 0 ? void 0 : cloneQueuedPrompt(value);
|
|
2030
|
+
}
|
|
2031
|
+
get values() {
|
|
2032
|
+
return this.#values.map(cloneQueuedPrompt);
|
|
2033
|
+
}
|
|
2034
|
+
get size() {
|
|
2035
|
+
return this.#values.length;
|
|
1701
2036
|
}
|
|
1702
2037
|
queue(prompt) {
|
|
1703
|
-
const value = prompt
|
|
1704
|
-
if (value
|
|
1705
|
-
this.#value
|
|
2038
|
+
const value = normalizeQueuedPrompt(prompt);
|
|
2039
|
+
if (value === void 0) return false;
|
|
2040
|
+
this.#values.push(value);
|
|
1706
2041
|
return true;
|
|
1707
2042
|
}
|
|
1708
2043
|
cancel() {
|
|
1709
|
-
const value = this.#
|
|
1710
|
-
|
|
1711
|
-
return value;
|
|
2044
|
+
const value = this.#values.pop();
|
|
2045
|
+
return value === void 0 ? void 0 : cloneQueuedPrompt(value);
|
|
1712
2046
|
}
|
|
1713
2047
|
take() {
|
|
1714
|
-
|
|
2048
|
+
const value = this.#values.shift();
|
|
2049
|
+
return value === void 0 ? void 0 : cloneQueuedPrompt(value);
|
|
1715
2050
|
}
|
|
1716
2051
|
};
|
|
1717
2052
|
async function runTerminalSubmissionChain(options) {
|
|
1718
|
-
let prompt =
|
|
1719
|
-
|
|
2053
|
+
let prompt = normalizeQueuedPrompt({
|
|
2054
|
+
text: options.initialPrompt,
|
|
2055
|
+
displayText: options.initialDisplayPrompt ?? options.initialPrompt,
|
|
2056
|
+
...options.initialContent === void 0 ? {} : { content: options.initialContent }
|
|
2057
|
+
});
|
|
1720
2058
|
while (prompt !== void 0) {
|
|
1721
|
-
options.onStart(
|
|
1722
|
-
if (
|
|
2059
|
+
options.onStart(prompt.displayText);
|
|
2060
|
+
if (prompt.content === void 0) await submitSafely(options.session, prompt.text, options.report);
|
|
2061
|
+
else {
|
|
1723
2062
|
try {
|
|
1724
|
-
await options.
|
|
2063
|
+
await options.session.submit({ text: prompt.text, content: prompt.content });
|
|
1725
2064
|
} catch (error) {
|
|
1726
2065
|
safeReport(options.report, safeUiError(error));
|
|
1727
2066
|
}
|
|
1728
|
-
} else {
|
|
1729
|
-
await submitSafely(options.session, prompt, options.report);
|
|
1730
2067
|
}
|
|
1731
2068
|
options.onFinish();
|
|
1732
2069
|
if (options.shouldContinue?.() === false) return;
|
|
1733
2070
|
prompt = options.pending.take();
|
|
1734
|
-
if (prompt !== void 0) options.onPendingConsumed();
|
|
1735
|
-
initial = false;
|
|
2071
|
+
if (prompt !== void 0) options.onPendingConsumed(options.pending.values);
|
|
1736
2072
|
}
|
|
1737
2073
|
}
|
|
1738
2074
|
function classifyTerminalInput(key) {
|
|
@@ -1755,6 +2091,9 @@ function completionKeyAction(key, menuOpen) {
|
|
|
1755
2091
|
function slashKeyAction(key, completion) {
|
|
1756
2092
|
return completionKeyAction(key, completion !== null);
|
|
1757
2093
|
}
|
|
2094
|
+
function canShowSlashCompletion(_activeSession, input, dismissedInput, blockedByModal) {
|
|
2095
|
+
return dismissedInput !== input && !blockedByModal;
|
|
2096
|
+
}
|
|
1758
2097
|
function appRuntimeOptions(props, output, onApprovalChange) {
|
|
1759
2098
|
return {
|
|
1760
2099
|
workspace: props.workspace,
|
|
@@ -1788,7 +2127,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1788
2127
|
const [mentionCandidates, setMentionCandidates] = useState2([]);
|
|
1789
2128
|
const [mentionSelection, setMentionSelection] = useState2(0);
|
|
1790
2129
|
const [dismissedMentionInput, setDismissedMentionInput] = useState2();
|
|
1791
|
-
const [
|
|
2130
|
+
const [pendingPrompts, setPendingPrompts] = useState2([]);
|
|
1792
2131
|
const [revision, setRevision] = useState2(0);
|
|
1793
2132
|
const [ideContext, setIdeContext] = useState2();
|
|
1794
2133
|
const [questionIndex, setQuestionIndex] = useState2(0);
|
|
@@ -1799,11 +2138,12 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1799
2138
|
const [updateTo, setUpdateTo] = useState2();
|
|
1800
2139
|
const [transcript, dispatch] = useReducer(transcriptReducer, void 0, createTranscriptState);
|
|
1801
2140
|
const scrollRef = useRef4(null);
|
|
1802
|
-
const
|
|
1803
|
-
const
|
|
2141
|
+
const mainTaskScrollRef = useRef4(null);
|
|
2142
|
+
const subagentTaskScrollRef = useRef4(null);
|
|
2143
|
+
const hoveredTaskTrack = useRef4(null);
|
|
1804
2144
|
const runtimeRef = useRef4(void 0);
|
|
1805
2145
|
const pendingPromptRef = useRef4(void 0);
|
|
1806
|
-
pendingPromptRef.current ??= new
|
|
2146
|
+
pendingPromptRef.current ??= new PendingPromptQueue();
|
|
1807
2147
|
const closing = useRef4(false);
|
|
1808
2148
|
const clipboardBusy = useRef4(false);
|
|
1809
2149
|
const textBuf = useRef4({ pending: "", timer: null });
|
|
@@ -1814,8 +2154,9 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1814
2154
|
pastedBlocks,
|
|
1815
2155
|
imageAttachments
|
|
1816
2156
|
});
|
|
2157
|
+
const promptEditHistory = useRef4(new PromptEditHistory());
|
|
1817
2158
|
promptDraftRef.current = { text: input, cursor: promptCursor, pastedBlocks, imageAttachments };
|
|
1818
|
-
const commitPromptDraft = (next) => {
|
|
2159
|
+
const commitPromptDraft = (next, recordHistory = true) => {
|
|
1819
2160
|
const current = promptDraftRef.current;
|
|
1820
2161
|
const resolved = {
|
|
1821
2162
|
text: next.text,
|
|
@@ -1823,6 +2164,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1823
2164
|
pastedBlocks: next.pastedBlocks ?? current.pastedBlocks,
|
|
1824
2165
|
imageAttachments: next.imageAttachments ?? current.imageAttachments
|
|
1825
2166
|
};
|
|
2167
|
+
if (recordHistory) promptEditHistory.current.record(current, resolved);
|
|
1826
2168
|
promptDraftRef.current = resolved;
|
|
1827
2169
|
setInput(resolved.text);
|
|
1828
2170
|
setPromptCursor(resolved.cursor);
|
|
@@ -2044,7 +2386,12 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2044
2386
|
setCustomQuestionActive(false);
|
|
2045
2387
|
}, [questions]);
|
|
2046
2388
|
const derivedSlashCompletion = deriveSlashCompletion(input, promptCursor, slashCandidates, slashSelection);
|
|
2047
|
-
const slashCompletion =
|
|
2389
|
+
const slashCompletion = canShowSlashCompletion(
|
|
2390
|
+
transcript.active !== void 0,
|
|
2391
|
+
input,
|
|
2392
|
+
dismissedSlashInput,
|
|
2393
|
+
approval !== void 0 || questions !== void 0
|
|
2394
|
+
) ? derivedSlashCompletion : null;
|
|
2048
2395
|
const derivedMentionCompletion = slashCompletion === null ? deriveMentionCompletion(input, promptCursor, mentionCandidates, mentionSelection) : null;
|
|
2049
2396
|
const mentionCompletion = dismissedMentionInput === input || transcript.active !== void 0 || approval !== void 0 || questions !== void 0 ? null : derivedMentionCompletion;
|
|
2050
2397
|
const completedTokenLength = completedSlashTokenLength(input, slashCandidates, slashCompletion !== null);
|
|
@@ -2062,11 +2409,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2062
2409
|
setClipboardNotice("Flavor is still starting; try pasting the image again.");
|
|
2063
2410
|
return;
|
|
2064
2411
|
}
|
|
2065
|
-
if (
|
|
2066
|
-
setClipboardNotice("Images can only be attached to a new prompt.");
|
|
2067
|
-
return;
|
|
2068
|
-
}
|
|
2069
|
-
if (imageAttachments.length >= DEFAULT_MAX_IMAGES) {
|
|
2412
|
+
if (promptDraftRef.current.imageAttachments.length >= DEFAULT_MAX_IMAGES) {
|
|
2070
2413
|
setClipboardNotice(`A prompt can contain at most ${DEFAULT_MAX_IMAGES} images.`);
|
|
2071
2414
|
return;
|
|
2072
2415
|
}
|
|
@@ -2080,14 +2423,15 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2080
2423
|
return;
|
|
2081
2424
|
}
|
|
2082
2425
|
const incomingBytes = Buffer.byteLength(attachment.dataBase64, "base64");
|
|
2083
|
-
const
|
|
2426
|
+
const currentDraft = promptDraftRef.current;
|
|
2427
|
+
const currentBytes = currentDraft.imageAttachments.reduce((sum, image) => sum + image.bytes, 0);
|
|
2084
2428
|
if (currentBytes + incomingBytes > DEFAULT_MAX_TOTAL_IMAGE_BYTES) {
|
|
2085
2429
|
throw new Error(`Image attachments exceed the maximum total size of ${DEFAULT_MAX_TOTAL_IMAGE_BYTES} bytes`);
|
|
2086
2430
|
}
|
|
2087
2431
|
const [stored] = await new SessionAssetStore({ workspace }).store(active.sessionId, [attachment]);
|
|
2088
2432
|
if (stored === void 0) throw new Error("Clipboard image could not be stored");
|
|
2089
|
-
|
|
2090
|
-
setClipboardNotice(`Added [Image #${imageAttachments.length + 1}] ${stored.name ?? basename3(stored.source.path)}`);
|
|
2433
|
+
commitPromptDraft({ ...currentDraft, imageAttachments: [...currentDraft.imageAttachments, stored] });
|
|
2434
|
+
setClipboardNotice(`Added [Image #${currentDraft.imageAttachments.length + 1}] ${stored.name ?? basename3(stored.source.path)}`);
|
|
2091
2435
|
} catch (error) {
|
|
2092
2436
|
setClipboardNotice(safeUiError(error));
|
|
2093
2437
|
} finally {
|
|
@@ -2097,7 +2441,12 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2097
2441
|
use_input_default((character, key, event) => {
|
|
2098
2442
|
const terminalAction = classifyTerminalInput(key);
|
|
2099
2443
|
if (terminalAction?.type === "scroll") {
|
|
2100
|
-
const scroll = selectWheelScrollTarget(
|
|
2444
|
+
const scroll = selectWheelScrollTarget(
|
|
2445
|
+
scrollRef.current,
|
|
2446
|
+
mainTaskScrollRef.current,
|
|
2447
|
+
subagentTaskScrollRef.current,
|
|
2448
|
+
hoveredTaskTrack.current
|
|
2449
|
+
);
|
|
2101
2450
|
if (scroll !== null) {
|
|
2102
2451
|
if (terminalAction.rows < 0) scrollUp(scroll, -terminalAction.rows);
|
|
2103
2452
|
else scrollDown(scroll, terminalAction.rows);
|
|
@@ -2110,12 +2459,13 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2110
2459
|
return;
|
|
2111
2460
|
}
|
|
2112
2461
|
const active = runtimeRef.current;
|
|
2113
|
-
if (
|
|
2114
|
-
if (selection.hasSelection())
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2462
|
+
if (isCopyShortcut(character, key)) {
|
|
2463
|
+
if (selection.hasSelection()) selection.copySelection();
|
|
2464
|
+
else if (process.platform !== "darwin") interrupt();
|
|
2465
|
+
return;
|
|
2466
|
+
}
|
|
2467
|
+
if (key.ctrl && character.toLowerCase() === "c") {
|
|
2468
|
+
interrupt();
|
|
2119
2469
|
return;
|
|
2120
2470
|
}
|
|
2121
2471
|
if (shouldReadClipboardImage(character, key, event.keypress.isPasted)) {
|
|
@@ -2188,23 +2538,20 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2188
2538
|
setPromptCursor(0);
|
|
2189
2539
|
return;
|
|
2190
2540
|
}
|
|
2191
|
-
if (!key.ctrl && !key.meta && character) setCustomQuestionActive(true);
|
|
2541
|
+
if (!key.ctrl && !key.meta && !key.super && character) setCustomQuestionActive(true);
|
|
2192
2542
|
else return;
|
|
2193
2543
|
}
|
|
2194
2544
|
}
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
setDismissedMentionInput(void 0);
|
|
2206
|
-
return;
|
|
2207
|
-
}
|
|
2545
|
+
const historyAction = promptHistoryAction(character, key);
|
|
2546
|
+
if (historyAction !== null) {
|
|
2547
|
+
const draft = promptDraftRef.current;
|
|
2548
|
+
const restored = historyAction === "undo" ? promptEditHistory.current.undo(draft) : promptEditHistory.current.redo(draft);
|
|
2549
|
+
if (restored !== void 0) commitPromptDraft(restored, false);
|
|
2550
|
+
setSlashSelection(0);
|
|
2551
|
+
setDismissedSlashInput(void 0);
|
|
2552
|
+
setMentionSelection(0);
|
|
2553
|
+
setDismissedMentionInput(void 0);
|
|
2554
|
+
return;
|
|
2208
2555
|
}
|
|
2209
2556
|
const menuAction = slashKeyAction(key, slashCompletion);
|
|
2210
2557
|
if (menuAction?.type === "select" && slashCompletion !== null) {
|
|
@@ -2215,8 +2562,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2215
2562
|
const selected = slashCompletion.items[slashCompletion.selectedIndex];
|
|
2216
2563
|
if (selected !== void 0) {
|
|
2217
2564
|
const next = completeSlashSelection(input, promptCursor, selected.name);
|
|
2218
|
-
|
|
2219
|
-
setPromptCursor(next.cursor);
|
|
2565
|
+
commitPromptDraft(next);
|
|
2220
2566
|
setDismissedSlashInput(next.text);
|
|
2221
2567
|
}
|
|
2222
2568
|
return;
|
|
@@ -2239,9 +2585,24 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2239
2585
|
setDismissedMentionInput(input);
|
|
2240
2586
|
return;
|
|
2241
2587
|
}
|
|
2588
|
+
if (key.escape && transcript.active !== void 0) {
|
|
2589
|
+
const restored = pendingPromptRef.current.cancel();
|
|
2590
|
+
if (restored !== void 0) {
|
|
2591
|
+
setPendingPrompts([...pendingPromptRef.current.values]);
|
|
2592
|
+
const restoredDraft = restoreQueuedPrompt(restored);
|
|
2593
|
+
promptEditHistory.current.reset();
|
|
2594
|
+
commitPromptDraft(restoredDraft, false);
|
|
2595
|
+
setClipboardNotice(restoredDraft.imageAttachments.length === 0 ? void 0 : `Restored ${restoredDraft.imageAttachments.length} pending ${restoredDraft.imageAttachments.length === 1 ? "image" : "images"}.`);
|
|
2596
|
+
setSlashSelection(0);
|
|
2597
|
+
setDismissedSlashInput(void 0);
|
|
2598
|
+
setMentionSelection(0);
|
|
2599
|
+
setDismissedMentionInput(void 0);
|
|
2600
|
+
return;
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2242
2603
|
if (key.return) {
|
|
2243
2604
|
const images = [...imageAttachments];
|
|
2244
|
-
const prepared = prepareCliSubmission(input, images
|
|
2605
|
+
const prepared = prepareCliSubmission(input, images);
|
|
2245
2606
|
if (prepared.kind === "empty" || active === void 0) return;
|
|
2246
2607
|
if (prepared.kind === "error") {
|
|
2247
2608
|
setClipboardNotice(prepared.message);
|
|
@@ -2251,8 +2612,12 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2251
2612
|
const { delivery, prompt } = resolvePromptDelivery(transcript.active !== void 0, key, submittedText);
|
|
2252
2613
|
if (!prompt) return;
|
|
2253
2614
|
if (delivery === "followUp" && transcript.active !== void 0) {
|
|
2254
|
-
if (!pendingPromptRef.current.queue(
|
|
2255
|
-
|
|
2615
|
+
if (!pendingPromptRef.current.queue({
|
|
2616
|
+
text: prompt,
|
|
2617
|
+
displayText: prepared.content === void 0 ? prompt : prepared.displayText,
|
|
2618
|
+
...prepared.content === void 0 ? {} : { content: prepared.content }
|
|
2619
|
+
})) return;
|
|
2620
|
+
setPendingPrompts([...pendingPromptRef.current.values]);
|
|
2256
2621
|
}
|
|
2257
2622
|
scrollRef.current?.scrollToBottom();
|
|
2258
2623
|
setHistory((current) => [...current, submittedText].slice(-HISTORY_CAP));
|
|
@@ -2261,6 +2626,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2261
2626
|
setPastedBlocks([]);
|
|
2262
2627
|
setImageAttachments([]);
|
|
2263
2628
|
promptDraftRef.current = { text: "", cursor: 0, pastedBlocks: [], imageAttachments: [] };
|
|
2629
|
+
promptEditHistory.current.reset();
|
|
2264
2630
|
setClipboardNotice(void 0);
|
|
2265
2631
|
setPromptCursor(0);
|
|
2266
2632
|
setSlashSelection(0);
|
|
@@ -2273,15 +2639,12 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2273
2639
|
initialPrompt: prompt,
|
|
2274
2640
|
...prepared.content === void 0 ? {} : {
|
|
2275
2641
|
initialDisplayPrompt: prepared.displayText,
|
|
2276
|
-
|
|
2277
|
-
text,
|
|
2278
|
-
content: prepared.content
|
|
2279
|
-
})
|
|
2642
|
+
initialContent: prepared.content
|
|
2280
2643
|
},
|
|
2281
2644
|
pending: pendingPromptRef.current,
|
|
2282
2645
|
onStart: (next) => dispatch({ type: "submit", prompt: next }),
|
|
2283
2646
|
onFinish: () => dispatch({ type: "finish" }),
|
|
2284
|
-
onPendingConsumed: () =>
|
|
2647
|
+
onPendingConsumed: (remaining) => setPendingPrompts([...remaining]),
|
|
2285
2648
|
report: (error) => dispatch({ type: "submit-error", message: error }),
|
|
2286
2649
|
shouldContinue: () => !closing.current
|
|
2287
2650
|
});
|
|
@@ -2298,8 +2661,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2298
2661
|
const draft = promptDraftRef.current;
|
|
2299
2662
|
const imageEdit = removeLastCliImageOnBackspace(draft.text, draft.cursor, draft.imageAttachments);
|
|
2300
2663
|
if (imageEdit.handled) {
|
|
2301
|
-
|
|
2302
|
-
promptDraftRef.current = { ...draft, imageAttachments: imageEdit.images };
|
|
2664
|
+
commitPromptDraft({ ...draft, imageAttachments: imageEdit.images });
|
|
2303
2665
|
setClipboardNotice(imageEdit.images.length === 0 ? "Removed image attachment." : `Removed image attachment; ${imageEdit.images.length} remaining.`);
|
|
2304
2666
|
return;
|
|
2305
2667
|
}
|
|
@@ -2342,7 +2704,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2342
2704
|
setDismissedSlashInput(void 0);
|
|
2343
2705
|
setMentionSelection(0);
|
|
2344
2706
|
setDismissedMentionInput(void 0);
|
|
2345
|
-
} else if (!key.ctrl && !key.meta && character) {
|
|
2707
|
+
} else if (!key.ctrl && !key.meta && !key.super && character) {
|
|
2346
2708
|
const draft = promptDraftRef.current;
|
|
2347
2709
|
const nextPastedBlocks = /[\r\n]/u.test(character) ? [...draft.pastedBlocks, { id: draft.pastedBlocks.length + 1, text: character }] : draft.pastedBlocks;
|
|
2348
2710
|
commitPromptDraft({
|
|
@@ -2388,9 +2750,10 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2388
2750
|
...ideContext === void 0 ? {} : { ideContext },
|
|
2389
2751
|
completedSlashTokenLength: completedTokenLength,
|
|
2390
2752
|
scrollRef,
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2753
|
+
mainTaskScrollRef,
|
|
2754
|
+
subagentTaskScrollRef,
|
|
2755
|
+
onTaskPanelHoverChange: (track) => {
|
|
2756
|
+
hoveredTaskTrack.current = track;
|
|
2394
2757
|
},
|
|
2395
2758
|
...slashCompletion === null ? {} : { completion: slashCompletion },
|
|
2396
2759
|
...mentionCompletion === null ? {} : { mentionCompletion, onMentionSelect: selectMention },
|
|
@@ -2398,7 +2761,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2398
2761
|
...questions === void 0 ? {} : { questions },
|
|
2399
2762
|
memoryReviews,
|
|
2400
2763
|
memoryAutoDismissSeconds,
|
|
2401
|
-
|
|
2764
|
+
pendingPrompts,
|
|
2402
2765
|
questionIndex,
|
|
2403
2766
|
questionAnswers,
|
|
2404
2767
|
customQuestionActive
|
|
@@ -2511,7 +2874,7 @@ function TerminalLayout({
|
|
|
2511
2874
|
columns,
|
|
2512
2875
|
rows = 24,
|
|
2513
2876
|
activeSession,
|
|
2514
|
-
|
|
2877
|
+
pendingPrompts = [],
|
|
2515
2878
|
approval,
|
|
2516
2879
|
questions,
|
|
2517
2880
|
memoryReviews = [],
|
|
@@ -2524,7 +2887,8 @@ function TerminalLayout({
|
|
|
2524
2887
|
onMentionSelect,
|
|
2525
2888
|
completedSlashTokenLength: tokenLength = 0,
|
|
2526
2889
|
scrollRef,
|
|
2527
|
-
|
|
2890
|
+
mainTaskScrollRef,
|
|
2891
|
+
subagentTaskScrollRef,
|
|
2528
2892
|
onTaskPanelHoverChange,
|
|
2529
2893
|
onPromptCursorChange,
|
|
2530
2894
|
ideContext
|
|
@@ -2546,7 +2910,7 @@ function TerminalLayout({
|
|
|
2546
2910
|
const completedWindow = cliTranscriptWindow(completed);
|
|
2547
2911
|
const questionRows = questions === void 0 ? 0 : 4 + (questions[questionIndex]?.options.length ?? 0) + questions.length * 2;
|
|
2548
2912
|
const memoryReviewRows = memoryReviews.length === 0 ? 0 : 5;
|
|
2549
|
-
const fixedBottomRows = (approval === void 0 ? 0 : 3) + questionRows + memoryReviewRows + menuRows + (
|
|
2913
|
+
const fixedBottomRows = (approval === void 0 ? 0 : 3) + questionRows + memoryReviewRows + menuRows + (pendingPrompts.length === 0 ? 0 : 1) + imageAttachments.length + (clipboardNotice === void 0 ? 0 : 1) + 2;
|
|
2550
2914
|
const taskPanelRows = taskPanelViewportRows(rows, fixedBottomRows, activeTaskBlocks.length > 0);
|
|
2551
2915
|
const availableBottomRows = Math.max(1, rows - taskPanelRows - 1);
|
|
2552
2916
|
const bottomMaxRows = Math.min(availableBottomRows, Math.max(Math.floor(rows / 2), fixedBottomRows + 1));
|
|
@@ -2583,7 +2947,8 @@ function TerminalLayout({
|
|
|
2583
2947
|
interactive: activeSession,
|
|
2584
2948
|
maxHeight: taskPanelRows,
|
|
2585
2949
|
columns,
|
|
2586
|
-
...
|
|
2950
|
+
...mainTaskScrollRef === void 0 ? {} : { mainScrollRef: mainTaskScrollRef },
|
|
2951
|
+
...subagentTaskScrollRef === void 0 ? {} : { subagentScrollRef: subagentTaskScrollRef },
|
|
2587
2952
|
...onTaskPanelHoverChange === void 0 ? {} : { onHoverChange: onTaskPanelHoverChange }
|
|
2588
2953
|
}
|
|
2589
2954
|
),
|
|
@@ -2617,10 +2982,12 @@ function TerminalLayout({
|
|
|
2617
2982
|
memoryReviews.length === 0 ? null : /* @__PURE__ */ jsx5(MemoryReviewCards, { reviews: memoryReviews, autoDismissSeconds: memoryAutoDismissSeconds }),
|
|
2618
2983
|
completion === void 0 ? null : /* @__PURE__ */ jsx5(SlashMenu, { completion }),
|
|
2619
2984
|
mentionCompletion === void 0 ? null : /* @__PURE__ */ jsx5(MentionMenu, { completion: mentionCompletion, ...onMentionSelect === void 0 ? {} : { onSelect: onMentionSelect } }),
|
|
2620
|
-
|
|
2621
|
-
"Pending
|
|
2622
|
-
|
|
2623
|
-
" \xB7
|
|
2985
|
+
pendingPrompts.length === 0 ? null : /* @__PURE__ */ jsxs4(Text, { color: "yellow", wrap: "truncate-end", children: [
|
|
2986
|
+
"Pending (",
|
|
2987
|
+
pendingPrompts.length,
|
|
2988
|
+
") \xB7 ",
|
|
2989
|
+
queuedPromptLabel(pendingPrompts.at(-1)),
|
|
2990
|
+
" \xB7 Esc edit latest"
|
|
2624
2991
|
] }),
|
|
2625
2992
|
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: "\u2500".repeat(dividerWidth) }),
|
|
2626
2993
|
imageAttachments.map((image, index) => /* @__PURE__ */ jsxs4(Text, { color: "cyan", wrap: "truncate-end", children: [
|
|
@@ -2645,7 +3012,7 @@ function TerminalLayout({
|
|
|
2645
3012
|
/* @__PURE__ */ jsx5(
|
|
2646
3013
|
FooterStatus,
|
|
2647
3014
|
{
|
|
2648
|
-
hint: activeSession ? "Ctrl+C cancel \xB7 Enter queue \xB7 Esc edit
|
|
3015
|
+
hint: activeSession ? "Ctrl+C cancel \xB7 Enter queue \xB7 Esc edit latest \xB7 / menu \xB7 Ctrl/Cmd+V image" : completion !== void 0 ? "\u2191/\u2193 select \xB7 Tab complete \xB7 Esc close" : mentionCompletion !== void 0 ? "\u2191/\u2193 select \xB7 Tab complete \xB7 click choose \xB7 Esc close" : "Enter send \xB7 Ctrl/Cmd+V image \xB7 \u2191\u2193 history \xB7 Ctrl+C exit",
|
|
2649
3016
|
...ideContext === void 0 ? {} : { ideContext }
|
|
2650
3017
|
}
|
|
2651
3018
|
)
|
|
@@ -2749,6 +3116,7 @@ function SlashMenu({ completion }) {
|
|
|
2749
3116
|
return /* @__PURE__ */ jsxs4(Text, { ...presentation.rowStyle, wrap: "truncate-end", children: [
|
|
2750
3117
|
presentation.marker,
|
|
2751
3118
|
/* @__PURE__ */ jsx5(HighlightedName, { name: candidate.name, query: completion.query, matchStyle: presentation.matchStyle }),
|
|
3119
|
+
candidate.kind === "skill" || candidate.kind === "plugin" ? /* @__PURE__ */ jsx5(Text, { color: candidate.kind === "skill" ? "magentaBright" : "cyanBright", children: ` ${candidate.kind}` }) : null,
|
|
2752
3120
|
candidate.description === void 0 ? null : /* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` ${candidate.description}` })
|
|
2753
3121
|
] }, `${candidate.kind}:${candidate.name}`);
|
|
2754
3122
|
}) });
|
|
@@ -2804,8 +3172,10 @@ function jumpScroll(scroll, delta) {
|
|
|
2804
3172
|
scroll.scrollTo(Math.max(0, target));
|
|
2805
3173
|
}
|
|
2806
3174
|
}
|
|
2807
|
-
function selectWheelScrollTarget(transcript,
|
|
2808
|
-
|
|
3175
|
+
function selectWheelScrollTarget(transcript, mainTasks, subagentTasks, hoveredTrack) {
|
|
3176
|
+
if (hoveredTrack === "main" && mainTasks !== null) return mainTasks;
|
|
3177
|
+
if (hoveredTrack === "subagent" && subagentTasks !== null) return subagentTasks;
|
|
3178
|
+
return transcript;
|
|
2809
3179
|
}
|
|
2810
3180
|
function taskPanelViewportRows(rows, reservedBottomRows, hasTasks) {
|
|
2811
3181
|
if (!hasTasks) return 0;
|
|
@@ -3682,12 +4052,14 @@ export {
|
|
|
3682
4052
|
FooterStatus,
|
|
3683
4053
|
HISTORY_CAP,
|
|
3684
4054
|
MentionMenu,
|
|
4055
|
+
PendingPromptQueue,
|
|
4056
|
+
PromptEditHistory,
|
|
3685
4057
|
PromptLine,
|
|
3686
4058
|
SHUTDOWN_TIMEOUT_MS,
|
|
3687
|
-
SinglePendingPrompt,
|
|
3688
4059
|
TerminalLayout,
|
|
3689
4060
|
appRuntimeOptions,
|
|
3690
4061
|
boundedCliTurn,
|
|
4062
|
+
canShowSlashCompletion,
|
|
3691
4063
|
classifyTerminalInput,
|
|
3692
4064
|
cliTranscriptWindow,
|
|
3693
4065
|
closeAndDisposeRuntime,
|
|
@@ -3695,13 +4067,17 @@ export {
|
|
|
3695
4067
|
editPrompt,
|
|
3696
4068
|
editPromptWithPastedBlocks,
|
|
3697
4069
|
ideFooterPresentation,
|
|
4070
|
+
isCopyShortcut,
|
|
3698
4071
|
navigateHistory,
|
|
3699
4072
|
pastedDraftPresentation,
|
|
3700
4073
|
prepareCliSubmission,
|
|
3701
4074
|
promptCursorFromClick,
|
|
3702
4075
|
promptDelivery,
|
|
4076
|
+
promptHistoryAction,
|
|
4077
|
+
queuedPromptLabel,
|
|
3703
4078
|
removeLastCliImageOnBackspace,
|
|
3704
4079
|
resolvePromptDelivery,
|
|
4080
|
+
restoreQueuedPrompt,
|
|
3705
4081
|
runTerminalSubmissionChain,
|
|
3706
4082
|
selectWheelScrollTarget,
|
|
3707
4083
|
shutdownRuntime,
|