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