@wrongstack/tui 0.9.19 → 0.9.20
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.js +336 -58
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -44,7 +44,7 @@ function ConfirmPrompt({
|
|
|
44
44
|
React2.useEffect(() => {
|
|
45
45
|
process.stdout.write("\x07");
|
|
46
46
|
}, []);
|
|
47
|
-
useInput((input2,
|
|
47
|
+
useInput((input2, _key) => {
|
|
48
48
|
if (!input2 || input2 === "\r" || input2 === "\n") return;
|
|
49
49
|
const ch = input2.toLowerCase();
|
|
50
50
|
if (ch === "y") {
|
|
@@ -159,38 +159,52 @@ function FilePicker({ query, matches, selected }) {
|
|
|
159
159
|
] }, m))
|
|
160
160
|
] });
|
|
161
161
|
}
|
|
162
|
-
function highlight(path3,
|
|
162
|
+
function highlight(path3, _query) {
|
|
163
163
|
return path3;
|
|
164
164
|
}
|
|
165
|
-
function FleetPanel({ entries, totalCost,
|
|
165
|
+
function FleetPanel({ entries, totalCost, collabSession }) {
|
|
166
166
|
const list = Object.values(entries);
|
|
167
|
-
if (list.length === 0) return null;
|
|
168
|
-
const
|
|
167
|
+
if (list.length === 0 && !collabSession) return null;
|
|
168
|
+
const leader = list.find((e) => e.id === "leader");
|
|
169
|
+
const subagents = list.filter((e) => e.id !== "leader");
|
|
170
|
+
const running = subagents.filter((e) => e.status === "running");
|
|
169
171
|
const runningCount = running.length;
|
|
170
|
-
const
|
|
171
|
-
const
|
|
172
|
+
const hasCollab = !!collabSession;
|
|
173
|
+
const costLabel = totalCost > 0 ? ` \xB7 ${totalCost.toFixed(3)}` : "";
|
|
174
|
+
const collabLabel = hasCollab && collabSession.sessionId ? ` \xB7 collab(${collabSession.bugCount}b/${collabSession.planCount}p/${collabSession.evalCount}e)` : "";
|
|
175
|
+
const summaryLine = runningCount > 0 ? `${runningCount} running${costLabel}${collabLabel}` : `idle${costLabel}${collabLabel}`;
|
|
172
176
|
const shown = running.slice(0, 3);
|
|
173
177
|
const overflow = running.length > 3 ? running.length - 3 : 0;
|
|
178
|
+
const leaderTool = hasCollab ? "waiting for agents" : leader?.currentTool?.name ?? (leader?.status === "running" ? "running" : "\u2014");
|
|
174
179
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
175
180
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
176
181
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u26A1 Fleet" }),
|
|
177
182
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
178
183
|
/* @__PURE__ */ jsx(Text, { children: summaryLine })
|
|
179
184
|
] }),
|
|
185
|
+
hasCollab && leader ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
186
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u25CF" }),
|
|
187
|
+
/* @__PURE__ */ jsx(Text, { children: leader.name.slice(0, 14).padEnd(14) }),
|
|
188
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2192" }),
|
|
189
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: leaderTool })
|
|
190
|
+
] }) : null,
|
|
180
191
|
shown.map((entry) => {
|
|
181
|
-
const name =
|
|
192
|
+
const name = entry.name && entry.name !== entry.id ? entry.name : entry.id.slice(0, 8);
|
|
182
193
|
const tool = entry.currentTool?.name ?? "\u2014";
|
|
183
194
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
184
195
|
/* @__PURE__ */ jsx(Text, { color: "green", children: "\u25CF" }),
|
|
185
|
-
/* @__PURE__ */ jsx(Text, { children: name.slice(0,
|
|
196
|
+
/* @__PURE__ */ jsx(Text, { children: name.slice(0, 14).padEnd(14) }),
|
|
186
197
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2192" }),
|
|
187
198
|
/* @__PURE__ */ jsx(Text, { color: "cyan", children: tool })
|
|
188
199
|
] }, entry.id);
|
|
189
200
|
}),
|
|
190
201
|
overflow > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
191
|
-
"
|
|
202
|
+
" ",
|
|
203
|
+
"+",
|
|
192
204
|
overflow,
|
|
193
|
-
"
|
|
205
|
+
": ",
|
|
206
|
+
running[3]?.name?.slice(0, 12) ?? "agent",
|
|
207
|
+
"\u2026"
|
|
194
208
|
] }) : null
|
|
195
209
|
] });
|
|
196
210
|
}
|
|
@@ -215,8 +229,7 @@ function StatusBar({
|
|
|
215
229
|
processCount,
|
|
216
230
|
hiddenItems,
|
|
217
231
|
eternalStage,
|
|
218
|
-
goalSummary
|
|
219
|
-
autoProceedCountdown
|
|
232
|
+
goalSummary
|
|
220
233
|
}) {
|
|
221
234
|
const hiddenSet = new Set(hiddenItems);
|
|
222
235
|
const usage = tokenCounter?.total();
|
|
@@ -612,7 +625,8 @@ function FleetMonitor({
|
|
|
612
625
|
totalCost,
|
|
613
626
|
totalTokens,
|
|
614
627
|
maxConcurrent = 4,
|
|
615
|
-
nowTick
|
|
628
|
+
nowTick,
|
|
629
|
+
collabSession
|
|
616
630
|
}) {
|
|
617
631
|
const all = Object.values(entries);
|
|
618
632
|
const running = all.filter((e) => e.status === "running");
|
|
@@ -651,7 +665,12 @@ function FleetMonitor({
|
|
|
651
665
|
}
|
|
652
666
|
}
|
|
653
667
|
events.sort((a, b) => b.at - a.at);
|
|
654
|
-
const timeline = events.slice(0,
|
|
668
|
+
const timeline = events.slice(0, 20);
|
|
669
|
+
const VERDICT_COLOR = {
|
|
670
|
+
approve: "green",
|
|
671
|
+
needs_revision: "yellow",
|
|
672
|
+
reject: "red"
|
|
673
|
+
};
|
|
655
674
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
656
675
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
657
676
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "FLEET \xB7 ORCHESTRATION" }),
|
|
@@ -674,6 +693,39 @@ function FleetMonitor({
|
|
|
674
693
|
] }) : null,
|
|
675
694
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 Ctrl+F to close" })
|
|
676
695
|
] }),
|
|
696
|
+
collabSession ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
697
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
698
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "magenta", children: "\u26A1 COLLAB SESSION" }),
|
|
699
|
+
collabSession.sessionId ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: collabSession.sessionId.slice(0, 8) }) : null,
|
|
700
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
701
|
+
/* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
702
|
+
"\u{1F41B}",
|
|
703
|
+
collabSession.bugCount
|
|
704
|
+
] }),
|
|
705
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
706
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
707
|
+
"\u{1F4D0}",
|
|
708
|
+
collabSession.planCount
|
|
709
|
+
] }),
|
|
710
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
711
|
+
/* @__PURE__ */ jsxs(Text, { color: "blue", children: [
|
|
712
|
+
"\u2696\uFE0F",
|
|
713
|
+
collabSession.evalCount
|
|
714
|
+
] }),
|
|
715
|
+
collabSession.overallVerdict ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
716
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
717
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: VERDICT_COLOR[collabSession.overallVerdict], children: collabSession.overallVerdict })
|
|
718
|
+
] }) : null
|
|
719
|
+
] }),
|
|
720
|
+
collabSession.timeline.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 0, children: collabSession.timeline.slice(0, 6).map((ev, i) => (
|
|
721
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: timeline is rebuilt per render
|
|
722
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
723
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `${fmtElapsed(Math.max(0, nowTick - ev.at))} ago`.padEnd(10) }),
|
|
724
|
+
/* @__PURE__ */ jsx(Text, { color: ev.color, children: ev.icon }),
|
|
725
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ev.text })
|
|
726
|
+
] }, i)
|
|
727
|
+
)) }) : null
|
|
728
|
+
] }) : null,
|
|
677
729
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
678
730
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "concurrency" }),
|
|
679
731
|
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
@@ -771,6 +823,26 @@ function snippet(s2, max = 72) {
|
|
|
771
823
|
if (oneLine2.length <= max) return oneLine2;
|
|
772
824
|
return `${oneLine2.slice(0, max - 1)}\u2026`;
|
|
773
825
|
}
|
|
826
|
+
function ContextBar({
|
|
827
|
+
pct,
|
|
828
|
+
tokens,
|
|
829
|
+
maxTokens
|
|
830
|
+
}) {
|
|
831
|
+
const clamped = Math.max(0, Math.min(2, pct));
|
|
832
|
+
const totalBars = 10;
|
|
833
|
+
const filled = Math.round(clamped * totalBars);
|
|
834
|
+
const empty = totalBars - filled;
|
|
835
|
+
const color = pct < 0.6 ? "green" : pct < 0.75 ? "yellow" : "red";
|
|
836
|
+
const pctText = pct >= 1 ? `${Math.round(pct * 100)}%+` : `${Math.round(pct * 100)}%`;
|
|
837
|
+
const tokenText = tokens ? ` ${fmtTokens2(tokens)}/${fmtTokens2(maxTokens ?? 2e5)}` : "";
|
|
838
|
+
return /* @__PURE__ */ jsxs(Text, { color, children: [
|
|
839
|
+
"\u2588".repeat(filled),
|
|
840
|
+
"\u2591".repeat(Math.max(0, empty)),
|
|
841
|
+
" ",
|
|
842
|
+
pctText,
|
|
843
|
+
tokenText
|
|
844
|
+
] });
|
|
845
|
+
}
|
|
774
846
|
function AgentsMonitor({
|
|
775
847
|
entries,
|
|
776
848
|
totalCost,
|
|
@@ -894,7 +966,11 @@ function AgentsMonitor({
|
|
|
894
966
|
"/",
|
|
895
967
|
e.budgetWarning.limit,
|
|
896
968
|
" \u2014 extending"
|
|
897
|
-
] }) }) : null
|
|
969
|
+
] }) }) : null,
|
|
970
|
+
e.ctxPct !== void 0 ? /* @__PURE__ */ jsxs(Box, { paddingLeft: 2, children: [
|
|
971
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "ctx " }),
|
|
972
|
+
/* @__PURE__ */ jsx(ContextBar, { pct: e.ctxPct, tokens: e.ctxTokens, maxTokens: e.ctxMaxTokens })
|
|
973
|
+
] }) : null
|
|
898
974
|
] }, e.id);
|
|
899
975
|
})
|
|
900
976
|
] });
|
|
@@ -1010,7 +1086,7 @@ var STATUS3 = {
|
|
|
1010
1086
|
function s(entry) {
|
|
1011
1087
|
return STATUS3[entry] ?? { icon: "?", color: "white" };
|
|
1012
1088
|
}
|
|
1013
|
-
function PhasePanel({ phases,
|
|
1089
|
+
function PhasePanel({ phases, nowTick }) {
|
|
1014
1090
|
const list = Object.values(phases);
|
|
1015
1091
|
if (list.length === 0) return null;
|
|
1016
1092
|
const done = list.filter((p) => p.status === "completed" || p.status === "skipped").length;
|
|
@@ -2692,9 +2768,36 @@ var BEGIN = "[200~";
|
|
|
2692
2768
|
var END = "[201~";
|
|
2693
2769
|
var BEGIN_RE = /\x1b?\[200~/g;
|
|
2694
2770
|
var END_RE = /\x1b?\[201~/g;
|
|
2771
|
+
var PARTIAL_ANSI_RE = /^\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/;
|
|
2772
|
+
var ANSI_RE = new RegExp(
|
|
2773
|
+
[
|
|
2774
|
+
// CSI: ESC [ params* intermediates* final
|
|
2775
|
+
// params 0x30-0x3f (digits, ; : < = > ?)
|
|
2776
|
+
// intermediates 0x20-0x2f (space … /)
|
|
2777
|
+
// final 0x40-0x7e (@ … ~)
|
|
2778
|
+
"\\x1b\\[[\\x30-\\x3f]*[\\x20-\\x2f]*[\\x40-\\x7e]",
|
|
2779
|
+
// OSC: ESC ] … BEL (\x07) or ST (\x1b\\)
|
|
2780
|
+
"\\x1b\\][^\\x07\\x1b]*(?:\\x07|\\x1b\\\\)",
|
|
2781
|
+
// DCS: ESC P … ST (\x1b\\)
|
|
2782
|
+
"\\x1bP[^\\x1b]*(?:\\x1b\\\\)",
|
|
2783
|
+
// SOS / PM: ESC X / ESC ^
|
|
2784
|
+
"\\x1b[XP][^\\x1b]*(?:\\x1b\\\\)",
|
|
2785
|
+
// Standalone ESC — guard only
|
|
2786
|
+
"\\x1b"
|
|
2787
|
+
].join("|"),
|
|
2788
|
+
"g"
|
|
2789
|
+
);
|
|
2695
2790
|
function feedPaste(accum, input) {
|
|
2696
|
-
if (accum === null && !input.includes(BEGIN))
|
|
2697
|
-
|
|
2791
|
+
if (accum === null && !input.includes(BEGIN)) {
|
|
2792
|
+
if (input.startsWith("[") && !input.startsWith(BEGIN) && !input.startsWith(END)) {
|
|
2793
|
+
if (PARTIAL_ANSI_RE.test(input)) {
|
|
2794
|
+
return { accum: "", complete: null };
|
|
2795
|
+
}
|
|
2796
|
+
return null;
|
|
2797
|
+
}
|
|
2798
|
+
return null;
|
|
2799
|
+
}
|
|
2800
|
+
const piece = input.replace(BEGIN_RE, "").replace(END_RE, "").replace(ANSI_RE, "");
|
|
2698
2801
|
const next = (accum ?? "") + piece;
|
|
2699
2802
|
if (input.includes(END)) return { accum: null, complete: next };
|
|
2700
2803
|
return { accum: next, complete: null };
|
|
@@ -2966,10 +3069,10 @@ function reducer(state, action) {
|
|
|
2966
3069
|
case "clearPlaceholdersOnly":
|
|
2967
3070
|
return { ...state, placeholders: [], placeholderContents: [] };
|
|
2968
3071
|
case "clearHistory": {
|
|
2969
|
-
const
|
|
3072
|
+
const banner = state.entries.find((e) => e.kind === "banner");
|
|
2970
3073
|
return {
|
|
2971
3074
|
...state,
|
|
2972
|
-
entries:
|
|
3075
|
+
entries: banner ? [banner] : state.entries,
|
|
2973
3076
|
queue: [],
|
|
2974
3077
|
nextQueueId: 1
|
|
2975
3078
|
};
|
|
@@ -2985,7 +3088,7 @@ function reducer(state, action) {
|
|
|
2985
3088
|
case "steerStart":
|
|
2986
3089
|
return { ...state, steeringPending: true, steerSnapshot: action.snapshot };
|
|
2987
3090
|
case "steerConsume":
|
|
2988
|
-
return { ...state, steeringPending: false, steerSnapshot: null };
|
|
3091
|
+
return { ...state, steeringPending: false, steerSnapshot: null, interrupts: 0 };
|
|
2989
3092
|
case "resetInterrupts":
|
|
2990
3093
|
return { ...state, interrupts: 0 };
|
|
2991
3094
|
case "hint":
|
|
@@ -3289,7 +3392,7 @@ function reducer(state, action) {
|
|
|
3289
3392
|
case "fleetDelta": {
|
|
3290
3393
|
const cur = state.fleet[action.id];
|
|
3291
3394
|
if (!cur) return state;
|
|
3292
|
-
const appended = (cur.streamingText + action.text).slice(-
|
|
3395
|
+
const appended = (cur.streamingText + action.text).slice(-500);
|
|
3293
3396
|
return {
|
|
3294
3397
|
...state,
|
|
3295
3398
|
fleet: {
|
|
@@ -3401,6 +3504,23 @@ function reducer(state, action) {
|
|
|
3401
3504
|
}
|
|
3402
3505
|
};
|
|
3403
3506
|
}
|
|
3507
|
+
case "fleetCtxPct": {
|
|
3508
|
+
const cur = state.fleet[action.id];
|
|
3509
|
+
if (!cur) return state;
|
|
3510
|
+
return {
|
|
3511
|
+
...state,
|
|
3512
|
+
fleet: {
|
|
3513
|
+
...state.fleet,
|
|
3514
|
+
[action.id]: {
|
|
3515
|
+
...cur,
|
|
3516
|
+
ctxPct: action.load,
|
|
3517
|
+
ctxTokens: action.tokens,
|
|
3518
|
+
ctxMaxTokens: action.maxContext,
|
|
3519
|
+
lastEventAt: Date.now()
|
|
3520
|
+
}
|
|
3521
|
+
}
|
|
3522
|
+
};
|
|
3523
|
+
}
|
|
3404
3524
|
case "fleetCost": {
|
|
3405
3525
|
return {
|
|
3406
3526
|
...state,
|
|
@@ -3452,6 +3572,18 @@ function reducer(state, action) {
|
|
|
3452
3572
|
}
|
|
3453
3573
|
};
|
|
3454
3574
|
}
|
|
3575
|
+
case "leaderCtxPct": {
|
|
3576
|
+
return {
|
|
3577
|
+
...state,
|
|
3578
|
+
leader: {
|
|
3579
|
+
...state.leader,
|
|
3580
|
+
ctxPct: action.load,
|
|
3581
|
+
ctxTokens: action.tokens,
|
|
3582
|
+
ctxMaxTokens: action.maxContext,
|
|
3583
|
+
lastEventAt: Date.now()
|
|
3584
|
+
}
|
|
3585
|
+
};
|
|
3586
|
+
}
|
|
3455
3587
|
case "setStreamFleet": {
|
|
3456
3588
|
return { ...state, streamFleet: action.enabled };
|
|
3457
3589
|
}
|
|
@@ -3578,6 +3710,59 @@ function reducer(state, action) {
|
|
|
3578
3710
|
case "worktreeMonitorToggle": {
|
|
3579
3711
|
return { ...state, worktreeMonitorOpen: !state.worktreeMonitorOpen };
|
|
3580
3712
|
}
|
|
3713
|
+
// --- Collab session ---
|
|
3714
|
+
case "collabSubagentSpawned": {
|
|
3715
|
+
if (state.collabSession) return state;
|
|
3716
|
+
return {
|
|
3717
|
+
...state,
|
|
3718
|
+
collabSession: {
|
|
3719
|
+
sessionId: null,
|
|
3720
|
+
bugCount: 0,
|
|
3721
|
+
planCount: 0,
|
|
3722
|
+
evalCount: 0,
|
|
3723
|
+
overallVerdict: null,
|
|
3724
|
+
timeline: [{ at: Date.now(), icon: "\u26A1", color: "cyan", text: `${action.role} spawned` }],
|
|
3725
|
+
startedAt: Date.now()
|
|
3726
|
+
}
|
|
3727
|
+
};
|
|
3728
|
+
}
|
|
3729
|
+
case "collabBugFound": {
|
|
3730
|
+
const cs = state.collabSession;
|
|
3731
|
+
if (!cs) {
|
|
3732
|
+
return {
|
|
3733
|
+
...state,
|
|
3734
|
+
collabSession: {
|
|
3735
|
+
sessionId: action.sessionId,
|
|
3736
|
+
bugCount: 1,
|
|
3737
|
+
planCount: 0,
|
|
3738
|
+
evalCount: 0,
|
|
3739
|
+
overallVerdict: null,
|
|
3740
|
+
timeline: [{ at: Date.now(), icon: "\u{1F41B}", color: "red", text: `bug: ${action.description.slice(0, 60)}\u2026` }],
|
|
3741
|
+
startedAt: Date.now()
|
|
3742
|
+
}
|
|
3743
|
+
};
|
|
3744
|
+
}
|
|
3745
|
+
const entry = { at: Date.now(), icon: "\u{1F41B}", color: "red", text: `bug [${action.severity}]: ${action.description.slice(0, 55)}\u2026` };
|
|
3746
|
+
return { ...state, collabSession: { ...cs, sessionId: action.sessionId, bugCount: cs.bugCount + 1, timeline: [entry, ...cs.timeline].slice(0, 30) } };
|
|
3747
|
+
}
|
|
3748
|
+
case "collabPlanEmitted": {
|
|
3749
|
+
const cs = state.collabSession;
|
|
3750
|
+
if (!cs) return state;
|
|
3751
|
+
const entry = { at: Date.now(), icon: "\u{1F4D0}", color: "yellow", text: `plan [${action.riskScore}]: ${action.phaseCount} phases` };
|
|
3752
|
+
return { ...state, collabSession: { ...cs, sessionId: action.sessionId, planCount: cs.planCount + 1, timeline: [entry, ...cs.timeline].slice(0, 30) } };
|
|
3753
|
+
}
|
|
3754
|
+
case "collabEvalComplete": {
|
|
3755
|
+
const cs = state.collabSession;
|
|
3756
|
+
if (!cs) return state;
|
|
3757
|
+
const entry = { at: Date.now(), icon: "\u2696\uFE0F", color: action.verdict === "approve" ? "green" : action.verdict === "reject" ? "red" : "yellow", text: `eval ${action.score}/10 \u2192 ${action.verdict}` };
|
|
3758
|
+
return { ...state, collabSession: { ...cs, sessionId: action.sessionId, evalCount: cs.evalCount + 1, timeline: [entry, ...cs.timeline].slice(0, 30) } };
|
|
3759
|
+
}
|
|
3760
|
+
case "collabSessionDone": {
|
|
3761
|
+
const cs = state.collabSession;
|
|
3762
|
+
if (!cs) return state;
|
|
3763
|
+
const entry = { at: Date.now(), icon: "\u{1F3C1}", color: "green", text: `session done \u2014 ${action.verdict}` };
|
|
3764
|
+
return { ...state, collabSession: { ...cs, overallVerdict: action.verdict, timeline: [entry, ...cs.timeline].slice(0, 30) } };
|
|
3765
|
+
}
|
|
3581
3766
|
}
|
|
3582
3767
|
}
|
|
3583
3768
|
var PASTE_THRESHOLD_CHARS = 200;
|
|
@@ -3747,6 +3932,7 @@ function App({
|
|
|
3747
3932
|
streamFleet: true,
|
|
3748
3933
|
monitorOpen: false,
|
|
3749
3934
|
agentsMonitorOpen: false,
|
|
3935
|
+
collabSession: null,
|
|
3750
3936
|
checkpoints: [],
|
|
3751
3937
|
rewindOverlay: null,
|
|
3752
3938
|
eternalStage: null,
|
|
@@ -3813,7 +3999,6 @@ function App({
|
|
|
3813
3999
|
clearInterval(t);
|
|
3814
4000
|
};
|
|
3815
4001
|
}, [agent.ctx.cwd]);
|
|
3816
|
-
(tokenCounter?.total().input ?? 0) + (tokenCounter?.total().cacheRead ?? 0) + (tokenCounter?.total().cacheWrite ?? 0);
|
|
3817
4002
|
const maxContext = effectiveMaxContext ?? agent.ctx.provider.capabilities.maxContext;
|
|
3818
4003
|
const currentContextTokens = (tokenCounter?.currentRequestTokens()?.input ?? 0) + (tokenCounter?.currentRequestTokens()?.cacheRead ?? 0);
|
|
3819
4004
|
const contextWindow = useMemo(() => {
|
|
@@ -3857,7 +4042,10 @@ function App({
|
|
|
3857
4042
|
cost: 0,
|
|
3858
4043
|
startedAt: state.leader.startedAt,
|
|
3859
4044
|
lastEventAt: state.leader.lastEventAt,
|
|
3860
|
-
currentTool: state.leader.currentTool
|
|
4045
|
+
currentTool: state.leader.currentTool,
|
|
4046
|
+
ctxPct: state.leader.ctxPct,
|
|
4047
|
+
ctxTokens: state.leader.ctxTokens,
|
|
4048
|
+
ctxMaxTokens: state.leader.ctxMaxTokens
|
|
3861
4049
|
};
|
|
3862
4050
|
return { leader: leaderEntry, ...state.fleet };
|
|
3863
4051
|
}, [state.fleet, state.leader, state.status, provider, model]);
|
|
@@ -3868,9 +4056,8 @@ function App({
|
|
|
3868
4056
|
const existing = m.get(id);
|
|
3869
4057
|
if (existing) return existing;
|
|
3870
4058
|
const n = m.size + 1;
|
|
3871
|
-
const suffix = name && name !== id ? ` ${name}` : "";
|
|
3872
4059
|
const v = {
|
|
3873
|
-
label: `AGENT#${n}
|
|
4060
|
+
label: name && name !== id ? name : `AGENT#${n}`,
|
|
3874
4061
|
color: STREAM_COLORS[(n - 1) % STREAM_COLORS.length]
|
|
3875
4062
|
};
|
|
3876
4063
|
m.set(id, v);
|
|
@@ -4514,6 +4701,23 @@ function App({
|
|
|
4514
4701
|
}
|
|
4515
4702
|
});
|
|
4516
4703
|
});
|
|
4704
|
+
const offCtxPct = events.on("subagent.ctx_pct", (e) => {
|
|
4705
|
+
dispatch({
|
|
4706
|
+
type: "fleetCtxPct",
|
|
4707
|
+
id: e.subagentId,
|
|
4708
|
+
load: e.load,
|
|
4709
|
+
tokens: e.tokens,
|
|
4710
|
+
maxContext: e.maxContext
|
|
4711
|
+
});
|
|
4712
|
+
});
|
|
4713
|
+
const offLeaderCtxPct = events.on("ctx.pct", (e) => {
|
|
4714
|
+
dispatch({
|
|
4715
|
+
type: "leaderCtxPct",
|
|
4716
|
+
load: e.load,
|
|
4717
|
+
tokens: e.tokens,
|
|
4718
|
+
maxContext: e.maxContext
|
|
4719
|
+
});
|
|
4720
|
+
});
|
|
4517
4721
|
const offTool = events.on("subagent.tool_executed", (e) => {
|
|
4518
4722
|
dispatch({
|
|
4519
4723
|
type: "fleetTool",
|
|
@@ -4532,6 +4736,8 @@ function App({
|
|
|
4532
4736
|
offBudgetWarning();
|
|
4533
4737
|
offBudgetExtended();
|
|
4534
4738
|
offIterationSummary();
|
|
4739
|
+
offCtxPct();
|
|
4740
|
+
offLeaderCtxPct();
|
|
4535
4741
|
offTool();
|
|
4536
4742
|
};
|
|
4537
4743
|
}, [events, director]);
|
|
@@ -4941,6 +5147,70 @@ function App({
|
|
|
4941
5147
|
}
|
|
4942
5148
|
break;
|
|
4943
5149
|
}
|
|
5150
|
+
// --- Collab session events ---
|
|
5151
|
+
case "bug.found": {
|
|
5152
|
+
const role = e.subagentId.includes("bug-hunter") ? "bug-hunter" : e.subagentId.includes("refactor-planner") ? "refactor-planner" : e.subagentId.includes("critic") ? "critic" : null;
|
|
5153
|
+
if (!role && !state.collabSession) {
|
|
5154
|
+
break;
|
|
5155
|
+
}
|
|
5156
|
+
if (!state.collabSession) {
|
|
5157
|
+
dispatch({ type: "collabSubagentSpawned", subagentId: e.subagentId, role: role ?? "unknown" });
|
|
5158
|
+
}
|
|
5159
|
+
const bp = e.payload;
|
|
5160
|
+
if (bp?.finding) {
|
|
5161
|
+
const sessionId = e.subagentId.split("-").slice(1).join("-") || e.subagentId;
|
|
5162
|
+
dispatch({
|
|
5163
|
+
type: "collabBugFound",
|
|
5164
|
+
sessionId,
|
|
5165
|
+
bugId: bp.finding.id ?? "unknown",
|
|
5166
|
+
severity: bp.finding.severity ?? "unknown",
|
|
5167
|
+
description: bp.finding.description ?? ""
|
|
5168
|
+
});
|
|
5169
|
+
}
|
|
5170
|
+
break;
|
|
5171
|
+
}
|
|
5172
|
+
case "refactor.plan": {
|
|
5173
|
+
if (!state.collabSession) break;
|
|
5174
|
+
const pp = e.payload;
|
|
5175
|
+
if (pp?.plan) {
|
|
5176
|
+
const sessionId = e.subagentId.split("-").slice(1).join("-") || e.subagentId;
|
|
5177
|
+
dispatch({
|
|
5178
|
+
type: "collabPlanEmitted",
|
|
5179
|
+
sessionId,
|
|
5180
|
+
planId: pp.plan.id ?? "unknown",
|
|
5181
|
+
riskScore: pp.plan.riskScore ?? "unknown",
|
|
5182
|
+
phaseCount: pp.plan.phases?.length ?? 0
|
|
5183
|
+
});
|
|
5184
|
+
}
|
|
5185
|
+
break;
|
|
5186
|
+
}
|
|
5187
|
+
case "critic.evaluation": {
|
|
5188
|
+
if (!state.collabSession) break;
|
|
5189
|
+
const ep = e.payload;
|
|
5190
|
+
if (ep?.evaluation) {
|
|
5191
|
+
const sessionId = e.subagentId.split("-").slice(1).join("-") || e.subagentId;
|
|
5192
|
+
dispatch({
|
|
5193
|
+
type: "collabEvalComplete",
|
|
5194
|
+
sessionId,
|
|
5195
|
+
evalId: ep.evaluation.id ?? "unknown",
|
|
5196
|
+
verdict: ep.evaluation.verdict ?? "unknown",
|
|
5197
|
+
score: ep.evaluation.score ?? 0
|
|
5198
|
+
});
|
|
5199
|
+
}
|
|
5200
|
+
break;
|
|
5201
|
+
}
|
|
5202
|
+
case "collab.session_done": {
|
|
5203
|
+
if (!state.collabSession) break;
|
|
5204
|
+
const dp = e.payload;
|
|
5205
|
+
if (dp?.report) {
|
|
5206
|
+
dispatch({
|
|
5207
|
+
type: "collabSessionDone",
|
|
5208
|
+
sessionId: dp.report.sessionId ?? state.collabSession.sessionId ?? "unknown",
|
|
5209
|
+
verdict: dp.report.overallVerdict ?? "needs_revision"
|
|
5210
|
+
});
|
|
5211
|
+
}
|
|
5212
|
+
break;
|
|
5213
|
+
}
|
|
4944
5214
|
}
|
|
4945
5215
|
});
|
|
4946
5216
|
const offDone = d.on("task.completed", (payload) => {
|
|
@@ -5102,7 +5372,7 @@ function App({
|
|
|
5102
5372
|
setDraft(next, cursor + full.length);
|
|
5103
5373
|
};
|
|
5104
5374
|
const handleKey = async (input, key) => {
|
|
5105
|
-
if (state.status === "aborting" && state.interrupts === 0) return;
|
|
5375
|
+
if (state.status === "aborting" && !state.steeringPending && state.interrupts === 0) return;
|
|
5106
5376
|
if (state.confirmQueue.length > 0) return;
|
|
5107
5377
|
if (inputGateRef.current) return;
|
|
5108
5378
|
if (key.escape) {
|
|
@@ -5186,14 +5456,6 @@ function App({
|
|
|
5186
5456
|
}
|
|
5187
5457
|
return;
|
|
5188
5458
|
}
|
|
5189
|
-
if (key.ctrl && input === "p") {
|
|
5190
|
-
dispatch({ type: "autoPhaseMonitorToggle" });
|
|
5191
|
-
return;
|
|
5192
|
-
}
|
|
5193
|
-
if (key.ctrl && input === "t") {
|
|
5194
|
-
dispatch({ type: "worktreeMonitorToggle" });
|
|
5195
|
-
return;
|
|
5196
|
-
}
|
|
5197
5459
|
if (state.autonomyPicker.open) {
|
|
5198
5460
|
if (key.escape) {
|
|
5199
5461
|
dispatch({ type: "autonomyPickerClose" });
|
|
@@ -5320,20 +5582,47 @@ function App({
|
|
|
5320
5582
|
return;
|
|
5321
5583
|
}
|
|
5322
5584
|
if (key.ctrl && input === "f") {
|
|
5323
|
-
|
|
5585
|
+
if (state.agentsMonitorOpen) {
|
|
5586
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
5587
|
+
dispatch({ type: "toggleMonitor" });
|
|
5588
|
+
} else {
|
|
5589
|
+
dispatch({ type: "toggleMonitor" });
|
|
5590
|
+
}
|
|
5324
5591
|
return;
|
|
5325
5592
|
}
|
|
5326
5593
|
if (key.ctrl && input === "g") {
|
|
5327
|
-
|
|
5594
|
+
if (state.monitorOpen) {
|
|
5595
|
+
dispatch({ type: "toggleMonitor" });
|
|
5596
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
5597
|
+
} else {
|
|
5598
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
5599
|
+
}
|
|
5328
5600
|
return;
|
|
5329
5601
|
}
|
|
5330
|
-
if (key.
|
|
5331
|
-
|
|
5602
|
+
if (key.ctrl && input === "t") {
|
|
5603
|
+
if (state.worktreeMonitorOpen) {
|
|
5604
|
+
dispatch({ type: "worktreeMonitorToggle" });
|
|
5605
|
+
return;
|
|
5606
|
+
}
|
|
5607
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
5608
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
5609
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
5610
|
+
dispatch({ type: "worktreeMonitorToggle" });
|
|
5332
5611
|
return;
|
|
5333
5612
|
}
|
|
5334
|
-
if (key.escape
|
|
5335
|
-
|
|
5336
|
-
|
|
5613
|
+
if (key.escape) {
|
|
5614
|
+
if (state.agentsMonitorOpen) {
|
|
5615
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
5616
|
+
return;
|
|
5617
|
+
}
|
|
5618
|
+
if (state.monitorOpen) {
|
|
5619
|
+
dispatch({ type: "toggleMonitor" });
|
|
5620
|
+
return;
|
|
5621
|
+
}
|
|
5622
|
+
if (state.worktreeMonitorOpen) {
|
|
5623
|
+
dispatch({ type: "worktreeMonitorToggle" });
|
|
5624
|
+
return;
|
|
5625
|
+
}
|
|
5337
5626
|
}
|
|
5338
5627
|
if (isEnter) {
|
|
5339
5628
|
const now = Date.now();
|
|
@@ -5436,18 +5725,6 @@ function App({
|
|
|
5436
5725
|
setDraft("", 0);
|
|
5437
5726
|
return;
|
|
5438
5727
|
}
|
|
5439
|
-
if (key.ctrl && input === "w") {
|
|
5440
|
-
if (state.worktreeMonitorOpen) {
|
|
5441
|
-
dispatch({ type: "worktreeMonitorToggle" });
|
|
5442
|
-
return;
|
|
5443
|
-
}
|
|
5444
|
-
if (cursor === 0) return;
|
|
5445
|
-
const beforeCursor = buffer.slice(0, cursor);
|
|
5446
|
-
const lastWordStart = beforeCursor.lastIndexOf(" ") + 1;
|
|
5447
|
-
const next2 = buffer.slice(0, lastWordStart) + buffer.slice(cursor);
|
|
5448
|
-
setDraft(next2, lastWordStart);
|
|
5449
|
-
return;
|
|
5450
|
-
}
|
|
5451
5728
|
if (key.delete || key.ctrl && input === "d") {
|
|
5452
5729
|
if (cursor >= buffer.length) return;
|
|
5453
5730
|
const next2 = buffer.slice(0, cursor) + buffer.slice(cursor + 1);
|
|
@@ -5817,7 +6094,7 @@ User message:
|
|
|
5817
6094
|
value: state.buffer,
|
|
5818
6095
|
cursor: state.cursor,
|
|
5819
6096
|
placeholders: state.placeholders,
|
|
5820
|
-
disabled: state.status === "aborting" || state.confirmQueue.length > 0,
|
|
6097
|
+
disabled: state.status === "aborting" && !state.steeringPending || state.confirmQueue.length > 0,
|
|
5821
6098
|
hint: inputHint,
|
|
5822
6099
|
onKey: handleKey
|
|
5823
6100
|
}
|
|
@@ -5941,9 +6218,10 @@ User message:
|
|
|
5941
6218
|
entries: state.fleet,
|
|
5942
6219
|
totalCost: state.fleetCost,
|
|
5943
6220
|
totalTokens: state.fleetTokens,
|
|
5944
|
-
nowTick
|
|
6221
|
+
nowTick,
|
|
6222
|
+
collabSession: state.collabSession
|
|
5945
6223
|
}
|
|
5946
|
-
) : director ? /* @__PURE__ */ jsx(FleetPanel, { entries:
|
|
6224
|
+
) : director ? /* @__PURE__ */ jsx(FleetPanel, { entries: entriesWithLeader, totalCost: state.fleetCost, roster: fleetRoster, collabSession: state.collabSession }) : null,
|
|
5947
6225
|
state.autoPhase && !state.autoPhase.monitorOpen ? /* @__PURE__ */ jsx(
|
|
5948
6226
|
PhasePanel,
|
|
5949
6227
|
{
|