reasonix 0.5.8 → 0.5.13
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 +454 -122
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +44 -6
- package/dist/index.js +44 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -2589,7 +2589,7 @@ var DEFAULT_PICKER_IGNORE_DIRS = [
|
|
|
2589
2589
|
"venv",
|
|
2590
2590
|
"__pycache__"
|
|
2591
2591
|
];
|
|
2592
|
-
function
|
|
2592
|
+
function listFilesWithStatsSync(root, opts = {}) {
|
|
2593
2593
|
const maxResults = Math.max(1, opts.maxResults ?? 500);
|
|
2594
2594
|
const ignore = new Set(opts.ignoreDirs ?? DEFAULT_PICKER_IGNORE_DIRS);
|
|
2595
2595
|
const rootAbs = resolve(root);
|
|
@@ -2610,7 +2610,12 @@ function listFilesSync(root, opts = {}) {
|
|
|
2610
2610
|
if (ent.name.startsWith(".") || ignore.has(ent.name)) continue;
|
|
2611
2611
|
walk2(join5(dirAbs, ent.name), relPath);
|
|
2612
2612
|
} else if (ent.isFile()) {
|
|
2613
|
-
|
|
2613
|
+
let mtimeMs = 0;
|
|
2614
|
+
try {
|
|
2615
|
+
mtimeMs = statSync2(join5(dirAbs, ent.name)).mtimeMs;
|
|
2616
|
+
} catch {
|
|
2617
|
+
}
|
|
2618
|
+
out.push({ path: relPath, mtimeMs });
|
|
2614
2619
|
}
|
|
2615
2620
|
}
|
|
2616
2621
|
};
|
|
@@ -2625,12 +2630,31 @@ function detectAtPicker(input) {
|
|
|
2625
2630
|
const atOffset = input.length - query.length - 1;
|
|
2626
2631
|
return { query, atOffset };
|
|
2627
2632
|
}
|
|
2628
|
-
function rankPickerCandidates(files, query,
|
|
2629
|
-
|
|
2633
|
+
function rankPickerCandidates(files, query, limitOrOpts) {
|
|
2634
|
+
const opts = typeof limitOrOpts === "number" ? { limit: limitOrOpts } : limitOrOpts ?? {};
|
|
2635
|
+
const limit = opts.limit ?? 40;
|
|
2636
|
+
const recent = new Set(opts.recentlyUsed ?? []);
|
|
2637
|
+
const entries = files.map(
|
|
2638
|
+
(f) => typeof f === "string" ? { path: f, mtimeMs: 0 } : f
|
|
2639
|
+
);
|
|
2640
|
+
if (!query) {
|
|
2641
|
+
const anyMtime = entries.some((e) => e.mtimeMs > 0);
|
|
2642
|
+
if (!anyMtime && recent.size === 0) {
|
|
2643
|
+
return entries.slice(0, limit).map((e) => e.path);
|
|
2644
|
+
}
|
|
2645
|
+
const sorted = [...entries].sort((a, b) => {
|
|
2646
|
+
const aRecent = recent.has(a.path) ? 1 : 0;
|
|
2647
|
+
const bRecent = recent.has(b.path) ? 1 : 0;
|
|
2648
|
+
if (aRecent !== bRecent) return bRecent - aRecent;
|
|
2649
|
+
if (a.mtimeMs !== b.mtimeMs) return b.mtimeMs - a.mtimeMs;
|
|
2650
|
+
return a.path.localeCompare(b.path);
|
|
2651
|
+
});
|
|
2652
|
+
return sorted.slice(0, limit).map((e) => e.path);
|
|
2653
|
+
}
|
|
2630
2654
|
const needle = query.toLowerCase();
|
|
2631
2655
|
const scored = [];
|
|
2632
|
-
for (const
|
|
2633
|
-
const lower =
|
|
2656
|
+
for (const e of entries) {
|
|
2657
|
+
const lower = e.path.toLowerCase();
|
|
2634
2658
|
const hit = lower.indexOf(needle);
|
|
2635
2659
|
if (hit < 0) continue;
|
|
2636
2660
|
const slash = lower.lastIndexOf("/");
|
|
@@ -2638,9 +2662,18 @@ function rankPickerCandidates(files, query, limit = 40) {
|
|
|
2638
2662
|
let score = 2;
|
|
2639
2663
|
if (base.startsWith(needle)) score = 0;
|
|
2640
2664
|
else if (lower.startsWith(needle)) score = 1;
|
|
2641
|
-
scored.push({
|
|
2665
|
+
scored.push({
|
|
2666
|
+
path: e.path,
|
|
2667
|
+
score: score * 1e4 + hit,
|
|
2668
|
+
mtimeMs: e.mtimeMs,
|
|
2669
|
+
recent: recent.has(e.path)
|
|
2670
|
+
});
|
|
2642
2671
|
}
|
|
2643
|
-
scored.sort((a, b) =>
|
|
2672
|
+
scored.sort((a, b) => {
|
|
2673
|
+
if (a.score !== b.score) return a.score - b.score;
|
|
2674
|
+
if (a.recent !== b.recent) return a.recent ? -1 : 1;
|
|
2675
|
+
return b.mtimeMs - a.mtimeMs;
|
|
2676
|
+
});
|
|
2644
2677
|
return scored.slice(0, limit).map((s) => s.path);
|
|
2645
2678
|
}
|
|
2646
2679
|
var AT_MENTION_PATTERN = /(?<=^|\s)@([a-zA-Z0-9_./\\-]+)/g;
|
|
@@ -5606,11 +5639,80 @@ function formatLogSize(path = defaultUsageLogPath()) {
|
|
|
5606
5639
|
// src/cli/commands/chat.tsx
|
|
5607
5640
|
import { existsSync as existsSync10, statSync as statSync6 } from "fs";
|
|
5608
5641
|
import { render } from "ink";
|
|
5609
|
-
import
|
|
5642
|
+
import React17, { useState as useState7 } from "react";
|
|
5610
5643
|
|
|
5611
5644
|
// src/cli/ui/App.tsx
|
|
5612
|
-
import { Box as
|
|
5613
|
-
import
|
|
5645
|
+
import { Box as Box13, Static, Text as Text13, useApp, useInput as useInput4 } from "ink";
|
|
5646
|
+
import React14, { useCallback, useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState5 } from "react";
|
|
5647
|
+
|
|
5648
|
+
// src/code/diff-preview.ts
|
|
5649
|
+
function formatEditBlockDiff(block, opts = {}) {
|
|
5650
|
+
const contextLines = Math.max(0, opts.contextLines ?? 2);
|
|
5651
|
+
const maxLines = Math.max(4, opts.maxLines ?? 20);
|
|
5652
|
+
const indent = opts.indent ?? " ";
|
|
5653
|
+
const search = block.search === "" ? [] : block.search.split("\n");
|
|
5654
|
+
const replace = block.replace.split("\n");
|
|
5655
|
+
if (search.length === 0) {
|
|
5656
|
+
return renderAllPlus(replace, indent, maxLines);
|
|
5657
|
+
}
|
|
5658
|
+
let leading = 0;
|
|
5659
|
+
while (leading < search.length && leading < replace.length && search[leading] === replace[leading]) {
|
|
5660
|
+
leading++;
|
|
5661
|
+
}
|
|
5662
|
+
let trailing = 0;
|
|
5663
|
+
while (trailing < search.length - leading && trailing < replace.length - leading && search[search.length - 1 - trailing] === replace[replace.length - 1 - trailing]) {
|
|
5664
|
+
trailing++;
|
|
5665
|
+
}
|
|
5666
|
+
const searchMiddle = search.slice(leading, search.length - trailing);
|
|
5667
|
+
const replaceMiddle = replace.slice(leading, replace.length - trailing);
|
|
5668
|
+
const leadShown = search.slice(Math.max(0, leading - contextLines), leading);
|
|
5669
|
+
const leadHidden = leading - leadShown.length;
|
|
5670
|
+
const trailShown = search.slice(
|
|
5671
|
+
search.length - trailing,
|
|
5672
|
+
search.length - trailing + contextLines
|
|
5673
|
+
);
|
|
5674
|
+
const trailHidden = trailing - trailShown.length;
|
|
5675
|
+
const out = [];
|
|
5676
|
+
if (leadHidden > 0) {
|
|
5677
|
+
out.push(`${indent} \u2026 ${leadHidden} unchanged line${leadHidden === 1 ? "" : "s"} above`);
|
|
5678
|
+
}
|
|
5679
|
+
for (const l of leadShown) out.push(`${indent} ${l}`);
|
|
5680
|
+
for (const l of searchMiddle) out.push(`${indent}- ${l}`);
|
|
5681
|
+
for (const l of replaceMiddle) out.push(`${indent}+ ${l}`);
|
|
5682
|
+
for (const l of trailShown) out.push(`${indent} ${l}`);
|
|
5683
|
+
if (trailHidden > 0) {
|
|
5684
|
+
out.push(`${indent} \u2026 ${trailHidden} unchanged line${trailHidden === 1 ? "" : "s"} below`);
|
|
5685
|
+
}
|
|
5686
|
+
return capLines(out, maxLines, indent);
|
|
5687
|
+
}
|
|
5688
|
+
function formatAllBlockDiffs(blocks, opts = {}) {
|
|
5689
|
+
const out = [];
|
|
5690
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
5691
|
+
const b = blocks[i];
|
|
5692
|
+
const removed = b.search === "" ? 0 : countLines2(b.search);
|
|
5693
|
+
const added = countLines2(b.replace);
|
|
5694
|
+
const tag = b.search === "" ? "NEW " : " ";
|
|
5695
|
+
if (i > 0) out.push("");
|
|
5696
|
+
out.push(` ${tag}${b.path} (-${removed} +${added} lines)`);
|
|
5697
|
+
out.push(...formatEditBlockDiff(b, opts));
|
|
5698
|
+
}
|
|
5699
|
+
return out;
|
|
5700
|
+
}
|
|
5701
|
+
function countLines2(s) {
|
|
5702
|
+
if (s.length === 0) return 0;
|
|
5703
|
+
return (s.match(/\n/g)?.length ?? 0) + 1;
|
|
5704
|
+
}
|
|
5705
|
+
function renderAllPlus(lines, indent, maxLines) {
|
|
5706
|
+
const out = lines.map((l) => `${indent}+ ${l}`);
|
|
5707
|
+
return capLines(out, maxLines, indent);
|
|
5708
|
+
}
|
|
5709
|
+
function capLines(lines, maxLines, indent) {
|
|
5710
|
+
if (lines.length <= maxLines) return lines;
|
|
5711
|
+
const head = lines.slice(0, maxLines - 1);
|
|
5712
|
+
const hidden = lines.length - head.length;
|
|
5713
|
+
head.push(`${indent}\u2026 (${hidden} more diff lines \u2014 full content applies on /apply)`);
|
|
5714
|
+
return head;
|
|
5715
|
+
}
|
|
5614
5716
|
|
|
5615
5717
|
// src/tools/skills.ts
|
|
5616
5718
|
function registerSkillTools(registry, opts = {}) {
|
|
@@ -6792,16 +6894,49 @@ function derivePrefix(command) {
|
|
|
6792
6894
|
return TWO_TOKEN_WRAPPERS.has(first) ? `${first} ${tokens[1]}` : first;
|
|
6793
6895
|
}
|
|
6794
6896
|
|
|
6795
|
-
// src/cli/ui/
|
|
6897
|
+
// src/cli/ui/SlashArgPicker.tsx
|
|
6796
6898
|
import { Box as Box10, Text as Text10 } from "ink";
|
|
6797
6899
|
import React11 from "react";
|
|
6900
|
+
function SlashArgPicker({
|
|
6901
|
+
matches,
|
|
6902
|
+
selectedIndex,
|
|
6903
|
+
spec,
|
|
6904
|
+
kind,
|
|
6905
|
+
partial
|
|
6906
|
+
}) {
|
|
6907
|
+
if (kind === "hint") {
|
|
6908
|
+
return /* @__PURE__ */ React11.createElement(Box10, { paddingX: 1 }, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " ", /* @__PURE__ */ React11.createElement(Text10, { bold: true }, "/", spec.cmd), spec.argsHint ? ` ${spec.argsHint}` : "", " \u2014 ", spec.summary));
|
|
6909
|
+
}
|
|
6910
|
+
if (matches === null) return null;
|
|
6911
|
+
if (matches.length === 0) {
|
|
6912
|
+
return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " ", /* @__PURE__ */ React11.createElement(Text10, { bold: true }, "/", spec.cmd), spec.argsHint ? ` ${spec.argsHint}` : "", " \u2014 ", spec.summary), /* @__PURE__ */ React11.createElement(Text10, { color: "yellow" }, ' no match for "', partial, '" \u2014 keep typing, or Backspace to edit'));
|
|
6913
|
+
}
|
|
6914
|
+
const MAX = 8;
|
|
6915
|
+
const total = matches.length;
|
|
6916
|
+
const windowStart = total <= MAX ? 0 : Math.max(0, Math.min(selectedIndex - Math.floor(MAX / 2), total - MAX));
|
|
6917
|
+
const shown = matches.slice(windowStart, windowStart + MAX);
|
|
6918
|
+
const hiddenAbove = windowStart;
|
|
6919
|
+
const hiddenBelow = total - windowStart - shown.length;
|
|
6920
|
+
return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " ", /* @__PURE__ */ React11.createElement(Text10, { bold: true }, "/", spec.cmd), spec.argsHint ? ` ${spec.argsHint}` : "", " \u2014 ", spec.summary), hiddenAbove > 0 ? /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " \u2191 ", hiddenAbove, " more above") : null, shown.map((value, i) => /* @__PURE__ */ React11.createElement(ArgRow, { key: value, value, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " \u2193 ", hiddenBelow, " more below") : null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " [\u2191\u2193] navigate \xB7 [Tab]/[Enter] pick"));
|
|
6921
|
+
}
|
|
6922
|
+
function ArgRow({ value, isSelected }) {
|
|
6923
|
+
const marker = isSelected ? "\u25B8" : " ";
|
|
6924
|
+
if (isSelected) {
|
|
6925
|
+
return /* @__PURE__ */ React11.createElement(Box10, null, /* @__PURE__ */ React11.createElement(Text10, { bold: true, color: "cyan" }, marker, " ", value));
|
|
6926
|
+
}
|
|
6927
|
+
return /* @__PURE__ */ React11.createElement(Box10, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, marker, " ", value));
|
|
6928
|
+
}
|
|
6929
|
+
|
|
6930
|
+
// src/cli/ui/SlashSuggestions.tsx
|
|
6931
|
+
import { Box as Box11, Text as Text11 } from "ink";
|
|
6932
|
+
import React12 from "react";
|
|
6798
6933
|
function SlashSuggestions({
|
|
6799
6934
|
matches,
|
|
6800
6935
|
selectedIndex
|
|
6801
6936
|
}) {
|
|
6802
6937
|
if (matches === null) return null;
|
|
6803
6938
|
if (matches.length === 0) {
|
|
6804
|
-
return /* @__PURE__ */
|
|
6939
|
+
return /* @__PURE__ */ React12.createElement(Box11, { paddingX: 1 }, /* @__PURE__ */ React12.createElement(Text11, { color: "yellow" }, "no slash command matches that prefix"), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, " \u2014 Backspace to edit, or /help for the full list"));
|
|
6805
6940
|
}
|
|
6806
6941
|
const MAX = 8;
|
|
6807
6942
|
const total = matches.length;
|
|
@@ -6809,21 +6944,21 @@ function SlashSuggestions({
|
|
|
6809
6944
|
const shown = matches.slice(windowStart, windowStart + MAX);
|
|
6810
6945
|
const hiddenAbove = windowStart;
|
|
6811
6946
|
const hiddenBelow = total - windowStart - shown.length;
|
|
6812
|
-
return /* @__PURE__ */
|
|
6947
|
+
return /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column", paddingX: 1 }, hiddenAbove > 0 ? /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, " \u2191 ", hiddenAbove, " more above") : null, shown.map((spec, i) => /* @__PURE__ */ React12.createElement(SuggestionRow, { key: spec.cmd, spec, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, " \u2193 ", hiddenBelow, " more below") : null, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, " [\u2191\u2193] navigate \xB7 [Tab]/[Enter] pick"));
|
|
6813
6948
|
}
|
|
6814
6949
|
function SuggestionRow({ spec, isSelected }) {
|
|
6815
6950
|
const marker = isSelected ? "\u25B8" : " ";
|
|
6816
6951
|
const name = `/${spec.cmd}`;
|
|
6817
6952
|
const argsSuffix = spec.argsHint ? ` ${spec.argsHint}` : "";
|
|
6818
6953
|
if (isSelected) {
|
|
6819
|
-
return /* @__PURE__ */
|
|
6954
|
+
return /* @__PURE__ */ React12.createElement(Box11, null, /* @__PURE__ */ React12.createElement(Text11, { bold: true, color: "cyan" }, marker, " ", name.padEnd(12), argsSuffix.padEnd(16)), /* @__PURE__ */ React12.createElement(Text11, { color: "cyan" }, " ", spec.summary));
|
|
6820
6955
|
}
|
|
6821
|
-
return /* @__PURE__ */
|
|
6956
|
+
return /* @__PURE__ */ React12.createElement(Box11, null, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, marker, " ", name.padEnd(12), argsSuffix.padEnd(16), " ", spec.summary));
|
|
6822
6957
|
}
|
|
6823
6958
|
|
|
6824
6959
|
// src/cli/ui/StatsPanel.tsx
|
|
6825
|
-
import { Box as
|
|
6826
|
-
import
|
|
6960
|
+
import { Box as Box12, Text as Text12, useStdout as useStdout2 } from "ink";
|
|
6961
|
+
import React13 from "react";
|
|
6827
6962
|
var WORDMARK_STYLES = [
|
|
6828
6963
|
{ ch: "\u25C8", color: "#5eead4", isLogo: true },
|
|
6829
6964
|
// teal — brand mark
|
|
@@ -6849,7 +6984,7 @@ function Wordmark({ busy }) {
|
|
|
6849
6984
|
const tick = useTick();
|
|
6850
6985
|
const period = busy ? 5 : 12;
|
|
6851
6986
|
const bright = Math.floor(tick / period) % 2 === 0;
|
|
6852
|
-
return /* @__PURE__ */
|
|
6987
|
+
return /* @__PURE__ */ React13.createElement(Text12, null, WORDMARK_STYLES.map((c) => /* @__PURE__ */ React13.createElement(Text12, { key: `${c.ch}-${c.color}`, color: c.color, bold: c.isLogo ? bright : true }, c.ch)));
|
|
6853
6988
|
}
|
|
6854
6989
|
var NARROW_BREAKPOINT = 120;
|
|
6855
6990
|
var COLD_START_TURNS = 3;
|
|
@@ -6871,7 +7006,7 @@ function StatsPanel({
|
|
|
6871
7006
|
const columns = stdout2?.columns ?? 80;
|
|
6872
7007
|
const narrow = columns < NARROW_BREAKPOINT;
|
|
6873
7008
|
const coldStart = summary.turns <= COLD_START_TURNS;
|
|
6874
|
-
return /* @__PURE__ */
|
|
7009
|
+
return /* @__PURE__ */ React13.createElement(Box12, { borderStyle: "round", borderColor: "cyan", flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React13.createElement(
|
|
6875
7010
|
Header,
|
|
6876
7011
|
{
|
|
6877
7012
|
model,
|
|
@@ -6885,7 +7020,7 @@ function StatsPanel({
|
|
|
6885
7020
|
narrow,
|
|
6886
7021
|
busy: busy ?? false
|
|
6887
7022
|
}
|
|
6888
|
-
), narrow ? /* @__PURE__ */
|
|
7023
|
+
), narrow ? /* @__PURE__ */ React13.createElement(
|
|
6889
7024
|
StackedMetrics,
|
|
6890
7025
|
{
|
|
6891
7026
|
summary,
|
|
@@ -6894,7 +7029,7 @@ function StatsPanel({
|
|
|
6894
7029
|
balance,
|
|
6895
7030
|
coldStart
|
|
6896
7031
|
}
|
|
6897
|
-
) : /* @__PURE__ */
|
|
7032
|
+
) : /* @__PURE__ */ React13.createElement(
|
|
6898
7033
|
InlineMetrics,
|
|
6899
7034
|
{
|
|
6900
7035
|
summary,
|
|
@@ -6917,7 +7052,7 @@ function Header({
|
|
|
6917
7052
|
narrow,
|
|
6918
7053
|
busy
|
|
6919
7054
|
}) {
|
|
6920
|
-
return /* @__PURE__ */
|
|
7055
|
+
return /* @__PURE__ */ React13.createElement(Box12, { justifyContent: "space-between" }, /* @__PURE__ */ React13.createElement(Box12, null, /* @__PURE__ */ React13.createElement(Wordmark, { busy }), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, ` v${VERSION}`), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React13.createElement(Text12, { color: "yellow" }, model), narrow ? null : /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, prefixHash)), harvestOn ? /* @__PURE__ */ React13.createElement(Text12, { color: "magenta" }, " \xB7 harvest") : null, branchOn ? /* @__PURE__ */ React13.createElement(Text12, { color: "blue" }, " \xB7 branch", branchBudget) : null, planMode ? /* @__PURE__ */ React13.createElement(Text12, { color: "red", bold: true }, " \xB7 PLAN") : null), /* @__PURE__ */ React13.createElement(Text12, null, updateAvailable ? /* @__PURE__ */ React13.createElement(Text12, { color: "yellow", bold: true }, `update: ${updateAvailable} \xB7 `) : null, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, narrow ? `turn ${turns}` : `turn ${turns} \xB7 /help`)));
|
|
6921
7056
|
}
|
|
6922
7057
|
function InlineMetrics({
|
|
6923
7058
|
summary,
|
|
@@ -6926,7 +7061,7 @@ function InlineMetrics({
|
|
|
6926
7061
|
balance,
|
|
6927
7062
|
coldStart
|
|
6928
7063
|
}) {
|
|
6929
|
-
return /* @__PURE__ */
|
|
7064
|
+
return /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React13.createElement(ContextCell, { ratio: ctxRatio, promptTokens: summary.lastPromptTokens, ctxMax }), /* @__PURE__ */ React13.createElement(CacheCell, { hitRatio: summary.cacheHitRatio, coldStart, turns: summary.turns }), /* @__PURE__ */ React13.createElement(CostCell, { summary, coldStart }), balance ? /* @__PURE__ */ React13.createElement(BalanceCell, { balance }) : null);
|
|
6930
7065
|
}
|
|
6931
7066
|
function StackedMetrics({
|
|
6932
7067
|
summary,
|
|
@@ -6935,7 +7070,7 @@ function StackedMetrics({
|
|
|
6935
7070
|
balance,
|
|
6936
7071
|
coldStart
|
|
6937
7072
|
}) {
|
|
6938
|
-
return /* @__PURE__ */
|
|
7073
|
+
return /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React13.createElement(
|
|
6939
7074
|
ContextCell,
|
|
6940
7075
|
{
|
|
6941
7076
|
ratio: ctxRatio,
|
|
@@ -6943,7 +7078,7 @@ function StackedMetrics({
|
|
|
6943
7078
|
ctxMax,
|
|
6944
7079
|
showBar: true
|
|
6945
7080
|
}
|
|
6946
|
-
), balance ? /* @__PURE__ */
|
|
7081
|
+
), balance ? /* @__PURE__ */ React13.createElement(BalanceCell, { balance }) : null, /* @__PURE__ */ React13.createElement(CacheCell, { hitRatio: summary.cacheHitRatio, coldStart, turns: summary.turns }), /* @__PURE__ */ React13.createElement(CostCell, { summary, coldStart }));
|
|
6947
7082
|
}
|
|
6948
7083
|
function ContextCell({
|
|
6949
7084
|
ratio,
|
|
@@ -6952,11 +7087,11 @@ function ContextCell({
|
|
|
6952
7087
|
showBar
|
|
6953
7088
|
}) {
|
|
6954
7089
|
if (promptTokens === 0) {
|
|
6955
|
-
return /* @__PURE__ */
|
|
7090
|
+
return /* @__PURE__ */ React13.createElement(Text12, null, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "ctx "), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "\u2014 (no turns yet)"));
|
|
6956
7091
|
}
|
|
6957
7092
|
const color = ratio >= 0.8 ? "red" : ratio >= 0.6 ? "yellow" : "green";
|
|
6958
7093
|
const pct2 = Math.round(ratio * 100);
|
|
6959
|
-
return /* @__PURE__ */
|
|
7094
|
+
return /* @__PURE__ */ React13.createElement(Text12, null, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "ctx "), showBar ? /* @__PURE__ */ React13.createElement(Bar, { ratio, color }) : null, showBar ? /* @__PURE__ */ React13.createElement(Text12, null, " ") : null, /* @__PURE__ */ React13.createElement(Text12, { color, bold: true }, formatTokens(promptTokens), "/", formatTokens(ctxMax)), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, " (", pct2, "%)"), ratio >= 0.8 ? /* @__PURE__ */ React13.createElement(Text12, { color: "red", bold: true }, " \xB7 /compact") : null);
|
|
6960
7095
|
}
|
|
6961
7096
|
function CacheCell({
|
|
6962
7097
|
hitRatio,
|
|
@@ -6965,33 +7100,33 @@ function CacheCell({
|
|
|
6965
7100
|
}) {
|
|
6966
7101
|
const pct2 = (hitRatio * 100).toFixed(1);
|
|
6967
7102
|
if (turns === 0) {
|
|
6968
|
-
return /* @__PURE__ */
|
|
7103
|
+
return /* @__PURE__ */ React13.createElement(Text12, null, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "cache "), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "\u2014"));
|
|
6969
7104
|
}
|
|
6970
7105
|
if (coldStart) {
|
|
6971
|
-
return /* @__PURE__ */
|
|
7106
|
+
return /* @__PURE__ */ React13.createElement(Text12, null, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "cache "), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, pct2, "% "), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true, italic: true }, "(cold start)"));
|
|
6972
7107
|
}
|
|
6973
7108
|
const color = hitRatio >= 0.7 ? "green" : hitRatio >= 0.4 ? "yellow" : "red";
|
|
6974
|
-
return /* @__PURE__ */
|
|
7109
|
+
return /* @__PURE__ */ React13.createElement(Text12, null, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "cache "), /* @__PURE__ */ React13.createElement(Text12, { color, bold: true }, pct2, "%"));
|
|
6975
7110
|
}
|
|
6976
7111
|
function CostCell({
|
|
6977
7112
|
summary,
|
|
6978
7113
|
coldStart
|
|
6979
7114
|
}) {
|
|
6980
7115
|
if (summary.turns === 0) {
|
|
6981
|
-
return /* @__PURE__ */
|
|
7116
|
+
return /* @__PURE__ */ React13.createElement(Text12, null, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "cost "), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "\u2014"));
|
|
6982
7117
|
}
|
|
6983
7118
|
const primaryColor = coldStart ? void 0 : "green";
|
|
6984
|
-
return /* @__PURE__ */
|
|
7119
|
+
return /* @__PURE__ */ React13.createElement(Text12, null, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "cost "), /* @__PURE__ */ React13.createElement(Text12, { color: primaryColor, bold: !coldStart, dimColor: coldStart }, "$", summary.totalCostUsd.toFixed(6)), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, " (in ", "$", summary.totalInputCostUsd.toFixed(6), " \xB7 out ", "$", summary.totalOutputCostUsd.toFixed(6), ")"));
|
|
6985
7120
|
}
|
|
6986
7121
|
function BalanceCell({ balance }) {
|
|
6987
7122
|
const color = balance.total < 1 ? "red" : balance.total < 5 ? "yellow" : "green";
|
|
6988
|
-
return /* @__PURE__ */
|
|
7123
|
+
return /* @__PURE__ */ React13.createElement(Text12, null, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "balance "), /* @__PURE__ */ React13.createElement(Text12, { color, bold: true }, balance.currency === "USD" ? "$" : "", balance.total.toFixed(2), balance.currency !== "USD" ? ` ${balance.currency}` : ""));
|
|
6989
7124
|
}
|
|
6990
7125
|
function Bar({ ratio, color }) {
|
|
6991
7126
|
const cells = 10;
|
|
6992
7127
|
const filled = Math.max(0, Math.min(cells, Math.round(ratio * cells)));
|
|
6993
7128
|
const bar = "\u2588".repeat(filled) + "\u2591".repeat(cells - filled);
|
|
6994
|
-
return /* @__PURE__ */
|
|
7129
|
+
return /* @__PURE__ */ React13.createElement(Text12, { color }, bar);
|
|
6995
7130
|
}
|
|
6996
7131
|
function formatTokens(n) {
|
|
6997
7132
|
if (n < 1024) return String(n);
|
|
@@ -7011,6 +7146,38 @@ function formatBangUserMessage(cmd, output) {
|
|
|
7011
7146
|
${output}`;
|
|
7012
7147
|
}
|
|
7013
7148
|
|
|
7149
|
+
// src/cli/ui/paste-collapse.ts
|
|
7150
|
+
var DEFAULT_PASTE_LINE_THRESHOLD = 40;
|
|
7151
|
+
var DEFAULT_PASTE_CHAR_THRESHOLD = 2e3;
|
|
7152
|
+
var DEFAULT_PASTE_HEAD_LINES = 10;
|
|
7153
|
+
function formatLongPaste(input, opts = {}) {
|
|
7154
|
+
const lineCap = opts.lineThreshold ?? DEFAULT_PASTE_LINE_THRESHOLD;
|
|
7155
|
+
const charCap = opts.charThreshold ?? DEFAULT_PASTE_CHAR_THRESHOLD;
|
|
7156
|
+
const headN = Math.max(1, opts.headLines ?? DEFAULT_PASTE_HEAD_LINES);
|
|
7157
|
+
const originalChars = input.length;
|
|
7158
|
+
const lines = input.split("\n");
|
|
7159
|
+
const originalLines = lines.length;
|
|
7160
|
+
if (originalChars <= charCap && originalLines <= lineCap) {
|
|
7161
|
+
return { displayText: input, collapsed: false, originalChars, originalLines };
|
|
7162
|
+
}
|
|
7163
|
+
const header2 = `\u25B8 pasted ${formatBytes(originalChars)} (${originalLines} lines) \u2014 first ${Math.min(headN, originalLines)} shown, full text sent to model`;
|
|
7164
|
+
const head = lines.slice(0, headN).join("\n");
|
|
7165
|
+
const remaining = originalLines - headN;
|
|
7166
|
+
const footer = remaining > 0 ? `\u2026 (${remaining} more line${remaining === 1 ? "" : "s"})` : "";
|
|
7167
|
+
const displayText = footer ? `${header2}
|
|
7168
|
+
${head}
|
|
7169
|
+
${footer}` : `${header2}
|
|
7170
|
+
${head}`;
|
|
7171
|
+
return { displayText, collapsed: true, originalChars, originalLines };
|
|
7172
|
+
}
|
|
7173
|
+
function formatBytes(n) {
|
|
7174
|
+
if (n < 1024) return `${n} B`;
|
|
7175
|
+
const kb = n / 1024;
|
|
7176
|
+
if (kb < 1024) return `${kb.toFixed(kb >= 10 ? 0 : 1)} KB`;
|
|
7177
|
+
const mb = kb / 1024;
|
|
7178
|
+
return `${mb.toFixed(mb >= 10 ? 0 : 1)} MB`;
|
|
7179
|
+
}
|
|
7180
|
+
|
|
7014
7181
|
// src/cli/ui/slash.ts
|
|
7015
7182
|
import { spawnSync } from "child_process";
|
|
7016
7183
|
|
|
@@ -7127,12 +7294,28 @@ var SLASH_COMMANDS = [
|
|
|
7127
7294
|
{
|
|
7128
7295
|
cmd: "preset",
|
|
7129
7296
|
argsHint: "<fast|smart|max>",
|
|
7130
|
-
summary: "one-tap model + harvest + branch bundle"
|
|
7297
|
+
summary: "one-tap model + harvest + branch bundle",
|
|
7298
|
+
argCompleter: ["fast", "smart", "max"]
|
|
7299
|
+
},
|
|
7300
|
+
{
|
|
7301
|
+
cmd: "model",
|
|
7302
|
+
argsHint: "<id>",
|
|
7303
|
+
summary: "switch DeepSeek model id",
|
|
7304
|
+
argCompleter: "models"
|
|
7131
7305
|
},
|
|
7132
|
-
{ cmd: "model", argsHint: "<id>", summary: "switch DeepSeek model id" },
|
|
7133
7306
|
{ cmd: "models", summary: "list available models fetched from DeepSeek /models" },
|
|
7134
|
-
{
|
|
7135
|
-
|
|
7307
|
+
{
|
|
7308
|
+
cmd: "harvest",
|
|
7309
|
+
argsHint: "[on|off]",
|
|
7310
|
+
summary: "toggle Pillar-2 plan-state extraction",
|
|
7311
|
+
argCompleter: ["on", "off"]
|
|
7312
|
+
},
|
|
7313
|
+
{
|
|
7314
|
+
cmd: "branch",
|
|
7315
|
+
argsHint: "<N|off>",
|
|
7316
|
+
summary: "run N parallel samples per turn (N>=2)",
|
|
7317
|
+
argCompleter: ["off", "2", "3", "4", "5"]
|
|
7318
|
+
},
|
|
7136
7319
|
{ cmd: "mcp", summary: "list MCP servers + tools attached to this session" },
|
|
7137
7320
|
{ cmd: "tool", argsHint: "[N]", summary: "dump full output of the Nth tool call (1=latest)" },
|
|
7138
7321
|
{
|
|
@@ -7169,6 +7352,7 @@ var SLASH_COMMANDS = [
|
|
|
7169
7352
|
argsHint: "[tokens]",
|
|
7170
7353
|
summary: "shrink oversized tool results in the log (cap in tokens, default 4000)"
|
|
7171
7354
|
},
|
|
7355
|
+
{ cmd: "keys", summary: "show all keyboard shortcuts and prompt prefixes" },
|
|
7172
7356
|
{ cmd: "sessions", summary: "list saved sessions (current marked with \u25B8)" },
|
|
7173
7357
|
{ cmd: "forget", summary: "delete the current session from disk" },
|
|
7174
7358
|
{ cmd: "setup", summary: "reminds you to exit and run `reasonix setup`" },
|
|
@@ -7189,7 +7373,8 @@ var SLASH_COMMANDS = [
|
|
|
7189
7373
|
cmd: "plan",
|
|
7190
7374
|
argsHint: "[on|off]",
|
|
7191
7375
|
summary: "toggle read-only plan mode (writes bounced until submit_plan + approval)",
|
|
7192
|
-
contextual: "code"
|
|
7376
|
+
contextual: "code",
|
|
7377
|
+
argCompleter: ["on", "off"]
|
|
7193
7378
|
},
|
|
7194
7379
|
{
|
|
7195
7380
|
cmd: "apply-plan",
|
|
@@ -7204,6 +7389,27 @@ function suggestSlashCommands(prefix, codeMode = false) {
|
|
|
7204
7389
|
return c.cmd.startsWith(p);
|
|
7205
7390
|
});
|
|
7206
7391
|
}
|
|
7392
|
+
function detectSlashArgContext(input, codeMode = false) {
|
|
7393
|
+
const m = /^\/(\S+) ([\s\S]*)$/.exec(input);
|
|
7394
|
+
if (!m) return null;
|
|
7395
|
+
const cmdName = m[1].toLowerCase();
|
|
7396
|
+
const tail = m[2] ?? "";
|
|
7397
|
+
const spec = SLASH_COMMANDS.find(
|
|
7398
|
+
(s) => s.cmd === cmdName && (s.contextual !== "code" || codeMode)
|
|
7399
|
+
);
|
|
7400
|
+
if (!spec) return null;
|
|
7401
|
+
const hasInternalSpace = /\s/.test(tail);
|
|
7402
|
+
const partialOffset = input.length - tail.length;
|
|
7403
|
+
if (hasInternalSpace) {
|
|
7404
|
+
return { spec, partial: tail, partialOffset, kind: "hint" };
|
|
7405
|
+
}
|
|
7406
|
+
return {
|
|
7407
|
+
spec,
|
|
7408
|
+
partial: tail,
|
|
7409
|
+
partialOffset,
|
|
7410
|
+
kind: spec.argCompleter ? "picker" : "hint"
|
|
7411
|
+
};
|
|
7412
|
+
}
|
|
7207
7413
|
function parseSlash(text) {
|
|
7208
7414
|
if (!text.startsWith("/")) return null;
|
|
7209
7415
|
const parts = text.slice(1).trim().split(/\s+/);
|
|
@@ -7229,12 +7435,42 @@ function handleSlash(cmd, args, loop, ctx = {}) {
|
|
|
7229
7435
|
info: `\u25B8 new conversation \u2014 dropped ${dropped} message(s) from context. Same session, fresh slate.`
|
|
7230
7436
|
};
|
|
7231
7437
|
}
|
|
7438
|
+
case "keys":
|
|
7439
|
+
return {
|
|
7440
|
+
info: [
|
|
7441
|
+
"Keyboard & prompt shortcuts:",
|
|
7442
|
+
"",
|
|
7443
|
+
" Enter submit the current prompt",
|
|
7444
|
+
" Shift+Enter / Ctrl+J insert a newline (multi-line prompt)",
|
|
7445
|
+
" \\<Enter> bash-style line continuation",
|
|
7446
|
+
" \u2190 \u2192 \u2191 \u2193 move cursor / recall history when buffer empty",
|
|
7447
|
+
" Ctrl+A / Ctrl+E jump to start / end of the current line",
|
|
7448
|
+
" Backspace delete left; Delete delete under cursor",
|
|
7449
|
+
" Esc abort the in-flight turn",
|
|
7450
|
+
" y / n accept / reject pending edits (code mode)",
|
|
7451
|
+
"",
|
|
7452
|
+
"Prompt prefixes:",
|
|
7453
|
+
" /<name> slash command; Tab/Enter picks from the suggestion list",
|
|
7454
|
+
" @<path> inline a file under [Referenced files] (code mode).",
|
|
7455
|
+
" Trailing `@\u2026` opens a file picker; \u2191/\u2193 navigate, Tab/Enter pick.",
|
|
7456
|
+
" !<cmd> run <cmd> as shell in the sandbox root; output goes into context",
|
|
7457
|
+
" so the model sees it next turn. No allowlist gate.",
|
|
7458
|
+
"",
|
|
7459
|
+
"Pickers (slash + @-mention):",
|
|
7460
|
+
" \u2191 / \u2193 navigate the suggestion list",
|
|
7461
|
+
" Tab insert the highlighted item without submitting",
|
|
7462
|
+
" Enter insert and (slash) run it, (@) keep editing",
|
|
7463
|
+
"",
|
|
7464
|
+
"Useful slashes: /help \xB7 /context \xB7 /stats \xB7 /compact \xB7 /new \xB7 /exit"
|
|
7465
|
+
].join("\n")
|
|
7466
|
+
};
|
|
7232
7467
|
case "help":
|
|
7233
7468
|
case "?":
|
|
7234
7469
|
return {
|
|
7235
7470
|
info: [
|
|
7236
7471
|
"Commands:",
|
|
7237
7472
|
" /help this message",
|
|
7473
|
+
" /keys keyboard shortcuts + prompt prefixes (!, @, /)",
|
|
7238
7474
|
" /status show current settings",
|
|
7239
7475
|
" /preset <fast|smart|max> one-tap presets \u2014 see below",
|
|
7240
7476
|
" /model <id> deepseek-chat or deepseek-reasoner",
|
|
@@ -8178,11 +8414,19 @@ function App({
|
|
|
8178
8414
|
const atFiles = useMemo(() => {
|
|
8179
8415
|
if (!codeMode?.rootDir) return [];
|
|
8180
8416
|
try {
|
|
8181
|
-
return
|
|
8417
|
+
return listFilesWithStatsSync(codeMode.rootDir, { maxResults: 500 });
|
|
8182
8418
|
} catch {
|
|
8183
8419
|
return [];
|
|
8184
8420
|
}
|
|
8185
8421
|
}, [codeMode?.rootDir]);
|
|
8422
|
+
const recentFilesRef = useRef2([]);
|
|
8423
|
+
const recordRecentFile = useCallback((p) => {
|
|
8424
|
+
const list = recentFilesRef.current;
|
|
8425
|
+
const i = list.indexOf(p);
|
|
8426
|
+
if (i >= 0) list.splice(i, 1);
|
|
8427
|
+
list.unshift(p);
|
|
8428
|
+
if (list.length > 20) list.length = 20;
|
|
8429
|
+
}, []);
|
|
8186
8430
|
const atPicker = useMemo(() => {
|
|
8187
8431
|
if (!codeMode?.rootDir) return null;
|
|
8188
8432
|
if (slashMatches !== null) return null;
|
|
@@ -8190,7 +8434,10 @@ function App({
|
|
|
8190
8434
|
}, [codeMode?.rootDir, input, slashMatches]);
|
|
8191
8435
|
const atMatches = useMemo(() => {
|
|
8192
8436
|
if (!atPicker) return null;
|
|
8193
|
-
return rankPickerCandidates(atFiles, atPicker.query,
|
|
8437
|
+
return rankPickerCandidates(atFiles, atPicker.query, {
|
|
8438
|
+
limit: 40,
|
|
8439
|
+
recentlyUsed: recentFilesRef.current
|
|
8440
|
+
});
|
|
8194
8441
|
}, [atPicker, atFiles]);
|
|
8195
8442
|
useEffect2(() => {
|
|
8196
8443
|
setAtSelected((prev) => {
|
|
@@ -8207,6 +8454,45 @@ function App({
|
|
|
8207
8454
|
},
|
|
8208
8455
|
[atPicker, input]
|
|
8209
8456
|
);
|
|
8457
|
+
const [slashArgSelected, setSlashArgSelected] = useState5(0);
|
|
8458
|
+
const slashArgContext = useMemo(() => {
|
|
8459
|
+
if (!input.startsWith("/")) return null;
|
|
8460
|
+
if (slashMatches !== null) return null;
|
|
8461
|
+
return detectSlashArgContext(input, !!codeMode);
|
|
8462
|
+
}, [input, slashMatches, codeMode]);
|
|
8463
|
+
const slashArgMatches = useMemo(() => {
|
|
8464
|
+
if (!slashArgContext || slashArgContext.kind !== "picker") return null;
|
|
8465
|
+
const completer = slashArgContext.spec.argCompleter;
|
|
8466
|
+
const partial = slashArgContext.partial;
|
|
8467
|
+
const needle = partial.toLowerCase();
|
|
8468
|
+
if (Array.isArray(completer)) {
|
|
8469
|
+
if (partial && completer.some((v) => v.toLowerCase() === needle)) return null;
|
|
8470
|
+
if (!partial) return completer.slice();
|
|
8471
|
+
return completer.filter((v) => v.toLowerCase().startsWith(needle));
|
|
8472
|
+
}
|
|
8473
|
+
if (completer === "models") {
|
|
8474
|
+
const all = models ?? [];
|
|
8475
|
+
if (partial && all.some((m) => m.toLowerCase() === needle)) return null;
|
|
8476
|
+
if (!partial) return all.slice(0, 40);
|
|
8477
|
+
return all.filter((m) => m.toLowerCase().includes(needle)).slice(0, 40);
|
|
8478
|
+
}
|
|
8479
|
+
return null;
|
|
8480
|
+
}, [slashArgContext, models]);
|
|
8481
|
+
useEffect2(() => {
|
|
8482
|
+
setSlashArgSelected((prev) => {
|
|
8483
|
+
if (!slashArgMatches || slashArgMatches.length === 0) return 0;
|
|
8484
|
+
if (prev >= slashArgMatches.length) return slashArgMatches.length - 1;
|
|
8485
|
+
return prev;
|
|
8486
|
+
});
|
|
8487
|
+
}, [slashArgMatches]);
|
|
8488
|
+
const pickSlashArg = useCallback(
|
|
8489
|
+
(chosen) => {
|
|
8490
|
+
if (!slashArgContext) return;
|
|
8491
|
+
const before = input.slice(0, slashArgContext.partialOffset);
|
|
8492
|
+
setInput(`${before}${chosen}`);
|
|
8493
|
+
},
|
|
8494
|
+
[slashArgContext, input]
|
|
8495
|
+
);
|
|
8210
8496
|
const loopRef = useRef2(null);
|
|
8211
8497
|
const subagentSinkRef = useRef2({ current: null });
|
|
8212
8498
|
const loop = useMemo(() => {
|
|
@@ -8391,6 +8677,21 @@ function App({
|
|
|
8391
8677
|
return;
|
|
8392
8678
|
}
|
|
8393
8679
|
}
|
|
8680
|
+
if (slashArgMatches && slashArgMatches.length > 0) {
|
|
8681
|
+
if (key.upArrow) {
|
|
8682
|
+
setSlashArgSelected((i) => Math.max(0, i - 1));
|
|
8683
|
+
return;
|
|
8684
|
+
}
|
|
8685
|
+
if (key.downArrow) {
|
|
8686
|
+
setSlashArgSelected((i) => Math.min(slashArgMatches.length - 1, i + 1));
|
|
8687
|
+
return;
|
|
8688
|
+
}
|
|
8689
|
+
if (key.tab) {
|
|
8690
|
+
const sel = slashArgMatches[slashArgSelected] ?? slashArgMatches[0];
|
|
8691
|
+
if (sel) pickSlashArg(sel);
|
|
8692
|
+
return;
|
|
8693
|
+
}
|
|
8694
|
+
}
|
|
8394
8695
|
if (slashMatches && slashMatches.length > 0) {
|
|
8395
8696
|
if (key.upArrow) {
|
|
8396
8697
|
setSlashSelected((i) => Math.max(0, i - 1));
|
|
@@ -8483,6 +8784,13 @@ function App({
|
|
|
8483
8784
|
return;
|
|
8484
8785
|
}
|
|
8485
8786
|
}
|
|
8787
|
+
if (slashArgMatches && slashArgMatches.length > 0 && slashArgContext) {
|
|
8788
|
+
const sel = slashArgMatches[slashArgSelected] ?? slashArgMatches[0];
|
|
8789
|
+
if (sel) {
|
|
8790
|
+
pickSlashArg(sel);
|
|
8791
|
+
return;
|
|
8792
|
+
}
|
|
8793
|
+
}
|
|
8486
8794
|
if (text.startsWith("/") && !text.includes(" ")) {
|
|
8487
8795
|
const typed = text.slice(1).toLowerCase();
|
|
8488
8796
|
const matches = suggestSlashCommands(typed, !!codeMode);
|
|
@@ -8632,13 +8940,19 @@ function App({
|
|
|
8632
8940
|
if (promptReport.blocked) return;
|
|
8633
8941
|
}
|
|
8634
8942
|
promptHistory.current.push(text);
|
|
8943
|
+
const pasteDisplay = formatLongPaste(text);
|
|
8635
8944
|
setHistorical((prev) => [
|
|
8636
8945
|
...prev,
|
|
8637
8946
|
// `leadSeparator`: thin rule above this user turn when history
|
|
8638
8947
|
// isn't empty — visual pacing for multi-turn sessions. First
|
|
8639
8948
|
// user message leaves it off so the UI doesn't open with a
|
|
8640
8949
|
// dangling divider.
|
|
8641
|
-
{
|
|
8950
|
+
{
|
|
8951
|
+
id: `u-${Date.now()}`,
|
|
8952
|
+
role: "user",
|
|
8953
|
+
text: pasteDisplay.displayText,
|
|
8954
|
+
leadSeparator: prev.length > 0
|
|
8955
|
+
}
|
|
8642
8956
|
]);
|
|
8643
8957
|
const assistantId = `a-${Date.now()}`;
|
|
8644
8958
|
const streamRef = { id: assistantId, text: "", reasoning: "" };
|
|
@@ -8775,6 +9089,19 @@ function App({
|
|
|
8775
9089
|
} else if (ev.role === "tool_start") {
|
|
8776
9090
|
setOngoingTool({ name: ev.toolName ?? "?", args: ev.toolArgs });
|
|
8777
9091
|
setToolProgress(null);
|
|
9092
|
+
if (codeMode && ev.toolArgs) {
|
|
9093
|
+
try {
|
|
9094
|
+
const parsed = JSON.parse(ev.toolArgs);
|
|
9095
|
+
for (const k of ["path", "file_path", "file"]) {
|
|
9096
|
+
const v = parsed[k];
|
|
9097
|
+
if (typeof v === "string" && v.trim()) {
|
|
9098
|
+
recordRecentFile(v.trim());
|
|
9099
|
+
break;
|
|
9100
|
+
}
|
|
9101
|
+
}
|
|
9102
|
+
} catch {
|
|
9103
|
+
}
|
|
9104
|
+
}
|
|
8778
9105
|
} else if (ev.role === "tool") {
|
|
8779
9106
|
flush();
|
|
8780
9107
|
setOngoingTool(null);
|
|
@@ -8884,6 +9211,11 @@ function App({
|
|
|
8884
9211
|
atPicker,
|
|
8885
9212
|
atSelected,
|
|
8886
9213
|
pickAtMention,
|
|
9214
|
+
recordRecentFile,
|
|
9215
|
+
slashArgMatches,
|
|
9216
|
+
slashArgContext,
|
|
9217
|
+
slashArgSelected,
|
|
9218
|
+
pickSlashArg,
|
|
8887
9219
|
togglePlanMode,
|
|
8888
9220
|
writeTranscript
|
|
8889
9221
|
]
|
|
@@ -9034,7 +9366,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
|
|
|
9034
9366
|
if (stagedInput?.plan) setPendingPlan(stagedInput.plan);
|
|
9035
9367
|
setStagedInput(null);
|
|
9036
9368
|
}, [stagedInput]);
|
|
9037
|
-
return /* @__PURE__ */
|
|
9369
|
+
return /* @__PURE__ */ React14.createElement(TickerProvider, { disabled: PLAIN_UI }, /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column" }, /* @__PURE__ */ React14.createElement(
|
|
9038
9370
|
StatsPanel,
|
|
9039
9371
|
{
|
|
9040
9372
|
summary,
|
|
@@ -9047,21 +9379,21 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
|
|
|
9047
9379
|
busy,
|
|
9048
9380
|
updateAvailable
|
|
9049
9381
|
}
|
|
9050
|
-
), /* @__PURE__ */
|
|
9382
|
+
), /* @__PURE__ */ React14.createElement(Static, { items: historical }, (item) => /* @__PURE__ */ React14.createElement(EventRow, { key: item.id, event: item, projectRoot: hookCwd })), !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && streaming ? /* @__PURE__ */ React14.createElement(Box13, { marginY: 1 }, /* @__PURE__ */ React14.createElement(EventRow, { event: streaming, projectRoot: hookCwd })) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && ongoingTool ? /* @__PURE__ */ React14.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && subagentActivity ? /* @__PURE__ */ React14.createElement(SubagentRow, { activity: subagentActivity }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && !ongoingTool && statusLine ? /* @__PURE__ */ React14.createElement(StatusRow, { text: statusLine }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && busy && !streaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React14.createElement(StatusRow, { text: "processing\u2026" }) : null, stagedInput ? /* @__PURE__ */ React14.createElement(
|
|
9051
9383
|
PlanRefineInput,
|
|
9052
9384
|
{
|
|
9053
9385
|
mode: stagedInput.mode,
|
|
9054
9386
|
onSubmit: handleStagedInputSubmit,
|
|
9055
9387
|
onCancel: handleStagedInputCancel
|
|
9056
9388
|
}
|
|
9057
|
-
) : pendingPlan ? /* @__PURE__ */
|
|
9389
|
+
) : pendingPlan ? /* @__PURE__ */ React14.createElement(PlanConfirm, { plan: pendingPlan, onChoose: handlePlanConfirm, projectRoot: hookCwd }) : pendingShell ? /* @__PURE__ */ React14.createElement(
|
|
9058
9390
|
ShellConfirm,
|
|
9059
9391
|
{
|
|
9060
9392
|
command: pendingShell,
|
|
9061
9393
|
allowPrefix: derivePrefix(pendingShell),
|
|
9062
9394
|
onChoose: handleShellConfirm
|
|
9063
9395
|
}
|
|
9064
|
-
) : /* @__PURE__ */
|
|
9396
|
+
) : /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(
|
|
9065
9397
|
PromptInput,
|
|
9066
9398
|
{
|
|
9067
9399
|
value: input,
|
|
@@ -9069,27 +9401,36 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
|
|
|
9069
9401
|
onSubmit: handleSubmit,
|
|
9070
9402
|
disabled: busy
|
|
9071
9403
|
}
|
|
9072
|
-
), /* @__PURE__ */
|
|
9404
|
+
), /* @__PURE__ */ React14.createElement(SlashSuggestions, { matches: slashMatches, selectedIndex: slashSelected }), /* @__PURE__ */ React14.createElement(
|
|
9073
9405
|
AtMentionSuggestions,
|
|
9074
9406
|
{
|
|
9075
9407
|
matches: atMatches,
|
|
9076
9408
|
selectedIndex: atSelected,
|
|
9077
9409
|
query: atPicker?.query ?? ""
|
|
9078
9410
|
}
|
|
9079
|
-
)
|
|
9411
|
+
), slashArgContext ? /* @__PURE__ */ React14.createElement(
|
|
9412
|
+
SlashArgPicker,
|
|
9413
|
+
{
|
|
9414
|
+
matches: slashArgMatches,
|
|
9415
|
+
selectedIndex: slashArgSelected,
|
|
9416
|
+
spec: slashArgContext.spec,
|
|
9417
|
+
kind: slashArgContext.kind,
|
|
9418
|
+
partial: slashArgContext.partial
|
|
9419
|
+
}
|
|
9420
|
+
) : null)));
|
|
9080
9421
|
}
|
|
9081
9422
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
9082
9423
|
function StatusRow({ text }) {
|
|
9083
9424
|
const tick = useTick();
|
|
9084
9425
|
const elapsed = useElapsedSeconds();
|
|
9085
|
-
return /* @__PURE__ */
|
|
9426
|
+
return /* @__PURE__ */ React14.createElement(Box13, { marginY: 1 }, /* @__PURE__ */ React14.createElement(Text13, { color: "magenta" }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React14.createElement(Text13, { color: "magenta" }, ` ${text}`), /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, ` ${elapsed}s`));
|
|
9086
9427
|
}
|
|
9087
9428
|
function SubagentRow({
|
|
9088
9429
|
activity
|
|
9089
9430
|
}) {
|
|
9090
9431
|
const tick = useTick();
|
|
9091
9432
|
const seconds = (activity.elapsedMs / 1e3).toFixed(1);
|
|
9092
|
-
return /* @__PURE__ */
|
|
9433
|
+
return /* @__PURE__ */ React14.createElement(Box13, { paddingLeft: 2 }, /* @__PURE__ */ React14.createElement(Text13, { color: "magenta" }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React14.createElement(Text13, { color: "magenta" }, ` \u232C subagent: ${activity.task}`), /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, ` \xB7 iter ${activity.iter} \xB7 ${seconds}s`));
|
|
9093
9434
|
}
|
|
9094
9435
|
function OngoingToolRow({
|
|
9095
9436
|
tool,
|
|
@@ -9098,7 +9439,7 @@ function OngoingToolRow({
|
|
|
9098
9439
|
const tick = useTick();
|
|
9099
9440
|
const elapsed = useElapsedSeconds();
|
|
9100
9441
|
const summary = summarizeToolArgs(tool.name, tool.args);
|
|
9101
|
-
return /* @__PURE__ */
|
|
9442
|
+
return /* @__PURE__ */ React14.createElement(Box13, { marginY: 1, flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Box13, null, /* @__PURE__ */ React14.createElement(Text13, { color: "cyan" }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React14.createElement(Text13, { color: "yellow" }, ` tool<${tool.name}> running\u2026`), /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, ` ${elapsed}s`)), progress ? /* @__PURE__ */ React14.createElement(Box13, { paddingLeft: 2 }, /* @__PURE__ */ React14.createElement(Text13, { color: "cyan" }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ React14.createElement(Box13, { paddingLeft: 2 }, /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, summary)) : null);
|
|
9102
9443
|
}
|
|
9103
9444
|
function renderProgressLine(p) {
|
|
9104
9445
|
const msg = p.message ? ` ${p.message}` : "";
|
|
@@ -9164,18 +9505,9 @@ function formatEditResults(results) {
|
|
|
9164
9505
|
return [header2, ...lines].join("\n");
|
|
9165
9506
|
}
|
|
9166
9507
|
function formatPendingPreview(blocks) {
|
|
9167
|
-
const lines = blocks.map((b) => {
|
|
9168
|
-
const removed = b.search === "" ? 0 : countLines2(b.search);
|
|
9169
|
-
const added = countLines2(b.replace);
|
|
9170
|
-
const tag = b.search === "" ? "NEW " : " ";
|
|
9171
|
-
return ` ${tag}${b.path} (-${removed} +${added} lines)`;
|
|
9172
|
-
});
|
|
9173
9508
|
const header2 = `\u25B8 ${blocks.length} pending edit block(s) \u2014 /apply (or y) to commit \xB7 /discard (or n) to drop`;
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
function countLines2(s) {
|
|
9177
|
-
if (s.length === 0) return 0;
|
|
9178
|
-
return (s.match(/\n/g)?.length ?? 0) + 1;
|
|
9509
|
+
const diffLines = formatAllBlockDiffs(blocks);
|
|
9510
|
+
return [header2, ...diffLines].join("\n");
|
|
9179
9511
|
}
|
|
9180
9512
|
function formatUndoResults(results) {
|
|
9181
9513
|
const lines = results.map((r) => {
|
|
@@ -9194,15 +9526,15 @@ function describeRepair(repair) {
|
|
|
9194
9526
|
}
|
|
9195
9527
|
|
|
9196
9528
|
// src/cli/ui/SessionPicker.tsx
|
|
9197
|
-
import { Box as
|
|
9198
|
-
import
|
|
9529
|
+
import { Box as Box14, Text as Text14 } from "ink";
|
|
9530
|
+
import React15 from "react";
|
|
9199
9531
|
function SessionPicker({
|
|
9200
9532
|
sessionName,
|
|
9201
9533
|
messageCount,
|
|
9202
9534
|
lastActive,
|
|
9203
9535
|
onChoose
|
|
9204
9536
|
}) {
|
|
9205
|
-
return /* @__PURE__ */
|
|
9537
|
+
return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React15.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text14, { bold: true, color: "cyan" }, `Session "${sessionName}" has ${messageCount} prior message${messageCount === 1 ? "" : "s"}`), /* @__PURE__ */ React15.createElement(Text14, { dimColor: true }, ` \xB7 last active ${relativeTime(lastActive)}`)), /* @__PURE__ */ React15.createElement(
|
|
9206
9538
|
SingleSelect,
|
|
9207
9539
|
{
|
|
9208
9540
|
initialValue: "new",
|
|
@@ -9225,7 +9557,7 @@ function SessionPicker({
|
|
|
9225
9557
|
],
|
|
9226
9558
|
onSubmit: (v) => onChoose(v)
|
|
9227
9559
|
}
|
|
9228
|
-
), /* @__PURE__ */
|
|
9560
|
+
), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text14, { dimColor: true }, "\u2191\u2193 to move \xB7 Enter to pick")));
|
|
9229
9561
|
}
|
|
9230
9562
|
function relativeTime(date) {
|
|
9231
9563
|
const ms = Date.now() - date.getTime();
|
|
@@ -9241,9 +9573,9 @@ function relativeTime(date) {
|
|
|
9241
9573
|
}
|
|
9242
9574
|
|
|
9243
9575
|
// src/cli/ui/Setup.tsx
|
|
9244
|
-
import { Box as
|
|
9576
|
+
import { Box as Box15, Text as Text15, useApp as useApp2 } from "ink";
|
|
9245
9577
|
import TextInput from "ink-text-input";
|
|
9246
|
-
import
|
|
9578
|
+
import React16, { useState as useState6 } from "react";
|
|
9247
9579
|
function Setup({ onReady }) {
|
|
9248
9580
|
const [value, setValue] = useState6("");
|
|
9249
9581
|
const [error, setError] = useState6(null);
|
|
@@ -9267,7 +9599,7 @@ function Setup({ onReady }) {
|
|
|
9267
9599
|
}
|
|
9268
9600
|
onReady(trimmed);
|
|
9269
9601
|
};
|
|
9270
|
-
return /* @__PURE__ */
|
|
9602
|
+
return /* @__PURE__ */ React16.createElement(Box15, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React16.createElement(Text15, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React16.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text15, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React16.createElement(Text15, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React16.createElement(Text15, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React16.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text15, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React16.createElement(
|
|
9271
9603
|
TextInput,
|
|
9272
9604
|
{
|
|
9273
9605
|
value,
|
|
@@ -9276,7 +9608,7 @@ function Setup({ onReady }) {
|
|
|
9276
9608
|
mask: "\u2022",
|
|
9277
9609
|
placeholder: "sk-..."
|
|
9278
9610
|
}
|
|
9279
|
-
)), error ? /* @__PURE__ */
|
|
9611
|
+
)), error ? /* @__PURE__ */ React16.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text15, { color: "red" }, error)) : value ? /* @__PURE__ */ React16.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text15, { dimColor: true }, "preview: ", redactKey(value))) : null, /* @__PURE__ */ React16.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text15, { dimColor: true }, "(Type /exit to abort.)")));
|
|
9280
9612
|
}
|
|
9281
9613
|
|
|
9282
9614
|
// src/cli/commands/chat.tsx
|
|
@@ -9292,7 +9624,7 @@ function Root({
|
|
|
9292
9624
|
const [key, setKey] = useState7(initialKey);
|
|
9293
9625
|
const [pending, setPending] = useState7(sessionPreview);
|
|
9294
9626
|
if (!key) {
|
|
9295
|
-
return /* @__PURE__ */
|
|
9627
|
+
return /* @__PURE__ */ React17.createElement(
|
|
9296
9628
|
Setup,
|
|
9297
9629
|
{
|
|
9298
9630
|
onReady: (k) => {
|
|
@@ -9304,7 +9636,7 @@ function Root({
|
|
|
9304
9636
|
}
|
|
9305
9637
|
process.env.DEEPSEEK_API_KEY = key;
|
|
9306
9638
|
if (pending && appProps.session) {
|
|
9307
|
-
return /* @__PURE__ */
|
|
9639
|
+
return /* @__PURE__ */ React17.createElement(
|
|
9308
9640
|
SessionPicker,
|
|
9309
9641
|
{
|
|
9310
9642
|
sessionName: appProps.session,
|
|
@@ -9319,7 +9651,7 @@ function Root({
|
|
|
9319
9651
|
}
|
|
9320
9652
|
);
|
|
9321
9653
|
}
|
|
9322
|
-
return /* @__PURE__ */
|
|
9654
|
+
return /* @__PURE__ */ React17.createElement(
|
|
9323
9655
|
App,
|
|
9324
9656
|
{
|
|
9325
9657
|
model: appProps.model,
|
|
@@ -9422,7 +9754,7 @@ async function chatCommand(opts) {
|
|
|
9422
9754
|
rewriteSession(opts.session, []);
|
|
9423
9755
|
}
|
|
9424
9756
|
const { waitUntilExit } = render(
|
|
9425
|
-
/* @__PURE__ */
|
|
9757
|
+
/* @__PURE__ */ React17.createElement(
|
|
9426
9758
|
Root,
|
|
9427
9759
|
{
|
|
9428
9760
|
initialKey,
|
|
@@ -9485,34 +9817,34 @@ async function codeCommand(opts = {}) {
|
|
|
9485
9817
|
import { writeFileSync as writeFileSync5 } from "fs";
|
|
9486
9818
|
import { basename as basename2 } from "path";
|
|
9487
9819
|
import { render as render2 } from "ink";
|
|
9488
|
-
import
|
|
9820
|
+
import React20 from "react";
|
|
9489
9821
|
|
|
9490
9822
|
// src/cli/ui/DiffApp.tsx
|
|
9491
|
-
import { Box as
|
|
9492
|
-
import
|
|
9823
|
+
import { Box as Box17, Static as Static2, Text as Text17, useApp as useApp3, useInput as useInput5 } from "ink";
|
|
9824
|
+
import React19, { useState as useState8 } from "react";
|
|
9493
9825
|
|
|
9494
9826
|
// src/cli/ui/RecordView.tsx
|
|
9495
|
-
import { Box as
|
|
9496
|
-
import
|
|
9827
|
+
import { Box as Box16, Text as Text16 } from "ink";
|
|
9828
|
+
import React18 from "react";
|
|
9497
9829
|
function RecordView({ rec, compact = false }) {
|
|
9498
9830
|
const toolArgsMax = compact ? 120 : 200;
|
|
9499
9831
|
const toolContentMax = compact ? 200 : 400;
|
|
9500
9832
|
if (rec.role === "user") {
|
|
9501
|
-
return /* @__PURE__ */
|
|
9833
|
+
return /* @__PURE__ */ React18.createElement(Box16, { marginTop: 1 }, /* @__PURE__ */ React18.createElement(Text16, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React18.createElement(Text16, null, rec.content));
|
|
9502
9834
|
}
|
|
9503
9835
|
if (rec.role === "assistant_final") {
|
|
9504
|
-
return /* @__PURE__ */
|
|
9836
|
+
return /* @__PURE__ */ React18.createElement(Box16, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React18.createElement(Box16, null, /* @__PURE__ */ React18.createElement(Text16, { bold: true, color: "green" }, "assistant"), rec.cost !== void 0 ? /* @__PURE__ */ React18.createElement(Text16, { dimColor: true }, " $", rec.cost.toFixed(6)) : null, rec.usage ? /* @__PURE__ */ React18.createElement(CacheBadge, { usage: rec.usage }) : null), rec.planState ? /* @__PURE__ */ React18.createElement(PlanStateBlock, { planState: rec.planState }) : null, rec.content ? /* @__PURE__ */ React18.createElement(Text16, null, rec.content) : /* @__PURE__ */ React18.createElement(Text16, { dimColor: true, italic: true }, "(tool-call response only)"));
|
|
9505
9837
|
}
|
|
9506
9838
|
if (rec.role === "tool") {
|
|
9507
|
-
return /* @__PURE__ */
|
|
9839
|
+
return /* @__PURE__ */ React18.createElement(Box16, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React18.createElement(Text16, { color: "yellow" }, "tool<", rec.tool ?? "?", ">"), rec.args ? /* @__PURE__ */ React18.createElement(Text16, { dimColor: true }, " args: ", truncate3(rec.args, toolArgsMax)) : null, /* @__PURE__ */ React18.createElement(Text16, { dimColor: true }, " \u2192 ", truncate3(rec.content, toolContentMax)));
|
|
9508
9840
|
}
|
|
9509
9841
|
if (rec.role === "error") {
|
|
9510
|
-
return /* @__PURE__ */
|
|
9842
|
+
return /* @__PURE__ */ React18.createElement(Box16, { marginTop: 1 }, /* @__PURE__ */ React18.createElement(Text16, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React18.createElement(Text16, { color: "red" }, rec.error ?? rec.content));
|
|
9511
9843
|
}
|
|
9512
9844
|
if (rec.role === "done" || rec.role === "assistant_delta") {
|
|
9513
9845
|
return null;
|
|
9514
9846
|
}
|
|
9515
|
-
return /* @__PURE__ */
|
|
9847
|
+
return /* @__PURE__ */ React18.createElement(Box16, null, /* @__PURE__ */ React18.createElement(Text16, { dimColor: true }, "[", rec.role, "] ", rec.content));
|
|
9516
9848
|
}
|
|
9517
9849
|
function CacheBadge({ usage }) {
|
|
9518
9850
|
const hit = usage.prompt_cache_hit_tokens ?? 0;
|
|
@@ -9521,7 +9853,7 @@ function CacheBadge({ usage }) {
|
|
|
9521
9853
|
if (total === 0) return null;
|
|
9522
9854
|
const pct2 = hit / total * 100;
|
|
9523
9855
|
const color = pct2 >= 70 ? "green" : pct2 >= 40 ? "yellow" : "red";
|
|
9524
|
-
return /* @__PURE__ */
|
|
9856
|
+
return /* @__PURE__ */ React18.createElement(Text16, null, /* @__PURE__ */ React18.createElement(Text16, { dimColor: true }, " \xB7 cache "), /* @__PURE__ */ React18.createElement(Text16, { color }, pct2.toFixed(1), "%"));
|
|
9525
9857
|
}
|
|
9526
9858
|
function truncate3(s, max) {
|
|
9527
9859
|
return s.length <= max ? s : `${s.slice(0, max)}\u2026 (+${s.length - max} chars)`;
|
|
@@ -9555,7 +9887,7 @@ function DiffApp({ report }) {
|
|
|
9555
9887
|
}
|
|
9556
9888
|
});
|
|
9557
9889
|
const pair = report.pairs[idx];
|
|
9558
|
-
return /* @__PURE__ */
|
|
9890
|
+
return /* @__PURE__ */ React19.createElement(Box17, { flexDirection: "column" }, /* @__PURE__ */ React19.createElement(DiffHeader, { report }), /* @__PURE__ */ React19.createElement(Box17, { marginTop: 1, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ React19.createElement(Text17, { color: "cyan", bold: true }, "turn ", pair?.turn ?? "?", " (", idx + 1, " / ", report.pairs.length, ")"), /* @__PURE__ */ React19.createElement(Text17, null, pair ? /* @__PURE__ */ React19.createElement(KindBadge, { kind: pair.kind }) : null)), /* @__PURE__ */ React19.createElement(Box17, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React19.createElement(Pane, { label: report.a.label, headerColor: "blue", records: paneRecords(pair, "a") }), /* @__PURE__ */ React19.createElement(Pane, { label: report.b.label, headerColor: "magenta", records: paneRecords(pair, "b") })), pair?.divergenceNote ? /* @__PURE__ */ React19.createElement(Box17, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React19.createElement(Text17, { color: "yellow" }, "\u2605 "), /* @__PURE__ */ React19.createElement(Text17, null, pair.divergenceNote)) : null, /* @__PURE__ */ React19.createElement(Box17, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React19.createElement(Text17, { dimColor: true }, /* @__PURE__ */ React19.createElement(Text17, { bold: true }, "j"), "/", /* @__PURE__ */ React19.createElement(Text17, { bold: true }, "\u2193"), " next \xB7 ", /* @__PURE__ */ React19.createElement(Text17, { bold: true }, "k"), "/", /* @__PURE__ */ React19.createElement(Text17, { bold: true }, "\u2191"), " ", "prev \xB7 ", /* @__PURE__ */ React19.createElement(Text17, { bold: true }, "n"), " next-diverge \xB7 ", /* @__PURE__ */ React19.createElement(Text17, { bold: true }, "N"), "/", /* @__PURE__ */ React19.createElement(Text17, { bold: true }, "p"), " ", "prev-diverge \xB7 ", /* @__PURE__ */ React19.createElement(Text17, { bold: true }, "g"), "/", /* @__PURE__ */ React19.createElement(Text17, { bold: true }, "G"), " first/last \xB7 ", /* @__PURE__ */ React19.createElement(Text17, { bold: true }, "q"), " ", "quit")));
|
|
9559
9891
|
}
|
|
9560
9892
|
function DiffHeader({ report }) {
|
|
9561
9893
|
const a = report.a;
|
|
@@ -9573,15 +9905,15 @@ function DiffHeader({ report }) {
|
|
|
9573
9905
|
} else if (a.stats.prefixHashes[0] && a.stats.prefixHashes[0] === b.stats.prefixHashes[0]) {
|
|
9574
9906
|
prefixLine = `shared prefix hash ${a.stats.prefixHashes[0].slice(0, 12)}\u2026 \u2014 cache delta attributable to log stability, not prompt change.`;
|
|
9575
9907
|
}
|
|
9576
|
-
return /* @__PURE__ */
|
|
9908
|
+
return /* @__PURE__ */ React19.createElement(Box17, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React19.createElement(Box17, { justifyContent: "space-between" }, /* @__PURE__ */ React19.createElement(Text17, null, /* @__PURE__ */ React19.createElement(Text17, { color: "cyan", bold: true }, "reasonix diff"), /* @__PURE__ */ React19.createElement(Text17, { dimColor: true }, " \xB7 A="), /* @__PURE__ */ React19.createElement(Text17, { color: "blue" }, a.label), /* @__PURE__ */ React19.createElement(Text17, { dimColor: true }, " vs B="), /* @__PURE__ */ React19.createElement(Text17, { color: "magenta" }, b.label)), /* @__PURE__ */ React19.createElement(Text17, { dimColor: true }, report.pairs.length, " turns aligned")), /* @__PURE__ */ React19.createElement(Box17, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React19.createElement(Text17, null, /* @__PURE__ */ React19.createElement(Text17, { dimColor: true }, "cache "), /* @__PURE__ */ React19.createElement(Text17, null, (a.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React19.createElement(Text17, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React19.createElement(Text17, null, (b.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React19.createElement(Text17, { color: cacheDelta >= 0 ? "green" : "red", bold: true }, " ", cacheDelta >= 0 ? "+" : "", (cacheDelta * 100).toFixed(1), "pp")), /* @__PURE__ */ React19.createElement(Text17, null, /* @__PURE__ */ React19.createElement(Text17, { dimColor: true }, "cost "), /* @__PURE__ */ React19.createElement(Text17, null, "$", a.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React19.createElement(Text17, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React19.createElement(Text17, null, "$", b.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React19.createElement(Text17, { color: costDelta2 <= 0 ? "green" : "red", bold: true }, " ", costDelta2 >= 0 ? "+" : "", costDelta2.toFixed(1), "%")), /* @__PURE__ */ React19.createElement(Text17, null, /* @__PURE__ */ React19.createElement(Text17, { dimColor: true }, "model calls "), /* @__PURE__ */ React19.createElement(Text17, null, a.stats.turns, " \u2192 ", b.stats.turns))), prefixLine ? /* @__PURE__ */ React19.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React19.createElement(Text17, { dimColor: true, italic: true }, prefixLine)) : null);
|
|
9577
9909
|
}
|
|
9578
9910
|
function Pane({
|
|
9579
9911
|
label,
|
|
9580
9912
|
headerColor,
|
|
9581
9913
|
records
|
|
9582
9914
|
}) {
|
|
9583
|
-
return /* @__PURE__ */
|
|
9584
|
-
|
|
9915
|
+
return /* @__PURE__ */ React19.createElement(
|
|
9916
|
+
Box17,
|
|
9585
9917
|
{
|
|
9586
9918
|
flexDirection: "column",
|
|
9587
9919
|
flexGrow: 1,
|
|
@@ -9589,21 +9921,21 @@ function Pane({
|
|
|
9589
9921
|
borderStyle: "single",
|
|
9590
9922
|
borderColor: headerColor
|
|
9591
9923
|
},
|
|
9592
|
-
/* @__PURE__ */
|
|
9593
|
-
records.length === 0 ? /* @__PURE__ */
|
|
9924
|
+
/* @__PURE__ */ React19.createElement(Text17, { color: headerColor, bold: true }, label),
|
|
9925
|
+
records.length === 0 ? /* @__PURE__ */ React19.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React19.createElement(Text17, { dimColor: true, italic: true }, "(no records on this side for this turn)")) : /* @__PURE__ */ React19.createElement(Static2, { items: records.map((rec, i) => ({ key: `${label}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React19.createElement(RecordView, { key, rec, compact: true }))
|
|
9594
9926
|
);
|
|
9595
9927
|
}
|
|
9596
9928
|
function KindBadge({ kind }) {
|
|
9597
9929
|
if (kind === "match") {
|
|
9598
|
-
return /* @__PURE__ */
|
|
9930
|
+
return /* @__PURE__ */ React19.createElement(Text17, { color: "green" }, "\u2713 match");
|
|
9599
9931
|
}
|
|
9600
9932
|
if (kind === "diverge") {
|
|
9601
|
-
return /* @__PURE__ */
|
|
9933
|
+
return /* @__PURE__ */ React19.createElement(Text17, { color: "yellow" }, "\u2605 diverge");
|
|
9602
9934
|
}
|
|
9603
9935
|
if (kind === "only_in_a") {
|
|
9604
|
-
return /* @__PURE__ */
|
|
9936
|
+
return /* @__PURE__ */ React19.createElement(Text17, { color: "blue" }, "\u2190 only in A");
|
|
9605
9937
|
}
|
|
9606
|
-
return /* @__PURE__ */
|
|
9938
|
+
return /* @__PURE__ */ React19.createElement(Text17, { color: "magenta" }, "\u2192 only in B");
|
|
9607
9939
|
}
|
|
9608
9940
|
function paneRecords(pair, side) {
|
|
9609
9941
|
if (!pair) return [];
|
|
@@ -9634,7 +9966,7 @@ markdown report written to ${opts.mdPath}`);
|
|
|
9634
9966
|
return;
|
|
9635
9967
|
}
|
|
9636
9968
|
if (wantTui) {
|
|
9637
|
-
const { waitUntilExit } = render2(
|
|
9969
|
+
const { waitUntilExit } = render2(React20.createElement(DiffApp, { report }), {
|
|
9638
9970
|
exitOnCtrlC: true,
|
|
9639
9971
|
patchConsole: false
|
|
9640
9972
|
});
|
|
@@ -9775,11 +10107,11 @@ function pad2(s, width) {
|
|
|
9775
10107
|
|
|
9776
10108
|
// src/cli/commands/replay.ts
|
|
9777
10109
|
import { render as render3 } from "ink";
|
|
9778
|
-
import
|
|
10110
|
+
import React22 from "react";
|
|
9779
10111
|
|
|
9780
10112
|
// src/cli/ui/ReplayApp.tsx
|
|
9781
|
-
import { Box as
|
|
9782
|
-
import
|
|
10113
|
+
import { Box as Box18, Static as Static3, Text as Text18, useApp as useApp4, useInput as useInput6 } from "ink";
|
|
10114
|
+
import React21, { useMemo as useMemo2, useState as useState9 } from "react";
|
|
9783
10115
|
function ReplayApp({ meta, pages }) {
|
|
9784
10116
|
const { exit } = useApp4();
|
|
9785
10117
|
const maxIdx = Math.max(0, pages.length - 1);
|
|
@@ -9818,14 +10150,14 @@ function ReplayApp({ meta, pages }) {
|
|
|
9818
10150
|
const prefixHash = cumStats.prefixHashes.length === 1 ? cumStats.prefixHashes[0].slice(0, 16) : cumStats.prefixHashes.length === 0 ? "(untracked)" : `(churned \xD7${cumStats.prefixHashes.length})`;
|
|
9819
10151
|
const currentPage = pages[idx];
|
|
9820
10152
|
const progressLabel = pages.length === 0 ? "empty transcript" : `turn ${idx + 1} / ${pages.length}`;
|
|
9821
|
-
return /* @__PURE__ */
|
|
10153
|
+
return /* @__PURE__ */ React21.createElement(Box18, { flexDirection: "column" }, /* @__PURE__ */ React21.createElement(
|
|
9822
10154
|
StatsPanel,
|
|
9823
10155
|
{
|
|
9824
10156
|
summary,
|
|
9825
10157
|
model: cumStats.models[0] ?? meta?.model ?? "?",
|
|
9826
10158
|
prefixHash
|
|
9827
10159
|
}
|
|
9828
|
-
), /* @__PURE__ */
|
|
10160
|
+
), /* @__PURE__ */ React21.createElement(Box18, { flexDirection: "column", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React21.createElement(Box18, { justifyContent: "space-between" }, /* @__PURE__ */ React21.createElement(Text18, { color: "cyan", bold: true }, progressLabel), meta ? /* @__PURE__ */ React21.createElement(Text18, { dimColor: true }, meta.source, meta.task ? ` \xB7 ${meta.task}` : "", meta.mode ? ` \xB7 ${meta.mode}` : "") : null), currentPage ? /* @__PURE__ */ React21.createElement(Static3, { items: currentPage.records.map((rec, i) => ({ key: `${idx}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React21.createElement(RecordView, { key, rec })) : /* @__PURE__ */ React21.createElement(Text18, { dimColor: true, italic: true }, "no records")), /* @__PURE__ */ React21.createElement(Box18, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React21.createElement(Text18, { dimColor: true }, /* @__PURE__ */ React21.createElement(Text18, { bold: true }, "j"), "/", /* @__PURE__ */ React21.createElement(Text18, { bold: true }, "\u2193"), "/", /* @__PURE__ */ React21.createElement(Text18, { bold: true }, "space"), " next \xB7 ", /* @__PURE__ */ React21.createElement(Text18, { bold: true }, "k"), "/", /* @__PURE__ */ React21.createElement(Text18, { bold: true }, "\u2191"), " prev \xB7 ", /* @__PURE__ */ React21.createElement(Text18, { bold: true }, "g"), " first \xB7 ", /* @__PURE__ */ React21.createElement(Text18, { bold: true }, "G"), " last \xB7", " ", /* @__PURE__ */ React21.createElement(Text18, { bold: true }, "q"), " quit")));
|
|
9829
10161
|
}
|
|
9830
10162
|
|
|
9831
10163
|
// src/cli/commands/replay.ts
|
|
@@ -9837,7 +10169,7 @@ async function replayCommand(opts) {
|
|
|
9837
10169
|
}
|
|
9838
10170
|
const { parsed } = replayFromFile(opts.path);
|
|
9839
10171
|
const pages = groupRecordsByTurn(parsed.records);
|
|
9840
|
-
const { waitUntilExit } = render3(
|
|
10172
|
+
const { waitUntilExit } = render3(React22.createElement(ReplayApp, { meta: parsed.meta, pages }), {
|
|
9841
10173
|
exitOnCtrlC: true,
|
|
9842
10174
|
patchConsole: false
|
|
9843
10175
|
});
|
|
@@ -10142,12 +10474,12 @@ function truncate4(s, max) {
|
|
|
10142
10474
|
|
|
10143
10475
|
// src/cli/commands/setup.tsx
|
|
10144
10476
|
import { render as render4 } from "ink";
|
|
10145
|
-
import
|
|
10477
|
+
import React24 from "react";
|
|
10146
10478
|
|
|
10147
10479
|
// src/cli/ui/Wizard.tsx
|
|
10148
|
-
import { Box as
|
|
10480
|
+
import { Box as Box19, Text as Text19, useApp as useApp5, useInput as useInput7 } from "ink";
|
|
10149
10481
|
import TextInput2 from "ink-text-input";
|
|
10150
|
-
import
|
|
10482
|
+
import React23, { useState as useState10 } from "react";
|
|
10151
10483
|
|
|
10152
10484
|
// src/cli/ui/presets.ts
|
|
10153
10485
|
var PRESETS = {
|
|
@@ -10186,7 +10518,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
10186
10518
|
if (key.escape && step !== "saved" && onCancel) onCancel();
|
|
10187
10519
|
});
|
|
10188
10520
|
if (step === "apiKey") {
|
|
10189
|
-
return /* @__PURE__ */
|
|
10521
|
+
return /* @__PURE__ */ React23.createElement(
|
|
10190
10522
|
ApiKeyStep,
|
|
10191
10523
|
{
|
|
10192
10524
|
onSubmit: (key) => {
|
|
@@ -10200,7 +10532,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
10200
10532
|
);
|
|
10201
10533
|
}
|
|
10202
10534
|
if (step === "preset") {
|
|
10203
|
-
return /* @__PURE__ */
|
|
10535
|
+
return /* @__PURE__ */ React23.createElement(StepFrame, { title: "Pick a preset", step: 1, total: 3 }, /* @__PURE__ */ React23.createElement(
|
|
10204
10536
|
SingleSelect,
|
|
10205
10537
|
{
|
|
10206
10538
|
items: presetItems(),
|
|
@@ -10210,10 +10542,10 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
10210
10542
|
setStep("mcp");
|
|
10211
10543
|
}
|
|
10212
10544
|
}
|
|
10213
|
-
), /* @__PURE__ */
|
|
10545
|
+
), /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "\u2191/\u2193 move \xB7 enter confirm \xB7 esc cancel")));
|
|
10214
10546
|
}
|
|
10215
10547
|
if (step === "mcp") {
|
|
10216
|
-
return /* @__PURE__ */
|
|
10548
|
+
return /* @__PURE__ */ React23.createElement(StepFrame, { title: "Which MCP servers should Reasonix wire up for you?", step: 2, total: 3 }, /* @__PURE__ */ React23.createElement(
|
|
10217
10549
|
MultiSelect,
|
|
10218
10550
|
{
|
|
10219
10551
|
items: mcpItems(),
|
|
@@ -10238,7 +10570,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
10238
10570
|
}
|
|
10239
10571
|
const currentName = pending[0];
|
|
10240
10572
|
const entry = CATALOG_BY_NAME.get(currentName);
|
|
10241
|
-
return /* @__PURE__ */
|
|
10573
|
+
return /* @__PURE__ */ React23.createElement(
|
|
10242
10574
|
McpArgsStep,
|
|
10243
10575
|
{
|
|
10244
10576
|
entry,
|
|
@@ -10256,7 +10588,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
10256
10588
|
}
|
|
10257
10589
|
if (step === "review") {
|
|
10258
10590
|
const specs = data.selectedCatalog.map((name) => buildSpec(name, data.catalogArgs));
|
|
10259
|
-
return /* @__PURE__ */
|
|
10591
|
+
return /* @__PURE__ */ React23.createElement(StepFrame, { title: "Ready to save", step: 3, total: 3 }, /* @__PURE__ */ React23.createElement(Box19, { flexDirection: "column" }, /* @__PURE__ */ React23.createElement(SummaryLine, { label: "API key", value: redactKey(data.apiKey) }), /* @__PURE__ */ React23.createElement(SummaryLine, { label: "Preset", value: data.preset }), /* @__PURE__ */ React23.createElement(
|
|
10260
10592
|
SummaryLine,
|
|
10261
10593
|
{
|
|
10262
10594
|
label: "MCP",
|
|
@@ -10264,8 +10596,8 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
10264
10596
|
}
|
|
10265
10597
|
), specs.map((spec, i) => (
|
|
10266
10598
|
// biome-ignore lint/suspicious/noArrayIndexKey: review-only render, order fixed
|
|
10267
|
-
/* @__PURE__ */
|
|
10268
|
-
)), /* @__PURE__ */
|
|
10599
|
+
/* @__PURE__ */ React23.createElement(Box19, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "\xB7 ", spec))
|
|
10600
|
+
)), /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, null, "Saves to ", defaultConfigPath())), error ? /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, { color: "red" }, error)) : null, /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "enter save \xB7 esc cancel"))), /* @__PURE__ */ React23.createElement(
|
|
10269
10601
|
ReviewConfirm,
|
|
10270
10602
|
{
|
|
10271
10603
|
onConfirm: () => {
|
|
@@ -10291,7 +10623,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
10291
10623
|
}
|
|
10292
10624
|
));
|
|
10293
10625
|
}
|
|
10294
|
-
return /* @__PURE__ */
|
|
10626
|
+
return /* @__PURE__ */ React23.createElement(Box19, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React23.createElement(Text19, { bold: true, color: "green" }, "\u25B8 Saved."), /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, null, "Run `reasonix` any time to start chatting \u2014 your settings are remembered.")), /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "Press enter to exit.")), /* @__PURE__ */ React23.createElement(ExitOnEnter, { onExit: exit }));
|
|
10295
10627
|
}
|
|
10296
10628
|
function ApiKeyStep({
|
|
10297
10629
|
onSubmit,
|
|
@@ -10299,7 +10631,7 @@ function ApiKeyStep({
|
|
|
10299
10631
|
onError
|
|
10300
10632
|
}) {
|
|
10301
10633
|
const [value, setValue] = useState10("");
|
|
10302
|
-
return /* @__PURE__ */
|
|
10634
|
+
return /* @__PURE__ */ React23.createElement(Box19, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React23.createElement(Text19, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React23.createElement(
|
|
10303
10635
|
TextInput2,
|
|
10304
10636
|
{
|
|
10305
10637
|
value,
|
|
@@ -10316,7 +10648,7 @@ function ApiKeyStep({
|
|
|
10316
10648
|
mask: "\u2022",
|
|
10317
10649
|
placeholder: "sk-..."
|
|
10318
10650
|
}
|
|
10319
|
-
)), error ? /* @__PURE__ */
|
|
10651
|
+
)), error ? /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, { color: "red" }, error)) : value ? /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "preview: ", redactKey(value))) : null);
|
|
10320
10652
|
}
|
|
10321
10653
|
function McpArgsStep({
|
|
10322
10654
|
entry,
|
|
@@ -10325,7 +10657,7 @@ function McpArgsStep({
|
|
|
10325
10657
|
onError
|
|
10326
10658
|
}) {
|
|
10327
10659
|
const [value, setValue] = useState10("");
|
|
10328
|
-
return /* @__PURE__ */
|
|
10660
|
+
return /* @__PURE__ */ React23.createElement(StepFrame, { title: `Configure ${entry.name}`, step: 2, total: 3 }, /* @__PURE__ */ React23.createElement(Box19, { flexDirection: "column" }, /* @__PURE__ */ React23.createElement(Text19, null, entry.summary), entry.note ? /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, entry.note)) : null, /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, null, "Required parameter: "), /* @__PURE__ */ React23.createElement(Text19, { bold: true }, entry.userArgs)), /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, { bold: true, color: "cyan" }, entry.userArgs, " \u203A "), /* @__PURE__ */ React23.createElement(
|
|
10329
10661
|
TextInput2,
|
|
10330
10662
|
{
|
|
10331
10663
|
value,
|
|
@@ -10341,7 +10673,7 @@ function McpArgsStep({
|
|
|
10341
10673
|
},
|
|
10342
10674
|
placeholder: placeholderFor(entry)
|
|
10343
10675
|
}
|
|
10344
|
-
)), error ? /* @__PURE__ */
|
|
10676
|
+
)), error ? /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, { color: "red" }, error)) : null));
|
|
10345
10677
|
}
|
|
10346
10678
|
function ReviewConfirm({ onConfirm }) {
|
|
10347
10679
|
useInput7((_i, key) => {
|
|
@@ -10361,10 +10693,10 @@ function StepFrame({
|
|
|
10361
10693
|
total,
|
|
10362
10694
|
children
|
|
10363
10695
|
}) {
|
|
10364
|
-
return /* @__PURE__ */
|
|
10696
|
+
return /* @__PURE__ */ React23.createElement(Box19, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React23.createElement(Box19, null, /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "Step ", step, "/", total, " \xB7", " "), /* @__PURE__ */ React23.createElement(Text19, { bold: true, color: "cyan" }, title)), /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1, flexDirection: "column" }, children));
|
|
10365
10697
|
}
|
|
10366
10698
|
function SummaryLine({ label, value }) {
|
|
10367
|
-
return /* @__PURE__ */
|
|
10699
|
+
return /* @__PURE__ */ React23.createElement(Box19, null, /* @__PURE__ */ React23.createElement(Text19, null, label.padEnd(12)), /* @__PURE__ */ React23.createElement(Text19, { bold: true }, value));
|
|
10368
10700
|
}
|
|
10369
10701
|
function presetItems() {
|
|
10370
10702
|
return ["fast", "smart", "max"].map((name) => ({
|
|
@@ -10420,7 +10752,7 @@ async function setupCommand(_opts = {}) {
|
|
|
10420
10752
|
const existingKey = loadApiKey();
|
|
10421
10753
|
const existing = readConfig();
|
|
10422
10754
|
const { waitUntilExit, unmount } = render4(
|
|
10423
|
-
/* @__PURE__ */
|
|
10755
|
+
/* @__PURE__ */ React24.createElement(
|
|
10424
10756
|
Wizard,
|
|
10425
10757
|
{
|
|
10426
10758
|
existingApiKey: existingKey,
|