@wrongstack/tui 0.89.1 → 0.104.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,7 +1,7 @@
1
- import { writeErr, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, buildChildEnv } from '@wrongstack/core';
1
+ import { expectDefined, writeErr, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, buildChildEnv } from '@wrongstack/core';
2
2
  export { buildGoalPreamble } from '@wrongstack/core';
3
- import { Box, Text, render, useApp, useStdout, Static, useInput, useStdin } from 'ink';
4
- import React6, { useState, useEffect, useReducer, useRef, useMemo, useCallback } from 'react';
3
+ import { Box, Text, useInput, useStdin, useStdout, render, useApp, Static } from 'ink';
4
+ import React6, { useState, useEffect, memo, useReducer, useRef, useMemo, useCallback } from 'react';
5
5
  import * as fs2 from 'fs/promises';
6
6
  import * as path2 from 'path';
7
7
  import { routeImagesForModel } from '@wrongstack/runtime/vision';
@@ -12,35 +12,6 @@ import { expectDefined as expectDefined$1 } from '@wrongstack/core/utils';
12
12
  import { spawn } from 'child_process';
13
13
 
14
14
  // src/run-tui.ts
15
-
16
- // src/theme.ts
17
- var theme = Object.freeze({
18
- accent: "cyan",
19
- user: "yellow",
20
- assistant: "cyan",
21
- tool: "cyan",
22
- success: "green",
23
- warn: "yellow",
24
- error: "red",
25
- dim: true,
26
- borderDefault: "gray",
27
- borderActive: "yellow",
28
- brand: "magenta",
29
- monitor: {
30
- fleet: "cyan",
31
- agents: "magenta",
32
- worktree: "green",
33
- phase: "cyan"
34
- },
35
- diffAddBg: "greenBright",
36
- diffDelBg: "redBright"
37
- });
38
- function expectDefined(value) {
39
- if (value === null || value === void 0) {
40
- throw new Error("Expected value to be defined");
41
- }
42
- return value;
43
- }
44
15
  var MODE_ICONS = {
45
16
  teach: "\u{1F9D1}\u200D\u{1F3EB}",
46
17
  brief: "\u26A1",
@@ -79,10 +50,10 @@ function StatusBar({
79
50
  fleetAgents,
80
51
  git,
81
52
  subagentCount = 0,
82
- context,
83
53
  brain,
84
54
  projectName,
85
55
  processCount,
56
+ context,
86
57
  hiddenItems,
87
58
  eternalStage,
88
59
  goalSummary,
@@ -169,9 +140,15 @@ function StatusBar({
169
140
  ] }),
170
141
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
171
142
  /* @__PURE__ */ jsx(Text, { color: "magenta", children: model }),
172
- context && context.max > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
143
+ context && !hiddenSet.has("context") ? /* @__PURE__ */ jsxs(Fragment, { children: [
173
144
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
174
- /* @__PURE__ */ jsx(ContextChip, { ctx: context })
145
+ /* @__PURE__ */ jsxs(Text, { color: context.used / context.max < 0.6 ? "green" : context.used / context.max < 0.75 ? "yellow" : "red", children: [
146
+ "ctx ",
147
+ renderMeter(context.used / context.max, 8),
148
+ " ",
149
+ Math.round(context.used / context.max * 100),
150
+ "%"
151
+ ] })
175
152
  ] }) : null,
176
153
  usage && isComfortable ? /* @__PURE__ */ jsxs(Fragment, { children: [
177
154
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
@@ -490,26 +467,6 @@ function EternalStageChip({
490
467
  ] });
491
468
  }
492
469
  }
493
- function ContextChip({ ctx }) {
494
- const ratio = Math.max(0, Math.min(1, ctx.used / ctx.max));
495
- const pct = Math.round(ratio * 100);
496
- const color = ratio >= 0.85 ? theme.error : ratio >= 0.65 ? theme.warn : theme.accent;
497
- return /* @__PURE__ */ jsxs(Text, { children: [
498
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "ctx " }),
499
- /* @__PURE__ */ jsx(Text, { color, children: renderMeter(ratio, 12) }),
500
- /* @__PURE__ */ jsxs(Text, { color, bold: true, children: [
501
- " ",
502
- pct,
503
- "%"
504
- ] }),
505
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
506
- " ",
507
- fmtTok(ctx.used),
508
- "/",
509
- fmtTok(ctx.max)
510
- ] })
511
- ] });
512
- }
513
470
  function stateChip(state, fleetRunning) {
514
471
  if (state === "idle" && fleetRunning > 0) {
515
472
  return { label: `agents \u25B6${fleetRunning}`, color: "magenta" };
@@ -1300,6 +1257,7 @@ function ConfirmPrompt({
1300
1257
  function EnhancePanel({
1301
1258
  original,
1302
1259
  refined,
1260
+ english,
1303
1261
  delayMs,
1304
1262
  onDecision
1305
1263
  }) {
@@ -1326,6 +1284,8 @@ function EnhancePanel({
1326
1284
  } else if (key.escape) {
1327
1285
  onDecision("original");
1328
1286
  } else if (input?.toLowerCase() === "e") {
1287
+ onDecision("english");
1288
+ } else if (input?.toLowerCase() === "t") {
1329
1289
  onDecision("edit");
1330
1290
  }
1331
1291
  });
@@ -1344,17 +1304,23 @@ function EnhancePanel({
1344
1304
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: original })
1345
1305
  ] }),
1346
1306
  /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
1347
- /* @__PURE__ */ jsx(Text, { color: "green", children: "refined: " }),
1307
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: "refined: " }),
1348
1308
  /* @__PURE__ */ jsx(Text, { color: "white", children: refined })
1349
1309
  ] }),
1310
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
1311
+ /* @__PURE__ */ jsx(Text, { color: "green", children: "english: " }),
1312
+ /* @__PURE__ */ jsx(Text, { color: "white", children: english })
1313
+ ] }),
1350
1314
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
1351
1315
  /* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsxs(Text, { children: [
1352
- /* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: "[Enter]" }),
1353
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: " send \xB7 " }),
1354
- /* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "[Esc]" }),
1355
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: " use original \xB7 " }),
1356
- /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "[e]" }),
1357
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "dit" })
1316
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "[Enter]" }),
1317
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " refined \xB7 " }),
1318
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: "[e]" }),
1319
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " english \xB7 " }),
1320
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "[t]" }),
1321
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " edit \xB7 " }),
1322
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "red", children: "[Esc]" }),
1323
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " original" })
1358
1324
  ] }) })
1359
1325
  ] });
1360
1326
  }
@@ -1487,6 +1453,29 @@ function FleetPanel({
1487
1453
  ] }) : null
1488
1454
  ] });
1489
1455
  }
1456
+
1457
+ // src/theme.ts
1458
+ var theme = Object.freeze({
1459
+ accent: "cyan",
1460
+ user: "yellow",
1461
+ assistant: "cyan",
1462
+ tool: "cyan",
1463
+ success: "green",
1464
+ warn: "yellow",
1465
+ error: "red",
1466
+ dim: true,
1467
+ borderDefault: "gray",
1468
+ borderActive: "yellow",
1469
+ brand: "magenta",
1470
+ monitor: {
1471
+ fleet: "cyan",
1472
+ agents: "magenta",
1473
+ worktree: "green",
1474
+ phase: "cyan"
1475
+ },
1476
+ diffAddBg: "greenBright",
1477
+ diffDelBg: "redBright"
1478
+ });
1490
1479
  function helpSections() {
1491
1480
  const nav = [];
1492
1481
  nav.push(
@@ -2442,10 +2431,11 @@ function MarkdownView({
2442
2431
  }
2443
2432
  const quote = line.match(QUOTE_RE);
2444
2433
  if (quote && line.startsWith(">")) {
2434
+ const qContent = quote[1] ?? "";
2445
2435
  rows.push(
2446
2436
  /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
2447
2437
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
2448
- /* @__PURE__ */ jsx(InlineLine, { tokens: parseInline(quote[1] ?? ""), dim: true })
2438
+ /[\u2500-\u257F]/.test(qContent) ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", children: [...qContent].slice(0, (contentWidth ?? termWidth) - 2).map((ch, ci) => /* @__PURE__ */ jsx(Text, { dimColor: true, children: ch }, ci)) }) : /* @__PURE__ */ jsx(InlineLine, { tokens: parseInline(qContent), dim: true })
2449
2439
  ] }, `q${key++}`)
2450
2440
  );
2451
2441
  continue;
@@ -2470,6 +2460,14 @@ function MarkdownView({
2470
2460
  );
2471
2461
  continue;
2472
2462
  }
2463
+ if (/[\u2500-\u257F]/.test(line)) {
2464
+ const maxW = contentWidth ?? termWidth;
2465
+ const chars = [...line].slice(0, maxW);
2466
+ rows.push(
2467
+ /* @__PURE__ */ jsx(Box, { flexDirection: "row", children: chars.map((ch, ci) => /* @__PURE__ */ jsx(Text, { children: ch }, ci)) }, `bx${key++}`)
2468
+ );
2469
+ continue;
2470
+ }
2473
2471
  rows.push(/* @__PURE__ */ jsx(InlineLine, { tokens: parseInline(line) }, `p${key++}`));
2474
2472
  }
2475
2473
  return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: rows });
@@ -3610,7 +3608,7 @@ function History({ entries, streamingText, toolStream }) {
3610
3608
  const tail = streamingText ? tailForDisplay(streamingText, MAX_STREAM_DISPLAY_CHARS) : "";
3611
3609
  return /* @__PURE__ */ jsxs(Fragment, { children: [
3612
3610
  /* @__PURE__ */ jsx(Static, { items: entries, children: (entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth }) }, entry.id) }),
3613
- tail ? /* @__PURE__ */ jsx(AssistantTail, { text: tail, termWidth }) : null
3611
+ /* @__PURE__ */ jsx(Box, { flexGrow: 1, children: tail ? /* @__PURE__ */ jsx(AssistantTail, { text: tail, termWidth }) : null })
3614
3612
  ] });
3615
3613
  }
3616
3614
 
@@ -3716,12 +3714,6 @@ function layoutInputRows(prompt, value, cursor, width) {
3716
3714
  if (row.length > 0 || rows.length === 0) rows.push(row);
3717
3715
  return rows;
3718
3716
  }
3719
- function expectDefined3(value) {
3720
- if (value === null || value === void 0) {
3721
- throw new Error("Expected value to be defined");
3722
- }
3723
- return value;
3724
- }
3725
3717
  function renderRow2(cells, rowKey, promptColor) {
3726
3718
  const out = [];
3727
3719
  let run = "";
@@ -3778,7 +3770,7 @@ function isBackspaceOrDelete(data) {
3778
3770
  function parseMouseWheel(data) {
3779
3771
  const m = data.match(new RegExp(`^${String.fromCharCode(27)}\\[<(\\d+);(\\d+);(\\d+)([Mm])$`, "u"));
3780
3772
  if (!m) return null;
3781
- const cb = Number.parseInt(expectDefined3(m[1]), 10);
3773
+ const cb = Number.parseInt(expectDefined(m[1]), 10);
3782
3774
  if (cb === 64) return 1;
3783
3775
  if (cb === 65) return -1;
3784
3776
  return null;
@@ -3801,7 +3793,7 @@ var EMPTY_KEY = {
3801
3793
  home: false,
3802
3794
  end: false
3803
3795
  };
3804
- function Input({
3796
+ var Input = memo(function Input2({
3805
3797
  prompt = "\u203A ",
3806
3798
  value,
3807
3799
  cursor,
@@ -3874,7 +3866,7 @@ function Input({
3874
3866
  ),
3875
3867
  hint ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: hint }) : null
3876
3868
  ] });
3877
- }
3869
+ });
3878
3870
  function fmtElapsed2(ms) {
3879
3871
  if (ms < 1e3) return `${ms}ms`;
3880
3872
  if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
@@ -3897,63 +3889,48 @@ function fmtRecentTool(tool) {
3897
3889
  parts.push(`${tool.outputLines}L`);
3898
3890
  return parts.join(" ");
3899
3891
  }
3900
- function fmtRecentMessage(message) {
3901
- const text = message.text.replace(/\s+/g, " ");
3902
- return text.length > 48 ? `${text.slice(0, 47)}...` : text;
3892
+ function truncToWidth(s2, width) {
3893
+ if (width <= 0) return "";
3894
+ if (s2.length <= width) return s2;
3895
+ if (width === 1) return "\u2026";
3896
+ return `${s2.slice(0, width - 1)}\u2026`;
3897
+ }
3898
+ function formatRow(e, now) {
3899
+ const toolElapsed = e.currentTool ? now - e.currentTool.startedAt : 0;
3900
+ const taskElapsed = now - e.startedAt;
3901
+ const toolSeg = e.currentTool ? `\u2192 ${e.currentTool.name} (${fmtElapsed2(toolElapsed)})` : "\xB7";
3902
+ const recentTools = (e.recentTools ?? []).slice(-2).map(fmtRecentTool).join(" | ");
3903
+ const head = `${e.name.slice(0, 14).padEnd(14)} \xB7 ${toolSeg} \xB7 ${e.iterations}it ${e.toolCalls}tc \xB7 ${fmtElapsed2(taskElapsed)}`;
3904
+ return recentTools ? `${head} | last: ${recentTools}` : head;
3905
+ }
3906
+ function activityStripRows(entries, now, maxRows, width) {
3907
+ const bodyWidth = Math.max(0, width - 2);
3908
+ const running = Object.values(entries).filter((e) => e.status === "running").sort((a, b) => a.startedAt - b.startedAt);
3909
+ const rows = [];
3910
+ const overflow = running.length > maxRows;
3911
+ const shown = overflow ? running.slice(0, maxRows - 1) : running.slice(0, maxRows);
3912
+ for (const e of shown) rows.push(truncToWidth(formatRow(e, now), bodyWidth));
3913
+ if (overflow)
3914
+ rows.push(truncToWidth(`\u2026+${running.length - (maxRows - 1)} more running`, bodyWidth));
3915
+ while (rows.length < maxRows) rows.push("");
3916
+ return rows;
3903
3917
  }
3904
3918
  var LiveActivityStrip = React6.memo(function LiveActivityStrip2({
3905
3919
  entries,
3906
3920
  nowTick,
3907
3921
  maxRows = 4
3908
3922
  }) {
3909
- const running = Object.values(entries).filter((e) => e.status === "running").sort((a, b) => a.startedAt - b.startedAt).slice(0, maxRows);
3910
- if (running.length === 0) {
3911
- if (Object.keys(entries).length === 0) return null;
3912
- return /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingX: 1, children: Array.from({ length: maxRows }, (_, slot) => slot).map((slot) => /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }, `empty-${slot}`)) });
3913
- }
3914
- const now = Date.now();
3915
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
3916
- running.map((e) => {
3917
- const toolElapsed = e.currentTool ? now - e.currentTool.startedAt : 0;
3918
- const taskElapsed = now - e.startedAt;
3919
- const toolSeg = e.currentTool ? `\u2192 ${e.currentTool.name} (${fmtElapsed2(toolElapsed)})` : "idle between tools";
3920
- const recentTools = (e.recentTools ?? []).slice(-2).map(fmtRecentTool).join(" | ");
3921
- const messageText = e.streamingText.trim() || (e.recentMessages ?? []).slice(-1).map(fmtRecentMessage).join("");
3922
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
3923
- /* @__PURE__ */ jsx(Text, { color: theme.accent, children: "\u25CF" }),
3924
- /* @__PURE__ */ jsx(Text, { children: e.name.slice(0, 14).padEnd(14) }),
3925
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
3926
- /* @__PURE__ */ jsx(Text, { color: e.currentTool ? theme.success : theme.warn, children: toolSeg }),
3927
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
3928
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
3929
- e.iterations,
3930
- "it ",
3931
- e.toolCalls,
3932
- "tc \xB7 ",
3933
- fmtElapsed2(taskElapsed)
3934
- ] }),
3935
- recentTools ? /* @__PURE__ */ jsxs(Fragment, { children: [
3936
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "|" }),
3937
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
3938
- "last: ",
3939
- recentTools
3940
- ] })
3941
- ] }) : null,
3942
- messageText ? /* @__PURE__ */ jsxs(Fragment, { children: [
3943
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "|" }),
3944
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
3945
- "msg: ",
3946
- fmtRecentMessage({ text: messageText})
3947
- ] })
3948
- ] }) : null
3949
- ] }, e.id);
3950
- }),
3951
- Object.values(entries).filter((e) => e.status === "running").length > maxRows ? /* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
3952
- "\u2026+",
3953
- Object.values(entries).filter((e) => e.status === "running").length - maxRows,
3954
- " more"
3955
- ] }) }) : null
3956
- ] });
3923
+ const { stdout } = useStdout();
3924
+ const width = Math.max(10, (stdout?.columns ?? 80) - 2);
3925
+ if (Object.keys(entries).length === 0) return null;
3926
+ const rows = activityStripRows(entries, Date.now(), maxRows, width);
3927
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingX: 1, children: rows.map((text, slot) => (
3928
+ // biome-ignore lint/suspicious/noArrayIndexKey: fixed-height slots, index IS the identity
3929
+ /* @__PURE__ */ jsx(Box, { height: 1, children: text === "" ? /* @__PURE__ */ jsx(Text, { children: " " }) : /* @__PURE__ */ jsxs(Fragment, { children: [
3930
+ /* @__PURE__ */ jsx(Text, { color: theme.accent, children: "\u25CF " }),
3931
+ /* @__PURE__ */ jsx(Text, { dimColor: true, wrap: "truncate", children: text })
3932
+ ] }) }, `strip-${slot}`)
3933
+ )) });
3957
3934
  });
3958
3935
  var MAX_VISIBLE = 10;
3959
3936
  function getVisibleWindow(selected, total) {
@@ -4347,6 +4324,106 @@ function ProcessListMonitor() {
4347
4324
  ] })
4348
4325
  ] });
4349
4326
  }
4327
+ function GoalPanel({ goal }) {
4328
+ if (!goal) {
4329
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
4330
+ /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: "\u{1F3AF} Goal" }) }),
4331
+ /* @__PURE__ */ jsxs(Box, { children: [
4332
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No goal set. Use " }),
4333
+ /* @__PURE__ */ jsxs(Text, { color: theme.accent, children: [
4334
+ "/goal set ",
4335
+ "<mission>"
4336
+ ] }),
4337
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " to create one." })
4338
+ ] }),
4339
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press F9 or Esc to close." }) })
4340
+ ] });
4341
+ }
4342
+ const displayGoal = goal.refinedGoal || goal.goal;
4343
+ const stateIcon = goal.goalState === "active" ? "\u{1F504}" : goal.goalState === "paused" ? "\u23F8" : goal.goalState === "completed" ? "\u2705" : "\u23F9";
4344
+ const stateColor = goal.goalState === "active" ? "green" : goal.goalState === "paused" ? "yellow" : goal.goalState === "completed" ? "green" : "red";
4345
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
4346
+ /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsxs(Text, { bold: true, color: theme.accent, children: [
4347
+ "\u{1F3AF} Goal \u2014 ",
4348
+ goal.goalState
4349
+ ] }) }),
4350
+ /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
4351
+ /* @__PURE__ */ jsxs(Text, { children: [
4352
+ stateIcon,
4353
+ " "
4354
+ ] }),
4355
+ /* @__PURE__ */ jsx(Text, { bold: true, children: displayGoal })
4356
+ ] }),
4357
+ goal.refinedGoal && goal.refinedGoal !== goal.goal && /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
4358
+ " (original: ",
4359
+ goal.goal.length > 60 ? goal.goal.slice(0, 57) + "\u2026" : goal.goal,
4360
+ ")"
4361
+ ] }) }),
4362
+ typeof goal.progress === "number" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
4363
+ /* @__PURE__ */ jsx(Box, { children: renderProgressBar(goal.progress, goal.progressTrend) }),
4364
+ goal.progressNote && /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
4365
+ " ",
4366
+ goal.progressNote
4367
+ ] }) })
4368
+ ] }),
4369
+ goal.deliverables && goal.deliverables.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
4370
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { bold: true, children: [
4371
+ "Deliverables (",
4372
+ goal.deliverables.length,
4373
+ "):"
4374
+ ] }) }),
4375
+ goal.deliverables.map((d, i) => {
4376
+ const done = /^\[[x✓]\]|✅|\(done\)/i.test(d);
4377
+ return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: done ? "green" : void 0, dimColor: !done, children: [
4378
+ " ",
4379
+ done ? "\u2713" : "\u25CB",
4380
+ " ",
4381
+ d
4382
+ ] }) }, i);
4383
+ })
4384
+ ] }),
4385
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
4386
+ /* @__PURE__ */ jsxs(Box, { children: [
4387
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Iterations: " }),
4388
+ /* @__PURE__ */ jsx(Text, { children: goal.iterations })
4389
+ ] }),
4390
+ /* @__PURE__ */ jsxs(Box, { children: [
4391
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "State: " }),
4392
+ /* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
4393
+ stateIcon,
4394
+ " ",
4395
+ goal.goalState
4396
+ ] })
4397
+ ] }),
4398
+ goal.lastTask && /* @__PURE__ */ jsxs(Box, { children: [
4399
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Last task: " }),
4400
+ /* @__PURE__ */ jsx(Text, { children: goal.lastTask.length > 50 ? goal.lastTask.slice(0, 47) + "\u2026" : goal.lastTask })
4401
+ ] }),
4402
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press F9 or Esc to close." }) })
4403
+ ] })
4404
+ ] });
4405
+ }
4406
+ function renderProgressBar(progress, trend) {
4407
+ const pct = Math.min(100, Math.max(0, Math.round(progress)));
4408
+ const filled = Math.round(pct / 5);
4409
+ const empty = 20 - filled;
4410
+ const trendIcon = trend === "accelerating" ? " \u{1F680}" : trend === "stalling" ? " \u26A0\uFE0F" : trend === "steady" ? " \u27A1\uFE0F" : "";
4411
+ return /* @__PURE__ */ jsxs(Box, { children: [
4412
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "Progress: " }),
4413
+ /* @__PURE__ */ jsx(Text, { color: "green", children: "\u2588".repeat(filled) }),
4414
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2591".repeat(empty) }),
4415
+ /* @__PURE__ */ jsxs(Text, { bold: true, children: [
4416
+ " ",
4417
+ pct,
4418
+ "%"
4419
+ ] }),
4420
+ trend && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
4421
+ trendIcon,
4422
+ " ",
4423
+ trend
4424
+ ] })
4425
+ ] });
4426
+ }
4350
4427
  var DELAY_PRESETS_MS = [0, 15e3, 3e4, 45e3, 6e4, 12e4];
4351
4428
  var SETTINGS_MODES = ["off", "suggest", "auto"];
4352
4429
  var LOG_LEVELS = ["error", "warn", "info", "debug", "trace"];
@@ -4533,7 +4610,7 @@ function SettingsPicker({
4533
4610
  };
4534
4611
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
4535
4612
  /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Settings \u2501\u2501" }),
4536
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 field \xB7 \u2190/\u2192 change \xB7 Enter save \xB7 Esc cancel" }),
4613
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 field \xB7 \u2190/\u2192 change (instant save) \xB7 Esc close" }),
4537
4614
  hasAbove ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2191 ${windowStart} field${windowStart === 1 ? "" : "s"} above` }) : null,
4538
4615
  rows.map((row, i) => {
4539
4616
  const fieldAtRow = fieldRowIndex.indexOf(i);
@@ -5556,12 +5633,6 @@ function useBrainEvents(events, dispatch) {
5556
5633
  };
5557
5634
  }, [events, dispatch]);
5558
5635
  }
5559
- function expectDefined4(value) {
5560
- if (value === null || value === void 0) {
5561
- throw new Error("Expected value to be defined");
5562
- }
5563
- return value;
5564
- }
5565
5636
  var STREAM_COLORS2 = ["cyan", "magenta", "yellow", "green", "blue"];
5566
5637
  function labelFor2(labelsRef, id, name) {
5567
5638
  const m = labelsRef.current;
@@ -5570,7 +5641,7 @@ function labelFor2(labelsRef, id, name) {
5570
5641
  const n = m.size + 1;
5571
5642
  const v = {
5572
5643
  label: name && name !== id ? name : `AGENT#${n}`,
5573
- color: expectDefined4(STREAM_COLORS2[(n - 1) % STREAM_COLORS2.length])
5644
+ color: expectDefined(STREAM_COLORS2[(n - 1) % STREAM_COLORS2.length])
5574
5645
  };
5575
5646
  m.set(id, v);
5576
5647
  return v;
@@ -6099,14 +6170,6 @@ function buildSteeringPreamble(snapshot, newDirection) {
6099
6170
  lines.push("]");
6100
6171
  return lines.join("\n");
6101
6172
  }
6102
-
6103
- // src/app-reducer.ts
6104
- function expectDefined5(value) {
6105
- if (value === null || value === void 0) {
6106
- throw new Error("Expected value to be defined");
6107
- }
6108
- return value;
6109
- }
6110
6173
  function reducer(state, action) {
6111
6174
  switch (action.type) {
6112
6175
  case "addEntry": {
@@ -6471,13 +6534,13 @@ function reducer(state, action) {
6471
6534
  const i = SETTINGS_MODES.indexOf(sp.mode);
6472
6535
  const base = i < 0 ? 0 : i;
6473
6536
  const next = (base + action.delta + SETTINGS_MODES.length) % SETTINGS_MODES.length;
6474
- return { ...state, settingsPicker: { ...sp, mode: expectDefined5(SETTINGS_MODES[next]), hint: void 0 } };
6537
+ return { ...state, settingsPicker: { ...sp, mode: expectDefined(SETTINGS_MODES[next]), hint: void 0 } };
6475
6538
  }
6476
6539
  if (f === 1) {
6477
6540
  const j = DELAY_PRESETS_MS.indexOf(sp.delayMs);
6478
6541
  const base = j < 0 ? 0 : j;
6479
6542
  const next = (base + action.delta + DELAY_PRESETS_MS.length) % DELAY_PRESETS_MS.length;
6480
- return { ...state, settingsPicker: { ...sp, delayMs: expectDefined5(DELAY_PRESETS_MS[next]), hint: void 0 } };
6543
+ return { ...state, settingsPicker: { ...sp, delayMs: expectDefined(DELAY_PRESETS_MS[next]), hint: void 0 } };
6481
6544
  }
6482
6545
  if (f === 2) return { ...state, settingsPicker: { ...sp, titleAnimation: !sp.titleAnimation, hint: void 0 } };
6483
6546
  if (f === 3) return { ...state, settingsPicker: { ...sp, yolo: !sp.yolo, hint: void 0 } };
@@ -6495,26 +6558,26 @@ function reducer(state, action) {
6495
6558
  const i = COMPACTOR_STRATEGIES.indexOf(sp.contextStrategy);
6496
6559
  const base = i < 0 ? 0 : i;
6497
6560
  const next = (base + action.delta + COMPACTOR_STRATEGIES.length) % COMPACTOR_STRATEGIES.length;
6498
- return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined5(COMPACTOR_STRATEGIES[next]), hint: void 0 } };
6561
+ return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined(COMPACTOR_STRATEGIES[next]), hint: void 0 } };
6499
6562
  }
6500
6563
  if (f === 15) {
6501
6564
  const i = LOG_LEVELS.indexOf(sp.logLevel);
6502
6565
  const base = i < 0 ? 0 : i;
6503
6566
  const next = (base + action.delta + LOG_LEVELS.length) % LOG_LEVELS.length;
6504
- return { ...state, settingsPicker: { ...sp, logLevel: expectDefined5(LOG_LEVELS[next]), hint: void 0 } };
6567
+ return { ...state, settingsPicker: { ...sp, logLevel: expectDefined(LOG_LEVELS[next]), hint: void 0 } };
6505
6568
  }
6506
6569
  if (f === 16) {
6507
6570
  const i = AUDIT_LEVELS.indexOf(sp.auditLevel);
6508
6571
  const base = i < 0 ? 0 : i;
6509
6572
  const next = (base + action.delta + AUDIT_LEVELS.length) % AUDIT_LEVELS.length;
6510
- return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined5(AUDIT_LEVELS[next]), hint: void 0 } };
6573
+ return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined(AUDIT_LEVELS[next]), hint: void 0 } };
6511
6574
  }
6512
6575
  if (f === 17) return { ...state, settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: void 0 } };
6513
6576
  {
6514
6577
  const j = MAX_ITERATIONS_PRESETS.indexOf(sp.maxIterations);
6515
6578
  const base = j < 0 ? 0 : j;
6516
6579
  const next = (base + action.delta + MAX_ITERATIONS_PRESETS.length) % MAX_ITERATIONS_PRESETS.length;
6517
- return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined5(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
6580
+ return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
6518
6581
  }
6519
6582
  }
6520
6583
  case "settingsHint":
@@ -6871,6 +6934,9 @@ function reducer(state, action) {
6871
6934
  case "toggleProcessList": {
6872
6935
  return { ...state, processListOpen: !state.processListOpen };
6873
6936
  }
6937
+ case "toggleGoalPanel": {
6938
+ return { ...state, goalPanelOpen: !state.goalPanelOpen };
6939
+ }
6874
6940
  case "checkpointReceived": {
6875
6941
  const existing = state.checkpoints.find((c) => c.promptIndex === action.cp.promptIndex);
6876
6942
  if (existing) return state;
@@ -7169,12 +7235,6 @@ function reducer(state, action) {
7169
7235
  }
7170
7236
  }
7171
7237
  }
7172
- function expectDefined6(value) {
7173
- if (value === null || value === void 0) {
7174
- throw new Error("Expected value to be defined");
7175
- }
7176
- return value;
7177
- }
7178
7238
  var INPUT_PROMPT = "\u203A ";
7179
7239
  function selectedSlashCommandLine(picker) {
7180
7240
  if (!picker.open || picker.matches.length === 0) return null;
@@ -7280,8 +7340,13 @@ function App({
7280
7340
  type: "goalSummary",
7281
7341
  summary: {
7282
7342
  goal: goal.goal,
7343
+ refinedGoal: goal.refinedGoal,
7283
7344
  goalState: goal.goalState ?? "active",
7284
7345
  iterations: goal.iterations,
7346
+ progress: goal.progress,
7347
+ progressNote: goal.progressNote,
7348
+ progressTrend: goal.progressTrend,
7349
+ deliverables: goal.deliverables,
7285
7350
  lastTask: lastEntry?.task,
7286
7351
  lastStatus: lastEntry?.status
7287
7352
  }
@@ -7374,6 +7439,7 @@ function App({
7374
7439
  todosMonitorOpen: false,
7375
7440
  queuePanelOpen: false,
7376
7441
  processListOpen: false,
7442
+ goalPanelOpen: false,
7377
7443
  collabSession: null,
7378
7444
  checkpoints: [],
7379
7445
  rewindOverlay: null,
@@ -7438,6 +7504,12 @@ function App({
7438
7504
  const t = setInterval(() => setNowTick(Date.now()), 1e4);
7439
7505
  return () => clearInterval(t);
7440
7506
  }, []);
7507
+ const [enhanceDots, setEnhanceDots] = useState(0);
7508
+ useEffect(() => {
7509
+ if (!state.enhanceBusy) return;
7510
+ const t = setInterval(() => setEnhanceDots((n) => (n + 1) % 4), 400);
7511
+ return () => clearInterval(t);
7512
+ }, [state.enhanceBusy]);
7441
7513
  const todosRef = useRef(JSON.stringify([]));
7442
7514
  useEffect(() => {
7443
7515
  const poll = () => {
@@ -7587,8 +7659,74 @@ function App({
7587
7659
  state.toolStream?.text,
7588
7660
  eraseLiveRegion
7589
7661
  ]);
7662
+ const resizeGateRef = useRef(0);
7663
+ const preResizePanelsRef = useRef(null);
7590
7664
  useEffect(() => {
7591
- const handleResize = () => eraseLiveRegion();
7665
+ const handleResize = () => {
7666
+ const seq = ++resizeGateRef.current;
7667
+ preResizePanelsRef.current = {
7668
+ settings: stateRef.current.settingsPicker.open,
7669
+ help: stateRef.current.helpOpen,
7670
+ monitor: stateRef.current.monitorOpen,
7671
+ agents: stateRef.current.agentsMonitorOpen,
7672
+ worktree: stateRef.current.worktreeMonitorOpen,
7673
+ todos: stateRef.current.todosMonitorOpen,
7674
+ queue: stateRef.current.queuePanelOpen,
7675
+ processList: stateRef.current.processListOpen
7676
+ };
7677
+ if (stateRef.current.settingsPicker.open) dispatch({ type: "settingsClose" });
7678
+ if (stateRef.current.modelPicker.open) dispatch({ type: "modelPickerClose" });
7679
+ if (stateRef.current.autonomyPicker.open) dispatch({ type: "autonomyPickerClose" });
7680
+ if (stateRef.current.slashPicker.open) dispatch({ type: "slashPickerClose" });
7681
+ if (stateRef.current.picker.open) dispatch({ type: "pickerClose" });
7682
+ if (stateRef.current.rewindOverlay) dispatch({ type: "rewindOverlayClose" });
7683
+ if (stateRef.current.helpOpen) dispatch({ type: "toggleHelp" });
7684
+ if (stateRef.current.monitorOpen) dispatch({ type: "toggleMonitor" });
7685
+ if (stateRef.current.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
7686
+ if (stateRef.current.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
7687
+ if (stateRef.current.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
7688
+ if (stateRef.current.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
7689
+ if (stateRef.current.processListOpen) dispatch({ type: "toggleProcessList" });
7690
+ eraseLiveRegion();
7691
+ setTimeout(() => {
7692
+ if (resizeGateRef.current !== seq) return;
7693
+ const prev = preResizePanelsRef.current;
7694
+ if (!prev) return;
7695
+ if (prev.settings) {
7696
+ const sp = stateRef.current.settingsPicker;
7697
+ dispatch({
7698
+ type: "settingsOpen",
7699
+ mode: sp.mode,
7700
+ delayMs: sp.delayMs,
7701
+ titleAnimation: sp.titleAnimation,
7702
+ yolo: sp.yolo,
7703
+ streamFleet: sp.streamFleet,
7704
+ chime: sp.chime,
7705
+ confirmExit: sp.confirmExit,
7706
+ nextPrediction: sp.nextPrediction,
7707
+ featureMcp: sp.featureMcp,
7708
+ featurePlugins: sp.featurePlugins,
7709
+ featureMemory: sp.featureMemory,
7710
+ featureSkills: sp.featureSkills,
7711
+ featureModelsRegistry: sp.featureModelsRegistry,
7712
+ contextAutoCompact: sp.contextAutoCompact,
7713
+ contextStrategy: sp.contextStrategy,
7714
+ logLevel: sp.logLevel,
7715
+ auditLevel: sp.auditLevel,
7716
+ indexOnStart: sp.indexOnStart,
7717
+ maxIterations: sp.maxIterations
7718
+ });
7719
+ }
7720
+ if (prev.help) dispatch({ type: "toggleHelp" });
7721
+ if (prev.monitor) dispatch({ type: "toggleMonitor" });
7722
+ if (prev.agents) dispatch({ type: "toggleAgentsMonitor" });
7723
+ if (prev.worktree) dispatch({ type: "worktreeMonitorToggle" });
7724
+ if (prev.todos) dispatch({ type: "toggleTodosMonitor" });
7725
+ if (prev.queue) dispatch({ type: "toggleQueuePanel" });
7726
+ if (prev.processList) dispatch({ type: "toggleProcessList" });
7727
+ preResizePanelsRef.current = null;
7728
+ }, 300);
7729
+ };
7592
7730
  process.stdout.on("resize", handleResize);
7593
7731
  return () => {
7594
7732
  process.stdout.off("resize", handleResize);
@@ -7596,7 +7734,7 @@ function App({
7596
7734
  }, [eraseLiveRegion]);
7597
7735
  React6.useLayoutEffect(() => {
7598
7736
  if (state.enhanceBusy || state.enhance != null) eraseLiveRegion();
7599
- }, [state.enhanceBusy, state.enhance, eraseLiveRegion]);
7737
+ });
7600
7738
  useEffect(() => {
7601
7739
  const detected = detectAtToken(state.buffer, state.cursor);
7602
7740
  if (!detected) {
@@ -7912,6 +8050,66 @@ function App({
7912
8050
  maxIterations: s2.maxIterations ?? 500
7913
8051
  });
7914
8052
  }, [getSettings]);
8053
+ const settingsAutoSaveGateRef = useRef(true);
8054
+ useEffect(() => {
8055
+ if (state.settingsPicker.open) {
8056
+ settingsAutoSaveGateRef.current = true;
8057
+ }
8058
+ }, [state.settingsPicker.open]);
8059
+ useEffect(() => {
8060
+ const sp = state.settingsPicker;
8061
+ const save = saveSettings;
8062
+ if (!sp.open || !save) return;
8063
+ if (settingsAutoSaveGateRef.current) {
8064
+ settingsAutoSaveGateRef.current = false;
8065
+ return;
8066
+ }
8067
+ Promise.resolve(save({
8068
+ mode: sp.mode,
8069
+ delayMs: sp.delayMs,
8070
+ titleAnimation: sp.titleAnimation,
8071
+ yolo: sp.yolo,
8072
+ streamFleet: sp.streamFleet,
8073
+ chime: sp.chime,
8074
+ confirmExit: sp.confirmExit,
8075
+ nextPrediction: sp.nextPrediction,
8076
+ featureMcp: sp.featureMcp,
8077
+ featurePlugins: sp.featurePlugins,
8078
+ featureMemory: sp.featureMemory,
8079
+ featureSkills: sp.featureSkills,
8080
+ featureModelsRegistry: sp.featureModelsRegistry,
8081
+ contextAutoCompact: sp.contextAutoCompact,
8082
+ contextStrategy: sp.contextStrategy,
8083
+ logLevel: sp.logLevel,
8084
+ auditLevel: sp.auditLevel,
8085
+ indexOnStart: sp.indexOnStart,
8086
+ maxIterations: sp.maxIterations
8087
+ })).then((err) => {
8088
+ if (err) dispatch({ type: "settingsHint", text: err });
8089
+ });
8090
+ }, [
8091
+ state.settingsPicker.open,
8092
+ state.settingsPicker.mode,
8093
+ state.settingsPicker.delayMs,
8094
+ state.settingsPicker.titleAnimation,
8095
+ state.settingsPicker.yolo,
8096
+ state.settingsPicker.streamFleet,
8097
+ state.settingsPicker.chime,
8098
+ state.settingsPicker.confirmExit,
8099
+ state.settingsPicker.nextPrediction,
8100
+ state.settingsPicker.featureMcp,
8101
+ state.settingsPicker.featurePlugins,
8102
+ state.settingsPicker.featureMemory,
8103
+ state.settingsPicker.featureSkills,
8104
+ state.settingsPicker.featureModelsRegistry,
8105
+ state.settingsPicker.contextAutoCompact,
8106
+ state.settingsPicker.contextStrategy,
8107
+ state.settingsPicker.logLevel,
8108
+ state.settingsPicker.auditLevel,
8109
+ state.settingsPicker.indexOnStart,
8110
+ state.settingsPicker.maxIterations,
8111
+ saveSettings
8112
+ ]);
7915
8113
  useEffect(() => {
7916
8114
  if (!getPickableProviders || !switchProviderAndModel) return;
7917
8115
  const cmd = {
@@ -8277,15 +8475,22 @@ function App({
8277
8475
  const commitPaste = async (full) => {
8278
8476
  const builder = builderRef.current;
8279
8477
  if (!builder || !full) return;
8280
- if (builder.wouldCollapse(full) || full.includes("\n")) {
8478
+ const { buffer, cursor } = draftRef.current;
8479
+ const isSlashCmd = buffer.trimStart().startsWith("/");
8480
+ const mustCollapse = builder.wouldCollapse(full);
8481
+ const multiLine = full.includes("\n");
8482
+ if (isSlashCmd && !mustCollapse) {
8483
+ const next2 = buffer.slice(0, cursor) + full + buffer.slice(cursor);
8484
+ setDraft(next2, cursor + full.length);
8485
+ return;
8486
+ }
8487
+ if (mustCollapse || multiLine) {
8281
8488
  const token = await builder.registerPaste(full);
8282
8489
  tokenPreviewsRef.current.set(token, truncatePastePreview(full, 6));
8283
- const { buffer: buffer2, cursor: cursor2 } = draftRef.current;
8284
- const next2 = buffer2.slice(0, cursor2) + token + buffer2.slice(cursor2);
8285
- setDraft(next2, cursor2 + token.length);
8490
+ const next2 = buffer.slice(0, cursor) + token + buffer.slice(cursor);
8491
+ setDraft(next2, cursor + token.length);
8286
8492
  return;
8287
8493
  }
8288
- const { buffer, cursor } = draftRef.current;
8289
8494
  const next = buffer.slice(0, cursor) + full + buffer.slice(cursor);
8290
8495
  setDraft(next, cursor + full.length);
8291
8496
  };
@@ -8455,12 +8660,6 @@ function App({
8455
8660
  const now = Date.now();
8456
8661
  if (now - lastEnterAtRef.current < 50) return;
8457
8662
  lastEnterAtRef.current = now;
8458
- const { mode, delayMs, titleAnimation, yolo: yolo2, streamFleet, chime: chime2, confirmExit: confirmExit2, nextPrediction, featureMcp, featurePlugins, featureMemory, featureSkills, featureModelsRegistry, contextAutoCompact, contextStrategy, logLevel, auditLevel, indexOnStart, maxIterations } = state.settingsPicker;
8459
- const err = await saveSettings?.({ mode, delayMs, titleAnimation, yolo: yolo2, streamFleet, chime: chime2, confirmExit: confirmExit2, nextPrediction, featureMcp, featurePlugins, featureMemory, featureSkills, featureModelsRegistry, contextAutoCompact, contextStrategy, logLevel, auditLevel, indexOnStart, maxIterations });
8460
- if (err) {
8461
- dispatch({ type: "settingsHint", text: err });
8462
- return;
8463
- }
8464
8663
  dispatch({ type: "settingsClose" });
8465
8664
  return;
8466
8665
  }
@@ -8717,6 +8916,23 @@ function App({
8717
8916
  }
8718
8917
  return;
8719
8918
  }
8919
+ if (key.fn === 9) {
8920
+ if (state.goalPanelOpen) {
8921
+ dispatch({ type: "toggleGoalPanel" });
8922
+ } else {
8923
+ if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
8924
+ if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
8925
+ if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
8926
+ if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
8927
+ if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
8928
+ if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
8929
+ if (state.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
8930
+ if (state.processListOpen) dispatch({ type: "toggleProcessList" });
8931
+ if (state.helpOpen) dispatch({ type: "toggleHelp" });
8932
+ dispatch({ type: "toggleGoalPanel" });
8933
+ }
8934
+ return;
8935
+ }
8720
8936
  if (key.ctrl && input === "s") {
8721
8937
  if (state.settingsPicker.open) {
8722
8938
  dispatch({ type: "settingsClose" });
@@ -8787,6 +9003,10 @@ function App({
8787
9003
  dispatch({ type: "toggleProcessList" });
8788
9004
  return;
8789
9005
  }
9006
+ if (state.goalPanelOpen) {
9007
+ dispatch({ type: "toggleGoalPanel" });
9008
+ return;
9009
+ }
8790
9010
  }
8791
9011
  if (input === "?" && !key.ctrl && !key.meta && draftRef.current.buffer === "" && !state.slashPicker.open && !state.picker.open && !state.modelPicker.open && !state.autonomyPicker.open && !state.settingsPicker.open && !state.rewindOverlay && !state.monitorOpen && !state.agentsMonitorOpen && !state.worktreeMonitorOpen && !state.todosMonitorOpen && !state.autoPhase?.monitorOpen) {
8792
9012
  dispatch({ type: "toggleHelp" });
@@ -8873,7 +9093,7 @@ function App({
8873
9093
  setDraft(buffer, buffer.length);
8874
9094
  return;
8875
9095
  }
8876
- const overlayOpen = state.monitorOpen || state.agentsMonitorOpen || state.worktreeMonitorOpen || state.todosMonitorOpen || state.queuePanelOpen || state.processListOpen || state.helpOpen || (state.autoPhase?.monitorOpen ?? false) || state.rewindOverlay !== null;
9096
+ const overlayOpen = state.monitorOpen || state.agentsMonitorOpen || state.worktreeMonitorOpen || state.todosMonitorOpen || state.queuePanelOpen || state.processListOpen || state.goalPanelOpen || state.helpOpen || (state.autoPhase?.monitorOpen ?? false) || state.rewindOverlay !== null;
8877
9097
  if (key.upArrow) {
8878
9098
  if (!overlayOpen && state.inputHistory.length > 0) {
8879
9099
  dispatch({ type: "historyUp" });
@@ -9230,18 +9450,31 @@ function App({
9230
9450
  if (!builder) return;
9231
9451
  const steering = state.steeringPending;
9232
9452
  let effectiveText = trimmed;
9233
- const hasChips = trimmed ? new RegExp(INLINE_TOKEN_SRC, "g").test(trimmed) : false;
9234
- if (enhanceEnabledRef.current && state.status === "idle" && !steering && !hasChips && shouldEnhance(trimmed)) {
9453
+ const chips = [];
9454
+ let cleanText = trimmed;
9455
+ const chipRe = new RegExp(INLINE_TOKEN_SRC, "g");
9456
+ let chipMatch;
9457
+ while ((chipMatch = chipRe.exec(trimmed)) !== null) {
9458
+ chips.push(chipMatch[0]);
9459
+ }
9460
+ if (chips.length > 0) {
9461
+ cleanText = trimmed.replace(chipRe, "").replace(/\s{2,}/g, " ").trim();
9462
+ if (!cleanText) {
9463
+ cleanText = trimmed;
9464
+ chips.length = 0;
9465
+ }
9466
+ }
9467
+ if (enhanceEnabledRef.current && state.status === "idle" && !steering && shouldEnhance(cleanText)) {
9235
9468
  dispatch({ type: "enhanceBusy", on: true });
9236
9469
  const ac = new AbortController();
9237
9470
  enhanceAbortRef.current = ac;
9238
- let refined = null;
9471
+ let result = null;
9239
9472
  let enhanceErr = null;
9240
9473
  try {
9241
- refined = await enhanceUserPrompt({
9474
+ result = await enhanceUserPrompt({
9242
9475
  provider: agent.ctx.provider,
9243
9476
  model: agent.ctx.model,
9244
- text: trimmed,
9477
+ text: cleanText,
9245
9478
  signal: ac.signal,
9246
9479
  onError: (reason) => {
9247
9480
  enhanceErr = reason;
@@ -9254,7 +9487,7 @@ function App({
9254
9487
  enhanceAbortRef.current = null;
9255
9488
  dispatch({ type: "enhanceBusy", on: false });
9256
9489
  }
9257
- if (refined === null && !ac.signal.aborted) {
9490
+ if (result === null && !ac.signal.aborted) {
9258
9491
  dispatch({
9259
9492
  type: "addEntry",
9260
9493
  entry: {
@@ -9263,19 +9496,34 @@ function App({
9263
9496
  }
9264
9497
  });
9265
9498
  }
9266
- if (refined && !normalizedEqual(refined, trimmed)) {
9499
+ if (result && !normalizedEqual(result.refined, cleanText)) {
9500
+ const chipSuffix = chips.length > 0 ? ` ${chips.join(" ")}` : "";
9501
+ const refinedWithChips = result.refined + chipSuffix;
9502
+ const englishWithChips = result.english + chipSuffix;
9267
9503
  const decision = await new Promise((resolve) => {
9268
- dispatch({ type: "enhanceOpen", info: { original: trimmed, refined, resolve } });
9504
+ dispatch({
9505
+ type: "enhanceOpen",
9506
+ info: {
9507
+ original: trimmed,
9508
+ refined: refinedWithChips,
9509
+ english: englishWithChips,
9510
+ resolve
9511
+ }
9512
+ });
9269
9513
  });
9270
9514
  dispatch({ type: "enhanceClose" });
9271
9515
  if (decision === "edit") {
9272
- setDraft(refined, refined.length);
9516
+ setDraft(refinedWithChips, refinedWithChips.length);
9273
9517
  return;
9274
9518
  }
9275
- effectiveText = decision === "refined" ? refined : trimmed;
9519
+ if (decision === "english") {
9520
+ effectiveText = englishWithChips;
9521
+ } else {
9522
+ effectiveText = decision === "refined" ? refinedWithChips : trimmed;
9523
+ }
9276
9524
  }
9277
9525
  }
9278
- const sddContext = getSDDContext?.();
9526
+ const sddContext = await getSDDContext?.();
9279
9527
  if (sddContext && trimmed) {
9280
9528
  builder.appendText(`[SDD SESSION ACTIVE]
9281
9529
  ${sddContext}
@@ -9343,6 +9591,9 @@ User message:
9343
9591
  })();
9344
9592
  }, [initialAsk, initialGoal]);
9345
9593
  handleKeyRef.current = handleKey;
9594
+ const stableOnKey = useCallback((input, key) => {
9595
+ handleKeyRef.current?.(input, key);
9596
+ }, []);
9346
9597
  const inputHint = useMemo(() => {
9347
9598
  if (state.status !== "idle") return "";
9348
9599
  if (state.buffer.startsWith("/")) return "slash command \u2014 Enter to dispatch";
@@ -9369,7 +9620,7 @@ User message:
9369
9620
  cursor: state.cursor,
9370
9621
  disabled: state.status === "aborting" && !state.steeringPending || state.confirmQueue.length > 0,
9371
9622
  hint: inputHint,
9372
- onKey: handleKey
9623
+ onKey: stableOnKey
9373
9624
  }
9374
9625
  ),
9375
9626
  state.picker.open ? /* @__PURE__ */ jsx(
@@ -9462,7 +9713,7 @@ User message:
9462
9713
  }
9463
9714
  ) }) : null,
9464
9715
  state.confirmQueue.length > 0 && (() => {
9465
- const head = expectDefined6(state.confirmQueue[0]);
9716
+ const head = expectDefined(state.confirmQueue[0]);
9466
9717
  let resolved = false;
9467
9718
  const onDecision = (decision) => {
9468
9719
  if (resolved) return;
@@ -9517,7 +9768,15 @@ User message:
9517
9768
  }
9518
9769
  }
9519
9770
  ) }) : null,
9520
- state.enhanceBusy && !state.enhance ? /* @__PURE__ */ jsx(Box, { paddingX: 1, children: /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u2728 refining your request\u2026" }) }) : null,
9771
+ state.enhanceBusy && !state.enhance ? /* @__PURE__ */ jsx(Box, { paddingX: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
9772
+ "\u2728 refining",
9773
+ " ",
9774
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: state.buffer.length > 100 ? `${state.buffer.slice(0, 97)}\u2026` : state.buffer }),
9775
+ /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
9776
+ " ",
9777
+ ".".repeat(enhanceDots) || "\xA0"
9778
+ ] })
9779
+ ] }) }) : null,
9521
9780
  state.enhance ? (() => {
9522
9781
  const info = state.enhance;
9523
9782
  let resolved = false;
@@ -9531,6 +9790,7 @@ User message:
9531
9790
  {
9532
9791
  original: info.original,
9533
9792
  refined: info.refined,
9793
+ english: info.english,
9534
9794
  delayMs: enhanceDelayMs,
9535
9795
  onDecision
9536
9796
  }
@@ -9620,7 +9880,8 @@ User message:
9620
9880
  ) : null,
9621
9881
  Object.keys(state.worktrees).length > 0 && !state.worktreeMonitorOpen && !state.monitorOpen ? /* @__PURE__ */ jsx(WorktreePanel, { worktrees: state.worktrees, nowTick }) : null,
9622
9882
  state.queuePanelOpen ? /* @__PURE__ */ jsx(QueuePanel, { items: state.queue }) : null,
9623
- state.processListOpen ? /* @__PURE__ */ jsx(ProcessListMonitor, {}) : null
9883
+ state.processListOpen ? /* @__PURE__ */ jsx(ProcessListMonitor, {}) : null,
9884
+ state.goalPanelOpen ? /* @__PURE__ */ jsx(GoalPanel, { goal: state.goalSummary }) : null
9624
9885
  ] })
9625
9886
  ] }) });
9626
9887
  }