@wrongstack/tui 0.155.0 → 0.250.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 +320 -2
- package/dist/index.js +2628 -291
- 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 * as
|
|
5
|
-
import React5, { useState, useEffect, useMemo, memo, useRef, useCallback, useReducer } from 'react';
|
|
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';
|
|
6
6
|
import * as fs2 from 'fs/promises';
|
|
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" }),
|
|
@@ -210,6 +295,9 @@ function StatusBar({
|
|
|
210
295
|
"/",
|
|
211
296
|
indexState.totalFiles
|
|
212
297
|
] })
|
|
298
|
+
] }) : indexState?.circuit?.state === "open" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
299
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
300
|
+
/* @__PURE__ */ jsx(Text, { color: "red", children: "\u2699 index paused (/reindex)" })
|
|
213
301
|
] }) : null
|
|
214
302
|
] })
|
|
215
303
|
) }),
|
|
@@ -247,8 +335,15 @@ function StatusBar({
|
|
|
247
335
|
projectName
|
|
248
336
|
] })
|
|
249
337
|
] }) : null,
|
|
338
|
+
workingDir && !hiddenSet.has("working_dir") ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
339
|
+
yolo || startedAt != null || projectName || goalSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
340
|
+
/* @__PURE__ */ jsxs(Text, { color: "blue", children: [
|
|
341
|
+
"\u{1F4C2} ",
|
|
342
|
+
workingDir
|
|
343
|
+
] })
|
|
344
|
+
] }) : null,
|
|
250
345
|
goalSummary ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
251
|
-
yolo || startedAt != null || projectName ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
346
|
+
yolo || startedAt != null || projectName || workingDir ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
252
347
|
/* @__PURE__ */ jsxs(
|
|
253
348
|
Text,
|
|
254
349
|
{
|
|
@@ -268,11 +363,11 @@ function StatusBar({
|
|
|
268
363
|
)
|
|
269
364
|
] }) : null,
|
|
270
365
|
modeLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
271
|
-
yolo || autonomy && autonomy !== "off" || eternalStage || startedAt != null || projectName || goalSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
366
|
+
yolo || autonomy && autonomy !== "off" || eternalStage || startedAt != null || projectName || workingDir || goalSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
272
367
|
/* @__PURE__ */ jsx(Text, { color: "cyan", children: modeIcon(modeLabel) })
|
|
273
368
|
] }) : null,
|
|
274
369
|
hasAutoProceed ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
275
|
-
yolo || autonomy && autonomy !== "off" || eternalStage || startedAt != null || projectName || goalSummary || modeLabel ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
370
|
+
yolo || autonomy && autonomy !== "off" || eternalStage || startedAt != null || projectName || workingDir || goalSummary || modeLabel ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
276
371
|
/* @__PURE__ */ jsxs(Text, { color: autoProceedCountdown != null && autoProceedCountdown <= 5 ? "yellow" : "cyan", children: [
|
|
277
372
|
"\u23F3 auto in ",
|
|
278
373
|
autoProceedCountdown,
|
|
@@ -280,16 +375,12 @@ function StatusBar({
|
|
|
280
375
|
] })
|
|
281
376
|
] }) : null,
|
|
282
377
|
git ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
283
|
-
yolo || startedAt != null || projectName ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
378
|
+
yolo || startedAt != null || projectName || workingDir ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
284
379
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
285
380
|
/* @__PURE__ */ jsxs(Text, { color: "magenta", children: [
|
|
286
381
|
"\u2387 ",
|
|
287
382
|
git.branch
|
|
288
383
|
] }),
|
|
289
|
-
git.added > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
290
|
-
" +",
|
|
291
|
-
git.added
|
|
292
|
-
] }) : null,
|
|
293
384
|
git.deleted > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
294
385
|
" -",
|
|
295
386
|
git.deleted
|
|
@@ -299,6 +390,15 @@ function StatusBar({
|
|
|
299
390
|
git.untracked
|
|
300
391
|
] }) : null
|
|
301
392
|
] })
|
|
393
|
+
] }) : null,
|
|
394
|
+
sessionCount != null && sessionCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
395
|
+
yolo || startedAt != null || projectName || workingDir || git ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
396
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
397
|
+
"\u29C9 ",
|
|
398
|
+
sessionCount,
|
|
399
|
+
" session",
|
|
400
|
+
sessionCount === 1 ? "" : "s"
|
|
401
|
+
] })
|
|
302
402
|
] }) : null
|
|
303
403
|
] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
|
|
304
404
|
hasThirdLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
@@ -339,6 +439,36 @@ function StatusBar({
|
|
|
339
439
|
] }) : null
|
|
340
440
|
] })
|
|
341
441
|
] }) : null,
|
|
442
|
+
hasTaskActivity ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
443
|
+
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,
|
|
444
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
445
|
+
/* @__PURE__ */ jsx(Text, { color: "magenta", children: "\u26A1 " }),
|
|
446
|
+
tasks.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
447
|
+
"\u231B",
|
|
448
|
+
tasks.inProgress
|
|
449
|
+
] }) : null,
|
|
450
|
+
tasks.inProgress > 0 && (tasks.pending > 0 || tasks.blocked > 0) ? " " : "",
|
|
451
|
+
tasks.pending > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
452
|
+
"\u2610",
|
|
453
|
+
tasks.pending
|
|
454
|
+
] }) : null,
|
|
455
|
+
tasks.pending > 0 && tasks.blocked > 0 ? " " : "",
|
|
456
|
+
tasks.blocked > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
457
|
+
"\u2298",
|
|
458
|
+
tasks.blocked
|
|
459
|
+
] }) : null,
|
|
460
|
+
(tasks.pending > 0 || tasks.blocked > 0) && (tasks.completed > 0 || tasks.failed > 0) ? " " : "",
|
|
461
|
+
tasks.completed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
462
|
+
"\u2713",
|
|
463
|
+
tasks.completed
|
|
464
|
+
] }) : null,
|
|
465
|
+
tasks.completed > 0 && tasks.failed > 0 ? " " : "",
|
|
466
|
+
tasks.failed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
467
|
+
"\u2717",
|
|
468
|
+
tasks.failed
|
|
469
|
+
] }) : null
|
|
470
|
+
] })
|
|
471
|
+
] }) : null,
|
|
342
472
|
fleetHasActivity ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
343
473
|
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
474
|
fleet ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
@@ -405,9 +535,64 @@ function StatusBar({
|
|
|
405
535
|
enhanceCountdown,
|
|
406
536
|
"s"
|
|
407
537
|
] })
|
|
538
|
+
] }) : null,
|
|
539
|
+
hasNextStepsAutoSubmit && nextStepsAutoSubmitCountdown != null ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
540
|
+
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,
|
|
541
|
+
/* @__PURE__ */ jsxs(Text, { color: nextStepsAutoSubmitCountdown <= 3 ? "yellow" : "cyan", children: [
|
|
542
|
+
"\u23F3 next step in ",
|
|
543
|
+
nextStepsAutoSubmitCountdown,
|
|
544
|
+
"s"
|
|
545
|
+
] })
|
|
408
546
|
] }) : null
|
|
409
547
|
] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
|
|
410
|
-
|
|
548
|
+
mailbox ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
549
|
+
mailbox.unread > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", bold: true, children: [
|
|
550
|
+
"\u2709 ",
|
|
551
|
+
mailbox.unread,
|
|
552
|
+
" new"
|
|
553
|
+
] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2709 0" }),
|
|
554
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
555
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
556
|
+
"\u{1F465} ",
|
|
557
|
+
mailbox.onlineAgents,
|
|
558
|
+
" online"
|
|
559
|
+
] }),
|
|
560
|
+
mailbox.lastSubject ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
561
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
562
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
563
|
+
mailbox.lastFrom ? `${mailbox.lastFrom}: ` : "",
|
|
564
|
+
mailbox.lastSubject.length > 40 ? `${mailbox.lastSubject.slice(0, 37)}\u2026` : mailbox.lastSubject
|
|
565
|
+
] })
|
|
566
|
+
] }) : null,
|
|
567
|
+
fleetAgents && fleetAgents.length > 0 ? fleetAgents.map((a, i) => (
|
|
568
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: agent list is stable per render
|
|
569
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
570
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
571
|
+
" ",
|
|
572
|
+
/* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
|
|
573
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
574
|
+
/* @__PURE__ */ jsx(Text, { dimColor: !a.running, ...a.running ? { color: "yellow" } : {}, children: a.running ? "\u25B6" : "\xB7" }),
|
|
575
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
576
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtElapsed(a.elapsedMs) }),
|
|
577
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
578
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
579
|
+
a.toolCalls,
|
|
580
|
+
"t"
|
|
581
|
+
] }),
|
|
582
|
+
a.tool ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
583
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
584
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: a.tool })
|
|
585
|
+
] }) : null,
|
|
586
|
+
a.extensions && a.extensions > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
587
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
588
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
589
|
+
"\u26A1\xD7",
|
|
590
|
+
a.extensions
|
|
591
|
+
] })
|
|
592
|
+
] }) : null
|
|
593
|
+
] }, i)
|
|
594
|
+
)) : null
|
|
595
|
+
] }) : fleetAgents && fleetAgents.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => (
|
|
411
596
|
// biome-ignore lint/suspicious/noArrayIndexKey: agent list is stable per render
|
|
412
597
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
413
598
|
/* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
|
|
@@ -513,6 +698,32 @@ function EternalStageChip({
|
|
|
513
698
|
] });
|
|
514
699
|
}
|
|
515
700
|
}
|
|
701
|
+
var SB_GAP = 2;
|
|
702
|
+
var SB_PADX = 1;
|
|
703
|
+
function statusBarModelSpan(opts) {
|
|
704
|
+
let col = SB_PADX;
|
|
705
|
+
if (opts.version) {
|
|
706
|
+
col += `WS v${opts.version}`.length + SB_GAP;
|
|
707
|
+
col += 1 + SB_GAP;
|
|
708
|
+
}
|
|
709
|
+
const { label } = stateChip(opts.state, opts.fleetRunning ?? 0);
|
|
710
|
+
col += 2 + label.length + SB_GAP;
|
|
711
|
+
col += 1 + SB_GAP;
|
|
712
|
+
return { start: col, len: opts.model.length };
|
|
713
|
+
}
|
|
714
|
+
function statusBarAutonomySpan(opts) {
|
|
715
|
+
if (!opts.autonomy || opts.autonomy === "off") return null;
|
|
716
|
+
let col = SB_PADX;
|
|
717
|
+
if (opts.yolo) {
|
|
718
|
+
col += "\u26A0 YOLO".length + SB_GAP;
|
|
719
|
+
col += 1 + SB_GAP;
|
|
720
|
+
}
|
|
721
|
+
return { start: col, len: 2 + opts.autonomy.toUpperCase().length };
|
|
722
|
+
}
|
|
723
|
+
function statusBarTodosSpan() {
|
|
724
|
+
const LABEL_MAX = 20;
|
|
725
|
+
return { start: SB_PADX, len: LABEL_MAX };
|
|
726
|
+
}
|
|
516
727
|
function stateChip(state, fleetRunning) {
|
|
517
728
|
if (state === "idle" && fleetRunning > 0) {
|
|
518
729
|
return { label: `agents \u25B6${fleetRunning}`, color: "magenta" };
|
|
@@ -522,18 +733,30 @@ function stateChip(state, fleetRunning) {
|
|
|
522
733
|
return { label: "thinking\u2026", color: "green" };
|
|
523
734
|
}
|
|
524
735
|
var WAVE_COLORS = [
|
|
525
|
-
"#
|
|
526
|
-
|
|
527
|
-
"#
|
|
528
|
-
|
|
529
|
-
"#
|
|
530
|
-
|
|
531
|
-
"#
|
|
532
|
-
|
|
533
|
-
"#
|
|
534
|
-
|
|
535
|
-
"#
|
|
536
|
-
|
|
736
|
+
"#f38ba8",
|
|
737
|
+
// red
|
|
738
|
+
"#eba0ac",
|
|
739
|
+
// maroon
|
|
740
|
+
"#fab387",
|
|
741
|
+
// peach
|
|
742
|
+
"#f9e2af",
|
|
743
|
+
// yellow
|
|
744
|
+
"#a6e3a1",
|
|
745
|
+
// green
|
|
746
|
+
"#94e2d5",
|
|
747
|
+
// teal
|
|
748
|
+
"#89dceb",
|
|
749
|
+
// sky
|
|
750
|
+
"#89b4fa",
|
|
751
|
+
// blue
|
|
752
|
+
"#b4befe",
|
|
753
|
+
// lavender
|
|
754
|
+
"#cba6f7",
|
|
755
|
+
// mauve
|
|
756
|
+
"#f5c2e7",
|
|
757
|
+
// pink
|
|
758
|
+
"#f2cdcd"
|
|
759
|
+
// flamingo
|
|
537
760
|
];
|
|
538
761
|
function WaveText({ text, phase }) {
|
|
539
762
|
return /* @__PURE__ */ jsx(Text, { bold: true, children: Array.from(text).map((ch, i) => (
|
|
@@ -854,12 +1077,12 @@ function ContextBar({
|
|
|
854
1077
|
tokens,
|
|
855
1078
|
maxTokens
|
|
856
1079
|
}) {
|
|
857
|
-
const clamped = Math.max(0, Math.min(
|
|
1080
|
+
const clamped = Math.max(0, Math.min(1, pct));
|
|
858
1081
|
const totalBars = 10;
|
|
859
1082
|
const filled = Math.round(clamped * totalBars);
|
|
860
1083
|
const empty = totalBars - filled;
|
|
861
|
-
const color =
|
|
862
|
-
const pctText =
|
|
1084
|
+
const color = clamped < 0.6 ? "green" : clamped < 0.75 ? "yellow" : "red";
|
|
1085
|
+
const pctText = `${Math.min(Math.round(pct * 100), 100)}%`;
|
|
863
1086
|
const tokenText = tokens ? ` ${fmtTokens2(tokens)}/${fmtTokens2(maxTokens ?? 2e5)}` : "";
|
|
864
1087
|
return /* @__PURE__ */ jsxs(Text, { color, children: [
|
|
865
1088
|
"\u2588".repeat(filled),
|
|
@@ -1467,8 +1690,8 @@ function FilePicker({ query, matches, selected }) {
|
|
|
1467
1690
|
] }, m))
|
|
1468
1691
|
] });
|
|
1469
1692
|
}
|
|
1470
|
-
function highlight(
|
|
1471
|
-
return
|
|
1693
|
+
function highlight(path6, _query) {
|
|
1694
|
+
return path6;
|
|
1472
1695
|
}
|
|
1473
1696
|
function FleetPanel({
|
|
1474
1697
|
entries,
|
|
@@ -1535,29 +1758,103 @@ function FleetPanel({
|
|
|
1535
1758
|
] }) : null
|
|
1536
1759
|
] });
|
|
1537
1760
|
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
},
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
}
|
|
1761
|
+
function fmtTime(iso) {
|
|
1762
|
+
const d = new Date(iso);
|
|
1763
|
+
const now = Date.now();
|
|
1764
|
+
const diff = now - d.getTime();
|
|
1765
|
+
if (diff < 6e4) return "just now";
|
|
1766
|
+
if (diff < 36e5) return `${Math.round(diff / 6e4)}m ago`;
|
|
1767
|
+
if (diff < 864e5) return `${Math.round(diff / 36e5)}h ago`;
|
|
1768
|
+
return d.toLocaleDateString();
|
|
1769
|
+
}
|
|
1770
|
+
function fmtBody(body, maxLen) {
|
|
1771
|
+
const oneLine2 = body.replace(/\n/g, " ");
|
|
1772
|
+
return oneLine2.length > maxLen ? `${oneLine2.slice(0, maxLen - 1)}\u2026` : oneLine2;
|
|
1773
|
+
}
|
|
1774
|
+
var TYPE_ICONS = {
|
|
1775
|
+
note: "\u{1F4DD}",
|
|
1776
|
+
ask: "\u2753",
|
|
1777
|
+
assign: "\u{1F4CB}",
|
|
1778
|
+
steer: "\u{1F504}",
|
|
1779
|
+
btw: "\u{1F4AC}",
|
|
1780
|
+
broadcast: "\u{1F4E2}",
|
|
1781
|
+
status: "\u{1F7E2}",
|
|
1782
|
+
result: "\u2705"
|
|
1783
|
+
};
|
|
1784
|
+
function MailboxPanel({
|
|
1785
|
+
messages,
|
|
1786
|
+
agents,
|
|
1787
|
+
unreadCount,
|
|
1788
|
+
open
|
|
1789
|
+
}) {
|
|
1790
|
+
const { stdout } = useStdout();
|
|
1791
|
+
const [termWidth, setTermWidth] = useState(stdout?.columns ?? 90);
|
|
1792
|
+
useEffect(() => {
|
|
1793
|
+
const handleResize = () => setTermWidth(stdout?.columns ?? 90);
|
|
1794
|
+
handleResize();
|
|
1795
|
+
process.stdout.on("resize", handleResize);
|
|
1796
|
+
return () => {
|
|
1797
|
+
process.stdout.off("resize", handleResize);
|
|
1798
|
+
};
|
|
1799
|
+
}, [stdout]);
|
|
1800
|
+
if (!open) return null;
|
|
1801
|
+
const showMessages = messages.slice(0, 6);
|
|
1802
|
+
const showAgents = agents.slice(0, 8);
|
|
1803
|
+
const maxSubjectLen = Math.max(15, Math.min(30, termWidth - 55));
|
|
1804
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, flexShrink: 0, children: [
|
|
1805
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
1806
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u{1F4EC} Mailbox" }),
|
|
1807
|
+
unreadCount > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", bold: true, children: [
|
|
1808
|
+
unreadCount,
|
|
1809
|
+
" unread"
|
|
1810
|
+
] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "0 unread" }),
|
|
1811
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
1812
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1813
|
+
agents.length,
|
|
1814
|
+
" agent",
|
|
1815
|
+
agents.length === 1 ? "" : "s",
|
|
1816
|
+
" online"
|
|
1817
|
+
] })
|
|
1818
|
+
] }),
|
|
1819
|
+
showMessages.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
1820
|
+
/* @__PURE__ */ jsx(Text, { bold: true, dimColor: true, children: "Messages" }),
|
|
1821
|
+
showMessages.map((m) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1822
|
+
/* @__PURE__ */ jsx(Text, { children: TYPE_ICONS[m.type] ?? "\u{1F4E8}" }),
|
|
1823
|
+
/* @__PURE__ */ jsx(Text, { color: m.readByMe ? void 0 : "yellow", bold: !m.readByMe, children: m.from }),
|
|
1824
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: m.subject.length > maxSubjectLen ? `${m.subject.slice(0, maxSubjectLen - 1)}\u2026` : m.subject }),
|
|
1825
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtBody(m.body, 40) }),
|
|
1826
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtTime(m.timestamp) }),
|
|
1827
|
+
m.readByCount > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1828
|
+
"\u{1F441} ",
|
|
1829
|
+
m.readByCount
|
|
1830
|
+
] }) : /* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: "\u2709 new" }),
|
|
1831
|
+
m.completed ? /* @__PURE__ */ jsx(Text, { color: "green", children: "\u2713" }) : null
|
|
1832
|
+
] }, m.id))
|
|
1833
|
+
] }) : /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No messages yet." }) }),
|
|
1834
|
+
showAgents.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
1835
|
+
/* @__PURE__ */ jsx(Text, { bold: true, dimColor: true, children: "Online agents" }),
|
|
1836
|
+
showAgents.map((a) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1837
|
+
/* @__PURE__ */ jsx(Text, { color: a.online ? "green" : "dim", children: a.online ? "\u25CF" : "\u25CB" }),
|
|
1838
|
+
/* @__PURE__ */ jsx(Text, { children: a.name }),
|
|
1839
|
+
a.role ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1840
|
+
"(",
|
|
1841
|
+
a.role,
|
|
1842
|
+
")"
|
|
1843
|
+
] }) : null,
|
|
1844
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: a.status }),
|
|
1845
|
+
a.currentTool ? /* @__PURE__ */ jsx(Text, { color: "cyan", children: a.currentTool }) : null,
|
|
1846
|
+
a.currentTask ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: a.currentTask.length > 25 ? `${a.currentTask.slice(0, 24)}\u2026` : a.currentTask }) : null,
|
|
1847
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtTime(a.lastSeenAt) }),
|
|
1848
|
+
a.source ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1849
|
+
"[",
|
|
1850
|
+
a.source,
|
|
1851
|
+
"]"
|
|
1852
|
+
] }) : null
|
|
1853
|
+
] }, a.agentId))
|
|
1854
|
+
] }) : null,
|
|
1855
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "/mailbox \u2014 Esc to close" }) })
|
|
1856
|
+
] });
|
|
1857
|
+
}
|
|
1561
1858
|
function helpSections() {
|
|
1562
1859
|
const nav = [];
|
|
1563
1860
|
nav.push(
|
|
@@ -1569,12 +1866,16 @@ function helpSections() {
|
|
|
1569
1866
|
{
|
|
1570
1867
|
title: "Monitors",
|
|
1571
1868
|
entries: [
|
|
1869
|
+
{ keys: "F1", desc: "project switcher (also /project)" },
|
|
1572
1870
|
{ keys: "Ctrl+F / F2", desc: "fleet orchestration monitor" },
|
|
1573
1871
|
{ keys: "Ctrl+G / F3", desc: "agents live monitor" },
|
|
1574
1872
|
{ keys: "Ctrl+T / F4", desc: "worktree monitor" },
|
|
1575
1873
|
{ keys: "F5", desc: "autonomy settings (also Ctrl+S)" },
|
|
1576
1874
|
{ keys: "F6", desc: "todos monitor overlay" },
|
|
1577
1875
|
{ keys: "F7", desc: "queue panel" },
|
|
1876
|
+
{ keys: "F8", desc: "process list overlay" },
|
|
1877
|
+
{ keys: "F9", desc: "goal panel" },
|
|
1878
|
+
{ keys: "F10", desc: "live sessions panel" },
|
|
1578
1879
|
{ keys: "Esc", desc: "close the open monitor / overlay" }
|
|
1579
1880
|
]
|
|
1580
1881
|
},
|
|
@@ -1591,6 +1892,7 @@ function helpSections() {
|
|
|
1591
1892
|
{
|
|
1592
1893
|
title: "Commands",
|
|
1593
1894
|
entries: [
|
|
1895
|
+
{ keys: "/project", desc: "switch projects (also F1)" },
|
|
1594
1896
|
{ keys: "/help", desc: "list all slash commands" },
|
|
1595
1897
|
{ keys: "/model", desc: "switch the active model" },
|
|
1596
1898
|
{ keys: "/fleet", desc: "multi-agent fleet controls" },
|
|
@@ -2148,14 +2450,14 @@ function computeWidths(allRows, cols, maxWidth, sepWidths) {
|
|
|
2148
2450
|
const cell = row[c] ?? "";
|
|
2149
2451
|
const stripped = stripInlineMarkers(cell);
|
|
2150
2452
|
const total = strWidth(stripped);
|
|
2151
|
-
natural[c] = Math.max(expectDefined
|
|
2453
|
+
natural[c] = Math.max(expectDefined(natural[c]), total);
|
|
2152
2454
|
}
|
|
2153
2455
|
}
|
|
2154
2456
|
if (sepWidths) {
|
|
2155
2457
|
for (let c = 0; c < cols && c < sepWidths.length; c++) {
|
|
2156
2458
|
const sepW = sepWidths[c];
|
|
2157
2459
|
if (sepW != null) {
|
|
2158
|
-
natural[c] = Math.max(expectDefined
|
|
2460
|
+
natural[c] = Math.max(expectDefined(natural[c]), sepW);
|
|
2159
2461
|
}
|
|
2160
2462
|
}
|
|
2161
2463
|
}
|
|
@@ -2167,7 +2469,7 @@ function computeWidths(allRows, cols, maxWidth, sepWidths) {
|
|
|
2167
2469
|
let maxIdx = -1;
|
|
2168
2470
|
let maxVal = MIN_COL_WIDTH;
|
|
2169
2471
|
for (let i = 0; i < cols; i++) {
|
|
2170
|
-
const w = expectDefined
|
|
2472
|
+
const w = expectDefined(widths[i]);
|
|
2171
2473
|
if (w > maxVal) {
|
|
2172
2474
|
maxVal = w;
|
|
2173
2475
|
maxIdx = i;
|
|
@@ -2227,7 +2529,7 @@ function strWidth(s2) {
|
|
|
2227
2529
|
if (i < len) i++;
|
|
2228
2530
|
continue;
|
|
2229
2531
|
}
|
|
2230
|
-
const code = expectDefined
|
|
2532
|
+
const code = expectDefined(s2.codePointAt(i));
|
|
2231
2533
|
const cpLen = code > 65535 ? 2 : 1;
|
|
2232
2534
|
if (code === 8205 || // ZWJ — Zero Width Joiner (emoji sequences)
|
|
2233
2535
|
code === 8203 || // ZWSP — Zero Width Space
|
|
@@ -2299,7 +2601,7 @@ function stripInlineMarkers(text) {
|
|
|
2299
2601
|
}
|
|
2300
2602
|
var ANSI_BOLD = "\x1B[1m";
|
|
2301
2603
|
var ANSI_DIM = "\x1B[2m";
|
|
2302
|
-
var ANSI_CYAN = "\x1B[
|
|
2604
|
+
var ANSI_CYAN = "\x1B[38;2;148;226;213m";
|
|
2303
2605
|
var ANSI_STRIKE = "\x1B[9m";
|
|
2304
2606
|
var ANSI_RESET_ALL = "\x1B[0m";
|
|
2305
2607
|
function applyInlineAnsi(text) {
|
|
@@ -2404,7 +2706,11 @@ function padCell(text, width, align) {
|
|
|
2404
2706
|
}
|
|
2405
2707
|
return displayText + " ".repeat(pad);
|
|
2406
2708
|
}
|
|
2709
|
+
var _parseCache = /* @__PURE__ */ new Map();
|
|
2710
|
+
var _PARSE_CACHE_MAX = 5e3;
|
|
2407
2711
|
function parseInline(text) {
|
|
2712
|
+
const cached = _parseCache.get(text);
|
|
2713
|
+
if (cached) return cached;
|
|
2408
2714
|
const tokens = [];
|
|
2409
2715
|
let plain = "";
|
|
2410
2716
|
let i = 0;
|
|
@@ -2457,6 +2763,15 @@ function parseInline(text) {
|
|
|
2457
2763
|
i += 1;
|
|
2458
2764
|
}
|
|
2459
2765
|
flush();
|
|
2766
|
+
if (_parseCache.size >= _PARSE_CACHE_MAX) {
|
|
2767
|
+
let dropped = 0;
|
|
2768
|
+
const target = Math.floor(_PARSE_CACHE_MAX / 4);
|
|
2769
|
+
for (const key of _parseCache.keys()) {
|
|
2770
|
+
_parseCache.delete(key);
|
|
2771
|
+
if (++dropped >= target) break;
|
|
2772
|
+
}
|
|
2773
|
+
}
|
|
2774
|
+
_parseCache.set(text, tokens);
|
|
2460
2775
|
return tokens;
|
|
2461
2776
|
}
|
|
2462
2777
|
function InlineLine({ tokens, dim }) {
|
|
@@ -3123,7 +3438,7 @@ function streamBoxRows(text, maxLines, contentWidth) {
|
|
|
3123
3438
|
}
|
|
3124
3439
|
return rows;
|
|
3125
3440
|
}
|
|
3126
|
-
React5.memo(function ToolStreamBox2({
|
|
3441
|
+
var ToolStreamBox = React5.memo(function ToolStreamBox2({
|
|
3127
3442
|
name,
|
|
3128
3443
|
text,
|
|
3129
3444
|
startedAt,
|
|
@@ -3408,7 +3723,7 @@ function Banner({
|
|
|
3408
3723
|
entry
|
|
3409
3724
|
}) {
|
|
3410
3725
|
const cwdShort = shortenPath(entry.cwd, 48);
|
|
3411
|
-
const projectLabel =
|
|
3726
|
+
const projectLabel = path4.basename(entry.cwd);
|
|
3412
3727
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 0, children: [
|
|
3413
3728
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
3414
3729
|
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: " \u259F\u259B " }),
|
|
@@ -3440,23 +3755,111 @@ function Banner({
|
|
|
3440
3755
|
] }),
|
|
3441
3756
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
3442
3757
|
/* @__PURE__ */ jsx(Text, { color: "cyan", children: " hints " }),
|
|
3443
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "/help \xB7
|
|
3758
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "/help \xB7 F1 projects \xB7 F10 sessions \xB7 /exit" })
|
|
3444
3759
|
] })
|
|
3445
3760
|
] });
|
|
3446
3761
|
}
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3762
|
+
|
|
3763
|
+
// src/components/suggestions.ts
|
|
3764
|
+
var STRICT_HEADING_RE = /💡\s*Next steps?\s*\n+/i;
|
|
3765
|
+
var PERMISSIVE_HEADING_PATTERNS = [
|
|
3766
|
+
{ re: /💡\s*Next steps?\s*\n+/i, label: "emoji" },
|
|
3767
|
+
{ re: /##?\s*Next steps?\s*\n+/i, label: "markdown" },
|
|
3768
|
+
{ re: /\n{1,2}Next steps?\s*\n+/i, label: "plain" }
|
|
3769
|
+
];
|
|
3770
|
+
var ITEM_RE = /^(?:(\d+)[.)]\s*|[-*•]\s*)(.+)$/;
|
|
3771
|
+
var MAX_STEPS = 6;
|
|
3772
|
+
function parseNextSteps(content, strict = false, requireHeading = true) {
|
|
3773
|
+
if (requireHeading) {
|
|
3774
|
+
return parseWithHeading(content, strict);
|
|
3775
|
+
}
|
|
3776
|
+
return parseRawNumbered(content);
|
|
3777
|
+
}
|
|
3778
|
+
function parseRawNumbered(content) {
|
|
3779
|
+
const lines = content.split("\n");
|
|
3452
3780
|
const steps = [];
|
|
3453
|
-
const
|
|
3454
|
-
for (const
|
|
3455
|
-
const
|
|
3456
|
-
if (
|
|
3781
|
+
const seenNumbers = /* @__PURE__ */ new Set();
|
|
3782
|
+
for (const rawLine of lines) {
|
|
3783
|
+
const line = rawLine.trim();
|
|
3784
|
+
if (!line) continue;
|
|
3785
|
+
const m = ITEM_RE.exec(line);
|
|
3786
|
+
if (!m) continue;
|
|
3787
|
+
const numPart = m[1];
|
|
3788
|
+
let text = m[2].trim();
|
|
3789
|
+
let index;
|
|
3790
|
+
if (numPart !== void 0) {
|
|
3791
|
+
index = Number.parseInt(numPart, 10);
|
|
3792
|
+
} else {
|
|
3793
|
+
index = steps.length + 1;
|
|
3794
|
+
}
|
|
3795
|
+
if (seenNumbers.has(index)) continue;
|
|
3796
|
+
if (text.length < 3) continue;
|
|
3797
|
+
seenNumbers.add(index);
|
|
3798
|
+
steps.push({ index, text });
|
|
3799
|
+
if (steps.length >= MAX_STEPS) break;
|
|
3800
|
+
}
|
|
3801
|
+
return { steps, texts: steps.map((s2) => s2.text), stripped: content };
|
|
3802
|
+
}
|
|
3803
|
+
function parseWithHeading(content, strict) {
|
|
3804
|
+
const headingRe = strict ? STRICT_HEADING_RE : buildPermissiveHeadingRe();
|
|
3805
|
+
const headingMatch = headingRe.exec(content);
|
|
3806
|
+
if (!headingMatch) {
|
|
3807
|
+
return { steps: [], texts: [], stripped: content };
|
|
3808
|
+
}
|
|
3809
|
+
const headingEnd = headingMatch.index + headingMatch[0].length;
|
|
3810
|
+
const afterHeading = content.slice(headingEnd);
|
|
3811
|
+
const lines = afterHeading.split("\n");
|
|
3812
|
+
const steps = [];
|
|
3813
|
+
const seenNumbers = /* @__PURE__ */ new Set();
|
|
3814
|
+
for (const rawLine of lines) {
|
|
3815
|
+
const line = rawLine.trim();
|
|
3816
|
+
if (!line) continue;
|
|
3817
|
+
const m = ITEM_RE.exec(line);
|
|
3818
|
+
if (!m) break;
|
|
3819
|
+
const numPart = m[1];
|
|
3820
|
+
let text = m[2].trim();
|
|
3821
|
+
let index;
|
|
3822
|
+
if (numPart !== void 0) {
|
|
3823
|
+
index = Number.parseInt(numPart, 10);
|
|
3824
|
+
} else {
|
|
3825
|
+
index = steps.length + 1;
|
|
3826
|
+
}
|
|
3827
|
+
if (seenNumbers.has(index)) continue;
|
|
3828
|
+
if (text.length < 3) continue;
|
|
3829
|
+
seenNumbers.add(index);
|
|
3830
|
+
steps.push({ index, text });
|
|
3831
|
+
if (steps.length >= MAX_STEPS) break;
|
|
3832
|
+
}
|
|
3833
|
+
if (steps.length === 0) {
|
|
3834
|
+
return { steps: [], texts: [], stripped: content };
|
|
3457
3835
|
}
|
|
3458
|
-
const
|
|
3459
|
-
|
|
3836
|
+
const texts = steps.map((s2) => s2.text);
|
|
3837
|
+
const blockStart = headingMatch.index;
|
|
3838
|
+
const blockEnd = headingEnd + findBlockEnd(afterHeading, steps.length);
|
|
3839
|
+
const stripped = (content.slice(0, blockStart) + content.slice(blockStart + blockEnd)).replace(/\n{3,}/g, "\n\n").trim();
|
|
3840
|
+
return { steps, texts, stripped };
|
|
3841
|
+
}
|
|
3842
|
+
function buildPermissiveHeadingRe() {
|
|
3843
|
+
const variants = PERMISSIVE_HEADING_PATTERNS.map(({ re }) => `(?:${re.source})`).join("|");
|
|
3844
|
+
return new RegExp(variants, "i");
|
|
3845
|
+
}
|
|
3846
|
+
function findBlockEnd(afterHeading, stepCount) {
|
|
3847
|
+
const lines = afterHeading.split("\n");
|
|
3848
|
+
let consumed = 0;
|
|
3849
|
+
let found = 0;
|
|
3850
|
+
for (const rawLine of lines) {
|
|
3851
|
+
const line = rawLine.trim();
|
|
3852
|
+
if (!line) {
|
|
3853
|
+
consumed += rawLine.length + 1;
|
|
3854
|
+
continue;
|
|
3855
|
+
}
|
|
3856
|
+
const m = ITEM_RE.exec(line);
|
|
3857
|
+
if (!m) break;
|
|
3858
|
+
consumed += rawLine.length + 1;
|
|
3859
|
+
found++;
|
|
3860
|
+
if (found >= stepCount) break;
|
|
3861
|
+
}
|
|
3862
|
+
return consumed;
|
|
3460
3863
|
}
|
|
3461
3864
|
function brainStatusStyle(status) {
|
|
3462
3865
|
switch (status) {
|
|
@@ -3468,6 +3871,8 @@ function brainStatusStyle(status) {
|
|
|
3468
3871
|
return { icon: "?", color: "yellow" };
|
|
3469
3872
|
case "denied":
|
|
3470
3873
|
return { icon: "\xD7", color: "red" };
|
|
3874
|
+
case "intervention":
|
|
3875
|
+
return { icon: "\u26A1", color: "yellow" };
|
|
3471
3876
|
}
|
|
3472
3877
|
}
|
|
3473
3878
|
function brainRiskColor(risk) {
|
|
@@ -3484,12 +3889,19 @@ function brainRiskColor(risk) {
|
|
|
3484
3889
|
}
|
|
3485
3890
|
var Entry = React5.memo(function Entry2({
|
|
3486
3891
|
entry,
|
|
3487
|
-
termWidth
|
|
3892
|
+
termWidth,
|
|
3893
|
+
setSuggestions
|
|
3488
3894
|
}) {
|
|
3489
3895
|
const nextSteps = useMemo(() => {
|
|
3490
3896
|
if (entry.kind !== "assistant") return { steps: [], stripped: "" };
|
|
3491
|
-
return parseNextSteps(entry.text);
|
|
3897
|
+
return parseNextSteps(entry.text, true);
|
|
3492
3898
|
}, [entry.kind, entry.text]);
|
|
3899
|
+
useEffect(() => {
|
|
3900
|
+
if (!setSuggestions) return;
|
|
3901
|
+
const text = entry.text ?? "";
|
|
3902
|
+
const { texts } = parseNextSteps(text, true);
|
|
3903
|
+
if (texts.length > 0) setSuggestions(texts);
|
|
3904
|
+
}, [entry.kind, entry.text, setSuggestions]);
|
|
3493
3905
|
switch (entry.kind) {
|
|
3494
3906
|
case "user":
|
|
3495
3907
|
return /* @__PURE__ */ jsx(
|
|
@@ -3618,8 +4030,10 @@ var Entry = React5.memo(function Entry2({
|
|
|
3618
4030
|
diff ? /* @__PURE__ */ jsx(DiffBlock, { rows: diff.rows, hidden: diff.hidden }) : null
|
|
3619
4031
|
] });
|
|
3620
4032
|
}
|
|
3621
|
-
case "info":
|
|
3622
|
-
|
|
4033
|
+
case "info": {
|
|
4034
|
+
const hasAnsi = /\x1b\[/.test(entry.text);
|
|
4035
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: !hasAnsi, children: entry.text });
|
|
4036
|
+
}
|
|
3623
4037
|
case "warn":
|
|
3624
4038
|
return /* @__PURE__ */ jsx(
|
|
3625
4039
|
Box,
|
|
@@ -3728,7 +4142,7 @@ var Entry = React5.memo(function Entry2({
|
|
|
3728
4142
|
}
|
|
3729
4143
|
}
|
|
3730
4144
|
});
|
|
3731
|
-
function History({ entries, streamingText, toolStream }) {
|
|
4145
|
+
function History({ entries, generation, streamingText, toolStream, setSuggestions }) {
|
|
3732
4146
|
const { stdout } = useStdout();
|
|
3733
4147
|
const [termSize, setTermSize] = useState({
|
|
3734
4148
|
columns: stdout?.columns ?? 80,
|
|
@@ -3746,10 +4160,210 @@ function History({ entries, streamingText, toolStream }) {
|
|
|
3746
4160
|
const termWidth = termSize.columns;
|
|
3747
4161
|
const tail = streamingText ? tailForDisplay(streamingText, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
3748
4162
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3749
|
-
/* @__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) }),
|
|
4163
|
+
/* @__PURE__ */ jsx(Static, { items: entries, children: (entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth, setSuggestions }) }, entry.id) }, generation ?? 0),
|
|
3750
4164
|
/* @__PURE__ */ jsx(Box, { flexGrow: 1, children: tail ? /* @__PURE__ */ jsx(AssistantTail, { text: tail, termWidth }) : null })
|
|
3751
4165
|
] });
|
|
3752
4166
|
}
|
|
4167
|
+
var MAX_MOUNTED = 500;
|
|
4168
|
+
function scrollbarThumb(rows, offset, total) {
|
|
4169
|
+
const scrollable = total > rows;
|
|
4170
|
+
if (!scrollable) return { top: 0, size: rows, scrollable: false };
|
|
4171
|
+
const windowTop = Math.max(0, total - rows - offset);
|
|
4172
|
+
const size = Math.max(1, Math.round(rows / total * rows));
|
|
4173
|
+
const rawTop = Math.round(windowTop / total * rows);
|
|
4174
|
+
const top = Math.max(0, Math.min(rawTop, rows - size));
|
|
4175
|
+
return { top, size, scrollable: true };
|
|
4176
|
+
}
|
|
4177
|
+
function scrollOffsetForTrackRow(rows, total, cell) {
|
|
4178
|
+
if (total <= rows) return 0;
|
|
4179
|
+
const maxOffset = total - rows;
|
|
4180
|
+
const clampedCell = Math.max(0, Math.min(rows - 1, cell));
|
|
4181
|
+
const windowTop = Math.round(clampedCell / Math.max(1, rows - 1) * maxOffset);
|
|
4182
|
+
return Math.max(0, Math.min(maxOffset, maxOffset - windowTop));
|
|
4183
|
+
}
|
|
4184
|
+
function Scrollbar({
|
|
4185
|
+
rows,
|
|
4186
|
+
offset,
|
|
4187
|
+
total
|
|
4188
|
+
}) {
|
|
4189
|
+
const { top: thumbTop, size: thumbSize, scrollable } = scrollbarThumb(rows, offset, total);
|
|
4190
|
+
const cells = [];
|
|
4191
|
+
for (let i = 0; i < rows; i++) {
|
|
4192
|
+
cells.push(i >= thumbTop && i < thumbTop + thumbSize ? "\u2588" : "\u2502");
|
|
4193
|
+
}
|
|
4194
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginLeft: 1, flexShrink: 0, children: cells.map((c, i) => /* @__PURE__ */ jsx(
|
|
4195
|
+
Text,
|
|
4196
|
+
{
|
|
4197
|
+
...scrollable ? { color: theme.accent } : {},
|
|
4198
|
+
dimColor: !scrollable || c === "\u2502",
|
|
4199
|
+
children: c
|
|
4200
|
+
},
|
|
4201
|
+
i
|
|
4202
|
+
)) });
|
|
4203
|
+
}
|
|
4204
|
+
function ScrollableHistory({
|
|
4205
|
+
entries,
|
|
4206
|
+
streamingText,
|
|
4207
|
+
toolStream,
|
|
4208
|
+
scrollOffset,
|
|
4209
|
+
viewportRows,
|
|
4210
|
+
totalLines,
|
|
4211
|
+
onMeasure,
|
|
4212
|
+
maxWidth,
|
|
4213
|
+
setSuggestions
|
|
4214
|
+
}) {
|
|
4215
|
+
const { stdout } = useStdout();
|
|
4216
|
+
const rawWidth = stdout?.columns ?? 80;
|
|
4217
|
+
const termWidth = maxWidth ? Math.min(rawWidth, maxWidth) : rawWidth;
|
|
4218
|
+
const tail = streamingText ? tailForDisplay(streamingText, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
4219
|
+
const toolTail = toolStream?.text ? tailForDisplay(toolStream.text, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
4220
|
+
const hiddenCount = Math.max(0, entries.length - MAX_MOUNTED);
|
|
4221
|
+
const shown = hiddenCount > 0 ? entries.slice(-MAX_MOUNTED) : entries;
|
|
4222
|
+
const contentRef = useRef(null);
|
|
4223
|
+
const lastReported = useRef(-1);
|
|
4224
|
+
useLayoutEffect(() => {
|
|
4225
|
+
const node = contentRef.current;
|
|
4226
|
+
if (!node) return;
|
|
4227
|
+
const { height } = measureElement(node);
|
|
4228
|
+
if (height !== lastReported.current) {
|
|
4229
|
+
lastReported.current = height;
|
|
4230
|
+
onMeasure(height);
|
|
4231
|
+
}
|
|
4232
|
+
}, [onMeasure]);
|
|
4233
|
+
const vp = Math.max(1, viewportRows);
|
|
4234
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
4235
|
+
/* @__PURE__ */ jsx(
|
|
4236
|
+
Box,
|
|
4237
|
+
{
|
|
4238
|
+
flexDirection: "column",
|
|
4239
|
+
flexGrow: 1,
|
|
4240
|
+
height: vp,
|
|
4241
|
+
overflowY: "hidden",
|
|
4242
|
+
justifyContent: "flex-end",
|
|
4243
|
+
children: /* @__PURE__ */ jsxs(
|
|
4244
|
+
Box,
|
|
4245
|
+
{
|
|
4246
|
+
ref: contentRef,
|
|
4247
|
+
flexDirection: "column",
|
|
4248
|
+
marginBottom: Math.max(0, scrollOffset),
|
|
4249
|
+
flexShrink: 0,
|
|
4250
|
+
children: [
|
|
4251
|
+
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,
|
|
4252
|
+
shown.map((entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, flexShrink: 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth, setSuggestions }) }, entry.id)),
|
|
4253
|
+
tail ? /* @__PURE__ */ jsx(AssistantTail, { text: tail, termWidth }) : null,
|
|
4254
|
+
toolTail && toolStream ? /* @__PURE__ */ jsx(
|
|
4255
|
+
ToolStreamBox,
|
|
4256
|
+
{
|
|
4257
|
+
name: toolStream.name,
|
|
4258
|
+
text: toolTail,
|
|
4259
|
+
startedAt: toolStream.startedAt,
|
|
4260
|
+
termWidth
|
|
4261
|
+
}
|
|
4262
|
+
) : null
|
|
4263
|
+
]
|
|
4264
|
+
}
|
|
4265
|
+
)
|
|
4266
|
+
}
|
|
4267
|
+
),
|
|
4268
|
+
/* @__PURE__ */ jsx(Scrollbar, { rows: vp, offset: Math.max(0, scrollOffset), total: totalLines })
|
|
4269
|
+
] });
|
|
4270
|
+
}
|
|
4271
|
+
var MB = 1024 * 1024;
|
|
4272
|
+
function defaultHeapLogPath() {
|
|
4273
|
+
return path4.join(wstackGlobalRoot(), "logs", "heap.jsonl");
|
|
4274
|
+
}
|
|
4275
|
+
function takeHeapSample() {
|
|
4276
|
+
const m = process.memoryUsage();
|
|
4277
|
+
const limit = v8.getHeapStatistics().heap_size_limit || 0;
|
|
4278
|
+
return {
|
|
4279
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4280
|
+
rss: m.rss,
|
|
4281
|
+
heapUsed: m.heapUsed,
|
|
4282
|
+
heapTotal: m.heapTotal,
|
|
4283
|
+
external: m.external,
|
|
4284
|
+
heapLimit: limit,
|
|
4285
|
+
load: limit > 0 ? m.heapUsed / limit : 0
|
|
4286
|
+
};
|
|
4287
|
+
}
|
|
4288
|
+
function startHeapWatchdog(opts = {}) {
|
|
4289
|
+
const sampleEveryMs = opts.sampleEveryMs ?? 6e4;
|
|
4290
|
+
const logEveryMs = opts.logEveryMs ?? 3e5;
|
|
4291
|
+
const logPath = opts.logPath ?? defaultHeapLogPath();
|
|
4292
|
+
const warnAt = opts.warnAt ?? 0.6;
|
|
4293
|
+
const criticalAt = opts.criticalAt ?? 0.85;
|
|
4294
|
+
const REARM_MARGIN = 0.05;
|
|
4295
|
+
let warnArmed = true;
|
|
4296
|
+
let criticalArmed = true;
|
|
4297
|
+
let lastLogAt = 0;
|
|
4298
|
+
let writeChain = Promise.resolve();
|
|
4299
|
+
let dirReady = false;
|
|
4300
|
+
const append = (line) => {
|
|
4301
|
+
writeChain = writeChain.then(async () => {
|
|
4302
|
+
if (!dirReady) {
|
|
4303
|
+
await fs2.mkdir(path4.dirname(logPath), { recursive: true });
|
|
4304
|
+
dirReady = true;
|
|
4305
|
+
}
|
|
4306
|
+
await fs2.appendFile(logPath, `${line}
|
|
4307
|
+
`, "utf8");
|
|
4308
|
+
}).catch(() => void 0);
|
|
4309
|
+
};
|
|
4310
|
+
const tick = () => {
|
|
4311
|
+
const s2 = takeHeapSample();
|
|
4312
|
+
if (s2.load >= criticalAt && criticalArmed) {
|
|
4313
|
+
criticalArmed = false;
|
|
4314
|
+
warnArmed = false;
|
|
4315
|
+
opts.onWarn?.(
|
|
4316
|
+
"critical",
|
|
4317
|
+
`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}`,
|
|
4318
|
+
s2
|
|
4319
|
+
);
|
|
4320
|
+
} else if (s2.load >= warnAt && warnArmed) {
|
|
4321
|
+
warnArmed = false;
|
|
4322
|
+
opts.onWarn?.(
|
|
4323
|
+
"warn",
|
|
4324
|
+
`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}`,
|
|
4325
|
+
s2
|
|
4326
|
+
);
|
|
4327
|
+
}
|
|
4328
|
+
if (!warnArmed && s2.load < warnAt - REARM_MARGIN) warnArmed = true;
|
|
4329
|
+
if (!criticalArmed && s2.load < criticalAt - REARM_MARGIN) criticalArmed = true;
|
|
4330
|
+
const due = Date.now() - lastLogAt >= logEveryMs;
|
|
4331
|
+
const crossed = s2.load >= warnAt;
|
|
4332
|
+
if (due || crossed) {
|
|
4333
|
+
lastLogAt = Date.now();
|
|
4334
|
+
let extras = {};
|
|
4335
|
+
try {
|
|
4336
|
+
extras = opts.collectStats?.() ?? {};
|
|
4337
|
+
} catch {
|
|
4338
|
+
}
|
|
4339
|
+
append(JSON.stringify({ pid: process.pid, ...s2, ...extras }));
|
|
4340
|
+
}
|
|
4341
|
+
};
|
|
4342
|
+
const timer = setInterval(tick, sampleEveryMs);
|
|
4343
|
+
timer.unref?.();
|
|
4344
|
+
tick();
|
|
4345
|
+
return () => {
|
|
4346
|
+
clearInterval(timer);
|
|
4347
|
+
};
|
|
4348
|
+
}
|
|
4349
|
+
|
|
4350
|
+
// src/hit-test.ts
|
|
4351
|
+
var SCROLLBAR_HIT_WIDTH = 2;
|
|
4352
|
+
function hitRegion(layout, x, y) {
|
|
4353
|
+
const { termRows, termCols, viewportRows } = layout;
|
|
4354
|
+
if (y < 1 || y > termRows || x < 1 || x > termCols) return null;
|
|
4355
|
+
if (y <= viewportRows) {
|
|
4356
|
+
if (x > termCols - SCROLLBAR_HIT_WIDTH) return { kind: "scrollbar", cell: y - 1 };
|
|
4357
|
+
return { kind: "history", row: y - 1 };
|
|
4358
|
+
}
|
|
4359
|
+
return { kind: "bottom", row: y - viewportRows - 1 };
|
|
4360
|
+
}
|
|
4361
|
+
function statusBarLineRow(opts) {
|
|
4362
|
+
const contentLines = opts.statusBarHeight - opts.headerRows;
|
|
4363
|
+
if (opts.line < 0 || opts.line >= contentLines) return null;
|
|
4364
|
+
const bandTop = opts.termRows - opts.belowHeight - opts.statusBarHeight + 1;
|
|
4365
|
+
return bandTop + opts.headerRows + opts.line;
|
|
4366
|
+
}
|
|
3753
4367
|
|
|
3754
4368
|
// src/fn-keys.ts
|
|
3755
4369
|
function fnKey(data) {
|
|
@@ -3853,6 +4467,45 @@ function layoutInputRows(prompt, value, cursor, width) {
|
|
|
3853
4467
|
if (row.length > 0 || rows.length === 0) rows.push(row);
|
|
3854
4468
|
return rows;
|
|
3855
4469
|
}
|
|
4470
|
+
|
|
4471
|
+
// src/mouse.ts
|
|
4472
|
+
var ESC = String.fromCharCode(27);
|
|
4473
|
+
var MOUSE_CLICK_ON = `${ESC}[?1000h${ESC}[?1006h`;
|
|
4474
|
+
var MOUSE_OFF = `${ESC}[?1003l${ESC}[?1002l${ESC}[?1000l${ESC}[?1006l`;
|
|
4475
|
+
var SGR_MOUSE_GLOBAL = new RegExp(`${ESC}\\[<(\\d+);(\\d+);(\\d+)([Mm])`, "gu");
|
|
4476
|
+
var LEAKED_MOUSE_RE = /\[<\d+;\d+;\d+[Mm]/;
|
|
4477
|
+
function decodeMouse(cb, x, y, released) {
|
|
4478
|
+
const shift = (cb & 4) !== 0;
|
|
4479
|
+
const meta = (cb & 8) !== 0;
|
|
4480
|
+
const ctrl = (cb & 16) !== 0;
|
|
4481
|
+
const motion = (cb & 32) !== 0;
|
|
4482
|
+
const wheel = (cb & 64) !== 0;
|
|
4483
|
+
const low = cb & 3;
|
|
4484
|
+
if (wheel) {
|
|
4485
|
+
const dir = low === 0 ? 1 : low === 1 ? -1 : 0;
|
|
4486
|
+
return { kind: "wheel", button: "none", x, y, wheel: dir, shift, meta, ctrl, motion: false };
|
|
4487
|
+
}
|
|
4488
|
+
const button = low === 0 ? "left" : low === 1 ? "middle" : low === 2 ? "right" : "none";
|
|
4489
|
+
const kind = motion ? "move" : released ? "release" : "press";
|
|
4490
|
+
return { kind, button, x, y, wheel: 0, shift, meta, ctrl, motion };
|
|
4491
|
+
}
|
|
4492
|
+
function parseMouseEvents(data) {
|
|
4493
|
+
const events = [];
|
|
4494
|
+
for (const m of data.matchAll(SGR_MOUSE_GLOBAL)) {
|
|
4495
|
+
events.push(
|
|
4496
|
+
decodeMouse(
|
|
4497
|
+
Number.parseInt(m[1], 10),
|
|
4498
|
+
Number.parseInt(m[2], 10),
|
|
4499
|
+
Number.parseInt(m[3], 10),
|
|
4500
|
+
m[4] === "m"
|
|
4501
|
+
)
|
|
4502
|
+
);
|
|
4503
|
+
}
|
|
4504
|
+
return events;
|
|
4505
|
+
}
|
|
4506
|
+
function isLeakedMouseInput(input) {
|
|
4507
|
+
return LEAKED_MOUSE_RE.test(input);
|
|
4508
|
+
}
|
|
3856
4509
|
function renderRow2(cells, rowKey, promptColor) {
|
|
3857
4510
|
const out = [];
|
|
3858
4511
|
let run = "";
|
|
@@ -3907,14 +4560,6 @@ function isBackspaceOrDelete(data) {
|
|
|
3907
4560
|
if (data === "\x1B[3~") return "delete";
|
|
3908
4561
|
return null;
|
|
3909
4562
|
}
|
|
3910
|
-
function parseMouseWheel(data) {
|
|
3911
|
-
const m = data.match(new RegExp(`^${String.fromCharCode(27)}\\[<(\\d+);(\\d+);(\\d+)([Mm])$`, "u"));
|
|
3912
|
-
if (!m) return null;
|
|
3913
|
-
const cb = Number.parseInt(expectDefined(m[1]), 10);
|
|
3914
|
-
if (cb === 64) return 1;
|
|
3915
|
-
if (cb === 65) return -1;
|
|
3916
|
-
return null;
|
|
3917
|
-
}
|
|
3918
4563
|
var EMPTY_KEY = {
|
|
3919
4564
|
upArrow: false,
|
|
3920
4565
|
downArrow: false,
|
|
@@ -3948,6 +4593,7 @@ var Input = memo(function Input2({
|
|
|
3948
4593
|
const suppressInkDeleteRef = useRef(false);
|
|
3949
4594
|
useInput((input, key) => {
|
|
3950
4595
|
if (disabled) return;
|
|
4596
|
+
if (input && isLeakedMouseInput(input)) return;
|
|
3951
4597
|
if (key.escape && suppressInkEscRef.current) {
|
|
3952
4598
|
suppressInkEscRef.current = false;
|
|
3953
4599
|
return;
|
|
@@ -4011,9 +4657,15 @@ var Input = memo(function Input2({
|
|
|
4011
4657
|
onKey("", { ...EMPTY_KEY, backspace: true, ctrl: true });
|
|
4012
4658
|
return;
|
|
4013
4659
|
}
|
|
4014
|
-
const
|
|
4015
|
-
if (
|
|
4016
|
-
|
|
4660
|
+
const mouseEvents = parseMouseEvents(s2);
|
|
4661
|
+
if (mouseEvents.length > 0) {
|
|
4662
|
+
for (const ev of mouseEvents) {
|
|
4663
|
+
onKey("", {
|
|
4664
|
+
...EMPTY_KEY,
|
|
4665
|
+
mouse: ev,
|
|
4666
|
+
wheelDeltaY: ev.kind === "wheel" ? ev.wheel : void 0
|
|
4667
|
+
});
|
|
4668
|
+
}
|
|
4017
4669
|
return;
|
|
4018
4670
|
}
|
|
4019
4671
|
const fn = fnKey(s2);
|
|
@@ -4319,6 +4971,80 @@ function PhasePanel({ phases, nowTick }) {
|
|
|
4319
4971
|
}
|
|
4320
4972
|
);
|
|
4321
4973
|
}
|
|
4974
|
+
var MAX_VISIBLE2 = 12;
|
|
4975
|
+
function visibleWindow(selected, total) {
|
|
4976
|
+
if (total <= MAX_VISIBLE2) return { start: 0, end: total };
|
|
4977
|
+
const half = Math.floor(MAX_VISIBLE2 / 2);
|
|
4978
|
+
let start = selected - half;
|
|
4979
|
+
let end = start + MAX_VISIBLE2;
|
|
4980
|
+
if (start < 0) {
|
|
4981
|
+
start = 0;
|
|
4982
|
+
end = MAX_VISIBLE2;
|
|
4983
|
+
}
|
|
4984
|
+
if (end > total) {
|
|
4985
|
+
end = total;
|
|
4986
|
+
start = total - MAX_VISIBLE2;
|
|
4987
|
+
}
|
|
4988
|
+
return { start, end };
|
|
4989
|
+
}
|
|
4990
|
+
function ProjectPicker({
|
|
4991
|
+
items,
|
|
4992
|
+
selected,
|
|
4993
|
+
filter,
|
|
4994
|
+
hint
|
|
4995
|
+
}) {
|
|
4996
|
+
const total = items.length;
|
|
4997
|
+
const { start, end } = visibleWindow(selected, total);
|
|
4998
|
+
const visible = items.slice(start, end);
|
|
4999
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, flexShrink: 0, children: [
|
|
5000
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Switch Project \u2501\u2501" }),
|
|
5001
|
+
filter ? /* @__PURE__ */ jsxs(Box, { children: [
|
|
5002
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: "Filter: " }),
|
|
5003
|
+
/* @__PURE__ */ jsx(Text, { children: filter }),
|
|
5004
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2588" })
|
|
5005
|
+
] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "type to filter \xB7 \u2191\u2193 navigate \xB7 Enter select \xB7 Esc cancel" }),
|
|
5006
|
+
start > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5007
|
+
"\u2191 ",
|
|
5008
|
+
start,
|
|
5009
|
+
" more above"
|
|
5010
|
+
] }) : null,
|
|
5011
|
+
visible.map((item) => {
|
|
5012
|
+
const idx = items.indexOf(item);
|
|
5013
|
+
const isSelected = idx === selected;
|
|
5014
|
+
const isDivider = item.key === "__divider__";
|
|
5015
|
+
if (isDivider) {
|
|
5016
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500".repeat(36) }, item.key);
|
|
5017
|
+
}
|
|
5018
|
+
const marker = isSelected ? "\u25B8" : " ";
|
|
5019
|
+
const labelColor = isSelected ? "cyan" : void 0;
|
|
5020
|
+
const metaColor = "grey";
|
|
5021
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
5022
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
5023
|
+
/* @__PURE__ */ jsxs(Text, { inverse: isSelected, color: labelColor, children: [
|
|
5024
|
+
` ${marker} `,
|
|
5025
|
+
/* @__PURE__ */ jsx(Text, { bold: isSelected, children: item.label })
|
|
5026
|
+
] }),
|
|
5027
|
+
item.meta ? /* @__PURE__ */ jsxs(Text, { dimColor: !isSelected, color: isSelected ? "cyan" : metaColor, children: [
|
|
5028
|
+
" ",
|
|
5029
|
+
item.meta
|
|
5030
|
+
] }) : null
|
|
5031
|
+
] }),
|
|
5032
|
+
item.subtitle ? /* @__PURE__ */ jsxs(Text, { dimColor: !isSelected, color: isSelected ? "cyan" : metaColor, children: [
|
|
5033
|
+
" ",
|
|
5034
|
+
item.subtitle
|
|
5035
|
+
] }) : null
|
|
5036
|
+
] }, item.key);
|
|
5037
|
+
}),
|
|
5038
|
+
end < total ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5039
|
+
"\u2193 ",
|
|
5040
|
+
total - end,
|
|
5041
|
+
" more below \xB7 ",
|
|
5042
|
+
total,
|
|
5043
|
+
" total"
|
|
5044
|
+
] }) : null,
|
|
5045
|
+
hint ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) }) : null
|
|
5046
|
+
] });
|
|
5047
|
+
}
|
|
4322
5048
|
function QueuePanel({ items }) {
|
|
4323
5049
|
const { stdout } = useStdout();
|
|
4324
5050
|
const w = stdout?.columns ?? 80;
|
|
@@ -4549,32 +5275,227 @@ function renderProgressBar(progress, trend) {
|
|
|
4549
5275
|
] })
|
|
4550
5276
|
] });
|
|
4551
5277
|
}
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
5278
|
+
function ResumePicker({
|
|
5279
|
+
sessions,
|
|
5280
|
+
selected,
|
|
5281
|
+
busy,
|
|
5282
|
+
error,
|
|
5283
|
+
hint
|
|
5284
|
+
}) {
|
|
5285
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
5286
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Resume Session \u2501\u2501" }),
|
|
5287
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: busy ? "Resuming selected session\u2026" : "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc cancel" }),
|
|
5288
|
+
error ? /* @__PURE__ */ jsx(Text, { color: "red", children: error }) : null,
|
|
5289
|
+
sessions.length === 0 && !busy ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No sessions found." }) : sessions.map((s2, i) => {
|
|
5290
|
+
const isCurrent = s2.isCurrent;
|
|
5291
|
+
const isSelected = i === selected;
|
|
5292
|
+
const date = s2.startedAt.slice(0, 16).replace("T", " ");
|
|
5293
|
+
const outcomeBadge = s2.outcome === "completed" ? "\u2713 " : s2.outcome === "aborted" ? "\u26A0 " : s2.outcome === "error" ? "\u2717 " : s2.outcome === "timeout" ? "\u23F1 " : " ";
|
|
5294
|
+
const toolStr = s2.toolCallCount > 0 ? `${s2.toolCallCount} tool${s2.toolCallCount === 1 ? "" : "s"}` : "";
|
|
5295
|
+
const iterStr = s2.iterationCount > 0 ? `${s2.iterationCount} iter${s2.iterationCount === 1 ? "" : "s"}` : "";
|
|
5296
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
5297
|
+
/* @__PURE__ */ jsxs(
|
|
5298
|
+
Text,
|
|
5299
|
+
{
|
|
5300
|
+
inverse: isSelected,
|
|
5301
|
+
dimColor: isCurrent ?? false,
|
|
5302
|
+
...isSelected ? { color: isCurrent ? "gray" : "cyan" } : {},
|
|
5303
|
+
children: [
|
|
5304
|
+
isSelected ? "\u203A " : " ",
|
|
5305
|
+
/* @__PURE__ */ jsx(Text, { bold: true, dimColor: isCurrent ?? false, children: s2.id }),
|
|
5306
|
+
isCurrent ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (current)" }) : null,
|
|
5307
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5308
|
+
" ",
|
|
5309
|
+
date
|
|
5310
|
+
] })
|
|
5311
|
+
]
|
|
5312
|
+
}
|
|
5313
|
+
),
|
|
5314
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5315
|
+
isSelected ? " " : " ",
|
|
5316
|
+
outcomeBadge,
|
|
5317
|
+
s2.tokenTotal.toLocaleString(),
|
|
5318
|
+
" tok",
|
|
5319
|
+
toolStr ? ` \xB7 ${toolStr}` : "",
|
|
5320
|
+
iterStr ? ` \xB7 ${iterStr}` : "",
|
|
5321
|
+
s2.toolErrorCount > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
5322
|
+
" \xB7 ",
|
|
5323
|
+
s2.toolErrorCount,
|
|
5324
|
+
" err"
|
|
5325
|
+
] }) : null
|
|
5326
|
+
] }),
|
|
5327
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5328
|
+
isSelected ? " " : " ",
|
|
5329
|
+
s2.title.length > 72 ? `${s2.title.slice(0, 71)}\u2026` : s2.title
|
|
5330
|
+
] })
|
|
5331
|
+
] }, s2.id);
|
|
5332
|
+
}),
|
|
5333
|
+
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
5334
|
+
] });
|
|
4564
5335
|
}
|
|
4565
|
-
function
|
|
4566
|
-
|
|
4567
|
-
|
|
5336
|
+
function statusIcon(status) {
|
|
5337
|
+
switch (status) {
|
|
5338
|
+
case "active":
|
|
5339
|
+
return "\u25CF";
|
|
5340
|
+
case "idle":
|
|
5341
|
+
return "\u25C9";
|
|
5342
|
+
case "closing":
|
|
5343
|
+
return "\u25D0";
|
|
5344
|
+
case "stale":
|
|
5345
|
+
return "\u25CB";
|
|
5346
|
+
default:
|
|
5347
|
+
return "?";
|
|
5348
|
+
}
|
|
4568
5349
|
}
|
|
4569
|
-
function
|
|
4570
|
-
|
|
5350
|
+
function agentIcon(status) {
|
|
5351
|
+
switch (status) {
|
|
5352
|
+
case "running":
|
|
5353
|
+
return "\u25B6";
|
|
5354
|
+
case "streaming":
|
|
5355
|
+
return "\u21BB";
|
|
5356
|
+
case "waiting_user":
|
|
5357
|
+
return "\u23F3";
|
|
5358
|
+
case "error":
|
|
5359
|
+
return "\u2717";
|
|
5360
|
+
case "idle":
|
|
5361
|
+
return "\u25A0";
|
|
5362
|
+
default:
|
|
5363
|
+
return "?";
|
|
5364
|
+
}
|
|
4571
5365
|
}
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
}
|
|
4577
|
-
|
|
5366
|
+
function fmtDuration2(startedAt) {
|
|
5367
|
+
const diff = Date.now() - new Date(startedAt).getTime();
|
|
5368
|
+
const min = Math.floor(diff / 6e4);
|
|
5369
|
+
if (min < 1) return "<1m";
|
|
5370
|
+
if (min < 60) return `${min}m`;
|
|
5371
|
+
const h = Math.floor(min / 60);
|
|
5372
|
+
if (h < 24) return `${h}h ${min % 60}m`;
|
|
5373
|
+
return `${Math.floor(h / 24)}d ${h % 24}h`;
|
|
5374
|
+
}
|
|
5375
|
+
function SessionsPanel({
|
|
5376
|
+
sessions,
|
|
5377
|
+
busy,
|
|
5378
|
+
selected,
|
|
5379
|
+
resumeConfirm,
|
|
5380
|
+
currentSessionId
|
|
5381
|
+
}) {
|
|
5382
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, flexShrink: 0, children: [
|
|
5383
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
5384
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u29C9 Sessions" }),
|
|
5385
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 F10 or Esc to close" }),
|
|
5386
|
+
busy && /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 loading\u2026" })
|
|
5387
|
+
] }),
|
|
5388
|
+
resumeConfirm ? /* @__PURE__ */ jsxs(Box, { marginY: 1, borderStyle: "single", borderColor: "yellow", paddingX: 1, children: [
|
|
5389
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", bold: true, children: [
|
|
5390
|
+
'\u26A0 Resume session "',
|
|
5391
|
+
resumeConfirm.sessionName,
|
|
5392
|
+
'"?'
|
|
5393
|
+
] }),
|
|
5394
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "This will replace the current conversation. Press Enter to confirm, Esc to cancel." })
|
|
5395
|
+
] }) : null,
|
|
5396
|
+
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: [
|
|
5397
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
5398
|
+
/* @__PURE__ */ jsxs(Text, { inverse: idx === selected, color: s2.status === "active" ? "green" : s2.status === "idle" ? "cyan" : "yellow", children: [
|
|
5399
|
+
s2.sessionId === currentSessionId ? "\u25CF " : "",
|
|
5400
|
+
statusIcon(s2.status),
|
|
5401
|
+
" "
|
|
5402
|
+
] }),
|
|
5403
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: s2.projectName }),
|
|
5404
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5405
|
+
" [",
|
|
5406
|
+
s2.projectSlug,
|
|
5407
|
+
"]"
|
|
5408
|
+
] }),
|
|
5409
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5410
|
+
" \xB7 ",
|
|
5411
|
+
s2.sessionId.slice(0, 8)
|
|
5412
|
+
] }),
|
|
5413
|
+
s2.gitBranch ? /* @__PURE__ */ jsxs(Text, { color: "magenta", children: [
|
|
5414
|
+
" \u2387 ",
|
|
5415
|
+
s2.gitBranch
|
|
5416
|
+
] }) : null,
|
|
5417
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5418
|
+
" \xB7 ",
|
|
5419
|
+
fmtDuration2(s2.startedAt)
|
|
5420
|
+
] }),
|
|
5421
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5422
|
+
" \xB7 PID ",
|
|
5423
|
+
s2.pid
|
|
5424
|
+
] })
|
|
5425
|
+
] }),
|
|
5426
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5427
|
+
" wd: ",
|
|
5428
|
+
s2.workingDir
|
|
5429
|
+
] }),
|
|
5430
|
+
/* @__PURE__ */ jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [
|
|
5431
|
+
s2.agents.slice(0, 8).map((a) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
5432
|
+
/* @__PURE__ */ jsxs(Text, { color: a.status === "running" ? "green" : a.status === "streaming" ? "cyan" : a.status === "error" ? "red" : a.status === "waiting_user" ? "yellow" : "grey", children: [
|
|
5433
|
+
agentIcon(a.status),
|
|
5434
|
+
" "
|
|
5435
|
+
] }),
|
|
5436
|
+
/* @__PURE__ */ jsx(Text, { children: a.name }),
|
|
5437
|
+
a.currentTool ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5438
|
+
" [",
|
|
5439
|
+
a.currentTool,
|
|
5440
|
+
"]"
|
|
5441
|
+
] }) : null,
|
|
5442
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5443
|
+
" \xB7 ",
|
|
5444
|
+
a.iterations,
|
|
5445
|
+
" iter \xB7 ",
|
|
5446
|
+
a.toolCalls,
|
|
5447
|
+
" tools"
|
|
5448
|
+
] })
|
|
5449
|
+
] }, a.id)),
|
|
5450
|
+
s2.agents.length > 8 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5451
|
+
" ... and ",
|
|
5452
|
+
s2.agents.length - 8,
|
|
5453
|
+
" more"
|
|
5454
|
+
] }) : null
|
|
5455
|
+
] })
|
|
5456
|
+
] }, s2.sessionId)),
|
|
5457
|
+
sessions.length > 0 && /* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
|
|
5458
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5459
|
+
sessions.length,
|
|
5460
|
+
" session",
|
|
5461
|
+
sessions.length === 1 ? "" : "s",
|
|
5462
|
+
" \xB7 \u2191\u2193 navigate \xB7 Enter to resume/switch \xB7 Esc close"
|
|
5463
|
+
] }),
|
|
5464
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5465
|
+
"Tip: /sessions kill ",
|
|
5466
|
+
"<id>",
|
|
5467
|
+
" to stop a background session"
|
|
5468
|
+
] })
|
|
5469
|
+
] })
|
|
5470
|
+
] });
|
|
5471
|
+
}
|
|
5472
|
+
var DELAY_PRESETS_MS = [0, 15e3, 3e4, 45e3, 6e4, 12e4];
|
|
5473
|
+
var SETTINGS_MODES = ["off", "suggest", "auto"];
|
|
5474
|
+
var LOG_LEVELS = ["error", "warn", "info", "debug", "trace"];
|
|
5475
|
+
var AUDIT_LEVELS = ["minimal", "standard", "full"];
|
|
5476
|
+
var COMPACTOR_STRATEGIES = ["hybrid", "intelligent", "selective"];
|
|
5477
|
+
var MAX_ITERATIONS_PRESETS = [100, 200, 500, 1e3, 0];
|
|
5478
|
+
var AUTO_PROCEED_MAX_PRESETS = [10, 25, 50, 100, 250, 0];
|
|
5479
|
+
var ENHANCE_DELAY_PRESETS = [3e4, 45e3, 6e4, 9e4, 12e4];
|
|
5480
|
+
var ENHANCE_LANGUAGES = ["original", "english"];
|
|
5481
|
+
function formatSettingsDelay(ms) {
|
|
5482
|
+
if (ms === 0) return "disabled";
|
|
5483
|
+
if (ms >= 6e4) return `${Math.round(ms / 6e4)}m`;
|
|
5484
|
+
return `${Math.round(ms / 1e3)}s`;
|
|
5485
|
+
}
|
|
5486
|
+
function formatMaxIterations(n) {
|
|
5487
|
+
if (n === 0) return "unlimited";
|
|
5488
|
+
return String(n);
|
|
5489
|
+
}
|
|
5490
|
+
function formatEnhanceDelay(ms) {
|
|
5491
|
+
return `${Math.round(ms / 1e3)}s`;
|
|
5492
|
+
}
|
|
5493
|
+
var MODE_DESC = {
|
|
5494
|
+
off: "Agent stops after each turn (normal)",
|
|
5495
|
+
suggest: "Shows next-step suggestions after each turn",
|
|
5496
|
+
auto: "Self-driving \u2014 agent continues automatically"
|
|
5497
|
+
};
|
|
5498
|
+
var SETTINGS_FIELD_COUNT = 25;
|
|
4578
5499
|
var CONFIG_SCOPES = ["global", "project"];
|
|
4579
5500
|
function SettingsPicker({
|
|
4580
5501
|
field,
|
|
@@ -4599,6 +5520,8 @@ function SettingsPicker({
|
|
|
4599
5520
|
maxIterations,
|
|
4600
5521
|
autoProceedMaxIterations,
|
|
4601
5522
|
enhanceDelayMs,
|
|
5523
|
+
enhanceEnabled,
|
|
5524
|
+
enhanceLanguage,
|
|
4602
5525
|
debugStream,
|
|
4603
5526
|
configScope,
|
|
4604
5527
|
hint
|
|
@@ -4722,6 +5645,16 @@ function SettingsPicker({
|
|
|
4722
5645
|
value: formatEnhanceDelay(enhanceDelayMs),
|
|
4723
5646
|
detail: "Timeout for prompt refinement preview (30s\u2013120s)"
|
|
4724
5647
|
},
|
|
5648
|
+
{
|
|
5649
|
+
label: "Refine",
|
|
5650
|
+
value: boolVal(enhanceEnabled),
|
|
5651
|
+
detail: "Enable prompt refinement before sending"
|
|
5652
|
+
},
|
|
5653
|
+
{
|
|
5654
|
+
label: "Refine language",
|
|
5655
|
+
value: enhanceLanguage,
|
|
5656
|
+
detail: "original (keep language) | english (translate)"
|
|
5657
|
+
},
|
|
4725
5658
|
// ── Debug ──
|
|
4726
5659
|
{ section: "Debug" },
|
|
4727
5660
|
{
|
|
@@ -4883,6 +5816,54 @@ function windowRows(rows, focus, max) {
|
|
|
4883
5816
|
}
|
|
4884
5817
|
return { rows: rows.slice(start, end), start, end, contextHeader };
|
|
4885
5818
|
}
|
|
5819
|
+
function hintsFor(ctx) {
|
|
5820
|
+
if (ctx.confirm) {
|
|
5821
|
+
return [
|
|
5822
|
+
{ key: "y", label: "yes" },
|
|
5823
|
+
{ key: "n", label: "no" },
|
|
5824
|
+
{ key: "a", label: "always" },
|
|
5825
|
+
{ key: "d", label: "deny" }
|
|
5826
|
+
];
|
|
5827
|
+
}
|
|
5828
|
+
if (ctx.picker) {
|
|
5829
|
+
return [
|
|
5830
|
+
{ key: "\u2191\u2193", label: "move" },
|
|
5831
|
+
{ key: "\u21B5", label: "select" },
|
|
5832
|
+
{ key: "Esc", label: "cancel" }
|
|
5833
|
+
];
|
|
5834
|
+
}
|
|
5835
|
+
if (ctx.monitor) {
|
|
5836
|
+
const hints = [
|
|
5837
|
+
{ key: "Esc", label: "close" },
|
|
5838
|
+
{ key: "^F", label: "fleet" },
|
|
5839
|
+
{ key: "^G", label: "agents" },
|
|
5840
|
+
{ key: "^T", label: "worktrees" },
|
|
5841
|
+
{ key: "F6", label: "todos" },
|
|
5842
|
+
{ key: "F9", label: "goal" }
|
|
5843
|
+
];
|
|
5844
|
+
if (ctx.nextPanelHint) {
|
|
5845
|
+
hints.push({ key: ctx.nextPanelHint.key, label: ctx.nextPanelHint.label, discovery: true });
|
|
5846
|
+
}
|
|
5847
|
+
return hints;
|
|
5848
|
+
}
|
|
5849
|
+
const base = [{ key: "?", label: "help" }];
|
|
5850
|
+
if (ctx.managed) base.push({ key: "PgUp/PgDn", label: "scroll" });
|
|
5851
|
+
base.push({ key: "^G", label: "agents" }, { key: "^C", label: "stop" });
|
|
5852
|
+
if (ctx.nextPanelHint) {
|
|
5853
|
+
base.push({ key: ctx.nextPanelHint.key, label: ctx.nextPanelHint.label, discovery: true });
|
|
5854
|
+
}
|
|
5855
|
+
return base;
|
|
5856
|
+
}
|
|
5857
|
+
function KeyHintBar({ context }) {
|
|
5858
|
+
const hints = hintsFor(context);
|
|
5859
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "row", paddingX: 1, children: hints.map((h, i) => (
|
|
5860
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: hints are positional + stable
|
|
5861
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", marginRight: 2, children: [
|
|
5862
|
+
/* @__PURE__ */ jsx(Text, { color: h.discovery ? theme.monitor.agents : theme.accent, children: h.key }),
|
|
5863
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${h.label}` })
|
|
5864
|
+
] }, i)
|
|
5865
|
+
)) });
|
|
5866
|
+
}
|
|
4886
5867
|
function TodosMonitor({ todos }) {
|
|
4887
5868
|
const { stdout } = useStdout();
|
|
4888
5869
|
const done = todos.filter((t) => t.status === "completed").length;
|
|
@@ -5224,7 +6205,7 @@ async function loadIndex(root) {
|
|
|
5224
6205
|
async function walk(root, rel, depth, out) {
|
|
5225
6206
|
if (out.length >= MAX_FILES_INDEXED) return;
|
|
5226
6207
|
if (depth > MAX_DEPTH) return;
|
|
5227
|
-
const dir = rel ?
|
|
6208
|
+
const dir = rel ? path4.join(root, rel) : root;
|
|
5228
6209
|
let entries;
|
|
5229
6210
|
try {
|
|
5230
6211
|
entries = await fs2.readdir(dir, { withFileTypes: true });
|
|
@@ -5796,11 +6777,28 @@ function useBrainEvents(events, dispatch) {
|
|
|
5796
6777
|
const offAnswered = events.on("brain.decision_answered", (payload) => addBrainEntry("answered", payload));
|
|
5797
6778
|
const offAskHuman = events.on("brain.decision_ask_human", (payload) => addBrainEntry("ask_human", payload));
|
|
5798
6779
|
const offDenied = events.on("brain.decision_denied", (payload) => addBrainEntry("denied", payload));
|
|
6780
|
+
const offIntervention = events.on("brain.intervention", (payload) => {
|
|
6781
|
+
const decision = payload.intervened ? `steered the agent (${payload.kind.replace(/_/g, " ")})` : "observed \u2014 no action needed";
|
|
6782
|
+
const rationale = payload.decision.type === "answer" ? payload.decision.rationale : void 0;
|
|
6783
|
+
dispatch({
|
|
6784
|
+
type: "addEntry",
|
|
6785
|
+
entry: {
|
|
6786
|
+
kind: "brain",
|
|
6787
|
+
status: "intervention",
|
|
6788
|
+
source: "monitor",
|
|
6789
|
+
risk: payload.request.risk,
|
|
6790
|
+
question: payload.request.question,
|
|
6791
|
+
decision,
|
|
6792
|
+
rationale
|
|
6793
|
+
}
|
|
6794
|
+
});
|
|
6795
|
+
});
|
|
5799
6796
|
return () => {
|
|
5800
6797
|
offRequested();
|
|
5801
6798
|
offAnswered();
|
|
5802
6799
|
offAskHuman();
|
|
5803
6800
|
offDenied();
|
|
6801
|
+
offIntervention();
|
|
5804
6802
|
};
|
|
5805
6803
|
}, [events, dispatch]);
|
|
5806
6804
|
}
|
|
@@ -5812,7 +6810,7 @@ function labelFor2(labelsRef, id, name) {
|
|
|
5812
6810
|
const n = m.size + 1;
|
|
5813
6811
|
const v = {
|
|
5814
6812
|
label: name && name !== id ? name : `AGENT#${n}`,
|
|
5815
|
-
color: expectDefined(STREAM_COLORS2[(n - 1) % STREAM_COLORS2.length])
|
|
6813
|
+
color: expectDefined$1(STREAM_COLORS2[(n - 1) % STREAM_COLORS2.length])
|
|
5816
6814
|
};
|
|
5817
6815
|
m.set(id, v);
|
|
5818
6816
|
return v;
|
|
@@ -6081,6 +7079,10 @@ function useAutoPhaseEvents(subscribeAutoPhase, dispatch, stateRef) {
|
|
|
6081
7079
|
if (!p.kept) dispatch({ type: "worktreeRemove", handleId: p.handleId });
|
|
6082
7080
|
break;
|
|
6083
7081
|
}
|
|
7082
|
+
case "countdown.tick": {
|
|
7083
|
+
dispatch({ type: "countdownTick", remainingSeconds: payload.remaining });
|
|
7084
|
+
break;
|
|
7085
|
+
}
|
|
6084
7086
|
}
|
|
6085
7087
|
};
|
|
6086
7088
|
return subscribeAutoPhase(handler);
|
|
@@ -6341,6 +7343,52 @@ function buildSteeringPreamble(snapshot, newDirection) {
|
|
|
6341
7343
|
lines.push("]");
|
|
6342
7344
|
return lines.join("\n");
|
|
6343
7345
|
}
|
|
7346
|
+
var MAX_TOOL_STREAM_RETAINED_CHARS = 1e5;
|
|
7347
|
+
var MAX_RETAINED_INPUT_CHARS = 2048;
|
|
7348
|
+
var MAX_RETAINED_INPUT_DEPTH = 4;
|
|
7349
|
+
var MAX_RETAINED_INPUT_ITEMS = 64;
|
|
7350
|
+
function pruneToolInput(value, depth = 0) {
|
|
7351
|
+
if (typeof value === "string") {
|
|
7352
|
+
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;
|
|
7353
|
+
}
|
|
7354
|
+
if (value === null || typeof value !== "object") return value;
|
|
7355
|
+
if (depth >= MAX_RETAINED_INPUT_DEPTH) return "[pruned: too deep]";
|
|
7356
|
+
if (Array.isArray(value)) {
|
|
7357
|
+
const head = value.slice(0, MAX_RETAINED_INPUT_ITEMS).map((v) => pruneToolInput(v, depth + 1));
|
|
7358
|
+
if (value.length > MAX_RETAINED_INPUT_ITEMS) {
|
|
7359
|
+
head.push(`[pruned: ${value.length - MAX_RETAINED_INPUT_ITEMS} more items]`);
|
|
7360
|
+
}
|
|
7361
|
+
return head;
|
|
7362
|
+
}
|
|
7363
|
+
const out = {};
|
|
7364
|
+
let n = 0;
|
|
7365
|
+
for (const [k, v] of Object.entries(value)) {
|
|
7366
|
+
if (n++ >= MAX_RETAINED_INPUT_ITEMS) {
|
|
7367
|
+
out["\u2026"] = "[pruned: more keys]";
|
|
7368
|
+
break;
|
|
7369
|
+
}
|
|
7370
|
+
out[k] = pruneToolInput(v, depth + 1);
|
|
7371
|
+
}
|
|
7372
|
+
return out;
|
|
7373
|
+
}
|
|
7374
|
+
function firstSelectable(items) {
|
|
7375
|
+
const idx = items.findIndex((it) => it.key !== "__divider__");
|
|
7376
|
+
return idx >= 0 ? idx : 0;
|
|
7377
|
+
}
|
|
7378
|
+
function skipDivider(items, idx, dir) {
|
|
7379
|
+
let i = idx;
|
|
7380
|
+
for (let steps = 0; steps < items.length; steps++) {
|
|
7381
|
+
const item = items[i];
|
|
7382
|
+
if (!item || item.key === "__divider__") {
|
|
7383
|
+
i += dir;
|
|
7384
|
+
if (i < 0) i = items.length - 1;
|
|
7385
|
+
if (i >= items.length) i = 0;
|
|
7386
|
+
continue;
|
|
7387
|
+
}
|
|
7388
|
+
return i;
|
|
7389
|
+
}
|
|
7390
|
+
return idx;
|
|
7391
|
+
}
|
|
6344
7392
|
function reducer(state, action) {
|
|
6345
7393
|
switch (action.type) {
|
|
6346
7394
|
case "addEntry": {
|
|
@@ -6348,7 +7396,8 @@ function reducer(state, action) {
|
|
|
6348
7396
|
if ((e.kind === "user" || e.kind === "assistant" || e.kind === "info" || e.kind === "warn" || e.kind === "error" || e.kind === "turn-summary") && !e.text?.trim()) {
|
|
6349
7397
|
return state;
|
|
6350
7398
|
}
|
|
6351
|
-
const
|
|
7399
|
+
const stored = e.kind === "tool" && e.input !== void 0 ? { ...e, input: pruneToolInput(e.input) } : e;
|
|
7400
|
+
const appended = [...state.entries, { ...stored, id: state.nextId }];
|
|
6352
7401
|
return { ...state, entries: appended, nextId: state.nextId + 1 };
|
|
6353
7402
|
}
|
|
6354
7403
|
case "setBuffer":
|
|
@@ -6472,9 +7521,11 @@ function reducer(state, action) {
|
|
|
6472
7521
|
case "toolStreamAppend": {
|
|
6473
7522
|
const cur = state.toolStream;
|
|
6474
7523
|
if (cur && cur.toolUseId === action.toolUseId) {
|
|
7524
|
+
const combined = cur.text + action.text;
|
|
7525
|
+
const text = combined.length > MAX_TOOL_STREAM_RETAINED_CHARS ? combined.slice(-MAX_TOOL_STREAM_RETAINED_CHARS) : combined;
|
|
6475
7526
|
return {
|
|
6476
7527
|
...state,
|
|
6477
|
-
toolStream: { ...cur, text
|
|
7528
|
+
toolStream: { ...cur, text }
|
|
6478
7529
|
};
|
|
6479
7530
|
}
|
|
6480
7531
|
return {
|
|
@@ -6661,6 +7712,35 @@ function reducer(state, action) {
|
|
|
6661
7712
|
...state,
|
|
6662
7713
|
autonomyPicker: { ...state.autonomyPicker, hint: action.text }
|
|
6663
7714
|
};
|
|
7715
|
+
case "resumePickerOpen":
|
|
7716
|
+
return {
|
|
7717
|
+
...state,
|
|
7718
|
+
resumePicker: { open: true, sessions: action.sessions, selected: 0, busy: false, hint: void 0, error: void 0 }
|
|
7719
|
+
};
|
|
7720
|
+
case "resumePickerClose":
|
|
7721
|
+
return {
|
|
7722
|
+
...state,
|
|
7723
|
+
resumePicker: { open: false, sessions: [], selected: 0, busy: false, hint: void 0, error: void 0 }
|
|
7724
|
+
};
|
|
7725
|
+
case "resumePickerMove": {
|
|
7726
|
+
const nr = state.resumePicker.sessions.length;
|
|
7727
|
+
if (nr === 0) return state;
|
|
7728
|
+
const nextR = (state.resumePicker.selected + action.delta + nr) % nr;
|
|
7729
|
+
return { ...state, resumePicker: { ...state.resumePicker, selected: nextR } };
|
|
7730
|
+
}
|
|
7731
|
+
case "resumePickerBusy":
|
|
7732
|
+
return { ...state, resumePicker: { ...state.resumePicker, busy: action.on } };
|
|
7733
|
+
case "resumePickerHint":
|
|
7734
|
+
return { ...state, resumePicker: { ...state.resumePicker, hint: action.text } };
|
|
7735
|
+
case "resumePickerError":
|
|
7736
|
+
return { ...state, resumePicker: { ...state.resumePicker, error: action.text, busy: false } };
|
|
7737
|
+
case "replaceHistory": {
|
|
7738
|
+
const banners = state.entries.filter((e) => e.kind === "banner");
|
|
7739
|
+
const maxBannerId = banners.length > 0 ? Math.max(...banners.map((b) => b.id)) : 0;
|
|
7740
|
+
const shifted = action.entries.map((e, i) => ({ ...e, id: maxBannerId + 1 + i }));
|
|
7741
|
+
const nextId = maxBannerId + 1 + shifted.length;
|
|
7742
|
+
return { ...state, entries: [...banners, ...shifted], nextId, historyGen: state.historyGen + 1 };
|
|
7743
|
+
}
|
|
6664
7744
|
case "settingsOpen":
|
|
6665
7745
|
return {
|
|
6666
7746
|
...state,
|
|
@@ -6688,6 +7768,8 @@ function reducer(state, action) {
|
|
|
6688
7768
|
maxIterations: action.maxIterations,
|
|
6689
7769
|
autoProceedMaxIterations: action.autoProceedMaxIterations,
|
|
6690
7770
|
enhanceDelayMs: action.enhanceDelayMs,
|
|
7771
|
+
enhanceEnabled: action.enhanceEnabled,
|
|
7772
|
+
enhanceLanguage: action.enhanceLanguage,
|
|
6691
7773
|
debugStream: action.debugStream,
|
|
6692
7774
|
configScope: action.configScope,
|
|
6693
7775
|
hint: void 0
|
|
@@ -6716,13 +7798,13 @@ function reducer(state, action) {
|
|
|
6716
7798
|
const i = SETTINGS_MODES.indexOf(sp.mode);
|
|
6717
7799
|
const base = i < 0 ? 0 : i;
|
|
6718
7800
|
const next = (base + action.delta + SETTINGS_MODES.length) % SETTINGS_MODES.length;
|
|
6719
|
-
return { ...state, settingsPicker: { ...sp, mode: expectDefined(SETTINGS_MODES[next]), hint: void 0 } };
|
|
7801
|
+
return { ...state, settingsPicker: { ...sp, mode: expectDefined$1(SETTINGS_MODES[next]), hint: void 0 } };
|
|
6720
7802
|
}
|
|
6721
7803
|
if (f === 1) {
|
|
6722
7804
|
const j = DELAY_PRESETS_MS.indexOf(sp.delayMs);
|
|
6723
7805
|
const base = j < 0 ? 0 : j;
|
|
6724
7806
|
const next = (base + action.delta + DELAY_PRESETS_MS.length) % DELAY_PRESETS_MS.length;
|
|
6725
|
-
return { ...state, settingsPicker: { ...sp, delayMs: expectDefined(DELAY_PRESETS_MS[next]), hint: void 0 } };
|
|
7807
|
+
return { ...state, settingsPicker: { ...sp, delayMs: expectDefined$1(DELAY_PRESETS_MS[next]), hint: void 0 } };
|
|
6726
7808
|
}
|
|
6727
7809
|
if (f === 2) return { ...state, settingsPicker: { ...sp, titleAnimation: !sp.titleAnimation, hint: void 0 } };
|
|
6728
7810
|
if (f === 3) return { ...state, settingsPicker: { ...sp, yolo: !sp.yolo, hint: void 0 } };
|
|
@@ -6740,50 +7822,99 @@ function reducer(state, action) {
|
|
|
6740
7822
|
const i = COMPACTOR_STRATEGIES.indexOf(sp.contextStrategy);
|
|
6741
7823
|
const base = i < 0 ? 0 : i;
|
|
6742
7824
|
const next = (base + action.delta + COMPACTOR_STRATEGIES.length) % COMPACTOR_STRATEGIES.length;
|
|
6743
|
-
return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined(COMPACTOR_STRATEGIES[next]), hint: void 0 } };
|
|
7825
|
+
return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined$1(COMPACTOR_STRATEGIES[next]), hint: void 0 } };
|
|
6744
7826
|
}
|
|
6745
7827
|
if (f === 15) {
|
|
6746
7828
|
const i = LOG_LEVELS.indexOf(sp.logLevel);
|
|
6747
7829
|
const base = i < 0 ? 0 : i;
|
|
6748
7830
|
const next = (base + action.delta + LOG_LEVELS.length) % LOG_LEVELS.length;
|
|
6749
|
-
return { ...state, settingsPicker: { ...sp, logLevel: expectDefined(LOG_LEVELS[next]), hint: void 0 } };
|
|
7831
|
+
return { ...state, settingsPicker: { ...sp, logLevel: expectDefined$1(LOG_LEVELS[next]), hint: void 0 } };
|
|
6750
7832
|
}
|
|
6751
7833
|
if (f === 16) {
|
|
6752
7834
|
const i = AUDIT_LEVELS.indexOf(sp.auditLevel);
|
|
6753
7835
|
const base = i < 0 ? 0 : i;
|
|
6754
7836
|
const next = (base + action.delta + AUDIT_LEVELS.length) % AUDIT_LEVELS.length;
|
|
6755
|
-
return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined(AUDIT_LEVELS[next]), hint: void 0 } };
|
|
7837
|
+
return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined$1(AUDIT_LEVELS[next]), hint: void 0 } };
|
|
6756
7838
|
}
|
|
6757
7839
|
if (f === 17) return { ...state, settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: void 0 } };
|
|
6758
7840
|
if (f === 18) {
|
|
6759
7841
|
const j = MAX_ITERATIONS_PRESETS.indexOf(sp.maxIterations);
|
|
6760
7842
|
const base = j < 0 ? 0 : j;
|
|
6761
7843
|
const next = (base + action.delta + MAX_ITERATIONS_PRESETS.length) % MAX_ITERATIONS_PRESETS.length;
|
|
6762
|
-
return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
|
|
7844
|
+
return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined$1(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
|
|
6763
7845
|
}
|
|
6764
7846
|
if (f === 19) {
|
|
6765
7847
|
const aj = AUTO_PROCEED_MAX_PRESETS.indexOf(sp.autoProceedMaxIterations);
|
|
6766
7848
|
const abase = aj < 0 ? 0 : aj;
|
|
6767
7849
|
const anext = (abase + action.delta + AUTO_PROCEED_MAX_PRESETS.length) % AUTO_PROCEED_MAX_PRESETS.length;
|
|
6768
|
-
return { ...state, settingsPicker: { ...sp, autoProceedMaxIterations: expectDefined(AUTO_PROCEED_MAX_PRESETS[anext]), hint: void 0 } };
|
|
7850
|
+
return { ...state, settingsPicker: { ...sp, autoProceedMaxIterations: expectDefined$1(AUTO_PROCEED_MAX_PRESETS[anext]), hint: void 0 } };
|
|
6769
7851
|
}
|
|
6770
7852
|
if (f === 20) {
|
|
6771
7853
|
const ej = ENHANCE_DELAY_PRESETS.indexOf(sp.enhanceDelayMs);
|
|
6772
7854
|
const ebase = ej < 0 ? 0 : ej;
|
|
6773
7855
|
const enext = (ebase + action.delta + ENHANCE_DELAY_PRESETS.length) % ENHANCE_DELAY_PRESETS.length;
|
|
6774
|
-
return { ...state, settingsPicker: { ...sp, enhanceDelayMs: expectDefined(ENHANCE_DELAY_PRESETS[enext]), hint: void 0 } };
|
|
7856
|
+
return { ...state, settingsPicker: { ...sp, enhanceDelayMs: expectDefined$1(ENHANCE_DELAY_PRESETS[enext]), hint: void 0 } };
|
|
6775
7857
|
}
|
|
6776
|
-
if (f === 21) return { ...state, settingsPicker: { ...sp,
|
|
7858
|
+
if (f === 21) return { ...state, settingsPicker: { ...sp, enhanceEnabled: !sp.enhanceEnabled, hint: void 0 } };
|
|
6777
7859
|
if (f === 22) {
|
|
7860
|
+
const i = ENHANCE_LANGUAGES.indexOf(sp.enhanceLanguage);
|
|
7861
|
+
const base = i < 0 ? 0 : i;
|
|
7862
|
+
const next = (base + action.delta + ENHANCE_LANGUAGES.length) % ENHANCE_LANGUAGES.length;
|
|
7863
|
+
return { ...state, settingsPicker: { ...sp, enhanceLanguage: expectDefined$1(ENHANCE_LANGUAGES[next]), hint: void 0 } };
|
|
7864
|
+
}
|
|
7865
|
+
if (f === 23) return { ...state, settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 } };
|
|
7866
|
+
if (f === 24) {
|
|
6778
7867
|
const i = CONFIG_SCOPES.indexOf(sp.configScope);
|
|
6779
7868
|
const base = i < 0 ? 0 : i;
|
|
6780
7869
|
const next = (base + action.delta + CONFIG_SCOPES.length) % CONFIG_SCOPES.length;
|
|
6781
|
-
return { ...state, settingsPicker: { ...sp, configScope: expectDefined(CONFIG_SCOPES[next]), hint: void 0 } };
|
|
7870
|
+
return { ...state, settingsPicker: { ...sp, configScope: expectDefined$1(CONFIG_SCOPES[next]), hint: void 0 } };
|
|
6782
7871
|
}
|
|
6783
7872
|
return state;
|
|
6784
7873
|
}
|
|
6785
7874
|
case "settingsHint":
|
|
6786
7875
|
return { ...state, settingsPicker: { ...state.settingsPicker, hint: action.text } };
|
|
7876
|
+
case "projectPickerOpen":
|
|
7877
|
+
return {
|
|
7878
|
+
...state,
|
|
7879
|
+
projectPicker: {
|
|
7880
|
+
open: true,
|
|
7881
|
+
allItems: action.items,
|
|
7882
|
+
items: action.items,
|
|
7883
|
+
selected: firstSelectable(action.items),
|
|
7884
|
+
filter: "",
|
|
7885
|
+
hint: void 0
|
|
7886
|
+
}
|
|
7887
|
+
};
|
|
7888
|
+
case "projectPickerClose":
|
|
7889
|
+
return {
|
|
7890
|
+
...state,
|
|
7891
|
+
projectPicker: { open: false, allItems: [], items: [], selected: 0, filter: "", hint: void 0 }
|
|
7892
|
+
};
|
|
7893
|
+
case "projectPickerMove": {
|
|
7894
|
+
const cur = state.projectPicker;
|
|
7895
|
+
const list = cur.items;
|
|
7896
|
+
if (list.length === 0) return state;
|
|
7897
|
+
const nextRaw = (cur.selected + action.delta + list.length) % list.length;
|
|
7898
|
+
const next = skipDivider(list, nextRaw, action.delta > 0 ? 1 : -1);
|
|
7899
|
+
return { ...state, projectPicker: { ...cur, selected: next } };
|
|
7900
|
+
}
|
|
7901
|
+
case "projectPickerFilter": {
|
|
7902
|
+
const cur = state.projectPicker;
|
|
7903
|
+
const filtered = action.filter ? cur.allItems.filter(
|
|
7904
|
+
(item) => item.kind !== "project" || item.label.toLowerCase().includes(action.filter.toLowerCase()) || (item.subtitle ?? "").toLowerCase().includes(action.filter.toLowerCase())
|
|
7905
|
+
) : cur.allItems;
|
|
7906
|
+
return {
|
|
7907
|
+
...state,
|
|
7908
|
+
projectPicker: {
|
|
7909
|
+
...cur,
|
|
7910
|
+
filter: action.filter,
|
|
7911
|
+
items: filtered,
|
|
7912
|
+
selected: firstSelectable(filtered)
|
|
7913
|
+
}
|
|
7914
|
+
};
|
|
7915
|
+
}
|
|
7916
|
+
case "projectPickerHint":
|
|
7917
|
+
return { ...state, projectPicker: { ...state.projectPicker, hint: action.text } };
|
|
6787
7918
|
case "confirmOpen":
|
|
6788
7919
|
return { ...state, confirmQueue: [...state.confirmQueue, action.info] };
|
|
6789
7920
|
case "confirmClose":
|
|
@@ -7459,6 +8590,47 @@ function reducer(state, action) {
|
|
|
7459
8590
|
if (state.debugStreamStats === null) return state;
|
|
7460
8591
|
return { ...state, debugStreamStats: null };
|
|
7461
8592
|
}
|
|
8593
|
+
case "toggleSessionsPanel": {
|
|
8594
|
+
return { ...state, sessionsPanelOpen: !state.sessionsPanelOpen };
|
|
8595
|
+
}
|
|
8596
|
+
case "sessionsPanelSet": {
|
|
8597
|
+
return {
|
|
8598
|
+
...state,
|
|
8599
|
+
sessionsPanel: { sessions: action.sessions, busy: false, selected: action.sessions.length > 0 ? 0 : -1 }
|
|
8600
|
+
};
|
|
8601
|
+
}
|
|
8602
|
+
case "sessionsPanelMove": {
|
|
8603
|
+
const cur = state.sessionsPanel;
|
|
8604
|
+
if (cur.sessions.length === 0) return state;
|
|
8605
|
+
const next = (cur.selected + action.delta + cur.sessions.length) % cur.sessions.length;
|
|
8606
|
+
return { ...state, sessionsPanel: { ...cur, selected: next } };
|
|
8607
|
+
}
|
|
8608
|
+
case "sessionsPanelBusy": {
|
|
8609
|
+
return {
|
|
8610
|
+
...state,
|
|
8611
|
+
sessionsPanel: { ...state.sessionsPanel, busy: action.on }
|
|
8612
|
+
};
|
|
8613
|
+
}
|
|
8614
|
+
case "sessionResumeConfirmSet": {
|
|
8615
|
+
return {
|
|
8616
|
+
...state,
|
|
8617
|
+
sessionResumeConfirm: { sessionId: action.sessionId, sessionName: action.sessionName }
|
|
8618
|
+
};
|
|
8619
|
+
}
|
|
8620
|
+
case "sessionResumeConfirmClear": {
|
|
8621
|
+
return { ...state, sessionResumeConfirm: null };
|
|
8622
|
+
}
|
|
8623
|
+
// --- Auto-proceed countdown ---
|
|
8624
|
+
case "countdownTick": {
|
|
8625
|
+
if (action.remainingSeconds <= 0) {
|
|
8626
|
+
return state.countdown ? { ...state, countdown: null } : state;
|
|
8627
|
+
}
|
|
8628
|
+
return { ...state, countdown: { remainingSeconds: action.remainingSeconds } };
|
|
8629
|
+
}
|
|
8630
|
+
case "countdownEnded": {
|
|
8631
|
+
if (state.countdown === null) return state;
|
|
8632
|
+
return { ...state, countdown: null };
|
|
8633
|
+
}
|
|
7462
8634
|
}
|
|
7463
8635
|
}
|
|
7464
8636
|
var INPUT_PROMPT = "\u203A ";
|
|
@@ -7467,7 +8639,7 @@ function selectedSlashCommandLine(picker) {
|
|
|
7467
8639
|
const picked = picker.matches[picker.selected];
|
|
7468
8640
|
return picked ? `/${picked.name}` : null;
|
|
7469
8641
|
}
|
|
7470
|
-
function rehydrateHistory(messages, startId) {
|
|
8642
|
+
function rehydrateHistory(messages, startId, toolCalls) {
|
|
7471
8643
|
const entries = [];
|
|
7472
8644
|
let nextId = startId;
|
|
7473
8645
|
for (const msg of messages) {
|
|
@@ -7481,6 +8653,20 @@ function rehydrateHistory(messages, startId) {
|
|
|
7481
8653
|
entries.push({ id: nextId++, kind: "assistant", text: trimmed });
|
|
7482
8654
|
}
|
|
7483
8655
|
}
|
|
8656
|
+
if (toolCalls && toolCalls.length > 0) {
|
|
8657
|
+
for (const tc of toolCalls) {
|
|
8658
|
+
entries.push({
|
|
8659
|
+
id: nextId++,
|
|
8660
|
+
kind: "tool",
|
|
8661
|
+
name: tc.name,
|
|
8662
|
+
durationMs: tc.durationMs,
|
|
8663
|
+
ok: tc.ok,
|
|
8664
|
+
outputBytes: tc.outputBytes,
|
|
8665
|
+
outputTokens: tc.outputTokens,
|
|
8666
|
+
outputLines: tc.outputLines
|
|
8667
|
+
});
|
|
8668
|
+
}
|
|
8669
|
+
}
|
|
7484
8670
|
return entries;
|
|
7485
8671
|
}
|
|
7486
8672
|
var PASTE_THRESHOLD_CHARS = 200;
|
|
@@ -7495,9 +8681,11 @@ function App({
|
|
|
7495
8681
|
model,
|
|
7496
8682
|
banner = true,
|
|
7497
8683
|
queueStore,
|
|
8684
|
+
onQueueChange,
|
|
7498
8685
|
yolo = false,
|
|
7499
8686
|
chime = false,
|
|
7500
8687
|
confirmExit = true,
|
|
8688
|
+
mouse = false,
|
|
7501
8689
|
enhanceEnabled = true,
|
|
7502
8690
|
enhanceController,
|
|
7503
8691
|
enhanceDelayMs = 15e3,
|
|
@@ -7519,12 +8707,17 @@ function App({
|
|
|
7519
8707
|
getSettings,
|
|
7520
8708
|
saveSettings,
|
|
7521
8709
|
predictNext,
|
|
8710
|
+
onSuggestionsParsed,
|
|
8711
|
+
getSuggestions,
|
|
8712
|
+
setSuggestions,
|
|
7522
8713
|
switchAutonomy,
|
|
7523
8714
|
effectiveMaxContext,
|
|
7524
8715
|
onExit,
|
|
7525
8716
|
director,
|
|
7526
8717
|
fleetRoster,
|
|
7527
8718
|
onClearHistory,
|
|
8719
|
+
listSessions,
|
|
8720
|
+
onResumeSession,
|
|
7528
8721
|
fleetStreamController,
|
|
7529
8722
|
statuslineHiddenItems,
|
|
7530
8723
|
setStatuslineHiddenItems,
|
|
@@ -7535,7 +8728,14 @@ function App({
|
|
|
7535
8728
|
modeLabel,
|
|
7536
8729
|
getModeLabel,
|
|
7537
8730
|
registerDebugStreamCallback,
|
|
7538
|
-
restoreDebugStreamCallback
|
|
8731
|
+
restoreDebugStreamCallback,
|
|
8732
|
+
restoredToolCalls,
|
|
8733
|
+
getProjectPickerItems,
|
|
8734
|
+
onProjectSelect,
|
|
8735
|
+
requestExit,
|
|
8736
|
+
getLiveSessions,
|
|
8737
|
+
onSwitchToSession,
|
|
8738
|
+
initialAgentsMonitorOpen
|
|
7539
8739
|
}) {
|
|
7540
8740
|
const { exit } = useApp();
|
|
7541
8741
|
const { stdout } = useStdout();
|
|
@@ -7546,6 +8746,8 @@ function App({
|
|
|
7546
8746
|
const [autonomyLive, setAutonomyLive] = useState(getAutonomy?.() ?? "off");
|
|
7547
8747
|
const [liveModeLabel, setLiveModeLabel] = useState(modeLabel ?? "");
|
|
7548
8748
|
const [hiddenItems, setHiddenItems] = useState(statuslineHiddenItems);
|
|
8749
|
+
const [sessionCount, setSessionCount] = useState(0);
|
|
8750
|
+
const prevBranchRef = useRef(null);
|
|
7549
8751
|
const [indexState, setIndexState] = useState(() => getIndexState());
|
|
7550
8752
|
useEffect(() => {
|
|
7551
8753
|
setIndexState(getIndexState());
|
|
@@ -7596,7 +8798,8 @@ function App({
|
|
|
7596
8798
|
return rehydrateHistory(
|
|
7597
8799
|
visible,
|
|
7598
8800
|
/* startId */
|
|
7599
|
-
1
|
|
8801
|
+
1,
|
|
8802
|
+
restoredToolCalls
|
|
7600
8803
|
);
|
|
7601
8804
|
})();
|
|
7602
8805
|
const initialNextId = 1 + restoredEntries.length;
|
|
@@ -7616,6 +8819,7 @@ function App({
|
|
|
7616
8819
|
] : [],
|
|
7617
8820
|
...restoredEntries
|
|
7618
8821
|
],
|
|
8822
|
+
historyGen: 0,
|
|
7619
8823
|
buffer: "",
|
|
7620
8824
|
cursor: 0,
|
|
7621
8825
|
streamingText: "",
|
|
@@ -7645,7 +8849,9 @@ function App({
|
|
|
7645
8849
|
searchQuery: ""
|
|
7646
8850
|
},
|
|
7647
8851
|
autonomyPicker: { open: false, options: [], selected: 0 },
|
|
7648
|
-
|
|
8852
|
+
resumePicker: { open: false, sessions: [], selected: 0, busy: false, hint: void 0, error: void 0 },
|
|
8853
|
+
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" },
|
|
8854
|
+
projectPicker: { open: false, allItems: [], items: [], selected: 0, filter: "", hint: void 0 },
|
|
7649
8855
|
confirmQueue: [],
|
|
7650
8856
|
enhance: null,
|
|
7651
8857
|
enhanceEnabled,
|
|
@@ -7667,12 +8873,15 @@ function App({
|
|
|
7667
8873
|
fleetConcurrency: 4,
|
|
7668
8874
|
streamFleet: true,
|
|
7669
8875
|
monitorOpen: false,
|
|
7670
|
-
agentsMonitorOpen: false,
|
|
8876
|
+
agentsMonitorOpen: initialAgentsMonitorOpen ?? false,
|
|
7671
8877
|
helpOpen: false,
|
|
7672
8878
|
todosMonitorOpen: false,
|
|
7673
8879
|
queuePanelOpen: false,
|
|
7674
8880
|
processListOpen: false,
|
|
7675
8881
|
goalPanelOpen: false,
|
|
8882
|
+
sessionsPanelOpen: false,
|
|
8883
|
+
sessionsPanel: { sessions: [], busy: false, selected: -1 },
|
|
8884
|
+
sessionResumeConfirm: null,
|
|
7676
8885
|
collabSession: null,
|
|
7677
8886
|
checkpoints: [],
|
|
7678
8887
|
rewindOverlay: null,
|
|
@@ -7685,7 +8894,8 @@ function App({
|
|
|
7685
8894
|
totalLines: 0,
|
|
7686
8895
|
viewportRows: 0,
|
|
7687
8896
|
pendingNewLines: 0,
|
|
7688
|
-
debugStreamStats: null
|
|
8897
|
+
debugStreamStats: null,
|
|
8898
|
+
countdown: null
|
|
7689
8899
|
});
|
|
7690
8900
|
const builderRef = useRef(null);
|
|
7691
8901
|
if (builderRef.current === null) {
|
|
@@ -7699,9 +8909,23 @@ function App({
|
|
|
7699
8909
|
const lastEnterAtRef = useRef(0);
|
|
7700
8910
|
const tokenPreviewsRef = useRef(/* @__PURE__ */ new Map());
|
|
7701
8911
|
const projectName = React5.useMemo(() => {
|
|
7702
|
-
const base =
|
|
7703
|
-
return base && base !==
|
|
8912
|
+
const base = path4.basename(projectRoot);
|
|
8913
|
+
return base && base !== path4.sep ? base : void 0;
|
|
7704
8914
|
}, [projectRoot]);
|
|
8915
|
+
const [workingDirChip, setWorkingDirChip] = React5.useState(() => {
|
|
8916
|
+
const ctx = agent.ctx;
|
|
8917
|
+
if (ctx.workingDir && ctx.workingDir !== projectRoot) {
|
|
8918
|
+
return path4.relative(projectRoot, ctx.workingDir) || ".";
|
|
8919
|
+
}
|
|
8920
|
+
return void 0;
|
|
8921
|
+
});
|
|
8922
|
+
React5.useEffect(() => {
|
|
8923
|
+
const ctx = agent.ctx;
|
|
8924
|
+
return ctx.onWorkingDirChanged((newDir) => {
|
|
8925
|
+
const rel = path4.relative(projectRoot, newDir) || ".";
|
|
8926
|
+
setWorkingDirChip(rel === "." ? void 0 : rel);
|
|
8927
|
+
});
|
|
8928
|
+
}, [agent.ctx, projectRoot]);
|
|
7705
8929
|
const chimeRef = useRef(chime);
|
|
7706
8930
|
chimeRef.current = chime;
|
|
7707
8931
|
const confirmExitRef = useRef(confirmExit);
|
|
@@ -7713,6 +8937,48 @@ function App({
|
|
|
7713
8937
|
stateRef.current = state;
|
|
7714
8938
|
const draftRef = useRef({ buffer: state.buffer, cursor: state.cursor });
|
|
7715
8939
|
draftRef.current = { buffer: state.buffer, cursor: state.cursor };
|
|
8940
|
+
const [mouseMode, setMouseMode] = useState(mouse);
|
|
8941
|
+
const pickerOverlayOpen = state.modelPicker.open || state.autonomyPicker.open || state.settingsPicker.open || state.projectPicker.open || state.slashPicker.open || state.picker.open;
|
|
8942
|
+
const mouseTrackingOn = mouseMode || pickerOverlayOpen;
|
|
8943
|
+
const mouseWrittenRef = useRef(false);
|
|
8944
|
+
useEffect(() => {
|
|
8945
|
+
if (mouseWrittenRef.current === mouseTrackingOn) return;
|
|
8946
|
+
mouseWrittenRef.current = mouseTrackingOn;
|
|
8947
|
+
try {
|
|
8948
|
+
process.stdout.write(mouseTrackingOn ? MOUSE_CLICK_ON : MOUSE_OFF);
|
|
8949
|
+
} catch {
|
|
8950
|
+
}
|
|
8951
|
+
}, [mouseTrackingOn]);
|
|
8952
|
+
useEffect(
|
|
8953
|
+
() => () => {
|
|
8954
|
+
try {
|
|
8955
|
+
process.stdout.write(MOUSE_OFF);
|
|
8956
|
+
} catch {
|
|
8957
|
+
}
|
|
8958
|
+
},
|
|
8959
|
+
[]
|
|
8960
|
+
);
|
|
8961
|
+
const bottomRegionRef = useRef(null);
|
|
8962
|
+
const statusBarWrapRef = useRef(null);
|
|
8963
|
+
const belowStatusBarRef = useRef(null);
|
|
8964
|
+
const [termRows, setTermRows] = useState(stdout?.rows ?? 24);
|
|
8965
|
+
useEffect(() => {
|
|
8966
|
+
const onResize = () => setTermRows(process.stdout.rows ?? 24);
|
|
8967
|
+
process.stdout.on("resize", onResize);
|
|
8968
|
+
return () => {
|
|
8969
|
+
process.stdout.off("resize", onResize);
|
|
8970
|
+
};
|
|
8971
|
+
}, []);
|
|
8972
|
+
useLayoutEffect(() => {
|
|
8973
|
+
if (!mouseMode) return;
|
|
8974
|
+
const node = bottomRegionRef.current;
|
|
8975
|
+
if (!node) return;
|
|
8976
|
+
const { height } = measureElement(node);
|
|
8977
|
+
const vp = Math.max(1, termRows - height);
|
|
8978
|
+
if (vp !== stateRef.current.viewportRows) {
|
|
8979
|
+
dispatch({ type: "setViewportRows", rows: vp });
|
|
8980
|
+
}
|
|
8981
|
+
});
|
|
7716
8982
|
const handleKeyRef = useRef(null);
|
|
7717
8983
|
const handleRewindTo = React5.useCallback(
|
|
7718
8984
|
async (checkpointIndex) => {
|
|
@@ -7738,6 +9004,35 @@ function App({
|
|
|
7738
9004
|
const t = setInterval(() => setNowTick(Date.now()), 1e4);
|
|
7739
9005
|
return () => clearInterval(t);
|
|
7740
9006
|
}, []);
|
|
9007
|
+
useEffect(() => {
|
|
9008
|
+
const approxChars = (v) => {
|
|
9009
|
+
try {
|
|
9010
|
+
return JSON.stringify(v)?.length ?? 0;
|
|
9011
|
+
} catch {
|
|
9012
|
+
return -1;
|
|
9013
|
+
}
|
|
9014
|
+
};
|
|
9015
|
+
return startHeapWatchdog({
|
|
9016
|
+
collectStats: () => ({
|
|
9017
|
+
historyEntries: stateRef.current.entries.length,
|
|
9018
|
+
historyChars: approxChars(stateRef.current.entries),
|
|
9019
|
+
messages: agent.ctx.state.messages.length,
|
|
9020
|
+
messagesChars: approxChars(agent.ctx.state.messages),
|
|
9021
|
+
runningTools: stateRef.current.runningTools.size,
|
|
9022
|
+
// Bytes queued in stdout's writable buffer. On Windows, TTY writes
|
|
9023
|
+
// are asynchronous — a render storm (e.g. high-frequency tool
|
|
9024
|
+
// progress dispatches) queues whole ANSI frames here as live heap
|
|
9025
|
+
// strings, invisible to every other counter.
|
|
9026
|
+
stdoutQueued: process.stdout.writableLength ?? 0
|
|
9027
|
+
}),
|
|
9028
|
+
onWarn: (level, message) => {
|
|
9029
|
+
dispatch({
|
|
9030
|
+
type: "addEntry",
|
|
9031
|
+
entry: { kind: level === "critical" ? "error" : "warn", text: message }
|
|
9032
|
+
});
|
|
9033
|
+
}
|
|
9034
|
+
});
|
|
9035
|
+
}, [agent.ctx]);
|
|
7741
9036
|
useEffect(() => {
|
|
7742
9037
|
if (state.goalPanelOpen) refreshGoalSummary();
|
|
7743
9038
|
}, [state.goalPanelOpen, nowTick, refreshGoalSummary]);
|
|
@@ -7748,20 +9043,14 @@ function App({
|
|
|
7748
9043
|
return () => clearInterval(t);
|
|
7749
9044
|
}, [state.enhanceBusy]);
|
|
7750
9045
|
const todosRef = useRef(JSON.stringify([]));
|
|
9046
|
+
const staleGuardRef = useRef(JSON.stringify({ a: "", y: false, m: "", model: "", provider: "" }));
|
|
7751
9047
|
useEffect(() => {
|
|
7752
9048
|
const poll = () => {
|
|
7753
|
-
const
|
|
7754
|
-
if (
|
|
7755
|
-
todosRef.current =
|
|
9049
|
+
const todoSnap = JSON.stringify(agent.ctx.todos.map((t2) => ({ s: t2.status })));
|
|
9050
|
+
if (todoSnap !== todosRef.current) {
|
|
9051
|
+
todosRef.current = todoSnap;
|
|
7756
9052
|
setNowTick(Date.now());
|
|
7757
9053
|
}
|
|
7758
|
-
};
|
|
7759
|
-
const t = setInterval(poll, 2e3);
|
|
7760
|
-
return () => clearInterval(t);
|
|
7761
|
-
}, [agent.ctx.todos]);
|
|
7762
|
-
const staleGuardRef = useRef(JSON.stringify({ a: "", y: false, m: "", model: "", provider: "" }));
|
|
7763
|
-
useEffect(() => {
|
|
7764
|
-
const poll = () => {
|
|
7765
9054
|
const a = getAutonomy?.() ?? "off";
|
|
7766
9055
|
const y = getYolo?.() ?? false;
|
|
7767
9056
|
const m = getModeLabel?.() ?? "";
|
|
@@ -7793,23 +9082,162 @@ function App({
|
|
|
7793
9082
|
liveModel,
|
|
7794
9083
|
liveProvider,
|
|
7795
9084
|
agent.ctx.model,
|
|
7796
|
-
agent.ctx.provider
|
|
9085
|
+
agent.ctx.provider,
|
|
9086
|
+
agent.ctx.todos
|
|
7797
9087
|
]);
|
|
7798
9088
|
const [gitInfo, setGitInfo] = React5.useState(null);
|
|
7799
9089
|
useEffect(() => {
|
|
7800
9090
|
let cancelled = false;
|
|
7801
9091
|
const refresh = () => {
|
|
7802
9092
|
readGitInfo(agent.ctx.cwd).then((info) => {
|
|
7803
|
-
if (
|
|
7804
|
-
|
|
9093
|
+
if (cancelled) return;
|
|
9094
|
+
setGitInfo(info);
|
|
9095
|
+
if (info && info.branch) {
|
|
9096
|
+
const prev = prevBranchRef.current;
|
|
9097
|
+
if (prev !== null && prev !== info.branch) {
|
|
9098
|
+
const msg = {
|
|
9099
|
+
role: "user",
|
|
9100
|
+
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.` }]
|
|
9101
|
+
};
|
|
9102
|
+
agent.ctx.messages.push(msg);
|
|
9103
|
+
try {
|
|
9104
|
+
import('@wrongstack/core').then(({ getSessionRegistry }) => {
|
|
9105
|
+
const reg = getSessionRegistry();
|
|
9106
|
+
if (reg) {
|
|
9107
|
+
reg.updateAgents([]).catch(() => {
|
|
9108
|
+
});
|
|
9109
|
+
}
|
|
9110
|
+
}).catch(() => {
|
|
9111
|
+
});
|
|
9112
|
+
} catch {
|
|
9113
|
+
}
|
|
9114
|
+
}
|
|
9115
|
+
prevBranchRef.current = info.branch;
|
|
9116
|
+
}
|
|
9117
|
+
}).catch(() => {
|
|
9118
|
+
if (!cancelled) setGitInfo(null);
|
|
9119
|
+
});
|
|
7805
9120
|
};
|
|
7806
9121
|
refresh();
|
|
9122
|
+
if (gitInfo?.branch && prevBranchRef.current === null) {
|
|
9123
|
+
prevBranchRef.current = gitInfo.branch;
|
|
9124
|
+
}
|
|
7807
9125
|
const t = setInterval(refresh, 5e3);
|
|
7808
9126
|
return () => {
|
|
7809
9127
|
cancelled = true;
|
|
7810
9128
|
clearInterval(t);
|
|
7811
9129
|
};
|
|
7812
|
-
}, [agent.ctx.cwd]);
|
|
9130
|
+
}, [agent.ctx.cwd, gitInfo?.branch]);
|
|
9131
|
+
useEffect(() => {
|
|
9132
|
+
if (!getLiveSessions) return;
|
|
9133
|
+
let cancelled = false;
|
|
9134
|
+
const poll = async () => {
|
|
9135
|
+
try {
|
|
9136
|
+
const sessions = await getLiveSessions();
|
|
9137
|
+
if (!cancelled) setSessionCount(sessions.length);
|
|
9138
|
+
} catch {
|
|
9139
|
+
}
|
|
9140
|
+
};
|
|
9141
|
+
void poll();
|
|
9142
|
+
const t = setInterval(poll, 3e4);
|
|
9143
|
+
if (t.unref) t.unref();
|
|
9144
|
+
return () => {
|
|
9145
|
+
cancelled = true;
|
|
9146
|
+
clearInterval(t);
|
|
9147
|
+
};
|
|
9148
|
+
}, [getLiveSessions]);
|
|
9149
|
+
const [mailboxStatus, setMailboxStatus] = useState({
|
|
9150
|
+
unread: 0,
|
|
9151
|
+
onlineAgents: 0
|
|
9152
|
+
});
|
|
9153
|
+
useEffect(() => {
|
|
9154
|
+
const seenAgents = /* @__PURE__ */ new Set();
|
|
9155
|
+
const unsub1 = events.onPattern("mailbox.unread_count", (_e, payload) => {
|
|
9156
|
+
const p = payload;
|
|
9157
|
+
setMailboxStatus((prev) => ({ ...prev, unread: p?.count ?? 0 }));
|
|
9158
|
+
});
|
|
9159
|
+
const unsub2 = events.onPattern("mailbox.received", (_e, payload) => {
|
|
9160
|
+
const p = payload;
|
|
9161
|
+
setMailboxStatus((prev) => ({
|
|
9162
|
+
...prev,
|
|
9163
|
+
lastSubject: p?.subject ?? prev.lastSubject,
|
|
9164
|
+
lastFrom: p?.from ?? prev.lastFrom
|
|
9165
|
+
}));
|
|
9166
|
+
});
|
|
9167
|
+
const unsub3 = events.onPattern("mailbox.agent_registered", (_e, payload) => {
|
|
9168
|
+
const p = payload;
|
|
9169
|
+
if (p?.agentId) seenAgents.add(p.agentId);
|
|
9170
|
+
setMailboxStatus((prev) => ({ ...prev, onlineAgents: seenAgents.size }));
|
|
9171
|
+
});
|
|
9172
|
+
const unsub4 = events.onPattern("mailbox.agent_heartbeat", (_e, payload) => {
|
|
9173
|
+
const p = payload;
|
|
9174
|
+
if (p?.agentId) seenAgents.add(p.agentId);
|
|
9175
|
+
setMailboxStatus((prev) => ({ ...prev, onlineAgents: seenAgents.size }));
|
|
9176
|
+
});
|
|
9177
|
+
return () => {
|
|
9178
|
+
unsub1();
|
|
9179
|
+
unsub2();
|
|
9180
|
+
unsub3();
|
|
9181
|
+
unsub4();
|
|
9182
|
+
};
|
|
9183
|
+
}, [events]);
|
|
9184
|
+
const [mailboxPanelOpen, setMailboxPanelOpen] = useState(false);
|
|
9185
|
+
const [mailboxMessages, setMailboxMessages] = useState([]);
|
|
9186
|
+
const [mailboxAgents, setMailboxAgents] = useState([]);
|
|
9187
|
+
useEffect(() => {
|
|
9188
|
+
if (!mailboxPanelOpen) return;
|
|
9189
|
+
const poll = async () => {
|
|
9190
|
+
};
|
|
9191
|
+
void poll();
|
|
9192
|
+
const t = setInterval(poll, 1e4);
|
|
9193
|
+
return () => clearInterval(t);
|
|
9194
|
+
}, [mailboxPanelOpen]);
|
|
9195
|
+
useEffect(() => {
|
|
9196
|
+
const unsub = events.onPattern("mailbox.received", (_e, payload) => {
|
|
9197
|
+
const p = payload;
|
|
9198
|
+
if (!p?.messageId) return;
|
|
9199
|
+
setMailboxMessages((prev) => {
|
|
9200
|
+
if (prev.some((m) => m.id === p.messageId)) return prev;
|
|
9201
|
+
return [
|
|
9202
|
+
{
|
|
9203
|
+
id: p.messageId,
|
|
9204
|
+
from: p.from ?? "unknown",
|
|
9205
|
+
to: "*",
|
|
9206
|
+
type: p.type ?? "note",
|
|
9207
|
+
subject: p.subject ?? "",
|
|
9208
|
+
body: "",
|
|
9209
|
+
priority: "normal",
|
|
9210
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9211
|
+
readByCount: 0,
|
|
9212
|
+
readByMe: false,
|
|
9213
|
+
completed: false
|
|
9214
|
+
},
|
|
9215
|
+
...prev
|
|
9216
|
+
].slice(0, 50);
|
|
9217
|
+
});
|
|
9218
|
+
});
|
|
9219
|
+
const unsub2 = events.onPattern("mailbox.agent_registered", (_e, payload) => {
|
|
9220
|
+
const p = payload;
|
|
9221
|
+
if (!p?.agentId) return;
|
|
9222
|
+
setMailboxAgents((prev) => {
|
|
9223
|
+
if (prev.some((a) => a.agentId === p.agentId)) return prev;
|
|
9224
|
+
return [...prev, {
|
|
9225
|
+
agentId: p.agentId,
|
|
9226
|
+
name: p.name ?? p.agentId,
|
|
9227
|
+
role: p.role,
|
|
9228
|
+
sessionId: p.sessionId ?? "?",
|
|
9229
|
+
status: "idle",
|
|
9230
|
+
lastSeenAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9231
|
+
online: true,
|
|
9232
|
+
source: p.source
|
|
9233
|
+
}].slice(0, 30);
|
|
9234
|
+
});
|
|
9235
|
+
});
|
|
9236
|
+
return () => {
|
|
9237
|
+
unsub();
|
|
9238
|
+
unsub2();
|
|
9239
|
+
};
|
|
9240
|
+
}, [events]);
|
|
7813
9241
|
const maxContext = activeMaxContext ?? agent.ctx.provider.capabilities.maxContext;
|
|
7814
9242
|
const currentContextTokens = (tokenCounter?.currentRequestTokens()?.input ?? 0) + (tokenCounter?.currentRequestTokens()?.cacheRead ?? 0);
|
|
7815
9243
|
const contextWindow = useMemo(() => {
|
|
@@ -7897,6 +9325,53 @@ function App({
|
|
|
7897
9325
|
clearInterval(id);
|
|
7898
9326
|
};
|
|
7899
9327
|
}, [agent.ctx.meta]);
|
|
9328
|
+
const [taskCounts, setTaskCounts] = useState(null);
|
|
9329
|
+
useEffect(() => {
|
|
9330
|
+
const taskPath = agent.ctx.meta["task.path"];
|
|
9331
|
+
if (typeof taskPath !== "string" || !taskPath) return;
|
|
9332
|
+
let cancelled = false;
|
|
9333
|
+
const poll = async () => {
|
|
9334
|
+
try {
|
|
9335
|
+
const data = await fs2.readFile(taskPath, "utf8");
|
|
9336
|
+
const parsed = JSON.parse(data);
|
|
9337
|
+
if (cancelled) return;
|
|
9338
|
+
if (!Array.isArray(parsed.tasks)) {
|
|
9339
|
+
setTaskCounts(null);
|
|
9340
|
+
return;
|
|
9341
|
+
}
|
|
9342
|
+
let pending = 0, inProgress = 0, completed = 0, blocked = 0, failed = 0;
|
|
9343
|
+
for (const t of parsed.tasks) {
|
|
9344
|
+
switch (t?.status) {
|
|
9345
|
+
case "completed":
|
|
9346
|
+
completed++;
|
|
9347
|
+
break;
|
|
9348
|
+
case "in_progress":
|
|
9349
|
+
inProgress++;
|
|
9350
|
+
break;
|
|
9351
|
+
case "blocked":
|
|
9352
|
+
blocked++;
|
|
9353
|
+
break;
|
|
9354
|
+
case "failed":
|
|
9355
|
+
failed++;
|
|
9356
|
+
break;
|
|
9357
|
+
default:
|
|
9358
|
+
pending++;
|
|
9359
|
+
break;
|
|
9360
|
+
}
|
|
9361
|
+
}
|
|
9362
|
+
const total = pending + inProgress + completed + blocked + failed;
|
|
9363
|
+
setTaskCounts(total > 0 ? { pending, inProgress, completed, blocked, failed } : null);
|
|
9364
|
+
} catch {
|
|
9365
|
+
if (!cancelled) setTaskCounts(null);
|
|
9366
|
+
}
|
|
9367
|
+
};
|
|
9368
|
+
void poll();
|
|
9369
|
+
const id = setInterval(poll, 3e3);
|
|
9370
|
+
return () => {
|
|
9371
|
+
cancelled = true;
|
|
9372
|
+
clearInterval(id);
|
|
9373
|
+
};
|
|
9374
|
+
}, [agent.ctx.meta]);
|
|
7900
9375
|
const prevAnyOverlayOpen = useRef(false);
|
|
7901
9376
|
const prevEntriesCount = useRef(0);
|
|
7902
9377
|
const prevToolStreamLen = useRef(0);
|
|
@@ -7907,7 +9382,7 @@ function App({
|
|
|
7907
9382
|
}
|
|
7908
9383
|
}, []);
|
|
7909
9384
|
React5.useLayoutEffect(() => {
|
|
7910
|
-
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;
|
|
9385
|
+
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;
|
|
7911
9386
|
const overlayClosed = prevAnyOverlayOpen.current && !anyOpenNow;
|
|
7912
9387
|
const newEntryCommitted = state.entries.length > prevEntriesCount.current;
|
|
7913
9388
|
const curToolStreamLen = state.toolStream?.text.length ?? 0;
|
|
@@ -7934,22 +9409,29 @@ function App({
|
|
|
7934
9409
|
]);
|
|
7935
9410
|
const resizeGateRef = useRef(0);
|
|
7936
9411
|
const preResizePanelsRef = useRef(null);
|
|
9412
|
+
const resizeRestoreTimerRef = useRef(null);
|
|
9413
|
+
const mountedRef = useRef(true);
|
|
7937
9414
|
useEffect(() => {
|
|
7938
9415
|
const handleResize = () => {
|
|
7939
9416
|
const seq = ++resizeGateRef.current;
|
|
7940
9417
|
preResizePanelsRef.current = {
|
|
7941
9418
|
settings: stateRef.current.settingsPicker.open,
|
|
9419
|
+
projectPicker: stateRef.current.projectPicker.open,
|
|
7942
9420
|
help: stateRef.current.helpOpen,
|
|
7943
9421
|
monitor: stateRef.current.monitorOpen,
|
|
7944
9422
|
agents: stateRef.current.agentsMonitorOpen,
|
|
7945
9423
|
worktree: stateRef.current.worktreeMonitorOpen,
|
|
7946
9424
|
todos: stateRef.current.todosMonitorOpen,
|
|
7947
9425
|
queue: stateRef.current.queuePanelOpen,
|
|
7948
|
-
processList: stateRef.current.processListOpen
|
|
9426
|
+
processList: stateRef.current.processListOpen,
|
|
9427
|
+
goalPanel: stateRef.current.goalPanelOpen,
|
|
9428
|
+
sessionsPanel: stateRef.current.sessionsPanelOpen
|
|
7949
9429
|
};
|
|
7950
9430
|
if (stateRef.current.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
9431
|
+
if (stateRef.current.projectPicker.open) dispatch({ type: "projectPickerClose" });
|
|
7951
9432
|
if (stateRef.current.modelPicker.open) dispatch({ type: "modelPickerClose" });
|
|
7952
9433
|
if (stateRef.current.autonomyPicker.open) dispatch({ type: "autonomyPickerClose" });
|
|
9434
|
+
if (stateRef.current.resumePicker.open) dispatch({ type: "resumePickerClose" });
|
|
7953
9435
|
if (stateRef.current.slashPicker.open) dispatch({ type: "slashPickerClose" });
|
|
7954
9436
|
if (stateRef.current.picker.open) dispatch({ type: "pickerClose" });
|
|
7955
9437
|
if (stateRef.current.rewindOverlay) dispatch({ type: "rewindOverlayClose" });
|
|
@@ -7960,8 +9442,11 @@ function App({
|
|
|
7960
9442
|
if (stateRef.current.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
7961
9443
|
if (stateRef.current.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
7962
9444
|
if (stateRef.current.processListOpen) dispatch({ type: "toggleProcessList" });
|
|
9445
|
+
if (stateRef.current.goalPanelOpen) dispatch({ type: "toggleGoalPanel" });
|
|
9446
|
+
if (stateRef.current.sessionsPanelOpen) dispatch({ type: "toggleSessionsPanel" });
|
|
7963
9447
|
eraseLiveRegion();
|
|
7964
|
-
setTimeout(() => {
|
|
9448
|
+
resizeRestoreTimerRef.current = setTimeout(() => {
|
|
9449
|
+
if (!mountedRef.current) return;
|
|
7965
9450
|
if (resizeGateRef.current !== seq) return;
|
|
7966
9451
|
const prev = preResizePanelsRef.current;
|
|
7967
9452
|
if (!prev) return;
|
|
@@ -7990,10 +9475,16 @@ function App({
|
|
|
7990
9475
|
maxIterations: sp.maxIterations,
|
|
7991
9476
|
autoProceedMaxIterations: sp.autoProceedMaxIterations,
|
|
7992
9477
|
enhanceDelayMs: sp.enhanceDelayMs,
|
|
9478
|
+
enhanceEnabled: sp.enhanceEnabled,
|
|
9479
|
+
enhanceLanguage: sp.enhanceLanguage,
|
|
7993
9480
|
debugStream: sp.debugStream,
|
|
7994
9481
|
configScope: sp.configScope
|
|
7995
9482
|
});
|
|
7996
9483
|
}
|
|
9484
|
+
if (prev.projectPicker) {
|
|
9485
|
+
const pp = stateRef.current.projectPicker;
|
|
9486
|
+
dispatch({ type: "projectPickerOpen", items: pp.allItems });
|
|
9487
|
+
}
|
|
7997
9488
|
if (prev.help) dispatch({ type: "toggleHelp" });
|
|
7998
9489
|
if (prev.monitor) dispatch({ type: "toggleMonitor" });
|
|
7999
9490
|
if (prev.agents) dispatch({ type: "toggleAgentsMonitor" });
|
|
@@ -8001,11 +9492,19 @@ function App({
|
|
|
8001
9492
|
if (prev.todos) dispatch({ type: "toggleTodosMonitor" });
|
|
8002
9493
|
if (prev.queue) dispatch({ type: "toggleQueuePanel" });
|
|
8003
9494
|
if (prev.processList) dispatch({ type: "toggleProcessList" });
|
|
9495
|
+
if (prev.goalPanel) dispatch({ type: "toggleGoalPanel" });
|
|
9496
|
+
if (prev.sessionsPanel) dispatch({ type: "toggleSessionsPanel" });
|
|
8004
9497
|
preResizePanelsRef.current = null;
|
|
9498
|
+
resizeRestoreTimerRef.current = null;
|
|
8005
9499
|
}, 300);
|
|
8006
9500
|
};
|
|
8007
9501
|
process.stdout.on("resize", handleResize);
|
|
8008
9502
|
return () => {
|
|
9503
|
+
if (resizeRestoreTimerRef.current) {
|
|
9504
|
+
clearTimeout(resizeRestoreTimerRef.current);
|
|
9505
|
+
resizeRestoreTimerRef.current = null;
|
|
9506
|
+
}
|
|
9507
|
+
mountedRef.current = false;
|
|
8009
9508
|
process.stdout.off("resize", handleResize);
|
|
8010
9509
|
};
|
|
8011
9510
|
}, [eraseLiveRegion]);
|
|
@@ -8106,7 +9605,7 @@ function App({
|
|
|
8106
9605
|
dispatch({ type: "pickerClose" });
|
|
8107
9606
|
return;
|
|
8108
9607
|
}
|
|
8109
|
-
const absPath =
|
|
9608
|
+
const absPath = path4.isAbsolute(picked) ? picked : path4.join(projectRoot, picked);
|
|
8110
9609
|
try {
|
|
8111
9610
|
const data = await fs2.readFile(absPath, "utf8");
|
|
8112
9611
|
const token = await builder.registerFile({
|
|
@@ -8167,6 +9666,9 @@ function App({
|
|
|
8167
9666
|
if (!queueStore) return;
|
|
8168
9667
|
queueStore.write(state.queue.map(({ displayText, blocks }) => ({ displayText, blocks }))).catch(() => void 0);
|
|
8169
9668
|
}, [state.queue, queueStore]);
|
|
9669
|
+
useEffect(() => {
|
|
9670
|
+
onQueueChange?.(state.queue.map((q) => q.displayText));
|
|
9671
|
+
}, [state.queue, onQueueChange]);
|
|
8170
9672
|
useEffect(() => {
|
|
8171
9673
|
const cmd = createQueueSlashCommand({
|
|
8172
9674
|
getQueue: () => stateRef.current.queue,
|
|
@@ -8302,6 +9804,28 @@ function App({
|
|
|
8302
9804
|
const providers = await getPickableProviders();
|
|
8303
9805
|
dispatch({ type: "modelPickerOpen", providers });
|
|
8304
9806
|
}, [getPickableProviders]);
|
|
9807
|
+
const openProjectPicker = React5.useCallback(async () => {
|
|
9808
|
+
if (!getProjectPickerItems) return;
|
|
9809
|
+
const items = await getProjectPickerItems();
|
|
9810
|
+
dispatch({ type: "projectPickerOpen", items });
|
|
9811
|
+
}, [getProjectPickerItems]);
|
|
9812
|
+
const loadLiveSessions = React5.useCallback(async () => {
|
|
9813
|
+
if (!getLiveSessions) return;
|
|
9814
|
+
dispatch({ type: "sessionsPanelBusy", on: true });
|
|
9815
|
+
try {
|
|
9816
|
+
const sessions = await getLiveSessions();
|
|
9817
|
+
dispatch({ type: "sessionsPanelSet", sessions });
|
|
9818
|
+
} catch {
|
|
9819
|
+
dispatch({ type: "sessionsPanelBusy", on: false });
|
|
9820
|
+
}
|
|
9821
|
+
}, [getLiveSessions]);
|
|
9822
|
+
useEffect(() => {
|
|
9823
|
+
if (!state.sessionsPanelOpen || !getLiveSessions) return void 0;
|
|
9824
|
+
const t = setInterval(() => {
|
|
9825
|
+
void loadLiveSessions();
|
|
9826
|
+
}, 5e3);
|
|
9827
|
+
return () => clearInterval(t);
|
|
9828
|
+
}, [state.sessionsPanelOpen, getLiveSessions, loadLiveSessions]);
|
|
8305
9829
|
const openSettings = React5.useCallback(() => {
|
|
8306
9830
|
if (!getSettings) return;
|
|
8307
9831
|
const s2 = getSettings();
|
|
@@ -8328,38 +9852,87 @@ function App({
|
|
|
8328
9852
|
maxIterations: s2.maxIterations ?? 500,
|
|
8329
9853
|
autoProceedMaxIterations: s2.autoProceedMaxIterations ?? 50,
|
|
8330
9854
|
enhanceDelayMs: s2.enhanceDelayMs ?? 6e4,
|
|
9855
|
+
enhanceEnabled: s2.enhanceEnabled ?? true,
|
|
9856
|
+
enhanceLanguage: s2.enhanceLanguage ?? "original",
|
|
8331
9857
|
debugStream: s2.debugStream ?? false,
|
|
8332
9858
|
configScope: s2.configScope ?? "global"
|
|
8333
9859
|
});
|
|
8334
9860
|
}, [getSettings]);
|
|
8335
|
-
const
|
|
8336
|
-
const
|
|
9861
|
+
const autoSubmitStreakRef = useRef(0);
|
|
9862
|
+
const autoSubmitCapWarnedRef = useRef(false);
|
|
9863
|
+
const [nextStepsRecheck, setNextStepsRecheck] = useState(0);
|
|
9864
|
+
useEffect(() => {
|
|
9865
|
+
autoSubmitStreakRef.current = 0;
|
|
9866
|
+
autoSubmitCapWarnedRef.current = false;
|
|
9867
|
+
}, [autonomyLive]);
|
|
8337
9868
|
useEffect(() => {
|
|
8338
|
-
if (autonomyLive !== "auto") {
|
|
8339
|
-
clearInterval(
|
|
8340
|
-
|
|
8341
|
-
|
|
9869
|
+
if (state.status !== "idle" || autonomyLive !== "auto") {
|
|
9870
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
9871
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
9872
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
9873
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
8342
9874
|
return;
|
|
8343
9875
|
}
|
|
9876
|
+
if (state.enhance != null || state.enhanceBusy) {
|
|
9877
|
+
return;
|
|
9878
|
+
}
|
|
9879
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
9880
|
+
return;
|
|
9881
|
+
}
|
|
9882
|
+
const suggestions = getSuggestions?.() ?? [];
|
|
9883
|
+
if (suggestions.length === 0) {
|
|
9884
|
+
const recheck = setTimeout(() => setNextStepsRecheck((t) => t + 1), 1500);
|
|
9885
|
+
return () => clearTimeout(recheck);
|
|
9886
|
+
}
|
|
8344
9887
|
const cfg = getSettings?.();
|
|
9888
|
+
const maxAuto = cfg?.autoProceedMaxIterations ?? 50;
|
|
9889
|
+
if (maxAuto > 0 && autoSubmitStreakRef.current >= maxAuto) {
|
|
9890
|
+
if (!autoSubmitCapWarnedRef.current) {
|
|
9891
|
+
autoSubmitCapWarnedRef.current = true;
|
|
9892
|
+
dispatch({
|
|
9893
|
+
type: "addEntry",
|
|
9894
|
+
entry: {
|
|
9895
|
+
kind: "warn",
|
|
9896
|
+
text: `Auto-proceed paused after ${maxAuto} consecutive automatic turns \u2014 type anything to continue (autonomy stays on).`
|
|
9897
|
+
}
|
|
9898
|
+
});
|
|
9899
|
+
}
|
|
9900
|
+
return;
|
|
9901
|
+
}
|
|
8345
9902
|
const delay = cfg?.delayMs ?? 45e3;
|
|
9903
|
+
const top = suggestions[0];
|
|
9904
|
+
if (!top) return;
|
|
9905
|
+
nextStepsAutoSubmitSuggestionRef.current = top;
|
|
8346
9906
|
const start = Date.now();
|
|
8347
|
-
|
|
8348
|
-
|
|
9907
|
+
setNextStepsAutoSubmitCountdown(Math.ceil(delay / 1e3));
|
|
9908
|
+
nextStepsAutoSubmitTimerRef.current = setInterval(() => {
|
|
8349
9909
|
const remaining = Math.max(0, Math.ceil((delay - (Date.now() - start)) / 1e3));
|
|
8350
9910
|
if (remaining <= 0) {
|
|
8351
|
-
clearInterval(
|
|
8352
|
-
|
|
8353
|
-
|
|
9911
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
9912
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
9913
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
9914
|
+
const suggestion = nextStepsAutoSubmitSuggestionRef.current;
|
|
9915
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
9916
|
+
if (suggestion) {
|
|
9917
|
+
autoSubmitStreakRef.current += 1;
|
|
9918
|
+
setDraft(suggestion, suggestion.length);
|
|
9919
|
+
void (async () => {
|
|
9920
|
+
const trimmed = suggestion.trim();
|
|
9921
|
+
if (!trimmed) return;
|
|
9922
|
+
const blocks = [{ type: "text", text: trimmed }];
|
|
9923
|
+
dispatch({ type: "addEntry", entry: { kind: "user", text: trimmed } });
|
|
9924
|
+
await runBlocksRef.current(blocks);
|
|
9925
|
+
})();
|
|
9926
|
+
}
|
|
8354
9927
|
} else {
|
|
8355
|
-
|
|
9928
|
+
setNextStepsAutoSubmitCountdown(remaining);
|
|
8356
9929
|
}
|
|
8357
9930
|
}, 500);
|
|
8358
9931
|
return () => {
|
|
8359
|
-
clearInterval(
|
|
8360
|
-
|
|
9932
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
9933
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
8361
9934
|
};
|
|
8362
|
-
}, [autonomyLive, getSettings]);
|
|
9935
|
+
}, [state.status, autonomyLive, state.enhance, state.enhanceBusy, nextStepsRecheck, getSettings, getSuggestions, dispatch]);
|
|
8363
9936
|
const settingsAutoSaveGateRef = useRef(true);
|
|
8364
9937
|
useEffect(() => {
|
|
8365
9938
|
if (state.settingsPicker.open) {
|
|
@@ -8396,6 +9969,8 @@ function App({
|
|
|
8396
9969
|
maxIterations: sp.maxIterations,
|
|
8397
9970
|
autoProceedMaxIterations: sp.autoProceedMaxIterations,
|
|
8398
9971
|
enhanceDelayMs: sp.enhanceDelayMs,
|
|
9972
|
+
enhanceEnabled: sp.enhanceEnabled,
|
|
9973
|
+
enhanceLanguage: sp.enhanceLanguage,
|
|
8399
9974
|
debugStream: sp.debugStream,
|
|
8400
9975
|
configScope: sp.configScope
|
|
8401
9976
|
})).then((err) => {
|
|
@@ -8458,6 +10033,21 @@ function App({
|
|
|
8458
10033
|
slashRegistry.unregister("settings");
|
|
8459
10034
|
};
|
|
8460
10035
|
}, [slashRegistry, getSettings, saveSettings, openSettings]);
|
|
10036
|
+
useEffect(() => {
|
|
10037
|
+
const cmd = {
|
|
10038
|
+
name: "mailbox",
|
|
10039
|
+
aliases: ["inbox", "mail"],
|
|
10040
|
+
description: "Toggle the inter-agent mailbox panel \u2014 messages, read receipts, online agents.",
|
|
10041
|
+
async run() {
|
|
10042
|
+
setMailboxPanelOpen((prev) => !prev);
|
|
10043
|
+
return { message: void 0 };
|
|
10044
|
+
}
|
|
10045
|
+
};
|
|
10046
|
+
slashRegistry.register(cmd, "tui", { official: true });
|
|
10047
|
+
return () => {
|
|
10048
|
+
slashRegistry.unregister("mailbox");
|
|
10049
|
+
};
|
|
10050
|
+
}, [slashRegistry]);
|
|
8461
10051
|
useEffect(() => {
|
|
8462
10052
|
if (!switchAutonomy) return;
|
|
8463
10053
|
const cmd = {
|
|
@@ -8474,6 +10064,34 @@ function App({
|
|
|
8474
10064
|
slashRegistry.unregister("autonomy");
|
|
8475
10065
|
};
|
|
8476
10066
|
}, [slashRegistry, switchAutonomy]);
|
|
10067
|
+
useEffect(() => {
|
|
10068
|
+
const cmd = {
|
|
10069
|
+
name: "resume",
|
|
10070
|
+
aliases: ["load"],
|
|
10071
|
+
description: "Resume a previous session \u2014 pick from a list of recent sessions.",
|
|
10072
|
+
async run() {
|
|
10073
|
+
if (!listSessions) {
|
|
10074
|
+
return { message: "Session listing not available." };
|
|
10075
|
+
}
|
|
10076
|
+
try {
|
|
10077
|
+
const sessions = await listSessions(20);
|
|
10078
|
+
if (sessions.length === 0) {
|
|
10079
|
+
return { message: "No saved sessions." };
|
|
10080
|
+
}
|
|
10081
|
+
dispatch({ type: "resumePickerOpen", sessions });
|
|
10082
|
+
} catch (err) {
|
|
10083
|
+
return {
|
|
10084
|
+
message: err instanceof Error ? err.message : String(err)
|
|
10085
|
+
};
|
|
10086
|
+
}
|
|
10087
|
+
return { message: void 0 };
|
|
10088
|
+
}
|
|
10089
|
+
};
|
|
10090
|
+
slashRegistry.register(cmd, "tui", { official: true });
|
|
10091
|
+
return () => {
|
|
10092
|
+
slashRegistry.unregister("resume");
|
|
10093
|
+
};
|
|
10094
|
+
}, [slashRegistry, listSessions]);
|
|
8477
10095
|
useEffect(() => {
|
|
8478
10096
|
const FLUSH_MS2 = 100;
|
|
8479
10097
|
const flush = () => {
|
|
@@ -8666,6 +10284,9 @@ function App({
|
|
|
8666
10284
|
}, [state.enhanceEnabled]);
|
|
8667
10285
|
const enhanceAbortRef = useRef(null);
|
|
8668
10286
|
const [enhanceCountdown, setEnhanceCountdown] = useState(null);
|
|
10287
|
+
const [nextStepsAutoSubmitCountdown, setNextStepsAutoSubmitCountdown] = useState(null);
|
|
10288
|
+
const nextStepsAutoSubmitSuggestionRef = useRef(null);
|
|
10289
|
+
const nextStepsAutoSubmitTimerRef = useRef(void 0);
|
|
8669
10290
|
useTuiEventBridge({
|
|
8670
10291
|
events,
|
|
8671
10292
|
dispatch,
|
|
@@ -8873,7 +10494,28 @@ function App({
|
|
|
8873
10494
|
return;
|
|
8874
10495
|
}
|
|
8875
10496
|
}
|
|
8876
|
-
const
|
|
10497
|
+
const overlaySelectable = state.modelPicker.open || state.autonomyPicker.open || state.resumePicker.open || state.settingsPicker.open || state.projectPicker.open || state.slashPicker.open || state.picker.open;
|
|
10498
|
+
const clickConfirm = overlaySelectable && key.mouse?.kind === "press" && key.mouse.button === "left";
|
|
10499
|
+
const clickCancel = overlaySelectable && key.mouse?.kind === "press" && key.mouse.button === "right";
|
|
10500
|
+
const isEnter = key.return || input === "\r" || input === "\n" || clickConfirm;
|
|
10501
|
+
if (clickCancel) {
|
|
10502
|
+
if (state.modelPicker.open) {
|
|
10503
|
+
dispatch(
|
|
10504
|
+
state.modelPicker.step === "model" ? { type: "modelPickerBack" } : { type: "modelPickerClose" }
|
|
10505
|
+
);
|
|
10506
|
+
} else if (state.autonomyPicker.open) {
|
|
10507
|
+
dispatch({ type: "autonomyPickerClose" });
|
|
10508
|
+
} else if (state.resumePicker.open) {
|
|
10509
|
+
dispatch({ type: "resumePickerClose" });
|
|
10510
|
+
} else if (state.settingsPicker.open) {
|
|
10511
|
+
dispatch({ type: "settingsClose" });
|
|
10512
|
+
} else if (state.slashPicker.open) {
|
|
10513
|
+
dispatch({ type: "slashPickerClose" });
|
|
10514
|
+
} else if (state.picker.open) {
|
|
10515
|
+
dispatch({ type: "pickerClose" });
|
|
10516
|
+
}
|
|
10517
|
+
return;
|
|
10518
|
+
}
|
|
8877
10519
|
if (state.modelPicker.open) {
|
|
8878
10520
|
if (key.escape) {
|
|
8879
10521
|
if (state.modelPicker.step === "model") {
|
|
@@ -8883,6 +10525,10 @@ function App({
|
|
|
8883
10525
|
}
|
|
8884
10526
|
return;
|
|
8885
10527
|
}
|
|
10528
|
+
if (key.mouse?.kind === "wheel") {
|
|
10529
|
+
dispatch({ type: "modelPickerMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10530
|
+
return;
|
|
10531
|
+
}
|
|
8886
10532
|
if (key.upArrow) {
|
|
8887
10533
|
dispatch({ type: "modelPickerMove", delta: -1 });
|
|
8888
10534
|
return;
|
|
@@ -8948,6 +10594,10 @@ function App({
|
|
|
8948
10594
|
dispatch({ type: "autonomyPickerClose" });
|
|
8949
10595
|
return;
|
|
8950
10596
|
}
|
|
10597
|
+
if (key.mouse?.kind === "wheel") {
|
|
10598
|
+
dispatch({ type: "autonomyPickerMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10599
|
+
return;
|
|
10600
|
+
}
|
|
8951
10601
|
if (key.upArrow) {
|
|
8952
10602
|
dispatch({ type: "autonomyPickerMove", delta: -1 });
|
|
8953
10603
|
return;
|
|
@@ -8972,11 +10622,64 @@ function App({
|
|
|
8972
10622
|
}
|
|
8973
10623
|
return;
|
|
8974
10624
|
}
|
|
10625
|
+
if (state.resumePicker.open) {
|
|
10626
|
+
if (key.escape) {
|
|
10627
|
+
dispatch({ type: "resumePickerClose" });
|
|
10628
|
+
return;
|
|
10629
|
+
}
|
|
10630
|
+
if (key.mouse?.kind === "wheel") {
|
|
10631
|
+
dispatch({ type: "resumePickerMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10632
|
+
return;
|
|
10633
|
+
}
|
|
10634
|
+
if (key.upArrow) {
|
|
10635
|
+
dispatch({ type: "resumePickerMove", delta: -1 });
|
|
10636
|
+
return;
|
|
10637
|
+
}
|
|
10638
|
+
if (key.downArrow) {
|
|
10639
|
+
dispatch({ type: "resumePickerMove", delta: 1 });
|
|
10640
|
+
return;
|
|
10641
|
+
}
|
|
10642
|
+
if (isEnter) {
|
|
10643
|
+
const now = Date.now();
|
|
10644
|
+
if (now - lastEnterAtRef.current < 50) return;
|
|
10645
|
+
lastEnterAtRef.current = now;
|
|
10646
|
+
const session = state.resumePicker.sessions[state.resumePicker.selected];
|
|
10647
|
+
if (!session || session.isCurrent) return;
|
|
10648
|
+
if (state.resumePicker.busy) return;
|
|
10649
|
+
dispatch({ type: "resumePickerBusy", on: true });
|
|
10650
|
+
onResumeSession?.(session.id).then((result) => {
|
|
10651
|
+
if (!result) {
|
|
10652
|
+
dispatch({ type: "resumePickerError", text: `Failed to resume session ${session.id}.` });
|
|
10653
|
+
return;
|
|
10654
|
+
}
|
|
10655
|
+
dispatch({ type: "replaceHistory", entries: result.entries, nextId: result.nextId });
|
|
10656
|
+
dispatch({ type: "resumePickerClose" });
|
|
10657
|
+
dispatch({
|
|
10658
|
+
type: "addEntry",
|
|
10659
|
+
entry: {
|
|
10660
|
+
kind: "info",
|
|
10661
|
+
text: `Resumed session ${result.sessionId} \u2014 ${result.entries.length} entries replayed.`
|
|
10662
|
+
}
|
|
10663
|
+
});
|
|
10664
|
+
}).catch((err) => {
|
|
10665
|
+
dispatch({
|
|
10666
|
+
type: "resumePickerError",
|
|
10667
|
+
text: err instanceof Error ? err.message : String(err)
|
|
10668
|
+
});
|
|
10669
|
+
});
|
|
10670
|
+
return;
|
|
10671
|
+
}
|
|
10672
|
+
return;
|
|
10673
|
+
}
|
|
8975
10674
|
if (state.settingsPicker.open) {
|
|
8976
|
-
if (key.escape || key.ctrl && input === "s"
|
|
10675
|
+
if (key.escape || key.ctrl && input === "s") {
|
|
8977
10676
|
dispatch({ type: "settingsClose" });
|
|
8978
10677
|
return;
|
|
8979
10678
|
}
|
|
10679
|
+
if (key.mouse?.kind === "wheel") {
|
|
10680
|
+
dispatch({ type: "settingsFieldMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10681
|
+
return;
|
|
10682
|
+
}
|
|
8980
10683
|
if (key.upArrow) {
|
|
8981
10684
|
dispatch({ type: "settingsFieldMove", delta: -1 });
|
|
8982
10685
|
return;
|
|
@@ -9002,11 +10705,166 @@ function App({
|
|
|
9002
10705
|
}
|
|
9003
10706
|
return;
|
|
9004
10707
|
}
|
|
10708
|
+
if (state.projectPicker.open) {
|
|
10709
|
+
if (key.escape) {
|
|
10710
|
+
if (state.projectPicker.filter) {
|
|
10711
|
+
dispatch({ type: "projectPickerFilter", filter: "" });
|
|
10712
|
+
} else {
|
|
10713
|
+
dispatch({ type: "projectPickerClose" });
|
|
10714
|
+
}
|
|
10715
|
+
return;
|
|
10716
|
+
}
|
|
10717
|
+
if (key.mouse?.kind === "wheel") {
|
|
10718
|
+
dispatch({ type: "projectPickerMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10719
|
+
return;
|
|
10720
|
+
}
|
|
10721
|
+
if (key.upArrow) {
|
|
10722
|
+
dispatch({ type: "projectPickerMove", delta: -1 });
|
|
10723
|
+
return;
|
|
10724
|
+
}
|
|
10725
|
+
if (key.downArrow) {
|
|
10726
|
+
dispatch({ type: "projectPickerMove", delta: 1 });
|
|
10727
|
+
return;
|
|
10728
|
+
}
|
|
10729
|
+
if (isEnter) {
|
|
10730
|
+
const now = Date.now();
|
|
10731
|
+
if (now - lastEnterAtRef.current < 50) return;
|
|
10732
|
+
lastEnterAtRef.current = now;
|
|
10733
|
+
const items = state.projectPicker.items;
|
|
10734
|
+
const selected = state.projectPicker.selected;
|
|
10735
|
+
if (selected < 0 || selected >= items.length) return;
|
|
10736
|
+
const item = items[selected];
|
|
10737
|
+
if (!item || item.key === "__divider__" || item.key === "quit") {
|
|
10738
|
+
dispatch({ type: "projectPickerClose" });
|
|
10739
|
+
return;
|
|
10740
|
+
}
|
|
10741
|
+
if (item.kind === "project") {
|
|
10742
|
+
await onProjectSelect?.(item.key, item.kind);
|
|
10743
|
+
dispatch({ type: "projectPickerClose" });
|
|
10744
|
+
requestExit?.(42);
|
|
10745
|
+
return;
|
|
10746
|
+
}
|
|
10747
|
+
dispatch({ type: "projectPickerClose" });
|
|
10748
|
+
if (item.key === "new-session") {
|
|
10749
|
+
await onProjectSelect?.(item.key, item.kind);
|
|
10750
|
+
requestExit?.(42);
|
|
10751
|
+
} else if (item.key === "prev-sessions") {
|
|
10752
|
+
void submit("/resume");
|
|
10753
|
+
}
|
|
10754
|
+
return;
|
|
10755
|
+
}
|
|
10756
|
+
if (input && input.length === 1 && input.charCodeAt(0) >= 32 && input.charCodeAt(0) < 127) {
|
|
10757
|
+
dispatch({ type: "projectPickerFilter", filter: state.projectPicker.filter + input });
|
|
10758
|
+
return;
|
|
10759
|
+
}
|
|
10760
|
+
if (key.backspace) {
|
|
10761
|
+
if (state.projectPicker.filter.length > 0) {
|
|
10762
|
+
dispatch({
|
|
10763
|
+
type: "projectPickerFilter",
|
|
10764
|
+
filter: state.projectPicker.filter.slice(0, -1)
|
|
10765
|
+
});
|
|
10766
|
+
}
|
|
10767
|
+
return;
|
|
10768
|
+
}
|
|
10769
|
+
return;
|
|
10770
|
+
}
|
|
10771
|
+
if (state.sessionsPanelOpen) {
|
|
10772
|
+
if (key.escape) {
|
|
10773
|
+
if (state.sessionResumeConfirm) {
|
|
10774
|
+
dispatch({ type: "sessionResumeConfirmClear" });
|
|
10775
|
+
} else {
|
|
10776
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
10777
|
+
}
|
|
10778
|
+
return;
|
|
10779
|
+
}
|
|
10780
|
+
if (key.upArrow) {
|
|
10781
|
+
dispatch({ type: "sessionsPanelMove", delta: -1 });
|
|
10782
|
+
return;
|
|
10783
|
+
}
|
|
10784
|
+
if (key.downArrow) {
|
|
10785
|
+
dispatch({ type: "sessionsPanelMove", delta: 1 });
|
|
10786
|
+
return;
|
|
10787
|
+
}
|
|
10788
|
+
if (key.mouse?.kind === "wheel") {
|
|
10789
|
+
dispatch({ type: "sessionsPanelMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10790
|
+
return;
|
|
10791
|
+
}
|
|
10792
|
+
if (isEnter) {
|
|
10793
|
+
const now = Date.now();
|
|
10794
|
+
if (now - lastEnterAtRef.current < 50) return;
|
|
10795
|
+
lastEnterAtRef.current = now;
|
|
10796
|
+
if (state.sessionResumeConfirm) {
|
|
10797
|
+
const pending = state.sessionResumeConfirm;
|
|
10798
|
+
dispatch({ type: "sessionResumeConfirmClear" });
|
|
10799
|
+
dispatch({ type: "sessionsPanelBusy", on: true });
|
|
10800
|
+
onResumeSession?.(pending.sessionId).then((result) => {
|
|
10801
|
+
if (!result) {
|
|
10802
|
+
dispatch({ type: "sessionsPanelBusy", on: false });
|
|
10803
|
+
return;
|
|
10804
|
+
}
|
|
10805
|
+
dispatch({ type: "replaceHistory", entries: result.entries, nextId: result.nextId });
|
|
10806
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
10807
|
+
dispatch({
|
|
10808
|
+
type: "addEntry",
|
|
10809
|
+
entry: {
|
|
10810
|
+
kind: "info",
|
|
10811
|
+
text: `Resumed session ${result.sessionId} \u2014 ${result.entries.length} entries replayed.`
|
|
10812
|
+
}
|
|
10813
|
+
});
|
|
10814
|
+
}).catch(() => {
|
|
10815
|
+
dispatch({ type: "sessionsPanelBusy", on: false });
|
|
10816
|
+
});
|
|
10817
|
+
return;
|
|
10818
|
+
}
|
|
10819
|
+
const sessions = state.sessionsPanel.sessions;
|
|
10820
|
+
const sel = state.sessionsPanel.selected;
|
|
10821
|
+
if (sel < 0 || sel >= sessions.length) return;
|
|
10822
|
+
const session = sessions[sel];
|
|
10823
|
+
if (!session) return;
|
|
10824
|
+
const isCurrentProject = session.projectRoot === projectRoot;
|
|
10825
|
+
if (isCurrentProject) {
|
|
10826
|
+
if (session.pid === process.pid) {
|
|
10827
|
+
dispatch({
|
|
10828
|
+
type: "addEntry",
|
|
10829
|
+
entry: { kind: "info", text: "That is this session \u2014 nothing to resume." }
|
|
10830
|
+
});
|
|
10831
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
10832
|
+
return;
|
|
10833
|
+
}
|
|
10834
|
+
if (session.pid != null) {
|
|
10835
|
+
dispatch({
|
|
10836
|
+
type: "addEntry",
|
|
10837
|
+
entry: {
|
|
10838
|
+
kind: "warn",
|
|
10839
|
+
text: `Session is open in another running wstack (pid ${session.pid}) \u2014 a live session cannot be resumed here. Use /resume for previous sessions.`
|
|
10840
|
+
}
|
|
10841
|
+
});
|
|
10842
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
10843
|
+
return;
|
|
10844
|
+
}
|
|
10845
|
+
dispatch({
|
|
10846
|
+
type: "sessionResumeConfirmSet",
|
|
10847
|
+
sessionId: session.sessionId,
|
|
10848
|
+
sessionName: session.projectName
|
|
10849
|
+
});
|
|
10850
|
+
} else {
|
|
10851
|
+
onSwitchToSession?.(session.sessionId, session.projectRoot ?? "", session.projectName);
|
|
10852
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
10853
|
+
requestExit?.(42);
|
|
10854
|
+
}
|
|
10855
|
+
return;
|
|
10856
|
+
}
|
|
10857
|
+
return;
|
|
10858
|
+
}
|
|
9005
10859
|
if (state.slashPicker.open) {
|
|
9006
10860
|
if (key.escape) {
|
|
9007
10861
|
dispatch({ type: "slashPickerClose" });
|
|
9008
10862
|
return;
|
|
9009
10863
|
}
|
|
10864
|
+
if (key.mouse?.kind === "wheel") {
|
|
10865
|
+
dispatch({ type: "slashPickerMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10866
|
+
return;
|
|
10867
|
+
}
|
|
9010
10868
|
if (key.upArrow) {
|
|
9011
10869
|
dispatch({ type: "slashPickerMove", delta: -1 });
|
|
9012
10870
|
return;
|
|
@@ -9043,6 +10901,10 @@ function App({
|
|
|
9043
10901
|
dispatch({ type: "pickerClose" });
|
|
9044
10902
|
return;
|
|
9045
10903
|
}
|
|
10904
|
+
if (key.mouse?.kind === "wheel") {
|
|
10905
|
+
dispatch({ type: "pickerMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
10906
|
+
return;
|
|
10907
|
+
}
|
|
9046
10908
|
if (key.upArrow) {
|
|
9047
10909
|
dispatch({ type: "pickerMove", delta: -1 });
|
|
9048
10910
|
return;
|
|
@@ -9169,6 +11031,24 @@ function App({
|
|
|
9169
11031
|
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
9170
11032
|
dispatch({ type: "toggleTodosMonitor" });
|
|
9171
11033
|
};
|
|
11034
|
+
if (key.fn === 1) {
|
|
11035
|
+
if (state.projectPicker.open) {
|
|
11036
|
+
dispatch({ type: "projectPickerClose" });
|
|
11037
|
+
} else {
|
|
11038
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
11039
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
11040
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
11041
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
11042
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
11043
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
11044
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
11045
|
+
if (state.processListOpen) dispatch({ type: "toggleProcessList" });
|
|
11046
|
+
if (state.goalPanelOpen) dispatch({ type: "toggleGoalPanel" });
|
|
11047
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
11048
|
+
openProjectPicker();
|
|
11049
|
+
}
|
|
11050
|
+
return;
|
|
11051
|
+
}
|
|
9172
11052
|
if (key.ctrl && input === "f" || key.fn === 2) {
|
|
9173
11053
|
toggleFleetOverlay();
|
|
9174
11054
|
return;
|
|
@@ -9181,47 +11061,6 @@ function App({
|
|
|
9181
11061
|
toggleWorktreeOverlay();
|
|
9182
11062
|
return;
|
|
9183
11063
|
}
|
|
9184
|
-
if (key.fn === 5) {
|
|
9185
|
-
if (state.settingsPicker.open) {
|
|
9186
|
-
dispatch({ type: "settingsClose" });
|
|
9187
|
-
} else if (getSettings && saveSettings) {
|
|
9188
|
-
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
9189
|
-
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
9190
|
-
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
9191
|
-
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
9192
|
-
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
9193
|
-
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
9194
|
-
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
9195
|
-
const cfg = getSettings();
|
|
9196
|
-
dispatch({
|
|
9197
|
-
type: "settingsOpen",
|
|
9198
|
-
mode: cfg.mode,
|
|
9199
|
-
delayMs: cfg.delayMs,
|
|
9200
|
-
titleAnimation: cfg.titleAnimation ?? true,
|
|
9201
|
-
yolo: cfg.yolo ?? false,
|
|
9202
|
-
streamFleet: cfg.streamFleet ?? true,
|
|
9203
|
-
chime: cfg.chime ?? false,
|
|
9204
|
-
confirmExit: cfg.confirmExit ?? true,
|
|
9205
|
-
nextPrediction: cfg.nextPrediction ?? false,
|
|
9206
|
-
featureMcp: cfg.featureMcp ?? true,
|
|
9207
|
-
featurePlugins: cfg.featurePlugins ?? true,
|
|
9208
|
-
featureMemory: cfg.featureMemory ?? true,
|
|
9209
|
-
featureSkills: cfg.featureSkills ?? true,
|
|
9210
|
-
featureModelsRegistry: cfg.featureModelsRegistry ?? true,
|
|
9211
|
-
contextAutoCompact: cfg.contextAutoCompact ?? true,
|
|
9212
|
-
contextStrategy: cfg.contextStrategy ?? "hybrid",
|
|
9213
|
-
logLevel: cfg.logLevel ?? "info",
|
|
9214
|
-
auditLevel: cfg.auditLevel ?? "standard",
|
|
9215
|
-
indexOnStart: cfg.indexOnStart ?? true,
|
|
9216
|
-
maxIterations: cfg.maxIterations ?? 500,
|
|
9217
|
-
autoProceedMaxIterations: cfg.autoProceedMaxIterations ?? 50,
|
|
9218
|
-
enhanceDelayMs: cfg.enhanceDelayMs ?? 6e4,
|
|
9219
|
-
debugStream: cfg.debugStream ?? false,
|
|
9220
|
-
configScope: cfg.configScope ?? "global"
|
|
9221
|
-
});
|
|
9222
|
-
}
|
|
9223
|
-
return;
|
|
9224
|
-
}
|
|
9225
11064
|
if (key.fn === 6) {
|
|
9226
11065
|
toggleTodosOverlay();
|
|
9227
11066
|
return;
|
|
@@ -9274,6 +11113,25 @@ function App({
|
|
|
9274
11113
|
}
|
|
9275
11114
|
return;
|
|
9276
11115
|
}
|
|
11116
|
+
if (key.fn === 10) {
|
|
11117
|
+
if (state.sessionsPanelOpen) {
|
|
11118
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
11119
|
+
} else {
|
|
11120
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
11121
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
11122
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
11123
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
11124
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
11125
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
11126
|
+
if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
11127
|
+
if (state.processListOpen) dispatch({ type: "toggleProcessList" });
|
|
11128
|
+
if (state.goalPanelOpen) dispatch({ type: "toggleGoalPanel" });
|
|
11129
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
11130
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
11131
|
+
loadLiveSessions();
|
|
11132
|
+
}
|
|
11133
|
+
return;
|
|
11134
|
+
}
|
|
9277
11135
|
if (key.ctrl && input === "s") {
|
|
9278
11136
|
if (state.settingsPicker.open) {
|
|
9279
11137
|
dispatch({ type: "settingsClose" });
|
|
@@ -9309,6 +11167,8 @@ function App({
|
|
|
9309
11167
|
maxIterations: cfg.maxIterations ?? 500,
|
|
9310
11168
|
autoProceedMaxIterations: cfg.autoProceedMaxIterations ?? 50,
|
|
9311
11169
|
enhanceDelayMs: cfg.enhanceDelayMs ?? 6e4,
|
|
11170
|
+
enhanceEnabled: cfg.enhanceEnabled ?? true,
|
|
11171
|
+
enhanceLanguage: cfg.enhanceLanguage ?? "original",
|
|
9312
11172
|
debugStream: cfg.debugStream ?? false,
|
|
9313
11173
|
configScope: cfg.configScope ?? "global"
|
|
9314
11174
|
});
|
|
@@ -9332,6 +11192,10 @@ function App({
|
|
|
9332
11192
|
dispatch({ type: "settingsClose" });
|
|
9333
11193
|
return;
|
|
9334
11194
|
}
|
|
11195
|
+
if (state.projectPicker.open) {
|
|
11196
|
+
dispatch({ type: "projectPickerClose" });
|
|
11197
|
+
return;
|
|
11198
|
+
}
|
|
9335
11199
|
if (state.queuePanelOpen) {
|
|
9336
11200
|
dispatch({ type: "toggleQueuePanel" });
|
|
9337
11201
|
return;
|
|
@@ -9344,11 +11208,15 @@ function App({
|
|
|
9344
11208
|
dispatch({ type: "toggleGoalPanel" });
|
|
9345
11209
|
return;
|
|
9346
11210
|
}
|
|
11211
|
+
if (state.sessionsPanelOpen) {
|
|
11212
|
+
dispatch({ type: "toggleSessionsPanel" });
|
|
11213
|
+
return;
|
|
11214
|
+
}
|
|
9347
11215
|
}
|
|
9348
11216
|
if (state.processListOpen) {
|
|
9349
11217
|
return;
|
|
9350
11218
|
}
|
|
9351
|
-
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) {
|
|
11219
|
+
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) {
|
|
9352
11220
|
dispatch({ type: "toggleHelp" });
|
|
9353
11221
|
return;
|
|
9354
11222
|
}
|
|
@@ -9382,6 +11250,12 @@ function App({
|
|
|
9382
11250
|
}
|
|
9383
11251
|
if (cursor === 0) return;
|
|
9384
11252
|
const next2 = buffer.slice(0, cursor - 1) + buffer.slice(cursor);
|
|
11253
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
11254
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
11255
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
11256
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
11257
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
11258
|
+
}
|
|
9385
11259
|
setDraft(next2, cursor - 1);
|
|
9386
11260
|
return;
|
|
9387
11261
|
}
|
|
@@ -9392,12 +11266,24 @@ function App({
|
|
|
9392
11266
|
const nextWordStart = afterCursor.indexOf(" ");
|
|
9393
11267
|
const end = nextWordStart === -1 ? buffer.length : cursor + nextWordStart + 1;
|
|
9394
11268
|
const next3 = buffer.slice(0, cursor) + buffer.slice(end);
|
|
11269
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
11270
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
11271
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
11272
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
11273
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
11274
|
+
}
|
|
9395
11275
|
setDraft(next3, cursor);
|
|
9396
11276
|
return;
|
|
9397
11277
|
}
|
|
9398
11278
|
if (cursor >= buffer.length) return;
|
|
9399
11279
|
const span = tokenLengthForward(buffer, cursor) || 1;
|
|
9400
11280
|
const next2 = buffer.slice(0, cursor) + buffer.slice(cursor + span);
|
|
11281
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
11282
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
11283
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
11284
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
11285
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
11286
|
+
}
|
|
9401
11287
|
setDraft(next2, cursor);
|
|
9402
11288
|
return;
|
|
9403
11289
|
}
|
|
@@ -9433,7 +11319,67 @@ function App({
|
|
|
9433
11319
|
setDraft(buffer, buffer.length);
|
|
9434
11320
|
return;
|
|
9435
11321
|
}
|
|
9436
|
-
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;
|
|
11322
|
+
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;
|
|
11323
|
+
if (mouseMode && !overlayOpen) {
|
|
11324
|
+
if (key.mouse?.kind === "wheel") {
|
|
11325
|
+
if (key.mouse.shift) dispatch({ type: "scrollPage", dir: key.mouse.wheel > 0 ? "up" : "down" });
|
|
11326
|
+
else dispatch({ type: "scrollBy", delta: key.mouse.wheel > 0 ? 3 : -3 });
|
|
11327
|
+
return;
|
|
11328
|
+
}
|
|
11329
|
+
if ((key.mouse?.kind === "press" || key.mouse?.kind === "move") && key.mouse.button === "left") {
|
|
11330
|
+
const region = hitRegion(
|
|
11331
|
+
{ termRows, termCols: stdout?.columns ?? 80, viewportRows: state.viewportRows },
|
|
11332
|
+
key.mouse.x,
|
|
11333
|
+
key.mouse.y
|
|
11334
|
+
);
|
|
11335
|
+
if (region?.kind === "scrollbar") {
|
|
11336
|
+
dispatch({
|
|
11337
|
+
type: "scrollTo",
|
|
11338
|
+
offset: scrollOffsetForTrackRow(state.viewportRows, state.totalLines, region.cell)
|
|
11339
|
+
});
|
|
11340
|
+
return;
|
|
11341
|
+
}
|
|
11342
|
+
}
|
|
11343
|
+
if (key.mouse?.kind === "press" && key.mouse.button === "left" && statusBarWrapRef.current) {
|
|
11344
|
+
const sbHeight = measureElement(statusBarWrapRef.current).height;
|
|
11345
|
+
const belowHeight = belowStatusBarRef.current ? measureElement(belowStatusBarRef.current).height : 0;
|
|
11346
|
+
const cols = stdout?.columns ?? 80;
|
|
11347
|
+
const mx = key.mouse.x;
|
|
11348
|
+
const my = key.mouse.y;
|
|
11349
|
+
const rowFor = (line) => statusBarLineRow({ termRows, statusBarHeight: sbHeight, belowHeight, headerRows: 1, line });
|
|
11350
|
+
const inSpan = (span) => mx >= span.start + 1 && mx <= span.start + span.len;
|
|
11351
|
+
if (cols >= COMPACT_THRESHOLD && my === rowFor(0)) {
|
|
11352
|
+
const span = statusBarModelSpan({
|
|
11353
|
+
version: appVersion,
|
|
11354
|
+
state: state.status,
|
|
11355
|
+
fleetRunning: fleetCounts?.running ?? 0,
|
|
11356
|
+
model: `${liveProvider}/${liveModel}`
|
|
11357
|
+
});
|
|
11358
|
+
if (inSpan(span)) {
|
|
11359
|
+
await openModelPicker();
|
|
11360
|
+
return;
|
|
11361
|
+
}
|
|
11362
|
+
}
|
|
11363
|
+
const autoSpan = statusBarAutonomySpan({ yolo: yoloLive, autonomy: autonomyLive });
|
|
11364
|
+
if (autoSpan && my === rowFor(1) && inSpan(autoSpan)) {
|
|
11365
|
+
dispatch({ type: "autonomyPickerOpen", options: AUTONOMY_OPTIONS });
|
|
11366
|
+
return;
|
|
11367
|
+
}
|
|
11368
|
+
const todosShown = !!todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0);
|
|
11369
|
+
if (todosShown && my === rowFor(2) && inSpan(statusBarTodosSpan())) {
|
|
11370
|
+
dispatch({ type: "toggleTodosMonitor" });
|
|
11371
|
+
return;
|
|
11372
|
+
}
|
|
11373
|
+
}
|
|
11374
|
+
if (key.pageUp) {
|
|
11375
|
+
dispatch({ type: "scrollPage", dir: "up" });
|
|
11376
|
+
return;
|
|
11377
|
+
}
|
|
11378
|
+
if (key.pageDown) {
|
|
11379
|
+
dispatch({ type: "scrollPage", dir: "down" });
|
|
11380
|
+
return;
|
|
11381
|
+
}
|
|
11382
|
+
}
|
|
9437
11383
|
if (key.upArrow) {
|
|
9438
11384
|
if (!overlayOpen && state.inputHistory.length > 0) {
|
|
9439
11385
|
dispatch({ type: "historyUp" });
|
|
@@ -9465,6 +11411,12 @@ function App({
|
|
|
9465
11411
|
return;
|
|
9466
11412
|
}
|
|
9467
11413
|
if (key.ctrl && input === "u") {
|
|
11414
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
11415
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
11416
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
11417
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
11418
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
11419
|
+
}
|
|
9468
11420
|
setDraft("", 0);
|
|
9469
11421
|
return;
|
|
9470
11422
|
}
|
|
@@ -9472,12 +11424,24 @@ function App({
|
|
|
9472
11424
|
if (cursor >= buffer.length) return;
|
|
9473
11425
|
const span = tokenLengthForward(buffer, cursor) || 1;
|
|
9474
11426
|
const next2 = buffer.slice(0, cursor) + buffer.slice(cursor + span);
|
|
11427
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
11428
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
11429
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
11430
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
11431
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
11432
|
+
}
|
|
9475
11433
|
setDraft(next2, cursor);
|
|
9476
11434
|
return;
|
|
9477
11435
|
}
|
|
9478
11436
|
if (key.ctrl && input === "k") {
|
|
9479
11437
|
if (cursor >= buffer.length) return;
|
|
9480
11438
|
const next2 = buffer.slice(0, cursor);
|
|
11439
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
11440
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
11441
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
11442
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
11443
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
11444
|
+
}
|
|
9481
11445
|
setDraft(next2, cursor);
|
|
9482
11446
|
return;
|
|
9483
11447
|
}
|
|
@@ -9495,6 +11459,12 @@ function App({
|
|
|
9495
11459
|
await commitPaste(input);
|
|
9496
11460
|
return;
|
|
9497
11461
|
}
|
|
11462
|
+
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
11463
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
11464
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
11465
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
11466
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
11467
|
+
}
|
|
9498
11468
|
const next = buffer.slice(0, cursor) + input + buffer.slice(cursor);
|
|
9499
11469
|
setDraft(next, cursor + input.length);
|
|
9500
11470
|
};
|
|
@@ -9561,6 +11531,12 @@ function App({
|
|
|
9561
11531
|
} catch {
|
|
9562
11532
|
}
|
|
9563
11533
|
}
|
|
11534
|
+
if (result.status === "done" && result.finalText && onSuggestionsParsed) {
|
|
11535
|
+
try {
|
|
11536
|
+
onSuggestionsParsed(result.finalText);
|
|
11537
|
+
} catch {
|
|
11538
|
+
}
|
|
11539
|
+
}
|
|
9564
11540
|
if (tokenCounter && before) {
|
|
9565
11541
|
const after = tokenCounter.total();
|
|
9566
11542
|
const costAfter = tokenCounter.estimateCost().total;
|
|
@@ -9715,6 +11691,9 @@ function App({
|
|
|
9715
11691
|
return;
|
|
9716
11692
|
}
|
|
9717
11693
|
dispatch({ type: "resetInterrupts" });
|
|
11694
|
+
autoSubmitStreakRef.current = 0;
|
|
11695
|
+
autoSubmitCapWarnedRef.current = false;
|
|
11696
|
+
dispatch({ type: "scrollToBottom" });
|
|
9718
11697
|
const pushSubmittedHistory = () => {
|
|
9719
11698
|
if (trimmed) dispatch({ type: "historyPush", text: trimmed });
|
|
9720
11699
|
};
|
|
@@ -9755,6 +11734,25 @@ ${content}
|
|
|
9755
11734
|
const m = res.metadata.autoPhaseInit;
|
|
9756
11735
|
dispatch({ type: "autoPhaseInit", title: m.title });
|
|
9757
11736
|
}
|
|
11737
|
+
const mouseToggle = res?.metadata?.mouseToggle;
|
|
11738
|
+
if (mouseToggle) {
|
|
11739
|
+
const nextVal = mouseToggle === "on" ? true : mouseToggle === "off" ? false : mouseToggle === "toggle" ? !mouseMode : mouseMode;
|
|
11740
|
+
if (mouseToggle !== "query" && nextVal !== mouseMode) {
|
|
11741
|
+
setMouseMode(nextVal);
|
|
11742
|
+
const cur = getSettings?.();
|
|
11743
|
+
if (cur && saveSettings) {
|
|
11744
|
+
Promise.resolve(saveSettings({ ...cur, mouseMode: nextVal })).catch(() => {
|
|
11745
|
+
});
|
|
11746
|
+
}
|
|
11747
|
+
}
|
|
11748
|
+
dispatch({
|
|
11749
|
+
type: "addEntry",
|
|
11750
|
+
entry: {
|
|
11751
|
+
kind: "info",
|
|
11752
|
+
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."
|
|
11753
|
+
}
|
|
11754
|
+
});
|
|
11755
|
+
}
|
|
9758
11756
|
const ctxModel = agent.ctx.model;
|
|
9759
11757
|
if (ctxModel && ctxModel !== liveModel) setLiveModel(ctxModel);
|
|
9760
11758
|
const ctxProviderId = agent.ctx.provider?.id;
|
|
@@ -9914,6 +11912,9 @@ User message:
|
|
|
9914
11912
|
clearDraft();
|
|
9915
11913
|
const blocks = await builder.submit();
|
|
9916
11914
|
if (state.status !== "idle") {
|
|
11915
|
+
if (autonomyLive === "auto" && nextStepsAutoSubmitTimerRef.current != null) {
|
|
11916
|
+
switchAutonomy?.("off");
|
|
11917
|
+
}
|
|
9917
11918
|
dispatch({
|
|
9918
11919
|
type: "addEntry",
|
|
9919
11920
|
entry: { kind: "user", text: displayText, queued: true, pasteContent }
|
|
@@ -9922,6 +11923,9 @@ User message:
|
|
|
9922
11923
|
return;
|
|
9923
11924
|
}
|
|
9924
11925
|
dispatch({ type: "addEntry", entry: { kind: "user", text: displayText, pasteContent } });
|
|
11926
|
+
if (autonomyLive === "auto" && nextStepsAutoSubmitTimerRef.current != null) {
|
|
11927
|
+
switchAutonomy?.("off");
|
|
11928
|
+
}
|
|
9925
11929
|
await runBlocks(blocks);
|
|
9926
11930
|
};
|
|
9927
11931
|
const bootInjectedRef = useRef(false);
|
|
@@ -9974,15 +11978,29 @@ User message:
|
|
|
9974
11978
|
const inputHeight = Math.max(1, inputCellRows.length);
|
|
9975
11979
|
const hideInput = enhanceActive || state.helpOpen || state.processListOpen;
|
|
9976
11980
|
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, flexShrink: 0, children: [
|
|
9977
|
-
/* @__PURE__ */ jsx(
|
|
11981
|
+
mouseMode ? /* @__PURE__ */ jsx(
|
|
11982
|
+
ScrollableHistory,
|
|
11983
|
+
{
|
|
11984
|
+
entries: state.entries,
|
|
11985
|
+
streamingText: state.streamingText,
|
|
11986
|
+
toolStream: state.toolStream,
|
|
11987
|
+
scrollOffset: state.scrollOffset,
|
|
11988
|
+
viewportRows: state.viewportRows,
|
|
11989
|
+
totalLines: state.totalLines,
|
|
11990
|
+
onMeasure: (totalLines) => dispatch({ type: "setMeasuredLines", totalLines }),
|
|
11991
|
+
setSuggestions
|
|
11992
|
+
}
|
|
11993
|
+
) : /* @__PURE__ */ jsx(
|
|
9978
11994
|
History,
|
|
9979
11995
|
{
|
|
9980
11996
|
entries: state.entries,
|
|
11997
|
+
generation: state.historyGen,
|
|
9981
11998
|
streamingText: state.streamingText,
|
|
9982
|
-
toolStream: state.toolStream
|
|
11999
|
+
toolStream: state.toolStream,
|
|
12000
|
+
setSuggestions
|
|
9983
12001
|
}
|
|
9984
12002
|
),
|
|
9985
|
-
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [
|
|
12003
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexShrink: 0, ref: bottomRegionRef, children: [
|
|
9986
12004
|
/* @__PURE__ */ jsx(
|
|
9987
12005
|
Input,
|
|
9988
12006
|
{
|
|
@@ -10033,6 +12051,16 @@ User message:
|
|
|
10033
12051
|
hint: state.autonomyPicker.hint
|
|
10034
12052
|
}
|
|
10035
12053
|
) : null,
|
|
12054
|
+
state.resumePicker.open ? /* @__PURE__ */ jsx(
|
|
12055
|
+
ResumePicker,
|
|
12056
|
+
{
|
|
12057
|
+
sessions: state.resumePicker.sessions,
|
|
12058
|
+
selected: state.resumePicker.selected,
|
|
12059
|
+
busy: state.resumePicker.busy,
|
|
12060
|
+
error: state.resumePicker.error,
|
|
12061
|
+
hint: state.resumePicker.hint
|
|
12062
|
+
}
|
|
12063
|
+
) : null,
|
|
10036
12064
|
state.settingsPicker.open ? /* @__PURE__ */ jsx(
|
|
10037
12065
|
SettingsPicker,
|
|
10038
12066
|
{
|
|
@@ -10058,11 +12086,32 @@ User message:
|
|
|
10058
12086
|
maxIterations: state.settingsPicker.maxIterations,
|
|
10059
12087
|
autoProceedMaxIterations: state.settingsPicker.autoProceedMaxIterations,
|
|
10060
12088
|
enhanceDelayMs: state.settingsPicker.enhanceDelayMs,
|
|
12089
|
+
enhanceEnabled: state.settingsPicker.enhanceEnabled,
|
|
12090
|
+
enhanceLanguage: state.settingsPicker.enhanceLanguage,
|
|
10061
12091
|
debugStream: state.settingsPicker.debugStream,
|
|
10062
12092
|
configScope: state.settingsPicker.configScope,
|
|
10063
12093
|
hint: state.settingsPicker.hint
|
|
10064
12094
|
}
|
|
10065
12095
|
) : null,
|
|
12096
|
+
state.projectPicker.open ? /* @__PURE__ */ jsx(
|
|
12097
|
+
ProjectPicker,
|
|
12098
|
+
{
|
|
12099
|
+
items: state.projectPicker.items,
|
|
12100
|
+
selected: state.projectPicker.selected,
|
|
12101
|
+
filter: state.projectPicker.filter,
|
|
12102
|
+
hint: state.projectPicker.hint
|
|
12103
|
+
}
|
|
12104
|
+
) : null,
|
|
12105
|
+
state.sessionsPanelOpen ? /* @__PURE__ */ jsx(
|
|
12106
|
+
SessionsPanel,
|
|
12107
|
+
{
|
|
12108
|
+
sessions: state.sessionsPanel.sessions,
|
|
12109
|
+
busy: state.sessionsPanel.busy,
|
|
12110
|
+
selected: state.sessionsPanel.selected,
|
|
12111
|
+
resumeConfirm: state.sessionResumeConfirm ? { sessionName: state.sessionResumeConfirm.sessionName } : void 0,
|
|
12112
|
+
currentSessionId: agent.ctx.session?.id
|
|
12113
|
+
}
|
|
12114
|
+
) : null,
|
|
10066
12115
|
state.rewindOverlay ? (() => {
|
|
10067
12116
|
const overlay = state.rewindOverlay;
|
|
10068
12117
|
return /* @__PURE__ */ jsx(
|
|
@@ -10090,7 +12139,7 @@ User message:
|
|
|
10090
12139
|
}
|
|
10091
12140
|
) }) : null,
|
|
10092
12141
|
state.confirmQueue.length > 0 && (() => {
|
|
10093
|
-
const head = expectDefined(state.confirmQueue[0]);
|
|
12142
|
+
const head = expectDefined$1(state.confirmQueue[0]);
|
|
10094
12143
|
let resolved = false;
|
|
10095
12144
|
const onDecision = (decision) => {
|
|
10096
12145
|
if (resolved) return;
|
|
@@ -10175,7 +12224,7 @@ User message:
|
|
|
10175
12224
|
}
|
|
10176
12225
|
);
|
|
10177
12226
|
})() : null,
|
|
10178
|
-
/* @__PURE__ */ jsx(
|
|
12227
|
+
/* @__PURE__ */ jsx(Box, { ref: statusBarWrapRef, flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx(
|
|
10179
12228
|
StatusBar,
|
|
10180
12229
|
{
|
|
10181
12230
|
model: `${liveProvider}/${liveModel}`,
|
|
@@ -10189,11 +12238,13 @@ User message:
|
|
|
10189
12238
|
startedAt: startedAtRef.current,
|
|
10190
12239
|
todos,
|
|
10191
12240
|
plan: planCounts ?? void 0,
|
|
12241
|
+
tasks: taskCounts ?? void 0,
|
|
10192
12242
|
fleet: fleetCounts,
|
|
10193
12243
|
git: gitInfo,
|
|
10194
12244
|
context: contextWindow,
|
|
10195
12245
|
brain: state.brain,
|
|
10196
12246
|
projectName,
|
|
12247
|
+
workingDir: workingDirChip,
|
|
10197
12248
|
subagentCount: Object.keys(state.fleet).length,
|
|
10198
12249
|
processCount: getProcessRegistry().activeCount,
|
|
10199
12250
|
hiddenItems,
|
|
@@ -10203,67 +12254,101 @@ User message:
|
|
|
10203
12254
|
modeLabel: liveModeLabel || void 0,
|
|
10204
12255
|
debugStreamStats: state.debugStreamStats,
|
|
10205
12256
|
enhanceCountdown,
|
|
10206
|
-
|
|
12257
|
+
nextStepsAutoSubmitCountdown,
|
|
12258
|
+
autoProceedCountdown: state.countdown?.remainingSeconds ?? null,
|
|
12259
|
+
sessionCount,
|
|
12260
|
+
mailbox: mailboxStatus
|
|
10207
12261
|
}
|
|
10208
|
-
),
|
|
10209
|
-
|
|
10210
|
-
|
|
10211
|
-
AgentsMonitor,
|
|
10212
|
-
{
|
|
10213
|
-
entries: entriesWithLeader,
|
|
10214
|
-
totalCost: state.fleetCost,
|
|
10215
|
-
leaderCost: tokenCounter?.estimateCost().total ?? 0,
|
|
10216
|
-
totalTokens: state.fleetTokens,
|
|
10217
|
-
nowTick
|
|
10218
|
-
}
|
|
10219
|
-
) : state.autoPhase?.monitorOpen ? /* @__PURE__ */ jsx(
|
|
10220
|
-
PhaseMonitor,
|
|
10221
|
-
{
|
|
10222
|
-
phases: state.autoPhase.phases,
|
|
10223
|
-
runningPhaseIds: state.autoPhase.runningPhaseIds,
|
|
10224
|
-
elapsedMs: state.autoPhase.elapsedMs,
|
|
10225
|
-
nowTick,
|
|
10226
|
-
onClose: () => dispatch({ type: "autoPhaseMonitorToggle" })
|
|
10227
|
-
}
|
|
10228
|
-
) : state.worktreeMonitorOpen ? /* @__PURE__ */ jsx(
|
|
10229
|
-
WorktreeMonitor,
|
|
10230
|
-
{
|
|
10231
|
-
worktrees: state.worktrees,
|
|
10232
|
-
baseBranch: state.worktreeBase,
|
|
10233
|
-
nowTick,
|
|
10234
|
-
onClose: () => dispatch({ type: "worktreeMonitorToggle" })
|
|
10235
|
-
}
|
|
10236
|
-
) : state.todosMonitorOpen ? /* @__PURE__ */ jsx(TodosMonitor, { todos: agent.ctx.todos }) : state.monitorOpen ? /* @__PURE__ */ jsx(
|
|
10237
|
-
FleetMonitor,
|
|
10238
|
-
{
|
|
10239
|
-
entries: state.fleet,
|
|
10240
|
-
totalCost: state.fleetCost,
|
|
10241
|
-
totalTokens: state.fleetTokens,
|
|
10242
|
-
maxConcurrent: state.fleetConcurrency,
|
|
10243
|
-
nowTick,
|
|
10244
|
-
collabSession: state.collabSession
|
|
10245
|
-
}
|
|
10246
|
-
) : director ? /* @__PURE__ */ jsx(
|
|
10247
|
-
FleetPanel,
|
|
10248
|
-
{
|
|
10249
|
-
entries: entriesWithLeader,
|
|
10250
|
-
totalCost: state.fleetCost,
|
|
10251
|
-
roster: fleetRoster,
|
|
10252
|
-
collabSession: state.collabSession
|
|
10253
|
-
}
|
|
10254
|
-
) : null,
|
|
10255
|
-
state.autoPhase && !state.autoPhase.monitorOpen ? /* @__PURE__ */ jsx(
|
|
10256
|
-
PhasePanel,
|
|
12262
|
+
) }),
|
|
12263
|
+
/* @__PURE__ */ jsx(
|
|
12264
|
+
MailboxPanel,
|
|
10257
12265
|
{
|
|
10258
|
-
|
|
10259
|
-
|
|
10260
|
-
|
|
12266
|
+
messages: mailboxMessages,
|
|
12267
|
+
agents: mailboxAgents,
|
|
12268
|
+
unreadCount: mailboxStatus.unread,
|
|
12269
|
+
open: mailboxPanelOpen
|
|
10261
12270
|
}
|
|
10262
|
-
)
|
|
10263
|
-
|
|
10264
|
-
|
|
10265
|
-
|
|
10266
|
-
|
|
12271
|
+
),
|
|
12272
|
+
/* @__PURE__ */ jsxs(Box, { ref: belowStatusBarRef, flexDirection: "column", flexShrink: 0, children: [
|
|
12273
|
+
state.helpOpen ? /* @__PURE__ */ jsx(HelpOverlay, {}) : null,
|
|
12274
|
+
state.agentsMonitorOpen ? /* @__PURE__ */ jsx(
|
|
12275
|
+
AgentsMonitor,
|
|
12276
|
+
{
|
|
12277
|
+
entries: entriesWithLeader,
|
|
12278
|
+
totalCost: state.fleetCost,
|
|
12279
|
+
leaderCost: tokenCounter?.estimateCost().total ?? 0,
|
|
12280
|
+
totalTokens: state.fleetTokens,
|
|
12281
|
+
nowTick
|
|
12282
|
+
}
|
|
12283
|
+
) : state.autoPhase?.monitorOpen ? /* @__PURE__ */ jsx(
|
|
12284
|
+
PhaseMonitor,
|
|
12285
|
+
{
|
|
12286
|
+
phases: state.autoPhase.phases,
|
|
12287
|
+
runningPhaseIds: state.autoPhase.runningPhaseIds,
|
|
12288
|
+
elapsedMs: state.autoPhase.elapsedMs,
|
|
12289
|
+
nowTick,
|
|
12290
|
+
onClose: () => dispatch({ type: "autoPhaseMonitorToggle" })
|
|
12291
|
+
}
|
|
12292
|
+
) : state.worktreeMonitorOpen ? /* @__PURE__ */ jsx(
|
|
12293
|
+
WorktreeMonitor,
|
|
12294
|
+
{
|
|
12295
|
+
worktrees: state.worktrees,
|
|
12296
|
+
baseBranch: state.worktreeBase,
|
|
12297
|
+
nowTick,
|
|
12298
|
+
onClose: () => dispatch({ type: "worktreeMonitorToggle" })
|
|
12299
|
+
}
|
|
12300
|
+
) : state.todosMonitorOpen ? /* @__PURE__ */ jsx(TodosMonitor, { todos: agent.ctx.todos }) : state.monitorOpen ? /* @__PURE__ */ jsx(
|
|
12301
|
+
FleetMonitor,
|
|
12302
|
+
{
|
|
12303
|
+
entries: state.fleet,
|
|
12304
|
+
totalCost: state.fleetCost,
|
|
12305
|
+
totalTokens: state.fleetTokens,
|
|
12306
|
+
maxConcurrent: state.fleetConcurrency,
|
|
12307
|
+
nowTick,
|
|
12308
|
+
collabSession: state.collabSession
|
|
12309
|
+
}
|
|
12310
|
+
) : director ? /* @__PURE__ */ jsx(
|
|
12311
|
+
FleetPanel,
|
|
12312
|
+
{
|
|
12313
|
+
entries: entriesWithLeader,
|
|
12314
|
+
totalCost: state.fleetCost,
|
|
12315
|
+
roster: fleetRoster,
|
|
12316
|
+
collabSession: state.collabSession
|
|
12317
|
+
}
|
|
12318
|
+
) : null,
|
|
12319
|
+
state.autoPhase && !state.autoPhase.monitorOpen ? /* @__PURE__ */ jsx(
|
|
12320
|
+
PhasePanel,
|
|
12321
|
+
{
|
|
12322
|
+
phases: state.autoPhase.phases,
|
|
12323
|
+
runningPhaseIds: state.autoPhase.runningPhaseIds,
|
|
12324
|
+
nowTick
|
|
12325
|
+
}
|
|
12326
|
+
) : null,
|
|
12327
|
+
Object.keys(state.worktrees).length > 0 && !state.worktreeMonitorOpen && !state.monitorOpen ? /* @__PURE__ */ jsx(WorktreePanel, { worktrees: state.worktrees, nowTick }) : null,
|
|
12328
|
+
state.queuePanelOpen ? /* @__PURE__ */ jsx(QueuePanel, { items: state.queue }) : null,
|
|
12329
|
+
state.processListOpen ? /* @__PURE__ */ jsx(ProcessListMonitor, {}) : null,
|
|
12330
|
+
state.goalPanelOpen ? /* @__PURE__ */ jsx(GoalPanel, { goal: state.goalSummary }) : null,
|
|
12331
|
+
(() => {
|
|
12332
|
+
const anyMonitorOpen = state.agentsMonitorOpen || (state.autoPhase?.monitorOpen ?? false) || state.worktreeMonitorOpen || state.todosMonitorOpen || state.monitorOpen || state.processListOpen || state.queuePanelOpen || state.goalPanelOpen;
|
|
12333
|
+
let nextPanelHint;
|
|
12334
|
+
if (state.agentsMonitorOpen) {
|
|
12335
|
+
nextPanelHint = { key: "F6", label: "todos" };
|
|
12336
|
+
} else if (state.autoPhase?.monitorOpen || state.worktreeMonitorOpen || state.todosMonitorOpen) {
|
|
12337
|
+
nextPanelHint = { key: "F9", label: "goal" };
|
|
12338
|
+
} else if (state.queuePanelOpen || state.processListOpen || state.goalPanelOpen) {
|
|
12339
|
+
nextPanelHint = { key: "F3", label: "agents" };
|
|
12340
|
+
} else if (anyMonitorOpen) {
|
|
12341
|
+
nextPanelHint = { key: "F3", label: "agents" };
|
|
12342
|
+
}
|
|
12343
|
+
const ctx = {
|
|
12344
|
+
monitor: anyMonitorOpen,
|
|
12345
|
+
managed: state.scrollOffset > 0,
|
|
12346
|
+
picker: state.settingsPicker.open || state.modelPicker.open || state.autonomyPicker.open,
|
|
12347
|
+
nextPanelHint
|
|
12348
|
+
};
|
|
12349
|
+
return /* @__PURE__ */ jsx(KeyHintBar, { context: ctx });
|
|
12350
|
+
})()
|
|
12351
|
+
] })
|
|
10267
12352
|
] })
|
|
10268
12353
|
] }) });
|
|
10269
12354
|
}
|
|
@@ -10365,6 +12450,45 @@ function startTerminalTitle(opts) {
|
|
|
10365
12450
|
// src/run-tui.ts
|
|
10366
12451
|
var BRACKETED_PASTE_ON = "\x1B[?2004h";
|
|
10367
12452
|
var BRACKETED_PASTE_OFF = "\x1B[?2004l";
|
|
12453
|
+
var origConsoleLog = console.log;
|
|
12454
|
+
var origConsoleWarn = console.warn;
|
|
12455
|
+
var origConsoleError = console.error;
|
|
12456
|
+
var origConsoleDebug = console.debug;
|
|
12457
|
+
var origConsoleInfo = console.info;
|
|
12458
|
+
var origConsoleTable = console.table;
|
|
12459
|
+
var origConsoleTrace = console.trace;
|
|
12460
|
+
var origStderrWrite = process.stderr.write.bind(process.stderr);
|
|
12461
|
+
var consoleNoop = (..._args) => {
|
|
12462
|
+
};
|
|
12463
|
+
var stderrNoop = ((_chunk, _encodingOrCb, _cb) => {
|
|
12464
|
+
if (typeof _encodingOrCb === "function") _encodingOrCb();
|
|
12465
|
+
else if (typeof _cb === "function") _cb();
|
|
12466
|
+
return true;
|
|
12467
|
+
});
|
|
12468
|
+
var warningNoop = (_warning) => {
|
|
12469
|
+
};
|
|
12470
|
+
function silenceTerminal() {
|
|
12471
|
+
console.log = consoleNoop;
|
|
12472
|
+
console.warn = consoleNoop;
|
|
12473
|
+
console.error = consoleNoop;
|
|
12474
|
+
console.debug = consoleNoop;
|
|
12475
|
+
console.info = consoleNoop;
|
|
12476
|
+
console.table = consoleNoop;
|
|
12477
|
+
console.trace = consoleNoop;
|
|
12478
|
+
process.stderr.write = stderrNoop;
|
|
12479
|
+
process.on("warning", warningNoop);
|
|
12480
|
+
}
|
|
12481
|
+
function unsilenceTerminal() {
|
|
12482
|
+
console.log = origConsoleLog;
|
|
12483
|
+
console.warn = origConsoleWarn;
|
|
12484
|
+
console.error = origConsoleError;
|
|
12485
|
+
console.debug = origConsoleDebug;
|
|
12486
|
+
console.info = origConsoleInfo;
|
|
12487
|
+
console.table = origConsoleTable;
|
|
12488
|
+
console.trace = origConsoleTrace;
|
|
12489
|
+
process.stderr.write = origStderrWrite;
|
|
12490
|
+
process.off("warning", warningNoop);
|
|
12491
|
+
}
|
|
10368
12492
|
async function runTui(opts) {
|
|
10369
12493
|
const stdout = process.stdout;
|
|
10370
12494
|
const stdin = process.stdin;
|
|
@@ -10374,14 +12498,16 @@ async function runTui(opts) {
|
|
|
10374
12498
|
);
|
|
10375
12499
|
return 2;
|
|
10376
12500
|
}
|
|
12501
|
+
silenceTerminal();
|
|
10377
12502
|
stdout.write(BRACKETED_PASTE_ON);
|
|
12503
|
+
const mouseEnabled = opts.mouse ?? opts.getSettings?.().mouseMode ?? process.env.WRONGSTACK_MOUSE === "1";
|
|
10378
12504
|
stdout.write("\x1B[2J\x1B[H");
|
|
10379
12505
|
const inkStdin = stdin;
|
|
10380
12506
|
const stopTitle = opts.titleAnimation !== false ? startTerminalTitle({
|
|
10381
12507
|
stdout,
|
|
10382
12508
|
events: opts.events,
|
|
10383
12509
|
model: opts.model,
|
|
10384
|
-
appName: opts.projectRoot ?
|
|
12510
|
+
appName: opts.projectRoot ? path4.basename(opts.projectRoot) : void 0
|
|
10385
12511
|
}) : (() => {
|
|
10386
12512
|
});
|
|
10387
12513
|
const swallowSignals = ["SIGTSTP", "SIGQUIT", "SIGTTIN", "SIGTTOU"];
|
|
@@ -10397,12 +12523,14 @@ async function runTui(opts) {
|
|
|
10397
12523
|
const cleanup = () => {
|
|
10398
12524
|
if (cleaned) return;
|
|
10399
12525
|
cleaned = true;
|
|
12526
|
+
unsilenceTerminal();
|
|
10400
12527
|
try {
|
|
10401
12528
|
stopTitle();
|
|
10402
12529
|
} catch {
|
|
10403
12530
|
}
|
|
10404
12531
|
try {
|
|
10405
12532
|
stdout.write(BRACKETED_PASTE_OFF);
|
|
12533
|
+
stdout.write(MOUSE_OFF);
|
|
10406
12534
|
} catch {
|
|
10407
12535
|
}
|
|
10408
12536
|
};
|
|
@@ -10423,14 +12551,26 @@ async function runTui(opts) {
|
|
|
10423
12551
|
};
|
|
10424
12552
|
return new Promise((resolve) => {
|
|
10425
12553
|
let exitCode = 0;
|
|
12554
|
+
let hardExitTimer = null;
|
|
10426
12555
|
const onExit = (code) => {
|
|
10427
12556
|
exitCode = code;
|
|
10428
12557
|
};
|
|
10429
12558
|
const settle = (code) => {
|
|
12559
|
+
if (hardExitTimer) {
|
|
12560
|
+
clearTimeout(hardExitTimer);
|
|
12561
|
+
hardExitTimer = null;
|
|
12562
|
+
}
|
|
10430
12563
|
cleanup();
|
|
10431
12564
|
detachListeners();
|
|
10432
12565
|
resolve(code);
|
|
10433
12566
|
};
|
|
12567
|
+
const requestExit = (code) => {
|
|
12568
|
+
onExit(code);
|
|
12569
|
+
instance?.unmount();
|
|
12570
|
+
hardExitTimer = setTimeout(() => process.exit(code), 5e3);
|
|
12571
|
+
hardExitTimer.unref();
|
|
12572
|
+
};
|
|
12573
|
+
opts.requestExit = requestExit;
|
|
10434
12574
|
let instance;
|
|
10435
12575
|
try {
|
|
10436
12576
|
instance = render(
|
|
@@ -10445,6 +12585,7 @@ async function runTui(opts) {
|
|
|
10445
12585
|
model: opts.model,
|
|
10446
12586
|
banner: opts.banner ?? true,
|
|
10447
12587
|
queueStore: opts.queueStore,
|
|
12588
|
+
onQueueChange: opts.onQueueChange,
|
|
10448
12589
|
yolo: opts.yolo,
|
|
10449
12590
|
getYolo: opts.getYolo,
|
|
10450
12591
|
getAutonomy: opts.getAutonomy,
|
|
@@ -10480,12 +12621,24 @@ async function runTui(opts) {
|
|
|
10480
12621
|
getSettings: opts.getSettings,
|
|
10481
12622
|
saveSettings: opts.saveSettings,
|
|
10482
12623
|
predictNext: opts.predictNext,
|
|
12624
|
+
onSuggestionsParsed: opts.onSuggestionsParsed,
|
|
10483
12625
|
chime: opts.chime,
|
|
10484
12626
|
confirmExit: opts.confirmExit,
|
|
12627
|
+
mouse: mouseEnabled,
|
|
10485
12628
|
modeLabel: opts.modeLabel,
|
|
10486
12629
|
getModeLabel: opts.getModeLabel,
|
|
10487
12630
|
registerDebugStreamCallback: opts.registerDebugStreamCallback,
|
|
10488
|
-
restoreDebugStreamCallback: opts.restoreDebugStreamCallback
|
|
12631
|
+
restoreDebugStreamCallback: opts.restoreDebugStreamCallback,
|
|
12632
|
+
restoredMessages: opts.restoredMessages,
|
|
12633
|
+
restoredToolCalls: opts.restoredToolCalls,
|
|
12634
|
+
listSessions: opts.listSessions,
|
|
12635
|
+
onResumeSession: opts.onResumeSession,
|
|
12636
|
+
getProjectPickerItems: opts.getProjectPickerItems,
|
|
12637
|
+
onProjectSelect: opts.onProjectSelect,
|
|
12638
|
+
requestExit: opts.requestExit,
|
|
12639
|
+
getLiveSessions: opts.getLiveSessions,
|
|
12640
|
+
onSwitchToSession: opts.onSwitchToSession,
|
|
12641
|
+
initialAgentsMonitorOpen: opts.initialAgentsMonitorOpen
|
|
10489
12642
|
}),
|
|
10490
12643
|
{ exitOnCtrlC: false, stdin: inkStdin }
|
|
10491
12644
|
);
|
|
@@ -10516,6 +12669,190 @@ async function runTui(opts) {
|
|
|
10516
12669
|
});
|
|
10517
12670
|
}
|
|
10518
12671
|
|
|
10519
|
-
|
|
12672
|
+
// src/components/history/replay.ts
|
|
12673
|
+
function replaySessionEvents(events, startId) {
|
|
12674
|
+
const entries = [];
|
|
12675
|
+
let nextId = startId;
|
|
12676
|
+
const pendingTools = /* @__PURE__ */ new Map();
|
|
12677
|
+
const completedTools = /* @__PURE__ */ new Set();
|
|
12678
|
+
for (const ev of events) {
|
|
12679
|
+
const entry = eventToEntry(ev, pendingTools, completedTools);
|
|
12680
|
+
if (entry) {
|
|
12681
|
+
entries.push({ ...entry, id: nextId++ });
|
|
12682
|
+
}
|
|
12683
|
+
}
|
|
12684
|
+
for (const [, tu] of pendingTools) {
|
|
12685
|
+
entries.push({
|
|
12686
|
+
id: nextId++,
|
|
12687
|
+
kind: "tool",
|
|
12688
|
+
name: tu.name,
|
|
12689
|
+
durationMs: 0,
|
|
12690
|
+
ok: false,
|
|
12691
|
+
input: tu.input
|
|
12692
|
+
});
|
|
12693
|
+
}
|
|
12694
|
+
return entries;
|
|
12695
|
+
}
|
|
12696
|
+
function eventToEntry(ev, pendingTools, completedTools) {
|
|
12697
|
+
switch (ev.type) {
|
|
12698
|
+
case "user_input": {
|
|
12699
|
+
const text = typeof ev.content === "string" ? ev.content : Array.isArray(ev.content) ? ev.content.filter((b) => b.type === "text").map((b) => b.text).join("") : "";
|
|
12700
|
+
if (!text.trim()) return null;
|
|
12701
|
+
return { kind: "user", text };
|
|
12702
|
+
}
|
|
12703
|
+
case "llm_response": {
|
|
12704
|
+
const text = ev.content.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
12705
|
+
if (!text.trim()) return null;
|
|
12706
|
+
return { kind: "assistant", text };
|
|
12707
|
+
}
|
|
12708
|
+
case "tool_use": {
|
|
12709
|
+
pendingTools.set(ev.id, { name: ev.name, input: ev.input, ts: ev.ts });
|
|
12710
|
+
return null;
|
|
12711
|
+
}
|
|
12712
|
+
case "tool_result": {
|
|
12713
|
+
if (completedTools.has(ev.id)) {
|
|
12714
|
+
completedTools.delete(ev.id);
|
|
12715
|
+
return null;
|
|
12716
|
+
}
|
|
12717
|
+
const tu = pendingTools.get(ev.id);
|
|
12718
|
+
pendingTools.delete(ev.id);
|
|
12719
|
+
return {
|
|
12720
|
+
kind: "tool",
|
|
12721
|
+
name: tu?.name ?? ev.id,
|
|
12722
|
+
durationMs: 0,
|
|
12723
|
+
// duration not available from tool_result alone
|
|
12724
|
+
ok: !ev.isError,
|
|
12725
|
+
input: tu?.input,
|
|
12726
|
+
output: typeof ev.content === "string" ? ev.content.slice(0, 400) : void 0
|
|
12727
|
+
};
|
|
12728
|
+
}
|
|
12729
|
+
case "tool_call_start": {
|
|
12730
|
+
pendingTools.set(ev.id, { name: ev.name, input: ev.input, ts: ev.ts });
|
|
12731
|
+
return null;
|
|
12732
|
+
}
|
|
12733
|
+
case "tool_call_end": {
|
|
12734
|
+
const tu = pendingTools.get(ev.id);
|
|
12735
|
+
pendingTools.delete(ev.id);
|
|
12736
|
+
completedTools.add(ev.id);
|
|
12737
|
+
return {
|
|
12738
|
+
kind: "tool",
|
|
12739
|
+
name: tu?.name ?? ev.name,
|
|
12740
|
+
durationMs: ev.durationMs,
|
|
12741
|
+
ok: ev.ok ?? false,
|
|
12742
|
+
input: tu?.input,
|
|
12743
|
+
outputBytes: ev.outputBytes,
|
|
12744
|
+
outputTokens: ev.outputTokens,
|
|
12745
|
+
outputLines: ev.outputLines
|
|
12746
|
+
};
|
|
12747
|
+
}
|
|
12748
|
+
case "compaction": {
|
|
12749
|
+
const before = (ev.before / 1e3).toFixed(0);
|
|
12750
|
+
const after = (ev.after / 1e3).toFixed(0);
|
|
12751
|
+
const level = ev.level ? ` (${ev.level})` : "";
|
|
12752
|
+
const reductions = ev.reductions && ev.reductions.length > 0 ? ` [${ev.reductions.map((r) => `${r.phase}: \u2212${r.saved}`).join(", ")}]` : "";
|
|
12753
|
+
return {
|
|
12754
|
+
kind: "info",
|
|
12755
|
+
text: `\u27F2 context compacted${level}: ${before}K \u2192 ${after}K tokens${reductions}`
|
|
12756
|
+
};
|
|
12757
|
+
}
|
|
12758
|
+
case "error": {
|
|
12759
|
+
return {
|
|
12760
|
+
kind: "error",
|
|
12761
|
+
text: ev.phase ? `[${ev.phase}] ${ev.message}` : ev.message
|
|
12762
|
+
};
|
|
12763
|
+
}
|
|
12764
|
+
case "provider_retry": {
|
|
12765
|
+
const secs = (ev.delayMs / 1e3).toFixed(ev.delayMs >= 1e3 ? 1 : 2);
|
|
12766
|
+
return {
|
|
12767
|
+
kind: "warn",
|
|
12768
|
+
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}`
|
|
12769
|
+
};
|
|
12770
|
+
}
|
|
12771
|
+
case "provider_error": {
|
|
12772
|
+
return {
|
|
12773
|
+
kind: "error",
|
|
12774
|
+
text: ev.status ? `provider error (HTTP ${ev.status}, ${ev.retryable ? "retryable" : "fatal"}): ${ev.description}` : `provider error (${ev.retryable ? "retryable" : "fatal"}): ${ev.description}`
|
|
12775
|
+
};
|
|
12776
|
+
}
|
|
12777
|
+
case "checkpoint": {
|
|
12778
|
+
return {
|
|
12779
|
+
kind: "info",
|
|
12780
|
+
text: `\u2713 checkpoint #${ev.promptIndex}: "${ev.promptPreview.slice(0, 60)}"`
|
|
12781
|
+
};
|
|
12782
|
+
}
|
|
12783
|
+
case "agent_spawned": {
|
|
12784
|
+
return {
|
|
12785
|
+
kind: "subagent",
|
|
12786
|
+
agentLabel: ev.agentId.slice(0, 8),
|
|
12787
|
+
agentColor: "magenta",
|
|
12788
|
+
icon: "\u26A1",
|
|
12789
|
+
text: `spawned as ${ev.role}`
|
|
12790
|
+
};
|
|
12791
|
+
}
|
|
12792
|
+
case "agent_stopped": {
|
|
12793
|
+
return {
|
|
12794
|
+
kind: "subagent",
|
|
12795
|
+
agentLabel: ev.agentId.slice(0, 8),
|
|
12796
|
+
agentColor: "gray",
|
|
12797
|
+
icon: "\u2298",
|
|
12798
|
+
text: "stopped"
|
|
12799
|
+
};
|
|
12800
|
+
}
|
|
12801
|
+
case "agent_error": {
|
|
12802
|
+
return {
|
|
12803
|
+
kind: "subagent",
|
|
12804
|
+
agentLabel: ev.agentId.slice(0, 8),
|
|
12805
|
+
agentColor: "red",
|
|
12806
|
+
icon: "\u2717",
|
|
12807
|
+
text: `error: ${ev.error.slice(0, 80)}`
|
|
12808
|
+
};
|
|
12809
|
+
}
|
|
12810
|
+
case "mode_changed": {
|
|
12811
|
+
return {
|
|
12812
|
+
kind: "info",
|
|
12813
|
+
text: `mode: ${ev.from} \u2192 ${ev.to}`
|
|
12814
|
+
};
|
|
12815
|
+
}
|
|
12816
|
+
case "skill_activated": {
|
|
12817
|
+
return {
|
|
12818
|
+
kind: "info",
|
|
12819
|
+
text: `skill activated: ${ev.skillName}`
|
|
12820
|
+
};
|
|
12821
|
+
}
|
|
12822
|
+
case "skill_deactivated": {
|
|
12823
|
+
return {
|
|
12824
|
+
kind: "info",
|
|
12825
|
+
text: `skill deactivated: ${ev.skillName}`
|
|
12826
|
+
};
|
|
12827
|
+
}
|
|
12828
|
+
case "message_truncated": {
|
|
12829
|
+
return {
|
|
12830
|
+
kind: "warn",
|
|
12831
|
+
text: ev.after < ev.before ? `message truncated: ${ev.before} \u2192 ${ev.after} tokens` : `message truncated at ${ev.after} tokens`
|
|
12832
|
+
};
|
|
12833
|
+
}
|
|
12834
|
+
// Skipped — internal markers not relevant for display
|
|
12835
|
+
case "session_start":
|
|
12836
|
+
case "session_resumed":
|
|
12837
|
+
case "session_end":
|
|
12838
|
+
case "in_flight_start":
|
|
12839
|
+
case "in_flight_end":
|
|
12840
|
+
case "llm_request":
|
|
12841
|
+
case "tool_progress":
|
|
12842
|
+
case "rewound":
|
|
12843
|
+
case "file_snapshot":
|
|
12844
|
+
case "task_created":
|
|
12845
|
+
case "task_updated":
|
|
12846
|
+
case "task_completed":
|
|
12847
|
+
case "task_failed":
|
|
12848
|
+
case "spec_parsed":
|
|
12849
|
+
case "spec_analyzed":
|
|
12850
|
+
return null;
|
|
12851
|
+
default:
|
|
12852
|
+
return null;
|
|
12853
|
+
}
|
|
12854
|
+
}
|
|
12855
|
+
|
|
12856
|
+
export { parseInline, parseNextSteps, replaySessionEvents, runTui };
|
|
10520
12857
|
//# sourceMappingURL=index.js.map
|
|
10521
12858
|
//# sourceMappingURL=index.js.map
|