@wrongstack/tui 0.89.1 → 0.89.3

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) {
@@ -4533,7 +4510,7 @@ function SettingsPicker({
4533
4510
  };
4534
4511
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
4535
4512
  /* @__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" }),
4513
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 field \xB7 \u2190/\u2192 change (instant save) \xB7 Esc close" }),
4537
4514
  hasAbove ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2191 ${windowStart} field${windowStart === 1 ? "" : "s"} above` }) : null,
4538
4515
  rows.map((row, i) => {
4539
4516
  const fieldAtRow = fieldRowIndex.indexOf(i);
@@ -5556,12 +5533,6 @@ function useBrainEvents(events, dispatch) {
5556
5533
  };
5557
5534
  }, [events, dispatch]);
5558
5535
  }
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
5536
  var STREAM_COLORS2 = ["cyan", "magenta", "yellow", "green", "blue"];
5566
5537
  function labelFor2(labelsRef, id, name) {
5567
5538
  const m = labelsRef.current;
@@ -5570,7 +5541,7 @@ function labelFor2(labelsRef, id, name) {
5570
5541
  const n = m.size + 1;
5571
5542
  const v = {
5572
5543
  label: name && name !== id ? name : `AGENT#${n}`,
5573
- color: expectDefined4(STREAM_COLORS2[(n - 1) % STREAM_COLORS2.length])
5544
+ color: expectDefined(STREAM_COLORS2[(n - 1) % STREAM_COLORS2.length])
5574
5545
  };
5575
5546
  m.set(id, v);
5576
5547
  return v;
@@ -6099,14 +6070,6 @@ function buildSteeringPreamble(snapshot, newDirection) {
6099
6070
  lines.push("]");
6100
6071
  return lines.join("\n");
6101
6072
  }
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
6073
  function reducer(state, action) {
6111
6074
  switch (action.type) {
6112
6075
  case "addEntry": {
@@ -6471,13 +6434,13 @@ function reducer(state, action) {
6471
6434
  const i = SETTINGS_MODES.indexOf(sp.mode);
6472
6435
  const base = i < 0 ? 0 : i;
6473
6436
  const next = (base + action.delta + SETTINGS_MODES.length) % SETTINGS_MODES.length;
6474
- return { ...state, settingsPicker: { ...sp, mode: expectDefined5(SETTINGS_MODES[next]), hint: void 0 } };
6437
+ return { ...state, settingsPicker: { ...sp, mode: expectDefined(SETTINGS_MODES[next]), hint: void 0 } };
6475
6438
  }
6476
6439
  if (f === 1) {
6477
6440
  const j = DELAY_PRESETS_MS.indexOf(sp.delayMs);
6478
6441
  const base = j < 0 ? 0 : j;
6479
6442
  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 } };
6443
+ return { ...state, settingsPicker: { ...sp, delayMs: expectDefined(DELAY_PRESETS_MS[next]), hint: void 0 } };
6481
6444
  }
6482
6445
  if (f === 2) return { ...state, settingsPicker: { ...sp, titleAnimation: !sp.titleAnimation, hint: void 0 } };
6483
6446
  if (f === 3) return { ...state, settingsPicker: { ...sp, yolo: !sp.yolo, hint: void 0 } };
@@ -6495,26 +6458,26 @@ function reducer(state, action) {
6495
6458
  const i = COMPACTOR_STRATEGIES.indexOf(sp.contextStrategy);
6496
6459
  const base = i < 0 ? 0 : i;
6497
6460
  const next = (base + action.delta + COMPACTOR_STRATEGIES.length) % COMPACTOR_STRATEGIES.length;
6498
- return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined5(COMPACTOR_STRATEGIES[next]), hint: void 0 } };
6461
+ return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined(COMPACTOR_STRATEGIES[next]), hint: void 0 } };
6499
6462
  }
6500
6463
  if (f === 15) {
6501
6464
  const i = LOG_LEVELS.indexOf(sp.logLevel);
6502
6465
  const base = i < 0 ? 0 : i;
6503
6466
  const next = (base + action.delta + LOG_LEVELS.length) % LOG_LEVELS.length;
6504
- return { ...state, settingsPicker: { ...sp, logLevel: expectDefined5(LOG_LEVELS[next]), hint: void 0 } };
6467
+ return { ...state, settingsPicker: { ...sp, logLevel: expectDefined(LOG_LEVELS[next]), hint: void 0 } };
6505
6468
  }
6506
6469
  if (f === 16) {
6507
6470
  const i = AUDIT_LEVELS.indexOf(sp.auditLevel);
6508
6471
  const base = i < 0 ? 0 : i;
6509
6472
  const next = (base + action.delta + AUDIT_LEVELS.length) % AUDIT_LEVELS.length;
6510
- return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined5(AUDIT_LEVELS[next]), hint: void 0 } };
6473
+ return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined(AUDIT_LEVELS[next]), hint: void 0 } };
6511
6474
  }
6512
6475
  if (f === 17) return { ...state, settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: void 0 } };
6513
6476
  {
6514
6477
  const j = MAX_ITERATIONS_PRESETS.indexOf(sp.maxIterations);
6515
6478
  const base = j < 0 ? 0 : j;
6516
6479
  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 } };
6480
+ return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
6518
6481
  }
6519
6482
  }
6520
6483
  case "settingsHint":
@@ -7169,12 +7132,6 @@ function reducer(state, action) {
7169
7132
  }
7170
7133
  }
7171
7134
  }
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
7135
  var INPUT_PROMPT = "\u203A ";
7179
7136
  function selectedSlashCommandLine(picker) {
7180
7137
  if (!picker.open || picker.matches.length === 0) return null;
@@ -7438,6 +7395,12 @@ function App({
7438
7395
  const t = setInterval(() => setNowTick(Date.now()), 1e4);
7439
7396
  return () => clearInterval(t);
7440
7397
  }, []);
7398
+ const [enhanceDots, setEnhanceDots] = useState(0);
7399
+ useEffect(() => {
7400
+ if (!state.enhanceBusy) return;
7401
+ const t = setInterval(() => setEnhanceDots((n) => (n + 1) % 4), 400);
7402
+ return () => clearInterval(t);
7403
+ }, [state.enhanceBusy]);
7441
7404
  const todosRef = useRef(JSON.stringify([]));
7442
7405
  useEffect(() => {
7443
7406
  const poll = () => {
@@ -7587,8 +7550,74 @@ function App({
7587
7550
  state.toolStream?.text,
7588
7551
  eraseLiveRegion
7589
7552
  ]);
7553
+ const resizeGateRef = useRef(0);
7554
+ const preResizePanelsRef = useRef(null);
7590
7555
  useEffect(() => {
7591
- const handleResize = () => eraseLiveRegion();
7556
+ const handleResize = () => {
7557
+ const seq = ++resizeGateRef.current;
7558
+ preResizePanelsRef.current = {
7559
+ settings: stateRef.current.settingsPicker.open,
7560
+ help: stateRef.current.helpOpen,
7561
+ monitor: stateRef.current.monitorOpen,
7562
+ agents: stateRef.current.agentsMonitorOpen,
7563
+ worktree: stateRef.current.worktreeMonitorOpen,
7564
+ todos: stateRef.current.todosMonitorOpen,
7565
+ queue: stateRef.current.queuePanelOpen,
7566
+ processList: stateRef.current.processListOpen
7567
+ };
7568
+ if (stateRef.current.settingsPicker.open) dispatch({ type: "settingsClose" });
7569
+ if (stateRef.current.modelPicker.open) dispatch({ type: "modelPickerClose" });
7570
+ if (stateRef.current.autonomyPicker.open) dispatch({ type: "autonomyPickerClose" });
7571
+ if (stateRef.current.slashPicker.open) dispatch({ type: "slashPickerClose" });
7572
+ if (stateRef.current.picker.open) dispatch({ type: "pickerClose" });
7573
+ if (stateRef.current.rewindOverlay) dispatch({ type: "rewindOverlayClose" });
7574
+ if (stateRef.current.helpOpen) dispatch({ type: "toggleHelp" });
7575
+ if (stateRef.current.monitorOpen) dispatch({ type: "toggleMonitor" });
7576
+ if (stateRef.current.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
7577
+ if (stateRef.current.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
7578
+ if (stateRef.current.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
7579
+ if (stateRef.current.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
7580
+ if (stateRef.current.processListOpen) dispatch({ type: "toggleProcessList" });
7581
+ eraseLiveRegion();
7582
+ setTimeout(() => {
7583
+ if (resizeGateRef.current !== seq) return;
7584
+ const prev = preResizePanelsRef.current;
7585
+ if (!prev) return;
7586
+ if (prev.settings) {
7587
+ const sp = stateRef.current.settingsPicker;
7588
+ dispatch({
7589
+ type: "settingsOpen",
7590
+ mode: sp.mode,
7591
+ delayMs: sp.delayMs,
7592
+ titleAnimation: sp.titleAnimation,
7593
+ yolo: sp.yolo,
7594
+ streamFleet: sp.streamFleet,
7595
+ chime: sp.chime,
7596
+ confirmExit: sp.confirmExit,
7597
+ nextPrediction: sp.nextPrediction,
7598
+ featureMcp: sp.featureMcp,
7599
+ featurePlugins: sp.featurePlugins,
7600
+ featureMemory: sp.featureMemory,
7601
+ featureSkills: sp.featureSkills,
7602
+ featureModelsRegistry: sp.featureModelsRegistry,
7603
+ contextAutoCompact: sp.contextAutoCompact,
7604
+ contextStrategy: sp.contextStrategy,
7605
+ logLevel: sp.logLevel,
7606
+ auditLevel: sp.auditLevel,
7607
+ indexOnStart: sp.indexOnStart,
7608
+ maxIterations: sp.maxIterations
7609
+ });
7610
+ }
7611
+ if (prev.help) dispatch({ type: "toggleHelp" });
7612
+ if (prev.monitor) dispatch({ type: "toggleMonitor" });
7613
+ if (prev.agents) dispatch({ type: "toggleAgentsMonitor" });
7614
+ if (prev.worktree) dispatch({ type: "worktreeMonitorToggle" });
7615
+ if (prev.todos) dispatch({ type: "toggleTodosMonitor" });
7616
+ if (prev.queue) dispatch({ type: "toggleQueuePanel" });
7617
+ if (prev.processList) dispatch({ type: "toggleProcessList" });
7618
+ preResizePanelsRef.current = null;
7619
+ }, 300);
7620
+ };
7592
7621
  process.stdout.on("resize", handleResize);
7593
7622
  return () => {
7594
7623
  process.stdout.off("resize", handleResize);
@@ -7596,7 +7625,7 @@ function App({
7596
7625
  }, [eraseLiveRegion]);
7597
7626
  React6.useLayoutEffect(() => {
7598
7627
  if (state.enhanceBusy || state.enhance != null) eraseLiveRegion();
7599
- }, [state.enhanceBusy, state.enhance, eraseLiveRegion]);
7628
+ });
7600
7629
  useEffect(() => {
7601
7630
  const detected = detectAtToken(state.buffer, state.cursor);
7602
7631
  if (!detected) {
@@ -7912,6 +7941,66 @@ function App({
7912
7941
  maxIterations: s2.maxIterations ?? 500
7913
7942
  });
7914
7943
  }, [getSettings]);
7944
+ const settingsAutoSaveGateRef = useRef(true);
7945
+ useEffect(() => {
7946
+ if (state.settingsPicker.open) {
7947
+ settingsAutoSaveGateRef.current = true;
7948
+ }
7949
+ }, [state.settingsPicker.open]);
7950
+ useEffect(() => {
7951
+ const sp = state.settingsPicker;
7952
+ const save = saveSettings;
7953
+ if (!sp.open || !save) return;
7954
+ if (settingsAutoSaveGateRef.current) {
7955
+ settingsAutoSaveGateRef.current = false;
7956
+ return;
7957
+ }
7958
+ Promise.resolve(save({
7959
+ mode: sp.mode,
7960
+ delayMs: sp.delayMs,
7961
+ titleAnimation: sp.titleAnimation,
7962
+ yolo: sp.yolo,
7963
+ streamFleet: sp.streamFleet,
7964
+ chime: sp.chime,
7965
+ confirmExit: sp.confirmExit,
7966
+ nextPrediction: sp.nextPrediction,
7967
+ featureMcp: sp.featureMcp,
7968
+ featurePlugins: sp.featurePlugins,
7969
+ featureMemory: sp.featureMemory,
7970
+ featureSkills: sp.featureSkills,
7971
+ featureModelsRegistry: sp.featureModelsRegistry,
7972
+ contextAutoCompact: sp.contextAutoCompact,
7973
+ contextStrategy: sp.contextStrategy,
7974
+ logLevel: sp.logLevel,
7975
+ auditLevel: sp.auditLevel,
7976
+ indexOnStart: sp.indexOnStart,
7977
+ maxIterations: sp.maxIterations
7978
+ })).then((err) => {
7979
+ if (err) dispatch({ type: "settingsHint", text: err });
7980
+ });
7981
+ }, [
7982
+ state.settingsPicker.open,
7983
+ state.settingsPicker.mode,
7984
+ state.settingsPicker.delayMs,
7985
+ state.settingsPicker.titleAnimation,
7986
+ state.settingsPicker.yolo,
7987
+ state.settingsPicker.streamFleet,
7988
+ state.settingsPicker.chime,
7989
+ state.settingsPicker.confirmExit,
7990
+ state.settingsPicker.nextPrediction,
7991
+ state.settingsPicker.featureMcp,
7992
+ state.settingsPicker.featurePlugins,
7993
+ state.settingsPicker.featureMemory,
7994
+ state.settingsPicker.featureSkills,
7995
+ state.settingsPicker.featureModelsRegistry,
7996
+ state.settingsPicker.contextAutoCompact,
7997
+ state.settingsPicker.contextStrategy,
7998
+ state.settingsPicker.logLevel,
7999
+ state.settingsPicker.auditLevel,
8000
+ state.settingsPicker.indexOnStart,
8001
+ state.settingsPicker.maxIterations,
8002
+ saveSettings
8003
+ ]);
7915
8004
  useEffect(() => {
7916
8005
  if (!getPickableProviders || !switchProviderAndModel) return;
7917
8006
  const cmd = {
@@ -8277,15 +8366,22 @@ function App({
8277
8366
  const commitPaste = async (full) => {
8278
8367
  const builder = builderRef.current;
8279
8368
  if (!builder || !full) return;
8280
- if (builder.wouldCollapse(full) || full.includes("\n")) {
8369
+ const { buffer, cursor } = draftRef.current;
8370
+ const isSlashCmd = buffer.trimStart().startsWith("/");
8371
+ const mustCollapse = builder.wouldCollapse(full);
8372
+ const multiLine = full.includes("\n");
8373
+ if (isSlashCmd && !mustCollapse) {
8374
+ const next2 = buffer.slice(0, cursor) + full + buffer.slice(cursor);
8375
+ setDraft(next2, cursor + full.length);
8376
+ return;
8377
+ }
8378
+ if (mustCollapse || multiLine) {
8281
8379
  const token = await builder.registerPaste(full);
8282
8380
  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);
8381
+ const next2 = buffer.slice(0, cursor) + token + buffer.slice(cursor);
8382
+ setDraft(next2, cursor + token.length);
8286
8383
  return;
8287
8384
  }
8288
- const { buffer, cursor } = draftRef.current;
8289
8385
  const next = buffer.slice(0, cursor) + full + buffer.slice(cursor);
8290
8386
  setDraft(next, cursor + full.length);
8291
8387
  };
@@ -8455,12 +8551,6 @@ function App({
8455
8551
  const now = Date.now();
8456
8552
  if (now - lastEnterAtRef.current < 50) return;
8457
8553
  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
8554
  dispatch({ type: "settingsClose" });
8465
8555
  return;
8466
8556
  }
@@ -9235,10 +9325,10 @@ function App({
9235
9325
  dispatch({ type: "enhanceBusy", on: true });
9236
9326
  const ac = new AbortController();
9237
9327
  enhanceAbortRef.current = ac;
9238
- let refined = null;
9328
+ let result = null;
9239
9329
  let enhanceErr = null;
9240
9330
  try {
9241
- refined = await enhanceUserPrompt({
9331
+ result = await enhanceUserPrompt({
9242
9332
  provider: agent.ctx.provider,
9243
9333
  model: agent.ctx.model,
9244
9334
  text: trimmed,
@@ -9254,7 +9344,7 @@ function App({
9254
9344
  enhanceAbortRef.current = null;
9255
9345
  dispatch({ type: "enhanceBusy", on: false });
9256
9346
  }
9257
- if (refined === null && !ac.signal.aborted) {
9347
+ if (result === null && !ac.signal.aborted) {
9258
9348
  dispatch({
9259
9349
  type: "addEntry",
9260
9350
  entry: {
@@ -9263,19 +9353,31 @@ function App({
9263
9353
  }
9264
9354
  });
9265
9355
  }
9266
- if (refined && !normalizedEqual(refined, trimmed)) {
9356
+ if (result && !normalizedEqual(result.refined, trimmed)) {
9267
9357
  const decision = await new Promise((resolve) => {
9268
- dispatch({ type: "enhanceOpen", info: { original: trimmed, refined, resolve } });
9358
+ dispatch({
9359
+ type: "enhanceOpen",
9360
+ info: {
9361
+ original: trimmed,
9362
+ refined: result.refined,
9363
+ english: result.english,
9364
+ resolve
9365
+ }
9366
+ });
9269
9367
  });
9270
9368
  dispatch({ type: "enhanceClose" });
9271
9369
  if (decision === "edit") {
9272
- setDraft(refined, refined.length);
9370
+ setDraft(result.refined, result.refined.length);
9273
9371
  return;
9274
9372
  }
9275
- effectiveText = decision === "refined" ? refined : trimmed;
9373
+ if (decision === "english") {
9374
+ effectiveText = result.english;
9375
+ } else {
9376
+ effectiveText = decision === "refined" ? result.refined : trimmed;
9377
+ }
9276
9378
  }
9277
9379
  }
9278
- const sddContext = getSDDContext?.();
9380
+ const sddContext = await getSDDContext?.();
9279
9381
  if (sddContext && trimmed) {
9280
9382
  builder.appendText(`[SDD SESSION ACTIVE]
9281
9383
  ${sddContext}
@@ -9343,6 +9445,9 @@ User message:
9343
9445
  })();
9344
9446
  }, [initialAsk, initialGoal]);
9345
9447
  handleKeyRef.current = handleKey;
9448
+ const stableOnKey = useCallback((input, key) => {
9449
+ handleKeyRef.current?.(input, key);
9450
+ }, []);
9346
9451
  const inputHint = useMemo(() => {
9347
9452
  if (state.status !== "idle") return "";
9348
9453
  if (state.buffer.startsWith("/")) return "slash command \u2014 Enter to dispatch";
@@ -9369,7 +9474,7 @@ User message:
9369
9474
  cursor: state.cursor,
9370
9475
  disabled: state.status === "aborting" && !state.steeringPending || state.confirmQueue.length > 0,
9371
9476
  hint: inputHint,
9372
- onKey: handleKey
9477
+ onKey: stableOnKey
9373
9478
  }
9374
9479
  ),
9375
9480
  state.picker.open ? /* @__PURE__ */ jsx(
@@ -9462,7 +9567,7 @@ User message:
9462
9567
  }
9463
9568
  ) }) : null,
9464
9569
  state.confirmQueue.length > 0 && (() => {
9465
- const head = expectDefined6(state.confirmQueue[0]);
9570
+ const head = expectDefined(state.confirmQueue[0]);
9466
9571
  let resolved = false;
9467
9572
  const onDecision = (decision) => {
9468
9573
  if (resolved) return;
@@ -9517,7 +9622,15 @@ User message:
9517
9622
  }
9518
9623
  }
9519
9624
  ) }) : null,
9520
- state.enhanceBusy && !state.enhance ? /* @__PURE__ */ jsx(Box, { paddingX: 1, children: /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u2728 refining your request\u2026" }) }) : null,
9625
+ state.enhanceBusy && !state.enhance ? /* @__PURE__ */ jsx(Box, { paddingX: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
9626
+ "\u2728 refining",
9627
+ " ",
9628
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: state.buffer.length > 100 ? `${state.buffer.slice(0, 97)}\u2026` : state.buffer }),
9629
+ /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
9630
+ " ",
9631
+ ".".repeat(enhanceDots) || "\xA0"
9632
+ ] })
9633
+ ] }) }) : null,
9521
9634
  state.enhance ? (() => {
9522
9635
  const info = state.enhance;
9523
9636
  let resolved = false;
@@ -9531,6 +9644,7 @@ User message:
9531
9644
  {
9532
9645
  original: info.original,
9533
9646
  refined: info.refined,
9647
+ english: info.english,
9534
9648
  delayMs: enhanceDelayMs,
9535
9649
  onDecision
9536
9650
  }