reasonix 0.13.1 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -7767,12 +7767,12 @@ function formatLogSize(path5 = defaultUsageLogPath()) {
7767
7767
  // src/cli/commands/chat.tsx
7768
7768
  import { existsSync as existsSync23, statSync as statSync13 } from "fs";
7769
7769
  import { render } from "ink";
7770
- import React29, { useState as useState12 } from "react";
7770
+ import React30, { useState as useState12 } from "react";
7771
7771
 
7772
7772
  // src/cli/ui/App.tsx
7773
7773
  import * as pathMod7 from "path";
7774
- import { Box as Box24, Text as Text22, useStdout as useStdout9 } from "ink";
7775
- import React26, { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo3, useRef as useRef6, useState as useState10 } from "react";
7774
+ import { Box as Box25, Text as Text23, useStdout as useStdout9 } from "ink";
7775
+ import React27, { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo3, useRef as useRef6, useState as useState10 } from "react";
7776
7776
 
7777
7777
  // src/code/pending-edits.ts
7778
7778
  import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync11, unlinkSync as unlinkSync3, writeFileSync as writeFileSync6 } from "fs";
@@ -11055,6 +11055,17 @@ var StdinReader = class {
11055
11055
  /** Buffer for paste content. */
11056
11056
  pasteBuf = "";
11057
11057
  escTimer = null;
11058
+ // Deferred-dispatch handle paired with `escTimer`. The timer
11059
+ // queues an Immediate that runs in the event loop's CHECK phase —
11060
+ // i.e. AFTER the POLL phase where stdin 'data' events fire — so
11061
+ // a multi-byte sequence whose chunks queued up while the loop was
11062
+ // blocked (heavy render, etc.) gets a chance to be processed
11063
+ // BEFORE we emit a bogus standalone-Esc. Fixes the "I didn't press
11064
+ // Esc but it aborted the turn" class of bug: previously the timer's
11065
+ // setTimeout callback ran in the timers phase ahead of poll, so a
11066
+ // split sequence like `\x1b` + `[A` would dispatch escape+upArrow
11067
+ // even though the user only pressed Up.
11068
+ escImmediate = null;
11058
11069
  started = false;
11059
11070
  /** The actual `data` listener — kept as a field so `stop()` can detach it. */
11060
11071
  listener = null;
@@ -11116,14 +11127,22 @@ var StdinReader = class {
11116
11127
  clearTimeout(this.escTimer);
11117
11128
  this.escTimer = null;
11118
11129
  }
11130
+ if (this.escImmediate) {
11131
+ clearImmediate(this.escImmediate);
11132
+ this.escImmediate = null;
11133
+ }
11119
11134
  }
11120
11135
  scheduleEscTimer() {
11121
11136
  this.cancelEscTimer();
11122
11137
  this.escTimer = setTimeout(() => {
11123
- if (this.state === "esc") {
11124
- this.state = "idle";
11125
- this.dispatch({ input: "", escape: true });
11126
- }
11138
+ this.escTimer = null;
11139
+ this.escImmediate = setImmediate(() => {
11140
+ this.escImmediate = null;
11141
+ if (this.state === "esc") {
11142
+ this.state = "idle";
11143
+ this.dispatch({ input: "", escape: true });
11144
+ }
11145
+ });
11127
11146
  }, ESC_TIMEOUT_MS);
11128
11147
  }
11129
11148
  handleChunk(chunk) {
@@ -14752,6 +14771,279 @@ function appendBulletToFile(path5, note, newFileHeader) {
14752
14771
  return { path: path5, created: false };
14753
14772
  }
14754
14773
 
14774
+ // src/cli/ui/log-rows.tsx
14775
+ import { Box as Box24, Text as Text22 } from "ink";
14776
+ import React26 from "react";
14777
+ function wrapToWidth(text, width) {
14778
+ if (width <= 0) return [text];
14779
+ const out = [];
14780
+ for (const line of text.split("\n")) {
14781
+ if (line.length === 0) {
14782
+ out.push("");
14783
+ continue;
14784
+ }
14785
+ if (line.length <= width) {
14786
+ out.push(line);
14787
+ continue;
14788
+ }
14789
+ let i = 0;
14790
+ while (i < line.length) {
14791
+ out.push(line.slice(i, i + width));
14792
+ i += width;
14793
+ }
14794
+ }
14795
+ return out;
14796
+ }
14797
+ function itemRows(item) {
14798
+ return item.kind === "row" ? 1 : item.rows;
14799
+ }
14800
+ function detectInfoTone(text) {
14801
+ const m = text.match(/^([▸▶▲⚠✓✗✖↻ⓘ])\s*(.*)$/s);
14802
+ const lead = m?.[1] ?? "\u25B8";
14803
+ const body = m?.[2] ?? text;
14804
+ let color2 = COLOR.info;
14805
+ if (lead === "\u25B2" || lead === "\u26A0") color2 = COLOR.warn;
14806
+ else if (lead === "\u2713") color2 = COLOR.ok;
14807
+ else if (lead === "\u2717" || lead === "\u2716") color2 = COLOR.err;
14808
+ else if (lead === "\u21BB") color2 = COLOR.primary;
14809
+ return { lead, color: color2, body };
14810
+ }
14811
+ function AccentRow({
14812
+ color: color2,
14813
+ prefix,
14814
+ body,
14815
+ bodyColor,
14816
+ bodyDim
14817
+ }) {
14818
+ return /* @__PURE__ */ React26.createElement(
14819
+ Box24,
14820
+ {
14821
+ borderStyle: "single",
14822
+ borderTop: false,
14823
+ borderRight: false,
14824
+ borderBottom: false,
14825
+ borderColor: color2,
14826
+ paddingLeft: 1
14827
+ },
14828
+ prefix,
14829
+ /* @__PURE__ */ React26.createElement(Text22, { color: bodyColor, dimColor: bodyDim }, body)
14830
+ );
14831
+ }
14832
+ function accentRows(baseId, glyph, glyphColor, text, bodyColor, bodyDim, width) {
14833
+ const indentCells = 1 + 1 + glyph.length + 2;
14834
+ const inner = Math.max(8, width - indentCells);
14835
+ const lines = wrapToWidth(text, inner);
14836
+ return lines.map((line, i) => ({
14837
+ kind: "row",
14838
+ id: `${baseId}/${i}`,
14839
+ content: i === 0 ? /* @__PURE__ */ React26.createElement(
14840
+ AccentRow,
14841
+ {
14842
+ color: glyphColor,
14843
+ prefix: /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(Text22, { color: glyphColor, bold: true }, glyph), /* @__PURE__ */ React26.createElement(Text22, null, " ")),
14844
+ body: line,
14845
+ bodyColor,
14846
+ bodyDim
14847
+ }
14848
+ ) : /* @__PURE__ */ React26.createElement(
14849
+ AccentRow,
14850
+ {
14851
+ color: glyphColor,
14852
+ prefix: /* @__PURE__ */ React26.createElement(Text22, null, " ".repeat(glyph.length + 2)),
14853
+ body: line,
14854
+ bodyColor,
14855
+ bodyDim
14856
+ }
14857
+ )
14858
+ }));
14859
+ }
14860
+ function assistantToRows(event, projectRoot, width = 80) {
14861
+ const hasComplexSub = event.branch || event.reasoning || event.planState && Object.keys(event.planState).length > 0;
14862
+ if (hasComplexSub) {
14863
+ return [
14864
+ {
14865
+ kind: "block",
14866
+ id: event.id,
14867
+ rows: estimatedHeight(event),
14868
+ content: /* @__PURE__ */ React26.createElement(EventRow, { event, projectRoot })
14869
+ }
14870
+ ];
14871
+ }
14872
+ const items = [];
14873
+ items.push({
14874
+ kind: "row",
14875
+ id: `${event.id}/spacer-top`,
14876
+ content: /* @__PURE__ */ React26.createElement(Text22, null, " ")
14877
+ });
14878
+ items.push({
14879
+ kind: "row",
14880
+ id: `${event.id}/head`,
14881
+ content: /* @__PURE__ */ React26.createElement(Box24, null, /* @__PURE__ */ React26.createElement(Text22, { color: COLOR.assistant, bold: true }, "\u25C6"), event.stats ? /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(Text22, null, " "), /* @__PURE__ */ React26.createElement(Text22, { backgroundColor: COLOR.assistant, color: "black", bold: true }, ` ${event.stats.model.replace(/^deepseek-/, "")} `)) : null)
14882
+ });
14883
+ const body = event.text || "(empty body \u2014 likely tool-call only)";
14884
+ const dim = !event.text;
14885
+ items.push(...accentRows(event.id, "", COLOR.assistant, body, COLOR.assistant, dim, width));
14886
+ if (event.repair) {
14887
+ items.push({
14888
+ kind: "row",
14889
+ id: `${event.id}/repair`,
14890
+ content: /* @__PURE__ */ React26.createElement(Box24, { paddingLeft: 2 }, /* @__PURE__ */ React26.createElement(Text22, { color: COLOR.accent }, event.repair))
14891
+ });
14892
+ }
14893
+ if (event.stats) {
14894
+ const hit = (event.stats.cacheHitRatio * 100).toFixed(1);
14895
+ const hitColor = event.stats.cacheHitRatio >= 0.7 ? "#4ade80" : event.stats.cacheHitRatio >= 0.4 ? "#fcd34d" : "#f87171";
14896
+ items.push({
14897
+ kind: "row",
14898
+ id: `${event.id}/stats`,
14899
+ content: /* @__PURE__ */ React26.createElement(Box24, { paddingLeft: 2 }, /* @__PURE__ */ React26.createElement(Text22, { color: hitColor, bold: true }, `\u232C ${hit}%`), /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React26.createElement(Text22, { color: "#94a3b8" }, "in "), /* @__PURE__ */ React26.createElement(Text22, { color: "#67e8f9", bold: true }, event.stats.usage.promptTokens), /* @__PURE__ */ React26.createElement(Text22, { color: "#94a3b8" }, " \u2192 out "), /* @__PURE__ */ React26.createElement(Text22, { color: "#c4b5fd", bold: true }, event.stats.usage.completionTokens), /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React26.createElement(Text22, { color: "#86efac", bold: true }, `$${event.stats.cost.toFixed(6)}`))
14900
+ });
14901
+ }
14902
+ return items;
14903
+ }
14904
+ function eventToItems(event, projectRoot, width = 80) {
14905
+ if (event.role === "info") {
14906
+ const { lead, color: color2, body } = detectInfoTone(event.text);
14907
+ return accentRows(event.id, lead, color2, body, void 0, true, width);
14908
+ }
14909
+ if (event.role === "warning") {
14910
+ return accentRows(event.id, "\u25B2 warn", COLOR.warn, event.text, COLOR.warn, false, width);
14911
+ }
14912
+ if (event.role === "error") {
14913
+ return accentRows(event.id, "\u2726 error", COLOR.err, event.text, COLOR.err, false, width);
14914
+ }
14915
+ if (event.role === "assistant" && !event.streaming) {
14916
+ return assistantToRows(event, projectRoot, width);
14917
+ }
14918
+ if (event.role === "step-progress") {
14919
+ const sp = event.stepProgress;
14920
+ const counter = sp && sp.total > 0 ? `${sp.completed}/${sp.total}` : "";
14921
+ const label = sp?.title ? `${sp.stepId} \xB7 ${sp.title}` : sp?.stepId ?? "";
14922
+ const rows = [];
14923
+ rows.push({
14924
+ kind: "row",
14925
+ id: `${event.id}/spacer`,
14926
+ content: /* @__PURE__ */ React26.createElement(Text22, null, " ")
14927
+ });
14928
+ rows.push({
14929
+ kind: "row",
14930
+ id: `${event.id}/head`,
14931
+ content: /* @__PURE__ */ React26.createElement(Box24, null, /* @__PURE__ */ React26.createElement(Text22, { backgroundColor: "#4ade80", color: "black", bold: true }, " \u2713 STEP "), counter ? /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(Text22, null, " "), /* @__PURE__ */ React26.createElement(Text22, { color: "#4ade80", bold: true }, counter)) : null, /* @__PURE__ */ React26.createElement(Text22, null, " "), /* @__PURE__ */ React26.createElement(Text22, { color: "#86efac" }, label))
14932
+ });
14933
+ if (event.text) {
14934
+ for (const [i, line] of event.text.split("\n").entries()) {
14935
+ rows.push({
14936
+ kind: "row",
14937
+ id: `${event.id}/body/${i}`,
14938
+ content: /* @__PURE__ */ React26.createElement(Box24, { paddingLeft: 2 }, /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, line))
14939
+ });
14940
+ }
14941
+ }
14942
+ if (sp?.notes) {
14943
+ rows.push({
14944
+ kind: "row",
14945
+ id: `${event.id}/notes`,
14946
+ content: /* @__PURE__ */ React26.createElement(Box24, { paddingLeft: 2 }, /* @__PURE__ */ React26.createElement(Text22, { color: "#fbbf24", dimColor: true }, `note: ${sp.notes}`))
14947
+ });
14948
+ }
14949
+ return rows;
14950
+ }
14951
+ return [
14952
+ {
14953
+ kind: "block",
14954
+ id: event.id,
14955
+ rows: estimatedHeight(event),
14956
+ content: /* @__PURE__ */ React26.createElement(EventRow, { event, projectRoot })
14957
+ }
14958
+ ];
14959
+ }
14960
+ function estimatedHeight(e) {
14961
+ const text = e.text ?? "";
14962
+ const wrapLines = Math.max(0, Math.floor(text.length / 80));
14963
+ if (e.role === "user") return 3 + wrapLines;
14964
+ if (e.role === "assistant") {
14965
+ let h = 4 + wrapLines;
14966
+ if (e.reasoning) h += 3;
14967
+ if (e.branch) h += 4;
14968
+ return h;
14969
+ }
14970
+ if (e.role === "tool") {
14971
+ const isEditFile = e.toolName === "edit_file" || e.toolName?.endsWith("_edit_file");
14972
+ if (isEditFile) {
14973
+ const diffLines = (text.match(/\n/g)?.length ?? 0) + 1;
14974
+ return 6 + Math.min(20, diffLines);
14975
+ }
14976
+ return 2;
14977
+ }
14978
+ if (e.role === "plan" || e.role === "plan-replay" || e.role === "plan-resumed") return 10;
14979
+ if (e.role === "ctx-breakdown") return 7;
14980
+ return 2;
14981
+ }
14982
+ function sliceLogItems(items, available, scrollOffsetRows) {
14983
+ if (items.length === 0) {
14984
+ return { items: [], maxScrollRows: 0, totalRows: 0 };
14985
+ }
14986
+ const heights = items.map(itemRows);
14987
+ const totalRows = heights.reduce((a, b) => a + b, 0);
14988
+ const maxScrollRows = Math.max(0, totalRows - available);
14989
+ const offset = Math.max(0, Math.min(scrollOffsetRows, maxScrollRows));
14990
+ const viewportBottom = totalRows - offset;
14991
+ const viewportTop = Math.max(0, viewportBottom - available);
14992
+ let cursor = 0;
14993
+ let firstIdx = -1;
14994
+ let lastIdx = -1;
14995
+ for (let i = 0; i < items.length; i++) {
14996
+ const eStart = cursor;
14997
+ const eEnd = cursor + heights[i];
14998
+ cursor = eEnd;
14999
+ if (eEnd <= viewportTop) continue;
15000
+ if (eStart >= viewportBottom) break;
15001
+ if (firstIdx === -1) firstIdx = i;
15002
+ lastIdx = i;
15003
+ }
15004
+ if (firstIdx === -1) {
15005
+ return { items: [items[items.length - 1]], maxScrollRows, totalRows };
15006
+ }
15007
+ return {
15008
+ items: items.slice(firstIdx, lastIdx + 1),
15009
+ maxScrollRows,
15010
+ totalRows
15011
+ };
15012
+ }
15013
+ function renderLogItem(item) {
15014
+ if (item.kind === "row") {
15015
+ return /* @__PURE__ */ React26.createElement(Box24, { key: item.id, height: 1, flexShrink: 0 }, item.content);
15016
+ }
15017
+ return /* @__PURE__ */ React26.createElement(Box24, { key: item.id, flexShrink: 0 }, item.content);
15018
+ }
15019
+ function ScrollBar({
15020
+ height,
15021
+ totalRows,
15022
+ viewportRows,
15023
+ scrollOffsetRows
15024
+ }) {
15025
+ if (totalRows <= viewportRows || height <= 0) return null;
15026
+ const maxScroll = Math.max(0, totalRows - viewportRows);
15027
+ const offset = Math.max(0, Math.min(scrollOffsetRows, maxScroll));
15028
+ const viewportBottomFrac = (totalRows - offset) / totalRows;
15029
+ const viewportTopFrac = Math.max(0, viewportBottomFrac - viewportRows / totalRows);
15030
+ const thumbStart = Math.floor(viewportTopFrac * height);
15031
+ const thumbEnd = Math.min(height, Math.ceil(viewportBottomFrac * height));
15032
+ const thumbSize = Math.max(1, thumbEnd - thumbStart);
15033
+ const cells = [];
15034
+ for (let i = 0; i < height; i++) {
15035
+ const inThumb = i >= thumbStart && i < thumbStart + thumbSize;
15036
+ cells.push(
15037
+ /* @__PURE__ */ React26.createElement(Text22, { key: `sb-${i}`, color: inThumb ? COLOR.brand : COLOR.info, dimColor: !inThumb }, inThumb ? "\u2588" : "\u2502")
15038
+ );
15039
+ }
15040
+ return /* @__PURE__ */ React26.createElement(Box24, { flexDirection: "column", width: 1, flexShrink: 0 }, cells);
15041
+ }
15042
+ function BottomHint({ rowsBelow }) {
15043
+ if (rowsBelow <= 0) return null;
15044
+ return /* @__PURE__ */ React26.createElement(Box24, { height: 1, flexShrink: 0 }, /* @__PURE__ */ React26.createElement(Text22, { color: COLOR.primary, bold: true }, "\u2193"), /* @__PURE__ */ React26.createElement(Text22, null, " "), /* @__PURE__ */ React26.createElement(Text22, { color: COLOR.primary }, `${rowsBelow} row${rowsBelow === 1 ? "" : "s"} below`), /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, " \xB7 End to jump \xB7 wheel-down to scroll"));
15045
+ }
15046
+
14755
15047
  // src/cli/ui/loop.ts
14756
15048
  var MIN_LOOP_INTERVAL_MS = 5e3;
14757
15049
  var MAX_LOOP_INTERVAL_MS = 6 * 60 * 6e4;
@@ -18262,63 +18554,16 @@ var FLUSH_INTERVAL_MS = (() => {
18262
18554
  return Math.round(parsed);
18263
18555
  })();
18264
18556
  var PLAIN_UI = process.env.REASONIX_UI === "plain";
18265
- function heightOfEvent(e) {
18266
- const text = e.text ?? "";
18267
- const wrapLines = Math.max(0, Math.floor(text.length / 80));
18268
- if (e.role === "user") return 3 + wrapLines;
18269
- if (e.role === "assistant") {
18270
- let h = 4 + wrapLines;
18271
- if (e.reasoning) h += 3;
18272
- if (e.branch) h += 4;
18273
- return h;
18274
- }
18275
- if (e.role === "tool") {
18276
- const isEditFile = e.toolName === "edit_file" || e.toolName?.endsWith("_edit_file");
18277
- if (isEditFile) {
18278
- const diffLines = (text.match(/\n/g)?.length ?? 0) + 1;
18279
- return 6 + Math.min(20, diffLines);
18280
- }
18281
- return 2;
18282
- }
18283
- if (e.role === "info" || e.role === "warning") return 2;
18284
- if (e.role === "error") return 2 + wrapLines;
18285
- if (e.role === "plan" || e.role === "plan-replay" || e.role === "plan-resumed") return 10;
18286
- if (e.role === "ctx-breakdown") return 7;
18287
- if (e.role === "step-progress") return 1;
18288
- return 2;
18289
- }
18290
- function sliceVisibleEvents(events, termRows, scrollOffset = 0) {
18291
- const reservedRows = 10;
18292
- const available = Math.max(8, termRows - reservedRows);
18293
- if (events.length === 0) {
18294
- return { events: [], maxScrollEvents: 0 };
18295
- }
18296
- const maxScrollEvents = Math.max(0, events.length - 1);
18297
- const offset = Math.max(0, Math.min(scrollOffset, maxScrollEvents));
18298
- const endIdx = events.length - offset;
18299
- let startIdx = endIdx - 1;
18300
- let used = heightOfEvent(events[startIdx]);
18301
- for (let i = endIdx - 2; i >= 0; i--) {
18302
- const h = heightOfEvent(events[i]);
18303
- if (used + h > available) break;
18304
- used += h;
18305
- startIdx = i;
18306
- }
18307
- return {
18308
- events: events.slice(startIdx, endIdx),
18309
- maxScrollEvents
18310
- };
18311
- }
18312
18557
  function LoopStatusRow({
18313
18558
  loop: loop2
18314
18559
  }) {
18315
- const [, setTick] = React26.useState(0);
18316
- React26.useEffect(() => {
18560
+ const [, setTick] = React27.useState(0);
18561
+ React27.useEffect(() => {
18317
18562
  const id = setInterval(() => setTick((t2) => t2 + 1), 1e3);
18318
18563
  return () => clearInterval(id);
18319
18564
  }, []);
18320
18565
  const nextFireMs = Math.max(0, loop2.nextFireAt - Date.now());
18321
- return /* @__PURE__ */ React26.createElement(Box24, null, /* @__PURE__ */ React26.createElement(Text22, { color: "cyan" }, `\u25B8 ${formatLoopStatus(loop2.prompt, nextFireMs, loop2.iter)} \xB7 /loop stop or type to cancel`));
18566
+ return /* @__PURE__ */ React27.createElement(Box25, null, /* @__PURE__ */ React27.createElement(Text23, { color: "cyan" }, `\u25B8 ${formatLoopStatus(loop2.prompt, nextFireMs, loop2.iter)} \xB7 /loop stop or type to cancel`));
18322
18567
  }
18323
18568
  function App({
18324
18569
  model: model2,
@@ -18342,6 +18587,8 @@ function App({
18342
18587
  const scrollAnimRef = useRef6(null);
18343
18588
  const scrollTargetRef = useRef6(0);
18344
18589
  const scrollDisplayedRef = useRef6(0);
18590
+ const scrollMaxRowsRef = useRef6(0);
18591
+ const lastTotalRowsRef = useRef6(0);
18345
18592
  useEffect7(() => {
18346
18593
  return () => {
18347
18594
  if (scrollAnimRef.current) {
@@ -18376,16 +18623,24 @@ function App({
18376
18623
  }, []);
18377
18624
  const lastHistoricalLenRef = useRef6(0);
18378
18625
  useEffect7(() => {
18379
- const prev = lastHistoricalLenRef.current;
18380
- const cur = historical.length;
18381
- lastHistoricalLenRef.current = cur;
18382
- if (cur > prev && scrollTargetRef.current > 0) {
18383
- const delta = cur - prev;
18384
- scrollTargetRef.current += delta;
18385
- scrollDisplayedRef.current += delta;
18386
- setLogScrollOffset((p) => p + delta);
18387
- } else if (cur < prev) {
18388
- const newMax = Math.max(0, cur - 1);
18626
+ const prevLen = lastHistoricalLenRef.current;
18627
+ const curLen = historical.length;
18628
+ lastHistoricalLenRef.current = curLen;
18629
+ if (curLen > prevLen && scrollTargetRef.current > 0) {
18630
+ const cols = stdout4?.columns ?? 80;
18631
+ let deltaRows = 0;
18632
+ for (let i = prevLen; i < curLen; i++) {
18633
+ for (const it of eventToItems(historical[i], void 0, cols)) {
18634
+ deltaRows += it.kind === "row" ? 1 : it.rows;
18635
+ }
18636
+ }
18637
+ if (deltaRows > 0) {
18638
+ scrollTargetRef.current += deltaRows;
18639
+ scrollDisplayedRef.current += deltaRows;
18640
+ setLogScrollOffset((p) => p + deltaRows);
18641
+ }
18642
+ } else if (curLen < prevLen) {
18643
+ const newMax = scrollMaxRowsRef.current;
18389
18644
  if (scrollTargetRef.current > newMax) {
18390
18645
  scrollTargetRef.current = newMax;
18391
18646
  scrollDisplayedRef.current = newMax;
@@ -18393,6 +18648,14 @@ function App({
18393
18648
  }
18394
18649
  }
18395
18650
  }, [historical]);
18651
+ useEffect7(() => {
18652
+ const max = scrollMaxRowsRef.current;
18653
+ if (logScrollOffset > max) {
18654
+ scrollTargetRef.current = max;
18655
+ scrollDisplayedRef.current = max;
18656
+ setLogScrollOffset(max);
18657
+ }
18658
+ }, [logScrollOffset]);
18396
18659
  const [input, setInput] = useState10("");
18397
18660
  const [busy, setBusy] = useState10(false);
18398
18661
  const abortedThisTurn = useRef6(false);
@@ -18931,25 +19194,26 @@ function App({
18931
19194
  if (ev.paste) {
18932
19195
  return;
18933
19196
  }
18934
- const maxOffset = Math.max(0, historical.length - 1);
19197
+ const maxOffset = scrollMaxRowsRef.current;
19198
+ const viewportRows = Math.max(8, (stdout4?.rows ?? 30) - 10);
18935
19199
  if (ev.mouseScrollUp) {
18936
19200
  if (maxOffset === 0) return;
18937
- animateScrollTo((prev) => Math.min(maxOffset, prev + 1));
19201
+ animateScrollTo((prev) => Math.min(maxOffset, prev + 3));
18938
19202
  return;
18939
19203
  }
18940
19204
  if (ev.mouseScrollDown) {
18941
19205
  if (maxOffset === 0) return;
18942
- animateScrollTo((prev) => Math.max(0, prev - 1));
19206
+ animateScrollTo((prev) => Math.max(0, prev - 3));
18943
19207
  return;
18944
19208
  }
18945
19209
  if (ev.pageUp) {
18946
19210
  if (maxOffset === 0) return;
18947
- animateScrollTo((prev) => Math.min(maxOffset, prev + 3));
19211
+ animateScrollTo((prev) => Math.min(maxOffset, prev + (viewportRows - 2)));
18948
19212
  return;
18949
19213
  }
18950
19214
  if (ev.pageDown) {
18951
19215
  if (maxOffset === 0) return;
18952
- animateScrollTo((prev) => Math.max(0, prev - 3));
19216
+ animateScrollTo((prev) => Math.max(0, prev - (viewportRows - 2)));
18953
19217
  return;
18954
19218
  }
18955
19219
  if (ev.home) {
@@ -20902,7 +21166,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
20902
21166
  async (choice) => handleReviseConfirmRef.current(choice),
20903
21167
  []
20904
21168
  );
20905
- return /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(
21169
+ return /* @__PURE__ */ React27.createElement(React27.Fragment, null, /* @__PURE__ */ React27.createElement(
20906
21170
  TickerProvider,
20907
21171
  {
20908
21172
  disabled: PLAIN_UI || isResizing || !!pendingPlan || !!pendingShell || !!pendingWorkspace || !!pendingEditReview || walkthroughActive || !!pendingCheckpoint || !!stagedCheckpointRevise || !!pendingChoice || !!stagedChoiceCustom || !!pendingRevision || // Idle gate: when nothing is actively happening, suspend the
@@ -20915,15 +21179,15 @@ Continue executing from the next pending step. Call mark_step_complete after eac
20915
21179
  // changes (incoming stream, key press, modal popup).
20916
21180
  !busy && !streaming
20917
21181
  },
20918
- /* @__PURE__ */ React26.createElement(
20919
- Box24,
21182
+ /* @__PURE__ */ React27.createElement(
21183
+ Box25,
20920
21184
  {
20921
21185
  flexDirection: "column",
20922
21186
  height: stdout4?.rows ?? 30,
20923
21187
  width: stdout4?.columns ?? 80,
20924
21188
  overflow: "hidden"
20925
21189
  },
20926
- /* @__PURE__ */ React26.createElement(
21190
+ /* @__PURE__ */ React27.createElement(
20927
21191
  StatsPanel,
20928
21192
  {
20929
21193
  summary,
@@ -20944,48 +21208,71 @@ Continue executing from the next pending step. Call mark_step_complete after eac
20944
21208
  sessionName: session ?? null
20945
21209
  }
20946
21210
  ),
20947
- /* @__PURE__ */ React26.createElement(
20948
- Box24,
21211
+ /* @__PURE__ */ React27.createElement(
21212
+ Box25,
20949
21213
  {
20950
- flexDirection: "column",
20951
- justifyContent: logScrollOffset === 0 ? "flex-end" : "flex-start",
21214
+ flexDirection: "row",
20952
21215
  height: pendingShell || pendingWorkspace || pendingPlan || pendingEditReview || pendingCheckpoint || stagedCheckpointRevise || stagedInput || stagedChoiceCustom || pendingChoice || pendingRevision || walkthroughActive ? 0 : Math.max(5, (stdout4?.rows ?? 30) - 9),
20953
21216
  overflow: "hidden"
20954
21217
  },
20955
- (() => {
20956
- const slice = sliceVisibleEvents(historical, stdout4?.rows ?? 30, logScrollOffset);
20957
- return /* @__PURE__ */ React26.createElement(React26.Fragment, null, slice.events.map((item) => /* @__PURE__ */ React26.createElement(EventRow, { key: item.id, event: item, projectRoot: currentRootDir })));
20958
- })(),
20959
- !historical.some((e) => e.role === "user" || e.role === "assistant") && !busy && !streaming ? /* @__PURE__ */ React26.createElement(WelcomeBanner, { inCodeMode: !!codeMode, dashboardUrl }) : null,
20960
- !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && streaming ? /* @__PURE__ */ React26.createElement(Box24, { marginY: 1 }, /* @__PURE__ */ React26.createElement(EventRow, { event: streaming, projectRoot: currentRootDir })) : null,
20961
- !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && ongoingTool ? /* @__PURE__ */ React26.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null,
20962
- !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && subagentActivity ? /* @__PURE__ */ React26.createElement(SubagentRow, { activity: subagentActivity }) : null,
20963
- !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !ongoingTool && statusLine ? /* @__PURE__ */ React26.createElement(StatusRow, { text: statusLine }) : null,
20964
- !PLAIN_UI && undoBanner && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision ? /* @__PURE__ */ React26.createElement(UndoBanner, { banner: undoBanner }) : null,
20965
- !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && busy && !streaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React26.createElement(StatusRow, { text: "processing\u2026" }) : null
21218
+ /* @__PURE__ */ React27.createElement(Box25, { flexDirection: "column", flexGrow: 1, overflow: "hidden" }, /* @__PURE__ */ React27.createElement(
21219
+ Box25,
21220
+ {
21221
+ flexDirection: "column",
21222
+ flexGrow: 1,
21223
+ justifyContent: logScrollOffset === 0 ? "flex-end" : "flex-start",
21224
+ overflow: "hidden"
21225
+ },
21226
+ (() => {
21227
+ const reservedRows = 10;
21228
+ const available = Math.max(8, (stdout4?.rows ?? 30) - reservedRows);
21229
+ const cols = stdout4?.columns ?? 80;
21230
+ const items = historical.flatMap((e) => eventToItems(e, currentRootDir, cols));
21231
+ const slice = sliceLogItems(items, available, logScrollOffset);
21232
+ scrollMaxRowsRef.current = slice.maxScrollRows;
21233
+ lastTotalRowsRef.current = slice.totalRows;
21234
+ return /* @__PURE__ */ React27.createElement(React27.Fragment, null, slice.items.map(renderLogItem));
21235
+ })(),
21236
+ !historical.some((e) => e.role === "user" || e.role === "assistant") && !busy && !streaming ? /* @__PURE__ */ React27.createElement(WelcomeBanner, { inCodeMode: !!codeMode, dashboardUrl }) : null,
21237
+ !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && streaming ? /* @__PURE__ */ React27.createElement(Box25, { marginY: 1 }, /* @__PURE__ */ React27.createElement(EventRow, { event: streaming, projectRoot: currentRootDir })) : null,
21238
+ !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && ongoingTool ? /* @__PURE__ */ React27.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null,
21239
+ !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && subagentActivity ? /* @__PURE__ */ React27.createElement(SubagentRow, { activity: subagentActivity }) : null,
21240
+ !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !ongoingTool && statusLine ? /* @__PURE__ */ React27.createElement(StatusRow, { text: statusLine }) : null,
21241
+ !PLAIN_UI && undoBanner && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision ? /* @__PURE__ */ React27.createElement(UndoBanner, { banner: undoBanner }) : null,
21242
+ !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && busy && !streaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React27.createElement(StatusRow, { text: "processing\u2026" }) : null
21243
+ ), /* @__PURE__ */ React27.createElement(BottomHint, { rowsBelow: logScrollOffset })),
21244
+ /* @__PURE__ */ React27.createElement(
21245
+ ScrollBar,
21246
+ {
21247
+ height: Math.max(5, (stdout4?.rows ?? 30) - 9),
21248
+ totalRows: lastTotalRowsRef.current,
21249
+ viewportRows: Math.max(8, (stdout4?.rows ?? 30) - 10),
21250
+ scrollOffsetRows: logScrollOffset
21251
+ }
21252
+ )
20966
21253
  ),
20967
- stagedInput ? /* @__PURE__ */ React26.createElement(
21254
+ stagedInput ? /* @__PURE__ */ React27.createElement(
20968
21255
  PlanRefineInput,
20969
21256
  {
20970
21257
  mode: stagedInput.mode,
20971
21258
  onSubmit: handleStagedInputSubmit,
20972
21259
  onCancel: handleStagedInputCancel
20973
21260
  }
20974
- ) : stagedCheckpointRevise ? /* @__PURE__ */ React26.createElement(
21261
+ ) : stagedCheckpointRevise ? /* @__PURE__ */ React27.createElement(
20975
21262
  PlanRefineInput,
20976
21263
  {
20977
21264
  mode: "checkpoint-revise",
20978
21265
  onSubmit: handleCheckpointReviseSubmit,
20979
21266
  onCancel: handleCheckpointReviseCancel
20980
21267
  }
20981
- ) : stagedChoiceCustom ? /* @__PURE__ */ React26.createElement(
21268
+ ) : stagedChoiceCustom ? /* @__PURE__ */ React27.createElement(
20982
21269
  PlanRefineInput,
20983
21270
  {
20984
21271
  mode: "choice-custom",
20985
21272
  onSubmit: handleChoiceCustomSubmit,
20986
21273
  onCancel: handleChoiceCustomCancel
20987
21274
  }
20988
- ) : pendingChoice ? /* @__PURE__ */ React26.createElement(
21275
+ ) : pendingChoice ? /* @__PURE__ */ React27.createElement(
20989
21276
  ChoiceConfirm,
20990
21277
  {
20991
21278
  question: pendingChoice.question,
@@ -20993,7 +21280,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
20993
21280
  allowCustom: pendingChoice.allowCustom,
20994
21281
  onChoose: stableHandleChoiceConfirm
20995
21282
  }
20996
- ) : pendingRevision ? /* @__PURE__ */ React26.createElement(
21283
+ ) : pendingRevision ? /* @__PURE__ */ React27.createElement(
20997
21284
  PlanReviseConfirm,
20998
21285
  {
20999
21286
  reason: pendingRevision.reason,
@@ -21004,7 +21291,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21004
21291
  summary: pendingRevision.summary,
21005
21292
  onChoose: stableHandleReviseConfirm
21006
21293
  }
21007
- ) : pendingCheckpoint ? /* @__PURE__ */ React26.createElement(
21294
+ ) : pendingCheckpoint ? /* @__PURE__ */ React27.createElement(
21008
21295
  PlanCheckpointConfirm,
21009
21296
  {
21010
21297
  stepId: pendingCheckpoint.stepId,
@@ -21015,7 +21302,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21015
21302
  completedStepIds: completedStepIdsRef.current,
21016
21303
  onChoose: stableHandleCheckpointConfirm
21017
21304
  }
21018
- ) : pendingPlan ? /* @__PURE__ */ React26.createElement(
21305
+ ) : pendingPlan ? /* @__PURE__ */ React27.createElement(
21019
21306
  PlanConfirm,
21020
21307
  {
21021
21308
  plan: pendingPlan,
@@ -21024,7 +21311,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21024
21311
  onChoose: stableHandlePlanConfirm,
21025
21312
  projectRoot: currentRootDir
21026
21313
  }
21027
- ) : pendingShell ? /* @__PURE__ */ React26.createElement(
21314
+ ) : pendingShell ? /* @__PURE__ */ React27.createElement(
21028
21315
  ShellConfirm,
21029
21316
  {
21030
21317
  command: pendingShell.command,
@@ -21032,7 +21319,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21032
21319
  kind: pendingShell.kind,
21033
21320
  onChoose: handleShellConfirm
21034
21321
  }
21035
- ) : pendingWorkspace ? /* @__PURE__ */ React26.createElement(
21322
+ ) : pendingWorkspace ? /* @__PURE__ */ React27.createElement(
21036
21323
  WorkspaceConfirm,
21037
21324
  {
21038
21325
  path: pendingWorkspace.path,
@@ -21040,7 +21327,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21040
21327
  mcpServerCount: mcpServers?.length ?? 0,
21041
21328
  onChoose: handleWorkspaceConfirm
21042
21329
  }
21043
- ) : pendingEditReview ? /* @__PURE__ */ React26.createElement(
21330
+ ) : pendingEditReview ? /* @__PURE__ */ React27.createElement(
21044
21331
  EditConfirm,
21045
21332
  {
21046
21333
  block: pendingEditReview,
@@ -21052,14 +21339,14 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21052
21339
  }
21053
21340
  }
21054
21341
  }
21055
- ) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */ React26.createElement(
21342
+ ) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */ React27.createElement(
21056
21343
  EditConfirm,
21057
21344
  {
21058
21345
  key: `walk-${pendingTick}`,
21059
21346
  block: pendingEdits.current[0],
21060
21347
  onChoose: handleWalkChoice
21061
21348
  }
21062
- ) : /* @__PURE__ */ React26.createElement(React26.Fragment, null, codeMode ? /* @__PURE__ */ React26.createElement(
21349
+ ) : /* @__PURE__ */ React27.createElement(React27.Fragment, null, codeMode ? /* @__PURE__ */ React27.createElement(
21063
21350
  ModeStatusBar,
21064
21351
  {
21065
21352
  editMode,
@@ -21069,7 +21356,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21069
21356
  undoArmed: !!undoBanner || hasUndoable(),
21070
21357
  jobs: codeMode.jobs
21071
21358
  }
21072
- ) : null, activeLoop ? /* @__PURE__ */ React26.createElement(LoopStatusRow, { loop: activeLoop }) : null, /* @__PURE__ */ React26.createElement(
21359
+ ) : null, activeLoop ? /* @__PURE__ */ React27.createElement(LoopStatusRow, { loop: activeLoop }) : null, /* @__PURE__ */ React27.createElement(
21073
21360
  PromptInput,
21074
21361
  {
21075
21362
  value: input,
@@ -21079,14 +21366,14 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21079
21366
  onHistoryPrev: recallPrev,
21080
21367
  onHistoryNext: recallNext
21081
21368
  }
21082
- ), /* @__PURE__ */ React26.createElement(SlashSuggestions, { matches: slashMatches, selectedIndex: slashSelected }), /* @__PURE__ */ React26.createElement(
21369
+ ), /* @__PURE__ */ React27.createElement(SlashSuggestions, { matches: slashMatches, selectedIndex: slashSelected }), /* @__PURE__ */ React27.createElement(
21083
21370
  AtMentionSuggestions,
21084
21371
  {
21085
21372
  matches: atMatches,
21086
21373
  selectedIndex: atSelected,
21087
21374
  query: atPicker?.query ?? ""
21088
21375
  }
21089
- ), slashArgContext ? /* @__PURE__ */ React26.createElement(
21376
+ ), slashArgContext ? /* @__PURE__ */ React27.createElement(
21090
21377
  SlashArgPicker,
21091
21378
  {
21092
21379
  matches: slashArgMatches,
@@ -21101,15 +21388,15 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21101
21388
  }
21102
21389
 
21103
21390
  // src/cli/ui/SessionPicker.tsx
21104
- import { Box as Box25, Text as Text23 } from "ink";
21105
- import React27 from "react";
21391
+ import { Box as Box26, Text as Text24 } from "ink";
21392
+ import React28 from "react";
21106
21393
  function SessionPicker({
21107
21394
  sessionName,
21108
21395
  messageCount,
21109
21396
  lastActive,
21110
21397
  onChoose
21111
21398
  }) {
21112
- return /* @__PURE__ */ React27.createElement(Box25, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React27.createElement(Box25, { marginBottom: 1 }, /* @__PURE__ */ React27.createElement(Text23, { color: COLOR.brand, bold: true }, GLYPH.brand), /* @__PURE__ */ React27.createElement(Text23, null, " "), /* @__PURE__ */ React27.createElement(Text23, { color: COLOR.primary, bold: true }, `"${sessionName}"`), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, ` has ${messageCount} prior message${messageCount === 1 ? "" : "s"}`), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, ` \xB7 last active ${relativeTime2(lastActive)}`)), /* @__PURE__ */ React27.createElement(
21399
+ return /* @__PURE__ */ React28.createElement(Box26, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React28.createElement(Box26, { marginBottom: 1 }, /* @__PURE__ */ React28.createElement(Text24, { color: COLOR.brand, bold: true }, GLYPH.brand), /* @__PURE__ */ React28.createElement(Text24, null, " "), /* @__PURE__ */ React28.createElement(Text24, { color: COLOR.primary, bold: true }, `"${sessionName}"`), /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, ` has ${messageCount} prior message${messageCount === 1 ? "" : "s"}`), /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, ` \xB7 last active ${relativeTime2(lastActive)}`)), /* @__PURE__ */ React28.createElement(
21113
21400
  SingleSelect,
21114
21401
  {
21115
21402
  initialValue: "new",
@@ -21132,7 +21419,7 @@ function SessionPicker({
21132
21419
  ],
21133
21420
  onSubmit: (v) => onChoose(v)
21134
21421
  }
21135
- ), /* @__PURE__ */ React27.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, " \u2191\u2193 navigate \xB7 \u23CE select")));
21422
+ ), /* @__PURE__ */ React28.createElement(Box26, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, " \u2191\u2193 navigate \xB7 \u23CE select")));
21136
21423
  }
21137
21424
  function relativeTime2(date) {
21138
21425
  const ms = Date.now() - date.getTime();
@@ -21148,9 +21435,9 @@ function relativeTime2(date) {
21148
21435
  }
21149
21436
 
21150
21437
  // src/cli/ui/Setup.tsx
21151
- import { Box as Box26, Text as Text24, useApp } from "ink";
21438
+ import { Box as Box27, Text as Text25, useApp } from "ink";
21152
21439
  import TextInput from "ink-text-input";
21153
- import React28, { useState as useState11 } from "react";
21440
+ import React29, { useState as useState11 } from "react";
21154
21441
  function Setup({ onReady }) {
21155
21442
  const [value, setValue] = useState11("");
21156
21443
  const [error, setError] = useState11(null);
@@ -21174,7 +21461,7 @@ function Setup({ onReady }) {
21174
21461
  }
21175
21462
  onReady(trimmed);
21176
21463
  };
21177
- return /* @__PURE__ */ React28.createElement(Box26, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React28.createElement(Box26, null, /* @__PURE__ */ React28.createElement(Text24, { bold: true, color: GRADIENT[0] }, GLYPH.brand), /* @__PURE__ */ React28.createElement(Text24, null, " "), /* @__PURE__ */ React28.createElement(Text24, { bold: true }, "Welcome to "), /* @__PURE__ */ React28.createElement(Text24, { bold: true, color: GRADIENT[2] }, "REASONIX")), /* @__PURE__ */ React28.createElement(Box26, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text24, { color: COLOR.info }, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React28.createElement(Box26, null, /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, " free credit on signup \xB7 "), /* @__PURE__ */ React28.createElement(Text24, { color: COLOR.primary }, "https://platform.deepseek.com/api_keys")), /* @__PURE__ */ React28.createElement(Box26, null, /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, " saved to "), /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, defaultConfigPath())), /* @__PURE__ */ React28.createElement(Box26, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text24, { bold: true, color: COLOR.brand }, GLYPH.bar), /* @__PURE__ */ React28.createElement(Text24, { bold: true, color: COLOR.primary }, " \u203A "), /* @__PURE__ */ React28.createElement(
21464
+ return /* @__PURE__ */ React29.createElement(Box27, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React29.createElement(Box27, null, /* @__PURE__ */ React29.createElement(Text25, { bold: true, color: GRADIENT[0] }, GLYPH.brand), /* @__PURE__ */ React29.createElement(Text25, null, " "), /* @__PURE__ */ React29.createElement(Text25, { bold: true }, "Welcome to "), /* @__PURE__ */ React29.createElement(Text25, { bold: true, color: GRADIENT[2] }, "REASONIX")), /* @__PURE__ */ React29.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text25, { color: COLOR.info }, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React29.createElement(Box27, null, /* @__PURE__ */ React29.createElement(Text25, { dimColor: true }, " free credit on signup \xB7 "), /* @__PURE__ */ React29.createElement(Text25, { color: COLOR.primary }, "https://platform.deepseek.com/api_keys")), /* @__PURE__ */ React29.createElement(Box27, null, /* @__PURE__ */ React29.createElement(Text25, { dimColor: true }, " saved to "), /* @__PURE__ */ React29.createElement(Text25, { dimColor: true }, defaultConfigPath())), /* @__PURE__ */ React29.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text25, { bold: true, color: COLOR.brand }, GLYPH.bar), /* @__PURE__ */ React29.createElement(Text25, { bold: true, color: COLOR.primary }, " \u203A "), /* @__PURE__ */ React29.createElement(
21178
21465
  TextInput,
21179
21466
  {
21180
21467
  value,
@@ -21183,7 +21470,7 @@ function Setup({ onReady }) {
21183
21470
  mask: "\u2022",
21184
21471
  placeholder: "sk-..."
21185
21472
  }
21186
- )), error ? /* @__PURE__ */ React28.createElement(Box26, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text24, { color: COLOR.err, bold: true }, GLYPH.err), /* @__PURE__ */ React28.createElement(Text24, { color: COLOR.err }, ` ${error}`)) : value ? /* @__PURE__ */ React28.createElement(Box26, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, ` preview \xB7 ${redactKey(value)}`)) : null, /* @__PURE__ */ React28.createElement(Box26, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, " /exit to abort")));
21473
+ )), error ? /* @__PURE__ */ React29.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text25, { color: COLOR.err, bold: true }, GLYPH.err), /* @__PURE__ */ React29.createElement(Text25, { color: COLOR.err }, ` ${error}`)) : value ? /* @__PURE__ */ React29.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text25, { dimColor: true }, ` preview \xB7 ${redactKey(value)}`)) : null, /* @__PURE__ */ React29.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text25, { dimColor: true }, " /exit to abort")));
21187
21474
  }
21188
21475
 
21189
21476
  // src/cli/commands/chat.tsx
@@ -21199,7 +21486,7 @@ function Root({
21199
21486
  const [key, setKey] = useState12(initialKey);
21200
21487
  const [pending, setPending] = useState12(sessionPreview);
21201
21488
  if (!key) {
21202
- return /* @__PURE__ */ React29.createElement(
21489
+ return /* @__PURE__ */ React30.createElement(
21203
21490
  Setup,
21204
21491
  {
21205
21492
  onReady: (k) => {
@@ -21211,7 +21498,7 @@ function Root({
21211
21498
  }
21212
21499
  process.env.DEEPSEEK_API_KEY = key;
21213
21500
  if (pending && appProps.session) {
21214
- return /* @__PURE__ */ React29.createElement(KeystrokeProvider, null, /* @__PURE__ */ React29.createElement(
21501
+ return /* @__PURE__ */ React30.createElement(KeystrokeProvider, null, /* @__PURE__ */ React30.createElement(
21215
21502
  SessionPicker,
21216
21503
  {
21217
21504
  sessionName: appProps.session,
@@ -21226,7 +21513,7 @@ function Root({
21226
21513
  }
21227
21514
  ));
21228
21515
  }
21229
- return /* @__PURE__ */ React29.createElement(KeystrokeProvider, null, /* @__PURE__ */ React29.createElement(
21516
+ return /* @__PURE__ */ React30.createElement(KeystrokeProvider, null, /* @__PURE__ */ React30.createElement(
21230
21517
  App,
21231
21518
  {
21232
21519
  model: appProps.model,
@@ -21333,7 +21620,7 @@ async function chatCommand(opts) {
21333
21620
  rewriteSession(opts.session, []);
21334
21621
  }
21335
21622
  const { waitUntilExit } = render(
21336
- /* @__PURE__ */ React29.createElement(
21623
+ /* @__PURE__ */ React30.createElement(
21337
21624
  Root,
21338
21625
  {
21339
21626
  initialKey,
@@ -21686,35 +21973,35 @@ async function commitCommand(opts = {}) {
21686
21973
  import { writeFileSync as writeFileSync15 } from "fs";
21687
21974
  import { basename as basename4 } from "path";
21688
21975
  import { render as render2 } from "ink";
21689
- import React32 from "react";
21976
+ import React33 from "react";
21690
21977
 
21691
21978
  // src/cli/ui/DiffApp.tsx
21692
- import { Box as Box28, Static, Text as Text26, useApp as useApp2, useInput } from "ink";
21693
- import React31, { useState as useState13 } from "react";
21979
+ import { Box as Box29, Static, Text as Text27, useApp as useApp2, useInput } from "ink";
21980
+ import React32, { useState as useState13 } from "react";
21694
21981
 
21695
21982
  // src/cli/ui/RecordView.tsx
21696
- import { Box as Box27, Text as Text25 } from "ink";
21697
- import React30 from "react";
21983
+ import { Box as Box28, Text as Text26 } from "ink";
21984
+ import React31 from "react";
21698
21985
  function RecordView({ rec, compact: compact2 = false }) {
21699
21986
  const toolArgsMax = compact2 ? 120 : 200;
21700
21987
  const toolContentMax = compact2 ? 200 : 400;
21701
21988
  if (rec.role === "user") {
21702
21989
  const content = rec.content.includes("\n") ? rec.content.split("\n").join("\n ") : rec.content;
21703
- return /* @__PURE__ */ React30.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(Text25, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React30.createElement(Text25, null, content));
21990
+ return /* @__PURE__ */ React31.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React31.createElement(Text26, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React31.createElement(Text26, null, content));
21704
21991
  }
21705
21992
  if (rec.role === "assistant_final") {
21706
- return /* @__PURE__ */ React30.createElement(Box27, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React30.createElement(Box27, null, /* @__PURE__ */ React30.createElement(Text25, { bold: true, color: "green" }, "assistant"), rec.cost !== void 0 ? /* @__PURE__ */ React30.createElement(Text25, { dimColor: true }, " $", rec.cost.toFixed(6)) : null, rec.usage ? /* @__PURE__ */ React30.createElement(CacheBadge, { usage: rec.usage }) : null), rec.planState ? /* @__PURE__ */ React30.createElement(PlanStateBlock, { planState: rec.planState }) : null, rec.content ? /* @__PURE__ */ React30.createElement(Text25, null, rec.content) : /* @__PURE__ */ React30.createElement(Text25, { dimColor: true, italic: true }, "(tool-call response only)"));
21993
+ return /* @__PURE__ */ React31.createElement(Box28, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React31.createElement(Box28, null, /* @__PURE__ */ React31.createElement(Text26, { bold: true, color: "green" }, "assistant"), rec.cost !== void 0 ? /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, " $", rec.cost.toFixed(6)) : null, rec.usage ? /* @__PURE__ */ React31.createElement(CacheBadge, { usage: rec.usage }) : null), rec.planState ? /* @__PURE__ */ React31.createElement(PlanStateBlock, { planState: rec.planState }) : null, rec.content ? /* @__PURE__ */ React31.createElement(Text26, null, rec.content) : /* @__PURE__ */ React31.createElement(Text26, { dimColor: true, italic: true }, "(tool-call response only)"));
21707
21994
  }
21708
21995
  if (rec.role === "tool") {
21709
- return /* @__PURE__ */ React30.createElement(Box27, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React30.createElement(Text25, { color: "yellow" }, "tool<", rec.tool ?? "?", ">"), rec.args ? /* @__PURE__ */ React30.createElement(Text25, { dimColor: true }, " args: ", truncate2(rec.args, toolArgsMax)) : null, /* @__PURE__ */ React30.createElement(Text25, { dimColor: true }, " \u2192 ", truncate2(rec.content, toolContentMax)));
21996
+ return /* @__PURE__ */ React31.createElement(Box28, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React31.createElement(Text26, { color: "yellow" }, "tool<", rec.tool ?? "?", ">"), rec.args ? /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, " args: ", truncate2(rec.args, toolArgsMax)) : null, /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, " \u2192 ", truncate2(rec.content, toolContentMax)));
21710
21997
  }
21711
21998
  if (rec.role === "error") {
21712
- return /* @__PURE__ */ React30.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(Text25, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React30.createElement(Text25, { color: "red" }, rec.error ?? rec.content));
21999
+ return /* @__PURE__ */ React31.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React31.createElement(Text26, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React31.createElement(Text26, { color: "red" }, rec.error ?? rec.content));
21713
22000
  }
21714
22001
  if (rec.role === "done" || rec.role === "assistant_delta") {
21715
22002
  return null;
21716
22003
  }
21717
- return /* @__PURE__ */ React30.createElement(Box27, null, /* @__PURE__ */ React30.createElement(Text25, { dimColor: true }, "[", rec.role, "] ", rec.content));
22004
+ return /* @__PURE__ */ React31.createElement(Box28, null, /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, "[", rec.role, "] ", rec.content));
21718
22005
  }
21719
22006
  function CacheBadge({ usage }) {
21720
22007
  const hit = usage.prompt_cache_hit_tokens ?? 0;
@@ -21723,7 +22010,7 @@ function CacheBadge({ usage }) {
21723
22010
  if (total === 0) return null;
21724
22011
  const pct2 = hit / total * 100;
21725
22012
  const color2 = pct2 >= 70 ? "green" : pct2 >= 40 ? "yellow" : "red";
21726
- return /* @__PURE__ */ React30.createElement(Text25, null, /* @__PURE__ */ React30.createElement(Text25, { dimColor: true }, " \xB7 cache "), /* @__PURE__ */ React30.createElement(Text25, { color: color2 }, pct2.toFixed(1), "%"));
22013
+ return /* @__PURE__ */ React31.createElement(Text26, null, /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, " \xB7 cache "), /* @__PURE__ */ React31.createElement(Text26, { color: color2 }, pct2.toFixed(1), "%"));
21727
22014
  }
21728
22015
  function truncate2(s, max) {
21729
22016
  return s.length <= max ? s : `${s.slice(0, max)}\u2026 (+${s.length - max} chars)`;
@@ -21757,7 +22044,7 @@ function DiffApp({ report }) {
21757
22044
  }
21758
22045
  });
21759
22046
  const pair = report.pairs[idx];
21760
- return /* @__PURE__ */ React31.createElement(Box28, { flexDirection: "column" }, /* @__PURE__ */ React31.createElement(DiffHeader, { report }), /* @__PURE__ */ React31.createElement(Box28, { marginTop: 1, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ React31.createElement(Text26, { color: "cyan", bold: true }, "turn ", pair?.turn ?? "?", " (", idx + 1, " / ", report.pairs.length, ")"), /* @__PURE__ */ React31.createElement(Text26, null, pair ? /* @__PURE__ */ React31.createElement(KindBadge, { kind: pair.kind }) : null)), /* @__PURE__ */ React31.createElement(Box28, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React31.createElement(Pane, { label: report.a.label, headerColor: "blue", records: paneRecords(pair, "a") }), /* @__PURE__ */ React31.createElement(Pane, { label: report.b.label, headerColor: "magenta", records: paneRecords(pair, "b") })), pair?.divergenceNote ? /* @__PURE__ */ React31.createElement(Box28, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React31.createElement(Text26, { color: "yellow" }, "\u2605 "), /* @__PURE__ */ React31.createElement(Text26, null, pair.divergenceNote)) : null, /* @__PURE__ */ React31.createElement(Box28, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, /* @__PURE__ */ React31.createElement(Text26, { bold: true }, "j"), "/", /* @__PURE__ */ React31.createElement(Text26, { bold: true }, "\u2193"), " next \xB7 ", /* @__PURE__ */ React31.createElement(Text26, { bold: true }, "k"), "/", /* @__PURE__ */ React31.createElement(Text26, { bold: true }, "\u2191"), " ", "prev \xB7 ", /* @__PURE__ */ React31.createElement(Text26, { bold: true }, "n"), " next-diverge \xB7 ", /* @__PURE__ */ React31.createElement(Text26, { bold: true }, "N"), "/", /* @__PURE__ */ React31.createElement(Text26, { bold: true }, "p"), " ", "prev-diverge \xB7 ", /* @__PURE__ */ React31.createElement(Text26, { bold: true }, "g"), "/", /* @__PURE__ */ React31.createElement(Text26, { bold: true }, "G"), " first/last \xB7 ", /* @__PURE__ */ React31.createElement(Text26, { bold: true }, "q"), " ", "quit")));
22047
+ return /* @__PURE__ */ React32.createElement(Box29, { flexDirection: "column" }, /* @__PURE__ */ React32.createElement(DiffHeader, { report }), /* @__PURE__ */ React32.createElement(Box29, { marginTop: 1, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ React32.createElement(Text27, { color: "cyan", bold: true }, "turn ", pair?.turn ?? "?", " (", idx + 1, " / ", report.pairs.length, ")"), /* @__PURE__ */ React32.createElement(Text27, null, pair ? /* @__PURE__ */ React32.createElement(KindBadge, { kind: pair.kind }) : null)), /* @__PURE__ */ React32.createElement(Box29, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React32.createElement(Pane, { label: report.a.label, headerColor: "blue", records: paneRecords(pair, "a") }), /* @__PURE__ */ React32.createElement(Pane, { label: report.b.label, headerColor: "magenta", records: paneRecords(pair, "b") })), pair?.divergenceNote ? /* @__PURE__ */ React32.createElement(Box29, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React32.createElement(Text27, { color: "yellow" }, "\u2605 "), /* @__PURE__ */ React32.createElement(Text27, null, pair.divergenceNote)) : null, /* @__PURE__ */ React32.createElement(Box29, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "j"), "/", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "\u2193"), " next \xB7 ", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "k"), "/", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "\u2191"), " ", "prev \xB7 ", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "n"), " next-diverge \xB7 ", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "N"), "/", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "p"), " ", "prev-diverge \xB7 ", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "g"), "/", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "G"), " first/last \xB7 ", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "q"), " ", "quit")));
21761
22048
  }
21762
22049
  function DiffHeader({ report }) {
21763
22050
  const a = report.a;
@@ -21775,15 +22062,15 @@ function DiffHeader({ report }) {
21775
22062
  } else if (a.stats.prefixHashes[0] && a.stats.prefixHashes[0] === b.stats.prefixHashes[0]) {
21776
22063
  prefixLine = `shared prefix hash ${a.stats.prefixHashes[0].slice(0, 12)}\u2026 \u2014 cache delta attributable to log stability, not prompt change.`;
21777
22064
  }
21778
- return /* @__PURE__ */ React31.createElement(Box28, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React31.createElement(Box28, { justifyContent: "space-between" }, /* @__PURE__ */ React31.createElement(Text26, null, /* @__PURE__ */ React31.createElement(Text26, { color: "cyan", bold: true }, "reasonix diff"), /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, " \xB7 A="), /* @__PURE__ */ React31.createElement(Text26, { color: "blue" }, a.label), /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, " vs B="), /* @__PURE__ */ React31.createElement(Text26, { color: "magenta" }, b.label)), /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, report.pairs.length, " turns aligned")), /* @__PURE__ */ React31.createElement(Box28, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React31.createElement(Text26, null, /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, "cache "), /* @__PURE__ */ React31.createElement(Text26, null, (a.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React31.createElement(Text26, null, (b.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React31.createElement(Text26, { color: cacheDelta >= 0 ? "green" : "red", bold: true }, " ", cacheDelta >= 0 ? "+" : "", (cacheDelta * 100).toFixed(1), "pp")), /* @__PURE__ */ React31.createElement(Text26, null, /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, "cost "), /* @__PURE__ */ React31.createElement(Text26, null, "$", a.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React31.createElement(Text26, null, "$", b.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React31.createElement(Text26, { color: costDelta2 <= 0 ? "green" : "red", bold: true }, " ", costDelta2 >= 0 ? "+" : "", costDelta2.toFixed(1), "%")), /* @__PURE__ */ React31.createElement(Text26, null, /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, "model calls "), /* @__PURE__ */ React31.createElement(Text26, null, a.stats.turns, " \u2192 ", b.stats.turns))), prefixLine ? /* @__PURE__ */ React31.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React31.createElement(Text26, { dimColor: true, italic: true }, prefixLine)) : null);
22065
+ return /* @__PURE__ */ React32.createElement(Box29, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React32.createElement(Box29, { justifyContent: "space-between" }, /* @__PURE__ */ React32.createElement(Text27, null, /* @__PURE__ */ React32.createElement(Text27, { color: "cyan", bold: true }, "reasonix diff"), /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, " \xB7 A="), /* @__PURE__ */ React32.createElement(Text27, { color: "blue" }, a.label), /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, " vs B="), /* @__PURE__ */ React32.createElement(Text27, { color: "magenta" }, b.label)), /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, report.pairs.length, " turns aligned")), /* @__PURE__ */ React32.createElement(Box29, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React32.createElement(Text27, null, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, "cache "), /* @__PURE__ */ React32.createElement(Text27, null, (a.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React32.createElement(Text27, null, (b.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React32.createElement(Text27, { color: cacheDelta >= 0 ? "green" : "red", bold: true }, " ", cacheDelta >= 0 ? "+" : "", (cacheDelta * 100).toFixed(1), "pp")), /* @__PURE__ */ React32.createElement(Text27, null, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, "cost "), /* @__PURE__ */ React32.createElement(Text27, null, "$", a.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React32.createElement(Text27, null, "$", b.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React32.createElement(Text27, { color: costDelta2 <= 0 ? "green" : "red", bold: true }, " ", costDelta2 >= 0 ? "+" : "", costDelta2.toFixed(1), "%")), /* @__PURE__ */ React32.createElement(Text27, null, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, "model calls "), /* @__PURE__ */ React32.createElement(Text27, null, a.stats.turns, " \u2192 ", b.stats.turns))), prefixLine ? /* @__PURE__ */ React32.createElement(Box29, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true, italic: true }, prefixLine)) : null);
21779
22066
  }
21780
22067
  function Pane({
21781
22068
  label,
21782
22069
  headerColor,
21783
22070
  records
21784
22071
  }) {
21785
- return /* @__PURE__ */ React31.createElement(
21786
- Box28,
22072
+ return /* @__PURE__ */ React32.createElement(
22073
+ Box29,
21787
22074
  {
21788
22075
  flexDirection: "column",
21789
22076
  flexGrow: 1,
@@ -21791,21 +22078,21 @@ function Pane({
21791
22078
  borderStyle: "single",
21792
22079
  borderColor: headerColor
21793
22080
  },
21794
- /* @__PURE__ */ React31.createElement(Text26, { color: headerColor, bold: true }, label),
21795
- records.length === 0 ? /* @__PURE__ */ React31.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React31.createElement(Text26, { dimColor: true, italic: true }, "(no records on this side for this turn)")) : /* @__PURE__ */ React31.createElement(Static, { items: records.map((rec, i) => ({ key: `${label}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React31.createElement(RecordView, { key, rec, compact: true }))
22081
+ /* @__PURE__ */ React32.createElement(Text27, { color: headerColor, bold: true }, label),
22082
+ records.length === 0 ? /* @__PURE__ */ React32.createElement(Box29, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true, italic: true }, "(no records on this side for this turn)")) : /* @__PURE__ */ React32.createElement(Static, { items: records.map((rec, i) => ({ key: `${label}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React32.createElement(RecordView, { key, rec, compact: true }))
21796
22083
  );
21797
22084
  }
21798
22085
  function KindBadge({ kind }) {
21799
22086
  if (kind === "match") {
21800
- return /* @__PURE__ */ React31.createElement(Text26, { color: "green" }, "\u2713 match");
22087
+ return /* @__PURE__ */ React32.createElement(Text27, { color: "green" }, "\u2713 match");
21801
22088
  }
21802
22089
  if (kind === "diverge") {
21803
- return /* @__PURE__ */ React31.createElement(Text26, { color: "yellow" }, "\u2605 diverge");
22090
+ return /* @__PURE__ */ React32.createElement(Text27, { color: "yellow" }, "\u2605 diverge");
21804
22091
  }
21805
22092
  if (kind === "only_in_a") {
21806
- return /* @__PURE__ */ React31.createElement(Text26, { color: "blue" }, "\u2190 only in A");
22093
+ return /* @__PURE__ */ React32.createElement(Text27, { color: "blue" }, "\u2190 only in A");
21807
22094
  }
21808
- return /* @__PURE__ */ React31.createElement(Text26, { color: "magenta" }, "\u2192 only in B");
22095
+ return /* @__PURE__ */ React32.createElement(Text27, { color: "magenta" }, "\u2192 only in B");
21809
22096
  }
21810
22097
  function paneRecords(pair, side) {
21811
22098
  if (!pair) return [];
@@ -21836,7 +22123,7 @@ markdown report written to ${opts.mdPath}`);
21836
22123
  return;
21837
22124
  }
21838
22125
  if (wantTui) {
21839
- const { waitUntilExit } = render2(React32.createElement(DiffApp, { report }), {
22126
+ const { waitUntilExit } = render2(React33.createElement(DiffApp, { report }), {
21840
22127
  exitOnCtrlC: true,
21841
22128
  patchConsole: false
21842
22129
  });
@@ -22476,11 +22763,11 @@ function pad2(s, width) {
22476
22763
 
22477
22764
  // src/cli/commands/replay.ts
22478
22765
  import { render as render3 } from "ink";
22479
- import React34 from "react";
22766
+ import React35 from "react";
22480
22767
 
22481
22768
  // src/cli/ui/ReplayApp.tsx
22482
- import { Box as Box29, Static as Static2, Text as Text27, useApp as useApp3, useInput as useInput2 } from "ink";
22483
- import React33, { useMemo as useMemo4, useState as useState14 } from "react";
22769
+ import { Box as Box30, Static as Static2, Text as Text28, useApp as useApp3, useInput as useInput2 } from "ink";
22770
+ import React34, { useMemo as useMemo4, useState as useState14 } from "react";
22484
22771
  function ReplayApp({ meta, pages }) {
22485
22772
  const { exit: exit2 } = useApp3();
22486
22773
  const maxIdx = Math.max(0, pages.length - 1);
@@ -22520,14 +22807,14 @@ function ReplayApp({ meta, pages }) {
22520
22807
  const prefixHash = cumStats.prefixHashes.length === 1 ? cumStats.prefixHashes[0].slice(0, 16) : cumStats.prefixHashes.length === 0 ? "(untracked)" : `(churned \xD7${cumStats.prefixHashes.length})`;
22521
22808
  const currentPage = pages[idx];
22522
22809
  const progressLabel = pages.length === 0 ? "empty transcript" : `turn ${idx + 1} / ${pages.length}`;
22523
- return /* @__PURE__ */ React33.createElement(Box29, { flexDirection: "column" }, /* @__PURE__ */ React33.createElement(
22810
+ return /* @__PURE__ */ React34.createElement(Box30, { flexDirection: "column" }, /* @__PURE__ */ React34.createElement(
22524
22811
  StatsPanel,
22525
22812
  {
22526
22813
  summary,
22527
22814
  model: cumStats.models[0] ?? meta?.model ?? "?",
22528
22815
  prefixHash
22529
22816
  }
22530
- ), /* @__PURE__ */ React33.createElement(Box29, { flexDirection: "column", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React33.createElement(Box29, { justifyContent: "space-between" }, /* @__PURE__ */ React33.createElement(Text27, { color: "cyan", bold: true }, progressLabel), meta ? /* @__PURE__ */ React33.createElement(Text27, { dimColor: true }, meta.source, meta.task ? ` \xB7 ${meta.task}` : "", meta.mode ? ` \xB7 ${meta.mode}` : "") : null), currentPage ? /* @__PURE__ */ React33.createElement(Static2, { items: currentPage.records.map((rec, i) => ({ key: `${idx}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React33.createElement(RecordView, { key, rec })) : /* @__PURE__ */ React33.createElement(Text27, { dimColor: true, italic: true }, "no records")), /* @__PURE__ */ React33.createElement(Box29, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React33.createElement(Text27, { dimColor: true }, /* @__PURE__ */ React33.createElement(Text27, { bold: true }, "j"), "/", /* @__PURE__ */ React33.createElement(Text27, { bold: true }, "\u2193"), "/", /* @__PURE__ */ React33.createElement(Text27, { bold: true }, "space"), " next \xB7 ", /* @__PURE__ */ React33.createElement(Text27, { bold: true }, "k"), "/", /* @__PURE__ */ React33.createElement(Text27, { bold: true }, "\u2191"), " prev \xB7 ", /* @__PURE__ */ React33.createElement(Text27, { bold: true }, "g"), " first \xB7 ", /* @__PURE__ */ React33.createElement(Text27, { bold: true }, "G"), " last \xB7", " ", /* @__PURE__ */ React33.createElement(Text27, { bold: true }, "q"), " quit")));
22817
+ ), /* @__PURE__ */ React34.createElement(Box30, { flexDirection: "column", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React34.createElement(Box30, { justifyContent: "space-between" }, /* @__PURE__ */ React34.createElement(Text28, { color: "cyan", bold: true }, progressLabel), meta ? /* @__PURE__ */ React34.createElement(Text28, { dimColor: true }, meta.source, meta.task ? ` \xB7 ${meta.task}` : "", meta.mode ? ` \xB7 ${meta.mode}` : "") : null), currentPage ? /* @__PURE__ */ React34.createElement(Static2, { items: currentPage.records.map((rec, i) => ({ key: `${idx}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React34.createElement(RecordView, { key, rec })) : /* @__PURE__ */ React34.createElement(Text28, { dimColor: true, italic: true }, "no records")), /* @__PURE__ */ React34.createElement(Box30, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React34.createElement(Text28, { dimColor: true }, /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "j"), "/", /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "\u2193"), "/", /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "space"), " next \xB7 ", /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "k"), "/", /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "\u2191"), " prev \xB7 ", /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "g"), " first \xB7 ", /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "G"), " last \xB7", " ", /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "q"), " quit")));
22531
22818
  }
22532
22819
 
22533
22820
  // src/cli/commands/replay.ts
@@ -22539,7 +22826,7 @@ async function replayCommand(opts) {
22539
22826
  }
22540
22827
  const { parsed } = replayFromFile(opts.path);
22541
22828
  const pages = groupRecordsByTurn(parsed.records);
22542
- const { waitUntilExit } = render3(React34.createElement(ReplayApp, { meta: parsed.meta, pages }), {
22829
+ const { waitUntilExit } = render3(React35.createElement(ReplayApp, { meta: parsed.meta, pages }), {
22543
22830
  exitOnCtrlC: true,
22544
22831
  patchConsole: false
22545
22832
  });
@@ -22845,12 +23132,12 @@ function truncate3(s, max) {
22845
23132
 
22846
23133
  // src/cli/commands/setup.tsx
22847
23134
  import { render as render4 } from "ink";
22848
- import React36 from "react";
23135
+ import React37 from "react";
22849
23136
 
22850
23137
  // src/cli/ui/Wizard.tsx
22851
- import { Box as Box30, Text as Text28, useApp as useApp4, useInput as useInput3 } from "ink";
23138
+ import { Box as Box31, Text as Text29, useApp as useApp4, useInput as useInput3 } from "ink";
22852
23139
  import TextInput2 from "ink-text-input";
22853
- import React35, { useState as useState15 } from "react";
23140
+ import React36, { useState as useState15 } from "react";
22854
23141
  var CATALOG_BY_NAME = new Map(MCP_CATALOG.map((e) => [e.name, e]));
22855
23142
  function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
22856
23143
  const { exit: exit2 } = useApp4();
@@ -22866,7 +23153,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
22866
23153
  if (key.escape && step !== "saved" && onCancel) onCancel();
22867
23154
  });
22868
23155
  if (step === "apiKey") {
22869
- return /* @__PURE__ */ React35.createElement(
23156
+ return /* @__PURE__ */ React36.createElement(
22870
23157
  ApiKeyStep,
22871
23158
  {
22872
23159
  onSubmit: (key) => {
@@ -22880,7 +23167,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
22880
23167
  );
22881
23168
  }
22882
23169
  if (step === "preset") {
22883
- return /* @__PURE__ */ React35.createElement(StepFrame, { title: "Pick a preset", step: 1, total: 3 }, /* @__PURE__ */ React35.createElement(
23170
+ return /* @__PURE__ */ React36.createElement(StepFrame, { title: "Pick a preset", step: 1, total: 3 }, /* @__PURE__ */ React36.createElement(
22884
23171
  SingleSelect,
22885
23172
  {
22886
23173
  items: presetItems(),
@@ -22890,10 +23177,10 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
22890
23177
  setStep("mcp");
22891
23178
  }
22892
23179
  }
22893
- ), /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text28, { dimColor: true }, "[\u2191\u2193] navigate \xB7 [Enter] confirm \xB7 [Esc] cancel")));
23180
+ ), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "[\u2191\u2193] navigate \xB7 [Enter] confirm \xB7 [Esc] cancel")));
22894
23181
  }
22895
23182
  if (step === "mcp") {
22896
- return /* @__PURE__ */ React35.createElement(StepFrame, { title: "Which MCP servers should Reasonix wire up for you?", step: 2, total: 3 }, /* @__PURE__ */ React35.createElement(
23183
+ return /* @__PURE__ */ React36.createElement(StepFrame, { title: "Which MCP servers should Reasonix wire up for you?", step: 2, total: 3 }, /* @__PURE__ */ React36.createElement(
22897
23184
  MultiSelect,
22898
23185
  {
22899
23186
  items: mcpItems(),
@@ -22918,7 +23205,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
22918
23205
  }
22919
23206
  const currentName = pending[0];
22920
23207
  const entry = CATALOG_BY_NAME.get(currentName);
22921
- return /* @__PURE__ */ React35.createElement(
23208
+ return /* @__PURE__ */ React36.createElement(
22922
23209
  McpArgsStep,
22923
23210
  {
22924
23211
  entry,
@@ -22936,7 +23223,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
22936
23223
  }
22937
23224
  if (step === "review") {
22938
23225
  const specs = data.selectedCatalog.map((name) => buildSpec(name, data.catalogArgs));
22939
- return /* @__PURE__ */ React35.createElement(StepFrame, { title: "Ready to save", step: 3, total: 3 }, /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "column" }, /* @__PURE__ */ React35.createElement(SummaryLine, { label: "API key", value: redactKey(data.apiKey) }), /* @__PURE__ */ React35.createElement(SummaryLine, { label: "Preset", value: data.preset }), /* @__PURE__ */ React35.createElement(
23226
+ return /* @__PURE__ */ React36.createElement(StepFrame, { title: "Ready to save", step: 3, total: 3 }, /* @__PURE__ */ React36.createElement(Box31, { flexDirection: "column" }, /* @__PURE__ */ React36.createElement(SummaryLine, { label: "API key", value: redactKey(data.apiKey) }), /* @__PURE__ */ React36.createElement(SummaryLine, { label: "Preset", value: data.preset }), /* @__PURE__ */ React36.createElement(
22940
23227
  SummaryLine,
22941
23228
  {
22942
23229
  label: "MCP",
@@ -22944,8 +23231,8 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
22944
23231
  }
22945
23232
  ), specs.map((spec, i) => (
22946
23233
  // biome-ignore lint/suspicious/noArrayIndexKey: review-only render, order fixed
22947
- /* @__PURE__ */ React35.createElement(Box30, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React35.createElement(Text28, { dimColor: true }, "\xB7 ", spec))
22948
- )), /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text28, null, "Saves to ", defaultConfigPath())), error ? /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text28, { color: "red" }, error)) : null, /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text28, { dimColor: true }, "[Enter] save \xB7 [Esc] cancel"))), /* @__PURE__ */ React35.createElement(
23234
+ /* @__PURE__ */ React36.createElement(Box31, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "\xB7 ", spec))
23235
+ )), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, null, "Saves to ", defaultConfigPath())), error ? /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { color: "red" }, error)) : null, /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "[Enter] save \xB7 [Esc] cancel"))), /* @__PURE__ */ React36.createElement(
22949
23236
  ReviewConfirm,
22950
23237
  {
22951
23238
  onConfirm: () => {
@@ -22971,7 +23258,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
22971
23258
  }
22972
23259
  ));
22973
23260
  }
22974
- return /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React35.createElement(Text28, { bold: true, color: "green" }, "\u25B8 Saved."), /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text28, null, "Run `reasonix` any time to start chatting \u2014 your settings are remembered.")), /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text28, { dimColor: true }, "[Enter] to exit")), /* @__PURE__ */ React35.createElement(ExitOnEnter, { onExit: exit2 }));
23261
+ return /* @__PURE__ */ React36.createElement(Box31, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React36.createElement(Text29, { bold: true, color: "green" }, "\u25B8 Saved."), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, null, "Run `reasonix` any time to start chatting \u2014 your settings are remembered.")), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "[Enter] to exit")), /* @__PURE__ */ React36.createElement(ExitOnEnter, { onExit: exit2 }));
22975
23262
  }
22976
23263
  function ApiKeyStep({
22977
23264
  onSubmit,
@@ -22979,7 +23266,7 @@ function ApiKeyStep({
22979
23266
  onError
22980
23267
  }) {
22981
23268
  const [value, setValue] = useState15("");
22982
- return /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React35.createElement(Text28, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text28, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React35.createElement(Text28, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React35.createElement(Text28, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text28, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React35.createElement(
23269
+ return /* @__PURE__ */ React36.createElement(Box31, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React36.createElement(Text29, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React36.createElement(
22983
23270
  TextInput2,
22984
23271
  {
22985
23272
  value,
@@ -22996,7 +23283,7 @@ function ApiKeyStep({
22996
23283
  mask: "\u2022",
22997
23284
  placeholder: "sk-..."
22998
23285
  }
22999
- )), error ? /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text28, { color: "red" }, error)) : value ? /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text28, { dimColor: true }, "preview: ", redactKey(value))) : null);
23286
+ )), error ? /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { color: "red" }, error)) : value ? /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "preview: ", redactKey(value))) : null);
23000
23287
  }
23001
23288
  function McpArgsStep({
23002
23289
  entry,
@@ -23005,7 +23292,7 @@ function McpArgsStep({
23005
23292
  onError
23006
23293
  }) {
23007
23294
  const [value, setValue] = useState15("");
23008
- return /* @__PURE__ */ React35.createElement(StepFrame, { title: `Configure ${entry.name}`, step: 2, total: 3 }, /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "column" }, /* @__PURE__ */ React35.createElement(Text28, null, entry.summary), entry.note ? /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text28, { dimColor: true }, entry.note)) : null, /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text28, null, "Required parameter: "), /* @__PURE__ */ React35.createElement(Text28, { bold: true }, entry.userArgs)), /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text28, { bold: true, color: "cyan" }, entry.userArgs, " \u203A "), /* @__PURE__ */ React35.createElement(
23295
+ return /* @__PURE__ */ React36.createElement(StepFrame, { title: `Configure ${entry.name}`, step: 2, total: 3 }, /* @__PURE__ */ React36.createElement(Box31, { flexDirection: "column" }, /* @__PURE__ */ React36.createElement(Text29, null, entry.summary), entry.note ? /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, entry.note)) : null, /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, null, "Required parameter: "), /* @__PURE__ */ React36.createElement(Text29, { bold: true }, entry.userArgs)), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { bold: true, color: "cyan" }, entry.userArgs, " \u203A "), /* @__PURE__ */ React36.createElement(
23009
23296
  TextInput2,
23010
23297
  {
23011
23298
  value,
@@ -23021,7 +23308,7 @@ function McpArgsStep({
23021
23308
  },
23022
23309
  placeholder: placeholderFor(entry)
23023
23310
  }
23024
- )), error ? /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text28, { color: "red" }, error)) : null));
23311
+ )), error ? /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { color: "red" }, error)) : null));
23025
23312
  }
23026
23313
  function ReviewConfirm({ onConfirm }) {
23027
23314
  useInput3((_i, key) => {
@@ -23041,10 +23328,10 @@ function StepFrame({
23041
23328
  total,
23042
23329
  children
23043
23330
  }) {
23044
- return /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React35.createElement(Box30, null, /* @__PURE__ */ React35.createElement(Text28, { dimColor: true }, "Step ", step, "/", total, " \xB7", " "), /* @__PURE__ */ React35.createElement(Text28, { bold: true, color: "cyan" }, title)), /* @__PURE__ */ React35.createElement(Box30, { marginTop: 1, flexDirection: "column" }, children));
23331
+ return /* @__PURE__ */ React36.createElement(Box31, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React36.createElement(Box31, null, /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "Step ", step, "/", total, " \xB7", " "), /* @__PURE__ */ React36.createElement(Text29, { bold: true, color: "cyan" }, title)), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1, flexDirection: "column" }, children));
23045
23332
  }
23046
23333
  function SummaryLine({ label, value }) {
23047
- return /* @__PURE__ */ React35.createElement(Box30, null, /* @__PURE__ */ React35.createElement(Text28, null, label.padEnd(12)), /* @__PURE__ */ React35.createElement(Text28, { bold: true }, value));
23334
+ return /* @__PURE__ */ React36.createElement(Box31, null, /* @__PURE__ */ React36.createElement(Text29, null, label.padEnd(12)), /* @__PURE__ */ React36.createElement(Text29, { bold: true }, value));
23048
23335
  }
23049
23336
  function presetItems() {
23050
23337
  return ["auto", "flash", "pro"].map((name) => ({
@@ -23100,7 +23387,7 @@ async function setupCommand(_opts = {}) {
23100
23387
  const existingKey = loadApiKey();
23101
23388
  const existing = readConfig();
23102
23389
  const { waitUntilExit, unmount } = render4(
23103
- /* @__PURE__ */ React36.createElement(
23390
+ /* @__PURE__ */ React37.createElement(
23104
23391
  Wizard,
23105
23392
  {
23106
23393
  existingApiKey: existingKey,