@wrongstack/tui 0.73.1 → 0.82.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -10
- package/dist/index.d.ts +86 -63
- package/dist/index.js +1474 -568
- 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
|
-
import { Box, Text, render, useApp, useStdout,
|
|
4
|
-
import
|
|
3
|
+
import { Box, Text, render, useApp, useStdout, Static, useInput, useStdin } from 'ink';
|
|
4
|
+
import React6, { useState, useEffect, useReducer, useRef, useMemo, useCallback } 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,34 @@ var theme = Object.freeze({
|
|
|
34
34
|
diffAddBg: "greenBright",
|
|
35
35
|
diffDelBg: "redBright"
|
|
36
36
|
});
|
|
37
|
+
function expectDefined(value) {
|
|
38
|
+
if (value === null || value === void 0) {
|
|
39
|
+
throw new Error("Expected value to be defined");
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
var MODE_ICONS = {
|
|
44
|
+
teach: "\u{1F9D1}\u200D\u{1F3EB}",
|
|
45
|
+
brief: "\u26A1",
|
|
46
|
+
"code-reviewer": "\u{1F50D}",
|
|
47
|
+
"bug-hunter": "\u{1F41B}",
|
|
48
|
+
"security-scanner": "\u{1F6E1}\uFE0F",
|
|
49
|
+
"refactor-planner": "\u{1F527}",
|
|
50
|
+
architect: "\u{1F3D7}\uFE0F",
|
|
51
|
+
debugger: "\u{1FAB2}",
|
|
52
|
+
test: "\u{1F9EA}",
|
|
53
|
+
document: "\u{1F4DD}",
|
|
54
|
+
"skill-creator": "\u{1F6E0}\uFE0F"
|
|
55
|
+
};
|
|
56
|
+
function modeIcon(label) {
|
|
57
|
+
if (!label) return "";
|
|
58
|
+
const icon = MODE_ICONS[label] ?? "\u25AA";
|
|
59
|
+
return `${icon} ${label}`;
|
|
60
|
+
}
|
|
37
61
|
var COMPACT_THRESHOLD = 50;
|
|
38
62
|
var COMFORTABLE_THRESHOLD = 90;
|
|
63
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
64
|
+
var SPINNER_INTERVAL_MS = 250;
|
|
39
65
|
function StatusBar({
|
|
40
66
|
model,
|
|
41
67
|
version,
|
|
@@ -45,7 +71,7 @@ function StatusBar({
|
|
|
45
71
|
queueCount = 0,
|
|
46
72
|
yolo = false,
|
|
47
73
|
autonomy,
|
|
48
|
-
|
|
74
|
+
startedAt,
|
|
49
75
|
todos,
|
|
50
76
|
plan,
|
|
51
77
|
fleet,
|
|
@@ -58,7 +84,9 @@ function StatusBar({
|
|
|
58
84
|
processCount,
|
|
59
85
|
hiddenItems,
|
|
60
86
|
eternalStage,
|
|
61
|
-
goalSummary
|
|
87
|
+
goalSummary,
|
|
88
|
+
indexState,
|
|
89
|
+
modeLabel
|
|
62
90
|
}) {
|
|
63
91
|
const { stdout } = useStdout();
|
|
64
92
|
const [termWidth, setTermWidth] = useState(stdout?.columns ?? 90);
|
|
@@ -76,8 +104,26 @@ function StatusBar({
|
|
|
76
104
|
const usage = tokenCounter?.total();
|
|
77
105
|
const cost = tokenCounter?.estimateCost();
|
|
78
106
|
const cache2 = tokenCounter?.cacheStats();
|
|
107
|
+
const [elapsedMs, setElapsedMs] = useState(startedAt ? Date.now() - startedAt : 0);
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
if (startedAt == null) return;
|
|
110
|
+
const t = setInterval(() => setElapsedMs(Date.now() - startedAt), 1e3);
|
|
111
|
+
return () => clearInterval(t);
|
|
112
|
+
}, [startedAt]);
|
|
113
|
+
const [spinnerIdx, setSpinnerIdx] = useState(0);
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
if (state === "idle" || state === "aborting") return;
|
|
116
|
+
const t = setInterval(
|
|
117
|
+
() => setSpinnerIdx((n) => (n + 1) % SPINNER_FRAMES.length),
|
|
118
|
+
SPINNER_INTERVAL_MS
|
|
119
|
+
);
|
|
120
|
+
return () => clearInterval(t);
|
|
121
|
+
}, [state]);
|
|
122
|
+
const spinner = expectDefined(SPINNER_FRAMES[spinnerIdx]);
|
|
79
123
|
const { label: stateLabel, color: stateColor } = stateChip(state, fleet?.running ?? 0);
|
|
80
|
-
const
|
|
124
|
+
const statePrefix = state === "idle" || state === "aborting" ? "\u25CF" : spinner;
|
|
125
|
+
const thinking = state === "running" || state === "streaming";
|
|
126
|
+
const hasSecondLine = yolo || autonomy && autonomy !== "off" || startedAt != null || git !== null && git !== void 0 || projectName !== void 0 && projectName.length > 0 || goalSummary !== null && goalSummary !== void 0 || !!modeLabel;
|
|
81
127
|
const fleetHasActivity = fleet && (fleet.running > 0 || fleet.idle > 0 || fleet.pending > 0 || fleet.completed > 0) || subagentCount > 0;
|
|
82
128
|
const hasBrainActivity = !!brain && brain.state !== "idle";
|
|
83
129
|
const hasThirdLine = todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) || fleetHasActivity || hasBrainActivity;
|
|
@@ -95,8 +141,8 @@ function StatusBar({
|
|
|
95
141
|
/* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: isCompact ? (
|
|
96
142
|
// Ultra-compact: state · model
|
|
97
143
|
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
98
|
-
/* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
|
|
99
|
-
|
|
144
|
+
thinking ? /* @__PURE__ */ jsx(WaveText, { text: `${statePrefix}${stateLabel}`, phase: spinnerIdx }) : /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
|
|
145
|
+
statePrefix,
|
|
100
146
|
stateLabel
|
|
101
147
|
] }),
|
|
102
148
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
@@ -115,8 +161,9 @@ function StatusBar({
|
|
|
115
161
|
] }),
|
|
116
162
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" })
|
|
117
163
|
] }) : null,
|
|
118
|
-
/* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
|
|
119
|
-
|
|
164
|
+
thinking ? /* @__PURE__ */ jsx(WaveText, { text: `${statePrefix} ${stateLabel}`, phase: spinnerIdx }) : /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
|
|
165
|
+
statePrefix,
|
|
166
|
+
" ",
|
|
120
167
|
stateLabel
|
|
121
168
|
] }),
|
|
122
169
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
@@ -170,6 +217,15 @@ function StatusBar({
|
|
|
170
217
|
hint ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
171
218
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
172
219
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: hint })
|
|
220
|
+
] }) : null,
|
|
221
|
+
indexState?.indexing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
222
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
223
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
224
|
+
"\u2699 indexing ",
|
|
225
|
+
indexState.currentFile,
|
|
226
|
+
"/",
|
|
227
|
+
indexState.totalFiles
|
|
228
|
+
] })
|
|
173
229
|
] }) : null
|
|
174
230
|
] })
|
|
175
231
|
) }),
|
|
@@ -201,14 +257,14 @@ function StatusBar({
|
|
|
201
257
|
] })
|
|
202
258
|
] }) : null,
|
|
203
259
|
projectName ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
204
|
-
yolo ||
|
|
260
|
+
yolo || startedAt != null ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
205
261
|
/* @__PURE__ */ jsxs(Text, { color: "blue", children: [
|
|
206
262
|
"\u{1F4C1} ",
|
|
207
263
|
projectName
|
|
208
264
|
] })
|
|
209
265
|
] }) : null,
|
|
210
266
|
goalSummary ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
211
|
-
yolo ||
|
|
267
|
+
yolo || startedAt != null || projectName ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
212
268
|
/* @__PURE__ */ jsxs(
|
|
213
269
|
Text,
|
|
214
270
|
{
|
|
@@ -227,8 +283,12 @@ function StatusBar({
|
|
|
227
283
|
}
|
|
228
284
|
)
|
|
229
285
|
] }) : null,
|
|
286
|
+
modeLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
287
|
+
yolo || autonomy && autonomy !== "off" || eternalStage || startedAt != null || projectName || goalSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
288
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: modeIcon(modeLabel) })
|
|
289
|
+
] }) : null,
|
|
230
290
|
git ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
231
|
-
yolo ||
|
|
291
|
+
yolo || startedAt != null || projectName ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
232
292
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
233
293
|
/* @__PURE__ */ jsxs(Text, { color: "magenta", children: [
|
|
234
294
|
"\u2387 ",
|
|
@@ -248,7 +308,7 @@ function StatusBar({
|
|
|
248
308
|
] }) : null
|
|
249
309
|
] })
|
|
250
310
|
] }) : null
|
|
251
|
-
] }) :
|
|
311
|
+
] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
|
|
252
312
|
hasThirdLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
253
313
|
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
254
314
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "todos " }),
|
|
@@ -322,13 +382,13 @@ function StatusBar({
|
|
|
322
382
|
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
383
|
/* @__PURE__ */ jsx(BrainChip, { brain })
|
|
324
384
|
] }) : null
|
|
325
|
-
] }) :
|
|
385
|
+
] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
|
|
326
386
|
fleetAgents && fleetAgents.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => (
|
|
327
387
|
// biome-ignore lint/suspicious/noArrayIndexKey: agent list is stable per render
|
|
328
388
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
329
389
|
/* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
|
|
330
390
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
331
|
-
/* @__PURE__ */ jsx(Text, {
|
|
391
|
+
/* @__PURE__ */ jsx(Text, { dimColor: !a.running, ...a.running ? { color: "yellow" } : {}, children: a.running ? "\u25B6" : "\xB7" }),
|
|
332
392
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
333
393
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtElapsed(a.elapsedMs) }),
|
|
334
394
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
@@ -348,7 +408,7 @@ function StatusBar({
|
|
|
348
408
|
] })
|
|
349
409
|
] }) : null
|
|
350
410
|
] }, i)
|
|
351
|
-
)) }) :
|
|
411
|
+
)) }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) })
|
|
352
412
|
]
|
|
353
413
|
}
|
|
354
414
|
);
|
|
@@ -457,6 +517,26 @@ function stateChip(state, fleetRunning) {
|
|
|
457
517
|
if (state === "aborting") return { label: "aborting\u2026", color: "yellow" };
|
|
458
518
|
return { label: "thinking\u2026", color: "green" };
|
|
459
519
|
}
|
|
520
|
+
var WAVE_COLORS = [
|
|
521
|
+
"#ff5f5f",
|
|
522
|
+
"#ff8f3f",
|
|
523
|
+
"#ffd23f",
|
|
524
|
+
"#bce84a",
|
|
525
|
+
"#6bcb77",
|
|
526
|
+
"#3dd9c0",
|
|
527
|
+
"#3fb6ff",
|
|
528
|
+
"#5f8bff",
|
|
529
|
+
"#845ef7",
|
|
530
|
+
"#b15bff",
|
|
531
|
+
"#f06595",
|
|
532
|
+
"#ff5fa2"
|
|
533
|
+
];
|
|
534
|
+
function WaveText({ text, phase }) {
|
|
535
|
+
return /* @__PURE__ */ jsx(Text, { bold: true, children: Array.from(text).map((ch, i) => (
|
|
536
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: glyph order is positional and re-rendered each tick
|
|
537
|
+
/* @__PURE__ */ jsx(Text, { color: WAVE_COLORS[(i + phase) % WAVE_COLORS.length], children: ch }, i)
|
|
538
|
+
)) });
|
|
539
|
+
}
|
|
460
540
|
var FILLED = "\u2588";
|
|
461
541
|
var EMPTY = "\u2591";
|
|
462
542
|
function renderProgress(ratio, width) {
|
|
@@ -518,7 +598,7 @@ function bucketActivity(recentTools, now, bins = 12, binMs = 2e3) {
|
|
|
518
598
|
let idx = Math.floor((t.at - windowStart) / binMs);
|
|
519
599
|
if (idx < 0) idx = 0;
|
|
520
600
|
if (idx >= bins) idx = bins - 1;
|
|
521
|
-
out[idx]
|
|
601
|
+
out[idx] = (out[idx] ?? 0) + 1;
|
|
522
602
|
}
|
|
523
603
|
return out;
|
|
524
604
|
}
|
|
@@ -647,7 +727,7 @@ function FleetMonitor({
|
|
|
647
727
|
// biome-ignore lint/suspicious/noArrayIndexKey: timeline is rebuilt per render
|
|
648
728
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
649
729
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `${fmtElapsed(Math.max(0, nowTick - ev.at))} ago`.padEnd(10) }),
|
|
650
|
-
/* @__PURE__ */ jsx(Text, { color: ev.color, children: ev.icon }),
|
|
730
|
+
/* @__PURE__ */ jsx(Text, { ...ev.color ? { color: ev.color } : {}, children: ev.icon }),
|
|
651
731
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ev.text })
|
|
652
732
|
] }, i)
|
|
653
733
|
)) }) : null
|
|
@@ -779,10 +859,12 @@ function ContextBar({
|
|
|
779
859
|
function AgentsMonitor({
|
|
780
860
|
entries,
|
|
781
861
|
totalCost,
|
|
862
|
+
leaderCost = 0,
|
|
782
863
|
totalTokens,
|
|
783
864
|
nowTick
|
|
784
865
|
}) {
|
|
785
866
|
const all = Object.values(entries);
|
|
867
|
+
const grandCost = leaderCost + totalCost;
|
|
786
868
|
const live = selectLiveAgents(all, nowTick);
|
|
787
869
|
const running = live.filter((e) => e.status === "running").length;
|
|
788
870
|
const totalDone = all.filter((e) => e.status === "success").length;
|
|
@@ -824,9 +906,17 @@ function AgentsMonitor({
|
|
|
824
906
|
fmtTokens2(totalTokens.output),
|
|
825
907
|
"\u2193"
|
|
826
908
|
] }) : null,
|
|
827
|
-
/* @__PURE__ */
|
|
909
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "total" }),
|
|
910
|
+
/* @__PURE__ */ jsxs(Text, { color: "green", bold: true, children: [
|
|
828
911
|
"$",
|
|
829
|
-
|
|
912
|
+
grandCost.toFixed(3)
|
|
913
|
+
] }),
|
|
914
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
915
|
+
"(leader $",
|
|
916
|
+
leaderCost.toFixed(3),
|
|
917
|
+
" \xB7 fleet $",
|
|
918
|
+
totalCost.toFixed(3),
|
|
919
|
+
")"
|
|
830
920
|
] }),
|
|
831
921
|
hiddenIdle > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
832
922
|
"\xB7 ",
|
|
@@ -869,6 +959,10 @@ function AgentsMonitor({
|
|
|
869
959
|
e.extensions && e.extensions > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
870
960
|
"\u26A1\xD7",
|
|
871
961
|
e.extensions
|
|
962
|
+
] }) : null,
|
|
963
|
+
e.cost > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
964
|
+
"$",
|
|
965
|
+
e.cost.toFixed(3)
|
|
872
966
|
] }) : null
|
|
873
967
|
] }),
|
|
874
968
|
e.status === "running" && e.currentTool ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, paddingLeft: 2, children: [
|
|
@@ -954,14 +1048,14 @@ function AutonomyPicker({
|
|
|
954
1048
|
selected,
|
|
955
1049
|
hint
|
|
956
1050
|
}) {
|
|
957
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
1051
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, children: [
|
|
958
1052
|
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Autonomy Mode \u2501\u2501" }),
|
|
959
1053
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc cancel \xB7 Ctrl+C exit" }),
|
|
960
1054
|
options.map((opt, i) => /* @__PURE__ */ jsxs(
|
|
961
1055
|
Text,
|
|
962
1056
|
{
|
|
963
|
-
color: i === selected ? opt.color : void 0,
|
|
964
1057
|
inverse: i === selected,
|
|
1058
|
+
...i === selected ? { color: opt.color } : {},
|
|
965
1059
|
children: [
|
|
966
1060
|
i === selected ? "\u203A " : " ",
|
|
967
1061
|
/* @__PURE__ */ jsx(Text, { bold: true, children: opt.label.padEnd(12) }),
|
|
@@ -1077,7 +1171,7 @@ function CheckpointTimeline({
|
|
|
1077
1171
|
onConfirm(selected);
|
|
1078
1172
|
}
|
|
1079
1173
|
});
|
|
1080
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
|
|
1174
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 1, children: [
|
|
1081
1175
|
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
1082
1176
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u27F2 Session Rewind" }),
|
|
1083
1177
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2014 \u2191/\u2193 navigate \xB7 Enter rewind \xB7 Esc cancel" })
|
|
@@ -1086,8 +1180,8 @@ function CheckpointTimeline({
|
|
|
1086
1180
|
const isSelected = i === selected;
|
|
1087
1181
|
const label = `[${cp.promptIndex}] ${cp.promptPreview}`;
|
|
1088
1182
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
1089
|
-
/* @__PURE__ */ jsx(Text, {
|
|
1090
|
-
/* @__PURE__ */ jsx(Text, {
|
|
1183
|
+
/* @__PURE__ */ jsx(Text, { bold: isSelected, ...isSelected ? { color: "cyan" } : {}, children: isSelected ? "\u25B8 " : " " }),
|
|
1184
|
+
/* @__PURE__ */ jsx(Text, { bold: isSelected, ...isSelected ? { color: "cyan" } : {}, children: label }),
|
|
1091
1185
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1092
1186
|
" ",
|
|
1093
1187
|
new Date(cp.ts).toLocaleTimeString()
|
|
@@ -1132,7 +1226,7 @@ function hasDiff(input) {
|
|
|
1132
1226
|
}
|
|
1133
1227
|
function renderDiffLine(line) {
|
|
1134
1228
|
const prefix = line.startsWith("+") ? "green" : line.startsWith("-") ? "red" : line.startsWith("@@") ? "cyan" : void 0;
|
|
1135
|
-
return /* @__PURE__ */ jsxs(Text, { color: prefix, children: [
|
|
1229
|
+
return /* @__PURE__ */ jsxs(Text, { ...prefix ? { color: prefix } : {}, children: [
|
|
1136
1230
|
line,
|
|
1137
1231
|
"\n"
|
|
1138
1232
|
] }, line);
|
|
@@ -1147,7 +1241,7 @@ function ConfirmPrompt({
|
|
|
1147
1241
|
suggestedPattern,
|
|
1148
1242
|
onDecision
|
|
1149
1243
|
}) {
|
|
1150
|
-
|
|
1244
|
+
React6.useEffect(() => {
|
|
1151
1245
|
writeOut("\x07");
|
|
1152
1246
|
}, []);
|
|
1153
1247
|
useInput((input2, _key) => {
|
|
@@ -1176,27 +1270,88 @@ function ConfirmPrompt({
|
|
|
1176
1270
|
inputSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: inputSummary }) : null,
|
|
1177
1271
|
showDiff && diff ? /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginY: 1, children: renderDiff(diff) }) : null,
|
|
1178
1272
|
/* @__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(
|
|
1273
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsx(Text, { children: buttonLabels(suggestedPattern).map((l) => /* @__PURE__ */ jsxs(React6.Fragment, { children: [
|
|
1180
1274
|
/* @__PURE__ */ jsx(Text, { bold: true, color: BUTTON_COLOR[l.decision], children: l.bracket }),
|
|
1181
1275
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: l.rest })
|
|
1182
1276
|
] }, l.decision)) }) })
|
|
1183
1277
|
] });
|
|
1184
1278
|
}
|
|
1279
|
+
function EnhancePanel({
|
|
1280
|
+
original,
|
|
1281
|
+
refined,
|
|
1282
|
+
delayMs,
|
|
1283
|
+
onDecision
|
|
1284
|
+
}) {
|
|
1285
|
+
const totalSecs = Math.max(1, Math.ceil(delayMs / 1e3));
|
|
1286
|
+
const [remaining, setRemaining] = React6.useState(totalSecs);
|
|
1287
|
+
const decideRef = React6.useRef(onDecision);
|
|
1288
|
+
decideRef.current = onDecision;
|
|
1289
|
+
React6.useEffect(() => {
|
|
1290
|
+
const id = setInterval(() => {
|
|
1291
|
+
setRemaining((r) => {
|
|
1292
|
+
if (r <= 1) {
|
|
1293
|
+
clearInterval(id);
|
|
1294
|
+
decideRef.current("refined");
|
|
1295
|
+
return 0;
|
|
1296
|
+
}
|
|
1297
|
+
return r - 1;
|
|
1298
|
+
});
|
|
1299
|
+
}, 1e3);
|
|
1300
|
+
return () => clearInterval(id);
|
|
1301
|
+
}, []);
|
|
1302
|
+
useInput((input, key) => {
|
|
1303
|
+
if (key.return) {
|
|
1304
|
+
onDecision("refined");
|
|
1305
|
+
} else if (key.escape) {
|
|
1306
|
+
onDecision("original");
|
|
1307
|
+
} else if (input?.toLowerCase() === "e") {
|
|
1308
|
+
onDecision("edit");
|
|
1309
|
+
}
|
|
1310
|
+
});
|
|
1311
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
1312
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
1313
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u2728 Refined request" }),
|
|
1314
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
1315
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1316
|
+
"\u2014 sending in ",
|
|
1317
|
+
remaining,
|
|
1318
|
+
"s"
|
|
1319
|
+
] })
|
|
1320
|
+
] }),
|
|
1321
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
1322
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "original: " }),
|
|
1323
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: original })
|
|
1324
|
+
] }),
|
|
1325
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
1326
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: "refined: " }),
|
|
1327
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: refined })
|
|
1328
|
+
] }),
|
|
1329
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
|
|
1330
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsxs(Text, { children: [
|
|
1331
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: "[Enter]" }),
|
|
1332
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " send \xB7 " }),
|
|
1333
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "[Esc]" }),
|
|
1334
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " use original \xB7 " }),
|
|
1335
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "[e]" }),
|
|
1336
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "dit" })
|
|
1337
|
+
] }) })
|
|
1338
|
+
] });
|
|
1339
|
+
}
|
|
1185
1340
|
function FilePicker({ query, matches, selected }) {
|
|
1186
1341
|
if (matches.length === 0) {
|
|
1187
|
-
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingX: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1342
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1188
1343
|
"@",
|
|
1189
1344
|
query,
|
|
1190
1345
|
" \u2014 no matches"
|
|
1191
1346
|
] }) });
|
|
1192
1347
|
}
|
|
1193
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
1348
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
1194
1349
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1195
1350
|
"@",
|
|
1196
1351
|
query || "\u2026",
|
|
1197
1352
|
" \u2014 \u2191/\u2193 select, Enter attach, Esc cancel"
|
|
1198
1353
|
] }),
|
|
1199
|
-
matches.map((m, i) => /* @__PURE__ */ jsxs(Text, {
|
|
1354
|
+
matches.map((m, i) => /* @__PURE__ */ jsxs(Text, { inverse: i === selected, ...i === selected ? { color: "cyan" } : {}, children: [
|
|
1200
1355
|
i === selected ? "\u203A " : " ",
|
|
1201
1356
|
highlight(m)
|
|
1202
1357
|
] }, m))
|
|
@@ -1270,9 +1425,8 @@ function FleetPanel({
|
|
|
1270
1425
|
] }) : null
|
|
1271
1426
|
] });
|
|
1272
1427
|
}
|
|
1273
|
-
function helpSections(
|
|
1428
|
+
function helpSections() {
|
|
1274
1429
|
const nav = [];
|
|
1275
|
-
if (opts.managed) nav.push({ keys: "PgUp/PgDn", desc: "scroll chat history" });
|
|
1276
1430
|
nav.push(
|
|
1277
1431
|
{ keys: "\u2191/\u2193", desc: "previous / next input (empty prompt)" },
|
|
1278
1432
|
{ keys: "?", desc: "open this help (empty prompt)" }
|
|
@@ -1285,6 +1439,9 @@ function helpSections(opts) {
|
|
|
1285
1439
|
{ keys: "Ctrl+F / F2", desc: "fleet orchestration monitor" },
|
|
1286
1440
|
{ keys: "Ctrl+G / F3", desc: "agents live monitor" },
|
|
1287
1441
|
{ keys: "Ctrl+T / F4", desc: "worktree monitor" },
|
|
1442
|
+
{ keys: "F5", desc: "autonomy settings (also Ctrl+S)" },
|
|
1443
|
+
{ keys: "F6", desc: "todos monitor overlay" },
|
|
1444
|
+
{ keys: "F7", desc: "queue panel" },
|
|
1288
1445
|
{ keys: "Esc", desc: "close the open monitor / overlay" }
|
|
1289
1446
|
]
|
|
1290
1447
|
},
|
|
@@ -1312,10 +1469,8 @@ function helpSections(opts) {
|
|
|
1312
1469
|
}
|
|
1313
1470
|
];
|
|
1314
1471
|
}
|
|
1315
|
-
function HelpOverlay({
|
|
1316
|
-
|
|
1317
|
-
}) {
|
|
1318
|
-
const sections = helpSections({ managed });
|
|
1472
|
+
function HelpOverlay() {
|
|
1473
|
+
const sections = helpSections();
|
|
1319
1474
|
const keyWidth = Math.max(...sections.flatMap((s2) => s2.entries.map((e) => e.keys.length)), 0);
|
|
1320
1475
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
1321
1476
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
@@ -1780,6 +1935,12 @@ function detectLang(fenceInfo) {
|
|
|
1780
1935
|
}
|
|
1781
1936
|
|
|
1782
1937
|
// src/markdown-table.ts
|
|
1938
|
+
function expectDefined2(value) {
|
|
1939
|
+
if (value === null || value === void 0) {
|
|
1940
|
+
throw new Error("Expected value to be defined");
|
|
1941
|
+
}
|
|
1942
|
+
return value;
|
|
1943
|
+
}
|
|
1783
1944
|
var ROW_RE = /^\s*\|.*\|\s*$/;
|
|
1784
1945
|
var SEP_RE = /^\s*\|[\s\-:|]+\|\s*$/;
|
|
1785
1946
|
function detectTable(lines, start) {
|
|
@@ -1860,16 +2021,17 @@ function computeWidths(allRows, cols, maxWidth, sepWidths) {
|
|
|
1860
2021
|
for (const row of allRows) {
|
|
1861
2022
|
for (let c = 0; c < cols; c++) {
|
|
1862
2023
|
const cell = row[c] ?? "";
|
|
1863
|
-
const
|
|
1864
|
-
const
|
|
1865
|
-
|
|
2024
|
+
const stripped = stripInlineMarkers(cell);
|
|
2025
|
+
const w = longestWord(stripped);
|
|
2026
|
+
const total = strWidth(stripped);
|
|
2027
|
+
natural[c] = Math.max(expectDefined2(natural[c]), w, total);
|
|
1866
2028
|
}
|
|
1867
2029
|
}
|
|
1868
2030
|
if (sepWidths) {
|
|
1869
2031
|
for (let c = 0; c < cols && c < sepWidths.length; c++) {
|
|
1870
2032
|
const sepW = sepWidths[c];
|
|
1871
2033
|
if (sepW != null) {
|
|
1872
|
-
natural[c] = Math.max(natural[c], sepW);
|
|
2034
|
+
natural[c] = Math.max(expectDefined2(natural[c]), sepW);
|
|
1873
2035
|
}
|
|
1874
2036
|
}
|
|
1875
2037
|
}
|
|
@@ -1881,24 +2043,90 @@ function computeWidths(allRows, cols, maxWidth, sepWidths) {
|
|
|
1881
2043
|
let maxIdx = -1;
|
|
1882
2044
|
let maxVal = MIN_COL_WIDTH;
|
|
1883
2045
|
for (let i = 0; i < cols; i++) {
|
|
1884
|
-
const w = widths[i];
|
|
2046
|
+
const w = expectDefined2(widths[i]);
|
|
1885
2047
|
if (w > maxVal) {
|
|
1886
2048
|
maxVal = w;
|
|
1887
2049
|
maxIdx = i;
|
|
1888
2050
|
}
|
|
1889
2051
|
}
|
|
1890
2052
|
if (maxIdx < 0) break;
|
|
1891
|
-
widths[maxIdx]
|
|
2053
|
+
widths[maxIdx] = (widths[maxIdx] ?? 0) - 1;
|
|
1892
2054
|
sum--;
|
|
1893
2055
|
}
|
|
1894
2056
|
return widths;
|
|
1895
2057
|
}
|
|
1896
2058
|
var MIN_COL_WIDTH = 4;
|
|
2059
|
+
var LIGATURE_PAIRS = [
|
|
2060
|
+
["-", ">"],
|
|
2061
|
+
// → arrow
|
|
2062
|
+
["<", "-"],
|
|
2063
|
+
// ←
|
|
2064
|
+
["=", ">"],
|
|
2065
|
+
// ⇒
|
|
2066
|
+
["<", "="],
|
|
2067
|
+
// ≤
|
|
2068
|
+
[">", "="],
|
|
2069
|
+
// ≥
|
|
2070
|
+
["!", "="],
|
|
2071
|
+
// ≠
|
|
2072
|
+
["=", "="],
|
|
2073
|
+
// equality (some fonts)
|
|
2074
|
+
["~", ">"],
|
|
2075
|
+
// ⇝
|
|
2076
|
+
["<", "~"]
|
|
2077
|
+
// ⇜
|
|
2078
|
+
];
|
|
2079
|
+
var ZWSP = "\u200B";
|
|
2080
|
+
function breakLigatures(text) {
|
|
2081
|
+
if (!/[-<=>!~]/.test(text)) return text;
|
|
2082
|
+
let result = "";
|
|
2083
|
+
for (let i = 0; i < text.length; i++) {
|
|
2084
|
+
result += text[i];
|
|
2085
|
+
if (i + 1 >= text.length) break;
|
|
2086
|
+
for (const [a, b] of LIGATURE_PAIRS) {
|
|
2087
|
+
if (text[i] === a && text[i + 1] === b) {
|
|
2088
|
+
result += ZWSP;
|
|
2089
|
+
break;
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
return result;
|
|
2094
|
+
}
|
|
1897
2095
|
function strWidth(s2) {
|
|
1898
2096
|
let width = 0;
|
|
1899
|
-
|
|
1900
|
-
|
|
2097
|
+
const len = s2.length;
|
|
2098
|
+
let i = 0;
|
|
2099
|
+
while (i < len) {
|
|
2100
|
+
if (s2[i] === "\x1B" && i + 1 < len && s2[i + 1] === "[") {
|
|
2101
|
+
i += 2;
|
|
2102
|
+
while (i < len && s2[i] !== "m") i++;
|
|
2103
|
+
if (i < len) i++;
|
|
2104
|
+
continue;
|
|
2105
|
+
}
|
|
2106
|
+
const code = expectDefined2(s2.codePointAt(i));
|
|
2107
|
+
const cpLen = code > 65535 ? 2 : 1;
|
|
2108
|
+
if (code === 8205 || // ZWJ — Zero Width Joiner (emoji sequences)
|
|
2109
|
+
code === 8203 || // ZWSP — Zero Width Space
|
|
2110
|
+
code === 8204 || // ZWNJ — Zero Width Non-Joiner
|
|
2111
|
+
code === 8206 || // LRM — Left-to-Right Mark
|
|
2112
|
+
code === 8207 || // RLM — Right-to-Left Mark
|
|
2113
|
+
code === 8288 || // WJ — Word Joiner
|
|
2114
|
+
code === 65279 || // BOM / ZWNBSP
|
|
2115
|
+
code >= 65024 && code <= 65039 || // Variation Selectors 1–16
|
|
2116
|
+
code >= 917760 && code <= 917999) {
|
|
2117
|
+
i += cpLen;
|
|
2118
|
+
continue;
|
|
2119
|
+
}
|
|
1901
2120
|
if (code < 32 || code >= 127 && code < 160) {
|
|
2121
|
+
i += cpLen;
|
|
2122
|
+
continue;
|
|
2123
|
+
}
|
|
2124
|
+
if (code >= 768 && code <= 879 || // Combining Diacritical Marks
|
|
2125
|
+
code >= 6832 && code <= 6911 || // Combining Diacritical Marks Extended
|
|
2126
|
+
code >= 7616 && code <= 7679 || // Combining Diacritical Marks Supplement
|
|
2127
|
+
code >= 8400 && code <= 8447 || // Combining Diacritical Marks for Symbols
|
|
2128
|
+
code >= 65056 && code <= 65071) {
|
|
2129
|
+
i += cpLen;
|
|
1902
2130
|
continue;
|
|
1903
2131
|
}
|
|
1904
2132
|
if (code >= 126976 || // Supplementary Pictographs (U+1F000-U+1FFFF)
|
|
@@ -1911,11 +2139,11 @@ function strWidth(s2) {
|
|
|
1911
2139
|
code >= 9664 && code <= 9726 || // More Geometric Shapes (includes ▶)
|
|
1912
2140
|
code >= 9984 && code <= 10175) {
|
|
1913
2141
|
width += 2;
|
|
2142
|
+
i += cpLen;
|
|
1914
2143
|
continue;
|
|
1915
2144
|
}
|
|
1916
2145
|
if (code >= 4352 && code <= 4447 || // Hangul Jamo
|
|
1917
|
-
code === 9001 || //
|
|
1918
|
-
code === 9002 || // RIGHT-POINTING ANGLE BRACKET
|
|
2146
|
+
code === 9001 || code === 9002 || // Angle brackets
|
|
1919
2147
|
code >= 11904 && code <= 12350 || // CJK Radicals Supplement
|
|
1920
2148
|
code >= 12352 && code <= 42191 || // Hiragana, Katakana, CJK
|
|
1921
2149
|
code >= 44032 && code <= 55203 || // Hangul Syllables
|
|
@@ -1927,9 +2155,11 @@ function strWidth(s2) {
|
|
|
1927
2155
|
code >= 131072 && code <= 196605 || // CJK Extension B+
|
|
1928
2156
|
code >= 196608 && code <= 262141) {
|
|
1929
2157
|
width += 2;
|
|
2158
|
+
i += cpLen;
|
|
1930
2159
|
continue;
|
|
1931
2160
|
}
|
|
1932
2161
|
width += 1;
|
|
2162
|
+
i += cpLen;
|
|
1933
2163
|
}
|
|
1934
2164
|
return width;
|
|
1935
2165
|
}
|
|
@@ -1944,8 +2174,22 @@ function longestWord(s2) {
|
|
|
1944
2174
|
function border(left, mid, right, widths) {
|
|
1945
2175
|
return left + widths.map((w) => "\u2500".repeat(w + 2)).join(mid) + right;
|
|
1946
2176
|
}
|
|
2177
|
+
function stripInlineMarkers(text) {
|
|
2178
|
+
return text.replace(/\*\*(.+?)\*\*/g, "$1").replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "$1").replace(/`(.+?)`/g, "$1").replace(/~~(.+?)~~/g, "$1");
|
|
2179
|
+
}
|
|
2180
|
+
var ANSI_BOLD = "\x1B[1m";
|
|
2181
|
+
var ANSI_RESET = "\x1B[22m";
|
|
2182
|
+
var ANSI_DIM = "\x1B[2m";
|
|
2183
|
+
var ANSI_CYAN = "\x1B[36m";
|
|
2184
|
+
var ANSI_STRIKE = "\x1B[9m";
|
|
2185
|
+
var ANSI_RESET_ALL = "\x1B[0m";
|
|
2186
|
+
function applyInlineAnsi(text) {
|
|
2187
|
+
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}`);
|
|
2188
|
+
}
|
|
1947
2189
|
function renderRow(cells, widths, aligns) {
|
|
1948
|
-
const
|
|
2190
|
+
const styled = cells.map((c) => applyInlineAnsi(c));
|
|
2191
|
+
const safe = styled.map((c) => breakLigatures(c));
|
|
2192
|
+
const wrapped = safe.map((c, i) => wrapCell(c, widths[i] ?? MIN_COL_WIDTH));
|
|
1949
2193
|
const height = Math.max(1, ...wrapped.map((w) => w.length));
|
|
1950
2194
|
const out = [];
|
|
1951
2195
|
for (let line = 0; line < height; line++) {
|
|
@@ -2102,10 +2346,10 @@ function InlineLine({ tokens, dim }) {
|
|
|
2102
2346
|
Text,
|
|
2103
2347
|
{
|
|
2104
2348
|
color: t.code ? theme.accent : "white",
|
|
2105
|
-
bold: t.bold,
|
|
2106
|
-
italic: t.italic,
|
|
2107
|
-
strikethrough: t.strike,
|
|
2108
|
-
dimColor: dim,
|
|
2349
|
+
bold: Boolean(t.bold),
|
|
2350
|
+
italic: Boolean(t.italic),
|
|
2351
|
+
strikethrough: Boolean(t.strike),
|
|
2352
|
+
dimColor: Boolean(dim),
|
|
2109
2353
|
children: t.text
|
|
2110
2354
|
},
|
|
2111
2355
|
j
|
|
@@ -2730,7 +2974,22 @@ function formatToolOutput(toolName, output, ok, _outputBytes, outputLines) {
|
|
|
2730
2974
|
}
|
|
2731
2975
|
var MAX_STREAM_DISPLAY_CHARS = 480;
|
|
2732
2976
|
var MAX_STREAM_LINES = 8;
|
|
2733
|
-
|
|
2977
|
+
function streamBoxRows(text, maxLines, contentWidth) {
|
|
2978
|
+
const trunc = (line) => line.length > contentWidth ? `${line.slice(0, contentWidth - 1)}\u2026` : line;
|
|
2979
|
+
const lines = text.split("\n");
|
|
2980
|
+
const totalLines = lines.length;
|
|
2981
|
+
const hidden = Math.max(0, totalLines - maxLines);
|
|
2982
|
+
const rows = [];
|
|
2983
|
+
if (hidden > 0) {
|
|
2984
|
+
rows.push({ text: ` \u2026 ${hidden} more line${hidden === 1 ? "" : "s"} above`, italic: true });
|
|
2985
|
+
for (const line of lines.slice(totalLines - (maxLines - 1))) rows.push({ text: trunc(line) });
|
|
2986
|
+
} else {
|
|
2987
|
+
for (let i = 0; i < maxLines - totalLines; i++) rows.push({ text: "" });
|
|
2988
|
+
for (const line of lines) rows.push({ text: trunc(line) });
|
|
2989
|
+
}
|
|
2990
|
+
return rows;
|
|
2991
|
+
}
|
|
2992
|
+
React6.memo(function ToolStreamBox2({
|
|
2734
2993
|
name,
|
|
2735
2994
|
text,
|
|
2736
2995
|
startedAt,
|
|
@@ -2742,11 +3001,10 @@ var ToolStreamBox = React5.memo(function ToolStreamBox2({
|
|
|
2742
3001
|
return () => clearInterval(t);
|
|
2743
3002
|
}, []);
|
|
2744
3003
|
const elapsedMs = Date.now() - startedAt;
|
|
2745
|
-
const
|
|
2746
|
-
const totalLines = lines.length;
|
|
3004
|
+
const totalLines = text.split("\n").length;
|
|
2747
3005
|
const hidden = Math.max(0, totalLines - MAX_STREAM_LINES);
|
|
2748
|
-
const visible = hidden > 0 ? lines.slice(hidden) : lines;
|
|
2749
3006
|
const contentWidth = Math.max(20, Math.min(termWidth - 4, 100));
|
|
3007
|
+
const rows = streamBoxRows(text, MAX_STREAM_LINES, contentWidth);
|
|
2750
3008
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 0, children: [
|
|
2751
3009
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
2752
3010
|
/* @__PURE__ */ jsx(Text, { color: theme.warn, children: "\u25C6 " }),
|
|
@@ -2754,13 +3012,10 @@ var ToolStreamBox = React5.memo(function ToolStreamBox2({
|
|
|
2754
3012
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u23F1 ${fmtDuration(elapsedMs)}` }),
|
|
2755
3013
|
hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` (${totalLines} lines, showing last ${MAX_STREAM_LINES})` }) : null
|
|
2756
3014
|
] }),
|
|
2757
|
-
/* @__PURE__ */
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: trimmed || " " }, i);
|
|
2762
|
-
})
|
|
2763
|
-
] })
|
|
3015
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", marginLeft: 2, children: rows.map((r, i) => (
|
|
3016
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: fixed-height block, index is the row
|
|
3017
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, italic: Boolean(r.italic), children: r.text || " " }, i)
|
|
3018
|
+
)) })
|
|
2764
3019
|
] });
|
|
2765
3020
|
});
|
|
2766
3021
|
function tailForDisplay(text, maxChars) {
|
|
@@ -2806,9 +3061,15 @@ function CodeBlock({
|
|
|
2806
3061
|
// biome-ignore lint/suspicious/noArrayIndexKey: code lines are positional
|
|
2807
3062
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2808
3063
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `${String(i + 1).padStart(gutterW, " ")} ` }),
|
|
2809
|
-
tokens.length === 0 ? " " : tokens.map((t, j) => (
|
|
2810
|
-
|
|
2811
|
-
|
|
3064
|
+
tokens.length === 0 ? " " : tokens.map((t, j) => /* @__PURE__ */ jsx(
|
|
3065
|
+
Text,
|
|
3066
|
+
{
|
|
3067
|
+
dimColor: Boolean(t.dim),
|
|
3068
|
+
bold: Boolean(t.bold),
|
|
3069
|
+
...t.color ? { color: t.color } : {},
|
|
3070
|
+
children: t.text
|
|
3071
|
+
},
|
|
3072
|
+
j
|
|
2812
3073
|
))
|
|
2813
3074
|
] }, i)
|
|
2814
3075
|
)),
|
|
@@ -2962,7 +3223,22 @@ function AssistantBody({
|
|
|
2962
3223
|
)
|
|
2963
3224
|
) });
|
|
2964
3225
|
}
|
|
2965
|
-
|
|
3226
|
+
var ASSISTANT_TAIL_LINES = 8;
|
|
3227
|
+
function assistantTailRows(text, tailLines, contentWidth) {
|
|
3228
|
+
const tail = text.split("\n").slice(-tailLines);
|
|
3229
|
+
const rows = [];
|
|
3230
|
+
for (let i = 0; i < tailLines - tail.length; i++) rows.push("");
|
|
3231
|
+
for (const line of tail) {
|
|
3232
|
+
rows.push(line.length > contentWidth ? `${line.slice(0, contentWidth - 1)}\u2026` : line);
|
|
3233
|
+
}
|
|
3234
|
+
return rows;
|
|
3235
|
+
}
|
|
3236
|
+
function AssistantTail({
|
|
3237
|
+
text,
|
|
3238
|
+
termWidth
|
|
3239
|
+
}) {
|
|
3240
|
+
const contentWidth = Math.max(20, termWidth - 3);
|
|
3241
|
+
const rows = assistantTailRows(text, ASSISTANT_TAIL_LINES, contentWidth);
|
|
2966
3242
|
return /* @__PURE__ */ jsxs(
|
|
2967
3243
|
Box,
|
|
2968
3244
|
{
|
|
@@ -2979,7 +3255,10 @@ function AssistantTail({ text }) {
|
|
|
2979
3255
|
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.assistant, children: "ASSISTANT" }),
|
|
2980
3256
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " (streaming\u2026)" })
|
|
2981
3257
|
] }),
|
|
2982
|
-
/* @__PURE__ */ jsx(
|
|
3258
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", children: rows.map((r, i) => (
|
|
3259
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: fixed-height block, index is the row
|
|
3260
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: r || " " }, i)
|
|
3261
|
+
)) })
|
|
2983
3262
|
]
|
|
2984
3263
|
}
|
|
2985
3264
|
);
|
|
@@ -3050,7 +3329,7 @@ function brainRiskColor(risk) {
|
|
|
3050
3329
|
function assistantContentWidth(termWidth) {
|
|
3051
3330
|
return Math.max(20, termWidth - MESSAGE_PANEL_CHROME_WIDTH);
|
|
3052
3331
|
}
|
|
3053
|
-
var Entry =
|
|
3332
|
+
var Entry = React6.memo(function Entry2({
|
|
3054
3333
|
entry,
|
|
3055
3334
|
termWidth
|
|
3056
3335
|
}) {
|
|
@@ -3142,8 +3421,8 @@ var Entry = React5.memo(function Entry2({
|
|
|
3142
3421
|
/* @__PURE__ */ jsx(
|
|
3143
3422
|
Text,
|
|
3144
3423
|
{
|
|
3145
|
-
color: !entry.ok || line.startsWith("!") ? "red" : void 0,
|
|
3146
3424
|
dimColor: entry.ok && !line.startsWith("!"),
|
|
3425
|
+
...!entry.ok || line.startsWith("!") ? { color: "red" } : {},
|
|
3147
3426
|
children: line
|
|
3148
3427
|
}
|
|
3149
3428
|
)
|
|
@@ -3276,19 +3555,9 @@ function History({ entries, streamingText, toolStream }) {
|
|
|
3276
3555
|
}, [stdout]);
|
|
3277
3556
|
const termWidth = termSize.columns;
|
|
3278
3557
|
const tail = streamingText ? tailForDisplay(streamingText, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
3279
|
-
const toolTail = toolStream?.text ? tailForDisplay(toolStream.text, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
3280
3558
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3281
3559
|
/* @__PURE__ */ jsx(Static, { items: entries, children: (entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth }) }, entry.id) }),
|
|
3282
|
-
tail ? /* @__PURE__ */ jsx(AssistantTail, { text: tail }) : null
|
|
3283
|
-
toolTail ? /* @__PURE__ */ jsx(
|
|
3284
|
-
ToolStreamBox,
|
|
3285
|
-
{
|
|
3286
|
-
name: toolStream.name,
|
|
3287
|
-
text: toolTail,
|
|
3288
|
-
startedAt: toolStream.startedAt,
|
|
3289
|
-
termWidth
|
|
3290
|
-
}
|
|
3291
|
-
) : null
|
|
3560
|
+
tail ? /* @__PURE__ */ jsx(AssistantTail, { text: tail, termWidth }) : null
|
|
3292
3561
|
] });
|
|
3293
3562
|
}
|
|
3294
3563
|
|
|
@@ -3394,6 +3663,12 @@ function layoutInputRows(prompt, value, cursor, width) {
|
|
|
3394
3663
|
if (row.length > 0 || rows.length === 0) rows.push(row);
|
|
3395
3664
|
return rows;
|
|
3396
3665
|
}
|
|
3666
|
+
function expectDefined3(value) {
|
|
3667
|
+
if (value === null || value === void 0) {
|
|
3668
|
+
throw new Error("Expected value to be defined");
|
|
3669
|
+
}
|
|
3670
|
+
return value;
|
|
3671
|
+
}
|
|
3397
3672
|
function renderRow2(cells, rowKey, promptColor) {
|
|
3398
3673
|
const out = [];
|
|
3399
3674
|
let run = "";
|
|
@@ -3442,6 +3717,19 @@ function isHomeEnd(data) {
|
|
|
3442
3717
|
return "end";
|
|
3443
3718
|
return null;
|
|
3444
3719
|
}
|
|
3720
|
+
function isBackspaceOrDelete(data) {
|
|
3721
|
+
if (data === "\x7F" || data === "\b") return "backspace";
|
|
3722
|
+
if (data === "\x1B[3~") return "delete";
|
|
3723
|
+
return null;
|
|
3724
|
+
}
|
|
3725
|
+
function parseMouseWheel(data) {
|
|
3726
|
+
const m = data.match(new RegExp(`^${String.fromCharCode(27)}\\[<(\\d+);(\\d+);(\\d+)([Mm])$`, "u"));
|
|
3727
|
+
if (!m) return null;
|
|
3728
|
+
const cb = Number.parseInt(expectDefined3(m[1]), 10);
|
|
3729
|
+
if (cb === 64) return 1;
|
|
3730
|
+
if (cb === 65) return -1;
|
|
3731
|
+
return null;
|
|
3732
|
+
}
|
|
3445
3733
|
var EMPTY_KEY = {
|
|
3446
3734
|
upArrow: false,
|
|
3447
3735
|
downArrow: false,
|
|
@@ -3477,15 +3765,29 @@ function Input({
|
|
|
3477
3765
|
if (!stdin || disabled) return;
|
|
3478
3766
|
const handleData = (data) => {
|
|
3479
3767
|
const s2 = data.toString();
|
|
3480
|
-
const
|
|
3481
|
-
if (
|
|
3768
|
+
const homeEnd = isHomeEnd(s2);
|
|
3769
|
+
if (homeEnd === "home") {
|
|
3482
3770
|
onKey("", { ...EMPTY_KEY, home: true });
|
|
3483
3771
|
return;
|
|
3484
3772
|
}
|
|
3485
|
-
if (
|
|
3773
|
+
if (homeEnd === "end") {
|
|
3486
3774
|
onKey("", { ...EMPTY_KEY, end: true });
|
|
3487
3775
|
return;
|
|
3488
3776
|
}
|
|
3777
|
+
const bsdel = isBackspaceOrDelete(s2);
|
|
3778
|
+
if (bsdel === "backspace") {
|
|
3779
|
+
onKey("", { ...EMPTY_KEY, backspace: true });
|
|
3780
|
+
return;
|
|
3781
|
+
}
|
|
3782
|
+
if (bsdel === "delete") {
|
|
3783
|
+
onKey("", { ...EMPTY_KEY, delete: true });
|
|
3784
|
+
return;
|
|
3785
|
+
}
|
|
3786
|
+
const wheelDelta = parseMouseWheel(s2);
|
|
3787
|
+
if (wheelDelta !== null) {
|
|
3788
|
+
onKey("", { ...EMPTY_KEY, wheelDeltaY: wheelDelta });
|
|
3789
|
+
return;
|
|
3790
|
+
}
|
|
3489
3791
|
const fn = fnKey(s2);
|
|
3490
3792
|
if (fn !== null) onKey("", { ...EMPTY_KEY, fn });
|
|
3491
3793
|
};
|
|
@@ -3520,45 +3822,6 @@ function Input({
|
|
|
3520
3822
|
hint ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: hint }) : null
|
|
3521
3823
|
] });
|
|
3522
3824
|
}
|
|
3523
|
-
function hintsFor(ctx) {
|
|
3524
|
-
if (ctx.confirm) {
|
|
3525
|
-
return [
|
|
3526
|
-
{ key: "y", label: "yes" },
|
|
3527
|
-
{ key: "n", label: "no" },
|
|
3528
|
-
{ key: "a", label: "always" },
|
|
3529
|
-
{ key: "d", label: "deny" }
|
|
3530
|
-
];
|
|
3531
|
-
}
|
|
3532
|
-
if (ctx.picker) {
|
|
3533
|
-
return [
|
|
3534
|
-
{ key: "\u2191\u2193", label: "move" },
|
|
3535
|
-
{ key: "\u21B5", label: "select" },
|
|
3536
|
-
{ key: "Esc", label: "cancel" }
|
|
3537
|
-
];
|
|
3538
|
-
}
|
|
3539
|
-
if (ctx.monitor) {
|
|
3540
|
-
return [
|
|
3541
|
-
{ key: "Esc", label: "close" },
|
|
3542
|
-
{ key: "^F", label: "fleet" },
|
|
3543
|
-
{ key: "^G", label: "agents" },
|
|
3544
|
-
{ key: "^T", label: "worktrees" }
|
|
3545
|
-
];
|
|
3546
|
-
}
|
|
3547
|
-
const base = [{ key: "?", label: "help" }];
|
|
3548
|
-
if (ctx.managed) base.push({ key: "PgUp/PgDn", label: "scroll" });
|
|
3549
|
-
base.push({ key: "^G", label: "agents" }, { key: "^C", label: "stop" });
|
|
3550
|
-
return base;
|
|
3551
|
-
}
|
|
3552
|
-
function KeyHintBar({ context }) {
|
|
3553
|
-
const hints = hintsFor(context);
|
|
3554
|
-
return /* @__PURE__ */ jsx(Box, { flexDirection: "row", paddingX: 1, children: hints.map((h, i) => (
|
|
3555
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: hints are positional + stable
|
|
3556
|
-
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", marginRight: 2, children: [
|
|
3557
|
-
/* @__PURE__ */ jsx(Text, { color: theme.accent, children: h.key }),
|
|
3558
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${h.label}` })
|
|
3559
|
-
] }, i)
|
|
3560
|
-
)) });
|
|
3561
|
-
}
|
|
3562
3825
|
function fmtElapsed2(ms) {
|
|
3563
3826
|
if (ms < 1e3) return `${ms}ms`;
|
|
3564
3827
|
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
@@ -3585,13 +3848,16 @@ function fmtRecentMessage(message) {
|
|
|
3585
3848
|
const text = message.text.replace(/\s+/g, " ");
|
|
3586
3849
|
return text.length > 48 ? `${text.slice(0, 47)}...` : text;
|
|
3587
3850
|
}
|
|
3588
|
-
var LiveActivityStrip =
|
|
3851
|
+
var LiveActivityStrip = React6.memo(function LiveActivityStrip2({
|
|
3589
3852
|
entries,
|
|
3590
3853
|
nowTick,
|
|
3591
3854
|
maxRows = 4
|
|
3592
3855
|
}) {
|
|
3593
3856
|
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)
|
|
3857
|
+
if (running.length === 0) {
|
|
3858
|
+
if (Object.keys(entries).length === 0) return null;
|
|
3859
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingX: 1, children: Array.from({ length: maxRows }, (_, slot) => slot).map((slot) => /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }, `empty-${slot}`)) });
|
|
3860
|
+
}
|
|
3595
3861
|
const now = Date.now();
|
|
3596
3862
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
3597
3863
|
running.map((e) => {
|
|
@@ -3661,10 +3927,10 @@ function ModelPicker({
|
|
|
3661
3927
|
hint
|
|
3662
3928
|
}) {
|
|
3663
3929
|
if (step === "provider") {
|
|
3664
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
3930
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
3665
3931
|
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Switch model \u2014 Step 1/2: Pick provider \u2501\u2501" }),
|
|
3666
3932
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc cancel \xB7 Ctrl+C exit" }),
|
|
3667
|
-
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, {
|
|
3933
|
+
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, { inverse: i === selected, ...i === selected ? { color: "cyan" } : {}, children: [
|
|
3668
3934
|
i === selected ? "\u203A " : " ",
|
|
3669
3935
|
/* @__PURE__ */ jsx(Text, { bold: true, children: p.id.padEnd(28) }),
|
|
3670
3936
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
@@ -3686,7 +3952,7 @@ function ModelPicker({
|
|
|
3686
3952
|
const { start, end } = getVisibleWindow(selected, total);
|
|
3687
3953
|
const visibleItems = filteredOptions.slice(start, end);
|
|
3688
3954
|
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: [
|
|
3955
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
3690
3956
|
/* @__PURE__ */ jsxs(Text, { color: "cyan", bold: true, children: [
|
|
3691
3957
|
"\u2501\u2501 Switch model \u2014 Step 2/2: Pick model ",
|
|
3692
3958
|
"(",
|
|
@@ -3707,8 +3973,8 @@ function ModelPicker({
|
|
|
3707
3973
|
return /* @__PURE__ */ jsxs(
|
|
3708
3974
|
Text,
|
|
3709
3975
|
{
|
|
3710
|
-
color: absoluteIndex === selected ? "cyan" : void 0,
|
|
3711
3976
|
inverse: absoluteIndex === selected,
|
|
3977
|
+
...absoluteIndex === selected ? { color: "cyan" } : {},
|
|
3712
3978
|
children: [
|
|
3713
3979
|
absoluteIndex === selected ? "\u203A " : " ",
|
|
3714
3980
|
id
|
|
@@ -3901,166 +4167,406 @@ function PhasePanel({ phases, nowTick }) {
|
|
|
3901
4167
|
}
|
|
3902
4168
|
);
|
|
3903
4169
|
}
|
|
3904
|
-
|
|
3905
|
-
function scrollbarThumb(rows, offset, total) {
|
|
3906
|
-
const scrollable = total > rows;
|
|
3907
|
-
if (!scrollable) return { top: 0, size: rows, scrollable: false };
|
|
3908
|
-
const windowTop = Math.max(0, total - rows - offset);
|
|
3909
|
-
const size = Math.max(1, Math.round(rows / total * rows));
|
|
3910
|
-
const rawTop = Math.round(windowTop / total * rows);
|
|
3911
|
-
const top = Math.max(0, Math.min(rawTop, rows - size));
|
|
3912
|
-
return { top, size, scrollable: true };
|
|
3913
|
-
}
|
|
3914
|
-
function Scrollbar({
|
|
3915
|
-
rows,
|
|
3916
|
-
offset,
|
|
3917
|
-
total
|
|
3918
|
-
}) {
|
|
3919
|
-
const { top: thumbTop, size: thumbSize, scrollable } = scrollbarThumb(rows, offset, total);
|
|
3920
|
-
const cells = [];
|
|
3921
|
-
for (let i = 0; i < rows; i++) {
|
|
3922
|
-
cells.push(i >= thumbTop && i < thumbTop + thumbSize ? "\u2588" : "\u2502");
|
|
3923
|
-
}
|
|
3924
|
-
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginLeft: 1, flexShrink: 0, children: cells.map((c, i) => /* @__PURE__ */ jsx(
|
|
3925
|
-
Text,
|
|
3926
|
-
{
|
|
3927
|
-
color: scrollable ? theme.accent : void 0,
|
|
3928
|
-
dimColor: !scrollable || c === "\u2502",
|
|
3929
|
-
children: c
|
|
3930
|
-
},
|
|
3931
|
-
i
|
|
3932
|
-
)) });
|
|
3933
|
-
}
|
|
3934
|
-
function ScrollableHistory({
|
|
3935
|
-
entries,
|
|
3936
|
-
streamingText,
|
|
3937
|
-
toolStream,
|
|
3938
|
-
scrollOffset,
|
|
3939
|
-
viewportRows,
|
|
3940
|
-
totalLines,
|
|
3941
|
-
onMeasure
|
|
3942
|
-
}) {
|
|
4170
|
+
function QueuePanel({ items }) {
|
|
3943
4171
|
const { stdout } = useStdout();
|
|
3944
|
-
const
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
}
|
|
3952
|
-
const
|
|
3953
|
-
const
|
|
3954
|
-
const
|
|
3955
|
-
const
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
}
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
shown.map((entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, flexShrink: 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth }) }, entry.id)),
|
|
3987
|
-
tail ? /* @__PURE__ */ jsx(AssistantTail, { text: tail }) : null,
|
|
3988
|
-
toolTail ? /* @__PURE__ */ jsx(
|
|
3989
|
-
ToolStreamBox,
|
|
3990
|
-
{
|
|
3991
|
-
name: toolStream.name,
|
|
3992
|
-
text: toolTail,
|
|
3993
|
-
startedAt: toolStream.startedAt,
|
|
3994
|
-
termWidth
|
|
3995
|
-
}
|
|
3996
|
-
) : null
|
|
3997
|
-
]
|
|
3998
|
-
}
|
|
3999
|
-
)
|
|
4000
|
-
}
|
|
4001
|
-
),
|
|
4002
|
-
/* @__PURE__ */ jsx(Scrollbar, { rows: vp, offset: Math.max(0, scrollOffset), total: totalLines })
|
|
4172
|
+
const w = stdout?.columns ?? 80;
|
|
4173
|
+
const h = stdout?.rows ?? 24;
|
|
4174
|
+
const avail = Math.max(10, Math.floor(w * 0.3) - 4);
|
|
4175
|
+
const labelMax = Math.max(4, avail - 7);
|
|
4176
|
+
const trunc = (s2) => {
|
|
4177
|
+
if (s2.length <= labelMax) return s2;
|
|
4178
|
+
return s2.slice(0, labelMax - 1) + "\u2026";
|
|
4179
|
+
};
|
|
4180
|
+
const OVERHEAD = 7;
|
|
4181
|
+
const maxVisible = Math.max(4, h - OVERHEAD);
|
|
4182
|
+
const visible = items.slice(0, maxVisible);
|
|
4183
|
+
const overflow = items.length - visible.length;
|
|
4184
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
4185
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
4186
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "QUEUE" }),
|
|
4187
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: items.length }),
|
|
4188
|
+
overflow > 0 ? /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
4189
|
+
"+",
|
|
4190
|
+
overflow
|
|
4191
|
+
] }) : null,
|
|
4192
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 F7 / Esc to close" })
|
|
4193
|
+
] }) }),
|
|
4194
|
+
items.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No queued messages" }) : /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
4195
|
+
visible.map((item, i) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", flexShrink: 0, children: [
|
|
4196
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4197
|
+
String(i + 1).padStart(2),
|
|
4198
|
+
"."
|
|
4199
|
+
] }),
|
|
4200
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4201
|
+
" ",
|
|
4202
|
+
trunc(item.displayText)
|
|
4203
|
+
] })
|
|
4204
|
+
] }, item.id)),
|
|
4205
|
+
overflow > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", flexShrink: 0, marginTop: 0, children: [
|
|
4206
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2026" }),
|
|
4207
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4208
|
+
" +",
|
|
4209
|
+
overflow,
|
|
4210
|
+
" more"
|
|
4211
|
+
] })
|
|
4212
|
+
] }) : null
|
|
4213
|
+
] })
|
|
4003
4214
|
] });
|
|
4004
4215
|
}
|
|
4005
4216
|
var DELAY_PRESETS_MS = [0, 15e3, 3e4, 45e3, 6e4, 12e4];
|
|
4006
4217
|
var SETTINGS_MODES = ["off", "suggest", "auto"];
|
|
4218
|
+
var LOG_LEVELS = ["error", "warn", "info", "debug", "trace"];
|
|
4219
|
+
var AUDIT_LEVELS = ["minimal", "standard", "full"];
|
|
4220
|
+
var COMPACTOR_STRATEGIES = ["hybrid", "intelligent", "selective"];
|
|
4221
|
+
var MAX_ITERATIONS_PRESETS = [100, 200, 500, 1e3, 0];
|
|
4007
4222
|
function formatSettingsDelay(ms) {
|
|
4008
4223
|
if (ms === 0) return "disabled";
|
|
4009
4224
|
if (ms >= 6e4) return `${Math.round(ms / 6e4)}m`;
|
|
4010
4225
|
return `${Math.round(ms / 1e3)}s`;
|
|
4011
4226
|
}
|
|
4227
|
+
function formatMaxIterations(n) {
|
|
4228
|
+
if (n === 0) return "unlimited";
|
|
4229
|
+
return String(n);
|
|
4230
|
+
}
|
|
4012
4231
|
var MODE_DESC = {
|
|
4013
4232
|
off: "Agent stops after each turn (normal)",
|
|
4014
4233
|
suggest: "Shows next-step suggestions after each turn",
|
|
4015
4234
|
auto: "Self-driving \u2014 agent continues automatically"
|
|
4016
4235
|
};
|
|
4236
|
+
var SETTINGS_FIELD_COUNT = 19;
|
|
4017
4237
|
function SettingsPicker({
|
|
4018
4238
|
field,
|
|
4019
4239
|
mode,
|
|
4020
4240
|
delayMs,
|
|
4241
|
+
titleAnimation,
|
|
4242
|
+
yolo,
|
|
4243
|
+
streamFleet,
|
|
4244
|
+
chime,
|
|
4245
|
+
confirmExit,
|
|
4246
|
+
nextPrediction,
|
|
4247
|
+
featureMcp,
|
|
4248
|
+
featurePlugins,
|
|
4249
|
+
featureMemory,
|
|
4250
|
+
featureSkills,
|
|
4251
|
+
featureModelsRegistry,
|
|
4252
|
+
contextAutoCompact,
|
|
4253
|
+
contextStrategy,
|
|
4254
|
+
logLevel,
|
|
4255
|
+
auditLevel,
|
|
4256
|
+
indexOnStart,
|
|
4257
|
+
maxIterations,
|
|
4021
4258
|
hint
|
|
4022
4259
|
}) {
|
|
4260
|
+
const boolVal = (v) => v ? "on" : "off";
|
|
4023
4261
|
const rows = [
|
|
4262
|
+
// ── Autonomy ──
|
|
4263
|
+
{ section: "Autonomy" },
|
|
4024
4264
|
{ label: "Default autonomy mode", value: mode, detail: MODE_DESC[mode] },
|
|
4025
4265
|
{
|
|
4026
4266
|
label: "Auto-proceed delay",
|
|
4027
4267
|
value: formatSettingsDelay(delayMs),
|
|
4028
4268
|
detail: "Wait before auto-continuing in auto mode"
|
|
4269
|
+
},
|
|
4270
|
+
// ── UX ──
|
|
4271
|
+
{ section: "UX" },
|
|
4272
|
+
{
|
|
4273
|
+
label: "Terminal title animation",
|
|
4274
|
+
value: boolVal(titleAnimation),
|
|
4275
|
+
detail: "Animated window/tab title with status"
|
|
4276
|
+
},
|
|
4277
|
+
{
|
|
4278
|
+
label: "YOLO mode",
|
|
4279
|
+
value: boolVal(yolo),
|
|
4280
|
+
detail: "Skip all confirmation prompts"
|
|
4281
|
+
},
|
|
4282
|
+
{
|
|
4283
|
+
label: "Stream fleet to chat",
|
|
4284
|
+
value: boolVal(streamFleet),
|
|
4285
|
+
detail: "Show subagent messages in main chat"
|
|
4286
|
+
},
|
|
4287
|
+
{
|
|
4288
|
+
label: "Completion chime",
|
|
4289
|
+
value: boolVal(chime),
|
|
4290
|
+
detail: "Play a sound when agent finishes"
|
|
4291
|
+
},
|
|
4292
|
+
{
|
|
4293
|
+
label: "Confirm before exit",
|
|
4294
|
+
value: boolVal(confirmExit),
|
|
4295
|
+
detail: "Ask for confirmation on Ctrl+C exit"
|
|
4296
|
+
},
|
|
4297
|
+
{
|
|
4298
|
+
label: "Next-step prediction",
|
|
4299
|
+
value: boolVal(nextPrediction),
|
|
4300
|
+
detail: "Show LLM-predicted next steps (/next)"
|
|
4301
|
+
},
|
|
4302
|
+
// ── Features ──
|
|
4303
|
+
{ section: "Features" },
|
|
4304
|
+
{
|
|
4305
|
+
label: "MCP servers",
|
|
4306
|
+
value: boolVal(featureMcp),
|
|
4307
|
+
detail: "Load MCP servers from config"
|
|
4308
|
+
},
|
|
4309
|
+
{
|
|
4310
|
+
label: "Plugins",
|
|
4311
|
+
value: boolVal(featurePlugins),
|
|
4312
|
+
detail: "Load npm plugins from config"
|
|
4313
|
+
},
|
|
4314
|
+
{
|
|
4315
|
+
label: "Memory",
|
|
4316
|
+
value: boolVal(featureMemory),
|
|
4317
|
+
detail: "Enable remember/forget tools"
|
|
4318
|
+
},
|
|
4319
|
+
{
|
|
4320
|
+
label: "Skills",
|
|
4321
|
+
value: boolVal(featureSkills),
|
|
4322
|
+
detail: "Discover and load skills from disk"
|
|
4323
|
+
},
|
|
4324
|
+
{
|
|
4325
|
+
label: "Models registry",
|
|
4326
|
+
value: boolVal(featureModelsRegistry),
|
|
4327
|
+
detail: "Fetch models.dev catalog at startup"
|
|
4328
|
+
},
|
|
4329
|
+
// ── Context ──
|
|
4330
|
+
{ section: "Context" },
|
|
4331
|
+
{
|
|
4332
|
+
label: "Auto-compact",
|
|
4333
|
+
value: boolVal(contextAutoCompact),
|
|
4334
|
+
detail: "Auto-compact context when thresholds crossed"
|
|
4335
|
+
},
|
|
4336
|
+
{
|
|
4337
|
+
label: "Compactor strategy",
|
|
4338
|
+
value: contextStrategy,
|
|
4339
|
+
detail: "hybrid (fast) | intelligent (LLM) | selective"
|
|
4340
|
+
},
|
|
4341
|
+
// ── Logging ──
|
|
4342
|
+
{ section: "Logging" },
|
|
4343
|
+
{
|
|
4344
|
+
label: "Log level",
|
|
4345
|
+
value: logLevel,
|
|
4346
|
+
detail: "Console log verbosity"
|
|
4347
|
+
},
|
|
4348
|
+
// ── Session ──
|
|
4349
|
+
{ section: "Session" },
|
|
4350
|
+
{
|
|
4351
|
+
label: "Audit level",
|
|
4352
|
+
value: auditLevel,
|
|
4353
|
+
detail: "minimal | standard | full (large)"
|
|
4354
|
+
},
|
|
4355
|
+
// ── Indexing ──
|
|
4356
|
+
{ section: "Indexing" },
|
|
4357
|
+
{
|
|
4358
|
+
label: "Index on session start",
|
|
4359
|
+
value: boolVal(indexOnStart),
|
|
4360
|
+
detail: "Run incremental index at session start"
|
|
4361
|
+
},
|
|
4362
|
+
// ── Tools ──
|
|
4363
|
+
{ section: "Tools" },
|
|
4364
|
+
{
|
|
4365
|
+
label: "Max iterations",
|
|
4366
|
+
value: formatMaxIterations(maxIterations),
|
|
4367
|
+
detail: "100\u20131000 or unlimited (0)"
|
|
4029
4368
|
}
|
|
4030
4369
|
];
|
|
4031
|
-
|
|
4370
|
+
const fieldRowIndex = [];
|
|
4371
|
+
for (let i = 0; i < rows.length; i++) {
|
|
4372
|
+
if (!rows[i]?.section) fieldRowIndex.push(i);
|
|
4373
|
+
}
|
|
4374
|
+
const VISIBLE_FIELDS = 8;
|
|
4375
|
+
const totalFields = fieldRowIndex.length;
|
|
4376
|
+
const windowStart = totalFields <= VISIBLE_FIELDS ? 0 : Math.max(0, Math.min(field - Math.floor(VISIBLE_FIELDS / 2), totalFields - VISIBLE_FIELDS));
|
|
4377
|
+
const windowEnd = Math.min(windowStart + VISIBLE_FIELDS, totalFields);
|
|
4378
|
+
const hasAbove = windowStart > 0;
|
|
4379
|
+
const hasBelow = windowEnd < totalFields;
|
|
4380
|
+
const sectionFields = [];
|
|
4381
|
+
let curHeader = -1;
|
|
4382
|
+
for (let i = 0; i < rows.length; i++) {
|
|
4383
|
+
if (rows[i]?.section) curHeader = i;
|
|
4384
|
+
else if (curHeader >= 0) {
|
|
4385
|
+
const fieldIdx = fieldRowIndex.indexOf(i);
|
|
4386
|
+
if (fieldIdx === -1) continue;
|
|
4387
|
+
const entry = sectionFields.find((s2) => s2.headerIdx === curHeader);
|
|
4388
|
+
if (entry) {
|
|
4389
|
+
entry.fieldEnd = fieldIdx + 1;
|
|
4390
|
+
} else {
|
|
4391
|
+
sectionFields.push({ headerIdx: curHeader, fieldStart: fieldIdx, fieldEnd: fieldIdx + 1 });
|
|
4392
|
+
}
|
|
4393
|
+
}
|
|
4394
|
+
}
|
|
4395
|
+
const shouldShowSection = (headerIdx) => {
|
|
4396
|
+
const sec = sectionFields.find((s2) => s2.headerIdx === headerIdx);
|
|
4397
|
+
if (!sec) return false;
|
|
4398
|
+
return sec.fieldStart < windowEnd && sec.fieldEnd > windowStart;
|
|
4399
|
+
};
|
|
4400
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
4032
4401
|
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Settings \u2501\u2501" }),
|
|
4033
4402
|
/* @__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
|
-
|
|
4403
|
+
hasAbove ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2191 ${windowStart} field${windowStart === 1 ? "" : "s"} above` }) : null,
|
|
4404
|
+
rows.map((row, i) => {
|
|
4405
|
+
const fieldAtRow = fieldRowIndex.indexOf(i);
|
|
4406
|
+
if (fieldAtRow === -1) {
|
|
4407
|
+
if (shouldShowSection(i)) {
|
|
4408
|
+
return /* @__PURE__ */ jsxs(Text, { bold: true, color: "green", children: [
|
|
4409
|
+
"\u2500\u2500 ",
|
|
4410
|
+
row.section,
|
|
4411
|
+
" \u2500\u2500"
|
|
4412
|
+
] }, `section-${row.section ?? i}`);
|
|
4413
|
+
}
|
|
4414
|
+
return null;
|
|
4415
|
+
}
|
|
4416
|
+
if (fieldAtRow < windowStart || fieldAtRow >= windowEnd) return null;
|
|
4417
|
+
const selected = fieldAtRow === field;
|
|
4418
|
+
return /* @__PURE__ */ jsxs(Text, { inverse: selected, ...selected ? { color: "yellow" } : {}, children: [
|
|
4419
|
+
selected ? "\u203A " : " ",
|
|
4420
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: (row.label ?? "").padEnd(26) }),
|
|
4421
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: String(row.value ?? "").padEnd(12) }),
|
|
4422
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: row.detail ?? "" })
|
|
4423
|
+
] }, `row-${row.label ?? fieldAtRow}`);
|
|
4424
|
+
}),
|
|
4425
|
+
hasBelow ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2193 ${totalFields - windowEnd} field${totalFields - windowEnd === 1 ? "" : "s"} below` }) : null,
|
|
4040
4426
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Persisted to ~/.wrongstack/config.json" }),
|
|
4041
4427
|
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
4042
4428
|
] });
|
|
4043
4429
|
}
|
|
4044
4430
|
function SlashMenu({ query, matches, selected }) {
|
|
4045
4431
|
const placeholder = query ? `/${query}` : "/";
|
|
4046
|
-
|
|
4432
|
+
const rows = [];
|
|
4433
|
+
let lastCategory = "";
|
|
4434
|
+
for (let i = 0; i < matches.length; i++) {
|
|
4435
|
+
const m = matches[i];
|
|
4436
|
+
if (m.category !== lastCategory) {
|
|
4437
|
+
lastCategory = m.category;
|
|
4438
|
+
rows.push({ type: "header", category: m.category });
|
|
4439
|
+
}
|
|
4440
|
+
rows.push({ type: "item", match: m, index: i });
|
|
4441
|
+
}
|
|
4442
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
4047
4443
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4048
4444
|
placeholder || "/",
|
|
4049
4445
|
" \u2014 \u2191/\u2193 select, Enter dispatch, Tab autocomplete, Esc close"
|
|
4050
4446
|
] }),
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4447
|
+
rows.map((row) => {
|
|
4448
|
+
if (row.type === "header") {
|
|
4449
|
+
return /* @__PURE__ */ jsxs(Text, { bold: true, color: "yellow", dimColor: true, children: [
|
|
4450
|
+
" ",
|
|
4451
|
+
row.category
|
|
4452
|
+
] }, `cat-${row.category}`);
|
|
4453
|
+
}
|
|
4454
|
+
const { match: m, index: i } = row;
|
|
4455
|
+
return /* @__PURE__ */ jsxs(Text, { inverse: i === selected, ...i === selected ? { color: "cyan" } : {}, children: [
|
|
4456
|
+
i === selected ? "\u203A " : " ",
|
|
4457
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: m.name }),
|
|
4458
|
+
m.argsHint ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4459
|
+
" ",
|
|
4460
|
+
m.argsHint
|
|
4461
|
+
] }) : null,
|
|
4462
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4463
|
+
" \u2014 ",
|
|
4464
|
+
m.description
|
|
4465
|
+
] })
|
|
4466
|
+
] }, m.name);
|
|
4467
|
+
}),
|
|
4468
|
+
matches.length === 0 && /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No matching commands" })
|
|
4469
|
+
] });
|
|
4470
|
+
}
|
|
4471
|
+
function TodosMonitor({ todos }) {
|
|
4472
|
+
const { stdout } = useStdout();
|
|
4473
|
+
const done = todos.filter((t) => t.status === "completed").length;
|
|
4474
|
+
const inProgress = todos.filter((t) => t.status === "in_progress").length;
|
|
4475
|
+
const pending = todos.filter((t) => t.status === "pending").length;
|
|
4476
|
+
const w = stdout?.columns ?? 80;
|
|
4477
|
+
const twoCols = w >= 100;
|
|
4478
|
+
const mid = Math.ceil(todos.length / 2);
|
|
4479
|
+
const colWidth = twoCols ? Math.floor((w - 8) / 2) : w - 6;
|
|
4480
|
+
const trunc = (text, maxLen) => {
|
|
4481
|
+
if (text.length <= maxLen) return text;
|
|
4482
|
+
return text.slice(0, maxLen - 1) + "\u2026";
|
|
4483
|
+
};
|
|
4484
|
+
const renderRow3 = (t, idx) => {
|
|
4485
|
+
const num = String(idx + 1).padStart(2);
|
|
4486
|
+
const label = t.status === "in_progress" && t.activeForm ? t.activeForm : t.content;
|
|
4487
|
+
const display = trunc(label, colWidth - 8);
|
|
4488
|
+
if (t.status === "completed") {
|
|
4489
|
+
return /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4490
|
+
" ",
|
|
4491
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4492
|
+
num,
|
|
4493
|
+
"."
|
|
4494
|
+
] }),
|
|
4055
4495
|
" ",
|
|
4056
|
-
|
|
4057
|
-
|
|
4496
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: "[x]" }),
|
|
4497
|
+
" ",
|
|
4498
|
+
display
|
|
4499
|
+
] }, t.id);
|
|
4500
|
+
}
|
|
4501
|
+
if (t.status === "in_progress") {
|
|
4502
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
4503
|
+
" ",
|
|
4504
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4505
|
+
num,
|
|
4506
|
+
"."
|
|
4507
|
+
] }),
|
|
4508
|
+
" ",
|
|
4509
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: "[~]" }),
|
|
4510
|
+
" ",
|
|
4511
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: display })
|
|
4512
|
+
] }, t.id);
|
|
4513
|
+
}
|
|
4514
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
4515
|
+
" ",
|
|
4516
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4517
|
+
num,
|
|
4518
|
+
"."
|
|
4519
|
+
] }),
|
|
4520
|
+
" ",
|
|
4521
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "[ ]" }),
|
|
4522
|
+
" ",
|
|
4523
|
+
display
|
|
4524
|
+
] }, t.id);
|
|
4525
|
+
};
|
|
4526
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
4527
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, marginBottom: 1, children: [
|
|
4528
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "TODOS" }),
|
|
4529
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
4058
4530
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4059
|
-
|
|
4060
|
-
|
|
4531
|
+
done,
|
|
4532
|
+
"/",
|
|
4533
|
+
todos.length,
|
|
4534
|
+
" done"
|
|
4535
|
+
] }),
|
|
4536
|
+
inProgress > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4537
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
4538
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
4539
|
+
"\u231B",
|
|
4540
|
+
inProgress
|
|
4541
|
+
] })
|
|
4542
|
+
] }) : null,
|
|
4543
|
+
pending > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4544
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
4545
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4546
|
+
"\u2610",
|
|
4547
|
+
pending
|
|
4548
|
+
] })
|
|
4549
|
+
] }) : null,
|
|
4550
|
+
done > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4551
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
4552
|
+
/* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
4553
|
+
"\u2713",
|
|
4554
|
+
done
|
|
4555
|
+
] })
|
|
4556
|
+
] }) : null,
|
|
4557
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 F6 / Esc to close" })
|
|
4558
|
+
] }),
|
|
4559
|
+
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 ? (
|
|
4560
|
+
/* Two-column layout: split the list in half, render side-by-side.
|
|
4561
|
+
Pass the absolute position so numbering is continuous across columns. */
|
|
4562
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
4563
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", width: colWidth, children: todos.slice(0, mid).map((t, i) => renderRow3(t, i)) }),
|
|
4564
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", width: colWidth, children: todos.slice(mid).map((t, i) => renderRow3(t, mid + i)) })
|
|
4061
4565
|
] })
|
|
4062
|
-
|
|
4063
|
-
|
|
4566
|
+
) : (
|
|
4567
|
+
/* Single column layout */
|
|
4568
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", children: todos.map(renderRow3) })
|
|
4569
|
+
)
|
|
4064
4570
|
] });
|
|
4065
4571
|
}
|
|
4066
4572
|
var fmtElapsed5 = (ms) => {
|
|
@@ -4395,15 +4901,57 @@ function runGit(cwd, args) {
|
|
|
4395
4901
|
}
|
|
4396
4902
|
});
|
|
4397
4903
|
}
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4904
|
+
function useBrainEvents(events, dispatch) {
|
|
4905
|
+
useEffect(() => {
|
|
4906
|
+
const requestSummary = (request) => `${request.source}: ${request.question}`.slice(0, 80);
|
|
4907
|
+
const addBrainEntry = (status, payload) => {
|
|
4908
|
+
const p = payload;
|
|
4909
|
+
const decision = p.decision.optionId ?? p.decision.text ?? p.decision.reason ?? p.decision.prompt ?? p.decision.type;
|
|
4910
|
+
dispatch({ type: "brainStatus", state: status, source: p.request.source, risk: p.request.risk, summary: decision });
|
|
4911
|
+
if (status === "ask_human") {
|
|
4912
|
+
const prompt = {
|
|
4913
|
+
requestId: p.request.id,
|
|
4914
|
+
source: p.request.source,
|
|
4915
|
+
risk: p.request.risk,
|
|
4916
|
+
question: p.request.question
|
|
4917
|
+
};
|
|
4918
|
+
if (p.request.context !== void 0) prompt.context = p.request.context;
|
|
4919
|
+
if (p.request.options !== void 0) prompt.options = p.request.options;
|
|
4920
|
+
dispatch({ type: "brainPromptSet", prompt });
|
|
4921
|
+
} else {
|
|
4922
|
+
dispatch({ type: "brainPromptClear" });
|
|
4923
|
+
}
|
|
4924
|
+
dispatch({ type: "addEntry", entry: { kind: "brain", status, source: p.request.source, risk: p.request.risk, question: p.request.question, decision, rationale: p.decision.rationale } });
|
|
4925
|
+
};
|
|
4926
|
+
const offRequested = events.on("brain.decision_requested", ({ request }) => {
|
|
4927
|
+
dispatch({ type: "brainStatus", state: "deciding", source: request.source, risk: request.risk, summary: requestSummary(request) });
|
|
4928
|
+
});
|
|
4929
|
+
const offAnswered = events.on("brain.decision_answered", (payload) => addBrainEntry("answered", payload));
|
|
4930
|
+
const offAskHuman = events.on("brain.decision_ask_human", (payload) => addBrainEntry("ask_human", payload));
|
|
4931
|
+
const offDenied = events.on("brain.decision_denied", (payload) => addBrainEntry("denied", payload));
|
|
4932
|
+
return () => {
|
|
4933
|
+
offRequested();
|
|
4934
|
+
offAnswered();
|
|
4935
|
+
offAskHuman();
|
|
4936
|
+
offDenied();
|
|
4937
|
+
};
|
|
4938
|
+
}, [events, dispatch]);
|
|
4939
|
+
}
|
|
4940
|
+
function expectDefined4(value) {
|
|
4941
|
+
if (value === null || value === void 0) {
|
|
4942
|
+
throw new Error("Expected value to be defined");
|
|
4943
|
+
}
|
|
4944
|
+
return value;
|
|
4945
|
+
}
|
|
4946
|
+
var STREAM_COLORS = ["cyan", "magenta", "yellow", "green", "blue"];
|
|
4947
|
+
function labelFor(labelsRef, id, name) {
|
|
4948
|
+
const m = labelsRef.current;
|
|
4949
|
+
const existing = m.get(id);
|
|
4402
4950
|
if (existing) return existing;
|
|
4403
4951
|
const n = m.size + 1;
|
|
4404
4952
|
const v = {
|
|
4405
4953
|
label: name && name !== id ? name : `AGENT#${n}`,
|
|
4406
|
-
color: STREAM_COLORS[(n - 1) % STREAM_COLORS.length]
|
|
4954
|
+
color: expectDefined4(STREAM_COLORS[(n - 1) % STREAM_COLORS.length])
|
|
4407
4955
|
};
|
|
4408
4956
|
m.set(id, v);
|
|
4409
4957
|
return v;
|
|
@@ -4493,34 +5041,6 @@ function useSubagentEvents(events, dispatch, setActiveMaxContext) {
|
|
|
4493
5041
|
};
|
|
4494
5042
|
}, [events, dispatch, setActiveMaxContext, lbl]);
|
|
4495
5043
|
}
|
|
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
5044
|
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
5045
|
function createKillSlashCommand() {
|
|
4526
5046
|
return {
|
|
@@ -4778,6 +5298,12 @@ function buildSteeringPreamble(snapshot, newDirection) {
|
|
|
4778
5298
|
}
|
|
4779
5299
|
|
|
4780
5300
|
// src/app-reducer.ts
|
|
5301
|
+
function expectDefined5(value) {
|
|
5302
|
+
if (value === null || value === void 0) {
|
|
5303
|
+
throw new Error("Expected value to be defined");
|
|
5304
|
+
}
|
|
5305
|
+
return value;
|
|
5306
|
+
}
|
|
4781
5307
|
function reducer(state, action) {
|
|
4782
5308
|
switch (action.type) {
|
|
4783
5309
|
case "addEntry": {
|
|
@@ -4803,7 +5329,22 @@ function reducer(state, action) {
|
|
|
4803
5329
|
queue: [],
|
|
4804
5330
|
nextQueueId: 1,
|
|
4805
5331
|
scrollOffset: 0,
|
|
4806
|
-
pendingNewLines: 0
|
|
5332
|
+
pendingNewLines: 0,
|
|
5333
|
+
// Reset fleet state on /clear so old subagent entries don't
|
|
5334
|
+
// cause the LiveActivityStrip to render stale spacers, and
|
|
5335
|
+
// the fleet cost/tokens chips show zero.
|
|
5336
|
+
fleet: {},
|
|
5337
|
+
fleetCost: 0,
|
|
5338
|
+
fleetTokens: { input: 0, output: 0 },
|
|
5339
|
+
leader: {
|
|
5340
|
+
iterations: 0,
|
|
5341
|
+
toolCalls: 0,
|
|
5342
|
+
recentTools: [],
|
|
5343
|
+
currentTool: void 0,
|
|
5344
|
+
startedAt: Date.now(),
|
|
5345
|
+
lastEventAt: Date.now(),
|
|
5346
|
+
iterating: false
|
|
5347
|
+
}
|
|
4807
5348
|
};
|
|
4808
5349
|
}
|
|
4809
5350
|
case "streamDelta":
|
|
@@ -5084,6 +5625,23 @@ function reducer(state, action) {
|
|
|
5084
5625
|
field: 0,
|
|
5085
5626
|
mode: action.mode,
|
|
5086
5627
|
delayMs: action.delayMs,
|
|
5628
|
+
titleAnimation: action.titleAnimation,
|
|
5629
|
+
yolo: action.yolo,
|
|
5630
|
+
streamFleet: action.streamFleet,
|
|
5631
|
+
chime: action.chime,
|
|
5632
|
+
confirmExit: action.confirmExit,
|
|
5633
|
+
nextPrediction: action.nextPrediction,
|
|
5634
|
+
featureMcp: action.featureMcp,
|
|
5635
|
+
featurePlugins: action.featurePlugins,
|
|
5636
|
+
featureMemory: action.featureMemory,
|
|
5637
|
+
featureSkills: action.featureSkills,
|
|
5638
|
+
featureModelsRegistry: action.featureModelsRegistry,
|
|
5639
|
+
contextAutoCompact: action.contextAutoCompact,
|
|
5640
|
+
contextStrategy: action.contextStrategy,
|
|
5641
|
+
logLevel: action.logLevel,
|
|
5642
|
+
auditLevel: action.auditLevel,
|
|
5643
|
+
indexOnStart: action.indexOnStart,
|
|
5644
|
+
maxIterations: action.maxIterations,
|
|
5087
5645
|
hint: void 0
|
|
5088
5646
|
}
|
|
5089
5647
|
};
|
|
@@ -5093,37 +5651,68 @@ function reducer(state, action) {
|
|
|
5093
5651
|
settingsPicker: { ...state.settingsPicker, open: false, hint: void 0 }
|
|
5094
5652
|
};
|
|
5095
5653
|
case "settingsFieldMove": {
|
|
5096
|
-
const next = (state.settingsPicker.field + action.delta +
|
|
5654
|
+
const next = (state.settingsPicker.field + action.delta + SETTINGS_FIELD_COUNT) % SETTINGS_FIELD_COUNT;
|
|
5097
5655
|
return {
|
|
5098
5656
|
...state,
|
|
5099
5657
|
settingsPicker: { ...state.settingsPicker, field: next, hint: void 0 }
|
|
5100
5658
|
};
|
|
5101
5659
|
}
|
|
5102
5660
|
case "settingsFieldSet": {
|
|
5103
|
-
const field = action.field
|
|
5661
|
+
const field = action.field >= 0 && action.field < SETTINGS_FIELD_COUNT ? action.field : 0;
|
|
5104
5662
|
return { ...state, settingsPicker: { ...state.settingsPicker, field, hint: void 0 } };
|
|
5105
5663
|
}
|
|
5106
5664
|
case "settingsValueChange": {
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
const
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5665
|
+
const sp = state.settingsPicker;
|
|
5666
|
+
const f = sp.field;
|
|
5667
|
+
if (f === 0) {
|
|
5668
|
+
const i = SETTINGS_MODES.indexOf(sp.mode);
|
|
5669
|
+
const base = i < 0 ? 0 : i;
|
|
5670
|
+
const next = (base + action.delta + SETTINGS_MODES.length) % SETTINGS_MODES.length;
|
|
5671
|
+
return { ...state, settingsPicker: { ...sp, mode: expectDefined5(SETTINGS_MODES[next]), hint: void 0 } };
|
|
5672
|
+
}
|
|
5673
|
+
if (f === 1) {
|
|
5674
|
+
const j = DELAY_PRESETS_MS.indexOf(sp.delayMs);
|
|
5675
|
+
const base = j < 0 ? 0 : j;
|
|
5676
|
+
const next = (base + action.delta + DELAY_PRESETS_MS.length) % DELAY_PRESETS_MS.length;
|
|
5677
|
+
return { ...state, settingsPicker: { ...sp, delayMs: expectDefined5(DELAY_PRESETS_MS[next]), hint: void 0 } };
|
|
5678
|
+
}
|
|
5679
|
+
if (f === 2) return { ...state, settingsPicker: { ...sp, titleAnimation: !sp.titleAnimation, hint: void 0 } };
|
|
5680
|
+
if (f === 3) return { ...state, settingsPicker: { ...sp, yolo: !sp.yolo, hint: void 0 } };
|
|
5681
|
+
if (f === 4) return { ...state, settingsPicker: { ...sp, streamFleet: !sp.streamFleet, hint: void 0 } };
|
|
5682
|
+
if (f === 5) return { ...state, settingsPicker: { ...sp, chime: !sp.chime, hint: void 0 } };
|
|
5683
|
+
if (f === 6) return { ...state, settingsPicker: { ...sp, confirmExit: !sp.confirmExit, hint: void 0 } };
|
|
5684
|
+
if (f === 7) return { ...state, settingsPicker: { ...sp, nextPrediction: !sp.nextPrediction, hint: void 0 } };
|
|
5685
|
+
if (f === 8) return { ...state, settingsPicker: { ...sp, featureMcp: !sp.featureMcp, hint: void 0 } };
|
|
5686
|
+
if (f === 9) return { ...state, settingsPicker: { ...sp, featurePlugins: !sp.featurePlugins, hint: void 0 } };
|
|
5687
|
+
if (f === 10) return { ...state, settingsPicker: { ...sp, featureMemory: !sp.featureMemory, hint: void 0 } };
|
|
5688
|
+
if (f === 11) return { ...state, settingsPicker: { ...sp, featureSkills: !sp.featureSkills, hint: void 0 } };
|
|
5689
|
+
if (f === 12) return { ...state, settingsPicker: { ...sp, featureModelsRegistry: !sp.featureModelsRegistry, hint: void 0 } };
|
|
5690
|
+
if (f === 13) return { ...state, settingsPicker: { ...sp, contextAutoCompact: !sp.contextAutoCompact, hint: void 0 } };
|
|
5691
|
+
if (f === 14) {
|
|
5692
|
+
const i = COMPACTOR_STRATEGIES.indexOf(sp.contextStrategy);
|
|
5693
|
+
const base = i < 0 ? 0 : i;
|
|
5694
|
+
const next = (base + action.delta + COMPACTOR_STRATEGIES.length) % COMPACTOR_STRATEGIES.length;
|
|
5695
|
+
return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined5(COMPACTOR_STRATEGIES[next]), hint: void 0 } };
|
|
5696
|
+
}
|
|
5697
|
+
if (f === 15) {
|
|
5698
|
+
const i = LOG_LEVELS.indexOf(sp.logLevel);
|
|
5699
|
+
const base = i < 0 ? 0 : i;
|
|
5700
|
+
const next = (base + action.delta + LOG_LEVELS.length) % LOG_LEVELS.length;
|
|
5701
|
+
return { ...state, settingsPicker: { ...sp, logLevel: expectDefined5(LOG_LEVELS[next]), hint: void 0 } };
|
|
5702
|
+
}
|
|
5703
|
+
if (f === 16) {
|
|
5704
|
+
const i = AUDIT_LEVELS.indexOf(sp.auditLevel);
|
|
5705
|
+
const base = i < 0 ? 0 : i;
|
|
5706
|
+
const next = (base + action.delta + AUDIT_LEVELS.length) % AUDIT_LEVELS.length;
|
|
5707
|
+
return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined5(AUDIT_LEVELS[next]), hint: void 0 } };
|
|
5708
|
+
}
|
|
5709
|
+
if (f === 17) return { ...state, settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: void 0 } };
|
|
5710
|
+
{
|
|
5711
|
+
const j = MAX_ITERATIONS_PRESETS.indexOf(sp.maxIterations);
|
|
5712
|
+
const base = j < 0 ? 0 : j;
|
|
5713
|
+
const next = (base + action.delta + MAX_ITERATIONS_PRESETS.length) % MAX_ITERATIONS_PRESETS.length;
|
|
5714
|
+
return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined5(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
|
|
5115
5715
|
}
|
|
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
5716
|
}
|
|
5128
5717
|
case "settingsHint":
|
|
5129
5718
|
return { ...state, settingsPicker: { ...state.settingsPicker, hint: action.text } };
|
|
@@ -5131,6 +5720,14 @@ function reducer(state, action) {
|
|
|
5131
5720
|
return { ...state, confirmQueue: [...state.confirmQueue, action.info] };
|
|
5132
5721
|
case "confirmClose":
|
|
5133
5722
|
return { ...state, confirmQueue: state.confirmQueue.slice(1) };
|
|
5723
|
+
case "enhanceOpen":
|
|
5724
|
+
return { ...state, enhance: action.info };
|
|
5725
|
+
case "enhanceClose":
|
|
5726
|
+
return { ...state, enhance: null };
|
|
5727
|
+
case "enhanceSet":
|
|
5728
|
+
return { ...state, enhanceEnabled: action.enabled };
|
|
5729
|
+
case "enhanceBusy":
|
|
5730
|
+
return { ...state, enhanceBusy: action.on };
|
|
5134
5731
|
case "resetContextChip":
|
|
5135
5732
|
return { ...state, contextChipVersion: state.contextChipVersion + 1 };
|
|
5136
5733
|
// --- Fleet ---
|
|
@@ -5362,8 +5959,24 @@ function reducer(state, action) {
|
|
|
5362
5959
|
};
|
|
5363
5960
|
}
|
|
5364
5961
|
case "fleetCost": {
|
|
5962
|
+
let fleet = state.fleet;
|
|
5963
|
+
if (action.perAgent) {
|
|
5964
|
+
let changed = false;
|
|
5965
|
+
const next = {};
|
|
5966
|
+
for (const [id, entry] of Object.entries(state.fleet)) {
|
|
5967
|
+
const cost = action.perAgent[id]?.cost;
|
|
5968
|
+
if (cost !== void 0 && cost !== entry.cost) {
|
|
5969
|
+
next[id] = { ...entry, cost };
|
|
5970
|
+
changed = true;
|
|
5971
|
+
} else {
|
|
5972
|
+
next[id] = entry;
|
|
5973
|
+
}
|
|
5974
|
+
}
|
|
5975
|
+
if (changed) fleet = next;
|
|
5976
|
+
}
|
|
5365
5977
|
return {
|
|
5366
5978
|
...state,
|
|
5979
|
+
fleet,
|
|
5367
5980
|
fleetCost: action.cost,
|
|
5368
5981
|
fleetTokens: action.input !== void 0 || action.output !== void 0 ? {
|
|
5369
5982
|
input: action.input ?? state.fleetTokens.input,
|
|
@@ -5442,6 +6055,12 @@ function reducer(state, action) {
|
|
|
5442
6055
|
case "toggleHelp": {
|
|
5443
6056
|
return { ...state, helpOpen: !state.helpOpen };
|
|
5444
6057
|
}
|
|
6058
|
+
case "toggleTodosMonitor": {
|
|
6059
|
+
return { ...state, todosMonitorOpen: !state.todosMonitorOpen };
|
|
6060
|
+
}
|
|
6061
|
+
case "toggleQueuePanel": {
|
|
6062
|
+
return { ...state, queuePanelOpen: !state.queuePanelOpen };
|
|
6063
|
+
}
|
|
5445
6064
|
case "checkpointReceived": {
|
|
5446
6065
|
const existing = state.checkpoints.find((c) => c.promptIndex === action.cp.promptIndex);
|
|
5447
6066
|
if (existing) return state;
|
|
@@ -5740,13 +6359,34 @@ function reducer(state, action) {
|
|
|
5740
6359
|
}
|
|
5741
6360
|
}
|
|
5742
6361
|
}
|
|
5743
|
-
|
|
6362
|
+
function expectDefined6(value) {
|
|
6363
|
+
if (value === null || value === void 0) {
|
|
6364
|
+
throw new Error("Expected value to be defined");
|
|
6365
|
+
}
|
|
6366
|
+
return value;
|
|
6367
|
+
}
|
|
5744
6368
|
var INPUT_PROMPT = "\u203A ";
|
|
5745
6369
|
function selectedSlashCommandLine(picker) {
|
|
5746
6370
|
if (!picker.open || picker.matches.length === 0) return null;
|
|
5747
6371
|
const picked = picker.matches[picker.selected];
|
|
5748
6372
|
return picked ? `/${picked.name}` : null;
|
|
5749
6373
|
}
|
|
6374
|
+
function rehydrateHistory(messages, startId) {
|
|
6375
|
+
const entries = [];
|
|
6376
|
+
let nextId = startId;
|
|
6377
|
+
for (const msg of messages) {
|
|
6378
|
+
if (msg.role === "system") continue;
|
|
6379
|
+
const text = typeof msg.content === "string" ? msg.content : msg.content.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
6380
|
+
const trimmed = text.trim();
|
|
6381
|
+
if (!trimmed) continue;
|
|
6382
|
+
if (msg.role === "user") {
|
|
6383
|
+
entries.push({ id: nextId++, kind: "user", text: trimmed });
|
|
6384
|
+
} else if (msg.role === "assistant") {
|
|
6385
|
+
entries.push({ id: nextId++, kind: "assistant", text: trimmed });
|
|
6386
|
+
}
|
|
6387
|
+
}
|
|
6388
|
+
return entries;
|
|
6389
|
+
}
|
|
5750
6390
|
var PASTE_THRESHOLD_CHARS = 200;
|
|
5751
6391
|
function App({
|
|
5752
6392
|
agent,
|
|
@@ -5760,6 +6400,11 @@ function App({
|
|
|
5760
6400
|
banner = true,
|
|
5761
6401
|
queueStore,
|
|
5762
6402
|
yolo = false,
|
|
6403
|
+
chime = false,
|
|
6404
|
+
confirmExit = true,
|
|
6405
|
+
enhanceEnabled = true,
|
|
6406
|
+
enhanceController,
|
|
6407
|
+
enhanceDelayMs = 4e3,
|
|
5763
6408
|
getYolo,
|
|
5764
6409
|
getAutonomy,
|
|
5765
6410
|
getEternalEngine,
|
|
@@ -5791,7 +6436,8 @@ function App({
|
|
|
5791
6436
|
initialGoal,
|
|
5792
6437
|
initialAsk,
|
|
5793
6438
|
sessionsDir,
|
|
5794
|
-
|
|
6439
|
+
modeLabel,
|
|
6440
|
+
getModeLabel
|
|
5795
6441
|
}) {
|
|
5796
6442
|
const { exit } = useApp();
|
|
5797
6443
|
const [liveModel, setLiveModel] = useState(model);
|
|
@@ -5799,19 +6445,13 @@ function App({
|
|
|
5799
6445
|
const [activeMaxContext, setActiveMaxContext] = useState(effectiveMaxContext);
|
|
5800
6446
|
const [yoloLive, setYoloLive] = useState(yolo);
|
|
5801
6447
|
const [autonomyLive, setAutonomyLive] = useState(getAutonomy?.() ?? "off");
|
|
6448
|
+
const [liveModeLabel, setLiveModeLabel] = useState(modeLabel ?? "");
|
|
5802
6449
|
const [hiddenItems, setHiddenItems] = useState(statuslineHiddenItems);
|
|
5803
|
-
const
|
|
5804
|
-
const [termRows, setTermRows] = useState(stdout?.rows ?? 24);
|
|
6450
|
+
const [indexState, setIndexState] = useState(() => getIndexState());
|
|
5805
6451
|
useEffect(() => {
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
};
|
|
5809
|
-
process.stdout.on("resize", onResize);
|
|
5810
|
-
return () => {
|
|
5811
|
-
process.stdout.off("resize", onResize);
|
|
5812
|
-
};
|
|
6452
|
+
setIndexState(getIndexState());
|
|
6453
|
+
return onIndexStateChange((next) => setIndexState(next));
|
|
5813
6454
|
}, []);
|
|
5814
|
-
const [managedLive, setManagedLive] = useState(managed);
|
|
5815
6455
|
useEffect(() => {
|
|
5816
6456
|
setHiddenItems(statuslineHiddenItems);
|
|
5817
6457
|
}, [statuslineHiddenItems]);
|
|
@@ -5840,19 +6480,34 @@ function App({
|
|
|
5840
6480
|
}).catch(() => {
|
|
5841
6481
|
});
|
|
5842
6482
|
}, [projectRoot]);
|
|
6483
|
+
const restoredEntries = (() => {
|
|
6484
|
+
const msgs = agent.ctx.messages;
|
|
6485
|
+
if (!msgs || msgs.length === 0) return [];
|
|
6486
|
+
const visible = msgs.filter((m) => m.role !== "system");
|
|
6487
|
+
if (visible.length === 0) return [];
|
|
6488
|
+
return rehydrateHistory(
|
|
6489
|
+
visible,
|
|
6490
|
+
/* startId */
|
|
6491
|
+
1
|
|
6492
|
+
);
|
|
6493
|
+
})();
|
|
6494
|
+
const initialNextId = 1 + restoredEntries.length;
|
|
5843
6495
|
const [state, dispatch] = useReducer(reducer, {
|
|
5844
|
-
entries:
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
6496
|
+
entries: [
|
|
6497
|
+
...banner ? [
|
|
6498
|
+
{
|
|
6499
|
+
id: 0,
|
|
6500
|
+
kind: "banner",
|
|
6501
|
+
version: appVersion ?? "dev",
|
|
6502
|
+
provider: provider ?? "agent",
|
|
6503
|
+
model,
|
|
6504
|
+
cwd: agent.ctx.cwd,
|
|
6505
|
+
family,
|
|
6506
|
+
keyTail
|
|
6507
|
+
}
|
|
6508
|
+
] : [],
|
|
6509
|
+
...restoredEntries
|
|
6510
|
+
],
|
|
5856
6511
|
buffer: "",
|
|
5857
6512
|
cursor: 0,
|
|
5858
6513
|
streamingText: "",
|
|
@@ -5864,7 +6519,7 @@ function App({
|
|
|
5864
6519
|
hint: "",
|
|
5865
6520
|
brain: { state: "idle" },
|
|
5866
6521
|
brainPrompt: null,
|
|
5867
|
-
nextId:
|
|
6522
|
+
nextId: initialNextId,
|
|
5868
6523
|
picker: { open: false, query: "", matches: [], selected: 0 },
|
|
5869
6524
|
slashPicker: { open: false, query: "", matches: [], selected: 0 },
|
|
5870
6525
|
runningTools: /* @__PURE__ */ new Map(),
|
|
@@ -5882,8 +6537,11 @@ function App({
|
|
|
5882
6537
|
searchQuery: ""
|
|
5883
6538
|
},
|
|
5884
6539
|
autonomyPicker: { open: false, options: [], selected: 0 },
|
|
5885
|
-
settingsPicker: { open: false, field: 0, mode: "off", delayMs: 0 },
|
|
6540
|
+
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
6541
|
confirmQueue: [],
|
|
6542
|
+
enhance: null,
|
|
6543
|
+
enhanceEnabled,
|
|
6544
|
+
enhanceBusy: false,
|
|
5887
6545
|
contextChipVersion: 0,
|
|
5888
6546
|
fleet: {},
|
|
5889
6547
|
leader: {
|
|
@@ -5902,6 +6560,8 @@ function App({
|
|
|
5902
6560
|
monitorOpen: false,
|
|
5903
6561
|
agentsMonitorOpen: false,
|
|
5904
6562
|
helpOpen: false,
|
|
6563
|
+
todosMonitorOpen: false,
|
|
6564
|
+
queuePanelOpen: false,
|
|
5905
6565
|
collabSession: null,
|
|
5906
6566
|
checkpoints: [],
|
|
5907
6567
|
rewindOverlay: null,
|
|
@@ -5926,10 +6586,14 @@ function App({
|
|
|
5926
6586
|
const inputGateRef = useRef(false);
|
|
5927
6587
|
const lastEnterAtRef = useRef(0);
|
|
5928
6588
|
const tokenPreviewsRef = useRef(/* @__PURE__ */ new Map());
|
|
5929
|
-
const projectName =
|
|
6589
|
+
const projectName = React6.useMemo(() => {
|
|
5930
6590
|
const base = path2.basename(projectRoot);
|
|
5931
6591
|
return base && base !== path2.sep ? base : void 0;
|
|
5932
6592
|
}, [projectRoot]);
|
|
6593
|
+
const chimeRef = useRef(chime);
|
|
6594
|
+
chimeRef.current = chime;
|
|
6595
|
+
const confirmExitRef = useRef(confirmExit);
|
|
6596
|
+
confirmExitRef.current = confirmExit;
|
|
5933
6597
|
const streamingTextRef = useRef("");
|
|
5934
6598
|
const pendingDeltaRef = useRef("");
|
|
5935
6599
|
const flushTimerRef = useRef(null);
|
|
@@ -5937,21 +6601,8 @@ function App({
|
|
|
5937
6601
|
stateRef.current = state;
|
|
5938
6602
|
const draftRef = useRef({ buffer: state.buffer, cursor: state.cursor });
|
|
5939
6603
|
draftRef.current = { buffer: state.buffer, cursor: state.cursor };
|
|
5940
|
-
const bottomRef = useRef(null);
|
|
5941
|
-
React5.useLayoutEffect(() => {
|
|
5942
|
-
if (!managedLive) return;
|
|
5943
|
-
const node = bottomRef.current;
|
|
5944
|
-
if (!node) return;
|
|
5945
|
-
const { height } = measureElement(node);
|
|
5946
|
-
const s2 = stateRef.current;
|
|
5947
|
-
const affordance = s2.scrollOffset > 0 && s2.pendingNewLines > 0 ? 1 : 0;
|
|
5948
|
-
const vp = Math.max(MIN_VIEWPORT, termRows - height - affordance - 1);
|
|
5949
|
-
if (vp !== s2.viewportRows) {
|
|
5950
|
-
dispatch({ type: "setViewportRows", rows: vp });
|
|
5951
|
-
}
|
|
5952
|
-
}, [managedLive, termRows]);
|
|
5953
6604
|
const handleKeyRef = useRef(null);
|
|
5954
|
-
const handleRewindTo =
|
|
6605
|
+
const handleRewindTo = React6.useCallback(
|
|
5955
6606
|
async (checkpointIndex) => {
|
|
5956
6607
|
const sessionId = agent.ctx.session.id;
|
|
5957
6608
|
if (!sessionId) return;
|
|
@@ -5970,13 +6621,24 @@ function App({
|
|
|
5970
6621
|
dispatch({ type: "clearInput" });
|
|
5971
6622
|
};
|
|
5972
6623
|
const startedAtRef = useRef(Date.now());
|
|
5973
|
-
const [nowTick, setNowTick] =
|
|
6624
|
+
const [nowTick, setNowTick] = React6.useState(Date.now());
|
|
5974
6625
|
useEffect(() => {
|
|
5975
|
-
const t = setInterval(() => setNowTick(Date.now()),
|
|
6626
|
+
const t = setInterval(() => setNowTick(Date.now()), 1e4);
|
|
5976
6627
|
return () => clearInterval(t);
|
|
5977
6628
|
}, []);
|
|
5978
|
-
const
|
|
5979
|
-
|
|
6629
|
+
const todosRef = useRef(JSON.stringify([]));
|
|
6630
|
+
useEffect(() => {
|
|
6631
|
+
const poll = () => {
|
|
6632
|
+
const snap = JSON.stringify(agent.ctx.todos.map((t2) => ({ s: t2.status })));
|
|
6633
|
+
if (snap !== todosRef.current) {
|
|
6634
|
+
todosRef.current = snap;
|
|
6635
|
+
setNowTick(Date.now());
|
|
6636
|
+
}
|
|
6637
|
+
};
|
|
6638
|
+
const t = setInterval(poll, 2e3);
|
|
6639
|
+
return () => clearInterval(t);
|
|
6640
|
+
}, [agent.ctx.todos]);
|
|
6641
|
+
const [gitInfo, setGitInfo] = React6.useState(null);
|
|
5980
6642
|
useEffect(() => {
|
|
5981
6643
|
let cancelled = false;
|
|
5982
6644
|
const refresh = () => {
|
|
@@ -6031,7 +6693,10 @@ function App({
|
|
|
6031
6693
|
toolCalls: state.leader.toolCalls,
|
|
6032
6694
|
recentTools: state.leader.recentTools,
|
|
6033
6695
|
recentMessages: [],
|
|
6034
|
-
cost
|
|
6696
|
+
// Leader (main session) cost — the same number the statusline shows.
|
|
6697
|
+
// Kept distinct from fleet (subagent) cost so the monitor can show a
|
|
6698
|
+
// trustworthy grand total = leader + fleet.
|
|
6699
|
+
cost: tokenCounter?.estimateCost().total ?? 0,
|
|
6035
6700
|
startedAt: state.leader.startedAt,
|
|
6036
6701
|
lastEventAt: state.leader.lastEventAt,
|
|
6037
6702
|
currentTool: state.leader.currentTool,
|
|
@@ -6040,7 +6705,7 @@ function App({
|
|
|
6040
6705
|
ctxMaxTokens: state.leader.ctxMaxTokens ?? effectiveMaxContext
|
|
6041
6706
|
};
|
|
6042
6707
|
return { leader: leaderEntry, ...state.fleet };
|
|
6043
|
-
}, [state.fleet, state.leader, state.status, provider, model, effectiveMaxContext]);
|
|
6708
|
+
}, [state.fleet, state.leader, state.status, provider, model, effectiveMaxContext, tokenCounter]);
|
|
6044
6709
|
const STREAM_COLORS2 = ["cyan", "magenta", "yellow", "green", "blue"];
|
|
6045
6710
|
const labelsRef = useRef(/* @__PURE__ */ new Map());
|
|
6046
6711
|
const labelFor2 = (id, name) => {
|
|
@@ -6050,7 +6715,7 @@ function App({
|
|
|
6050
6715
|
const n = m.size + 1;
|
|
6051
6716
|
const v = {
|
|
6052
6717
|
label: name && name !== id ? name : `AGENT#${n}`,
|
|
6053
|
-
color: STREAM_COLORS2[(n - 1) % STREAM_COLORS2.length]
|
|
6718
|
+
color: STREAM_COLORS2[(n - 1) % STREAM_COLORS2.length] ?? "cyan"
|
|
6054
6719
|
};
|
|
6055
6720
|
m.set(id, v);
|
|
6056
6721
|
return v;
|
|
@@ -6091,19 +6756,23 @@ function App({
|
|
|
6091
6756
|
}, [agent.ctx.meta]);
|
|
6092
6757
|
const prevAnyOverlayOpen = useRef(false);
|
|
6093
6758
|
const prevEntriesCount = useRef(0);
|
|
6759
|
+
const prevToolStreamLen = useRef(0);
|
|
6094
6760
|
const eraseLiveRegion = useCallback(() => {
|
|
6095
6761
|
try {
|
|
6096
6762
|
writeOut("\x1B[J");
|
|
6097
6763
|
} catch {
|
|
6098
6764
|
}
|
|
6099
6765
|
}, []);
|
|
6100
|
-
|
|
6101
|
-
const anyOpenNow = state.picker.open || state.slashPicker.open || state.modelPicker.open || state.autonomyPicker.open || state.settingsPicker.open || state.confirmQueue.length > 0;
|
|
6766
|
+
React6.useLayoutEffect(() => {
|
|
6767
|
+
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
6768
|
const overlayClosed = prevAnyOverlayOpen.current && !anyOpenNow;
|
|
6103
6769
|
const newEntryCommitted = state.entries.length > prevEntriesCount.current;
|
|
6770
|
+
const curToolStreamLen = state.toolStream?.text.length ?? 0;
|
|
6771
|
+
const toolStreamGrew = curToolStreamLen > 0 && curToolStreamLen > prevToolStreamLen.current;
|
|
6104
6772
|
prevAnyOverlayOpen.current = anyOpenNow;
|
|
6105
6773
|
prevEntriesCount.current = state.entries.length;
|
|
6106
|
-
|
|
6774
|
+
prevToolStreamLen.current = curToolStreamLen;
|
|
6775
|
+
if (overlayClosed || newEntryCommitted || toolStreamGrew) {
|
|
6107
6776
|
eraseLiveRegion();
|
|
6108
6777
|
}
|
|
6109
6778
|
}, [
|
|
@@ -6112,8 +6781,11 @@ function App({
|
|
|
6112
6781
|
state.modelPicker.open,
|
|
6113
6782
|
state.autonomyPicker.open,
|
|
6114
6783
|
state.settingsPicker.open,
|
|
6784
|
+
state.enhanceBusy,
|
|
6785
|
+
state.enhance,
|
|
6115
6786
|
state.confirmQueue.length,
|
|
6116
6787
|
state.entries.length,
|
|
6788
|
+
state.toolStream?.text,
|
|
6117
6789
|
eraseLiveRegion
|
|
6118
6790
|
]);
|
|
6119
6791
|
useEffect(() => {
|
|
@@ -6123,6 +6795,9 @@ function App({
|
|
|
6123
6795
|
process.stdout.off("resize", handleResize);
|
|
6124
6796
|
};
|
|
6125
6797
|
}, [eraseLiveRegion]);
|
|
6798
|
+
React6.useLayoutEffect(() => {
|
|
6799
|
+
if (state.enhanceBusy || state.enhance != null) eraseLiveRegion();
|
|
6800
|
+
}, [state.enhanceBusy, state.enhance, eraseLiveRegion]);
|
|
6126
6801
|
useEffect(() => {
|
|
6127
6802
|
const detected = detectAtToken(state.buffer, state.cursor);
|
|
6128
6803
|
if (!detected) {
|
|
@@ -6154,16 +6829,22 @@ function App({
|
|
|
6154
6829
|
}
|
|
6155
6830
|
const query = trimmed.slice(1).toLowerCase();
|
|
6156
6831
|
const allCommands = slashRegistry.listWithOwner();
|
|
6832
|
+
const CATEGORY_ORDER = ["Run", "Session", "Inspect", "Agent", "Config", "App"];
|
|
6157
6833
|
const matches = allCommands.filter(({ cmd }) => {
|
|
6158
6834
|
const name = cmd.name.toLowerCase();
|
|
6159
6835
|
const aliases = cmd.aliases ?? [];
|
|
6160
6836
|
return name.includes(query) || aliases.some((a) => a.toLowerCase().includes(query));
|
|
6161
|
-
}).
|
|
6837
|
+
}).map(({ cmd, owner }) => ({
|
|
6162
6838
|
name: cmd.name,
|
|
6163
6839
|
description: cmd.description,
|
|
6164
6840
|
argsHint: cmd.argsHint,
|
|
6165
|
-
isBuiltin: owner === "core"
|
|
6166
|
-
|
|
6841
|
+
isBuiltin: owner === "core",
|
|
6842
|
+
category: cmd.category ?? "App"
|
|
6843
|
+
})).sort((a, b) => {
|
|
6844
|
+
const catDiff = CATEGORY_ORDER.indexOf(a.category) - CATEGORY_ORDER.indexOf(b.category);
|
|
6845
|
+
if (catDiff !== 0) return catDiff;
|
|
6846
|
+
return a.name.localeCompare(b.name);
|
|
6847
|
+
});
|
|
6167
6848
|
if (!state.slashPicker.open) {
|
|
6168
6849
|
dispatch({ type: "slashPickerOpen", query, matches });
|
|
6169
6850
|
} else if (state.slashPicker.query !== query) {
|
|
@@ -6295,44 +6976,6 @@ function App({
|
|
|
6295
6976
|
getProcessRegistry().killAll();
|
|
6296
6977
|
};
|
|
6297
6978
|
}, []);
|
|
6298
|
-
useEffect(() => {
|
|
6299
|
-
const ALT_OFF = "\x1B[?1049l";
|
|
6300
|
-
const ALT_ON = "\x1B[?1049h";
|
|
6301
|
-
const cmd = {
|
|
6302
|
-
name: "altscreen",
|
|
6303
|
-
description: "Toggle the alt-screen buffer. Default is OFF (native scroll); /altscreen on for full-screen mode.",
|
|
6304
|
-
async run(args) {
|
|
6305
|
-
const arg = args.trim().toLowerCase();
|
|
6306
|
-
if (arg === "off") {
|
|
6307
|
-
try {
|
|
6308
|
-
writeOut(ALT_OFF);
|
|
6309
|
-
} catch {
|
|
6310
|
-
return { message: "Failed to exit alt-screen." };
|
|
6311
|
-
}
|
|
6312
|
-
setManagedLive(false);
|
|
6313
|
-
return {
|
|
6314
|
-
message: "Alt-screen disabled. New entries will land in normal scrollback (mouse wheel / Shift+PgUp work). On-screen history rendered before this command is no longer reachable via terminal scroll. Resize may now leak the live region \u2014 `/altscreen on` to re-enable."
|
|
6315
|
-
};
|
|
6316
|
-
}
|
|
6317
|
-
if (arg === "on") {
|
|
6318
|
-
try {
|
|
6319
|
-
writeOut(ALT_ON);
|
|
6320
|
-
} catch {
|
|
6321
|
-
return { message: "Failed to re-enter alt-screen." };
|
|
6322
|
-
}
|
|
6323
|
-
setManagedLive(true);
|
|
6324
|
-
return {
|
|
6325
|
-
message: "Alt-screen re-enabled. Managed scroll (PgUp/PgDn) is now active; native scroll is off."
|
|
6326
|
-
};
|
|
6327
|
-
}
|
|
6328
|
-
return { message: "Usage: /altscreen on|off" };
|
|
6329
|
-
}
|
|
6330
|
-
};
|
|
6331
|
-
slashRegistry.register(cmd);
|
|
6332
|
-
return () => {
|
|
6333
|
-
slashRegistry.unregister("altscreen");
|
|
6334
|
-
};
|
|
6335
|
-
}, [slashRegistry]);
|
|
6336
6979
|
useEffect(() => {
|
|
6337
6980
|
const cmd = {
|
|
6338
6981
|
name: "steer",
|
|
@@ -6439,15 +7082,36 @@ function App({
|
|
|
6439
7082
|
slashRegistry.unregister("agents");
|
|
6440
7083
|
};
|
|
6441
7084
|
}, [slashRegistry]);
|
|
6442
|
-
const openModelPicker =
|
|
7085
|
+
const openModelPicker = React6.useCallback(async () => {
|
|
6443
7086
|
if (!getPickableProviders) return;
|
|
6444
7087
|
const providers = await getPickableProviders();
|
|
6445
7088
|
dispatch({ type: "modelPickerOpen", providers });
|
|
6446
7089
|
}, [getPickableProviders]);
|
|
6447
|
-
const openSettings =
|
|
7090
|
+
const openSettings = React6.useCallback(() => {
|
|
6448
7091
|
if (!getSettings) return;
|
|
6449
7092
|
const s2 = getSettings();
|
|
6450
|
-
dispatch({
|
|
7093
|
+
dispatch({
|
|
7094
|
+
type: "settingsOpen",
|
|
7095
|
+
mode: s2.mode,
|
|
7096
|
+
delayMs: s2.delayMs,
|
|
7097
|
+
titleAnimation: s2.titleAnimation ?? true,
|
|
7098
|
+
yolo: s2.yolo ?? false,
|
|
7099
|
+
streamFleet: s2.streamFleet ?? true,
|
|
7100
|
+
chime: s2.chime ?? false,
|
|
7101
|
+
confirmExit: s2.confirmExit ?? true,
|
|
7102
|
+
nextPrediction: s2.nextPrediction ?? false,
|
|
7103
|
+
featureMcp: s2.featureMcp ?? true,
|
|
7104
|
+
featurePlugins: s2.featurePlugins ?? true,
|
|
7105
|
+
featureMemory: s2.featureMemory ?? true,
|
|
7106
|
+
featureSkills: s2.featureSkills ?? true,
|
|
7107
|
+
featureModelsRegistry: s2.featureModelsRegistry ?? true,
|
|
7108
|
+
contextAutoCompact: s2.contextAutoCompact ?? true,
|
|
7109
|
+
contextStrategy: s2.contextStrategy ?? "hybrid",
|
|
7110
|
+
logLevel: s2.logLevel ?? "info",
|
|
7111
|
+
auditLevel: s2.auditLevel ?? "standard",
|
|
7112
|
+
indexOnStart: s2.indexOnStart ?? true,
|
|
7113
|
+
maxIterations: s2.maxIterations ?? 500
|
|
7114
|
+
});
|
|
6451
7115
|
}, [getSettings]);
|
|
6452
7116
|
useEffect(() => {
|
|
6453
7117
|
if (!getPickableProviders || !switchProviderAndModel) return;
|
|
@@ -6460,7 +7124,7 @@ function App({
|
|
|
6460
7124
|
return { message: void 0 };
|
|
6461
7125
|
}
|
|
6462
7126
|
};
|
|
6463
|
-
slashRegistry.register(cmd);
|
|
7127
|
+
slashRegistry.register(cmd, "tui", { official: true });
|
|
6464
7128
|
return () => {
|
|
6465
7129
|
slashRegistry.unregister("model");
|
|
6466
7130
|
};
|
|
@@ -6470,13 +7134,13 @@ function App({
|
|
|
6470
7134
|
const cmd = {
|
|
6471
7135
|
name: "settings",
|
|
6472
7136
|
aliases: ["config", "prefs"],
|
|
6473
|
-
description: "
|
|
7137
|
+
description: "Open the interactive settings editor (19 config fields across 8 sections).",
|
|
6474
7138
|
async run() {
|
|
6475
7139
|
openSettings();
|
|
6476
7140
|
return { message: void 0 };
|
|
6477
7141
|
}
|
|
6478
7142
|
};
|
|
6479
|
-
slashRegistry.register(cmd);
|
|
7143
|
+
slashRegistry.register(cmd, "tui", { official: true });
|
|
6480
7144
|
return () => {
|
|
6481
7145
|
slashRegistry.unregister("settings");
|
|
6482
7146
|
};
|
|
@@ -6492,7 +7156,7 @@ function App({
|
|
|
6492
7156
|
return { message: void 0 };
|
|
6493
7157
|
}
|
|
6494
7158
|
};
|
|
6495
|
-
slashRegistry.register(cmd);
|
|
7159
|
+
slashRegistry.register(cmd, "tui", { official: true });
|
|
6496
7160
|
return () => {
|
|
6497
7161
|
slashRegistry.unregister("autonomy");
|
|
6498
7162
|
};
|
|
@@ -6533,23 +7197,25 @@ function App({
|
|
|
6533
7197
|
});
|
|
6534
7198
|
});
|
|
6535
7199
|
const offTool = events.on("tool.executed", (e) => {
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
7200
|
+
if (e.name !== "delegate") {
|
|
7201
|
+
dispatch({
|
|
7202
|
+
type: "addEntry",
|
|
7203
|
+
entry: {
|
|
7204
|
+
kind: "tool",
|
|
7205
|
+
name: e.name,
|
|
7206
|
+
durationMs: e.durationMs,
|
|
7207
|
+
ok: e.ok,
|
|
7208
|
+
input: e.input,
|
|
7209
|
+
output: e.output,
|
|
7210
|
+
// Real model-visible sizes — forwarded so the size chip beside
|
|
7211
|
+
// the tool header can show what the model paid for instead of
|
|
7212
|
+
// the misleading preview-byte count we used to surface.
|
|
7213
|
+
outputBytes: e.outputBytes,
|
|
7214
|
+
outputTokens: e.outputTokens,
|
|
7215
|
+
outputLines: e.outputLines
|
|
7216
|
+
}
|
|
7217
|
+
});
|
|
7218
|
+
}
|
|
6553
7219
|
dispatch({ type: "toolEnded", name: e.name });
|
|
6554
7220
|
dispatch({ type: "toolStreamClear", name: e.name });
|
|
6555
7221
|
dispatch({ type: "leaderToolEnd", name: e.name, ok: e.ok, durationMs: e.durationMs });
|
|
@@ -6609,6 +7275,34 @@ function App({
|
|
|
6609
7275
|
}
|
|
6610
7276
|
});
|
|
6611
7277
|
});
|
|
7278
|
+
const offDelegateStart = events.on("delegate.started", (e) => {
|
|
7279
|
+
const task = e.task.length > 100 ? `${e.task.slice(0, 99)}\u2026` : e.task;
|
|
7280
|
+
dispatch({
|
|
7281
|
+
type: "addEntry",
|
|
7282
|
+
entry: {
|
|
7283
|
+
kind: "subagent",
|
|
7284
|
+
agentLabel: e.target,
|
|
7285
|
+
agentColor: "magenta",
|
|
7286
|
+
icon: "\u{1F91D}",
|
|
7287
|
+
text: "delegating",
|
|
7288
|
+
detail: task
|
|
7289
|
+
}
|
|
7290
|
+
});
|
|
7291
|
+
});
|
|
7292
|
+
const offDelegateDone = events.on("delegate.completed", (e) => {
|
|
7293
|
+
const cost = e.costUsd && e.costUsd > 0 ? `$${e.costUsd.toFixed(3)}` : void 0;
|
|
7294
|
+
dispatch({
|
|
7295
|
+
type: "addEntry",
|
|
7296
|
+
entry: {
|
|
7297
|
+
kind: "subagent",
|
|
7298
|
+
agentLabel: e.target,
|
|
7299
|
+
agentColor: e.ok ? "green" : "red",
|
|
7300
|
+
icon: e.ok ? "\u2713" : "\u2717",
|
|
7301
|
+
text: e.summary,
|
|
7302
|
+
detail: cost
|
|
7303
|
+
}
|
|
7304
|
+
});
|
|
7305
|
+
});
|
|
6612
7306
|
return () => {
|
|
6613
7307
|
offDelta();
|
|
6614
7308
|
offToolStart();
|
|
@@ -6621,6 +7315,8 @@ function App({
|
|
|
6621
7315
|
offProvResp();
|
|
6622
7316
|
offConfirmNeeded();
|
|
6623
7317
|
offTrustPersisted();
|
|
7318
|
+
offDelegateStart();
|
|
7319
|
+
offDelegateDone();
|
|
6624
7320
|
if (flushTimerRef.current) clearTimeout(flushTimerRef.current);
|
|
6625
7321
|
};
|
|
6626
7322
|
}, [events, agent.ctx.todos]);
|
|
@@ -6628,6 +7324,11 @@ function App({
|
|
|
6628
7324
|
useEffect(() => {
|
|
6629
7325
|
streamFleetRef.current = state.streamFleet;
|
|
6630
7326
|
}, [state.streamFleet]);
|
|
7327
|
+
const enhanceEnabledRef = useRef(state.enhanceEnabled);
|
|
7328
|
+
useEffect(() => {
|
|
7329
|
+
enhanceEnabledRef.current = state.enhanceEnabled;
|
|
7330
|
+
}, [state.enhanceEnabled]);
|
|
7331
|
+
const enhanceAbortRef = useRef(null);
|
|
6631
7332
|
useSubagentEvents(events, dispatch, setActiveMaxContext);
|
|
6632
7333
|
useEffect(() => {
|
|
6633
7334
|
const offCheckpoint = events.on("checkpoint.written", (e) => {
|
|
@@ -6853,6 +7554,18 @@ function App({
|
|
|
6853
7554
|
useEffect(() => {
|
|
6854
7555
|
if (fleetStreamController) fleetStreamController.enabled = state.streamFleet;
|
|
6855
7556
|
}, [state.streamFleet, fleetStreamController]);
|
|
7557
|
+
useEffect(() => {
|
|
7558
|
+
if (!enhanceController) return;
|
|
7559
|
+
enhanceController.enabled = state.enhanceEnabled;
|
|
7560
|
+
enhanceController.setEnabled = (enabled) => {
|
|
7561
|
+
dispatch({ type: "enhanceSet", enabled });
|
|
7562
|
+
};
|
|
7563
|
+
return () => {
|
|
7564
|
+
enhanceController.setEnabled = (enabled) => {
|
|
7565
|
+
enhanceController.enabled = enabled;
|
|
7566
|
+
};
|
|
7567
|
+
};
|
|
7568
|
+
}, [enhanceController, state.enhanceEnabled]);
|
|
6856
7569
|
useEffect(() => {
|
|
6857
7570
|
if (!agentsMonitorController) return;
|
|
6858
7571
|
agentsMonitorController.visible = state.agentsMonitorOpen;
|
|
@@ -6932,7 +7645,8 @@ function App({
|
|
|
6932
7645
|
type: "fleetCost",
|
|
6933
7646
|
cost: d.snapshot().total.cost,
|
|
6934
7647
|
input: d.snapshot().total.input,
|
|
6935
|
-
output: d.snapshot().total.output
|
|
7648
|
+
output: d.snapshot().total.output,
|
|
7649
|
+
perAgent: d.snapshot().perSubagent
|
|
6936
7650
|
});
|
|
6937
7651
|
const seen = new Set(Object.keys(status.subagents));
|
|
6938
7652
|
const pending = /* @__PURE__ */ new Map();
|
|
@@ -7061,7 +7775,8 @@ function App({
|
|
|
7061
7775
|
type: "fleetCost",
|
|
7062
7776
|
cost: d.snapshot().total.cost,
|
|
7063
7777
|
input: d.snapshot().total.input,
|
|
7064
|
-
output: d.snapshot().total.output
|
|
7778
|
+
output: d.snapshot().total.output,
|
|
7779
|
+
perAgent: d.snapshot().perSubagent
|
|
7065
7780
|
});
|
|
7066
7781
|
break;
|
|
7067
7782
|
}
|
|
@@ -7189,7 +7904,8 @@ function App({
|
|
|
7189
7904
|
type: "fleetCost",
|
|
7190
7905
|
cost: d.snapshot().total.cost,
|
|
7191
7906
|
input: d.snapshot().total.input,
|
|
7192
|
-
output: d.snapshot().total.output
|
|
7907
|
+
output: d.snapshot().total.output,
|
|
7908
|
+
perAgent: d.snapshot().perSubagent
|
|
7193
7909
|
});
|
|
7194
7910
|
if (streamFlushTimer) {
|
|
7195
7911
|
clearTimeout(streamFlushTimer);
|
|
@@ -7270,7 +7986,7 @@ function App({
|
|
|
7270
7986
|
type: "addEntry",
|
|
7271
7987
|
entry: {
|
|
7272
7988
|
kind: "warn",
|
|
7273
|
-
text: `Iteration cancelled${director ? " + fleet terminated" : ""}${procTag}. Dropped ${droppedCount} queued message${droppedCount === 1 ? "" : "s"}. Press Ctrl+C again to exit
|
|
7989
|
+
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
7990
|
}
|
|
7275
7991
|
});
|
|
7276
7992
|
} else {
|
|
@@ -7278,7 +7994,7 @@ function App({
|
|
|
7278
7994
|
type: "addEntry",
|
|
7279
7995
|
entry: {
|
|
7280
7996
|
kind: "warn",
|
|
7281
|
-
text: `Iteration cancelled${director ? " + fleet terminated" : ""}${procTag}. Press Ctrl+C again to exit
|
|
7997
|
+
text: `Iteration cancelled${director ? " + fleet terminated" : ""}${procTag}. ${confirmExitRef.current ? "Press Ctrl+C again to confirm exit." : "Press Ctrl+C again to exit."}`
|
|
7282
7998
|
}
|
|
7283
7999
|
});
|
|
7284
8000
|
}
|
|
@@ -7309,7 +8025,7 @@ function App({
|
|
|
7309
8025
|
type: "addEntry",
|
|
7310
8026
|
entry: {
|
|
7311
8027
|
kind: "warn",
|
|
7312
|
-
text: `${bits.join(" + ") || "Background work stopped"}. Press Ctrl+C again to exit
|
|
8028
|
+
text: `${bits.join(" + ") || "Background work stopped"}. ${confirmExitRef.current ? "Press Ctrl+C again to confirm exit." : "Press Ctrl+C again to exit."}`
|
|
7313
8029
|
}
|
|
7314
8030
|
});
|
|
7315
8031
|
return;
|
|
@@ -7352,29 +8068,16 @@ function App({
|
|
|
7352
8068
|
const handleKey = async (input, key) => {
|
|
7353
8069
|
if (state.status === "aborting" && !state.steeringPending && state.interrupts === 0) return;
|
|
7354
8070
|
if (state.confirmQueue.length > 0) return;
|
|
8071
|
+
if (state.enhanceBusy) {
|
|
8072
|
+
if (key.escape) enhanceAbortRef.current?.abort();
|
|
8073
|
+
return;
|
|
8074
|
+
}
|
|
8075
|
+
if (state.enhance) return;
|
|
7355
8076
|
if (state.helpOpen) {
|
|
7356
8077
|
if (key.escape || input === "?" || input === "q") dispatch({ type: "toggleHelp" });
|
|
7357
8078
|
return;
|
|
7358
8079
|
}
|
|
7359
8080
|
if (inputGateRef.current) return;
|
|
7360
|
-
if (managedLive) {
|
|
7361
|
-
if (key.pageUp) {
|
|
7362
|
-
dispatch({ type: "scrollPage", dir: "up" });
|
|
7363
|
-
return;
|
|
7364
|
-
}
|
|
7365
|
-
if (key.pageDown) {
|
|
7366
|
-
dispatch({ type: "scrollPage", dir: "down" });
|
|
7367
|
-
return;
|
|
7368
|
-
}
|
|
7369
|
-
if (key.ctrl && key.home) {
|
|
7370
|
-
dispatch({ type: "scrollToTop" });
|
|
7371
|
-
return;
|
|
7372
|
-
}
|
|
7373
|
-
if (key.ctrl && key.end) {
|
|
7374
|
-
dispatch({ type: "scrollToBottom" });
|
|
7375
|
-
return;
|
|
7376
|
-
}
|
|
7377
|
-
}
|
|
7378
8081
|
if (key.escape) {
|
|
7379
8082
|
const now = Date.now();
|
|
7380
8083
|
if (state.buffer.length > 0 && now - lastEscAtRef.current < ESC_DOUBLE_PRESS_MS) {
|
|
@@ -7527,8 +8230,8 @@ function App({
|
|
|
7527
8230
|
const now = Date.now();
|
|
7528
8231
|
if (now - lastEnterAtRef.current < 50) return;
|
|
7529
8232
|
lastEnterAtRef.current = now;
|
|
7530
|
-
const { mode, delayMs } = state.settingsPicker;
|
|
7531
|
-
const err = await saveSettings?.({ mode, delayMs });
|
|
8233
|
+
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;
|
|
8234
|
+
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
8235
|
if (err) {
|
|
7533
8236
|
dispatch({ type: "settingsHint", text: err });
|
|
7534
8237
|
return;
|
|
@@ -7641,20 +8344,32 @@ function App({
|
|
|
7641
8344
|
return;
|
|
7642
8345
|
}
|
|
7643
8346
|
const toggleFleetOverlay = () => {
|
|
7644
|
-
if (state.
|
|
7645
|
-
dispatch({ type: "toggleAgentsMonitor" });
|
|
7646
|
-
dispatch({ type: "toggleMonitor" });
|
|
7647
|
-
} else {
|
|
8347
|
+
if (state.monitorOpen) {
|
|
7648
8348
|
dispatch({ type: "toggleMonitor" });
|
|
8349
|
+
return;
|
|
7649
8350
|
}
|
|
8351
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
8352
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
8353
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
8354
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8355
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
8356
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
8357
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
8358
|
+
dispatch({ type: "toggleMonitor" });
|
|
7650
8359
|
};
|
|
7651
8360
|
const toggleAgentsOverlay = () => {
|
|
7652
|
-
if (state.
|
|
7653
|
-
dispatch({ type: "toggleMonitor" });
|
|
7654
|
-
dispatch({ type: "toggleAgentsMonitor" });
|
|
7655
|
-
} else {
|
|
8361
|
+
if (state.agentsMonitorOpen) {
|
|
7656
8362
|
dispatch({ type: "toggleAgentsMonitor" });
|
|
8363
|
+
return;
|
|
7657
8364
|
}
|
|
8365
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
8366
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
8367
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
8368
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8369
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
8370
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
8371
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
8372
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
7658
8373
|
};
|
|
7659
8374
|
const toggleWorktreeOverlay = () => {
|
|
7660
8375
|
if (state.worktreeMonitorOpen) {
|
|
@@ -7664,8 +8379,26 @@ function App({
|
|
|
7664
8379
|
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
7665
8380
|
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
7666
8381
|
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8382
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
8383
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
8384
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
8385
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
7667
8386
|
dispatch({ type: "worktreeMonitorToggle" });
|
|
7668
8387
|
};
|
|
8388
|
+
const toggleTodosOverlay = () => {
|
|
8389
|
+
if (state.todosMonitorOpen) {
|
|
8390
|
+
dispatch({ type: "toggleTodosMonitor" });
|
|
8391
|
+
return;
|
|
8392
|
+
}
|
|
8393
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
8394
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
8395
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
8396
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8397
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
8398
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
8399
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
8400
|
+
dispatch({ type: "toggleTodosMonitor" });
|
|
8401
|
+
};
|
|
7669
8402
|
if (key.ctrl && input === "f" || key.fn === 2) {
|
|
7670
8403
|
toggleFleetOverlay();
|
|
7671
8404
|
return;
|
|
@@ -7678,12 +8411,96 @@ function App({
|
|
|
7678
8411
|
toggleWorktreeOverlay();
|
|
7679
8412
|
return;
|
|
7680
8413
|
}
|
|
8414
|
+
if (key.fn === 5) {
|
|
8415
|
+
if (state.settingsPicker.open) {
|
|
8416
|
+
dispatch({ type: "settingsClose" });
|
|
8417
|
+
} else if (getSettings && saveSettings) {
|
|
8418
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
8419
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
8420
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
8421
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
8422
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8423
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
8424
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
8425
|
+
const cfg = getSettings();
|
|
8426
|
+
dispatch({
|
|
8427
|
+
type: "settingsOpen",
|
|
8428
|
+
mode: cfg.mode,
|
|
8429
|
+
delayMs: cfg.delayMs,
|
|
8430
|
+
titleAnimation: cfg.titleAnimation ?? true,
|
|
8431
|
+
yolo: cfg.yolo ?? false,
|
|
8432
|
+
streamFleet: cfg.streamFleet ?? true,
|
|
8433
|
+
chime: cfg.chime ?? false,
|
|
8434
|
+
confirmExit: cfg.confirmExit ?? true,
|
|
8435
|
+
nextPrediction: cfg.nextPrediction ?? false,
|
|
8436
|
+
featureMcp: cfg.featureMcp ?? true,
|
|
8437
|
+
featurePlugins: cfg.featurePlugins ?? true,
|
|
8438
|
+
featureMemory: cfg.featureMemory ?? true,
|
|
8439
|
+
featureSkills: cfg.featureSkills ?? true,
|
|
8440
|
+
featureModelsRegistry: cfg.featureModelsRegistry ?? true,
|
|
8441
|
+
contextAutoCompact: cfg.contextAutoCompact ?? true,
|
|
8442
|
+
contextStrategy: cfg.contextStrategy ?? "hybrid",
|
|
8443
|
+
logLevel: cfg.logLevel ?? "info",
|
|
8444
|
+
auditLevel: cfg.auditLevel ?? "standard",
|
|
8445
|
+
indexOnStart: cfg.indexOnStart ?? true,
|
|
8446
|
+
maxIterations: cfg.maxIterations ?? 500
|
|
8447
|
+
});
|
|
8448
|
+
}
|
|
8449
|
+
return;
|
|
8450
|
+
}
|
|
8451
|
+
if (key.fn === 6) {
|
|
8452
|
+
toggleTodosOverlay();
|
|
8453
|
+
return;
|
|
8454
|
+
}
|
|
8455
|
+
if (key.fn === 7) {
|
|
8456
|
+
if (state.queuePanelOpen) {
|
|
8457
|
+
dispatch({ type: "toggleQueuePanel" });
|
|
8458
|
+
} else {
|
|
8459
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
8460
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
8461
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
8462
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
8463
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8464
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
8465
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
8466
|
+
dispatch({ type: "toggleQueuePanel" });
|
|
8467
|
+
}
|
|
8468
|
+
return;
|
|
8469
|
+
}
|
|
7681
8470
|
if (key.ctrl && input === "s") {
|
|
7682
8471
|
if (state.settingsPicker.open) {
|
|
7683
8472
|
dispatch({ type: "settingsClose" });
|
|
7684
8473
|
} else if (getSettings && saveSettings) {
|
|
8474
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
8475
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
8476
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
8477
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
8478
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8479
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
8480
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
7685
8481
|
const cfg = getSettings();
|
|
7686
|
-
dispatch({
|
|
8482
|
+
dispatch({
|
|
8483
|
+
type: "settingsOpen",
|
|
8484
|
+
mode: cfg.mode,
|
|
8485
|
+
delayMs: cfg.delayMs,
|
|
8486
|
+
titleAnimation: cfg.titleAnimation ?? true,
|
|
8487
|
+
yolo: cfg.yolo ?? false,
|
|
8488
|
+
streamFleet: cfg.streamFleet ?? true,
|
|
8489
|
+
chime: cfg.chime ?? false,
|
|
8490
|
+
confirmExit: cfg.confirmExit ?? true,
|
|
8491
|
+
nextPrediction: cfg.nextPrediction ?? false,
|
|
8492
|
+
featureMcp: cfg.featureMcp ?? true,
|
|
8493
|
+
featurePlugins: cfg.featurePlugins ?? true,
|
|
8494
|
+
featureMemory: cfg.featureMemory ?? true,
|
|
8495
|
+
featureSkills: cfg.featureSkills ?? true,
|
|
8496
|
+
featureModelsRegistry: cfg.featureModelsRegistry ?? true,
|
|
8497
|
+
contextAutoCompact: cfg.contextAutoCompact ?? true,
|
|
8498
|
+
contextStrategy: cfg.contextStrategy ?? "hybrid",
|
|
8499
|
+
logLevel: cfg.logLevel ?? "info",
|
|
8500
|
+
auditLevel: cfg.auditLevel ?? "standard",
|
|
8501
|
+
indexOnStart: cfg.indexOnStart ?? true,
|
|
8502
|
+
maxIterations: cfg.maxIterations ?? 500
|
|
8503
|
+
});
|
|
7687
8504
|
}
|
|
7688
8505
|
return;
|
|
7689
8506
|
}
|
|
@@ -7700,12 +8517,34 @@ function App({
|
|
|
7700
8517
|
dispatch({ type: "worktreeMonitorToggle" });
|
|
7701
8518
|
return;
|
|
7702
8519
|
}
|
|
8520
|
+
if (state.todosMonitorOpen) {
|
|
8521
|
+
dispatch({ type: "toggleTodosMonitor" });
|
|
8522
|
+
return;
|
|
8523
|
+
}
|
|
8524
|
+
if (state.autoPhase?.monitorOpen) {
|
|
8525
|
+
dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8526
|
+
return;
|
|
8527
|
+
}
|
|
8528
|
+
if (state.settingsPicker.open) {
|
|
8529
|
+
dispatch({ type: "settingsClose" });
|
|
8530
|
+
return;
|
|
8531
|
+
}
|
|
8532
|
+
if (state.queuePanelOpen) {
|
|
8533
|
+
dispatch({ type: "toggleQueuePanel" });
|
|
8534
|
+
return;
|
|
8535
|
+
}
|
|
7703
8536
|
}
|
|
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) {
|
|
8537
|
+
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
8538
|
dispatch({ type: "toggleHelp" });
|
|
7706
8539
|
return;
|
|
7707
8540
|
}
|
|
7708
8541
|
if (isEnter) {
|
|
8542
|
+
if (key.shift) {
|
|
8543
|
+
const { buffer: buffer2, cursor: cursor2 } = draftRef.current;
|
|
8544
|
+
const next2 = buffer2.slice(0, cursor2) + "\n" + buffer2.slice(cursor2);
|
|
8545
|
+
setDraft(next2, cursor2 + 1);
|
|
8546
|
+
return;
|
|
8547
|
+
}
|
|
7709
8548
|
const now = Date.now();
|
|
7710
8549
|
if (now - lastEnterAtRef.current < 50) return;
|
|
7711
8550
|
lastEnterAtRef.current = now;
|
|
@@ -7713,36 +8552,41 @@ function App({
|
|
|
7713
8552
|
return;
|
|
7714
8553
|
}
|
|
7715
8554
|
const { buffer, cursor } = draftRef.current;
|
|
7716
|
-
if (key.backspace
|
|
8555
|
+
if (key.backspace) {
|
|
7717
8556
|
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
|
-
}
|
|
8557
|
+
if (cursor === 0) return;
|
|
8558
|
+
const beforeCursor = buffer.slice(0, cursor);
|
|
8559
|
+
const lastWordStart = beforeCursor.lastIndexOf(" ") + 1;
|
|
8560
|
+
const next3 = beforeCursor.slice(0, lastWordStart) + buffer.slice(cursor);
|
|
8561
|
+
setDraft(next3, lastWordStart);
|
|
7732
8562
|
return;
|
|
7733
8563
|
}
|
|
7734
|
-
|
|
7735
|
-
|
|
7736
|
-
|
|
7737
|
-
|
|
7738
|
-
return;
|
|
7739
|
-
}
|
|
8564
|
+
const tokenDel = deleteTokenBackward(buffer, cursor);
|
|
8565
|
+
if (tokenDel) {
|
|
8566
|
+
setDraft(tokenDel.buffer, tokenDel.cursor);
|
|
8567
|
+
return;
|
|
7740
8568
|
}
|
|
7741
8569
|
if (cursor === 0) return;
|
|
7742
8570
|
const next2 = buffer.slice(0, cursor - 1) + buffer.slice(cursor);
|
|
7743
8571
|
setDraft(next2, cursor - 1);
|
|
7744
8572
|
return;
|
|
7745
8573
|
}
|
|
8574
|
+
if (key.delete) {
|
|
8575
|
+
if (key.ctrl) {
|
|
8576
|
+
if (cursor >= buffer.length) return;
|
|
8577
|
+
const afterCursor = buffer.slice(cursor);
|
|
8578
|
+
const nextWordStart = afterCursor.indexOf(" ");
|
|
8579
|
+
const end = nextWordStart === -1 ? buffer.length : cursor + nextWordStart + 1;
|
|
8580
|
+
const next3 = buffer.slice(0, cursor) + buffer.slice(end);
|
|
8581
|
+
setDraft(next3, cursor);
|
|
8582
|
+
return;
|
|
8583
|
+
}
|
|
8584
|
+
if (cursor >= buffer.length) return;
|
|
8585
|
+
const span = tokenLengthForward(buffer, cursor) || 1;
|
|
8586
|
+
const next2 = buffer.slice(0, cursor) + buffer.slice(cursor + span);
|
|
8587
|
+
setDraft(next2, cursor);
|
|
8588
|
+
return;
|
|
8589
|
+
}
|
|
7746
8590
|
if (key.leftArrow) {
|
|
7747
8591
|
if (key.ctrl) {
|
|
7748
8592
|
if (cursor === 0) return;
|
|
@@ -7768,19 +8612,11 @@ function App({
|
|
|
7768
8612
|
return;
|
|
7769
8613
|
}
|
|
7770
8614
|
if (key.home) {
|
|
7771
|
-
|
|
7772
|
-
dispatch({ type: "scrollToTop" });
|
|
7773
|
-
} else {
|
|
7774
|
-
setDraft(buffer, 0);
|
|
7775
|
-
}
|
|
8615
|
+
setDraft(buffer, 0);
|
|
7776
8616
|
return;
|
|
7777
8617
|
}
|
|
7778
8618
|
if (key.end) {
|
|
7779
|
-
|
|
7780
|
-
dispatch({ type: "scrollToBottom" });
|
|
7781
|
-
} else {
|
|
7782
|
-
setDraft(buffer, buffer.length);
|
|
7783
|
-
}
|
|
8619
|
+
setDraft(buffer, buffer.length);
|
|
7784
8620
|
return;
|
|
7785
8621
|
}
|
|
7786
8622
|
if (key.upArrow) {
|
|
@@ -7813,7 +8649,7 @@ function App({
|
|
|
7813
8649
|
setDraft("", 0);
|
|
7814
8650
|
return;
|
|
7815
8651
|
}
|
|
7816
|
-
if (key.
|
|
8652
|
+
if (key.ctrl && input === "d") {
|
|
7817
8653
|
if (cursor >= buffer.length) return;
|
|
7818
8654
|
const span = tokenLengthForward(buffer, cursor) || 1;
|
|
7819
8655
|
const next2 = buffer.slice(0, cursor) + buffer.slice(cursor + span);
|
|
@@ -7940,10 +8776,20 @@ function App({
|
|
|
7940
8776
|
} finally {
|
|
7941
8777
|
activeCtrlRef.current = null;
|
|
7942
8778
|
dispatch({ type: "status", status: "idle" });
|
|
8779
|
+
if (chimeRef.current) {
|
|
8780
|
+
try {
|
|
8781
|
+
process.stdout.write("\x07");
|
|
8782
|
+
} catch {
|
|
8783
|
+
}
|
|
8784
|
+
}
|
|
7943
8785
|
}
|
|
7944
8786
|
const head = stateRef.current.queue[0];
|
|
7945
8787
|
if (head) {
|
|
7946
8788
|
dispatch({ type: "dequeueFirst" });
|
|
8789
|
+
dispatch({
|
|
8790
|
+
type: "addEntry",
|
|
8791
|
+
entry: { kind: "user", text: head.displayText }
|
|
8792
|
+
});
|
|
7947
8793
|
await runBlocks(head.blocks);
|
|
7948
8794
|
}
|
|
7949
8795
|
};
|
|
@@ -8088,6 +8934,10 @@ function App({
|
|
|
8088
8934
|
void runParallelLoopRef.current();
|
|
8089
8935
|
}
|
|
8090
8936
|
}
|
|
8937
|
+
if (getModeLabel) {
|
|
8938
|
+
const currentMode = getModeLabel();
|
|
8939
|
+
if (currentMode !== liveModeLabel) setLiveModeLabel(currentMode);
|
|
8940
|
+
}
|
|
8091
8941
|
if (res?.exit) {
|
|
8092
8942
|
exit();
|
|
8093
8943
|
onExit(0);
|
|
@@ -8107,6 +8957,7 @@ function App({
|
|
|
8107
8957
|
const cmd = trimmed.slice(1).split(/\s+/, 1)[0];
|
|
8108
8958
|
if (cmd === "clear") {
|
|
8109
8959
|
onClearHistory?.(dispatch);
|
|
8960
|
+
tokenCounter?.reset();
|
|
8110
8961
|
}
|
|
8111
8962
|
} catch (err) {
|
|
8112
8963
|
dispatch({
|
|
@@ -8119,6 +8970,52 @@ function App({
|
|
|
8119
8970
|
const builder = builderRef.current;
|
|
8120
8971
|
if (!builder) return;
|
|
8121
8972
|
const steering = state.steeringPending;
|
|
8973
|
+
let effectiveText = trimmed;
|
|
8974
|
+
const hasChips = trimmed ? new RegExp(INLINE_TOKEN_SRC, "g").test(trimmed) : false;
|
|
8975
|
+
if (enhanceEnabledRef.current && state.status === "idle" && !steering && !hasChips && shouldEnhance(trimmed)) {
|
|
8976
|
+
dispatch({ type: "enhanceBusy", on: true });
|
|
8977
|
+
const ac = new AbortController();
|
|
8978
|
+
enhanceAbortRef.current = ac;
|
|
8979
|
+
let refined = null;
|
|
8980
|
+
let enhanceErr = null;
|
|
8981
|
+
try {
|
|
8982
|
+
refined = await enhanceUserPrompt({
|
|
8983
|
+
provider: agent.ctx.provider,
|
|
8984
|
+
model: agent.ctx.model,
|
|
8985
|
+
text: trimmed,
|
|
8986
|
+
signal: ac.signal,
|
|
8987
|
+
onError: (reason) => {
|
|
8988
|
+
enhanceErr = reason;
|
|
8989
|
+
},
|
|
8990
|
+
// Feed recent conversation so follow-ups ("do the same", "that file")
|
|
8991
|
+
// resolve against context instead of being refined blind.
|
|
8992
|
+
history: recentTextTurns(agent.ctx.messages)
|
|
8993
|
+
});
|
|
8994
|
+
} finally {
|
|
8995
|
+
enhanceAbortRef.current = null;
|
|
8996
|
+
dispatch({ type: "enhanceBusy", on: false });
|
|
8997
|
+
}
|
|
8998
|
+
if (refined === null && !ac.signal.aborted) {
|
|
8999
|
+
dispatch({
|
|
9000
|
+
type: "addEntry",
|
|
9001
|
+
entry: {
|
|
9002
|
+
kind: "info",
|
|
9003
|
+
text: enhanceErr ? `\u2728 refinement unavailable (${enhanceErr}) \u2014 sent your message as-is` : "\u2728 refinement unavailable \u2014 sent your message as-is"
|
|
9004
|
+
}
|
|
9005
|
+
});
|
|
9006
|
+
}
|
|
9007
|
+
if (refined && !normalizedEqual(refined, trimmed)) {
|
|
9008
|
+
const decision = await new Promise((resolve) => {
|
|
9009
|
+
dispatch({ type: "enhanceOpen", info: { original: trimmed, refined, resolve } });
|
|
9010
|
+
});
|
|
9011
|
+
dispatch({ type: "enhanceClose" });
|
|
9012
|
+
if (decision === "edit") {
|
|
9013
|
+
setDraft(refined, refined.length);
|
|
9014
|
+
return;
|
|
9015
|
+
}
|
|
9016
|
+
effectiveText = decision === "refined" ? refined : trimmed;
|
|
9017
|
+
}
|
|
9018
|
+
}
|
|
8122
9019
|
const sddContext = getSDDContext?.();
|
|
8123
9020
|
if (sddContext && trimmed) {
|
|
8124
9021
|
builder.appendText(`[SDD SESSION ACTIVE]
|
|
@@ -8129,11 +9026,11 @@ User message:
|
|
|
8129
9026
|
`);
|
|
8130
9027
|
}
|
|
8131
9028
|
if (trimmed) {
|
|
8132
|
-
const toAppend = steering ? buildSteeringPreamble(state.steerSnapshot,
|
|
9029
|
+
const toAppend = steering ? buildSteeringPreamble(state.steerSnapshot, effectiveText) : effectiveText;
|
|
8133
9030
|
builder.appendText(toAppend);
|
|
8134
9031
|
}
|
|
8135
9032
|
if (steering) dispatch({ type: "steerConsume" });
|
|
8136
|
-
const displayText = trimmed ? steering ? `\u21AF ${
|
|
9033
|
+
const displayText = trimmed ? steering ? `\u21AF ${effectiveText}` : effectiveText : "(attachments only)";
|
|
8137
9034
|
const pasteParts = [];
|
|
8138
9035
|
for (const m of trimmed.matchAll(new RegExp(INLINE_TOKEN_SRC, "g"))) {
|
|
8139
9036
|
const token = m[0];
|
|
@@ -8193,20 +9090,9 @@ User message:
|
|
|
8193
9090
|
if (state.picker.open) return "";
|
|
8194
9091
|
return "";
|
|
8195
9092
|
}, [state.buffer, state.status, state.picker.open]);
|
|
8196
|
-
const
|
|
8197
|
-
return /* @__PURE__ */
|
|
8198
|
-
|
|
8199
|
-
ScrollableHistory,
|
|
8200
|
-
{
|
|
8201
|
-
entries: state.entries,
|
|
8202
|
-
streamingText: state.streamingText,
|
|
8203
|
-
toolStream: state.toolStream,
|
|
8204
|
-
scrollOffset: state.scrollOffset,
|
|
8205
|
-
viewportRows: state.viewportRows || Math.max(MIN_VIEWPORT, termRows - 8),
|
|
8206
|
-
totalLines: state.totalLines,
|
|
8207
|
-
onMeasure: (total) => dispatch({ type: "setMeasuredLines", totalLines: total })
|
|
8208
|
-
}
|
|
8209
|
-
) : /* @__PURE__ */ jsx(
|
|
9093
|
+
const enhanceActive = state.enhanceBusy || state.enhance != null;
|
|
9094
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, flexShrink: 0, children: [
|
|
9095
|
+
/* @__PURE__ */ jsx(
|
|
8210
9096
|
History,
|
|
8211
9097
|
{
|
|
8212
9098
|
entries: state.entries,
|
|
@@ -8214,17 +9100,16 @@ User message:
|
|
|
8214
9100
|
toolStream: state.toolStream
|
|
8215
9101
|
}
|
|
8216
9102
|
),
|
|
8217
|
-
|
|
8218
|
-
/* @__PURE__ */ jsxs(Box, { ref: managedLive ? bottomRef : void 0, flexDirection: "column", flexShrink: 0, children: [
|
|
9103
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [
|
|
8219
9104
|
/* @__PURE__ */ jsx(LiveActivityStrip, { entries: state.fleet, nowTick }),
|
|
8220
9105
|
/* @__PURE__ */ jsx(
|
|
8221
9106
|
Input,
|
|
8222
9107
|
{
|
|
8223
9108
|
prompt: INPUT_PROMPT,
|
|
8224
|
-
value: state.buffer,
|
|
8225
|
-
cursor: state.cursor,
|
|
9109
|
+
value: enhanceActive ? "" : state.buffer,
|
|
9110
|
+
cursor: enhanceActive ? 0 : state.cursor,
|
|
8226
9111
|
disabled: state.status === "aborting" && !state.steeringPending || state.confirmQueue.length > 0,
|
|
8227
|
-
hint: inputHint,
|
|
9112
|
+
hint: enhanceActive ? "" : inputHint,
|
|
8228
9113
|
onKey: handleKey
|
|
8229
9114
|
}
|
|
8230
9115
|
),
|
|
@@ -8271,19 +9156,42 @@ User message:
|
|
|
8271
9156
|
field: state.settingsPicker.field,
|
|
8272
9157
|
mode: state.settingsPicker.mode,
|
|
8273
9158
|
delayMs: state.settingsPicker.delayMs,
|
|
9159
|
+
titleAnimation: state.settingsPicker.titleAnimation,
|
|
9160
|
+
yolo: state.settingsPicker.yolo,
|
|
9161
|
+
streamFleet: state.settingsPicker.streamFleet,
|
|
9162
|
+
chime: state.settingsPicker.chime,
|
|
9163
|
+
confirmExit: state.settingsPicker.confirmExit,
|
|
9164
|
+
nextPrediction: state.settingsPicker.nextPrediction,
|
|
9165
|
+
featureMcp: state.settingsPicker.featureMcp,
|
|
9166
|
+
featurePlugins: state.settingsPicker.featurePlugins,
|
|
9167
|
+
featureMemory: state.settingsPicker.featureMemory,
|
|
9168
|
+
featureSkills: state.settingsPicker.featureSkills,
|
|
9169
|
+
featureModelsRegistry: state.settingsPicker.featureModelsRegistry,
|
|
9170
|
+
contextAutoCompact: state.settingsPicker.contextAutoCompact,
|
|
9171
|
+
contextStrategy: state.settingsPicker.contextStrategy,
|
|
9172
|
+
logLevel: state.settingsPicker.logLevel,
|
|
9173
|
+
auditLevel: state.settingsPicker.auditLevel,
|
|
9174
|
+
indexOnStart: state.settingsPicker.indexOnStart,
|
|
9175
|
+
maxIterations: state.settingsPicker.maxIterations,
|
|
8274
9176
|
hint: state.settingsPicker.hint
|
|
8275
9177
|
}
|
|
8276
9178
|
) : null,
|
|
8277
|
-
state.rewindOverlay ?
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
9179
|
+
state.rewindOverlay ? (() => {
|
|
9180
|
+
const overlay = state.rewindOverlay;
|
|
9181
|
+
return /* @__PURE__ */ jsx(
|
|
9182
|
+
CheckpointTimeline,
|
|
9183
|
+
{
|
|
9184
|
+
checkpoints: overlay.checkpoints,
|
|
9185
|
+
selected: overlay.selected,
|
|
9186
|
+
onSelect: (i) => dispatch({ type: "rewindOverlayMove", delta: i - overlay.selected }),
|
|
9187
|
+
onConfirm: (i) => {
|
|
9188
|
+
const checkpoint = overlay.checkpoints[i];
|
|
9189
|
+
if (checkpoint) handleRewindTo(checkpoint.promptIndex);
|
|
9190
|
+
},
|
|
9191
|
+
onClose: () => dispatch({ type: "rewindOverlayClose" })
|
|
9192
|
+
}
|
|
9193
|
+
);
|
|
9194
|
+
})() : null,
|
|
8287
9195
|
state.brainPrompt ? /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginY: 1, flexShrink: 0, children: /* @__PURE__ */ jsx(
|
|
8288
9196
|
BrainDecisionPrompt,
|
|
8289
9197
|
{
|
|
@@ -8295,7 +9203,7 @@ User message:
|
|
|
8295
9203
|
}
|
|
8296
9204
|
) }) : null,
|
|
8297
9205
|
state.confirmQueue.length > 0 && (() => {
|
|
8298
|
-
const head = state.confirmQueue[0];
|
|
9206
|
+
const head = expectDefined6(state.confirmQueue[0]);
|
|
8299
9207
|
let resolved = false;
|
|
8300
9208
|
const onDecision = (decision) => {
|
|
8301
9209
|
if (resolved) return;
|
|
@@ -8313,6 +9221,25 @@ User message:
|
|
|
8313
9221
|
}
|
|
8314
9222
|
);
|
|
8315
9223
|
})(),
|
|
9224
|
+
state.enhanceBusy && !state.enhance ? /* @__PURE__ */ jsx(Box, { paddingX: 1, children: /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u2728 refining your request\u2026" }) }) : null,
|
|
9225
|
+
state.enhance ? (() => {
|
|
9226
|
+
const info = state.enhance;
|
|
9227
|
+
let resolved = false;
|
|
9228
|
+
const onDecision = (decision) => {
|
|
9229
|
+
if (resolved) return;
|
|
9230
|
+
resolved = true;
|
|
9231
|
+
info.resolve(decision);
|
|
9232
|
+
};
|
|
9233
|
+
return /* @__PURE__ */ jsx(
|
|
9234
|
+
EnhancePanel,
|
|
9235
|
+
{
|
|
9236
|
+
original: info.original,
|
|
9237
|
+
refined: info.refined,
|
|
9238
|
+
delayMs: enhanceDelayMs,
|
|
9239
|
+
onDecision
|
|
9240
|
+
}
|
|
9241
|
+
);
|
|
9242
|
+
})() : null,
|
|
8316
9243
|
/* @__PURE__ */ jsx(
|
|
8317
9244
|
StatusBar,
|
|
8318
9245
|
{
|
|
@@ -8324,7 +9251,7 @@ User message:
|
|
|
8324
9251
|
queueCount: state.queue.length,
|
|
8325
9252
|
yolo: yoloLive,
|
|
8326
9253
|
autonomy: autonomyLive,
|
|
8327
|
-
|
|
9254
|
+
startedAt: startedAtRef.current,
|
|
8328
9255
|
todos,
|
|
8329
9256
|
plan: planCounts ?? void 0,
|
|
8330
9257
|
fleet: fleetCounts,
|
|
@@ -8336,26 +9263,18 @@ User message:
|
|
|
8336
9263
|
processCount: getProcessRegistry().activeCount,
|
|
8337
9264
|
hiddenItems,
|
|
8338
9265
|
eternalStage: state.eternalStage,
|
|
8339
|
-
goalSummary: state.goalSummary
|
|
9266
|
+
goalSummary: state.goalSummary,
|
|
9267
|
+
indexState,
|
|
9268
|
+
modeLabel: liveModeLabel || void 0
|
|
8340
9269
|
}
|
|
8341
9270
|
),
|
|
8342
|
-
|
|
8343
|
-
KeyHintBar,
|
|
8344
|
-
{
|
|
8345
|
-
context: {
|
|
8346
|
-
confirm: state.confirmQueue.length > 0,
|
|
8347
|
-
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,
|
|
8349
|
-
managed: managedLive
|
|
8350
|
-
}
|
|
8351
|
-
}
|
|
8352
|
-
) : null,
|
|
8353
|
-
state.helpOpen ? /* @__PURE__ */ jsx(HelpOverlay, { managed: managedLive }) : null,
|
|
9271
|
+
state.helpOpen ? /* @__PURE__ */ jsx(HelpOverlay, {}) : null,
|
|
8354
9272
|
state.agentsMonitorOpen ? /* @__PURE__ */ jsx(
|
|
8355
9273
|
AgentsMonitor,
|
|
8356
9274
|
{
|
|
8357
9275
|
entries: entriesWithLeader,
|
|
8358
9276
|
totalCost: state.fleetCost,
|
|
9277
|
+
leaderCost: tokenCounter?.estimateCost().total ?? 0,
|
|
8359
9278
|
totalTokens: state.fleetTokens,
|
|
8360
9279
|
nowTick
|
|
8361
9280
|
}
|
|
@@ -8376,7 +9295,7 @@ User message:
|
|
|
8376
9295
|
nowTick,
|
|
8377
9296
|
onClose: () => dispatch({ type: "worktreeMonitorToggle" })
|
|
8378
9297
|
}
|
|
8379
|
-
) : state.monitorOpen ? /* @__PURE__ */ jsx(
|
|
9298
|
+
) : state.todosMonitorOpen ? /* @__PURE__ */ jsx(TodosMonitor, { todos: agent.ctx.todos }) : state.monitorOpen ? /* @__PURE__ */ jsx(
|
|
8380
9299
|
FleetMonitor,
|
|
8381
9300
|
{
|
|
8382
9301
|
entries: state.fleet,
|
|
@@ -8403,9 +9322,10 @@ User message:
|
|
|
8403
9322
|
nowTick
|
|
8404
9323
|
}
|
|
8405
9324
|
) : null,
|
|
8406
|
-
Object.keys(state.worktrees).length > 0 && !state.worktreeMonitorOpen && !state.monitorOpen ? /* @__PURE__ */ jsx(WorktreePanel, { worktrees: state.worktrees, nowTick }) : null
|
|
9325
|
+
Object.keys(state.worktrees).length > 0 && !state.worktreeMonitorOpen && !state.monitorOpen ? /* @__PURE__ */ jsx(WorktreePanel, { worktrees: state.worktrees, nowTick }) : null,
|
|
9326
|
+
state.queuePanelOpen ? /* @__PURE__ */ jsx(QueuePanel, { items: state.queue }) : null
|
|
8407
9327
|
] })
|
|
8408
|
-
] });
|
|
9328
|
+
] }) });
|
|
8409
9329
|
}
|
|
8410
9330
|
function renderRunningTools(running) {
|
|
8411
9331
|
if (running.size === 0) return "";
|
|
@@ -8505,9 +9425,6 @@ function startTerminalTitle(opts) {
|
|
|
8505
9425
|
// src/run-tui.ts
|
|
8506
9426
|
var BRACKETED_PASTE_ON = "\x1B[?2004h";
|
|
8507
9427
|
var BRACKETED_PASTE_OFF = "\x1B[?2004l";
|
|
8508
|
-
var ALT_SCREEN_ON = "\x1B[?1049h";
|
|
8509
|
-
var ALT_SCREEN_OFF = "\x1B[?1049l";
|
|
8510
|
-
var CURSOR_HOME = "\x1B[H";
|
|
8511
9428
|
async function runTui(opts) {
|
|
8512
9429
|
const stdout = process.stdout;
|
|
8513
9430
|
const stdin = process.stdin;
|
|
@@ -8517,14 +9434,11 @@ async function runTui(opts) {
|
|
|
8517
9434
|
);
|
|
8518
9435
|
return 2;
|
|
8519
9436
|
}
|
|
8520
|
-
const useAltScreen = opts.altScreen === true;
|
|
8521
|
-
if (useAltScreen) {
|
|
8522
|
-
stdout.write(ALT_SCREEN_ON);
|
|
8523
|
-
stdout.write(CURSOR_HOME);
|
|
8524
|
-
}
|
|
8525
9437
|
stdout.write(BRACKETED_PASTE_ON);
|
|
9438
|
+
stdout.write("\x1B[2J\x1B[H");
|
|
8526
9439
|
const inkStdin = stdin;
|
|
8527
|
-
const stopTitle = startTerminalTitle({ stdout, events: opts.events, model: opts.model })
|
|
9440
|
+
const stopTitle = opts.titleAnimation !== false ? startTerminalTitle({ stdout, events: opts.events, model: opts.model }) : (() => {
|
|
9441
|
+
});
|
|
8528
9442
|
const swallowSignals = ["SIGTSTP", "SIGQUIT", "SIGTTIN", "SIGTTOU"];
|
|
8529
9443
|
const swallow = () => {
|
|
8530
9444
|
};
|
|
@@ -8544,9 +9458,6 @@ async function runTui(opts) {
|
|
|
8544
9458
|
}
|
|
8545
9459
|
try {
|
|
8546
9460
|
stdout.write(BRACKETED_PASTE_OFF);
|
|
8547
|
-
if (useAltScreen) {
|
|
8548
|
-
stdout.write(ALT_SCREEN_OFF);
|
|
8549
|
-
}
|
|
8550
9461
|
} catch {
|
|
8551
9462
|
}
|
|
8552
9463
|
};
|
|
@@ -8573,18 +9484,12 @@ async function runTui(opts) {
|
|
|
8573
9484
|
const settle = (code) => {
|
|
8574
9485
|
cleanup();
|
|
8575
9486
|
detachListeners();
|
|
8576
|
-
if (useAltScreen && opts.onAfterExit) {
|
|
8577
|
-
try {
|
|
8578
|
-
opts.onAfterExit();
|
|
8579
|
-
} catch {
|
|
8580
|
-
}
|
|
8581
|
-
}
|
|
8582
9487
|
resolve(code);
|
|
8583
9488
|
};
|
|
8584
9489
|
let instance;
|
|
8585
9490
|
try {
|
|
8586
9491
|
instance = render(
|
|
8587
|
-
|
|
9492
|
+
React6.createElement(App, {
|
|
8588
9493
|
agent: opts.agent,
|
|
8589
9494
|
slashRegistry: opts.slashRegistry,
|
|
8590
9495
|
attachments: opts.attachments,
|
|
@@ -8614,8 +9519,10 @@ async function runTui(opts) {
|
|
|
8614
9519
|
onExit,
|
|
8615
9520
|
director: opts.director ?? null,
|
|
8616
9521
|
fleetRoster: opts.fleetRoster,
|
|
8617
|
-
onClearHistory: opts.onClearHistory ? (dispatch) => opts.onClearHistory(dispatch) : void 0,
|
|
9522
|
+
onClearHistory: opts.onClearHistory ? (dispatch) => opts.onClearHistory?.(dispatch) : void 0,
|
|
8618
9523
|
fleetStreamController: opts.fleetStreamController,
|
|
9524
|
+
enhanceController: opts.enhanceController,
|
|
9525
|
+
enhanceEnabled: opts.enhanceController?.enabled ?? true,
|
|
8619
9526
|
statuslineHiddenItems: opts.statuslineHiddenItems,
|
|
8620
9527
|
setStatuslineHiddenItems: opts.setStatuslineHiddenItems,
|
|
8621
9528
|
agentsMonitorController: opts.agentsMonitorController,
|
|
@@ -8628,9 +9535,10 @@ async function runTui(opts) {
|
|
|
8628
9535
|
getSettings: opts.getSettings,
|
|
8629
9536
|
saveSettings: opts.saveSettings,
|
|
8630
9537
|
predictNext: opts.predictNext,
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
9538
|
+
chime: opts.chime,
|
|
9539
|
+
confirmExit: opts.confirmExit,
|
|
9540
|
+
modeLabel: opts.modeLabel,
|
|
9541
|
+
getModeLabel: opts.getModeLabel
|
|
8634
9542
|
}),
|
|
8635
9543
|
{ exitOnCtrlC: false, stdin: inkStdin }
|
|
8636
9544
|
);
|
|
@@ -8643,16 +9551,14 @@ async function runTui(opts) {
|
|
|
8643
9551
|
return;
|
|
8644
9552
|
}
|
|
8645
9553
|
let detachResize = null;
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
8654
|
-
detachResize = () => stdout.off("resize", onResize);
|
|
8655
|
-
}
|
|
9554
|
+
const onResize = () => {
|
|
9555
|
+
try {
|
|
9556
|
+
stdout.write("\x1B[J");
|
|
9557
|
+
} catch {
|
|
9558
|
+
}
|
|
9559
|
+
};
|
|
9560
|
+
stdout.on("resize", onResize);
|
|
9561
|
+
detachResize = () => stdout.off("resize", onResize);
|
|
8656
9562
|
instance.waitUntilExit().then(() => {
|
|
8657
9563
|
detachResize?.();
|
|
8658
9564
|
settle(exitCode);
|