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/README.md +371 -167
- package/dist/cli/index.js +164 -173
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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.
|
|
3522
|
+
var VERSION = "0.4.14";
|
|
3523
3523
|
|
|
3524
3524
|
// src/cli/commands/chat.tsx
|
|
3525
3525
|
import { render } from "ink";
|
|
3526
|
-
import
|
|
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
|
|
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
|
|
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 =
|
|
3868
|
+
var EventRow = React4.memo(function EventRow2({ event }) {
|
|
3847
3869
|
if (event.role === "user") {
|
|
3848
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
3852
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3900
|
+
return /* @__PURE__ */ React4.createElement(Text3, { key, color: "red" }, line);
|
|
3879
3901
|
}
|
|
3880
3902
|
if (line.startsWith("+ ")) {
|
|
3881
|
-
return /* @__PURE__ */
|
|
3903
|
+
return /* @__PURE__ */ React4.createElement(Text3, { key, color: "green" }, line);
|
|
3882
3904
|
}
|
|
3883
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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
|
|
4017
|
-
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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 =
|
|
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] =
|
|
4575
|
-
const [streaming, setStreaming] =
|
|
4576
|
-
const [input, setInput] =
|
|
4577
|
-
const [busy, setBusy] =
|
|
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] =
|
|
4580
|
-
const [toolProgress, setToolProgress] =
|
|
4581
|
-
const [statusLine, setStatusLine] =
|
|
4582
|
-
const [balance, setBalance] =
|
|
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] =
|
|
4590
|
-
const [summary, setSummary] =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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__ */
|
|
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__ */
|
|
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
|
|
5028
|
-
const
|
|
5029
|
-
|
|
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
|
|
5046
|
-
const
|
|
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__ */
|
|
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
|
|
5143
|
+
import React9, { useState as useState3 } from "react";
|
|
5157
5144
|
function Setup({ onReady }) {
|
|
5158
|
-
const [value, setValue] =
|
|
5159
|
-
const [error, setError] =
|
|
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__ */
|
|
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__ */
|
|
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] =
|
|
5181
|
+
const [key, setKey] = useState4(initialKey);
|
|
5195
5182
|
if (!key) {
|
|
5196
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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] =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
5444
|
-
records.length === 0 ? /* @__PURE__ */
|
|
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__ */
|
|
5438
|
+
return /* @__PURE__ */ React12.createElement(Text10, { color: "green" }, "\u2713 match");
|
|
5450
5439
|
}
|
|
5451
5440
|
if (kind === "diverge") {
|
|
5452
|
-
return /* @__PURE__ */
|
|
5441
|
+
return /* @__PURE__ */ React12.createElement(Text10, { color: "yellow" }, "\u2605 diverge");
|
|
5453
5442
|
}
|
|
5454
5443
|
if (kind === "only_in_a") {
|
|
5455
|
-
return /* @__PURE__ */
|
|
5444
|
+
return /* @__PURE__ */ React12.createElement(Text10, { color: "blue" }, "\u2190 only in A");
|
|
5456
5445
|
}
|
|
5457
|
-
return /* @__PURE__ */
|
|
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(
|
|
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
|
|
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
|
|
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] =
|
|
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__ */
|
|
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__ */
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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] =
|
|
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__ */
|
|
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] =
|
|
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] =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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] =
|
|
6125
|
-
const [data, setData] =
|
|
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] =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
6215
|
-
)), /* @__PURE__ */
|
|
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__ */
|
|
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] =
|
|
6249
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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] =
|
|
6275
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
}
|