reasonix 0.35.0 → 0.36.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 (80) hide show
  1. package/dashboard/dist/app.js +42 -3
  2. package/dashboard/dist/app.js.map +1 -1
  3. package/dist/cli/{chat-AB5D7I3V.js → chat-RGMYAOY2.js} +16 -15
  4. package/dist/cli/{chunk-RJ5GUVS2.js → chunk-2MCYGFLK.js} +10 -10
  5. package/dist/cli/chunk-2MCYGFLK.js.map +1 -0
  6. package/dist/cli/{chunk-SW3CCXEV.js → chunk-4Q3GRJIU.js} +2 -2
  7. package/dist/cli/{chunk-5JXXEPDM.js → chunk-BHLHOS5Y.js} +8 -2
  8. package/dist/cli/chunk-BHLHOS5Y.js.map +1 -0
  9. package/dist/cli/{chunk-IDP65VCC.js → chunk-BJ376EN3.js} +9 -8
  10. package/dist/cli/chunk-BJ376EN3.js.map +1 -0
  11. package/dist/cli/{chunk-2AWTGJ2C.js → chunk-CRPQUBP6.js} +26 -9
  12. package/dist/cli/{chunk-2AWTGJ2C.js.map → chunk-CRPQUBP6.js.map} +1 -1
  13. package/dist/cli/{chunk-GPHBJWCV.js → chunk-EN4LAZW5.js} +297 -171
  14. package/dist/cli/chunk-EN4LAZW5.js.map +1 -0
  15. package/dist/cli/{chunk-JJTOZPM3.js → chunk-IPCPEZWQ.js} +2 -2
  16. package/dist/cli/{chunk-SN7YH6FC.js → chunk-MLXUGPJE.js} +168 -35
  17. package/dist/cli/chunk-MLXUGPJE.js.map +1 -0
  18. package/dist/cli/{chunk-SX6L4HZZ.js → chunk-QPNZWUZF.js} +53 -6
  19. package/dist/cli/chunk-QPNZWUZF.js.map +1 -0
  20. package/dist/cli/{chunk-N2IC4XDL.js → chunk-QRUQ2BFT.js} +13 -8
  21. package/dist/cli/{chunk-N2IC4XDL.js.map → chunk-QRUQ2BFT.js.map} +1 -1
  22. package/dist/cli/{chunk-KZHMKOJH.js → chunk-T52GAWPP.js} +25 -3
  23. package/dist/cli/chunk-T52GAWPP.js.map +1 -0
  24. package/dist/cli/{chunk-I6YIAK6C.js → chunk-UNMYFZPZ.js} +2 -2
  25. package/dist/cli/{update-4TJWRUIN.js → chunk-WJ3YX4PZ.js} +51 -12
  26. package/dist/cli/chunk-WJ3YX4PZ.js.map +1 -0
  27. package/dist/cli/{chunk-RXGEGA7K.js → chunk-XQIFIB3U.js} +18 -7
  28. package/dist/cli/{chunk-RXGEGA7K.js.map → chunk-XQIFIB3U.js.map} +1 -1
  29. package/dist/cli/{chunk-2EBODRRO.js → chunk-ZJR4QLXB.js} +5 -1
  30. package/dist/cli/{chunk-2EBODRRO.js.map → chunk-ZJR4QLXB.js.map} +1 -1
  31. package/dist/cli/{code-XBEFHXVM.js → code-KJB3WDU6.js} +19 -17
  32. package/dist/cli/code-KJB3WDU6.js.map +1 -0
  33. package/dist/cli/{commands-MEZPSEHV.js → commands-FE2UDFBC.js} +3 -3
  34. package/dist/cli/{commit-CE4EFTUQ.js → commit-3IAGB22T.js} +5 -4
  35. package/dist/cli/commit-3IAGB22T.js.map +1 -0
  36. package/dist/cli/{doctor-A565GMWD.js → doctor-DKD34EFD.js} +7 -7
  37. package/dist/cli/index.js +33 -31
  38. package/dist/cli/index.js.map +1 -1
  39. package/dist/cli/{mcp-LDFK5QJI.js → mcp-2RDEQST6.js} +2 -2
  40. package/dist/cli/{mcp-browse-FYHEITCM.js → mcp-browse-VM5GLRBQ.js} +2 -2
  41. package/dist/cli/{mcp-inspect-T2HBR22P.js → mcp-inspect-CWSVCZUQ.js} +3 -3
  42. package/dist/cli/{replay-P2WC5N5X.js → replay-D7RT2DR7.js} +2 -2
  43. package/dist/cli/{run-QBWJETS3.js → run-FK5UBIIM.js} +11 -10
  44. package/dist/cli/run-FK5UBIIM.js.map +1 -0
  45. package/dist/cli/{server-SMLVXIW4.js → server-W4XJK4GX.js} +16 -16
  46. package/dist/cli/{server-SMLVXIW4.js.map → server-W4XJK4GX.js.map} +1 -1
  47. package/dist/cli/{sessions-55RIZVWG.js → sessions-YZXWMIWW.js} +8 -8
  48. package/dist/cli/{setup-QXMONZ4P.js → setup-IIAJXHP4.js} +196 -130
  49. package/dist/cli/setup-IIAJXHP4.js.map +1 -0
  50. package/dist/cli/update-GUCWB4UN.js +13 -0
  51. package/dist/cli/update-GUCWB4UN.js.map +1 -0
  52. package/dist/cli/{version-Q2HA3AAC.js → version-DWD6RLIU.js} +10 -10
  53. package/dist/index.d.ts +14 -2
  54. package/dist/index.js +270 -47
  55. package/dist/index.js.map +1 -1
  56. package/package.json +1 -1
  57. package/dist/cli/chunk-5JXXEPDM.js.map +0 -1
  58. package/dist/cli/chunk-GPHBJWCV.js.map +0 -1
  59. package/dist/cli/chunk-IDP65VCC.js.map +0 -1
  60. package/dist/cli/chunk-KZHMKOJH.js.map +0 -1
  61. package/dist/cli/chunk-RJ5GUVS2.js.map +0 -1
  62. package/dist/cli/chunk-SN7YH6FC.js.map +0 -1
  63. package/dist/cli/chunk-SX6L4HZZ.js.map +0 -1
  64. package/dist/cli/code-XBEFHXVM.js.map +0 -1
  65. package/dist/cli/commit-CE4EFTUQ.js.map +0 -1
  66. package/dist/cli/run-QBWJETS3.js.map +0 -1
  67. package/dist/cli/setup-QXMONZ4P.js.map +0 -1
  68. package/dist/cli/update-4TJWRUIN.js.map +0 -1
  69. /package/dist/cli/{chat-AB5D7I3V.js.map → chat-RGMYAOY2.js.map} +0 -0
  70. /package/dist/cli/{chunk-SW3CCXEV.js.map → chunk-4Q3GRJIU.js.map} +0 -0
  71. /package/dist/cli/{chunk-JJTOZPM3.js.map → chunk-IPCPEZWQ.js.map} +0 -0
  72. /package/dist/cli/{chunk-I6YIAK6C.js.map → chunk-UNMYFZPZ.js.map} +0 -0
  73. /package/dist/cli/{commands-MEZPSEHV.js.map → commands-FE2UDFBC.js.map} +0 -0
  74. /package/dist/cli/{doctor-A565GMWD.js.map → doctor-DKD34EFD.js.map} +0 -0
  75. /package/dist/cli/{mcp-LDFK5QJI.js.map → mcp-2RDEQST6.js.map} +0 -0
  76. /package/dist/cli/{mcp-browse-FYHEITCM.js.map → mcp-browse-VM5GLRBQ.js.map} +0 -0
  77. /package/dist/cli/{mcp-inspect-T2HBR22P.js.map → mcp-inspect-CWSVCZUQ.js.map} +0 -0
  78. /package/dist/cli/{replay-P2WC5N5X.js.map → replay-D7RT2DR7.js.map} +0 -0
  79. /package/dist/cli/{sessions-55RIZVWG.js.map → sessions-YZXWMIWW.js.map} +0 -0
  80. /package/dist/cli/{version-Q2HA3AAC.js.map → version-DWD6RLIU.js.map} +0 -0
@@ -34,7 +34,7 @@ import {
34
34
  toWholeFileEditBlock,
35
35
  walkFilesStream,
36
36
  webFetch
37
- } from "./chunk-N2IC4XDL.js";
37
+ } from "./chunk-QRUQ2BFT.js";
38
38
  import {
39
39
  McpClient,
40
40
  SseTransport,
@@ -42,7 +42,7 @@ import {
42
42
  StreamableHttpTransport,
43
43
  inspectMcpServer,
44
44
  parseMcpSpec
45
- } from "./chunk-I6YIAK6C.js";
45
+ } from "./chunk-UNMYFZPZ.js";
46
46
  import {
47
47
  openTranscriptFile,
48
48
  recordFromLoopEvent,
@@ -55,7 +55,7 @@ import {
55
55
  KeystrokeProvider,
56
56
  SingleSelect,
57
57
  useKeystroke
58
- } from "./chunk-KZHMKOJH.js";
58
+ } from "./chunk-T52GAWPP.js";
59
59
  import {
60
60
  COLOR,
61
61
  GLYPH,
@@ -63,7 +63,7 @@ import {
63
63
  ThemeProvider,
64
64
  useColor,
65
65
  useThemeTokens
66
- } from "./chunk-2EBODRRO.js";
66
+ } from "./chunk-ZJR4QLXB.js";
67
67
  import {
68
68
  PRESETS,
69
69
  PRESET_DESCRIPTIONS,
@@ -71,7 +71,7 @@ import {
71
71
  } from "./chunk-MHDNZXJJ.js";
72
72
  import {
73
73
  runDoctorChecks
74
- } from "./chunk-IDP65VCC.js";
74
+ } from "./chunk-BJ376EN3.js";
75
75
  import {
76
76
  countTokens
77
77
  } from "./chunk-DAEAAVDF.js";
@@ -84,6 +84,10 @@ import {
84
84
  import {
85
85
  renderDashboard
86
86
  } from "./chunk-4DCHFFEY.js";
87
+ import {
88
+ MANUAL_UPDATE_COMMANDS,
89
+ planUpdate
90
+ } from "./chunk-WJ3YX4PZ.js";
87
91
  import {
88
92
  SLASH_COMMANDS,
89
93
  archivePlanState,
@@ -97,23 +101,23 @@ import {
97
101
  resolveSlashAlias,
98
102
  savePlanState,
99
103
  suggestSlashCommands
100
- } from "./chunk-RJ5GUVS2.js";
101
- import {
102
- eventLogPath,
103
- openEventSink
104
- } from "./chunk-G3XNWSFN.js";
104
+ } from "./chunk-2MCYGFLK.js";
105
105
  import {
106
106
  fetchSmitheryDetail,
107
107
  loadMorePages,
108
108
  openRegistry,
109
109
  specStringFor
110
110
  } from "./chunk-SOZE7V7V.js";
111
+ import {
112
+ eventLogPath,
113
+ openEventSink
114
+ } from "./chunk-G3XNWSFN.js";
111
115
  import {
112
116
  BUILTIN_ALLOWLIST,
113
117
  formatCommandResult,
114
118
  pauseGate,
115
119
  runCommand
116
- } from "./chunk-SX6L4HZZ.js";
120
+ } from "./chunk-QPNZWUZF.js";
117
121
  import {
118
122
  PROJECT_MEMORY_FILE,
119
123
  SkillStore,
@@ -127,13 +131,7 @@ import {
127
131
  loadHooks,
128
132
  projectSettingsPath,
129
133
  runHooks
130
- } from "./chunk-JJTOZPM3.js";
131
- import {
132
- VERSION,
133
- compareVersions,
134
- getLatestVersion,
135
- isNpxInstall
136
- } from "./chunk-2AWTGJ2C.js";
134
+ } from "./chunk-IPCPEZWQ.js";
137
135
  import {
138
136
  deleteSession,
139
137
  detectGitBranch,
@@ -154,7 +152,7 @@ import {
154
152
  setLanguage,
155
153
  t,
156
154
  tObj
157
- } from "./chunk-SN7YH6FC.js";
155
+ } from "./chunk-MLXUGPJE.js";
158
156
  import {
159
157
  addProjectShellAllowed,
160
158
  clearProjectShellAllowed,
@@ -162,6 +160,7 @@ import {
162
160
  editModeHintShown,
163
161
  isPlausibleKey,
164
162
  loadApiKey,
163
+ loadBaseUrl,
165
164
  loadEditMode,
166
165
  loadProjectShellAllowed,
167
166
  loadReasoningEffort,
@@ -181,7 +180,7 @@ import {
181
180
  webSearchEndpoint,
182
181
  webSearchEngine,
183
182
  writeConfig
184
- } from "./chunk-5JXXEPDM.js";
183
+ } from "./chunk-BHLHOS5Y.js";
185
184
  import {
186
185
  CARD,
187
186
  FG,
@@ -205,6 +204,13 @@ import {
205
204
  DEEPSEEK_PRICING,
206
205
  DEFAULT_CONTEXT_TOKENS
207
206
  } from "./chunk-ORM6PK57.js";
207
+ import {
208
+ VERSION,
209
+ compareVersions,
210
+ detectInstallSource,
211
+ detectNpmInstallPrefix,
212
+ getLatestVersion
213
+ } from "./chunk-CRPQUBP6.js";
208
214
 
209
215
  // src/cli/commands/chat.tsx
210
216
  import { render } from "ink";
@@ -231,7 +237,7 @@ function buildMcpServerSummary(opts) {
231
237
  // src/cli/ui/App.tsx
232
238
  import { statSync } from "fs";
233
239
  import { resolve as resolve2 } from "path";
234
- import { Box as Box49, Text as Text52, useStdout as useStdout14 } from "ink";
240
+ import { Box as Box49, Text as Text52, useStdout as useStdout15 } from "ink";
235
241
  import React60, { useCallback as useCallback11, useEffect as useEffect12, useMemo as useMemo9, useRef as useRef9, useState as useState20 } from "react";
236
242
 
237
243
  // src/code/checkpoints.ts
@@ -5322,9 +5328,17 @@ function processMultilineKey(value, cursor, keyIn) {
5322
5328
  return cursor === value.length ? NOOP : { next: null, cursor: value.length, submit: false };
5323
5329
  }
5324
5330
  if (key.ctrl && key.input === "p") {
5331
+ if (value.includes("\n")) {
5332
+ const moved = moveCursorUp(value, cursor);
5333
+ if (moved !== cursor) return { next: null, cursor: moved, submit: false };
5334
+ }
5325
5335
  return { ...NOOP, historyHandoff: "prev" };
5326
5336
  }
5327
5337
  if (key.ctrl && key.input === "n") {
5338
+ if (value.includes("\n")) {
5339
+ const moved = moveCursorDown(value, cursor);
5340
+ if (moved !== cursor) return { next: null, cursor: moved, submit: false };
5341
+ }
5328
5342
  return { ...NOOP, historyHandoff: "next" };
5329
5343
  }
5330
5344
  if (key.leftArrow) {
@@ -5333,15 +5347,8 @@ function processMultilineKey(value, cursor, keyIn) {
5333
5347
  if (key.rightArrow) {
5334
5348
  return { next: null, cursor: Math.min(value.length, cursor + 1), submit: false };
5335
5349
  }
5336
- if (key.upArrow) {
5337
- if (value.length === 0) return { ...NOOP, historyHandoff: "prev" };
5338
- const moved = moveCursorUp(value, cursor);
5339
- return moved === cursor ? NOOP : { next: null, cursor: moved, submit: false };
5340
- }
5341
- if (key.downArrow) {
5342
- if (value.length === 0) return { ...NOOP, historyHandoff: "next" };
5343
- const moved = moveCursorDown(value, cursor);
5344
- return moved === cursor ? NOOP : { next: null, cursor: moved, submit: false };
5350
+ if (key.upArrow || key.downArrow) {
5351
+ return NOOP;
5345
5352
  }
5346
5353
  if (key.ctrl && key.input === "a" || key.home) {
5347
5354
  return { next: null, cursor: startOfLine(value, cursor), submit: false };
@@ -5907,7 +5914,8 @@ function HintRow() {
5907
5914
  const items = [
5908
5915
  { key: "\u23CE", sep: "send" },
5909
5916
  { key: "\u21E7\u23CE", sep: "newline" },
5910
- { key: "\u2191\u2193", sep: "history" },
5917
+ { key: "\u2191\u2193", sep: "scroll" },
5918
+ { key: "^P/^N", sep: "history" },
5911
5919
  { key: "esc", sep: "abort" },
5912
5920
  { key: "^C", sep: "quit" }
5913
5921
  ];
@@ -6423,8 +6431,12 @@ function ArgRow({ value, isSelected }) {
6423
6431
  }
6424
6432
 
6425
6433
  // src/cli/ui/SlashSuggestions.tsx
6426
- import { Box as Box23, Text as Text23 } from "ink";
6434
+ import { Box as Box23, Text as Text23, useStdout as useStdout8 } from "ink";
6427
6435
  import React27 from "react";
6436
+ var GROUP_MODE_MAX_ROWS = 24;
6437
+ var SEARCH_MODE_MAX_ROWS = 8;
6438
+ var COMMAND_NAME_CELLS = 14;
6439
+ var ARGS_CELLS = 14;
6428
6440
  var GROUP_LABEL = {
6429
6441
  chat: "CHAT",
6430
6442
  setup: "SETUP",
@@ -6442,26 +6454,82 @@ function SlashSuggestions({
6442
6454
  advancedHidden
6443
6455
  }) {
6444
6456
  const color = useColor();
6457
+ const { stdout } = useStdout8();
6458
+ const cols = stdout?.columns ?? 80;
6459
+ const [rememberedWindowStart, setRememberedWindowStart] = React27.useState(0);
6460
+ const maxRows = groupMode ? GROUP_MODE_MAX_ROWS : SEARCH_MODE_MAX_ROWS;
6461
+ const safeMatches = matches ?? [];
6462
+ const windowStart = computeWindowStart(
6463
+ safeMatches,
6464
+ maxRows,
6465
+ selectedIndex,
6466
+ rememberedWindowStart,
6467
+ groupMode
6468
+ );
6469
+ React27.useEffect(() => {
6470
+ setRememberedWindowStart(windowStart);
6471
+ }, [windowStart]);
6445
6472
  if (matches === null) return null;
6446
6473
  if (matches.length === 0) {
6447
6474
  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"));
6448
6475
  }
6449
- const MAX = groupMode ? 24 : 8;
6450
6476
  const total = matches.length;
6451
- const windowStart = total <= MAX ? 0 : Math.max(0, Math.min(selectedIndex - Math.floor(MAX / 2), total - MAX));
6452
- const shown = matches.slice(windowStart, windowStart + MAX);
6477
+ const items = buildVisibleItems(matches, windowStart, maxRows, groupMode);
6478
+ const shownCommands = items.filter((item) => item.kind === "command");
6453
6479
  const hiddenAbove = windowStart;
6454
- const hiddenBelow = total - windowStart - shown.length;
6455
- let lastGroup = null;
6456
- if (windowStart > 0) lastGroup = matches[windowStart - 1]?.group ?? null;
6457
- 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) => {
6458
- const idx = windowStart + i;
6459
- const showHeader = groupMode && spec.group !== lastGroup;
6460
- lastGroup = spec.group;
6461
- return /* @__PURE__ */ React27.createElement(React27.Fragment, { key: spec.cmd }, showHeader ? /* @__PURE__ */ React27.createElement(Box23, { marginTop: idx === 0 ? 0 : 1 }, /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, ` ${GROUP_LABEL[spec.group]}`)) : null, /* @__PURE__ */ React27.createElement(SuggestionRow, { spec, isSelected: idx === selectedIndex }));
6480
+ const hiddenBelow = total - windowStart - shownCommands.length;
6481
+ return /* @__PURE__ */ React27.createElement(Box23, { flexDirection: "column", paddingX: 1, marginTop: 1, flexShrink: 0, flexWrap: "nowrap" }, /* @__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), items.map((item) => {
6482
+ if (item.kind === "group") {
6483
+ return /* @__PURE__ */ React27.createElement(GroupHeader, { key: `group:${item.group}:${item.beforeIndex}`, group: item.group });
6484
+ }
6485
+ return /* @__PURE__ */ React27.createElement(
6486
+ SuggestionRow,
6487
+ {
6488
+ key: `cmd:${item.spec.group}:${item.spec.cmd}`,
6489
+ spec: item.spec,
6490
+ isSelected: item.index === selectedIndex,
6491
+ columns: cols
6492
+ }
6493
+ );
6462
6494
  }), 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")));
6463
6495
  }
6464
- function SuggestionRow({ spec, isSelected }) {
6496
+ function computeWindowStart(matches, maxRows, selectedIndex, currentWindowStart, groupMode = false) {
6497
+ if (matches.length <= 0) return 0;
6498
+ const maxWindowStart = Math.max(0, matches.length - 1);
6499
+ let start = Math.max(0, Math.min(currentWindowStart, maxWindowStart));
6500
+ const clampedSelectedIndex = Math.max(0, Math.min(selectedIndex, matches.length - 1));
6501
+ if (clampedSelectedIndex < start) start = clampedSelectedIndex;
6502
+ while (start < clampedSelectedIndex) {
6503
+ const visibleCommandIndexes = buildVisibleItems(matches, start, maxRows, groupMode).filter((item) => item.kind === "command").map((item) => item.index);
6504
+ if (visibleCommandIndexes.includes(clampedSelectedIndex)) break;
6505
+ start += 1;
6506
+ }
6507
+ return Math.min(start, maxWindowStart);
6508
+ }
6509
+ function buildVisibleItems(matches, windowStart, maxRows, groupMode = false) {
6510
+ const out = [];
6511
+ for (let idx = windowStart; idx < matches.length && out.length < maxRows; idx += 1) {
6512
+ const spec = matches[idx];
6513
+ if (groupMode && shouldShowGroupHeader(matches, idx)) {
6514
+ if (out.length >= maxRows) break;
6515
+ out.push({ kind: "group", group: spec.group, beforeIndex: idx });
6516
+ }
6517
+ if (out.length >= maxRows) break;
6518
+ out.push({ kind: "command", spec, index: idx });
6519
+ }
6520
+ return out;
6521
+ }
6522
+ function shouldShowGroupHeader(matches, idx) {
6523
+ return idx === 0 || matches[idx]?.group !== matches[idx - 1]?.group;
6524
+ }
6525
+ function GroupHeader({ group }) {
6526
+ return /* @__PURE__ */ React27.createElement(Box23, { flexShrink: 0, height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React27.createElement(Text23, { dimColor: true, wrap: "truncate" }, ` ${GROUP_LABEL[group]}`));
6527
+ }
6528
+ function SuggestionRow({
6529
+ spec,
6530
+ isSelected,
6531
+ columns
6532
+ }) {
6465
6533
  const color = useColor();
6466
6534
  const name = `/${spec.cmd}`;
6467
6535
  const argsSuffix = spec.argsHint ? spec.argsHint : "";
@@ -6469,7 +6537,19 @@ function SuggestionRow({ spec, isSelected }) {
6469
6537
  const translated = t(key);
6470
6538
  const summary = translated === key ? spec.summary : translated;
6471
6539
  const aliasHint = spec.aliases?.length ? ` \xB7 /${spec.aliases.join(" /")}` : "";
6472
- 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);
6540
+ const reservedCells = 2 + COMMAND_NAME_CELLS + ARGS_CELLS + 2 + 2;
6541
+ const summaryBudget = Math.max(8, columns - reservedCells);
6542
+ const summaryText = truncateCells(`${summary}${aliasHint}`, summaryBudget);
6543
+ return /* @__PURE__ */ React27.createElement(Box23, { flexDirection: "row", flexWrap: "nowrap", flexShrink: 0, height: 1, minHeight: 1 }, /* @__PURE__ */ React27.createElement(Text23, { color: isSelected ? color.primary : color.info, bold: isSelected, wrap: "truncate" }, isSelected ? `${GLYPH.cur} ` : " "), /* @__PURE__ */ React27.createElement(Text23, { color: color.accent, bold: isSelected, wrap: "truncate" }, padOrTrim(name, COMMAND_NAME_CELLS)), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true, wrap: "truncate" }, padOrTrim(argsSuffix, ARGS_CELLS)), /* @__PURE__ */ React27.createElement(Text23, { wrap: "truncate" }, " "), /* @__PURE__ */ React27.createElement(Text23, { color: isSelected ? color.user : color.info, dimColor: !isSelected, wrap: "truncate" }, summaryText));
6544
+ }
6545
+ function padOrTrim(value, cells) {
6546
+ const trimmed = truncateCells(value, cells);
6547
+ return trimmed.padEnd(cells);
6548
+ }
6549
+ function truncateCells(value, maxCells) {
6550
+ if (value.length <= maxCells) return value;
6551
+ if (maxCells <= 1) return value.slice(0, Math.max(0, maxCells));
6552
+ return `${value.slice(0, maxCells - 1)}\u2026`;
6473
6553
  }
6474
6554
 
6475
6555
  // src/cli/ui/WelcomeBanner.tsx
@@ -7838,10 +7918,16 @@ function CtxCard({ card }) {
7838
7918
  {
7839
7919
  glyph: "\u2318",
7840
7920
  tone: TONE.brand,
7841
- title: "context",
7921
+ title: t("cardTitles.context"),
7842
7922
  meta: [`${used.toLocaleString()} / ${cap.toLocaleString()} (${usedPct.toFixed(1)}%)`]
7843
7923
  }
7844
- ), row("system", card.systemTokens, card.systemTokens / cap, TONE.brand), row("tools", card.toolsTokens, card.toolsTokens / cap, TONE.warn), row("log", card.logTokens, card.logTokens / cap, TONE.ok), row("input", card.inputTokens, card.inputTokens / cap, TONE.accent), card.topTools.length > 0 ? /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement(Text26, { color: FG.faint }, `top tools \xB7 ${card.toolsCount} total \xB7 ${card.logMessages} log msgs`), card.topTools.slice(0, 5).map((t2) => /* @__PURE__ */ React32.createElement(Box27, { key: `${t2.turn}-${t2.name}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React32.createElement(Text26, { color: FG.sub }, t2.name), /* @__PURE__ */ React32.createElement(Text26, { color: FG.faint }, `\xB7 turn ${t2.turn} \xB7 ${t2.tokens.toLocaleString()}`)))) : null);
7924
+ ), row(t("cardLabels.system"), card.systemTokens, card.systemTokens / cap, TONE.brand), row(t("cardLabels.tools"), card.toolsTokens, card.toolsTokens / cap, TONE.warn), row(t("cardLabels.log"), card.logTokens, card.logTokens / cap, TONE.ok), row(t("cardLabels.input"), card.inputTokens, card.inputTokens / cap, TONE.accent), card.topTools.length > 0 ? /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement(Text26, { color: FG.faint }, `${t("cardLabels.topTools")} \xB7 ${card.toolsCount} ${t("cardLabels.tools")} \xB7 ${card.logMessages} ${t("cardLabels.logMsgs")}`), card.topTools.slice(0, 5).map((tool) => /* @__PURE__ */ React32.createElement(Box27, { key: `${tool.turn}-${tool.name}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React32.createElement(Text26, { color: FG.sub }, tool.name), /* @__PURE__ */ React32.createElement(
7925
+ Text26,
7926
+ {
7927
+ color: FG.faint
7928
+ },
7929
+ `\xB7 ${t("cardLabels.turn")} ${tool.turn} \xB7 ${tool.tokens.toLocaleString()}`
7930
+ )))) : null);
7845
7931
  }
7846
7932
 
7847
7933
  // src/cli/ui/cards/DiffCard.tsx
@@ -7909,7 +7995,7 @@ import { Box as Box30, Text as Text29 } from "ink";
7909
7995
  import React35 from "react";
7910
7996
  var STACK_TAIL = 5;
7911
7997
  function ErrorCard({ card }) {
7912
- const retryNote = card.retries !== void 0 && card.retries > 0 ? `${card.retries} retr${card.retries === 1 ? "y" : "ies"}` : null;
7998
+ const retryNote = card.retries !== void 0 && card.retries > 0 ? `${card.retries} ${t("cardLabels.retries")}` : null;
7913
7999
  const stackLines = card.stack ? card.stack.split("\n") : [];
7914
8000
  const stackTrunc = stackLines.length > STACK_TAIL;
7915
8001
  const stackVisible = stackTrunc ? stackLines.slice(-STACK_TAIL) : stackLines;
@@ -7921,10 +8007,13 @@ function ErrorCard({ card }) {
7921
8007
  {
7922
8008
  glyph: "\u2716",
7923
8009
  tone: TONE.err,
7924
- title: card.title || "error",
8010
+ title: card.title || t("cardTitles.error"),
7925
8011
  meta: retryNote ? [retryNote] : void 0
7926
8012
  }
7927
- ), messageLines.map((line, i) => /* @__PURE__ */ React35.createElement(Text29, { key: `${card.id}:msg:${i}`, color: TONE.err }, line || " ")), hasStack ? /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text29, { color: FG.meta }, "stack trace"), stackHidden > 0 ? /* @__PURE__ */ React35.createElement(Text29, { color: FG.faint }, `\u22EE ${stackHidden} earlier stack line${stackHidden === 1 ? "" : "s"} hidden`) : null, stackVisible.map((line, i) => /* @__PURE__ */ React35.createElement(Text29, { key: `${card.id}:stk:${stackHidden + i}`, color: FG.meta }, line || " "))) : null);
8013
+ ), messageLines.map((line, i) => /* @__PURE__ */ React35.createElement(Text29, { key: `${card.id}:msg:${i}`, color: TONE.err }, line || " ")), hasStack ? /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text29, { color: FG.meta }, t("cardLabels.stackTrace")), stackHidden > 0 ? /* @__PURE__ */ React35.createElement(Text29, { color: FG.faint }, t(
8014
+ stackHidden === 1 ? "cardLabels.earlierStackLine" : "cardLabels.earlierStackLines",
8015
+ { count: stackHidden }
8016
+ )) : null, stackVisible.map((line, i) => /* @__PURE__ */ React35.createElement(Text29, { key: `${card.id}:stk:${stackHidden + i}`, color: FG.meta }, line || " "))) : null);
7928
8017
  }
7929
8018
 
7930
8019
  // src/cli/ui/cards/LiveCard.tsx
@@ -8090,7 +8179,7 @@ function anchorIndex(steps) {
8090
8179
  }
8091
8180
 
8092
8181
  // src/cli/ui/cards/ReasoningCard.tsx
8093
- import { Box as Box34, Text as Text35, useStdout as useStdout8 } from "ink";
8182
+ import { Box as Box34, Text as Text35, useStdout as useStdout9 } from "ink";
8094
8183
  import React41 from "react";
8095
8184
 
8096
8185
  // src/frame/width.ts
@@ -8157,7 +8246,7 @@ function ReasoningCard({
8157
8246
  card,
8158
8247
  expanded
8159
8248
  }) {
8160
- const { stdout } = useStdout8();
8249
+ const { stdout } = useStdout9();
8161
8250
  const cols = stdout?.columns ?? 80;
8162
8251
  const lineCells = Math.max(20, cols - 4);
8163
8252
  const allLines = card.text.length > 0 ? card.text.split("\n") : [];
@@ -8169,7 +8258,7 @@ function ReasoningHeader({ card }) {
8169
8258
  const streamingActive = card.streaming && !card.aborted;
8170
8259
  const headColor = card.aborted ? TONE.err : streamingActive ? TONE_ACTIVE.accent : TONE.accent;
8171
8260
  const glyph = streamingActive ? "\u25C7" : "\u25C6";
8172
- const title = streamingActive ? "reasoning\u2026" : card.aborted ? "reasoning (aborted)" : "reasoning";
8261
+ const title = streamingActive ? t("cardTitles.reasoningEllipsis") : card.aborted ? t("cardTitles.reasoningAborted") : t("cardTitles.reasoning");
8173
8262
  const meta = [];
8174
8263
  const m = headerMeta(card);
8175
8264
  if (m) meta.push(m);
@@ -8191,11 +8280,11 @@ function ReasoningHeader({ card }) {
8191
8280
  }
8192
8281
  function headerMeta(card) {
8193
8282
  if (card.streaming) {
8194
- return card.tokens > 0 ? `${card.tokens.toLocaleString()} tok` : "";
8283
+ return card.tokens > 0 ? `${card.tokens.toLocaleString()} ${t("cardLabels.tok")}` : "";
8195
8284
  }
8196
8285
  const parts = [];
8197
- if (card.tokens > 0) parts.push(`${card.tokens.toLocaleString()} tok`);
8198
- if (card.paragraphs > 0) parts.push(`${card.paragraphs} \xB6`);
8286
+ if (card.tokens > 0) parts.push(`${card.tokens.toLocaleString()} ${t("cardLabels.tok")}`);
8287
+ if (card.paragraphs > 0) parts.push(`${card.paragraphs} ${t("cardLabels.pilcrow")}`);
8199
8288
  return parts.join(" \xB7 ");
8200
8289
  }
8201
8290
  function headerDuration(card) {
@@ -8246,18 +8335,24 @@ import React42 from "react";
8246
8335
  function SearchCard({ card }) {
8247
8336
  const fileCount = new Set(card.hits.map((h) => h.file)).size;
8248
8337
  const elapsed = `${(card.elapsedMs / 1e3).toFixed(2)}s`;
8249
- const stats2 = `${card.hits.length} hit${card.hits.length === 1 ? "" : "s"} \xB7 ${fileCount} file${fileCount === 1 ? "" : "s"}`;
8338
+ const stats2 = t(card.hits.length === 1 ? "cardLabels.hitSingular" : "cardLabels.hitsPlural", {
8339
+ count: card.hits.length,
8340
+ files: fileCount
8341
+ });
8250
8342
  const grouped = groupByFile(card.hits.slice(0, 10));
8251
8343
  return /* @__PURE__ */ React42.createElement(Card, { tone: TONE.info }, /* @__PURE__ */ React42.createElement(
8252
8344
  CardHeader,
8253
8345
  {
8254
8346
  glyph: "\u2299",
8255
8347
  tone: TONE.info,
8256
- title: "search",
8348
+ title: t("cardTitles.search"),
8257
8349
  subtitle: `"${card.query}"`,
8258
8350
  meta: [stats2, elapsed]
8259
8351
  }
8260
- ), grouped.map(([file, hits]) => /* @__PURE__ */ React42.createElement(Box35, { key: file, flexDirection: "column" }, /* @__PURE__ */ React42.createElement(Text36, { bold: true, color: FG.strong }, file), hits.map((h, i) => /* @__PURE__ */ React42.createElement(Box35, { key: `${file}:${h.line}:${i}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React42.createElement(Text36, { color: FG.faint }, `${h.line.toString().padStart(4)} \u2502`), /* @__PURE__ */ React42.createElement(HighlightedLine, { text: h.preview, start: h.matchStart, end: h.matchEnd }))))), card.hits.length > 10 ? /* @__PURE__ */ React42.createElement(Text36, { color: FG.faint }, `\u22EE +${card.hits.length - 10} more hits`) : null);
8352
+ ), grouped.map(([file, hits]) => /* @__PURE__ */ React42.createElement(Box35, { key: file, flexDirection: "column" }, /* @__PURE__ */ React42.createElement(Text36, { bold: true, color: FG.strong }, file), hits.map((h, i) => /* @__PURE__ */ React42.createElement(Box35, { key: `${file}:${h.line}:${i}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React42.createElement(Text36, { color: FG.faint }, `${h.line.toString().padStart(4)} \u2502`), /* @__PURE__ */ React42.createElement(HighlightedLine, { text: h.preview, start: h.matchStart, end: h.matchEnd }))))), card.hits.length > 10 ? /* @__PURE__ */ React42.createElement(Text36, { color: FG.faint }, t(
8353
+ card.hits.length - 10 === 1 ? "cardLabels.moreHitSingular" : "cardLabels.moreHitsPlural",
8354
+ { count: card.hits.length - 10 }
8355
+ )) : null);
8261
8356
  }
8262
8357
  function HighlightedLine({
8263
8358
  text,
@@ -8280,7 +8375,7 @@ function groupByFile(hits) {
8280
8375
  }
8281
8376
 
8282
8377
  // src/cli/ui/cards/StreamingCard.tsx
8283
- import { Box as Box37, Text as Text38, useStdout as useStdout10 } from "ink";
8378
+ import { Box as Box37, Text as Text38, useStdout as useStdout11 } from "ink";
8284
8379
  import React44, { useContext as useContext5 } from "react";
8285
8380
 
8286
8381
  // src/cli/ui/layout/LiveExpandContext.ts
@@ -8289,7 +8384,7 @@ var LiveExpandContext = createContext3(false);
8289
8384
 
8290
8385
  // src/cli/ui/markdown.tsx
8291
8386
  import { highlight, supportsLanguage } from "cli-highlight";
8292
- import { Box as Box36, Text as Text37, useStdout as useStdout9 } from "ink";
8387
+ import { Box as Box36, Text as Text37, useStdout as useStdout10 } from "ink";
8293
8388
  import React43 from "react";
8294
8389
  import stringWidth from "string-width";
8295
8390
  var BODY_LEFT_CELLS = 7;
@@ -8297,7 +8392,7 @@ var MarkdownWidthCtx = React43.createContext(void 0);
8297
8392
  function useWidth() {
8298
8393
  const ctx = React43.useContext(MarkdownWidthCtx);
8299
8394
  if (ctx !== void 0) return ctx;
8300
- return (useStdout9()?.stdout?.columns ?? process.stdout.columns ?? 80) - BODY_LEFT_CELLS;
8395
+ return (useStdout10()?.stdout?.columns ?? process.stdout.columns ?? 80) - BODY_LEFT_CELLS;
8301
8396
  }
8302
8397
  marked.setOptions({ gfm: true, breaks: false });
8303
8398
  function Markdown({ text, width }) {
@@ -8618,7 +8713,7 @@ function tokenRate(text, startTs, endTs) {
8618
8713
  }
8619
8714
  var PILL_RATE = { bg: "#11141a", fg: "#8b949e" };
8620
8715
  function StreamingCard({ card }) {
8621
- const { stdout } = useStdout10();
8716
+ const { stdout } = useStdout11();
8622
8717
  const cols = stdout?.columns ?? 80;
8623
8718
  const expanded = useContext5(LiveExpandContext);
8624
8719
  const reserveCap = expanded ? EXPANDED_MAX_LINES + 2 : STREAMING_PREVIEW_LINES2 + 2;
@@ -8637,7 +8732,7 @@ function StreamingCard({ card }) {
8637
8732
  {
8638
8733
  glyph: "\u2039",
8639
8734
  tone: TONE.ok,
8640
- title: "reply",
8735
+ title: t("cardTitles.reply"),
8641
8736
  right: /* @__PURE__ */ React44.createElement(React44.Fragment, null, ratePill, modelPill)
8642
8737
  }
8643
8738
  ), /* @__PURE__ */ React44.createElement(Markdown, { text: card.text }));
@@ -8651,7 +8746,7 @@ function StreamingCard({ card }) {
8651
8746
  const aborted = !!card.aborted;
8652
8747
  const headColor = aborted ? TONE.err : TONE_ACTIVE.brand;
8653
8748
  const glyph = aborted ? "\u2039" : "\u25C8";
8654
- const headLabel = aborted ? "aborted" : "writing\u2026";
8749
+ const headLabel = aborted ? t("cardLabels.aborted") : t("cardLabels.writing");
8655
8750
  const { tokens: liveTokens, tps: liveTps } = tokenRate(card.text, card.ts, Date.now());
8656
8751
  const liveRatePill = !aborted && liveTokens >= MIN_TOKENS_FOR_RATE && liveTps !== null ? /* @__PURE__ */ React44.createElement(Pill, { label: `${liveTps} t/s`, ...PILL_RATE, bold: false }) : null;
8657
8752
  const expandPill = !aborted ? /* @__PURE__ */ React44.createElement(Pill, { label: expanded ? "expanded \u2303o" : "preview \u2303o", ...PILL_RATE, bold: false }) : null;
@@ -8663,13 +8758,9 @@ function StreamingCard({ card }) {
8663
8758
  title: headLabel,
8664
8759
  right: /* @__PURE__ */ React44.createElement(React44.Fragment, null, liveRatePill, expandPill, aborted ? null : /* @__PURE__ */ React44.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand }), modelPill)
8665
8760
  }
8666
- ), expanded && droppedAbove > 0 ? /* @__PURE__ */ React44.createElement(
8667
- Text38,
8668
- {
8669
- color: FG.faint
8670
- },
8671
- `\u22EF ${droppedAbove} earlier line${droppedAbove === 1 ? "" : "s"} above`
8672
- ) : null, visible.map((line, i) => /* @__PURE__ */ React44.createElement(Box37, { key: `${card.id}:${visualLines.length - visible.length + i}`, flexDirection: "row" }, /* @__PURE__ */ React44.createElement(Text38, { color: aborted ? FG.meta : FG.body }, clipToCells(line, lineCells)))), aborted ? /* @__PURE__ */ React44.createElement(Text38, { color: FG.faint }, "[truncated by esc]") : null);
8761
+ ), expanded && droppedAbove > 0 ? /* @__PURE__ */ React44.createElement(Text38, { color: FG.faint }, t(droppedAbove === 1 ? "cardLabels.earlierLine" : "cardLabels.earlierLines", {
8762
+ count: droppedAbove
8763
+ })) : null, visible.map((line, i) => /* @__PURE__ */ React44.createElement(Box37, { key: `${card.id}:${visualLines.length - visible.length + i}`, flexDirection: "row" }, /* @__PURE__ */ React44.createElement(Text38, { color: aborted ? FG.meta : FG.body }, clipToCells(line, lineCells)))), aborted ? /* @__PURE__ */ React44.createElement(Text38, { color: FG.faint }, t("cardLabels.truncatedByEsc")) : null);
8673
8764
  }
8674
8765
 
8675
8766
  // src/cli/ui/cards/SubAgentCard.tsx
@@ -8683,22 +8774,22 @@ function SubAgentCard({ card }) {
8683
8774
  failed: tone.err
8684
8775
  };
8685
8776
  const headColor = statusColor[card.status];
8686
- const headGlyph = card.status === "failed" ? "\u2716" : "\u232C";
8777
+ const headGlyph = card.status === "failed" ? "\u2717" : "\u232C";
8687
8778
  const runningChildren = card.children.filter((c) => !isChildDone(c)).length;
8688
8779
  const isRunning = card.status === "running";
8689
8780
  const inLive = useContext6(ActiveCardContext);
8690
- const headerMeta2 = isRunning ? runningChildren > 0 ? [`${runningChildren} running`] : ["working"] : [{ text: card.status, color: headColor }];
8781
+ const headerMeta2 = isRunning ? runningChildren > 0 ? [`${runningChildren} ${t("cardLabels.runningLabel")}`] : [t("cardLabels.workingLabel")] : [{ text: card.status, color: headColor }];
8691
8782
  return /* @__PURE__ */ React45.createElement(Card, { tone: headColor }, /* @__PURE__ */ React45.createElement(
8692
8783
  CardHeader,
8693
8784
  {
8694
8785
  glyph: headGlyph,
8695
8786
  tone: headColor,
8696
- title: "subagent",
8787
+ title: t("cardTitles.subagent"),
8697
8788
  titleColor: tone.violet,
8698
8789
  subtitle: card.task,
8699
8790
  meta: headerMeta2
8700
8791
  }
8701
- ), 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 }))));
8792
+ ), card.name ? /* @__PURE__ */ React45.createElement(Text39, { color: fg.faint }, `${t("cardLabels.agent")} \xB7 ${card.name}`) : null, card.tools && card.tools.length > 0 && /* @__PURE__ */ React45.createElement(Text39, { color: fg.faint }, `${t("cardLabels.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 }))));
8702
8793
  }
8703
8794
  function isChildDone(card) {
8704
8795
  switch (card.kind) {
@@ -8734,7 +8825,7 @@ function childVisual(card, doneColor, failedColor, fallbackColor) {
8734
8825
  statusGlyph: done ? doneGlyph(doneColor) : runningGlyph(CARD.reasoning.color),
8735
8826
  kindGlyph: "\u25C6",
8736
8827
  kindColor: CARD.reasoning.color,
8737
- text: `reasoning \xB7 ${card.paragraphs} \xB6`
8828
+ text: t("cardLabels.reasoningLabel", { count: card.paragraphs })
8738
8829
  };
8739
8830
  }
8740
8831
  case "tool": {
@@ -8751,7 +8842,7 @@ function childVisual(card, doneColor, failedColor, fallbackColor) {
8751
8842
  statusGlyph: card.done ? doneGlyph(doneColor) : runningGlyph(CARD.streaming.color),
8752
8843
  kindGlyph: "\u25C8",
8753
8844
  kindColor: CARD.streaming.color,
8754
- text: card.done ? "response" : "writing \u2026"
8845
+ text: card.done ? t("cardLabels.response") : t("cardLabels.writing")
8755
8846
  };
8756
8847
  case "diff":
8757
8848
  return {
@@ -8848,7 +8939,7 @@ function TipRowRender({
8848
8939
  }
8849
8940
 
8850
8941
  // src/cli/ui/cards/ToolCard.tsx
8851
- import { Text as Text42, useStdout as useStdout11 } from "ink";
8942
+ import { Text as Text42, useStdout as useStdout12 } from "ink";
8852
8943
  import React48 from "react";
8853
8944
  var READ_TAIL = 2;
8854
8945
  var OTHER_TAIL = 5;
@@ -8857,7 +8948,7 @@ function tailLinesFor(name) {
8857
8948
  return /(?:^|_)(read|search|list|tree|get|status|diff|fetch|grep)(_|$)/.test(lower) || lower === "job_output" ? READ_TAIL : OTHER_TAIL;
8858
8949
  }
8859
8950
  function ToolCard({ card }) {
8860
- const { stdout } = useStdout11();
8951
+ const { stdout } = useStdout12();
8861
8952
  const cols = stdout?.columns ?? 80;
8862
8953
  const lineCells = Math.max(20, cols - 4);
8863
8954
  const argsLabel = formatArgsSummary(card.args);
@@ -8876,7 +8967,7 @@ function ToolCard({ card }) {
8876
8967
  meta.push({ text: `\u21BB ${card.retry.attempt}/${card.retry.max}`, color: TONE.warn });
8877
8968
  }
8878
8969
  if (card.rejected) {
8879
- meta.push({ text: "rejected", color: TONE.err });
8970
+ meta.push({ text: t("cardLabels.rejected"), color: TONE.err });
8880
8971
  }
8881
8972
  for (const part of metaTrail(card)) meta.push(part);
8882
8973
  return /* @__PURE__ */ React48.createElement(Card, { tone: headColor }, /* @__PURE__ */ React48.createElement(
@@ -8889,7 +8980,9 @@ function ToolCard({ card }) {
8889
8980
  meta: meta.length > 0 ? meta : void 0,
8890
8981
  right: status2 === "running" ? /* @__PURE__ */ React48.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand, bold: true }) : void 0
8891
8982
  }
8892
- ), showBody && (subagentMarkdown !== null ? /* @__PURE__ */ React48.createElement(Markdown, { text: subagentMarkdown, width: lineCells }) : /* @__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(
8983
+ ), showBody && (subagentMarkdown !== null ? /* @__PURE__ */ React48.createElement(Markdown, { text: subagentMarkdown, width: lineCells }) : /* @__PURE__ */ React48.createElement(React48.Fragment, null, hidden > 0 ? /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, t(hidden === 1 ? "cardLabels.earlierLine" : "cardLabels.earlierLines", {
8984
+ count: hidden
8985
+ })) : null, visible.map((line, i) => /* @__PURE__ */ React48.createElement(
8893
8986
  Text42,
8894
8987
  {
8895
8988
  key: `${card.id}:${hidden + i}`,
@@ -8949,10 +9042,11 @@ function headerColorFor(s) {
8949
9042
  function metaTrail(card) {
8950
9043
  const parts = [];
8951
9044
  const inputBytes = largestStringInputBytes(card.args);
8952
- if (inputBytes !== null) parts.push(`${formatBytes(inputBytes)} in`);
8953
- if (card.elapsedMs > 0) parts.push(`${(card.elapsedMs / 1e3).toFixed(2)}s`);
9045
+ if (inputBytes !== null) parts.push(t("cardLabels.bytesIn", { bytes: formatBytes(inputBytes) }));
9046
+ if (card.elapsedMs > 0)
9047
+ parts.push(t("cardLabels.elapsedSec", { secs: (card.elapsedMs / 1e3).toFixed(2) }));
8954
9048
  if (card.done && !card.rejected && !card.aborted && card.exitCode !== void 0 && card.exitCode !== 0) {
8955
- parts.push(`exit ${card.exitCode}`);
9049
+ parts.push(t("cardLabels.exit", { code: card.exitCode }));
8956
9050
  }
8957
9051
  return parts;
8958
9052
  }
@@ -9009,13 +9103,16 @@ function UsageCard({ card }) {
9009
9103
  const promptRatio = card.tokens.prompt / cap;
9010
9104
  const reasonRatio = card.tokens.reason / cap;
9011
9105
  const outputRatio = card.tokens.output / cap;
9012
- const headerMeta2 = [`turn ${card.turn}`, formatCost(card.cost, card.balanceCurrency)];
9106
+ const headerMeta2 = [
9107
+ `${t("cardLabels.turn")} ${card.turn}`,
9108
+ formatCost(card.cost, card.balanceCurrency)
9109
+ ];
9013
9110
  if (card.elapsedMs !== void 0) headerMeta2.push(`${(card.elapsedMs / 1e3).toFixed(1)}s`);
9014
- 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));
9111
+ return /* @__PURE__ */ React49.createElement(Card, { tone: FG.meta }, /* @__PURE__ */ React49.createElement(CardHeader, { glyph: "\u03A3", tone: FG.meta, title: t("cardTitles.usage"), meta: headerMeta2 }), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, t("cardLabels.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 }, t("cardLabels.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 }, t("cardLabels.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 }, t("cardLabels.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 }, t("cardLabels.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 ${t("cardLabels.balance")}`), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: TONE.brand }, formatBalance(card.balance, card.balanceCurrency))) : null));
9015
9112
  }
9016
9113
  function CompactUsageRow({ card }) {
9017
9114
  const elapsed = card.elapsedMs !== void 0 ? ` \xB7 ${(card.elapsedMs / 1e3).toFixed(1)}s` : "";
9018
- 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);
9115
+ 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 }, `${t("cardLabels.turn")} ${card.turn}`), /* @__PURE__ */ React49.createElement(Text43, { color: FG.meta }, `\xB7 ${compactNum(card.tokens.prompt)} ${t("cardLabels.prompt")} \xB7 ${compactNum(card.tokens.output)} ${t("cardLabels.output")}`), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `\xB7 ${t("cardLabels.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);
9019
9116
  }
9020
9117
 
9021
9118
  // src/cli/ui/cards/UserCard.tsx
@@ -9338,7 +9435,7 @@ function summarizeToolArgs(name, args) {
9338
9435
  }
9339
9436
 
9340
9437
  // src/cli/ui/layout/StatusRow.tsx
9341
- import { Box as Box46, Text as Text49, useStdout as useStdout12 } from "ink";
9438
+ import { Box as Box46, Text as Text49, useStdout as useStdout13 } from "ink";
9342
9439
  import React56 from "react";
9343
9440
 
9344
9441
  // src/cli/ui/primitives/Countdown.tsx
@@ -9359,21 +9456,28 @@ var FEEDBACK_HINT_MIN_COLS = 100;
9359
9456
  function StatusRow() {
9360
9457
  const status2 = useAgentState((s) => s.status);
9361
9458
  const session = useAgentState((s) => s.session);
9362
- const { stdout } = useStdout12();
9459
+ const { stdout } = useStdout13();
9363
9460
  const cols = stdout?.columns ?? 80;
9364
9461
  const ruleWidth = Math.max(RULE_MIN, cols - RULE_PAD);
9365
9462
  const hasTurn = status2.cost > 0;
9366
9463
  const hasSession = status2.sessionCost > 0;
9367
9464
  const hasBalance = typeof status2.balance === "number";
9368
9465
  const showWallet = cols >= WALLET_MIN_COLS && (hasSession || hasBalance);
9369
- 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(
9466
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Box46, { height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, null, " "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint, wrap: "truncate" }, "\u2500".repeat(ruleWidth))), /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, minHeight: 1, flexWrap: "nowrap", flexShrink: 0 }, /* @__PURE__ */ React56.createElement(Text49, { wrap: "truncate" }, " "), 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, wrap: "truncate" }, `${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, wrap: "truncate" }, "\u25B8 "), /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: FG.body, wrap: "truncate" }, `${formatCost(status2.cost, status2.balanceCurrency)} turn`)), /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(
9467
+ Text49,
9468
+ {
9469
+ color: TONE.accent,
9470
+ wrap: "truncate"
9471
+ },
9472
+ `cache ${Math.round(status2.cacheHit * 100)}%`
9473
+ ), showWallet && /* @__PURE__ */ React56.createElement(
9370
9474
  WalletPill,
9371
9475
  {
9372
9476
  sessionCostUsd: status2.sessionCost,
9373
9477
  balance: status2.balance,
9374
9478
  currency: status2.balanceCurrency
9375
9479
  }
9376
- ), cols >= VERSION_MIN_COLS && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint }, `v${VERSION}`), cols >= FEEDBACK_HINT_MIN_COLS && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint }, " \xB7 "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta }, "\u2691 "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub }, "/feedback")))));
9480
+ ), cols >= VERSION_MIN_COLS && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint, wrap: "truncate" }, `v${VERSION}`), cols >= FEEDBACK_HINT_MIN_COLS && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint, wrap: "truncate" }, " \xB7 "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta, wrap: "truncate" }, "\u2691 "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub, wrap: "truncate" }, "/feedback")))));
9377
9481
  }
9378
9482
  function WalletPill({
9379
9483
  sessionCostUsd,
@@ -9382,7 +9486,14 @@ function WalletPill({
9382
9486
  }) {
9383
9487
  const showSpent = sessionCostUsd > 0;
9384
9488
  const showBalance = typeof balance === "number";
9385
- 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"));
9489
+ return /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta, wrap: "truncate" }, "\u26C1 "), showSpent && /* @__PURE__ */ React56.createElement(
9490
+ Text49,
9491
+ {
9492
+ color: FG.body,
9493
+ wrap: "truncate"
9494
+ },
9495
+ `${formatCost(sessionCostUsd, currency, 2)} spent`
9496
+ ), showSpent && showBalance && /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta, wrap: "truncate" }, " / "), showBalance && /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: balanceColor(balance, currency), wrap: "truncate" }, formatBalance(balance, currency, { fractionDigits: 2 })), showBalance && /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint, wrap: "truncate" }, " left"));
9386
9497
  }
9387
9498
  function ModePill2({
9388
9499
  mode: mode2,
@@ -9391,18 +9502,18 @@ function ModePill2({
9391
9502
  }) {
9392
9503
  if (network === "online") {
9393
9504
  const pill = modeGlyph(mode2);
9394
- return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: pill.color }, pill.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub }, ` ${mode2}`));
9505
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: pill.color, wrap: "truncate" }, pill.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub, wrap: "truncate" }, ` ${mode2}`));
9395
9506
  }
9396
9507
  const dot = networkDot(network);
9397
9508
  if (network === "slow") {
9398
9509
  const tail = detail ? ` \xB7 ${detail}` : "";
9399
- 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}`));
9510
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, ` ${mode2} \xB7 slow${tail}`));
9400
9511
  }
9401
9512
  if (network === "disconnected") {
9402
9513
  const tail = detail ? ` \xB7 ${detail}` : "";
9403
- 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}`));
9514
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, ` disconnect${tail}`));
9404
9515
  }
9405
- 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"));
9516
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, " reconnecting\u2026"));
9406
9517
  }
9407
9518
  function CountdownRow({
9408
9519
  mode: mode2,
@@ -9410,14 +9521,14 @@ function CountdownRow({
9410
9521
  }) {
9411
9522
  const pill = modeGlyph(mode2);
9412
9523
  const endsAt = Date.now() + secondsLeft * 1e3;
9413
- 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"));
9524
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: pill.color, wrap: "truncate" }, pill.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub, wrap: "truncate" }, ` ${mode2} \xB7 `), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.warn, wrap: "truncate" }, "approving in "), /* @__PURE__ */ React56.createElement(Countdown, { endsAt }), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.warn, wrap: "truncate" }, "s \xB7 esc to interrupt"));
9414
9525
  }
9415
9526
  function RecordingPill({ rec }) {
9416
9527
  const sizeMb = (rec.sizeBytes / (1024 * 1024)).toFixed(1);
9417
- 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`));
9528
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: TONE.err, wrap: "truncate" }, "\u25CFREC"), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.err, wrap: "truncate" }, ` ${sizeMb} MB \xB7 ${rec.events} evt`));
9418
9529
  }
9419
9530
  function Sep() {
9420
- return /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta }, " \xB7 ");
9531
+ return /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta, wrap: "truncate" }, " \xB7 ");
9421
9532
  }
9422
9533
  function modeGlyph(mode2) {
9423
9534
  switch (mode2) {
@@ -9445,7 +9556,7 @@ function networkDot(state) {
9445
9556
  }
9446
9557
 
9447
9558
  // src/cli/ui/layout/ToastRail.tsx
9448
- import { Box as Box47, Text as Text50, useStdout as useStdout13 } from "ink";
9559
+ import { Box as Box47, Text as Text50, useStdout as useStdout14 } from "ink";
9449
9560
  import React57, { useEffect as useEffect8 } from "react";
9450
9561
  var TONE_COLOR = {
9451
9562
  ok: TONE.ok,
@@ -9468,7 +9579,7 @@ function ToastRail() {
9468
9579
  const toasts = useAgentState((s) => s.toasts);
9469
9580
  const dispatch = useDispatch();
9470
9581
  useSlowTick();
9471
- const { stdout } = useStdout13();
9582
+ const { stdout } = useStdout14();
9472
9583
  const cols = stdout?.columns ?? 80;
9473
9584
  const rule = "\u2501".repeat(Math.max(20, cols - 4));
9474
9585
  const now = Date.now();
@@ -9873,24 +9984,28 @@ var update = (_args, _loop, ctx) => {
9873
9984
  return { info: lines.join("\n") };
9874
9985
  }
9875
9986
  lines.push(t("handlers.admin.updateLatest", { version: latest }));
9876
- const diff = compareVersions(VERSION, latest);
9877
- if (diff >= 0) {
9987
+ if (compareVersions(VERSION, latest) >= 0) {
9878
9988
  lines.push("", t("handlers.admin.updateUpToDate"));
9879
9989
  return { info: lines.join("\n") };
9880
9990
  }
9881
- if (isNpxInstall()) {
9991
+ const installSource = detectInstallSource();
9992
+ const npmPrefix = installSource === "npm" ? detectNpmInstallPrefix() : null;
9993
+ const plan2 = planUpdate({ current: VERSION, latest, installSource, npmPrefix });
9994
+ if (plan2.action === "npx-hint") {
9882
9995
  lines.push("", t("handlers.admin.updateNpxHint"), t("handlers.admin.updateNpxForce"));
9996
+ return { info: lines.join("\n") };
9997
+ }
9998
+ lines.push("", t("handlers.admin.updateUpgradeHint"), t("handlers.admin.updateUpgradeCmd1"));
9999
+ if (plan2.action === "run-install" && plan2.command) {
10000
+ lines.push(t("handlers.admin.updateUpgradeCmd2", { command: plan2.command.join(" ") }));
9883
10001
  } else {
9884
- lines.push(
9885
- "",
9886
- t("handlers.admin.updateUpgradeHint"),
9887
- t("handlers.admin.updateUpgradeCmd1"),
9888
- t("handlers.admin.updateUpgradeCmd2"),
9889
- "",
9890
- t("handlers.admin.updateInSessionDisabled"),
9891
- t("handlers.admin.updateInSessionDisabled2")
9892
- );
10002
+ lines.push(...MANUAL_UPDATE_COMMANDS.map((c) => ` ${c}`));
9893
10003
  }
10004
+ lines.push(
10005
+ "",
10006
+ t("handlers.admin.updateInSessionDisabled"),
10007
+ t("handlers.admin.updateInSessionDisabled2")
10008
+ );
9894
10009
  return { info: lines.join("\n") };
9895
10010
  };
9896
10011
  var stats = () => {
@@ -11067,7 +11182,9 @@ function buildFeedbackDiagnostic(input) {
11067
11182
  }
11068
11183
  function formatVersion(installed, latest) {
11069
11184
  if (!latest) return installed;
11070
- if (latest === installed) return `${installed} (latest)`;
11185
+ const cmp = compareVersions(installed, latest);
11186
+ if (cmp === 0) return `${installed} (latest)`;
11187
+ if (cmp > 0) return installed;
11071
11188
  return `${installed} (latest: ${latest})`;
11072
11189
  }
11073
11190
  function formatModel(model2, effort) {
@@ -11715,6 +11832,31 @@ var handlers17 = {
11715
11832
  se: (args, loop2, ctx) => handlers17["search-engine"](args, loop2, ctx)
11716
11833
  };
11717
11834
 
11835
+ // src/cli/ui/slash/nearest.ts
11836
+ function nearestCommands(input, all, opts = {}) {
11837
+ if (!input) return [];
11838
+ const max = opts.max ?? 3;
11839
+ const maxDistance = Math.min(opts.maxDistance ?? 3, Math.floor(input.length / 2));
11840
+ if (max <= 0 || maxDistance <= 0) return [];
11841
+ return all.map((name) => ({ name, distance: levenshtein(input, name) })).filter((entry) => entry.distance <= maxDistance).sort((a, b) => a.distance - b.distance || a.name.localeCompare(b.name)).slice(0, max).map((entry) => entry.name);
11842
+ }
11843
+ function levenshtein(a, b) {
11844
+ if (a === b) return 0;
11845
+ if (!a) return b.length;
11846
+ if (!b) return a.length;
11847
+ let prev = Array.from({ length: b.length + 1 }, (_, i) => i);
11848
+ let next = new Array(b.length + 1).fill(0);
11849
+ for (let i = 0; i < a.length; i += 1) {
11850
+ next[0] = i + 1;
11851
+ for (let j = 0; j < b.length; j += 1) {
11852
+ const cost2 = a[i] === b[j] ? 0 : 1;
11853
+ next[j + 1] = Math.min((next[j] ?? 0) + 1, (prev[j + 1] ?? 0) + 1, (prev[j] ?? 0) + cost2);
11854
+ }
11855
+ [prev, next] = [next, prev];
11856
+ }
11857
+ return prev[b.length] ?? 0;
11858
+ }
11859
+
11718
11860
  // src/cli/ui/slash/dispatch.ts
11719
11861
  var HANDLERS = {
11720
11862
  ...handlers,
@@ -11738,6 +11880,11 @@ var HANDLERS = {
11738
11880
  function handleSlash(cmd, args, loop2, ctx = {}) {
11739
11881
  const h = HANDLERS[resolveSlashAlias(cmd)];
11740
11882
  if (h) return h(args, loop2, ctx);
11883
+ const suggestions = nearestCommands(cmd, Object.keys(HANDLERS));
11884
+ if (suggestions.length > 0) {
11885
+ const list2 = suggestions.map((name) => `/${name}`).join(", ");
11886
+ return { unknown: true, info: `unknown command: /${cmd} \u2014 did you mean ${list2}?` };
11887
+ }
11741
11888
  return { unknown: true, info: `unknown command: /${cmd} (try /help)` };
11742
11889
  }
11743
11890
 
@@ -12658,9 +12805,9 @@ function useSubagent({
12658
12805
  // src/cli/ui/App.tsx
12659
12806
  var FLUSH_INTERVAL_MS = (() => {
12660
12807
  const raw = process.env.REASONIX_FLUSH_MS;
12661
- if (!raw) return 33;
12808
+ if (!raw) return 16;
12662
12809
  const parsed = Number(raw);
12663
- if (!Number.isFinite(parsed) || parsed < 16 || parsed > 1e3) return 33;
12810
+ if (!Number.isFinite(parsed) || parsed < 16 || parsed > 1e3) return 16;
12664
12811
  return Math.round(parsed);
12665
12812
  })();
12666
12813
  var PLAIN_UI = process.env.REASONIX_UI === "plain";
@@ -12702,7 +12849,8 @@ function AppInner({
12702
12849
  progressSink,
12703
12850
  codeMode,
12704
12851
  noDashboard,
12705
- onSwitchSession
12852
+ onSwitchSession,
12853
+ mouse = true
12706
12854
  }) {
12707
12855
  markPhase("app_inner_start");
12708
12856
  const log = useScrollback();
@@ -12734,18 +12882,18 @@ function AppInner({
12734
12882
  }, [busy]);
12735
12883
  const [ongoingTool, setOngoingTool] = useState20(null);
12736
12884
  const [toolProgress, setToolProgress] = useState20(null);
12737
- const { stdout } = useStdout14();
12885
+ const { stdout } = useStdout15();
12738
12886
  useEffect12(() => {
12739
12887
  if (!stdout || !stdout.isTTY) return;
12740
12888
  stdout.write("\x1B[?2004h");
12741
12889
  stdout.write("\x1B[>4;2m");
12742
- stdout.write("\x1B[?1006h\x1B[?1000h");
12890
+ if (mouse) stdout.write("\x1B[?1007h");
12743
12891
  return () => {
12744
- stdout.write("\x1B[?1000l\x1B[?1006l");
12892
+ if (mouse) stdout.write("\x1B[?1007l");
12745
12893
  stdout.write("\x1B[?2004l");
12746
12894
  stdout.write("\x1B[>4m");
12747
12895
  };
12748
- }, [stdout]);
12896
+ }, [stdout, mouse]);
12749
12897
  const walletCurrencyRef = useRef9(void 0);
12750
12898
  const { activities: subagentActivities, sinkRef: subagentSinkRef } = useSubagent({
12751
12899
  session,
@@ -12894,7 +13042,7 @@ function AppInner({
12894
13042
  const loopRef = useRef9(null);
12895
13043
  const loop2 = useMemo9(() => {
12896
13044
  if (loopRef.current) return loopRef.current;
12897
- const client = new DeepSeekClient();
13045
+ const client = new DeepSeekClient({ baseUrl: loadBaseUrl() });
12898
13046
  if (tools && !tools.has("run_skill")) {
12899
13047
  registerSkillTools(tools, {
12900
13048
  projectRoot: codeMode?.rootDir,
@@ -13214,11 +13362,12 @@ function AppInner({
13214
13362
  }, [session, loop2, codeMode, syncPendingCount, log]);
13215
13363
  const quitProcess = useQuit(transcriptRef);
13216
13364
  useKeystroke((ev) => {
13365
+ const pickerOwnsArrows = (atState?.entries.length ?? 0) > 0 || (slashMatches?.length ?? 0) > 0 || (slashArgMatches?.length ?? 0) > 0 || pendingShell != null;
13217
13366
  if (ev.pageUp || ev.mouseScrollUp) chatScroll.scrollUp();
13218
13367
  else if (ev.pageDown || ev.mouseScrollDown) chatScroll.scrollDown();
13219
13368
  else if (ev.end) chatScroll.jumpToBottom();
13220
- else if ((!chatScroll.pinned || busy) && ev.upArrow) chatScroll.scrollUp();
13221
- else if ((!chatScroll.pinned || busy) && ev.downArrow) chatScroll.scrollDown();
13369
+ else if (!pickerOwnsArrows && ev.upArrow) chatScroll.scrollUp();
13370
+ else if (!pickerOwnsArrows && ev.downArrow) chatScroll.scrollDown();
13222
13371
  }, !modalOpen);
13223
13372
  useKeystroke((ev) => {
13224
13373
  const chKey = ev.input;
@@ -13433,7 +13582,7 @@ function AppInner({
13433
13582
  if (dashboardRef.current) return dashboardRef.current.url;
13434
13583
  if (dashboardStartingRef.current) return dashboardStartingRef.current;
13435
13584
  const startup = (async () => {
13436
- const { startDashboardServer } = await import("./server-SMLVXIW4.js");
13585
+ const { startDashboardServer } = await import("./server-W4XJK4GX.js");
13437
13586
  const handle = await startDashboardServer({
13438
13587
  mode: "attached",
13439
13588
  configPath: defaultConfigPath(),
@@ -14376,7 +14525,7 @@ function AppInner({
14376
14525
  }
14377
14526
  if (!staged) return;
14378
14527
  const trimmed = feedback2.trim();
14379
- let synthetic;
14528
+ const tail = trimmed.length > 50 ? `${trimmed.slice(0, 50)}\u2026` : trimmed;
14380
14529
  let marker;
14381
14530
  if (staged.mode === "approve") {
14382
14531
  togglePlanMode(false);
@@ -14394,19 +14543,7 @@ function AppInner({
14394
14543
  });
14395
14544
  persistPlanState();
14396
14545
  }
14397
- if (trimmed) {
14398
- synthetic = `The plan above has been approved. Implement it now. You are out of plan mode \u2014 use edit_file / write_file / run_command as needed.
14399
-
14400
- User's additional instructions / answers to your open questions:
14401
-
14402
- ${trimmed}
14403
-
14404
- Factor these in before the first edit. Stick to the plan unless you discover a concrete reason to deviate; if you do, tell me and wait for a response.`;
14405
- marker = `\u25B8 plan approved + instructions \u2014 ${trimmed.length > 50 ? `${trimmed.slice(0, 50)}\u2026` : trimmed}`;
14406
- } else {
14407
- synthetic = "The plan above has been approved. Implement it now. You are out of plan mode \u2014 use edit_file / write_file / run_command as needed. If the plan listed open questions and I didn't answer them, default to the safest interpretation and call them out in your first reply. Don't fabricate preferences \u2014 if a question is truly unanswerable without me, stop and ask.";
14408
- marker = "\u25B8 plan approved \u2014 implementing";
14409
- }
14546
+ marker = trimmed ? `\u25B8 plan approved + instructions \u2014 ${tail}` : "\u25B8 plan approved \u2014 implementing";
14410
14547
  } else if (staged.mode === "reject") {
14411
14548
  planStepsRef.current = null;
14412
14549
  completedStepIdsRef.current = /* @__PURE__ */ new Set();
@@ -14415,38 +14552,20 @@ Factor these in before the first edit. Stick to the plan unless you discover a c
14415
14552
  persistPlanState();
14416
14553
  togglePlanMode(false);
14417
14554
  agentStore.dispatch({ type: "plan.drop" });
14418
- if (trimmed) {
14419
- synthetic = `The plan was rejected. User's reason / what they actually want:
14420
-
14421
- ${trimmed}
14422
-
14423
- Drop the proposed plan entirely. Use this guidance to understand what the user is after \u2014 ask follow-up questions if anything is still unclear, otherwise propose a different plan that addresses it.`;
14424
- marker = `\u25B8 plan rejected \u2014 ${trimmed.length > 50 ? `${trimmed.slice(0, 50)}\u2026` : trimmed}`;
14425
- } else {
14426
- synthetic = "The plan was cancelled. Drop it entirely. Ask me what I actually want before proposing another plan or making any changes.";
14427
- marker = "\u25B8 plan cancelled";
14428
- }
14555
+ marker = trimmed ? `\u25B8 plan rejected \u2014 ${tail}` : "\u25B8 plan cancelled";
14429
14556
  } else {
14430
- if (trimmed) {
14431
- synthetic = `The plan needs refinement. User feedback / answers:
14432
-
14433
- ${trimmed}
14434
-
14435
- Stay in plan mode \u2014 address the feedback (explore more if needed), then submit an improved submit_plan call. Don't propose a near-identical plan unless you explain why the feedback doesn't apply.`;
14436
- marker = `\u25B8 refining \u2014 ${trimmed.length > 50 ? `${trimmed.slice(0, 50)}\u2026` : trimmed}`;
14437
- } else {
14438
- synthetic = "The plan needs refinement. The user saw your open questions / risks block and chose not to answer specifics. Pick the safest default for each open question, call those defaults out explicitly in the new plan, and submit the refined submit_plan. Do not re-ask \u2014 the user already saw the questions.";
14439
- marker = "\u25B8 refining \u2014 using safe defaults";
14440
- }
14557
+ marker = trimmed ? `\u25B8 refining \u2014 ${tail}` : "\u25B8 refining \u2014 using safe defaults";
14441
14558
  }
14559
+ log.pushInfo(marker);
14442
14560
  const gateId = pendingGateIdRef.current;
14443
14561
  if (gateId !== null) {
14562
+ const fb = trimmed || void 0;
14444
14563
  if (staged.mode === "approve") {
14445
- pauseGate.resolve(gateId, { type: "approve" });
14564
+ pauseGate.resolve(gateId, { type: "approve", feedback: fb });
14446
14565
  } else if (staged.mode === "reject") {
14447
- pauseGate.resolve(gateId, { type: "cancel" });
14566
+ pauseGate.resolve(gateId, { type: "cancel", feedback: fb });
14448
14567
  } else {
14449
- pauseGate.resolve(gateId, { type: "refine" });
14568
+ pauseGate.resolve(gateId, { type: "refine", feedback: fb });
14450
14569
  }
14451
14570
  }
14452
14571
  },
@@ -14989,7 +15108,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14989
15108
  block: pendingEdits.current[0],
14990
15109
  onChoose: handleWalkChoice
14991
15110
  }
14992
- ) : !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(
15111
+ ) : !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(Box49, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, /* @__PURE__ */ React60.createElement(Box49, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, codeMode ? /* @__PURE__ */ React60.createElement(
14993
15112
  ModeStatusBar,
14994
15113
  {
14995
15114
  editMode,
@@ -15009,15 +15128,16 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
15009
15128
  onHistoryPrev: recallPrev,
15010
15129
  onHistoryNext: recallNext
15011
15130
  }
15012
- ), slashMatches !== null ? /* @__PURE__ */ React60.createElement(
15131
+ )), /* @__PURE__ */ React60.createElement(Box49, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, slashMatches !== null ? /* @__PURE__ */ React60.createElement(
15013
15132
  SlashSuggestions,
15014
15133
  {
15134
+ key: `slash-suggestions:${slashGroupMode ? "group" : "search"}`,
15015
15135
  matches: slashMatches,
15016
15136
  selectedIndex: slashSelected,
15017
15137
  groupMode: slashGroupMode,
15018
15138
  advancedHidden: slashAdvancedHidden
15019
15139
  }
15020
- ) : null, atState !== null ? /* @__PURE__ */ React60.createElement(AtMentionSuggestions, { state: atState, selectedIndex: atSelected }) : null, slashArgContext ? /* @__PURE__ */ React60.createElement(
15140
+ ) : null, atState !== null ? /* @__PURE__ */ React60.createElement(AtMentionSuggestions, { state: atState, selectedIndex: atSelected }) : null), slashArgContext ? /* @__PURE__ */ React60.createElement(
15021
15141
  SlashArgPicker,
15022
15142
  {
15023
15143
  matches: slashArgMatches,
@@ -15089,7 +15209,7 @@ function Setup({ onReady }) {
15089
15209
  return;
15090
15210
  }
15091
15211
  if (!isPlausibleKey(trimmed)) {
15092
- setError("Doesn't look like a DeepSeek key. They start with 'sk-' and are 30+ chars.");
15212
+ setError("Key looks too short \u2014 paste the full token (16+ chars, no spaces).");
15093
15213
  setValue("");
15094
15214
  return;
15095
15215
  }
@@ -15382,6 +15502,7 @@ function Root({
15382
15502
  progressSink,
15383
15503
  codeMode: appProps.codeMode,
15384
15504
  noDashboard: appProps.noDashboard,
15505
+ mouse: appProps.mouse,
15385
15506
  onSwitchSession: setActiveSession
15386
15507
  }
15387
15508
  ));
@@ -15456,7 +15577,12 @@ async function chatCommand(opts) {
15456
15577
  exitOnCtrlC: true,
15457
15578
  // patchConsole:false — winpty/MINTTY redraw-glitch source.
15458
15579
  patchConsole: false,
15459
- incrementalRendering: true,
15580
+ // incrementalRendering:false — Ink's diff drifts when stringWidth
15581
+ // misjudges CJK / emoji ZWJ width or when async terminal-event
15582
+ // bytes interleave mid-render, leaving residual rows. Full-frame
15583
+ // redraws cost more stdout bytes per flush but eliminate the
15584
+ // ghost class.
15585
+ incrementalRendering: false,
15460
15586
  // Default true — alt-screen is the only mode without scrollback-
15461
15587
  // reflow ghosting. `--no-alt-screen` opts back into scrollback mode
15462
15588
  // for users who need chat output preserved in shell history on exit.
@@ -15474,4 +15600,4 @@ async function chatCommand(opts) {
15474
15600
  export {
15475
15601
  chatCommand
15476
15602
  };
15477
- //# sourceMappingURL=chunk-GPHBJWCV.js.map
15603
+ //# sourceMappingURL=chunk-EN4LAZW5.js.map