@wrongstack/tui 0.265.1 → 0.268.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.js CHANGED
@@ -1,4 +1,4 @@
1
- import { writeErr, resolveProjectDir, wstackGlobalRoot, GlobalMailbox, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, expectDefined as expectDefined$1, projectSlug, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, buildChildEnv } from '@wrongstack/core';
1
+ import { writeErr, resolveProjectDir, wstackGlobalRoot, createHqPublisherFromEnv, GlobalMailbox, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, expectDefined as expectDefined$1, projectSlug, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, buildChildEnv } from '@wrongstack/core';
2
2
  export { buildGoalPreamble } from '@wrongstack/core';
3
3
  import { Box as Box$1, useInput, useStdin, useStdout, Text as Text$1, render, useApp, measureElement, Static } from 'ink';
4
4
  import { randomUUID } from 'crypto';
@@ -88,6 +88,13 @@ var Box = forwardRef(function Box2({ borderColor, backgroundColor, ...rest }, re
88
88
  }
89
89
  );
90
90
  });
91
+ function snapshotTokenCounter(tokenCounter) {
92
+ return {
93
+ usage: tokenCounter.total(),
94
+ cost: tokenCounter.estimateCost(),
95
+ cacheStats: tokenCounter.cacheStats()
96
+ };
97
+ }
91
98
  function useTokenCounterRefresh(tokenCounter, events) {
92
99
  const [data, setData] = useState(
93
100
  () => tokenCounter ? {
@@ -97,18 +104,32 @@ function useTokenCounterRefresh(tokenCounter, events) {
97
104
  } : void 0
98
105
  );
99
106
  useEffect(() => {
100
- if (!tokenCounter || !events) return;
107
+ if (!tokenCounter) {
108
+ setData(void 0);
109
+ return;
110
+ }
111
+ const snapshot = () => snapshotTokenCounter(tokenCounter);
112
+ setData(snapshot());
113
+ if (!events) return;
101
114
  const off = events.on("token.accounted", () => {
102
- setData({
103
- usage: tokenCounter.total(),
104
- cost: tokenCounter.estimateCost(),
105
- cacheStats: tokenCounter.cacheStats()
106
- });
115
+ setData(snapshot());
107
116
  });
108
117
  return off;
109
118
  }, [tokenCounter, events]);
110
119
  return data;
111
120
  }
121
+ function chipExpired(meta, now = Date.now()) {
122
+ if (meta.expiresIn == null) return false;
123
+ return now >= meta.shownAt + meta.expiresIn * 6e4;
124
+ }
125
+ function isStreamChipVisible(key, dataIsPresent, hiddenSet, visibleChips) {
126
+ if (!dataIsPresent) return false;
127
+ if (hiddenSet.has(key)) return false;
128
+ const meta = visibleChips.find((c) => c.key === key);
129
+ if (!meta) return false;
130
+ if (chipExpired(meta)) return false;
131
+ return true;
132
+ }
112
133
  var MODE_ICONS = {
113
134
  teach: "\u{1F9D1}\u200D\u{1F3EB}",
114
135
  brief: "\u26A1",
@@ -163,6 +184,7 @@ function StatusBar({
163
184
  context,
164
185
  contextStrategy,
165
186
  hiddenItems,
187
+ mode = "detailed",
166
188
  events,
167
189
  eternalStage,
168
190
  goalSummary,
@@ -177,7 +199,8 @@ function StatusBar({
177
199
  sessionCount,
178
200
  mailbox,
179
201
  tokenSavingMode,
180
- toolCount
202
+ toolCount,
203
+ visibleChips = []
181
204
  }) {
182
205
  const { stdout } = useStdout();
183
206
  const [termWidth, setTermWidth] = useState(stdout?.columns ?? 90);
@@ -218,13 +241,75 @@ function StatusBar({
218
241
  const hasAutoProceed = autoProceedCountdown != null && autoProceedCountdown > 0;
219
242
  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 || tokenSavingMode || typeof toolCount === "number" && toolCount > 0;
220
243
  const fleetHasActivity = fleet && (fleet.running > 0 || fleet.idle > 0 || fleet.pending > 0 || fleet.completed > 0) || subagentCount > 0;
221
- const hasBrainActivity = !!brain && brain.state !== "idle";
222
- const hasDebugStream = !!debugStreamStats;
223
- const hasEnhanceCountdown = enhanceCountdown != null && enhanceCountdown > 0;
244
+ const showBrain = isStreamChipVisible("brain", brain, hiddenSet ?? /* @__PURE__ */ new Set(), visibleChips);
245
+ const showDebugStream = isStreamChipVisible("debug_stream", debugStreamStats, hiddenSet ?? /* @__PURE__ */ new Set(), visibleChips);
246
+ const showEnhance = isStreamChipVisible("enhance", enhanceCountdown, hiddenSet ?? /* @__PURE__ */ new Set(), visibleChips);
224
247
  const hasNextStepsAutoSubmit = nextStepsAutoSubmitCountdown != null && nextStepsAutoSubmitCountdown > 0;
225
248
  const countdownColor = nextStepsAutoSubmitCountdown != null ? nextStepsAutoSubmitCountdown > 20 ? "green" : nextStepsAutoSubmitCountdown > 10 ? "yellow" : "red" : "green";
226
249
  const hasTaskActivity = tasks && (tasks.pending > 0 || tasks.inProgress > 0 || tasks.completed > 0 || tasks.blocked > 0 || tasks.failed > 0);
227
- 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;
250
+ const hasThirdLine = todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && !hiddenSet.has("todos") || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) && !hiddenSet.has("plan") || hasTaskActivity && !hiddenSet.has("tasks") || fleetHasActivity && !hiddenSet.has("fleet") || showBrain || showDebugStream || showEnhance || hasNextStepsAutoSubmit;
251
+ const minimalWorkParts = [
252
+ queueCount > 0 ? `q${queueCount}` : "",
253
+ todos && !hiddenSet.has("todos") && todos.inProgress + todos.pending > 0 ? `todo ${todos.inProgress}/${todos.pending}` : "",
254
+ hasTaskActivity && !hiddenSet.has("tasks") ? `task ${tasks.inProgress}/${tasks.pending}` : "",
255
+ fleetHasActivity && !hiddenSet.has("fleet") ? fleet ? `agent \u25B6${fleet.running} \xB7${fleet.idle}` : `agent ${subagentCount}` : "",
256
+ typeof processCount === "number" && processCount > 0 ? `proc ${processCount}` : ""
257
+ ].filter(Boolean);
258
+ if (mode === "minimum") {
259
+ const ctxMax = context?.max;
260
+ const ctxRatio = context && ctxMax ? context.used / ctxMax : void 0;
261
+ const ctxClampedRatio = ctxRatio !== void 0 ? Math.min(ctxRatio, 1) : void 0;
262
+ const ctxPctText = ctxRatio !== void 0 ? `${Math.min(Math.round(ctxRatio * 100), 100)}%` : void 0;
263
+ return /* @__PURE__ */ jsx(
264
+ Box,
265
+ {
266
+ flexDirection: "column",
267
+ paddingX: 1,
268
+ borderStyle: "single",
269
+ borderTop: true,
270
+ borderBottom: false,
271
+ borderLeft: false,
272
+ borderRight: false,
273
+ children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
274
+ version ? /* @__PURE__ */ jsxs(Text, { children: [
275
+ /* @__PURE__ */ jsx(Text, { color: "blue", bold: true, children: "WS" }),
276
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
277
+ " v",
278
+ version
279
+ ] })
280
+ ] }) : null,
281
+ version ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
282
+ thinking ? /* @__PURE__ */ jsx(WaveText, { text: `${statePrefix} ${stateLabel}`, phase: spinnerIdx }) : /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
283
+ statePrefix,
284
+ " ",
285
+ stateLabel
286
+ ] }),
287
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
288
+ /* @__PURE__ */ jsx(Text, { color: "magenta", children: model }),
289
+ ctxClampedRatio !== void 0 && ctxPctText && ctxMax !== void 0 && !hiddenSet.has("context") ? /* @__PURE__ */ jsxs(Fragment, { children: [
290
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
291
+ /* @__PURE__ */ jsxs(Text, { color: ctxClampedRatio < 0.6 ? "green" : ctxClampedRatio < 0.75 ? "yellow" : "red", children: [
292
+ "ctx ",
293
+ ctxPctText,
294
+ "/",
295
+ fmtTok(ctxMax)
296
+ ] })
297
+ ] }) : null,
298
+ cost && cost.total > 0 && !hiddenSet.has("cost") ? /* @__PURE__ */ jsxs(Fragment, { children: [
299
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
300
+ /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
301
+ "$",
302
+ cost.total.toFixed(4)
303
+ ] })
304
+ ] }) : null,
305
+ minimalWorkParts.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
306
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
307
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: minimalWorkParts.slice(0, 3).join(" \xB7 ") })
308
+ ] }) : null
309
+ ] })
310
+ }
311
+ );
312
+ }
228
313
  return /* @__PURE__ */ jsxs(
229
314
  Box,
230
315
  {
@@ -277,6 +362,8 @@ function StatusBar({
277
362
  renderMeter(clampedRatio, 8),
278
363
  " ",
279
364
  pctText,
365
+ "/",
366
+ fmtTok(context.max),
280
367
  contextStrategy ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
281
368
  " [",
282
369
  contextStrategy,
@@ -304,7 +391,7 @@ function StatusBar({
304
391
  "%"
305
392
  ] })
306
393
  ] }) : null,
307
- cost && cost.total > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
394
+ cost && cost.total > 0 && !hiddenSet.has("cost") ? /* @__PURE__ */ jsxs(Fragment, { children: [
308
395
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
309
396
  /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
310
397
  "$",
@@ -432,7 +519,7 @@ function StatusBar({
432
519
  "s"
433
520
  ] })
434
521
  ] }) : null,
435
- git ? /* @__PURE__ */ jsxs(Fragment, { children: [
522
+ git && !hiddenSet.has("git") ? /* @__PURE__ */ jsxs(Fragment, { children: [
436
523
  yolo || startedAt != null || projectName || workingDir ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
437
524
  /* @__PURE__ */ jsxs(Text, { children: [
438
525
  /* @__PURE__ */ jsxs(Text, { color: "magenta", children: [
@@ -450,7 +537,7 @@ function StatusBar({
450
537
  ] })
451
538
  ] }) : null,
452
539
  sessionCount != null && sessionCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
453
- yolo || startedAt != null || projectName || workingDir || git ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
540
+ yolo || startedAt != null || projectName || workingDir || git && !hiddenSet.has("git") ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
454
541
  /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
455
542
  "\u29C9 ",
456
543
  sessionCount,
@@ -459,7 +546,7 @@ function StatusBar({
459
546
  ] })
460
547
  ] }) : null,
461
548
  toolCount != null ? /* @__PURE__ */ jsxs(Fragment, { children: [
462
- yolo || startedAt != null || projectName || workingDir || git || sessionCount ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
549
+ yolo || startedAt != null || projectName || workingDir || git && !hiddenSet.has("git") || sessionCount ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
463
550
  /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
464
551
  "\u{1F527} ",
465
552
  toolCount,
@@ -468,12 +555,12 @@ function StatusBar({
468
555
  ] })
469
556
  ] }) : null,
470
557
  tokenSavingMode ? /* @__PURE__ */ jsxs(Fragment, { children: [
471
- yolo || startedAt != null || projectName || workingDir || git || sessionCount || toolCount ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
558
+ yolo || startedAt != null || projectName || workingDir || git && !hiddenSet.has("git") || sessionCount || toolCount ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
472
559
  /* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: "\u{1F4BE} save" })
473
560
  ] }) : null
474
561
  ] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
475
562
  hasThirdLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
476
- todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) ? /* @__PURE__ */ jsxs(Text, { children: [
563
+ todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && !hiddenSet.has("todos") ? /* @__PURE__ */ jsxs(Text, { children: [
477
564
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "todos " }),
478
565
  todos.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
479
566
  "\u231B",
@@ -490,8 +577,8 @@ function StatusBar({
490
577
  todos.completed
491
578
  ] }) : null
492
579
  ] }) : null,
493
- plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) ? /* @__PURE__ */ jsxs(Fragment, { children: [
494
- todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
580
+ plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) && !hiddenSet.has("plan") ? /* @__PURE__ */ jsxs(Fragment, { children: [
581
+ todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && !hiddenSet.has("todos") ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
495
582
  /* @__PURE__ */ jsxs(Text, { children: [
496
583
  /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u{1F4CB} " }),
497
584
  plan.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
@@ -515,8 +602,8 @@ function StatusBar({
515
602
  ] }) : null
516
603
  ] })
517
604
  ] }) : null,
518
- hasTaskActivity ? /* @__PURE__ */ jsxs(Fragment, { children: [
519
- 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,
605
+ hasTaskActivity && !hiddenSet.has("tasks") ? /* @__PURE__ */ jsxs(Fragment, { children: [
606
+ todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && !hiddenSet.has("todos") || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) && !hiddenSet.has("plan") ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
520
607
  /* @__PURE__ */ jsxs(Text, { children: [
521
608
  /* @__PURE__ */ jsx(Text, { color: "magenta", children: "\u26A1 " }),
522
609
  tasks.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
@@ -550,8 +637,8 @@ function StatusBar({
550
637
  ] }) : null
551
638
  ] })
552
639
  ] }) : null,
553
- fleetHasActivity ? /* @__PURE__ */ jsxs(Fragment, { children: [
554
- 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,
640
+ fleetHasActivity && !hiddenSet.has("fleet") ? /* @__PURE__ */ jsxs(Fragment, { children: [
641
+ todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && !hiddenSet.has("todos") || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) && !hiddenSet.has("plan") ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
555
642
  fleet ? /* @__PURE__ */ jsxs(Text, { children: [
556
643
  /* @__PURE__ */ jsx(Text, { color: "blue", children: "\u{1F310} " }),
557
644
  fleet.running > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
@@ -581,12 +668,12 @@ function StatusBar({
581
668
  subagentCount === 1 ? "" : "s"
582
669
  ] })
583
670
  ] }) : null,
584
- hasBrainActivity && brain ? /* @__PURE__ */ jsxs(Fragment, { children: [
585
- 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,
671
+ showBrain ? /* @__PURE__ */ jsxs(Fragment, { children: [
672
+ todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && !hiddenSet.has("todos") || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) && !hiddenSet.has("plan") || hasTaskActivity && !hiddenSet.has("tasks") || fleetHasActivity && !hiddenSet.has("fleet") ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
586
673
  /* @__PURE__ */ jsx(BrainChip, { brain })
587
674
  ] }) : null,
588
- hasDebugStream && debugStreamStats ? /* @__PURE__ */ jsxs(Fragment, { children: [
589
- todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) || fleetHasActivity || hasBrainActivity ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
675
+ showDebugStream ? /* @__PURE__ */ jsxs(Fragment, { children: [
676
+ todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && !hiddenSet.has("todos") || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) && !hiddenSet.has("plan") || hasTaskActivity && !hiddenSet.has("tasks") || fleetHasActivity && !hiddenSet.has("fleet") || showBrain ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
590
677
  /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
591
678
  /* @__PURE__ */ jsx(Text, { bold: true, children: "\u{1F41B} stream" }),
592
679
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
@@ -609,8 +696,8 @@ function StatusBar({
609
696
  ] })
610
697
  ] })
611
698
  ] }) : null,
612
- hasEnhanceCountdown && enhanceCountdown != null ? /* @__PURE__ */ jsxs(Fragment, { children: [
613
- todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) || fleetHasActivity || hasBrainActivity || hasDebugStream ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
699
+ showEnhance ? /* @__PURE__ */ jsxs(Fragment, { children: [
700
+ todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && !hiddenSet.has("todos") || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) && !hiddenSet.has("plan") || hasTaskActivity && !hiddenSet.has("tasks") || fleetHasActivity && !hiddenSet.has("fleet") || showBrain || showDebugStream ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
614
701
  /* @__PURE__ */ jsxs(Text, { color: enhanceCountdown > 15 ? "green" : enhanceCountdown > 5 ? "yellow" : "red", children: [
615
702
  "\u23F3 auto-send in ",
616
703
  enhanceCountdown,
@@ -618,7 +705,7 @@ function StatusBar({
618
705
  ] })
619
706
  ] }) : null,
620
707
  hasNextStepsAutoSubmit && nextStepsAutoSubmitCountdown != null ? /* @__PURE__ */ jsxs(Fragment, { children: [
621
- 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,
708
+ todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && !hiddenSet.has("todos") || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) && !hiddenSet.has("plan") || hasTaskActivity && !hiddenSet.has("tasks") || fleetHasActivity && !hiddenSet.has("fleet") || showBrain || showDebugStream || showEnhance ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
622
709
  /* @__PURE__ */ jsxs(Text, { color: countdownColor, bold: true, children: [
623
710
  "\u23F3 ",
624
711
  nextStepsAutoSubmitCountdown,
@@ -631,7 +718,7 @@ function StatusBar({
631
718
  ] })
632
719
  ] }) : null
633
720
  ] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
634
- mailbox ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
721
+ mailbox && !hiddenSet.has("mailbox") ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
635
722
  mailbox.unread > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", bold: true, children: [
636
723
  "\u2709 ",
637
724
  mailbox.unread,
@@ -1138,6 +1225,36 @@ function FleetMonitor({
1138
1225
  ] }) : null
1139
1226
  ] });
1140
1227
  }
1228
+ var TOOL_GLYPHS = {
1229
+ file: "\u25A4",
1230
+ edit: "\u270E",
1231
+ search: "\u2315",
1232
+ folder: "\u25A3",
1233
+ terminal: "\u2318",
1234
+ web: "\u25C8",
1235
+ git: "\u2387",
1236
+ tree: "\u2630",
1237
+ code: "\u2699",
1238
+ test: "\u2697",
1239
+ package: "\u2B22",
1240
+ document: "\u2637",
1241
+ scaffold: "\u2731",
1242
+ todo: "\u2610",
1243
+ plan: "\u2756",
1244
+ task: "\u25AA",
1245
+ meta: "\u274F",
1246
+ index: "\u229B",
1247
+ json: "\u2317",
1248
+ diff: "\u2206",
1249
+ logs: "\u2261",
1250
+ settings: "\u2699",
1251
+ brain: "\u2726",
1252
+ fallback: "\u2022"
1253
+ };
1254
+ function getToolVisual(name) {
1255
+ const id = getToolIcon(name);
1256
+ return { glyph: TOOL_GLYPHS[id], color: TOOL_ICON_CONFIG[id].color };
1257
+ }
1141
1258
  var STATUS2 = {
1142
1259
  idle: { icon: "\u25CB", color: "gray" },
1143
1260
  running: { icon: "\u25B6", color: "yellow" },
@@ -1146,22 +1263,19 @@ var STATUS2 = {
1146
1263
  timeout: { icon: "\u23F1", color: "yellow" },
1147
1264
  stopped: { icon: "\u2298", color: "gray" }
1148
1265
  };
1149
- function isTerminal(status) {
1266
+ var IDLE_HIDE_MS = 6e4;
1267
+ var EMPTY_AGENTS_CLOSE_DELAY_MS = 7500;
1268
+ function isTerminalAgentStatus(status) {
1150
1269
  return status === "success" || status === "failed" || status === "timeout" || status === "stopped";
1151
1270
  }
1152
- var IDLE_HIDE_MS = 6e4;
1153
- function selectLiveAgents(all, now, idleHideMs = IDLE_HIDE_MS) {
1154
- const visible = all.filter((e) => {
1155
- if (isTerminal(e.status)) return false;
1156
- if (e.status === "running") return true;
1157
- return now - e.lastEventAt < idleHideMs;
1158
- });
1159
- return visible.sort((a, b) => {
1160
- if (a.status === "running" && b.status !== "running") return -1;
1161
- if (a.status !== "running" && b.status === "running") return 1;
1162
- if (a.status === "running") return a.startedAt - b.startedAt;
1163
- return b.lastEventAt - a.lastEventAt;
1164
- });
1271
+ function isLeaderEntry(entry) {
1272
+ return entry.id === "leader" || entry.name === "LEADER";
1273
+ }
1274
+ function selectLiveAgents(all, _now, _idleHideMs = IDLE_HIDE_MS) {
1275
+ const leader = all.find(isLeaderEntry);
1276
+ const activeSubagents = all.filter((entry) => !isLeaderEntry(entry) && !isTerminalAgentStatus(entry.status));
1277
+ const showLeader = leader !== void 0 && (leader.status !== "idle" || activeSubagents.length > 0);
1278
+ return all.filter((entry) => isLeaderEntry(entry) ? showLeader : activeSubagents.some((active) => active.id === entry.id));
1165
1279
  }
1166
1280
  function fmtTokens2(n) {
1167
1281
  if (n < 1e3) return String(n);
@@ -1173,6 +1287,86 @@ function snippet(s2, max = 72) {
1173
1287
  if (oneLine2.length <= max) return oneLine2;
1174
1288
  return `${oneLine2.slice(0, max - 1)}\u2026`;
1175
1289
  }
1290
+ function fmtShortDuration(ms) {
1291
+ if (ms < 1e3) return `${Math.max(0, Math.round(ms))}ms`;
1292
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(ms < 1e4 ? 1 : 0)}s`;
1293
+ const m = Math.floor(ms / 6e4);
1294
+ const s2 = Math.floor(ms % 6e4 / 1e3);
1295
+ return `${m}m${s2.toString().padStart(2, "0")}s`;
1296
+ }
1297
+ function fmtSignedTokens(n) {
1298
+ return n <= 0 ? "0" : fmtTokens2(n);
1299
+ }
1300
+ function fmtOptionalTimestamp(ms) {
1301
+ if (!ms || ms <= 0) return "unknown";
1302
+ return new Date(ms).toLocaleTimeString("en-US", { hour12: false });
1303
+ }
1304
+ function formatContextRunway(tokens, maxTokens) {
1305
+ if (!tokens || !maxTokens || maxTokens <= 0) return "ctx unknown";
1306
+ const left = Math.max(0, maxTokens - tokens);
1307
+ return `${fmtTokens2(tokens)}/${fmtTokens2(maxTokens)} \xB7 ${fmtSignedTokens(left)} free`;
1308
+ }
1309
+ function formatRecentToolChip(tool) {
1310
+ const status = tool.ok === false ? "\u2717" : "\u2713";
1311
+ const duration = typeof tool.durationMs === "number" ? ` ${fmtShortDuration(tool.durationMs)}` : "";
1312
+ const lines = typeof tool.outputLines === "number" && tool.outputLines > 0 ? ` ${tool.outputLines}L` : "";
1313
+ const bytes = typeof tool.outputBytes === "number" && tool.outputBytes > 0 ? ` ${fmtTokens2(tool.outputBytes)}B` : "";
1314
+ return `${status} ${tool.name}${duration}${lines}${bytes}`;
1315
+ }
1316
+ function formatAgentDetailHeader(entry) {
1317
+ return entry.name || entry.id;
1318
+ }
1319
+ function agentRisk(entry) {
1320
+ const pct = entry.ctxPct ?? 0;
1321
+ if (entry.budgetWarning || entry.failureReason || pct >= 0.9) return "critical";
1322
+ if (pct >= 0.75 || (entry.extensions ?? 0) > 0) return "hot";
1323
+ if (entry.status === "running" || pct >= 0.55) return "busy";
1324
+ return "calm";
1325
+ }
1326
+ function riskMeta(risk) {
1327
+ switch (risk) {
1328
+ case "critical":
1329
+ return { icon: "\u25C6", color: "red", label: "critical" };
1330
+ case "hot":
1331
+ return { icon: "\u25B2", color: "yellow", label: "hot" };
1332
+ case "busy":
1333
+ return { icon: "\u25CF", color: "cyan", label: "busy" };
1334
+ case "calm":
1335
+ return { icon: "\u25CB", color: "green", label: "calm" };
1336
+ }
1337
+ }
1338
+ function currentAction(entry, now) {
1339
+ if (entry.currentTool) return `\u2192 ${entry.currentTool.name} ${fmtShortDuration(now - entry.currentTool.startedAt)}`;
1340
+ if (entry.status === "running") return "thinking";
1341
+ const last = entry.recentTools[entry.recentTools.length - 1];
1342
+ if (last) return `last ${last.name}`;
1343
+ const msg = entry.recentMessages[entry.recentMessages.length - 1];
1344
+ if (msg) return `msg ${snippet(msg.text, 34)}`;
1345
+ return "standing by";
1346
+ }
1347
+ function selectAgentDetail(live, selectedId) {
1348
+ return live.find((entry) => entry.id === selectedId) ?? live.find(isLeaderEntry) ?? live[0];
1349
+ }
1350
+ function nextEmptyAgentsCloseStartedAt(liveCount, now, currentStartedAt) {
1351
+ if (liveCount > 0) return void 0;
1352
+ return currentStartedAt ?? now;
1353
+ }
1354
+ function shouldCloseEmptyAgentsMonitor(liveCount, now, emptyStartedAt, delayMs = EMPTY_AGENTS_CLOSE_DELAY_MS) {
1355
+ return liveCount === 0 && emptyStartedAt !== void 0 && now - emptyStartedAt >= delayMs;
1356
+ }
1357
+ function selectHotAgent(entries) {
1358
+ const riskScore = { critical: 3, hot: 2, busy: 1, calm: 0 };
1359
+ return [...entries].sort((a, b) => {
1360
+ const ar = riskScore[agentRisk(a)];
1361
+ const br = riskScore[agentRisk(b)];
1362
+ if (br !== ar) return br - ar;
1363
+ const bp = b.ctxPct ?? 0;
1364
+ const ap = a.ctxPct ?? 0;
1365
+ if (bp !== ap) return bp - ap;
1366
+ if (b.toolCalls !== a.toolCalls) return b.toolCalls - a.toolCalls;
1367
+ return b.lastEventAt - a.lastEventAt;
1368
+ }).at(0);
1369
+ }
1176
1370
  function ContextBar({
1177
1371
  pct,
1178
1372
  tokens,
@@ -1201,10 +1395,13 @@ function AgentRow({
1201
1395
  const s2 = STATUS2[entry.status];
1202
1396
  const elapsed = entry.status === "running" ? fmtElapsed(Math.max(0, now - entry.startedAt)) : entry.status;
1203
1397
  const modelLabel = fmtModelLabel(entry.provider, entry.model);
1398
+ const activity = sparkline(bucketActivity(entry.recentTools, now, 10, 3e3));
1399
+ const risk = riskMeta(agentRisk(entry));
1204
1400
  const ctxCostStr = entry.ctxCost !== void 0 && entry.ctxCost > 0 ? ` ctx ${entry.ctxCost.toFixed(4)}` : "";
1205
1401
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1206
1402
  /* @__PURE__ */ jsx(Text, { color: selected ? "magenta" : "gray", children: selected ? "\u25B6" : " " }),
1207
1403
  /* @__PURE__ */ jsx(Text, { color: s2.color, bold: true, children: s2.icon }),
1404
+ /* @__PURE__ */ jsx(Text, { color: risk.color, children: risk.icon }),
1208
1405
  /* @__PURE__ */ jsx(Text, { bold: selected, ...selected ? { color: "magenta" } : {}, children: entry.name }),
1209
1406
  modelLabel ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: modelLabel }) : null,
1210
1407
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
@@ -1214,17 +1411,10 @@ function AgentRow({
1214
1411
  entry.toolCalls,
1215
1412
  "t"
1216
1413
  ] }),
1414
+ activity ? /* @__PURE__ */ jsx(Text, { color: "green", children: activity }) : null,
1217
1415
  entry.ctxPct !== void 0 ? /* @__PURE__ */ jsx(ContextBar, { pct: entry.ctxPct, tokens: entry.ctxTokens, maxTokens: entry.ctxMaxTokens }) : null,
1218
1416
  ctxCostStr ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: ctxCostStr }) : null,
1219
- entry.status === "running" && entry.currentTool ? /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
1220
- "\u2192 ",
1221
- entry.currentTool.name,
1222
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1223
- " (",
1224
- Math.max(0, now - entry.currentTool.startedAt),
1225
- "ms)"
1226
- ] })
1227
- ] }) : null,
1417
+ /* @__PURE__ */ jsx(Text, { color: entry.currentTool ? "cyan" : "gray", children: currentAction(entry, now) }),
1228
1418
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: elapsed }),
1229
1419
  entry.extensions && entry.extensions > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1230
1420
  "\u26A1\xD7",
@@ -1244,162 +1434,280 @@ function AgentDetail({
1244
1434
  const lastTool = entry.recentTools[entry.recentTools.length - 1];
1245
1435
  const lastMessage = entry.recentMessages[entry.recentMessages.length - 1];
1246
1436
  const streamTail = entry.streamingText ? snippet(entry.streamingText.slice(-160)) : "";
1247
- const modelLabel = fmtModelLabel(entry.provider, entry.model);
1248
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingLeft: 4, borderStyle: "single", borderColor: "magenta", borderLeft: true, children: [
1249
- spark || lastTool ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1250
- /* @__PURE__ */ jsx(Text, { color: "green", children: spark || "" }),
1251
- lastTool ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1252
- "last: ",
1253
- lastTool.name,
1254
- typeof lastTool.durationMs === "number" ? ` ${lastTool.durationMs}ms` : "",
1255
- lastTool.ok === false ? " \u2717" : ""
1256
- ] }) : null
1257
- ] }) : null,
1258
- !modelLabel && (entry.provider || entry.model) ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1259
- "provider: ",
1260
- entry.provider || "(leader)",
1261
- " \xB7 model: ",
1262
- entry.model || "\u2014"
1263
- ] }) }) : null,
1264
- entry.cost > 0 || entry.ctxCost && entry.ctxCost > 0 ? /* @__PURE__ */ jsxs(Box, { children: [
1265
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "cost: " }),
1266
- entry.cost > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
1267
- "$",
1268
- entry.cost.toFixed(4),
1269
- " total"
1270
- ] }) : null,
1271
- entry.cost > 0 && entry.ctxCost && entry.ctxCost > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }) : null,
1272
- entry.ctxCost && entry.ctxCost > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1273
- "$",
1274
- entry.ctxCost.toFixed(4),
1275
- " ctx"
1276
- ] }) : null
1277
- ] }) : null,
1278
- entry.status === "running" && streamTail ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1279
- ">",
1280
- " ",
1281
- streamTail
1282
- ] }) }) : null,
1283
- (entry.status !== "running" || !streamTail) && lastMessage ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1284
- "msg: ",
1285
- snippet(lastMessage.text)
1286
- ] }) }) : null,
1287
- entry.budgetWarning ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1288
- "\u26A1 ",
1289
- entry.budgetWarning.kind,
1290
- " ",
1291
- entry.budgetWarning.used,
1292
- "/",
1293
- entry.budgetWarning.limit,
1294
- " \u2014 extending"
1295
- ] }) }) : null,
1296
- entry.failureReason && entry.status !== "success" ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: "red", children: [
1297
- "\u2717 ",
1298
- entry.failureReason
1299
- ] }) }) : null
1300
- ] });
1437
+ const risk = riskMeta(agentRisk(entry));
1438
+ const ctxLine = formatContextRunway(entry.ctxTokens, entry.ctxMaxTokens);
1439
+ const modelLabel = fmtModelLabel(entry.provider, entry.model) || [entry.provider, entry.model].filter(Boolean).join("/");
1440
+ return /* @__PURE__ */ jsx(Box, { alignSelf: "stretch", flexDirection: "column", width: "100%", flexGrow: 1, children: /* @__PURE__ */ jsxs(
1441
+ Box,
1442
+ {
1443
+ alignSelf: "stretch",
1444
+ flexDirection: "column",
1445
+ width: "100%",
1446
+ flexGrow: 1,
1447
+ paddingX: 1,
1448
+ borderStyle: "single",
1449
+ borderColor: "magenta",
1450
+ children: [
1451
+ /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 1, children: /* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: formatAgentDetailHeader(entry) }) }),
1452
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1453
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "id" }),
1454
+ /* @__PURE__ */ jsx(Text, { children: entry.id }),
1455
+ modelLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [
1456
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 model" }),
1457
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: modelLabel })
1458
+ ] }) : null,
1459
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 status" }),
1460
+ /* @__PURE__ */ jsxs(Text, { color: STATUS2[entry.status].color, children: [
1461
+ STATUS2[entry.status].icon,
1462
+ " ",
1463
+ entry.status
1464
+ ] })
1465
+ ] }),
1466
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1467
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "runtime" }),
1468
+ /* @__PURE__ */ jsx(Text, { children: fmtElapsed(Math.max(0, now - entry.startedAt)) }),
1469
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 started" }),
1470
+ /* @__PURE__ */ jsx(Text, { children: fmtOptionalTimestamp(entry.startedAt) }),
1471
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 last event" }),
1472
+ /* @__PURE__ */ jsxs(Text, { children: [
1473
+ fmtShortDuration(Math.max(0, now - entry.lastEventAt)),
1474
+ " ago"
1475
+ ] }),
1476
+ entry.extensions && entry.extensions > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1477
+ "\xB7 extensions \u26A1\xD7",
1478
+ entry.extensions
1479
+ ] }) : null
1480
+ ] }),
1481
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1482
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "throughput" }),
1483
+ /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
1484
+ entry.iterations,
1485
+ " iterations"
1486
+ ] }),
1487
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
1488
+ /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
1489
+ entry.toolCalls,
1490
+ " tools"
1491
+ ] }),
1492
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 current" }),
1493
+ /* @__PURE__ */ jsx(Text, { color: entry.currentTool ? "cyan" : "gray", children: currentAction(entry, now) })
1494
+ ] }),
1495
+ spark || lastTool ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1496
+ /* @__PURE__ */ jsx(Text, { color: "green", children: spark || "" }),
1497
+ lastTool ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1498
+ "last: ",
1499
+ lastTool.name,
1500
+ typeof lastTool.durationMs === "number" ? ` ${lastTool.durationMs}ms` : "",
1501
+ lastTool.ok === false ? " \u2717" : ""
1502
+ ] }) : null
1503
+ ] }) : null,
1504
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1505
+ /* @__PURE__ */ jsxs(Text, { color: risk.color, children: [
1506
+ risk.icon,
1507
+ " ",
1508
+ risk.label
1509
+ ] }),
1510
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "ctx" }),
1511
+ /* @__PURE__ */ jsx(Text, { color: risk.color, children: ctxLine }),
1512
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1513
+ "idle ",
1514
+ fmtShortDuration(Math.max(0, now - entry.lastEventAt))
1515
+ ] })
1516
+ ] }),
1517
+ entry.cost > 0 || entry.ctxCost && entry.ctxCost > 0 ? /* @__PURE__ */ jsxs(Box, { children: [
1518
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "cost: " }),
1519
+ entry.cost > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
1520
+ "$",
1521
+ entry.cost.toFixed(4),
1522
+ " total"
1523
+ ] }) : null,
1524
+ entry.cost > 0 && entry.ctxCost && entry.ctxCost > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }) : null,
1525
+ entry.ctxCost && entry.ctxCost > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1526
+ "$",
1527
+ entry.ctxCost.toFixed(4),
1528
+ " ctx"
1529
+ ] }) : null
1530
+ ] }) : null,
1531
+ entry.transcriptPath ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1532
+ "transcript: ",
1533
+ snippet(entry.transcriptPath, 120)
1534
+ ] }) }) : null,
1535
+ entry.recentTools.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1536
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "recent" }),
1537
+ entry.recentTools.slice(-4).map((tool, i) => {
1538
+ const visual = getToolVisual(tool.name);
1539
+ return (
1540
+ // biome-ignore lint/suspicious/noArrayIndexKey: recent tool entries do not carry stable ids.
1541
+ /* @__PURE__ */ jsx(Text, { color: tool.ok === false ? "red" : visual.color, children: `\u2039${visual.glyph} ${formatRecentToolChip(tool)}\u203A` }, `${tool.name}-${tool.at}-${i}`)
1542
+ );
1543
+ })
1544
+ ] }) : null,
1545
+ entry.status === "running" && streamTail ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1546
+ ">",
1547
+ " ",
1548
+ streamTail
1549
+ ] }) }) : null,
1550
+ (entry.status !== "running" || !streamTail) && lastMessage ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1551
+ "msg: ",
1552
+ snippet(lastMessage.text)
1553
+ ] }) }) : null,
1554
+ entry.budgetWarning ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1555
+ "\u26A1 ",
1556
+ entry.budgetWarning.kind,
1557
+ " ",
1558
+ entry.budgetWarning.used,
1559
+ "/",
1560
+ entry.budgetWarning.limit,
1561
+ " \u2014 extending"
1562
+ ] }) }) : null,
1563
+ entry.failureReason && entry.status !== "success" ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: "red", children: [
1564
+ "\u2717 ",
1565
+ entry.failureReason
1566
+ ] }) }) : null
1567
+ ]
1568
+ }
1569
+ ) });
1301
1570
  }
1302
1571
  function AgentsMonitor({
1303
1572
  entries,
1304
1573
  totalCost,
1305
1574
  leaderCost = 0,
1306
1575
  totalTokens,
1307
- nowTick
1576
+ nowTick,
1577
+ onClose
1308
1578
  }) {
1309
1579
  const all = Object.values(entries);
1310
1580
  const grandCost = leaderCost + totalCost;
1311
- const live = useMemo(() => selectLiveAgents(all, nowTick), [all, nowTick]);
1312
- const [selectedIndex, setSelectedIndex] = useState(0);
1313
- const safeIndex = Math.min(selectedIndex, Math.max(0, live.length - 1));
1581
+ const live = useMemo(() => selectLiveAgents(all), [all, nowTick]);
1582
+ const [selectedId, setSelectedId] = useState(void 0);
1583
+ const [emptyAgentsCloseStartedAt, setEmptyAgentsCloseStartedAt] = useState(void 0);
1584
+ useEffect(() => {
1585
+ const nextStartedAt = nextEmptyAgentsCloseStartedAt(live.length, nowTick, emptyAgentsCloseStartedAt);
1586
+ if (nextStartedAt !== emptyAgentsCloseStartedAt) setEmptyAgentsCloseStartedAt(nextStartedAt);
1587
+ if (shouldCloseEmptyAgentsMonitor(live.length, nowTick, nextStartedAt)) onClose?.();
1588
+ }, [emptyAgentsCloseStartedAt, live.length, nowTick, onClose]);
1589
+ const selected = selectAgentDetail(live, selectedId);
1590
+ const selectedIndex = selected ? live.findIndex((entry) => entry.id === selected.id) : -1;
1314
1591
  useInput((_input, key) => {
1592
+ if (live.length === 0) return;
1315
1593
  if (key.upArrow) {
1316
- setSelectedIndex((prev) => Math.max(0, prev - 1));
1594
+ const next = Math.max(0, selectedIndex - 1);
1595
+ setSelectedId(live[next]?.id);
1317
1596
  } else if (key.downArrow) {
1318
- setSelectedIndex((prev) => Math.min(live.length - 1, prev + 1));
1597
+ const next = Math.min(live.length - 1, selectedIndex + 1);
1598
+ setSelectedId(live[next]?.id);
1319
1599
  }
1320
1600
  });
1321
1601
  const running = live.filter((e) => e.status === "running").length;
1322
1602
  const totalDone = all.filter((e) => e.status === "success").length;
1323
1603
  const totalFailed = all.filter((e) => e.status === "failed" || e.status === "timeout").length;
1324
- const hiddenIdle = all.filter(
1604
+ const staleIdle = all.filter(
1325
1605
  (e) => e.status === "idle" && nowTick - e.lastEventAt >= IDLE_HIDE_MS
1326
1606
  ).length;
1327
- const selected = live[safeIndex];
1328
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, children: [
1329
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1330
- /* @__PURE__ */ jsx(Text, { bold: true, color: "magenta", children: "AGENTS \xB7 LIVE" }),
1331
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
1332
- /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1333
- "\u25B6",
1334
- running
1335
- ] }),
1336
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
1337
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "done" }),
1338
- /* @__PURE__ */ jsxs(Text, { color: "green", children: [
1339
- "\u2713",
1340
- totalDone
1341
- ] }),
1342
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
1343
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "failed" }),
1344
- totalFailed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
1345
- "\u2717",
1346
- totalFailed
1347
- ] }) : null,
1348
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 \u2191\u2193 nav \xB7 Ctrl+G / F3 close" })
1349
- ] }),
1350
- live.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1351
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "models" }),
1352
- (() => {
1353
- const seen = /* @__PURE__ */ new Map();
1354
- for (const e of live) {
1355
- if (e.model) seen.set(e.name ?? e.id, `${e.provider ?? "?"}/${e.model}`);
1356
- }
1357
- return [...seen.entries()].slice(0, 4).map(([name, mod]) => /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1358
- name,
1359
- ":",
1360
- mod
1361
- ] }, name));
1362
- })()
1363
- ] }) : null,
1364
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1365
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "shown" }),
1366
- /* @__PURE__ */ jsx(Text, { color: "magenta", children: live.length }),
1367
- totalTokens ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1368
- " ",
1369
- fmtTokens2(totalTokens.input),
1370
- "\u2191 ",
1371
- fmtTokens2(totalTokens.output),
1372
- "\u2193"
1373
- ] }) : null,
1374
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "total" }),
1375
- /* @__PURE__ */ jsxs(Text, { color: "green", bold: true, children: [
1376
- "$",
1377
- grandCost.toFixed(4)
1378
- ] }),
1379
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1380
- "(leader $",
1381
- leaderCost.toFixed(4),
1382
- " \xB7 fleet $",
1383
- totalCost.toFixed(4),
1384
- ")"
1385
- ] }),
1386
- hiddenIdle > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1387
- "\xB7 ",
1388
- hiddenIdle,
1389
- " idle hidden"
1390
- ] }) : null
1391
- ] }),
1392
- live.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No live agents \u2014 spawn with /spawn or /fleet dispatch." }) : null,
1393
- live.map((e) => /* @__PURE__ */ jsx(AgentRow, { entry: e, now: nowTick, selected: e.id === selected?.id }, e.id)),
1394
- selected ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
1395
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, paddingLeft: 2, children: [
1396
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500" }),
1397
- /* @__PURE__ */ jsx(Text, { color: "magenta", children: selected.name }),
1398
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "details \u2500\u2500\u2500" })
1399
- ] }),
1400
- /* @__PURE__ */ jsx(AgentDetail, { entry: selected, now: nowTick })
1401
- ] }) : null
1402
- ] });
1607
+ const hotAgent = selectHotAgent(live);
1608
+ const pressure = live.length > 0 ? live.reduce((max, e) => Math.max(max, e.ctxPct ?? 0), 0) : 0;
1609
+ const toolCalls = live.reduce((sum, e) => sum + e.toolCalls, 0);
1610
+ const iterations = live.reduce((sum, e) => sum + e.iterations, 0);
1611
+ return /* @__PURE__ */ jsxs(
1612
+ Box,
1613
+ {
1614
+ alignSelf: "stretch",
1615
+ flexDirection: "column",
1616
+ width: "100%",
1617
+ borderStyle: "round",
1618
+ borderColor: "magenta",
1619
+ paddingX: 1,
1620
+ flexGrow: 1,
1621
+ children: [
1622
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1623
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "magenta", children: "AGENTS \xB7 LIVE" }),
1624
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
1625
+ /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1626
+ "\u25B6",
1627
+ running
1628
+ ] }),
1629
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
1630
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "done" }),
1631
+ /* @__PURE__ */ jsxs(Text, { color: "green", children: [
1632
+ "\u2713",
1633
+ totalDone
1634
+ ] }),
1635
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
1636
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "failed" }),
1637
+ totalFailed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
1638
+ "\u2717",
1639
+ totalFailed
1640
+ ] }) : null,
1641
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 \u2191\u2193 nav \xB7 Ctrl+G / F3 close" })
1642
+ ] }),
1643
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1644
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "pulse" }),
1645
+ /* @__PURE__ */ jsxs(Text, { color: pressure >= 0.9 ? "red" : pressure >= 0.75 ? "yellow" : "green", children: [
1646
+ "max ctx ",
1647
+ Math.round(pressure * 100),
1648
+ "%"
1649
+ ] }),
1650
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 hot" }),
1651
+ hotAgent ? /* @__PURE__ */ jsxs(Text, { color: riskMeta(agentRisk(hotAgent)).color, children: [
1652
+ hotAgent.name,
1653
+ " ",
1654
+ hotAgent.ctxPct !== void 0 ? `${Math.round(hotAgent.ctxPct * 100)}%` : ""
1655
+ ] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "none" }),
1656
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 throughput" }),
1657
+ /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
1658
+ iterations,
1659
+ "L/",
1660
+ toolCalls,
1661
+ "t"
1662
+ ] })
1663
+ ] }),
1664
+ live.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1665
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "models" }),
1666
+ (() => {
1667
+ const seen = /* @__PURE__ */ new Map();
1668
+ for (const e of live) {
1669
+ if (e.model) seen.set(e.name ?? e.id, `${e.provider ?? "?"}/${e.model}`);
1670
+ }
1671
+ return [...seen.entries()].slice(0, 4).map(([name, mod]) => /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1672
+ name,
1673
+ ":",
1674
+ mod
1675
+ ] }, name));
1676
+ })()
1677
+ ] }) : null,
1678
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1679
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "shown" }),
1680
+ /* @__PURE__ */ jsx(Text, { color: "magenta", children: live.length }),
1681
+ totalTokens ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1682
+ " ",
1683
+ fmtTokens2(totalTokens.input),
1684
+ "\u2191 ",
1685
+ fmtTokens2(totalTokens.output),
1686
+ "\u2193"
1687
+ ] }) : null,
1688
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "total" }),
1689
+ /* @__PURE__ */ jsxs(Text, { color: "green", bold: true, children: [
1690
+ "$",
1691
+ grandCost.toFixed(4)
1692
+ ] }),
1693
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1694
+ "(leader $",
1695
+ leaderCost.toFixed(4),
1696
+ " \xB7 fleet $",
1697
+ totalCost.toFixed(4),
1698
+ ")"
1699
+ ] }),
1700
+ staleIdle > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1701
+ "\xB7 ",
1702
+ staleIdle,
1703
+ " idle stale"
1704
+ ] }) : null
1705
+ ] }),
1706
+ live.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No live agents \u2014 spawn with /spawn or /fleet dispatch." }) : null,
1707
+ live.map((e) => e.id === selected?.id ? /* @__PURE__ */ jsx(AgentDetail, { entry: e, now: nowTick }, e.id) : /* @__PURE__ */ jsx(AgentRow, { entry: e, now: nowTick, selected: false }, e.id))
1708
+ ]
1709
+ }
1710
+ );
1403
1711
  }
1404
1712
  var AUTONOMY_OPTIONS = [
1405
1713
  {
@@ -1859,6 +2167,139 @@ function FleetPanel({
1859
2167
  ] }) : null
1860
2168
  ] });
1861
2169
  }
2170
+
2171
+ // src/f-key-panels.ts
2172
+ var F_KEY_PANEL_ENTRIES = [
2173
+ {
2174
+ key: 1,
2175
+ label: "Project switcher",
2176
+ action: "projectPickerOpen",
2177
+ helpKeys: "F1",
2178
+ helpDescription: "project switcher (also /project)"
2179
+ },
2180
+ {
2181
+ key: 2,
2182
+ label: "Fleet orchestration monitor",
2183
+ action: "toggleMonitor",
2184
+ helpKeys: "Ctrl+F / F2",
2185
+ helpDescription: "fleet orchestration monitor"
2186
+ },
2187
+ {
2188
+ key: 3,
2189
+ label: "Agents live monitor",
2190
+ action: "toggleAgentsMonitor",
2191
+ helpKeys: "Ctrl+G / F3",
2192
+ helpDescription: "agents live monitor"
2193
+ },
2194
+ {
2195
+ key: 4,
2196
+ label: "Worktree monitor",
2197
+ action: "toggleWorktreeMonitor",
2198
+ helpKeys: "Ctrl+T / F4",
2199
+ helpDescription: "worktree monitor"
2200
+ },
2201
+ {
2202
+ key: 5,
2203
+ label: "Plan panel",
2204
+ action: "togglePlanPanel",
2205
+ helpKeys: "F5",
2206
+ helpDescription: "plan panel"
2207
+ },
2208
+ {
2209
+ key: 6,
2210
+ label: "Todos monitor overlay",
2211
+ action: "toggleTodosMonitor",
2212
+ helpKeys: "F6",
2213
+ helpDescription: "todos monitor overlay"
2214
+ },
2215
+ {
2216
+ key: 7,
2217
+ label: "Queue panel",
2218
+ action: "toggleQueuePanel",
2219
+ helpKeys: "F7",
2220
+ helpDescription: "queue panel"
2221
+ },
2222
+ {
2223
+ key: 8,
2224
+ label: "Process list overlay",
2225
+ action: "toggleProcessList",
2226
+ helpKeys: "F8",
2227
+ helpDescription: "process list overlay"
2228
+ },
2229
+ {
2230
+ key: 9,
2231
+ label: "Goal panel",
2232
+ action: "toggleGoalPanel",
2233
+ helpKeys: "F9",
2234
+ helpDescription: "goal panel"
2235
+ },
2236
+ {
2237
+ key: 10,
2238
+ label: "Live sessions panel",
2239
+ action: "toggleSessionsPanel",
2240
+ helpKeys: "F10",
2241
+ helpDescription: "live sessions panel"
2242
+ },
2243
+ {
2244
+ key: 11,
2245
+ label: "Coordinator monitor",
2246
+ action: "toggleCoordinatorMonitor",
2247
+ helpKeys: "F11",
2248
+ helpDescription: "coordinator monitor"
2249
+ },
2250
+ {
2251
+ key: 12,
2252
+ label: "Status line picker",
2253
+ action: "statuslineOpen",
2254
+ helpKeys: "F12",
2255
+ helpDescription: "status line picker"
2256
+ }
2257
+ ];
2258
+ var PAYLOAD_FREE_ACTIONS = /* @__PURE__ */ new Set([
2259
+ "toggleMonitor",
2260
+ "toggleAgentsMonitor",
2261
+ "toggleWorktreeMonitor",
2262
+ "togglePlanPanel",
2263
+ "toggleTodosMonitor",
2264
+ "toggleQueuePanel",
2265
+ "toggleProcessList",
2266
+ "toggleGoalPanel",
2267
+ "toggleSessionsPanel",
2268
+ "toggleCoordinatorMonitor"
2269
+ ]);
2270
+ function actionForFKeyPanel(entry, hiddenItems = []) {
2271
+ if (entry.action === "projectPickerOpen") return null;
2272
+ if (entry.action === "statuslineOpen") {
2273
+ return { type: "statuslineOpen", hiddenItems: [...hiddenItems] };
2274
+ }
2275
+ if (PAYLOAD_FREE_ACTIONS.has(entry.action)) {
2276
+ return { type: entry.action };
2277
+ }
2278
+ return null;
2279
+ }
2280
+ function FKeyPicker({ selected }) {
2281
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, flexShrink: 0, children: [
2282
+ /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 F-Key Panels \u2501\u2501" }),
2283
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191\u2193 navigate \xB7 Enter open \xB7 Esc close" }),
2284
+ F_KEY_PANEL_ENTRIES.map((entry) => {
2285
+ const idx = entry.key - 1;
2286
+ const isSelected = idx === selected;
2287
+ const marker = isSelected ? "\u25B8" : " ";
2288
+ const labelColor = isSelected ? "cyan" : void 0;
2289
+ return /* @__PURE__ */ jsxs(Box, { children: [
2290
+ /* @__PURE__ */ jsx(Box, { width: 4, flexShrink: 0, children: /* @__PURE__ */ jsx(Text, { color: "dimColor", children: marker }) }),
2291
+ /* @__PURE__ */ jsxs(Text, { color: "dimColor", children: [
2292
+ "F",
2293
+ entry.key
2294
+ ] }),
2295
+ /* @__PURE__ */ jsx(Text, { children: " " }),
2296
+ /* @__PURE__ */ jsx(Text, { color: labelColor, children: entry.label })
2297
+ ] }, entry.key);
2298
+ }),
2299
+ selected > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191 Scroll up" }) : null,
2300
+ selected < 11 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2193 Scroll down" }) : null
2301
+ ] });
2302
+ }
1862
2303
  function fmtTime(iso) {
1863
2304
  const d = new Date(iso);
1864
2305
  const now = Date.now();
@@ -1956,36 +2397,6 @@ function MailboxPanel({
1956
2397
  /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "/mailbox \u2014 Esc to close" }) })
1957
2398
  ] });
1958
2399
  }
1959
- var TOOL_GLYPHS = {
1960
- file: "\u25A4",
1961
- edit: "\u270E",
1962
- search: "\u2315",
1963
- folder: "\u25A3",
1964
- terminal: "\u25B8",
1965
- web: "\u25C8",
1966
- git: "\u2387",
1967
- tree: "\u2630",
1968
- code: "\u2699",
1969
- test: "\u2697",
1970
- package: "\u2B22",
1971
- document: "\u2637",
1972
- scaffold: "\u2731",
1973
- todo: "\u2610",
1974
- plan: "\u2756",
1975
- task: "\u25AA",
1976
- meta: "\u274F",
1977
- index: "\u229B",
1978
- json: "\u2317",
1979
- diff: "\u2206",
1980
- logs: "\u2261",
1981
- settings: "\u2699",
1982
- brain: "\u2726",
1983
- fallback: "\u2022"
1984
- };
1985
- function getToolVisual(name) {
1986
- const id = getToolIcon(name);
1987
- return { glyph: TOOL_GLYPHS[id], color: TOOL_ICON_CONFIG[id].color };
1988
- }
1989
2400
  function helpSections() {
1990
2401
  const nav = [];
1991
2402
  nav.push(
@@ -1997,16 +2408,10 @@ function helpSections() {
1997
2408
  {
1998
2409
  title: "Monitors",
1999
2410
  entries: [
2000
- { keys: "F1", desc: "project switcher (also /project)" },
2001
- { keys: "Ctrl+F / F2", desc: "fleet orchestration monitor" },
2002
- { keys: "Ctrl+G / F3", desc: "agents live monitor" },
2003
- { keys: "Ctrl+T / F4", desc: "worktree monitor" },
2004
- { keys: "F5", desc: "autonomy settings (also Ctrl+S)" },
2005
- { keys: "F6", desc: "todos monitor overlay" },
2006
- { keys: "F7", desc: "queue panel" },
2007
- { keys: "F8", desc: "process list overlay" },
2008
- { keys: "F9", desc: "goal panel" },
2009
- { keys: "F10", desc: "live sessions panel" },
2411
+ ...F_KEY_PANEL_ENTRIES.map((entry) => ({
2412
+ keys: entry.helpKeys,
2413
+ desc: entry.helpDescription
2414
+ })),
2010
2415
  { keys: "Esc", desc: "close the open monitor / overlay" }
2011
2416
  ]
2012
2417
  },
@@ -5433,21 +5838,33 @@ function ProcessListMonitor() {
5433
5838
  const all = registry.list();
5434
5839
  const stats = registry.stats();
5435
5840
  const safeIndex = Math.min(selectedIndex, Math.max(0, all.length - 1));
5841
+ if (safeIndex !== selectedIndex) {
5842
+ setSelectedIndex(safeIndex);
5843
+ }
5436
5844
  const selected = all[safeIndex];
5437
5845
  const now = Date.now();
5438
5846
  const running = all.filter((p) => !p.killed).length;
5439
5847
  const b = stats.breaker;
5440
5848
  const breakerState = b.state === "closed" ? "\u{1F7E2} closed" : b.state === "half-open" ? "\u{1F7E1} half-open" : "\u{1F534} open";
5849
+ const pageSize = Math.max(1, Math.floor(all.length / 2));
5441
5850
  useInput((input, key) => {
5442
5851
  if (key.upArrow) {
5443
5852
  setSelectedIndex((prev) => Math.max(0, prev - 1));
5444
5853
  } else if (key.downArrow) {
5445
5854
  setSelectedIndex((prev) => Math.min(all.length - 1, prev + 1));
5855
+ } else if (key.pageUp) {
5856
+ setSelectedIndex((prev) => Math.max(0, prev - pageSize));
5857
+ } else if (key.pageDown) {
5858
+ setSelectedIndex((prev) => Math.min(all.length - 1, prev + pageSize));
5859
+ } else if (key.home || key.ctrl && input === "a" || input === "g") {
5860
+ setSelectedIndex(0);
5861
+ } else if (key.end || key.ctrl && input === "e" || input === "G") {
5862
+ setSelectedIndex(Math.max(0, all.length - 1));
5446
5863
  } else if (key.return && selected) {
5447
5864
  getProcessRegistry().kill(selected.pid);
5448
5865
  } else if (key.delete && selected) {
5449
5866
  getProcessRegistry().kill(selected.pid, { force: true });
5450
- } else if (input === "a") {
5867
+ } else if (input === "a" && !key.ctrl) {
5451
5868
  getProcessRegistry().killAll();
5452
5869
  } else if (input === "A") {
5453
5870
  getProcessRegistry().killAll({ force: true });
@@ -5493,6 +5910,13 @@ function ProcessListMonitor() {
5493
5910
  /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, marginTop: 1, children: [
5494
5911
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191\u2193 nav" }),
5495
5912
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
5913
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "PgUp/PgDn page" }),
5914
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
5915
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Home/Ctrl+A/g first" }),
5916
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
5917
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "End/Ctrl+E/G last" })
5918
+ ] }),
5919
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
5496
5920
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Enter kill (SIGTERM)" }),
5497
5921
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
5498
5922
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Del force kill (SIGKILL)" }),
@@ -6086,7 +6510,23 @@ var SETTINGS_MODES = ["off", "suggest", "auto"];
6086
6510
  var LOG_LEVELS = ["error", "warn", "info", "debug", "trace"];
6087
6511
  var AUDIT_LEVELS = ["minimal", "standard", "full"];
6088
6512
  var COMPACTOR_STRATEGIES = ["hybrid", "intelligent", "selective"];
6513
+ var CONTEXT_MODES = ["balanced", "frugal", "deep", "archival"];
6514
+ var CONTEXT_MODE_DESCS = {
6515
+ balanced: "Normal context usage (default)",
6516
+ frugal: "Conservative token use",
6517
+ deep: "Larger context for complex tasks",
6518
+ archival: "Maximize context retention"
6519
+ };
6520
+ var STATUSLINE_MODES = ["minimum", "detailed"];
6521
+ var REASONING_MODES = ["auto", "on", "off"];
6522
+ var REASONING_EFFORTS = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
6523
+ var CACHE_TTLS = ["default", "5m", "1h"];
6524
+ var STATUSLINE_MODE_DESCS = {
6525
+ minimum: "Single line with essential chips only",
6526
+ detailed: "Full multi-line statusline (default)"
6527
+ };
6089
6528
  var MAX_ITERATIONS_PRESETS = [100, 200, 500, 1e3, 0];
6529
+ var MAX_CONCURRENT_PRESETS = [1, 3, 5, 10, 25, 50, 0];
6090
6530
  var AUTO_PROCEED_MAX_PRESETS = [10, 25, 50, 100, 250, 0];
6091
6531
  var ENHANCE_DELAY_PRESETS = [3e4, 45e3, 6e4, 9e4, 12e4];
6092
6532
  var ENHANCE_LANGUAGES = ["original", "english"];
@@ -6115,7 +6555,7 @@ var MODE_DESC = {
6115
6555
  suggest: "Shows next-step suggestions after each turn",
6116
6556
  auto: "Self-driving \u2014 agent continues automatically"
6117
6557
  };
6118
- var SETTINGS_FIELD_COUNT = 27;
6558
+ var SETTINGS_FIELD_COUNT = 34;
6119
6559
  var CONFIG_SCOPES = ["global", "project"];
6120
6560
  function SettingsPicker({
6121
6561
  field,
@@ -6136,6 +6576,8 @@ function SettingsPicker({
6136
6576
  allowOutsideProjectRoot,
6137
6577
  contextAutoCompact,
6138
6578
  contextStrategy,
6579
+ contextMode,
6580
+ maxConcurrent,
6139
6581
  logLevel,
6140
6582
  auditLevel,
6141
6583
  indexOnStart,
@@ -6145,6 +6587,11 @@ function SettingsPicker({
6145
6587
  enhanceEnabled,
6146
6588
  enhanceLanguage,
6147
6589
  debugStream,
6590
+ statuslineMode,
6591
+ reasoningMode,
6592
+ reasoningEffort,
6593
+ reasoningPreserve,
6594
+ cacheTtl,
6148
6595
  configScope,
6149
6596
  hint
6150
6597
  }) {
@@ -6239,6 +6686,18 @@ function SettingsPicker({
6239
6686
  value: contextStrategy,
6240
6687
  detail: "hybrid (fast) | intelligent (LLM) | selective"
6241
6688
  },
6689
+ {
6690
+ label: "Context mode",
6691
+ value: contextMode,
6692
+ detail: CONTEXT_MODE_DESCS[contextMode]
6693
+ },
6694
+ // ── Fleet ──
6695
+ { section: "Fleet" },
6696
+ {
6697
+ label: "Max concurrent",
6698
+ value: maxConcurrent === 0 ? "unlimited" : String(maxConcurrent),
6699
+ detail: "Max subagents (0 = unlimited)"
6700
+ },
6242
6701
  // ── Logging ──
6243
6702
  { section: "Logging" },
6244
6703
  {
@@ -6287,6 +6746,28 @@ function SettingsPicker({
6287
6746
  value: enhanceLanguage,
6288
6747
  detail: "original (keep language) | english (translate)"
6289
6748
  },
6749
+ // ── Reasoning ──
6750
+ { section: "Reasoning" },
6751
+ {
6752
+ label: "Reasoning mode",
6753
+ value: reasoningMode,
6754
+ detail: "auto (provider default) | on | off"
6755
+ },
6756
+ {
6757
+ label: "Reasoning effort",
6758
+ value: reasoningEffort,
6759
+ detail: "none\u2013max (model-dependent)"
6760
+ },
6761
+ {
6762
+ label: "Preserve thinking",
6763
+ value: boolVal(reasoningPreserve),
6764
+ detail: "Keep reasoning across turns"
6765
+ },
6766
+ {
6767
+ label: "Cache TTL",
6768
+ value: cacheTtl,
6769
+ detail: "Prompt cache TTL (5m | 1h)"
6770
+ },
6290
6771
  // ── Debug ──
6291
6772
  { section: "Debug" },
6292
6773
  {
@@ -6294,6 +6775,11 @@ function SettingsPicker({
6294
6775
  value: boolVal(debugStream),
6295
6776
  detail: "Hex-dump raw SSE bytes to stderr"
6296
6777
  },
6778
+ {
6779
+ label: "Statusline",
6780
+ value: statuslineMode,
6781
+ detail: STATUSLINE_MODE_DESCS[statuslineMode]
6782
+ },
6297
6783
  {
6298
6784
  label: "Config scope",
6299
6785
  value: configScope,
@@ -6360,6 +6846,145 @@ function SettingsPicker({
6360
6846
  hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
6361
6847
  ] });
6362
6848
  }
6849
+ function isChipExpired(meta, now = Date.now()) {
6850
+ if (meta.expiresIn == null || meta.expiresIn === 0) return false;
6851
+ if (meta.shownAt == null || meta.shownAt === 0) return false;
6852
+ return now >= meta.shownAt + meta.expiresIn * 60 * 1e3;
6853
+ }
6854
+ var ITEM_DESCRIPTIONS = {
6855
+ todos: "Todo items (pending/in-progress/done)",
6856
+ plan: "Plan board items",
6857
+ tasks: "Task board items",
6858
+ fleet: "Fleet agent status",
6859
+ git: "Git branch name",
6860
+ elapsed: "Session elapsed time",
6861
+ context: "Context window usage %",
6862
+ cost: "Token cost estimate",
6863
+ working_dir: "Current working directory",
6864
+ brain: "Brain arbiter decisions",
6865
+ mailbox: "Mailbox unread messages",
6866
+ enhance: "Prompt-enhance countdown",
6867
+ debug_stream: "Stream debug telemetry"
6868
+ };
6869
+ var ITEM_LINE = {
6870
+ context: 1,
6871
+ cost: 1,
6872
+ elapsed: 2,
6873
+ working_dir: 2,
6874
+ git: 2,
6875
+ todos: 3,
6876
+ plan: 3,
6877
+ tasks: 3,
6878
+ fleet: 4,
6879
+ brain: 3,
6880
+ mailbox: 3,
6881
+ enhance: 3,
6882
+ debug_stream: 3
6883
+ };
6884
+ Object.keys(ITEM_LINE).length;
6885
+ var STATUSLINE_ITEMS = [
6886
+ // Line 1
6887
+ "context",
6888
+ "cost",
6889
+ // Line 2
6890
+ "elapsed",
6891
+ "git",
6892
+ "working_dir",
6893
+ // Line 3
6894
+ "brain",
6895
+ "debug_stream",
6896
+ "enhance",
6897
+ "mailbox",
6898
+ "plan",
6899
+ "tasks",
6900
+ "todos",
6901
+ // Line 4
6902
+ "fleet"
6903
+ ];
6904
+ var STREAM_CHIP_KEYS = ["brain", "mailbox", "enhance", "debug_stream"];
6905
+ function groupByLine(items) {
6906
+ const map = /* @__PURE__ */ new Map();
6907
+ for (const item of items) {
6908
+ const line = ITEM_LINE[item];
6909
+ if (!map.has(line)) map.set(line, []);
6910
+ map.get(line).push(item);
6911
+ }
6912
+ return map;
6913
+ }
6914
+ function StatuslinePicker({
6915
+ field,
6916
+ hiddenItems,
6917
+ visibleChips = [],
6918
+ hint
6919
+ }) {
6920
+ const hiddenSet = new Set(hiddenItems);
6921
+ const visibleChipsMap = new Map(visibleChips.map((c) => [c.key, c]));
6922
+ const totalFields = STATUSLINE_ITEMS.length;
6923
+ const byLine = groupByLine(STATUSLINE_ITEMS);
6924
+ const rows = [];
6925
+ for (const [line, items] of [...byLine.entries()].sort((a, b) => a[0] - b[0])) {
6926
+ rows.push({ section: `Line ${line}` });
6927
+ for (const item of items) {
6928
+ const fieldIdx = STATUSLINE_ITEMS.indexOf(item);
6929
+ rows.push({ item, fieldIdx });
6930
+ }
6931
+ }
6932
+ const VISIBLE_FIELDS = 7;
6933
+ const windowStart = Math.max(0, Math.min(field - Math.floor(VISIBLE_FIELDS / 2), totalFields - VISIBLE_FIELDS));
6934
+ const windowEnd = Math.min(windowStart + VISIBLE_FIELDS, totalFields);
6935
+ const hasAbove = windowStart > 0;
6936
+ const hasBelow = windowEnd < totalFields;
6937
+ const boolVal = (item) => {
6938
+ if (hiddenSet.has(item)) return "off";
6939
+ if (STREAM_CHIP_KEYS.includes(item)) {
6940
+ const meta = visibleChipsMap.get(item);
6941
+ if (!meta) return "off";
6942
+ if (meta.expiresIn == null) return "on ";
6943
+ const remainingMs = meta.shownAt + meta.expiresIn * 6e4 - Date.now();
6944
+ if (remainingMs <= 0) return "exp";
6945
+ const remainingMin = Math.max(1, Math.ceil(remainingMs / 6e4));
6946
+ return `~${remainingMin}m`;
6947
+ }
6948
+ return "on ";
6949
+ };
6950
+ const valColor = (item) => {
6951
+ if (hiddenSet.has(item)) return "red";
6952
+ if (STREAM_CHIP_KEYS.includes(item)) {
6953
+ const meta = visibleChipsMap.get(item);
6954
+ if (!meta) return "red";
6955
+ if (isChipExpired(meta)) return "red";
6956
+ return "yellow";
6957
+ }
6958
+ return "green";
6959
+ };
6960
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
6961
+ /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Statusline \u2501\u2501" }),
6962
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 move \xB7 \u2190/\u2192 toggle \xB7 Esc to close" }),
6963
+ hasAbove ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2191 ${windowStart} item${windowStart === 1 ? "" : "s"} above` }) : null,
6964
+ rows.map((row) => {
6965
+ if (row.section) {
6966
+ return /* @__PURE__ */ jsxs(Text, { bold: true, color: "green", children: [
6967
+ "\u2500\u2500 ",
6968
+ row.section,
6969
+ " \u2500\u2500"
6970
+ ] }, `section-${row.section}`);
6971
+ }
6972
+ const item = row.item;
6973
+ const fieldIdx = row.fieldIdx;
6974
+ const selected = fieldIdx === field;
6975
+ return /* @__PURE__ */ jsxs(Text, { inverse: selected, ...selected ? { color: "yellow" } : {}, children: [
6976
+ selected ? "\u203A " : " ",
6977
+ /* @__PURE__ */ jsx(Text, { bold: true, children: item.padEnd(12) }),
6978
+ /* @__PURE__ */ jsx(Text, { color: valColor(item), children: boolVal(item).padEnd(4) }),
6979
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: ITEM_DESCRIPTIONS[item] }),
6980
+ selected ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2190/\u2192 toggle" }) : null
6981
+ ] }, `row-${item}`);
6982
+ }),
6983
+ hasBelow ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2193 ${totalFields - windowEnd} item${totalFields - windowEnd === 1 ? "" : "s"} below` }) : null,
6984
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Changes apply instantly \xB7 persisted to ~/.wrongstack/statusline.json \xB7 auto chips expire after ~5m" }),
6985
+ hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
6986
+ ] });
6987
+ }
6363
6988
  var MAX_VISIBLE_ITEMS = 8;
6364
6989
  function SlashMenu({ query, matches, selected }) {
6365
6990
  const placeholder = query ? `/${query}` : "/";
@@ -7379,7 +8004,8 @@ function useTuiControllers({
7379
8004
  agentsMonitorOpen,
7380
8005
  fleetStreamController,
7381
8006
  enhanceController,
7382
- agentsMonitorController
8007
+ agentsMonitorController,
8008
+ onPanelOpen
7383
8009
  }) {
7384
8010
  useEffect(() => {
7385
8011
  if (!fleetStreamController) return;
@@ -7425,6 +8051,16 @@ function useTuiControllers({
7425
8051
  useEffect(() => {
7426
8052
  if (agentsMonitorController) agentsMonitorController.visible = agentsMonitorOpen;
7427
8053
  }, [agentsMonitorController, agentsMonitorOpen]);
8054
+ useEffect(() => {
8055
+ if (!onPanelOpen) return;
8056
+ onPanelOpen.current = (action) => {
8057
+ dispatch({ type: action });
8058
+ return true;
8059
+ };
8060
+ return () => {
8061
+ onPanelOpen.current = null;
8062
+ };
8063
+ }, [onPanelOpen, dispatch]);
7428
8064
  }
7429
8065
  function useBrainEvents(events, dispatch) {
7430
8066
  useEffect(() => {
@@ -8021,6 +8657,26 @@ function buildSteeringPreamble(snapshot, newDirection) {
8021
8657
  lines.push("]");
8022
8658
  return lines.join("\n");
8023
8659
  }
8660
+ function closePanels(state) {
8661
+ return {
8662
+ monitorOpen: false,
8663
+ agentsMonitorOpen: false,
8664
+ helpOpen: false,
8665
+ todosMonitorOpen: false,
8666
+ queuePanelOpen: false,
8667
+ processListOpen: false,
8668
+ planPanelOpen: false,
8669
+ goalPanelOpen: false,
8670
+ sessionsPanelOpen: false,
8671
+ settingsPicker: { ...state.settingsPicker, open: false },
8672
+ statuslinePicker: { ...state.statuslinePicker, open: false },
8673
+ projectPicker: { ...state.projectPicker, open: false },
8674
+ fKeyPicker: { ...state.fKeyPicker, open: false },
8675
+ autoPhase: state.autoPhase ? { ...state.autoPhase, monitorOpen: false } : state.autoPhase,
8676
+ worktreeMonitorOpen: false,
8677
+ coordinator: { ...state.coordinator, monitorOpen: false }
8678
+ };
8679
+ }
8024
8680
  var MAX_TOOL_STREAM_RETAINED_CHARS = 1e5;
8025
8681
  var MAX_RETAINED_INPUT_CHARS = 2048;
8026
8682
  var MAX_RETAINED_INPUT_DEPTH = 4;
@@ -8288,6 +8944,7 @@ function reducer(state, action) {
8288
8944
  case "modelPickerOpen":
8289
8945
  return {
8290
8946
  ...state,
8947
+ ...closePanels(state),
8291
8948
  modelPicker: {
8292
8949
  open: true,
8293
8950
  step: "provider",
@@ -8375,6 +9032,7 @@ function reducer(state, action) {
8375
9032
  case "autonomyPickerOpen":
8376
9033
  return {
8377
9034
  ...state,
9035
+ ...closePanels(state),
8378
9036
  autonomyPicker: { open: true, options: action.options, selected: 0, hint: void 0 }
8379
9037
  };
8380
9038
  case "autonomyPickerClose":
@@ -8399,6 +9057,7 @@ function reducer(state, action) {
8399
9057
  case "resumePickerOpen":
8400
9058
  return {
8401
9059
  ...state,
9060
+ ...closePanels(state),
8402
9061
  resumePicker: { open: true, sessions: action.sessions, selected: 0, busy: false, hint: void 0, error: void 0 }
8403
9062
  };
8404
9063
  case "resumePickerClose":
@@ -8428,6 +9087,7 @@ function reducer(state, action) {
8428
9087
  case "settingsOpen":
8429
9088
  return {
8430
9089
  ...state,
9090
+ ...closePanels(state),
8431
9091
  settingsPicker: {
8432
9092
  open: true,
8433
9093
  field: 0,
@@ -8448,6 +9108,8 @@ function reducer(state, action) {
8448
9108
  allowOutsideProjectRoot: action.allowOutsideProjectRoot,
8449
9109
  contextAutoCompact: action.contextAutoCompact,
8450
9110
  contextStrategy: action.contextStrategy,
9111
+ contextMode: action.contextMode,
9112
+ maxConcurrent: action.maxConcurrent,
8451
9113
  logLevel: action.logLevel,
8452
9114
  auditLevel: action.auditLevel,
8453
9115
  indexOnStart: action.indexOnStart,
@@ -8457,6 +9119,11 @@ function reducer(state, action) {
8457
9119
  enhanceEnabled: action.enhanceEnabled,
8458
9120
  enhanceLanguage: action.enhanceLanguage,
8459
9121
  debugStream: action.debugStream,
9122
+ statuslineMode: action.statuslineMode,
9123
+ reasoningMode: action.reasoningMode,
9124
+ reasoningEffort: action.reasoningEffort,
9125
+ reasoningPreserve: action.reasoningPreserve,
9126
+ cacheTtl: action.cacheTtl,
8460
9127
  configScope: action.configScope,
8461
9128
  hint: void 0
8462
9129
  }
@@ -8519,57 +9186,152 @@ function reducer(state, action) {
8519
9186
  return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined$1(COMPACTOR_STRATEGIES[next]), hint: bootHint } };
8520
9187
  }
8521
9188
  if (f === 17) {
9189
+ const i = CONTEXT_MODES.indexOf(sp.contextMode);
9190
+ const base = i < 0 ? 0 : i;
9191
+ const next = (base + action.delta + CONTEXT_MODES.length) % CONTEXT_MODES.length;
9192
+ return { ...state, settingsPicker: { ...sp, contextMode: expectDefined$1(CONTEXT_MODES[next]), hint: bootHint } };
9193
+ }
9194
+ if (f === 18) {
9195
+ const j = MAX_CONCURRENT_PRESETS.indexOf(sp.maxConcurrent);
9196
+ const base = j < 0 ? 0 : j;
9197
+ const next = (base + action.delta + MAX_CONCURRENT_PRESETS.length) % MAX_CONCURRENT_PRESETS.length;
9198
+ return { ...state, settingsPicker: { ...sp, maxConcurrent: expectDefined$1(MAX_CONCURRENT_PRESETS[next]), hint: void 0 } };
9199
+ }
9200
+ if (f === 19) {
8522
9201
  const i = LOG_LEVELS.indexOf(sp.logLevel);
8523
9202
  const base = i < 0 ? 0 : i;
8524
9203
  const next = (base + action.delta + LOG_LEVELS.length) % LOG_LEVELS.length;
8525
9204
  return { ...state, settingsPicker: { ...sp, logLevel: expectDefined$1(LOG_LEVELS[next]), hint: void 0 } };
8526
9205
  }
8527
- if (f === 18) {
9206
+ if (f === 20) {
8528
9207
  const i = AUDIT_LEVELS.indexOf(sp.auditLevel);
8529
9208
  const base = i < 0 ? 0 : i;
8530
9209
  const next = (base + action.delta + AUDIT_LEVELS.length) % AUDIT_LEVELS.length;
8531
9210
  return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined$1(AUDIT_LEVELS[next]), hint: void 0 } };
8532
9211
  }
8533
- if (f === 19) return { ...state, settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: bootHint } };
8534
- if (f === 20) {
9212
+ if (f === 21) return { ...state, settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: bootHint } };
9213
+ if (f === 22) {
8535
9214
  const j = MAX_ITERATIONS_PRESETS.indexOf(sp.maxIterations);
8536
9215
  const base = j < 0 ? 0 : j;
8537
9216
  const next = (base + action.delta + MAX_ITERATIONS_PRESETS.length) % MAX_ITERATIONS_PRESETS.length;
8538
9217
  return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined$1(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
8539
9218
  }
8540
- if (f === 21) {
9219
+ if (f === 23) {
8541
9220
  const aj = AUTO_PROCEED_MAX_PRESETS.indexOf(sp.autoProceedMaxIterations);
8542
9221
  const abase = aj < 0 ? 0 : aj;
8543
9222
  const anext = (abase + action.delta + AUTO_PROCEED_MAX_PRESETS.length) % AUTO_PROCEED_MAX_PRESETS.length;
8544
9223
  return { ...state, settingsPicker: { ...sp, autoProceedMaxIterations: expectDefined$1(AUTO_PROCEED_MAX_PRESETS[anext]), hint: void 0 } };
8545
9224
  }
8546
- if (f === 22) {
9225
+ if (f === 24) {
8547
9226
  const ej = ENHANCE_DELAY_PRESETS.indexOf(sp.enhanceDelayMs);
8548
9227
  const ebase = ej < 0 ? 0 : ej;
8549
9228
  const enext = (ebase + action.delta + ENHANCE_DELAY_PRESETS.length) % ENHANCE_DELAY_PRESETS.length;
8550
9229
  return { ...state, settingsPicker: { ...sp, enhanceDelayMs: expectDefined$1(ENHANCE_DELAY_PRESETS[enext]), hint: void 0 } };
8551
9230
  }
8552
- if (f === 23) return { ...state, settingsPicker: { ...sp, enhanceEnabled: !sp.enhanceEnabled, hint: void 0 } };
8553
- if (f === 24) {
9231
+ if (f === 25) return { ...state, settingsPicker: { ...sp, enhanceEnabled: !sp.enhanceEnabled, hint: void 0 } };
9232
+ if (f === 26) {
8554
9233
  const i = ENHANCE_LANGUAGES.indexOf(sp.enhanceLanguage);
8555
9234
  const base = i < 0 ? 0 : i;
8556
9235
  const next = (base + action.delta + ENHANCE_LANGUAGES.length) % ENHANCE_LANGUAGES.length;
8557
9236
  return { ...state, settingsPicker: { ...sp, enhanceLanguage: expectDefined$1(ENHANCE_LANGUAGES[next]), hint: void 0 } };
8558
9237
  }
8559
- if (f === 25) return { ...state, settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 } };
8560
- if (f === 26) {
9238
+ if (f === 27) return { ...state, settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 } };
9239
+ if (f === 28) {
9240
+ const i = STATUSLINE_MODES.indexOf(sp.statuslineMode);
9241
+ const base = i < 0 ? STATUSLINE_MODES.indexOf("detailed") : i;
9242
+ const next = (base + action.delta + STATUSLINE_MODES.length) % STATUSLINE_MODES.length;
9243
+ return { ...state, settingsPicker: { ...sp, statuslineMode: expectDefined$1(STATUSLINE_MODES[next]), hint: void 0 } };
9244
+ }
9245
+ if (f === 29) {
8561
9246
  const i = CONFIG_SCOPES.indexOf(sp.configScope);
8562
9247
  const base = i < 0 ? 0 : i;
8563
9248
  const next = (base + action.delta + CONFIG_SCOPES.length) % CONFIG_SCOPES.length;
8564
9249
  return { ...state, settingsPicker: { ...sp, configScope: expectDefined$1(CONFIG_SCOPES[next]), hint: void 0 } };
8565
9250
  }
9251
+ if (f === 30) {
9252
+ const i = REASONING_MODES.indexOf(sp.reasoningMode);
9253
+ const base = i < 0 ? 0 : i;
9254
+ const next = (base + action.delta + REASONING_MODES.length) % REASONING_MODES.length;
9255
+ return { ...state, settingsPicker: { ...sp, reasoningMode: expectDefined$1(REASONING_MODES[next]), hint: void 0 } };
9256
+ }
9257
+ if (f === 31) {
9258
+ const i = REASONING_EFFORTS.indexOf(sp.reasoningEffort);
9259
+ const base = i < 0 ? REASONING_EFFORTS.indexOf("high") : i;
9260
+ const next = (base + action.delta + REASONING_EFFORTS.length) % REASONING_EFFORTS.length;
9261
+ return { ...state, settingsPicker: { ...sp, reasoningEffort: expectDefined$1(REASONING_EFFORTS[next]), hint: void 0 } };
9262
+ }
9263
+ if (f === 32) return { ...state, settingsPicker: { ...sp, reasoningPreserve: !sp.reasoningPreserve, hint: void 0 } };
9264
+ if (f === 33) {
9265
+ const i = CACHE_TTLS.indexOf(sp.cacheTtl);
9266
+ const base = i < 0 ? 0 : i;
9267
+ const next = (base + action.delta + CACHE_TTLS.length) % CACHE_TTLS.length;
9268
+ return { ...state, settingsPicker: { ...sp, cacheTtl: expectDefined$1(CACHE_TTLS[next]), hint: void 0 } };
9269
+ }
8566
9270
  return state;
8567
9271
  }
8568
9272
  case "settingsHint":
8569
9273
  return { ...state, settingsPicker: { ...state.settingsPicker, hint: action.text } };
9274
+ // ── Statusline picker ───────────────────────────────────────────────
9275
+ case "statuslineOpen":
9276
+ return {
9277
+ ...state,
9278
+ ...closePanels(state),
9279
+ statuslinePicker: { open: true, field: 0, hiddenItems: action.hiddenItems, visibleChips: state.statuslinePicker.visibleChips, hint: void 0 }
9280
+ };
9281
+ case "statuslineClose":
9282
+ return { ...state, statuslinePicker: { ...state.statuslinePicker, open: false, hint: void 0 } };
9283
+ case "statuslineFieldMove": {
9284
+ const totalFields = 13;
9285
+ const next = (state.statuslinePicker.field + action.delta + totalFields) % totalFields;
9286
+ return { ...state, statuslinePicker: { ...state.statuslinePicker, field: next, hint: void 0 } };
9287
+ }
9288
+ case "statuslineFieldSet": {
9289
+ const totalFields = 13;
9290
+ const field = action.field >= 0 && action.field < totalFields ? action.field : 0;
9291
+ return { ...state, statuslinePicker: { ...state.statuslinePicker, field, hint: void 0 } };
9292
+ }
9293
+ case "statuslineToggle": {
9294
+ const cur = state.statuslinePicker;
9295
+ const hiddenSet = new Set(cur.hiddenItems);
9296
+ if (hiddenSet.has(action.item)) {
9297
+ hiddenSet.delete(action.item);
9298
+ } else {
9299
+ hiddenSet.add(action.item);
9300
+ }
9301
+ return { ...state, statuslinePicker: { ...cur, hiddenItems: [...hiddenSet] } };
9302
+ }
9303
+ case "statuslineHint":
9304
+ return { ...state, statuslinePicker: { ...state.statuslinePicker, hint: action.text } };
9305
+ case "statuslineChipShow": {
9306
+ const cur = state.statuslinePicker;
9307
+ const existing = cur.visibleChips.findIndex((c) => c.key === action.key);
9308
+ const meta = action.expiresIn != null ? { key: action.key, shownAt: Date.now(), expiresIn: action.expiresIn } : { key: action.key, shownAt: Date.now() };
9309
+ if (existing >= 0) {
9310
+ const updated = [...cur.visibleChips];
9311
+ updated[existing] = meta;
9312
+ return { ...state, statuslinePicker: { ...cur, visibleChips: updated } };
9313
+ }
9314
+ return { ...state, statuslinePicker: { ...cur, visibleChips: [...cur.visibleChips, meta] } };
9315
+ }
9316
+ case "statuslineChipExpire": {
9317
+ const cur = state.statuslinePicker;
9318
+ return {
9319
+ ...state,
9320
+ statuslinePicker: {
9321
+ ...cur,
9322
+ visibleChips: cur.visibleChips.filter((c) => c.key !== action.key)
9323
+ }
9324
+ };
9325
+ }
9326
+ case "statuslineVisibleChipsSync":
9327
+ return {
9328
+ ...state,
9329
+ statuslinePicker: { ...state.statuslinePicker, visibleChips: action.visibleChips }
9330
+ };
8570
9331
  case "projectPickerOpen":
8571
9332
  return {
8572
9333
  ...state,
9334
+ ...closePanels(state),
8573
9335
  projectPicker: {
8574
9336
  open: true,
8575
9337
  allItems: action.items,
@@ -8609,6 +9371,15 @@ function reducer(state, action) {
8609
9371
  }
8610
9372
  case "projectPickerHint":
8611
9373
  return { ...state, projectPicker: { ...state.projectPicker, hint: action.text } };
9374
+ case "fKeyPickerOpen":
9375
+ return { ...state, ...closePanels(state), fKeyPicker: { open: true, selected: 0 } };
9376
+ case "fKeyPickerClose":
9377
+ return { ...state, fKeyPicker: { open: false, selected: 0 } };
9378
+ case "fKeyPickerMove": {
9379
+ const count = 12;
9380
+ const next = (state.fKeyPicker.selected + action.delta + count) % count;
9381
+ return { ...state, fKeyPicker: { ...state.fKeyPicker, selected: next } };
9382
+ }
8612
9383
  case "confirmOpen":
8613
9384
  return { ...state, confirmQueue: [...state.confirmQueue, action.info] };
8614
9385
  case "confirmClose":
@@ -8946,35 +9717,35 @@ function reducer(state, action) {
8946
9717
  }
8947
9718
  case "toggleMonitor": {
8948
9719
  const opening = !state.monitorOpen;
8949
- return opening ? { ...state, monitorOpen: true, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, monitorOpen: false };
9720
+ return opening ? { ...state, ...closePanels(state), monitorOpen: true } : { ...state, monitorOpen: false };
8950
9721
  }
8951
9722
  case "toggleAgentsMonitor": {
8952
9723
  const opening = !state.agentsMonitorOpen;
8953
- return opening ? { ...state, agentsMonitorOpen: true, monitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, agentsMonitorOpen: false };
9724
+ return opening ? { ...state, ...closePanels(state), agentsMonitorOpen: true } : { ...state, agentsMonitorOpen: false };
8954
9725
  }
8955
9726
  case "toggleHelp": {
8956
9727
  const opening = !state.helpOpen;
8957
- return opening ? { ...state, helpOpen: true, monitorOpen: false, agentsMonitorOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, helpOpen: false };
9728
+ return opening ? { ...state, ...closePanels(state), helpOpen: true } : { ...state, helpOpen: false };
8958
9729
  }
8959
9730
  case "toggleTodosMonitor": {
8960
9731
  const opening = !state.todosMonitorOpen;
8961
- return opening ? { ...state, todosMonitorOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, todosMonitorOpen: false };
9732
+ return opening ? { ...state, ...closePanels(state), todosMonitorOpen: true } : { ...state, todosMonitorOpen: false };
8962
9733
  }
8963
9734
  case "toggleQueuePanel": {
8964
9735
  const opening = !state.queuePanelOpen;
8965
- return opening ? { ...state, queuePanelOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, queuePanelOpen: false };
9736
+ return opening ? { ...state, ...closePanels(state), queuePanelOpen: true } : { ...state, queuePanelOpen: false };
8966
9737
  }
8967
9738
  case "toggleProcessList": {
8968
9739
  const opening = !state.processListOpen;
8969
- return opening ? { ...state, processListOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, goalPanelOpen: false } : { ...state, processListOpen: false };
9740
+ return opening ? { ...state, ...closePanels(state), processListOpen: true } : { ...state, processListOpen: false };
8970
9741
  }
8971
9742
  case "togglePlanPanel": {
8972
9743
  const opening = !state.planPanelOpen;
8973
- return opening ? { ...state, planPanelOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, planPanelOpen: false };
9744
+ return opening ? { ...state, ...closePanels(state), planPanelOpen: true } : { ...state, planPanelOpen: false };
8974
9745
  }
8975
9746
  case "toggleGoalPanel": {
8976
9747
  const opening = !state.goalPanelOpen;
8977
- return opening ? { ...state, goalPanelOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false } : { ...state, goalPanelOpen: false };
9748
+ return opening ? { ...state, ...closePanels(state), goalPanelOpen: true } : { ...state, goalPanelOpen: false };
8978
9749
  }
8979
9750
  case "checkpointReceived": {
8980
9751
  const existing = state.checkpoints.find((c) => c.promptIndex === action.cp.promptIndex);
@@ -9060,9 +9831,14 @@ function reducer(state, action) {
9060
9831
  }
9061
9832
  case "autoPhaseMonitorToggle": {
9062
9833
  if (!state.autoPhase) return state;
9063
- return {
9834
+ const opening = !state.autoPhase.monitorOpen;
9835
+ return opening ? {
9064
9836
  ...state,
9065
- autoPhase: { ...state.autoPhase, monitorOpen: !state.autoPhase.monitorOpen }
9837
+ ...closePanels(state),
9838
+ autoPhase: { ...state.autoPhase, monitorOpen: true }
9839
+ } : {
9840
+ ...state,
9841
+ autoPhase: { ...state.autoPhase, monitorOpen: false }
9066
9842
  };
9067
9843
  }
9068
9844
  case "autoPhaseReset": {
@@ -9094,7 +9870,8 @@ function reducer(state, action) {
9094
9870
  return { ...state, worktrees: next };
9095
9871
  }
9096
9872
  case "worktreeMonitorToggle": {
9097
- return { ...state, worktreeMonitorOpen: !state.worktreeMonitorOpen };
9873
+ const opening = !state.worktreeMonitorOpen;
9874
+ return opening ? { ...state, ...closePanels(state), worktreeMonitorOpen: true } : { ...state, worktreeMonitorOpen: false };
9098
9875
  }
9099
9876
  // --- In-app chat scroll ---
9100
9877
  case "scrollBy": {
@@ -9289,7 +10066,8 @@ function reducer(state, action) {
9289
10066
  return { ...state, debugStreamStats: null };
9290
10067
  }
9291
10068
  case "toggleSessionsPanel": {
9292
- return { ...state, sessionsPanelOpen: !state.sessionsPanelOpen };
10069
+ const opening = !state.sessionsPanelOpen;
10070
+ return opening ? { ...state, ...closePanels(state), sessionsPanelOpen: true, sessionResumeConfirm: null } : { ...state, sessionsPanelOpen: false, sessionResumeConfirm: null };
9293
10071
  }
9294
10072
  case "sessionsPanelSet": {
9295
10073
  const sessions = Array.isArray(action.sessions) ? action.sessions : [];
@@ -9394,15 +10172,8 @@ function reducer(state, action) {
9394
10172
  const opening = !state.coordinator.monitorOpen;
9395
10173
  return opening ? {
9396
10174
  ...state,
9397
- coordinator: { ...state.coordinator, monitorOpen: true },
9398
- // Close other monitors when opening coordinator
9399
- monitorOpen: false,
9400
- agentsMonitorOpen: false,
9401
- helpOpen: false,
9402
- todosMonitorOpen: false,
9403
- queuePanelOpen: false,
9404
- processListOpen: false,
9405
- goalPanelOpen: false
10175
+ ...closePanels(state),
10176
+ coordinator: { ...state.coordinator, monitorOpen: true }
9406
10177
  } : { ...state, coordinator: { ...state.coordinator, monitorOpen: false } };
9407
10178
  }
9408
10179
  }
@@ -9444,6 +10215,7 @@ function rehydrateHistory(messages, startId, toolCalls) {
9444
10215
  return entries;
9445
10216
  }
9446
10217
  var PASTE_THRESHOLD_CHARS = 200;
10218
+ var SB_PADX2 = 2;
9447
10219
  function App({
9448
10220
  agent,
9449
10221
  slashRegistry,
@@ -9501,6 +10273,7 @@ function App({
9501
10273
  interruptController,
9502
10274
  statuslineHiddenItems,
9503
10275
  setStatuslineHiddenItems,
10276
+ saveStatuslineHiddenItems,
9504
10277
  agentsMonitorController,
9505
10278
  initialGoal,
9506
10279
  initialAsk,
@@ -9516,9 +10289,13 @@ function App({
9516
10289
  getLiveSessions,
9517
10290
  onSwitchToSession,
9518
10291
  initialAgentsMonitorOpen,
10292
+ onPanelOpen,
9519
10293
  subscribeCoordinatorEvents,
9520
10294
  onCoordinatorStart,
9521
10295
  onCoordinatorStop,
10296
+ // Reserved for the coordinator monitor panel: terminal-driven task discovery/claim.
10297
+ onCoordinatorTasks: _onCoordinatorTasks,
10298
+ onCoordinatorClaim: _onCoordinatorClaim,
9522
10299
  coordinatorRunning = false,
9523
10300
  clientId
9524
10301
  }) {
@@ -9550,6 +10327,8 @@ function App({
9550
10327
  modeLabel,
9551
10328
  statuslineHiddenItems
9552
10329
  });
10330
+ const hiddenItemsRef = useRef(hiddenItems);
10331
+ hiddenItemsRef.current = hiddenItems;
9553
10332
  const prevBranchRef = useRef(null);
9554
10333
  const [indexState, setIndexState] = useState(() => getIndexState());
9555
10334
  useEffect(() => {
@@ -9583,7 +10362,10 @@ function App({
9583
10362
  }, [statuslineHiddenItems]);
9584
10363
  useEffect(() => {
9585
10364
  setStatuslineHiddenItems(hiddenItems);
9586
- }, [setStatuslineHiddenItems, hiddenItems]);
10365
+ saveStatuslineHiddenItems(hiddenItems).catch?.((err) => {
10366
+ console.error("[statusline] failed to persist hidden items:", err);
10367
+ });
10368
+ }, [setStatuslineHiddenItems, saveStatuslineHiddenItems, hiddenItems]);
9587
10369
  const projectRoot = agent.ctx.projectRoot;
9588
10370
  const refreshGoalSummary = useCallback(() => {
9589
10371
  if (!projectRoot) return;
@@ -9675,8 +10457,10 @@ function App({
9675
10457
  },
9676
10458
  autonomyPicker: { open: false, options: [], selected: 0 },
9677
10459
  resumePicker: { open: false, sessions: [], selected: 0, busy: false, hint: void 0, error: void 0 },
9678
- 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, tokenSavingTier: "off", allowOutsideProjectRoot: 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" },
10460
+ 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, tokenSavingTier: "off", allowOutsideProjectRoot: true, contextAutoCompact: true, contextStrategy: "hybrid", contextMode: "balanced", maxConcurrent: 10, logLevel: "info", auditLevel: "standard", indexOnStart: true, maxIterations: 500, autoProceedMaxIterations: 50, enhanceDelayMs: 6e4, enhanceEnabled: true, enhanceLanguage: "original", debugStream: false, statuslineMode: "detailed", reasoningMode: "auto", reasoningEffort: "high", reasoningPreserve: false, cacheTtl: "default", configScope: "global" },
10461
+ statuslinePicker: { open: false, field: 0, hiddenItems: [], visibleChips: [], hint: void 0 },
9679
10462
  projectPicker: { open: false, allItems: [], items: [], selected: 0, filter: "", hint: void 0 },
10463
+ fKeyPicker: { open: false, selected: 0 },
9680
10464
  confirmQueue: [],
9681
10465
  enhance: null,
9682
10466
  enhanceEnabled,
@@ -9730,6 +10514,52 @@ function App({
9730
10514
  debugStreamStats: null,
9731
10515
  countdown: null
9732
10516
  });
10517
+ useEffect(() => {
10518
+ if (state.statuslinePicker.open) {
10519
+ const pickerHidden = state.statuslinePicker.hiddenItems;
10520
+ const currentHidden = new Set(hiddenItems);
10521
+ const pickerHiddenSet = new Set(pickerHidden);
10522
+ const differs = currentHidden.size !== pickerHiddenSet.size || pickerHidden.some((item) => !currentHidden.has(item)) || hiddenItems.some((item) => !pickerHiddenSet.has(item));
10523
+ if (differs) {
10524
+ setHiddenItems([...pickerHidden]);
10525
+ }
10526
+ }
10527
+ }, [state.statuslinePicker.hiddenItems, state.statuslinePicker.open, setHiddenItems, hiddenItems]);
10528
+ const prevBrainPromptRef = useRef(state.brainPrompt);
10529
+ const prevEnhanceRef = useRef(state.enhance);
10530
+ useEffect(() => {
10531
+ if (state.brainPrompt && !prevBrainPromptRef.current) {
10532
+ dispatch({ type: "statuslineChipShow", key: "brain", expiresIn: 5 });
10533
+ } else if (!state.brainPrompt && prevBrainPromptRef.current) {
10534
+ if (state.statuslinePicker.visibleChips.some((c) => c.key === "brain")) {
10535
+ dispatch({ type: "statuslineChipExpire", key: "brain" });
10536
+ }
10537
+ }
10538
+ prevBrainPromptRef.current = state.brainPrompt;
10539
+ if (state.enhance && !prevEnhanceRef.current) {
10540
+ dispatch({ type: "statuslineChipShow", key: "enhance", expiresIn: 5 });
10541
+ } else if (!state.enhance && prevEnhanceRef.current) {
10542
+ if (state.statuslinePicker.visibleChips.some((c) => c.key === "enhance")) {
10543
+ dispatch({ type: "statuslineChipExpire", key: "enhance" });
10544
+ }
10545
+ }
10546
+ prevEnhanceRef.current = state.enhance;
10547
+ }, [
10548
+ state.brainPrompt,
10549
+ state.enhance,
10550
+ state.statuslinePicker.visibleChips,
10551
+ dispatch
10552
+ ]);
10553
+ useEffect(() => {
10554
+ const interval = setInterval(() => {
10555
+ const now = Date.now();
10556
+ const expired = state.statuslinePicker.visibleChips.filter((c) => isChipExpired(c, now));
10557
+ for (const chip of expired) {
10558
+ dispatch({ type: "statuslineChipExpire", key: chip.key });
10559
+ }
10560
+ }, 3e4);
10561
+ return () => clearInterval(interval);
10562
+ }, [state.statuslinePicker.visibleChips, dispatch]);
9733
10563
  useAutonomousCoordinator(subscribeCoordinatorEvents, dispatch);
9734
10564
  const builderRef = useRef(null);
9735
10565
  if (builderRef.current === null) {
@@ -9761,6 +10591,7 @@ function App({
9761
10591
  });
9762
10592
  }, [agent.ctx, projectRoot]);
9763
10593
  const liveSettings = getSettings?.();
10594
+ const liveStatuslineMode = liveSettings?.statuslineMode ?? "detailed";
9764
10595
  const chimeRef = useRef(chime);
9765
10596
  chimeRef.current = liveSettings?.chime ?? chime;
9766
10597
  const confirmExitRef = useRef(confirmExit);
@@ -9824,11 +10655,11 @@ function App({
9824
10655
  async (checkpointIndex) => {
9825
10656
  const sessionId = agent.ctx.session.id;
9826
10657
  if (!sessionId) return;
9827
- const rewinder = new DefaultSessionRewinder(sessionsDir ?? "", projectRoot ?? agent.ctx.cwd);
10658
+ const rewinder = new DefaultSessionRewinder(sessionsDir ?? "", agent.ctx.projectRoot ?? agent.ctx.cwd);
9828
10659
  await rewinder.rewindToCheckpoint(sessionId, checkpointIndex);
9829
10660
  await agent.ctx.session.truncateToCheckpoint(checkpointIndex);
9830
10661
  },
9831
- [agent.ctx.session, sessionsDir, projectRoot, agent.ctx.cwd]
10662
+ [agent.ctx.session, sessionsDir, agent.ctx.projectRoot, agent.ctx.cwd]
9832
10663
  );
9833
10664
  const setDraft = (buffer, cursor) => {
9834
10665
  draftRef.current = { buffer, cursor };
@@ -10125,8 +10956,8 @@ function App({
10125
10956
  const leaderEntry = {
10126
10957
  id: "leader",
10127
10958
  name: "LEADER",
10128
- provider,
10129
- model,
10959
+ provider: liveProvider,
10960
+ model: liveModel,
10130
10961
  status: state.status === "running" || state.status === "streaming" || state.leader.iterating ? "running" : "idle",
10131
10962
  streamingText: "",
10132
10963
  iterations: state.leader.iterations,
@@ -10145,7 +10976,7 @@ function App({
10145
10976
  ctxMaxTokens: state.leader.ctxMaxTokens ?? effectiveMaxContext
10146
10977
  };
10147
10978
  return { leader: leaderEntry, ...state.fleet };
10148
- }, [state.fleet, state.leader, state.status, provider, model, effectiveMaxContext, tokenCounter]);
10979
+ }, [state.fleet, state.leader, state.status, liveProvider, liveModel, effectiveMaxContext, tokenCounter]);
10149
10980
  const [planCounts, setPlanCounts] = useState(null);
10150
10981
  useEffect(() => {
10151
10982
  const planPath = agent.ctx.meta["plan.path"];
@@ -10329,6 +11160,8 @@ function App({
10329
11160
  allowOutsideProjectRoot: sp.allowOutsideProjectRoot,
10330
11161
  contextAutoCompact: sp.contextAutoCompact,
10331
11162
  contextStrategy: sp.contextStrategy,
11163
+ contextMode: sp.contextMode,
11164
+ maxConcurrent: sp.maxConcurrent,
10332
11165
  logLevel: sp.logLevel,
10333
11166
  auditLevel: sp.auditLevel,
10334
11167
  indexOnStart: sp.indexOnStart,
@@ -10338,6 +11171,11 @@ function App({
10338
11171
  enhanceEnabled: sp.enhanceEnabled,
10339
11172
  enhanceLanguage: sp.enhanceLanguage,
10340
11173
  debugStream: sp.debugStream,
11174
+ statuslineMode: sp.statuslineMode,
11175
+ reasoningMode: sp.reasoningMode,
11176
+ reasoningEffort: sp.reasoningEffort,
11177
+ reasoningPreserve: sp.reasoningPreserve,
11178
+ cacheTtl: sp.cacheTtl,
10341
11179
  configScope: sp.configScope
10342
11180
  });
10343
11181
  }
@@ -10405,6 +11243,7 @@ function App({
10405
11243
  const allCommands = slashRegistry.listWithOwner();
10406
11244
  const CATEGORY_ORDER = ["Run", "Session", "Inspect", "Agent", "Config", "App"];
10407
11245
  const matches = allCommands.filter(({ cmd }) => {
11246
+ if (query === "" && cmd.hidden) return false;
10408
11247
  const name = cmd.name.toLowerCase();
10409
11248
  const aliases = cmd.aliases ?? [];
10410
11249
  return name.includes(query) || aliases.some((a) => a.toLowerCase().includes(query));
@@ -10691,6 +11530,9 @@ function App({
10691
11530
  const items = await getProjectPickerItems();
10692
11531
  dispatch({ type: "projectPickerOpen", items });
10693
11532
  }, [getProjectPickerItems]);
11533
+ const openFKeyPicker = React5.useCallback(() => {
11534
+ dispatch({ type: "fKeyPickerOpen" });
11535
+ }, [dispatch]);
10694
11536
  const loadLiveSessions = React5.useCallback(async () => {
10695
11537
  if (!getLiveSessions) {
10696
11538
  dispatch({ type: "sessionsPanelSet", sessions: [] });
@@ -10733,6 +11575,8 @@ function App({
10733
11575
  allowOutsideProjectRoot: s2.allowOutsideProjectRoot ?? true,
10734
11576
  contextAutoCompact: s2.contextAutoCompact ?? true,
10735
11577
  contextStrategy: s2.contextStrategy ?? "hybrid",
11578
+ contextMode: s2.contextMode ?? "balanced",
11579
+ maxConcurrent: s2.maxConcurrent ?? 10,
10736
11580
  logLevel: s2.logLevel ?? "info",
10737
11581
  auditLevel: s2.auditLevel ?? "standard",
10738
11582
  indexOnStart: s2.indexOnStart ?? true,
@@ -10742,6 +11586,11 @@ function App({
10742
11586
  enhanceEnabled: s2.enhanceEnabled ?? true,
10743
11587
  enhanceLanguage: s2.enhanceLanguage ?? "original",
10744
11588
  debugStream: s2.debugStream ?? false,
11589
+ statuslineMode: s2.statuslineMode ?? "detailed",
11590
+ reasoningMode: s2.reasoningMode ?? "auto",
11591
+ reasoningEffort: s2.reasoningEffort ?? "high",
11592
+ reasoningPreserve: s2.reasoningPreserve ?? false,
11593
+ cacheTtl: s2.cacheTtl ?? "default",
10745
11594
  configScope: s2.configScope ?? "global"
10746
11595
  });
10747
11596
  }, [getSettings]);
@@ -10869,6 +11718,8 @@ function App({
10869
11718
  allowOutsideProjectRoot: sp.allowOutsideProjectRoot,
10870
11719
  contextAutoCompact: sp.contextAutoCompact,
10871
11720
  contextStrategy: sp.contextStrategy,
11721
+ contextMode: sp.contextMode,
11722
+ maxConcurrent: sp.maxConcurrent,
10872
11723
  logLevel: sp.logLevel,
10873
11724
  auditLevel: sp.auditLevel,
10874
11725
  indexOnStart: sp.indexOnStart,
@@ -10878,6 +11729,11 @@ function App({
10878
11729
  enhanceEnabled: sp.enhanceEnabled,
10879
11730
  enhanceLanguage: sp.enhanceLanguage,
10880
11731
  debugStream: sp.debugStream,
11732
+ statuslineMode: sp.statuslineMode,
11733
+ reasoningMode: sp.reasoningMode,
11734
+ reasoningEffort: sp.reasoningEffort,
11735
+ reasoningPreserve: sp.reasoningPreserve,
11736
+ cacheTtl: sp.cacheTtl,
10881
11737
  configScope: sp.configScope
10882
11738
  })).then((err) => {
10883
11739
  if (err) dispatch({ type: "settingsHint", text: err });
@@ -10901,6 +11757,8 @@ function App({
10901
11757
  state.settingsPicker.allowOutsideProjectRoot,
10902
11758
  state.settingsPicker.contextAutoCompact,
10903
11759
  state.settingsPicker.contextStrategy,
11760
+ state.settingsPicker.contextMode,
11761
+ state.settingsPicker.maxConcurrent,
10904
11762
  state.settingsPicker.logLevel,
10905
11763
  state.settingsPicker.auditLevel,
10906
11764
  state.settingsPicker.indexOnStart,
@@ -10910,6 +11768,11 @@ function App({
10910
11768
  state.settingsPicker.enhanceEnabled,
10911
11769
  state.settingsPicker.enhanceLanguage,
10912
11770
  state.settingsPicker.debugStream,
11771
+ state.settingsPicker.statuslineMode,
11772
+ state.settingsPicker.reasoningMode,
11773
+ state.settingsPicker.reasoningEffort,
11774
+ state.settingsPicker.reasoningPreserve,
11775
+ state.settingsPicker.cacheTtl,
10913
11776
  saveSettings
10914
11777
  ]);
10915
11778
  useEffect(() => {
@@ -10928,6 +11791,20 @@ function App({
10928
11791
  slashRegistry.unregister("model");
10929
11792
  };
10930
11793
  }, [slashRegistry, getPickableProviders, switchProviderAndModel, openModelPicker]);
11794
+ useEffect(() => {
11795
+ const cmd = {
11796
+ name: "f",
11797
+ description: "Open F-key panel picker. Arrow keys to navigate, Enter to open, Esc to close.",
11798
+ async run() {
11799
+ openFKeyPicker();
11800
+ return { message: void 0 };
11801
+ }
11802
+ };
11803
+ slashRegistry.register(cmd, "tui", { official: true });
11804
+ return () => {
11805
+ slashRegistry.unregister("f");
11806
+ };
11807
+ }, [slashRegistry, openFKeyPicker]);
10931
11808
  useEffect(() => {
10932
11809
  if (!getSettings || !saveSettings) return;
10933
11810
  const cmd = {
@@ -10944,6 +11821,26 @@ function App({
10944
11821
  slashRegistry.unregister("settings");
10945
11822
  };
10946
11823
  }, [slashRegistry, getSettings, saveSettings, openSettings]);
11824
+ useEffect(() => {
11825
+ const cmd = {
11826
+ name: "statusline",
11827
+ aliases: ["sl"],
11828
+ description: "Customize status bar chips: /statusline (interactive) or /statusline <item> [on|off]",
11829
+ async run(args) {
11830
+ if (args.trim()) return { message: void 0 };
11831
+ const hookHidden = hiddenItemsRef.current;
11832
+ const reducerStreamHidden = stateRef.current.statuslinePicker.hiddenItems.filter(
11833
+ (item) => !hookHidden.includes(item)
11834
+ );
11835
+ dispatch({ type: "statuslineOpen", hiddenItems: [...hookHidden, ...reducerStreamHidden] });
11836
+ return { message: void 0 };
11837
+ }
11838
+ };
11839
+ slashRegistry.register(cmd, "tui", { official: true });
11840
+ return () => {
11841
+ slashRegistry.unregister("statusline");
11842
+ };
11843
+ }, [slashRegistry]);
10947
11844
  useEffect(() => {
10948
11845
  const cmd = {
10949
11846
  name: "mailbox",
@@ -11265,7 +12162,8 @@ function App({
11265
12162
  agentsMonitorOpen: state.agentsMonitorOpen,
11266
12163
  fleetStreamController,
11267
12164
  enhanceController,
11268
- agentsMonitorController
12165
+ agentsMonitorController,
12166
+ onPanelOpen
11269
12167
  });
11270
12168
  useEffect(() => {
11271
12169
  if (!interruptController) return;
@@ -11677,6 +12575,32 @@ function App({
11677
12575
  }
11678
12576
  return;
11679
12577
  }
12578
+ if (state.statuslinePicker.open) {
12579
+ if (key.escape) {
12580
+ dispatch({ type: "statuslineClose" });
12581
+ return;
12582
+ }
12583
+ if (key.mouse?.kind === "wheel") {
12584
+ dispatch({ type: "statuslineFieldMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
12585
+ return;
12586
+ }
12587
+ if (key.upArrow) {
12588
+ dispatch({ type: "statuslineFieldMove", delta: -1 });
12589
+ return;
12590
+ }
12591
+ if (key.downArrow) {
12592
+ dispatch({ type: "statuslineFieldMove", delta: 1 });
12593
+ return;
12594
+ }
12595
+ if (key.leftArrow || key.rightArrow) {
12596
+ const focused = STATUSLINE_ITEMS[state.statuslinePicker.field];
12597
+ if (focused) {
12598
+ dispatch({ type: "statuslineToggle", item: focused });
12599
+ }
12600
+ return;
12601
+ }
12602
+ return;
12603
+ }
11680
12604
  if (state.projectPicker.open) {
11681
12605
  if (key.escape) {
11682
12606
  if (state.projectPicker.filter) {
@@ -11713,13 +12637,13 @@ function App({
11713
12637
  if (item.kind === "project") {
11714
12638
  await onProjectSelect?.(item.key, item.kind);
11715
12639
  dispatch({ type: "projectPickerClose" });
11716
- requestExit?.(42);
12640
+ dispatch({ type: "addEntry", entry: { kind: "info", text: `Switched project: ${item.label.trim()}.` } });
11717
12641
  return;
11718
12642
  }
11719
12643
  dispatch({ type: "projectPickerClose" });
11720
12644
  if (item.key === "new-session") {
11721
12645
  await onProjectSelect?.(item.key, item.kind);
11722
- requestExit?.(42);
12646
+ dispatch({ type: "addEntry", entry: { kind: "info", text: "Started a fresh session in this project." } });
11723
12647
  } else if (item.key === "prev-sessions") {
11724
12648
  void submit("/resume");
11725
12649
  }
@@ -11868,6 +12792,34 @@ function App({
11868
12792
  return;
11869
12793
  }
11870
12794
  }
12795
+ if (state.fKeyPicker.open) {
12796
+ if (key.escape) {
12797
+ dispatch({ type: "fKeyPickerClose" });
12798
+ return;
12799
+ }
12800
+ if (key.upArrow) {
12801
+ dispatch({ type: "fKeyPickerMove", delta: -1 });
12802
+ return;
12803
+ }
12804
+ if (key.downArrow) {
12805
+ dispatch({ type: "fKeyPickerMove", delta: 1 });
12806
+ return;
12807
+ }
12808
+ if (isEnter) {
12809
+ const selected = state.fKeyPicker.selected;
12810
+ const entry = F_KEY_PANEL_ENTRIES[selected];
12811
+ if (!entry) return;
12812
+ dispatch({ type: "fKeyPickerClose" });
12813
+ if (entry.action === "projectPickerOpen") {
12814
+ openProjectPicker();
12815
+ return;
12816
+ }
12817
+ const action = actionForFKeyPanel(entry, state.statuslinePicker.hiddenItems);
12818
+ if (action) dispatch(action);
12819
+ return;
12820
+ }
12821
+ return;
12822
+ }
11871
12823
  if (state.picker.open) {
11872
12824
  if (key.escape) {
11873
12825
  dispatch({ type: "pickerClose" });
@@ -12123,6 +13075,10 @@ function App({
12123
13075
  dispatch({ type: "toggleCoordinatorMonitor" });
12124
13076
  return;
12125
13077
  }
13078
+ if (key.fn === 12) {
13079
+ dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
13080
+ return;
13081
+ }
12126
13082
  if (key.ctrl && input === "s") {
12127
13083
  if (state.settingsPicker.open) {
12128
13084
  dispatch({ type: "settingsClose" });
@@ -12150,10 +13106,12 @@ function App({
12150
13106
  featureMemory: cfg.featureMemory ?? true,
12151
13107
  featureSkills: cfg.featureSkills ?? true,
12152
13108
  featureModelsRegistry: cfg.featureModelsRegistry ?? true,
12153
- tokenSavingTier: cfg.featureTokenSaving ?? "off",
13109
+ tokenSavingTier: cfg.tokenSavingTier ?? "off",
12154
13110
  allowOutsideProjectRoot: cfg.allowOutsideProjectRoot ?? true,
12155
13111
  contextAutoCompact: cfg.contextAutoCompact ?? true,
12156
13112
  contextStrategy: cfg.contextStrategy ?? "hybrid",
13113
+ contextMode: cfg.contextMode ?? "balanced",
13114
+ maxConcurrent: cfg.maxConcurrent ?? 10,
12157
13115
  logLevel: cfg.logLevel ?? "info",
12158
13116
  auditLevel: cfg.auditLevel ?? "standard",
12159
13117
  indexOnStart: cfg.indexOnStart ?? true,
@@ -12163,6 +13121,11 @@ function App({
12163
13121
  enhanceEnabled: cfg.enhanceEnabled ?? true,
12164
13122
  enhanceLanguage: cfg.enhanceLanguage ?? "original",
12165
13123
  debugStream: cfg.debugStream ?? false,
13124
+ statuslineMode: cfg.statuslineMode ?? "detailed",
13125
+ reasoningMode: cfg.reasoningMode ?? "auto",
13126
+ reasoningEffort: cfg.reasoningEffort ?? "high",
13127
+ reasoningPreserve: cfg.reasoningPreserve ?? false,
13128
+ cacheTtl: cfg.cacheTtl ?? "default",
12166
13129
  configScope: cfg.configScope ?? "global"
12167
13130
  });
12168
13131
  }
@@ -12217,7 +13180,8 @@ function App({
12217
13180
  if (state.processListOpen) {
12218
13181
  return;
12219
13182
  }
12220
- 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) {
13183
+ const overlayOpen = state.monitorOpen || state.agentsMonitorOpen || state.worktreeMonitorOpen || state.todosMonitorOpen || state.queuePanelOpen || state.processListOpen || state.goalPanelOpen || state.sessionsPanelOpen || state.coordinator.monitorOpen || state.helpOpen || (state.autoPhase?.monitorOpen ?? false) || state.rewindOverlay !== null;
13184
+ if (input === "?" && !key.ctrl && !key.meta && draftRef.current.buffer === "" && !overlayOpen) {
12221
13185
  dispatch({ type: "toggleHelp" });
12222
13186
  return;
12223
13187
  }
@@ -12333,7 +13297,7 @@ function App({
12333
13297
  setDraft(buffer, buffer.length);
12334
13298
  return;
12335
13299
  }
12336
- if (key.upArrow || key.downArrow || key.pageUp || key.pageDown) {
13300
+ if (!overlayOpen && (key.upArrow || key.downArrow || key.pageUp || key.pageDown)) {
12337
13301
  const width = stdout?.columns ?? 80;
12338
13302
  const rows = layoutInputRows(INPUT_PROMPT, buffer, cursor, width);
12339
13303
  if (rows.length <= 1) ; else {
@@ -12384,7 +13348,6 @@ function App({
12384
13348
  }
12385
13349
  }
12386
13350
  }
12387
- const overlayOpen = state.monitorOpen || state.agentsMonitorOpen || state.worktreeMonitorOpen || state.todosMonitorOpen || state.queuePanelOpen || state.processListOpen || state.goalPanelOpen || state.sessionsPanelOpen || state.coordinator.monitorOpen || state.helpOpen || (state.autoPhase?.monitorOpen ?? false) || state.rewindOverlay !== null;
12388
13351
  if (mouseMode && !overlayOpen) {
12389
13352
  if (key.mouse?.kind === "wheel") {
12390
13353
  if (key.mouse.shift) dispatch({ type: "scrollPage", dir: key.mouse.wheel > 0 ? "up" : "down" });
@@ -12435,6 +13398,40 @@ function App({
12435
13398
  dispatch({ type: "toggleTodosMonitor" });
12436
13399
  return;
12437
13400
  }
13401
+ const hiddenSet = new Set(state.statuslinePicker.hiddenItems);
13402
+ if (my === rowFor(2)) {
13403
+ const mxLocal = mx - SB_PADX2 - 1;
13404
+ if (!hiddenSet.has("todos") && mxLocal >= 0 && mxLocal < 20) {
13405
+ dispatch({ type: "statuslineFieldSet", field: 11 });
13406
+ dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
13407
+ return;
13408
+ }
13409
+ if (!hiddenSet.has("plan")) {
13410
+ const planStart = 21;
13411
+ if (mxLocal >= planStart && mxLocal < planStart + 22) {
13412
+ dispatch({ type: "statuslineFieldSet", field: 9 });
13413
+ dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
13414
+ return;
13415
+ }
13416
+ }
13417
+ if (!hiddenSet.has("tasks")) {
13418
+ const tasksStart = 44;
13419
+ if (mxLocal >= tasksStart && mxLocal < tasksStart + 26) {
13420
+ dispatch({ type: "statuslineFieldSet", field: 10 });
13421
+ dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
13422
+ return;
13423
+ }
13424
+ }
13425
+ }
13426
+ if (my === rowFor(3) && !hiddenSet.has("fleet")) {
13427
+ const mxLocal = mx - SB_PADX2 - 1;
13428
+ const fleetStart = 0;
13429
+ if (mxLocal >= fleetStart && mxLocal < fleetStart + 22) {
13430
+ dispatch({ type: "statuslineFieldSet", field: 12 });
13431
+ dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
13432
+ return;
13433
+ }
13434
+ }
12438
13435
  }
12439
13436
  if (key.pageUp) {
12440
13437
  dispatch({ type: "scrollPage", dir: "up" });
@@ -12513,7 +13510,7 @@ function App({
12513
13510
  setDraft(next2, cursor);
12514
13511
  return;
12515
13512
  }
12516
- if (key.ctrl) {
13513
+ if (key.ctrl && input === "v") {
12517
13514
  await pasteClipboardText();
12518
13515
  return;
12519
13516
  }
@@ -13054,6 +14051,7 @@ User message:
13054
14051
  );
13055
14052
  const inputHeight = Math.max(1, inputCellRows.length);
13056
14053
  const hideInput = enhanceActive || state.helpOpen || state.processListOpen;
14054
+ const lowerFunctionPanelOpen = state.monitorOpen || state.agentsMonitorOpen || (state.autoPhase?.monitorOpen ?? false) || state.worktreeMonitorOpen || state.planPanelOpen || state.todosMonitorOpen || state.queuePanelOpen || state.processListOpen || state.goalPanelOpen;
13057
14055
  return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, flexShrink: 0, children: [
13058
14056
  mouseMode ? /* @__PURE__ */ jsx(
13059
14057
  ScrollableHistory,
@@ -13163,6 +14161,8 @@ User message:
13163
14161
  allowOutsideProjectRoot: state.settingsPicker.allowOutsideProjectRoot,
13164
14162
  contextAutoCompact: state.settingsPicker.contextAutoCompact,
13165
14163
  contextStrategy: state.settingsPicker.contextStrategy,
14164
+ contextMode: state.settingsPicker.contextMode,
14165
+ maxConcurrent: state.settingsPicker.maxConcurrent,
13166
14166
  logLevel: state.settingsPicker.logLevel,
13167
14167
  auditLevel: state.settingsPicker.auditLevel,
13168
14168
  indexOnStart: state.settingsPicker.indexOnStart,
@@ -13172,10 +14172,24 @@ User message:
13172
14172
  enhanceEnabled: state.settingsPicker.enhanceEnabled,
13173
14173
  enhanceLanguage: state.settingsPicker.enhanceLanguage,
13174
14174
  debugStream: state.settingsPicker.debugStream,
14175
+ statuslineMode: state.settingsPicker.statuslineMode,
14176
+ reasoningMode: state.settingsPicker.reasoningMode,
14177
+ reasoningEffort: state.settingsPicker.reasoningEffort,
14178
+ reasoningPreserve: state.settingsPicker.reasoningPreserve,
14179
+ cacheTtl: state.settingsPicker.cacheTtl,
13175
14180
  configScope: state.settingsPicker.configScope,
13176
14181
  hint: state.settingsPicker.hint
13177
14182
  }
13178
14183
  ) : null,
14184
+ state.statuslinePicker.open ? /* @__PURE__ */ jsx(
14185
+ StatuslinePicker,
14186
+ {
14187
+ field: state.statuslinePicker.field,
14188
+ hiddenItems: state.statuslinePicker.hiddenItems,
14189
+ visibleChips: state.statuslinePicker.visibleChips,
14190
+ hint: state.statuslinePicker.hint
14191
+ }
14192
+ ) : null,
13179
14193
  state.projectPicker.open ? /* @__PURE__ */ jsx(
13180
14194
  ProjectPicker,
13181
14195
  {
@@ -13185,6 +14199,7 @@ User message:
13185
14199
  hint: state.projectPicker.hint
13186
14200
  }
13187
14201
  ) : null,
14202
+ state.fKeyPicker.open ? /* @__PURE__ */ jsx(FKeyPicker, { selected: state.fKeyPicker.selected }) : null,
13188
14203
  state.sessionsPanelOpen ? /* @__PURE__ */ jsx(
13189
14204
  SessionsPanel,
13190
14205
  {
@@ -13340,6 +14355,8 @@ User message:
13340
14355
  subagentCount: Object.keys(state.fleet).length,
13341
14356
  processCount: getProcessRegistry().activeCount,
13342
14357
  hiddenItems,
14358
+ mode: liveStatuslineMode,
14359
+ visibleChips: state.statuslinePicker.visibleChips,
13343
14360
  events,
13344
14361
  eternalStage: state.eternalStage,
13345
14362
  goalSummary: state.goalSummary,
@@ -13375,7 +14392,8 @@ User message:
13375
14392
  totalCost: state.fleetCost,
13376
14393
  leaderCost: tokenCounter?.estimateCost().total ?? 0,
13377
14394
  totalTokens: state.fleetTokens,
13378
- nowTick
14395
+ nowTick,
14396
+ onClose: () => dispatch({ type: "toggleAgentsMonitor" })
13379
14397
  }
13380
14398
  ) : state.autoPhase?.monitorOpen ? /* @__PURE__ */ jsx(
13381
14399
  PhaseMonitor,
@@ -13403,6 +14421,21 @@ User message:
13403
14421
  nowTick,
13404
14422
  collabSession: state.collabSession
13405
14423
  }
14424
+ ) : state.planPanelOpen ? /* @__PURE__ */ jsx(
14425
+ PlanPanel,
14426
+ {
14427
+ projectRoot: agent.ctx.projectRoot,
14428
+ sessionId: agent.ctx.session?.id ?? null,
14429
+ onClose: () => dispatch({ type: "togglePlanPanel" })
14430
+ }
14431
+ ) : state.queuePanelOpen ? /* @__PURE__ */ jsx(QueuePanel, { items: state.queue }) : state.processListOpen ? /* @__PURE__ */ jsx(ProcessListMonitor, {}) : state.goalPanelOpen ? /* @__PURE__ */ jsx(
14432
+ GoalPanel,
14433
+ {
14434
+ goal: state.goalSummary,
14435
+ onCoordinatorStart: onCoordinatorStart ?? void 0,
14436
+ onCoordinatorStop: onCoordinatorStop ?? void 0,
14437
+ coordinatorRunning
14438
+ }
13406
14439
  ) : director ? /* @__PURE__ */ jsx(
13407
14440
  FleetPanel,
13408
14441
  {
@@ -13412,7 +14445,7 @@ User message:
13412
14445
  collabSession: state.collabSession
13413
14446
  }
13414
14447
  ) : null,
13415
- state.autoPhase && !state.autoPhase.monitorOpen ? /* @__PURE__ */ jsx(
14448
+ state.autoPhase && !lowerFunctionPanelOpen ? /* @__PURE__ */ jsx(
13416
14449
  PhasePanel,
13417
14450
  {
13418
14451
  phases: state.autoPhase.phases,
@@ -13420,26 +14453,7 @@ User message:
13420
14453
  nowTick
13421
14454
  }
13422
14455
  ) : null,
13423
- Object.keys(state.worktrees).length > 0 && !state.worktreeMonitorOpen && !state.monitorOpen ? /* @__PURE__ */ jsx(WorktreePanel, { worktrees: state.worktrees, nowTick }) : null,
13424
- state.queuePanelOpen ? /* @__PURE__ */ jsx(QueuePanel, { items: state.queue }) : null,
13425
- state.processListOpen ? /* @__PURE__ */ jsx(ProcessListMonitor, {}) : null,
13426
- state.planPanelOpen ? /* @__PURE__ */ jsx(
13427
- PlanPanel,
13428
- {
13429
- projectRoot,
13430
- sessionId: agent.ctx.session?.id ?? null,
13431
- onClose: () => dispatch({ type: "togglePlanPanel" })
13432
- }
13433
- ) : null,
13434
- state.goalPanelOpen ? /* @__PURE__ */ jsx(
13435
- GoalPanel,
13436
- {
13437
- goal: state.goalSummary,
13438
- onCoordinatorStart: onCoordinatorStart ?? void 0,
13439
- onCoordinatorStop: onCoordinatorStop ?? void 0,
13440
- coordinatorRunning
13441
- }
13442
- ) : null,
14456
+ Object.keys(state.worktrees).length > 0 && !lowerFunctionPanelOpen ? /* @__PURE__ */ jsx(WorktreePanel, { worktrees: state.worktrees, nowTick }) : null,
13443
14457
  (() => {
13444
14458
  const anyMonitorOpen = state.agentsMonitorOpen || (state.autoPhase?.monitorOpen ?? false) || state.worktreeMonitorOpen || state.todosMonitorOpen || state.monitorOpen || state.processListOpen || state.queuePanelOpen || state.goalPanelOpen;
13445
14459
  let nextPanelHint;
@@ -13687,7 +14701,9 @@ async function runTui(opts) {
13687
14701
  if (!opts.projectRoot) return null;
13688
14702
  try {
13689
14703
  const projectDir = resolveProjectDir(opts.projectRoot, wstackGlobalRoot());
13690
- const mailbox = new GlobalMailbox(projectDir, opts.events);
14704
+ const hqPublisher = createHqPublisherFromEnv({ clientKind: "tui", projectRoot: opts.projectRoot, projectName: path5.basename(opts.projectRoot), appConfig: opts.appConfig });
14705
+ hqPublisher?.connect();
14706
+ const mailbox = new GlobalMailbox(projectDir, opts.events, hqPublisher);
13691
14707
  const clientId = `tui@${randomUUID().slice(0, 8)}`;
13692
14708
  await mailbox.registerClient({
13693
14709
  clientId,
@@ -13800,6 +14816,7 @@ async function runTui(opts) {
13800
14816
  enhanceEnabled: opts.enhanceController?.enabled ?? true,
13801
14817
  statuslineHiddenItems: opts.statuslineHiddenItems,
13802
14818
  setStatuslineHiddenItems: opts.setStatuslineHiddenItems,
14819
+ saveStatuslineHiddenItems: opts.saveStatuslineHiddenItems,
13803
14820
  agentsMonitorController: opts.agentsMonitorController,
13804
14821
  initialGoal: opts.initialGoal,
13805
14822
  initialAsk: opts.initialAsk,
@@ -13836,8 +14853,14 @@ async function runTui(opts) {
13836
14853
  onSwitchToSession: opts.onSwitchToSession,
13837
14854
  initialAgentsMonitorOpen: opts.initialAgentsMonitorOpen,
13838
14855
  subscribeCoordinatorEvents: opts.subscribeCoordinatorEvents,
14856
+ onPanelOpen: opts.onPanelOpen,
13839
14857
  onCoordinatorStart: opts.onCoordinatorStart,
13840
- onCoordinatorStop: opts.onCoordinatorStop
14858
+ onCoordinatorStop: opts.onCoordinatorStop,
14859
+ onCoordinatorTasks: opts.onCoordinatorTasks,
14860
+ onCoordinatorClaim: opts.onCoordinatorClaim,
14861
+ onCoordinatorComplete: opts.onCoordinatorComplete,
14862
+ onCoordinatorFail: opts.onCoordinatorFail,
14863
+ onCoordinatorStatus: opts.onCoordinatorStatus
13841
14864
  }),
13842
14865
  { exitOnCtrlC: false, stdin: inkStdin }
13843
14866
  );