reasonix 0.33.2 → 0.34.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dashboard/dist/app.js +1 -21
  2. package/dashboard/dist/app.js.map +1 -1
  3. package/dist/cli/{chat-ZMSAXE77.js → chat-TD6GR3QK.js} +14 -13
  4. package/dist/cli/chunk-2EBODRRO.js +149 -0
  5. package/dist/cli/chunk-2EBODRRO.js.map +1 -0
  6. package/dist/cli/{chunk-DULSP7JH.js → chunk-5JXXEPDM.js} +34 -1
  7. package/dist/cli/chunk-5JXXEPDM.js.map +1 -0
  8. package/dist/cli/{chunk-OW7IHE6M.js → chunk-EINEIIIW.js} +693 -364
  9. package/dist/cli/chunk-EINEIIIW.js.map +1 -0
  10. package/dist/cli/{chunk-WVJL7ZO2.js → chunk-F3ILWP2L.js} +4 -4
  11. package/dist/cli/{chunk-SDE5U32Z.js → chunk-KZHMKOJH.js} +13 -8
  12. package/dist/cli/{chunk-SDE5U32Z.js.map → chunk-KZHMKOJH.js.map} +1 -1
  13. package/dist/cli/{chunk-G7M3QWEN.js → chunk-LNTORE5K.js} +225 -132
  14. package/dist/cli/chunk-LNTORE5K.js.map +1 -0
  15. package/dist/cli/chunk-MRLXEMZ7.js +26 -0
  16. package/dist/cli/chunk-MRLXEMZ7.js.map +1 -0
  17. package/dist/cli/{chunk-WBDE4IRI.js → chunk-OERAGRJX.js} +2 -2
  18. package/dist/cli/{chunk-QGE6AF76.js → chunk-Q36KBLSU.js} +207 -8
  19. package/dist/cli/chunk-Q36KBLSU.js.map +1 -0
  20. package/dist/cli/{chunk-RZILUXUC.js → chunk-RXGEGA7K.js} +2 -2
  21. package/dist/cli/{chunk-FXGQ5NHE.js → chunk-SA4UGZPG.js} +21 -1
  22. package/dist/cli/chunk-SA4UGZPG.js.map +1 -0
  23. package/dist/cli/{chunk-J5VLP23S.js → chunk-SW3CCXEV.js} +2 -2
  24. package/dist/cli/{chunk-W4LDFAZ6.js → chunk-SX6L4HZZ.js} +2 -2
  25. package/dist/cli/chunk-WUI3P4RA.js +319 -0
  26. package/dist/cli/chunk-WUI3P4RA.js.map +1 -0
  27. package/dist/cli/{code-R4TXQQEE.js → code-TGUOQBRJ.js} +15 -14
  28. package/dist/cli/{code-R4TXQQEE.js.map → code-TGUOQBRJ.js.map} +1 -1
  29. package/dist/cli/{commands-JWT2MWVH.js → commands-MEZPSEHV.js} +4 -3
  30. package/dist/cli/{commands-JWT2MWVH.js.map → commands-MEZPSEHV.js.map} +1 -1
  31. package/dist/cli/{commit-RPZBOZS2.js → commit-CE4EFTUQ.js} +3 -2
  32. package/dist/cli/{commit-RPZBOZS2.js.map → commit-CE4EFTUQ.js.map} +1 -1
  33. package/dist/cli/{doctor-V5HLCMSQ.js → doctor-YASM64X6.js} +7 -6
  34. package/dist/cli/index.js +22 -21
  35. package/dist/cli/index.js.map +1 -1
  36. package/dist/cli/{mcp-ARTNQ24O.js → mcp-LDFK5QJI.js} +3 -2
  37. package/dist/cli/{mcp-ARTNQ24O.js.map → mcp-LDFK5QJI.js.map} +1 -1
  38. package/dist/cli/{mcp-browse-HLO2ENDL.js → mcp-browse-FYHEITCM.js} +3 -2
  39. package/dist/cli/{mcp-browse-HLO2ENDL.js.map → mcp-browse-FYHEITCM.js.map} +1 -1
  40. package/dist/cli/{replay-Q43DSMG6.js → replay-JEDLU7F2.js} +8 -6
  41. package/dist/cli/{replay-Q43DSMG6.js.map → replay-JEDLU7F2.js.map} +1 -1
  42. package/dist/cli/{run-HK3FP266.js → run-NHD2RSTD.js} +7 -6
  43. package/dist/cli/{run-HK3FP266.js.map → run-NHD2RSTD.js.map} +1 -1
  44. package/dist/cli/{server-SYC3OVOP.js → server-MC4A4WAJ.js} +9 -8
  45. package/dist/cli/{server-SYC3OVOP.js.map → server-MC4A4WAJ.js.map} +1 -1
  46. package/dist/cli/{sessions-3XU2GGHX.js → sessions-ZHWJEW4L.js} +7 -6
  47. package/dist/cli/{sessions-3XU2GGHX.js.map → sessions-ZHWJEW4L.js.map} +1 -1
  48. package/dist/cli/{setup-CCJZAWTY.js → setup-DK43MT47.js} +6 -5
  49. package/dist/cli/{setup-CCJZAWTY.js.map → setup-DK43MT47.js.map} +1 -1
  50. package/dist/cli/{version-5SGI2SEE.js → version-O362UKPM.js} +7 -6
  51. package/dist/cli/{version-5SGI2SEE.js.map → version-O362UKPM.js.map} +1 -1
  52. package/dist/index.d.ts +45 -1
  53. package/dist/index.js +569 -27
  54. package/dist/index.js.map +1 -1
  55. package/package.json +1 -1
  56. package/dist/cli/chunk-63KAV5DX.js +0 -106
  57. package/dist/cli/chunk-63KAV5DX.js.map +0 -1
  58. package/dist/cli/chunk-DULSP7JH.js.map +0 -1
  59. package/dist/cli/chunk-FXGQ5NHE.js.map +0 -1
  60. package/dist/cli/chunk-G7M3QWEN.js.map +0 -1
  61. package/dist/cli/chunk-OW7IHE6M.js.map +0 -1
  62. package/dist/cli/chunk-QGE6AF76.js.map +0 -1
  63. package/dist/cli/chunk-ZPTSJGX5.js +0 -88
  64. package/dist/cli/chunk-ZPTSJGX5.js.map +0 -1
  65. /package/dist/cli/{chat-ZMSAXE77.js.map → chat-TD6GR3QK.js.map} +0 -0
  66. /package/dist/cli/{chunk-WVJL7ZO2.js.map → chunk-F3ILWP2L.js.map} +0 -0
  67. /package/dist/cli/{chunk-WBDE4IRI.js.map → chunk-OERAGRJX.js.map} +0 -0
  68. /package/dist/cli/{chunk-RZILUXUC.js.map → chunk-RXGEGA7K.js.map} +0 -0
  69. /package/dist/cli/{chunk-J5VLP23S.js.map → chunk-SW3CCXEV.js.map} +0 -0
  70. /package/dist/cli/{chunk-W4LDFAZ6.js.map → chunk-SX6L4HZZ.js.map} +0 -0
  71. /package/dist/cli/{doctor-V5HLCMSQ.js.map → doctor-YASM64X6.js.map} +0 -0
@@ -6,16 +6,6 @@ import {
6
6
  import {
7
7
  preflightStdioSpec
8
8
  } from "./chunk-RFX7TYVV.js";
9
- import {
10
- CARD,
11
- FG,
12
- SURFACE,
13
- TONE,
14
- TONE_ACTIVE,
15
- balanceColor,
16
- formatBalance,
17
- formatCost
18
- } from "./chunk-63KAV5DX.js";
19
9
  import {
20
10
  dumpStartupProfile,
21
11
  markPhase
@@ -30,7 +20,8 @@ import {
30
20
  expandAtMentions,
31
21
  expandAtUrls,
32
22
  formatSubagentResult,
33
- listFilesWithStatsAsync,
23
+ listDirectory,
24
+ parseAtQuery,
34
25
  parseEditBlocks,
35
26
  rankPickerCandidates,
36
27
  registerChoiceTool,
@@ -41,8 +32,9 @@ import {
41
32
  snapshotBeforeEdits,
42
33
  spawnSubagent,
43
34
  toWholeFileEditBlock,
35
+ walkFilesStream,
44
36
  webFetch
45
- } from "./chunk-G7M3QWEN.js";
37
+ } from "./chunk-LNTORE5K.js";
46
38
  import {
47
39
  McpClient,
48
40
  SseTransport,
@@ -63,12 +55,15 @@ import {
63
55
  KeystrokeProvider,
64
56
  SingleSelect,
65
57
  useKeystroke
66
- } from "./chunk-SDE5U32Z.js";
58
+ } from "./chunk-KZHMKOJH.js";
67
59
  import {
68
60
  COLOR,
69
61
  GLYPH,
70
- GRADIENT
71
- } from "./chunk-ZPTSJGX5.js";
62
+ GRADIENT,
63
+ ThemeProvider,
64
+ useColor,
65
+ useThemeTokens
66
+ } from "./chunk-2EBODRRO.js";
72
67
  import {
73
68
  PRESETS,
74
69
  PRESET_DESCRIPTIONS,
@@ -76,7 +71,7 @@ import {
76
71
  } from "./chunk-MHDNZXJJ.js";
77
72
  import {
78
73
  runDoctorChecks
79
- } from "./chunk-WVJL7ZO2.js";
74
+ } from "./chunk-F3ILWP2L.js";
80
75
  import {
81
76
  countTokens
82
77
  } from "./chunk-DAEAAVDF.js";
@@ -102,7 +97,7 @@ import {
102
97
  resolveSlashAlias,
103
98
  savePlanState,
104
99
  suggestSlashCommands
105
- } from "./chunk-FXGQ5NHE.js";
100
+ } from "./chunk-SA4UGZPG.js";
106
101
  import {
107
102
  eventLogPath,
108
103
  openEventSink
@@ -118,7 +113,7 @@ import {
118
113
  formatCommandResult,
119
114
  pauseGate,
120
115
  runCommand
121
- } from "./chunk-W4LDFAZ6.js";
116
+ } from "./chunk-SX6L4HZZ.js";
122
117
  import {
123
118
  PROJECT_MEMORY_FILE,
124
119
  SkillStore,
@@ -132,7 +127,7 @@ import {
132
127
  loadHooks,
133
128
  projectSettingsPath,
134
129
  runHooks
135
- } from "./chunk-WBDE4IRI.js";
130
+ } from "./chunk-OERAGRJX.js";
136
131
  import {
137
132
  VERSION,
138
133
  compareVersions,
@@ -157,8 +152,9 @@ import {
157
152
  notifyLanguageChange,
158
153
  onLanguageChange,
159
154
  setLanguage,
160
- t
161
- } from "./chunk-QGE6AF76.js";
155
+ t,
156
+ tObj
157
+ } from "./chunk-Q36KBLSU.js";
162
158
  import {
163
159
  addProjectShellAllowed,
164
160
  clearProjectShellAllowed,
@@ -169,18 +165,35 @@ import {
169
165
  loadEditMode,
170
166
  loadProjectShellAllowed,
171
167
  loadReasoningEffort,
168
+ loadTheme,
172
169
  markEditModeHintShown,
170
+ markMouseClipboardHintShown,
171
+ mouseClipboardHintShown,
173
172
  readConfig,
174
173
  redactKey,
175
174
  removeProjectShellAllowed,
175
+ resolveThemePreference,
176
176
  saveApiKey,
177
177
  saveEditMode,
178
178
  saveReasoningEffort,
179
+ saveTheme,
179
180
  searchEnabled,
180
181
  webSearchEndpoint,
181
182
  webSearchEngine,
182
183
  writeConfig
183
- } from "./chunk-DULSP7JH.js";
184
+ } from "./chunk-5JXXEPDM.js";
185
+ import {
186
+ CARD,
187
+ FG,
188
+ SURFACE,
189
+ TONE,
190
+ TONE_ACTIVE,
191
+ balanceColor,
192
+ formatBalance,
193
+ formatCost,
194
+ isThemeName,
195
+ listThemeNames
196
+ } from "./chunk-WUI3P4RA.js";
184
197
  import {
185
198
  aggregateUsage,
186
199
  appendUsage,
@@ -195,7 +208,7 @@ import {
195
208
 
196
209
  // src/cli/commands/chat.tsx
197
210
  import { render } from "ink";
198
- import React62, { useState as useState22 } from "react";
211
+ import React63, { useState as useState22 } from "react";
199
212
 
200
213
  // src/mcp/summary.ts
201
214
  function buildMcpServerSummary(opts) {
@@ -218,8 +231,8 @@ function buildMcpServerSummary(opts) {
218
231
  // src/cli/ui/App.tsx
219
232
  import { statSync } from "fs";
220
233
  import { resolve as resolve2 } from "path";
221
- import { Box as Box48, Text as Text51, useStdout as useStdout14 } from "ink";
222
- import React59, { useCallback as useCallback11, useEffect as useEffect12, useMemo as useMemo9, useRef as useRef8, useState as useState20 } from "react";
234
+ import { Box as Box49, Text as Text52, useStdout as useStdout14 } from "ink";
235
+ import React60, { useCallback as useCallback11, useEffect as useEffect12, useMemo as useMemo9, useRef as useRef9, useState as useState20 } from "react";
223
236
 
224
237
  // src/code/checkpoints.ts
225
238
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
@@ -851,28 +864,64 @@ ${skill2.body}${argsBlock}`;
851
864
  // src/cli/ui/AtMentionSuggestions.tsx
852
865
  import { Box, Text } from "ink";
853
866
  import React from "react";
867
+ var ROW_WINDOW = 8;
854
868
  function AtMentionSuggestions({
855
- matches,
856
- selectedIndex,
857
- query
869
+ state,
870
+ selectedIndex
858
871
  }) {
859
- if (matches === null) return null;
860
- if (matches.length === 0) {
861
- return /* @__PURE__ */ React.createElement(Box, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: COLOR.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React.createElement(Text, null, " "), /* @__PURE__ */ React.createElement(Text, { color: COLOR.warn }, `no files match "@${query}"`), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " \u2014 keep typing or Backspace; paths resolve from the code root"));
862
- }
863
- const MAX = 8;
864
- const total = matches.length;
865
- const windowStart = total <= MAX ? 0 : Math.max(0, Math.min(selectedIndex - Math.floor(MAX / 2), total - MAX));
866
- const shown = matches.slice(windowStart, windowStart + MAX);
872
+ const color = useColor();
873
+ if (!state) return null;
874
+ const isBrowse = state.kind === "browse";
875
+ const entries = state.entries;
876
+ const total = entries.length;
877
+ const windowStart = total <= ROW_WINDOW ? 0 : Math.max(0, Math.min(selectedIndex - Math.floor(ROW_WINDOW / 2), total - ROW_WINDOW));
878
+ const shown = entries.slice(windowStart, windowStart + ROW_WINDOW);
867
879
  const hiddenAbove = windowStart;
868
880
  const hiddenBelow = total - windowStart - shown.length;
869
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: COLOR.primary, bold: true }, "@ "), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, query ? `${total} match${total === 1 ? "" : "es"} for "${query}"` : `${total} file${total === 1 ? "" : "s"}`), hiddenAbove > 0 ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null), shown.map((path, i) => /* @__PURE__ */ React.createElement(FileRow, { key: path, path, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, ` \u2193 ${hiddenBelow} below`) : null, /* @__PURE__ */ React.createElement(Box, { marginTop: 0 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " \u2191\u2193 navigate \xB7 Tab / \u23CE insert as @path \xB7 esc cancel")));
881
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React.createElement(HeaderRow, { state, hiddenAbove }), total === 0 ? /* @__PURE__ */ React.createElement(EmptyRow, { state, color }) : null, shown.map((entry, i) => /* @__PURE__ */ React.createElement(
882
+ EntryRow,
883
+ {
884
+ key: `${entry.insertPath}:${entry.isDir ? "d" : "f"}`,
885
+ entry,
886
+ isSelected: windowStart + i === selectedIndex
887
+ }
888
+ )), hiddenBelow > 0 ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, ` \u2193 ${hiddenBelow} below`) : null, /* @__PURE__ */ React.createElement(FooterRow, { isBrowse, hasFolder: shown.some((e) => e.isDir) }));
870
889
  }
871
- function FileRow({ path, isSelected }) {
872
- const slash = path.lastIndexOf("/");
873
- const dir = slash >= 0 ? `${path.slice(0, slash)}/` : "";
874
- const base = slash >= 0 ? path.slice(slash + 1) : path;
875
- return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: isSelected ? COLOR.primary : COLOR.info, bold: isSelected }, isSelected ? `${GLYPH.cur} ` : " "), /* @__PURE__ */ React.createElement(Text, { color: COLOR.primary, bold: isSelected }, base.padEnd(20)), dir ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, ` ${dir}`) : null);
890
+ function HeaderRow({
891
+ state,
892
+ hiddenAbove
893
+ }) {
894
+ const color = useColor();
895
+ const total = state.entries.length;
896
+ const lead = /* @__PURE__ */ React.createElement(Text, { color: color.primary, bold: true }, "@ ");
897
+ if (state.kind === "browse") {
898
+ const where = state.baseDir === "" ? "/" : `${state.baseDir}/`;
899
+ const counter = state.loading ? "loading\u2026" : `${total} ${total === 1 ? "entry" : "entries"}`;
900
+ return /* @__PURE__ */ React.createElement(Box, null, lead, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, `${where} ${counter}`), hiddenAbove > 0 ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null);
901
+ }
902
+ const status2 = state.searching ? `searching\u2026 ${state.scanned} scanned \xB7 ${total} ${total === 1 ? "match" : "matches"}` : `${total} ${total === 1 ? "match" : "matches"} for "${state.filter}"`;
903
+ return /* @__PURE__ */ React.createElement(Box, null, lead, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, status2), hiddenAbove > 0 ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null);
904
+ }
905
+ function EmptyRow({ state, color }) {
906
+ if (state.kind === "browse") {
907
+ if (state.loading) return null;
908
+ return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: color.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React.createElement(Text, null, " "), /* @__PURE__ */ React.createElement(Text, { color: color.warn }, "empty directory"));
909
+ }
910
+ if (state.searching) {
911
+ return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "scanning the tree\u2026"));
912
+ }
913
+ return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: color.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React.createElement(Text, null, " "), /* @__PURE__ */ React.createElement(Text, { color: color.warn }, `no files match "${state.filter}"`));
914
+ }
915
+ function EntryRow({ entry, isSelected }) {
916
+ const color = useColor();
917
+ const cursor = isSelected ? `${GLYPH.cur} ` : " ";
918
+ const labelColor = entry.isDir ? color.accent : color.primary;
919
+ const labelText = entry.isDir ? `${entry.label}/` : entry.label;
920
+ return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: isSelected ? color.primary : color.info, bold: isSelected }, cursor), /* @__PURE__ */ React.createElement(Text, { color: labelColor, bold: isSelected }, labelText.padEnd(20)), entry.dirSuffix ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, ` ${entry.dirSuffix}`) : null);
921
+ }
922
+ function FooterRow({ isBrowse, hasFolder }) {
923
+ const hint = isBrowse ? hasFolder ? "\u2191\u2193 navigate \xB7 Tab drill into folder \xB7 \u23CE insert \xB7 esc cancel" : "\u2191\u2193 navigate \xB7 Tab / \u23CE insert as @path \xB7 esc cancel" : "\u2191\u2193 navigate \xB7 Tab / \u23CE insert as @path \xB7 esc cancel";
924
+ return /* @__PURE__ */ React.createElement(Box, { marginTop: 0 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, ` ${hint}`));
876
925
  }
877
926
 
878
927
  // src/cli/ui/CheckpointPicker.tsx
@@ -6332,13 +6381,14 @@ function SlashArgPicker({
6332
6381
  kind,
6333
6382
  partial
6334
6383
  }) {
6335
- const headerRow = /* @__PURE__ */ React26.createElement(Box22, null, /* @__PURE__ */ React26.createElement(Text22, { color: COLOR.accent, bold: true }, "/ "), /* @__PURE__ */ React26.createElement(Text22, { color: COLOR.accent, bold: true }, `/${spec.cmd}`), spec.argsHint ? /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, ` ${spec.argsHint}`) : null, /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, ` ${spec.summary}`));
6384
+ const color = useColor();
6385
+ const headerRow = /* @__PURE__ */ React26.createElement(Box22, null, /* @__PURE__ */ React26.createElement(Text22, { color: color.accent, bold: true }, "/ "), /* @__PURE__ */ React26.createElement(Text22, { color: color.accent, bold: true }, `/${spec.cmd}`), spec.argsHint ? /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, ` ${spec.argsHint}`) : null, /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, ` ${spec.summary}`));
6336
6386
  if (kind === "hint") {
6337
6387
  return /* @__PURE__ */ React26.createElement(Box22, { paddingX: 1, marginTop: 1 }, headerRow);
6338
6388
  }
6339
6389
  if (matches === null) return null;
6340
6390
  if (matches.length === 0) {
6341
- return /* @__PURE__ */ React26.createElement(Box22, { flexDirection: "column", paddingX: 1, marginTop: 1 }, headerRow, /* @__PURE__ */ React26.createElement(Box22, null, /* @__PURE__ */ React26.createElement(Text22, { color: COLOR.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React26.createElement(Text22, { color: COLOR.warn }, ` no match for "${partial}"`), /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, " \u2014 keep typing, or Backspace to edit")));
6391
+ return /* @__PURE__ */ React26.createElement(Box22, { flexDirection: "column", paddingX: 1, marginTop: 1 }, headerRow, /* @__PURE__ */ React26.createElement(Box22, null, /* @__PURE__ */ React26.createElement(Text22, { color: color.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React26.createElement(Text22, { color: color.warn }, ` no match for "${partial}"`), /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, " \u2014 keep typing, or Backspace to edit")));
6342
6392
  }
6343
6393
  const MAX = 8;
6344
6394
  const total = matches.length;
@@ -6349,7 +6399,8 @@ function SlashArgPicker({
6349
6399
  return /* @__PURE__ */ React26.createElement(Box22, { flexDirection: "column", paddingX: 1, marginTop: 1 }, headerRow, hiddenAbove > 0 ? /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null, shown.map((value, i) => /* @__PURE__ */ React26.createElement(ArgRow, { key: value, value, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, ` \u2193 ${hiddenBelow} below`) : null, /* @__PURE__ */ React26.createElement(Box22, { marginTop: 0 }, /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, " \u2191\u2193 navigate \xB7 Tab / \u23CE pick \xB7 esc cancel")));
6350
6400
  }
6351
6401
  function ArgRow({ value, isSelected }) {
6352
- return /* @__PURE__ */ React26.createElement(Box22, null, /* @__PURE__ */ React26.createElement(Text22, { color: isSelected ? COLOR.primary : COLOR.info, bold: isSelected }, isSelected ? `${GLYPH.cur} ` : " "), /* @__PURE__ */ React26.createElement(Text22, { color: isSelected ? COLOR.user : COLOR.info, bold: isSelected, dimColor: !isSelected }, value));
6402
+ const color = useColor();
6403
+ return /* @__PURE__ */ React26.createElement(Box22, null, /* @__PURE__ */ React26.createElement(Text22, { color: isSelected ? color.primary : color.info, bold: isSelected }, isSelected ? `${GLYPH.cur} ` : " "), /* @__PURE__ */ React26.createElement(Text22, { color: isSelected ? color.user : color.info, bold: isSelected, dimColor: !isSelected }, value));
6353
6404
  }
6354
6405
 
6355
6406
  // src/cli/ui/SlashSuggestions.tsx
@@ -6371,9 +6422,10 @@ function SlashSuggestions({
6371
6422
  groupMode,
6372
6423
  advancedHidden
6373
6424
  }) {
6425
+ const color = useColor();
6374
6426
  if (matches === null) return null;
6375
6427
  if (matches.length === 0) {
6376
- return /* @__PURE__ */ React27.createElement(Box23, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React27.createElement(Text23, { color: COLOR.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React27.createElement(Text23, null, " "), /* @__PURE__ */ React27.createElement(Text23, { color: COLOR.warn }, "no slash command matches that prefix"), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, " \u2014 Backspace to edit, or /help for the full list"));
6428
+ return /* @__PURE__ */ React27.createElement(Box23, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React27.createElement(Text23, { color: color.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React27.createElement(Text23, null, " "), /* @__PURE__ */ React27.createElement(Text23, { color: color.warn }, "no slash command matches that prefix"), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, " \u2014 Backspace to edit, or /help for the full list"));
6377
6429
  }
6378
6430
  const MAX = groupMode ? 24 : 8;
6379
6431
  const total = matches.length;
@@ -6383,7 +6435,7 @@ function SlashSuggestions({
6383
6435
  const hiddenBelow = total - windowStart - shown.length;
6384
6436
  let lastGroup = null;
6385
6437
  if (windowStart > 0) lastGroup = matches[windowStart - 1]?.group ?? null;
6386
- return /* @__PURE__ */ React27.createElement(Box23, { flexDirection: "column", paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React27.createElement(Box23, null, /* @__PURE__ */ React27.createElement(Text23, { color: COLOR.accent, bold: true }, "/ "), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, `${total} command${total === 1 ? "" : "s"}`), hiddenAbove > 0 ? /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null), shown.map((spec, i) => {
6438
+ return /* @__PURE__ */ React27.createElement(Box23, { flexDirection: "column", paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React27.createElement(Box23, null, /* @__PURE__ */ React27.createElement(Text23, { color: color.accent, bold: true }, "/ "), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, `${total} command${total === 1 ? "" : "s"}`), hiddenAbove > 0 ? /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null), shown.map((spec, i) => {
6387
6439
  const idx = windowStart + i;
6388
6440
  const showHeader = groupMode && spec.group !== lastGroup;
6389
6441
  lastGroup = spec.group;
@@ -6391,13 +6443,14 @@ function SlashSuggestions({
6391
6443
  }), hiddenBelow > 0 ? /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, ` \u2193 ${hiddenBelow} below`) : null, groupMode && advancedHidden && advancedHidden > 0 ? /* @__PURE__ */ React27.createElement(Box23, { marginTop: 1 }, /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, ` + ${advancedHidden} advanced \xB7 type a letter to search`)) : null, /* @__PURE__ */ React27.createElement(Box23, { marginTop: 0 }, /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, " \u2191\u2193 navigate \xB7 Tab / \u23CE pick \xB7 esc cancel")));
6392
6444
  }
6393
6445
  function SuggestionRow({ spec, isSelected }) {
6446
+ const color = useColor();
6394
6447
  const name = `/${spec.cmd}`;
6395
6448
  const argsSuffix = spec.argsHint ? spec.argsHint : "";
6396
6449
  const key = `slash.${spec.cmd}.description`;
6397
6450
  const translated = t(key);
6398
6451
  const summary = translated === key ? spec.summary : translated;
6399
6452
  const aliasHint = spec.aliases?.length ? ` \xB7 /${spec.aliases.join(" /")}` : "";
6400
- return /* @__PURE__ */ React27.createElement(Box23, null, /* @__PURE__ */ React27.createElement(Text23, { color: isSelected ? COLOR.primary : COLOR.info, bold: isSelected }, isSelected ? `${GLYPH.cur} ` : " "), /* @__PURE__ */ React27.createElement(Text23, { color: COLOR.accent, bold: isSelected }, name.padEnd(14)), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, argsSuffix.padEnd(14)), /* @__PURE__ */ React27.createElement(Text23, null, " "), /* @__PURE__ */ React27.createElement(Text23, { color: isSelected ? COLOR.user : COLOR.info, dimColor: !isSelected }, summary), aliasHint ? /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, aliasHint) : null);
6453
+ return /* @__PURE__ */ React27.createElement(Box23, null, /* @__PURE__ */ React27.createElement(Text23, { color: isSelected ? color.primary : color.info, bold: isSelected }, isSelected ? `${GLYPH.cur} ` : " "), /* @__PURE__ */ React27.createElement(Text23, { color: color.accent, bold: isSelected }, name.padEnd(14)), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, argsSuffix.padEnd(14)), /* @__PURE__ */ React27.createElement(Text23, null, " "), /* @__PURE__ */ React27.createElement(Text23, { color: isSelected ? color.user : color.info, dimColor: !isSelected }, summary), aliasHint ? /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, aliasHint) : null);
6401
6454
  }
6402
6455
 
6403
6456
  // src/cli/ui/WelcomeBanner.tsx
@@ -6803,31 +6856,64 @@ function useAgentSession({
6803
6856
  }
6804
6857
 
6805
6858
  // src/cli/ui/hooks/useChatScroll.ts
6806
- import { useCallback as useCallback2, useEffect as useEffect4, useState as useState14 } from "react";
6859
+ import { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef2, useState as useState14 } from "react";
6807
6860
  var SCROLL_PAGE_ROWS = 3;
6861
+ var COALESCE_MS = 16;
6808
6862
  function useChatScroll() {
6809
6863
  const [scrollRows, setScrollRows] = useState14(0);
6810
6864
  const [pinned, setPinned] = useState14(true);
6811
6865
  const [maxScroll, setMaxScrollState] = useState14(0);
6866
+ const maxScrollRef = useRef2(0);
6867
+ const pendingDelta = useRef2(0);
6868
+ const flushTimer = useRef2(null);
6869
+ const flush = useCallback2(() => {
6870
+ flushTimer.current = null;
6871
+ const d = pendingDelta.current;
6872
+ pendingDelta.current = 0;
6873
+ if (d === 0) return;
6874
+ if (d < 0) setPinned(false);
6875
+ setScrollRows((o) => {
6876
+ const next = Math.max(0, Math.min(maxScrollRef.current, o + d));
6877
+ if (next >= maxScrollRef.current) setPinned(true);
6878
+ return next;
6879
+ });
6880
+ }, []);
6881
+ const schedule = useCallback2(
6882
+ (delta) => {
6883
+ pendingDelta.current += delta;
6884
+ if (flushTimer.current !== null) return;
6885
+ flushTimer.current = setTimeout(flush, COALESCE_MS);
6886
+ },
6887
+ [flush]
6888
+ );
6889
+ useEffect4(() => {
6890
+ return () => {
6891
+ if (flushTimer.current !== null) {
6892
+ clearTimeout(flushTimer.current);
6893
+ flushTimer.current = null;
6894
+ }
6895
+ };
6896
+ }, []);
6812
6897
  useEffect4(() => {
6813
6898
  if (pinned) setScrollRows(maxScroll);
6814
6899
  }, [pinned, maxScroll]);
6815
6900
  useEffect4(() => {
6816
6901
  if (scrollRows > maxScroll) setScrollRows(maxScroll);
6817
6902
  }, [scrollRows, maxScroll]);
6818
- const scrollUp = useCallback2(() => {
6819
- setPinned(false);
6820
- setScrollRows((o) => Math.max(0, o - SCROLL_PAGE_ROWS));
6903
+ const scrollUp = useCallback2(() => schedule(-SCROLL_PAGE_ROWS), [schedule]);
6904
+ const scrollDown = useCallback2(() => schedule(SCROLL_PAGE_ROWS), [schedule]);
6905
+ const jumpToBottom = useCallback2(() => {
6906
+ pendingDelta.current = 0;
6907
+ if (flushTimer.current !== null) {
6908
+ clearTimeout(flushTimer.current);
6909
+ flushTimer.current = null;
6910
+ }
6911
+ setPinned(true);
6912
+ }, []);
6913
+ const setMaxScroll = useCallback2((rows) => {
6914
+ maxScrollRef.current = rows;
6915
+ setMaxScrollState(rows);
6821
6916
  }, []);
6822
- const scrollDown = useCallback2(() => {
6823
- setScrollRows((o) => {
6824
- const next = Math.min(maxScroll, o + SCROLL_PAGE_ROWS);
6825
- if (next >= maxScroll) setPinned(true);
6826
- return next;
6827
- });
6828
- }, [maxScroll]);
6829
- const jumpToBottom = useCallback2(() => setPinned(true), []);
6830
- const setMaxScroll = useCallback2((rows) => setMaxScrollState(rows), []);
6831
6917
  return { scrollRows, pinned, scrollUp, scrollDown, jumpToBottom, setMaxScroll };
6832
6918
  }
6833
6919
 
@@ -6883,10 +6969,10 @@ function useCodeMode(opts) {
6883
6969
  }
6884
6970
 
6885
6971
  // src/cli/ui/hooks/useInputRecall.ts
6886
- import { useCallback as useCallback4, useRef as useRef2 } from "react";
6972
+ import { useCallback as useCallback4, useRef as useRef3 } from "react";
6887
6973
  function useInputRecall(setInput) {
6888
- const promptHistory = useRef2([]);
6889
- const historyCursor = useRef2(-1);
6974
+ const promptHistory = useRef3([]);
6975
+ const historyCursor = useRef3(-1);
6890
6976
  const recallPrev = useCallback4(() => {
6891
6977
  const hist = promptHistory.current;
6892
6978
  if (hist.length === 0) return;
@@ -6911,13 +6997,13 @@ function useInputRecall(setInput) {
6911
6997
  }
6912
6998
 
6913
6999
  // src/cli/ui/hooks/useLoopMode.ts
6914
- import { useCallback as useCallback5, useEffect as useEffect5, useRef as useRef3, useState as useState15 } from "react";
7000
+ import { useCallback as useCallback5, useEffect as useEffect5, useRef as useRef4, useState as useState15 } from "react";
6915
7001
  function useLoopMode(opts) {
6916
7002
  const { log, busyRef, handleSubmitRef } = opts;
6917
7003
  const [activeLoop, setActiveLoop] = useState15(null);
6918
- const activeLoopRef = useRef3(null);
6919
- const loopTimerRef = useRef3(null);
6920
- const loopFiringRef = useRef3(false);
7004
+ const activeLoopRef = useRef4(null);
7005
+ const loopTimerRef = useRef4(null);
7006
+ const loopFiringRef = useRef4(false);
6921
7007
  useEffect5(() => {
6922
7008
  activeLoopRef.current = activeLoop;
6923
7009
  }, [activeLoop]);
@@ -7150,6 +7236,16 @@ function reduce(state, event) {
7150
7236
  text: event.text,
7151
7237
  meta: event.meta
7152
7238
  });
7239
+ case "tip.show":
7240
+ return appendCard(state, {
7241
+ kind: "tip",
7242
+ id: event.id,
7243
+ ts: event.ts,
7244
+ topic: event.topic,
7245
+ sections: event.sections,
7246
+ footer: event.footer,
7247
+ oneTime: event.oneTime
7248
+ });
7153
7249
  case "session.reset":
7154
7250
  return { ...state, cards: [], focusedCardId: null, toasts: [] };
7155
7251
  case "plan.show":
@@ -7455,6 +7551,22 @@ ${stack}` : message
7455
7551
  });
7456
7552
  return id;
7457
7553
  },
7554
+ pushTip({ topic, sections, footer, oneTime = true }) {
7555
+ const id = nextId2("tip");
7556
+ dispatch({
7557
+ type: "tip.show",
7558
+ id,
7559
+ ts: Date.now(),
7560
+ topic,
7561
+ sections: sections.map((s) => ({
7562
+ title: s.title,
7563
+ rows: s.rows.map((r) => ({ key: r.key, text: r.text }))
7564
+ })),
7565
+ footer,
7566
+ oneTime
7567
+ });
7568
+ return id;
7569
+ },
7458
7570
  pushCtxPressureIfHigh(usedTokens, ctxMax) {
7459
7571
  if (ctxMax <= 0) return;
7460
7572
  const pct = usedTokens / ctxMax * 100;
@@ -7619,12 +7731,12 @@ function useTranscriptWriter(transcriptRef, model2, prefixHash) {
7619
7731
  }
7620
7732
 
7621
7733
  // src/cli/ui/layout/CardStream.tsx
7622
- import { Box as Box43, Text as Text45, useBoxMetrics } from "ink";
7623
- import React52, { useEffect as useEffect7, useRef as useRef4 } from "react";
7734
+ import { Box as Box44, Text as Text46, useBoxMetrics } from "ink";
7735
+ import React53, { useEffect as useEffect7, useRef as useRef5 } from "react";
7624
7736
 
7625
7737
  // src/cli/ui/cards/CardRenderer.tsx
7626
- import { Box as Box42, Text as Text44 } from "ink";
7627
- import React51 from "react";
7738
+ import { Box as Box43, Text as Text45 } from "ink";
7739
+ import React52 from "react";
7628
7740
 
7629
7741
  // src/cli/ui/cards/CtxCard.tsx
7630
7742
  import { Box as Box27, Text as Text26 } from "ink";
@@ -7748,11 +7860,6 @@ function DiffCard({ card }) {
7748
7860
  // src/cli/ui/cards/DoctorCard.tsx
7749
7861
  import { Box as Box29, Text as Text28 } from "ink";
7750
7862
  import React34 from "react";
7751
- var LEVEL_COLOR = {
7752
- ok: TONE.ok,
7753
- warn: TONE.warn,
7754
- fail: TONE.err
7755
- };
7756
7863
  var LEVEL_GLYPH = {
7757
7864
  ok: "\u2713",
7758
7865
  warn: "\u26A0",
@@ -7764,12 +7871,18 @@ var LEVEL_TAG = {
7764
7871
  fail: "FAIL"
7765
7872
  };
7766
7873
  function DoctorCard({ card }) {
7874
+ const { fg, tone } = useThemeTokens();
7875
+ const levelColor = {
7876
+ ok: tone.ok,
7877
+ warn: tone.warn,
7878
+ fail: tone.err
7879
+ };
7767
7880
  const ok = card.checks.filter((c) => c.level === "ok").length;
7768
7881
  const warn = card.checks.filter((c) => c.level === "warn").length;
7769
7882
  const fail = card.checks.filter((c) => c.level === "fail").length;
7770
7883
  const labelWidth = card.checks.reduce((m, c) => Math.max(m, c.label.length), 0);
7771
7884
  const summary = `${card.checks.length} checks \xB7 ${ok} passed${warn > 0 ? ` \xB7 ${warn} warn` : ""}${fail > 0 ? ` \xB7 ${fail} fail` : ""}`;
7772
- return /* @__PURE__ */ React34.createElement(Card, { tone: CARD.tool.color }, /* @__PURE__ */ React34.createElement(CardHeader, { glyph: "\u2695", tone: CARD.tool.color, title: "doctor", meta: [summary] }), card.checks.map((c) => /* @__PURE__ */ React34.createElement(Box29, { key: c.label, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React34.createElement(Text28, { color: LEVEL_COLOR[c.level] }, LEVEL_GLYPH[c.level]), /* @__PURE__ */ React34.createElement(Text28, { bold: true, color: FG.body }, c.label.padEnd(labelWidth + 1)), /* @__PURE__ */ React34.createElement(Text28, { color: FG.sub }, c.detail), /* @__PURE__ */ React34.createElement(Text28, { color: LEVEL_COLOR[c.level] }, LEVEL_TAG[c.level]))));
7885
+ return /* @__PURE__ */ React34.createElement(Card, { tone: CARD.tool.color }, /* @__PURE__ */ React34.createElement(CardHeader, { glyph: "\u2695", tone: CARD.tool.color, title: "doctor", meta: [summary] }), card.checks.map((c) => /* @__PURE__ */ React34.createElement(Box29, { key: c.label, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React34.createElement(Text28, { color: levelColor[c.level] }, LEVEL_GLYPH[c.level]), /* @__PURE__ */ React34.createElement(Text28, { bold: true, color: fg.body }, c.label.padEnd(labelWidth + 1)), /* @__PURE__ */ React34.createElement(Text28, { color: fg.sub }, c.detail), /* @__PURE__ */ React34.createElement(Text28, { color: levelColor[c.level] }, LEVEL_TAG[c.level]))));
7773
7886
  }
7774
7887
 
7775
7888
  // src/cli/ui/cards/ErrorCard.tsx
@@ -7909,27 +8022,28 @@ var STATUS_GLYPH = {
7909
8022
  blocked: "!",
7910
8023
  skipped: "s"
7911
8024
  };
7912
- var STATUS_COLOR = {
7913
- queued: FG.faint,
7914
- running: TONE_ACTIVE.brand,
7915
- done: TONE.ok,
7916
- failed: TONE.err,
7917
- blocked: TONE.warn,
7918
- skipped: FG.faint
7919
- };
7920
8025
  var VISIBLE_WINDOW = 5;
7921
8026
  function PlanCard({ card }) {
8027
+ const { fg, tone, toneActive } = useThemeTokens();
8028
+ const statusColor = {
8029
+ queued: fg.faint,
8030
+ running: toneActive.brand,
8031
+ done: tone.ok,
8032
+ failed: tone.err,
8033
+ blocked: tone.warn,
8034
+ skipped: fg.faint
8035
+ };
7922
8036
  const doneCount = card.steps.filter((s) => s.status === "done").length;
7923
8037
  const variantTag = card.variant === "resumed" ? "resumed \xB7 " : card.variant === "replay" ? "\u23EA archive \xB7 " : "";
7924
8038
  const progress = `${variantTag}${doneCount}/${card.steps.length} done`;
7925
8039
  const hasRunning = card.steps.some((s) => s.status === "running");
7926
- const tone = hasRunning ? TONE_ACTIVE.accent : TONE.accent;
8040
+ const cardTone = hasRunning ? toneActive.accent : tone.accent;
7927
8041
  const window = pickWindow(card.steps);
7928
- return /* @__PURE__ */ React39.createElement(Card, { tone }, /* @__PURE__ */ React39.createElement(CardHeader, { glyph: "\u229E", tone, title: card.title, meta: [progress] }), window.hiddenBefore > 0 ? /* @__PURE__ */ React39.createElement(Box33, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React39.createElement(Text33, { color: TONE.ok }, "\u2713"), /* @__PURE__ */ React39.createElement(Text33, { color: FG.faint }, `\u22EF ${window.hiddenBefore} done`)) : null, window.steps.map((step) => {
8042
+ return /* @__PURE__ */ React39.createElement(Card, { tone: cardTone }, /* @__PURE__ */ React39.createElement(CardHeader, { glyph: "\u229E", tone: cardTone, title: card.title, meta: [progress] }), window.hiddenBefore > 0 ? /* @__PURE__ */ React39.createElement(Box33, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React39.createElement(Text33, { color: tone.ok }, "\u2713"), /* @__PURE__ */ React39.createElement(Text33, { color: fg.faint }, `\u22EF ${window.hiddenBefore} done`)) : null, window.steps.map((step) => {
7929
8043
  const isActive = step.status === "running";
7930
- const titleColor = isActive ? FG.strong : FG.sub;
7931
- return /* @__PURE__ */ React39.createElement(Box33, { key: step.id, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React39.createElement(Text33, { color: STATUS_COLOR[step.status] }, STATUS_GLYPH[step.status]), /* @__PURE__ */ React39.createElement(Text33, { bold: isActive, color: titleColor }, `${step.indexLabel}. ${step.title}`), isActive ? /* @__PURE__ */ React39.createElement(Text33, { color: TONE_ACTIVE.brand }, "\u2190 in progress") : null);
7932
- }), window.hiddenAfter > 0 ? /* @__PURE__ */ React39.createElement(Box33, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React39.createElement(Text33, { color: FG.faint }, "\u25CB"), /* @__PURE__ */ React39.createElement(Text33, { color: FG.faint }, `\u22EF ${window.hiddenAfter} upcoming`)) : null);
8044
+ const titleColor = isActive ? fg.strong : fg.sub;
8045
+ return /* @__PURE__ */ React39.createElement(Box33, { key: step.id, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React39.createElement(Text33, { color: statusColor[step.status] }, STATUS_GLYPH[step.status]), /* @__PURE__ */ React39.createElement(Text33, { bold: isActive, color: titleColor }, `${step.indexLabel}. ${step.title}`), isActive ? /* @__PURE__ */ React39.createElement(Text33, { color: toneActive.brand }, "\u2190 in progress") : null);
8046
+ }), window.hiddenAfter > 0 ? /* @__PURE__ */ React39.createElement(Box33, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React39.createElement(Text33, { color: fg.faint }, "\u25CB"), /* @__PURE__ */ React39.createElement(Text33, { color: fg.faint }, `\u22EF ${window.hiddenAfter} upcoming`)) : null);
7933
8047
  }
7934
8048
  function pickWindow(steps) {
7935
8049
  if (steps.length <= VISIBLE_WINDOW) {
@@ -8542,13 +8656,14 @@ function StreamingCard({ card }) {
8542
8656
  // src/cli/ui/cards/SubAgentCard.tsx
8543
8657
  import { Box as Box38, Text as Text39 } from "ink";
8544
8658
  import React45, { useContext as useContext6 } from "react";
8545
- var STATUS_COLOR2 = {
8546
- running: TONE_ACTIVE.violet,
8547
- done: TONE.ok,
8548
- failed: TONE.err
8549
- };
8550
8659
  function SubAgentCard({ card }) {
8551
- const headColor = STATUS_COLOR2[card.status];
8660
+ const { fg, tone, toneActive } = useThemeTokens();
8661
+ const statusColor = {
8662
+ running: toneActive.violet,
8663
+ done: tone.ok,
8664
+ failed: tone.err
8665
+ };
8666
+ const headColor = statusColor[card.status];
8552
8667
  const headGlyph = card.status === "failed" ? "\u2716" : "\u232C";
8553
8668
  const runningChildren = card.children.filter((c) => !isChildDone(c)).length;
8554
8669
  const isRunning = card.status === "running";
@@ -8560,11 +8675,11 @@ function SubAgentCard({ card }) {
8560
8675
  glyph: headGlyph,
8561
8676
  tone: headColor,
8562
8677
  title: "subagent",
8563
- titleColor: TONE.violet,
8678
+ titleColor: tone.violet,
8564
8679
  subtitle: card.task,
8565
8680
  meta: headerMeta2
8566
8681
  }
8567
- ), card.name ? /* @__PURE__ */ React45.createElement(Text39, { color: FG.faint }, `agent \xB7 ${card.name}`) : null, card.tools && card.tools.length > 0 && /* @__PURE__ */ React45.createElement(Text39, { color: FG.faint }, `tools \xB7 ${card.tools.join(", ")}`), card.children.map((child) => /* @__PURE__ */ React45.createElement(Box38, { key: child.id, flexDirection: "row", gap: 1 }, inLive ? null : /* @__PURE__ */ React45.createElement(Text39, { color: TONE.violet }, "\u258E"), /* @__PURE__ */ React45.createElement(ChildRow, { card: child }))));
8682
+ ), card.name ? /* @__PURE__ */ React45.createElement(Text39, { color: fg.faint }, `agent \xB7 ${card.name}`) : null, card.tools && card.tools.length > 0 && /* @__PURE__ */ React45.createElement(Text39, { color: fg.faint }, `tools \xB7 ${card.tools.join(", ")}`), card.children.map((child) => /* @__PURE__ */ React45.createElement(Box38, { key: child.id, flexDirection: "row", gap: 1 }, inLive ? null : /* @__PURE__ */ React45.createElement(Text39, { color: tone.violet }, "\u258E"), /* @__PURE__ */ React45.createElement(ChildRow, { card: child }))));
8568
8683
  }
8569
8684
  function isChildDone(card) {
8570
8685
  switch (card.kind) {
@@ -8578,9 +8693,10 @@ function isChildDone(card) {
8578
8693
  }
8579
8694
  }
8580
8695
  function ChildRow({ card }) {
8581
- const v = childVisual(card);
8696
+ const { fg, tone } = useThemeTokens();
8697
+ const v = childVisual(card, tone.ok, tone.err, fg.faint);
8582
8698
  const isDone = isChildDone(card);
8583
- return /* @__PURE__ */ React45.createElement(React45.Fragment, null, v.statusGlyph, /* @__PURE__ */ React45.createElement(Text39, { color: v.kindColor }, v.kindGlyph), /* @__PURE__ */ React45.createElement(Text39, { dimColor: isDone, color: FG.body }, v.text));
8699
+ return /* @__PURE__ */ React45.createElement(React45.Fragment, null, v.statusGlyph, /* @__PURE__ */ React45.createElement(Text39, { color: v.kindColor }, v.kindGlyph), /* @__PURE__ */ React45.createElement(Text39, { dimColor: isDone, color: fg.body }, v.text));
8584
8700
  }
8585
8701
  function runningGlyph(color) {
8586
8702
  return /* @__PURE__ */ React45.createElement(Spinner, { kind: "circle", color });
@@ -8588,15 +8704,15 @@ function runningGlyph(color) {
8588
8704
  function doneGlyph(color) {
8589
8705
  return /* @__PURE__ */ React45.createElement(Text39, { color }, "\u2713");
8590
8706
  }
8591
- function failedGlyph() {
8592
- return /* @__PURE__ */ React45.createElement(Text39, { color: TONE.err }, "\u2716");
8707
+ function failedGlyph(color) {
8708
+ return /* @__PURE__ */ React45.createElement(Text39, { color }, "\u2716");
8593
8709
  }
8594
- function childVisual(card) {
8710
+ function childVisual(card, doneColor, failedColor, fallbackColor) {
8595
8711
  switch (card.kind) {
8596
8712
  case "reasoning": {
8597
8713
  const done = !card.streaming;
8598
8714
  return {
8599
- statusGlyph: done ? doneGlyph(TONE.ok) : runningGlyph(CARD.reasoning.color),
8715
+ statusGlyph: done ? doneGlyph(doneColor) : runningGlyph(CARD.reasoning.color),
8600
8716
  kindGlyph: "\u25C6",
8601
8717
  kindColor: CARD.reasoning.color,
8602
8718
  text: `reasoning \xB7 ${card.paragraphs} \xB6`
@@ -8605,7 +8721,7 @@ function childVisual(card) {
8605
8721
  case "tool": {
8606
8722
  const elapsed = card.elapsedMs > 0 ? ` \xB7 ${(card.elapsedMs / 1e3).toFixed(2)}s` : "";
8607
8723
  return {
8608
- statusGlyph: card.done ? doneGlyph(TONE.ok) : runningGlyph(CARD.tool.color),
8724
+ statusGlyph: card.done ? doneGlyph(doneColor) : runningGlyph(CARD.tool.color),
8609
8725
  kindGlyph: "\u25A3",
8610
8726
  kindColor: CARD.tool.color,
8611
8727
  text: `${card.name}${elapsed}`
@@ -8613,30 +8729,30 @@ function childVisual(card) {
8613
8729
  }
8614
8730
  case "streaming":
8615
8731
  return {
8616
- statusGlyph: card.done ? doneGlyph(TONE.ok) : runningGlyph(CARD.streaming.color),
8732
+ statusGlyph: card.done ? doneGlyph(doneColor) : runningGlyph(CARD.streaming.color),
8617
8733
  kindGlyph: "\u25C8",
8618
8734
  kindColor: CARD.streaming.color,
8619
8735
  text: card.done ? "response" : "writing \u2026"
8620
8736
  };
8621
8737
  case "diff":
8622
8738
  return {
8623
- statusGlyph: doneGlyph(TONE.ok),
8739
+ statusGlyph: doneGlyph(doneColor),
8624
8740
  kindGlyph: "\xB1",
8625
8741
  kindColor: CARD.diff.color,
8626
8742
  text: card.file
8627
8743
  };
8628
8744
  case "error":
8629
8745
  return {
8630
- statusGlyph: failedGlyph(),
8746
+ statusGlyph: failedGlyph(failedColor),
8631
8747
  kindGlyph: "\u2716",
8632
8748
  kindColor: CARD.error.color,
8633
8749
  text: card.title
8634
8750
  };
8635
8751
  default:
8636
8752
  return {
8637
- statusGlyph: /* @__PURE__ */ React45.createElement(Text39, { color: FG.faint }, "\xB7"),
8753
+ statusGlyph: /* @__PURE__ */ React45.createElement(Text39, { color: fallbackColor }, "\xB7"),
8638
8754
  kindGlyph: "\xB7",
8639
- kindColor: FG.faint,
8755
+ kindColor: fallbackColor,
8640
8756
  text: card.kind
8641
8757
  };
8642
8758
  }
@@ -8651,39 +8767,70 @@ var STEP_GLYPH = {
8651
8767
  done: "\u2713",
8652
8768
  failed: "\u2717"
8653
8769
  };
8654
- var STEP_COLOR = {
8655
- queued: FG.faint,
8656
- running: TONE.warn,
8657
- done: TONE.ok,
8658
- failed: TONE.err
8659
- };
8660
- var TASK_COLOR = {
8661
- running: TONE.warn,
8662
- done: TONE.ok,
8663
- failed: TONE.err
8664
- };
8665
8770
  var TASK_GLYPH = {
8666
8771
  running: "\u25B6",
8667
8772
  done: "\u2713",
8668
8773
  failed: "\u2717"
8669
8774
  };
8670
8775
  function TaskCard({ card }) {
8776
+ const { fg, tone } = useThemeTokens();
8777
+ const stepColor = {
8778
+ queued: fg.faint,
8779
+ running: tone.warn,
8780
+ done: tone.ok,
8781
+ failed: tone.err
8782
+ };
8783
+ const taskColor = {
8784
+ running: tone.warn,
8785
+ done: tone.ok,
8786
+ failed: tone.err
8787
+ };
8671
8788
  const elapsed = `${(card.elapsedMs / 1e3).toFixed(1)}s`;
8672
- return /* @__PURE__ */ React46.createElement(Card, { tone: TASK_COLOR[card.status] }, /* @__PURE__ */ React46.createElement(
8789
+ return /* @__PURE__ */ React46.createElement(Card, { tone: taskColor[card.status] }, /* @__PURE__ */ React46.createElement(
8673
8790
  CardHeader,
8674
8791
  {
8675
8792
  glyph: TASK_GLYPH[card.status],
8676
- tone: TASK_COLOR[card.status],
8793
+ tone: taskColor[card.status],
8677
8794
  title: `step ${card.index}/${card.total}`,
8678
8795
  subtitle: card.title,
8679
8796
  meta: [elapsed, card.status]
8680
8797
  }
8681
- ), card.steps.map((step) => /* @__PURE__ */ React46.createElement(Box39, { key: step.id, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React46.createElement(Text40, { color: STEP_COLOR[step.status] }, STEP_GLYPH[step.status]), /* @__PURE__ */ React46.createElement(Text40, { bold: true, color: FG.body }, (step.toolName ?? "step").padEnd(7)), /* @__PURE__ */ React46.createElement(Text40, { color: FG.sub }, step.title), step.detail ? /* @__PURE__ */ React46.createElement(Text40, { color: FG.faint }, step.detail) : null, step.elapsedMs !== void 0 ? /* @__PURE__ */ React46.createElement(Text40, { color: FG.faint }, `${(step.elapsedMs / 1e3).toFixed(2)}s`) : null)));
8798
+ ), card.steps.map((step) => /* @__PURE__ */ React46.createElement(Box39, { key: step.id, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React46.createElement(Text40, { color: stepColor[step.status] }, STEP_GLYPH[step.status]), /* @__PURE__ */ React46.createElement(Text40, { bold: true, color: fg.body }, (step.toolName ?? "step").padEnd(7)), /* @__PURE__ */ React46.createElement(Text40, { color: fg.sub }, step.title), step.detail ? /* @__PURE__ */ React46.createElement(Text40, { color: fg.faint }, step.detail) : null, step.elapsedMs !== void 0 ? /* @__PURE__ */ React46.createElement(Text40, { color: fg.faint }, `${(step.elapsedMs / 1e3).toFixed(2)}s`) : null)));
8682
8799
  }
8683
8800
 
8684
- // src/cli/ui/cards/ToolCard.tsx
8685
- import { Text as Text41, useStdout as useStdout11 } from "ink";
8801
+ // src/cli/ui/cards/TipCard.tsx
8802
+ import { Box as Box40, Text as Text41 } from "ink";
8686
8803
  import React47 from "react";
8804
+ import stringWidth2 from "string-width";
8805
+ var KEY_GUTTER = 4;
8806
+ function TipCard({ card }) {
8807
+ const keyWidth = card.sections.reduce(
8808
+ (max, sec) => sec.rows.reduce((m, r) => Math.max(m, stringWidth2(r.key)), max),
8809
+ 0
8810
+ );
8811
+ return /* @__PURE__ */ React47.createElement(Box40, { flexDirection: "column", paddingLeft: 2, marginY: 1 }, /* @__PURE__ */ React47.createElement(Box40, { flexDirection: "row", justifyContent: "space-between" }, /* @__PURE__ */ React47.createElement(Box40, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React47.createElement(Text41, { color: TONE.accent, bold: true }, "\u24D8"), /* @__PURE__ */ React47.createElement(Text41, { color: FG.body, bold: true }, card.topic)), card.oneTime ? /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, t("ui.tipShownOnce")) : null), card.sections.map((section, i) => /* @__PURE__ */ React47.createElement(Box40, { key: section.title ?? `section-${i}`, flexDirection: "column", marginTop: 1 }, section.title ? /* @__PURE__ */ React47.createElement(Box40, { marginBottom: 0 }, /* @__PURE__ */ React47.createElement(Text41, { color: FG.sub }, section.title)) : null, section.rows.map((row2) => /* @__PURE__ */ React47.createElement(
8812
+ TipRowRender,
8813
+ {
8814
+ key: row2.key,
8815
+ row: row2,
8816
+ keyWidth,
8817
+ indent: section.title ? 2 : 0
8818
+ }
8819
+ )))), card.footer ? /* @__PURE__ */ React47.createElement(Box40, { marginTop: 1 }, /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, card.footer)) : null);
8820
+ }
8821
+ function TipRowRender({
8822
+ row: row2,
8823
+ keyWidth,
8824
+ indent
8825
+ }) {
8826
+ const pad = " ".repeat(Math.max(0, keyWidth - stringWidth2(row2.key) + KEY_GUTTER));
8827
+ const lead = indent > 0 ? " ".repeat(indent) : "";
8828
+ return /* @__PURE__ */ React47.createElement(Box40, { flexDirection: "row" }, lead ? /* @__PURE__ */ React47.createElement(Text41, null, lead) : null, /* @__PURE__ */ React47.createElement(Text41, { color: TONE.accent }, row2.key), /* @__PURE__ */ React47.createElement(Text41, null, pad), /* @__PURE__ */ React47.createElement(Text41, { color: FG.body }, row2.text));
8829
+ }
8830
+
8831
+ // src/cli/ui/cards/ToolCard.tsx
8832
+ import { Text as Text42, useStdout as useStdout11 } from "ink";
8833
+ import React48 from "react";
8687
8834
  var READ_TAIL = 2;
8688
8835
  var OTHER_TAIL = 5;
8689
8836
  function tailLinesFor(name) {
@@ -8712,7 +8859,7 @@ function ToolCard({ card }) {
8712
8859
  meta.push({ text: "rejected", color: TONE.err });
8713
8860
  }
8714
8861
  for (const part of metaTrail(card)) meta.push(part);
8715
- return /* @__PURE__ */ React47.createElement(Card, { tone: headColor }, /* @__PURE__ */ React47.createElement(
8862
+ return /* @__PURE__ */ React48.createElement(Card, { tone: headColor }, /* @__PURE__ */ React48.createElement(
8716
8863
  CardHeader,
8717
8864
  {
8718
8865
  glyph: statusGlyph2(status2),
@@ -8720,10 +8867,10 @@ function ToolCard({ card }) {
8720
8867
  title: card.name,
8721
8868
  subtitle: argsLabel || void 0,
8722
8869
  meta: meta.length > 0 ? meta : void 0,
8723
- right: status2 === "running" ? /* @__PURE__ */ React47.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand, bold: true }) : void 0
8870
+ right: status2 === "running" ? /* @__PURE__ */ React48.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand, bold: true }) : void 0
8724
8871
  }
8725
- ), showBody && /* @__PURE__ */ React47.createElement(React47.Fragment, null, hidden > 0 ? /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, `\u22EE ${hidden} earlier line${hidden === 1 ? "" : "s"} (use /tool to read full)`) : null, visible.map((line, i) => /* @__PURE__ */ React47.createElement(
8726
- Text41,
8872
+ ), showBody && /* @__PURE__ */ React48.createElement(React48.Fragment, null, hidden > 0 ? /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, `\u22EE ${hidden} earlier line${hidden === 1 ? "" : "s"} (use /tool to read full)`) : null, visible.map((line, i) => /* @__PURE__ */ React48.createElement(
8873
+ Text42,
8727
8874
  {
8728
8875
  key: `${card.id}:${hidden + i}`,
8729
8876
  color: errColor,
@@ -8778,15 +8925,15 @@ function metaTrail(card) {
8778
8925
  function formatArgsSummary(args) {
8779
8926
  if (typeof args === "string") return args.length > 60 ? `${args.slice(0, 60)}\u2026` : args;
8780
8927
  if (args && typeof args === "object") {
8781
- const keys = Object.keys(args);
8782
- if (keys.length === 0) return "";
8783
- const first = keys[0];
8928
+ const keys2 = Object.keys(args);
8929
+ if (keys2.length === 0) return "";
8930
+ const first = keys2[0];
8784
8931
  const value = args[first];
8785
8932
  if (typeof value === "string") {
8786
8933
  const trimmed = value.length > 40 ? `${value.slice(0, 40)}\u2026` : value;
8787
- return keys.length === 1 ? trimmed : `${trimmed} +${keys.length - 1}`;
8934
+ return keys2.length === 1 ? trimmed : `${trimmed} +${keys2.length - 1}`;
8788
8935
  }
8789
- return keys.join(" ");
8936
+ return keys2.join(" ");
8790
8937
  }
8791
8938
  return "";
8792
8939
  }
@@ -8809,8 +8956,8 @@ function formatBytes(n) {
8809
8956
  }
8810
8957
 
8811
8958
  // src/cli/ui/cards/UsageCard.tsx
8812
- import { Box as Box41, Text as Text42 } from "ink";
8813
- import React48 from "react";
8959
+ import { Box as Box42, Text as Text43 } from "ink";
8960
+ import React49 from "react";
8814
8961
  var BAR_CELLS2 = 30;
8815
8962
  function compactNum(n) {
8816
8963
  if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
@@ -8820,25 +8967,25 @@ function compactNum(n) {
8820
8967
  function bar(ratio, color) {
8821
8968
  const filled = Math.max(0, Math.min(BAR_CELLS2, Math.round(ratio * BAR_CELLS2)));
8822
8969
  const empty = BAR_CELLS2 - filled;
8823
- return /* @__PURE__ */ React48.createElement(React48.Fragment, null, /* @__PURE__ */ React48.createElement(Text42, { color }, "\u2588".repeat(filled)), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, "\u2591".repeat(empty)));
8970
+ return /* @__PURE__ */ React49.createElement(React49.Fragment, null, /* @__PURE__ */ React49.createElement(Text43, { color }, "\u2588".repeat(filled)), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, "\u2591".repeat(empty)));
8824
8971
  }
8825
8972
  function UsageCard({ card }) {
8826
- if (card.compact) return /* @__PURE__ */ React48.createElement(CompactUsageRow, { card });
8973
+ if (card.compact) return /* @__PURE__ */ React49.createElement(CompactUsageRow, { card });
8827
8974
  const cap = Math.max(1, card.tokens.promptCap);
8828
8975
  const promptRatio = card.tokens.prompt / cap;
8829
8976
  const reasonRatio = card.tokens.reason / cap;
8830
8977
  const outputRatio = card.tokens.output / cap;
8831
8978
  const headerMeta2 = [`turn ${card.turn}`, formatCost(card.cost, card.balanceCurrency)];
8832
8979
  if (card.elapsedMs !== void 0) headerMeta2.push(`${(card.elapsedMs / 1e3).toFixed(1)}s`);
8833
- return /* @__PURE__ */ React48.createElement(Card, { tone: FG.meta }, /* @__PURE__ */ React48.createElement(CardHeader, { glyph: "\u03A3", tone: FG.meta, title: "usage", meta: headerMeta2 }), /* @__PURE__ */ React48.createElement(Box41, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React48.createElement(Text42, { color: FG.sub }, "prompt"), bar(promptRatio, TONE.brand), /* @__PURE__ */ React48.createElement(Text42, { bold: true, color: FG.body }, card.tokens.prompt.toLocaleString()), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, `/ 1M \xB7 ${(promptRatio * 100).toFixed(1)}%`)), /* @__PURE__ */ React48.createElement(Box41, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React48.createElement(Text42, { color: FG.sub }, "reason"), bar(reasonRatio, TONE.accent), /* @__PURE__ */ React48.createElement(Text42, { bold: true, color: FG.body }, card.tokens.reason.toLocaleString())), /* @__PURE__ */ React48.createElement(Box41, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React48.createElement(Text42, { color: FG.sub }, "output"), bar(outputRatio, TONE.brand), /* @__PURE__ */ React48.createElement(Text42, { bold: true, color: FG.body }, card.tokens.output.toLocaleString())), /* @__PURE__ */ React48.createElement(Box41, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React48.createElement(Text42, { color: FG.sub }, "cache "), bar(card.cacheHit, TONE.ok), /* @__PURE__ */ React48.createElement(Text42, { bold: true, color: TONE.ok }, `${(card.cacheHit * 100).toFixed(1)}%`)), /* @__PURE__ */ React48.createElement(Box41, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, "session"), /* @__PURE__ */ React48.createElement(Text42, { bold: true, color: FG.body }, `\u26C1 ${formatCost(card.sessionCost, card.balanceCurrency, 3)}`), card.balance !== void 0 ? /* @__PURE__ */ React48.createElement(React48.Fragment, null, /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, "\xB7 balance"), /* @__PURE__ */ React48.createElement(Text42, { bold: true, color: TONE.brand }, formatBalance(card.balance, card.balanceCurrency))) : null));
8980
+ return /* @__PURE__ */ React49.createElement(Card, { tone: FG.meta }, /* @__PURE__ */ React49.createElement(CardHeader, { glyph: "\u03A3", tone: FG.meta, title: "usage", meta: headerMeta2 }), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, "prompt"), bar(promptRatio, TONE.brand), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.prompt.toLocaleString()), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `/ 1M \xB7 ${(promptRatio * 100).toFixed(1)}%`)), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, "reason"), bar(reasonRatio, TONE.accent), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.reason.toLocaleString())), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, "output"), bar(outputRatio, TONE.brand), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.output.toLocaleString())), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, "cache "), bar(card.cacheHit, TONE.ok), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: TONE.ok }, `${(card.cacheHit * 100).toFixed(1)}%`)), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, "session"), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, `\u26C1 ${formatCost(card.sessionCost, card.balanceCurrency, 3)}`), card.balance !== void 0 ? /* @__PURE__ */ React49.createElement(React49.Fragment, null, /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, "\xB7 balance"), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: TONE.brand }, formatBalance(card.balance, card.balanceCurrency))) : null));
8834
8981
  }
8835
8982
  function CompactUsageRow({ card }) {
8836
8983
  const elapsed = card.elapsedMs !== void 0 ? ` \xB7 ${(card.elapsedMs / 1e3).toFixed(1)}s` : "";
8837
- return /* @__PURE__ */ React48.createElement(Box41, { flexDirection: "row", gap: 1, marginTop: 1 }, /* @__PURE__ */ React48.createElement(Text42, { color: FG.meta }, "\u03A3"), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, `turn ${card.turn}`), /* @__PURE__ */ React48.createElement(Text42, { color: FG.meta }, `\xB7 ${compactNum(card.tokens.prompt)} prompt \xB7 ${compactNum(card.tokens.output)} out`), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, "\xB7 cache"), /* @__PURE__ */ React48.createElement(Text42, { color: TONE.ok }, `${(card.cacheHit * 100).toFixed(0)}%`), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, `\xB7 ${formatCost(card.cost, card.balanceCurrency)}${elapsed}`), card.balance !== void 0 ? /* @__PURE__ */ React48.createElement(Text42, { color: TONE.brand }, `\xB7 ${formatBalance(card.balance, card.balanceCurrency)}`) : null);
8984
+ return /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1, marginTop: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.meta }, "\u03A3"), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `turn ${card.turn}`), /* @__PURE__ */ React49.createElement(Text43, { color: FG.meta }, `\xB7 ${compactNum(card.tokens.prompt)} prompt \xB7 ${compactNum(card.tokens.output)} out`), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, "\xB7 cache"), /* @__PURE__ */ React49.createElement(Text43, { color: TONE.ok }, `${(card.cacheHit * 100).toFixed(0)}%`), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `\xB7 ${formatCost(card.cost, card.balanceCurrency)}${elapsed}`), card.balance !== void 0 ? /* @__PURE__ */ React49.createElement(Text43, { color: TONE.brand }, `\xB7 ${formatBalance(card.balance, card.balanceCurrency)}`) : null);
8838
8985
  }
8839
8986
 
8840
8987
  // src/cli/ui/cards/UserCard.tsx
8841
- import React49 from "react";
8988
+ import React50 from "react";
8842
8989
 
8843
8990
  // src/cli/ui/cards/time.ts
8844
8991
  function formatRelativeTime(ts, now = Date.now()) {
@@ -8855,7 +9002,7 @@ function formatRelativeTime(ts, now = Date.now()) {
8855
9002
 
8856
9003
  // src/cli/ui/cards/UserCard.tsx
8857
9004
  function UserCard({ card }) {
8858
- return /* @__PURE__ */ React49.createElement(Card, { tone: TONE.accent }, /* @__PURE__ */ React49.createElement(
9005
+ return /* @__PURE__ */ React50.createElement(Card, { tone: TONE.accent }, /* @__PURE__ */ React50.createElement(
8859
9006
  CardHeader,
8860
9007
  {
8861
9008
  glyph: "\u203A",
@@ -8864,15 +9011,15 @@ function UserCard({ card }) {
8864
9011
  titleColor: FG.sub,
8865
9012
  meta: [formatRelativeTime(card.ts)]
8866
9013
  }
8867
- ), /* @__PURE__ */ React49.createElement(Markdown, { text: card.text }));
9014
+ ), /* @__PURE__ */ React50.createElement(Markdown, { text: card.text }));
8868
9015
  }
8869
9016
 
8870
9017
  // src/cli/ui/cards/WarnCard.tsx
8871
- import { Text as Text43 } from "ink";
8872
- import React50 from "react";
9018
+ import { Text as Text44 } from "ink";
9019
+ import React51 from "react";
8873
9020
  function WarnCard({ card }) {
8874
9021
  const messageLines = card.message.length > 0 ? card.message.split("\n") : [];
8875
- return /* @__PURE__ */ React50.createElement(Card, { tone: TONE.warn }, /* @__PURE__ */ React50.createElement(
9022
+ return /* @__PURE__ */ React51.createElement(Card, { tone: TONE.warn }, /* @__PURE__ */ React51.createElement(
8876
9023
  CardHeader,
8877
9024
  {
8878
9025
  glyph: "\u26A0",
@@ -8880,55 +9027,57 @@ function WarnCard({ card }) {
8880
9027
  title: card.title,
8881
9028
  meta: card.detail ? [card.detail] : void 0
8882
9029
  }
8883
- ), messageLines.map((line, i) => /* @__PURE__ */ React50.createElement(Text43, { key: `${card.id}:${i}`, color: FG.body }, line || " ")));
9030
+ ), messageLines.map((line, i) => /* @__PURE__ */ React51.createElement(Text44, { key: `${card.id}:${i}`, color: FG.body }, line || " ")));
8884
9031
  }
8885
9032
 
8886
9033
  // src/cli/ui/cards/CardRenderer.tsx
8887
- var CardRenderer = React51.memo(function CardRenderer2({
9034
+ var CardRenderer = React52.memo(function CardRenderer2({
8888
9035
  card
8889
9036
  }) {
8890
- return /* @__PURE__ */ React51.createElement(Box42, { flexDirection: "column" }, renderCard(card));
9037
+ return /* @__PURE__ */ React52.createElement(Box43, { flexDirection: "column" }, renderCard(card));
8891
9038
  });
8892
9039
  function renderCard(card) {
8893
9040
  switch (card.kind) {
8894
9041
  case "user":
8895
- return /* @__PURE__ */ React51.createElement(UserCard, { card });
9042
+ return /* @__PURE__ */ React52.createElement(UserCard, { card });
8896
9043
  case "reasoning":
8897
- return /* @__PURE__ */ React51.createElement(ReasoningCard, { card, expanded: true });
9044
+ return /* @__PURE__ */ React52.createElement(ReasoningCard, { card, expanded: true });
8898
9045
  case "streaming":
8899
- return /* @__PURE__ */ React51.createElement(StreamingCard, { card });
9046
+ return /* @__PURE__ */ React52.createElement(StreamingCard, { card });
8900
9047
  case "tool":
8901
- return /* @__PURE__ */ React51.createElement(ToolCard, { card });
9048
+ return /* @__PURE__ */ React52.createElement(ToolCard, { card });
8902
9049
  case "task":
8903
- return /* @__PURE__ */ React51.createElement(TaskCard, { card });
9050
+ return /* @__PURE__ */ React52.createElement(TaskCard, { card });
8904
9051
  case "plan":
8905
- return /* @__PURE__ */ React51.createElement(PlanCard, { card });
9052
+ return /* @__PURE__ */ React52.createElement(PlanCard, { card });
8906
9053
  case "diff":
8907
- return /* @__PURE__ */ React51.createElement(DiffCard, { card });
9054
+ return /* @__PURE__ */ React52.createElement(DiffCard, { card });
8908
9055
  case "error":
8909
- return /* @__PURE__ */ React51.createElement(ErrorCard, { card });
9056
+ return /* @__PURE__ */ React52.createElement(ErrorCard, { card });
8910
9057
  case "warn":
8911
- return /* @__PURE__ */ React51.createElement(WarnCard, { card });
9058
+ return /* @__PURE__ */ React52.createElement(WarnCard, { card });
8912
9059
  case "usage":
8913
- return /* @__PURE__ */ React51.createElement(UsageCard, { card });
9060
+ return /* @__PURE__ */ React52.createElement(UsageCard, { card });
8914
9061
  case "memory":
8915
- return /* @__PURE__ */ React51.createElement(MemoryCard, { card });
9062
+ return /* @__PURE__ */ React52.createElement(MemoryCard, { card });
8916
9063
  case "subagent":
8917
- return /* @__PURE__ */ React51.createElement(SubAgentCard, { card });
9064
+ return /* @__PURE__ */ React52.createElement(SubAgentCard, { card });
8918
9065
  case "search":
8919
- return /* @__PURE__ */ React51.createElement(SearchCard, { card });
9066
+ return /* @__PURE__ */ React52.createElement(SearchCard, { card });
8920
9067
  case "live":
8921
- return /* @__PURE__ */ React51.createElement(LiveCard, { card });
9068
+ return /* @__PURE__ */ React52.createElement(LiveCard, { card });
9069
+ case "tip":
9070
+ return /* @__PURE__ */ React52.createElement(TipCard, { card });
8922
9071
  case "ctx":
8923
- return /* @__PURE__ */ React51.createElement(CtxCard, { card });
9072
+ return /* @__PURE__ */ React52.createElement(CtxCard, { card });
8924
9073
  case "doctor":
8925
- return /* @__PURE__ */ React51.createElement(DoctorCard, { card });
9074
+ return /* @__PURE__ */ React52.createElement(DoctorCard, { card });
8926
9075
  default:
8927
- return /* @__PURE__ */ React51.createElement(FallbackCard, { card });
9076
+ return /* @__PURE__ */ React52.createElement(FallbackCard, { card });
8928
9077
  }
8929
9078
  }
8930
9079
  function FallbackCard({ card }) {
8931
- return /* @__PURE__ */ React51.createElement(Box42, { flexDirection: "row" }, /* @__PURE__ */ React51.createElement(Text44, { color: FG.faint }, ` \xB7 ${card.kind} card \xB7 not yet migrated`));
9080
+ return /* @__PURE__ */ React52.createElement(Box43, { flexDirection: "row" }, /* @__PURE__ */ React52.createElement(Text45, { color: FG.faint }, ` \xB7 ${card.kind} card \xB7 not yet migrated`));
8932
9081
  }
8933
9082
 
8934
9083
  // src/cli/ui/layout/CardStream.tsx
@@ -8938,8 +9087,8 @@ function CardStream({
8938
9087
  suppressLive = false
8939
9088
  }) {
8940
9089
  const cards = useAgentState((s) => s.cards);
8941
- const outerRef = useRef4(null);
8942
- const innerRef = useRef4(null);
9090
+ const outerRef = useRef5(null);
9091
+ const innerRef = useRef5(null);
8943
9092
  const outer = useBoxMetrics(outerRef);
8944
9093
  const inner = useBoxMetrics(innerRef);
8945
9094
  const maxScroll = Math.max(0, inner.height - outer.height);
@@ -8950,7 +9099,7 @@ function CardStream({
8950
9099
  if (suppressLive && cards.length > 0 && !isFullySettled(cards[cards.length - 1])) {
8951
9100
  visible = cards.slice(0, -1);
8952
9101
  }
8953
- return /* @__PURE__ */ React52.createElement(React52.Fragment, null, scrollRows > 0 ? /* @__PURE__ */ React52.createElement(Text45, { color: FG.faint }, " \u2191 earlier \u2014 PgUp / wheel / \u2191") : null, /* @__PURE__ */ React52.createElement(Box43, { ref: outerRef, flexDirection: "column", flexGrow: 1, overflow: "hidden" }, /* @__PURE__ */ React52.createElement(Box43, { ref: innerRef, flexDirection: "column", marginTop: -scrollRows, flexShrink: 0 }, visible.map((card) => /* @__PURE__ */ React52.createElement(CardRenderer, { key: card.id, card })))));
9102
+ return /* @__PURE__ */ React53.createElement(React53.Fragment, null, scrollRows > 0 ? /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, " \u2191 earlier \u2014 PgUp / wheel / \u2191") : null, /* @__PURE__ */ React53.createElement(Box44, { ref: outerRef, flexDirection: "column", flexGrow: 1, overflow: "hidden" }, /* @__PURE__ */ React53.createElement(Box44, { ref: innerRef, flexDirection: "column", marginTop: -scrollRows, flexShrink: 0 }, visible.map((card) => /* @__PURE__ */ React53.createElement(CardRenderer, { key: card.id, card })))));
8954
9103
  }
8955
9104
  function isFullySettled(card) {
8956
9105
  switch (card.kind) {
@@ -8970,12 +9119,13 @@ function isFullySettled(card) {
8970
9119
  }
8971
9120
 
8972
9121
  // src/cli/ui/layout/LiveRows.tsx
8973
- import { Box as Box44, Text as Text46 } from "ink";
8974
- import React53 from "react";
9122
+ import { Box as Box45, Text as Text47 } from "ink";
9123
+ import React54 from "react";
8975
9124
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
8976
9125
  function ThinkingRow({ text }) {
8977
9126
  const elapsed = useElapsedSeconds();
8978
- return /* @__PURE__ */ React53.createElement(Box44, { marginY: 1, paddingX: 1, gap: 1 }, /* @__PURE__ */ React53.createElement(Spinner, { kind: "circle", color: TONE.accent }), /* @__PURE__ */ React53.createElement(Text46, { italic: true, color: FG.sub }, text), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, `${elapsed}s`));
9127
+ const { fg, tone } = useThemeTokens();
9128
+ return /* @__PURE__ */ React54.createElement(Box45, { marginY: 1, paddingX: 1, gap: 1 }, /* @__PURE__ */ React54.createElement(Spinner, { kind: "circle", color: TONE.accent }), /* @__PURE__ */ React54.createElement(Text47, { italic: true, color: FG.sub }, text), /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, `${elapsed}s`));
8979
9129
  }
8980
9130
  function ModeStatusBar({
8981
9131
  editMode,
@@ -8987,24 +9137,24 @@ function ModeStatusBar({
8987
9137
  }) {
8988
9138
  useSlowTick();
8989
9139
  const running = jobs2?.runningCount() ?? 0;
8990
- const jobsTag = running > 0 ? /* @__PURE__ */ React53.createElement(Text46, { color: TONE.warn, bold: true }, ` \xB7 \u23F5 ${running} job${running === 1 ? "" : "s"}`) : null;
9140
+ const jobsTag = running > 0 ? /* @__PURE__ */ React54.createElement(Text47, { color: TONE.warn, bold: true }, ` \xB7 \u23F5 ${running} job${running === 1 ? "" : "s"}`) : null;
8991
9141
  if (planMode) {
8992
- return /* @__PURE__ */ React53.createElement(ModeBarFrame, null, /* @__PURE__ */ React53.createElement(ModePill, { label: "PLAN MODE", color: TONE.err, flash }), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, " writes gated \xB7 /plan off to leave"), jobsTag);
9142
+ return /* @__PURE__ */ React54.createElement(ModeBarFrame, null, /* @__PURE__ */ React54.createElement(ModePill, { label: "PLAN MODE", color: TONE.err, flash }), /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, " writes gated \xB7 /plan off to leave"), jobsTag);
8993
9143
  }
8994
9144
  const label = editMode === "yolo" ? "YOLO" : editMode === "auto" ? "AUTO" : "REVIEW";
8995
9145
  const pillColor = editMode === "yolo" ? TONE.err : editMode === "auto" ? TONE.accent : TONE.brand;
8996
9146
  const mid = editMode === "yolo" ? "edits + shell auto \xB7 /undo to roll back" : editMode === "auto" ? "edits land now \xB7 u to undo" : pendingCount > 0 ? `${pendingCount} queued \xB7 y apply \xB7 n discard` : "edits queued \xB7 y apply \xB7 n discard";
8997
- return /* @__PURE__ */ React53.createElement(ModeBarFrame, null, /* @__PURE__ */ React53.createElement(ModePill, { label, color: pillColor, flash }), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, ` ${mid} \xB7 Shift+Tab to flip`), jobsTag);
9147
+ return /* @__PURE__ */ React54.createElement(ModeBarFrame, null, /* @__PURE__ */ React54.createElement(ModePill, { label, color: pillColor, flash }), /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, ` ${mid} \xB7 Shift+Tab to flip`), jobsTag);
8998
9148
  }
8999
9149
  function ModeBarFrame({ children }) {
9000
- return /* @__PURE__ */ React53.createElement(Box44, { paddingX: 1 }, children);
9150
+ return /* @__PURE__ */ React54.createElement(Box45, { paddingX: 1 }, children);
9001
9151
  }
9002
9152
  function ModePill({
9003
9153
  label,
9004
9154
  color,
9005
9155
  flash
9006
9156
  }) {
9007
- return /* @__PURE__ */ React53.createElement(Text46, { color, bold: true, inverse: flash }, `[${label}]`);
9157
+ return /* @__PURE__ */ React54.createElement(Text47, { color, bold: true, inverse: flash }, `[${label}]`);
9008
9158
  }
9009
9159
  function UndoBanner({
9010
9160
  banner
@@ -9019,7 +9169,7 @@ function UndoBanner({
9019
9169
  const urgent = !paused && remainingSec <= 1;
9020
9170
  const pct = remainingMs / totalMs * 100;
9021
9171
  const tone = paused ? TONE.warn : urgent ? TONE.err : TONE.accent;
9022
- return /* @__PURE__ */ React53.createElement(Box44, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React53.createElement(Text46, { backgroundColor: TONE.accent, color: "black", bold: true }, ` \u2713 AUTO-APPLIED ${ok}/${total} `), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, " press "), /* @__PURE__ */ React53.createElement(Text46, { backgroundColor: TONE.brand, color: "black", bold: true }, " u "), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, paused ? " to undo \xB7 " : " to undo \xB7 "), /* @__PURE__ */ React53.createElement(Text46, { backgroundColor: paused ? TONE.warn : FG.faint, color: "black", bold: true }, " space "), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, paused ? " to resume " : " to pause "), /* @__PURE__ */ React53.createElement(CharBar, { pct, width: 20, color: tone, showLabel: false }), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, " "), /* @__PURE__ */ React53.createElement(Text46, { color: tone, bold: urgent || paused }, paused ? `${remainingSec}s \xB7 paused` : `${remainingSec}s`));
9172
+ return /* @__PURE__ */ React54.createElement(Box45, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React54.createElement(Text47, { backgroundColor: TONE.accent, color: "black", bold: true }, ` \u2713 AUTO-APPLIED ${ok}/${total} `), /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, " press "), /* @__PURE__ */ React54.createElement(Text47, { backgroundColor: TONE.brand, color: "black", bold: true }, " u "), /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, paused ? " to undo \xB7 " : " to undo \xB7 "), /* @__PURE__ */ React54.createElement(Text47, { backgroundColor: paused ? TONE.warn : FG.faint, color: "black", bold: true }, " space "), /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, paused ? " to resume " : " to pause "), /* @__PURE__ */ React54.createElement(CharBar, { pct, width: 20, color: tone, showLabel: false }), /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, " "), /* @__PURE__ */ React54.createElement(Text47, { color: tone, bold: urgent || paused }, paused ? `${remainingSec}s \xB7 paused` : `${remainingSec}s`));
9023
9173
  }
9024
9174
  function subagentPhaseLabel(phase, iter, elapsedMs) {
9025
9175
  if (phase === "summarising") return "summarising findings\u2026";
@@ -9034,7 +9184,7 @@ function SubagentRow({ activity }) {
9034
9184
  const last = activity.lastInner;
9035
9185
  const subtitle = activity.skillName ?? truncate2(activity.task, 48);
9036
9186
  const modelBadge = activity.model ? modelBadgeFor(activity.model) : null;
9037
- return /* @__PURE__ */ React53.createElement(Card, { tone: CARD.subagent.color }, /* @__PURE__ */ React53.createElement(
9187
+ return /* @__PURE__ */ React54.createElement(Card, { tone: CARD.subagent.color }, /* @__PURE__ */ React54.createElement(
9038
9188
  CardHeader,
9039
9189
  {
9040
9190
  glyph: "\u232C",
@@ -9044,9 +9194,9 @@ function SubagentRow({ activity }) {
9044
9194
  titleBg: PILL_SECTION.plan.bg,
9045
9195
  subtitle,
9046
9196
  meta: [`iter ${activity.iter}`, `${seconds}s`],
9047
- right: /* @__PURE__ */ React53.createElement(React53.Fragment, null, modelBadge ? /* @__PURE__ */ React53.createElement(Pill, { label: modelBadge.label, ...PILL_MODEL[modelBadge.kind], bold: false }) : null, /* @__PURE__ */ React53.createElement(Spinner, { kind: "braille", color: CARD.subagent.color }))
9197
+ right: /* @__PURE__ */ React54.createElement(React54.Fragment, null, modelBadge ? /* @__PURE__ */ React54.createElement(Pill, { label: modelBadge.label, ...PILL_MODEL[modelBadge.kind], bold: false }) : null, /* @__PURE__ */ React54.createElement(Spinner, { kind: "braille", color: CARD.subagent.color }))
9048
9198
  }
9049
- ), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, "task ", /* @__PURE__ */ React53.createElement(Text46, { color: FG.sub }, activity.task)), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, "last ", last ? /* @__PURE__ */ React53.createElement(React53.Fragment, null, /* @__PURE__ */ React53.createElement(Text46, { color: last.color }, `${last.glyph} `), /* @__PURE__ */ React53.createElement(Text46, { color: FG.body }, last.label), last.meta ? /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, ` ${last.meta}`) : null) : /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, "queued\u2026")), /* @__PURE__ */ React53.createElement(Text46, { color: TONE.brand }, "\u25B6 ", phase));
9199
+ ), /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, "task ", /* @__PURE__ */ React54.createElement(Text47, { color: FG.sub }, activity.task)), /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, "last ", last ? /* @__PURE__ */ React54.createElement(React54.Fragment, null, /* @__PURE__ */ React54.createElement(Text47, { color: last.color }, `${last.glyph} `), /* @__PURE__ */ React54.createElement(Text47, { color: FG.body }, last.label), last.meta ? /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, ` ${last.meta}`) : null) : /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, "queued\u2026")), /* @__PURE__ */ React54.createElement(Text47, { color: TONE.brand }, "\u25B6 ", phase));
9050
9200
  }
9051
9201
  function SubagentLiveStack({
9052
9202
  activities,
@@ -9054,13 +9204,13 @@ function SubagentLiveStack({
9054
9204
  }) {
9055
9205
  const tick = useTick();
9056
9206
  if (activities.length === 0) return null;
9057
- if (activities.length === 1) return /* @__PURE__ */ React53.createElement(SubagentRow, { activity: activities[0] });
9207
+ if (activities.length === 1) return /* @__PURE__ */ React54.createElement(SubagentRow, { activity: activities[0] });
9058
9208
  const visible = activities.slice(0, max);
9059
9209
  const overflow = activities.length - visible.length;
9060
9210
  const summarising = activities.filter((a) => a.phase === "summarising").length;
9061
9211
  const metaParts = [`${activities.length} running`];
9062
9212
  if (summarising > 0) metaParts.push(`${summarising} summarising`);
9063
- return /* @__PURE__ */ React53.createElement(Card, { tone: CARD.subagent.color }, /* @__PURE__ */ React53.createElement(
9213
+ return /* @__PURE__ */ React54.createElement(Card, { tone: CARD.subagent.color }, /* @__PURE__ */ React54.createElement(
9064
9214
  CardHeader,
9065
9215
  {
9066
9216
  glyph: "\u232C",
@@ -9069,9 +9219,9 @@ function SubagentLiveStack({
9069
9219
  titleColor: PILL_SECTION.plan.fg,
9070
9220
  titleBg: PILL_SECTION.plan.bg,
9071
9221
  subtitle: metaParts.join(" \xB7 "),
9072
- right: /* @__PURE__ */ React53.createElement(Spinner, { kind: "braille", color: CARD.subagent.color })
9222
+ right: /* @__PURE__ */ React54.createElement(Spinner, { kind: "braille", color: CARD.subagent.color })
9073
9223
  }
9074
- ), visible.map((a, i) => /* @__PURE__ */ React53.createElement(CompactSubagentLine, { key: a.runId, activity: a, tick, index: i })), overflow > 0 ? /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, ` +${overflow} more running\u2026`) : null);
9224
+ ), visible.map((a, i) => /* @__PURE__ */ React54.createElement(CompactSubagentLine, { key: a.runId, activity: a, tick, index: i })), overflow > 0 ? /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, ` +${overflow} more running\u2026`) : null);
9075
9225
  }
9076
9226
  function CompactSubagentLine({
9077
9227
  activity,
@@ -9086,7 +9236,7 @@ function CompactSubagentLine({
9086
9236
  const title = activity.skillName ?? truncate2(activity.task, 28);
9087
9237
  const titlePadded = title.padEnd(28);
9088
9238
  const last = activity.lastInner;
9089
- return /* @__PURE__ */ React53.createElement(Box44, { flexDirection: "row" }, /* @__PURE__ */ React53.createElement(Text46, { color: glyphColor, bold: true }, ` ${glyph} `), /* @__PURE__ */ React53.createElement(Text46, { color: FG.body }, titlePadded), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, ` iter ${String(activity.iter).padStart(2)} \xB7 ${seconds}s \xB7 `), last ? /* @__PURE__ */ React53.createElement(React53.Fragment, null, /* @__PURE__ */ React53.createElement(Text46, { color: last.color }, `${last.glyph} `), /* @__PURE__ */ React53.createElement(Text46, { color: FG.body }, truncate2(last.label, 18)), last.meta ? /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, ` ${last.meta}`) : null) : /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, "queued\u2026"));
9239
+ return /* @__PURE__ */ React54.createElement(Box45, { flexDirection: "row" }, /* @__PURE__ */ React54.createElement(Text47, { color: glyphColor, bold: true }, ` ${glyph} `), /* @__PURE__ */ React54.createElement(Text47, { color: FG.body }, titlePadded), /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, ` iter ${String(activity.iter).padStart(2)} \xB7 ${seconds}s \xB7 `), last ? /* @__PURE__ */ React54.createElement(React54.Fragment, null, /* @__PURE__ */ React54.createElement(Text47, { color: last.color }, `${last.glyph} `), /* @__PURE__ */ React54.createElement(Text47, { color: FG.body }, truncate2(last.label, 18)), last.meta ? /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, ` ${last.meta}`) : null) : /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, "queued\u2026"));
9090
9240
  }
9091
9241
  function truncate2(text, max) {
9092
9242
  return text.length > max ? `${text.slice(0, max)}\u2026` : text;
@@ -9098,7 +9248,7 @@ function OngoingToolRow({
9098
9248
  const tick = useTick();
9099
9249
  const elapsed = useElapsedSeconds();
9100
9250
  const summary = summarizeToolArgs(tool.name, tool.args);
9101
- return /* @__PURE__ */ React53.createElement(Box44, { marginY: 1, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React53.createElement(Box44, null, /* @__PURE__ */ React53.createElement(Text46, { color: CARD.tool.color, bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React53.createElement(Text46, null, " "), /* @__PURE__ */ React53.createElement(Text46, { color: CARD.tool.color, bold: true }, `\u25A3 ${tool.name}`), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, ` running \xB7 ${elapsed}s`)), progress ? /* @__PURE__ */ React53.createElement(Box44, { paddingLeft: 3 }, /* @__PURE__ */ React53.createElement(Text46, { color: TONE.brand }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ React53.createElement(Box44, { paddingLeft: 3 }, /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, summary)) : null);
9251
+ return /* @__PURE__ */ React54.createElement(Box45, { marginY: 1, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React54.createElement(Box45, null, /* @__PURE__ */ React54.createElement(Text47, { color: CARD.tool.color, bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React54.createElement(Text47, null, " "), /* @__PURE__ */ React54.createElement(Text47, { color: CARD.tool.color, bold: true }, `\u25A3 ${tool.name}`), /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, ` running \xB7 ${elapsed}s`)), progress ? /* @__PURE__ */ React54.createElement(Box45, { paddingLeft: 3 }, /* @__PURE__ */ React54.createElement(Text47, { color: TONE.brand }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ React54.createElement(Box45, { paddingLeft: 3 }, /* @__PURE__ */ React54.createElement(Text47, { color: FG.faint }, summary)) : null);
9102
9252
  }
9103
9253
  function renderProgressLine(p) {
9104
9254
  const msg = p.message ? ` ${p.message}` : "";
@@ -9154,16 +9304,16 @@ function summarizeToolArgs(name, args) {
9154
9304
  }
9155
9305
 
9156
9306
  // src/cli/ui/layout/StatusRow.tsx
9157
- import { Box as Box45, Text as Text48, useStdout as useStdout12 } from "ink";
9158
- import React55 from "react";
9307
+ import { Box as Box46, Text as Text49, useStdout as useStdout12 } from "ink";
9308
+ import React56 from "react";
9159
9309
 
9160
9310
  // src/cli/ui/primitives/Countdown.tsx
9161
- import { Text as Text47 } from "ink";
9162
- import React54 from "react";
9311
+ import { Text as Text48 } from "ink";
9312
+ import React55 from "react";
9163
9313
  function Countdown({ endsAt, color = TONE.brand }) {
9164
9314
  useSlowTick();
9165
9315
  const remainingSec = Math.max(0, Math.ceil((endsAt - Date.now()) / 1e3));
9166
- return /* @__PURE__ */ React54.createElement(Text47, { bold: true, color }, String(remainingSec));
9316
+ return /* @__PURE__ */ React55.createElement(Text48, { bold: true, color }, String(remainingSec));
9167
9317
  }
9168
9318
 
9169
9319
  // src/cli/ui/layout/StatusRow.tsx
@@ -9180,7 +9330,7 @@ function StatusRow() {
9180
9330
  const hasSession = status2.sessionCost > 0;
9181
9331
  const hasBalance = typeof status2.balance === "number";
9182
9332
  const showWallet = cols >= WALLET_MIN_COLS && (hasSession || hasBalance);
9183
- return /* @__PURE__ */ React55.createElement(Box45, { flexDirection: "column" }, /* @__PURE__ */ React55.createElement(Box45, null, /* @__PURE__ */ React55.createElement(Text48, null, " "), /* @__PURE__ */ React55.createElement(Text48, { color: FG.faint }, "\u2500".repeat(ruleWidth))), /* @__PURE__ */ React55.createElement(Box45, { flexDirection: "row" }, /* @__PURE__ */ React55.createElement(Text48, null, " "), status2.recording ? /* @__PURE__ */ React55.createElement(RecordingPill, { rec: status2.recording }) : status2.countdownSeconds !== void 0 ? /* @__PURE__ */ React55.createElement(CountdownRow, { mode: status2.mode, secondsLeft: status2.countdownSeconds }) : /* @__PURE__ */ React55.createElement(ModePill2, { mode: status2.mode, network: status2.network, detail: status2.networkDetail }), /* @__PURE__ */ React55.createElement(Sep, null), /* @__PURE__ */ React55.createElement(Text48, { color: FG.sub }, `${session.id} \xB7 ${session.branch}`), hasTurn && /* @__PURE__ */ React55.createElement(React55.Fragment, null, /* @__PURE__ */ React55.createElement(Sep, null), /* @__PURE__ */ React55.createElement(Text48, { bold: true, color: TONE.brand }, "\u25B8 "), /* @__PURE__ */ React55.createElement(Text48, { bold: true, color: FG.body }, `${formatCost(status2.cost, status2.balanceCurrency)} turn`)), /* @__PURE__ */ React55.createElement(Sep, null), /* @__PURE__ */ React55.createElement(Text48, { color: TONE.accent }, `cache ${Math.round(status2.cacheHit * 100)}%`), showWallet && /* @__PURE__ */ React55.createElement(
9333
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "column" }, /* @__PURE__ */ React56.createElement(Box46, null, /* @__PURE__ */ React56.createElement(Text49, null, " "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint }, "\u2500".repeat(ruleWidth))), /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, null, " "), status2.recording ? /* @__PURE__ */ React56.createElement(RecordingPill, { rec: status2.recording }) : status2.countdownSeconds !== void 0 ? /* @__PURE__ */ React56.createElement(CountdownRow, { mode: status2.mode, secondsLeft: status2.countdownSeconds }) : /* @__PURE__ */ React56.createElement(ModePill2, { mode: status2.mode, network: status2.network, detail: status2.networkDetail }), /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub }, `${session.id} \xB7 ${session.branch}`), hasTurn && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: TONE.brand }, "\u25B8 "), /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: FG.body }, `${formatCost(status2.cost, status2.balanceCurrency)} turn`)), /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.accent }, `cache ${Math.round(status2.cacheHit * 100)}%`), showWallet && /* @__PURE__ */ React56.createElement(
9184
9334
  WalletPill,
9185
9335
  {
9186
9336
  sessionCostUsd: status2.sessionCost,
@@ -9196,7 +9346,7 @@ function WalletPill({
9196
9346
  }) {
9197
9347
  const showSpent = sessionCostUsd > 0;
9198
9348
  const showBalance = typeof balance === "number";
9199
- return /* @__PURE__ */ React55.createElement(React55.Fragment, null, /* @__PURE__ */ React55.createElement(Sep, null), /* @__PURE__ */ React55.createElement(Text48, { color: FG.meta }, "\u26C1 "), showSpent && /* @__PURE__ */ React55.createElement(Text48, { color: FG.body }, `${formatCost(sessionCostUsd, currency, 2)} spent`), showSpent && showBalance && /* @__PURE__ */ React55.createElement(Text48, { color: FG.meta }, " / "), showBalance && /* @__PURE__ */ React55.createElement(Text48, { bold: true, color: balanceColor(balance, currency) }, formatBalance(balance, currency, { fractionDigits: 2 })), showBalance && /* @__PURE__ */ React55.createElement(Text48, { color: FG.faint }, " left"));
9349
+ return /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta }, "\u26C1 "), showSpent && /* @__PURE__ */ React56.createElement(Text49, { color: FG.body }, `${formatCost(sessionCostUsd, currency, 2)} spent`), showSpent && showBalance && /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta }, " / "), showBalance && /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: balanceColor(balance, currency) }, formatBalance(balance, currency, { fractionDigits: 2 })), showBalance && /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint }, " left"));
9200
9350
  }
9201
9351
  function ModePill2({
9202
9352
  mode: mode2,
@@ -9205,18 +9355,18 @@ function ModePill2({
9205
9355
  }) {
9206
9356
  if (network === "online") {
9207
9357
  const pill = modeGlyph(mode2);
9208
- return /* @__PURE__ */ React55.createElement(Box45, { flexDirection: "row" }, /* @__PURE__ */ React55.createElement(Text48, { color: pill.color }, pill.glyph), /* @__PURE__ */ React55.createElement(Text48, { color: FG.sub }, ` ${mode2}`));
9358
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: pill.color }, pill.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub }, ` ${mode2}`));
9209
9359
  }
9210
9360
  const dot = networkDot(network);
9211
9361
  if (network === "slow") {
9212
9362
  const tail = detail ? ` \xB7 ${detail}` : "";
9213
- return /* @__PURE__ */ React55.createElement(Box45, { flexDirection: "row" }, /* @__PURE__ */ React55.createElement(Text48, { color: dot.color }, dot.glyph), /* @__PURE__ */ React55.createElement(Text48, { color: dot.color }, ` ${mode2} \xB7 slow${tail}`));
9363
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, ` ${mode2} \xB7 slow${tail}`));
9214
9364
  }
9215
9365
  if (network === "disconnected") {
9216
9366
  const tail = detail ? ` \xB7 ${detail}` : "";
9217
- return /* @__PURE__ */ React55.createElement(Box45, { flexDirection: "row" }, /* @__PURE__ */ React55.createElement(Text48, { color: dot.color }, dot.glyph), /* @__PURE__ */ React55.createElement(Text48, { color: dot.color }, ` disconnect${tail}`));
9367
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, ` disconnect${tail}`));
9218
9368
  }
9219
- return /* @__PURE__ */ React55.createElement(Box45, { flexDirection: "row" }, /* @__PURE__ */ React55.createElement(Text48, { color: dot.color }, dot.glyph), /* @__PURE__ */ React55.createElement(Text48, { color: dot.color }, " reconnecting\u2026"));
9369
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, " reconnecting\u2026"));
9220
9370
  }
9221
9371
  function CountdownRow({
9222
9372
  mode: mode2,
@@ -9224,14 +9374,14 @@ function CountdownRow({
9224
9374
  }) {
9225
9375
  const pill = modeGlyph(mode2);
9226
9376
  const endsAt = Date.now() + secondsLeft * 1e3;
9227
- return /* @__PURE__ */ React55.createElement(Box45, { flexDirection: "row" }, /* @__PURE__ */ React55.createElement(Text48, { color: pill.color }, pill.glyph), /* @__PURE__ */ React55.createElement(Text48, { color: FG.sub }, ` ${mode2} \xB7 `), /* @__PURE__ */ React55.createElement(Text48, { color: TONE.warn }, "approving in "), /* @__PURE__ */ React55.createElement(Countdown, { endsAt }), /* @__PURE__ */ React55.createElement(Text48, { color: TONE.warn }, "s \xB7 esc to interrupt"));
9377
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: pill.color }, pill.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub }, ` ${mode2} \xB7 `), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.warn }, "approving in "), /* @__PURE__ */ React56.createElement(Countdown, { endsAt }), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.warn }, "s \xB7 esc to interrupt"));
9228
9378
  }
9229
9379
  function RecordingPill({ rec }) {
9230
9380
  const sizeMb = (rec.sizeBytes / (1024 * 1024)).toFixed(1);
9231
- return /* @__PURE__ */ React55.createElement(Box45, { flexDirection: "row" }, /* @__PURE__ */ React55.createElement(Text48, { bold: true, color: TONE.err }, "\u25CFREC"), /* @__PURE__ */ React55.createElement(Text48, { color: TONE.err }, ` ${sizeMb} MB \xB7 ${rec.events} evt`));
9381
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: TONE.err }, "\u25CFREC"), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.err }, ` ${sizeMb} MB \xB7 ${rec.events} evt`));
9232
9382
  }
9233
9383
  function Sep() {
9234
- return /* @__PURE__ */ React55.createElement(Text48, { color: FG.meta }, " \xB7 ");
9384
+ return /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta }, " \xB7 ");
9235
9385
  }
9236
9386
  function modeGlyph(mode2) {
9237
9387
  switch (mode2) {
@@ -9259,8 +9409,8 @@ function networkDot(state) {
9259
9409
  }
9260
9410
 
9261
9411
  // src/cli/ui/layout/ToastRail.tsx
9262
- import { Box as Box46, Text as Text49, useStdout as useStdout13 } from "ink";
9263
- import React56, { useEffect as useEffect8 } from "react";
9412
+ import { Box as Box47, Text as Text50, useStdout as useStdout13 } from "ink";
9413
+ import React57, { useEffect as useEffect8 } from "react";
9264
9414
  var TONE_COLOR = {
9265
9415
  ok: TONE.ok,
9266
9416
  info: TONE.brand,
@@ -9298,17 +9448,17 @@ function ToastRail() {
9298
9448
  }, [toasts, dispatch]);
9299
9449
  const visible = toasts.filter((t2) => now - t2.bornAt < t2.ttlMs);
9300
9450
  if (visible.length === 0) return null;
9301
- return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "column" }, visible.map((t2) => {
9451
+ return /* @__PURE__ */ React57.createElement(Box47, { flexDirection: "column" }, visible.map((t2) => {
9302
9452
  const color = TONE_COLOR[t2.tone];
9303
9453
  const glyph = TONE_GLYPH[t2.tone];
9304
9454
  const body = bodyColor(t2, now);
9305
9455
  const remainingSec = Math.max(0, Math.ceil((t2.ttlMs - (now - t2.bornAt)) / 1e3));
9306
- return /* @__PURE__ */ React56.createElement(Box46, { key: t2.id, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React56.createElement(Text49, { color }, rule), /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color }, glyph), /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: body }, ` ${t2.title}`), t2.detail !== void 0 && /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub }, ` \xB7 ${t2.detail}`), /* @__PURE__ */ React56.createElement(Box46, { flexGrow: 1 }), /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint }, `${remainingSec}s`)));
9456
+ return /* @__PURE__ */ React57.createElement(Box47, { key: t2.id, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React57.createElement(Text50, { color }, rule), /* @__PURE__ */ React57.createElement(Box47, { flexDirection: "row" }, /* @__PURE__ */ React57.createElement(Text50, { color }, glyph), /* @__PURE__ */ React57.createElement(Text50, { bold: true, color: body }, ` ${t2.title}`), t2.detail !== void 0 && /* @__PURE__ */ React57.createElement(Text50, { color: FG.sub }, ` \xB7 ${t2.detail}`), /* @__PURE__ */ React57.createElement(Box47, { flexGrow: 1 }), /* @__PURE__ */ React57.createElement(Text50, { color: FG.faint }, `${remainingSec}s`)));
9307
9457
  }));
9308
9458
  }
9309
9459
 
9310
9460
  // src/cli/ui/layout/plan-live-row.tsx
9311
- import React57 from "react";
9461
+ import React58 from "react";
9312
9462
  function isActivePlanInFlight(card) {
9313
9463
  if (card.kind !== "plan") return false;
9314
9464
  if (card.variant !== "active") return false;
@@ -9323,7 +9473,7 @@ function PlanLiveRow() {
9323
9473
  return null;
9324
9474
  });
9325
9475
  if (!planCard) return null;
9326
- return /* @__PURE__ */ React57.createElement(PlanCard, { card: planCard });
9476
+ return /* @__PURE__ */ React58.createElement(PlanCard, { card: planCard });
9327
9477
  }
9328
9478
 
9329
9479
  // src/cli/ui/loop.ts
@@ -9851,12 +10001,19 @@ var loop = (args, _loop, ctx) => {
9851
10001
  })
9852
10002
  };
9853
10003
  };
10004
+ var keys = (_args, _loop, ctx) => {
10005
+ if (!ctx.postKeys) return { info: t("handlers.basic.keysNeedsTui") };
10006
+ const ref = tObj("ui.keysReference");
10007
+ ctx.postKeys({ topic: ref.topic, sections: ref.sections, footer: ref.footer });
10008
+ return {};
10009
+ };
9854
10010
  var handlers2 = {
9855
10011
  exit,
9856
10012
  new: resetLog,
9857
10013
  help,
9858
10014
  retry,
9859
- loop
10015
+ loop,
10016
+ keys
9860
10017
  };
9861
10018
 
9862
10019
  // src/cli/ui/slash/handlers/dashboard.ts
@@ -10775,8 +10932,8 @@ var handlers10 = {
10775
10932
  };
10776
10933
 
10777
10934
  // src/cli/ui/ctx-breakdown.tsx
10778
- import { Box as Box47, Text as Text50 } from "ink";
10779
- import React58 from "react";
10935
+ import { Box as Box48, Text as Text51 } from "ink";
10936
+ import React59 from "react";
10780
10937
  function computeCtxBreakdown(loop2) {
10781
10938
  const systemTokens = countTokens(loop2.prefix.system);
10782
10939
  const toolsTokens = countTokens(JSON.stringify(loop2.prefix.toolSpecs));
@@ -11306,8 +11463,40 @@ var handlers15 = {
11306
11463
  skills: skill
11307
11464
  };
11308
11465
 
11309
- // src/cli/ui/slash/handlers/web-search-engine.ts
11466
+ // src/cli/ui/slash/handlers/theme.ts
11467
+ var themeChoices = ["auto", ...listThemeNames()];
11468
+ function formatThemeStatus() {
11469
+ const configured = loadTheme();
11470
+ const active = resolveThemePreference(configured, process.env.REASONIX_THEME);
11471
+ const source = configured && configured !== "auto" ? "config" : "env/default";
11472
+ return [
11473
+ `theme: ${active} (${source})`,
11474
+ `configured: ${configured ?? "unset"}`,
11475
+ `available: ${themeChoices.join(", ")}`,
11476
+ "usage: /theme <name|auto>"
11477
+ ].join("\n");
11478
+ }
11479
+ function isThemeChoice(value) {
11480
+ return value === "auto" || isThemeName(value);
11481
+ }
11482
+ var theme = (args) => {
11483
+ const next = args[0];
11484
+ if (!next) return { info: formatThemeStatus() };
11485
+ if (!isThemeChoice(next)) {
11486
+ return { info: `unknown theme: ${next}
11487
+ available: ${themeChoices.join(", ")}` };
11488
+ }
11489
+ saveTheme(next);
11490
+ const active = resolveThemePreference(next, process.env.REASONIX_THEME);
11491
+ return { info: `theme saved: ${next}
11492
+ active on next launch: ${active}` };
11493
+ };
11310
11494
  var handlers16 = {
11495
+ theme
11496
+ };
11497
+
11498
+ // src/cli/ui/slash/handlers/web-search-engine.ts
11499
+ var handlers17 = {
11311
11500
  "search-engine": (args, _loop, ctx) => {
11312
11501
  const engine = args[0];
11313
11502
  if (!engine || engine !== "mojeek" && engine !== "searxng") {
@@ -11340,7 +11529,7 @@ var handlers16 = {
11340
11529
  const detail = engine === "searxng" ? t("handlers.webSearchEngine.confirmedDetail", { endpoint: webSearchEndpoint() }) : "";
11341
11530
  return { info: t("handlers.webSearchEngine.confirmed", { engine, detail }) };
11342
11531
  },
11343
- se: (args, loop2, ctx) => handlers16["search-engine"](args, loop2, ctx)
11532
+ se: (args, loop2, ctx) => handlers17["search-engine"](args, loop2, ctx)
11344
11533
  };
11345
11534
 
11346
11535
  // src/cli/ui/slash/dispatch.ts
@@ -11359,8 +11548,9 @@ var HANDLERS = {
11359
11548
  ...handlers12,
11360
11549
  ...handlers13,
11361
11550
  ...handlers14,
11551
+ ...handlers16,
11362
11552
  ...handlers15,
11363
- ...handlers16
11553
+ ...handlers17
11364
11554
  };
11365
11555
  function handleSlash(cmd, args, loop2, ctx = {}) {
11366
11556
  const h = HANDLERS[resolveSlashAlias(cmd)];
@@ -11497,6 +11687,20 @@ ${card.meta}` : card.text
11497
11687
  case "ctx":
11498
11688
  out.push({ id: card.id, role: "info", text: card.text });
11499
11689
  break;
11690
+ case "tip": {
11691
+ const sectionTexts = card.sections.map((sec) => {
11692
+ const body2 = sec.rows.map((r) => `${r.key} ${r.text}`).join("\n");
11693
+ return sec.title ? `[${sec.title}]
11694
+ ${body2}` : body2;
11695
+ });
11696
+ const body = sectionTexts.join("\n\n");
11697
+ const text = card.footer ? `${card.topic}
11698
+ ${body}
11699
+ ${card.footer}` : `${card.topic}
11700
+ ${body}`;
11701
+ out.push({ id: card.id, role: "info", text });
11702
+ break;
11703
+ }
11500
11704
  case "plan": {
11501
11705
  const done = card.steps.filter((s) => s.status === "done").length;
11502
11706
  const tag2 = card.variant === "resumed" ? "[resumed]" : card.variant === "replay" ? "[replay]" : "";
@@ -11579,7 +11783,10 @@ function hydrateCardsFromMessages(messages) {
11579
11783
  }
11580
11784
 
11581
11785
  // src/cli/ui/useCompletionPickers.ts
11582
- import { useCallback as useCallback8, useEffect as useEffect9, useMemo as useMemo8, useRef as useRef5, useState as useState16 } from "react";
11786
+ import { useCallback as useCallback8, useEffect as useEffect9, useMemo as useMemo8, useReducer as useReducer2, useRef as useRef6, useState as useState16 } from "react";
11787
+ var SEARCH_DEBOUNCE_MS = 80;
11788
+ var SEARCH_FLUSH_MS = 50;
11789
+ var SEARCH_RESULT_CAP = 200;
11583
11790
  function useCompletionPickers({
11584
11791
  input,
11585
11792
  setInput,
@@ -11607,23 +11814,7 @@ function useCompletionPickers({
11607
11814
  });
11608
11815
  }, [slashMatches]);
11609
11816
  const [atSelected, setAtSelected] = useState16(0);
11610
- const [atFiles, setAtFiles] = useState16([]);
11611
- useEffect9(() => {
11612
- if (!codeMode) {
11613
- setAtFiles([]);
11614
- return;
11615
- }
11616
- let cancelled = false;
11617
- listFilesWithStatsAsync(rootDir, { maxResults: 500 }).then((files) => {
11618
- if (!cancelled) setAtFiles(files);
11619
- }).catch(() => {
11620
- if (!cancelled) setAtFiles([]);
11621
- });
11622
- return () => {
11623
- cancelled = true;
11624
- };
11625
- }, [codeMode, rootDir]);
11626
- const recentFilesRef = useRef5([]);
11817
+ const recentFilesRef = useRef6([]);
11627
11818
  const recordRecentFile = useCallback8((p) => {
11628
11819
  const list2 = recentFilesRef.current;
11629
11820
  const i = list2.indexOf(p);
@@ -11636,25 +11827,50 @@ function useCompletionPickers({
11636
11827
  if (slashMatches !== null) return null;
11637
11828
  return detectAtPicker(input);
11638
11829
  }, [codeMode, input, slashMatches]);
11639
- const atMatches = useMemo8(() => {
11640
- if (!atPicker) return null;
11641
- return rankPickerCandidates(atFiles, atPicker.query, {
11642
- limit: 40,
11643
- recentlyUsed: recentFilesRef.current
11644
- });
11645
- }, [atPicker, atFiles]);
11830
+ const parsed = useMemo8(
11831
+ () => atPicker ? parseAtQuery(atPicker.query) : null,
11832
+ [atPicker]
11833
+ );
11834
+ const atMode = parsed ? parsed.trailingSlash || parsed.filter === "" ? "browse" : "search" : null;
11835
+ const browseDir = parsed && atMode === "browse" ? parsed.dir : "";
11836
+ const browse = useBrowseListing(rootDir, atMode === "browse" ? browseDir : null);
11837
+ const search = useStreamingSearch(
11838
+ rootDir,
11839
+ atMode === "search" && parsed ? parsed.filter : null,
11840
+ recentFilesRef
11841
+ );
11842
+ const atState = useMemo8(() => {
11843
+ if (!parsed) return null;
11844
+ if (atMode === "browse") {
11845
+ return {
11846
+ kind: "browse",
11847
+ baseDir: browseDir,
11848
+ entries: browse.entries,
11849
+ loading: browse.loading
11850
+ };
11851
+ }
11852
+ return {
11853
+ kind: "search",
11854
+ filter: parsed.filter,
11855
+ entries: search.entries,
11856
+ scanned: search.scanned,
11857
+ searching: search.searching
11858
+ };
11859
+ }, [parsed, atMode, browseDir, browse, search]);
11646
11860
  useEffect9(() => {
11647
11861
  setAtSelected((prev) => {
11648
- if (!atMatches || atMatches.length === 0) return 0;
11649
- if (prev >= atMatches.length) return atMatches.length - 1;
11862
+ const len = atState?.entries.length ?? 0;
11863
+ if (len === 0) return 0;
11864
+ if (prev >= len) return len - 1;
11650
11865
  return prev;
11651
11866
  });
11652
- }, [atMatches]);
11867
+ }, [atState]);
11653
11868
  const pickAtMention = useCallback8(
11654
- (chosenPath) => {
11869
+ (entry, action) => {
11655
11870
  if (!atPicker) return;
11656
11871
  const before = input.slice(0, atPicker.atOffset);
11657
- setInput(`${before}@${chosenPath} `);
11872
+ const tail = action === "drill" && entry.isDir ? `${entry.insertPath}/` : `${entry.insertPath} `;
11873
+ setInput(`${before}@${tail}`);
11658
11874
  },
11659
11875
  [atPicker, input, setInput]
11660
11876
  );
@@ -11725,8 +11941,7 @@ function useCompletionPickers({
11725
11941
  setSlashSelected,
11726
11942
  slashGroupMode,
11727
11943
  slashAdvancedHidden,
11728
- atPicker,
11729
- atMatches,
11944
+ atState,
11730
11945
  atSelected,
11731
11946
  setAtSelected,
11732
11947
  pickAtMention,
@@ -11738,15 +11953,122 @@ function useCompletionPickers({
11738
11953
  pickSlashArg
11739
11954
  };
11740
11955
  }
11956
+ function useBrowseListing(rootDir, dir) {
11957
+ const [entries, setEntries] = useState16([]);
11958
+ const [loading, setLoading] = useState16(false);
11959
+ useEffect9(() => {
11960
+ if (dir === null) {
11961
+ setEntries([]);
11962
+ setLoading(false);
11963
+ return;
11964
+ }
11965
+ let cancelled = false;
11966
+ setLoading(true);
11967
+ listDirectory(rootDir, dir).then(
11968
+ (raw) => {
11969
+ if (cancelled) return;
11970
+ setEntries(raw.map(toBrowseEntry));
11971
+ setLoading(false);
11972
+ },
11973
+ () => {
11974
+ if (cancelled) return;
11975
+ setEntries([]);
11976
+ setLoading(false);
11977
+ }
11978
+ );
11979
+ return () => {
11980
+ cancelled = true;
11981
+ };
11982
+ }, [rootDir, dir]);
11983
+ return { entries, loading };
11984
+ }
11985
+ function toBrowseEntry(d) {
11986
+ return { label: d.name, insertPath: d.path, dirSuffix: "", isDir: d.isDir };
11987
+ }
11988
+ function useStreamingSearch(rootDir, filter, recentFilesRef) {
11989
+ const [, bumpRender] = useReducer2((x) => x + 1, 0);
11990
+ const hitsRef = useRef6([]);
11991
+ const scannedRef = useRef6(0);
11992
+ const searchingRef = useRef6(false);
11993
+ const rankedRef = useRef6([]);
11994
+ useEffect9(() => {
11995
+ if (filter === null) {
11996
+ hitsRef.current = [];
11997
+ scannedRef.current = 0;
11998
+ searchingRef.current = false;
11999
+ rankedRef.current = [];
12000
+ bumpRender();
12001
+ return;
12002
+ }
12003
+ hitsRef.current = [];
12004
+ scannedRef.current = 0;
12005
+ searchingRef.current = true;
12006
+ rankedRef.current = [];
12007
+ bumpRender();
12008
+ const ac = new AbortController();
12009
+ let flushTimer = null;
12010
+ const scheduleFlush = () => {
12011
+ if (flushTimer) return;
12012
+ flushTimer = setTimeout(() => {
12013
+ flushTimer = null;
12014
+ rankedRef.current = rankSearchHits(hitsRef.current, filter, recentFilesRef.current ?? []);
12015
+ bumpRender();
12016
+ }, SEARCH_FLUSH_MS);
12017
+ };
12018
+ const debounce = setTimeout(() => {
12019
+ walkFilesStream(rootDir, {
12020
+ signal: ac.signal,
12021
+ onEntry: (e) => {
12022
+ hitsRef.current.push(e);
12023
+ if (hitsRef.current.length >= SEARCH_RESULT_CAP * 8) return false;
12024
+ scheduleFlush();
12025
+ },
12026
+ onProgress: (n) => {
12027
+ scannedRef.current = n;
12028
+ scheduleFlush();
12029
+ }
12030
+ }).then(() => {
12031
+ searchingRef.current = false;
12032
+ rankedRef.current = rankSearchHits(hitsRef.current, filter, recentFilesRef.current ?? []);
12033
+ bumpRender();
12034
+ });
12035
+ }, SEARCH_DEBOUNCE_MS);
12036
+ return () => {
12037
+ clearTimeout(debounce);
12038
+ if (flushTimer) clearTimeout(flushTimer);
12039
+ ac.abort();
12040
+ };
12041
+ }, [rootDir, filter, recentFilesRef]);
12042
+ return {
12043
+ entries: rankedRef.current,
12044
+ scanned: scannedRef.current,
12045
+ searching: searchingRef.current
12046
+ };
12047
+ }
12048
+ function rankSearchHits(hits, filter, recent) {
12049
+ const ranked = rankPickerCandidates(hits, filter, {
12050
+ limit: SEARCH_RESULT_CAP,
12051
+ recentlyUsed: recent
12052
+ });
12053
+ return ranked.map((path) => {
12054
+ const slash = path.lastIndexOf("/");
12055
+ return {
12056
+ label: slash >= 0 ? path.slice(slash + 1) : path,
12057
+ insertPath: path,
12058
+ dirSuffix: slash >= 0 ? `${path.slice(0, slash)}/` : "",
12059
+ isDir: false
12060
+ };
12061
+ });
12062
+ }
11741
12063
 
11742
12064
  // src/cli/ui/useEditHistory.ts
11743
- import { useCallback as useCallback9, useRef as useRef6, useState as useState17 } from "react";
12065
+ import { useCallback as useCallback9, useRef as useRef7, useState as useState17 } from "react";
11744
12066
  function useEditHistory(codeMode) {
11745
- const editHistory = useRef6([]);
11746
- const nextHistoryId = useRef6(1);
11747
- const currentTurnEntry = useRef6(null);
12067
+ const editHistory = useRef7([]);
12068
+ const nextHistoryId = useRef7(1);
12069
+ const currentTurnEntry = useRef7(null);
11748
12070
  const [undoBanner, setUndoBanner] = useState17(null);
11749
- const undoTimeoutRef = useRef6(null);
12071
+ const undoTimeoutRef = useRef7(null);
11750
12072
  const recordEdit = useCallback9(
11751
12073
  (source, blocks, results, snaps) => {
11752
12074
  if (snaps.length === 0) return;
@@ -12043,7 +12365,7 @@ function useSessionInfo(loop2) {
12043
12365
  }
12044
12366
 
12045
12367
  // src/cli/ui/useSubagent.ts
12046
- import { useEffect as useEffect11, useRef as useRef7, useState as useState19 } from "react";
12368
+ import { useEffect as useEffect11, useRef as useRef8, useState as useState19 } from "react";
12047
12369
  function summariseInner(ev) {
12048
12370
  if (ev.role === "tool_start") {
12049
12371
  return {
@@ -12075,8 +12397,8 @@ function useSubagent({
12075
12397
  getWalletCurrency
12076
12398
  }) {
12077
12399
  const [activities, setActivities] = useState19([]);
12078
- const sinkRef = useRef7({ current: null });
12079
- const getWalletCurrencyRef = useRef7(getWalletCurrency);
12400
+ const sinkRef = useRef8({ current: null });
12401
+ const getWalletCurrencyRef = useRef8(getWalletCurrency);
12080
12402
  useEffect11(() => {
12081
12403
  getWalletCurrencyRef.current = getWalletCurrency;
12082
12404
  }, [getWalletCurrency]);
@@ -12162,13 +12484,13 @@ var PLAIN_UI = process.env.REASONIX_UI === "plain";
12162
12484
  function LoopStatusRow({
12163
12485
  loop: loop2
12164
12486
  }) {
12165
- const [, setTick] = React59.useState(0);
12166
- React59.useEffect(() => {
12487
+ const [, setTick] = React60.useState(0);
12488
+ React60.useEffect(() => {
12167
12489
  const id = setInterval(() => setTick((t2) => t2 + 1), 1e3);
12168
12490
  return () => clearInterval(id);
12169
12491
  }, []);
12170
12492
  const nextFireMs = Math.max(0, loop2.nextFireAt - Date.now());
12171
- return /* @__PURE__ */ React59.createElement(Box48, null, /* @__PURE__ */ React59.createElement(Text51, { color: "cyan" }, `\u25B8 ${formatLoopStatus(loop2.prompt, nextFireMs, loop2.iter)} \xB7 /loop stop or type to cancel`));
12493
+ return /* @__PURE__ */ React60.createElement(Box49, null, /* @__PURE__ */ React60.createElement(Text52, { color: "cyan" }, `\u25B8 ${formatLoopStatus(loop2.prompt, nextFireMs, loop2.iter)} \xB7 /loop stop or type to cancel`));
12172
12494
  }
12173
12495
  function App(props) {
12174
12496
  markPhase("app_render_start");
@@ -12177,11 +12499,12 @@ function App(props) {
12177
12499
  model: props.model,
12178
12500
  workspace: props.codeMode?.rootDir ?? process.cwd()
12179
12501
  });
12180
- const initialCards = React59.useMemo(
12502
+ const initialCards = React60.useMemo(
12181
12503
  () => props.session ? hydrateCardsFromMessages(loadSessionMessages(props.session)) : [],
12182
12504
  [props.session]
12183
12505
  );
12184
- return /* @__PURE__ */ React59.createElement(AgentStoreProvider, { session, initialCards }, /* @__PURE__ */ React59.createElement(AppInner, { ...props }));
12506
+ const themeName = resolveThemePreference(loadTheme(), process.env.REASONIX_THEME);
12507
+ return /* @__PURE__ */ React60.createElement(ThemeProvider, { name: themeName }, /* @__PURE__ */ React60.createElement(AgentStoreProvider, { session, initialCards }, /* @__PURE__ */ React60.createElement(AppInner, { ...props })));
12185
12508
  }
12186
12509
  function AppInner({
12187
12510
  model: model2,
@@ -12222,7 +12545,7 @@ function AppInner({
12222
12545
  dumpStartupProfile();
12223
12546
  }, []);
12224
12547
  const [liveMcpServers, setLiveMcpServers] = useState20(() => mcpServers ?? []);
12225
- const abortedThisTurn = useRef8(false);
12548
+ const abortedThisTurn = useRef9(false);
12226
12549
  useEffect12(() => {
12227
12550
  busyRef.current = busy;
12228
12551
  }, [busy]);
@@ -12233,12 +12556,14 @@ function AppInner({
12233
12556
  if (!stdout || !stdout.isTTY) return;
12234
12557
  stdout.write("\x1B[?2004h");
12235
12558
  stdout.write("\x1B[>4;2m");
12559
+ stdout.write("\x1B[?1006h\x1B[?1000h");
12236
12560
  return () => {
12561
+ stdout.write("\x1B[?1000l\x1B[?1006l");
12237
12562
  stdout.write("\x1B[?2004l");
12238
12563
  stdout.write("\x1B[>4m");
12239
12564
  };
12240
12565
  }, [stdout]);
12241
- const walletCurrencyRef = useRef8(void 0);
12566
+ const walletCurrencyRef = useRef9(void 0);
12242
12567
  const { activities: subagentActivities, sinkRef: subagentSinkRef } = useSubagent({
12243
12568
  session,
12244
12569
  log,
@@ -12263,7 +12588,7 @@ function AppInner({
12263
12588
  hasUndoable,
12264
12589
  touchedPaths
12265
12590
  } = useEditHistory(codeMode);
12266
- const pendingEdits = useRef8([]);
12591
+ const pendingEdits = useRef9([]);
12267
12592
  const [pendingCount, setPendingCount] = useState20(0);
12268
12593
  const syncPendingCount = useCallback11(() => {
12269
12594
  setPendingCount(pendingEdits.current.length);
@@ -12274,22 +12599,22 @@ function AppInner({
12274
12599
  if (model2 === "deepseek-v4-pro") return "pro";
12275
12600
  return "auto";
12276
12601
  });
12277
- const editModeRef = useRef8(editMode);
12602
+ const editModeRef = useRef9(editMode);
12278
12603
  useEffect12(() => {
12279
12604
  editModeRef.current = editMode;
12280
12605
  if (codeMode) saveEditMode(editMode);
12281
12606
  }, [editMode, codeMode]);
12282
- const planModeRef = useRef8(false);
12283
- const currentRootDirRef = useRef8("");
12284
- const latestVersionRef = useRef8(null);
12607
+ const planModeRef = useRef9(false);
12608
+ const currentRootDirRef = useRef9("");
12609
+ const latestVersionRef = useRef9(null);
12285
12610
  const [pendingEditReview, setPendingEditReview] = useState20(null);
12286
12611
  const [walkthroughActive, setWalkthroughActive] = useState20(false);
12287
12612
  const [pendingTick, setPendingTick] = useState20(0);
12288
- const editReviewResolveRef = useRef8(null);
12289
- const turnEditPolicyRef = useRef8("ask");
12613
+ const editReviewResolveRef = useRef9(null);
12614
+ const turnEditPolicyRef = useRef9("ask");
12290
12615
  const [modeFlash, setModeFlash] = useState20(false);
12291
- const modeFlashTimeoutRef = useRef8(null);
12292
- const prevEditModeRef = useRef8(editMode);
12616
+ const modeFlashTimeoutRef = useRef9(null);
12617
+ const prevEditModeRef = useRef9(editMode);
12293
12618
  useEffect12(() => {
12294
12619
  if (prevEditModeRef.current === editMode) return;
12295
12620
  prevEditModeRef.current = editMode;
@@ -12321,23 +12646,23 @@ function AppInner({
12321
12646
  const [turnOnPro, setTurnOnPro] = useState20(false);
12322
12647
  const [queuedSubmit, setQueuedSubmit] = useState20(null);
12323
12648
  const { recallPrev, recallNext, pushHistory, resetCursor } = useInputRecall(setInput);
12324
- const assistantIterCounter = useRef8(0);
12325
- const atUrlCache = useRef8(/* @__PURE__ */ new Map());
12326
- const handleSubmitRef = useRef8(null);
12327
- const busyRef = useRef8(false);
12328
- const dashboardRef = useRef8(null);
12329
- const dashboardStartingRef = useRef8(null);
12330
- const eventSubscribersRef = useRef8(/* @__PURE__ */ new Set());
12331
- const activePickerResolverRef = useRef8(null);
12332
- const activePickerSnapshotRef = useRef8(null);
12333
- const activeViewerResolverRef = useRef8(null);
12334
- const activeViewerSnapshotRef = useRef8(null);
12649
+ const assistantIterCounter = useRef9(0);
12650
+ const atUrlCache = useRef9(/* @__PURE__ */ new Map());
12651
+ const handleSubmitRef = useRef9(null);
12652
+ const busyRef = useRef9(false);
12653
+ const dashboardRef = useRef9(null);
12654
+ const dashboardStartingRef = useRef9(null);
12655
+ const eventSubscribersRef = useRef9(/* @__PURE__ */ new Set());
12656
+ const activePickerResolverRef = useRef9(null);
12657
+ const activePickerSnapshotRef = useRef9(null);
12658
+ const activeViewerResolverRef = useRef9(null);
12659
+ const activeViewerSnapshotRef = useRef9(null);
12335
12660
  const [pendingReplayViewer, setPendingReplayViewer] = useState20(null);
12336
- const planStepsRef = useRef8(null);
12337
- const completedStepIdsRef = useRef8(/* @__PURE__ */ new Set());
12338
- const planBodyRef = useRef8(null);
12339
- const planSummaryRef = useRef8(null);
12340
- const toolStartedAtRef = useRef8(null);
12661
+ const planStepsRef = useRef9(null);
12662
+ const completedStepIdsRef = useRef9(/* @__PURE__ */ new Set());
12663
+ const planBodyRef = useRef9(null);
12664
+ const planSummaryRef = useRef9(null);
12665
+ const toolStartedAtRef = useRef9(null);
12341
12666
  const persistPlanState = useCallback11(() => {
12342
12667
  if (!session) return;
12343
12668
  const steps = planStepsRef.current;
@@ -12361,7 +12686,7 @@ function AppInner({
12361
12686
  lastPromptTokens: 0,
12362
12687
  lastTurnCostUsd: 0
12363
12688
  });
12364
- const transcriptRef = useRef8(null);
12689
+ const transcriptRef = useRef9(null);
12365
12690
  if (transcript && !transcriptRef.current) {
12366
12691
  transcriptRef.current = openTranscriptFile(transcript, {
12367
12692
  version: 1,
@@ -12370,8 +12695,8 @@ function AppInner({
12370
12695
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
12371
12696
  });
12372
12697
  }
12373
- const eventSinkRef = useRef8(null);
12374
- const eventizerRef = useRef8(null);
12698
+ const eventSinkRef = useRef9(null);
12699
+ const eventizerRef = useRef9(null);
12375
12700
  if (session && !eventSinkRef.current) {
12376
12701
  eventSinkRef.current = openEventSink(eventLogPath(session));
12377
12702
  eventizerRef.current = new Eventizer();
@@ -12383,7 +12708,7 @@ function AppInner({
12383
12708
  void eventSinkRef.current?.close();
12384
12709
  };
12385
12710
  }, []);
12386
- const loopRef = useRef8(null);
12711
+ const loopRef = useRef9(null);
12387
12712
  const loop2 = useMemo9(() => {
12388
12713
  if (loopRef.current) return loopRef.current;
12389
12714
  const client = new DeepSeekClient();
@@ -12489,8 +12814,8 @@ function AppInner({
12489
12814
  useEffect12(() => {
12490
12815
  latestVersionRef.current = latestVersion ?? null;
12491
12816
  }, [latestVersion]);
12492
- const balanceRef = useRef8(null);
12493
- const modelsRef = useRef8(null);
12817
+ const balanceRef = useRef9(null);
12818
+ const modelsRef = useRef9(null);
12494
12819
  useEffect12(() => {
12495
12820
  modelsRef.current = models;
12496
12821
  }, [models]);
@@ -12621,8 +12946,7 @@ function AppInner({
12621
12946
  setSlashSelected,
12622
12947
  slashGroupMode,
12623
12948
  slashAdvancedHidden,
12624
- atPicker,
12625
- atMatches,
12949
+ atState,
12626
12950
  atSelected,
12627
12951
  setAtSelected,
12628
12952
  pickAtMention,
@@ -12654,7 +12978,7 @@ function AppInner({
12654
12978
  if (progressSink.current) progressSink.current = null;
12655
12979
  };
12656
12980
  }, [progressSink]);
12657
- const sessionBannerShown = useRef8(false);
12981
+ const sessionBannerShown = useRef9(false);
12658
12982
  useEffect12(() => {
12659
12983
  if (sessionBannerShown.current) return;
12660
12984
  sessionBannerShown.current = true;
@@ -12695,14 +13019,20 @@ function AppInner({
12695
13019
  }
12696
13020
  }
12697
13021
  if (codeMode && !editModeHintShown()) {
12698
- log.pushInfo(t("ui.tipEditBindings"));
13022
+ const tip = tObj("ui.tipEditBindings");
13023
+ log.pushTip({ topic: tip.topic, sections: tip.sections, footer: tip.footer });
12699
13024
  markEditModeHintShown();
12700
13025
  }
13026
+ if (!mouseClipboardHintShown()) {
13027
+ const tip = tObj("ui.tipMouseClipboard");
13028
+ log.pushTip({ topic: tip.topic, sections: tip.sections, footer: tip.footer });
13029
+ markMouseClipboardHintShown();
13030
+ }
12701
13031
  }, [session, loop2, codeMode, syncPendingCount, log]);
12702
13032
  const quitProcess = useQuit(transcriptRef);
12703
13033
  useKeystroke((ev) => {
12704
- if (ev.pageUp) chatScroll.scrollUp();
12705
- else if (ev.pageDown) chatScroll.scrollDown();
13034
+ if (ev.pageUp || ev.mouseScrollUp) chatScroll.scrollUp();
13035
+ else if (ev.pageDown || ev.mouseScrollDown) chatScroll.scrollDown();
12706
13036
  else if (ev.end) chatScroll.jumpToBottom();
12707
13037
  else if ((!chatScroll.pinned || busy) && ev.upArrow) chatScroll.scrollUp();
12708
13038
  else if ((!chatScroll.pinned || busy) && ev.downArrow) chatScroll.scrollDown();
@@ -12734,7 +13064,7 @@ function AppInner({
12734
13064
  stopLoop();
12735
13065
  return;
12736
13066
  }
12737
- if (key.escape && !busy && (slashMatches || atMatches || slashArgContext)) {
13067
+ if (key.escape && !busy && (slashMatches || atState || slashArgContext)) {
12738
13068
  setInput("");
12739
13069
  return;
12740
13070
  }
@@ -12772,18 +13102,19 @@ function AppInner({
12772
13102
  }
12773
13103
  if (busy) return;
12774
13104
  if (pendingShell) return;
12775
- if (atMatches && atMatches.length > 0) {
13105
+ if (atState && atState.entries.length > 0) {
13106
+ const entries = atState.entries;
12776
13107
  if (key.upArrow) {
12777
13108
  setAtSelected((i) => Math.max(0, i - 1));
12778
13109
  return;
12779
13110
  }
12780
13111
  if (key.downArrow) {
12781
- setAtSelected((i) => Math.min(atMatches.length - 1, i + 1));
13112
+ setAtSelected((i) => Math.min(entries.length - 1, i + 1));
12782
13113
  return;
12783
13114
  }
12784
13115
  if (key.tab) {
12785
- const sel = atMatches[atSelected] ?? atMatches[0];
12786
- if (sel) pickAtMention(sel);
13116
+ const sel = entries[atSelected] ?? entries[0];
13117
+ if (sel) pickAtMention(sel, sel.isDir ? "drill" : "commit");
12787
13118
  return;
12788
13119
  }
12789
13120
  }
@@ -12919,7 +13250,7 @@ function AppInner({
12919
13250
  if (dashboardRef.current) return dashboardRef.current.url;
12920
13251
  if (dashboardStartingRef.current) return dashboardStartingRef.current;
12921
13252
  const startup = (async () => {
12922
- const { startDashboardServer } = await import("./server-SYC3OVOP.js");
13253
+ const { startDashboardServer } = await import("./server-MC4A4WAJ.js");
12923
13254
  const handle = await startDashboardServer({
12924
13255
  mode: "attached",
12925
13256
  configPath: defaultConfigPath(),
@@ -13227,10 +13558,10 @@ function AppInner({
13227
13558
  }
13228
13559
  clearFiringFlag();
13229
13560
  if (busy) return;
13230
- if (atMatches && atMatches.length > 0 && atPicker) {
13231
- const sel = atMatches[atSelected] ?? atMatches[0];
13561
+ if (atState && atState.entries.length > 0) {
13562
+ const sel = atState.entries[atSelected] ?? atState.entries[0];
13232
13563
  if (sel) {
13233
- pickAtMention(sel);
13564
+ pickAtMention(sel, "commit");
13234
13565
  return;
13235
13566
  }
13236
13567
  }
@@ -13358,6 +13689,12 @@ function AppInner({
13358
13689
  postInfo: (text2) => log.pushInfo(text2),
13359
13690
  postDoctor: (checks) => log.showDoctor(checks),
13360
13691
  postUsage: (args) => log.showUsageVerbose(args),
13692
+ postKeys: (args) => log.pushTip({
13693
+ topic: args.topic,
13694
+ sections: args.sections,
13695
+ footer: args.footer,
13696
+ oneTime: false
13697
+ }),
13361
13698
  dispatch: agentStore.dispatch,
13362
13699
  reloadHooks: () => {
13363
13700
  const fresh = loadHooks({ projectRoot: codeMode ? currentRootDir : void 0 });
@@ -13730,8 +14067,7 @@ function AppInner({
13730
14067
  planMode,
13731
14068
  session,
13732
14069
  slashSelected,
13733
- atMatches,
13734
- atPicker,
14070
+ atState,
13735
14071
  atSelected,
13736
14072
  pickAtMention,
13737
14073
  recordRecentFile,
@@ -13799,7 +14135,7 @@ function AppInner({
13799
14135
  },
13800
14136
  [pendingShell, codeMode, currentRootDir, log]
13801
14137
  );
13802
- const pendingGateIdRef = useRef8(null);
14138
+ const pendingGateIdRef = useRef9(null);
13803
14139
  useEffect12(() => {
13804
14140
  if (!busy && queuedSubmit !== null) {
13805
14141
  const text = queuedSubmit;
@@ -13836,7 +14172,7 @@ function AppInner({
13836
14172
  },
13837
14173
  [pendingPlan]
13838
14174
  );
13839
- const handlePlanConfirmRef = useRef8(handlePlanConfirm);
14175
+ const handlePlanConfirmRef = useRef9(handlePlanConfirm);
13840
14176
  useEffect12(() => {
13841
14177
  handlePlanConfirmRef.current = handlePlanConfirm;
13842
14178
  }, [handlePlanConfirm]);
@@ -13930,7 +14266,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
13930
14266
  },
13931
14267
  [stagedInput, togglePlanMode, persistPlanState, agentStore, log]
13932
14268
  );
13933
- const handleStagedInputSubmitRef = useRef8(handleStagedInputSubmit);
14269
+ const handleStagedInputSubmitRef = useRef9(handleStagedInputSubmit);
13934
14270
  useEffect12(() => {
13935
14271
  handleStagedInputSubmitRef.current = handleStagedInputSubmit;
13936
14272
  }, [handleStagedInputSubmit]);
@@ -13959,7 +14295,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
13959
14295
  },
13960
14296
  [pendingChoice]
13961
14297
  );
13962
- const handleShellConfirmRef = useRef8(handleShellConfirm);
14298
+ const handleShellConfirmRef = useRef9(handleShellConfirm);
13963
14299
  useEffect12(() => {
13964
14300
  handleShellConfirmRef.current = handleShellConfirm;
13965
14301
  }, [handleShellConfirm]);
@@ -14022,11 +14358,11 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14022
14358
  }
14023
14359
  });
14024
14360
  }, []);
14025
- const pendingPlanRef = useRef8(null);
14361
+ const pendingPlanRef = useRef9(null);
14026
14362
  useEffect12(() => {
14027
14363
  pendingPlanRef.current = pendingPlan;
14028
14364
  }, [pendingPlan]);
14029
- const handleChoiceConfirmRef = useRef8(handleChoiceConfirm);
14365
+ const handleChoiceConfirmRef = useRef9(handleChoiceConfirm);
14030
14366
  useEffect12(() => {
14031
14367
  handleChoiceConfirmRef.current = handleChoiceConfirm;
14032
14368
  }, [handleChoiceConfirm]);
@@ -14079,7 +14415,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14079
14415
  },
14080
14416
  [pendingCheckpoint, codeMode, touchedPaths, log]
14081
14417
  );
14082
- const handleCheckpointConfirmRef = useRef8(handleCheckpointConfirm);
14418
+ const handleCheckpointConfirmRef = useRef9(handleCheckpointConfirm);
14083
14419
  useEffect12(() => {
14084
14420
  handleCheckpointConfirmRef.current = handleCheckpointConfirm;
14085
14421
  }, [handleCheckpointConfirm]);
@@ -14108,7 +14444,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14108
14444
  },
14109
14445
  [codeMode, touchedPaths, log]
14110
14446
  );
14111
- const handleAutoCheckpointContinueRef = useRef8(handleAutoCheckpointContinue);
14447
+ const handleAutoCheckpointContinueRef = useRef9(handleAutoCheckpointContinue);
14112
14448
  useEffect12(() => {
14113
14449
  handleAutoCheckpointContinueRef.current = handleAutoCheckpointContinue;
14114
14450
  }, [handleAutoCheckpointContinue]);
@@ -14143,7 +14479,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14143
14479
  setStagedCheckpointRevise(null);
14144
14480
  if (snap) setPendingCheckpoint(snap);
14145
14481
  }, [stagedCheckpointRevise]);
14146
- const handleCheckpointReviseSubmitRef = useRef8(handleCheckpointReviseSubmit);
14482
+ const handleCheckpointReviseSubmitRef = useRef9(handleCheckpointReviseSubmit);
14147
14483
  useEffect12(() => {
14148
14484
  handleCheckpointReviseSubmitRef.current = handleCheckpointReviseSubmit;
14149
14485
  }, [handleCheckpointReviseSubmit]);
@@ -14194,7 +14530,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14194
14530
  },
14195
14531
  [pendingRevision, persistPlanState, agentStore, log]
14196
14532
  );
14197
- const handleReviseConfirmRef = useRef8(handleReviseConfirm);
14533
+ const handleReviseConfirmRef = useRef9(handleReviseConfirm);
14198
14534
  useEffect12(() => {
14199
14535
  handleReviseConfirmRef.current = handleReviseConfirm;
14200
14536
  }, [handleReviseConfirm]);
@@ -14203,14 +14539,14 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14203
14539
  []
14204
14540
  );
14205
14541
  const tickerSuspended = PLAIN_UI || modalOpen || !busy && !isStreaming;
14206
- return /* @__PURE__ */ React59.createElement(React59.Fragment, null, /* @__PURE__ */ React59.createElement(TickerProvider, { disabled: tickerSuspended }, /* @__PURE__ */ React59.createElement(ViewportBudgetProvider, null, /* @__PURE__ */ React59.createElement(Box48, { flexDirection: "row", height: stdout?.rows ?? 24 }, /* @__PURE__ */ React59.createElement(Box48, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React59.createElement(Box48, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React59.createElement(LiveExpandContext.Provider, { value: liveExpand }, /* @__PURE__ */ React59.createElement(
14542
+ return /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(TickerProvider, { disabled: tickerSuspended }, /* @__PURE__ */ React60.createElement(ViewportBudgetProvider, null, /* @__PURE__ */ React60.createElement(Box49, { flexDirection: "row", height: stdout?.rows ?? 24 }, /* @__PURE__ */ React60.createElement(Box49, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React60.createElement(Box49, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React60.createElement(LiveExpandContext.Provider, { value: liveExpand }, /* @__PURE__ */ React60.createElement(
14207
14543
  CardStream,
14208
14544
  {
14209
14545
  suppressLive: modalOpen,
14210
14546
  scrollRows: chatScroll.scrollRows,
14211
14547
  onMaxScrollChange: chatScroll.setMaxScroll
14212
14548
  }
14213
- )), !hasConversation && !busy && !isStreaming ? /* @__PURE__ */ React59.createElement(
14549
+ )), !hasConversation && !busy && !isStreaming ? /* @__PURE__ */ React60.createElement(
14214
14550
  WelcomeBanner,
14215
14551
  {
14216
14552
  inCodeMode: !!codeMode,
@@ -14218,28 +14554,28 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14218
14554
  dashboardUrl,
14219
14555
  languageVersion
14220
14556
  }
14221
- ) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && ongoingTool ? /* @__PURE__ */ React59.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && subagentActivities.length > 0 ? /* @__PURE__ */ React59.createElement(SubagentLiveStack, { activities: subagentActivities, max: 3 }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && !ongoingTool && statusLine ? /* @__PURE__ */ React59.createElement(ThinkingRow, { text: statusLine }) : null, !PLAIN_UI && undoBanner && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && !pendingChoice && !stagedChoiceCustom && !pendingRevision && !stagedCheckpointRevise && !pendingCheckpoint ? /* @__PURE__ */ React59.createElement(UndoBanner, { banner: undoBanner }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && busy && !isStreaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React59.createElement(ThinkingRow, { text: "processing\u2026" }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview ? /* @__PURE__ */ React59.createElement(PlanLiveRow, null) : null, /* @__PURE__ */ React59.createElement(ToastRail, null)), stagedInput ? /* @__PURE__ */ React59.createElement(
14557
+ ) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && ongoingTool ? /* @__PURE__ */ React60.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && subagentActivities.length > 0 ? /* @__PURE__ */ React60.createElement(SubagentLiveStack, { activities: subagentActivities, max: 3 }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && !ongoingTool && statusLine ? /* @__PURE__ */ React60.createElement(ThinkingRow, { text: statusLine }) : null, !PLAIN_UI && undoBanner && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && !pendingChoice && !stagedChoiceCustom && !pendingRevision && !stagedCheckpointRevise && !pendingCheckpoint ? /* @__PURE__ */ React60.createElement(UndoBanner, { banner: undoBanner }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && busy && !isStreaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React60.createElement(ThinkingRow, { text: "processing\u2026" }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview ? /* @__PURE__ */ React60.createElement(PlanLiveRow, null) : null, /* @__PURE__ */ React60.createElement(ToastRail, null)), stagedInput ? /* @__PURE__ */ React60.createElement(
14222
14558
  PlanRefineInput,
14223
14559
  {
14224
14560
  mode: stagedInput.mode,
14225
14561
  onSubmit: handleStagedInputSubmit,
14226
14562
  onCancel: handleStagedInputCancel
14227
14563
  }
14228
- ) : stagedChoiceCustom ? /* @__PURE__ */ React59.createElement(
14564
+ ) : stagedChoiceCustom ? /* @__PURE__ */ React60.createElement(
14229
14565
  PlanRefineInput,
14230
14566
  {
14231
14567
  mode: "choice-custom",
14232
14568
  onSubmit: handleChoiceCustomSubmit,
14233
14569
  onCancel: handleChoiceCustomCancel
14234
14570
  }
14235
- ) : stagedCheckpointRevise ? /* @__PURE__ */ React59.createElement(
14571
+ ) : stagedCheckpointRevise ? /* @__PURE__ */ React60.createElement(
14236
14572
  PlanRefineInput,
14237
14573
  {
14238
14574
  mode: "checkpoint-revise",
14239
14575
  onSubmit: (text) => handleCheckpointReviseSubmit(text, stagedCheckpointRevise),
14240
14576
  onCancel: handleCheckpointReviseCancel
14241
14577
  }
14242
- ) : pendingChoice ? /* @__PURE__ */ React59.createElement(
14578
+ ) : pendingChoice ? /* @__PURE__ */ React60.createElement(
14243
14579
  ChoiceConfirm,
14244
14580
  {
14245
14581
  question: pendingChoice.question,
@@ -14247,7 +14583,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14247
14583
  allowCustom: pendingChoice.allowCustom,
14248
14584
  onChoose: stableHandleChoiceConfirm
14249
14585
  }
14250
- ) : pendingRevision ? /* @__PURE__ */ React59.createElement(
14586
+ ) : pendingRevision ? /* @__PURE__ */ React60.createElement(
14251
14587
  PlanReviseConfirm,
14252
14588
  {
14253
14589
  reason: pendingRevision.reason,
@@ -14258,7 +14594,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14258
14594
  summary: pendingRevision.summary,
14259
14595
  onChoose: stableHandleReviseConfirm
14260
14596
  }
14261
- ) : pendingCheckpoint ? /* @__PURE__ */ React59.createElement(
14597
+ ) : pendingCheckpoint ? /* @__PURE__ */ React60.createElement(
14262
14598
  PlanCheckpointConfirm,
14263
14599
  {
14264
14600
  stepId: pendingCheckpoint.stepId,
@@ -14269,7 +14605,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14269
14605
  completedStepIds: completedStepIdsRef.current,
14270
14606
  onChoose: stableHandleCheckpointConfirm
14271
14607
  }
14272
- ) : pendingCheckpointPicker ? /* @__PURE__ */ React59.createElement(
14608
+ ) : pendingCheckpointPicker ? /* @__PURE__ */ React60.createElement(
14273
14609
  CheckpointPicker,
14274
14610
  {
14275
14611
  checkpoints: checkpointPickerList,
@@ -14314,7 +14650,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14314
14650
  }
14315
14651
  }
14316
14652
  }
14317
- ) : pendingSessionsPicker ? /* @__PURE__ */ React59.createElement(
14653
+ ) : pendingSessionsPicker ? /* @__PURE__ */ React60.createElement(
14318
14654
  SessionPicker,
14319
14655
  {
14320
14656
  sessions: sessionsPickerList,
@@ -14359,7 +14695,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14359
14695
  }
14360
14696
  }
14361
14697
  }
14362
- ) : pendingModelPicker ? /* @__PURE__ */ React59.createElement(
14698
+ ) : pendingModelPicker ? /* @__PURE__ */ React60.createElement(
14363
14699
  ModelPicker,
14364
14700
  {
14365
14701
  models,
@@ -14391,7 +14727,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14391
14727
  }
14392
14728
  }
14393
14729
  }
14394
- ) : pendingMcpHub ? /* @__PURE__ */ React59.createElement(
14730
+ ) : pendingMcpHub ? /* @__PURE__ */ React60.createElement(
14395
14731
  McpHub,
14396
14732
  {
14397
14733
  initialTab: pendingMcpHub.tab,
@@ -14411,7 +14747,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14411
14747
  return r;
14412
14748
  } : void 0
14413
14749
  }
14414
- ) : pendingPlan ? /* @__PURE__ */ React59.createElement(
14750
+ ) : pendingPlan ? /* @__PURE__ */ React60.createElement(
14415
14751
  PlanConfirm,
14416
14752
  {
14417
14753
  plan: pendingPlan,
@@ -14420,7 +14756,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14420
14756
  onChoose: stableHandlePlanConfirm,
14421
14757
  projectRoot: currentRootDir
14422
14758
  }
14423
- ) : pendingReviseEditor ? /* @__PURE__ */ React59.createElement(
14759
+ ) : pendingReviseEditor ? /* @__PURE__ */ React60.createElement(
14424
14760
  PlanReviseEditor,
14425
14761
  {
14426
14762
  steps: planStepsRef.current ?? [],
@@ -14439,7 +14775,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14439
14775
  setPendingPlan(planText);
14440
14776
  }
14441
14777
  }
14442
- ) : pendingShell ? /* @__PURE__ */ React59.createElement(
14778
+ ) : pendingShell ? /* @__PURE__ */ React60.createElement(
14443
14779
  ShellConfirm,
14444
14780
  {
14445
14781
  command: pendingShell.command,
@@ -14447,7 +14783,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14447
14783
  kind: pendingShell.kind,
14448
14784
  onChoose: handleShellConfirm
14449
14785
  }
14450
- ) : pendingEditReview ? /* @__PURE__ */ React59.createElement(
14786
+ ) : pendingEditReview ? /* @__PURE__ */ React60.createElement(
14451
14787
  EditConfirm,
14452
14788
  {
14453
14789
  block: pendingEditReview,
@@ -14459,14 +14795,14 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14459
14795
  }
14460
14796
  }
14461
14797
  }
14462
- ) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */ React59.createElement(
14798
+ ) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */ React60.createElement(
14463
14799
  EditConfirm,
14464
14800
  {
14465
14801
  key: `walk-${pendingTick}`,
14466
14802
  block: pendingEdits.current[0],
14467
14803
  onChoose: handleWalkChoice
14468
14804
  }
14469
- ) : !chatScroll.pinned ? /* @__PURE__ */ React59.createElement(Text51, { color: FG.faint }, " \u{1F4D6} reading history \u2014 End / PgDn to return \xB7 \u2193 to advance one line") : /* @__PURE__ */ React59.createElement(React59.Fragment, null, codeMode ? /* @__PURE__ */ React59.createElement(
14805
+ ) : !chatScroll.pinned ? /* @__PURE__ */ React60.createElement(Text52, { color: FG.faint }, " \u{1F4D6} reading history \u2014 End / PgDn to return \xB7 \u2193 to advance one line") : /* @__PURE__ */ React60.createElement(React60.Fragment, null, codeMode ? /* @__PURE__ */ React60.createElement(
14470
14806
  ModeStatusBar,
14471
14807
  {
14472
14808
  editMode,
@@ -14476,7 +14812,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14476
14812
  undoArmed: !!undoBanner || hasUndoable(),
14477
14813
  jobs: codeMode.jobs
14478
14814
  }
14479
- ) : null, activeLoop ? /* @__PURE__ */ React59.createElement(LoopStatusRow, { loop: activeLoop }) : null, /* @__PURE__ */ React59.createElement(StatusRow, null), /* @__PURE__ */ React59.createElement(
14815
+ ) : null, activeLoop ? /* @__PURE__ */ React60.createElement(LoopStatusRow, { loop: activeLoop }) : null, /* @__PURE__ */ React60.createElement(StatusRow, null), /* @__PURE__ */ React60.createElement(
14480
14816
  PromptInput,
14481
14817
  {
14482
14818
  value: input,
@@ -14486,7 +14822,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14486
14822
  onHistoryPrev: recallPrev,
14487
14823
  onHistoryNext: recallNext
14488
14824
  }
14489
- ), slashMatches !== null ? /* @__PURE__ */ React59.createElement(
14825
+ ), slashMatches !== null ? /* @__PURE__ */ React60.createElement(
14490
14826
  SlashSuggestions,
14491
14827
  {
14492
14828
  matches: slashMatches,
@@ -14494,14 +14830,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14494
14830
  groupMode: slashGroupMode,
14495
14831
  advancedHidden: slashAdvancedHidden
14496
14832
  }
14497
- ) : null, atMatches !== null ? /* @__PURE__ */ React59.createElement(
14498
- AtMentionSuggestions,
14499
- {
14500
- matches: atMatches,
14501
- selectedIndex: atSelected,
14502
- query: atPicker?.query ?? ""
14503
- }
14504
- ) : null, slashArgContext ? /* @__PURE__ */ React59.createElement(
14833
+ ) : null, atState !== null ? /* @__PURE__ */ React60.createElement(AtMentionSuggestions, { state: atState, selectedIndex: atSelected }) : null, slashArgContext ? /* @__PURE__ */ React60.createElement(
14505
14834
  SlashArgPicker,
14506
14835
  {
14507
14836
  matches: slashArgMatches,
@@ -14514,12 +14843,12 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14514
14843
  }
14515
14844
 
14516
14845
  // src/cli/ui/Setup.tsx
14517
- import { Box as Box49, Text as Text53, useApp } from "ink";
14518
- import React61, { useState as useState21 } from "react";
14846
+ import { Box as Box50, Text as Text54, useApp } from "ink";
14847
+ import React62, { useState as useState21 } from "react";
14519
14848
 
14520
14849
  // src/cli/ui/MaskedInput.tsx
14521
- import { Text as Text52, useInput } from "ink";
14522
- import React60, { useRef as useRef9 } from "react";
14850
+ import { Text as Text53, useInput } from "ink";
14851
+ import React61, { useRef as useRef10 } from "react";
14523
14852
  function stripPasteMarkers(s) {
14524
14853
  return s.replace(/\u001b?\[20[01]~/g, "").replace(/\u001b/g, "");
14525
14854
  }
@@ -14530,7 +14859,7 @@ function MaskedInput({
14530
14859
  mask = "\u2022",
14531
14860
  placeholder = ""
14532
14861
  }) {
14533
- const valueRef = useRef9(value);
14862
+ const valueRef = useRef10(value);
14534
14863
  valueRef.current = value;
14535
14864
  useInput((input, key) => {
14536
14865
  if (key.return) {
@@ -14554,11 +14883,11 @@ function MaskedInput({
14554
14883
  });
14555
14884
  if (value.length === 0) {
14556
14885
  if (placeholder.length === 0) {
14557
- return /* @__PURE__ */ React60.createElement(Text52, { inverse: true }, " ");
14886
+ return /* @__PURE__ */ React61.createElement(Text53, { inverse: true }, " ");
14558
14887
  }
14559
- return /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(Text52, { inverse: true }, placeholder[0]), /* @__PURE__ */ React60.createElement(Text52, { color: FG.faint }, placeholder.slice(1)));
14888
+ return /* @__PURE__ */ React61.createElement(React61.Fragment, null, /* @__PURE__ */ React61.createElement(Text53, { inverse: true }, placeholder[0]), /* @__PURE__ */ React61.createElement(Text53, { color: FG.faint }, placeholder.slice(1)));
14560
14889
  }
14561
- return /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(Text52, null, mask.repeat(value.length)), /* @__PURE__ */ React60.createElement(Text52, { inverse: true }, " "));
14890
+ return /* @__PURE__ */ React61.createElement(React61.Fragment, null, /* @__PURE__ */ React61.createElement(Text53, null, mask.repeat(value.length)), /* @__PURE__ */ React61.createElement(Text53, { inverse: true }, " "));
14562
14891
  }
14563
14892
 
14564
14893
  // src/cli/ui/Setup.tsx
@@ -14585,7 +14914,7 @@ function Setup({ onReady }) {
14585
14914
  }
14586
14915
  onReady(trimmed);
14587
14916
  };
14588
- return /* @__PURE__ */ React61.createElement(Box49, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React61.createElement(Box49, null, /* @__PURE__ */ React61.createElement(Text53, { bold: true, color: GRADIENT[0] }, GLYPH.brand), /* @__PURE__ */ React61.createElement(Text53, null, " "), /* @__PURE__ */ React61.createElement(Text53, { bold: true }, "Welcome to "), /* @__PURE__ */ React61.createElement(Text53, { bold: true, color: GRADIENT[2] }, "REASONIX")), /* @__PURE__ */ React61.createElement(Box49, { marginTop: 1 }, /* @__PURE__ */ React61.createElement(Text53, { color: COLOR.info }, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React61.createElement(Box49, null, /* @__PURE__ */ React61.createElement(Text53, { dimColor: true }, " sign up at \xB7 "), /* @__PURE__ */ React61.createElement(Text53, { color: COLOR.primary }, "https://platform.deepseek.com/api_keys")), /* @__PURE__ */ React61.createElement(Box49, null, /* @__PURE__ */ React61.createElement(Text53, { dimColor: true }, " saved to "), /* @__PURE__ */ React61.createElement(Text53, { dimColor: true }, defaultConfigPath())), /* @__PURE__ */ React61.createElement(Box49, { marginTop: 1 }, /* @__PURE__ */ React61.createElement(Text53, { bold: true, color: COLOR.brand }, GLYPH.bar), /* @__PURE__ */ React61.createElement(Text53, { bold: true, color: COLOR.primary }, " \u203A "), /* @__PURE__ */ React61.createElement(
14917
+ return /* @__PURE__ */ React62.createElement(Box50, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React62.createElement(Box50, null, /* @__PURE__ */ React62.createElement(Text54, { bold: true, color: GRADIENT[0] }, GLYPH.brand), /* @__PURE__ */ React62.createElement(Text54, null, " "), /* @__PURE__ */ React62.createElement(Text54, { bold: true }, "Welcome to "), /* @__PURE__ */ React62.createElement(Text54, { bold: true, color: GRADIENT[2] }, "REASONIX")), /* @__PURE__ */ React62.createElement(Box50, { marginTop: 1 }, /* @__PURE__ */ React62.createElement(Text54, { color: COLOR.info }, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React62.createElement(Box50, null, /* @__PURE__ */ React62.createElement(Text54, { dimColor: true }, " sign up at \xB7 "), /* @__PURE__ */ React62.createElement(Text54, { color: COLOR.primary }, "https://platform.deepseek.com/api_keys")), /* @__PURE__ */ React62.createElement(Box50, null, /* @__PURE__ */ React62.createElement(Text54, { dimColor: true }, " saved to "), /* @__PURE__ */ React62.createElement(Text54, { dimColor: true }, defaultConfigPath())), /* @__PURE__ */ React62.createElement(Box50, { marginTop: 1 }, /* @__PURE__ */ React62.createElement(Text54, { bold: true, color: COLOR.brand }, GLYPH.bar), /* @__PURE__ */ React62.createElement(Text54, { bold: true, color: COLOR.primary }, " \u203A "), /* @__PURE__ */ React62.createElement(
14589
14918
  MaskedInput,
14590
14919
  {
14591
14920
  value,
@@ -14594,7 +14923,7 @@ function Setup({ onReady }) {
14594
14923
  mask: "\u2022",
14595
14924
  placeholder: "sk-..."
14596
14925
  }
14597
- )), error ? /* @__PURE__ */ React61.createElement(Box49, { marginTop: 1 }, /* @__PURE__ */ React61.createElement(Text53, { color: COLOR.err, bold: true }, GLYPH.err), /* @__PURE__ */ React61.createElement(Text53, { color: COLOR.err }, ` ${error}`)) : value ? /* @__PURE__ */ React61.createElement(Box49, { marginTop: 1 }, /* @__PURE__ */ React61.createElement(Text53, { dimColor: true }, ` preview \xB7 ${redactKey(value)}`)) : null, /* @__PURE__ */ React61.createElement(Box49, { marginTop: 1 }, /* @__PURE__ */ React61.createElement(Text53, { dimColor: true }, " /exit to abort")));
14926
+ )), error ? /* @__PURE__ */ React62.createElement(Box50, { marginTop: 1 }, /* @__PURE__ */ React62.createElement(Text54, { color: COLOR.err, bold: true }, GLYPH.err), /* @__PURE__ */ React62.createElement(Text54, { color: COLOR.err }, ` ${error}`)) : value ? /* @__PURE__ */ React62.createElement(Box50, { marginTop: 1 }, /* @__PURE__ */ React62.createElement(Text54, { dimColor: true }, ` preview \xB7 ${redactKey(value)}`)) : null, /* @__PURE__ */ React62.createElement(Box50, { marginTop: 1 }, /* @__PURE__ */ React62.createElement(Text54, { dimColor: true }, " /exit to abort")));
14598
14927
  }
14599
14928
 
14600
14929
  // src/cli/ui/drain-tty.ts
@@ -14805,7 +15134,7 @@ function Root({
14805
15134
  const workspaceRoot = appProps.codeMode?.rootDir ?? process.cwd();
14806
15135
  const [sessions2, setSessions] = useState22(() => listSessionsForWorkspace(workspaceRoot));
14807
15136
  if (!key) {
14808
- return /* @__PURE__ */ React62.createElement(
15137
+ return /* @__PURE__ */ React63.createElement(
14809
15138
  Setup,
14810
15139
  {
14811
15140
  onReady: (k) => {
@@ -14817,7 +15146,7 @@ function Root({
14817
15146
  }
14818
15147
  process.env.DEEPSEEK_API_KEY = key;
14819
15148
  if (pickerOpen) {
14820
- return /* @__PURE__ */ React62.createElement(KeystrokeProvider, null, /* @__PURE__ */ React62.createElement(
15149
+ return /* @__PURE__ */ React63.createElement(KeystrokeProvider, null, /* @__PURE__ */ React63.createElement(
14821
15150
  SessionPicker,
14822
15151
  {
14823
15152
  sessions: sessions2,
@@ -14850,7 +15179,7 @@ function Root({
14850
15179
  }
14851
15180
  ));
14852
15181
  }
14853
- return /* @__PURE__ */ React62.createElement(KeystrokeProvider, null, /* @__PURE__ */ React62.createElement(
15182
+ return /* @__PURE__ */ React63.createElement(KeystrokeProvider, null, /* @__PURE__ */ React63.createElement(
14854
15183
  App,
14855
15184
  {
14856
15185
  key: activeSession ?? "__new__",
@@ -14922,7 +15251,7 @@ async function chatCommand(opts) {
14922
15251
  const showPicker = !opts.session && !opts.forceResume && listSessionsForWorkspace(launchWorkspace).length > 0;
14923
15252
  markPhase("ink_render_call");
14924
15253
  const { waitUntilExit } = render(
14925
- /* @__PURE__ */ React62.createElement(
15254
+ /* @__PURE__ */ React63.createElement(
14926
15255
  Root,
14927
15256
  {
14928
15257
  initialKey,
@@ -14958,4 +15287,4 @@ async function chatCommand(opts) {
14958
15287
  export {
14959
15288
  chatCommand
14960
15289
  };
14961
- //# sourceMappingURL=chunk-OW7IHE6M.js.map
15290
+ //# sourceMappingURL=chunk-EINEIIIW.js.map