@wrongstack/tui 0.267.0 → 0.269.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { writeErr, resolveProjectDir, wstackGlobalRoot, GlobalMailbox, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, expectDefined as expectDefined$1, projectSlug, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, buildChildEnv } from '@wrongstack/core';
1
+ import { writeErr, resolveProjectDir, wstackGlobalRoot, createHqPublisherFromEnv, GlobalMailbox, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, expectDefined as expectDefined$1, projectSlug, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, buildChildEnv } from '@wrongstack/core';
2
2
  export { buildGoalPreamble } from '@wrongstack/core';
3
3
  import { Box as Box$1, useInput, useStdin, useStdout, Text as Text$1, render, useApp, measureElement, Static } from 'ink';
4
4
  import { randomUUID } from 'crypto';
@@ -88,27 +88,46 @@ var Box = forwardRef(function Box2({ borderColor, backgroundColor, ...rest }, re
88
88
  }
89
89
  );
90
90
  });
91
+ function snapshotTokenCounter(tokenCounter) {
92
+ return {
93
+ usage: tokenCounter.total(),
94
+ currentRequest: tokenCounter.currentRequestTokens(),
95
+ cost: tokenCounter.estimateCost(),
96
+ cacheStats: tokenCounter.cacheStats()
97
+ };
98
+ }
91
99
  function useTokenCounterRefresh(tokenCounter, events) {
92
100
  const [data, setData] = useState(
93
- () => tokenCounter ? {
94
- usage: tokenCounter.total(),
95
- cost: tokenCounter.estimateCost(),
96
- cacheStats: tokenCounter.cacheStats()
97
- } : void 0
101
+ () => tokenCounter ? snapshotTokenCounter(tokenCounter) : void 0
98
102
  );
99
103
  useEffect(() => {
100
- if (!tokenCounter || !events) return;
104
+ if (!tokenCounter) {
105
+ setData(void 0);
106
+ return;
107
+ }
108
+ const snapshot = () => snapshotTokenCounter(tokenCounter);
109
+ setData(snapshot());
110
+ if (!events) return;
101
111
  const off = events.on("token.accounted", () => {
102
- setData({
103
- usage: tokenCounter.total(),
104
- cost: tokenCounter.estimateCost(),
105
- cacheStats: tokenCounter.cacheStats()
106
- });
112
+ setData(snapshot());
107
113
  });
108
114
  return off;
109
115
  }, [tokenCounter, events]);
110
116
  return data;
111
117
  }
118
+
119
+ // src/thinking-word.ts
120
+ var DEFAULT_TUI_THINKING_WORD = "thinking";
121
+ var MAX_TUI_THINKING_WORD_LENGTH = 16;
122
+ function normalizeTuiThinkingWord(value) {
123
+ if (typeof value !== "string") return DEFAULT_TUI_THINKING_WORD;
124
+ const word = value.trim();
125
+ if (word.length === 0 || word.length > MAX_TUI_THINKING_WORD_LENGTH) {
126
+ return DEFAULT_TUI_THINKING_WORD;
127
+ }
128
+ if (!/^[\p{L}\p{N}_-]+$/u.test(word)) return DEFAULT_TUI_THINKING_WORD;
129
+ return word;
130
+ }
112
131
  function chipExpired(meta, now = Date.now()) {
113
132
  if (meta.expiresIn == null) return false;
114
133
  return now >= meta.shownAt + meta.expiresIn * 6e4;
@@ -151,10 +170,23 @@ var COMPACT_THRESHOLD = 50;
151
170
  var COMFORTABLE_THRESHOLD = 90;
152
171
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
153
172
  var SPINNER_INTERVAL_MS = 250;
173
+ function tokenDisplayTotals(usage, currentRequest) {
174
+ const usageInput = usage ? usage.input + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0) : 0;
175
+ const usageOutput = usage?.output ?? 0;
176
+ const fallbackInput = currentRequest ? currentRequest.input + currentRequest.cacheRead : 0;
177
+ return {
178
+ input: usageInput > 0 ? usageInput : fallbackInput,
179
+ output: usageOutput
180
+ };
181
+ }
182
+ function hasTokenDisplay(tokens) {
183
+ return tokens.input > 0 || tokens.output > 0;
184
+ }
154
185
  function StatusBar({
155
186
  model,
156
187
  version,
157
188
  state,
189
+ thinkingWord,
158
190
  tokenCounter,
159
191
  hint,
160
192
  queueCount = 0,
@@ -175,6 +207,7 @@ function StatusBar({
175
207
  context,
176
208
  contextStrategy,
177
209
  hiddenItems,
210
+ mode = "detailed",
178
211
  events,
179
212
  eternalStage,
180
213
  goalSummary,
@@ -207,6 +240,8 @@ function StatusBar({
207
240
  const hiddenSet = new Set(hiddenItems);
208
241
  const tokenData = useTokenCounterRefresh(tokenCounter, events);
209
242
  const usage = tokenData?.usage;
243
+ const displayTokens = tokenDisplayTotals(usage, tokenData?.currentRequest);
244
+ const showTokenDisplay = hasTokenDisplay(displayTokens);
210
245
  const cost = tokenData?.cost;
211
246
  const cache2 = tokenData?.cacheStats;
212
247
  const [elapsedMs, setElapsedMs] = useState(startedAt ? Date.now() - startedAt : 0);
@@ -225,7 +260,7 @@ function StatusBar({
225
260
  return () => clearInterval(t);
226
261
  }, [state]);
227
262
  const spinner = expectDefined$1(SPINNER_FRAMES[spinnerIdx]);
228
- const { label: stateLabel, color: stateColor } = stateChip(state, fleet?.running ?? 0);
263
+ const { label: stateLabel, color: stateColor } = stateChip(state, fleet?.running ?? 0, thinkingWord);
229
264
  const statePrefix = state === "idle" || state === "aborting" ? "\u25CF" : spinner;
230
265
  const thinking = state === "running" || state === "streaming";
231
266
  const hasAutoProceed = autoProceedCountdown != null && autoProceedCountdown > 0;
@@ -238,6 +273,78 @@ function StatusBar({
238
273
  const countdownColor = nextStepsAutoSubmitCountdown != null ? nextStepsAutoSubmitCountdown > 20 ? "green" : nextStepsAutoSubmitCountdown > 10 ? "yellow" : "red" : "green";
239
274
  const hasTaskActivity = tasks && (tasks.pending > 0 || tasks.inProgress > 0 || tasks.completed > 0 || tasks.blocked > 0 || tasks.failed > 0);
240
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;
276
+ 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}` : ""
282
+ ].filter(Boolean);
283
+ if (mode === "minimum") {
284
+ const ctxMax = context?.max;
285
+ const ctxRatio = context && ctxMax ? context.used / ctxMax : void 0;
286
+ const ctxClampedRatio = ctxRatio !== void 0 ? Math.min(ctxRatio, 1) : void 0;
287
+ const ctxPctText = ctxRatio !== void 0 ? `${Math.min(Math.round(ctxRatio * 100), 100)}%` : void 0;
288
+ return /* @__PURE__ */ jsx(
289
+ Box,
290
+ {
291
+ flexDirection: "column",
292
+ paddingX: 1,
293
+ borderStyle: "single",
294
+ borderTop: true,
295
+ borderBottom: false,
296
+ borderLeft: false,
297
+ borderRight: false,
298
+ children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
299
+ version ? /* @__PURE__ */ jsxs(Text, { children: [
300
+ /* @__PURE__ */ jsx(Text, { color: "blue", bold: true, children: "WS" }),
301
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
302
+ " v",
303
+ version
304
+ ] })
305
+ ] }) : 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: [
308
+ statePrefix,
309
+ " ",
310
+ 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: [
315
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
316
+ /* @__PURE__ */ jsxs(Text, { color: ctxClampedRatio < 0.6 ? "green" : ctxClampedRatio < 0.75 ? "yellow" : "red", children: [
317
+ "ctx ",
318
+ ctxPctText,
319
+ "/",
320
+ fmtTok(ctxMax)
321
+ ] })
322
+ ] }) : null,
323
+ showTokenDisplay ? /* @__PURE__ */ jsxs(Fragment, { children: [
324
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
325
+ /* @__PURE__ */ jsxs(Text, { children: [
326
+ "\u2191 ",
327
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(displayTokens.input) }),
328
+ " \u2193",
329
+ " ",
330
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(displayTokens.output) })
331
+ ] })
332
+ ] }) : null,
333
+ cost && cost.total > 0 && !hiddenSet.has("cost") ? /* @__PURE__ */ jsxs(Fragment, { children: [
334
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
335
+ /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
336
+ "$",
337
+ cost.total.toFixed(4)
338
+ ] })
339
+ ] }) : null,
340
+ minimalWorkParts.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
341
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
342
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: minimalWorkParts.slice(0, 3).join(" \xB7 ") })
343
+ ] }) : null
344
+ ] })
345
+ }
346
+ );
347
+ }
241
348
  return /* @__PURE__ */ jsxs(
242
349
  Box,
243
350
  {
@@ -290,6 +397,8 @@ function StatusBar({
290
397
  renderMeter(clampedRatio, 8),
291
398
  " ",
292
399
  pctText,
400
+ "/",
401
+ fmtTok(context.max),
293
402
  contextStrategy ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
294
403
  " [",
295
404
  contextStrategy,
@@ -298,15 +407,14 @@ function StatusBar({
298
407
  ] });
299
408
  })()
300
409
  ] }) : null,
301
- usage && isComfortable ? /* @__PURE__ */ jsxs(Fragment, { children: [
410
+ showTokenDisplay ? /* @__PURE__ */ jsxs(Fragment, { children: [
302
411
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
303
412
  /* @__PURE__ */ jsxs(Text, { children: [
304
- "\u2191",
413
+ "\u2191 ",
414
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(displayTokens.input) }),
415
+ " \u2193",
305
416
  " ",
306
- /* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(usage.input + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0)) }),
307
- " ",
308
- "\u2193 ",
309
- /* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(usage.output) })
417
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(displayTokens.output) })
310
418
  ] })
311
419
  ] }) : null,
312
420
  cache2 && cache2.hitRatio > 0 && isComfortable ? /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -820,7 +928,7 @@ function statusBarModelSpan(opts) {
820
928
  col += `WS v${opts.version}`.length + SB_GAP;
821
929
  col += 1 + SB_GAP;
822
930
  }
823
- const { label } = stateChip(opts.state, opts.fleetRunning ?? 0);
931
+ const { label } = stateChip(opts.state, opts.fleetRunning ?? 0, opts.thinkingWord);
824
932
  col += 2 + label.length + SB_GAP;
825
933
  col += 1 + SB_GAP;
826
934
  return { start: col, len: opts.model.length };
@@ -838,13 +946,13 @@ function statusBarTodosSpan() {
838
946
  const LABEL_MAX = 20;
839
947
  return { start: SB_PADX, len: LABEL_MAX };
840
948
  }
841
- function stateChip(state, fleetRunning) {
949
+ function stateChip(state, fleetRunning, thinkingWord) {
842
950
  if (state === "idle" && fleetRunning > 0) {
843
951
  return { label: `agents \u25B6${fleetRunning}`, color: "magenta" };
844
952
  }
845
953
  if (state === "idle") return { label: "idle", color: "cyan" };
846
954
  if (state === "aborting") return { label: "aborting\u2026", color: "yellow" };
847
- return { label: "thinking\u2026", color: "green" };
955
+ return { label: `${normalizeTuiThinkingWord(thinkingWord)}\u2026`, color: "green" };
848
956
  }
849
957
  var WAVE_COLORS = [
850
958
  "#f38ba8",
@@ -1151,6 +1259,36 @@ function FleetMonitor({
1151
1259
  ] }) : null
1152
1260
  ] });
1153
1261
  }
1262
+ var TOOL_GLYPHS = {
1263
+ file: "\u25A4",
1264
+ edit: "\u270E",
1265
+ search: "\u2315",
1266
+ folder: "\u25A3",
1267
+ terminal: "\u2318",
1268
+ web: "\u25C8",
1269
+ git: "\u2387",
1270
+ tree: "\u2630",
1271
+ code: "\u2699",
1272
+ test: "\u2697",
1273
+ package: "\u2B22",
1274
+ document: "\u2637",
1275
+ scaffold: "\u2731",
1276
+ todo: "\u2610",
1277
+ plan: "\u2756",
1278
+ task: "\u25AA",
1279
+ meta: "\u274F",
1280
+ index: "\u229B",
1281
+ json: "\u2317",
1282
+ diff: "\u2206",
1283
+ logs: "\u2261",
1284
+ settings: "\u2699",
1285
+ brain: "\u2726",
1286
+ fallback: "\u2022"
1287
+ };
1288
+ function getToolVisual(name) {
1289
+ const id = getToolIcon(name);
1290
+ return { glyph: TOOL_GLYPHS[id], color: TOOL_ICON_CONFIG[id].color };
1291
+ }
1154
1292
  var STATUS2 = {
1155
1293
  idle: { icon: "\u25CB", color: "gray" },
1156
1294
  running: { icon: "\u25B6", color: "yellow" },
@@ -1159,22 +1297,19 @@ var STATUS2 = {
1159
1297
  timeout: { icon: "\u23F1", color: "yellow" },
1160
1298
  stopped: { icon: "\u2298", color: "gray" }
1161
1299
  };
1162
- function isTerminal(status) {
1300
+ var IDLE_HIDE_MS = 6e4;
1301
+ var EMPTY_AGENTS_CLOSE_DELAY_MS = 7500;
1302
+ function isTerminalAgentStatus(status) {
1163
1303
  return status === "success" || status === "failed" || status === "timeout" || status === "stopped";
1164
1304
  }
1165
- var IDLE_HIDE_MS = 6e4;
1166
- function selectLiveAgents(all, now, idleHideMs = IDLE_HIDE_MS) {
1167
- const visible = all.filter((e) => {
1168
- if (isTerminal(e.status)) return false;
1169
- if (e.status === "running") return true;
1170
- return now - e.lastEventAt < idleHideMs;
1171
- });
1172
- return visible.sort((a, b) => {
1173
- if (a.status === "running" && b.status !== "running") return -1;
1174
- if (a.status !== "running" && b.status === "running") return 1;
1175
- if (a.status === "running") return a.startedAt - b.startedAt;
1176
- return b.lastEventAt - a.lastEventAt;
1177
- });
1305
+ function isLeaderEntry(entry) {
1306
+ return entry.id === "leader" || entry.name === "LEADER";
1307
+ }
1308
+ function selectLiveAgents(all, _now, _idleHideMs = IDLE_HIDE_MS) {
1309
+ const leader = all.find(isLeaderEntry);
1310
+ const activeSubagents = all.filter((entry) => !isLeaderEntry(entry) && !isTerminalAgentStatus(entry.status));
1311
+ const showLeader = leader !== void 0 && (leader.status !== "idle" || activeSubagents.length > 0);
1312
+ return all.filter((entry) => isLeaderEntry(entry) ? showLeader : activeSubagents.some((active) => active.id === entry.id));
1178
1313
  }
1179
1314
  function fmtTokens2(n) {
1180
1315
  if (n < 1e3) return String(n);
@@ -1186,6 +1321,86 @@ function snippet(s2, max = 72) {
1186
1321
  if (oneLine2.length <= max) return oneLine2;
1187
1322
  return `${oneLine2.slice(0, max - 1)}\u2026`;
1188
1323
  }
1324
+ function fmtShortDuration(ms) {
1325
+ if (ms < 1e3) return `${Math.max(0, Math.round(ms))}ms`;
1326
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(ms < 1e4 ? 1 : 0)}s`;
1327
+ const m = Math.floor(ms / 6e4);
1328
+ const s2 = Math.floor(ms % 6e4 / 1e3);
1329
+ return `${m}m${s2.toString().padStart(2, "0")}s`;
1330
+ }
1331
+ function fmtSignedTokens(n) {
1332
+ return n <= 0 ? "0" : fmtTokens2(n);
1333
+ }
1334
+ function fmtOptionalTimestamp(ms) {
1335
+ if (!ms || ms <= 0) return "unknown";
1336
+ return new Date(ms).toLocaleTimeString("en-US", { hour12: false });
1337
+ }
1338
+ function formatContextRunway(tokens, maxTokens) {
1339
+ if (!tokens || !maxTokens || maxTokens <= 0) return "ctx unknown";
1340
+ const left = Math.max(0, maxTokens - tokens);
1341
+ return `${fmtTokens2(tokens)}/${fmtTokens2(maxTokens)} \xB7 ${fmtSignedTokens(left)} free`;
1342
+ }
1343
+ function formatRecentToolChip(tool) {
1344
+ const status = tool.ok === false ? "\u2717" : "\u2713";
1345
+ const duration = typeof tool.durationMs === "number" ? ` ${fmtShortDuration(tool.durationMs)}` : "";
1346
+ const lines = typeof tool.outputLines === "number" && tool.outputLines > 0 ? ` ${tool.outputLines}L` : "";
1347
+ const bytes = typeof tool.outputBytes === "number" && tool.outputBytes > 0 ? ` ${fmtTokens2(tool.outputBytes)}B` : "";
1348
+ return `${status} ${tool.name}${duration}${lines}${bytes}`;
1349
+ }
1350
+ function formatAgentDetailHeader(entry) {
1351
+ return entry.name || entry.id;
1352
+ }
1353
+ function agentRisk(entry) {
1354
+ const pct = entry.ctxPct ?? 0;
1355
+ if (entry.budgetWarning || entry.failureReason || pct >= 0.9) return "critical";
1356
+ if (pct >= 0.75 || (entry.extensions ?? 0) > 0) return "hot";
1357
+ if (entry.status === "running" || pct >= 0.55) return "busy";
1358
+ return "calm";
1359
+ }
1360
+ function riskMeta(risk) {
1361
+ switch (risk) {
1362
+ case "critical":
1363
+ return { icon: "\u25C6", color: "red", label: "critical" };
1364
+ case "hot":
1365
+ return { icon: "\u25B2", color: "yellow", label: "hot" };
1366
+ case "busy":
1367
+ return { icon: "\u25CF", color: "cyan", label: "busy" };
1368
+ case "calm":
1369
+ return { icon: "\u25CB", color: "green", label: "calm" };
1370
+ }
1371
+ }
1372
+ function currentAction(entry, now) {
1373
+ if (entry.currentTool) return `\u2192 ${entry.currentTool.name} ${fmtShortDuration(now - entry.currentTool.startedAt)}`;
1374
+ if (entry.status === "running") return "thinking";
1375
+ const last = entry.recentTools[entry.recentTools.length - 1];
1376
+ if (last) return `last ${last.name}`;
1377
+ const msg = entry.recentMessages[entry.recentMessages.length - 1];
1378
+ if (msg) return `msg ${snippet(msg.text, 34)}`;
1379
+ return "standing by";
1380
+ }
1381
+ function selectAgentDetail(live, selectedId) {
1382
+ return live.find((entry) => entry.id === selectedId) ?? live.find(isLeaderEntry) ?? live[0];
1383
+ }
1384
+ function nextEmptyAgentsCloseStartedAt(liveCount, now, currentStartedAt) {
1385
+ if (liveCount > 0) return void 0;
1386
+ return currentStartedAt ?? now;
1387
+ }
1388
+ function shouldCloseEmptyAgentsMonitor(liveCount, now, emptyStartedAt, delayMs = EMPTY_AGENTS_CLOSE_DELAY_MS) {
1389
+ return liveCount === 0 && emptyStartedAt !== void 0 && now - emptyStartedAt >= delayMs;
1390
+ }
1391
+ function selectHotAgent(entries) {
1392
+ const riskScore = { critical: 3, hot: 2, busy: 1, calm: 0 };
1393
+ return [...entries].sort((a, b) => {
1394
+ const ar = riskScore[agentRisk(a)];
1395
+ const br = riskScore[agentRisk(b)];
1396
+ if (br !== ar) return br - ar;
1397
+ const bp = b.ctxPct ?? 0;
1398
+ const ap = a.ctxPct ?? 0;
1399
+ if (bp !== ap) return bp - ap;
1400
+ if (b.toolCalls !== a.toolCalls) return b.toolCalls - a.toolCalls;
1401
+ return b.lastEventAt - a.lastEventAt;
1402
+ }).at(0);
1403
+ }
1189
1404
  function ContextBar({
1190
1405
  pct,
1191
1406
  tokens,
@@ -1214,10 +1429,13 @@ function AgentRow({
1214
1429
  const s2 = STATUS2[entry.status];
1215
1430
  const elapsed = entry.status === "running" ? fmtElapsed(Math.max(0, now - entry.startedAt)) : entry.status;
1216
1431
  const modelLabel = fmtModelLabel(entry.provider, entry.model);
1432
+ const activity = sparkline(bucketActivity(entry.recentTools, now, 10, 3e3));
1433
+ const risk = riskMeta(agentRisk(entry));
1217
1434
  const ctxCostStr = entry.ctxCost !== void 0 && entry.ctxCost > 0 ? ` ctx ${entry.ctxCost.toFixed(4)}` : "";
1218
1435
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1219
1436
  /* @__PURE__ */ jsx(Text, { color: selected ? "magenta" : "gray", children: selected ? "\u25B6" : " " }),
1220
1437
  /* @__PURE__ */ jsx(Text, { color: s2.color, bold: true, children: s2.icon }),
1438
+ /* @__PURE__ */ jsx(Text, { color: risk.color, children: risk.icon }),
1221
1439
  /* @__PURE__ */ jsx(Text, { bold: selected, ...selected ? { color: "magenta" } : {}, children: entry.name }),
1222
1440
  modelLabel ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: modelLabel }) : null,
1223
1441
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
@@ -1227,17 +1445,10 @@ function AgentRow({
1227
1445
  entry.toolCalls,
1228
1446
  "t"
1229
1447
  ] }),
1448
+ activity ? /* @__PURE__ */ jsx(Text, { color: "green", children: activity }) : null,
1230
1449
  entry.ctxPct !== void 0 ? /* @__PURE__ */ jsx(ContextBar, { pct: entry.ctxPct, tokens: entry.ctxTokens, maxTokens: entry.ctxMaxTokens }) : null,
1231
1450
  ctxCostStr ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: ctxCostStr }) : null,
1232
- entry.status === "running" && entry.currentTool ? /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
1233
- "\u2192 ",
1234
- entry.currentTool.name,
1235
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1236
- " (",
1237
- Math.max(0, now - entry.currentTool.startedAt),
1238
- "ms)"
1239
- ] })
1240
- ] }) : null,
1451
+ /* @__PURE__ */ jsx(Text, { color: entry.currentTool ? "cyan" : "gray", children: currentAction(entry, now) }),
1241
1452
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: elapsed }),
1242
1453
  entry.extensions && entry.extensions > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1243
1454
  "\u26A1\xD7",
@@ -1257,162 +1468,280 @@ function AgentDetail({
1257
1468
  const lastTool = entry.recentTools[entry.recentTools.length - 1];
1258
1469
  const lastMessage = entry.recentMessages[entry.recentMessages.length - 1];
1259
1470
  const streamTail = entry.streamingText ? snippet(entry.streamingText.slice(-160)) : "";
1260
- const modelLabel = fmtModelLabel(entry.provider, entry.model);
1261
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingLeft: 4, borderStyle: "single", borderColor: "magenta", borderLeft: true, children: [
1262
- spark || lastTool ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1263
- /* @__PURE__ */ jsx(Text, { color: "green", children: spark || "" }),
1264
- lastTool ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1265
- "last: ",
1266
- lastTool.name,
1267
- typeof lastTool.durationMs === "number" ? ` ${lastTool.durationMs}ms` : "",
1268
- lastTool.ok === false ? " \u2717" : ""
1269
- ] }) : null
1270
- ] }) : null,
1271
- !modelLabel && (entry.provider || entry.model) ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1272
- "provider: ",
1273
- entry.provider || "(leader)",
1274
- " \xB7 model: ",
1275
- entry.model || "\u2014"
1276
- ] }) }) : null,
1277
- entry.cost > 0 || entry.ctxCost && entry.ctxCost > 0 ? /* @__PURE__ */ jsxs(Box, { children: [
1278
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "cost: " }),
1279
- entry.cost > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
1280
- "$",
1281
- entry.cost.toFixed(4),
1282
- " total"
1283
- ] }) : null,
1284
- entry.cost > 0 && entry.ctxCost && entry.ctxCost > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }) : null,
1285
- entry.ctxCost && entry.ctxCost > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1286
- "$",
1287
- entry.ctxCost.toFixed(4),
1288
- " ctx"
1289
- ] }) : null
1290
- ] }) : null,
1291
- entry.status === "running" && streamTail ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1292
- ">",
1293
- " ",
1294
- streamTail
1295
- ] }) }) : null,
1296
- (entry.status !== "running" || !streamTail) && lastMessage ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1297
- "msg: ",
1298
- snippet(lastMessage.text)
1299
- ] }) }) : null,
1300
- entry.budgetWarning ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1301
- "\u26A1 ",
1302
- entry.budgetWarning.kind,
1303
- " ",
1304
- entry.budgetWarning.used,
1305
- "/",
1306
- entry.budgetWarning.limit,
1307
- " \u2014 extending"
1308
- ] }) }) : null,
1309
- entry.failureReason && entry.status !== "success" ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: "red", children: [
1310
- "\u2717 ",
1311
- entry.failureReason
1312
- ] }) }) : null
1313
- ] });
1471
+ const risk = riskMeta(agentRisk(entry));
1472
+ const ctxLine = formatContextRunway(entry.ctxTokens, entry.ctxMaxTokens);
1473
+ const modelLabel = fmtModelLabel(entry.provider, entry.model) || [entry.provider, entry.model].filter(Boolean).join("/");
1474
+ return /* @__PURE__ */ jsx(Box, { alignSelf: "stretch", flexDirection: "column", width: "100%", flexGrow: 1, children: /* @__PURE__ */ jsxs(
1475
+ Box,
1476
+ {
1477
+ alignSelf: "stretch",
1478
+ flexDirection: "column",
1479
+ width: "100%",
1480
+ flexGrow: 1,
1481
+ paddingX: 1,
1482
+ borderStyle: "single",
1483
+ borderColor: "magenta",
1484
+ children: [
1485
+ /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 1, children: /* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: formatAgentDetailHeader(entry) }) }),
1486
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1487
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "id" }),
1488
+ /* @__PURE__ */ jsx(Text, { children: entry.id }),
1489
+ modelLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [
1490
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 model" }),
1491
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: modelLabel })
1492
+ ] }) : null,
1493
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 status" }),
1494
+ /* @__PURE__ */ jsxs(Text, { color: STATUS2[entry.status].color, children: [
1495
+ STATUS2[entry.status].icon,
1496
+ " ",
1497
+ entry.status
1498
+ ] })
1499
+ ] }),
1500
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1501
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "runtime" }),
1502
+ /* @__PURE__ */ jsx(Text, { children: fmtElapsed(Math.max(0, now - entry.startedAt)) }),
1503
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 started" }),
1504
+ /* @__PURE__ */ jsx(Text, { children: fmtOptionalTimestamp(entry.startedAt) }),
1505
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 last event" }),
1506
+ /* @__PURE__ */ jsxs(Text, { children: [
1507
+ fmtShortDuration(Math.max(0, now - entry.lastEventAt)),
1508
+ " ago"
1509
+ ] }),
1510
+ entry.extensions && entry.extensions > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1511
+ "\xB7 extensions \u26A1\xD7",
1512
+ entry.extensions
1513
+ ] }) : null
1514
+ ] }),
1515
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1516
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "throughput" }),
1517
+ /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
1518
+ entry.iterations,
1519
+ " iterations"
1520
+ ] }),
1521
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
1522
+ /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
1523
+ entry.toolCalls,
1524
+ " tools"
1525
+ ] }),
1526
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 current" }),
1527
+ /* @__PURE__ */ jsx(Text, { color: entry.currentTool ? "cyan" : "gray", children: currentAction(entry, now) })
1528
+ ] }),
1529
+ spark || lastTool ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1530
+ /* @__PURE__ */ jsx(Text, { color: "green", children: spark || "" }),
1531
+ lastTool ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1532
+ "last: ",
1533
+ lastTool.name,
1534
+ typeof lastTool.durationMs === "number" ? ` ${lastTool.durationMs}ms` : "",
1535
+ lastTool.ok === false ? " \u2717" : ""
1536
+ ] }) : null
1537
+ ] }) : null,
1538
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1539
+ /* @__PURE__ */ jsxs(Text, { color: risk.color, children: [
1540
+ risk.icon,
1541
+ " ",
1542
+ risk.label
1543
+ ] }),
1544
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "ctx" }),
1545
+ /* @__PURE__ */ jsx(Text, { color: risk.color, children: ctxLine }),
1546
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1547
+ "idle ",
1548
+ fmtShortDuration(Math.max(0, now - entry.lastEventAt))
1549
+ ] })
1550
+ ] }),
1551
+ entry.cost > 0 || entry.ctxCost && entry.ctxCost > 0 ? /* @__PURE__ */ jsxs(Box, { children: [
1552
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "cost: " }),
1553
+ entry.cost > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
1554
+ "$",
1555
+ entry.cost.toFixed(4),
1556
+ " total"
1557
+ ] }) : null,
1558
+ entry.cost > 0 && entry.ctxCost && entry.ctxCost > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }) : null,
1559
+ entry.ctxCost && entry.ctxCost > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1560
+ "$",
1561
+ entry.ctxCost.toFixed(4),
1562
+ " ctx"
1563
+ ] }) : null
1564
+ ] }) : null,
1565
+ entry.transcriptPath ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1566
+ "transcript: ",
1567
+ snippet(entry.transcriptPath, 120)
1568
+ ] }) }) : null,
1569
+ entry.recentTools.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1570
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "recent" }),
1571
+ entry.recentTools.slice(-4).map((tool, i) => {
1572
+ const visual = getToolVisual(tool.name);
1573
+ return (
1574
+ // biome-ignore lint/suspicious/noArrayIndexKey: recent tool entries do not carry stable ids.
1575
+ /* @__PURE__ */ jsx(Text, { color: tool.ok === false ? "red" : visual.color, children: `\u2039${visual.glyph} ${formatRecentToolChip(tool)}\u203A` }, `${tool.name}-${tool.at}-${i}`)
1576
+ );
1577
+ })
1578
+ ] }) : null,
1579
+ entry.status === "running" && streamTail ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1580
+ ">",
1581
+ " ",
1582
+ streamTail
1583
+ ] }) }) : null,
1584
+ (entry.status !== "running" || !streamTail) && lastMessage ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1585
+ "msg: ",
1586
+ snippet(lastMessage.text)
1587
+ ] }) }) : null,
1588
+ entry.budgetWarning ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1589
+ "\u26A1 ",
1590
+ entry.budgetWarning.kind,
1591
+ " ",
1592
+ entry.budgetWarning.used,
1593
+ "/",
1594
+ entry.budgetWarning.limit,
1595
+ " \u2014 extending"
1596
+ ] }) }) : null,
1597
+ entry.failureReason && entry.status !== "success" ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: "red", children: [
1598
+ "\u2717 ",
1599
+ entry.failureReason
1600
+ ] }) }) : null
1601
+ ]
1602
+ }
1603
+ ) });
1314
1604
  }
1315
1605
  function AgentsMonitor({
1316
1606
  entries,
1317
1607
  totalCost,
1318
1608
  leaderCost = 0,
1319
1609
  totalTokens,
1320
- nowTick
1610
+ nowTick,
1611
+ onClose
1321
1612
  }) {
1322
1613
  const all = Object.values(entries);
1323
1614
  const grandCost = leaderCost + totalCost;
1324
- const live = useMemo(() => selectLiveAgents(all, nowTick), [all, nowTick]);
1325
- const [selectedIndex, setSelectedIndex] = useState(0);
1326
- const safeIndex = Math.min(selectedIndex, Math.max(0, live.length - 1));
1615
+ const live = useMemo(() => selectLiveAgents(all), [all, nowTick]);
1616
+ const [selectedId, setSelectedId] = useState(void 0);
1617
+ const [emptyAgentsCloseStartedAt, setEmptyAgentsCloseStartedAt] = useState(void 0);
1618
+ useEffect(() => {
1619
+ const nextStartedAt = nextEmptyAgentsCloseStartedAt(live.length, nowTick, emptyAgentsCloseStartedAt);
1620
+ if (nextStartedAt !== emptyAgentsCloseStartedAt) setEmptyAgentsCloseStartedAt(nextStartedAt);
1621
+ if (shouldCloseEmptyAgentsMonitor(live.length, nowTick, nextStartedAt)) onClose?.();
1622
+ }, [emptyAgentsCloseStartedAt, live.length, nowTick, onClose]);
1623
+ const selected = selectAgentDetail(live, selectedId);
1624
+ const selectedIndex = selected ? live.findIndex((entry) => entry.id === selected.id) : -1;
1327
1625
  useInput((_input, key) => {
1626
+ if (live.length === 0) return;
1328
1627
  if (key.upArrow) {
1329
- setSelectedIndex((prev) => Math.max(0, prev - 1));
1628
+ const next = Math.max(0, selectedIndex - 1);
1629
+ setSelectedId(live[next]?.id);
1330
1630
  } else if (key.downArrow) {
1331
- setSelectedIndex((prev) => Math.min(live.length - 1, prev + 1));
1631
+ const next = Math.min(live.length - 1, selectedIndex + 1);
1632
+ setSelectedId(live[next]?.id);
1332
1633
  }
1333
1634
  });
1334
1635
  const running = live.filter((e) => e.status === "running").length;
1335
1636
  const totalDone = all.filter((e) => e.status === "success").length;
1336
1637
  const totalFailed = all.filter((e) => e.status === "failed" || e.status === "timeout").length;
1337
- const hiddenIdle = all.filter(
1638
+ const staleIdle = all.filter(
1338
1639
  (e) => e.status === "idle" && nowTick - e.lastEventAt >= IDLE_HIDE_MS
1339
1640
  ).length;
1340
- const selected = live[safeIndex];
1341
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, children: [
1342
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1343
- /* @__PURE__ */ jsx(Text, { bold: true, color: "magenta", children: "AGENTS \xB7 LIVE" }),
1344
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
1345
- /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1346
- "\u25B6",
1347
- running
1348
- ] }),
1349
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
1350
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "done" }),
1351
- /* @__PURE__ */ jsxs(Text, { color: "green", children: [
1352
- "\u2713",
1353
- totalDone
1354
- ] }),
1355
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
1356
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "failed" }),
1357
- totalFailed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
1358
- "\u2717",
1359
- totalFailed
1360
- ] }) : null,
1361
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 \u2191\u2193 nav \xB7 Ctrl+G / F3 close" })
1362
- ] }),
1363
- live.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1364
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "models" }),
1365
- (() => {
1366
- const seen = /* @__PURE__ */ new Map();
1367
- for (const e of live) {
1368
- if (e.model) seen.set(e.name ?? e.id, `${e.provider ?? "?"}/${e.model}`);
1369
- }
1370
- return [...seen.entries()].slice(0, 4).map(([name, mod]) => /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1371
- name,
1372
- ":",
1373
- mod
1374
- ] }, name));
1375
- })()
1376
- ] }) : null,
1377
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1378
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "shown" }),
1379
- /* @__PURE__ */ jsx(Text, { color: "magenta", children: live.length }),
1380
- totalTokens ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1381
- " ",
1382
- fmtTokens2(totalTokens.input),
1383
- "\u2191 ",
1384
- fmtTokens2(totalTokens.output),
1385
- "\u2193"
1386
- ] }) : null,
1387
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "total" }),
1388
- /* @__PURE__ */ jsxs(Text, { color: "green", bold: true, children: [
1389
- "$",
1390
- grandCost.toFixed(4)
1391
- ] }),
1392
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1393
- "(leader $",
1394
- leaderCost.toFixed(4),
1395
- " \xB7 fleet $",
1396
- totalCost.toFixed(4),
1397
- ")"
1398
- ] }),
1399
- hiddenIdle > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1400
- "\xB7 ",
1401
- hiddenIdle,
1402
- " idle hidden"
1403
- ] }) : null
1404
- ] }),
1405
- live.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No live agents \u2014 spawn with /spawn or /fleet dispatch." }) : null,
1406
- live.map((e) => /* @__PURE__ */ jsx(AgentRow, { entry: e, now: nowTick, selected: e.id === selected?.id }, e.id)),
1407
- selected ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
1408
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, paddingLeft: 2, children: [
1409
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500" }),
1410
- /* @__PURE__ */ jsx(Text, { color: "magenta", children: selected.name }),
1411
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "details \u2500\u2500\u2500" })
1412
- ] }),
1413
- /* @__PURE__ */ jsx(AgentDetail, { entry: selected, now: nowTick })
1414
- ] }) : null
1415
- ] });
1641
+ const hotAgent = selectHotAgent(live);
1642
+ const pressure = live.length > 0 ? live.reduce((max, e) => Math.max(max, e.ctxPct ?? 0), 0) : 0;
1643
+ const toolCalls = live.reduce((sum, e) => sum + e.toolCalls, 0);
1644
+ const iterations = live.reduce((sum, e) => sum + e.iterations, 0);
1645
+ return /* @__PURE__ */ jsxs(
1646
+ Box,
1647
+ {
1648
+ alignSelf: "stretch",
1649
+ flexDirection: "column",
1650
+ width: "100%",
1651
+ borderStyle: "round",
1652
+ borderColor: "magenta",
1653
+ paddingX: 1,
1654
+ flexGrow: 1,
1655
+ children: [
1656
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1657
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "magenta", children: "AGENTS \xB7 LIVE" }),
1658
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
1659
+ /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1660
+ "\u25B6",
1661
+ running
1662
+ ] }),
1663
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
1664
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "done" }),
1665
+ /* @__PURE__ */ jsxs(Text, { color: "green", children: [
1666
+ "\u2713",
1667
+ totalDone
1668
+ ] }),
1669
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
1670
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "failed" }),
1671
+ totalFailed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
1672
+ "\u2717",
1673
+ totalFailed
1674
+ ] }) : null,
1675
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 \u2191\u2193 nav \xB7 Ctrl+G / F3 close" })
1676
+ ] }),
1677
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1678
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "pulse" }),
1679
+ /* @__PURE__ */ jsxs(Text, { color: pressure >= 0.9 ? "red" : pressure >= 0.75 ? "yellow" : "green", children: [
1680
+ "max ctx ",
1681
+ Math.round(pressure * 100),
1682
+ "%"
1683
+ ] }),
1684
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 hot" }),
1685
+ hotAgent ? /* @__PURE__ */ jsxs(Text, { color: riskMeta(agentRisk(hotAgent)).color, children: [
1686
+ hotAgent.name,
1687
+ " ",
1688
+ hotAgent.ctxPct !== void 0 ? `${Math.round(hotAgent.ctxPct * 100)}%` : ""
1689
+ ] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "none" }),
1690
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 throughput" }),
1691
+ /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
1692
+ iterations,
1693
+ "L/",
1694
+ toolCalls,
1695
+ "t"
1696
+ ] })
1697
+ ] }),
1698
+ live.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1699
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "models" }),
1700
+ (() => {
1701
+ const seen = /* @__PURE__ */ new Map();
1702
+ for (const e of live) {
1703
+ if (e.model) seen.set(e.name ?? e.id, `${e.provider ?? "?"}/${e.model}`);
1704
+ }
1705
+ return [...seen.entries()].slice(0, 4).map(([name, mod]) => /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1706
+ name,
1707
+ ":",
1708
+ mod
1709
+ ] }, name));
1710
+ })()
1711
+ ] }) : null,
1712
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
1713
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "shown" }),
1714
+ /* @__PURE__ */ jsx(Text, { color: "magenta", children: live.length }),
1715
+ totalTokens ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1716
+ " ",
1717
+ fmtTokens2(totalTokens.input),
1718
+ "\u2191 ",
1719
+ fmtTokens2(totalTokens.output),
1720
+ "\u2193"
1721
+ ] }) : null,
1722
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "total" }),
1723
+ /* @__PURE__ */ jsxs(Text, { color: "green", bold: true, children: [
1724
+ "$",
1725
+ grandCost.toFixed(4)
1726
+ ] }),
1727
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1728
+ "(leader $",
1729
+ leaderCost.toFixed(4),
1730
+ " \xB7 fleet $",
1731
+ totalCost.toFixed(4),
1732
+ ")"
1733
+ ] }),
1734
+ staleIdle > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1735
+ "\xB7 ",
1736
+ staleIdle,
1737
+ " idle stale"
1738
+ ] }) : null
1739
+ ] }),
1740
+ live.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No live agents \u2014 spawn with /spawn or /fleet dispatch." }) : null,
1741
+ live.map((e) => e.id === selected?.id ? /* @__PURE__ */ jsx(AgentDetail, { entry: e, now: nowTick }, e.id) : /* @__PURE__ */ jsx(AgentRow, { entry: e, now: nowTick, selected: false }, e.id))
1742
+ ]
1743
+ }
1744
+ );
1416
1745
  }
1417
1746
  var AUTONOMY_OPTIONS = [
1418
1747
  {
@@ -1872,25 +2201,121 @@ function FleetPanel({
1872
2201
  ] }) : null
1873
2202
  ] });
1874
2203
  }
1875
- var F_KEY_ENTRIES = [
1876
- { key: 1, label: "Project switcher", action: "projectPickerOpen" },
1877
- { key: 2, label: "Fleet orchestration monitor", action: "toggleMonitor" },
1878
- { key: 3, label: "Agents live monitor", action: "toggleAgentsMonitor" },
1879
- { key: 4, label: "Worktree monitor", action: "toggleWorktreeMonitor" },
1880
- { key: 5, label: "Autonomy settings", action: "togglePlanPanel" },
1881
- { key: 6, label: "Todos monitor overlay", action: "toggleTodosMonitor" },
1882
- { key: 7, label: "Queue panel", action: "toggleQueuePanel" },
1883
- { key: 8, label: "Process list overlay", action: "toggleProcessList" },
1884
- { key: 9, label: "Goal panel", action: "toggleGoalPanel" },
1885
- { key: 10, label: "Live sessions panel", action: "toggleSessionsPanel" },
1886
- { key: 11, label: "Coordinator monitor", action: "toggleCoordinatorMonitor" },
1887
- { key: 12, label: "Status line picker", action: "statuslineOpen" }
2204
+
2205
+ // src/f-key-panels.ts
2206
+ var F_KEY_PANEL_ENTRIES = [
2207
+ {
2208
+ key: 1,
2209
+ label: "Project switcher",
2210
+ action: "projectPickerOpen",
2211
+ helpKeys: "F1 or /project",
2212
+ helpDescription: "project switcher (F1 may open terminal help)"
2213
+ },
2214
+ {
2215
+ key: 2,
2216
+ label: "Fleet orchestration monitor",
2217
+ action: "toggleMonitor",
2218
+ helpKeys: "F2 or /fleet",
2219
+ helpDescription: "fleet monitor (Ctrl+F may be terminal Find)"
2220
+ },
2221
+ {
2222
+ key: 3,
2223
+ label: "Agents live monitor",
2224
+ action: "toggleAgentsMonitor",
2225
+ helpKeys: "F3 or Ctrl+G",
2226
+ helpDescription: "agents live monitor (F3 is safer)"
2227
+ },
2228
+ {
2229
+ key: 4,
2230
+ label: "Worktree monitor",
2231
+ action: "toggleWorktreeMonitor",
2232
+ helpKeys: "F4 or /worktree",
2233
+ helpDescription: "worktree monitor (Ctrl+T may be reserved)"
2234
+ },
2235
+ {
2236
+ key: 5,
2237
+ label: "Plan panel",
2238
+ action: "togglePlanPanel",
2239
+ helpKeys: "F5 or /plan",
2240
+ helpDescription: "plan panel (F5 may be host refresh/run)"
2241
+ },
2242
+ {
2243
+ key: 6,
2244
+ label: "Todos monitor overlay",
2245
+ action: "toggleTodosMonitor",
2246
+ helpKeys: "F6",
2247
+ helpDescription: "todos monitor overlay"
2248
+ },
2249
+ {
2250
+ key: 7,
2251
+ label: "Queue panel",
2252
+ action: "toggleQueuePanel",
2253
+ helpKeys: "F7",
2254
+ helpDescription: "queue panel"
2255
+ },
2256
+ {
2257
+ key: 8,
2258
+ label: "Process list overlay",
2259
+ action: "toggleProcessList",
2260
+ helpKeys: "F8",
2261
+ helpDescription: "process list overlay"
2262
+ },
2263
+ {
2264
+ key: 9,
2265
+ label: "Goal panel",
2266
+ action: "toggleGoalPanel",
2267
+ helpKeys: "F9",
2268
+ helpDescription: "goal panel"
2269
+ },
2270
+ {
2271
+ key: 10,
2272
+ label: "Live sessions panel",
2273
+ action: "toggleSessionsPanel",
2274
+ helpKeys: "F10 or /resume",
2275
+ helpDescription: "live sessions panel (F10 may open host menu)"
2276
+ },
2277
+ {
2278
+ key: 11,
2279
+ label: "Coordinator monitor",
2280
+ action: "toggleCoordinatorMonitor",
2281
+ helpKeys: "F11 or /coordinator",
2282
+ helpDescription: "coordinator monitor (F11 may toggle fullscreen)"
2283
+ },
2284
+ {
2285
+ key: 12,
2286
+ label: "Status line picker",
2287
+ action: "statuslineOpen",
2288
+ helpKeys: "F12 or /sl",
2289
+ helpDescription: "status line picker (F12 may be host/devtools)"
2290
+ }
1888
2291
  ];
2292
+ var PAYLOAD_FREE_ACTIONS = /* @__PURE__ */ new Set([
2293
+ "toggleMonitor",
2294
+ "toggleAgentsMonitor",
2295
+ "toggleWorktreeMonitor",
2296
+ "togglePlanPanel",
2297
+ "toggleTodosMonitor",
2298
+ "toggleQueuePanel",
2299
+ "toggleProcessList",
2300
+ "toggleGoalPanel",
2301
+ "toggleSessionsPanel",
2302
+ "toggleCoordinatorMonitor"
2303
+ ]);
2304
+ function actionForFKeyPanel(entry, hiddenItems = []) {
2305
+ if (entry.action === "projectPickerOpen") return null;
2306
+ if (entry.action === "statuslineOpen") {
2307
+ return { type: "statuslineOpen", hiddenItems: [...hiddenItems] };
2308
+ }
2309
+ if (PAYLOAD_FREE_ACTIONS.has(entry.action)) {
2310
+ return { type: entry.action };
2311
+ }
2312
+ return null;
2313
+ }
1889
2314
  function FKeyPicker({ selected }) {
1890
2315
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, flexShrink: 0, children: [
1891
2316
  /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 F-Key Panels \u2501\u2501" }),
1892
2317
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191\u2193 navigate \xB7 Enter open \xB7 Esc close" }),
1893
- F_KEY_ENTRIES.map((entry) => {
2318
+ F_KEY_PANEL_ENTRIES.map((entry) => {
1894
2319
  const idx = entry.key - 1;
1895
2320
  const isSelected = idx === selected;
1896
2321
  const marker = isSelected ? "\u25B8" : " ";
@@ -2002,39 +2427,9 @@ function MailboxPanel({
2002
2427
  "]"
2003
2428
  ] }) : null
2004
2429
  ] }, a.agentId))
2005
- ] }) : null,
2006
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "/mailbox \u2014 Esc to close" }) })
2007
- ] });
2008
- }
2009
- var TOOL_GLYPHS = {
2010
- file: "\u25A4",
2011
- edit: "\u270E",
2012
- search: "\u2315",
2013
- folder: "\u25A3",
2014
- terminal: "\u2318",
2015
- web: "\u25C8",
2016
- git: "\u2387",
2017
- tree: "\u2630",
2018
- code: "\u2699",
2019
- test: "\u2697",
2020
- package: "\u2B22",
2021
- document: "\u2637",
2022
- scaffold: "\u2731",
2023
- todo: "\u2610",
2024
- plan: "\u2756",
2025
- task: "\u25AA",
2026
- meta: "\u274F",
2027
- index: "\u229B",
2028
- json: "\u2317",
2029
- diff: "\u2206",
2030
- logs: "\u2261",
2031
- settings: "\u2699",
2032
- brain: "\u2726",
2033
- fallback: "\u2022"
2034
- };
2035
- function getToolVisual(name) {
2036
- const id = getToolIcon(name);
2037
- return { glyph: TOOL_GLYPHS[id], color: TOOL_ICON_CONFIG[id].color };
2430
+ ] }) : null,
2431
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "/mailbox \u2014 Esc to close" }) })
2432
+ ] });
2038
2433
  }
2039
2434
  function helpSections() {
2040
2435
  const nav = [];
@@ -2047,16 +2442,10 @@ function helpSections() {
2047
2442
  {
2048
2443
  title: "Monitors",
2049
2444
  entries: [
2050
- { keys: "F1", desc: "project switcher (also /project)" },
2051
- { keys: "Ctrl+F / F2", desc: "fleet orchestration monitor" },
2052
- { keys: "Ctrl+G / F3", desc: "agents live monitor" },
2053
- { keys: "Ctrl+T / F4", desc: "worktree monitor" },
2054
- { keys: "F5", desc: "autonomy settings (also Ctrl+S)" },
2055
- { keys: "F6", desc: "todos monitor overlay" },
2056
- { keys: "F7", desc: "queue panel" },
2057
- { keys: "F8", desc: "process list overlay" },
2058
- { keys: "F9", desc: "goal panel" },
2059
- { keys: "F10", desc: "live sessions panel" },
2445
+ ...F_KEY_PANEL_ENTRIES.map((entry) => ({
2446
+ keys: entry.helpKeys,
2447
+ desc: entry.helpDescription
2448
+ })),
2060
2449
  { keys: "Esc", desc: "close the open monitor / overlay" }
2061
2450
  ]
2062
2451
  },
@@ -2065,8 +2454,11 @@ function helpSections() {
2065
2454
  entries: [
2066
2455
  { keys: "Enter", desc: "send (queues while the agent is busy)" },
2067
2456
  { keys: "Esc Esc", desc: "clear the input buffer" },
2068
- { keys: "Ctrl+Backspace", desc: "delete the previous word" },
2069
- { keys: "Ctrl+S", desc: "edit autonomy settings" },
2457
+ { keys: "Ctrl+\u2190/\u2192", desc: "word navigation (terminal-dependent)" },
2458
+ { keys: "Ctrl+Backspace", desc: "delete previous word/chip" },
2459
+ { keys: "Ctrl+S or /settings", desc: "settings (Ctrl+S may be reserved)" },
2460
+ { keys: "Ctrl+V", desc: "paste text (may be host paste)" },
2461
+ { keys: "Alt+V", desc: "paste image (terminal-dependent)" },
2070
2462
  { keys: "Ctrl+C", desc: "interrupt the run \xB7 twice to exit" }
2071
2463
  ]
2072
2464
  },
@@ -4086,7 +4478,7 @@ function parseRawNumbered(content) {
4086
4478
  const m = ITEM_RE.exec(line);
4087
4479
  if (!m) continue;
4088
4480
  const numPart = m[1];
4089
- let text = m[2].trim();
4481
+ const text = m[2].trim();
4090
4482
  const hasAuto = !!m[3];
4091
4483
  let index;
4092
4484
  if (numPart !== void 0) {
@@ -4124,7 +4516,7 @@ function parseWithHeading(content, strict) {
4124
4516
  const m = ITEM_RE.exec(line);
4125
4517
  if (!m) break;
4126
4518
  const numPart = m[1];
4127
- let text = m[2].trim();
4519
+ const text = m[2].trim();
4128
4520
  const hasAuto = !!m[3];
4129
4521
  let index;
4130
4522
  if (numPart !== void 0) {
@@ -4755,6 +5147,15 @@ function tokenLengthForward(buffer, cursor) {
4755
5147
  const m = buffer.slice(cursor).match(AT_START);
4756
5148
  return m ? m[0].length : 0;
4757
5149
  }
5150
+ function tokenSpanAt(buffer, cursor) {
5151
+ const clamped = Math.max(0, Math.min(cursor, buffer.length));
5152
+ for (const m of buffer.matchAll(GLOBAL)) {
5153
+ const start = m.index ?? 0;
5154
+ const end = start + m[0].length;
5155
+ if (clamped >= start && clamped <= end) return { start, end };
5156
+ }
5157
+ return null;
5158
+ }
4758
5159
  function splitChips(text) {
4759
5160
  if (!text) return [];
4760
5161
  const spans = [];
@@ -4939,6 +5340,11 @@ function isHomeEnd(data) {
4939
5340
  return "end";
4940
5341
  return null;
4941
5342
  }
5343
+ function isCtrlArrow(data) {
5344
+ if (data === "\x1B[1;5D" || data === "\x1B[5D") return "left";
5345
+ if (data === "\x1B[1;5C" || data === "\x1B[5C") return "right";
5346
+ return null;
5347
+ }
4942
5348
  function isBackspaceOrDelete(data) {
4943
5349
  if (data === "\x1B\x7F" || data === "\x1B\b") return "metaBackspace";
4944
5350
  if (data === "\x7F" || data === "\b") return "backspace";
@@ -4976,6 +5382,8 @@ var Input = memo(function Input2({
4976
5382
  const suppressInkEscRef = useRef(false);
4977
5383
  const suppressInkBackspaceRef = useRef(false);
4978
5384
  const suppressInkDeleteRef = useRef(false);
5385
+ const suppressInkCtrlLeftRef = useRef(false);
5386
+ const suppressInkCtrlRightRef = useRef(false);
4979
5387
  useInput((input, key) => {
4980
5388
  if (disabled) return;
4981
5389
  if (input && isLeakedMouseInput(input)) return;
@@ -4991,6 +5399,14 @@ var Input = memo(function Input2({
4991
5399
  suppressInkDeleteRef.current = false;
4992
5400
  return;
4993
5401
  }
5402
+ if (key.ctrl && key.leftArrow && suppressInkCtrlLeftRef.current) {
5403
+ suppressInkCtrlLeftRef.current = false;
5404
+ return;
5405
+ }
5406
+ if (key.ctrl && key.rightArrow && suppressInkCtrlRightRef.current) {
5407
+ suppressInkCtrlRightRef.current = false;
5408
+ return;
5409
+ }
4994
5410
  onKey(input, key);
4995
5411
  });
4996
5412
  const { stdin } = useStdin();
@@ -5026,6 +5442,17 @@ var Input = memo(function Input2({
5026
5442
  onKey("", { ...EMPTY_KEY, end: true });
5027
5443
  return;
5028
5444
  }
5445
+ const ctrlArrow = isCtrlArrow(s2);
5446
+ if (ctrlArrow === "left") {
5447
+ suppressInkCtrlLeftRef.current = true;
5448
+ onKey("", { ...EMPTY_KEY, leftArrow: true, ctrl: true });
5449
+ return;
5450
+ }
5451
+ if (ctrlArrow === "right") {
5452
+ suppressInkCtrlRightRef.current = true;
5453
+ onKey("", { ...EMPTY_KEY, rightArrow: true, ctrl: true });
5454
+ return;
5455
+ }
5029
5456
  const bsdel = isBackspaceOrDelete(s2);
5030
5457
  if (bsdel === "backspace") {
5031
5458
  suppressInkBackspaceRef.current = true;
@@ -6162,6 +6589,14 @@ var CONTEXT_MODE_DESCS = {
6162
6589
  deep: "Larger context for complex tasks",
6163
6590
  archival: "Maximize context retention"
6164
6591
  };
6592
+ var STATUSLINE_MODES = ["minimum", "detailed"];
6593
+ var REASONING_MODES = ["auto", "on", "off"];
6594
+ var REASONING_EFFORTS = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
6595
+ var CACHE_TTLS = ["default", "5m", "1h"];
6596
+ var STATUSLINE_MODE_DESCS = {
6597
+ minimum: "Single line with essential chips only",
6598
+ detailed: "Full multi-line statusline (default)"
6599
+ };
6165
6600
  var MAX_ITERATIONS_PRESETS = [100, 200, 500, 1e3, 0];
6166
6601
  var MAX_CONCURRENT_PRESETS = [1, 3, 5, 10, 25, 50, 0];
6167
6602
  var AUTO_PROCEED_MAX_PRESETS = [10, 25, 50, 100, 250, 0];
@@ -6192,7 +6627,7 @@ var MODE_DESC = {
6192
6627
  suggest: "Shows next-step suggestions after each turn",
6193
6628
  auto: "Self-driving \u2014 agent continues automatically"
6194
6629
  };
6195
- var SETTINGS_FIELD_COUNT = 29;
6630
+ var SETTINGS_FIELD_COUNT = 35;
6196
6631
  var CONFIG_SCOPES = ["global", "project"];
6197
6632
  function SettingsPicker({
6198
6633
  field,
@@ -6211,19 +6646,25 @@ function SettingsPicker({
6211
6646
  featureModelsRegistry,
6212
6647
  tokenSavingTier,
6213
6648
  allowOutsideProjectRoot,
6649
+ maxIterations,
6650
+ autoProceedMaxIterations,
6651
+ enhanceDelayMs,
6652
+ enhanceEnabled,
6653
+ enhanceLanguage,
6654
+ indexOnStart,
6655
+ thinkingWord,
6656
+ reasoningMode,
6657
+ reasoningEffort,
6658
+ reasoningPreserve,
6659
+ cacheTtl,
6214
6660
  contextAutoCompact,
6215
6661
  contextStrategy,
6216
6662
  contextMode,
6217
6663
  maxConcurrent,
6218
6664
  logLevel,
6219
6665
  auditLevel,
6220
- indexOnStart,
6221
- maxIterations,
6222
- autoProceedMaxIterations,
6223
- enhanceDelayMs,
6224
- enhanceEnabled,
6225
- enhanceLanguage,
6226
6666
  debugStream,
6667
+ statuslineMode,
6227
6668
  configScope,
6228
6669
  hint
6229
6670
  }) {
@@ -6306,6 +6747,65 @@ function SettingsPicker({
6306
6747
  value: boolVal(allowOutsideProjectRoot),
6307
6748
  detail: "Allow tools to access paths outside project root"
6308
6749
  },
6750
+ // ── Tools ──
6751
+ { section: "Tools" },
6752
+ {
6753
+ label: "Max iterations",
6754
+ value: formatMaxIterations(maxIterations),
6755
+ detail: "100\u20131000 or unlimited (0)"
6756
+ },
6757
+ {
6758
+ label: "Auto-proceed max iterations",
6759
+ value: formatMaxIterations(autoProceedMaxIterations),
6760
+ detail: "Stop auto-proceed after N iterations (0 = unlimited, default 50)"
6761
+ },
6762
+ {
6763
+ label: "Refine preview countdown",
6764
+ value: formatEnhanceDelay(enhanceDelayMs),
6765
+ detail: "Timeout for prompt refinement preview (30s\u2013120s)"
6766
+ },
6767
+ {
6768
+ label: "Refine",
6769
+ value: boolVal(enhanceEnabled),
6770
+ detail: "Enable prompt refinement before sending"
6771
+ },
6772
+ {
6773
+ label: "Refine language",
6774
+ value: enhanceLanguage,
6775
+ detail: "original (keep language) | english (translate)"
6776
+ },
6777
+ {
6778
+ label: "Index on session start",
6779
+ value: boolVal(indexOnStart),
6780
+ detail: "Run incremental index at session start"
6781
+ },
6782
+ // ── Reasoning ──
6783
+ { section: "Reasoning" },
6784
+ {
6785
+ label: "Thinking word",
6786
+ value: thinkingWord,
6787
+ detail: "Word shown in status bar while agent works"
6788
+ },
6789
+ {
6790
+ label: "Reasoning mode",
6791
+ value: reasoningMode,
6792
+ detail: "auto (provider default) | on | off"
6793
+ },
6794
+ {
6795
+ label: "Reasoning effort",
6796
+ value: reasoningEffort,
6797
+ detail: "none\u2013max (model-dependent)"
6798
+ },
6799
+ {
6800
+ label: "Preserve thinking",
6801
+ value: boolVal(reasoningPreserve),
6802
+ detail: "Keep reasoning across turns"
6803
+ },
6804
+ {
6805
+ label: "Cache TTL",
6806
+ value: cacheTtl,
6807
+ detail: "Prompt cache TTL (5m | 1h)"
6808
+ },
6309
6809
  // ── Context ──
6310
6810
  { section: "Context" },
6311
6811
  {
@@ -6337,47 +6837,11 @@ function SettingsPicker({
6337
6837
  value: logLevel,
6338
6838
  detail: "Console log verbosity"
6339
6839
  },
6340
- // ── Session ──
6341
- { section: "Session" },
6342
6840
  {
6343
6841
  label: "Audit level",
6344
6842
  value: auditLevel,
6345
6843
  detail: "minimal | standard | full (large)"
6346
6844
  },
6347
- // ── Indexing ──
6348
- { section: "Indexing" },
6349
- {
6350
- label: "Index on session start",
6351
- value: boolVal(indexOnStart),
6352
- detail: "Run incremental index at session start"
6353
- },
6354
- // ── Tools ──
6355
- { section: "Tools" },
6356
- {
6357
- label: "Max iterations",
6358
- value: formatMaxIterations(maxIterations),
6359
- detail: "100\u20131000 or unlimited (0)"
6360
- },
6361
- {
6362
- label: "Auto-proceed max iterations",
6363
- value: formatMaxIterations(autoProceedMaxIterations),
6364
- detail: "Stop auto-proceed after N iterations (0 = unlimited, default 50)"
6365
- },
6366
- {
6367
- label: "Refine preview countdown",
6368
- value: formatEnhanceDelay(enhanceDelayMs),
6369
- detail: "Timeout for prompt refinement preview (30s\u2013120s)"
6370
- },
6371
- {
6372
- label: "Refine",
6373
- value: boolVal(enhanceEnabled),
6374
- detail: "Enable prompt refinement before sending"
6375
- },
6376
- {
6377
- label: "Refine language",
6378
- value: enhanceLanguage,
6379
- detail: "original (keep language) | english (translate)"
6380
- },
6381
6845
  // ── Debug ──
6382
6846
  { section: "Debug" },
6383
6847
  {
@@ -6385,6 +6849,11 @@ function SettingsPicker({
6385
6849
  value: boolVal(debugStream),
6386
6850
  detail: "Hex-dump raw SSE bytes to stderr"
6387
6851
  },
6852
+ {
6853
+ label: "Statusline",
6854
+ value: statuslineMode,
6855
+ detail: STATUSLINE_MODE_DESCS[statuslineMode]
6856
+ },
6388
6857
  {
6389
6858
  label: "Config scope",
6390
6859
  value: configScope,
@@ -6697,9 +7166,9 @@ function hintsFor(ctx) {
6697
7166
  if (ctx.monitor) {
6698
7167
  const hints = [
6699
7168
  { key: "Esc", label: "close" },
6700
- { key: "^F", label: "fleet" },
6701
- { key: "^G", label: "agents" },
6702
- { key: "^T", label: "worktrees" },
7169
+ { key: "F2", label: "fleet" },
7170
+ { key: "F3", label: "agents" },
7171
+ { key: "F4", label: "worktrees" },
6703
7172
  { key: "F6", label: "todos" },
6704
7173
  { key: "F9", label: "goal" }
6705
7174
  ];
@@ -6710,7 +7179,7 @@ function hintsFor(ctx) {
6710
7179
  }
6711
7180
  const base = [{ key: "?", label: "help" }];
6712
7181
  if (ctx.managed) base.push({ key: "PgUp/PgDn", label: "scroll" });
6713
- base.push({ key: "^G", label: "agents" }, { key: "^C", label: "stop" });
7182
+ base.push({ key: "F3", label: "agents" }, { key: "^C", label: "stop" });
6714
7183
  if (ctx.nextPanelHint) {
6715
7184
  base.push({ key: ctx.nextPanelHint.key, label: ctx.nextPanelHint.label, discovery: true });
6716
7185
  }
@@ -6847,6 +7316,9 @@ var WT_STATUS = {
6847
7316
  function fmt(s2) {
6848
7317
  return WT_STATUS[s2] ?? { icon: "?", color: "white", label: s2 };
6849
7318
  }
7319
+ function isWorktreeMonitorCloseKey(input, key) {
7320
+ return key.escape === true || key.ctrl === true && input === "w";
7321
+ }
6850
7322
  function WorktreeMonitor({
6851
7323
  worktrees,
6852
7324
  baseBranch,
@@ -6854,7 +7326,7 @@ function WorktreeMonitor({
6854
7326
  onClose
6855
7327
  }) {
6856
7328
  useInput((input, key) => {
6857
- if (key.ctrl && input === "w") onClose();
7329
+ if (isWorktreeMonitorCloseKey(input, key)) onClose();
6858
7330
  });
6859
7331
  const TERMINAL_TTL_MS = 5 * 6e4;
6860
7332
  const list = Object.values(worktrees);
@@ -6891,7 +7363,7 @@ function WorktreeMonitor({
6891
7363
  failed
6892
7364
  ] })
6893
7365
  ] }) : null,
6894
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 Ctrl+T / F4 to close" })
7366
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 Esc / F4 to close" })
6895
7367
  ] }),
6896
7368
  recent.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No worktrees. They appear when AutoPhase runs with isolation on." }) : recent.map((w) => {
6897
7369
  const s2 = fmt(w.status);
@@ -6941,7 +7413,7 @@ function WorktreeMonitor({
6941
7413
  ] }, w.branch);
6942
7414
  }),
6943
7415
  /* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
6944
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Ctrl+T to close \xB7 merge conflicts with /worktree merge <branch>" }),
7416
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Esc / F4 to close \xB7 merge conflicts with /worktree merge <branch>" }),
6945
7417
  staleTerminal > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${staleTerminal} terminal pruned` }) : null
6946
7418
  ] })
6947
7419
  ] });
@@ -8262,6 +8734,26 @@ function buildSteeringPreamble(snapshot, newDirection) {
8262
8734
  lines.push("]");
8263
8735
  return lines.join("\n");
8264
8736
  }
8737
+ function closePanels(state) {
8738
+ return {
8739
+ monitorOpen: false,
8740
+ agentsMonitorOpen: false,
8741
+ helpOpen: false,
8742
+ todosMonitorOpen: false,
8743
+ queuePanelOpen: false,
8744
+ processListOpen: false,
8745
+ planPanelOpen: false,
8746
+ goalPanelOpen: false,
8747
+ sessionsPanelOpen: false,
8748
+ settingsPicker: { ...state.settingsPicker, open: false },
8749
+ statuslinePicker: { ...state.statuslinePicker, open: false },
8750
+ projectPicker: { ...state.projectPicker, open: false },
8751
+ fKeyPicker: { ...state.fKeyPicker, open: false },
8752
+ autoPhase: state.autoPhase ? { ...state.autoPhase, monitorOpen: false } : state.autoPhase,
8753
+ worktreeMonitorOpen: false,
8754
+ coordinator: { ...state.coordinator, monitorOpen: false }
8755
+ };
8756
+ }
8265
8757
  var MAX_TOOL_STREAM_RETAINED_CHARS = 1e5;
8266
8758
  var MAX_RETAINED_INPUT_CHARS = 2048;
8267
8759
  var MAX_RETAINED_INPUT_DEPTH = 4;
@@ -8529,6 +9021,7 @@ function reducer(state, action) {
8529
9021
  case "modelPickerOpen":
8530
9022
  return {
8531
9023
  ...state,
9024
+ ...closePanels(state),
8532
9025
  modelPicker: {
8533
9026
  open: true,
8534
9027
  step: "provider",
@@ -8616,6 +9109,7 @@ function reducer(state, action) {
8616
9109
  case "autonomyPickerOpen":
8617
9110
  return {
8618
9111
  ...state,
9112
+ ...closePanels(state),
8619
9113
  autonomyPicker: { open: true, options: action.options, selected: 0, hint: void 0 }
8620
9114
  };
8621
9115
  case "autonomyPickerClose":
@@ -8640,6 +9134,7 @@ function reducer(state, action) {
8640
9134
  case "resumePickerOpen":
8641
9135
  return {
8642
9136
  ...state,
9137
+ ...closePanels(state),
8643
9138
  resumePicker: { open: true, sessions: action.sessions, selected: 0, busy: false, hint: void 0, error: void 0 }
8644
9139
  };
8645
9140
  case "resumePickerClose":
@@ -8669,6 +9164,7 @@ function reducer(state, action) {
8669
9164
  case "settingsOpen":
8670
9165
  return {
8671
9166
  ...state,
9167
+ ...closePanels(state),
8672
9168
  settingsPicker: {
8673
9169
  open: true,
8674
9170
  field: 0,
@@ -8700,6 +9196,12 @@ function reducer(state, action) {
8700
9196
  enhanceEnabled: action.enhanceEnabled,
8701
9197
  enhanceLanguage: action.enhanceLanguage,
8702
9198
  debugStream: action.debugStream,
9199
+ statuslineMode: action.statuslineMode,
9200
+ reasoningMode: action.reasoningMode,
9201
+ reasoningEffort: action.reasoningEffort,
9202
+ reasoningPreserve: action.reasoningPreserve,
9203
+ thinkingWord: action.thinkingWord,
9204
+ cacheTtl: action.cacheTtl,
8703
9205
  configScope: action.configScope,
8704
9206
  hint: void 0
8705
9207
  }
@@ -8754,65 +9256,91 @@ function reducer(state, action) {
8754
9256
  return { ...state, settingsPicker: { ...sp, tokenSavingTier: TOKEN_SAVING_TIERS[next] ?? "off", hint: bootHint } };
8755
9257
  }
8756
9258
  if (f === 14) return { ...state, settingsPicker: { ...sp, allowOutsideProjectRoot: !sp.allowOutsideProjectRoot, hint: void 0 } };
8757
- if (f === 15) return { ...state, settingsPicker: { ...sp, contextAutoCompact: !sp.contextAutoCompact, hint: void 0 } };
9259
+ if (f === 15) {
9260
+ const j = MAX_ITERATIONS_PRESETS.indexOf(sp.maxIterations);
9261
+ const base = j < 0 ? 0 : j;
9262
+ const next = (base + action.delta + MAX_ITERATIONS_PRESETS.length) % MAX_ITERATIONS_PRESETS.length;
9263
+ return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined$1(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
9264
+ }
8758
9265
  if (f === 16) {
9266
+ const aj = AUTO_PROCEED_MAX_PRESETS.indexOf(sp.autoProceedMaxIterations);
9267
+ const abase = aj < 0 ? 0 : aj;
9268
+ const anext = (abase + action.delta + AUTO_PROCEED_MAX_PRESETS.length) % AUTO_PROCEED_MAX_PRESETS.length;
9269
+ return { ...state, settingsPicker: { ...sp, autoProceedMaxIterations: expectDefined$1(AUTO_PROCEED_MAX_PRESETS[anext]), hint: void 0 } };
9270
+ }
9271
+ if (f === 17) {
9272
+ const ej = ENHANCE_DELAY_PRESETS.indexOf(sp.enhanceDelayMs);
9273
+ const ebase = ej < 0 ? 0 : ej;
9274
+ const enext = (ebase + action.delta + ENHANCE_DELAY_PRESETS.length) % ENHANCE_DELAY_PRESETS.length;
9275
+ return { ...state, settingsPicker: { ...sp, enhanceDelayMs: expectDefined$1(ENHANCE_DELAY_PRESETS[enext]), hint: void 0 } };
9276
+ }
9277
+ if (f === 18) return { ...state, settingsPicker: { ...sp, enhanceEnabled: !sp.enhanceEnabled, hint: void 0 } };
9278
+ if (f === 19) {
9279
+ const i = ENHANCE_LANGUAGES.indexOf(sp.enhanceLanguage);
9280
+ const base = i < 0 ? 0 : i;
9281
+ const next = (base + action.delta + ENHANCE_LANGUAGES.length) % ENHANCE_LANGUAGES.length;
9282
+ return { ...state, settingsPicker: { ...sp, enhanceLanguage: expectDefined$1(ENHANCE_LANGUAGES[next]), hint: void 0 } };
9283
+ }
9284
+ if (f === 20) return { ...state, settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: bootHint } };
9285
+ if (f === 21) return state;
9286
+ if (f === 22) {
9287
+ const i = REASONING_MODES.indexOf(sp.reasoningMode);
9288
+ const base = i < 0 ? 0 : i;
9289
+ const next = (base + action.delta + REASONING_MODES.length) % REASONING_MODES.length;
9290
+ return { ...state, settingsPicker: { ...sp, reasoningMode: expectDefined$1(REASONING_MODES[next]), hint: void 0 } };
9291
+ }
9292
+ if (f === 23) {
9293
+ const i = REASONING_EFFORTS.indexOf(sp.reasoningEffort);
9294
+ const base = i < 0 ? REASONING_EFFORTS.indexOf("high") : i;
9295
+ const next = (base + action.delta + REASONING_EFFORTS.length) % REASONING_EFFORTS.length;
9296
+ return { ...state, settingsPicker: { ...sp, reasoningEffort: expectDefined$1(REASONING_EFFORTS[next]), hint: void 0 } };
9297
+ }
9298
+ if (f === 24) return { ...state, settingsPicker: { ...sp, reasoningPreserve: !sp.reasoningPreserve, hint: void 0 } };
9299
+ if (f === 25) {
9300
+ const i = CACHE_TTLS.indexOf(sp.cacheTtl);
9301
+ const base = i < 0 ? 0 : i;
9302
+ const next = (base + action.delta + CACHE_TTLS.length) % CACHE_TTLS.length;
9303
+ return { ...state, settingsPicker: { ...sp, cacheTtl: expectDefined$1(CACHE_TTLS[next]), hint: void 0 } };
9304
+ }
9305
+ if (f === 26) return { ...state, settingsPicker: { ...sp, contextAutoCompact: !sp.contextAutoCompact, hint: void 0 } };
9306
+ if (f === 27) {
8759
9307
  const i = COMPACTOR_STRATEGIES.indexOf(sp.contextStrategy);
8760
9308
  const base = i < 0 ? 0 : i;
8761
9309
  const next = (base + action.delta + COMPACTOR_STRATEGIES.length) % COMPACTOR_STRATEGIES.length;
8762
9310
  return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined$1(COMPACTOR_STRATEGIES[next]), hint: bootHint } };
8763
9311
  }
8764
- if (f === 17) {
9312
+ if (f === 28) {
8765
9313
  const i = CONTEXT_MODES.indexOf(sp.contextMode);
8766
9314
  const base = i < 0 ? 0 : i;
8767
9315
  const next = (base + action.delta + CONTEXT_MODES.length) % CONTEXT_MODES.length;
8768
9316
  return { ...state, settingsPicker: { ...sp, contextMode: expectDefined$1(CONTEXT_MODES[next]), hint: bootHint } };
8769
9317
  }
8770
- if (f === 18) {
9318
+ if (f === 29) {
8771
9319
  const j = MAX_CONCURRENT_PRESETS.indexOf(sp.maxConcurrent);
8772
9320
  const base = j < 0 ? 0 : j;
8773
9321
  const next = (base + action.delta + MAX_CONCURRENT_PRESETS.length) % MAX_CONCURRENT_PRESETS.length;
8774
9322
  return { ...state, settingsPicker: { ...sp, maxConcurrent: expectDefined$1(MAX_CONCURRENT_PRESETS[next]), hint: void 0 } };
8775
9323
  }
8776
- if (f === 19) {
9324
+ if (f === 30) {
8777
9325
  const i = LOG_LEVELS.indexOf(sp.logLevel);
8778
9326
  const base = i < 0 ? 0 : i;
8779
9327
  const next = (base + action.delta + LOG_LEVELS.length) % LOG_LEVELS.length;
8780
9328
  return { ...state, settingsPicker: { ...sp, logLevel: expectDefined$1(LOG_LEVELS[next]), hint: void 0 } };
8781
9329
  }
8782
- if (f === 20) {
9330
+ if (f === 31) {
8783
9331
  const i = AUDIT_LEVELS.indexOf(sp.auditLevel);
8784
9332
  const base = i < 0 ? 0 : i;
8785
9333
  const next = (base + action.delta + AUDIT_LEVELS.length) % AUDIT_LEVELS.length;
8786
9334
  return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined$1(AUDIT_LEVELS[next]), hint: void 0 } };
8787
9335
  }
8788
- if (f === 21) return { ...state, settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: bootHint } };
8789
- if (f === 22) {
8790
- const j = MAX_ITERATIONS_PRESETS.indexOf(sp.maxIterations);
8791
- const base = j < 0 ? 0 : j;
8792
- const next = (base + action.delta + MAX_ITERATIONS_PRESETS.length) % MAX_ITERATIONS_PRESETS.length;
8793
- return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined$1(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
8794
- }
8795
- if (f === 23) {
8796
- const aj = AUTO_PROCEED_MAX_PRESETS.indexOf(sp.autoProceedMaxIterations);
8797
- const abase = aj < 0 ? 0 : aj;
8798
- const anext = (abase + action.delta + AUTO_PROCEED_MAX_PRESETS.length) % AUTO_PROCEED_MAX_PRESETS.length;
8799
- return { ...state, settingsPicker: { ...sp, autoProceedMaxIterations: expectDefined$1(AUTO_PROCEED_MAX_PRESETS[anext]), hint: void 0 } };
8800
- }
8801
- if (f === 24) {
8802
- const ej = ENHANCE_DELAY_PRESETS.indexOf(sp.enhanceDelayMs);
8803
- const ebase = ej < 0 ? 0 : ej;
8804
- const enext = (ebase + action.delta + ENHANCE_DELAY_PRESETS.length) % ENHANCE_DELAY_PRESETS.length;
8805
- return { ...state, settingsPicker: { ...sp, enhanceDelayMs: expectDefined$1(ENHANCE_DELAY_PRESETS[enext]), hint: void 0 } };
8806
- }
8807
- if (f === 25) return { ...state, settingsPicker: { ...sp, enhanceEnabled: !sp.enhanceEnabled, hint: void 0 } };
8808
- if (f === 26) {
8809
- const i = ENHANCE_LANGUAGES.indexOf(sp.enhanceLanguage);
8810
- const base = i < 0 ? 0 : i;
8811
- const next = (base + action.delta + ENHANCE_LANGUAGES.length) % ENHANCE_LANGUAGES.length;
8812
- return { ...state, settingsPicker: { ...sp, enhanceLanguage: expectDefined$1(ENHANCE_LANGUAGES[next]), hint: void 0 } };
9336
+ if (f === 32) return { ...state, settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 } };
9337
+ if (f === 33) {
9338
+ const i = STATUSLINE_MODES.indexOf(sp.statuslineMode);
9339
+ const base = i < 0 ? STATUSLINE_MODES.indexOf("detailed") : i;
9340
+ const next = (base + action.delta + STATUSLINE_MODES.length) % STATUSLINE_MODES.length;
9341
+ return { ...state, settingsPicker: { ...sp, statuslineMode: expectDefined$1(STATUSLINE_MODES[next]), hint: void 0 } };
8813
9342
  }
8814
- if (f === 27) return { ...state, settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 } };
8815
- if (f === 28) {
9343
+ if (f === 34) {
8816
9344
  const i = CONFIG_SCOPES.indexOf(sp.configScope);
8817
9345
  const base = i < 0 ? 0 : i;
8818
9346
  const next = (base + action.delta + CONFIG_SCOPES.length) % CONFIG_SCOPES.length;
@@ -8826,6 +9354,7 @@ function reducer(state, action) {
8826
9354
  case "statuslineOpen":
8827
9355
  return {
8828
9356
  ...state,
9357
+ ...closePanels(state),
8829
9358
  statuslinePicker: { open: true, field: 0, hiddenItems: action.hiddenItems, visibleChips: state.statuslinePicker.visibleChips, hint: void 0 }
8830
9359
  };
8831
9360
  case "statuslineClose":
@@ -8881,6 +9410,7 @@ function reducer(state, action) {
8881
9410
  case "projectPickerOpen":
8882
9411
  return {
8883
9412
  ...state,
9413
+ ...closePanels(state),
8884
9414
  projectPicker: {
8885
9415
  open: true,
8886
9416
  allItems: action.items,
@@ -8921,7 +9451,7 @@ function reducer(state, action) {
8921
9451
  case "projectPickerHint":
8922
9452
  return { ...state, projectPicker: { ...state.projectPicker, hint: action.text } };
8923
9453
  case "fKeyPickerOpen":
8924
- return { ...state, fKeyPicker: { open: true, selected: 0 } };
9454
+ return { ...state, ...closePanels(state), fKeyPicker: { open: true, selected: 0 } };
8925
9455
  case "fKeyPickerClose":
8926
9456
  return { ...state, fKeyPicker: { open: false, selected: 0 } };
8927
9457
  case "fKeyPickerMove": {
@@ -9266,35 +9796,35 @@ function reducer(state, action) {
9266
9796
  }
9267
9797
  case "toggleMonitor": {
9268
9798
  const opening = !state.monitorOpen;
9269
- return opening ? { ...state, monitorOpen: true, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, monitorOpen: false };
9799
+ return opening ? { ...state, ...closePanels(state), monitorOpen: true } : { ...state, monitorOpen: false };
9270
9800
  }
9271
9801
  case "toggleAgentsMonitor": {
9272
9802
  const opening = !state.agentsMonitorOpen;
9273
- return opening ? { ...state, agentsMonitorOpen: true, monitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, agentsMonitorOpen: false };
9803
+ return opening ? { ...state, ...closePanels(state), agentsMonitorOpen: true } : { ...state, agentsMonitorOpen: false };
9274
9804
  }
9275
9805
  case "toggleHelp": {
9276
9806
  const opening = !state.helpOpen;
9277
- return opening ? { ...state, helpOpen: true, monitorOpen: false, agentsMonitorOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, helpOpen: false };
9807
+ return opening ? { ...state, ...closePanels(state), helpOpen: true } : { ...state, helpOpen: false };
9278
9808
  }
9279
9809
  case "toggleTodosMonitor": {
9280
9810
  const opening = !state.todosMonitorOpen;
9281
- return opening ? { ...state, todosMonitorOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, todosMonitorOpen: false };
9811
+ return opening ? { ...state, ...closePanels(state), todosMonitorOpen: true } : { ...state, todosMonitorOpen: false };
9282
9812
  }
9283
9813
  case "toggleQueuePanel": {
9284
9814
  const opening = !state.queuePanelOpen;
9285
- return opening ? { ...state, queuePanelOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, queuePanelOpen: false };
9815
+ return opening ? { ...state, ...closePanels(state), queuePanelOpen: true } : { ...state, queuePanelOpen: false };
9286
9816
  }
9287
9817
  case "toggleProcessList": {
9288
9818
  const opening = !state.processListOpen;
9289
- return opening ? { ...state, processListOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, goalPanelOpen: false } : { ...state, processListOpen: false };
9819
+ return opening ? { ...state, ...closePanels(state), processListOpen: true } : { ...state, processListOpen: false };
9290
9820
  }
9291
9821
  case "togglePlanPanel": {
9292
9822
  const opening = !state.planPanelOpen;
9293
- return opening ? { ...state, planPanelOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, planPanelOpen: false };
9823
+ return opening ? { ...state, ...closePanels(state), planPanelOpen: true } : { ...state, planPanelOpen: false };
9294
9824
  }
9295
9825
  case "toggleGoalPanel": {
9296
9826
  const opening = !state.goalPanelOpen;
9297
- return opening ? { ...state, goalPanelOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false } : { ...state, goalPanelOpen: false };
9827
+ return opening ? { ...state, ...closePanels(state), goalPanelOpen: true } : { ...state, goalPanelOpen: false };
9298
9828
  }
9299
9829
  case "checkpointReceived": {
9300
9830
  const existing = state.checkpoints.find((c) => c.promptIndex === action.cp.promptIndex);
@@ -9380,9 +9910,14 @@ function reducer(state, action) {
9380
9910
  }
9381
9911
  case "autoPhaseMonitorToggle": {
9382
9912
  if (!state.autoPhase) return state;
9383
- return {
9913
+ const opening = !state.autoPhase.monitorOpen;
9914
+ return opening ? {
9915
+ ...state,
9916
+ ...closePanels(state),
9917
+ autoPhase: { ...state.autoPhase, monitorOpen: true }
9918
+ } : {
9384
9919
  ...state,
9385
- autoPhase: { ...state.autoPhase, monitorOpen: !state.autoPhase.monitorOpen }
9920
+ autoPhase: { ...state.autoPhase, monitorOpen: false }
9386
9921
  };
9387
9922
  }
9388
9923
  case "autoPhaseReset": {
@@ -9414,7 +9949,8 @@ function reducer(state, action) {
9414
9949
  return { ...state, worktrees: next };
9415
9950
  }
9416
9951
  case "worktreeMonitorToggle": {
9417
- return { ...state, worktreeMonitorOpen: !state.worktreeMonitorOpen };
9952
+ const opening = !state.worktreeMonitorOpen;
9953
+ return opening ? { ...state, ...closePanels(state), worktreeMonitorOpen: true } : { ...state, worktreeMonitorOpen: false };
9418
9954
  }
9419
9955
  // --- In-app chat scroll ---
9420
9956
  case "scrollBy": {
@@ -9609,7 +10145,8 @@ function reducer(state, action) {
9609
10145
  return { ...state, debugStreamStats: null };
9610
10146
  }
9611
10147
  case "toggleSessionsPanel": {
9612
- return { ...state, sessionsPanelOpen: !state.sessionsPanelOpen };
10148
+ const opening = !state.sessionsPanelOpen;
10149
+ return opening ? { ...state, ...closePanels(state), sessionsPanelOpen: true, sessionResumeConfirm: null } : { ...state, sessionsPanelOpen: false, sessionResumeConfirm: null };
9613
10150
  }
9614
10151
  case "sessionsPanelSet": {
9615
10152
  const sessions = Array.isArray(action.sessions) ? action.sessions : [];
@@ -9714,15 +10251,8 @@ function reducer(state, action) {
9714
10251
  const opening = !state.coordinator.monitorOpen;
9715
10252
  return opening ? {
9716
10253
  ...state,
9717
- coordinator: { ...state.coordinator, monitorOpen: true },
9718
- // Close other monitors when opening coordinator
9719
- monitorOpen: false,
9720
- agentsMonitorOpen: false,
9721
- helpOpen: false,
9722
- todosMonitorOpen: false,
9723
- queuePanelOpen: false,
9724
- processListOpen: false,
9725
- goalPanelOpen: false
10254
+ ...closePanels(state),
10255
+ coordinator: { ...state.coordinator, monitorOpen: true }
9726
10256
  } : { ...state, coordinator: { ...state.coordinator, monitorOpen: false } };
9727
10257
  }
9728
10258
  }
@@ -9733,6 +10263,41 @@ function selectedSlashCommandLine(picker) {
9733
10263
  const picked = picker.matches[picker.selected];
9734
10264
  return picked ? `/${picked.name}` : null;
9735
10265
  }
10266
+ function isInputWordSeparator(ch) {
10267
+ return ch === void 0 || /\s/.test(ch);
10268
+ }
10269
+ function previousInputWordStart(buffer, cursor) {
10270
+ let i = Math.max(0, Math.min(cursor, buffer.length));
10271
+ const chipAtCursor = tokenSpanAt(buffer, i);
10272
+ if (chipAtCursor && i > chipAtCursor.start) return chipAtCursor.start;
10273
+ while (i > 0 && isInputWordSeparator(buffer[i - 1])) i--;
10274
+ const chipBeforeCursor = tokenSpanAt(buffer, i);
10275
+ if (chipBeforeCursor && i === chipBeforeCursor.end) return chipBeforeCursor.start;
10276
+ while (i > 0 && !isInputWordSeparator(buffer[i - 1])) {
10277
+ const chip = tokenSpanAt(buffer, i - 1);
10278
+ if (chip) {
10279
+ i = chip.start;
10280
+ continue;
10281
+ }
10282
+ i--;
10283
+ }
10284
+ return i;
10285
+ }
10286
+ function nextInputWordStart(buffer, cursor) {
10287
+ let i = Math.max(0, Math.min(cursor, buffer.length));
10288
+ const chipAtCursor = tokenSpanAt(buffer, i);
10289
+ if (chipAtCursor && i < chipAtCursor.end) i = chipAtCursor.end;
10290
+ else while (i < buffer.length && !isInputWordSeparator(buffer[i])) {
10291
+ const chip = tokenSpanAt(buffer, i);
10292
+ if (chip) {
10293
+ i = chip.end;
10294
+ continue;
10295
+ }
10296
+ i++;
10297
+ }
10298
+ while (i < buffer.length && isInputWordSeparator(buffer[i])) i++;
10299
+ return i;
10300
+ }
9736
10301
  function rehydrateHistory(messages, startId, toolCalls) {
9737
10302
  const entries = [];
9738
10303
  let nextId = startId;
@@ -9842,6 +10407,9 @@ function App({
9842
10407
  subscribeCoordinatorEvents,
9843
10408
  onCoordinatorStart,
9844
10409
  onCoordinatorStop,
10410
+ // Reserved for the coordinator monitor panel: terminal-driven task discovery/claim.
10411
+ onCoordinatorTasks: _onCoordinatorTasks,
10412
+ onCoordinatorClaim: _onCoordinatorClaim,
9845
10413
  coordinatorRunning = false,
9846
10414
  clientId
9847
10415
  }) {
@@ -10003,7 +10571,7 @@ function App({
10003
10571
  },
10004
10572
  autonomyPicker: { open: false, options: [], selected: 0 },
10005
10573
  resumePicker: { open: false, sessions: [], selected: 0, busy: false, hint: void 0, error: void 0 },
10006
- 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, configScope: "global" },
10574
+ 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" },
10007
10575
  statuslinePicker: { open: false, field: 0, hiddenItems: [], visibleChips: [], hint: void 0 },
10008
10576
  projectPicker: { open: false, allItems: [], items: [], selected: 0, filter: "", hint: void 0 },
10009
10577
  fKeyPicker: { open: false, selected: 0 },
@@ -10137,6 +10705,8 @@ function App({
10137
10705
  });
10138
10706
  }, [agent.ctx, projectRoot]);
10139
10707
  const liveSettings = getSettings?.();
10708
+ const liveStatuslineMode = liveSettings?.statuslineMode ?? "detailed";
10709
+ const liveThinkingWord = liveSettings?.thinkingWord ?? "thinking";
10140
10710
  const chimeRef = useRef(chime);
10141
10711
  chimeRef.current = liveSettings?.chime ?? chime;
10142
10712
  const confirmExitRef = useRef(confirmExit);
@@ -10200,11 +10770,11 @@ function App({
10200
10770
  async (checkpointIndex) => {
10201
10771
  const sessionId = agent.ctx.session.id;
10202
10772
  if (!sessionId) return;
10203
- const rewinder = new DefaultSessionRewinder(sessionsDir ?? "", projectRoot ?? agent.ctx.cwd);
10773
+ const rewinder = new DefaultSessionRewinder(sessionsDir ?? "", agent.ctx.projectRoot ?? agent.ctx.cwd);
10204
10774
  await rewinder.rewindToCheckpoint(sessionId, checkpointIndex);
10205
10775
  await agent.ctx.session.truncateToCheckpoint(checkpointIndex);
10206
10776
  },
10207
- [agent.ctx.session, sessionsDir, projectRoot, agent.ctx.cwd]
10777
+ [agent.ctx.session, sessionsDir, agent.ctx.projectRoot, agent.ctx.cwd]
10208
10778
  );
10209
10779
  const setDraft = (buffer, cursor) => {
10210
10780
  draftRef.current = { buffer, cursor };
@@ -10501,8 +11071,8 @@ function App({
10501
11071
  const leaderEntry = {
10502
11072
  id: "leader",
10503
11073
  name: "LEADER",
10504
- provider,
10505
- model,
11074
+ provider: liveProvider,
11075
+ model: liveModel,
10506
11076
  status: state.status === "running" || state.status === "streaming" || state.leader.iterating ? "running" : "idle",
10507
11077
  streamingText: "",
10508
11078
  iterations: state.leader.iterations,
@@ -10521,7 +11091,7 @@ function App({
10521
11091
  ctxMaxTokens: state.leader.ctxMaxTokens ?? effectiveMaxContext
10522
11092
  };
10523
11093
  return { leader: leaderEntry, ...state.fleet };
10524
- }, [state.fleet, state.leader, state.status, provider, model, effectiveMaxContext, tokenCounter]);
11094
+ }, [state.fleet, state.leader, state.status, liveProvider, liveModel, effectiveMaxContext, tokenCounter]);
10525
11095
  const [planCounts, setPlanCounts] = useState(null);
10526
11096
  useEffect(() => {
10527
11097
  const planPath = agent.ctx.meta["plan.path"];
@@ -10716,6 +11286,12 @@ function App({
10716
11286
  enhanceEnabled: sp.enhanceEnabled,
10717
11287
  enhanceLanguage: sp.enhanceLanguage,
10718
11288
  debugStream: sp.debugStream,
11289
+ statuslineMode: sp.statuslineMode,
11290
+ reasoningMode: sp.reasoningMode,
11291
+ reasoningEffort: sp.reasoningEffort,
11292
+ reasoningPreserve: sp.reasoningPreserve,
11293
+ thinkingWord: sp.thinkingWord,
11294
+ cacheTtl: sp.cacheTtl,
10719
11295
  configScope: sp.configScope
10720
11296
  });
10721
11297
  }
@@ -11126,6 +11702,12 @@ function App({
11126
11702
  enhanceEnabled: s2.enhanceEnabled ?? true,
11127
11703
  enhanceLanguage: s2.enhanceLanguage ?? "original",
11128
11704
  debugStream: s2.debugStream ?? false,
11705
+ statuslineMode: s2.statuslineMode ?? "detailed",
11706
+ reasoningMode: s2.reasoningMode ?? "auto",
11707
+ reasoningEffort: s2.reasoningEffort ?? "high",
11708
+ reasoningPreserve: s2.reasoningPreserve ?? false,
11709
+ thinkingWord: s2.thinkingWord ?? "thinking",
11710
+ cacheTtl: s2.cacheTtl ?? "default",
11129
11711
  configScope: s2.configScope ?? "global"
11130
11712
  });
11131
11713
  }, [getSettings]);
@@ -11264,6 +11846,12 @@ function App({
11264
11846
  enhanceEnabled: sp.enhanceEnabled,
11265
11847
  enhanceLanguage: sp.enhanceLanguage,
11266
11848
  debugStream: sp.debugStream,
11849
+ statuslineMode: sp.statuslineMode,
11850
+ reasoningMode: sp.reasoningMode,
11851
+ reasoningEffort: sp.reasoningEffort,
11852
+ reasoningPreserve: sp.reasoningPreserve,
11853
+ thinkingWord: sp.thinkingWord,
11854
+ cacheTtl: sp.cacheTtl,
11267
11855
  configScope: sp.configScope
11268
11856
  })).then((err) => {
11269
11857
  if (err) dispatch({ type: "settingsHint", text: err });
@@ -11298,6 +11886,13 @@ function App({
11298
11886
  state.settingsPicker.enhanceEnabled,
11299
11887
  state.settingsPicker.enhanceLanguage,
11300
11888
  state.settingsPicker.debugStream,
11889
+ state.settingsPicker.statuslineMode,
11890
+ state.settingsPicker.reasoningMode,
11891
+ state.settingsPicker.reasoningEffort,
11892
+ state.settingsPicker.reasoningPreserve,
11893
+ state.settingsPicker.thinkingWord,
11894
+ state.settingsPicker.cacheTtl,
11895
+ state.settingsPicker.configScope,
11301
11896
  saveSettings
11302
11897
  ]);
11303
11898
  useEffect(() => {
@@ -12095,7 +12690,7 @@ function App({
12095
12690
  const now = Date.now();
12096
12691
  if (now - lastEnterAtRef.current < 50) return;
12097
12692
  lastEnterAtRef.current = now;
12098
- dispatch({ type: "settingsClose" });
12693
+ dispatch({ type: "settingsValueChange", delta: 1 });
12099
12694
  return;
12100
12695
  }
12101
12696
  return;
@@ -12162,13 +12757,13 @@ function App({
12162
12757
  if (item.kind === "project") {
12163
12758
  await onProjectSelect?.(item.key, item.kind);
12164
12759
  dispatch({ type: "projectPickerClose" });
12165
- requestExit?.(42);
12760
+ dispatch({ type: "addEntry", entry: { kind: "info", text: `Switched project: ${item.label.trim()}.` } });
12166
12761
  return;
12167
12762
  }
12168
12763
  dispatch({ type: "projectPickerClose" });
12169
12764
  if (item.key === "new-session") {
12170
12765
  await onProjectSelect?.(item.key, item.kind);
12171
- requestExit?.(42);
12766
+ dispatch({ type: "addEntry", entry: { kind: "info", text: "Started a fresh session in this project." } });
12172
12767
  } else if (item.key === "prev-sessions") {
12173
12768
  void submit("/resume");
12174
12769
  }
@@ -12332,10 +12927,15 @@ function App({
12332
12927
  }
12333
12928
  if (isEnter) {
12334
12929
  const selected = state.fKeyPicker.selected;
12335
- const entry = F_KEY_ENTRIES[selected];
12930
+ const entry = F_KEY_PANEL_ENTRIES[selected];
12336
12931
  if (!entry) return;
12337
12932
  dispatch({ type: "fKeyPickerClose" });
12338
- dispatch({ type: entry.action });
12933
+ if (entry.action === "projectPickerOpen") {
12934
+ openProjectPicker();
12935
+ return;
12936
+ }
12937
+ const action = actionForFKeyPanel(entry, state.statuslinePicker.hiddenItems);
12938
+ if (action) dispatch(action);
12339
12939
  return;
12340
12940
  }
12341
12941
  return;
@@ -12595,6 +13195,39 @@ function App({
12595
13195
  dispatch({ type: "toggleCoordinatorMonitor" });
12596
13196
  return;
12597
13197
  }
13198
+ if (key.fn === 12) {
13199
+ dispatch({ type: "statuslineOpen", hiddenItems: state.statuslinePicker.hiddenItems });
13200
+ return;
13201
+ }
13202
+ if (state.settingsPicker.open) {
13203
+ if (key.escape) {
13204
+ dispatch({ type: "settingsClose" });
13205
+ return;
13206
+ }
13207
+ if (key.upArrow) {
13208
+ dispatch({ type: "settingsFieldMove", delta: -1 });
13209
+ return;
13210
+ }
13211
+ if (key.downArrow) {
13212
+ dispatch({ type: "settingsFieldMove", delta: 1 });
13213
+ return;
13214
+ }
13215
+ if (key.leftArrow) {
13216
+ dispatch({ type: "settingsValueChange", delta: -1 });
13217
+ return;
13218
+ }
13219
+ if (key.rightArrow) {
13220
+ dispatch({ type: "settingsValueChange", delta: 1 });
13221
+ return;
13222
+ }
13223
+ if (isEnter) {
13224
+ const now = Date.now();
13225
+ if (now - lastEnterAtRef.current < 50) return;
13226
+ lastEnterAtRef.current = now;
13227
+ dispatch({ type: "settingsValueChange", delta: 1 });
13228
+ return;
13229
+ }
13230
+ }
12598
13231
  if (key.ctrl && input === "s") {
12599
13232
  if (state.settingsPicker.open) {
12600
13233
  dispatch({ type: "settingsClose" });
@@ -12637,6 +13270,12 @@ function App({
12637
13270
  enhanceEnabled: cfg.enhanceEnabled ?? true,
12638
13271
  enhanceLanguage: cfg.enhanceLanguage ?? "original",
12639
13272
  debugStream: cfg.debugStream ?? false,
13273
+ statuslineMode: cfg.statuslineMode ?? "detailed",
13274
+ reasoningMode: cfg.reasoningMode ?? "auto",
13275
+ reasoningEffort: cfg.reasoningEffort ?? "high",
13276
+ reasoningPreserve: cfg.reasoningPreserve ?? false,
13277
+ thinkingWord: cfg.thinkingWord ?? "thinking",
13278
+ cacheTtl: cfg.cacheTtl ?? "default",
12640
13279
  configScope: cfg.configScope ?? "global"
12641
13280
  });
12642
13281
  }
@@ -12724,10 +13363,18 @@ function App({
12724
13363
  if (key.backspace) {
12725
13364
  if (key.ctrl) {
12726
13365
  if (cursor === 0) return;
12727
- const beforeCursor = buffer.slice(0, cursor);
12728
- const lastWordStart = beforeCursor.lastIndexOf(" ") + 1;
12729
- const next3 = beforeCursor.slice(0, lastWordStart) + buffer.slice(cursor);
12730
- setDraft(next3, lastWordStart);
13366
+ const chip = tokenSpanAt(buffer, cursor);
13367
+ const deleteStart = chip && cursor > chip.start && cursor < chip.end ? chip.start : previousInputWordStart(buffer, cursor);
13368
+ const deleteEnd = chip && cursor > chip.start && cursor < chip.end ? chip.end : cursor;
13369
+ const next3 = buffer.slice(0, deleteStart) + buffer.slice(deleteEnd);
13370
+ if (nextStepsAutoSubmitTimerRef.current != null) {
13371
+ clearInterval(nextStepsAutoSubmitTimerRef.current);
13372
+ nextStepsAutoSubmitTimerRef.current = void 0;
13373
+ setNextStepsAutoSubmitCountdown(null);
13374
+ setNextStepsAutoSubmitLabel(null);
13375
+ nextStepsAutoSubmitSuggestionRef.current = null;
13376
+ }
13377
+ setDraft(next3, deleteStart);
12731
13378
  return;
12732
13379
  }
12733
13380
  const tokenDel = deleteTokenBackward(buffer, cursor);
@@ -12750,17 +13397,18 @@ function App({
12750
13397
  if (key.delete) {
12751
13398
  if (key.ctrl) {
12752
13399
  if (cursor >= buffer.length) return;
12753
- const afterCursor = buffer.slice(cursor);
12754
- const nextWordStart = afterCursor.indexOf(" ");
12755
- const end = nextWordStart === -1 ? buffer.length : cursor + nextWordStart + 1;
12756
- const next3 = buffer.slice(0, cursor) + buffer.slice(end);
13400
+ const chip = tokenSpanAt(buffer, cursor);
13401
+ const deleteStart = chip && cursor > chip.start && cursor < chip.end ? chip.start : cursor;
13402
+ const deleteEnd = chip && cursor > chip.start && cursor < chip.end ? chip.end : nextInputWordStart(buffer, cursor);
13403
+ const next3 = buffer.slice(0, deleteStart) + buffer.slice(deleteEnd);
12757
13404
  if (nextStepsAutoSubmitTimerRef.current != null) {
12758
13405
  clearInterval(nextStepsAutoSubmitTimerRef.current);
12759
13406
  nextStepsAutoSubmitTimerRef.current = void 0;
12760
13407
  setNextStepsAutoSubmitCountdown(null);
13408
+ setNextStepsAutoSubmitLabel(null);
12761
13409
  nextStepsAutoSubmitSuggestionRef.current = null;
12762
13410
  }
12763
- setDraft(next3, cursor);
13411
+ setDraft(next3, deleteStart);
12764
13412
  return;
12765
13413
  }
12766
13414
  if (cursor >= buffer.length) return;
@@ -12778,11 +13426,7 @@ function App({
12778
13426
  }
12779
13427
  if (key.leftArrow) {
12780
13428
  if (key.ctrl) {
12781
- if (cursor === 0) return;
12782
- const beforeCursor = buffer.slice(0, cursor);
12783
- const prevWordStart = beforeCursor.lastIndexOf(" ");
12784
- const target = prevWordStart === -1 ? 0 : prevWordStart + 1;
12785
- setDraft(buffer, target);
13429
+ setDraft(buffer, previousInputWordStart(buffer, cursor));
12786
13430
  return;
12787
13431
  }
12788
13432
  if (cursor > 0) setDraft(buffer, cursor - 1);
@@ -12790,11 +13434,7 @@ function App({
12790
13434
  }
12791
13435
  if (key.rightArrow) {
12792
13436
  if (key.ctrl) {
12793
- if (cursor >= buffer.length) return;
12794
- const afterCursor = buffer.slice(cursor);
12795
- const nextWordStart = afterCursor.indexOf(" ");
12796
- const target = nextWordStart === -1 ? buffer.length : cursor + nextWordStart + 1;
12797
- setDraft(buffer, target);
13437
+ setDraft(buffer, nextInputWordStart(buffer, cursor));
12798
13438
  return;
12799
13439
  }
12800
13440
  if (cursor < buffer.length) setDraft(buffer, cursor + 1);
@@ -13562,6 +14202,7 @@ User message:
13562
14202
  );
13563
14203
  const inputHeight = Math.max(1, inputCellRows.length);
13564
14204
  const hideInput = enhanceActive || state.helpOpen || state.processListOpen;
14205
+ const lowerFunctionPanelOpen = state.monitorOpen || state.agentsMonitorOpen || (state.autoPhase?.monitorOpen ?? false) || state.worktreeMonitorOpen || state.planPanelOpen || state.todosMonitorOpen || state.queuePanelOpen || state.processListOpen || state.goalPanelOpen;
13565
14206
  return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, flexShrink: 0, children: [
13566
14207
  mouseMode ? /* @__PURE__ */ jsx(
13567
14208
  ScrollableHistory,
@@ -13676,12 +14317,18 @@ User message:
13676
14317
  logLevel: state.settingsPicker.logLevel,
13677
14318
  auditLevel: state.settingsPicker.auditLevel,
13678
14319
  indexOnStart: state.settingsPicker.indexOnStart,
14320
+ thinkingWord: state.settingsPicker.thinkingWord,
13679
14321
  maxIterations: state.settingsPicker.maxIterations,
13680
14322
  autoProceedMaxIterations: state.settingsPicker.autoProceedMaxIterations,
13681
14323
  enhanceDelayMs: state.settingsPicker.enhanceDelayMs,
13682
14324
  enhanceEnabled: state.settingsPicker.enhanceEnabled,
13683
14325
  enhanceLanguage: state.settingsPicker.enhanceLanguage,
13684
14326
  debugStream: state.settingsPicker.debugStream,
14327
+ statuslineMode: state.settingsPicker.statuslineMode,
14328
+ reasoningMode: state.settingsPicker.reasoningMode,
14329
+ reasoningEffort: state.settingsPicker.reasoningEffort,
14330
+ reasoningPreserve: state.settingsPicker.reasoningPreserve,
14331
+ cacheTtl: state.settingsPicker.cacheTtl,
13685
14332
  configScope: state.settingsPicker.configScope,
13686
14333
  hint: state.settingsPicker.hint
13687
14334
  }
@@ -13841,6 +14488,7 @@ User message:
13841
14488
  model: `${liveProvider}/${liveModel}`,
13842
14489
  version: appVersion,
13843
14490
  state: state.status,
14491
+ thinkingWord: liveThinkingWord,
13844
14492
  tokenCounter,
13845
14493
  hint: renderRunningTools(state.runningTools) || state.hint,
13846
14494
  queueCount: state.queue.length,
@@ -13860,6 +14508,7 @@ User message:
13860
14508
  subagentCount: Object.keys(state.fleet).length,
13861
14509
  processCount: getProcessRegistry().activeCount,
13862
14510
  hiddenItems,
14511
+ mode: liveStatuslineMode,
13863
14512
  visibleChips: state.statuslinePicker.visibleChips,
13864
14513
  events,
13865
14514
  eternalStage: state.eternalStage,
@@ -13896,7 +14545,8 @@ User message:
13896
14545
  totalCost: state.fleetCost,
13897
14546
  leaderCost: tokenCounter?.estimateCost().total ?? 0,
13898
14547
  totalTokens: state.fleetTokens,
13899
- nowTick
14548
+ nowTick,
14549
+ onClose: () => dispatch({ type: "toggleAgentsMonitor" })
13900
14550
  }
13901
14551
  ) : state.autoPhase?.monitorOpen ? /* @__PURE__ */ jsx(
13902
14552
  PhaseMonitor,
@@ -13924,6 +14574,21 @@ User message:
13924
14574
  nowTick,
13925
14575
  collabSession: state.collabSession
13926
14576
  }
14577
+ ) : state.planPanelOpen ? /* @__PURE__ */ jsx(
14578
+ PlanPanel,
14579
+ {
14580
+ projectRoot: agent.ctx.projectRoot,
14581
+ sessionId: agent.ctx.session?.id ?? null,
14582
+ onClose: () => dispatch({ type: "togglePlanPanel" })
14583
+ }
14584
+ ) : state.queuePanelOpen ? /* @__PURE__ */ jsx(QueuePanel, { items: state.queue }) : state.processListOpen ? /* @__PURE__ */ jsx(ProcessListMonitor, {}) : state.goalPanelOpen ? /* @__PURE__ */ jsx(
14585
+ GoalPanel,
14586
+ {
14587
+ goal: state.goalSummary,
14588
+ onCoordinatorStart: onCoordinatorStart ?? void 0,
14589
+ onCoordinatorStop: onCoordinatorStop ?? void 0,
14590
+ coordinatorRunning
14591
+ }
13927
14592
  ) : director ? /* @__PURE__ */ jsx(
13928
14593
  FleetPanel,
13929
14594
  {
@@ -13933,7 +14598,7 @@ User message:
13933
14598
  collabSession: state.collabSession
13934
14599
  }
13935
14600
  ) : null,
13936
- state.autoPhase && !state.autoPhase.monitorOpen ? /* @__PURE__ */ jsx(
14601
+ state.autoPhase && !lowerFunctionPanelOpen ? /* @__PURE__ */ jsx(
13937
14602
  PhasePanel,
13938
14603
  {
13939
14604
  phases: state.autoPhase.phases,
@@ -13941,26 +14606,7 @@ User message:
13941
14606
  nowTick
13942
14607
  }
13943
14608
  ) : null,
13944
- Object.keys(state.worktrees).length > 0 && !state.worktreeMonitorOpen && !state.monitorOpen ? /* @__PURE__ */ jsx(WorktreePanel, { worktrees: state.worktrees, nowTick }) : null,
13945
- state.queuePanelOpen ? /* @__PURE__ */ jsx(QueuePanel, { items: state.queue }) : null,
13946
- state.processListOpen ? /* @__PURE__ */ jsx(ProcessListMonitor, {}) : null,
13947
- state.planPanelOpen ? /* @__PURE__ */ jsx(
13948
- PlanPanel,
13949
- {
13950
- projectRoot,
13951
- sessionId: agent.ctx.session?.id ?? null,
13952
- onClose: () => dispatch({ type: "togglePlanPanel" })
13953
- }
13954
- ) : null,
13955
- state.goalPanelOpen ? /* @__PURE__ */ jsx(
13956
- GoalPanel,
13957
- {
13958
- goal: state.goalSummary,
13959
- onCoordinatorStart: onCoordinatorStart ?? void 0,
13960
- onCoordinatorStop: onCoordinatorStop ?? void 0,
13961
- coordinatorRunning
13962
- }
13963
- ) : null,
14609
+ Object.keys(state.worktrees).length > 0 && !lowerFunctionPanelOpen ? /* @__PURE__ */ jsx(WorktreePanel, { worktrees: state.worktrees, nowTick }) : null,
13964
14610
  (() => {
13965
14611
  const anyMonitorOpen = state.agentsMonitorOpen || (state.autoPhase?.monitorOpen ?? false) || state.worktreeMonitorOpen || state.todosMonitorOpen || state.monitorOpen || state.processListOpen || state.queuePanelOpen || state.goalPanelOpen;
13966
14612
  let nextPanelHint;
@@ -14208,7 +14854,9 @@ async function runTui(opts) {
14208
14854
  if (!opts.projectRoot) return null;
14209
14855
  try {
14210
14856
  const projectDir = resolveProjectDir(opts.projectRoot, wstackGlobalRoot());
14211
- const mailbox = new GlobalMailbox(projectDir, opts.events);
14857
+ const hqPublisher = createHqPublisherFromEnv({ clientKind: "tui", projectRoot: opts.projectRoot, projectName: path5.basename(opts.projectRoot), appConfig: opts.appConfig });
14858
+ hqPublisher?.connect();
14859
+ const mailbox = new GlobalMailbox(projectDir, opts.events, hqPublisher);
14212
14860
  const clientId = `tui@${randomUUID().slice(0, 8)}`;
14213
14861
  await mailbox.registerClient({
14214
14862
  clientId,
@@ -14360,7 +15008,12 @@ async function runTui(opts) {
14360
15008
  subscribeCoordinatorEvents: opts.subscribeCoordinatorEvents,
14361
15009
  onPanelOpen: opts.onPanelOpen,
14362
15010
  onCoordinatorStart: opts.onCoordinatorStart,
14363
- onCoordinatorStop: opts.onCoordinatorStop
15011
+ onCoordinatorStop: opts.onCoordinatorStop,
15012
+ onCoordinatorTasks: opts.onCoordinatorTasks,
15013
+ onCoordinatorClaim: opts.onCoordinatorClaim,
15014
+ onCoordinatorComplete: opts.onCoordinatorComplete,
15015
+ onCoordinatorFail: opts.onCoordinatorFail,
15016
+ onCoordinatorStatus: opts.onCoordinatorStatus
14364
15017
  }),
14365
15018
  { exitOnCtrlC: false, stdin: inkStdin }
14366
15019
  );