reasonix 0.33.2 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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-TL4HMNEQ.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-5SAMVHA3.js} +584 -288
  9. package/dist/cli/chunk-5SAMVHA3.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-V6F4BKMG.js} +15 -14
  28. package/dist/cli/{code-R4TXQQEE.js.map → code-V6F4BKMG.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-TL4HMNEQ.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 useRef8, 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
@@ -7150,6 +7203,16 @@ function reduce(state, event) {
7150
7203
  text: event.text,
7151
7204
  meta: event.meta
7152
7205
  });
7206
+ case "tip.show":
7207
+ return appendCard(state, {
7208
+ kind: "tip",
7209
+ id: event.id,
7210
+ ts: event.ts,
7211
+ topic: event.topic,
7212
+ sections: event.sections,
7213
+ footer: event.footer,
7214
+ oneTime: event.oneTime
7215
+ });
7153
7216
  case "session.reset":
7154
7217
  return { ...state, cards: [], focusedCardId: null, toasts: [] };
7155
7218
  case "plan.show":
@@ -7455,6 +7518,22 @@ ${stack}` : message
7455
7518
  });
7456
7519
  return id;
7457
7520
  },
7521
+ pushTip({ topic, sections, footer, oneTime = true }) {
7522
+ const id = nextId2("tip");
7523
+ dispatch({
7524
+ type: "tip.show",
7525
+ id,
7526
+ ts: Date.now(),
7527
+ topic,
7528
+ sections: sections.map((s) => ({
7529
+ title: s.title,
7530
+ rows: s.rows.map((r) => ({ key: r.key, text: r.text }))
7531
+ })),
7532
+ footer,
7533
+ oneTime
7534
+ });
7535
+ return id;
7536
+ },
7458
7537
  pushCtxPressureIfHigh(usedTokens, ctxMax) {
7459
7538
  if (ctxMax <= 0) return;
7460
7539
  const pct = usedTokens / ctxMax * 100;
@@ -7619,12 +7698,12 @@ function useTranscriptWriter(transcriptRef, model2, prefixHash) {
7619
7698
  }
7620
7699
 
7621
7700
  // 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";
7701
+ import { Box as Box44, Text as Text46, useBoxMetrics } from "ink";
7702
+ import React53, { useEffect as useEffect7, useRef as useRef4 } from "react";
7624
7703
 
7625
7704
  // src/cli/ui/cards/CardRenderer.tsx
7626
- import { Box as Box42, Text as Text44 } from "ink";
7627
- import React51 from "react";
7705
+ import { Box as Box43, Text as Text45 } from "ink";
7706
+ import React52 from "react";
7628
7707
 
7629
7708
  // src/cli/ui/cards/CtxCard.tsx
7630
7709
  import { Box as Box27, Text as Text26 } from "ink";
@@ -7748,11 +7827,6 @@ function DiffCard({ card }) {
7748
7827
  // src/cli/ui/cards/DoctorCard.tsx
7749
7828
  import { Box as Box29, Text as Text28 } from "ink";
7750
7829
  import React34 from "react";
7751
- var LEVEL_COLOR = {
7752
- ok: TONE.ok,
7753
- warn: TONE.warn,
7754
- fail: TONE.err
7755
- };
7756
7830
  var LEVEL_GLYPH = {
7757
7831
  ok: "\u2713",
7758
7832
  warn: "\u26A0",
@@ -7764,12 +7838,18 @@ var LEVEL_TAG = {
7764
7838
  fail: "FAIL"
7765
7839
  };
7766
7840
  function DoctorCard({ card }) {
7841
+ const { fg, tone } = useThemeTokens();
7842
+ const levelColor = {
7843
+ ok: tone.ok,
7844
+ warn: tone.warn,
7845
+ fail: tone.err
7846
+ };
7767
7847
  const ok = card.checks.filter((c) => c.level === "ok").length;
7768
7848
  const warn = card.checks.filter((c) => c.level === "warn").length;
7769
7849
  const fail = card.checks.filter((c) => c.level === "fail").length;
7770
7850
  const labelWidth = card.checks.reduce((m, c) => Math.max(m, c.label.length), 0);
7771
7851
  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]))));
7852
+ 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
7853
  }
7774
7854
 
7775
7855
  // src/cli/ui/cards/ErrorCard.tsx
@@ -7909,27 +7989,28 @@ var STATUS_GLYPH = {
7909
7989
  blocked: "!",
7910
7990
  skipped: "s"
7911
7991
  };
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
7992
  var VISIBLE_WINDOW = 5;
7921
7993
  function PlanCard({ card }) {
7994
+ const { fg, tone, toneActive } = useThemeTokens();
7995
+ const statusColor = {
7996
+ queued: fg.faint,
7997
+ running: toneActive.brand,
7998
+ done: tone.ok,
7999
+ failed: tone.err,
8000
+ blocked: tone.warn,
8001
+ skipped: fg.faint
8002
+ };
7922
8003
  const doneCount = card.steps.filter((s) => s.status === "done").length;
7923
8004
  const variantTag = card.variant === "resumed" ? "resumed \xB7 " : card.variant === "replay" ? "\u23EA archive \xB7 " : "";
7924
8005
  const progress = `${variantTag}${doneCount}/${card.steps.length} done`;
7925
8006
  const hasRunning = card.steps.some((s) => s.status === "running");
7926
- const tone = hasRunning ? TONE_ACTIVE.accent : TONE.accent;
8007
+ const cardTone = hasRunning ? toneActive.accent : tone.accent;
7927
8008
  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) => {
8009
+ 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
8010
  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);
8011
+ const titleColor = isActive ? fg.strong : fg.sub;
8012
+ 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);
8013
+ }), 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
8014
  }
7934
8015
  function pickWindow(steps) {
7935
8016
  if (steps.length <= VISIBLE_WINDOW) {
@@ -8542,13 +8623,14 @@ function StreamingCard({ card }) {
8542
8623
  // src/cli/ui/cards/SubAgentCard.tsx
8543
8624
  import { Box as Box38, Text as Text39 } from "ink";
8544
8625
  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
8626
  function SubAgentCard({ card }) {
8551
- const headColor = STATUS_COLOR2[card.status];
8627
+ const { fg, tone, toneActive } = useThemeTokens();
8628
+ const statusColor = {
8629
+ running: toneActive.violet,
8630
+ done: tone.ok,
8631
+ failed: tone.err
8632
+ };
8633
+ const headColor = statusColor[card.status];
8552
8634
  const headGlyph = card.status === "failed" ? "\u2716" : "\u232C";
8553
8635
  const runningChildren = card.children.filter((c) => !isChildDone(c)).length;
8554
8636
  const isRunning = card.status === "running";
@@ -8560,11 +8642,11 @@ function SubAgentCard({ card }) {
8560
8642
  glyph: headGlyph,
8561
8643
  tone: headColor,
8562
8644
  title: "subagent",
8563
- titleColor: TONE.violet,
8645
+ titleColor: tone.violet,
8564
8646
  subtitle: card.task,
8565
8647
  meta: headerMeta2
8566
8648
  }
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 }))));
8649
+ ), 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
8650
  }
8569
8651
  function isChildDone(card) {
8570
8652
  switch (card.kind) {
@@ -8578,9 +8660,10 @@ function isChildDone(card) {
8578
8660
  }
8579
8661
  }
8580
8662
  function ChildRow({ card }) {
8581
- const v = childVisual(card);
8663
+ const { fg, tone } = useThemeTokens();
8664
+ const v = childVisual(card, tone.ok, tone.err, fg.faint);
8582
8665
  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));
8666
+ 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
8667
  }
8585
8668
  function runningGlyph(color) {
8586
8669
  return /* @__PURE__ */ React45.createElement(Spinner, { kind: "circle", color });
@@ -8588,15 +8671,15 @@ function runningGlyph(color) {
8588
8671
  function doneGlyph(color) {
8589
8672
  return /* @__PURE__ */ React45.createElement(Text39, { color }, "\u2713");
8590
8673
  }
8591
- function failedGlyph() {
8592
- return /* @__PURE__ */ React45.createElement(Text39, { color: TONE.err }, "\u2716");
8674
+ function failedGlyph(color) {
8675
+ return /* @__PURE__ */ React45.createElement(Text39, { color }, "\u2716");
8593
8676
  }
8594
- function childVisual(card) {
8677
+ function childVisual(card, doneColor, failedColor, fallbackColor) {
8595
8678
  switch (card.kind) {
8596
8679
  case "reasoning": {
8597
8680
  const done = !card.streaming;
8598
8681
  return {
8599
- statusGlyph: done ? doneGlyph(TONE.ok) : runningGlyph(CARD.reasoning.color),
8682
+ statusGlyph: done ? doneGlyph(doneColor) : runningGlyph(CARD.reasoning.color),
8600
8683
  kindGlyph: "\u25C6",
8601
8684
  kindColor: CARD.reasoning.color,
8602
8685
  text: `reasoning \xB7 ${card.paragraphs} \xB6`
@@ -8605,7 +8688,7 @@ function childVisual(card) {
8605
8688
  case "tool": {
8606
8689
  const elapsed = card.elapsedMs > 0 ? ` \xB7 ${(card.elapsedMs / 1e3).toFixed(2)}s` : "";
8607
8690
  return {
8608
- statusGlyph: card.done ? doneGlyph(TONE.ok) : runningGlyph(CARD.tool.color),
8691
+ statusGlyph: card.done ? doneGlyph(doneColor) : runningGlyph(CARD.tool.color),
8609
8692
  kindGlyph: "\u25A3",
8610
8693
  kindColor: CARD.tool.color,
8611
8694
  text: `${card.name}${elapsed}`
@@ -8613,30 +8696,30 @@ function childVisual(card) {
8613
8696
  }
8614
8697
  case "streaming":
8615
8698
  return {
8616
- statusGlyph: card.done ? doneGlyph(TONE.ok) : runningGlyph(CARD.streaming.color),
8699
+ statusGlyph: card.done ? doneGlyph(doneColor) : runningGlyph(CARD.streaming.color),
8617
8700
  kindGlyph: "\u25C8",
8618
8701
  kindColor: CARD.streaming.color,
8619
8702
  text: card.done ? "response" : "writing \u2026"
8620
8703
  };
8621
8704
  case "diff":
8622
8705
  return {
8623
- statusGlyph: doneGlyph(TONE.ok),
8706
+ statusGlyph: doneGlyph(doneColor),
8624
8707
  kindGlyph: "\xB1",
8625
8708
  kindColor: CARD.diff.color,
8626
8709
  text: card.file
8627
8710
  };
8628
8711
  case "error":
8629
8712
  return {
8630
- statusGlyph: failedGlyph(),
8713
+ statusGlyph: failedGlyph(failedColor),
8631
8714
  kindGlyph: "\u2716",
8632
8715
  kindColor: CARD.error.color,
8633
8716
  text: card.title
8634
8717
  };
8635
8718
  default:
8636
8719
  return {
8637
- statusGlyph: /* @__PURE__ */ React45.createElement(Text39, { color: FG.faint }, "\xB7"),
8720
+ statusGlyph: /* @__PURE__ */ React45.createElement(Text39, { color: fallbackColor }, "\xB7"),
8638
8721
  kindGlyph: "\xB7",
8639
- kindColor: FG.faint,
8722
+ kindColor: fallbackColor,
8640
8723
  text: card.kind
8641
8724
  };
8642
8725
  }
@@ -8651,39 +8734,70 @@ var STEP_GLYPH = {
8651
8734
  done: "\u2713",
8652
8735
  failed: "\u2717"
8653
8736
  };
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
8737
  var TASK_GLYPH = {
8666
8738
  running: "\u25B6",
8667
8739
  done: "\u2713",
8668
8740
  failed: "\u2717"
8669
8741
  };
8670
8742
  function TaskCard({ card }) {
8743
+ const { fg, tone } = useThemeTokens();
8744
+ const stepColor = {
8745
+ queued: fg.faint,
8746
+ running: tone.warn,
8747
+ done: tone.ok,
8748
+ failed: tone.err
8749
+ };
8750
+ const taskColor = {
8751
+ running: tone.warn,
8752
+ done: tone.ok,
8753
+ failed: tone.err
8754
+ };
8671
8755
  const elapsed = `${(card.elapsedMs / 1e3).toFixed(1)}s`;
8672
- return /* @__PURE__ */ React46.createElement(Card, { tone: TASK_COLOR[card.status] }, /* @__PURE__ */ React46.createElement(
8756
+ return /* @__PURE__ */ React46.createElement(Card, { tone: taskColor[card.status] }, /* @__PURE__ */ React46.createElement(
8673
8757
  CardHeader,
8674
8758
  {
8675
8759
  glyph: TASK_GLYPH[card.status],
8676
- tone: TASK_COLOR[card.status],
8760
+ tone: taskColor[card.status],
8677
8761
  title: `step ${card.index}/${card.total}`,
8678
8762
  subtitle: card.title,
8679
8763
  meta: [elapsed, card.status]
8680
8764
  }
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)));
8765
+ ), 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
8766
  }
8683
8767
 
8684
- // src/cli/ui/cards/ToolCard.tsx
8685
- import { Text as Text41, useStdout as useStdout11 } from "ink";
8768
+ // src/cli/ui/cards/TipCard.tsx
8769
+ import { Box as Box40, Text as Text41 } from "ink";
8686
8770
  import React47 from "react";
8771
+ import stringWidth2 from "string-width";
8772
+ var KEY_GUTTER = 4;
8773
+ function TipCard({ card }) {
8774
+ const keyWidth = card.sections.reduce(
8775
+ (max, sec) => sec.rows.reduce((m, r) => Math.max(m, stringWidth2(r.key)), max),
8776
+ 0
8777
+ );
8778
+ 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(
8779
+ TipRowRender,
8780
+ {
8781
+ key: row2.key,
8782
+ row: row2,
8783
+ keyWidth,
8784
+ indent: section.title ? 2 : 0
8785
+ }
8786
+ )))), card.footer ? /* @__PURE__ */ React47.createElement(Box40, { marginTop: 1 }, /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, card.footer)) : null);
8787
+ }
8788
+ function TipRowRender({
8789
+ row: row2,
8790
+ keyWidth,
8791
+ indent
8792
+ }) {
8793
+ const pad = " ".repeat(Math.max(0, keyWidth - stringWidth2(row2.key) + KEY_GUTTER));
8794
+ const lead = indent > 0 ? " ".repeat(indent) : "";
8795
+ 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));
8796
+ }
8797
+
8798
+ // src/cli/ui/cards/ToolCard.tsx
8799
+ import { Text as Text42, useStdout as useStdout11 } from "ink";
8800
+ import React48 from "react";
8687
8801
  var READ_TAIL = 2;
8688
8802
  var OTHER_TAIL = 5;
8689
8803
  function tailLinesFor(name) {
@@ -8712,7 +8826,7 @@ function ToolCard({ card }) {
8712
8826
  meta.push({ text: "rejected", color: TONE.err });
8713
8827
  }
8714
8828
  for (const part of metaTrail(card)) meta.push(part);
8715
- return /* @__PURE__ */ React47.createElement(Card, { tone: headColor }, /* @__PURE__ */ React47.createElement(
8829
+ return /* @__PURE__ */ React48.createElement(Card, { tone: headColor }, /* @__PURE__ */ React48.createElement(
8716
8830
  CardHeader,
8717
8831
  {
8718
8832
  glyph: statusGlyph2(status2),
@@ -8720,10 +8834,10 @@ function ToolCard({ card }) {
8720
8834
  title: card.name,
8721
8835
  subtitle: argsLabel || void 0,
8722
8836
  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
8837
+ right: status2 === "running" ? /* @__PURE__ */ React48.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand, bold: true }) : void 0
8724
8838
  }
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,
8839
+ ), 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(
8840
+ Text42,
8727
8841
  {
8728
8842
  key: `${card.id}:${hidden + i}`,
8729
8843
  color: errColor,
@@ -8778,15 +8892,15 @@ function metaTrail(card) {
8778
8892
  function formatArgsSummary(args) {
8779
8893
  if (typeof args === "string") return args.length > 60 ? `${args.slice(0, 60)}\u2026` : args;
8780
8894
  if (args && typeof args === "object") {
8781
- const keys = Object.keys(args);
8782
- if (keys.length === 0) return "";
8783
- const first = keys[0];
8895
+ const keys2 = Object.keys(args);
8896
+ if (keys2.length === 0) return "";
8897
+ const first = keys2[0];
8784
8898
  const value = args[first];
8785
8899
  if (typeof value === "string") {
8786
8900
  const trimmed = value.length > 40 ? `${value.slice(0, 40)}\u2026` : value;
8787
- return keys.length === 1 ? trimmed : `${trimmed} +${keys.length - 1}`;
8901
+ return keys2.length === 1 ? trimmed : `${trimmed} +${keys2.length - 1}`;
8788
8902
  }
8789
- return keys.join(" ");
8903
+ return keys2.join(" ");
8790
8904
  }
8791
8905
  return "";
8792
8906
  }
@@ -8809,8 +8923,8 @@ function formatBytes(n) {
8809
8923
  }
8810
8924
 
8811
8925
  // src/cli/ui/cards/UsageCard.tsx
8812
- import { Box as Box41, Text as Text42 } from "ink";
8813
- import React48 from "react";
8926
+ import { Box as Box42, Text as Text43 } from "ink";
8927
+ import React49 from "react";
8814
8928
  var BAR_CELLS2 = 30;
8815
8929
  function compactNum(n) {
8816
8930
  if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
@@ -8820,25 +8934,25 @@ function compactNum(n) {
8820
8934
  function bar(ratio, color) {
8821
8935
  const filled = Math.max(0, Math.min(BAR_CELLS2, Math.round(ratio * BAR_CELLS2)));
8822
8936
  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)));
8937
+ 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
8938
  }
8825
8939
  function UsageCard({ card }) {
8826
- if (card.compact) return /* @__PURE__ */ React48.createElement(CompactUsageRow, { card });
8940
+ if (card.compact) return /* @__PURE__ */ React49.createElement(CompactUsageRow, { card });
8827
8941
  const cap = Math.max(1, card.tokens.promptCap);
8828
8942
  const promptRatio = card.tokens.prompt / cap;
8829
8943
  const reasonRatio = card.tokens.reason / cap;
8830
8944
  const outputRatio = card.tokens.output / cap;
8831
8945
  const headerMeta2 = [`turn ${card.turn}`, formatCost(card.cost, card.balanceCurrency)];
8832
8946
  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));
8947
+ 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
8948
  }
8835
8949
  function CompactUsageRow({ card }) {
8836
8950
  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);
8951
+ 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
8952
  }
8839
8953
 
8840
8954
  // src/cli/ui/cards/UserCard.tsx
8841
- import React49 from "react";
8955
+ import React50 from "react";
8842
8956
 
8843
8957
  // src/cli/ui/cards/time.ts
8844
8958
  function formatRelativeTime(ts, now = Date.now()) {
@@ -8855,7 +8969,7 @@ function formatRelativeTime(ts, now = Date.now()) {
8855
8969
 
8856
8970
  // src/cli/ui/cards/UserCard.tsx
8857
8971
  function UserCard({ card }) {
8858
- return /* @__PURE__ */ React49.createElement(Card, { tone: TONE.accent }, /* @__PURE__ */ React49.createElement(
8972
+ return /* @__PURE__ */ React50.createElement(Card, { tone: TONE.accent }, /* @__PURE__ */ React50.createElement(
8859
8973
  CardHeader,
8860
8974
  {
8861
8975
  glyph: "\u203A",
@@ -8864,15 +8978,15 @@ function UserCard({ card }) {
8864
8978
  titleColor: FG.sub,
8865
8979
  meta: [formatRelativeTime(card.ts)]
8866
8980
  }
8867
- ), /* @__PURE__ */ React49.createElement(Markdown, { text: card.text }));
8981
+ ), /* @__PURE__ */ React50.createElement(Markdown, { text: card.text }));
8868
8982
  }
8869
8983
 
8870
8984
  // src/cli/ui/cards/WarnCard.tsx
8871
- import { Text as Text43 } from "ink";
8872
- import React50 from "react";
8985
+ import { Text as Text44 } from "ink";
8986
+ import React51 from "react";
8873
8987
  function WarnCard({ card }) {
8874
8988
  const messageLines = card.message.length > 0 ? card.message.split("\n") : [];
8875
- return /* @__PURE__ */ React50.createElement(Card, { tone: TONE.warn }, /* @__PURE__ */ React50.createElement(
8989
+ return /* @__PURE__ */ React51.createElement(Card, { tone: TONE.warn }, /* @__PURE__ */ React51.createElement(
8876
8990
  CardHeader,
8877
8991
  {
8878
8992
  glyph: "\u26A0",
@@ -8880,55 +8994,57 @@ function WarnCard({ card }) {
8880
8994
  title: card.title,
8881
8995
  meta: card.detail ? [card.detail] : void 0
8882
8996
  }
8883
- ), messageLines.map((line, i) => /* @__PURE__ */ React50.createElement(Text43, { key: `${card.id}:${i}`, color: FG.body }, line || " ")));
8997
+ ), messageLines.map((line, i) => /* @__PURE__ */ React51.createElement(Text44, { key: `${card.id}:${i}`, color: FG.body }, line || " ")));
8884
8998
  }
8885
8999
 
8886
9000
  // src/cli/ui/cards/CardRenderer.tsx
8887
- var CardRenderer = React51.memo(function CardRenderer2({
9001
+ var CardRenderer = React52.memo(function CardRenderer2({
8888
9002
  card
8889
9003
  }) {
8890
- return /* @__PURE__ */ React51.createElement(Box42, { flexDirection: "column" }, renderCard(card));
9004
+ return /* @__PURE__ */ React52.createElement(Box43, { flexDirection: "column" }, renderCard(card));
8891
9005
  });
8892
9006
  function renderCard(card) {
8893
9007
  switch (card.kind) {
8894
9008
  case "user":
8895
- return /* @__PURE__ */ React51.createElement(UserCard, { card });
9009
+ return /* @__PURE__ */ React52.createElement(UserCard, { card });
8896
9010
  case "reasoning":
8897
- return /* @__PURE__ */ React51.createElement(ReasoningCard, { card, expanded: true });
9011
+ return /* @__PURE__ */ React52.createElement(ReasoningCard, { card, expanded: true });
8898
9012
  case "streaming":
8899
- return /* @__PURE__ */ React51.createElement(StreamingCard, { card });
9013
+ return /* @__PURE__ */ React52.createElement(StreamingCard, { card });
8900
9014
  case "tool":
8901
- return /* @__PURE__ */ React51.createElement(ToolCard, { card });
9015
+ return /* @__PURE__ */ React52.createElement(ToolCard, { card });
8902
9016
  case "task":
8903
- return /* @__PURE__ */ React51.createElement(TaskCard, { card });
9017
+ return /* @__PURE__ */ React52.createElement(TaskCard, { card });
8904
9018
  case "plan":
8905
- return /* @__PURE__ */ React51.createElement(PlanCard, { card });
9019
+ return /* @__PURE__ */ React52.createElement(PlanCard, { card });
8906
9020
  case "diff":
8907
- return /* @__PURE__ */ React51.createElement(DiffCard, { card });
9021
+ return /* @__PURE__ */ React52.createElement(DiffCard, { card });
8908
9022
  case "error":
8909
- return /* @__PURE__ */ React51.createElement(ErrorCard, { card });
9023
+ return /* @__PURE__ */ React52.createElement(ErrorCard, { card });
8910
9024
  case "warn":
8911
- return /* @__PURE__ */ React51.createElement(WarnCard, { card });
9025
+ return /* @__PURE__ */ React52.createElement(WarnCard, { card });
8912
9026
  case "usage":
8913
- return /* @__PURE__ */ React51.createElement(UsageCard, { card });
9027
+ return /* @__PURE__ */ React52.createElement(UsageCard, { card });
8914
9028
  case "memory":
8915
- return /* @__PURE__ */ React51.createElement(MemoryCard, { card });
9029
+ return /* @__PURE__ */ React52.createElement(MemoryCard, { card });
8916
9030
  case "subagent":
8917
- return /* @__PURE__ */ React51.createElement(SubAgentCard, { card });
9031
+ return /* @__PURE__ */ React52.createElement(SubAgentCard, { card });
8918
9032
  case "search":
8919
- return /* @__PURE__ */ React51.createElement(SearchCard, { card });
9033
+ return /* @__PURE__ */ React52.createElement(SearchCard, { card });
8920
9034
  case "live":
8921
- return /* @__PURE__ */ React51.createElement(LiveCard, { card });
9035
+ return /* @__PURE__ */ React52.createElement(LiveCard, { card });
9036
+ case "tip":
9037
+ return /* @__PURE__ */ React52.createElement(TipCard, { card });
8922
9038
  case "ctx":
8923
- return /* @__PURE__ */ React51.createElement(CtxCard, { card });
9039
+ return /* @__PURE__ */ React52.createElement(CtxCard, { card });
8924
9040
  case "doctor":
8925
- return /* @__PURE__ */ React51.createElement(DoctorCard, { card });
9041
+ return /* @__PURE__ */ React52.createElement(DoctorCard, { card });
8926
9042
  default:
8927
- return /* @__PURE__ */ React51.createElement(FallbackCard, { card });
9043
+ return /* @__PURE__ */ React52.createElement(FallbackCard, { card });
8928
9044
  }
8929
9045
  }
8930
9046
  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`));
9047
+ return /* @__PURE__ */ React52.createElement(Box43, { flexDirection: "row" }, /* @__PURE__ */ React52.createElement(Text45, { color: FG.faint }, ` \xB7 ${card.kind} card \xB7 not yet migrated`));
8932
9048
  }
8933
9049
 
8934
9050
  // src/cli/ui/layout/CardStream.tsx
@@ -8950,7 +9066,7 @@ function CardStream({
8950
9066
  if (suppressLive && cards.length > 0 && !isFullySettled(cards[cards.length - 1])) {
8951
9067
  visible = cards.slice(0, -1);
8952
9068
  }
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 })))));
9069
+ 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
9070
  }
8955
9071
  function isFullySettled(card) {
8956
9072
  switch (card.kind) {
@@ -8970,12 +9086,13 @@ function isFullySettled(card) {
8970
9086
  }
8971
9087
 
8972
9088
  // src/cli/ui/layout/LiveRows.tsx
8973
- import { Box as Box44, Text as Text46 } from "ink";
8974
- import React53 from "react";
9089
+ import { Box as Box45, Text as Text47 } from "ink";
9090
+ import React54 from "react";
8975
9091
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
8976
9092
  function ThinkingRow({ text }) {
8977
9093
  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`));
9094
+ const { fg, tone } = useThemeTokens();
9095
+ 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
9096
  }
8980
9097
  function ModeStatusBar({
8981
9098
  editMode,
@@ -8987,24 +9104,24 @@ function ModeStatusBar({
8987
9104
  }) {
8988
9105
  useSlowTick();
8989
9106
  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;
9107
+ const jobsTag = running > 0 ? /* @__PURE__ */ React54.createElement(Text47, { color: TONE.warn, bold: true }, ` \xB7 \u23F5 ${running} job${running === 1 ? "" : "s"}`) : null;
8991
9108
  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);
9109
+ 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
9110
  }
8994
9111
  const label = editMode === "yolo" ? "YOLO" : editMode === "auto" ? "AUTO" : "REVIEW";
8995
9112
  const pillColor = editMode === "yolo" ? TONE.err : editMode === "auto" ? TONE.accent : TONE.brand;
8996
9113
  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);
9114
+ 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
9115
  }
8999
9116
  function ModeBarFrame({ children }) {
9000
- return /* @__PURE__ */ React53.createElement(Box44, { paddingX: 1 }, children);
9117
+ return /* @__PURE__ */ React54.createElement(Box45, { paddingX: 1 }, children);
9001
9118
  }
9002
9119
  function ModePill({
9003
9120
  label,
9004
9121
  color,
9005
9122
  flash
9006
9123
  }) {
9007
- return /* @__PURE__ */ React53.createElement(Text46, { color, bold: true, inverse: flash }, `[${label}]`);
9124
+ return /* @__PURE__ */ React54.createElement(Text47, { color, bold: true, inverse: flash }, `[${label}]`);
9008
9125
  }
9009
9126
  function UndoBanner({
9010
9127
  banner
@@ -9019,7 +9136,7 @@ function UndoBanner({
9019
9136
  const urgent = !paused && remainingSec <= 1;
9020
9137
  const pct = remainingMs / totalMs * 100;
9021
9138
  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`));
9139
+ 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
9140
  }
9024
9141
  function subagentPhaseLabel(phase, iter, elapsedMs) {
9025
9142
  if (phase === "summarising") return "summarising findings\u2026";
@@ -9034,7 +9151,7 @@ function SubagentRow({ activity }) {
9034
9151
  const last = activity.lastInner;
9035
9152
  const subtitle = activity.skillName ?? truncate2(activity.task, 48);
9036
9153
  const modelBadge = activity.model ? modelBadgeFor(activity.model) : null;
9037
- return /* @__PURE__ */ React53.createElement(Card, { tone: CARD.subagent.color }, /* @__PURE__ */ React53.createElement(
9154
+ return /* @__PURE__ */ React54.createElement(Card, { tone: CARD.subagent.color }, /* @__PURE__ */ React54.createElement(
9038
9155
  CardHeader,
9039
9156
  {
9040
9157
  glyph: "\u232C",
@@ -9044,9 +9161,9 @@ function SubagentRow({ activity }) {
9044
9161
  titleBg: PILL_SECTION.plan.bg,
9045
9162
  subtitle,
9046
9163
  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 }))
9164
+ 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
9165
  }
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));
9166
+ ), /* @__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
9167
  }
9051
9168
  function SubagentLiveStack({
9052
9169
  activities,
@@ -9054,13 +9171,13 @@ function SubagentLiveStack({
9054
9171
  }) {
9055
9172
  const tick = useTick();
9056
9173
  if (activities.length === 0) return null;
9057
- if (activities.length === 1) return /* @__PURE__ */ React53.createElement(SubagentRow, { activity: activities[0] });
9174
+ if (activities.length === 1) return /* @__PURE__ */ React54.createElement(SubagentRow, { activity: activities[0] });
9058
9175
  const visible = activities.slice(0, max);
9059
9176
  const overflow = activities.length - visible.length;
9060
9177
  const summarising = activities.filter((a) => a.phase === "summarising").length;
9061
9178
  const metaParts = [`${activities.length} running`];
9062
9179
  if (summarising > 0) metaParts.push(`${summarising} summarising`);
9063
- return /* @__PURE__ */ React53.createElement(Card, { tone: CARD.subagent.color }, /* @__PURE__ */ React53.createElement(
9180
+ return /* @__PURE__ */ React54.createElement(Card, { tone: CARD.subagent.color }, /* @__PURE__ */ React54.createElement(
9064
9181
  CardHeader,
9065
9182
  {
9066
9183
  glyph: "\u232C",
@@ -9069,9 +9186,9 @@ function SubagentLiveStack({
9069
9186
  titleColor: PILL_SECTION.plan.fg,
9070
9187
  titleBg: PILL_SECTION.plan.bg,
9071
9188
  subtitle: metaParts.join(" \xB7 "),
9072
- right: /* @__PURE__ */ React53.createElement(Spinner, { kind: "braille", color: CARD.subagent.color })
9189
+ right: /* @__PURE__ */ React54.createElement(Spinner, { kind: "braille", color: CARD.subagent.color })
9073
9190
  }
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);
9191
+ ), 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
9192
  }
9076
9193
  function CompactSubagentLine({
9077
9194
  activity,
@@ -9086,7 +9203,7 @@ function CompactSubagentLine({
9086
9203
  const title = activity.skillName ?? truncate2(activity.task, 28);
9087
9204
  const titlePadded = title.padEnd(28);
9088
9205
  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"));
9206
+ 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
9207
  }
9091
9208
  function truncate2(text, max) {
9092
9209
  return text.length > max ? `${text.slice(0, max)}\u2026` : text;
@@ -9098,7 +9215,7 @@ function OngoingToolRow({
9098
9215
  const tick = useTick();
9099
9216
  const elapsed = useElapsedSeconds();
9100
9217
  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);
9218
+ 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
9219
  }
9103
9220
  function renderProgressLine(p) {
9104
9221
  const msg = p.message ? ` ${p.message}` : "";
@@ -9154,16 +9271,16 @@ function summarizeToolArgs(name, args) {
9154
9271
  }
9155
9272
 
9156
9273
  // src/cli/ui/layout/StatusRow.tsx
9157
- import { Box as Box45, Text as Text48, useStdout as useStdout12 } from "ink";
9158
- import React55 from "react";
9274
+ import { Box as Box46, Text as Text49, useStdout as useStdout12 } from "ink";
9275
+ import React56 from "react";
9159
9276
 
9160
9277
  // src/cli/ui/primitives/Countdown.tsx
9161
- import { Text as Text47 } from "ink";
9162
- import React54 from "react";
9278
+ import { Text as Text48 } from "ink";
9279
+ import React55 from "react";
9163
9280
  function Countdown({ endsAt, color = TONE.brand }) {
9164
9281
  useSlowTick();
9165
9282
  const remainingSec = Math.max(0, Math.ceil((endsAt - Date.now()) / 1e3));
9166
- return /* @__PURE__ */ React54.createElement(Text47, { bold: true, color }, String(remainingSec));
9283
+ return /* @__PURE__ */ React55.createElement(Text48, { bold: true, color }, String(remainingSec));
9167
9284
  }
9168
9285
 
9169
9286
  // src/cli/ui/layout/StatusRow.tsx
@@ -9180,7 +9297,7 @@ function StatusRow() {
9180
9297
  const hasSession = status2.sessionCost > 0;
9181
9298
  const hasBalance = typeof status2.balance === "number";
9182
9299
  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(
9300
+ 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
9301
  WalletPill,
9185
9302
  {
9186
9303
  sessionCostUsd: status2.sessionCost,
@@ -9196,7 +9313,7 @@ function WalletPill({
9196
9313
  }) {
9197
9314
  const showSpent = sessionCostUsd > 0;
9198
9315
  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"));
9316
+ 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
9317
  }
9201
9318
  function ModePill2({
9202
9319
  mode: mode2,
@@ -9205,18 +9322,18 @@ function ModePill2({
9205
9322
  }) {
9206
9323
  if (network === "online") {
9207
9324
  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}`));
9325
+ 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
9326
  }
9210
9327
  const dot = networkDot(network);
9211
9328
  if (network === "slow") {
9212
9329
  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}`));
9330
+ 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
9331
  }
9215
9332
  if (network === "disconnected") {
9216
9333
  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}`));
9334
+ 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
9335
  }
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"));
9336
+ 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
9337
  }
9221
9338
  function CountdownRow({
9222
9339
  mode: mode2,
@@ -9224,14 +9341,14 @@ function CountdownRow({
9224
9341
  }) {
9225
9342
  const pill = modeGlyph(mode2);
9226
9343
  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"));
9344
+ 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
9345
  }
9229
9346
  function RecordingPill({ rec }) {
9230
9347
  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`));
9348
+ 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
9349
  }
9233
9350
  function Sep() {
9234
- return /* @__PURE__ */ React55.createElement(Text48, { color: FG.meta }, " \xB7 ");
9351
+ return /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta }, " \xB7 ");
9235
9352
  }
9236
9353
  function modeGlyph(mode2) {
9237
9354
  switch (mode2) {
@@ -9259,8 +9376,8 @@ function networkDot(state) {
9259
9376
  }
9260
9377
 
9261
9378
  // 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";
9379
+ import { Box as Box47, Text as Text50, useStdout as useStdout13 } from "ink";
9380
+ import React57, { useEffect as useEffect8 } from "react";
9264
9381
  var TONE_COLOR = {
9265
9382
  ok: TONE.ok,
9266
9383
  info: TONE.brand,
@@ -9298,17 +9415,17 @@ function ToastRail() {
9298
9415
  }, [toasts, dispatch]);
9299
9416
  const visible = toasts.filter((t2) => now - t2.bornAt < t2.ttlMs);
9300
9417
  if (visible.length === 0) return null;
9301
- return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "column" }, visible.map((t2) => {
9418
+ return /* @__PURE__ */ React57.createElement(Box47, { flexDirection: "column" }, visible.map((t2) => {
9302
9419
  const color = TONE_COLOR[t2.tone];
9303
9420
  const glyph = TONE_GLYPH[t2.tone];
9304
9421
  const body = bodyColor(t2, now);
9305
9422
  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`)));
9423
+ 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
9424
  }));
9308
9425
  }
9309
9426
 
9310
9427
  // src/cli/ui/layout/plan-live-row.tsx
9311
- import React57 from "react";
9428
+ import React58 from "react";
9312
9429
  function isActivePlanInFlight(card) {
9313
9430
  if (card.kind !== "plan") return false;
9314
9431
  if (card.variant !== "active") return false;
@@ -9323,7 +9440,7 @@ function PlanLiveRow() {
9323
9440
  return null;
9324
9441
  });
9325
9442
  if (!planCard) return null;
9326
- return /* @__PURE__ */ React57.createElement(PlanCard, { card: planCard });
9443
+ return /* @__PURE__ */ React58.createElement(PlanCard, { card: planCard });
9327
9444
  }
9328
9445
 
9329
9446
  // src/cli/ui/loop.ts
@@ -9851,12 +9968,19 @@ var loop = (args, _loop, ctx) => {
9851
9968
  })
9852
9969
  };
9853
9970
  };
9971
+ var keys = (_args, _loop, ctx) => {
9972
+ if (!ctx.postKeys) return { info: t("handlers.basic.keysNeedsTui") };
9973
+ const ref = tObj("ui.keysReference");
9974
+ ctx.postKeys({ topic: ref.topic, sections: ref.sections, footer: ref.footer });
9975
+ return {};
9976
+ };
9854
9977
  var handlers2 = {
9855
9978
  exit,
9856
9979
  new: resetLog,
9857
9980
  help,
9858
9981
  retry,
9859
- loop
9982
+ loop,
9983
+ keys
9860
9984
  };
9861
9985
 
9862
9986
  // src/cli/ui/slash/handlers/dashboard.ts
@@ -10775,8 +10899,8 @@ var handlers10 = {
10775
10899
  };
10776
10900
 
10777
10901
  // src/cli/ui/ctx-breakdown.tsx
10778
- import { Box as Box47, Text as Text50 } from "ink";
10779
- import React58 from "react";
10902
+ import { Box as Box48, Text as Text51 } from "ink";
10903
+ import React59 from "react";
10780
10904
  function computeCtxBreakdown(loop2) {
10781
10905
  const systemTokens = countTokens(loop2.prefix.system);
10782
10906
  const toolsTokens = countTokens(JSON.stringify(loop2.prefix.toolSpecs));
@@ -11306,8 +11430,40 @@ var handlers15 = {
11306
11430
  skills: skill
11307
11431
  };
11308
11432
 
11309
- // src/cli/ui/slash/handlers/web-search-engine.ts
11433
+ // src/cli/ui/slash/handlers/theme.ts
11434
+ var themeChoices = ["auto", ...listThemeNames()];
11435
+ function formatThemeStatus() {
11436
+ const configured = loadTheme();
11437
+ const active = resolveThemePreference(configured, process.env.REASONIX_THEME);
11438
+ const source = configured && configured !== "auto" ? "config" : "env/default";
11439
+ return [
11440
+ `theme: ${active} (${source})`,
11441
+ `configured: ${configured ?? "unset"}`,
11442
+ `available: ${themeChoices.join(", ")}`,
11443
+ "usage: /theme <name|auto>"
11444
+ ].join("\n");
11445
+ }
11446
+ function isThemeChoice(value) {
11447
+ return value === "auto" || isThemeName(value);
11448
+ }
11449
+ var theme = (args) => {
11450
+ const next = args[0];
11451
+ if (!next) return { info: formatThemeStatus() };
11452
+ if (!isThemeChoice(next)) {
11453
+ return { info: `unknown theme: ${next}
11454
+ available: ${themeChoices.join(", ")}` };
11455
+ }
11456
+ saveTheme(next);
11457
+ const active = resolveThemePreference(next, process.env.REASONIX_THEME);
11458
+ return { info: `theme saved: ${next}
11459
+ active on next launch: ${active}` };
11460
+ };
11310
11461
  var handlers16 = {
11462
+ theme
11463
+ };
11464
+
11465
+ // src/cli/ui/slash/handlers/web-search-engine.ts
11466
+ var handlers17 = {
11311
11467
  "search-engine": (args, _loop, ctx) => {
11312
11468
  const engine = args[0];
11313
11469
  if (!engine || engine !== "mojeek" && engine !== "searxng") {
@@ -11340,7 +11496,7 @@ var handlers16 = {
11340
11496
  const detail = engine === "searxng" ? t("handlers.webSearchEngine.confirmedDetail", { endpoint: webSearchEndpoint() }) : "";
11341
11497
  return { info: t("handlers.webSearchEngine.confirmed", { engine, detail }) };
11342
11498
  },
11343
- se: (args, loop2, ctx) => handlers16["search-engine"](args, loop2, ctx)
11499
+ se: (args, loop2, ctx) => handlers17["search-engine"](args, loop2, ctx)
11344
11500
  };
11345
11501
 
11346
11502
  // src/cli/ui/slash/dispatch.ts
@@ -11359,8 +11515,9 @@ var HANDLERS = {
11359
11515
  ...handlers12,
11360
11516
  ...handlers13,
11361
11517
  ...handlers14,
11518
+ ...handlers16,
11362
11519
  ...handlers15,
11363
- ...handlers16
11520
+ ...handlers17
11364
11521
  };
11365
11522
  function handleSlash(cmd, args, loop2, ctx = {}) {
11366
11523
  const h = HANDLERS[resolveSlashAlias(cmd)];
@@ -11497,6 +11654,20 @@ ${card.meta}` : card.text
11497
11654
  case "ctx":
11498
11655
  out.push({ id: card.id, role: "info", text: card.text });
11499
11656
  break;
11657
+ case "tip": {
11658
+ const sectionTexts = card.sections.map((sec) => {
11659
+ const body2 = sec.rows.map((r) => `${r.key} ${r.text}`).join("\n");
11660
+ return sec.title ? `[${sec.title}]
11661
+ ${body2}` : body2;
11662
+ });
11663
+ const body = sectionTexts.join("\n\n");
11664
+ const text = card.footer ? `${card.topic}
11665
+ ${body}
11666
+ ${card.footer}` : `${card.topic}
11667
+ ${body}`;
11668
+ out.push({ id: card.id, role: "info", text });
11669
+ break;
11670
+ }
11500
11671
  case "plan": {
11501
11672
  const done = card.steps.filter((s) => s.status === "done").length;
11502
11673
  const tag2 = card.variant === "resumed" ? "[resumed]" : card.variant === "replay" ? "[replay]" : "";
@@ -11579,7 +11750,10 @@ function hydrateCardsFromMessages(messages) {
11579
11750
  }
11580
11751
 
11581
11752
  // src/cli/ui/useCompletionPickers.ts
11582
- import { useCallback as useCallback8, useEffect as useEffect9, useMemo as useMemo8, useRef as useRef5, useState as useState16 } from "react";
11753
+ import { useCallback as useCallback8, useEffect as useEffect9, useMemo as useMemo8, useReducer as useReducer2, useRef as useRef5, useState as useState16 } from "react";
11754
+ var SEARCH_DEBOUNCE_MS = 80;
11755
+ var SEARCH_FLUSH_MS = 50;
11756
+ var SEARCH_RESULT_CAP = 200;
11583
11757
  function useCompletionPickers({
11584
11758
  input,
11585
11759
  setInput,
@@ -11607,22 +11781,6 @@ function useCompletionPickers({
11607
11781
  });
11608
11782
  }, [slashMatches]);
11609
11783
  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
11784
  const recentFilesRef = useRef5([]);
11627
11785
  const recordRecentFile = useCallback8((p) => {
11628
11786
  const list2 = recentFilesRef.current;
@@ -11636,25 +11794,50 @@ function useCompletionPickers({
11636
11794
  if (slashMatches !== null) return null;
11637
11795
  return detectAtPicker(input);
11638
11796
  }, [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]);
11797
+ const parsed = useMemo8(
11798
+ () => atPicker ? parseAtQuery(atPicker.query) : null,
11799
+ [atPicker]
11800
+ );
11801
+ const atMode = parsed ? parsed.trailingSlash || parsed.filter === "" ? "browse" : "search" : null;
11802
+ const browseDir = parsed && atMode === "browse" ? parsed.dir : "";
11803
+ const browse = useBrowseListing(rootDir, atMode === "browse" ? browseDir : null);
11804
+ const search = useStreamingSearch(
11805
+ rootDir,
11806
+ atMode === "search" && parsed ? parsed.filter : null,
11807
+ recentFilesRef
11808
+ );
11809
+ const atState = useMemo8(() => {
11810
+ if (!parsed) return null;
11811
+ if (atMode === "browse") {
11812
+ return {
11813
+ kind: "browse",
11814
+ baseDir: browseDir,
11815
+ entries: browse.entries,
11816
+ loading: browse.loading
11817
+ };
11818
+ }
11819
+ return {
11820
+ kind: "search",
11821
+ filter: parsed.filter,
11822
+ entries: search.entries,
11823
+ scanned: search.scanned,
11824
+ searching: search.searching
11825
+ };
11826
+ }, [parsed, atMode, browseDir, browse, search]);
11646
11827
  useEffect9(() => {
11647
11828
  setAtSelected((prev) => {
11648
- if (!atMatches || atMatches.length === 0) return 0;
11649
- if (prev >= atMatches.length) return atMatches.length - 1;
11829
+ const len = atState?.entries.length ?? 0;
11830
+ if (len === 0) return 0;
11831
+ if (prev >= len) return len - 1;
11650
11832
  return prev;
11651
11833
  });
11652
- }, [atMatches]);
11834
+ }, [atState]);
11653
11835
  const pickAtMention = useCallback8(
11654
- (chosenPath) => {
11836
+ (entry, action) => {
11655
11837
  if (!atPicker) return;
11656
11838
  const before = input.slice(0, atPicker.atOffset);
11657
- setInput(`${before}@${chosenPath} `);
11839
+ const tail = action === "drill" && entry.isDir ? `${entry.insertPath}/` : `${entry.insertPath} `;
11840
+ setInput(`${before}@${tail}`);
11658
11841
  },
11659
11842
  [atPicker, input, setInput]
11660
11843
  );
@@ -11725,8 +11908,7 @@ function useCompletionPickers({
11725
11908
  setSlashSelected,
11726
11909
  slashGroupMode,
11727
11910
  slashAdvancedHidden,
11728
- atPicker,
11729
- atMatches,
11911
+ atState,
11730
11912
  atSelected,
11731
11913
  setAtSelected,
11732
11914
  pickAtMention,
@@ -11738,6 +11920,113 @@ function useCompletionPickers({
11738
11920
  pickSlashArg
11739
11921
  };
11740
11922
  }
11923
+ function useBrowseListing(rootDir, dir) {
11924
+ const [entries, setEntries] = useState16([]);
11925
+ const [loading, setLoading] = useState16(false);
11926
+ useEffect9(() => {
11927
+ if (dir === null) {
11928
+ setEntries([]);
11929
+ setLoading(false);
11930
+ return;
11931
+ }
11932
+ let cancelled = false;
11933
+ setLoading(true);
11934
+ listDirectory(rootDir, dir).then(
11935
+ (raw) => {
11936
+ if (cancelled) return;
11937
+ setEntries(raw.map(toBrowseEntry));
11938
+ setLoading(false);
11939
+ },
11940
+ () => {
11941
+ if (cancelled) return;
11942
+ setEntries([]);
11943
+ setLoading(false);
11944
+ }
11945
+ );
11946
+ return () => {
11947
+ cancelled = true;
11948
+ };
11949
+ }, [rootDir, dir]);
11950
+ return { entries, loading };
11951
+ }
11952
+ function toBrowseEntry(d) {
11953
+ return { label: d.name, insertPath: d.path, dirSuffix: "", isDir: d.isDir };
11954
+ }
11955
+ function useStreamingSearch(rootDir, filter, recentFilesRef) {
11956
+ const [, bumpRender] = useReducer2((x) => x + 1, 0);
11957
+ const hitsRef = useRef5([]);
11958
+ const scannedRef = useRef5(0);
11959
+ const searchingRef = useRef5(false);
11960
+ const rankedRef = useRef5([]);
11961
+ useEffect9(() => {
11962
+ if (filter === null) {
11963
+ hitsRef.current = [];
11964
+ scannedRef.current = 0;
11965
+ searchingRef.current = false;
11966
+ rankedRef.current = [];
11967
+ bumpRender();
11968
+ return;
11969
+ }
11970
+ hitsRef.current = [];
11971
+ scannedRef.current = 0;
11972
+ searchingRef.current = true;
11973
+ rankedRef.current = [];
11974
+ bumpRender();
11975
+ const ac = new AbortController();
11976
+ let flushTimer = null;
11977
+ const scheduleFlush = () => {
11978
+ if (flushTimer) return;
11979
+ flushTimer = setTimeout(() => {
11980
+ flushTimer = null;
11981
+ rankedRef.current = rankSearchHits(hitsRef.current, filter, recentFilesRef.current ?? []);
11982
+ bumpRender();
11983
+ }, SEARCH_FLUSH_MS);
11984
+ };
11985
+ const debounce = setTimeout(() => {
11986
+ walkFilesStream(rootDir, {
11987
+ signal: ac.signal,
11988
+ onEntry: (e) => {
11989
+ hitsRef.current.push(e);
11990
+ if (hitsRef.current.length >= SEARCH_RESULT_CAP * 8) return false;
11991
+ scheduleFlush();
11992
+ },
11993
+ onProgress: (n) => {
11994
+ scannedRef.current = n;
11995
+ scheduleFlush();
11996
+ }
11997
+ }).then(() => {
11998
+ searchingRef.current = false;
11999
+ rankedRef.current = rankSearchHits(hitsRef.current, filter, recentFilesRef.current ?? []);
12000
+ bumpRender();
12001
+ });
12002
+ }, SEARCH_DEBOUNCE_MS);
12003
+ return () => {
12004
+ clearTimeout(debounce);
12005
+ if (flushTimer) clearTimeout(flushTimer);
12006
+ ac.abort();
12007
+ };
12008
+ }, [rootDir, filter, recentFilesRef]);
12009
+ return {
12010
+ entries: rankedRef.current,
12011
+ scanned: scannedRef.current,
12012
+ searching: searchingRef.current
12013
+ };
12014
+ }
12015
+ function rankSearchHits(hits, filter, recent) {
12016
+ const ranked = rankPickerCandidates(hits, filter, {
12017
+ limit: SEARCH_RESULT_CAP,
12018
+ recentlyUsed: recent
12019
+ });
12020
+ return ranked.map((path) => {
12021
+ const slash = path.lastIndexOf("/");
12022
+ return {
12023
+ label: slash >= 0 ? path.slice(slash + 1) : path,
12024
+ insertPath: path,
12025
+ dirSuffix: slash >= 0 ? `${path.slice(0, slash)}/` : "",
12026
+ isDir: false
12027
+ };
12028
+ });
12029
+ }
11741
12030
 
11742
12031
  // src/cli/ui/useEditHistory.ts
11743
12032
  import { useCallback as useCallback9, useRef as useRef6, useState as useState17 } from "react";
@@ -12162,13 +12451,13 @@ var PLAIN_UI = process.env.REASONIX_UI === "plain";
12162
12451
  function LoopStatusRow({
12163
12452
  loop: loop2
12164
12453
  }) {
12165
- const [, setTick] = React59.useState(0);
12166
- React59.useEffect(() => {
12454
+ const [, setTick] = React60.useState(0);
12455
+ React60.useEffect(() => {
12167
12456
  const id = setInterval(() => setTick((t2) => t2 + 1), 1e3);
12168
12457
  return () => clearInterval(id);
12169
12458
  }, []);
12170
12459
  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`));
12460
+ 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
12461
  }
12173
12462
  function App(props) {
12174
12463
  markPhase("app_render_start");
@@ -12177,11 +12466,12 @@ function App(props) {
12177
12466
  model: props.model,
12178
12467
  workspace: props.codeMode?.rootDir ?? process.cwd()
12179
12468
  });
12180
- const initialCards = React59.useMemo(
12469
+ const initialCards = React60.useMemo(
12181
12470
  () => props.session ? hydrateCardsFromMessages(loadSessionMessages(props.session)) : [],
12182
12471
  [props.session]
12183
12472
  );
12184
- return /* @__PURE__ */ React59.createElement(AgentStoreProvider, { session, initialCards }, /* @__PURE__ */ React59.createElement(AppInner, { ...props }));
12473
+ const themeName = resolveThemePreference(loadTheme(), process.env.REASONIX_THEME);
12474
+ return /* @__PURE__ */ React60.createElement(ThemeProvider, { name: themeName }, /* @__PURE__ */ React60.createElement(AgentStoreProvider, { session, initialCards }, /* @__PURE__ */ React60.createElement(AppInner, { ...props })));
12185
12475
  }
12186
12476
  function AppInner({
12187
12477
  model: model2,
@@ -12233,7 +12523,9 @@ function AppInner({
12233
12523
  if (!stdout || !stdout.isTTY) return;
12234
12524
  stdout.write("\x1B[?2004h");
12235
12525
  stdout.write("\x1B[>4;2m");
12526
+ stdout.write("\x1B[?1006h\x1B[?1000h");
12236
12527
  return () => {
12528
+ stdout.write("\x1B[?1000l\x1B[?1006l");
12237
12529
  stdout.write("\x1B[?2004l");
12238
12530
  stdout.write("\x1B[>4m");
12239
12531
  };
@@ -12621,8 +12913,7 @@ function AppInner({
12621
12913
  setSlashSelected,
12622
12914
  slashGroupMode,
12623
12915
  slashAdvancedHidden,
12624
- atPicker,
12625
- atMatches,
12916
+ atState,
12626
12917
  atSelected,
12627
12918
  setAtSelected,
12628
12919
  pickAtMention,
@@ -12695,14 +12986,20 @@ function AppInner({
12695
12986
  }
12696
12987
  }
12697
12988
  if (codeMode && !editModeHintShown()) {
12698
- log.pushInfo(t("ui.tipEditBindings"));
12989
+ const tip = tObj("ui.tipEditBindings");
12990
+ log.pushTip({ topic: tip.topic, sections: tip.sections, footer: tip.footer });
12699
12991
  markEditModeHintShown();
12700
12992
  }
12993
+ if (!mouseClipboardHintShown()) {
12994
+ const tip = tObj("ui.tipMouseClipboard");
12995
+ log.pushTip({ topic: tip.topic, sections: tip.sections, footer: tip.footer });
12996
+ markMouseClipboardHintShown();
12997
+ }
12701
12998
  }, [session, loop2, codeMode, syncPendingCount, log]);
12702
12999
  const quitProcess = useQuit(transcriptRef);
12703
13000
  useKeystroke((ev) => {
12704
- if (ev.pageUp) chatScroll.scrollUp();
12705
- else if (ev.pageDown) chatScroll.scrollDown();
13001
+ if (ev.pageUp || ev.mouseScrollUp) chatScroll.scrollUp();
13002
+ else if (ev.pageDown || ev.mouseScrollDown) chatScroll.scrollDown();
12706
13003
  else if (ev.end) chatScroll.jumpToBottom();
12707
13004
  else if ((!chatScroll.pinned || busy) && ev.upArrow) chatScroll.scrollUp();
12708
13005
  else if ((!chatScroll.pinned || busy) && ev.downArrow) chatScroll.scrollDown();
@@ -12734,7 +13031,7 @@ function AppInner({
12734
13031
  stopLoop();
12735
13032
  return;
12736
13033
  }
12737
- if (key.escape && !busy && (slashMatches || atMatches || slashArgContext)) {
13034
+ if (key.escape && !busy && (slashMatches || atState || slashArgContext)) {
12738
13035
  setInput("");
12739
13036
  return;
12740
13037
  }
@@ -12772,18 +13069,19 @@ function AppInner({
12772
13069
  }
12773
13070
  if (busy) return;
12774
13071
  if (pendingShell) return;
12775
- if (atMatches && atMatches.length > 0) {
13072
+ if (atState && atState.entries.length > 0) {
13073
+ const entries = atState.entries;
12776
13074
  if (key.upArrow) {
12777
13075
  setAtSelected((i) => Math.max(0, i - 1));
12778
13076
  return;
12779
13077
  }
12780
13078
  if (key.downArrow) {
12781
- setAtSelected((i) => Math.min(atMatches.length - 1, i + 1));
13079
+ setAtSelected((i) => Math.min(entries.length - 1, i + 1));
12782
13080
  return;
12783
13081
  }
12784
13082
  if (key.tab) {
12785
- const sel = atMatches[atSelected] ?? atMatches[0];
12786
- if (sel) pickAtMention(sel);
13083
+ const sel = entries[atSelected] ?? entries[0];
13084
+ if (sel) pickAtMention(sel, sel.isDir ? "drill" : "commit");
12787
13085
  return;
12788
13086
  }
12789
13087
  }
@@ -12919,7 +13217,7 @@ function AppInner({
12919
13217
  if (dashboardRef.current) return dashboardRef.current.url;
12920
13218
  if (dashboardStartingRef.current) return dashboardStartingRef.current;
12921
13219
  const startup = (async () => {
12922
- const { startDashboardServer } = await import("./server-SYC3OVOP.js");
13220
+ const { startDashboardServer } = await import("./server-MC4A4WAJ.js");
12923
13221
  const handle = await startDashboardServer({
12924
13222
  mode: "attached",
12925
13223
  configPath: defaultConfigPath(),
@@ -13227,10 +13525,10 @@ function AppInner({
13227
13525
  }
13228
13526
  clearFiringFlag();
13229
13527
  if (busy) return;
13230
- if (atMatches && atMatches.length > 0 && atPicker) {
13231
- const sel = atMatches[atSelected] ?? atMatches[0];
13528
+ if (atState && atState.entries.length > 0) {
13529
+ const sel = atState.entries[atSelected] ?? atState.entries[0];
13232
13530
  if (sel) {
13233
- pickAtMention(sel);
13531
+ pickAtMention(sel, "commit");
13234
13532
  return;
13235
13533
  }
13236
13534
  }
@@ -13358,6 +13656,12 @@ function AppInner({
13358
13656
  postInfo: (text2) => log.pushInfo(text2),
13359
13657
  postDoctor: (checks) => log.showDoctor(checks),
13360
13658
  postUsage: (args) => log.showUsageVerbose(args),
13659
+ postKeys: (args) => log.pushTip({
13660
+ topic: args.topic,
13661
+ sections: args.sections,
13662
+ footer: args.footer,
13663
+ oneTime: false
13664
+ }),
13361
13665
  dispatch: agentStore.dispatch,
13362
13666
  reloadHooks: () => {
13363
13667
  const fresh = loadHooks({ projectRoot: codeMode ? currentRootDir : void 0 });
@@ -13730,8 +14034,7 @@ function AppInner({
13730
14034
  planMode,
13731
14035
  session,
13732
14036
  slashSelected,
13733
- atMatches,
13734
- atPicker,
14037
+ atState,
13735
14038
  atSelected,
13736
14039
  pickAtMention,
13737
14040
  recordRecentFile,
@@ -14203,14 +14506,14 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14203
14506
  []
14204
14507
  );
14205
14508
  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(
14509
+ 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
14510
  CardStream,
14208
14511
  {
14209
14512
  suppressLive: modalOpen,
14210
14513
  scrollRows: chatScroll.scrollRows,
14211
14514
  onMaxScrollChange: chatScroll.setMaxScroll
14212
14515
  }
14213
- )), !hasConversation && !busy && !isStreaming ? /* @__PURE__ */ React59.createElement(
14516
+ )), !hasConversation && !busy && !isStreaming ? /* @__PURE__ */ React60.createElement(
14214
14517
  WelcomeBanner,
14215
14518
  {
14216
14519
  inCodeMode: !!codeMode,
@@ -14218,28 +14521,28 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14218
14521
  dashboardUrl,
14219
14522
  languageVersion
14220
14523
  }
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(
14524
+ ) : 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
14525
  PlanRefineInput,
14223
14526
  {
14224
14527
  mode: stagedInput.mode,
14225
14528
  onSubmit: handleStagedInputSubmit,
14226
14529
  onCancel: handleStagedInputCancel
14227
14530
  }
14228
- ) : stagedChoiceCustom ? /* @__PURE__ */ React59.createElement(
14531
+ ) : stagedChoiceCustom ? /* @__PURE__ */ React60.createElement(
14229
14532
  PlanRefineInput,
14230
14533
  {
14231
14534
  mode: "choice-custom",
14232
14535
  onSubmit: handleChoiceCustomSubmit,
14233
14536
  onCancel: handleChoiceCustomCancel
14234
14537
  }
14235
- ) : stagedCheckpointRevise ? /* @__PURE__ */ React59.createElement(
14538
+ ) : stagedCheckpointRevise ? /* @__PURE__ */ React60.createElement(
14236
14539
  PlanRefineInput,
14237
14540
  {
14238
14541
  mode: "checkpoint-revise",
14239
14542
  onSubmit: (text) => handleCheckpointReviseSubmit(text, stagedCheckpointRevise),
14240
14543
  onCancel: handleCheckpointReviseCancel
14241
14544
  }
14242
- ) : pendingChoice ? /* @__PURE__ */ React59.createElement(
14545
+ ) : pendingChoice ? /* @__PURE__ */ React60.createElement(
14243
14546
  ChoiceConfirm,
14244
14547
  {
14245
14548
  question: pendingChoice.question,
@@ -14247,7 +14550,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14247
14550
  allowCustom: pendingChoice.allowCustom,
14248
14551
  onChoose: stableHandleChoiceConfirm
14249
14552
  }
14250
- ) : pendingRevision ? /* @__PURE__ */ React59.createElement(
14553
+ ) : pendingRevision ? /* @__PURE__ */ React60.createElement(
14251
14554
  PlanReviseConfirm,
14252
14555
  {
14253
14556
  reason: pendingRevision.reason,
@@ -14258,7 +14561,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14258
14561
  summary: pendingRevision.summary,
14259
14562
  onChoose: stableHandleReviseConfirm
14260
14563
  }
14261
- ) : pendingCheckpoint ? /* @__PURE__ */ React59.createElement(
14564
+ ) : pendingCheckpoint ? /* @__PURE__ */ React60.createElement(
14262
14565
  PlanCheckpointConfirm,
14263
14566
  {
14264
14567
  stepId: pendingCheckpoint.stepId,
@@ -14269,7 +14572,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14269
14572
  completedStepIds: completedStepIdsRef.current,
14270
14573
  onChoose: stableHandleCheckpointConfirm
14271
14574
  }
14272
- ) : pendingCheckpointPicker ? /* @__PURE__ */ React59.createElement(
14575
+ ) : pendingCheckpointPicker ? /* @__PURE__ */ React60.createElement(
14273
14576
  CheckpointPicker,
14274
14577
  {
14275
14578
  checkpoints: checkpointPickerList,
@@ -14314,7 +14617,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14314
14617
  }
14315
14618
  }
14316
14619
  }
14317
- ) : pendingSessionsPicker ? /* @__PURE__ */ React59.createElement(
14620
+ ) : pendingSessionsPicker ? /* @__PURE__ */ React60.createElement(
14318
14621
  SessionPicker,
14319
14622
  {
14320
14623
  sessions: sessionsPickerList,
@@ -14359,7 +14662,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14359
14662
  }
14360
14663
  }
14361
14664
  }
14362
- ) : pendingModelPicker ? /* @__PURE__ */ React59.createElement(
14665
+ ) : pendingModelPicker ? /* @__PURE__ */ React60.createElement(
14363
14666
  ModelPicker,
14364
14667
  {
14365
14668
  models,
@@ -14391,7 +14694,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14391
14694
  }
14392
14695
  }
14393
14696
  }
14394
- ) : pendingMcpHub ? /* @__PURE__ */ React59.createElement(
14697
+ ) : pendingMcpHub ? /* @__PURE__ */ React60.createElement(
14395
14698
  McpHub,
14396
14699
  {
14397
14700
  initialTab: pendingMcpHub.tab,
@@ -14411,7 +14714,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14411
14714
  return r;
14412
14715
  } : void 0
14413
14716
  }
14414
- ) : pendingPlan ? /* @__PURE__ */ React59.createElement(
14717
+ ) : pendingPlan ? /* @__PURE__ */ React60.createElement(
14415
14718
  PlanConfirm,
14416
14719
  {
14417
14720
  plan: pendingPlan,
@@ -14420,7 +14723,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14420
14723
  onChoose: stableHandlePlanConfirm,
14421
14724
  projectRoot: currentRootDir
14422
14725
  }
14423
- ) : pendingReviseEditor ? /* @__PURE__ */ React59.createElement(
14726
+ ) : pendingReviseEditor ? /* @__PURE__ */ React60.createElement(
14424
14727
  PlanReviseEditor,
14425
14728
  {
14426
14729
  steps: planStepsRef.current ?? [],
@@ -14439,7 +14742,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14439
14742
  setPendingPlan(planText);
14440
14743
  }
14441
14744
  }
14442
- ) : pendingShell ? /* @__PURE__ */ React59.createElement(
14745
+ ) : pendingShell ? /* @__PURE__ */ React60.createElement(
14443
14746
  ShellConfirm,
14444
14747
  {
14445
14748
  command: pendingShell.command,
@@ -14447,7 +14750,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14447
14750
  kind: pendingShell.kind,
14448
14751
  onChoose: handleShellConfirm
14449
14752
  }
14450
- ) : pendingEditReview ? /* @__PURE__ */ React59.createElement(
14753
+ ) : pendingEditReview ? /* @__PURE__ */ React60.createElement(
14451
14754
  EditConfirm,
14452
14755
  {
14453
14756
  block: pendingEditReview,
@@ -14459,14 +14762,14 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14459
14762
  }
14460
14763
  }
14461
14764
  }
14462
- ) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */ React59.createElement(
14765
+ ) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */ React60.createElement(
14463
14766
  EditConfirm,
14464
14767
  {
14465
14768
  key: `walk-${pendingTick}`,
14466
14769
  block: pendingEdits.current[0],
14467
14770
  onChoose: handleWalkChoice
14468
14771
  }
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(
14772
+ ) : !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
14773
  ModeStatusBar,
14471
14774
  {
14472
14775
  editMode,
@@ -14476,7 +14779,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14476
14779
  undoArmed: !!undoBanner || hasUndoable(),
14477
14780
  jobs: codeMode.jobs
14478
14781
  }
14479
- ) : null, activeLoop ? /* @__PURE__ */ React59.createElement(LoopStatusRow, { loop: activeLoop }) : null, /* @__PURE__ */ React59.createElement(StatusRow, null), /* @__PURE__ */ React59.createElement(
14782
+ ) : null, activeLoop ? /* @__PURE__ */ React60.createElement(LoopStatusRow, { loop: activeLoop }) : null, /* @__PURE__ */ React60.createElement(StatusRow, null), /* @__PURE__ */ React60.createElement(
14480
14783
  PromptInput,
14481
14784
  {
14482
14785
  value: input,
@@ -14486,7 +14789,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14486
14789
  onHistoryPrev: recallPrev,
14487
14790
  onHistoryNext: recallNext
14488
14791
  }
14489
- ), slashMatches !== null ? /* @__PURE__ */ React59.createElement(
14792
+ ), slashMatches !== null ? /* @__PURE__ */ React60.createElement(
14490
14793
  SlashSuggestions,
14491
14794
  {
14492
14795
  matches: slashMatches,
@@ -14494,14 +14797,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14494
14797
  groupMode: slashGroupMode,
14495
14798
  advancedHidden: slashAdvancedHidden
14496
14799
  }
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(
14800
+ ) : null, atState !== null ? /* @__PURE__ */ React60.createElement(AtMentionSuggestions, { state: atState, selectedIndex: atSelected }) : null, slashArgContext ? /* @__PURE__ */ React60.createElement(
14505
14801
  SlashArgPicker,
14506
14802
  {
14507
14803
  matches: slashArgMatches,
@@ -14514,12 +14810,12 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14514
14810
  }
14515
14811
 
14516
14812
  // src/cli/ui/Setup.tsx
14517
- import { Box as Box49, Text as Text53, useApp } from "ink";
14518
- import React61, { useState as useState21 } from "react";
14813
+ import { Box as Box50, Text as Text54, useApp } from "ink";
14814
+ import React62, { useState as useState21 } from "react";
14519
14815
 
14520
14816
  // src/cli/ui/MaskedInput.tsx
14521
- import { Text as Text52, useInput } from "ink";
14522
- import React60, { useRef as useRef9 } from "react";
14817
+ import { Text as Text53, useInput } from "ink";
14818
+ import React61, { useRef as useRef9 } from "react";
14523
14819
  function stripPasteMarkers(s) {
14524
14820
  return s.replace(/\u001b?\[20[01]~/g, "").replace(/\u001b/g, "");
14525
14821
  }
@@ -14554,11 +14850,11 @@ function MaskedInput({
14554
14850
  });
14555
14851
  if (value.length === 0) {
14556
14852
  if (placeholder.length === 0) {
14557
- return /* @__PURE__ */ React60.createElement(Text52, { inverse: true }, " ");
14853
+ return /* @__PURE__ */ React61.createElement(Text53, { inverse: true }, " ");
14558
14854
  }
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)));
14855
+ 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
14856
  }
14561
- return /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(Text52, null, mask.repeat(value.length)), /* @__PURE__ */ React60.createElement(Text52, { inverse: true }, " "));
14857
+ return /* @__PURE__ */ React61.createElement(React61.Fragment, null, /* @__PURE__ */ React61.createElement(Text53, null, mask.repeat(value.length)), /* @__PURE__ */ React61.createElement(Text53, { inverse: true }, " "));
14562
14858
  }
14563
14859
 
14564
14860
  // src/cli/ui/Setup.tsx
@@ -14585,7 +14881,7 @@ function Setup({ onReady }) {
14585
14881
  }
14586
14882
  onReady(trimmed);
14587
14883
  };
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(
14884
+ 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
14885
  MaskedInput,
14590
14886
  {
14591
14887
  value,
@@ -14594,7 +14890,7 @@ function Setup({ onReady }) {
14594
14890
  mask: "\u2022",
14595
14891
  placeholder: "sk-..."
14596
14892
  }
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")));
14893
+ )), 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
14894
  }
14599
14895
 
14600
14896
  // src/cli/ui/drain-tty.ts
@@ -14805,7 +15101,7 @@ function Root({
14805
15101
  const workspaceRoot = appProps.codeMode?.rootDir ?? process.cwd();
14806
15102
  const [sessions2, setSessions] = useState22(() => listSessionsForWorkspace(workspaceRoot));
14807
15103
  if (!key) {
14808
- return /* @__PURE__ */ React62.createElement(
15104
+ return /* @__PURE__ */ React63.createElement(
14809
15105
  Setup,
14810
15106
  {
14811
15107
  onReady: (k) => {
@@ -14817,7 +15113,7 @@ function Root({
14817
15113
  }
14818
15114
  process.env.DEEPSEEK_API_KEY = key;
14819
15115
  if (pickerOpen) {
14820
- return /* @__PURE__ */ React62.createElement(KeystrokeProvider, null, /* @__PURE__ */ React62.createElement(
15116
+ return /* @__PURE__ */ React63.createElement(KeystrokeProvider, null, /* @__PURE__ */ React63.createElement(
14821
15117
  SessionPicker,
14822
15118
  {
14823
15119
  sessions: sessions2,
@@ -14850,7 +15146,7 @@ function Root({
14850
15146
  }
14851
15147
  ));
14852
15148
  }
14853
- return /* @__PURE__ */ React62.createElement(KeystrokeProvider, null, /* @__PURE__ */ React62.createElement(
15149
+ return /* @__PURE__ */ React63.createElement(KeystrokeProvider, null, /* @__PURE__ */ React63.createElement(
14854
15150
  App,
14855
15151
  {
14856
15152
  key: activeSession ?? "__new__",
@@ -14922,7 +15218,7 @@ async function chatCommand(opts) {
14922
15218
  const showPicker = !opts.session && !opts.forceResume && listSessionsForWorkspace(launchWorkspace).length > 0;
14923
15219
  markPhase("ink_render_call");
14924
15220
  const { waitUntilExit } = render(
14925
- /* @__PURE__ */ React62.createElement(
15221
+ /* @__PURE__ */ React63.createElement(
14926
15222
  Root,
14927
15223
  {
14928
15224
  initialKey,
@@ -14958,4 +15254,4 @@ async function chatCommand(opts) {
14958
15254
  export {
14959
15255
  chatCommand
14960
15256
  };
14961
- //# sourceMappingURL=chunk-OW7IHE6M.js.map
15257
+ //# sourceMappingURL=chunk-5SAMVHA3.js.map