@wrongstack/tui 0.73.1 → 0.77.0
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/dist/index.d.ts +50 -10
- package/dist/index.js +1239 -206
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { writeErr, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, buildChildEnv } from '@wrongstack/core';
|
|
1
|
+
import { writeErr, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, buildChildEnv } from '@wrongstack/core';
|
|
2
2
|
export { buildGoalPreamble } from '@wrongstack/core';
|
|
3
3
|
import { Box, Text, render, useApp, useStdout, measureElement, Static, useInput, useStdin } from 'ink';
|
|
4
|
-
import
|
|
4
|
+
import React6, { useState, useEffect, useReducer, useRef, useMemo, useCallback, useLayoutEffect } from 'react';
|
|
5
5
|
import * as fs2 from 'fs/promises';
|
|
6
6
|
import * as path2 from 'path';
|
|
7
7
|
import { routeImagesForModel } from '@wrongstack/runtime/vision';
|
|
8
|
-
import { getProcessRegistry } from '@wrongstack/tools';
|
|
8
|
+
import { getIndexState, onIndexStateChange, getProcessRegistry } from '@wrongstack/tools';
|
|
9
9
|
import { readClipboardImage } from '@wrongstack/runtime/clipboard';
|
|
10
10
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
11
11
|
import { spawn } from 'child_process';
|
|
@@ -34,8 +34,28 @@ var theme = Object.freeze({
|
|
|
34
34
|
diffAddBg: "greenBright",
|
|
35
35
|
diffDelBg: "redBright"
|
|
36
36
|
});
|
|
37
|
+
var MODE_ICONS = {
|
|
38
|
+
teach: "\u{1F9D1}\u200D\u{1F3EB}",
|
|
39
|
+
brief: "\u26A1",
|
|
40
|
+
"code-reviewer": "\u{1F50D}",
|
|
41
|
+
"bug-hunter": "\u{1F41B}",
|
|
42
|
+
"security-scanner": "\u{1F6E1}\uFE0F",
|
|
43
|
+
"refactor-planner": "\u{1F527}",
|
|
44
|
+
architect: "\u{1F3D7}\uFE0F",
|
|
45
|
+
debugger: "\u{1FAB2}",
|
|
46
|
+
test: "\u{1F9EA}",
|
|
47
|
+
document: "\u{1F4DD}",
|
|
48
|
+
"skill-creator": "\u{1F6E0}\uFE0F"
|
|
49
|
+
};
|
|
50
|
+
function modeIcon(label) {
|
|
51
|
+
if (!label) return "";
|
|
52
|
+
const icon = MODE_ICONS[label] ?? "\u25AA";
|
|
53
|
+
return `${icon} ${label}`;
|
|
54
|
+
}
|
|
37
55
|
var COMPACT_THRESHOLD = 50;
|
|
38
56
|
var COMFORTABLE_THRESHOLD = 90;
|
|
57
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
58
|
+
var SPINNER_INTERVAL_MS = 130;
|
|
39
59
|
function StatusBar({
|
|
40
60
|
model,
|
|
41
61
|
version,
|
|
@@ -58,7 +78,9 @@ function StatusBar({
|
|
|
58
78
|
processCount,
|
|
59
79
|
hiddenItems,
|
|
60
80
|
eternalStage,
|
|
61
|
-
goalSummary
|
|
81
|
+
goalSummary,
|
|
82
|
+
indexState,
|
|
83
|
+
modeLabel
|
|
62
84
|
}) {
|
|
63
85
|
const { stdout } = useStdout();
|
|
64
86
|
const [termWidth, setTermWidth] = useState(stdout?.columns ?? 90);
|
|
@@ -76,8 +98,19 @@ function StatusBar({
|
|
|
76
98
|
const usage = tokenCounter?.total();
|
|
77
99
|
const cost = tokenCounter?.estimateCost();
|
|
78
100
|
const cache2 = tokenCounter?.cacheStats();
|
|
101
|
+
const [spinnerIdx, setSpinnerIdx] = useState(0);
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
if (state === "idle" || state === "aborting") return;
|
|
104
|
+
const t = setInterval(
|
|
105
|
+
() => setSpinnerIdx((n) => (n + 1) % SPINNER_FRAMES.length),
|
|
106
|
+
SPINNER_INTERVAL_MS
|
|
107
|
+
);
|
|
108
|
+
return () => clearInterval(t);
|
|
109
|
+
}, [state]);
|
|
110
|
+
const spinner = SPINNER_FRAMES[spinnerIdx];
|
|
79
111
|
const { label: stateLabel, color: stateColor } = stateChip(state, fleet?.running ?? 0);
|
|
80
|
-
const
|
|
112
|
+
const statePrefix = state === "idle" || state === "aborting" ? "\u25CF" : spinner;
|
|
113
|
+
const hasSecondLine = yolo || autonomy && autonomy !== "off" || elapsedMs !== void 0 || git !== null && git !== void 0 || projectName !== void 0 && projectName.length > 0 || goalSummary !== null && goalSummary !== void 0 || !!modeLabel;
|
|
81
114
|
const fleetHasActivity = fleet && (fleet.running > 0 || fleet.idle > 0 || fleet.pending > 0 || fleet.completed > 0) || subagentCount > 0;
|
|
82
115
|
const hasBrainActivity = !!brain && brain.state !== "idle";
|
|
83
116
|
const hasThirdLine = todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) || fleetHasActivity || hasBrainActivity;
|
|
@@ -96,7 +129,7 @@ function StatusBar({
|
|
|
96
129
|
// Ultra-compact: state · model
|
|
97
130
|
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
98
131
|
/* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
|
|
99
|
-
|
|
132
|
+
statePrefix,
|
|
100
133
|
stateLabel
|
|
101
134
|
] }),
|
|
102
135
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
@@ -116,7 +149,8 @@ function StatusBar({
|
|
|
116
149
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" })
|
|
117
150
|
] }) : null,
|
|
118
151
|
/* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
|
|
119
|
-
|
|
152
|
+
statePrefix,
|
|
153
|
+
" ",
|
|
120
154
|
stateLabel
|
|
121
155
|
] }),
|
|
122
156
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
@@ -170,6 +204,15 @@ function StatusBar({
|
|
|
170
204
|
hint ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
171
205
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
172
206
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: hint })
|
|
207
|
+
] }) : null,
|
|
208
|
+
indexState && indexState.indexing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
209
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
210
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
211
|
+
"\u2699 indexing ",
|
|
212
|
+
indexState.currentFile,
|
|
213
|
+
"/",
|
|
214
|
+
indexState.totalFiles
|
|
215
|
+
] })
|
|
173
216
|
] }) : null
|
|
174
217
|
] })
|
|
175
218
|
) }),
|
|
@@ -227,6 +270,10 @@ function StatusBar({
|
|
|
227
270
|
}
|
|
228
271
|
)
|
|
229
272
|
] }) : null,
|
|
273
|
+
modeLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
274
|
+
yolo || autonomy && autonomy !== "off" || eternalStage || elapsedMs !== void 0 || projectName || goalSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
275
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: modeIcon(modeLabel) })
|
|
276
|
+
] }) : null,
|
|
230
277
|
git ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
231
278
|
yolo || elapsedMs !== void 0 || projectName ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
232
279
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
@@ -248,7 +295,7 @@ function StatusBar({
|
|
|
248
295
|
] }) : null
|
|
249
296
|
] })
|
|
250
297
|
] }) : null
|
|
251
|
-
] }) :
|
|
298
|
+
] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
|
|
252
299
|
hasThirdLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
253
300
|
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
254
301
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "todos " }),
|
|
@@ -322,7 +369,7 @@ function StatusBar({
|
|
|
322
369
|
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) || fleetHasActivity ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
323
370
|
/* @__PURE__ */ jsx(BrainChip, { brain })
|
|
324
371
|
] }) : null
|
|
325
|
-
] }) :
|
|
372
|
+
] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
|
|
326
373
|
fleetAgents && fleetAgents.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => (
|
|
327
374
|
// biome-ignore lint/suspicious/noArrayIndexKey: agent list is stable per render
|
|
328
375
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
@@ -348,7 +395,7 @@ function StatusBar({
|
|
|
348
395
|
] })
|
|
349
396
|
] }) : null
|
|
350
397
|
] }, i)
|
|
351
|
-
)) }) :
|
|
398
|
+
)) }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) })
|
|
352
399
|
]
|
|
353
400
|
}
|
|
354
401
|
);
|
|
@@ -779,10 +826,12 @@ function ContextBar({
|
|
|
779
826
|
function AgentsMonitor({
|
|
780
827
|
entries,
|
|
781
828
|
totalCost,
|
|
829
|
+
leaderCost = 0,
|
|
782
830
|
totalTokens,
|
|
783
831
|
nowTick
|
|
784
832
|
}) {
|
|
785
833
|
const all = Object.values(entries);
|
|
834
|
+
const grandCost = leaderCost + totalCost;
|
|
786
835
|
const live = selectLiveAgents(all, nowTick);
|
|
787
836
|
const running = live.filter((e) => e.status === "running").length;
|
|
788
837
|
const totalDone = all.filter((e) => e.status === "success").length;
|
|
@@ -824,9 +873,17 @@ function AgentsMonitor({
|
|
|
824
873
|
fmtTokens2(totalTokens.output),
|
|
825
874
|
"\u2193"
|
|
826
875
|
] }) : null,
|
|
827
|
-
/* @__PURE__ */
|
|
876
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "total" }),
|
|
877
|
+
/* @__PURE__ */ jsxs(Text, { color: "green", bold: true, children: [
|
|
828
878
|
"$",
|
|
829
|
-
|
|
879
|
+
grandCost.toFixed(3)
|
|
880
|
+
] }),
|
|
881
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
882
|
+
"(leader $",
|
|
883
|
+
leaderCost.toFixed(3),
|
|
884
|
+
" \xB7 fleet $",
|
|
885
|
+
totalCost.toFixed(3),
|
|
886
|
+
")"
|
|
830
887
|
] }),
|
|
831
888
|
hiddenIdle > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
832
889
|
"\xB7 ",
|
|
@@ -869,6 +926,10 @@ function AgentsMonitor({
|
|
|
869
926
|
e.extensions && e.extensions > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
870
927
|
"\u26A1\xD7",
|
|
871
928
|
e.extensions
|
|
929
|
+
] }) : null,
|
|
930
|
+
e.cost > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
931
|
+
"$",
|
|
932
|
+
e.cost.toFixed(3)
|
|
872
933
|
] }) : null
|
|
873
934
|
] }),
|
|
874
935
|
e.status === "running" && e.currentTool ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, paddingLeft: 2, children: [
|
|
@@ -954,7 +1015,7 @@ function AutonomyPicker({
|
|
|
954
1015
|
selected,
|
|
955
1016
|
hint
|
|
956
1017
|
}) {
|
|
957
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
1018
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, children: [
|
|
958
1019
|
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Autonomy Mode \u2501\u2501" }),
|
|
959
1020
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc cancel \xB7 Ctrl+C exit" }),
|
|
960
1021
|
options.map((opt, i) => /* @__PURE__ */ jsxs(
|
|
@@ -1077,7 +1138,7 @@ function CheckpointTimeline({
|
|
|
1077
1138
|
onConfirm(selected);
|
|
1078
1139
|
}
|
|
1079
1140
|
});
|
|
1080
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
|
|
1141
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 1, children: [
|
|
1081
1142
|
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
1082
1143
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u27F2 Session Rewind" }),
|
|
1083
1144
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2014 \u2191/\u2193 navigate \xB7 Enter rewind \xB7 Esc cancel" })
|
|
@@ -1147,7 +1208,7 @@ function ConfirmPrompt({
|
|
|
1147
1208
|
suggestedPattern,
|
|
1148
1209
|
onDecision
|
|
1149
1210
|
}) {
|
|
1150
|
-
|
|
1211
|
+
React6.useEffect(() => {
|
|
1151
1212
|
writeOut("\x07");
|
|
1152
1213
|
}, []);
|
|
1153
1214
|
useInput((input2, _key) => {
|
|
@@ -1176,21 +1237,82 @@ function ConfirmPrompt({
|
|
|
1176
1237
|
inputSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: inputSummary }) : null,
|
|
1177
1238
|
showDiff && diff ? /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginY: 1, children: renderDiff(diff) }) : null,
|
|
1178
1239
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
|
|
1179
|
-
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsx(Text, { children: buttonLabels(suggestedPattern).map((l) => /* @__PURE__ */ jsxs(
|
|
1240
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsx(Text, { children: buttonLabels(suggestedPattern).map((l) => /* @__PURE__ */ jsxs(React6.Fragment, { children: [
|
|
1180
1241
|
/* @__PURE__ */ jsx(Text, { bold: true, color: BUTTON_COLOR[l.decision], children: l.bracket }),
|
|
1181
1242
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: l.rest })
|
|
1182
1243
|
] }, l.decision)) }) })
|
|
1183
1244
|
] });
|
|
1184
1245
|
}
|
|
1246
|
+
function EnhancePanel({
|
|
1247
|
+
original,
|
|
1248
|
+
refined,
|
|
1249
|
+
delayMs,
|
|
1250
|
+
onDecision
|
|
1251
|
+
}) {
|
|
1252
|
+
const totalSecs = Math.max(1, Math.ceil(delayMs / 1e3));
|
|
1253
|
+
const [remaining, setRemaining] = React6.useState(totalSecs);
|
|
1254
|
+
const decideRef = React6.useRef(onDecision);
|
|
1255
|
+
decideRef.current = onDecision;
|
|
1256
|
+
React6.useEffect(() => {
|
|
1257
|
+
const id = setInterval(() => {
|
|
1258
|
+
setRemaining((r) => {
|
|
1259
|
+
if (r <= 1) {
|
|
1260
|
+
clearInterval(id);
|
|
1261
|
+
decideRef.current("refined");
|
|
1262
|
+
return 0;
|
|
1263
|
+
}
|
|
1264
|
+
return r - 1;
|
|
1265
|
+
});
|
|
1266
|
+
}, 1e3);
|
|
1267
|
+
return () => clearInterval(id);
|
|
1268
|
+
}, []);
|
|
1269
|
+
useInput((input, key) => {
|
|
1270
|
+
if (key.return) {
|
|
1271
|
+
onDecision("refined");
|
|
1272
|
+
} else if (key.escape) {
|
|
1273
|
+
onDecision("original");
|
|
1274
|
+
} else if (input?.toLowerCase() === "e") {
|
|
1275
|
+
onDecision("edit");
|
|
1276
|
+
}
|
|
1277
|
+
});
|
|
1278
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
1279
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
1280
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u2728 Refined request" }),
|
|
1281
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
1282
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1283
|
+
"\u2014 sending in ",
|
|
1284
|
+
remaining,
|
|
1285
|
+
"s"
|
|
1286
|
+
] })
|
|
1287
|
+
] }),
|
|
1288
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
1289
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "original: " }),
|
|
1290
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: original })
|
|
1291
|
+
] }),
|
|
1292
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
1293
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: "refined: " }),
|
|
1294
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: refined })
|
|
1295
|
+
] }),
|
|
1296
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
|
|
1297
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsxs(Text, { children: [
|
|
1298
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: "[Enter]" }),
|
|
1299
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " send \xB7 " }),
|
|
1300
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "[Esc]" }),
|
|
1301
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " use original \xB7 " }),
|
|
1302
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "[e]" }),
|
|
1303
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "dit" })
|
|
1304
|
+
] }) })
|
|
1305
|
+
] });
|
|
1306
|
+
}
|
|
1185
1307
|
function FilePicker({ query, matches, selected }) {
|
|
1186
1308
|
if (matches.length === 0) {
|
|
1187
|
-
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingX: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1309
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1188
1310
|
"@",
|
|
1189
1311
|
query,
|
|
1190
1312
|
" \u2014 no matches"
|
|
1191
1313
|
] }) });
|
|
1192
1314
|
}
|
|
1193
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
1315
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
1194
1316
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1195
1317
|
"@",
|
|
1196
1318
|
query || "\u2026",
|
|
@@ -1285,6 +1407,9 @@ function helpSections(opts) {
|
|
|
1285
1407
|
{ keys: "Ctrl+F / F2", desc: "fleet orchestration monitor" },
|
|
1286
1408
|
{ keys: "Ctrl+G / F3", desc: "agents live monitor" },
|
|
1287
1409
|
{ keys: "Ctrl+T / F4", desc: "worktree monitor" },
|
|
1410
|
+
{ keys: "F5", desc: "autonomy settings (also Ctrl+S)" },
|
|
1411
|
+
{ keys: "F6", desc: "todos monitor overlay" },
|
|
1412
|
+
{ keys: "F7", desc: "queue panel" },
|
|
1288
1413
|
{ keys: "Esc", desc: "close the open monitor / overlay" }
|
|
1289
1414
|
]
|
|
1290
1415
|
},
|
|
@@ -1860,8 +1985,9 @@ function computeWidths(allRows, cols, maxWidth, sepWidths) {
|
|
|
1860
1985
|
for (const row of allRows) {
|
|
1861
1986
|
for (let c = 0; c < cols; c++) {
|
|
1862
1987
|
const cell = row[c] ?? "";
|
|
1863
|
-
const
|
|
1864
|
-
const
|
|
1988
|
+
const stripped = stripInlineMarkers(cell);
|
|
1989
|
+
const w = longestWord(stripped);
|
|
1990
|
+
const total = strWidth(stripped);
|
|
1865
1991
|
natural[c] = Math.max(natural[c], w, total);
|
|
1866
1992
|
}
|
|
1867
1993
|
}
|
|
@@ -1894,11 +2020,77 @@ function computeWidths(allRows, cols, maxWidth, sepWidths) {
|
|
|
1894
2020
|
return widths;
|
|
1895
2021
|
}
|
|
1896
2022
|
var MIN_COL_WIDTH = 4;
|
|
2023
|
+
var LIGATURE_PAIRS = [
|
|
2024
|
+
["-", ">"],
|
|
2025
|
+
// → arrow
|
|
2026
|
+
["<", "-"],
|
|
2027
|
+
// ←
|
|
2028
|
+
["=", ">"],
|
|
2029
|
+
// ⇒
|
|
2030
|
+
["<", "="],
|
|
2031
|
+
// ≤
|
|
2032
|
+
[">", "="],
|
|
2033
|
+
// ≥
|
|
2034
|
+
["!", "="],
|
|
2035
|
+
// ≠
|
|
2036
|
+
["=", "="],
|
|
2037
|
+
// equality (some fonts)
|
|
2038
|
+
["~", ">"],
|
|
2039
|
+
// ⇝
|
|
2040
|
+
["<", "~"]
|
|
2041
|
+
// ⇜
|
|
2042
|
+
];
|
|
2043
|
+
var ZWSP = "\u200B";
|
|
2044
|
+
function breakLigatures(text) {
|
|
2045
|
+
if (!/[-<=>!~]/.test(text)) return text;
|
|
2046
|
+
let result = "";
|
|
2047
|
+
for (let i = 0; i < text.length; i++) {
|
|
2048
|
+
result += text[i];
|
|
2049
|
+
if (i + 1 >= text.length) break;
|
|
2050
|
+
for (const [a, b] of LIGATURE_PAIRS) {
|
|
2051
|
+
if (text[i] === a && text[i + 1] === b) {
|
|
2052
|
+
result += ZWSP;
|
|
2053
|
+
break;
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
return result;
|
|
2058
|
+
}
|
|
1897
2059
|
function strWidth(s2) {
|
|
1898
2060
|
let width = 0;
|
|
1899
|
-
|
|
1900
|
-
|
|
2061
|
+
const len = s2.length;
|
|
2062
|
+
let i = 0;
|
|
2063
|
+
while (i < len) {
|
|
2064
|
+
if (s2[i] === "\x1B" && i + 1 < len && s2[i + 1] === "[") {
|
|
2065
|
+
i += 2;
|
|
2066
|
+
while (i < len && s2[i] !== "m") i++;
|
|
2067
|
+
if (i < len) i++;
|
|
2068
|
+
continue;
|
|
2069
|
+
}
|
|
2070
|
+
const code = s2.codePointAt(i);
|
|
2071
|
+
const cpLen = code > 65535 ? 2 : 1;
|
|
2072
|
+
if (code === 8205 || // ZWJ — Zero Width Joiner (emoji sequences)
|
|
2073
|
+
code === 8203 || // ZWSP — Zero Width Space
|
|
2074
|
+
code === 8204 || // ZWNJ — Zero Width Non-Joiner
|
|
2075
|
+
code === 8206 || // LRM — Left-to-Right Mark
|
|
2076
|
+
code === 8207 || // RLM — Right-to-Left Mark
|
|
2077
|
+
code === 8288 || // WJ — Word Joiner
|
|
2078
|
+
code === 65279 || // BOM / ZWNBSP
|
|
2079
|
+
code >= 65024 && code <= 65039 || // Variation Selectors 1–16
|
|
2080
|
+
code >= 917760 && code <= 917999) {
|
|
2081
|
+
i += cpLen;
|
|
2082
|
+
continue;
|
|
2083
|
+
}
|
|
1901
2084
|
if (code < 32 || code >= 127 && code < 160) {
|
|
2085
|
+
i += cpLen;
|
|
2086
|
+
continue;
|
|
2087
|
+
}
|
|
2088
|
+
if (code >= 768 && code <= 879 || // Combining Diacritical Marks
|
|
2089
|
+
code >= 6832 && code <= 6911 || // Combining Diacritical Marks Extended
|
|
2090
|
+
code >= 7616 && code <= 7679 || // Combining Diacritical Marks Supplement
|
|
2091
|
+
code >= 8400 && code <= 8447 || // Combining Diacritical Marks for Symbols
|
|
2092
|
+
code >= 65056 && code <= 65071) {
|
|
2093
|
+
i += cpLen;
|
|
1902
2094
|
continue;
|
|
1903
2095
|
}
|
|
1904
2096
|
if (code >= 126976 || // Supplementary Pictographs (U+1F000-U+1FFFF)
|
|
@@ -1911,11 +2103,11 @@ function strWidth(s2) {
|
|
|
1911
2103
|
code >= 9664 && code <= 9726 || // More Geometric Shapes (includes ▶)
|
|
1912
2104
|
code >= 9984 && code <= 10175) {
|
|
1913
2105
|
width += 2;
|
|
2106
|
+
i += cpLen;
|
|
1914
2107
|
continue;
|
|
1915
2108
|
}
|
|
1916
2109
|
if (code >= 4352 && code <= 4447 || // Hangul Jamo
|
|
1917
|
-
code === 9001 || //
|
|
1918
|
-
code === 9002 || // RIGHT-POINTING ANGLE BRACKET
|
|
2110
|
+
code === 9001 || code === 9002 || // Angle brackets
|
|
1919
2111
|
code >= 11904 && code <= 12350 || // CJK Radicals Supplement
|
|
1920
2112
|
code >= 12352 && code <= 42191 || // Hiragana, Katakana, CJK
|
|
1921
2113
|
code >= 44032 && code <= 55203 || // Hangul Syllables
|
|
@@ -1927,9 +2119,11 @@ function strWidth(s2) {
|
|
|
1927
2119
|
code >= 131072 && code <= 196605 || // CJK Extension B+
|
|
1928
2120
|
code >= 196608 && code <= 262141) {
|
|
1929
2121
|
width += 2;
|
|
2122
|
+
i += cpLen;
|
|
1930
2123
|
continue;
|
|
1931
2124
|
}
|
|
1932
2125
|
width += 1;
|
|
2126
|
+
i += cpLen;
|
|
1933
2127
|
}
|
|
1934
2128
|
return width;
|
|
1935
2129
|
}
|
|
@@ -1944,8 +2138,22 @@ function longestWord(s2) {
|
|
|
1944
2138
|
function border(left, mid, right, widths) {
|
|
1945
2139
|
return left + widths.map((w) => "\u2500".repeat(w + 2)).join(mid) + right;
|
|
1946
2140
|
}
|
|
2141
|
+
function stripInlineMarkers(text) {
|
|
2142
|
+
return text.replace(/\*\*(.+?)\*\*/g, "$1").replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "$1").replace(/`(.+?)`/g, "$1").replace(/~~(.+?)~~/g, "$1");
|
|
2143
|
+
}
|
|
2144
|
+
var ANSI_BOLD = "\x1B[1m";
|
|
2145
|
+
var ANSI_RESET = "\x1B[22m";
|
|
2146
|
+
var ANSI_DIM = "\x1B[2m";
|
|
2147
|
+
var ANSI_CYAN = "\x1B[36m";
|
|
2148
|
+
var ANSI_STRIKE = "\x1B[9m";
|
|
2149
|
+
var ANSI_RESET_ALL = "\x1B[0m";
|
|
2150
|
+
function applyInlineAnsi(text) {
|
|
2151
|
+
return text.replace(/\*\*(.+?)\*\*/g, `${ANSI_BOLD}$1${ANSI_RESET}`).replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, `${ANSI_DIM}$1${ANSI_RESET_ALL}`).replace(/`(.+?)`/g, `${ANSI_CYAN}$1${ANSI_RESET_ALL}`).replace(/~~(.+?)~~/g, `${ANSI_STRIKE}$1${ANSI_RESET_ALL}`);
|
|
2152
|
+
}
|
|
1947
2153
|
function renderRow(cells, widths, aligns) {
|
|
1948
|
-
const
|
|
2154
|
+
const styled = cells.map((c) => applyInlineAnsi(c));
|
|
2155
|
+
const safe = styled.map((c) => breakLigatures(c));
|
|
2156
|
+
const wrapped = safe.map((c, i) => wrapCell(c, widths[i] ?? MIN_COL_WIDTH));
|
|
1949
2157
|
const height = Math.max(1, ...wrapped.map((w) => w.length));
|
|
1950
2158
|
const out = [];
|
|
1951
2159
|
for (let line = 0; line < height; line++) {
|
|
@@ -2730,7 +2938,7 @@ function formatToolOutput(toolName, output, ok, _outputBytes, outputLines) {
|
|
|
2730
2938
|
}
|
|
2731
2939
|
var MAX_STREAM_DISPLAY_CHARS = 480;
|
|
2732
2940
|
var MAX_STREAM_LINES = 8;
|
|
2733
|
-
var ToolStreamBox =
|
|
2941
|
+
var ToolStreamBox = React6.memo(function ToolStreamBox2({
|
|
2734
2942
|
name,
|
|
2735
2943
|
text,
|
|
2736
2944
|
startedAt,
|
|
@@ -3050,7 +3258,7 @@ function brainRiskColor(risk) {
|
|
|
3050
3258
|
function assistantContentWidth(termWidth) {
|
|
3051
3259
|
return Math.max(20, termWidth - MESSAGE_PANEL_CHROME_WIDTH);
|
|
3052
3260
|
}
|
|
3053
|
-
var Entry =
|
|
3261
|
+
var Entry = React6.memo(function Entry2({
|
|
3054
3262
|
entry,
|
|
3055
3263
|
termWidth
|
|
3056
3264
|
}) {
|
|
@@ -3442,6 +3650,11 @@ function isHomeEnd(data) {
|
|
|
3442
3650
|
return "end";
|
|
3443
3651
|
return null;
|
|
3444
3652
|
}
|
|
3653
|
+
function isBackspaceOrDelete(data) {
|
|
3654
|
+
if (data === "\x7F" || data === "\b") return "backspace";
|
|
3655
|
+
if (data === "\x1B[3~") return "delete";
|
|
3656
|
+
return null;
|
|
3657
|
+
}
|
|
3445
3658
|
var EMPTY_KEY = {
|
|
3446
3659
|
upArrow: false,
|
|
3447
3660
|
downArrow: false,
|
|
@@ -3477,15 +3690,24 @@ function Input({
|
|
|
3477
3690
|
if (!stdin || disabled) return;
|
|
3478
3691
|
const handleData = (data) => {
|
|
3479
3692
|
const s2 = data.toString();
|
|
3480
|
-
const
|
|
3481
|
-
if (
|
|
3693
|
+
const homeEnd = isHomeEnd(s2);
|
|
3694
|
+
if (homeEnd === "home") {
|
|
3482
3695
|
onKey("", { ...EMPTY_KEY, home: true });
|
|
3483
3696
|
return;
|
|
3484
3697
|
}
|
|
3485
|
-
if (
|
|
3698
|
+
if (homeEnd === "end") {
|
|
3486
3699
|
onKey("", { ...EMPTY_KEY, end: true });
|
|
3487
3700
|
return;
|
|
3488
3701
|
}
|
|
3702
|
+
const bsdel = isBackspaceOrDelete(s2);
|
|
3703
|
+
if (bsdel === "backspace") {
|
|
3704
|
+
onKey("", { ...EMPTY_KEY, backspace: true });
|
|
3705
|
+
return;
|
|
3706
|
+
}
|
|
3707
|
+
if (bsdel === "delete") {
|
|
3708
|
+
onKey("", { ...EMPTY_KEY, delete: true });
|
|
3709
|
+
return;
|
|
3710
|
+
}
|
|
3489
3711
|
const fn = fnKey(s2);
|
|
3490
3712
|
if (fn !== null) onKey("", { ...EMPTY_KEY, fn });
|
|
3491
3713
|
};
|
|
@@ -3541,11 +3763,12 @@ function hintsFor(ctx) {
|
|
|
3541
3763
|
{ key: "Esc", label: "close" },
|
|
3542
3764
|
{ key: "^F", label: "fleet" },
|
|
3543
3765
|
{ key: "^G", label: "agents" },
|
|
3544
|
-
{ key: "^T", label: "worktrees" }
|
|
3766
|
+
{ key: "^T", label: "worktrees" },
|
|
3767
|
+
{ key: "F6", label: "todos" }
|
|
3545
3768
|
];
|
|
3546
3769
|
}
|
|
3547
3770
|
const base = [{ key: "?", label: "help" }];
|
|
3548
|
-
if (ctx.managed) base.push({ key: "PgUp/PgDn", label: "scroll" });
|
|
3771
|
+
if (ctx.managed) base.push({ key: "PgUp/PgDn", label: "scroll" }, { key: "F5", label: "Settings" });
|
|
3549
3772
|
base.push({ key: "^G", label: "agents" }, { key: "^C", label: "stop" });
|
|
3550
3773
|
return base;
|
|
3551
3774
|
}
|
|
@@ -3585,13 +3808,16 @@ function fmtRecentMessage(message) {
|
|
|
3585
3808
|
const text = message.text.replace(/\s+/g, " ");
|
|
3586
3809
|
return text.length > 48 ? `${text.slice(0, 47)}...` : text;
|
|
3587
3810
|
}
|
|
3588
|
-
var LiveActivityStrip =
|
|
3811
|
+
var LiveActivityStrip = React6.memo(function LiveActivityStrip2({
|
|
3589
3812
|
entries,
|
|
3590
3813
|
nowTick,
|
|
3591
3814
|
maxRows = 4
|
|
3592
3815
|
}) {
|
|
3593
3816
|
const running = Object.values(entries).filter((e) => e.status === "running").sort((a, b) => a.startedAt - b.startedAt).slice(0, maxRows);
|
|
3594
|
-
if (running.length === 0)
|
|
3817
|
+
if (running.length === 0) {
|
|
3818
|
+
if (Object.keys(entries).length === 0) return null;
|
|
3819
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingX: 1, children: Array.from({ length: maxRows }, (_, i) => /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }, `empty-${i}`)) });
|
|
3820
|
+
}
|
|
3595
3821
|
const now = Date.now();
|
|
3596
3822
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
3597
3823
|
running.map((e) => {
|
|
@@ -3661,7 +3887,7 @@ function ModelPicker({
|
|
|
3661
3887
|
hint
|
|
3662
3888
|
}) {
|
|
3663
3889
|
if (step === "provider") {
|
|
3664
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
3890
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
3665
3891
|
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Switch model \u2014 Step 1/2: Pick provider \u2501\u2501" }),
|
|
3666
3892
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc cancel \xB7 Ctrl+C exit" }),
|
|
3667
3893
|
providerOptions.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "(no providers with keys \u2014 add one via `wstack auth`)" }) : providerOptions.map((p, i) => /* @__PURE__ */ jsxs(Text, { color: i === selected ? "cyan" : void 0, inverse: i === selected, children: [
|
|
@@ -3686,7 +3912,7 @@ function ModelPicker({
|
|
|
3686
3912
|
const { start, end } = getVisibleWindow(selected, total);
|
|
3687
3913
|
const visibleItems = filteredOptions.slice(start, end);
|
|
3688
3914
|
const searchHint = searchQuery ? ` | filter:"${searchQuery}" \u2192 ${total} match${total === 1 ? "" : "es"}` : total > MAX_VISIBLE ? ` (${total} models \u2014 type to filter)` : "";
|
|
3689
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
3915
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
3690
3916
|
/* @__PURE__ */ jsxs(Text, { color: "cyan", bold: true, children: [
|
|
3691
3917
|
"\u2501\u2501 Switch model \u2014 Step 2/2: Pick model ",
|
|
3692
3918
|
"(",
|
|
@@ -3901,6 +4127,52 @@ function PhasePanel({ phases, nowTick }) {
|
|
|
3901
4127
|
}
|
|
3902
4128
|
);
|
|
3903
4129
|
}
|
|
4130
|
+
function QueuePanel({ items }) {
|
|
4131
|
+
const { stdout } = useStdout();
|
|
4132
|
+
const w = stdout?.columns ?? 80;
|
|
4133
|
+
const h = stdout?.rows ?? 24;
|
|
4134
|
+
const avail = Math.max(10, Math.floor(w * 0.3) - 4);
|
|
4135
|
+
const labelMax = Math.max(4, avail - 7);
|
|
4136
|
+
const trunc = (s2) => {
|
|
4137
|
+
if (s2.length <= labelMax) return s2;
|
|
4138
|
+
return s2.slice(0, labelMax - 1) + "\u2026";
|
|
4139
|
+
};
|
|
4140
|
+
const OVERHEAD = 7;
|
|
4141
|
+
const maxVisible = Math.max(4, h - OVERHEAD);
|
|
4142
|
+
const visible = items.slice(0, maxVisible);
|
|
4143
|
+
const overflow = items.length - visible.length;
|
|
4144
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
4145
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
4146
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "QUEUE" }),
|
|
4147
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: items.length }),
|
|
4148
|
+
overflow > 0 ? /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
4149
|
+
"+",
|
|
4150
|
+
overflow
|
|
4151
|
+
] }) : null,
|
|
4152
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 F7 / Esc to close" })
|
|
4153
|
+
] }) }),
|
|
4154
|
+
items.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No queued messages" }) : /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
4155
|
+
visible.map((item, i) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", flexShrink: 0, children: [
|
|
4156
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4157
|
+
String(i + 1).padStart(2),
|
|
4158
|
+
"."
|
|
4159
|
+
] }),
|
|
4160
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4161
|
+
" ",
|
|
4162
|
+
trunc(item.displayText)
|
|
4163
|
+
] })
|
|
4164
|
+
] }, item.id)),
|
|
4165
|
+
overflow > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", flexShrink: 0, marginTop: 0, children: [
|
|
4166
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2026" }),
|
|
4167
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4168
|
+
" +",
|
|
4169
|
+
overflow,
|
|
4170
|
+
" more"
|
|
4171
|
+
] })
|
|
4172
|
+
] }) : null
|
|
4173
|
+
] })
|
|
4174
|
+
] });
|
|
4175
|
+
}
|
|
3904
4176
|
var MAX_MOUNTED = 500;
|
|
3905
4177
|
function scrollbarThumb(rows, offset, total) {
|
|
3906
4178
|
const scrollable = total > rows;
|
|
@@ -3938,17 +4210,12 @@ function ScrollableHistory({
|
|
|
3938
4210
|
scrollOffset,
|
|
3939
4211
|
viewportRows,
|
|
3940
4212
|
totalLines,
|
|
3941
|
-
onMeasure
|
|
4213
|
+
onMeasure,
|
|
4214
|
+
maxWidth
|
|
3942
4215
|
}) {
|
|
3943
4216
|
const { stdout } = useStdout();
|
|
3944
|
-
const
|
|
3945
|
-
|
|
3946
|
-
const onResize = () => setTermWidth(stdout?.columns ?? 80);
|
|
3947
|
-
process.stdout.on("resize", onResize);
|
|
3948
|
-
return () => {
|
|
3949
|
-
process.stdout.off("resize", onResize);
|
|
3950
|
-
};
|
|
3951
|
-
}, [stdout]);
|
|
4217
|
+
const rawWidth = stdout?.columns ?? 80;
|
|
4218
|
+
const termWidth = maxWidth ? Math.min(rawWidth, maxWidth) : rawWidth;
|
|
3952
4219
|
const tail = streamingText ? tailForDisplay(streamingText, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
3953
4220
|
const toolTail = toolStream?.text ? tailForDisplay(toolStream.text, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
3954
4221
|
const hiddenCount = Math.max(0, entries.length - MAX_MOUNTED);
|
|
@@ -4004,46 +4271,221 @@ function ScrollableHistory({
|
|
|
4004
4271
|
}
|
|
4005
4272
|
var DELAY_PRESETS_MS = [0, 15e3, 3e4, 45e3, 6e4, 12e4];
|
|
4006
4273
|
var SETTINGS_MODES = ["off", "suggest", "auto"];
|
|
4274
|
+
var LOG_LEVELS = ["error", "warn", "info", "debug", "trace"];
|
|
4275
|
+
var AUDIT_LEVELS = ["minimal", "standard", "full"];
|
|
4276
|
+
var COMPACTOR_STRATEGIES = ["hybrid", "intelligent", "selective"];
|
|
4277
|
+
var MAX_ITERATIONS_PRESETS = [100, 200, 500, 1e3, 0];
|
|
4007
4278
|
function formatSettingsDelay(ms) {
|
|
4008
4279
|
if (ms === 0) return "disabled";
|
|
4009
4280
|
if (ms >= 6e4) return `${Math.round(ms / 6e4)}m`;
|
|
4010
4281
|
return `${Math.round(ms / 1e3)}s`;
|
|
4011
4282
|
}
|
|
4283
|
+
function formatMaxIterations(n) {
|
|
4284
|
+
if (n === 0) return "unlimited";
|
|
4285
|
+
return String(n);
|
|
4286
|
+
}
|
|
4012
4287
|
var MODE_DESC = {
|
|
4013
4288
|
off: "Agent stops after each turn (normal)",
|
|
4014
4289
|
suggest: "Shows next-step suggestions after each turn",
|
|
4015
4290
|
auto: "Self-driving \u2014 agent continues automatically"
|
|
4016
4291
|
};
|
|
4292
|
+
var SETTINGS_FIELD_COUNT = 19;
|
|
4017
4293
|
function SettingsPicker({
|
|
4018
4294
|
field,
|
|
4019
4295
|
mode,
|
|
4020
4296
|
delayMs,
|
|
4297
|
+
titleAnimation,
|
|
4298
|
+
yolo,
|
|
4299
|
+
streamFleet,
|
|
4300
|
+
chime,
|
|
4301
|
+
confirmExit,
|
|
4302
|
+
nextPrediction,
|
|
4303
|
+
featureMcp,
|
|
4304
|
+
featurePlugins,
|
|
4305
|
+
featureMemory,
|
|
4306
|
+
featureSkills,
|
|
4307
|
+
featureModelsRegistry,
|
|
4308
|
+
contextAutoCompact,
|
|
4309
|
+
contextStrategy,
|
|
4310
|
+
logLevel,
|
|
4311
|
+
auditLevel,
|
|
4312
|
+
indexOnStart,
|
|
4313
|
+
maxIterations,
|
|
4021
4314
|
hint
|
|
4022
4315
|
}) {
|
|
4316
|
+
const boolVal = (v) => v ? "on" : "off";
|
|
4023
4317
|
const rows = [
|
|
4318
|
+
// ── Autonomy ──
|
|
4319
|
+
{ section: "Autonomy" },
|
|
4024
4320
|
{ label: "Default autonomy mode", value: mode, detail: MODE_DESC[mode] },
|
|
4025
4321
|
{
|
|
4026
4322
|
label: "Auto-proceed delay",
|
|
4027
4323
|
value: formatSettingsDelay(delayMs),
|
|
4028
4324
|
detail: "Wait before auto-continuing in auto mode"
|
|
4325
|
+
},
|
|
4326
|
+
// ── UX ──
|
|
4327
|
+
{ section: "UX" },
|
|
4328
|
+
{
|
|
4329
|
+
label: "Terminal title animation",
|
|
4330
|
+
value: boolVal(titleAnimation),
|
|
4331
|
+
detail: "Animated window/tab title with status"
|
|
4332
|
+
},
|
|
4333
|
+
{
|
|
4334
|
+
label: "YOLO mode",
|
|
4335
|
+
value: boolVal(yolo),
|
|
4336
|
+
detail: "Skip all confirmation prompts"
|
|
4337
|
+
},
|
|
4338
|
+
{
|
|
4339
|
+
label: "Stream fleet to chat",
|
|
4340
|
+
value: boolVal(streamFleet),
|
|
4341
|
+
detail: "Show subagent messages in main chat"
|
|
4342
|
+
},
|
|
4343
|
+
{
|
|
4344
|
+
label: "Completion chime",
|
|
4345
|
+
value: boolVal(chime),
|
|
4346
|
+
detail: "Play a sound when agent finishes"
|
|
4347
|
+
},
|
|
4348
|
+
{
|
|
4349
|
+
label: "Confirm before exit",
|
|
4350
|
+
value: boolVal(confirmExit),
|
|
4351
|
+
detail: "Ask for confirmation on Ctrl+C exit"
|
|
4352
|
+
},
|
|
4353
|
+
{
|
|
4354
|
+
label: "Next-step prediction",
|
|
4355
|
+
value: boolVal(nextPrediction),
|
|
4356
|
+
detail: "Show LLM-predicted next steps (/next)"
|
|
4357
|
+
},
|
|
4358
|
+
// ── Features ──
|
|
4359
|
+
{ section: "Features" },
|
|
4360
|
+
{
|
|
4361
|
+
label: "MCP servers",
|
|
4362
|
+
value: boolVal(featureMcp),
|
|
4363
|
+
detail: "Load MCP servers from config"
|
|
4364
|
+
},
|
|
4365
|
+
{
|
|
4366
|
+
label: "Plugins",
|
|
4367
|
+
value: boolVal(featurePlugins),
|
|
4368
|
+
detail: "Load npm plugins from config"
|
|
4369
|
+
},
|
|
4370
|
+
{
|
|
4371
|
+
label: "Memory",
|
|
4372
|
+
value: boolVal(featureMemory),
|
|
4373
|
+
detail: "Enable remember/forget tools"
|
|
4374
|
+
},
|
|
4375
|
+
{
|
|
4376
|
+
label: "Skills",
|
|
4377
|
+
value: boolVal(featureSkills),
|
|
4378
|
+
detail: "Discover and load skills from disk"
|
|
4379
|
+
},
|
|
4380
|
+
{
|
|
4381
|
+
label: "Models registry",
|
|
4382
|
+
value: boolVal(featureModelsRegistry),
|
|
4383
|
+
detail: "Fetch models.dev catalog at startup"
|
|
4384
|
+
},
|
|
4385
|
+
// ── Context ──
|
|
4386
|
+
{ section: "Context" },
|
|
4387
|
+
{
|
|
4388
|
+
label: "Auto-compact",
|
|
4389
|
+
value: boolVal(contextAutoCompact),
|
|
4390
|
+
detail: "Auto-compact context when thresholds crossed"
|
|
4391
|
+
},
|
|
4392
|
+
{
|
|
4393
|
+
label: "Compactor strategy",
|
|
4394
|
+
value: contextStrategy,
|
|
4395
|
+
detail: "hybrid (fast) | intelligent (LLM) | selective"
|
|
4396
|
+
},
|
|
4397
|
+
// ── Logging ──
|
|
4398
|
+
{ section: "Logging" },
|
|
4399
|
+
{
|
|
4400
|
+
label: "Log level",
|
|
4401
|
+
value: logLevel,
|
|
4402
|
+
detail: "Console log verbosity"
|
|
4403
|
+
},
|
|
4404
|
+
// ── Session ──
|
|
4405
|
+
{ section: "Session" },
|
|
4406
|
+
{
|
|
4407
|
+
label: "Audit level",
|
|
4408
|
+
value: auditLevel,
|
|
4409
|
+
detail: "minimal | standard | full (large)"
|
|
4410
|
+
},
|
|
4411
|
+
// ── Indexing ──
|
|
4412
|
+
{ section: "Indexing" },
|
|
4413
|
+
{
|
|
4414
|
+
label: "Index on session start",
|
|
4415
|
+
value: boolVal(indexOnStart),
|
|
4416
|
+
detail: "Run incremental index at session start"
|
|
4417
|
+
},
|
|
4418
|
+
// ── Tools ──
|
|
4419
|
+
{ section: "Tools" },
|
|
4420
|
+
{
|
|
4421
|
+
label: "Max iterations",
|
|
4422
|
+
value: formatMaxIterations(maxIterations),
|
|
4423
|
+
detail: "100\u20131000 or unlimited (0)"
|
|
4029
4424
|
}
|
|
4030
4425
|
];
|
|
4031
|
-
|
|
4426
|
+
const fieldRowIndex = [];
|
|
4427
|
+
for (let i = 0; i < rows.length; i++) {
|
|
4428
|
+
if (!rows[i].section) fieldRowIndex.push(i);
|
|
4429
|
+
}
|
|
4430
|
+
const VISIBLE_FIELDS = 8;
|
|
4431
|
+
const totalFields = fieldRowIndex.length;
|
|
4432
|
+
const windowStart = totalFields <= VISIBLE_FIELDS ? 0 : Math.max(0, Math.min(field - Math.floor(VISIBLE_FIELDS / 2), totalFields - VISIBLE_FIELDS));
|
|
4433
|
+
const windowEnd = Math.min(windowStart + VISIBLE_FIELDS, totalFields);
|
|
4434
|
+
const hasAbove = windowStart > 0;
|
|
4435
|
+
const hasBelow = windowEnd < totalFields;
|
|
4436
|
+
const sectionFields = [];
|
|
4437
|
+
let curHeader = -1;
|
|
4438
|
+
for (let i = 0; i < rows.length; i++) {
|
|
4439
|
+
if (rows[i].section) curHeader = i;
|
|
4440
|
+
else if (curHeader >= 0) {
|
|
4441
|
+
const fieldIdx = fieldRowIndex.indexOf(i);
|
|
4442
|
+
if (fieldIdx === -1) continue;
|
|
4443
|
+
const entry = sectionFields.find((s2) => s2.headerIdx === curHeader);
|
|
4444
|
+
if (entry) {
|
|
4445
|
+
entry.fieldEnd = fieldIdx + 1;
|
|
4446
|
+
} else {
|
|
4447
|
+
sectionFields.push({ headerIdx: curHeader, fieldStart: fieldIdx, fieldEnd: fieldIdx + 1 });
|
|
4448
|
+
}
|
|
4449
|
+
}
|
|
4450
|
+
}
|
|
4451
|
+
const shouldShowSection = (headerIdx) => {
|
|
4452
|
+
const sec = sectionFields.find((s2) => s2.headerIdx === headerIdx);
|
|
4453
|
+
if (!sec) return false;
|
|
4454
|
+
return sec.fieldStart < windowEnd && sec.fieldEnd > windowStart;
|
|
4455
|
+
};
|
|
4456
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
4032
4457
|
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Settings \u2501\u2501" }),
|
|
4033
4458
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 field \xB7 \u2190/\u2192 change \xB7 Enter save \xB7 Esc cancel" }),
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4459
|
+
hasAbove ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2191 ${windowStart} field${windowStart === 1 ? "" : "s"} above` }) : null,
|
|
4460
|
+
rows.map((row, i) => {
|
|
4461
|
+
const fieldAtRow = fieldRowIndex.indexOf(i);
|
|
4462
|
+
if (fieldAtRow === -1) {
|
|
4463
|
+
if (shouldShowSection(i)) {
|
|
4464
|
+
return /* @__PURE__ */ jsxs(Text, { bold: true, color: "green", children: [
|
|
4465
|
+
"\u2500\u2500 ",
|
|
4466
|
+
row.section,
|
|
4467
|
+
" \u2500\u2500"
|
|
4468
|
+
] }, `section-${i}`);
|
|
4469
|
+
}
|
|
4470
|
+
return null;
|
|
4471
|
+
}
|
|
4472
|
+
if (fieldAtRow < windowStart || fieldAtRow >= windowEnd) return null;
|
|
4473
|
+
const selected = fieldAtRow === field;
|
|
4474
|
+
return /* @__PURE__ */ jsxs(Text, { color: selected ? "yellow" : void 0, inverse: selected, children: [
|
|
4475
|
+
selected ? "\u203A " : " ",
|
|
4476
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: (row.label ?? "").padEnd(26) }),
|
|
4477
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: String(row.value ?? "").padEnd(12) }),
|
|
4478
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: row.detail ?? "" })
|
|
4479
|
+
] }, `row-${i}`);
|
|
4480
|
+
}),
|
|
4481
|
+
hasBelow ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2193 ${totalFields - windowEnd} field${totalFields - windowEnd === 1 ? "" : "s"} below` }) : null,
|
|
4040
4482
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Persisted to ~/.wrongstack/config.json" }),
|
|
4041
4483
|
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
4042
4484
|
] });
|
|
4043
4485
|
}
|
|
4044
4486
|
function SlashMenu({ query, matches, selected }) {
|
|
4045
4487
|
const placeholder = query ? `/${query}` : "/";
|
|
4046
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
4488
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
4047
4489
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4048
4490
|
placeholder || "/",
|
|
4049
4491
|
" \u2014 \u2191/\u2193 select, Enter dispatch, Tab autocomplete, Esc close"
|
|
@@ -4063,6 +4505,110 @@ function SlashMenu({ query, matches, selected }) {
|
|
|
4063
4505
|
matches.length === 0 && /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No matching commands" })
|
|
4064
4506
|
] });
|
|
4065
4507
|
}
|
|
4508
|
+
function TodosMonitor({ todos }) {
|
|
4509
|
+
const { stdout } = useStdout();
|
|
4510
|
+
useInput((_input, key) => {
|
|
4511
|
+
if (key.escape) ;
|
|
4512
|
+
});
|
|
4513
|
+
const done = todos.filter((t) => t.status === "completed").length;
|
|
4514
|
+
const inProgress = todos.filter((t) => t.status === "in_progress").length;
|
|
4515
|
+
const pending = todos.filter((t) => t.status === "pending").length;
|
|
4516
|
+
const w = stdout?.columns ?? 80;
|
|
4517
|
+
const twoCols = w >= 100;
|
|
4518
|
+
const mid = Math.ceil(todos.length / 2);
|
|
4519
|
+
const colWidth = twoCols ? Math.floor((w - 8) / 2) : w - 6;
|
|
4520
|
+
const trunc = (text, maxLen) => {
|
|
4521
|
+
if (text.length <= maxLen) return text;
|
|
4522
|
+
return text.slice(0, maxLen - 1) + "\u2026";
|
|
4523
|
+
};
|
|
4524
|
+
const renderRow3 = (t, idx) => {
|
|
4525
|
+
const num = String(idx + 1).padStart(2);
|
|
4526
|
+
const label = t.status === "in_progress" && t.activeForm ? t.activeForm : t.content;
|
|
4527
|
+
const display = trunc(label, colWidth - 8);
|
|
4528
|
+
if (t.status === "completed") {
|
|
4529
|
+
return /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4530
|
+
" ",
|
|
4531
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4532
|
+
num,
|
|
4533
|
+
"."
|
|
4534
|
+
] }),
|
|
4535
|
+
" ",
|
|
4536
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: "[x]" }),
|
|
4537
|
+
" ",
|
|
4538
|
+
display
|
|
4539
|
+
] }, t.id);
|
|
4540
|
+
}
|
|
4541
|
+
if (t.status === "in_progress") {
|
|
4542
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
4543
|
+
" ",
|
|
4544
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4545
|
+
num,
|
|
4546
|
+
"."
|
|
4547
|
+
] }),
|
|
4548
|
+
" ",
|
|
4549
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: "[~]" }),
|
|
4550
|
+
" ",
|
|
4551
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: display })
|
|
4552
|
+
] }, t.id);
|
|
4553
|
+
}
|
|
4554
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
4555
|
+
" ",
|
|
4556
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4557
|
+
num,
|
|
4558
|
+
"."
|
|
4559
|
+
] }),
|
|
4560
|
+
" ",
|
|
4561
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "[ ]" }),
|
|
4562
|
+
" ",
|
|
4563
|
+
display
|
|
4564
|
+
] }, t.id);
|
|
4565
|
+
};
|
|
4566
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
4567
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, marginBottom: 1, children: [
|
|
4568
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "TODOS" }),
|
|
4569
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
4570
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4571
|
+
done,
|
|
4572
|
+
"/",
|
|
4573
|
+
todos.length,
|
|
4574
|
+
" done"
|
|
4575
|
+
] }),
|
|
4576
|
+
inProgress > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4577
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
4578
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
4579
|
+
"\u231B",
|
|
4580
|
+
inProgress
|
|
4581
|
+
] })
|
|
4582
|
+
] }) : null,
|
|
4583
|
+
pending > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4584
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
4585
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4586
|
+
"\u2610",
|
|
4587
|
+
pending
|
|
4588
|
+
] })
|
|
4589
|
+
] }) : null,
|
|
4590
|
+
done > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4591
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
4592
|
+
/* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
4593
|
+
"\u2713",
|
|
4594
|
+
done
|
|
4595
|
+
] })
|
|
4596
|
+
] }) : null,
|
|
4597
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 F6 / Esc to close" })
|
|
4598
|
+
] }),
|
|
4599
|
+
todos.length === 0 ? /* @__PURE__ */ jsx(Box, { marginY: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No todos. The agent will create them as it plans work." }) }) : twoCols ? (
|
|
4600
|
+
/* Two-column layout: split the list in half, render side-by-side.
|
|
4601
|
+
Pass the absolute position so numbering is continuous across columns. */
|
|
4602
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
4603
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", width: colWidth, children: todos.slice(0, mid).map((t, i) => renderRow3(t, i)) }),
|
|
4604
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", width: colWidth, children: todos.slice(mid).map((t, i) => renderRow3(t, mid + i)) })
|
|
4605
|
+
] })
|
|
4606
|
+
) : (
|
|
4607
|
+
/* Single column layout */
|
|
4608
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", children: todos.map(renderRow3) })
|
|
4609
|
+
)
|
|
4610
|
+
] });
|
|
4611
|
+
}
|
|
4066
4612
|
var fmtElapsed5 = (ms) => {
|
|
4067
4613
|
const s2 = Math.floor(ms / 1e3);
|
|
4068
4614
|
const m = Math.floor(s2 / 60);
|
|
@@ -4395,6 +4941,34 @@ function runGit(cwd, args) {
|
|
|
4395
4941
|
}
|
|
4396
4942
|
});
|
|
4397
4943
|
}
|
|
4944
|
+
function useBrainEvents(events, dispatch) {
|
|
4945
|
+
useEffect(() => {
|
|
4946
|
+
const requestSummary = (request) => `${request.source}: ${request.question}`.slice(0, 80);
|
|
4947
|
+
const addBrainEntry = (status, payload) => {
|
|
4948
|
+
const p = payload;
|
|
4949
|
+
const decision = p.decision.optionId ?? p.decision.text ?? p.decision.reason ?? p.decision.prompt ?? p.decision.type;
|
|
4950
|
+
dispatch({ type: "brainStatus", state: status, source: p.request.source, risk: p.request.risk, summary: decision });
|
|
4951
|
+
if (status === "ask_human") {
|
|
4952
|
+
dispatch({ type: "brainPromptSet", prompt: { requestId: p.request.id, source: p.request.source, risk: p.request.risk, question: p.request.question, context: p.request.context, options: p.request.options } });
|
|
4953
|
+
} else {
|
|
4954
|
+
dispatch({ type: "brainPromptClear" });
|
|
4955
|
+
}
|
|
4956
|
+
dispatch({ type: "addEntry", entry: { kind: "brain", status, source: p.request.source, risk: p.request.risk, question: p.request.question, decision, rationale: p.decision.rationale } });
|
|
4957
|
+
};
|
|
4958
|
+
const offRequested = events.on("brain.decision_requested", ({ request }) => {
|
|
4959
|
+
dispatch({ type: "brainStatus", state: "deciding", source: request.source, risk: request.risk, summary: requestSummary(request) });
|
|
4960
|
+
});
|
|
4961
|
+
const offAnswered = events.on("brain.decision_answered", (payload) => addBrainEntry("answered", payload));
|
|
4962
|
+
const offAskHuman = events.on("brain.decision_ask_human", (payload) => addBrainEntry("ask_human", payload));
|
|
4963
|
+
const offDenied = events.on("brain.decision_denied", (payload) => addBrainEntry("denied", payload));
|
|
4964
|
+
return () => {
|
|
4965
|
+
offRequested();
|
|
4966
|
+
offAnswered();
|
|
4967
|
+
offAskHuman();
|
|
4968
|
+
offDenied();
|
|
4969
|
+
};
|
|
4970
|
+
}, [events, dispatch]);
|
|
4971
|
+
}
|
|
4398
4972
|
var STREAM_COLORS = ["cyan", "magenta", "yellow", "green", "blue"];
|
|
4399
4973
|
function labelFor(labelsRef, id, name) {
|
|
4400
4974
|
const m = labelsRef.current;
|
|
@@ -4493,34 +5067,6 @@ function useSubagentEvents(events, dispatch, setActiveMaxContext) {
|
|
|
4493
5067
|
};
|
|
4494
5068
|
}, [events, dispatch, setActiveMaxContext, lbl]);
|
|
4495
5069
|
}
|
|
4496
|
-
function useBrainEvents(events, dispatch) {
|
|
4497
|
-
useEffect(() => {
|
|
4498
|
-
const requestSummary = (request) => `${request.source}: ${request.question}`.slice(0, 80);
|
|
4499
|
-
const addBrainEntry = (status, payload) => {
|
|
4500
|
-
const p = payload;
|
|
4501
|
-
const decision = p.decision.optionId ?? p.decision.text ?? p.decision.reason ?? p.decision.prompt ?? p.decision.type;
|
|
4502
|
-
dispatch({ type: "brainStatus", state: status, source: p.request.source, risk: p.request.risk, summary: decision });
|
|
4503
|
-
if (status === "ask_human") {
|
|
4504
|
-
dispatch({ type: "brainPromptSet", prompt: { requestId: p.request.id, source: p.request.source, risk: p.request.risk, question: p.request.question, context: p.request.context, options: p.request.options } });
|
|
4505
|
-
} else {
|
|
4506
|
-
dispatch({ type: "brainPromptClear" });
|
|
4507
|
-
}
|
|
4508
|
-
dispatch({ type: "addEntry", entry: { kind: "brain", status, source: p.request.source, risk: p.request.risk, question: p.request.question, decision, rationale: p.decision.rationale } });
|
|
4509
|
-
};
|
|
4510
|
-
const offRequested = events.on("brain.decision_requested", ({ request }) => {
|
|
4511
|
-
dispatch({ type: "brainStatus", state: "deciding", source: request.source, risk: request.risk, summary: requestSummary(request) });
|
|
4512
|
-
});
|
|
4513
|
-
const offAnswered = events.on("brain.decision_answered", (payload) => addBrainEntry("answered", payload));
|
|
4514
|
-
const offAskHuman = events.on("brain.decision_ask_human", (payload) => addBrainEntry("ask_human", payload));
|
|
4515
|
-
const offDenied = events.on("brain.decision_denied", (payload) => addBrainEntry("denied", payload));
|
|
4516
|
-
return () => {
|
|
4517
|
-
offRequested();
|
|
4518
|
-
offAnswered();
|
|
4519
|
-
offAskHuman();
|
|
4520
|
-
offDenied();
|
|
4521
|
-
};
|
|
4522
|
-
}, [events, dispatch]);
|
|
4523
|
-
}
|
|
4524
5070
|
var USAGE = "Usage:\n /kill \u2014 list active processes + breaker state\n /kill list \u2014 same as /kill\n /kill all \u2014 kill all tracked processes (SIGTERM \u2192 SIGKILL)\n /kill force \u2014 kill all with SIGKILL immediately\n /kill reset \u2014 reset the circuit breaker to closed\n /kill <pid> \u2014 kill a specific process by PID";
|
|
4525
5071
|
function createKillSlashCommand() {
|
|
4526
5072
|
return {
|
|
@@ -4803,7 +5349,22 @@ function reducer(state, action) {
|
|
|
4803
5349
|
queue: [],
|
|
4804
5350
|
nextQueueId: 1,
|
|
4805
5351
|
scrollOffset: 0,
|
|
4806
|
-
pendingNewLines: 0
|
|
5352
|
+
pendingNewLines: 0,
|
|
5353
|
+
// Reset fleet state on /clear so old subagent entries don't
|
|
5354
|
+
// cause the LiveActivityStrip to render stale spacers, and
|
|
5355
|
+
// the fleet cost/tokens chips show zero.
|
|
5356
|
+
fleet: {},
|
|
5357
|
+
fleetCost: 0,
|
|
5358
|
+
fleetTokens: { input: 0, output: 0 },
|
|
5359
|
+
leader: {
|
|
5360
|
+
iterations: 0,
|
|
5361
|
+
toolCalls: 0,
|
|
5362
|
+
recentTools: [],
|
|
5363
|
+
currentTool: void 0,
|
|
5364
|
+
startedAt: Date.now(),
|
|
5365
|
+
lastEventAt: Date.now(),
|
|
5366
|
+
iterating: false
|
|
5367
|
+
}
|
|
4807
5368
|
};
|
|
4808
5369
|
}
|
|
4809
5370
|
case "streamDelta":
|
|
@@ -5084,6 +5645,23 @@ function reducer(state, action) {
|
|
|
5084
5645
|
field: 0,
|
|
5085
5646
|
mode: action.mode,
|
|
5086
5647
|
delayMs: action.delayMs,
|
|
5648
|
+
titleAnimation: action.titleAnimation,
|
|
5649
|
+
yolo: action.yolo,
|
|
5650
|
+
streamFleet: action.streamFleet,
|
|
5651
|
+
chime: action.chime,
|
|
5652
|
+
confirmExit: action.confirmExit,
|
|
5653
|
+
nextPrediction: action.nextPrediction,
|
|
5654
|
+
featureMcp: action.featureMcp,
|
|
5655
|
+
featurePlugins: action.featurePlugins,
|
|
5656
|
+
featureMemory: action.featureMemory,
|
|
5657
|
+
featureSkills: action.featureSkills,
|
|
5658
|
+
featureModelsRegistry: action.featureModelsRegistry,
|
|
5659
|
+
contextAutoCompact: action.contextAutoCompact,
|
|
5660
|
+
contextStrategy: action.contextStrategy,
|
|
5661
|
+
logLevel: action.logLevel,
|
|
5662
|
+
auditLevel: action.auditLevel,
|
|
5663
|
+
indexOnStart: action.indexOnStart,
|
|
5664
|
+
maxIterations: action.maxIterations,
|
|
5087
5665
|
hint: void 0
|
|
5088
5666
|
}
|
|
5089
5667
|
};
|
|
@@ -5093,37 +5671,68 @@ function reducer(state, action) {
|
|
|
5093
5671
|
settingsPicker: { ...state.settingsPicker, open: false, hint: void 0 }
|
|
5094
5672
|
};
|
|
5095
5673
|
case "settingsFieldMove": {
|
|
5096
|
-
const next = (state.settingsPicker.field + action.delta +
|
|
5674
|
+
const next = (state.settingsPicker.field + action.delta + SETTINGS_FIELD_COUNT) % SETTINGS_FIELD_COUNT;
|
|
5097
5675
|
return {
|
|
5098
5676
|
...state,
|
|
5099
5677
|
settingsPicker: { ...state.settingsPicker, field: next, hint: void 0 }
|
|
5100
5678
|
};
|
|
5101
5679
|
}
|
|
5102
5680
|
case "settingsFieldSet": {
|
|
5103
|
-
const field = action.field
|
|
5681
|
+
const field = action.field >= 0 && action.field < SETTINGS_FIELD_COUNT ? action.field : 0;
|
|
5104
5682
|
return { ...state, settingsPicker: { ...state.settingsPicker, field, hint: void 0 } };
|
|
5105
5683
|
}
|
|
5106
5684
|
case "settingsValueChange": {
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
const
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5685
|
+
const sp = state.settingsPicker;
|
|
5686
|
+
const f = sp.field;
|
|
5687
|
+
if (f === 0) {
|
|
5688
|
+
const i = SETTINGS_MODES.indexOf(sp.mode);
|
|
5689
|
+
const base = i < 0 ? 0 : i;
|
|
5690
|
+
const next = (base + action.delta + SETTINGS_MODES.length) % SETTINGS_MODES.length;
|
|
5691
|
+
return { ...state, settingsPicker: { ...sp, mode: SETTINGS_MODES[next], hint: void 0 } };
|
|
5692
|
+
}
|
|
5693
|
+
if (f === 1) {
|
|
5694
|
+
const j = DELAY_PRESETS_MS.indexOf(sp.delayMs);
|
|
5695
|
+
const base = j < 0 ? 0 : j;
|
|
5696
|
+
const next = (base + action.delta + DELAY_PRESETS_MS.length) % DELAY_PRESETS_MS.length;
|
|
5697
|
+
return { ...state, settingsPicker: { ...sp, delayMs: DELAY_PRESETS_MS[next], hint: void 0 } };
|
|
5698
|
+
}
|
|
5699
|
+
if (f === 2) return { ...state, settingsPicker: { ...sp, titleAnimation: !sp.titleAnimation, hint: void 0 } };
|
|
5700
|
+
if (f === 3) return { ...state, settingsPicker: { ...sp, yolo: !sp.yolo, hint: void 0 } };
|
|
5701
|
+
if (f === 4) return { ...state, settingsPicker: { ...sp, streamFleet: !sp.streamFleet, hint: void 0 } };
|
|
5702
|
+
if (f === 5) return { ...state, settingsPicker: { ...sp, chime: !sp.chime, hint: void 0 } };
|
|
5703
|
+
if (f === 6) return { ...state, settingsPicker: { ...sp, confirmExit: !sp.confirmExit, hint: void 0 } };
|
|
5704
|
+
if (f === 7) return { ...state, settingsPicker: { ...sp, nextPrediction: !sp.nextPrediction, hint: void 0 } };
|
|
5705
|
+
if (f === 8) return { ...state, settingsPicker: { ...sp, featureMcp: !sp.featureMcp, hint: void 0 } };
|
|
5706
|
+
if (f === 9) return { ...state, settingsPicker: { ...sp, featurePlugins: !sp.featurePlugins, hint: void 0 } };
|
|
5707
|
+
if (f === 10) return { ...state, settingsPicker: { ...sp, featureMemory: !sp.featureMemory, hint: void 0 } };
|
|
5708
|
+
if (f === 11) return { ...state, settingsPicker: { ...sp, featureSkills: !sp.featureSkills, hint: void 0 } };
|
|
5709
|
+
if (f === 12) return { ...state, settingsPicker: { ...sp, featureModelsRegistry: !sp.featureModelsRegistry, hint: void 0 } };
|
|
5710
|
+
if (f === 13) return { ...state, settingsPicker: { ...sp, contextAutoCompact: !sp.contextAutoCompact, hint: void 0 } };
|
|
5711
|
+
if (f === 14) {
|
|
5712
|
+
const i = COMPACTOR_STRATEGIES.indexOf(sp.contextStrategy);
|
|
5713
|
+
const base = i < 0 ? 0 : i;
|
|
5714
|
+
const next = (base + action.delta + COMPACTOR_STRATEGIES.length) % COMPACTOR_STRATEGIES.length;
|
|
5715
|
+
return { ...state, settingsPicker: { ...sp, contextStrategy: COMPACTOR_STRATEGIES[next], hint: void 0 } };
|
|
5716
|
+
}
|
|
5717
|
+
if (f === 15) {
|
|
5718
|
+
const i = LOG_LEVELS.indexOf(sp.logLevel);
|
|
5719
|
+
const base = i < 0 ? 0 : i;
|
|
5720
|
+
const next = (base + action.delta + LOG_LEVELS.length) % LOG_LEVELS.length;
|
|
5721
|
+
return { ...state, settingsPicker: { ...sp, logLevel: LOG_LEVELS[next], hint: void 0 } };
|
|
5722
|
+
}
|
|
5723
|
+
if (f === 16) {
|
|
5724
|
+
const i = AUDIT_LEVELS.indexOf(sp.auditLevel);
|
|
5725
|
+
const base = i < 0 ? 0 : i;
|
|
5726
|
+
const next = (base + action.delta + AUDIT_LEVELS.length) % AUDIT_LEVELS.length;
|
|
5727
|
+
return { ...state, settingsPicker: { ...sp, auditLevel: AUDIT_LEVELS[next], hint: void 0 } };
|
|
5728
|
+
}
|
|
5729
|
+
if (f === 17) return { ...state, settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: void 0 } };
|
|
5730
|
+
{
|
|
5731
|
+
const j = MAX_ITERATIONS_PRESETS.indexOf(sp.maxIterations);
|
|
5732
|
+
const base = j < 0 ? 0 : j;
|
|
5733
|
+
const next = (base + action.delta + MAX_ITERATIONS_PRESETS.length) % MAX_ITERATIONS_PRESETS.length;
|
|
5734
|
+
return { ...state, settingsPicker: { ...sp, maxIterations: MAX_ITERATIONS_PRESETS[next], hint: void 0 } };
|
|
5115
5735
|
}
|
|
5116
|
-
const j = DELAY_PRESETS_MS.indexOf(state.settingsPicker.delayMs);
|
|
5117
|
-
const base = j < 0 ? 0 : j;
|
|
5118
|
-
const next = (base + action.delta + DELAY_PRESETS_MS.length) % DELAY_PRESETS_MS.length;
|
|
5119
|
-
return {
|
|
5120
|
-
...state,
|
|
5121
|
-
settingsPicker: {
|
|
5122
|
-
...state.settingsPicker,
|
|
5123
|
-
delayMs: DELAY_PRESETS_MS[next],
|
|
5124
|
-
hint: void 0
|
|
5125
|
-
}
|
|
5126
|
-
};
|
|
5127
5736
|
}
|
|
5128
5737
|
case "settingsHint":
|
|
5129
5738
|
return { ...state, settingsPicker: { ...state.settingsPicker, hint: action.text } };
|
|
@@ -5131,6 +5740,14 @@ function reducer(state, action) {
|
|
|
5131
5740
|
return { ...state, confirmQueue: [...state.confirmQueue, action.info] };
|
|
5132
5741
|
case "confirmClose":
|
|
5133
5742
|
return { ...state, confirmQueue: state.confirmQueue.slice(1) };
|
|
5743
|
+
case "enhanceOpen":
|
|
5744
|
+
return { ...state, enhance: action.info };
|
|
5745
|
+
case "enhanceClose":
|
|
5746
|
+
return { ...state, enhance: null };
|
|
5747
|
+
case "enhanceSet":
|
|
5748
|
+
return { ...state, enhanceEnabled: action.enabled };
|
|
5749
|
+
case "enhanceBusy":
|
|
5750
|
+
return { ...state, enhanceBusy: action.on };
|
|
5134
5751
|
case "resetContextChip":
|
|
5135
5752
|
return { ...state, contextChipVersion: state.contextChipVersion + 1 };
|
|
5136
5753
|
// --- Fleet ---
|
|
@@ -5362,8 +5979,24 @@ function reducer(state, action) {
|
|
|
5362
5979
|
};
|
|
5363
5980
|
}
|
|
5364
5981
|
case "fleetCost": {
|
|
5982
|
+
let fleet = state.fleet;
|
|
5983
|
+
if (action.perAgent) {
|
|
5984
|
+
let changed = false;
|
|
5985
|
+
const next = {};
|
|
5986
|
+
for (const [id, entry] of Object.entries(state.fleet)) {
|
|
5987
|
+
const cost = action.perAgent[id]?.cost;
|
|
5988
|
+
if (cost !== void 0 && cost !== entry.cost) {
|
|
5989
|
+
next[id] = { ...entry, cost };
|
|
5990
|
+
changed = true;
|
|
5991
|
+
} else {
|
|
5992
|
+
next[id] = entry;
|
|
5993
|
+
}
|
|
5994
|
+
}
|
|
5995
|
+
if (changed) fleet = next;
|
|
5996
|
+
}
|
|
5365
5997
|
return {
|
|
5366
5998
|
...state,
|
|
5999
|
+
fleet,
|
|
5367
6000
|
fleetCost: action.cost,
|
|
5368
6001
|
fleetTokens: action.input !== void 0 || action.output !== void 0 ? {
|
|
5369
6002
|
input: action.input ?? state.fleetTokens.input,
|
|
@@ -5442,6 +6075,12 @@ function reducer(state, action) {
|
|
|
5442
6075
|
case "toggleHelp": {
|
|
5443
6076
|
return { ...state, helpOpen: !state.helpOpen };
|
|
5444
6077
|
}
|
|
6078
|
+
case "toggleTodosMonitor": {
|
|
6079
|
+
return { ...state, todosMonitorOpen: !state.todosMonitorOpen };
|
|
6080
|
+
}
|
|
6081
|
+
case "toggleQueuePanel": {
|
|
6082
|
+
return { ...state, queuePanelOpen: !state.queuePanelOpen };
|
|
6083
|
+
}
|
|
5445
6084
|
case "checkpointReceived": {
|
|
5446
6085
|
const existing = state.checkpoints.find((c) => c.promptIndex === action.cp.promptIndex);
|
|
5447
6086
|
if (existing) return state;
|
|
@@ -5747,6 +6386,21 @@ function selectedSlashCommandLine(picker) {
|
|
|
5747
6386
|
const picked = picker.matches[picker.selected];
|
|
5748
6387
|
return picked ? `/${picked.name}` : null;
|
|
5749
6388
|
}
|
|
6389
|
+
function rehydrateHistory(messages, startId) {
|
|
6390
|
+
const entries = [];
|
|
6391
|
+
for (const msg of messages) {
|
|
6392
|
+
if (msg.role === "system") continue;
|
|
6393
|
+
const text = typeof msg.content === "string" ? msg.content : msg.content.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
6394
|
+
const trimmed = text.trim();
|
|
6395
|
+
if (!trimmed) continue;
|
|
6396
|
+
if (msg.role === "user") {
|
|
6397
|
+
entries.push({ id: startId++, kind: "user", text: trimmed });
|
|
6398
|
+
} else if (msg.role === "assistant") {
|
|
6399
|
+
entries.push({ id: startId++, kind: "assistant", text: trimmed });
|
|
6400
|
+
}
|
|
6401
|
+
}
|
|
6402
|
+
return entries;
|
|
6403
|
+
}
|
|
5750
6404
|
var PASTE_THRESHOLD_CHARS = 200;
|
|
5751
6405
|
function App({
|
|
5752
6406
|
agent,
|
|
@@ -5760,6 +6414,11 @@ function App({
|
|
|
5760
6414
|
banner = true,
|
|
5761
6415
|
queueStore,
|
|
5762
6416
|
yolo = false,
|
|
6417
|
+
chime = false,
|
|
6418
|
+
confirmExit = true,
|
|
6419
|
+
enhanceEnabled = true,
|
|
6420
|
+
enhanceController,
|
|
6421
|
+
enhanceDelayMs = 4e3,
|
|
5763
6422
|
getYolo,
|
|
5764
6423
|
getAutonomy,
|
|
5765
6424
|
getEternalEngine,
|
|
@@ -5791,7 +6450,9 @@ function App({
|
|
|
5791
6450
|
initialGoal,
|
|
5792
6451
|
initialAsk,
|
|
5793
6452
|
sessionsDir,
|
|
5794
|
-
managed = false
|
|
6453
|
+
managed = false,
|
|
6454
|
+
modeLabel,
|
|
6455
|
+
getModeLabel
|
|
5795
6456
|
}) {
|
|
5796
6457
|
const { exit } = useApp();
|
|
5797
6458
|
const [liveModel, setLiveModel] = useState(model);
|
|
@@ -5799,7 +6460,13 @@ function App({
|
|
|
5799
6460
|
const [activeMaxContext, setActiveMaxContext] = useState(effectiveMaxContext);
|
|
5800
6461
|
const [yoloLive, setYoloLive] = useState(yolo);
|
|
5801
6462
|
const [autonomyLive, setAutonomyLive] = useState(getAutonomy?.() ?? "off");
|
|
6463
|
+
const [liveModeLabel, setLiveModeLabel] = useState(modeLabel ?? "");
|
|
5802
6464
|
const [hiddenItems, setHiddenItems] = useState(statuslineHiddenItems);
|
|
6465
|
+
const [indexState, setIndexState] = useState(() => getIndexState());
|
|
6466
|
+
useEffect(() => {
|
|
6467
|
+
setIndexState(getIndexState());
|
|
6468
|
+
return onIndexStateChange((next) => setIndexState(next));
|
|
6469
|
+
}, []);
|
|
5803
6470
|
const { stdout } = useStdout();
|
|
5804
6471
|
const [termRows, setTermRows] = useState(stdout?.rows ?? 24);
|
|
5805
6472
|
useEffect(() => {
|
|
@@ -5840,19 +6507,34 @@ function App({
|
|
|
5840
6507
|
}).catch(() => {
|
|
5841
6508
|
});
|
|
5842
6509
|
}, [projectRoot]);
|
|
6510
|
+
const restoredEntries = (() => {
|
|
6511
|
+
const msgs = agent.ctx.messages;
|
|
6512
|
+
if (!msgs || msgs.length === 0) return [];
|
|
6513
|
+
const visible = msgs.filter((m) => m.role !== "system");
|
|
6514
|
+
if (visible.length === 0) return [];
|
|
6515
|
+
return rehydrateHistory(
|
|
6516
|
+
visible,
|
|
6517
|
+
/* startId */
|
|
6518
|
+
1
|
|
6519
|
+
);
|
|
6520
|
+
})();
|
|
6521
|
+
const initialNextId = 1 + restoredEntries.length;
|
|
5843
6522
|
const [state, dispatch] = useReducer(reducer, {
|
|
5844
|
-
entries:
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
6523
|
+
entries: [
|
|
6524
|
+
...banner ? [
|
|
6525
|
+
{
|
|
6526
|
+
id: 0,
|
|
6527
|
+
kind: "banner",
|
|
6528
|
+
version: appVersion ?? "dev",
|
|
6529
|
+
provider: provider ?? "agent",
|
|
6530
|
+
model,
|
|
6531
|
+
cwd: agent.ctx.cwd,
|
|
6532
|
+
family,
|
|
6533
|
+
keyTail
|
|
6534
|
+
}
|
|
6535
|
+
] : [],
|
|
6536
|
+
...restoredEntries
|
|
6537
|
+
],
|
|
5856
6538
|
buffer: "",
|
|
5857
6539
|
cursor: 0,
|
|
5858
6540
|
streamingText: "",
|
|
@@ -5864,7 +6546,7 @@ function App({
|
|
|
5864
6546
|
hint: "",
|
|
5865
6547
|
brain: { state: "idle" },
|
|
5866
6548
|
brainPrompt: null,
|
|
5867
|
-
nextId:
|
|
6549
|
+
nextId: initialNextId,
|
|
5868
6550
|
picker: { open: false, query: "", matches: [], selected: 0 },
|
|
5869
6551
|
slashPicker: { open: false, query: "", matches: [], selected: 0 },
|
|
5870
6552
|
runningTools: /* @__PURE__ */ new Map(),
|
|
@@ -5882,8 +6564,11 @@ function App({
|
|
|
5882
6564
|
searchQuery: ""
|
|
5883
6565
|
},
|
|
5884
6566
|
autonomyPicker: { open: false, options: [], selected: 0 },
|
|
5885
|
-
settingsPicker: { open: false, field: 0, mode: "off", delayMs: 0 },
|
|
6567
|
+
settingsPicker: { open: false, field: 0, mode: "off", delayMs: 0, titleAnimation: true, yolo: false, streamFleet: true, chime: false, confirmExit: true, nextPrediction: false, featureMcp: true, featurePlugins: true, featureMemory: true, featureSkills: true, featureModelsRegistry: true, contextAutoCompact: true, contextStrategy: "hybrid", logLevel: "info", auditLevel: "standard", indexOnStart: true, maxIterations: 500 },
|
|
5886
6568
|
confirmQueue: [],
|
|
6569
|
+
enhance: null,
|
|
6570
|
+
enhanceEnabled,
|
|
6571
|
+
enhanceBusy: false,
|
|
5887
6572
|
contextChipVersion: 0,
|
|
5888
6573
|
fleet: {},
|
|
5889
6574
|
leader: {
|
|
@@ -5902,6 +6587,8 @@ function App({
|
|
|
5902
6587
|
monitorOpen: false,
|
|
5903
6588
|
agentsMonitorOpen: false,
|
|
5904
6589
|
helpOpen: false,
|
|
6590
|
+
todosMonitorOpen: false,
|
|
6591
|
+
queuePanelOpen: false,
|
|
5905
6592
|
collabSession: null,
|
|
5906
6593
|
checkpoints: [],
|
|
5907
6594
|
rewindOverlay: null,
|
|
@@ -5926,10 +6613,14 @@ function App({
|
|
|
5926
6613
|
const inputGateRef = useRef(false);
|
|
5927
6614
|
const lastEnterAtRef = useRef(0);
|
|
5928
6615
|
const tokenPreviewsRef = useRef(/* @__PURE__ */ new Map());
|
|
5929
|
-
const projectName =
|
|
6616
|
+
const projectName = React6.useMemo(() => {
|
|
5930
6617
|
const base = path2.basename(projectRoot);
|
|
5931
6618
|
return base && base !== path2.sep ? base : void 0;
|
|
5932
6619
|
}, [projectRoot]);
|
|
6620
|
+
const chimeRef = useRef(chime);
|
|
6621
|
+
chimeRef.current = chime;
|
|
6622
|
+
const confirmExitRef = useRef(confirmExit);
|
|
6623
|
+
confirmExitRef.current = confirmExit;
|
|
5933
6624
|
const streamingTextRef = useRef("");
|
|
5934
6625
|
const pendingDeltaRef = useRef("");
|
|
5935
6626
|
const flushTimerRef = useRef(null);
|
|
@@ -5938,7 +6629,7 @@ function App({
|
|
|
5938
6629
|
const draftRef = useRef({ buffer: state.buffer, cursor: state.cursor });
|
|
5939
6630
|
draftRef.current = { buffer: state.buffer, cursor: state.cursor };
|
|
5940
6631
|
const bottomRef = useRef(null);
|
|
5941
|
-
|
|
6632
|
+
React6.useLayoutEffect(() => {
|
|
5942
6633
|
if (!managedLive) return;
|
|
5943
6634
|
const node = bottomRef.current;
|
|
5944
6635
|
if (!node) return;
|
|
@@ -5951,7 +6642,7 @@ function App({
|
|
|
5951
6642
|
}
|
|
5952
6643
|
}, [managedLive, termRows]);
|
|
5953
6644
|
const handleKeyRef = useRef(null);
|
|
5954
|
-
const handleRewindTo =
|
|
6645
|
+
const handleRewindTo = React6.useCallback(
|
|
5955
6646
|
async (checkpointIndex) => {
|
|
5956
6647
|
const sessionId = agent.ctx.session.id;
|
|
5957
6648
|
if (!sessionId) return;
|
|
@@ -5970,13 +6661,13 @@ function App({
|
|
|
5970
6661
|
dispatch({ type: "clearInput" });
|
|
5971
6662
|
};
|
|
5972
6663
|
const startedAtRef = useRef(Date.now());
|
|
5973
|
-
const [nowTick, setNowTick] =
|
|
6664
|
+
const [nowTick, setNowTick] = React6.useState(Date.now());
|
|
5974
6665
|
useEffect(() => {
|
|
5975
6666
|
const t = setInterval(() => setNowTick(Date.now()), 1e3);
|
|
5976
6667
|
return () => clearInterval(t);
|
|
5977
6668
|
}, []);
|
|
5978
6669
|
const elapsedMs = nowTick - startedAtRef.current;
|
|
5979
|
-
const [gitInfo, setGitInfo] =
|
|
6670
|
+
const [gitInfo, setGitInfo] = React6.useState(null);
|
|
5980
6671
|
useEffect(() => {
|
|
5981
6672
|
let cancelled = false;
|
|
5982
6673
|
const refresh = () => {
|
|
@@ -6031,7 +6722,10 @@ function App({
|
|
|
6031
6722
|
toolCalls: state.leader.toolCalls,
|
|
6032
6723
|
recentTools: state.leader.recentTools,
|
|
6033
6724
|
recentMessages: [],
|
|
6034
|
-
cost
|
|
6725
|
+
// Leader (main session) cost — the same number the statusline shows.
|
|
6726
|
+
// Kept distinct from fleet (subagent) cost so the monitor can show a
|
|
6727
|
+
// trustworthy grand total = leader + fleet.
|
|
6728
|
+
cost: tokenCounter?.estimateCost().total ?? 0,
|
|
6035
6729
|
startedAt: state.leader.startedAt,
|
|
6036
6730
|
lastEventAt: state.leader.lastEventAt,
|
|
6037
6731
|
currentTool: state.leader.currentTool,
|
|
@@ -6040,7 +6734,7 @@ function App({
|
|
|
6040
6734
|
ctxMaxTokens: state.leader.ctxMaxTokens ?? effectiveMaxContext
|
|
6041
6735
|
};
|
|
6042
6736
|
return { leader: leaderEntry, ...state.fleet };
|
|
6043
|
-
}, [state.fleet, state.leader, state.status, provider, model, effectiveMaxContext]);
|
|
6737
|
+
}, [state.fleet, state.leader, state.status, provider, model, effectiveMaxContext, tokenCounter]);
|
|
6044
6738
|
const STREAM_COLORS2 = ["cyan", "magenta", "yellow", "green", "blue"];
|
|
6045
6739
|
const labelsRef = useRef(/* @__PURE__ */ new Map());
|
|
6046
6740
|
const labelFor2 = (id, name) => {
|
|
@@ -6091,19 +6785,23 @@ function App({
|
|
|
6091
6785
|
}, [agent.ctx.meta]);
|
|
6092
6786
|
const prevAnyOverlayOpen = useRef(false);
|
|
6093
6787
|
const prevEntriesCount = useRef(0);
|
|
6788
|
+
const prevToolStreamLen = useRef(0);
|
|
6094
6789
|
const eraseLiveRegion = useCallback(() => {
|
|
6095
6790
|
try {
|
|
6096
6791
|
writeOut("\x1B[J");
|
|
6097
6792
|
} catch {
|
|
6098
6793
|
}
|
|
6099
6794
|
}, []);
|
|
6100
|
-
|
|
6101
|
-
const anyOpenNow = state.picker.open || state.slashPicker.open || state.modelPicker.open || state.autonomyPicker.open || state.settingsPicker.open || state.confirmQueue.length > 0;
|
|
6795
|
+
React6.useLayoutEffect(() => {
|
|
6796
|
+
const anyOpenNow = state.picker.open || state.slashPicker.open || state.modelPicker.open || state.autonomyPicker.open || state.settingsPicker.open || state.enhanceBusy || state.enhance != null || state.confirmQueue.length > 0;
|
|
6102
6797
|
const overlayClosed = prevAnyOverlayOpen.current && !anyOpenNow;
|
|
6103
6798
|
const newEntryCommitted = state.entries.length > prevEntriesCount.current;
|
|
6799
|
+
const curToolStreamLen = state.toolStream?.text.length ?? 0;
|
|
6800
|
+
const toolStreamGrew = curToolStreamLen > 0 && curToolStreamLen > prevToolStreamLen.current;
|
|
6104
6801
|
prevAnyOverlayOpen.current = anyOpenNow;
|
|
6105
6802
|
prevEntriesCount.current = state.entries.length;
|
|
6106
|
-
|
|
6803
|
+
prevToolStreamLen.current = curToolStreamLen;
|
|
6804
|
+
if (overlayClosed || newEntryCommitted || toolStreamGrew) {
|
|
6107
6805
|
eraseLiveRegion();
|
|
6108
6806
|
}
|
|
6109
6807
|
}, [
|
|
@@ -6112,8 +6810,11 @@ function App({
|
|
|
6112
6810
|
state.modelPicker.open,
|
|
6113
6811
|
state.autonomyPicker.open,
|
|
6114
6812
|
state.settingsPicker.open,
|
|
6813
|
+
state.enhanceBusy,
|
|
6814
|
+
state.enhance,
|
|
6115
6815
|
state.confirmQueue.length,
|
|
6116
6816
|
state.entries.length,
|
|
6817
|
+
state.toolStream?.text,
|
|
6117
6818
|
eraseLiveRegion
|
|
6118
6819
|
]);
|
|
6119
6820
|
useEffect(() => {
|
|
@@ -6123,6 +6824,9 @@ function App({
|
|
|
6123
6824
|
process.stdout.off("resize", handleResize);
|
|
6124
6825
|
};
|
|
6125
6826
|
}, [eraseLiveRegion]);
|
|
6827
|
+
React6.useLayoutEffect(() => {
|
|
6828
|
+
if (state.enhanceBusy || state.enhance != null) eraseLiveRegion();
|
|
6829
|
+
}, [nowTick, state.enhanceBusy, state.enhance, eraseLiveRegion]);
|
|
6126
6830
|
useEffect(() => {
|
|
6127
6831
|
const detected = detectAtToken(state.buffer, state.cursor);
|
|
6128
6832
|
if (!detected) {
|
|
@@ -6439,15 +7143,36 @@ function App({
|
|
|
6439
7143
|
slashRegistry.unregister("agents");
|
|
6440
7144
|
};
|
|
6441
7145
|
}, [slashRegistry]);
|
|
6442
|
-
const openModelPicker =
|
|
7146
|
+
const openModelPicker = React6.useCallback(async () => {
|
|
6443
7147
|
if (!getPickableProviders) return;
|
|
6444
7148
|
const providers = await getPickableProviders();
|
|
6445
7149
|
dispatch({ type: "modelPickerOpen", providers });
|
|
6446
7150
|
}, [getPickableProviders]);
|
|
6447
|
-
const openSettings =
|
|
7151
|
+
const openSettings = React6.useCallback(() => {
|
|
6448
7152
|
if (!getSettings) return;
|
|
6449
7153
|
const s2 = getSettings();
|
|
6450
|
-
dispatch({
|
|
7154
|
+
dispatch({
|
|
7155
|
+
type: "settingsOpen",
|
|
7156
|
+
mode: s2.mode,
|
|
7157
|
+
delayMs: s2.delayMs,
|
|
7158
|
+
titleAnimation: s2.titleAnimation ?? true,
|
|
7159
|
+
yolo: s2.yolo ?? false,
|
|
7160
|
+
streamFleet: s2.streamFleet ?? true,
|
|
7161
|
+
chime: s2.chime ?? false,
|
|
7162
|
+
confirmExit: s2.confirmExit ?? true,
|
|
7163
|
+
nextPrediction: s2.nextPrediction ?? false,
|
|
7164
|
+
featureMcp: s2.featureMcp ?? true,
|
|
7165
|
+
featurePlugins: s2.featurePlugins ?? true,
|
|
7166
|
+
featureMemory: s2.featureMemory ?? true,
|
|
7167
|
+
featureSkills: s2.featureSkills ?? true,
|
|
7168
|
+
featureModelsRegistry: s2.featureModelsRegistry ?? true,
|
|
7169
|
+
contextAutoCompact: s2.contextAutoCompact ?? true,
|
|
7170
|
+
contextStrategy: s2.contextStrategy ?? "hybrid",
|
|
7171
|
+
logLevel: s2.logLevel ?? "info",
|
|
7172
|
+
auditLevel: s2.auditLevel ?? "standard",
|
|
7173
|
+
indexOnStart: s2.indexOnStart ?? true,
|
|
7174
|
+
maxIterations: s2.maxIterations ?? 500
|
|
7175
|
+
});
|
|
6451
7176
|
}, [getSettings]);
|
|
6452
7177
|
useEffect(() => {
|
|
6453
7178
|
if (!getPickableProviders || !switchProviderAndModel) return;
|
|
@@ -6460,7 +7185,7 @@ function App({
|
|
|
6460
7185
|
return { message: void 0 };
|
|
6461
7186
|
}
|
|
6462
7187
|
};
|
|
6463
|
-
slashRegistry.register(cmd);
|
|
7188
|
+
slashRegistry.register(cmd, "tui", { official: true });
|
|
6464
7189
|
return () => {
|
|
6465
7190
|
slashRegistry.unregister("model");
|
|
6466
7191
|
};
|
|
@@ -6470,13 +7195,13 @@ function App({
|
|
|
6470
7195
|
const cmd = {
|
|
6471
7196
|
name: "settings",
|
|
6472
7197
|
aliases: ["config", "prefs"],
|
|
6473
|
-
description: "
|
|
7198
|
+
description: "Open the interactive settings editor (19 config fields across 8 sections).",
|
|
6474
7199
|
async run() {
|
|
6475
7200
|
openSettings();
|
|
6476
7201
|
return { message: void 0 };
|
|
6477
7202
|
}
|
|
6478
7203
|
};
|
|
6479
|
-
slashRegistry.register(cmd);
|
|
7204
|
+
slashRegistry.register(cmd, "tui", { official: true });
|
|
6480
7205
|
return () => {
|
|
6481
7206
|
slashRegistry.unregister("settings");
|
|
6482
7207
|
};
|
|
@@ -6492,7 +7217,7 @@ function App({
|
|
|
6492
7217
|
return { message: void 0 };
|
|
6493
7218
|
}
|
|
6494
7219
|
};
|
|
6495
|
-
slashRegistry.register(cmd);
|
|
7220
|
+
slashRegistry.register(cmd, "tui", { official: true });
|
|
6496
7221
|
return () => {
|
|
6497
7222
|
slashRegistry.unregister("autonomy");
|
|
6498
7223
|
};
|
|
@@ -6533,23 +7258,25 @@ function App({
|
|
|
6533
7258
|
});
|
|
6534
7259
|
});
|
|
6535
7260
|
const offTool = events.on("tool.executed", (e) => {
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
7261
|
+
if (e.name !== "delegate") {
|
|
7262
|
+
dispatch({
|
|
7263
|
+
type: "addEntry",
|
|
7264
|
+
entry: {
|
|
7265
|
+
kind: "tool",
|
|
7266
|
+
name: e.name,
|
|
7267
|
+
durationMs: e.durationMs,
|
|
7268
|
+
ok: e.ok,
|
|
7269
|
+
input: e.input,
|
|
7270
|
+
output: e.output,
|
|
7271
|
+
// Real model-visible sizes — forwarded so the size chip beside
|
|
7272
|
+
// the tool header can show what the model paid for instead of
|
|
7273
|
+
// the misleading preview-byte count we used to surface.
|
|
7274
|
+
outputBytes: e.outputBytes,
|
|
7275
|
+
outputTokens: e.outputTokens,
|
|
7276
|
+
outputLines: e.outputLines
|
|
7277
|
+
}
|
|
7278
|
+
});
|
|
7279
|
+
}
|
|
6553
7280
|
dispatch({ type: "toolEnded", name: e.name });
|
|
6554
7281
|
dispatch({ type: "toolStreamClear", name: e.name });
|
|
6555
7282
|
dispatch({ type: "leaderToolEnd", name: e.name, ok: e.ok, durationMs: e.durationMs });
|
|
@@ -6609,6 +7336,34 @@ function App({
|
|
|
6609
7336
|
}
|
|
6610
7337
|
});
|
|
6611
7338
|
});
|
|
7339
|
+
const offDelegateStart = events.on("delegate.started", (e) => {
|
|
7340
|
+
const task = e.task.length > 100 ? `${e.task.slice(0, 99)}\u2026` : e.task;
|
|
7341
|
+
dispatch({
|
|
7342
|
+
type: "addEntry",
|
|
7343
|
+
entry: {
|
|
7344
|
+
kind: "subagent",
|
|
7345
|
+
agentLabel: e.target,
|
|
7346
|
+
agentColor: "magenta",
|
|
7347
|
+
icon: "\u{1F91D}",
|
|
7348
|
+
text: "delegating",
|
|
7349
|
+
detail: task
|
|
7350
|
+
}
|
|
7351
|
+
});
|
|
7352
|
+
});
|
|
7353
|
+
const offDelegateDone = events.on("delegate.completed", (e) => {
|
|
7354
|
+
const cost = e.costUsd && e.costUsd > 0 ? `$${e.costUsd.toFixed(3)}` : void 0;
|
|
7355
|
+
dispatch({
|
|
7356
|
+
type: "addEntry",
|
|
7357
|
+
entry: {
|
|
7358
|
+
kind: "subagent",
|
|
7359
|
+
agentLabel: e.target,
|
|
7360
|
+
agentColor: e.ok ? "green" : "red",
|
|
7361
|
+
icon: e.ok ? "\u2713" : "\u2717",
|
|
7362
|
+
text: e.summary,
|
|
7363
|
+
detail: cost
|
|
7364
|
+
}
|
|
7365
|
+
});
|
|
7366
|
+
});
|
|
6612
7367
|
return () => {
|
|
6613
7368
|
offDelta();
|
|
6614
7369
|
offToolStart();
|
|
@@ -6621,6 +7376,8 @@ function App({
|
|
|
6621
7376
|
offProvResp();
|
|
6622
7377
|
offConfirmNeeded();
|
|
6623
7378
|
offTrustPersisted();
|
|
7379
|
+
offDelegateStart();
|
|
7380
|
+
offDelegateDone();
|
|
6624
7381
|
if (flushTimerRef.current) clearTimeout(flushTimerRef.current);
|
|
6625
7382
|
};
|
|
6626
7383
|
}, [events, agent.ctx.todos]);
|
|
@@ -6628,6 +7385,11 @@ function App({
|
|
|
6628
7385
|
useEffect(() => {
|
|
6629
7386
|
streamFleetRef.current = state.streamFleet;
|
|
6630
7387
|
}, [state.streamFleet]);
|
|
7388
|
+
const enhanceEnabledRef = useRef(state.enhanceEnabled);
|
|
7389
|
+
useEffect(() => {
|
|
7390
|
+
enhanceEnabledRef.current = state.enhanceEnabled;
|
|
7391
|
+
}, [state.enhanceEnabled]);
|
|
7392
|
+
const enhanceAbortRef = useRef(null);
|
|
6631
7393
|
useSubagentEvents(events, dispatch, setActiveMaxContext);
|
|
6632
7394
|
useEffect(() => {
|
|
6633
7395
|
const offCheckpoint = events.on("checkpoint.written", (e) => {
|
|
@@ -6853,6 +7615,18 @@ function App({
|
|
|
6853
7615
|
useEffect(() => {
|
|
6854
7616
|
if (fleetStreamController) fleetStreamController.enabled = state.streamFleet;
|
|
6855
7617
|
}, [state.streamFleet, fleetStreamController]);
|
|
7618
|
+
useEffect(() => {
|
|
7619
|
+
if (!enhanceController) return;
|
|
7620
|
+
enhanceController.enabled = state.enhanceEnabled;
|
|
7621
|
+
enhanceController.setEnabled = (enabled) => {
|
|
7622
|
+
dispatch({ type: "enhanceSet", enabled });
|
|
7623
|
+
};
|
|
7624
|
+
return () => {
|
|
7625
|
+
enhanceController.setEnabled = (enabled) => {
|
|
7626
|
+
enhanceController.enabled = enabled;
|
|
7627
|
+
};
|
|
7628
|
+
};
|
|
7629
|
+
}, [enhanceController, state.enhanceEnabled]);
|
|
6856
7630
|
useEffect(() => {
|
|
6857
7631
|
if (!agentsMonitorController) return;
|
|
6858
7632
|
agentsMonitorController.visible = state.agentsMonitorOpen;
|
|
@@ -6932,7 +7706,8 @@ function App({
|
|
|
6932
7706
|
type: "fleetCost",
|
|
6933
7707
|
cost: d.snapshot().total.cost,
|
|
6934
7708
|
input: d.snapshot().total.input,
|
|
6935
|
-
output: d.snapshot().total.output
|
|
7709
|
+
output: d.snapshot().total.output,
|
|
7710
|
+
perAgent: d.snapshot().perSubagent
|
|
6936
7711
|
});
|
|
6937
7712
|
const seen = new Set(Object.keys(status.subagents));
|
|
6938
7713
|
const pending = /* @__PURE__ */ new Map();
|
|
@@ -7061,7 +7836,8 @@ function App({
|
|
|
7061
7836
|
type: "fleetCost",
|
|
7062
7837
|
cost: d.snapshot().total.cost,
|
|
7063
7838
|
input: d.snapshot().total.input,
|
|
7064
|
-
output: d.snapshot().total.output
|
|
7839
|
+
output: d.snapshot().total.output,
|
|
7840
|
+
perAgent: d.snapshot().perSubagent
|
|
7065
7841
|
});
|
|
7066
7842
|
break;
|
|
7067
7843
|
}
|
|
@@ -7189,7 +7965,8 @@ function App({
|
|
|
7189
7965
|
type: "fleetCost",
|
|
7190
7966
|
cost: d.snapshot().total.cost,
|
|
7191
7967
|
input: d.snapshot().total.input,
|
|
7192
|
-
output: d.snapshot().total.output
|
|
7968
|
+
output: d.snapshot().total.output,
|
|
7969
|
+
perAgent: d.snapshot().perSubagent
|
|
7193
7970
|
});
|
|
7194
7971
|
if (streamFlushTimer) {
|
|
7195
7972
|
clearTimeout(streamFlushTimer);
|
|
@@ -7270,7 +8047,7 @@ function App({
|
|
|
7270
8047
|
type: "addEntry",
|
|
7271
8048
|
entry: {
|
|
7272
8049
|
kind: "warn",
|
|
7273
|
-
text: `Iteration cancelled${director ? " + fleet terminated" : ""}${procTag}. Dropped ${droppedCount} queued message${droppedCount === 1 ? "" : "s"}. Press Ctrl+C again to exit
|
|
8050
|
+
text: `Iteration cancelled${director ? " + fleet terminated" : ""}${procTag}. Dropped ${droppedCount} queued message${droppedCount === 1 ? "" : "s"}. ${confirmExitRef.current ? "Press Ctrl+C again to confirm exit." : "Press Ctrl+C again to exit."}`
|
|
7274
8051
|
}
|
|
7275
8052
|
});
|
|
7276
8053
|
} else {
|
|
@@ -7278,7 +8055,7 @@ function App({
|
|
|
7278
8055
|
type: "addEntry",
|
|
7279
8056
|
entry: {
|
|
7280
8057
|
kind: "warn",
|
|
7281
|
-
text: `Iteration cancelled${director ? " + fleet terminated" : ""}${procTag}. Press Ctrl+C again to exit
|
|
8058
|
+
text: `Iteration cancelled${director ? " + fleet terminated" : ""}${procTag}. ${confirmExitRef.current ? "Press Ctrl+C again to confirm exit." : "Press Ctrl+C again to exit."}`
|
|
7282
8059
|
}
|
|
7283
8060
|
});
|
|
7284
8061
|
}
|
|
@@ -7309,7 +8086,7 @@ function App({
|
|
|
7309
8086
|
type: "addEntry",
|
|
7310
8087
|
entry: {
|
|
7311
8088
|
kind: "warn",
|
|
7312
|
-
text: `${bits.join(" + ") || "Background work stopped"}. Press Ctrl+C again to exit
|
|
8089
|
+
text: `${bits.join(" + ") || "Background work stopped"}. ${confirmExitRef.current ? "Press Ctrl+C again to confirm exit." : "Press Ctrl+C again to exit."}`
|
|
7313
8090
|
}
|
|
7314
8091
|
});
|
|
7315
8092
|
return;
|
|
@@ -7352,10 +8129,16 @@ function App({
|
|
|
7352
8129
|
const handleKey = async (input, key) => {
|
|
7353
8130
|
if (state.status === "aborting" && !state.steeringPending && state.interrupts === 0) return;
|
|
7354
8131
|
if (state.confirmQueue.length > 0) return;
|
|
8132
|
+
if (state.enhanceBusy) {
|
|
8133
|
+
if (key.escape) enhanceAbortRef.current?.abort();
|
|
8134
|
+
return;
|
|
8135
|
+
}
|
|
8136
|
+
if (state.enhance) return;
|
|
7355
8137
|
if (state.helpOpen) {
|
|
7356
8138
|
if (key.escape || input === "?" || input === "q") dispatch({ type: "toggleHelp" });
|
|
7357
8139
|
return;
|
|
7358
8140
|
}
|
|
8141
|
+
state.todosMonitorOpen || state.monitorOpen || state.agentsMonitorOpen || state.worktreeMonitorOpen || !!state.autoPhase?.monitorOpen;
|
|
7359
8142
|
if (inputGateRef.current) return;
|
|
7360
8143
|
if (managedLive) {
|
|
7361
8144
|
if (key.pageUp) {
|
|
@@ -7527,8 +8310,8 @@ function App({
|
|
|
7527
8310
|
const now = Date.now();
|
|
7528
8311
|
if (now - lastEnterAtRef.current < 50) return;
|
|
7529
8312
|
lastEnterAtRef.current = now;
|
|
7530
|
-
const { mode, delayMs } = state.settingsPicker;
|
|
7531
|
-
const err = await saveSettings?.({ mode, delayMs });
|
|
8313
|
+
const { mode, delayMs, titleAnimation, yolo: yolo2, streamFleet, chime: chime2, confirmExit: confirmExit2, nextPrediction, featureMcp, featurePlugins, featureMemory, featureSkills, featureModelsRegistry, contextAutoCompact, contextStrategy, logLevel, auditLevel, indexOnStart, maxIterations } = state.settingsPicker;
|
|
8314
|
+
const err = await saveSettings?.({ mode, delayMs, titleAnimation, yolo: yolo2, streamFleet, chime: chime2, confirmExit: confirmExit2, nextPrediction, featureMcp, featurePlugins, featureMemory, featureSkills, featureModelsRegistry, contextAutoCompact, contextStrategy, logLevel, auditLevel, indexOnStart, maxIterations });
|
|
7532
8315
|
if (err) {
|
|
7533
8316
|
dispatch({ type: "settingsHint", text: err });
|
|
7534
8317
|
return;
|
|
@@ -7641,20 +8424,32 @@ function App({
|
|
|
7641
8424
|
return;
|
|
7642
8425
|
}
|
|
7643
8426
|
const toggleFleetOverlay = () => {
|
|
7644
|
-
if (state.
|
|
7645
|
-
dispatch({ type: "toggleAgentsMonitor" });
|
|
7646
|
-
dispatch({ type: "toggleMonitor" });
|
|
7647
|
-
} else {
|
|
8427
|
+
if (state.monitorOpen) {
|
|
7648
8428
|
dispatch({ type: "toggleMonitor" });
|
|
8429
|
+
return;
|
|
7649
8430
|
}
|
|
8431
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
8432
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
8433
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
8434
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8435
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
8436
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
8437
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
8438
|
+
dispatch({ type: "toggleMonitor" });
|
|
7650
8439
|
};
|
|
7651
8440
|
const toggleAgentsOverlay = () => {
|
|
7652
|
-
if (state.
|
|
7653
|
-
dispatch({ type: "toggleMonitor" });
|
|
7654
|
-
dispatch({ type: "toggleAgentsMonitor" });
|
|
7655
|
-
} else {
|
|
8441
|
+
if (state.agentsMonitorOpen) {
|
|
7656
8442
|
dispatch({ type: "toggleAgentsMonitor" });
|
|
8443
|
+
return;
|
|
7657
8444
|
}
|
|
8445
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
8446
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
8447
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
8448
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8449
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
8450
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
8451
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
8452
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
7658
8453
|
};
|
|
7659
8454
|
const toggleWorktreeOverlay = () => {
|
|
7660
8455
|
if (state.worktreeMonitorOpen) {
|
|
@@ -7664,8 +8459,26 @@ function App({
|
|
|
7664
8459
|
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
7665
8460
|
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
7666
8461
|
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8462
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
8463
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
8464
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
8465
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
7667
8466
|
dispatch({ type: "worktreeMonitorToggle" });
|
|
7668
8467
|
};
|
|
8468
|
+
const toggleTodosOverlay = () => {
|
|
8469
|
+
if (state.todosMonitorOpen) {
|
|
8470
|
+
dispatch({ type: "toggleTodosMonitor" });
|
|
8471
|
+
return;
|
|
8472
|
+
}
|
|
8473
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
8474
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
8475
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
8476
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8477
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
8478
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
8479
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
8480
|
+
dispatch({ type: "toggleTodosMonitor" });
|
|
8481
|
+
};
|
|
7669
8482
|
if (key.ctrl && input === "f" || key.fn === 2) {
|
|
7670
8483
|
toggleFleetOverlay();
|
|
7671
8484
|
return;
|
|
@@ -7678,12 +8491,96 @@ function App({
|
|
|
7678
8491
|
toggleWorktreeOverlay();
|
|
7679
8492
|
return;
|
|
7680
8493
|
}
|
|
8494
|
+
if (key.fn === 5) {
|
|
8495
|
+
if (state.settingsPicker.open) {
|
|
8496
|
+
dispatch({ type: "settingsClose" });
|
|
8497
|
+
} else if (getSettings && saveSettings) {
|
|
8498
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
8499
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
8500
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
8501
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
8502
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8503
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
8504
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
8505
|
+
const cfg = getSettings();
|
|
8506
|
+
dispatch({
|
|
8507
|
+
type: "settingsOpen",
|
|
8508
|
+
mode: cfg.mode,
|
|
8509
|
+
delayMs: cfg.delayMs,
|
|
8510
|
+
titleAnimation: cfg.titleAnimation ?? true,
|
|
8511
|
+
yolo: cfg.yolo ?? false,
|
|
8512
|
+
streamFleet: cfg.streamFleet ?? true,
|
|
8513
|
+
chime: cfg.chime ?? false,
|
|
8514
|
+
confirmExit: cfg.confirmExit ?? true,
|
|
8515
|
+
nextPrediction: cfg.nextPrediction ?? false,
|
|
8516
|
+
featureMcp: cfg.featureMcp ?? true,
|
|
8517
|
+
featurePlugins: cfg.featurePlugins ?? true,
|
|
8518
|
+
featureMemory: cfg.featureMemory ?? true,
|
|
8519
|
+
featureSkills: cfg.featureSkills ?? true,
|
|
8520
|
+
featureModelsRegistry: cfg.featureModelsRegistry ?? true,
|
|
8521
|
+
contextAutoCompact: cfg.contextAutoCompact ?? true,
|
|
8522
|
+
contextStrategy: cfg.contextStrategy ?? "hybrid",
|
|
8523
|
+
logLevel: cfg.logLevel ?? "info",
|
|
8524
|
+
auditLevel: cfg.auditLevel ?? "standard",
|
|
8525
|
+
indexOnStart: cfg.indexOnStart ?? true,
|
|
8526
|
+
maxIterations: cfg.maxIterations ?? 500
|
|
8527
|
+
});
|
|
8528
|
+
}
|
|
8529
|
+
return;
|
|
8530
|
+
}
|
|
8531
|
+
if (key.fn === 6) {
|
|
8532
|
+
toggleTodosOverlay();
|
|
8533
|
+
return;
|
|
8534
|
+
}
|
|
8535
|
+
if (key.fn === 7) {
|
|
8536
|
+
if (state.queuePanelOpen) {
|
|
8537
|
+
dispatch({ type: "toggleQueuePanel" });
|
|
8538
|
+
} else {
|
|
8539
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
8540
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
8541
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
8542
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
8543
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8544
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
8545
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
8546
|
+
dispatch({ type: "toggleQueuePanel" });
|
|
8547
|
+
}
|
|
8548
|
+
return;
|
|
8549
|
+
}
|
|
7681
8550
|
if (key.ctrl && input === "s") {
|
|
7682
8551
|
if (state.settingsPicker.open) {
|
|
7683
8552
|
dispatch({ type: "settingsClose" });
|
|
7684
8553
|
} else if (getSettings && saveSettings) {
|
|
8554
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
8555
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
8556
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
8557
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
8558
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8559
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
8560
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
7685
8561
|
const cfg = getSettings();
|
|
7686
|
-
dispatch({
|
|
8562
|
+
dispatch({
|
|
8563
|
+
type: "settingsOpen",
|
|
8564
|
+
mode: cfg.mode,
|
|
8565
|
+
delayMs: cfg.delayMs,
|
|
8566
|
+
titleAnimation: cfg.titleAnimation ?? true,
|
|
8567
|
+
yolo: cfg.yolo ?? false,
|
|
8568
|
+
streamFleet: cfg.streamFleet ?? true,
|
|
8569
|
+
chime: cfg.chime ?? false,
|
|
8570
|
+
confirmExit: cfg.confirmExit ?? true,
|
|
8571
|
+
nextPrediction: cfg.nextPrediction ?? false,
|
|
8572
|
+
featureMcp: cfg.featureMcp ?? true,
|
|
8573
|
+
featurePlugins: cfg.featurePlugins ?? true,
|
|
8574
|
+
featureMemory: cfg.featureMemory ?? true,
|
|
8575
|
+
featureSkills: cfg.featureSkills ?? true,
|
|
8576
|
+
featureModelsRegistry: cfg.featureModelsRegistry ?? true,
|
|
8577
|
+
contextAutoCompact: cfg.contextAutoCompact ?? true,
|
|
8578
|
+
contextStrategy: cfg.contextStrategy ?? "hybrid",
|
|
8579
|
+
logLevel: cfg.logLevel ?? "info",
|
|
8580
|
+
auditLevel: cfg.auditLevel ?? "standard",
|
|
8581
|
+
indexOnStart: cfg.indexOnStart ?? true,
|
|
8582
|
+
maxIterations: cfg.maxIterations ?? 500
|
|
8583
|
+
});
|
|
7687
8584
|
}
|
|
7688
8585
|
return;
|
|
7689
8586
|
}
|
|
@@ -7700,12 +8597,34 @@ function App({
|
|
|
7700
8597
|
dispatch({ type: "worktreeMonitorToggle" });
|
|
7701
8598
|
return;
|
|
7702
8599
|
}
|
|
8600
|
+
if (state.todosMonitorOpen) {
|
|
8601
|
+
dispatch({ type: "toggleTodosMonitor" });
|
|
8602
|
+
return;
|
|
8603
|
+
}
|
|
8604
|
+
if (state.autoPhase?.monitorOpen) {
|
|
8605
|
+
dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8606
|
+
return;
|
|
8607
|
+
}
|
|
8608
|
+
if (state.settingsPicker.open) {
|
|
8609
|
+
dispatch({ type: "settingsClose" });
|
|
8610
|
+
return;
|
|
8611
|
+
}
|
|
8612
|
+
if (state.queuePanelOpen) {
|
|
8613
|
+
dispatch({ type: "toggleQueuePanel" });
|
|
8614
|
+
return;
|
|
8615
|
+
}
|
|
7703
8616
|
}
|
|
7704
|
-
if (input === "?" && !key.ctrl && !key.meta && draftRef.current.buffer === "" && !state.slashPicker.open && !state.picker.open && !state.modelPicker.open && !state.autonomyPicker.open && !state.settingsPicker.open && !state.rewindOverlay && !state.monitorOpen && !state.agentsMonitorOpen && !state.worktreeMonitorOpen && !state.autoPhase?.monitorOpen) {
|
|
8617
|
+
if (input === "?" && !key.ctrl && !key.meta && draftRef.current.buffer === "" && !state.slashPicker.open && !state.picker.open && !state.modelPicker.open && !state.autonomyPicker.open && !state.settingsPicker.open && !state.rewindOverlay && !state.monitorOpen && !state.agentsMonitorOpen && !state.worktreeMonitorOpen && !state.todosMonitorOpen && !state.autoPhase?.monitorOpen) {
|
|
7705
8618
|
dispatch({ type: "toggleHelp" });
|
|
7706
8619
|
return;
|
|
7707
8620
|
}
|
|
7708
8621
|
if (isEnter) {
|
|
8622
|
+
if (key.shift) {
|
|
8623
|
+
const { buffer: buffer2, cursor: cursor2 } = draftRef.current;
|
|
8624
|
+
const next2 = buffer2.slice(0, cursor2) + "\n" + buffer2.slice(cursor2);
|
|
8625
|
+
setDraft(next2, cursor2 + 1);
|
|
8626
|
+
return;
|
|
8627
|
+
}
|
|
7709
8628
|
const now = Date.now();
|
|
7710
8629
|
if (now - lastEnterAtRef.current < 50) return;
|
|
7711
8630
|
lastEnterAtRef.current = now;
|
|
@@ -7713,36 +8632,41 @@ function App({
|
|
|
7713
8632
|
return;
|
|
7714
8633
|
}
|
|
7715
8634
|
const { buffer, cursor } = draftRef.current;
|
|
7716
|
-
if (key.backspace
|
|
8635
|
+
if (key.backspace) {
|
|
7717
8636
|
if (key.ctrl) {
|
|
7718
|
-
if (
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
setDraft(next3, lastWordStart);
|
|
7724
|
-
} else {
|
|
7725
|
-
if (cursor >= buffer.length) return;
|
|
7726
|
-
const afterCursor = buffer.slice(cursor);
|
|
7727
|
-
const nextWordStart = afterCursor.indexOf(" ");
|
|
7728
|
-
const end = nextWordStart === -1 ? buffer.length : cursor + nextWordStart + 1;
|
|
7729
|
-
const next3 = buffer.slice(0, cursor) + buffer.slice(end);
|
|
7730
|
-
setDraft(next3, cursor);
|
|
7731
|
-
}
|
|
8637
|
+
if (cursor === 0) return;
|
|
8638
|
+
const beforeCursor = buffer.slice(0, cursor);
|
|
8639
|
+
const lastWordStart = beforeCursor.lastIndexOf(" ") + 1;
|
|
8640
|
+
const next3 = beforeCursor.slice(0, lastWordStart) + buffer.slice(cursor);
|
|
8641
|
+
setDraft(next3, lastWordStart);
|
|
7732
8642
|
return;
|
|
7733
8643
|
}
|
|
7734
|
-
|
|
7735
|
-
|
|
7736
|
-
|
|
7737
|
-
|
|
7738
|
-
return;
|
|
7739
|
-
}
|
|
8644
|
+
const tokenDel = deleteTokenBackward(buffer, cursor);
|
|
8645
|
+
if (tokenDel) {
|
|
8646
|
+
setDraft(tokenDel.buffer, tokenDel.cursor);
|
|
8647
|
+
return;
|
|
7740
8648
|
}
|
|
7741
8649
|
if (cursor === 0) return;
|
|
7742
8650
|
const next2 = buffer.slice(0, cursor - 1) + buffer.slice(cursor);
|
|
7743
8651
|
setDraft(next2, cursor - 1);
|
|
7744
8652
|
return;
|
|
7745
8653
|
}
|
|
8654
|
+
if (key.delete) {
|
|
8655
|
+
if (key.ctrl) {
|
|
8656
|
+
if (cursor >= buffer.length) return;
|
|
8657
|
+
const afterCursor = buffer.slice(cursor);
|
|
8658
|
+
const nextWordStart = afterCursor.indexOf(" ");
|
|
8659
|
+
const end = nextWordStart === -1 ? buffer.length : cursor + nextWordStart + 1;
|
|
8660
|
+
const next3 = buffer.slice(0, cursor) + buffer.slice(end);
|
|
8661
|
+
setDraft(next3, cursor);
|
|
8662
|
+
return;
|
|
8663
|
+
}
|
|
8664
|
+
if (cursor >= buffer.length) return;
|
|
8665
|
+
const span = tokenLengthForward(buffer, cursor) || 1;
|
|
8666
|
+
const next2 = buffer.slice(0, cursor) + buffer.slice(cursor + span);
|
|
8667
|
+
setDraft(next2, cursor);
|
|
8668
|
+
return;
|
|
8669
|
+
}
|
|
7746
8670
|
if (key.leftArrow) {
|
|
7747
8671
|
if (key.ctrl) {
|
|
7748
8672
|
if (cursor === 0) return;
|
|
@@ -7813,7 +8737,7 @@ function App({
|
|
|
7813
8737
|
setDraft("", 0);
|
|
7814
8738
|
return;
|
|
7815
8739
|
}
|
|
7816
|
-
if (key.
|
|
8740
|
+
if (key.ctrl && input === "d") {
|
|
7817
8741
|
if (cursor >= buffer.length) return;
|
|
7818
8742
|
const span = tokenLengthForward(buffer, cursor) || 1;
|
|
7819
8743
|
const next2 = buffer.slice(0, cursor) + buffer.slice(cursor + span);
|
|
@@ -7940,10 +8864,20 @@ function App({
|
|
|
7940
8864
|
} finally {
|
|
7941
8865
|
activeCtrlRef.current = null;
|
|
7942
8866
|
dispatch({ type: "status", status: "idle" });
|
|
8867
|
+
if (chimeRef.current) {
|
|
8868
|
+
try {
|
|
8869
|
+
process.stdout.write("\x07");
|
|
8870
|
+
} catch {
|
|
8871
|
+
}
|
|
8872
|
+
}
|
|
7943
8873
|
}
|
|
7944
8874
|
const head = stateRef.current.queue[0];
|
|
7945
8875
|
if (head) {
|
|
7946
8876
|
dispatch({ type: "dequeueFirst" });
|
|
8877
|
+
dispatch({
|
|
8878
|
+
type: "addEntry",
|
|
8879
|
+
entry: { kind: "user", text: head.displayText }
|
|
8880
|
+
});
|
|
7947
8881
|
await runBlocks(head.blocks);
|
|
7948
8882
|
}
|
|
7949
8883
|
};
|
|
@@ -8088,6 +9022,10 @@ function App({
|
|
|
8088
9022
|
void runParallelLoopRef.current();
|
|
8089
9023
|
}
|
|
8090
9024
|
}
|
|
9025
|
+
if (getModeLabel) {
|
|
9026
|
+
const currentMode = getModeLabel();
|
|
9027
|
+
if (currentMode !== liveModeLabel) setLiveModeLabel(currentMode);
|
|
9028
|
+
}
|
|
8091
9029
|
if (res?.exit) {
|
|
8092
9030
|
exit();
|
|
8093
9031
|
onExit(0);
|
|
@@ -8107,6 +9045,7 @@ function App({
|
|
|
8107
9045
|
const cmd = trimmed.slice(1).split(/\s+/, 1)[0];
|
|
8108
9046
|
if (cmd === "clear") {
|
|
8109
9047
|
onClearHistory?.(dispatch);
|
|
9048
|
+
tokenCounter?.reset();
|
|
8110
9049
|
}
|
|
8111
9050
|
} catch (err) {
|
|
8112
9051
|
dispatch({
|
|
@@ -8119,6 +9058,52 @@ function App({
|
|
|
8119
9058
|
const builder = builderRef.current;
|
|
8120
9059
|
if (!builder) return;
|
|
8121
9060
|
const steering = state.steeringPending;
|
|
9061
|
+
let effectiveText = trimmed;
|
|
9062
|
+
const hasChips = trimmed ? new RegExp(INLINE_TOKEN_SRC, "g").test(trimmed) : false;
|
|
9063
|
+
if (enhanceEnabledRef.current && state.status === "idle" && !steering && !hasChips && shouldEnhance(trimmed)) {
|
|
9064
|
+
dispatch({ type: "enhanceBusy", on: true });
|
|
9065
|
+
const ac = new AbortController();
|
|
9066
|
+
enhanceAbortRef.current = ac;
|
|
9067
|
+
let refined = null;
|
|
9068
|
+
let enhanceErr = null;
|
|
9069
|
+
try {
|
|
9070
|
+
refined = await enhanceUserPrompt({
|
|
9071
|
+
provider: agent.ctx.provider,
|
|
9072
|
+
model: agent.ctx.model,
|
|
9073
|
+
text: trimmed,
|
|
9074
|
+
signal: ac.signal,
|
|
9075
|
+
onError: (reason) => {
|
|
9076
|
+
enhanceErr = reason;
|
|
9077
|
+
},
|
|
9078
|
+
// Feed recent conversation so follow-ups ("do the same", "that file")
|
|
9079
|
+
// resolve against context instead of being refined blind.
|
|
9080
|
+
history: recentTextTurns(agent.ctx.messages)
|
|
9081
|
+
});
|
|
9082
|
+
} finally {
|
|
9083
|
+
enhanceAbortRef.current = null;
|
|
9084
|
+
dispatch({ type: "enhanceBusy", on: false });
|
|
9085
|
+
}
|
|
9086
|
+
if (refined === null && !ac.signal.aborted) {
|
|
9087
|
+
dispatch({
|
|
9088
|
+
type: "addEntry",
|
|
9089
|
+
entry: {
|
|
9090
|
+
kind: "info",
|
|
9091
|
+
text: enhanceErr ? `\u2728 refinement unavailable (${enhanceErr}) \u2014 sent your message as-is` : "\u2728 refinement unavailable \u2014 sent your message as-is"
|
|
9092
|
+
}
|
|
9093
|
+
});
|
|
9094
|
+
}
|
|
9095
|
+
if (refined && !normalizedEqual(refined, trimmed)) {
|
|
9096
|
+
const decision = await new Promise((resolve) => {
|
|
9097
|
+
dispatch({ type: "enhanceOpen", info: { original: trimmed, refined, resolve } });
|
|
9098
|
+
});
|
|
9099
|
+
dispatch({ type: "enhanceClose" });
|
|
9100
|
+
if (decision === "edit") {
|
|
9101
|
+
setDraft(refined, refined.length);
|
|
9102
|
+
return;
|
|
9103
|
+
}
|
|
9104
|
+
effectiveText = decision === "refined" ? refined : trimmed;
|
|
9105
|
+
}
|
|
9106
|
+
}
|
|
8122
9107
|
const sddContext = getSDDContext?.();
|
|
8123
9108
|
if (sddContext && trimmed) {
|
|
8124
9109
|
builder.appendText(`[SDD SESSION ACTIVE]
|
|
@@ -8129,11 +9114,11 @@ User message:
|
|
|
8129
9114
|
`);
|
|
8130
9115
|
}
|
|
8131
9116
|
if (trimmed) {
|
|
8132
|
-
const toAppend = steering ? buildSteeringPreamble(state.steerSnapshot,
|
|
9117
|
+
const toAppend = steering ? buildSteeringPreamble(state.steerSnapshot, effectiveText) : effectiveText;
|
|
8133
9118
|
builder.appendText(toAppend);
|
|
8134
9119
|
}
|
|
8135
9120
|
if (steering) dispatch({ type: "steerConsume" });
|
|
8136
|
-
const displayText = trimmed ? steering ? `\u21AF ${
|
|
9121
|
+
const displayText = trimmed ? steering ? `\u21AF ${effectiveText}` : effectiveText : "(attachments only)";
|
|
8137
9122
|
const pasteParts = [];
|
|
8138
9123
|
for (const m of trimmed.matchAll(new RegExp(INLINE_TOKEN_SRC, "g"))) {
|
|
8139
9124
|
const token = m[0];
|
|
@@ -8194,7 +9179,8 @@ User message:
|
|
|
8194
9179
|
return "";
|
|
8195
9180
|
}, [state.buffer, state.status, state.picker.open]);
|
|
8196
9181
|
const affordanceShown = managedLive && state.scrollOffset > 0 && state.pendingNewLines > 0;
|
|
8197
|
-
|
|
9182
|
+
const enhanceActive = state.enhanceBusy || state.enhance != null;
|
|
9183
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", height: managedLive ? termRows : void 0, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, flexShrink: 0, children: [
|
|
8198
9184
|
managedLive ? /* @__PURE__ */ jsx(
|
|
8199
9185
|
ScrollableHistory,
|
|
8200
9186
|
{
|
|
@@ -8221,10 +9207,10 @@ User message:
|
|
|
8221
9207
|
Input,
|
|
8222
9208
|
{
|
|
8223
9209
|
prompt: INPUT_PROMPT,
|
|
8224
|
-
value: state.buffer,
|
|
8225
|
-
cursor: state.cursor,
|
|
9210
|
+
value: enhanceActive ? "" : state.buffer,
|
|
9211
|
+
cursor: enhanceActive ? 0 : state.cursor,
|
|
8226
9212
|
disabled: state.status === "aborting" && !state.steeringPending || state.confirmQueue.length > 0,
|
|
8227
|
-
hint: inputHint,
|
|
9213
|
+
hint: enhanceActive ? "" : inputHint,
|
|
8228
9214
|
onKey: handleKey
|
|
8229
9215
|
}
|
|
8230
9216
|
),
|
|
@@ -8271,6 +9257,23 @@ User message:
|
|
|
8271
9257
|
field: state.settingsPicker.field,
|
|
8272
9258
|
mode: state.settingsPicker.mode,
|
|
8273
9259
|
delayMs: state.settingsPicker.delayMs,
|
|
9260
|
+
titleAnimation: state.settingsPicker.titleAnimation,
|
|
9261
|
+
yolo: state.settingsPicker.yolo,
|
|
9262
|
+
streamFleet: state.settingsPicker.streamFleet,
|
|
9263
|
+
chime: state.settingsPicker.chime,
|
|
9264
|
+
confirmExit: state.settingsPicker.confirmExit,
|
|
9265
|
+
nextPrediction: state.settingsPicker.nextPrediction,
|
|
9266
|
+
featureMcp: state.settingsPicker.featureMcp,
|
|
9267
|
+
featurePlugins: state.settingsPicker.featurePlugins,
|
|
9268
|
+
featureMemory: state.settingsPicker.featureMemory,
|
|
9269
|
+
featureSkills: state.settingsPicker.featureSkills,
|
|
9270
|
+
featureModelsRegistry: state.settingsPicker.featureModelsRegistry,
|
|
9271
|
+
contextAutoCompact: state.settingsPicker.contextAutoCompact,
|
|
9272
|
+
contextStrategy: state.settingsPicker.contextStrategy,
|
|
9273
|
+
logLevel: state.settingsPicker.logLevel,
|
|
9274
|
+
auditLevel: state.settingsPicker.auditLevel,
|
|
9275
|
+
indexOnStart: state.settingsPicker.indexOnStart,
|
|
9276
|
+
maxIterations: state.settingsPicker.maxIterations,
|
|
8274
9277
|
hint: state.settingsPicker.hint
|
|
8275
9278
|
}
|
|
8276
9279
|
) : null,
|
|
@@ -8313,6 +9316,25 @@ User message:
|
|
|
8313
9316
|
}
|
|
8314
9317
|
);
|
|
8315
9318
|
})(),
|
|
9319
|
+
state.enhanceBusy && !state.enhance ? /* @__PURE__ */ jsx(Box, { paddingX: 1, children: /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u2728 refining your request\u2026" }) }) : null,
|
|
9320
|
+
state.enhance ? (() => {
|
|
9321
|
+
const info = state.enhance;
|
|
9322
|
+
let resolved = false;
|
|
9323
|
+
const onDecision = (decision) => {
|
|
9324
|
+
if (resolved) return;
|
|
9325
|
+
resolved = true;
|
|
9326
|
+
info.resolve(decision);
|
|
9327
|
+
};
|
|
9328
|
+
return /* @__PURE__ */ jsx(
|
|
9329
|
+
EnhancePanel,
|
|
9330
|
+
{
|
|
9331
|
+
original: info.original,
|
|
9332
|
+
refined: info.refined,
|
|
9333
|
+
delayMs: enhanceDelayMs,
|
|
9334
|
+
onDecision
|
|
9335
|
+
}
|
|
9336
|
+
);
|
|
9337
|
+
})() : null,
|
|
8316
9338
|
/* @__PURE__ */ jsx(
|
|
8317
9339
|
StatusBar,
|
|
8318
9340
|
{
|
|
@@ -8336,7 +9358,9 @@ User message:
|
|
|
8336
9358
|
processCount: getProcessRegistry().activeCount,
|
|
8337
9359
|
hiddenItems,
|
|
8338
9360
|
eternalStage: state.eternalStage,
|
|
8339
|
-
goalSummary: state.goalSummary
|
|
9361
|
+
goalSummary: state.goalSummary,
|
|
9362
|
+
indexState,
|
|
9363
|
+
modeLabel: liveModeLabel || void 0
|
|
8340
9364
|
}
|
|
8341
9365
|
),
|
|
8342
9366
|
managedLive ? /* @__PURE__ */ jsx(
|
|
@@ -8345,7 +9369,7 @@ User message:
|
|
|
8345
9369
|
context: {
|
|
8346
9370
|
confirm: state.confirmQueue.length > 0,
|
|
8347
9371
|
picker: state.picker.open || state.slashPicker.open || state.modelPicker.open || state.autonomyPicker.open || state.settingsPicker.open || !!state.rewindOverlay,
|
|
8348
|
-
monitor: state.agentsMonitorOpen || state.monitorOpen || state.worktreeMonitorOpen || !!state.autoPhase?.monitorOpen,
|
|
9372
|
+
monitor: state.agentsMonitorOpen || state.monitorOpen || state.worktreeMonitorOpen || state.todosMonitorOpen || !!state.autoPhase?.monitorOpen,
|
|
8349
9373
|
managed: managedLive
|
|
8350
9374
|
}
|
|
8351
9375
|
}
|
|
@@ -8356,6 +9380,7 @@ User message:
|
|
|
8356
9380
|
{
|
|
8357
9381
|
entries: entriesWithLeader,
|
|
8358
9382
|
totalCost: state.fleetCost,
|
|
9383
|
+
leaderCost: tokenCounter?.estimateCost().total ?? 0,
|
|
8359
9384
|
totalTokens: state.fleetTokens,
|
|
8360
9385
|
nowTick
|
|
8361
9386
|
}
|
|
@@ -8376,7 +9401,7 @@ User message:
|
|
|
8376
9401
|
nowTick,
|
|
8377
9402
|
onClose: () => dispatch({ type: "worktreeMonitorToggle" })
|
|
8378
9403
|
}
|
|
8379
|
-
) : state.monitorOpen ? /* @__PURE__ */ jsx(
|
|
9404
|
+
) : state.todosMonitorOpen && !managedLive ? /* @__PURE__ */ jsx(TodosMonitor, { todos: agent.ctx.todos }) : state.monitorOpen ? /* @__PURE__ */ jsx(
|
|
8380
9405
|
FleetMonitor,
|
|
8381
9406
|
{
|
|
8382
9407
|
entries: state.fleet,
|
|
@@ -8403,9 +9428,10 @@ User message:
|
|
|
8403
9428
|
nowTick
|
|
8404
9429
|
}
|
|
8405
9430
|
) : null,
|
|
8406
|
-
Object.keys(state.worktrees).length > 0 && !state.worktreeMonitorOpen && !state.monitorOpen ? /* @__PURE__ */ jsx(WorktreePanel, { worktrees: state.worktrees, nowTick }) : null
|
|
9431
|
+
Object.keys(state.worktrees).length > 0 && !state.worktreeMonitorOpen && !state.monitorOpen ? /* @__PURE__ */ jsx(WorktreePanel, { worktrees: state.worktrees, nowTick }) : null,
|
|
9432
|
+
state.queuePanelOpen ? /* @__PURE__ */ jsx(QueuePanel, { items: state.queue }) : null
|
|
8407
9433
|
] })
|
|
8408
|
-
] });
|
|
9434
|
+
] }) });
|
|
8409
9435
|
}
|
|
8410
9436
|
function renderRunningTools(running) {
|
|
8411
9437
|
if (running.size === 0) return "";
|
|
@@ -8524,7 +9550,8 @@ async function runTui(opts) {
|
|
|
8524
9550
|
}
|
|
8525
9551
|
stdout.write(BRACKETED_PASTE_ON);
|
|
8526
9552
|
const inkStdin = stdin;
|
|
8527
|
-
const stopTitle = startTerminalTitle({ stdout, events: opts.events, model: opts.model })
|
|
9553
|
+
const stopTitle = opts.titleAnimation !== false ? startTerminalTitle({ stdout, events: opts.events, model: opts.model }) : (() => {
|
|
9554
|
+
});
|
|
8528
9555
|
const swallowSignals = ["SIGTSTP", "SIGQUIT", "SIGTTIN", "SIGTTOU"];
|
|
8529
9556
|
const swallow = () => {
|
|
8530
9557
|
};
|
|
@@ -8584,7 +9611,7 @@ async function runTui(opts) {
|
|
|
8584
9611
|
let instance;
|
|
8585
9612
|
try {
|
|
8586
9613
|
instance = render(
|
|
8587
|
-
|
|
9614
|
+
React6.createElement(App, {
|
|
8588
9615
|
agent: opts.agent,
|
|
8589
9616
|
slashRegistry: opts.slashRegistry,
|
|
8590
9617
|
attachments: opts.attachments,
|
|
@@ -8616,6 +9643,8 @@ async function runTui(opts) {
|
|
|
8616
9643
|
fleetRoster: opts.fleetRoster,
|
|
8617
9644
|
onClearHistory: opts.onClearHistory ? (dispatch) => opts.onClearHistory(dispatch) : void 0,
|
|
8618
9645
|
fleetStreamController: opts.fleetStreamController,
|
|
9646
|
+
enhanceController: opts.enhanceController,
|
|
9647
|
+
enhanceEnabled: opts.enhanceController?.enabled ?? true,
|
|
8619
9648
|
statuslineHiddenItems: opts.statuslineHiddenItems,
|
|
8620
9649
|
setStatuslineHiddenItems: opts.setStatuslineHiddenItems,
|
|
8621
9650
|
agentsMonitorController: opts.agentsMonitorController,
|
|
@@ -8630,7 +9659,11 @@ async function runTui(opts) {
|
|
|
8630
9659
|
predictNext: opts.predictNext,
|
|
8631
9660
|
// Managed viewport (in-app scroll + collapsibility) follows
|
|
8632
9661
|
// alt-screen: it owns the screen, so there's no native-scrollback leak.
|
|
8633
|
-
managed: useAltScreen
|
|
9662
|
+
managed: useAltScreen,
|
|
9663
|
+
chime: opts.chime,
|
|
9664
|
+
confirmExit: opts.confirmExit,
|
|
9665
|
+
modeLabel: opts.modeLabel,
|
|
9666
|
+
getModeLabel: opts.getModeLabel
|
|
8634
9667
|
}),
|
|
8635
9668
|
{ exitOnCtrlC: false, stdin: inkStdin }
|
|
8636
9669
|
);
|