@wrongstack/tui 0.41.0 → 0.51.3
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 +51 -26
- package/dist/index.js +294 -4
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,54 @@ interface ProviderOption {
|
|
|
13
13
|
modelsLabel?: string;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
type SerialAutonomyStage = {
|
|
17
|
+
phase: 'idle';
|
|
18
|
+
} | {
|
|
19
|
+
phase: 'decide';
|
|
20
|
+
reason: string;
|
|
21
|
+
} | {
|
|
22
|
+
phase: 'execute';
|
|
23
|
+
task: string;
|
|
24
|
+
} | {
|
|
25
|
+
phase: 'reflect';
|
|
26
|
+
status: 'success' | 'failure' | 'aborted' | 'skipped';
|
|
27
|
+
note?: string;
|
|
28
|
+
} | {
|
|
29
|
+
phase: 'sleep';
|
|
30
|
+
ms: number;
|
|
31
|
+
} | {
|
|
32
|
+
phase: 'paused';
|
|
33
|
+
} | {
|
|
34
|
+
phase: 'stopped';
|
|
35
|
+
} | {
|
|
36
|
+
phase: 'error';
|
|
37
|
+
message: string;
|
|
38
|
+
};
|
|
39
|
+
type ParallelAutonomyStage = {
|
|
40
|
+
phase: 'idle';
|
|
41
|
+
} | {
|
|
42
|
+
phase: 'decompose';
|
|
43
|
+
} | {
|
|
44
|
+
phase: 'fanout';
|
|
45
|
+
slots: number;
|
|
46
|
+
} | {
|
|
47
|
+
phase: 'await';
|
|
48
|
+
taskIds: string[];
|
|
49
|
+
} | {
|
|
50
|
+
phase: 'aggregate';
|
|
51
|
+
successCount: number;
|
|
52
|
+
total: number;
|
|
53
|
+
goalComplete: boolean;
|
|
54
|
+
} | {
|
|
55
|
+
phase: 'sleep';
|
|
56
|
+
ms: number;
|
|
57
|
+
} | {
|
|
58
|
+
phase: 'stopped';
|
|
59
|
+
} | {
|
|
60
|
+
phase: 'error';
|
|
61
|
+
message: string;
|
|
62
|
+
};
|
|
63
|
+
type AutonomyStage = SerialAutonomyStage | ParallelAutonomyStage;
|
|
16
64
|
interface RunTuiOptions {
|
|
17
65
|
agent: Agent;
|
|
18
66
|
slashRegistry: SlashCommandRegistry;
|
|
@@ -51,33 +99,10 @@ interface RunTuiOptions {
|
|
|
51
99
|
*/
|
|
52
100
|
subscribeEternalIteration?: (fn: (entry: _wrongstack_core.JournalEntry) => void) => () => void;
|
|
53
101
|
/**
|
|
54
|
-
* Subscribe to per-iteration stage transitions from the
|
|
55
|
-
* TUI uses this to render live status
|
|
56
|
-
* sleep/paused/stopped) in the status bar.
|
|
102
|
+
* Subscribe to per-iteration stage transitions from the autonomy engines.
|
|
103
|
+
* TUI uses this to render live status in the status bar.
|
|
57
104
|
*/
|
|
58
|
-
subscribeEternalStage?: (fn: (stage:
|
|
59
|
-
phase: 'idle';
|
|
60
|
-
} | {
|
|
61
|
-
phase: 'decide';
|
|
62
|
-
reason: string;
|
|
63
|
-
} | {
|
|
64
|
-
phase: 'execute';
|
|
65
|
-
task: string;
|
|
66
|
-
} | {
|
|
67
|
-
phase: 'reflect';
|
|
68
|
-
status: 'success' | 'failure' | 'aborted' | 'skipped';
|
|
69
|
-
note?: string;
|
|
70
|
-
} | {
|
|
71
|
-
phase: 'sleep';
|
|
72
|
-
ms: number;
|
|
73
|
-
} | {
|
|
74
|
-
phase: 'paused';
|
|
75
|
-
} | {
|
|
76
|
-
phase: 'stopped';
|
|
77
|
-
} | {
|
|
78
|
-
phase: 'error';
|
|
79
|
-
message: string;
|
|
80
|
-
}) => void) => () => void;
|
|
105
|
+
subscribeEternalStage?: (fn: (stage: AutonomyStage) => void) => () => void;
|
|
81
106
|
/** Renders in the startup banner. Read from the CLI's package.json. */
|
|
82
107
|
appVersion?: string;
|
|
83
108
|
/** Provider id for the startup banner ("openai", "anthropic", ...). */
|
package/dist/index.js
CHANGED
|
@@ -54,6 +54,7 @@ function StatusBar({
|
|
|
54
54
|
git,
|
|
55
55
|
subagentCount = 0,
|
|
56
56
|
context,
|
|
57
|
+
brain,
|
|
57
58
|
projectName,
|
|
58
59
|
processCount,
|
|
59
60
|
hiddenItems,
|
|
@@ -79,7 +80,8 @@ function StatusBar({
|
|
|
79
80
|
const { label: stateLabel, color: stateColor } = stateChip(state, fleet?.running ?? 0);
|
|
80
81
|
const hasSecondLine = yolo || autonomy && autonomy !== "off" || elapsedMs !== void 0 || git !== null && git !== void 0 || projectName !== void 0 && projectName.length > 0 || goalSummary !== null && goalSummary !== void 0;
|
|
81
82
|
const fleetHasActivity = fleet && (fleet.running > 0 || fleet.idle > 0 || fleet.pending > 0 || fleet.completed > 0) || subagentCount > 0;
|
|
82
|
-
const
|
|
83
|
+
const hasBrainActivity = !!brain && brain.state !== "idle";
|
|
84
|
+
const hasThirdLine = todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) || fleetHasActivity || hasBrainActivity;
|
|
83
85
|
return /* @__PURE__ */ jsxs(
|
|
84
86
|
Box,
|
|
85
87
|
{
|
|
@@ -316,6 +318,10 @@ function StatusBar({
|
|
|
316
318
|
" agent",
|
|
317
319
|
subagentCount === 1 ? "" : "s"
|
|
318
320
|
] })
|
|
321
|
+
] }) : null,
|
|
322
|
+
hasBrainActivity && brain ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
323
|
+
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) || fleetHasActivity ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
324
|
+
/* @__PURE__ */ jsx(BrainChip, { brain })
|
|
319
325
|
] }) : null
|
|
320
326
|
] }) : null,
|
|
321
327
|
fleetAgents && fleetAgents.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => (
|
|
@@ -348,6 +354,18 @@ function StatusBar({
|
|
|
348
354
|
}
|
|
349
355
|
);
|
|
350
356
|
}
|
|
357
|
+
function BrainChip({ brain }) {
|
|
358
|
+
const color = brain.state === "denied" ? "red" : brain.state === "ask_human" ? "yellow" : brain.state === "deciding" ? "magenta" : "cyan";
|
|
359
|
+
const label = brain.state === "deciding" ? "deciding" : brain.state === "ask_human" ? "human" : brain.state;
|
|
360
|
+
const scope = brain.source ? ` ${brain.source}` : "";
|
|
361
|
+
const summary = brain.summary ? ` \xB7 ${brain.summary.slice(0, 40)}` : "";
|
|
362
|
+
return /* @__PURE__ */ jsxs(Text, { color, children: [
|
|
363
|
+
"\u{1F9E0} ",
|
|
364
|
+
label,
|
|
365
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: scope }),
|
|
366
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: summary })
|
|
367
|
+
] });
|
|
368
|
+
}
|
|
351
369
|
function EternalStageChip({
|
|
352
370
|
stage
|
|
353
371
|
}) {
|
|
@@ -376,6 +394,25 @@ function EternalStageChip({
|
|
|
376
394
|
]
|
|
377
395
|
}
|
|
378
396
|
);
|
|
397
|
+
case "decompose":
|
|
398
|
+
return /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u2B07 decompose" });
|
|
399
|
+
case "fanout":
|
|
400
|
+
return /* @__PURE__ */ jsxs(Text, { color: "magenta", children: [
|
|
401
|
+
"\u21C4 fanout: ",
|
|
402
|
+
stage.slots
|
|
403
|
+
] });
|
|
404
|
+
case "await":
|
|
405
|
+
return /* @__PURE__ */ jsxs(Text, { color: "magenta", children: [
|
|
406
|
+
"\u23F3 await: ",
|
|
407
|
+
stage.taskIds.length
|
|
408
|
+
] });
|
|
409
|
+
case "aggregate":
|
|
410
|
+
return /* @__PURE__ */ jsxs(Text, { color: stage.goalComplete ? "green" : "magenta", children: [
|
|
411
|
+
"\u21A9 aggregate: ",
|
|
412
|
+
stage.successCount,
|
|
413
|
+
"/",
|
|
414
|
+
stage.total
|
|
415
|
+
] });
|
|
379
416
|
case "sleep":
|
|
380
417
|
return /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
381
418
|
"\u{1F4A4} sleep ",
|
|
@@ -734,6 +771,9 @@ function fmtTokens2(n) {
|
|
|
734
771
|
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
735
772
|
return `${(n / 1e6).toFixed(1)}M`;
|
|
736
773
|
}
|
|
774
|
+
function fmtExactTokens(n) {
|
|
775
|
+
return `${Math.round(n).toLocaleString("en-US")} tok`;
|
|
776
|
+
}
|
|
737
777
|
function snippet(s2, max = 72) {
|
|
738
778
|
const oneLine2 = s2.replace(/\s+/g, " ").trim();
|
|
739
779
|
if (oneLine2.length <= max) return oneLine2;
|
|
@@ -831,6 +871,10 @@ function AgentsMonitor({
|
|
|
831
871
|
/* @__PURE__ */ jsx(Text, { color: s2.color, bold: true, children: s2.icon }),
|
|
832
872
|
/* @__PURE__ */ jsx(Text, { bold: true, children: e.name }),
|
|
833
873
|
fmtModelLabel(e.provider, e.model) ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtModelLabel(e.provider, e.model) }) : null,
|
|
874
|
+
e.ctxMaxTokens && e.ctxMaxTokens > 0 ? /* @__PURE__ */ jsxs(Text, { color: "blue", children: [
|
|
875
|
+
"ctx max ",
|
|
876
|
+
fmtExactTokens(e.ctxMaxTokens)
|
|
877
|
+
] }) : null,
|
|
834
878
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
835
879
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: elapsed }),
|
|
836
880
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
@@ -952,6 +996,92 @@ function AutonomyPicker({
|
|
|
952
996
|
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
953
997
|
] });
|
|
954
998
|
}
|
|
999
|
+
function riskColor(risk) {
|
|
1000
|
+
switch (risk) {
|
|
1001
|
+
case "low":
|
|
1002
|
+
return "green";
|
|
1003
|
+
case "medium":
|
|
1004
|
+
return "cyan";
|
|
1005
|
+
case "high":
|
|
1006
|
+
return "yellow";
|
|
1007
|
+
case "critical":
|
|
1008
|
+
return "red";
|
|
1009
|
+
default:
|
|
1010
|
+
return "white";
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
function optionKey(index) {
|
|
1014
|
+
return String.fromCharCode("A".charCodeAt(0) + index);
|
|
1015
|
+
}
|
|
1016
|
+
function contextLines(context) {
|
|
1017
|
+
if (!context?.trim()) return [];
|
|
1018
|
+
return context.trim().split("\n").slice(0, 5);
|
|
1019
|
+
}
|
|
1020
|
+
function BrainDecisionPrompt({
|
|
1021
|
+
requestId,
|
|
1022
|
+
source,
|
|
1023
|
+
risk,
|
|
1024
|
+
question,
|
|
1025
|
+
context,
|
|
1026
|
+
options = [],
|
|
1027
|
+
onAnswer
|
|
1028
|
+
}) {
|
|
1029
|
+
const color = riskColor(risk);
|
|
1030
|
+
const ctx = contextLines(context);
|
|
1031
|
+
useInput((input, key) => {
|
|
1032
|
+
if (!onAnswer) return;
|
|
1033
|
+
if (key.escape || input.toLowerCase() === "d") {
|
|
1034
|
+
onAnswer({ id: requestId, deny: true, text: "Denied by human from TUI." });
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
const ch = input.toLowerCase();
|
|
1038
|
+
const index = ch >= "a" && ch <= "z" ? ch.charCodeAt(0) - "a".charCodeAt(0) : Number(ch) - 1;
|
|
1039
|
+
const option = Number.isInteger(index) && index >= 0 ? options[index] : void 0;
|
|
1040
|
+
if (option) onAnswer({ id: requestId, optionId: option.id, text: option.label });
|
|
1041
|
+
});
|
|
1042
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, children: [
|
|
1043
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsx(Text, { bold: true, color: "magenta", children: "\u{1F9E0} BRAIN REQUIRES HUMAN DECISION" }) }),
|
|
1044
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1045
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Source:" }),
|
|
1046
|
+
/* @__PURE__ */ jsx(Text, { children: source }),
|
|
1047
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Risk:" }),
|
|
1048
|
+
/* @__PURE__ */ jsx(Text, { color, children: risk })
|
|
1049
|
+
] }),
|
|
1050
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: question }),
|
|
1051
|
+
ctx.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
1052
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Context:" }),
|
|
1053
|
+
ctx.map((line, index) => (
|
|
1054
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: context lines are static for this prompt render
|
|
1055
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: line }, index)
|
|
1056
|
+
))
|
|
1057
|
+
] }) : null,
|
|
1058
|
+
options.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
1059
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Options:" }),
|
|
1060
|
+
options.slice(0, 6).map((option, index) => {
|
|
1061
|
+
const key = optionKey(index);
|
|
1062
|
+
const optionColor = riskColor(String(option.risk ?? risk));
|
|
1063
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
1064
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1065
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, color: "yellow", children: [
|
|
1066
|
+
"[",
|
|
1067
|
+
key,
|
|
1068
|
+
"]"
|
|
1069
|
+
] }),
|
|
1070
|
+
" ",
|
|
1071
|
+
/* @__PURE__ */ jsx(Text, { color: optionColor, children: option.label }),
|
|
1072
|
+
option.recommended ? /* @__PURE__ */ jsx(Text, { color: "green", children: " recommended" }) : null
|
|
1073
|
+
] }),
|
|
1074
|
+
option.consequence ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1075
|
+
" ",
|
|
1076
|
+
option.consequence
|
|
1077
|
+
] }) : null
|
|
1078
|
+
] }, option.id);
|
|
1079
|
+
})
|
|
1080
|
+
] }) : null,
|
|
1081
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
|
|
1082
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press A/B/C or 1/2/3 to answer; Esc or D denies with the safe default." })
|
|
1083
|
+
] });
|
|
1084
|
+
}
|
|
955
1085
|
function CheckpointTimeline({
|
|
956
1086
|
checkpoints,
|
|
957
1087
|
selected,
|
|
@@ -2318,6 +2448,30 @@ function DiffBlock({ rows, hidden }) {
|
|
|
2318
2448
|
hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: `${blank} \u2026 ${hidden} more line${hidden === 1 ? "" : "s"}` }) : null
|
|
2319
2449
|
] });
|
|
2320
2450
|
}
|
|
2451
|
+
function brainStatusStyle(status) {
|
|
2452
|
+
switch (status) {
|
|
2453
|
+
case "thinking":
|
|
2454
|
+
return { icon: "\u2026", color: "magenta" };
|
|
2455
|
+
case "answered":
|
|
2456
|
+
return { icon: "\u2696", color: "cyan" };
|
|
2457
|
+
case "ask_human":
|
|
2458
|
+
return { icon: "?", color: "yellow" };
|
|
2459
|
+
case "denied":
|
|
2460
|
+
return { icon: "\xD7", color: "red" };
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
function brainRiskColor(risk) {
|
|
2464
|
+
switch (risk) {
|
|
2465
|
+
case "low":
|
|
2466
|
+
return "green";
|
|
2467
|
+
case "medium":
|
|
2468
|
+
return "cyan";
|
|
2469
|
+
case "high":
|
|
2470
|
+
return "yellow";
|
|
2471
|
+
case "critical":
|
|
2472
|
+
return "red";
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2321
2475
|
var Entry = React4.memo(function Entry2({
|
|
2322
2476
|
entry,
|
|
2323
2477
|
termWidth
|
|
@@ -2450,6 +2604,38 @@ var Entry = React4.memo(function Entry2({
|
|
|
2450
2604
|
);
|
|
2451
2605
|
case "turn-summary":
|
|
2452
2606
|
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: entry.text });
|
|
2607
|
+
case "brain": {
|
|
2608
|
+
const statusStyle = brainStatusStyle(entry.status);
|
|
2609
|
+
const riskColor2 = brainRiskColor(entry.risk);
|
|
2610
|
+
return /* @__PURE__ */ jsxs(
|
|
2611
|
+
Box,
|
|
2612
|
+
{
|
|
2613
|
+
flexDirection: "column",
|
|
2614
|
+
marginY: 1,
|
|
2615
|
+
borderStyle: "single",
|
|
2616
|
+
borderTop: false,
|
|
2617
|
+
borderRight: false,
|
|
2618
|
+
borderBottom: false,
|
|
2619
|
+
borderColor: "magenta",
|
|
2620
|
+
paddingLeft: 1,
|
|
2621
|
+
children: [
|
|
2622
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
2623
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "magenta", children: "BRAIN" }),
|
|
2624
|
+
/* @__PURE__ */ jsx(Text, { color: statusStyle.color, children: statusStyle.icon }),
|
|
2625
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: entry.source }),
|
|
2626
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
2627
|
+
/* @__PURE__ */ jsx(Text, { color: riskColor2, children: entry.risk })
|
|
2628
|
+
] }),
|
|
2629
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: entry.question }),
|
|
2630
|
+
entry.decision ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
2631
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Decision: " }),
|
|
2632
|
+
/* @__PURE__ */ jsx(Text, { color: statusStyle.color, children: entry.decision })
|
|
2633
|
+
] }) : null,
|
|
2634
|
+
entry.rationale ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: entry.rationale }) : null
|
|
2635
|
+
]
|
|
2636
|
+
}
|
|
2637
|
+
);
|
|
2638
|
+
}
|
|
2453
2639
|
case "confirm":
|
|
2454
2640
|
return /* @__PURE__ */ jsxs(
|
|
2455
2641
|
Box,
|
|
@@ -4574,6 +4760,21 @@ function reducer(state, action) {
|
|
|
4574
4760
|
return { ...state, interrupts: 0 };
|
|
4575
4761
|
case "hint":
|
|
4576
4762
|
return { ...state, hint: action.text };
|
|
4763
|
+
case "brainStatus":
|
|
4764
|
+
return {
|
|
4765
|
+
...state,
|
|
4766
|
+
brain: {
|
|
4767
|
+
state: action.state,
|
|
4768
|
+
source: action.source,
|
|
4769
|
+
risk: action.risk,
|
|
4770
|
+
summary: action.summary,
|
|
4771
|
+
updatedAt: Date.now()
|
|
4772
|
+
}
|
|
4773
|
+
};
|
|
4774
|
+
case "brainPromptSet":
|
|
4775
|
+
return { ...state, brainPrompt: action.prompt };
|
|
4776
|
+
case "brainPromptClear":
|
|
4777
|
+
return { ...state, brainPrompt: null };
|
|
4577
4778
|
case "pickerOpen":
|
|
4578
4779
|
return {
|
|
4579
4780
|
...state,
|
|
@@ -5534,6 +5735,7 @@ function App({
|
|
|
5534
5735
|
const { exit } = useApp();
|
|
5535
5736
|
const [liveModel, setLiveModel] = useState(model);
|
|
5536
5737
|
const [liveProvider, setLiveProvider] = useState(provider ?? "agent");
|
|
5738
|
+
const [activeMaxContext, setActiveMaxContext] = useState(effectiveMaxContext);
|
|
5537
5739
|
const [yoloLive, setYoloLive] = useState(yolo);
|
|
5538
5740
|
const [autonomyLive, setAutonomyLive] = useState(getAutonomy?.() ?? "off");
|
|
5539
5741
|
const [hiddenItems, setHiddenItems] = useState(statuslineHiddenItems);
|
|
@@ -5602,6 +5804,8 @@ function App({
|
|
|
5602
5804
|
steeringPending: false,
|
|
5603
5805
|
steerSnapshot: null,
|
|
5604
5806
|
hint: "",
|
|
5807
|
+
brain: { state: "idle" },
|
|
5808
|
+
brainPrompt: null,
|
|
5605
5809
|
nextId: 1,
|
|
5606
5810
|
picker: { open: false, query: "", matches: [], selected: 0 },
|
|
5607
5811
|
slashPicker: { open: false, query: "", matches: [], selected: 0 },
|
|
@@ -5943,7 +6147,7 @@ function App({
|
|
|
5943
6147
|
clearInterval(t);
|
|
5944
6148
|
};
|
|
5945
6149
|
}, [agent.ctx.cwd]);
|
|
5946
|
-
const maxContext =
|
|
6150
|
+
const maxContext = activeMaxContext ?? agent.ctx.provider.capabilities.maxContext;
|
|
5947
6151
|
const currentContextTokens = (tokenCounter?.currentRequestTokens()?.input ?? 0) + (tokenCounter?.currentRequestTokens()?.cacheRead ?? 0);
|
|
5948
6152
|
const contextWindow = useMemo(() => {
|
|
5949
6153
|
void state.contextChipVersion;
|
|
@@ -5989,10 +6193,10 @@ function App({
|
|
|
5989
6193
|
currentTool: state.leader.currentTool,
|
|
5990
6194
|
ctxPct: state.leader.ctxPct,
|
|
5991
6195
|
ctxTokens: state.leader.ctxTokens,
|
|
5992
|
-
ctxMaxTokens: state.leader.ctxMaxTokens
|
|
6196
|
+
ctxMaxTokens: state.leader.ctxMaxTokens ?? effectiveMaxContext
|
|
5993
6197
|
};
|
|
5994
6198
|
return { leader: leaderEntry, ...state.fleet };
|
|
5995
|
-
}, [state.fleet, state.leader, state.status, provider, model]);
|
|
6199
|
+
}, [state.fleet, state.leader, state.status, provider, model, effectiveMaxContext]);
|
|
5996
6200
|
const STREAM_COLORS = ["cyan", "magenta", "yellow", "green", "blue"];
|
|
5997
6201
|
const labelsRef = useRef(/* @__PURE__ */ new Map());
|
|
5998
6202
|
const labelFor = (id, name) => {
|
|
@@ -6769,6 +6973,7 @@ function App({
|
|
|
6769
6973
|
});
|
|
6770
6974
|
});
|
|
6771
6975
|
const offLeaderCtxPct = events.on("ctx.pct", (e) => {
|
|
6976
|
+
setActiveMaxContext(e.maxContext);
|
|
6772
6977
|
dispatch({
|
|
6773
6978
|
type: "leaderCtxPct",
|
|
6774
6979
|
load: e.load,
|
|
@@ -6776,6 +6981,9 @@ function App({
|
|
|
6776
6981
|
maxContext: e.maxContext
|
|
6777
6982
|
});
|
|
6778
6983
|
});
|
|
6984
|
+
const offLeaderMaxContext = events.on("ctx.max_context", (e) => {
|
|
6985
|
+
if (e.maxContext > 0) setActiveMaxContext(e.maxContext);
|
|
6986
|
+
});
|
|
6779
6987
|
const offTool = events.on("subagent.tool_executed", (e) => {
|
|
6780
6988
|
dispatch({
|
|
6781
6989
|
type: "fleetTool",
|
|
@@ -6796,6 +7004,7 @@ function App({
|
|
|
6796
7004
|
offIterationSummary();
|
|
6797
7005
|
offCtxPct();
|
|
6798
7006
|
offLeaderCtxPct();
|
|
7007
|
+
offLeaderMaxContext();
|
|
6799
7008
|
offTool();
|
|
6800
7009
|
};
|
|
6801
7010
|
}, [events, director]);
|
|
@@ -6823,6 +7032,71 @@ function App({
|
|
|
6823
7032
|
offRewound();
|
|
6824
7033
|
};
|
|
6825
7034
|
}, [events, onClearHistory]);
|
|
7035
|
+
useEffect(() => {
|
|
7036
|
+
const requestSummary = (request) => `${request.source}: ${request.question}`.slice(0, 80);
|
|
7037
|
+
const addBrainEntry = (status, payload) => {
|
|
7038
|
+
const p = payload;
|
|
7039
|
+
const decision = p.decision.optionId ?? p.decision.text ?? p.decision.reason ?? p.decision.prompt ?? p.decision.type;
|
|
7040
|
+
dispatch({
|
|
7041
|
+
type: "brainStatus",
|
|
7042
|
+
state: status,
|
|
7043
|
+
source: p.request.source,
|
|
7044
|
+
risk: p.request.risk,
|
|
7045
|
+
summary: decision
|
|
7046
|
+
});
|
|
7047
|
+
if (status === "ask_human") {
|
|
7048
|
+
dispatch({
|
|
7049
|
+
type: "brainPromptSet",
|
|
7050
|
+
prompt: {
|
|
7051
|
+
requestId: p.request.id,
|
|
7052
|
+
source: p.request.source,
|
|
7053
|
+
risk: p.request.risk,
|
|
7054
|
+
question: p.request.question,
|
|
7055
|
+
context: p.request.context,
|
|
7056
|
+
options: p.request.options
|
|
7057
|
+
}
|
|
7058
|
+
});
|
|
7059
|
+
} else {
|
|
7060
|
+
dispatch({ type: "brainPromptClear" });
|
|
7061
|
+
}
|
|
7062
|
+
dispatch({
|
|
7063
|
+
type: "addEntry",
|
|
7064
|
+
entry: {
|
|
7065
|
+
kind: "brain",
|
|
7066
|
+
status,
|
|
7067
|
+
source: p.request.source,
|
|
7068
|
+
risk: p.request.risk,
|
|
7069
|
+
question: p.request.question,
|
|
7070
|
+
decision,
|
|
7071
|
+
rationale: p.decision.rationale
|
|
7072
|
+
}
|
|
7073
|
+
});
|
|
7074
|
+
};
|
|
7075
|
+
const offRequested = events.on("brain.decision_requested", ({ request }) => {
|
|
7076
|
+
dispatch({
|
|
7077
|
+
type: "brainStatus",
|
|
7078
|
+
state: "deciding",
|
|
7079
|
+
source: request.source,
|
|
7080
|
+
risk: request.risk,
|
|
7081
|
+
summary: requestSummary(request)
|
|
7082
|
+
});
|
|
7083
|
+
});
|
|
7084
|
+
const offAnswered = events.on("brain.decision_answered", (payload) => {
|
|
7085
|
+
addBrainEntry("answered", payload);
|
|
7086
|
+
});
|
|
7087
|
+
const offAskHuman = events.on("brain.decision_ask_human", (payload) => {
|
|
7088
|
+
addBrainEntry("ask_human", payload);
|
|
7089
|
+
});
|
|
7090
|
+
const offDenied = events.on("brain.decision_denied", (payload) => {
|
|
7091
|
+
addBrainEntry("denied", payload);
|
|
7092
|
+
});
|
|
7093
|
+
return () => {
|
|
7094
|
+
offRequested();
|
|
7095
|
+
offAnswered();
|
|
7096
|
+
offAskHuman();
|
|
7097
|
+
offDenied();
|
|
7098
|
+
};
|
|
7099
|
+
}, [events]);
|
|
6826
7100
|
useEffect(() => {
|
|
6827
7101
|
if (!subscribeAutoPhase) return;
|
|
6828
7102
|
const handler = (event, payload) => {
|
|
@@ -7613,6 +7887,7 @@ function App({
|
|
|
7613
7887
|
}
|
|
7614
7888
|
setLiveProvider(providerId);
|
|
7615
7889
|
setLiveModel(modelId);
|
|
7890
|
+
setActiveMaxContext(agent.ctx.provider.capabilities.maxContext);
|
|
7616
7891
|
dispatch({
|
|
7617
7892
|
type: "addEntry",
|
|
7618
7893
|
entry: { kind: "info", text: `Switched to ${providerId} / ${modelId}.` }
|
|
@@ -8213,6 +8488,10 @@ function App({
|
|
|
8213
8488
|
if (ctxModel && ctxModel !== liveModel) setLiveModel(ctxModel);
|
|
8214
8489
|
const ctxProviderId = agent.ctx.provider?.id;
|
|
8215
8490
|
if (ctxProviderId && ctxProviderId !== liveProvider) setLiveProvider(ctxProviderId);
|
|
8491
|
+
const ctxMaxContext = agent.ctx.provider.capabilities.maxContext;
|
|
8492
|
+
if (ctxMaxContext > 0 && ctxMaxContext !== activeMaxContext) {
|
|
8493
|
+
setActiveMaxContext(ctxMaxContext);
|
|
8494
|
+
}
|
|
8216
8495
|
if (getYolo) {
|
|
8217
8496
|
const currentYolo = getYolo();
|
|
8218
8497
|
if (currentYolo !== yoloLive) setYoloLive(currentYolo);
|
|
@@ -8437,6 +8716,16 @@ User message:
|
|
|
8437
8716
|
onClose: () => dispatch({ type: "rewindOverlayClose" })
|
|
8438
8717
|
}
|
|
8439
8718
|
) : null,
|
|
8719
|
+
state.brainPrompt ? /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginY: 1, flexShrink: 0, children: /* @__PURE__ */ jsx(
|
|
8720
|
+
BrainDecisionPrompt,
|
|
8721
|
+
{
|
|
8722
|
+
...state.brainPrompt,
|
|
8723
|
+
onAnswer: (answer) => {
|
|
8724
|
+
events.emit("brain.human_answered", { ...answer, at: Date.now() });
|
|
8725
|
+
dispatch({ type: "brainPromptClear" });
|
|
8726
|
+
}
|
|
8727
|
+
}
|
|
8728
|
+
) }) : null,
|
|
8440
8729
|
state.confirmQueue.length > 0 && (() => {
|
|
8441
8730
|
const head = state.confirmQueue[0];
|
|
8442
8731
|
let resolved = false;
|
|
@@ -8474,6 +8763,7 @@ User message:
|
|
|
8474
8763
|
fleet: fleetCounts,
|
|
8475
8764
|
git: gitInfo,
|
|
8476
8765
|
context: contextWindow,
|
|
8766
|
+
brain: state.brain,
|
|
8477
8767
|
projectName,
|
|
8478
8768
|
subagentCount: Object.keys(state.fleet).length,
|
|
8479
8769
|
processCount: getProcessRegistry().activeCount,
|