flavor-code 1.4.0-beta.8 → 1.4.1-beta.1
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-KSUBHHLR.js → app-UKTPW3E6.js} +784 -183
- package/dist/{chunk-EXOSMO57.js → chunk-7YFHRORG.js} +2 -3
- package/dist/{chunk-EUKT7HEU.js → chunk-FAORPP4F.js} +1 -1
- package/dist/{chunk-LLC7WBXP.js → chunk-O2PC44GY.js} +216 -42
- 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 +218 -45
- 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/models/structured.d.ts +7 -0
- package/dist/models/types.d.ts +1 -1
- package/dist/permissions/engine.d.ts +2 -0
- package/dist/sdk/index.js +3 -3
- package/dist/ui/session.d.ts +2 -0
- 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-O2PC44GY.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,18 +34,21 @@ 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
|
|
|
47
49
|
// src/ui/app.tsx
|
|
48
50
|
import { basename as basename3 } from "path";
|
|
51
|
+
import { homedir } from "os";
|
|
49
52
|
import { useEffect as useEffect3, useReducer, useRef as useRef4, useState as useState2 } from "react";
|
|
50
53
|
|
|
51
54
|
// src/claude-ink/hooks/use-animation-frame.ts
|
|
@@ -969,7 +972,13 @@ function wrapPromptInput(input, codePointCursor, options) {
|
|
|
969
972
|
// src/ui/task-progress.tsx
|
|
970
973
|
import { useRef as useRef3 } from "react";
|
|
971
974
|
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
972
|
-
function TaskStatusLine({
|
|
975
|
+
function TaskStatusLine({
|
|
976
|
+
block,
|
|
977
|
+
interactive,
|
|
978
|
+
textWidth,
|
|
979
|
+
maxTextLines,
|
|
980
|
+
showRoleBadge = true
|
|
981
|
+
}) {
|
|
973
982
|
const running = block.state === "running";
|
|
974
983
|
const { stdout } = useStdout();
|
|
975
984
|
const foreground = interactive && (block.activity === "model" || block.task?.role === "main");
|
|
@@ -982,6 +991,8 @@ function TaskStatusLine({ block, interactive }) {
|
|
|
982
991
|
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
992
|
const presentation = statusPresentation(block, elapsed, foreground);
|
|
984
993
|
const { metaColor, metaLabel, statusLabel, statusColor, text } = presentation;
|
|
994
|
+
const badge = showRoleBadge ? presentation.badge : void 0;
|
|
995
|
+
const badgeColor = presentation.badgeColor;
|
|
985
996
|
let before = text;
|
|
986
997
|
let after = "";
|
|
987
998
|
if (statusLabel !== void 0) {
|
|
@@ -1007,14 +1018,26 @@ function TaskStatusLine({ block, interactive }) {
|
|
|
1007
1018
|
thinkingScroll.current = { start: state.start, lastTime: time };
|
|
1008
1019
|
return state.text;
|
|
1009
1020
|
})() : void 0;
|
|
1021
|
+
const textSegments = [
|
|
1022
|
+
{ text: `${presentation.glyph} `, color: presentation.color },
|
|
1023
|
+
...badge ? [{ text: `${badge} `, color: badgeColor }] : [],
|
|
1024
|
+
{ text: before, color: presentation.color },
|
|
1025
|
+
...statusLabel === void 0 ? [] : [
|
|
1026
|
+
{ text: " \xB7 ", color: presentation.color },
|
|
1027
|
+
{ text: statusLabel, color: statusColor ?? presentation.color }
|
|
1028
|
+
],
|
|
1029
|
+
...after ? [{ text: after, color: presentation.color }] : [],
|
|
1030
|
+
...metaLabel === void 0 ? [] : [{ text: ` ${metaLabel}`, color: metaColor ?? "ansi:blackBright" }]
|
|
1031
|
+
];
|
|
1032
|
+
const boundedText = textWidth === void 0 || maxTextLines === void 0 ? void 0 : limitTaskTextSegments(textSegments, textWidth, maxTextLines).segments;
|
|
1010
1033
|
return /* @__PURE__ */ jsxs2(Box_default, { flexDirection: "column", width: "100%", children: [
|
|
1011
|
-
/* @__PURE__ */
|
|
1034
|
+
/* @__PURE__ */ jsx3(Box_default, { ref, flexDirection: "row", width: "100%", children: boundedText === void 0 ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1012
1035
|
/* @__PURE__ */ jsxs2(Text, { ...presentation.color === void 0 ? {} : { color: presentation.color }, children: [
|
|
1013
1036
|
presentation.glyph,
|
|
1014
1037
|
" "
|
|
1015
1038
|
] }),
|
|
1016
|
-
|
|
1017
|
-
|
|
1039
|
+
badge ? /* @__PURE__ */ jsxs2(Text, { color: badgeColor, children: [
|
|
1040
|
+
badge,
|
|
1018
1041
|
" "
|
|
1019
1042
|
] }) : null,
|
|
1020
1043
|
/* @__PURE__ */ jsx3(Text, { ...presentation.color === void 0 ? {} : { color: presentation.color }, children: before }),
|
|
@@ -1027,10 +1050,69 @@ function TaskStatusLine({ block, interactive }) {
|
|
|
1027
1050
|
" ",
|
|
1028
1051
|
metaLabel
|
|
1029
1052
|
] })
|
|
1030
|
-
] }),
|
|
1053
|
+
] }) : /* @__PURE__ */ jsx3(Text, { children: boundedText.map((segment, index) => /* @__PURE__ */ jsx3(Text, { ...segment.color === void 0 ? {} : { color: segment.color }, children: segment.text }, index)) }) }),
|
|
1031
1054
|
thinkingLine === void 0 ? null : /* @__PURE__ */ jsx3(ThinkingLineView, { text: thinkingLine })
|
|
1032
1055
|
] });
|
|
1033
1056
|
}
|
|
1057
|
+
function limitTaskTextSegments(segments, width, maxLines = 3) {
|
|
1058
|
+
const lineWidth = Math.max(3, Math.floor(width));
|
|
1059
|
+
const lineLimit = Math.max(1, Math.floor(maxLines));
|
|
1060
|
+
const lines = [[]];
|
|
1061
|
+
const widths = [0];
|
|
1062
|
+
let truncated = false;
|
|
1063
|
+
outer: for (let segmentIndex = 0; segmentIndex < segments.length; segmentIndex += 1) {
|
|
1064
|
+
const segment = segments[segmentIndex];
|
|
1065
|
+
for (const { segment: grapheme } of getGraphemeSegmenter().segment(segment.text)) {
|
|
1066
|
+
if (grapheme === "\n" || grapheme === "\r" || grapheme === "\r\n") {
|
|
1067
|
+
if (lines.length >= lineLimit) {
|
|
1068
|
+
truncated = true;
|
|
1069
|
+
break outer;
|
|
1070
|
+
}
|
|
1071
|
+
lines.push([]);
|
|
1072
|
+
widths.push(0);
|
|
1073
|
+
continue;
|
|
1074
|
+
}
|
|
1075
|
+
const glyphWidth = stringWidth(grapheme);
|
|
1076
|
+
const lineIndex = lines.length - 1;
|
|
1077
|
+
if (glyphWidth > 0 && widths[lineIndex] + glyphWidth > lineWidth && lines[lineIndex].length > 0) {
|
|
1078
|
+
if (lines.length >= lineLimit) {
|
|
1079
|
+
truncated = true;
|
|
1080
|
+
break outer;
|
|
1081
|
+
}
|
|
1082
|
+
lines.push([]);
|
|
1083
|
+
widths.push(0);
|
|
1084
|
+
}
|
|
1085
|
+
const target = lines.length - 1;
|
|
1086
|
+
lines[target].push({ value: grapheme, width: glyphWidth, segmentIndex });
|
|
1087
|
+
widths[target] = widths[target] + glyphWidth;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
if (truncated) {
|
|
1091
|
+
const lastIndex = lines.length - 1;
|
|
1092
|
+
const last = lines[lastIndex];
|
|
1093
|
+
while (last.length > 0 && widths[lastIndex] > lineWidth - 3) {
|
|
1094
|
+
widths[lastIndex] = widths[lastIndex] - last.pop().width;
|
|
1095
|
+
}
|
|
1096
|
+
while (last.length > 0 && /^\s$/u.test(last.at(-1).value)) {
|
|
1097
|
+
widths[lastIndex] = widths[lastIndex] - last.pop().width;
|
|
1098
|
+
}
|
|
1099
|
+
last.push({ value: "...", width: 3, segmentIndex: last.at(-1)?.segmentIndex ?? 0 });
|
|
1100
|
+
}
|
|
1101
|
+
const output = [];
|
|
1102
|
+
const append = (value, segmentIndex) => {
|
|
1103
|
+
const previous = output.at(-1);
|
|
1104
|
+
if (previous?.segmentIndex === segmentIndex) previous.text += value;
|
|
1105
|
+
else output.push({ text: value, color: segments[segmentIndex]?.color, segmentIndex });
|
|
1106
|
+
};
|
|
1107
|
+
lines.forEach((line, lineIndex) => {
|
|
1108
|
+
if (lineIndex > 0) append("\n", line[0]?.segmentIndex ?? output.at(-1)?.segmentIndex ?? 0);
|
|
1109
|
+
for (const token of line) append(token.value, token.segmentIndex);
|
|
1110
|
+
});
|
|
1111
|
+
return {
|
|
1112
|
+
truncated,
|
|
1113
|
+
segments: output.map(({ text, color }) => ({ text, ...color === void 0 ? {} : { color } }))
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1034
1116
|
var THINKING_RAIL = "#416f84";
|
|
1035
1117
|
var THINKING_TEXT = "#91a0a8";
|
|
1036
1118
|
function ThinkingLineView({ text }) {
|
|
@@ -1039,13 +1121,16 @@ function ThinkingLineView({ text }) {
|
|
|
1039
1121
|
/* @__PURE__ */ jsx3(Text, { color: THINKING_TEXT, wrap: "truncate-end", children: text })
|
|
1040
1122
|
] });
|
|
1041
1123
|
}
|
|
1042
|
-
var SPLIT_TRACK_MIN_COLUMNS =
|
|
1124
|
+
var SPLIT_TRACK_MIN_COLUMNS = 96;
|
|
1125
|
+
var SPLIT_TRACK_GUTTER_COLUMNS = 3;
|
|
1126
|
+
var SPLIT_TRACK_MAIN_RATIO = 0.44;
|
|
1043
1127
|
function TaskProgressPanel({
|
|
1044
1128
|
blocks,
|
|
1045
1129
|
interactive,
|
|
1046
1130
|
maxHeight = 8,
|
|
1047
1131
|
columns = 80,
|
|
1048
|
-
|
|
1132
|
+
mainScrollRef,
|
|
1133
|
+
subagentScrollRef,
|
|
1049
1134
|
onHoverChange
|
|
1050
1135
|
}) {
|
|
1051
1136
|
if (blocks.length === 0 || maxHeight <= 0) return null;
|
|
@@ -1054,54 +1139,210 @@ function TaskProgressPanel({
|
|
|
1054
1139
|
const hasTasks = taskBlocks.length > 0;
|
|
1055
1140
|
const hasSubagents = subagentBlocks.length > 0;
|
|
1056
1141
|
const split = hasTasks && hasSubagents && columns >= SPLIT_TRACK_MIN_COLUMNS;
|
|
1057
|
-
|
|
1142
|
+
const hoverProps = (track) => ({
|
|
1143
|
+
onMouseEnter: () => onHoverChange?.(track)
|
|
1144
|
+
});
|
|
1145
|
+
return /* @__PURE__ */ jsx3(
|
|
1058
1146
|
Box_default,
|
|
1059
1147
|
{
|
|
1060
1148
|
flexDirection: "column",
|
|
1061
1149
|
flexShrink: 0,
|
|
1062
1150
|
width: "100%",
|
|
1063
1151
|
maxHeight,
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1152
|
+
onMouseLeave: () => onHoverChange?.(null),
|
|
1153
|
+
children: split ? /* @__PURE__ */ jsx3(
|
|
1154
|
+
SplitTracks,
|
|
1155
|
+
{
|
|
1156
|
+
taskBlocks,
|
|
1157
|
+
subagentBlocks,
|
|
1158
|
+
interactive,
|
|
1159
|
+
height: maxHeight,
|
|
1160
|
+
columns,
|
|
1161
|
+
mainScrollRef,
|
|
1162
|
+
subagentScrollRef,
|
|
1163
|
+
hoverProps
|
|
1164
|
+
}
|
|
1165
|
+
) : hasTasks && hasSubagents ? /* @__PURE__ */ jsx3(
|
|
1166
|
+
StackedTracks,
|
|
1167
|
+
{
|
|
1168
|
+
taskBlocks,
|
|
1169
|
+
subagentBlocks,
|
|
1170
|
+
interactive,
|
|
1171
|
+
height: maxHeight,
|
|
1172
|
+
columns,
|
|
1173
|
+
mainScrollRef,
|
|
1174
|
+
subagentScrollRef,
|
|
1175
|
+
hoverProps
|
|
1176
|
+
}
|
|
1177
|
+
) : /* @__PURE__ */ jsx3(
|
|
1178
|
+
SingleTrack,
|
|
1179
|
+
{
|
|
1180
|
+
role: hasTasks ? "main" : "subagent",
|
|
1181
|
+
blocks: hasTasks ? taskBlocks : subagentBlocks,
|
|
1182
|
+
interactive,
|
|
1183
|
+
height: maxHeight,
|
|
1184
|
+
width: columns,
|
|
1185
|
+
scrollRef: hasTasks ? mainScrollRef : subagentScrollRef,
|
|
1186
|
+
hoverProps
|
|
1187
|
+
}
|
|
1188
|
+
)
|
|
1087
1189
|
}
|
|
1088
1190
|
);
|
|
1089
1191
|
}
|
|
1090
|
-
function
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1192
|
+
function SplitTracks({
|
|
1193
|
+
taskBlocks,
|
|
1194
|
+
subagentBlocks,
|
|
1195
|
+
interactive,
|
|
1196
|
+
height,
|
|
1197
|
+
columns,
|
|
1198
|
+
mainScrollRef,
|
|
1199
|
+
subagentScrollRef,
|
|
1200
|
+
hoverProps
|
|
1201
|
+
}) {
|
|
1202
|
+
const contentHeight = Math.max(0, height - 1);
|
|
1203
|
+
const availableWidth = columns - SPLIT_TRACK_GUTTER_COLUMNS;
|
|
1204
|
+
const leftWidth = Math.max(1, Math.floor(availableWidth * SPLIT_TRACK_MAIN_RATIO));
|
|
1205
|
+
const rightWidth = Math.max(1, availableWidth - leftWidth);
|
|
1206
|
+
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1207
|
+
/* @__PURE__ */ jsxs2(Box_default, { flexDirection: "row", width: "100%", children: [
|
|
1208
|
+
/* @__PURE__ */ jsx3(Box_default, { width: leftWidth, ...hoverProps("main"), children: /* @__PURE__ */ jsx3(TrackHeader, { role: "main", count: taskBlocks.length, width: leftWidth }) }),
|
|
1209
|
+
/* @__PURE__ */ jsx3(Text, { color: "ansi:white", children: "\u2500\u252C\u2500" }),
|
|
1210
|
+
/* @__PURE__ */ jsx3(Box_default, { width: rightWidth, ...hoverProps("subagent"), children: /* @__PURE__ */ jsx3(TrackHeader, { role: "subagent", count: subagentBlocks.length, width: rightWidth }) })
|
|
1211
|
+
] }),
|
|
1212
|
+
contentHeight <= 0 ? null : /* @__PURE__ */ jsxs2(Box_default, { flexDirection: "row", width: "100%", height: contentHeight, children: [
|
|
1213
|
+
/* @__PURE__ */ jsx3(Box_default, { width: leftWidth, minWidth: 0, flexDirection: "column", ...hoverProps("main"), children: /* @__PURE__ */ jsx3(
|
|
1214
|
+
TrackScrollBox,
|
|
1215
|
+
{
|
|
1216
|
+
ref: mainScrollRef,
|
|
1217
|
+
blocks: taskBlocks,
|
|
1218
|
+
interactive,
|
|
1219
|
+
height: contentHeight,
|
|
1220
|
+
width: leftWidth,
|
|
1221
|
+
maxTextLines: 2
|
|
1222
|
+
}
|
|
1223
|
+
) }),
|
|
1224
|
+
/* @__PURE__ */ jsx3(TrackDivider, { height: contentHeight }),
|
|
1225
|
+
/* @__PURE__ */ jsx3(Box_default, { width: rightWidth, minWidth: 0, flexDirection: "column", ...hoverProps("subagent"), children: /* @__PURE__ */ jsx3(
|
|
1226
|
+
TrackScrollBox,
|
|
1227
|
+
{
|
|
1228
|
+
ref: subagentScrollRef,
|
|
1229
|
+
blocks: subagentBlocks,
|
|
1230
|
+
interactive,
|
|
1231
|
+
height: contentHeight,
|
|
1232
|
+
width: rightWidth,
|
|
1233
|
+
maxTextLines: 2
|
|
1234
|
+
}
|
|
1235
|
+
) })
|
|
1236
|
+
] })
|
|
1237
|
+
] });
|
|
1238
|
+
}
|
|
1239
|
+
function StackedTracks({
|
|
1240
|
+
taskBlocks,
|
|
1241
|
+
subagentBlocks,
|
|
1242
|
+
interactive,
|
|
1243
|
+
height,
|
|
1244
|
+
columns,
|
|
1245
|
+
mainScrollRef,
|
|
1246
|
+
subagentScrollRef,
|
|
1247
|
+
hoverProps
|
|
1248
|
+
}) {
|
|
1249
|
+
if (height <= 1) {
|
|
1250
|
+
return /* @__PURE__ */ jsx3(Box_default, { ...hoverProps("main"), children: /* @__PURE__ */ jsx3(TrackHeader, { role: "main", count: taskBlocks.length, width: columns }) });
|
|
1251
|
+
}
|
|
1252
|
+
const mainHeight = Math.ceil(height / 2);
|
|
1253
|
+
const subagentHeight = Math.floor(height / 2);
|
|
1254
|
+
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1255
|
+
/* @__PURE__ */ jsx3(
|
|
1256
|
+
SingleTrack,
|
|
1257
|
+
{
|
|
1258
|
+
role: "main",
|
|
1259
|
+
blocks: taskBlocks,
|
|
1260
|
+
interactive,
|
|
1261
|
+
height: mainHeight,
|
|
1262
|
+
width: columns,
|
|
1263
|
+
scrollRef: mainScrollRef,
|
|
1264
|
+
hoverProps
|
|
1265
|
+
}
|
|
1266
|
+
),
|
|
1267
|
+
/* @__PURE__ */ jsx3(
|
|
1268
|
+
SingleTrack,
|
|
1269
|
+
{
|
|
1270
|
+
role: "subagent",
|
|
1271
|
+
blocks: subagentBlocks,
|
|
1272
|
+
interactive,
|
|
1273
|
+
height: subagentHeight,
|
|
1274
|
+
width: columns,
|
|
1275
|
+
scrollRef: subagentScrollRef,
|
|
1276
|
+
hoverProps
|
|
1277
|
+
}
|
|
1278
|
+
)
|
|
1095
1279
|
] });
|
|
1096
1280
|
}
|
|
1097
|
-
function
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1281
|
+
function SingleTrack({
|
|
1282
|
+
role,
|
|
1283
|
+
blocks,
|
|
1284
|
+
interactive,
|
|
1285
|
+
height,
|
|
1286
|
+
width,
|
|
1287
|
+
scrollRef,
|
|
1288
|
+
hoverProps
|
|
1289
|
+
}) {
|
|
1290
|
+
const contentHeight = Math.max(0, height - 1);
|
|
1291
|
+
return /* @__PURE__ */ jsxs2(Box_default, { flexDirection: "column", width: "100%", height, ...hoverProps(role), children: [
|
|
1292
|
+
/* @__PURE__ */ jsx3(TrackHeader, { role, count: blocks.length, width }),
|
|
1293
|
+
contentHeight <= 0 ? null : /* @__PURE__ */ jsx3(
|
|
1294
|
+
TrackScrollBox,
|
|
1295
|
+
{
|
|
1296
|
+
ref: scrollRef,
|
|
1297
|
+
blocks,
|
|
1298
|
+
interactive,
|
|
1299
|
+
height: contentHeight,
|
|
1300
|
+
width,
|
|
1301
|
+
maxTextLines: 3
|
|
1302
|
+
}
|
|
1303
|
+
)
|
|
1101
1304
|
] });
|
|
1102
1305
|
}
|
|
1103
|
-
function
|
|
1104
|
-
|
|
1306
|
+
function TrackScrollBox({
|
|
1307
|
+
ref,
|
|
1308
|
+
blocks,
|
|
1309
|
+
interactive,
|
|
1310
|
+
height,
|
|
1311
|
+
width,
|
|
1312
|
+
maxTextLines
|
|
1313
|
+
}) {
|
|
1314
|
+
return /* @__PURE__ */ jsx3(
|
|
1315
|
+
ScrollBox_default,
|
|
1316
|
+
{
|
|
1317
|
+
...ref === void 0 ? {} : { ref },
|
|
1318
|
+
flexDirection: "column",
|
|
1319
|
+
flexShrink: 1,
|
|
1320
|
+
width: "100%",
|
|
1321
|
+
height,
|
|
1322
|
+
maxHeight: height,
|
|
1323
|
+
paddingX: 1,
|
|
1324
|
+
children: blocks.map((block) => /* @__PURE__ */ jsx3(
|
|
1325
|
+
TaskStatusLine,
|
|
1326
|
+
{
|
|
1327
|
+
block,
|
|
1328
|
+
interactive,
|
|
1329
|
+
textWidth: Math.max(3, width - 2),
|
|
1330
|
+
maxTextLines,
|
|
1331
|
+
showRoleBadge: false
|
|
1332
|
+
},
|
|
1333
|
+
block.id
|
|
1334
|
+
))
|
|
1335
|
+
}
|
|
1336
|
+
);
|
|
1337
|
+
}
|
|
1338
|
+
function TrackHeader({ role, count, width }) {
|
|
1339
|
+
const label = role === "main" ? `task plan (${count})` : `subagents (${count})`;
|
|
1340
|
+
const prefix = `\u2500\u2500 ${label} `;
|
|
1341
|
+
const line = prefix.length >= width ? prefix.slice(0, Math.max(0, width)) : `${prefix}${"\u2500".repeat(width - prefix.length)}`;
|
|
1342
|
+
return /* @__PURE__ */ jsx3(Text, { color: "ansi:white", wrap: "truncate-end", children: line });
|
|
1343
|
+
}
|
|
1344
|
+
function TrackDivider({ height }) {
|
|
1345
|
+
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
1346
|
}
|
|
1106
1347
|
|
|
1107
1348
|
// src/ui/file-diff-style.ts
|
|
@@ -1117,6 +1358,12 @@ function fileDiffLineStyle(kind) {
|
|
|
1117
1358
|
}
|
|
1118
1359
|
|
|
1119
1360
|
// src/ui/slash-completion.ts
|
|
1361
|
+
var CANDIDATE_KIND_PRIORITY = {
|
|
1362
|
+
skill: 0,
|
|
1363
|
+
plugin: 0,
|
|
1364
|
+
command: 1,
|
|
1365
|
+
tool: 2
|
|
1366
|
+
};
|
|
1120
1367
|
function slashCandidatePresentation(selected) {
|
|
1121
1368
|
return {
|
|
1122
1369
|
marker: selected ? "\u203A " : " ",
|
|
@@ -1177,6 +1424,8 @@ function deriveSlashCompletion(input, cursor, candidates, selectedIndex, visible
|
|
|
1177
1424
|
const leftPrefix = left.name.toLowerCase().startsWith(normalized);
|
|
1178
1425
|
const rightPrefix = right.name.toLowerCase().startsWith(normalized);
|
|
1179
1426
|
if (leftPrefix !== rightPrefix) return leftPrefix ? -1 : 1;
|
|
1427
|
+
const kindPriority = CANDIDATE_KIND_PRIORITY[left.kind] - CANDIDATE_KIND_PRIORITY[right.kind];
|
|
1428
|
+
if (kindPriority !== 0) return kindPriority;
|
|
1180
1429
|
return left.name.localeCompare(right.name);
|
|
1181
1430
|
});
|
|
1182
1431
|
if (items.length === 0) return null;
|
|
@@ -1651,26 +1900,118 @@ function timestamp(value) {
|
|
|
1651
1900
|
return `${year}${month}${day}-${hour}${minute}${second}`;
|
|
1652
1901
|
}
|
|
1653
1902
|
|
|
1903
|
+
// src/ui/prompt-history.ts
|
|
1904
|
+
import { createHash as createHash2, randomUUID as randomUUID2 } from "crypto";
|
|
1905
|
+
import { mkdir as mkdir2, readFile, rename as rename2, writeFile } from "fs/promises";
|
|
1906
|
+
import { join as join2, resolve as resolve2 } from "path";
|
|
1907
|
+
var HISTORY_VERSION = 1;
|
|
1908
|
+
var PromptHistoryStore = class {
|
|
1909
|
+
#directory;
|
|
1910
|
+
#path;
|
|
1911
|
+
#workspace;
|
|
1912
|
+
#maxEntries;
|
|
1913
|
+
#writeChain = Promise.resolve();
|
|
1914
|
+
constructor(options) {
|
|
1915
|
+
this.#workspace = resolve2(options.workspace);
|
|
1916
|
+
this.#maxEntries = Math.max(1, Math.floor(options.maxEntries ?? 200));
|
|
1917
|
+
this.#directory = join2(resolve2(options.home), ".flavor-code", "history");
|
|
1918
|
+
const key = createHash2("sha256").update(this.#workspace).digest("hex").slice(0, 24);
|
|
1919
|
+
this.#path = join2(this.#directory, `${key}.json`);
|
|
1920
|
+
}
|
|
1921
|
+
async load() {
|
|
1922
|
+
try {
|
|
1923
|
+
const parsed = JSON.parse(await readFile(this.#path, "utf8"));
|
|
1924
|
+
if (parsed.version !== HISTORY_VERSION || parsed.workspace !== this.#workspace || !Array.isArray(parsed.entries)) return [];
|
|
1925
|
+
return parsed.entries.filter((entry) => typeof entry === "string" && entry.trim().length > 0).slice(-this.#maxEntries);
|
|
1926
|
+
} catch {
|
|
1927
|
+
return [];
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
append(entry) {
|
|
1931
|
+
const normalized = entry.trim();
|
|
1932
|
+
if (normalized.length === 0) return this.#writeChain;
|
|
1933
|
+
this.#writeChain = this.#writeChain.catch(() => void 0).then(async () => {
|
|
1934
|
+
const entries = [...await this.load(), normalized].slice(-this.#maxEntries);
|
|
1935
|
+
await mkdir2(this.#directory, { recursive: true, mode: 448 });
|
|
1936
|
+
const temporary = join2(this.#directory, `.${randomUUID2()}.tmp`);
|
|
1937
|
+
const document = { version: HISTORY_VERSION, workspace: this.#workspace, entries };
|
|
1938
|
+
await writeFile(temporary, `${JSON.stringify(document, null, 2)}
|
|
1939
|
+
`, { encoding: "utf8", mode: 384 });
|
|
1940
|
+
await rename2(temporary, this.#path);
|
|
1941
|
+
});
|
|
1942
|
+
return this.#writeChain;
|
|
1943
|
+
}
|
|
1944
|
+
};
|
|
1945
|
+
|
|
1654
1946
|
// src/ui/app.tsx
|
|
1655
1947
|
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1656
1948
|
var HISTORY_CAP = 200;
|
|
1657
1949
|
var BUILTIN_SLASH_CANDIDATES = MVP_COMMANDS.map((name) => ({ name, description: COMMAND_DESCRIPTIONS[name] }));
|
|
1658
1950
|
var PROMPT_HORIZONTAL_PADDING = 1;
|
|
1951
|
+
function clonePromptDraft(state) {
|
|
1952
|
+
return {
|
|
1953
|
+
...state,
|
|
1954
|
+
pastedBlocks: [...state.pastedBlocks],
|
|
1955
|
+
imageAttachments: [...state.imageAttachments]
|
|
1956
|
+
};
|
|
1957
|
+
}
|
|
1958
|
+
var PromptEditHistory = class {
|
|
1959
|
+
constructor(limit = 100) {
|
|
1960
|
+
this.limit = limit;
|
|
1961
|
+
}
|
|
1962
|
+
limit;
|
|
1963
|
+
#undo = [];
|
|
1964
|
+
#redo = [];
|
|
1965
|
+
record(previous, next) {
|
|
1966
|
+
if (previous.text === next.text && previous.pastedBlocks === next.pastedBlocks && previous.imageAttachments === next.imageAttachments) return;
|
|
1967
|
+
this.#undo.push(clonePromptDraft(previous));
|
|
1968
|
+
if (this.#undo.length > this.limit) this.#undo.shift();
|
|
1969
|
+
this.#redo.length = 0;
|
|
1970
|
+
}
|
|
1971
|
+
undo(current) {
|
|
1972
|
+
const previous = this.#undo.pop();
|
|
1973
|
+
if (previous === void 0) return void 0;
|
|
1974
|
+
this.#redo.push(clonePromptDraft(current));
|
|
1975
|
+
return clonePromptDraft(previous);
|
|
1976
|
+
}
|
|
1977
|
+
redo(current) {
|
|
1978
|
+
const next = this.#redo.pop();
|
|
1979
|
+
if (next === void 0) return void 0;
|
|
1980
|
+
this.#undo.push(clonePromptDraft(current));
|
|
1981
|
+
return clonePromptDraft(next);
|
|
1982
|
+
}
|
|
1983
|
+
reset() {
|
|
1984
|
+
this.#undo.length = 0;
|
|
1985
|
+
this.#redo.length = 0;
|
|
1986
|
+
}
|
|
1987
|
+
};
|
|
1988
|
+
function promptHistoryAction(character, key, platform = process.platform) {
|
|
1989
|
+
const modifier = platform === "darwin" ? key.super : key.ctrl;
|
|
1990
|
+
if (!modifier || character.toLowerCase() !== "z") return null;
|
|
1991
|
+
return key.shift ? "redo" : "undo";
|
|
1992
|
+
}
|
|
1993
|
+
function isCopyShortcut(character, key, platform = process.platform) {
|
|
1994
|
+
return character.toLowerCase() === "c" && (platform === "darwin" ? key.super : key.ctrl);
|
|
1995
|
+
}
|
|
1996
|
+
function isPlatformShortcut(character, key, letter, platform = process.platform) {
|
|
1997
|
+
if (character.toLowerCase() !== letter.toLowerCase()) return false;
|
|
1998
|
+
return platform === "darwin" ? key.super || key.ctrl : key.ctrl;
|
|
1999
|
+
}
|
|
2000
|
+
function outputToggleShortcut(platform = process.platform) {
|
|
2001
|
+
return platform === "darwin" ? "Cmd+O" : "Ctrl+O";
|
|
2002
|
+
}
|
|
1659
2003
|
function removeLastCliImageOnBackspace(input, cursor, images) {
|
|
1660
2004
|
if (input.length === 0 && cursor === 0 && images.length > 0) {
|
|
1661
2005
|
return { handled: true, images: images.slice(0, -1) };
|
|
1662
2006
|
}
|
|
1663
2007
|
return { handled: false, images: [...images] };
|
|
1664
2008
|
}
|
|
1665
|
-
function prepareCliSubmission(input, images
|
|
2009
|
+
function prepareCliSubmission(input, images) {
|
|
1666
2010
|
const entered = input.trim();
|
|
1667
2011
|
if (entered.length === 0 && images.length === 0) return { kind: "empty" };
|
|
1668
2012
|
if (images.length > 0 && entered.startsWith("/")) {
|
|
1669
2013
|
return { kind: "error", message: "Image attachments cannot be used with slash commands." };
|
|
1670
2014
|
}
|
|
1671
|
-
if (images.length > 0 && activeSession) {
|
|
1672
|
-
return { kind: "error", message: "Images can only be attached to a new prompt." };
|
|
1673
|
-
}
|
|
1674
2015
|
const text = entered || "Analyze the attached image(s).";
|
|
1675
2016
|
if (images.length === 0) return { kind: "ready", text, displayText: text };
|
|
1676
2017
|
const content = [{ type: "text", text }, ...images];
|
|
@@ -1681,6 +2022,10 @@ function prepareCliSubmission(input, images, activeSession) {
|
|
|
1681
2022
|
content
|
|
1682
2023
|
};
|
|
1683
2024
|
}
|
|
2025
|
+
function runningEscapeAction(activeSession, pendingCount) {
|
|
2026
|
+
if (!activeSession) return null;
|
|
2027
|
+
return pendingCount > 0 ? "restore-pending" : "interrupt";
|
|
2028
|
+
}
|
|
1684
2029
|
function promptDelivery(activeSession, key) {
|
|
1685
2030
|
if (!activeSession) return "prompt";
|
|
1686
2031
|
return "followUp";
|
|
@@ -1694,52 +2039,100 @@ function resolvePromptDelivery(activeSession, key, input) {
|
|
|
1694
2039
|
}
|
|
1695
2040
|
return { delivery: promptDelivery(activeSession, key), prompt: input };
|
|
1696
2041
|
}
|
|
1697
|
-
|
|
1698
|
-
|
|
2042
|
+
function cloneQueuedPrompt(prompt) {
|
|
2043
|
+
return {
|
|
2044
|
+
text: prompt.text,
|
|
2045
|
+
displayText: prompt.displayText,
|
|
2046
|
+
...prompt.content === void 0 ? {} : { content: [...prompt.content] }
|
|
2047
|
+
};
|
|
2048
|
+
}
|
|
2049
|
+
function normalizeQueuedPrompt(prompt) {
|
|
2050
|
+
if (typeof prompt === "string") {
|
|
2051
|
+
const text2 = prompt.trim();
|
|
2052
|
+
return text2.length === 0 ? void 0 : { text: text2, displayText: text2 };
|
|
2053
|
+
}
|
|
2054
|
+
const text = prompt.text.trim();
|
|
2055
|
+
if (text.length === 0) return void 0;
|
|
2056
|
+
const displayText = prompt.displayText.trim() || text;
|
|
2057
|
+
return cloneQueuedPrompt({
|
|
2058
|
+
text,
|
|
2059
|
+
displayText,
|
|
2060
|
+
...prompt.content === void 0 ? {} : { content: prompt.content }
|
|
2061
|
+
});
|
|
2062
|
+
}
|
|
2063
|
+
function queuedPromptLabel(prompt) {
|
|
2064
|
+
const imageCount = prompt.content?.filter((block) => block.type === "image").length ?? 0;
|
|
2065
|
+
const text = prompt.text.replace(/\s+/gu, " ").trim();
|
|
2066
|
+
if (imageCount === 0) return text;
|
|
2067
|
+
return `${text} \xB7 ${imageCount} ${imageCount === 1 ? "image" : "images"}`;
|
|
2068
|
+
}
|
|
2069
|
+
function restoreQueuedPrompt(prompt) {
|
|
2070
|
+
const imageAttachments = prompt.content?.filter(
|
|
2071
|
+
(block) => block.type === "image"
|
|
2072
|
+
) ?? [];
|
|
2073
|
+
return {
|
|
2074
|
+
text: prompt.text,
|
|
2075
|
+
cursor: [...prompt.text].length,
|
|
2076
|
+
pastedBlocks: [],
|
|
2077
|
+
imageAttachments
|
|
2078
|
+
};
|
|
2079
|
+
}
|
|
2080
|
+
var PendingPromptQueue = class {
|
|
2081
|
+
#values = [];
|
|
1699
2082
|
get value() {
|
|
1700
|
-
|
|
2083
|
+
const value = this.#values.at(-1);
|
|
2084
|
+
return value === void 0 ? void 0 : cloneQueuedPrompt(value);
|
|
2085
|
+
}
|
|
2086
|
+
get values() {
|
|
2087
|
+
return this.#values.map(cloneQueuedPrompt);
|
|
2088
|
+
}
|
|
2089
|
+
get size() {
|
|
2090
|
+
return this.#values.length;
|
|
1701
2091
|
}
|
|
1702
2092
|
queue(prompt) {
|
|
1703
|
-
const value = prompt
|
|
1704
|
-
if (value
|
|
1705
|
-
this.#value
|
|
2093
|
+
const value = normalizeQueuedPrompt(prompt);
|
|
2094
|
+
if (value === void 0) return false;
|
|
2095
|
+
this.#values.push(value);
|
|
1706
2096
|
return true;
|
|
1707
2097
|
}
|
|
1708
2098
|
cancel() {
|
|
1709
|
-
const value = this.#
|
|
1710
|
-
|
|
1711
|
-
return value;
|
|
2099
|
+
const value = this.#values.pop();
|
|
2100
|
+
return value === void 0 ? void 0 : cloneQueuedPrompt(value);
|
|
1712
2101
|
}
|
|
1713
2102
|
take() {
|
|
1714
|
-
|
|
2103
|
+
const value = this.#values.shift();
|
|
2104
|
+
return value === void 0 ? void 0 : cloneQueuedPrompt(value);
|
|
1715
2105
|
}
|
|
1716
2106
|
};
|
|
1717
2107
|
async function runTerminalSubmissionChain(options) {
|
|
1718
|
-
let prompt =
|
|
1719
|
-
|
|
2108
|
+
let prompt = normalizeQueuedPrompt({
|
|
2109
|
+
text: options.initialPrompt,
|
|
2110
|
+
displayText: options.initialDisplayPrompt ?? options.initialPrompt,
|
|
2111
|
+
...options.initialContent === void 0 ? {} : { content: options.initialContent }
|
|
2112
|
+
});
|
|
1720
2113
|
while (prompt !== void 0) {
|
|
1721
|
-
options.onStart(
|
|
1722
|
-
if (
|
|
2114
|
+
options.onStart(prompt.displayText);
|
|
2115
|
+
if (prompt.content === void 0) await submitSafely(options.session, prompt.text, options.report);
|
|
2116
|
+
else {
|
|
1723
2117
|
try {
|
|
1724
|
-
await options.
|
|
2118
|
+
await options.session.submit({ text: prompt.text, content: prompt.content });
|
|
1725
2119
|
} catch (error) {
|
|
1726
2120
|
safeReport(options.report, safeUiError(error));
|
|
1727
2121
|
}
|
|
1728
|
-
} else {
|
|
1729
|
-
await submitSafely(options.session, prompt, options.report);
|
|
1730
2122
|
}
|
|
1731
2123
|
options.onFinish();
|
|
1732
2124
|
if (options.shouldContinue?.() === false) return;
|
|
1733
2125
|
prompt = options.pending.take();
|
|
1734
|
-
if (prompt !== void 0) options.onPendingConsumed();
|
|
1735
|
-
initial = false;
|
|
2126
|
+
if (prompt !== void 0) options.onPendingConsumed(options.pending.values);
|
|
1736
2127
|
}
|
|
1737
2128
|
}
|
|
1738
|
-
function classifyTerminalInput(key) {
|
|
2129
|
+
function classifyTerminalInput(key, activeSession = false) {
|
|
1739
2130
|
if (key.wheelUp) return { type: "scroll", rows: -3 };
|
|
1740
2131
|
if (key.wheelDown) return { type: "scroll", rows: 3 };
|
|
1741
2132
|
if (key.pageUp) return { type: "page", fraction: -0.5 };
|
|
1742
2133
|
if (key.pageDown) return { type: "page", fraction: 0.5 };
|
|
2134
|
+
if (activeSession && key.upArrow) return { type: "scroll", rows: -3 };
|
|
2135
|
+
if (activeSession && key.downArrow) return { type: "scroll", rows: 3 };
|
|
1743
2136
|
if (key.upArrow) return { type: "history", direction: "up" };
|
|
1744
2137
|
if (key.downArrow) return { type: "history", direction: "down" };
|
|
1745
2138
|
return null;
|
|
@@ -1755,6 +2148,9 @@ function completionKeyAction(key, menuOpen) {
|
|
|
1755
2148
|
function slashKeyAction(key, completion) {
|
|
1756
2149
|
return completionKeyAction(key, completion !== null);
|
|
1757
2150
|
}
|
|
2151
|
+
function canShowSlashCompletion(_activeSession, input, dismissedInput, blockedByModal) {
|
|
2152
|
+
return dismissedInput !== input && !blockedByModal;
|
|
2153
|
+
}
|
|
1758
2154
|
function appRuntimeOptions(props, output, onApprovalChange) {
|
|
1759
2155
|
return {
|
|
1760
2156
|
workspace: props.workspace,
|
|
@@ -1779,6 +2175,8 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1779
2175
|
const [clipboardNotice, setClipboardNotice] = useState2();
|
|
1780
2176
|
const [history, setHistory] = useState2([]);
|
|
1781
2177
|
const [historyCursor, setHistoryCursor] = useState2(0);
|
|
2178
|
+
const [approvalExpanded, setApprovalExpanded] = useState2(false);
|
|
2179
|
+
const [expandedOutput, setExpandedOutput] = useState2(false);
|
|
1782
2180
|
const [promptCursor, setPromptCursor] = useState2(0);
|
|
1783
2181
|
const [slashCandidates, setSlashCandidates] = useState2(
|
|
1784
2182
|
() => buildSlashCandidates(BUILTIN_SLASH_CANDIDATES, [], [])
|
|
@@ -1788,7 +2186,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1788
2186
|
const [mentionCandidates, setMentionCandidates] = useState2([]);
|
|
1789
2187
|
const [mentionSelection, setMentionSelection] = useState2(0);
|
|
1790
2188
|
const [dismissedMentionInput, setDismissedMentionInput] = useState2();
|
|
1791
|
-
const [
|
|
2189
|
+
const [pendingPrompts, setPendingPrompts] = useState2([]);
|
|
1792
2190
|
const [revision, setRevision] = useState2(0);
|
|
1793
2191
|
const [ideContext, setIdeContext] = useState2();
|
|
1794
2192
|
const [questionIndex, setQuestionIndex] = useState2(0);
|
|
@@ -1799,11 +2197,12 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1799
2197
|
const [updateTo, setUpdateTo] = useState2();
|
|
1800
2198
|
const [transcript, dispatch] = useReducer(transcriptReducer, void 0, createTranscriptState);
|
|
1801
2199
|
const scrollRef = useRef4(null);
|
|
1802
|
-
const
|
|
1803
|
-
const
|
|
2200
|
+
const mainTaskScrollRef = useRef4(null);
|
|
2201
|
+
const subagentTaskScrollRef = useRef4(null);
|
|
2202
|
+
const hoveredTaskTrack = useRef4(null);
|
|
1804
2203
|
const runtimeRef = useRef4(void 0);
|
|
1805
2204
|
const pendingPromptRef = useRef4(void 0);
|
|
1806
|
-
pendingPromptRef.current ??= new
|
|
2205
|
+
pendingPromptRef.current ??= new PendingPromptQueue();
|
|
1807
2206
|
const closing = useRef4(false);
|
|
1808
2207
|
const clipboardBusy = useRef4(false);
|
|
1809
2208
|
const textBuf = useRef4({ pending: "", timer: null });
|
|
@@ -1814,8 +2213,15 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1814
2213
|
pastedBlocks,
|
|
1815
2214
|
imageAttachments
|
|
1816
2215
|
});
|
|
2216
|
+
const promptEditHistory = useRef4(new PromptEditHistory());
|
|
2217
|
+
const historyRef = useRef4([]);
|
|
2218
|
+
const historyCursorRef = useRef4(0);
|
|
2219
|
+
const historyDraftRef = useRef4(void 0);
|
|
2220
|
+
const reverseSearchRef = useRef4(void 0);
|
|
2221
|
+
const promptHistoryStoreRef = useRef4(void 0);
|
|
2222
|
+
promptHistoryStoreRef.current ??= new PromptHistoryStore({ home: home ?? homedir(), workspace, maxEntries: HISTORY_CAP });
|
|
1817
2223
|
promptDraftRef.current = { text: input, cursor: promptCursor, pastedBlocks, imageAttachments };
|
|
1818
|
-
const commitPromptDraft = (next) => {
|
|
2224
|
+
const commitPromptDraft = (next, recordHistory = true) => {
|
|
1819
2225
|
const current = promptDraftRef.current;
|
|
1820
2226
|
const resolved = {
|
|
1821
2227
|
text: next.text,
|
|
@@ -1823,6 +2229,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1823
2229
|
pastedBlocks: next.pastedBlocks ?? current.pastedBlocks,
|
|
1824
2230
|
imageAttachments: next.imageAttachments ?? current.imageAttachments
|
|
1825
2231
|
};
|
|
2232
|
+
if (recordHistory) promptEditHistory.current.record(current, resolved);
|
|
1826
2233
|
promptDraftRef.current = resolved;
|
|
1827
2234
|
setInput(resolved.text);
|
|
1828
2235
|
setPromptCursor(resolved.cursor);
|
|
@@ -1830,6 +2237,19 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1830
2237
|
if (next.imageAttachments !== void 0) setImageAttachments(next.imageAttachments);
|
|
1831
2238
|
};
|
|
1832
2239
|
useTerminalTitle("Flavor Code");
|
|
2240
|
+
useEffect3(() => {
|
|
2241
|
+
let disposed = false;
|
|
2242
|
+
void promptHistoryStoreRef.current.load().then((entries) => {
|
|
2243
|
+
if (disposed) return;
|
|
2244
|
+
historyRef.current = entries;
|
|
2245
|
+
historyCursorRef.current = entries.length;
|
|
2246
|
+
setHistory(entries);
|
|
2247
|
+
setHistoryCursor(entries.length);
|
|
2248
|
+
});
|
|
2249
|
+
return () => {
|
|
2250
|
+
disposed = true;
|
|
2251
|
+
};
|
|
2252
|
+
}, [workspace, home]);
|
|
1833
2253
|
const flushText = () => {
|
|
1834
2254
|
flushThinking();
|
|
1835
2255
|
const t = textBuf.current;
|
|
@@ -2043,8 +2463,14 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2043
2463
|
setQuestionAnswers({});
|
|
2044
2464
|
setCustomQuestionActive(false);
|
|
2045
2465
|
}, [questions]);
|
|
2466
|
+
useEffect3(() => setApprovalExpanded(false), [approval?.id]);
|
|
2046
2467
|
const derivedSlashCompletion = deriveSlashCompletion(input, promptCursor, slashCandidates, slashSelection);
|
|
2047
|
-
const slashCompletion =
|
|
2468
|
+
const slashCompletion = canShowSlashCompletion(
|
|
2469
|
+
transcript.active !== void 0,
|
|
2470
|
+
input,
|
|
2471
|
+
dismissedSlashInput,
|
|
2472
|
+
approval !== void 0 || questions !== void 0
|
|
2473
|
+
) ? derivedSlashCompletion : null;
|
|
2048
2474
|
const derivedMentionCompletion = slashCompletion === null ? deriveMentionCompletion(input, promptCursor, mentionCandidates, mentionSelection) : null;
|
|
2049
2475
|
const mentionCompletion = dismissedMentionInput === input || transcript.active !== void 0 || approval !== void 0 || questions !== void 0 ? null : derivedMentionCompletion;
|
|
2050
2476
|
const completedTokenLength = completedSlashTokenLength(input, slashCandidates, slashCompletion !== null);
|
|
@@ -2062,11 +2488,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2062
2488
|
setClipboardNotice("Flavor is still starting; try pasting the image again.");
|
|
2063
2489
|
return;
|
|
2064
2490
|
}
|
|
2065
|
-
if (
|
|
2066
|
-
setClipboardNotice("Images can only be attached to a new prompt.");
|
|
2067
|
-
return;
|
|
2068
|
-
}
|
|
2069
|
-
if (imageAttachments.length >= DEFAULT_MAX_IMAGES) {
|
|
2491
|
+
if (promptDraftRef.current.imageAttachments.length >= DEFAULT_MAX_IMAGES) {
|
|
2070
2492
|
setClipboardNotice(`A prompt can contain at most ${DEFAULT_MAX_IMAGES} images.`);
|
|
2071
2493
|
return;
|
|
2072
2494
|
}
|
|
@@ -2080,14 +2502,15 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2080
2502
|
return;
|
|
2081
2503
|
}
|
|
2082
2504
|
const incomingBytes = Buffer.byteLength(attachment.dataBase64, "base64");
|
|
2083
|
-
const
|
|
2505
|
+
const currentDraft = promptDraftRef.current;
|
|
2506
|
+
const currentBytes = currentDraft.imageAttachments.reduce((sum, image) => sum + image.bytes, 0);
|
|
2084
2507
|
if (currentBytes + incomingBytes > DEFAULT_MAX_TOTAL_IMAGE_BYTES) {
|
|
2085
2508
|
throw new Error(`Image attachments exceed the maximum total size of ${DEFAULT_MAX_TOTAL_IMAGE_BYTES} bytes`);
|
|
2086
2509
|
}
|
|
2087
2510
|
const [stored] = await new SessionAssetStore({ workspace }).store(active.sessionId, [attachment]);
|
|
2088
2511
|
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)}`);
|
|
2512
|
+
commitPromptDraft({ ...currentDraft, imageAttachments: [...currentDraft.imageAttachments, stored] });
|
|
2513
|
+
setClipboardNotice(`Added [Image #${currentDraft.imageAttachments.length + 1}] ${stored.name ?? basename3(stored.source.path)}`);
|
|
2091
2514
|
} catch (error) {
|
|
2092
2515
|
setClipboardNotice(safeUiError(error));
|
|
2093
2516
|
} finally {
|
|
@@ -2095,9 +2518,17 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2095
2518
|
}
|
|
2096
2519
|
};
|
|
2097
2520
|
use_input_default((character, key, event) => {
|
|
2098
|
-
const terminalAction = classifyTerminalInput(
|
|
2521
|
+
const terminalAction = classifyTerminalInput(
|
|
2522
|
+
key,
|
|
2523
|
+
transcript.active !== void 0 && slashCompletion === null && mentionCompletion === null
|
|
2524
|
+
);
|
|
2099
2525
|
if (terminalAction?.type === "scroll") {
|
|
2100
|
-
const scroll = selectWheelScrollTarget(
|
|
2526
|
+
const scroll = selectWheelScrollTarget(
|
|
2527
|
+
scrollRef.current,
|
|
2528
|
+
mainTaskScrollRef.current,
|
|
2529
|
+
subagentTaskScrollRef.current,
|
|
2530
|
+
hoveredTaskTrack.current
|
|
2531
|
+
);
|
|
2101
2532
|
if (scroll !== null) {
|
|
2102
2533
|
if (terminalAction.rows < 0) scrollUp(scroll, -terminalAction.rows);
|
|
2103
2534
|
else scrollDown(scroll, terminalAction.rows);
|
|
@@ -2110,12 +2541,17 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2110
2541
|
return;
|
|
2111
2542
|
}
|
|
2112
2543
|
const active = runtimeRef.current;
|
|
2113
|
-
if (
|
|
2114
|
-
if (selection.hasSelection())
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2544
|
+
if (isCopyShortcut(character, key)) {
|
|
2545
|
+
if (selection.hasSelection()) selection.copySelection();
|
|
2546
|
+
else if (process.platform !== "darwin") interrupt();
|
|
2547
|
+
return;
|
|
2548
|
+
}
|
|
2549
|
+
if (key.ctrl && character.toLowerCase() === "c") {
|
|
2550
|
+
interrupt();
|
|
2551
|
+
return;
|
|
2552
|
+
}
|
|
2553
|
+
if (isPlatformShortcut(character, key, "o")) {
|
|
2554
|
+
setExpandedOutput((value) => !value);
|
|
2119
2555
|
return;
|
|
2120
2556
|
}
|
|
2121
2557
|
if (shouldReadClipboardImage(character, key, event.keypress.isPasted)) {
|
|
@@ -2123,8 +2559,15 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2123
2559
|
return;
|
|
2124
2560
|
}
|
|
2125
2561
|
if (active?.approvals.pending !== void 0) {
|
|
2562
|
+
if (character.toLowerCase() === "v") setApprovalExpanded((value) => !value);
|
|
2126
2563
|
if (character.toLowerCase() === "y") active.approvals.resolve("once");
|
|
2127
2564
|
if (character.toLowerCase() === "n" || key.escape) active.approvals.resolve("deny");
|
|
2565
|
+
if (character.toLowerCase() === "e") {
|
|
2566
|
+
void Promise.resolve(active.services.setPermissionMode("acceptEdits")).then(() => {
|
|
2567
|
+
setRevision((value) => value + 1);
|
|
2568
|
+
setClipboardNotice("Permission mode changed to acceptEdits; review the current request, then allow or deny it.");
|
|
2569
|
+
}).catch((error) => dispatch({ type: "submit-error", message: safeUiError(error) }));
|
|
2570
|
+
}
|
|
2128
2571
|
if (character.toLowerCase() === "a") {
|
|
2129
2572
|
if (isDestructiveTool(active.approvals.pending.tool)) {
|
|
2130
2573
|
active.approvals.resolve("once");
|
|
@@ -2188,23 +2631,35 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2188
2631
|
setPromptCursor(0);
|
|
2189
2632
|
return;
|
|
2190
2633
|
}
|
|
2191
|
-
if (!key.ctrl && !key.meta && character) setCustomQuestionActive(true);
|
|
2634
|
+
if (!key.ctrl && !key.meta && !key.super && character) setCustomQuestionActive(true);
|
|
2192
2635
|
else return;
|
|
2193
2636
|
}
|
|
2194
2637
|
}
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2638
|
+
const historyAction = promptHistoryAction(character, key);
|
|
2639
|
+
if (historyAction !== null) {
|
|
2640
|
+
const draft = promptDraftRef.current;
|
|
2641
|
+
const restored = historyAction === "undo" ? promptEditHistory.current.undo(draft) : promptEditHistory.current.redo(draft);
|
|
2642
|
+
if (restored !== void 0) commitPromptDraft(restored, false);
|
|
2643
|
+
setSlashSelection(0);
|
|
2644
|
+
setDismissedSlashInput(void 0);
|
|
2645
|
+
setMentionSelection(0);
|
|
2646
|
+
setDismissedMentionInput(void 0);
|
|
2647
|
+
return;
|
|
2648
|
+
}
|
|
2649
|
+
if (isPlatformShortcut(character, key, "r")) {
|
|
2650
|
+
const draft = promptDraftRef.current;
|
|
2651
|
+
if (historyCursorRef.current === historyRef.current.length) historyDraftRef.current = clonePromptDraft(draft);
|
|
2652
|
+
const previous = reverseSearchRef.current;
|
|
2653
|
+
const query = previous?.query ?? draft.text;
|
|
2654
|
+
const match = reverseSearchHistory(historyRef.current, query, previous?.cursor ?? historyRef.current.length);
|
|
2655
|
+
if (match !== void 0) {
|
|
2656
|
+
reverseSearchRef.current = { query, cursor: match.cursor };
|
|
2657
|
+
historyCursorRef.current = match.cursor;
|
|
2658
|
+
setHistoryCursor(match.cursor);
|
|
2659
|
+
commitPromptDraft({ text: match.input, cursor: match.promptCursor, pastedBlocks: [], imageAttachments: [] }, false);
|
|
2660
|
+
setClipboardNotice(`reverse-i-search: ${query || "(latest)"} \xB7 Ctrl/Cmd+R for older match`);
|
|
2661
|
+
} else setClipboardNotice(`No older history match for ${query || "(latest)"}.`);
|
|
2662
|
+
return;
|
|
2208
2663
|
}
|
|
2209
2664
|
const menuAction = slashKeyAction(key, slashCompletion);
|
|
2210
2665
|
if (menuAction?.type === "select" && slashCompletion !== null) {
|
|
@@ -2215,8 +2670,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2215
2670
|
const selected = slashCompletion.items[slashCompletion.selectedIndex];
|
|
2216
2671
|
if (selected !== void 0) {
|
|
2217
2672
|
const next = completeSlashSelection(input, promptCursor, selected.name);
|
|
2218
|
-
|
|
2219
|
-
setPromptCursor(next.cursor);
|
|
2673
|
+
commitPromptDraft(next);
|
|
2220
2674
|
setDismissedSlashInput(next.text);
|
|
2221
2675
|
}
|
|
2222
2676
|
return;
|
|
@@ -2239,9 +2693,28 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2239
2693
|
setDismissedMentionInput(input);
|
|
2240
2694
|
return;
|
|
2241
2695
|
}
|
|
2696
|
+
if (key.escape && transcript.active !== void 0) {
|
|
2697
|
+
const escapeAction = runningEscapeAction(true, pendingPromptRef.current.size);
|
|
2698
|
+
if (escapeAction === "restore-pending") {
|
|
2699
|
+
const restored = pendingPromptRef.current.cancel();
|
|
2700
|
+
if (restored === void 0) return;
|
|
2701
|
+
setPendingPrompts([...pendingPromptRef.current.values]);
|
|
2702
|
+
const restoredDraft = restoreQueuedPrompt(restored);
|
|
2703
|
+
promptEditHistory.current.reset();
|
|
2704
|
+
commitPromptDraft(restoredDraft, false);
|
|
2705
|
+
setClipboardNotice(restoredDraft.imageAttachments.length === 0 ? void 0 : `Restored ${restoredDraft.imageAttachments.length} pending ${restoredDraft.imageAttachments.length === 1 ? "image" : "images"}.`);
|
|
2706
|
+
setSlashSelection(0);
|
|
2707
|
+
setDismissedSlashInput(void 0);
|
|
2708
|
+
setMentionSelection(0);
|
|
2709
|
+
setDismissedMentionInput(void 0);
|
|
2710
|
+
return;
|
|
2711
|
+
}
|
|
2712
|
+
interrupt();
|
|
2713
|
+
return;
|
|
2714
|
+
}
|
|
2242
2715
|
if (key.return) {
|
|
2243
2716
|
const images = [...imageAttachments];
|
|
2244
|
-
const prepared = prepareCliSubmission(input, images
|
|
2717
|
+
const prepared = prepareCliSubmission(input, images);
|
|
2245
2718
|
if (prepared.kind === "empty" || active === void 0) return;
|
|
2246
2719
|
if (prepared.kind === "error") {
|
|
2247
2720
|
setClipboardNotice(prepared.message);
|
|
@@ -2251,16 +2724,27 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2251
2724
|
const { delivery, prompt } = resolvePromptDelivery(transcript.active !== void 0, key, submittedText);
|
|
2252
2725
|
if (!prompt) return;
|
|
2253
2726
|
if (delivery === "followUp" && transcript.active !== void 0) {
|
|
2254
|
-
if (!pendingPromptRef.current.queue(
|
|
2255
|
-
|
|
2727
|
+
if (!pendingPromptRef.current.queue({
|
|
2728
|
+
text: prompt,
|
|
2729
|
+
displayText: prepared.content === void 0 ? prompt : prepared.displayText,
|
|
2730
|
+
...prepared.content === void 0 ? {} : { content: prepared.content }
|
|
2731
|
+
})) return;
|
|
2732
|
+
setPendingPrompts([...pendingPromptRef.current.values]);
|
|
2256
2733
|
}
|
|
2257
2734
|
scrollRef.current?.scrollToBottom();
|
|
2258
|
-
|
|
2259
|
-
|
|
2735
|
+
const nextHistory = [...historyRef.current, submittedText].slice(-HISTORY_CAP);
|
|
2736
|
+
historyRef.current = nextHistory;
|
|
2737
|
+
historyCursorRef.current = nextHistory.length;
|
|
2738
|
+
historyDraftRef.current = void 0;
|
|
2739
|
+
reverseSearchRef.current = void 0;
|
|
2740
|
+
setHistory(nextHistory);
|
|
2741
|
+
setHistoryCursor(nextHistory.length);
|
|
2742
|
+
void promptHistoryStoreRef.current.append(submittedText).catch(() => void 0);
|
|
2260
2743
|
setInput("");
|
|
2261
2744
|
setPastedBlocks([]);
|
|
2262
2745
|
setImageAttachments([]);
|
|
2263
2746
|
promptDraftRef.current = { text: "", cursor: 0, pastedBlocks: [], imageAttachments: [] };
|
|
2747
|
+
promptEditHistory.current.reset();
|
|
2264
2748
|
setClipboardNotice(void 0);
|
|
2265
2749
|
setPromptCursor(0);
|
|
2266
2750
|
setSlashSelection(0);
|
|
@@ -2273,15 +2757,12 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2273
2757
|
initialPrompt: prompt,
|
|
2274
2758
|
...prepared.content === void 0 ? {} : {
|
|
2275
2759
|
initialDisplayPrompt: prepared.displayText,
|
|
2276
|
-
|
|
2277
|
-
text,
|
|
2278
|
-
content: prepared.content
|
|
2279
|
-
})
|
|
2760
|
+
initialContent: prepared.content
|
|
2280
2761
|
},
|
|
2281
2762
|
pending: pendingPromptRef.current,
|
|
2282
2763
|
onStart: (next) => dispatch({ type: "submit", prompt: next }),
|
|
2283
2764
|
onFinish: () => dispatch({ type: "finish" }),
|
|
2284
|
-
onPendingConsumed: () =>
|
|
2765
|
+
onPendingConsumed: (remaining) => setPendingPrompts([...remaining]),
|
|
2285
2766
|
report: (error) => dispatch({ type: "submit-error", message: error }),
|
|
2286
2767
|
shouldContinue: () => !closing.current
|
|
2287
2768
|
});
|
|
@@ -2295,11 +2776,11 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2295
2776
|
return;
|
|
2296
2777
|
}
|
|
2297
2778
|
if (key.backspace) {
|
|
2779
|
+
reverseSearchRef.current = void 0;
|
|
2298
2780
|
const draft = promptDraftRef.current;
|
|
2299
2781
|
const imageEdit = removeLastCliImageOnBackspace(draft.text, draft.cursor, draft.imageAttachments);
|
|
2300
2782
|
if (imageEdit.handled) {
|
|
2301
|
-
|
|
2302
|
-
promptDraftRef.current = { ...draft, imageAttachments: imageEdit.images };
|
|
2783
|
+
commitPromptDraft({ ...draft, imageAttachments: imageEdit.images });
|
|
2303
2784
|
setClipboardNotice(imageEdit.images.length === 0 ? "Removed image attachment." : `Removed image attachment; ${imageEdit.images.length} remaining.`);
|
|
2304
2785
|
return;
|
|
2305
2786
|
}
|
|
@@ -2314,6 +2795,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2314
2795
|
setMentionSelection(0);
|
|
2315
2796
|
setDismissedMentionInput(void 0);
|
|
2316
2797
|
} else if (key.delete) {
|
|
2798
|
+
reverseSearchRef.current = void 0;
|
|
2317
2799
|
const draft = promptDraftRef.current;
|
|
2318
2800
|
commitPromptDraft({ ...editPrompt({ text: draft.text, cursor: draft.cursor }, { type: "delete" }), pastedBlocks: draft.pastedBlocks });
|
|
2319
2801
|
setSlashSelection(0);
|
|
@@ -2321,28 +2803,31 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2321
2803
|
setMentionSelection(0);
|
|
2322
2804
|
setDismissedMentionInput(void 0);
|
|
2323
2805
|
} else if (key.leftArrow) {
|
|
2806
|
+
reverseSearchRef.current = void 0;
|
|
2324
2807
|
const draft = promptDraftRef.current;
|
|
2325
2808
|
commitPromptDraft({ ...editPrompt({ text: draft.text, cursor: draft.cursor }, { type: "left" }), pastedBlocks: draft.pastedBlocks });
|
|
2326
2809
|
} else if (key.rightArrow) {
|
|
2810
|
+
reverseSearchRef.current = void 0;
|
|
2327
2811
|
const draft = promptDraftRef.current;
|
|
2328
2812
|
commitPromptDraft({ ...editPrompt({ text: draft.text, cursor: draft.cursor }, { type: "right" }), pastedBlocks: draft.pastedBlocks });
|
|
2329
|
-
} else if (terminalAction?.type === "history" &&
|
|
2330
|
-
const next =
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2813
|
+
} else if (terminalAction?.type === "history" && historyRef.current.length) {
|
|
2814
|
+
const next = navigatePromptHistory({
|
|
2815
|
+
history: historyRef.current,
|
|
2816
|
+
cursor: historyCursorRef.current,
|
|
2817
|
+
current: promptDraftRef.current,
|
|
2818
|
+
...historyDraftRef.current === void 0 ? {} : { stashed: historyDraftRef.current }
|
|
2819
|
+
}, terminalAction.direction);
|
|
2820
|
+
historyCursorRef.current = next.cursor;
|
|
2821
|
+
historyDraftRef.current = next.stashed;
|
|
2822
|
+
reverseSearchRef.current = void 0;
|
|
2339
2823
|
setHistoryCursor(next.cursor);
|
|
2340
|
-
commitPromptDraft(
|
|
2824
|
+
commitPromptDraft(next.draft, false);
|
|
2341
2825
|
setSlashSelection(0);
|
|
2342
2826
|
setDismissedSlashInput(void 0);
|
|
2343
2827
|
setMentionSelection(0);
|
|
2344
2828
|
setDismissedMentionInput(void 0);
|
|
2345
|
-
} else if (!key.ctrl && !key.meta && character) {
|
|
2829
|
+
} else if (!key.ctrl && !key.meta && !key.super && character) {
|
|
2830
|
+
reverseSearchRef.current = void 0;
|
|
2346
2831
|
const draft = promptDraftRef.current;
|
|
2347
2832
|
const nextPastedBlocks = /[\r\n]/u.test(character) ? [...draft.pastedBlocks, { id: draft.pastedBlocks.length + 1, text: character }] : draft.pastedBlocks;
|
|
2348
2833
|
commitPromptDraft({
|
|
@@ -2388,17 +2873,20 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2388
2873
|
...ideContext === void 0 ? {} : { ideContext },
|
|
2389
2874
|
completedSlashTokenLength: completedTokenLength,
|
|
2390
2875
|
scrollRef,
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2876
|
+
mainTaskScrollRef,
|
|
2877
|
+
subagentTaskScrollRef,
|
|
2878
|
+
onTaskPanelHoverChange: (track) => {
|
|
2879
|
+
hoveredTaskTrack.current = track;
|
|
2394
2880
|
},
|
|
2395
2881
|
...slashCompletion === null ? {} : { completion: slashCompletion },
|
|
2396
2882
|
...mentionCompletion === null ? {} : { mentionCompletion, onMentionSelect: selectMention },
|
|
2397
2883
|
...approval === void 0 ? {} : { approval },
|
|
2884
|
+
approvalExpanded,
|
|
2885
|
+
expandedOutput,
|
|
2398
2886
|
...questions === void 0 ? {} : { questions },
|
|
2399
2887
|
memoryReviews,
|
|
2400
2888
|
memoryAutoDismissSeconds,
|
|
2401
|
-
|
|
2889
|
+
pendingPrompts,
|
|
2402
2890
|
questionIndex,
|
|
2403
2891
|
questionAnswers,
|
|
2404
2892
|
customQuestionActive
|
|
@@ -2433,6 +2921,46 @@ var CLI_VISIBLE_TURN_LIMIT = 40;
|
|
|
2433
2921
|
var CLI_VISIBLE_BLOCK_LIMIT = 320;
|
|
2434
2922
|
var CLI_VISIBLE_BLOCKS_PER_TURN = 80;
|
|
2435
2923
|
var CLI_VISIBLE_TEXT_CHARS = 32e3;
|
|
2924
|
+
function approvalDetailLines(approval) {
|
|
2925
|
+
const lines = [];
|
|
2926
|
+
if (approval.agent !== "main") lines.push(`Agent: ${approval.agent}`);
|
|
2927
|
+
if (approval.command !== void 0) {
|
|
2928
|
+
const command = [approval.command, ...(approval.args ?? []).map(formatApprovalArgument)].join(" ");
|
|
2929
|
+
lines.push(`Command: ${command}`);
|
|
2930
|
+
} else if (approval.args !== void 0 && approval.args.length > 0) {
|
|
2931
|
+
lines.push(`Arguments: ${approval.args.map(formatApprovalArgument).join(" ")}`);
|
|
2932
|
+
}
|
|
2933
|
+
if (approval.cwd !== void 0) lines.push(`Working directory: ${approval.cwd}`);
|
|
2934
|
+
for (const [index, path] of (approval.paths ?? []).entries()) {
|
|
2935
|
+
lines.push(`${approval.paths.length === 1 ? "Path" : `Path ${index + 1}`}: ${path}`);
|
|
2936
|
+
}
|
|
2937
|
+
const inputLines = approvalInputLines(approval.input);
|
|
2938
|
+
if (inputLines.length > 0) lines.push("Tool input:", ...inputLines.map((line) => ` ${line}`));
|
|
2939
|
+
if (lines.length === 0) lines.push("No additional parameters were supplied.");
|
|
2940
|
+
return lines;
|
|
2941
|
+
}
|
|
2942
|
+
function formatApprovalArgument(value) {
|
|
2943
|
+
return /\s|["']/u.test(value) ? JSON.stringify(value) : value;
|
|
2944
|
+
}
|
|
2945
|
+
function approvalInputLines(input) {
|
|
2946
|
+
if (input === void 0) return [];
|
|
2947
|
+
if (typeof input !== "object" || input === null || Array.isArray(input)) return [formatApprovalValue(input)];
|
|
2948
|
+
const lines = [];
|
|
2949
|
+
for (const [key, value] of Object.entries(input)) {
|
|
2950
|
+
if (typeof value === "string" && /[\r\n]/u.test(value)) {
|
|
2951
|
+
lines.push(`${key}: |`, ...value.replace(/\r\n/gu, "\n").split("\n").map((line) => ` ${line}`));
|
|
2952
|
+
} else lines.push(`${key}: ${formatApprovalValue(value)}`);
|
|
2953
|
+
}
|
|
2954
|
+
return lines;
|
|
2955
|
+
}
|
|
2956
|
+
function formatApprovalValue(value) {
|
|
2957
|
+
if (typeof value === "string") return value;
|
|
2958
|
+
try {
|
|
2959
|
+
return JSON.stringify(value);
|
|
2960
|
+
} catch {
|
|
2961
|
+
return String(value);
|
|
2962
|
+
}
|
|
2963
|
+
}
|
|
2436
2964
|
function boundedCliDisplayText(text, limit = CLI_VISIBLE_TEXT_CHARS) {
|
|
2437
2965
|
if (text.length <= limit) return text;
|
|
2438
2966
|
const half = Math.floor((limit - 80) / 2);
|
|
@@ -2511,8 +3039,10 @@ function TerminalLayout({
|
|
|
2511
3039
|
columns,
|
|
2512
3040
|
rows = 24,
|
|
2513
3041
|
activeSession,
|
|
2514
|
-
|
|
3042
|
+
pendingPrompts = [],
|
|
2515
3043
|
approval,
|
|
3044
|
+
approvalExpanded = false,
|
|
3045
|
+
expandedOutput = false,
|
|
2516
3046
|
questions,
|
|
2517
3047
|
memoryReviews = [],
|
|
2518
3048
|
memoryAutoDismissSeconds = 0,
|
|
@@ -2524,12 +3054,14 @@ function TerminalLayout({
|
|
|
2524
3054
|
onMentionSelect,
|
|
2525
3055
|
completedSlashTokenLength: tokenLength = 0,
|
|
2526
3056
|
scrollRef,
|
|
2527
|
-
|
|
3057
|
+
mainTaskScrollRef,
|
|
3058
|
+
subagentTaskScrollRef,
|
|
2528
3059
|
onTaskPanelHoverChange,
|
|
2529
3060
|
onPromptCursorChange,
|
|
2530
3061
|
ideContext
|
|
2531
3062
|
}) {
|
|
2532
3063
|
const dividerWidth = Math.max(1, columns - 1);
|
|
3064
|
+
const outputShortcut = outputToggleShortcut();
|
|
2533
3065
|
const showWelcome = completed.length === 0 && active === void 0;
|
|
2534
3066
|
const activeCompletion = completion ?? mentionCompletion;
|
|
2535
3067
|
const menuRows = activeCompletion === void 0 ? 0 : Math.min(6, activeCompletion.items.length - activeCompletion.windowStart);
|
|
@@ -2542,11 +3074,12 @@ function TerminalLayout({
|
|
|
2542
3074
|
(block) => !(block.kind === "status" && block.task !== void 0)
|
|
2543
3075
|
)
|
|
2544
3076
|
};
|
|
2545
|
-
const activeWithoutTasks = rawActiveWithoutTasks === void 0 ? void 0 : boundedCliTurn(rawActiveWithoutTasks).turn;
|
|
2546
|
-
const completedWindow = cliTranscriptWindow(completed);
|
|
3077
|
+
const activeWithoutTasks = rawActiveWithoutTasks === void 0 ? void 0 : expandedOutput ? rawActiveWithoutTasks : boundedCliTurn(rawActiveWithoutTasks).turn;
|
|
3078
|
+
const completedWindow = expandedOutput ? { turns: completed, hiddenTurns: 0, hiddenBlocks: 0 } : cliTranscriptWindow(completed);
|
|
2547
3079
|
const questionRows = questions === void 0 ? 0 : 4 + (questions[questionIndex]?.options.length ?? 0) + questions.length * 2;
|
|
2548
3080
|
const memoryReviewRows = memoryReviews.length === 0 ? 0 : 5;
|
|
2549
|
-
const
|
|
3081
|
+
const approvalRows = approval === void 0 ? 0 : 3 + (approvalExpanded ? approvalDetailLines(approval).length : 0);
|
|
3082
|
+
const fixedBottomRows = approvalRows + questionRows + memoryReviewRows + menuRows + (pendingPrompts.length === 0 ? 0 : 1) + imageAttachments.length + (clipboardNotice === void 0 ? 0 : 1) + 2;
|
|
2550
3083
|
const taskPanelRows = taskPanelViewportRows(rows, fixedBottomRows, activeTaskBlocks.length > 0);
|
|
2551
3084
|
const availableBottomRows = Math.max(1, rows - taskPanelRows - 1);
|
|
2552
3085
|
const bottomMaxRows = Math.min(availableBottomRows, Math.max(Math.floor(rows / 2), fixedBottomRows + 1));
|
|
@@ -2565,15 +3098,17 @@ function TerminalLayout({
|
|
|
2565
3098
|
completedWindow.hiddenTurns,
|
|
2566
3099
|
" earlier turns and ",
|
|
2567
3100
|
completedWindow.hiddenBlocks,
|
|
2568
|
-
" output items
|
|
3101
|
+
" output items hidden \xB7 ",
|
|
3102
|
+
outputShortcut,
|
|
3103
|
+
" expand all"
|
|
2569
3104
|
] }) : null,
|
|
2570
3105
|
completedWindow.turns.map((turn, index) => /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", children: [
|
|
2571
3106
|
index > 0 ? /* @__PURE__ */ jsx5(TurnSeparator, { width: columns }) : null,
|
|
2572
|
-
/* @__PURE__ */ jsx5(TurnView, { turn, interactive: false, workspaceName })
|
|
3107
|
+
/* @__PURE__ */ jsx5(TurnView, { turn, interactive: false, workspaceName, expandedOutput })
|
|
2573
3108
|
] }, turn.id)),
|
|
2574
3109
|
activeWithoutTasks === void 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", children: [
|
|
2575
3110
|
completedWindow.turns.length > 0 ? /* @__PURE__ */ jsx5(TurnSeparator, { width: columns }) : null,
|
|
2576
|
-
/* @__PURE__ */ jsx5(TurnView, { turn: activeWithoutTasks, interactive: activeSession, workspaceName })
|
|
3111
|
+
/* @__PURE__ */ jsx5(TurnView, { turn: activeWithoutTasks, interactive: activeSession, workspaceName, expandedOutput })
|
|
2577
3112
|
] })
|
|
2578
3113
|
] }),
|
|
2579
3114
|
/* @__PURE__ */ jsx5(
|
|
@@ -2583,7 +3118,8 @@ function TerminalLayout({
|
|
|
2583
3118
|
interactive: activeSession,
|
|
2584
3119
|
maxHeight: taskPanelRows,
|
|
2585
3120
|
columns,
|
|
2586
|
-
...
|
|
3121
|
+
...mainTaskScrollRef === void 0 ? {} : { mainScrollRef: mainTaskScrollRef },
|
|
3122
|
+
...subagentTaskScrollRef === void 0 ? {} : { subagentScrollRef: subagentTaskScrollRef },
|
|
2587
3123
|
...onTaskPanelHoverChange === void 0 ? {} : { onHoverChange: onTaskPanelHoverChange }
|
|
2588
3124
|
}
|
|
2589
3125
|
),
|
|
@@ -2597,18 +3133,30 @@ function TerminalLayout({
|
|
|
2597
3133
|
"\u2502 ",
|
|
2598
3134
|
approval.reason ?? "This action needs permission."
|
|
2599
3135
|
] }),
|
|
2600
|
-
|
|
2601
|
-
"\
|
|
3136
|
+
approvalExpanded ? approvalDetailLines(approval).map((line, index) => /* @__PURE__ */ jsxs4(Text, { color: "magentaBright", wrap: "truncate-end", children: [
|
|
3137
|
+
"\u2502 ",
|
|
3138
|
+
line
|
|
3139
|
+
] }, `${approval.id}:detail:${index}`)) : null,
|
|
3140
|
+
isDestructiveTool(approval.tool) || approval.allowAlways === false ? /* @__PURE__ */ jsxs4(Text, { bold: true, color: "magenta", children: [
|
|
3141
|
+
"\u2514\u2500 ",
|
|
3142
|
+
/* @__PURE__ */ jsx5(Text, { color: "cyan", children: "v" }),
|
|
3143
|
+
"=details / ",
|
|
2602
3144
|
/* @__PURE__ */ jsx5(Text, { color: "green", children: "y" }),
|
|
2603
3145
|
"=once / ",
|
|
3146
|
+
/* @__PURE__ */ jsx5(Text, { color: "cyan", children: "e" }),
|
|
3147
|
+
"=accept edits / ",
|
|
2604
3148
|
/* @__PURE__ */ jsx5(Text, { color: "red", children: "n" }),
|
|
2605
3149
|
"=deny"
|
|
2606
3150
|
] }) : /* @__PURE__ */ jsxs4(Text, { bold: true, color: "magenta", children: [
|
|
2607
|
-
"\u2514\u2500
|
|
3151
|
+
"\u2514\u2500 ",
|
|
3152
|
+
/* @__PURE__ */ jsx5(Text, { color: "cyan", children: "v" }),
|
|
3153
|
+
"=details / ",
|
|
2608
3154
|
/* @__PURE__ */ jsx5(Text, { color: "green", children: "y" }),
|
|
2609
3155
|
"=once / ",
|
|
2610
3156
|
/* @__PURE__ */ jsx5(Text, { color: "yellow", children: "a" }),
|
|
2611
3157
|
"=same-type / ",
|
|
3158
|
+
/* @__PURE__ */ jsx5(Text, { color: "cyan", children: "e" }),
|
|
3159
|
+
"=accept edits / ",
|
|
2612
3160
|
/* @__PURE__ */ jsx5(Text, { color: "red", children: "n" }),
|
|
2613
3161
|
"=deny"
|
|
2614
3162
|
] })
|
|
@@ -2617,10 +3165,12 @@ function TerminalLayout({
|
|
|
2617
3165
|
memoryReviews.length === 0 ? null : /* @__PURE__ */ jsx5(MemoryReviewCards, { reviews: memoryReviews, autoDismissSeconds: memoryAutoDismissSeconds }),
|
|
2618
3166
|
completion === void 0 ? null : /* @__PURE__ */ jsx5(SlashMenu, { completion }),
|
|
2619
3167
|
mentionCompletion === void 0 ? null : /* @__PURE__ */ jsx5(MentionMenu, { completion: mentionCompletion, ...onMentionSelect === void 0 ? {} : { onSelect: onMentionSelect } }),
|
|
2620
|
-
|
|
2621
|
-
"Pending
|
|
2622
|
-
|
|
2623
|
-
" \xB7
|
|
3168
|
+
pendingPrompts.length === 0 ? null : /* @__PURE__ */ jsxs4(Text, { color: "yellow", wrap: "truncate-end", children: [
|
|
3169
|
+
"Pending (",
|
|
3170
|
+
pendingPrompts.length,
|
|
3171
|
+
") \xB7 ",
|
|
3172
|
+
queuedPromptLabel(pendingPrompts.at(-1)),
|
|
3173
|
+
" \xB7 Esc edit latest"
|
|
2624
3174
|
] }),
|
|
2625
3175
|
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: "\u2500".repeat(dividerWidth) }),
|
|
2626
3176
|
imageAttachments.map((image, index) => /* @__PURE__ */ jsxs4(Text, { color: "cyan", wrap: "truncate-end", children: [
|
|
@@ -2645,7 +3195,7 @@ function TerminalLayout({
|
|
|
2645
3195
|
/* @__PURE__ */ jsx5(
|
|
2646
3196
|
FooterStatus,
|
|
2647
3197
|
{
|
|
2648
|
-
hint: activeSession ? "Ctrl+C cancel \xB7 Enter queue \xB7
|
|
3198
|
+
hint: activeSession ? `Esc ${pendingPrompts.length > 0 ? "edit latest" : "stop"} \xB7 Ctrl+C cancel \xB7 Enter queue \xB7 Ctrl/Cmd+R history \xB7 ${outputShortcut} ${expandedOutput ? "collapse" : "expand"} output` : 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 \u2191\u2193/Ctrl/Cmd+R history \xB7 ${outputShortcut} ${expandedOutput ? "collapse" : "expand"} output \xB7 Ctrl+C exit`,
|
|
2649
3199
|
...ideContext === void 0 ? {} : { ideContext }
|
|
2650
3200
|
}
|
|
2651
3201
|
)
|
|
@@ -2749,6 +3299,7 @@ function SlashMenu({ completion }) {
|
|
|
2749
3299
|
return /* @__PURE__ */ jsxs4(Text, { ...presentation.rowStyle, wrap: "truncate-end", children: [
|
|
2750
3300
|
presentation.marker,
|
|
2751
3301
|
/* @__PURE__ */ jsx5(HighlightedName, { name: candidate.name, query: completion.query, matchStyle: presentation.matchStyle }),
|
|
3302
|
+
candidate.kind === "skill" || candidate.kind === "plugin" ? /* @__PURE__ */ jsx5(Text, { color: candidate.kind === "skill" ? "magentaBright" : "cyanBright", children: ` ${candidate.kind}` }) : null,
|
|
2752
3303
|
candidate.description === void 0 ? null : /* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` ${candidate.description}` })
|
|
2753
3304
|
] }, `${candidate.kind}:${candidate.name}`);
|
|
2754
3305
|
}) });
|
|
@@ -2804,8 +3355,10 @@ function jumpScroll(scroll, delta) {
|
|
|
2804
3355
|
scroll.scrollTo(Math.max(0, target));
|
|
2805
3356
|
}
|
|
2806
3357
|
}
|
|
2807
|
-
function selectWheelScrollTarget(transcript,
|
|
2808
|
-
|
|
3358
|
+
function selectWheelScrollTarget(transcript, mainTasks, subagentTasks, hoveredTrack) {
|
|
3359
|
+
if (hoveredTrack === "main" && mainTasks !== null) return mainTasks;
|
|
3360
|
+
if (hoveredTrack === "subagent" && subagentTasks !== null) return subagentTasks;
|
|
3361
|
+
return transcript;
|
|
2809
3362
|
}
|
|
2810
3363
|
function taskPanelViewportRows(rows, reservedBottomRows, hasTasks) {
|
|
2811
3364
|
if (!hasTasks) return 0;
|
|
@@ -2829,12 +3382,13 @@ function TurnSeparator({ width }) {
|
|
|
2829
3382
|
function TurnView({
|
|
2830
3383
|
turn,
|
|
2831
3384
|
interactive,
|
|
2832
|
-
workspaceName
|
|
3385
|
+
workspaceName,
|
|
3386
|
+
expandedOutput
|
|
2833
3387
|
}) {
|
|
2834
3388
|
if (turn.kind === "compaction") {
|
|
2835
3389
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", marginBottom: 1, borderStyle: "round", borderColor: "ansi:yellowBright", paddingX: 1, children: [
|
|
2836
3390
|
/* @__PURE__ */ jsx5(Text, { color: "ansi:yellowBright", bold: true, children: turn.prompt }),
|
|
2837
|
-
turn.blocks.map((block, index) => block.kind === "status" ? /* @__PURE__ */ jsx5(StatusBlockView, { block, interactive, workspaceName }, block.id) : /* @__PURE__ */ jsx5(Box_default, { children: /* @__PURE__ */ jsx5(AssistantText, { text: block.text }) }, `${turn.id}-text-${index}`))
|
|
3391
|
+
turn.blocks.map((block, index) => block.kind === "status" ? /* @__PURE__ */ jsx5(StatusBlockView, { block, interactive, workspaceName, expandedOutput }, block.id) : /* @__PURE__ */ jsx5(Box_default, { children: /* @__PURE__ */ jsx5(AssistantText, { text: block.text }) }, `${turn.id}-text-${index}`))
|
|
2838
3392
|
] });
|
|
2839
3393
|
}
|
|
2840
3394
|
if (turn.source?.kind === "pal") {
|
|
@@ -2851,7 +3405,7 @@ function TurnView({
|
|
|
2851
3405
|
] }),
|
|
2852
3406
|
/* @__PURE__ */ jsx5(Text, { color: "ansi:whiteBright", children: turn.prompt })
|
|
2853
3407
|
] }),
|
|
2854
|
-
/* @__PURE__ */ jsx5(Box_default, { flexDirection: "column", paddingLeft: 2, marginTop: 1, children: turn.blocks.map((block, index) => block.kind === "status" ? /* @__PURE__ */ jsx5(StatusBlockView, { block, interactive, workspaceName }, block.id) : /* @__PURE__ */ jsx5(Box_default, { marginBottom: 1, children: /* @__PURE__ */ jsx5(AssistantText, { text: block.text }) }, `${turn.id}-text-${index}`)) })
|
|
3408
|
+
/* @__PURE__ */ jsx5(Box_default, { flexDirection: "column", paddingLeft: 2, marginTop: 1, children: turn.blocks.map((block, index) => block.kind === "status" ? /* @__PURE__ */ jsx5(StatusBlockView, { block, interactive, workspaceName, expandedOutput }, block.id) : /* @__PURE__ */ jsx5(Box_default, { marginBottom: 1, children: /* @__PURE__ */ jsx5(AssistantText, { text: block.text }) }, `${turn.id}-text-${index}`)) })
|
|
2855
3409
|
] });
|
|
2856
3410
|
}
|
|
2857
3411
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", marginBottom: 1, children: [
|
|
@@ -2862,7 +3416,7 @@ function TurnView({
|
|
|
2862
3416
|
turn.prompt
|
|
2863
3417
|
] })
|
|
2864
3418
|
] }),
|
|
2865
|
-
/* @__PURE__ */ jsx5(Box_default, { flexDirection: "column", paddingLeft: 2, marginTop: 1, children: turn.blocks.map((block, index) => block.kind === "status" ? /* @__PURE__ */ jsx5(StatusBlockView, { block, interactive, workspaceName }, block.id) : /* @__PURE__ */ jsx5(Box_default, { marginBottom: 1, children: /* @__PURE__ */ jsx5(AssistantText, { text: block.text }) }, `${turn.id}-text-${index}`)) })
|
|
3419
|
+
/* @__PURE__ */ jsx5(Box_default, { flexDirection: "column", paddingLeft: 2, marginTop: 1, children: turn.blocks.map((block, index) => block.kind === "status" ? /* @__PURE__ */ jsx5(StatusBlockView, { block, interactive, workspaceName, expandedOutput }, block.id) : /* @__PURE__ */ jsx5(Box_default, { marginBottom: 1, children: /* @__PURE__ */ jsx5(AssistantText, { text: block.text }) }, `${turn.id}-text-${index}`)) })
|
|
2866
3420
|
] });
|
|
2867
3421
|
}
|
|
2868
3422
|
var DIFF_CONTENT = fileDiffLineStyle("context").contentColor;
|
|
@@ -3041,11 +3595,12 @@ function PromptLine({
|
|
|
3041
3595
|
function StatusBlockView({
|
|
3042
3596
|
block,
|
|
3043
3597
|
interactive,
|
|
3044
|
-
workspaceName
|
|
3598
|
+
workspaceName,
|
|
3599
|
+
expandedOutput
|
|
3045
3600
|
}) {
|
|
3046
3601
|
const visibleBlock = cliToolTitle(block);
|
|
3047
3602
|
const outcome = cliToolOutcome(block);
|
|
3048
|
-
const primary = visibleBlock.activity === "model" || visibleBlock.task !== void 0 ? /* @__PURE__ */ jsx5(TaskStatusLine, { block: visibleBlock, interactive }) : visibleBlock.state === "completed" && visibleBlock.presentation !== void 0 ? /* @__PURE__ */ jsx5(ToolPresentationView, { presentation: visibleBlock.presentation, workspaceName }) : /* @__PURE__ */ jsx5(StatusLine, { block: visibleBlock, interactive });
|
|
3603
|
+
const primary = visibleBlock.activity === "model" || visibleBlock.task !== void 0 ? /* @__PURE__ */ jsx5(TaskStatusLine, { block: visibleBlock, interactive }) : visibleBlock.state === "completed" && visibleBlock.presentation !== void 0 ? /* @__PURE__ */ jsx5(ToolPresentationView, { presentation: visibleBlock.presentation, workspaceName, expandedOutput }) : /* @__PURE__ */ jsx5(StatusLine, { block: visibleBlock, interactive });
|
|
3049
3604
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", children: [
|
|
3050
3605
|
primary,
|
|
3051
3606
|
outcome === void 0 ? null : /* @__PURE__ */ jsx5(Box_default, { paddingLeft: 2, children: /* @__PURE__ */ jsxs4(Text, { dimColor: true, children: [
|
|
@@ -3057,13 +3612,14 @@ function StatusBlockView({
|
|
|
3057
3612
|
}
|
|
3058
3613
|
function ToolPresentationView({
|
|
3059
3614
|
presentation,
|
|
3060
|
-
workspaceName
|
|
3615
|
+
workspaceName,
|
|
3616
|
+
expandedOutput
|
|
3061
3617
|
}) {
|
|
3062
|
-
if (presentation.kind === "changeset") return /* @__PURE__ */ jsx5(ChangeSetPresentationView, { presentation, workspaceName });
|
|
3618
|
+
if (presentation.kind === "changeset") return /* @__PURE__ */ jsx5(ChangeSetPresentationView, { presentation, workspaceName, expanded: expandedOutput });
|
|
3063
3619
|
if (presentation.kind === "file-change") return /* @__PURE__ */ jsx5(FileDiffView, { presentation });
|
|
3064
|
-
if (presentation.kind === "terminal") return /* @__PURE__ */ jsx5(CommandPresentationView, { presentation });
|
|
3065
|
-
if (presentation.kind === "web") return /* @__PURE__ */ jsx5(WebPresentationView, { presentation });
|
|
3066
|
-
if (presentation.kind === "job") return /* @__PURE__ */ jsx5(JobPresentationView, { presentation });
|
|
3620
|
+
if (presentation.kind === "terminal") return /* @__PURE__ */ jsx5(CommandPresentationView, { presentation, expanded: expandedOutput });
|
|
3621
|
+
if (presentation.kind === "web") return /* @__PURE__ */ jsx5(WebPresentationView, { presentation, expanded: expandedOutput });
|
|
3622
|
+
if (presentation.kind === "job") return /* @__PURE__ */ jsx5(JobPresentationView, { presentation, expanded: expandedOutput });
|
|
3067
3623
|
return /* @__PURE__ */ jsx5(Box_default, { paddingLeft: 2, children: /* @__PURE__ */ jsxs4(Text, { children: [
|
|
3068
3624
|
presentation.title,
|
|
3069
3625
|
presentation.summary ? ` \xB7 ${presentation.summary}` : ""
|
|
@@ -3073,9 +3629,10 @@ var CLI_CHANGESET_FILE_LIMIT = 8;
|
|
|
3073
3629
|
var CHANGESET_TONE = "#b99bf8";
|
|
3074
3630
|
function ChangeSetPresentationView({
|
|
3075
3631
|
presentation,
|
|
3076
|
-
workspaceName
|
|
3632
|
+
workspaceName,
|
|
3633
|
+
expanded
|
|
3077
3634
|
}) {
|
|
3078
|
-
const visibleFiles = presentation.files.slice(0, CLI_CHANGESET_FILE_LIMIT);
|
|
3635
|
+
const visibleFiles = expanded ? presentation.files : presentation.files.slice(0, CLI_CHANGESET_FILE_LIMIT);
|
|
3079
3636
|
const added = presentation.files.reduce((total, file) => total + file.added, 0);
|
|
3080
3637
|
const removed = presentation.files.reduce((total, file) => total + file.removed, 0);
|
|
3081
3638
|
const fileLabel = presentation.files.length === 1 ? "FILE" : "FILES";
|
|
@@ -3142,18 +3699,22 @@ function workspaceRelativePath(value, workspaceName) {
|
|
|
3142
3699
|
if (normalized.toLocaleLowerCase().startsWith(rootPrefix.toLocaleLowerCase())) return normalized.slice(rootPrefix.length);
|
|
3143
3700
|
return normalized;
|
|
3144
3701
|
}
|
|
3145
|
-
var CLI_COMMAND_OUTPUT_LINE_LIMIT =
|
|
3702
|
+
var CLI_COMMAND_OUTPUT_LINE_LIMIT = 8;
|
|
3146
3703
|
function CommandPresentationView({
|
|
3147
|
-
presentation
|
|
3704
|
+
presentation,
|
|
3705
|
+
expanded
|
|
3148
3706
|
}) {
|
|
3149
3707
|
const state = presentation.state ?? commandState(presentation.exitCode);
|
|
3150
3708
|
const tone = jobStateColor(state);
|
|
3151
3709
|
const label = presentation.variant === "terminal" ? "TERMINAL" : "COMMAND";
|
|
3152
3710
|
const hasStdout = jobOutputLines(presentation.stdout ?? "").length > 0;
|
|
3153
3711
|
const hasStderr = jobOutputLines(presentation.stderr ?? "").length > 0;
|
|
3154
|
-
const
|
|
3712
|
+
const collapsedPerStreamLimit = hasStdout && hasStderr ? Math.floor(CLI_COMMAND_OUTPUT_LINE_LIMIT / 2) : CLI_COMMAND_OUTPUT_LINE_LIMIT;
|
|
3713
|
+
const perStreamLimit = expanded ? Number.POSITIVE_INFINITY : collapsedPerStreamLimit;
|
|
3155
3714
|
const stdout = boundedCommandLines(presentation.stdout ?? "", perStreamLimit);
|
|
3156
3715
|
const stderr = boundedCommandLines(presentation.stderr ?? "", perStreamLimit);
|
|
3716
|
+
const collapsible = stdout.total > collapsedPerStreamLimit || stderr.total > collapsedPerStreamLimit;
|
|
3717
|
+
const shortcut = outputToggleShortcut();
|
|
3157
3718
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
3158
3719
|
/* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
3159
3720
|
/* @__PURE__ */ jsx5(Text, { color: tone, children: "\u250C\u2500 " }),
|
|
@@ -3175,7 +3736,15 @@ function CommandPresentationView({
|
|
|
3175
3736
|
] }),
|
|
3176
3737
|
/* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
3177
3738
|
/* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2514\u2500 " }),
|
|
3178
|
-
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: commandFooter(presentation, state) })
|
|
3739
|
+
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: commandFooter(presentation, state) }),
|
|
3740
|
+
collapsible ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
3741
|
+
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: " \xB7 " }),
|
|
3742
|
+
/* @__PURE__ */ jsx5(Text, { color: "ansi:cyanBright", children: shortcut }),
|
|
3743
|
+
/* @__PURE__ */ jsxs4(Text, { dimColor: true, children: [
|
|
3744
|
+
" ",
|
|
3745
|
+
expanded ? "collapse" : "expand"
|
|
3746
|
+
] })
|
|
3747
|
+
] }) : null
|
|
3179
3748
|
] })
|
|
3180
3749
|
] });
|
|
3181
3750
|
}
|
|
@@ -3189,7 +3758,8 @@ function CommandOutputSection({
|
|
|
3189
3758
|
/* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
3190
3759
|
/* @__PURE__ */ jsx5(Text, { color: tone, children: "\u251C\u2500 " }),
|
|
3191
3760
|
/* @__PURE__ */ jsx5(Text, { color: error ? "#e06c50" : tone, bold: true, children: label }),
|
|
3192
|
-
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` \xB7 ${value.total} ${value.total === 1 ? "LINE" : "LINES"}` })
|
|
3761
|
+
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` \xB7 ${value.total} ${value.total === 1 ? "LINE" : "LINES"}` }),
|
|
3762
|
+
value.hidden === 0 ? null : /* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` \xB7 ${value.head.length + value.tail.length} SHOWN` })
|
|
3193
3763
|
] }),
|
|
3194
3764
|
value.head.map((line, index) => /* @__PURE__ */ jsx5(CommandOutputLine, { line, tone, error }, `head:${index}`)),
|
|
3195
3765
|
value.hidden === 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
@@ -3214,8 +3784,8 @@ function CommandOutputLine({ line, tone, error }) {
|
|
|
3214
3784
|
function boundedCommandLines(output, limit) {
|
|
3215
3785
|
const lines = jobOutputLines(output);
|
|
3216
3786
|
if (lines.length <= limit) return { total: lines.length, head: lines, tail: [], hidden: 0 };
|
|
3217
|
-
const headCount = Math.ceil(limit
|
|
3218
|
-
const tailCount = Math.
|
|
3787
|
+
const headCount = Math.ceil(limit * 0.625);
|
|
3788
|
+
const tailCount = Math.max(0, limit - headCount);
|
|
3219
3789
|
return {
|
|
3220
3790
|
total: lines.length,
|
|
3221
3791
|
head: lines.slice(0, headCount),
|
|
@@ -3234,7 +3804,8 @@ function commandFooter(presentation, state) {
|
|
|
3234
3804
|
}
|
|
3235
3805
|
var CLI_WEB_RESULT_LIMIT = 5;
|
|
3236
3806
|
function WebPresentationView({
|
|
3237
|
-
presentation
|
|
3807
|
+
presentation,
|
|
3808
|
+
expanded
|
|
3238
3809
|
}) {
|
|
3239
3810
|
const items = presentation.items ?? [];
|
|
3240
3811
|
if (presentation.items === void 0) return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
@@ -3252,7 +3823,7 @@ function WebPresentationView({
|
|
|
3252
3823
|
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: "Page content added to context" })
|
|
3253
3824
|
] })
|
|
3254
3825
|
] });
|
|
3255
|
-
const visibleItems = items.slice(0, CLI_WEB_RESULT_LIMIT);
|
|
3826
|
+
const visibleItems = expanded ? items : items.slice(0, CLI_WEB_RESULT_LIMIT);
|
|
3256
3827
|
const query = presentation.title.replace(/^Search:\s*/iu, "").trim();
|
|
3257
3828
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
3258
3829
|
/* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
@@ -3298,13 +3869,14 @@ function compactWebSource(value) {
|
|
|
3298
3869
|
var CLI_JOB_LOG_LINE_LIMIT = 12;
|
|
3299
3870
|
var CLI_JOB_LIST_LIMIT = 8;
|
|
3300
3871
|
function JobPresentationView({
|
|
3301
|
-
presentation
|
|
3872
|
+
presentation,
|
|
3873
|
+
expanded
|
|
3302
3874
|
}) {
|
|
3303
|
-
if (presentation.action === "list") return /* @__PURE__ */ jsx5(JobListPresentationView, { presentation });
|
|
3875
|
+
if (presentation.action === "list") return /* @__PURE__ */ jsx5(JobListPresentationView, { presentation, expanded });
|
|
3304
3876
|
const state = presentation.state ?? "running";
|
|
3305
3877
|
const tone = jobStateColor(state);
|
|
3306
3878
|
const lines = jobOutputLines(presentation.output ?? "");
|
|
3307
|
-
const visibleLines = lines.slice(-CLI_JOB_LOG_LINE_LIMIT);
|
|
3879
|
+
const visibleLines = expanded ? lines : lines.slice(-CLI_JOB_LOG_LINE_LIMIT);
|
|
3308
3880
|
const hiddenLines = lines.length - visibleLines.length;
|
|
3309
3881
|
const showLog = presentation.action === "read" || presentation.action === "kill" || lines.length > 0;
|
|
3310
3882
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
@@ -3353,10 +3925,11 @@ function JobPresentationView({
|
|
|
3353
3925
|
] });
|
|
3354
3926
|
}
|
|
3355
3927
|
function JobListPresentationView({
|
|
3356
|
-
presentation
|
|
3928
|
+
presentation,
|
|
3929
|
+
expanded
|
|
3357
3930
|
}) {
|
|
3358
3931
|
const jobs = presentation.jobs ?? [];
|
|
3359
|
-
const visibleJobs = jobs.slice(0, CLI_JOB_LIST_LIMIT);
|
|
3932
|
+
const visibleJobs = expanded ? jobs : jobs.slice(0, CLI_JOB_LIST_LIMIT);
|
|
3360
3933
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
3361
3934
|
/* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
3362
3935
|
/* @__PURE__ */ jsx5(Text, { color: "#d7a657", children: "\u250C\u2500 " }),
|
|
@@ -3624,6 +4197,22 @@ function navigateHistory(state, direction) {
|
|
|
3624
4197
|
const input = state.history[cursor] ?? "";
|
|
3625
4198
|
return { cursor, input, promptCursor: [...input].length };
|
|
3626
4199
|
}
|
|
4200
|
+
function navigatePromptHistory(state, direction) {
|
|
4201
|
+
const stashed = direction === "up" && state.cursor === state.history.length ? clonePromptDraft(state.current) : state.stashed;
|
|
4202
|
+
const next = navigateHistory(state, direction);
|
|
4203
|
+
const draft = next.cursor === state.history.length && stashed !== void 0 ? clonePromptDraft(stashed) : { text: next.input, cursor: next.promptCursor, pastedBlocks: [], imageAttachments: [] };
|
|
4204
|
+
return { cursor: next.cursor, draft, ...stashed === void 0 ? {} : { stashed } };
|
|
4205
|
+
}
|
|
4206
|
+
function reverseSearchHistory(history, query, before = history.length) {
|
|
4207
|
+
const needle = query.toLocaleLowerCase();
|
|
4208
|
+
for (let cursor = Math.min(history.length, before) - 1; cursor >= 0; cursor -= 1) {
|
|
4209
|
+
const input = history[cursor];
|
|
4210
|
+
if (needle.length === 0 || input.toLocaleLowerCase().includes(needle)) {
|
|
4211
|
+
return { cursor, input, promptCursor: [...input].length };
|
|
4212
|
+
}
|
|
4213
|
+
}
|
|
4214
|
+
return void 0;
|
|
4215
|
+
}
|
|
3627
4216
|
async function submitSafely(session, prompt, report) {
|
|
3628
4217
|
try {
|
|
3629
4218
|
await session.submit(prompt);
|
|
@@ -3682,12 +4271,15 @@ export {
|
|
|
3682
4271
|
FooterStatus,
|
|
3683
4272
|
HISTORY_CAP,
|
|
3684
4273
|
MentionMenu,
|
|
4274
|
+
PendingPromptQueue,
|
|
4275
|
+
PromptEditHistory,
|
|
3685
4276
|
PromptLine,
|
|
3686
4277
|
SHUTDOWN_TIMEOUT_MS,
|
|
3687
|
-
SinglePendingPrompt,
|
|
3688
4278
|
TerminalLayout,
|
|
3689
4279
|
appRuntimeOptions,
|
|
4280
|
+
approvalDetailLines,
|
|
3690
4281
|
boundedCliTurn,
|
|
4282
|
+
canShowSlashCompletion,
|
|
3691
4283
|
classifyTerminalInput,
|
|
3692
4284
|
cliTranscriptWindow,
|
|
3693
4285
|
closeAndDisposeRuntime,
|
|
@@ -3695,14 +4287,23 @@ export {
|
|
|
3695
4287
|
editPrompt,
|
|
3696
4288
|
editPromptWithPastedBlocks,
|
|
3697
4289
|
ideFooterPresentation,
|
|
4290
|
+
isCopyShortcut,
|
|
4291
|
+
isPlatformShortcut,
|
|
3698
4292
|
navigateHistory,
|
|
4293
|
+
navigatePromptHistory,
|
|
4294
|
+
outputToggleShortcut,
|
|
3699
4295
|
pastedDraftPresentation,
|
|
3700
4296
|
prepareCliSubmission,
|
|
3701
4297
|
promptCursorFromClick,
|
|
3702
4298
|
promptDelivery,
|
|
4299
|
+
promptHistoryAction,
|
|
4300
|
+
queuedPromptLabel,
|
|
3703
4301
|
removeLastCliImageOnBackspace,
|
|
3704
4302
|
resolvePromptDelivery,
|
|
4303
|
+
restoreQueuedPrompt,
|
|
4304
|
+
reverseSearchHistory,
|
|
3705
4305
|
runTerminalSubmissionChain,
|
|
4306
|
+
runningEscapeAction,
|
|
3706
4307
|
selectWheelScrollTarget,
|
|
3707
4308
|
shutdownRuntime,
|
|
3708
4309
|
slashKeyAction,
|