@wrongstack/tui 0.148.0 → 0.236.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +272 -2
- package/dist/index.js +2584 -297
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -1,17 +1,91 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { writeErr, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, expectDefined as expectDefined$1, wstackGlobalRoot, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, buildChildEnv } from '@wrongstack/core';
|
|
2
2
|
export { buildGoalPreamble } from '@wrongstack/core';
|
|
3
|
-
import { Box
|
|
4
|
-
import
|
|
3
|
+
import { Box as Box$1, useInput, useStdin, useStdout, Text as Text$1, render, useApp, measureElement, Static } from 'ink';
|
|
4
|
+
import * as path4 from 'path';
|
|
5
|
+
import React5, { forwardRef, useState, useEffect, useMemo, memo, useRef, useCallback, useReducer, useLayoutEffect } from 'react';
|
|
5
6
|
import * as fs2 from 'fs/promises';
|
|
6
|
-
import * as path2 from 'path';
|
|
7
7
|
import { routeImagesForModel } from '@wrongstack/runtime/vision';
|
|
8
8
|
import { getIndexState, onIndexStateChange, getProcessRegistry } from '@wrongstack/tools';
|
|
9
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
9
10
|
import { readClipboardImage } from '@wrongstack/runtime/clipboard';
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
11
|
+
import { expectDefined } from '@wrongstack/core/utils';
|
|
12
|
+
import * as v8 from 'v8';
|
|
12
13
|
import { spawn } from 'child_process';
|
|
13
14
|
|
|
14
15
|
// src/run-tui.ts
|
|
16
|
+
|
|
17
|
+
// src/theme.ts
|
|
18
|
+
var pastel = Object.freeze({
|
|
19
|
+
// Base 8
|
|
20
|
+
black: "#11111b",
|
|
21
|
+
red: "#f38ba8",
|
|
22
|
+
green: "#a6e3a1",
|
|
23
|
+
yellow: "#f9e2af",
|
|
24
|
+
blue: "#89b4fa",
|
|
25
|
+
magenta: "#cba6f7",
|
|
26
|
+
cyan: "#94e2d5",
|
|
27
|
+
white: "#cdd6f4",
|
|
28
|
+
// Greys
|
|
29
|
+
gray: "#7f849c",
|
|
30
|
+
grey: "#7f849c",
|
|
31
|
+
// Bright variants — a touch lighter / shifted within the same family
|
|
32
|
+
blackBright: "#585b70",
|
|
33
|
+
redBright: "#eba0ac",
|
|
34
|
+
greenBright: "#b8e8b0",
|
|
35
|
+
yellowBright: "#f5e6b8",
|
|
36
|
+
blueBright: "#89dceb",
|
|
37
|
+
magentaBright: "#b4befe",
|
|
38
|
+
cyanBright: "#99e6da",
|
|
39
|
+
whiteBright: "#ffffff"
|
|
40
|
+
});
|
|
41
|
+
function softColor(color) {
|
|
42
|
+
if (!color) return color;
|
|
43
|
+
return pastel[color] ?? color;
|
|
44
|
+
}
|
|
45
|
+
var theme = Object.freeze({
|
|
46
|
+
accent: pastel.cyan,
|
|
47
|
+
user: pastel.yellow,
|
|
48
|
+
assistant: pastel.cyan,
|
|
49
|
+
tool: pastel.cyan,
|
|
50
|
+
success: pastel.green,
|
|
51
|
+
warn: pastel.yellow,
|
|
52
|
+
error: pastel.red,
|
|
53
|
+
dim: true,
|
|
54
|
+
// Subtle slate border — present but never harsh.
|
|
55
|
+
borderDefault: pastel.blackBright,
|
|
56
|
+
borderActive: pastel.yellow,
|
|
57
|
+
brand: pastel.magenta,
|
|
58
|
+
monitor: {
|
|
59
|
+
fleet: pastel.cyan,
|
|
60
|
+
agents: pastel.magenta,
|
|
61
|
+
worktree: pastel.green,
|
|
62
|
+
phase: pastel.cyan
|
|
63
|
+
},
|
|
64
|
+
// Diff blocks render dark text on a pastel wash (see DiffBlock).
|
|
65
|
+
diffAddBg: pastel.green,
|
|
66
|
+
diffDelBg: pastel.red
|
|
67
|
+
});
|
|
68
|
+
var colorProps = (color, backgroundColor) => {
|
|
69
|
+
const c = softColor(color);
|
|
70
|
+
const bg = softColor(backgroundColor);
|
|
71
|
+
return { ...c ? { color: c } : {}, ...bg ? { backgroundColor: bg } : {} };
|
|
72
|
+
};
|
|
73
|
+
function Text({ color, backgroundColor, ...rest }) {
|
|
74
|
+
return /* @__PURE__ */ jsx(Text$1, { ...rest, ...colorProps(color, backgroundColor) });
|
|
75
|
+
}
|
|
76
|
+
var Box = forwardRef(function Box2({ borderColor, backgroundColor, ...rest }, ref) {
|
|
77
|
+
const bc = softColor(borderColor);
|
|
78
|
+
const bg = softColor(backgroundColor);
|
|
79
|
+
return /* @__PURE__ */ jsx(
|
|
80
|
+
Box$1,
|
|
81
|
+
{
|
|
82
|
+
ref,
|
|
83
|
+
...rest,
|
|
84
|
+
...bc ? { borderColor: bc } : {},
|
|
85
|
+
...bg ? { backgroundColor: bg } : {}
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
});
|
|
15
89
|
var MODE_ICONS = {
|
|
16
90
|
teach: "\u{1F9D1}\u200D\u{1F3EB}",
|
|
17
91
|
brief: "\u26A1",
|
|
@@ -46,12 +120,14 @@ function StatusBar({
|
|
|
46
120
|
startedAt,
|
|
47
121
|
todos,
|
|
48
122
|
plan,
|
|
123
|
+
tasks,
|
|
49
124
|
fleet,
|
|
50
125
|
fleetAgents,
|
|
51
126
|
git,
|
|
52
127
|
subagentCount = 0,
|
|
53
128
|
brain,
|
|
54
129
|
projectName,
|
|
130
|
+
workingDir,
|
|
55
131
|
processCount,
|
|
56
132
|
context,
|
|
57
133
|
hiddenItems,
|
|
@@ -61,7 +137,10 @@ function StatusBar({
|
|
|
61
137
|
modeLabel,
|
|
62
138
|
debugStreamStats,
|
|
63
139
|
enhanceCountdown,
|
|
64
|
-
|
|
140
|
+
nextStepsAutoSubmitCountdown,
|
|
141
|
+
autoProceedCountdown,
|
|
142
|
+
sessionCount,
|
|
143
|
+
mailbox
|
|
65
144
|
}) {
|
|
66
145
|
const { stdout } = useStdout();
|
|
67
146
|
const [termWidth, setTermWidth] = useState(stdout?.columns ?? 90);
|
|
@@ -94,17 +173,19 @@ function StatusBar({
|
|
|
94
173
|
);
|
|
95
174
|
return () => clearInterval(t);
|
|
96
175
|
}, [state]);
|
|
97
|
-
const spinner = expectDefined(SPINNER_FRAMES[spinnerIdx]);
|
|
176
|
+
const spinner = expectDefined$1(SPINNER_FRAMES[spinnerIdx]);
|
|
98
177
|
const { label: stateLabel, color: stateColor } = stateChip(state, fleet?.running ?? 0);
|
|
99
178
|
const statePrefix = state === "idle" || state === "aborting" ? "\u25CF" : spinner;
|
|
100
179
|
const thinking = state === "running" || state === "streaming";
|
|
101
180
|
const hasAutoProceed = autoProceedCountdown != null && autoProceedCountdown > 0;
|
|
102
|
-
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 || hasAutoProceed;
|
|
181
|
+
const hasSecondLine = yolo || autonomy && autonomy !== "off" || startedAt != null || git !== null && git !== void 0 || projectName !== void 0 && projectName.length > 0 || workingDir !== void 0 && workingDir.length > 0 || goalSummary !== null && goalSummary !== void 0 || !!modeLabel || hasAutoProceed;
|
|
103
182
|
const fleetHasActivity = fleet && (fleet.running > 0 || fleet.idle > 0 || fleet.pending > 0 || fleet.completed > 0) || subagentCount > 0;
|
|
104
183
|
const hasBrainActivity = !!brain && brain.state !== "idle";
|
|
105
184
|
const hasDebugStream = !!debugStreamStats;
|
|
106
185
|
const hasEnhanceCountdown = enhanceCountdown != null && enhanceCountdown > 0;
|
|
107
|
-
const
|
|
186
|
+
const hasNextStepsAutoSubmit = nextStepsAutoSubmitCountdown != null && nextStepsAutoSubmitCountdown > 0;
|
|
187
|
+
const hasTaskActivity = tasks && (tasks.pending > 0 || tasks.inProgress > 0 || tasks.completed > 0 || tasks.blocked > 0 || tasks.failed > 0);
|
|
188
|
+
const hasThirdLine = todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) || hasTaskActivity || fleetHasActivity || hasBrainActivity || hasDebugStream || hasEnhanceCountdown || hasNextStepsAutoSubmit;
|
|
108
189
|
return /* @__PURE__ */ jsxs(
|
|
109
190
|
Box,
|
|
110
191
|
{
|
|
@@ -148,13 +229,17 @@ function StatusBar({
|
|
|
148
229
|
/* @__PURE__ */ jsx(Text, { color: "magenta", children: model }),
|
|
149
230
|
context && !hiddenSet.has("context") ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
150
231
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
232
|
+
(() => {
|
|
233
|
+
const ratio = context.used / context.max;
|
|
234
|
+
const clampedRatio = Math.min(ratio, 1);
|
|
235
|
+
const pctText = `${Math.min(Math.round(ratio * 100), 100)}%`;
|
|
236
|
+
return /* @__PURE__ */ jsxs(Text, { color: clampedRatio < 0.6 ? "green" : clampedRatio < 0.75 ? "yellow" : "red", children: [
|
|
237
|
+
"ctx ",
|
|
238
|
+
renderMeter(clampedRatio, 8),
|
|
239
|
+
" ",
|
|
240
|
+
pctText
|
|
241
|
+
] });
|
|
242
|
+
})()
|
|
158
243
|
] }) : null,
|
|
159
244
|
usage && isComfortable ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
160
245
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
@@ -247,8 +332,15 @@ function StatusBar({
|
|
|
247
332
|
projectName
|
|
248
333
|
] })
|
|
249
334
|
] }) : null,
|
|
335
|
+
workingDir && !hiddenSet.has("working_dir") ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
336
|
+
yolo || startedAt != null || projectName || goalSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
337
|
+
/* @__PURE__ */ jsxs(Text, { color: "blue", children: [
|
|
338
|
+
"\u{1F4C2} ",
|
|
339
|
+
workingDir
|
|
340
|
+
] })
|
|
341
|
+
] }) : null,
|
|
250
342
|
goalSummary ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
251
|
-
yolo || startedAt != null || projectName ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
343
|
+
yolo || startedAt != null || projectName || workingDir ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
252
344
|
/* @__PURE__ */ jsxs(
|
|
253
345
|
Text,
|
|
254
346
|
{
|
|
@@ -268,11 +360,11 @@ function StatusBar({
|
|
|
268
360
|
)
|
|
269
361
|
] }) : null,
|
|
270
362
|
modeLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
271
|
-
yolo || autonomy && autonomy !== "off" || eternalStage || startedAt != null || projectName || goalSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
363
|
+
yolo || autonomy && autonomy !== "off" || eternalStage || startedAt != null || projectName || workingDir || goalSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
272
364
|
/* @__PURE__ */ jsx(Text, { color: "cyan", children: modeIcon(modeLabel) })
|
|
273
365
|
] }) : null,
|
|
274
366
|
hasAutoProceed ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
275
|
-
yolo || autonomy && autonomy !== "off" || eternalStage || startedAt != null || projectName || goalSummary || modeLabel ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
367
|
+
yolo || autonomy && autonomy !== "off" || eternalStage || startedAt != null || projectName || workingDir || goalSummary || modeLabel ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
276
368
|
/* @__PURE__ */ jsxs(Text, { color: autoProceedCountdown != null && autoProceedCountdown <= 5 ? "yellow" : "cyan", children: [
|
|
277
369
|
"\u23F3 auto in ",
|
|
278
370
|
autoProceedCountdown,
|
|
@@ -280,16 +372,12 @@ function StatusBar({
|
|
|
280
372
|
] })
|
|
281
373
|
] }) : null,
|
|
282
374
|
git ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
283
|
-
yolo || startedAt != null || projectName ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
375
|
+
yolo || startedAt != null || projectName || workingDir ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
284
376
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
285
377
|
/* @__PURE__ */ jsxs(Text, { color: "magenta", children: [
|
|
286
378
|
"\u2387 ",
|
|
287
379
|
git.branch
|
|
288
380
|
] }),
|
|
289
|
-
git.added > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
290
|
-
" +",
|
|
291
|
-
git.added
|
|
292
|
-
] }) : null,
|
|
293
381
|
git.deleted > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
294
382
|
" -",
|
|
295
383
|
git.deleted
|
|
@@ -299,6 +387,15 @@ function StatusBar({
|
|
|
299
387
|
git.untracked
|
|
300
388
|
] }) : null
|
|
301
389
|
] })
|
|
390
|
+
] }) : null,
|
|
391
|
+
sessionCount != null && sessionCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
392
|
+
yolo || startedAt != null || projectName || workingDir || git ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
393
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
394
|
+
"\u29C9 ",
|
|
395
|
+
sessionCount,
|
|
396
|
+
" session",
|
|
397
|
+
sessionCount === 1 ? "" : "s"
|
|
398
|
+
] })
|
|
302
399
|
] }) : null
|
|
303
400
|
] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
|
|
304
401
|
hasThirdLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
@@ -339,6 +436,36 @@ function StatusBar({
|
|
|
339
436
|
] }) : null
|
|
340
437
|
] })
|
|
341
438
|
] }) : null,
|
|
439
|
+
hasTaskActivity ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
440
|
+
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
441
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
442
|
+
/* @__PURE__ */ jsx(Text, { color: "magenta", children: "\u26A1 " }),
|
|
443
|
+
tasks.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
444
|
+
"\u231B",
|
|
445
|
+
tasks.inProgress
|
|
446
|
+
] }) : null,
|
|
447
|
+
tasks.inProgress > 0 && (tasks.pending > 0 || tasks.blocked > 0) ? " " : "",
|
|
448
|
+
tasks.pending > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
449
|
+
"\u2610",
|
|
450
|
+
tasks.pending
|
|
451
|
+
] }) : null,
|
|
452
|
+
tasks.pending > 0 && tasks.blocked > 0 ? " " : "",
|
|
453
|
+
tasks.blocked > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
454
|
+
"\u2298",
|
|
455
|
+
tasks.blocked
|
|
456
|
+
] }) : null,
|
|
457
|
+
(tasks.pending > 0 || tasks.blocked > 0) && (tasks.completed > 0 || tasks.failed > 0) ? " " : "",
|
|
458
|
+
tasks.completed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
459
|
+
"\u2713",
|
|
460
|
+
tasks.completed
|
|
461
|
+
] }) : null,
|
|
462
|
+
tasks.completed > 0 && tasks.failed > 0 ? " " : "",
|
|
463
|
+
tasks.failed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
464
|
+
"\u2717",
|
|
465
|
+
tasks.failed
|
|
466
|
+
] }) : null
|
|
467
|
+
] })
|
|
468
|
+
] }) : null,
|
|
342
469
|
fleetHasActivity ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
343
470
|
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
344
471
|
fleet ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
@@ -405,9 +532,64 @@ function StatusBar({
|
|
|
405
532
|
enhanceCountdown,
|
|
406
533
|
"s"
|
|
407
534
|
] })
|
|
535
|
+
] }) : null,
|
|
536
|
+
hasNextStepsAutoSubmit && nextStepsAutoSubmitCountdown != null ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
537
|
+
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) || fleetHasActivity || hasBrainActivity || hasDebugStream || hasEnhanceCountdown ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
538
|
+
/* @__PURE__ */ jsxs(Text, { color: nextStepsAutoSubmitCountdown <= 3 ? "yellow" : "cyan", children: [
|
|
539
|
+
"\u23F3 next step in ",
|
|
540
|
+
nextStepsAutoSubmitCountdown,
|
|
541
|
+
"s"
|
|
542
|
+
] })
|
|
408
543
|
] }) : null
|
|
409
544
|
] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
|
|
410
|
-
|
|
545
|
+
mailbox ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
546
|
+
mailbox.unread > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", bold: true, children: [
|
|
547
|
+
"\u2709 ",
|
|
548
|
+
mailbox.unread,
|
|
549
|
+
" new"
|
|
550
|
+
] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2709 0" }),
|
|
551
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
552
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
553
|
+
"\u{1F465} ",
|
|
554
|
+
mailbox.onlineAgents,
|
|
555
|
+
" online"
|
|
556
|
+
] }),
|
|
557
|
+
mailbox.lastSubject ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
558
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
559
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
560
|
+
mailbox.lastFrom ? `${mailbox.lastFrom}: ` : "",
|
|
561
|
+
mailbox.lastSubject.length > 40 ? `${mailbox.lastSubject.slice(0, 37)}\u2026` : mailbox.lastSubject
|
|
562
|
+
] })
|
|
563
|
+
] }) : null,
|
|
564
|
+
fleetAgents && fleetAgents.length > 0 ? fleetAgents.map((a, i) => (
|
|
565
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: agent list is stable per render
|
|
566
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
567
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
568
|
+
" ",
|
|
569
|
+
/* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
|
|
570
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
571
|
+
/* @__PURE__ */ jsx(Text, { dimColor: !a.running, ...a.running ? { color: "yellow" } : {}, children: a.running ? "\u25B6" : "\xB7" }),
|
|
572
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
573
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtElapsed(a.elapsedMs) }),
|
|
574
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
575
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
576
|
+
a.toolCalls,
|
|
577
|
+
"t"
|
|
578
|
+
] }),
|
|
579
|
+
a.tool ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
580
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
581
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: a.tool })
|
|
582
|
+
] }) : null,
|
|
583
|
+
a.extensions && a.extensions > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
584
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
585
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
586
|
+
"\u26A1\xD7",
|
|
587
|
+
a.extensions
|
|
588
|
+
] })
|
|
589
|
+
] }) : null
|
|
590
|
+
] }, i)
|
|
591
|
+
)) : null
|
|
592
|
+
] }) : fleetAgents && fleetAgents.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => (
|
|
411
593
|
// biome-ignore lint/suspicious/noArrayIndexKey: agent list is stable per render
|
|
412
594
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
413
595
|
/* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
|
|
@@ -513,6 +695,32 @@ function EternalStageChip({
|
|
|
513
695
|
] });
|
|
514
696
|
}
|
|
515
697
|
}
|
|
698
|
+
var SB_GAP = 2;
|
|
699
|
+
var SB_PADX = 1;
|
|
700
|
+
function statusBarModelSpan(opts) {
|
|
701
|
+
let col = SB_PADX;
|
|
702
|
+
if (opts.version) {
|
|
703
|
+
col += `WS v${opts.version}`.length + SB_GAP;
|
|
704
|
+
col += 1 + SB_GAP;
|
|
705
|
+
}
|
|
706
|
+
const { label } = stateChip(opts.state, opts.fleetRunning ?? 0);
|
|
707
|
+
col += 2 + label.length + SB_GAP;
|
|
708
|
+
col += 1 + SB_GAP;
|
|
709
|
+
return { start: col, len: opts.model.length };
|
|
710
|
+
}
|
|
711
|
+
function statusBarAutonomySpan(opts) {
|
|
712
|
+
if (!opts.autonomy || opts.autonomy === "off") return null;
|
|
713
|
+
let col = SB_PADX;
|
|
714
|
+
if (opts.yolo) {
|
|
715
|
+
col += "\u26A0 YOLO".length + SB_GAP;
|
|
716
|
+
col += 1 + SB_GAP;
|
|
717
|
+
}
|
|
718
|
+
return { start: col, len: 2 + opts.autonomy.toUpperCase().length };
|
|
719
|
+
}
|
|
720
|
+
function statusBarTodosSpan() {
|
|
721
|
+
const LABEL_MAX = 20;
|
|
722
|
+
return { start: SB_PADX, len: LABEL_MAX };
|
|
723
|
+
}
|
|
516
724
|
function stateChip(state, fleetRunning) {
|
|
517
725
|
if (state === "idle" && fleetRunning > 0) {
|
|
518
726
|
return { label: `agents \u25B6${fleetRunning}`, color: "magenta" };
|
|
@@ -522,18 +730,30 @@ function stateChip(state, fleetRunning) {
|
|
|
522
730
|
return { label: "thinking\u2026", color: "green" };
|
|
523
731
|
}
|
|
524
732
|
var WAVE_COLORS = [
|
|
525
|
-
"#
|
|
526
|
-
|
|
527
|
-
"#
|
|
528
|
-
|
|
529
|
-
"#
|
|
530
|
-
|
|
531
|
-
"#
|
|
532
|
-
|
|
533
|
-
"#
|
|
534
|
-
|
|
535
|
-
"#
|
|
536
|
-
|
|
733
|
+
"#f38ba8",
|
|
734
|
+
// red
|
|
735
|
+
"#eba0ac",
|
|
736
|
+
// maroon
|
|
737
|
+
"#fab387",
|
|
738
|
+
// peach
|
|
739
|
+
"#f9e2af",
|
|
740
|
+
// yellow
|
|
741
|
+
"#a6e3a1",
|
|
742
|
+
// green
|
|
743
|
+
"#94e2d5",
|
|
744
|
+
// teal
|
|
745
|
+
"#89dceb",
|
|
746
|
+
// sky
|
|
747
|
+
"#89b4fa",
|
|
748
|
+
// blue
|
|
749
|
+
"#b4befe",
|
|
750
|
+
// lavender
|
|
751
|
+
"#cba6f7",
|
|
752
|
+
// mauve
|
|
753
|
+
"#f5c2e7",
|
|
754
|
+
// pink
|
|
755
|
+
"#f2cdcd"
|
|
756
|
+
// flamingo
|
|
537
757
|
];
|
|
538
758
|
function WaveText({ text, phase }) {
|
|
539
759
|
return /* @__PURE__ */ jsx(Text, { bold: true, children: Array.from(text).map((ch, i) => (
|
|
@@ -854,12 +1074,12 @@ function ContextBar({
|
|
|
854
1074
|
tokens,
|
|
855
1075
|
maxTokens
|
|
856
1076
|
}) {
|
|
857
|
-
const clamped = Math.max(0, Math.min(
|
|
1077
|
+
const clamped = Math.max(0, Math.min(1, pct));
|
|
858
1078
|
const totalBars = 10;
|
|
859
1079
|
const filled = Math.round(clamped * totalBars);
|
|
860
1080
|
const empty = totalBars - filled;
|
|
861
|
-
const color =
|
|
862
|
-
const pctText =
|
|
1081
|
+
const color = clamped < 0.6 ? "green" : clamped < 0.75 ? "yellow" : "red";
|
|
1082
|
+
const pctText = `${Math.min(Math.round(pct * 100), 100)}%`;
|
|
863
1083
|
const tokenText = tokens ? ` ${fmtTokens2(tokens)}/${fmtTokens2(maxTokens ?? 2e5)}` : "";
|
|
864
1084
|
return /* @__PURE__ */ jsxs(Text, { color, children: [
|
|
865
1085
|
"\u2588".repeat(filled),
|
|
@@ -1467,8 +1687,8 @@ function FilePicker({ query, matches, selected }) {
|
|
|
1467
1687
|
] }, m))
|
|
1468
1688
|
] });
|
|
1469
1689
|
}
|
|
1470
|
-
function highlight(
|
|
1471
|
-
return
|
|
1690
|
+
function highlight(path6, _query) {
|
|
1691
|
+
return path6;
|
|
1472
1692
|
}
|
|
1473
1693
|
function FleetPanel({
|
|
1474
1694
|
entries,
|
|
@@ -1535,29 +1755,103 @@ function FleetPanel({
|
|
|
1535
1755
|
] }) : null
|
|
1536
1756
|
] });
|
|
1537
1757
|
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
},
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
}
|
|
1758
|
+
function fmtTime(iso) {
|
|
1759
|
+
const d = new Date(iso);
|
|
1760
|
+
const now = Date.now();
|
|
1761
|
+
const diff = now - d.getTime();
|
|
1762
|
+
if (diff < 6e4) return "just now";
|
|
1763
|
+
if (diff < 36e5) return `${Math.round(diff / 6e4)}m ago`;
|
|
1764
|
+
if (diff < 864e5) return `${Math.round(diff / 36e5)}h ago`;
|
|
1765
|
+
return d.toLocaleDateString();
|
|
1766
|
+
}
|
|
1767
|
+
function fmtBody(body, maxLen) {
|
|
1768
|
+
const oneLine2 = body.replace(/\n/g, " ");
|
|
1769
|
+
return oneLine2.length > maxLen ? `${oneLine2.slice(0, maxLen - 1)}\u2026` : oneLine2;
|
|
1770
|
+
}
|
|
1771
|
+
var TYPE_ICONS = {
|
|
1772
|
+
note: "\u{1F4DD}",
|
|
1773
|
+
ask: "\u2753",
|
|
1774
|
+
assign: "\u{1F4CB}",
|
|
1775
|
+
steer: "\u{1F504}",
|
|
1776
|
+
btw: "\u{1F4AC}",
|
|
1777
|
+
broadcast: "\u{1F4E2}",
|
|
1778
|
+
status: "\u{1F7E2}",
|
|
1779
|
+
result: "\u2705"
|
|
1780
|
+
};
|
|
1781
|
+
function MailboxPanel({
|
|
1782
|
+
messages,
|
|
1783
|
+
agents,
|
|
1784
|
+
unreadCount,
|
|
1785
|
+
open
|
|
1786
|
+
}) {
|
|
1787
|
+
const { stdout } = useStdout();
|
|
1788
|
+
const [termWidth, setTermWidth] = useState(stdout?.columns ?? 90);
|
|
1789
|
+
useEffect(() => {
|
|
1790
|
+
const handleResize = () => setTermWidth(stdout?.columns ?? 90);
|
|
1791
|
+
handleResize();
|
|
1792
|
+
process.stdout.on("resize", handleResize);
|
|
1793
|
+
return () => {
|
|
1794
|
+
process.stdout.off("resize", handleResize);
|
|
1795
|
+
};
|
|
1796
|
+
}, [stdout]);
|
|
1797
|
+
if (!open) return null;
|
|
1798
|
+
const showMessages = messages.slice(0, 6);
|
|
1799
|
+
const showAgents = agents.slice(0, 8);
|
|
1800
|
+
const maxSubjectLen = Math.max(15, Math.min(30, termWidth - 55));
|
|
1801
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, flexShrink: 0, children: [
|
|
1802
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
1803
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u{1F4EC} Mailbox" }),
|
|
1804
|
+
unreadCount > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", bold: true, children: [
|
|
1805
|
+
unreadCount,
|
|
1806
|
+
" unread"
|
|
1807
|
+
] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "0 unread" }),
|
|
1808
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
1809
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1810
|
+
agents.length,
|
|
1811
|
+
" agent",
|
|
1812
|
+
agents.length === 1 ? "" : "s",
|
|
1813
|
+
" online"
|
|
1814
|
+
] })
|
|
1815
|
+
] }),
|
|
1816
|
+
showMessages.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
1817
|
+
/* @__PURE__ */ jsx(Text, { bold: true, dimColor: true, children: "Messages" }),
|
|
1818
|
+
showMessages.map((m) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1819
|
+
/* @__PURE__ */ jsx(Text, { children: TYPE_ICONS[m.type] ?? "\u{1F4E8}" }),
|
|
1820
|
+
/* @__PURE__ */ jsx(Text, { color: m.readByMe ? void 0 : "yellow", bold: !m.readByMe, children: m.from }),
|
|
1821
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: m.subject.length > maxSubjectLen ? `${m.subject.slice(0, maxSubjectLen - 1)}\u2026` : m.subject }),
|
|
1822
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtBody(m.body, 40) }),
|
|
1823
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtTime(m.timestamp) }),
|
|
1824
|
+
m.readByCount > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1825
|
+
"\u{1F441} ",
|
|
1826
|
+
m.readByCount
|
|
1827
|
+
] }) : /* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: "\u2709 new" }),
|
|
1828
|
+
m.completed ? /* @__PURE__ */ jsx(Text, { color: "green", children: "\u2713" }) : null
|
|
1829
|
+
] }, m.id))
|
|
1830
|
+
] }) : /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No messages yet." }) }),
|
|
1831
|
+
showAgents.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
1832
|
+
/* @__PURE__ */ jsx(Text, { bold: true, dimColor: true, children: "Online agents" }),
|
|
1833
|
+
showAgents.map((a) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1834
|
+
/* @__PURE__ */ jsx(Text, { color: a.online ? "green" : "dim", children: a.online ? "\u25CF" : "\u25CB" }),
|
|
1835
|
+
/* @__PURE__ */ jsx(Text, { children: a.name }),
|
|
1836
|
+
a.role ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1837
|
+
"(",
|
|
1838
|
+
a.role,
|
|
1839
|
+
")"
|
|
1840
|
+
] }) : null,
|
|
1841
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: a.status }),
|
|
1842
|
+
a.currentTool ? /* @__PURE__ */ jsx(Text, { color: "cyan", children: a.currentTool }) : null,
|
|
1843
|
+
a.currentTask ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: a.currentTask.length > 25 ? `${a.currentTask.slice(0, 24)}\u2026` : a.currentTask }) : null,
|
|
1844
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtTime(a.lastSeenAt) }),
|
|
1845
|
+
a.source ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1846
|
+
"[",
|
|
1847
|
+
a.source,
|
|
1848
|
+
"]"
|
|
1849
|
+
] }) : null
|
|
1850
|
+
] }, a.agentId))
|
|
1851
|
+
] }) : null,
|
|
1852
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "/mailbox \u2014 Esc to close" }) })
|
|
1853
|
+
] });
|
|
1854
|
+
}
|
|
1561
1855
|
function helpSections() {
|
|
1562
1856
|
const nav = [];
|
|
1563
1857
|
nav.push(
|
|
@@ -1569,12 +1863,16 @@ function helpSections() {
|
|
|
1569
1863
|
{
|
|
1570
1864
|
title: "Monitors",
|
|
1571
1865
|
entries: [
|
|
1866
|
+
{ keys: "F1", desc: "project switcher (also /project)" },
|
|
1572
1867
|
{ keys: "Ctrl+F / F2", desc: "fleet orchestration monitor" },
|
|
1573
1868
|
{ keys: "Ctrl+G / F3", desc: "agents live monitor" },
|
|
1574
1869
|
{ keys: "Ctrl+T / F4", desc: "worktree monitor" },
|
|
1575
1870
|
{ keys: "F5", desc: "autonomy settings (also Ctrl+S)" },
|
|
1576
1871
|
{ keys: "F6", desc: "todos monitor overlay" },
|
|
1577
1872
|
{ keys: "F7", desc: "queue panel" },
|
|
1873
|
+
{ keys: "F8", desc: "process list overlay" },
|
|
1874
|
+
{ keys: "F9", desc: "goal panel" },
|
|
1875
|
+
{ keys: "F10", desc: "live sessions panel" },
|
|
1578
1876
|
{ keys: "Esc", desc: "close the open monitor / overlay" }
|
|
1579
1877
|
]
|
|
1580
1878
|
},
|
|
@@ -1591,6 +1889,7 @@ function helpSections() {
|
|
|
1591
1889
|
{
|
|
1592
1890
|
title: "Commands",
|
|
1593
1891
|
entries: [
|
|
1892
|
+
{ keys: "/project", desc: "switch projects (also F1)" },
|
|
1594
1893
|
{ keys: "/help", desc: "list all slash commands" },
|
|
1595
1894
|
{ keys: "/model", desc: "switch the active model" },
|
|
1596
1895
|
{ keys: "/fleet", desc: "multi-agent fleet controls" },
|
|
@@ -1607,7 +1906,7 @@ function HelpOverlay() {
|
|
|
1607
1906
|
const keyWidth = Math.max(...sections.flatMap((s2) => s2.entries.map((e) => e.keys.length)), 0);
|
|
1608
1907
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
1609
1908
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1610
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: "
|
|
1909
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: "Keyboard shortcuts" }),
|
|
1611
1910
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 Esc to close" })
|
|
1612
1911
|
] }),
|
|
1613
1912
|
sections.map((sec) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
@@ -2148,14 +2447,14 @@ function computeWidths(allRows, cols, maxWidth, sepWidths) {
|
|
|
2148
2447
|
const cell = row[c] ?? "";
|
|
2149
2448
|
const stripped = stripInlineMarkers(cell);
|
|
2150
2449
|
const total = strWidth(stripped);
|
|
2151
|
-
natural[c] = Math.max(expectDefined
|
|
2450
|
+
natural[c] = Math.max(expectDefined(natural[c]), total);
|
|
2152
2451
|
}
|
|
2153
2452
|
}
|
|
2154
2453
|
if (sepWidths) {
|
|
2155
2454
|
for (let c = 0; c < cols && c < sepWidths.length; c++) {
|
|
2156
2455
|
const sepW = sepWidths[c];
|
|
2157
2456
|
if (sepW != null) {
|
|
2158
|
-
natural[c] = Math.max(expectDefined
|
|
2457
|
+
natural[c] = Math.max(expectDefined(natural[c]), sepW);
|
|
2159
2458
|
}
|
|
2160
2459
|
}
|
|
2161
2460
|
}
|
|
@@ -2167,7 +2466,7 @@ function computeWidths(allRows, cols, maxWidth, sepWidths) {
|
|
|
2167
2466
|
let maxIdx = -1;
|
|
2168
2467
|
let maxVal = MIN_COL_WIDTH;
|
|
2169
2468
|
for (let i = 0; i < cols; i++) {
|
|
2170
|
-
const w = expectDefined
|
|
2469
|
+
const w = expectDefined(widths[i]);
|
|
2171
2470
|
if (w > maxVal) {
|
|
2172
2471
|
maxVal = w;
|
|
2173
2472
|
maxIdx = i;
|
|
@@ -2227,7 +2526,7 @@ function strWidth(s2) {
|
|
|
2227
2526
|
if (i < len) i++;
|
|
2228
2527
|
continue;
|
|
2229
2528
|
}
|
|
2230
|
-
const code = expectDefined
|
|
2529
|
+
const code = expectDefined(s2.codePointAt(i));
|
|
2231
2530
|
const cpLen = code > 65535 ? 2 : 1;
|
|
2232
2531
|
if (code === 8205 || // ZWJ — Zero Width Joiner (emoji sequences)
|
|
2233
2532
|
code === 8203 || // ZWSP — Zero Width Space
|
|
@@ -2299,7 +2598,7 @@ function stripInlineMarkers(text) {
|
|
|
2299
2598
|
}
|
|
2300
2599
|
var ANSI_BOLD = "\x1B[1m";
|
|
2301
2600
|
var ANSI_DIM = "\x1B[2m";
|
|
2302
|
-
var ANSI_CYAN = "\x1B[
|
|
2601
|
+
var ANSI_CYAN = "\x1B[38;2;148;226;213m";
|
|
2303
2602
|
var ANSI_STRIKE = "\x1B[9m";
|
|
2304
2603
|
var ANSI_RESET_ALL = "\x1B[0m";
|
|
2305
2604
|
function applyInlineAnsi(text) {
|
|
@@ -2404,7 +2703,11 @@ function padCell(text, width, align) {
|
|
|
2404
2703
|
}
|
|
2405
2704
|
return displayText + " ".repeat(pad);
|
|
2406
2705
|
}
|
|
2706
|
+
var _parseCache = /* @__PURE__ */ new Map();
|
|
2707
|
+
var _PARSE_CACHE_MAX = 5e3;
|
|
2407
2708
|
function parseInline(text) {
|
|
2709
|
+
const cached = _parseCache.get(text);
|
|
2710
|
+
if (cached) return cached;
|
|
2408
2711
|
const tokens = [];
|
|
2409
2712
|
let plain = "";
|
|
2410
2713
|
let i = 0;
|
|
@@ -2457,6 +2760,15 @@ function parseInline(text) {
|
|
|
2457
2760
|
i += 1;
|
|
2458
2761
|
}
|
|
2459
2762
|
flush();
|
|
2763
|
+
if (_parseCache.size >= _PARSE_CACHE_MAX) {
|
|
2764
|
+
let dropped = 0;
|
|
2765
|
+
const target = Math.floor(_PARSE_CACHE_MAX / 4);
|
|
2766
|
+
for (const key of _parseCache.keys()) {
|
|
2767
|
+
_parseCache.delete(key);
|
|
2768
|
+
if (++dropped >= target) break;
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2771
|
+
_parseCache.set(text, tokens);
|
|
2460
2772
|
return tokens;
|
|
2461
2773
|
}
|
|
2462
2774
|
function InlineLine({ tokens, dim }) {
|
|
@@ -3123,7 +3435,7 @@ function streamBoxRows(text, maxLines, contentWidth) {
|
|
|
3123
3435
|
}
|
|
3124
3436
|
return rows;
|
|
3125
3437
|
}
|
|
3126
|
-
React5.memo(function ToolStreamBox2({
|
|
3438
|
+
var ToolStreamBox = React5.memo(function ToolStreamBox2({
|
|
3127
3439
|
name,
|
|
3128
3440
|
text,
|
|
3129
3441
|
startedAt,
|
|
@@ -3408,10 +3720,11 @@ function Banner({
|
|
|
3408
3720
|
entry
|
|
3409
3721
|
}) {
|
|
3410
3722
|
const cwdShort = shortenPath(entry.cwd, 48);
|
|
3723
|
+
const projectLabel = path4.basename(entry.cwd);
|
|
3411
3724
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 0, children: [
|
|
3412
3725
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
3413
3726
|
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: " \u259F\u259B " }),
|
|
3414
|
-
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children:
|
|
3727
|
+
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: projectLabel }),
|
|
3415
3728
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " v" }),
|
|
3416
3729
|
/* @__PURE__ */ jsx(Text, { children: entry.version })
|
|
3417
3730
|
] }),
|
|
@@ -3439,10 +3752,24 @@ function Banner({
|
|
|
3439
3752
|
] }),
|
|
3440
3753
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
3441
3754
|
/* @__PURE__ */ jsx(Text, { color: "cyan", children: " hints " }),
|
|
3442
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "/help \xB7
|
|
3755
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "/help \xB7 F1 projects \xB7 F10 sessions \xB7 /exit" })
|
|
3443
3756
|
] })
|
|
3444
3757
|
] });
|
|
3445
3758
|
}
|
|
3759
|
+
var NEXT_STEPS_RE = /💡\s*Next steps?\s*\n+((?:\d+\.\s+.+\n?)+)/i;
|
|
3760
|
+
function parseNextSteps(content) {
|
|
3761
|
+
const match = NEXT_STEPS_RE.exec(content);
|
|
3762
|
+
if (!match?.[1]) return { steps: [], stripped: content };
|
|
3763
|
+
const block = match[1];
|
|
3764
|
+
const steps = [];
|
|
3765
|
+
const lines = block.split("\n").filter(Boolean);
|
|
3766
|
+
for (const line of lines) {
|
|
3767
|
+
const m = /^(\d+)\.\s+(.+)$/.exec(line.trim());
|
|
3768
|
+
if (m) steps.push({ index: Number.parseInt(m[1], 10), text: m[2].trim() });
|
|
3769
|
+
}
|
|
3770
|
+
const stripped = content.replace(NEXT_STEPS_RE, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
3771
|
+
return { steps: steps.slice(0, 6), stripped };
|
|
3772
|
+
}
|
|
3446
3773
|
function brainStatusStyle(status) {
|
|
3447
3774
|
switch (status) {
|
|
3448
3775
|
case "thinking":
|
|
@@ -3453,6 +3780,8 @@ function brainStatusStyle(status) {
|
|
|
3453
3780
|
return { icon: "?", color: "yellow" };
|
|
3454
3781
|
case "denied":
|
|
3455
3782
|
return { icon: "\xD7", color: "red" };
|
|
3783
|
+
case "intervention":
|
|
3784
|
+
return { icon: "\u26A1", color: "yellow" };
|
|
3456
3785
|
}
|
|
3457
3786
|
}
|
|
3458
3787
|
function brainRiskColor(risk) {
|
|
@@ -3471,6 +3800,10 @@ var Entry = React5.memo(function Entry2({
|
|
|
3471
3800
|
entry,
|
|
3472
3801
|
termWidth
|
|
3473
3802
|
}) {
|
|
3803
|
+
const nextSteps = useMemo(() => {
|
|
3804
|
+
if (entry.kind !== "assistant") return { steps: [], stripped: "" };
|
|
3805
|
+
return parseNextSteps(entry.text);
|
|
3806
|
+
}, [entry.kind, entry.text]);
|
|
3474
3807
|
switch (entry.kind) {
|
|
3475
3808
|
case "user":
|
|
3476
3809
|
return /* @__PURE__ */ jsx(
|
|
@@ -3499,24 +3832,52 @@ var Entry = React5.memo(function Entry2({
|
|
|
3499
3832
|
);
|
|
3500
3833
|
case "assistant": {
|
|
3501
3834
|
const contentWidth = assistantContentWidth(termWidth);
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3835
|
+
const { steps, stripped } = nextSteps;
|
|
3836
|
+
const hasNext = steps.length > 0;
|
|
3837
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
3838
|
+
/* @__PURE__ */ jsxs(
|
|
3839
|
+
Box,
|
|
3840
|
+
{
|
|
3841
|
+
flexDirection: "column",
|
|
3842
|
+
marginX: MESSAGE_PANEL_MARGIN,
|
|
3843
|
+
marginY: 1,
|
|
3844
|
+
borderStyle: "single",
|
|
3845
|
+
borderTop: false,
|
|
3846
|
+
borderRight: false,
|
|
3847
|
+
borderBottom: hasNext ? false : void 0,
|
|
3848
|
+
borderColor: theme.assistant,
|
|
3849
|
+
paddingLeft: 1,
|
|
3850
|
+
children: [
|
|
3851
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsx(Text, { bold: true, color: theme.assistant, children: "ASSISTANT" }) }),
|
|
3852
|
+
/* @__PURE__ */ jsx(AssistantBody, { text: stripped, termWidth, contentWidth })
|
|
3853
|
+
]
|
|
3854
|
+
}
|
|
3855
|
+
),
|
|
3856
|
+
hasNext && /* @__PURE__ */ jsxs(
|
|
3857
|
+
Box,
|
|
3858
|
+
{
|
|
3859
|
+
flexDirection: "column",
|
|
3860
|
+
marginX: MESSAGE_PANEL_MARGIN,
|
|
3861
|
+
marginY: 1,
|
|
3862
|
+
borderStyle: "single",
|
|
3863
|
+
borderTop: false,
|
|
3864
|
+
borderRight: false,
|
|
3865
|
+
borderBottom: false,
|
|
3866
|
+
borderColor: theme.accent,
|
|
3867
|
+
paddingLeft: 1,
|
|
3868
|
+
children: [
|
|
3869
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
3870
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: "\u{1F4A1} NEXT STEPS " }),
|
|
3871
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "(use /next 1, /next 1 2 3 to select)" })
|
|
3872
|
+
] }),
|
|
3873
|
+
steps.map((s2) => /* @__PURE__ */ jsx(Box, { flexDirection: "row", marginTop: 0, children: /* @__PURE__ */ jsxs(Text, { children: [
|
|
3874
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: ` ${s2.index}. ` }),
|
|
3875
|
+
/* @__PURE__ */ jsx(Text, { children: s2.text })
|
|
3876
|
+
] }) }, s2.index))
|
|
3877
|
+
]
|
|
3878
|
+
}
|
|
3879
|
+
)
|
|
3880
|
+
] });
|
|
3520
3881
|
}
|
|
3521
3882
|
case "tool": {
|
|
3522
3883
|
const argSummary = formatToolArgs(entry.name, entry.input);
|
|
@@ -3571,8 +3932,10 @@ var Entry = React5.memo(function Entry2({
|
|
|
3571
3932
|
diff ? /* @__PURE__ */ jsx(DiffBlock, { rows: diff.rows, hidden: diff.hidden }) : null
|
|
3572
3933
|
] });
|
|
3573
3934
|
}
|
|
3574
|
-
case "info":
|
|
3575
|
-
|
|
3935
|
+
case "info": {
|
|
3936
|
+
const hasAnsi = /\x1b\[/.test(entry.text);
|
|
3937
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: !hasAnsi, children: entry.text });
|
|
3938
|
+
}
|
|
3576
3939
|
case "warn":
|
|
3577
3940
|
return /* @__PURE__ */ jsx(
|
|
3578
3941
|
Box,
|
|
@@ -3681,7 +4044,7 @@ var Entry = React5.memo(function Entry2({
|
|
|
3681
4044
|
}
|
|
3682
4045
|
}
|
|
3683
4046
|
});
|
|
3684
|
-
function History({ entries, streamingText, toolStream }) {
|
|
4047
|
+
function History({ entries, generation, streamingText, toolStream }) {
|
|
3685
4048
|
const { stdout } = useStdout();
|
|
3686
4049
|
const [termSize, setTermSize] = useState({
|
|
3687
4050
|
columns: stdout?.columns ?? 80,
|
|
@@ -3699,10 +4062,209 @@ function History({ entries, streamingText, toolStream }) {
|
|
|
3699
4062
|
const termWidth = termSize.columns;
|
|
3700
4063
|
const tail = streamingText ? tailForDisplay(streamingText, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
3701
4064
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3702
|
-
/* @__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) }),
|
|
4065
|
+
/* @__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) }, generation ?? 0),
|
|
3703
4066
|
/* @__PURE__ */ jsx(Box, { flexGrow: 1, children: tail ? /* @__PURE__ */ jsx(AssistantTail, { text: tail, termWidth }) : null })
|
|
3704
4067
|
] });
|
|
3705
4068
|
}
|
|
4069
|
+
var MAX_MOUNTED = 500;
|
|
4070
|
+
function scrollbarThumb(rows, offset, total) {
|
|
4071
|
+
const scrollable = total > rows;
|
|
4072
|
+
if (!scrollable) return { top: 0, size: rows, scrollable: false };
|
|
4073
|
+
const windowTop = Math.max(0, total - rows - offset);
|
|
4074
|
+
const size = Math.max(1, Math.round(rows / total * rows));
|
|
4075
|
+
const rawTop = Math.round(windowTop / total * rows);
|
|
4076
|
+
const top = Math.max(0, Math.min(rawTop, rows - size));
|
|
4077
|
+
return { top, size, scrollable: true };
|
|
4078
|
+
}
|
|
4079
|
+
function scrollOffsetForTrackRow(rows, total, cell) {
|
|
4080
|
+
if (total <= rows) return 0;
|
|
4081
|
+
const maxOffset = total - rows;
|
|
4082
|
+
const clampedCell = Math.max(0, Math.min(rows - 1, cell));
|
|
4083
|
+
const windowTop = Math.round(clampedCell / Math.max(1, rows - 1) * maxOffset);
|
|
4084
|
+
return Math.max(0, Math.min(maxOffset, maxOffset - windowTop));
|
|
4085
|
+
}
|
|
4086
|
+
function Scrollbar({
|
|
4087
|
+
rows,
|
|
4088
|
+
offset,
|
|
4089
|
+
total
|
|
4090
|
+
}) {
|
|
4091
|
+
const { top: thumbTop, size: thumbSize, scrollable } = scrollbarThumb(rows, offset, total);
|
|
4092
|
+
const cells = [];
|
|
4093
|
+
for (let i = 0; i < rows; i++) {
|
|
4094
|
+
cells.push(i >= thumbTop && i < thumbTop + thumbSize ? "\u2588" : "\u2502");
|
|
4095
|
+
}
|
|
4096
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginLeft: 1, flexShrink: 0, children: cells.map((c, i) => /* @__PURE__ */ jsx(
|
|
4097
|
+
Text,
|
|
4098
|
+
{
|
|
4099
|
+
...scrollable ? { color: theme.accent } : {},
|
|
4100
|
+
dimColor: !scrollable || c === "\u2502",
|
|
4101
|
+
children: c
|
|
4102
|
+
},
|
|
4103
|
+
i
|
|
4104
|
+
)) });
|
|
4105
|
+
}
|
|
4106
|
+
function ScrollableHistory({
|
|
4107
|
+
entries,
|
|
4108
|
+
streamingText,
|
|
4109
|
+
toolStream,
|
|
4110
|
+
scrollOffset,
|
|
4111
|
+
viewportRows,
|
|
4112
|
+
totalLines,
|
|
4113
|
+
onMeasure,
|
|
4114
|
+
maxWidth
|
|
4115
|
+
}) {
|
|
4116
|
+
const { stdout } = useStdout();
|
|
4117
|
+
const rawWidth = stdout?.columns ?? 80;
|
|
4118
|
+
const termWidth = maxWidth ? Math.min(rawWidth, maxWidth) : rawWidth;
|
|
4119
|
+
const tail = streamingText ? tailForDisplay(streamingText, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
4120
|
+
const toolTail = toolStream?.text ? tailForDisplay(toolStream.text, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
4121
|
+
const hiddenCount = Math.max(0, entries.length - MAX_MOUNTED);
|
|
4122
|
+
const shown = hiddenCount > 0 ? entries.slice(-MAX_MOUNTED) : entries;
|
|
4123
|
+
const contentRef = useRef(null);
|
|
4124
|
+
const lastReported = useRef(-1);
|
|
4125
|
+
useLayoutEffect(() => {
|
|
4126
|
+
const node = contentRef.current;
|
|
4127
|
+
if (!node) return;
|
|
4128
|
+
const { height } = measureElement(node);
|
|
4129
|
+
if (height !== lastReported.current) {
|
|
4130
|
+
lastReported.current = height;
|
|
4131
|
+
onMeasure(height);
|
|
4132
|
+
}
|
|
4133
|
+
}, [onMeasure]);
|
|
4134
|
+
const vp = Math.max(1, viewportRows);
|
|
4135
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
4136
|
+
/* @__PURE__ */ jsx(
|
|
4137
|
+
Box,
|
|
4138
|
+
{
|
|
4139
|
+
flexDirection: "column",
|
|
4140
|
+
flexGrow: 1,
|
|
4141
|
+
height: vp,
|
|
4142
|
+
overflowY: "hidden",
|
|
4143
|
+
justifyContent: "flex-end",
|
|
4144
|
+
children: /* @__PURE__ */ jsxs(
|
|
4145
|
+
Box,
|
|
4146
|
+
{
|
|
4147
|
+
ref: contentRef,
|
|
4148
|
+
flexDirection: "column",
|
|
4149
|
+
marginBottom: Math.max(0, scrollOffset),
|
|
4150
|
+
flexShrink: 0,
|
|
4151
|
+
children: [
|
|
4152
|
+
hiddenCount > 0 ? /* @__PURE__ */ jsx(Box, { flexShrink: 0, children: /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: ` \u2191 ${hiddenCount} earlier ${hiddenCount === 1 ? "entry" : "entries"} (scroll lives in this session; full log on disk)` }) }) : null,
|
|
4153
|
+
shown.map((entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, flexShrink: 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth }) }, entry.id)),
|
|
4154
|
+
tail ? /* @__PURE__ */ jsx(AssistantTail, { text: tail, termWidth }) : null,
|
|
4155
|
+
toolTail && toolStream ? /* @__PURE__ */ jsx(
|
|
4156
|
+
ToolStreamBox,
|
|
4157
|
+
{
|
|
4158
|
+
name: toolStream.name,
|
|
4159
|
+
text: toolTail,
|
|
4160
|
+
startedAt: toolStream.startedAt,
|
|
4161
|
+
termWidth
|
|
4162
|
+
}
|
|
4163
|
+
) : null
|
|
4164
|
+
]
|
|
4165
|
+
}
|
|
4166
|
+
)
|
|
4167
|
+
}
|
|
4168
|
+
),
|
|
4169
|
+
/* @__PURE__ */ jsx(Scrollbar, { rows: vp, offset: Math.max(0, scrollOffset), total: totalLines })
|
|
4170
|
+
] });
|
|
4171
|
+
}
|
|
4172
|
+
var MB = 1024 * 1024;
|
|
4173
|
+
function defaultHeapLogPath() {
|
|
4174
|
+
return path4.join(wstackGlobalRoot(), "logs", "heap.jsonl");
|
|
4175
|
+
}
|
|
4176
|
+
function takeHeapSample() {
|
|
4177
|
+
const m = process.memoryUsage();
|
|
4178
|
+
const limit = v8.getHeapStatistics().heap_size_limit || 0;
|
|
4179
|
+
return {
|
|
4180
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4181
|
+
rss: m.rss,
|
|
4182
|
+
heapUsed: m.heapUsed,
|
|
4183
|
+
heapTotal: m.heapTotal,
|
|
4184
|
+
external: m.external,
|
|
4185
|
+
heapLimit: limit,
|
|
4186
|
+
load: limit > 0 ? m.heapUsed / limit : 0
|
|
4187
|
+
};
|
|
4188
|
+
}
|
|
4189
|
+
function startHeapWatchdog(opts = {}) {
|
|
4190
|
+
const sampleEveryMs = opts.sampleEveryMs ?? 6e4;
|
|
4191
|
+
const logEveryMs = opts.logEveryMs ?? 3e5;
|
|
4192
|
+
const logPath = opts.logPath ?? defaultHeapLogPath();
|
|
4193
|
+
const warnAt = opts.warnAt ?? 0.6;
|
|
4194
|
+
const criticalAt = opts.criticalAt ?? 0.85;
|
|
4195
|
+
const REARM_MARGIN = 0.05;
|
|
4196
|
+
let warnArmed = true;
|
|
4197
|
+
let criticalArmed = true;
|
|
4198
|
+
let lastLogAt = 0;
|
|
4199
|
+
let writeChain = Promise.resolve();
|
|
4200
|
+
let dirReady = false;
|
|
4201
|
+
const append = (line) => {
|
|
4202
|
+
writeChain = writeChain.then(async () => {
|
|
4203
|
+
if (!dirReady) {
|
|
4204
|
+
await fs2.mkdir(path4.dirname(logPath), { recursive: true });
|
|
4205
|
+
dirReady = true;
|
|
4206
|
+
}
|
|
4207
|
+
await fs2.appendFile(logPath, `${line}
|
|
4208
|
+
`, "utf8");
|
|
4209
|
+
}).catch(() => void 0);
|
|
4210
|
+
};
|
|
4211
|
+
const tick = () => {
|
|
4212
|
+
const s2 = takeHeapSample();
|
|
4213
|
+
if (s2.load >= criticalAt && criticalArmed) {
|
|
4214
|
+
criticalArmed = false;
|
|
4215
|
+
warnArmed = false;
|
|
4216
|
+
opts.onWarn?.(
|
|
4217
|
+
"critical",
|
|
4218
|
+
`Heap critical: ${Math.round(s2.heapUsed / MB)} MB of ~${Math.round(s2.heapLimit / MB)} MB V8 limit (${Math.round(s2.load * 100)}%). An out-of-memory crash is likely soon \u2014 finish/checkpoint work and restart the session. Diagnostics: ${logPath}`,
|
|
4219
|
+
s2
|
|
4220
|
+
);
|
|
4221
|
+
} else if (s2.load >= warnAt && warnArmed) {
|
|
4222
|
+
warnArmed = false;
|
|
4223
|
+
opts.onWarn?.(
|
|
4224
|
+
"warn",
|
|
4225
|
+
`Heap high: ${Math.round(s2.heapUsed / MB)} MB of ~${Math.round(s2.heapLimit / MB)} MB V8 limit (${Math.round(s2.load * 100)}%). Memory diagnostics are being recorded to ${logPath}`,
|
|
4226
|
+
s2
|
|
4227
|
+
);
|
|
4228
|
+
}
|
|
4229
|
+
if (!warnArmed && s2.load < warnAt - REARM_MARGIN) warnArmed = true;
|
|
4230
|
+
if (!criticalArmed && s2.load < criticalAt - REARM_MARGIN) criticalArmed = true;
|
|
4231
|
+
const due = Date.now() - lastLogAt >= logEveryMs;
|
|
4232
|
+
const crossed = s2.load >= warnAt;
|
|
4233
|
+
if (due || crossed) {
|
|
4234
|
+
lastLogAt = Date.now();
|
|
4235
|
+
let extras = {};
|
|
4236
|
+
try {
|
|
4237
|
+
extras = opts.collectStats?.() ?? {};
|
|
4238
|
+
} catch {
|
|
4239
|
+
}
|
|
4240
|
+
append(JSON.stringify({ pid: process.pid, ...s2, ...extras }));
|
|
4241
|
+
}
|
|
4242
|
+
};
|
|
4243
|
+
const timer = setInterval(tick, sampleEveryMs);
|
|
4244
|
+
timer.unref?.();
|
|
4245
|
+
tick();
|
|
4246
|
+
return () => {
|
|
4247
|
+
clearInterval(timer);
|
|
4248
|
+
};
|
|
4249
|
+
}
|
|
4250
|
+
|
|
4251
|
+
// src/hit-test.ts
|
|
4252
|
+
var SCROLLBAR_HIT_WIDTH = 2;
|
|
4253
|
+
function hitRegion(layout, x, y) {
|
|
4254
|
+
const { termRows, termCols, viewportRows } = layout;
|
|
4255
|
+
if (y < 1 || y > termRows || x < 1 || x > termCols) return null;
|
|
4256
|
+
if (y <= viewportRows) {
|
|
4257
|
+
if (x > termCols - SCROLLBAR_HIT_WIDTH) return { kind: "scrollbar", cell: y - 1 };
|
|
4258
|
+
return { kind: "history", row: y - 1 };
|
|
4259
|
+
}
|
|
4260
|
+
return { kind: "bottom", row: y - viewportRows - 1 };
|
|
4261
|
+
}
|
|
4262
|
+
function statusBarLineRow(opts) {
|
|
4263
|
+
const contentLines = opts.statusBarHeight - opts.headerRows;
|
|
4264
|
+
if (opts.line < 0 || opts.line >= contentLines) return null;
|
|
4265
|
+
const bandTop = opts.termRows - opts.belowHeight - opts.statusBarHeight + 1;
|
|
4266
|
+
return bandTop + opts.headerRows + opts.line;
|
|
4267
|
+
}
|
|
3706
4268
|
|
|
3707
4269
|
// src/fn-keys.ts
|
|
3708
4270
|
function fnKey(data) {
|
|
@@ -3806,6 +4368,45 @@ function layoutInputRows(prompt, value, cursor, width) {
|
|
|
3806
4368
|
if (row.length > 0 || rows.length === 0) rows.push(row);
|
|
3807
4369
|
return rows;
|
|
3808
4370
|
}
|
|
4371
|
+
|
|
4372
|
+
// src/mouse.ts
|
|
4373
|
+
var ESC = String.fromCharCode(27);
|
|
4374
|
+
var MOUSE_CLICK_ON = `${ESC}[?1000h${ESC}[?1006h`;
|
|
4375
|
+
var MOUSE_OFF = `${ESC}[?1003l${ESC}[?1002l${ESC}[?1000l${ESC}[?1006l`;
|
|
4376
|
+
var SGR_MOUSE_GLOBAL = new RegExp(`${ESC}\\[<(\\d+);(\\d+);(\\d+)([Mm])`, "gu");
|
|
4377
|
+
var LEAKED_MOUSE_RE = /\[<\d+;\d+;\d+[Mm]/;
|
|
4378
|
+
function decodeMouse(cb, x, y, released) {
|
|
4379
|
+
const shift = (cb & 4) !== 0;
|
|
4380
|
+
const meta = (cb & 8) !== 0;
|
|
4381
|
+
const ctrl = (cb & 16) !== 0;
|
|
4382
|
+
const motion = (cb & 32) !== 0;
|
|
4383
|
+
const wheel = (cb & 64) !== 0;
|
|
4384
|
+
const low = cb & 3;
|
|
4385
|
+
if (wheel) {
|
|
4386
|
+
const dir = low === 0 ? 1 : low === 1 ? -1 : 0;
|
|
4387
|
+
return { kind: "wheel", button: "none", x, y, wheel: dir, shift, meta, ctrl, motion: false };
|
|
4388
|
+
}
|
|
4389
|
+
const button = low === 0 ? "left" : low === 1 ? "middle" : low === 2 ? "right" : "none";
|
|
4390
|
+
const kind = motion ? "move" : released ? "release" : "press";
|
|
4391
|
+
return { kind, button, x, y, wheel: 0, shift, meta, ctrl, motion };
|
|
4392
|
+
}
|
|
4393
|
+
function parseMouseEvents(data) {
|
|
4394
|
+
const events = [];
|
|
4395
|
+
for (const m of data.matchAll(SGR_MOUSE_GLOBAL)) {
|
|
4396
|
+
events.push(
|
|
4397
|
+
decodeMouse(
|
|
4398
|
+
Number.parseInt(m[1], 10),
|
|
4399
|
+
Number.parseInt(m[2], 10),
|
|
4400
|
+
Number.parseInt(m[3], 10),
|
|
4401
|
+
m[4] === "m"
|
|
4402
|
+
)
|
|
4403
|
+
);
|
|
4404
|
+
}
|
|
4405
|
+
return events;
|
|
4406
|
+
}
|
|
4407
|
+
function isLeakedMouseInput(input) {
|
|
4408
|
+
return LEAKED_MOUSE_RE.test(input);
|
|
4409
|
+
}
|
|
3809
4410
|
function renderRow2(cells, rowKey, promptColor) {
|
|
3810
4411
|
const out = [];
|
|
3811
4412
|
let run = "";
|
|
@@ -3860,14 +4461,6 @@ function isBackspaceOrDelete(data) {
|
|
|
3860
4461
|
if (data === "\x1B[3~") return "delete";
|
|
3861
4462
|
return null;
|
|
3862
4463
|
}
|
|
3863
|
-
function parseMouseWheel(data) {
|
|
3864
|
-
const m = data.match(new RegExp(`^${String.fromCharCode(27)}\\[<(\\d+);(\\d+);(\\d+)([Mm])$`, "u"));
|
|
3865
|
-
if (!m) return null;
|
|
3866
|
-
const cb = Number.parseInt(expectDefined(m[1]), 10);
|
|
3867
|
-
if (cb === 64) return 1;
|
|
3868
|
-
if (cb === 65) return -1;
|
|
3869
|
-
return null;
|
|
3870
|
-
}
|
|
3871
4464
|
var EMPTY_KEY = {
|
|
3872
4465
|
upArrow: false,
|
|
3873
4466
|
downArrow: false,
|
|
@@ -3901,6 +4494,7 @@ var Input = memo(function Input2({
|
|
|
3901
4494
|
const suppressInkDeleteRef = useRef(false);
|
|
3902
4495
|
useInput((input, key) => {
|
|
3903
4496
|
if (disabled) return;
|
|
4497
|
+
if (input && isLeakedMouseInput(input)) return;
|
|
3904
4498
|
if (key.escape && suppressInkEscRef.current) {
|
|
3905
4499
|
suppressInkEscRef.current = false;
|
|
3906
4500
|
return;
|
|
@@ -3964,9 +4558,15 @@ var Input = memo(function Input2({
|
|
|
3964
4558
|
onKey("", { ...EMPTY_KEY, backspace: true, ctrl: true });
|
|
3965
4559
|
return;
|
|
3966
4560
|
}
|
|
3967
|
-
const
|
|
3968
|
-
if (
|
|
3969
|
-
|
|
4561
|
+
const mouseEvents = parseMouseEvents(s2);
|
|
4562
|
+
if (mouseEvents.length > 0) {
|
|
4563
|
+
for (const ev of mouseEvents) {
|
|
4564
|
+
onKey("", {
|
|
4565
|
+
...EMPTY_KEY,
|
|
4566
|
+
mouse: ev,
|
|
4567
|
+
wheelDeltaY: ev.kind === "wheel" ? ev.wheel : void 0
|
|
4568
|
+
});
|
|
4569
|
+
}
|
|
3970
4570
|
return;
|
|
3971
4571
|
}
|
|
3972
4572
|
const fn = fnKey(s2);
|
|
@@ -4272,6 +4872,80 @@ function PhasePanel({ phases, nowTick }) {
|
|
|
4272
4872
|
}
|
|
4273
4873
|
);
|
|
4274
4874
|
}
|
|
4875
|
+
var MAX_VISIBLE2 = 12;
|
|
4876
|
+
function visibleWindow(selected, total) {
|
|
4877
|
+
if (total <= MAX_VISIBLE2) return { start: 0, end: total };
|
|
4878
|
+
const half = Math.floor(MAX_VISIBLE2 / 2);
|
|
4879
|
+
let start = selected - half;
|
|
4880
|
+
let end = start + MAX_VISIBLE2;
|
|
4881
|
+
if (start < 0) {
|
|
4882
|
+
start = 0;
|
|
4883
|
+
end = MAX_VISIBLE2;
|
|
4884
|
+
}
|
|
4885
|
+
if (end > total) {
|
|
4886
|
+
end = total;
|
|
4887
|
+
start = total - MAX_VISIBLE2;
|
|
4888
|
+
}
|
|
4889
|
+
return { start, end };
|
|
4890
|
+
}
|
|
4891
|
+
function ProjectPicker({
|
|
4892
|
+
items,
|
|
4893
|
+
selected,
|
|
4894
|
+
filter,
|
|
4895
|
+
hint
|
|
4896
|
+
}) {
|
|
4897
|
+
const total = items.length;
|
|
4898
|
+
const { start, end } = visibleWindow(selected, total);
|
|
4899
|
+
const visible = items.slice(start, end);
|
|
4900
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, flexShrink: 0, children: [
|
|
4901
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Switch Project \u2501\u2501" }),
|
|
4902
|
+
filter ? /* @__PURE__ */ jsxs(Box, { children: [
|
|
4903
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: "Filter: " }),
|
|
4904
|
+
/* @__PURE__ */ jsx(Text, { children: filter }),
|
|
4905
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2588" })
|
|
4906
|
+
] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "type to filter \xB7 \u2191\u2193 navigate \xB7 Enter select \xB7 Esc cancel" }),
|
|
4907
|
+
start > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4908
|
+
"\u2191 ",
|
|
4909
|
+
start,
|
|
4910
|
+
" more above"
|
|
4911
|
+
] }) : null,
|
|
4912
|
+
visible.map((item) => {
|
|
4913
|
+
const idx = items.indexOf(item);
|
|
4914
|
+
const isSelected = idx === selected;
|
|
4915
|
+
const isDivider = item.key === "__divider__";
|
|
4916
|
+
if (isDivider) {
|
|
4917
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500".repeat(36) }, item.key);
|
|
4918
|
+
}
|
|
4919
|
+
const marker = isSelected ? "\u25B8" : " ";
|
|
4920
|
+
const labelColor = isSelected ? "cyan" : void 0;
|
|
4921
|
+
const metaColor = "grey";
|
|
4922
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
4923
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
4924
|
+
/* @__PURE__ */ jsxs(Text, { inverse: isSelected, color: labelColor, children: [
|
|
4925
|
+
` ${marker} `,
|
|
4926
|
+
/* @__PURE__ */ jsx(Text, { bold: isSelected, children: item.label })
|
|
4927
|
+
] }),
|
|
4928
|
+
item.meta ? /* @__PURE__ */ jsxs(Text, { dimColor: !isSelected, color: isSelected ? "cyan" : metaColor, children: [
|
|
4929
|
+
" ",
|
|
4930
|
+
item.meta
|
|
4931
|
+
] }) : null
|
|
4932
|
+
] }),
|
|
4933
|
+
item.subtitle ? /* @__PURE__ */ jsxs(Text, { dimColor: !isSelected, color: isSelected ? "cyan" : metaColor, children: [
|
|
4934
|
+
" ",
|
|
4935
|
+
item.subtitle
|
|
4936
|
+
] }) : null
|
|
4937
|
+
] }, item.key);
|
|
4938
|
+
}),
|
|
4939
|
+
end < total ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
4940
|
+
"\u2193 ",
|
|
4941
|
+
total - end,
|
|
4942
|
+
" more below \xB7 ",
|
|
4943
|
+
total,
|
|
4944
|
+
" total"
|
|
4945
|
+
] }) : null,
|
|
4946
|
+
hint ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) }) : null
|
|
4947
|
+
] });
|
|
4948
|
+
}
|
|
4275
4949
|
function QueuePanel({ items }) {
|
|
4276
4950
|
const { stdout } = useStdout();
|
|
4277
4951
|
const w = stdout?.columns ?? 80;
|
|
@@ -4502,32 +5176,227 @@ function renderProgressBar(progress, trend) {
|
|
|
4502
5176
|
] })
|
|
4503
5177
|
] });
|
|
4504
5178
|
}
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
5179
|
+
function ResumePicker({
|
|
5180
|
+
sessions,
|
|
5181
|
+
selected,
|
|
5182
|
+
busy,
|
|
5183
|
+
error,
|
|
5184
|
+
hint
|
|
5185
|
+
}) {
|
|
5186
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
5187
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Resume Session \u2501\u2501" }),
|
|
5188
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: busy ? "Resuming selected session\u2026" : "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc cancel" }),
|
|
5189
|
+
error ? /* @__PURE__ */ jsx(Text, { color: "red", children: error }) : null,
|
|
5190
|
+
sessions.length === 0 && !busy ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No sessions found." }) : sessions.map((s2, i) => {
|
|
5191
|
+
const isCurrent = s2.isCurrent;
|
|
5192
|
+
const isSelected = i === selected;
|
|
5193
|
+
const date = s2.startedAt.slice(0, 16).replace("T", " ");
|
|
5194
|
+
const outcomeBadge = s2.outcome === "completed" ? "\u2713 " : s2.outcome === "aborted" ? "\u26A0 " : s2.outcome === "error" ? "\u2717 " : s2.outcome === "timeout" ? "\u23F1 " : " ";
|
|
5195
|
+
const toolStr = s2.toolCallCount > 0 ? `${s2.toolCallCount} tool${s2.toolCallCount === 1 ? "" : "s"}` : "";
|
|
5196
|
+
const iterStr = s2.iterationCount > 0 ? `${s2.iterationCount} iter${s2.iterationCount === 1 ? "" : "s"}` : "";
|
|
5197
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
5198
|
+
/* @__PURE__ */ jsxs(
|
|
5199
|
+
Text,
|
|
5200
|
+
{
|
|
5201
|
+
inverse: isSelected,
|
|
5202
|
+
dimColor: isCurrent ?? false,
|
|
5203
|
+
...isSelected ? { color: isCurrent ? "gray" : "cyan" } : {},
|
|
5204
|
+
children: [
|
|
5205
|
+
isSelected ? "\u203A " : " ",
|
|
5206
|
+
/* @__PURE__ */ jsx(Text, { bold: true, dimColor: isCurrent ?? false, children: s2.id }),
|
|
5207
|
+
isCurrent ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (current)" }) : null,
|
|
5208
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5209
|
+
" ",
|
|
5210
|
+
date
|
|
5211
|
+
] })
|
|
5212
|
+
]
|
|
5213
|
+
}
|
|
5214
|
+
),
|
|
5215
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5216
|
+
isSelected ? " " : " ",
|
|
5217
|
+
outcomeBadge,
|
|
5218
|
+
s2.tokenTotal.toLocaleString(),
|
|
5219
|
+
" tok",
|
|
5220
|
+
toolStr ? ` \xB7 ${toolStr}` : "",
|
|
5221
|
+
iterStr ? ` \xB7 ${iterStr}` : "",
|
|
5222
|
+
s2.toolErrorCount > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
5223
|
+
" \xB7 ",
|
|
5224
|
+
s2.toolErrorCount,
|
|
5225
|
+
" err"
|
|
5226
|
+
] }) : null
|
|
5227
|
+
] }),
|
|
5228
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5229
|
+
isSelected ? " " : " ",
|
|
5230
|
+
s2.title.length > 72 ? `${s2.title.slice(0, 71)}\u2026` : s2.title
|
|
5231
|
+
] })
|
|
5232
|
+
] }, s2.id);
|
|
5233
|
+
}),
|
|
5234
|
+
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
5235
|
+
] });
|
|
4517
5236
|
}
|
|
4518
|
-
function
|
|
4519
|
-
|
|
4520
|
-
|
|
5237
|
+
function statusIcon(status) {
|
|
5238
|
+
switch (status) {
|
|
5239
|
+
case "active":
|
|
5240
|
+
return "\u25CF";
|
|
5241
|
+
case "idle":
|
|
5242
|
+
return "\u25C9";
|
|
5243
|
+
case "closing":
|
|
5244
|
+
return "\u25D0";
|
|
5245
|
+
case "stale":
|
|
5246
|
+
return "\u25CB";
|
|
5247
|
+
default:
|
|
5248
|
+
return "?";
|
|
5249
|
+
}
|
|
4521
5250
|
}
|
|
4522
|
-
function
|
|
4523
|
-
|
|
5251
|
+
function agentIcon(status) {
|
|
5252
|
+
switch (status) {
|
|
5253
|
+
case "running":
|
|
5254
|
+
return "\u25B6";
|
|
5255
|
+
case "streaming":
|
|
5256
|
+
return "\u21BB";
|
|
5257
|
+
case "waiting_user":
|
|
5258
|
+
return "\u23F3";
|
|
5259
|
+
case "error":
|
|
5260
|
+
return "\u2717";
|
|
5261
|
+
case "idle":
|
|
5262
|
+
return "\u25A0";
|
|
5263
|
+
default:
|
|
5264
|
+
return "?";
|
|
5265
|
+
}
|
|
4524
5266
|
}
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
5267
|
+
function fmtDuration2(startedAt) {
|
|
5268
|
+
const diff = Date.now() - new Date(startedAt).getTime();
|
|
5269
|
+
const min = Math.floor(diff / 6e4);
|
|
5270
|
+
if (min < 1) return "<1m";
|
|
5271
|
+
if (min < 60) return `${min}m`;
|
|
5272
|
+
const h = Math.floor(min / 60);
|
|
5273
|
+
if (h < 24) return `${h}h ${min % 60}m`;
|
|
5274
|
+
return `${Math.floor(h / 24)}d ${h % 24}h`;
|
|
5275
|
+
}
|
|
5276
|
+
function SessionsPanel({
|
|
5277
|
+
sessions,
|
|
5278
|
+
busy,
|
|
5279
|
+
selected,
|
|
5280
|
+
resumeConfirm,
|
|
5281
|
+
currentSessionId
|
|
5282
|
+
}) {
|
|
5283
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, flexShrink: 0, children: [
|
|
5284
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
5285
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u29C9 Sessions" }),
|
|
5286
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 F10 or Esc to close" }),
|
|
5287
|
+
busy && /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 loading\u2026" })
|
|
5288
|
+
] }),
|
|
5289
|
+
resumeConfirm ? /* @__PURE__ */ jsxs(Box, { marginY: 1, borderStyle: "single", borderColor: "yellow", paddingX: 1, children: [
|
|
5290
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", bold: true, children: [
|
|
5291
|
+
'\u26A0 Resume session "',
|
|
5292
|
+
resumeConfirm.sessionName,
|
|
5293
|
+
'"?'
|
|
5294
|
+
] }),
|
|
5295
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "This will replace the current conversation. Press Enter to confirm, Esc to cancel." })
|
|
5296
|
+
] }) : null,
|
|
5297
|
+
sessions.length === 0 ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: busy ? "Loading sessions..." : "No live sessions. Open another wstack instance to see it here." }) }) : sessions.map((s2, idx) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
5298
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
5299
|
+
/* @__PURE__ */ jsxs(Text, { inverse: idx === selected, color: s2.status === "active" ? "green" : s2.status === "idle" ? "cyan" : "yellow", children: [
|
|
5300
|
+
s2.sessionId === currentSessionId ? "\u25CF " : "",
|
|
5301
|
+
statusIcon(s2.status),
|
|
5302
|
+
" "
|
|
5303
|
+
] }),
|
|
5304
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: s2.projectName }),
|
|
5305
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5306
|
+
" [",
|
|
5307
|
+
s2.projectSlug,
|
|
5308
|
+
"]"
|
|
5309
|
+
] }),
|
|
5310
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5311
|
+
" \xB7 ",
|
|
5312
|
+
s2.sessionId.slice(0, 8)
|
|
5313
|
+
] }),
|
|
5314
|
+
s2.gitBranch ? /* @__PURE__ */ jsxs(Text, { color: "magenta", children: [
|
|
5315
|
+
" \u2387 ",
|
|
5316
|
+
s2.gitBranch
|
|
5317
|
+
] }) : null,
|
|
5318
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5319
|
+
" \xB7 ",
|
|
5320
|
+
fmtDuration2(s2.startedAt)
|
|
5321
|
+
] }),
|
|
5322
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5323
|
+
" \xB7 PID ",
|
|
5324
|
+
s2.pid
|
|
5325
|
+
] })
|
|
5326
|
+
] }),
|
|
5327
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5328
|
+
" wd: ",
|
|
5329
|
+
s2.workingDir
|
|
5330
|
+
] }),
|
|
5331
|
+
/* @__PURE__ */ jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [
|
|
5332
|
+
s2.agents.slice(0, 8).map((a) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
5333
|
+
/* @__PURE__ */ jsxs(Text, { color: a.status === "running" ? "green" : a.status === "streaming" ? "cyan" : a.status === "error" ? "red" : a.status === "waiting_user" ? "yellow" : "grey", children: [
|
|
5334
|
+
agentIcon(a.status),
|
|
5335
|
+
" "
|
|
5336
|
+
] }),
|
|
5337
|
+
/* @__PURE__ */ jsx(Text, { children: a.name }),
|
|
5338
|
+
a.currentTool ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5339
|
+
" [",
|
|
5340
|
+
a.currentTool,
|
|
5341
|
+
"]"
|
|
5342
|
+
] }) : null,
|
|
5343
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5344
|
+
" \xB7 ",
|
|
5345
|
+
a.iterations,
|
|
5346
|
+
" iter \xB7 ",
|
|
5347
|
+
a.toolCalls,
|
|
5348
|
+
" tools"
|
|
5349
|
+
] })
|
|
5350
|
+
] }, a.id)),
|
|
5351
|
+
s2.agents.length > 8 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5352
|
+
" ... and ",
|
|
5353
|
+
s2.agents.length - 8,
|
|
5354
|
+
" more"
|
|
5355
|
+
] }) : null
|
|
5356
|
+
] })
|
|
5357
|
+
] }, s2.sessionId)),
|
|
5358
|
+
sessions.length > 0 && /* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
|
|
5359
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5360
|
+
sessions.length,
|
|
5361
|
+
" session",
|
|
5362
|
+
sessions.length === 1 ? "" : "s",
|
|
5363
|
+
" \xB7 \u2191\u2193 navigate \xB7 Enter to resume/switch \xB7 Esc close"
|
|
5364
|
+
] }),
|
|
5365
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5366
|
+
"Tip: /sessions kill ",
|
|
5367
|
+
"<id>",
|
|
5368
|
+
" to stop a background session"
|
|
5369
|
+
] })
|
|
5370
|
+
] })
|
|
5371
|
+
] });
|
|
5372
|
+
}
|
|
5373
|
+
var DELAY_PRESETS_MS = [0, 15e3, 3e4, 45e3, 6e4, 12e4];
|
|
5374
|
+
var SETTINGS_MODES = ["off", "suggest", "auto"];
|
|
5375
|
+
var LOG_LEVELS = ["error", "warn", "info", "debug", "trace"];
|
|
5376
|
+
var AUDIT_LEVELS = ["minimal", "standard", "full"];
|
|
5377
|
+
var COMPACTOR_STRATEGIES = ["hybrid", "intelligent", "selective"];
|
|
5378
|
+
var MAX_ITERATIONS_PRESETS = [100, 200, 500, 1e3, 0];
|
|
5379
|
+
var AUTO_PROCEED_MAX_PRESETS = [10, 25, 50, 100, 250, 0];
|
|
5380
|
+
var ENHANCE_DELAY_PRESETS = [3e4, 45e3, 6e4, 9e4, 12e4];
|
|
5381
|
+
var ENHANCE_LANGUAGES = ["original", "english"];
|
|
5382
|
+
function formatSettingsDelay(ms) {
|
|
5383
|
+
if (ms === 0) return "disabled";
|
|
5384
|
+
if (ms >= 6e4) return `${Math.round(ms / 6e4)}m`;
|
|
5385
|
+
return `${Math.round(ms / 1e3)}s`;
|
|
5386
|
+
}
|
|
5387
|
+
function formatMaxIterations(n) {
|
|
5388
|
+
if (n === 0) return "unlimited";
|
|
5389
|
+
return String(n);
|
|
5390
|
+
}
|
|
5391
|
+
function formatEnhanceDelay(ms) {
|
|
5392
|
+
return `${Math.round(ms / 1e3)}s`;
|
|
5393
|
+
}
|
|
5394
|
+
var MODE_DESC = {
|
|
5395
|
+
off: "Agent stops after each turn (normal)",
|
|
5396
|
+
suggest: "Shows next-step suggestions after each turn",
|
|
5397
|
+
auto: "Self-driving \u2014 agent continues automatically"
|
|
4529
5398
|
};
|
|
4530
|
-
var SETTINGS_FIELD_COUNT =
|
|
5399
|
+
var SETTINGS_FIELD_COUNT = 24;
|
|
4531
5400
|
var CONFIG_SCOPES = ["global", "project"];
|
|
4532
5401
|
function SettingsPicker({
|
|
4533
5402
|
field,
|
|
@@ -4552,6 +5421,8 @@ function SettingsPicker({
|
|
|
4552
5421
|
maxIterations,
|
|
4553
5422
|
autoProceedMaxIterations,
|
|
4554
5423
|
enhanceDelayMs,
|
|
5424
|
+
enhanceEnabled,
|
|
5425
|
+
enhanceLanguage,
|
|
4555
5426
|
debugStream,
|
|
4556
5427
|
configScope,
|
|
4557
5428
|
hint
|
|
@@ -4675,6 +5546,16 @@ function SettingsPicker({
|
|
|
4675
5546
|
value: formatEnhanceDelay(enhanceDelayMs),
|
|
4676
5547
|
detail: "Timeout for prompt refinement preview (30s\u2013120s)"
|
|
4677
5548
|
},
|
|
5549
|
+
{
|
|
5550
|
+
label: "Refine",
|
|
5551
|
+
value: boolVal(enhanceEnabled),
|
|
5552
|
+
detail: "Enable prompt refinement before sending"
|
|
5553
|
+
},
|
|
5554
|
+
{
|
|
5555
|
+
label: "Refine language",
|
|
5556
|
+
value: enhanceLanguage,
|
|
5557
|
+
detail: "original (keep language) | english (translate)"
|
|
5558
|
+
},
|
|
4678
5559
|
// ── Debug ──
|
|
4679
5560
|
{ section: "Debug" },
|
|
4680
5561
|
{
|
|
@@ -4836,6 +5717,54 @@ function windowRows(rows, focus, max) {
|
|
|
4836
5717
|
}
|
|
4837
5718
|
return { rows: rows.slice(start, end), start, end, contextHeader };
|
|
4838
5719
|
}
|
|
5720
|
+
function hintsFor(ctx) {
|
|
5721
|
+
if (ctx.confirm) {
|
|
5722
|
+
return [
|
|
5723
|
+
{ key: "y", label: "yes" },
|
|
5724
|
+
{ key: "n", label: "no" },
|
|
5725
|
+
{ key: "a", label: "always" },
|
|
5726
|
+
{ key: "d", label: "deny" }
|
|
5727
|
+
];
|
|
5728
|
+
}
|
|
5729
|
+
if (ctx.picker) {
|
|
5730
|
+
return [
|
|
5731
|
+
{ key: "\u2191\u2193", label: "move" },
|
|
5732
|
+
{ key: "\u21B5", label: "select" },
|
|
5733
|
+
{ key: "Esc", label: "cancel" }
|
|
5734
|
+
];
|
|
5735
|
+
}
|
|
5736
|
+
if (ctx.monitor) {
|
|
5737
|
+
const hints = [
|
|
5738
|
+
{ key: "Esc", label: "close" },
|
|
5739
|
+
{ key: "^F", label: "fleet" },
|
|
5740
|
+
{ key: "^G", label: "agents" },
|
|
5741
|
+
{ key: "^T", label: "worktrees" },
|
|
5742
|
+
{ key: "F6", label: "todos" },
|
|
5743
|
+
{ key: "F9", label: "goal" }
|
|
5744
|
+
];
|
|
5745
|
+
if (ctx.nextPanelHint) {
|
|
5746
|
+
hints.push({ key: ctx.nextPanelHint.key, label: ctx.nextPanelHint.label, discovery: true });
|
|
5747
|
+
}
|
|
5748
|
+
return hints;
|
|
5749
|
+
}
|
|
5750
|
+
const base = [{ key: "?", label: "help" }];
|
|
5751
|
+
if (ctx.managed) base.push({ key: "PgUp/PgDn", label: "scroll" });
|
|
5752
|
+
base.push({ key: "^G", label: "agents" }, { key: "^C", label: "stop" });
|
|
5753
|
+
if (ctx.nextPanelHint) {
|
|
5754
|
+
base.push({ key: ctx.nextPanelHint.key, label: ctx.nextPanelHint.label, discovery: true });
|
|
5755
|
+
}
|
|
5756
|
+
return base;
|
|
5757
|
+
}
|
|
5758
|
+
function KeyHintBar({ context }) {
|
|
5759
|
+
const hints = hintsFor(context);
|
|
5760
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "row", paddingX: 1, children: hints.map((h, i) => (
|
|
5761
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: hints are positional + stable
|
|
5762
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", marginRight: 2, children: [
|
|
5763
|
+
/* @__PURE__ */ jsx(Text, { color: h.discovery ? theme.monitor.agents : theme.accent, children: h.key }),
|
|
5764
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${h.label}` })
|
|
5765
|
+
] }, i)
|
|
5766
|
+
)) });
|
|
5767
|
+
}
|
|
4839
5768
|
function TodosMonitor({ todos }) {
|
|
4840
5769
|
const { stdout } = useStdout();
|
|
4841
5770
|
const done = todos.filter((t) => t.status === "completed").length;
|
|
@@ -5177,7 +6106,7 @@ async function loadIndex(root) {
|
|
|
5177
6106
|
async function walk(root, rel, depth, out) {
|
|
5178
6107
|
if (out.length >= MAX_FILES_INDEXED) return;
|
|
5179
6108
|
if (depth > MAX_DEPTH) return;
|
|
5180
|
-
const dir = rel ?
|
|
6109
|
+
const dir = rel ? path4.join(root, rel) : root;
|
|
5181
6110
|
let entries;
|
|
5182
6111
|
try {
|
|
5183
6112
|
entries = await fs2.readdir(dir, { withFileTypes: true });
|
|
@@ -5749,11 +6678,28 @@ function useBrainEvents(events, dispatch) {
|
|
|
5749
6678
|
const offAnswered = events.on("brain.decision_answered", (payload) => addBrainEntry("answered", payload));
|
|
5750
6679
|
const offAskHuman = events.on("brain.decision_ask_human", (payload) => addBrainEntry("ask_human", payload));
|
|
5751
6680
|
const offDenied = events.on("brain.decision_denied", (payload) => addBrainEntry("denied", payload));
|
|
6681
|
+
const offIntervention = events.on("brain.intervention", (payload) => {
|
|
6682
|
+
const decision = payload.intervened ? `steered the agent (${payload.kind.replace(/_/g, " ")})` : "observed \u2014 no action needed";
|
|
6683
|
+
const rationale = payload.decision.type === "answer" ? payload.decision.rationale : void 0;
|
|
6684
|
+
dispatch({
|
|
6685
|
+
type: "addEntry",
|
|
6686
|
+
entry: {
|
|
6687
|
+
kind: "brain",
|
|
6688
|
+
status: "intervention",
|
|
6689
|
+
source: "monitor",
|
|
6690
|
+
risk: payload.request.risk,
|
|
6691
|
+
question: payload.request.question,
|
|
6692
|
+
decision,
|
|
6693
|
+
rationale
|
|
6694
|
+
}
|
|
6695
|
+
});
|
|
6696
|
+
});
|
|
5752
6697
|
return () => {
|
|
5753
6698
|
offRequested();
|
|
5754
6699
|
offAnswered();
|
|
5755
6700
|
offAskHuman();
|
|
5756
6701
|
offDenied();
|
|
6702
|
+
offIntervention();
|
|
5757
6703
|
};
|
|
5758
6704
|
}, [events, dispatch]);
|
|
5759
6705
|
}
|
|
@@ -5765,7 +6711,7 @@ function labelFor2(labelsRef, id, name) {
|
|
|
5765
6711
|
const n = m.size + 1;
|
|
5766
6712
|
const v = {
|
|
5767
6713
|
label: name && name !== id ? name : `AGENT#${n}`,
|
|
5768
|
-
color: expectDefined(STREAM_COLORS2[(n - 1) % STREAM_COLORS2.length])
|
|
6714
|
+
color: expectDefined$1(STREAM_COLORS2[(n - 1) % STREAM_COLORS2.length])
|
|
5769
6715
|
};
|
|
5770
6716
|
m.set(id, v);
|
|
5771
6717
|
return v;
|
|
@@ -6034,6 +6980,10 @@ function useAutoPhaseEvents(subscribeAutoPhase, dispatch, stateRef) {
|
|
|
6034
6980
|
if (!p.kept) dispatch({ type: "worktreeRemove", handleId: p.handleId });
|
|
6035
6981
|
break;
|
|
6036
6982
|
}
|
|
6983
|
+
case "countdown.tick": {
|
|
6984
|
+
dispatch({ type: "countdownTick", remainingSeconds: payload.remaining });
|
|
6985
|
+
break;
|
|
6986
|
+
}
|
|
6037
6987
|
}
|
|
6038
6988
|
};
|
|
6039
6989
|
return subscribeAutoPhase(handler);
|
|
@@ -6294,6 +7244,52 @@ function buildSteeringPreamble(snapshot, newDirection) {
|
|
|
6294
7244
|
lines.push("]");
|
|
6295
7245
|
return lines.join("\n");
|
|
6296
7246
|
}
|
|
7247
|
+
var MAX_TOOL_STREAM_RETAINED_CHARS = 1e5;
|
|
7248
|
+
var MAX_RETAINED_INPUT_CHARS = 2048;
|
|
7249
|
+
var MAX_RETAINED_INPUT_DEPTH = 4;
|
|
7250
|
+
var MAX_RETAINED_INPUT_ITEMS = 64;
|
|
7251
|
+
function pruneToolInput(value, depth = 0) {
|
|
7252
|
+
if (typeof value === "string") {
|
|
7253
|
+
return value.length > MAX_RETAINED_INPUT_CHARS ? `${value.slice(0, MAX_RETAINED_INPUT_CHARS)}\u2026 [truncated, ${value.length} chars \u2014 full payload in session log]` : value;
|
|
7254
|
+
}
|
|
7255
|
+
if (value === null || typeof value !== "object") return value;
|
|
7256
|
+
if (depth >= MAX_RETAINED_INPUT_DEPTH) return "[pruned: too deep]";
|
|
7257
|
+
if (Array.isArray(value)) {
|
|
7258
|
+
const head = value.slice(0, MAX_RETAINED_INPUT_ITEMS).map((v) => pruneToolInput(v, depth + 1));
|
|
7259
|
+
if (value.length > MAX_RETAINED_INPUT_ITEMS) {
|
|
7260
|
+
head.push(`[pruned: ${value.length - MAX_RETAINED_INPUT_ITEMS} more items]`);
|
|
7261
|
+
}
|
|
7262
|
+
return head;
|
|
7263
|
+
}
|
|
7264
|
+
const out = {};
|
|
7265
|
+
let n = 0;
|
|
7266
|
+
for (const [k, v] of Object.entries(value)) {
|
|
7267
|
+
if (n++ >= MAX_RETAINED_INPUT_ITEMS) {
|
|
7268
|
+
out["\u2026"] = "[pruned: more keys]";
|
|
7269
|
+
break;
|
|
7270
|
+
}
|
|
7271
|
+
out[k] = pruneToolInput(v, depth + 1);
|
|
7272
|
+
}
|
|
7273
|
+
return out;
|
|
7274
|
+
}
|
|
7275
|
+
function firstSelectable(items) {
|
|
7276
|
+
const idx = items.findIndex((it) => it.key !== "__divider__");
|
|
7277
|
+
return idx >= 0 ? idx : 0;
|
|
7278
|
+
}
|
|
7279
|
+
function skipDivider(items, idx, dir) {
|
|
7280
|
+
let i = idx;
|
|
7281
|
+
for (let steps = 0; steps < items.length; steps++) {
|
|
7282
|
+
const item = items[i];
|
|
7283
|
+
if (!item || item.key === "__divider__") {
|
|
7284
|
+
i += dir;
|
|
7285
|
+
if (i < 0) i = items.length - 1;
|
|
7286
|
+
if (i >= items.length) i = 0;
|
|
7287
|
+
continue;
|
|
7288
|
+
}
|
|
7289
|
+
return i;
|
|
7290
|
+
}
|
|
7291
|
+
return idx;
|
|
7292
|
+
}
|
|
6297
7293
|
function reducer(state, action) {
|
|
6298
7294
|
switch (action.type) {
|
|
6299
7295
|
case "addEntry": {
|
|
@@ -6301,7 +7297,8 @@ function reducer(state, action) {
|
|
|
6301
7297
|
if ((e.kind === "user" || e.kind === "assistant" || e.kind === "info" || e.kind === "warn" || e.kind === "error" || e.kind === "turn-summary") && !e.text?.trim()) {
|
|
6302
7298
|
return state;
|
|
6303
7299
|
}
|
|
6304
|
-
const
|
|
7300
|
+
const stored = e.kind === "tool" && e.input !== void 0 ? { ...e, input: pruneToolInput(e.input) } : e;
|
|
7301
|
+
const appended = [...state.entries, { ...stored, id: state.nextId }];
|
|
6305
7302
|
return { ...state, entries: appended, nextId: state.nextId + 1 };
|
|
6306
7303
|
}
|
|
6307
7304
|
case "setBuffer":
|
|
@@ -6425,9 +7422,11 @@ function reducer(state, action) {
|
|
|
6425
7422
|
case "toolStreamAppend": {
|
|
6426
7423
|
const cur = state.toolStream;
|
|
6427
7424
|
if (cur && cur.toolUseId === action.toolUseId) {
|
|
7425
|
+
const combined = cur.text + action.text;
|
|
7426
|
+
const text = combined.length > MAX_TOOL_STREAM_RETAINED_CHARS ? combined.slice(-MAX_TOOL_STREAM_RETAINED_CHARS) : combined;
|
|
6428
7427
|
return {
|
|
6429
7428
|
...state,
|
|
6430
|
-
toolStream: { ...cur, text
|
|
7429
|
+
toolStream: { ...cur, text }
|
|
6431
7430
|
};
|
|
6432
7431
|
}
|
|
6433
7432
|
return {
|
|
@@ -6614,6 +7613,35 @@ function reducer(state, action) {
|
|
|
6614
7613
|
...state,
|
|
6615
7614
|
autonomyPicker: { ...state.autonomyPicker, hint: action.text }
|
|
6616
7615
|
};
|
|
7616
|
+
case "resumePickerOpen":
|
|
7617
|
+
return {
|
|
7618
|
+
...state,
|
|
7619
|
+
resumePicker: { open: true, sessions: action.sessions, selected: 0, busy: false, hint: void 0, error: void 0 }
|
|
7620
|
+
};
|
|
7621
|
+
case "resumePickerClose":
|
|
7622
|
+
return {
|
|
7623
|
+
...state,
|
|
7624
|
+
resumePicker: { open: false, sessions: [], selected: 0, busy: false, hint: void 0, error: void 0 }
|
|
7625
|
+
};
|
|
7626
|
+
case "resumePickerMove": {
|
|
7627
|
+
const nr = state.resumePicker.sessions.length;
|
|
7628
|
+
if (nr === 0) return state;
|
|
7629
|
+
const nextR = (state.resumePicker.selected + action.delta + nr) % nr;
|
|
7630
|
+
return { ...state, resumePicker: { ...state.resumePicker, selected: nextR } };
|
|
7631
|
+
}
|
|
7632
|
+
case "resumePickerBusy":
|
|
7633
|
+
return { ...state, resumePicker: { ...state.resumePicker, busy: action.on } };
|
|
7634
|
+
case "resumePickerHint":
|
|
7635
|
+
return { ...state, resumePicker: { ...state.resumePicker, hint: action.text } };
|
|
7636
|
+
case "resumePickerError":
|
|
7637
|
+
return { ...state, resumePicker: { ...state.resumePicker, error: action.text, busy: false } };
|
|
7638
|
+
case "replaceHistory": {
|
|
7639
|
+
const banners = state.entries.filter((e) => e.kind === "banner");
|
|
7640
|
+
const maxBannerId = banners.length > 0 ? Math.max(...banners.map((b) => b.id)) : 0;
|
|
7641
|
+
const shifted = action.entries.map((e, i) => ({ ...e, id: maxBannerId + 1 + i }));
|
|
7642
|
+
const nextId = maxBannerId + 1 + shifted.length;
|
|
7643
|
+
return { ...state, entries: [...banners, ...shifted], nextId, historyGen: state.historyGen + 1 };
|
|
7644
|
+
}
|
|
6617
7645
|
case "settingsOpen":
|
|
6618
7646
|
return {
|
|
6619
7647
|
...state,
|
|
@@ -6641,6 +7669,8 @@ function reducer(state, action) {
|
|
|
6641
7669
|
maxIterations: action.maxIterations,
|
|
6642
7670
|
autoProceedMaxIterations: action.autoProceedMaxIterations,
|
|
6643
7671
|
enhanceDelayMs: action.enhanceDelayMs,
|
|
7672
|
+
enhanceEnabled: action.enhanceEnabled,
|
|
7673
|
+
enhanceLanguage: action.enhanceLanguage,
|
|
6644
7674
|
debugStream: action.debugStream,
|
|
6645
7675
|
configScope: action.configScope,
|
|
6646
7676
|
hint: void 0
|
|
@@ -6669,13 +7699,13 @@ function reducer(state, action) {
|
|
|
6669
7699
|
const i = SETTINGS_MODES.indexOf(sp.mode);
|
|
6670
7700
|
const base = i < 0 ? 0 : i;
|
|
6671
7701
|
const next = (base + action.delta + SETTINGS_MODES.length) % SETTINGS_MODES.length;
|
|
6672
|
-
return { ...state, settingsPicker: { ...sp, mode: expectDefined(SETTINGS_MODES[next]), hint: void 0 } };
|
|
7702
|
+
return { ...state, settingsPicker: { ...sp, mode: expectDefined$1(SETTINGS_MODES[next]), hint: void 0 } };
|
|
6673
7703
|
}
|
|
6674
7704
|
if (f === 1) {
|
|
6675
7705
|
const j = DELAY_PRESETS_MS.indexOf(sp.delayMs);
|
|
6676
7706
|
const base = j < 0 ? 0 : j;
|
|
6677
7707
|
const next = (base + action.delta + DELAY_PRESETS_MS.length) % DELAY_PRESETS_MS.length;
|
|
6678
|
-
return { ...state, settingsPicker: { ...sp, delayMs: expectDefined(DELAY_PRESETS_MS[next]), hint: void 0 } };
|
|
7708
|
+
return { ...state, settingsPicker: { ...sp, delayMs: expectDefined$1(DELAY_PRESETS_MS[next]), hint: void 0 } };
|
|
6679
7709
|
}
|
|
6680
7710
|
if (f === 2) return { ...state, settingsPicker: { ...sp, titleAnimation: !sp.titleAnimation, hint: void 0 } };
|
|
6681
7711
|
if (f === 3) return { ...state, settingsPicker: { ...sp, yolo: !sp.yolo, hint: void 0 } };
|
|
@@ -6693,50 +7723,99 @@ function reducer(state, action) {
|
|
|
6693
7723
|
const i = COMPACTOR_STRATEGIES.indexOf(sp.contextStrategy);
|
|
6694
7724
|
const base = i < 0 ? 0 : i;
|
|
6695
7725
|
const next = (base + action.delta + COMPACTOR_STRATEGIES.length) % COMPACTOR_STRATEGIES.length;
|
|
6696
|
-
return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined(COMPACTOR_STRATEGIES[next]), hint: void 0 } };
|
|
7726
|
+
return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined$1(COMPACTOR_STRATEGIES[next]), hint: void 0 } };
|
|
6697
7727
|
}
|
|
6698
7728
|
if (f === 15) {
|
|
6699
7729
|
const i = LOG_LEVELS.indexOf(sp.logLevel);
|
|
6700
7730
|
const base = i < 0 ? 0 : i;
|
|
6701
7731
|
const next = (base + action.delta + LOG_LEVELS.length) % LOG_LEVELS.length;
|
|
6702
|
-
return { ...state, settingsPicker: { ...sp, logLevel: expectDefined(LOG_LEVELS[next]), hint: void 0 } };
|
|
7732
|
+
return { ...state, settingsPicker: { ...sp, logLevel: expectDefined$1(LOG_LEVELS[next]), hint: void 0 } };
|
|
6703
7733
|
}
|
|
6704
7734
|
if (f === 16) {
|
|
6705
7735
|
const i = AUDIT_LEVELS.indexOf(sp.auditLevel);
|
|
6706
7736
|
const base = i < 0 ? 0 : i;
|
|
6707
7737
|
const next = (base + action.delta + AUDIT_LEVELS.length) % AUDIT_LEVELS.length;
|
|
6708
|
-
return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined(AUDIT_LEVELS[next]), hint: void 0 } };
|
|
7738
|
+
return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined$1(AUDIT_LEVELS[next]), hint: void 0 } };
|
|
6709
7739
|
}
|
|
6710
7740
|
if (f === 17) return { ...state, settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: void 0 } };
|
|
6711
7741
|
if (f === 18) {
|
|
6712
7742
|
const j = MAX_ITERATIONS_PRESETS.indexOf(sp.maxIterations);
|
|
6713
7743
|
const base = j < 0 ? 0 : j;
|
|
6714
7744
|
const next = (base + action.delta + MAX_ITERATIONS_PRESETS.length) % MAX_ITERATIONS_PRESETS.length;
|
|
6715
|
-
return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
|
|
7745
|
+
return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined$1(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
|
|
6716
7746
|
}
|
|
6717
7747
|
if (f === 19) {
|
|
6718
7748
|
const aj = AUTO_PROCEED_MAX_PRESETS.indexOf(sp.autoProceedMaxIterations);
|
|
6719
7749
|
const abase = aj < 0 ? 0 : aj;
|
|
6720
7750
|
const anext = (abase + action.delta + AUTO_PROCEED_MAX_PRESETS.length) % AUTO_PROCEED_MAX_PRESETS.length;
|
|
6721
|
-
return { ...state, settingsPicker: { ...sp, autoProceedMaxIterations: expectDefined(AUTO_PROCEED_MAX_PRESETS[anext]), hint: void 0 } };
|
|
7751
|
+
return { ...state, settingsPicker: { ...sp, autoProceedMaxIterations: expectDefined$1(AUTO_PROCEED_MAX_PRESETS[anext]), hint: void 0 } };
|
|
6722
7752
|
}
|
|
6723
7753
|
if (f === 20) {
|
|
6724
7754
|
const ej = ENHANCE_DELAY_PRESETS.indexOf(sp.enhanceDelayMs);
|
|
6725
7755
|
const ebase = ej < 0 ? 0 : ej;
|
|
6726
7756
|
const enext = (ebase + action.delta + ENHANCE_DELAY_PRESETS.length) % ENHANCE_DELAY_PRESETS.length;
|
|
6727
|
-
return { ...state, settingsPicker: { ...sp, enhanceDelayMs: expectDefined(ENHANCE_DELAY_PRESETS[enext]), hint: void 0 } };
|
|
7757
|
+
return { ...state, settingsPicker: { ...sp, enhanceDelayMs: expectDefined$1(ENHANCE_DELAY_PRESETS[enext]), hint: void 0 } };
|
|
6728
7758
|
}
|
|
6729
|
-
if (f ===
|
|
6730
|
-
if (f ===
|
|
7759
|
+
if (f === 20) return { ...state, settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 } };
|
|
7760
|
+
if (f === 21) {
|
|
6731
7761
|
const i = CONFIG_SCOPES.indexOf(sp.configScope);
|
|
6732
7762
|
const base = i < 0 ? 0 : i;
|
|
6733
7763
|
const next = (base + action.delta + CONFIG_SCOPES.length) % CONFIG_SCOPES.length;
|
|
6734
|
-
return { ...state, settingsPicker: { ...sp, configScope: expectDefined(CONFIG_SCOPES[next]), hint: void 0 } };
|
|
7764
|
+
return { ...state, settingsPicker: { ...sp, configScope: expectDefined$1(CONFIG_SCOPES[next]), hint: void 0 } };
|
|
7765
|
+
}
|
|
7766
|
+
if (f === 22) return { ...state, settingsPicker: { ...sp, enhanceEnabled: !sp.enhanceEnabled, hint: void 0 } };
|
|
7767
|
+
if (f === 23) {
|
|
7768
|
+
const i = ENHANCE_LANGUAGES.indexOf(sp.enhanceLanguage);
|
|
7769
|
+
const base = i < 0 ? 0 : i;
|
|
7770
|
+
const next = (base + action.delta + ENHANCE_LANGUAGES.length) % ENHANCE_LANGUAGES.length;
|
|
7771
|
+
return { ...state, settingsPicker: { ...sp, enhanceLanguage: expectDefined$1(ENHANCE_LANGUAGES[next]), hint: void 0 } };
|
|
6735
7772
|
}
|
|
6736
7773
|
return state;
|
|
6737
7774
|
}
|
|
6738
7775
|
case "settingsHint":
|
|
6739
7776
|
return { ...state, settingsPicker: { ...state.settingsPicker, hint: action.text } };
|
|
7777
|
+
case "projectPickerOpen":
|
|
7778
|
+
return {
|
|
7779
|
+
...state,
|
|
7780
|
+
projectPicker: {
|
|
7781
|
+
open: true,
|
|
7782
|
+
allItems: action.items,
|
|
7783
|
+
items: action.items,
|
|
7784
|
+
selected: firstSelectable(action.items),
|
|
7785
|
+
filter: "",
|
|
7786
|
+
hint: void 0
|
|
7787
|
+
}
|
|
7788
|
+
};
|
|
7789
|
+
case "projectPickerClose":
|
|
7790
|
+
return {
|
|
7791
|
+
...state,
|
|
7792
|
+
projectPicker: { open: false, allItems: [], items: [], selected: 0, filter: "", hint: void 0 }
|
|
7793
|
+
};
|
|
7794
|
+
case "projectPickerMove": {
|
|
7795
|
+
const cur = state.projectPicker;
|
|
7796
|
+
const list = cur.items;
|
|
7797
|
+
if (list.length === 0) return state;
|
|
7798
|
+
const nextRaw = (cur.selected + action.delta + list.length) % list.length;
|
|
7799
|
+
const next = skipDivider(list, nextRaw, action.delta > 0 ? 1 : -1);
|
|
7800
|
+
return { ...state, projectPicker: { ...cur, selected: next } };
|
|
7801
|
+
}
|
|
7802
|
+
case "projectPickerFilter": {
|
|
7803
|
+
const cur = state.projectPicker;
|
|
7804
|
+
const filtered = action.filter ? cur.allItems.filter(
|
|
7805
|
+
(item) => item.kind !== "project" || item.label.toLowerCase().includes(action.filter.toLowerCase()) || (item.subtitle ?? "").toLowerCase().includes(action.filter.toLowerCase())
|
|
7806
|
+
) : cur.allItems;
|
|
7807
|
+
return {
|
|
7808
|
+
...state,
|
|
7809
|
+
projectPicker: {
|
|
7810
|
+
...cur,
|
|
7811
|
+
filter: action.filter,
|
|
7812
|
+
items: filtered,
|
|
7813
|
+
selected: firstSelectable(filtered)
|
|
7814
|
+
}
|
|
7815
|
+
};
|
|
7816
|
+
}
|
|
7817
|
+
case "projectPickerHint":
|
|
7818
|
+
return { ...state, projectPicker: { ...state.projectPicker, hint: action.text } };
|
|
6740
7819
|
case "confirmOpen":
|
|
6741
7820
|
return { ...state, confirmQueue: [...state.confirmQueue, action.info] };
|
|
6742
7821
|
case "confirmClose":
|
|
@@ -7412,6 +8491,47 @@ function reducer(state, action) {
|
|
|
7412
8491
|
if (state.debugStreamStats === null) return state;
|
|
7413
8492
|
return { ...state, debugStreamStats: null };
|
|
7414
8493
|
}
|
|
8494
|
+
case "toggleSessionsPanel": {
|
|
8495
|
+
return { ...state, sessionsPanelOpen: !state.sessionsPanelOpen };
|
|
8496
|
+
}
|
|
8497
|
+
case "sessionsPanelSet": {
|
|
8498
|
+
return {
|
|
8499
|
+
...state,
|
|
8500
|
+
sessionsPanel: { sessions: action.sessions, busy: false, selected: action.sessions.length > 0 ? 0 : -1 }
|
|
8501
|
+
};
|
|
8502
|
+
}
|
|
8503
|
+
case "sessionsPanelMove": {
|
|
8504
|
+
const cur = state.sessionsPanel;
|
|
8505
|
+
if (cur.sessions.length === 0) return state;
|
|
8506
|
+
const next = (cur.selected + action.delta + cur.sessions.length) % cur.sessions.length;
|
|
8507
|
+
return { ...state, sessionsPanel: { ...cur, selected: next } };
|
|
8508
|
+
}
|
|
8509
|
+
case "sessionsPanelBusy": {
|
|
8510
|
+
return {
|
|
8511
|
+
...state,
|
|
8512
|
+
sessionsPanel: { ...state.sessionsPanel, busy: action.on }
|
|
8513
|
+
};
|
|
8514
|
+
}
|
|
8515
|
+
case "sessionResumeConfirmSet": {
|
|
8516
|
+
return {
|
|
8517
|
+
...state,
|
|
8518
|
+
sessionResumeConfirm: { sessionId: action.sessionId, sessionName: action.sessionName }
|
|
8519
|
+
};
|
|
8520
|
+
}
|
|
8521
|
+
case "sessionResumeConfirmClear": {
|
|
8522
|
+
return { ...state, sessionResumeConfirm: null };
|
|
8523
|
+
}
|
|
8524
|
+
// --- Auto-proceed countdown ---
|
|
8525
|
+
case "countdownTick": {
|
|
8526
|
+
if (action.remainingSeconds <= 0) {
|
|
8527
|
+
return state.countdown ? { ...state, countdown: null } : state;
|
|
8528
|
+
}
|
|
8529
|
+
return { ...state, countdown: { remainingSeconds: action.remainingSeconds } };
|
|
8530
|
+
}
|
|
8531
|
+
case "countdownEnded": {
|
|
8532
|
+
if (state.countdown === null) return state;
|
|
8533
|
+
return { ...state, countdown: null };
|
|
8534
|
+
}
|
|
7415
8535
|
}
|
|
7416
8536
|
}
|
|
7417
8537
|
var INPUT_PROMPT = "\u203A ";
|
|
@@ -7420,7 +8540,7 @@ function selectedSlashCommandLine(picker) {
|
|
|
7420
8540
|
const picked = picker.matches[picker.selected];
|
|
7421
8541
|
return picked ? `/${picked.name}` : null;
|
|
7422
8542
|
}
|
|
7423
|
-
function rehydrateHistory(messages, startId) {
|
|
8543
|
+
function rehydrateHistory(messages, startId, toolCalls) {
|
|
7424
8544
|
const entries = [];
|
|
7425
8545
|
let nextId = startId;
|
|
7426
8546
|
for (const msg of messages) {
|
|
@@ -7434,6 +8554,20 @@ function rehydrateHistory(messages, startId) {
|
|
|
7434
8554
|
entries.push({ id: nextId++, kind: "assistant", text: trimmed });
|
|
7435
8555
|
}
|
|
7436
8556
|
}
|
|
8557
|
+
if (toolCalls && toolCalls.length > 0) {
|
|
8558
|
+
for (const tc of toolCalls) {
|
|
8559
|
+
entries.push({
|
|
8560
|
+
id: nextId++,
|
|
8561
|
+
kind: "tool",
|
|
8562
|
+
name: tc.name,
|
|
8563
|
+
durationMs: tc.durationMs,
|
|
8564
|
+
ok: tc.ok,
|
|
8565
|
+
outputBytes: tc.outputBytes,
|
|
8566
|
+
outputTokens: tc.outputTokens,
|
|
8567
|
+
outputLines: tc.outputLines
|
|
8568
|
+
});
|
|
8569
|
+
}
|
|
8570
|
+
}
|
|
7437
8571
|
return entries;
|
|
7438
8572
|
}
|
|
7439
8573
|
var PASTE_THRESHOLD_CHARS = 200;
|
|
@@ -7448,9 +8582,11 @@ function App({
|
|
|
7448
8582
|
model,
|
|
7449
8583
|
banner = true,
|
|
7450
8584
|
queueStore,
|
|
8585
|
+
onQueueChange,
|
|
7451
8586
|
yolo = false,
|
|
7452
8587
|
chime = false,
|
|
7453
8588
|
confirmExit = true,
|
|
8589
|
+
mouse = false,
|
|
7454
8590
|
enhanceEnabled = true,
|
|
7455
8591
|
enhanceController,
|
|
7456
8592
|
enhanceDelayMs = 15e3,
|
|
@@ -7472,12 +8608,16 @@ function App({
|
|
|
7472
8608
|
getSettings,
|
|
7473
8609
|
saveSettings,
|
|
7474
8610
|
predictNext,
|
|
8611
|
+
onSuggestionsParsed,
|
|
8612
|
+
getSuggestions,
|
|
7475
8613
|
switchAutonomy,
|
|
7476
8614
|
effectiveMaxContext,
|
|
7477
8615
|
onExit,
|
|
7478
8616
|
director,
|
|
7479
8617
|
fleetRoster,
|
|
7480
8618
|
onClearHistory,
|
|
8619
|
+
listSessions,
|
|
8620
|
+
onResumeSession,
|
|
7481
8621
|
fleetStreamController,
|
|
7482
8622
|
statuslineHiddenItems,
|
|
7483
8623
|
setStatuslineHiddenItems,
|
|
@@ -7488,7 +8628,14 @@ function App({
|
|
|
7488
8628
|
modeLabel,
|
|
7489
8629
|
getModeLabel,
|
|
7490
8630
|
registerDebugStreamCallback,
|
|
7491
|
-
restoreDebugStreamCallback
|
|
8631
|
+
restoreDebugStreamCallback,
|
|
8632
|
+
restoredToolCalls,
|
|
8633
|
+
getProjectPickerItems,
|
|
8634
|
+
onProjectSelect,
|
|
8635
|
+
requestExit,
|
|
8636
|
+
getLiveSessions,
|
|
8637
|
+
onSwitchToSession,
|
|
8638
|
+
initialAgentsMonitorOpen
|
|
7492
8639
|
}) {
|
|
7493
8640
|
const { exit } = useApp();
|
|
7494
8641
|
const { stdout } = useStdout();
|
|
@@ -7499,6 +8646,8 @@ function App({
|
|
|
7499
8646
|
const [autonomyLive, setAutonomyLive] = useState(getAutonomy?.() ?? "off");
|
|
7500
8647
|
const [liveModeLabel, setLiveModeLabel] = useState(modeLabel ?? "");
|
|
7501
8648
|
const [hiddenItems, setHiddenItems] = useState(statuslineHiddenItems);
|
|
8649
|
+
const [sessionCount, setSessionCount] = useState(0);
|
|
8650
|
+
const prevBranchRef = useRef(null);
|
|
7502
8651
|
const [indexState, setIndexState] = useState(() => getIndexState());
|
|
7503
8652
|
useEffect(() => {
|
|
7504
8653
|
setIndexState(getIndexState());
|
|
@@ -7549,7 +8698,8 @@ function App({
|
|
|
7549
8698
|
return rehydrateHistory(
|
|
7550
8699
|
visible,
|
|
7551
8700
|
/* startId */
|
|
7552
|
-
1
|
|
8701
|
+
1,
|
|
8702
|
+
restoredToolCalls
|
|
7553
8703
|
);
|
|
7554
8704
|
})();
|
|
7555
8705
|
const initialNextId = 1 + restoredEntries.length;
|
|
@@ -7569,6 +8719,7 @@ function App({
|
|
|
7569
8719
|
] : [],
|
|
7570
8720
|
...restoredEntries
|
|
7571
8721
|
],
|
|
8722
|
+
historyGen: 0,
|
|
7572
8723
|
buffer: "",
|
|
7573
8724
|
cursor: 0,
|
|
7574
8725
|
streamingText: "",
|
|
@@ -7598,7 +8749,9 @@ function App({
|
|
|
7598
8749
|
searchQuery: ""
|
|
7599
8750
|
},
|
|
7600
8751
|
autonomyPicker: { open: false, options: [], selected: 0 },
|
|
7601
|
-
|
|
8752
|
+
resumePicker: { open: false, sessions: [], selected: 0, busy: false, hint: void 0, error: void 0 },
|
|
8753
|
+
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, autoProceedMaxIterations: 50, enhanceDelayMs: 6e4, enhanceEnabled: true, enhanceLanguage: "original", debugStream: false, configScope: "global" },
|
|
8754
|
+
projectPicker: { open: false, allItems: [], items: [], selected: 0, filter: "", hint: void 0 },
|
|
7602
8755
|
confirmQueue: [],
|
|
7603
8756
|
enhance: null,
|
|
7604
8757
|
enhanceEnabled,
|
|
@@ -7620,12 +8773,15 @@ function App({
|
|
|
7620
8773
|
fleetConcurrency: 4,
|
|
7621
8774
|
streamFleet: true,
|
|
7622
8775
|
monitorOpen: false,
|
|
7623
|
-
agentsMonitorOpen: false,
|
|
8776
|
+
agentsMonitorOpen: initialAgentsMonitorOpen ?? false,
|
|
7624
8777
|
helpOpen: false,
|
|
7625
8778
|
todosMonitorOpen: false,
|
|
7626
8779
|
queuePanelOpen: false,
|
|
7627
8780
|
processListOpen: false,
|
|
7628
8781
|
goalPanelOpen: false,
|
|
8782
|
+
sessionsPanelOpen: false,
|
|
8783
|
+
sessionsPanel: { sessions: [], busy: false, selected: -1 },
|
|
8784
|
+
sessionResumeConfirm: null,
|
|
7629
8785
|
collabSession: null,
|
|
7630
8786
|
checkpoints: [],
|
|
7631
8787
|
rewindOverlay: null,
|
|
@@ -7638,7 +8794,8 @@ function App({
|
|
|
7638
8794
|
totalLines: 0,
|
|
7639
8795
|
viewportRows: 0,
|
|
7640
8796
|
pendingNewLines: 0,
|
|
7641
|
-
debugStreamStats: null
|
|
8797
|
+
debugStreamStats: null,
|
|
8798
|
+
countdown: null
|
|
7642
8799
|
});
|
|
7643
8800
|
const builderRef = useRef(null);
|
|
7644
8801
|
if (builderRef.current === null) {
|
|
@@ -7652,9 +8809,23 @@ function App({
|
|
|
7652
8809
|
const lastEnterAtRef = useRef(0);
|
|
7653
8810
|
const tokenPreviewsRef = useRef(/* @__PURE__ */ new Map());
|
|
7654
8811
|
const projectName = React5.useMemo(() => {
|
|
7655
|
-
const base =
|
|
7656
|
-
return base && base !==
|
|
8812
|
+
const base = path4.basename(projectRoot);
|
|
8813
|
+
return base && base !== path4.sep ? base : void 0;
|
|
7657
8814
|
}, [projectRoot]);
|
|
8815
|
+
const [workingDirChip, setWorkingDirChip] = React5.useState(() => {
|
|
8816
|
+
const ctx = agent.ctx;
|
|
8817
|
+
if (ctx.workingDir && ctx.workingDir !== projectRoot) {
|
|
8818
|
+
return path4.relative(projectRoot, ctx.workingDir) || ".";
|
|
8819
|
+
}
|
|
8820
|
+
return void 0;
|
|
8821
|
+
});
|
|
8822
|
+
React5.useEffect(() => {
|
|
8823
|
+
const ctx = agent.ctx;
|
|
8824
|
+
return ctx.onWorkingDirChanged((newDir) => {
|
|
8825
|
+
const rel = path4.relative(projectRoot, newDir) || ".";
|
|
8826
|
+
setWorkingDirChip(rel === "." ? void 0 : rel);
|
|
8827
|
+
});
|
|
8828
|
+
}, [agent.ctx, projectRoot]);
|
|
7658
8829
|
const chimeRef = useRef(chime);
|
|
7659
8830
|
chimeRef.current = chime;
|
|
7660
8831
|
const confirmExitRef = useRef(confirmExit);
|
|
@@ -7666,6 +8837,48 @@ function App({
|
|
|
7666
8837
|
stateRef.current = state;
|
|
7667
8838
|
const draftRef = useRef({ buffer: state.buffer, cursor: state.cursor });
|
|
7668
8839
|
draftRef.current = { buffer: state.buffer, cursor: state.cursor };
|
|
8840
|
+
const [mouseMode, setMouseMode] = useState(mouse);
|
|
8841
|
+
const pickerOverlayOpen = state.modelPicker.open || state.autonomyPicker.open || state.settingsPicker.open || state.projectPicker.open || state.slashPicker.open || state.picker.open;
|
|
8842
|
+
const mouseTrackingOn = mouseMode || pickerOverlayOpen;
|
|
8843
|
+
const mouseWrittenRef = useRef(false);
|
|
8844
|
+
useEffect(() => {
|
|
8845
|
+
if (mouseWrittenRef.current === mouseTrackingOn) return;
|
|
8846
|
+
mouseWrittenRef.current = mouseTrackingOn;
|
|
8847
|
+
try {
|
|
8848
|
+
process.stdout.write(mouseTrackingOn ? MOUSE_CLICK_ON : MOUSE_OFF);
|
|
8849
|
+
} catch {
|
|
8850
|
+
}
|
|
8851
|
+
}, [mouseTrackingOn]);
|
|
8852
|
+
useEffect(
|
|
8853
|
+
() => () => {
|
|
8854
|
+
try {
|
|
8855
|
+
process.stdout.write(MOUSE_OFF);
|
|
8856
|
+
} catch {
|
|
8857
|
+
}
|
|
8858
|
+
},
|
|
8859
|
+
[]
|
|
8860
|
+
);
|
|
8861
|
+
const bottomRegionRef = useRef(null);
|
|
8862
|
+
const statusBarWrapRef = useRef(null);
|
|
8863
|
+
const belowStatusBarRef = useRef(null);
|
|
8864
|
+
const [termRows, setTermRows] = useState(stdout?.rows ?? 24);
|
|
8865
|
+
useEffect(() => {
|
|
8866
|
+
const onResize = () => setTermRows(process.stdout.rows ?? 24);
|
|
8867
|
+
process.stdout.on("resize", onResize);
|
|
8868
|
+
return () => {
|
|
8869
|
+
process.stdout.off("resize", onResize);
|
|
8870
|
+
};
|
|
8871
|
+
}, []);
|
|
8872
|
+
useLayoutEffect(() => {
|
|
8873
|
+
if (!mouseMode) return;
|
|
8874
|
+
const node = bottomRegionRef.current;
|
|
8875
|
+
if (!node) return;
|
|
8876
|
+
const { height } = measureElement(node);
|
|
8877
|
+
const vp = Math.max(1, termRows - height);
|
|
8878
|
+
if (vp !== stateRef.current.viewportRows) {
|
|
8879
|
+
dispatch({ type: "setViewportRows", rows: vp });
|
|
8880
|
+
}
|
|
8881
|
+
});
|
|
7669
8882
|
const handleKeyRef = useRef(null);
|
|
7670
8883
|
const handleRewindTo = React5.useCallback(
|
|
7671
8884
|
async (checkpointIndex) => {
|
|
@@ -7691,6 +8904,35 @@ function App({
|
|
|
7691
8904
|
const t = setInterval(() => setNowTick(Date.now()), 1e4);
|
|
7692
8905
|
return () => clearInterval(t);
|
|
7693
8906
|
}, []);
|
|
8907
|
+
useEffect(() => {
|
|
8908
|
+
const approxChars = (v) => {
|
|
8909
|
+
try {
|
|
8910
|
+
return JSON.stringify(v)?.length ?? 0;
|
|
8911
|
+
} catch {
|
|
8912
|
+
return -1;
|
|
8913
|
+
}
|
|
8914
|
+
};
|
|
8915
|
+
return startHeapWatchdog({
|
|
8916
|
+
collectStats: () => ({
|
|
8917
|
+
historyEntries: stateRef.current.entries.length,
|
|
8918
|
+
historyChars: approxChars(stateRef.current.entries),
|
|
8919
|
+
messages: agent.ctx.state.messages.length,
|
|
8920
|
+
messagesChars: approxChars(agent.ctx.state.messages),
|
|
8921
|
+
runningTools: stateRef.current.runningTools.size,
|
|
8922
|
+
// Bytes queued in stdout's writable buffer. On Windows, TTY writes
|
|
8923
|
+
// are asynchronous — a render storm (e.g. high-frequency tool
|
|
8924
|
+
// progress dispatches) queues whole ANSI frames here as live heap
|
|
8925
|
+
// strings, invisible to every other counter.
|
|
8926
|
+
stdoutQueued: process.stdout.writableLength ?? 0
|
|
8927
|
+
}),
|
|
8928
|
+
onWarn: (level, message) => {
|
|
8929
|
+
dispatch({
|
|
8930
|
+
type: "addEntry",
|
|
8931
|
+
entry: { kind: level === "critical" ? "error" : "warn", text: message }
|
|
8932
|
+
});
|
|
8933
|
+
}
|
|
8934
|
+
});
|
|
8935
|
+
}, [agent.ctx]);
|
|
7694
8936
|
useEffect(() => {
|
|
7695
8937
|
if (state.goalPanelOpen) refreshGoalSummary();
|
|
7696
8938
|
}, [state.goalPanelOpen, nowTick, refreshGoalSummary]);
|
|
@@ -7701,20 +8943,14 @@ function App({
|
|
|
7701
8943
|
return () => clearInterval(t);
|
|
7702
8944
|
}, [state.enhanceBusy]);
|
|
7703
8945
|
const todosRef = useRef(JSON.stringify([]));
|
|
8946
|
+
const staleGuardRef = useRef(JSON.stringify({ a: "", y: false, m: "", model: "", provider: "" }));
|
|
7704
8947
|
useEffect(() => {
|
|
7705
8948
|
const poll = () => {
|
|
7706
|
-
const
|
|
7707
|
-
if (
|
|
7708
|
-
todosRef.current =
|
|
8949
|
+
const todoSnap = JSON.stringify(agent.ctx.todos.map((t2) => ({ s: t2.status })));
|
|
8950
|
+
if (todoSnap !== todosRef.current) {
|
|
8951
|
+
todosRef.current = todoSnap;
|
|
7709
8952
|
setNowTick(Date.now());
|
|
7710
8953
|
}
|
|
7711
|
-
};
|
|
7712
|
-
const t = setInterval(poll, 2e3);
|
|
7713
|
-
return () => clearInterval(t);
|
|
7714
|
-
}, [agent.ctx.todos]);
|
|
7715
|
-
const staleGuardRef = useRef(JSON.stringify({ a: "", y: false, m: "", model: "", provider: "" }));
|
|
7716
|
-
useEffect(() => {
|
|
7717
|
-
const poll = () => {
|
|
7718
8954
|
const a = getAutonomy?.() ?? "off";
|
|
7719
8955
|
const y = getYolo?.() ?? false;
|
|
7720
8956
|
const m = getModeLabel?.() ?? "";
|
|
@@ -7746,23 +8982,162 @@ function App({
|
|
|
7746
8982
|
liveModel,
|
|
7747
8983
|
liveProvider,
|
|
7748
8984
|
agent.ctx.model,
|
|
7749
|
-
agent.ctx.provider
|
|
8985
|
+
agent.ctx.provider,
|
|
8986
|
+
agent.ctx.todos
|
|
7750
8987
|
]);
|
|
7751
8988
|
const [gitInfo, setGitInfo] = React5.useState(null);
|
|
7752
8989
|
useEffect(() => {
|
|
7753
8990
|
let cancelled = false;
|
|
7754
8991
|
const refresh = () => {
|
|
7755
8992
|
readGitInfo(agent.ctx.cwd).then((info) => {
|
|
7756
|
-
if (
|
|
7757
|
-
|
|
8993
|
+
if (cancelled) return;
|
|
8994
|
+
setGitInfo(info);
|
|
8995
|
+
if (info && info.branch) {
|
|
8996
|
+
const prev = prevBranchRef.current;
|
|
8997
|
+
if (prev !== null && prev !== info.branch) {
|
|
8998
|
+
const msg = {
|
|
8999
|
+
role: "user",
|
|
9000
|
+
content: [{ type: "text", text: `[system] Git branch switched: \u2387 ${prev} \u2192 \u2387 ${info.branch}. The working tree is now on branch "${info.branch}". Any file changes from the previous branch are no longer visible.` }]
|
|
9001
|
+
};
|
|
9002
|
+
agent.ctx.messages.push(msg);
|
|
9003
|
+
try {
|
|
9004
|
+
import('@wrongstack/core').then(({ getSessionRegistry }) => {
|
|
9005
|
+
const reg = getSessionRegistry();
|
|
9006
|
+
if (reg) {
|
|
9007
|
+
reg.updateAgents([]).catch(() => {
|
|
9008
|
+
});
|
|
9009
|
+
}
|
|
9010
|
+
}).catch(() => {
|
|
9011
|
+
});
|
|
9012
|
+
} catch {
|
|
9013
|
+
}
|
|
9014
|
+
}
|
|
9015
|
+
prevBranchRef.current = info.branch;
|
|
9016
|
+
}
|
|
9017
|
+
}).catch(() => {
|
|
9018
|
+
if (!cancelled) setGitInfo(null);
|
|
9019
|
+
});
|
|
7758
9020
|
};
|
|
7759
9021
|
refresh();
|
|
9022
|
+
if (gitInfo?.branch && prevBranchRef.current === null) {
|
|
9023
|
+
prevBranchRef.current = gitInfo.branch;
|
|
9024
|
+
}
|
|
7760
9025
|
const t = setInterval(refresh, 5e3);
|
|
7761
9026
|
return () => {
|
|
7762
9027
|
cancelled = true;
|
|
7763
9028
|
clearInterval(t);
|
|
7764
9029
|
};
|
|
7765
|
-
}, [agent.ctx.cwd]);
|
|
9030
|
+
}, [agent.ctx.cwd, gitInfo?.branch]);
|
|
9031
|
+
useEffect(() => {
|
|
9032
|
+
if (!getLiveSessions) return;
|
|
9033
|
+
let cancelled = false;
|
|
9034
|
+
const poll = async () => {
|
|
9035
|
+
try {
|
|
9036
|
+
const sessions = await getLiveSessions();
|
|
9037
|
+
if (!cancelled) setSessionCount(sessions.length);
|
|
9038
|
+
} catch {
|
|
9039
|
+
}
|
|
9040
|
+
};
|
|
9041
|
+
void poll();
|
|
9042
|
+
const t = setInterval(poll, 3e4);
|
|
9043
|
+
if (t.unref) t.unref();
|
|
9044
|
+
return () => {
|
|
9045
|
+
cancelled = true;
|
|
9046
|
+
clearInterval(t);
|
|
9047
|
+
};
|
|
9048
|
+
}, [getLiveSessions]);
|
|
9049
|
+
const [mailboxStatus, setMailboxStatus] = useState({
|
|
9050
|
+
unread: 0,
|
|
9051
|
+
onlineAgents: 0
|
|
9052
|
+
});
|
|
9053
|
+
useEffect(() => {
|
|
9054
|
+
const seenAgents = /* @__PURE__ */ new Set();
|
|
9055
|
+
const unsub1 = events.onPattern("mailbox.unread_count", (_e, payload) => {
|
|
9056
|
+
const p = payload;
|
|
9057
|
+
setMailboxStatus((prev) => ({ ...prev, unread: p?.count ?? 0 }));
|
|
9058
|
+
});
|
|
9059
|
+
const unsub2 = events.onPattern("mailbox.received", (_e, payload) => {
|
|
9060
|
+
const p = payload;
|
|
9061
|
+
setMailboxStatus((prev) => ({
|
|
9062
|
+
...prev,
|
|
9063
|
+
lastSubject: p?.subject ?? prev.lastSubject,
|
|
9064
|
+
lastFrom: p?.from ?? prev.lastFrom
|
|
9065
|
+
}));
|
|
9066
|
+
});
|
|
9067
|
+
const unsub3 = events.onPattern("mailbox.agent_registered", (_e, payload) => {
|
|
9068
|
+
const p = payload;
|
|
9069
|
+
if (p?.agentId) seenAgents.add(p.agentId);
|
|
9070
|
+
setMailboxStatus((prev) => ({ ...prev, onlineAgents: seenAgents.size }));
|
|
9071
|
+
});
|
|
9072
|
+
const unsub4 = events.onPattern("mailbox.agent_heartbeat", (_e, payload) => {
|
|
9073
|
+
const p = payload;
|
|
9074
|
+
if (p?.agentId) seenAgents.add(p.agentId);
|
|
9075
|
+
setMailboxStatus((prev) => ({ ...prev, onlineAgents: seenAgents.size }));
|
|
9076
|
+
});
|
|
9077
|
+
return () => {
|
|
9078
|
+
unsub1();
|
|
9079
|
+
unsub2();
|
|
9080
|
+
unsub3();
|
|
9081
|
+
unsub4();
|
|
9082
|
+
};
|
|
9083
|
+
}, [events]);
|
|
9084
|
+
const [mailboxPanelOpen, setMailboxPanelOpen] = useState(false);
|
|
9085
|
+
const [mailboxMessages, setMailboxMessages] = useState([]);
|
|
9086
|
+
const [mailboxAgents, setMailboxAgents] = useState([]);
|
|
9087
|
+
useEffect(() => {
|
|
9088
|
+
if (!mailboxPanelOpen) return;
|
|
9089
|
+
const poll = async () => {
|
|
9090
|
+
};
|
|
9091
|
+
void poll();
|
|
9092
|
+
const t = setInterval(poll, 1e4);
|
|
9093
|
+
return () => clearInterval(t);
|
|
9094
|
+
}, [mailboxPanelOpen]);
|
|
9095
|
+
useEffect(() => {
|
|
9096
|
+
const unsub = events.onPattern("mailbox.received", (_e, payload) => {
|
|
9097
|
+
const p = payload;
|
|
9098
|
+
if (!p?.messageId) return;
|
|
9099
|
+
setMailboxMessages((prev) => {
|
|
9100
|
+
if (prev.some((m) => m.id === p.messageId)) return prev;
|
|
9101
|
+
return [
|
|
9102
|
+
{
|
|
9103
|
+
id: p.messageId,
|
|
9104
|
+
from: p.from ?? "unknown",
|
|
9105
|
+
to: "*",
|
|
9106
|
+
type: p.type ?? "note",
|
|
9107
|
+
subject: p.subject ?? "",
|
|
9108
|
+
body: "",
|
|
9109
|
+
priority: "normal",
|
|
9110
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9111
|
+
readByCount: 0,
|
|
9112
|
+
readByMe: false,
|
|
9113
|
+
completed: false
|
|
9114
|
+
},
|
|
9115
|
+
...prev
|
|
9116
|
+
].slice(0, 50);
|
|
9117
|
+
});
|
|
9118
|
+
});
|
|
9119
|
+
const unsub2 = events.onPattern("mailbox.agent_registered", (_e, payload) => {
|
|
9120
|
+
const p = payload;
|
|
9121
|
+
if (!p?.agentId) return;
|
|
9122
|
+
setMailboxAgents((prev) => {
|
|
9123
|
+
if (prev.some((a) => a.agentId === p.agentId)) return prev;
|
|
9124
|
+
return [...prev, {
|
|
9125
|
+
agentId: p.agentId,
|
|
9126
|
+
name: p.name ?? p.agentId,
|
|
9127
|
+
role: p.role,
|
|
9128
|
+
sessionId: p.sessionId ?? "?",
|
|
9129
|
+
status: "idle",
|
|
9130
|
+
lastSeenAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9131
|
+
online: true,
|
|
9132
|
+
source: p.source
|
|
9133
|
+
}].slice(0, 30);
|
|
9134
|
+
});
|
|
9135
|
+
});
|
|
9136
|
+
return () => {
|
|
9137
|
+
unsub();
|
|
9138
|
+
unsub2();
|
|
9139
|
+
};
|
|
9140
|
+
}, [events]);
|
|
7766
9141
|
const maxContext = activeMaxContext ?? agent.ctx.provider.capabilities.maxContext;
|
|
7767
9142
|
const currentContextTokens = (tokenCounter?.currentRequestTokens()?.input ?? 0) + (tokenCounter?.currentRequestTokens()?.cacheRead ?? 0);
|
|
7768
9143
|
const contextWindow = useMemo(() => {
|
|
@@ -7850,6 +9225,53 @@ function App({
|
|
|
7850
9225
|
clearInterval(id);
|
|
7851
9226
|
};
|
|
7852
9227
|
}, [agent.ctx.meta]);
|
|
9228
|
+
const [taskCounts, setTaskCounts] = useState(null);
|
|
9229
|
+
useEffect(() => {
|
|
9230
|
+
const taskPath = agent.ctx.meta["task.path"];
|
|
9231
|
+
if (typeof taskPath !== "string" || !taskPath) return;
|
|
9232
|
+
let cancelled = false;
|
|
9233
|
+
const poll = async () => {
|
|
9234
|
+
try {
|
|
9235
|
+
const data = await fs2.readFile(taskPath, "utf8");
|
|
9236
|
+
const parsed = JSON.parse(data);
|
|
9237
|
+
if (cancelled) return;
|
|
9238
|
+
if (!Array.isArray(parsed.tasks)) {
|
|
9239
|
+
setTaskCounts(null);
|
|
9240
|
+
return;
|
|
9241
|
+
}
|
|
9242
|
+
let pending = 0, inProgress = 0, completed = 0, blocked = 0, failed = 0;
|
|
9243
|
+
for (const t of parsed.tasks) {
|
|
9244
|
+
switch (t?.status) {
|
|
9245
|
+
case "completed":
|
|
9246
|
+
completed++;
|
|
9247
|
+
break;
|
|
9248
|
+
case "in_progress":
|
|
9249
|
+
inProgress++;
|
|
9250
|
+
break;
|
|
9251
|
+
case "blocked":
|
|
9252
|
+
blocked++;
|
|
9253
|
+
break;
|
|
9254
|
+
case "failed":
|
|
9255
|
+
failed++;
|
|
9256
|
+
break;
|
|
9257
|
+
default:
|
|
9258
|
+
pending++;
|
|
9259
|
+
break;
|
|
9260
|
+
}
|
|
9261
|
+
}
|
|
9262
|
+
const total = pending + inProgress + completed + blocked + failed;
|
|
9263
|
+
setTaskCounts(total > 0 ? { pending, inProgress, completed, blocked, failed } : null);
|
|
9264
|
+
} catch {
|
|
9265
|
+
if (!cancelled) setTaskCounts(null);
|
|
9266
|
+
}
|
|
9267
|
+
};
|
|
9268
|
+
void poll();
|
|
9269
|
+
const id = setInterval(poll, 3e3);
|
|
9270
|
+
return () => {
|
|
9271
|
+
cancelled = true;
|
|
9272
|
+
clearInterval(id);
|
|
9273
|
+
};
|
|
9274
|
+
}, [agent.ctx.meta]);
|
|
7853
9275
|
const prevAnyOverlayOpen = useRef(false);
|
|
7854
9276
|
const prevEntriesCount = useRef(0);
|
|
7855
9277
|
const prevToolStreamLen = useRef(0);
|
|
@@ -7860,7 +9282,7 @@ function App({
|
|
|
7860
9282
|
}
|
|
7861
9283
|
}, []);
|
|
7862
9284
|
React5.useLayoutEffect(() => {
|
|
7863
|
-
const anyOpenNow = state.picker.open || state.slashPicker.open || state.modelPicker.open || state.autonomyPicker.open || state.settingsPicker.open || state.enhanceBusy || state.enhance != null || state.escConfirm != null || state.confirmQueue.length > 0;
|
|
9285
|
+
const anyOpenNow = state.picker.open || state.slashPicker.open || state.modelPicker.open || state.autonomyPicker.open || state.resumePicker.open || state.settingsPicker.open || state.enhanceBusy || state.enhance != null || state.escConfirm != null || state.confirmQueue.length > 0;
|
|
7864
9286
|
const overlayClosed = prevAnyOverlayOpen.current && !anyOpenNow;
|
|
7865
9287
|
const newEntryCommitted = state.entries.length > prevEntriesCount.current;
|
|
7866
9288
|
const curToolStreamLen = state.toolStream?.text.length ?? 0;
|
|
@@ -7887,22 +9309,29 @@ function App({
|
|
|
7887
9309
|
]);
|
|
7888
9310
|
const resizeGateRef = useRef(0);
|
|
7889
9311
|
const preResizePanelsRef = useRef(null);
|
|
9312
|
+
const resizeRestoreTimerRef = useRef(null);
|
|
9313
|
+
const mountedRef = useRef(true);
|
|
7890
9314
|
useEffect(() => {
|
|
7891
9315
|
const handleResize = () => {
|
|
7892
9316
|
const seq = ++resizeGateRef.current;
|
|
7893
9317
|
preResizePanelsRef.current = {
|
|
7894
9318
|
settings: stateRef.current.settingsPicker.open,
|
|
9319
|
+
projectPicker: stateRef.current.projectPicker.open,
|
|
7895
9320
|
help: stateRef.current.helpOpen,
|
|
7896
9321
|
monitor: stateRef.current.monitorOpen,
|
|
7897
9322
|
agents: stateRef.current.agentsMonitorOpen,
|
|
7898
9323
|
worktree: stateRef.current.worktreeMonitorOpen,
|
|
7899
9324
|
todos: stateRef.current.todosMonitorOpen,
|
|
7900
9325
|
queue: stateRef.current.queuePanelOpen,
|
|
7901
|
-
processList: stateRef.current.processListOpen
|
|
9326
|
+
processList: stateRef.current.processListOpen,
|
|
9327
|
+
goalPanel: stateRef.current.goalPanelOpen,
|
|
9328
|
+
sessionsPanel: stateRef.current.sessionsPanelOpen
|
|
7902
9329
|
};
|
|
7903
9330
|
if (stateRef.current.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
9331
|
+
if (stateRef.current.projectPicker.open) dispatch({ type: "projectPickerClose" });
|
|
7904
9332
|
if (stateRef.current.modelPicker.open) dispatch({ type: "modelPickerClose" });
|
|
7905
9333
|
if (stateRef.current.autonomyPicker.open) dispatch({ type: "autonomyPickerClose" });
|
|
9334
|
+
if (stateRef.current.resumePicker.open) dispatch({ type: "resumePickerClose" });
|
|
7906
9335
|
if (stateRef.current.slashPicker.open) dispatch({ type: "slashPickerClose" });
|
|
7907
9336
|
if (stateRef.current.picker.open) dispatch({ type: "pickerClose" });
|
|
7908
9337
|
if (stateRef.current.rewindOverlay) dispatch({ type: "rewindOverlayClose" });
|
|
@@ -7913,8 +9342,11 @@ function App({
|
|
|
7913
9342
|
if (stateRef.current.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
7914
9343
|
if (stateRef.current.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
7915
9344
|
if (stateRef.current.processListOpen) dispatch({ type: "toggleProcessList" });
|
|
9345
|
+
if (stateRef.current.goalPanelOpen) dispatch({ type: "toggleGoalPanel" });
|
|
9346
|
+
if (stateRef.current.sessionsPanelOpen) dispatch({ type: "toggleSessionsPanel" });
|
|
7916
9347
|
eraseLiveRegion();
|
|
7917
|
-
setTimeout(() => {
|
|
9348
|
+
resizeRestoreTimerRef.current = setTimeout(() => {
|
|
9349
|
+
if (!mountedRef.current) return;
|
|
7918
9350
|
if (resizeGateRef.current !== seq) return;
|
|
7919
9351
|
const prev = preResizePanelsRef.current;
|
|
7920
9352
|
if (!prev) return;
|
|
@@ -7943,10 +9375,16 @@ function App({
|
|
|
7943
9375
|
maxIterations: sp.maxIterations,
|
|
7944
9376
|
autoProceedMaxIterations: sp.autoProceedMaxIterations,
|
|
7945
9377
|
enhanceDelayMs: sp.enhanceDelayMs,
|
|
9378
|
+
enhanceEnabled: sp.enhanceEnabled,
|
|
9379
|
+
enhanceLanguage: sp.enhanceLanguage,
|
|
7946
9380
|
debugStream: sp.debugStream,
|
|
7947
9381
|
configScope: sp.configScope
|
|
7948
9382
|
});
|
|
7949
9383
|
}
|
|
9384
|
+
if (prev.projectPicker) {
|
|
9385
|
+
const pp = stateRef.current.projectPicker;
|
|
9386
|
+
dispatch({ type: "projectPickerOpen", items: pp.allItems });
|
|
9387
|
+
}
|
|
7950
9388
|
if (prev.help) dispatch({ type: "toggleHelp" });
|
|
7951
9389
|
if (prev.monitor) dispatch({ type: "toggleMonitor" });
|
|
7952
9390
|
if (prev.agents) dispatch({ type: "toggleAgentsMonitor" });
|
|
@@ -7954,11 +9392,19 @@ function App({
|
|
|
7954
9392
|
if (prev.todos) dispatch({ type: "toggleTodosMonitor" });
|
|
7955
9393
|
if (prev.queue) dispatch({ type: "toggleQueuePanel" });
|
|
7956
9394
|
if (prev.processList) dispatch({ type: "toggleProcessList" });
|
|
9395
|
+
if (prev.goalPanel) dispatch({ type: "toggleGoalPanel" });
|
|
9396
|
+
if (prev.sessionsPanel) dispatch({ type: "toggleSessionsPanel" });
|
|
7957
9397
|
preResizePanelsRef.current = null;
|
|
9398
|
+
resizeRestoreTimerRef.current = null;
|
|
7958
9399
|
}, 300);
|
|
7959
9400
|
};
|
|
7960
9401
|
process.stdout.on("resize", handleResize);
|
|
7961
9402
|
return () => {
|
|
9403
|
+
if (resizeRestoreTimerRef.current) {
|
|
9404
|
+
clearTimeout(resizeRestoreTimerRef.current);
|
|
9405
|
+
resizeRestoreTimerRef.current = null;
|
|
9406
|
+
}
|
|
9407
|
+
mountedRef.current = false;
|
|
7962
9408
|
process.stdout.off("resize", handleResize);
|
|
7963
9409
|
};
|
|
7964
9410
|
}, [eraseLiveRegion]);
|
|
@@ -8059,7 +9505,7 @@ function App({
|
|
|
8059
9505
|
dispatch({ type: "pickerClose" });
|
|
8060
9506
|
return;
|
|
8061
9507
|
}
|
|
8062
|
-
const absPath =
|
|
9508
|
+
const absPath = path4.isAbsolute(picked) ? picked : path4.join(projectRoot, picked);
|
|
8063
9509
|
try {
|
|
8064
9510
|
const data = await fs2.readFile(absPath, "utf8");
|
|
8065
9511
|
const token = await builder.registerFile({
|
|
@@ -8120,6 +9566,9 @@ function App({
|
|
|
8120
9566
|
if (!queueStore) return;
|
|
8121
9567
|
queueStore.write(state.queue.map(({ displayText, blocks }) => ({ displayText, blocks }))).catch(() => void 0);
|
|
8122
9568
|
}, [state.queue, queueStore]);
|
|
9569
|
+
useEffect(() => {
|
|
9570
|
+
onQueueChange?.(state.queue.map((q) => q.displayText));
|
|
9571
|
+
}, [state.queue, onQueueChange]);
|
|
8123
9572
|
useEffect(() => {
|
|
8124
9573
|
const cmd = createQueueSlashCommand({
|
|
8125
9574
|
getQueue: () => stateRef.current.queue,
|
|
@@ -8255,6 +9704,28 @@ function App({
|
|
|
8255
9704
|
const providers = await getPickableProviders();
|
|
8256
9705
|
dispatch({ type: "modelPickerOpen", providers });
|
|
8257
9706
|
}, [getPickableProviders]);
|
|
9707
|
+
const openProjectPicker = React5.useCallback(async () => {
|
|
9708
|
+
if (!getProjectPickerItems) return;
|
|
9709
|
+
const items = await getProjectPickerItems();
|
|
9710
|
+
dispatch({ type: "projectPickerOpen", items });
|
|
9711
|
+
}, [getProjectPickerItems]);
|
|
9712
|
+
const loadLiveSessions = React5.useCallback(async () => {
|
|
9713
|
+
if (!getLiveSessions) return;
|
|
9714
|
+
dispatch({ type: "sessionsPanelBusy", on: true });
|
|
9715
|
+
try {
|
|
9716
|
+
const sessions = await getLiveSessions();
|
|
9717
|
+
dispatch({ type: "sessionsPanelSet", sessions });
|
|
9718
|
+
} catch {
|
|
9719
|
+
dispatch({ type: "sessionsPanelBusy", on: false });
|
|
9720
|
+
}
|
|
9721
|
+
}, [getLiveSessions]);
|
|
9722
|
+
useEffect(() => {
|
|
9723
|
+
if (!state.sessionsPanelOpen || !getLiveSessions) return void 0;
|
|
9724
|
+
const t = setInterval(() => {
|
|
9725
|
+
void loadLiveSessions();
|
|
9726
|
+
}, 5e3);
|
|
9727
|
+
return () => clearInterval(t);
|
|
9728
|
+
}, [state.sessionsPanelOpen, getLiveSessions, loadLiveSessions]);
|
|
8258
9729
|
const openSettings = React5.useCallback(() => {
|
|
8259
9730
|
if (!getSettings) return;
|
|
8260
9731
|
const s2 = getSettings();
|
|
@@ -8281,38 +9752,87 @@ function App({
|
|
|
8281
9752
|
maxIterations: s2.maxIterations ?? 500,
|
|
8282
9753
|
autoProceedMaxIterations: s2.autoProceedMaxIterations ?? 50,
|
|
8283
9754
|
enhanceDelayMs: s2.enhanceDelayMs ?? 6e4,
|
|
9755
|
+
enhanceEnabled: s2.enhanceEnabled ?? true,
|
|
9756
|
+
enhanceLanguage: s2.enhanceLanguage ?? "original",
|
|
8284
9757
|
debugStream: s2.debugStream ?? false,
|
|
8285
9758
|
configScope: s2.configScope ?? "global"
|
|
8286
9759
|
});
|
|
8287
9760
|
}, [getSettings]);
|
|
8288
|
-
const
|
|
8289
|
-
const
|
|
9761
|
+
const autoSubmitStreakRef = useRef(0);
|
|
9762
|
+
const autoSubmitCapWarnedRef = useRef(false);
|
|
9763
|
+
const [nextStepsRecheck, setNextStepsRecheck] = useState(0);
|
|
8290
9764
|
useEffect(() => {
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
9765
|
+
autoSubmitStreakRef.current = 0;
|
|
9766
|
+
autoSubmitCapWarnedRef.current = false;
|
|
9767
|
+
}, [autonomyLive]);
|
|
9768
|
+
useEffect(() => {
|
|
9769
|
+
if (state.status !== "idle" || autonomyLive !== "auto") {
|
|
9770
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
9771
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
9772
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
9773
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
9774
|
+
return;
|
|
9775
|
+
}
|
|
9776
|
+
if (state.enhance != null || state.enhanceBusy) {
|
|
9777
|
+
return;
|
|
9778
|
+
}
|
|
9779
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
9780
|
+
return;
|
|
9781
|
+
}
|
|
9782
|
+
const suggestions = getSuggestions?.() ?? [];
|
|
9783
|
+
if (suggestions.length === 0) {
|
|
9784
|
+
const recheck = setTimeout(() => setNextStepsRecheck((t) => t + 1), 1500);
|
|
9785
|
+
return () => clearTimeout(recheck);
|
|
9786
|
+
}
|
|
9787
|
+
const cfg = getSettings?.();
|
|
9788
|
+
const maxAuto = cfg?.autoProceedMaxIterations ?? 50;
|
|
9789
|
+
if (maxAuto > 0 && autoSubmitStreakRef.current >= maxAuto) {
|
|
9790
|
+
if (!autoSubmitCapWarnedRef.current) {
|
|
9791
|
+
autoSubmitCapWarnedRef.current = true;
|
|
9792
|
+
dispatch({
|
|
9793
|
+
type: "addEntry",
|
|
9794
|
+
entry: {
|
|
9795
|
+
kind: "warn",
|
|
9796
|
+
text: `Auto-proceed paused after ${maxAuto} consecutive automatic turns \u2014 type anything to continue (autonomy stays on).`
|
|
9797
|
+
}
|
|
9798
|
+
});
|
|
9799
|
+
}
|
|
8295
9800
|
return;
|
|
8296
9801
|
}
|
|
8297
|
-
const cfg = getSettings?.();
|
|
8298
9802
|
const delay = cfg?.delayMs ?? 45e3;
|
|
9803
|
+
const top = suggestions[0];
|
|
9804
|
+
if (!top) return;
|
|
9805
|
+
nextStepsAutoSubmitSuggestionRef.current = top;
|
|
8299
9806
|
const start = Date.now();
|
|
8300
|
-
|
|
8301
|
-
|
|
9807
|
+
setNextStepsAutoSubmitCountdown(Math.ceil(delay / 1e3));
|
|
9808
|
+
nextStepsAutoSubmitTimerRef.current = setInterval(() => {
|
|
8302
9809
|
const remaining = Math.max(0, Math.ceil((delay - (Date.now() - start)) / 1e3));
|
|
8303
9810
|
if (remaining <= 0) {
|
|
8304
|
-
clearInterval(
|
|
8305
|
-
|
|
8306
|
-
|
|
9811
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
9812
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
9813
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
9814
|
+
const suggestion = nextStepsAutoSubmitSuggestionRef.current;
|
|
9815
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
9816
|
+
if (suggestion) {
|
|
9817
|
+
autoSubmitStreakRef.current += 1;
|
|
9818
|
+
setDraft(suggestion, suggestion.length);
|
|
9819
|
+
void (async () => {
|
|
9820
|
+
const trimmed = suggestion.trim();
|
|
9821
|
+
if (!trimmed) return;
|
|
9822
|
+
const blocks = [{ type: "text", text: trimmed }];
|
|
9823
|
+
dispatch({ type: "addEntry", entry: { kind: "user", text: trimmed } });
|
|
9824
|
+
await runBlocksRef.current(blocks);
|
|
9825
|
+
})();
|
|
9826
|
+
}
|
|
8307
9827
|
} else {
|
|
8308
|
-
|
|
9828
|
+
setNextStepsAutoSubmitCountdown(remaining);
|
|
8309
9829
|
}
|
|
8310
9830
|
}, 500);
|
|
8311
9831
|
return () => {
|
|
8312
|
-
clearInterval(
|
|
8313
|
-
|
|
9832
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
9833
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
8314
9834
|
};
|
|
8315
|
-
}, [autonomyLive, getSettings]);
|
|
9835
|
+
}, [state.status, autonomyLive, state.enhance, state.enhanceBusy, nextStepsRecheck, getSettings, getSuggestions, dispatch]);
|
|
8316
9836
|
const settingsAutoSaveGateRef = useRef(true);
|
|
8317
9837
|
useEffect(() => {
|
|
8318
9838
|
if (state.settingsPicker.open) {
|
|
@@ -8349,6 +9869,8 @@ function App({
|
|
|
8349
9869
|
maxIterations: sp.maxIterations,
|
|
8350
9870
|
autoProceedMaxIterations: sp.autoProceedMaxIterations,
|
|
8351
9871
|
enhanceDelayMs: sp.enhanceDelayMs,
|
|
9872
|
+
enhanceEnabled: sp.enhanceEnabled,
|
|
9873
|
+
enhanceLanguage: sp.enhanceLanguage,
|
|
8352
9874
|
debugStream: sp.debugStream,
|
|
8353
9875
|
configScope: sp.configScope
|
|
8354
9876
|
})).then((err) => {
|
|
@@ -8411,6 +9933,21 @@ function App({
|
|
|
8411
9933
|
slashRegistry.unregister("settings");
|
|
8412
9934
|
};
|
|
8413
9935
|
}, [slashRegistry, getSettings, saveSettings, openSettings]);
|
|
9936
|
+
useEffect(() => {
|
|
9937
|
+
const cmd = {
|
|
9938
|
+
name: "mailbox",
|
|
9939
|
+
aliases: ["inbox", "mail"],
|
|
9940
|
+
description: "Toggle the inter-agent mailbox panel \u2014 messages, read receipts, online agents.",
|
|
9941
|
+
async run() {
|
|
9942
|
+
setMailboxPanelOpen((prev) => !prev);
|
|
9943
|
+
return { message: void 0 };
|
|
9944
|
+
}
|
|
9945
|
+
};
|
|
9946
|
+
slashRegistry.register(cmd, "tui", { official: true });
|
|
9947
|
+
return () => {
|
|
9948
|
+
slashRegistry.unregister("mailbox");
|
|
9949
|
+
};
|
|
9950
|
+
}, [slashRegistry]);
|
|
8414
9951
|
useEffect(() => {
|
|
8415
9952
|
if (!switchAutonomy) return;
|
|
8416
9953
|
const cmd = {
|
|
@@ -8427,6 +9964,34 @@ function App({
|
|
|
8427
9964
|
slashRegistry.unregister("autonomy");
|
|
8428
9965
|
};
|
|
8429
9966
|
}, [slashRegistry, switchAutonomy]);
|
|
9967
|
+
useEffect(() => {
|
|
9968
|
+
const cmd = {
|
|
9969
|
+
name: "resume",
|
|
9970
|
+
aliases: ["load"],
|
|
9971
|
+
description: "Resume a previous session \u2014 pick from a list of recent sessions.",
|
|
9972
|
+
async run() {
|
|
9973
|
+
if (!listSessions) {
|
|
9974
|
+
return { message: "Session listing not available." };
|
|
9975
|
+
}
|
|
9976
|
+
try {
|
|
9977
|
+
const sessions = await listSessions(20);
|
|
9978
|
+
if (sessions.length === 0) {
|
|
9979
|
+
return { message: "No saved sessions." };
|
|
9980
|
+
}
|
|
9981
|
+
dispatch({ type: "resumePickerOpen", sessions });
|
|
9982
|
+
} catch (err) {
|
|
9983
|
+
return {
|
|
9984
|
+
message: err instanceof Error ? err.message : String(err)
|
|
9985
|
+
};
|
|
9986
|
+
}
|
|
9987
|
+
return { message: void 0 };
|
|
9988
|
+
}
|
|
9989
|
+
};
|
|
9990
|
+
slashRegistry.register(cmd, "tui", { official: true });
|
|
9991
|
+
return () => {
|
|
9992
|
+
slashRegistry.unregister("resume");
|
|
9993
|
+
};
|
|
9994
|
+
}, [slashRegistry, listSessions]);
|
|
8430
9995
|
useEffect(() => {
|
|
8431
9996
|
const FLUSH_MS2 = 100;
|
|
8432
9997
|
const flush = () => {
|
|
@@ -8619,6 +10184,9 @@ function App({
|
|
|
8619
10184
|
}, [state.enhanceEnabled]);
|
|
8620
10185
|
const enhanceAbortRef = useRef(null);
|
|
8621
10186
|
const [enhanceCountdown, setEnhanceCountdown] = useState(null);
|
|
10187
|
+
const [nextStepsAutoSubmitCountdown, setNextStepsAutoSubmitCountdown] = useState(null);
|
|
10188
|
+
const nextStepsAutoSubmitSuggestionRef = useRef(null);
|
|
10189
|
+
const nextStepsAutoSubmitTimerRef = useRef(void 0);
|
|
8622
10190
|
useTuiEventBridge({
|
|
8623
10191
|
events,
|
|
8624
10192
|
dispatch,
|
|
@@ -8826,7 +10394,28 @@ function App({
|
|
|
8826
10394
|
return;
|
|
8827
10395
|
}
|
|
8828
10396
|
}
|
|
8829
|
-
const
|
|
10397
|
+
const overlaySelectable = state.modelPicker.open || state.autonomyPicker.open || state.resumePicker.open || state.settingsPicker.open || state.projectPicker.open || state.slashPicker.open || state.picker.open;
|
|
10398
|
+
const clickConfirm = overlaySelectable && key.mouse?.kind === "press" && key.mouse.button === "left";
|
|
10399
|
+
const clickCancel = overlaySelectable && key.mouse?.kind === "press" && key.mouse.button === "right";
|
|
10400
|
+
const isEnter = key.return || input === "\r" || input === "\n" || clickConfirm;
|
|
10401
|
+
if (clickCancel) {
|
|
10402
|
+
if (state.modelPicker.open) {
|
|
10403
|
+
dispatch(
|
|
10404
|
+
state.modelPicker.step === "model" ? { type: "modelPickerBack" } : { type: "modelPickerClose" }
|
|
10405
|
+
);
|
|
10406
|
+
} else if (state.autonomyPicker.open) {
|
|
10407
|
+
dispatch({ type: "autonomyPickerClose" });
|
|
10408
|
+
} else if (state.resumePicker.open) {
|
|
10409
|
+
dispatch({ type: "resumePickerClose" });
|
|
10410
|
+
} else if (state.settingsPicker.open) {
|
|
10411
|
+
dispatch({ type: "settingsClose" });
|
|
10412
|
+
} else if (state.slashPicker.open) {
|
|
10413
|
+
dispatch({ type: "slashPickerClose" });
|
|
10414
|
+
} else if (state.picker.open) {
|
|
10415
|
+
dispatch({ type: "pickerClose" });
|
|
10416
|
+
}
|
|
10417
|
+
return;
|
|
10418
|
+
}
|
|
8830
10419
|
if (state.modelPicker.open) {
|
|
8831
10420
|
if (key.escape) {
|
|
8832
10421
|
if (state.modelPicker.step === "model") {
|
|
@@ -8836,6 +10425,10 @@ function App({
|
|
|
8836
10425
|
}
|
|
8837
10426
|
return;
|
|
8838
10427
|
}
|
|
10428
|
+
if (key.mouse?.kind === "wheel") {
|
|
10429
|
+
dispatch({ type: "modelPickerMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10430
|
+
return;
|
|
10431
|
+
}
|
|
8839
10432
|
if (key.upArrow) {
|
|
8840
10433
|
dispatch({ type: "modelPickerMove", delta: -1 });
|
|
8841
10434
|
return;
|
|
@@ -8901,6 +10494,10 @@ function App({
|
|
|
8901
10494
|
dispatch({ type: "autonomyPickerClose" });
|
|
8902
10495
|
return;
|
|
8903
10496
|
}
|
|
10497
|
+
if (key.mouse?.kind === "wheel") {
|
|
10498
|
+
dispatch({ type: "autonomyPickerMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10499
|
+
return;
|
|
10500
|
+
}
|
|
8904
10501
|
if (key.upArrow) {
|
|
8905
10502
|
dispatch({ type: "autonomyPickerMove", delta: -1 });
|
|
8906
10503
|
return;
|
|
@@ -8925,11 +10522,64 @@ function App({
|
|
|
8925
10522
|
}
|
|
8926
10523
|
return;
|
|
8927
10524
|
}
|
|
10525
|
+
if (state.resumePicker.open) {
|
|
10526
|
+
if (key.escape) {
|
|
10527
|
+
dispatch({ type: "resumePickerClose" });
|
|
10528
|
+
return;
|
|
10529
|
+
}
|
|
10530
|
+
if (key.mouse?.kind === "wheel") {
|
|
10531
|
+
dispatch({ type: "resumePickerMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10532
|
+
return;
|
|
10533
|
+
}
|
|
10534
|
+
if (key.upArrow) {
|
|
10535
|
+
dispatch({ type: "resumePickerMove", delta: -1 });
|
|
10536
|
+
return;
|
|
10537
|
+
}
|
|
10538
|
+
if (key.downArrow) {
|
|
10539
|
+
dispatch({ type: "resumePickerMove", delta: 1 });
|
|
10540
|
+
return;
|
|
10541
|
+
}
|
|
10542
|
+
if (isEnter) {
|
|
10543
|
+
const now = Date.now();
|
|
10544
|
+
if (now - lastEnterAtRef.current < 50) return;
|
|
10545
|
+
lastEnterAtRef.current = now;
|
|
10546
|
+
const session = state.resumePicker.sessions[state.resumePicker.selected];
|
|
10547
|
+
if (!session || session.isCurrent) return;
|
|
10548
|
+
if (state.resumePicker.busy) return;
|
|
10549
|
+
dispatch({ type: "resumePickerBusy", on: true });
|
|
10550
|
+
onResumeSession?.(session.id).then((result) => {
|
|
10551
|
+
if (!result) {
|
|
10552
|
+
dispatch({ type: "resumePickerError", text: `Failed to resume session ${session.id}.` });
|
|
10553
|
+
return;
|
|
10554
|
+
}
|
|
10555
|
+
dispatch({ type: "replaceHistory", entries: result.entries, nextId: result.nextId });
|
|
10556
|
+
dispatch({ type: "resumePickerClose" });
|
|
10557
|
+
dispatch({
|
|
10558
|
+
type: "addEntry",
|
|
10559
|
+
entry: {
|
|
10560
|
+
kind: "info",
|
|
10561
|
+
text: `Resumed session ${result.sessionId} \u2014 ${result.entries.length} entries replayed.`
|
|
10562
|
+
}
|
|
10563
|
+
});
|
|
10564
|
+
}).catch((err) => {
|
|
10565
|
+
dispatch({
|
|
10566
|
+
type: "resumePickerError",
|
|
10567
|
+
text: err instanceof Error ? err.message : String(err)
|
|
10568
|
+
});
|
|
10569
|
+
});
|
|
10570
|
+
return;
|
|
10571
|
+
}
|
|
10572
|
+
return;
|
|
10573
|
+
}
|
|
8928
10574
|
if (state.settingsPicker.open) {
|
|
8929
|
-
if (key.escape || key.ctrl && input === "s"
|
|
10575
|
+
if (key.escape || key.ctrl && input === "s") {
|
|
8930
10576
|
dispatch({ type: "settingsClose" });
|
|
8931
10577
|
return;
|
|
8932
10578
|
}
|
|
10579
|
+
if (key.mouse?.kind === "wheel") {
|
|
10580
|
+
dispatch({ type: "settingsFieldMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10581
|
+
return;
|
|
10582
|
+
}
|
|
8933
10583
|
if (key.upArrow) {
|
|
8934
10584
|
dispatch({ type: "settingsFieldMove", delta: -1 });
|
|
8935
10585
|
return;
|
|
@@ -8955,11 +10605,166 @@ function App({
|
|
|
8955
10605
|
}
|
|
8956
10606
|
return;
|
|
8957
10607
|
}
|
|
10608
|
+
if (state.projectPicker.open) {
|
|
10609
|
+
if (key.escape) {
|
|
10610
|
+
if (state.projectPicker.filter) {
|
|
10611
|
+
dispatch({ type: "projectPickerFilter", filter: "" });
|
|
10612
|
+
} else {
|
|
10613
|
+
dispatch({ type: "projectPickerClose" });
|
|
10614
|
+
}
|
|
10615
|
+
return;
|
|
10616
|
+
}
|
|
10617
|
+
if (key.mouse?.kind === "wheel") {
|
|
10618
|
+
dispatch({ type: "projectPickerMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10619
|
+
return;
|
|
10620
|
+
}
|
|
10621
|
+
if (key.upArrow) {
|
|
10622
|
+
dispatch({ type: "projectPickerMove", delta: -1 });
|
|
10623
|
+
return;
|
|
10624
|
+
}
|
|
10625
|
+
if (key.downArrow) {
|
|
10626
|
+
dispatch({ type: "projectPickerMove", delta: 1 });
|
|
10627
|
+
return;
|
|
10628
|
+
}
|
|
10629
|
+
if (isEnter) {
|
|
10630
|
+
const now = Date.now();
|
|
10631
|
+
if (now - lastEnterAtRef.current < 50) return;
|
|
10632
|
+
lastEnterAtRef.current = now;
|
|
10633
|
+
const items = state.projectPicker.items;
|
|
10634
|
+
const selected = state.projectPicker.selected;
|
|
10635
|
+
if (selected < 0 || selected >= items.length) return;
|
|
10636
|
+
const item = items[selected];
|
|
10637
|
+
if (!item || item.key === "__divider__" || item.key === "quit") {
|
|
10638
|
+
dispatch({ type: "projectPickerClose" });
|
|
10639
|
+
return;
|
|
10640
|
+
}
|
|
10641
|
+
if (item.kind === "project") {
|
|
10642
|
+
onProjectSelect?.(item.key, item.kind);
|
|
10643
|
+
dispatch({ type: "projectPickerClose" });
|
|
10644
|
+
requestExit?.(42);
|
|
10645
|
+
return;
|
|
10646
|
+
}
|
|
10647
|
+
dispatch({ type: "projectPickerClose" });
|
|
10648
|
+
if (item.key === "new-session") {
|
|
10649
|
+
onProjectSelect?.(item.key, item.kind);
|
|
10650
|
+
requestExit?.(42);
|
|
10651
|
+
} else if (item.key === "prev-sessions") {
|
|
10652
|
+
void submit("/resume");
|
|
10653
|
+
}
|
|
10654
|
+
return;
|
|
10655
|
+
}
|
|
10656
|
+
if (input && input.length === 1 && input.charCodeAt(0) >= 32 && input.charCodeAt(0) < 127) {
|
|
10657
|
+
dispatch({ type: "projectPickerFilter", filter: state.projectPicker.filter + input });
|
|
10658
|
+
return;
|
|
10659
|
+
}
|
|
10660
|
+
if (key.backspace) {
|
|
10661
|
+
if (state.projectPicker.filter.length > 0) {
|
|
10662
|
+
dispatch({
|
|
10663
|
+
type: "projectPickerFilter",
|
|
10664
|
+
filter: state.projectPicker.filter.slice(0, -1)
|
|
10665
|
+
});
|
|
10666
|
+
}
|
|
10667
|
+
return;
|
|
10668
|
+
}
|
|
10669
|
+
return;
|
|
10670
|
+
}
|
|
10671
|
+
if (state.sessionsPanelOpen) {
|
|
10672
|
+
if (key.escape) {
|
|
10673
|
+
if (state.sessionResumeConfirm) {
|
|
10674
|
+
dispatch({ type: "sessionResumeConfirmClear" });
|
|
10675
|
+
} else {
|
|
10676
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
10677
|
+
}
|
|
10678
|
+
return;
|
|
10679
|
+
}
|
|
10680
|
+
if (key.upArrow) {
|
|
10681
|
+
dispatch({ type: "sessionsPanelMove", delta: -1 });
|
|
10682
|
+
return;
|
|
10683
|
+
}
|
|
10684
|
+
if (key.downArrow) {
|
|
10685
|
+
dispatch({ type: "sessionsPanelMove", delta: 1 });
|
|
10686
|
+
return;
|
|
10687
|
+
}
|
|
10688
|
+
if (key.mouse?.kind === "wheel") {
|
|
10689
|
+
dispatch({ type: "sessionsPanelMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10690
|
+
return;
|
|
10691
|
+
}
|
|
10692
|
+
if (isEnter) {
|
|
10693
|
+
const now = Date.now();
|
|
10694
|
+
if (now - lastEnterAtRef.current < 50) return;
|
|
10695
|
+
lastEnterAtRef.current = now;
|
|
10696
|
+
if (state.sessionResumeConfirm) {
|
|
10697
|
+
const pending = state.sessionResumeConfirm;
|
|
10698
|
+
dispatch({ type: "sessionResumeConfirmClear" });
|
|
10699
|
+
dispatch({ type: "sessionsPanelBusy", on: true });
|
|
10700
|
+
onResumeSession?.(pending.sessionId).then((result) => {
|
|
10701
|
+
if (!result) {
|
|
10702
|
+
dispatch({ type: "sessionsPanelBusy", on: false });
|
|
10703
|
+
return;
|
|
10704
|
+
}
|
|
10705
|
+
dispatch({ type: "replaceHistory", entries: result.entries, nextId: result.nextId });
|
|
10706
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
10707
|
+
dispatch({
|
|
10708
|
+
type: "addEntry",
|
|
10709
|
+
entry: {
|
|
10710
|
+
kind: "info",
|
|
10711
|
+
text: `Resumed session ${result.sessionId} \u2014 ${result.entries.length} entries replayed.`
|
|
10712
|
+
}
|
|
10713
|
+
});
|
|
10714
|
+
}).catch(() => {
|
|
10715
|
+
dispatch({ type: "sessionsPanelBusy", on: false });
|
|
10716
|
+
});
|
|
10717
|
+
return;
|
|
10718
|
+
}
|
|
10719
|
+
const sessions = state.sessionsPanel.sessions;
|
|
10720
|
+
const sel = state.sessionsPanel.selected;
|
|
10721
|
+
if (sel < 0 || sel >= sessions.length) return;
|
|
10722
|
+
const session = sessions[sel];
|
|
10723
|
+
if (!session) return;
|
|
10724
|
+
const isCurrentProject = session.projectRoot === projectRoot;
|
|
10725
|
+
if (isCurrentProject) {
|
|
10726
|
+
if (session.pid === process.pid) {
|
|
10727
|
+
dispatch({
|
|
10728
|
+
type: "addEntry",
|
|
10729
|
+
entry: { kind: "info", text: "That is this session \u2014 nothing to resume." }
|
|
10730
|
+
});
|
|
10731
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
10732
|
+
return;
|
|
10733
|
+
}
|
|
10734
|
+
if (session.pid != null) {
|
|
10735
|
+
dispatch({
|
|
10736
|
+
type: "addEntry",
|
|
10737
|
+
entry: {
|
|
10738
|
+
kind: "warn",
|
|
10739
|
+
text: `Session is open in another running wstack (pid ${session.pid}) \u2014 a live session cannot be resumed here. Use /resume for previous sessions.`
|
|
10740
|
+
}
|
|
10741
|
+
});
|
|
10742
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
10743
|
+
return;
|
|
10744
|
+
}
|
|
10745
|
+
dispatch({
|
|
10746
|
+
type: "sessionResumeConfirmSet",
|
|
10747
|
+
sessionId: session.sessionId,
|
|
10748
|
+
sessionName: session.projectName
|
|
10749
|
+
});
|
|
10750
|
+
} else {
|
|
10751
|
+
onSwitchToSession?.(session.sessionId, session.projectRoot ?? "", session.projectName);
|
|
10752
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
10753
|
+
requestExit?.(42);
|
|
10754
|
+
}
|
|
10755
|
+
return;
|
|
10756
|
+
}
|
|
10757
|
+
return;
|
|
10758
|
+
}
|
|
8958
10759
|
if (state.slashPicker.open) {
|
|
8959
10760
|
if (key.escape) {
|
|
8960
10761
|
dispatch({ type: "slashPickerClose" });
|
|
8961
10762
|
return;
|
|
8962
10763
|
}
|
|
10764
|
+
if (key.mouse?.kind === "wheel") {
|
|
10765
|
+
dispatch({ type: "slashPickerMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10766
|
+
return;
|
|
10767
|
+
}
|
|
8963
10768
|
if (key.upArrow) {
|
|
8964
10769
|
dispatch({ type: "slashPickerMove", delta: -1 });
|
|
8965
10770
|
return;
|
|
@@ -8996,6 +10801,10 @@ function App({
|
|
|
8996
10801
|
dispatch({ type: "pickerClose" });
|
|
8997
10802
|
return;
|
|
8998
10803
|
}
|
|
10804
|
+
if (key.mouse?.kind === "wheel") {
|
|
10805
|
+
dispatch({ type: "pickerMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10806
|
+
return;
|
|
10807
|
+
}
|
|
8999
10808
|
if (key.upArrow) {
|
|
9000
10809
|
dispatch({ type: "pickerMove", delta: -1 });
|
|
9001
10810
|
return;
|
|
@@ -9122,6 +10931,24 @@ function App({
|
|
|
9122
10931
|
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
9123
10932
|
dispatch({ type: "toggleTodosMonitor" });
|
|
9124
10933
|
};
|
|
10934
|
+
if (key.fn === 1) {
|
|
10935
|
+
if (state.projectPicker.open) {
|
|
10936
|
+
dispatch({ type: "projectPickerClose" });
|
|
10937
|
+
} else {
|
|
10938
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
10939
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
10940
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
10941
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
10942
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
10943
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
10944
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
10945
|
+
if (state.processListOpen) dispatch({ type: "toggleProcessList" });
|
|
10946
|
+
if (state.goalPanelOpen) dispatch({ type: "toggleGoalPanel" });
|
|
10947
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
10948
|
+
openProjectPicker();
|
|
10949
|
+
}
|
|
10950
|
+
return;
|
|
10951
|
+
}
|
|
9125
10952
|
if (key.ctrl && input === "f" || key.fn === 2) {
|
|
9126
10953
|
toggleFleetOverlay();
|
|
9127
10954
|
return;
|
|
@@ -9134,47 +10961,6 @@ function App({
|
|
|
9134
10961
|
toggleWorktreeOverlay();
|
|
9135
10962
|
return;
|
|
9136
10963
|
}
|
|
9137
|
-
if (key.fn === 5) {
|
|
9138
|
-
if (state.settingsPicker.open) {
|
|
9139
|
-
dispatch({ type: "settingsClose" });
|
|
9140
|
-
} else if (getSettings && saveSettings) {
|
|
9141
|
-
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
9142
|
-
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
9143
|
-
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
9144
|
-
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
9145
|
-
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
9146
|
-
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
9147
|
-
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
9148
|
-
const cfg = getSettings();
|
|
9149
|
-
dispatch({
|
|
9150
|
-
type: "settingsOpen",
|
|
9151
|
-
mode: cfg.mode,
|
|
9152
|
-
delayMs: cfg.delayMs,
|
|
9153
|
-
titleAnimation: cfg.titleAnimation ?? true,
|
|
9154
|
-
yolo: cfg.yolo ?? false,
|
|
9155
|
-
streamFleet: cfg.streamFleet ?? true,
|
|
9156
|
-
chime: cfg.chime ?? false,
|
|
9157
|
-
confirmExit: cfg.confirmExit ?? true,
|
|
9158
|
-
nextPrediction: cfg.nextPrediction ?? false,
|
|
9159
|
-
featureMcp: cfg.featureMcp ?? true,
|
|
9160
|
-
featurePlugins: cfg.featurePlugins ?? true,
|
|
9161
|
-
featureMemory: cfg.featureMemory ?? true,
|
|
9162
|
-
featureSkills: cfg.featureSkills ?? true,
|
|
9163
|
-
featureModelsRegistry: cfg.featureModelsRegistry ?? true,
|
|
9164
|
-
contextAutoCompact: cfg.contextAutoCompact ?? true,
|
|
9165
|
-
contextStrategy: cfg.contextStrategy ?? "hybrid",
|
|
9166
|
-
logLevel: cfg.logLevel ?? "info",
|
|
9167
|
-
auditLevel: cfg.auditLevel ?? "standard",
|
|
9168
|
-
indexOnStart: cfg.indexOnStart ?? true,
|
|
9169
|
-
maxIterations: cfg.maxIterations ?? 500,
|
|
9170
|
-
autoProceedMaxIterations: cfg.autoProceedMaxIterations ?? 50,
|
|
9171
|
-
enhanceDelayMs: cfg.enhanceDelayMs ?? 6e4,
|
|
9172
|
-
debugStream: cfg.debugStream ?? false,
|
|
9173
|
-
configScope: cfg.configScope ?? "global"
|
|
9174
|
-
});
|
|
9175
|
-
}
|
|
9176
|
-
return;
|
|
9177
|
-
}
|
|
9178
10964
|
if (key.fn === 6) {
|
|
9179
10965
|
toggleTodosOverlay();
|
|
9180
10966
|
return;
|
|
@@ -9227,6 +11013,25 @@ function App({
|
|
|
9227
11013
|
}
|
|
9228
11014
|
return;
|
|
9229
11015
|
}
|
|
11016
|
+
if (key.fn === 10) {
|
|
11017
|
+
if (state.sessionsPanelOpen) {
|
|
11018
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
11019
|
+
} else {
|
|
11020
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
11021
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
11022
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
11023
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
11024
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
11025
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
11026
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
11027
|
+
if (state.processListOpen) dispatch({ type: "toggleProcessList" });
|
|
11028
|
+
if (state.goalPanelOpen) dispatch({ type: "toggleGoalPanel" });
|
|
11029
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
11030
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
11031
|
+
loadLiveSessions();
|
|
11032
|
+
}
|
|
11033
|
+
return;
|
|
11034
|
+
}
|
|
9230
11035
|
if (key.ctrl && input === "s") {
|
|
9231
11036
|
if (state.settingsPicker.open) {
|
|
9232
11037
|
dispatch({ type: "settingsClose" });
|
|
@@ -9262,6 +11067,8 @@ function App({
|
|
|
9262
11067
|
maxIterations: cfg.maxIterations ?? 500,
|
|
9263
11068
|
autoProceedMaxIterations: cfg.autoProceedMaxIterations ?? 50,
|
|
9264
11069
|
enhanceDelayMs: cfg.enhanceDelayMs ?? 6e4,
|
|
11070
|
+
enhanceEnabled: cfg.enhanceEnabled ?? true,
|
|
11071
|
+
enhanceLanguage: cfg.enhanceLanguage ?? "original",
|
|
9265
11072
|
debugStream: cfg.debugStream ?? false,
|
|
9266
11073
|
configScope: cfg.configScope ?? "global"
|
|
9267
11074
|
});
|
|
@@ -9285,6 +11092,10 @@ function App({
|
|
|
9285
11092
|
dispatch({ type: "settingsClose" });
|
|
9286
11093
|
return;
|
|
9287
11094
|
}
|
|
11095
|
+
if (state.projectPicker.open) {
|
|
11096
|
+
dispatch({ type: "projectPickerClose" });
|
|
11097
|
+
return;
|
|
11098
|
+
}
|
|
9288
11099
|
if (state.queuePanelOpen) {
|
|
9289
11100
|
dispatch({ type: "toggleQueuePanel" });
|
|
9290
11101
|
return;
|
|
@@ -9297,11 +11108,15 @@ function App({
|
|
|
9297
11108
|
dispatch({ type: "toggleGoalPanel" });
|
|
9298
11109
|
return;
|
|
9299
11110
|
}
|
|
11111
|
+
if (state.sessionsPanelOpen) {
|
|
11112
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
11113
|
+
return;
|
|
11114
|
+
}
|
|
9300
11115
|
}
|
|
9301
11116
|
if (state.processListOpen) {
|
|
9302
11117
|
return;
|
|
9303
11118
|
}
|
|
9304
|
-
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) {
|
|
11119
|
+
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.goalPanelOpen && !state.sessionsPanelOpen && !state.autoPhase?.monitorOpen) {
|
|
9305
11120
|
dispatch({ type: "toggleHelp" });
|
|
9306
11121
|
return;
|
|
9307
11122
|
}
|
|
@@ -9335,6 +11150,12 @@ function App({
|
|
|
9335
11150
|
}
|
|
9336
11151
|
if (cursor === 0) return;
|
|
9337
11152
|
const next2 = buffer.slice(0, cursor - 1) + buffer.slice(cursor);
|
|
11153
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
11154
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
11155
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
11156
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
11157
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
11158
|
+
}
|
|
9338
11159
|
setDraft(next2, cursor - 1);
|
|
9339
11160
|
return;
|
|
9340
11161
|
}
|
|
@@ -9345,12 +11166,24 @@ function App({
|
|
|
9345
11166
|
const nextWordStart = afterCursor.indexOf(" ");
|
|
9346
11167
|
const end = nextWordStart === -1 ? buffer.length : cursor + nextWordStart + 1;
|
|
9347
11168
|
const next3 = buffer.slice(0, cursor) + buffer.slice(end);
|
|
11169
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
11170
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
11171
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
11172
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
11173
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
11174
|
+
}
|
|
9348
11175
|
setDraft(next3, cursor);
|
|
9349
11176
|
return;
|
|
9350
11177
|
}
|
|
9351
11178
|
if (cursor >= buffer.length) return;
|
|
9352
11179
|
const span = tokenLengthForward(buffer, cursor) || 1;
|
|
9353
11180
|
const next2 = buffer.slice(0, cursor) + buffer.slice(cursor + span);
|
|
11181
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
11182
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
11183
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
11184
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
11185
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
11186
|
+
}
|
|
9354
11187
|
setDraft(next2, cursor);
|
|
9355
11188
|
return;
|
|
9356
11189
|
}
|
|
@@ -9386,7 +11219,67 @@ function App({
|
|
|
9386
11219
|
setDraft(buffer, buffer.length);
|
|
9387
11220
|
return;
|
|
9388
11221
|
}
|
|
9389
|
-
const overlayOpen = state.monitorOpen || state.agentsMonitorOpen || state.worktreeMonitorOpen || state.todosMonitorOpen || state.queuePanelOpen || state.processListOpen || state.goalPanelOpen || state.helpOpen || (state.autoPhase?.monitorOpen ?? false) || state.rewindOverlay !== null;
|
|
11222
|
+
const overlayOpen = state.monitorOpen || state.agentsMonitorOpen || state.worktreeMonitorOpen || state.todosMonitorOpen || state.queuePanelOpen || state.processListOpen || state.goalPanelOpen || state.sessionsPanelOpen || state.helpOpen || (state.autoPhase?.monitorOpen ?? false) || state.rewindOverlay !== null;
|
|
11223
|
+
if (mouseMode && !overlayOpen) {
|
|
11224
|
+
if (key.mouse?.kind === "wheel") {
|
|
11225
|
+
if (key.mouse.shift) dispatch({ type: "scrollPage", dir: key.mouse.wheel > 0 ? "up" : "down" });
|
|
11226
|
+
else dispatch({ type: "scrollBy", delta: key.mouse.wheel > 0 ? 3 : -3 });
|
|
11227
|
+
return;
|
|
11228
|
+
}
|
|
11229
|
+
if ((key.mouse?.kind === "press" || key.mouse?.kind === "move") && key.mouse.button === "left") {
|
|
11230
|
+
const region = hitRegion(
|
|
11231
|
+
{ termRows, termCols: stdout?.columns ?? 80, viewportRows: state.viewportRows },
|
|
11232
|
+
key.mouse.x,
|
|
11233
|
+
key.mouse.y
|
|
11234
|
+
);
|
|
11235
|
+
if (region?.kind === "scrollbar") {
|
|
11236
|
+
dispatch({
|
|
11237
|
+
type: "scrollTo",
|
|
11238
|
+
offset: scrollOffsetForTrackRow(state.viewportRows, state.totalLines, region.cell)
|
|
11239
|
+
});
|
|
11240
|
+
return;
|
|
11241
|
+
}
|
|
11242
|
+
}
|
|
11243
|
+
if (key.mouse?.kind === "press" && key.mouse.button === "left" && statusBarWrapRef.current) {
|
|
11244
|
+
const sbHeight = measureElement(statusBarWrapRef.current).height;
|
|
11245
|
+
const belowHeight = belowStatusBarRef.current ? measureElement(belowStatusBarRef.current).height : 0;
|
|
11246
|
+
const cols = stdout?.columns ?? 80;
|
|
11247
|
+
const mx = key.mouse.x;
|
|
11248
|
+
const my = key.mouse.y;
|
|
11249
|
+
const rowFor = (line) => statusBarLineRow({ termRows, statusBarHeight: sbHeight, belowHeight, headerRows: 1, line });
|
|
11250
|
+
const inSpan = (span) => mx >= span.start + 1 && mx <= span.start + span.len;
|
|
11251
|
+
if (cols >= COMPACT_THRESHOLD && my === rowFor(0)) {
|
|
11252
|
+
const span = statusBarModelSpan({
|
|
11253
|
+
version: appVersion,
|
|
11254
|
+
state: state.status,
|
|
11255
|
+
fleetRunning: fleetCounts?.running ?? 0,
|
|
11256
|
+
model: `${liveProvider}/${liveModel}`
|
|
11257
|
+
});
|
|
11258
|
+
if (inSpan(span)) {
|
|
11259
|
+
await openModelPicker();
|
|
11260
|
+
return;
|
|
11261
|
+
}
|
|
11262
|
+
}
|
|
11263
|
+
const autoSpan = statusBarAutonomySpan({ yolo: yoloLive, autonomy: autonomyLive });
|
|
11264
|
+
if (autoSpan && my === rowFor(1) && inSpan(autoSpan)) {
|
|
11265
|
+
dispatch({ type: "autonomyPickerOpen", options: AUTONOMY_OPTIONS });
|
|
11266
|
+
return;
|
|
11267
|
+
}
|
|
11268
|
+
const todosShown = !!todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0);
|
|
11269
|
+
if (todosShown && my === rowFor(2) && inSpan(statusBarTodosSpan())) {
|
|
11270
|
+
dispatch({ type: "toggleTodosMonitor" });
|
|
11271
|
+
return;
|
|
11272
|
+
}
|
|
11273
|
+
}
|
|
11274
|
+
if (key.pageUp) {
|
|
11275
|
+
dispatch({ type: "scrollPage", dir: "up" });
|
|
11276
|
+
return;
|
|
11277
|
+
}
|
|
11278
|
+
if (key.pageDown) {
|
|
11279
|
+
dispatch({ type: "scrollPage", dir: "down" });
|
|
11280
|
+
return;
|
|
11281
|
+
}
|
|
11282
|
+
}
|
|
9390
11283
|
if (key.upArrow) {
|
|
9391
11284
|
if (!overlayOpen && state.inputHistory.length > 0) {
|
|
9392
11285
|
dispatch({ type: "historyUp" });
|
|
@@ -9418,6 +11311,12 @@ function App({
|
|
|
9418
11311
|
return;
|
|
9419
11312
|
}
|
|
9420
11313
|
if (key.ctrl && input === "u") {
|
|
11314
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
11315
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
11316
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
11317
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
11318
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
11319
|
+
}
|
|
9421
11320
|
setDraft("", 0);
|
|
9422
11321
|
return;
|
|
9423
11322
|
}
|
|
@@ -9425,12 +11324,24 @@ function App({
|
|
|
9425
11324
|
if (cursor >= buffer.length) return;
|
|
9426
11325
|
const span = tokenLengthForward(buffer, cursor) || 1;
|
|
9427
11326
|
const next2 = buffer.slice(0, cursor) + buffer.slice(cursor + span);
|
|
11327
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
11328
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
11329
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
11330
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
11331
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
11332
|
+
}
|
|
9428
11333
|
setDraft(next2, cursor);
|
|
9429
11334
|
return;
|
|
9430
11335
|
}
|
|
9431
11336
|
if (key.ctrl && input === "k") {
|
|
9432
11337
|
if (cursor >= buffer.length) return;
|
|
9433
11338
|
const next2 = buffer.slice(0, cursor);
|
|
11339
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
11340
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
11341
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
11342
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
11343
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
11344
|
+
}
|
|
9434
11345
|
setDraft(next2, cursor);
|
|
9435
11346
|
return;
|
|
9436
11347
|
}
|
|
@@ -9448,6 +11359,12 @@ function App({
|
|
|
9448
11359
|
await commitPaste(input);
|
|
9449
11360
|
return;
|
|
9450
11361
|
}
|
|
11362
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
11363
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
11364
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
11365
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
11366
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
11367
|
+
}
|
|
9451
11368
|
const next = buffer.slice(0, cursor) + input + buffer.slice(cursor);
|
|
9452
11369
|
setDraft(next, cursor + input.length);
|
|
9453
11370
|
};
|
|
@@ -9514,6 +11431,12 @@ function App({
|
|
|
9514
11431
|
} catch {
|
|
9515
11432
|
}
|
|
9516
11433
|
}
|
|
11434
|
+
if (result.status === "done" && result.finalText && onSuggestionsParsed) {
|
|
11435
|
+
try {
|
|
11436
|
+
onSuggestionsParsed(result.finalText);
|
|
11437
|
+
} catch {
|
|
11438
|
+
}
|
|
11439
|
+
}
|
|
9517
11440
|
if (tokenCounter && before) {
|
|
9518
11441
|
const after = tokenCounter.total();
|
|
9519
11442
|
const costAfter = tokenCounter.estimateCost().total;
|
|
@@ -9668,6 +11591,9 @@ function App({
|
|
|
9668
11591
|
return;
|
|
9669
11592
|
}
|
|
9670
11593
|
dispatch({ type: "resetInterrupts" });
|
|
11594
|
+
autoSubmitStreakRef.current = 0;
|
|
11595
|
+
autoSubmitCapWarnedRef.current = false;
|
|
11596
|
+
dispatch({ type: "scrollToBottom" });
|
|
9671
11597
|
const pushSubmittedHistory = () => {
|
|
9672
11598
|
if (trimmed) dispatch({ type: "historyPush", text: trimmed });
|
|
9673
11599
|
};
|
|
@@ -9708,6 +11634,25 @@ ${content}
|
|
|
9708
11634
|
const m = res.metadata.autoPhaseInit;
|
|
9709
11635
|
dispatch({ type: "autoPhaseInit", title: m.title });
|
|
9710
11636
|
}
|
|
11637
|
+
const mouseToggle = res?.metadata?.mouseToggle;
|
|
11638
|
+
if (mouseToggle) {
|
|
11639
|
+
const nextVal = mouseToggle === "on" ? true : mouseToggle === "off" ? false : mouseToggle === "toggle" ? !mouseMode : mouseMode;
|
|
11640
|
+
if (mouseToggle !== "query" && nextVal !== mouseMode) {
|
|
11641
|
+
setMouseMode(nextVal);
|
|
11642
|
+
const cur = getSettings?.();
|
|
11643
|
+
if (cur && saveSettings) {
|
|
11644
|
+
Promise.resolve(saveSettings({ ...cur, mouseMode: nextVal })).catch(() => {
|
|
11645
|
+
});
|
|
11646
|
+
}
|
|
11647
|
+
}
|
|
11648
|
+
dispatch({
|
|
11649
|
+
type: "addEntry",
|
|
11650
|
+
entry: {
|
|
11651
|
+
kind: "info",
|
|
11652
|
+
text: nextVal ? "Mouse mode: ON \u2014 wheel scrolls the chat in-app, clickable UI active. (Native scrollback off; Shift+wheel = page.)" : "Mouse mode: OFF \u2014 terminal native scrollback restored."
|
|
11653
|
+
}
|
|
11654
|
+
});
|
|
11655
|
+
}
|
|
9711
11656
|
const ctxModel = agent.ctx.model;
|
|
9712
11657
|
if (ctxModel && ctxModel !== liveModel) setLiveModel(ctxModel);
|
|
9713
11658
|
const ctxProviderId = agent.ctx.provider?.id;
|
|
@@ -9867,6 +11812,9 @@ User message:
|
|
|
9867
11812
|
clearDraft();
|
|
9868
11813
|
const blocks = await builder.submit();
|
|
9869
11814
|
if (state.status !== "idle") {
|
|
11815
|
+
if (autonomyLive === "auto" && nextStepsAutoSubmitTimerRef.current != null) {
|
|
11816
|
+
switchAutonomy?.("off");
|
|
11817
|
+
}
|
|
9870
11818
|
dispatch({
|
|
9871
11819
|
type: "addEntry",
|
|
9872
11820
|
entry: { kind: "user", text: displayText, queued: true, pasteContent }
|
|
@@ -9875,6 +11823,9 @@ User message:
|
|
|
9875
11823
|
return;
|
|
9876
11824
|
}
|
|
9877
11825
|
dispatch({ type: "addEntry", entry: { kind: "user", text: displayText, pasteContent } });
|
|
11826
|
+
if (autonomyLive === "auto" && nextStepsAutoSubmitTimerRef.current != null) {
|
|
11827
|
+
switchAutonomy?.("off");
|
|
11828
|
+
}
|
|
9878
11829
|
await runBlocks(blocks);
|
|
9879
11830
|
};
|
|
9880
11831
|
const bootInjectedRef = useRef(false);
|
|
@@ -9927,15 +11878,27 @@ User message:
|
|
|
9927
11878
|
const inputHeight = Math.max(1, inputCellRows.length);
|
|
9928
11879
|
const hideInput = enhanceActive || state.helpOpen || state.processListOpen;
|
|
9929
11880
|
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, flexShrink: 0, children: [
|
|
9930
|
-
/* @__PURE__ */ jsx(
|
|
11881
|
+
mouseMode ? /* @__PURE__ */ jsx(
|
|
11882
|
+
ScrollableHistory,
|
|
11883
|
+
{
|
|
11884
|
+
entries: state.entries,
|
|
11885
|
+
streamingText: state.streamingText,
|
|
11886
|
+
toolStream: state.toolStream,
|
|
11887
|
+
scrollOffset: state.scrollOffset,
|
|
11888
|
+
viewportRows: state.viewportRows,
|
|
11889
|
+
totalLines: state.totalLines,
|
|
11890
|
+
onMeasure: (totalLines) => dispatch({ type: "setMeasuredLines", totalLines })
|
|
11891
|
+
}
|
|
11892
|
+
) : /* @__PURE__ */ jsx(
|
|
9931
11893
|
History,
|
|
9932
11894
|
{
|
|
9933
11895
|
entries: state.entries,
|
|
11896
|
+
generation: state.historyGen,
|
|
9934
11897
|
streamingText: state.streamingText,
|
|
9935
11898
|
toolStream: state.toolStream
|
|
9936
11899
|
}
|
|
9937
11900
|
),
|
|
9938
|
-
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [
|
|
11901
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexShrink: 0, ref: bottomRegionRef, children: [
|
|
9939
11902
|
/* @__PURE__ */ jsx(
|
|
9940
11903
|
Input,
|
|
9941
11904
|
{
|
|
@@ -9986,6 +11949,16 @@ User message:
|
|
|
9986
11949
|
hint: state.autonomyPicker.hint
|
|
9987
11950
|
}
|
|
9988
11951
|
) : null,
|
|
11952
|
+
state.resumePicker.open ? /* @__PURE__ */ jsx(
|
|
11953
|
+
ResumePicker,
|
|
11954
|
+
{
|
|
11955
|
+
sessions: state.resumePicker.sessions,
|
|
11956
|
+
selected: state.resumePicker.selected,
|
|
11957
|
+
busy: state.resumePicker.busy,
|
|
11958
|
+
error: state.resumePicker.error,
|
|
11959
|
+
hint: state.resumePicker.hint
|
|
11960
|
+
}
|
|
11961
|
+
) : null,
|
|
9989
11962
|
state.settingsPicker.open ? /* @__PURE__ */ jsx(
|
|
9990
11963
|
SettingsPicker,
|
|
9991
11964
|
{
|
|
@@ -10011,11 +11984,32 @@ User message:
|
|
|
10011
11984
|
maxIterations: state.settingsPicker.maxIterations,
|
|
10012
11985
|
autoProceedMaxIterations: state.settingsPicker.autoProceedMaxIterations,
|
|
10013
11986
|
enhanceDelayMs: state.settingsPicker.enhanceDelayMs,
|
|
11987
|
+
enhanceEnabled: state.settingsPicker.enhanceEnabled,
|
|
11988
|
+
enhanceLanguage: state.settingsPicker.enhanceLanguage,
|
|
10014
11989
|
debugStream: state.settingsPicker.debugStream,
|
|
10015
11990
|
configScope: state.settingsPicker.configScope,
|
|
10016
11991
|
hint: state.settingsPicker.hint
|
|
10017
11992
|
}
|
|
10018
11993
|
) : null,
|
|
11994
|
+
state.projectPicker.open ? /* @__PURE__ */ jsx(
|
|
11995
|
+
ProjectPicker,
|
|
11996
|
+
{
|
|
11997
|
+
items: state.projectPicker.items,
|
|
11998
|
+
selected: state.projectPicker.selected,
|
|
11999
|
+
filter: state.projectPicker.filter,
|
|
12000
|
+
hint: state.projectPicker.hint
|
|
12001
|
+
}
|
|
12002
|
+
) : null,
|
|
12003
|
+
state.sessionsPanelOpen ? /* @__PURE__ */ jsx(
|
|
12004
|
+
SessionsPanel,
|
|
12005
|
+
{
|
|
12006
|
+
sessions: state.sessionsPanel.sessions,
|
|
12007
|
+
busy: state.sessionsPanel.busy,
|
|
12008
|
+
selected: state.sessionsPanel.selected,
|
|
12009
|
+
resumeConfirm: state.sessionResumeConfirm ? { sessionName: state.sessionResumeConfirm.sessionName } : void 0,
|
|
12010
|
+
currentSessionId: agent.ctx.session?.id
|
|
12011
|
+
}
|
|
12012
|
+
) : null,
|
|
10019
12013
|
state.rewindOverlay ? (() => {
|
|
10020
12014
|
const overlay = state.rewindOverlay;
|
|
10021
12015
|
return /* @__PURE__ */ jsx(
|
|
@@ -10043,7 +12037,7 @@ User message:
|
|
|
10043
12037
|
}
|
|
10044
12038
|
) }) : null,
|
|
10045
12039
|
state.confirmQueue.length > 0 && (() => {
|
|
10046
|
-
const head = expectDefined(state.confirmQueue[0]);
|
|
12040
|
+
const head = expectDefined$1(state.confirmQueue[0]);
|
|
10047
12041
|
let resolved = false;
|
|
10048
12042
|
const onDecision = (decision) => {
|
|
10049
12043
|
if (resolved) return;
|
|
@@ -10128,7 +12122,7 @@ User message:
|
|
|
10128
12122
|
}
|
|
10129
12123
|
);
|
|
10130
12124
|
})() : null,
|
|
10131
|
-
/* @__PURE__ */ jsx(
|
|
12125
|
+
/* @__PURE__ */ jsx(Box, { ref: statusBarWrapRef, flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx(
|
|
10132
12126
|
StatusBar,
|
|
10133
12127
|
{
|
|
10134
12128
|
model: `${liveProvider}/${liveModel}`,
|
|
@@ -10142,11 +12136,13 @@ User message:
|
|
|
10142
12136
|
startedAt: startedAtRef.current,
|
|
10143
12137
|
todos,
|
|
10144
12138
|
plan: planCounts ?? void 0,
|
|
12139
|
+
tasks: taskCounts ?? void 0,
|
|
10145
12140
|
fleet: fleetCounts,
|
|
10146
12141
|
git: gitInfo,
|
|
10147
12142
|
context: contextWindow,
|
|
10148
12143
|
brain: state.brain,
|
|
10149
12144
|
projectName,
|
|
12145
|
+
workingDir: workingDirChip,
|
|
10150
12146
|
subagentCount: Object.keys(state.fleet).length,
|
|
10151
12147
|
processCount: getProcessRegistry().activeCount,
|
|
10152
12148
|
hiddenItems,
|
|
@@ -10156,67 +12152,101 @@ User message:
|
|
|
10156
12152
|
modeLabel: liveModeLabel || void 0,
|
|
10157
12153
|
debugStreamStats: state.debugStreamStats,
|
|
10158
12154
|
enhanceCountdown,
|
|
10159
|
-
|
|
12155
|
+
nextStepsAutoSubmitCountdown,
|
|
12156
|
+
autoProceedCountdown: state.countdown?.remainingSeconds ?? null,
|
|
12157
|
+
sessionCount,
|
|
12158
|
+
mailbox: mailboxStatus
|
|
10160
12159
|
}
|
|
10161
|
-
),
|
|
10162
|
-
|
|
10163
|
-
|
|
10164
|
-
AgentsMonitor,
|
|
10165
|
-
{
|
|
10166
|
-
entries: entriesWithLeader,
|
|
10167
|
-
totalCost: state.fleetCost,
|
|
10168
|
-
leaderCost: tokenCounter?.estimateCost().total ?? 0,
|
|
10169
|
-
totalTokens: state.fleetTokens,
|
|
10170
|
-
nowTick
|
|
10171
|
-
}
|
|
10172
|
-
) : state.autoPhase?.monitorOpen ? /* @__PURE__ */ jsx(
|
|
10173
|
-
PhaseMonitor,
|
|
10174
|
-
{
|
|
10175
|
-
phases: state.autoPhase.phases,
|
|
10176
|
-
runningPhaseIds: state.autoPhase.runningPhaseIds,
|
|
10177
|
-
elapsedMs: state.autoPhase.elapsedMs,
|
|
10178
|
-
nowTick,
|
|
10179
|
-
onClose: () => dispatch({ type: "autoPhaseMonitorToggle" })
|
|
10180
|
-
}
|
|
10181
|
-
) : state.worktreeMonitorOpen ? /* @__PURE__ */ jsx(
|
|
10182
|
-
WorktreeMonitor,
|
|
10183
|
-
{
|
|
10184
|
-
worktrees: state.worktrees,
|
|
10185
|
-
baseBranch: state.worktreeBase,
|
|
10186
|
-
nowTick,
|
|
10187
|
-
onClose: () => dispatch({ type: "worktreeMonitorToggle" })
|
|
10188
|
-
}
|
|
10189
|
-
) : state.todosMonitorOpen ? /* @__PURE__ */ jsx(TodosMonitor, { todos: agent.ctx.todos }) : state.monitorOpen ? /* @__PURE__ */ jsx(
|
|
10190
|
-
FleetMonitor,
|
|
10191
|
-
{
|
|
10192
|
-
entries: state.fleet,
|
|
10193
|
-
totalCost: state.fleetCost,
|
|
10194
|
-
totalTokens: state.fleetTokens,
|
|
10195
|
-
maxConcurrent: state.fleetConcurrency,
|
|
10196
|
-
nowTick,
|
|
10197
|
-
collabSession: state.collabSession
|
|
10198
|
-
}
|
|
10199
|
-
) : director ? /* @__PURE__ */ jsx(
|
|
10200
|
-
FleetPanel,
|
|
10201
|
-
{
|
|
10202
|
-
entries: entriesWithLeader,
|
|
10203
|
-
totalCost: state.fleetCost,
|
|
10204
|
-
roster: fleetRoster,
|
|
10205
|
-
collabSession: state.collabSession
|
|
10206
|
-
}
|
|
10207
|
-
) : null,
|
|
10208
|
-
state.autoPhase && !state.autoPhase.monitorOpen ? /* @__PURE__ */ jsx(
|
|
10209
|
-
PhasePanel,
|
|
12160
|
+
) }),
|
|
12161
|
+
/* @__PURE__ */ jsx(
|
|
12162
|
+
MailboxPanel,
|
|
10210
12163
|
{
|
|
10211
|
-
|
|
10212
|
-
|
|
10213
|
-
|
|
12164
|
+
messages: mailboxMessages,
|
|
12165
|
+
agents: mailboxAgents,
|
|
12166
|
+
unreadCount: mailboxStatus.unread,
|
|
12167
|
+
open: mailboxPanelOpen
|
|
10214
12168
|
}
|
|
10215
|
-
)
|
|
10216
|
-
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
|
|
12169
|
+
),
|
|
12170
|
+
/* @__PURE__ */ jsxs(Box, { ref: belowStatusBarRef, flexDirection: "column", flexShrink: 0, children: [
|
|
12171
|
+
state.helpOpen ? /* @__PURE__ */ jsx(HelpOverlay, {}) : null,
|
|
12172
|
+
state.agentsMonitorOpen ? /* @__PURE__ */ jsx(
|
|
12173
|
+
AgentsMonitor,
|
|
12174
|
+
{
|
|
12175
|
+
entries: entriesWithLeader,
|
|
12176
|
+
totalCost: state.fleetCost,
|
|
12177
|
+
leaderCost: tokenCounter?.estimateCost().total ?? 0,
|
|
12178
|
+
totalTokens: state.fleetTokens,
|
|
12179
|
+
nowTick
|
|
12180
|
+
}
|
|
12181
|
+
) : state.autoPhase?.monitorOpen ? /* @__PURE__ */ jsx(
|
|
12182
|
+
PhaseMonitor,
|
|
12183
|
+
{
|
|
12184
|
+
phases: state.autoPhase.phases,
|
|
12185
|
+
runningPhaseIds: state.autoPhase.runningPhaseIds,
|
|
12186
|
+
elapsedMs: state.autoPhase.elapsedMs,
|
|
12187
|
+
nowTick,
|
|
12188
|
+
onClose: () => dispatch({ type: "autoPhaseMonitorToggle" })
|
|
12189
|
+
}
|
|
12190
|
+
) : state.worktreeMonitorOpen ? /* @__PURE__ */ jsx(
|
|
12191
|
+
WorktreeMonitor,
|
|
12192
|
+
{
|
|
12193
|
+
worktrees: state.worktrees,
|
|
12194
|
+
baseBranch: state.worktreeBase,
|
|
12195
|
+
nowTick,
|
|
12196
|
+
onClose: () => dispatch({ type: "worktreeMonitorToggle" })
|
|
12197
|
+
}
|
|
12198
|
+
) : state.todosMonitorOpen ? /* @__PURE__ */ jsx(TodosMonitor, { todos: agent.ctx.todos }) : state.monitorOpen ? /* @__PURE__ */ jsx(
|
|
12199
|
+
FleetMonitor,
|
|
12200
|
+
{
|
|
12201
|
+
entries: state.fleet,
|
|
12202
|
+
totalCost: state.fleetCost,
|
|
12203
|
+
totalTokens: state.fleetTokens,
|
|
12204
|
+
maxConcurrent: state.fleetConcurrency,
|
|
12205
|
+
nowTick,
|
|
12206
|
+
collabSession: state.collabSession
|
|
12207
|
+
}
|
|
12208
|
+
) : director ? /* @__PURE__ */ jsx(
|
|
12209
|
+
FleetPanel,
|
|
12210
|
+
{
|
|
12211
|
+
entries: entriesWithLeader,
|
|
12212
|
+
totalCost: state.fleetCost,
|
|
12213
|
+
roster: fleetRoster,
|
|
12214
|
+
collabSession: state.collabSession
|
|
12215
|
+
}
|
|
12216
|
+
) : null,
|
|
12217
|
+
state.autoPhase && !state.autoPhase.monitorOpen ? /* @__PURE__ */ jsx(
|
|
12218
|
+
PhasePanel,
|
|
12219
|
+
{
|
|
12220
|
+
phases: state.autoPhase.phases,
|
|
12221
|
+
runningPhaseIds: state.autoPhase.runningPhaseIds,
|
|
12222
|
+
nowTick
|
|
12223
|
+
}
|
|
12224
|
+
) : null,
|
|
12225
|
+
Object.keys(state.worktrees).length > 0 && !state.worktreeMonitorOpen && !state.monitorOpen ? /* @__PURE__ */ jsx(WorktreePanel, { worktrees: state.worktrees, nowTick }) : null,
|
|
12226
|
+
state.queuePanelOpen ? /* @__PURE__ */ jsx(QueuePanel, { items: state.queue }) : null,
|
|
12227
|
+
state.processListOpen ? /* @__PURE__ */ jsx(ProcessListMonitor, {}) : null,
|
|
12228
|
+
state.goalPanelOpen ? /* @__PURE__ */ jsx(GoalPanel, { goal: state.goalSummary }) : null,
|
|
12229
|
+
(() => {
|
|
12230
|
+
const anyMonitorOpen = state.agentsMonitorOpen || (state.autoPhase?.monitorOpen ?? false) || state.worktreeMonitorOpen || state.todosMonitorOpen || state.monitorOpen || state.processListOpen || state.queuePanelOpen || state.goalPanelOpen;
|
|
12231
|
+
let nextPanelHint;
|
|
12232
|
+
if (state.agentsMonitorOpen) {
|
|
12233
|
+
nextPanelHint = { key: "F6", label: "todos" };
|
|
12234
|
+
} else if (state.autoPhase?.monitorOpen || state.worktreeMonitorOpen || state.todosMonitorOpen) {
|
|
12235
|
+
nextPanelHint = { key: "F9", label: "goal" };
|
|
12236
|
+
} else if (state.queuePanelOpen || state.processListOpen || state.goalPanelOpen) {
|
|
12237
|
+
nextPanelHint = { key: "F3", label: "agents" };
|
|
12238
|
+
} else if (anyMonitorOpen) {
|
|
12239
|
+
nextPanelHint = { key: "F3", label: "agents" };
|
|
12240
|
+
}
|
|
12241
|
+
const ctx = {
|
|
12242
|
+
monitor: anyMonitorOpen,
|
|
12243
|
+
managed: state.scrollOffset > 0,
|
|
12244
|
+
picker: state.settingsPicker.open || state.modelPicker.open || state.autonomyPicker.open,
|
|
12245
|
+
nextPanelHint
|
|
12246
|
+
};
|
|
12247
|
+
return /* @__PURE__ */ jsx(KeyHintBar, { context: ctx });
|
|
12248
|
+
})()
|
|
12249
|
+
] })
|
|
10220
12250
|
] })
|
|
10221
12251
|
] }) });
|
|
10222
12252
|
}
|
|
@@ -10318,6 +12348,45 @@ function startTerminalTitle(opts) {
|
|
|
10318
12348
|
// src/run-tui.ts
|
|
10319
12349
|
var BRACKETED_PASTE_ON = "\x1B[?2004h";
|
|
10320
12350
|
var BRACKETED_PASTE_OFF = "\x1B[?2004l";
|
|
12351
|
+
var origConsoleLog = console.log;
|
|
12352
|
+
var origConsoleWarn = console.warn;
|
|
12353
|
+
var origConsoleError = console.error;
|
|
12354
|
+
var origConsoleDebug = console.debug;
|
|
12355
|
+
var origConsoleInfo = console.info;
|
|
12356
|
+
var origConsoleTable = console.table;
|
|
12357
|
+
var origConsoleTrace = console.trace;
|
|
12358
|
+
var origStderrWrite = process.stderr.write.bind(process.stderr);
|
|
12359
|
+
var consoleNoop = (..._args) => {
|
|
12360
|
+
};
|
|
12361
|
+
var stderrNoop = ((_chunk, _encodingOrCb, _cb) => {
|
|
12362
|
+
if (typeof _encodingOrCb === "function") _encodingOrCb();
|
|
12363
|
+
else if (typeof _cb === "function") _cb();
|
|
12364
|
+
return true;
|
|
12365
|
+
});
|
|
12366
|
+
var warningNoop = (_warning) => {
|
|
12367
|
+
};
|
|
12368
|
+
function silenceTerminal() {
|
|
12369
|
+
console.log = consoleNoop;
|
|
12370
|
+
console.warn = consoleNoop;
|
|
12371
|
+
console.error = consoleNoop;
|
|
12372
|
+
console.debug = consoleNoop;
|
|
12373
|
+
console.info = consoleNoop;
|
|
12374
|
+
console.table = consoleNoop;
|
|
12375
|
+
console.trace = consoleNoop;
|
|
12376
|
+
process.stderr.write = stderrNoop;
|
|
12377
|
+
process.on("warning", warningNoop);
|
|
12378
|
+
}
|
|
12379
|
+
function unsilenceTerminal() {
|
|
12380
|
+
console.log = origConsoleLog;
|
|
12381
|
+
console.warn = origConsoleWarn;
|
|
12382
|
+
console.error = origConsoleError;
|
|
12383
|
+
console.debug = origConsoleDebug;
|
|
12384
|
+
console.info = origConsoleInfo;
|
|
12385
|
+
console.table = origConsoleTable;
|
|
12386
|
+
console.trace = origConsoleTrace;
|
|
12387
|
+
process.stderr.write = origStderrWrite;
|
|
12388
|
+
process.off("warning", warningNoop);
|
|
12389
|
+
}
|
|
10321
12390
|
async function runTui(opts) {
|
|
10322
12391
|
const stdout = process.stdout;
|
|
10323
12392
|
const stdin = process.stdin;
|
|
@@ -10327,10 +12396,17 @@ async function runTui(opts) {
|
|
|
10327
12396
|
);
|
|
10328
12397
|
return 2;
|
|
10329
12398
|
}
|
|
12399
|
+
silenceTerminal();
|
|
10330
12400
|
stdout.write(BRACKETED_PASTE_ON);
|
|
12401
|
+
const mouseEnabled = opts.mouse ?? opts.getSettings?.().mouseMode ?? process.env.WRONGSTACK_MOUSE === "1";
|
|
10331
12402
|
stdout.write("\x1B[2J\x1B[H");
|
|
10332
12403
|
const inkStdin = stdin;
|
|
10333
|
-
const stopTitle = opts.titleAnimation !== false ? startTerminalTitle({
|
|
12404
|
+
const stopTitle = opts.titleAnimation !== false ? startTerminalTitle({
|
|
12405
|
+
stdout,
|
|
12406
|
+
events: opts.events,
|
|
12407
|
+
model: opts.model,
|
|
12408
|
+
appName: opts.projectRoot ? path4.basename(opts.projectRoot) : void 0
|
|
12409
|
+
}) : (() => {
|
|
10334
12410
|
});
|
|
10335
12411
|
const swallowSignals = ["SIGTSTP", "SIGQUIT", "SIGTTIN", "SIGTTOU"];
|
|
10336
12412
|
const swallow = () => {
|
|
@@ -10345,12 +12421,14 @@ async function runTui(opts) {
|
|
|
10345
12421
|
const cleanup = () => {
|
|
10346
12422
|
if (cleaned) return;
|
|
10347
12423
|
cleaned = true;
|
|
12424
|
+
unsilenceTerminal();
|
|
10348
12425
|
try {
|
|
10349
12426
|
stopTitle();
|
|
10350
12427
|
} catch {
|
|
10351
12428
|
}
|
|
10352
12429
|
try {
|
|
10353
12430
|
stdout.write(BRACKETED_PASTE_OFF);
|
|
12431
|
+
stdout.write(MOUSE_OFF);
|
|
10354
12432
|
} catch {
|
|
10355
12433
|
}
|
|
10356
12434
|
};
|
|
@@ -10371,14 +12449,26 @@ async function runTui(opts) {
|
|
|
10371
12449
|
};
|
|
10372
12450
|
return new Promise((resolve) => {
|
|
10373
12451
|
let exitCode = 0;
|
|
12452
|
+
let hardExitTimer = null;
|
|
10374
12453
|
const onExit = (code) => {
|
|
10375
12454
|
exitCode = code;
|
|
10376
12455
|
};
|
|
10377
12456
|
const settle = (code) => {
|
|
12457
|
+
if (hardExitTimer) {
|
|
12458
|
+
clearTimeout(hardExitTimer);
|
|
12459
|
+
hardExitTimer = null;
|
|
12460
|
+
}
|
|
10378
12461
|
cleanup();
|
|
10379
12462
|
detachListeners();
|
|
10380
12463
|
resolve(code);
|
|
10381
12464
|
};
|
|
12465
|
+
const requestExit = (code) => {
|
|
12466
|
+
onExit(code);
|
|
12467
|
+
instance?.unmount();
|
|
12468
|
+
hardExitTimer = setTimeout(() => process.exit(code), 5e3);
|
|
12469
|
+
hardExitTimer.unref();
|
|
12470
|
+
};
|
|
12471
|
+
opts.requestExit = requestExit;
|
|
10382
12472
|
let instance;
|
|
10383
12473
|
try {
|
|
10384
12474
|
instance = render(
|
|
@@ -10393,6 +12483,7 @@ async function runTui(opts) {
|
|
|
10393
12483
|
model: opts.model,
|
|
10394
12484
|
banner: opts.banner ?? true,
|
|
10395
12485
|
queueStore: opts.queueStore,
|
|
12486
|
+
onQueueChange: opts.onQueueChange,
|
|
10396
12487
|
yolo: opts.yolo,
|
|
10397
12488
|
getYolo: opts.getYolo,
|
|
10398
12489
|
getAutonomy: opts.getAutonomy,
|
|
@@ -10428,12 +12519,24 @@ async function runTui(opts) {
|
|
|
10428
12519
|
getSettings: opts.getSettings,
|
|
10429
12520
|
saveSettings: opts.saveSettings,
|
|
10430
12521
|
predictNext: opts.predictNext,
|
|
12522
|
+
onSuggestionsParsed: opts.onSuggestionsParsed,
|
|
10431
12523
|
chime: opts.chime,
|
|
10432
12524
|
confirmExit: opts.confirmExit,
|
|
12525
|
+
mouse: mouseEnabled,
|
|
10433
12526
|
modeLabel: opts.modeLabel,
|
|
10434
12527
|
getModeLabel: opts.getModeLabel,
|
|
10435
12528
|
registerDebugStreamCallback: opts.registerDebugStreamCallback,
|
|
10436
|
-
restoreDebugStreamCallback: opts.restoreDebugStreamCallback
|
|
12529
|
+
restoreDebugStreamCallback: opts.restoreDebugStreamCallback,
|
|
12530
|
+
restoredMessages: opts.restoredMessages,
|
|
12531
|
+
restoredToolCalls: opts.restoredToolCalls,
|
|
12532
|
+
listSessions: opts.listSessions,
|
|
12533
|
+
onResumeSession: opts.onResumeSession,
|
|
12534
|
+
getProjectPickerItems: opts.getProjectPickerItems,
|
|
12535
|
+
onProjectSelect: opts.onProjectSelect,
|
|
12536
|
+
requestExit: opts.requestExit,
|
|
12537
|
+
getLiveSessions: opts.getLiveSessions,
|
|
12538
|
+
onSwitchToSession: opts.onSwitchToSession,
|
|
12539
|
+
initialAgentsMonitorOpen: opts.initialAgentsMonitorOpen
|
|
10437
12540
|
}),
|
|
10438
12541
|
{ exitOnCtrlC: false, stdin: inkStdin }
|
|
10439
12542
|
);
|
|
@@ -10464,6 +12567,190 @@ async function runTui(opts) {
|
|
|
10464
12567
|
});
|
|
10465
12568
|
}
|
|
10466
12569
|
|
|
10467
|
-
|
|
12570
|
+
// src/components/history/replay.ts
|
|
12571
|
+
function replaySessionEvents(events, startId) {
|
|
12572
|
+
const entries = [];
|
|
12573
|
+
let nextId = startId;
|
|
12574
|
+
const pendingTools = /* @__PURE__ */ new Map();
|
|
12575
|
+
const completedTools = /* @__PURE__ */ new Set();
|
|
12576
|
+
for (const ev of events) {
|
|
12577
|
+
const entry = eventToEntry(ev, pendingTools, completedTools);
|
|
12578
|
+
if (entry) {
|
|
12579
|
+
entries.push({ ...entry, id: nextId++ });
|
|
12580
|
+
}
|
|
12581
|
+
}
|
|
12582
|
+
for (const [, tu] of pendingTools) {
|
|
12583
|
+
entries.push({
|
|
12584
|
+
id: nextId++,
|
|
12585
|
+
kind: "tool",
|
|
12586
|
+
name: tu.name,
|
|
12587
|
+
durationMs: 0,
|
|
12588
|
+
ok: false,
|
|
12589
|
+
input: tu.input
|
|
12590
|
+
});
|
|
12591
|
+
}
|
|
12592
|
+
return entries;
|
|
12593
|
+
}
|
|
12594
|
+
function eventToEntry(ev, pendingTools, completedTools) {
|
|
12595
|
+
switch (ev.type) {
|
|
12596
|
+
case "user_input": {
|
|
12597
|
+
const text = typeof ev.content === "string" ? ev.content : Array.isArray(ev.content) ? ev.content.filter((b) => b.type === "text").map((b) => b.text).join("") : "";
|
|
12598
|
+
if (!text.trim()) return null;
|
|
12599
|
+
return { kind: "user", text };
|
|
12600
|
+
}
|
|
12601
|
+
case "llm_response": {
|
|
12602
|
+
const text = ev.content.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
12603
|
+
if (!text.trim()) return null;
|
|
12604
|
+
return { kind: "assistant", text };
|
|
12605
|
+
}
|
|
12606
|
+
case "tool_use": {
|
|
12607
|
+
pendingTools.set(ev.id, { name: ev.name, input: ev.input, ts: ev.ts });
|
|
12608
|
+
return null;
|
|
12609
|
+
}
|
|
12610
|
+
case "tool_result": {
|
|
12611
|
+
if (completedTools.has(ev.id)) {
|
|
12612
|
+
completedTools.delete(ev.id);
|
|
12613
|
+
return null;
|
|
12614
|
+
}
|
|
12615
|
+
const tu = pendingTools.get(ev.id);
|
|
12616
|
+
pendingTools.delete(ev.id);
|
|
12617
|
+
return {
|
|
12618
|
+
kind: "tool",
|
|
12619
|
+
name: tu?.name ?? ev.id,
|
|
12620
|
+
durationMs: 0,
|
|
12621
|
+
// duration not available from tool_result alone
|
|
12622
|
+
ok: !ev.isError,
|
|
12623
|
+
input: tu?.input,
|
|
12624
|
+
output: typeof ev.content === "string" ? ev.content.slice(0, 400) : void 0
|
|
12625
|
+
};
|
|
12626
|
+
}
|
|
12627
|
+
case "tool_call_start": {
|
|
12628
|
+
pendingTools.set(ev.id, { name: ev.name, input: ev.input, ts: ev.ts });
|
|
12629
|
+
return null;
|
|
12630
|
+
}
|
|
12631
|
+
case "tool_call_end": {
|
|
12632
|
+
const tu = pendingTools.get(ev.id);
|
|
12633
|
+
pendingTools.delete(ev.id);
|
|
12634
|
+
completedTools.add(ev.id);
|
|
12635
|
+
return {
|
|
12636
|
+
kind: "tool",
|
|
12637
|
+
name: tu?.name ?? ev.name,
|
|
12638
|
+
durationMs: ev.durationMs,
|
|
12639
|
+
ok: ev.ok ?? false,
|
|
12640
|
+
input: tu?.input,
|
|
12641
|
+
outputBytes: ev.outputBytes,
|
|
12642
|
+
outputTokens: ev.outputTokens,
|
|
12643
|
+
outputLines: ev.outputLines
|
|
12644
|
+
};
|
|
12645
|
+
}
|
|
12646
|
+
case "compaction": {
|
|
12647
|
+
const before = (ev.before / 1e3).toFixed(0);
|
|
12648
|
+
const after = (ev.after / 1e3).toFixed(0);
|
|
12649
|
+
const level = ev.level ? ` (${ev.level})` : "";
|
|
12650
|
+
const reductions = ev.reductions && ev.reductions.length > 0 ? ` [${ev.reductions.map((r) => `${r.phase}: \u2212${r.saved}`).join(", ")}]` : "";
|
|
12651
|
+
return {
|
|
12652
|
+
kind: "info",
|
|
12653
|
+
text: `\u27F2 context compacted${level}: ${before}K \u2192 ${after}K tokens${reductions}`
|
|
12654
|
+
};
|
|
12655
|
+
}
|
|
12656
|
+
case "error": {
|
|
12657
|
+
return {
|
|
12658
|
+
kind: "error",
|
|
12659
|
+
text: ev.phase ? `[${ev.phase}] ${ev.message}` : ev.message
|
|
12660
|
+
};
|
|
12661
|
+
}
|
|
12662
|
+
case "provider_retry": {
|
|
12663
|
+
const secs = (ev.delayMs / 1e3).toFixed(ev.delayMs >= 1e3 ? 1 : 2);
|
|
12664
|
+
return {
|
|
12665
|
+
kind: "warn",
|
|
12666
|
+
text: ev.status ? `\u27F3 retry ${ev.attempt} (HTTP ${ev.status}) after ${secs}s \u2014 ${ev.description}` : `\u27F3 retry ${ev.attempt} after ${secs}s \u2014 ${ev.description}`
|
|
12667
|
+
};
|
|
12668
|
+
}
|
|
12669
|
+
case "provider_error": {
|
|
12670
|
+
return {
|
|
12671
|
+
kind: "error",
|
|
12672
|
+
text: ev.status ? `provider error (HTTP ${ev.status}, ${ev.retryable ? "retryable" : "fatal"}): ${ev.description}` : `provider error (${ev.retryable ? "retryable" : "fatal"}): ${ev.description}`
|
|
12673
|
+
};
|
|
12674
|
+
}
|
|
12675
|
+
case "checkpoint": {
|
|
12676
|
+
return {
|
|
12677
|
+
kind: "info",
|
|
12678
|
+
text: `\u2713 checkpoint #${ev.promptIndex}: "${ev.promptPreview.slice(0, 60)}"`
|
|
12679
|
+
};
|
|
12680
|
+
}
|
|
12681
|
+
case "agent_spawned": {
|
|
12682
|
+
return {
|
|
12683
|
+
kind: "subagent",
|
|
12684
|
+
agentLabel: ev.agentId.slice(0, 8),
|
|
12685
|
+
agentColor: "magenta",
|
|
12686
|
+
icon: "\u26A1",
|
|
12687
|
+
text: `spawned as ${ev.role}`
|
|
12688
|
+
};
|
|
12689
|
+
}
|
|
12690
|
+
case "agent_stopped": {
|
|
12691
|
+
return {
|
|
12692
|
+
kind: "subagent",
|
|
12693
|
+
agentLabel: ev.agentId.slice(0, 8),
|
|
12694
|
+
agentColor: "gray",
|
|
12695
|
+
icon: "\u2298",
|
|
12696
|
+
text: "stopped"
|
|
12697
|
+
};
|
|
12698
|
+
}
|
|
12699
|
+
case "agent_error": {
|
|
12700
|
+
return {
|
|
12701
|
+
kind: "subagent",
|
|
12702
|
+
agentLabel: ev.agentId.slice(0, 8),
|
|
12703
|
+
agentColor: "red",
|
|
12704
|
+
icon: "\u2717",
|
|
12705
|
+
text: `error: ${ev.error.slice(0, 80)}`
|
|
12706
|
+
};
|
|
12707
|
+
}
|
|
12708
|
+
case "mode_changed": {
|
|
12709
|
+
return {
|
|
12710
|
+
kind: "info",
|
|
12711
|
+
text: `mode: ${ev.from} \u2192 ${ev.to}`
|
|
12712
|
+
};
|
|
12713
|
+
}
|
|
12714
|
+
case "skill_activated": {
|
|
12715
|
+
return {
|
|
12716
|
+
kind: "info",
|
|
12717
|
+
text: `skill activated: ${ev.skillName}`
|
|
12718
|
+
};
|
|
12719
|
+
}
|
|
12720
|
+
case "skill_deactivated": {
|
|
12721
|
+
return {
|
|
12722
|
+
kind: "info",
|
|
12723
|
+
text: `skill deactivated: ${ev.skillName}`
|
|
12724
|
+
};
|
|
12725
|
+
}
|
|
12726
|
+
case "message_truncated": {
|
|
12727
|
+
return {
|
|
12728
|
+
kind: "warn",
|
|
12729
|
+
text: ev.after < ev.before ? `message truncated: ${ev.before} \u2192 ${ev.after} tokens` : `message truncated at ${ev.after} tokens`
|
|
12730
|
+
};
|
|
12731
|
+
}
|
|
12732
|
+
// Skipped — internal markers not relevant for display
|
|
12733
|
+
case "session_start":
|
|
12734
|
+
case "session_resumed":
|
|
12735
|
+
case "session_end":
|
|
12736
|
+
case "in_flight_start":
|
|
12737
|
+
case "in_flight_end":
|
|
12738
|
+
case "llm_request":
|
|
12739
|
+
case "tool_progress":
|
|
12740
|
+
case "rewound":
|
|
12741
|
+
case "file_snapshot":
|
|
12742
|
+
case "task_created":
|
|
12743
|
+
case "task_updated":
|
|
12744
|
+
case "task_completed":
|
|
12745
|
+
case "task_failed":
|
|
12746
|
+
case "spec_parsed":
|
|
12747
|
+
case "spec_analyzed":
|
|
12748
|
+
return null;
|
|
12749
|
+
default:
|
|
12750
|
+
return null;
|
|
12751
|
+
}
|
|
12752
|
+
}
|
|
12753
|
+
|
|
12754
|
+
export { parseInline, replaySessionEvents, runTui };
|
|
10468
12755
|
//# sourceMappingURL=index.js.map
|
|
10469
12756
|
//# sourceMappingURL=index.js.map
|