@wrongstack/tui 0.272.2 → 0.273.1

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
@@ -3,7 +3,7 @@ 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';
5
5
  import * as path5 from 'path';
6
- import React5, { forwardRef, useState, useEffect, useMemo, memo, useRef, useCallback, useReducer, useLayoutEffect } from 'react';
6
+ import React5, { forwardRef, useState, useEffect, useMemo, memo, useRef, useCallback, useReducer, useLayoutEffect, isValidElement, Fragment as Fragment$1 } from 'react';
7
7
  import * as fs3 from 'fs/promises';
8
8
  import { expectDefined, toErrorMessage, resolveWstackPaths as resolveWstackPaths$1 } from '@wrongstack/core/utils';
9
9
  import { routeImagesForModel } from '@wrongstack/runtime/vision';
@@ -140,6 +140,11 @@ function isStreamChipVisible(key, dataIsPresent, hiddenSet, visibleChips) {
140
140
  if (chipExpired(meta)) return false;
141
141
  return true;
142
142
  }
143
+ function hasMailboxActivity(mailbox) {
144
+ if (!mailbox) return false;
145
+ const peerClientCount = Math.max(0, mailbox.onlineClients.tui - 1) + mailbox.onlineClients.webui + mailbox.onlineClients.repl;
146
+ return mailbox.unread > 0 || mailbox.onlineAgents > 1 || peerClientCount > 0 || Boolean(mailbox.lastSubject || mailbox.lastFrom);
147
+ }
143
148
  var MODE_ICONS = {
144
149
  teach: "\u{1F9D1}\u200D\u{1F3EB}",
145
150
  brief: "\u26A1",
@@ -166,6 +171,68 @@ function formatSuggestionLabel(label, maxLen = 28) {
166
171
  const lastSpace = shortened.lastIndexOf(" ");
167
172
  return lastSpace > 10 ? `${shortened.slice(0, lastSpace)}\u2026` : `${shortened}\u2026`;
168
173
  }
174
+ function countdownColor(secs, warn, danger) {
175
+ if (secs > warn) return "green";
176
+ if (secs > danger) return "yellow";
177
+ return "red";
178
+ }
179
+ function joinChips(chips) {
180
+ const out = [];
181
+ chips.forEach((chip, i) => {
182
+ if (i > 0) {
183
+ out.push(
184
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }, `sep-${i}`)
185
+ );
186
+ }
187
+ out.push(/* @__PURE__ */ jsx(Fragment$1, { children: chip }, `chip-${i}`));
188
+ });
189
+ return out;
190
+ }
191
+ function truncateChip(text, max) {
192
+ return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
193
+ }
194
+ function nodeText(node) {
195
+ if (node == null || typeof node === "boolean") return "";
196
+ if (typeof node === "string") return node;
197
+ if (typeof node === "number") return String(node);
198
+ if (Array.isArray(node)) return node.map(nodeText).join("");
199
+ if (isValidElement(node)) {
200
+ return nodeText(node.props.children);
201
+ }
202
+ return "";
203
+ }
204
+ var SB_SEP_COST = 5;
205
+ function planChipFit(widths, budget, sepCost = SB_SEP_COST) {
206
+ let used = 0;
207
+ let keep = 0;
208
+ for (const w of widths) {
209
+ const cost = w + (keep > 0 ? sepCost : 0);
210
+ if (keep > 0 && used + cost > budget) break;
211
+ used += cost;
212
+ keep += 1;
213
+ }
214
+ return keep;
215
+ }
216
+ function renderChipLine(chips, budget) {
217
+ const keep = planChipFit(
218
+ chips.map((c) => nodeText(c).length),
219
+ budget
220
+ );
221
+ const nodes = joinChips(chips.slice(0, keep));
222
+ const dropped = chips.length - keep;
223
+ if (dropped > 0) {
224
+ nodes.push(
225
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }, "ovf-sep")
226
+ );
227
+ nodes.push(
228
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
229
+ "+",
230
+ dropped
231
+ ] }, "ovf")
232
+ );
233
+ }
234
+ return nodes;
235
+ }
169
236
  var COMPACT_THRESHOLD = 50;
170
237
  var COMFORTABLE_THRESHOLD = 90;
171
238
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
@@ -237,19 +304,22 @@ function StatusBar({
237
304
  }, [stdout]);
238
305
  const isCompact = termWidth < COMPACT_THRESHOLD;
239
306
  const isComfortable = termWidth >= COMFORTABLE_THRESHOLD;
240
- const hiddenSet = new Set(hiddenItems);
307
+ const hiddenSet = useMemo(() => new Set(hiddenItems), [hiddenItems]);
308
+ const showChip = (item) => !hiddenSet.has(item);
241
309
  const tokenData = useTokenCounterRefresh(tokenCounter, events);
242
310
  const usage = tokenData?.usage;
243
311
  const displayTokens = tokenDisplayTotals(usage, tokenData?.currentRequest);
244
312
  const showTokenDisplay = hasTokenDisplay(displayTokens);
245
313
  const cost = tokenData?.cost;
246
314
  const cache2 = tokenData?.cacheStats;
315
+ const elapsedHidden = hiddenSet.has("elapsed");
247
316
  const [elapsedMs, setElapsedMs] = useState(startedAt ? Date.now() - startedAt : 0);
248
317
  useEffect(() => {
249
- if (startedAt == null) return;
318
+ if (startedAt == null || elapsedHidden) return;
319
+ setElapsedMs(Date.now() - startedAt);
250
320
  const t = setInterval(() => setElapsedMs(Date.now() - startedAt), 1e3);
251
321
  return () => clearInterval(t);
252
- }, [startedAt]);
322
+ }, [startedAt, elapsedHidden]);
253
323
  const [spinnerIdx, setSpinnerIdx] = useState(0);
254
324
  useEffect(() => {
255
325
  if (state === "idle" || state === "aborting") return;
@@ -264,21 +334,22 @@ function StatusBar({
264
334
  const statePrefix = state === "idle" || state === "aborting" ? "\u25CF" : spinner;
265
335
  const thinking = state === "running" || state === "streaming";
266
336
  const hasAutoProceed = autoProceedCountdown != null && autoProceedCountdown > 0;
267
- 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;
337
+ const hasSecondLine = yolo && showChip("yolo") || autonomy && autonomy !== "off" && showChip("autonomy") || eternalStage != null && showChip("eternal_stage") || startedAt != null && showChip("elapsed") || git !== null && git !== void 0 && showChip("git") || projectName !== void 0 && projectName.length > 0 && showChip("project") || workingDir !== void 0 && workingDir.length > 0 && showChip("working_dir") || goalSummary !== null && goalSummary !== void 0 && showChip("goal") || !!modeLabel && showChip("mode") || hasAutoProceed && showChip("auto_proceed") || tokenSavingMode && showChip("token_saving") || typeof toolCount === "number" && toolCount > 0 && showChip("tools") || sessionCount != null && sessionCount > 0 && showChip("sessions");
268
338
  const fleetHasActivity = fleet && (fleet.running > 0 || fleet.idle > 0 || fleet.pending > 0 || fleet.completed > 0) || subagentCount > 0;
269
- const showBrain = isStreamChipVisible("brain", brain, hiddenSet ?? /* @__PURE__ */ new Set(), visibleChips);
270
- const showDebugStream = isStreamChipVisible("debug_stream", debugStreamStats, hiddenSet ?? /* @__PURE__ */ new Set(), visibleChips);
271
- const showEnhance = isStreamChipVisible("enhance", enhanceCountdown, hiddenSet ?? /* @__PURE__ */ new Set(), visibleChips);
339
+ const showBrain = isStreamChipVisible("brain", brain, hiddenSet, visibleChips);
340
+ const showDebugStream = isStreamChipVisible("debug_stream", debugStreamStats, hiddenSet, visibleChips);
341
+ const showEnhance = isStreamChipVisible("enhance", enhanceCountdown, hiddenSet, visibleChips);
342
+ const showMailbox = showChip("mailbox") && hasMailboxActivity(mailbox);
272
343
  const hasNextStepsAutoSubmit = nextStepsAutoSubmitCountdown != null && nextStepsAutoSubmitCountdown > 0;
273
- const countdownColor = nextStepsAutoSubmitCountdown != null ? nextStepsAutoSubmitCountdown > 20 ? "green" : nextStepsAutoSubmitCountdown > 10 ? "yellow" : "red" : "green";
344
+ const nextStepsColor = nextStepsAutoSubmitCountdown != null ? countdownColor(nextStepsAutoSubmitCountdown, 20, 10) : "green";
274
345
  const hasTaskActivity = tasks && (tasks.pending > 0 || tasks.inProgress > 0 || tasks.completed > 0 || tasks.blocked > 0 || tasks.failed > 0);
275
- 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;
346
+ const hasThirdLine = todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && showChip("todos") || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) && showChip("plan") || hasTaskActivity && showChip("tasks") || fleetHasActivity && showChip("fleet") || showBrain || showDebugStream || showEnhance || hasNextStepsAutoSubmit && showChip("next_steps");
276
347
  const minimalWorkParts = [
277
- queueCount > 0 ? `q${queueCount}` : "",
278
- todos && !hiddenSet.has("todos") && todos.inProgress + todos.pending > 0 ? `todo ${todos.inProgress}/${todos.pending}` : "",
279
- hasTaskActivity && !hiddenSet.has("tasks") ? `task ${tasks.inProgress}/${tasks.pending}` : "",
280
- fleetHasActivity && !hiddenSet.has("fleet") ? fleet ? `agent \u25B6${fleet.running} \xB7${fleet.idle}` : `agent ${subagentCount}` : "",
281
- typeof processCount === "number" && processCount > 0 ? `proc ${processCount}` : ""
348
+ queueCount > 0 && showChip("queue") ? `q${queueCount}` : "",
349
+ todos && showChip("todos") && todos.inProgress + todos.pending > 0 ? `todo ${todos.inProgress}/${todos.pending}` : "",
350
+ hasTaskActivity && showChip("tasks") ? `task ${tasks.inProgress}/${tasks.pending}` : "",
351
+ fleetHasActivity && showChip("fleet") ? fleet ? `agent \u25B6${fleet.running} \xB7${fleet.idle}` : `agent ${subagentCount}` : "",
352
+ typeof processCount === "number" && processCount > 0 && showChip("processes") ? `proc ${processCount}` : ""
282
353
  ].filter(Boolean);
283
354
  if (mode === "minimum") {
284
355
  const ctxMax = context?.max;
@@ -296,22 +367,22 @@ function StatusBar({
296
367
  borderLeft: false,
297
368
  borderRight: false,
298
369
  children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
299
- version ? /* @__PURE__ */ jsxs(Text, { children: [
370
+ version && showChip("version") ? /* @__PURE__ */ jsxs(Text, { children: [
300
371
  /* @__PURE__ */ jsx(Text, { color: "blue", bold: true, children: "WS" }),
301
372
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
302
373
  " v",
303
374
  version
304
375
  ] })
305
376
  ] }) : null,
306
- version ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
307
- thinking ? /* @__PURE__ */ jsx(WaveText, { text: `${statePrefix} ${stateLabel}`, phase: spinnerIdx }) : /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
377
+ version && showChip("version") && (showChip("state") || showChip("model")) ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
378
+ showChip("state") && thinking ? /* @__PURE__ */ jsx(WaveText, { text: `${statePrefix} ${stateLabel}`, phase: spinnerIdx }) : showChip("state") ? /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
308
379
  statePrefix,
309
380
  " ",
310
381
  stateLabel
311
- ] }),
312
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
313
- /* @__PURE__ */ jsx(Text, { color: "magenta", children: model }),
314
- ctxClampedRatio !== void 0 && ctxPctText && ctxMax !== void 0 && !hiddenSet.has("context") ? /* @__PURE__ */ jsxs(Fragment, { children: [
382
+ ] }) : null,
383
+ showChip("state") && showChip("model") ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
384
+ showChip("model") ? /* @__PURE__ */ jsx(Text, { color: "magenta", children: model }) : null,
385
+ ctxClampedRatio !== void 0 && ctxPctText && ctxMax !== void 0 && showChip("context") ? /* @__PURE__ */ jsxs(Fragment, { children: [
315
386
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
316
387
  /* @__PURE__ */ jsxs(Text, { color: ctxClampedRatio < 0.6 ? "green" : ctxClampedRatio < 0.75 ? "yellow" : "red", children: [
317
388
  "ctx ",
@@ -320,7 +391,7 @@ function StatusBar({
320
391
  fmtTok(ctxMax)
321
392
  ] })
322
393
  ] }) : null,
323
- showTokenDisplay ? /* @__PURE__ */ jsxs(Fragment, { children: [
394
+ showTokenDisplay && showChip("tokens") ? /* @__PURE__ */ jsxs(Fragment, { children: [
324
395
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
325
396
  /* @__PURE__ */ jsxs(Text, { children: [
326
397
  "\u2191 ",
@@ -330,7 +401,7 @@ function StatusBar({
330
401
  /* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(displayTokens.output) })
331
402
  ] })
332
403
  ] }) : null,
333
- cost && cost.total > 0 && !hiddenSet.has("cost") ? /* @__PURE__ */ jsxs(Fragment, { children: [
404
+ cost && cost.total > 0 && showChip("cost") ? /* @__PURE__ */ jsxs(Fragment, { children: [
334
405
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
335
406
  /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
336
407
  "$",
@@ -359,17 +430,17 @@ function StatusBar({
359
430
  /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: isCompact ? (
360
431
  // Ultra-compact: state · model
361
432
  /* @__PURE__ */ jsxs(Fragment, { children: [
362
- thinking ? /* @__PURE__ */ jsx(WaveText, { text: `${statePrefix}${stateLabel}`, phase: spinnerIdx }) : /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
433
+ showChip("state") && thinking ? /* @__PURE__ */ jsx(WaveText, { text: `${statePrefix}${stateLabel}`, phase: spinnerIdx }) : showChip("state") ? /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
363
434
  statePrefix,
364
435
  stateLabel
365
- ] }),
366
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
367
- /* @__PURE__ */ jsx(Text, { color: "magenta", children: model })
436
+ ] }) : null,
437
+ showChip("state") && showChip("model") ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }) : null,
438
+ showChip("model") ? /* @__PURE__ */ jsx(Text, { color: "magenta", children: model }) : null
368
439
  ] })
369
440
  ) : (
370
441
  // Full mode: version · state · model · context · tokens · cost · queue · processes · hint
371
442
  /* @__PURE__ */ jsxs(Fragment, { children: [
372
- version ? /* @__PURE__ */ jsxs(Fragment, { children: [
443
+ version && showChip("version") ? /* @__PURE__ */ jsxs(Fragment, { children: [
373
444
  /* @__PURE__ */ jsxs(Text, { children: [
374
445
  /* @__PURE__ */ jsx(Text, { color: "blue", bold: true, children: "WS" }),
375
446
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
@@ -379,14 +450,16 @@ function StatusBar({
379
450
  ] }),
380
451
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" })
381
452
  ] }) : null,
382
- thinking ? /* @__PURE__ */ jsx(WaveText, { text: `${statePrefix} ${stateLabel}`, phase: spinnerIdx }) : /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
453
+ showChip("state") && thinking ? /* @__PURE__ */ jsx(WaveText, { text: `${statePrefix} ${stateLabel}`, phase: spinnerIdx }) : showChip("state") ? /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
383
454
  statePrefix,
384
455
  " ",
385
456
  stateLabel
386
- ] }),
387
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
388
- /* @__PURE__ */ jsx(Text, { color: "magenta", children: model }),
389
- context && !hiddenSet.has("context") ? /* @__PURE__ */ jsxs(Fragment, { children: [
457
+ ] }) : null,
458
+ showChip("model") ? /* @__PURE__ */ jsxs(Fragment, { children: [
459
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
460
+ /* @__PURE__ */ jsx(Text, { color: "magenta", children: model })
461
+ ] }) : null,
462
+ context && showChip("context") ? /* @__PURE__ */ jsxs(Fragment, { children: [
390
463
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
391
464
  (() => {
392
465
  const ratio = context.used / context.max;
@@ -407,7 +480,7 @@ function StatusBar({
407
480
  ] });
408
481
  })()
409
482
  ] }) : null,
410
- showTokenDisplay ? /* @__PURE__ */ jsxs(Fragment, { children: [
483
+ showTokenDisplay && showChip("tokens") ? /* @__PURE__ */ jsxs(Fragment, { children: [
411
484
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
412
485
  /* @__PURE__ */ jsxs(Text, { children: [
413
486
  "\u2191 ",
@@ -417,7 +490,7 @@ function StatusBar({
417
490
  /* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(displayTokens.output) })
418
491
  ] })
419
492
  ] }) : null,
420
- cache2 && cache2.hitRatio > 0 && isComfortable ? /* @__PURE__ */ jsxs(Fragment, { children: [
493
+ cache2 && cache2.hitRatio > 0 && isComfortable && showChip("cache") ? /* @__PURE__ */ jsxs(Fragment, { children: [
421
494
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
422
495
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
423
496
  "cache ",
@@ -425,21 +498,21 @@ function StatusBar({
425
498
  "%"
426
499
  ] })
427
500
  ] }) : null,
428
- cost && cost.total > 0 && !hiddenSet.has("cost") ? /* @__PURE__ */ jsxs(Fragment, { children: [
501
+ cost && cost.total > 0 && showChip("cost") ? /* @__PURE__ */ jsxs(Fragment, { children: [
429
502
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
430
503
  /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
431
504
  "$",
432
505
  cost.total.toFixed(4)
433
506
  ] })
434
507
  ] }) : null,
435
- queueCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
508
+ queueCount > 0 && showChip("queue") ? /* @__PURE__ */ jsxs(Fragment, { children: [
436
509
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
437
510
  /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
438
511
  "\u231B queued: ",
439
512
  queueCount
440
513
  ] })
441
514
  ] }) : null,
442
- typeof processCount === "number" && processCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
515
+ typeof processCount === "number" && processCount > 0 && showChip("processes") ? /* @__PURE__ */ jsxs(Fragment, { children: [
443
516
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
444
517
  /* @__PURE__ */ jsxs(Text, { color: "red", children: [
445
518
  "\u26A1 ",
@@ -448,11 +521,11 @@ function StatusBar({
448
521
  processCount === 1 ? "" : "es"
449
522
  ] })
450
523
  ] }) : null,
451
- hint ? /* @__PURE__ */ jsxs(Fragment, { children: [
524
+ hint && showChip("hint") ? /* @__PURE__ */ jsxs(Fragment, { children: [
452
525
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
453
526
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: hint })
454
527
  ] }) : null,
455
- indexState?.indexing ? /* @__PURE__ */ jsxs(Fragment, { children: [
528
+ indexState?.indexing && showChip("index") ? /* @__PURE__ */ jsxs(Fragment, { children: [
456
529
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
457
530
  /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
458
531
  "\u2699 indexing ",
@@ -460,11 +533,11 @@ function StatusBar({
460
533
  "/",
461
534
  indexState.totalFiles
462
535
  ] })
463
- ] }) : indexState?.circuit?.state === "open" ? /* @__PURE__ */ jsxs(Fragment, { children: [
536
+ ] }) : indexState?.circuit?.state === "open" && showChip("index") ? /* @__PURE__ */ jsxs(Fragment, { children: [
464
537
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
465
538
  /* @__PURE__ */ jsx(Text, { color: "red", children: "\u2699 index paused (/reindex)" })
466
539
  ] }) : null,
467
- breakerCountdown ? (() => {
540
+ breakerCountdown && showChip("breaker") ? (() => {
468
541
  const secs = Math.ceil(breakerCountdown.remainingMs / 1e3);
469
542
  const ratio = breakerCountdown.totalMs > 0 ? breakerCountdown.remainingMs / breakerCountdown.totalMs : 0;
470
543
  const c = secs > 20 ? "green" : secs > 10 ? "yellow" : "red";
@@ -480,11 +553,10 @@ function StatusBar({
480
553
  })() : null
481
554
  ] })
482
555
  ) }),
483
- hasSecondLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
484
- yolo ? /* @__PURE__ */ jsx(Text, { color: "red", bold: true, children: "\u26A0 YOLO" }) : null,
485
- autonomy && autonomy !== "off" ? /* @__PURE__ */ jsxs(Fragment, { children: [
486
- yolo ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
487
- /* @__PURE__ */ jsxs(
556
+ hasSecondLine ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: renderChipLine(
557
+ [
558
+ yolo && showChip("yolo") ? /* @__PURE__ */ jsx(Text, { color: "red", bold: true, children: "\u26A0 YOLO" }) : null,
559
+ autonomy && autonomy !== "off" && showChip("autonomy") ? /* @__PURE__ */ jsxs(
488
560
  Text,
489
561
  {
490
562
  color: autonomy === "eternal" ? "red" : autonomy === "auto" ? "yellow" : "cyan",
@@ -494,36 +566,21 @@ function StatusBar({
494
566
  autonomy.toUpperCase()
495
567
  ]
496
568
  }
497
- )
498
- ] }) : null,
499
- eternalStage ? /* @__PURE__ */ jsxs(Fragment, { children: [
500
- yolo || autonomy && autonomy !== "off" ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
501
- /* @__PURE__ */ jsx(EternalStageChip, { stage: eternalStage })
502
- ] }) : null,
503
- elapsedMs !== void 0 && !hiddenSet.has("elapsed") ? /* @__PURE__ */ jsxs(Fragment, { children: [
504
- yolo || autonomy && autonomy !== "off" || eternalStage ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
505
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
569
+ ) : null,
570
+ eternalStage && showChip("eternal_stage") ? /* @__PURE__ */ jsx(EternalStageChip, { stage: eternalStage }) : null,
571
+ elapsedMs !== void 0 && showChip("elapsed") ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
506
572
  "\u23F1 ",
507
573
  fmtElapsed(elapsedMs)
508
- ] })
509
- ] }) : null,
510
- projectName ? /* @__PURE__ */ jsxs(Fragment, { children: [
511
- yolo || startedAt != null ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
512
- /* @__PURE__ */ jsxs(Text, { color: "blue", children: [
574
+ ] }) : null,
575
+ projectName && showChip("project") ? /* @__PURE__ */ jsxs(Text, { color: "blue", children: [
513
576
  "\u{1F4C1} ",
514
- projectName
515
- ] })
516
- ] }) : null,
517
- workingDir && !hiddenSet.has("working_dir") ? /* @__PURE__ */ jsxs(Fragment, { children: [
518
- yolo || startedAt != null || projectName || goalSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
519
- /* @__PURE__ */ jsxs(Text, { color: "blue", children: [
577
+ truncateChip(projectName, 24)
578
+ ] }) : null,
579
+ workingDir && showChip("working_dir") ? /* @__PURE__ */ jsxs(Text, { color: "blue", children: [
520
580
  "\u{1F4C2} ",
521
- workingDir
522
- ] })
523
- ] }) : null,
524
- goalSummary ? /* @__PURE__ */ jsxs(Fragment, { children: [
525
- yolo || startedAt != null || projectName || workingDir ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
526
- /* @__PURE__ */ jsxs(
581
+ truncateChip(workingDir, 28)
582
+ ] }) : null,
583
+ goalSummary && showChip("goal") ? /* @__PURE__ */ jsxs(
527
584
  Text,
528
585
  {
529
586
  color: goalSummary.goalState === "active" ? "green" : goalSummary.goalState === "paused" ? "yellow" : goalSummary.goalState === "completed" ? "green" : "dim",
@@ -539,26 +596,17 @@ function StatusBar({
539
596
  ")"
540
597
  ]
541
598
  }
542
- )
543
- ] }) : null,
544
- modeLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [
545
- yolo || autonomy && autonomy !== "off" || eternalStage || startedAt != null || projectName || workingDir || goalSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
546
- /* @__PURE__ */ jsx(Text, { color: "cyan", children: modeIcon(modeLabel) })
547
- ] }) : null,
548
- hasAutoProceed ? /* @__PURE__ */ jsxs(Fragment, { children: [
549
- yolo || autonomy && autonomy !== "off" || eternalStage || startedAt != null || projectName || workingDir || goalSummary || modeLabel ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
550
- /* @__PURE__ */ jsxs(Text, { color: autoProceedCountdown != null && autoProceedCountdown <= 5 ? "yellow" : "cyan", children: [
599
+ ) : null,
600
+ modeLabel && showChip("mode") ? /* @__PURE__ */ jsx(Text, { color: "cyan", children: modeIcon(modeLabel) }) : null,
601
+ hasAutoProceed && showChip("auto_proceed") ? /* @__PURE__ */ jsxs(Text, { color: autoProceedCountdown != null && autoProceedCountdown <= 5 ? "yellow" : "cyan", children: [
551
602
  "\u23F3 auto in ",
552
603
  autoProceedCountdown,
553
604
  "s"
554
- ] })
555
- ] }) : null,
556
- git && !hiddenSet.has("git") ? /* @__PURE__ */ jsxs(Fragment, { children: [
557
- yolo || startedAt != null || projectName || workingDir ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
558
- /* @__PURE__ */ jsxs(Text, { children: [
605
+ ] }) : null,
606
+ git && showChip("git") ? /* @__PURE__ */ jsxs(Text, { children: [
559
607
  /* @__PURE__ */ jsxs(Text, { color: "magenta", children: [
560
608
  "\u2387 ",
561
- git.branch
609
+ truncateChip(git.branch, 24)
562
610
  ] }),
563
611
  git.deleted > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
564
612
  " -",
@@ -568,52 +616,43 @@ function StatusBar({
568
616
  " ?",
569
617
  git.untracked
570
618
  ] }) : null
571
- ] })
572
- ] }) : null,
573
- sessionCount != null && sessionCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
574
- yolo || startedAt != null || projectName || workingDir || git && !hiddenSet.has("git") ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
575
- /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
619
+ ] }) : null,
620
+ sessionCount != null && sessionCount > 0 && showChip("sessions") ? /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
576
621
  "\u29C9 ",
577
622
  sessionCount,
578
623
  " session",
579
624
  sessionCount === 1 ? "" : "s"
580
- ] })
581
- ] }) : null,
582
- toolCount != null ? /* @__PURE__ */ jsxs(Fragment, { children: [
583
- yolo || startedAt != null || projectName || workingDir || git && !hiddenSet.has("git") || sessionCount ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
584
- /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
625
+ ] }) : null,
626
+ toolCount != null && showChip("tools") ? /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
585
627
  "\u{1F527} ",
586
628
  toolCount,
587
629
  " tool",
588
630
  toolCount === 1 ? "" : "s"
589
- ] })
590
- ] }) : null,
591
- tokenSavingMode ? /* @__PURE__ */ jsxs(Fragment, { children: [
592
- yolo || startedAt != null || projectName || workingDir || git && !hiddenSet.has("git") || sessionCount || toolCount ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
593
- /* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: "\u{1F4BE} save" })
594
- ] }) : null
595
- ] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
596
- hasThirdLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
597
- todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && !hiddenSet.has("todos") ? /* @__PURE__ */ jsxs(Text, { children: [
598
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "todos " }),
599
- todos.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
600
- "\u231B",
601
- todos.inProgress
602
631
  ] }) : null,
603
- todos.inProgress > 0 && (todos.pending > 0 || todos.completed > 0) ? " " : "",
604
- todos.pending > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
605
- "\u2610",
606
- todos.pending
632
+ tokenSavingMode && showChip("token_saving") ? /* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: "\u{1F4BE} save" }) : null
633
+ ].filter((c) => c !== null),
634
+ termWidth - 6
635
+ ) }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
636
+ hasThirdLine ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: renderChipLine(
637
+ [
638
+ todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && showChip("todos") ? /* @__PURE__ */ jsxs(Text, { children: [
639
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "todos " }),
640
+ todos.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
641
+ "\u231B",
642
+ todos.inProgress
643
+ ] }) : null,
644
+ todos.inProgress > 0 && (todos.pending > 0 || todos.completed > 0) ? " " : "",
645
+ todos.pending > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
646
+ "\u2610",
647
+ todos.pending
648
+ ] }) : null,
649
+ todos.pending > 0 && todos.completed > 0 ? " " : "",
650
+ todos.completed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
651
+ "\u2713",
652
+ todos.completed
653
+ ] }) : null
607
654
  ] }) : null,
608
- todos.pending > 0 && todos.completed > 0 ? " " : "",
609
- todos.completed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
610
- "\u2713",
611
- todos.completed
612
- ] }) : null
613
- ] }) : null,
614
- plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) && !hiddenSet.has("plan") ? /* @__PURE__ */ jsxs(Fragment, { children: [
615
- todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && !hiddenSet.has("todos") ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
616
- /* @__PURE__ */ jsxs(Text, { children: [
655
+ plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) && showChip("plan") ? /* @__PURE__ */ jsxs(Text, { children: [
617
656
  /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u{1F4CB} " }),
618
657
  plan.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
619
658
  "\u231B",
@@ -634,11 +673,8 @@ function StatusBar({
634
673
  plan.scope,
635
674
  "]"
636
675
  ] }) : null
637
- ] })
638
- ] }) : null,
639
- hasTaskActivity && !hiddenSet.has("tasks") ? /* @__PURE__ */ jsxs(Fragment, { children: [
640
- 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,
641
- /* @__PURE__ */ jsxs(Text, { children: [
676
+ ] }) : null,
677
+ hasTaskActivity && showChip("tasks") ? /* @__PURE__ */ jsxs(Text, { children: [
642
678
  /* @__PURE__ */ jsx(Text, { color: "magenta", children: "\u26A1 " }),
643
679
  tasks.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
644
680
  "\u231B",
@@ -669,11 +705,8 @@ function StatusBar({
669
705
  tasks.scope,
670
706
  "]"
671
707
  ] }) : null
672
- ] })
673
- ] }) : null,
674
- fleetHasActivity && !hiddenSet.has("fleet") ? /* @__PURE__ */ jsxs(Fragment, { children: [
675
- 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,
676
- fleet ? /* @__PURE__ */ jsxs(Text, { children: [
708
+ ] }) : null,
709
+ fleetHasActivity && showChip("fleet") ? fleet ? /* @__PURE__ */ jsxs(Text, { children: [
677
710
  /* @__PURE__ */ jsx(Text, { color: "blue", children: "\u{1F310} " }),
678
711
  fleet.running > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
679
712
  "\u25B6",
@@ -700,15 +733,9 @@ function StatusBar({
700
733
  subagentCount,
701
734
  " agent",
702
735
  subagentCount === 1 ? "" : "s"
703
- ] })
704
- ] }) : null,
705
- showBrain ? /* @__PURE__ */ jsxs(Fragment, { children: [
706
- 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,
707
- /* @__PURE__ */ jsx(BrainChip, { brain })
708
- ] }) : null,
709
- showDebugStream ? /* @__PURE__ */ jsxs(Fragment, { children: [
710
- 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,
711
- /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
736
+ ] }) : null,
737
+ showBrain ? /* @__PURE__ */ jsx(BrainChip, { brain }) : null,
738
+ showDebugStream ? /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
712
739
  /* @__PURE__ */ jsx(Text, { bold: true, children: "\u{1F41B} stream" }),
713
740
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
714
741
  " #",
@@ -728,31 +755,28 @@ function StatusBar({
728
755
  " \xB7 ",
729
756
  fmtDebugBytes(debugStreamStats.totalBytes)
730
757
  ] })
731
- ] })
732
- ] }) : null,
733
- showEnhance ? /* @__PURE__ */ jsxs(Fragment, { children: [
734
- 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,
735
- /* @__PURE__ */ jsxs(Text, { color: enhanceCountdown > 15 ? "green" : enhanceCountdown > 5 ? "yellow" : "red", children: [
758
+ ] }) : null,
759
+ showEnhance ? /* @__PURE__ */ jsxs(Text, { color: countdownColor(enhanceCountdown, 15, 5), children: [
736
760
  "\u23F3 auto-send in ",
737
761
  enhanceCountdown,
738
762
  "s"
739
- ] })
740
- ] }) : null,
741
- hasNextStepsAutoSubmit && nextStepsAutoSubmitCountdown != null ? /* @__PURE__ */ jsxs(Fragment, { children: [
742
- 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,
743
- /* @__PURE__ */ jsxs(Text, { color: countdownColor, bold: true, children: [
744
- "\u23F3 ",
745
- nextStepsAutoSubmitCountdown,
746
- "s"
747
- ] }),
748
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
749
- " ",
750
- nextStepsAutoSubmitLabel ? formatSuggestionLabel(nextStepsAutoSubmitLabel) : "",
751
- " \xB7 \u21E5 edit"
752
- ] })
753
- ] }) : null
754
- ] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
755
- mailbox && !hiddenSet.has("mailbox") ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
763
+ ] }) : null,
764
+ hasNextStepsAutoSubmit && nextStepsAutoSubmitCountdown != null && showChip("next_steps") ? /* @__PURE__ */ jsxs(Fragment, { children: [
765
+ /* @__PURE__ */ jsxs(Text, { color: nextStepsColor, bold: true, children: [
766
+ "\u23F3 ",
767
+ nextStepsAutoSubmitCountdown,
768
+ "s"
769
+ ] }),
770
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
771
+ " ",
772
+ nextStepsAutoSubmitLabel ? formatSuggestionLabel(nextStepsAutoSubmitLabel) : "",
773
+ " \xB7 \u21E5 edit"
774
+ ] })
775
+ ] }) : null
776
+ ].filter((c) => c !== null),
777
+ termWidth - 6
778
+ ) }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
779
+ mailbox && showMailbox ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
756
780
  mailbox.unread > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", bold: true, children: [
757
781
  "\u2709 ",
758
782
  mailbox.unread,
@@ -786,37 +810,9 @@ function StatusBar({
786
810
  mailbox.lastSubject.length > 40 ? `${mailbox.lastSubject.slice(0, 37)}\u2026` : mailbox.lastSubject
787
811
  ] })
788
812
  ] }) : null,
789
- fleetAgents && fleetAgents.length > 0 ? fleetAgents.map((a, i) => (
790
- // biome-ignore lint/suspicious/noArrayIndexKey: agent list is stable per render
791
- /* @__PURE__ */ jsxs(Text, { children: [
792
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
793
- " ",
794
- /* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
795
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
796
- /* @__PURE__ */ jsx(Text, { dimColor: !a.running, ...a.running ? { color: "yellow" } : {}, children: a.running ? "\u25B6" : "\xB7" }),
797
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
798
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtElapsed(a.elapsedMs) }),
799
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
800
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
801
- a.toolCalls,
802
- "t"
803
- ] }),
804
- a.tool ? /* @__PURE__ */ jsxs(Fragment, { children: [
805
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
806
- /* @__PURE__ */ jsx(Text, { color: "cyan", children: a.tool })
807
- ] }) : null,
808
- a.extensions && a.extensions > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
809
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
810
- /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
811
- "\u26A1\xD7",
812
- a.extensions
813
- ] })
814
- ] }) : null
815
- ] }, i)
816
- )) : null
817
- ] }) : fleetAgents && fleetAgents.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => (
818
- // biome-ignore lint/suspicious/noArrayIndexKey: agent list is stable per render
819
- /* @__PURE__ */ jsxs(Text, { children: [
813
+ fleetAgents && fleetAgents.length > 0 && showChip("fleet_agents") ? fleetAgents.map((a, i) => /* @__PURE__ */ jsxs(Text, { children: [
814
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
815
+ " ",
820
816
  /* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
821
817
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
822
818
  /* @__PURE__ */ jsx(Text, { dimColor: !a.running, ...a.running ? { color: "yellow" } : {}, children: a.running ? "\u25B6" : "\xB7" }),
@@ -838,8 +834,30 @@ function StatusBar({
838
834
  a.extensions
839
835
  ] })
840
836
  ] }) : null
841
- ] }, i)
842
- )) }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) })
837
+ ] }, i)) : null
838
+ ] }) : fleetAgents && fleetAgents.length > 0 && showChip("fleet_agents") ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => /* @__PURE__ */ jsxs(Text, { children: [
839
+ /* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
840
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
841
+ /* @__PURE__ */ jsx(Text, { dimColor: !a.running, ...a.running ? { color: "yellow" } : {}, children: a.running ? "\u25B6" : "\xB7" }),
842
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
843
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtElapsed(a.elapsedMs) }),
844
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
845
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
846
+ a.toolCalls,
847
+ "t"
848
+ ] }),
849
+ a.tool ? /* @__PURE__ */ jsxs(Fragment, { children: [
850
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
851
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: a.tool })
852
+ ] }) : null,
853
+ a.extensions && a.extensions > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
854
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
855
+ /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
856
+ "\u26A1\xD7",
857
+ a.extensions
858
+ ] })
859
+ ] }) : null
860
+ ] }, i)) }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) })
843
861
  ]
844
862
  }
845
863
  );
@@ -981,10 +999,7 @@ var WAVE_COLORS = [
981
999
  // flamingo
982
1000
  ];
983
1001
  function WaveText({ text, phase }) {
984
- return /* @__PURE__ */ jsx(Text, { bold: true, children: Array.from(text).map((ch, i) => (
985
- // biome-ignore lint/suspicious/noArrayIndexKey: glyph order is positional and re-rendered each tick
986
- /* @__PURE__ */ jsx(Text, { color: WAVE_COLORS[(i + phase) % WAVE_COLORS.length] ?? "#ffffff", children: ch }, i)
987
- )) });
1002
+ return /* @__PURE__ */ jsx(Text, { bold: true, children: Array.from(text).map((ch, i) => /* @__PURE__ */ jsx(Text, { color: WAVE_COLORS[(i + phase) % WAVE_COLORS.length] ?? "#ffffff", children: ch }, i)) });
988
1003
  }
989
1004
  var FILLED = "\u2588";
990
1005
  var EMPTY = "\u2591";
@@ -1183,14 +1198,11 @@ function FleetMonitor({
1183
1198
  /* @__PURE__ */ jsx(Text, { bold: true, color: VERDICT_COLOR[collabSession.overallVerdict] ?? "white", children: collabSession.overallVerdict })
1184
1199
  ] }) : null
1185
1200
  ] }),
1186
- collabSession.timeline.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 0, children: collabSession.timeline.slice(0, 6).map((ev, i) => (
1187
- // biome-ignore lint/suspicious/noArrayIndexKey: timeline is rebuilt per render
1188
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1189
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${fmtElapsed(Math.max(0, nowTick - ev.at))} ago`.padEnd(10) }),
1190
- /* @__PURE__ */ jsx(Text, { ...ev.color ? { color: ev.color } : {}, children: ev.icon }),
1191
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: ev.text })
1192
- ] }, i)
1193
- )) }) : null
1201
+ collabSession.timeline.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 0, children: collabSession.timeline.slice(0, 6).map((ev, i) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1202
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${fmtElapsed(Math.max(0, nowTick - ev.at))} ago`.padEnd(10) }),
1203
+ /* @__PURE__ */ jsx(Text, { ...ev.color ? { color: ev.color } : {}, children: ev.icon }),
1204
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: ev.text })
1205
+ ] }, i)) }) : null
1194
1206
  ] }) : null,
1195
1207
  /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1196
1208
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "concurrency" }),
@@ -1228,7 +1240,7 @@ function FleetMonitor({
1228
1240
  const s2 = STATUS[e.status];
1229
1241
  const elapsed = e.status === "running" ? fmtElapsed(Math.max(0, nowTick - e.startedAt)) : fmtElapsed(Math.max(0, nowTick - e.lastEventAt)) + " ago";
1230
1242
  const model = fmtModelLabel(e.provider, e.model) || "\u2014";
1231
- const ltCtx = e.ctxPct !== void 0 ? `L${e.iterations} ${e.toolCalls}t ${Math.round(e.ctxPct * 100)}%` : `L${e.iterations} ${e.toolCalls}t`;
1243
+ const ltCtx = e.ctxPct !== void 0 ? `L${e.iterations} ${e.toolCalls}t ${Math.min(100, Math.max(0, Math.round(e.ctxPct * 100)))}%` : `L${e.iterations} ${e.toolCalls}t`;
1232
1244
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1233
1245
  /* @__PURE__ */ jsx(Text, { color: s2.color, children: s2.icon }),
1234
1246
  /* @__PURE__ */ jsx(Text, { children: e.name.padEnd(14).slice(0, 14) }),
@@ -1248,14 +1260,11 @@ function FleetMonitor({
1248
1260
  ] }) : null,
1249
1261
  timeline.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
1250
1262
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "timeline" }),
1251
- timeline.map((ev, i) => (
1252
- // biome-ignore lint/suspicious/noArrayIndexKey: timeline is rebuilt per render
1253
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1254
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${fmtElapsed(Math.max(0, nowTick - ev.at))} ago`.padEnd(10) }),
1255
- /* @__PURE__ */ jsx(Text, { color: ev.color, children: ev.icon }),
1256
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: ev.text })
1257
- ] }, i)
1258
- ))
1263
+ timeline.map((ev, i) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1264
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${fmtElapsed(Math.max(0, nowTick - ev.at))} ago`.padEnd(10) }),
1265
+ /* @__PURE__ */ jsx(Text, { color: ev.color, children: ev.icon }),
1266
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: ev.text })
1267
+ ] }, i))
1259
1268
  ] }) : null
1260
1269
  ] });
1261
1270
  }
@@ -1421,6 +1430,10 @@ function ContextBar({
1421
1430
  tokenText
1422
1431
  ] });
1423
1432
  }
1433
+ function pctTextFromRatio(pct) {
1434
+ if (typeof pct !== "number" || !Number.isFinite(pct)) return "0%";
1435
+ return `${Math.min(100, Math.max(0, Math.round(pct * 100)))}%`;
1436
+ }
1424
1437
  function AgentRow({
1425
1438
  entry,
1426
1439
  now,
@@ -1570,10 +1583,7 @@ function AgentDetail({
1570
1583
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "recent" }),
1571
1584
  entry.recentTools.slice(-4).map((tool, i) => {
1572
1585
  const visual = getToolVisual(tool.name);
1573
- return (
1574
- // biome-ignore lint/suspicious/noArrayIndexKey: recent tool entries do not carry stable ids.
1575
- /* @__PURE__ */ jsx(Text, { color: tool.ok === false ? "red" : visual.color, children: `\u2039${visual.glyph} ${formatRecentToolChip(tool)}\u203A` }, `${tool.name}-${tool.at}-${i}`)
1576
- );
1586
+ return /* @__PURE__ */ jsx(Text, { color: tool.ok === false ? "red" : visual.color, children: `\u2039${visual.glyph} ${formatRecentToolChip(tool)}\u203A` }, `${tool.name}-${tool.at}-${i}`);
1577
1587
  })
1578
1588
  ] }) : null,
1579
1589
  entry.status === "running" && streamTail ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
@@ -1678,14 +1688,13 @@ function AgentsMonitor({
1678
1688
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "pulse" }),
1679
1689
  /* @__PURE__ */ jsxs(Text, { color: pressure >= 0.9 ? "red" : pressure >= 0.75 ? "yellow" : "green", children: [
1680
1690
  "max ctx ",
1681
- Math.round(pressure * 100),
1682
- "%"
1691
+ pctTextFromRatio(pressure)
1683
1692
  ] }),
1684
1693
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 hot" }),
1685
1694
  hotAgent ? /* @__PURE__ */ jsxs(Text, { color: riskMeta(agentRisk(hotAgent)).color, children: [
1686
1695
  hotAgent.name,
1687
1696
  " ",
1688
- hotAgent.ctxPct !== void 0 ? `${Math.round(hotAgent.ctxPct * 100)}%` : ""
1697
+ hotAgent.ctxPct !== void 0 ? pctTextFromRatio(hotAgent.ctxPct) : ""
1689
1698
  ] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "none" }),
1690
1699
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 throughput" }),
1691
1700
  /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
@@ -1853,10 +1862,7 @@ function BrainDecisionPrompt({
1853
1862
  /* @__PURE__ */ jsx(Text, { color: "white", children: question }),
1854
1863
  ctx.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
1855
1864
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Context:" }),
1856
- ctx.map((line, index) => (
1857
- // biome-ignore lint/suspicious/noArrayIndexKey: context lines are static for this prompt render
1858
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: line }, index)
1859
- ))
1865
+ ctx.map((line, index) => /* @__PURE__ */ jsx(Text, { dimColor: true, children: line }, index))
1860
1866
  ] }) : null,
1861
1867
  options.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
1862
1868
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Options:" }),
@@ -3507,10 +3513,7 @@ function MarkdownView({
3507
3513
  /[\u2500-\u257F]/.test(qContent) ? (
3508
3514
  // Box-drawing characters inside blockquotes also need transparent
3509
3515
  // background to avoid inheriting the message panel background.
3510
- /* @__PURE__ */ jsx(Box, { flexDirection: "row", backgroundColor: "transparent", children: [...qContent].slice(0, (contentWidth ?? termWidth) - 2).map((ch, ci) => (
3511
- /* biome-ignore lint/suspicious/noArrayIndexKey: characters are not reorderable */
3512
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: ch }, ci)
3513
- )) })
3516
+ /* @__PURE__ */ jsx(Box, { flexDirection: "row", backgroundColor: "transparent", children: [...qContent].slice(0, (contentWidth ?? termWidth) - 2).map((ch, ci) => /* @__PURE__ */ jsx(Text, { dimColor: true, children: ch }, ci)) })
3514
3517
  ) : /* @__PURE__ */ jsx(InlineLine, { tokens: parseInline(qContent), dim: true })
3515
3518
  ] }, `q${key++}`)
3516
3519
  );
@@ -3540,10 +3543,7 @@ function MarkdownView({
3540
3543
  const maxW = contentWidth ?? termWidth;
3541
3544
  const chars = [...line].slice(0, maxW);
3542
3545
  rows.push(
3543
- /* @__PURE__ */ jsx(Box, { width: maxW, backgroundColor: "transparent", flexDirection: "row", children: chars.map((ch, ci) => (
3544
- /* biome-ignore lint/suspicious/noArrayIndexKey: characters are not reorderable */
3545
- /* @__PURE__ */ jsx(Text, { children: ch }, ci)
3546
- )) }, `bx${key++}`)
3546
+ /* @__PURE__ */ jsx(Box, { width: maxW, backgroundColor: "transparent", flexDirection: "row", children: chars.map((ch, ci) => /* @__PURE__ */ jsx(Text, { children: ch }, ci)) }, `bx${key++}`)
3547
3547
  );
3548
3548
  continue;
3549
3549
  }
@@ -3633,6 +3633,19 @@ function formatMatchHit(hit) {
3633
3633
  return void 0;
3634
3634
  }
3635
3635
  var ARG_BUDGET = 60;
3636
+ function stringArrayOf(v) {
3637
+ return Array.isArray(v) ? v.filter((item) => typeof item === "string") : void 0;
3638
+ }
3639
+ function fileScopeSummary(files, fallback) {
3640
+ const list = stringArrayOf(files);
3641
+ if (list && list.length > 0) {
3642
+ const first = list[0] ?? "";
3643
+ const more = list.length > 1 ? ` (+${list.length - 1})` : "";
3644
+ return first ? `${shortenPath(first, 42)}${more}` : `${list.length} files`;
3645
+ }
3646
+ const scalar = typeof files === "string" ? files : fallback;
3647
+ return scalar ? shortenPath(scalar, 44) : "";
3648
+ }
3636
3649
  function formatToolArgs(toolName, input) {
3637
3650
  if (!input || typeof input !== "object") return "";
3638
3651
  const obj = input;
@@ -3641,13 +3654,18 @@ function formatToolArgs(toolName, input) {
3641
3654
  case "write":
3642
3655
  case "edit":
3643
3656
  case "patch":
3644
- case "document":
3645
3657
  case "list_dir":
3646
3658
  case "ls":
3647
3659
  case "tree": {
3648
3660
  const p = stringOf(obj["path"]) ?? stringOf(obj["file"]);
3649
3661
  return p ? shortenPath(p, ARG_BUDGET) : "";
3650
3662
  }
3663
+ case "document": {
3664
+ const target = stringOf(obj["target"]) ?? "all";
3665
+ const scope = fileScopeSummary(obj["files"], stringOf(obj["path"]));
3666
+ const style = stringOf(obj["style"]);
3667
+ return [target, scope, style].filter(Boolean).join(" \xB7 ");
3668
+ }
3651
3669
  case "grep":
3652
3670
  case "search":
3653
3671
  case "replace": {
@@ -3663,12 +3681,19 @@ function formatToolArgs(toolName, input) {
3663
3681
  }
3664
3682
  case "bash":
3665
3683
  case "shell":
3666
- case "exec":
3667
3684
  case "install":
3668
3685
  case "git": {
3669
3686
  const cmd = stringOf(obj["command"]) ?? stringOf(obj["args"]);
3670
3687
  return cmd ? truncMid(cmd, ARG_BUDGET) : "";
3671
3688
  }
3689
+ case "exec": {
3690
+ const command = stringOf(obj["command"]);
3691
+ const args = stringArrayOf(obj["args"]) ?? [];
3692
+ const cwd = stringOf(obj["cwd"]);
3693
+ const cmd = [command, ...args].filter(Boolean).join(" ");
3694
+ const head = cmd ? truncMid(cmd, cwd ? 44 : ARG_BUDGET) : "";
3695
+ return cwd ? `${head} in ${shortenPath(cwd, 14)}` : head;
3696
+ }
3672
3697
  case "diff": {
3673
3698
  const files = Array.isArray(obj["files"]) ? obj["files"] : void 0;
3674
3699
  if (files && files.length > 0) {
@@ -3690,6 +3715,19 @@ function formatToolArgs(toolName, input) {
3690
3715
  if (Array.isArray(list)) return `${list.length} item${list.length === 1 ? "" : "s"}`;
3691
3716
  return "";
3692
3717
  }
3718
+ case "plan": {
3719
+ const action = stringOf(obj["action"]) ?? "show";
3720
+ const target = stringOf(obj["target"]) ?? stringOf(obj["title"]) ?? stringOf(obj["template"]) ?? "";
3721
+ const scope = stringOf(obj["scope"]);
3722
+ return [action, target ? truncMid(target, 34) : "", scope].filter(Boolean).join(" \xB7 ");
3723
+ }
3724
+ case "task": {
3725
+ const action = stringOf(obj["action"]) ?? "show";
3726
+ const task = obj["task"] && typeof obj["task"] === "object" ? obj["task"] : void 0;
3727
+ const target = stringOf(obj["target"]) ?? stringOf(obj["id"]) ?? stringOf(task?.["title"]) ?? (Array.isArray(obj["tasks"]) ? `${obj["tasks"].length} tasks` : "");
3728
+ const status = stringOf(obj["status"]);
3729
+ return [action, target ? truncMid(target, 32) : "", status].filter(Boolean).join(" \xB7 ");
3730
+ }
3693
3731
  case "lint":
3694
3732
  case "format":
3695
3733
  case "typecheck":
@@ -3717,19 +3755,79 @@ function formatToolArgs(toolName, input) {
3717
3755
  if (tmpl && name) return `${tmpl} \u2192 ${truncMid(name, ARG_BUDGET - tmpl.length - 4)}`;
3718
3756
  return name ?? tmpl ?? "";
3719
3757
  }
3720
- case "remember":
3721
- case "forget":
3758
+ case "remember": {
3759
+ const scope = stringOf(obj["scope"]);
3760
+ const type = stringOf(obj["type"]);
3761
+ const text = stringOf(obj["text"]);
3762
+ return [scope, type, text ? truncMid(text, 34) : ""].filter(Boolean).join(" \xB7 ");
3763
+ }
3764
+ case "forget": {
3765
+ const query = stringOf(obj["query"]);
3766
+ const scope = stringOf(obj["scope"]);
3767
+ return [query ? `"${truncMid(query, 36)}"` : "", scope].filter(Boolean).join(" \xB7 ");
3768
+ }
3769
+ case "search_memory":
3770
+ case "find_related_memories": {
3771
+ const query = stringOf(obj["query"]) ?? stringOf(obj["text"]);
3772
+ const scope = stringOf(obj["scope"]);
3773
+ return [query ? `"${truncMid(query, 36)}"` : "", scope].filter(Boolean).join(" \xB7 ");
3774
+ }
3722
3775
  case "memory": {
3723
3776
  const key = stringOf(obj["key"]) ?? stringOf(obj["name"]);
3724
3777
  return key ? truncMid(key, ARG_BUDGET) : "";
3725
3778
  }
3726
3779
  case "mode": {
3780
+ const action = stringOf(obj["action"]);
3727
3781
  const m = stringOf(obj["mode"]) ?? stringOf(obj["name"]);
3728
- return m ? truncMid(m, ARG_BUDGET) : "";
3782
+ return [action, m].filter(Boolean).join(" \xB7 ");
3729
3783
  }
3730
3784
  case "logs": {
3731
3785
  const target = stringOf(obj["target"]) ?? stringOf(obj["service"]) ?? stringOf(obj["path"]);
3732
- return target ? truncMid(target, ARG_BUDGET) : "";
3786
+ const filter = stringOf(obj["filter"]);
3787
+ const since = stringOf(obj["since"]);
3788
+ const lines = typeof obj["lines"] === "number" ? `${obj["lines"]} lines` : "";
3789
+ return [target ? shortenPath(target, 34) : "", filter ? `/${truncMid(filter, 16)}/` : "", since, lines].filter(Boolean).join(" \xB7 ");
3790
+ }
3791
+ case "tool_help": {
3792
+ const tool = stringOf(obj["tool"]) ?? "all";
3793
+ const format = stringOf(obj["format"]);
3794
+ return [tool, format].filter(Boolean).join(" \xB7 ");
3795
+ }
3796
+ case "tool_search": {
3797
+ const query = stringOf(obj["query"]);
3798
+ const tags = stringArrayOf(obj["tags"]);
3799
+ const filters = [
3800
+ query ? `"${truncMid(query, 28)}"` : "",
3801
+ tags && tags.length > 0 ? tags.join(",") : "",
3802
+ stringOf(obj["permission"]),
3803
+ typeof obj["mutating"] === "boolean" ? obj["mutating"] ? "mutating" : "read-only" : ""
3804
+ ].filter(Boolean);
3805
+ return filters.join(" \xB7 ");
3806
+ }
3807
+ case "tool_use": {
3808
+ const tool = stringOf(obj["tool"]);
3809
+ return tool ? `call ${tool}` : "";
3810
+ }
3811
+ case "batch_tool_use": {
3812
+ const calls = Array.isArray(obj["calls"]) ? obj["calls"] : [];
3813
+ const mode = obj["parallel"] === false ? "sequential" : "parallel";
3814
+ return `${calls.length} call${calls.length === 1 ? "" : "s"} \xB7 ${mode}`;
3815
+ }
3816
+ case "codebase-index": {
3817
+ const langs = stringArrayOf(obj["langs"]);
3818
+ const force = obj["force"] === true ? "force" : "";
3819
+ return [force, langs && langs.length > 0 ? langs.join(",") : "incremental"].filter(Boolean).join(" \xB7 ");
3820
+ }
3821
+ case "codebase-search": {
3822
+ const query = stringOf(obj["query"]);
3823
+ const filters = [stringOf(obj["kind"]), stringOf(obj["lang"]), stringOf(obj["file"]) ? `in ${shortenPath(String(obj["file"]), 24)}` : ""].filter(Boolean).join(" \xB7 ");
3824
+ return [query ? `"${truncMid(query, 30)}"` : "", filters].filter(Boolean).join(" \xB7 ");
3825
+ }
3826
+ case "codebase-stats":
3827
+ return "index health";
3828
+ case "set_working_dir": {
3829
+ const p = stringOf(obj["path"]);
3830
+ return p ? shortenPath(p, ARG_BUDGET) : "current";
3733
3831
  }
3734
3832
  }
3735
3833
  for (const key of ["path", "file", "url", "name", "query", "pattern", "command"]) {
@@ -4102,6 +4200,716 @@ function formatToolOutput(toolName, output, ok, _outputBytes, outputLines) {
4102
4200
  const collapsed = text.replace(/\s+/g, " ").trim();
4103
4201
  return [truncMid(collapsed, GENERIC_BUDGET)];
4104
4202
  }
4203
+ var VISUAL_MAX_LINES = 7;
4204
+ var VISUAL_TEXT_BUDGET = 92;
4205
+ function formatToolVisualOutput(toolName, output, ok, input) {
4206
+ if (!output) return void 0;
4207
+ const text = output.trim();
4208
+ if (!text) return void 0;
4209
+ if (toolName === "read") return visualRead(text);
4210
+ if (toolName === "grep" || toolName === "search") return visualSearch(toolName, text);
4211
+ if (toolName === "glob") return visualPathList(toolName, text);
4212
+ if (toolName === "tree") return visualTree(text);
4213
+ if (toolName === "bash" || toolName === "shell" || toolName === "git" || toolName === "exec" || toolName === "install") {
4214
+ return visualCommand(toolName, text, ok);
4215
+ }
4216
+ if (toolName === "test" || toolName === "lint" || toolName === "typecheck" || toolName === "format") {
4217
+ return visualVerifier(toolName, text, ok);
4218
+ }
4219
+ if (toolName === "fetch" || toolName === "webfetch" || toolName === "web_fetch") {
4220
+ return visualFetch(text);
4221
+ }
4222
+ if (toolName === "json") return visualJson(text);
4223
+ if (toolName === "outdated") return visualOutdated(text);
4224
+ if (toolName === "audit") return visualAudit(text);
4225
+ if (toolName === "scaffold") return visualScaffold(text);
4226
+ if (toolName === "todo") return visualTodo(text);
4227
+ if (toolName === "task" || toolName === "plan") return visualWorkBoard(toolName, text, ok);
4228
+ if (toolName === "remember" || toolName === "forget" || toolName === "search_memory" || toolName === "find_related_memories") {
4229
+ return visualMemory(toolName, text, ok);
4230
+ }
4231
+ if (toolName === "logs") return visualLogs(text);
4232
+ if (toolName === "document") return visualDocument(text);
4233
+ if (toolName === "tool_help" || toolName === "tool_search") return visualToolCatalog(toolName, text);
4234
+ if (toolName === "tool_use" || toolName === "batch_tool_use") return visualMetaExecution(toolName, text, ok);
4235
+ if (toolName === "codebase-index" || toolName === "codebase-search" || toolName === "codebase-stats") {
4236
+ return visualCodebase(toolName, text, ok);
4237
+ }
4238
+ if (toolName === "set_working_dir") return visualWorkingDir(text, ok);
4239
+ if (toolName === "mode") return visualMode(text, ok);
4240
+ return void 0;
4241
+ }
4242
+ function ToolOutputLines({ lines, hasFollowingBlock }) {
4243
+ return /* @__PURE__ */ jsx(Fragment, { children: lines.map((line, i) => {
4244
+ const branch = i === lines.length - 1 && !hasFollowingBlock ? " \u2514\u2500 " : " \u251C\u2500 ";
4245
+ const color = colorForVisualKind(line.kind);
4246
+ return /* @__PURE__ */ jsxs(Text, { children: [
4247
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: branch }),
4248
+ line.marker ? /* @__PURE__ */ jsx(Text, { color, bold: true, children: line.marker }) : null,
4249
+ line.path ? /* @__PURE__ */ jsxs(Fragment, { children: [
4250
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: shortenPath(line.path, 56) }),
4251
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " " })
4252
+ ] }) : null,
4253
+ line.lineNo ? /* @__PURE__ */ jsxs(Fragment, { children: [
4254
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: String(line.lineNo).padStart(4, " ") }),
4255
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " })
4256
+ ] }) : null,
4257
+ /* @__PURE__ */ jsx(Text, { color, dimColor: line.kind === "meta" || line.kind === "stdout", children: truncMid(line.text, VISUAL_TEXT_BUDGET) })
4258
+ ] }, `${line.kind}-${i}`);
4259
+ }) });
4260
+ }
4261
+ function colorForVisualKind(kind) {
4262
+ switch (kind) {
4263
+ case "ok":
4264
+ return "green";
4265
+ case "warn":
4266
+ return "yellow";
4267
+ case "error":
4268
+ case "stderr":
4269
+ return "red";
4270
+ case "path":
4271
+ case "match":
4272
+ return "cyan";
4273
+ case "code":
4274
+ return "white";
4275
+ case "stdout":
4276
+ case "meta":
4277
+ return void 0;
4278
+ }
4279
+ }
4280
+ function visualRead(text) {
4281
+ const lines = bodyLines(text);
4282
+ const numbered = lines.map((line) => line.match(/^\s*(\d+)→(.*)$/)).filter((match) => Boolean(match?.[1]));
4283
+ if (numbered.length === 0) {
4284
+ const first = firstNonEmpty(lines.join("\n"));
4285
+ return first ? [{ kind: "meta", text: first }] : void 0;
4286
+ }
4287
+ const rows = numbered.slice(0, 5).map((match) => ({
4288
+ kind: "code",
4289
+ lineNo: match[1],
4290
+ text: match[2] ?? ""
4291
+ }));
4292
+ if (numbered.length > rows.length) {
4293
+ rows.push({ kind: "meta", text: `${numbered.length - rows.length} more read line(s)` });
4294
+ }
4295
+ return rows;
4296
+ }
4297
+ function visualSearch(toolName, text) {
4298
+ const json = tryParseJson(text);
4299
+ if (json && typeof json === "object") {
4300
+ const obj = json;
4301
+ const matches = Array.isArray(obj["matches"]) ? obj["matches"] : Array.isArray(obj["results"]) ? obj["results"] : [];
4302
+ return visualSearchMatches(matches, numOf(obj["count"]) ?? matches.length);
4303
+ }
4304
+ const lines = bodyLines(text);
4305
+ if (lines.length === 0 || lines[0] === "(no matches)") return void 0;
4306
+ const rows = [];
4307
+ let currentPath;
4308
+ let consumed = 0;
4309
+ for (const line of lines) {
4310
+ if (consumed >= VISUAL_MAX_LINES) break;
4311
+ const fileHeader = line.match(/^(.+?) \((\d+) match\(es\), showing \d+\)$/);
4312
+ if (fileHeader?.[1]) {
4313
+ currentPath = fileHeader[1];
4314
+ rows.push({ kind: "path", path: currentPath, text: `${fileHeader[2] ?? "?"} match(es)` });
4315
+ consumed++;
4316
+ continue;
4317
+ }
4318
+ const direct = line.match(/^(.+?):(\d+):(.*)$/);
4319
+ const grouped = line.match(/^(\d+):(.*)$/);
4320
+ if (direct?.[1] && direct[2]) {
4321
+ rows.push({ kind: "match", path: direct[1], lineNo: direct[2], text: direct[3] ?? "" });
4322
+ consumed++;
4323
+ } else if (grouped?.[1]) {
4324
+ rows.push({ kind: "match", path: currentPath, lineNo: grouped[1], text: grouped[2] ?? "" });
4325
+ consumed++;
4326
+ } else if (line.trim() && !line.startsWith(`${toolName}:`)) {
4327
+ rows.push({ kind: "meta", text: line.trim() });
4328
+ consumed++;
4329
+ }
4330
+ }
4331
+ if (lines.length > consumed) rows.push({ kind: "meta", text: `${lines.length - consumed} more result line(s)` });
4332
+ return rows.length > 0 ? rows : void 0;
4333
+ }
4334
+ function visualSearchMatches(matches, count) {
4335
+ if (count === 0) return [{ kind: "ok", marker: "ok ", text: "no matches" }];
4336
+ const rows = [];
4337
+ for (const match of matches.slice(0, VISUAL_MAX_LINES)) {
4338
+ const hit = parseMatchHit(match);
4339
+ if (hit) rows.push({ kind: "match", path: hit.path, lineNo: hit.line, text: hit.text });
4340
+ }
4341
+ if (rows.length === 0) return count > 0 ? [{ kind: "meta", text: `${count} result${count === 1 ? "" : "s"}` }] : void 0;
4342
+ if (count > rows.length) rows.push({ kind: "meta", text: `${count - rows.length} more result(s)` });
4343
+ return rows;
4344
+ }
4345
+ function parseMatchHit(hit) {
4346
+ if (typeof hit === "string") {
4347
+ const m = hit.match(/^(.+?):(\d+):(.*)$/);
4348
+ return m?.[1] && m[2] ? { path: m[1], line: m[2], text: m[3] ?? "" } : { text: hit };
4349
+ }
4350
+ if (hit && typeof hit === "object") {
4351
+ const o = hit;
4352
+ const path7 = stringOf(o["file"]) ?? stringOf(o["path"]) ?? stringOf(o["url"]);
4353
+ const line = numOf(o["line"]) ?? numOf(o["lineNumber"]);
4354
+ const title = stringOf(o["title"]);
4355
+ const snippet2 = stringOf(o["snippet"]);
4356
+ const text = stringOf(o["text"]) ?? stringOf(o["match"]) ?? stringOf(o["preview"]) ?? [title, snippet2].filter(Boolean).join(" \u2014 ");
4357
+ return { path: path7, line: line === void 0 ? void 0 : String(line), text };
4358
+ }
4359
+ return void 0;
4360
+ }
4361
+ function visualPathList(toolName, text) {
4362
+ const json = tryParseJson(text);
4363
+ const files = json && typeof json === "object" && Array.isArray(json["files"]) ? json["files"].filter((v) => typeof v === "string") : bodyLines(text).filter((line) => line.trim() && !line.startsWith(`${toolName}:`));
4364
+ if (files.length === 0) return void 0;
4365
+ const rows = files.slice(0, VISUAL_MAX_LINES).map((file) => ({
4366
+ kind: "path",
4367
+ path: file,
4368
+ text: ""
4369
+ }));
4370
+ if (files.length > rows.length) rows.push({ kind: "meta", text: `${files.length - rows.length} more path(s)` });
4371
+ return rows;
4372
+ }
4373
+ function visualTree(text) {
4374
+ const lines = bodyLines(text).filter((line) => line.trim());
4375
+ if (lines.length === 0) return void 0;
4376
+ const rows = lines.slice(0, VISUAL_MAX_LINES).map((line) => ({
4377
+ kind: line.includes("\u2500\u2500") || line.includes("|--") ? "path" : "meta",
4378
+ text: line
4379
+ }));
4380
+ if (lines.length > rows.length) rows.push({ kind: "meta", text: `${lines.length - rows.length} more tree line(s)` });
4381
+ return rows;
4382
+ }
4383
+ function visualCommand(toolName, text, ok) {
4384
+ const json = tryParseJson(text);
4385
+ if (json && typeof json === "object") {
4386
+ const obj = json;
4387
+ return commandRows({
4388
+ exit: numOf(obj["exit_code"]) ?? numOf(obj["exitCode"]),
4389
+ timedOut: obj["timed_out"] === true || obj["timedOut"] === true,
4390
+ stdout: stringOf(obj["stdout"]) ?? stringOf(obj["output"]),
4391
+ stderr: stringOf(obj["stderr"]) ?? stringOf(obj["error"]),
4392
+ ok
4393
+ });
4394
+ }
4395
+ const header = parseHeaderLine(text);
4396
+ const sections = parseNamedSections(text);
4397
+ return commandRows({
4398
+ exit: numberFromParsedField(header.fields, "exit_code") ?? numberFromParsedField(header.fields, "exitCode"),
4399
+ timedOut: header.fields["timed_out"] === "true" || header.fields["timedOut"] === "true",
4400
+ stdout: sections.get("stdout") ?? sections.get("output"),
4401
+ stderr: sections.get("stderr") ?? sections.get("error"),
4402
+ ok,
4403
+ label: toolName
4404
+ });
4405
+ }
4406
+ function commandRows(opts) {
4407
+ const rows = [];
4408
+ const statusKind = opts.timedOut ? "warn" : opts.ok && (opts.exit ?? 0) === 0 ? "ok" : "error";
4409
+ const status = opts.timedOut ? "timed out" : opts.exit !== void 0 ? `exit ${opts.exit}` : opts.ok ? "completed" : "failed";
4410
+ rows.push({ kind: statusKind, marker: statusKind === "ok" ? "ok " : statusKind === "warn" ? "! " : "x ", text: opts.label ? `${opts.label} ${status}` : status });
4411
+ appendOutputPreview(rows, opts.stdout, "stdout");
4412
+ appendOutputPreview(rows, opts.stderr, "stderr");
4413
+ return rows.length > 0 ? rows.slice(0, VISUAL_MAX_LINES) : void 0;
4414
+ }
4415
+ function visualVerifier(toolName, text, ok) {
4416
+ const json = tryParseJson(text);
4417
+ if (json && typeof json === "object") {
4418
+ const obj = json;
4419
+ const errors = numOf(obj["errors"]) ?? numOf(obj["failed"]) ?? 0;
4420
+ const warnings = numOf(obj["warnings"]) ?? 0;
4421
+ const changed2 = numOf(obj["files_changed"]) ?? 0;
4422
+ const statusKind2 = !ok || errors > 0 ? "error" : changed2 > 0 ? "warn" : "ok";
4423
+ const parts = [
4424
+ toolName,
4425
+ errors > 0 ? `${errors} error${errors === 1 ? "" : "s"}` : void 0,
4426
+ warnings > 0 ? `${warnings} warning${warnings === 1 ? "" : "s"}` : void 0,
4427
+ changed2 > 0 ? `${changed2} changed` : void 0,
4428
+ toolName === "test" ? `${numOf(obj["passed"]) ?? 0}/${numOf(obj["tests_run"]) ?? 0} passed` : void 0
4429
+ ].filter(Boolean);
4430
+ return [{ kind: statusKind2, marker: statusKind2 === "ok" ? "ok " : statusKind2 === "warn" ? "! " : "x ", text: parts.join(" \xB7 ") || toolName }];
4431
+ }
4432
+ const header = parseHeaderLine(text);
4433
+ const sections = parseNamedSections(text);
4434
+ const report = sections.get("report") ?? "";
4435
+ const errorContext = sections.get("error_context");
4436
+ const fields = { ...header.fields, ...parseKeyValueLines(report) };
4437
+ const status = fields["status"];
4438
+ const errorCount = numberFromParsedField(fields, "errors") ?? numberFromParsedField(fields, "failed") ?? 0;
4439
+ const warningCount = numberFromParsedField(fields, "warnings") ?? 0;
4440
+ const changed = numberFromParsedField(fields, "files_changed") ?? 0;
4441
+ const statusKind = !ok || errorContext || errorCount > 0 ? "error" : status === "changed" || changed > 0 ? "warn" : "ok";
4442
+ const rows = [{
4443
+ kind: statusKind,
4444
+ marker: statusKind === "ok" ? "ok " : statusKind === "warn" ? "! " : "x ",
4445
+ text: [
4446
+ toolName,
4447
+ status ? `status=${status}` : void 0,
4448
+ errorCount > 0 ? `${errorCount} error${errorCount === 1 ? "" : "s"}` : void 0,
4449
+ warningCount > 0 ? `${warningCount} warning${warningCount === 1 ? "" : "s"}` : void 0,
4450
+ changed > 0 ? `${changed} changed` : void 0
4451
+ ].filter(Boolean).join(" \xB7 ")
4452
+ }];
4453
+ appendOutputPreview(rows, errorContext, "stderr");
4454
+ return rows.slice(0, VISUAL_MAX_LINES);
4455
+ }
4456
+ function visualFetch(text) {
4457
+ const json = tryParseJson(text);
4458
+ if (json && typeof json === "object") {
4459
+ const obj = json;
4460
+ const status = numOf(obj["status"]);
4461
+ const ct = stringOf(obj["content_type"]);
4462
+ const content = stringOf(obj["content"]);
4463
+ return fetchRows(status, ct, content);
4464
+ }
4465
+ const header = parseHeaderLine(text);
4466
+ return fetchRows(
4467
+ numberFromParsedField(header.fields, "status"),
4468
+ header.fields["content_type"],
4469
+ bodyLines(text).join("\n")
4470
+ );
4471
+ }
4472
+ function fetchRows(status, contentType, content) {
4473
+ const kind = status === void 0 ? "meta" : status >= 200 && status < 300 ? "ok" : status >= 300 && status < 400 ? "warn" : "error";
4474
+ const rows = [{
4475
+ kind,
4476
+ marker: kind === "ok" ? "ok " : kind === "warn" ? "! " : kind === "error" ? "x " : void 0,
4477
+ text: [status !== void 0 ? `HTTP ${status}` : "HTTP", contentType?.split(";")[0]].filter(Boolean).join(" \xB7 ")
4478
+ }];
4479
+ const preview = firstNonEmpty(content ?? "");
4480
+ if (preview) rows.push({ kind: "stdout", text: preview });
4481
+ return rows;
4482
+ }
4483
+ function visualJson(text) {
4484
+ const json = tryParseJson(text);
4485
+ if (!json || typeof json !== "object" || Array.isArray(json)) return void 0;
4486
+ const obj = json;
4487
+ const err = stringOf(obj["error"]);
4488
+ if (err) return [{ kind: "error", marker: "x ", text: err }];
4489
+ const type = stringOf(obj["type"]);
4490
+ const keys = Array.isArray(obj["keys"]) ? obj["keys"].length : void 0;
4491
+ return [{ kind: "ok", marker: "ok ", text: [type ?? "json", keys !== void 0 ? `${keys} key${keys === 1 ? "" : "s"}` : void 0].filter(Boolean).join(" \xB7 ") }];
4492
+ }
4493
+ function visualOutdated(text) {
4494
+ const lines = bodyLines(text).filter((line) => line.trim() && !line.startsWith("outdated"));
4495
+ if (lines.length === 0) return void 0;
4496
+ return lines.slice(0, VISUAL_MAX_LINES).map((line) => ({ kind: "warn", marker: "! ", text: line }));
4497
+ }
4498
+ function visualAudit(text) {
4499
+ const lines = bodyLines(text).filter((line) => line.trim() && !line.startsWith("audit"));
4500
+ if (lines.length === 0) return void 0;
4501
+ return lines.slice(0, VISUAL_MAX_LINES).map((line) => ({
4502
+ kind: /^critical|^high/i.test(line) ? "error" : /^moderate|^medium/i.test(line) ? "warn" : "meta",
4503
+ marker: /^critical|^high/i.test(line) ? "x " : /^moderate|^medium/i.test(line) ? "! " : void 0,
4504
+ text: line
4505
+ }));
4506
+ }
4507
+ function visualScaffold(text) {
4508
+ const json = tryParseJson(text);
4509
+ if (!json || typeof json !== "object") return void 0;
4510
+ const obj = json;
4511
+ const created = Array.isArray(obj["created"]) ? obj["created"] : [];
4512
+ const skipped = Array.isArray(obj["skipped"]) ? obj["skipped"] : [];
4513
+ const rows = [];
4514
+ for (const file of created.slice(0, 5)) {
4515
+ if (typeof file === "string") rows.push({ kind: "ok", marker: "+ ", path: file, text: "" });
4516
+ }
4517
+ if (skipped.length > 0) rows.push({ kind: "warn", marker: "! ", text: `${skipped.length} skipped` });
4518
+ return rows.length > 0 ? rows : void 0;
4519
+ }
4520
+ function visualTodo(text) {
4521
+ const json = tryParseJson(text);
4522
+ const fields = json && typeof json === "object" && !Array.isArray(json) ? recordToStringFields(json) : parseHeaderLine(text).fields;
4523
+ const count = numberFromParsedField(fields, "count") ?? 0;
4524
+ const inProgress = numberFromParsedField(fields, "in_progress") ?? 0;
4525
+ return [{
4526
+ kind: count > 0 ? "ok" : "meta",
4527
+ marker: count > 0 ? "ok " : void 0,
4528
+ text: `${count} todo${count === 1 ? "" : "s"}${inProgress > 0 ? ` \xB7 ${inProgress} in progress` : ""}`
4529
+ }];
4530
+ }
4531
+ function visualWorkBoard(toolName, text, ok) {
4532
+ const json = tryParseJson(text);
4533
+ if (json && typeof json === "object" && !Array.isArray(json)) {
4534
+ const obj = json;
4535
+ const rows2 = boardSummaryRows(toolName, recordToStringFields(obj), ok);
4536
+ appendBoardPreview(rows2, stringOf(obj["message"]));
4537
+ appendBoardPreview(rows2, stringOf(obj["plan"]));
4538
+ const todos = Array.isArray(obj["todos"]) ? obj["todos"] : [];
4539
+ for (const todo of todos.slice(0, 3)) {
4540
+ if (todo && typeof todo === "object") {
4541
+ const o = todo;
4542
+ rows2.push({ kind: "path", marker: "+ ", text: stringOf(o["content"]) ?? stringOf(o["id"]) ?? "todo" });
4543
+ }
4544
+ }
4545
+ return rows2.slice(0, VISUAL_MAX_LINES);
4546
+ }
4547
+ const header = parseHeaderLine(text);
4548
+ const sections = parseNamedSections(text);
4549
+ const rows = boardSummaryRows(toolName, header.fields, ok);
4550
+ appendBoardPreview(rows, sections.get("message") ?? sections.get("plan") ?? bodyLines(text).join("\n"));
4551
+ return rows.slice(0, VISUAL_MAX_LINES);
4552
+ }
4553
+ function boardSummaryRows(toolName, fields, ok) {
4554
+ const success = fields["ok"] !== "false" && ok;
4555
+ const count = numberFromParsedField(fields, "count");
4556
+ const open = numberFromParsedField(fields, "open");
4557
+ const completed = numberFromParsedField(fields, "completed");
4558
+ const inProgress = numberFromParsedField(fields, "inProgress") ?? numberFromParsedField(fields, "in_progress");
4559
+ const parts = [
4560
+ toolName,
4561
+ count !== void 0 ? `${count} item${count === 1 ? "" : "s"}` : void 0,
4562
+ open !== void 0 ? `${open} open` : void 0,
4563
+ completed !== void 0 ? `${completed} done` : void 0,
4564
+ inProgress !== void 0 && inProgress > 0 ? `${inProgress} in progress` : void 0
4565
+ ].filter(Boolean);
4566
+ return [{
4567
+ kind: success ? "ok" : "error",
4568
+ marker: success ? "ok " : "x ",
4569
+ text: parts.join(" \xB7 ") || toolName
4570
+ }];
4571
+ }
4572
+ function appendBoardPreview(rows, text) {
4573
+ if (!text) return;
4574
+ const lines = text.split(/\r?\n/).map((line) => line.replace(/^[\s│├└─>*-]+/, "").trim()).filter((line) => line && !line.startsWith("{") && !line.startsWith("["));
4575
+ for (const line of lines.slice(0, 4)) {
4576
+ rows.push({ kind: line.includes("failed") || line.includes("not configured") ? "error" : "meta", text: line });
4577
+ }
4578
+ }
4579
+ function visualMemory(toolName, text, ok) {
4580
+ const json = tryParseJson(text);
4581
+ if (json && typeof json === "object" && !Array.isArray(json)) {
4582
+ const obj = json;
4583
+ if (toolName === "search_memory" || toolName === "find_related_memories") {
4584
+ return memoryResultRows(Array.isArray(obj["results"]) ? obj["results"] : []);
4585
+ }
4586
+ const fields = recordToStringFields(obj);
4587
+ return [memoryStatusRow(toolName, fields, ok)];
4588
+ }
4589
+ const header = parseHeaderLine(text);
4590
+ if (toolName === "search_memory" || toolName === "find_related_memories") {
4591
+ return memoryResultRows(bodyLines(text));
4592
+ }
4593
+ return [memoryStatusRow(toolName, header.fields, ok)];
4594
+ }
4595
+ function memoryStatusRow(toolName, fields, ok) {
4596
+ const scope = fields["scope"];
4597
+ const removed = numberFromParsedField(fields, "removed");
4598
+ const text = toolName === "forget" ? `${removed ?? 0} removed${scope ? ` \xB7 ${scope}` : ""}` : `${toolName}${scope ? ` \xB7 ${scope}` : ""}`;
4599
+ return { kind: ok ? "ok" : "error", marker: ok ? "ok " : "x ", text };
4600
+ }
4601
+ function memoryResultRows(results) {
4602
+ if (results.length === 0) return [{ kind: "meta", text: "no memories" }];
4603
+ const rows = [];
4604
+ for (const result of results.slice(0, VISUAL_MAX_LINES)) {
4605
+ if (typeof result === "string") {
4606
+ const parsed = tryParseJson(result);
4607
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
4608
+ const o = parsed;
4609
+ rows.push({ kind: "meta", marker: tagMarker(stringOf(o["priority"])), text: memoryText(o) });
4610
+ } else {
4611
+ rows.push({ kind: "meta", text: result });
4612
+ }
4613
+ } else if (result && typeof result === "object") {
4614
+ const o = result;
4615
+ rows.push({ kind: "meta", marker: tagMarker(stringOf(o["priority"])), text: memoryText(o) });
4616
+ }
4617
+ }
4618
+ if (results.length > rows.length) rows.push({ kind: "meta", text: `${results.length - rows.length} more memory result(s)` });
4619
+ return rows;
4620
+ }
4621
+ function memoryText(o) {
4622
+ const type = stringOf(o["type"]);
4623
+ const scope = stringOf(o["scope"]);
4624
+ const text = stringOf(o["text"]) ?? "";
4625
+ return [type ? `[${type}]` : void 0, scope, text].filter(Boolean).join(" ");
4626
+ }
4627
+ function tagMarker(priority) {
4628
+ if (priority === "critical" || priority === "high") return "! ";
4629
+ return void 0;
4630
+ }
4631
+ function visualLogs(text) {
4632
+ const json = tryParseJson(text);
4633
+ if (json && typeof json === "object" && !Array.isArray(json)) {
4634
+ const obj = json;
4635
+ const rows2 = [{
4636
+ kind: "meta",
4637
+ text: `${stringOf(obj["source"]) ?? "logs"} \xB7 ${numOf(obj["total"]) ?? 0} entries${obj["truncated"] === true ? " \xB7 truncated" : ""}`
4638
+ }];
4639
+ const entries = Array.isArray(obj["entries"]) ? obj["entries"] : [];
4640
+ appendLogEntries(rows2, entries);
4641
+ return rows2;
4642
+ }
4643
+ const header = parseHeaderLine(text);
4644
+ const rows = [{ kind: "meta", text: `${header.label}${header.fields["total"] ? ` \xB7 ${header.fields["total"]} entries` : ""}` }];
4645
+ appendLogEntries(rows, bodyLines(text));
4646
+ return rows.slice(0, VISUAL_MAX_LINES);
4647
+ }
4648
+ function appendLogEntries(rows, entries) {
4649
+ for (const entry of entries.slice(0, 5)) {
4650
+ if (typeof entry === "string") {
4651
+ rows.push(logLine(entry));
4652
+ } else if (entry && typeof entry === "object") {
4653
+ const o = entry;
4654
+ rows.push(logLine([stringOf(o["timestamp"]), stringOf(o["level"]), stringOf(o["source"]), stringOf(o["message"])].filter(Boolean).join(" ")));
4655
+ }
4656
+ }
4657
+ if (entries.length > 5) rows.push({ kind: "meta", text: `${entries.length - 5} more log line(s)` });
4658
+ }
4659
+ function logLine(line) {
4660
+ const kind = /\b(error|fatal|panic)\b/i.test(line) ? "error" : /\b(warn|warning)\b/i.test(line) ? "warn" : "stdout";
4661
+ return { kind, marker: kind === "error" ? "x " : kind === "warn" ? "! " : void 0, text: line };
4662
+ }
4663
+ function visualDocument(text) {
4664
+ const json = tryParseJson(text);
4665
+ const rows = [];
4666
+ if (json && typeof json === "object" && !Array.isArray(json)) {
4667
+ const obj = json;
4668
+ rows.push({
4669
+ kind: "ok",
4670
+ marker: "ok ",
4671
+ text: `${numOf(obj["items_documented"]) ?? 0} documented \xB7 ${numOf(obj["files_processed"]) ?? 0} files \xB7 ${stringOf(obj["style"]) ?? "style"}`
4672
+ });
4673
+ appendDocumentResults(rows, Array.isArray(obj["results"]) ? obj["results"] : []);
4674
+ return rows.slice(0, VISUAL_MAX_LINES);
4675
+ }
4676
+ const header = parseHeaderLine(text);
4677
+ rows.push({
4678
+ kind: "ok",
4679
+ marker: "ok ",
4680
+ text: `${header.fields["items_documented"] ?? "0"} documented \xB7 ${header.fields["files_processed"] ?? "0"} files`
4681
+ });
4682
+ appendDocumentResults(rows, bodyLines(text));
4683
+ return rows.slice(0, VISUAL_MAX_LINES);
4684
+ }
4685
+ function appendDocumentResults(rows, results) {
4686
+ for (const result of results.slice(0, 5)) {
4687
+ const obj = typeof result === "string" ? tryParseJson(result) : result;
4688
+ if (obj && typeof obj === "object" && !Array.isArray(obj)) {
4689
+ const o = obj;
4690
+ const status = stringOf(o["status"]) ?? "item";
4691
+ rows.push({
4692
+ kind: status === "error" ? "error" : status === "skipped" ? "warn" : "path",
4693
+ marker: status === "error" ? "x " : status === "skipped" ? "! " : "+ ",
4694
+ path: stringOf(o["path"]),
4695
+ text: stringOf(o["name"]) ?? stringOf(o["signature"]) ?? status
4696
+ });
4697
+ } else if (typeof result === "string" && result.trim()) {
4698
+ rows.push({ kind: "meta", text: result.trim() });
4699
+ }
4700
+ }
4701
+ }
4702
+ function visualToolCatalog(toolName, text) {
4703
+ const json = tryParseJson(text);
4704
+ const rows = [];
4705
+ if (json && typeof json === "object" && !Array.isArray(json)) {
4706
+ const obj = json;
4707
+ const total = numOf(obj["total"]) ?? 0;
4708
+ rows.push({ kind: total > 0 ? "ok" : "warn", marker: total > 0 ? "ok " : "! ", text: `${toolName} \xB7 ${total} result${total === 1 ? "" : "s"}` });
4709
+ const tools = Array.isArray(obj["tools"]) ? obj["tools"] : [];
4710
+ for (const tool of tools.slice(0, 5)) {
4711
+ if (tool && typeof tool === "object") {
4712
+ const o = tool;
4713
+ rows.push({
4714
+ kind: o["mutating"] === true ? "warn" : "path",
4715
+ marker: o["mutating"] === true ? "! " : void 0,
4716
+ text: [stringOf(o["name"]), stringOf(o["permission"]), stringOf(o["description"])].filter(Boolean).join(" \xB7 ")
4717
+ });
4718
+ }
4719
+ }
4720
+ return rows.slice(0, VISUAL_MAX_LINES);
4721
+ }
4722
+ const header = parseHeaderLine(text);
4723
+ return [{ kind: "meta", text: header.label || toolName }];
4724
+ }
4725
+ function visualMetaExecution(toolName, text, ok) {
4726
+ const json = tryParseJson(text);
4727
+ if (!json || typeof json !== "object" || Array.isArray(json)) {
4728
+ const header = parseHeaderLine(text);
4729
+ return [{ kind: ok ? "ok" : "error", marker: ok ? "ok " : "x ", text: header.label || toolName }];
4730
+ }
4731
+ const obj = json;
4732
+ if (toolName === "tool_use") {
4733
+ const success = obj["success"] !== false && ok;
4734
+ const target = stringOf(obj["tool"]) ?? "tool";
4735
+ return [{
4736
+ kind: success ? "ok" : "error",
4737
+ marker: success ? "ok " : "x ",
4738
+ text: `${target} \xB7 ${numOf(obj["executionMs"]) ?? 0}ms${success ? "" : ` \xB7 ${stringOf(obj["error"]) ?? "failed"}`}`
4739
+ }];
4740
+ }
4741
+ const total = numOf(obj["total"]) ?? 0;
4742
+ const succeeded = numOf(obj["succeeded"]) ?? 0;
4743
+ const failed = numOf(obj["failed"]) ?? 0;
4744
+ const rows = [{
4745
+ kind: failed > 0 || !ok ? "error" : "ok",
4746
+ marker: failed > 0 || !ok ? "x " : "ok ",
4747
+ text: `${succeeded}/${total} succeeded${failed > 0 ? ` \xB7 ${failed} failed` : ""}`
4748
+ }];
4749
+ const results = Array.isArray(obj["results"]) ? obj["results"] : [];
4750
+ for (const result of results.slice(0, 5)) {
4751
+ if (result && typeof result === "object") {
4752
+ const r = result;
4753
+ const success = r["success"] !== false;
4754
+ rows.push({
4755
+ kind: success ? "ok" : "error",
4756
+ marker: success ? "ok " : "x ",
4757
+ text: `${stringOf(r["tool"]) ?? "tool"} \xB7 ${numOf(r["executionMs"]) ?? 0}ms${success ? "" : ` \xB7 ${stringOf(r["error"]) ?? "failed"}`}`
4758
+ });
4759
+ }
4760
+ }
4761
+ return rows.slice(0, VISUAL_MAX_LINES);
4762
+ }
4763
+ function visualCodebase(toolName, text, ok) {
4764
+ const json = tryParseJson(text);
4765
+ if (!json || typeof json !== "object" || Array.isArray(json)) {
4766
+ const header = parseHeaderLine(text);
4767
+ return [{ kind: ok ? "ok" : "warn", marker: ok ? "ok " : "! ", text: header.label || toolName }];
4768
+ }
4769
+ const obj = json;
4770
+ if (toolName === "codebase-search") {
4771
+ const status2 = stringOf(obj["indexStatus"]);
4772
+ const total = numOf(obj["total"]) ?? 0;
4773
+ const rows = [{
4774
+ kind: status2 ? "warn" : "ok",
4775
+ marker: status2 ? "! " : "ok ",
4776
+ text: status2 ?? `${total} symbol result${total === 1 ? "" : "s"} for "${stringOf(obj["query"]) ?? ""}"`
4777
+ }];
4778
+ const results = Array.isArray(obj["results"]) ? obj["results"] : [];
4779
+ for (const result of results.slice(0, 5)) {
4780
+ if (result && typeof result === "object") {
4781
+ const r = result;
4782
+ rows.push({
4783
+ kind: "match",
4784
+ path: stringOf(r["file"]),
4785
+ lineNo: numOf(r["line"])?.toString(),
4786
+ text: [stringOf(r["kind"]), stringOf(r["name"]), stringOf(r["signature"])].filter(Boolean).join(" \xB7 ")
4787
+ });
4788
+ }
4789
+ }
4790
+ return rows.slice(0, VISUAL_MAX_LINES);
4791
+ }
4792
+ if (toolName === "codebase-index") {
4793
+ const errors = Array.isArray(obj["errors"]) ? obj["errors"] : [];
4794
+ return [{
4795
+ kind: errors.length > 0 || !ok ? "error" : stringOf(obj["note"]) ? "warn" : "ok",
4796
+ marker: errors.length > 0 || !ok ? "x " : stringOf(obj["note"]) ? "! " : "ok ",
4797
+ text: stringOf(obj["note"]) ?? `${numOf(obj["filesIndexed"]) ?? 0} files \xB7 ${numOf(obj["symbolsIndexed"]) ?? 0} symbols \xB7 ${fmtDuration(numOf(obj["durationMs"]) ?? 0)}`
4798
+ }];
4799
+ }
4800
+ const status = stringOf(obj["indexStatus"]);
4801
+ return [{
4802
+ kind: status ? "warn" : "ok",
4803
+ marker: status ? "! " : "ok ",
4804
+ text: status ?? `${numOf(obj["totalSymbols"]) ?? 0} symbols \xB7 ${numOf(obj["totalFiles"]) ?? 0} files \xB7 ${fmtBytes(numOf(obj["sizeBytes"]) ?? 0)}`
4805
+ }];
4806
+ }
4807
+ function visualWorkingDir(text, ok) {
4808
+ const json = tryParseJson(text);
4809
+ const obj = json && typeof json === "object" && !Array.isArray(json) ? json : void 0;
4810
+ if (!obj) return void 0;
4811
+ const err = stringOf(obj["error"]);
4812
+ return [{
4813
+ kind: err || !ok ? "error" : "ok",
4814
+ marker: err || !ok ? "x " : "ok ",
4815
+ path: stringOf(obj["current"]),
4816
+ text: err ?? stringOf(obj["message"]) ?? "working directory"
4817
+ }];
4818
+ }
4819
+ function visualMode(text, ok) {
4820
+ const json = tryParseJson(text);
4821
+ const obj = json && typeof json === "object" && !Array.isArray(json) ? json : void 0;
4822
+ if (!obj) return void 0;
4823
+ if (Array.isArray(obj["modes"])) {
4824
+ const modes = obj["modes"];
4825
+ const rows = [{ kind: "ok", marker: "ok ", text: `${modes.length} mode${modes.length === 1 ? "" : "s"}` }];
4826
+ for (const mode of modes.slice(0, 5)) {
4827
+ if (mode && typeof mode === "object") {
4828
+ const m = mode;
4829
+ rows.push({ kind: "path", text: [stringOf(m["id"]), stringOf(m["name"]), stringOf(m["description"])].filter(Boolean).join(" \xB7 ") });
4830
+ }
4831
+ }
4832
+ return rows;
4833
+ }
4834
+ const success = obj["success"] !== false && ok;
4835
+ return [{
4836
+ kind: success ? "ok" : "error",
4837
+ marker: success ? "ok " : "x ",
4838
+ text: [stringOf(obj["action"]) ?? "mode", stringOf(obj["currentMode"]), stringOf(obj["message"])].filter(Boolean).join(" \xB7 ")
4839
+ }];
4840
+ }
4841
+ function recordToStringFields(obj) {
4842
+ const out = {};
4843
+ for (const [key, value] of Object.entries(obj)) {
4844
+ if (value === void 0 || value === null) continue;
4845
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
4846
+ out[key] = String(value);
4847
+ }
4848
+ }
4849
+ return out;
4850
+ }
4851
+ function appendOutputPreview(rows, output, kind) {
4852
+ if (!output) return;
4853
+ const lines = output.split(/\r?\n/).filter((line) => line.trim());
4854
+ for (const line of lines.slice(0, 3)) rows.push({ kind, text: line.trim() });
4855
+ if (lines.length > 3) rows.push({ kind: "meta", text: `${lines.length - 3} more ${kind} line(s)` });
4856
+ }
4857
+ function bodyLines(text) {
4858
+ const lines = text.replace(/\r/g, "").split("\n");
4859
+ if (lines.length > 0 && /^[^\n]+(?:\s+\([^)]*\))?$/.test(lines[0] ?? "")) {
4860
+ return lines.slice(1);
4861
+ }
4862
+ return lines;
4863
+ }
4864
+ function parseHeaderLine(text) {
4865
+ const first = text.split(/\r?\n/, 1)[0] ?? "";
4866
+ const match = first.match(/^(.+?)(?: \((.*)\))?$/);
4867
+ const label = match?.[1] ?? first;
4868
+ const rawFields = match?.[2] ?? "";
4869
+ return { label, fields: parseInlineFields(rawFields) };
4870
+ }
4871
+ function parseInlineFields(raw) {
4872
+ const fields = {};
4873
+ for (const match of raw.matchAll(/([A-Za-z_][A-Za-z0-9_]*)=([^ ]+)/g)) {
4874
+ if (match[1] && match[2]) fields[match[1]] = match[2];
4875
+ }
4876
+ return fields;
4877
+ }
4878
+ function parseNamedSections(text) {
4879
+ const sections = /* @__PURE__ */ new Map();
4880
+ const lines = text.replace(/\r/g, "").split("\n");
4881
+ let current;
4882
+ const buf = [];
4883
+ const flush = () => {
4884
+ if (current) sections.set(current, buf.join("\n").trim());
4885
+ buf.length = 0;
4886
+ };
4887
+ for (const line of lines.slice(1)) {
4888
+ const m = line.match(/^([a-z_]+):$/);
4889
+ if (m?.[1]) {
4890
+ flush();
4891
+ current = m[1];
4892
+ continue;
4893
+ }
4894
+ if (current) buf.push(line);
4895
+ }
4896
+ flush();
4897
+ return sections;
4898
+ }
4899
+ function parseKeyValueLines(text) {
4900
+ const out = {};
4901
+ for (const line of text.split(/\r?\n/)) {
4902
+ const m = line.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
4903
+ if (m?.[1]) out[m[1]] = m[2] ?? "";
4904
+ }
4905
+ return out;
4906
+ }
4907
+ function numberFromParsedField(fields, key) {
4908
+ const raw = fields[key];
4909
+ if (raw === void 0) return void 0;
4910
+ const n = Number.parseInt(raw, 10);
4911
+ return Number.isFinite(n) ? n : void 0;
4912
+ }
4105
4913
  var MAX_STREAM_DISPLAY_CHARS = 480;
4106
4914
  var MAX_STREAM_LINES = 8;
4107
4915
  function streamBoxRows(text, maxLines, contentWidth) {
@@ -4146,10 +4954,7 @@ var ToolStreamBox = React5.memo(function ToolStreamBox2({
4146
4954
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u23F1 ${fmtDuration(elapsedMs)}` }),
4147
4955
  hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` (${totalLines} lines, showing last ${MAX_STREAM_LINES})` }) : null
4148
4956
  ] }),
4149
- /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginLeft: 2, children: rows.map((r, i) => (
4150
- // biome-ignore lint/suspicious/noArrayIndexKey: fixed-height block, index is the row
4151
- /* @__PURE__ */ jsx(Text, { dimColor: true, italic: Boolean(r.italic), children: r.text || " " }, i)
4152
- )) })
4957
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginLeft: 2, children: rows.map((r, i) => /* @__PURE__ */ jsx(Text, { dimColor: true, italic: Boolean(r.italic), children: r.text || " " }, i)) })
4153
4958
  ] });
4154
4959
  });
4155
4960
  function tailForDisplay(text, maxChars) {
@@ -4162,7 +4967,7 @@ function tailForDisplay(text, maxChars) {
4162
4967
  return `\u2026 ${text.slice(cut)}`;
4163
4968
  }
4164
4969
  var MAX_CODE_LINES = 80;
4165
- var DIFF_MAX_LINES = 8;
4970
+ var DIFF_MAX_LINES = 12;
4166
4971
  function CodeBlock({
4167
4972
  code,
4168
4973
  lang,
@@ -4194,58 +4999,83 @@ function CodeBlock({
4194
4999
  paddingX: 1,
4195
5000
  children: [
4196
5001
  lang !== "plain" ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: lang }) : null,
4197
- rows.map((tokens, i) => (
4198
- // biome-ignore lint/suspicious/noArrayIndexKey: code lines are positional
4199
- /* @__PURE__ */ jsxs(Text, { children: [
4200
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${String(i + 1).padStart(gutterW, " ")} ` }),
4201
- tokens.length === 0 ? " " : tokens.map((t, j) => /* @__PURE__ */ jsx(
4202
- Text,
4203
- {
4204
- dimColor: Boolean(t.dim),
4205
- bold: Boolean(t.bold),
4206
- ...t.color ? { color: t.color } : {},
4207
- children: t.text
4208
- },
4209
- j
4210
- ))
4211
- ] }, i)
4212
- )),
5002
+ rows.map((tokens, i) => /* @__PURE__ */ jsxs(Text, { children: [
5003
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${String(i + 1).padStart(gutterW, " ")} ` }),
5004
+ tokens.length === 0 ? " " : tokens.map((t, j) => /* @__PURE__ */ jsx(
5005
+ Text,
5006
+ {
5007
+ dimColor: Boolean(t.dim),
5008
+ bold: Boolean(t.bold),
5009
+ ...t.color ? { color: t.color } : {},
5010
+ children: t.text
5011
+ },
5012
+ j
5013
+ ))
5014
+ ] }, i)),
4213
5015
  hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: `\u2026 +${hidden} more line${hidden === 1 ? "" : "s"}` }) : null
4214
5016
  ]
4215
5017
  }
4216
5018
  );
4217
5019
  }
4218
- function DiffBlock({ rows, hidden }) {
5020
+ function DiffBlock({
5021
+ rows,
5022
+ hidden,
5023
+ hiddenAdded = 0,
5024
+ hiddenRemoved = 0
5025
+ }) {
4219
5026
  let gutterWidth = 1;
4220
5027
  for (const r of rows) {
4221
- const n = r.kind === "del" ? r.oldLine : r.newLine;
4222
- if (typeof n === "number") {
4223
- const w = String(n).length;
4224
- if (w > gutterWidth) gutterWidth = w;
5028
+ for (const n of [r.oldLine, r.newLine]) {
5029
+ if (typeof n === "number") {
5030
+ const w = String(n).length;
5031
+ if (w > gutterWidth) gutterWidth = w;
5032
+ }
4225
5033
  }
4226
5034
  }
4227
5035
  const blank = " ".repeat(gutterWidth);
5036
+ const gutterPad = `${blank} ${blank}`;
5037
+ const footerStats = [
5038
+ hiddenAdded > 0 ? `+${hiddenAdded}` : "",
5039
+ hiddenRemoved > 0 ? `-${hiddenRemoved}` : ""
5040
+ ].filter(Boolean);
5041
+ const markerFor = (kind) => {
5042
+ if (kind === "add") return "+";
5043
+ if (kind === "del") return "-";
5044
+ return " ";
5045
+ };
5046
+ const textForDisplay = (row) => {
5047
+ if ((row.kind === "add" || row.kind === "del" || row.kind === "ctx") && row.text.length > 0) {
5048
+ return row.text.slice(1) || " ";
5049
+ }
5050
+ return row.text || " ";
5051
+ };
4228
5052
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 4, marginTop: 0, children: [
4229
5053
  rows.map((row, i) => {
4230
5054
  const key = i;
4231
5055
  if (row.kind === "hunk") {
4232
- return /* @__PURE__ */ jsx(Text, { color: "cyan", dimColor: true, children: row.text }, key);
5056
+ return /* @__PURE__ */ jsx(Text, { color: "cyan", dimColor: true, children: `${gutterPad} ${row.text}` }, key);
4233
5057
  }
4234
5058
  if (row.kind === "meta") {
4235
- return /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${blank} ${row.text}` }, key);
5059
+ return /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${gutterPad} ${row.text}` }, key);
4236
5060
  }
4237
- const lnNumber = row.kind === "del" ? row.oldLine : row.newLine;
4238
- const lnText = typeof lnNumber === "number" ? String(lnNumber).padStart(gutterWidth, " ") : blank;
5061
+ const oldLn = typeof row.oldLine === "number" ? String(row.oldLine).padStart(gutterWidth, " ") : blank;
5062
+ const newLn = typeof row.newLine === "number" ? String(row.newLine).padStart(gutterWidth, " ") : blank;
4239
5063
  if (row.kind === "ctx") {
4240
- return /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${lnText} ${row.text}` }, key);
5064
+ return /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${oldLn} ${newLn} ${textForDisplay(row)}` }, key);
4241
5065
  }
4242
5066
  const bg = row.kind === "add" ? theme.diffAddBg : theme.diffDelBg;
5067
+ const lineColor = row.kind === "add" ? theme.success : theme.error;
5068
+ const marker = markerFor(row.kind);
4243
5069
  return /* @__PURE__ */ jsxs(Text, { children: [
4244
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${lnText} ` }),
4245
- /* @__PURE__ */ jsx(Text, { backgroundColor: bg, color: "black", children: row.text })
5070
+ /* @__PURE__ */ jsx(Text, { color: row.kind === "del" ? lineColor : void 0, dimColor: row.kind !== "del", children: oldLn }),
5071
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
5072
+ /* @__PURE__ */ jsx(Text, { color: row.kind === "add" ? lineColor : void 0, dimColor: row.kind !== "add", children: newLn }),
5073
+ /* @__PURE__ */ jsx(Text, { children: " " }),
5074
+ /* @__PURE__ */ jsx(Text, { color: lineColor, bold: true, children: marker }),
5075
+ /* @__PURE__ */ jsx(Text, { backgroundColor: bg, color: "black", children: textForDisplay(row) })
4246
5076
  ] }, key);
4247
5077
  }),
4248
- hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: `${blank} \u2026 ${hidden} more line${hidden === 1 ? "" : "s"}` }) : null
5078
+ hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: `${gutterPad} \u2026 ${hidden} more line${hidden === 1 ? "" : "s"}${footerStats.length > 0 ? ` (${footerStats.join(" ")})` : ""}` }) : null
4249
5079
  ] });
4250
5080
  }
4251
5081
  function parseUnifiedDiff(diff, maxLines) {
@@ -4284,19 +5114,35 @@ function parseUnifiedDiff(diff, maxLines) {
4284
5114
  oldLn++;
4285
5115
  newLn++;
4286
5116
  }
4287
- if (all.length === 0) return { rows: [], hidden: 0 };
4288
- if (all.length <= maxLines) return { rows: all, hidden: 0 };
4289
- return { rows: all.slice(0, maxLines), hidden: all.length - maxLines };
5117
+ const added = all.filter((row) => row.kind === "add").length;
5118
+ const removed = all.filter((row) => row.kind === "del").length;
5119
+ if (all.length === 0) {
5120
+ return { rows: [], hidden: 0, added: 0, removed: 0, hiddenAdded: 0, hiddenRemoved: 0 };
5121
+ }
5122
+ if (all.length <= maxLines) {
5123
+ return { rows: all, hidden: 0, added, removed, hiddenAdded: 0, hiddenRemoved: 0 };
5124
+ }
5125
+ const rows = all.slice(0, maxLines);
5126
+ const hiddenRows = all.slice(maxLines);
5127
+ return {
5128
+ rows,
5129
+ hidden: hiddenRows.length,
5130
+ added,
5131
+ removed,
5132
+ hiddenAdded: hiddenRows.filter((row) => row.kind === "add").length,
5133
+ hiddenRemoved: hiddenRows.filter((row) => row.kind === "del").length
5134
+ };
4290
5135
  }
4291
- function extractDiffPreview(toolName, output) {
5136
+ function extractDiffPreview(toolName, output, input) {
4292
5137
  if (!output) return void 0;
4293
5138
  const text = output.trim();
4294
5139
  if (!text) return void 0;
4295
5140
  let diff;
4296
- if (toolName === "edit" || toolName === "diff") {
5141
+ if (toolName === "edit" || toolName === "diff" || toolName === "write") {
4297
5142
  const parsed = tryParseJson(text);
4298
5143
  if (parsed && typeof parsed === "object") {
4299
- diff = stringOf(parsed["diff"]);
5144
+ const obj = parsed;
5145
+ diff = toolName === "write" && obj["created"] === true ? newFileDiffFromWriteInput(obj, input) ?? stringOf(obj["diff"]) : stringOf(obj["diff"]);
4300
5146
  }
4301
5147
  } else if (toolName === "patch") {
4302
5148
  const parsed = tryParseJson(text);
@@ -4305,9 +5151,32 @@ function extractDiffPreview(toolName, output) {
4305
5151
  } else if (text.includes("@@") || text.startsWith("---")) {
4306
5152
  diff = text;
4307
5153
  }
5154
+ } else if (toolName === "replace") {
5155
+ const parsed = tryParseJson(text);
5156
+ if (parsed && typeof parsed === "object") {
5157
+ diff = collectReplaceDiffs(parsed);
5158
+ }
4308
5159
  }
4309
- if (!diff || !diff.trim() || diff.startsWith("(no-op")) return void 0;
4310
- return parseUnifiedDiff(diff, DIFF_MAX_LINES);
5160
+ if (!diff?.trim() || diff.startsWith("(no-op")) return void 0;
5161
+ const preview = parseUnifiedDiff(diff, DIFF_MAX_LINES);
5162
+ return preview.rows.length > 0 ? preview : void 0;
5163
+ }
5164
+ function collectReplaceDiffs(obj) {
5165
+ const results = Array.isArray(obj["results"]) ? obj["results"] : [];
5166
+ const diffs = results.map(
5167
+ (result) => result && typeof result === "object" ? stringOf(result["diff"]) : void 0
5168
+ ).filter((diff) => Boolean(diff?.trim()));
5169
+ return diffs.length > 0 ? diffs.join("\n") : void 0;
5170
+ }
5171
+ function newFileDiffFromWriteInput(output, input) {
5172
+ if (!input || typeof input !== "object") return void 0;
5173
+ const obj = input;
5174
+ const content = stringOf(obj["content"]);
5175
+ if (content === void 0) return void 0;
5176
+ const path7 = stringOf(output["path"]) ?? stringOf(obj["path"]) ?? "new file";
5177
+ const lines = content === "" ? [] : content.replace(/\n$/, "").split("\n");
5178
+ const header = [`+++ ${path7}`, `@@ -0,0 +1,${lines.length} @@`];
5179
+ return [...header, ...lines.map((line) => `+${line}`)].join("\n");
4311
5180
  }
4312
5181
  var MESSAGE_PANEL_CHROME_WIDTH = 2;
4313
5182
  function assistantContentWidth(termWidth) {
@@ -4354,20 +5223,14 @@ function AssistantBody({
4354
5223
  const segments = splitFencedBlocks(text);
4355
5224
  const inner = contentWidth ?? termWidth;
4356
5225
  return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: segments.map(
4357
- (seg, i) => seg.type === "code" ? (
4358
- // biome-ignore lint/suspicious/noArrayIndexKey: segment order is stable
4359
- /* @__PURE__ */ jsx(CodeBlock, { code: seg.text, lang: seg.lang ?? "plain", contentWidth: inner }, i)
4360
- ) : (
4361
- // biome-ignore lint/suspicious/noArrayIndexKey: segment order is stable
4362
- /* @__PURE__ */ jsx(
4363
- MarkdownView,
4364
- {
4365
- text: seg.text,
4366
- termWidth: inner,
4367
- tableWidth: termWidth - MESSAGE_PANEL_CHROME_WIDTH
4368
- },
4369
- i
4370
- )
5226
+ (seg, i) => seg.type === "code" ? /* @__PURE__ */ jsx(CodeBlock, { code: seg.text, lang: seg.lang ?? "plain", contentWidth: inner }, i) : /* @__PURE__ */ jsx(
5227
+ MarkdownView,
5228
+ {
5229
+ text: seg.text,
5230
+ termWidth: inner,
5231
+ tableWidth: termWidth - MESSAGE_PANEL_CHROME_WIDTH
5232
+ },
5233
+ i
4371
5234
  )
4372
5235
  ) });
4373
5236
  }
@@ -4403,10 +5266,7 @@ function AssistantTail({
4403
5266
  /* @__PURE__ */ jsx(Text, { bold: true, color: theme.assistant, children: "ASSISTANT" }),
4404
5267
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (streaming\u2026)" })
4405
5268
  ] }),
4406
- /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: rows.map((r, i) => (
4407
- // biome-ignore lint/suspicious/noArrayIndexKey: fixed-height block, index is the row
4408
- /* @__PURE__ */ jsx(Text, { color: "white", children: r || " " }, i)
4409
- )) })
5269
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: rows.map((r, i) => /* @__PURE__ */ jsx(Text, { color: "white", children: r || " " }, i)) })
4410
5270
  ]
4411
5271
  }
4412
5272
  );
@@ -4706,7 +5566,8 @@ var Entry = React5.memo(function Entry2({
4706
5566
  entry.outputBytes,
4707
5567
  entry.outputLines
4708
5568
  );
4709
- const diff = entry.ok ? extractDiffPreview(entry.name, entry.output) : void 0;
5569
+ const visualLines = formatToolVisualOutput(entry.name, entry.output, entry.ok, entry.input);
5570
+ const diff = entry.ok ? extractDiffPreview(entry.name, entry.output, entry.input) : void 0;
4710
5571
  const sizeChip = (() => {
4711
5572
  if (!entry.ok) return "";
4712
5573
  const parts = [];
@@ -4733,21 +5594,26 @@ var Entry = React5.memo(function Entry2({
4733
5594
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${fmtDuration(entry.durationMs)}` }),
4734
5595
  sizeChip ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${sizeChip}` }) : null
4735
5596
  ] }),
4736
- outLines.map((line, i) => (
4737
- // biome-ignore lint/suspicious/noArrayIndexKey: tool output lines are static, index is stable
4738
- /* @__PURE__ */ jsxs(Text, { children: [
4739
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: i === outLines.length - 1 && !diff ? " \u2514\u2500 " : " \u251C\u2500 " }),
4740
- /* @__PURE__ */ jsx(
4741
- Text,
4742
- {
4743
- dimColor: entry.ok && !line.startsWith("!"),
4744
- ...!entry.ok || line.startsWith("!") ? { color: "red" } : {},
4745
- children: line
4746
- }
4747
- )
4748
- ] }, i)
4749
- )),
4750
- diff ? /* @__PURE__ */ jsx(DiffBlock, { rows: diff.rows, hidden: diff.hidden }) : null
5597
+ visualLines ? /* @__PURE__ */ jsx(ToolOutputLines, { lines: visualLines, hasFollowingBlock: Boolean(diff) }) : outLines.map((line, i) => /* @__PURE__ */ jsxs(Text, { children: [
5598
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: i === outLines.length - 1 && !diff ? " \u2514\u2500 " : " \u251C\u2500 " }),
5599
+ /* @__PURE__ */ jsx(
5600
+ Text,
5601
+ {
5602
+ dimColor: entry.ok && !line.startsWith("!"),
5603
+ ...!entry.ok || line.startsWith("!") ? { color: "red" } : {},
5604
+ children: line
5605
+ }
5606
+ )
5607
+ ] }, i)),
5608
+ diff ? /* @__PURE__ */ jsx(
5609
+ DiffBlock,
5610
+ {
5611
+ rows: diff.rows,
5612
+ hidden: diff.hidden,
5613
+ hiddenAdded: diff.hiddenAdded,
5614
+ hiddenRemoved: diff.hiddenRemoved
5615
+ }
5616
+ ) : null
4751
5617
  ] });
4752
5618
  }
4753
5619
  case "info": {
@@ -4851,13 +5717,10 @@ var Entry = React5.memo(function Entry2({
4851
5717
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: entry.detail })
4852
5718
  ] }) : null
4853
5719
  ] }),
4854
- lines.slice(1).map((line, i) => (
4855
- // biome-ignore lint/suspicious/noArrayIndexKey: stable line index
4856
- /* @__PURE__ */ jsxs(Text, { children: [
4857
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
4858
- /* @__PURE__ */ jsx(Text, { children: line })
4859
- ] }, i)
4860
- ))
5720
+ lines.slice(1).map((line, i) => /* @__PURE__ */ jsxs(Text, { children: [
5721
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
5722
+ /* @__PURE__ */ jsx(Text, { children: line })
5723
+ ] }, i))
4861
5724
  ] });
4862
5725
  }
4863
5726
  }
@@ -5507,13 +6370,7 @@ var Input = memo(function Input2({
5507
6370
  }
5508
6371
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
5509
6372
  rows.map(
5510
- (row, i) => row.length === 0 ? (
5511
- // biome-ignore lint/suspicious/noArrayIndexKey: rows are positional and re-laid out every render
5512
- /* @__PURE__ */ jsx(Text, { children: " " }, i)
5513
- ) : (
5514
- // biome-ignore lint/suspicious/noArrayIndexKey: rows are positional and re-laid out every render
5515
- /* @__PURE__ */ jsx(Text, { children: renderRow2(row, `r${i}`, promptColor) }, i)
5516
- )
6373
+ (row, i) => row.length === 0 ? /* @__PURE__ */ jsx(Text, { children: " " }, i) : /* @__PURE__ */ jsx(Text, { children: renderRow2(row, `r${i}`, promptColor) }, i)
5517
6374
  ),
5518
6375
  hint ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: hint }) : null
5519
6376
  ] });
@@ -5673,30 +6530,181 @@ function PhaseMonitor({
5673
6530
  const isRunning = runningPhaseIds.includes(phaseKey);
5674
6531
  const elapsed = phase.startedAt ? fmtElapsed2(nowTick - phase.startedAt) : "\u2014";
5675
6532
  const progress = phase.totalTasks > 0 ? `${phase.completedTasks}/${phase.totalTasks}` : "\u2014";
5676
- return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
5677
- /* @__PURE__ */ jsx(Text, { color: s2.color, bold: true, children: s2.icon }),
5678
- /* @__PURE__ */ jsx(Text, { bold: true, children: phase.name }),
5679
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
5680
- /* @__PURE__ */ jsx(Text, { color: s2.color, children: s2.label }),
5681
- isRunning ? /* @__PURE__ */ jsxs(Fragment, { children: [
5682
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
5683
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
5684
- "elapsed ",
5685
- elapsed
5686
- ] })
5687
- ] }) : null,
5688
- phase.totalTasks > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
6533
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
6534
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
6535
+ /* @__PURE__ */ jsx(Text, { color: s2.color, bold: true, children: s2.icon }),
6536
+ /* @__PURE__ */ jsx(Text, { bold: true, children: phase.name }),
5689
6537
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
5690
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
5691
- "tasks ",
5692
- progress
6538
+ /* @__PURE__ */ jsx(Text, { color: s2.color, children: s2.label }),
6539
+ isRunning ? /* @__PURE__ */ jsxs(Fragment, { children: [
6540
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
6541
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
6542
+ "elapsed ",
6543
+ elapsed
6544
+ ] })
6545
+ ] }) : null,
6546
+ phase.totalTasks > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
6547
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
6548
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
6549
+ "tasks ",
6550
+ progress
6551
+ ] })
5693
6552
  ] })
5694
- ] })
5695
- ] }) }, phaseKey);
6553
+ ] }),
6554
+ (phase.activeTasks ?? []).map((t) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, marginLeft: 2, children: [
6555
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u25CF" }),
6556
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: t.agent ?? "agent" }),
6557
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2192" }),
6558
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: t.title || "(task)" })
6559
+ ] }, t.taskId))
6560
+ ] }, phaseKey);
5696
6561
  }),
5697
6562
  /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate phases" }) })
5698
6563
  ] });
5699
6564
  }
6565
+ var STATUS3 = {
6566
+ pending: { icon: "\u25CB", color: "gray" },
6567
+ queued: { icon: "\u25D4", color: "cyan" },
6568
+ in_progress: { icon: "\u25B6", color: "yellow" },
6569
+ blocked: { icon: "\u2298", color: "magenta" },
6570
+ review: { icon: "\u25C6", color: "blue" },
6571
+ failed: { icon: "\u2717", color: "red" },
6572
+ completed: { icon: "\u2713", color: "green" },
6573
+ cancelled: { icon: "\u229D", color: "gray" }
6574
+ };
6575
+ var RUN_STATUS = {
6576
+ running: "yellow",
6577
+ paused: "magenta",
6578
+ completed: "green",
6579
+ failed: "red",
6580
+ deadlocked: "red",
6581
+ idle: "gray"
6582
+ };
6583
+ var PRIORITY = {
6584
+ critical: "red",
6585
+ high: "yellow",
6586
+ medium: "cyan",
6587
+ low: "gray"
6588
+ };
6589
+ var FEED_KIND = {
6590
+ started: { icon: "\u25B6", color: "yellow" },
6591
+ completed: { icon: "\u2713", color: "green" },
6592
+ failed: { icon: "\u2717", color: "red" },
6593
+ retrying: { icon: "\u21BB", color: "yellow" },
6594
+ wave: { icon: "\u224B", color: "magenta" },
6595
+ deadlock: { icon: "\u26A0", color: "red" },
6596
+ verification_failed: { icon: "\u26CA", color: "red" },
6597
+ conflict: { icon: "\u2442", color: "yellow" },
6598
+ split: { icon: "\u22D4", color: "cyan" },
6599
+ supervisor: { icon: "\u2726", color: "magenta" }
6600
+ };
6601
+ function clip(s2, n) {
6602
+ return s2.length > n ? `${s2.slice(0, n - 1)}\u2026` : s2;
6603
+ }
6604
+ function TaskCard({ task }) {
6605
+ const st2 = STATUS3[task.displayStatus] ?? { icon: "?", color: "white" };
6606
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, width: 26, children: [
6607
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
6608
+ /* @__PURE__ */ jsx(Text, { color: st2.color, bold: true, children: st2.icon }),
6609
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: task.shortId }),
6610
+ /* @__PURE__ */ jsx(Text, { color: PRIORITY[task.priority] ?? "gray", children: task.priority[0]?.toUpperCase() })
6611
+ ] }),
6612
+ /* @__PURE__ */ jsx(Text, { wrap: "truncate-end", children: clip(task.title, 24) }),
6613
+ task.deps.length > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
6614
+ "\u2190 ",
6615
+ clip(task.deps.join(", "), 22)
6616
+ ] }) : null,
6617
+ task.agentName ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
6618
+ /* @__PURE__ */ jsx(Text, { color: task.displayStatus === "in_progress" ? "yellow" : "gray", children: "\u25CF" }),
6619
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: clip(task.agentName, 14) }),
6620
+ task.retries > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
6621
+ "\u21BB",
6622
+ task.retries
6623
+ ] }) : null
6624
+ ] }) : null,
6625
+ task.worktreeBranch ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
6626
+ "\u2325 ",
6627
+ clip(task.worktreeBranch, 22)
6628
+ ] }) : null
6629
+ ] });
6630
+ }
6631
+ function SddBoardOverlay({
6632
+ snapshot,
6633
+ focusColumn = null
6634
+ }) {
6635
+ const byShort = new Map(snapshot.tasks.map((t) => [t.shortId, t]));
6636
+ const p = snapshot.progress;
6637
+ const chains = snapshot.diagnostics?.deadlockChains ?? [];
6638
+ const recentFeed = (snapshot.feed ?? []).slice(0, 6);
6639
+ const focused = typeof focusColumn === "number" && focusColumn >= 0 && focusColumn < snapshot.columns.length ? focusColumn : null;
6640
+ const columns = focused === null ? snapshot.columns : [snapshot.columns[focused]];
6641
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
6642
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, marginBottom: 1, children: [
6643
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "SDD BOARD" }),
6644
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
6645
+ /* @__PURE__ */ jsx(Text, { bold: true, children: clip(snapshot.title, 32) }),
6646
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
6647
+ /* @__PURE__ */ jsx(Text, { color: RUN_STATUS[snapshot.status] ?? "white", children: snapshot.status }),
6648
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
6649
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
6650
+ "wave ",
6651
+ snapshot.wave + 1
6652
+ ] }),
6653
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
6654
+ /* @__PURE__ */ jsxs(Text, { color: "green", children: [
6655
+ "\u2713",
6656
+ p.completed
6657
+ ] }),
6658
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "/" }),
6659
+ /* @__PURE__ */ jsx(Text, { children: p.total }),
6660
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
6661
+ "(",
6662
+ p.percentComplete,
6663
+ "%)"
6664
+ ] }),
6665
+ p.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
6666
+ "\u25B6",
6667
+ p.inProgress
6668
+ ] }) : null,
6669
+ p.failed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
6670
+ "\u2717",
6671
+ p.failed
6672
+ ] }) : null,
6673
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 Ctrl+B close \xB7 c clean wt \xB7 z rollback" }),
6674
+ focused !== null ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
6675
+ "\u2502 column ",
6676
+ focused + 1,
6677
+ "/",
6678
+ snapshot.columns.length
6679
+ ] }) : null
6680
+ ] }),
6681
+ chains.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
6682
+ /* @__PURE__ */ jsx(Text, { color: "red", bold: true, children: "\u26A0 Deadlock \u2014 blocked by failed tasks:" }),
6683
+ chains.map((c) => /* @__PURE__ */ jsxs(Text, { color: "red", children: [
6684
+ " ",
6685
+ c.blocked,
6686
+ " \u2190 ",
6687
+ c.blockedBy.join(", ")
6688
+ ] }, c.blocked))
6689
+ ] }) : null,
6690
+ snapshot.tasks.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No active SDD run. Start one with /sdd execute." }) : /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: columns.map((col) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginRight: 1, children: [
6691
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: col.label }),
6692
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500".repeat(12) }),
6693
+ col.taskIds.map((sid) => byShort.get(sid)).filter((t) => Boolean(t)).map((t) => /* @__PURE__ */ jsx(TaskCard, { task: t }, t.id))
6694
+ ] }, col.label)) }),
6695
+ recentFeed.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
6696
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "Recent activity" }),
6697
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500".repeat(12) }),
6698
+ recentFeed.map((f, i) => {
6699
+ const k = FEED_KIND[f.kind] ?? FEED_KIND.started;
6700
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
6701
+ /* @__PURE__ */ jsx(Text, { color: k?.color ?? "white", children: k?.icon ?? "\u2022" }),
6702
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: clip(f.text, 70) })
6703
+ ] }, `${f.ts}-${i}`);
6704
+ })
6705
+ ] }) : null
6706
+ ] });
6707
+ }
5700
6708
  var fmtElapsed3 = (ms) => {
5701
6709
  const s2 = Math.floor(ms / 1e3);
5702
6710
  const m = Math.floor(s2 / 60);
@@ -5705,7 +6713,7 @@ var fmtElapsed3 = (ms) => {
5705
6713
  if (m > 0) return `${m}:${String(s2 % 60).padStart(2, "0")}`;
5706
6714
  return `${s2}s`;
5707
6715
  };
5708
- var STATUS3 = {
6716
+ var STATUS4 = {
5709
6717
  pending: { icon: "\u25CB", color: "gray" },
5710
6718
  ready: { icon: "\u25D0", color: "cyan" },
5711
6719
  running: { icon: "\u25CF", color: "yellow" },
@@ -5715,7 +6723,7 @@ var STATUS3 = {
5715
6723
  skipped: { icon: "\u2298", color: "gray" }
5716
6724
  };
5717
6725
  function s(entry) {
5718
- return STATUS3[entry] ?? { icon: "?", color: "white" };
6726
+ return STATUS4[entry] ?? { icon: "?", color: "white" };
5719
6727
  }
5720
6728
  function PhasePanel({ phases, nowTick }) {
5721
6729
  const list = Object.values(phases);
@@ -6033,7 +7041,7 @@ function GoalPanel({
6033
7041
  /* @__PURE__ */ jsx(Box, { marginTop: 1, children: coordinatorRunning ? /* @__PURE__ */ jsxs(Fragment, { children: [
6034
7042
  /* @__PURE__ */ jsx(Text, { color: "green", children: "\u25CF Coordinator running " }),
6035
7043
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "[S] Stop coordinator" })
6036
- ] }) : /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "[C] Start coordinator" }) }) })
7044
+ ] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "[C] Start coordinator" }) })
6037
7045
  ] });
6038
7046
  }
6039
7047
  const displayGoal = goal.refinedGoal || goal.goal;
@@ -6071,15 +7079,12 @@ function GoalPanel({
6071
7079
  ] }) }),
6072
7080
  goal.deliverables.map((d, i) => {
6073
7081
  const done = /^\[[x✓]\]|✅|\(done\)/i.test(d);
6074
- return (
6075
- // biome-ignore lint/suspicious/noArrayIndexKey: deliverables are stable text strings
6076
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { ...done ? { color: "green" } : {}, dimColor: !done, children: [
6077
- " ",
6078
- done ? "\u2713" : "\u25CB",
6079
- " ",
6080
- d
6081
- ] }) }, i)
6082
- );
7082
+ return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { ...done ? { color: "green" } : {}, dimColor: !done, children: [
7083
+ " ",
7084
+ done ? "\u2713" : "\u25CB",
7085
+ " ",
7086
+ d
7087
+ ] }) }, i);
6083
7088
  })
6084
7089
  ] }),
6085
7090
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
@@ -6103,7 +7108,7 @@ function GoalPanel({
6103
7108
  /* @__PURE__ */ jsx(Box, { marginTop: 1, children: coordinatorRunning ? /* @__PURE__ */ jsxs(Fragment, { children: [
6104
7109
  /* @__PURE__ */ jsx(Text, { color: "green", children: "\u25CF Coordinator running " }),
6105
7110
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "[S] Stop coordinator" })
6106
- ] }) : /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "[C] Start coordinator" }) }) })
7111
+ ] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "[C] Start coordinator" }) })
6107
7112
  ] })
6108
7113
  ] });
6109
7114
  }
@@ -6598,9 +7603,9 @@ var STATUSLINE_MODE_DESCS = {
6598
7603
  detailed: "Full multi-line statusline (default)"
6599
7604
  };
6600
7605
  var MAX_ITERATIONS_PRESETS = [100, 200, 500, 1e3, 0];
6601
- var MAX_CONCURRENT_PRESETS = [1, 3, 5, 10, 25, 50, 0];
7606
+ var MAX_CONCURRENT_PRESETS = [1, 3, 4, 5, 10, 25, 50, 0];
6602
7607
  var AUTO_PROCEED_MAX_PRESETS = [10, 25, 50, 100, 250, 0];
6603
- var ENHANCE_DELAY_PRESETS = [3e4, 45e3, 6e4, 9e4, 12e4];
7608
+ var ENHANCE_DELAY_PRESETS = [15e3, 3e4, 45e3, 6e4, 9e4, 12e4];
6604
7609
  var ENHANCE_LANGUAGES = ["original", "english"];
6605
7610
  var TOKEN_SAVING_TIERS = ["off", "minimal", "light", "medium", "aggressive"];
6606
7611
  var TOKEN_SAVING_TIER_DESCS = {
@@ -6762,7 +7767,7 @@ function SettingsPicker({
6762
7767
  {
6763
7768
  label: "Refine preview countdown",
6764
7769
  value: formatEnhanceDelay(enhanceDelayMs),
6765
- detail: "Timeout for prompt refinement preview (30s\u2013120s)"
7770
+ detail: "Timeout for prompt refinement preview (15s\u2013120s)"
6766
7771
  },
6767
7772
  {
6768
7773
  label: "Refine",
@@ -6827,8 +7832,8 @@ function SettingsPicker({
6827
7832
  { section: "Fleet" },
6828
7833
  {
6829
7834
  label: "Max concurrent",
6830
- value: maxConcurrent === 0 ? "unlimited" : String(maxConcurrent),
6831
- detail: "Max subagents (0 = unlimited)"
7835
+ value: maxConcurrent === 0 ? "default" : String(maxConcurrent),
7836
+ detail: "Max subagents (0 = default)"
6832
7837
  },
6833
7838
  // ── Logging ──
6834
7839
  { section: "Logging" },
@@ -6892,7 +7897,7 @@ function SettingsPicker({
6892
7897
  };
6893
7898
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
6894
7899
  /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Settings \u2501\u2501" }),
6895
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 field \xB7 \u2190/\u2192 change (instant apply) \xB7 F5 to close" }),
7900
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 field \xB7 \u2190/\u2192 change + autosave \xB7 F5 to close" }),
6896
7901
  hasAbove ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2191 ${windowStart} field${windowStart === 1 ? "" : "s"} above` }) : null,
6897
7902
  rows.map((row, i) => {
6898
7903
  const fieldAtRow = fieldRowIndex.indexOf(i);
@@ -6916,7 +7921,7 @@ function SettingsPicker({
6916
7921
  ] }, `row-${row.label ?? fieldAtRow}`);
6917
7922
  }),
6918
7923
  hasBelow ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2193 ${totalFields - windowEnd} field${totalFields - windowEnd === 1 ? "" : "s"} below` }) : null,
6919
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Persisted to ~/.wrongstack/config.json" }),
7924
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: configScope === "project" ? "Persisted to <project>/.wrongstack/config.json" : "Persisted to ~/.wrongstack/config.json" }),
6920
7925
  hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
6921
7926
  ] });
6922
7927
  }
@@ -6926,54 +7931,120 @@ function isChipExpired(meta, now = Date.now()) {
6926
7931
  return now >= meta.shownAt + meta.expiresIn * 60 * 1e3;
6927
7932
  }
6928
7933
  var ITEM_DESCRIPTIONS = {
7934
+ version: "WrongStack version chip",
7935
+ state: "Agent run state / thinking spinner",
7936
+ model: "Current provider/model id",
7937
+ tokens: "Input/output token counters",
7938
+ cache: "Prompt cache hit ratio",
7939
+ queue: "Queued prompt count",
7940
+ processes: "Tracked shell/process count",
7941
+ hint: "Transient status hint text",
7942
+ index: "Codebase indexing status",
7943
+ breaker: "Process breaker countdown",
6929
7944
  todos: "Todo items (pending/in-progress/done)",
6930
7945
  plan: "Plan board items",
6931
7946
  tasks: "Task board items",
6932
7947
  fleet: "Fleet agent status",
7948
+ fleet_agents: "Per-agent live detail row",
6933
7949
  git: "Git branch name",
6934
7950
  elapsed: "Session elapsed time",
6935
7951
  context: "Context window usage %",
6936
7952
  cost: "Token cost estimate",
6937
7953
  working_dir: "Current working directory",
7954
+ project: "Project name",
7955
+ yolo: "YOLO permission mode",
7956
+ autonomy: "Autonomy mode",
7957
+ eternal_stage: "Autonomy stage",
7958
+ goal: "Active goal summary",
7959
+ mode: "Active agent mode label",
7960
+ auto_proceed: "Auto-proceed countdown",
7961
+ sessions: "Live session count",
7962
+ tools: "Registered tool count",
7963
+ token_saving: "Token-saving mode indicator",
6938
7964
  brain: "Brain arbiter decisions",
6939
7965
  mailbox: "Mailbox unread messages",
6940
7966
  enhance: "Prompt-enhance countdown",
6941
- debug_stream: "Stream debug telemetry"
7967
+ debug_stream: "Stream debug telemetry",
7968
+ next_steps: "Next-step auto-submit countdown"
6942
7969
  };
6943
7970
  var ITEM_LINE = {
7971
+ breaker: 1,
7972
+ cache: 1,
6944
7973
  context: 1,
6945
7974
  cost: 1,
7975
+ hint: 1,
7976
+ index: 1,
7977
+ model: 1,
7978
+ processes: 1,
7979
+ queue: 1,
7980
+ state: 1,
7981
+ tokens: 1,
7982
+ version: 1,
7983
+ auto_proceed: 2,
7984
+ autonomy: 2,
6946
7985
  elapsed: 2,
6947
- working_dir: 2,
7986
+ eternal_stage: 2,
6948
7987
  git: 2,
7988
+ goal: 2,
7989
+ mode: 2,
7990
+ project: 2,
7991
+ sessions: 2,
7992
+ token_saving: 2,
7993
+ tools: 2,
7994
+ working_dir: 2,
7995
+ yolo: 2,
7996
+ brain: 3,
7997
+ debug_stream: 3,
7998
+ enhance: 3,
7999
+ fleet: 3,
8000
+ next_steps: 3,
6949
8001
  todos: 3,
6950
8002
  plan: 3,
6951
8003
  tasks: 3,
6952
- fleet: 4,
6953
- brain: 3,
6954
- mailbox: 3,
6955
- enhance: 3,
6956
- debug_stream: 3
8004
+ fleet_agents: 4,
8005
+ mailbox: 4
6957
8006
  };
6958
- Object.keys(ITEM_LINE).length;
8007
+ var STATUSLINE_FIELD_COUNT = Object.keys(ITEM_LINE).length;
6959
8008
  var STATUSLINE_ITEMS = [
6960
8009
  // Line 1
8010
+ "breaker",
8011
+ "cache",
6961
8012
  "context",
6962
8013
  "cost",
8014
+ "hint",
8015
+ "index",
8016
+ "model",
8017
+ "processes",
8018
+ "queue",
8019
+ "state",
8020
+ "tokens",
8021
+ "version",
6963
8022
  // Line 2
8023
+ "auto_proceed",
8024
+ "autonomy",
6964
8025
  "elapsed",
8026
+ "eternal_stage",
6965
8027
  "git",
8028
+ "goal",
8029
+ "mode",
8030
+ "project",
8031
+ "sessions",
8032
+ "token_saving",
8033
+ "tools",
6966
8034
  "working_dir",
8035
+ "yolo",
6967
8036
  // Line 3
6968
8037
  "brain",
6969
8038
  "debug_stream",
6970
8039
  "enhance",
6971
- "mailbox",
8040
+ "fleet",
8041
+ "next_steps",
6972
8042
  "plan",
6973
8043
  "tasks",
6974
8044
  "todos",
6975
8045
  // Line 4
6976
- "fleet"
8046
+ "fleet_agents",
8047
+ "mailbox"
6977
8048
  ];
6978
8049
  var STREAM_CHIP_KEYS = ["brain", "mailbox", "enhance", "debug_stream"];
6979
8050
  function groupByLine(items) {
@@ -7012,10 +8083,10 @@ function StatuslinePicker({
7012
8083
  if (hiddenSet.has(item)) return "off";
7013
8084
  if (STREAM_CHIP_KEYS.includes(item)) {
7014
8085
  const meta = visibleChipsMap.get(item);
7015
- if (!meta) return "off";
8086
+ if (!meta) return "auto";
7016
8087
  if (meta.expiresIn == null) return "on ";
7017
8088
  const remainingMs = meta.shownAt + meta.expiresIn * 6e4 - Date.now();
7018
- if (remainingMs <= 0) return "exp";
8089
+ if (remainingMs <= 0) return "auto";
7019
8090
  const remainingMin = Math.max(1, Math.ceil(remainingMs / 6e4));
7020
8091
  return `~${remainingMin}m`;
7021
8092
  }
@@ -7025,8 +8096,8 @@ function StatuslinePicker({
7025
8096
  if (hiddenSet.has(item)) return "red";
7026
8097
  if (STREAM_CHIP_KEYS.includes(item)) {
7027
8098
  const meta = visibleChipsMap.get(item);
7028
- if (!meta) return "red";
7029
- if (isChipExpired(meta)) return "red";
8099
+ if (!meta) return "cyan";
8100
+ if (isChipExpired(meta)) return "cyan";
7030
8101
  return "yellow";
7031
8102
  }
7032
8103
  return "green";
@@ -7055,7 +8126,7 @@ function StatuslinePicker({
7055
8126
  ] }, `row-${item}`);
7056
8127
  }),
7057
8128
  hasBelow ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2193 ${totalFields - windowEnd} item${totalFields - windowEnd === 1 ? "" : "s"} below` }) : null,
7058
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Changes apply instantly \xB7 persisted to ~/.wrongstack/statusline.json \xB7 auto chips expire after ~5m" }),
8129
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Changes apply instantly \xB7 persisted to ~/.wrongstack/statusline.json \xB7 auto chips show when data exists" }),
7059
8130
  hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
7060
8131
  ] });
7061
8132
  }
@@ -7106,6 +8177,10 @@ function SlashMenu({ query, matches, selected }) {
7106
8177
  " ",
7107
8178
  m.argsHint
7108
8179
  ] }) : null,
8180
+ m.matchedAlias ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
8181
+ " alias /",
8182
+ m.matchedAlias
8183
+ ] }) : null,
7109
8184
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
7110
8185
  " \u2014 ",
7111
8186
  m.description
@@ -7187,13 +8262,10 @@ function hintsFor(ctx) {
7187
8262
  }
7188
8263
  function KeyHintBar({ context }) {
7189
8264
  const hints = hintsFor(context);
7190
- return /* @__PURE__ */ jsx(Box, { flexDirection: "row", paddingX: 1, children: hints.map((h, i) => (
7191
- // biome-ignore lint/suspicious/noArrayIndexKey: hints are positional + stable
7192
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", marginRight: 2, children: [
7193
- /* @__PURE__ */ jsx(Text, { color: h.discovery ? theme.monitor.agents : theme.accent, children: h.key }),
7194
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${h.label}` })
7195
- ] }, i)
7196
- )) });
8265
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "row", paddingX: 1, children: hints.map((h, i) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", marginRight: 2, children: [
8266
+ /* @__PURE__ */ jsx(Text, { color: h.discovery ? theme.monitor.agents : theme.accent, children: h.key }),
8267
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${h.label}` })
8268
+ ] }, i)) });
7197
8269
  }
7198
8270
  function TodosMonitor({ todos }) {
7199
8271
  const { stdout } = useStdout();
@@ -7426,7 +8498,7 @@ var fmtElapsed6 = (ms) => {
7426
8498
  if (m > 0) return `${m}:${String(s2 % 60).padStart(2, "0")}`;
7427
8499
  return `${s2}s`;
7428
8500
  };
7429
- var STATUS4 = {
8501
+ var STATUS5 = {
7430
8502
  allocating: { icon: "\u25CB", color: "gray" },
7431
8503
  active: { icon: "\u25CF", color: "yellow" },
7432
8504
  committing: { icon: "\u25D0", color: "cyan" },
@@ -7436,7 +8508,7 @@ var STATUS4 = {
7436
8508
  failed: { icon: "\u2717", color: "red" }
7437
8509
  };
7438
8510
  function st(status) {
7439
- return STATUS4[status] ?? { icon: "?", color: "white" };
8511
+ return STATUS5[status] ?? { icon: "?", color: "white" };
7440
8512
  }
7441
8513
  function WorktreePanel({
7442
8514
  worktrees,
@@ -8386,16 +9458,56 @@ function useAutoPhaseEvents(subscribeAutoPhase, dispatch, stateRef) {
8386
9458
  });
8387
9459
  break;
8388
9460
  }
8389
- case "phase.statusChange": {
9461
+ case "phase.statusChange": {
9462
+ const p = payload;
9463
+ const status = p.to === "running" ? "running" : p.to;
9464
+ dispatch({
9465
+ type: "autoPhasePhaseUpdate",
9466
+ phaseId: p.phaseId,
9467
+ name: p.name,
9468
+ status,
9469
+ completedTasks: 0,
9470
+ totalTasks: 0
9471
+ });
9472
+ break;
9473
+ }
9474
+ case "phase.taskStarted": {
9475
+ const p = payload;
9476
+ dispatch({
9477
+ type: "autoPhaseTaskActive",
9478
+ phaseId: p.phaseId,
9479
+ taskId: p.taskId,
9480
+ title: p.taskTitle,
9481
+ agent: p.agentName,
9482
+ active: true
9483
+ });
9484
+ break;
9485
+ }
9486
+ case "phase.taskAssigned": {
9487
+ const p = payload;
9488
+ const active = stateRef.current.autoPhase?.phases[p.phaseId]?.activeTasks?.find(
9489
+ (t) => t.taskId === p.taskId
9490
+ );
9491
+ if (active) {
9492
+ dispatch({
9493
+ type: "autoPhaseTaskActive",
9494
+ phaseId: p.phaseId,
9495
+ taskId: p.taskId,
9496
+ title: active.title,
9497
+ agent: p.agentName,
9498
+ active: true
9499
+ });
9500
+ }
9501
+ break;
9502
+ }
9503
+ case "phase.taskFailed": {
8390
9504
  const p = payload;
8391
- const status = p.to === "running" ? "running" : p.to;
8392
9505
  dispatch({
8393
- type: "autoPhasePhaseUpdate",
9506
+ type: "autoPhaseTaskActive",
8394
9507
  phaseId: p.phaseId,
8395
- name: p.name,
8396
- status,
8397
- completedTasks: 0,
8398
- totalTasks: 0
9508
+ taskId: p.taskId,
9509
+ title: "",
9510
+ active: false
8399
9511
  });
8400
9512
  break;
8401
9513
  }
@@ -8412,6 +9524,13 @@ function useAutoPhaseEvents(subscribeAutoPhase, dispatch, stateRef) {
8412
9524
  totalTasks: existing.totalTasks
8413
9525
  });
8414
9526
  }
9527
+ dispatch({
9528
+ type: "autoPhaseTaskActive",
9529
+ phaseId: p.phaseId,
9530
+ taskId: p.taskId,
9531
+ title: "",
9532
+ active: false
9533
+ });
8415
9534
  break;
8416
9535
  }
8417
9536
  case "autonomous.tick": {
@@ -8430,6 +9549,11 @@ function useAutoPhaseEvents(subscribeAutoPhase, dispatch, stateRef) {
8430
9549
  dispatch({ type: "autoPhaseReset" });
8431
9550
  break;
8432
9551
  }
9552
+ case "sdd.board.snapshot": {
9553
+ const p = payload;
9554
+ if (p.snapshot) dispatch({ type: "sddBoardSnapshot", snapshot: p.snapshot });
9555
+ break;
9556
+ }
8433
9557
  case "worktree.allocated": {
8434
9558
  const p = payload;
8435
9559
  dispatch({
@@ -8713,6 +9837,79 @@ function oneLine(s2, max) {
8713
9837
  return collapsed.length <= max ? collapsed : `${collapsed.slice(0, max - 1)}\u2026`;
8714
9838
  }
8715
9839
 
9840
+ // src/slash-command-search.ts
9841
+ var CATEGORY_ORDER = ["Run", "Session", "Inspect", "Agent", "Config", "App"];
9842
+ function buildSlashCommandMatches(entries, rawQuery) {
9843
+ const query = normalizeSlashQuery(rawQuery);
9844
+ const matches = [];
9845
+ for (const entry of entries) {
9846
+ const ranked = rankSlashCommand(entry, query);
9847
+ if (!ranked) continue;
9848
+ matches.push(ranked);
9849
+ }
9850
+ return matches.sort((a, b) => {
9851
+ if (a.rank !== b.rank) return a.rank - b.rank;
9852
+ const catDiff = CATEGORY_ORDER.indexOf(a.category) - CATEGORY_ORDER.indexOf(b.category);
9853
+ if (catDiff !== 0) return catDiff;
9854
+ return a.name.localeCompare(b.name);
9855
+ }).map(({ rank: _rank, ...match }) => match);
9856
+ }
9857
+ function normalizeSlashQuery(raw) {
9858
+ return raw.trim().replace(/^\/+/, "").toLowerCase();
9859
+ }
9860
+ function rankSlashCommand(entry, query) {
9861
+ const { cmd, owner } = entry;
9862
+ if (query === "" && cmd.hidden) return null;
9863
+ const name = displayName(entry);
9864
+ const lowerName = name.toLowerCase();
9865
+ const aliases = aliasCandidates(entry);
9866
+ const category = cmd.category ?? "App";
9867
+ let rank = null;
9868
+ let matchedAlias;
9869
+ if (query === "") {
9870
+ rank = 100;
9871
+ } else if (lowerName === query) {
9872
+ rank = 0;
9873
+ } else if (aliases.find((alias) => alias.toLowerCase() === query)) {
9874
+ rank = 5;
9875
+ matchedAlias = aliases.find((alias) => alias.toLowerCase() === query);
9876
+ } else if (lowerName.startsWith(query)) {
9877
+ rank = 10;
9878
+ } else {
9879
+ const prefixAlias = aliases.find((alias) => alias.toLowerCase().startsWith(query));
9880
+ if (prefixAlias) {
9881
+ rank = 20;
9882
+ matchedAlias = prefixAlias;
9883
+ }
9884
+ }
9885
+ if (rank == null) return null;
9886
+ return {
9887
+ name,
9888
+ description: cmd.description,
9889
+ argsHint: cmd.argsHint,
9890
+ isBuiltin: owner === "core",
9891
+ category,
9892
+ ...matchedAlias ? { matchedAlias } : {},
9893
+ rank
9894
+ };
9895
+ }
9896
+ function displayName({ cmd, owner, fullName }) {
9897
+ if (owner === "core") return cmd.name;
9898
+ return fullName.includes(":") ? fullName : cmd.name;
9899
+ }
9900
+ function aliasCandidates({ cmd, owner, fullName }) {
9901
+ const aliases = cmd.aliases ?? [];
9902
+ if (owner === "core") return aliases;
9903
+ const out = [...aliases];
9904
+ for (const alias of aliases) {
9905
+ out.push(`${owner}:${alias}`);
9906
+ }
9907
+ if (fullName.includes(":")) {
9908
+ return out.filter((alias) => alias.includes(":"));
9909
+ }
9910
+ return out;
9911
+ }
9912
+
8716
9913
  // src/steering-preamble.ts
8717
9914
  function buildSteeringPreamble(snapshot, newDirection) {
8718
9915
  const lines = ["[STEERING \u2014 I pressed Esc to interrupt you mid-task on purpose.", ""];
@@ -8764,10 +9961,15 @@ function closePanels(state) {
8764
9961
  projectPicker: { ...state.projectPicker, open: false },
8765
9962
  fKeyPicker: { ...state.fKeyPicker, open: false },
8766
9963
  autoPhase: state.autoPhase ? { ...state.autoPhase, monitorOpen: false } : state.autoPhase,
9964
+ sddBoard: state.sddBoard ? { ...state.sddBoard, monitorOpen: false } : state.sddBoard,
8767
9965
  worktreeMonitorOpen: false,
8768
9966
  coordinator: { ...state.coordinator, monitorOpen: false }
8769
9967
  };
8770
9968
  }
9969
+ function clampContextLoad(load) {
9970
+ if (!Number.isFinite(load)) return 0;
9971
+ return Math.max(0, Math.min(1, load));
9972
+ }
8771
9973
  var MAX_TOOL_STREAM_RETAINED_CHARS = 1e5;
8772
9974
  var MAX_RETAINED_INPUT_CHARS = 2048;
8773
9975
  var MAX_RETAINED_INPUT_DEPTH = 4;
@@ -9149,12 +10351,26 @@ function reducer(state, action) {
9149
10351
  return {
9150
10352
  ...state,
9151
10353
  ...closePanels(state),
9152
- resumePicker: { open: true, sessions: action.sessions, selected: 0, busy: false, hint: void 0, error: void 0 }
10354
+ resumePicker: {
10355
+ open: true,
10356
+ sessions: action.sessions,
10357
+ selected: 0,
10358
+ busy: false,
10359
+ hint: void 0,
10360
+ error: void 0
10361
+ }
9153
10362
  };
9154
10363
  case "resumePickerClose":
9155
10364
  return {
9156
10365
  ...state,
9157
- resumePicker: { open: false, sessions: [], selected: 0, busy: false, hint: void 0, error: void 0 }
10366
+ resumePicker: {
10367
+ open: false,
10368
+ sessions: [],
10369
+ selected: 0,
10370
+ busy: false,
10371
+ hint: void 0,
10372
+ error: void 0
10373
+ }
9158
10374
  };
9159
10375
  case "resumePickerMove": {
9160
10376
  const nr = state.resumePicker.sessions.length;
@@ -9173,7 +10389,12 @@ function reducer(state, action) {
9173
10389
  const maxBannerId = banners.length > 0 ? Math.max(...banners.map((b) => b.id)) : 0;
9174
10390
  const shifted = action.entries.map((e, i) => ({ ...e, id: maxBannerId + 1 + i }));
9175
10391
  const nextId = maxBannerId + 1 + shifted.length;
9176
- return { ...state, entries: [...banners, ...shifted], nextId, historyGen: state.historyGen + 1 };
10392
+ return {
10393
+ ...state,
10394
+ entries: [...banners, ...shifted],
10395
+ nextId,
10396
+ historyGen: state.historyGen + 1
10397
+ };
9177
10398
  }
9178
10399
  case "settingsOpen":
9179
10400
  return {
@@ -9244,121 +10465,295 @@ function reducer(state, action) {
9244
10465
  const i = SETTINGS_MODES.indexOf(sp.mode);
9245
10466
  const base = i < 0 ? 0 : i;
9246
10467
  const next = (base + action.delta + SETTINGS_MODES.length) % SETTINGS_MODES.length;
9247
- return { ...state, settingsPicker: { ...sp, mode: expectDefined$1(SETTINGS_MODES[next]), hint: void 0 } };
10468
+ return {
10469
+ ...state,
10470
+ settingsPicker: { ...sp, mode: expectDefined$1(SETTINGS_MODES[next]), hint: void 0 }
10471
+ };
9248
10472
  }
9249
10473
  if (f === 1) {
9250
10474
  const j = DELAY_PRESETS_MS.indexOf(sp.delayMs);
9251
10475
  const base = j < 0 ? 0 : j;
9252
10476
  const next = (base + action.delta + DELAY_PRESETS_MS.length) % DELAY_PRESETS_MS.length;
9253
- return { ...state, settingsPicker: { ...sp, delayMs: expectDefined$1(DELAY_PRESETS_MS[next]), hint: void 0 } };
10477
+ return {
10478
+ ...state,
10479
+ settingsPicker: {
10480
+ ...sp,
10481
+ delayMs: expectDefined$1(DELAY_PRESETS_MS[next]),
10482
+ hint: void 0
10483
+ }
10484
+ };
9254
10485
  }
9255
- if (f === 2) return { ...state, settingsPicker: { ...sp, titleAnimation: !sp.titleAnimation, hint: void 0 } };
10486
+ if (f === 2)
10487
+ return {
10488
+ ...state,
10489
+ settingsPicker: { ...sp, titleAnimation: !sp.titleAnimation, hint: void 0 }
10490
+ };
9256
10491
  if (f === 3) return { ...state, settingsPicker: { ...sp, yolo: !sp.yolo, hint: void 0 } };
9257
- if (f === 4) return { ...state, settingsPicker: { ...sp, streamFleet: !sp.streamFleet, hint: void 0 } };
9258
- if (f === 5) return { ...state, settingsPicker: { ...sp, chime: !sp.chime, hint: void 0 } };
9259
- if (f === 6) return { ...state, settingsPicker: { ...sp, confirmExit: !sp.confirmExit, hint: void 0 } };
9260
- if (f === 7) return { ...state, settingsPicker: { ...sp, nextPrediction: !sp.nextPrediction, hint: void 0 } };
9261
- if (f === 8) return { ...state, settingsPicker: { ...sp, featureMcp: !sp.featureMcp, hint: bootHint } };
9262
- if (f === 9) return { ...state, settingsPicker: { ...sp, featurePlugins: !sp.featurePlugins, hint: bootHint } };
9263
- if (f === 10) return { ...state, settingsPicker: { ...sp, featureMemory: !sp.featureMemory, hint: bootHint } };
9264
- if (f === 11) return { ...state, settingsPicker: { ...sp, featureSkills: !sp.featureSkills, hint: bootHint } };
9265
- if (f === 12) return { ...state, settingsPicker: { ...sp, featureModelsRegistry: !sp.featureModelsRegistry, hint: bootHint } };
10492
+ if (f === 4)
10493
+ return {
10494
+ ...state,
10495
+ settingsPicker: { ...sp, streamFleet: !sp.streamFleet, hint: void 0 }
10496
+ };
10497
+ if (f === 5)
10498
+ return { ...state, settingsPicker: { ...sp, chime: !sp.chime, hint: void 0 } };
10499
+ if (f === 6)
10500
+ return {
10501
+ ...state,
10502
+ settingsPicker: { ...sp, confirmExit: !sp.confirmExit, hint: void 0 }
10503
+ };
10504
+ if (f === 7)
10505
+ return {
10506
+ ...state,
10507
+ settingsPicker: { ...sp, nextPrediction: !sp.nextPrediction, hint: void 0 }
10508
+ };
10509
+ if (f === 8)
10510
+ return { ...state, settingsPicker: { ...sp, featureMcp: !sp.featureMcp, hint: bootHint } };
10511
+ if (f === 9)
10512
+ return {
10513
+ ...state,
10514
+ settingsPicker: { ...sp, featurePlugins: !sp.featurePlugins, hint: bootHint }
10515
+ };
10516
+ if (f === 10)
10517
+ return {
10518
+ ...state,
10519
+ settingsPicker: { ...sp, featureMemory: !sp.featureMemory, hint: bootHint }
10520
+ };
10521
+ if (f === 11)
10522
+ return {
10523
+ ...state,
10524
+ settingsPicker: { ...sp, featureSkills: !sp.featureSkills, hint: bootHint }
10525
+ };
10526
+ if (f === 12)
10527
+ return {
10528
+ ...state,
10529
+ settingsPicker: {
10530
+ ...sp,
10531
+ featureModelsRegistry: !sp.featureModelsRegistry,
10532
+ hint: bootHint
10533
+ }
10534
+ };
9266
10535
  if (f === 13) {
9267
- const i = TOKEN_SAVING_TIERS.indexOf(sp.tokenSavingTier);
10536
+ const i = TOKEN_SAVING_TIERS.indexOf(
10537
+ sp.tokenSavingTier
10538
+ );
9268
10539
  const base = i < 0 ? 0 : i;
9269
10540
  const next = (base + action.delta + TOKEN_SAVING_TIERS.length) % TOKEN_SAVING_TIERS.length;
9270
- return { ...state, settingsPicker: { ...sp, tokenSavingTier: TOKEN_SAVING_TIERS[next] ?? "off", hint: bootHint } };
10541
+ return {
10542
+ ...state,
10543
+ settingsPicker: {
10544
+ ...sp,
10545
+ tokenSavingTier: TOKEN_SAVING_TIERS[next] ?? "off",
10546
+ hint: bootHint
10547
+ }
10548
+ };
9271
10549
  }
9272
- if (f === 14) return { ...state, settingsPicker: { ...sp, allowOutsideProjectRoot: !sp.allowOutsideProjectRoot, hint: void 0 } };
10550
+ if (f === 14)
10551
+ return {
10552
+ ...state,
10553
+ settingsPicker: {
10554
+ ...sp,
10555
+ allowOutsideProjectRoot: !sp.allowOutsideProjectRoot,
10556
+ hint: void 0
10557
+ }
10558
+ };
9273
10559
  if (f === 15) {
9274
10560
  const j = MAX_ITERATIONS_PRESETS.indexOf(sp.maxIterations);
9275
10561
  const base = j < 0 ? 0 : j;
9276
10562
  const next = (base + action.delta + MAX_ITERATIONS_PRESETS.length) % MAX_ITERATIONS_PRESETS.length;
9277
- return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined$1(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
10563
+ return {
10564
+ ...state,
10565
+ settingsPicker: {
10566
+ ...sp,
10567
+ maxIterations: expectDefined$1(MAX_ITERATIONS_PRESETS[next]),
10568
+ hint: void 0
10569
+ }
10570
+ };
9278
10571
  }
9279
10572
  if (f === 16) {
9280
10573
  const aj = AUTO_PROCEED_MAX_PRESETS.indexOf(sp.autoProceedMaxIterations);
9281
10574
  const abase = aj < 0 ? 0 : aj;
9282
10575
  const anext = (abase + action.delta + AUTO_PROCEED_MAX_PRESETS.length) % AUTO_PROCEED_MAX_PRESETS.length;
9283
- return { ...state, settingsPicker: { ...sp, autoProceedMaxIterations: expectDefined$1(AUTO_PROCEED_MAX_PRESETS[anext]), hint: void 0 } };
10576
+ return {
10577
+ ...state,
10578
+ settingsPicker: {
10579
+ ...sp,
10580
+ autoProceedMaxIterations: expectDefined$1(AUTO_PROCEED_MAX_PRESETS[anext]),
10581
+ hint: void 0
10582
+ }
10583
+ };
9284
10584
  }
9285
10585
  if (f === 17) {
9286
10586
  const ej = ENHANCE_DELAY_PRESETS.indexOf(sp.enhanceDelayMs);
9287
10587
  const ebase = ej < 0 ? 0 : ej;
9288
10588
  const enext = (ebase + action.delta + ENHANCE_DELAY_PRESETS.length) % ENHANCE_DELAY_PRESETS.length;
9289
- return { ...state, settingsPicker: { ...sp, enhanceDelayMs: expectDefined$1(ENHANCE_DELAY_PRESETS[enext]), hint: void 0 } };
10589
+ return {
10590
+ ...state,
10591
+ settingsPicker: {
10592
+ ...sp,
10593
+ enhanceDelayMs: expectDefined$1(ENHANCE_DELAY_PRESETS[enext]),
10594
+ hint: void 0
10595
+ }
10596
+ };
9290
10597
  }
9291
- if (f === 18) return { ...state, settingsPicker: { ...sp, enhanceEnabled: !sp.enhanceEnabled, hint: void 0 } };
10598
+ if (f === 18)
10599
+ return {
10600
+ ...state,
10601
+ settingsPicker: { ...sp, enhanceEnabled: !sp.enhanceEnabled, hint: void 0 }
10602
+ };
9292
10603
  if (f === 19) {
9293
10604
  const i = ENHANCE_LANGUAGES.indexOf(sp.enhanceLanguage);
9294
10605
  const base = i < 0 ? 0 : i;
9295
10606
  const next = (base + action.delta + ENHANCE_LANGUAGES.length) % ENHANCE_LANGUAGES.length;
9296
- return { ...state, settingsPicker: { ...sp, enhanceLanguage: expectDefined$1(ENHANCE_LANGUAGES[next]), hint: void 0 } };
10607
+ return {
10608
+ ...state,
10609
+ settingsPicker: {
10610
+ ...sp,
10611
+ enhanceLanguage: expectDefined$1(ENHANCE_LANGUAGES[next]),
10612
+ hint: void 0
10613
+ }
10614
+ };
9297
10615
  }
9298
- if (f === 20) return { ...state, settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: bootHint } };
10616
+ if (f === 20)
10617
+ return {
10618
+ ...state,
10619
+ settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: bootHint }
10620
+ };
9299
10621
  if (f === 21) return state;
9300
10622
  if (f === 22) {
9301
10623
  const i = REASONING_MODES.indexOf(sp.reasoningMode);
9302
10624
  const base = i < 0 ? 0 : i;
9303
10625
  const next = (base + action.delta + REASONING_MODES.length) % REASONING_MODES.length;
9304
- return { ...state, settingsPicker: { ...sp, reasoningMode: expectDefined$1(REASONING_MODES[next]), hint: void 0 } };
10626
+ return {
10627
+ ...state,
10628
+ settingsPicker: {
10629
+ ...sp,
10630
+ reasoningMode: expectDefined$1(REASONING_MODES[next]),
10631
+ hint: void 0
10632
+ }
10633
+ };
9305
10634
  }
9306
10635
  if (f === 23) {
9307
- const i = REASONING_EFFORTS.indexOf(sp.reasoningEffort);
10636
+ const i = REASONING_EFFORTS.indexOf(
10637
+ sp.reasoningEffort
10638
+ );
9308
10639
  const base = i < 0 ? REASONING_EFFORTS.indexOf("high") : i;
9309
10640
  const next = (base + action.delta + REASONING_EFFORTS.length) % REASONING_EFFORTS.length;
9310
- return { ...state, settingsPicker: { ...sp, reasoningEffort: expectDefined$1(REASONING_EFFORTS[next]), hint: void 0 } };
10641
+ return {
10642
+ ...state,
10643
+ settingsPicker: {
10644
+ ...sp,
10645
+ reasoningEffort: expectDefined$1(REASONING_EFFORTS[next]),
10646
+ hint: void 0
10647
+ }
10648
+ };
9311
10649
  }
9312
- if (f === 24) return { ...state, settingsPicker: { ...sp, reasoningPreserve: !sp.reasoningPreserve, hint: void 0 } };
10650
+ if (f === 24)
10651
+ return {
10652
+ ...state,
10653
+ settingsPicker: { ...sp, reasoningPreserve: !sp.reasoningPreserve, hint: void 0 }
10654
+ };
9313
10655
  if (f === 25) {
9314
10656
  const i = CACHE_TTLS.indexOf(sp.cacheTtl);
9315
10657
  const base = i < 0 ? 0 : i;
9316
10658
  const next = (base + action.delta + CACHE_TTLS.length) % CACHE_TTLS.length;
9317
- return { ...state, settingsPicker: { ...sp, cacheTtl: expectDefined$1(CACHE_TTLS[next]), hint: void 0 } };
10659
+ return {
10660
+ ...state,
10661
+ settingsPicker: { ...sp, cacheTtl: expectDefined$1(CACHE_TTLS[next]), hint: void 0 }
10662
+ };
9318
10663
  }
9319
- if (f === 26) return { ...state, settingsPicker: { ...sp, contextAutoCompact: !sp.contextAutoCompact, hint: void 0 } };
10664
+ if (f === 26)
10665
+ return {
10666
+ ...state,
10667
+ settingsPicker: { ...sp, contextAutoCompact: !sp.contextAutoCompact, hint: void 0 }
10668
+ };
9320
10669
  if (f === 27) {
9321
10670
  const i = COMPACTOR_STRATEGIES.indexOf(sp.contextStrategy);
9322
10671
  const base = i < 0 ? 0 : i;
9323
10672
  const next = (base + action.delta + COMPACTOR_STRATEGIES.length) % COMPACTOR_STRATEGIES.length;
9324
- return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined$1(COMPACTOR_STRATEGIES[next]), hint: bootHint } };
10673
+ return {
10674
+ ...state,
10675
+ settingsPicker: {
10676
+ ...sp,
10677
+ contextStrategy: expectDefined$1(COMPACTOR_STRATEGIES[next]),
10678
+ hint: bootHint
10679
+ }
10680
+ };
9325
10681
  }
9326
10682
  if (f === 28) {
9327
10683
  const i = CONTEXT_MODES.indexOf(sp.contextMode);
9328
10684
  const base = i < 0 ? 0 : i;
9329
10685
  const next = (base + action.delta + CONTEXT_MODES.length) % CONTEXT_MODES.length;
9330
- return { ...state, settingsPicker: { ...sp, contextMode: expectDefined$1(CONTEXT_MODES[next]), hint: bootHint } };
10686
+ return {
10687
+ ...state,
10688
+ settingsPicker: {
10689
+ ...sp,
10690
+ contextMode: expectDefined$1(CONTEXT_MODES[next]),
10691
+ hint: bootHint
10692
+ }
10693
+ };
9331
10694
  }
9332
10695
  if (f === 29) {
9333
10696
  const j = MAX_CONCURRENT_PRESETS.indexOf(sp.maxConcurrent);
9334
10697
  const base = j < 0 ? 0 : j;
9335
10698
  const next = (base + action.delta + MAX_CONCURRENT_PRESETS.length) % MAX_CONCURRENT_PRESETS.length;
9336
- return { ...state, settingsPicker: { ...sp, maxConcurrent: expectDefined$1(MAX_CONCURRENT_PRESETS[next]), hint: void 0 } };
10699
+ const maxConcurrent = expectDefined$1(MAX_CONCURRENT_PRESETS[next]);
10700
+ return {
10701
+ ...state,
10702
+ settingsPicker: {
10703
+ ...sp,
10704
+ maxConcurrent,
10705
+ hint: maxConcurrent === 0 ? bootHint : void 0
10706
+ }
10707
+ };
9337
10708
  }
9338
10709
  if (f === 30) {
9339
10710
  const i = LOG_LEVELS.indexOf(sp.logLevel);
9340
10711
  const base = i < 0 ? 0 : i;
9341
10712
  const next = (base + action.delta + LOG_LEVELS.length) % LOG_LEVELS.length;
9342
- return { ...state, settingsPicker: { ...sp, logLevel: expectDefined$1(LOG_LEVELS[next]), hint: void 0 } };
10713
+ return {
10714
+ ...state,
10715
+ settingsPicker: { ...sp, logLevel: expectDefined$1(LOG_LEVELS[next]), hint: void 0 }
10716
+ };
9343
10717
  }
9344
10718
  if (f === 31) {
9345
10719
  const i = AUDIT_LEVELS.indexOf(sp.auditLevel);
9346
10720
  const base = i < 0 ? 0 : i;
9347
10721
  const next = (base + action.delta + AUDIT_LEVELS.length) % AUDIT_LEVELS.length;
9348
- return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined$1(AUDIT_LEVELS[next]), hint: void 0 } };
10722
+ return {
10723
+ ...state,
10724
+ settingsPicker: { ...sp, auditLevel: expectDefined$1(AUDIT_LEVELS[next]), hint: void 0 }
10725
+ };
9349
10726
  }
9350
- if (f === 32) return { ...state, settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 } };
10727
+ if (f === 32)
10728
+ return {
10729
+ ...state,
10730
+ settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 }
10731
+ };
9351
10732
  if (f === 33) {
9352
10733
  const i = STATUSLINE_MODES.indexOf(sp.statuslineMode);
9353
10734
  const base = i < 0 ? STATUSLINE_MODES.indexOf("detailed") : i;
9354
10735
  const next = (base + action.delta + STATUSLINE_MODES.length) % STATUSLINE_MODES.length;
9355
- return { ...state, settingsPicker: { ...sp, statuslineMode: expectDefined$1(STATUSLINE_MODES[next]), hint: void 0 } };
10736
+ return {
10737
+ ...state,
10738
+ settingsPicker: {
10739
+ ...sp,
10740
+ statuslineMode: expectDefined$1(STATUSLINE_MODES[next]),
10741
+ hint: void 0
10742
+ }
10743
+ };
9356
10744
  }
9357
10745
  if (f === 34) {
9358
10746
  const i = CONFIG_SCOPES.indexOf(sp.configScope);
9359
10747
  const base = i < 0 ? 0 : i;
9360
10748
  const next = (base + action.delta + CONFIG_SCOPES.length) % CONFIG_SCOPES.length;
9361
- return { ...state, settingsPicker: { ...sp, configScope: expectDefined$1(CONFIG_SCOPES[next]), hint: void 0 } };
10749
+ return {
10750
+ ...state,
10751
+ settingsPicker: {
10752
+ ...sp,
10753
+ configScope: expectDefined$1(CONFIG_SCOPES[next]),
10754
+ hint: void 0
10755
+ }
10756
+ };
9362
10757
  }
9363
10758
  return state;
9364
10759
  }
@@ -9369,17 +10764,29 @@ function reducer(state, action) {
9369
10764
  return {
9370
10765
  ...state,
9371
10766
  ...closePanels(state),
9372
- statuslinePicker: { open: true, field: 0, hiddenItems: action.hiddenItems, visibleChips: state.statuslinePicker.visibleChips, hint: void 0 }
10767
+ statuslinePicker: {
10768
+ open: true,
10769
+ field: 0,
10770
+ hiddenItems: action.hiddenItems,
10771
+ visibleChips: state.statuslinePicker.visibleChips,
10772
+ hint: void 0
10773
+ }
9373
10774
  };
9374
10775
  case "statuslineClose":
9375
- return { ...state, statuslinePicker: { ...state.statuslinePicker, open: false, hint: void 0 } };
10776
+ return {
10777
+ ...state,
10778
+ statuslinePicker: { ...state.statuslinePicker, open: false, hint: void 0 }
10779
+ };
9376
10780
  case "statuslineFieldMove": {
9377
- const totalFields = 13;
10781
+ const totalFields = STATUSLINE_FIELD_COUNT;
9378
10782
  const next = (state.statuslinePicker.field + action.delta + totalFields) % totalFields;
9379
- return { ...state, statuslinePicker: { ...state.statuslinePicker, field: next, hint: void 0 } };
10783
+ return {
10784
+ ...state,
10785
+ statuslinePicker: { ...state.statuslinePicker, field: next, hint: void 0 }
10786
+ };
9380
10787
  }
9381
10788
  case "statuslineFieldSet": {
9382
- const totalFields = 13;
10789
+ const totalFields = STATUSLINE_FIELD_COUNT;
9383
10790
  const field = action.field >= 0 && action.field < totalFields ? action.field : 0;
9384
10791
  return { ...state, statuslinePicker: { ...state.statuslinePicker, field, hint: void 0 } };
9385
10792
  }
@@ -9391,7 +10798,10 @@ function reducer(state, action) {
9391
10798
  } else {
9392
10799
  hiddenSet.add(action.item);
9393
10800
  }
9394
- return { ...state, statuslinePicker: { ...cur, hiddenItems: [...hiddenSet] } };
10801
+ return {
10802
+ ...state,
10803
+ statuslinePicker: { ...cur, hiddenItems: [...hiddenSet] }
10804
+ };
9395
10805
  }
9396
10806
  case "statuslineHint":
9397
10807
  return { ...state, statuslinePicker: { ...state.statuslinePicker, hint: action.text } };
@@ -9437,7 +10847,14 @@ function reducer(state, action) {
9437
10847
  case "projectPickerClose":
9438
10848
  return {
9439
10849
  ...state,
9440
- projectPicker: { open: false, allItems: [], items: [], selected: 0, filter: "", hint: void 0 }
10850
+ projectPicker: {
10851
+ open: false,
10852
+ allItems: [],
10853
+ items: [],
10854
+ selected: 0,
10855
+ filter: "",
10856
+ hint: void 0
10857
+ }
9441
10858
  };
9442
10859
  case "projectPickerMove": {
9443
10860
  const cur = state.projectPicker;
@@ -9705,13 +11122,14 @@ function reducer(state, action) {
9705
11122
  case "fleetCtxPct": {
9706
11123
  const cur = state.fleet[action.id];
9707
11124
  if (!cur) return state;
11125
+ const ctxPct = clampContextLoad(action.load);
9708
11126
  return {
9709
11127
  ...state,
9710
11128
  fleet: {
9711
11129
  ...state.fleet,
9712
11130
  [action.id]: {
9713
11131
  ...cur,
9714
- ctxPct: action.load,
11132
+ ctxPct,
9715
11133
  ctxTokens: action.tokens,
9716
11134
  ctxMaxTokens: action.maxContext,
9717
11135
  ctxCost: action.ctxCost,
@@ -9794,11 +11212,12 @@ function reducer(state, action) {
9794
11212
  };
9795
11213
  }
9796
11214
  case "leaderCtxPct": {
11215
+ const ctxPct = clampContextLoad(action.load);
9797
11216
  return {
9798
11217
  ...state,
9799
11218
  leader: {
9800
11219
  ...state.leader,
9801
- ctxPct: action.load,
11220
+ ctxPct,
9802
11221
  ctxTokens: action.tokens,
9803
11222
  ctxMaxTokens: action.maxContext,
9804
11223
  lastEventAt: Date.now()
@@ -9905,12 +11324,31 @@ function reducer(state, action) {
9905
11324
  status: action.status,
9906
11325
  completedTasks: action.completedTasks,
9907
11326
  totalTasks: action.totalTasks,
9908
- startedAt: action.startedAt
11327
+ startedAt: action.startedAt,
11328
+ // Preserve the live worker list across status/count updates.
11329
+ activeTasks: existing.phases[action.phaseId]?.activeTasks
9909
11330
  }
9910
11331
  }
9911
11332
  }
9912
11333
  };
9913
11334
  }
11335
+ case "autoPhaseTaskActive": {
11336
+ if (!state.autoPhase) return state;
11337
+ const phase = state.autoPhase.phases[action.phaseId];
11338
+ if (!phase) return state;
11339
+ const without = (phase.activeTasks ?? []).filter((t) => t.taskId !== action.taskId);
11340
+ const activeTasks = action.active ? [...without, { taskId: action.taskId, title: action.title, agent: action.agent }] : without;
11341
+ return {
11342
+ ...state,
11343
+ autoPhase: {
11344
+ ...state.autoPhase,
11345
+ phases: {
11346
+ ...state.autoPhase.phases,
11347
+ [action.phaseId]: { ...phase, activeTasks }
11348
+ }
11349
+ }
11350
+ };
11351
+ }
9914
11352
  case "autoPhaseRunningPhases": {
9915
11353
  if (!state.autoPhase) return state;
9916
11354
  return {
@@ -9937,6 +11375,41 @@ function reducer(state, action) {
9937
11375
  case "autoPhaseReset": {
9938
11376
  return { ...state, autoPhase: null };
9939
11377
  }
11378
+ case "sddBoardSnapshot": {
11379
+ const monitorOpen = state.sddBoard?.monitorOpen ?? false;
11380
+ const prevFocus = state.sddBoard?.focusColumn;
11381
+ const focusColumn = typeof prevFocus === "number" && prevFocus >= 0 && prevFocus < action.snapshot.columns.length ? prevFocus : void 0;
11382
+ return { ...state, sddBoard: { snapshot: action.snapshot, monitorOpen, focusColumn } };
11383
+ }
11384
+ case "toggleSddBoardMonitor": {
11385
+ if (!state.sddBoard) return state;
11386
+ const opening = !state.sddBoard.monitorOpen;
11387
+ return opening ? {
11388
+ ...state,
11389
+ ...closePanels(state),
11390
+ sddBoard: { ...state.sddBoard, monitorOpen: true }
11391
+ } : {
11392
+ ...state,
11393
+ sddBoard: { ...state.sddBoard, monitorOpen: false, focusColumn: void 0 }
11394
+ };
11395
+ }
11396
+ case "sddBoardFocusNext": {
11397
+ if (!state.sddBoard) return state;
11398
+ if (!state.sddBoard.monitorOpen) return state;
11399
+ const max = state.sddBoard.snapshot.columns.length - 1;
11400
+ if (max < 0) return state;
11401
+ const current = state.sddBoard.focusColumn;
11402
+ const next = typeof current === "number" ? Math.min(max, current + 1) : 0;
11403
+ return { ...state, sddBoard: { ...state.sddBoard, focusColumn: next } };
11404
+ }
11405
+ case "sddBoardFocusPrev": {
11406
+ if (!state.sddBoard) return state;
11407
+ if (!state.sddBoard.monitorOpen) return state;
11408
+ const current = state.sddBoard.focusColumn;
11409
+ if (typeof current !== "number") return state;
11410
+ const next = current <= 0 ? void 0 : current - 1;
11411
+ return { ...state, sddBoard: { ...state.sddBoard, focusColumn: next } };
11412
+ }
9940
11413
  case "worktreeUpsert": {
9941
11414
  const prev = state.worktrees[action.handleId];
9942
11415
  const merged = {
@@ -10314,32 +11787,56 @@ function nextInputWordStart(buffer, cursor) {
10314
11787
  }
10315
11788
  function rehydrateHistory(messages, startId, toolCalls) {
10316
11789
  const entries = [];
11790
+ const toolCallsById = /* @__PURE__ */ new Map();
11791
+ if (toolCalls) {
11792
+ for (const tc of toolCalls) {
11793
+ if (!toolCallsById.has(tc.id)) toolCallsById.set(tc.id, tc);
11794
+ }
11795
+ }
11796
+ const consumed = /* @__PURE__ */ new Set();
11797
+ const fallback = [];
10317
11798
  let nextId = startId;
11799
+ const textOf = (msg) => {
11800
+ if (typeof msg.content === "string") return msg.content;
11801
+ return msg.content.filter((b) => b.type === "text").map((b) => b.text).join("");
11802
+ };
11803
+ const toolEntryFor = (tc) => ({
11804
+ id: nextId++,
11805
+ kind: "tool",
11806
+ name: tc.name,
11807
+ durationMs: tc.durationMs,
11808
+ ok: tc.ok,
11809
+ outputBytes: tc.outputBytes,
11810
+ outputTokens: tc.outputTokens,
11811
+ outputLines: tc.outputLines
11812
+ });
10318
11813
  for (const msg of messages) {
10319
11814
  if (msg.role === "system") continue;
10320
- const text = typeof msg.content === "string" ? msg.content : msg.content.filter((b) => b.type === "text").map((b) => b.text).join("");
10321
- const trimmed = text.trim();
10322
- if (!trimmed) continue;
11815
+ const text = textOf(msg).trim();
11816
+ if (!text) continue;
10323
11817
  if (msg.role === "user") {
10324
- entries.push({ id: nextId++, kind: "user", text: trimmed });
10325
- } else if (msg.role === "assistant") {
10326
- entries.push({ id: nextId++, kind: "assistant", text: trimmed });
11818
+ entries.push({ id: nextId++, kind: "user", text });
11819
+ continue;
11820
+ }
11821
+ if (msg.role === "assistant") {
11822
+ entries.push({ id: nextId++, kind: "assistant", text });
11823
+ if (Array.isArray(msg.content)) {
11824
+ for (const block of msg.content) {
11825
+ if (block.type !== "tool_use") continue;
11826
+ const tc = toolCallsById.get(block.id);
11827
+ if (!tc) continue;
11828
+ entries.push(toolEntryFor(tc));
11829
+ consumed.add(block.id);
11830
+ }
11831
+ }
10327
11832
  }
10328
11833
  }
10329
- if (toolCalls && toolCalls.length > 0) {
11834
+ if (toolCalls) {
10330
11835
  for (const tc of toolCalls) {
10331
- entries.push({
10332
- id: nextId++,
10333
- kind: "tool",
10334
- name: tc.name,
10335
- durationMs: tc.durationMs,
10336
- ok: tc.ok,
10337
- outputBytes: tc.outputBytes,
10338
- outputTokens: tc.outputTokens,
10339
- outputLines: tc.outputLines
10340
- });
11836
+ if (!consumed.has(tc.id)) fallback.push(toolEntryFor(tc));
10341
11837
  }
10342
11838
  }
11839
+ entries.push(...fallback);
10343
11840
  return entries;
10344
11841
  }
10345
11842
  var PASTE_THRESHOLD_CHARS = 200;
@@ -10369,6 +11866,7 @@ function App({
10369
11866
  getAutonomy,
10370
11867
  getEternalEngine,
10371
11868
  getParallelEngine,
11869
+ getSddRun,
10372
11870
  subscribeEternalIteration,
10373
11871
  subscribeEternalStage,
10374
11872
  subscribeAutoPhase,
@@ -10396,6 +11894,7 @@ function App({
10396
11894
  director,
10397
11895
  fleetRoster,
10398
11896
  onClearHistory,
11897
+ clearTerminal,
10399
11898
  listSessions,
10400
11899
  onResumeSession,
10401
11900
  fleetStreamController,
@@ -10627,6 +12126,7 @@ function App({
10627
12126
  eternalStage: null,
10628
12127
  goalSummary: null,
10629
12128
  autoPhase: null,
12129
+ sddBoard: null,
10630
12130
  worktrees: {},
10631
12131
  worktreeMonitorOpen: false,
10632
12132
  coordinator: {
@@ -10738,8 +12238,22 @@ function App({
10738
12238
  stateRef.current = state;
10739
12239
  const draftRef = useRef({ buffer: state.buffer, cursor: state.cursor });
10740
12240
  draftRef.current = { buffer: state.buffer, cursor: state.cursor };
12241
+ const statuslineHiddenForPicker = useCallback(() => {
12242
+ const hookHidden = hiddenItemsRef.current;
12243
+ const hookHiddenSet = new Set(hookHidden);
12244
+ const reducerOnlyHidden = stateRef.current.statuslinePicker.hiddenItems.filter(
12245
+ (item) => !hookHiddenSet.has(item)
12246
+ );
12247
+ return [...hookHidden, ...reducerOnlyHidden];
12248
+ }, []);
12249
+ const openStatuslinePicker = useCallback((field) => {
12250
+ if (field !== void 0) {
12251
+ dispatch({ type: "statuslineFieldSet", field });
12252
+ }
12253
+ dispatch({ type: "statuslineOpen", hiddenItems: statuslineHiddenForPicker() });
12254
+ }, [statuslineHiddenForPicker]);
10741
12255
  const [mouseMode, setMouseMode] = useState(mouse);
10742
- const pickerOverlayOpen = state.modelPicker.open || state.autonomyPicker.open || state.settingsPicker.open || state.projectPicker.open || state.slashPicker.open || state.picker.open;
12256
+ const pickerOverlayOpen = state.modelPicker.open || state.autonomyPicker.open || state.settingsPicker.open || state.projectPicker.open || state.slashPicker.open || state.statuslinePicker.open || state.fKeyPicker.open || state.picker.open;
10743
12257
  const mouseTrackingOn = mouseMode || pickerOverlayOpen;
10744
12258
  const mouseWrittenRef = useRef(false);
10745
12259
  useEffect(() => {
@@ -10893,7 +12407,7 @@ function App({
10893
12407
  readGitInfo(agent.ctx.cwd).then((info) => {
10894
12408
  if (cancelled) return;
10895
12409
  setGitInfo(info);
10896
- if (info && info.branch) {
12410
+ if (info?.branch) {
10897
12411
  const prev = prevBranchRef.current;
10898
12412
  if (prev !== null && prev !== info.branch) {
10899
12413
  const msg = {
@@ -11371,24 +12885,7 @@ function App({
11371
12885
  return;
11372
12886
  }
11373
12887
  const query = trimmed.slice(1).toLowerCase();
11374
- const allCommands = slashRegistry.listWithOwner();
11375
- const CATEGORY_ORDER = ["Run", "Session", "Inspect", "Agent", "Config", "App"];
11376
- const matches = allCommands.filter(({ cmd }) => {
11377
- if (query === "" && cmd.hidden) return false;
11378
- const name = cmd.name.toLowerCase();
11379
- const aliases = cmd.aliases ?? [];
11380
- return name.includes(query) || aliases.some((a) => a.toLowerCase().includes(query));
11381
- }).map(({ cmd, owner }) => ({
11382
- name: cmd.name,
11383
- description: cmd.description,
11384
- argsHint: cmd.argsHint,
11385
- isBuiltin: owner === "core",
11386
- category: cmd.category ?? "App"
11387
- })).sort((a, b) => {
11388
- const catDiff = CATEGORY_ORDER.indexOf(a.category) - CATEGORY_ORDER.indexOf(b.category);
11389
- if (catDiff !== 0) return catDiff;
11390
- return a.name.localeCompare(b.name);
11391
- });
12888
+ const matches = buildSlashCommandMatches(slashRegistry.listWithOwner(), query);
11392
12889
  if (!state.slashPicker.open) {
11393
12890
  dispatch({ type: "slashPickerOpen", query, matches });
11394
12891
  } else if (state.slashPicker.query !== query) {
@@ -11962,12 +13459,41 @@ function App({
11962
13459
  aliases: ["sl"],
11963
13460
  description: "Customize status bar chips: /statusline (interactive) or /statusline <item> [on|off]",
11964
13461
  async run(args) {
11965
- if (args.trim()) return { message: void 0 };
11966
- const hookHidden = hiddenItemsRef.current;
11967
- const reducerStreamHidden = stateRef.current.statuslinePicker.hiddenItems.filter(
11968
- (item) => !hookHidden.includes(item)
11969
- );
11970
- dispatch({ type: "statuslineOpen", hiddenItems: [...hookHidden, ...reducerStreamHidden] });
13462
+ const trimmed = args.trim();
13463
+ if (trimmed) {
13464
+ const [rawItem, rawAction] = trimmed.split(/\s+/);
13465
+ const item = rawItem;
13466
+ const action = rawAction?.toLowerCase();
13467
+ const applyHidden = (items) => {
13468
+ const deduped = [...new Set(items)];
13469
+ hiddenItemsRef.current = deduped;
13470
+ setHiddenItems(deduped);
13471
+ };
13472
+ if (item === "reset") {
13473
+ applyHidden([]);
13474
+ return { message: "StatusBar config reset to defaults." };
13475
+ }
13476
+ if (item === "all") {
13477
+ if (action !== "on" && action !== "off") {
13478
+ return { message: "Usage: /statusline all on|off" };
13479
+ }
13480
+ applyHidden(action === "off" ? [...STATUSLINE_ITEMS] : []);
13481
+ return { message: `statusline all: ${action === "on" ? "showing all chips" : "hiding all chips"}` };
13482
+ }
13483
+ if (!item || !STATUSLINE_ITEMS.includes(item)) {
13484
+ return { message: `Unknown item "${rawItem ?? ""}". Run /statusline to see available items.` };
13485
+ }
13486
+ if (action !== void 0 && action !== "on" && action !== "off") {
13487
+ return { message: `Usage: /statusline ${item} on|off` };
13488
+ }
13489
+ const hidden = new Set(hiddenItemsRef.current);
13490
+ const nextVisible = action ? action === "on" : hidden.has(item);
13491
+ if (nextVisible) hidden.delete(item);
13492
+ else hidden.add(item);
13493
+ applyHidden([...hidden]);
13494
+ return { message: `statusline ${item}: ${nextVisible ? "on" : "off"}` };
13495
+ }
13496
+ openStatuslinePicker();
11971
13497
  return { message: void 0 };
11972
13498
  }
11973
13499
  };
@@ -11975,7 +13501,7 @@ function App({
11975
13501
  return () => {
11976
13502
  slashRegistry.unregister("statusline");
11977
13503
  };
11978
- }, [slashRegistry]);
13504
+ }, [slashRegistry, openStatuslinePicker, setHiddenItems]);
11979
13505
  useEffect(() => {
11980
13506
  const cmd = {
11981
13507
  name: "mailbox",
@@ -12395,9 +13921,12 @@ function App({
12395
13921
  (e) => e.status === "running"
12396
13922
  ).length;
12397
13923
  const autonomyRunning = eternalLoopRunningRef.current || parallelLoopRunningRef.current || getEternalEngine?.()?.currentState === "running" || getParallelEngine?.()?.currentState === "running";
12398
- if (autonomyRunning || fleetRunning > 0) {
13924
+ const sddRun = getSddRun?.();
13925
+ const sddRunning = sddRun?.isRunning() ?? false;
13926
+ if (autonomyRunning || fleetRunning > 0 || sddRunning) {
12399
13927
  getEternalEngine?.()?.stop();
12400
13928
  getParallelEngine?.()?.stop();
13929
+ if (sddRunning) sddRun?.stop();
12401
13930
  if (autonomyRunning) switchAutonomy?.("off");
12402
13931
  if (director) {
12403
13932
  const cap = new Promise((resolve) => {
@@ -12409,6 +13938,7 @@ function App({
12409
13938
  const killed2 = getProcessRegistry().killAll();
12410
13939
  const bits = [];
12411
13940
  if (autonomyRunning) bits.push("autonomy stopped");
13941
+ if (sddRunning) bits.push("SDD run stopped");
12412
13942
  if (fleetRunning > 0)
12413
13943
  bits.push(`${fleetRunning} agent${fleetRunning === 1 ? "" : "s"} terminated`);
12414
13944
  if (killed2.length > 0)
@@ -12434,7 +13964,7 @@ function App({
12434
13964
  return () => {
12435
13965
  process.off("SIGINT", onSigint);
12436
13966
  };
12437
- }, [director, getEternalEngine, getParallelEngine, switchAutonomy, onExit, exit]);
13967
+ }, [director, getEternalEngine, getParallelEngine, getSddRun, switchAutonomy, onExit, exit]);
12438
13968
  const commitPaste = async (full) => {
12439
13969
  const builder = builderRef.current;
12440
13970
  if (!builder || !full) return;
@@ -12949,7 +14479,7 @@ function App({
12949
14479
  openProjectPicker();
12950
14480
  return;
12951
14481
  }
12952
- const action = actionForFKeyPanel(entry, state.statuslinePicker.hiddenItems);
14482
+ const action = actionForFKeyPanel(entry, statuslineHiddenForPicker());
12953
14483
  if (action) dispatch(action);
12954
14484
  return;
12955
14485
  }
@@ -13120,6 +14650,50 @@ function App({
13120
14650
  toggleWorktreeOverlay();
13121
14651
  return;
13122
14652
  }
14653
+ if (key.ctrl && input === "b") {
14654
+ dispatch({ type: "toggleSddBoardMonitor" });
14655
+ return;
14656
+ }
14657
+ if (state.sddBoard?.monitorOpen && !key.ctrl && !key.meta) {
14658
+ if (key.rightArrow) {
14659
+ dispatch({ type: "sddBoardFocusNext" });
14660
+ return;
14661
+ }
14662
+ if (key.leftArrow) {
14663
+ dispatch({ type: "sddBoardFocusPrev" });
14664
+ return;
14665
+ }
14666
+ if (input === "c") {
14667
+ const run = getSddRun?.();
14668
+ if (run) {
14669
+ void run.cleanupWorktrees().then((n) => {
14670
+ dispatch({
14671
+ type: "addEntry",
14672
+ entry: {
14673
+ kind: n > 0 ? "info" : "warn",
14674
+ text: n > 0 ? `Cleaned ${n} SDD worktree${n === 1 ? "" : "s"}.` : "No SDD worktrees to clean (stop the run first if it is live)."
14675
+ }
14676
+ });
14677
+ });
14678
+ }
14679
+ return;
14680
+ }
14681
+ if (input === "z") {
14682
+ const run = getSddRun?.();
14683
+ if (run) {
14684
+ void run.rollback().then((r) => {
14685
+ dispatch({
14686
+ type: "addEntry",
14687
+ entry: {
14688
+ kind: r.ok ? "info" : "warn",
14689
+ text: r.ok ? r.reverted > 0 ? `Rolled back ${r.reverted} run commit${r.reverted === 1 ? "" : "s"} (revert commits added).` : "Nothing to roll back." : `Rollback failed: ${r.reason ?? "unknown error"}`
14690
+ }
14691
+ });
14692
+ });
14693
+ }
14694
+ return;
14695
+ }
14696
+ }
13123
14697
  if (key.fn === 5) {
13124
14698
  if (state.planPanelOpen) {
13125
14699
  dispatch({ type: "togglePlanPanel" });
@@ -13211,7 +14785,7 @@ function App({
13211
14785
  return;
13212
14786
  }
13213
14787
  if (key.fn === 12) {
13214
- dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
14788
+ openStatuslinePicker();
13215
14789
  return;
13216
14790
  }
13217
14791
  if (state.settingsPicker.open) {
@@ -13270,7 +14844,7 @@ function App({
13270
14844
  featureMemory: cfg.featureMemory ?? true,
13271
14845
  featureSkills: cfg.featureSkills ?? true,
13272
14846
  featureModelsRegistry: cfg.featureModelsRegistry ?? true,
13273
- tokenSavingTier: cfg.tokenSavingTier ?? "off",
14847
+ tokenSavingTier: cfg.featureTokenSaving ?? "off",
13274
14848
  allowOutsideProjectRoot: cfg.allowOutsideProjectRoot ?? true,
13275
14849
  contextAutoCompact: cfg.contextAutoCompact ?? true,
13276
14850
  contextStrategy: cfg.contextStrategy ?? "hybrid",
@@ -13547,6 +15121,10 @@ function App({
13547
15121
  version: appVersion,
13548
15122
  state: state.status,
13549
15123
  fleetRunning: fleetCounts?.running ?? 0,
15124
+ // Must match the rendered state label width — while streaming the bar
15125
+ // shows the configured thinking word, so the span shifts with it.
15126
+ // Omitting this made the model chip un-clickable mid-stream.
15127
+ thinkingWord: liveThinkingWord,
13550
15128
  model: `${liveProvider}/${liveModel}`
13551
15129
  });
13552
15130
  if (inSpan(span)) {
@@ -13564,27 +15142,24 @@ function App({
13564
15142
  dispatch({ type: "toggleTodosMonitor" });
13565
15143
  return;
13566
15144
  }
13567
- const hiddenSet = new Set(state.statuslinePicker.hiddenItems);
15145
+ const hiddenSet = new Set(statuslineHiddenForPicker());
13568
15146
  if (my === rowFor(2)) {
13569
15147
  const mxLocal = mx - SB_PADX2 - 1;
13570
15148
  if (!hiddenSet.has("todos") && mxLocal >= 0 && mxLocal < 20) {
13571
- dispatch({ type: "statuslineFieldSet", field: 11 });
13572
- dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
15149
+ openStatuslinePicker(STATUSLINE_ITEMS.indexOf("todos"));
13573
15150
  return;
13574
15151
  }
13575
15152
  if (!hiddenSet.has("plan")) {
13576
15153
  const planStart = 21;
13577
15154
  if (mxLocal >= planStart && mxLocal < planStart + 22) {
13578
- dispatch({ type: "statuslineFieldSet", field: 9 });
13579
- dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
15155
+ openStatuslinePicker(STATUSLINE_ITEMS.indexOf("plan"));
13580
15156
  return;
13581
15157
  }
13582
15158
  }
13583
15159
  if (!hiddenSet.has("tasks")) {
13584
15160
  const tasksStart = 44;
13585
15161
  if (mxLocal >= tasksStart && mxLocal < tasksStart + 26) {
13586
- dispatch({ type: "statuslineFieldSet", field: 10 });
13587
- dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
15162
+ openStatuslinePicker(STATUSLINE_ITEMS.indexOf("tasks"));
13588
15163
  return;
13589
15164
  }
13590
15165
  }
@@ -13593,8 +15168,7 @@ function App({
13593
15168
  const mxLocal = mx - SB_PADX2 - 1;
13594
15169
  const fleetStart = 0;
13595
15170
  if (mxLocal >= fleetStart && mxLocal < fleetStart + 22) {
13596
- dispatch({ type: "statuslineFieldSet", field: 12 });
13597
- dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
15171
+ openStatuslinePicker(STATUSLINE_ITEMS.indexOf("fleet"));
13598
15172
  return;
13599
15173
  }
13600
15174
  }
@@ -14037,6 +15611,7 @@ ${content}
14037
15611
  }
14038
15612
  const cmd = trimmed.slice(1).split(/\s+/, 1)[0];
14039
15613
  if (cmd === "clear") {
15614
+ clearTerminal?.();
14040
15615
  onClearHistory?.(dispatch);
14041
15616
  tokenCounter?.reset();
14042
15617
  }
@@ -14153,7 +15728,7 @@ User message:
14153
15728
  pushSubmittedHistory();
14154
15729
  clearDraft();
14155
15730
  const blocks = await builder.submit();
14156
- if (state.status !== "idle") {
15731
+ if (state.status !== "idle" && !steering) {
14157
15732
  if (autonomyLive === "auto" && nextStepsAutoSubmitTimerRef.current != null) {
14158
15733
  switchAutonomy?.("off");
14159
15734
  }
@@ -14573,6 +16148,12 @@ User message:
14573
16148
  elapsedMs: state.autoPhase.elapsedMs,
14574
16149
  nowTick
14575
16150
  }
16151
+ ) : state.sddBoard?.monitorOpen ? /* @__PURE__ */ jsx(
16152
+ SddBoardOverlay,
16153
+ {
16154
+ snapshot: state.sddBoard.snapshot,
16155
+ focusColumn: state.sddBoard.focusColumn ?? null
16156
+ }
14576
16157
  ) : state.worktreeMonitorOpen ? /* @__PURE__ */ jsx(
14577
16158
  WorktreeMonitor,
14578
16159
  {
@@ -14973,6 +16554,13 @@ async function runTui(opts) {
14973
16554
  };
14974
16555
  opts.requestExit = requestExit;
14975
16556
  let instance;
16557
+ const clearTerminal = () => {
16558
+ try {
16559
+ instance?.clear();
16560
+ stdout.write("\x1B[2J\x1B[3J\x1B[H");
16561
+ } catch {
16562
+ }
16563
+ };
14976
16564
  try {
14977
16565
  instance = render(
14978
16566
  React5.createElement(App, {
@@ -14992,6 +16580,7 @@ async function runTui(opts) {
14992
16580
  getAutonomy: opts.getAutonomy,
14993
16581
  getEternalEngine: opts.getEternalEngine,
14994
16582
  getParallelEngine: opts.getParallelEngine,
16583
+ getSddRun: opts.getSddRun,
14995
16584
  subscribeEternalIteration: opts.subscribeEternalIteration,
14996
16585
  subscribeEternalStage: opts.subscribeEternalStage,
14997
16586
  subscribeAutoPhase: opts.subscribeAutoPhase,
@@ -15007,6 +16596,7 @@ async function runTui(opts) {
15007
16596
  director: opts.director ?? null,
15008
16597
  fleetRoster: opts.fleetRoster,
15009
16598
  onClearHistory: opts.onClearHistory ? (dispatch) => opts.onClearHistory?.(dispatch) : void 0,
16599
+ clearTerminal,
15010
16600
  fleetStreamController: opts.fleetStreamController,
15011
16601
  interruptController: opts.interruptController,
15012
16602
  enhanceController: opts.enhanceController,