flavor-code 1.4.0-beta.9 → 1.4.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-XEW4ES4R.js → app-4YRKE7VI.js} +754 -176
- package/dist/{chunk-EXOSMO57.js → chunk-7YFHRORG.js} +2 -3
- package/dist/{chunk-D4OD67V6.js → chunk-FAORPP4F.js} +1 -1
- package/dist/{chunk-CWCYXOH6.js → chunk-O2PC44GY.js} +204 -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 +206 -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,115 @@ 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
|
+
}
|
|
1659
2000
|
function removeLastCliImageOnBackspace(input, cursor, images) {
|
|
1660
2001
|
if (input.length === 0 && cursor === 0 && images.length > 0) {
|
|
1661
2002
|
return { handled: true, images: images.slice(0, -1) };
|
|
1662
2003
|
}
|
|
1663
2004
|
return { handled: false, images: [...images] };
|
|
1664
2005
|
}
|
|
1665
|
-
function prepareCliSubmission(input, images
|
|
2006
|
+
function prepareCliSubmission(input, images) {
|
|
1666
2007
|
const entered = input.trim();
|
|
1667
2008
|
if (entered.length === 0 && images.length === 0) return { kind: "empty" };
|
|
1668
2009
|
if (images.length > 0 && entered.startsWith("/")) {
|
|
1669
2010
|
return { kind: "error", message: "Image attachments cannot be used with slash commands." };
|
|
1670
2011
|
}
|
|
1671
|
-
if (images.length > 0 && activeSession) {
|
|
1672
|
-
return { kind: "error", message: "Images can only be attached to a new prompt." };
|
|
1673
|
-
}
|
|
1674
2012
|
const text = entered || "Analyze the attached image(s).";
|
|
1675
2013
|
if (images.length === 0) return { kind: "ready", text, displayText: text };
|
|
1676
2014
|
const content = [{ type: "text", text }, ...images];
|
|
@@ -1681,6 +2019,10 @@ function prepareCliSubmission(input, images, activeSession) {
|
|
|
1681
2019
|
content
|
|
1682
2020
|
};
|
|
1683
2021
|
}
|
|
2022
|
+
function runningEscapeAction(activeSession, pendingCount) {
|
|
2023
|
+
if (!activeSession) return null;
|
|
2024
|
+
return pendingCount > 0 ? "restore-pending" : "interrupt";
|
|
2025
|
+
}
|
|
1684
2026
|
function promptDelivery(activeSession, key) {
|
|
1685
2027
|
if (!activeSession) return "prompt";
|
|
1686
2028
|
return "followUp";
|
|
@@ -1694,45 +2036,91 @@ function resolvePromptDelivery(activeSession, key, input) {
|
|
|
1694
2036
|
}
|
|
1695
2037
|
return { delivery: promptDelivery(activeSession, key), prompt: input };
|
|
1696
2038
|
}
|
|
1697
|
-
|
|
1698
|
-
|
|
2039
|
+
function cloneQueuedPrompt(prompt) {
|
|
2040
|
+
return {
|
|
2041
|
+
text: prompt.text,
|
|
2042
|
+
displayText: prompt.displayText,
|
|
2043
|
+
...prompt.content === void 0 ? {} : { content: [...prompt.content] }
|
|
2044
|
+
};
|
|
2045
|
+
}
|
|
2046
|
+
function normalizeQueuedPrompt(prompt) {
|
|
2047
|
+
if (typeof prompt === "string") {
|
|
2048
|
+
const text2 = prompt.trim();
|
|
2049
|
+
return text2.length === 0 ? void 0 : { text: text2, displayText: text2 };
|
|
2050
|
+
}
|
|
2051
|
+
const text = prompt.text.trim();
|
|
2052
|
+
if (text.length === 0) return void 0;
|
|
2053
|
+
const displayText = prompt.displayText.trim() || text;
|
|
2054
|
+
return cloneQueuedPrompt({
|
|
2055
|
+
text,
|
|
2056
|
+
displayText,
|
|
2057
|
+
...prompt.content === void 0 ? {} : { content: prompt.content }
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
function queuedPromptLabel(prompt) {
|
|
2061
|
+
const imageCount = prompt.content?.filter((block) => block.type === "image").length ?? 0;
|
|
2062
|
+
const text = prompt.text.replace(/\s+/gu, " ").trim();
|
|
2063
|
+
if (imageCount === 0) return text;
|
|
2064
|
+
return `${text} \xB7 ${imageCount} ${imageCount === 1 ? "image" : "images"}`;
|
|
2065
|
+
}
|
|
2066
|
+
function restoreQueuedPrompt(prompt) {
|
|
2067
|
+
const imageAttachments = prompt.content?.filter(
|
|
2068
|
+
(block) => block.type === "image"
|
|
2069
|
+
) ?? [];
|
|
2070
|
+
return {
|
|
2071
|
+
text: prompt.text,
|
|
2072
|
+
cursor: [...prompt.text].length,
|
|
2073
|
+
pastedBlocks: [],
|
|
2074
|
+
imageAttachments
|
|
2075
|
+
};
|
|
2076
|
+
}
|
|
2077
|
+
var PendingPromptQueue = class {
|
|
2078
|
+
#values = [];
|
|
1699
2079
|
get value() {
|
|
1700
|
-
|
|
2080
|
+
const value = this.#values.at(-1);
|
|
2081
|
+
return value === void 0 ? void 0 : cloneQueuedPrompt(value);
|
|
2082
|
+
}
|
|
2083
|
+
get values() {
|
|
2084
|
+
return this.#values.map(cloneQueuedPrompt);
|
|
2085
|
+
}
|
|
2086
|
+
get size() {
|
|
2087
|
+
return this.#values.length;
|
|
1701
2088
|
}
|
|
1702
2089
|
queue(prompt) {
|
|
1703
|
-
const value = prompt
|
|
1704
|
-
if (value
|
|
1705
|
-
this.#value
|
|
2090
|
+
const value = normalizeQueuedPrompt(prompt);
|
|
2091
|
+
if (value === void 0) return false;
|
|
2092
|
+
this.#values.push(value);
|
|
1706
2093
|
return true;
|
|
1707
2094
|
}
|
|
1708
2095
|
cancel() {
|
|
1709
|
-
const value = this.#
|
|
1710
|
-
|
|
1711
|
-
return value;
|
|
2096
|
+
const value = this.#values.pop();
|
|
2097
|
+
return value === void 0 ? void 0 : cloneQueuedPrompt(value);
|
|
1712
2098
|
}
|
|
1713
2099
|
take() {
|
|
1714
|
-
|
|
2100
|
+
const value = this.#values.shift();
|
|
2101
|
+
return value === void 0 ? void 0 : cloneQueuedPrompt(value);
|
|
1715
2102
|
}
|
|
1716
2103
|
};
|
|
1717
2104
|
async function runTerminalSubmissionChain(options) {
|
|
1718
|
-
let prompt =
|
|
1719
|
-
|
|
2105
|
+
let prompt = normalizeQueuedPrompt({
|
|
2106
|
+
text: options.initialPrompt,
|
|
2107
|
+
displayText: options.initialDisplayPrompt ?? options.initialPrompt,
|
|
2108
|
+
...options.initialContent === void 0 ? {} : { content: options.initialContent }
|
|
2109
|
+
});
|
|
1720
2110
|
while (prompt !== void 0) {
|
|
1721
|
-
options.onStart(
|
|
1722
|
-
if (
|
|
2111
|
+
options.onStart(prompt.displayText);
|
|
2112
|
+
if (prompt.content === void 0) await submitSafely(options.session, prompt.text, options.report);
|
|
2113
|
+
else {
|
|
1723
2114
|
try {
|
|
1724
|
-
await options.
|
|
2115
|
+
await options.session.submit({ text: prompt.text, content: prompt.content });
|
|
1725
2116
|
} catch (error) {
|
|
1726
2117
|
safeReport(options.report, safeUiError(error));
|
|
1727
2118
|
}
|
|
1728
|
-
} else {
|
|
1729
|
-
await submitSafely(options.session, prompt, options.report);
|
|
1730
2119
|
}
|
|
1731
2120
|
options.onFinish();
|
|
1732
2121
|
if (options.shouldContinue?.() === false) return;
|
|
1733
2122
|
prompt = options.pending.take();
|
|
1734
|
-
if (prompt !== void 0) options.onPendingConsumed();
|
|
1735
|
-
initial = false;
|
|
2123
|
+
if (prompt !== void 0) options.onPendingConsumed(options.pending.values);
|
|
1736
2124
|
}
|
|
1737
2125
|
}
|
|
1738
2126
|
function classifyTerminalInput(key) {
|
|
@@ -1755,6 +2143,9 @@ function completionKeyAction(key, menuOpen) {
|
|
|
1755
2143
|
function slashKeyAction(key, completion) {
|
|
1756
2144
|
return completionKeyAction(key, completion !== null);
|
|
1757
2145
|
}
|
|
2146
|
+
function canShowSlashCompletion(_activeSession, input, dismissedInput, blockedByModal) {
|
|
2147
|
+
return dismissedInput !== input && !blockedByModal;
|
|
2148
|
+
}
|
|
1758
2149
|
function appRuntimeOptions(props, output, onApprovalChange) {
|
|
1759
2150
|
return {
|
|
1760
2151
|
workspace: props.workspace,
|
|
@@ -1779,6 +2170,8 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1779
2170
|
const [clipboardNotice, setClipboardNotice] = useState2();
|
|
1780
2171
|
const [history, setHistory] = useState2([]);
|
|
1781
2172
|
const [historyCursor, setHistoryCursor] = useState2(0);
|
|
2173
|
+
const [approvalExpanded, setApprovalExpanded] = useState2(false);
|
|
2174
|
+
const [expandedOutput, setExpandedOutput] = useState2(false);
|
|
1782
2175
|
const [promptCursor, setPromptCursor] = useState2(0);
|
|
1783
2176
|
const [slashCandidates, setSlashCandidates] = useState2(
|
|
1784
2177
|
() => buildSlashCandidates(BUILTIN_SLASH_CANDIDATES, [], [])
|
|
@@ -1788,7 +2181,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1788
2181
|
const [mentionCandidates, setMentionCandidates] = useState2([]);
|
|
1789
2182
|
const [mentionSelection, setMentionSelection] = useState2(0);
|
|
1790
2183
|
const [dismissedMentionInput, setDismissedMentionInput] = useState2();
|
|
1791
|
-
const [
|
|
2184
|
+
const [pendingPrompts, setPendingPrompts] = useState2([]);
|
|
1792
2185
|
const [revision, setRevision] = useState2(0);
|
|
1793
2186
|
const [ideContext, setIdeContext] = useState2();
|
|
1794
2187
|
const [questionIndex, setQuestionIndex] = useState2(0);
|
|
@@ -1799,11 +2192,12 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1799
2192
|
const [updateTo, setUpdateTo] = useState2();
|
|
1800
2193
|
const [transcript, dispatch] = useReducer(transcriptReducer, void 0, createTranscriptState);
|
|
1801
2194
|
const scrollRef = useRef4(null);
|
|
1802
|
-
const
|
|
1803
|
-
const
|
|
2195
|
+
const mainTaskScrollRef = useRef4(null);
|
|
2196
|
+
const subagentTaskScrollRef = useRef4(null);
|
|
2197
|
+
const hoveredTaskTrack = useRef4(null);
|
|
1804
2198
|
const runtimeRef = useRef4(void 0);
|
|
1805
2199
|
const pendingPromptRef = useRef4(void 0);
|
|
1806
|
-
pendingPromptRef.current ??= new
|
|
2200
|
+
pendingPromptRef.current ??= new PendingPromptQueue();
|
|
1807
2201
|
const closing = useRef4(false);
|
|
1808
2202
|
const clipboardBusy = useRef4(false);
|
|
1809
2203
|
const textBuf = useRef4({ pending: "", timer: null });
|
|
@@ -1814,8 +2208,15 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1814
2208
|
pastedBlocks,
|
|
1815
2209
|
imageAttachments
|
|
1816
2210
|
});
|
|
2211
|
+
const promptEditHistory = useRef4(new PromptEditHistory());
|
|
2212
|
+
const historyRef = useRef4([]);
|
|
2213
|
+
const historyCursorRef = useRef4(0);
|
|
2214
|
+
const historyDraftRef = useRef4(void 0);
|
|
2215
|
+
const reverseSearchRef = useRef4(void 0);
|
|
2216
|
+
const promptHistoryStoreRef = useRef4(void 0);
|
|
2217
|
+
promptHistoryStoreRef.current ??= new PromptHistoryStore({ home: home ?? homedir(), workspace, maxEntries: HISTORY_CAP });
|
|
1817
2218
|
promptDraftRef.current = { text: input, cursor: promptCursor, pastedBlocks, imageAttachments };
|
|
1818
|
-
const commitPromptDraft = (next) => {
|
|
2219
|
+
const commitPromptDraft = (next, recordHistory = true) => {
|
|
1819
2220
|
const current = promptDraftRef.current;
|
|
1820
2221
|
const resolved = {
|
|
1821
2222
|
text: next.text,
|
|
@@ -1823,6 +2224,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1823
2224
|
pastedBlocks: next.pastedBlocks ?? current.pastedBlocks,
|
|
1824
2225
|
imageAttachments: next.imageAttachments ?? current.imageAttachments
|
|
1825
2226
|
};
|
|
2227
|
+
if (recordHistory) promptEditHistory.current.record(current, resolved);
|
|
1826
2228
|
promptDraftRef.current = resolved;
|
|
1827
2229
|
setInput(resolved.text);
|
|
1828
2230
|
setPromptCursor(resolved.cursor);
|
|
@@ -1830,6 +2232,19 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
1830
2232
|
if (next.imageAttachments !== void 0) setImageAttachments(next.imageAttachments);
|
|
1831
2233
|
};
|
|
1832
2234
|
useTerminalTitle("Flavor Code");
|
|
2235
|
+
useEffect3(() => {
|
|
2236
|
+
let disposed = false;
|
|
2237
|
+
void promptHistoryStoreRef.current.load().then((entries) => {
|
|
2238
|
+
if (disposed) return;
|
|
2239
|
+
historyRef.current = entries;
|
|
2240
|
+
historyCursorRef.current = entries.length;
|
|
2241
|
+
setHistory(entries);
|
|
2242
|
+
setHistoryCursor(entries.length);
|
|
2243
|
+
});
|
|
2244
|
+
return () => {
|
|
2245
|
+
disposed = true;
|
|
2246
|
+
};
|
|
2247
|
+
}, [workspace, home]);
|
|
1833
2248
|
const flushText = () => {
|
|
1834
2249
|
flushThinking();
|
|
1835
2250
|
const t = textBuf.current;
|
|
@@ -2043,8 +2458,14 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2043
2458
|
setQuestionAnswers({});
|
|
2044
2459
|
setCustomQuestionActive(false);
|
|
2045
2460
|
}, [questions]);
|
|
2461
|
+
useEffect3(() => setApprovalExpanded(false), [approval?.id]);
|
|
2046
2462
|
const derivedSlashCompletion = deriveSlashCompletion(input, promptCursor, slashCandidates, slashSelection);
|
|
2047
|
-
const slashCompletion =
|
|
2463
|
+
const slashCompletion = canShowSlashCompletion(
|
|
2464
|
+
transcript.active !== void 0,
|
|
2465
|
+
input,
|
|
2466
|
+
dismissedSlashInput,
|
|
2467
|
+
approval !== void 0 || questions !== void 0
|
|
2468
|
+
) ? derivedSlashCompletion : null;
|
|
2048
2469
|
const derivedMentionCompletion = slashCompletion === null ? deriveMentionCompletion(input, promptCursor, mentionCandidates, mentionSelection) : null;
|
|
2049
2470
|
const mentionCompletion = dismissedMentionInput === input || transcript.active !== void 0 || approval !== void 0 || questions !== void 0 ? null : derivedMentionCompletion;
|
|
2050
2471
|
const completedTokenLength = completedSlashTokenLength(input, slashCandidates, slashCompletion !== null);
|
|
@@ -2062,11 +2483,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2062
2483
|
setClipboardNotice("Flavor is still starting; try pasting the image again.");
|
|
2063
2484
|
return;
|
|
2064
2485
|
}
|
|
2065
|
-
if (
|
|
2066
|
-
setClipboardNotice("Images can only be attached to a new prompt.");
|
|
2067
|
-
return;
|
|
2068
|
-
}
|
|
2069
|
-
if (imageAttachments.length >= DEFAULT_MAX_IMAGES) {
|
|
2486
|
+
if (promptDraftRef.current.imageAttachments.length >= DEFAULT_MAX_IMAGES) {
|
|
2070
2487
|
setClipboardNotice(`A prompt can contain at most ${DEFAULT_MAX_IMAGES} images.`);
|
|
2071
2488
|
return;
|
|
2072
2489
|
}
|
|
@@ -2080,14 +2497,15 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2080
2497
|
return;
|
|
2081
2498
|
}
|
|
2082
2499
|
const incomingBytes = Buffer.byteLength(attachment.dataBase64, "base64");
|
|
2083
|
-
const
|
|
2500
|
+
const currentDraft = promptDraftRef.current;
|
|
2501
|
+
const currentBytes = currentDraft.imageAttachments.reduce((sum, image) => sum + image.bytes, 0);
|
|
2084
2502
|
if (currentBytes + incomingBytes > DEFAULT_MAX_TOTAL_IMAGE_BYTES) {
|
|
2085
2503
|
throw new Error(`Image attachments exceed the maximum total size of ${DEFAULT_MAX_TOTAL_IMAGE_BYTES} bytes`);
|
|
2086
2504
|
}
|
|
2087
2505
|
const [stored] = await new SessionAssetStore({ workspace }).store(active.sessionId, [attachment]);
|
|
2088
2506
|
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)}`);
|
|
2507
|
+
commitPromptDraft({ ...currentDraft, imageAttachments: [...currentDraft.imageAttachments, stored] });
|
|
2508
|
+
setClipboardNotice(`Added [Image #${currentDraft.imageAttachments.length + 1}] ${stored.name ?? basename3(stored.source.path)}`);
|
|
2091
2509
|
} catch (error) {
|
|
2092
2510
|
setClipboardNotice(safeUiError(error));
|
|
2093
2511
|
} finally {
|
|
@@ -2097,7 +2515,12 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2097
2515
|
use_input_default((character, key, event) => {
|
|
2098
2516
|
const terminalAction = classifyTerminalInput(key);
|
|
2099
2517
|
if (terminalAction?.type === "scroll") {
|
|
2100
|
-
const scroll = selectWheelScrollTarget(
|
|
2518
|
+
const scroll = selectWheelScrollTarget(
|
|
2519
|
+
scrollRef.current,
|
|
2520
|
+
mainTaskScrollRef.current,
|
|
2521
|
+
subagentTaskScrollRef.current,
|
|
2522
|
+
hoveredTaskTrack.current
|
|
2523
|
+
);
|
|
2101
2524
|
if (scroll !== null) {
|
|
2102
2525
|
if (terminalAction.rows < 0) scrollUp(scroll, -terminalAction.rows);
|
|
2103
2526
|
else scrollDown(scroll, terminalAction.rows);
|
|
@@ -2110,12 +2533,18 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2110
2533
|
return;
|
|
2111
2534
|
}
|
|
2112
2535
|
const active = runtimeRef.current;
|
|
2113
|
-
if (
|
|
2114
|
-
if (selection.hasSelection())
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2536
|
+
if (isCopyShortcut(character, key)) {
|
|
2537
|
+
if (selection.hasSelection()) selection.copySelection();
|
|
2538
|
+
else if (process.platform !== "darwin") interrupt();
|
|
2539
|
+
return;
|
|
2540
|
+
}
|
|
2541
|
+
if (key.ctrl && character.toLowerCase() === "c") {
|
|
2542
|
+
interrupt();
|
|
2543
|
+
return;
|
|
2544
|
+
}
|
|
2545
|
+
if (isPlatformShortcut(character, key, "o")) {
|
|
2546
|
+
setExpandedOutput((value) => !value);
|
|
2547
|
+
scrollRef.current?.scrollToBottom();
|
|
2119
2548
|
return;
|
|
2120
2549
|
}
|
|
2121
2550
|
if (shouldReadClipboardImage(character, key, event.keypress.isPasted)) {
|
|
@@ -2123,8 +2552,15 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2123
2552
|
return;
|
|
2124
2553
|
}
|
|
2125
2554
|
if (active?.approvals.pending !== void 0) {
|
|
2555
|
+
if (character.toLowerCase() === "v") setApprovalExpanded((value) => !value);
|
|
2126
2556
|
if (character.toLowerCase() === "y") active.approvals.resolve("once");
|
|
2127
2557
|
if (character.toLowerCase() === "n" || key.escape) active.approvals.resolve("deny");
|
|
2558
|
+
if (character.toLowerCase() === "e") {
|
|
2559
|
+
void Promise.resolve(active.services.setPermissionMode("acceptEdits")).then(() => {
|
|
2560
|
+
setRevision((value) => value + 1);
|
|
2561
|
+
setClipboardNotice("Permission mode changed to acceptEdits; review the current request, then allow or deny it.");
|
|
2562
|
+
}).catch((error) => dispatch({ type: "submit-error", message: safeUiError(error) }));
|
|
2563
|
+
}
|
|
2128
2564
|
if (character.toLowerCase() === "a") {
|
|
2129
2565
|
if (isDestructiveTool(active.approvals.pending.tool)) {
|
|
2130
2566
|
active.approvals.resolve("once");
|
|
@@ -2188,23 +2624,35 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2188
2624
|
setPromptCursor(0);
|
|
2189
2625
|
return;
|
|
2190
2626
|
}
|
|
2191
|
-
if (!key.ctrl && !key.meta && character) setCustomQuestionActive(true);
|
|
2627
|
+
if (!key.ctrl && !key.meta && !key.super && character) setCustomQuestionActive(true);
|
|
2192
2628
|
else return;
|
|
2193
2629
|
}
|
|
2194
2630
|
}
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2631
|
+
const historyAction = promptHistoryAction(character, key);
|
|
2632
|
+
if (historyAction !== null) {
|
|
2633
|
+
const draft = promptDraftRef.current;
|
|
2634
|
+
const restored = historyAction === "undo" ? promptEditHistory.current.undo(draft) : promptEditHistory.current.redo(draft);
|
|
2635
|
+
if (restored !== void 0) commitPromptDraft(restored, false);
|
|
2636
|
+
setSlashSelection(0);
|
|
2637
|
+
setDismissedSlashInput(void 0);
|
|
2638
|
+
setMentionSelection(0);
|
|
2639
|
+
setDismissedMentionInput(void 0);
|
|
2640
|
+
return;
|
|
2641
|
+
}
|
|
2642
|
+
if (isPlatformShortcut(character, key, "r")) {
|
|
2643
|
+
const draft = promptDraftRef.current;
|
|
2644
|
+
if (historyCursorRef.current === historyRef.current.length) historyDraftRef.current = clonePromptDraft(draft);
|
|
2645
|
+
const previous = reverseSearchRef.current;
|
|
2646
|
+
const query = previous?.query ?? draft.text;
|
|
2647
|
+
const match = reverseSearchHistory(historyRef.current, query, previous?.cursor ?? historyRef.current.length);
|
|
2648
|
+
if (match !== void 0) {
|
|
2649
|
+
reverseSearchRef.current = { query, cursor: match.cursor };
|
|
2650
|
+
historyCursorRef.current = match.cursor;
|
|
2651
|
+
setHistoryCursor(match.cursor);
|
|
2652
|
+
commitPromptDraft({ text: match.input, cursor: match.promptCursor, pastedBlocks: [], imageAttachments: [] }, false);
|
|
2653
|
+
setClipboardNotice(`reverse-i-search: ${query || "(latest)"} \xB7 Ctrl/Cmd+R for older match`);
|
|
2654
|
+
} else setClipboardNotice(`No older history match for ${query || "(latest)"}.`);
|
|
2655
|
+
return;
|
|
2208
2656
|
}
|
|
2209
2657
|
const menuAction = slashKeyAction(key, slashCompletion);
|
|
2210
2658
|
if (menuAction?.type === "select" && slashCompletion !== null) {
|
|
@@ -2215,8 +2663,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2215
2663
|
const selected = slashCompletion.items[slashCompletion.selectedIndex];
|
|
2216
2664
|
if (selected !== void 0) {
|
|
2217
2665
|
const next = completeSlashSelection(input, promptCursor, selected.name);
|
|
2218
|
-
|
|
2219
|
-
setPromptCursor(next.cursor);
|
|
2666
|
+
commitPromptDraft(next);
|
|
2220
2667
|
setDismissedSlashInput(next.text);
|
|
2221
2668
|
}
|
|
2222
2669
|
return;
|
|
@@ -2239,9 +2686,28 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2239
2686
|
setDismissedMentionInput(input);
|
|
2240
2687
|
return;
|
|
2241
2688
|
}
|
|
2689
|
+
if (key.escape && transcript.active !== void 0) {
|
|
2690
|
+
const escapeAction = runningEscapeAction(true, pendingPromptRef.current.size);
|
|
2691
|
+
if (escapeAction === "restore-pending") {
|
|
2692
|
+
const restored = pendingPromptRef.current.cancel();
|
|
2693
|
+
if (restored === void 0) return;
|
|
2694
|
+
setPendingPrompts([...pendingPromptRef.current.values]);
|
|
2695
|
+
const restoredDraft = restoreQueuedPrompt(restored);
|
|
2696
|
+
promptEditHistory.current.reset();
|
|
2697
|
+
commitPromptDraft(restoredDraft, false);
|
|
2698
|
+
setClipboardNotice(restoredDraft.imageAttachments.length === 0 ? void 0 : `Restored ${restoredDraft.imageAttachments.length} pending ${restoredDraft.imageAttachments.length === 1 ? "image" : "images"}.`);
|
|
2699
|
+
setSlashSelection(0);
|
|
2700
|
+
setDismissedSlashInput(void 0);
|
|
2701
|
+
setMentionSelection(0);
|
|
2702
|
+
setDismissedMentionInput(void 0);
|
|
2703
|
+
return;
|
|
2704
|
+
}
|
|
2705
|
+
interrupt();
|
|
2706
|
+
return;
|
|
2707
|
+
}
|
|
2242
2708
|
if (key.return) {
|
|
2243
2709
|
const images = [...imageAttachments];
|
|
2244
|
-
const prepared = prepareCliSubmission(input, images
|
|
2710
|
+
const prepared = prepareCliSubmission(input, images);
|
|
2245
2711
|
if (prepared.kind === "empty" || active === void 0) return;
|
|
2246
2712
|
if (prepared.kind === "error") {
|
|
2247
2713
|
setClipboardNotice(prepared.message);
|
|
@@ -2251,16 +2717,27 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2251
2717
|
const { delivery, prompt } = resolvePromptDelivery(transcript.active !== void 0, key, submittedText);
|
|
2252
2718
|
if (!prompt) return;
|
|
2253
2719
|
if (delivery === "followUp" && transcript.active !== void 0) {
|
|
2254
|
-
if (!pendingPromptRef.current.queue(
|
|
2255
|
-
|
|
2720
|
+
if (!pendingPromptRef.current.queue({
|
|
2721
|
+
text: prompt,
|
|
2722
|
+
displayText: prepared.content === void 0 ? prompt : prepared.displayText,
|
|
2723
|
+
...prepared.content === void 0 ? {} : { content: prepared.content }
|
|
2724
|
+
})) return;
|
|
2725
|
+
setPendingPrompts([...pendingPromptRef.current.values]);
|
|
2256
2726
|
}
|
|
2257
2727
|
scrollRef.current?.scrollToBottom();
|
|
2258
|
-
|
|
2259
|
-
|
|
2728
|
+
const nextHistory = [...historyRef.current, submittedText].slice(-HISTORY_CAP);
|
|
2729
|
+
historyRef.current = nextHistory;
|
|
2730
|
+
historyCursorRef.current = nextHistory.length;
|
|
2731
|
+
historyDraftRef.current = void 0;
|
|
2732
|
+
reverseSearchRef.current = void 0;
|
|
2733
|
+
setHistory(nextHistory);
|
|
2734
|
+
setHistoryCursor(nextHistory.length);
|
|
2735
|
+
void promptHistoryStoreRef.current.append(submittedText).catch(() => void 0);
|
|
2260
2736
|
setInput("");
|
|
2261
2737
|
setPastedBlocks([]);
|
|
2262
2738
|
setImageAttachments([]);
|
|
2263
2739
|
promptDraftRef.current = { text: "", cursor: 0, pastedBlocks: [], imageAttachments: [] };
|
|
2740
|
+
promptEditHistory.current.reset();
|
|
2264
2741
|
setClipboardNotice(void 0);
|
|
2265
2742
|
setPromptCursor(0);
|
|
2266
2743
|
setSlashSelection(0);
|
|
@@ -2273,15 +2750,12 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2273
2750
|
initialPrompt: prompt,
|
|
2274
2751
|
...prepared.content === void 0 ? {} : {
|
|
2275
2752
|
initialDisplayPrompt: prepared.displayText,
|
|
2276
|
-
|
|
2277
|
-
text,
|
|
2278
|
-
content: prepared.content
|
|
2279
|
-
})
|
|
2753
|
+
initialContent: prepared.content
|
|
2280
2754
|
},
|
|
2281
2755
|
pending: pendingPromptRef.current,
|
|
2282
2756
|
onStart: (next) => dispatch({ type: "submit", prompt: next }),
|
|
2283
2757
|
onFinish: () => dispatch({ type: "finish" }),
|
|
2284
|
-
onPendingConsumed: () =>
|
|
2758
|
+
onPendingConsumed: (remaining) => setPendingPrompts([...remaining]),
|
|
2285
2759
|
report: (error) => dispatch({ type: "submit-error", message: error }),
|
|
2286
2760
|
shouldContinue: () => !closing.current
|
|
2287
2761
|
});
|
|
@@ -2295,11 +2769,11 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2295
2769
|
return;
|
|
2296
2770
|
}
|
|
2297
2771
|
if (key.backspace) {
|
|
2772
|
+
reverseSearchRef.current = void 0;
|
|
2298
2773
|
const draft = promptDraftRef.current;
|
|
2299
2774
|
const imageEdit = removeLastCliImageOnBackspace(draft.text, draft.cursor, draft.imageAttachments);
|
|
2300
2775
|
if (imageEdit.handled) {
|
|
2301
|
-
|
|
2302
|
-
promptDraftRef.current = { ...draft, imageAttachments: imageEdit.images };
|
|
2776
|
+
commitPromptDraft({ ...draft, imageAttachments: imageEdit.images });
|
|
2303
2777
|
setClipboardNotice(imageEdit.images.length === 0 ? "Removed image attachment." : `Removed image attachment; ${imageEdit.images.length} remaining.`);
|
|
2304
2778
|
return;
|
|
2305
2779
|
}
|
|
@@ -2314,6 +2788,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2314
2788
|
setMentionSelection(0);
|
|
2315
2789
|
setDismissedMentionInput(void 0);
|
|
2316
2790
|
} else if (key.delete) {
|
|
2791
|
+
reverseSearchRef.current = void 0;
|
|
2317
2792
|
const draft = promptDraftRef.current;
|
|
2318
2793
|
commitPromptDraft({ ...editPrompt({ text: draft.text, cursor: draft.cursor }, { type: "delete" }), pastedBlocks: draft.pastedBlocks });
|
|
2319
2794
|
setSlashSelection(0);
|
|
@@ -2321,28 +2796,31 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2321
2796
|
setMentionSelection(0);
|
|
2322
2797
|
setDismissedMentionInput(void 0);
|
|
2323
2798
|
} else if (key.leftArrow) {
|
|
2799
|
+
reverseSearchRef.current = void 0;
|
|
2324
2800
|
const draft = promptDraftRef.current;
|
|
2325
2801
|
commitPromptDraft({ ...editPrompt({ text: draft.text, cursor: draft.cursor }, { type: "left" }), pastedBlocks: draft.pastedBlocks });
|
|
2326
2802
|
} else if (key.rightArrow) {
|
|
2803
|
+
reverseSearchRef.current = void 0;
|
|
2327
2804
|
const draft = promptDraftRef.current;
|
|
2328
2805
|
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
|
-
|
|
2806
|
+
} else if (terminalAction?.type === "history" && historyRef.current.length) {
|
|
2807
|
+
const next = navigatePromptHistory({
|
|
2808
|
+
history: historyRef.current,
|
|
2809
|
+
cursor: historyCursorRef.current,
|
|
2810
|
+
current: promptDraftRef.current,
|
|
2811
|
+
...historyDraftRef.current === void 0 ? {} : { stashed: historyDraftRef.current }
|
|
2812
|
+
}, terminalAction.direction);
|
|
2813
|
+
historyCursorRef.current = next.cursor;
|
|
2814
|
+
historyDraftRef.current = next.stashed;
|
|
2815
|
+
reverseSearchRef.current = void 0;
|
|
2339
2816
|
setHistoryCursor(next.cursor);
|
|
2340
|
-
commitPromptDraft(
|
|
2817
|
+
commitPromptDraft(next.draft, false);
|
|
2341
2818
|
setSlashSelection(0);
|
|
2342
2819
|
setDismissedSlashInput(void 0);
|
|
2343
2820
|
setMentionSelection(0);
|
|
2344
2821
|
setDismissedMentionInput(void 0);
|
|
2345
|
-
} else if (!key.ctrl && !key.meta && character) {
|
|
2822
|
+
} else if (!key.ctrl && !key.meta && !key.super && character) {
|
|
2823
|
+
reverseSearchRef.current = void 0;
|
|
2346
2824
|
const draft = promptDraftRef.current;
|
|
2347
2825
|
const nextPastedBlocks = /[\r\n]/u.test(character) ? [...draft.pastedBlocks, { id: draft.pastedBlocks.length + 1, text: character }] : draft.pastedBlocks;
|
|
2348
2826
|
commitPromptDraft({
|
|
@@ -2388,17 +2866,20 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2388
2866
|
...ideContext === void 0 ? {} : { ideContext },
|
|
2389
2867
|
completedSlashTokenLength: completedTokenLength,
|
|
2390
2868
|
scrollRef,
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2869
|
+
mainTaskScrollRef,
|
|
2870
|
+
subagentTaskScrollRef,
|
|
2871
|
+
onTaskPanelHoverChange: (track) => {
|
|
2872
|
+
hoveredTaskTrack.current = track;
|
|
2394
2873
|
},
|
|
2395
2874
|
...slashCompletion === null ? {} : { completion: slashCompletion },
|
|
2396
2875
|
...mentionCompletion === null ? {} : { mentionCompletion, onMentionSelect: selectMention },
|
|
2397
2876
|
...approval === void 0 ? {} : { approval },
|
|
2877
|
+
approvalExpanded,
|
|
2878
|
+
expandedOutput,
|
|
2398
2879
|
...questions === void 0 ? {} : { questions },
|
|
2399
2880
|
memoryReviews,
|
|
2400
2881
|
memoryAutoDismissSeconds,
|
|
2401
|
-
|
|
2882
|
+
pendingPrompts,
|
|
2402
2883
|
questionIndex,
|
|
2403
2884
|
questionAnswers,
|
|
2404
2885
|
customQuestionActive
|
|
@@ -2433,6 +2914,46 @@ var CLI_VISIBLE_TURN_LIMIT = 40;
|
|
|
2433
2914
|
var CLI_VISIBLE_BLOCK_LIMIT = 320;
|
|
2434
2915
|
var CLI_VISIBLE_BLOCKS_PER_TURN = 80;
|
|
2435
2916
|
var CLI_VISIBLE_TEXT_CHARS = 32e3;
|
|
2917
|
+
function approvalDetailLines(approval) {
|
|
2918
|
+
const lines = [];
|
|
2919
|
+
if (approval.agent !== "main") lines.push(`Agent: ${approval.agent}`);
|
|
2920
|
+
if (approval.command !== void 0) {
|
|
2921
|
+
const command = [approval.command, ...(approval.args ?? []).map(formatApprovalArgument)].join(" ");
|
|
2922
|
+
lines.push(`Command: ${command}`);
|
|
2923
|
+
} else if (approval.args !== void 0 && approval.args.length > 0) {
|
|
2924
|
+
lines.push(`Arguments: ${approval.args.map(formatApprovalArgument).join(" ")}`);
|
|
2925
|
+
}
|
|
2926
|
+
if (approval.cwd !== void 0) lines.push(`Working directory: ${approval.cwd}`);
|
|
2927
|
+
for (const [index, path] of (approval.paths ?? []).entries()) {
|
|
2928
|
+
lines.push(`${approval.paths.length === 1 ? "Path" : `Path ${index + 1}`}: ${path}`);
|
|
2929
|
+
}
|
|
2930
|
+
const inputLines = approvalInputLines(approval.input);
|
|
2931
|
+
if (inputLines.length > 0) lines.push("Tool input:", ...inputLines.map((line) => ` ${line}`));
|
|
2932
|
+
if (lines.length === 0) lines.push("No additional parameters were supplied.");
|
|
2933
|
+
return lines;
|
|
2934
|
+
}
|
|
2935
|
+
function formatApprovalArgument(value) {
|
|
2936
|
+
return /\s|["']/u.test(value) ? JSON.stringify(value) : value;
|
|
2937
|
+
}
|
|
2938
|
+
function approvalInputLines(input) {
|
|
2939
|
+
if (input === void 0) return [];
|
|
2940
|
+
if (typeof input !== "object" || input === null || Array.isArray(input)) return [formatApprovalValue(input)];
|
|
2941
|
+
const lines = [];
|
|
2942
|
+
for (const [key, value] of Object.entries(input)) {
|
|
2943
|
+
if (typeof value === "string" && /[\r\n]/u.test(value)) {
|
|
2944
|
+
lines.push(`${key}: |`, ...value.replace(/\r\n/gu, "\n").split("\n").map((line) => ` ${line}`));
|
|
2945
|
+
} else lines.push(`${key}: ${formatApprovalValue(value)}`);
|
|
2946
|
+
}
|
|
2947
|
+
return lines;
|
|
2948
|
+
}
|
|
2949
|
+
function formatApprovalValue(value) {
|
|
2950
|
+
if (typeof value === "string") return value;
|
|
2951
|
+
try {
|
|
2952
|
+
return JSON.stringify(value);
|
|
2953
|
+
} catch {
|
|
2954
|
+
return String(value);
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2436
2957
|
function boundedCliDisplayText(text, limit = CLI_VISIBLE_TEXT_CHARS) {
|
|
2437
2958
|
if (text.length <= limit) return text;
|
|
2438
2959
|
const half = Math.floor((limit - 80) / 2);
|
|
@@ -2511,8 +3032,10 @@ function TerminalLayout({
|
|
|
2511
3032
|
columns,
|
|
2512
3033
|
rows = 24,
|
|
2513
3034
|
activeSession,
|
|
2514
|
-
|
|
3035
|
+
pendingPrompts = [],
|
|
2515
3036
|
approval,
|
|
3037
|
+
approvalExpanded = false,
|
|
3038
|
+
expandedOutput = false,
|
|
2516
3039
|
questions,
|
|
2517
3040
|
memoryReviews = [],
|
|
2518
3041
|
memoryAutoDismissSeconds = 0,
|
|
@@ -2524,7 +3047,8 @@ function TerminalLayout({
|
|
|
2524
3047
|
onMentionSelect,
|
|
2525
3048
|
completedSlashTokenLength: tokenLength = 0,
|
|
2526
3049
|
scrollRef,
|
|
2527
|
-
|
|
3050
|
+
mainTaskScrollRef,
|
|
3051
|
+
subagentTaskScrollRef,
|
|
2528
3052
|
onTaskPanelHoverChange,
|
|
2529
3053
|
onPromptCursorChange,
|
|
2530
3054
|
ideContext
|
|
@@ -2542,11 +3066,12 @@ function TerminalLayout({
|
|
|
2542
3066
|
(block) => !(block.kind === "status" && block.task !== void 0)
|
|
2543
3067
|
)
|
|
2544
3068
|
};
|
|
2545
|
-
const activeWithoutTasks = rawActiveWithoutTasks === void 0 ? void 0 : boundedCliTurn(rawActiveWithoutTasks).turn;
|
|
2546
|
-
const completedWindow = cliTranscriptWindow(completed);
|
|
3069
|
+
const activeWithoutTasks = rawActiveWithoutTasks === void 0 ? void 0 : expandedOutput ? rawActiveWithoutTasks : boundedCliTurn(rawActiveWithoutTasks).turn;
|
|
3070
|
+
const completedWindow = expandedOutput ? { turns: completed, hiddenTurns: 0, hiddenBlocks: 0 } : cliTranscriptWindow(completed);
|
|
2547
3071
|
const questionRows = questions === void 0 ? 0 : 4 + (questions[questionIndex]?.options.length ?? 0) + questions.length * 2;
|
|
2548
3072
|
const memoryReviewRows = memoryReviews.length === 0 ? 0 : 5;
|
|
2549
|
-
const
|
|
3073
|
+
const approvalRows = approval === void 0 ? 0 : 3 + (approvalExpanded ? approvalDetailLines(approval).length : 0);
|
|
3074
|
+
const fixedBottomRows = approvalRows + questionRows + memoryReviewRows + menuRows + (pendingPrompts.length === 0 ? 0 : 1) + imageAttachments.length + (clipboardNotice === void 0 ? 0 : 1) + 2;
|
|
2550
3075
|
const taskPanelRows = taskPanelViewportRows(rows, fixedBottomRows, activeTaskBlocks.length > 0);
|
|
2551
3076
|
const availableBottomRows = Math.max(1, rows - taskPanelRows - 1);
|
|
2552
3077
|
const bottomMaxRows = Math.min(availableBottomRows, Math.max(Math.floor(rows / 2), fixedBottomRows + 1));
|
|
@@ -2565,15 +3090,15 @@ function TerminalLayout({
|
|
|
2565
3090
|
completedWindow.hiddenTurns,
|
|
2566
3091
|
" earlier turns and ",
|
|
2567
3092
|
completedWindow.hiddenBlocks,
|
|
2568
|
-
" output items
|
|
3093
|
+
" output items hidden \xB7 Ctrl/Cmd+O expand all"
|
|
2569
3094
|
] }) : null,
|
|
2570
3095
|
completedWindow.turns.map((turn, index) => /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", children: [
|
|
2571
3096
|
index > 0 ? /* @__PURE__ */ jsx5(TurnSeparator, { width: columns }) : null,
|
|
2572
|
-
/* @__PURE__ */ jsx5(TurnView, { turn, interactive: false, workspaceName })
|
|
3097
|
+
/* @__PURE__ */ jsx5(TurnView, { turn, interactive: false, workspaceName, expandedOutput })
|
|
2573
3098
|
] }, turn.id)),
|
|
2574
3099
|
activeWithoutTasks === void 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", children: [
|
|
2575
3100
|
completedWindow.turns.length > 0 ? /* @__PURE__ */ jsx5(TurnSeparator, { width: columns }) : null,
|
|
2576
|
-
/* @__PURE__ */ jsx5(TurnView, { turn: activeWithoutTasks, interactive: activeSession, workspaceName })
|
|
3101
|
+
/* @__PURE__ */ jsx5(TurnView, { turn: activeWithoutTasks, interactive: activeSession, workspaceName, expandedOutput })
|
|
2577
3102
|
] })
|
|
2578
3103
|
] }),
|
|
2579
3104
|
/* @__PURE__ */ jsx5(
|
|
@@ -2583,7 +3108,8 @@ function TerminalLayout({
|
|
|
2583
3108
|
interactive: activeSession,
|
|
2584
3109
|
maxHeight: taskPanelRows,
|
|
2585
3110
|
columns,
|
|
2586
|
-
...
|
|
3111
|
+
...mainTaskScrollRef === void 0 ? {} : { mainScrollRef: mainTaskScrollRef },
|
|
3112
|
+
...subagentTaskScrollRef === void 0 ? {} : { subagentScrollRef: subagentTaskScrollRef },
|
|
2587
3113
|
...onTaskPanelHoverChange === void 0 ? {} : { onHoverChange: onTaskPanelHoverChange }
|
|
2588
3114
|
}
|
|
2589
3115
|
),
|
|
@@ -2597,18 +3123,30 @@ function TerminalLayout({
|
|
|
2597
3123
|
"\u2502 ",
|
|
2598
3124
|
approval.reason ?? "This action needs permission."
|
|
2599
3125
|
] }),
|
|
2600
|
-
|
|
2601
|
-
"\
|
|
3126
|
+
approvalExpanded ? approvalDetailLines(approval).map((line, index) => /* @__PURE__ */ jsxs4(Text, { color: "magentaBright", wrap: "truncate-end", children: [
|
|
3127
|
+
"\u2502 ",
|
|
3128
|
+
line
|
|
3129
|
+
] }, `${approval.id}:detail:${index}`)) : null,
|
|
3130
|
+
isDestructiveTool(approval.tool) || approval.allowAlways === false ? /* @__PURE__ */ jsxs4(Text, { bold: true, color: "magenta", children: [
|
|
3131
|
+
"\u2514\u2500 ",
|
|
3132
|
+
/* @__PURE__ */ jsx5(Text, { color: "cyan", children: "v" }),
|
|
3133
|
+
"=details / ",
|
|
2602
3134
|
/* @__PURE__ */ jsx5(Text, { color: "green", children: "y" }),
|
|
2603
3135
|
"=once / ",
|
|
3136
|
+
/* @__PURE__ */ jsx5(Text, { color: "cyan", children: "e" }),
|
|
3137
|
+
"=accept edits / ",
|
|
2604
3138
|
/* @__PURE__ */ jsx5(Text, { color: "red", children: "n" }),
|
|
2605
3139
|
"=deny"
|
|
2606
3140
|
] }) : /* @__PURE__ */ jsxs4(Text, { bold: true, color: "magenta", children: [
|
|
2607
|
-
"\u2514\u2500
|
|
3141
|
+
"\u2514\u2500 ",
|
|
3142
|
+
/* @__PURE__ */ jsx5(Text, { color: "cyan", children: "v" }),
|
|
3143
|
+
"=details / ",
|
|
2608
3144
|
/* @__PURE__ */ jsx5(Text, { color: "green", children: "y" }),
|
|
2609
3145
|
"=once / ",
|
|
2610
3146
|
/* @__PURE__ */ jsx5(Text, { color: "yellow", children: "a" }),
|
|
2611
3147
|
"=same-type / ",
|
|
3148
|
+
/* @__PURE__ */ jsx5(Text, { color: "cyan", children: "e" }),
|
|
3149
|
+
"=accept edits / ",
|
|
2612
3150
|
/* @__PURE__ */ jsx5(Text, { color: "red", children: "n" }),
|
|
2613
3151
|
"=deny"
|
|
2614
3152
|
] })
|
|
@@ -2617,10 +3155,12 @@ function TerminalLayout({
|
|
|
2617
3155
|
memoryReviews.length === 0 ? null : /* @__PURE__ */ jsx5(MemoryReviewCards, { reviews: memoryReviews, autoDismissSeconds: memoryAutoDismissSeconds }),
|
|
2618
3156
|
completion === void 0 ? null : /* @__PURE__ */ jsx5(SlashMenu, { completion }),
|
|
2619
3157
|
mentionCompletion === void 0 ? null : /* @__PURE__ */ jsx5(MentionMenu, { completion: mentionCompletion, ...onMentionSelect === void 0 ? {} : { onSelect: onMentionSelect } }),
|
|
2620
|
-
|
|
2621
|
-
"Pending
|
|
2622
|
-
|
|
2623
|
-
" \xB7
|
|
3158
|
+
pendingPrompts.length === 0 ? null : /* @__PURE__ */ jsxs4(Text, { color: "yellow", wrap: "truncate-end", children: [
|
|
3159
|
+
"Pending (",
|
|
3160
|
+
pendingPrompts.length,
|
|
3161
|
+
") \xB7 ",
|
|
3162
|
+
queuedPromptLabel(pendingPrompts.at(-1)),
|
|
3163
|
+
" \xB7 Esc edit latest"
|
|
2624
3164
|
] }),
|
|
2625
3165
|
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: "\u2500".repeat(dividerWidth) }),
|
|
2626
3166
|
imageAttachments.map((image, index) => /* @__PURE__ */ jsxs4(Text, { color: "cyan", wrap: "truncate-end", children: [
|
|
@@ -2645,7 +3185,7 @@ function TerminalLayout({
|
|
|
2645
3185
|
/* @__PURE__ */ jsx5(
|
|
2646
3186
|
FooterStatus,
|
|
2647
3187
|
{
|
|
2648
|
-
hint: activeSession ? "Ctrl+C cancel \xB7 Enter queue \xB7
|
|
3188
|
+
hint: activeSession ? `Esc ${pendingPrompts.length > 0 ? "edit latest" : "stop"} \xB7 Ctrl+C cancel \xB7 Enter queue \xB7 Ctrl/Cmd+R history \xB7 Ctrl/Cmd+O ${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 Ctrl/Cmd+O ${expandedOutput ? "collapse" : "expand"} output \xB7 Ctrl+C exit`,
|
|
2649
3189
|
...ideContext === void 0 ? {} : { ideContext }
|
|
2650
3190
|
}
|
|
2651
3191
|
)
|
|
@@ -2749,6 +3289,7 @@ function SlashMenu({ completion }) {
|
|
|
2749
3289
|
return /* @__PURE__ */ jsxs4(Text, { ...presentation.rowStyle, wrap: "truncate-end", children: [
|
|
2750
3290
|
presentation.marker,
|
|
2751
3291
|
/* @__PURE__ */ jsx5(HighlightedName, { name: candidate.name, query: completion.query, matchStyle: presentation.matchStyle }),
|
|
3292
|
+
candidate.kind === "skill" || candidate.kind === "plugin" ? /* @__PURE__ */ jsx5(Text, { color: candidate.kind === "skill" ? "magentaBright" : "cyanBright", children: ` ${candidate.kind}` }) : null,
|
|
2752
3293
|
candidate.description === void 0 ? null : /* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` ${candidate.description}` })
|
|
2753
3294
|
] }, `${candidate.kind}:${candidate.name}`);
|
|
2754
3295
|
}) });
|
|
@@ -2804,8 +3345,10 @@ function jumpScroll(scroll, delta) {
|
|
|
2804
3345
|
scroll.scrollTo(Math.max(0, target));
|
|
2805
3346
|
}
|
|
2806
3347
|
}
|
|
2807
|
-
function selectWheelScrollTarget(transcript,
|
|
2808
|
-
|
|
3348
|
+
function selectWheelScrollTarget(transcript, mainTasks, subagentTasks, hoveredTrack) {
|
|
3349
|
+
if (hoveredTrack === "main" && mainTasks !== null) return mainTasks;
|
|
3350
|
+
if (hoveredTrack === "subagent" && subagentTasks !== null) return subagentTasks;
|
|
3351
|
+
return transcript;
|
|
2809
3352
|
}
|
|
2810
3353
|
function taskPanelViewportRows(rows, reservedBottomRows, hasTasks) {
|
|
2811
3354
|
if (!hasTasks) return 0;
|
|
@@ -2829,12 +3372,13 @@ function TurnSeparator({ width }) {
|
|
|
2829
3372
|
function TurnView({
|
|
2830
3373
|
turn,
|
|
2831
3374
|
interactive,
|
|
2832
|
-
workspaceName
|
|
3375
|
+
workspaceName,
|
|
3376
|
+
expandedOutput
|
|
2833
3377
|
}) {
|
|
2834
3378
|
if (turn.kind === "compaction") {
|
|
2835
3379
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", marginBottom: 1, borderStyle: "round", borderColor: "ansi:yellowBright", paddingX: 1, children: [
|
|
2836
3380
|
/* @__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}`))
|
|
3381
|
+
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
3382
|
] });
|
|
2839
3383
|
}
|
|
2840
3384
|
if (turn.source?.kind === "pal") {
|
|
@@ -2851,7 +3395,7 @@ function TurnView({
|
|
|
2851
3395
|
] }),
|
|
2852
3396
|
/* @__PURE__ */ jsx5(Text, { color: "ansi:whiteBright", children: turn.prompt })
|
|
2853
3397
|
] }),
|
|
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}`)) })
|
|
3398
|
+
/* @__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
3399
|
] });
|
|
2856
3400
|
}
|
|
2857
3401
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", marginBottom: 1, children: [
|
|
@@ -2862,7 +3406,7 @@ function TurnView({
|
|
|
2862
3406
|
turn.prompt
|
|
2863
3407
|
] })
|
|
2864
3408
|
] }),
|
|
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}`)) })
|
|
3409
|
+
/* @__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
3410
|
] });
|
|
2867
3411
|
}
|
|
2868
3412
|
var DIFF_CONTENT = fileDiffLineStyle("context").contentColor;
|
|
@@ -3041,11 +3585,12 @@ function PromptLine({
|
|
|
3041
3585
|
function StatusBlockView({
|
|
3042
3586
|
block,
|
|
3043
3587
|
interactive,
|
|
3044
|
-
workspaceName
|
|
3588
|
+
workspaceName,
|
|
3589
|
+
expandedOutput
|
|
3045
3590
|
}) {
|
|
3046
3591
|
const visibleBlock = cliToolTitle(block);
|
|
3047
3592
|
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 });
|
|
3593
|
+
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
3594
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", children: [
|
|
3050
3595
|
primary,
|
|
3051
3596
|
outcome === void 0 ? null : /* @__PURE__ */ jsx5(Box_default, { paddingLeft: 2, children: /* @__PURE__ */ jsxs4(Text, { dimColor: true, children: [
|
|
@@ -3057,13 +3602,14 @@ function StatusBlockView({
|
|
|
3057
3602
|
}
|
|
3058
3603
|
function ToolPresentationView({
|
|
3059
3604
|
presentation,
|
|
3060
|
-
workspaceName
|
|
3605
|
+
workspaceName,
|
|
3606
|
+
expandedOutput
|
|
3061
3607
|
}) {
|
|
3062
|
-
if (presentation.kind === "changeset") return /* @__PURE__ */ jsx5(ChangeSetPresentationView, { presentation, workspaceName });
|
|
3608
|
+
if (presentation.kind === "changeset") return /* @__PURE__ */ jsx5(ChangeSetPresentationView, { presentation, workspaceName, expanded: expandedOutput });
|
|
3063
3609
|
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 });
|
|
3610
|
+
if (presentation.kind === "terminal") return /* @__PURE__ */ jsx5(CommandPresentationView, { presentation, expanded: expandedOutput });
|
|
3611
|
+
if (presentation.kind === "web") return /* @__PURE__ */ jsx5(WebPresentationView, { presentation, expanded: expandedOutput });
|
|
3612
|
+
if (presentation.kind === "job") return /* @__PURE__ */ jsx5(JobPresentationView, { presentation, expanded: expandedOutput });
|
|
3067
3613
|
return /* @__PURE__ */ jsx5(Box_default, { paddingLeft: 2, children: /* @__PURE__ */ jsxs4(Text, { children: [
|
|
3068
3614
|
presentation.title,
|
|
3069
3615
|
presentation.summary ? ` \xB7 ${presentation.summary}` : ""
|
|
@@ -3073,9 +3619,10 @@ var CLI_CHANGESET_FILE_LIMIT = 8;
|
|
|
3073
3619
|
var CHANGESET_TONE = "#b99bf8";
|
|
3074
3620
|
function ChangeSetPresentationView({
|
|
3075
3621
|
presentation,
|
|
3076
|
-
workspaceName
|
|
3622
|
+
workspaceName,
|
|
3623
|
+
expanded
|
|
3077
3624
|
}) {
|
|
3078
|
-
const visibleFiles = presentation.files.slice(0, CLI_CHANGESET_FILE_LIMIT);
|
|
3625
|
+
const visibleFiles = expanded ? presentation.files : presentation.files.slice(0, CLI_CHANGESET_FILE_LIMIT);
|
|
3079
3626
|
const added = presentation.files.reduce((total, file) => total + file.added, 0);
|
|
3080
3627
|
const removed = presentation.files.reduce((total, file) => total + file.removed, 0);
|
|
3081
3628
|
const fileLabel = presentation.files.length === 1 ? "FILE" : "FILES";
|
|
@@ -3144,14 +3691,15 @@ function workspaceRelativePath(value, workspaceName) {
|
|
|
3144
3691
|
}
|
|
3145
3692
|
var CLI_COMMAND_OUTPUT_LINE_LIMIT = 16;
|
|
3146
3693
|
function CommandPresentationView({
|
|
3147
|
-
presentation
|
|
3694
|
+
presentation,
|
|
3695
|
+
expanded
|
|
3148
3696
|
}) {
|
|
3149
3697
|
const state = presentation.state ?? commandState(presentation.exitCode);
|
|
3150
3698
|
const tone = jobStateColor(state);
|
|
3151
3699
|
const label = presentation.variant === "terminal" ? "TERMINAL" : "COMMAND";
|
|
3152
3700
|
const hasStdout = jobOutputLines(presentation.stdout ?? "").length > 0;
|
|
3153
3701
|
const hasStderr = jobOutputLines(presentation.stderr ?? "").length > 0;
|
|
3154
|
-
const perStreamLimit = hasStdout && hasStderr ? Math.floor(CLI_COMMAND_OUTPUT_LINE_LIMIT / 2) : CLI_COMMAND_OUTPUT_LINE_LIMIT;
|
|
3702
|
+
const perStreamLimit = expanded ? Number.POSITIVE_INFINITY : hasStdout && hasStderr ? Math.floor(CLI_COMMAND_OUTPUT_LINE_LIMIT / 2) : CLI_COMMAND_OUTPUT_LINE_LIMIT;
|
|
3155
3703
|
const stdout = boundedCommandLines(presentation.stdout ?? "", perStreamLimit);
|
|
3156
3704
|
const stderr = boundedCommandLines(presentation.stderr ?? "", perStreamLimit);
|
|
3157
3705
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
@@ -3234,7 +3782,8 @@ function commandFooter(presentation, state) {
|
|
|
3234
3782
|
}
|
|
3235
3783
|
var CLI_WEB_RESULT_LIMIT = 5;
|
|
3236
3784
|
function WebPresentationView({
|
|
3237
|
-
presentation
|
|
3785
|
+
presentation,
|
|
3786
|
+
expanded
|
|
3238
3787
|
}) {
|
|
3239
3788
|
const items = presentation.items ?? [];
|
|
3240
3789
|
if (presentation.items === void 0) return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
@@ -3252,7 +3801,7 @@ function WebPresentationView({
|
|
|
3252
3801
|
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: "Page content added to context" })
|
|
3253
3802
|
] })
|
|
3254
3803
|
] });
|
|
3255
|
-
const visibleItems = items.slice(0, CLI_WEB_RESULT_LIMIT);
|
|
3804
|
+
const visibleItems = expanded ? items : items.slice(0, CLI_WEB_RESULT_LIMIT);
|
|
3256
3805
|
const query = presentation.title.replace(/^Search:\s*/iu, "").trim();
|
|
3257
3806
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
3258
3807
|
/* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
@@ -3298,13 +3847,14 @@ function compactWebSource(value) {
|
|
|
3298
3847
|
var CLI_JOB_LOG_LINE_LIMIT = 12;
|
|
3299
3848
|
var CLI_JOB_LIST_LIMIT = 8;
|
|
3300
3849
|
function JobPresentationView({
|
|
3301
|
-
presentation
|
|
3850
|
+
presentation,
|
|
3851
|
+
expanded
|
|
3302
3852
|
}) {
|
|
3303
|
-
if (presentation.action === "list") return /* @__PURE__ */ jsx5(JobListPresentationView, { presentation });
|
|
3853
|
+
if (presentation.action === "list") return /* @__PURE__ */ jsx5(JobListPresentationView, { presentation, expanded });
|
|
3304
3854
|
const state = presentation.state ?? "running";
|
|
3305
3855
|
const tone = jobStateColor(state);
|
|
3306
3856
|
const lines = jobOutputLines(presentation.output ?? "");
|
|
3307
|
-
const visibleLines = lines.slice(-CLI_JOB_LOG_LINE_LIMIT);
|
|
3857
|
+
const visibleLines = expanded ? lines : lines.slice(-CLI_JOB_LOG_LINE_LIMIT);
|
|
3308
3858
|
const hiddenLines = lines.length - visibleLines.length;
|
|
3309
3859
|
const showLog = presentation.action === "read" || presentation.action === "kill" || lines.length > 0;
|
|
3310
3860
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
@@ -3353,10 +3903,11 @@ function JobPresentationView({
|
|
|
3353
3903
|
] });
|
|
3354
3904
|
}
|
|
3355
3905
|
function JobListPresentationView({
|
|
3356
|
-
presentation
|
|
3906
|
+
presentation,
|
|
3907
|
+
expanded
|
|
3357
3908
|
}) {
|
|
3358
3909
|
const jobs = presentation.jobs ?? [];
|
|
3359
|
-
const visibleJobs = jobs.slice(0, CLI_JOB_LIST_LIMIT);
|
|
3910
|
+
const visibleJobs = expanded ? jobs : jobs.slice(0, CLI_JOB_LIST_LIMIT);
|
|
3360
3911
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
3361
3912
|
/* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
3362
3913
|
/* @__PURE__ */ jsx5(Text, { color: "#d7a657", children: "\u250C\u2500 " }),
|
|
@@ -3624,6 +4175,22 @@ function navigateHistory(state, direction) {
|
|
|
3624
4175
|
const input = state.history[cursor] ?? "";
|
|
3625
4176
|
return { cursor, input, promptCursor: [...input].length };
|
|
3626
4177
|
}
|
|
4178
|
+
function navigatePromptHistory(state, direction) {
|
|
4179
|
+
const stashed = direction === "up" && state.cursor === state.history.length ? clonePromptDraft(state.current) : state.stashed;
|
|
4180
|
+
const next = navigateHistory(state, direction);
|
|
4181
|
+
const draft = next.cursor === state.history.length && stashed !== void 0 ? clonePromptDraft(stashed) : { text: next.input, cursor: next.promptCursor, pastedBlocks: [], imageAttachments: [] };
|
|
4182
|
+
return { cursor: next.cursor, draft, ...stashed === void 0 ? {} : { stashed } };
|
|
4183
|
+
}
|
|
4184
|
+
function reverseSearchHistory(history, query, before = history.length) {
|
|
4185
|
+
const needle = query.toLocaleLowerCase();
|
|
4186
|
+
for (let cursor = Math.min(history.length, before) - 1; cursor >= 0; cursor -= 1) {
|
|
4187
|
+
const input = history[cursor];
|
|
4188
|
+
if (needle.length === 0 || input.toLocaleLowerCase().includes(needle)) {
|
|
4189
|
+
return { cursor, input, promptCursor: [...input].length };
|
|
4190
|
+
}
|
|
4191
|
+
}
|
|
4192
|
+
return void 0;
|
|
4193
|
+
}
|
|
3627
4194
|
async function submitSafely(session, prompt, report) {
|
|
3628
4195
|
try {
|
|
3629
4196
|
await session.submit(prompt);
|
|
@@ -3682,12 +4249,15 @@ export {
|
|
|
3682
4249
|
FooterStatus,
|
|
3683
4250
|
HISTORY_CAP,
|
|
3684
4251
|
MentionMenu,
|
|
4252
|
+
PendingPromptQueue,
|
|
4253
|
+
PromptEditHistory,
|
|
3685
4254
|
PromptLine,
|
|
3686
4255
|
SHUTDOWN_TIMEOUT_MS,
|
|
3687
|
-
SinglePendingPrompt,
|
|
3688
4256
|
TerminalLayout,
|
|
3689
4257
|
appRuntimeOptions,
|
|
4258
|
+
approvalDetailLines,
|
|
3690
4259
|
boundedCliTurn,
|
|
4260
|
+
canShowSlashCompletion,
|
|
3691
4261
|
classifyTerminalInput,
|
|
3692
4262
|
cliTranscriptWindow,
|
|
3693
4263
|
closeAndDisposeRuntime,
|
|
@@ -3695,14 +4265,22 @@ export {
|
|
|
3695
4265
|
editPrompt,
|
|
3696
4266
|
editPromptWithPastedBlocks,
|
|
3697
4267
|
ideFooterPresentation,
|
|
4268
|
+
isCopyShortcut,
|
|
4269
|
+
isPlatformShortcut,
|
|
3698
4270
|
navigateHistory,
|
|
4271
|
+
navigatePromptHistory,
|
|
3699
4272
|
pastedDraftPresentation,
|
|
3700
4273
|
prepareCliSubmission,
|
|
3701
4274
|
promptCursorFromClick,
|
|
3702
4275
|
promptDelivery,
|
|
4276
|
+
promptHistoryAction,
|
|
4277
|
+
queuedPromptLabel,
|
|
3703
4278
|
removeLastCliImageOnBackspace,
|
|
3704
4279
|
resolvePromptDelivery,
|
|
4280
|
+
restoreQueuedPrompt,
|
|
4281
|
+
reverseSearchHistory,
|
|
3705
4282
|
runTerminalSubmissionChain,
|
|
4283
|
+
runningEscapeAction,
|
|
3706
4284
|
selectWheelScrollTarget,
|
|
3707
4285
|
shutdownRuntime,
|
|
3708
4286
|
slashKeyAction,
|