reasonix 0.4.13 → 0.4.14

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
@@ -3519,19 +3519,19 @@ function sep() {
3519
3519
  }
3520
3520
 
3521
3521
  // src/index.ts
3522
- var VERSION = "0.4.3";
3522
+ var VERSION = "0.4.14";
3523
3523
 
3524
3524
  // src/cli/commands/chat.tsx
3525
3525
  import { render } from "ink";
3526
- import React9, { useState as useState5 } from "react";
3526
+ import React10, { useState as useState4 } from "react";
3527
3527
 
3528
3528
  // src/cli/ui/App.tsx
3529
3529
  import { Box as Box7, Static, Text as Text7, useApp, useInput as useInput2 } from "ink";
3530
- import React7, { useCallback, useEffect as useEffect3, useMemo, useRef, useState as useState3 } from "react";
3530
+ import React8, { useCallback, useEffect as useEffect2, useMemo, useRef, useState as useState2 } from "react";
3531
3531
 
3532
3532
  // src/cli/ui/EventLog.tsx
3533
3533
  import { Box as Box3, Text as Text3 } from "ink";
3534
- import React3, { useEffect, useState } from "react";
3534
+ import React4 from "react";
3535
3535
 
3536
3536
  // src/cli/ui/PlanStateBlock.tsx
3537
3537
  import { Box, Text } from "ink";
@@ -3842,45 +3842,67 @@ function Markdown({ text }) {
3842
3842
  return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", gap: 1 }, blocks.map((b, i) => /* @__PURE__ */ React2.createElement(BlockView, { key: `${i}-${b.kind}`, block: b })));
3843
3843
  }
3844
3844
 
3845
+ // src/cli/ui/ticker.tsx
3846
+ import React3, { createContext, useContext, useEffect, useState } from "react";
3847
+ var TICK_MS = 120;
3848
+ var TickContext = createContext(0);
3849
+ function TickerProvider({ children, disabled }) {
3850
+ const [tick, setTick] = useState(0);
3851
+ useEffect(() => {
3852
+ if (disabled) return;
3853
+ const id = setInterval(() => setTick((t) => t + 1), TICK_MS);
3854
+ return () => clearInterval(id);
3855
+ }, [disabled]);
3856
+ return /* @__PURE__ */ React3.createElement(TickContext.Provider, { value: tick }, children);
3857
+ }
3858
+ function useTick() {
3859
+ return useContext(TickContext);
3860
+ }
3861
+ function useElapsedSeconds() {
3862
+ const [start] = useState(() => Date.now());
3863
+ useTick();
3864
+ return Math.floor((Date.now() - start) / 1e3);
3865
+ }
3866
+
3845
3867
  // src/cli/ui/EventLog.tsx
3846
- var EventRow = React3.memo(function EventRow2({ event }) {
3868
+ var EventRow = React4.memo(function EventRow2({ event }) {
3847
3869
  if (event.role === "user") {
3848
- return /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React3.createElement(Text3, null, event.text));
3870
+ return /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(Text3, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React4.createElement(Text3, null, event.text));
3849
3871
  }
3850
3872
  if (event.role === "assistant") {
3851
- if (event.streaming) return /* @__PURE__ */ React3.createElement(StreamingAssistant, { event });
3852
- return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { bold: true, color: "green" }, "assistant")), event.branch ? /* @__PURE__ */ React3.createElement(BranchBlock, { branch: event.branch }) : null, event.reasoning ? /* @__PURE__ */ React3.createElement(ReasoningBlock, { reasoning: event.reasoning }) : null, !isPlanStateEmpty(event.planState) ? /* @__PURE__ */ React3.createElement(PlanStateBlock, { planState: event.planState }) : null, event.text ? /* @__PURE__ */ React3.createElement(Markdown, { text: event.text }) : /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "(no content)"), event.stats ? /* @__PURE__ */ React3.createElement(StatsLine, { stats: event.stats }) : null, event.repair ? /* @__PURE__ */ React3.createElement(Text3, { color: "magenta" }, event.repair) : null);
3873
+ if (event.streaming) return /* @__PURE__ */ React4.createElement(StreamingAssistant, { event });
3874
+ return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(Text3, { bold: true, color: "green" }, "assistant")), event.branch ? /* @__PURE__ */ React4.createElement(BranchBlock, { branch: event.branch }) : null, event.reasoning ? /* @__PURE__ */ React4.createElement(ReasoningBlock, { reasoning: event.reasoning }) : null, !isPlanStateEmpty(event.planState) ? /* @__PURE__ */ React4.createElement(PlanStateBlock, { planState: event.planState }) : null, event.text ? /* @__PURE__ */ React4.createElement(Markdown, { text: event.text }) : /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, "(no content)"), event.stats ? /* @__PURE__ */ React4.createElement(StatsLine, { stats: event.stats }) : null, event.repair ? /* @__PURE__ */ React4.createElement(Text3, { color: "magenta" }, event.repair) : null);
3853
3875
  }
3854
3876
  if (event.role === "tool") {
3855
3877
  const isError = event.text.startsWith("ERROR:");
3856
3878
  const color = isError ? "red" : "yellow";
3857
3879
  const marker = isError ? "\u2717" : "\u2192";
3858
3880
  const isEditFile = (event.toolName === "edit_file" || event.toolName?.endsWith("_edit_file")) && !isError;
3859
- return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color }, `tool<${event.toolName ?? "?"}> ${marker}`), isEditFile ? /* @__PURE__ */ React3.createElement(EditFileDiff, { text: event.text }) : /* @__PURE__ */ React3.createElement(Text3, { color: isError ? "red" : void 0, dimColor: !isError }, " ", truncate2(event.text, 400)));
3881
+ return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text3, { color }, `tool<${event.toolName ?? "?"}> ${marker}`), isEditFile ? /* @__PURE__ */ React4.createElement(EditFileDiff, { text: event.text }) : /* @__PURE__ */ React4.createElement(Text3, { color: isError ? "red" : void 0, dimColor: !isError }, " ", truncate2(event.text, 400)));
3860
3882
  }
3861
3883
  if (event.role === "error") {
3862
- return /* @__PURE__ */ React3.createElement(Box3, { marginTop: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React3.createElement(Text3, { color: "red" }, event.text));
3884
+ return /* @__PURE__ */ React4.createElement(Box3, { marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text3, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React4.createElement(Text3, { color: "red" }, event.text));
3863
3885
  }
3864
3886
  if (event.role === "info") {
3865
- return /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, event.text));
3887
+ return /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, event.text));
3866
3888
  }
3867
3889
  if (event.role === "warning") {
3868
- return /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { color: "yellow" }, "\u25B8 "), /* @__PURE__ */ React3.createElement(Text3, { color: "yellow" }, event.text));
3890
+ return /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(Text3, { color: "yellow" }, "\u25B8 "), /* @__PURE__ */ React4.createElement(Text3, { color: "yellow" }, event.text));
3869
3891
  }
3870
- return /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, null, event.text));
3892
+ return /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(Text3, null, event.text));
3871
3893
  });
3872
3894
  function EditFileDiff({ text }) {
3873
3895
  const lines = text.split(/\r?\n/);
3874
3896
  const [statusHeader, hunkHeader, ...body] = lines;
3875
- return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, ` ${statusHeader ?? ""}`), hunkHeader !== void 0 ? /* @__PURE__ */ React3.createElement(Text3, { color: "cyan", bold: true }, hunkHeader) : null, body.map((line, i) => {
3897
+ return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, ` ${statusHeader ?? ""}`), hunkHeader !== void 0 ? /* @__PURE__ */ React4.createElement(Text3, { color: "cyan", bold: true }, hunkHeader) : null, body.map((line, i) => {
3876
3898
  const key = `${i}-${line.slice(0, 32)}`;
3877
3899
  if (line.startsWith("- ")) {
3878
- return /* @__PURE__ */ React3.createElement(Text3, { key, color: "red" }, line);
3900
+ return /* @__PURE__ */ React4.createElement(Text3, { key, color: "red" }, line);
3879
3901
  }
3880
3902
  if (line.startsWith("+ ")) {
3881
- return /* @__PURE__ */ React3.createElement(Text3, { key, color: "green" }, line);
3903
+ return /* @__PURE__ */ React4.createElement(Text3, { key, color: "green" }, line);
3882
3904
  }
3883
- return /* @__PURE__ */ React3.createElement(Text3, { key, dimColor: true }, line);
3905
+ return /* @__PURE__ */ React4.createElement(Text3, { key, dimColor: true }, line);
3884
3906
  }));
3885
3907
  }
3886
3908
  function BranchBlock({ branch }) {
@@ -3889,33 +3911,28 @@ function BranchBlock({ branch }) {
3889
3911
  const t = (branch.temperatures[i] ?? 0).toFixed(1);
3890
3912
  return `${marker} #${i} T=${t} u=${u}`;
3891
3913
  }).join(" ");
3892
- return /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { color: "blue" }, "\u{1F500} branched ", /* @__PURE__ */ React3.createElement(Text3, { bold: true }, branch.budget), ` samples \u2192 picked #${branch.chosenIndex} `, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, per)));
3914
+ return /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(Text3, { color: "blue" }, "\u{1F500} branched ", /* @__PURE__ */ React4.createElement(Text3, { bold: true }, branch.budget), ` samples \u2192 picked #${branch.chosenIndex} `, /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, per)));
3893
3915
  }
3894
3916
  function ReasoningBlock({ reasoning }) {
3895
3917
  const max = 260;
3896
3918
  const flat = reasoning.replace(/\s+/g, " ").trim();
3897
3919
  const preview = flat.length <= max ? flat : `\u2026 (+${flat.length - max} earlier chars) ${flat.slice(-max)}`;
3898
- return /* @__PURE__ */ React3.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true, italic: true }, "\u21B3 thinking: ", preview));
3920
+ return /* @__PURE__ */ React4.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React4.createElement(Text3, { dimColor: true, italic: true }, "\u21B3 thinking: ", preview));
3899
3921
  }
3900
3922
  function Elapsed() {
3901
- const [s, setS] = useState(0);
3902
- useEffect(() => {
3903
- const start = Date.now();
3904
- const id = setInterval(() => setS(Math.floor((Date.now() - start) / 1e3)), 1e3);
3905
- return () => clearInterval(id);
3906
- }, []);
3923
+ const s = useElapsedSeconds();
3907
3924
  const mm = String(Math.floor(s / 60)).padStart(2, "0");
3908
3925
  const ss = String(s % 60).padStart(2, "0");
3909
- return /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, `${mm}:${ss}`);
3926
+ return /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, `${mm}:${ss}`);
3910
3927
  }
3911
3928
  function StreamingAssistant({ event }) {
3912
3929
  if (event.branchProgress) {
3913
3930
  const p = event.branchProgress;
3914
3931
  if (p.completed === 0) {
3915
- return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { bold: true, color: "green" }, "assistant", " "), /* @__PURE__ */ React3.createElement(Text3, { color: "blue" }, "\u{1F500} launching ", p.total, " parallel samples (R1 thinking in parallel)\u2026", " "), /* @__PURE__ */ React3.createElement(Elapsed, null)), /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " ", "spread across T=0.0/0.5/1.0 \xB7 typical wait 30-90s for reasoner"));
3932
+ return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(Text3, { bold: true, color: "green" }, "assistant", " "), /* @__PURE__ */ React4.createElement(Text3, { color: "blue" }, "\u{1F500} launching ", p.total, " parallel samples (R1 thinking in parallel)\u2026", " "), /* @__PURE__ */ React4.createElement(Elapsed, null)), /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, " ", "spread across T=0.0/0.5/1.0 \xB7 typical wait 30-90s for reasoner"));
3916
3933
  }
3917
3934
  const pct2 = Math.round(p.completed / p.total * 100);
3918
- return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { bold: true, color: "green" }, "assistant", " "), /* @__PURE__ */ React3.createElement(Text3, { color: "blue" }, "\u{1F500} branching ", p.completed, "/", p.total, " (", pct2, "%)", " "), /* @__PURE__ */ React3.createElement(Elapsed, null)), /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " latest #", p.latestIndex, " T=", p.latestTemperature.toFixed(1), " u=", p.latestUncertainties, p.completed < p.total ? " \xB7 waiting for other samples\u2026" : " \xB7 selecting winner\u2026"));
3935
+ return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(Text3, { bold: true, color: "green" }, "assistant", " "), /* @__PURE__ */ React4.createElement(Text3, { color: "blue" }, "\u{1F500} branching ", p.completed, "/", p.total, " (", pct2, "%)", " "), /* @__PURE__ */ React4.createElement(Elapsed, null)), /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, " latest #", p.latestIndex, " T=", p.latestTemperature.toFixed(1), " u=", p.latestUncertainties, p.completed < p.total ? " \xB7 waiting for other samples\u2026" : " \xB7 selecting winner\u2026"));
3919
3936
  }
3920
3937
  const tail = lastLine(event.text, 140);
3921
3938
  const reasoningTail = event.reasoning ? lastLine(event.reasoning, 120) : "";
@@ -3943,16 +3960,12 @@ function StreamingAssistant({ event }) {
3943
3960
  label = parts.join(" \xB7 ");
3944
3961
  labelColor = "green";
3945
3962
  }
3946
- return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { bold: true, color: "green" }, "assistant", " "), /* @__PURE__ */ React3.createElement(Pulse, null), /* @__PURE__ */ React3.createElement(Text3, { color: labelColor }, ` ${label} `), /* @__PURE__ */ React3.createElement(Elapsed, null)), reasoningTail ? /* @__PURE__ */ React3.createElement(Text3, { dimColor: true, italic: true }, "\u21B3 thinking: ", reasoningTail) : null, tail ? /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "\u25B8 ", tail) : reasoningOnly ? /* @__PURE__ */ React3.createElement(Text3, { color: "yellow", dimColor: true }, " R1 is thinking before it speaks \u2014 body text starts when reasoning completes (typically 20-90s).") : /* @__PURE__ */ React3.createElement(Text3, { dimColor: true, italic: true }, " connection open, first byte typically in 5-60s depending on model + load"));
3963
+ return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(Text3, { bold: true, color: "green" }, "assistant", " "), /* @__PURE__ */ React4.createElement(Pulse, null), /* @__PURE__ */ React4.createElement(Text3, { color: labelColor }, ` ${label} `), /* @__PURE__ */ React4.createElement(Elapsed, null)), reasoningTail ? /* @__PURE__ */ React4.createElement(Text3, { dimColor: true, italic: true }, "\u21B3 thinking: ", reasoningTail) : null, tail ? /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, "\u25B8 ", tail) : reasoningOnly ? /* @__PURE__ */ React4.createElement(Text3, { color: "yellow", dimColor: true }, " R1 is thinking before it speaks \u2014 body text starts when reasoning completes (typically 20-90s).") : /* @__PURE__ */ React4.createElement(Text3, { dimColor: true, italic: true }, " connection open, first byte typically in 5-60s depending on model + load"));
3947
3964
  }
3948
3965
  function Pulse() {
3949
- const [tick, setTick] = useState(0);
3950
- useEffect(() => {
3951
- const id = setInterval(() => setTick((t) => t + 1), 500);
3952
- return () => clearInterval(id);
3953
- }, []);
3966
+ const tick = useTick();
3954
3967
  const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
3955
- return /* @__PURE__ */ React3.createElement(Text3, { color: "cyan" }, frames[tick % frames.length]);
3968
+ return /* @__PURE__ */ React4.createElement(Text3, { color: "cyan" }, frames[Math.floor(tick / 4) % frames.length]);
3956
3969
  }
3957
3970
  function lastLine(s, maxChars) {
3958
3971
  const flat = s.replace(/\s+/g, " ").trim();
@@ -3961,7 +3974,7 @@ function lastLine(s, maxChars) {
3961
3974
  }
3962
3975
  function StatsLine({ stats }) {
3963
3976
  const hit = (stats.cacheHitRatio * 100).toFixed(1);
3964
- return /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " \u21B3 cache ", hit, "% \xB7 tokens ", stats.usage.promptTokens, "\u2192", stats.usage.completionTokens, " \xB7 $", stats.cost.toFixed(6));
3977
+ return /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, " \u21B3 cache ", hit, "% \xB7 tokens ", stats.usage.promptTokens, "\u2192", stats.usage.completionTokens, " \xB7 $", stats.cost.toFixed(6));
3965
3978
  }
3966
3979
  function truncate2(s, max) {
3967
3980
  return s.length <= max ? s : `${s.slice(0, max)}\u2026 (+${s.length - max} chars)`;
@@ -3969,7 +3982,7 @@ function truncate2(s, max) {
3969
3982
 
3970
3983
  // src/cli/ui/PromptInput.tsx
3971
3984
  import { Box as Box4, Text as Text4, useInput } from "ink";
3972
- import React4, { useEffect as useEffect2, useState as useState2 } from "react";
3985
+ import React5 from "react";
3973
3986
 
3974
3987
  // src/cli/ui/multiline-keys.ts
3975
3988
  var BACKSLASH_SUFFIX = /\\$/;
@@ -4013,16 +4026,8 @@ function PromptInput({
4013
4026
  disabled,
4014
4027
  placeholder
4015
4028
  }) {
4016
- const [showCursor, setShowCursor] = useState2(true);
4017
- useEffect2(() => {
4018
- if (disabled) {
4019
- setShowCursor(false);
4020
- return;
4021
- }
4022
- setShowCursor(true);
4023
- const id = setInterval(() => setShowCursor((s) => !s), 500);
4024
- return () => clearInterval(id);
4025
- }, [disabled]);
4029
+ const tick = useTick();
4030
+ const showCursor = disabled ? false : Math.floor(tick / 4) % 2 === 0;
4026
4031
  useInput(
4027
4032
  (input, key) => {
4028
4033
  const keyEvent = {
@@ -4051,27 +4056,27 @@ function PromptInput({
4051
4056
  const effectivePlaceholder = disabled ? placeholder ?? "\u2026waiting for response\u2026" : placeholder ?? "type a message, or /command \xB7 Ctrl+J for newline";
4052
4057
  const lines = value.length > 0 ? value.split("\n") : [""];
4053
4058
  const borderColor = disabled ? "gray" : "cyan";
4054
- return /* @__PURE__ */ React4.createElement(Box4, { borderStyle: "round", borderColor, paddingX: 1, flexDirection: "column" }, lines.map((line, i) => {
4059
+ return /* @__PURE__ */ React5.createElement(Box4, { borderStyle: "round", borderColor, paddingX: 1, flexDirection: "column" }, lines.map((line, i) => {
4055
4060
  const isLast = i === lines.length - 1;
4056
4061
  const isFirst = i === 0;
4057
4062
  const showPlaceholder = isFirst && value.length === 0;
4058
4063
  return (
4059
4064
  // biome-ignore lint/suspicious/noArrayIndexKey: stable by construction — lines are derived from `value.split("\n")` and never reordered
4060
- /* @__PURE__ */ React4.createElement(Box4, { key: i }, isFirst ? /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: borderColor }, "you \u203A", " ") : /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, " "), showPlaceholder && isLast && !disabled ? /* @__PURE__ */ React4.createElement(Text4, { color: borderColor }, showCursor ? "\u258C" : " ") : null, showPlaceholder ? /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, effectivePlaceholder) : /* @__PURE__ */ React4.createElement(Text4, null, line), !showPlaceholder && isLast && !disabled ? /* @__PURE__ */ React4.createElement(Text4, { color: borderColor }, showCursor ? "\u258C" : " ") : null)
4065
+ /* @__PURE__ */ React5.createElement(Box4, { key: i }, isFirst ? /* @__PURE__ */ React5.createElement(Text4, { bold: true, color: borderColor }, "you \u203A", " ") : /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, " "), showPlaceholder && isLast && !disabled ? /* @__PURE__ */ React5.createElement(Text4, { color: borderColor }, showCursor ? "\u258C" : " ") : null, showPlaceholder ? /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, effectivePlaceholder) : /* @__PURE__ */ React5.createElement(Text4, null, line), !showPlaceholder && isLast && !disabled ? /* @__PURE__ */ React5.createElement(Text4, { color: borderColor }, showCursor ? "\u258C" : " ") : null)
4061
4066
  );
4062
4067
  }));
4063
4068
  }
4064
4069
 
4065
4070
  // src/cli/ui/SlashSuggestions.tsx
4066
4071
  import { Box as Box5, Text as Text5 } from "ink";
4067
- import React5 from "react";
4072
+ import React6 from "react";
4068
4073
  function SlashSuggestions({
4069
4074
  matches,
4070
4075
  selectedIndex
4071
4076
  }) {
4072
4077
  if (matches === null) return null;
4073
4078
  if (matches.length === 0) {
4074
- return /* @__PURE__ */ React5.createElement(Box5, { paddingX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "yellow" }, "no slash command matches that prefix"), /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, " \u2014 Backspace to edit, or /help for the full list"));
4079
+ return /* @__PURE__ */ React6.createElement(Box5, { paddingX: 1 }, /* @__PURE__ */ React6.createElement(Text5, { color: "yellow" }, "no slash command matches that prefix"), /* @__PURE__ */ React6.createElement(Text5, { dimColor: true }, " \u2014 Backspace to edit, or /help for the full list"));
4075
4080
  }
4076
4081
  const MAX = 8;
4077
4082
  const total = matches.length;
@@ -4079,21 +4084,21 @@ function SlashSuggestions({
4079
4084
  const shown = matches.slice(windowStart, windowStart + MAX);
4080
4085
  const hiddenAbove = windowStart;
4081
4086
  const hiddenBelow = total - windowStart - shown.length;
4082
- return /* @__PURE__ */ React5.createElement(Box5, { flexDirection: "column", paddingX: 1 }, hiddenAbove > 0 ? /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, " \u2191 ", hiddenAbove, " more above") : null, shown.map((spec, i) => /* @__PURE__ */ React5.createElement(SuggestionRow, { key: spec.cmd, spec, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, " \u2193 ", hiddenBelow, " more below") : null, /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, " \u2191/\u2193 navigate \xB7 Tab or Enter to pick"));
4087
+ return /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column", paddingX: 1 }, hiddenAbove > 0 ? /* @__PURE__ */ React6.createElement(Text5, { dimColor: true }, " \u2191 ", hiddenAbove, " more above") : null, shown.map((spec, i) => /* @__PURE__ */ React6.createElement(SuggestionRow, { key: spec.cmd, spec, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React6.createElement(Text5, { dimColor: true }, " \u2193 ", hiddenBelow, " more below") : null, /* @__PURE__ */ React6.createElement(Text5, { dimColor: true }, " \u2191/\u2193 navigate \xB7 Tab or Enter to pick"));
4083
4088
  }
4084
4089
  function SuggestionRow({ spec, isSelected }) {
4085
4090
  const marker = isSelected ? "\u25B8" : " ";
4086
4091
  const name = `/${spec.cmd}`;
4087
4092
  const argsSuffix = spec.argsHint ? ` ${spec.argsHint}` : "";
4088
4093
  if (isSelected) {
4089
- return /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { bold: true, color: "cyan" }, marker, " ", name.padEnd(12), argsSuffix.padEnd(16)), /* @__PURE__ */ React5.createElement(Text5, { color: "cyan" }, " ", spec.summary));
4094
+ return /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text5, { bold: true, color: "cyan" }, marker, " ", name.padEnd(12), argsSuffix.padEnd(16)), /* @__PURE__ */ React6.createElement(Text5, { color: "cyan" }, " ", spec.summary));
4090
4095
  }
4091
- return /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, marker, " ", name.padEnd(12), argsSuffix.padEnd(16), " ", spec.summary));
4096
+ return /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text5, { dimColor: true }, marker, " ", name.padEnd(12), argsSuffix.padEnd(16), " ", spec.summary));
4092
4097
  }
4093
4098
 
4094
4099
  // src/cli/ui/StatsPanel.tsx
4095
4100
  import { Box as Box6, Text as Text6 } from "ink";
4096
- import React6 from "react";
4101
+ import React7 from "react";
4097
4102
  function StatsPanel({
4098
4103
  summary,
4099
4104
  model,
@@ -4108,7 +4113,7 @@ function StatsPanel({
4108
4113
  const ctxMax = DEEPSEEK_CONTEXT_TOKENS[model] ?? DEFAULT_CONTEXT_TOKENS;
4109
4114
  const ctxRatio = summary.lastPromptTokens / ctxMax;
4110
4115
  const ctxColor = ctxRatio >= 0.8 ? "red" : ctxRatio >= 0.5 ? "yellow" : void 0;
4111
- return /* @__PURE__ */ React6.createElement(Box6, { borderStyle: "round", borderColor: "cyan", flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React6.createElement(Box6, { justifyContent: "space-between" }, /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan", bold: true }, "Reasonix"), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 model "), /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, model), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 prefix "), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, prefixHash), harvestOn ? /* @__PURE__ */ React6.createElement(Text6, { color: "magenta" }, " \xB7 harvest") : null, branchOn ? /* @__PURE__ */ React6.createElement(Text6, { color: "blue" }, " \xB7 branch", branchBudget) : null), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "turns ", summary.turns, " \xB7 type /help")), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "cache hit "), /* @__PURE__ */ React6.createElement(Text6, { color: hitColor, bold: true }, hitPct, "%")), /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "cost "), /* @__PURE__ */ React6.createElement(Text6, { color: "green", bold: true }, "$", summary.totalCostUsd.toFixed(6)), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " (in ", "$", summary.totalInputCostUsd.toFixed(6), " \xB7 out ", "$", summary.totalOutputCostUsd.toFixed(6), ")")), summary.lastPromptTokens > 0 ? /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "ctx "), /* @__PURE__ */ React6.createElement(Text6, { color: ctxColor, bold: ctxColor !== void 0 }, formatTokens(summary.lastPromptTokens), "/", formatTokens(ctxMax)), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " (", (ctxRatio * 100).toFixed(0), "%)"), ctxRatio >= 0.8 ? /* @__PURE__ */ React6.createElement(Text6, { color: "red", bold: true }, " ", "\xB7 /compact") : null) : null, balance ? /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "balance "), /* @__PURE__ */ React6.createElement(Text6, { color: balance.total < 1 ? "red" : balance.total < 5 ? "yellow" : "green", bold: true }, balance.currency === "USD" ? "$" : "", balance.total.toFixed(2), balance.currency !== "USD" ? ` ${balance.currency}` : "")) : null));
4116
+ return /* @__PURE__ */ React7.createElement(Box6, { borderStyle: "round", borderColor: "cyan", flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React7.createElement(Box6, { justifyContent: "space-between" }, /* @__PURE__ */ React7.createElement(Text6, null, /* @__PURE__ */ React7.createElement(Text6, { color: "cyan", bold: true }, "Reasonix"), /* @__PURE__ */ React7.createElement(Text6, { dimColor: true }, " \xB7 model "), /* @__PURE__ */ React7.createElement(Text6, { color: "yellow" }, model), /* @__PURE__ */ React7.createElement(Text6, { dimColor: true }, " \xB7 prefix "), /* @__PURE__ */ React7.createElement(Text6, { dimColor: true }, prefixHash), harvestOn ? /* @__PURE__ */ React7.createElement(Text6, { color: "magenta" }, " \xB7 harvest") : null, branchOn ? /* @__PURE__ */ React7.createElement(Text6, { color: "blue" }, " \xB7 branch", branchBudget) : null), /* @__PURE__ */ React7.createElement(Text6, { dimColor: true }, "turns ", summary.turns, " \xB7 type /help")), /* @__PURE__ */ React7.createElement(Box6, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React7.createElement(Text6, null, /* @__PURE__ */ React7.createElement(Text6, { dimColor: true }, "cache hit "), /* @__PURE__ */ React7.createElement(Text6, { color: hitColor, bold: true }, hitPct, "%")), /* @__PURE__ */ React7.createElement(Text6, null, /* @__PURE__ */ React7.createElement(Text6, { dimColor: true }, "cost "), /* @__PURE__ */ React7.createElement(Text6, { color: "green", bold: true }, "$", summary.totalCostUsd.toFixed(6)), /* @__PURE__ */ React7.createElement(Text6, { dimColor: true }, " (in ", "$", summary.totalInputCostUsd.toFixed(6), " \xB7 out ", "$", summary.totalOutputCostUsd.toFixed(6), ")")), summary.lastPromptTokens > 0 ? /* @__PURE__ */ React7.createElement(Text6, null, /* @__PURE__ */ React7.createElement(Text6, { dimColor: true }, "ctx "), /* @__PURE__ */ React7.createElement(Text6, { color: ctxColor, bold: ctxColor !== void 0 }, formatTokens(summary.lastPromptTokens), "/", formatTokens(ctxMax)), /* @__PURE__ */ React7.createElement(Text6, { dimColor: true }, " (", (ctxRatio * 100).toFixed(0), "%)"), ctxRatio >= 0.8 ? /* @__PURE__ */ React7.createElement(Text6, { color: "red", bold: true }, " ", "\xB7 /compact") : null) : null, balance ? /* @__PURE__ */ React7.createElement(Text6, null, /* @__PURE__ */ React7.createElement(Text6, { dimColor: true }, "balance "), /* @__PURE__ */ React7.createElement(Text6, { color: balance.total < 1 ? "red" : balance.total < 5 ? "yellow" : "green", bold: true }, balance.currency === "USD" ? "$" : "", balance.total.toFixed(2), balance.currency !== "USD" ? ` ${balance.currency}` : "")) : null));
4112
4117
  }
4113
4118
  function formatTokens(n) {
4114
4119
  if (n < 1e3) return String(n);
@@ -4556,7 +4561,8 @@ function gitTail(res) {
4556
4561
  }
4557
4562
 
4558
4563
  // src/cli/ui/App.tsx
4559
- var FLUSH_INTERVAL_MS = 60;
4564
+ var FLUSH_INTERVAL_MS = 100;
4565
+ var PLAIN_UI = process.env.REASONIX_UI === "plain";
4560
4566
  function App({
4561
4567
  model,
4562
4568
  system,
@@ -4571,23 +4577,23 @@ function App({
4571
4577
  codeMode
4572
4578
  }) {
4573
4579
  const { exit } = useApp();
4574
- const [historical, setHistorical] = useState3([]);
4575
- const [streaming, setStreaming] = useState3(null);
4576
- const [input, setInput] = useState3("");
4577
- const [busy, setBusy] = useState3(false);
4580
+ const [historical, setHistorical] = useState2([]);
4581
+ const [streaming, setStreaming] = useState2(null);
4582
+ const [input, setInput] = useState2("");
4583
+ const [busy, setBusy] = useState2(false);
4578
4584
  const abortedThisTurn = useRef(false);
4579
- const [ongoingTool, setOngoingTool] = useState3(null);
4580
- const [toolProgress, setToolProgress] = useState3(null);
4581
- const [statusLine, setStatusLine] = useState3(null);
4582
- const [balance, setBalance] = useState3(null);
4585
+ const [ongoingTool, setOngoingTool] = useState2(null);
4586
+ const [toolProgress, setToolProgress] = useState2(null);
4587
+ const [statusLine, setStatusLine] = useState2(null);
4588
+ const [balance, setBalance] = useState2(null);
4583
4589
  const lastEditSnapshots = useRef(null);
4584
4590
  const pendingEdits = useRef([]);
4585
4591
  const promptHistory = useRef([]);
4586
4592
  const historyCursor = useRef(-1);
4587
4593
  const assistantIterCounter = useRef(0);
4588
4594
  const toolHistoryRef = useRef([]);
4589
- const [slashSelected, setSlashSelected] = useState3(0);
4590
- const [summary, setSummary] = useState3({
4595
+ const [slashSelected, setSlashSelected] = useState2(0);
4596
+ const [summary, setSummary] = useState2({
4591
4597
  turns: 0,
4592
4598
  totalCostUsd: 0,
4593
4599
  totalInputCostUsd: 0,
@@ -4606,7 +4612,7 @@ function App({
4606
4612
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
4607
4613
  });
4608
4614
  }
4609
- useEffect3(() => {
4615
+ useEffect2(() => {
4610
4616
  return () => {
4611
4617
  transcriptRef.current?.end();
4612
4618
  };
@@ -4615,7 +4621,7 @@ function App({
4615
4621
  if (!input.startsWith("/") || input.includes(" ")) return null;
4616
4622
  return suggestSlashCommands(input.slice(1), !!codeMode);
4617
4623
  }, [input, codeMode]);
4618
- useEffect3(() => {
4624
+ useEffect2(() => {
4619
4625
  setSlashSelected((prev) => {
4620
4626
  if (!slashMatches || slashMatches.length === 0) return 0;
4621
4627
  if (prev >= slashMatches.length) return slashMatches.length - 1;
@@ -4634,7 +4640,7 @@ function App({
4634
4640
  loopRef.current = l;
4635
4641
  return l;
4636
4642
  }, [model, system, harvest2, branch, session, tools]);
4637
- useEffect3(() => {
4643
+ useEffect2(() => {
4638
4644
  let cancelled = false;
4639
4645
  void (async () => {
4640
4646
  const bal = await loop.client.getBalance().catch(() => null);
@@ -4646,7 +4652,7 @@ function App({
4646
4652
  cancelled = true;
4647
4653
  };
4648
4654
  }, [loop]);
4649
- useEffect3(() => {
4655
+ useEffect2(() => {
4650
4656
  if (!progressSink) return;
4651
4657
  progressSink.current = (info) => {
4652
4658
  setToolProgress({
@@ -4660,7 +4666,7 @@ function App({
4660
4666
  };
4661
4667
  }, [progressSink]);
4662
4668
  const sessionBannerShown = useRef(false);
4663
- useEffect3(() => {
4669
+ useEffect2(() => {
4664
4670
  if (sessionBannerShown.current) return;
4665
4671
  sessionBannerShown.current = true;
4666
4672
  if (!session) {
@@ -4869,7 +4875,7 @@ function App({
4869
4875
  streaming: true
4870
4876
  });
4871
4877
  };
4872
- const timer = setInterval(flush, FLUSH_INTERVAL_MS);
4878
+ const timer = PLAIN_UI ? null : setInterval(flush, FLUSH_INTERVAL_MS);
4873
4879
  try {
4874
4880
  for await (const ev of loop.step(text)) {
4875
4881
  writeTranscript(ev);
@@ -4981,7 +4987,7 @@ function App({
4981
4987
  }
4982
4988
  flush();
4983
4989
  } finally {
4984
- clearInterval(timer);
4990
+ if (timer) clearInterval(timer);
4985
4991
  setStreaming(null);
4986
4992
  setOngoingTool(null);
4987
4993
  setToolProgress(null);
@@ -5011,7 +5017,7 @@ function App({
5011
5017
  writeTranscript
5012
5018
  ]
5013
5019
  );
5014
- return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column" }, /* @__PURE__ */ React7.createElement(
5020
+ return /* @__PURE__ */ React8.createElement(TickerProvider, { disabled: PLAIN_UI }, /* @__PURE__ */ React8.createElement(Box7, { flexDirection: "column" }, /* @__PURE__ */ React8.createElement(
5015
5021
  StatsPanel,
5016
5022
  {
5017
5023
  summary,
@@ -5021,41 +5027,22 @@ function App({
5021
5027
  branchBudget: loop.branchOptions.budget,
5022
5028
  balance
5023
5029
  }
5024
- ), /* @__PURE__ */ React7.createElement(Static, { items: historical }, (item) => /* @__PURE__ */ React7.createElement(EventRow, { key: item.id, event: item })), streaming ? /* @__PURE__ */ React7.createElement(Box7, { marginY: 1 }, /* @__PURE__ */ React7.createElement(EventRow, { event: streaming })) : null, ongoingTool ? /* @__PURE__ */ React7.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !ongoingTool && statusLine ? /* @__PURE__ */ React7.createElement(StatusRow, { text: statusLine }) : null, busy && !streaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React7.createElement(StatusRow, { text: "processing\u2026" }) : null, /* @__PURE__ */ React7.createElement(PromptInput, { value: input, onChange: setInput, onSubmit: handleSubmit, disabled: busy }), /* @__PURE__ */ React7.createElement(SlashSuggestions, { matches: slashMatches, selectedIndex: slashSelected }));
5030
+ ), /* @__PURE__ */ React8.createElement(Static, { items: historical }, (item) => /* @__PURE__ */ React8.createElement(EventRow, { key: item.id, event: item })), !PLAIN_UI && streaming ? /* @__PURE__ */ React8.createElement(Box7, { marginY: 1 }, /* @__PURE__ */ React8.createElement(EventRow, { event: streaming })) : null, !PLAIN_UI && ongoingTool ? /* @__PURE__ */ React8.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !PLAIN_UI && !ongoingTool && statusLine ? /* @__PURE__ */ React8.createElement(StatusRow, { text: statusLine }) : null, !PLAIN_UI && busy && !streaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React8.createElement(StatusRow, { text: "processing\u2026" }) : null, /* @__PURE__ */ React8.createElement(PromptInput, { value: input, onChange: setInput, onSubmit: handleSubmit, disabled: busy }), /* @__PURE__ */ React8.createElement(SlashSuggestions, { matches: slashMatches, selectedIndex: slashSelected })));
5025
5031
  }
5032
+ var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
5026
5033
  function StatusRow({ text }) {
5027
- const [tick, setTick] = useState3(0);
5028
- const [elapsed, setElapsed] = useState3(0);
5029
- useEffect3(() => {
5030
- const start = Date.now();
5031
- const frameId = setInterval(() => setTick((t) => t + 1), 120);
5032
- const secId = setInterval(() => setElapsed(Math.floor((Date.now() - start) / 1e3)), 1e3);
5033
- return () => {
5034
- clearInterval(frameId);
5035
- clearInterval(secId);
5036
- };
5037
- }, []);
5038
- const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
5039
- return /* @__PURE__ */ React7.createElement(Box7, { marginY: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "magenta" }, frames[tick % frames.length]), /* @__PURE__ */ React7.createElement(Text7, { color: "magenta" }, ` ${text}`), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, ` ${elapsed}s`));
5034
+ const tick = useTick();
5035
+ const elapsed = useElapsedSeconds();
5036
+ return /* @__PURE__ */ React8.createElement(Box7, { marginY: 1 }, /* @__PURE__ */ React8.createElement(Text7, { color: "magenta" }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React8.createElement(Text7, { color: "magenta" }, ` ${text}`), /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, ` ${elapsed}s`));
5040
5037
  }
5041
5038
  function OngoingToolRow({
5042
5039
  tool,
5043
5040
  progress
5044
5041
  }) {
5045
- const [tick, setTick] = useState3(0);
5046
- const [elapsed, setElapsed] = useState3(0);
5047
- useEffect3(() => {
5048
- const start = Date.now();
5049
- const frameId = setInterval(() => setTick((t) => t + 1), 120);
5050
- const secId = setInterval(() => setElapsed(Math.floor((Date.now() - start) / 1e3)), 1e3);
5051
- return () => {
5052
- clearInterval(frameId);
5053
- clearInterval(secId);
5054
- };
5055
- }, []);
5056
- const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
5042
+ const tick = useTick();
5043
+ const elapsed = useElapsedSeconds();
5057
5044
  const summary = summarizeToolArgs(tool.name, tool.args);
5058
- return /* @__PURE__ */ React7.createElement(Box7, { marginY: 1, flexDirection: "column" }, /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, frames[tick % frames.length]), /* @__PURE__ */ React7.createElement(Text7, { color: "yellow" }, ` tool<${tool.name}> running\u2026`), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, ` ${elapsed}s`)), progress ? /* @__PURE__ */ React7.createElement(Box7, { paddingLeft: 2 }, /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ React7.createElement(Box7, { paddingLeft: 2 }, /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, summary)) : null);
5045
+ return /* @__PURE__ */ React8.createElement(Box7, { marginY: 1, flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Box7, null, /* @__PURE__ */ React8.createElement(Text7, { color: "cyan" }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React8.createElement(Text7, { color: "yellow" }, ` tool<${tool.name}> running\u2026`), /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, ` ${elapsed}s`)), progress ? /* @__PURE__ */ React8.createElement(Box7, { paddingLeft: 2 }, /* @__PURE__ */ React8.createElement(Text7, { color: "cyan" }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ React8.createElement(Box7, { paddingLeft: 2 }, /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, summary)) : null);
5059
5046
  }
5060
5047
  function renderProgressLine(p) {
5061
5048
  const msg = p.message ? ` ${p.message}` : "";
@@ -5153,10 +5140,10 @@ function describeRepair(repair) {
5153
5140
  // src/cli/ui/Setup.tsx
5154
5141
  import { Box as Box8, Text as Text8, useApp as useApp2 } from "ink";
5155
5142
  import TextInput from "ink-text-input";
5156
- import React8, { useState as useState4 } from "react";
5143
+ import React9, { useState as useState3 } from "react";
5157
5144
  function Setup({ onReady }) {
5158
- const [value, setValue] = useState4("");
5159
- const [error, setError] = useState4(null);
5145
+ const [value, setValue] = useState3("");
5146
+ const [error, setError] = useState3(null);
5160
5147
  const { exit } = useApp2();
5161
5148
  const handleSubmit = (raw) => {
5162
5149
  const trimmed = raw.trim();
@@ -5177,7 +5164,7 @@ function Setup({ onReady }) {
5177
5164
  }
5178
5165
  onReady(trimmed);
5179
5166
  };
5180
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React8.createElement(Text8, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React8.createElement(Text8, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React8.createElement(Text8, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React8.createElement(
5167
+ return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React9.createElement(Text8, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text8, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text8, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React9.createElement(
5181
5168
  TextInput,
5182
5169
  {
5183
5170
  value,
@@ -5186,14 +5173,14 @@ function Setup({ onReady }) {
5186
5173
  mask: "\u2022",
5187
5174
  placeholder: "sk-..."
5188
5175
  }
5189
- )), error ? /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "red" }, error)) : value ? /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, { dimColor: true }, "preview: ", redactKey(value))) : null, /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, { dimColor: true }, "(Type /exit to abort.)")));
5176
+ )), error ? /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text8, { color: "red" }, error)) : value ? /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, "preview: ", redactKey(value))) : null, /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, "(Type /exit to abort.)")));
5190
5177
  }
5191
5178
 
5192
5179
  // src/cli/commands/chat.tsx
5193
5180
  function Root({ initialKey, tools, mcpSpecs, mcpServers, progressSink, ...appProps }) {
5194
- const [key, setKey] = useState5(initialKey);
5181
+ const [key, setKey] = useState4(initialKey);
5195
5182
  if (!key) {
5196
- return /* @__PURE__ */ React9.createElement(
5183
+ return /* @__PURE__ */ React10.createElement(
5197
5184
  Setup,
5198
5185
  {
5199
5186
  onReady: (k) => {
@@ -5204,7 +5191,7 @@ function Root({ initialKey, tools, mcpSpecs, mcpServers, progressSink, ...appPro
5204
5191
  );
5205
5192
  }
5206
5193
  process.env.DEEPSEEK_API_KEY = key;
5207
- return /* @__PURE__ */ React9.createElement(
5194
+ return /* @__PURE__ */ React10.createElement(
5208
5195
  App,
5209
5196
  {
5210
5197
  model: appProps.model,
@@ -5288,7 +5275,7 @@ async function chatCommand(opts) {
5288
5275
  }
5289
5276
  const mcpSpecs = successfulSpecs;
5290
5277
  const { waitUntilExit } = render(
5291
- /* @__PURE__ */ React9.createElement(
5278
+ /* @__PURE__ */ React10.createElement(
5292
5279
  Root,
5293
5280
  {
5294
5281
  initialKey,
@@ -5299,7 +5286,9 @@ async function chatCommand(opts) {
5299
5286
  ...opts
5300
5287
  }
5301
5288
  ),
5302
- { exitOnCtrlC: true }
5289
+ // patchConsole:false we never log to console during the TUI, and the
5290
+ // patch is a known redraw-glitch source on winpty/MINTTY terminals.
5291
+ { exitOnCtrlC: true, patchConsole: false }
5303
5292
  );
5304
5293
  try {
5305
5294
  await waitUntilExit();
@@ -5336,34 +5325,34 @@ async function codeCommand(opts = {}) {
5336
5325
  import { writeFileSync as writeFileSync4 } from "fs";
5337
5326
  import { basename as basename2 } from "path";
5338
5327
  import { render as render2 } from "ink";
5339
- import React12 from "react";
5328
+ import React13 from "react";
5340
5329
 
5341
5330
  // src/cli/ui/DiffApp.tsx
5342
5331
  import { Box as Box10, Static as Static2, Text as Text10, useApp as useApp3, useInput as useInput3 } from "ink";
5343
- import React11, { useState as useState6 } from "react";
5332
+ import React12, { useState as useState5 } from "react";
5344
5333
 
5345
5334
  // src/cli/ui/RecordView.tsx
5346
5335
  import { Box as Box9, Text as Text9 } from "ink";
5347
- import React10 from "react";
5336
+ import React11 from "react";
5348
5337
  function RecordView({ rec, compact = false }) {
5349
5338
  const toolArgsMax = compact ? 120 : 200;
5350
5339
  const toolContentMax = compact ? 200 : 400;
5351
5340
  if (rec.role === "user") {
5352
- return /* @__PURE__ */ React10.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text9, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React10.createElement(Text9, null, rec.content));
5341
+ return /* @__PURE__ */ React11.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text9, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React11.createElement(Text9, null, rec.content));
5353
5342
  }
5354
5343
  if (rec.role === "assistant_final") {
5355
- return /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box9, null, /* @__PURE__ */ React10.createElement(Text9, { bold: true, color: "green" }, "assistant"), rec.cost !== void 0 ? /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, " $", rec.cost.toFixed(6)) : null, rec.usage ? /* @__PURE__ */ React10.createElement(CacheBadge, { usage: rec.usage }) : null), rec.planState ? /* @__PURE__ */ React10.createElement(PlanStateBlock, { planState: rec.planState }) : null, rec.content ? /* @__PURE__ */ React10.createElement(Text9, null, rec.content) : /* @__PURE__ */ React10.createElement(Text9, { dimColor: true, italic: true }, "(tool-call response only)"));
5344
+ return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(Text9, { bold: true, color: "green" }, "assistant"), rec.cost !== void 0 ? /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, " $", rec.cost.toFixed(6)) : null, rec.usage ? /* @__PURE__ */ React11.createElement(CacheBadge, { usage: rec.usage }) : null), rec.planState ? /* @__PURE__ */ React11.createElement(PlanStateBlock, { planState: rec.planState }) : null, rec.content ? /* @__PURE__ */ React11.createElement(Text9, null, rec.content) : /* @__PURE__ */ React11.createElement(Text9, { dimColor: true, italic: true }, "(tool-call response only)"));
5356
5345
  }
5357
5346
  if (rec.role === "tool") {
5358
- return /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text9, { color: "yellow" }, "tool<", rec.tool ?? "?", ">"), rec.args ? /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, " args: ", truncate3(rec.args, toolArgsMax)) : null, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, " \u2192 ", truncate3(rec.content, toolContentMax)));
5347
+ return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text9, { color: "yellow" }, "tool<", rec.tool ?? "?", ">"), rec.args ? /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, " args: ", truncate3(rec.args, toolArgsMax)) : null, /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, " \u2192 ", truncate3(rec.content, toolContentMax)));
5359
5348
  }
5360
5349
  if (rec.role === "error") {
5361
- return /* @__PURE__ */ React10.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text9, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React10.createElement(Text9, { color: "red" }, rec.error ?? rec.content));
5350
+ return /* @__PURE__ */ React11.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text9, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React11.createElement(Text9, { color: "red" }, rec.error ?? rec.content));
5362
5351
  }
5363
5352
  if (rec.role === "done" || rec.role === "assistant_delta") {
5364
5353
  return null;
5365
5354
  }
5366
- return /* @__PURE__ */ React10.createElement(Box9, null, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, "[", rec.role, "] ", rec.content));
5355
+ return /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, "[", rec.role, "] ", rec.content));
5367
5356
  }
5368
5357
  function CacheBadge({ usage }) {
5369
5358
  const hit = usage.prompt_cache_hit_tokens ?? 0;
@@ -5372,7 +5361,7 @@ function CacheBadge({ usage }) {
5372
5361
  if (total === 0) return null;
5373
5362
  const pct2 = hit / total * 100;
5374
5363
  const color = pct2 >= 70 ? "green" : pct2 >= 40 ? "yellow" : "red";
5375
- return /* @__PURE__ */ React10.createElement(Text9, null, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, " \xB7 cache "), /* @__PURE__ */ React10.createElement(Text9, { color }, pct2.toFixed(1), "%"));
5364
+ return /* @__PURE__ */ React11.createElement(Text9, null, /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, " \xB7 cache "), /* @__PURE__ */ React11.createElement(Text9, { color }, pct2.toFixed(1), "%"));
5376
5365
  }
5377
5366
  function truncate3(s, max) {
5378
5367
  return s.length <= max ? s : `${s.slice(0, max)}\u2026 (+${s.length - max} chars)`;
@@ -5383,7 +5372,7 @@ function DiffApp({ report }) {
5383
5372
  const { exit } = useApp3();
5384
5373
  const maxIdx = Math.max(0, report.pairs.length - 1);
5385
5374
  const initialIdx = report.firstDivergenceTurn ? report.pairs.findIndex((p) => p.turn === report.firstDivergenceTurn) : 0;
5386
- const [idx, setIdx] = useState6(Math.max(0, initialIdx));
5375
+ const [idx, setIdx] = useState5(Math.max(0, initialIdx));
5387
5376
  useInput3((input, key) => {
5388
5377
  if (input === "q" || key.ctrl && input === "c") {
5389
5378
  exit();
@@ -5406,7 +5395,7 @@ function DiffApp({ report }) {
5406
5395
  }
5407
5396
  });
5408
5397
  const pair = report.pairs[idx];
5409
- return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React11.createElement(DiffHeader, { report }), /* @__PURE__ */ React11.createElement(Box10, { marginTop: 1, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ React11.createElement(Text10, { color: "cyan", bold: true }, "turn ", pair?.turn ?? "?", " (", idx + 1, " / ", report.pairs.length, ")"), /* @__PURE__ */ React11.createElement(Text10, null, pair ? /* @__PURE__ */ React11.createElement(KindBadge, { kind: pair.kind }) : null)), /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React11.createElement(Pane, { label: report.a.label, headerColor: "blue", records: paneRecords(pair, "a") }), /* @__PURE__ */ React11.createElement(Pane, { label: report.b.label, headerColor: "magenta", records: paneRecords(pair, "b") })), pair?.divergenceNote ? /* @__PURE__ */ React11.createElement(Box10, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React11.createElement(Text10, { color: "yellow" }, "\u2605 "), /* @__PURE__ */ React11.createElement(Text10, null, pair.divergenceNote)) : null, /* @__PURE__ */ React11.createElement(Box10, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, /* @__PURE__ */ React11.createElement(Text10, { bold: true }, "j"), "/", /* @__PURE__ */ React11.createElement(Text10, { bold: true }, "\u2193"), " next \xB7 ", /* @__PURE__ */ React11.createElement(Text10, { bold: true }, "k"), "/", /* @__PURE__ */ React11.createElement(Text10, { bold: true }, "\u2191"), " ", "prev \xB7 ", /* @__PURE__ */ React11.createElement(Text10, { bold: true }, "n"), " next-diverge \xB7 ", /* @__PURE__ */ React11.createElement(Text10, { bold: true }, "N"), "/", /* @__PURE__ */ React11.createElement(Text10, { bold: true }, "p"), " ", "prev-diverge \xB7 ", /* @__PURE__ */ React11.createElement(Text10, { bold: true }, "g"), "/", /* @__PURE__ */ React11.createElement(Text10, { bold: true }, "G"), " first/last \xB7 ", /* @__PURE__ */ React11.createElement(Text10, { bold: true }, "q"), " ", "quit")));
5398
+ return /* @__PURE__ */ React12.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React12.createElement(DiffHeader, { report }), /* @__PURE__ */ React12.createElement(Box10, { marginTop: 1, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ React12.createElement(Text10, { color: "cyan", bold: true }, "turn ", pair?.turn ?? "?", " (", idx + 1, " / ", report.pairs.length, ")"), /* @__PURE__ */ React12.createElement(Text10, null, pair ? /* @__PURE__ */ React12.createElement(KindBadge, { kind: pair.kind }) : null)), /* @__PURE__ */ React12.createElement(Box10, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React12.createElement(Pane, { label: report.a.label, headerColor: "blue", records: paneRecords(pair, "a") }), /* @__PURE__ */ React12.createElement(Pane, { label: report.b.label, headerColor: "magenta", records: paneRecords(pair, "b") })), pair?.divergenceNote ? /* @__PURE__ */ React12.createElement(Box10, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React12.createElement(Text10, { color: "yellow" }, "\u2605 "), /* @__PURE__ */ React12.createElement(Text10, null, pair.divergenceNote)) : null, /* @__PURE__ */ React12.createElement(Box10, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React12.createElement(Text10, { dimColor: true }, /* @__PURE__ */ React12.createElement(Text10, { bold: true }, "j"), "/", /* @__PURE__ */ React12.createElement(Text10, { bold: true }, "\u2193"), " next \xB7 ", /* @__PURE__ */ React12.createElement(Text10, { bold: true }, "k"), "/", /* @__PURE__ */ React12.createElement(Text10, { bold: true }, "\u2191"), " ", "prev \xB7 ", /* @__PURE__ */ React12.createElement(Text10, { bold: true }, "n"), " next-diverge \xB7 ", /* @__PURE__ */ React12.createElement(Text10, { bold: true }, "N"), "/", /* @__PURE__ */ React12.createElement(Text10, { bold: true }, "p"), " ", "prev-diverge \xB7 ", /* @__PURE__ */ React12.createElement(Text10, { bold: true }, "g"), "/", /* @__PURE__ */ React12.createElement(Text10, { bold: true }, "G"), " first/last \xB7 ", /* @__PURE__ */ React12.createElement(Text10, { bold: true }, "q"), " ", "quit")));
5410
5399
  }
5411
5400
  function DiffHeader({ report }) {
5412
5401
  const a = report.a;
@@ -5424,14 +5413,14 @@ function DiffHeader({ report }) {
5424
5413
  } else if (a.stats.prefixHashes[0] && a.stats.prefixHashes[0] === b.stats.prefixHashes[0]) {
5425
5414
  prefixLine = `shared prefix hash ${a.stats.prefixHashes[0].slice(0, 12)}\u2026 \u2014 cache delta attributable to log stability, not prompt change.`;
5426
5415
  }
5427
- return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React11.createElement(Box10, { justifyContent: "space-between" }, /* @__PURE__ */ React11.createElement(Text10, null, /* @__PURE__ */ React11.createElement(Text10, { color: "cyan", bold: true }, "reasonix diff"), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " \xB7 A="), /* @__PURE__ */ React11.createElement(Text10, { color: "blue" }, a.label), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " vs B="), /* @__PURE__ */ React11.createElement(Text10, { color: "magenta" }, b.label)), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, report.pairs.length, " turns aligned")), /* @__PURE__ */ React11.createElement(Box10, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React11.createElement(Text10, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "cache "), /* @__PURE__ */ React11.createElement(Text10, null, (a.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React11.createElement(Text10, null, (b.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React11.createElement(Text10, { color: cacheDelta >= 0 ? "green" : "red", bold: true }, " ", cacheDelta >= 0 ? "+" : "", (cacheDelta * 100).toFixed(1), "pp")), /* @__PURE__ */ React11.createElement(Text10, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "cost "), /* @__PURE__ */ React11.createElement(Text10, null, "$", a.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React11.createElement(Text10, null, "$", b.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React11.createElement(Text10, { color: costDelta2 <= 0 ? "green" : "red", bold: true }, " ", costDelta2 >= 0 ? "+" : "", costDelta2.toFixed(1), "%")), /* @__PURE__ */ React11.createElement(Text10, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "model calls "), /* @__PURE__ */ React11.createElement(Text10, null, a.stats.turns, " \u2192 ", b.stats.turns))), prefixLine ? /* @__PURE__ */ React11.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true, italic: true }, prefixLine)) : null);
5416
+ return /* @__PURE__ */ React12.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React12.createElement(Box10, { justifyContent: "space-between" }, /* @__PURE__ */ React12.createElement(Text10, null, /* @__PURE__ */ React12.createElement(Text10, { color: "cyan", bold: true }, "reasonix diff"), /* @__PURE__ */ React12.createElement(Text10, { dimColor: true }, " \xB7 A="), /* @__PURE__ */ React12.createElement(Text10, { color: "blue" }, a.label), /* @__PURE__ */ React12.createElement(Text10, { dimColor: true }, " vs B="), /* @__PURE__ */ React12.createElement(Text10, { color: "magenta" }, b.label)), /* @__PURE__ */ React12.createElement(Text10, { dimColor: true }, report.pairs.length, " turns aligned")), /* @__PURE__ */ React12.createElement(Box10, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React12.createElement(Text10, null, /* @__PURE__ */ React12.createElement(Text10, { dimColor: true }, "cache "), /* @__PURE__ */ React12.createElement(Text10, null, (a.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React12.createElement(Text10, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React12.createElement(Text10, null, (b.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React12.createElement(Text10, { color: cacheDelta >= 0 ? "green" : "red", bold: true }, " ", cacheDelta >= 0 ? "+" : "", (cacheDelta * 100).toFixed(1), "pp")), /* @__PURE__ */ React12.createElement(Text10, null, /* @__PURE__ */ React12.createElement(Text10, { dimColor: true }, "cost "), /* @__PURE__ */ React12.createElement(Text10, null, "$", a.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React12.createElement(Text10, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React12.createElement(Text10, null, "$", b.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React12.createElement(Text10, { color: costDelta2 <= 0 ? "green" : "red", bold: true }, " ", costDelta2 >= 0 ? "+" : "", costDelta2.toFixed(1), "%")), /* @__PURE__ */ React12.createElement(Text10, null, /* @__PURE__ */ React12.createElement(Text10, { dimColor: true }, "model calls "), /* @__PURE__ */ React12.createElement(Text10, null, a.stats.turns, " \u2192 ", b.stats.turns))), prefixLine ? /* @__PURE__ */ React12.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React12.createElement(Text10, { dimColor: true, italic: true }, prefixLine)) : null);
5428
5417
  }
5429
5418
  function Pane({
5430
5419
  label,
5431
5420
  headerColor,
5432
5421
  records
5433
5422
  }) {
5434
- return /* @__PURE__ */ React11.createElement(
5423
+ return /* @__PURE__ */ React12.createElement(
5435
5424
  Box10,
5436
5425
  {
5437
5426
  flexDirection: "column",
@@ -5440,21 +5429,21 @@ function Pane({
5440
5429
  borderStyle: "single",
5441
5430
  borderColor: headerColor
5442
5431
  },
5443
- /* @__PURE__ */ React11.createElement(Text10, { color: headerColor, bold: true }, label),
5444
- records.length === 0 ? /* @__PURE__ */ React11.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true, italic: true }, "(no records on this side for this turn)")) : /* @__PURE__ */ React11.createElement(Static2, { items: records.map((rec, i) => ({ key: `${label}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React11.createElement(RecordView, { key, rec, compact: true }))
5432
+ /* @__PURE__ */ React12.createElement(Text10, { color: headerColor, bold: true }, label),
5433
+ records.length === 0 ? /* @__PURE__ */ React12.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React12.createElement(Text10, { dimColor: true, italic: true }, "(no records on this side for this turn)")) : /* @__PURE__ */ React12.createElement(Static2, { items: records.map((rec, i) => ({ key: `${label}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React12.createElement(RecordView, { key, rec, compact: true }))
5445
5434
  );
5446
5435
  }
5447
5436
  function KindBadge({ kind }) {
5448
5437
  if (kind === "match") {
5449
- return /* @__PURE__ */ React11.createElement(Text10, { color: "green" }, "\u2713 match");
5438
+ return /* @__PURE__ */ React12.createElement(Text10, { color: "green" }, "\u2713 match");
5450
5439
  }
5451
5440
  if (kind === "diverge") {
5452
- return /* @__PURE__ */ React11.createElement(Text10, { color: "yellow" }, "\u2605 diverge");
5441
+ return /* @__PURE__ */ React12.createElement(Text10, { color: "yellow" }, "\u2605 diverge");
5453
5442
  }
5454
5443
  if (kind === "only_in_a") {
5455
- return /* @__PURE__ */ React11.createElement(Text10, { color: "blue" }, "\u2190 only in A");
5444
+ return /* @__PURE__ */ React12.createElement(Text10, { color: "blue" }, "\u2190 only in A");
5456
5445
  }
5457
- return /* @__PURE__ */ React11.createElement(Text10, { color: "magenta" }, "\u2192 only in B");
5446
+ return /* @__PURE__ */ React12.createElement(Text10, { color: "magenta" }, "\u2192 only in B");
5458
5447
  }
5459
5448
  function paneRecords(pair, side) {
5460
5449
  if (!pair) return [];
@@ -5485,8 +5474,9 @@ markdown report written to ${opts.mdPath}`);
5485
5474
  return;
5486
5475
  }
5487
5476
  if (wantTui) {
5488
- const { waitUntilExit } = render2(React12.createElement(DiffApp, { report }), {
5489
- exitOnCtrlC: true
5477
+ const { waitUntilExit } = render2(React13.createElement(DiffApp, { report }), {
5478
+ exitOnCtrlC: true,
5479
+ patchConsole: false
5490
5480
  });
5491
5481
  await waitUntilExit();
5492
5482
  return;
@@ -5625,15 +5615,15 @@ function pad(s, width) {
5625
5615
 
5626
5616
  // src/cli/commands/replay.ts
5627
5617
  import { render as render3 } from "ink";
5628
- import React14 from "react";
5618
+ import React15 from "react";
5629
5619
 
5630
5620
  // src/cli/ui/ReplayApp.tsx
5631
5621
  import { Box as Box11, Static as Static3, Text as Text11, useApp as useApp4, useInput as useInput4 } from "ink";
5632
- import React13, { useMemo as useMemo2, useState as useState7 } from "react";
5622
+ import React14, { useMemo as useMemo2, useState as useState6 } from "react";
5633
5623
  function ReplayApp({ meta, pages }) {
5634
5624
  const { exit } = useApp4();
5635
5625
  const maxIdx = Math.max(0, pages.length - 1);
5636
- const [idx, setIdx] = useState7(maxIdx);
5626
+ const [idx, setIdx] = useState6(maxIdx);
5637
5627
  useInput4((input, key) => {
5638
5628
  if (input === "q" || key.ctrl && input === "c") {
5639
5629
  exit();
@@ -5668,14 +5658,14 @@ function ReplayApp({ meta, pages }) {
5668
5658
  const prefixHash = cumStats.prefixHashes.length === 1 ? cumStats.prefixHashes[0].slice(0, 16) : cumStats.prefixHashes.length === 0 ? "(untracked)" : `(churned \xD7${cumStats.prefixHashes.length})`;
5669
5659
  const currentPage = pages[idx];
5670
5660
  const progressLabel = pages.length === 0 ? "empty transcript" : `turn ${idx + 1} / ${pages.length}`;
5671
- return /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column" }, /* @__PURE__ */ React13.createElement(
5661
+ return /* @__PURE__ */ React14.createElement(Box11, { flexDirection: "column" }, /* @__PURE__ */ React14.createElement(
5672
5662
  StatsPanel,
5673
5663
  {
5674
5664
  summary,
5675
5665
  model: cumStats.models[0] ?? meta?.model ?? "?",
5676
5666
  prefixHash
5677
5667
  }
5678
- ), /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React13.createElement(Box11, { justifyContent: "space-between" }, /* @__PURE__ */ React13.createElement(Text11, { color: "cyan", bold: true }, progressLabel), meta ? /* @__PURE__ */ React13.createElement(Text11, { dimColor: true }, meta.source, meta.task ? ` \xB7 ${meta.task}` : "", meta.mode ? ` \xB7 ${meta.mode}` : "") : null), currentPage ? /* @__PURE__ */ React13.createElement(Static3, { items: currentPage.records.map((rec, i) => ({ key: `${idx}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React13.createElement(RecordView, { key, rec })) : /* @__PURE__ */ React13.createElement(Text11, { dimColor: true, italic: true }, "no records")), /* @__PURE__ */ React13.createElement(Box11, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React13.createElement(Text11, { dimColor: true }, /* @__PURE__ */ React13.createElement(Text11, { bold: true }, "j"), "/", /* @__PURE__ */ React13.createElement(Text11, { bold: true }, "\u2193"), "/", /* @__PURE__ */ React13.createElement(Text11, { bold: true }, "space"), " next \xB7 ", /* @__PURE__ */ React13.createElement(Text11, { bold: true }, "k"), "/", /* @__PURE__ */ React13.createElement(Text11, { bold: true }, "\u2191"), " prev \xB7 ", /* @__PURE__ */ React13.createElement(Text11, { bold: true }, "g"), " first \xB7 ", /* @__PURE__ */ React13.createElement(Text11, { bold: true }, "G"), " last \xB7", " ", /* @__PURE__ */ React13.createElement(Text11, { bold: true }, "q"), " quit")));
5668
+ ), /* @__PURE__ */ React14.createElement(Box11, { flexDirection: "column", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React14.createElement(Box11, { justifyContent: "space-between" }, /* @__PURE__ */ React14.createElement(Text11, { color: "cyan", bold: true }, progressLabel), meta ? /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, meta.source, meta.task ? ` \xB7 ${meta.task}` : "", meta.mode ? ` \xB7 ${meta.mode}` : "") : null), currentPage ? /* @__PURE__ */ React14.createElement(Static3, { items: currentPage.records.map((rec, i) => ({ key: `${idx}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React14.createElement(RecordView, { key, rec })) : /* @__PURE__ */ React14.createElement(Text11, { dimColor: true, italic: true }, "no records")), /* @__PURE__ */ React14.createElement(Box11, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, /* @__PURE__ */ React14.createElement(Text11, { bold: true }, "j"), "/", /* @__PURE__ */ React14.createElement(Text11, { bold: true }, "\u2193"), "/", /* @__PURE__ */ React14.createElement(Text11, { bold: true }, "space"), " next \xB7 ", /* @__PURE__ */ React14.createElement(Text11, { bold: true }, "k"), "/", /* @__PURE__ */ React14.createElement(Text11, { bold: true }, "\u2191"), " prev \xB7 ", /* @__PURE__ */ React14.createElement(Text11, { bold: true }, "g"), " first \xB7 ", /* @__PURE__ */ React14.createElement(Text11, { bold: true }, "G"), " last \xB7", " ", /* @__PURE__ */ React14.createElement(Text11, { bold: true }, "q"), " quit")));
5679
5669
  }
5680
5670
 
5681
5671
  // src/cli/commands/replay.ts
@@ -5687,8 +5677,9 @@ async function replayCommand(opts) {
5687
5677
  }
5688
5678
  const { parsed } = replayFromFile(opts.path);
5689
5679
  const pages = groupRecordsByTurn(parsed.records);
5690
- const { waitUntilExit } = render3(React14.createElement(ReplayApp, { meta: parsed.meta, pages }), {
5691
- exitOnCtrlC: true
5680
+ const { waitUntilExit } = render3(React15.createElement(ReplayApp, { meta: parsed.meta, pages }), {
5681
+ exitOnCtrlC: true,
5682
+ patchConsole: false
5692
5683
  });
5693
5684
  await waitUntilExit();
5694
5685
  }
@@ -5988,16 +5979,16 @@ function truncate4(s, max) {
5988
5979
 
5989
5980
  // src/cli/commands/setup.tsx
5990
5981
  import { render as render4 } from "ink";
5991
- import React17 from "react";
5982
+ import React18 from "react";
5992
5983
 
5993
5984
  // src/cli/ui/Wizard.tsx
5994
5985
  import { Box as Box13, Text as Text13, useApp as useApp5, useInput as useInput6 } from "ink";
5995
5986
  import TextInput2 from "ink-text-input";
5996
- import React16, { useState as useState9 } from "react";
5987
+ import React17, { useState as useState8 } from "react";
5997
5988
 
5998
5989
  // src/cli/ui/Select.tsx
5999
5990
  import { Box as Box12, Text as Text12, useInput as useInput5 } from "ink";
6000
- import React15, { useState as useState8 } from "react";
5991
+ import React16, { useState as useState7 } from "react";
6001
5992
  function SingleSelect({
6002
5993
  items,
6003
5994
  initialValue,
@@ -6008,7 +5999,7 @@ function SingleSelect({
6008
5999
  0,
6009
6000
  items.findIndex((i) => i.value === initialValue && !i.disabled)
6010
6001
  );
6011
- const [index, setIndex] = useState8(initialIndex === -1 ? 0 : initialIndex);
6002
+ const [index, setIndex] = useState7(initialIndex === -1 ? 0 : initialIndex);
6012
6003
  useInput5((_input, key) => {
6013
6004
  if (key.upArrow) {
6014
6005
  setIndex((i) => findNextEnabled(items, i, -1));
@@ -6021,7 +6012,7 @@ function SingleSelect({
6021
6012
  onCancel();
6022
6013
  }
6023
6014
  });
6024
- return /* @__PURE__ */ React15.createElement(Box12, { flexDirection: "column" }, items.map((item, i) => /* @__PURE__ */ React15.createElement(
6015
+ return /* @__PURE__ */ React16.createElement(Box12, { flexDirection: "column" }, items.map((item, i) => /* @__PURE__ */ React16.createElement(
6025
6016
  SelectRow,
6026
6017
  {
6027
6018
  key: item.value,
@@ -6038,11 +6029,11 @@ function MultiSelect({
6038
6029
  onCancel,
6039
6030
  footer
6040
6031
  }) {
6041
- const [index, setIndex] = useState8(() => {
6032
+ const [index, setIndex] = useState7(() => {
6042
6033
  const first = items.findIndex((i) => !i.disabled);
6043
6034
  return first === -1 ? 0 : first;
6044
6035
  });
6045
- const [selected, setSelected] = useState8(new Set(initialSelected));
6036
+ const [selected, setSelected] = useState7(new Set(initialSelected));
6046
6037
  useInput5((input, key) => {
6047
6038
  if (key.upArrow) {
6048
6039
  setIndex((i) => findNextEnabled(items, i, -1));
@@ -6064,10 +6055,10 @@ function MultiSelect({
6064
6055
  onCancel();
6065
6056
  }
6066
6057
  });
6067
- return /* @__PURE__ */ React15.createElement(Box12, { flexDirection: "column" }, items.map((item, i) => {
6058
+ return /* @__PURE__ */ React16.createElement(Box12, { flexDirection: "column" }, items.map((item, i) => {
6068
6059
  const checked = selected.has(item.value);
6069
6060
  const marker = checked ? "[x]" : "[ ]";
6070
- return /* @__PURE__ */ React15.createElement(
6061
+ return /* @__PURE__ */ React16.createElement(
6071
6062
  SelectRow,
6072
6063
  {
6073
6064
  key: item.value,
@@ -6076,7 +6067,7 @@ function MultiSelect({
6076
6067
  marker: `${i === index ? "\u25B8" : " "} ${marker}`
6077
6068
  }
6078
6069
  );
6079
- }), footer ? /* @__PURE__ */ React15.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text12, { dimColor: true }, footer)) : null);
6070
+ }), footer ? /* @__PURE__ */ React16.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text12, { dimColor: true }, footer)) : null);
6080
6071
  }
6081
6072
  function SelectRow({
6082
6073
  item,
@@ -6084,7 +6075,7 @@ function SelectRow({
6084
6075
  marker
6085
6076
  }) {
6086
6077
  const color = item.disabled ? "gray" : active ? "cyan" : void 0;
6087
- return /* @__PURE__ */ React15.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React15.createElement(Box12, null, /* @__PURE__ */ React15.createElement(Text12, { color }, marker, " ", item.label)), item.hint ? /* @__PURE__ */ React15.createElement(Box12, { paddingLeft: marker.length + 1 }, /* @__PURE__ */ React15.createElement(Text12, { dimColor: true }, item.hint)) : null);
6078
+ return /* @__PURE__ */ React16.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React16.createElement(Box12, null, /* @__PURE__ */ React16.createElement(Text12, { color }, marker, " ", item.label)), item.hint ? /* @__PURE__ */ React16.createElement(Box12, { paddingLeft: marker.length + 1 }, /* @__PURE__ */ React16.createElement(Text12, { dimColor: true }, item.hint)) : null);
6088
6079
  }
6089
6080
  function findNextEnabled(items, from, step) {
6090
6081
  if (items.length === 0) return 0;
@@ -6121,19 +6112,19 @@ var PRESET_DESCRIPTIONS = {
6121
6112
  var CATALOG_BY_NAME = new Map(MCP_CATALOG.map((e) => [e.name, e]));
6122
6113
  function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
6123
6114
  const { exit } = useApp5();
6124
- const [step, setStep] = useState9(existingApiKey ? "preset" : "apiKey");
6125
- const [data, setData] = useState9({
6115
+ const [step, setStep] = useState8(existingApiKey ? "preset" : "apiKey");
6116
+ const [data, setData] = useState8({
6126
6117
  apiKey: existingApiKey ?? "",
6127
6118
  preset: initial?.preset ?? "fast",
6128
6119
  selectedCatalog: deriveInitialCatalog(initial?.mcp ?? []),
6129
6120
  catalogArgs: {}
6130
6121
  });
6131
- const [error, setError] = useState9(null);
6122
+ const [error, setError] = useState8(null);
6132
6123
  useInput6((_input, key) => {
6133
6124
  if (key.escape && step !== "saved" && onCancel) onCancel();
6134
6125
  });
6135
6126
  if (step === "apiKey") {
6136
- return /* @__PURE__ */ React16.createElement(
6127
+ return /* @__PURE__ */ React17.createElement(
6137
6128
  ApiKeyStep,
6138
6129
  {
6139
6130
  onSubmit: (key) => {
@@ -6147,7 +6138,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
6147
6138
  );
6148
6139
  }
6149
6140
  if (step === "preset") {
6150
- return /* @__PURE__ */ React16.createElement(StepFrame, { title: "Pick a preset", step: 1, total: 3 }, /* @__PURE__ */ React16.createElement(
6141
+ return /* @__PURE__ */ React17.createElement(StepFrame, { title: "Pick a preset", step: 1, total: 3 }, /* @__PURE__ */ React17.createElement(
6151
6142
  SingleSelect,
6152
6143
  {
6153
6144
  items: presetItems(),
@@ -6157,10 +6148,10 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
6157
6148
  setStep("mcp");
6158
6149
  }
6159
6150
  }
6160
- ), /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, { dimColor: true }, "\u2191/\u2193 move \xB7 enter confirm \xB7 esc cancel")));
6151
+ ), /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, "\u2191/\u2193 move \xB7 enter confirm \xB7 esc cancel")));
6161
6152
  }
6162
6153
  if (step === "mcp") {
6163
- return /* @__PURE__ */ React16.createElement(StepFrame, { title: "Which MCP servers should Reasonix wire up for you?", step: 2, total: 3 }, /* @__PURE__ */ React16.createElement(
6154
+ return /* @__PURE__ */ React17.createElement(StepFrame, { title: "Which MCP servers should Reasonix wire up for you?", step: 2, total: 3 }, /* @__PURE__ */ React17.createElement(
6164
6155
  MultiSelect,
6165
6156
  {
6166
6157
  items: mcpItems(),
@@ -6185,7 +6176,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
6185
6176
  }
6186
6177
  const currentName = pending[0];
6187
6178
  const entry = CATALOG_BY_NAME.get(currentName);
6188
- return /* @__PURE__ */ React16.createElement(
6179
+ return /* @__PURE__ */ React17.createElement(
6189
6180
  McpArgsStep,
6190
6181
  {
6191
6182
  entry,
@@ -6203,7 +6194,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
6203
6194
  }
6204
6195
  if (step === "review") {
6205
6196
  const specs = data.selectedCatalog.map((name) => buildSpec(name, data.catalogArgs));
6206
- return /* @__PURE__ */ React16.createElement(StepFrame, { title: "Ready to save", step: 3, total: 3 }, /* @__PURE__ */ React16.createElement(Box13, { flexDirection: "column" }, /* @__PURE__ */ React16.createElement(SummaryLine, { label: "API key", value: redactKey(data.apiKey) }), /* @__PURE__ */ React16.createElement(SummaryLine, { label: "Preset", value: data.preset }), /* @__PURE__ */ React16.createElement(
6197
+ return /* @__PURE__ */ React17.createElement(StepFrame, { title: "Ready to save", step: 3, total: 3 }, /* @__PURE__ */ React17.createElement(Box13, { flexDirection: "column" }, /* @__PURE__ */ React17.createElement(SummaryLine, { label: "API key", value: redactKey(data.apiKey) }), /* @__PURE__ */ React17.createElement(SummaryLine, { label: "Preset", value: data.preset }), /* @__PURE__ */ React17.createElement(
6207
6198
  SummaryLine,
6208
6199
  {
6209
6200
  label: "MCP",
@@ -6211,8 +6202,8 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
6211
6202
  }
6212
6203
  ), specs.map((spec, i) => (
6213
6204
  // biome-ignore lint/suspicious/noArrayIndexKey: review-only render, order fixed
6214
- /* @__PURE__ */ React16.createElement(Box13, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React16.createElement(Text13, { dimColor: true }, "\xB7 ", spec))
6215
- )), /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, null, "Saves to ", defaultConfigPath())), error ? /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, { color: "red" }, error)) : null, /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, { dimColor: true }, "enter save \xB7 esc cancel"))), /* @__PURE__ */ React16.createElement(
6205
+ /* @__PURE__ */ React17.createElement(Box13, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, "\xB7 ", spec))
6206
+ )), /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, null, "Saves to ", defaultConfigPath())), error ? /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, { color: "red" }, error)) : null, /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, "enter save \xB7 esc cancel"))), /* @__PURE__ */ React17.createElement(
6216
6207
  ReviewConfirm,
6217
6208
  {
6218
6209
  onConfirm: () => {
@@ -6238,15 +6229,15 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
6238
6229
  }
6239
6230
  ));
6240
6231
  }
6241
- return /* @__PURE__ */ React16.createElement(Box13, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React16.createElement(Text13, { bold: true, color: "green" }, "\u25B8 Saved."), /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, null, "Run `reasonix` any time to start chatting \u2014 your settings are remembered.")), /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, { dimColor: true }, "Press enter to exit.")), /* @__PURE__ */ React16.createElement(ExitOnEnter, { onExit: exit }));
6232
+ return /* @__PURE__ */ React17.createElement(Box13, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React17.createElement(Text13, { bold: true, color: "green" }, "\u25B8 Saved."), /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, null, "Run `reasonix` any time to start chatting \u2014 your settings are remembered.")), /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, "Press enter to exit.")), /* @__PURE__ */ React17.createElement(ExitOnEnter, { onExit: exit }));
6242
6233
  }
6243
6234
  function ApiKeyStep({
6244
6235
  onSubmit,
6245
6236
  error,
6246
6237
  onError
6247
6238
  }) {
6248
- const [value, setValue] = useState9("");
6249
- return /* @__PURE__ */ React16.createElement(Box13, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React16.createElement(Text13, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React16.createElement(Text13, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React16.createElement(Text13, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React16.createElement(
6239
+ const [value, setValue] = useState8("");
6240
+ return /* @__PURE__ */ React17.createElement(Box13, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React17.createElement(Text13, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React17.createElement(
6250
6241
  TextInput2,
6251
6242
  {
6252
6243
  value,
@@ -6263,7 +6254,7 @@ function ApiKeyStep({
6263
6254
  mask: "\u2022",
6264
6255
  placeholder: "sk-..."
6265
6256
  }
6266
- )), error ? /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, { color: "red" }, error)) : value ? /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, { dimColor: true }, "preview: ", redactKey(value))) : null);
6257
+ )), error ? /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, { color: "red" }, error)) : value ? /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, "preview: ", redactKey(value))) : null);
6267
6258
  }
6268
6259
  function McpArgsStep({
6269
6260
  entry,
@@ -6271,8 +6262,8 @@ function McpArgsStep({
6271
6262
  onSubmit,
6272
6263
  onError
6273
6264
  }) {
6274
- const [value, setValue] = useState9("");
6275
- return /* @__PURE__ */ React16.createElement(StepFrame, { title: `Configure ${entry.name}`, step: 2, total: 3 }, /* @__PURE__ */ React16.createElement(Box13, { flexDirection: "column" }, /* @__PURE__ */ React16.createElement(Text13, null, entry.summary), entry.note ? /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, { dimColor: true }, entry.note)) : null, /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, null, "Required parameter: "), /* @__PURE__ */ React16.createElement(Text13, { bold: true }, entry.userArgs)), /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, { bold: true, color: "cyan" }, entry.userArgs, " \u203A "), /* @__PURE__ */ React16.createElement(
6265
+ const [value, setValue] = useState8("");
6266
+ return /* @__PURE__ */ React17.createElement(StepFrame, { title: `Configure ${entry.name}`, step: 2, total: 3 }, /* @__PURE__ */ React17.createElement(Box13, { flexDirection: "column" }, /* @__PURE__ */ React17.createElement(Text13, null, entry.summary), entry.note ? /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, entry.note)) : null, /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, null, "Required parameter: "), /* @__PURE__ */ React17.createElement(Text13, { bold: true }, entry.userArgs)), /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, { bold: true, color: "cyan" }, entry.userArgs, " \u203A "), /* @__PURE__ */ React17.createElement(
6276
6267
  TextInput2,
6277
6268
  {
6278
6269
  value,
@@ -6288,7 +6279,7 @@ function McpArgsStep({
6288
6279
  },
6289
6280
  placeholder: placeholderFor(entry)
6290
6281
  }
6291
- )), error ? /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, { color: "red" }, error)) : null));
6282
+ )), error ? /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, { color: "red" }, error)) : null));
6292
6283
  }
6293
6284
  function ReviewConfirm({ onConfirm }) {
6294
6285
  useInput6((_i, key) => {
@@ -6308,10 +6299,10 @@ function StepFrame({
6308
6299
  total,
6309
6300
  children
6310
6301
  }) {
6311
- return /* @__PURE__ */ React16.createElement(Box13, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React16.createElement(Box13, null, /* @__PURE__ */ React16.createElement(Text13, { dimColor: true }, "Step ", step, "/", total, " \xB7", " "), /* @__PURE__ */ React16.createElement(Text13, { bold: true, color: "cyan" }, title)), /* @__PURE__ */ React16.createElement(Box13, { marginTop: 1, flexDirection: "column" }, children));
6302
+ return /* @__PURE__ */ React17.createElement(Box13, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React17.createElement(Box13, null, /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, "Step ", step, "/", total, " \xB7", " "), /* @__PURE__ */ React17.createElement(Text13, { bold: true, color: "cyan" }, title)), /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1, flexDirection: "column" }, children));
6312
6303
  }
6313
6304
  function SummaryLine({ label, value }) {
6314
- return /* @__PURE__ */ React16.createElement(Box13, null, /* @__PURE__ */ React16.createElement(Text13, null, label.padEnd(12)), /* @__PURE__ */ React16.createElement(Text13, { bold: true }, value));
6305
+ return /* @__PURE__ */ React17.createElement(Box13, null, /* @__PURE__ */ React17.createElement(Text13, null, label.padEnd(12)), /* @__PURE__ */ React17.createElement(Text13, { bold: true }, value));
6315
6306
  }
6316
6307
  function presetItems() {
6317
6308
  return ["fast", "smart", "max"].map((name) => ({
@@ -6367,7 +6358,7 @@ async function setupCommand(_opts = {}) {
6367
6358
  const existingKey = loadApiKey();
6368
6359
  const existing = readConfig();
6369
6360
  const { waitUntilExit, unmount } = render4(
6370
- /* @__PURE__ */ React17.createElement(
6361
+ /* @__PURE__ */ React18.createElement(
6371
6362
  Wizard,
6372
6363
  {
6373
6364
  existingApiKey: existingKey,
@@ -6379,7 +6370,7 @@ async function setupCommand(_opts = {}) {
6379
6370
  }
6380
6371
  }
6381
6372
  ),
6382
- { exitOnCtrlC: true }
6373
+ { exitOnCtrlC: true, patchConsole: false }
6383
6374
  );
6384
6375
  await waitUntilExit();
6385
6376
  }