reasonix 0.7.4 → 0.7.5
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 +768 -477
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -7113,11 +7113,11 @@ function formatLogSize(path = defaultUsageLogPath()) {
|
|
|
7113
7113
|
// src/cli/commands/chat.tsx
|
|
7114
7114
|
import { existsSync as existsSync12, statSync as statSync7 } from "fs";
|
|
7115
7115
|
import { render } from "ink";
|
|
7116
|
-
import
|
|
7116
|
+
import React26, { useState as useState12 } from "react";
|
|
7117
7117
|
|
|
7118
7118
|
// src/cli/ui/App.tsx
|
|
7119
|
-
import { Box as
|
|
7120
|
-
import
|
|
7119
|
+
import { Box as Box21, Static, useApp, useStdout as useStdout8 } from "ink";
|
|
7120
|
+
import React23, { useCallback as useCallback4, useEffect as useEffect6, useMemo as useMemo3, useRef as useRef6, useState as useState10 } from "react";
|
|
7121
7121
|
|
|
7122
7122
|
// src/code/pending-edits.ts
|
|
7123
7123
|
import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync11, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "fs";
|
|
@@ -7430,26 +7430,42 @@ function AtMentionSuggestions({
|
|
|
7430
7430
|
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingX: 1, marginTop: 1 }, hiddenAbove > 0 ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " \u2191 ", hiddenAbove, " more above") : null, shown.map((path, i) => /* @__PURE__ */ React.createElement(FileRow, { key: path, path, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " \u2193 ", hiddenBelow, " more below") : null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " [\u2191\u2193] navigate \xB7 [Tab]/[Enter] pick \xB7 file content inlined on send"));
|
|
7431
7431
|
}
|
|
7432
7432
|
function FileRow({ path, isSelected }) {
|
|
7433
|
-
const marker = isSelected ? "\u25B8" : " ";
|
|
7434
7433
|
const slash = path.lastIndexOf("/");
|
|
7435
7434
|
const dir = slash >= 0 ? `${path.slice(0, slash)}/` : "";
|
|
7436
7435
|
const base = slash >= 0 ? path.slice(slash + 1) : path;
|
|
7437
7436
|
if (isSelected) {
|
|
7438
|
-
return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, {
|
|
7437
|
+
return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { backgroundColor: "#67e8f9", color: "black", bold: true }, ` \u25B8 ${base}${dir ? ` ${dir}` : ""} `));
|
|
7439
7438
|
}
|
|
7440
|
-
return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, {
|
|
7439
|
+
return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "#94a3b8" }, ` ${base}`), dir ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, ` ${dir}`) : null);
|
|
7441
7440
|
}
|
|
7442
7441
|
|
|
7443
7442
|
// src/cli/ui/ChoiceConfirm.tsx
|
|
7444
|
-
import { Box as
|
|
7445
|
-
import
|
|
7443
|
+
import { Box as Box4 } from "ink";
|
|
7444
|
+
import React5 from "react";
|
|
7445
|
+
|
|
7446
|
+
// src/cli/ui/ModalCard.tsx
|
|
7447
|
+
import { Box as Box2, Text as Text2, useStdout } from "ink";
|
|
7448
|
+
import React2 from "react";
|
|
7449
|
+
function ModalCard({
|
|
7450
|
+
accent,
|
|
7451
|
+
title,
|
|
7452
|
+
subtitle,
|
|
7453
|
+
icon,
|
|
7454
|
+
children
|
|
7455
|
+
}) {
|
|
7456
|
+
const { stdout: stdout2 } = useStdout();
|
|
7457
|
+
const cols = stdout2?.columns ?? 80;
|
|
7458
|
+
const ruleWidth = Math.min(80, Math.max(28, cols - 4));
|
|
7459
|
+
const titleText = icon ? ` ${icon} ${title} ` : ` ${title} `;
|
|
7460
|
+
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React2.createElement(Box2, null, /* @__PURE__ */ React2.createElement(Text2, { color: accent }, "\u2594".repeat(ruleWidth))), /* @__PURE__ */ React2.createElement(Box2, { marginTop: 1 }, /* @__PURE__ */ React2.createElement(Text2, { backgroundColor: accent, color: "black", bold: true }, titleText), subtitle ? /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, ` ${subtitle}`) : null), /* @__PURE__ */ React2.createElement(Box2, { marginTop: 1, flexDirection: "column" }, children), /* @__PURE__ */ React2.createElement(Box2, { marginTop: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: accent, dimColor: true }, "\u2581".repeat(ruleWidth))));
|
|
7461
|
+
}
|
|
7446
7462
|
|
|
7447
7463
|
// src/cli/ui/Select.tsx
|
|
7448
|
-
import { Box as
|
|
7449
|
-
import
|
|
7464
|
+
import { Box as Box3, Text as Text3 } from "ink";
|
|
7465
|
+
import React4, { useState } from "react";
|
|
7450
7466
|
|
|
7451
7467
|
// src/cli/ui/keystroke-context.tsx
|
|
7452
|
-
import
|
|
7468
|
+
import React3, { createContext, useContext, useEffect, useRef } from "react";
|
|
7453
7469
|
|
|
7454
7470
|
// src/cli/ui/stdin-reader.ts
|
|
7455
7471
|
import { stdin } from "process";
|
|
@@ -7771,7 +7787,7 @@ function KeystrokeProvider({
|
|
|
7771
7787
|
unsubscribe();
|
|
7772
7788
|
};
|
|
7773
7789
|
}, [providedReader]);
|
|
7774
|
-
return /* @__PURE__ */
|
|
7790
|
+
return /* @__PURE__ */ React3.createElement(KeystrokeContext.Provider, { value: busRef.current }, children);
|
|
7775
7791
|
}
|
|
7776
7792
|
function useKeystroke(handler, isActive = true) {
|
|
7777
7793
|
const bus = useContext(KeystrokeContext);
|
|
@@ -7809,7 +7825,7 @@ function SingleSelect({
|
|
|
7809
7825
|
onCancel();
|
|
7810
7826
|
}
|
|
7811
7827
|
});
|
|
7812
|
-
return /* @__PURE__ */
|
|
7828
|
+
return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, items.map((item, i) => /* @__PURE__ */ React4.createElement(
|
|
7813
7829
|
SelectRow,
|
|
7814
7830
|
{
|
|
7815
7831
|
key: item.value,
|
|
@@ -7817,7 +7833,7 @@ function SingleSelect({
|
|
|
7817
7833
|
active: i === index,
|
|
7818
7834
|
marker: i === index ? "\u25B8" : " "
|
|
7819
7835
|
}
|
|
7820
|
-
)), footer ? /* @__PURE__ */
|
|
7836
|
+
)), footer ? /* @__PURE__ */ React4.createElement(Box3, { marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, footer)) : null);
|
|
7821
7837
|
}
|
|
7822
7838
|
function MultiSelect({
|
|
7823
7839
|
items,
|
|
@@ -7853,10 +7869,10 @@ function MultiSelect({
|
|
|
7853
7869
|
onCancel();
|
|
7854
7870
|
}
|
|
7855
7871
|
});
|
|
7856
|
-
return /* @__PURE__ */
|
|
7872
|
+
return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, items.map((item, i) => {
|
|
7857
7873
|
const checked = selected.has(item.value);
|
|
7858
7874
|
const marker = checked ? "[x]" : "[ ]";
|
|
7859
|
-
return /* @__PURE__ */
|
|
7875
|
+
return /* @__PURE__ */ React4.createElement(
|
|
7860
7876
|
SelectRow,
|
|
7861
7877
|
{
|
|
7862
7878
|
key: item.value,
|
|
@@ -7865,7 +7881,7 @@ function MultiSelect({
|
|
|
7865
7881
|
marker: `${i === index ? "\u25B8" : " "} ${marker}`
|
|
7866
7882
|
}
|
|
7867
7883
|
);
|
|
7868
|
-
}), footer ? /* @__PURE__ */
|
|
7884
|
+
}), footer ? /* @__PURE__ */ React4.createElement(Box3, { marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, footer)) : null);
|
|
7869
7885
|
}
|
|
7870
7886
|
function SelectRow({
|
|
7871
7887
|
item,
|
|
@@ -7873,7 +7889,7 @@ function SelectRow({
|
|
|
7873
7889
|
marker
|
|
7874
7890
|
}) {
|
|
7875
7891
|
const color = item.disabled ? "gray" : active ? "cyan" : void 0;
|
|
7876
|
-
return /* @__PURE__ */
|
|
7892
|
+
return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(Text3, { color }, marker, " ", item.label)), item.hint ? /* @__PURE__ */ React4.createElement(Box3, { paddingLeft: marker.length + 1 }, /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, item.hint)) : null);
|
|
7877
7893
|
}
|
|
7878
7894
|
function findNextEnabled(items, from, step) {
|
|
7879
7895
|
if (items.length === 0) return 0;
|
|
@@ -7906,7 +7922,7 @@ function ChoiceConfirmInner({ question, options, allowCustom, onChoose }) {
|
|
|
7906
7922
|
label: "Cancel \u2014 drop the question",
|
|
7907
7923
|
hint: "Model stops and asks what you want instead."
|
|
7908
7924
|
});
|
|
7909
|
-
return /* @__PURE__ */
|
|
7925
|
+
return /* @__PURE__ */ React5.createElement(ModalCard, { accent: "#f0abfc", icon: "\u{1F500}", title: "model wants you to pick", subtitle: question }, /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(
|
|
7910
7926
|
SingleSelect,
|
|
7911
7927
|
{
|
|
7912
7928
|
initialValue: options[0]?.id,
|
|
@@ -7921,11 +7937,11 @@ function ChoiceConfirmInner({ question, options, allowCustom, onChoose }) {
|
|
|
7921
7937
|
}
|
|
7922
7938
|
)));
|
|
7923
7939
|
}
|
|
7924
|
-
var ChoiceConfirm =
|
|
7940
|
+
var ChoiceConfirm = React5.memo(ChoiceConfirmInner);
|
|
7925
7941
|
|
|
7926
7942
|
// src/cli/ui/EditConfirm.tsx
|
|
7927
|
-
import { Box as
|
|
7928
|
-
import
|
|
7943
|
+
import { Box as Box5, Text as Text4, useStdout as useStdout2 } from "ink";
|
|
7944
|
+
import React6, { useMemo, useState as useState2 } from "react";
|
|
7929
7945
|
|
|
7930
7946
|
// src/code/diff-preview.ts
|
|
7931
7947
|
function formatEditBlockDiff(block, opts = {}) {
|
|
@@ -8000,7 +8016,7 @@ function capLines(lines, maxLines, indent) {
|
|
|
8000
8016
|
var MODAL_OVERHEAD_ROWS = 18;
|
|
8001
8017
|
var MIN_DIFF_ROWS = 8;
|
|
8002
8018
|
function EditConfirm({ block, onChoose }) {
|
|
8003
|
-
const { stdout: stdout2 } =
|
|
8019
|
+
const { stdout: stdout2 } = useStdout2();
|
|
8004
8020
|
const rows = stdout2?.rows ?? 40;
|
|
8005
8021
|
const budget = Math.max(MIN_DIFF_ROWS, rows - MODAL_OVERHEAD_ROWS);
|
|
8006
8022
|
const allLines = useMemo(
|
|
@@ -8064,57 +8080,75 @@ function EditConfirm({ block, onChoose }) {
|
|
|
8064
8080
|
const hiddenBelow = Math.max(0, allLines.length - effectiveScroll - budget);
|
|
8065
8081
|
const totalLines = allLines.length;
|
|
8066
8082
|
const showScrollHud = hiddenAbove + hiddenBelow > 0;
|
|
8067
|
-
|
|
8068
|
-
|
|
8083
|
+
const subtitleParts = [`-${removed} +${added} lines`];
|
|
8084
|
+
if (showScrollHud) {
|
|
8085
|
+
subtitleParts.push(
|
|
8086
|
+
`viewing ${effectiveScroll + 1}-${effectiveScroll + visibleLines.length}/${totalLines}`
|
|
8087
|
+
);
|
|
8088
|
+
}
|
|
8089
|
+
return /* @__PURE__ */ React6.createElement(
|
|
8090
|
+
ModalCard,
|
|
8069
8091
|
{
|
|
8070
|
-
|
|
8092
|
+
accent: isNew ? "#86efac" : "#fcd34d",
|
|
8093
|
+
icon: isNew ? "\u271A" : "\u270E",
|
|
8094
|
+
title: `${tag} ${block.path}`,
|
|
8095
|
+
subtitle: subtitleParts.join(" \xB7 ")
|
|
8071
8096
|
},
|
|
8072
|
-
|
|
8073
|
-
) : null, /* @__PURE__ */ React5.createElement(Box4, { marginTop: hiddenAbove > 0 ? 0 : 1, flexDirection: "column" }, visibleLines.map((line, i) => {
|
|
8074
|
-
const trimmed = line.trimStart();
|
|
8075
|
-
const color = trimmed.startsWith("+") ? "green" : trimmed.startsWith("-") ? "red" : void 0;
|
|
8076
|
-
const dim = !color;
|
|
8077
|
-
return /* @__PURE__ */ React5.createElement(
|
|
8097
|
+
hiddenAbove > 0 ? /* @__PURE__ */ React6.createElement(
|
|
8078
8098
|
Text4,
|
|
8079
8099
|
{
|
|
8080
|
-
|
|
8081
|
-
color,
|
|
8082
|
-
dimColor: dim
|
|
8100
|
+
dimColor: true
|
|
8083
8101
|
},
|
|
8084
|
-
line
|
|
8085
|
-
)
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8102
|
+
` \u2191 ${hiddenAbove} line${hiddenAbove === 1 ? "" : "s"} above (\u2191/k or PgUp)`
|
|
8103
|
+
) : null,
|
|
8104
|
+
/* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column" }, visibleLines.map((line, i) => {
|
|
8105
|
+
const trimmed = line.trimStart();
|
|
8106
|
+
const color = trimmed.startsWith("+") ? "#4ade80" : trimmed.startsWith("-") ? "#f87171" : void 0;
|
|
8107
|
+
const dim = !color;
|
|
8108
|
+
return /* @__PURE__ */ React6.createElement(
|
|
8109
|
+
Text4,
|
|
8110
|
+
{
|
|
8111
|
+
key: `diff-${effectiveScroll}-${i}`,
|
|
8112
|
+
color,
|
|
8113
|
+
dimColor: dim
|
|
8114
|
+
},
|
|
8115
|
+
line
|
|
8116
|
+
);
|
|
8117
|
+
})),
|
|
8118
|
+
hiddenBelow > 0 ? /* @__PURE__ */ React6.createElement(
|
|
8119
|
+
Text4,
|
|
8120
|
+
{
|
|
8121
|
+
dimColor: true
|
|
8122
|
+
},
|
|
8123
|
+
` \u2193 ${hiddenBelow} line${hiddenBelow === 1 ? "" : "s"} below (\u2193/j or Space/PgDn)`
|
|
8124
|
+
) : null,
|
|
8125
|
+
/* @__PURE__ */ React6.createElement(Box5, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text4, { dimColor: true }, "[", /* @__PURE__ */ React6.createElement(Text4, { color: "#67e8f9", bold: true }, "y"), "/Enter] apply \xB7 [", /* @__PURE__ */ React6.createElement(Text4, { color: "#67e8f9", bold: true }, "n"), "] reject \xB7 [", /* @__PURE__ */ React6.createElement(Text4, { color: "#67e8f9", bold: true }, "a"), "] apply rest \xB7 [", /* @__PURE__ */ React6.createElement(Text4, { color: "#67e8f9", bold: true }, "A"), "] flip AUTO \xB7 [", /* @__PURE__ */ React6.createElement(Text4, { color: "#67e8f9", bold: true }, "\u2191\u2193/Space"), "] scroll \xB7 [Esc] abort"))
|
|
8126
|
+
);
|
|
8093
8127
|
}
|
|
8094
8128
|
|
|
8095
8129
|
// src/cli/ui/EventLog.tsx
|
|
8096
|
-
import { Box as
|
|
8097
|
-
import
|
|
8130
|
+
import { Box as Box9, Text as Text8, useStdout as useStdout3 } from "ink";
|
|
8131
|
+
import React11 from "react";
|
|
8098
8132
|
|
|
8099
8133
|
// src/cli/ui/PlanStateBlock.tsx
|
|
8100
|
-
import { Box as
|
|
8101
|
-
import
|
|
8134
|
+
import { Box as Box6, Text as Text5 } from "ink";
|
|
8135
|
+
import React7 from "react";
|
|
8102
8136
|
function PlanStateBlock({ planState }) {
|
|
8103
8137
|
const fields = [];
|
|
8104
|
-
if (planState.subgoals.length) fields.push(["subgoals", planState.subgoals, "
|
|
8138
|
+
if (planState.subgoals.length) fields.push(["subgoals", planState.subgoals, "#67e8f9", false]);
|
|
8105
8139
|
if (planState.hypotheses.length)
|
|
8106
|
-
fields.push(["hypotheses", planState.hypotheses, "
|
|
8140
|
+
fields.push(["hypotheses", planState.hypotheses, "#86efac", false]);
|
|
8107
8141
|
if (planState.uncertainties.length)
|
|
8108
|
-
fields.push(["uncertainties", planState.uncertainties, "
|
|
8142
|
+
fields.push(["uncertainties", planState.uncertainties, "#fcd34d", false]);
|
|
8109
8143
|
if (planState.rejectedPaths.length)
|
|
8110
|
-
fields.push(["rejected", planState.rejectedPaths, "
|
|
8144
|
+
fields.push(["rejected", planState.rejectedPaths, "#94a3b8", true]);
|
|
8111
8145
|
if (fields.length === 0) return null;
|
|
8112
|
-
return /* @__PURE__ */
|
|
8146
|
+
return /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", marginBottom: 1 }, fields.map(([label, items, color, dim]) => /* @__PURE__ */ React7.createElement(Box6, { key: label }, /* @__PURE__ */ React7.createElement(Text5, { backgroundColor: color, color: "black", bold: true, dimColor: dim }, ` ${label} ${items.length} `), /* @__PURE__ */ React7.createElement(Text5, null, " "), /* @__PURE__ */ React7.createElement(Text5, { dimColor: dim }, items.join(" \xB7 ")))));
|
|
8113
8147
|
}
|
|
8114
8148
|
|
|
8115
8149
|
// src/cli/ui/PlanStepList.tsx
|
|
8116
|
-
import { Box as
|
|
8117
|
-
import
|
|
8150
|
+
import { Box as Box7, Text as Text6 } from "ink";
|
|
8151
|
+
import React8 from "react";
|
|
8118
8152
|
function riskDots(risk) {
|
|
8119
8153
|
switch (risk) {
|
|
8120
8154
|
case "high":
|
|
@@ -8127,18 +8161,6 @@ function riskDots(risk) {
|
|
|
8127
8161
|
return { dots: " ", color: "gray" };
|
|
8128
8162
|
}
|
|
8129
8163
|
}
|
|
8130
|
-
function statusGlyph(status2) {
|
|
8131
|
-
switch (status2) {
|
|
8132
|
-
case "done":
|
|
8133
|
-
return { glyph: "\u2713", color: "green" };
|
|
8134
|
-
case "running":
|
|
8135
|
-
return { glyph: "\u25B6", color: "cyan" };
|
|
8136
|
-
case "skipped":
|
|
8137
|
-
return { glyph: "\u2014", color: "gray" };
|
|
8138
|
-
default:
|
|
8139
|
-
return { glyph: " ", color: "yellow" };
|
|
8140
|
-
}
|
|
8141
|
-
}
|
|
8142
8164
|
function getStatus(stepId, statuses) {
|
|
8143
8165
|
if (!statuses) return "pending";
|
|
8144
8166
|
if (statuses instanceof Map) {
|
|
@@ -8153,25 +8175,37 @@ function PlanStepListInner({ steps, statuses, focusStepId }) {
|
|
|
8153
8175
|
{ length: steps.length },
|
|
8154
8176
|
(_, i) => getStatus(steps[i].id, statuses)
|
|
8155
8177
|
).filter((s) => s === "done").length;
|
|
8156
|
-
|
|
8178
|
+
const pct2 = Math.round(doneCount / steps.length * 100);
|
|
8179
|
+
return /* @__PURE__ */ React8.createElement(Box7, { flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Box7, null, /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, `${steps.length} step${steps.length === 1 ? "" : "s"}`, doneCount > 0 ? ` \xB7 ${doneCount}/${steps.length} done (${pct2}%)` : "", hasAnyRisk ? " \xB7 risk: " : ""), hasAnyRisk ? /* @__PURE__ */ React8.createElement(RiskLegend, null) : null), /* @__PURE__ */ React8.createElement(Box7, { flexDirection: "column", marginTop: 1 }, steps.map((step) => {
|
|
8157
8180
|
const status2 = getStatus(step.id, statuses);
|
|
8158
8181
|
const focus = focusStepId === step.id;
|
|
8159
8182
|
const risk = riskDots(step.risk);
|
|
8160
|
-
const glyph = statusGlyph(status2);
|
|
8161
8183
|
const titleDim = status2 === "done" || status2 === "skipped";
|
|
8162
|
-
return /* @__PURE__ */
|
|
8184
|
+
return /* @__PURE__ */ React8.createElement(Box7, { key: step.id }, /* @__PURE__ */ React8.createElement(Text6, { color: focus ? "#67e8f9" : "gray", bold: focus }, focus ? "\u25B8 " : " "), /* @__PURE__ */ React8.createElement(Text6, { color: risk.color, bold: true }, risk.dots), /* @__PURE__ */ React8.createElement(Text6, null, " "), /* @__PURE__ */ React8.createElement(StatusBadge, { status: status2 }), /* @__PURE__ */ React8.createElement(Text6, null, " "), /* @__PURE__ */ React8.createElement(Text6, { dimColor: titleDim, bold: focus }, `${step.id} \xB7 ${step.title}`));
|
|
8163
8185
|
})));
|
|
8164
8186
|
}
|
|
8187
|
+
function StatusBadge({ status: status2 }) {
|
|
8188
|
+
switch (status2) {
|
|
8189
|
+
case "done":
|
|
8190
|
+
return /* @__PURE__ */ React8.createElement(Text6, { backgroundColor: "#4ade80", color: "black", bold: true }, " \u2713 DONE ");
|
|
8191
|
+
case "running":
|
|
8192
|
+
return /* @__PURE__ */ React8.createElement(Text6, { backgroundColor: "#67e8f9", color: "black", bold: true }, " \u25B6 RUN ");
|
|
8193
|
+
case "skipped":
|
|
8194
|
+
return /* @__PURE__ */ React8.createElement(Text6, { backgroundColor: "#94a3b8", color: "black", bold: true }, " \u2014 SKIP ");
|
|
8195
|
+
default:
|
|
8196
|
+
return /* @__PURE__ */ React8.createElement(Text6, { color: "#94a3b8", dimColor: true }, " \u2610 PEND ");
|
|
8197
|
+
}
|
|
8198
|
+
}
|
|
8165
8199
|
function RiskLegend() {
|
|
8166
|
-
return /* @__PURE__ */
|
|
8200
|
+
return /* @__PURE__ */ React8.createElement(Box7, null, /* @__PURE__ */ React8.createElement(Text6, { color: "green" }, "\u25CF"), /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, " low "), /* @__PURE__ */ React8.createElement(Text6, { color: "yellow" }, "\u25CF\u25CF"), /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, " med "), /* @__PURE__ */ React8.createElement(Text6, { color: "red" }, "\u25CF\u25CF\u25CF"), /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, " high"));
|
|
8167
8201
|
}
|
|
8168
|
-
var PlanStepList =
|
|
8202
|
+
var PlanStepList = React8.memo(PlanStepListInner);
|
|
8169
8203
|
|
|
8170
8204
|
// src/cli/ui/markdown.tsx
|
|
8171
8205
|
import { readFileSync as readFileSync13, statSync as statSync6 } from "fs";
|
|
8172
8206
|
import { isAbsolute as isAbsolute4, join as join11 } from "path";
|
|
8173
|
-
import { Box as
|
|
8174
|
-
import
|
|
8207
|
+
import { Box as Box8, Text as Text7 } from "ink";
|
|
8208
|
+
import React9 from "react";
|
|
8175
8209
|
var SUPERSCRIPT = {
|
|
8176
8210
|
"0": "\u2070",
|
|
8177
8211
|
"1": "\xB9",
|
|
@@ -8426,67 +8460,67 @@ function InlineMd({
|
|
|
8426
8460
|
for (const m of text.matchAll(INLINE_RE)) {
|
|
8427
8461
|
const start = m.index ?? 0;
|
|
8428
8462
|
if (start > last) {
|
|
8429
|
-
parts.push(/* @__PURE__ */
|
|
8463
|
+
parts.push(/* @__PURE__ */ React9.createElement(Text7, { key: `t${idx++}` }, text.slice(last, start)));
|
|
8430
8464
|
}
|
|
8431
8465
|
if (m[2] !== void 0 && m[3] !== void 0) {
|
|
8432
8466
|
const linkText = m[2];
|
|
8433
8467
|
const url = m[3];
|
|
8434
8468
|
if (isExternalUrl(url)) {
|
|
8435
8469
|
parts.push(
|
|
8436
|
-
/* @__PURE__ */
|
|
8470
|
+
/* @__PURE__ */ React9.createElement(Text7, { key: `l${idx++}`, color: "blue", underline: true }, linkText)
|
|
8437
8471
|
);
|
|
8438
8472
|
} else {
|
|
8439
8473
|
const status2 = citations?.get(url);
|
|
8440
8474
|
if (status2 && !status2.ok) {
|
|
8441
8475
|
parts.push(
|
|
8442
|
-
/* @__PURE__ */
|
|
8476
|
+
/* @__PURE__ */ React9.createElement(Text7, { key: `l${idx++}`, color: "red", strikethrough: true }, `${linkText} \u2717`)
|
|
8443
8477
|
);
|
|
8444
8478
|
} else {
|
|
8445
8479
|
parts.push(
|
|
8446
|
-
/* @__PURE__ */
|
|
8480
|
+
/* @__PURE__ */ React9.createElement(Text7, { key: `l${idx++}`, color: "cyan", underline: true }, linkText)
|
|
8447
8481
|
);
|
|
8448
8482
|
}
|
|
8449
8483
|
}
|
|
8450
8484
|
} else if (m[4] !== void 0) {
|
|
8451
8485
|
parts.push(
|
|
8452
|
-
/* @__PURE__ */
|
|
8486
|
+
/* @__PURE__ */ React9.createElement(Text7, { key: `bi${idx++}`, bold: true, italic: true }, m[4])
|
|
8453
8487
|
);
|
|
8454
8488
|
} else if (m[5] !== void 0) {
|
|
8455
8489
|
parts.push(
|
|
8456
|
-
/* @__PURE__ */
|
|
8490
|
+
/* @__PURE__ */ React9.createElement(Text7, { key: `b${idx++}`, bold: true }, m[5])
|
|
8457
8491
|
);
|
|
8458
8492
|
} else if (m[6] !== void 0) {
|
|
8459
8493
|
const stripped = m[6].replace(/^(\w+)\s+/, "");
|
|
8460
8494
|
parts.push(
|
|
8461
|
-
/* @__PURE__ */
|
|
8495
|
+
/* @__PURE__ */ React9.createElement(Text7, { key: `c${idx++}`, color: "yellow" }, stripped)
|
|
8462
8496
|
);
|
|
8463
8497
|
} else if (m[7] !== void 0) {
|
|
8464
8498
|
parts.push(
|
|
8465
|
-
/* @__PURE__ */
|
|
8499
|
+
/* @__PURE__ */ React9.createElement(Text7, { key: `c${idx++}`, color: "yellow" }, m[7])
|
|
8466
8500
|
);
|
|
8467
8501
|
} else if (m[8] !== void 0) {
|
|
8468
8502
|
parts.push(
|
|
8469
|
-
/* @__PURE__ */
|
|
8503
|
+
/* @__PURE__ */ React9.createElement(Text7, { key: `s${idx++}`, strikethrough: true, dimColor: true }, m[8])
|
|
8470
8504
|
);
|
|
8471
8505
|
} else if (m[9] !== void 0) {
|
|
8472
8506
|
parts.push(
|
|
8473
|
-
/* @__PURE__ */
|
|
8507
|
+
/* @__PURE__ */ React9.createElement(Text7, { key: `i${idx++}`, italic: true }, m[9])
|
|
8474
8508
|
);
|
|
8475
8509
|
} else if (m[10] !== void 0) {
|
|
8476
|
-
parts.push(/* @__PURE__ */
|
|
8510
|
+
parts.push(/* @__PURE__ */ React9.createElement(Text7, { key: `esc${idx++}` }, m[10]));
|
|
8477
8511
|
}
|
|
8478
8512
|
last = start + m[0].length;
|
|
8479
8513
|
}
|
|
8480
8514
|
if (last < text.length) {
|
|
8481
|
-
parts.push(/* @__PURE__ */
|
|
8515
|
+
parts.push(/* @__PURE__ */ React9.createElement(Text7, { key: `t${idx++}` }, text.slice(last)));
|
|
8482
8516
|
}
|
|
8483
8517
|
if (padTo !== void 0) {
|
|
8484
8518
|
const seen = visibleWidth(text);
|
|
8485
8519
|
if (seen < padTo) {
|
|
8486
|
-
parts.push(/* @__PURE__ */
|
|
8520
|
+
parts.push(/* @__PURE__ */ React9.createElement(Text7, { key: `pad${idx++}` }, " ".repeat(padTo - seen)));
|
|
8487
8521
|
}
|
|
8488
8522
|
}
|
|
8489
|
-
return /* @__PURE__ */
|
|
8523
|
+
return /* @__PURE__ */ React9.createElement(Text7, null, parts);
|
|
8490
8524
|
}
|
|
8491
8525
|
function stripInlineMarkup(s) {
|
|
8492
8526
|
return s.replace(
|
|
@@ -8725,34 +8759,34 @@ function parseBulletItem(raw) {
|
|
|
8725
8759
|
function BlockView({ block, citations }) {
|
|
8726
8760
|
switch (block.kind) {
|
|
8727
8761
|
case "heading":
|
|
8728
|
-
return /* @__PURE__ */
|
|
8762
|
+
return /* @__PURE__ */ React9.createElement(HeadingView, { level: block.level, text: block.text, citations });
|
|
8729
8763
|
case "paragraph":
|
|
8730
|
-
return /* @__PURE__ */
|
|
8764
|
+
return /* @__PURE__ */ React9.createElement(ParagraphView, { text: block.text, citations });
|
|
8731
8765
|
case "bullet":
|
|
8732
|
-
return /* @__PURE__ */
|
|
8766
|
+
return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column" }, block.items.map((item, i) => /* @__PURE__ */ React9.createElement(Box8, { key: `${i}-${item.text.slice(0, 24)}` }, /* @__PURE__ */ React9.createElement(Text7, { color: item.task === "done" ? "green" : "cyan" }, bulletPrefix(block, i, item)), item.task === "done" ? /* @__PURE__ */ React9.createElement(Text7, { strikethrough: true, dimColor: true }, /* @__PURE__ */ React9.createElement(InlineMd, { text: item.text, citations })) : /* @__PURE__ */ React9.createElement(InlineMd, { text: item.text, citations }))));
|
|
8733
8767
|
case "quote":
|
|
8734
|
-
return /* @__PURE__ */
|
|
8768
|
+
return /* @__PURE__ */ React9.createElement(BlockquoteView, { block, citations });
|
|
8735
8769
|
case "code":
|
|
8736
8770
|
if (DIAGRAM_LANGS.has(block.lang.toLowerCase())) {
|
|
8737
|
-
return /* @__PURE__ */
|
|
8771
|
+
return /* @__PURE__ */ React9.createElement(DiagramCodeBlock, { lang: block.lang, text: block.text });
|
|
8738
8772
|
}
|
|
8739
|
-
return /* @__PURE__ */
|
|
8773
|
+
return /* @__PURE__ */ React9.createElement(CodeBlockView, { lang: block.lang, text: block.text });
|
|
8740
8774
|
case "edit-block":
|
|
8741
|
-
return /* @__PURE__ */
|
|
8775
|
+
return /* @__PURE__ */ React9.createElement(EditBlockRow, { block });
|
|
8742
8776
|
case "table":
|
|
8743
|
-
return /* @__PURE__ */
|
|
8777
|
+
return /* @__PURE__ */ React9.createElement(TableBlockRow, { block, citations });
|
|
8744
8778
|
case "hr":
|
|
8745
|
-
return /* @__PURE__ */
|
|
8779
|
+
return /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
8746
8780
|
}
|
|
8747
8781
|
}
|
|
8748
8782
|
function ParagraphView({ text, citations }) {
|
|
8749
8783
|
if (!text.includes("\n")) {
|
|
8750
|
-
return /* @__PURE__ */
|
|
8784
|
+
return /* @__PURE__ */ React9.createElement(InlineMd, { text, citations });
|
|
8751
8785
|
}
|
|
8752
8786
|
const rows = text.split("\n");
|
|
8753
|
-
return /* @__PURE__ */
|
|
8787
|
+
return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column" }, rows.map((row2, i) => (
|
|
8754
8788
|
// biome-ignore lint/suspicious/noArrayIndexKey: hard-break rows are source-ordered and never reorder
|
|
8755
|
-
/* @__PURE__ */
|
|
8789
|
+
/* @__PURE__ */ React9.createElement(InlineMd, { key: `ln-${i}`, text: row2, citations })
|
|
8756
8790
|
)));
|
|
8757
8791
|
}
|
|
8758
8792
|
function bulletPrefix(block, i, item) {
|
|
@@ -8765,12 +8799,11 @@ function BlockquoteView({
|
|
|
8765
8799
|
block,
|
|
8766
8800
|
citations
|
|
8767
8801
|
}) {
|
|
8768
|
-
return /* @__PURE__ */
|
|
8769
|
-
|
|
8802
|
+
return /* @__PURE__ */ React9.createElement(
|
|
8803
|
+
Box8,
|
|
8770
8804
|
{
|
|
8771
8805
|
borderStyle: "single",
|
|
8772
|
-
borderColor: "
|
|
8773
|
-
borderDimColor: true,
|
|
8806
|
+
borderColor: "#c4b5fd",
|
|
8774
8807
|
borderTop: false,
|
|
8775
8808
|
borderRight: false,
|
|
8776
8809
|
borderBottom: false,
|
|
@@ -8778,7 +8811,7 @@ function BlockquoteView({
|
|
|
8778
8811
|
flexDirection: "column",
|
|
8779
8812
|
gap: 1
|
|
8780
8813
|
},
|
|
8781
|
-
block.children.map((child, i) => /* @__PURE__ */
|
|
8814
|
+
block.children.map((child, i) => /* @__PURE__ */ React9.createElement(BlockView, { key: `q-${i}-${child.kind}`, block: child, citations }))
|
|
8782
8815
|
);
|
|
8783
8816
|
}
|
|
8784
8817
|
function splitTableRow(line) {
|
|
@@ -8796,14 +8829,14 @@ function TableBlockRow({ block, citations }) {
|
|
|
8796
8829
|
widths.push(Math.min(40, Math.max(3, ...cellLengths)));
|
|
8797
8830
|
}
|
|
8798
8831
|
const separator = widths.map((w) => "\u2500".repeat(w)).join("\u2500\u253C\u2500");
|
|
8799
|
-
return /* @__PURE__ */
|
|
8832
|
+
return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Box8, null, block.header.map((cell, ci) => (
|
|
8800
8833
|
// biome-ignore lint/suspicious/noArrayIndexKey: table columns never reorder — derived from a static header array
|
|
8801
|
-
/* @__PURE__ */
|
|
8802
|
-
))), /* @__PURE__ */
|
|
8834
|
+
/* @__PURE__ */ React9.createElement(Text7, { key: `h-${ci}`, bold: true, color: "cyan" }, /* @__PURE__ */ React9.createElement(InlineMd, { text: cell, padTo: widths[ci] ?? 3, citations }), ci < colCount - 1 ? " \u2502 " : "")
|
|
8835
|
+
))), /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, separator), block.rows.map((row2, ri) => (
|
|
8803
8836
|
// biome-ignore lint/suspicious/noArrayIndexKey: table rows render in source order and don't reorder
|
|
8804
|
-
/* @__PURE__ */
|
|
8837
|
+
/* @__PURE__ */ React9.createElement(Box8, { key: `r-${ri}` }, Array.from({ length: colCount }).map((_, ci) => (
|
|
8805
8838
|
// biome-ignore lint/suspicious/noArrayIndexKey: same — column axis is fixed by the table shape
|
|
8806
|
-
/* @__PURE__ */
|
|
8839
|
+
/* @__PURE__ */ React9.createElement(Text7, { key: `c-${ri}-${ci}` }, /* @__PURE__ */ React9.createElement(InlineMd, { text: row2[ci] ?? "", padTo: widths[ci] ?? 3, citations }), ci < colCount - 1 ? " \u2502 " : "")
|
|
8807
8840
|
)))
|
|
8808
8841
|
)));
|
|
8809
8842
|
}
|
|
@@ -8823,7 +8856,7 @@ function EditBlockRow({ block }) {
|
|
|
8823
8856
|
const isNewFile = block.search.length === 0;
|
|
8824
8857
|
const searchLines = block.search.split("\n");
|
|
8825
8858
|
const replaceLines = block.replace.split("\n");
|
|
8826
|
-
return /* @__PURE__ */
|
|
8859
|
+
return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React9.createElement(Box8, null, /* @__PURE__ */ React9.createElement(Text7, { bold: true, color: "cyan" }, block.filename), isNewFile ? /* @__PURE__ */ React9.createElement(Text7, { color: "green", bold: true }, " (new file)") : null), isNewFile ? null : /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", marginTop: 1 }, searchLines.map((line, i) => /* @__PURE__ */ React9.createElement(Text7, { key: `s-${i}-${line.length}`, color: "red" }, `- ${line}`))), /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", marginTop: isNewFile ? 1 : 0 }, replaceLines.map((line, i) => /* @__PURE__ */ React9.createElement(Text7, { key: `r-${i}-${line.length}`, color: "green" }, `+ ${line}`))));
|
|
8827
8860
|
}
|
|
8828
8861
|
var DIAGRAM_LANGS = /* @__PURE__ */ new Set([
|
|
8829
8862
|
"mermaid",
|
|
@@ -8843,30 +8876,124 @@ var DIAGRAM_VIEWER_HINT = {
|
|
|
8843
8876
|
dot: "\u2192 paste at https://dreampuf.github.io/GraphvizOnline to view",
|
|
8844
8877
|
graphviz: "\u2192 paste at https://dreampuf.github.io/GraphvizOnline to view"
|
|
8845
8878
|
};
|
|
8879
|
+
function HeadingView({
|
|
8880
|
+
level,
|
|
8881
|
+
text,
|
|
8882
|
+
citations
|
|
8883
|
+
}) {
|
|
8884
|
+
if (level === 1) {
|
|
8885
|
+
return /* @__PURE__ */ React9.createElement(Box8, { marginY: 1 }, /* @__PURE__ */ React9.createElement(Text7, { backgroundColor: "#67e8f9", color: "black", bold: true }, ` ${text} `));
|
|
8886
|
+
}
|
|
8887
|
+
if (level === 2) {
|
|
8888
|
+
return /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text7, { backgroundColor: "#c4b5fd", color: "black", bold: true }, ` ${text} `));
|
|
8889
|
+
}
|
|
8890
|
+
if (level === 3) {
|
|
8891
|
+
return /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text7, { backgroundColor: "#f0abfc", color: "black", bold: true }, ` ${text} `));
|
|
8892
|
+
}
|
|
8893
|
+
return /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text7, { bold: true, color: "#f0abfc" }, "\u25B8", " "), /* @__PURE__ */ React9.createElement(Text7, { bold: true }, /* @__PURE__ */ React9.createElement(InlineMd, { text, citations })));
|
|
8894
|
+
}
|
|
8895
|
+
function CodeBlockView({ lang, text }) {
|
|
8896
|
+
const langLabel = lang.trim();
|
|
8897
|
+
return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "#7dd3fc", paddingX: 1 }, langLabel ? /* @__PURE__ */ React9.createElement(Box8, null, /* @__PURE__ */ React9.createElement(Text7, { backgroundColor: "#7dd3fc", color: "black", bold: true }, ` ${langLabel} `)) : null, /* @__PURE__ */ React9.createElement(Text7, { color: "#fde68a" }, text));
|
|
8898
|
+
}
|
|
8846
8899
|
function DiagramCodeBlock({ lang, text }) {
|
|
8847
8900
|
const hint = DIAGRAM_VIEWER_HINT[lang.toLowerCase()] ?? "\u2192 render with the matching viewer to view";
|
|
8848
|
-
return /* @__PURE__ */
|
|
8901
|
+
return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", borderStyle: "double", borderColor: "magenta", paddingX: 1 }, /* @__PURE__ */ React9.createElement(Text7, { bold: true, color: "magenta" }, `\u25C7 ${lang} diagram (source \u2014 terminal can't draw the graph)`), /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text7, { color: "yellow" }, text)), /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, hint)));
|
|
8849
8902
|
}
|
|
8850
8903
|
function Markdown({ text, projectRoot }) {
|
|
8851
8904
|
const cleaned = expandAutolinks(expandEmoji(stripMath(text)));
|
|
8852
8905
|
const root = projectRoot ?? process.cwd();
|
|
8853
|
-
const citations =
|
|
8854
|
-
const blocks =
|
|
8906
|
+
const citations = React9.useMemo(() => collectCitations(cleaned, root), [cleaned, root]);
|
|
8907
|
+
const blocks = React9.useMemo(() => parseBlocks(cleaned), [cleaned]);
|
|
8855
8908
|
const broken = [];
|
|
8856
8909
|
for (const [url, status2] of citations) {
|
|
8857
8910
|
if (!status2.ok) broken.push({ url, reason: status2.reason });
|
|
8858
8911
|
}
|
|
8859
|
-
return /* @__PURE__ */
|
|
8912
|
+
return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", gap: 1 }, blocks.map((b, i) => /* @__PURE__ */ React9.createElement(BlockView, { key: `${i}-${b.kind}`, block: b, citations })), broken.length > 0 ? /* @__PURE__ */ React9.createElement(BrokenCitationsBlock, { items: broken }) : null);
|
|
8860
8913
|
}
|
|
8861
8914
|
function BrokenCitationsBlock({ items }) {
|
|
8862
|
-
return /* @__PURE__ */
|
|
8915
|
+
return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 1 }, /* @__PURE__ */ React9.createElement(Text7, { color: "red", bold: true }, `\u26A0 ${items.length} broken citation${items.length > 1 ? "s" : ""} \u2014 the model referenced paths or lines that don't exist`), items.map((b, i) => (
|
|
8863
8916
|
// biome-ignore lint/suspicious/noArrayIndexKey: list is derived from a Map iteration order, stable per render
|
|
8864
|
-
/* @__PURE__ */
|
|
8917
|
+
/* @__PURE__ */ React9.createElement(Text7, { key: `bc-${i}`, color: "red" }, ` \u2717 ${b.url} \u2192 ${b.reason}`)
|
|
8865
8918
|
)));
|
|
8866
8919
|
}
|
|
8867
8920
|
|
|
8921
|
+
// src/cli/ui/theme.ts
|
|
8922
|
+
var GRADIENT = [
|
|
8923
|
+
"#5eead4",
|
|
8924
|
+
// teal
|
|
8925
|
+
"#67e8f9",
|
|
8926
|
+
// cyan
|
|
8927
|
+
"#7dd3fc",
|
|
8928
|
+
// sky
|
|
8929
|
+
"#93c5fd",
|
|
8930
|
+
// blue
|
|
8931
|
+
"#a5b4fc",
|
|
8932
|
+
// indigo
|
|
8933
|
+
"#c4b5fd",
|
|
8934
|
+
// violet
|
|
8935
|
+
"#d8b4fe",
|
|
8936
|
+
// purple
|
|
8937
|
+
"#f0abfc"
|
|
8938
|
+
// fuchsia
|
|
8939
|
+
];
|
|
8940
|
+
var COLOR = {
|
|
8941
|
+
primary: "#67e8f9",
|
|
8942
|
+
// cyan-300
|
|
8943
|
+
accent: "#c4b5fd",
|
|
8944
|
+
// violet-300
|
|
8945
|
+
brand: "#5eead4",
|
|
8946
|
+
// teal-300
|
|
8947
|
+
user: "#67e8f9",
|
|
8948
|
+
// user message glyph + bar
|
|
8949
|
+
assistant: "#86efac",
|
|
8950
|
+
// green-300, assistant glyph + bar
|
|
8951
|
+
tool: "#fcd34d",
|
|
8952
|
+
// amber-300, tool ok pill bg
|
|
8953
|
+
toolErr: "#fda4af",
|
|
8954
|
+
// rose-300, tool err pill bg
|
|
8955
|
+
info: "#94a3b8",
|
|
8956
|
+
// slate-400, info / dim
|
|
8957
|
+
warn: "#fbbf24",
|
|
8958
|
+
// amber-400
|
|
8959
|
+
err: "#f87171",
|
|
8960
|
+
// red-400
|
|
8961
|
+
ok: "#4ade80"
|
|
8962
|
+
// green-400
|
|
8963
|
+
};
|
|
8964
|
+
var GLYPH = {
|
|
8965
|
+
brand: "\u25C8",
|
|
8966
|
+
user: "\u25C7",
|
|
8967
|
+
assistant: "\u25C6",
|
|
8968
|
+
toolOk: "\u25A3",
|
|
8969
|
+
toolErr: "\u25A5",
|
|
8970
|
+
warn: "\u25B2",
|
|
8971
|
+
err: "\u2726",
|
|
8972
|
+
arrow: "\u203A",
|
|
8973
|
+
bullet: "\xB7",
|
|
8974
|
+
bar: "\u258E",
|
|
8975
|
+
thinBar: "\u258F",
|
|
8976
|
+
block: "\u2588",
|
|
8977
|
+
shade1: "\u2591",
|
|
8978
|
+
shade2: "\u2592",
|
|
8979
|
+
shade3: "\u2593"
|
|
8980
|
+
};
|
|
8981
|
+
function gradientCells(width, glyph = GLYPH.block) {
|
|
8982
|
+
const cells = [];
|
|
8983
|
+
if (width <= 0) return cells;
|
|
8984
|
+
const last = GRADIENT.length - 1;
|
|
8985
|
+
for (let i = 0; i < width; i++) {
|
|
8986
|
+
const t = width === 1 ? 0 : i * last / (width - 1);
|
|
8987
|
+
const lo = Math.floor(t);
|
|
8988
|
+
const hi = Math.min(last, lo + 1);
|
|
8989
|
+
const color = t - lo < 0.5 ? GRADIENT[lo] : GRADIENT[hi];
|
|
8990
|
+
cells.push({ ch: glyph, color });
|
|
8991
|
+
}
|
|
8992
|
+
return cells;
|
|
8993
|
+
}
|
|
8994
|
+
|
|
8868
8995
|
// src/cli/ui/ticker.tsx
|
|
8869
|
-
import
|
|
8996
|
+
import React10, { createContext as createContext2, useContext as useContext2, useEffect as useEffect2, useState as useState3 } from "react";
|
|
8870
8997
|
var TICK_MS = 120;
|
|
8871
8998
|
var TickContext = createContext2(0);
|
|
8872
8999
|
function TickerProvider({ children, disabled }) {
|
|
@@ -8876,7 +9003,7 @@ function TickerProvider({ children, disabled }) {
|
|
|
8876
9003
|
const id = setInterval(() => setTick((t) => t + 1), TICK_MS);
|
|
8877
9004
|
return () => clearInterval(id);
|
|
8878
9005
|
}, [disabled]);
|
|
8879
|
-
return /* @__PURE__ */
|
|
9006
|
+
return /* @__PURE__ */ React10.createElement(TickContext.Provider, { value: tick }, children);
|
|
8880
9007
|
}
|
|
8881
9008
|
function useTick() {
|
|
8882
9009
|
return useContext2(TickContext);
|
|
@@ -9029,51 +9156,105 @@ function RoleGlyph({
|
|
|
9029
9156
|
glyph,
|
|
9030
9157
|
color
|
|
9031
9158
|
}) {
|
|
9032
|
-
return /* @__PURE__ */
|
|
9159
|
+
return /* @__PURE__ */ React11.createElement(Text8, { color, bold: true }, glyph);
|
|
9160
|
+
}
|
|
9161
|
+
function ToolPill({ label, status: status2 }) {
|
|
9162
|
+
const bg = status2 === "err" ? "red" : "yellow";
|
|
9163
|
+
const symbol = status2 === "err" ? "\u2717" : "\u2713";
|
|
9164
|
+
return /* @__PURE__ */ React11.createElement(Text8, { backgroundColor: bg, color: "black", bold: true }, ` ${symbol} ${label} `);
|
|
9033
9165
|
}
|
|
9034
9166
|
function indentContinuationLines(text) {
|
|
9035
9167
|
if (!text.includes("\n")) return text;
|
|
9036
9168
|
return text.split("\n").join("\n ");
|
|
9037
9169
|
}
|
|
9038
|
-
var EventRow =
|
|
9170
|
+
var EventRow = React11.memo(function EventRow2({
|
|
9039
9171
|
event,
|
|
9040
9172
|
projectRoot
|
|
9041
9173
|
}) {
|
|
9042
9174
|
if (event.role === "user") {
|
|
9043
|
-
return /* @__PURE__ */
|
|
9175
|
+
return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column" }, event.leadSeparator ? /* @__PURE__ */ React11.createElement(TurnSeparator, null) : null, /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(RoleGlyph, { glyph: ROLE_GLYPH.user, color: "cyan" }), /* @__PURE__ */ React11.createElement(Text8, null, " "), /* @__PURE__ */ React11.createElement(
|
|
9176
|
+
Box9,
|
|
9177
|
+
{
|
|
9178
|
+
flexDirection: "column",
|
|
9179
|
+
borderStyle: "single",
|
|
9180
|
+
borderTop: false,
|
|
9181
|
+
borderRight: false,
|
|
9182
|
+
borderBottom: false,
|
|
9183
|
+
borderColor: COLOR.user,
|
|
9184
|
+
paddingLeft: 1
|
|
9185
|
+
},
|
|
9186
|
+
/* @__PURE__ */ React11.createElement(Text8, null, indentContinuationLines(event.text))
|
|
9187
|
+
)));
|
|
9044
9188
|
}
|
|
9045
9189
|
if (event.role === "assistant") {
|
|
9046
|
-
if (event.streaming) return /* @__PURE__ */
|
|
9047
|
-
return /* @__PURE__ */
|
|
9190
|
+
if (event.streaming) return /* @__PURE__ */ React11.createElement(StreamingAssistant, { event });
|
|
9191
|
+
return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(RoleGlyph, { glyph: ROLE_GLYPH.assistant, color: "green" }), event.stats ? /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(Text8, null, " "), /* @__PURE__ */ React11.createElement(Text8, { backgroundColor: COLOR.assistant, color: "black", bold: true }, ` ${event.stats.model.replace(/^deepseek-/, "")} `)) : null), /* @__PURE__ */ React11.createElement(
|
|
9192
|
+
Box9,
|
|
9193
|
+
{
|
|
9194
|
+
flexDirection: "column",
|
|
9195
|
+
marginTop: 1,
|
|
9196
|
+
borderStyle: "single",
|
|
9197
|
+
borderTop: false,
|
|
9198
|
+
borderRight: false,
|
|
9199
|
+
borderBottom: false,
|
|
9200
|
+
borderColor: COLOR.assistant,
|
|
9201
|
+
paddingLeft: 1
|
|
9202
|
+
},
|
|
9203
|
+
event.branch ? /* @__PURE__ */ React11.createElement(BranchBlock, { branch: event.branch }) : null,
|
|
9204
|
+
event.reasoning ? /* @__PURE__ */ React11.createElement(ReasoningBlock, { reasoning: event.reasoning }) : null,
|
|
9205
|
+
!isPlanStateEmpty(event.planState) ? /* @__PURE__ */ React11.createElement(PlanStateBlock, { planState: event.planState }) : null,
|
|
9206
|
+
event.text ? /* @__PURE__ */ React11.createElement(Markdown, { text: event.text, projectRoot }) : /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, "(no content)"),
|
|
9207
|
+
event.stats ? /* @__PURE__ */ React11.createElement(StatsLine, { stats: event.stats }) : null,
|
|
9208
|
+
event.repair ? /* @__PURE__ */ React11.createElement(Text8, { color: COLOR.accent }, event.repair) : null
|
|
9209
|
+
));
|
|
9048
9210
|
}
|
|
9049
9211
|
if (event.role === "tool") {
|
|
9050
9212
|
const isExplicitError = event.text.startsWith("ERROR:");
|
|
9051
9213
|
const isEditFile = (event.toolName === "edit_file" || event.toolName?.endsWith("_edit_file")) && !isExplicitError;
|
|
9052
9214
|
if (isEditFile) {
|
|
9053
|
-
return /* @__PURE__ */
|
|
9215
|
+
return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(ToolPill, { label: event.toolName ?? "?", status: "ok" }), /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, " diff:")), /* @__PURE__ */ React11.createElement(
|
|
9216
|
+
Box9,
|
|
9217
|
+
{
|
|
9218
|
+
flexDirection: "column",
|
|
9219
|
+
marginTop: 1,
|
|
9220
|
+
borderStyle: "single",
|
|
9221
|
+
borderTop: false,
|
|
9222
|
+
borderRight: false,
|
|
9223
|
+
borderBottom: false,
|
|
9224
|
+
borderColor: COLOR.tool,
|
|
9225
|
+
paddingLeft: 1
|
|
9226
|
+
},
|
|
9227
|
+
/* @__PURE__ */ React11.createElement(EditFileDiff, { text: event.text })
|
|
9228
|
+
));
|
|
9054
9229
|
}
|
|
9055
9230
|
const summary = summarizeToolResult(event.toolName ?? "?", event.text);
|
|
9056
|
-
const
|
|
9057
|
-
const
|
|
9058
|
-
const marker = summary.isError ? "\u2717" : "\u2192";
|
|
9059
|
-
const durationLabel = event.durationMs !== void 0 && event.durationMs >= 100 ? ` (${formatDuration(event.durationMs)})` : "";
|
|
9231
|
+
const status2 = summary.isError ? "err" : "ok";
|
|
9232
|
+
const durationLabel = event.durationMs !== void 0 && event.durationMs >= 100 ? formatDuration(event.durationMs) : "";
|
|
9060
9233
|
const indexHint = event.toolIndex !== void 0 ? ` /tool ${event.toolIndex}` : "";
|
|
9061
|
-
return /* @__PURE__ */
|
|
9234
|
+
return /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(ToolPill, { label: event.toolName ?? "?", status: status2 }), durationLabel ? /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, ` ${durationLabel}`) : null, /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, " "), /* @__PURE__ */ React11.createElement(Text8, { color: status2 === "err" ? "red" : void 0, dimColor: status2 === "ok" }, summary.summary), indexHint ? /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, indexHint) : null);
|
|
9062
9235
|
}
|
|
9063
9236
|
if (event.role === "error") {
|
|
9064
|
-
return /* @__PURE__ */
|
|
9237
|
+
return /* @__PURE__ */ React11.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text8, { backgroundColor: "#f87171", color: "black", bold: true }, " \u2726 ERROR "), /* @__PURE__ */ React11.createElement(Text8, null, " "), /* @__PURE__ */ React11.createElement(Text8, { color: "#f87171" }, indentContinuationLines(event.text)));
|
|
9065
9238
|
}
|
|
9066
9239
|
if (event.role === "info") {
|
|
9067
|
-
|
|
9240
|
+
const m = event.text.match(/^([▸▶▲⚠✓✗✖↻ⓘ])\s*(.*)$/s);
|
|
9241
|
+
const lead = m?.[1] ?? "\u25B8";
|
|
9242
|
+
const body = m?.[2] ?? event.text;
|
|
9243
|
+
let leadColor = COLOR.info;
|
|
9244
|
+
if (lead === "\u25B2" || lead === "\u26A0") leadColor = COLOR.warn;
|
|
9245
|
+
else if (lead === "\u2713") leadColor = COLOR.ok;
|
|
9246
|
+
else if (lead === "\u2717" || lead === "\u2716") leadColor = COLOR.err;
|
|
9247
|
+
else if (lead === "\u21BB") leadColor = COLOR.primary;
|
|
9248
|
+
return /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(Text8, { color: leadColor, bold: true }, lead), /* @__PURE__ */ React11.createElement(Text8, null, " "), /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, body));
|
|
9068
9249
|
}
|
|
9069
9250
|
if (event.role === "plan") {
|
|
9070
|
-
return /* @__PURE__ */
|
|
9251
|
+
return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(Text8, { bold: true, color: "cyan" }, "\u{1F4CB} plan proposed \u2014 pick a choice below")), /* @__PURE__ */ React11.createElement(Box9, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Markdown, { text: event.text, projectRoot })));
|
|
9071
9252
|
}
|
|
9072
9253
|
if (event.role === "step-progress") {
|
|
9073
9254
|
const sp = event.stepProgress;
|
|
9074
|
-
const counter = sp && sp.total > 0 ?
|
|
9255
|
+
const counter = sp && sp.total > 0 ? `${sp.completed}/${sp.total}` : "";
|
|
9075
9256
|
const label = sp?.title ? `${sp.stepId} \xB7 ${sp.title}` : sp?.stepId ?? "";
|
|
9076
|
-
return /* @__PURE__ */
|
|
9257
|
+
return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(Text8, { backgroundColor: "#4ade80", color: "black", bold: true }, " \u2713 STEP "), counter ? /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(Text8, null, " "), /* @__PURE__ */ React11.createElement(Text8, { color: "#4ade80", bold: true }, counter)) : null, /* @__PURE__ */ React11.createElement(Text8, null, " "), /* @__PURE__ */ React11.createElement(Text8, { color: "#86efac" }, label)), event.text ? /* @__PURE__ */ React11.createElement(Box9, { paddingLeft: 2 }, /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, event.text)) : null, sp?.notes ? /* @__PURE__ */ React11.createElement(Box9, { paddingLeft: 2 }, /* @__PURE__ */ React11.createElement(Text8, { color: "#fbbf24", dimColor: true }, `note: ${sp.notes}`)) : null);
|
|
9077
9258
|
}
|
|
9078
9259
|
if (event.role === "plan-resumed") {
|
|
9079
9260
|
const rp = event.resumedPlan;
|
|
@@ -9088,7 +9269,7 @@ var EventRow = React10.memo(function EventRow2({
|
|
|
9088
9269
|
])
|
|
9089
9270
|
);
|
|
9090
9271
|
const nextStep = rp.steps.find((s) => !completedSet.has(s.id));
|
|
9091
|
-
return /* @__PURE__ */
|
|
9272
|
+
return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(Text8, { backgroundColor: "#67e8f9", color: "black", bold: true }, " \u21BB RESUMED PLAN "), /* @__PURE__ */ React11.createElement(Text8, null, " "), /* @__PURE__ */ React11.createElement(Text8, { color: "#67e8f9", bold: true }, `${done}/${total}`), /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, ` done \xB7 last touched ${rp.relativeTime}`)), rp.summary ? /* @__PURE__ */ React11.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text8, { color: "#67e8f9" }, rp.summary)) : null, /* @__PURE__ */ React11.createElement(Box9, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React11.createElement(PlanStepList, { steps: rp.steps, statuses, focusStepId: nextStep?.id })));
|
|
9092
9273
|
}
|
|
9093
9274
|
if (event.role === "plan-replay") {
|
|
9094
9275
|
const r = event.replayPlan;
|
|
@@ -9099,76 +9280,79 @@ var EventRow = React10.memo(function EventRow2({
|
|
|
9099
9280
|
const statuses = new Map(
|
|
9100
9281
|
r.steps.map((s) => [s.id, completedSet.has(s.id) ? "done" : "pending"])
|
|
9101
9282
|
);
|
|
9102
|
-
const navHint = r.total > 1 ? `
|
|
9103
|
-
return /* @__PURE__ */
|
|
9104
|
-
Text8,
|
|
9105
|
-
{
|
|
9106
|
-
dimColor: true
|
|
9107
|
-
},
|
|
9108
|
-
` completed ${r.relativeTime} \xB7 ${done}/${total} done${navHint}`
|
|
9109
|
-
)), r.summary ? /* @__PURE__ */ React10.createElement(Box8, null, /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, ` ${r.summary}`)) : null, /* @__PURE__ */ React10.createElement(Box8, null, /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, ` ${r.archiveBasename}`))), r.body ? /* @__PURE__ */ React10.createElement(Box8, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Markdown, { text: r.body, projectRoot })) : null, /* @__PURE__ */ React10.createElement(Box8, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(PlanStepList, { steps: r.steps, statuses })), /* @__PURE__ */ React10.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, r.total > 1 ? `(read-only \xB7 /replay ${r.index === 1 ? 2 : 1} for the ${r.index === 1 ? "next" : "newest"} archive)` : "(read-only \xB7 this is an archived plan)")));
|
|
9283
|
+
const navHint = r.total > 1 ? ` \xB7 ${r.index}/${r.total}` : "";
|
|
9284
|
+
return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(Text8, { backgroundColor: "#94a3b8", color: "black", bold: true }, " \u23EA REPLAY "), /* @__PURE__ */ React11.createElement(Text8, null, " "), /* @__PURE__ */ React11.createElement(Text8, { color: "#94a3b8", bold: true }, `${done}/${total}`), /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, ` done \xB7 ${r.relativeTime}${navHint}`)), r.summary ? /* @__PURE__ */ React11.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text8, { color: "#94a3b8" }, r.summary)) : null, /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, r.archiveBasename)), r.body ? /* @__PURE__ */ React11.createElement(Box9, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Markdown, { text: r.body, projectRoot })) : null, /* @__PURE__ */ React11.createElement(Box9, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React11.createElement(PlanStepList, { steps: r.steps, statuses })), /* @__PURE__ */ React11.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, r.total > 1 ? `(read-only \xB7 /replay ${r.index === 1 ? 2 : 1} for the ${r.index === 1 ? "next" : "newest"} archive)` : "(read-only \xB7 this is an archived plan)")));
|
|
9110
9285
|
}
|
|
9111
9286
|
if (event.role === "warning") {
|
|
9112
|
-
return /* @__PURE__ */
|
|
9287
|
+
return /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(Text8, { backgroundColor: "#fbbf24", color: "black", bold: true }, " \u25B2 WARN "), /* @__PURE__ */ React11.createElement(Text8, null, " "), /* @__PURE__ */ React11.createElement(Text8, { color: "#fbbf24" }, indentContinuationLines(event.text)));
|
|
9113
9288
|
}
|
|
9114
|
-
return /* @__PURE__ */
|
|
9289
|
+
return /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(Text8, null, event.text));
|
|
9115
9290
|
});
|
|
9116
9291
|
function TurnSeparator() {
|
|
9117
|
-
const { stdout: stdout2 } =
|
|
9292
|
+
const { stdout: stdout2 } = useStdout3();
|
|
9118
9293
|
const cols = stdout2?.columns ?? 80;
|
|
9119
9294
|
const width = Math.max(16, cols - 2);
|
|
9120
|
-
const
|
|
9121
|
-
const
|
|
9122
|
-
const
|
|
9123
|
-
return /* @__PURE__ */
|
|
9295
|
+
const sideWidth = Math.max(2, Math.floor((width - 5) / 2));
|
|
9296
|
+
const leftCells = gradientCells(sideWidth, "\u2500");
|
|
9297
|
+
const rightCells = gradientCells(sideWidth, "\u2500");
|
|
9298
|
+
return /* @__PURE__ */ React11.createElement(Box9, { marginTop: 1, marginBottom: 1 }, leftCells.map((c, i) => (
|
|
9299
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: fixed-width gradient row
|
|
9300
|
+
/* @__PURE__ */ React11.createElement(Text8, { key: `tsep-l-${i}`, color: c.color }, c.ch)
|
|
9301
|
+
)), /* @__PURE__ */ React11.createElement(Text8, { color: COLOR.brand, bold: true }, " \u25C6 "), rightCells.map((c, i) => (
|
|
9302
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: fixed-width gradient row
|
|
9303
|
+
/* @__PURE__ */ React11.createElement(Text8, { key: `tsep-r-${i}`, color: c.color }, c.ch)
|
|
9304
|
+
)));
|
|
9124
9305
|
}
|
|
9125
9306
|
function EditFileDiff({ text }) {
|
|
9126
9307
|
const lines = text.split(/\r?\n/);
|
|
9127
9308
|
const [statusHeader, hunkHeader, ...body] = lines;
|
|
9128
|
-
return /* @__PURE__ */
|
|
9309
|
+
return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, ` ${statusHeader ?? ""}`), hunkHeader !== void 0 ? /* @__PURE__ */ React11.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text8, { backgroundColor: "#c4b5fd", color: "black", bold: true }, ` ${hunkHeader.trim()} `)) : null, body.map((line, i) => {
|
|
9129
9310
|
const key = `${i}-${line.slice(0, 32)}`;
|
|
9130
|
-
|
|
9131
|
-
|
|
9311
|
+
const stripped = line.replace(/^ {2}/, "");
|
|
9312
|
+
if (stripped.startsWith("- ")) {
|
|
9313
|
+
return /* @__PURE__ */ React11.createElement(Box9, { key }, /* @__PURE__ */ React11.createElement(Text8, { color: "#f87171", bold: true }, "\u2212 "), /* @__PURE__ */ React11.createElement(Text8, { color: "#fca5a5" }, stripped.slice(2)));
|
|
9132
9314
|
}
|
|
9133
|
-
if (
|
|
9134
|
-
return /* @__PURE__ */
|
|
9315
|
+
if (stripped.startsWith("+ ")) {
|
|
9316
|
+
return /* @__PURE__ */ React11.createElement(Box9, { key }, /* @__PURE__ */ React11.createElement(Text8, { color: "#4ade80", bold: true }, "+ "), /* @__PURE__ */ React11.createElement(Text8, { color: "#86efac" }, stripped.slice(2)));
|
|
9135
9317
|
}
|
|
9136
|
-
return /* @__PURE__ */
|
|
9318
|
+
return /* @__PURE__ */ React11.createElement(Box9, { key }, /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, " "), /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, stripped));
|
|
9137
9319
|
}));
|
|
9138
9320
|
}
|
|
9139
9321
|
function BranchBlock({ branch: branch2 }) {
|
|
9140
|
-
|
|
9141
|
-
const
|
|
9322
|
+
return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(Text8, { backgroundColor: "#93c5fd", color: "black", bold: true }, ` \u2387 BRANCH \xD7${branch2.budget} `), /* @__PURE__ */ React11.createElement(Text8, null, " "), /* @__PURE__ */ React11.createElement(Text8, { color: "#93c5fd" }, "picked "), /* @__PURE__ */ React11.createElement(Text8, { color: "#93c5fd", bold: true }, "#", branch2.chosenIndex)), /* @__PURE__ */ React11.createElement(Box9, { paddingLeft: 2, marginTop: 1 }, branch2.uncertainties.map((u, i) => {
|
|
9323
|
+
const chosen = i === branch2.chosenIndex;
|
|
9142
9324
|
const t = (branch2.temperatures[i] ?? 0).toFixed(1);
|
|
9143
|
-
return
|
|
9144
|
-
|
|
9145
|
-
|
|
9325
|
+
return (
|
|
9326
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: branch index is positional and stable
|
|
9327
|
+
/* @__PURE__ */ React11.createElement(Text8, { key: `b-${i}` }, /* @__PURE__ */ React11.createElement(Text8, { color: chosen ? "#93c5fd" : "#475569", bold: chosen }, chosen ? "\u25B8 " : " "), /* @__PURE__ */ React11.createElement(Text8, { color: chosen ? "#93c5fd" : "#94a3b8", bold: chosen }, `#${i}`), /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, ` T=${t} u=${u} `))
|
|
9328
|
+
);
|
|
9329
|
+
})));
|
|
9146
9330
|
}
|
|
9147
9331
|
function ReasoningBlock({ reasoning }) {
|
|
9148
9332
|
const max = 260;
|
|
9149
9333
|
const flat = reasoning.replace(/\s+/g, " ").trim();
|
|
9150
9334
|
const preview = flat.length <= max ? flat : `\u2026 (+${flat.length - max} earlier chars) ${flat.slice(-max)}`;
|
|
9151
|
-
return /* @__PURE__ */
|
|
9335
|
+
return /* @__PURE__ */ React11.createElement(Box9, { marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text8, { backgroundColor: COLOR.accent, color: "black", bold: true }, " \u22EF thinking "), /* @__PURE__ */ React11.createElement(Text8, null, " "), /* @__PURE__ */ React11.createElement(Text8, { color: COLOR.accent, italic: true, dimColor: true }, preview));
|
|
9152
9336
|
}
|
|
9153
9337
|
function Elapsed() {
|
|
9154
9338
|
const s = useElapsedSeconds();
|
|
9155
9339
|
const mm = String(Math.floor(s / 60)).padStart(2, "0");
|
|
9156
9340
|
const ss = String(s % 60).padStart(2, "0");
|
|
9157
|
-
return /* @__PURE__ */
|
|
9341
|
+
return /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, `${mm}:${ss}`);
|
|
9158
9342
|
}
|
|
9159
9343
|
function PulsingAssistantGlyph() {
|
|
9160
9344
|
const tick = useTick();
|
|
9161
9345
|
const on = Math.floor(tick / 4) % 2 === 0;
|
|
9162
|
-
return /* @__PURE__ */
|
|
9346
|
+
return /* @__PURE__ */ React11.createElement(Text8, { color: "green", bold: true }, on ? ROLE_GLYPH.assistant : ROLE_GLYPH.assistantPulse);
|
|
9163
9347
|
}
|
|
9164
9348
|
function StreamingAssistant({ event }) {
|
|
9165
9349
|
if (event.branchProgress) {
|
|
9166
9350
|
const p = event.branchProgress;
|
|
9167
9351
|
if (p.completed === 0) {
|
|
9168
|
-
return /* @__PURE__ */
|
|
9352
|
+
return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React11.createElement(Text8, { color: "blue" }, " \u2387 launching ", p.total, " parallel samples (R1 thinking in parallel)\u2026 "), /* @__PURE__ */ React11.createElement(Elapsed, null)), /* @__PURE__ */ React11.createElement(Text8, { color: "yellow" }, " ", "spread across T=0.0/0.5/1.0 \xB7 reasoner typically takes 30-90s \u2014 this is normal"));
|
|
9169
9353
|
}
|
|
9170
9354
|
const pct2 = Math.round(p.completed / p.total * 100);
|
|
9171
|
-
return /* @__PURE__ */
|
|
9355
|
+
return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React11.createElement(Text8, { color: "blue" }, " \u2387 branching ", p.completed, "/", p.total, " (", pct2, "%) "), /* @__PURE__ */ React11.createElement(Elapsed, null)), /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, " latest #", p.latestIndex, " T=", p.latestTemperature.toFixed(1), " u=", p.latestUncertainties, p.completed < p.total ? " \xB7 waiting for other samples\u2026" : " \xB7 selecting winner\u2026"));
|
|
9172
9356
|
}
|
|
9173
9357
|
const tail = lastLine(event.text, 140);
|
|
9174
9358
|
const reasoningTail = event.reasoning ? lastLine(event.reasoning, 120) : "";
|
|
@@ -9176,38 +9360,43 @@ function StreamingAssistant({ event }) {
|
|
|
9176
9360
|
const preFirstByte = !event.text && !event.reasoning && !toolCallBuild;
|
|
9177
9361
|
const reasoningOnly = !event.text && !!event.reasoning && !toolCallBuild;
|
|
9178
9362
|
const toolCallOnly = !event.text && !event.reasoning && !!toolCallBuild;
|
|
9363
|
+
let pillBg;
|
|
9364
|
+
let pillText;
|
|
9179
9365
|
let label;
|
|
9180
|
-
let labelColor;
|
|
9181
9366
|
if (preFirstByte) {
|
|
9367
|
+
pillBg = "#fbbf24";
|
|
9368
|
+
pillText = "WAITING";
|
|
9182
9369
|
label = "request sent \xB7 waiting for server";
|
|
9183
|
-
labelColor = "yellow";
|
|
9184
9370
|
} else if (reasoningOnly) {
|
|
9185
|
-
|
|
9186
|
-
|
|
9371
|
+
pillBg = "#c4b5fd";
|
|
9372
|
+
pillText = "THINKING";
|
|
9373
|
+
label = `${event.reasoning?.length ?? 0} chars of thought`;
|
|
9187
9374
|
} else if (toolCallOnly) {
|
|
9188
|
-
|
|
9189
|
-
|
|
9375
|
+
pillBg = "#f0abfc";
|
|
9376
|
+
pillText = "DISPATCH";
|
|
9377
|
+
label = `assembling${formatToolCallIndex(toolCallBuild)} <${toolCallBuild.name}> \xB7 ${toolCallBuild.chars} chars${formatReadyTail(toolCallBuild)}`;
|
|
9190
9378
|
} else {
|
|
9191
|
-
|
|
9192
|
-
|
|
9379
|
+
pillBg = "#86efac";
|
|
9380
|
+
pillText = "WRITING";
|
|
9381
|
+
const parts = [`${event.text.length} chars`];
|
|
9382
|
+
if (event.reasoning) parts.push(`after ${event.reasoning.length} reasoning`);
|
|
9193
9383
|
if (toolCallBuild) {
|
|
9194
9384
|
parts.push(
|
|
9195
|
-
`
|
|
9385
|
+
`tool${formatToolCallIndex(toolCallBuild)} <${toolCallBuild.name}> ${toolCallBuild.chars}c${formatReadyTail(toolCallBuild)}`
|
|
9196
9386
|
);
|
|
9197
9387
|
}
|
|
9198
9388
|
label = parts.join(" \xB7 ");
|
|
9199
|
-
labelColor = "green";
|
|
9200
9389
|
}
|
|
9201
|
-
return /* @__PURE__ */
|
|
9202
|
-
// Non-dim
|
|
9390
|
+
return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React11.createElement(Text8, null, " "), /* @__PURE__ */ React11.createElement(Pulse, null), /* @__PURE__ */ React11.createElement(Text8, null, " "), /* @__PURE__ */ React11.createElement(Text8, { backgroundColor: pillBg, color: "black", bold: true }, ` ${pillText} `), /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, ` ${label} `), /* @__PURE__ */ React11.createElement(Elapsed, null)), reasoningTail ? /* @__PURE__ */ React11.createElement(Box9, { paddingLeft: 3 }, /* @__PURE__ */ React11.createElement(Text8, { color: "#c4b5fd", italic: true, dimColor: true }, "\u21B3 ", reasoningTail)) : null, tail ? /* @__PURE__ */ React11.createElement(Box9, { paddingLeft: 3 }, /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, "\u25B8 ", tail)) : preFirstByte ? (
|
|
9391
|
+
// Non-dim amber: first-time users misread the dim version as
|
|
9203
9392
|
// "app frozen". The reassurance has to be VISIBLE to do its job.
|
|
9204
|
-
/* @__PURE__ */
|
|
9205
|
-
) : reasoningOnly ? /* @__PURE__ */
|
|
9393
|
+
/* @__PURE__ */ React11.createElement(Box9, { paddingLeft: 3 }, /* @__PURE__ */ React11.createElement(Text8, { color: "#fbbf24", italic: true }, "waiting for first byte \u2014 typical 5\u201360s depending on model + load"))
|
|
9394
|
+
) : reasoningOnly ? /* @__PURE__ */ React11.createElement(Box9, { paddingLeft: 3 }, /* @__PURE__ */ React11.createElement(Text8, { color: "#c4b5fd", italic: true }, "R1 thinks before it speaks \u2014 body text arrives when reasoning finishes (20\u201390s)")) : toolCallOnly ? /* @__PURE__ */ React11.createElement(Box9, { paddingLeft: 3 }, /* @__PURE__ */ React11.createElement(Text8, { color: "#f0abfc", italic: true }, "tool-call arguments streaming \u2014 about to dispatch")) : event.reasoning ? /* @__PURE__ */ React11.createElement(Box9, { paddingLeft: 3 }, /* @__PURE__ */ React11.createElement(Text8, { color: "#fbbf24", italic: true }, "R1 still reasoning \u2014 body text or tool call arrives when thinking finishes")) : null);
|
|
9206
9395
|
}
|
|
9207
9396
|
function Pulse() {
|
|
9208
9397
|
const tick = useTick();
|
|
9209
9398
|
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
9210
|
-
return /* @__PURE__ */
|
|
9399
|
+
return /* @__PURE__ */ React11.createElement(Text8, { color: "cyan" }, frames[Math.floor(tick / 4) % frames.length]);
|
|
9211
9400
|
}
|
|
9212
9401
|
function formatToolCallIndex(tb) {
|
|
9213
9402
|
if (!tb || tb.index === void 0) return "";
|
|
@@ -9226,17 +9415,18 @@ function lastLine(s, maxChars) {
|
|
|
9226
9415
|
}
|
|
9227
9416
|
function StatsLine({ stats: stats2 }) {
|
|
9228
9417
|
const hit = (stats2.cacheHitRatio * 100).toFixed(1);
|
|
9229
|
-
|
|
9418
|
+
const hitColor = stats2.cacheHitRatio >= 0.7 ? "#4ade80" : stats2.cacheHitRatio >= 0.4 ? "#fcd34d" : "#f87171";
|
|
9419
|
+
return /* @__PURE__ */ React11.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text8, { color: hitColor, bold: true }, `\u232C ${hit}%`), /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React11.createElement(Text8, { color: "#94a3b8" }, "in ", /* @__PURE__ */ React11.createElement(Text8, { color: "#67e8f9", bold: true }, stats2.usage.promptTokens), " \u2192 out ", /* @__PURE__ */ React11.createElement(Text8, { color: "#c4b5fd", bold: true }, stats2.usage.completionTokens)), /* @__PURE__ */ React11.createElement(Text8, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React11.createElement(Text8, { color: "#86efac", bold: true }, `$${stats2.cost.toFixed(6)}`));
|
|
9230
9420
|
}
|
|
9231
9421
|
|
|
9232
9422
|
// src/cli/ui/LiveRows.tsx
|
|
9233
|
-
import { Box as
|
|
9234
|
-
import
|
|
9423
|
+
import { Box as Box10, Text as Text9, useStdout as useStdout4 } from "ink";
|
|
9424
|
+
import React12 from "react";
|
|
9235
9425
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
9236
9426
|
function StatusRow({ text }) {
|
|
9237
9427
|
const tick = useTick();
|
|
9238
9428
|
const elapsed = useElapsedSeconds();
|
|
9239
|
-
return /* @__PURE__ */
|
|
9429
|
+
return /* @__PURE__ */ React12.createElement(Box10, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React12.createElement(Text9, { color: "#c4b5fd", bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React12.createElement(Text9, null, " "), /* @__PURE__ */ React12.createElement(Text9, { color: "#c4b5fd" }, text), /* @__PURE__ */ React12.createElement(Text9, { dimColor: true }, ` \xB7 ${elapsed}s`));
|
|
9240
9430
|
}
|
|
9241
9431
|
function ModeStatusBar({
|
|
9242
9432
|
editMode,
|
|
@@ -9248,14 +9438,28 @@ function ModeStatusBar({
|
|
|
9248
9438
|
}) {
|
|
9249
9439
|
useTick();
|
|
9250
9440
|
const running = jobs2?.runningCount() ?? 0;
|
|
9251
|
-
const jobsTag = running > 0 ? /* @__PURE__ */
|
|
9441
|
+
const jobsTag = running > 0 ? /* @__PURE__ */ React12.createElement(Text9, { color: "yellow", bold: true }, ` \xB7 \u23F5 ${running} job${running === 1 ? "" : "s"}`) : null;
|
|
9252
9442
|
if (planMode) {
|
|
9253
|
-
return /* @__PURE__ */
|
|
9443
|
+
return /* @__PURE__ */ React12.createElement(ModeBarFrame, null, /* @__PURE__ */ React12.createElement(ModePill, { label: "PLAN MODE", bg: "red", flash }), /* @__PURE__ */ React12.createElement(Text9, { dimColor: true }, " writes gated \xB7 /plan off to leave"), jobsTag);
|
|
9254
9444
|
}
|
|
9255
|
-
const
|
|
9256
|
-
const
|
|
9257
|
-
const
|
|
9258
|
-
|
|
9445
|
+
const isAuto = editMode === "auto";
|
|
9446
|
+
const label = isAuto ? "AUTO" : "REVIEW";
|
|
9447
|
+
const bg = isAuto ? "magenta" : "cyan";
|
|
9448
|
+
const mid = isAuto ? "edits land now \xB7 u to undo" : pendingCount > 0 ? `${pendingCount} queued \xB7 y apply \xB7 n discard` : "edits queued \xB7 y apply \xB7 n discard";
|
|
9449
|
+
return /* @__PURE__ */ React12.createElement(ModeBarFrame, null, /* @__PURE__ */ React12.createElement(ModePill, { label, bg, flash }), /* @__PURE__ */ React12.createElement(Text9, { dimColor: true }, ` ${mid} \xB7 Shift+Tab to flip`), jobsTag);
|
|
9450
|
+
}
|
|
9451
|
+
function ModeBarFrame({ children }) {
|
|
9452
|
+
const { stdout: stdout2 } = useStdout4();
|
|
9453
|
+
const cols = stdout2?.columns ?? 80;
|
|
9454
|
+
const ruleWidth = Math.max(20, cols - 2);
|
|
9455
|
+
return /* @__PURE__ */ React12.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React12.createElement(Box10, { paddingX: 1 }, /* @__PURE__ */ React12.createElement(Text9, { color: "#475569", dimColor: true }, "\u254C".repeat(ruleWidth))), /* @__PURE__ */ React12.createElement(Box10, { paddingX: 1 }, children));
|
|
9456
|
+
}
|
|
9457
|
+
function ModePill({
|
|
9458
|
+
label,
|
|
9459
|
+
bg,
|
|
9460
|
+
flash
|
|
9461
|
+
}) {
|
|
9462
|
+
return /* @__PURE__ */ React12.createElement(Text9, { backgroundColor: bg, color: "white", bold: true, inverse: flash }, ` ${label} `);
|
|
9259
9463
|
}
|
|
9260
9464
|
function UndoBanner({
|
|
9261
9465
|
banner
|
|
@@ -9265,14 +9469,15 @@ function UndoBanner({
|
|
|
9265
9469
|
const remainingSec = Math.ceil(remainingMs / 1e3);
|
|
9266
9470
|
const ok = banner.results.filter((r) => r.status === "applied" || r.status === "created").length;
|
|
9267
9471
|
const total = banner.results.length;
|
|
9268
|
-
|
|
9472
|
+
const urgent = remainingSec <= 1;
|
|
9473
|
+
return /* @__PURE__ */ React12.createElement(Box10, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React12.createElement(Text9, { backgroundColor: "#c4b5fd", color: "black", bold: true }, ` \u2713 AUTO-APPLIED ${ok}/${total} `), /* @__PURE__ */ React12.createElement(Text9, { dimColor: true }, " press "), /* @__PURE__ */ React12.createElement(Text9, { backgroundColor: "#67e8f9", color: "black", bold: true }, " u "), /* @__PURE__ */ React12.createElement(Text9, { dimColor: true }, " to undo "), /* @__PURE__ */ React12.createElement(Text9, { color: urgent ? "#f87171" : "#c4b5fd", bold: urgent }, `${remainingSec}s`));
|
|
9269
9474
|
}
|
|
9270
9475
|
function SubagentRow({
|
|
9271
9476
|
activity
|
|
9272
9477
|
}) {
|
|
9273
9478
|
const tick = useTick();
|
|
9274
9479
|
const seconds = (activity.elapsedMs / 1e3).toFixed(1);
|
|
9275
|
-
return /* @__PURE__ */
|
|
9480
|
+
return /* @__PURE__ */ React12.createElement(Box10, { paddingLeft: 3 }, /* @__PURE__ */ React12.createElement(Text9, { color: "#c4b5fd", bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React12.createElement(Text9, null, " "), /* @__PURE__ */ React12.createElement(Text9, { backgroundColor: "#c4b5fd", color: "black", bold: true }, " \u232C subagent "), /* @__PURE__ */ React12.createElement(Text9, { color: "#c4b5fd" }, ` ${activity.task}`), /* @__PURE__ */ React12.createElement(Text9, { dimColor: true }, ` iter ${activity.iter} \xB7 ${seconds}s`));
|
|
9276
9481
|
}
|
|
9277
9482
|
function OngoingToolRow({
|
|
9278
9483
|
tool: tool2,
|
|
@@ -9281,7 +9486,7 @@ function OngoingToolRow({
|
|
|
9281
9486
|
const tick = useTick();
|
|
9282
9487
|
const elapsed = useElapsedSeconds();
|
|
9283
9488
|
const summary = summarizeToolArgs(tool2.name, tool2.args);
|
|
9284
|
-
return /* @__PURE__ */
|
|
9489
|
+
return /* @__PURE__ */ React12.createElement(Box10, { marginY: 1, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React12.createElement(Box10, null, /* @__PURE__ */ React12.createElement(Text9, { color: "#fcd34d", bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React12.createElement(Text9, null, " "), /* @__PURE__ */ React12.createElement(Text9, { backgroundColor: "#fcd34d", color: "black", bold: true }, ` \u23F5 ${tool2.name} `), /* @__PURE__ */ React12.createElement(Text9, { color: "#fcd34d" }, " running"), /* @__PURE__ */ React12.createElement(Text9, { dimColor: true }, ` \xB7 ${elapsed}s`)), progress ? /* @__PURE__ */ React12.createElement(Box10, { paddingLeft: 3 }, /* @__PURE__ */ React12.createElement(Text9, { color: "#67e8f9" }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ React12.createElement(Box10, { paddingLeft: 3 }, /* @__PURE__ */ React12.createElement(Text9, { dimColor: true }, summary)) : null);
|
|
9285
9490
|
}
|
|
9286
9491
|
function renderProgressLine(p) {
|
|
9287
9492
|
const msg = p.message ? ` ${p.message}` : "";
|
|
@@ -9337,8 +9542,8 @@ function summarizeToolArgs(name, args) {
|
|
|
9337
9542
|
}
|
|
9338
9543
|
|
|
9339
9544
|
// src/cli/ui/PlanCheckpointConfirm.tsx
|
|
9340
|
-
import { Box as
|
|
9341
|
-
import
|
|
9545
|
+
import { Box as Box11 } from "ink";
|
|
9546
|
+
import React13 from "react";
|
|
9342
9547
|
function PlanCheckpointConfirmInner({
|
|
9343
9548
|
stepId,
|
|
9344
9549
|
title,
|
|
@@ -9349,10 +9554,11 @@ function PlanCheckpointConfirmInner({
|
|
|
9349
9554
|
onChoose
|
|
9350
9555
|
}) {
|
|
9351
9556
|
const label = title ? `${stepId} \xB7 ${title}` : stepId;
|
|
9352
|
-
const counter = total > 0 ?
|
|
9557
|
+
const counter = total > 0 ? `${completed}/${total}` : "";
|
|
9353
9558
|
const isLast = total > 0 && completed >= total;
|
|
9354
9559
|
const statuses = buildStatusMap(steps, completedStepIds, stepId, isLast);
|
|
9355
|
-
|
|
9560
|
+
const subtitle = counter ? `${counter} \xB7 ${label}` : label;
|
|
9561
|
+
return /* @__PURE__ */ React13.createElement(ModalCard, { accent: "#86efac", icon: "\u2713", title: "checkpoint \u2014 step done", subtitle }, steps && steps.length > 0 ? /* @__PURE__ */ React13.createElement(Box11, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React13.createElement(PlanStepList, { steps, statuses, focusStepId: stepId })) : null, /* @__PURE__ */ React13.createElement(
|
|
9356
9562
|
SingleSelect,
|
|
9357
9563
|
{
|
|
9358
9564
|
initialValue: isLast ? "stop" : "continue",
|
|
@@ -9377,9 +9583,9 @@ function PlanCheckpointConfirmInner({
|
|
|
9377
9583
|
onCancel: () => onChoose("stop"),
|
|
9378
9584
|
footer: "[\u2191\u2193] navigate \xB7 [Enter] select \xB7 [Esc] stop"
|
|
9379
9585
|
}
|
|
9380
|
-
))
|
|
9586
|
+
));
|
|
9381
9587
|
}
|
|
9382
|
-
var PlanCheckpointConfirm =
|
|
9588
|
+
var PlanCheckpointConfirm = React13.memo(PlanCheckpointConfirmInner);
|
|
9383
9589
|
function buildStatusMap(steps, completedStepIds, currentStepId, isLast) {
|
|
9384
9590
|
const map = /* @__PURE__ */ new Map();
|
|
9385
9591
|
if (!steps) return map;
|
|
@@ -9396,42 +9602,53 @@ function buildStatusMap(steps, completedStepIds, currentStepId, isLast) {
|
|
|
9396
9602
|
}
|
|
9397
9603
|
|
|
9398
9604
|
// src/cli/ui/PlanConfirm.tsx
|
|
9399
|
-
import { Box as
|
|
9400
|
-
import
|
|
9605
|
+
import { Box as Box12, Text as Text10 } from "ink";
|
|
9606
|
+
import React14 from "react";
|
|
9401
9607
|
function PlanConfirmInner({ plan: plan2, steps, summary, onChoose }) {
|
|
9402
9608
|
const hasOpenQuestions = /^#{1,6}\s*(open[-\s]?questions?|risks?|unknowns?|assumptions?|unclear)/im.test(plan2) || /^#{1,6}\s*(待确认|开放问题|风险|未知|假设|不确定)/im.test(plan2);
|
|
9403
|
-
return /* @__PURE__ */
|
|
9404
|
-
|
|
9609
|
+
return /* @__PURE__ */ React14.createElement(
|
|
9610
|
+
ModalCard,
|
|
9405
9611
|
{
|
|
9406
|
-
|
|
9407
|
-
|
|
9408
|
-
|
|
9409
|
-
|
|
9410
|
-
|
|
9411
|
-
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9421
|
-
|
|
9422
|
-
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
|
|
9612
|
+
accent: "#67e8f9",
|
|
9613
|
+
icon: "\u{1F4CB}",
|
|
9614
|
+
title: "plan proposed",
|
|
9615
|
+
subtitle: summary ?? "approve / refine / cancel"
|
|
9616
|
+
},
|
|
9617
|
+
hasOpenQuestions ? /* @__PURE__ */ React14.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text10, { color: "#fbbf24" }, "\u25B2 the plan flags open questions or risks \u2014 pick", " ", /* @__PURE__ */ React14.createElement(Text10, { bold: true }, "Refine / answer questions"), " to write concrete answers before the model moves on.")) : null,
|
|
9618
|
+
steps && steps.length > 0 ? /* @__PURE__ */ React14.createElement(Box12, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React14.createElement(PlanStepList, { steps })) : null,
|
|
9619
|
+
/* @__PURE__ */ React14.createElement(
|
|
9620
|
+
SingleSelect,
|
|
9621
|
+
{
|
|
9622
|
+
initialValue: hasOpenQuestions ? "refine" : "approve",
|
|
9623
|
+
items: [
|
|
9624
|
+
{
|
|
9625
|
+
value: "approve",
|
|
9626
|
+
label: "Approve and implement",
|
|
9627
|
+
hint: "Exit plan mode. The model starts executing. You'll get a text input to add any last instructions (or just press Enter to skip)."
|
|
9628
|
+
},
|
|
9629
|
+
{
|
|
9630
|
+
value: "refine",
|
|
9631
|
+
label: "Refine / answer questions",
|
|
9632
|
+
hint: "Stay in plan mode. Write answers, modifications, or critiques; the model revises and re-submits."
|
|
9633
|
+
},
|
|
9634
|
+
{
|
|
9635
|
+
value: "cancel",
|
|
9636
|
+
label: "Cancel",
|
|
9637
|
+
hint: "Exit plan mode. Drop the plan; the model won't implement it."
|
|
9638
|
+
}
|
|
9639
|
+
],
|
|
9640
|
+
onSubmit: (v) => onChoose(v),
|
|
9641
|
+
onCancel: () => onChoose("cancel"),
|
|
9642
|
+
footer: "[\u2191\u2193] navigate \xB7 [Enter] select \xB7 [Esc] cancel"
|
|
9643
|
+
}
|
|
9644
|
+
)
|
|
9645
|
+
);
|
|
9429
9646
|
}
|
|
9430
|
-
var PlanConfirm =
|
|
9647
|
+
var PlanConfirm = React14.memo(PlanConfirmInner);
|
|
9431
9648
|
|
|
9432
9649
|
// src/cli/ui/PlanRefineInput.tsx
|
|
9433
|
-
import { Box as
|
|
9434
|
-
import
|
|
9650
|
+
import { Box as Box13, Text as Text11 } from "ink";
|
|
9651
|
+
import React15, { useState as useState4 } from "react";
|
|
9435
9652
|
function PlanRefineInput({ mode: mode2, onSubmit, onCancel }) {
|
|
9436
9653
|
const [value, setValue] = useState4("");
|
|
9437
9654
|
useKeystroke((ev) => {
|
|
@@ -9455,15 +9672,33 @@ function PlanRefineInput({ mode: mode2, onSubmit, onCancel }) {
|
|
|
9455
9672
|
setValue((v) => v + ev.input);
|
|
9456
9673
|
}
|
|
9457
9674
|
});
|
|
9458
|
-
const
|
|
9459
|
-
const
|
|
9675
|
+
const tick = useTick();
|
|
9676
|
+
const cursorOn = Math.floor(tick / 4) % 2 === 0;
|
|
9677
|
+
const meta = mode2 === "approve" ? {
|
|
9678
|
+
title: "approving \u2014 any last instructions?",
|
|
9679
|
+
icon: "\u{1F4CB}",
|
|
9680
|
+
accent: "#67e8f9"
|
|
9681
|
+
} : mode2 === "checkpoint-revise" ? {
|
|
9682
|
+
title: "revising \u2014 what should change before the next step?",
|
|
9683
|
+
icon: "\u270F",
|
|
9684
|
+
accent: "#fbbf24"
|
|
9685
|
+
} : mode2 === "choice-custom" ? {
|
|
9686
|
+
title: "custom answer \u2014 type whatever fits",
|
|
9687
|
+
icon: "\u{1F500}",
|
|
9688
|
+
accent: "#f0abfc"
|
|
9689
|
+
} : {
|
|
9690
|
+
title: "refining \u2014 what should the model change?",
|
|
9691
|
+
icon: "\u270F",
|
|
9692
|
+
accent: "#fbbf24"
|
|
9693
|
+
};
|
|
9694
|
+
const hint = mode2 === "approve" ? "Answer questions the plan raised, add constraints, or just press Enter to approve as-is." : mode2 === "checkpoint-revise" ? "Scope change, skip steps, alternative approach \u2014 the model adjusts the remaining plan." : mode2 === "choice-custom" ? "Free-form reply. The model reads it verbatim and proceeds \u2014 no need to match the listed options." : "Describe what's wrong or missing, or answer questions the plan raised.";
|
|
9460
9695
|
const blankHint = mode2 === "approve" ? " (Enter with blank = approve without extra instructions.)" : mode2 === "checkpoint-revise" ? " (Enter with blank = continue with the current plan.)" : mode2 === "choice-custom" ? " (Enter with blank = ask the model what you actually want.)" : " (Enter with blank = ask the model to list concrete questions.)";
|
|
9461
|
-
return /* @__PURE__ */
|
|
9696
|
+
return /* @__PURE__ */ React15.createElement(ModalCard, { accent: meta.accent, icon: meta.icon, title: meta.title }, /* @__PURE__ */ React15.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text11, { dimColor: true }, hint, " Enter to send \xB7 Esc to return to the picker.", value === "" ? blankHint : "")), /* @__PURE__ */ React15.createElement(Box13, null, /* @__PURE__ */ React15.createElement(Text11, { color: meta.accent, bold: true }, "\u203A "), /* @__PURE__ */ React15.createElement(Text11, null, value), /* @__PURE__ */ React15.createElement(Text11, { color: meta.accent, bold: true }, cursorOn ? "\u258D" : " ")));
|
|
9462
9697
|
}
|
|
9463
9698
|
|
|
9464
9699
|
// src/cli/ui/PlanReviseConfirm.tsx
|
|
9465
|
-
import { Box as
|
|
9466
|
-
import
|
|
9700
|
+
import { Box as Box14, Text as Text12 } from "ink";
|
|
9701
|
+
import React16 from "react";
|
|
9467
9702
|
function computeDiff(oldSteps, newSteps) {
|
|
9468
9703
|
const oldIds = new Set(oldSteps.map((s) => s.id));
|
|
9469
9704
|
const newIds = new Set(newSteps.map((s) => s.id));
|
|
@@ -9479,13 +9714,13 @@ function computeDiff(oldSteps, newSteps) {
|
|
|
9479
9714
|
function riskDots2(risk) {
|
|
9480
9715
|
switch (risk) {
|
|
9481
9716
|
case "high":
|
|
9482
|
-
return { dots: "\u25CF\u25CF\u25CF", color: "
|
|
9717
|
+
return { dots: "\u25CF\u25CF\u25CF", color: "#f87171" };
|
|
9483
9718
|
case "med":
|
|
9484
|
-
return { dots: "\u25CF\u25CF ", color: "
|
|
9719
|
+
return { dots: "\u25CF\u25CF ", color: "#fbbf24" };
|
|
9485
9720
|
case "low":
|
|
9486
|
-
return { dots: "\u25CF ", color: "
|
|
9721
|
+
return { dots: "\u25CF ", color: "#4ade80" };
|
|
9487
9722
|
default:
|
|
9488
|
-
return { dots: " ", color: "
|
|
9723
|
+
return { dots: " ", color: "#94a3b8" };
|
|
9489
9724
|
}
|
|
9490
9725
|
}
|
|
9491
9726
|
function PlanReviseConfirmInner({
|
|
@@ -9499,40 +9734,52 @@ function PlanReviseConfirmInner({
|
|
|
9499
9734
|
const removedCount = rows.filter((r) => r.kind === "removed").length;
|
|
9500
9735
|
const addedCount = rows.filter((r) => r.kind === "added").length;
|
|
9501
9736
|
const keptCount = rows.filter((r) => r.kind === "kept").length;
|
|
9502
|
-
return /* @__PURE__ */
|
|
9503
|
-
|
|
9504
|
-
const prefix = row2.kind === "removed" ? "\u2212" : row2.kind === "added" ? "+" : " ";
|
|
9505
|
-
const prefixColor = row2.kind === "removed" ? "red" : row2.kind === "added" ? "green" : "gray";
|
|
9506
|
-
const dim = row2.kind === "kept";
|
|
9507
|
-
const strike = row2.kind === "removed";
|
|
9508
|
-
return /* @__PURE__ */ React15.createElement(Box13, { key: `${row2.kind}-${row2.step.id}` }, /* @__PURE__ */ React15.createElement(Text13, { color: prefixColor, bold: true }, `${prefix} `), /* @__PURE__ */ React15.createElement(Text13, { color: risk.color, bold: true, dimColor: dim }, risk.dots), /* @__PURE__ */ React15.createElement(Text13, { dimColor: dim, strikethrough: strike }, ` ${row2.step.id} \xB7 ${row2.step.title}`));
|
|
9509
|
-
})), /* @__PURE__ */ React15.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(
|
|
9510
|
-
SingleSelect,
|
|
9737
|
+
return /* @__PURE__ */ React16.createElement(
|
|
9738
|
+
ModalCard,
|
|
9511
9739
|
{
|
|
9512
|
-
|
|
9513
|
-
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
|
|
9517
|
-
|
|
9518
|
-
|
|
9519
|
-
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
|
|
9523
|
-
|
|
9524
|
-
|
|
9525
|
-
|
|
9526
|
-
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9740
|
+
accent: "#fbbf24",
|
|
9741
|
+
icon: "\u270F",
|
|
9742
|
+
title: "plan revision proposed",
|
|
9743
|
+
subtitle: `\u2212${removedCount} +${addedCount} \xB7 ${keptCount} kept`
|
|
9744
|
+
},
|
|
9745
|
+
/* @__PURE__ */ React16.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text12, null, reason)),
|
|
9746
|
+
summary ? /* @__PURE__ */ React16.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text12, { dimColor: true }, `updated summary: ${summary}`)) : null,
|
|
9747
|
+
/* @__PURE__ */ React16.createElement(Box14, { marginBottom: 1, flexDirection: "column" }, rows.map((row2) => {
|
|
9748
|
+
const risk = riskDots2(row2.step.risk);
|
|
9749
|
+
const prefix = row2.kind === "removed" ? "\u2212" : row2.kind === "added" ? "+" : " ";
|
|
9750
|
+
const prefixColor = row2.kind === "removed" ? "#f87171" : row2.kind === "added" ? "#4ade80" : "#94a3b8";
|
|
9751
|
+
const dim = row2.kind === "kept";
|
|
9752
|
+
const strike = row2.kind === "removed";
|
|
9753
|
+
return /* @__PURE__ */ React16.createElement(Box14, { key: `${row2.kind}-${row2.step.id}` }, /* @__PURE__ */ React16.createElement(Text12, { color: prefixColor, bold: true }, `${prefix} `), /* @__PURE__ */ React16.createElement(Text12, { color: risk.color, bold: true, dimColor: dim }, risk.dots), /* @__PURE__ */ React16.createElement(Text12, { dimColor: dim, strikethrough: strike }, ` ${row2.step.id} \xB7 ${row2.step.title}`));
|
|
9754
|
+
})),
|
|
9755
|
+
/* @__PURE__ */ React16.createElement(
|
|
9756
|
+
SingleSelect,
|
|
9757
|
+
{
|
|
9758
|
+
initialValue: "accept",
|
|
9759
|
+
items: [
|
|
9760
|
+
{
|
|
9761
|
+
value: "accept",
|
|
9762
|
+
label: "Accept revision \u2014 apply the new step list",
|
|
9763
|
+
hint: "Replaces the remaining plan with the proposed steps. Done steps are untouched."
|
|
9764
|
+
},
|
|
9765
|
+
{
|
|
9766
|
+
value: "reject",
|
|
9767
|
+
label: "Reject \u2014 keep the original plan",
|
|
9768
|
+
hint: "Drops the proposal. Model continues with the original remaining steps."
|
|
9769
|
+
}
|
|
9770
|
+
],
|
|
9771
|
+
onSubmit: (v) => onChoose(v),
|
|
9772
|
+
onCancel: () => onChoose("reject"),
|
|
9773
|
+
footer: "[\u2191\u2193] navigate \xB7 [Enter] select \xB7 [Esc] reject"
|
|
9774
|
+
}
|
|
9775
|
+
)
|
|
9776
|
+
);
|
|
9530
9777
|
}
|
|
9531
|
-
var PlanReviseConfirm =
|
|
9778
|
+
var PlanReviseConfirm = React16.memo(PlanReviseConfirmInner);
|
|
9532
9779
|
|
|
9533
9780
|
// src/cli/ui/PromptInput.tsx
|
|
9534
|
-
import { Box as
|
|
9535
|
-
import
|
|
9781
|
+
import { Box as Box15, Text as Text13, useStdout as useStdout5 } from "ink";
|
|
9782
|
+
import React17, { useRef as useRef2, useState as useState5 } from "react";
|
|
9536
9783
|
|
|
9537
9784
|
// src/cli/ui/key-normalize.ts
|
|
9538
9785
|
var CSI_TAIL_TO_FLAGS = [
|
|
@@ -10003,7 +10250,7 @@ function PromptInput({
|
|
|
10003
10250
|
if (action.historyHandoff === "prev") onHistoryPrev?.();
|
|
10004
10251
|
if (action.historyHandoff === "next") onHistoryNext?.();
|
|
10005
10252
|
}, !disabled);
|
|
10006
|
-
const { stdout: stdout2 } =
|
|
10253
|
+
const { stdout: stdout2 } = useStdout5();
|
|
10007
10254
|
const cols = stdout2?.columns ?? 80;
|
|
10008
10255
|
const narrow = cols <= 90;
|
|
10009
10256
|
const promptBody = narrow ? "\u203A " : "you \u203A ";
|
|
@@ -10015,14 +10262,19 @@ function PromptInput({
|
|
|
10015
10262
|
const effectivePlaceholder = disabled ? placeholder ?? "\u2026waiting for response\u2026" : placeholder ?? placeholderActive;
|
|
10016
10263
|
const lines = value.length > 0 ? value.split("\n") : [""];
|
|
10017
10264
|
const accentColor = disabled ? "gray" : "cyan";
|
|
10265
|
+
const animate = !disabled && cols >= 100;
|
|
10266
|
+
const tick = useTick();
|
|
10267
|
+
const barOffset = animate ? Math.floor(tick / 6) : 0;
|
|
10268
|
+
const barColorAt = (rowIdx) => disabled ? "gray" : GRADIENT[((rowIdx + barOffset) % GRADIENT.length + GRADIENT.length) % GRADIENT.length];
|
|
10269
|
+
const cursorVisible = animate ? Math.floor(tick / 4) % 2 === 0 : true;
|
|
10018
10270
|
const { line: cursorLine, col: cursorCol } = lineAndColumn(value, cursor);
|
|
10019
10271
|
const renderItems = collapseLinesForDisplay(lines, cursorLine);
|
|
10020
10272
|
const showHugeBufferHints = lines.length > 20;
|
|
10021
|
-
return /* @__PURE__ */
|
|
10273
|
+
return /* @__PURE__ */ React17.createElement(Box15, { flexDirection: "column", paddingX: 1 }, renderItems.map((item, renderIdx) => {
|
|
10022
10274
|
if (item.kind === "skip") {
|
|
10023
10275
|
return (
|
|
10024
10276
|
// biome-ignore lint/suspicious/noArrayIndexKey: stable — collapse markers derive from a fixed sliding window
|
|
10025
|
-
/* @__PURE__ */
|
|
10277
|
+
/* @__PURE__ */ React17.createElement(Box15, { key: `skip-${renderIdx}` }, /* @__PURE__ */ React17.createElement(Text13, { color: barColorAt(renderIdx) }, BAR), /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, continuationIndent.slice(BAR.length)), /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, `[\u2026 ${item.linesHidden} line${item.linesHidden === 1 ? "" : "s"} hidden \u2014 full content kept, submitted on Enter \u2026]`))
|
|
10026
10278
|
);
|
|
10027
10279
|
}
|
|
10028
10280
|
const i = item.originalIndex;
|
|
@@ -10030,7 +10282,7 @@ function PromptInput({
|
|
|
10030
10282
|
const isFirst = i === 0;
|
|
10031
10283
|
const isCursorLine = i === cursorLine;
|
|
10032
10284
|
const showPlaceholder = isFirst && value.length === 0;
|
|
10033
|
-
return /* @__PURE__ */
|
|
10285
|
+
return /* @__PURE__ */ React17.createElement(
|
|
10034
10286
|
PromptLine,
|
|
10035
10287
|
{
|
|
10036
10288
|
key: `ln-${i}`,
|
|
@@ -10038,29 +10290,33 @@ function PromptInput({
|
|
|
10038
10290
|
isFirst,
|
|
10039
10291
|
isCursorLine: isCursorLine && !disabled,
|
|
10040
10292
|
cursorCol: isCursorLine ? cursorCol : null,
|
|
10293
|
+
cursorVisible,
|
|
10041
10294
|
showPlaceholder,
|
|
10042
10295
|
placeholderText: effectivePlaceholder,
|
|
10043
10296
|
promptPrefix,
|
|
10044
10297
|
continuationIndent,
|
|
10045
10298
|
visibleCells,
|
|
10046
10299
|
accentColor,
|
|
10300
|
+
barColor: barColorAt(i),
|
|
10047
10301
|
pastes: pastesRef.current,
|
|
10048
10302
|
disabled: disabled === true
|
|
10049
10303
|
}
|
|
10050
10304
|
);
|
|
10051
|
-
}), showHugeBufferHints && !disabled ? /* @__PURE__ */
|
|
10305
|
+
}), showHugeBufferHints && !disabled ? /* @__PURE__ */ React17.createElement(Box15, null, /* @__PURE__ */ React17.createElement(Text13, { color: barColorAt(0) }, BAR), /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, continuationIndent.slice(BAR.length)), /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, `[${lines.length} lines \xB7 PageUp/PageDown jump to top/bottom \xB7 Ctrl+U clear \xB7 Ctrl+W del word]`)) : null, !disabled && !narrow && value.length > 0 && !value.includes("\n") ? /* @__PURE__ */ React17.createElement(Box15, null, /* @__PURE__ */ React17.createElement(Text13, { color: barColorAt(0) }, BAR), /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, continuationIndent.slice(BAR.length)), /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, "[Ctrl+J] newline \xB7 [Enter] submit \xB7 ends with \\ for line continuation")) : null, disabled ? /* @__PURE__ */ React17.createElement(Box15, null, /* @__PURE__ */ React17.createElement(Text13, { color: barColorAt(0) }, BAR), /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, continuationIndent.slice(BAR.length)), /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, "[Esc] to stop")) : null);
|
|
10052
10306
|
}
|
|
10053
10307
|
function PromptLine({
|
|
10054
10308
|
line,
|
|
10055
10309
|
isFirst,
|
|
10056
10310
|
isCursorLine,
|
|
10057
10311
|
cursorCol,
|
|
10312
|
+
cursorVisible,
|
|
10058
10313
|
showPlaceholder,
|
|
10059
10314
|
placeholderText,
|
|
10060
10315
|
promptPrefix,
|
|
10061
10316
|
continuationIndent,
|
|
10062
10317
|
visibleCells,
|
|
10063
10318
|
accentColor,
|
|
10319
|
+
barColor,
|
|
10064
10320
|
pastes,
|
|
10065
10321
|
disabled
|
|
10066
10322
|
}) {
|
|
@@ -10068,25 +10324,27 @@ function PromptLine({
|
|
|
10068
10324
|
const bodyPrefix = promptPrefix.slice(BAR.length);
|
|
10069
10325
|
const bodyContinuation = continuationIndent.slice(BAR.length);
|
|
10070
10326
|
if (showPlaceholder) {
|
|
10071
|
-
return /* @__PURE__ */
|
|
10327
|
+
return /* @__PURE__ */ React17.createElement(Box15, null, /* @__PURE__ */ React17.createElement(Text13, { color: barColor }, barText), /* @__PURE__ */ React17.createElement(Text13, { bold: true, color: accentColor }, bodyPrefix), !disabled ? /* @__PURE__ */ React17.createElement(Text13, { color: accentColor }, cursorVisible ? "\u258C" : " ") : null, /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, placeholderText));
|
|
10072
10328
|
}
|
|
10073
10329
|
const viewport = buildViewport(line, isCursorLine ? cursorCol : null, visibleCells, pastes);
|
|
10074
|
-
return /* @__PURE__ */
|
|
10330
|
+
return /* @__PURE__ */ React17.createElement(Box15, null, /* @__PURE__ */ React17.createElement(Text13, { color: barColor }, barText), isFirst ? /* @__PURE__ */ React17.createElement(Text13, { bold: true, color: accentColor }, bodyPrefix) : /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, bodyContinuation), viewport.hiddenLeft ? /* @__PURE__ */ React17.createElement(Text13, { color: "gray", dimColor: true }, "\u2039") : null, /* @__PURE__ */ React17.createElement(
|
|
10075
10331
|
ViewportContent,
|
|
10076
10332
|
{
|
|
10077
10333
|
segments: viewport.segments,
|
|
10078
10334
|
cursorCell: isCursorLine ? viewport.cursorCell : null,
|
|
10079
|
-
accentColor
|
|
10335
|
+
accentColor,
|
|
10336
|
+
cursorVisible
|
|
10080
10337
|
}
|
|
10081
|
-
), viewport.hiddenRight ? /* @__PURE__ */
|
|
10338
|
+
), viewport.hiddenRight ? /* @__PURE__ */ React17.createElement(Text13, { color: "gray", dimColor: true }, "\u203A") : null);
|
|
10082
10339
|
}
|
|
10083
10340
|
function ViewportContent({
|
|
10084
10341
|
segments,
|
|
10085
10342
|
cursorCell,
|
|
10086
|
-
accentColor
|
|
10343
|
+
accentColor,
|
|
10344
|
+
cursorVisible
|
|
10087
10345
|
}) {
|
|
10088
10346
|
if (cursorCell === null) {
|
|
10089
|
-
return /* @__PURE__ */
|
|
10347
|
+
return /* @__PURE__ */ React17.createElement(React17.Fragment, null, segments.map((seg, i) => renderSegment(seg, i, false)));
|
|
10090
10348
|
}
|
|
10091
10349
|
const out = [];
|
|
10092
10350
|
let cells = 0;
|
|
@@ -10105,7 +10363,7 @@ function ViewportContent({
|
|
|
10105
10363
|
}
|
|
10106
10364
|
if (seg.kind === "paste") {
|
|
10107
10365
|
out.push(
|
|
10108
|
-
/* @__PURE__ */
|
|
10366
|
+
/* @__PURE__ */ React17.createElement(Text13, { key: `p-${i}-cursor`, color: "magenta", bold: true, inverse: cursorVisible }, seg.label)
|
|
10109
10367
|
);
|
|
10110
10368
|
placed = true;
|
|
10111
10369
|
cells += segCells;
|
|
@@ -10114,29 +10372,29 @@ function ViewportContent({
|
|
|
10114
10372
|
const offsetIntoSeg = cursorCell - cells;
|
|
10115
10373
|
const split = splitTextByCells(seg.text, offsetIntoSeg);
|
|
10116
10374
|
if (split.before.length > 0) {
|
|
10117
|
-
out.push(/* @__PURE__ */
|
|
10375
|
+
out.push(/* @__PURE__ */ React17.createElement(Text13, { key: `t-${i}-b` }, split.before));
|
|
10118
10376
|
}
|
|
10119
10377
|
if (split.atCursor.length > 0) {
|
|
10120
10378
|
out.push(
|
|
10121
|
-
/* @__PURE__ */
|
|
10379
|
+
/* @__PURE__ */ React17.createElement(Text13, { key: `t-${i}-c`, inverse: cursorVisible, color: accentColor }, split.atCursor)
|
|
10122
10380
|
);
|
|
10123
10381
|
} else {
|
|
10124
10382
|
out.push(
|
|
10125
|
-
/* @__PURE__ */
|
|
10383
|
+
/* @__PURE__ */ React17.createElement(Text13, { key: `t-${i}-c-eol`, color: accentColor }, cursorVisible ? "\u258C" : " ")
|
|
10126
10384
|
);
|
|
10127
10385
|
}
|
|
10128
10386
|
if (split.after.length > 0) {
|
|
10129
|
-
out.push(/* @__PURE__ */
|
|
10387
|
+
out.push(/* @__PURE__ */ React17.createElement(Text13, { key: `t-${i}-a` }, split.after));
|
|
10130
10388
|
}
|
|
10131
10389
|
placed = true;
|
|
10132
10390
|
cells += segCells;
|
|
10133
10391
|
}
|
|
10134
10392
|
if (!placed) {
|
|
10135
10393
|
out.push(
|
|
10136
|
-
/* @__PURE__ */
|
|
10394
|
+
/* @__PURE__ */ React17.createElement(Text13, { key: "cursor-eol", color: accentColor }, cursorVisible ? "\u258C" : " ")
|
|
10137
10395
|
);
|
|
10138
10396
|
}
|
|
10139
|
-
return /* @__PURE__ */
|
|
10397
|
+
return /* @__PURE__ */ React17.createElement(React17.Fragment, null, out);
|
|
10140
10398
|
}
|
|
10141
10399
|
function segmentCells(seg) {
|
|
10142
10400
|
if (seg.kind === "paste") return seg.label.length;
|
|
@@ -10176,9 +10434,9 @@ function charCellsForText(ch) {
|
|
|
10176
10434
|
}
|
|
10177
10435
|
function renderSegment(seg, key, _inverse) {
|
|
10178
10436
|
if (seg.kind === "text") {
|
|
10179
|
-
return /* @__PURE__ */
|
|
10437
|
+
return /* @__PURE__ */ React17.createElement(Text13, { key: `s-${key}` }, seg.text);
|
|
10180
10438
|
}
|
|
10181
|
-
return /* @__PURE__ */
|
|
10439
|
+
return /* @__PURE__ */ React17.createElement(Text13, { key: `s-${key}`, backgroundColor: "#f0abfc", color: "black", bold: true }, seg.label);
|
|
10182
10440
|
}
|
|
10183
10441
|
var COLLAPSE_THRESHOLD = 20;
|
|
10184
10442
|
var COLLAPSE_HEAD_LINES = 3;
|
|
@@ -10205,36 +10463,47 @@ function collapseLinesForDisplay(lines, cursorLine) {
|
|
|
10205
10463
|
}
|
|
10206
10464
|
|
|
10207
10465
|
// src/cli/ui/ShellConfirm.tsx
|
|
10208
|
-
import { Box as
|
|
10209
|
-
import
|
|
10466
|
+
import { Box as Box16, Text as Text14 } from "ink";
|
|
10467
|
+
import React18 from "react";
|
|
10210
10468
|
function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
|
|
10211
10469
|
const isBackground = kind === "run_background";
|
|
10212
|
-
|
|
10213
|
-
|
|
10470
|
+
const subtitle = isBackground ? "long-running process \u2014 keeps running after approval, /kill to stop" : "model wants to run a shell command";
|
|
10471
|
+
return /* @__PURE__ */ React18.createElement(
|
|
10472
|
+
ModalCard,
|
|
10214
10473
|
{
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
|
|
10222
|
-
|
|
10223
|
-
|
|
10224
|
-
|
|
10225
|
-
|
|
10226
|
-
|
|
10227
|
-
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
|
|
10236
|
-
|
|
10237
|
-
|
|
10474
|
+
accent: "#f87171",
|
|
10475
|
+
icon: isBackground ? "\u23F1" : "\u26A1",
|
|
10476
|
+
title: isBackground ? "background process" : "shell command",
|
|
10477
|
+
subtitle
|
|
10478
|
+
},
|
|
10479
|
+
/* @__PURE__ */ React18.createElement(Box16, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Text14, { dimColor: true }, "$ "), /* @__PURE__ */ React18.createElement(Text14, { color: "#67e8f9", bold: true }, command)),
|
|
10480
|
+
/* @__PURE__ */ React18.createElement(
|
|
10481
|
+
SingleSelect,
|
|
10482
|
+
{
|
|
10483
|
+
initialValue: "run_once",
|
|
10484
|
+
items: [
|
|
10485
|
+
{
|
|
10486
|
+
value: "run_once",
|
|
10487
|
+
label: "Run once",
|
|
10488
|
+
hint: "Execute this command, don't remember it."
|
|
10489
|
+
},
|
|
10490
|
+
{
|
|
10491
|
+
value: "always_allow",
|
|
10492
|
+
label: `Always allow "${allowPrefix}" in this project`,
|
|
10493
|
+
hint: "Save the prefix to ~/.reasonix/config.json; future matches auto-run."
|
|
10494
|
+
},
|
|
10495
|
+
{
|
|
10496
|
+
value: "deny",
|
|
10497
|
+
label: "Deny",
|
|
10498
|
+
hint: "Tell the model the user refused; it will continue without this command."
|
|
10499
|
+
}
|
|
10500
|
+
],
|
|
10501
|
+
onSubmit: (v) => onChoose(v),
|
|
10502
|
+
onCancel: () => onChoose("deny"),
|
|
10503
|
+
footer: "[\u2191\u2193] navigate \xB7 [Enter] select \xB7 [Esc] deny"
|
|
10504
|
+
}
|
|
10505
|
+
)
|
|
10506
|
+
);
|
|
10238
10507
|
}
|
|
10239
10508
|
function derivePrefix(command) {
|
|
10240
10509
|
const tokens = command.trim().split(/\s+/).filter(Boolean);
|
|
@@ -10266,8 +10535,8 @@ function derivePrefix(command) {
|
|
|
10266
10535
|
}
|
|
10267
10536
|
|
|
10268
10537
|
// src/cli/ui/SlashArgPicker.tsx
|
|
10269
|
-
import { Box as
|
|
10270
|
-
import
|
|
10538
|
+
import { Box as Box17, Text as Text15 } from "ink";
|
|
10539
|
+
import React19 from "react";
|
|
10271
10540
|
function SlashArgPicker({
|
|
10272
10541
|
matches,
|
|
10273
10542
|
selectedIndex,
|
|
@@ -10276,11 +10545,11 @@ function SlashArgPicker({
|
|
|
10276
10545
|
partial
|
|
10277
10546
|
}) {
|
|
10278
10547
|
if (kind === "hint") {
|
|
10279
|
-
return /* @__PURE__ */
|
|
10548
|
+
return /* @__PURE__ */ React19.createElement(Box17, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, " ", /* @__PURE__ */ React19.createElement(Text15, { bold: true }, "/", spec.cmd), spec.argsHint ? ` ${spec.argsHint}` : "", " \u2014 ", spec.summary));
|
|
10280
10549
|
}
|
|
10281
10550
|
if (matches === null) return null;
|
|
10282
10551
|
if (matches.length === 0) {
|
|
10283
|
-
return /* @__PURE__ */
|
|
10552
|
+
return /* @__PURE__ */ React19.createElement(Box17, { flexDirection: "column", paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, " ", /* @__PURE__ */ React19.createElement(Text15, { bold: true }, "/", spec.cmd), spec.argsHint ? ` ${spec.argsHint}` : "", " \u2014 ", spec.summary), /* @__PURE__ */ React19.createElement(Text15, { color: "yellow" }, ' no match for "', partial, '" \u2014 keep typing, or Backspace to edit'));
|
|
10284
10553
|
}
|
|
10285
10554
|
const MAX = 8;
|
|
10286
10555
|
const total = matches.length;
|
|
@@ -10288,26 +10557,26 @@ function SlashArgPicker({
|
|
|
10288
10557
|
const shown = matches.slice(windowStart, windowStart + MAX);
|
|
10289
10558
|
const hiddenAbove = windowStart;
|
|
10290
10559
|
const hiddenBelow = total - windowStart - shown.length;
|
|
10291
|
-
return /* @__PURE__ */
|
|
10560
|
+
return /* @__PURE__ */ React19.createElement(Box17, { flexDirection: "column", paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, " ", /* @__PURE__ */ React19.createElement(Text15, { bold: true }, "/", spec.cmd), spec.argsHint ? ` ${spec.argsHint}` : "", " \u2014 ", spec.summary), hiddenAbove > 0 ? /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, " \u2191 ", hiddenAbove, " more above") : null, shown.map((value, i) => /* @__PURE__ */ React19.createElement(ArgRow, { key: value, value, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, " \u2193 ", hiddenBelow, " more below") : null, /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, " [\u2191\u2193] navigate \xB7 [Tab]/[Enter] pick"));
|
|
10292
10561
|
}
|
|
10293
10562
|
function ArgRow({ value, isSelected }) {
|
|
10294
10563
|
const marker = isSelected ? "\u25B8" : " ";
|
|
10295
10564
|
if (isSelected) {
|
|
10296
|
-
return /* @__PURE__ */
|
|
10565
|
+
return /* @__PURE__ */ React19.createElement(Box17, null, /* @__PURE__ */ React19.createElement(Text15, { bold: true, color: "cyan" }, marker, " ", value));
|
|
10297
10566
|
}
|
|
10298
|
-
return /* @__PURE__ */
|
|
10567
|
+
return /* @__PURE__ */ React19.createElement(Box17, null, /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, marker, " ", value));
|
|
10299
10568
|
}
|
|
10300
10569
|
|
|
10301
10570
|
// src/cli/ui/SlashSuggestions.tsx
|
|
10302
|
-
import { Box as
|
|
10303
|
-
import
|
|
10571
|
+
import { Box as Box18, Text as Text16 } from "ink";
|
|
10572
|
+
import React20 from "react";
|
|
10304
10573
|
function SlashSuggestions({
|
|
10305
10574
|
matches,
|
|
10306
10575
|
selectedIndex
|
|
10307
10576
|
}) {
|
|
10308
10577
|
if (matches === null) return null;
|
|
10309
10578
|
if (matches.length === 0) {
|
|
10310
|
-
return /* @__PURE__ */
|
|
10579
|
+
return /* @__PURE__ */ React20.createElement(Box18, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React20.createElement(Text16, { color: "yellow" }, "no slash command matches that prefix"), /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, " \u2014 Backspace to edit, or /help for the full list"));
|
|
10311
10580
|
}
|
|
10312
10581
|
const MAX = 8;
|
|
10313
10582
|
const total = matches.length;
|
|
@@ -10315,47 +10584,29 @@ function SlashSuggestions({
|
|
|
10315
10584
|
const shown = matches.slice(windowStart, windowStart + MAX);
|
|
10316
10585
|
const hiddenAbove = windowStart;
|
|
10317
10586
|
const hiddenBelow = total - windowStart - shown.length;
|
|
10318
|
-
return /* @__PURE__ */
|
|
10587
|
+
return /* @__PURE__ */ React20.createElement(Box18, { flexDirection: "column", paddingX: 1, marginTop: 1 }, hiddenAbove > 0 ? /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, " \u2191 ", hiddenAbove, " more above") : null, shown.map((spec, i) => /* @__PURE__ */ React20.createElement(SuggestionRow, { key: spec.cmd, spec, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, " \u2193 ", hiddenBelow, " more below") : null, /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, " [\u2191\u2193] navigate \xB7 [Tab]/[Enter] pick"));
|
|
10319
10588
|
}
|
|
10320
10589
|
function SuggestionRow({ spec, isSelected }) {
|
|
10321
|
-
const marker = isSelected ? "\u25B8" : " ";
|
|
10322
10590
|
const name = `/${spec.cmd}`;
|
|
10323
10591
|
const argsSuffix = spec.argsHint ? ` ${spec.argsHint}` : "";
|
|
10324
10592
|
if (isSelected) {
|
|
10325
|
-
return /* @__PURE__ */
|
|
10593
|
+
return /* @__PURE__ */ React20.createElement(Box18, null, /* @__PURE__ */ React20.createElement(Text16, { backgroundColor: "#67e8f9", color: "black", bold: true }, ` \u25B8 ${name.padEnd(12)}${argsSuffix.padEnd(16)} ${spec.summary} `));
|
|
10326
10594
|
}
|
|
10327
|
-
return /* @__PURE__ */
|
|
10595
|
+
return /* @__PURE__ */ React20.createElement(Box18, null, /* @__PURE__ */ React20.createElement(Text16, { color: "#94a3b8" }, ` ${name.padEnd(12)}${argsSuffix.padEnd(16)} ${spec.summary}`));
|
|
10328
10596
|
}
|
|
10329
10597
|
|
|
10330
10598
|
// src/cli/ui/StatsPanel.tsx
|
|
10331
|
-
import { Box as
|
|
10332
|
-
import
|
|
10333
|
-
var
|
|
10334
|
-
|
|
10335
|
-
// teal — brand mark
|
|
10336
|
-
{ ch: " ", color: "#5eead4", isLogo: false },
|
|
10337
|
-
{ ch: "R", color: "#67e8f9", isLogo: false },
|
|
10338
|
-
// cyan
|
|
10339
|
-
{ ch: "E", color: "#7dd3fc", isLogo: false },
|
|
10340
|
-
// sky
|
|
10341
|
-
{ ch: "A", color: "#93c5fd", isLogo: false },
|
|
10342
|
-
// blue
|
|
10343
|
-
{ ch: "S", color: "#a5b4fc", isLogo: false },
|
|
10344
|
-
// indigo
|
|
10345
|
-
{ ch: "O", color: "#c4b5fd", isLogo: false },
|
|
10346
|
-
// violet
|
|
10347
|
-
{ ch: "N", color: "#d8b4fe", isLogo: false },
|
|
10348
|
-
// purple
|
|
10349
|
-
{ ch: "I", color: "#f0abfc", isLogo: false },
|
|
10350
|
-
// fuchsia
|
|
10351
|
-
{ ch: "X", color: "#f0abfc", isLogo: false }
|
|
10352
|
-
// fuchsia
|
|
10353
|
-
];
|
|
10354
|
-
function Wordmark({ busy }) {
|
|
10599
|
+
import { Box as Box19, Text as Text17, useStdout as useStdout6 } from "ink";
|
|
10600
|
+
import React21 from "react";
|
|
10601
|
+
var WORDMARK_LETTERS = ["R", "E", "A", "S", "O", "N", "I", "X"];
|
|
10602
|
+
function Wordmark({ busy, animate }) {
|
|
10355
10603
|
const tick = useTick();
|
|
10356
|
-
const
|
|
10357
|
-
const bright = Math.floor(tick /
|
|
10358
|
-
|
|
10604
|
+
const pulsePeriod = busy ? 5 : 12;
|
|
10605
|
+
const bright = animate ? Math.floor(tick / pulsePeriod) % 2 === 0 : true;
|
|
10606
|
+
const rotateEvery = busy ? 2 : 4;
|
|
10607
|
+
const offset = animate ? Math.floor(tick / rotateEvery) : 0;
|
|
10608
|
+
const colorAt = (i) => GRADIENT[((i + offset) % GRADIENT.length + GRADIENT.length) % GRADIENT.length];
|
|
10609
|
+
return /* @__PURE__ */ React21.createElement(Text17, null, /* @__PURE__ */ React21.createElement(Text17, { color: colorAt(0), bold: bright }, "\u25C8"), /* @__PURE__ */ React21.createElement(Text17, null, " "), WORDMARK_LETTERS.map((letter, i) => /* @__PURE__ */ React21.createElement(Text17, { key: letter, color: colorAt(i + 1), bold: true }, letter)));
|
|
10359
10610
|
}
|
|
10360
10611
|
var NARROW_BREAKPOINT = 120;
|
|
10361
10612
|
var COLD_START_TURNS = 3;
|
|
@@ -10377,20 +10628,20 @@ function StatsPanel({
|
|
|
10377
10628
|
const branchOn = (branchBudget ?? 1) > 1;
|
|
10378
10629
|
const ctxMax = DEEPSEEK_CONTEXT_TOKENS[model2] ?? DEFAULT_CONTEXT_TOKENS;
|
|
10379
10630
|
const ctxRatio = summary.lastPromptTokens / ctxMax;
|
|
10380
|
-
const { stdout: stdout2 } =
|
|
10631
|
+
const { stdout: stdout2 } = useStdout6();
|
|
10381
10632
|
const columns = stdout2?.columns ?? 80;
|
|
10382
10633
|
const narrow = columns < NARROW_BREAKPOINT;
|
|
10383
10634
|
const coldStart = summary.turns <= COLD_START_TURNS;
|
|
10384
10635
|
const ruleWidth = Math.max(20, columns - 2);
|
|
10636
|
+
const animate = columns >= 100;
|
|
10385
10637
|
return (
|
|
10386
|
-
// Borderless layout: no `borderStyle`, no rounded box
|
|
10387
|
-
//
|
|
10388
|
-
//
|
|
10389
|
-
//
|
|
10390
|
-
//
|
|
10391
|
-
//
|
|
10392
|
-
|
|
10393
|
-
/* @__PURE__ */ React20.createElement(Box18, { flexDirection: "column", paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React20.createElement(
|
|
10638
|
+
// Borderless layout: no `borderStyle`, no rounded box. Bordered
|
|
10639
|
+
// Boxes were the most visible amplifier of Ink's eraseLines
|
|
10640
|
+
// miscount on Windows terminals. Visual weight here comes from
|
|
10641
|
+
// truecolor gradient rules at the top and bottom (rendered as
|
|
10642
|
+
// pure Text so they never trigger the eraseLines bug), the
|
|
10643
|
+
// animated wordmark + pill row, and a soft inner padding.
|
|
10644
|
+
/* @__PURE__ */ React21.createElement(Box19, { flexDirection: "column", paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React21.createElement(GradientRule, { width: ruleWidth, animate }), /* @__PURE__ */ React21.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(
|
|
10394
10645
|
Header,
|
|
10395
10646
|
{
|
|
10396
10647
|
model: model2,
|
|
@@ -10406,9 +10657,10 @@ function StatsPanel({
|
|
|
10406
10657
|
narrow,
|
|
10407
10658
|
busy: busy ?? false,
|
|
10408
10659
|
proArmed: proArmed ?? false,
|
|
10409
|
-
escalated: escalated ?? false
|
|
10660
|
+
escalated: escalated ?? false,
|
|
10661
|
+
animate
|
|
10410
10662
|
}
|
|
10411
|
-
), narrow ? /* @__PURE__ */
|
|
10663
|
+
)), narrow ? /* @__PURE__ */ React21.createElement(
|
|
10412
10664
|
StackedMetrics,
|
|
10413
10665
|
{
|
|
10414
10666
|
summary,
|
|
@@ -10417,7 +10669,7 @@ function StatsPanel({
|
|
|
10417
10669
|
balance,
|
|
10418
10670
|
coldStart
|
|
10419
10671
|
}
|
|
10420
|
-
) : /* @__PURE__ */
|
|
10672
|
+
) : /* @__PURE__ */ React21.createElement(
|
|
10421
10673
|
InlineMetrics,
|
|
10422
10674
|
{
|
|
10423
10675
|
summary,
|
|
@@ -10426,9 +10678,28 @@ function StatsPanel({
|
|
|
10426
10678
|
balance,
|
|
10427
10679
|
coldStart
|
|
10428
10680
|
}
|
|
10429
|
-
), /* @__PURE__ */
|
|
10681
|
+
), /* @__PURE__ */ React21.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(GradientRule, { width: ruleWidth, thin: true, animate })))
|
|
10430
10682
|
);
|
|
10431
10683
|
}
|
|
10684
|
+
function GradientRule({
|
|
10685
|
+
width,
|
|
10686
|
+
thin,
|
|
10687
|
+
animate
|
|
10688
|
+
}) {
|
|
10689
|
+
const tick = useTick();
|
|
10690
|
+
const offset = animate ? Math.floor(tick / 6) : 0;
|
|
10691
|
+
const ch = thin ? "\u2581" : "\u2584";
|
|
10692
|
+
const len = GRADIENT.length;
|
|
10693
|
+
return /* @__PURE__ */ React21.createElement(Box19, null, Array.from({ length: width }, (_, i) => {
|
|
10694
|
+
const t = width === 1 ? 0 : i * (len - 1) / (width - 1);
|
|
10695
|
+
const idx = (Math.round(t) + offset) % len;
|
|
10696
|
+
const color = GRADIENT[(idx % len + len) % len];
|
|
10697
|
+
return (
|
|
10698
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: fixed-width gradient cells never reorder
|
|
10699
|
+
/* @__PURE__ */ React21.createElement(Text17, { key: `grule-${i}`, color }, ch)
|
|
10700
|
+
);
|
|
10701
|
+
}));
|
|
10702
|
+
}
|
|
10432
10703
|
function Header({
|
|
10433
10704
|
model: model2,
|
|
10434
10705
|
prefixHash,
|
|
@@ -10443,14 +10714,16 @@ function Header({
|
|
|
10443
10714
|
narrow,
|
|
10444
10715
|
busy,
|
|
10445
10716
|
proArmed,
|
|
10446
|
-
escalated
|
|
10717
|
+
escalated,
|
|
10718
|
+
animate
|
|
10447
10719
|
}) {
|
|
10448
10720
|
const modePill = planMode ? { label: "PLAN", bg: "red" } : editMode === "auto" ? { label: "AUTO", bg: "magenta" } : editMode === "review" ? { label: "REVIEW", bg: "cyan" } : null;
|
|
10449
10721
|
const proPill = escalated ? { label: "\u21E7 PRO", bg: "red" } : proArmed ? { label: "\u21E7 PRO", bg: "yellow" } : null;
|
|
10450
|
-
|
|
10722
|
+
const showSecondary = animate && !narrow;
|
|
10723
|
+
return /* @__PURE__ */ React21.createElement(Box19, { justifyContent: "space-between" }, /* @__PURE__ */ React21.createElement(Box19, null, /* @__PURE__ */ React21.createElement(Wordmark, { busy, animate }), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, ` ${VERSION}`), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, " "), /* @__PURE__ */ React21.createElement(Text17, { color: "yellow", bold: true }, model2.replace(/^deepseek-/, "")), modePill ? /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement(Text17, null, " "), /* @__PURE__ */ React21.createElement(Pill, { label: modePill.label, bg: modePill.bg })) : null, proPill ? /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement(Text17, null, " "), /* @__PURE__ */ React21.createElement(Pill, { label: proPill.label, bg: proPill.bg })) : null, showSecondary && harvestOn ? /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, /* @__PURE__ */ React21.createElement(Text17, null, " "), /* @__PURE__ */ React21.createElement(Text17, { color: "magenta" }, "harvest")) : null, showSecondary && branchOn ? /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, /* @__PURE__ */ React21.createElement(Text17, null, " "), /* @__PURE__ */ React21.createElement(Text17, { color: "blue" }, `branch\xD7${branchBudget}`)) : null, showSecondary && reasoningEffort === "max" ? /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement(Text17, null, " "), /* @__PURE__ */ React21.createElement(Text17, { color: "green", dimColor: true }, "max")) : null, showSecondary && reasoningEffort === "high" ? /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement(Text17, null, " "), /* @__PURE__ */ React21.createElement(Text17, { color: "yellow", dimColor: true }, "high")) : null), /* @__PURE__ */ React21.createElement(Text17, null, updateAvailable ? /* @__PURE__ */ React21.createElement(Text17, { color: "yellow", bold: true }, `\u2191 ${updateAvailable} `) : null, /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, narrow ? `t${turns}` : `turn ${turns} \xB7 /help`)));
|
|
10451
10724
|
}
|
|
10452
10725
|
function Pill({ label, bg }) {
|
|
10453
|
-
return /* @__PURE__ */
|
|
10726
|
+
return /* @__PURE__ */ React21.createElement(Text17, { backgroundColor: bg, color: "white", bold: true }, ` ${label} `);
|
|
10454
10727
|
}
|
|
10455
10728
|
function InlineMetrics({
|
|
10456
10729
|
summary,
|
|
@@ -10459,7 +10732,7 @@ function InlineMetrics({
|
|
|
10459
10732
|
balance,
|
|
10460
10733
|
coldStart
|
|
10461
10734
|
}) {
|
|
10462
|
-
return /* @__PURE__ */
|
|
10735
|
+
return /* @__PURE__ */ React21.createElement(Box19, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React21.createElement(ContextCell, { ratio: ctxRatio, promptTokens: summary.lastPromptTokens, ctxMax }), /* @__PURE__ */ React21.createElement(CacheCell, { hitRatio: summary.cacheHitRatio, coldStart, turns: summary.turns }), /* @__PURE__ */ React21.createElement(CostCell, { summary, coldStart }), balance ? /* @__PURE__ */ React21.createElement(BalanceCell, { balance }) : null);
|
|
10463
10736
|
}
|
|
10464
10737
|
function StackedMetrics({
|
|
10465
10738
|
summary,
|
|
@@ -10468,7 +10741,7 @@ function StackedMetrics({
|
|
|
10468
10741
|
balance,
|
|
10469
10742
|
coldStart
|
|
10470
10743
|
}) {
|
|
10471
|
-
return /* @__PURE__ */
|
|
10744
|
+
return /* @__PURE__ */ React21.createElement(Box19, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React21.createElement(
|
|
10472
10745
|
ContextCell,
|
|
10473
10746
|
{
|
|
10474
10747
|
ratio: ctxRatio,
|
|
@@ -10476,7 +10749,7 @@ function StackedMetrics({
|
|
|
10476
10749
|
ctxMax,
|
|
10477
10750
|
showBar: true
|
|
10478
10751
|
}
|
|
10479
|
-
), balance ? /* @__PURE__ */
|
|
10752
|
+
), balance ? /* @__PURE__ */ React21.createElement(BalanceCell, { balance }) : null, /* @__PURE__ */ React21.createElement(CacheCell, { hitRatio: summary.cacheHitRatio, coldStart, turns: summary.turns }), /* @__PURE__ */ React21.createElement(CostCell, { summary, coldStart }));
|
|
10480
10753
|
}
|
|
10481
10754
|
function ContextCell({
|
|
10482
10755
|
ratio,
|
|
@@ -10485,11 +10758,11 @@ function ContextCell({
|
|
|
10485
10758
|
showBar
|
|
10486
10759
|
}) {
|
|
10487
10760
|
if (promptTokens === 0) {
|
|
10488
|
-
return /* @__PURE__ */
|
|
10761
|
+
return /* @__PURE__ */ React21.createElement(Text17, null, /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.info, dimColor: true }, "\u25A3 ctx "), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, "\u2014 (no turns yet)"));
|
|
10489
10762
|
}
|
|
10490
|
-
const color = ratio >= 0.8 ?
|
|
10763
|
+
const color = ratio >= 0.8 ? COLOR.err : ratio >= 0.6 ? COLOR.warn : COLOR.ok;
|
|
10491
10764
|
const pct2 = Math.round(ratio * 100);
|
|
10492
|
-
return /* @__PURE__ */
|
|
10765
|
+
return /* @__PURE__ */ React21.createElement(Text17, null, /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.info }, "\u25A3 ctx "), /* @__PURE__ */ React21.createElement(Bar, { ratio, color, cells: showBar ? 14 : 10 }), /* @__PURE__ */ React21.createElement(Text17, null, " "), /* @__PURE__ */ React21.createElement(Text17, { color, bold: true }, formatTokens(promptTokens), "/", formatTokens(ctxMax)), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, " (", pct2, "%)"), ratio >= 0.8 ? /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.err, bold: true }, " \xB7 /compact") : null);
|
|
10493
10766
|
}
|
|
10494
10767
|
function CacheCell({
|
|
10495
10768
|
hitRatio,
|
|
@@ -10498,46 +10771,48 @@ function CacheCell({
|
|
|
10498
10771
|
}) {
|
|
10499
10772
|
const pct2 = (hitRatio * 100).toFixed(1);
|
|
10500
10773
|
if (turns === 0) {
|
|
10501
|
-
return /* @__PURE__ */
|
|
10774
|
+
return /* @__PURE__ */ React21.createElement(Text17, null, /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.info, dimColor: true }, "\u232C cache "), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, "\u2014"));
|
|
10502
10775
|
}
|
|
10503
10776
|
if (coldStart) {
|
|
10504
|
-
return /* @__PURE__ */
|
|
10777
|
+
return /* @__PURE__ */ React21.createElement(Text17, null, /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.info, dimColor: true }, "\u232C cache "), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, pct2, "% "), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true, italic: true }, "(cold start)"));
|
|
10505
10778
|
}
|
|
10506
|
-
const color = hitRatio >= 0.7 ?
|
|
10507
|
-
return /* @__PURE__ */
|
|
10779
|
+
const color = hitRatio >= 0.7 ? COLOR.ok : hitRatio >= 0.4 ? COLOR.warn : COLOR.err;
|
|
10780
|
+
return /* @__PURE__ */ React21.createElement(Text17, null, /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.info }, "\u232C cache "), /* @__PURE__ */ React21.createElement(Text17, { color, bold: true }, pct2, "%"));
|
|
10508
10781
|
}
|
|
10509
10782
|
function turnCostColor(cost) {
|
|
10510
10783
|
if (cost <= 0) return void 0;
|
|
10511
|
-
if (cost >= 0.2) return
|
|
10512
|
-
if (cost >= 0.05) return
|
|
10513
|
-
return
|
|
10784
|
+
if (cost >= 0.2) return COLOR.err;
|
|
10785
|
+
if (cost >= 0.05) return COLOR.warn;
|
|
10786
|
+
return COLOR.ok;
|
|
10514
10787
|
}
|
|
10515
10788
|
function sessionCostColor(cost) {
|
|
10516
10789
|
if (cost <= 0) return void 0;
|
|
10517
|
-
if (cost >= 5) return
|
|
10518
|
-
if (cost >= 0.5) return
|
|
10519
|
-
return
|
|
10790
|
+
if (cost >= 5) return COLOR.err;
|
|
10791
|
+
if (cost >= 0.5) return COLOR.warn;
|
|
10792
|
+
return COLOR.ok;
|
|
10520
10793
|
}
|
|
10521
10794
|
function CostCell({
|
|
10522
10795
|
summary,
|
|
10523
10796
|
coldStart
|
|
10524
10797
|
}) {
|
|
10525
10798
|
if (summary.turns === 0) {
|
|
10526
|
-
return /* @__PURE__ */
|
|
10799
|
+
return /* @__PURE__ */ React21.createElement(Text17, null, /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.info, dimColor: true }, "\u25F4 cost "), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, "\u2014"));
|
|
10527
10800
|
}
|
|
10528
10801
|
const turnColor = coldStart ? void 0 : turnCostColor(summary.lastTurnCostUsd);
|
|
10529
10802
|
const sessionColor = coldStart ? void 0 : sessionCostColor(summary.totalCostUsd);
|
|
10530
|
-
return /* @__PURE__ */
|
|
10803
|
+
return /* @__PURE__ */ React21.createElement(Text17, null, /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.info }, "\u25F4 turn "), /* @__PURE__ */ React21.createElement(Text17, { color: turnColor, bold: !coldStart, dimColor: coldStart }, "$", summary.lastTurnCostUsd.toFixed(4)), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, " \xB7 session "), /* @__PURE__ */ React21.createElement(Text17, { color: sessionColor, bold: !coldStart, dimColor: coldStart }, "$", summary.totalCostUsd.toFixed(4)));
|
|
10531
10804
|
}
|
|
10532
10805
|
function BalanceCell({ balance }) {
|
|
10533
|
-
const color = balance.total < 1 ?
|
|
10534
|
-
return /* @__PURE__ */
|
|
10806
|
+
const color = balance.total < 1 ? COLOR.err : balance.total < 5 ? COLOR.warn : COLOR.ok;
|
|
10807
|
+
return /* @__PURE__ */ React21.createElement(Text17, null, /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.info }, "\u25D0 balance "), /* @__PURE__ */ React21.createElement(Text17, { color, bold: true }, balance.currency === "USD" ? "$" : "", balance.total.toFixed(2), balance.currency !== "USD" ? ` ${balance.currency}` : ""));
|
|
10535
10808
|
}
|
|
10536
|
-
function Bar({
|
|
10537
|
-
|
|
10809
|
+
function Bar({
|
|
10810
|
+
ratio,
|
|
10811
|
+
color,
|
|
10812
|
+
cells = 14
|
|
10813
|
+
}) {
|
|
10538
10814
|
const filled = Math.max(0, Math.min(cells, Math.round(ratio * cells)));
|
|
10539
|
-
|
|
10540
|
-
return /* @__PURE__ */ React20.createElement(Text18, { color }, bar);
|
|
10815
|
+
return /* @__PURE__ */ React21.createElement(Text17, null, /* @__PURE__ */ React21.createElement(Text17, { color }, "\u25B0".repeat(filled)), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, "\u25B1".repeat(cells - filled)));
|
|
10541
10816
|
}
|
|
10542
10817
|
function formatTokens(n) {
|
|
10543
10818
|
if (n < 1024) return String(n);
|
|
@@ -10546,13 +10821,26 @@ function formatTokens(n) {
|
|
|
10546
10821
|
}
|
|
10547
10822
|
|
|
10548
10823
|
// src/cli/ui/WelcomeBanner.tsx
|
|
10549
|
-
import { Box as
|
|
10550
|
-
import
|
|
10824
|
+
import { Box as Box20, Text as Text18, useStdout as useStdout7 } from "ink";
|
|
10825
|
+
import React22 from "react";
|
|
10551
10826
|
function WelcomeBanner({ inCodeMode }) {
|
|
10552
|
-
|
|
10827
|
+
const { stdout: stdout2 } = useStdout7();
|
|
10828
|
+
const cols = stdout2?.columns ?? 80;
|
|
10829
|
+
const ruleWidth = Math.min(60, Math.max(28, cols - 4));
|
|
10830
|
+
return /* @__PURE__ */ React22.createElement(Box20, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React22.createElement(GradientRule2, { width: ruleWidth }), /* @__PURE__ */ React22.createElement(BarRow, null, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: COLOR.brand }, "\u25C8 welcome"), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, " \xB7 type a message to start")), /* @__PURE__ */ React22.createElement(BarRow, null), /* @__PURE__ */ React22.createElement(BarRow, null, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: COLOR.primary }, "quick start")), /* @__PURE__ */ React22.createElement(Hint, { cmd: "/help", desc: "every command + keyboard shortcut" }), /* @__PURE__ */ React22.createElement(Hint, { cmd: "/skill", desc: "invoke a stored playbook" }), inCodeMode ? /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(Hint, { cmd: "@path", desc: "inline a file in your message" }), /* @__PURE__ */ React22.createElement(Hint, { cmd: "!cmd", desc: "run a shell command, output goes to context" })) : null, /* @__PURE__ */ React22.createElement(Hint, { cmd: "/exit", desc: "quit (Ctrl+C also works)" }), /* @__PURE__ */ React22.createElement(BarRow, null), /* @__PURE__ */ React22.createElement(BarRow, null, /* @__PURE__ */ React22.createElement(Text18, { dimColor: true, italic: true }, "tip:"), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, " Ctrl+J inserts a newline \xB7 trailing \\ also continues")), /* @__PURE__ */ React22.createElement(Box20, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(GradientRule2, { width: ruleWidth, thin: true })));
|
|
10831
|
+
}
|
|
10832
|
+
function GradientRule2({ width, thin }) {
|
|
10833
|
+
const cells = gradientCells(width, thin ? "\u2581" : "\u2584");
|
|
10834
|
+
return /* @__PURE__ */ React22.createElement(Box20, null, cells.map((c, i) => (
|
|
10835
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: fixed-width gradient row, never reordered
|
|
10836
|
+
/* @__PURE__ */ React22.createElement(Text18, { key: `wrule-${i}`, color: c.color }, c.ch)
|
|
10837
|
+
)));
|
|
10838
|
+
}
|
|
10839
|
+
function BarRow({ children }) {
|
|
10840
|
+
return /* @__PURE__ */ React22.createElement(Box20, null, /* @__PURE__ */ React22.createElement(Text18, { color: COLOR.brand, bold: true }, "\u258E"), /* @__PURE__ */ React22.createElement(Text18, null, " "), children);
|
|
10553
10841
|
}
|
|
10554
10842
|
function Hint({ cmd, desc }) {
|
|
10555
|
-
return /* @__PURE__ */
|
|
10843
|
+
return /* @__PURE__ */ React22.createElement(BarRow, null, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: COLOR.accent }, cmd.padEnd(8)), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, ` ${desc}`));
|
|
10556
10844
|
}
|
|
10557
10845
|
|
|
10558
10846
|
// src/cli/ui/bang.ts
|
|
@@ -12894,7 +13182,7 @@ function App({
|
|
|
12894
13182
|
const abortedThisTurn = useRef6(false);
|
|
12895
13183
|
const [ongoingTool, setOngoingTool] = useState10(null);
|
|
12896
13184
|
const [toolProgress, setToolProgress] = useState10(null);
|
|
12897
|
-
const { stdout: stdout2 } =
|
|
13185
|
+
const { stdout: stdout2 } = useStdout8();
|
|
12898
13186
|
useEffect6(() => {
|
|
12899
13187
|
if (!stdout2 || !stdout2.isTTY) return;
|
|
12900
13188
|
stdout2.write("\x1B[?2004h");
|
|
@@ -14477,12 +14765,12 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
14477
14765
|
async (choice) => handleReviseConfirmRef.current(choice),
|
|
14478
14766
|
[]
|
|
14479
14767
|
);
|
|
14480
|
-
return /* @__PURE__ */
|
|
14768
|
+
return /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(
|
|
14481
14769
|
TickerProvider,
|
|
14482
14770
|
{
|
|
14483
14771
|
disabled: PLAIN_UI || !!pendingPlan || !!pendingShell || !!pendingEditReview || !!pendingCheckpoint || !!stagedCheckpointRevise || !!pendingChoice || !!stagedChoiceCustom || !!pendingRevision
|
|
14484
14772
|
},
|
|
14485
|
-
/* @__PURE__ */
|
|
14773
|
+
/* @__PURE__ */ React23.createElement(Box21, { flexDirection: "column" }, /* @__PURE__ */ React23.createElement(
|
|
14486
14774
|
StatsPanel,
|
|
14487
14775
|
{
|
|
14488
14776
|
summary,
|
|
@@ -14499,28 +14787,28 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
14499
14787
|
proArmed,
|
|
14500
14788
|
escalated: turnOnPro
|
|
14501
14789
|
}
|
|
14502
|
-
), /* @__PURE__ */
|
|
14790
|
+
), /* @__PURE__ */ React23.createElement(Static, { items: historical }, (item) => /* @__PURE__ */ React23.createElement(EventRow, { key: item.id, event: item, projectRoot: hookCwd })), !historical.some((e) => e.role === "user" || e.role === "assistant") && !busy && !streaming ? /* @__PURE__ */ React23.createElement(WelcomeBanner, { inCodeMode: !!codeMode }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && streaming ? /* @__PURE__ */ React23.createElement(Box21, { marginY: 1 }, /* @__PURE__ */ React23.createElement(EventRow, { event: streaming, projectRoot: hookCwd })) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && ongoingTool ? /* @__PURE__ */ React23.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && subagentActivity ? /* @__PURE__ */ React23.createElement(SubagentRow, { activity: subagentActivity }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !ongoingTool && statusLine ? /* @__PURE__ */ React23.createElement(StatusRow, { text: statusLine }) : null, !PLAIN_UI && undoBanner && !pendingShell && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision ? /* @__PURE__ */ React23.createElement(UndoBanner, { banner: undoBanner }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && busy && !streaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React23.createElement(StatusRow, { text: "processing\u2026" }) : null, stagedInput ? /* @__PURE__ */ React23.createElement(
|
|
14503
14791
|
PlanRefineInput,
|
|
14504
14792
|
{
|
|
14505
14793
|
mode: stagedInput.mode,
|
|
14506
14794
|
onSubmit: handleStagedInputSubmit,
|
|
14507
14795
|
onCancel: handleStagedInputCancel
|
|
14508
14796
|
}
|
|
14509
|
-
) : stagedCheckpointRevise ? /* @__PURE__ */
|
|
14797
|
+
) : stagedCheckpointRevise ? /* @__PURE__ */ React23.createElement(
|
|
14510
14798
|
PlanRefineInput,
|
|
14511
14799
|
{
|
|
14512
14800
|
mode: "checkpoint-revise",
|
|
14513
14801
|
onSubmit: handleCheckpointReviseSubmit,
|
|
14514
14802
|
onCancel: handleCheckpointReviseCancel
|
|
14515
14803
|
}
|
|
14516
|
-
) : stagedChoiceCustom ? /* @__PURE__ */
|
|
14804
|
+
) : stagedChoiceCustom ? /* @__PURE__ */ React23.createElement(
|
|
14517
14805
|
PlanRefineInput,
|
|
14518
14806
|
{
|
|
14519
14807
|
mode: "choice-custom",
|
|
14520
14808
|
onSubmit: handleChoiceCustomSubmit,
|
|
14521
14809
|
onCancel: handleChoiceCustomCancel
|
|
14522
14810
|
}
|
|
14523
|
-
) : pendingChoice ? /* @__PURE__ */
|
|
14811
|
+
) : pendingChoice ? /* @__PURE__ */ React23.createElement(
|
|
14524
14812
|
ChoiceConfirm,
|
|
14525
14813
|
{
|
|
14526
14814
|
question: pendingChoice.question,
|
|
@@ -14528,7 +14816,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
14528
14816
|
allowCustom: pendingChoice.allowCustom,
|
|
14529
14817
|
onChoose: stableHandleChoiceConfirm
|
|
14530
14818
|
}
|
|
14531
|
-
) : pendingRevision ? /* @__PURE__ */
|
|
14819
|
+
) : pendingRevision ? /* @__PURE__ */ React23.createElement(
|
|
14532
14820
|
PlanReviseConfirm,
|
|
14533
14821
|
{
|
|
14534
14822
|
reason: pendingRevision.reason,
|
|
@@ -14539,7 +14827,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
14539
14827
|
summary: pendingRevision.summary,
|
|
14540
14828
|
onChoose: stableHandleReviseConfirm
|
|
14541
14829
|
}
|
|
14542
|
-
) : pendingCheckpoint ? /* @__PURE__ */
|
|
14830
|
+
) : pendingCheckpoint ? /* @__PURE__ */ React23.createElement(
|
|
14543
14831
|
PlanCheckpointConfirm,
|
|
14544
14832
|
{
|
|
14545
14833
|
stepId: pendingCheckpoint.stepId,
|
|
@@ -14550,7 +14838,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
14550
14838
|
completedStepIds: completedStepIdsRef.current,
|
|
14551
14839
|
onChoose: stableHandleCheckpointConfirm
|
|
14552
14840
|
}
|
|
14553
|
-
) : pendingPlan ? /* @__PURE__ */
|
|
14841
|
+
) : pendingPlan ? /* @__PURE__ */ React23.createElement(
|
|
14554
14842
|
PlanConfirm,
|
|
14555
14843
|
{
|
|
14556
14844
|
plan: pendingPlan,
|
|
@@ -14559,7 +14847,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
14559
14847
|
onChoose: stableHandlePlanConfirm,
|
|
14560
14848
|
projectRoot: hookCwd
|
|
14561
14849
|
}
|
|
14562
|
-
) : pendingShell ? /* @__PURE__ */
|
|
14850
|
+
) : pendingShell ? /* @__PURE__ */ React23.createElement(
|
|
14563
14851
|
ShellConfirm,
|
|
14564
14852
|
{
|
|
14565
14853
|
command: pendingShell.command,
|
|
@@ -14567,7 +14855,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
14567
14855
|
kind: pendingShell.kind,
|
|
14568
14856
|
onChoose: handleShellConfirm
|
|
14569
14857
|
}
|
|
14570
|
-
) : pendingEditReview ? /* @__PURE__ */
|
|
14858
|
+
) : pendingEditReview ? /* @__PURE__ */ React23.createElement(
|
|
14571
14859
|
EditConfirm,
|
|
14572
14860
|
{
|
|
14573
14861
|
block: pendingEditReview,
|
|
@@ -14579,7 +14867,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
14579
14867
|
}
|
|
14580
14868
|
}
|
|
14581
14869
|
}
|
|
14582
|
-
) : /* @__PURE__ */
|
|
14870
|
+
) : /* @__PURE__ */ React23.createElement(React23.Fragment, null, codeMode ? /* @__PURE__ */ React23.createElement(
|
|
14583
14871
|
ModeStatusBar,
|
|
14584
14872
|
{
|
|
14585
14873
|
editMode,
|
|
@@ -14589,7 +14877,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
14589
14877
|
undoArmed: !!undoBanner || hasUndoable(),
|
|
14590
14878
|
jobs: codeMode.jobs
|
|
14591
14879
|
}
|
|
14592
|
-
) : null, /* @__PURE__ */
|
|
14880
|
+
) : null, /* @__PURE__ */ React23.createElement(
|
|
14593
14881
|
PromptInput,
|
|
14594
14882
|
{
|
|
14595
14883
|
value: input,
|
|
@@ -14599,14 +14887,14 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
14599
14887
|
onHistoryPrev: recallPrev,
|
|
14600
14888
|
onHistoryNext: recallNext
|
|
14601
14889
|
}
|
|
14602
|
-
), /* @__PURE__ */
|
|
14890
|
+
), /* @__PURE__ */ React23.createElement(SlashSuggestions, { matches: slashMatches, selectedIndex: slashSelected }), /* @__PURE__ */ React23.createElement(
|
|
14603
14891
|
AtMentionSuggestions,
|
|
14604
14892
|
{
|
|
14605
14893
|
matches: atMatches,
|
|
14606
14894
|
selectedIndex: atSelected,
|
|
14607
14895
|
query: atPicker?.query ?? ""
|
|
14608
14896
|
}
|
|
14609
|
-
), slashArgContext ? /* @__PURE__ */
|
|
14897
|
+
), slashArgContext ? /* @__PURE__ */ React23.createElement(
|
|
14610
14898
|
SlashArgPicker,
|
|
14611
14899
|
{
|
|
14612
14900
|
matches: slashArgMatches,
|
|
@@ -14620,15 +14908,15 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
14620
14908
|
}
|
|
14621
14909
|
|
|
14622
14910
|
// src/cli/ui/SessionPicker.tsx
|
|
14623
|
-
import { Box as
|
|
14624
|
-
import
|
|
14911
|
+
import { Box as Box22, Text as Text19 } from "ink";
|
|
14912
|
+
import React24 from "react";
|
|
14625
14913
|
function SessionPicker({
|
|
14626
14914
|
sessionName,
|
|
14627
14915
|
messageCount,
|
|
14628
14916
|
lastActive,
|
|
14629
14917
|
onChoose
|
|
14630
14918
|
}) {
|
|
14631
|
-
return /* @__PURE__ */
|
|
14919
|
+
return /* @__PURE__ */ React24.createElement(Box22, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React24.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text19, { bold: true, color: "cyan" }, `Session "${sessionName}" has ${messageCount} prior message${messageCount === 1 ? "" : "s"}`), /* @__PURE__ */ React24.createElement(Text19, { dimColor: true }, ` \xB7 last active ${relativeTime2(lastActive)}`)), /* @__PURE__ */ React24.createElement(
|
|
14632
14920
|
SingleSelect,
|
|
14633
14921
|
{
|
|
14634
14922
|
initialValue: "new",
|
|
@@ -14651,7 +14939,7 @@ function SessionPicker({
|
|
|
14651
14939
|
],
|
|
14652
14940
|
onSubmit: (v) => onChoose(v)
|
|
14653
14941
|
}
|
|
14654
|
-
), /* @__PURE__ */
|
|
14942
|
+
), /* @__PURE__ */ React24.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React24.createElement(Text19, { dimColor: true }, "[\u2191\u2193] navigate \xB7 [Enter] select")));
|
|
14655
14943
|
}
|
|
14656
14944
|
function relativeTime2(date) {
|
|
14657
14945
|
const ms = Date.now() - date.getTime();
|
|
@@ -14667,9 +14955,9 @@ function relativeTime2(date) {
|
|
|
14667
14955
|
}
|
|
14668
14956
|
|
|
14669
14957
|
// src/cli/ui/Setup.tsx
|
|
14670
|
-
import { Box as
|
|
14958
|
+
import { Box as Box23, Text as Text20, useApp as useApp2 } from "ink";
|
|
14671
14959
|
import TextInput from "ink-text-input";
|
|
14672
|
-
import
|
|
14960
|
+
import React25, { useState as useState11 } from "react";
|
|
14673
14961
|
function Setup({ onReady }) {
|
|
14674
14962
|
const [value, setValue] = useState11("");
|
|
14675
14963
|
const [error, setError] = useState11(null);
|
|
@@ -14693,7 +14981,7 @@ function Setup({ onReady }) {
|
|
|
14693
14981
|
}
|
|
14694
14982
|
onReady(trimmed);
|
|
14695
14983
|
};
|
|
14696
|
-
return /* @__PURE__ */
|
|
14984
|
+
return /* @__PURE__ */ React25.createElement(Box23, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React25.createElement(Text20, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React25.createElement(Box23, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React25.createElement(Text20, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React25.createElement(Text20, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React25.createElement(Box23, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React25.createElement(
|
|
14697
14985
|
TextInput,
|
|
14698
14986
|
{
|
|
14699
14987
|
value,
|
|
@@ -14702,7 +14990,7 @@ function Setup({ onReady }) {
|
|
|
14702
14990
|
mask: "\u2022",
|
|
14703
14991
|
placeholder: "sk-..."
|
|
14704
14992
|
}
|
|
14705
|
-
)), error ? /* @__PURE__ */
|
|
14993
|
+
)), error ? /* @__PURE__ */ React25.createElement(Box23, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, { color: "red" }, error)) : value ? /* @__PURE__ */ React25.createElement(Box23, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, { dimColor: true }, "preview: ", redactKey(value))) : null, /* @__PURE__ */ React25.createElement(Box23, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text20, { dimColor: true }, "(Type /exit to abort.)")));
|
|
14706
14994
|
}
|
|
14707
14995
|
|
|
14708
14996
|
// src/cli/commands/chat.tsx
|
|
@@ -14718,7 +15006,7 @@ function Root({
|
|
|
14718
15006
|
const [key, setKey] = useState12(initialKey);
|
|
14719
15007
|
const [pending, setPending] = useState12(sessionPreview);
|
|
14720
15008
|
if (!key) {
|
|
14721
|
-
return /* @__PURE__ */
|
|
15009
|
+
return /* @__PURE__ */ React26.createElement(
|
|
14722
15010
|
Setup,
|
|
14723
15011
|
{
|
|
14724
15012
|
onReady: (k) => {
|
|
@@ -14730,7 +15018,7 @@ function Root({
|
|
|
14730
15018
|
}
|
|
14731
15019
|
process.env.DEEPSEEK_API_KEY = key;
|
|
14732
15020
|
if (pending && appProps.session) {
|
|
14733
|
-
return /* @__PURE__ */
|
|
15021
|
+
return /* @__PURE__ */ React26.createElement(KeystrokeProvider, null, /* @__PURE__ */ React26.createElement(
|
|
14734
15022
|
SessionPicker,
|
|
14735
15023
|
{
|
|
14736
15024
|
sessionName: appProps.session,
|
|
@@ -14745,7 +15033,7 @@ function Root({
|
|
|
14745
15033
|
}
|
|
14746
15034
|
));
|
|
14747
15035
|
}
|
|
14748
|
-
return /* @__PURE__ */
|
|
15036
|
+
return /* @__PURE__ */ React26.createElement(KeystrokeProvider, null, /* @__PURE__ */ React26.createElement(
|
|
14749
15037
|
App,
|
|
14750
15038
|
{
|
|
14751
15039
|
model: appProps.model,
|
|
@@ -14849,8 +15137,11 @@ async function chatCommand(opts) {
|
|
|
14849
15137
|
} else if (opts.session && opts.forceNew) {
|
|
14850
15138
|
rewriteSession(opts.session, []);
|
|
14851
15139
|
}
|
|
15140
|
+
if (process.stdout.isTTY) {
|
|
15141
|
+
process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
15142
|
+
}
|
|
14852
15143
|
const { waitUntilExit } = render(
|
|
14853
|
-
/* @__PURE__ */
|
|
15144
|
+
/* @__PURE__ */ React26.createElement(
|
|
14854
15145
|
Root,
|
|
14855
15146
|
{
|
|
14856
15147
|
initialKey,
|
|
@@ -14919,35 +15210,35 @@ async function codeCommand(opts = {}) {
|
|
|
14919
15210
|
import { writeFileSync as writeFileSync7 } from "fs";
|
|
14920
15211
|
import { basename as basename3 } from "path";
|
|
14921
15212
|
import { render as render2 } from "ink";
|
|
14922
|
-
import
|
|
15213
|
+
import React29 from "react";
|
|
14923
15214
|
|
|
14924
15215
|
// src/cli/ui/DiffApp.tsx
|
|
14925
|
-
import { Box as
|
|
14926
|
-
import
|
|
15216
|
+
import { Box as Box25, Static as Static2, Text as Text22, useApp as useApp3, useInput } from "ink";
|
|
15217
|
+
import React28, { useState as useState13 } from "react";
|
|
14927
15218
|
|
|
14928
15219
|
// src/cli/ui/RecordView.tsx
|
|
14929
|
-
import { Box as
|
|
14930
|
-
import
|
|
15220
|
+
import { Box as Box24, Text as Text21 } from "ink";
|
|
15221
|
+
import React27 from "react";
|
|
14931
15222
|
function RecordView({ rec, compact: compact2 = false }) {
|
|
14932
15223
|
const toolArgsMax = compact2 ? 120 : 200;
|
|
14933
15224
|
const toolContentMax = compact2 ? 200 : 400;
|
|
14934
15225
|
if (rec.role === "user") {
|
|
14935
15226
|
const content = rec.content.includes("\n") ? rec.content.split("\n").join("\n ") : rec.content;
|
|
14936
|
-
return /* @__PURE__ */
|
|
15227
|
+
return /* @__PURE__ */ React27.createElement(Box24, { marginTop: 1 }, /* @__PURE__ */ React27.createElement(Text21, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React27.createElement(Text21, null, content));
|
|
14937
15228
|
}
|
|
14938
15229
|
if (rec.role === "assistant_final") {
|
|
14939
|
-
return /* @__PURE__ */
|
|
15230
|
+
return /* @__PURE__ */ React27.createElement(Box24, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React27.createElement(Box24, null, /* @__PURE__ */ React27.createElement(Text21, { bold: true, color: "green" }, "assistant"), rec.cost !== void 0 ? /* @__PURE__ */ React27.createElement(Text21, { dimColor: true }, " $", rec.cost.toFixed(6)) : null, rec.usage ? /* @__PURE__ */ React27.createElement(CacheBadge, { usage: rec.usage }) : null), rec.planState ? /* @__PURE__ */ React27.createElement(PlanStateBlock, { planState: rec.planState }) : null, rec.content ? /* @__PURE__ */ React27.createElement(Text21, null, rec.content) : /* @__PURE__ */ React27.createElement(Text21, { dimColor: true, italic: true }, "(tool-call response only)"));
|
|
14940
15231
|
}
|
|
14941
15232
|
if (rec.role === "tool") {
|
|
14942
|
-
return /* @__PURE__ */
|
|
15233
|
+
return /* @__PURE__ */ React27.createElement(Box24, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React27.createElement(Text21, { color: "yellow" }, "tool<", rec.tool ?? "?", ">"), rec.args ? /* @__PURE__ */ React27.createElement(Text21, { dimColor: true }, " args: ", truncate2(rec.args, toolArgsMax)) : null, /* @__PURE__ */ React27.createElement(Text21, { dimColor: true }, " \u2192 ", truncate2(rec.content, toolContentMax)));
|
|
14943
15234
|
}
|
|
14944
15235
|
if (rec.role === "error") {
|
|
14945
|
-
return /* @__PURE__ */
|
|
15236
|
+
return /* @__PURE__ */ React27.createElement(Box24, { marginTop: 1 }, /* @__PURE__ */ React27.createElement(Text21, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React27.createElement(Text21, { color: "red" }, rec.error ?? rec.content));
|
|
14946
15237
|
}
|
|
14947
15238
|
if (rec.role === "done" || rec.role === "assistant_delta") {
|
|
14948
15239
|
return null;
|
|
14949
15240
|
}
|
|
14950
|
-
return /* @__PURE__ */
|
|
15241
|
+
return /* @__PURE__ */ React27.createElement(Box24, null, /* @__PURE__ */ React27.createElement(Text21, { dimColor: true }, "[", rec.role, "] ", rec.content));
|
|
14951
15242
|
}
|
|
14952
15243
|
function CacheBadge({ usage }) {
|
|
14953
15244
|
const hit = usage.prompt_cache_hit_tokens ?? 0;
|
|
@@ -14956,7 +15247,7 @@ function CacheBadge({ usage }) {
|
|
|
14956
15247
|
if (total === 0) return null;
|
|
14957
15248
|
const pct2 = hit / total * 100;
|
|
14958
15249
|
const color = pct2 >= 70 ? "green" : pct2 >= 40 ? "yellow" : "red";
|
|
14959
|
-
return /* @__PURE__ */
|
|
15250
|
+
return /* @__PURE__ */ React27.createElement(Text21, null, /* @__PURE__ */ React27.createElement(Text21, { dimColor: true }, " \xB7 cache "), /* @__PURE__ */ React27.createElement(Text21, { color }, pct2.toFixed(1), "%"));
|
|
14960
15251
|
}
|
|
14961
15252
|
function truncate2(s, max) {
|
|
14962
15253
|
return s.length <= max ? s : `${s.slice(0, max)}\u2026 (+${s.length - max} chars)`;
|
|
@@ -14990,7 +15281,7 @@ function DiffApp({ report }) {
|
|
|
14990
15281
|
}
|
|
14991
15282
|
});
|
|
14992
15283
|
const pair = report.pairs[idx];
|
|
14993
|
-
return /* @__PURE__ */
|
|
15284
|
+
return /* @__PURE__ */ React28.createElement(Box25, { flexDirection: "column" }, /* @__PURE__ */ React28.createElement(DiffHeader, { report }), /* @__PURE__ */ React28.createElement(Box25, { marginTop: 1, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ React28.createElement(Text22, { color: "cyan", bold: true }, "turn ", pair?.turn ?? "?", " (", idx + 1, " / ", report.pairs.length, ")"), /* @__PURE__ */ React28.createElement(Text22, null, pair ? /* @__PURE__ */ React28.createElement(KindBadge, { kind: pair.kind }) : null)), /* @__PURE__ */ React28.createElement(Box25, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React28.createElement(Pane, { label: report.a.label, headerColor: "blue", records: paneRecords(pair, "a") }), /* @__PURE__ */ React28.createElement(Pane, { label: report.b.label, headerColor: "magenta", records: paneRecords(pair, "b") })), pair?.divergenceNote ? /* @__PURE__ */ React28.createElement(Box25, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React28.createElement(Text22, { color: "yellow" }, "\u2605 "), /* @__PURE__ */ React28.createElement(Text22, null, pair.divergenceNote)) : null, /* @__PURE__ */ React28.createElement(Box25, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React28.createElement(Text22, { dimColor: true }, /* @__PURE__ */ React28.createElement(Text22, { bold: true }, "j"), "/", /* @__PURE__ */ React28.createElement(Text22, { bold: true }, "\u2193"), " next \xB7 ", /* @__PURE__ */ React28.createElement(Text22, { bold: true }, "k"), "/", /* @__PURE__ */ React28.createElement(Text22, { bold: true }, "\u2191"), " ", "prev \xB7 ", /* @__PURE__ */ React28.createElement(Text22, { bold: true }, "n"), " next-diverge \xB7 ", /* @__PURE__ */ React28.createElement(Text22, { bold: true }, "N"), "/", /* @__PURE__ */ React28.createElement(Text22, { bold: true }, "p"), " ", "prev-diverge \xB7 ", /* @__PURE__ */ React28.createElement(Text22, { bold: true }, "g"), "/", /* @__PURE__ */ React28.createElement(Text22, { bold: true }, "G"), " first/last \xB7 ", /* @__PURE__ */ React28.createElement(Text22, { bold: true }, "q"), " ", "quit")));
|
|
14994
15285
|
}
|
|
14995
15286
|
function DiffHeader({ report }) {
|
|
14996
15287
|
const a = report.a;
|
|
@@ -15008,15 +15299,15 @@ function DiffHeader({ report }) {
|
|
|
15008
15299
|
} else if (a.stats.prefixHashes[0] && a.stats.prefixHashes[0] === b.stats.prefixHashes[0]) {
|
|
15009
15300
|
prefixLine = `shared prefix hash ${a.stats.prefixHashes[0].slice(0, 12)}\u2026 \u2014 cache delta attributable to log stability, not prompt change.`;
|
|
15010
15301
|
}
|
|
15011
|
-
return /* @__PURE__ */
|
|
15302
|
+
return /* @__PURE__ */ React28.createElement(Box25, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React28.createElement(Box25, { justifyContent: "space-between" }, /* @__PURE__ */ React28.createElement(Text22, null, /* @__PURE__ */ React28.createElement(Text22, { color: "cyan", bold: true }, "reasonix diff"), /* @__PURE__ */ React28.createElement(Text22, { dimColor: true }, " \xB7 A="), /* @__PURE__ */ React28.createElement(Text22, { color: "blue" }, a.label), /* @__PURE__ */ React28.createElement(Text22, { dimColor: true }, " vs B="), /* @__PURE__ */ React28.createElement(Text22, { color: "magenta" }, b.label)), /* @__PURE__ */ React28.createElement(Text22, { dimColor: true }, report.pairs.length, " turns aligned")), /* @__PURE__ */ React28.createElement(Box25, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React28.createElement(Text22, null, /* @__PURE__ */ React28.createElement(Text22, { dimColor: true }, "cache "), /* @__PURE__ */ React28.createElement(Text22, null, (a.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React28.createElement(Text22, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React28.createElement(Text22, null, (b.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React28.createElement(Text22, { color: cacheDelta >= 0 ? "green" : "red", bold: true }, " ", cacheDelta >= 0 ? "+" : "", (cacheDelta * 100).toFixed(1), "pp")), /* @__PURE__ */ React28.createElement(Text22, null, /* @__PURE__ */ React28.createElement(Text22, { dimColor: true }, "cost "), /* @__PURE__ */ React28.createElement(Text22, null, "$", a.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React28.createElement(Text22, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React28.createElement(Text22, null, "$", b.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React28.createElement(Text22, { color: costDelta2 <= 0 ? "green" : "red", bold: true }, " ", costDelta2 >= 0 ? "+" : "", costDelta2.toFixed(1), "%")), /* @__PURE__ */ React28.createElement(Text22, null, /* @__PURE__ */ React28.createElement(Text22, { dimColor: true }, "model calls "), /* @__PURE__ */ React28.createElement(Text22, null, a.stats.turns, " \u2192 ", b.stats.turns))), prefixLine ? /* @__PURE__ */ React28.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text22, { dimColor: true, italic: true }, prefixLine)) : null);
|
|
15012
15303
|
}
|
|
15013
15304
|
function Pane({
|
|
15014
15305
|
label,
|
|
15015
15306
|
headerColor,
|
|
15016
15307
|
records
|
|
15017
15308
|
}) {
|
|
15018
|
-
return /* @__PURE__ */
|
|
15019
|
-
|
|
15309
|
+
return /* @__PURE__ */ React28.createElement(
|
|
15310
|
+
Box25,
|
|
15020
15311
|
{
|
|
15021
15312
|
flexDirection: "column",
|
|
15022
15313
|
flexGrow: 1,
|
|
@@ -15024,21 +15315,21 @@ function Pane({
|
|
|
15024
15315
|
borderStyle: "single",
|
|
15025
15316
|
borderColor: headerColor
|
|
15026
15317
|
},
|
|
15027
|
-
/* @__PURE__ */
|
|
15028
|
-
records.length === 0 ? /* @__PURE__ */
|
|
15318
|
+
/* @__PURE__ */ React28.createElement(Text22, { color: headerColor, bold: true }, label),
|
|
15319
|
+
records.length === 0 ? /* @__PURE__ */ React28.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text22, { dimColor: true, italic: true }, "(no records on this side for this turn)")) : /* @__PURE__ */ React28.createElement(Static2, { items: records.map((rec, i) => ({ key: `${label}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React28.createElement(RecordView, { key, rec, compact: true }))
|
|
15029
15320
|
);
|
|
15030
15321
|
}
|
|
15031
15322
|
function KindBadge({ kind }) {
|
|
15032
15323
|
if (kind === "match") {
|
|
15033
|
-
return /* @__PURE__ */
|
|
15324
|
+
return /* @__PURE__ */ React28.createElement(Text22, { color: "green" }, "\u2713 match");
|
|
15034
15325
|
}
|
|
15035
15326
|
if (kind === "diverge") {
|
|
15036
|
-
return /* @__PURE__ */
|
|
15327
|
+
return /* @__PURE__ */ React28.createElement(Text22, { color: "yellow" }, "\u2605 diverge");
|
|
15037
15328
|
}
|
|
15038
15329
|
if (kind === "only_in_a") {
|
|
15039
|
-
return /* @__PURE__ */
|
|
15330
|
+
return /* @__PURE__ */ React28.createElement(Text22, { color: "blue" }, "\u2190 only in A");
|
|
15040
15331
|
}
|
|
15041
|
-
return /* @__PURE__ */
|
|
15332
|
+
return /* @__PURE__ */ React28.createElement(Text22, { color: "magenta" }, "\u2192 only in B");
|
|
15042
15333
|
}
|
|
15043
15334
|
function paneRecords(pair, side) {
|
|
15044
15335
|
if (!pair) return [];
|
|
@@ -15069,7 +15360,7 @@ markdown report written to ${opts.mdPath}`);
|
|
|
15069
15360
|
return;
|
|
15070
15361
|
}
|
|
15071
15362
|
if (wantTui) {
|
|
15072
|
-
const { waitUntilExit } = render2(
|
|
15363
|
+
const { waitUntilExit } = render2(React29.createElement(DiffApp, { report }), {
|
|
15073
15364
|
exitOnCtrlC: true,
|
|
15074
15365
|
patchConsole: false
|
|
15075
15366
|
});
|
|
@@ -15210,11 +15501,11 @@ function pad2(s, width) {
|
|
|
15210
15501
|
|
|
15211
15502
|
// src/cli/commands/replay.ts
|
|
15212
15503
|
import { render as render3 } from "ink";
|
|
15213
|
-
import
|
|
15504
|
+
import React31 from "react";
|
|
15214
15505
|
|
|
15215
15506
|
// src/cli/ui/ReplayApp.tsx
|
|
15216
|
-
import { Box as
|
|
15217
|
-
import
|
|
15507
|
+
import { Box as Box26, Static as Static3, Text as Text23, useApp as useApp4, useInput as useInput2 } from "ink";
|
|
15508
|
+
import React30, { useMemo as useMemo4, useState as useState14 } from "react";
|
|
15218
15509
|
function ReplayApp({ meta, pages }) {
|
|
15219
15510
|
const { exit: exit2 } = useApp4();
|
|
15220
15511
|
const maxIdx = Math.max(0, pages.length - 1);
|
|
@@ -15254,14 +15545,14 @@ function ReplayApp({ meta, pages }) {
|
|
|
15254
15545
|
const prefixHash = cumStats.prefixHashes.length === 1 ? cumStats.prefixHashes[0].slice(0, 16) : cumStats.prefixHashes.length === 0 ? "(untracked)" : `(churned \xD7${cumStats.prefixHashes.length})`;
|
|
15255
15546
|
const currentPage = pages[idx];
|
|
15256
15547
|
const progressLabel = pages.length === 0 ? "empty transcript" : `turn ${idx + 1} / ${pages.length}`;
|
|
15257
|
-
return /* @__PURE__ */
|
|
15548
|
+
return /* @__PURE__ */ React30.createElement(Box26, { flexDirection: "column" }, /* @__PURE__ */ React30.createElement(
|
|
15258
15549
|
StatsPanel,
|
|
15259
15550
|
{
|
|
15260
15551
|
summary,
|
|
15261
15552
|
model: cumStats.models[0] ?? meta?.model ?? "?",
|
|
15262
15553
|
prefixHash
|
|
15263
15554
|
}
|
|
15264
|
-
), /* @__PURE__ */
|
|
15555
|
+
), /* @__PURE__ */ React30.createElement(Box26, { flexDirection: "column", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React30.createElement(Box26, { justifyContent: "space-between" }, /* @__PURE__ */ React30.createElement(Text23, { color: "cyan", bold: true }, progressLabel), meta ? /* @__PURE__ */ React30.createElement(Text23, { dimColor: true }, meta.source, meta.task ? ` \xB7 ${meta.task}` : "", meta.mode ? ` \xB7 ${meta.mode}` : "") : null), currentPage ? /* @__PURE__ */ React30.createElement(Static3, { items: currentPage.records.map((rec, i) => ({ key: `${idx}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React30.createElement(RecordView, { key, rec })) : /* @__PURE__ */ React30.createElement(Text23, { dimColor: true, italic: true }, "no records")), /* @__PURE__ */ React30.createElement(Box26, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React30.createElement(Text23, { dimColor: true }, /* @__PURE__ */ React30.createElement(Text23, { bold: true }, "j"), "/", /* @__PURE__ */ React30.createElement(Text23, { bold: true }, "\u2193"), "/", /* @__PURE__ */ React30.createElement(Text23, { bold: true }, "space"), " next \xB7 ", /* @__PURE__ */ React30.createElement(Text23, { bold: true }, "k"), "/", /* @__PURE__ */ React30.createElement(Text23, { bold: true }, "\u2191"), " prev \xB7 ", /* @__PURE__ */ React30.createElement(Text23, { bold: true }, "g"), " first \xB7 ", /* @__PURE__ */ React30.createElement(Text23, { bold: true }, "G"), " last \xB7", " ", /* @__PURE__ */ React30.createElement(Text23, { bold: true }, "q"), " quit")));
|
|
15265
15556
|
}
|
|
15266
15557
|
|
|
15267
15558
|
// src/cli/commands/replay.ts
|
|
@@ -15273,7 +15564,7 @@ async function replayCommand(opts) {
|
|
|
15273
15564
|
}
|
|
15274
15565
|
const { parsed } = replayFromFile(opts.path);
|
|
15275
15566
|
const pages = groupRecordsByTurn(parsed.records);
|
|
15276
|
-
const { waitUntilExit } = render3(
|
|
15567
|
+
const { waitUntilExit } = render3(React31.createElement(ReplayApp, { meta: parsed.meta, pages }), {
|
|
15277
15568
|
exitOnCtrlC: true,
|
|
15278
15569
|
patchConsole: false
|
|
15279
15570
|
});
|
|
@@ -15578,12 +15869,12 @@ function truncate3(s, max) {
|
|
|
15578
15869
|
|
|
15579
15870
|
// src/cli/commands/setup.tsx
|
|
15580
15871
|
import { render as render4 } from "ink";
|
|
15581
|
-
import
|
|
15872
|
+
import React33 from "react";
|
|
15582
15873
|
|
|
15583
15874
|
// src/cli/ui/Wizard.tsx
|
|
15584
|
-
import { Box as
|
|
15875
|
+
import { Box as Box27, Text as Text24, useApp as useApp5, useInput as useInput3 } from "ink";
|
|
15585
15876
|
import TextInput2 from "ink-text-input";
|
|
15586
|
-
import
|
|
15877
|
+
import React32, { useState as useState15 } from "react";
|
|
15587
15878
|
|
|
15588
15879
|
// src/cli/ui/presets.ts
|
|
15589
15880
|
var PRESETS = {
|
|
@@ -15631,7 +15922,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
15631
15922
|
if (key.escape && step !== "saved" && onCancel) onCancel();
|
|
15632
15923
|
});
|
|
15633
15924
|
if (step === "apiKey") {
|
|
15634
|
-
return /* @__PURE__ */
|
|
15925
|
+
return /* @__PURE__ */ React32.createElement(
|
|
15635
15926
|
ApiKeyStep,
|
|
15636
15927
|
{
|
|
15637
15928
|
onSubmit: (key) => {
|
|
@@ -15645,7 +15936,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
15645
15936
|
);
|
|
15646
15937
|
}
|
|
15647
15938
|
if (step === "preset") {
|
|
15648
|
-
return /* @__PURE__ */
|
|
15939
|
+
return /* @__PURE__ */ React32.createElement(StepFrame, { title: "Pick a preset", step: 1, total: 3 }, /* @__PURE__ */ React32.createElement(
|
|
15649
15940
|
SingleSelect,
|
|
15650
15941
|
{
|
|
15651
15942
|
items: presetItems(),
|
|
@@ -15655,10 +15946,10 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
15655
15946
|
setStep("mcp");
|
|
15656
15947
|
}
|
|
15657
15948
|
}
|
|
15658
|
-
), /* @__PURE__ */
|
|
15949
|
+
), /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text24, { dimColor: true }, "[\u2191\u2193] navigate \xB7 [Enter] confirm \xB7 [Esc] cancel")));
|
|
15659
15950
|
}
|
|
15660
15951
|
if (step === "mcp") {
|
|
15661
|
-
return /* @__PURE__ */
|
|
15952
|
+
return /* @__PURE__ */ React32.createElement(StepFrame, { title: "Which MCP servers should Reasonix wire up for you?", step: 2, total: 3 }, /* @__PURE__ */ React32.createElement(
|
|
15662
15953
|
MultiSelect,
|
|
15663
15954
|
{
|
|
15664
15955
|
items: mcpItems(),
|
|
@@ -15683,7 +15974,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
15683
15974
|
}
|
|
15684
15975
|
const currentName = pending[0];
|
|
15685
15976
|
const entry = CATALOG_BY_NAME.get(currentName);
|
|
15686
|
-
return /* @__PURE__ */
|
|
15977
|
+
return /* @__PURE__ */ React32.createElement(
|
|
15687
15978
|
McpArgsStep,
|
|
15688
15979
|
{
|
|
15689
15980
|
entry,
|
|
@@ -15701,7 +15992,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
15701
15992
|
}
|
|
15702
15993
|
if (step === "review") {
|
|
15703
15994
|
const specs = data.selectedCatalog.map((name) => buildSpec(name, data.catalogArgs));
|
|
15704
|
-
return /* @__PURE__ */
|
|
15995
|
+
return /* @__PURE__ */ React32.createElement(StepFrame, { title: "Ready to save", step: 3, total: 3 }, /* @__PURE__ */ React32.createElement(Box27, { flexDirection: "column" }, /* @__PURE__ */ React32.createElement(SummaryLine, { label: "API key", value: redactKey(data.apiKey) }), /* @__PURE__ */ React32.createElement(SummaryLine, { label: "Preset", value: data.preset }), /* @__PURE__ */ React32.createElement(
|
|
15705
15996
|
SummaryLine,
|
|
15706
15997
|
{
|
|
15707
15998
|
label: "MCP",
|
|
@@ -15709,8 +16000,8 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
15709
16000
|
}
|
|
15710
16001
|
), specs.map((spec, i) => (
|
|
15711
16002
|
// biome-ignore lint/suspicious/noArrayIndexKey: review-only render, order fixed
|
|
15712
|
-
/* @__PURE__ */
|
|
15713
|
-
)), /* @__PURE__ */
|
|
16003
|
+
/* @__PURE__ */ React32.createElement(Box27, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React32.createElement(Text24, { dimColor: true }, "\xB7 ", spec))
|
|
16004
|
+
)), /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text24, null, "Saves to ", defaultConfigPath())), error ? /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text24, { color: "red" }, error)) : null, /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text24, { dimColor: true }, "[Enter] save \xB7 [Esc] cancel"))), /* @__PURE__ */ React32.createElement(
|
|
15714
16005
|
ReviewConfirm,
|
|
15715
16006
|
{
|
|
15716
16007
|
onConfirm: () => {
|
|
@@ -15736,7 +16027,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
15736
16027
|
}
|
|
15737
16028
|
));
|
|
15738
16029
|
}
|
|
15739
|
-
return /* @__PURE__ */
|
|
16030
|
+
return /* @__PURE__ */ React32.createElement(Box27, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React32.createElement(Text24, { bold: true, color: "green" }, "\u25B8 Saved."), /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text24, null, "Run `reasonix` any time to start chatting \u2014 your settings are remembered.")), /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text24, { dimColor: true }, "[Enter] to exit")), /* @__PURE__ */ React32.createElement(ExitOnEnter, { onExit: exit2 }));
|
|
15740
16031
|
}
|
|
15741
16032
|
function ApiKeyStep({
|
|
15742
16033
|
onSubmit,
|
|
@@ -15744,7 +16035,7 @@ function ApiKeyStep({
|
|
|
15744
16035
|
onError
|
|
15745
16036
|
}) {
|
|
15746
16037
|
const [value, setValue] = useState15("");
|
|
15747
|
-
return /* @__PURE__ */
|
|
16038
|
+
return /* @__PURE__ */ React32.createElement(Box27, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React32.createElement(Text24, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text24, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React32.createElement(Text24, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React32.createElement(Text24, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text24, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React32.createElement(
|
|
15748
16039
|
TextInput2,
|
|
15749
16040
|
{
|
|
15750
16041
|
value,
|
|
@@ -15761,7 +16052,7 @@ function ApiKeyStep({
|
|
|
15761
16052
|
mask: "\u2022",
|
|
15762
16053
|
placeholder: "sk-..."
|
|
15763
16054
|
}
|
|
15764
|
-
)), error ? /* @__PURE__ */
|
|
16055
|
+
)), error ? /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text24, { color: "red" }, error)) : value ? /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text24, { dimColor: true }, "preview: ", redactKey(value))) : null);
|
|
15765
16056
|
}
|
|
15766
16057
|
function McpArgsStep({
|
|
15767
16058
|
entry,
|
|
@@ -15770,7 +16061,7 @@ function McpArgsStep({
|
|
|
15770
16061
|
onError
|
|
15771
16062
|
}) {
|
|
15772
16063
|
const [value, setValue] = useState15("");
|
|
15773
|
-
return /* @__PURE__ */
|
|
16064
|
+
return /* @__PURE__ */ React32.createElement(StepFrame, { title: `Configure ${entry.name}`, step: 2, total: 3 }, /* @__PURE__ */ React32.createElement(Box27, { flexDirection: "column" }, /* @__PURE__ */ React32.createElement(Text24, null, entry.summary), entry.note ? /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text24, { dimColor: true }, entry.note)) : null, /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text24, null, "Required parameter: "), /* @__PURE__ */ React32.createElement(Text24, { bold: true }, entry.userArgs)), /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text24, { bold: true, color: "cyan" }, entry.userArgs, " \u203A "), /* @__PURE__ */ React32.createElement(
|
|
15774
16065
|
TextInput2,
|
|
15775
16066
|
{
|
|
15776
16067
|
value,
|
|
@@ -15786,7 +16077,7 @@ function McpArgsStep({
|
|
|
15786
16077
|
},
|
|
15787
16078
|
placeholder: placeholderFor(entry)
|
|
15788
16079
|
}
|
|
15789
|
-
)), error ? /* @__PURE__ */
|
|
16080
|
+
)), error ? /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text24, { color: "red" }, error)) : null));
|
|
15790
16081
|
}
|
|
15791
16082
|
function ReviewConfirm({ onConfirm }) {
|
|
15792
16083
|
useInput3((_i, key) => {
|
|
@@ -15806,10 +16097,10 @@ function StepFrame({
|
|
|
15806
16097
|
total,
|
|
15807
16098
|
children
|
|
15808
16099
|
}) {
|
|
15809
|
-
return /* @__PURE__ */
|
|
16100
|
+
return /* @__PURE__ */ React32.createElement(Box27, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React32.createElement(Box27, null, /* @__PURE__ */ React32.createElement(Text24, { dimColor: true }, "Step ", step, "/", total, " \xB7", " "), /* @__PURE__ */ React32.createElement(Text24, { bold: true, color: "cyan" }, title)), /* @__PURE__ */ React32.createElement(Box27, { marginTop: 1, flexDirection: "column" }, children));
|
|
15810
16101
|
}
|
|
15811
16102
|
function SummaryLine({ label, value }) {
|
|
15812
|
-
return /* @__PURE__ */
|
|
16103
|
+
return /* @__PURE__ */ React32.createElement(Box27, null, /* @__PURE__ */ React32.createElement(Text24, null, label.padEnd(12)), /* @__PURE__ */ React32.createElement(Text24, { bold: true }, value));
|
|
15813
16104
|
}
|
|
15814
16105
|
function presetItems() {
|
|
15815
16106
|
return ["fast", "smart", "max"].map((name) => ({
|
|
@@ -15865,7 +16156,7 @@ async function setupCommand(_opts = {}) {
|
|
|
15865
16156
|
const existingKey = loadApiKey();
|
|
15866
16157
|
const existing = readConfig();
|
|
15867
16158
|
const { waitUntilExit, unmount } = render4(
|
|
15868
|
-
/* @__PURE__ */
|
|
16159
|
+
/* @__PURE__ */ React33.createElement(
|
|
15869
16160
|
Wizard,
|
|
15870
16161
|
{
|
|
15871
16162
|
existingApiKey: existingKey,
|