reasonix 0.37.0 → 0.38.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 (74) hide show
  1. package/README.md +1 -0
  2. package/README.zh-CN.md +1 -0
  3. package/dist/cli/{chat-7257YAPG.js → chat-FPEYKTMI.js} +13 -14
  4. package/dist/cli/{chunk-T52GAWPP.js → chunk-3VTV4WAH.js} +2 -2
  5. package/dist/cli/{chunk-MSKUP6PD.js → chunk-4PNXH2MH.js} +910 -659
  6. package/dist/cli/chunk-4PNXH2MH.js.map +1 -0
  7. package/dist/cli/{chunk-YER7WCHF.js → chunk-A63QT566.js} +24 -10
  8. package/dist/cli/chunk-A63QT566.js.map +1 -0
  9. package/dist/cli/{chunk-4Q3GRJIU.js → chunk-AATCLE5N.js} +2 -2
  10. package/dist/cli/{chunk-BHLHOS5Y.js → chunk-BW2HWSYH.js} +315 -5
  11. package/dist/cli/chunk-BW2HWSYH.js.map +1 -0
  12. package/dist/cli/{chunk-ZJR4QLXB.js → chunk-FB46F6H4.js} +2 -2
  13. package/dist/cli/{chunk-GKZJXYMY.js → chunk-FYKZB6TX.js} +415 -11
  14. package/dist/cli/chunk-FYKZB6TX.js.map +1 -0
  15. package/dist/cli/{chunk-XQIFIB3U.js → chunk-JOFZ6AW5.js} +2 -2
  16. package/dist/cli/{chunk-JGZKTAOH.js → chunk-LMNAMITH.js} +2 -2
  17. package/dist/cli/{chunk-S4GF3HPO.js → chunk-LY352GTC.js} +6 -4
  18. package/dist/cli/chunk-LY352GTC.js.map +1 -0
  19. package/dist/cli/{chunk-VF57YX2M.js → chunk-NYP2DDDV.js} +40 -1
  20. package/dist/cli/chunk-NYP2DDDV.js.map +1 -0
  21. package/dist/cli/{chunk-JULZ7JTO.js → chunk-T5U5JO7Q.js} +11 -8
  22. package/dist/cli/chunk-T5U5JO7Q.js.map +1 -0
  23. package/dist/cli/{chunk-SEFXUF24.js → chunk-YJKLNYCP.js} +113 -24
  24. package/dist/cli/chunk-YJKLNYCP.js.map +1 -0
  25. package/dist/cli/{code-64EG5IU2.js → code-GTE65OUT.js} +23 -17
  26. package/dist/cli/{code-64EG5IU2.js.map → code-GTE65OUT.js.map} +1 -1
  27. package/dist/cli/{commands-FE2UDFBC.js → commands-R4JWISND.js} +3 -4
  28. package/dist/cli/{commands-FE2UDFBC.js.map → commands-R4JWISND.js.map} +1 -1
  29. package/dist/cli/{commit-3IAGB22T.js → commit-TQ4DMUNS.js} +2 -3
  30. package/dist/cli/{commit-3IAGB22T.js.map → commit-TQ4DMUNS.js.map} +1 -1
  31. package/dist/cli/{doctor-BW5HSQDW.js → doctor-GGK2JKTA.js} +6 -7
  32. package/dist/cli/index.js +24 -25
  33. package/dist/cli/index.js.map +1 -1
  34. package/dist/cli/{mcp-2RDEQST6.js → mcp-M7I23TQ7.js} +2 -3
  35. package/dist/cli/{mcp-2RDEQST6.js.map → mcp-M7I23TQ7.js.map} +1 -1
  36. package/dist/cli/{mcp-browse-VM5GLRBQ.js → mcp-browse-TWO7RYT4.js} +2 -3
  37. package/dist/cli/{mcp-browse-VM5GLRBQ.js.map → mcp-browse-TWO7RYT4.js.map} +1 -1
  38. package/dist/cli/{prompt-KGIUONO3.js → prompt-ODPFOKSH.js} +2 -2
  39. package/dist/cli/{replay-D7RT2DR7.js → replay-R3QRXPI2.js} +13 -9
  40. package/dist/cli/replay-R3QRXPI2.js.map +1 -0
  41. package/dist/cli/{run-RWCOA32G.js → run-WGSPYYOJ.js} +7 -8
  42. package/dist/cli/{run-RWCOA32G.js.map → run-WGSPYYOJ.js.map} +1 -1
  43. package/dist/cli/{server-6ZW4TQUP.js → server-IZPWQYG3.js} +8 -9
  44. package/dist/cli/{server-6ZW4TQUP.js.map → server-IZPWQYG3.js.map} +1 -1
  45. package/dist/cli/{sessions-5ISNWFMU.js → sessions-E4UH5JYL.js} +7 -8
  46. package/dist/cli/{sessions-5ISNWFMU.js.map → sessions-E4UH5JYL.js.map} +1 -1
  47. package/dist/cli/{setup-HJG23NKJ.js → setup-FTZNN3TZ.js} +60 -15
  48. package/dist/cli/setup-FTZNN3TZ.js.map +1 -0
  49. package/dist/cli/{version-BXAN7Q4V.js → version-MDVCFTKA.js} +7 -8
  50. package/dist/cli/{version-BXAN7Q4V.js.map → version-MDVCFTKA.js.map} +1 -1
  51. package/dist/index.d.ts +3 -0
  52. package/dist/index.js +568 -40
  53. package/dist/index.js.map +1 -1
  54. package/package.json +1 -1
  55. package/dist/cli/chunk-BHLHOS5Y.js.map +0 -1
  56. package/dist/cli/chunk-GKZJXYMY.js.map +0 -1
  57. package/dist/cli/chunk-JULZ7JTO.js.map +0 -1
  58. package/dist/cli/chunk-MSKUP6PD.js.map +0 -1
  59. package/dist/cli/chunk-S4GF3HPO.js.map +0 -1
  60. package/dist/cli/chunk-SEFXUF24.js.map +0 -1
  61. package/dist/cli/chunk-VF57YX2M.js.map +0 -1
  62. package/dist/cli/chunk-WUI3P4RA.js +0 -319
  63. package/dist/cli/chunk-WUI3P4RA.js.map +0 -1
  64. package/dist/cli/chunk-YER7WCHF.js.map +0 -1
  65. package/dist/cli/replay-D7RT2DR7.js.map +0 -1
  66. package/dist/cli/setup-HJG23NKJ.js.map +0 -1
  67. /package/dist/cli/{chat-7257YAPG.js.map → chat-FPEYKTMI.js.map} +0 -0
  68. /package/dist/cli/{chunk-T52GAWPP.js.map → chunk-3VTV4WAH.js.map} +0 -0
  69. /package/dist/cli/{chunk-4Q3GRJIU.js.map → chunk-AATCLE5N.js.map} +0 -0
  70. /package/dist/cli/{chunk-ZJR4QLXB.js.map → chunk-FB46F6H4.js.map} +0 -0
  71. /package/dist/cli/{chunk-XQIFIB3U.js.map → chunk-JOFZ6AW5.js.map} +0 -0
  72. /package/dist/cli/{chunk-JGZKTAOH.js.map → chunk-LMNAMITH.js.map} +0 -0
  73. /package/dist/cli/{doctor-BW5HSQDW.js.map → doctor-GGK2JKTA.js.map} +0 -0
  74. /package/dist/cli/{prompt-KGIUONO3.js.map → prompt-ODPFOKSH.js.map} +0 -0
@@ -34,7 +34,7 @@ import {
34
34
  toWholeFileEditBlock,
35
35
  walkFilesStream,
36
36
  webFetch
37
- } from "./chunk-SEFXUF24.js";
37
+ } from "./chunk-YJKLNYCP.js";
38
38
  import {
39
39
  McpClient,
40
40
  SseTransport,
@@ -50,12 +50,12 @@ import {
50
50
  } from "./chunk-XHQIK7B6.js";
51
51
  import {
52
52
  MemoryStore
53
- } from "./chunk-YER7WCHF.js";
53
+ } from "./chunk-A63QT566.js";
54
54
  import {
55
55
  KeystrokeProvider,
56
56
  SingleSelect,
57
57
  useKeystroke
58
- } from "./chunk-T52GAWPP.js";
58
+ } from "./chunk-3VTV4WAH.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-ZJR4QLXB.js";
66
+ } from "./chunk-FB46F6H4.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-JULZ7JTO.js";
74
+ } from "./chunk-T5U5JO7Q.js";
75
75
  import {
76
76
  countTokens
77
77
  } from "./chunk-DAEAAVDF.js";
@@ -90,18 +90,21 @@ import {
90
90
  } from "./chunk-WJ3YX4PZ.js";
91
91
  import {
92
92
  SLASH_COMMANDS,
93
+ SLASH_GROUP_LABEL,
94
+ SLASH_GROUP_ORDER,
93
95
  archivePlanState,
94
96
  clearPlanState,
95
97
  countAdvancedCommands,
96
98
  detectSlashArgContext,
97
99
  listPlanArchives,
98
100
  loadPlanState,
101
+ orderSlashCommandsByGroup,
99
102
  parseSlash,
100
103
  relativeTime,
101
104
  resolveSlashAlias,
102
105
  savePlanState,
103
106
  suggestSlashCommands
104
- } from "./chunk-VF57YX2M.js";
107
+ } from "./chunk-NYP2DDDV.js";
105
108
  import {
106
109
  fetchSmitheryDetail,
107
110
  loadMorePages,
@@ -117,7 +120,7 @@ import {
117
120
  formatCommandResult,
118
121
  pauseGate,
119
122
  runCommand
120
- } from "./chunk-S4GF3HPO.js";
123
+ } from "./chunk-LY352GTC.js";
121
124
  import {
122
125
  PROJECT_MEMORY_FILE,
123
126
  SkillStore,
@@ -131,7 +134,7 @@ import {
131
134
  loadHooks,
132
135
  projectSettingsPath,
133
136
  runHooks
134
- } from "./chunk-JGZKTAOH.js";
137
+ } from "./chunk-LMNAMITH.js";
135
138
  import {
136
139
  deleteSession,
137
140
  detectGitBranch,
@@ -152,13 +155,23 @@ import {
152
155
  setLanguage,
153
156
  t,
154
157
  tObj
155
- } from "./chunk-GKZJXYMY.js";
158
+ } from "./chunk-FYKZB6TX.js";
156
159
  import {
160
+ CARD,
161
+ FG,
162
+ SURFACE,
163
+ TONE,
164
+ TONE_ACTIVE,
157
165
  addProjectShellAllowed,
166
+ balanceColor,
158
167
  clearProjectShellAllowed,
159
168
  defaultConfigPath,
160
169
  editModeHintShown,
170
+ formatBalance,
171
+ formatCost,
161
172
  isPlausibleKey,
173
+ isThemeName,
174
+ listThemeNames,
162
175
  loadApiKey,
163
176
  loadBaseUrl,
164
177
  loadEditMode,
@@ -180,19 +193,7 @@ import {
180
193
  webSearchEndpoint,
181
194
  webSearchEngine,
182
195
  writeConfig
183
- } from "./chunk-BHLHOS5Y.js";
184
- import {
185
- CARD,
186
- FG,
187
- SURFACE,
188
- TONE,
189
- TONE_ACTIVE,
190
- balanceColor,
191
- formatBalance,
192
- formatCost,
193
- isThemeName,
194
- listThemeNames
195
- } from "./chunk-WUI3P4RA.js";
196
+ } from "./chunk-BW2HWSYH.js";
196
197
  import {
197
198
  aggregateUsage,
198
199
  appendUsage,
@@ -214,7 +215,7 @@ import {
214
215
 
215
216
  // src/cli/commands/chat.tsx
216
217
  import { render } from "ink";
217
- import React67, { useState as useState28 } from "react";
218
+ import React68, { useState as useState29 } from "react";
218
219
 
219
220
  // src/mcp/summary.ts
220
221
  function buildMcpServerSummary(opts) {
@@ -237,8 +238,8 @@ function buildMcpServerSummary(opts) {
237
238
  // src/cli/ui/App.tsx
238
239
  import { statSync } from "fs";
239
240
  import { resolve as resolve2 } from "path";
240
- import { Box as Box51, Text as Text54, useStdout as useStdout16 } from "ink";
241
- import React64, { useCallback as useCallback13, useEffect as useEffect17, useMemo as useMemo10, useRef as useRef10, useState as useState26 } from "react";
241
+ import { Box as Box52, Text as Text55, useStdout as useStdout17 } from "ink";
242
+ import React65, { useCallback as useCallback13, useEffect as useEffect17, useMemo as useMemo11, useRef as useRef10, useState as useState27 } from "react";
242
243
 
243
244
  // src/code/checkpoints.ts
244
245
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
@@ -902,21 +903,21 @@ function HeaderRow({
902
903
  const lead = /* @__PURE__ */ React.createElement(Text, { color: color.primary, bold: true }, "@ ");
903
904
  if (state.kind === "browse") {
904
905
  const where = state.baseDir === "" ? "/" : `${state.baseDir}/`;
905
- const counter = state.loading ? "loading\u2026" : `${total} ${total === 1 ? "entry" : "entries"}`;
906
+ const counter = state.loading ? t("atMentions.loading") : t(total === 1 ? "atMentions.entrySingular" : "atMentions.entryPlural", { count: total });
906
907
  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);
907
908
  }
908
- const status2 = state.searching ? `searching\u2026 ${state.scanned} scanned \xB7 ${total} ${total === 1 ? "match" : "matches"}` : `${total} ${total === 1 ? "match" : "matches"} for "${state.filter}"`;
909
+ const status2 = state.searching ? `${t("atMentions.searching")} ${state.scanned} ${t("atMentions.scanned")} \xB7 ${total} ${total === 1 ? t("atMentions.match") : t("atMentions.matches")}` : `${total} ${total === 1 ? t("atMentions.match") : t("atMentions.matches")} ${t("atMentions.forFilter", { filter: state.filter })}`;
909
910
  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);
910
911
  }
911
912
  function EmptyRow({ state, color }) {
912
913
  if (state.kind === "browse") {
913
914
  if (state.loading) return null;
914
- 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"));
915
+ 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 }, t("atMentions.emptyDir")));
915
916
  }
916
917
  if (state.searching) {
917
- return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "scanning the tree\u2026"));
918
+ return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, t("atMentions.scanning")));
918
919
  }
919
- 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}"`));
920
+ 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 }, t("atMentions.noMatch", { filter: state.filter })));
920
921
  }
921
922
  function EntryRow({ entry, isSelected }) {
922
923
  const color = useColor();
@@ -926,8 +927,8 @@ function EntryRow({ entry, isSelected }) {
926
927
  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);
927
928
  }
928
929
  function FooterRow({ isBrowse, hasFolder }) {
929
- 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";
930
- return /* @__PURE__ */ React.createElement(Box, { marginTop: 0 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, ` ${hint}`));
930
+ const hintKey = isBrowse && hasFolder ? "atMentions.footerBrowse" : "atMentions.footerInsert";
931
+ return /* @__PURE__ */ React.createElement(Box, { marginTop: 0 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, ` ${t(hintKey)}`));
931
932
  }
932
933
 
933
934
  // src/cli/ui/BootSplash.tsx
@@ -1131,7 +1132,6 @@ var TONE_PALETTE = {
1131
1132
  accent: { color: CARD.plan.color, glyph: "\u229E" },
1132
1133
  info: { color: CARD.tool.color, glyph: "?" }
1133
1134
  };
1134
- var DEFAULT_FOOTER = "\u2191\u2193 pick \xB7 \u23CE confirm \xB7 esc cancel";
1135
1135
  function ApprovalCard({
1136
1136
  tone,
1137
1137
  glyph,
@@ -1139,14 +1139,15 @@ function ApprovalCard({
1139
1139
  metaRight,
1140
1140
  metaRightColor,
1141
1141
  children,
1142
- footerHint = DEFAULT_FOOTER
1142
+ footerHint
1143
1143
  }) {
1144
+ const effectiveFooter = footerHint ?? t("cardLabels.defaultFooter");
1144
1145
  const palette = TONE_PALETTE[tone];
1145
1146
  const headerGlyph = glyph ?? palette.glyph;
1146
1147
  const { stdout } = useStdout2();
1147
1148
  const cols = stdout?.columns ?? 80;
1148
1149
  const ruleWidth = Math.max(MIN_SEPARATOR, cols - SEPARATOR_PAD);
1149
- return /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "row" }, /* @__PURE__ */ React4.createElement(Text4, { color: palette.color, backgroundColor: SURFACE.bgElev }, " \u258E "), /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: palette.color, backgroundColor: SURFACE.bgElev }, `${headerGlyph} `), /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: FG.strong, backgroundColor: SURFACE.bgElev }, ` ${title} `), metaRight !== void 0 && /* @__PURE__ */ React4.createElement(Text4, { color: metaRightColor ?? FG.faint, backgroundColor: SURFACE.bgElev }, ` ${metaRight} `)), /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", paddingX: 2, marginTop: 1 }, children), /* @__PURE__ */ React4.createElement(Box4, { paddingX: 2, marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: FG.faint }, "\u2500".repeat(ruleWidth))), /* @__PURE__ */ React4.createElement(Box4, { paddingX: 2 }, /* @__PURE__ */ React4.createElement(Text4, { color: FG.faint }, footerHint)));
1150
+ return /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "row" }, /* @__PURE__ */ React4.createElement(Text4, { color: palette.color, backgroundColor: SURFACE.bgElev }, " \u258E "), /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: palette.color, backgroundColor: SURFACE.bgElev }, `${headerGlyph} `), /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: FG.strong, backgroundColor: SURFACE.bgElev }, ` ${title} `), metaRight !== void 0 && /* @__PURE__ */ React4.createElement(Text4, { color: metaRightColor ?? FG.faint, backgroundColor: SURFACE.bgElev }, ` ${metaRight} `)), /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", paddingX: 2, marginTop: 1 }, children), /* @__PURE__ */ React4.createElement(Box4, { paddingX: 2, marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: FG.faint }, "\u2500".repeat(ruleWidth))), /* @__PURE__ */ React4.createElement(Box4, { paddingX: 2 }, /* @__PURE__ */ React4.createElement(Text4, { color: FG.faint }, effectiveFooter)));
1150
1151
  }
1151
1152
 
1152
1153
  // src/cli/ui/layout/viewport-budget.tsx
@@ -1261,16 +1262,16 @@ function ChoiceConfirmInner({ question, options: options2, allowCustom, onChoose
1261
1262
  if (allowCustom) {
1262
1263
  items.push({
1263
1264
  value: CUSTOM_VALUE,
1264
- label: "Let me type my own answer",
1265
- hint: "None of the above fits \u2014 type a free-form reply. The model reads it verbatim."
1265
+ label: t("choiceConfirm.customLabel"),
1266
+ hint: t("choiceConfirm.customDesc")
1266
1267
  });
1267
1268
  }
1268
1269
  items.push({
1269
1270
  value: CANCEL_VALUE,
1270
- label: "Cancel \u2014 drop the question",
1271
- hint: "Model stops and asks what you want instead."
1271
+ label: t("choiceConfirm.cancelLabel"),
1272
+ hint: t("choiceConfirm.cancelDesc")
1272
1273
  });
1273
- return /* @__PURE__ */ React6.createElement(ApprovalCard, { tone: "info", title: question, metaRight: "awaiting" }, /* @__PURE__ */ React6.createElement(
1274
+ return /* @__PURE__ */ React6.createElement(ApprovalCard, { tone: "info", title: question, metaRight: t("shellConfirm.awaiting") }, /* @__PURE__ */ React6.createElement(
1274
1275
  SingleSelect,
1275
1276
  {
1276
1277
  initialValue: options2[0]?.id,
@@ -1515,7 +1516,6 @@ function Cell({
1515
1516
  // src/cli/ui/EditConfirm.tsx
1516
1517
  var MODAL_OVERHEAD_ROWS = 18;
1517
1518
  var MIN_DIFF_ROWS = 8;
1518
- var REVIEW_FOOTER = "[y/Enter] apply \xB7 [n] reject with reason \xB7 [a] apply rest \xB7 [A] flip AUTO \xB7 [\u2191\u2193/Space] scroll \xB7 [Esc] abort";
1519
1519
  function EditConfirm({ block: block2, onChoose }) {
1520
1520
  const rows = useTotalRows();
1521
1521
  const allocated = useReserveRows("modal", {
@@ -1580,7 +1580,7 @@ function EditConfirm({ block: block2, onChoose }) {
1580
1580
  const isNew = block2.search === "";
1581
1581
  const removed = isNew ? 0 : (block2.search.match(/\n/g)?.length ?? 0) + 1;
1582
1582
  const added = block2.replace === "" ? 0 : (block2.replace.match(/\n/g)?.length ?? 0) + 1;
1583
- const tag2 = isNew ? "NEW" : "EDIT";
1583
+ const tag2 = isNew ? t("editConfirm.newTag") : t("editConfirm.editTag");
1584
1584
  const tone = isNew ? "ok" : "warn";
1585
1585
  const glyph = isNew ? "\u271A" : "\u270E";
1586
1586
  const visibleRows = allRows.slice(effectiveScroll, effectiveScroll + budget2);
@@ -1588,10 +1588,14 @@ function EditConfirm({ block: block2, onChoose }) {
1588
1588
  const hiddenBelow = Math.max(0, allRows.length - effectiveScroll - budget2);
1589
1589
  const totalLines = allRows.length;
1590
1590
  const showScrollHud = hiddenAbove + hiddenBelow > 0;
1591
- const metaParts = [`-${removed} +${added} lines`];
1591
+ const metaParts = [t("editConfirm.linesCount", { removed, added })];
1592
1592
  if (showScrollHud) {
1593
1593
  metaParts.push(
1594
- `viewing ${effectiveScroll + 1}-${effectiveScroll + visibleRows.length}/${totalLines}`
1594
+ t("editConfirm.viewingRange", {
1595
+ start: effectiveScroll + 1,
1596
+ end: effectiveScroll + visibleRows.length,
1597
+ total: totalLines
1598
+ })
1595
1599
  );
1596
1600
  }
1597
1601
  if (phase === "context") {
@@ -1600,9 +1604,9 @@ function EditConfirm({ block: block2, onChoose }) {
1600
1604
  {
1601
1605
  tone: "error",
1602
1606
  glyph: "\u2717",
1603
- title: "Deny \u2014 provide context",
1604
- metaRight: "optional",
1605
- footerHint: "\u23CE submit \xB7 esc skip (deny without reason)"
1607
+ title: t("shellConfirm.denyTitle"),
1608
+ metaRight: t("shellConfirm.optional"),
1609
+ footerHint: t("editConfirm.denyFooter")
1606
1610
  },
1607
1611
  /* @__PURE__ */ React9.createElement(
1608
1612
  DenyContextInput,
@@ -1620,24 +1624,16 @@ function EditConfirm({ block: block2, onChoose }) {
1620
1624
  glyph,
1621
1625
  title: `${tag2} ${block2.path}`,
1622
1626
  metaRight: metaParts.join(" \xB7 "),
1623
- footerHint: REVIEW_FOOTER
1627
+ footerHint: t("editConfirm.footer")
1624
1628
  },
1625
- hiddenAbove > 0 ? /* @__PURE__ */ React9.createElement(
1626
- Text7,
1627
- {
1628
- dimColor: true
1629
- },
1630
- ` \u2191 ${hiddenAbove} line${hiddenAbove === 1 ? "" : "s"} above (\u2191/k or PgUp)`
1631
- ) : null,
1629
+ hiddenAbove > 0 ? /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, t(hiddenAbove === 1 ? "editConfirm.linesAbove" : "editConfirm.linesAbovePlural", {
1630
+ count: hiddenAbove
1631
+ })) : null,
1632
1632
  /* @__PURE__ */ React9.createElement(SplitDiff, { rows: visibleRows }),
1633
- /* @__PURE__ */ React9.createElement(Box7, null, /* @__PURE__ */ React9.createElement(Text7, { color: "#fbc8c8", backgroundColor: "#2a1212" }, " - old "), /* @__PURE__ */ React9.createElement(Text7, null, " "), /* @__PURE__ */ React9.createElement(Text7, { color: "#bef0c8", backgroundColor: "#0c2718" }, " + new "), /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, " side-by-side \xB7 removed lines on the left, added on the right \xB7 paired by offset")),
1634
- hiddenBelow > 0 ? /* @__PURE__ */ React9.createElement(
1635
- Text7,
1636
- {
1637
- dimColor: true
1638
- },
1639
- ` \u2193 ${hiddenBelow} line${hiddenBelow === 1 ? "" : "s"} below (\u2193/j or Space/PgDn)`
1640
- ) : null
1633
+ /* @__PURE__ */ React9.createElement(Box7, null, /* @__PURE__ */ React9.createElement(Text7, { color: "#fbc8c8", backgroundColor: "#2a1212" }, t("editConfirm.oldLabel")), /* @__PURE__ */ React9.createElement(Text7, null, " "), /* @__PURE__ */ React9.createElement(Text7, { color: "#bef0c8", backgroundColor: "#0c2718" }, t("editConfirm.newLabel")), /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, t("editConfirm.sideBySide"))),
1634
+ hiddenBelow > 0 ? /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, t(hiddenBelow === 1 ? "editConfirm.linesBelow" : "editConfirm.linesBelowPlural", {
1635
+ count: hiddenBelow
1636
+ })) : null
1641
1637
  );
1642
1638
  }
1643
1639
 
@@ -2325,12 +2321,12 @@ function ModelPicker({
2325
2321
  const loading = models === null;
2326
2322
  const empty = models !== null && models.length === 0;
2327
2323
  let lastSection = null;
2328
- return /* @__PURE__ */ React14.createElement(Box11, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React14.createElement(Box11, null, /* @__PURE__ */ React14.createElement(Text12, { bold: true, color: TONE.brand }, " \u25C8 REASONIX \xB7 pick a setup "), /* @__PURE__ */ React14.createElement(Text12, { color: FG.meta }, loading ? " \xB7 loading catalog\u2026" : empty ? " \xB7 catalog empty \u2014 using known fallbacks" : ` \xB7 ${modelList.length} models available`)), /* @__PURE__ */ React14.createElement(Box11, { height: 1 }), hiddenAbove > 0 ? /* @__PURE__ */ React14.createElement(Box11, null, /* @__PURE__ */ React14.createElement(Text12, { color: FG.faint }, ` \u2026 ${hiddenAbove} earlier`)) : null, shown.map((row2, i) => {
2324
+ return /* @__PURE__ */ React14.createElement(Box11, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React14.createElement(Box11, null, /* @__PURE__ */ React14.createElement(Text12, { bold: true, color: TONE.brand }, t("modelPicker.header")), /* @__PURE__ */ React14.createElement(Text12, { color: FG.meta }, loading ? t("modelPicker.loading") : empty ? t("modelPicker.catalogEmpty") : t("modelPicker.modelsAvailable", { count: modelList.length }))), /* @__PURE__ */ React14.createElement(Box11, { height: 1 }), hiddenAbove > 0 ? /* @__PURE__ */ React14.createElement(Box11, null, /* @__PURE__ */ React14.createElement(Text12, { color: FG.faint }, ` \u2026 ${hiddenAbove}`)) : null, shown.map((row2, i) => {
2329
2325
  const idx = start + i;
2330
2326
  const focused = idx === focus;
2331
2327
  const showHeader = row2.kind !== lastSection;
2332
2328
  lastSection = row2.kind;
2333
- const header = showHeader ? /* @__PURE__ */ React14.createElement(Box11, { key: `hdr-${row2.kind}`, marginTop: idx === 0 ? 0 : 1 }, /* @__PURE__ */ React14.createElement(Text12, { color: FG.meta }, row2.kind === "preset" ? " PRESETS \xB7 recommended \u2014 model + effort + auto-escalate" : " MODELS \xB7 raw pick \u2014 auto-escalate stays as-is")) : null;
2329
+ const header = showHeader ? /* @__PURE__ */ React14.createElement(Box11, { key: `hdr-${row2.kind}`, marginTop: idx === 0 ? 0 : 1 }, /* @__PURE__ */ React14.createElement(Text12, { color: FG.meta }, row2.kind === "preset" ? t("modelPicker.presetsHeader") : t("modelPicker.modelsHeader"))) : null;
2334
2330
  const body = row2.kind === "preset" ? /* @__PURE__ */ React14.createElement(
2335
2331
  PresetRow,
2336
2332
  {
@@ -2349,7 +2345,7 @@ function ModelPicker({
2349
2345
  }
2350
2346
  );
2351
2347
  return /* @__PURE__ */ React14.createElement(React14.Fragment, { key: `row-${idx}` }, header, body);
2352
- }), hiddenBelow > 0 ? /* @__PURE__ */ React14.createElement(Box11, null, /* @__PURE__ */ React14.createElement(Text12, { color: FG.faint }, ` \u2026 ${hiddenBelow} more`)) : null, /* @__PURE__ */ React14.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text12, { color: FG.faint }, " \u2191\u2193 pick \xB7 \u23CE confirm \xB7 [r] refresh \xB7 esc cancel")));
2348
+ }), hiddenBelow > 0 ? /* @__PURE__ */ React14.createElement(Box11, null, /* @__PURE__ */ React14.createElement(Text12, { color: FG.faint }, t("cardLabels.more", { count: hiddenBelow }))) : null, /* @__PURE__ */ React14.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text12, { color: FG.faint }, t("modelPicker.pickerFooter"))));
2353
2349
  }
2354
2350
  function PresetRow({
2355
2351
  name,
@@ -2357,7 +2353,7 @@ function PresetRow({
2357
2353
  active
2358
2354
  }) {
2359
2355
  const desc = PRESET_DESCRIPTIONS[name];
2360
- return /* @__PURE__ */ React14.createElement(Box11, null, /* @__PURE__ */ React14.createElement(Text12, { color: focused ? TONE.brand : FG.faint }, focused ? " \u25B8 " : " "), /* @__PURE__ */ React14.createElement(Text12, { bold: focused, color: focused ? FG.strong : FG.sub }, name.padEnd(8)), /* @__PURE__ */ React14.createElement(Text12, { color: focused ? FG.body : FG.meta }, desc.headline.padEnd(28)), /* @__PURE__ */ React14.createElement(Text12, { color: FG.meta }, ` ${desc.cost}`), active ? /* @__PURE__ */ React14.createElement(Text12, { color: TONE.brand }, " \xB7 current") : null);
2356
+ return /* @__PURE__ */ React14.createElement(Box11, null, /* @__PURE__ */ React14.createElement(Text12, { color: focused ? TONE.brand : FG.faint }, focused ? " \u25B8 " : " "), /* @__PURE__ */ React14.createElement(Text12, { bold: focused, color: focused ? FG.strong : FG.sub }, name.padEnd(8)), /* @__PURE__ */ React14.createElement(Text12, { color: focused ? FG.body : FG.meta }, desc.headline.padEnd(28)), /* @__PURE__ */ React14.createElement(Text12, { color: FG.meta }, ` ${desc.cost}`), active ? /* @__PURE__ */ React14.createElement(Text12, { color: TONE.brand }, t("modelPicker.currentLabel")) : null);
2361
2357
  }
2362
2358
  function ModelRow({
2363
2359
  id,
@@ -2365,7 +2361,7 @@ function ModelRow({
2365
2361
  active
2366
2362
  }) {
2367
2363
  const badge = modelBadgeFor(id);
2368
- return /* @__PURE__ */ React14.createElement(Box11, null, /* @__PURE__ */ React14.createElement(Text12, { color: focused ? TONE.brand : FG.faint }, focused ? " \u25B8 " : " "), /* @__PURE__ */ React14.createElement(Text12, { bold: focused, color: focused ? FG.strong : FG.sub }, id.padEnd(24)), /* @__PURE__ */ React14.createElement(Text12, null, " "), /* @__PURE__ */ React14.createElement(Pill, { label: badge.label, ...PILL_MODEL[badge.kind], bold: false }), active ? /* @__PURE__ */ React14.createElement(Text12, { color: TONE.brand }, " \xB7 current") : null);
2364
+ return /* @__PURE__ */ React14.createElement(Box11, null, /* @__PURE__ */ React14.createElement(Text12, { color: focused ? TONE.brand : FG.faint }, focused ? " \u25B8 " : " "), /* @__PURE__ */ React14.createElement(Text12, { bold: focused, color: focused ? FG.strong : FG.sub }, id.padEnd(24)), /* @__PURE__ */ React14.createElement(Text12, null, " "), /* @__PURE__ */ React14.createElement(Pill, { label: badge.label, ...PILL_MODEL[badge.kind], bold: false }), active ? /* @__PURE__ */ React14.createElement(Text12, { color: TONE.brand }, t("modelPicker.currentLabel")) : null);
2369
2365
  }
2370
2366
  function detectActivePreset(model2, effort, autoEscalate) {
2371
2367
  for (const name of PRESET_NAMES) {
@@ -5967,7 +5963,7 @@ function HintRow() {
5967
5963
  const items = [
5968
5964
  { key: "\u23CE", tKey: "composer.hintSend" },
5969
5965
  { key: "\u21E7\u23CE", tKey: "composer.hintNewline" },
5970
- { key: "\u2191\u2193", tKey: "composer.hintScroll" },
5966
+ { key: "^U", tKey: "composer.hintClear" },
5971
5967
  { key: "^P/^N", tKey: "composer.hintHistory" },
5972
5968
  { key: "esc", tKey: "composer.hintAbort" },
5973
5969
  { key: "^C", tKey: "composer.hintQuit" }
@@ -6221,10 +6217,11 @@ function SessionPicker({
6221
6217
  const snapshot = useMemo5(
6222
6218
  () => ({
6223
6219
  pickerKind: "sessions",
6224
- title: `pick a session \u2014 ${workspace}`,
6220
+ title: t("sessionPicker.title", { workspace }),
6225
6221
  items: sessions2.map((s) => {
6226
6222
  const branch = s.meta.branch ?? "main";
6227
- const summary = s.meta.summary ?? `${s.messageCount} message${s.messageCount === 1 ? "" : "s"}`;
6223
+ const count = s.messageCount;
6224
+ const summary = s.meta.summary ?? t(count === 1 ? "sessionPicker.messages" : "sessionPicker.messagesPlural", { count });
6228
6225
  const turns = s.meta.turnCount ?? Math.ceil(s.messageCount / 2);
6229
6226
  const currency = walletCurrency ?? s.meta.balanceCurrency;
6230
6227
  const costLabel = s.meta.totalCostUsd !== void 0 ? formatCost(s.meta.totalCostUsd, currency, 2) : "";
@@ -6233,11 +6230,11 @@ function SessionPicker({
6233
6230
  title: s.name,
6234
6231
  subtitle: summary,
6235
6232
  badge: branch,
6236
- meta: costLabel ? `${turns} turns \xB7 ${costLabel}` : `${turns} turns`
6233
+ meta: costLabel ? `${t("sessionPicker.turns", { count: turns })} \xB7 ${costLabel}` : t("sessionPicker.turns", { count: turns })
6237
6234
  };
6238
6235
  }),
6239
6236
  actions: ["pick", "delete", "rename", "new", "cancel"],
6240
- hint: "\u2191\u2193 pick \xB7 \u23CE open \xB7 [n] new \xB7 [d] delete \xB7 [r] rename \xB7 esc quit"
6237
+ hint: t("sessionPicker.pickerHint")
6241
6238
  }),
6242
6239
  [sessions2, workspace, walletCurrency]
6243
6240
  );
@@ -6311,7 +6308,7 @@ function SessionPicker({
6311
6308
  const end = Math.min(sessions2.length, start + visibleCount);
6312
6309
  const shown = sessions2.slice(start, end);
6313
6310
  const hiddenBelow = sessions2.length - end;
6314
- return /* @__PURE__ */ React25.createElement(Box21, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React25.createElement(Box21, null, /* @__PURE__ */ React25.createElement(Text21, { bold: true, color: TONE.brand }, " \u25C8 REASONIX \xB7 pick a session "), /* @__PURE__ */ React25.createElement(Text21, { color: FG.meta }, ` \xB7 ${workspace}`)), /* @__PURE__ */ React25.createElement(Box21, { height: 1 }), sessions2.length === 0 ? /* @__PURE__ */ React25.createElement(Box21, null, /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, " no saved sessions in this workspace yet \u2014 press "), /* @__PURE__ */ React25.createElement(Text21, { bold: true, color: TONE.brand }, "\u23CE"), /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, " to start a new one")) : shown.map((s, i) => /* @__PURE__ */ React25.createElement(
6311
+ return /* @__PURE__ */ React25.createElement(Box21, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React25.createElement(Box21, null, /* @__PURE__ */ React25.createElement(Text21, { bold: true, color: TONE.brand }, t("sessionPicker.header")), /* @__PURE__ */ React25.createElement(Text21, { color: FG.meta }, ` \xB7 ${workspace}`)), /* @__PURE__ */ React25.createElement(Box21, { height: 1 }), sessions2.length === 0 ? /* @__PURE__ */ React25.createElement(Box21, null, /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, t("sessionPicker.empty")), /* @__PURE__ */ React25.createElement(Text21, { bold: true, color: TONE.brand }, "\u23CE"), /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, t("sessionPicker.emptyNew"))) : shown.map((s, i) => /* @__PURE__ */ React25.createElement(
6315
6312
  SessionRow,
6316
6313
  {
6317
6314
  key: s.name,
@@ -6319,7 +6316,7 @@ function SessionPicker({
6319
6316
  focused: start + i === focus,
6320
6317
  walletCurrency
6321
6318
  }
6322
- )), hiddenBelow > 0 ? /* @__PURE__ */ React25.createElement(Box21, null, /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, ` \u2026 ${hiddenBelow} more`)) : null, renaming ? /* @__PURE__ */ React25.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, ` rename "${renaming.from}" \u2192 `), /* @__PURE__ */ React25.createElement(Text21, { bold: true, color: TONE.brand }, renaming.buf), /* @__PURE__ */ React25.createElement(Text21, { backgroundColor: TONE.brand, color: "black" }, " ")) : null, /* @__PURE__ */ React25.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, renaming ? " \u23CE confirm rename \xB7 esc cancel" : sessions2.length === 0 ? " \u23CE new session \xB7 esc quit" : " \u2191\u2193 pick \xB7 \u23CE open \xB7 [n] new \xB7 [d] delete \xB7 [r] rename \xB7 esc quit")));
6319
+ )), hiddenBelow > 0 ? /* @__PURE__ */ React25.createElement(Box21, null, /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, t("cardLabels.more", { count: hiddenBelow }))) : null, renaming ? /* @__PURE__ */ React25.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, t("sessionPicker.renamePrompt", { from: renaming.from })), /* @__PURE__ */ React25.createElement(Text21, { bold: true, color: TONE.brand }, renaming.buf), /* @__PURE__ */ React25.createElement(Text21, { backgroundColor: TONE.brand, color: "black" }, " ")) : null, /* @__PURE__ */ React25.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, renaming ? t("sessionPicker.renameHint") : sessions2.length === 0 ? t("sessionPicker.emptyHint") : t("sessionPicker.pickerHint"))));
6323
6320
  }
6324
6321
  function SessionRow({
6325
6322
  info,
@@ -6327,12 +6324,13 @@ function SessionRow({
6327
6324
  walletCurrency
6328
6325
  }) {
6329
6326
  const branch = info.meta.branch ?? "main";
6330
- const summary = info.meta.summary ?? `${info.messageCount} message${info.messageCount === 1 ? "" : "s"}`;
6327
+ const count = info.messageCount;
6328
+ const summary = info.meta.summary ?? t(count === 1 ? "sessionPicker.messages" : "sessionPicker.messagesPlural", { count });
6331
6329
  const turns = info.meta.turnCount ?? Math.ceil(info.messageCount / 2);
6332
6330
  const currency = walletCurrency ?? info.meta.balanceCurrency;
6333
6331
  const costLabel = info.meta.totalCostUsd !== void 0 ? formatCost(info.meta.totalCostUsd, currency, 2) : "";
6334
6332
  const time = relativeTime2(info.mtime);
6335
- return /* @__PURE__ */ React25.createElement(Box21, null, /* @__PURE__ */ React25.createElement(Text21, { color: focused ? TONE.brand : FG.faint }, focused ? " \u25B8 " : " "), /* @__PURE__ */ React25.createElement(Text21, { bold: focused, color: focused ? FG.strong : FG.sub }, info.name.padEnd(12)), /* @__PURE__ */ React25.createElement(Text21, { color: FG.meta }, ` \xB7 ${branch.padEnd(8)} \xB7 `), /* @__PURE__ */ React25.createElement(Text21, { color: focused ? FG.body : FG.sub }, truncate(summary, 40)), /* @__PURE__ */ React25.createElement(Box21, { flexGrow: 1 }), /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, `${time.padStart(11)} `), /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, `${turns} turns`), costLabel ? /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, ` \xB7 ${costLabel}`) : null);
6333
+ return /* @__PURE__ */ React25.createElement(Box21, null, /* @__PURE__ */ React25.createElement(Text21, { color: focused ? TONE.brand : FG.faint }, focused ? " \u25B8 " : " "), /* @__PURE__ */ React25.createElement(Text21, { bold: focused, color: focused ? FG.strong : FG.sub }, info.name.padEnd(12)), /* @__PURE__ */ React25.createElement(Text21, { color: FG.meta }, ` \xB7 ${branch.padEnd(8)} \xB7 `), /* @__PURE__ */ React25.createElement(Text21, { color: focused ? FG.body : FG.sub }, truncate(summary, 40)), /* @__PURE__ */ React25.createElement(Box21, { flexGrow: 1 }), /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, `${time.padStart(11)} `), /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, t("sessionPicker.turns", { count: turns })), costLabel ? /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, ` \xB7 ${costLabel}`) : null);
6336
6334
  }
6337
6335
  function truncate(s, max) {
6338
6336
  if (s.length <= max) return s;
@@ -6341,13 +6339,13 @@ function truncate(s, max) {
6341
6339
  function relativeTime2(date) {
6342
6340
  const ms = Date.now() - date.getTime();
6343
6341
  const mins = Math.floor(ms / 6e4);
6344
- if (mins < 1) return "just now";
6345
- if (mins < 60) return `${mins} min ago`;
6342
+ if (mins < 1) return t("sessionPicker.justNow");
6343
+ if (mins < 60) return t("sessionPicker.minAgo", { count: mins });
6346
6344
  const hours = Math.floor(mins / 60);
6347
- if (hours < 24) return `${hours}h ago`;
6345
+ if (hours < 24) return t("sessionPicker.hoursAgo", { count: hours });
6348
6346
  const days = Math.floor(hours / 24);
6349
- if (days === 1) return "yesterday";
6350
- if (days < 7) return `${days} days ago`;
6347
+ if (days === 1) return t("sessionPicker.yesterday");
6348
+ if (days < 7) return t("sessionPicker.daysAgo", { count: days });
6351
6349
  return date.toISOString().slice(0, 10);
6352
6350
  }
6353
6351
 
@@ -6357,7 +6355,7 @@ import React26, { useState as useState14 } from "react";
6357
6355
  function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
6358
6356
  useReserveRows("modal", { min: 8, max: 14 });
6359
6357
  const isBackground = kind === "run_background";
6360
- const subtitle = isBackground ? "long-running process \u2014 keeps running after approval, /kill to stop" : "model wants to run a shell command";
6358
+ const subtitle = isBackground ? t("shellConfirm.bgSubtitle") : t("shellConfirm.subtitle");
6361
6359
  const [phase, setPhase] = useState14("pick");
6362
6360
  if (phase === "deny") {
6363
6361
  return /* @__PURE__ */ React26.createElement(
@@ -6365,9 +6363,9 @@ function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
6365
6363
  {
6366
6364
  tone: "error",
6367
6365
  glyph: "\u2717",
6368
- title: "Deny \u2014 provide context",
6369
- metaRight: "optional",
6370
- footerHint: "type context \xB7 \u23CE submit with reason \xB7 esc skip (deny without reason)"
6366
+ title: t("shellConfirm.denyTitle"),
6367
+ metaRight: t("shellConfirm.optional"),
6368
+ footerHint: t("shellConfirm.denyFooter")
6371
6369
  },
6372
6370
  /* @__PURE__ */ React26.createElement(
6373
6371
  DenyContextInput,
@@ -6383,9 +6381,9 @@ function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
6383
6381
  {
6384
6382
  tone: "warn",
6385
6383
  glyph: isBackground ? "\u23F1" : "?",
6386
- title: isBackground ? "Background process" : "Shell command",
6387
- metaRight: "awaiting",
6388
- footerHint: "\u2191\u2193 pick \xB7 \u23CE confirm \xB7 Tab add context \xB7 esc cancel"
6384
+ title: isBackground ? t("shellConfirm.bgTitle") : t("shellConfirm.title"),
6385
+ metaRight: t("shellConfirm.awaiting"),
6386
+ footerHint: t("shellConfirm.pickFooter")
6389
6387
  },
6390
6388
  /* @__PURE__ */ React26.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React26.createElement(Text22, { color: FG.faint }, subtitle)),
6391
6389
  /* @__PURE__ */ React26.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React26.createElement(Text22, { bold: true, color: TONE.err }, "$ "), /* @__PURE__ */ React26.createElement(Text22, { bold: true, color: FG.strong }, command)),
@@ -6396,18 +6394,18 @@ function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
6396
6394
  items: [
6397
6395
  {
6398
6396
  value: "run_once",
6399
- label: "allow once",
6400
- hint: "run this command, ask again next time"
6397
+ label: t("shellConfirm.allowOnce"),
6398
+ hint: t("shellConfirm.allowOnceDesc")
6401
6399
  },
6402
6400
  {
6403
6401
  value: "always_allow",
6404
- label: "allow always",
6405
- hint: `remember \`${allowPrefix}\` for this project`
6402
+ label: t("shellConfirm.allowAlways"),
6403
+ hint: t("shellConfirm.allowAlwaysDesc", { prefix: allowPrefix })
6406
6404
  },
6407
6405
  {
6408
6406
  value: "deny",
6409
- label: "deny",
6410
- hint: "press Tab to add context telling the model why"
6407
+ label: t("shellConfirm.deny"),
6408
+ hint: t("shellConfirm.denyDesc")
6411
6409
  }
6412
6410
  ],
6413
6411
  onSubmit: (v) => {
@@ -6490,16 +6488,10 @@ var GROUP_MODE_MAX_ROWS = 24;
6490
6488
  var SEARCH_MODE_MAX_ROWS = 8;
6491
6489
  var COMMAND_NAME_CELLS = 14;
6492
6490
  var ARGS_CELLS = 14;
6493
- var GROUP_LABEL = {
6494
- chat: "CHAT",
6495
- setup: "SETUP",
6496
- info: "INFO",
6497
- session: "SESSION",
6498
- extend: "EXTEND",
6499
- code: "CODE",
6500
- jobs: "JOBS",
6501
- advanced: "ADVANCED"
6502
- };
6491
+ function groupLabel(group) {
6492
+ const key = `slashSuggestions.group${group.charAt(0).toUpperCase() + group.slice(1)}`;
6493
+ return t(key);
6494
+ }
6503
6495
  function SlashSuggestions({
6504
6496
  matches,
6505
6497
  selectedIndex,
@@ -6524,14 +6516,17 @@ function SlashSuggestions({
6524
6516
  }, [windowStart]);
6525
6517
  if (matches === null) return null;
6526
6518
  if (matches.length === 0) {
6527
- return /* @__PURE__ */ React28.createElement(Box24, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text24, { color: color.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React28.createElement(Text24, null, " "), /* @__PURE__ */ React28.createElement(Text24, { color: color.warn }, "no slash command matches that prefix"), /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, " \u2014 Backspace to edit, or /help for the full list"));
6519
+ return /* @__PURE__ */ React28.createElement(Box24, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text24, { color: color.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React28.createElement(Text24, null, " "), /* @__PURE__ */ React28.createElement(Text24, { color: color.warn }, t("slashSuggestions.noMatch")), /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, t("slashSuggestions.backspaceHint")));
6528
6520
  }
6529
6521
  const total = matches.length;
6530
6522
  const items = buildVisibleItems(matches, windowStart, maxRows, groupMode);
6531
6523
  const shownCommands = items.filter((item) => item.kind === "command");
6532
6524
  const hiddenAbove = windowStart;
6533
6525
  const hiddenBelow = total - windowStart - shownCommands.length;
6534
- return /* @__PURE__ */ React28.createElement(Box24, { flexDirection: "column", paddingX: 1, marginTop: 1, flexShrink: 0, flexWrap: "nowrap" }, /* @__PURE__ */ React28.createElement(Box24, null, /* @__PURE__ */ React28.createElement(Text24, { color: color.accent, bold: true }, "/ "), /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, `${total} command${total === 1 ? "" : "s"}`), hiddenAbove > 0 ? /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null), items.map((item) => {
6526
+ return /* @__PURE__ */ React28.createElement(Box24, { flexDirection: "column", paddingX: 1, marginTop: 1, flexShrink: 0, flexWrap: "nowrap" }, /* @__PURE__ */ React28.createElement(Box24, null, /* @__PURE__ */ React28.createElement(Text24, { color: color.accent, bold: true }, "/ "), /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, t(
6527
+ total === 1 ? "slashSuggestions.commandCount" : "slashSuggestions.commandCountPlural",
6528
+ { count: total }
6529
+ )), hiddenAbove > 0 ? /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, t("slashSuggestions.aboveLabel", { count: hiddenAbove })) : null), items.map((item) => {
6535
6530
  if (item.kind === "group") {
6536
6531
  return /* @__PURE__ */ React28.createElement(GroupHeader, { key: `group:${item.group}:${item.beforeIndex}`, group: item.group });
6537
6532
  }
@@ -6544,7 +6539,7 @@ function SlashSuggestions({
6544
6539
  columns: cols
6545
6540
  }
6546
6541
  );
6547
- }), hiddenBelow > 0 ? /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, ` \u2193 ${hiddenBelow} below`) : null, groupMode && advancedHidden && advancedHidden > 0 ? /* @__PURE__ */ React28.createElement(Box24, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, ` + ${advancedHidden} advanced \xB7 type a letter to search`)) : null, /* @__PURE__ */ React28.createElement(Box24, { marginTop: 0 }, /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, " \u2191\u2193 navigate \xB7 Tab / \u23CE pick \xB7 esc cancel")));
6542
+ }), hiddenBelow > 0 ? /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, t("slashSuggestions.belowLabel", { count: hiddenBelow })) : null, groupMode && advancedHidden && advancedHidden > 0 ? /* @__PURE__ */ React28.createElement(Box24, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, t("slashSuggestions.advancedHint", { count: advancedHidden }))) : null, /* @__PURE__ */ React28.createElement(Box24, { marginTop: 0 }, /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, t("slashSuggestions.footerHint"))));
6548
6543
  }
6549
6544
  function computeWindowStart(matches, maxRows, selectedIndex, currentWindowStart, groupMode = false) {
6550
6545
  if (matches.length <= 0) return 0;
@@ -6576,7 +6571,7 @@ function shouldShowGroupHeader(matches, idx) {
6576
6571
  return idx === 0 || matches[idx]?.group !== matches[idx - 1]?.group;
6577
6572
  }
6578
6573
  function GroupHeader({ group }) {
6579
- return /* @__PURE__ */ React28.createElement(Box24, { flexShrink: 0, height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React28.createElement(Text24, { dimColor: true, wrap: "truncate" }, ` ${GROUP_LABEL[group]}`));
6574
+ return /* @__PURE__ */ React28.createElement(Box24, { flexShrink: 0, height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React28.createElement(Text24, { dimColor: true, wrap: "truncate" }, ` ${groupLabel(group)}`));
6580
6575
  }
6581
6576
  function SuggestionRow({
6582
6577
  spec,
@@ -6662,7 +6657,7 @@ function WelcomeBanner({
6662
6657
  },
6663
6658
  /* @__PURE__ */ React30.createElement(Box26, { flexDirection: "row", gap: 2 }, /* @__PURE__ */ React30.createElement(Text26, { color: TONE.brand, bold: true }, "REASONIX"), /* @__PURE__ */ React30.createElement(Text26, { color: FG.faint }, "\xD7"), /* @__PURE__ */ React30.createElement(Box26, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React30.createElement(Text26, null, "\u{1F40B}"), /* @__PURE__ */ React30.createElement(Text26, { color: TONE.accent, bold: true }, "DeepSeek"))),
6664
6659
  /* @__PURE__ */ React30.createElement(Box26, { marginTop: 1, flexDirection: "column", alignItems: "center" }, /* @__PURE__ */ React30.createElement(Text26, { color: FG.body }, tagline), /* @__PURE__ */ React30.createElement(Text26, { color: FG.meta }, taglineSub))
6665
- ), /* @__PURE__ */ React30.createElement(Box26, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(Text26, { color: FG.sub }, startTextRaw)), /* @__PURE__ */ React30.createElement(Box26, { marginTop: 1, flexDirection: "row", gap: 3 }, HINTS.map((cmd) => /* @__PURE__ */ React30.createElement(Text26, { key: cmd, color: FG.meta }, cmd))), inCodeMode && workspaceRoot ? /* @__PURE__ */ React30.createElement(Box26, { marginTop: 1, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React30.createElement(Text26, { color: TONE.brand }, "\u25B8 workspace"), /* @__PURE__ */ React30.createElement(Text26, { color: FG.faint }, "\xB7"), /* @__PURE__ */ React30.createElement(Text26, { color: FG.body }, workspaceRoot), /* @__PURE__ */ React30.createElement(Text26, { color: FG.faint }, " (relaunch with --dir <path> to switch)")) : null, dashboardUrl ? /* @__PURE__ */ React30.createElement(Box26, { marginTop: 1, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React30.createElement(Text26, { color: TONE.brand, bold: true }, "\u25B8 web"), /* @__PURE__ */ React30.createElement(Text26, { color: FG.faint }, "\xB7"), /* @__PURE__ */ React30.createElement(Text26, { color: TONE.accent }, dashboardUrl)) : null);
6660
+ ), /* @__PURE__ */ React30.createElement(Box26, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(Text26, { color: FG.sub }, startTextRaw)), /* @__PURE__ */ React30.createElement(Box26, { marginTop: 1, flexDirection: "row", gap: 3 }, HINTS.map((cmd) => /* @__PURE__ */ React30.createElement(Text26, { key: cmd, color: FG.meta }, cmd))), inCodeMode && workspaceRoot ? /* @__PURE__ */ React30.createElement(Box26, { marginTop: 1, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React30.createElement(Text26, { color: TONE.brand }, t("welcomeBanner.workspace")), /* @__PURE__ */ React30.createElement(Text26, { color: FG.faint }, "\xB7"), /* @__PURE__ */ React30.createElement(Text26, { color: FG.body }, workspaceRoot), /* @__PURE__ */ React30.createElement(Text26, { color: FG.faint }, t("welcomeBanner.relaunchHint"))) : null, dashboardUrl ? /* @__PURE__ */ React30.createElement(Box26, { marginTop: 1, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React30.createElement(Text26, { color: TONE.brand, bold: true }, t("welcomeBanner.dashboard")), /* @__PURE__ */ React30.createElement(Text26, { color: FG.faint }, "\xB7"), /* @__PURE__ */ React30.createElement(Text26, { color: TONE.accent }, dashboardUrl)) : null);
6666
6661
  }
6667
6662
 
6668
6663
  // src/cli/ui/bang.ts
@@ -6677,6 +6672,241 @@ function formatBangUserMessage(cmd, output) {
6677
6672
  ${output}`;
6678
6673
  }
6679
6674
 
6675
+ // src/cli/ui/copy-mode/CopyMode.tsx
6676
+ import { Box as Box27, Text as Text27, useStdout as useStdout9 } from "ink";
6677
+ import React31, { useMemo as useMemo6, useState as useState15 } from "react";
6678
+
6679
+ // src/frame/width.ts
6680
+ import stringWidthLib from "string-width";
6681
+ var segmenter = new Intl.Segmenter("en", { granularity: "grapheme" });
6682
+ function graphemes(s) {
6683
+ return Array.from(segmenter.segment(s), (seg) => seg.segment);
6684
+ }
6685
+ function graphemeWidth(g) {
6686
+ if (g.length === 0) return 0;
6687
+ const w = stringWidthLib(g);
6688
+ if (w <= 0) return 0;
6689
+ if (w >= 2) return 2;
6690
+ return 1;
6691
+ }
6692
+ function clipToCells(s, maxCells) {
6693
+ if (maxCells <= 0) return "";
6694
+ if (stringWidthLib(s) <= maxCells) return s;
6695
+ const cap = maxCells - 1;
6696
+ let out = "";
6697
+ let cells = 0;
6698
+ for (const g of graphemes(s)) {
6699
+ const w = graphemeWidth(g);
6700
+ if (cells + w > cap) break;
6701
+ out += g;
6702
+ cells += w;
6703
+ }
6704
+ return `${out}\u2026`;
6705
+ }
6706
+ function wrapToCells(s, maxCells) {
6707
+ if (maxCells <= 0) return [];
6708
+ if (s.length === 0) return [""];
6709
+ const out = [];
6710
+ let cur = "";
6711
+ let cells = 0;
6712
+ for (const g of graphemes(s)) {
6713
+ const w = graphemeWidth(g);
6714
+ if (cells + w > maxCells) {
6715
+ out.push(cur);
6716
+ cur = g;
6717
+ cells = w;
6718
+ } else {
6719
+ cur += g;
6720
+ cells += w;
6721
+ }
6722
+ }
6723
+ if (cur.length > 0 || out.length === 0) out.push(cur);
6724
+ return out;
6725
+ }
6726
+
6727
+ // src/cli/ui/clipboard.ts
6728
+ import { mkdtempSync, writeFileSync as writeFileSync4 } from "fs";
6729
+ import { tmpdir } from "os";
6730
+ import { join as join4 } from "path";
6731
+ var OSC_52_LIMIT = 75e3;
6732
+ function writeClipboard(text) {
6733
+ const dir = mkdtempSync(join4(tmpdir(), "reasonix-clip-"));
6734
+ const filePath = join4(dir, "clip.txt");
6735
+ let osc52 = false;
6736
+ if (text.length <= OSC_52_LIMIT) {
6737
+ const b64 = Buffer.from(text, "utf8").toString("base64");
6738
+ process.stdout.write(`\x1B]52;c;${b64}\x1B\\`);
6739
+ osc52 = true;
6740
+ }
6741
+ let writtenPath = null;
6742
+ try {
6743
+ writeFileSync4(filePath, text, "utf8");
6744
+ writtenPath = filePath;
6745
+ } catch {
6746
+ }
6747
+ return { osc52, filePath: writtenPath, size: text.length };
6748
+ }
6749
+
6750
+ // src/cli/ui/copy-mode/snapshot.ts
6751
+ function buildSnapshot(cards) {
6752
+ const out = [];
6753
+ for (const card of cards) {
6754
+ if (card.kind === "user") {
6755
+ pushCard(out, card.id, "user", t("copyMode.labelUser"), card.text);
6756
+ } else if (card.kind === "streaming") {
6757
+ pushCard(out, card.id, "assistant", t("copyMode.labelAssistant"), card.text);
6758
+ } else if (card.kind === "reasoning") {
6759
+ pushCard(out, card.id, "reasoning", t("copyMode.labelReasoning"), card.text);
6760
+ }
6761
+ }
6762
+ return out;
6763
+ }
6764
+ function pushCard(out, cardId, role, label, body) {
6765
+ if (out.length > 0) out.push({ cardId, kind: "blank", role, text: "" });
6766
+ out.push({ cardId, kind: "header", role, text: `\u2500\u2500\u2500 ${label} \u2500\u2500\u2500` });
6767
+ const lines = body.length === 0 ? [""] : body.split("\n");
6768
+ for (const line of lines) out.push({ cardId, kind: "text", role, text: line });
6769
+ }
6770
+ function yankRange(snapshot, fromIdx, toIdx) {
6771
+ const lo = Math.min(fromIdx, toIdx);
6772
+ const hi = Math.max(fromIdx, toIdx);
6773
+ const picks = [];
6774
+ for (let i = lo; i <= hi; i++) {
6775
+ const line = snapshot[i];
6776
+ if (!line) continue;
6777
+ if (line.kind === "header") continue;
6778
+ picks.push(line.text);
6779
+ }
6780
+ while (picks.length > 0 && picks[picks.length - 1] === "") picks.pop();
6781
+ while (picks.length > 0 && picks[0] === "") picks.shift();
6782
+ return picks.join("\n");
6783
+ }
6784
+ function isYankable(line) {
6785
+ return !!line && line.kind !== "header";
6786
+ }
6787
+
6788
+ // src/cli/ui/copy-mode/CopyMode.tsx
6789
+ var CHROME_ROWS = 3;
6790
+ function CopyMode({ cards, onClose }) {
6791
+ const snapshot = useMemo6(() => buildSnapshot(cards), [cards]);
6792
+ const { stdout } = useStdout9();
6793
+ const termRows = stdout?.rows ?? 30;
6794
+ const termCols = stdout?.columns ?? 80;
6795
+ const bodyRows = Math.max(4, termRows - CHROME_ROWS);
6796
+ const lastYankableIdx = findLastYankable(snapshot);
6797
+ const initialCursor = findFirstYankable(snapshot);
6798
+ const [cursor, setCursor] = useState15(initialCursor);
6799
+ const [anchor, setAnchor] = useState15(null);
6800
+ const [status2, setStatus] = useState15(null);
6801
+ const stepDown = (i) => stepBy(snapshot, i, 1);
6802
+ const stepUp = (i) => stepBy(snapshot, i, -1);
6803
+ useKeystroke((ev) => {
6804
+ if (ev.escape || ev.input === "q" && !ev.ctrl && !ev.meta) return onClose(null);
6805
+ if (ev.input === "j" || ev.downArrow) return setCursor(stepDown(cursor));
6806
+ if (ev.input === "k" || ev.upArrow) return setCursor(stepUp(cursor));
6807
+ if (ev.pageDown) return setCursor(scrollBy(snapshot, cursor, bodyRows));
6808
+ if (ev.pageUp) return setCursor(scrollBy(snapshot, cursor, -bodyRows));
6809
+ if (ev.input === "g") return setCursor(initialCursor);
6810
+ if (ev.input === "G") return setCursor(lastYankableIdx);
6811
+ if (ev.input === "v" || ev.input === "V") {
6812
+ setAnchor((a) => a === null ? cursor : null);
6813
+ return;
6814
+ }
6815
+ if (ev.input === "y" || ev.return) {
6816
+ const from = anchor ?? cursor;
6817
+ const to = cursor;
6818
+ const text = yankRange(snapshot, from, to).trim();
6819
+ if (text.length === 0) {
6820
+ setStatus(t("copyMode.statusEmpty"));
6821
+ return;
6822
+ }
6823
+ const w = writeClipboard(text);
6824
+ setStatus(t("copyMode.statusYanked", { size: text.length, osc52: w.osc52 ? "y" : "n" }));
6825
+ setTimeout(() => onClose(w), 600);
6826
+ }
6827
+ });
6828
+ const window = computeWindow(snapshot, cursor, bodyRows);
6829
+ const selRange = anchor === null ? null : [Math.min(anchor, cursor), Math.max(anchor, cursor)];
6830
+ const totalY = countYankable(snapshot);
6831
+ const cursorY = countYankableUntil(snapshot, cursor);
6832
+ return /* @__PURE__ */ React31.createElement(Box27, { flexDirection: "column" }, /* @__PURE__ */ React31.createElement(Box27, null, /* @__PURE__ */ React31.createElement(Text27, { color: TONE.brand, bold: true }, t("copyMode.title")), /* @__PURE__ */ React31.createElement(Text27, { color: FG.faint }, ` ${t("copyMode.help")}`)), /* @__PURE__ */ React31.createElement(Box27, { flexDirection: "column" }, snapshot.length === 0 ? /* @__PURE__ */ React31.createElement(Text27, { color: FG.faint }, t("copyMode.empty")) : window.lines.map((line, i) => {
6833
+ const idx = window.start + i;
6834
+ return /* @__PURE__ */ React31.createElement(
6835
+ CopyLine,
6836
+ {
6837
+ key: `${line.cardId}-${idx}`,
6838
+ line,
6839
+ cols: termCols,
6840
+ isCursor: idx === cursor,
6841
+ inSelection: selRange !== null && idx >= selRange[0] && idx <= selRange[1]
6842
+ }
6843
+ );
6844
+ })), /* @__PURE__ */ React31.createElement(Box27, null, /* @__PURE__ */ React31.createElement(Text27, { color: FG.meta }, t("copyMode.statusBar", {
6845
+ cur: cursorY > 0 ? cursorY : 1,
6846
+ total: Math.max(1, totalY),
6847
+ sel: anchor === null ? "\u2014" : String(rangeYankable(snapshot, anchor, cursor))
6848
+ })), status2 ? /* @__PURE__ */ React31.createElement(Text27, { color: TONE.ok }, ` ${status2}`) : null));
6849
+ }
6850
+ function CopyLine({
6851
+ line,
6852
+ cols,
6853
+ isCursor,
6854
+ inSelection
6855
+ }) {
6856
+ const marker = isCursor ? "\u25B8 " : " ";
6857
+ const room = Math.max(1, cols - 2);
6858
+ const display = line.kind === "blank" ? "" : clipToCells(line.text, room);
6859
+ if (line.kind === "header") {
6860
+ return /* @__PURE__ */ React31.createElement(Box27, null, /* @__PURE__ */ React31.createElement(Text27, { color: isCursor ? TONE.brand : FG.faint }, marker), /* @__PURE__ */ React31.createElement(Text27, { color: FG.meta }, display));
6861
+ }
6862
+ const color = isCursor ? TONE.brand : FG.body;
6863
+ return /* @__PURE__ */ React31.createElement(Box27, null, /* @__PURE__ */ React31.createElement(Text27, { color: isCursor ? TONE.brand : FG.faint }, marker), /* @__PURE__ */ React31.createElement(Text27, { color, inverse: inSelection }, display.length === 0 ? " " : display));
6864
+ }
6865
+ function findFirstYankable(snapshot) {
6866
+ for (let i = 0; i < snapshot.length; i++) if (isYankable(snapshot[i])) return i;
6867
+ return 0;
6868
+ }
6869
+ function findLastYankable(snapshot) {
6870
+ for (let i = snapshot.length - 1; i >= 0; i--) if (isYankable(snapshot[i])) return i;
6871
+ return Math.max(0, snapshot.length - 1);
6872
+ }
6873
+ function stepBy(snapshot, from, dir) {
6874
+ const last = snapshot.length - 1;
6875
+ let i = Math.max(0, Math.min(last, from + dir));
6876
+ while (i > 0 && i < last && snapshot[i]?.kind === "header") i += dir;
6877
+ if (i < 0) return 0;
6878
+ if (i > last) return last;
6879
+ return i;
6880
+ }
6881
+ function scrollBy(snapshot, from, delta) {
6882
+ const last = snapshot.length - 1;
6883
+ return Math.max(0, Math.min(last, from + delta));
6884
+ }
6885
+ function computeWindow(snapshot, cursor, rows) {
6886
+ if (snapshot.length <= rows) return { start: 0, lines: snapshot.slice() };
6887
+ const half = Math.floor(rows / 2);
6888
+ let start = Math.max(0, cursor - half);
6889
+ if (start + rows > snapshot.length) start = snapshot.length - rows;
6890
+ return { start, lines: snapshot.slice(start, start + rows) };
6891
+ }
6892
+ function countYankable(snapshot) {
6893
+ let n = 0;
6894
+ for (const line of snapshot) if (isYankable(line)) n++;
6895
+ return n;
6896
+ }
6897
+ function countYankableUntil(snapshot, idx) {
6898
+ let n = 0;
6899
+ for (let i = 0; i <= Math.min(idx, snapshot.length - 1); i++) if (isYankable(snapshot[i])) n++;
6900
+ return n;
6901
+ }
6902
+ function rangeYankable(snapshot, a, b) {
6903
+ const lo = Math.min(a, b);
6904
+ const hi = Math.max(a, b);
6905
+ let n = 0;
6906
+ for (let i = lo; i <= hi; i++) if (isYankable(snapshot[i])) n++;
6907
+ return n;
6908
+ }
6909
+
6680
6910
  // src/cli/ui/edit-history.ts
6681
6911
  function isEntryFullyUndone(e) {
6682
6912
  return e.snapshots.length > 0 && e.snapshots.every((s) => e.undoneFiles.has(s.path));
@@ -6787,7 +7017,7 @@ function loopEventToDashboard(ev, ctx) {
6787
7017
  // src/cli/ui/hash-memory.ts
6788
7018
  import { closeSync, fstatSync, mkdirSync as mkdirSync4, openSync, readSync, writeSync } from "fs";
6789
7019
  import { homedir as homedir3 } from "os";
6790
- import { dirname as dirname4, join as join4 } from "path";
7020
+ import { dirname as dirname4, join as join5 } from "path";
6791
7021
  var PROJECT_HEADER = `# Reasonix project memory
6792
7022
 
6793
7023
  Notes the user pinned via the \`#\` prompt prefix. The whole file is
@@ -6819,12 +7049,12 @@ function detectHashMemory(text) {
6819
7049
  return { kind: "memory", note: body };
6820
7050
  }
6821
7051
  function appendProjectMemory(rootDir, note) {
6822
- return appendBulletToFile(join4(rootDir, PROJECT_MEMORY_FILE), note, PROJECT_HEADER);
7052
+ return appendBulletToFile(join5(rootDir, PROJECT_MEMORY_FILE), note, PROJECT_HEADER);
6823
7053
  }
6824
7054
  var GLOBAL_MEMORY_DIR = ".reasonix";
6825
7055
  var GLOBAL_MEMORY_FILE = "REASONIX.md";
6826
7056
  function globalMemoryPath(homeDir = homedir3()) {
6827
- return join4(homeDir, GLOBAL_MEMORY_DIR, GLOBAL_MEMORY_FILE);
7057
+ return join5(homeDir, GLOBAL_MEMORY_DIR, GLOBAL_MEMORY_FILE);
6828
7058
  }
6829
7059
  function appendGlobalMemory(note, homeDir) {
6830
7060
  return appendBulletToFile(globalMemoryPath(homeDir), note, GLOBAL_HEADER);
@@ -7027,7 +7257,7 @@ function handleToolEvent(ev, ctx) {
7027
7257
  }
7028
7258
 
7029
7259
  // src/cli/ui/state/provider.tsx
7030
- import React31 from "react";
7260
+ import React32 from "react";
7031
7261
 
7032
7262
  // src/cli/ui/state/reducer.ts
7033
7263
  function reduce(state, event) {
@@ -7391,26 +7621,26 @@ function createStore(session, initialCards) {
7391
7621
  }
7392
7622
 
7393
7623
  // src/cli/ui/state/provider.tsx
7394
- var StoreCtx = React31.createContext(null);
7624
+ var StoreCtx = React32.createContext(null);
7395
7625
  function AgentStoreProvider({
7396
7626
  session,
7397
7627
  initialCards,
7398
7628
  children
7399
7629
  }) {
7400
- const initialCardsRef = React31.useRef(initialCards);
7401
- const store = React31.useMemo(() => createStore(session, initialCardsRef.current), [session]);
7402
- return /* @__PURE__ */ React31.createElement(StoreCtx.Provider, { value: store }, children);
7630
+ const initialCardsRef = React32.useRef(initialCards);
7631
+ const store = React32.useMemo(() => createStore(session, initialCardsRef.current), [session]);
7632
+ return /* @__PURE__ */ React32.createElement(StoreCtx.Provider, { value: store }, children);
7403
7633
  }
7404
7634
  function useAgentStore() {
7405
- const store = React31.useContext(StoreCtx);
7635
+ const store = React32.useContext(StoreCtx);
7406
7636
  if (!store) throw new Error("useAgentStore must be used inside AgentStoreProvider");
7407
7637
  return store;
7408
7638
  }
7409
7639
  function useAgentState(selector) {
7410
7640
  const store = useAgentStore();
7411
- const subscribe = React31.useCallback((cb) => store.subscribe(cb), [store]);
7412
- const getSnapshot = React31.useCallback(() => selector(store.getState()), [store, selector]);
7413
- return React31.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
7641
+ const subscribe = React32.useCallback((cb) => store.subscribe(cb), [store]);
7642
+ const getSnapshot = React32.useCallback(() => selector(store.getState()), [store, selector]);
7643
+ return React32.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
7414
7644
  }
7415
7645
  function useDispatch() {
7416
7646
  return useAgentStore().dispatch;
@@ -7428,14 +7658,14 @@ function useActivityLabel() {
7428
7658
  }
7429
7659
 
7430
7660
  // src/cli/ui/hooks/useAgentSession.ts
7431
- import { useMemo as useMemo6 } from "react";
7661
+ import { useMemo as useMemo7 } from "react";
7432
7662
  function useAgentSession({
7433
7663
  sessionId,
7434
7664
  model: model2,
7435
7665
  workspace,
7436
7666
  branch
7437
7667
  }) {
7438
- return useMemo6(
7668
+ return useMemo7(
7439
7669
  () => ({
7440
7670
  id: sessionId ?? "default",
7441
7671
  branch: branch ?? "main",
@@ -7502,24 +7732,24 @@ import {
7502
7732
  useCallback as useCallback3,
7503
7733
  useEffect as useEffect5,
7504
7734
  useRef as useRef2,
7505
- useState as useState15
7735
+ useState as useState16
7506
7736
  } from "react";
7507
7737
  var FLASH_MS = 1200;
7508
7738
  function useEditGate(codeMode) {
7509
7739
  const pendingEdits = useRef2([]);
7510
- const [pendingCount, setPendingCount] = useState15(0);
7511
- const [pendingTick, setPendingTick] = useState15(0);
7740
+ const [pendingCount, setPendingCount] = useState16(0);
7741
+ const [pendingTick, setPendingTick] = useState16(0);
7512
7742
  const syncPendingCount = useCallback3(() => {
7513
7743
  setPendingCount(pendingEdits.current.length);
7514
7744
  setPendingTick((t2) => t2 + 1);
7515
7745
  }, []);
7516
- const [editMode, setEditMode] = useState15(() => codeMode ? loadEditMode() : "review");
7746
+ const [editMode, setEditMode] = useState16(() => codeMode ? loadEditMode() : "review");
7517
7747
  const editModeRef = useRef2(editMode);
7518
7748
  useEffect5(() => {
7519
7749
  editModeRef.current = editMode;
7520
7750
  if (codeMode) saveEditMode(editMode);
7521
7751
  }, [editMode, codeMode]);
7522
- const [modeFlash, setModeFlash] = useState15(false);
7752
+ const [modeFlash, setModeFlash] = useState16(false);
7523
7753
  const flashTimerRef = useRef2(null);
7524
7754
  const prevEditModeRef = useRef2(editMode);
7525
7755
  useEffect5(() => {
@@ -7545,9 +7775,9 @@ function useEditGate(codeMode) {
7545
7775
  }
7546
7776
 
7547
7777
  // src/cli/ui/hooks/useHookList.ts
7548
- import { useCallback as useCallback4, useState as useState16 } from "react";
7778
+ import { useCallback as useCallback4, useState as useState17 } from "react";
7549
7779
  function useHookList(initialProjectRoot) {
7550
- const [hookList, setHookList] = useState16(
7780
+ const [hookList, setHookList] = useState17(
7551
7781
  () => loadHooks({ projectRoot: initialProjectRoot })
7552
7782
  );
7553
7783
  const reloadHooks = useCallback4((projectRoot) => {
@@ -7587,18 +7817,18 @@ function useInputRecall(setInput) {
7587
7817
  }
7588
7818
 
7589
7819
  // src/cli/ui/hooks/useLanguageReload.ts
7590
- import { useEffect as useEffect6, useState as useState17 } from "react";
7820
+ import { useEffect as useEffect6, useState as useState18 } from "react";
7591
7821
  function useLanguageReload() {
7592
- const [version, setVersion] = useState17(0);
7822
+ const [version, setVersion] = useState18(0);
7593
7823
  useEffect6(() => onLanguageChange(() => setVersion((v) => v + 1)), []);
7594
7824
  return version;
7595
7825
  }
7596
7826
 
7597
7827
  // src/cli/ui/hooks/useLoopMode.ts
7598
- import { useCallback as useCallback6, useEffect as useEffect7, useRef as useRef4, useState as useState18 } from "react";
7828
+ import { useCallback as useCallback6, useEffect as useEffect7, useRef as useRef4, useState as useState19 } from "react";
7599
7829
  function useLoopMode(opts) {
7600
7830
  const { log, busyRef, handleSubmitRef } = opts;
7601
- const [activeLoop, setActiveLoop] = useState18(null);
7831
+ const [activeLoop, setActiveLoop] = useState19(null);
7602
7832
  const activeLoopRef = useRef4(null);
7603
7833
  const loopTimerRef = useRef4(null);
7604
7834
  const loopFiringRef = useRef4(false);
@@ -7682,13 +7912,13 @@ function useLoopMode(opts) {
7682
7912
  }
7683
7913
 
7684
7914
  // src/cli/ui/hooks/usePresetMode.ts
7685
- import { useState as useState19 } from "react";
7915
+ import { useState as useState20 } from "react";
7686
7916
  function usePresetMode(model2) {
7687
- const [preset2, setPreset] = useState19(
7917
+ const [preset2, setPreset] = useState20(
7688
7918
  () => model2 === "deepseek-v4-pro" ? "pro" : "auto"
7689
7919
  );
7690
- const [proArmed, setProArmed] = useState19(false);
7691
- const [turnOnPro, setTurnOnPro] = useState19(false);
7920
+ const [proArmed, setProArmed] = useState20(false);
7921
+ const [turnOnPro, setTurnOnPro] = useState20(false);
7692
7922
  return { preset: preset2, setPreset, proArmed, setProArmed, turnOnPro, setTurnOnPro };
7693
7923
  }
7694
7924
 
@@ -7709,7 +7939,7 @@ function useQuit(transcriptRef) {
7709
7939
  }
7710
7940
 
7711
7941
  // src/cli/ui/hooks/useScrollback.ts
7712
- import { useMemo as useMemo7 } from "react";
7942
+ import { useMemo as useMemo8 } from "react";
7713
7943
  var seq = 0;
7714
7944
  function nextId2(prefix) {
7715
7945
  seq += 1;
@@ -7722,7 +7952,7 @@ function formatTok(n) {
7722
7952
  }
7723
7953
  function useScrollback() {
7724
7954
  const dispatch = useDispatch();
7725
- return useMemo7(
7955
+ return useMemo8(
7726
7956
  () => ({
7727
7957
  pushUser(text) {
7728
7958
  const id = nextId2("u");
@@ -7935,10 +8165,10 @@ ${stack}` : message
7935
8165
  }
7936
8166
 
7937
8167
  // src/cli/ui/hooks/useTerminalSetup.ts
7938
- import { useStdout as useStdout9 } from "ink";
8168
+ import { useStdout as useStdout10 } from "ink";
7939
8169
  import { useEffect as useEffect9 } from "react";
7940
8170
  function useTerminalSetup(mouse) {
7941
- const { stdout } = useStdout9();
8171
+ const { stdout } = useStdout10();
7942
8172
  useEffect9(() => {
7943
8173
  if (!stdout || !stdout.isTTY) return;
7944
8174
  stdout.write("\x1B[?2004h");
@@ -7953,11 +8183,11 @@ function useTerminalSetup(mouse) {
7953
8183
  }
7954
8184
 
7955
8185
  // src/cli/ui/hooks/useToolProgressDisplay.ts
7956
- import { useCallback as useCallback8, useEffect as useEffect10, useState as useState20 } from "react";
8186
+ import { useCallback as useCallback8, useEffect as useEffect10, useState as useState21 } from "react";
7957
8187
  function useToolProgressDisplay(progressSink) {
7958
- const [ongoingTool, setOngoingTool] = useState20(null);
7959
- const [toolProgress, setToolProgress] = useState20(null);
7960
- const [statusLine, setStatusLine] = useState20(null);
8188
+ const [ongoingTool, setOngoingTool] = useState21(null);
8189
+ const [toolProgress, setToolProgress] = useState21(null);
8190
+ const [statusLine, setStatusLine] = useState21(null);
7961
8191
  useEffect10(() => {
7962
8192
  if (!progressSink) return;
7963
8193
  progressSink.current = (info) => {
@@ -8004,10 +8234,10 @@ function useTranscriptWriter(transcriptRef, model2, prefixHash) {
8004
8234
  import {
8005
8235
  useEffect as useEffect11,
8006
8236
  useRef as useRef5,
8007
- useState as useState21
8237
+ useState as useState22
8008
8238
  } from "react";
8009
8239
  function useWorkspaceRoot(launchRoot) {
8010
- const [currentRootDir, setCurrentRootDir] = useState21(() => launchRoot ?? process.cwd());
8240
+ const [currentRootDir, setCurrentRootDir] = useState22(() => launchRoot ?? process.cwd());
8011
8241
  const currentRootDirRef = useRef5(currentRootDir);
8012
8242
  useEffect11(() => {
8013
8243
  currentRootDirRef.current = currentRootDir;
@@ -8016,21 +8246,21 @@ function useWorkspaceRoot(launchRoot) {
8016
8246
  }
8017
8247
 
8018
8248
  // src/cli/ui/layout/CardStream.tsx
8019
- import { Box as Box46, Text as Text48, useBoxMetrics } from "ink";
8020
- import React57, { useEffect as useEffect12, useMemo as useMemo8, useRef as useRef6 } from "react";
8249
+ import { Box as Box47, Text as Text49, useBoxMetrics } from "ink";
8250
+ import React58, { useEffect as useEffect12, useMemo as useMemo9, useRef as useRef6 } from "react";
8021
8251
 
8022
8252
  // src/cli/ui/cards/CardRenderer.tsx
8023
- import { Box as Box45, Text as Text47 } from "ink";
8024
- import React55 from "react";
8253
+ import { Box as Box46, Text as Text48 } from "ink";
8254
+ import React56 from "react";
8025
8255
 
8026
8256
  // src/cli/ui/cards/CtxCard.tsx
8027
- import { Box as Box29, Text as Text28 } from "ink";
8028
- import React34 from "react";
8257
+ import { Box as Box30, Text as Text29 } from "ink";
8258
+ import React35 from "react";
8029
8259
 
8030
8260
  // src/cli/ui/primitives/Card.tsx
8031
- import { Box as Box27 } from "ink";
8032
- import React32, { useContext as useContext3 } from "react";
8033
- var ActiveCardContext = React32.createContext(true);
8261
+ import { Box as Box28 } from "ink";
8262
+ import React33, { useContext as useContext3 } from "react";
8263
+ var ActiveCardContext = React33.createContext(true);
8034
8264
  var STRIPE_BORDER = {
8035
8265
  topLeft: " ",
8036
8266
  top: " ",
@@ -8044,10 +8274,10 @@ var STRIPE_BORDER = {
8044
8274
  function Card({ tone, children }) {
8045
8275
  const active = useContext3(ActiveCardContext);
8046
8276
  if (!active) {
8047
- return /* @__PURE__ */ React32.createElement(Box27, { flexDirection: "column" }, children);
8277
+ return /* @__PURE__ */ React33.createElement(Box28, { flexDirection: "column" }, children);
8048
8278
  }
8049
- return /* @__PURE__ */ React32.createElement(
8050
- Box27,
8279
+ return /* @__PURE__ */ React33.createElement(
8280
+ Box28,
8051
8281
  {
8052
8282
  flexDirection: "column",
8053
8283
  borderStyle: STRIPE_BORDER,
@@ -8064,8 +8294,8 @@ function Card({ tone, children }) {
8064
8294
  }
8065
8295
 
8066
8296
  // src/cli/ui/primitives/CardHeader.tsx
8067
- import { Box as Box28, Text as Text27 } from "ink";
8068
- import React33, { useContext as useContext4 } from "react";
8297
+ import { Box as Box29, Text as Text28 } from "ink";
8298
+ import React34, { useContext as useContext4 } from "react";
8069
8299
  function CardHeader({
8070
8300
  glyph,
8071
8301
  tone,
@@ -8078,13 +8308,13 @@ function CardHeader({
8078
8308
  }) {
8079
8309
  const active = useContext4(ActiveCardContext);
8080
8310
  const visibleMeta = active ? meta : meta?.filter((item) => typeof item !== "string");
8081
- return /* @__PURE__ */ React33.createElement(Box28, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React33.createElement(Text27, { color: tone }, glyph), titleBg ? /* @__PURE__ */ React33.createElement(Text27, { backgroundColor: titleBg, color: titleColor ?? tone, bold: true }, ` ${title} `) : /* @__PURE__ */ React33.createElement(Text27, { bold: true, color: titleColor ?? tone }, title), subtitle ? /* @__PURE__ */ React33.createElement(Text27, { color: FG.body }, subtitle) : null, visibleMeta?.map((item, i) => {
8311
+ return /* @__PURE__ */ React34.createElement(Box29, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React34.createElement(Text28, { color: tone }, glyph), titleBg ? /* @__PURE__ */ React34.createElement(Text28, { backgroundColor: titleBg, color: titleColor ?? tone, bold: true }, ` ${title} `) : /* @__PURE__ */ React34.createElement(Text28, { bold: true, color: titleColor ?? tone }, title), subtitle ? /* @__PURE__ */ React34.createElement(Text28, { color: FG.body }, subtitle) : null, visibleMeta?.map((item, i) => {
8082
8312
  const isStr = typeof item === "string";
8083
8313
  const text = isStr ? item : item.text;
8084
8314
  const color = isStr ? FG.faint : item.color;
8085
8315
  return (
8086
8316
  // biome-ignore lint/suspicious/noArrayIndexKey: meta items are positional
8087
- /* @__PURE__ */ React33.createElement(React33.Fragment, { key: `m-${i}` }, /* @__PURE__ */ React33.createElement(Text27, { color: FG.faint }, "\xB7"), /* @__PURE__ */ React33.createElement(Text27, { color }, text))
8317
+ /* @__PURE__ */ React34.createElement(React34.Fragment, { key: `m-${i}` }, /* @__PURE__ */ React34.createElement(Text28, { color: FG.faint }, "\xB7"), /* @__PURE__ */ React34.createElement(Text28, { color }, text))
8088
8318
  );
8089
8319
  }), active ? right : null);
8090
8320
  }
@@ -8093,13 +8323,13 @@ function CardHeader({
8093
8323
  var BAR_CELLS = 32;
8094
8324
  function row(label, tokens, ratio, color) {
8095
8325
  const filled = Math.max(0, Math.min(BAR_CELLS, Math.round(ratio * BAR_CELLS)));
8096
- return /* @__PURE__ */ React34.createElement(Box29, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React34.createElement(Text28, { color: FG.sub }, label.padEnd(7)), /* @__PURE__ */ React34.createElement(Text28, { color }, "\u2588".repeat(filled)), /* @__PURE__ */ React34.createElement(Text28, { color: FG.faint }, "\u2591".repeat(BAR_CELLS - filled)), /* @__PURE__ */ React34.createElement(Text28, { bold: true, color: FG.body }, tokens.toLocaleString()), /* @__PURE__ */ React34.createElement(Text28, { color: FG.faint }, `\xB7 ${(ratio * 100).toFixed(1)}%`));
8326
+ return /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React35.createElement(Text29, { color: FG.sub }, label.padEnd(7)), /* @__PURE__ */ React35.createElement(Text29, { color }, "\u2588".repeat(filled)), /* @__PURE__ */ React35.createElement(Text29, { color: FG.faint }, "\u2591".repeat(BAR_CELLS - filled)), /* @__PURE__ */ React35.createElement(Text29, { bold: true, color: FG.body }, tokens.toLocaleString()), /* @__PURE__ */ React35.createElement(Text29, { color: FG.faint }, `\xB7 ${(ratio * 100).toFixed(1)}%`));
8097
8327
  }
8098
8328
  function CtxCard({ card }) {
8099
8329
  const cap = Math.max(1, card.ctxMax);
8100
8330
  const used = card.systemTokens + card.toolsTokens + card.logTokens + card.inputTokens;
8101
8331
  const usedPct = used / cap * 100;
8102
- return /* @__PURE__ */ React34.createElement(Card, { tone: TONE.brand }, /* @__PURE__ */ React34.createElement(
8332
+ return /* @__PURE__ */ React35.createElement(Card, { tone: TONE.brand }, /* @__PURE__ */ React35.createElement(
8103
8333
  CardHeader,
8104
8334
  {
8105
8335
  glyph: "\u2318",
@@ -8107,8 +8337,8 @@ function CtxCard({ card }) {
8107
8337
  title: t("cardTitles.context"),
8108
8338
  meta: [`${used.toLocaleString()} / ${cap.toLocaleString()} (${usedPct.toFixed(1)}%)`]
8109
8339
  }
8110
- ), 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__ */ React34.createElement(React34.Fragment, null, /* @__PURE__ */ React34.createElement(Text28, { 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__ */ React34.createElement(Box29, { key: `${tool.turn}-${tool.name}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React34.createElement(Text28, { color: FG.sub }, tool.name), /* @__PURE__ */ React34.createElement(
8111
- Text28,
8340
+ ), 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__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement(Text29, { 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__ */ React35.createElement(Box30, { key: `${tool.turn}-${tool.name}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React35.createElement(Text29, { color: FG.sub }, tool.name), /* @__PURE__ */ React35.createElement(
8341
+ Text29,
8112
8342
  {
8113
8343
  color: FG.faint
8114
8344
  },
@@ -8117,8 +8347,8 @@ function CtxCard({ card }) {
8117
8347
  }
8118
8348
 
8119
8349
  // src/cli/ui/cards/DiffCard.tsx
8120
- import { Box as Box30, Text as Text29 } from "ink";
8121
- import React35 from "react";
8350
+ import { Box as Box31, Text as Text30 } from "ink";
8351
+ import React36 from "react";
8122
8352
  var LINE_COLOR = {
8123
8353
  ctx: FG.sub,
8124
8354
  add: TONE.ok,
@@ -8133,7 +8363,7 @@ var LINE_GLYPH = {
8133
8363
  };
8134
8364
  function DiffCard({ card }) {
8135
8365
  const showFooter = card.hunks.length > 0;
8136
- return /* @__PURE__ */ React35.createElement(Card, { tone: TONE.ok }, /* @__PURE__ */ React35.createElement(
8366
+ return /* @__PURE__ */ React36.createElement(Card, { tone: TONE.ok }, /* @__PURE__ */ React36.createElement(
8137
8367
  CardHeader,
8138
8368
  {
8139
8369
  glyph: "\xB1",
@@ -8145,22 +8375,27 @@ function DiffCard({ card }) {
8145
8375
  { text: `-${card.stats.del}`, color: TONE.err }
8146
8376
  ]
8147
8377
  }
8148
- ), card.hunks.map((hunk) => /* @__PURE__ */ React35.createElement(Box30, { key: `${card.id}:${hunk.header}`, flexDirection: "column" }, /* @__PURE__ */ React35.createElement(Text29, { italic: true, color: FG.faint }, hunk.header), hunk.lines.map((line, li) => /* @__PURE__ */ React35.createElement(Box30, { key: `${card.id}:${hunk.header}:${li}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React35.createElement(Text29, { color: LINE_COLOR[line.kind] }, LINE_GLYPH[line.kind]), /* @__PURE__ */ React35.createElement(Text29, { color: LINE_COLOR[line.kind], dimColor: line.kind === "ctx" }, line.text))))), showFooter && /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "row", gap: 2 }, /* @__PURE__ */ React35.createElement(Text29, { bold: true, color: TONE.ok }, "[a] apply"), /* @__PURE__ */ React35.createElement(Text29, { color: FG.sub }, "[s] skip"), /* @__PURE__ */ React35.createElement(Text29, { bold: true, color: TONE.err }, "[r] reject")));
8378
+ ), card.hunks.map((hunk) => /* @__PURE__ */ React36.createElement(Box31, { key: `${card.id}:${hunk.header}`, flexDirection: "column" }, /* @__PURE__ */ React36.createElement(Text30, { italic: true, color: FG.faint }, hunk.header), hunk.lines.map((line, li) => /* @__PURE__ */ React36.createElement(Box31, { key: `${card.id}:${hunk.header}:${li}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React36.createElement(Text30, { color: LINE_COLOR[line.kind] }, LINE_GLYPH[line.kind]), /* @__PURE__ */ React36.createElement(Text30, { color: LINE_COLOR[line.kind], dimColor: line.kind === "ctx" }, line.text))))), showFooter && /* @__PURE__ */ React36.createElement(Box31, { flexDirection: "row", gap: 2 }, /* @__PURE__ */ React36.createElement(Text30, { bold: true, color: TONE.ok }, t("cardLabels.applyAction")), /* @__PURE__ */ React36.createElement(Text30, { color: FG.sub }, t("cardLabels.skipAction")), /* @__PURE__ */ React36.createElement(Text30, { bold: true, color: TONE.err }, t("cardLabels.rejectAction"))));
8149
8379
  }
8150
8380
 
8151
8381
  // src/cli/ui/cards/DoctorCard.tsx
8152
- import { Box as Box31, Text as Text30 } from "ink";
8153
- import React36 from "react";
8382
+ import { Box as Box32, Text as Text31 } from "ink";
8383
+ import React37 from "react";
8154
8384
  var LEVEL_GLYPH = {
8155
8385
  ok: "\u2713",
8156
8386
  warn: "\u26A0",
8157
8387
  fail: "\u2716"
8158
8388
  };
8159
- var LEVEL_TAG = {
8160
- ok: "OK",
8161
- warn: "warn",
8162
- fail: "FAIL"
8163
- };
8389
+ function levelTag(level) {
8390
+ switch (level) {
8391
+ case "ok":
8392
+ return t("cardLabels.levelOk");
8393
+ case "warn":
8394
+ return t("cardLabels.levelWarn");
8395
+ case "fail":
8396
+ return t("cardLabels.levelFail");
8397
+ }
8398
+ }
8164
8399
  function DoctorCard({ card }) {
8165
8400
  const { fg, tone } = useThemeTokens();
8166
8401
  const levelColor = {
@@ -8172,13 +8407,21 @@ function DoctorCard({ card }) {
8172
8407
  const warn = card.checks.filter((c) => c.level === "warn").length;
8173
8408
  const fail = card.checks.filter((c) => c.level === "fail").length;
8174
8409
  const labelWidth = card.checks.reduce((m, c) => Math.max(m, c.label.length), 0);
8175
- const summary = `${card.checks.length} checks \xB7 ${ok} passed${warn > 0 ? ` \xB7 ${warn} warn` : ""}${fail > 0 ? ` \xB7 ${fail} fail` : ""}`;
8176
- return /* @__PURE__ */ React36.createElement(Card, { tone: CARD.tool.color }, /* @__PURE__ */ React36.createElement(CardHeader, { glyph: "\u2695", tone: CARD.tool.color, title: "doctor", meta: [summary] }), card.checks.map((c) => /* @__PURE__ */ React36.createElement(Box31, { key: c.label, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React36.createElement(Text30, { color: levelColor[c.level] }, LEVEL_GLYPH[c.level]), /* @__PURE__ */ React36.createElement(Text30, { bold: true, color: fg.body }, c.label.padEnd(labelWidth + 1)), /* @__PURE__ */ React36.createElement(Text30, { color: fg.sub }, c.detail), /* @__PURE__ */ React36.createElement(Text30, { color: levelColor[c.level] }, LEVEL_TAG[c.level]))));
8410
+ const summary = `${card.checks.length} ${t("cardLabels.checksLabel")} \xB7 ${ok} ${t("cardLabels.passed")}${warn > 0 ? ` \xB7 ${warn} ${t("cardLabels.warnTag")}` : ""}${fail > 0 ? ` \xB7 ${fail} ${t("cardLabels.failTag")}` : ""}`;
8411
+ return /* @__PURE__ */ React37.createElement(Card, { tone: CARD.tool.color }, /* @__PURE__ */ React37.createElement(
8412
+ CardHeader,
8413
+ {
8414
+ glyph: "\u2695",
8415
+ tone: CARD.tool.color,
8416
+ title: t("cardTitles.doctor"),
8417
+ meta: [summary]
8418
+ }
8419
+ ), card.checks.map((c) => /* @__PURE__ */ React37.createElement(Box32, { key: c.label, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React37.createElement(Text31, { color: levelColor[c.level] }, LEVEL_GLYPH[c.level]), /* @__PURE__ */ React37.createElement(Text31, { bold: true, color: fg.body }, c.label.padEnd(labelWidth + 1)), /* @__PURE__ */ React37.createElement(Text31, { color: fg.sub }, c.detail), /* @__PURE__ */ React37.createElement(Text31, { color: levelColor[c.level] }, levelTag(c.level)))));
8177
8420
  }
8178
8421
 
8179
8422
  // src/cli/ui/cards/ErrorCard.tsx
8180
- import { Box as Box32, Text as Text31 } from "ink";
8181
- import React37 from "react";
8423
+ import { Box as Box33, Text as Text32 } from "ink";
8424
+ import React38 from "react";
8182
8425
  var STACK_TAIL = 5;
8183
8426
  function ErrorCard({ card }) {
8184
8427
  const retryNote = card.retries !== void 0 && card.retries > 0 ? `${card.retries} ${t("cardLabels.retries")}` : null;
@@ -8188,7 +8431,7 @@ function ErrorCard({ card }) {
8188
8431
  const stackHidden = stackTrunc ? stackLines.length - stackVisible.length : 0;
8189
8432
  const hasStack = stackVisible.length > 0;
8190
8433
  const messageLines = card.message.split("\n");
8191
- return /* @__PURE__ */ React37.createElement(Card, { tone: TONE.err }, /* @__PURE__ */ React37.createElement(
8434
+ return /* @__PURE__ */ React38.createElement(Card, { tone: TONE.err }, /* @__PURE__ */ React38.createElement(
8192
8435
  CardHeader,
8193
8436
  {
8194
8437
  glyph: "\u2716",
@@ -8196,19 +8439,19 @@ function ErrorCard({ card }) {
8196
8439
  title: card.title || t("cardTitles.error"),
8197
8440
  meta: retryNote ? [retryNote] : void 0
8198
8441
  }
8199
- ), messageLines.map((line, i) => /* @__PURE__ */ React37.createElement(Text31, { key: `${card.id}:msg:${i}`, color: TONE.err }, line || " ")), hasStack ? /* @__PURE__ */ React37.createElement(Box32, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React37.createElement(Text31, { color: FG.meta }, t("cardLabels.stackTrace")), stackHidden > 0 ? /* @__PURE__ */ React37.createElement(Text31, { color: FG.faint }, t(
8442
+ ), messageLines.map((line, i) => /* @__PURE__ */ React38.createElement(Text32, { key: `${card.id}:msg:${i}`, color: TONE.err }, line || " ")), hasStack ? /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text32, { color: FG.meta }, t("cardLabels.stackTrace")), stackHidden > 0 ? /* @__PURE__ */ React38.createElement(Text32, { color: FG.faint }, t(
8200
8443
  stackHidden === 1 ? "cardLabels.earlierStackLine" : "cardLabels.earlierStackLines",
8201
8444
  { count: stackHidden }
8202
- )) : null, stackVisible.map((line, i) => /* @__PURE__ */ React37.createElement(Text31, { key: `${card.id}:stk:${stackHidden + i}`, color: FG.meta }, line || " "))) : null);
8445
+ )) : null, stackVisible.map((line, i) => /* @__PURE__ */ React38.createElement(Text32, { key: `${card.id}:stk:${stackHidden + i}`, color: FG.meta }, line || " "))) : null);
8203
8446
  }
8204
8447
 
8205
8448
  // src/cli/ui/cards/LiveCard.tsx
8206
- import { Box as Box33, Text as Text33 } from "ink";
8207
- import React39 from "react";
8449
+ import { Box as Box34, Text as Text34 } from "ink";
8450
+ import React40 from "react";
8208
8451
 
8209
8452
  // src/cli/ui/primitives/Spinner.tsx
8210
- import { Text as Text32 } from "ink";
8211
- import React38 from "react";
8453
+ import { Text as Text33 } from "ink";
8454
+ import React39 from "react";
8212
8455
  var FRAMES = {
8213
8456
  circle: ["\u25D0", "\u25D3", "\u25D1", "\u25D2"],
8214
8457
  braille: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827"]
@@ -8217,7 +8460,7 @@ function Spinner({ kind = "circle", color, bold }) {
8217
8460
  const frames = FRAMES[kind];
8218
8461
  const tick = useTick();
8219
8462
  const frame = tick % frames.length;
8220
- return /* @__PURE__ */ React38.createElement(Text32, { bold, color }, frames[frame]);
8463
+ return /* @__PURE__ */ React39.createElement(Text33, { bold, color }, frames[frame]);
8221
8464
  }
8222
8465
 
8223
8466
  // src/cli/ui/cards/LiveCard.tsx
@@ -8244,24 +8487,30 @@ var VARIANT_GLYPH = {
8244
8487
  function LiveCard({ card }) {
8245
8488
  const color = TONE_TO_COLOR[card.tone];
8246
8489
  const glyph = VARIANT_GLYPH[card.variant];
8247
- return /* @__PURE__ */ React39.createElement(Box33, { paddingLeft: 2, flexDirection: "row", gap: 1 }, card.variant === "thinking" ? /* @__PURE__ */ React39.createElement(Spinner, { kind: "circle", color, bold: true }) : /* @__PURE__ */ React39.createElement(Text33, { bold: true, color }, glyph), /* @__PURE__ */ React39.createElement(Text33, { color: FG.body }, card.text), card.meta !== void 0 ? /* @__PURE__ */ React39.createElement(Text33, { color: FG.faint }, `\xB7 ${card.meta}`) : null);
8490
+ return /* @__PURE__ */ React40.createElement(Box34, { paddingLeft: 2, flexDirection: "row", gap: 1 }, card.variant === "thinking" ? /* @__PURE__ */ React40.createElement(Spinner, { kind: "circle", color, bold: true }) : /* @__PURE__ */ React40.createElement(Text34, { bold: true, color }, glyph), /* @__PURE__ */ React40.createElement(Text34, { color: FG.body }, card.text), card.meta !== void 0 ? /* @__PURE__ */ React40.createElement(Text34, { color: FG.faint }, `\xB7 ${card.meta}`) : null);
8248
8491
  }
8249
8492
 
8250
8493
  // src/cli/ui/cards/MemoryCard.tsx
8251
- import { Box as Box34, Text as Text34 } from "ink";
8252
- import React40 from "react";
8494
+ import { Box as Box35, Text as Text35 } from "ink";
8495
+ import React41 from "react";
8253
8496
  var CATEGORY_ORDER = [
8254
8497
  "user",
8255
8498
  "feedback",
8256
8499
  "project",
8257
8500
  "reference"
8258
8501
  ];
8259
- var CATEGORY_LABEL = {
8260
- user: "user",
8261
- feedback: "feedback",
8262
- project: "project",
8263
- reference: "reference"
8264
- };
8502
+ function categoryLabel(c) {
8503
+ switch (c) {
8504
+ case "user":
8505
+ return t("cardLabels.categoryUser");
8506
+ case "feedback":
8507
+ return t("cardLabels.categoryFeedback");
8508
+ case "project":
8509
+ return t("cardLabels.categoryProject");
8510
+ case "reference":
8511
+ return t("cardLabels.categoryReference");
8512
+ }
8513
+ }
8265
8514
  var CATEGORY_GLYPH = {
8266
8515
  user: "\u25C7",
8267
8516
  feedback: "\u2726",
@@ -8276,14 +8525,14 @@ var CATEGORY_GLYPH_COLOR = {
8276
8525
  };
8277
8526
  function MemoryCard({ card }) {
8278
8527
  const counts = countByCategory(card.entries);
8279
- const summary = CATEGORY_ORDER.filter((c) => counts[c] > 0).map((c) => `${counts[c]} ${c}`).join(" \xB7 ");
8280
- const tokens = card.tokens > 1024 ? `~${(card.tokens / 1024).toFixed(1)}K tok` : `~${card.tokens} tok`;
8281
- return /* @__PURE__ */ React40.createElement(Card, { tone: FG.meta }, /* @__PURE__ */ React40.createElement(
8528
+ const summary = CATEGORY_ORDER.filter((c) => counts[c] > 0).map((c) => `${counts[c]} ${categoryLabel(c)}`).join(" \xB7 ");
8529
+ const tokens = card.tokens > 1024 ? `~${(card.tokens / 1024).toFixed(1)}K ${t("cardLabels.tok")}` : `~${card.tokens} ${t("cardLabels.tok")}`;
8530
+ return /* @__PURE__ */ React41.createElement(Card, { tone: FG.meta }, /* @__PURE__ */ React41.createElement(
8282
8531
  CardHeader,
8283
8532
  {
8284
8533
  glyph: "\u2311",
8285
8534
  tone: FG.meta,
8286
- title: "context",
8535
+ title: t("cardTitles.context"),
8287
8536
  titleColor: FG.sub,
8288
8537
  meta: summary ? [summary, tokens] : [tokens]
8289
8538
  }
@@ -8291,7 +8540,7 @@ function MemoryCard({ card }) {
8291
8540
  const all = card.entries.filter((e) => e.category === category);
8292
8541
  const shown = all.slice(0, 5);
8293
8542
  const remaining = all.length - shown.length;
8294
- return /* @__PURE__ */ React40.createElement(Box34, { key: category, flexDirection: "column" }, /* @__PURE__ */ React40.createElement(Text34, { color: FG.faint }, `${CATEGORY_LABEL[category]} (${counts[category]})`), shown.map((entry) => /* @__PURE__ */ React40.createElement(Box34, { key: `${category}:${entry.summary}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React40.createElement(Text34, { color: CATEGORY_GLYPH_COLOR[category] }, CATEGORY_GLYPH[category]), /* @__PURE__ */ React40.createElement(Text34, { color: FG.sub }, entry.summary))), remaining > 0 ? /* @__PURE__ */ React40.createElement(Text34, { color: FG.faint }, `\u22EE +${remaining} more`) : null);
8543
+ return /* @__PURE__ */ React41.createElement(Box35, { key: category, flexDirection: "column" }, /* @__PURE__ */ React41.createElement(Text35, { color: FG.faint }, `${categoryLabel(category)} (${counts[category]})`), shown.map((entry) => /* @__PURE__ */ React41.createElement(Box35, { key: `${category}:${entry.summary}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React41.createElement(Text35, { color: CATEGORY_GLYPH_COLOR[category] }, CATEGORY_GLYPH[category]), /* @__PURE__ */ React41.createElement(Text35, { color: FG.sub }, entry.summary))), remaining > 0 ? /* @__PURE__ */ React41.createElement(Text35, { color: FG.faint }, t("cardLabels.more", { count: remaining })) : null);
8295
8544
  }));
8296
8545
  }
8297
8546
  function countByCategory(entries) {
@@ -8306,8 +8555,8 @@ function countByCategory(entries) {
8306
8555
  }
8307
8556
 
8308
8557
  // src/cli/ui/cards/PlanCard.tsx
8309
- import { Box as Box35, Text as Text35 } from "ink";
8310
- import React41 from "react";
8558
+ import { Box as Box36, Text as Text36 } from "ink";
8559
+ import React42 from "react";
8311
8560
  var STATUS_GLYPH = {
8312
8561
  queued: "\u25CB",
8313
8562
  running: "\u25B6",
@@ -8328,16 +8577,16 @@ function PlanCard({ card }) {
8328
8577
  skipped: fg.faint
8329
8578
  };
8330
8579
  const doneCount = card.steps.filter((s) => s.status === "done").length;
8331
- const variantTag = card.variant === "resumed" ? "resumed \xB7 " : card.variant === "replay" ? "\u23EA archive \xB7 " : "";
8332
- const progress = `${variantTag}${doneCount}/${card.steps.length} done`;
8580
+ const variantTag = card.variant === "resumed" ? t("cardLabels.resumed") : card.variant === "replay" ? t("cardLabels.archive") : "";
8581
+ const progress = `${variantTag}${doneCount}/${card.steps.length} ${t("cardLabels.done")}`;
8333
8582
  const hasRunning = card.steps.some((s) => s.status === "running");
8334
8583
  const cardTone = hasRunning ? toneActive.accent : tone.accent;
8335
8584
  const window = pickWindow(card.steps);
8336
- return /* @__PURE__ */ React41.createElement(Card, { tone: cardTone }, /* @__PURE__ */ React41.createElement(CardHeader, { glyph: "\u229E", tone: cardTone, title: card.title, meta: [progress] }), window.hiddenBefore > 0 ? /* @__PURE__ */ React41.createElement(Box35, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React41.createElement(Text35, { color: tone.ok }, "\u2713"), /* @__PURE__ */ React41.createElement(Text35, { color: fg.faint }, `\u22EF ${window.hiddenBefore} done`)) : null, window.steps.map((step) => {
8585
+ return /* @__PURE__ */ React42.createElement(Card, { tone: cardTone }, /* @__PURE__ */ React42.createElement(CardHeader, { glyph: "\u229E", tone: cardTone, title: card.title, meta: [progress] }), window.hiddenBefore > 0 ? /* @__PURE__ */ React42.createElement(Box36, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React42.createElement(Text36, { color: tone.ok }, "\u2713"), /* @__PURE__ */ React42.createElement(Text36, { color: fg.faint }, `\u22EF ${window.hiddenBefore} ${t("cardLabels.done")}`)) : null, window.steps.map((step) => {
8337
8586
  const isActive = step.status === "running";
8338
8587
  const titleColor = isActive ? fg.strong : fg.sub;
8339
- return /* @__PURE__ */ React41.createElement(Box35, { key: step.id, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React41.createElement(Text35, { color: statusColor[step.status] }, STATUS_GLYPH[step.status]), /* @__PURE__ */ React41.createElement(Text35, { bold: isActive, color: titleColor }, `${step.indexLabel}. ${step.title}`), isActive ? /* @__PURE__ */ React41.createElement(Text35, { color: toneActive.brand }, "\u2190 in progress") : null);
8340
- }), window.hiddenAfter > 0 ? /* @__PURE__ */ React41.createElement(Box35, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React41.createElement(Text35, { color: fg.faint }, "\u25CB"), /* @__PURE__ */ React41.createElement(Text35, { color: fg.faint }, `\u22EF ${window.hiddenAfter} upcoming`)) : null);
8588
+ return /* @__PURE__ */ React42.createElement(Box36, { key: step.id, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React42.createElement(Text36, { color: statusColor[step.status] }, STATUS_GLYPH[step.status]), /* @__PURE__ */ React42.createElement(Text36, { bold: isActive, color: titleColor }, `${step.indexLabel}. ${step.title}`), isActive ? /* @__PURE__ */ React42.createElement(Text36, { color: toneActive.brand }, t("cardLabels.inProgress")) : null);
8589
+ }), window.hiddenAfter > 0 ? /* @__PURE__ */ React42.createElement(Box36, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React42.createElement(Text36, { color: fg.faint }, "\u25CB"), /* @__PURE__ */ React42.createElement(Text36, { color: fg.faint }, `\u22EF ${window.hiddenAfter} ${t("cardLabels.upcoming")}`)) : null);
8341
8590
  }
8342
8591
  function pickWindow(steps) {
8343
8592
  if (steps.length <= VISIBLE_WINDOW) {
@@ -8365,64 +8614,16 @@ function anchorIndex(steps) {
8365
8614
  }
8366
8615
 
8367
8616
  // src/cli/ui/cards/ReasoningCard.tsx
8368
- import { Box as Box36, Text as Text37, useStdout as useStdout10 } from "ink";
8369
- import React43 from "react";
8370
-
8371
- // src/frame/width.ts
8372
- import stringWidthLib from "string-width";
8373
- var segmenter = new Intl.Segmenter("en", { granularity: "grapheme" });
8374
- function graphemes(s) {
8375
- return Array.from(segmenter.segment(s), (seg) => seg.segment);
8376
- }
8377
- function graphemeWidth(g) {
8378
- if (g.length === 0) return 0;
8379
- const w = stringWidthLib(g);
8380
- if (w <= 0) return 0;
8381
- if (w >= 2) return 2;
8382
- return 1;
8383
- }
8384
- function clipToCells(s, maxCells) {
8385
- if (maxCells <= 0) return "";
8386
- if (stringWidthLib(s) <= maxCells) return s;
8387
- const cap = maxCells - 1;
8388
- let out = "";
8389
- let cells = 0;
8390
- for (const g of graphemes(s)) {
8391
- const w = graphemeWidth(g);
8392
- if (cells + w > cap) break;
8393
- out += g;
8394
- cells += w;
8395
- }
8396
- return `${out}\u2026`;
8397
- }
8398
- function wrapToCells(s, maxCells) {
8399
- if (maxCells <= 0) return [];
8400
- if (s.length === 0) return [""];
8401
- const out = [];
8402
- let cur = "";
8403
- let cells = 0;
8404
- for (const g of graphemes(s)) {
8405
- const w = graphemeWidth(g);
8406
- if (cells + w > maxCells) {
8407
- out.push(cur);
8408
- cur = g;
8409
- cells = w;
8410
- } else {
8411
- cur += g;
8412
- cells += w;
8413
- }
8414
- }
8415
- if (cur.length > 0 || out.length === 0) out.push(cur);
8416
- return out;
8417
- }
8617
+ import { Box as Box37, Text as Text38, useStdout as useStdout11 } from "ink";
8618
+ import React44 from "react";
8418
8619
 
8419
8620
  // src/cli/ui/primitives/CursorBlock.tsx
8420
- import { Text as Text36 } from "ink";
8421
- import React42 from "react";
8621
+ import { Text as Text37 } from "ink";
8622
+ import React43 from "react";
8422
8623
  function CursorBlock() {
8423
8624
  const tick = useTick();
8424
8625
  const on = Math.floor(tick / 4) % 2 === 0;
8425
- return /* @__PURE__ */ React42.createElement(Text36, { inverse: on, color: CARD.streaming.color }, " ");
8626
+ return /* @__PURE__ */ React43.createElement(Text37, { inverse: on, color: CARD.streaming.color }, " ");
8426
8627
  }
8427
8628
 
8428
8629
  // src/cli/ui/cards/ReasoningCard.tsx
@@ -8432,13 +8633,13 @@ function ReasoningCard({
8432
8633
  card,
8433
8634
  expanded
8434
8635
  }) {
8435
- const { stdout } = useStdout10();
8636
+ const { stdout } = useStdout11();
8436
8637
  const cols = stdout?.columns ?? 80;
8437
8638
  const lineCells = Math.max(20, cols - 4);
8438
8639
  const allLines = card.text.length > 0 ? card.text.split("\n") : [];
8439
8640
  const showBody = expanded && (allLines.length > 0 || card.streaming);
8440
8641
  const tone = card.aborted ? TONE.err : card.streaming ? TONE_ACTIVE.accent : TONE.accent;
8441
- return /* @__PURE__ */ React43.createElement(Card, { tone }, /* @__PURE__ */ React43.createElement(ReasoningHeader, { card }), showBody && (card.streaming ? /* @__PURE__ */ React43.createElement(StreamingPreview, { card, allLines, lineCells }) : /* @__PURE__ */ React43.createElement(SettledPreview, { card, allLines, lineCells })));
8642
+ return /* @__PURE__ */ React44.createElement(Card, { tone }, /* @__PURE__ */ React44.createElement(ReasoningHeader, { card }), showBody && (card.streaming ? /* @__PURE__ */ React44.createElement(StreamingPreview, { card, allLines, lineCells }) : /* @__PURE__ */ React44.createElement(SettledPreview, { card, allLines, lineCells })));
8442
8643
  }
8443
8644
  function ReasoningHeader({ card }) {
8444
8645
  const streamingActive = card.streaming && !card.aborted;
@@ -8451,7 +8652,7 @@ function ReasoningHeader({ card }) {
8451
8652
  const duration = headerDuration(card);
8452
8653
  if (duration) meta.push(duration);
8453
8654
  const modelBadge = card.model ? modelBadgeFor(card.model) : null;
8454
- return /* @__PURE__ */ React43.createElement(
8655
+ return /* @__PURE__ */ React44.createElement(
8455
8656
  CardHeader,
8456
8657
  {
8457
8658
  glyph,
@@ -8460,7 +8661,7 @@ function ReasoningHeader({ card }) {
8460
8661
  titleColor: PILL_SECTION.reason.fg,
8461
8662
  titleBg: PILL_SECTION.reason.bg,
8462
8663
  meta: meta.length > 0 ? meta : void 0,
8463
- right: /* @__PURE__ */ React43.createElement(React43.Fragment, null, streamingActive ? /* @__PURE__ */ React43.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.accent }) : null, modelBadge ? /* @__PURE__ */ React43.createElement(Pill, { label: modelBadge.label, ...PILL_MODEL[modelBadge.kind], bold: false }) : null)
8664
+ right: /* @__PURE__ */ React44.createElement(React44.Fragment, null, streamingActive ? /* @__PURE__ */ React44.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.accent }) : null, modelBadge ? /* @__PURE__ */ React44.createElement(Pill, { label: modelBadge.label, ...PILL_MODEL[modelBadge.kind], bold: false }) : null)
8464
8665
  }
8465
8666
  );
8466
8667
  }
@@ -8481,13 +8682,13 @@ function headerDuration(card) {
8481
8682
  function StreamingPreview({ card, allLines, lineCells }) {
8482
8683
  const visualLines = allLines.flatMap((l) => wrapToCells(l, lineCells));
8483
8684
  const visible = visualLines.slice(-STREAMING_PREVIEW_LINES);
8484
- return /* @__PURE__ */ React43.createElement(BodyLines, { card, lines: visible, lineCells, cursorOnLast: true });
8685
+ return /* @__PURE__ */ React44.createElement(BodyLines, { card, lines: visible, lineCells, cursorOnLast: true });
8485
8686
  }
8486
8687
  function SettledPreview({ card, allLines, lineCells }) {
8487
8688
  const visualLines = allLines.flatMap((l) => wrapToCells(l, lineCells));
8488
8689
  const visible = visualLines.slice(-SETTLED_TAIL_LINES);
8489
8690
  const droppedLines = Math.max(0, visualLines.length - visible.length);
8490
- return /* @__PURE__ */ React43.createElement(React43.Fragment, null, droppedLines > 0 ? /* @__PURE__ */ React43.createElement(ElisionHint, { droppedLines, card }) : null, /* @__PURE__ */ React43.createElement(BodyLines, { card, lines: visible, lineCells, indexOffset: droppedLines }));
8691
+ return /* @__PURE__ */ React44.createElement(React44.Fragment, null, droppedLines > 0 ? /* @__PURE__ */ React44.createElement(ElisionHint, { droppedLines, card }) : null, /* @__PURE__ */ React44.createElement(BodyLines, { card, lines: visible, lineCells, indexOffset: droppedLines }));
8491
8692
  }
8492
8693
  function BodyLines({
8493
8694
  card,
@@ -8496,9 +8697,9 @@ function BodyLines({
8496
8697
  cursorOnLast = false,
8497
8698
  indexOffset = 0
8498
8699
  }) {
8499
- return /* @__PURE__ */ React43.createElement(React43.Fragment, null, lines.map((line, i) => {
8700
+ return /* @__PURE__ */ React44.createElement(React44.Fragment, null, lines.map((line, i) => {
8500
8701
  const isLast = i === lines.length - 1;
8501
- return /* @__PURE__ */ React43.createElement(Box36, { key: `${card.id}:b:${indexOffset + i}`, flexDirection: "row" }, /* @__PURE__ */ React43.createElement(Text37, { italic: true, color: FG.meta }, clipToCells(line, lineCells)), isLast && cursorOnLast && /* @__PURE__ */ React43.createElement(CursorBlock, null));
8702
+ return /* @__PURE__ */ React44.createElement(Box37, { key: `${card.id}:b:${indexOffset + i}`, flexDirection: "row" }, /* @__PURE__ */ React44.createElement(Text38, { italic: true, color: FG.meta }, clipToCells(line, lineCells)), isLast && cursorOnLast && /* @__PURE__ */ React44.createElement(CursorBlock, null));
8502
8703
  }));
8503
8704
  }
8504
8705
  function ElisionHint({
@@ -8512,12 +8713,12 @@ function ElisionHint({
8512
8713
  parts.push(`${droppedLines} line${droppedLines === 1 ? "" : "s"}`);
8513
8714
  }
8514
8715
  if (card.tokens > 0) parts.push(`${card.tokens.toLocaleString()} tok`);
8515
- return /* @__PURE__ */ React43.createElement(Text37, { color: FG.faint }, `\u22EF ${parts.join(" \xB7 ")} above \xB7 /reasoning last`);
8716
+ return /* @__PURE__ */ React44.createElement(Text38, { color: FG.faint }, `\u22EF ${parts.join(" \xB7 ")} above \xB7 /reasoning last`);
8516
8717
  }
8517
8718
 
8518
8719
  // src/cli/ui/cards/SearchCard.tsx
8519
- import { Box as Box37, Text as Text38 } from "ink";
8520
- import React44 from "react";
8720
+ import { Box as Box38, Text as Text39 } from "ink";
8721
+ import React45 from "react";
8521
8722
  function SearchCard({ card }) {
8522
8723
  const fileCount = new Set(card.hits.map((h) => h.file)).size;
8523
8724
  const elapsed = `${(card.elapsedMs / 1e3).toFixed(2)}s`;
@@ -8526,7 +8727,7 @@ function SearchCard({ card }) {
8526
8727
  files: fileCount
8527
8728
  });
8528
8729
  const grouped = groupByFile(card.hits.slice(0, 10));
8529
- return /* @__PURE__ */ React44.createElement(Card, { tone: TONE.info }, /* @__PURE__ */ React44.createElement(
8730
+ return /* @__PURE__ */ React45.createElement(Card, { tone: TONE.info }, /* @__PURE__ */ React45.createElement(
8530
8731
  CardHeader,
8531
8732
  {
8532
8733
  glyph: "\u2299",
@@ -8535,7 +8736,7 @@ function SearchCard({ card }) {
8535
8736
  subtitle: `"${card.query}"`,
8536
8737
  meta: [stats2, elapsed]
8537
8738
  }
8538
- ), grouped.map(([file, hits]) => /* @__PURE__ */ React44.createElement(Box37, { key: file, flexDirection: "column" }, /* @__PURE__ */ React44.createElement(Text38, { bold: true, color: FG.strong }, file), hits.map((h, i) => /* @__PURE__ */ React44.createElement(Box37, { key: `${file}:${h.line}:${i}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React44.createElement(Text38, { color: FG.faint }, `${h.line.toString().padStart(4)} \u2502`), /* @__PURE__ */ React44.createElement(HighlightedLine, { text: h.preview, start: h.matchStart, end: h.matchEnd }))))), card.hits.length > 10 ? /* @__PURE__ */ React44.createElement(Text38, { color: FG.faint }, t(
8739
+ ), grouped.map(([file, hits]) => /* @__PURE__ */ React45.createElement(Box38, { key: file, flexDirection: "column" }, /* @__PURE__ */ React45.createElement(Text39, { bold: true, color: FG.strong }, file), hits.map((h, i) => /* @__PURE__ */ React45.createElement(Box38, { key: `${file}:${h.line}:${i}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React45.createElement(Text39, { color: FG.faint }, `${h.line.toString().padStart(4)} \u2502`), /* @__PURE__ */ React45.createElement(HighlightedLine, { text: h.preview, start: h.matchStart, end: h.matchEnd }))))), card.hits.length > 10 ? /* @__PURE__ */ React45.createElement(Text39, { color: FG.faint }, t(
8539
8740
  card.hits.length - 10 === 1 ? "cardLabels.moreHitSingular" : "cardLabels.moreHitsPlural",
8540
8741
  { count: card.hits.length - 10 }
8541
8742
  )) : null);
@@ -8546,9 +8747,9 @@ function HighlightedLine({
8546
8747
  end
8547
8748
  }) {
8548
8749
  if (start < 0 || end <= start || end > text.length) {
8549
- return /* @__PURE__ */ React44.createElement(Text38, { color: FG.sub }, text);
8750
+ return /* @__PURE__ */ React45.createElement(Text39, { color: FG.sub }, text);
8550
8751
  }
8551
- return /* @__PURE__ */ React44.createElement(React44.Fragment, null, /* @__PURE__ */ React44.createElement(Text38, { color: FG.sub }, text.slice(0, start)), /* @__PURE__ */ React44.createElement(Text38, { bold: true, inverse: true }, text.slice(start, end)), /* @__PURE__ */ React44.createElement(Text38, { color: FG.sub }, text.slice(end)));
8752
+ return /* @__PURE__ */ React45.createElement(React45.Fragment, null, /* @__PURE__ */ React45.createElement(Text39, { color: FG.sub }, text.slice(0, start)), /* @__PURE__ */ React45.createElement(Text39, { bold: true, inverse: true }, text.slice(start, end)), /* @__PURE__ */ React45.createElement(Text39, { color: FG.sub }, text.slice(end)));
8552
8753
  }
8553
8754
  function groupByFile(hits) {
8554
8755
  const map = /* @__PURE__ */ new Map();
@@ -8561,8 +8762,8 @@ function groupByFile(hits) {
8561
8762
  }
8562
8763
 
8563
8764
  // src/cli/ui/cards/StreamingCard.tsx
8564
- import { Box as Box39, Text as Text40, useStdout as useStdout12 } from "ink";
8565
- import React46, { useContext as useContext5 } from "react";
8765
+ import { Box as Box40, Text as Text41, useStdout as useStdout13 } from "ink";
8766
+ import React47, { useContext as useContext5 } from "react";
8566
8767
 
8567
8768
  // src/cli/ui/layout/LiveExpandContext.ts
8568
8769
  import { createContext as createContext3 } from "react";
@@ -8570,54 +8771,54 @@ var LiveExpandContext = createContext3(false);
8570
8771
 
8571
8772
  // src/cli/ui/markdown.tsx
8572
8773
  import { highlight, supportsLanguage } from "cli-highlight";
8573
- import { Box as Box38, Text as Text39, useStdout as useStdout11 } from "ink";
8574
- import React45 from "react";
8774
+ import { Box as Box39, Text as Text40, useStdout as useStdout12 } from "ink";
8775
+ import React46 from "react";
8575
8776
  import stringWidth from "string-width";
8576
8777
  var BODY_LEFT_CELLS = 7;
8577
- var MarkdownWidthCtx = React45.createContext(void 0);
8778
+ var MarkdownWidthCtx = React46.createContext(void 0);
8578
8779
  function useWidth() {
8579
- const ctx = React45.useContext(MarkdownWidthCtx);
8780
+ const ctx = React46.useContext(MarkdownWidthCtx);
8580
8781
  if (ctx !== void 0) return ctx;
8581
- return (useStdout11()?.stdout?.columns ?? process.stdout.columns ?? 80) - BODY_LEFT_CELLS;
8782
+ return (useStdout12()?.stdout?.columns ?? process.stdout.columns ?? 80) - BODY_LEFT_CELLS;
8582
8783
  }
8583
8784
  marked.setOptions({ gfm: true, breaks: false });
8584
8785
  function Markdown({ text, width }) {
8585
- const tokens = React45.useMemo(() => marked.lexer(text), [text]);
8786
+ const tokens = React46.useMemo(() => marked.lexer(text), [text]);
8586
8787
  const ctxWidth = width !== void 0 ? Math.max(1, width) : void 0;
8587
- return /* @__PURE__ */ React45.createElement(MarkdownWidthCtx.Provider, { value: ctxWidth }, /* @__PURE__ */ React45.createElement(Box38, { flexDirection: "column", gap: 1 }, tokens.map((token, i) => /* @__PURE__ */ React45.createElement(BlockToken, { key: `${i}-${token.type}`, token }))));
8788
+ return /* @__PURE__ */ React46.createElement(MarkdownWidthCtx.Provider, { value: ctxWidth }, /* @__PURE__ */ React46.createElement(Box39, { flexDirection: "column", gap: 1 }, tokens.map((token, i) => /* @__PURE__ */ React46.createElement(BlockToken, { key: `${i}-${token.type}`, token }))));
8588
8789
  }
8589
8790
  function BlockToken({ token }) {
8590
8791
  switch (token.type) {
8591
8792
  case "heading":
8592
- return /* @__PURE__ */ React45.createElement(Heading, { token });
8793
+ return /* @__PURE__ */ React46.createElement(Heading, { token });
8593
8794
  case "paragraph":
8594
- return /* @__PURE__ */ React45.createElement(Paragraph, { token });
8795
+ return /* @__PURE__ */ React46.createElement(Paragraph, { token });
8595
8796
  case "list":
8596
- return /* @__PURE__ */ React45.createElement(List, { token, depth: 0 });
8797
+ return /* @__PURE__ */ React46.createElement(List, { token, depth: 0 });
8597
8798
  case "code":
8598
- return /* @__PURE__ */ React45.createElement(CodeBlock2, { token });
8799
+ return /* @__PURE__ */ React46.createElement(CodeBlock2, { token });
8599
8800
  case "blockquote":
8600
- return /* @__PURE__ */ React45.createElement(Blockquote, { token });
8801
+ return /* @__PURE__ */ React46.createElement(Blockquote, { token });
8601
8802
  case "hr":
8602
- return /* @__PURE__ */ React45.createElement(HorizontalRule, null);
8803
+ return /* @__PURE__ */ React46.createElement(HorizontalRule, null);
8603
8804
  case "table":
8604
- return /* @__PURE__ */ React45.createElement(Table, { token });
8805
+ return /* @__PURE__ */ React46.createElement(Table, { token });
8605
8806
  case "html":
8606
- return /* @__PURE__ */ React45.createElement(Text39, { color: FG.body }, token.text);
8807
+ return /* @__PURE__ */ React46.createElement(Text40, { color: FG.body }, token.text);
8607
8808
  case "space":
8608
8809
  return null;
8609
8810
  default:
8610
- return /* @__PURE__ */ React45.createElement(Text39, { color: FG.body }, token.raw ?? "");
8811
+ return /* @__PURE__ */ React46.createElement(Text40, { color: FG.body }, token.raw ?? "");
8611
8812
  }
8612
8813
  }
8613
8814
  function Heading({ token }) {
8614
- return /* @__PURE__ */ React45.createElement(Box38, null, /* @__PURE__ */ React45.createElement(Text39, { bold: true, color: FG.strong, backgroundColor: SURFACE.bgElev }, ` ${plainText(token.tokens)} `));
8815
+ return /* @__PURE__ */ React46.createElement(Box39, null, /* @__PURE__ */ React46.createElement(Text40, { bold: true, color: FG.strong, backgroundColor: SURFACE.bgElev }, ` ${plainText(token.tokens)} `));
8615
8816
  }
8616
8817
  function Paragraph({ token }) {
8617
- return /* @__PURE__ */ React45.createElement(Text39, { color: FG.body }, /* @__PURE__ */ React45.createElement(Inline, { tokens: token.tokens ?? [] }));
8818
+ return /* @__PURE__ */ React46.createElement(Text40, { color: FG.body }, /* @__PURE__ */ React46.createElement(Inline, { tokens: token.tokens ?? [] }));
8618
8819
  }
8619
8820
  function List({ token, depth }) {
8620
- return /* @__PURE__ */ React45.createElement(Box38, { flexDirection: "column" }, token.items.map((item, i) => /* @__PURE__ */ React45.createElement(
8821
+ return /* @__PURE__ */ React46.createElement(Box39, { flexDirection: "column" }, token.items.map((item, i) => /* @__PURE__ */ React46.createElement(
8621
8822
  ListItem,
8622
8823
  {
8623
8824
  key: `${i}-${item.text.slice(0, 24)}`,
@@ -8638,27 +8839,27 @@ function ListItem({
8638
8839
  const markerColor = item.task ? item.checked ? TONE.ok : FG.faint : FG.meta;
8639
8840
  const dim = item.task && item.checked === true;
8640
8841
  const indent = " ".repeat(depth + 1);
8641
- return /* @__PURE__ */ React45.createElement(Box38, null, /* @__PURE__ */ React45.createElement(Text39, { color: markerColor }, `${indent}${marker} `), /* @__PURE__ */ React45.createElement(Box38, { flexDirection: "column" }, item.tokens.map((tok, i) => {
8842
+ return /* @__PURE__ */ React46.createElement(Box39, null, /* @__PURE__ */ React46.createElement(Text40, { color: markerColor }, `${indent}${marker} `), /* @__PURE__ */ React46.createElement(Box39, { flexDirection: "column" }, item.tokens.map((tok, i) => {
8642
8843
  if (tok.type === "text") {
8643
8844
  const inner = tok.tokens;
8644
8845
  return (
8645
8846
  // biome-ignore lint/suspicious/noArrayIndexKey: list-item children are positional and stable per render
8646
- /* @__PURE__ */ React45.createElement(Text39, { key: `t-${i}`, color: dim ? FG.faint : FG.body, strikethrough: dim }, inner ? /* @__PURE__ */ React45.createElement(Inline, { tokens: inner }) : tok.text)
8847
+ /* @__PURE__ */ React46.createElement(Text40, { key: `t-${i}`, color: dim ? FG.faint : FG.body, strikethrough: dim }, inner ? /* @__PURE__ */ React46.createElement(Inline, { tokens: inner }) : tok.text)
8647
8848
  );
8648
8849
  }
8649
8850
  if (tok.type === "list") {
8650
- return /* @__PURE__ */ React45.createElement(List, { key: `l-${i}`, token: tok, depth: depth + 1 });
8851
+ return /* @__PURE__ */ React46.createElement(List, { key: `l-${i}`, token: tok, depth: depth + 1 });
8651
8852
  }
8652
- return /* @__PURE__ */ React45.createElement(BlockToken, { key: `b-${i}-${tok.type}`, token: tok });
8853
+ return /* @__PURE__ */ React46.createElement(BlockToken, { key: `b-${i}-${tok.type}`, token: tok });
8653
8854
  })));
8654
8855
  }
8655
8856
  function CodeBlock2({ token }) {
8656
8857
  const lang = token.lang?.split(/\s+/)[0] ?? "";
8657
8858
  const colored = highlightCode(token.text, lang);
8658
8859
  const lines = colored.split("\n");
8659
- return /* @__PURE__ */ React45.createElement(Box38, { flexDirection: "column" }, lang ? /* @__PURE__ */ React45.createElement(Box38, null, /* @__PURE__ */ React45.createElement(Text39, { color: FG.meta }, ` ${lang}`)) : null, /* @__PURE__ */ React45.createElement(Box38, { flexDirection: "column" }, lines.map((line, i) => (
8860
+ return /* @__PURE__ */ React46.createElement(Box39, { flexDirection: "column" }, lang ? /* @__PURE__ */ React46.createElement(Box39, null, /* @__PURE__ */ React46.createElement(Text40, { color: FG.meta }, ` ${lang}`)) : null, /* @__PURE__ */ React46.createElement(Box39, { flexDirection: "column" }, lines.map((line, i) => (
8660
8861
  // biome-ignore lint/suspicious/noArrayIndexKey: code lines are positional and stable per render
8661
- /* @__PURE__ */ React45.createElement(Text39, { key: `code-${i}`, backgroundColor: SURFACE.bgElev }, ` ${line} `)
8862
+ /* @__PURE__ */ React46.createElement(Text40, { key: `code-${i}`, backgroundColor: SURFACE.bgElev }, ` ${line} `)
8662
8863
  ))));
8663
8864
  }
8664
8865
  function highlightCode(source, lang) {
@@ -8671,7 +8872,7 @@ function highlightCode(source, lang) {
8671
8872
  }
8672
8873
  }
8673
8874
  function Blockquote({ token }) {
8674
- return /* @__PURE__ */ React45.createElement(Box38, { flexDirection: "column" }, (token.tokens ?? []).map((child, i) => /* @__PURE__ */ React45.createElement(Box38, { key: `${i}-${child.type}`, flexDirection: "row" }, /* @__PURE__ */ React45.createElement(Text39, { color: TONE.brand }, " \u258E "), /* @__PURE__ */ React45.createElement(Box38, { flexDirection: "column", flexGrow: 1 }, child.type === "paragraph" ? /* @__PURE__ */ React45.createElement(Text39, { italic: true, color: FG.sub }, /* @__PURE__ */ React45.createElement(Inline, { tokens: child.tokens ?? [] })) : /* @__PURE__ */ React45.createElement(BlockToken, { token: child })))));
8875
+ return /* @__PURE__ */ React46.createElement(Box39, { flexDirection: "column" }, (token.tokens ?? []).map((child, i) => /* @__PURE__ */ React46.createElement(Box39, { key: `${i}-${child.type}`, flexDirection: "row" }, /* @__PURE__ */ React46.createElement(Text40, { color: TONE.brand }, " \u258E "), /* @__PURE__ */ React46.createElement(Box39, { flexDirection: "column", flexGrow: 1 }, child.type === "paragraph" ? /* @__PURE__ */ React46.createElement(Text40, { italic: true, color: FG.sub }, /* @__PURE__ */ React46.createElement(Inline, { tokens: child.tokens ?? [] })) : /* @__PURE__ */ React46.createElement(BlockToken, { token: child })))));
8675
8876
  }
8676
8877
  function padToCells(text, cells) {
8677
8878
  const w = stringWidth(text);
@@ -8681,7 +8882,7 @@ function padToCells(text, cells) {
8681
8882
  function HorizontalRule() {
8682
8883
  const width = useWidth();
8683
8884
  const rule = "\u2500".repeat(Math.max(width, 1));
8684
- return /* @__PURE__ */ React45.createElement(Text39, { color: FG.faint }, ` ${rule}`);
8885
+ return /* @__PURE__ */ React46.createElement(Text40, { color: FG.faint }, ` ${rule}`);
8685
8886
  }
8686
8887
  function tableLayout(headerCells, bodyCells, availableWidth) {
8687
8888
  const colCount = headerCells.length;
@@ -8709,7 +8910,7 @@ function Table({ token }) {
8709
8910
  const bodyCells = token.rows.map((row2) => row2.map((c) => plainText(c.tokens)));
8710
8911
  const layout = tableLayout(headerCells, bodyCells, width);
8711
8912
  if (!layout.fallback)
8712
- return /* @__PURE__ */ React45.createElement(
8913
+ return /* @__PURE__ */ React46.createElement(
8713
8914
  ColumnarTable,
8714
8915
  {
8715
8916
  headerCells,
@@ -8719,7 +8920,7 @@ function Table({ token }) {
8719
8920
  gap: layout.gap
8720
8921
  }
8721
8922
  );
8722
- return /* @__PURE__ */ React45.createElement(
8923
+ return /* @__PURE__ */ React46.createElement(
8723
8924
  FallbackTable,
8724
8925
  {
8725
8926
  headerCells,
@@ -8737,14 +8938,14 @@ function ColumnarTable({
8737
8938
  gap
8738
8939
  }) {
8739
8940
  const ruleRow = widths.map((w) => "\u2500".repeat(w)).join(gap);
8740
- return /* @__PURE__ */ React45.createElement(Box38, { flexDirection: "column" }, /* @__PURE__ */ React45.createElement(Box38, null, /* @__PURE__ */ React45.createElement(Text39, null, " "), headerCells.map((cell, i) => (
8941
+ return /* @__PURE__ */ React46.createElement(Box39, { flexDirection: "column" }, /* @__PURE__ */ React46.createElement(Box39, null, /* @__PURE__ */ React46.createElement(Text40, null, " "), headerCells.map((cell, i) => (
8741
8942
  // biome-ignore lint/suspicious/noArrayIndexKey: header cells positional
8742
- /* @__PURE__ */ React45.createElement(React45.Fragment, { key: `h-${i}` }, /* @__PURE__ */ React45.createElement(Text39, { bold: true, color: FG.sub }, padToCells(cell, widths[i])), i < colCount - 1 ? /* @__PURE__ */ React45.createElement(Text39, null, gap) : null)
8743
- ))), /* @__PURE__ */ React45.createElement(Box38, null, /* @__PURE__ */ React45.createElement(Text39, null, " "), /* @__PURE__ */ React45.createElement(Text39, { color: FG.faint }, ruleRow)), bodyCells.map((row2, ri) => (
8943
+ /* @__PURE__ */ React46.createElement(React46.Fragment, { key: `h-${i}` }, /* @__PURE__ */ React46.createElement(Text40, { bold: true, color: FG.sub }, padToCells(cell, widths[i])), i < colCount - 1 ? /* @__PURE__ */ React46.createElement(Text40, null, gap) : null)
8944
+ ))), /* @__PURE__ */ React46.createElement(Box39, null, /* @__PURE__ */ React46.createElement(Text40, null, " "), /* @__PURE__ */ React46.createElement(Text40, { color: FG.faint }, ruleRow)), bodyCells.map((row2, ri) => (
8744
8945
  // biome-ignore lint/suspicious/noArrayIndexKey: body rows positional
8745
- /* @__PURE__ */ React45.createElement(Box38, { key: `tr-${ri}` }, /* @__PURE__ */ React45.createElement(Text39, null, " "), row2.map((cell, i) => (
8946
+ /* @__PURE__ */ React46.createElement(Box39, { key: `tr-${ri}` }, /* @__PURE__ */ React46.createElement(Text40, null, " "), row2.map((cell, i) => (
8746
8947
  // biome-ignore lint/suspicious/noArrayIndexKey: cells positional
8747
- /* @__PURE__ */ React45.createElement(React45.Fragment, { key: `c-${ri}-${i}` }, /* @__PURE__ */ React45.createElement(Text39, { color: FG.body }, padToCells(cell ?? "", widths[i])), i < colCount - 1 ? /* @__PURE__ */ React45.createElement(Text39, null, gap) : null)
8948
+ /* @__PURE__ */ React46.createElement(React46.Fragment, { key: `c-${ri}-${i}` }, /* @__PURE__ */ React46.createElement(Text40, { color: FG.body }, padToCells(cell ?? "", widths[i])), i < colCount - 1 ? /* @__PURE__ */ React46.createElement(Text40, null, gap) : null)
8748
8949
  )))
8749
8950
  )));
8750
8951
  }
@@ -8754,20 +8955,20 @@ function FallbackTable({
8754
8955
  labelPad,
8755
8956
  valueCells
8756
8957
  }) {
8757
- return /* @__PURE__ */ React45.createElement(Box38, { flexDirection: "column" }, bodyCells.map((row2, ri) => (
8958
+ return /* @__PURE__ */ React46.createElement(Box39, { flexDirection: "column" }, bodyCells.map((row2, ri) => (
8758
8959
  // biome-ignore lint/suspicious/noArrayIndexKey: body rows positional
8759
- /* @__PURE__ */ React45.createElement(Box38, { key: `fr-${ri}`, flexDirection: "column" }, ri > 0 ? /* @__PURE__ */ React45.createElement(Text39, null, " ") : null, headerCells.map((h, ci) => {
8960
+ /* @__PURE__ */ React46.createElement(Box39, { key: `fr-${ri}`, flexDirection: "column" }, ri > 0 ? /* @__PURE__ */ React46.createElement(Text40, null, " ") : null, headerCells.map((h, ci) => {
8760
8961
  const label = `${padToCells(h, labelPad - 2)}: `;
8761
8962
  const lines = wrapToCells(row2[ci] ?? "", valueCells);
8762
8963
  return lines.map((line, li) => (
8763
8964
  // biome-ignore lint/suspicious/noArrayIndexKey: fallback table lines are positional
8764
- /* @__PURE__ */ React45.createElement(Box38, { key: `fc-${ri}-${ci}-${li}` }, li === 0 ? /* @__PURE__ */ React45.createElement(Text39, { bold: true, color: FG.sub }, label) : /* @__PURE__ */ React45.createElement(Text39, null, padToCells("", labelPad)), /* @__PURE__ */ React45.createElement(Text39, { color: FG.body }, line))
8965
+ /* @__PURE__ */ React46.createElement(Box39, { key: `fc-${ri}-${ci}-${li}` }, li === 0 ? /* @__PURE__ */ React46.createElement(Text40, { bold: true, color: FG.sub }, label) : /* @__PURE__ */ React46.createElement(Text40, null, padToCells("", labelPad)), /* @__PURE__ */ React46.createElement(Text40, { color: FG.body }, line))
8765
8966
  ));
8766
8967
  }))
8767
8968
  )));
8768
8969
  }
8769
8970
  function Inline({ tokens }) {
8770
- return /* @__PURE__ */ React45.createElement(React45.Fragment, null, tokens.map((tok, i) => /* @__PURE__ */ React45.createElement(InlineToken, { key: `${i}-${tok.type}`, token: tok })));
8971
+ return /* @__PURE__ */ React46.createElement(React46.Fragment, null, tokens.map((tok, i) => /* @__PURE__ */ React46.createElement(InlineToken, { key: `${i}-${tok.type}`, token: tok })));
8771
8972
  }
8772
8973
  var FILE_REF_RE2 = /\b([A-Za-z0-9_./@\-]+\.[A-Za-z0-9]{1,6})(?::(\d+)(?:-(\d+))?)?\b/g;
8773
8974
  var MENTION_RE = /(?<![A-Za-z0-9_])@([A-Za-z0-9_./\-]+\.[A-Za-z0-9]{1,6})/g;
@@ -8778,10 +8979,10 @@ function looksLikeFileRef(path, hasLine) {
8778
8979
  return ext.length >= 2;
8779
8980
  }
8780
8981
  function osc8(label, _target, color) {
8781
- return /* @__PURE__ */ React45.createElement(Text39, { color, underline: true }, label);
8982
+ return /* @__PURE__ */ React46.createElement(Text40, { color, underline: true }, label);
8782
8983
  }
8783
8984
  function renderInlineText(raw) {
8784
- if (!raw) return /* @__PURE__ */ React45.createElement(Text39, null, raw);
8985
+ if (!raw) return /* @__PURE__ */ React46.createElement(Text40, null, raw);
8785
8986
  const out = [];
8786
8987
  let cursor = 0;
8787
8988
  const hits = [];
@@ -8792,7 +8993,7 @@ function renderInlineText(raw) {
8792
8993
  hits.push({
8793
8994
  start,
8794
8995
  end,
8795
- node: /* @__PURE__ */ React45.createElement(Text39, { color: TONE.warn, underline: true }, `@${path}`)
8996
+ node: /* @__PURE__ */ React46.createElement(Text40, { color: TONE.warn, underline: true }, `@${path}`)
8796
8997
  });
8797
8998
  }
8798
8999
  for (const m of raw.matchAll(FILE_REF_RE2)) {
@@ -8809,44 +9010,44 @@ function renderInlineText(raw) {
8809
9010
  let key = 0;
8810
9011
  for (const h of hits) {
8811
9012
  if (h.start > cursor) {
8812
- out.push(/* @__PURE__ */ React45.createElement(Text39, { key: `t-${key++}` }, raw.slice(cursor, h.start)));
9013
+ out.push(/* @__PURE__ */ React46.createElement(Text40, { key: `t-${key++}` }, raw.slice(cursor, h.start)));
8813
9014
  }
8814
- out.push(/* @__PURE__ */ React45.createElement(React45.Fragment, { key: `r-${key++}` }, h.node));
9015
+ out.push(/* @__PURE__ */ React46.createElement(React46.Fragment, { key: `r-${key++}` }, h.node));
8815
9016
  cursor = h.end;
8816
9017
  }
8817
- if (cursor < raw.length) out.push(/* @__PURE__ */ React45.createElement(Text39, { key: `t-${key++}` }, raw.slice(cursor)));
8818
- return /* @__PURE__ */ React45.createElement(React45.Fragment, null, out);
9018
+ if (cursor < raw.length) out.push(/* @__PURE__ */ React46.createElement(Text40, { key: `t-${key++}` }, raw.slice(cursor)));
9019
+ return /* @__PURE__ */ React46.createElement(React46.Fragment, null, out);
8819
9020
  }
8820
9021
  function InlineToken({ token }) {
8821
9022
  switch (token.type) {
8822
9023
  case "text": {
8823
9024
  const t2 = token;
8824
- return t2.tokens ? /* @__PURE__ */ React45.createElement(Inline, { tokens: t2.tokens }) : renderInlineText(t2.text);
9025
+ return t2.tokens ? /* @__PURE__ */ React46.createElement(Inline, { tokens: t2.tokens }) : renderInlineText(t2.text);
8825
9026
  }
8826
9027
  case "strong":
8827
- return /* @__PURE__ */ React45.createElement(Text39, { bold: true, color: FG.strong }, /* @__PURE__ */ React45.createElement(Inline, { tokens: token.tokens }));
9028
+ return /* @__PURE__ */ React46.createElement(Text40, { bold: true, color: FG.strong }, /* @__PURE__ */ React46.createElement(Inline, { tokens: token.tokens }));
8828
9029
  case "em":
8829
- return /* @__PURE__ */ React45.createElement(Text39, { italic: true }, /* @__PURE__ */ React45.createElement(Inline, { tokens: token.tokens }));
9030
+ return /* @__PURE__ */ React46.createElement(Text40, { italic: true }, /* @__PURE__ */ React46.createElement(Inline, { tokens: token.tokens }));
8830
9031
  case "codespan":
8831
- return /* @__PURE__ */ React45.createElement(Text39, { color: FG.strong, backgroundColor: SURFACE.bgElev }, ` ${token.text} `);
9032
+ return /* @__PURE__ */ React46.createElement(Text40, { color: FG.strong, backgroundColor: SURFACE.bgElev }, ` ${token.text} `);
8832
9033
  case "del":
8833
- return /* @__PURE__ */ React45.createElement(Text39, { color: TONE.err, strikethrough: true }, /* @__PURE__ */ React45.createElement(Inline, { tokens: token.tokens }));
9034
+ return /* @__PURE__ */ React46.createElement(Text40, { color: TONE.err, strikethrough: true }, /* @__PURE__ */ React46.createElement(Inline, { tokens: token.tokens }));
8834
9035
  case "link": {
8835
9036
  const l = token;
8836
- return /* @__PURE__ */ React45.createElement(Text39, { color: TONE.brand, underline: true }, /* @__PURE__ */ React45.createElement(Inline, { tokens: l.tokens }));
9037
+ return /* @__PURE__ */ React46.createElement(Text40, { color: TONE.brand, underline: true }, /* @__PURE__ */ React46.createElement(Inline, { tokens: l.tokens }));
8837
9038
  }
8838
9039
  case "image": {
8839
9040
  const im = token;
8840
- return /* @__PURE__ */ React45.createElement(Text39, { color: TONE.brand }, `[image: ${im.text || im.href}]`);
9041
+ return /* @__PURE__ */ React46.createElement(Text40, { color: TONE.brand }, `[image: ${im.text || im.href}]`);
8841
9042
  }
8842
9043
  case "br":
8843
- return /* @__PURE__ */ React45.createElement(Text39, null, "\n");
9044
+ return /* @__PURE__ */ React46.createElement(Text40, null, "\n");
8844
9045
  case "escape":
8845
- return /* @__PURE__ */ React45.createElement(Text39, null, token.text);
9046
+ return /* @__PURE__ */ React46.createElement(Text40, null, token.text);
8846
9047
  case "html":
8847
- return /* @__PURE__ */ React45.createElement(Text39, null, token.text);
9048
+ return /* @__PURE__ */ React46.createElement(Text40, null, token.text);
8848
9049
  default:
8849
- return /* @__PURE__ */ React45.createElement(Text39, null, token.raw ?? "");
9050
+ return /* @__PURE__ */ React46.createElement(Text40, null, token.raw ?? "");
8850
9051
  }
8851
9052
  }
8852
9053
  function plainText(tokens) {
@@ -8884,22 +9085,50 @@ var STREAMING_PREVIEW_LINES2 = 4;
8884
9085
  var EXPANDED_MAX_LINES = 60;
8885
9086
  var MIN_ELAPSED_MS_FOR_RATE = 500;
8886
9087
  var MIN_TOKENS_FOR_RATE = 4;
9088
+ var LIVE_TOKEN_CALIBRATION_CHARS = 500;
9089
+ var ESTIMATED_CHARS_PER_TOKEN = 4;
8887
9090
  function formatTokenCount(n) {
8888
9091
  if (n >= 1e4) return `${(n / 1e3).toFixed(1)}k`;
8889
9092
  if (n >= 1e3) return `${(n / 1e3).toFixed(2)}k`;
8890
9093
  return String(n);
8891
9094
  }
8892
- function tokenRate(text, startTs, endTs) {
8893
- const tokens = countTokens(text);
9095
+ function rateFromTokens(tokens, startTs, endTs) {
8894
9096
  const elapsedMs = endTs - startTs;
8895
9097
  if (elapsedMs < MIN_ELAPSED_MS_FOR_RATE || tokens < MIN_TOKENS_FOR_RATE) {
8896
9098
  return { tokens, tps: null };
8897
9099
  }
8898
9100
  return { tokens, tps: Math.round(tokens * 1e3 / elapsedMs) };
8899
9101
  }
9102
+ function tokenRate(text, startTs, endTs) {
9103
+ return rateFromTokens(countTokens(text), startTs, endTs);
9104
+ }
9105
+ function estimateLiveTokenCount(text, cardId, calibration, countFn = countTokens) {
9106
+ const chars = text.length;
9107
+ const shouldCalibrate = chars > 0 && (!calibration || calibration.cardId !== cardId || chars < calibration.chars || calibration.chars === 0 && chars > 0 || chars - calibration.chars >= LIVE_TOKEN_CALIBRATION_CHARS);
9108
+ if (shouldCalibrate) {
9109
+ const tokens = countFn(text);
9110
+ return { tokens, calibration: { cardId, chars, tokens }, exact: true };
9111
+ }
9112
+ const base = calibration?.cardId === cardId && chars >= calibration.chars ? calibration : null;
9113
+ const baseChars = base?.chars ?? 0;
9114
+ const baseTokens = base?.tokens ?? 0;
9115
+ const estimatedDelta = Math.ceil(Math.max(0, chars - baseChars) / ESTIMATED_CHARS_PER_TOKEN);
9116
+ return {
9117
+ tokens: baseTokens + estimatedDelta,
9118
+ calibration: base ?? { cardId, chars: 0, tokens: 0 },
9119
+ exact: false
9120
+ };
9121
+ }
9122
+ function useLiveTokenRate(card, enabled) {
9123
+ const calibrationRef = React47.useRef(null);
9124
+ if (!enabled) return { tokens: 0, tps: null };
9125
+ const estimate = estimateLiveTokenCount(card.text, card.id, calibrationRef.current);
9126
+ calibrationRef.current = estimate.calibration;
9127
+ return rateFromTokens(estimate.tokens, card.ts, Date.now());
9128
+ }
8900
9129
  var PILL_RATE = { bg: "#11141a", fg: "#8b949e" };
8901
9130
  function StreamingCard({ card }) {
8902
- const { stdout } = useStdout12();
9131
+ const { stdout } = useStdout13();
8903
9132
  const cols = stdout?.columns ?? 80;
8904
9133
  const expanded = useContext5(LiveExpandContext);
8905
9134
  const reserveCap = expanded ? EXPANDED_MAX_LINES + 2 : STREAMING_PREVIEW_LINES2 + 2;
@@ -8908,20 +9137,21 @@ function StreamingCard({ card }) {
8908
9137
  max: reserveCap
8909
9138
  });
8910
9139
  useSlowTick();
9140
+ const liveRate = useLiveTokenRate(card, !card.done && !card.aborted);
8911
9141
  const modelBadge = card.model ? modelBadgeFor(card.model) : null;
8912
- const modelPill = modelBadge ? /* @__PURE__ */ React46.createElement(Pill, { label: modelBadge.label, ...PILL_MODEL[modelBadge.kind], bold: false }) : null;
9142
+ const modelPill = modelBadge ? /* @__PURE__ */ React47.createElement(Pill, { label: modelBadge.label, ...PILL_MODEL[modelBadge.kind], bold: false }) : null;
8913
9143
  if (card.done && !card.aborted) {
8914
9144
  const { tokens, tps } = tokenRate(card.text, card.ts, card.endedAt ?? Date.now());
8915
- const ratePill = tokens >= MIN_TOKENS_FOR_RATE && tps !== null ? /* @__PURE__ */ React46.createElement(Pill, { label: `${formatTokenCount(tokens)} tok \xB7 ${tps} t/s`, ...PILL_RATE, bold: false }) : null;
8916
- return /* @__PURE__ */ React46.createElement(Card, { tone: TONE.ok }, /* @__PURE__ */ React46.createElement(
9145
+ const ratePill = tokens >= MIN_TOKENS_FOR_RATE && tps !== null ? /* @__PURE__ */ React47.createElement(Pill, { label: `${formatTokenCount(tokens)} tok \xB7 ${tps} t/s`, ...PILL_RATE, bold: false }) : null;
9146
+ return /* @__PURE__ */ React47.createElement(Card, { tone: TONE.ok }, /* @__PURE__ */ React47.createElement(
8917
9147
  CardHeader,
8918
9148
  {
8919
9149
  glyph: "\u2039",
8920
9150
  tone: TONE.ok,
8921
9151
  title: t("cardTitles.reply"),
8922
- right: /* @__PURE__ */ React46.createElement(React46.Fragment, null, ratePill, modelPill)
9152
+ right: /* @__PURE__ */ React47.createElement(React47.Fragment, null, ratePill, modelPill)
8923
9153
  }
8924
- ), /* @__PURE__ */ React46.createElement(Markdown, { text: card.text }));
9154
+ ), /* @__PURE__ */ React47.createElement(Markdown, { text: card.text }));
8925
9155
  }
8926
9156
  const lineCells = Math.max(20, cols - 4);
8927
9157
  const allLines = card.text.length > 0 ? card.text.split("\n") : [""];
@@ -8933,25 +9163,24 @@ function StreamingCard({ card }) {
8933
9163
  const headColor = aborted ? TONE.err : TONE_ACTIVE.brand;
8934
9164
  const glyph = aborted ? "\u2039" : "\u25C8";
8935
9165
  const headLabel = aborted ? t("cardLabels.aborted") : t("cardLabels.writing");
8936
- const { tokens: liveTokens, tps: liveTps } = tokenRate(card.text, card.ts, Date.now());
8937
- const liveRatePill = !aborted && liveTokens >= MIN_TOKENS_FOR_RATE && liveTps !== null ? /* @__PURE__ */ React46.createElement(Pill, { label: `${liveTps} t/s`, ...PILL_RATE, bold: false }) : null;
8938
- const expandPill = !aborted ? /* @__PURE__ */ React46.createElement(Pill, { label: expanded ? "expanded \u2303o" : "preview \u2303o", ...PILL_RATE, bold: false }) : null;
8939
- return /* @__PURE__ */ React46.createElement(Card, { tone: headColor }, /* @__PURE__ */ React46.createElement(
9166
+ const liveRatePill = !aborted && liveRate.tokens >= MIN_TOKENS_FOR_RATE && liveRate.tps !== null ? /* @__PURE__ */ React47.createElement(Pill, { label: `${liveRate.tps} t/s`, ...PILL_RATE, bold: false }) : null;
9167
+ const expandPill = !aborted ? /* @__PURE__ */ React47.createElement(Pill, { label: expanded ? "expanded \u2303o" : "preview \u2303o", ...PILL_RATE, bold: false }) : null;
9168
+ return /* @__PURE__ */ React47.createElement(Card, { tone: headColor }, /* @__PURE__ */ React47.createElement(
8940
9169
  CardHeader,
8941
9170
  {
8942
9171
  glyph,
8943
9172
  tone: headColor,
8944
9173
  title: headLabel,
8945
- right: /* @__PURE__ */ React46.createElement(React46.Fragment, null, liveRatePill, expandPill, aborted ? null : /* @__PURE__ */ React46.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand }), modelPill)
9174
+ right: /* @__PURE__ */ React47.createElement(React47.Fragment, null, liveRatePill, expandPill, aborted ? null : /* @__PURE__ */ React47.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand }), modelPill)
8946
9175
  }
8947
- ), expanded && droppedAbove > 0 ? /* @__PURE__ */ React46.createElement(Text40, { color: FG.faint }, t(droppedAbove === 1 ? "cardLabels.earlierLine" : "cardLabels.earlierLines", {
9176
+ ), expanded && droppedAbove > 0 ? /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, t(droppedAbove === 1 ? "cardLabels.earlierLine" : "cardLabels.earlierLines", {
8948
9177
  count: droppedAbove
8949
- })) : null, visible.map((line, i) => /* @__PURE__ */ React46.createElement(Box39, { key: `${card.id}:${visualLines.length - visible.length + i}`, flexDirection: "row" }, /* @__PURE__ */ React46.createElement(Text40, { color: aborted ? FG.meta : FG.body }, clipToCells(line, lineCells)))), aborted ? /* @__PURE__ */ React46.createElement(Text40, { color: FG.faint }, t("cardLabels.truncatedByEsc")) : null);
9178
+ })) : null, visible.map((line, i) => /* @__PURE__ */ React47.createElement(Box40, { key: `${card.id}:${visualLines.length - visible.length + i}`, flexDirection: "row" }, /* @__PURE__ */ React47.createElement(Text41, { color: aborted ? FG.meta : FG.body }, clipToCells(line, lineCells)))), aborted ? /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, t("cardLabels.truncatedByEsc")) : null);
8950
9179
  }
8951
9180
 
8952
9181
  // src/cli/ui/cards/SubAgentCard.tsx
8953
- import { Box as Box40, Text as Text41 } from "ink";
8954
- import React47, { useContext as useContext6 } from "react";
9182
+ import { Box as Box41, Text as Text42 } from "ink";
9183
+ import React48, { useContext as useContext6 } from "react";
8955
9184
  function SubAgentCard({ card }) {
8956
9185
  const { fg, tone, toneActive } = useThemeTokens();
8957
9186
  const statusColor = {
@@ -8965,7 +9194,7 @@ function SubAgentCard({ card }) {
8965
9194
  const isRunning = card.status === "running";
8966
9195
  const inLive = useContext6(ActiveCardContext);
8967
9196
  const headerMeta2 = isRunning ? runningChildren > 0 ? [`${runningChildren} ${t("cardLabels.runningLabel")}`] : [t("cardLabels.workingLabel")] : [{ text: card.status, color: headColor }];
8968
- return /* @__PURE__ */ React47.createElement(Card, { tone: headColor }, /* @__PURE__ */ React47.createElement(
9197
+ return /* @__PURE__ */ React48.createElement(Card, { tone: headColor }, /* @__PURE__ */ React48.createElement(
8969
9198
  CardHeader,
8970
9199
  {
8971
9200
  glyph: headGlyph,
@@ -8975,7 +9204,7 @@ function SubAgentCard({ card }) {
8975
9204
  subtitle: card.task,
8976
9205
  meta: headerMeta2
8977
9206
  }
8978
- ), card.name ? /* @__PURE__ */ React47.createElement(Text41, { color: fg.faint }, `${t("cardLabels.agent")} \xB7 ${card.name}`) : null, card.tools && card.tools.length > 0 && /* @__PURE__ */ React47.createElement(Text41, { color: fg.faint }, `${t("cardLabels.tools")} \xB7 ${card.tools.join(", ")}`), card.children.map((child) => /* @__PURE__ */ React47.createElement(Box40, { key: child.id, flexDirection: "row", gap: 1 }, inLive ? null : /* @__PURE__ */ React47.createElement(Text41, { color: tone.violet }, "\u258E"), /* @__PURE__ */ React47.createElement(ChildRow, { card: child }))));
9207
+ ), card.name ? /* @__PURE__ */ React48.createElement(Text42, { color: fg.faint }, `${t("cardLabels.agent")} \xB7 ${card.name}`) : null, card.tools && card.tools.length > 0 && /* @__PURE__ */ React48.createElement(Text42, { color: fg.faint }, `${t("cardLabels.tools")} \xB7 ${card.tools.join(", ")}`), card.children.map((child) => /* @__PURE__ */ React48.createElement(Box41, { key: child.id, flexDirection: "row", gap: 1 }, inLive ? null : /* @__PURE__ */ React48.createElement(Text42, { color: tone.violet }, "\u258E"), /* @__PURE__ */ React48.createElement(ChildRow, { card: child }))));
8979
9208
  }
8980
9209
  function isChildDone(card) {
8981
9210
  switch (card.kind) {
@@ -8992,16 +9221,16 @@ function ChildRow({ card }) {
8992
9221
  const { fg, tone } = useThemeTokens();
8993
9222
  const v = childVisual(card, tone.ok, tone.err, fg.faint);
8994
9223
  const isDone = isChildDone(card);
8995
- return /* @__PURE__ */ React47.createElement(React47.Fragment, null, v.statusGlyph, /* @__PURE__ */ React47.createElement(Text41, { color: v.kindColor }, v.kindGlyph), /* @__PURE__ */ React47.createElement(Text41, { dimColor: isDone, color: fg.body }, v.text));
9224
+ return /* @__PURE__ */ React48.createElement(React48.Fragment, null, v.statusGlyph, /* @__PURE__ */ React48.createElement(Text42, { color: v.kindColor }, v.kindGlyph), /* @__PURE__ */ React48.createElement(Text42, { dimColor: isDone, color: fg.body }, v.text));
8996
9225
  }
8997
9226
  function runningGlyph(color) {
8998
- return /* @__PURE__ */ React47.createElement(Spinner, { kind: "circle", color });
9227
+ return /* @__PURE__ */ React48.createElement(Spinner, { kind: "circle", color });
8999
9228
  }
9000
9229
  function doneGlyph(color) {
9001
- return /* @__PURE__ */ React47.createElement(Text41, { color }, "\u2713");
9230
+ return /* @__PURE__ */ React48.createElement(Text42, { color }, "\u2713");
9002
9231
  }
9003
9232
  function failedGlyph(color) {
9004
- return /* @__PURE__ */ React47.createElement(Text41, { color }, "\u2716");
9233
+ return /* @__PURE__ */ React48.createElement(Text42, { color }, "\u2716");
9005
9234
  }
9006
9235
  function childVisual(card, doneColor, failedColor, fallbackColor) {
9007
9236
  switch (card.kind) {
@@ -9046,7 +9275,7 @@ function childVisual(card, doneColor, failedColor, fallbackColor) {
9046
9275
  };
9047
9276
  default:
9048
9277
  return {
9049
- statusGlyph: /* @__PURE__ */ React47.createElement(Text41, { color: fallbackColor }, "\xB7"),
9278
+ statusGlyph: /* @__PURE__ */ React48.createElement(Text42, { color: fallbackColor }, "\xB7"),
9050
9279
  kindGlyph: "\xB7",
9051
9280
  kindColor: fallbackColor,
9052
9281
  text: card.kind
@@ -9055,8 +9284,8 @@ function childVisual(card, doneColor, failedColor, fallbackColor) {
9055
9284
  }
9056
9285
 
9057
9286
  // src/cli/ui/cards/TaskCard.tsx
9058
- import { Box as Box41, Text as Text42 } from "ink";
9059
- import React48 from "react";
9287
+ import { Box as Box42, Text as Text43 } from "ink";
9288
+ import React49 from "react";
9060
9289
  var STEP_GLYPH = {
9061
9290
  queued: "\u25CB",
9062
9291
  running: "\u25B6",
@@ -9082,21 +9311,21 @@ function TaskCard({ card }) {
9082
9311
  failed: tone.err
9083
9312
  };
9084
9313
  const elapsed = `${(card.elapsedMs / 1e3).toFixed(1)}s`;
9085
- return /* @__PURE__ */ React48.createElement(Card, { tone: taskColor[card.status] }, /* @__PURE__ */ React48.createElement(
9314
+ return /* @__PURE__ */ React49.createElement(Card, { tone: taskColor[card.status] }, /* @__PURE__ */ React49.createElement(
9086
9315
  CardHeader,
9087
9316
  {
9088
9317
  glyph: TASK_GLYPH[card.status],
9089
9318
  tone: taskColor[card.status],
9090
- title: `step ${card.index}/${card.total}`,
9319
+ title: `${t("cardLabels.stepLabel")} ${card.index}/${card.total}`,
9091
9320
  subtitle: card.title,
9092
9321
  meta: [elapsed, card.status]
9093
9322
  }
9094
- ), card.steps.map((step) => /* @__PURE__ */ React48.createElement(Box41, { key: step.id, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React48.createElement(Text42, { color: stepColor[step.status] }, STEP_GLYPH[step.status]), /* @__PURE__ */ React48.createElement(Text42, { bold: true, color: fg.body }, (step.toolName ?? "step").padEnd(7)), /* @__PURE__ */ React48.createElement(Text42, { color: fg.sub }, step.title), step.detail ? /* @__PURE__ */ React48.createElement(Text42, { color: fg.faint }, step.detail) : null, step.elapsedMs !== void 0 ? /* @__PURE__ */ React48.createElement(Text42, { color: fg.faint }, `${(step.elapsedMs / 1e3).toFixed(2)}s`) : null)));
9323
+ ), card.steps.map((step) => /* @__PURE__ */ React49.createElement(Box42, { key: step.id, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: stepColor[step.status] }, STEP_GLYPH[step.status]), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: fg.body }, (step.toolName ?? t("cardLabels.stepLabel")).padEnd(7)), /* @__PURE__ */ React49.createElement(Text43, { color: fg.sub }, step.title), step.detail ? /* @__PURE__ */ React49.createElement(Text43, { color: fg.faint }, step.detail) : null, step.elapsedMs !== void 0 ? /* @__PURE__ */ React49.createElement(Text43, { color: fg.faint }, `${(step.elapsedMs / 1e3).toFixed(2)}s`) : null)));
9095
9324
  }
9096
9325
 
9097
9326
  // src/cli/ui/cards/TipCard.tsx
9098
- import { Box as Box42, Text as Text43 } from "ink";
9099
- import React49 from "react";
9327
+ import { Box as Box43, Text as Text44 } from "ink";
9328
+ import React50 from "react";
9100
9329
  import stringWidth2 from "string-width";
9101
9330
  var KEY_GUTTER = 4;
9102
9331
  function TipCard({ card }) {
@@ -9104,7 +9333,7 @@ function TipCard({ card }) {
9104
9333
  (max, sec) => sec.rows.reduce((m, r) => Math.max(m, stringWidth2(r.key)), max),
9105
9334
  0
9106
9335
  );
9107
- return /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "column", paddingLeft: 2, marginY: 1 }, /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", justifyContent: "space-between" }, /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: TONE.accent, bold: true }, "\u24D8"), /* @__PURE__ */ React49.createElement(Text43, { color: FG.body, bold: true }, card.topic)), card.oneTime ? /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, t("ui.tipShownOnce")) : null), card.sections.map((section, i) => /* @__PURE__ */ React49.createElement(Box42, { key: section.title ?? `section-${i}`, flexDirection: "column", marginTop: 1 }, section.title ? /* @__PURE__ */ React49.createElement(Box42, { marginBottom: 0 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, section.title)) : null, section.rows.map((row2) => /* @__PURE__ */ React49.createElement(
9336
+ return /* @__PURE__ */ React50.createElement(Box43, { flexDirection: "column", paddingLeft: 2, marginY: 1 }, /* @__PURE__ */ React50.createElement(Box43, { flexDirection: "row", justifyContent: "space-between" }, /* @__PURE__ */ React50.createElement(Box43, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React50.createElement(Text44, { color: TONE.accent, bold: true }, "\u24D8"), /* @__PURE__ */ React50.createElement(Text44, { color: FG.body, bold: true }, card.topic)), card.oneTime ? /* @__PURE__ */ React50.createElement(Text44, { color: FG.faint }, t("ui.tipShownOnce")) : null), card.sections.map((section, i) => /* @__PURE__ */ React50.createElement(Box43, { key: section.title ?? `section-${i}`, flexDirection: "column", marginTop: 1 }, section.title ? /* @__PURE__ */ React50.createElement(Box43, { marginBottom: 0 }, /* @__PURE__ */ React50.createElement(Text44, { color: FG.sub }, section.title)) : null, section.rows.map((row2) => /* @__PURE__ */ React50.createElement(
9108
9337
  TipRowRender,
9109
9338
  {
9110
9339
  key: row2.key,
@@ -9112,7 +9341,7 @@ function TipCard({ card }) {
9112
9341
  keyWidth,
9113
9342
  indent: section.title ? 2 : 0
9114
9343
  }
9115
- )))), card.footer ? /* @__PURE__ */ React49.createElement(Box42, { marginTop: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, card.footer)) : null);
9344
+ )))), card.footer ? /* @__PURE__ */ React50.createElement(Box43, { marginTop: 1 }, /* @__PURE__ */ React50.createElement(Text44, { color: FG.faint }, card.footer)) : null);
9116
9345
  }
9117
9346
  function TipRowRender({
9118
9347
  row: row2,
@@ -9121,21 +9350,21 @@ function TipRowRender({
9121
9350
  }) {
9122
9351
  const pad = " ".repeat(Math.max(0, keyWidth - stringWidth2(row2.key) + KEY_GUTTER));
9123
9352
  const lead = indent > 0 ? " ".repeat(indent) : "";
9124
- return /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row" }, lead ? /* @__PURE__ */ React49.createElement(Text43, null, lead) : null, /* @__PURE__ */ React49.createElement(Text43, { color: TONE.accent }, row2.key), /* @__PURE__ */ React49.createElement(Text43, null, pad), /* @__PURE__ */ React49.createElement(Text43, { color: FG.body }, row2.text));
9353
+ return /* @__PURE__ */ React50.createElement(Box43, { flexDirection: "row" }, lead ? /* @__PURE__ */ React50.createElement(Text44, null, lead) : null, /* @__PURE__ */ React50.createElement(Text44, { color: TONE.accent }, row2.key), /* @__PURE__ */ React50.createElement(Text44, null, pad), /* @__PURE__ */ React50.createElement(Text44, { color: FG.body }, row2.text));
9125
9354
  }
9126
9355
 
9127
9356
  // src/cli/ui/cards/ToolCard.tsx
9128
- import { Text as Text44, useStdout as useStdout13 } from "ink";
9129
- import React51 from "react";
9357
+ import { Text as Text45, useStdout as useStdout14 } from "ink";
9358
+ import React52 from "react";
9130
9359
 
9131
9360
  // src/cli/ui/state/inflight-context.tsx
9132
- import React50, { createContext as createContext4, useContext as useContext7, useSyncExternalStore } from "react";
9361
+ import React51, { createContext as createContext4, useContext as useContext7, useSyncExternalStore } from "react";
9133
9362
  var Ctx = createContext4(null);
9134
9363
  function InflightProvider({
9135
9364
  inflight,
9136
9365
  children
9137
9366
  }) {
9138
- return /* @__PURE__ */ React50.createElement(Ctx.Provider, { value: inflight }, children);
9367
+ return /* @__PURE__ */ React51.createElement(Ctx.Provider, { value: inflight }, children);
9139
9368
  }
9140
9369
  function useIsInflight(id) {
9141
9370
  const inflight = useContext7(Ctx);
@@ -9156,11 +9385,14 @@ function tailLinesFor(name) {
9156
9385
  return /(?:^|_)(read|search|list|tree|get|status|diff|fetch|grep)(_|$)/.test(lower) || lower === "job_output" ? READ_TAIL : OTHER_TAIL;
9157
9386
  }
9158
9387
  function ToolCard({ card }) {
9159
- const { stdout } = useStdout13();
9388
+ const { stdout } = useStdout14();
9160
9389
  const cols = stdout?.columns ?? 80;
9161
9390
  const lineCells = Math.max(20, cols - 4);
9162
9391
  const argsLabel = formatArgsSummary(card.args);
9163
- const subagentMarkdown = unwrapSubagentMarkdown(card);
9392
+ const subagentMarkdown = React52.useMemo(
9393
+ () => unwrapSubagentMarkdown(card.name, card.output),
9394
+ [card.name, card.output]
9395
+ );
9164
9396
  const allLines = card.output.length > 0 ? card.output.split("\n") : [];
9165
9397
  const tail = tailLinesFor(card.name);
9166
9398
  const truncated = allLines.length > tail;
@@ -9179,7 +9411,7 @@ function ToolCard({ card }) {
9179
9411
  meta.push({ text: t("cardLabels.rejected"), color: TONE.err });
9180
9412
  }
9181
9413
  for (const part of metaTrail(card)) meta.push(part);
9182
- return /* @__PURE__ */ React51.createElement(Card, { tone: headColor }, /* @__PURE__ */ React51.createElement(
9414
+ return /* @__PURE__ */ React52.createElement(Card, { tone: headColor }, /* @__PURE__ */ React52.createElement(
9183
9415
  CardHeader,
9184
9416
  {
9185
9417
  glyph: statusGlyph2(status2),
@@ -9187,12 +9419,12 @@ function ToolCard({ card }) {
9187
9419
  title: card.name,
9188
9420
  subtitle: argsLabel || void 0,
9189
9421
  meta: meta.length > 0 ? meta : void 0,
9190
- right: status2 === "running" ? /* @__PURE__ */ React51.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand, bold: true }) : void 0
9422
+ right: status2 === "running" ? /* @__PURE__ */ React52.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand, bold: true }) : void 0
9191
9423
  }
9192
- ), showBody && (subagentMarkdown !== null ? /* @__PURE__ */ React51.createElement(Markdown, { text: subagentMarkdown, width: lineCells }) : /* @__PURE__ */ React51.createElement(React51.Fragment, null, hidden > 0 ? /* @__PURE__ */ React51.createElement(Text44, { color: FG.faint }, t(hidden === 1 ? "cardLabels.earlierLine" : "cardLabels.earlierLines", {
9424
+ ), showBody && (subagentMarkdown !== null ? /* @__PURE__ */ React52.createElement(Markdown, { text: subagentMarkdown, width: lineCells }) : /* @__PURE__ */ React52.createElement(React52.Fragment, null, hidden > 0 ? /* @__PURE__ */ React52.createElement(Text45, { color: FG.faint }, t(hidden === 1 ? "cardLabels.earlierLine" : "cardLabels.earlierLines", {
9193
9425
  count: hidden
9194
- })) : null, visible.map((line, i) => /* @__PURE__ */ React51.createElement(
9195
- Text44,
9426
+ })) : null, visible.map((line, i) => /* @__PURE__ */ React52.createElement(
9427
+ Text45,
9196
9428
  {
9197
9429
  key: `${card.id}:${hidden + i}`,
9198
9430
  color: errColor,
@@ -9201,11 +9433,11 @@ function ToolCard({ card }) {
9201
9433
  clipToCells(line, lineCells) || " "
9202
9434
  )))));
9203
9435
  }
9204
- function unwrapSubagentMarkdown(card) {
9205
- if (card.name !== "spawn_subagent") return null;
9206
- if (card.output.length === 0) return null;
9436
+ function unwrapSubagentMarkdown(name, output) {
9437
+ if (name !== "spawn_subagent") return null;
9438
+ if (output.length === 0) return null;
9207
9439
  try {
9208
- const parsed = JSON.parse(card.output);
9440
+ const parsed = JSON.parse(output);
9209
9441
  if (!parsed || typeof parsed !== "object") return null;
9210
9442
  const obj = parsed;
9211
9443
  if (obj.success !== true) return null;
@@ -9293,8 +9525,8 @@ function formatBytes(n) {
9293
9525
  }
9294
9526
 
9295
9527
  // src/cli/ui/cards/UsageCard.tsx
9296
- import { Box as Box44, Text as Text45 } from "ink";
9297
- import React52 from "react";
9528
+ import { Box as Box45, Text as Text46 } from "ink";
9529
+ import React53 from "react";
9298
9530
  var BAR_CELLS2 = 30;
9299
9531
  function compactNum(n) {
9300
9532
  if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
@@ -9304,10 +9536,10 @@ function compactNum(n) {
9304
9536
  function bar(ratio, color) {
9305
9537
  const filled = Math.max(0, Math.min(BAR_CELLS2, Math.round(ratio * BAR_CELLS2)));
9306
9538
  const empty = BAR_CELLS2 - filled;
9307
- return /* @__PURE__ */ React52.createElement(React52.Fragment, null, /* @__PURE__ */ React52.createElement(Text45, { color }, "\u2588".repeat(filled)), /* @__PURE__ */ React52.createElement(Text45, { color: FG.faint }, "\u2591".repeat(empty)));
9539
+ return /* @__PURE__ */ React53.createElement(React53.Fragment, null, /* @__PURE__ */ React53.createElement(Text46, { color }, "\u2588".repeat(filled)), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, "\u2591".repeat(empty)));
9308
9540
  }
9309
9541
  function UsageCard({ card }) {
9310
- if (card.compact) return /* @__PURE__ */ React52.createElement(CompactUsageRow, { card });
9542
+ if (card.compact) return /* @__PURE__ */ React53.createElement(CompactUsageRow, { card });
9311
9543
  const cap = Math.max(1, card.tokens.promptCap);
9312
9544
  const promptRatio = card.tokens.prompt / cap;
9313
9545
  const reasonRatio = card.tokens.reason / cap;
@@ -9317,15 +9549,15 @@ function UsageCard({ card }) {
9317
9549
  formatCost(card.cost, card.balanceCurrency)
9318
9550
  ];
9319
9551
  if (card.elapsedMs !== void 0) headerMeta2.push(`${(card.elapsedMs / 1e3).toFixed(1)}s`);
9320
- return /* @__PURE__ */ React52.createElement(Card, { tone: FG.meta }, /* @__PURE__ */ React52.createElement(CardHeader, { glyph: "\u03A3", tone: FG.meta, title: t("cardTitles.usage"), meta: headerMeta2 }), /* @__PURE__ */ React52.createElement(Box44, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React52.createElement(Text45, { color: FG.sub }, t("cardLabels.prompt")), bar(promptRatio, TONE.brand), /* @__PURE__ */ React52.createElement(Text45, { bold: true, color: FG.body }, card.tokens.prompt.toLocaleString()), /* @__PURE__ */ React52.createElement(Text45, { color: FG.faint }, `/ 1M \xB7 ${(promptRatio * 100).toFixed(1)}%`)), /* @__PURE__ */ React52.createElement(Box44, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React52.createElement(Text45, { color: FG.sub }, t("cardLabels.reason")), bar(reasonRatio, TONE.accent), /* @__PURE__ */ React52.createElement(Text45, { bold: true, color: FG.body }, card.tokens.reason.toLocaleString())), /* @__PURE__ */ React52.createElement(Box44, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React52.createElement(Text45, { color: FG.sub }, t("cardLabels.output")), bar(outputRatio, TONE.brand), /* @__PURE__ */ React52.createElement(Text45, { bold: true, color: FG.body }, card.tokens.output.toLocaleString())), /* @__PURE__ */ React52.createElement(Box44, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React52.createElement(Text45, { color: FG.sub }, t("cardLabels.cache"), " "), bar(card.cacheHit, TONE.ok), /* @__PURE__ */ React52.createElement(Text45, { bold: true, color: TONE.ok }, `${(card.cacheHit * 100).toFixed(1)}%`)), /* @__PURE__ */ React52.createElement(Box44, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React52.createElement(Text45, { color: FG.faint }, t("cardLabels.session")), /* @__PURE__ */ React52.createElement(Text45, { bold: true, color: FG.body }, `\u26C1 ${formatCost(card.sessionCost, card.balanceCurrency, 3)}`), card.balance !== void 0 ? /* @__PURE__ */ React52.createElement(React52.Fragment, null, /* @__PURE__ */ React52.createElement(Text45, { color: FG.faint }, `\xB7 ${t("cardLabels.balance")}`), /* @__PURE__ */ React52.createElement(Text45, { bold: true, color: TONE.brand }, formatBalance(card.balance, card.balanceCurrency))) : null));
9552
+ return /* @__PURE__ */ React53.createElement(Card, { tone: FG.meta }, /* @__PURE__ */ React53.createElement(CardHeader, { glyph: "\u03A3", tone: FG.meta, title: t("cardTitles.usage"), meta: headerMeta2 }), /* @__PURE__ */ React53.createElement(Box45, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React53.createElement(Text46, { color: FG.sub }, t("cardLabels.prompt")), bar(promptRatio, TONE.brand), /* @__PURE__ */ React53.createElement(Text46, { bold: true, color: FG.body }, card.tokens.prompt.toLocaleString()), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, `/ 1M \xB7 ${(promptRatio * 100).toFixed(1)}%`)), /* @__PURE__ */ React53.createElement(Box45, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React53.createElement(Text46, { color: FG.sub }, t("cardLabels.reason")), bar(reasonRatio, TONE.accent), /* @__PURE__ */ React53.createElement(Text46, { bold: true, color: FG.body }, card.tokens.reason.toLocaleString())), /* @__PURE__ */ React53.createElement(Box45, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React53.createElement(Text46, { color: FG.sub }, t("cardLabels.output")), bar(outputRatio, TONE.brand), /* @__PURE__ */ React53.createElement(Text46, { bold: true, color: FG.body }, card.tokens.output.toLocaleString())), /* @__PURE__ */ React53.createElement(Box45, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React53.createElement(Text46, { color: FG.sub }, t("cardLabels.cache"), " "), bar(card.cacheHit, TONE.ok), /* @__PURE__ */ React53.createElement(Text46, { bold: true, color: TONE.ok }, `${(card.cacheHit * 100).toFixed(1)}%`)), /* @__PURE__ */ React53.createElement(Box45, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, t("cardLabels.session")), /* @__PURE__ */ React53.createElement(Text46, { bold: true, color: FG.body }, `\u26C1 ${formatCost(card.sessionCost, card.balanceCurrency, 3)}`), card.balance !== void 0 ? /* @__PURE__ */ React53.createElement(React53.Fragment, null, /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, `\xB7 ${t("cardLabels.balance")}`), /* @__PURE__ */ React53.createElement(Text46, { bold: true, color: TONE.brand }, formatBalance(card.balance, card.balanceCurrency))) : null));
9321
9553
  }
9322
9554
  function CompactUsageRow({ card }) {
9323
9555
  const elapsed = card.elapsedMs !== void 0 ? ` \xB7 ${(card.elapsedMs / 1e3).toFixed(1)}s` : "";
9324
- return /* @__PURE__ */ React52.createElement(Box44, { flexDirection: "row", gap: 1, marginTop: 1 }, /* @__PURE__ */ React52.createElement(Text45, { color: FG.meta }, "\u03A3"), /* @__PURE__ */ React52.createElement(Text45, { color: FG.faint }, `${t("cardLabels.turn")} ${card.turn}`), /* @__PURE__ */ React52.createElement(Text45, { color: FG.meta }, `\xB7 ${compactNum(card.tokens.prompt)} ${t("cardLabels.prompt")} \xB7 ${compactNum(card.tokens.output)} ${t("cardLabels.output")}`), /* @__PURE__ */ React52.createElement(Text45, { color: FG.faint }, `\xB7 ${t("cardLabels.cache")}`), /* @__PURE__ */ React52.createElement(Text45, { color: TONE.ok }, `${(card.cacheHit * 100).toFixed(0)}%`), /* @__PURE__ */ React52.createElement(Text45, { color: FG.faint }, `\xB7 ${formatCost(card.cost, card.balanceCurrency)}${elapsed}`), card.balance !== void 0 ? /* @__PURE__ */ React52.createElement(Text45, { color: TONE.brand }, `\xB7 ${formatBalance(card.balance, card.balanceCurrency)}`) : null);
9556
+ return /* @__PURE__ */ React53.createElement(Box45, { flexDirection: "row", gap: 1, marginTop: 1 }, /* @__PURE__ */ React53.createElement(Text46, { color: FG.meta }, "\u03A3"), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, `${t("cardLabels.turn")} ${card.turn}`), /* @__PURE__ */ React53.createElement(Text46, { color: FG.meta }, `\xB7 ${compactNum(card.tokens.prompt)} ${t("cardLabels.prompt")} \xB7 ${compactNum(card.tokens.output)} ${t("cardLabels.output")}`), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, `\xB7 ${t("cardLabels.cache")}`), /* @__PURE__ */ React53.createElement(Text46, { color: TONE.ok }, `${(card.cacheHit * 100).toFixed(0)}%`), /* @__PURE__ */ React53.createElement(Text46, { color: FG.faint }, `\xB7 ${formatCost(card.cost, card.balanceCurrency)}${elapsed}`), card.balance !== void 0 ? /* @__PURE__ */ React53.createElement(Text46, { color: TONE.brand }, `\xB7 ${formatBalance(card.balance, card.balanceCurrency)}`) : null);
9325
9557
  }
9326
9558
 
9327
9559
  // src/cli/ui/cards/UserCard.tsx
9328
- import React53 from "react";
9560
+ import React54 from "react";
9329
9561
 
9330
9562
  // src/cli/ui/cards/time.ts
9331
9563
  function formatRelativeTime(ts, now = Date.now()) {
@@ -9342,24 +9574,24 @@ function formatRelativeTime(ts, now = Date.now()) {
9342
9574
 
9343
9575
  // src/cli/ui/cards/UserCard.tsx
9344
9576
  function UserCard({ card }) {
9345
- return /* @__PURE__ */ React53.createElement(Card, { tone: TONE.accent }, /* @__PURE__ */ React53.createElement(
9577
+ return /* @__PURE__ */ React54.createElement(Card, { tone: TONE.accent }, /* @__PURE__ */ React54.createElement(
9346
9578
  CardHeader,
9347
9579
  {
9348
9580
  glyph: "\u203A",
9349
9581
  tone: TONE.accent,
9350
- title: "you",
9582
+ title: t("cardTitles.you"),
9351
9583
  titleColor: FG.sub,
9352
9584
  meta: [formatRelativeTime(card.ts)]
9353
9585
  }
9354
- ), /* @__PURE__ */ React53.createElement(Markdown, { text: card.text }));
9586
+ ), /* @__PURE__ */ React54.createElement(Markdown, { text: card.text }));
9355
9587
  }
9356
9588
 
9357
9589
  // src/cli/ui/cards/WarnCard.tsx
9358
- import { Text as Text46 } from "ink";
9359
- import React54 from "react";
9590
+ import { Text as Text47 } from "ink";
9591
+ import React55 from "react";
9360
9592
  function WarnCard({ card }) {
9361
9593
  const messageLines = card.message.length > 0 ? card.message.split("\n") : [];
9362
- return /* @__PURE__ */ React54.createElement(Card, { tone: TONE.warn }, /* @__PURE__ */ React54.createElement(
9594
+ return /* @__PURE__ */ React55.createElement(Card, { tone: TONE.warn }, /* @__PURE__ */ React55.createElement(
9363
9595
  CardHeader,
9364
9596
  {
9365
9597
  glyph: "\u26A0",
@@ -9367,61 +9599,61 @@ function WarnCard({ card }) {
9367
9599
  title: card.title,
9368
9600
  meta: card.detail ? [card.detail] : void 0
9369
9601
  }
9370
- ), messageLines.map((line, i) => /* @__PURE__ */ React54.createElement(Text46, { key: `${card.id}:${i}`, color: FG.body }, line || " ")));
9602
+ ), messageLines.map((line, i) => /* @__PURE__ */ React55.createElement(Text47, { key: `${card.id}:${i}`, color: FG.body }, line || " ")));
9371
9603
  }
9372
9604
 
9373
9605
  // src/cli/ui/cards/CardRenderer.tsx
9374
- var CardRenderer = React55.memo(function CardRenderer2({
9606
+ var CardRenderer = React56.memo(function CardRenderer2({
9375
9607
  card
9376
9608
  }) {
9377
- return /* @__PURE__ */ React55.createElement(Box45, { flexDirection: "column" }, renderCard(card));
9609
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "column" }, renderCard(card));
9378
9610
  });
9379
9611
  function renderCard(card) {
9380
9612
  switch (card.kind) {
9381
9613
  case "user":
9382
- return /* @__PURE__ */ React55.createElement(UserCard, { card });
9614
+ return /* @__PURE__ */ React56.createElement(UserCard, { card });
9383
9615
  case "reasoning":
9384
- return /* @__PURE__ */ React55.createElement(ReasoningCard, { card, expanded: true });
9616
+ return /* @__PURE__ */ React56.createElement(ReasoningCard, { card, expanded: true });
9385
9617
  case "streaming":
9386
- return /* @__PURE__ */ React55.createElement(StreamingCard, { card });
9618
+ return /* @__PURE__ */ React56.createElement(StreamingCard, { card });
9387
9619
  case "tool":
9388
- return /* @__PURE__ */ React55.createElement(ToolCard, { card });
9620
+ return /* @__PURE__ */ React56.createElement(ToolCard, { card });
9389
9621
  case "task":
9390
- return /* @__PURE__ */ React55.createElement(TaskCard, { card });
9622
+ return /* @__PURE__ */ React56.createElement(TaskCard, { card });
9391
9623
  case "plan":
9392
- return /* @__PURE__ */ React55.createElement(PlanCard, { card });
9624
+ return /* @__PURE__ */ React56.createElement(PlanCard, { card });
9393
9625
  case "diff":
9394
- return /* @__PURE__ */ React55.createElement(DiffCard, { card });
9626
+ return /* @__PURE__ */ React56.createElement(DiffCard, { card });
9395
9627
  case "error":
9396
- return /* @__PURE__ */ React55.createElement(ErrorCard, { card });
9628
+ return /* @__PURE__ */ React56.createElement(ErrorCard, { card });
9397
9629
  case "warn":
9398
- return /* @__PURE__ */ React55.createElement(WarnCard, { card });
9630
+ return /* @__PURE__ */ React56.createElement(WarnCard, { card });
9399
9631
  case "usage":
9400
- return /* @__PURE__ */ React55.createElement(UsageCard, { card });
9632
+ return /* @__PURE__ */ React56.createElement(UsageCard, { card });
9401
9633
  case "memory":
9402
- return /* @__PURE__ */ React55.createElement(MemoryCard, { card });
9634
+ return /* @__PURE__ */ React56.createElement(MemoryCard, { card });
9403
9635
  case "subagent":
9404
- return /* @__PURE__ */ React55.createElement(SubAgentCard, { card });
9636
+ return /* @__PURE__ */ React56.createElement(SubAgentCard, { card });
9405
9637
  case "search":
9406
- return /* @__PURE__ */ React55.createElement(SearchCard, { card });
9638
+ return /* @__PURE__ */ React56.createElement(SearchCard, { card });
9407
9639
  case "live":
9408
- return /* @__PURE__ */ React55.createElement(LiveCard, { card });
9640
+ return /* @__PURE__ */ React56.createElement(LiveCard, { card });
9409
9641
  case "tip":
9410
- return /* @__PURE__ */ React55.createElement(TipCard, { card });
9642
+ return /* @__PURE__ */ React56.createElement(TipCard, { card });
9411
9643
  case "ctx":
9412
- return /* @__PURE__ */ React55.createElement(CtxCard, { card });
9644
+ return /* @__PURE__ */ React56.createElement(CtxCard, { card });
9413
9645
  case "doctor":
9414
- return /* @__PURE__ */ React55.createElement(DoctorCard, { card });
9646
+ return /* @__PURE__ */ React56.createElement(DoctorCard, { card });
9415
9647
  default:
9416
- return /* @__PURE__ */ React55.createElement(FallbackCard, { card });
9648
+ return /* @__PURE__ */ React56.createElement(FallbackCard, { card });
9417
9649
  }
9418
9650
  }
9419
9651
  function FallbackCard({ card }) {
9420
- return /* @__PURE__ */ React55.createElement(Box45, { flexDirection: "row" }, /* @__PURE__ */ React55.createElement(Text47, { color: FG.faint }, ` \xB7 ${card.kind} card \xB7 not yet migrated`));
9652
+ return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text48, { color: FG.faint }, ` \xB7 ${card.kind} card \xB7 not yet migrated`));
9421
9653
  }
9422
9654
 
9423
9655
  // src/cli/ui/state/chat-scroll-provider.tsx
9424
- import React56 from "react";
9656
+ import React57 from "react";
9425
9657
 
9426
9658
  // src/cli/ui/state/chat-scroll-store.ts
9427
9659
  var SCROLL_ARROW_ROWS = 3;
@@ -9520,23 +9752,23 @@ function createChatScrollStore() {
9520
9752
  }
9521
9753
 
9522
9754
  // src/cli/ui/state/chat-scroll-provider.tsx
9523
- var Ctx2 = React56.createContext(null);
9755
+ var Ctx2 = React57.createContext(null);
9524
9756
  function ChatScrollProvider({
9525
9757
  children
9526
9758
  }) {
9527
- const store = React56.useMemo(() => createChatScrollStore(), []);
9528
- return /* @__PURE__ */ React56.createElement(Ctx2.Provider, { value: store }, children);
9759
+ const store = React57.useMemo(() => createChatScrollStore(), []);
9760
+ return /* @__PURE__ */ React57.createElement(Ctx2.Provider, { value: store }, children);
9529
9761
  }
9530
9762
  function useStore() {
9531
- const s = React56.useContext(Ctx2);
9763
+ const s = React57.useContext(Ctx2);
9532
9764
  if (!s) throw new Error("useChatScroll* must be used inside ChatScrollProvider");
9533
9765
  return s;
9534
9766
  }
9535
9767
  function useChatScrollState(selector) {
9536
9768
  const store = useStore();
9537
- const subscribe = React56.useCallback((cb) => store.subscribe(cb), [store]);
9538
- const getSnapshot = React56.useCallback(() => selector(store.getState()), [store, selector]);
9539
- return React56.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
9769
+ const subscribe = React57.useCallback((cb) => store.subscribe(cb), [store]);
9770
+ const getSnapshot = React57.useCallback(() => selector(store.getState()), [store, selector]);
9771
+ return React57.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
9540
9772
  }
9541
9773
  function useChatScrollActions() {
9542
9774
  return useStore();
@@ -9568,7 +9800,7 @@ function CardStream({
9568
9800
  if (suppressLive && cards.length > 0 && !isFullySettled(cards[cards.length - 1])) {
9569
9801
  visible = cards.slice(0, -1);
9570
9802
  }
9571
- const items = useMemo8(() => {
9803
+ const items = useMemo9(() => {
9572
9804
  const winStart = Math.max(0, scrollRows - VISIBLE_BUFFER_ROWS);
9573
9805
  const winEnd = scrollRows + outer.height + VISIBLE_BUFFER_ROWS;
9574
9806
  const out = [];
@@ -9595,8 +9827,8 @@ function CardStream({
9595
9827
  }
9596
9828
  return out;
9597
9829
  }, [visible, cardHeights, scrollRows, outer.height]);
9598
- return /* @__PURE__ */ React57.createElement(React57.Fragment, null, /* @__PURE__ */ React57.createElement(Box46, { height: 1, flexShrink: 0 }, scrollRows > 0 ? /* @__PURE__ */ React57.createElement(ScrollIndicator, { scrollRows, maxScroll }) : null), /* @__PURE__ */ React57.createElement(Box46, { ref: outerRef, flexDirection: "column", flexGrow: 1, overflow: "hidden" }, /* @__PURE__ */ React57.createElement(Box46, { ref: innerRef, flexDirection: "column", marginTop: -scrollRows, flexShrink: 0 }, items.map(
9599
- (item) => item.kind === "spacer" ? /* @__PURE__ */ React57.createElement(Box46, { key: item.key, height: item.rows, flexShrink: 0 }) : /* @__PURE__ */ React57.createElement(MeasuredCard, { key: item.card.id, card: item.card, report: setCardHeight })
9830
+ return /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(Box47, { height: 1, flexShrink: 0 }, scrollRows > 0 ? /* @__PURE__ */ React58.createElement(ScrollIndicator, { scrollRows, maxScroll }) : null), /* @__PURE__ */ React58.createElement(Box47, { ref: outerRef, flexDirection: "column", flexGrow: 1, overflow: "hidden" }, /* @__PURE__ */ React58.createElement(Box47, { ref: innerRef, flexDirection: "column", marginTop: -scrollRows, flexShrink: 0 }, items.map(
9831
+ (item) => item.kind === "spacer" ? /* @__PURE__ */ React58.createElement(Box47, { key: item.key, height: item.rows, flexShrink: 0 }) : /* @__PURE__ */ React58.createElement(MeasuredCard, { key: item.card.id, card: item.card, report: setCardHeight })
9600
9832
  ))));
9601
9833
  }
9602
9834
  function MeasuredCard({
@@ -9608,15 +9840,15 @@ function MeasuredCard({
9608
9840
  useEffect12(() => {
9609
9841
  if (m.height > 0) report(card.id, m.height);
9610
9842
  }, [card.id, m.height, report]);
9611
- return /* @__PURE__ */ React57.createElement(Box46, { ref, flexDirection: "column", flexShrink: 0 }, /* @__PURE__ */ React57.createElement(CardRenderer, { card }));
9843
+ return /* @__PURE__ */ React58.createElement(Box47, { ref, flexDirection: "column", flexShrink: 0 }, /* @__PURE__ */ React58.createElement(CardRenderer, { card }));
9612
9844
  }
9613
9845
  function ScrollIndicator({
9614
9846
  scrollRows,
9615
9847
  maxScroll
9616
9848
  }) {
9617
9849
  const version = useChatScrollState((s) => s.scrollVersion);
9618
- const [hot, setHot] = React57.useState(false);
9619
- React57.useEffect(() => {
9850
+ const [hot, setHot] = React58.useState(false);
9851
+ React58.useEffect(() => {
9620
9852
  if (version === 0) return;
9621
9853
  setHot(true);
9622
9854
  const id = setTimeout(() => setHot(false), 220);
@@ -9624,7 +9856,7 @@ function ScrollIndicator({
9624
9856
  }, [version]);
9625
9857
  const remaining = Math.max(0, maxScroll - scrollRows);
9626
9858
  const text = ` \u2191 ${scrollRows} / ${maxScroll} rows above${remaining > 0 ? ` \u2014 ${remaining} more` : ""} \xB7 PgUp / wheel / \u2191`;
9627
- return /* @__PURE__ */ React57.createElement(Text48, { color: hot ? TONE.accent : FG.faint }, text);
9859
+ return /* @__PURE__ */ React58.createElement(Text49, { color: hot ? TONE.accent : FG.faint }, text);
9628
9860
  }
9629
9861
  function isFullySettled(card) {
9630
9862
  switch (card.kind) {
@@ -9644,13 +9876,13 @@ function isFullySettled(card) {
9644
9876
  }
9645
9877
 
9646
9878
  // src/cli/ui/layout/LiveRows.tsx
9647
- import { Box as Box47, Text as Text49 } from "ink";
9648
- import React58 from "react";
9879
+ import { Box as Box48, Text as Text50 } from "ink";
9880
+ import React59 from "react";
9649
9881
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
9650
9882
  function ThinkingRow({ text }) {
9651
9883
  const elapsed = useElapsedSeconds();
9652
9884
  const { fg, tone } = useThemeTokens();
9653
- return /* @__PURE__ */ React58.createElement(Box47, { marginY: 1, paddingX: 1, gap: 1 }, /* @__PURE__ */ React58.createElement(Spinner, { kind: "circle", color: TONE.accent }), /* @__PURE__ */ React58.createElement(Text49, { italic: true, color: FG.sub }, text), /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, `${elapsed}s`));
9885
+ return /* @__PURE__ */ React59.createElement(Box48, { marginY: 1, paddingX: 1, gap: 1 }, /* @__PURE__ */ React59.createElement(Spinner, { kind: "circle", color: TONE.accent }), /* @__PURE__ */ React59.createElement(Text50, { italic: true, color: FG.sub }, text), /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, `${elapsed}s`));
9654
9886
  }
9655
9887
  function ModeStatusBar({
9656
9888
  editMode,
@@ -9662,24 +9894,24 @@ function ModeStatusBar({
9662
9894
  }) {
9663
9895
  useSlowTick();
9664
9896
  const running = jobs2?.runningCount() ?? 0;
9665
- const jobsTag = running > 0 ? /* @__PURE__ */ React58.createElement(Text49, { color: TONE.warn, bold: true }, ` \xB7 \u23F5 ${running} job${running === 1 ? "" : "s"}`) : null;
9897
+ const jobsTag = running > 0 ? /* @__PURE__ */ React59.createElement(Text50, { color: TONE.warn, bold: true }, ` \xB7 \u23F5 ${running} job${running === 1 ? "" : "s"}`) : null;
9666
9898
  if (planMode) {
9667
- return /* @__PURE__ */ React58.createElement(ModeBarFrame, null, /* @__PURE__ */ React58.createElement(ModePill, { label: t("editMode.plan"), color: TONE.err, flash }), /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, t("editMode.writesGated")), jobsTag);
9899
+ return /* @__PURE__ */ React59.createElement(ModeBarFrame, null, /* @__PURE__ */ React59.createElement(ModePill, { label: t("editMode.plan"), color: TONE.err, flash }), /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, t("editMode.writesGated")), jobsTag);
9668
9900
  }
9669
9901
  const label = editMode === "yolo" ? t("editMode.yolo") : editMode === "auto" ? t("editMode.auto") : t("editMode.review");
9670
9902
  const pillColor = editMode === "yolo" ? TONE.err : editMode === "auto" ? TONE.accent : TONE.brand;
9671
9903
  const mid = editMode === "yolo" ? t("editMode.editsShellAuto") : editMode === "auto" ? t("editMode.editsLandNow") : pendingCount > 0 ? t("editMode.queuedApplyDiscard", { count: pendingCount }) : t("editMode.editsQueued");
9672
- return /* @__PURE__ */ React58.createElement(ModeBarFrame, null, /* @__PURE__ */ React58.createElement(ModePill, { label, color: pillColor, flash }), /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, t("editMode.shiftTabFlip", { mid })), jobsTag);
9904
+ return /* @__PURE__ */ React59.createElement(ModeBarFrame, null, /* @__PURE__ */ React59.createElement(ModePill, { label, color: pillColor, flash }), /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, t("editMode.shiftTabFlip", { mid })), jobsTag);
9673
9905
  }
9674
9906
  function ModeBarFrame({ children }) {
9675
- return /* @__PURE__ */ React58.createElement(Box47, { paddingX: 1 }, children);
9907
+ return /* @__PURE__ */ React59.createElement(Box48, { paddingX: 1 }, children);
9676
9908
  }
9677
9909
  function ModePill({
9678
9910
  label,
9679
9911
  color,
9680
9912
  flash
9681
9913
  }) {
9682
- return /* @__PURE__ */ React58.createElement(Text49, { color, bold: true, inverse: flash }, `[${label}]`);
9914
+ return /* @__PURE__ */ React59.createElement(Text50, { color, bold: true, inverse: flash }, `[${label}]`);
9683
9915
  }
9684
9916
  function UndoBanner({
9685
9917
  banner
@@ -9694,7 +9926,7 @@ function UndoBanner({
9694
9926
  const urgent = !paused && remainingSec <= 1;
9695
9927
  const pct = remainingMs / totalMs * 100;
9696
9928
  const tone = paused ? TONE.warn : urgent ? TONE.err : TONE.accent;
9697
- return /* @__PURE__ */ React58.createElement(Box47, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React58.createElement(Text49, { backgroundColor: TONE.accent, color: "black", bold: true }, ` \u2713 AUTO-APPLIED ${ok}/${total} `), /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, " press "), /* @__PURE__ */ React58.createElement(Text49, { backgroundColor: TONE.brand, color: "black", bold: true }, " u "), /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, paused ? " to undo \xB7 " : " to undo \xB7 "), /* @__PURE__ */ React58.createElement(Text49, { backgroundColor: paused ? TONE.warn : FG.faint, color: "black", bold: true }, " space "), /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, paused ? " to resume " : " to pause "), /* @__PURE__ */ React58.createElement(CharBar, { pct, width: 20, color: tone, showLabel: false }), /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, " "), /* @__PURE__ */ React58.createElement(Text49, { color: tone, bold: urgent || paused }, paused ? `${remainingSec}s \xB7 paused` : `${remainingSec}s`));
9929
+ return /* @__PURE__ */ React59.createElement(Box48, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React59.createElement(Text50, { backgroundColor: TONE.accent, color: "black", bold: true }, ` \u2713 AUTO-APPLIED ${ok}/${total} `), /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, " press "), /* @__PURE__ */ React59.createElement(Text50, { backgroundColor: TONE.brand, color: "black", bold: true }, " u "), /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, paused ? " to undo \xB7 " : " to undo \xB7 "), /* @__PURE__ */ React59.createElement(Text50, { backgroundColor: paused ? TONE.warn : FG.faint, color: "black", bold: true }, " space "), /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, paused ? " to resume " : " to pause "), /* @__PURE__ */ React59.createElement(CharBar, { pct, width: 20, color: tone, showLabel: false }), /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, " "), /* @__PURE__ */ React59.createElement(Text50, { color: tone, bold: urgent || paused }, paused ? `${remainingSec}s \xB7 paused` : `${remainingSec}s`));
9698
9930
  }
9699
9931
  function subagentPhaseLabel(phase, iter, elapsedMs) {
9700
9932
  if (phase === "summarising") return "summarising findings\u2026";
@@ -9709,7 +9941,7 @@ function SubagentRow({ activity }) {
9709
9941
  const last = activity.lastInner;
9710
9942
  const subtitle = activity.skillName ?? truncate2(activity.task, 48);
9711
9943
  const modelBadge = activity.model ? modelBadgeFor(activity.model) : null;
9712
- return /* @__PURE__ */ React58.createElement(Card, { tone: CARD.subagent.color }, /* @__PURE__ */ React58.createElement(
9944
+ return /* @__PURE__ */ React59.createElement(Card, { tone: CARD.subagent.color }, /* @__PURE__ */ React59.createElement(
9713
9945
  CardHeader,
9714
9946
  {
9715
9947
  glyph: "\u232C",
@@ -9719,9 +9951,9 @@ function SubagentRow({ activity }) {
9719
9951
  titleBg: PILL_SECTION.plan.bg,
9720
9952
  subtitle,
9721
9953
  meta: [`iter ${activity.iter}`, `${seconds}s`],
9722
- right: /* @__PURE__ */ React58.createElement(React58.Fragment, null, modelBadge ? /* @__PURE__ */ React58.createElement(Pill, { label: modelBadge.label, ...PILL_MODEL[modelBadge.kind], bold: false }) : null, /* @__PURE__ */ React58.createElement(Spinner, { kind: "braille", color: CARD.subagent.color }))
9954
+ right: /* @__PURE__ */ React59.createElement(React59.Fragment, null, modelBadge ? /* @__PURE__ */ React59.createElement(Pill, { label: modelBadge.label, ...PILL_MODEL[modelBadge.kind], bold: false }) : null, /* @__PURE__ */ React59.createElement(Spinner, { kind: "braille", color: CARD.subagent.color }))
9723
9955
  }
9724
- ), /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, "task ", /* @__PURE__ */ React58.createElement(Text49, { color: FG.sub }, activity.task)), /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, "last ", last ? /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(Text49, { color: last.color }, `${last.glyph} `), /* @__PURE__ */ React58.createElement(Text49, { color: FG.body }, last.label), last.meta ? /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, ` ${last.meta}`) : null) : /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, t("editMode.queuedDots"))), /* @__PURE__ */ React58.createElement(Text49, { color: TONE.brand }, "\u25B6 ", phase));
9956
+ ), /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, "task ", /* @__PURE__ */ React59.createElement(Text50, { color: FG.sub }, activity.task)), /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, "last ", last ? /* @__PURE__ */ React59.createElement(React59.Fragment, null, /* @__PURE__ */ React59.createElement(Text50, { color: last.color }, `${last.glyph} `), /* @__PURE__ */ React59.createElement(Text50, { color: FG.body }, last.label), last.meta ? /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, ` ${last.meta}`) : null) : /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, t("editMode.queuedDots"))), /* @__PURE__ */ React59.createElement(Text50, { color: TONE.brand }, "\u25B6 ", phase));
9725
9957
  }
9726
9958
  function SubagentLiveStack({
9727
9959
  activities,
@@ -9729,13 +9961,13 @@ function SubagentLiveStack({
9729
9961
  }) {
9730
9962
  const tick = useTick();
9731
9963
  if (activities.length === 0) return null;
9732
- if (activities.length === 1) return /* @__PURE__ */ React58.createElement(SubagentRow, { activity: activities[0] });
9964
+ if (activities.length === 1) return /* @__PURE__ */ React59.createElement(SubagentRow, { activity: activities[0] });
9733
9965
  const visible = activities.slice(0, max);
9734
9966
  const overflow = activities.length - visible.length;
9735
9967
  const summarising = activities.filter((a) => a.phase === "summarising").length;
9736
9968
  const metaParts = [`${activities.length} running`];
9737
9969
  if (summarising > 0) metaParts.push(`${summarising} summarising`);
9738
- return /* @__PURE__ */ React58.createElement(Card, { tone: CARD.subagent.color }, /* @__PURE__ */ React58.createElement(
9970
+ return /* @__PURE__ */ React59.createElement(Card, { tone: CARD.subagent.color }, /* @__PURE__ */ React59.createElement(
9739
9971
  CardHeader,
9740
9972
  {
9741
9973
  glyph: "\u232C",
@@ -9744,9 +9976,9 @@ function SubagentLiveStack({
9744
9976
  titleColor: PILL_SECTION.plan.fg,
9745
9977
  titleBg: PILL_SECTION.plan.bg,
9746
9978
  subtitle: metaParts.join(" \xB7 "),
9747
- right: /* @__PURE__ */ React58.createElement(Spinner, { kind: "braille", color: CARD.subagent.color })
9979
+ right: /* @__PURE__ */ React59.createElement(Spinner, { kind: "braille", color: CARD.subagent.color })
9748
9980
  }
9749
- ), visible.map((a, i) => /* @__PURE__ */ React58.createElement(CompactSubagentLine, { key: a.runId, activity: a, tick, index: i })), overflow > 0 ? /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, ` +${overflow} more running\u2026`) : null);
9981
+ ), visible.map((a, i) => /* @__PURE__ */ React59.createElement(CompactSubagentLine, { key: a.runId, activity: a, tick, index: i })), overflow > 0 ? /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, ` +${overflow} more running\u2026`) : null);
9750
9982
  }
9751
9983
  function CompactSubagentLine({
9752
9984
  activity,
@@ -9761,7 +9993,7 @@ function CompactSubagentLine({
9761
9993
  const title = activity.skillName ?? truncate2(activity.task, 28);
9762
9994
  const titlePadded = title.padEnd(28);
9763
9995
  const last = activity.lastInner;
9764
- return /* @__PURE__ */ React58.createElement(Box47, { flexDirection: "row" }, /* @__PURE__ */ React58.createElement(Text49, { color: glyphColor, bold: true }, ` ${glyph} `), /* @__PURE__ */ React58.createElement(Text49, { color: FG.body }, titlePadded), /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, ` iter ${String(activity.iter).padStart(2)} \xB7 ${seconds}s \xB7 `), last ? /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(Text49, { color: last.color }, `${last.glyph} `), /* @__PURE__ */ React58.createElement(Text49, { color: FG.body }, truncate2(last.label, 18)), last.meta ? /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, ` ${last.meta}`) : null) : /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, t("editMode.queuedDots")));
9996
+ return /* @__PURE__ */ React59.createElement(Box48, { flexDirection: "row" }, /* @__PURE__ */ React59.createElement(Text50, { color: glyphColor, bold: true }, ` ${glyph} `), /* @__PURE__ */ React59.createElement(Text50, { color: FG.body }, titlePadded), /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, ` iter ${String(activity.iter).padStart(2)} \xB7 ${seconds}s \xB7 `), last ? /* @__PURE__ */ React59.createElement(React59.Fragment, null, /* @__PURE__ */ React59.createElement(Text50, { color: last.color }, `${last.glyph} `), /* @__PURE__ */ React59.createElement(Text50, { color: FG.body }, truncate2(last.label, 18)), last.meta ? /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, ` ${last.meta}`) : null) : /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, t("editMode.queuedDots")));
9765
9997
  }
9766
9998
  function truncate2(text, max) {
9767
9999
  return text.length > max ? `${text.slice(0, max)}\u2026` : text;
@@ -9773,7 +10005,7 @@ function OngoingToolRow({
9773
10005
  const tick = useTick();
9774
10006
  const elapsed = useElapsedSeconds();
9775
10007
  const summary = summarizeToolArgs(tool.name, tool.args);
9776
- return /* @__PURE__ */ React58.createElement(Box47, { marginY: 1, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React58.createElement(Box47, null, /* @__PURE__ */ React58.createElement(Text49, { color: CARD.tool.color, bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React58.createElement(Text49, null, " "), /* @__PURE__ */ React58.createElement(Text49, { color: CARD.tool.color, bold: true }, `\u25A3 ${tool.name}`), /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, ` running \xB7 ${elapsed}s`)), progress ? /* @__PURE__ */ React58.createElement(Box47, { paddingLeft: 3 }, /* @__PURE__ */ React58.createElement(Text49, { color: TONE.brand }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ React58.createElement(Box47, { paddingLeft: 3 }, /* @__PURE__ */ React58.createElement(Text49, { color: FG.faint }, summary)) : null);
10008
+ return /* @__PURE__ */ React59.createElement(Box48, { marginY: 1, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React59.createElement(Box48, null, /* @__PURE__ */ React59.createElement(Text50, { color: CARD.tool.color, bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React59.createElement(Text50, null, " "), /* @__PURE__ */ React59.createElement(Text50, { color: CARD.tool.color, bold: true }, `\u25A3 ${tool.name}`), /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, ` running \xB7 ${elapsed}s`)), progress ? /* @__PURE__ */ React59.createElement(Box48, { paddingLeft: 3 }, /* @__PURE__ */ React59.createElement(Text50, { color: TONE.brand }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ React59.createElement(Box48, { paddingLeft: 3 }, /* @__PURE__ */ React59.createElement(Text50, { color: FG.faint }, summary)) : null);
9777
10009
  }
9778
10010
  function renderProgressLine(p) {
9779
10011
  const msg = p.message ? ` ${p.message}` : "";
@@ -9829,16 +10061,16 @@ function summarizeToolArgs(name, args) {
9829
10061
  }
9830
10062
 
9831
10063
  // src/cli/ui/layout/StatusRow.tsx
9832
- import { Box as Box48, Text as Text51, useStdout as useStdout14 } from "ink";
9833
- import React60 from "react";
10064
+ import { Box as Box49, Text as Text52, useStdout as useStdout15 } from "ink";
10065
+ import React61 from "react";
9834
10066
 
9835
10067
  // src/cli/ui/primitives/Countdown.tsx
9836
- import { Text as Text50 } from "ink";
9837
- import React59 from "react";
10068
+ import { Text as Text51 } from "ink";
10069
+ import React60 from "react";
9838
10070
  function Countdown({ endsAt, color = TONE.brand }) {
9839
10071
  useSlowTick();
9840
10072
  const remainingSec = Math.max(0, Math.ceil((endsAt - Date.now()) / 1e3));
9841
- return /* @__PURE__ */ React59.createElement(Text50, { bold: true, color }, String(remainingSec));
10073
+ return /* @__PURE__ */ React60.createElement(Text51, { bold: true, color }, String(remainingSec));
9842
10074
  }
9843
10075
 
9844
10076
  // src/cli/ui/layout/StatusRow.tsx
@@ -9850,28 +10082,28 @@ var FEEDBACK_HINT_MIN_COLS = 100;
9850
10082
  function StatusRow() {
9851
10083
  const status2 = useAgentState((s) => s.status);
9852
10084
  const session = useAgentState((s) => s.session);
9853
- const { stdout } = useStdout14();
10085
+ const { stdout } = useStdout15();
9854
10086
  const cols = stdout?.columns ?? 80;
9855
10087
  const ruleWidth = Math.max(RULE_MIN, cols - RULE_PAD);
9856
10088
  const hasTurn = status2.cost > 0;
9857
10089
  const hasSession = status2.sessionCost > 0;
9858
10090
  const hasBalance = typeof status2.balance === "number";
9859
10091
  const showWallet = cols >= WALLET_MIN_COLS && (hasSession || hasBalance);
9860
- return /* @__PURE__ */ React60.createElement(Box48, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, /* @__PURE__ */ React60.createElement(Box48, { height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React60.createElement(Text51, null, " "), /* @__PURE__ */ React60.createElement(Text51, { color: FG.faint, wrap: "truncate" }, "\u2500".repeat(ruleWidth))), /* @__PURE__ */ React60.createElement(Box48, { flexDirection: "row", height: 1, minHeight: 1, flexWrap: "nowrap", flexShrink: 0 }, /* @__PURE__ */ React60.createElement(Text51, { wrap: "truncate" }, " "), status2.recording ? /* @__PURE__ */ React60.createElement(RecordingPill, { rec: status2.recording }) : status2.countdownSeconds !== void 0 ? /* @__PURE__ */ React60.createElement(CountdownRow, { mode: status2.mode, secondsLeft: status2.countdownSeconds }) : /* @__PURE__ */ React60.createElement(ModePill2, { mode: status2.mode, network: status2.network, detail: status2.networkDetail }), /* @__PURE__ */ React60.createElement(Sep, null), /* @__PURE__ */ React60.createElement(Text51, { color: FG.sub, wrap: "truncate" }, `${session.id} \xB7 ${session.branch}`), hasTurn && /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(Sep, null), /* @__PURE__ */ React60.createElement(Text51, { bold: true, color: TONE.brand, wrap: "truncate" }, "\u25B8 "), /* @__PURE__ */ React60.createElement(Text51, { bold: true, color: FG.body, wrap: "truncate" }, `${formatCost(status2.cost, status2.balanceCurrency)} ${t("statusBar.turn")}`)), /* @__PURE__ */ React60.createElement(Sep, null), /* @__PURE__ */ React60.createElement(
9861
- Text51,
10092
+ return /* @__PURE__ */ React61.createElement(Box49, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, /* @__PURE__ */ React61.createElement(Box49, { height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React61.createElement(Text52, null, " "), /* @__PURE__ */ React61.createElement(Text52, { color: FG.faint, wrap: "truncate" }, "\u2500".repeat(ruleWidth))), /* @__PURE__ */ React61.createElement(Box49, { flexDirection: "row", height: 1, minHeight: 1, flexWrap: "nowrap", flexShrink: 0 }, /* @__PURE__ */ React61.createElement(Text52, { wrap: "truncate" }, " "), status2.recording ? /* @__PURE__ */ React61.createElement(RecordingPill, { rec: status2.recording }) : status2.countdownSeconds !== void 0 ? /* @__PURE__ */ React61.createElement(CountdownRow, { mode: status2.mode, secondsLeft: status2.countdownSeconds }) : /* @__PURE__ */ React61.createElement(ModePill2, { mode: status2.mode, network: status2.network, detail: status2.networkDetail }), /* @__PURE__ */ React61.createElement(Sep, null), /* @__PURE__ */ React61.createElement(Text52, { color: FG.sub, wrap: "truncate" }, `${session.id} \xB7 ${session.branch}`), hasTurn && /* @__PURE__ */ React61.createElement(React61.Fragment, null, /* @__PURE__ */ React61.createElement(Sep, null), /* @__PURE__ */ React61.createElement(Text52, { bold: true, color: TONE.brand, wrap: "truncate" }, "\u25B8 "), /* @__PURE__ */ React61.createElement(Text52, { bold: true, color: FG.body, wrap: "truncate" }, `${formatCost(status2.cost, status2.balanceCurrency)} ${t("statusBar.turn")}`)), /* @__PURE__ */ React61.createElement(Sep, null), /* @__PURE__ */ React61.createElement(
10093
+ Text52,
9862
10094
  {
9863
10095
  color: TONE.accent,
9864
10096
  wrap: "truncate"
9865
10097
  },
9866
10098
  `${t("statusBar.cache")} ${Math.round(status2.cacheHit * 100)}%`
9867
- ), showWallet && /* @__PURE__ */ React60.createElement(
10099
+ ), showWallet && /* @__PURE__ */ React61.createElement(
9868
10100
  WalletPill,
9869
10101
  {
9870
10102
  sessionCostUsd: status2.sessionCost,
9871
10103
  balance: status2.balance,
9872
10104
  currency: status2.balanceCurrency
9873
10105
  }
9874
- ), cols >= VERSION_MIN_COLS && /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(Sep, null), /* @__PURE__ */ React60.createElement(Text51, { color: FG.faint, wrap: "truncate" }, `v${VERSION}`), cols >= FEEDBACK_HINT_MIN_COLS && /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(Text51, { color: FG.faint, wrap: "truncate" }, " \xB7 "), /* @__PURE__ */ React60.createElement(Text51, { color: FG.meta, wrap: "truncate" }, "\u2691 "), /* @__PURE__ */ React60.createElement(Text51, { color: FG.sub, wrap: "truncate" }, "/feedback")))));
10106
+ ), cols >= VERSION_MIN_COLS && /* @__PURE__ */ React61.createElement(React61.Fragment, null, /* @__PURE__ */ React61.createElement(Sep, null), /* @__PURE__ */ React61.createElement(Text52, { color: FG.faint, wrap: "truncate" }, `v${VERSION}`), cols >= FEEDBACK_HINT_MIN_COLS && /* @__PURE__ */ React61.createElement(React61.Fragment, null, /* @__PURE__ */ React61.createElement(Text52, { color: FG.faint, wrap: "truncate" }, " \xB7 "), /* @__PURE__ */ React61.createElement(Text52, { color: FG.meta, wrap: "truncate" }, "\u2691 "), /* @__PURE__ */ React61.createElement(Text52, { color: FG.sub, wrap: "truncate" }, "/feedback")))));
9875
10107
  }
9876
10108
  function WalletPill({
9877
10109
  sessionCostUsd,
@@ -9880,14 +10112,14 @@ function WalletPill({
9880
10112
  }) {
9881
10113
  const showSpent = sessionCostUsd > 0;
9882
10114
  const showBalance = typeof balance === "number";
9883
- return /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(Sep, null), /* @__PURE__ */ React60.createElement(Text51, { color: FG.meta, wrap: "truncate" }, "\u26C1 "), showSpent && /* @__PURE__ */ React60.createElement(
9884
- Text51,
10115
+ return /* @__PURE__ */ React61.createElement(React61.Fragment, null, /* @__PURE__ */ React61.createElement(Sep, null), /* @__PURE__ */ React61.createElement(Text52, { color: FG.meta, wrap: "truncate" }, "\u26C1 "), showSpent && /* @__PURE__ */ React61.createElement(
10116
+ Text52,
9885
10117
  {
9886
10118
  color: FG.body,
9887
10119
  wrap: "truncate"
9888
10120
  },
9889
10121
  `${formatCost(sessionCostUsd, currency, 2)} ${t("statusBar.spent")}`
9890
- ), showSpent && showBalance && /* @__PURE__ */ React60.createElement(Text51, { color: FG.meta, wrap: "truncate" }, " / "), showBalance && /* @__PURE__ */ React60.createElement(Text51, { bold: true, color: balanceColor(balance, currency), wrap: "truncate" }, formatBalance(balance, currency, { fractionDigits: 2 })), showBalance && /* @__PURE__ */ React60.createElement(Text51, { color: FG.faint, wrap: "truncate" }, t("statusBar.left")));
10122
+ ), showSpent && showBalance && /* @__PURE__ */ React61.createElement(Text52, { color: FG.meta, wrap: "truncate" }, " / "), showBalance && /* @__PURE__ */ React61.createElement(Text52, { bold: true, color: balanceColor(balance, currency), wrap: "truncate" }, formatBalance(balance, currency, { fractionDigits: 2 })), showBalance && /* @__PURE__ */ React61.createElement(Text52, { color: FG.faint, wrap: "truncate" }, t("statusBar.left")));
9891
10123
  }
9892
10124
  function ModePill2({
9893
10125
  mode: mode2,
@@ -9896,18 +10128,18 @@ function ModePill2({
9896
10128
  }) {
9897
10129
  if (network === "online") {
9898
10130
  const pill = modeGlyph(mode2);
9899
- return /* @__PURE__ */ React60.createElement(Box48, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React60.createElement(Text51, { color: pill.color, wrap: "truncate" }, pill.glyph), /* @__PURE__ */ React60.createElement(Text51, { color: FG.sub, wrap: "truncate" }, ` ${mode2}`));
10131
+ return /* @__PURE__ */ React61.createElement(Box49, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React61.createElement(Text52, { color: pill.color, wrap: "truncate" }, pill.glyph), /* @__PURE__ */ React61.createElement(Text52, { color: FG.sub, wrap: "truncate" }, ` ${mode2}`));
9900
10132
  }
9901
10133
  const dot = networkDot(network);
9902
10134
  if (network === "slow") {
9903
10135
  const tail = detail ? ` \xB7 ${detail}` : "";
9904
- return /* @__PURE__ */ React60.createElement(Box48, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React60.createElement(Text51, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React60.createElement(Text51, { color: dot.color, wrap: "truncate" }, ` ${mode2} \xB7 ${t("statusBar.slow")}${tail}`));
10136
+ return /* @__PURE__ */ React61.createElement(Box49, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React61.createElement(Text52, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React61.createElement(Text52, { color: dot.color, wrap: "truncate" }, ` ${mode2} \xB7 ${t("statusBar.slow")}${tail}`));
9905
10137
  }
9906
10138
  if (network === "disconnected") {
9907
10139
  const tail = detail ? ` \xB7 ${detail}` : "";
9908
- return /* @__PURE__ */ React60.createElement(Box48, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React60.createElement(Text51, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React60.createElement(Text51, { color: dot.color, wrap: "truncate" }, ` ${t("statusBar.disconnect")}${tail}`));
10140
+ return /* @__PURE__ */ React61.createElement(Box49, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React61.createElement(Text52, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React61.createElement(Text52, { color: dot.color, wrap: "truncate" }, ` ${t("statusBar.disconnect")}${tail}`));
9909
10141
  }
9910
- return /* @__PURE__ */ React60.createElement(Box48, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React60.createElement(Text51, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React60.createElement(Text51, { color: dot.color, wrap: "truncate" }, ` ${t("statusBar.reconnecting")}`));
10142
+ return /* @__PURE__ */ React61.createElement(Box49, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React61.createElement(Text52, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React61.createElement(Text52, { color: dot.color, wrap: "truncate" }, ` ${t("statusBar.reconnecting")}`));
9911
10143
  }
9912
10144
  function CountdownRow({
9913
10145
  mode: mode2,
@@ -9915,12 +10147,12 @@ function CountdownRow({
9915
10147
  }) {
9916
10148
  const pill = modeGlyph(mode2);
9917
10149
  const endsAt = Date.now() + secondsLeft * 1e3;
9918
- return /* @__PURE__ */ React60.createElement(Box48, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React60.createElement(Text51, { color: pill.color, wrap: "truncate" }, pill.glyph), /* @__PURE__ */ React60.createElement(Text51, { color: FG.sub, wrap: "truncate" }, ` ${mode2} \xB7 `), /* @__PURE__ */ React60.createElement(Text51, { color: TONE.warn, wrap: "truncate" }, t("statusBar.approvingIn")), /* @__PURE__ */ React60.createElement(Countdown, { endsAt }), /* @__PURE__ */ React60.createElement(Text51, { color: TONE.warn, wrap: "truncate" }, t("statusBar.escToInterrupt")));
10150
+ return /* @__PURE__ */ React61.createElement(Box49, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React61.createElement(Text52, { color: pill.color, wrap: "truncate" }, pill.glyph), /* @__PURE__ */ React61.createElement(Text52, { color: FG.sub, wrap: "truncate" }, ` ${mode2} \xB7 `), /* @__PURE__ */ React61.createElement(Text52, { color: TONE.warn, wrap: "truncate" }, t("statusBar.approvingIn")), /* @__PURE__ */ React61.createElement(Countdown, { endsAt }), /* @__PURE__ */ React61.createElement(Text52, { color: TONE.warn, wrap: "truncate" }, t("statusBar.escToInterrupt")));
9919
10151
  }
9920
10152
  function RecordingPill({ rec }) {
9921
10153
  const sizeMb = (rec.sizeBytes / (1024 * 1024)).toFixed(1);
9922
- return /* @__PURE__ */ React60.createElement(Box48, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React60.createElement(Text51, { bold: true, color: TONE.err, wrap: "truncate" }, t("statusBar.recordingGlyph")), /* @__PURE__ */ React60.createElement(
9923
- Text51,
10154
+ return /* @__PURE__ */ React61.createElement(Box49, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React61.createElement(Text52, { bold: true, color: TONE.err, wrap: "truncate" }, t("statusBar.recordingGlyph")), /* @__PURE__ */ React61.createElement(
10155
+ Text52,
9924
10156
  {
9925
10157
  color: TONE.err,
9926
10158
  wrap: "truncate"
@@ -9929,7 +10161,7 @@ function RecordingPill({ rec }) {
9929
10161
  ));
9930
10162
  }
9931
10163
  function Sep() {
9932
- return /* @__PURE__ */ React60.createElement(Text51, { color: FG.meta, wrap: "truncate" }, " \xB7 ");
10164
+ return /* @__PURE__ */ React61.createElement(Text52, { color: FG.meta, wrap: "truncate" }, " \xB7 ");
9933
10165
  }
9934
10166
  function modeGlyph(mode2) {
9935
10167
  switch (mode2) {
@@ -9957,8 +10189,8 @@ function networkDot(state) {
9957
10189
  }
9958
10190
 
9959
10191
  // src/cli/ui/layout/ToastRail.tsx
9960
- import { Box as Box49, Text as Text52, useStdout as useStdout15 } from "ink";
9961
- import React61, { useEffect as useEffect13 } from "react";
10192
+ import { Box as Box50, Text as Text53, useStdout as useStdout16 } from "ink";
10193
+ import React62, { useEffect as useEffect13 } from "react";
9962
10194
  var TONE_COLOR = {
9963
10195
  ok: TONE.ok,
9964
10196
  info: TONE.brand,
@@ -9980,7 +10212,7 @@ function ToastRail() {
9980
10212
  const toasts = useAgentState((s) => s.toasts);
9981
10213
  const dispatch = useDispatch();
9982
10214
  useSlowTick();
9983
- const { stdout } = useStdout15();
10215
+ const { stdout } = useStdout16();
9984
10216
  const cols = stdout?.columns ?? 80;
9985
10217
  const rule = "\u2501".repeat(Math.max(20, cols - 4));
9986
10218
  const now = Date.now();
@@ -9996,17 +10228,17 @@ function ToastRail() {
9996
10228
  }, [toasts, dispatch]);
9997
10229
  const visible = toasts.filter((t2) => now - t2.bornAt < t2.ttlMs);
9998
10230
  if (visible.length === 0) return null;
9999
- return /* @__PURE__ */ React61.createElement(Box49, { flexDirection: "column" }, visible.map((t2) => {
10231
+ return /* @__PURE__ */ React62.createElement(Box50, { flexDirection: "column" }, visible.map((t2) => {
10000
10232
  const color = TONE_COLOR[t2.tone];
10001
10233
  const glyph = TONE_GLYPH[t2.tone];
10002
10234
  const body = bodyColor(t2, now);
10003
10235
  const remainingSec = Math.max(0, Math.ceil((t2.ttlMs - (now - t2.bornAt)) / 1e3));
10004
- return /* @__PURE__ */ React61.createElement(Box49, { key: t2.id, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React61.createElement(Text52, { color }, rule), /* @__PURE__ */ React61.createElement(Box49, { flexDirection: "row" }, /* @__PURE__ */ React61.createElement(Text52, { color }, glyph), /* @__PURE__ */ React61.createElement(Text52, { bold: true, color: body }, ` ${t2.title}`), t2.detail !== void 0 && /* @__PURE__ */ React61.createElement(Text52, { color: FG.sub }, ` \xB7 ${t2.detail}`), /* @__PURE__ */ React61.createElement(Box49, { flexGrow: 1 }), /* @__PURE__ */ React61.createElement(Text52, { color: FG.faint }, `${remainingSec}s`)));
10236
+ return /* @__PURE__ */ React62.createElement(Box50, { key: t2.id, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React62.createElement(Text53, { color }, rule), /* @__PURE__ */ React62.createElement(Box50, { flexDirection: "row" }, /* @__PURE__ */ React62.createElement(Text53, { color }, glyph), /* @__PURE__ */ React62.createElement(Text53, { bold: true, color: body }, ` ${t2.title}`), t2.detail !== void 0 && /* @__PURE__ */ React62.createElement(Text53, { color: FG.sub }, ` \xB7 ${t2.detail}`), /* @__PURE__ */ React62.createElement(Box50, { flexGrow: 1 }), /* @__PURE__ */ React62.createElement(Text53, { color: FG.faint }, `${remainingSec}s`)));
10005
10237
  }));
10006
10238
  }
10007
10239
 
10008
10240
  // src/cli/ui/layout/plan-live-row.tsx
10009
- import React62 from "react";
10241
+ import React63 from "react";
10010
10242
  function isActivePlanInFlight(card) {
10011
10243
  if (card.kind !== "plan") return false;
10012
10244
  if (card.variant !== "active") return false;
@@ -10021,7 +10253,7 @@ function PlanLiveRow() {
10021
10253
  return null;
10022
10254
  });
10023
10255
  if (!planCard) return null;
10024
- return /* @__PURE__ */ React62.createElement(PlanCard, { card: planCard });
10256
+ return /* @__PURE__ */ React63.createElement(PlanCard, { card: planCard });
10025
10257
  }
10026
10258
 
10027
10259
  // src/cli/ui/loop.ts
@@ -10442,26 +10674,19 @@ var resetLog = (_args, loop2) => {
10442
10674
  const info = archived ? t("handlers.basic.newInfoArchived", { count: dropped, archived }) : t("handlers.basic.newInfo", { count: dropped });
10443
10675
  return { clear: true, info };
10444
10676
  };
10445
- var GROUP_ORDER = [
10446
- "chat",
10447
- "setup",
10448
- "info",
10449
- "session",
10450
- "extend",
10451
- "code",
10452
- "jobs",
10453
- "advanced"
10454
- ];
10455
- var GROUP_HEADER = {
10456
- chat: "CHAT \xB7 daily turn ops",
10457
- setup: "SETUP \xB7 model + cost",
10458
- info: "INFO \xB7 current state",
10459
- session: "SESSION \xB7 saved sessions",
10460
- extend: "EXTEND \xB7 MCP, memory, skills",
10461
- code: "CODE \xB7 edits + plans (code mode)",
10462
- jobs: "JOBS \xB7 background processes (code mode)",
10463
- advanced: "ADVANCED \xB7 rare or set-and-forget"
10677
+ var GROUP_DETAIL = {
10678
+ setup: "model + cost",
10679
+ info: "current state",
10680
+ chat: "daily turn ops",
10681
+ extend: "MCP, memory, skills",
10682
+ session: "saved sessions",
10683
+ code: "edits + plans (code mode)",
10684
+ jobs: "background processes (code mode)",
10685
+ advanced: "rare or set-and-forget"
10464
10686
  };
10687
+ function groupHeader(group) {
10688
+ return `${SLASH_GROUP_LABEL[group]} \xB7 ${GROUP_DETAIL[group]}`;
10689
+ }
10465
10690
  function renderRow(spec) {
10466
10691
  const name = `/${spec.cmd}${spec.argsHint ? ` ${spec.argsHint}` : ""}`;
10467
10692
  const desc = t(`slash.${spec.cmd}.description`);
@@ -10470,10 +10695,15 @@ function renderRow(spec) {
10470
10695
  }
10471
10696
  var help = () => {
10472
10697
  const lines = [t("handlers.basic.helpTitle"), ""];
10473
- for (const group of GROUP_ORDER) {
10474
- const rows = SLASH_COMMANDS.filter((c) => c.group === group);
10698
+ const rowsByGroup = /* @__PURE__ */ new Map();
10699
+ for (const group of SLASH_GROUP_ORDER) rowsByGroup.set(group, []);
10700
+ for (const command of orderSlashCommandsByGroup(SLASH_COMMANDS)) {
10701
+ rowsByGroup.get(command.group).push(command);
10702
+ }
10703
+ for (const group of SLASH_GROUP_ORDER) {
10704
+ const rows = rowsByGroup.get(group) ?? [];
10475
10705
  if (rows.length === 0) continue;
10476
- lines.push(` ${GROUP_HEADER[group]}`);
10706
+ lines.push(` ${groupHeader(group)}`);
10477
10707
  for (const r of rows) lines.push(renderRow(r));
10478
10708
  lines.push("");
10479
10709
  }
@@ -10557,13 +10787,15 @@ var keys = (_args, _loop, ctx) => {
10557
10787
  ctx.postKeys({ topic: ref.topic, sections: ref.sections, footer: ref.footer });
10558
10788
  return {};
10559
10789
  };
10790
+ var copy = () => ({ openCopyMode: true });
10560
10791
  var handlers2 = {
10561
10792
  exit,
10562
10793
  new: resetLog,
10563
10794
  help,
10564
10795
  retry,
10565
10796
  loop,
10566
- keys
10797
+ keys,
10798
+ copy
10567
10799
  };
10568
10800
 
10569
10801
  // src/cli/ui/slash/handlers/dashboard.ts
@@ -11484,32 +11716,9 @@ var handlers10 = {
11484
11716
  // src/cli/ui/slash/handlers/observability.ts
11485
11717
  import { release } from "os";
11486
11718
 
11487
- // src/cli/ui/clipboard.ts
11488
- import { mkdtempSync, writeFileSync as writeFileSync4 } from "fs";
11489
- import { tmpdir } from "os";
11490
- import { join as join6 } from "path";
11491
- var OSC_52_LIMIT = 75e3;
11492
- function writeClipboard(text) {
11493
- const dir = mkdtempSync(join6(tmpdir(), "reasonix-clip-"));
11494
- const filePath = join6(dir, "clip.txt");
11495
- let osc52 = false;
11496
- if (text.length <= OSC_52_LIMIT) {
11497
- const b64 = Buffer.from(text, "utf8").toString("base64");
11498
- process.stdout.write(`\x1B]52;c;${b64}\x1B\\`);
11499
- osc52 = true;
11500
- }
11501
- let writtenPath = null;
11502
- try {
11503
- writeFileSync4(filePath, text, "utf8");
11504
- writtenPath = filePath;
11505
- } catch {
11506
- }
11507
- return { osc52, filePath: writtenPath, size: text.length };
11508
- }
11509
-
11510
11719
  // src/cli/ui/ctx-breakdown.tsx
11511
- import { Box as Box50, Text as Text53 } from "ink";
11512
- import React63 from "react";
11720
+ import { Box as Box51, Text as Text54 } from "ink";
11721
+ import React64 from "react";
11513
11722
  function computeCtxBreakdown(loop2) {
11514
11723
  const systemTokens = countTokens(loop2.prefix.system);
11515
11724
  const toolsTokens = countTokens(JSON.stringify(loop2.prefix.toolSpecs));
@@ -12511,7 +12720,7 @@ function hydrateCardsFromMessages(messages) {
12511
12720
  }
12512
12721
 
12513
12722
  // src/cli/ui/useCompletionPickers.ts
12514
- import { useCallback as useCallback10, useEffect as useEffect14, useMemo as useMemo9, useReducer as useReducer2, useRef as useRef7, useState as useState22 } from "react";
12723
+ import { useCallback as useCallback10, useEffect as useEffect14, useMemo as useMemo10, useReducer as useReducer2, useRef as useRef7, useState as useState23 } from "react";
12515
12724
  var SEARCH_DEBOUNCE_MS = 80;
12516
12725
  var SEARCH_FLUSH_MS = 50;
12517
12726
  var SEARCH_RESULT_CAP = 200;
@@ -12524,13 +12733,13 @@ function useCompletionPickers({
12524
12733
  mcpServers,
12525
12734
  slashUsage
12526
12735
  }) {
12527
- const [slashSelected, setSlashSelected] = useState22(0);
12528
- const slashMatches = useMemo9(() => {
12736
+ const [slashSelected, setSlashSelected] = useState23(0);
12737
+ const slashMatches = useMemo10(() => {
12529
12738
  if (!input.startsWith("/") || input.includes(" ")) return null;
12530
12739
  return suggestSlashCommands(input.slice(1), !!codeMode, slashUsage);
12531
12740
  }, [input, codeMode, slashUsage]);
12532
12741
  const slashGroupMode = input === "/";
12533
- const slashAdvancedHidden = useMemo9(
12742
+ const slashAdvancedHidden = useMemo10(
12534
12743
  () => slashGroupMode ? countAdvancedCommands(!!codeMode) : 0,
12535
12744
  [slashGroupMode, codeMode]
12536
12745
  );
@@ -12541,7 +12750,7 @@ function useCompletionPickers({
12541
12750
  return prev;
12542
12751
  });
12543
12752
  }, [slashMatches]);
12544
- const [atSelected, setAtSelected] = useState22(0);
12753
+ const [atSelected, setAtSelected] = useState23(0);
12545
12754
  const recentFilesRef = useRef7([]);
12546
12755
  const recordRecentFile = useCallback10((p) => {
12547
12756
  const list2 = recentFilesRef.current;
@@ -12550,12 +12759,12 @@ function useCompletionPickers({
12550
12759
  list2.unshift(p);
12551
12760
  if (list2.length > 20) list2.length = 20;
12552
12761
  }, []);
12553
- const atPicker = useMemo9(() => {
12762
+ const atPicker = useMemo10(() => {
12554
12763
  if (!codeMode) return null;
12555
12764
  if (slashMatches !== null) return null;
12556
12765
  return detectAtPicker(input);
12557
12766
  }, [codeMode, input, slashMatches]);
12558
- const parsed = useMemo9(
12767
+ const parsed = useMemo10(
12559
12768
  () => atPicker ? parseAtQuery(atPicker.query) : null,
12560
12769
  [atPicker]
12561
12770
  );
@@ -12567,7 +12776,7 @@ function useCompletionPickers({
12567
12776
  atMode === "search" && parsed ? parsed.filter : null,
12568
12777
  recentFilesRef
12569
12778
  );
12570
- const atState = useMemo9(() => {
12779
+ const atState = useMemo10(() => {
12571
12780
  if (!parsed) return null;
12572
12781
  if (atMode === "browse") {
12573
12782
  return {
@@ -12602,13 +12811,13 @@ function useCompletionPickers({
12602
12811
  },
12603
12812
  [atPicker, input, setInput]
12604
12813
  );
12605
- const [slashArgSelected, setSlashArgSelected] = useState22(0);
12606
- const slashArgContext = useMemo9(() => {
12814
+ const [slashArgSelected, setSlashArgSelected] = useState23(0);
12815
+ const slashArgContext = useMemo10(() => {
12607
12816
  if (!input.startsWith("/")) return null;
12608
12817
  if (slashMatches !== null) return null;
12609
12818
  return detectSlashArgContext(input, !!codeMode);
12610
12819
  }, [input, slashMatches, codeMode]);
12611
- const slashArgMatches = useMemo9(() => {
12820
+ const slashArgMatches = useMemo10(() => {
12612
12821
  if (!slashArgContext || slashArgContext.kind !== "picker") return null;
12613
12822
  const completer = slashArgContext.spec.argCompleter;
12614
12823
  const partial = slashArgContext.partial;
@@ -12682,8 +12891,8 @@ function useCompletionPickers({
12682
12891
  };
12683
12892
  }
12684
12893
  function useBrowseListing(rootDir, dir) {
12685
- const [entries, setEntries] = useState22([]);
12686
- const [loading, setLoading] = useState22(false);
12894
+ const [entries, setEntries] = useState23([]);
12895
+ const [loading, setLoading] = useState23(false);
12687
12896
  useEffect14(() => {
12688
12897
  if (dir === null) {
12689
12898
  setEntries([]);
@@ -12790,12 +12999,12 @@ function rankSearchHits(hits, filter, recent) {
12790
12999
  }
12791
13000
 
12792
13001
  // src/cli/ui/useEditHistory.ts
12793
- import { useCallback as useCallback11, useRef as useRef8, useState as useState23 } from "react";
13002
+ import { useCallback as useCallback11, useRef as useRef8, useState as useState24 } from "react";
12794
13003
  function useEditHistory(codeMode) {
12795
13004
  const editHistory = useRef8([]);
12796
13005
  const nextHistoryId = useRef8(1);
12797
13006
  const currentTurnEntry = useRef8(null);
12798
- const [undoBanner, setUndoBanner] = useState23(null);
13007
+ const [undoBanner, setUndoBanner] = useState24(null);
12799
13008
  const undoTimeoutRef = useRef8(null);
12800
13009
  const recordEdit = useCallback11(
12801
13010
  (source, blocks, results, snaps) => {
@@ -13020,11 +13229,11 @@ function useEditHistory(codeMode) {
13020
13229
  }
13021
13230
 
13022
13231
  // src/cli/ui/useSessionInfo.ts
13023
- import { useCallback as useCallback12, useEffect as useEffect15, useState as useState24 } from "react";
13232
+ import { useCallback as useCallback12, useEffect as useEffect15, useState as useState25 } from "react";
13024
13233
  function useSessionInfo(loop2) {
13025
- const [balance, setBalance] = useState24(null);
13026
- const [models, setModels] = useState24(null);
13027
- const [latestVersion, setLatestVersion] = useState24(null);
13234
+ const [balance, setBalance] = useState25(null);
13235
+ const [models, setModels] = useState25(null);
13236
+ const [latestVersion, setLatestVersion] = useState25(null);
13028
13237
  useEffect15(() => {
13029
13238
  let cancelled = false;
13030
13239
  void (async () => {
@@ -13093,7 +13302,46 @@ function useSessionInfo(loop2) {
13093
13302
  }
13094
13303
 
13095
13304
  // src/cli/ui/useSubagent.ts
13096
- import { useEffect as useEffect16, useRef as useRef9, useState as useState25 } from "react";
13305
+ import { useEffect as useEffect16, useRef as useRef9, useState as useState26 } from "react";
13306
+ function reduceSubagentInnerEvent(prev, ev) {
13307
+ if (ev.kind === "inner") {
13308
+ if (!ev.inner) return prev;
13309
+ const summary = summariseInner(ev.inner);
13310
+ if (!summary) return prev;
13311
+ return mapMatchingRun(prev, ev.runId, (a) => ({ ...a, lastInner: summary }));
13312
+ }
13313
+ if (ev.kind === "progress") {
13314
+ return mapMatchingRun(prev, ev.runId, (a) => {
13315
+ const iter = ev.iter ?? a.iter;
13316
+ const elapsedMs = ev.elapsedMs ?? a.elapsedMs;
13317
+ if (iter === a.iter && elapsedMs === a.elapsedMs) return a;
13318
+ return { ...a, iter, elapsedMs };
13319
+ });
13320
+ }
13321
+ if (ev.kind === "phase") {
13322
+ return mapMatchingRun(prev, ev.runId, (a) => {
13323
+ const phase = ev.phase ?? a.phase;
13324
+ if (phase === a.phase) return a;
13325
+ return { ...a, phase };
13326
+ });
13327
+ }
13328
+ return prev;
13329
+ }
13330
+ function mapMatchingRun(prev, runId, fn) {
13331
+ let idx = -1;
13332
+ for (let i = 0; i < prev.length; i++) {
13333
+ if (prev[i].runId === runId) {
13334
+ idx = i;
13335
+ break;
13336
+ }
13337
+ }
13338
+ if (idx < 0) return prev;
13339
+ const updated = fn(prev[idx]);
13340
+ if (updated === prev[idx]) return prev;
13341
+ const next = prev.slice();
13342
+ next[idx] = updated;
13343
+ return next;
13344
+ }
13097
13345
  function summariseInner(ev) {
13098
13346
  if (ev.role === "tool_start") {
13099
13347
  return {
@@ -13124,7 +13372,7 @@ function useSubagent({
13124
13372
  log,
13125
13373
  getWalletCurrency
13126
13374
  }) {
13127
- const [activities, setActivities] = useState25([]);
13375
+ const [activities, setActivities] = useState26([]);
13128
13376
  const sinkRef = useRef9({ current: null });
13129
13377
  const getWalletCurrencyRef = useRef9(getWalletCurrency);
13130
13378
  useEffect16(() => {
@@ -13172,26 +13420,7 @@ function useSubagent({
13172
13420
  }
13173
13421
  return;
13174
13422
  }
13175
- setActivities(
13176
- (prev) => prev.map((a) => {
13177
- if (a.runId !== ev.runId) return a;
13178
- if (ev.kind === "progress") {
13179
- return {
13180
- ...a,
13181
- iter: ev.iter ?? a.iter,
13182
- elapsedMs: ev.elapsedMs ?? a.elapsedMs
13183
- };
13184
- }
13185
- if (ev.kind === "phase") {
13186
- return { ...a, phase: ev.phase ?? a.phase };
13187
- }
13188
- if (ev.kind === "inner" && ev.inner) {
13189
- const summary = summariseInner(ev.inner);
13190
- return summary ? { ...a, lastInner: summary } : a;
13191
- }
13192
- return a;
13193
- })
13194
- );
13423
+ setActivities((prev) => reduceSubagentInnerEvent(prev, ev));
13195
13424
  };
13196
13425
  return () => {
13197
13426
  sinkRef.current.current = null;
@@ -13213,20 +13442,20 @@ function InputAreaWithHistoryHint({
13213
13442
  }) {
13214
13443
  const pinned = useChatScrollState((s) => s.pinned);
13215
13444
  if (!pinned) {
13216
- return /* @__PURE__ */ React64.createElement(Text54, { color: FG.faint }, " \u{1F4D6} reading history \u2014 End / PgDn to return \xB7 \u2193 to advance one line");
13445
+ return /* @__PURE__ */ React65.createElement(Text55, { color: FG.faint }, " \u{1F4D6} reading history \u2014 End / PgDn to return \xB7 \u2193 to advance one line");
13217
13446
  }
13218
- return /* @__PURE__ */ React64.createElement(React64.Fragment, null, inputArea);
13447
+ return /* @__PURE__ */ React65.createElement(React65.Fragment, null, inputArea);
13219
13448
  }
13220
13449
  function LoopStatusRow({
13221
13450
  loop: loop2
13222
13451
  }) {
13223
- const [, setTick] = React64.useState(0);
13224
- React64.useEffect(() => {
13452
+ const [, setTick] = React65.useState(0);
13453
+ React65.useEffect(() => {
13225
13454
  const id = setInterval(() => setTick((t2) => t2 + 1), 1e3);
13226
13455
  return () => clearInterval(id);
13227
13456
  }, []);
13228
13457
  const nextFireMs = Math.max(0, loop2.nextFireAt - Date.now());
13229
- return /* @__PURE__ */ React64.createElement(Box51, null, /* @__PURE__ */ React64.createElement(Text54, { color: "cyan" }, `\u25B8 ${formatLoopStatus(loop2.prompt, nextFireMs, loop2.iter)} \xB7 /loop stop or type to cancel`));
13458
+ return /* @__PURE__ */ React65.createElement(Box52, null, /* @__PURE__ */ React65.createElement(Text55, { color: "cyan" }, `\u25B8 ${formatLoopStatus(loop2.prompt, nextFireMs, loop2.iter)} \xB7 /loop stop or type to cancel`));
13230
13459
  }
13231
13460
  function App(props) {
13232
13461
  markPhase("app_render_start");
@@ -13235,14 +13464,14 @@ function App(props) {
13235
13464
  model: props.model,
13236
13465
  workspace: props.codeMode?.rootDir ?? process.cwd()
13237
13466
  });
13238
- const initialCards = React64.useMemo(
13467
+ const initialCards = React65.useMemo(
13239
13468
  () => props.session ? hydrateCardsFromMessages(loadSessionMessages(props.session)) : [],
13240
13469
  [props.session]
13241
13470
  );
13242
- const [themeName, setThemeName] = React64.useState(
13471
+ const [themeName, setThemeName] = React65.useState(
13243
13472
  () => resolveThemePreference(loadTheme(), process.env.REASONIX_THEME)
13244
13473
  );
13245
- return /* @__PURE__ */ React64.createElement(ThemeProvider, { name: themeName }, /* @__PURE__ */ React64.createElement(AgentStoreProvider, { session, initialCards }, /* @__PURE__ */ React64.createElement(ChatScrollProvider, null, /* @__PURE__ */ React64.createElement(AppInner, { ...props, themeName, setThemeName }))));
13474
+ return /* @__PURE__ */ React65.createElement(ThemeProvider, { name: themeName }, /* @__PURE__ */ React65.createElement(AgentStoreProvider, { session, initialCards }, /* @__PURE__ */ React65.createElement(ChatScrollProvider, null, /* @__PURE__ */ React65.createElement(AppInner, { ...props, themeName, setThemeName }))));
13246
13475
  }
13247
13476
  function AppInner({
13248
13477
  model: model2,
@@ -13271,17 +13500,17 @@ function AppInner({
13271
13500
  const isStreaming = useAgentState((s) => s.cards.some((c) => c.kind === "streaming" && !c.done));
13272
13501
  const activityLabel = useActivityLabel();
13273
13502
  const chatScroll = useChatScrollActions();
13274
- const [input, setInput] = useState26("");
13275
- const [busy, setBusy] = useState26(false);
13276
- const [slashUsage, setSlashUsage] = useState26(
13503
+ const [input, setInput] = useState27("");
13504
+ const [busy, setBusy] = useState27(false);
13505
+ const [slashUsage, setSlashUsage] = useState27(
13277
13506
  () => loadSlashUsage()
13278
13507
  );
13279
- const [liveExpand, setLiveExpand] = useState26(false);
13508
+ const [liveExpand, setLiveExpand] = useState27(false);
13280
13509
  useEffect17(() => {
13281
13510
  if (!isStreaming && liveExpand) setLiveExpand(false);
13282
13511
  }, [isStreaming, liveExpand]);
13283
13512
  const languageVersion = useLanguageReload();
13284
- const [bootReady, setBootReady] = useState26(false);
13513
+ const [bootReady, setBootReady] = useState27(false);
13285
13514
  useEffect17(() => {
13286
13515
  const t2 = setTimeout(() => setBootReady(true), 1400);
13287
13516
  return () => clearTimeout(t2);
@@ -13290,7 +13519,7 @@ function AppInner({
13290
13519
  markPhase("first_paint");
13291
13520
  dumpStartupProfile();
13292
13521
  }, []);
13293
- const [liveMcpServers, setLiveMcpServers] = useState26(() => mcpServers ?? []);
13522
+ const [liveMcpServers, setLiveMcpServers] = useState27(() => mcpServers ?? []);
13294
13523
  const abortedThisTurn = useRef10(false);
13295
13524
  useEffect17(() => {
13296
13525
  busyRef.current = busy;
@@ -13304,7 +13533,7 @@ function AppInner({
13304
13533
  setStatusLine,
13305
13534
  clear: clearToolProgressDisplay
13306
13535
  } = useToolProgressDisplay(progressSink);
13307
- const { stdout } = useStdout16();
13536
+ const { stdout } = useStdout17();
13308
13537
  useTerminalSetup(mouse);
13309
13538
  const walletCurrencyRef = useRef10(void 0);
13310
13539
  const { activities: subagentActivities, sinkRef: subagentSinkRef } = useSubagent({
@@ -13341,29 +13570,30 @@ function AppInner({
13341
13570
  const { preset: preset2, setPreset, proArmed, setProArmed, turnOnPro, setTurnOnPro } = usePresetMode(model2);
13342
13571
  const planModeRef = useRef10(false);
13343
13572
  const latestVersionRef = useRef10(null);
13344
- const [pendingEditReview, setPendingEditReview] = useState26(null);
13345
- const [walkthroughActive, setWalkthroughActive] = useState26(false);
13573
+ const [pendingEditReview, setPendingEditReview] = useState27(null);
13574
+ const [walkthroughActive, setWalkthroughActive] = useState27(false);
13346
13575
  const editReviewResolveRef = useRef10(null);
13347
13576
  const turnEditPolicyRef = useRef10("ask");
13348
- const [pendingShell, setPendingShell] = useState26(null);
13349
- const [pendingPlan, setPendingPlan] = useState26(null);
13350
- const [pendingReviseEditor, setPendingReviseEditor] = useState26(null);
13351
- const [pendingSessionsPicker, setPendingSessionsPicker] = useState26(false);
13352
- const [sessionsPickerList, setSessionsPickerList] = useState26([]);
13353
- const [pendingCheckpointPicker, setPendingCheckpointPicker] = useState26(false);
13354
- const [checkpointPickerList, setCheckpointPickerList] = useState26([]);
13355
- const [pendingMcpHub, setPendingMcpHub] = useState26(null);
13356
- const [pendingModelPicker, setPendingModelPicker] = useState26(false);
13357
- const [pendingThemePicker, setPendingThemePicker] = useState26(false);
13358
- const [stagedInput, setStagedInput] = useState26(null);
13359
- const [pendingCheckpoint, setPendingCheckpoint] = useState26(null);
13360
- const [stagedCheckpointRevise, setStagedCheckpointRevise] = useState26(null);
13361
- const [pendingRevision, setPendingRevision] = useState26(null);
13362
- const [pendingChoice, setPendingChoice] = useState26(null);
13363
- const [stagedChoiceCustom, setStagedChoiceCustom] = useState26(null);
13364
- const modalOpen = !!pendingShell || !!pendingPlan || !!pendingReviseEditor || !!pendingSessionsPicker || !!pendingCheckpointPicker || !!pendingMcpHub || pendingModelPicker || pendingThemePicker || !!stagedInput || !!pendingEditReview || walkthroughActive || !!pendingChoice || !!stagedChoiceCustom || !!pendingRevision || !!stagedCheckpointRevise || !!pendingCheckpoint;
13365
- const [planMode, setPlanMode] = useState26(false);
13366
- const [queuedSubmit, setQueuedSubmit] = useState26(null);
13577
+ const [pendingShell, setPendingShell] = useState27(null);
13578
+ const [pendingPlan, setPendingPlan] = useState27(null);
13579
+ const [pendingReviseEditor, setPendingReviseEditor] = useState27(null);
13580
+ const [pendingSessionsPicker, setPendingSessionsPicker] = useState27(false);
13581
+ const [sessionsPickerList, setSessionsPickerList] = useState27([]);
13582
+ const [pendingCheckpointPicker, setPendingCheckpointPicker] = useState27(false);
13583
+ const [checkpointPickerList, setCheckpointPickerList] = useState27([]);
13584
+ const [pendingMcpHub, setPendingMcpHub] = useState27(null);
13585
+ const [pendingModelPicker, setPendingModelPicker] = useState27(false);
13586
+ const [pendingThemePicker, setPendingThemePicker] = useState27(false);
13587
+ const [pendingCopyMode, setPendingCopyMode] = useState27(false);
13588
+ const [stagedInput, setStagedInput] = useState27(null);
13589
+ const [pendingCheckpoint, setPendingCheckpoint] = useState27(null);
13590
+ const [stagedCheckpointRevise, setStagedCheckpointRevise] = useState27(null);
13591
+ const [pendingRevision, setPendingRevision] = useState27(null);
13592
+ const [pendingChoice, setPendingChoice] = useState27(null);
13593
+ const [stagedChoiceCustom, setStagedChoiceCustom] = useState27(null);
13594
+ const modalOpen = !!pendingShell || !!pendingPlan || !!pendingReviseEditor || !!pendingSessionsPicker || !!pendingCheckpointPicker || !!pendingMcpHub || pendingModelPicker || pendingThemePicker || pendingCopyMode || !!stagedInput || !!pendingEditReview || walkthroughActive || !!pendingChoice || !!stagedChoiceCustom || !!pendingRevision || !!stagedCheckpointRevise || !!pendingCheckpoint;
13595
+ const [planMode, setPlanMode] = useState27(false);
13596
+ const [queuedSubmit, setQueuedSubmit] = useState27(null);
13367
13597
  const { recallPrev, recallNext, pushHistory, resetCursor } = useInputRecall(setInput);
13368
13598
  const assistantIterCounter = useRef10(0);
13369
13599
  const atUrlCache = useRef10(/* @__PURE__ */ new Map());
@@ -13376,7 +13606,7 @@ function AppInner({
13376
13606
  const activePickerSnapshotRef = useRef10(null);
13377
13607
  const activeViewerResolverRef = useRef10(null);
13378
13608
  const activeViewerSnapshotRef = useRef10(null);
13379
- const [pendingReplayViewer, setPendingReplayViewer] = useState26(null);
13609
+ const [pendingReplayViewer, setPendingReplayViewer] = useState27(null);
13380
13610
  const planStepsRef = useRef10(null);
13381
13611
  const completedStepIdsRef = useRef10(/* @__PURE__ */ new Set());
13382
13612
  const planBodyRef = useRef10(null);
@@ -13394,7 +13624,7 @@ function AppInner({
13394
13624
  if (planSummaryRef.current) extras.summary = planSummaryRef.current;
13395
13625
  savePlanState(session, steps, completedStepIdsRef.current, extras);
13396
13626
  }, [session]);
13397
- const [summary, setSummary] = useState26({
13627
+ const [summary, setSummary] = useState27({
13398
13628
  turns: 0,
13399
13629
  totalCostUsd: 0,
13400
13630
  totalInputCostUsd: 0,
@@ -13428,7 +13658,7 @@ function AppInner({
13428
13658
  };
13429
13659
  }, []);
13430
13660
  const loopRef = useRef10(null);
13431
- const loop2 = useMemo10(() => {
13661
+ const loop2 = useMemo11(() => {
13432
13662
  if (loopRef.current) return loopRef.current;
13433
13663
  const client = new DeepSeekClient({ baseUrl: loadBaseUrl() });
13434
13664
  if (tools && !tools.has("run_skill")) {
@@ -13598,7 +13828,7 @@ function AppInner({
13598
13828
  }
13599
13829
  }
13600
13830
  }, []);
13601
- const pickerPorts = useMemo10(
13831
+ const pickerPorts = useMemo11(
13602
13832
  () => ({
13603
13833
  broadcast: broadcastDashboardEvent,
13604
13834
  resolverRef: activePickerResolverRef,
@@ -13606,7 +13836,7 @@ function AppInner({
13606
13836
  }),
13607
13837
  [broadcastDashboardEvent]
13608
13838
  );
13609
- const viewerPorts = useMemo10(
13839
+ const viewerPorts = useMemo11(
13610
13840
  () => ({
13611
13841
  broadcast: broadcastDashboardEvent,
13612
13842
  resolverRef: activeViewerResolverRef,
@@ -13992,7 +14222,7 @@ function AppInner({
13992
14222
  if (dashboardRef.current) return dashboardRef.current.url;
13993
14223
  if (dashboardStartingRef.current) return dashboardStartingRef.current;
13994
14224
  const startup = (async () => {
13995
- const { startDashboardServer } = await import("./server-6ZW4TQUP.js");
14225
+ const { startDashboardServer } = await import("./server-IZPWQYG3.js");
13996
14226
  const handle = await startDashboardServer({
13997
14227
  mode: "attached",
13998
14228
  configPath: defaultConfigPath(),
@@ -14251,7 +14481,7 @@ function AppInner({
14251
14481
  const getDashboardUrl = useCallback13(() => {
14252
14482
  return dashboardRef.current?.url ?? null;
14253
14483
  }, []);
14254
- const [dashboardUrl, setDashboardUrlState] = useState26(null);
14484
+ const [dashboardUrl, setDashboardUrlState] = useState27(null);
14255
14485
  useEffect17(() => {
14256
14486
  if (noDashboard) return;
14257
14487
  if (dashboardRef.current) return;
@@ -14513,6 +14743,11 @@ function AppInner({
14513
14743
  pushHistory(text);
14514
14744
  return;
14515
14745
  }
14746
+ if (result.openCopyMode) {
14747
+ setPendingCopyMode(true);
14748
+ pushHistory(text);
14749
+ return;
14750
+ }
14516
14751
  if (result.openArgPickerFor) {
14517
14752
  pushHistory(text);
14518
14753
  setInput(`/${result.openArgPickerFor} `);
@@ -15289,8 +15524,8 @@ function AppInner({
15289
15524
  []
15290
15525
  );
15291
15526
  const tickerSuspended = modalOpen || !busy && !isStreaming;
15292
- if (!bootReady) return /* @__PURE__ */ React64.createElement(BootSplash, null);
15293
- return /* @__PURE__ */ React64.createElement(React64.Fragment, null, /* @__PURE__ */ React64.createElement(TickerProvider, { disabled: tickerSuspended }, /* @__PURE__ */ React64.createElement(ViewportBudgetProvider, null, /* @__PURE__ */ React64.createElement(InflightProvider, { inflight: loop2.inflight }, /* @__PURE__ */ React64.createElement(Box51, { flexDirection: "row", height: stdout?.rows ?? 24 }, /* @__PURE__ */ React64.createElement(Box51, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React64.createElement(Box51, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React64.createElement(LiveExpandContext.Provider, { value: liveExpand }, /* @__PURE__ */ React64.createElement(CardStream, { suppressLive: modalOpen })), !hasConversation && !busy && !isStreaming && slashMatches === null ? /* @__PURE__ */ React64.createElement(
15527
+ if (!bootReady) return /* @__PURE__ */ React65.createElement(BootSplash, null);
15528
+ return /* @__PURE__ */ React65.createElement(React65.Fragment, null, /* @__PURE__ */ React65.createElement(TickerProvider, { disabled: tickerSuspended }, /* @__PURE__ */ React65.createElement(ViewportBudgetProvider, null, /* @__PURE__ */ React65.createElement(InflightProvider, { inflight: loop2.inflight }, /* @__PURE__ */ React65.createElement(Box52, { flexDirection: "row", height: stdout?.rows ?? 24 }, /* @__PURE__ */ React65.createElement(Box52, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React65.createElement(Box52, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React65.createElement(LiveExpandContext.Provider, { value: liveExpand }, /* @__PURE__ */ React65.createElement(CardStream, { suppressLive: modalOpen })), !hasConversation && !busy && !isStreaming && slashMatches === null ? /* @__PURE__ */ React65.createElement(
15294
15529
  WelcomeBanner,
15295
15530
  {
15296
15531
  inCodeMode: !!codeMode,
@@ -15298,7 +15533,7 @@ function AppInner({
15298
15533
  dashboardUrl,
15299
15534
  languageVersion
15300
15535
  }
15301
- ) : null, !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && ongoingTool ? /* @__PURE__ */ React64.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && subagentActivities.length > 0 ? /* @__PURE__ */ React64.createElement(SubagentLiveStack, { activities: subagentActivities, max: 3 }) : null, !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && !ongoingTool && statusLine ? /* @__PURE__ */ React64.createElement(ThinkingRow, { text: statusLine }) : null, undoBanner && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && !pendingChoice && !stagedChoiceCustom && !pendingRevision && !stagedCheckpointRevise && !pendingCheckpoint ? /* @__PURE__ */ React64.createElement(UndoBanner, { banner: undoBanner }) : null, !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && busy && !isStreaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React64.createElement(ThinkingRow, { text: activityLabel }) : null, !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview ? /* @__PURE__ */ React64.createElement(PlanLiveRow, null) : null, /* @__PURE__ */ React64.createElement(ToastRail, null)), stagedInput ? /* @__PURE__ */ React64.createElement(
15536
+ ) : null, !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && ongoingTool ? /* @__PURE__ */ React65.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && subagentActivities.length > 0 ? /* @__PURE__ */ React65.createElement(SubagentLiveStack, { activities: subagentActivities, max: 3 }) : null, !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && !ongoingTool && statusLine ? /* @__PURE__ */ React65.createElement(ThinkingRow, { text: statusLine }) : null, undoBanner && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && !pendingChoice && !stagedChoiceCustom && !pendingRevision && !stagedCheckpointRevise && !pendingCheckpoint ? /* @__PURE__ */ React65.createElement(UndoBanner, { banner: undoBanner }) : null, !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && busy && !isStreaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React65.createElement(ThinkingRow, { text: activityLabel }) : null, !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview ? /* @__PURE__ */ React65.createElement(PlanLiveRow, null) : null, /* @__PURE__ */ React65.createElement(ToastRail, null)), stagedInput ? /* @__PURE__ */ React65.createElement(
15302
15537
  PlanRefineInput,
15303
15538
  {
15304
15539
  mode: stagedInput.mode,
@@ -15306,21 +15541,21 @@ function AppInner({
15306
15541
  onSubmit: handleStagedInputSubmit,
15307
15542
  onCancel: handleStagedInputCancel
15308
15543
  }
15309
- ) : stagedChoiceCustom ? /* @__PURE__ */ React64.createElement(
15544
+ ) : stagedChoiceCustom ? /* @__PURE__ */ React65.createElement(
15310
15545
  PlanRefineInput,
15311
15546
  {
15312
15547
  mode: "choice-custom",
15313
15548
  onSubmit: handleChoiceCustomSubmit,
15314
15549
  onCancel: handleChoiceCustomCancel
15315
15550
  }
15316
- ) : stagedCheckpointRevise ? /* @__PURE__ */ React64.createElement(
15551
+ ) : stagedCheckpointRevise ? /* @__PURE__ */ React65.createElement(
15317
15552
  PlanRefineInput,
15318
15553
  {
15319
15554
  mode: "checkpoint-revise",
15320
15555
  onSubmit: (text) => handleCheckpointReviseSubmit(text, stagedCheckpointRevise),
15321
15556
  onCancel: handleCheckpointReviseCancel
15322
15557
  }
15323
- ) : pendingChoice ? /* @__PURE__ */ React64.createElement(
15558
+ ) : pendingChoice ? /* @__PURE__ */ React65.createElement(
15324
15559
  ChoiceConfirm,
15325
15560
  {
15326
15561
  question: pendingChoice.question,
@@ -15328,7 +15563,7 @@ function AppInner({
15328
15563
  allowCustom: pendingChoice.allowCustom,
15329
15564
  onChoose: stableHandleChoiceConfirm
15330
15565
  }
15331
- ) : pendingRevision ? /* @__PURE__ */ React64.createElement(
15566
+ ) : pendingRevision ? /* @__PURE__ */ React65.createElement(
15332
15567
  PlanReviseConfirm,
15333
15568
  {
15334
15569
  reason: pendingRevision.reason,
@@ -15339,7 +15574,7 @@ function AppInner({
15339
15574
  summary: pendingRevision.summary,
15340
15575
  onChoose: stableHandleReviseConfirm
15341
15576
  }
15342
- ) : pendingCheckpoint ? /* @__PURE__ */ React64.createElement(
15577
+ ) : pendingCheckpoint ? /* @__PURE__ */ React65.createElement(
15343
15578
  PlanCheckpointConfirm,
15344
15579
  {
15345
15580
  stepId: pendingCheckpoint.stepId,
@@ -15350,7 +15585,7 @@ function AppInner({
15350
15585
  completedStepIds: completedStepIdsRef.current,
15351
15586
  onChoose: stableHandleCheckpointConfirm
15352
15587
  }
15353
- ) : pendingCheckpointPicker ? /* @__PURE__ */ React64.createElement(
15588
+ ) : pendingCheckpointPicker ? /* @__PURE__ */ React65.createElement(
15354
15589
  CheckpointPicker,
15355
15590
  {
15356
15591
  checkpoints: checkpointPickerList,
@@ -15395,7 +15630,7 @@ function AppInner({
15395
15630
  }
15396
15631
  }
15397
15632
  }
15398
- ) : pendingSessionsPicker ? /* @__PURE__ */ React64.createElement(
15633
+ ) : pendingSessionsPicker ? /* @__PURE__ */ React65.createElement(
15399
15634
  SessionPicker,
15400
15635
  {
15401
15636
  sessions: sessionsPickerList,
@@ -15440,7 +15675,7 @@ function AppInner({
15440
15675
  }
15441
15676
  }
15442
15677
  }
15443
- ) : pendingThemePicker ? /* @__PURE__ */ React64.createElement(
15678
+ ) : pendingThemePicker ? /* @__PURE__ */ React65.createElement(
15444
15679
  ThemePicker,
15445
15680
  {
15446
15681
  currentPreference: loadTheme() ?? "auto",
@@ -15458,7 +15693,23 @@ function AppInner({
15458
15693
  active now: ${active}`);
15459
15694
  }
15460
15695
  }
15461
- ) : pendingModelPicker ? /* @__PURE__ */ React64.createElement(
15696
+ ) : pendingCopyMode ? /* @__PURE__ */ React65.createElement(
15697
+ CopyMode,
15698
+ {
15699
+ cards: agentStore.getState().cards,
15700
+ onClose: (yanked) => {
15701
+ setPendingCopyMode(false);
15702
+ if (yanked) {
15703
+ const path = yanked.filePath;
15704
+ const info = yanked.osc52 ? t("copyMode.yankedToast", { size: yanked.size }) : t("copyMode.yankedToastFile", {
15705
+ size: yanked.size,
15706
+ path: path ?? "\u2014"
15707
+ });
15708
+ log.pushInfo(info);
15709
+ }
15710
+ }
15711
+ }
15712
+ ) : pendingModelPicker ? /* @__PURE__ */ React65.createElement(
15462
15713
  ModelPicker,
15463
15714
  {
15464
15715
  models,
@@ -15490,7 +15741,7 @@ function AppInner({
15490
15741
  }
15491
15742
  }
15492
15743
  }
15493
- ) : pendingMcpHub ? /* @__PURE__ */ React64.createElement(
15744
+ ) : pendingMcpHub ? /* @__PURE__ */ React65.createElement(
15494
15745
  McpHub,
15495
15746
  {
15496
15747
  initialTab: pendingMcpHub.tab,
@@ -15510,7 +15761,7 @@ function AppInner({
15510
15761
  return r;
15511
15762
  } : void 0
15512
15763
  }
15513
- ) : pendingPlan ? /* @__PURE__ */ React64.createElement(
15764
+ ) : pendingPlan ? /* @__PURE__ */ React65.createElement(
15514
15765
  PlanConfirm,
15515
15766
  {
15516
15767
  plan: pendingPlan,
@@ -15519,7 +15770,7 @@ function AppInner({
15519
15770
  onChoose: stableHandlePlanConfirm,
15520
15771
  projectRoot: currentRootDir
15521
15772
  }
15522
- ) : pendingReviseEditor ? /* @__PURE__ */ React64.createElement(
15773
+ ) : pendingReviseEditor ? /* @__PURE__ */ React65.createElement(
15523
15774
  PlanReviseEditor,
15524
15775
  {
15525
15776
  steps: planStepsRef.current ?? [],
@@ -15538,7 +15789,7 @@ function AppInner({
15538
15789
  setPendingPlan(planText);
15539
15790
  }
15540
15791
  }
15541
- ) : pendingShell ? /* @__PURE__ */ React64.createElement(
15792
+ ) : pendingShell ? /* @__PURE__ */ React65.createElement(
15542
15793
  ShellConfirm,
15543
15794
  {
15544
15795
  command: pendingShell.command,
@@ -15546,7 +15797,7 @@ function AppInner({
15546
15797
  kind: pendingShell.kind,
15547
15798
  onChoose: handleShellConfirm
15548
15799
  }
15549
- ) : pendingEditReview ? /* @__PURE__ */ React64.createElement(
15800
+ ) : pendingEditReview ? /* @__PURE__ */ React65.createElement(
15550
15801
  EditConfirm,
15551
15802
  {
15552
15803
  block: pendingEditReview,
@@ -15558,17 +15809,17 @@ function AppInner({
15558
15809
  }
15559
15810
  }
15560
15811
  }
15561
- ) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */ React64.createElement(
15812
+ ) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */ React65.createElement(
15562
15813
  EditConfirm,
15563
15814
  {
15564
15815
  key: `walk-${pendingTick}`,
15565
15816
  block: pendingEdits.current[0],
15566
15817
  onChoose: handleWalkChoice
15567
15818
  }
15568
- ) : /* @__PURE__ */ React64.createElement(
15819
+ ) : /* @__PURE__ */ React65.createElement(
15569
15820
  InputAreaWithHistoryHint,
15570
15821
  {
15571
- inputArea: /* @__PURE__ */ React64.createElement(Box51, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, /* @__PURE__ */ React64.createElement(Box51, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, codeMode ? /* @__PURE__ */ React64.createElement(
15822
+ inputArea: /* @__PURE__ */ React65.createElement(Box52, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, /* @__PURE__ */ React65.createElement(Box52, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, codeMode ? /* @__PURE__ */ React65.createElement(
15572
15823
  ModeStatusBar,
15573
15824
  {
15574
15825
  editMode,
@@ -15578,7 +15829,7 @@ function AppInner({
15578
15829
  undoArmed: !!undoBanner || hasUndoable(),
15579
15830
  jobs: codeMode.jobs
15580
15831
  }
15581
- ) : null, activeLoop ? /* @__PURE__ */ React64.createElement(LoopStatusRow, { loop: activeLoop }) : null, /* @__PURE__ */ React64.createElement(StatusRow, null), /* @__PURE__ */ React64.createElement(
15832
+ ) : null, activeLoop ? /* @__PURE__ */ React65.createElement(LoopStatusRow, { loop: activeLoop }) : null, /* @__PURE__ */ React65.createElement(StatusRow, null), /* @__PURE__ */ React65.createElement(
15582
15833
  PromptInput,
15583
15834
  {
15584
15835
  value: input,
@@ -15588,7 +15839,7 @@ function AppInner({
15588
15839
  onHistoryPrev: recallPrev,
15589
15840
  onHistoryNext: recallNext
15590
15841
  }
15591
- )), /* @__PURE__ */ React64.createElement(Box51, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, slashMatches !== null ? /* @__PURE__ */ React64.createElement(
15842
+ )), /* @__PURE__ */ React65.createElement(Box52, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, slashMatches !== null ? /* @__PURE__ */ React65.createElement(
15592
15843
  SlashSuggestions,
15593
15844
  {
15594
15845
  key: `slash-suggestions:${slashGroupMode ? "group" : "search"}`,
@@ -15597,7 +15848,7 @@ function AppInner({
15597
15848
  groupMode: slashGroupMode,
15598
15849
  advancedHidden: slashAdvancedHidden
15599
15850
  }
15600
- ) : null, atState !== null ? /* @__PURE__ */ React64.createElement(AtMentionSuggestions, { state: atState, selectedIndex: atSelected }) : null), slashArgContext ? /* @__PURE__ */ React64.createElement(
15851
+ ) : null, atState !== null ? /* @__PURE__ */ React65.createElement(AtMentionSuggestions, { state: atState, selectedIndex: atSelected }) : null), slashArgContext ? /* @__PURE__ */ React65.createElement(
15601
15852
  SlashArgPicker,
15602
15853
  {
15603
15854
  matches: slashArgMatches,
@@ -15612,12 +15863,12 @@ function AppInner({
15612
15863
  }
15613
15864
 
15614
15865
  // src/cli/ui/Setup.tsx
15615
- import { Box as Box52, Text as Text56, useApp } from "ink";
15616
- import React66, { useState as useState27 } from "react";
15866
+ import { Box as Box53, Text as Text57, useApp } from "ink";
15867
+ import React67, { useState as useState28 } from "react";
15617
15868
 
15618
15869
  // src/cli/ui/MaskedInput.tsx
15619
- import { Text as Text55, useInput } from "ink";
15620
- import React65, { useRef as useRef11 } from "react";
15870
+ import { Text as Text56, useInput } from "ink";
15871
+ import React66, { useRef as useRef11 } from "react";
15621
15872
  function stripPasteMarkers(s) {
15622
15873
  return s.replace(/\u001b?\[20[01]~/g, "").replace(/\u001b/g, "");
15623
15874
  }
@@ -15652,17 +15903,17 @@ function MaskedInput({
15652
15903
  });
15653
15904
  if (value.length === 0) {
15654
15905
  if (placeholder.length === 0) {
15655
- return /* @__PURE__ */ React65.createElement(Text55, { inverse: true }, " ");
15906
+ return /* @__PURE__ */ React66.createElement(Text56, { inverse: true }, " ");
15656
15907
  }
15657
- return /* @__PURE__ */ React65.createElement(React65.Fragment, null, /* @__PURE__ */ React65.createElement(Text55, { inverse: true }, placeholder[0]), /* @__PURE__ */ React65.createElement(Text55, { color: FG.faint }, placeholder.slice(1)));
15908
+ return /* @__PURE__ */ React66.createElement(React66.Fragment, null, /* @__PURE__ */ React66.createElement(Text56, { inverse: true }, placeholder[0]), /* @__PURE__ */ React66.createElement(Text56, { color: FG.faint }, placeholder.slice(1)));
15658
15909
  }
15659
- return /* @__PURE__ */ React65.createElement(React65.Fragment, null, /* @__PURE__ */ React65.createElement(Text55, null, mask.repeat(value.length)), /* @__PURE__ */ React65.createElement(Text55, { inverse: true }, " "));
15910
+ return /* @__PURE__ */ React66.createElement(React66.Fragment, null, /* @__PURE__ */ React66.createElement(Text56, null, mask.repeat(value.length)), /* @__PURE__ */ React66.createElement(Text56, { inverse: true }, " "));
15660
15911
  }
15661
15912
 
15662
15913
  // src/cli/ui/Setup.tsx
15663
15914
  function Setup({ onReady }) {
15664
- const [value, setValue] = useState27("");
15665
- const [error, setError] = useState27(null);
15915
+ const [value, setValue] = useState28("");
15916
+ const [error, setError] = useState28(null);
15666
15917
  const { exit: exit2 } = useApp();
15667
15918
  const handleSubmit = (raw) => {
15668
15919
  const trimmed = raw.trim();
@@ -15683,7 +15934,7 @@ function Setup({ onReady }) {
15683
15934
  }
15684
15935
  onReady(trimmed);
15685
15936
  };
15686
- return /* @__PURE__ */ React66.createElement(Box52, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React66.createElement(Box52, null, /* @__PURE__ */ React66.createElement(Text56, { bold: true, color: GRADIENT[0] }, GLYPH.brand), /* @__PURE__ */ React66.createElement(Text56, null, " "), /* @__PURE__ */ React66.createElement(Text56, { bold: true }, "Welcome to "), /* @__PURE__ */ React66.createElement(Text56, { bold: true, color: GRADIENT[2] }, "REASONIX")), /* @__PURE__ */ React66.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React66.createElement(Text56, { color: COLOR.info }, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React66.createElement(Box52, null, /* @__PURE__ */ React66.createElement(Text56, { dimColor: true }, " sign up at \xB7 "), /* @__PURE__ */ React66.createElement(Text56, { color: COLOR.primary }, "https://platform.deepseek.com/api_keys")), /* @__PURE__ */ React66.createElement(Box52, null, /* @__PURE__ */ React66.createElement(Text56, { dimColor: true }, " saved to "), /* @__PURE__ */ React66.createElement(Text56, { dimColor: true }, defaultConfigPath())), /* @__PURE__ */ React66.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React66.createElement(Text56, { bold: true, color: COLOR.brand }, GLYPH.bar), /* @__PURE__ */ React66.createElement(Text56, { bold: true, color: COLOR.primary }, " \u203A "), /* @__PURE__ */ React66.createElement(
15937
+ return /* @__PURE__ */ React67.createElement(Box53, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React67.createElement(Box53, null, /* @__PURE__ */ React67.createElement(Text57, { bold: true, color: GRADIENT[0] }, GLYPH.brand), /* @__PURE__ */ React67.createElement(Text57, null, " "), /* @__PURE__ */ React67.createElement(Text57, { bold: true }, "Welcome to "), /* @__PURE__ */ React67.createElement(Text57, { bold: true, color: GRADIENT[2] }, "REASONIX")), /* @__PURE__ */ React67.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React67.createElement(Text57, { color: COLOR.info }, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React67.createElement(Box53, null, /* @__PURE__ */ React67.createElement(Text57, { dimColor: true }, " sign up at \xB7 "), /* @__PURE__ */ React67.createElement(Text57, { color: COLOR.primary }, "https://platform.deepseek.com/api_keys")), /* @__PURE__ */ React67.createElement(Box53, null, /* @__PURE__ */ React67.createElement(Text57, { dimColor: true }, " saved to "), /* @__PURE__ */ React67.createElement(Text57, { dimColor: true }, defaultConfigPath())), /* @__PURE__ */ React67.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React67.createElement(Text57, { bold: true, color: COLOR.brand }, GLYPH.bar), /* @__PURE__ */ React67.createElement(Text57, { bold: true, color: COLOR.primary }, " \u203A "), /* @__PURE__ */ React67.createElement(
15687
15938
  MaskedInput,
15688
15939
  {
15689
15940
  value,
@@ -15692,7 +15943,7 @@ function Setup({ onReady }) {
15692
15943
  mask: "\u2022",
15693
15944
  placeholder: "sk-..."
15694
15945
  }
15695
- )), error ? /* @__PURE__ */ React66.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React66.createElement(Text56, { color: COLOR.err, bold: true }, GLYPH.err), /* @__PURE__ */ React66.createElement(Text56, { color: COLOR.err }, ` ${error}`)) : value ? /* @__PURE__ */ React66.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React66.createElement(Text56, { dimColor: true }, ` preview \xB7 ${redactKey(value)}`)) : null, /* @__PURE__ */ React66.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React66.createElement(Text56, { dimColor: true }, " /exit to abort")));
15946
+ )), error ? /* @__PURE__ */ React67.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React67.createElement(Text57, { color: COLOR.err, bold: true }, GLYPH.err), /* @__PURE__ */ React67.createElement(Text57, { color: COLOR.err }, ` ${error}`)) : value ? /* @__PURE__ */ React67.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React67.createElement(Text57, { dimColor: true }, ` preview \xB7 ${redactKey(value)}`)) : null, /* @__PURE__ */ React67.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React67.createElement(Text57, { dimColor: true }, " /exit to abort")));
15696
15947
  }
15697
15948
 
15698
15949
  // src/cli/ui/drain-tty.ts
@@ -15928,13 +16179,13 @@ function Root({
15928
16179
  mcpRuntime,
15929
16180
  ...appProps
15930
16181
  }) {
15931
- const [key, setKey] = useState28(initialKey);
15932
- const [pickerOpen, setPickerOpen] = useState28(showPicker);
15933
- const [activeSession, setActiveSession] = useState28(appProps.session);
16182
+ const [key, setKey] = useState29(initialKey);
16183
+ const [pickerOpen, setPickerOpen] = useState29(showPicker);
16184
+ const [activeSession, setActiveSession] = useState29(appProps.session);
15934
16185
  const workspaceRoot = appProps.codeMode?.rootDir ?? process.cwd();
15935
- const [sessions2, setSessions] = useState28(() => listSessionsForWorkspace(workspaceRoot));
16186
+ const [sessions2, setSessions] = useState29(() => listSessionsForWorkspace(workspaceRoot));
15936
16187
  if (!key) {
15937
- return /* @__PURE__ */ React67.createElement(
16188
+ return /* @__PURE__ */ React68.createElement(
15938
16189
  Setup,
15939
16190
  {
15940
16191
  onReady: (k) => {
@@ -15946,7 +16197,7 @@ function Root({
15946
16197
  }
15947
16198
  process.env.DEEPSEEK_API_KEY = key;
15948
16199
  if (pickerOpen) {
15949
- return /* @__PURE__ */ React67.createElement(KeystrokeProvider, null, /* @__PURE__ */ React67.createElement(
16200
+ return /* @__PURE__ */ React68.createElement(KeystrokeProvider, null, /* @__PURE__ */ React68.createElement(
15950
16201
  SessionPicker,
15951
16202
  {
15952
16203
  sessions: sessions2,
@@ -15979,7 +16230,7 @@ function Root({
15979
16230
  }
15980
16231
  ));
15981
16232
  }
15982
- return /* @__PURE__ */ React67.createElement(KeystrokeProvider, null, /* @__PURE__ */ React67.createElement(
16233
+ return /* @__PURE__ */ React68.createElement(KeystrokeProvider, null, /* @__PURE__ */ React68.createElement(
15983
16234
  App,
15984
16235
  {
15985
16236
  key: activeSession ?? "__new__",
@@ -16038,7 +16289,7 @@ async function chatCommand(opts) {
16038
16289
  const showPicker = !opts.session && !opts.forceResume && listSessionsForWorkspace(launchWorkspace).length > 0;
16039
16290
  markPhase("ink_render_call");
16040
16291
  const { waitUntilExit } = render(
16041
- /* @__PURE__ */ React67.createElement(
16292
+ /* @__PURE__ */ React68.createElement(
16042
16293
  Root,
16043
16294
  {
16044
16295
  initialKey,
@@ -16079,4 +16330,4 @@ async function chatCommand(opts) {
16079
16330
  export {
16080
16331
  chatCommand
16081
16332
  };
16082
- //# sourceMappingURL=chunk-MSKUP6PD.js.map
16333
+ //# sourceMappingURL=chunk-4PNXH2MH.js.map