@wrongstack/tui 0.273.0 → 0.274.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { writeErr, resolveProjectDir, wstackGlobalRoot, createHqPublisherFromEnv, GlobalMailbox, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, expectDefined as expectDefined$1, projectSlug, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, buildChildEnv } from '@wrongstack/core';
2
2
  export { buildGoalPreamble } from '@wrongstack/core';
3
- import { Box as Box$1, useInput, useStdin, useStdout, Text as Text$1, render, useApp, measureElement, Static } from 'ink';
3
+ import { Box as Box$1, useStdout, Static, measureElement, useInput, useStdin, Text as Text$1, render, useApp } 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, useLayoutEffect, useCallback, useReducer, 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';
@@ -119,6 +119,32 @@ function useTokenCounterRefresh(tokenCounter, events) {
119
119
  // src/thinking-word.ts
120
120
  var DEFAULT_TUI_THINKING_WORD = "thinking";
121
121
  var MAX_TUI_THINKING_WORD_LENGTH = 16;
122
+ var TUI_THINKING_WORD_POOL = [
123
+ "pondering",
124
+ "cogitating",
125
+ "ruminating",
126
+ "noodling",
127
+ "brewing",
128
+ "conjuring",
129
+ "percolating",
130
+ "scheming",
131
+ "tinkering",
132
+ "vibing",
133
+ "crafting",
134
+ "wrangling",
135
+ "summoning",
136
+ "finagling",
137
+ "marinating",
138
+ "hatching",
139
+ "juggling",
140
+ "spelunking",
141
+ "contemplating",
142
+ "bamboozling",
143
+ "alchemizing",
144
+ "incubating",
145
+ "doodling",
146
+ "mulling"
147
+ ];
122
148
  function normalizeTuiThinkingWord(value) {
123
149
  if (typeof value !== "string") return DEFAULT_TUI_THINKING_WORD;
124
150
  const word = value.trim();
@@ -128,6 +154,18 @@ function normalizeTuiThinkingWord(value) {
128
154
  if (!/^[\p{L}\p{N}_-]+$/u.test(word)) return DEFAULT_TUI_THINKING_WORD;
129
155
  return word;
130
156
  }
157
+ function isRandomTuiThinkingWord(value) {
158
+ if (typeof value !== "string") return true;
159
+ const word = value.trim().toLowerCase();
160
+ return word.length === 0 || word === DEFAULT_TUI_THINKING_WORD || word === "random";
161
+ }
162
+ function pickRandomTuiThinkingWord(previous) {
163
+ const pool = TUI_THINKING_WORD_POOL;
164
+ const candidates = previous ? pool.filter((w) => w !== previous) : pool;
165
+ const list = candidates.length > 0 ? candidates : pool;
166
+ const idx = Math.floor(Math.random() * list.length);
167
+ return list[idx] ?? list[0] ?? DEFAULT_TUI_THINKING_WORD;
168
+ }
131
169
  function chipExpired(meta, now = Date.now()) {
132
170
  if (meta.expiresIn == null) return false;
133
171
  return now >= meta.shownAt + meta.expiresIn * 6e4;
@@ -140,6 +178,11 @@ function isStreamChipVisible(key, dataIsPresent, hiddenSet, visibleChips) {
140
178
  if (chipExpired(meta)) return false;
141
179
  return true;
142
180
  }
181
+ function hasMailboxActivity(mailbox) {
182
+ if (!mailbox) return false;
183
+ const peerClientCount = Math.max(0, mailbox.onlineClients.tui - 1) + mailbox.onlineClients.webui + mailbox.onlineClients.repl;
184
+ return mailbox.unread > 0 || mailbox.onlineAgents > 1 || peerClientCount > 0 || Boolean(mailbox.lastSubject || mailbox.lastFrom);
185
+ }
143
186
  var MODE_ICONS = {
144
187
  teach: "\u{1F9D1}\u200D\u{1F3EB}",
145
188
  brief: "\u26A1",
@@ -166,6 +209,68 @@ function formatSuggestionLabel(label, maxLen = 28) {
166
209
  const lastSpace = shortened.lastIndexOf(" ");
167
210
  return lastSpace > 10 ? `${shortened.slice(0, lastSpace)}\u2026` : `${shortened}\u2026`;
168
211
  }
212
+ function countdownColor(secs, warn, danger) {
213
+ if (secs > warn) return "green";
214
+ if (secs > danger) return "yellow";
215
+ return "red";
216
+ }
217
+ function joinChips(chips) {
218
+ const out = [];
219
+ chips.forEach((chip, i) => {
220
+ if (i > 0) {
221
+ out.push(
222
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }, `sep-${i}`)
223
+ );
224
+ }
225
+ out.push(/* @__PURE__ */ jsx(Fragment$1, { children: chip }, `chip-${i}`));
226
+ });
227
+ return out;
228
+ }
229
+ function truncateChip(text, max) {
230
+ return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
231
+ }
232
+ function nodeText(node) {
233
+ if (node == null || typeof node === "boolean") return "";
234
+ if (typeof node === "string") return node;
235
+ if (typeof node === "number") return String(node);
236
+ if (Array.isArray(node)) return node.map(nodeText).join("");
237
+ if (isValidElement(node)) {
238
+ return nodeText(node.props.children);
239
+ }
240
+ return "";
241
+ }
242
+ var SB_SEP_COST = 5;
243
+ function planChipFit(widths, budget, sepCost = SB_SEP_COST) {
244
+ let used = 0;
245
+ let keep = 0;
246
+ for (const w of widths) {
247
+ const cost = w + (keep > 0 ? sepCost : 0);
248
+ if (keep > 0 && used + cost > budget) break;
249
+ used += cost;
250
+ keep += 1;
251
+ }
252
+ return keep;
253
+ }
254
+ function renderChipLine(chips, budget) {
255
+ const keep = planChipFit(
256
+ chips.map((c) => nodeText(c).length),
257
+ budget
258
+ );
259
+ const nodes = joinChips(chips.slice(0, keep));
260
+ const dropped = chips.length - keep;
261
+ if (dropped > 0) {
262
+ nodes.push(
263
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }, "ovf-sep")
264
+ );
265
+ nodes.push(
266
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
267
+ "+",
268
+ dropped
269
+ ] }, "ovf")
270
+ );
271
+ }
272
+ return nodes;
273
+ }
169
274
  var COMPACT_THRESHOLD = 50;
170
275
  var COMFORTABLE_THRESHOLD = 90;
171
276
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
@@ -237,19 +342,22 @@ function StatusBar({
237
342
  }, [stdout]);
238
343
  const isCompact = termWidth < COMPACT_THRESHOLD;
239
344
  const isComfortable = termWidth >= COMFORTABLE_THRESHOLD;
240
- const hiddenSet = new Set(hiddenItems);
345
+ const hiddenSet = useMemo(() => new Set(hiddenItems), [hiddenItems]);
346
+ const showChip = (item) => !hiddenSet.has(item);
241
347
  const tokenData = useTokenCounterRefresh(tokenCounter, events);
242
348
  const usage = tokenData?.usage;
243
349
  const displayTokens = tokenDisplayTotals(usage, tokenData?.currentRequest);
244
350
  const showTokenDisplay = hasTokenDisplay(displayTokens);
245
351
  const cost = tokenData?.cost;
246
352
  const cache2 = tokenData?.cacheStats;
353
+ const elapsedHidden = hiddenSet.has("elapsed");
247
354
  const [elapsedMs, setElapsedMs] = useState(startedAt ? Date.now() - startedAt : 0);
248
355
  useEffect(() => {
249
- if (startedAt == null) return;
356
+ if (startedAt == null || elapsedHidden) return;
357
+ setElapsedMs(Date.now() - startedAt);
250
358
  const t = setInterval(() => setElapsedMs(Date.now() - startedAt), 1e3);
251
359
  return () => clearInterval(t);
252
- }, [startedAt]);
360
+ }, [startedAt, elapsedHidden]);
253
361
  const [spinnerIdx, setSpinnerIdx] = useState(0);
254
362
  useEffect(() => {
255
363
  if (state === "idle" || state === "aborting") return;
@@ -264,21 +372,22 @@ function StatusBar({
264
372
  const statePrefix = state === "idle" || state === "aborting" ? "\u25CF" : spinner;
265
373
  const thinking = state === "running" || state === "streaming";
266
374
  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;
375
+ 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
376
  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);
377
+ const showBrain = isStreamChipVisible("brain", brain, hiddenSet, visibleChips);
378
+ const showDebugStream = isStreamChipVisible("debug_stream", debugStreamStats, hiddenSet, visibleChips);
379
+ const showEnhance = isStreamChipVisible("enhance", enhanceCountdown, hiddenSet, visibleChips);
380
+ const showMailbox = showChip("mailbox") && hasMailboxActivity(mailbox);
272
381
  const hasNextStepsAutoSubmit = nextStepsAutoSubmitCountdown != null && nextStepsAutoSubmitCountdown > 0;
273
- const countdownColor = nextStepsAutoSubmitCountdown != null ? nextStepsAutoSubmitCountdown > 20 ? "green" : nextStepsAutoSubmitCountdown > 10 ? "yellow" : "red" : "green";
382
+ const nextStepsColor = nextStepsAutoSubmitCountdown != null ? countdownColor(nextStepsAutoSubmitCountdown, 20, 10) : "green";
274
383
  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;
384
+ 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
385
  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}` : ""
386
+ queueCount > 0 && showChip("queue") ? `q${queueCount}` : "",
387
+ todos && showChip("todos") && todos.inProgress + todos.pending > 0 ? `todo ${todos.inProgress}/${todos.pending}` : "",
388
+ hasTaskActivity && showChip("tasks") ? `task ${tasks.inProgress}/${tasks.pending}` : "",
389
+ fleetHasActivity && showChip("fleet") ? fleet ? `agent \u25B6${fleet.running} \xB7${fleet.idle}` : `agent ${subagentCount}` : "",
390
+ typeof processCount === "number" && processCount > 0 && showChip("processes") ? `proc ${processCount}` : ""
282
391
  ].filter(Boolean);
283
392
  if (mode === "minimum") {
284
393
  const ctxMax = context?.max;
@@ -296,22 +405,22 @@ function StatusBar({
296
405
  borderLeft: false,
297
406
  borderRight: false,
298
407
  children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
299
- version ? /* @__PURE__ */ jsxs(Text, { children: [
408
+ version && showChip("version") ? /* @__PURE__ */ jsxs(Text, { children: [
300
409
  /* @__PURE__ */ jsx(Text, { color: "blue", bold: true, children: "WS" }),
301
410
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
302
411
  " v",
303
412
  version
304
413
  ] })
305
414
  ] }) : 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: [
415
+ version && showChip("version") && (showChip("state") || showChip("model")) ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
416
+ showChip("state") && thinking ? /* @__PURE__ */ jsx(WaveText, { text: `${statePrefix} ${stateLabel}`, phase: spinnerIdx }) : showChip("state") ? /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
308
417
  statePrefix,
309
418
  " ",
310
419
  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: [
420
+ ] }) : null,
421
+ showChip("state") && showChip("model") ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
422
+ showChip("model") ? /* @__PURE__ */ jsx(Text, { color: "magenta", children: model }) : null,
423
+ ctxClampedRatio !== void 0 && ctxPctText && ctxMax !== void 0 && showChip("context") ? /* @__PURE__ */ jsxs(Fragment, { children: [
315
424
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
316
425
  /* @__PURE__ */ jsxs(Text, { color: ctxClampedRatio < 0.6 ? "green" : ctxClampedRatio < 0.75 ? "yellow" : "red", children: [
317
426
  "ctx ",
@@ -320,7 +429,7 @@ function StatusBar({
320
429
  fmtTok(ctxMax)
321
430
  ] })
322
431
  ] }) : null,
323
- showTokenDisplay ? /* @__PURE__ */ jsxs(Fragment, { children: [
432
+ showTokenDisplay && showChip("tokens") ? /* @__PURE__ */ jsxs(Fragment, { children: [
324
433
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
325
434
  /* @__PURE__ */ jsxs(Text, { children: [
326
435
  "\u2191 ",
@@ -330,7 +439,7 @@ function StatusBar({
330
439
  /* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(displayTokens.output) })
331
440
  ] })
332
441
  ] }) : null,
333
- cost && cost.total > 0 && !hiddenSet.has("cost") ? /* @__PURE__ */ jsxs(Fragment, { children: [
442
+ cost && cost.total > 0 && showChip("cost") ? /* @__PURE__ */ jsxs(Fragment, { children: [
334
443
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
335
444
  /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
336
445
  "$",
@@ -359,17 +468,17 @@ function StatusBar({
359
468
  /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: isCompact ? (
360
469
  // Ultra-compact: state · model
361
470
  /* @__PURE__ */ jsxs(Fragment, { children: [
362
- thinking ? /* @__PURE__ */ jsx(WaveText, { text: `${statePrefix}${stateLabel}`, phase: spinnerIdx }) : /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
471
+ showChip("state") && thinking ? /* @__PURE__ */ jsx(WaveText, { text: `${statePrefix}${stateLabel}`, phase: spinnerIdx }) : showChip("state") ? /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
363
472
  statePrefix,
364
473
  stateLabel
365
- ] }),
366
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
367
- /* @__PURE__ */ jsx(Text, { color: "magenta", children: model })
474
+ ] }) : null,
475
+ showChip("state") && showChip("model") ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }) : null,
476
+ showChip("model") ? /* @__PURE__ */ jsx(Text, { color: "magenta", children: model }) : null
368
477
  ] })
369
478
  ) : (
370
479
  // Full mode: version · state · model · context · tokens · cost · queue · processes · hint
371
480
  /* @__PURE__ */ jsxs(Fragment, { children: [
372
- version ? /* @__PURE__ */ jsxs(Fragment, { children: [
481
+ version && showChip("version") ? /* @__PURE__ */ jsxs(Fragment, { children: [
373
482
  /* @__PURE__ */ jsxs(Text, { children: [
374
483
  /* @__PURE__ */ jsx(Text, { color: "blue", bold: true, children: "WS" }),
375
484
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
@@ -379,14 +488,16 @@ function StatusBar({
379
488
  ] }),
380
489
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" })
381
490
  ] }) : null,
382
- thinking ? /* @__PURE__ */ jsx(WaveText, { text: `${statePrefix} ${stateLabel}`, phase: spinnerIdx }) : /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
491
+ showChip("state") && thinking ? /* @__PURE__ */ jsx(WaveText, { text: `${statePrefix} ${stateLabel}`, phase: spinnerIdx }) : showChip("state") ? /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
383
492
  statePrefix,
384
493
  " ",
385
494
  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: [
495
+ ] }) : null,
496
+ showChip("model") ? /* @__PURE__ */ jsxs(Fragment, { children: [
497
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
498
+ /* @__PURE__ */ jsx(Text, { color: "magenta", children: model })
499
+ ] }) : null,
500
+ context && showChip("context") ? /* @__PURE__ */ jsxs(Fragment, { children: [
390
501
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
391
502
  (() => {
392
503
  const ratio = context.used / context.max;
@@ -407,7 +518,7 @@ function StatusBar({
407
518
  ] });
408
519
  })()
409
520
  ] }) : null,
410
- showTokenDisplay ? /* @__PURE__ */ jsxs(Fragment, { children: [
521
+ showTokenDisplay && showChip("tokens") ? /* @__PURE__ */ jsxs(Fragment, { children: [
411
522
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
412
523
  /* @__PURE__ */ jsxs(Text, { children: [
413
524
  "\u2191 ",
@@ -417,7 +528,7 @@ function StatusBar({
417
528
  /* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(displayTokens.output) })
418
529
  ] })
419
530
  ] }) : null,
420
- cache2 && cache2.hitRatio > 0 && isComfortable ? /* @__PURE__ */ jsxs(Fragment, { children: [
531
+ cache2 && cache2.hitRatio > 0 && isComfortable && showChip("cache") ? /* @__PURE__ */ jsxs(Fragment, { children: [
421
532
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
422
533
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
423
534
  "cache ",
@@ -425,21 +536,21 @@ function StatusBar({
425
536
  "%"
426
537
  ] })
427
538
  ] }) : null,
428
- cost && cost.total > 0 && !hiddenSet.has("cost") ? /* @__PURE__ */ jsxs(Fragment, { children: [
539
+ cost && cost.total > 0 && showChip("cost") ? /* @__PURE__ */ jsxs(Fragment, { children: [
429
540
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
430
541
  /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
431
542
  "$",
432
543
  cost.total.toFixed(4)
433
544
  ] })
434
545
  ] }) : null,
435
- queueCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
546
+ queueCount > 0 && showChip("queue") ? /* @__PURE__ */ jsxs(Fragment, { children: [
436
547
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
437
548
  /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
438
549
  "\u231B queued: ",
439
550
  queueCount
440
551
  ] })
441
552
  ] }) : null,
442
- typeof processCount === "number" && processCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
553
+ typeof processCount === "number" && processCount > 0 && showChip("processes") ? /* @__PURE__ */ jsxs(Fragment, { children: [
443
554
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
444
555
  /* @__PURE__ */ jsxs(Text, { color: "red", children: [
445
556
  "\u26A1 ",
@@ -448,11 +559,11 @@ function StatusBar({
448
559
  processCount === 1 ? "" : "es"
449
560
  ] })
450
561
  ] }) : null,
451
- hint ? /* @__PURE__ */ jsxs(Fragment, { children: [
562
+ hint && showChip("hint") ? /* @__PURE__ */ jsxs(Fragment, { children: [
452
563
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
453
564
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: hint })
454
565
  ] }) : null,
455
- indexState?.indexing ? /* @__PURE__ */ jsxs(Fragment, { children: [
566
+ indexState?.indexing && showChip("index") ? /* @__PURE__ */ jsxs(Fragment, { children: [
456
567
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
457
568
  /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
458
569
  "\u2699 indexing ",
@@ -460,11 +571,11 @@ function StatusBar({
460
571
  "/",
461
572
  indexState.totalFiles
462
573
  ] })
463
- ] }) : indexState?.circuit?.state === "open" ? /* @__PURE__ */ jsxs(Fragment, { children: [
574
+ ] }) : indexState?.circuit?.state === "open" && showChip("index") ? /* @__PURE__ */ jsxs(Fragment, { children: [
464
575
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
465
576
  /* @__PURE__ */ jsx(Text, { color: "red", children: "\u2699 index paused (/reindex)" })
466
577
  ] }) : null,
467
- breakerCountdown ? (() => {
578
+ breakerCountdown && showChip("breaker") ? (() => {
468
579
  const secs = Math.ceil(breakerCountdown.remainingMs / 1e3);
469
580
  const ratio = breakerCountdown.totalMs > 0 ? breakerCountdown.remainingMs / breakerCountdown.totalMs : 0;
470
581
  const c = secs > 20 ? "green" : secs > 10 ? "yellow" : "red";
@@ -480,11 +591,10 @@ function StatusBar({
480
591
  })() : null
481
592
  ] })
482
593
  ) }),
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(
594
+ hasSecondLine ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: renderChipLine(
595
+ [
596
+ yolo && showChip("yolo") ? /* @__PURE__ */ jsx(Text, { color: "red", bold: true, children: "\u26A0 YOLO" }) : null,
597
+ autonomy && autonomy !== "off" && showChip("autonomy") ? /* @__PURE__ */ jsxs(
488
598
  Text,
489
599
  {
490
600
  color: autonomy === "eternal" ? "red" : autonomy === "auto" ? "yellow" : "cyan",
@@ -494,36 +604,21 @@ function StatusBar({
494
604
  autonomy.toUpperCase()
495
605
  ]
496
606
  }
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: [
607
+ ) : null,
608
+ eternalStage && showChip("eternal_stage") ? /* @__PURE__ */ jsx(EternalStageChip, { stage: eternalStage }) : null,
609
+ elapsedMs !== void 0 && showChip("elapsed") ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
506
610
  "\u23F1 ",
507
611
  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: [
612
+ ] }) : null,
613
+ projectName && showChip("project") ? /* @__PURE__ */ jsxs(Text, { color: "blue", children: [
513
614
  "\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: [
615
+ truncateChip(projectName, 24)
616
+ ] }) : null,
617
+ workingDir && showChip("working_dir") ? /* @__PURE__ */ jsxs(Text, { color: "blue", children: [
520
618
  "\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(
619
+ truncateChip(workingDir, 28)
620
+ ] }) : null,
621
+ goalSummary && showChip("goal") ? /* @__PURE__ */ jsxs(
527
622
  Text,
528
623
  {
529
624
  color: goalSummary.goalState === "active" ? "green" : goalSummary.goalState === "paused" ? "yellow" : goalSummary.goalState === "completed" ? "green" : "dim",
@@ -539,26 +634,17 @@ function StatusBar({
539
634
  ")"
540
635
  ]
541
636
  }
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: [
637
+ ) : null,
638
+ modeLabel && showChip("mode") ? /* @__PURE__ */ jsx(Text, { color: "cyan", children: modeIcon(modeLabel) }) : null,
639
+ hasAutoProceed && showChip("auto_proceed") ? /* @__PURE__ */ jsxs(Text, { color: autoProceedCountdown != null && autoProceedCountdown <= 5 ? "yellow" : "cyan", children: [
551
640
  "\u23F3 auto in ",
552
641
  autoProceedCountdown,
553
642
  "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: [
643
+ ] }) : null,
644
+ git && showChip("git") ? /* @__PURE__ */ jsxs(Text, { children: [
559
645
  /* @__PURE__ */ jsxs(Text, { color: "magenta", children: [
560
646
  "\u2387 ",
561
- git.branch
647
+ truncateChip(git.branch, 24)
562
648
  ] }),
563
649
  git.deleted > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
564
650
  " -",
@@ -568,52 +654,43 @@ function StatusBar({
568
654
  " ?",
569
655
  git.untracked
570
656
  ] }) : 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: [
657
+ ] }) : null,
658
+ sessionCount != null && sessionCount > 0 && showChip("sessions") ? /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
576
659
  "\u29C9 ",
577
660
  sessionCount,
578
661
  " session",
579
662
  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: [
663
+ ] }) : null,
664
+ toolCount != null && showChip("tools") ? /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
585
665
  "\u{1F527} ",
586
666
  toolCount,
587
667
  " tool",
588
668
  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
669
  ] }) : 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
670
+ tokenSavingMode && showChip("token_saving") ? /* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: "\u{1F4BE} save" }) : null
671
+ ].filter((c) => c !== null),
672
+ termWidth - 6
673
+ ) }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
674
+ hasThirdLine ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: renderChipLine(
675
+ [
676
+ todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && showChip("todos") ? /* @__PURE__ */ jsxs(Text, { children: [
677
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "todos " }),
678
+ todos.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
679
+ "\u231B",
680
+ todos.inProgress
681
+ ] }) : null,
682
+ todos.inProgress > 0 && (todos.pending > 0 || todos.completed > 0) ? " " : "",
683
+ todos.pending > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
684
+ "\u2610",
685
+ todos.pending
686
+ ] }) : null,
687
+ todos.pending > 0 && todos.completed > 0 ? " " : "",
688
+ todos.completed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
689
+ "\u2713",
690
+ todos.completed
691
+ ] }) : null
607
692
  ] }) : 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: [
693
+ plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) && showChip("plan") ? /* @__PURE__ */ jsxs(Text, { children: [
617
694
  /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u{1F4CB} " }),
618
695
  plan.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
619
696
  "\u231B",
@@ -634,11 +711,8 @@ function StatusBar({
634
711
  plan.scope,
635
712
  "]"
636
713
  ] }) : 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: [
714
+ ] }) : null,
715
+ hasTaskActivity && showChip("tasks") ? /* @__PURE__ */ jsxs(Text, { children: [
642
716
  /* @__PURE__ */ jsx(Text, { color: "magenta", children: "\u26A1 " }),
643
717
  tasks.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
644
718
  "\u231B",
@@ -669,11 +743,8 @@ function StatusBar({
669
743
  tasks.scope,
670
744
  "]"
671
745
  ] }) : 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: [
746
+ ] }) : null,
747
+ fleetHasActivity && showChip("fleet") ? fleet ? /* @__PURE__ */ jsxs(Text, { children: [
677
748
  /* @__PURE__ */ jsx(Text, { color: "blue", children: "\u{1F310} " }),
678
749
  fleet.running > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
679
750
  "\u25B6",
@@ -700,15 +771,9 @@ function StatusBar({
700
771
  subagentCount,
701
772
  " agent",
702
773
  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: [
774
+ ] }) : null,
775
+ showBrain ? /* @__PURE__ */ jsx(BrainChip, { brain }) : null,
776
+ showDebugStream ? /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
712
777
  /* @__PURE__ */ jsx(Text, { bold: true, children: "\u{1F41B} stream" }),
713
778
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
714
779
  " #",
@@ -728,31 +793,28 @@ function StatusBar({
728
793
  " \xB7 ",
729
794
  fmtDebugBytes(debugStreamStats.totalBytes)
730
795
  ] })
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: [
796
+ ] }) : null,
797
+ showEnhance ? /* @__PURE__ */ jsxs(Text, { color: countdownColor(enhanceCountdown, 15, 5), children: [
736
798
  "\u23F3 auto-send in ",
737
799
  enhanceCountdown,
738
800
  "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: [
801
+ ] }) : null,
802
+ hasNextStepsAutoSubmit && nextStepsAutoSubmitCountdown != null && showChip("next_steps") ? /* @__PURE__ */ jsxs(Fragment, { children: [
803
+ /* @__PURE__ */ jsxs(Text, { color: nextStepsColor, bold: true, children: [
804
+ "\u23F3 ",
805
+ nextStepsAutoSubmitCountdown,
806
+ "s"
807
+ ] }),
808
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
809
+ " ",
810
+ nextStepsAutoSubmitLabel ? formatSuggestionLabel(nextStepsAutoSubmitLabel) : "",
811
+ " \xB7 \u21E5 edit"
812
+ ] })
813
+ ] }) : null
814
+ ].filter((c) => c !== null),
815
+ termWidth - 6
816
+ ) }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
817
+ mailbox && showMailbox ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
756
818
  mailbox.unread > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", bold: true, children: [
757
819
  "\u2709 ",
758
820
  mailbox.unread,
@@ -786,7 +848,7 @@ function StatusBar({
786
848
  mailbox.lastSubject.length > 40 ? `${mailbox.lastSubject.slice(0, 37)}\u2026` : mailbox.lastSubject
787
849
  ] })
788
850
  ] }) : null,
789
- fleetAgents && fleetAgents.length > 0 ? fleetAgents.map((a, i) => /* @__PURE__ */ jsxs(Text, { children: [
851
+ fleetAgents && fleetAgents.length > 0 && showChip("fleet_agents") ? fleetAgents.map((a, i) => /* @__PURE__ */ jsxs(Text, { children: [
790
852
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
791
853
  " ",
792
854
  /* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
@@ -811,7 +873,7 @@ function StatusBar({
811
873
  ] })
812
874
  ] }) : null
813
875
  ] }, i)) : null
814
- ] }) : fleetAgents && fleetAgents.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => /* @__PURE__ */ jsxs(Text, { children: [
876
+ ] }) : fleetAgents && fleetAgents.length > 0 && showChip("fleet_agents") ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => /* @__PURE__ */ jsxs(Text, { children: [
815
877
  /* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
816
878
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
817
879
  /* @__PURE__ */ jsx(Text, { dimColor: !a.running, ...a.running ? { color: "yellow" } : {}, children: a.running ? "\u25B6" : "\xB7" }),
@@ -1216,7 +1278,7 @@ function FleetMonitor({
1216
1278
  const s2 = STATUS[e.status];
1217
1279
  const elapsed = e.status === "running" ? fmtElapsed(Math.max(0, nowTick - e.startedAt)) : fmtElapsed(Math.max(0, nowTick - e.lastEventAt)) + " ago";
1218
1280
  const model = fmtModelLabel(e.provider, e.model) || "\u2014";
1219
- const ltCtx = e.ctxPct !== void 0 ? `L${e.iterations} ${e.toolCalls}t ${Math.round(e.ctxPct * 100)}%` : `L${e.iterations} ${e.toolCalls}t`;
1281
+ 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`;
1220
1282
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1221
1283
  /* @__PURE__ */ jsx(Text, { color: s2.color, children: s2.icon }),
1222
1284
  /* @__PURE__ */ jsx(Text, { children: e.name.padEnd(14).slice(0, 14) }),
@@ -1406,6 +1468,10 @@ function ContextBar({
1406
1468
  tokenText
1407
1469
  ] });
1408
1470
  }
1471
+ function pctTextFromRatio(pct) {
1472
+ if (typeof pct !== "number" || !Number.isFinite(pct)) return "0%";
1473
+ return `${Math.min(100, Math.max(0, Math.round(pct * 100)))}%`;
1474
+ }
1409
1475
  function AgentRow({
1410
1476
  entry,
1411
1477
  now,
@@ -1660,14 +1726,13 @@ function AgentsMonitor({
1660
1726
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "pulse" }),
1661
1727
  /* @__PURE__ */ jsxs(Text, { color: pressure >= 0.9 ? "red" : pressure >= 0.75 ? "yellow" : "green", children: [
1662
1728
  "max ctx ",
1663
- Math.round(pressure * 100),
1664
- "%"
1729
+ pctTextFromRatio(pressure)
1665
1730
  ] }),
1666
1731
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 hot" }),
1667
1732
  hotAgent ? /* @__PURE__ */ jsxs(Text, { color: riskMeta(agentRisk(hotAgent)).color, children: [
1668
1733
  hotAgent.name,
1669
1734
  " ",
1670
- hotAgent.ctxPct !== void 0 ? `${Math.round(hotAgent.ctxPct * 100)}%` : ""
1735
+ hotAgent.ctxPct !== void 0 ? pctTextFromRatio(hotAgent.ctxPct) : ""
1671
1736
  ] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "none" }),
1672
1737
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 throughput" }),
1673
1738
  /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
@@ -2450,10 +2515,84 @@ function helpSections() {
2450
2515
  { keys: "/fleet", desc: "multi-agent fleet controls" },
2451
2516
  { keys: "/goal", desc: "set an autonomous goal" },
2452
2517
  { keys: "/autonomy", desc: "autonomy mode (eternal / off)" },
2453
- { keys: "/settings", desc: "autonomy defaults (also Ctrl+S)" },
2518
+ { keys: "/settings", desc: "settings picker (also: /settings <chord> <value> \xB7 /settings reset <chord>)" },
2519
+ { keys: "/settings-get", desc: "show setting value(s) without opening picker" },
2454
2520
  { keys: "/clear", desc: "clear the conversation" }
2455
2521
  ]
2456
2522
  },
2523
+ {
2524
+ // Surface user-facing knobs that don't have a key chord or slash
2525
+ // command of their own — the only way to change them is through the
2526
+ // settings picker. Keeping the descriptions terse so the overlay
2527
+ // fits in narrow terminals.
2528
+ title: "Settings",
2529
+ entries: [
2530
+ {
2531
+ keys: "Multi-diff summary",
2532
+ desc: "min files before per-tool aggregate footer (Ctrl+M in picker, settings \u2192 tools, 0 = off, default 5)"
2533
+ },
2534
+ {
2535
+ keys: "Index on session start",
2536
+ desc: "run incremental index at startup (Ctrl+I in picker)"
2537
+ },
2538
+ {
2539
+ keys: "Thinking word",
2540
+ desc: "status-bar working word (Ctrl+W in picker; Enter to type your own)"
2541
+ },
2542
+ {
2543
+ keys: "Refine countdown / Refine",
2544
+ desc: "prompt refinement delay / on-off (Ctrl+R / Ctrl+E in picker)"
2545
+ },
2546
+ {
2547
+ keys: "Reasoning mode",
2548
+ desc: "auto / on / off (Ctrl+N in picker)"
2549
+ },
2550
+ {
2551
+ keys: "Max concurrent",
2552
+ desc: "parallel subagent cap (Ctrl+L in picker, settings \u2192 fleet)"
2553
+ },
2554
+ {
2555
+ keys: "Statusline",
2556
+ desc: "detailed / minimum density (Ctrl+D in picker)"
2557
+ },
2558
+ {
2559
+ keys: "Default autonomy mode",
2560
+ desc: "off / suggest / auto (Alt+A in picker, settings \u2192 autonomy)"
2561
+ },
2562
+ {
2563
+ keys: "YOLO mode",
2564
+ desc: "skip all confirmation prompts (Alt+Y in picker, settings \u2192 UX)"
2565
+ },
2566
+ {
2567
+ keys: "Token-saving mode",
2568
+ desc: "off / minimal / light / medium / aggressive (Alt+T in picker)"
2569
+ },
2570
+ {
2571
+ keys: "Context mode",
2572
+ desc: "balanced / frugal / deep / archival (Alt+X in picker, settings \u2192 context)"
2573
+ },
2574
+ {
2575
+ keys: "Confirm before exit",
2576
+ desc: "confirmation on Esc interrupt & Ctrl+C exit (Alt+S in picker, settings \u2192 UX)"
2577
+ },
2578
+ {
2579
+ keys: "Completion chime",
2580
+ desc: "play a sound when agent finishes (Alt+C in picker, settings \u2192 UX)"
2581
+ },
2582
+ {
2583
+ keys: "Log level / Audit level",
2584
+ desc: "console log verbosity / audit depth (Alt+Shift+L / Alt+Shift+A in picker, settings \u2192 logging)"
2585
+ },
2586
+ {
2587
+ keys: "Stream debug logging",
2588
+ desc: "hex-dump raw SSE bytes to stderr (Alt+Shift+B in picker, settings \u2192 debug)"
2589
+ },
2590
+ {
2591
+ keys: "Config scope",
2592
+ desc: "global / project (Alt+Shift+G in picker, settings \u2192 debug)"
2593
+ }
2594
+ ]
2595
+ },
2457
2596
  {
2458
2597
  title: "Tool Colors",
2459
2598
  entries: toolColorLegend()
@@ -4990,6 +5129,61 @@ function CodeBlock({
4990
5129
  }
4991
5130
  );
4992
5131
  }
5132
+ var MULTI_DIFF_SUMMARY_THRESHOLD = 5;
5133
+ function summarizeMultiFileDiffs(items) {
5134
+ let added = 0;
5135
+ let removed = 0;
5136
+ let hiddenAdded = 0;
5137
+ let hiddenRemoved = 0;
5138
+ let truncatedFiles = 0;
5139
+ for (const item of items) {
5140
+ added += item.preview.added;
5141
+ removed += item.preview.removed;
5142
+ hiddenAdded += item.preview.hiddenAdded;
5143
+ hiddenRemoved += item.preview.hiddenRemoved;
5144
+ if (item.preview.hidden > 0) truncatedFiles += 1;
5145
+ }
5146
+ return {
5147
+ fileCount: items.length,
5148
+ added,
5149
+ removed,
5150
+ hiddenAdded,
5151
+ hiddenRemoved,
5152
+ truncatedFiles
5153
+ };
5154
+ }
5155
+ function formatMultiDiffSummary(summary, threshold = MULTI_DIFF_SUMMARY_THRESHOLD) {
5156
+ if (threshold === 0) return null;
5157
+ const effectiveThreshold = threshold < 0 ? MULTI_DIFF_SUMMARY_THRESHOLD : threshold;
5158
+ if (summary.fileCount < effectiveThreshold) return null;
5159
+ const parts = [`${summary.fileCount} files`];
5160
+ if (summary.added > 0) parts.push(`+${summary.added}`);
5161
+ if (summary.removed > 0) parts.push(`-${summary.removed}`);
5162
+ if (summary.hiddenAdded > 0 || summary.hiddenRemoved > 0) {
5163
+ const hiddenParts = [];
5164
+ if (summary.hiddenAdded > 0) hiddenParts.push(`+${summary.hiddenAdded}`);
5165
+ if (summary.hiddenRemoved > 0) hiddenParts.push(`-${summary.hiddenRemoved}`);
5166
+ parts.push(`\u2026 ${hiddenParts.join(" ")} hidden across ${summary.truncatedFiles} file${summary.truncatedFiles === 1 ? "" : "s"}`);
5167
+ }
5168
+ return parts.join(" \xB7 ");
5169
+ }
5170
+ function DiffFileBlock({
5171
+ path: path7,
5172
+ preview
5173
+ }) {
5174
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
5175
+ /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: path7 }),
5176
+ /* @__PURE__ */ jsx(
5177
+ DiffBlock,
5178
+ {
5179
+ rows: preview.rows,
5180
+ hidden: preview.hidden,
5181
+ hiddenAdded: preview.hiddenAdded,
5182
+ hiddenRemoved: preview.hiddenRemoved
5183
+ }
5184
+ )
5185
+ ] });
5186
+ }
4993
5187
  function DiffBlock({
4994
5188
  rows,
4995
5189
  hidden,
@@ -5127,20 +5321,167 @@ function extractDiffPreview(toolName, output, input) {
5127
5321
  } else if (toolName === "replace") {
5128
5322
  const parsed = tryParseJson(text);
5129
5323
  if (parsed && typeof parsed === "object") {
5130
- diff = collectReplaceDiffs(parsed);
5324
+ diff = joinReplaceDiffs(parsed);
5131
5325
  }
5132
5326
  }
5133
5327
  if (!diff?.trim() || diff.startsWith("(no-op")) return void 0;
5134
5328
  const preview = parseUnifiedDiff(diff, DIFF_MAX_LINES);
5135
5329
  return preview.rows.length > 0 ? preview : void 0;
5136
5330
  }
5137
- function collectReplaceDiffs(obj) {
5138
- const results = Array.isArray(obj["results"]) ? obj["results"] : [];
5139
- const diffs = results.map(
5140
- (result) => result && typeof result === "object" ? stringOf(result["diff"]) : void 0
5141
- ).filter((diff) => Boolean(diff?.trim()));
5331
+ function joinReplaceDiffs(obj) {
5332
+ const items = splitReplaceDiffs(obj);
5333
+ const diffs = items.map((item) => item.diff);
5142
5334
  return diffs.length > 0 ? diffs.join("\n") : void 0;
5143
5335
  }
5336
+ function splitReplaceDiffs(obj) {
5337
+ const results = Array.isArray(obj["results"]) ? obj["results"] : [];
5338
+ const items = [];
5339
+ for (const result of results) {
5340
+ if (!result || typeof result !== "object") continue;
5341
+ const record = result;
5342
+ const diff = stringOf(record["diff"]);
5343
+ if (!diff?.trim()) continue;
5344
+ const path7 = stringOf(record["path"]);
5345
+ items.push(path7 ? { path: path7, diff } : { diff });
5346
+ }
5347
+ return items;
5348
+ }
5349
+ function extractMultiFileDiffs(toolName, output, input) {
5350
+ if (!output) return void 0;
5351
+ const items = collectMultiFileDiffItems(toolName, output, input);
5352
+ if (items === void 0) return void 0;
5353
+ if (items.length === 0) return void 0;
5354
+ const previews = [];
5355
+ for (const item of items) {
5356
+ const preview = parseUnifiedDiff(item.diff, DIFF_MAX_LINES);
5357
+ if (preview.rows.length === 0) continue;
5358
+ previews.push({ path: item.path ?? "unknown file", preview });
5359
+ }
5360
+ return previews.length > 0 ? previews : void 0;
5361
+ }
5362
+ function collectMultiFileDiffItems(toolName, output, _input) {
5363
+ const trimmed = output.trim();
5364
+ if (!trimmed) return void 0;
5365
+ if (toolName === "replace") {
5366
+ const parsed = tryParseJson(trimmed);
5367
+ if (!parsed || typeof parsed !== "object") return void 0;
5368
+ const items = splitReplaceDiffs(parsed);
5369
+ if (items.length === 0) return items;
5370
+ const allMissing = items.every((item) => !item.path);
5371
+ const fallback = allMissing && _input && typeof _input === "object" && typeof _input["path"] === "string" ? stringOf(_input["path"]) : void 0;
5372
+ if (fallback) {
5373
+ return items.map((item) => ({ path: item.path ?? fallback, diff: item.diff }));
5374
+ }
5375
+ return items;
5376
+ }
5377
+ if (toolName === "diff") {
5378
+ const parsed = tryParseJson(trimmed);
5379
+ if (parsed && typeof parsed === "object") {
5380
+ const obj = parsed;
5381
+ const files = Array.isArray(obj["files"]) ? obj["files"].map(stringOf).filter((p) => Boolean(p)) : [];
5382
+ const diff = stringOf(obj["diff"]) ?? stringOf(obj["stdout"]);
5383
+ if (!diff?.trim()) return void 0;
5384
+ const blocks = splitGitStyleDiff(diff);
5385
+ return blocks.map((block, idx) => ({
5386
+ path: files[idx] ?? block.path,
5387
+ diff: block.diff
5388
+ }));
5389
+ }
5390
+ if (trimmed.includes("@@")) return [{ diff: trimmed }];
5391
+ return void 0;
5392
+ }
5393
+ if (toolName === "patch") {
5394
+ const parsed = tryParseJson(trimmed);
5395
+ let diffText;
5396
+ let explicitFiles = [];
5397
+ if (parsed && typeof parsed === "object") {
5398
+ const obj = parsed;
5399
+ diffText = stringOf(obj["diff"]) ?? stringOf(obj["stdout"]);
5400
+ if (Array.isArray(obj["files"])) {
5401
+ explicitFiles = obj["files"].map(stringOf).filter((p) => Boolean(p));
5402
+ }
5403
+ } else if (trimmed.includes("@@") || trimmed.startsWith("---")) {
5404
+ diffText = trimmed;
5405
+ }
5406
+ if (!diffText?.trim()) return void 0;
5407
+ const blocks = splitGitStyleDiff(diffText);
5408
+ if (blocks.length === 0) {
5409
+ const path7 = explicitFiles[0] ?? extractPatchHeaderPath(diffText);
5410
+ return [{ path: path7, diff: diffText }];
5411
+ }
5412
+ return blocks.map((block, idx) => ({
5413
+ path: explicitFiles[idx] ?? block.path,
5414
+ diff: block.diff
5415
+ }));
5416
+ }
5417
+ return void 0;
5418
+ }
5419
+ function splitGitStyleDiff(diff) {
5420
+ const lines = diff.split("\n");
5421
+ const blocks = [];
5422
+ let current = null;
5423
+ const flush = () => {
5424
+ if (!current) return;
5425
+ const text = current.body.join("\n").trim();
5426
+ if (text) blocks.push({ path: current.path, diff: text });
5427
+ current = null;
5428
+ };
5429
+ for (const line of lines) {
5430
+ if (line.startsWith("diff --git ")) {
5431
+ flush();
5432
+ current = { path: parseDiffGitPath(line), body: [line], hasGitHeader: true };
5433
+ continue;
5434
+ }
5435
+ if (current) {
5436
+ current.body.push(line);
5437
+ if (!current.hasGitHeader && line.startsWith("--- a/") && current.body.length > 2) {
5438
+ const carriedBody = current.body.slice(0, -1);
5439
+ const carriedPath = current.path;
5440
+ const text = carriedBody.join("\n").trim();
5441
+ if (text) blocks.push({ path: carriedPath, diff: text });
5442
+ current = {
5443
+ path: line.slice("--- a/".length).trim(),
5444
+ body: [line],
5445
+ hasGitHeader: false
5446
+ };
5447
+ }
5448
+ } else if (line.startsWith("--- a/")) {
5449
+ current = { path: line.slice("--- a/".length).trim(), body: [line], hasGitHeader: false };
5450
+ } else if (line.startsWith("+++ b/")) {
5451
+ current = { body: [line], hasGitHeader: false };
5452
+ }
5453
+ }
5454
+ flush();
5455
+ if (blocks.length === 1 && !blocks[0].path) {
5456
+ const path7 = extractPatchHeaderPath(blocks[0].diff);
5457
+ if (path7) blocks[0] = { path: path7, diff: blocks[0].diff };
5458
+ }
5459
+ return blocks;
5460
+ }
5461
+ function parseDiffGitPath(line) {
5462
+ const rest = line.slice("diff --git ".length).trim();
5463
+ if (!rest) return void 0;
5464
+ const sep2 = rest.lastIndexOf(" b/");
5465
+ if (sep2 > 0 && sep2 > rest.length - sep2 - 3) {
5466
+ return rest.slice(sep2 + 3);
5467
+ }
5468
+ const spaceIdx = rest.lastIndexOf(" ");
5469
+ if (spaceIdx > 0) {
5470
+ const rhs = rest.slice(spaceIdx + 1);
5471
+ return rhs.startsWith("b/") ? rhs.slice(2) : rhs;
5472
+ }
5473
+ return void 0;
5474
+ }
5475
+ function extractPatchHeaderPath(diffText) {
5476
+ for (const line of diffText.split("\n")) {
5477
+ if (line.startsWith("+++ ")) {
5478
+ const path7 = line.slice(4).trim();
5479
+ const cleaned = path7.replace(/^b\//, "").split(" ")[0].trim();
5480
+ return cleaned || void 0;
5481
+ }
5482
+ }
5483
+ return void 0;
5484
+ }
5144
5485
  function newFileDiffFromWriteInput(output, input) {
5145
5486
  if (!input || typeof input !== "object") return void 0;
5146
5487
  const obj = input;
@@ -5439,7 +5780,7 @@ var Entry = React5.memo(function Entry2({
5439
5780
  termWidth,
5440
5781
  setSuggestions,
5441
5782
  autonomyMode,
5442
- autoSubmitCountdown
5783
+ multiDiffSummaryThreshold
5443
5784
  }) {
5444
5785
  const nextSteps = useMemo(() => {
5445
5786
  if (entry.kind !== "assistant") return { steps: [], stripped: "" };
@@ -5522,7 +5863,7 @@ var Entry = React5.memo(function Entry2({
5522
5863
  /* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: ` ${s2.index}. ` }),
5523
5864
  /* @__PURE__ */ jsx(Text, { children: s2.text }),
5524
5865
  s2.auto ? /* @__PURE__ */ jsx(Text, { color: "cyan", dimColor: true, children: " auto" }) : null,
5525
- autonomyMode === "auto" && i === 0 ? autoSubmitCountdown != null && autoSubmitCountdown > 0 ? /* @__PURE__ */ jsx(Text, { color: autoSubmitCountdown > 20 ? "green" : autoSubmitCountdown > 10 ? "yellow" : "red", children: ` auto in ${autoSubmitCountdown}s` }) : /* @__PURE__ */ jsx(Text, { color: "cyan", children: " \u23E9" }) : null
5866
+ autonomyMode === "auto" && i === 0 ? /* @__PURE__ */ jsx(Text, { color: "cyan", children: " \u23E9" }) : null
5526
5867
  ] }) }, s2.index))
5527
5868
  ]
5528
5869
  }
@@ -5531,30 +5872,49 @@ var Entry = React5.memo(function Entry2({
5531
5872
  }
5532
5873
  case "tool": {
5533
5874
  const { glyph, color } = getToolVisual(entry.name);
5534
- const argSummary = formatToolArgs(entry.name, entry.input);
5535
- const outLines = formatToolOutput(
5875
+ const {
5876
+ argSummary,
5877
+ outLines,
5878
+ visualLines,
5879
+ diff,
5880
+ multiDiffs,
5881
+ sizeChip
5882
+ } = useMemo(() => {
5883
+ const argSummary2 = formatToolArgs(entry.name, entry.input);
5884
+ const outLines2 = formatToolOutput(
5885
+ entry.name,
5886
+ entry.output,
5887
+ entry.ok,
5888
+ entry.outputBytes,
5889
+ entry.outputLines
5890
+ );
5891
+ const visualLines2 = formatToolVisualOutput(entry.name, entry.output, entry.ok, entry.input);
5892
+ const diff2 = entry.ok ? extractDiffPreview(entry.name, entry.output, entry.input) : void 0;
5893
+ const multiDiffs2 = entry.ok && !diff2 && (entry.name === "replace" || entry.name === "diff" || entry.name === "patch") ? extractMultiFileDiffs(entry.name, entry.output, entry.input) : void 0;
5894
+ const sizeChip2 = (() => {
5895
+ if (!entry.ok) return "";
5896
+ const parts = [];
5897
+ if (entry.outputLines !== void 0 && entry.outputLines > 0) {
5898
+ parts.push(`${entry.outputLines} L`);
5899
+ }
5900
+ if (entry.outputBytes && entry.outputBytes > 0) {
5901
+ parts.push(fmtBytes(entry.outputBytes));
5902
+ }
5903
+ if (entry.outputTokens && entry.outputTokens > 0) {
5904
+ parts.push(`\u2248${fmtTok2(entry.outputTokens)} tok`);
5905
+ }
5906
+ return parts.join(" \xB7 ");
5907
+ })();
5908
+ return { argSummary: argSummary2, outLines: outLines2, visualLines: visualLines2, diff: diff2, multiDiffs: multiDiffs2, sizeChip: sizeChip2 };
5909
+ }, [
5536
5910
  entry.name,
5537
5911
  entry.output,
5912
+ entry.input,
5538
5913
  entry.ok,
5539
5914
  entry.outputBytes,
5540
- entry.outputLines
5541
- );
5542
- const visualLines = formatToolVisualOutput(entry.name, entry.output, entry.ok, entry.input);
5543
- const diff = entry.ok ? extractDiffPreview(entry.name, entry.output, entry.input) : void 0;
5544
- const sizeChip = (() => {
5545
- if (!entry.ok) return "";
5546
- const parts = [];
5547
- if (entry.outputLines !== void 0 && entry.outputLines > 0) {
5548
- parts.push(`${entry.outputLines} L`);
5549
- }
5550
- if (entry.outputBytes && entry.outputBytes > 0) {
5551
- parts.push(fmtBytes(entry.outputBytes));
5552
- }
5553
- if (entry.outputTokens && entry.outputTokens > 0) {
5554
- parts.push(`\u2248${fmtTok2(entry.outputTokens)} tok`);
5555
- }
5556
- return parts.join(" \xB7 ");
5557
- })();
5915
+ entry.outputLines,
5916
+ entry.outputTokens
5917
+ ]);
5558
5918
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
5559
5919
  /* @__PURE__ */ jsxs(Text, { children: [
5560
5920
  /* @__PURE__ */ jsx(Text, { color, children: glyph }),
@@ -5567,8 +5927,8 @@ var Entry = React5.memo(function Entry2({
5567
5927
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${fmtDuration(entry.durationMs)}` }),
5568
5928
  sizeChip ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${sizeChip}` }) : null
5569
5929
  ] }),
5570
- visualLines ? /* @__PURE__ */ jsx(ToolOutputLines, { lines: visualLines, hasFollowingBlock: Boolean(diff) }) : outLines.map((line, i) => /* @__PURE__ */ jsxs(Text, { children: [
5571
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: i === outLines.length - 1 && !diff ? " \u2514\u2500 " : " \u251C\u2500 " }),
5930
+ visualLines ? /* @__PURE__ */ jsx(ToolOutputLines, { lines: visualLines, hasFollowingBlock: Boolean(diff || multiDiffs) }) : outLines.map((line, i) => /* @__PURE__ */ jsxs(Text, { children: [
5931
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: i === outLines.length - 1 && !diff && !multiDiffs ? " \u2514\u2500 " : " \u251C\u2500 " }),
5572
5932
  /* @__PURE__ */ jsx(
5573
5933
  Text,
5574
5934
  {
@@ -5578,7 +5938,16 @@ var Entry = React5.memo(function Entry2({
5578
5938
  }
5579
5939
  )
5580
5940
  ] }, i)),
5581
- diff ? /* @__PURE__ */ jsx(
5941
+ multiDiffs ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
5942
+ (() => {
5943
+ const summaryLine = formatMultiDiffSummary(
5944
+ summarizeMultiFileDiffs(multiDiffs),
5945
+ multiDiffSummaryThreshold ?? -1
5946
+ );
5947
+ return summaryLine ? /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: summaryLine }) : null;
5948
+ })(),
5949
+ multiDiffs.map((item) => /* @__PURE__ */ jsx(DiffFileBlock, { path: item.path, preview: item.preview }, item.path))
5950
+ ] }) : diff ? /* @__PURE__ */ jsx(
5582
5951
  DiffBlock,
5583
5952
  {
5584
5953
  rows: diff.rows,
@@ -5698,7 +6067,7 @@ var Entry = React5.memo(function Entry2({
5698
6067
  }
5699
6068
  }
5700
6069
  });
5701
- function History({ entries, generation, streamingText, toolStream, setSuggestions, autonomyMode, autoSubmitCountdown }) {
6070
+ var History = memo(function History2({ entries, generation, streamingText, toolStream, setSuggestions, autonomyMode, multiDiffSummaryThreshold }) {
5702
6071
  const { stdout } = useStdout();
5703
6072
  const [termSize, setTermSize] = useState({
5704
6073
  columns: stdout?.columns ?? 80,
@@ -5716,10 +6085,10 @@ function History({ entries, generation, streamingText, toolStream, setSuggestion
5716
6085
  const termWidth = termSize.columns;
5717
6086
  const tail = streamingText ? tailForDisplay(streamingText, MAX_STREAM_DISPLAY_CHARS) : "";
5718
6087
  return /* @__PURE__ */ jsxs(Fragment, { children: [
5719
- /* @__PURE__ */ jsx(Static, { items: entries, children: (entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth, setSuggestions, autonomyMode, autoSubmitCountdown }) }, entry.id) }, generation ?? 0),
6088
+ /* @__PURE__ */ jsx(Static, { items: entries, children: (entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth, setSuggestions, autonomyMode, multiDiffSummaryThreshold }) }, entry.id) }, generation ?? 0),
5720
6089
  /* @__PURE__ */ jsx(Box, { flexGrow: 1, children: tail ? /* @__PURE__ */ jsx(AssistantTail, { text: tail, termWidth }) : null })
5721
6090
  ] });
5722
- }
6091
+ });
5723
6092
  var MAX_MOUNTED = 500;
5724
6093
  function scrollbarThumb(rows, offset, total) {
5725
6094
  const scrollable = total > rows;
@@ -5757,7 +6126,7 @@ function Scrollbar({
5757
6126
  i
5758
6127
  )) });
5759
6128
  }
5760
- function ScrollableHistory({
6129
+ var ScrollableHistory = memo(function ScrollableHistory2({
5761
6130
  entries,
5762
6131
  streamingText,
5763
6132
  toolStream,
@@ -5767,8 +6136,7 @@ function ScrollableHistory({
5767
6136
  onMeasure,
5768
6137
  maxWidth,
5769
6138
  setSuggestions,
5770
- autonomyMode,
5771
- autoSubmitCountdown
6139
+ autonomyMode
5772
6140
  }) {
5773
6141
  const { stdout } = useStdout();
5774
6142
  const rawWidth = stdout?.columns ?? 80;
@@ -5807,7 +6175,7 @@ function ScrollableHistory({
5807
6175
  flexShrink: 0,
5808
6176
  children: [
5809
6177
  hiddenCount > 0 ? /* @__PURE__ */ jsx(Box, { flexShrink: 0, children: /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: ` \u2191 ${hiddenCount} earlier ${hiddenCount === 1 ? "entry" : "entries"} (scroll lives in this session; full log on disk)` }) }) : null,
5810
- shown.map((entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, flexShrink: 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth, setSuggestions, autonomyMode, autoSubmitCountdown }) }, entry.id)),
6178
+ shown.map((entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, flexShrink: 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth, setSuggestions, autonomyMode }) }, entry.id)),
5811
6179
  tail ? /* @__PURE__ */ jsx(AssistantTail, { text: tail, termWidth }) : null,
5812
6180
  toolTail && toolStream ? /* @__PURE__ */ jsx(
5813
6181
  ToolStreamBox,
@@ -5825,7 +6193,7 @@ function ScrollableHistory({
5825
6193
  ),
5826
6194
  /* @__PURE__ */ jsx(Scrollbar, { rows: vp, offset: Math.max(0, scrollOffset), total: totalLines })
5827
6195
  ] });
5828
- }
6196
+ });
5829
6197
  var MB = 1024 * 1024;
5830
6198
  function defaultHeapLogPath() {
5831
6199
  return path5.join(wstackGlobalRoot(), "logs", "heap.jsonl");
@@ -6602,12 +6970,15 @@ function TaskCard({ task }) {
6602
6970
  ] });
6603
6971
  }
6604
6972
  function SddBoardOverlay({
6605
- snapshot
6973
+ snapshot,
6974
+ focusColumn = null
6606
6975
  }) {
6607
6976
  const byShort = new Map(snapshot.tasks.map((t) => [t.shortId, t]));
6608
6977
  const p = snapshot.progress;
6609
6978
  const chains = snapshot.diagnostics?.deadlockChains ?? [];
6610
6979
  const recentFeed = (snapshot.feed ?? []).slice(0, 6);
6980
+ const focused = typeof focusColumn === "number" && focusColumn >= 0 && focusColumn < snapshot.columns.length ? focusColumn : null;
6981
+ const columns = focused === null ? snapshot.columns : [snapshot.columns[focused]];
6611
6982
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
6612
6983
  /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, marginBottom: 1, children: [
6613
6984
  /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "SDD BOARD" }),
@@ -6640,7 +7011,13 @@ function SddBoardOverlay({
6640
7011
  "\u2717",
6641
7012
  p.failed
6642
7013
  ] }) : null,
6643
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 Ctrl+B close \xB7 c clean wt \xB7 z rollback" })
7014
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 Ctrl+B close \xB7 c clean wt \xB7 z rollback" }),
7015
+ focused !== null ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
7016
+ "\u2502 column ",
7017
+ focused + 1,
7018
+ "/",
7019
+ snapshot.columns.length
7020
+ ] }) : null
6644
7021
  ] }),
6645
7022
  chains.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
6646
7023
  /* @__PURE__ */ jsx(Text, { color: "red", bold: true, children: "\u26A0 Deadlock \u2014 blocked by failed tasks:" }),
@@ -6651,7 +7028,7 @@ function SddBoardOverlay({
6651
7028
  c.blockedBy.join(", ")
6652
7029
  ] }, c.blocked))
6653
7030
  ] }) : null,
6654
- 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: snapshot.columns.map((col) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginRight: 1, children: [
7031
+ 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: [
6655
7032
  /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: col.label }),
6656
7033
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500".repeat(12) }),
6657
7034
  col.taskIds.map((sid) => byShort.get(sid)).filter((t) => Boolean(t)).map((t) => /* @__PURE__ */ jsx(TaskCard, { task: t }, t.id))
@@ -7567,9 +7944,10 @@ var STATUSLINE_MODE_DESCS = {
7567
7944
  detailed: "Full multi-line statusline (default)"
7568
7945
  };
7569
7946
  var MAX_ITERATIONS_PRESETS = [100, 200, 500, 1e3, 0];
7570
- var MAX_CONCURRENT_PRESETS = [1, 3, 5, 10, 25, 50, 0];
7947
+ var MAX_CONCURRENT_PRESETS = [1, 3, 4, 5, 10, 25, 50, 0];
7571
7948
  var AUTO_PROCEED_MAX_PRESETS = [10, 25, 50, 100, 250, 0];
7572
- var ENHANCE_DELAY_PRESETS = [3e4, 45e3, 6e4, 9e4, 12e4];
7949
+ var ENHANCE_DELAY_PRESETS = [15e3, 3e4, 45e3, 6e4, 9e4, 12e4];
7950
+ var MULTI_DIFF_SUMMARY_THRESHOLD_PRESETS = [3, 5, 8, 10, 15, 0];
7573
7951
  var ENHANCE_LANGUAGES = ["original", "english"];
7574
7952
  var TOKEN_SAVING_TIERS = ["off", "minimal", "light", "medium", "aggressive"];
7575
7953
  var TOKEN_SAVING_TIER_DESCS = {
@@ -7588,6 +7966,10 @@ function formatMaxIterations(n) {
7588
7966
  if (n === 0) return "unlimited";
7589
7967
  return String(n);
7590
7968
  }
7969
+ function formatMultiDiffSummaryThreshold(n) {
7970
+ if (n === 0) return "off";
7971
+ return String(n);
7972
+ }
7591
7973
  function formatEnhanceDelay(ms) {
7592
7974
  return `${Math.round(ms / 1e3)}s`;
7593
7975
  }
@@ -7596,60 +7978,526 @@ var MODE_DESC = {
7596
7978
  suggest: "Shows next-step suggestions after each turn",
7597
7979
  auto: "Self-driving \u2014 agent continues automatically"
7598
7980
  };
7599
- var SETTINGS_FIELD_COUNT = 35;
7981
+ var SETTINGS_FIELD_COUNT = 36;
7982
+ var THINKING_WORD_FIELD = 22;
7983
+ var SETTINGS_PICKER_JUMP_CHORDS = Object.freeze([
7984
+ // ── Ctrl chords (Tools / Reasoning / Fleet / Debug sections) ──
7985
+ // Most-tweaked rows first — these are the knobs users reach for daily.
7986
+ { mod: "ctrl", letter: "i", field: 20, label: "Index on session start" },
7987
+ { mod: "ctrl", letter: "m", field: 21, label: "Multi-diff summary" },
7988
+ { mod: "ctrl", letter: "w", field: 22, label: "Thinking word" },
7989
+ { mod: "ctrl", letter: "r", field: 17, label: "Refine preview countdown" },
7990
+ { mod: "ctrl", letter: "e", field: 18, label: "Refine" },
7991
+ { mod: "ctrl", letter: "n", field: 23, label: "Reasoning mode" },
7992
+ { mod: "ctrl", letter: "l", field: 30, label: "Max concurrent" },
7993
+ { mod: "ctrl", letter: "d", field: 34, label: "Statusline" },
7994
+ // ── Alt chords (Autonomy / UX / Features / Context sections) ──
7995
+ // The Ctrl set above is dominated by Tools + Reasoning rows; Alt picks up
7996
+ // the spread-out sections to give every region of the picker a fast path.
7997
+ { mod: "alt", letter: "a", field: 0, label: "Default autonomy mode" },
7998
+ { mod: "alt", letter: "y", field: 3, label: "YOLO mode" },
7999
+ { mod: "alt", letter: "c", field: 5, label: "Completion chime" },
8000
+ { mod: "alt", letter: "s", field: 6, label: "Confirm before exit" },
8001
+ { mod: "alt", letter: "t", field: 13, label: "Token-saving mode" },
8002
+ { mod: "alt", letter: "x", field: 29, label: "Context mode" },
8003
+ // ── Alt+Shift chords (Logging / Debug sections) ──
8004
+ // 'L' is taken by Ctrl+L (Max concurrent), so the Logging rows get the
8005
+ // composed Alt+Shift version. A standalone Alt+L would shadow the same
8006
+ // letter as Max concurrent's Ctrl chord, so the composition is the
8007
+ // disambiguator. 'A' and 'B' are both currently free as Alt+Shift
8008
+ // letters (B is unmapped at any mod), so the Debug row's "Stream debug
8009
+ // logging" takes B (de**B**ug, raw-**B**yte stream) rather than churn
8010
+ // the existing Ctrl+D → Statusline binding to make room. The Config
8011
+ // scope row uses G (**G**lobal / project) — G is free as Alt+Shift even
8012
+ // though Ctrl+G is the agents-monitor chord, because the mod+letter
8013
+ // composition makes them distinct at the keyboard-handler level.
8014
+ { mod: "alt-shift", letter: "l", field: 31, label: "Log level" },
8015
+ { mod: "alt-shift", letter: "a", field: 32, label: "Audit level" },
8016
+ { mod: "alt-shift", letter: "b", field: 33, label: "Stream debug logging" },
8017
+ { mod: "alt-shift", letter: "g", field: 35, label: "Config scope" }
8018
+ ]);
8019
+ function settingsPickerJumpField(mod, letter) {
8020
+ const lower = letter.toLowerCase();
8021
+ const chord = SETTINGS_PICKER_JUMP_CHORDS.find((c) => c.mod === mod && c.letter === lower);
8022
+ return chord?.field;
8023
+ }
8024
+ function settingsPickerSlug(label) {
8025
+ return label.toLowerCase().replace(/\s+/g, "-");
8026
+ }
8027
+ function settingsPickerJumpByName(name) {
8028
+ const query = settingsPickerSlug(name);
8029
+ if (!query) return void 0;
8030
+ const exact = SETTINGS_PICKER_JUMP_CHORDS.find(
8031
+ (c) => settingsPickerSlug(c.label) === query
8032
+ );
8033
+ if (exact) return exact.field;
8034
+ const queryTokens = query.split("-");
8035
+ for (const c of SETTINGS_PICKER_JUMP_CHORDS) {
8036
+ const labelTokens = settingsPickerSlug(c.label).split("-");
8037
+ if (queryTokens.every((t, i) => labelTokens[i] === t)) {
8038
+ return c.field;
8039
+ }
8040
+ }
8041
+ for (const c of SETTINGS_PICKER_JUMP_CHORDS) {
8042
+ const labelTokens = settingsPickerSlug(c.label).split("-");
8043
+ if (labelTokens.some((t) => t === query || t.startsWith(`${query}-`))) {
8044
+ return c.field;
8045
+ }
8046
+ }
8047
+ return void 0;
8048
+ }
8049
+ function settingsPickerJumpNames() {
8050
+ return SETTINGS_PICKER_JUMP_CHORDS.map((c) => settingsPickerSlug(c.label));
8051
+ }
8052
+ var THINKING_WORD_PRESETS = [
8053
+ "thinking",
8054
+ "random",
8055
+ "working",
8056
+ "cooking",
8057
+ "vibing",
8058
+ "pondering",
8059
+ "brewing",
8060
+ "crunching",
8061
+ "computing",
8062
+ "grinding",
8063
+ "noodling",
8064
+ "churning",
8065
+ "hacking"
8066
+ ];
7600
8067
  var CONFIG_SCOPES = ["global", "project"];
7601
- function SettingsPicker({
7602
- field,
7603
- mode,
7604
- delayMs,
7605
- titleAnimation,
7606
- yolo,
7607
- streamFleet,
7608
- chime,
7609
- confirmExit,
7610
- nextPrediction,
7611
- featureMcp,
7612
- featurePlugins,
7613
- featureMemory,
7614
- featureSkills,
7615
- featureModelsRegistry,
7616
- tokenSavingTier,
7617
- allowOutsideProjectRoot,
7618
- maxIterations,
7619
- autoProceedMaxIterations,
7620
- enhanceDelayMs,
7621
- enhanceEnabled,
7622
- enhanceLanguage,
7623
- indexOnStart,
7624
- thinkingWord,
7625
- reasoningMode,
7626
- reasoningEffort,
7627
- reasoningPreserve,
7628
- cacheTtl,
7629
- contextAutoCompact,
7630
- contextStrategy,
7631
- contextMode,
7632
- maxConcurrent,
7633
- logLevel,
7634
- auditLevel,
7635
- debugStream,
7636
- statuslineMode,
7637
- configScope,
7638
- hint
7639
- }) {
7640
- const boolVal = (v) => v ? "on" : "off";
7641
- const rows = [
7642
- // ── Autonomy ──
7643
- { section: "Autonomy" },
7644
- { label: "Default autonomy mode", value: mode, detail: MODE_DESC[mode] },
7645
- {
7646
- label: "Auto-proceed delay",
7647
- value: formatSettingsDelay(delayMs),
7648
- detail: "Wait before auto-continuing in auto mode"
7649
- },
7650
- // ── UX ──
7651
- { section: "UX" },
7652
- {
8068
+ var SETTINGS_FIELD_LABELS = [
8069
+ "Default autonomy mode",
8070
+ // 0
8071
+ "Auto-proceed delay",
8072
+ // 1
8073
+ "Terminal title animation",
8074
+ // 2
8075
+ "YOLO mode",
8076
+ // 3
8077
+ "Stream fleet",
8078
+ // 4
8079
+ "Completion chime",
8080
+ // 5
8081
+ "Confirm before exit",
8082
+ // 6
8083
+ "Next prediction",
8084
+ // 7
8085
+ "MCP features",
8086
+ // 8
8087
+ "Plugin features",
8088
+ // 9
8089
+ "Memory features",
8090
+ // 10
8091
+ "Skills features",
8092
+ // 11
8093
+ "Models registry",
8094
+ // 12
8095
+ "Token-saving mode",
8096
+ // 13
8097
+ "Allow outside project root",
8098
+ // 14
8099
+ "Max iterations",
8100
+ // 15
8101
+ "Auto-proceed max iterations",
8102
+ // 16
8103
+ "Refine preview countdown",
8104
+ // 17
8105
+ "Refine",
8106
+ // 18
8107
+ "Refine language",
8108
+ // 19
8109
+ "Index on session start",
8110
+ // 20
8111
+ "Multi-diff summary",
8112
+ // 21
8113
+ "Thinking word",
8114
+ // 22
8115
+ "Reasoning mode",
8116
+ // 23
8117
+ "Reasoning effort",
8118
+ // 24
8119
+ "Reasoning preserve",
8120
+ // 25
8121
+ "Cache TTL",
8122
+ // 26
8123
+ "Context auto-compact",
8124
+ // 27
8125
+ "Compactor strategy",
8126
+ // 28
8127
+ "Context mode",
8128
+ // 29
8129
+ "Max concurrent",
8130
+ // 30
8131
+ "Log level",
8132
+ // 31
8133
+ "Audit level",
8134
+ // 32
8135
+ "Stream debug logging",
8136
+ // 33
8137
+ "Statusline",
8138
+ // 34
8139
+ "Config scope"
8140
+ // 35
8141
+ ];
8142
+ function resolveSettingsFieldValue(field, input) {
8143
+ const raw = input.trim().toLowerCase();
8144
+ const label = SETTINGS_FIELD_LABELS[field] ?? `Field ${field}`;
8145
+ const BOOL_FIELDS = /* @__PURE__ */ new Map([
8146
+ [2, "titleAnimation"],
8147
+ [3, "yolo"],
8148
+ [4, "streamFleet"],
8149
+ [5, "chime"],
8150
+ [6, "confirmExit"],
8151
+ [7, "nextPrediction"],
8152
+ [8, "featureMcp"],
8153
+ [9, "featurePlugins"],
8154
+ [10, "featureMemory"],
8155
+ [11, "featureSkills"],
8156
+ [12, "featureModelsRegistry"],
8157
+ [14, "allowOutsideProjectRoot"],
8158
+ [18, "enhanceEnabled"],
8159
+ [20, "indexOnStart"],
8160
+ [25, "reasoningPreserve"],
8161
+ [27, "contextAutoCompact"],
8162
+ [33, "debugStream"]
8163
+ ]);
8164
+ const boolKey = BOOL_FIELDS.get(field);
8165
+ if (boolKey) {
8166
+ if (["on", "true", "yes", "1"].includes(raw)) {
8167
+ return { ok: true, patch: { [boolKey]: true }, label, displayValue: "on" };
8168
+ }
8169
+ if (["off", "false", "no", "0"].includes(raw)) {
8170
+ return { ok: true, patch: { [boolKey]: false }, label, displayValue: "off" };
8171
+ }
8172
+ return { ok: false, error: `Invalid value "${input}" for ${label}. Use on or off.` };
8173
+ }
8174
+ const ENUM_FIELDS = [
8175
+ [0, "mode", SETTINGS_MODES],
8176
+ [13, "tokenSavingTier", TOKEN_SAVING_TIERS],
8177
+ [19, "enhanceLanguage", ENHANCE_LANGUAGES],
8178
+ [23, "reasoningMode", REASONING_MODES],
8179
+ [24, "reasoningEffort", REASONING_EFFORTS],
8180
+ [26, "cacheTtl", CACHE_TTLS],
8181
+ [28, "contextStrategy", COMPACTOR_STRATEGIES],
8182
+ [29, "contextMode", CONTEXT_MODES],
8183
+ [31, "logLevel", LOG_LEVELS],
8184
+ [32, "auditLevel", AUDIT_LEVELS],
8185
+ [34, "statuslineMode", STATUSLINE_MODES],
8186
+ [35, "configScope", CONFIG_SCOPES]
8187
+ ];
8188
+ for (const [f, key, values] of ENUM_FIELDS) {
8189
+ if (field !== f) continue;
8190
+ const match = values.find((v) => v.toLowerCase() === raw);
8191
+ if (match) {
8192
+ return { ok: true, patch: { [key]: match }, label, displayValue: match };
8193
+ }
8194
+ return {
8195
+ ok: false,
8196
+ error: `Invalid value "${input}" for ${label}. Valid: ${values.join(", ")}.`
8197
+ };
8198
+ }
8199
+ const presetLabel = (n, zeroLabel) => n === 0 ? zeroLabel : String(n);
8200
+ const PRESET_FIELDS = [
8201
+ [1, "delayMs", DELAY_PRESETS_MS, (n) => formatSettingsDelay(n)],
8202
+ [15, "maxIterations", MAX_ITERATIONS_PRESETS, (n) => formatMaxIterations(n)],
8203
+ [16, "autoProceedMaxIterations", AUTO_PROCEED_MAX_PRESETS, (n) => formatMaxIterations(n)],
8204
+ [17, "enhanceDelayMs", ENHANCE_DELAY_PRESETS, (n) => formatEnhanceDelay(n)],
8205
+ [21, "multiDiffSummaryThreshold", MULTI_DIFF_SUMMARY_THRESHOLD_PRESETS, (n) => formatMultiDiffSummaryThreshold(n)],
8206
+ [30, "maxConcurrent", MAX_CONCURRENT_PRESETS, (n) => presetLabel(n, "runtime default")]
8207
+ ];
8208
+ for (const [f, key, presets, fmt2] of PRESET_FIELDS) {
8209
+ if (field !== f) continue;
8210
+ const asNum = Number.parseInt(raw, 10);
8211
+ if (!Number.isNaN(asNum) && presets.includes(asNum)) {
8212
+ return { ok: true, patch: { [key]: asNum }, label, displayValue: fmt2(asNum) };
8213
+ }
8214
+ const byName = presets.find((p) => fmt2(p).toLowerCase() === raw);
8215
+ if (byName !== void 0) {
8216
+ return { ok: true, patch: { [key]: byName }, label, displayValue: fmt2(byName) };
8217
+ }
8218
+ const options = presets.map((p) => fmt2(p)).join(", ");
8219
+ return {
8220
+ ok: false,
8221
+ error: `Invalid value "${input}" for ${label}. Available: ${options}.`
8222
+ };
8223
+ }
8224
+ if (field === 22) {
8225
+ const word = input.trim();
8226
+ if (word.length === 0 || word.length > MAX_TUI_THINKING_WORD_LENGTH) {
8227
+ return {
8228
+ ok: false,
8229
+ error: `"${input}" is not a valid thinking word. Use a single short word (1\u2013${MAX_TUI_THINKING_WORD_LENGTH} chars, letters/numbers only).`
8230
+ };
8231
+ }
8232
+ if (!/^[\p{L}\p{N}_-]+$/u.test(word)) {
8233
+ return {
8234
+ ok: false,
8235
+ error: `"${input}" is not a valid thinking word. Use a single short word (1\u2013${MAX_TUI_THINKING_WORD_LENGTH} chars, letters/numbers only).`
8236
+ };
8237
+ }
8238
+ return { ok: true, patch: { thinkingWord: word }, label, displayValue: word };
8239
+ }
8240
+ return { ok: false, error: `Unknown settings field ${field}.` };
8241
+ }
8242
+ function getSettingsFieldValue(values, field) {
8243
+ const label = SETTINGS_FIELD_LABELS[field] ?? `Field ${field}`;
8244
+ const BOOL_KEYS = [
8245
+ [2, "titleAnimation"],
8246
+ [3, "yolo"],
8247
+ [4, "streamFleet"],
8248
+ [5, "chime"],
8249
+ [6, "confirmExit"],
8250
+ [7, "nextPrediction"],
8251
+ [8, "featureMcp"],
8252
+ [9, "featurePlugins"],
8253
+ [10, "featureMemory"],
8254
+ [11, "featureSkills"],
8255
+ [12, "featureModelsRegistry"],
8256
+ [14, "allowOutsideProjectRoot"],
8257
+ [18, "enhanceEnabled"],
8258
+ [20, "indexOnStart"],
8259
+ [25, "reasoningPreserve"],
8260
+ [27, "contextAutoCompact"],
8261
+ [33, "debugStream"]
8262
+ ];
8263
+ for (const [f, key] of BOOL_KEYS) {
8264
+ if (field !== f) continue;
8265
+ return { ok: true, label, displayValue: values[key] ? "on" : "off" };
8266
+ }
8267
+ const ENUM_KEYS = [
8268
+ [0, "mode"],
8269
+ [13, "tokenSavingTier"],
8270
+ [19, "enhanceLanguage"],
8271
+ [23, "reasoningMode"],
8272
+ [24, "reasoningEffort"],
8273
+ [26, "cacheTtl"],
8274
+ [28, "contextStrategy"],
8275
+ [29, "contextMode"],
8276
+ [31, "logLevel"],
8277
+ [32, "auditLevel"],
8278
+ [34, "statuslineMode"],
8279
+ [35, "configScope"]
8280
+ ];
8281
+ for (const [f, key] of ENUM_KEYS) {
8282
+ if (field !== f) continue;
8283
+ return { ok: true, label, displayValue: String(values[key]) };
8284
+ }
8285
+ const presetLabel = (n, zeroLabel) => n === 0 ? zeroLabel : String(n);
8286
+ const PRESET_KEYS = [
8287
+ [1, "delayMs", formatSettingsDelay],
8288
+ [15, "maxIterations", formatMaxIterations],
8289
+ [16, "autoProceedMaxIterations", formatMaxIterations],
8290
+ [17, "enhanceDelayMs", formatEnhanceDelay],
8291
+ [21, "multiDiffSummaryThreshold", formatMultiDiffSummaryThreshold],
8292
+ [30, "maxConcurrent", (n) => presetLabel(n, "runtime default")]
8293
+ ];
8294
+ for (const [f, key, fmt2] of PRESET_KEYS) {
8295
+ if (field !== f) continue;
8296
+ return { ok: true, label, displayValue: fmt2(values[key]) };
8297
+ }
8298
+ if (field === 22) {
8299
+ return { ok: true, label, displayValue: values.thinkingWord };
8300
+ }
8301
+ return { ok: false, error: `Unknown settings field ${field}.` };
8302
+ }
8303
+ var SETTINGS_SECTIONS = [
8304
+ {
8305
+ name: "Autonomy",
8306
+ fields: [0, 1]
8307
+ },
8308
+ {
8309
+ name: "UX",
8310
+ fields: [2, 3, 4, 5, 6, 7]
8311
+ },
8312
+ {
8313
+ name: "Features",
8314
+ fields: [8, 9, 10, 11, 12, 13, 14]
8315
+ },
8316
+ {
8317
+ name: "Tools",
8318
+ fields: [15, 16, 17, 18, 19, 20, 21, 22]
8319
+ },
8320
+ {
8321
+ name: "Reasoning",
8322
+ fields: [23, 24, 25, 26]
8323
+ },
8324
+ {
8325
+ name: "Context",
8326
+ fields: [27, 28, 29]
8327
+ },
8328
+ {
8329
+ name: "Fleet",
8330
+ fields: [30]
8331
+ },
8332
+ {
8333
+ name: "Logging",
8334
+ fields: [31, 32]
8335
+ },
8336
+ {
8337
+ name: "Debug",
8338
+ fields: [33, 34, 35]
8339
+ }
8340
+ ];
8341
+ function formatAllSettingsSummary(values) {
8342
+ const lines = [];
8343
+ for (const section of SETTINGS_SECTIONS) {
8344
+ lines.push(`\u2500\u2500 ${section.name} \u2500\u2500`);
8345
+ for (const field of section.fields) {
8346
+ const result = getSettingsFieldValue(values, field);
8347
+ if (result.ok) {
8348
+ lines.push(` ${result.label.padEnd(28)} ${result.displayValue}`);
8349
+ }
8350
+ }
8351
+ }
8352
+ return lines.join("\n");
8353
+ }
8354
+ var SETTINGS_DEFAULTS = Object.freeze({
8355
+ mode: "off",
8356
+ delayMs: 0,
8357
+ titleAnimation: true,
8358
+ yolo: false,
8359
+ streamFleet: true,
8360
+ chime: false,
8361
+ confirmExit: true,
8362
+ nextPrediction: false,
8363
+ featureMcp: true,
8364
+ featurePlugins: true,
8365
+ featureMemory: true,
8366
+ featureSkills: true,
8367
+ featureModelsRegistry: true,
8368
+ tokenSavingTier: "off",
8369
+ allowOutsideProjectRoot: true,
8370
+ contextAutoCompact: true,
8371
+ contextStrategy: "hybrid",
8372
+ contextMode: "balanced",
8373
+ maxConcurrent: 10,
8374
+ logLevel: "info",
8375
+ auditLevel: "standard",
8376
+ indexOnStart: true,
8377
+ multiDiffSummaryThreshold: 5,
8378
+ maxIterations: 500,
8379
+ autoProceedMaxIterations: 50,
8380
+ enhanceDelayMs: 6e4,
8381
+ enhanceEnabled: true,
8382
+ enhanceLanguage: "original",
8383
+ debugStream: false,
8384
+ statuslineMode: "detailed",
8385
+ reasoningMode: "auto",
8386
+ reasoningEffort: "high",
8387
+ reasoningPreserve: false,
8388
+ thinkingWord: "thinking",
8389
+ cacheTtl: "default",
8390
+ configScope: "global"
8391
+ });
8392
+ function resetSettingsFieldValue(field) {
8393
+ const result = getSettingsFieldValue(SETTINGS_DEFAULTS, field);
8394
+ if (!result.ok) return result;
8395
+ const patch = buildResetPatch(field);
8396
+ if (!patch) return { ok: false, error: `Unknown settings field ${field}.` };
8397
+ return { ok: true, patch, label: result.label, displayValue: result.displayValue };
8398
+ }
8399
+ function buildResetPatch(field) {
8400
+ const KEY_MAP = [
8401
+ [0, "mode"],
8402
+ [1, "delayMs"],
8403
+ [2, "titleAnimation"],
8404
+ [3, "yolo"],
8405
+ [4, "streamFleet"],
8406
+ [5, "chime"],
8407
+ [6, "confirmExit"],
8408
+ [7, "nextPrediction"],
8409
+ [8, "featureMcp"],
8410
+ [9, "featurePlugins"],
8411
+ [10, "featureMemory"],
8412
+ [11, "featureSkills"],
8413
+ [12, "featureModelsRegistry"],
8414
+ [13, "tokenSavingTier"],
8415
+ [14, "allowOutsideProjectRoot"],
8416
+ [15, "maxIterations"],
8417
+ [16, "autoProceedMaxIterations"],
8418
+ [17, "enhanceDelayMs"],
8419
+ [18, "enhanceEnabled"],
8420
+ [19, "enhanceLanguage"],
8421
+ [20, "indexOnStart"],
8422
+ [21, "multiDiffSummaryThreshold"],
8423
+ [22, "thinkingWord"],
8424
+ [23, "reasoningMode"],
8425
+ [24, "reasoningEffort"],
8426
+ [25, "reasoningPreserve"],
8427
+ [26, "cacheTtl"],
8428
+ [27, "contextAutoCompact"],
8429
+ [28, "contextStrategy"],
8430
+ [29, "contextMode"],
8431
+ [30, "maxConcurrent"],
8432
+ [31, "logLevel"],
8433
+ [32, "auditLevel"],
8434
+ [33, "debugStream"],
8435
+ [34, "statuslineMode"],
8436
+ [35, "configScope"]
8437
+ ];
8438
+ for (const [f, key] of KEY_MAP) {
8439
+ if (f === field) {
8440
+ return { [key]: SETTINGS_DEFAULTS[key] };
8441
+ }
8442
+ }
8443
+ return null;
8444
+ }
8445
+ function SettingsPicker({
8446
+ field,
8447
+ filter,
8448
+ mode,
8449
+ delayMs,
8450
+ titleAnimation,
8451
+ yolo,
8452
+ streamFleet,
8453
+ chime,
8454
+ confirmExit,
8455
+ nextPrediction,
8456
+ featureMcp,
8457
+ featurePlugins,
8458
+ featureMemory,
8459
+ featureSkills,
8460
+ featureModelsRegistry,
8461
+ tokenSavingTier,
8462
+ allowOutsideProjectRoot,
8463
+ maxIterations,
8464
+ autoProceedMaxIterations,
8465
+ enhanceDelayMs,
8466
+ enhanceEnabled,
8467
+ enhanceLanguage,
8468
+ indexOnStart,
8469
+ multiDiffSummaryThreshold,
8470
+ thinkingWord,
8471
+ thinkingWordEditing,
8472
+ thinkingWordDraft,
8473
+ reasoningMode,
8474
+ reasoningEffort,
8475
+ reasoningPreserve,
8476
+ cacheTtl,
8477
+ contextAutoCompact,
8478
+ contextStrategy,
8479
+ contextMode,
8480
+ maxConcurrent,
8481
+ logLevel,
8482
+ auditLevel,
8483
+ debugStream,
8484
+ statuslineMode,
8485
+ configScope,
8486
+ hint
8487
+ }) {
8488
+ const boolVal = (v) => v ? "on" : "off";
8489
+ const rows = [
8490
+ // ── Autonomy ──
8491
+ { section: "Autonomy" },
8492
+ { label: "Default autonomy mode", value: mode, detail: MODE_DESC[mode] },
8493
+ {
8494
+ label: "Auto-proceed delay",
8495
+ value: formatSettingsDelay(delayMs),
8496
+ detail: "Wait before auto-continuing in auto mode"
8497
+ },
8498
+ // ── UX ──
8499
+ { section: "UX" },
8500
+ {
7653
8501
  label: "Terminal title animation",
7654
8502
  value: boolVal(titleAnimation),
7655
8503
  detail: "Animated window/tab title with status"
@@ -7731,7 +8579,7 @@ function SettingsPicker({
7731
8579
  {
7732
8580
  label: "Refine preview countdown",
7733
8581
  value: formatEnhanceDelay(enhanceDelayMs),
7734
- detail: "Timeout for prompt refinement preview (30s\u2013120s)"
8582
+ detail: "Timeout for prompt refinement preview (15s\u2013120s)"
7735
8583
  },
7736
8584
  {
7737
8585
  label: "Refine",
@@ -7748,12 +8596,17 @@ function SettingsPicker({
7748
8596
  value: boolVal(indexOnStart),
7749
8597
  detail: "Run incremental index at session start"
7750
8598
  },
8599
+ {
8600
+ label: "Multi-diff summary",
8601
+ value: formatMultiDiffSummaryThreshold(multiDiffSummaryThreshold),
8602
+ detail: "Min files before aggregate header (0 = off, default 5, 10 for big diffs)"
8603
+ },
7751
8604
  // ── Reasoning ──
7752
8605
  { section: "Reasoning" },
7753
8606
  {
7754
8607
  label: "Thinking word",
7755
- value: thinkingWord,
7756
- detail: "Word shown in status bar while agent works"
8608
+ value: thinkingWordEditing ? `${thinkingWordDraft ?? ""}\u258F` : thinkingWord,
8609
+ detail: thinkingWordEditing ? "type a word \xB7 Enter \u2713 \xB7 Esc \u2717 (\u226416, letters/digits/_/-)" : "Status-bar working word \xB7 thinking/random = surprise me \xB7 \u2190/\u2192 presets \xB7 Enter to type"
7757
8610
  },
7758
8611
  {
7759
8612
  label: "Reasoning mode",
@@ -7796,8 +8649,8 @@ function SettingsPicker({
7796
8649
  { section: "Fleet" },
7797
8650
  {
7798
8651
  label: "Max concurrent",
7799
- value: maxConcurrent === 0 ? "unlimited" : String(maxConcurrent),
7800
- detail: "Max subagents (0 = unlimited)"
8652
+ value: maxConcurrent === 0 ? "default" : String(maxConcurrent),
8653
+ detail: "Max subagents (0 = default)"
7801
8654
  },
7802
8655
  // ── Logging ──
7803
8656
  { section: "Logging" },
@@ -7833,6 +8686,94 @@ function SettingsPicker({
7833
8686
  for (let i = 0; i < rows.length; i++) {
7834
8687
  if (!rows[i]?.section) fieldRowIndex.push(i);
7835
8688
  }
8689
+ const filterActive = Boolean(filter && filter.length > 1);
8690
+ const filterQuery = filter && filter.length > 1 ? filter.slice(1).toLowerCase() : "";
8691
+ const fuzzyMatch = (haystack, needle) => {
8692
+ const lower = haystack.toLowerCase();
8693
+ const indices = [];
8694
+ let ni = 0;
8695
+ for (let hi = 0; hi < lower.length && ni < needle.length; hi++) {
8696
+ if (lower[hi] === needle[ni]) {
8697
+ indices.push(hi);
8698
+ ni++;
8699
+ }
8700
+ }
8701
+ return ni === needle.length ? indices : void 0;
8702
+ };
8703
+ const scoreMatch = (contiguous, matchIndices, labelLength) => {
8704
+ const tier = contiguous ? 0 : 1e3;
8705
+ if (!matchIndices || matchIndices.length === 0) {
8706
+ return tier;
8707
+ }
8708
+ const firstPos = matchIndices[0] ?? 0;
8709
+ const span = (matchIndices.at(-1) ?? 0) - firstPos;
8710
+ const gap = span - (matchIndices.length - 1);
8711
+ const lengthPenalty = Math.max(0, labelLength - 8);
8712
+ return tier + firstPos + gap * 2 + lengthPenalty;
8713
+ };
8714
+ const fuzzyResults = filterActive ? SETTINGS_PICKER_JUMP_CHORDS.map((c) => {
8715
+ const label = c.label;
8716
+ const contiguous = label.toLowerCase().includes(filterQuery);
8717
+ if (contiguous) {
8718
+ const firstIdx = label.toLowerCase().indexOf(filterQuery);
8719
+ const indices = Array.from({ length: filterQuery.length }, (_, i) => firstIdx + i);
8720
+ return { chord: c, contiguous, fuzzyIdx: void 0, score: scoreMatch(true, indices, label.length) };
8721
+ }
8722
+ const fuzzyIdx = fuzzyMatch(label, filterQuery);
8723
+ return {
8724
+ chord: c,
8725
+ contiguous: false,
8726
+ fuzzyIdx,
8727
+ score: fuzzyIdx !== void 0 ? scoreMatch(false, fuzzyIdx, label.length) : Infinity
8728
+ };
8729
+ }) : [];
8730
+ const rankedResults = fuzzyResults.filter((r) => r.contiguous || r.fuzzyIdx !== void 0).sort((a, b) => a.score - b.score);
8731
+ const filteredFieldIndices = rankedResults.map((r) => r.chord.field);
8732
+ const highlightSegments = (label) => {
8733
+ if (!filterActive || !filterQuery) return [{ text: label, match: false }];
8734
+ const result = fuzzyResults.find((r) => r.chord.label === label);
8735
+ if (!result) return [{ text: label, match: false }];
8736
+ if (result.contiguous) {
8737
+ const lower = label.toLowerCase();
8738
+ const segments = [];
8739
+ let cursor = 0;
8740
+ while (cursor < label.length) {
8741
+ const idx = lower.indexOf(filterQuery, cursor);
8742
+ if (idx === -1) {
8743
+ segments.push({ text: label.slice(cursor), match: false });
8744
+ break;
8745
+ }
8746
+ if (idx > cursor) {
8747
+ segments.push({ text: label.slice(cursor, idx), match: false });
8748
+ }
8749
+ segments.push({ text: label.slice(idx, idx + filterQuery.length), match: true });
8750
+ cursor = idx + filterQuery.length;
8751
+ }
8752
+ return segments;
8753
+ }
8754
+ if (result.fuzzyIdx) {
8755
+ const matchSet = new Set(result.fuzzyIdx);
8756
+ const segments = [];
8757
+ let current = "";
8758
+ let currentMatch = false;
8759
+ for (let i = 0; i < label.length; i++) {
8760
+ const isMatch = matchSet.has(i);
8761
+ if (i === 0) {
8762
+ current = label[i] ?? "";
8763
+ currentMatch = isMatch;
8764
+ } else if (isMatch === currentMatch) {
8765
+ current += label[i] ?? "";
8766
+ } else {
8767
+ segments.push({ text: current, match: currentMatch });
8768
+ current = label[i] ?? "";
8769
+ currentMatch = isMatch;
8770
+ }
8771
+ }
8772
+ if (current) segments.push({ text: current, match: currentMatch });
8773
+ return segments;
8774
+ }
8775
+ return [{ text: label, match: false }];
8776
+ };
7836
8777
  const VISIBLE_FIELDS = 8;
7837
8778
  const totalFields = fieldRowIndex.length;
7838
8779
  const windowStart = totalFields <= VISIBLE_FIELDS ? 0 : Math.max(0, Math.min(field - Math.floor(VISIBLE_FIELDS / 2), totalFields - VISIBLE_FIELDS));
@@ -7861,31 +8802,81 @@ function SettingsPicker({
7861
8802
  };
7862
8803
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
7863
8804
  /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Settings \u2501\u2501" }),
7864
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 field \xB7 \u2190/\u2192 change (instant apply) \xB7 F5 to close" }),
7865
- hasAbove ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2191 ${windowStart} field${windowStart === 1 ? "" : "s"} above` }) : null,
7866
- rows.map((row, i) => {
7867
- const fieldAtRow = fieldRowIndex.indexOf(i);
7868
- if (fieldAtRow === -1) {
7869
- if (shouldShowSection(i)) {
7870
- return /* @__PURE__ */ jsxs(Text, { bold: true, color: "green", children: [
7871
- "\u2500\u2500 ",
7872
- row.section,
7873
- " \u2500\u2500"
7874
- ] }, `section-${row.section ?? i}`);
8805
+ filterActive ? /* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: `Filter: ${filter} (${filteredFieldIndices.length} match${filteredFieldIndices.length === 1 ? "" : "es"})` }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 field \xB7 \u2190/\u2192 change + autosave \xB7 `/` to search \xB7 F5 to close" }),
8806
+ hasAbove && !filterActive ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2191 ${windowStart} field${windowStart === 1 ? "" : "s"} above` }) : null,
8807
+ filterActive && filteredFieldIndices.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: "No matching settings rows." }) : null,
8808
+ filterActive ? (
8809
+ // Filter mode: render ranked rows in score order (not picker
8810
+ // order). Each row is looked up by its field index from the
8811
+ // `rows` array via `fieldRowIndex`.
8812
+ rankedResults.map((result) => {
8813
+ const fieldIdx = result.chord.field;
8814
+ const rowIdx = fieldRowIndex[fieldIdx] ?? -1;
8815
+ const row = rows[rowIdx];
8816
+ if (!row || !row.label) return null;
8817
+ const selected = fieldIdx === field;
8818
+ const labelStr = row.label;
8819
+ const segments = highlightSegments(labelStr);
8820
+ const padNeeded = Math.max(0, 26 - labelStr.length);
8821
+ return /* @__PURE__ */ jsxs(Text, { inverse: selected, ...selected ? { color: "yellow" } : {}, children: [
8822
+ selected ? "\u203A " : " ",
8823
+ segments.map((seg, j) => /* @__PURE__ */ jsx(
8824
+ Text,
8825
+ {
8826
+ bold: true,
8827
+ ...seg.match ? { color: "yellow" } : { dimColor: true },
8828
+ children: seg.text
8829
+ },
8830
+ j
8831
+ )),
8832
+ /* @__PURE__ */ jsx(Text, { bold: true, dimColor: true, children: " ".repeat(padNeeded) }),
8833
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: String(row.value ?? "").padEnd(12) }),
8834
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: row.detail ?? "" })
8835
+ ] }, `frow-${labelStr}`);
8836
+ })
8837
+ ) : (
8838
+ // Normal mode: render rows in picker order with windowing.
8839
+ rows.map((row, i) => {
8840
+ const fieldAtRow = fieldRowIndex.indexOf(i);
8841
+ if (fieldAtRow === -1) {
8842
+ if (filterActive) return null;
8843
+ if (shouldShowSection(i)) {
8844
+ return /* @__PURE__ */ jsxs(Text, { bold: true, color: "green", children: [
8845
+ "\u2500\u2500 ",
8846
+ row.section,
8847
+ " \u2500\u2500"
8848
+ ] }, `section-${row.section ?? i}`);
8849
+ }
8850
+ return null;
7875
8851
  }
7876
- return null;
7877
- }
7878
- if (fieldAtRow < windowStart || fieldAtRow >= windowEnd) return null;
7879
- const selected = fieldAtRow === field;
7880
- return /* @__PURE__ */ jsxs(Text, { inverse: selected, ...selected ? { color: "yellow" } : {}, children: [
7881
- selected ? "\u203A " : " ",
7882
- /* @__PURE__ */ jsx(Text, { bold: true, children: (row.label ?? "").padEnd(26) }),
7883
- /* @__PURE__ */ jsx(Text, { color: "cyan", children: String(row.value ?? "").padEnd(12) }),
7884
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: row.detail ?? "" })
7885
- ] }, `row-${row.label ?? fieldAtRow}`);
7886
- }),
7887
- hasBelow ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2193 ${totalFields - windowEnd} field${totalFields - windowEnd === 1 ? "" : "s"} below` }) : null,
7888
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Persisted to ~/.wrongstack/config.json" }),
8852
+ if (filterActive) {
8853
+ if (!filteredFieldIndices.includes(fieldAtRow)) return null;
8854
+ } else if (fieldAtRow < windowStart || fieldAtRow >= windowEnd) return null;
8855
+ const selected = fieldAtRow === field;
8856
+ const labelStr = row.label ?? "";
8857
+ const segments = highlightSegments(labelStr);
8858
+ const padNeeded = Math.max(0, 26 - labelStr.length);
8859
+ return /* @__PURE__ */ jsxs(Text, { inverse: selected, ...selected ? { color: "yellow" } : {}, children: [
8860
+ selected ? "\u203A " : " ",
8861
+ filterActive ? /* @__PURE__ */ jsxs(Fragment, { children: [
8862
+ segments.map((seg, j) => /* @__PURE__ */ jsx(
8863
+ Text,
8864
+ {
8865
+ bold: true,
8866
+ ...seg.match ? { color: "yellow" } : { dimColor: true },
8867
+ children: seg.text
8868
+ },
8869
+ j
8870
+ )),
8871
+ /* @__PURE__ */ jsx(Text, { bold: true, dimColor: true, children: " ".repeat(padNeeded) })
8872
+ ] }) : /* @__PURE__ */ jsx(Text, { bold: true, children: labelStr.padEnd(26) }),
8873
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: String(row.value ?? "").padEnd(12) }),
8874
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: row.detail ?? "" })
8875
+ ] }, `row-${row.label ?? fieldAtRow}`);
8876
+ })
8877
+ ),
8878
+ hasBelow && !filterActive ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2193 ${totalFields - windowEnd} field${totalFields - windowEnd === 1 ? "" : "s"} below` }) : null,
8879
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: configScope === "project" ? "Persisted to <project>/.wrongstack/config.json" : "Persisted to ~/.wrongstack/config.json" }),
7889
8880
  hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
7890
8881
  ] });
7891
8882
  }
@@ -7895,54 +8886,120 @@ function isChipExpired(meta, now = Date.now()) {
7895
8886
  return now >= meta.shownAt + meta.expiresIn * 60 * 1e3;
7896
8887
  }
7897
8888
  var ITEM_DESCRIPTIONS = {
8889
+ version: "WrongStack version chip",
8890
+ state: "Agent run state / thinking spinner",
8891
+ model: "Current provider/model id",
8892
+ tokens: "Input/output token counters",
8893
+ cache: "Prompt cache hit ratio",
8894
+ queue: "Queued prompt count",
8895
+ processes: "Tracked shell/process count",
8896
+ hint: "Transient status hint text",
8897
+ index: "Codebase indexing status",
8898
+ breaker: "Process breaker countdown",
7898
8899
  todos: "Todo items (pending/in-progress/done)",
7899
8900
  plan: "Plan board items",
7900
8901
  tasks: "Task board items",
7901
8902
  fleet: "Fleet agent status",
8903
+ fleet_agents: "Per-agent live detail row",
7902
8904
  git: "Git branch name",
7903
8905
  elapsed: "Session elapsed time",
7904
8906
  context: "Context window usage %",
7905
8907
  cost: "Token cost estimate",
7906
8908
  working_dir: "Current working directory",
8909
+ project: "Project name",
8910
+ yolo: "YOLO permission mode",
8911
+ autonomy: "Autonomy mode",
8912
+ eternal_stage: "Autonomy stage",
8913
+ goal: "Active goal summary",
8914
+ mode: "Active agent mode label",
8915
+ auto_proceed: "Auto-proceed countdown",
8916
+ sessions: "Live session count",
8917
+ tools: "Registered tool count",
8918
+ token_saving: "Token-saving mode indicator",
7907
8919
  brain: "Brain arbiter decisions",
7908
8920
  mailbox: "Mailbox unread messages",
7909
8921
  enhance: "Prompt-enhance countdown",
7910
- debug_stream: "Stream debug telemetry"
8922
+ debug_stream: "Stream debug telemetry",
8923
+ next_steps: "Next-step auto-submit countdown"
7911
8924
  };
7912
8925
  var ITEM_LINE = {
8926
+ breaker: 1,
8927
+ cache: 1,
7913
8928
  context: 1,
7914
8929
  cost: 1,
8930
+ hint: 1,
8931
+ index: 1,
8932
+ model: 1,
8933
+ processes: 1,
8934
+ queue: 1,
8935
+ state: 1,
8936
+ tokens: 1,
8937
+ version: 1,
8938
+ auto_proceed: 2,
8939
+ autonomy: 2,
7915
8940
  elapsed: 2,
7916
- working_dir: 2,
8941
+ eternal_stage: 2,
7917
8942
  git: 2,
8943
+ goal: 2,
8944
+ mode: 2,
8945
+ project: 2,
8946
+ sessions: 2,
8947
+ token_saving: 2,
8948
+ tools: 2,
8949
+ working_dir: 2,
8950
+ yolo: 2,
8951
+ brain: 3,
8952
+ debug_stream: 3,
8953
+ enhance: 3,
8954
+ fleet: 3,
8955
+ next_steps: 3,
7918
8956
  todos: 3,
7919
8957
  plan: 3,
7920
8958
  tasks: 3,
7921
- fleet: 4,
7922
- brain: 3,
7923
- mailbox: 3,
7924
- enhance: 3,
7925
- debug_stream: 3
8959
+ fleet_agents: 4,
8960
+ mailbox: 4
7926
8961
  };
7927
- Object.keys(ITEM_LINE).length;
8962
+ var STATUSLINE_FIELD_COUNT = Object.keys(ITEM_LINE).length;
7928
8963
  var STATUSLINE_ITEMS = [
7929
8964
  // Line 1
8965
+ "breaker",
8966
+ "cache",
7930
8967
  "context",
7931
8968
  "cost",
8969
+ "hint",
8970
+ "index",
8971
+ "model",
8972
+ "processes",
8973
+ "queue",
8974
+ "state",
8975
+ "tokens",
8976
+ "version",
7932
8977
  // Line 2
8978
+ "auto_proceed",
8979
+ "autonomy",
7933
8980
  "elapsed",
8981
+ "eternal_stage",
7934
8982
  "git",
8983
+ "goal",
8984
+ "mode",
8985
+ "project",
8986
+ "sessions",
8987
+ "token_saving",
8988
+ "tools",
7935
8989
  "working_dir",
8990
+ "yolo",
7936
8991
  // Line 3
7937
8992
  "brain",
7938
8993
  "debug_stream",
7939
8994
  "enhance",
7940
- "mailbox",
8995
+ "fleet",
8996
+ "next_steps",
7941
8997
  "plan",
7942
8998
  "tasks",
7943
8999
  "todos",
7944
9000
  // Line 4
7945
- "fleet"
9001
+ "fleet_agents",
9002
+ "mailbox"
7946
9003
  ];
7947
9004
  var STREAM_CHIP_KEYS = ["brain", "mailbox", "enhance", "debug_stream"];
7948
9005
  function groupByLine(items) {
@@ -7964,27 +9021,31 @@ function StatuslinePicker({
7964
9021
  const visibleChipsMap = new Map(visibleChips.map((c) => [c.key, c]));
7965
9022
  const totalFields = STATUSLINE_ITEMS.length;
7966
9023
  const byLine = groupByLine(STATUSLINE_ITEMS);
9024
+ const VISIBLE_FIELDS = 8;
9025
+ const windowStart = Math.max(0, Math.min(field - Math.floor(VISIBLE_FIELDS / 2), totalFields - VISIBLE_FIELDS));
9026
+ const windowEnd = Math.min(windowStart + VISIBLE_FIELDS, totalFields);
9027
+ const hasAbove = windowStart > 0;
9028
+ const hasBelow = windowEnd < totalFields;
7967
9029
  const rows = [];
7968
9030
  for (const [line, items] of [...byLine.entries()].sort((a, b) => a[0] - b[0])) {
9031
+ const windowedItems = items.filter((item) => {
9032
+ const idx = STATUSLINE_ITEMS.indexOf(item);
9033
+ return idx >= windowStart && idx < windowEnd;
9034
+ });
9035
+ if (windowedItems.length === 0) continue;
7969
9036
  rows.push({ section: `Line ${line}` });
7970
- for (const item of items) {
7971
- const fieldIdx = STATUSLINE_ITEMS.indexOf(item);
7972
- rows.push({ item, fieldIdx });
9037
+ for (const item of windowedItems) {
9038
+ rows.push({ item, fieldIdx: STATUSLINE_ITEMS.indexOf(item) });
7973
9039
  }
7974
9040
  }
7975
- const VISIBLE_FIELDS = 7;
7976
- const windowStart = Math.max(0, Math.min(field - Math.floor(VISIBLE_FIELDS / 2), totalFields - VISIBLE_FIELDS));
7977
- const windowEnd = Math.min(windowStart + VISIBLE_FIELDS, totalFields);
7978
- const hasAbove = windowStart > 0;
7979
- const hasBelow = windowEnd < totalFields;
7980
9041
  const boolVal = (item) => {
7981
9042
  if (hiddenSet.has(item)) return "off";
7982
9043
  if (STREAM_CHIP_KEYS.includes(item)) {
7983
9044
  const meta = visibleChipsMap.get(item);
7984
- if (!meta) return "off";
9045
+ if (!meta) return "auto";
7985
9046
  if (meta.expiresIn == null) return "on ";
7986
9047
  const remainingMs = meta.shownAt + meta.expiresIn * 6e4 - Date.now();
7987
- if (remainingMs <= 0) return "exp";
9048
+ if (remainingMs <= 0) return "auto";
7988
9049
  const remainingMin = Math.max(1, Math.ceil(remainingMs / 6e4));
7989
9050
  return `~${remainingMin}m`;
7990
9051
  }
@@ -7994,8 +9055,8 @@ function StatuslinePicker({
7994
9055
  if (hiddenSet.has(item)) return "red";
7995
9056
  if (STREAM_CHIP_KEYS.includes(item)) {
7996
9057
  const meta = visibleChipsMap.get(item);
7997
- if (!meta) return "red";
7998
- if (isChipExpired(meta)) return "red";
9058
+ if (!meta) return "cyan";
9059
+ if (isChipExpired(meta)) return "cyan";
7999
9060
  return "yellow";
8000
9061
  }
8001
9062
  return "green";
@@ -8024,7 +9085,7 @@ function StatuslinePicker({
8024
9085
  ] }, `row-${item}`);
8025
9086
  }),
8026
9087
  hasBelow ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2193 ${totalFields - windowEnd} item${totalFields - windowEnd === 1 ? "" : "s"} below` }) : null,
8027
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Changes apply instantly \xB7 persisted to ~/.wrongstack/statusline.json \xB7 auto chips expire after ~5m" }),
9088
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Changes apply instantly \xB7 persisted to ~/.wrongstack/statusline.json \xB7 auto chips show when data exists" }),
8028
9089
  hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
8029
9090
  ] });
8030
9091
  }
@@ -8075,6 +9136,10 @@ function SlashMenu({ query, matches, selected }) {
8075
9136
  " ",
8076
9137
  m.argsHint
8077
9138
  ] }) : null,
9139
+ m.matchedAlias ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
9140
+ " alias /",
9141
+ m.matchedAlias
9142
+ ] }) : null,
8078
9143
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
8079
9144
  " \u2014 ",
8080
9145
  m.description
@@ -9731,6 +10796,79 @@ function oneLine(s2, max) {
9731
10796
  return collapsed.length <= max ? collapsed : `${collapsed.slice(0, max - 1)}\u2026`;
9732
10797
  }
9733
10798
 
10799
+ // src/slash-command-search.ts
10800
+ var CATEGORY_ORDER = ["Run", "Session", "Inspect", "Agent", "Config", "App"];
10801
+ function buildSlashCommandMatches(entries, rawQuery) {
10802
+ const query = normalizeSlashQuery(rawQuery);
10803
+ const matches = [];
10804
+ for (const entry of entries) {
10805
+ const ranked = rankSlashCommand(entry, query);
10806
+ if (!ranked) continue;
10807
+ matches.push(ranked);
10808
+ }
10809
+ return matches.sort((a, b) => {
10810
+ if (a.rank !== b.rank) return a.rank - b.rank;
10811
+ const catDiff = CATEGORY_ORDER.indexOf(a.category) - CATEGORY_ORDER.indexOf(b.category);
10812
+ if (catDiff !== 0) return catDiff;
10813
+ return a.name.localeCompare(b.name);
10814
+ }).map(({ rank: _rank, ...match }) => match);
10815
+ }
10816
+ function normalizeSlashQuery(raw) {
10817
+ return raw.trim().replace(/^\/+/, "").toLowerCase();
10818
+ }
10819
+ function rankSlashCommand(entry, query) {
10820
+ const { cmd, owner } = entry;
10821
+ if (query === "" && cmd.hidden) return null;
10822
+ const name = displayName(entry);
10823
+ const lowerName = name.toLowerCase();
10824
+ const aliases = aliasCandidates(entry);
10825
+ const category = cmd.category ?? "App";
10826
+ let rank = null;
10827
+ let matchedAlias;
10828
+ if (query === "") {
10829
+ rank = 100;
10830
+ } else if (lowerName === query) {
10831
+ rank = 0;
10832
+ } else if (aliases.find((alias) => alias.toLowerCase() === query)) {
10833
+ rank = 5;
10834
+ matchedAlias = aliases.find((alias) => alias.toLowerCase() === query);
10835
+ } else if (lowerName.startsWith(query)) {
10836
+ rank = 10;
10837
+ } else {
10838
+ const prefixAlias = aliases.find((alias) => alias.toLowerCase().startsWith(query));
10839
+ if (prefixAlias) {
10840
+ rank = 20;
10841
+ matchedAlias = prefixAlias;
10842
+ }
10843
+ }
10844
+ if (rank == null) return null;
10845
+ return {
10846
+ name,
10847
+ description: cmd.description,
10848
+ argsHint: cmd.argsHint,
10849
+ isBuiltin: owner === "core",
10850
+ category,
10851
+ ...matchedAlias ? { matchedAlias } : {},
10852
+ rank
10853
+ };
10854
+ }
10855
+ function displayName({ cmd, owner, fullName }) {
10856
+ if (owner === "core") return cmd.name;
10857
+ return fullName.includes(":") ? fullName : cmd.name;
10858
+ }
10859
+ function aliasCandidates({ cmd, owner, fullName }) {
10860
+ const aliases = cmd.aliases ?? [];
10861
+ if (owner === "core") return aliases;
10862
+ const out = [...aliases];
10863
+ for (const alias of aliases) {
10864
+ out.push(`${owner}:${alias}`);
10865
+ }
10866
+ if (fullName.includes(":")) {
10867
+ return out.filter((alias) => alias.includes(":"));
10868
+ }
10869
+ return out;
10870
+ }
10871
+
9734
10872
  // src/steering-preamble.ts
9735
10873
  function buildSteeringPreamble(snapshot, newDirection) {
9736
10874
  const lines = ["[STEERING \u2014 I pressed Esc to interrupt you mid-task on purpose.", ""];
@@ -9787,6 +10925,10 @@ function closePanels(state) {
9787
10925
  coordinator: { ...state.coordinator, monitorOpen: false }
9788
10926
  };
9789
10927
  }
10928
+ function clampContextLoad(load) {
10929
+ if (!Number.isFinite(load)) return 0;
10930
+ return Math.max(0, Math.min(1, load));
10931
+ }
9790
10932
  var MAX_TOOL_STREAM_RETAINED_CHARS = 1e5;
9791
10933
  var MAX_RETAINED_INPUT_CHARS = 2048;
9792
10934
  var MAX_RETAINED_INPUT_DEPTH = 4;
@@ -10168,12 +11310,26 @@ function reducer(state, action) {
10168
11310
  return {
10169
11311
  ...state,
10170
11312
  ...closePanels(state),
10171
- resumePicker: { open: true, sessions: action.sessions, selected: 0, busy: false, hint: void 0, error: void 0 }
11313
+ resumePicker: {
11314
+ open: true,
11315
+ sessions: action.sessions,
11316
+ selected: 0,
11317
+ busy: false,
11318
+ hint: void 0,
11319
+ error: void 0
11320
+ }
10172
11321
  };
10173
11322
  case "resumePickerClose":
10174
11323
  return {
10175
11324
  ...state,
10176
- resumePicker: { open: false, sessions: [], selected: 0, busy: false, hint: void 0, error: void 0 }
11325
+ resumePicker: {
11326
+ open: false,
11327
+ sessions: [],
11328
+ selected: 0,
11329
+ busy: false,
11330
+ hint: void 0,
11331
+ error: void 0
11332
+ }
10177
11333
  };
10178
11334
  case "resumePickerMove": {
10179
11335
  const nr = state.resumePicker.sessions.length;
@@ -10192,7 +11348,12 @@ function reducer(state, action) {
10192
11348
  const maxBannerId = banners.length > 0 ? Math.max(...banners.map((b) => b.id)) : 0;
10193
11349
  const shifted = action.entries.map((e, i) => ({ ...e, id: maxBannerId + 1 + i }));
10194
11350
  const nextId = maxBannerId + 1 + shifted.length;
10195
- return { ...state, entries: [...banners, ...shifted], nextId, historyGen: state.historyGen + 1 };
11351
+ return {
11352
+ ...state,
11353
+ entries: [...banners, ...shifted],
11354
+ nextId,
11355
+ historyGen: state.historyGen + 1
11356
+ };
10196
11357
  }
10197
11358
  case "settingsOpen":
10198
11359
  return {
@@ -10200,7 +11361,21 @@ function reducer(state, action) {
10200
11361
  ...closePanels(state),
10201
11362
  settingsPicker: {
10202
11363
  open: true,
10203
- field: 0,
11364
+ // The persisted `lastSettingsField` (from the canonical Settings
11365
+ // shape) drives where the picker lands on open. The slice's
11366
+ // `field` is a working copy that mirrors it until the user
11367
+ // navigates again. `state.settingsPicker.lastSettingsField` is
11368
+ // the fallback for the (rare) case where the action omits it
11369
+ // — e.g., a tests/dispatch path that hasn't been updated yet.
11370
+ // `||` (not `??`): a payload `lastSettingsField` of 0 means
11371
+ // "no saved value" (the default in the canonical Settings),
11372
+ // so we fall through to the runtime state's tracked value.
11373
+ // This lets the in-session `settingsFieldSet`/`settingsFieldMove`
11374
+ // preserve the field across close/reopen within the same session,
11375
+ // while a non-zero persisted value (loaded from disk) takes
11376
+ // priority on a fresh open.
11377
+ field: action.lastSettingsField || state.settingsPicker.lastSettingsField || 0,
11378
+ lastSettingsField: action.lastSettingsField || state.settingsPicker.lastSettingsField || 0,
10204
11379
  mode: action.mode,
10205
11380
  delayMs: action.delayMs,
10206
11381
  titleAnimation: action.titleAnimation,
@@ -10223,6 +11398,7 @@ function reducer(state, action) {
10223
11398
  logLevel: action.logLevel,
10224
11399
  auditLevel: action.auditLevel,
10225
11400
  indexOnStart: action.indexOnStart,
11401
+ multiDiffSummaryThreshold: action.multiDiffSummaryThreshold,
10226
11402
  maxIterations: action.maxIterations,
10227
11403
  autoProceedMaxIterations: action.autoProceedMaxIterations,
10228
11404
  enhanceDelayMs: action.enhanceDelayMs,
@@ -10234,6 +11410,11 @@ function reducer(state, action) {
10234
11410
  reasoningEffort: action.reasoningEffort,
10235
11411
  reasoningPreserve: action.reasoningPreserve,
10236
11412
  thinkingWord: action.thinkingWord,
11413
+ thinkingWordEditing: false,
11414
+ thinkingWordDraft: "",
11415
+ // Filter is always cleared on open — the user starts fresh.
11416
+ // Persisted `lastSettingsField` is restored separately above.
11417
+ filter: "",
10237
11418
  cacheTtl: action.cacheTtl,
10238
11419
  configScope: action.configScope,
10239
11420
  hint: void 0
@@ -10248,13 +11429,28 @@ function reducer(state, action) {
10248
11429
  const next = (state.settingsPicker.field + action.delta + SETTINGS_FIELD_COUNT) % SETTINGS_FIELD_COUNT;
10249
11430
  return {
10250
11431
  ...state,
10251
- settingsPicker: { ...state.settingsPicker, field: next, hint: void 0 }
11432
+ settingsPicker: {
11433
+ ...state.settingsPicker,
11434
+ field: next,
11435
+ lastSettingsField: next,
11436
+ thinkingWordEditing: false,
11437
+ thinkingWordDraft: "",
11438
+ hint: void 0
11439
+ }
10252
11440
  };
10253
11441
  }
10254
11442
  case "settingsFieldSet": {
10255
11443
  const field = action.field >= 0 && action.field < SETTINGS_FIELD_COUNT ? action.field : 0;
10256
- return { ...state, settingsPicker: { ...state.settingsPicker, field, hint: void 0 } };
11444
+ return {
11445
+ ...state,
11446
+ settingsPicker: { ...state.settingsPicker, field, lastSettingsField: field, hint: void 0 }
11447
+ };
10257
11448
  }
11449
+ case "settingsFilterSet":
11450
+ return {
11451
+ ...state,
11452
+ settingsPicker: { ...state.settingsPicker, filter: action.filter }
11453
+ };
10258
11454
  case "settingsValueChange": {
10259
11455
  const sp = state.settingsPicker;
10260
11456
  const f = sp.field;
@@ -10263,142 +11459,407 @@ function reducer(state, action) {
10263
11459
  const i = SETTINGS_MODES.indexOf(sp.mode);
10264
11460
  const base = i < 0 ? 0 : i;
10265
11461
  const next = (base + action.delta + SETTINGS_MODES.length) % SETTINGS_MODES.length;
10266
- return { ...state, settingsPicker: { ...sp, mode: expectDefined$1(SETTINGS_MODES[next]), hint: void 0 } };
11462
+ return {
11463
+ ...state,
11464
+ settingsPicker: { ...sp, mode: expectDefined$1(SETTINGS_MODES[next]), hint: void 0 }
11465
+ };
10267
11466
  }
10268
11467
  if (f === 1) {
10269
11468
  const j = DELAY_PRESETS_MS.indexOf(sp.delayMs);
10270
11469
  const base = j < 0 ? 0 : j;
10271
11470
  const next = (base + action.delta + DELAY_PRESETS_MS.length) % DELAY_PRESETS_MS.length;
10272
- return { ...state, settingsPicker: { ...sp, delayMs: expectDefined$1(DELAY_PRESETS_MS[next]), hint: void 0 } };
11471
+ return {
11472
+ ...state,
11473
+ settingsPicker: {
11474
+ ...sp,
11475
+ delayMs: expectDefined$1(DELAY_PRESETS_MS[next]),
11476
+ hint: void 0
11477
+ }
11478
+ };
10273
11479
  }
10274
- if (f === 2) return { ...state, settingsPicker: { ...sp, titleAnimation: !sp.titleAnimation, hint: void 0 } };
11480
+ if (f === 2)
11481
+ return {
11482
+ ...state,
11483
+ settingsPicker: { ...sp, titleAnimation: !sp.titleAnimation, hint: void 0 }
11484
+ };
10275
11485
  if (f === 3) return { ...state, settingsPicker: { ...sp, yolo: !sp.yolo, hint: void 0 } };
10276
- if (f === 4) return { ...state, settingsPicker: { ...sp, streamFleet: !sp.streamFleet, hint: void 0 } };
10277
- if (f === 5) return { ...state, settingsPicker: { ...sp, chime: !sp.chime, hint: void 0 } };
10278
- if (f === 6) return { ...state, settingsPicker: { ...sp, confirmExit: !sp.confirmExit, hint: void 0 } };
10279
- if (f === 7) return { ...state, settingsPicker: { ...sp, nextPrediction: !sp.nextPrediction, hint: void 0 } };
10280
- if (f === 8) return { ...state, settingsPicker: { ...sp, featureMcp: !sp.featureMcp, hint: bootHint } };
10281
- if (f === 9) return { ...state, settingsPicker: { ...sp, featurePlugins: !sp.featurePlugins, hint: bootHint } };
10282
- if (f === 10) return { ...state, settingsPicker: { ...sp, featureMemory: !sp.featureMemory, hint: bootHint } };
10283
- if (f === 11) return { ...state, settingsPicker: { ...sp, featureSkills: !sp.featureSkills, hint: bootHint } };
10284
- if (f === 12) return { ...state, settingsPicker: { ...sp, featureModelsRegistry: !sp.featureModelsRegistry, hint: bootHint } };
11486
+ if (f === 4)
11487
+ return {
11488
+ ...state,
11489
+ settingsPicker: { ...sp, streamFleet: !sp.streamFleet, hint: void 0 }
11490
+ };
11491
+ if (f === 5)
11492
+ return { ...state, settingsPicker: { ...sp, chime: !sp.chime, hint: void 0 } };
11493
+ if (f === 6)
11494
+ return {
11495
+ ...state,
11496
+ settingsPicker: { ...sp, confirmExit: !sp.confirmExit, hint: void 0 }
11497
+ };
11498
+ if (f === 7)
11499
+ return {
11500
+ ...state,
11501
+ settingsPicker: { ...sp, nextPrediction: !sp.nextPrediction, hint: void 0 }
11502
+ };
11503
+ if (f === 8)
11504
+ return { ...state, settingsPicker: { ...sp, featureMcp: !sp.featureMcp, hint: bootHint } };
11505
+ if (f === 9)
11506
+ return {
11507
+ ...state,
11508
+ settingsPicker: { ...sp, featurePlugins: !sp.featurePlugins, hint: bootHint }
11509
+ };
11510
+ if (f === 10)
11511
+ return {
11512
+ ...state,
11513
+ settingsPicker: { ...sp, featureMemory: !sp.featureMemory, hint: bootHint }
11514
+ };
11515
+ if (f === 11)
11516
+ return {
11517
+ ...state,
11518
+ settingsPicker: { ...sp, featureSkills: !sp.featureSkills, hint: bootHint }
11519
+ };
11520
+ if (f === 12)
11521
+ return {
11522
+ ...state,
11523
+ settingsPicker: {
11524
+ ...sp,
11525
+ featureModelsRegistry: !sp.featureModelsRegistry,
11526
+ hint: bootHint
11527
+ }
11528
+ };
10285
11529
  if (f === 13) {
10286
- const i = TOKEN_SAVING_TIERS.indexOf(sp.tokenSavingTier);
11530
+ const i = TOKEN_SAVING_TIERS.indexOf(
11531
+ sp.tokenSavingTier
11532
+ );
10287
11533
  const base = i < 0 ? 0 : i;
10288
11534
  const next = (base + action.delta + TOKEN_SAVING_TIERS.length) % TOKEN_SAVING_TIERS.length;
10289
- return { ...state, settingsPicker: { ...sp, tokenSavingTier: TOKEN_SAVING_TIERS[next] ?? "off", hint: bootHint } };
11535
+ return {
11536
+ ...state,
11537
+ settingsPicker: {
11538
+ ...sp,
11539
+ tokenSavingTier: TOKEN_SAVING_TIERS[next] ?? "off",
11540
+ hint: bootHint
11541
+ }
11542
+ };
10290
11543
  }
10291
- if (f === 14) return { ...state, settingsPicker: { ...sp, allowOutsideProjectRoot: !sp.allowOutsideProjectRoot, hint: void 0 } };
11544
+ if (f === 14)
11545
+ return {
11546
+ ...state,
11547
+ settingsPicker: {
11548
+ ...sp,
11549
+ allowOutsideProjectRoot: !sp.allowOutsideProjectRoot,
11550
+ hint: void 0
11551
+ }
11552
+ };
10292
11553
  if (f === 15) {
10293
11554
  const j = MAX_ITERATIONS_PRESETS.indexOf(sp.maxIterations);
10294
11555
  const base = j < 0 ? 0 : j;
10295
11556
  const next = (base + action.delta + MAX_ITERATIONS_PRESETS.length) % MAX_ITERATIONS_PRESETS.length;
10296
- return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined$1(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
11557
+ return {
11558
+ ...state,
11559
+ settingsPicker: {
11560
+ ...sp,
11561
+ maxIterations: expectDefined$1(MAX_ITERATIONS_PRESETS[next]),
11562
+ hint: void 0
11563
+ }
11564
+ };
10297
11565
  }
10298
11566
  if (f === 16) {
10299
11567
  const aj = AUTO_PROCEED_MAX_PRESETS.indexOf(sp.autoProceedMaxIterations);
10300
11568
  const abase = aj < 0 ? 0 : aj;
10301
11569
  const anext = (abase + action.delta + AUTO_PROCEED_MAX_PRESETS.length) % AUTO_PROCEED_MAX_PRESETS.length;
10302
- return { ...state, settingsPicker: { ...sp, autoProceedMaxIterations: expectDefined$1(AUTO_PROCEED_MAX_PRESETS[anext]), hint: void 0 } };
11570
+ return {
11571
+ ...state,
11572
+ settingsPicker: {
11573
+ ...sp,
11574
+ autoProceedMaxIterations: expectDefined$1(AUTO_PROCEED_MAX_PRESETS[anext]),
11575
+ hint: void 0
11576
+ }
11577
+ };
10303
11578
  }
10304
11579
  if (f === 17) {
10305
11580
  const ej = ENHANCE_DELAY_PRESETS.indexOf(sp.enhanceDelayMs);
10306
11581
  const ebase = ej < 0 ? 0 : ej;
10307
11582
  const enext = (ebase + action.delta + ENHANCE_DELAY_PRESETS.length) % ENHANCE_DELAY_PRESETS.length;
10308
- return { ...state, settingsPicker: { ...sp, enhanceDelayMs: expectDefined$1(ENHANCE_DELAY_PRESETS[enext]), hint: void 0 } };
11583
+ return {
11584
+ ...state,
11585
+ settingsPicker: {
11586
+ ...sp,
11587
+ enhanceDelayMs: expectDefined$1(ENHANCE_DELAY_PRESETS[enext]),
11588
+ hint: void 0
11589
+ }
11590
+ };
10309
11591
  }
10310
- if (f === 18) return { ...state, settingsPicker: { ...sp, enhanceEnabled: !sp.enhanceEnabled, hint: void 0 } };
11592
+ if (f === 18)
11593
+ return {
11594
+ ...state,
11595
+ settingsPicker: { ...sp, enhanceEnabled: !sp.enhanceEnabled, hint: void 0 }
11596
+ };
10311
11597
  if (f === 19) {
10312
11598
  const i = ENHANCE_LANGUAGES.indexOf(sp.enhanceLanguage);
10313
11599
  const base = i < 0 ? 0 : i;
10314
11600
  const next = (base + action.delta + ENHANCE_LANGUAGES.length) % ENHANCE_LANGUAGES.length;
10315
- return { ...state, settingsPicker: { ...sp, enhanceLanguage: expectDefined$1(ENHANCE_LANGUAGES[next]), hint: void 0 } };
11601
+ return {
11602
+ ...state,
11603
+ settingsPicker: {
11604
+ ...sp,
11605
+ enhanceLanguage: expectDefined$1(ENHANCE_LANGUAGES[next]),
11606
+ hint: void 0
11607
+ }
11608
+ };
11609
+ }
11610
+ if (f === 20)
11611
+ return {
11612
+ ...state,
11613
+ settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: bootHint }
11614
+ };
11615
+ if (f === 21) {
11616
+ const j = MULTI_DIFF_SUMMARY_THRESHOLD_PRESETS.indexOf(sp.multiDiffSummaryThreshold);
11617
+ const base = j < 0 ? 0 : j;
11618
+ const next = (base + action.delta + MULTI_DIFF_SUMMARY_THRESHOLD_PRESETS.length) % MULTI_DIFF_SUMMARY_THRESHOLD_PRESETS.length;
11619
+ const multiDiffSummaryThreshold = expectDefined$1(MULTI_DIFF_SUMMARY_THRESHOLD_PRESETS[next]);
11620
+ return {
11621
+ ...state,
11622
+ settingsPicker: { ...sp, multiDiffSummaryThreshold, hint: void 0 }
11623
+ };
11624
+ }
11625
+ if (f === THINKING_WORD_FIELD) {
11626
+ const cur = sp.thinkingWord;
11627
+ const list = THINKING_WORD_PRESETS.includes(cur) ? [...THINKING_WORD_PRESETS] : [cur, ...THINKING_WORD_PRESETS];
11628
+ const i = list.indexOf(cur);
11629
+ const base = i < 0 ? 0 : i;
11630
+ const next = (base + action.delta + list.length) % list.length;
11631
+ return {
11632
+ ...state,
11633
+ settingsPicker: { ...sp, thinkingWord: expectDefined$1(list[next]), hint: void 0 }
11634
+ };
10316
11635
  }
10317
- if (f === 20) return { ...state, settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: bootHint } };
10318
- if (f === 21) return state;
10319
- if (f === 22) {
11636
+ if (f === 23) {
10320
11637
  const i = REASONING_MODES.indexOf(sp.reasoningMode);
10321
11638
  const base = i < 0 ? 0 : i;
10322
11639
  const next = (base + action.delta + REASONING_MODES.length) % REASONING_MODES.length;
10323
- return { ...state, settingsPicker: { ...sp, reasoningMode: expectDefined$1(REASONING_MODES[next]), hint: void 0 } };
11640
+ return {
11641
+ ...state,
11642
+ settingsPicker: {
11643
+ ...sp,
11644
+ reasoningMode: expectDefined$1(REASONING_MODES[next]),
11645
+ hint: void 0
11646
+ }
11647
+ };
10324
11648
  }
10325
- if (f === 23) {
10326
- const i = REASONING_EFFORTS.indexOf(sp.reasoningEffort);
11649
+ if (f === 24) {
11650
+ const i = REASONING_EFFORTS.indexOf(
11651
+ sp.reasoningEffort
11652
+ );
10327
11653
  const base = i < 0 ? REASONING_EFFORTS.indexOf("high") : i;
10328
11654
  const next = (base + action.delta + REASONING_EFFORTS.length) % REASONING_EFFORTS.length;
10329
- return { ...state, settingsPicker: { ...sp, reasoningEffort: expectDefined$1(REASONING_EFFORTS[next]), hint: void 0 } };
11655
+ return {
11656
+ ...state,
11657
+ settingsPicker: {
11658
+ ...sp,
11659
+ reasoningEffort: expectDefined$1(REASONING_EFFORTS[next]),
11660
+ hint: void 0
11661
+ }
11662
+ };
10330
11663
  }
10331
- if (f === 24) return { ...state, settingsPicker: { ...sp, reasoningPreserve: !sp.reasoningPreserve, hint: void 0 } };
10332
- if (f === 25) {
11664
+ if (f === 25)
11665
+ return {
11666
+ ...state,
11667
+ settingsPicker: { ...sp, reasoningPreserve: !sp.reasoningPreserve, hint: void 0 }
11668
+ };
11669
+ if (f === 26) {
10333
11670
  const i = CACHE_TTLS.indexOf(sp.cacheTtl);
10334
11671
  const base = i < 0 ? 0 : i;
10335
11672
  const next = (base + action.delta + CACHE_TTLS.length) % CACHE_TTLS.length;
10336
- return { ...state, settingsPicker: { ...sp, cacheTtl: expectDefined$1(CACHE_TTLS[next]), hint: void 0 } };
11673
+ return {
11674
+ ...state,
11675
+ settingsPicker: { ...sp, cacheTtl: expectDefined$1(CACHE_TTLS[next]), hint: void 0 }
11676
+ };
10337
11677
  }
10338
- if (f === 26) return { ...state, settingsPicker: { ...sp, contextAutoCompact: !sp.contextAutoCompact, hint: void 0 } };
10339
- if (f === 27) {
11678
+ if (f === 27)
11679
+ return {
11680
+ ...state,
11681
+ settingsPicker: { ...sp, contextAutoCompact: !sp.contextAutoCompact, hint: void 0 }
11682
+ };
11683
+ if (f === 28) {
10340
11684
  const i = COMPACTOR_STRATEGIES.indexOf(sp.contextStrategy);
10341
11685
  const base = i < 0 ? 0 : i;
10342
11686
  const next = (base + action.delta + COMPACTOR_STRATEGIES.length) % COMPACTOR_STRATEGIES.length;
10343
- return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined$1(COMPACTOR_STRATEGIES[next]), hint: bootHint } };
11687
+ return {
11688
+ ...state,
11689
+ settingsPicker: {
11690
+ ...sp,
11691
+ contextStrategy: expectDefined$1(COMPACTOR_STRATEGIES[next]),
11692
+ hint: bootHint
11693
+ }
11694
+ };
10344
11695
  }
10345
- if (f === 28) {
11696
+ if (f === 29) {
10346
11697
  const i = CONTEXT_MODES.indexOf(sp.contextMode);
10347
11698
  const base = i < 0 ? 0 : i;
10348
11699
  const next = (base + action.delta + CONTEXT_MODES.length) % CONTEXT_MODES.length;
10349
- return { ...state, settingsPicker: { ...sp, contextMode: expectDefined$1(CONTEXT_MODES[next]), hint: bootHint } };
11700
+ return {
11701
+ ...state,
11702
+ settingsPicker: {
11703
+ ...sp,
11704
+ contextMode: expectDefined$1(CONTEXT_MODES[next]),
11705
+ hint: bootHint
11706
+ }
11707
+ };
10350
11708
  }
10351
- if (f === 29) {
11709
+ if (f === 30) {
10352
11710
  const j = MAX_CONCURRENT_PRESETS.indexOf(sp.maxConcurrent);
10353
11711
  const base = j < 0 ? 0 : j;
10354
11712
  const next = (base + action.delta + MAX_CONCURRENT_PRESETS.length) % MAX_CONCURRENT_PRESETS.length;
10355
- return { ...state, settingsPicker: { ...sp, maxConcurrent: expectDefined$1(MAX_CONCURRENT_PRESETS[next]), hint: void 0 } };
11713
+ const maxConcurrent = expectDefined$1(MAX_CONCURRENT_PRESETS[next]);
11714
+ return {
11715
+ ...state,
11716
+ settingsPicker: {
11717
+ ...sp,
11718
+ maxConcurrent,
11719
+ hint: maxConcurrent === 0 ? bootHint : void 0
11720
+ }
11721
+ };
10356
11722
  }
10357
- if (f === 30) {
11723
+ if (f === 31) {
10358
11724
  const i = LOG_LEVELS.indexOf(sp.logLevel);
10359
11725
  const base = i < 0 ? 0 : i;
10360
11726
  const next = (base + action.delta + LOG_LEVELS.length) % LOG_LEVELS.length;
10361
- return { ...state, settingsPicker: { ...sp, logLevel: expectDefined$1(LOG_LEVELS[next]), hint: void 0 } };
11727
+ return {
11728
+ ...state,
11729
+ settingsPicker: { ...sp, logLevel: expectDefined$1(LOG_LEVELS[next]), hint: void 0 }
11730
+ };
10362
11731
  }
10363
- if (f === 31) {
11732
+ if (f === 32) {
10364
11733
  const i = AUDIT_LEVELS.indexOf(sp.auditLevel);
10365
11734
  const base = i < 0 ? 0 : i;
10366
11735
  const next = (base + action.delta + AUDIT_LEVELS.length) % AUDIT_LEVELS.length;
10367
- return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined$1(AUDIT_LEVELS[next]), hint: void 0 } };
11736
+ return {
11737
+ ...state,
11738
+ settingsPicker: { ...sp, auditLevel: expectDefined$1(AUDIT_LEVELS[next]), hint: void 0 }
11739
+ };
10368
11740
  }
10369
- if (f === 32) return { ...state, settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 } };
10370
- if (f === 33) {
11741
+ if (f === 33)
11742
+ return {
11743
+ ...state,
11744
+ settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 }
11745
+ };
11746
+ if (f === 34) {
10371
11747
  const i = STATUSLINE_MODES.indexOf(sp.statuslineMode);
10372
11748
  const base = i < 0 ? STATUSLINE_MODES.indexOf("detailed") : i;
10373
11749
  const next = (base + action.delta + STATUSLINE_MODES.length) % STATUSLINE_MODES.length;
10374
- return { ...state, settingsPicker: { ...sp, statuslineMode: expectDefined$1(STATUSLINE_MODES[next]), hint: void 0 } };
11750
+ return {
11751
+ ...state,
11752
+ settingsPicker: {
11753
+ ...sp,
11754
+ statuslineMode: expectDefined$1(STATUSLINE_MODES[next]),
11755
+ hint: void 0
11756
+ }
11757
+ };
10375
11758
  }
10376
- if (f === 34) {
11759
+ if (f === 35) {
10377
11760
  const i = CONFIG_SCOPES.indexOf(sp.configScope);
10378
11761
  const base = i < 0 ? 0 : i;
10379
11762
  const next = (base + action.delta + CONFIG_SCOPES.length) % CONFIG_SCOPES.length;
10380
- return { ...state, settingsPicker: { ...sp, configScope: expectDefined$1(CONFIG_SCOPES[next]), hint: void 0 } };
11763
+ return {
11764
+ ...state,
11765
+ settingsPicker: {
11766
+ ...sp,
11767
+ configScope: expectDefined$1(CONFIG_SCOPES[next]),
11768
+ hint: void 0
11769
+ }
11770
+ };
10381
11771
  }
10382
11772
  return state;
10383
11773
  }
11774
+ case "settingsValueSet": {
11775
+ return {
11776
+ ...state,
11777
+ settingsPicker: { ...state.settingsPicker, ...action.patch, hint: void 0 }
11778
+ };
11779
+ }
10384
11780
  case "settingsHint":
10385
11781
  return { ...state, settingsPicker: { ...state.settingsPicker, hint: action.text } };
11782
+ case "settingsThinkingEditStart":
11783
+ return {
11784
+ ...state,
11785
+ settingsPicker: {
11786
+ ...state.settingsPicker,
11787
+ thinkingWordEditing: true,
11788
+ // Seed the draft with the current word so the user edits from it.
11789
+ thinkingWordDraft: state.settingsPicker.thinkingWord,
11790
+ hint: void 0
11791
+ }
11792
+ };
11793
+ case "settingsThinkingEditChange":
11794
+ return {
11795
+ ...state,
11796
+ settingsPicker: {
11797
+ ...state.settingsPicker,
11798
+ // Hard-cap the draft so it can't grow past the persisted limit.
11799
+ thinkingWordDraft: action.draft.slice(0, MAX_TUI_THINKING_WORD_LENGTH),
11800
+ hint: void 0
11801
+ }
11802
+ };
11803
+ case "settingsThinkingEditCommit": {
11804
+ const sp = state.settingsPicker;
11805
+ const raw = sp.thinkingWordDraft.trim();
11806
+ if (raw.length === 0) {
11807
+ return {
11808
+ ...state,
11809
+ settingsPicker: { ...sp, thinkingWordEditing: false, thinkingWordDraft: "", hint: void 0 }
11810
+ };
11811
+ }
11812
+ const normalized = normalizeTuiThinkingWord(raw);
11813
+ const valid = normalized === raw;
11814
+ return {
11815
+ ...state,
11816
+ settingsPicker: {
11817
+ ...sp,
11818
+ thinkingWord: valid ? normalized : sp.thinkingWord,
11819
+ thinkingWordEditing: false,
11820
+ thinkingWordDraft: "",
11821
+ hint: valid ? void 0 : `Invalid word \u2014 keep it \u2264${MAX_TUI_THINKING_WORD_LENGTH} chars (letters/digits/_/-)`
11822
+ }
11823
+ };
11824
+ }
11825
+ case "settingsThinkingEditCancel":
11826
+ return {
11827
+ ...state,
11828
+ settingsPicker: {
11829
+ ...state.settingsPicker,
11830
+ thinkingWordEditing: false,
11831
+ thinkingWordDraft: "",
11832
+ hint: void 0
11833
+ }
11834
+ };
10386
11835
  // ── Statusline picker ───────────────────────────────────────────────
10387
11836
  case "statuslineOpen":
10388
11837
  return {
10389
11838
  ...state,
10390
11839
  ...closePanels(state),
10391
- statuslinePicker: { open: true, field: 0, hiddenItems: action.hiddenItems, visibleChips: state.statuslinePicker.visibleChips, hint: void 0 }
11840
+ statuslinePicker: {
11841
+ open: true,
11842
+ field: 0,
11843
+ hiddenItems: action.hiddenItems,
11844
+ visibleChips: state.statuslinePicker.visibleChips,
11845
+ hint: void 0
11846
+ }
10392
11847
  };
10393
11848
  case "statuslineClose":
10394
- return { ...state, statuslinePicker: { ...state.statuslinePicker, open: false, hint: void 0 } };
11849
+ return {
11850
+ ...state,
11851
+ statuslinePicker: { ...state.statuslinePicker, open: false, hint: void 0 }
11852
+ };
10395
11853
  case "statuslineFieldMove": {
10396
- const totalFields = 13;
11854
+ const totalFields = STATUSLINE_FIELD_COUNT;
10397
11855
  const next = (state.statuslinePicker.field + action.delta + totalFields) % totalFields;
10398
- return { ...state, statuslinePicker: { ...state.statuslinePicker, field: next, hint: void 0 } };
11856
+ return {
11857
+ ...state,
11858
+ statuslinePicker: { ...state.statuslinePicker, field: next, hint: void 0 }
11859
+ };
10399
11860
  }
10400
11861
  case "statuslineFieldSet": {
10401
- const totalFields = 13;
11862
+ const totalFields = STATUSLINE_FIELD_COUNT;
10402
11863
  const field = action.field >= 0 && action.field < totalFields ? action.field : 0;
10403
11864
  return { ...state, statuslinePicker: { ...state.statuslinePicker, field, hint: void 0 } };
10404
11865
  }
@@ -10410,7 +11871,10 @@ function reducer(state, action) {
10410
11871
  } else {
10411
11872
  hiddenSet.add(action.item);
10412
11873
  }
10413
- return { ...state, statuslinePicker: { ...cur, hiddenItems: [...hiddenSet] } };
11874
+ return {
11875
+ ...state,
11876
+ statuslinePicker: { ...cur, hiddenItems: [...hiddenSet] }
11877
+ };
10414
11878
  }
10415
11879
  case "statuslineHint":
10416
11880
  return { ...state, statuslinePicker: { ...state.statuslinePicker, hint: action.text } };
@@ -10456,7 +11920,14 @@ function reducer(state, action) {
10456
11920
  case "projectPickerClose":
10457
11921
  return {
10458
11922
  ...state,
10459
- projectPicker: { open: false, allItems: [], items: [], selected: 0, filter: "", hint: void 0 }
11923
+ projectPicker: {
11924
+ open: false,
11925
+ allItems: [],
11926
+ items: [],
11927
+ selected: 0,
11928
+ filter: "",
11929
+ hint: void 0
11930
+ }
10460
11931
  };
10461
11932
  case "projectPickerMove": {
10462
11933
  const cur = state.projectPicker;
@@ -10724,13 +12195,14 @@ function reducer(state, action) {
10724
12195
  case "fleetCtxPct": {
10725
12196
  const cur = state.fleet[action.id];
10726
12197
  if (!cur) return state;
12198
+ const ctxPct = clampContextLoad(action.load);
10727
12199
  return {
10728
12200
  ...state,
10729
12201
  fleet: {
10730
12202
  ...state.fleet,
10731
12203
  [action.id]: {
10732
12204
  ...cur,
10733
- ctxPct: action.load,
12205
+ ctxPct,
10734
12206
  ctxTokens: action.tokens,
10735
12207
  ctxMaxTokens: action.maxContext,
10736
12208
  ctxCost: action.ctxCost,
@@ -10813,11 +12285,12 @@ function reducer(state, action) {
10813
12285
  };
10814
12286
  }
10815
12287
  case "leaderCtxPct": {
12288
+ const ctxPct = clampContextLoad(action.load);
10816
12289
  return {
10817
12290
  ...state,
10818
12291
  leader: {
10819
12292
  ...state.leader,
10820
- ctxPct: action.load,
12293
+ ctxPct,
10821
12294
  ctxTokens: action.tokens,
10822
12295
  ctxMaxTokens: action.maxContext,
10823
12296
  lastEventAt: Date.now()
@@ -10977,7 +12450,9 @@ function reducer(state, action) {
10977
12450
  }
10978
12451
  case "sddBoardSnapshot": {
10979
12452
  const monitorOpen = state.sddBoard?.monitorOpen ?? false;
10980
- return { ...state, sddBoard: { snapshot: action.snapshot, monitorOpen } };
12453
+ const prevFocus = state.sddBoard?.focusColumn;
12454
+ const focusColumn = typeof prevFocus === "number" && prevFocus >= 0 && prevFocus < action.snapshot.columns.length ? prevFocus : void 0;
12455
+ return { ...state, sddBoard: { snapshot: action.snapshot, monitorOpen, focusColumn } };
10981
12456
  }
10982
12457
  case "toggleSddBoardMonitor": {
10983
12458
  if (!state.sddBoard) return state;
@@ -10988,9 +12463,26 @@ function reducer(state, action) {
10988
12463
  sddBoard: { ...state.sddBoard, monitorOpen: true }
10989
12464
  } : {
10990
12465
  ...state,
10991
- sddBoard: { ...state.sddBoard, monitorOpen: false }
12466
+ sddBoard: { ...state.sddBoard, monitorOpen: false, focusColumn: void 0 }
10992
12467
  };
10993
12468
  }
12469
+ case "sddBoardFocusNext": {
12470
+ if (!state.sddBoard) return state;
12471
+ if (!state.sddBoard.monitorOpen) return state;
12472
+ const max = state.sddBoard.snapshot.columns.length - 1;
12473
+ if (max < 0) return state;
12474
+ const current = state.sddBoard.focusColumn;
12475
+ const next = typeof current === "number" ? Math.min(max, current + 1) : 0;
12476
+ return { ...state, sddBoard: { ...state.sddBoard, focusColumn: next } };
12477
+ }
12478
+ case "sddBoardFocusPrev": {
12479
+ if (!state.sddBoard) return state;
12480
+ if (!state.sddBoard.monitorOpen) return state;
12481
+ const current = state.sddBoard.focusColumn;
12482
+ if (typeof current !== "number") return state;
12483
+ const next = current <= 0 ? void 0 : current - 1;
12484
+ return { ...state, sddBoard: { ...state.sddBoard, focusColumn: next } };
12485
+ }
10994
12486
  case "worktreeUpsert": {
10995
12487
  const prev = state.worktrees[action.handleId];
10996
12488
  const merged = {
@@ -11368,32 +12860,56 @@ function nextInputWordStart(buffer, cursor) {
11368
12860
  }
11369
12861
  function rehydrateHistory(messages, startId, toolCalls) {
11370
12862
  const entries = [];
12863
+ const toolCallsById = /* @__PURE__ */ new Map();
12864
+ if (toolCalls) {
12865
+ for (const tc of toolCalls) {
12866
+ if (!toolCallsById.has(tc.id)) toolCallsById.set(tc.id, tc);
12867
+ }
12868
+ }
12869
+ const consumed = /* @__PURE__ */ new Set();
12870
+ const fallback = [];
11371
12871
  let nextId = startId;
12872
+ const textOf = (msg) => {
12873
+ if (typeof msg.content === "string") return msg.content;
12874
+ return msg.content.filter((b) => b.type === "text").map((b) => b.text).join("");
12875
+ };
12876
+ const toolEntryFor = (tc) => ({
12877
+ id: nextId++,
12878
+ kind: "tool",
12879
+ name: tc.name,
12880
+ durationMs: tc.durationMs,
12881
+ ok: tc.ok,
12882
+ outputBytes: tc.outputBytes,
12883
+ outputTokens: tc.outputTokens,
12884
+ outputLines: tc.outputLines
12885
+ });
11372
12886
  for (const msg of messages) {
11373
12887
  if (msg.role === "system") continue;
11374
- const text = typeof msg.content === "string" ? msg.content : msg.content.filter((b) => b.type === "text").map((b) => b.text).join("");
11375
- const trimmed = text.trim();
11376
- if (!trimmed) continue;
12888
+ const text = textOf(msg).trim();
12889
+ if (!text) continue;
11377
12890
  if (msg.role === "user") {
11378
- entries.push({ id: nextId++, kind: "user", text: trimmed });
11379
- } else if (msg.role === "assistant") {
11380
- entries.push({ id: nextId++, kind: "assistant", text: trimmed });
12891
+ entries.push({ id: nextId++, kind: "user", text });
12892
+ continue;
12893
+ }
12894
+ if (msg.role === "assistant") {
12895
+ entries.push({ id: nextId++, kind: "assistant", text });
12896
+ if (Array.isArray(msg.content)) {
12897
+ for (const block of msg.content) {
12898
+ if (block.type !== "tool_use") continue;
12899
+ const tc = toolCallsById.get(block.id);
12900
+ if (!tc) continue;
12901
+ entries.push(toolEntryFor(tc));
12902
+ consumed.add(block.id);
12903
+ }
12904
+ }
11381
12905
  }
11382
12906
  }
11383
- if (toolCalls && toolCalls.length > 0) {
12907
+ if (toolCalls) {
11384
12908
  for (const tc of toolCalls) {
11385
- entries.push({
11386
- id: nextId++,
11387
- kind: "tool",
11388
- name: tc.name,
11389
- durationMs: tc.durationMs,
11390
- ok: tc.ok,
11391
- outputBytes: tc.outputBytes,
11392
- outputTokens: tc.outputTokens,
11393
- outputLines: tc.outputLines
11394
- });
12909
+ if (!consumed.has(tc.id)) fallback.push(toolEntryFor(tc));
11395
12910
  }
11396
12911
  }
12912
+ entries.push(...fallback);
11397
12913
  return entries;
11398
12914
  }
11399
12915
  var PASTE_THRESHOLD_CHARS = 200;
@@ -11451,6 +12967,7 @@ function App({
11451
12967
  director,
11452
12968
  fleetRoster,
11453
12969
  onClearHistory,
12970
+ clearTerminal,
11454
12971
  listSessions,
11455
12972
  onResumeSession,
11456
12973
  fleetStreamController,
@@ -11641,7 +13158,7 @@ function App({
11641
13158
  },
11642
13159
  autonomyPicker: { open: false, options: [], selected: 0 },
11643
13160
  resumePicker: { open: false, sessions: [], selected: 0, busy: false, hint: void 0, error: void 0 },
11644
- settingsPicker: { open: false, field: 0, mode: "off", delayMs: 0, titleAnimation: true, yolo: false, streamFleet: true, chime: false, confirmExit: true, nextPrediction: false, featureMcp: true, featurePlugins: true, featureMemory: true, featureSkills: true, featureModelsRegistry: true, tokenSavingTier: "off", allowOutsideProjectRoot: true, contextAutoCompact: true, contextStrategy: "hybrid", contextMode: "balanced", maxConcurrent: 10, logLevel: "info", auditLevel: "standard", indexOnStart: true, maxIterations: 500, autoProceedMaxIterations: 50, enhanceDelayMs: 6e4, enhanceEnabled: true, enhanceLanguage: "original", debugStream: false, statuslineMode: "detailed", reasoningMode: "auto", reasoningEffort: "high", reasoningPreserve: false, thinkingWord: "thinking", cacheTtl: "default", configScope: "global" },
13161
+ settingsPicker: { open: false, field: 0, lastSettingsField: 0, filter: "", mode: "off", delayMs: 0, titleAnimation: true, yolo: false, streamFleet: true, chime: false, confirmExit: true, nextPrediction: false, featureMcp: true, featurePlugins: true, featureMemory: true, featureSkills: true, featureModelsRegistry: true, tokenSavingTier: "off", allowOutsideProjectRoot: true, contextAutoCompact: true, contextStrategy: "hybrid", contextMode: "balanced", maxConcurrent: 10, logLevel: "info", auditLevel: "standard", indexOnStart: true, multiDiffSummaryThreshold: 5, maxIterations: 500, autoProceedMaxIterations: 50, enhanceDelayMs: 6e4, enhanceEnabled: true, enhanceLanguage: "original", debugStream: false, statuslineMode: "detailed", reasoningMode: "auto", reasoningEffort: "high", reasoningPreserve: false, thinkingWord: "thinking", thinkingWordEditing: false, thinkingWordDraft: "", cacheTtl: "default", configScope: "global" },
11645
13162
  statuslinePicker: { open: false, field: 0, hiddenItems: [], visibleChips: [], hint: void 0 },
11646
13163
  projectPicker: { open: false, allItems: [], items: [], selected: 0, filter: "", hint: void 0 },
11647
13164
  fKeyPicker: { open: false, selected: 0 },
@@ -11778,6 +13295,20 @@ function App({
11778
13295
  const liveSettings = getSettings?.();
11779
13296
  const liveStatuslineMode = liveSettings?.statuslineMode ?? "detailed";
11780
13297
  const liveThinkingWord = liveSettings?.thinkingWord ?? "thinking";
13298
+ const [rolledThinkingWord, setRolledThinkingWord] = useState(
13299
+ () => pickRandomTuiThinkingWord()
13300
+ );
13301
+ const thinkingWorking = state.status === "running" || state.status === "streaming";
13302
+ const prevThinkingWorkingRef = useRef(false);
13303
+ useEffect(() => {
13304
+ if (thinkingWorking && !prevThinkingWorkingRef.current) {
13305
+ setRolledThinkingWord((prev) => pickRandomTuiThinkingWord(prev));
13306
+ }
13307
+ prevThinkingWorkingRef.current = thinkingWorking;
13308
+ }, [thinkingWorking]);
13309
+ const displayThinkingWord = isRandomTuiThinkingWord(liveThinkingWord) ? rolledThinkingWord : liveThinkingWord;
13310
+ const displayThinkingWordRef = useRef(displayThinkingWord);
13311
+ displayThinkingWordRef.current = displayThinkingWord;
11781
13312
  const chimeRef = useRef(chime);
11782
13313
  chimeRef.current = liveSettings?.chime ?? chime;
11783
13314
  const confirmExitRef = useRef(confirmExit);
@@ -11794,8 +13325,22 @@ function App({
11794
13325
  stateRef.current = state;
11795
13326
  const draftRef = useRef({ buffer: state.buffer, cursor: state.cursor });
11796
13327
  draftRef.current = { buffer: state.buffer, cursor: state.cursor };
13328
+ const statuslineHiddenForPicker = useCallback(() => {
13329
+ const hookHidden = hiddenItemsRef.current;
13330
+ const hookHiddenSet = new Set(hookHidden);
13331
+ const reducerOnlyHidden = stateRef.current.statuslinePicker.hiddenItems.filter(
13332
+ (item) => !hookHiddenSet.has(item)
13333
+ );
13334
+ return [...hookHidden, ...reducerOnlyHidden];
13335
+ }, []);
13336
+ const openStatuslinePicker = useCallback((field) => {
13337
+ if (field !== void 0) {
13338
+ dispatch({ type: "statuslineFieldSet", field });
13339
+ }
13340
+ dispatch({ type: "statuslineOpen", hiddenItems: statuslineHiddenForPicker() });
13341
+ }, [statuslineHiddenForPicker]);
11797
13342
  const [mouseMode, setMouseMode] = useState(mouse);
11798
- const pickerOverlayOpen = state.modelPicker.open || state.autonomyPicker.open || state.settingsPicker.open || state.projectPicker.open || state.slashPicker.open || state.picker.open;
13343
+ 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;
11799
13344
  const mouseTrackingOn = mouseMode || pickerOverlayOpen;
11800
13345
  const mouseWrittenRef = useRef(false);
11801
13346
  useEffect(() => {
@@ -12351,6 +13896,8 @@ function App({
12351
13896
  logLevel: sp.logLevel,
12352
13897
  auditLevel: sp.auditLevel,
12353
13898
  indexOnStart: sp.indexOnStart,
13899
+ multiDiffSummaryThreshold: sp.multiDiffSummaryThreshold,
13900
+ lastSettingsField: sp.lastSettingsField,
12354
13901
  maxIterations: sp.maxIterations,
12355
13902
  autoProceedMaxIterations: sp.autoProceedMaxIterations,
12356
13903
  enhanceDelayMs: sp.enhanceDelayMs,
@@ -12427,24 +13974,7 @@ function App({
12427
13974
  return;
12428
13975
  }
12429
13976
  const query = trimmed.slice(1).toLowerCase();
12430
- const allCommands = slashRegistry.listWithOwner();
12431
- const CATEGORY_ORDER = ["Run", "Session", "Inspect", "Agent", "Config", "App"];
12432
- const matches = allCommands.filter(({ cmd }) => {
12433
- if (query === "" && cmd.hidden) return false;
12434
- const name = cmd.name.toLowerCase();
12435
- const aliases = cmd.aliases ?? [];
12436
- return name.includes(query) || aliases.some((a) => a.toLowerCase().includes(query));
12437
- }).map(({ cmd, owner }) => ({
12438
- name: cmd.name,
12439
- description: cmd.description,
12440
- argsHint: cmd.argsHint,
12441
- isBuiltin: owner === "core",
12442
- category: cmd.category ?? "App"
12443
- })).sort((a, b) => {
12444
- const catDiff = CATEGORY_ORDER.indexOf(a.category) - CATEGORY_ORDER.indexOf(b.category);
12445
- if (catDiff !== 0) return catDiff;
12446
- return a.name.localeCompare(b.name);
12447
- });
13977
+ const matches = buildSlashCommandMatches(slashRegistry.listWithOwner(), query);
12448
13978
  if (!state.slashPicker.open) {
12449
13979
  dispatch({ type: "slashPickerOpen", query, matches });
12450
13980
  } else if (state.slashPicker.query !== query) {
@@ -12767,6 +14297,8 @@ function App({
12767
14297
  logLevel: s2.logLevel ?? "info",
12768
14298
  auditLevel: s2.auditLevel ?? "standard",
12769
14299
  indexOnStart: s2.indexOnStart ?? true,
14300
+ multiDiffSummaryThreshold: s2.multiDiffSummaryThreshold ?? 5,
14301
+ lastSettingsField: s2.lastSettingsField ?? 0,
12770
14302
  maxIterations: s2.maxIterations ?? 500,
12771
14303
  autoProceedMaxIterations: s2.autoProceedMaxIterations ?? 50,
12772
14304
  enhanceDelayMs: s2.enhanceDelayMs ?? 6e4,
@@ -12911,6 +14443,8 @@ function App({
12911
14443
  logLevel: sp.logLevel,
12912
14444
  auditLevel: sp.auditLevel,
12913
14445
  indexOnStart: sp.indexOnStart,
14446
+ multiDiffSummaryThreshold: sp.multiDiffSummaryThreshold,
14447
+ lastSettingsField: sp.lastSettingsField,
12914
14448
  maxIterations: sp.maxIterations,
12915
14449
  autoProceedMaxIterations: sp.autoProceedMaxIterations,
12916
14450
  enhanceDelayMs: sp.enhanceDelayMs,
@@ -13001,8 +14535,95 @@ function App({
13001
14535
  const cmd = {
13002
14536
  name: "settings",
13003
14537
  aliases: ["config", "prefs"],
13004
- description: "Open the interactive settings editor (19 config fields across 8 sections).",
13005
- async run() {
14538
+ description: "Open the settings editor, or set a value inline: /settings [<chord> [<value>]].",
14539
+ argsHint: "[<chord> [<value>]]",
14540
+ help: "Open the settings editor.\n\n /settings Open on the last-visited row\n /settings <chord> Open on that row\n /settings <chord> <v> Set <chord> to <v> without opening the picker\n /settings reset <chord> Reset <chord> to its factory default\n\nExamples:\n /settings yolo on Enable YOLO mode\n /settings multi-diff 8 Set multi-diff threshold to 8\n /settings thinking-word pondering Set the working-state word\n\nAvailable chords:\n " + settingsPickerJumpNames().join("\n "),
14541
+ async run(args) {
14542
+ const query = args.trim();
14543
+ if (query === "") {
14544
+ openSettings();
14545
+ return { message: void 0 };
14546
+ }
14547
+ if (query === "reset" || query.startsWith("reset ")) {
14548
+ const subArg = query.slice("reset".length).trim();
14549
+ if (subArg === "") {
14550
+ return {
14551
+ message: "Usage: /settings reset <chord>\nAvailable: " + settingsPickerJumpNames().join(", ")
14552
+ };
14553
+ }
14554
+ const field2 = settingsPickerJumpByName(subArg);
14555
+ if (field2 === void 0) {
14556
+ return {
14557
+ message: `Unknown settings row "${subArg}".
14558
+ Available chords:
14559
+ ${settingsPickerJumpNames().join("\n ")}`
14560
+ };
14561
+ }
14562
+ const result = resetSettingsFieldValue(field2);
14563
+ if (!result.ok) {
14564
+ return { message: result.error };
14565
+ }
14566
+ dispatch({ type: "settingsValueSet", patch: result.patch });
14567
+ const cur = getSettings ? getSettings() : void 0;
14568
+ if (cur && saveSettings) {
14569
+ const { tokenSavingTier, ...rest } = result.patch;
14570
+ Promise.resolve(
14571
+ saveSettings({
14572
+ ...cur,
14573
+ ...rest,
14574
+ ...tokenSavingTier !== void 0 ? { featureTokenSaving: tokenSavingTier } : {}
14575
+ })
14576
+ ).then((err) => {
14577
+ if (err) dispatch({ type: "settingsHint", text: err });
14578
+ });
14579
+ }
14580
+ return { message: `\u21BA ${result.label} reset to ${result.displayValue}` };
14581
+ }
14582
+ const spaceIdx = query.indexOf(" ");
14583
+ if (spaceIdx > 0) {
14584
+ const rowName = query.slice(0, spaceIdx);
14585
+ const valueStr = query.slice(spaceIdx + 1).trim();
14586
+ const field2 = settingsPickerJumpByName(rowName);
14587
+ if (field2 === void 0) {
14588
+ return {
14589
+ message: `Unknown settings row "${rowName}".
14590
+ Available chords:
14591
+ ${settingsPickerJumpNames().join("\n ")}`
14592
+ };
14593
+ }
14594
+ if (valueStr === "") {
14595
+ dispatch({ type: "settingsFieldSet", field: field2 });
14596
+ openSettings();
14597
+ return { message: void 0 };
14598
+ }
14599
+ const result = resolveSettingsFieldValue(field2, valueStr);
14600
+ if (!result.ok) {
14601
+ return { message: result.error };
14602
+ }
14603
+ dispatch({ type: "settingsValueSet", patch: result.patch });
14604
+ const cur = getSettings ? getSettings() : void 0;
14605
+ if (cur && saveSettings) {
14606
+ const { tokenSavingTier, ...rest } = result.patch;
14607
+ const updated = {
14608
+ ...cur,
14609
+ ...rest,
14610
+ ...tokenSavingTier !== void 0 ? { featureTokenSaving: tokenSavingTier } : {}
14611
+ };
14612
+ Promise.resolve(saveSettings(updated)).then((err) => {
14613
+ if (err) dispatch({ type: "settingsHint", text: err });
14614
+ });
14615
+ }
14616
+ return { message: `\u2713 ${result.label} \u2192 ${result.displayValue}` };
14617
+ }
14618
+ const field = settingsPickerJumpByName(query);
14619
+ if (field === void 0) {
14620
+ return {
14621
+ message: `Unknown settings row "${query}".
14622
+ Available chords:
14623
+ ${settingsPickerJumpNames().join("\n ")}`
14624
+ };
14625
+ }
14626
+ dispatch({ type: "settingsFieldSet", field });
13006
14627
  openSettings();
13007
14628
  return { message: void 0 };
13008
14629
  }
@@ -13011,19 +14632,80 @@ function App({
13011
14632
  return () => {
13012
14633
  slashRegistry.unregister("settings");
13013
14634
  };
13014
- }, [slashRegistry, getSettings, saveSettings, openSettings]);
14635
+ }, [slashRegistry, getSettings, saveSettings, openSettings, dispatch]);
14636
+ useEffect(() => {
14637
+ const cmd = {
14638
+ name: "settings-get",
14639
+ aliases: ["config-get", "get"],
14640
+ description: "Read a setting value without opening the picker.",
14641
+ argsHint: "<chord>",
14642
+ help: 'Show the current value of a setting.\n\nExamples:\n /settings-get yolo \u2192 "YOLO mode: off"\n /settings-get multi-diff \u2192 "Multi-diff summary: 5"\n /settings-get log-level \u2192 "Log level: info"\n\nAvailable chords:\n ' + settingsPickerJumpNames().join("\n "),
14643
+ async run(args) {
14644
+ const query = args.trim();
14645
+ if (query === "") {
14646
+ return { message: formatAllSettingsSummary(state.settingsPicker) };
14647
+ }
14648
+ const field = settingsPickerJumpByName(query);
14649
+ if (field === void 0) {
14650
+ return {
14651
+ message: `Unknown settings row "${query}".
14652
+ Available chords:
14653
+ ${settingsPickerJumpNames().join("\n ")}`
14654
+ };
14655
+ }
14656
+ const result = getSettingsFieldValue(state.settingsPicker, field);
14657
+ if (!result.ok) {
14658
+ return { message: result.error };
14659
+ }
14660
+ return { message: `${result.label}: ${result.displayValue}` };
14661
+ }
14662
+ };
14663
+ slashRegistry.register(cmd, "tui", { official: true });
14664
+ return () => {
14665
+ slashRegistry.unregister("settings-get");
14666
+ };
14667
+ }, [slashRegistry, state.settingsPicker]);
13015
14668
  useEffect(() => {
13016
14669
  const cmd = {
13017
14670
  name: "statusline",
13018
14671
  aliases: ["sl"],
13019
14672
  description: "Customize status bar chips: /statusline (interactive) or /statusline <item> [on|off]",
13020
14673
  async run(args) {
13021
- if (args.trim()) return { message: void 0 };
13022
- const hookHidden = hiddenItemsRef.current;
13023
- const reducerStreamHidden = stateRef.current.statuslinePicker.hiddenItems.filter(
13024
- (item) => !hookHidden.includes(item)
13025
- );
13026
- dispatch({ type: "statuslineOpen", hiddenItems: [...hookHidden, ...reducerStreamHidden] });
14674
+ const trimmed = args.trim();
14675
+ if (trimmed) {
14676
+ const [rawItem, rawAction] = trimmed.split(/\s+/);
14677
+ const item = rawItem;
14678
+ const action = rawAction?.toLowerCase();
14679
+ const applyHidden = (items) => {
14680
+ const deduped = [...new Set(items)];
14681
+ hiddenItemsRef.current = deduped;
14682
+ setHiddenItems(deduped);
14683
+ };
14684
+ if (item === "reset") {
14685
+ applyHidden([]);
14686
+ return { message: "StatusBar config reset to defaults." };
14687
+ }
14688
+ if (item === "all") {
14689
+ if (action !== "on" && action !== "off") {
14690
+ return { message: "Usage: /statusline all on|off" };
14691
+ }
14692
+ applyHidden(action === "off" ? [...STATUSLINE_ITEMS] : []);
14693
+ return { message: `statusline all: ${action === "on" ? "showing all chips" : "hiding all chips"}` };
14694
+ }
14695
+ if (!item || !STATUSLINE_ITEMS.includes(item)) {
14696
+ return { message: `Unknown item "${rawItem ?? ""}". Run /statusline to see available items.` };
14697
+ }
14698
+ if (action !== void 0 && action !== "on" && action !== "off") {
14699
+ return { message: `Usage: /statusline ${item} on|off` };
14700
+ }
14701
+ const hidden = new Set(hiddenItemsRef.current);
14702
+ const nextVisible = action ? action === "on" : hidden.has(item);
14703
+ if (nextVisible) hidden.delete(item);
14704
+ else hidden.add(item);
14705
+ applyHidden([...hidden]);
14706
+ return { message: `statusline ${item}: ${nextVisible ? "on" : "off"}` };
14707
+ }
14708
+ openStatuslinePicker();
13027
14709
  return { message: void 0 };
13028
14710
  }
13029
14711
  };
@@ -13031,7 +14713,7 @@ function App({
13031
14713
  return () => {
13032
14714
  slashRegistry.unregister("statusline");
13033
14715
  };
13034
- }, [slashRegistry]);
14716
+ }, [slashRegistry, openStatuslinePicker, setHiddenItems]);
13035
14717
  useEffect(() => {
13036
14718
  const cmd = {
13037
14719
  name: "mailbox",
@@ -13737,6 +15419,29 @@ function App({
13737
15419
  return;
13738
15420
  }
13739
15421
  if (state.settingsPicker.open) {
15422
+ const sp = state.settingsPicker;
15423
+ if (sp.thinkingWordEditing) {
15424
+ if (key.escape) {
15425
+ dispatch({ type: "settingsThinkingEditCancel" });
15426
+ return;
15427
+ }
15428
+ if (isEnter) {
15429
+ const now = Date.now();
15430
+ if (now - lastEnterAtRef.current < 50) return;
15431
+ lastEnterAtRef.current = now;
15432
+ dispatch({ type: "settingsThinkingEditCommit" });
15433
+ return;
15434
+ }
15435
+ if (key.backspace) {
15436
+ dispatch({ type: "settingsThinkingEditChange", draft: sp.thinkingWordDraft.slice(0, -1) });
15437
+ return;
15438
+ }
15439
+ if (input && input.length === 1 && input.charCodeAt(0) >= 32 && input.charCodeAt(0) < 127) {
15440
+ dispatch({ type: "settingsThinkingEditChange", draft: sp.thinkingWordDraft + input });
15441
+ return;
15442
+ }
15443
+ return;
15444
+ }
13740
15445
  if (key.escape || key.ctrl && input === "s") {
13741
15446
  dispatch({ type: "settingsClose" });
13742
15447
  return;
@@ -13745,6 +15450,33 @@ function App({
13745
15450
  dispatch({ type: "settingsFieldMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
13746
15451
  return;
13747
15452
  }
15453
+ if (input && input.length === 1 && (key.ctrl || key.meta)) {
15454
+ const mod = key.ctrl ? "ctrl" : key.shift ? "alt-shift" : "alt";
15455
+ const field = settingsPickerJumpField(mod, input);
15456
+ if (field !== void 0) {
15457
+ dispatch({ type: "settingsFieldSet", field });
15458
+ return;
15459
+ }
15460
+ }
15461
+ if (input === "/" && sp.filter === "") {
15462
+ dispatch({ type: "settingsFilterSet", filter: "/" });
15463
+ return;
15464
+ }
15465
+ if (sp.filter !== "") {
15466
+ if (key.escape) {
15467
+ dispatch({ type: "settingsFilterSet", filter: "" });
15468
+ return;
15469
+ }
15470
+ if (key.backspace) {
15471
+ const next2 = sp.filter.length > 1 ? sp.filter.slice(0, -1) : "";
15472
+ dispatch({ type: "settingsFilterSet", filter: next2 });
15473
+ return;
15474
+ }
15475
+ if (input && input.length === 1 && input.charCodeAt(0) >= 32 && input.charCodeAt(0) < 127) {
15476
+ dispatch({ type: "settingsFilterSet", filter: sp.filter + input });
15477
+ return;
15478
+ }
15479
+ }
13748
15480
  if (key.upArrow) {
13749
15481
  dispatch({ type: "settingsFieldMove", delta: -1 });
13750
15482
  return;
@@ -13765,7 +15497,15 @@ function App({
13765
15497
  const now = Date.now();
13766
15498
  if (now - lastEnterAtRef.current < 50) return;
13767
15499
  lastEnterAtRef.current = now;
13768
- dispatch({ type: "settingsValueChange", delta: 1 });
15500
+ if (sp.filter !== "") {
15501
+ dispatch({ type: "settingsFilterSet", filter: "" });
15502
+ return;
15503
+ }
15504
+ if (sp.field === THINKING_WORD_FIELD) {
15505
+ dispatch({ type: "settingsThinkingEditStart" });
15506
+ } else {
15507
+ dispatch({ type: "settingsValueChange", delta: 1 });
15508
+ }
13769
15509
  return;
13770
15510
  }
13771
15511
  return;
@@ -14009,7 +15749,7 @@ function App({
14009
15749
  openProjectPicker();
14010
15750
  return;
14011
15751
  }
14012
- const action = actionForFKeyPanel(entry, state.statuslinePicker.hiddenItems);
15752
+ const action = actionForFKeyPanel(entry, statuslineHiddenForPicker());
14013
15753
  if (action) dispatch(action);
14014
15754
  return;
14015
15755
  }
@@ -14185,6 +15925,14 @@ function App({
14185
15925
  return;
14186
15926
  }
14187
15927
  if (state.sddBoard?.monitorOpen && !key.ctrl && !key.meta) {
15928
+ if (key.rightArrow) {
15929
+ dispatch({ type: "sddBoardFocusNext" });
15930
+ return;
15931
+ }
15932
+ if (key.leftArrow) {
15933
+ dispatch({ type: "sddBoardFocusPrev" });
15934
+ return;
15935
+ }
14188
15936
  if (input === "c") {
14189
15937
  const run = getSddRun?.();
14190
15938
  if (run) {
@@ -14307,7 +16055,7 @@ function App({
14307
16055
  return;
14308
16056
  }
14309
16057
  if (key.fn === 12) {
14310
- dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
16058
+ openStatuslinePicker();
14311
16059
  return;
14312
16060
  }
14313
16061
  if (state.settingsPicker.open) {
@@ -14375,6 +16123,8 @@ function App({
14375
16123
  logLevel: cfg.logLevel ?? "info",
14376
16124
  auditLevel: cfg.auditLevel ?? "standard",
14377
16125
  indexOnStart: cfg.indexOnStart ?? true,
16126
+ multiDiffSummaryThreshold: cfg.multiDiffSummaryThreshold ?? 5,
16127
+ lastSettingsField: cfg.lastSettingsField ?? 0,
14378
16128
  maxIterations: cfg.maxIterations ?? 500,
14379
16129
  autoProceedMaxIterations: cfg.autoProceedMaxIterations ?? 50,
14380
16130
  enhanceDelayMs: cfg.enhanceDelayMs ?? 6e4,
@@ -14643,6 +16393,10 @@ function App({
14643
16393
  version: appVersion,
14644
16394
  state: state.status,
14645
16395
  fleetRunning: fleetCounts?.running ?? 0,
16396
+ // Must match the rendered state label width — while streaming the bar
16397
+ // shows the configured thinking word, so the span shifts with it.
16398
+ // Omitting this made the model chip un-clickable mid-stream.
16399
+ thinkingWord: displayThinkingWordRef.current,
14646
16400
  model: `${liveProvider}/${liveModel}`
14647
16401
  });
14648
16402
  if (inSpan(span)) {
@@ -14660,27 +16414,24 @@ function App({
14660
16414
  dispatch({ type: "toggleTodosMonitor" });
14661
16415
  return;
14662
16416
  }
14663
- const hiddenSet = new Set(state.statuslinePicker.hiddenItems);
16417
+ const hiddenSet = new Set(statuslineHiddenForPicker());
14664
16418
  if (my === rowFor(2)) {
14665
16419
  const mxLocal = mx - SB_PADX2 - 1;
14666
16420
  if (!hiddenSet.has("todos") && mxLocal >= 0 && mxLocal < 20) {
14667
- dispatch({ type: "statuslineFieldSet", field: 11 });
14668
- dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
16421
+ openStatuslinePicker(STATUSLINE_ITEMS.indexOf("todos"));
14669
16422
  return;
14670
16423
  }
14671
16424
  if (!hiddenSet.has("plan")) {
14672
16425
  const planStart = 21;
14673
16426
  if (mxLocal >= planStart && mxLocal < planStart + 22) {
14674
- dispatch({ type: "statuslineFieldSet", field: 9 });
14675
- dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
16427
+ openStatuslinePicker(STATUSLINE_ITEMS.indexOf("plan"));
14676
16428
  return;
14677
16429
  }
14678
16430
  }
14679
16431
  if (!hiddenSet.has("tasks")) {
14680
16432
  const tasksStart = 44;
14681
16433
  if (mxLocal >= tasksStart && mxLocal < tasksStart + 26) {
14682
- dispatch({ type: "statuslineFieldSet", field: 10 });
14683
- dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
16434
+ openStatuslinePicker(STATUSLINE_ITEMS.indexOf("tasks"));
14684
16435
  return;
14685
16436
  }
14686
16437
  }
@@ -14689,8 +16440,7 @@ function App({
14689
16440
  const mxLocal = mx - SB_PADX2 - 1;
14690
16441
  const fleetStart = 0;
14691
16442
  if (mxLocal >= fleetStart && mxLocal < fleetStart + 22) {
14692
- dispatch({ type: "statuslineFieldSet", field: 12 });
14693
- dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
16443
+ openStatuslinePicker(STATUSLINE_ITEMS.indexOf("fleet"));
14694
16444
  return;
14695
16445
  }
14696
16446
  }
@@ -15133,6 +16883,7 @@ ${content}
15133
16883
  }
15134
16884
  const cmd = trimmed.slice(1).split(/\s+/, 1)[0];
15135
16885
  if (cmd === "clear") {
16886
+ clearTerminal?.();
15136
16887
  onClearHistory?.(dispatch);
15137
16888
  tokenCounter?.reset();
15138
16889
  }
@@ -15249,14 +17000,16 @@ User message:
15249
17000
  pushSubmittedHistory();
15250
17001
  clearDraft();
15251
17002
  const blocks = await builder.submit();
15252
- if (state.status !== "idle") {
17003
+ if (state.status !== "idle" && !steering) {
15253
17004
  if (autonomyLive === "auto" && nextStepsAutoSubmitTimerRef.current != null) {
15254
17005
  switchAutonomy?.("off");
15255
17006
  }
15256
- dispatch({
15257
- type: "addEntry",
15258
- entry: { kind: "user", text: displayText, queued: true, pasteContent }
15259
- });
17007
+ if (!steering) {
17008
+ dispatch({
17009
+ type: "addEntry",
17010
+ entry: { kind: "user", text: displayText, queued: true, pasteContent }
17011
+ });
17012
+ }
15260
17013
  dispatch({ type: "enqueue", item: { displayText, blocks } });
15261
17014
  return;
15262
17015
  }
@@ -15329,7 +17082,7 @@ User message:
15329
17082
  onMeasure: (totalLines) => dispatch({ type: "setMeasuredLines", totalLines }),
15330
17083
  setSuggestions,
15331
17084
  autonomyMode: autonomyLive,
15332
- autoSubmitCountdown: nextStepsAutoSubmitCountdown
17085
+ multiDiffSummaryThreshold: state.settingsPicker.multiDiffSummaryThreshold
15333
17086
  }
15334
17087
  ) : /* @__PURE__ */ jsx(
15335
17088
  History,
@@ -15340,7 +17093,7 @@ User message:
15340
17093
  toolStream: state.toolStream,
15341
17094
  setSuggestions,
15342
17095
  autonomyMode: autonomyLive,
15343
- autoSubmitCountdown: nextStepsAutoSubmitCountdown
17096
+ multiDiffSummaryThreshold: state.settingsPicker.multiDiffSummaryThreshold
15344
17097
  }
15345
17098
  ),
15346
17099
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexShrink: 0, ref: bottomRegionRef, children: [
@@ -15430,7 +17183,10 @@ User message:
15430
17183
  logLevel: state.settingsPicker.logLevel,
15431
17184
  auditLevel: state.settingsPicker.auditLevel,
15432
17185
  indexOnStart: state.settingsPicker.indexOnStart,
17186
+ multiDiffSummaryThreshold: state.settingsPicker.multiDiffSummaryThreshold,
15433
17187
  thinkingWord: state.settingsPicker.thinkingWord,
17188
+ thinkingWordEditing: state.settingsPicker.thinkingWordEditing,
17189
+ thinkingWordDraft: state.settingsPicker.thinkingWordDraft,
15434
17190
  maxIterations: state.settingsPicker.maxIterations,
15435
17191
  autoProceedMaxIterations: state.settingsPicker.autoProceedMaxIterations,
15436
17192
  enhanceDelayMs: state.settingsPicker.enhanceDelayMs,
@@ -15443,6 +17199,7 @@ User message:
15443
17199
  reasoningPreserve: state.settingsPicker.reasoningPreserve,
15444
17200
  cacheTtl: state.settingsPicker.cacheTtl,
15445
17201
  configScope: state.settingsPicker.configScope,
17202
+ filter: state.settingsPicker.filter,
15446
17203
  hint: state.settingsPicker.hint
15447
17204
  }
15448
17205
  ) : null,
@@ -15601,7 +17358,7 @@ User message:
15601
17358
  model: `${liveProvider}/${liveModel}`,
15602
17359
  version: appVersion,
15603
17360
  state: state.status,
15604
- thinkingWord: liveThinkingWord,
17361
+ thinkingWord: displayThinkingWord,
15605
17362
  tokenCounter,
15606
17363
  hint: renderRunningTools(state.runningTools) || state.hint,
15607
17364
  queueCount: state.queue.length,
@@ -15669,7 +17426,13 @@ User message:
15669
17426
  elapsedMs: state.autoPhase.elapsedMs,
15670
17427
  nowTick
15671
17428
  }
15672
- ) : state.sddBoard?.monitorOpen ? /* @__PURE__ */ jsx(SddBoardOverlay, { snapshot: state.sddBoard.snapshot }) : state.worktreeMonitorOpen ? /* @__PURE__ */ jsx(
17429
+ ) : state.sddBoard?.monitorOpen ? /* @__PURE__ */ jsx(
17430
+ SddBoardOverlay,
17431
+ {
17432
+ snapshot: state.sddBoard.snapshot,
17433
+ focusColumn: state.sddBoard.focusColumn ?? null
17434
+ }
17435
+ ) : state.worktreeMonitorOpen ? /* @__PURE__ */ jsx(
15673
17436
  WorktreeMonitor,
15674
17437
  {
15675
17438
  worktrees: state.worktrees,
@@ -16069,6 +17832,13 @@ async function runTui(opts) {
16069
17832
  };
16070
17833
  opts.requestExit = requestExit;
16071
17834
  let instance;
17835
+ const clearTerminal = () => {
17836
+ try {
17837
+ instance?.clear();
17838
+ stdout.write("\x1B[2J\x1B[3J\x1B[H");
17839
+ } catch {
17840
+ }
17841
+ };
16072
17842
  try {
16073
17843
  instance = render(
16074
17844
  React5.createElement(App, {
@@ -16104,6 +17874,7 @@ async function runTui(opts) {
16104
17874
  director: opts.director ?? null,
16105
17875
  fleetRoster: opts.fleetRoster,
16106
17876
  onClearHistory: opts.onClearHistory ? (dispatch) => opts.onClearHistory?.(dispatch) : void 0,
17877
+ clearTerminal,
16107
17878
  fleetStreamController: opts.fleetStreamController,
16108
17879
  interruptController: opts.interruptController,
16109
17880
  enhanceController: opts.enhanceController,