reasonix 0.20.0 → 0.21.0
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 +707 -489
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +15 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1286,6 +1286,39 @@ function hasDotKey(obj) {
|
|
|
1286
1286
|
return false;
|
|
1287
1287
|
}
|
|
1288
1288
|
|
|
1289
|
+
// src/mcp/latency.ts
|
|
1290
|
+
var SAMPLE_SIZE = 5;
|
|
1291
|
+
var DEFAULT_THRESHOLD_MS = 4e3;
|
|
1292
|
+
var LatencyTracker = class {
|
|
1293
|
+
constructor(serverName, opts = {}) {
|
|
1294
|
+
this.serverName = serverName;
|
|
1295
|
+
this.thresholdMs = opts.thresholdMs ?? DEFAULT_THRESHOLD_MS;
|
|
1296
|
+
this.onSlow = opts.onSlow;
|
|
1297
|
+
}
|
|
1298
|
+
serverName;
|
|
1299
|
+
samples = [];
|
|
1300
|
+
wasOverThreshold = false;
|
|
1301
|
+
thresholdMs;
|
|
1302
|
+
onSlow;
|
|
1303
|
+
record(elapsedMs) {
|
|
1304
|
+
this.samples.push(elapsedMs);
|
|
1305
|
+
if (this.samples.length > SAMPLE_SIZE) this.samples.shift();
|
|
1306
|
+
if (this.samples.length < SAMPLE_SIZE) return;
|
|
1307
|
+
const p95 = computeP95(this.samples);
|
|
1308
|
+
const nowOver = p95 > this.thresholdMs;
|
|
1309
|
+
if (nowOver && !this.wasOverThreshold) {
|
|
1310
|
+
this.onSlow?.({ serverName: this.serverName, p95Ms: p95, sampleSize: this.samples.length });
|
|
1311
|
+
}
|
|
1312
|
+
this.wasOverThreshold = nowOver;
|
|
1313
|
+
}
|
|
1314
|
+
};
|
|
1315
|
+
function computeP95(samples) {
|
|
1316
|
+
if (samples.length === 0) return 0;
|
|
1317
|
+
const sorted = [...samples].sort((a, b) => a - b);
|
|
1318
|
+
const idx = Math.min(sorted.length - 1, Math.floor(sorted.length * 0.95));
|
|
1319
|
+
return sorted[idx] ?? 0;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1289
1322
|
// src/mcp/registry.ts
|
|
1290
1323
|
var DEFAULT_MAX_RESULT_CHARS = 32e3;
|
|
1291
1324
|
var DEFAULT_MAX_RESULT_TOKENS = 8e3;
|
|
@@ -1294,6 +1327,8 @@ async function bridgeMcpTools(client, opts = {}) {
|
|
|
1294
1327
|
const prefix = opts.namePrefix ?? "";
|
|
1295
1328
|
const maxResultChars = opts.maxResultChars ?? DEFAULT_MAX_RESULT_CHARS;
|
|
1296
1329
|
const result = { registry, registeredNames: [], skipped: [] };
|
|
1330
|
+
const serverName = opts.serverName ?? prefix.replace(/_$/, "") ?? "anon";
|
|
1331
|
+
const tracker = opts.onSlow ? new LatencyTracker(serverName, { thresholdMs: opts.slowThresholdMs, onSlow: opts.onSlow }) : null;
|
|
1297
1332
|
const listed = await client.listTools();
|
|
1298
1333
|
for (const mcpTool of listed.tools) {
|
|
1299
1334
|
if (!mcpTool.name) {
|
|
@@ -1306,6 +1341,7 @@ async function bridgeMcpTools(client, opts = {}) {
|
|
|
1306
1341
|
description: mcpTool.description ?? "",
|
|
1307
1342
|
parameters: mcpTool.inputSchema,
|
|
1308
1343
|
fn: async (args, ctx) => {
|
|
1344
|
+
const t0 = tracker ? Date.now() : 0;
|
|
1309
1345
|
const toolResult = await client.callTool(mcpTool.name, args, {
|
|
1310
1346
|
// Forward server-side progress frames to the bridge caller,
|
|
1311
1347
|
// tagged with the registered name so multi-server UIs can
|
|
@@ -1319,6 +1355,7 @@ async function bridgeMcpTools(client, opts = {}) {
|
|
|
1319
1355
|
// pending promise immediately, no "wait for subprocess".
|
|
1320
1356
|
signal: ctx?.signal
|
|
1321
1357
|
});
|
|
1358
|
+
if (tracker) tracker.record(Date.now() - t0);
|
|
1322
1359
|
return flattenMcpResult(toolResult, { maxChars: maxResultChars });
|
|
1323
1360
|
}
|
|
1324
1361
|
});
|
|
@@ -7591,11 +7628,11 @@ function formatLogSize(path5 = defaultUsageLogPath()) {
|
|
|
7591
7628
|
|
|
7592
7629
|
// src/cli/commands/chat.tsx
|
|
7593
7630
|
import { render } from "ink";
|
|
7594
|
-
import
|
|
7631
|
+
import React56, { useState as useState17 } from "react";
|
|
7595
7632
|
|
|
7596
7633
|
// src/cli/ui/App.tsx
|
|
7597
|
-
import { Box as
|
|
7598
|
-
import
|
|
7634
|
+
import { Box as Box46, Text as Text48, useStdout as useStdout14 } from "ink";
|
|
7635
|
+
import React54, { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMemo6, useRef as useRef6, useState as useState15 } from "react";
|
|
7599
7636
|
|
|
7600
7637
|
// src/adapters/event-sink-jsonl.ts
|
|
7601
7638
|
import { chmodSync as chmodSync3, createWriteStream as createWriteStream2, mkdirSync as mkdirSync6 } from "fs";
|
|
@@ -12938,17 +12975,59 @@ function EditConfirm({ block: block2, onChoose }) {
|
|
|
12938
12975
|
);
|
|
12939
12976
|
}
|
|
12940
12977
|
|
|
12978
|
+
// src/cli/ui/McpBrowser.tsx
|
|
12979
|
+
import { Box as Box7, Text as Text7 } from "ink";
|
|
12980
|
+
import React9, { useState as useState4 } from "react";
|
|
12981
|
+
function McpBrowser({ servers, configPath, onClose }) {
|
|
12982
|
+
const [index, setIndex] = useState4(0);
|
|
12983
|
+
const max = Math.max(0, servers.length - 1);
|
|
12984
|
+
useKeystroke((ev) => {
|
|
12985
|
+
if (ev.paste) return;
|
|
12986
|
+
if (ev.upArrow) setIndex((i) => Math.max(0, i - 1));
|
|
12987
|
+
else if (ev.downArrow) setIndex((i) => Math.min(max, i + 1));
|
|
12988
|
+
else if (ev.escape) onClose();
|
|
12989
|
+
});
|
|
12990
|
+
return /* @__PURE__ */ React9.createElement(Box7, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React9.createElement(Box7, null, /* @__PURE__ */ React9.createElement(Text7, { bold: true, color: COLOR.brand }, "\u25C8 MCP browser"), /* @__PURE__ */ React9.createElement(
|
|
12991
|
+
Text7,
|
|
12992
|
+
{
|
|
12993
|
+
dimColor: true
|
|
12994
|
+
},
|
|
12995
|
+
` \xB7 ${configPath} \xB7 ${servers.length} server${servers.length === 1 ? "" : "s"}`
|
|
12996
|
+
)), /* @__PURE__ */ React9.createElement(Box7, { marginTop: 1, flexDirection: "column" }, servers.length === 0 ? /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "No MCP servers attached. Run `reasonix setup` to pick some, or launch with --mcp.") : servers.map((s, i) => /* @__PURE__ */ React9.createElement(ServerRow, { key: s.label + s.spec, server: s, active: i === index }))), /* @__PURE__ */ React9.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "\u2191\u2193 pick \xB7 [r] reconnect (Stage C) \xB7 [d] disable (Stage C) \xB7 esc quit")));
|
|
12997
|
+
}
|
|
12998
|
+
function ServerRow({ server, active }) {
|
|
12999
|
+
const { label, toolCount, report } = server;
|
|
13000
|
+
const resourceCount = report.resources.supported ? report.resources.items.length : 0;
|
|
13001
|
+
const promptCount = report.prompts.supported ? report.prompts.items.length : 0;
|
|
13002
|
+
const elapsed = report.elapsedMs;
|
|
13003
|
+
const health = healthBadge(elapsed);
|
|
13004
|
+
const counts = `${toolCount} tools \xB7 ${resourceCount} resources \xB7 ${promptCount} prompts`;
|
|
13005
|
+
return /* @__PURE__ */ React9.createElement(Box7, { flexDirection: "column", marginBottom: active ? 1 : 0 }, /* @__PURE__ */ React9.createElement(Box7, null, /* @__PURE__ */ React9.createElement(Text7, { color: active ? COLOR.brand : void 0 }, active ? "\u25B8 " : " "), /* @__PURE__ */ React9.createElement(Text7, { bold: active, color: active ? "#e6edf3" : void 0 }, label.padEnd(14)), /* @__PURE__ */ React9.createElement(Text7, { color: health.color }, `${health.glyph} ${health.label}`), /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, ` ${counts}`)), active ? /* @__PURE__ */ React9.createElement(Box7, null, /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, ` ${capabilityList(server)}`)) : null);
|
|
13006
|
+
}
|
|
13007
|
+
function healthBadge(elapsedMs) {
|
|
13008
|
+
if (elapsedMs === 0) return { glyph: "\u2717", label: "no inspect data", color: COLOR.err };
|
|
13009
|
+
if (elapsedMs < 500) return { glyph: "\u25CF", label: `healthy \xB7 ${elapsedMs}ms`, color: COLOR.ok };
|
|
13010
|
+
if (elapsedMs < 3e3) return { glyph: "\u25CC", label: `slow \xB7 ${elapsedMs}ms`, color: COLOR.warn };
|
|
13011
|
+
return { glyph: "\u2717", label: `very slow \xB7 ${elapsedMs}ms`, color: COLOR.err };
|
|
13012
|
+
}
|
|
13013
|
+
function capabilityList(s) {
|
|
13014
|
+
const caps = ["tools/list", "tools/call"];
|
|
13015
|
+
if (s.report.resources.supported) caps.push("resources/list");
|
|
13016
|
+
if (s.report.prompts.supported) caps.push("prompts/list");
|
|
13017
|
+
return caps.join(" ");
|
|
13018
|
+
}
|
|
13019
|
+
|
|
12941
13020
|
// src/cli/ui/PlanCheckpointConfirm.tsx
|
|
12942
|
-
import { Box as
|
|
12943
|
-
import
|
|
13021
|
+
import { Box as Box10 } from "ink";
|
|
13022
|
+
import React12 from "react";
|
|
12944
13023
|
|
|
12945
13024
|
// src/cli/ui/PlanStepList.tsx
|
|
12946
|
-
import { Box as
|
|
12947
|
-
import
|
|
13025
|
+
import { Box as Box9, Text as Text9 } from "ink";
|
|
13026
|
+
import React11 from "react";
|
|
12948
13027
|
|
|
12949
13028
|
// src/cli/ui/char-bar.tsx
|
|
12950
|
-
import { Box as
|
|
12951
|
-
import
|
|
13029
|
+
import { Box as Box8, Text as Text8 } from "ink";
|
|
13030
|
+
import React10 from "react";
|
|
12952
13031
|
function CharBar({
|
|
12953
13032
|
pct: pct2,
|
|
12954
13033
|
width = 24,
|
|
@@ -12960,7 +13039,7 @@ function CharBar({
|
|
|
12960
13039
|
const total = Math.max(4, width);
|
|
12961
13040
|
const clamped = Math.max(0, Math.min(100, Number.isFinite(pct2) ? pct2 : 0));
|
|
12962
13041
|
const filled = Math.round(total * clamped / 100);
|
|
12963
|
-
return /* @__PURE__ */
|
|
13042
|
+
return /* @__PURE__ */ React10.createElement(Box8, null, /* @__PURE__ */ React10.createElement(Text8, { color: color2 }, GLYPH.block.repeat(filled)), /* @__PURE__ */ React10.createElement(Text8, { color: emptyColor ?? COLOR.info, dimColor: true }, GLYPH.shade1.repeat(total - filled)), showLabel ? /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, ` ${label ?? `${Math.round(clamped)}%`}`) : null);
|
|
12964
13043
|
}
|
|
12965
13044
|
|
|
12966
13045
|
// src/cli/ui/PlanStepList.tsx
|
|
@@ -12990,25 +13069,25 @@ function PlanStepListInner({ steps, statuses, focusStepId }) {
|
|
|
12990
13069
|
const doneCount = statusList.filter((s) => s === "done").length;
|
|
12991
13070
|
const pct2 = Math.round(doneCount / total * 100);
|
|
12992
13071
|
const showProgress = doneCount > 0;
|
|
12993
|
-
return /* @__PURE__ */
|
|
13072
|
+
return /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, showProgress ? `${doneCount}/${total} done (${pct2}%) \xB7 ${total} step${total === 1 ? "" : "s"}` : `${total} step${total === 1 ? "" : "s"}`)), /* @__PURE__ */ React11.createElement(Box9, { flexDirection: "column" }, steps.map((step, i) => {
|
|
12994
13073
|
const status3 = statusList[i];
|
|
12995
13074
|
const isLast = i === total - 1;
|
|
12996
13075
|
const isCur = focusStepId === step.id;
|
|
12997
13076
|
const sg = statusGlyph(status3, isCur);
|
|
12998
13077
|
const risk = riskLabel(step.risk);
|
|
12999
13078
|
const titleDim = status3 === "done" || status3 === "skipped";
|
|
13000
|
-
return /* @__PURE__ */
|
|
13001
|
-
|
|
13079
|
+
return /* @__PURE__ */ React11.createElement(Box9, { key: step.id }, /* @__PURE__ */ React11.createElement(Text9, { color: COLOR.info, dimColor: true }, isLast ? GLYPH.branchEnd : GLYPH.branch), /* @__PURE__ */ React11.createElement(Text9, null, " "), /* @__PURE__ */ React11.createElement(Text9, { color: sg.color, bold: status3 === "running" || isCur }, sg.glyph), /* @__PURE__ */ React11.createElement(Text9, null, " "), /* @__PURE__ */ React11.createElement(
|
|
13080
|
+
Text9,
|
|
13002
13081
|
{
|
|
13003
13082
|
dimColor: titleDim,
|
|
13004
13083
|
bold: isCur || status3 === "running",
|
|
13005
13084
|
strikethrough: status3 === "done" || status3 === "skipped"
|
|
13006
13085
|
},
|
|
13007
13086
|
`${step.id} \xB7 ${step.title}`
|
|
13008
|
-
), risk ? /* @__PURE__ */
|
|
13009
|
-
})), showProgress ? /* @__PURE__ */
|
|
13087
|
+
), risk ? /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(Text9, null, " "), /* @__PURE__ */ React11.createElement(Text9, { color: risk.color }, risk.text)) : null);
|
|
13088
|
+
})), showProgress ? /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(Text9, null, " "), /* @__PURE__ */ React11.createElement(CharBar, { pct: pct2, width: 24 })) : null);
|
|
13010
13089
|
}
|
|
13011
|
-
var PlanStepList =
|
|
13090
|
+
var PlanStepList = React11.memo(PlanStepListInner);
|
|
13012
13091
|
|
|
13013
13092
|
// src/cli/ui/PlanCheckpointConfirm.tsx
|
|
13014
13093
|
function PlanCheckpointConfirmInner({
|
|
@@ -13025,7 +13104,7 @@ function PlanCheckpointConfirmInner({
|
|
|
13025
13104
|
const isLast = total > 0 && completed >= total;
|
|
13026
13105
|
const statuses = buildStatusMap(steps, completedStepIds, stepId, isLast);
|
|
13027
13106
|
const subtitle = counter ? `${counter} \xB7 ${label}` : label;
|
|
13028
|
-
return /* @__PURE__ */
|
|
13107
|
+
return /* @__PURE__ */ React12.createElement(ApprovalCard, { tone: "ok", glyph: "\u26C1", title: "Checkpoint \u2014 step done", metaRight: subtitle }, steps && steps.length > 0 ? /* @__PURE__ */ React12.createElement(Box10, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React12.createElement(PlanStepList, { steps, statuses, focusStepId: stepId })) : null, /* @__PURE__ */ React12.createElement(
|
|
13029
13108
|
SingleSelect,
|
|
13030
13109
|
{
|
|
13031
13110
|
initialValue: isLast ? "stop" : "continue",
|
|
@@ -13051,7 +13130,7 @@ function PlanCheckpointConfirmInner({
|
|
|
13051
13130
|
}
|
|
13052
13131
|
));
|
|
13053
13132
|
}
|
|
13054
|
-
var PlanCheckpointConfirm =
|
|
13133
|
+
var PlanCheckpointConfirm = React12.memo(PlanCheckpointConfirmInner);
|
|
13055
13134
|
function buildStatusMap(steps, completedStepIds, currentStepId, isLast) {
|
|
13056
13135
|
const map = /* @__PURE__ */ new Map();
|
|
13057
13136
|
if (!steps) return map;
|
|
@@ -13067,11 +13146,11 @@ function buildStatusMap(steps, completedStepIds, currentStepId, isLast) {
|
|
|
13067
13146
|
}
|
|
13068
13147
|
|
|
13069
13148
|
// src/cli/ui/PlanConfirm.tsx
|
|
13070
|
-
import { Box as
|
|
13071
|
-
import
|
|
13149
|
+
import { Box as Box11, Text as Text10 } from "ink";
|
|
13150
|
+
import React13 from "react";
|
|
13072
13151
|
function PlanConfirmInner({ plan: plan3, steps, onChoose }) {
|
|
13073
13152
|
const hasOpenQuestions = /^#{1,6}\s*(open[-\s]?questions?|risks?|unknowns?|assumptions?|unclear)/im.test(plan3) || /^#{1,6}\s*(待确认|开放问题|风险|未知|假设|不确定)/im.test(plan3);
|
|
13074
|
-
return /* @__PURE__ */
|
|
13153
|
+
return /* @__PURE__ */ React13.createElement(
|
|
13075
13154
|
ApprovalCard,
|
|
13076
13155
|
{
|
|
13077
13156
|
tone: "accent",
|
|
@@ -13080,9 +13159,9 @@ function PlanConfirmInner({ plan: plan3, steps, onChoose }) {
|
|
|
13080
13159
|
metaRight: "awaiting",
|
|
13081
13160
|
metaRightColor: CARD.plan.color
|
|
13082
13161
|
},
|
|
13083
|
-
hasOpenQuestions ? /* @__PURE__ */
|
|
13084
|
-
steps && steps.length > 0 ? /* @__PURE__ */
|
|
13085
|
-
/* @__PURE__ */
|
|
13162
|
+
hasOpenQuestions ? /* @__PURE__ */ React13.createElement(Box11, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text10, { color: TONE.warn }, "\u25B2 the plan flags open questions or risks \u2014 pick ", /* @__PURE__ */ React13.createElement(Text10, { bold: true }, "refine"), " to write concrete answers before the model moves on.")) : null,
|
|
13163
|
+
steps && steps.length > 0 ? /* @__PURE__ */ React13.createElement(Box11, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React13.createElement(PlanStepList, { steps })) : null,
|
|
13164
|
+
/* @__PURE__ */ React13.createElement(
|
|
13086
13165
|
SingleSelect,
|
|
13087
13166
|
{
|
|
13088
13167
|
initialValue: hasOpenQuestions ? "refine" : "approve",
|
|
@@ -13114,21 +13193,21 @@ function PlanConfirmInner({ plan: plan3, steps, onChoose }) {
|
|
|
13114
13193
|
)
|
|
13115
13194
|
);
|
|
13116
13195
|
}
|
|
13117
|
-
var PlanConfirm =
|
|
13196
|
+
var PlanConfirm = React13.memo(PlanConfirmInner);
|
|
13118
13197
|
|
|
13119
13198
|
// src/cli/ui/PlanRefineInput.tsx
|
|
13120
|
-
import { Box as
|
|
13121
|
-
import
|
|
13199
|
+
import { Box as Box12, Text as Text11 } from "ink";
|
|
13200
|
+
import React15, { useState as useState6 } from "react";
|
|
13122
13201
|
|
|
13123
13202
|
// src/cli/ui/ticker.tsx
|
|
13124
|
-
import
|
|
13203
|
+
import React14, { createContext as createContext2, useContext as useContext2, useEffect as useEffect2, useState as useState5 } from "react";
|
|
13125
13204
|
var FAST_TICK_MS = 120;
|
|
13126
13205
|
var SLOW_TICK_MS = 1e3;
|
|
13127
13206
|
var FastTickContext = createContext2(0);
|
|
13128
13207
|
var SlowTickContext = createContext2(0);
|
|
13129
13208
|
function TickerProvider({ children, disabled }) {
|
|
13130
|
-
const [fast, setFast] =
|
|
13131
|
-
const [slow, setSlow] =
|
|
13209
|
+
const [fast, setFast] = useState5(0);
|
|
13210
|
+
const [slow, setSlow] = useState5(0);
|
|
13132
13211
|
useEffect2(() => {
|
|
13133
13212
|
if (disabled) return;
|
|
13134
13213
|
const fastId = setInterval(() => setFast((t2) => t2 + 1), FAST_TICK_MS);
|
|
@@ -13138,7 +13217,7 @@ function TickerProvider({ children, disabled }) {
|
|
|
13138
13217
|
clearInterval(slowId);
|
|
13139
13218
|
};
|
|
13140
13219
|
}, [disabled]);
|
|
13141
|
-
return /* @__PURE__ */
|
|
13220
|
+
return /* @__PURE__ */ React14.createElement(FastTickContext.Provider, { value: fast }, /* @__PURE__ */ React14.createElement(SlowTickContext.Provider, { value: slow }, children));
|
|
13142
13221
|
}
|
|
13143
13222
|
function useTick() {
|
|
13144
13223
|
return useContext2(FastTickContext);
|
|
@@ -13147,7 +13226,7 @@ function useSlowTick() {
|
|
|
13147
13226
|
return useContext2(SlowTickContext);
|
|
13148
13227
|
}
|
|
13149
13228
|
function useElapsedSeconds() {
|
|
13150
|
-
const [start] =
|
|
13229
|
+
const [start] = useState5(() => Date.now());
|
|
13151
13230
|
useSlowTick();
|
|
13152
13231
|
return Math.floor((Date.now() - start) / 1e3);
|
|
13153
13232
|
}
|
|
@@ -13188,7 +13267,7 @@ var MODES = {
|
|
|
13188
13267
|
}
|
|
13189
13268
|
};
|
|
13190
13269
|
function PlanRefineInput({ mode: mode2, onSubmit, onCancel }) {
|
|
13191
|
-
const [value, setValue] =
|
|
13270
|
+
const [value, setValue] = useState6("");
|
|
13192
13271
|
useKeystroke((ev) => {
|
|
13193
13272
|
if (ev.paste) {
|
|
13194
13273
|
setValue((v) => v + ev.input.replace(/\r?\n/g, " "));
|
|
@@ -13213,7 +13292,7 @@ function PlanRefineInput({ mode: mode2, onSubmit, onCancel }) {
|
|
|
13213
13292
|
const tick = useTick();
|
|
13214
13293
|
const cursorOn = Math.floor(tick / 4) % 2 === 0;
|
|
13215
13294
|
const meta = MODES[mode2];
|
|
13216
|
-
return /* @__PURE__ */
|
|
13295
|
+
return /* @__PURE__ */ React15.createElement(
|
|
13217
13296
|
ApprovalCard,
|
|
13218
13297
|
{
|
|
13219
13298
|
tone: meta.tone,
|
|
@@ -13221,14 +13300,14 @@ function PlanRefineInput({ mode: mode2, onSubmit, onCancel }) {
|
|
|
13221
13300
|
title: meta.title,
|
|
13222
13301
|
footerHint: "\u23CE send \xB7 esc return to picker"
|
|
13223
13302
|
},
|
|
13224
|
-
/* @__PURE__ */
|
|
13225
|
-
/* @__PURE__ */
|
|
13303
|
+
/* @__PURE__ */ React15.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text11, { color: FG.sub }, meta.hint, value === "" ? meta.blankHint : "")),
|
|
13304
|
+
/* @__PURE__ */ React15.createElement(Box12, null, /* @__PURE__ */ React15.createElement(Text11, { color: meta.cursorColor, bold: true }, "\u203A "), /* @__PURE__ */ React15.createElement(Text11, null, value), /* @__PURE__ */ React15.createElement(Text11, { color: meta.cursorColor, bold: true }, cursorOn ? "\u258D" : " "))
|
|
13226
13305
|
);
|
|
13227
13306
|
}
|
|
13228
13307
|
|
|
13229
13308
|
// src/cli/ui/PlanReviseConfirm.tsx
|
|
13230
|
-
import { Box as
|
|
13231
|
-
import
|
|
13309
|
+
import { Box as Box13, Text as Text12 } from "ink";
|
|
13310
|
+
import React16 from "react";
|
|
13232
13311
|
function computeDiff(oldSteps, newSteps) {
|
|
13233
13312
|
const oldIds = new Set(oldSteps.map((s) => s.id));
|
|
13234
13313
|
const newIds = new Set(newSteps.map((s) => s.id));
|
|
@@ -13264,7 +13343,7 @@ function PlanReviseConfirmInner({
|
|
|
13264
13343
|
const removedCount = rows.filter((r) => r.kind === "removed").length;
|
|
13265
13344
|
const addedCount = rows.filter((r) => r.kind === "added").length;
|
|
13266
13345
|
const keptCount = rows.filter((r) => r.kind === "kept").length;
|
|
13267
|
-
return /* @__PURE__ */
|
|
13346
|
+
return /* @__PURE__ */ React16.createElement(
|
|
13268
13347
|
ApprovalCard,
|
|
13269
13348
|
{
|
|
13270
13349
|
tone: "warn",
|
|
@@ -13272,17 +13351,17 @@ function PlanReviseConfirmInner({
|
|
|
13272
13351
|
title: "plan revision proposed",
|
|
13273
13352
|
metaRight: `\u2212${removedCount} +${addedCount} \xB7 ${keptCount} kept`
|
|
13274
13353
|
},
|
|
13275
|
-
/* @__PURE__ */
|
|
13276
|
-
summary ? /* @__PURE__ */
|
|
13277
|
-
/* @__PURE__ */
|
|
13354
|
+
/* @__PURE__ */ React16.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text12, null, reason)),
|
|
13355
|
+
summary ? /* @__PURE__ */ React16.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text12, { dimColor: true }, `updated summary: ${summary}`)) : null,
|
|
13356
|
+
/* @__PURE__ */ React16.createElement(Box13, { marginBottom: 1, flexDirection: "column" }, rows.map((row3) => {
|
|
13278
13357
|
const risk = riskDots(row3.step.risk);
|
|
13279
13358
|
const prefix = row3.kind === "removed" ? "\u2212" : row3.kind === "added" ? "+" : " ";
|
|
13280
13359
|
const prefixColor = row3.kind === "removed" ? "#f87171" : row3.kind === "added" ? "#4ade80" : "#94a3b8";
|
|
13281
13360
|
const dim = row3.kind === "kept";
|
|
13282
13361
|
const strike = row3.kind === "removed";
|
|
13283
|
-
return /* @__PURE__ */
|
|
13362
|
+
return /* @__PURE__ */ React16.createElement(Box13, { key: `${row3.kind}-${row3.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 }, ` ${row3.step.id} \xB7 ${row3.step.title}`));
|
|
13284
13363
|
})),
|
|
13285
|
-
/* @__PURE__ */
|
|
13364
|
+
/* @__PURE__ */ React16.createElement(
|
|
13286
13365
|
SingleSelect,
|
|
13287
13366
|
{
|
|
13288
13367
|
initialValue: "accept",
|
|
@@ -13304,22 +13383,22 @@ function PlanReviseConfirmInner({
|
|
|
13304
13383
|
)
|
|
13305
13384
|
);
|
|
13306
13385
|
}
|
|
13307
|
-
var PlanReviseConfirm =
|
|
13386
|
+
var PlanReviseConfirm = React16.memo(PlanReviseConfirmInner);
|
|
13308
13387
|
|
|
13309
13388
|
// src/cli/ui/PlanReviseEditor.tsx
|
|
13310
|
-
import { Box as
|
|
13311
|
-
import
|
|
13389
|
+
import { Box as Box14, Text as Text13 } from "ink";
|
|
13390
|
+
import React17, { useState as useState7 } from "react";
|
|
13312
13391
|
function PlanReviseEditor({
|
|
13313
13392
|
steps,
|
|
13314
13393
|
completedStepIds,
|
|
13315
13394
|
onAccept,
|
|
13316
13395
|
onCancel
|
|
13317
13396
|
}) {
|
|
13318
|
-
const [rows, setRows] =
|
|
13397
|
+
const [rows, setRows] = useState7(
|
|
13319
13398
|
() => steps.map((s) => ({ step: s, done: completedStepIds?.has(s.id) ?? false, skipped: false }))
|
|
13320
13399
|
);
|
|
13321
13400
|
const firstEditableIndex = rows.findIndex((r) => !r.done);
|
|
13322
|
-
const [focus, setFocus] =
|
|
13401
|
+
const [focus, setFocus] = useState7(firstEditableIndex < 0 ? 0 : firstEditableIndex);
|
|
13323
13402
|
useKeystroke((ev) => {
|
|
13324
13403
|
if (ev.paste) return;
|
|
13325
13404
|
if (ev.escape) {
|
|
@@ -13380,7 +13459,7 @@ function PlanReviseEditor({
|
|
|
13380
13459
|
return;
|
|
13381
13460
|
}
|
|
13382
13461
|
});
|
|
13383
|
-
return /* @__PURE__ */
|
|
13462
|
+
return /* @__PURE__ */ React17.createElement(
|
|
13384
13463
|
ApprovalCard,
|
|
13385
13464
|
{
|
|
13386
13465
|
tone: "accent",
|
|
@@ -13389,7 +13468,7 @@ function PlanReviseEditor({
|
|
|
13389
13468
|
metaRight: `${rows.length} steps`,
|
|
13390
13469
|
footerHint: "\u2191\u2193 focus \xB7 space toggle skip \xB7 k/j move \xB7 \u23CE accept \xB7 esc cancel"
|
|
13391
13470
|
},
|
|
13392
|
-
rows.map((r, i) => /* @__PURE__ */
|
|
13471
|
+
rows.map((r, i) => /* @__PURE__ */ React17.createElement(ReviseRow, { key: r.step.id, row: r, index: i, focused: i === focus }))
|
|
13393
13472
|
);
|
|
13394
13473
|
}
|
|
13395
13474
|
function ReviseRow({
|
|
@@ -13400,13 +13479,13 @@ function ReviseRow({
|
|
|
13400
13479
|
const marker = row3.done ? "[\u2713]" : row3.skipped ? "[s]" : focused ? "[ ]" : "[ ]";
|
|
13401
13480
|
const markerColor = row3.done ? TONE.ok : row3.skipped ? FG.faint : focused ? TONE.brand : FG.faint;
|
|
13402
13481
|
const titleColor = row3.done ? FG.sub : row3.skipped ? FG.faint : focused ? FG.strong : FG.sub;
|
|
13403
|
-
const focusGlyph = focused ? /* @__PURE__ */
|
|
13404
|
-
return /* @__PURE__ */
|
|
13482
|
+
const focusGlyph = focused ? /* @__PURE__ */ React17.createElement(Text13, { color: TONE.brand }, "\u25B8 ") : /* @__PURE__ */ React17.createElement(Text13, null, " ");
|
|
13483
|
+
return /* @__PURE__ */ React17.createElement(Box14, null, focusGlyph, /* @__PURE__ */ React17.createElement(Text13, { color: markerColor }, marker), /* @__PURE__ */ React17.createElement(Text13, { color: titleColor, bold: focused, italic: row3.skipped, strikethrough: row3.skipped }, ` ${index + 1}. ${row3.step.title}`), row3.skipped ? /* @__PURE__ */ React17.createElement(Text13, { color: TONE.warn }, " \u2190 skipped") : null);
|
|
13405
13484
|
}
|
|
13406
13485
|
|
|
13407
13486
|
// src/cli/ui/PromptInput.tsx
|
|
13408
|
-
import { Box as
|
|
13409
|
-
import
|
|
13487
|
+
import { Box as Box15, Text as Text14, useStdout as useStdout4 } from "ink";
|
|
13488
|
+
import React18, { useRef as useRef2, useState as useState8 } from "react";
|
|
13410
13489
|
|
|
13411
13490
|
// src/cli/ui/key-normalize.ts
|
|
13412
13491
|
var CSI_TAIL_TO_FLAGS = [
|
|
@@ -13812,7 +13891,7 @@ function PromptInput({
|
|
|
13812
13891
|
onHistoryPrev,
|
|
13813
13892
|
onHistoryNext
|
|
13814
13893
|
}) {
|
|
13815
|
-
const [cursor, setCursor] =
|
|
13894
|
+
const [cursor, setCursor] = useState8(value.length);
|
|
13816
13895
|
const pastesRef = useRef2(/* @__PURE__ */ new Map());
|
|
13817
13896
|
const nextPasteIdRef = useRef2(0);
|
|
13818
13897
|
const lastLocalValueRef = useRef2(value);
|
|
@@ -13899,14 +13978,14 @@ function PromptInput({
|
|
|
13899
13978
|
const { line: cursorLine, col: cursorCol } = lineAndColumn(value, cursor);
|
|
13900
13979
|
const renderItems = collapseLinesForDisplay(lines, cursorLine);
|
|
13901
13980
|
const showHugeBufferHints = lines.length > 20;
|
|
13902
|
-
return /* @__PURE__ */
|
|
13981
|
+
return /* @__PURE__ */ React18.createElement(Box15, { flexDirection: "column", paddingX: 1 }, (() => {
|
|
13903
13982
|
const rows = [];
|
|
13904
13983
|
let firstRowEmitted = false;
|
|
13905
13984
|
for (let renderIdx = 0; renderIdx < renderItems.length; renderIdx++) {
|
|
13906
13985
|
const item = renderItems[renderIdx];
|
|
13907
13986
|
if (item.kind === "skip") {
|
|
13908
13987
|
rows.push(
|
|
13909
|
-
/* @__PURE__ */
|
|
13988
|
+
/* @__PURE__ */ React18.createElement(Box15, { key: `skip-${renderIdx}` }, /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, continuationIndent), /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, `[\u2026 ${item.linesHidden} line${item.linesHidden === 1 ? "" : "s"} hidden \u2014 full content kept, submitted on Enter \u2026]`))
|
|
13910
13989
|
);
|
|
13911
13990
|
continue;
|
|
13912
13991
|
}
|
|
@@ -13916,7 +13995,7 @@ function PromptInput({
|
|
|
13916
13995
|
const showPlaceholder = i === 0 && value.length === 0;
|
|
13917
13996
|
if (showPlaceholder) {
|
|
13918
13997
|
rows.push(
|
|
13919
|
-
/* @__PURE__ */
|
|
13998
|
+
/* @__PURE__ */ React18.createElement(
|
|
13920
13999
|
PromptLine,
|
|
13921
14000
|
{
|
|
13922
14001
|
key: `ln-${i}-text-0`,
|
|
@@ -13947,7 +14026,7 @@ function PromptInput({
|
|
|
13947
14026
|
if (seg.kind === "paste") {
|
|
13948
14027
|
const cursorOnIt = isCursorLine && cursorCol >= seg.startOffset && cursorCol <= seg.startOffset + 1;
|
|
13949
14028
|
rows.push(
|
|
13950
|
-
/* @__PURE__ */
|
|
14029
|
+
/* @__PURE__ */ React18.createElement(
|
|
13951
14030
|
PasteChipRow,
|
|
13952
14031
|
{
|
|
13953
14032
|
key: `ln-${i}-paste-${segIdx}`,
|
|
@@ -13964,7 +14043,7 @@ function PromptInput({
|
|
|
13964
14043
|
}
|
|
13965
14044
|
const segHasCursor = isCursorLine && cursorCol >= seg.startOffset && cursorCol <= seg.startOffset + seg.text.length;
|
|
13966
14045
|
rows.push(
|
|
13967
|
-
/* @__PURE__ */
|
|
14046
|
+
/* @__PURE__ */ React18.createElement(
|
|
13968
14047
|
PromptLine,
|
|
13969
14048
|
{
|
|
13970
14049
|
key: `ln-${i}-text-${segIdx}`,
|
|
@@ -13989,7 +14068,7 @@ function PromptInput({
|
|
|
13989
14068
|
const isFirst = !firstRowEmitted;
|
|
13990
14069
|
firstRowEmitted = true;
|
|
13991
14070
|
rows.push(
|
|
13992
|
-
/* @__PURE__ */
|
|
14071
|
+
/* @__PURE__ */ React18.createElement(
|
|
13993
14072
|
PromptLine,
|
|
13994
14073
|
{
|
|
13995
14074
|
key: `ln-${i}-empty`,
|
|
@@ -14012,7 +14091,7 @@ function PromptInput({
|
|
|
14012
14091
|
}
|
|
14013
14092
|
}
|
|
14014
14093
|
return rows;
|
|
14015
|
-
})(), showHugeBufferHints && !disabled ? /* @__PURE__ */
|
|
14094
|
+
})(), showHugeBufferHints && !disabled ? /* @__PURE__ */ React18.createElement(Box15, null, /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, ` [${lines.length} lines \xB7 PgUp/PgDn jump \xB7 Ctrl+U clear \xB7 Ctrl+W del word]`)) : null, !disabled ? /* @__PURE__ */ React18.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, " \u23CE send \xB7 shift/alt+\u23CE newline \xB7 \u2191\u2193 history \xB7 esc abort \xB7 ctrl-c quit")) : /* @__PURE__ */ React18.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, " esc to stop")));
|
|
14016
14095
|
}
|
|
14017
14096
|
function splitLineByPastes(line) {
|
|
14018
14097
|
const out = [];
|
|
@@ -14049,9 +14128,9 @@ function PasteChipRow({
|
|
|
14049
14128
|
const leadColor = isFirst ? accentColor : FG.faint;
|
|
14050
14129
|
const labelText = formatChipLabel(entry, pasteId, visibleCells - 6);
|
|
14051
14130
|
if (active) {
|
|
14052
|
-
return /* @__PURE__ */
|
|
14131
|
+
return /* @__PURE__ */ React18.createElement(Box15, null, /* @__PURE__ */ React18.createElement(Text14, { bold: true, color: leadColor }, lead), /* @__PURE__ */ React18.createElement(Text14, { bold: true, color: accentColor }, "\u25B8 "), /* @__PURE__ */ React18.createElement(Text14, { bold: true, color: "black", backgroundColor: accentColor }, ` ${labelText} `));
|
|
14053
14132
|
}
|
|
14054
|
-
return /* @__PURE__ */
|
|
14133
|
+
return /* @__PURE__ */ React18.createElement(Box15, null, /* @__PURE__ */ React18.createElement(Text14, { bold: true, color: leadColor }, lead), /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, " "), /* @__PURE__ */ React18.createElement(Text14, { color: FG.meta }, "\u250C "), /* @__PURE__ */ React18.createElement(Text14, { color: FG.body, backgroundColor: SURFACE.bgElev }, `${labelText} `), /* @__PURE__ */ React18.createElement(Text14, { color: FG.meta }, " \u2510"));
|
|
14055
14134
|
}
|
|
14056
14135
|
function formatChipLabel(entry, pasteId, budget3) {
|
|
14057
14136
|
if (!entry) return `\u{1F4CB} paste #${pasteId + 1} \xB7 (missing)`;
|
|
@@ -14095,10 +14174,10 @@ function PromptLine({
|
|
|
14095
14174
|
disabled
|
|
14096
14175
|
}) {
|
|
14097
14176
|
if (showPlaceholder) {
|
|
14098
|
-
return /* @__PURE__ */
|
|
14177
|
+
return /* @__PURE__ */ React18.createElement(Box15, null, /* @__PURE__ */ React18.createElement(Text14, { bold: true, color: accentColor }, promptPrefix), !disabled ? /* @__PURE__ */ React18.createElement(Text14, { color: accentColor }, cursorVisible ? "\u258C" : " ") : null, /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, placeholderText));
|
|
14099
14178
|
}
|
|
14100
14179
|
const viewport = buildViewport(line, isCursorLine ? cursorCol : null, visibleCells, pastes);
|
|
14101
|
-
return /* @__PURE__ */
|
|
14180
|
+
return /* @__PURE__ */ React18.createElement(Box15, null, isFirst ? /* @__PURE__ */ React18.createElement(Text14, { bold: true, color: accentColor }, promptPrefix) : /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, continuationIndent), viewport.hiddenLeft ? /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, "\u2039") : null, /* @__PURE__ */ React18.createElement(
|
|
14102
14181
|
ViewportContent,
|
|
14103
14182
|
{
|
|
14104
14183
|
segments: viewport.segments,
|
|
@@ -14106,7 +14185,7 @@ function PromptLine({
|
|
|
14106
14185
|
accentColor,
|
|
14107
14186
|
cursorVisible
|
|
14108
14187
|
}
|
|
14109
|
-
), viewport.hiddenRight ? /* @__PURE__ */
|
|
14188
|
+
), viewport.hiddenRight ? /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, "\u203A") : null);
|
|
14110
14189
|
}
|
|
14111
14190
|
function ViewportContent({
|
|
14112
14191
|
segments,
|
|
@@ -14115,7 +14194,7 @@ function ViewportContent({
|
|
|
14115
14194
|
cursorVisible
|
|
14116
14195
|
}) {
|
|
14117
14196
|
if (cursorCell === null) {
|
|
14118
|
-
return /* @__PURE__ */
|
|
14197
|
+
return /* @__PURE__ */ React18.createElement(React18.Fragment, null, segments.map((seg, i) => renderSegment(seg, i, false)));
|
|
14119
14198
|
}
|
|
14120
14199
|
const out = [];
|
|
14121
14200
|
let cells = 0;
|
|
@@ -14134,8 +14213,8 @@ function ViewportContent({
|
|
|
14134
14213
|
}
|
|
14135
14214
|
if (seg.kind === "paste") {
|
|
14136
14215
|
out.push(
|
|
14137
|
-
/* @__PURE__ */
|
|
14138
|
-
|
|
14216
|
+
/* @__PURE__ */ React18.createElement(
|
|
14217
|
+
Text14,
|
|
14139
14218
|
{
|
|
14140
14219
|
key: `p-${i}-cursor`,
|
|
14141
14220
|
color: FG.body,
|
|
@@ -14152,29 +14231,29 @@ function ViewportContent({
|
|
|
14152
14231
|
const offsetIntoSeg = cursorCell - cells;
|
|
14153
14232
|
const split = splitTextByCells(seg.text, offsetIntoSeg);
|
|
14154
14233
|
if (split.before.length > 0) {
|
|
14155
|
-
out.push(/* @__PURE__ */
|
|
14234
|
+
out.push(/* @__PURE__ */ React18.createElement(Text14, { key: `t-${i}-b` }, split.before));
|
|
14156
14235
|
}
|
|
14157
14236
|
if (split.atCursor.length > 0) {
|
|
14158
14237
|
out.push(
|
|
14159
|
-
/* @__PURE__ */
|
|
14238
|
+
/* @__PURE__ */ React18.createElement(Text14, { key: `t-${i}-c`, inverse: cursorVisible, color: accentColor }, split.atCursor)
|
|
14160
14239
|
);
|
|
14161
14240
|
} else {
|
|
14162
14241
|
out.push(
|
|
14163
|
-
/* @__PURE__ */
|
|
14242
|
+
/* @__PURE__ */ React18.createElement(Text14, { key: `t-${i}-c-eol`, color: accentColor }, cursorVisible ? "\u258C" : " ")
|
|
14164
14243
|
);
|
|
14165
14244
|
}
|
|
14166
14245
|
if (split.after.length > 0) {
|
|
14167
|
-
out.push(/* @__PURE__ */
|
|
14246
|
+
out.push(/* @__PURE__ */ React18.createElement(Text14, { key: `t-${i}-a` }, split.after));
|
|
14168
14247
|
}
|
|
14169
14248
|
placed = true;
|
|
14170
14249
|
cells += segCells;
|
|
14171
14250
|
}
|
|
14172
14251
|
if (!placed) {
|
|
14173
14252
|
out.push(
|
|
14174
|
-
/* @__PURE__ */
|
|
14253
|
+
/* @__PURE__ */ React18.createElement(Text14, { key: "cursor-eol", color: accentColor }, cursorVisible ? "\u258C" : " ")
|
|
14175
14254
|
);
|
|
14176
14255
|
}
|
|
14177
|
-
return /* @__PURE__ */
|
|
14256
|
+
return /* @__PURE__ */ React18.createElement(React18.Fragment, null, out);
|
|
14178
14257
|
}
|
|
14179
14258
|
function segmentCells(seg) {
|
|
14180
14259
|
if (seg.kind === "paste") return seg.label.length;
|
|
@@ -14214,9 +14293,9 @@ function charCellsForText(ch) {
|
|
|
14214
14293
|
}
|
|
14215
14294
|
function renderSegment(seg, key, _inverse) {
|
|
14216
14295
|
if (seg.kind === "text") {
|
|
14217
|
-
return /* @__PURE__ */
|
|
14296
|
+
return /* @__PURE__ */ React18.createElement(Text14, { key: `s-${key}` }, seg.text);
|
|
14218
14297
|
}
|
|
14219
|
-
return /* @__PURE__ */
|
|
14298
|
+
return /* @__PURE__ */ React18.createElement(Text14, { key: `s-${key}`, backgroundColor: SURFACE.bgElev, color: FG.body }, seg.label);
|
|
14220
14299
|
}
|
|
14221
14300
|
var COLLAPSE_THRESHOLD = 20;
|
|
14222
14301
|
var COLLAPSE_HEAD_LINES = 3;
|
|
@@ -14243,16 +14322,16 @@ function collapseLinesForDisplay(lines, cursorLine) {
|
|
|
14243
14322
|
}
|
|
14244
14323
|
|
|
14245
14324
|
// src/cli/ui/SessionPicker.tsx
|
|
14246
|
-
import { Box as
|
|
14247
|
-
import
|
|
14325
|
+
import { Box as Box16, Text as Text15, useStdout as useStdout5 } from "ink";
|
|
14326
|
+
import React19, { useState as useState9 } from "react";
|
|
14248
14327
|
var PAGE_MARGIN = 6;
|
|
14249
14328
|
function SessionPicker({
|
|
14250
14329
|
sessions: sessions2,
|
|
14251
14330
|
workspace: workspace2,
|
|
14252
14331
|
onChoose
|
|
14253
14332
|
}) {
|
|
14254
|
-
const [focus, setFocus] =
|
|
14255
|
-
const [renaming, setRenaming] =
|
|
14333
|
+
const [focus, setFocus] = useState9(0);
|
|
14334
|
+
const [renaming, setRenaming] = useState9(null);
|
|
14256
14335
|
const { stdout: stdout4 } = useStdout5();
|
|
14257
14336
|
const rows = stdout4?.rows ?? 40;
|
|
14258
14337
|
const visibleCount = Math.max(3, rows - PAGE_MARGIN);
|
|
@@ -14306,7 +14385,7 @@ function SessionPicker({
|
|
|
14306
14385
|
const end = Math.min(sessions2.length, start + visibleCount);
|
|
14307
14386
|
const shown = sessions2.slice(start, end);
|
|
14308
14387
|
const hiddenBelow = sessions2.length - end;
|
|
14309
|
-
return /* @__PURE__ */
|
|
14388
|
+
return /* @__PURE__ */ React19.createElement(Box16, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React19.createElement(Box16, null, /* @__PURE__ */ React19.createElement(Text15, { bold: true, color: TONE.brand }, " \u25C8 REASONIX \xB7 pick a session "), /* @__PURE__ */ React19.createElement(Text15, { color: FG.meta }, ` \xB7 ${workspace2}`)), /* @__PURE__ */ React19.createElement(Box16, { height: 1 }), sessions2.length === 0 ? /* @__PURE__ */ React19.createElement(Box16, null, /* @__PURE__ */ React19.createElement(Text15, { color: FG.faint }, " no saved sessions in this workspace yet \u2014 press "), /* @__PURE__ */ React19.createElement(Text15, { bold: true, color: TONE.brand }, "\u23CE"), /* @__PURE__ */ React19.createElement(Text15, { color: FG.faint }, " to start a new one")) : shown.map((s, i) => /* @__PURE__ */ React19.createElement(SessionRow, { key: s.name, info: s, focused: start + i === focus })), hiddenBelow > 0 ? /* @__PURE__ */ React19.createElement(Box16, null, /* @__PURE__ */ React19.createElement(Text15, { color: FG.faint }, ` \u2026 ${hiddenBelow} more`)) : null, renaming ? /* @__PURE__ */ React19.createElement(Box16, { marginTop: 1 }, /* @__PURE__ */ React19.createElement(Text15, { color: FG.faint }, ` rename "${renaming.from}" \u2192 `), /* @__PURE__ */ React19.createElement(Text15, { bold: true, color: TONE.brand }, renaming.buf), /* @__PURE__ */ React19.createElement(Text15, { backgroundColor: TONE.brand, color: "black" }, " ")) : null, /* @__PURE__ */ React19.createElement(Box16, { marginTop: 1 }, /* @__PURE__ */ React19.createElement(Text15, { color: FG.faint }, renaming ? " \u23CE confirm rename \xB7 esc cancel" : sessions2.length === 0 ? " \u23CE new session \xB7 esc quit" : " \u2191\u2193 pick \xB7 \u23CE open \xB7 [n] new \xB7 [d] delete \xB7 [r] rename \xB7 esc quit")));
|
|
14310
14389
|
}
|
|
14311
14390
|
function SessionRow({
|
|
14312
14391
|
info,
|
|
@@ -14317,7 +14396,7 @@ function SessionRow({
|
|
|
14317
14396
|
const turns = info.meta.turnCount ?? Math.ceil(info.messageCount / 2);
|
|
14318
14397
|
const costCny = info.meta.totalCostUsd !== void 0 ? `\xA5${(info.meta.totalCostUsd * USD_TO_CNY).toFixed(2)}` : "";
|
|
14319
14398
|
const time = relativeTime2(info.mtime);
|
|
14320
|
-
return /* @__PURE__ */
|
|
14399
|
+
return /* @__PURE__ */ React19.createElement(Box16, null, /* @__PURE__ */ React19.createElement(Text15, { color: focused ? TONE.brand : FG.faint }, focused ? " \u25B8 " : " "), /* @__PURE__ */ React19.createElement(Text15, { bold: focused, color: focused ? FG.strong : FG.sub }, info.name.padEnd(12)), /* @__PURE__ */ React19.createElement(Text15, { color: FG.meta }, ` \xB7 ${branch2.padEnd(8)} \xB7 `), /* @__PURE__ */ React19.createElement(Text15, { color: focused ? FG.body : FG.sub }, truncate2(summary, 40)), /* @__PURE__ */ React19.createElement(Box16, { flexGrow: 1 }), /* @__PURE__ */ React19.createElement(Text15, { color: FG.faint }, `${time.padStart(11)} `), /* @__PURE__ */ React19.createElement(Text15, { color: FG.faint }, `${turns} turns`), costCny ? /* @__PURE__ */ React19.createElement(Text15, { color: FG.faint }, ` \xB7 ${costCny}`) : null);
|
|
14321
14400
|
}
|
|
14322
14401
|
function truncate2(s, max) {
|
|
14323
14402
|
if (s.length <= max) return s;
|
|
@@ -14337,14 +14416,14 @@ function relativeTime2(date) {
|
|
|
14337
14416
|
}
|
|
14338
14417
|
|
|
14339
14418
|
// src/cli/ui/ShellConfirm.tsx
|
|
14340
|
-
import { Box as
|
|
14341
|
-
import
|
|
14419
|
+
import { Box as Box17, Text as Text16 } from "ink";
|
|
14420
|
+
import React20, { useState as useState10 } from "react";
|
|
14342
14421
|
function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
|
|
14343
14422
|
const isBackground = kind === "run_background";
|
|
14344
14423
|
const subtitle = isBackground ? "long-running process \u2014 keeps running after approval, /kill to stop" : "model wants to run a shell command";
|
|
14345
|
-
const [phase, setPhase] =
|
|
14424
|
+
const [phase, setPhase] = useState10("pick");
|
|
14346
14425
|
if (phase === "deny") {
|
|
14347
|
-
return /* @__PURE__ */
|
|
14426
|
+
return /* @__PURE__ */ React20.createElement(
|
|
14348
14427
|
ApprovalCard,
|
|
14349
14428
|
{
|
|
14350
14429
|
tone: "error",
|
|
@@ -14353,7 +14432,7 @@ function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
|
|
|
14353
14432
|
metaRight: "optional",
|
|
14354
14433
|
footerHint: "\u23CE submit \xB7 esc skip (deny without reason)"
|
|
14355
14434
|
},
|
|
14356
|
-
/* @__PURE__ */
|
|
14435
|
+
/* @__PURE__ */ React20.createElement(
|
|
14357
14436
|
DenyContextInput,
|
|
14358
14437
|
{
|
|
14359
14438
|
onSubmit: (context2) => onChoose("deny", context2 || void 0),
|
|
@@ -14362,7 +14441,7 @@ function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
|
|
|
14362
14441
|
)
|
|
14363
14442
|
);
|
|
14364
14443
|
}
|
|
14365
|
-
return /* @__PURE__ */
|
|
14444
|
+
return /* @__PURE__ */ React20.createElement(
|
|
14366
14445
|
ApprovalCard,
|
|
14367
14446
|
{
|
|
14368
14447
|
tone: "warn",
|
|
@@ -14371,9 +14450,9 @@ function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
|
|
|
14371
14450
|
metaRight: "awaiting",
|
|
14372
14451
|
footerHint: "\u2191\u2193 pick \xB7 \u23CE confirm \xB7 esc cancel"
|
|
14373
14452
|
},
|
|
14374
|
-
/* @__PURE__ */
|
|
14375
|
-
/* @__PURE__ */
|
|
14376
|
-
/* @__PURE__ */
|
|
14453
|
+
/* @__PURE__ */ React20.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text16, { color: FG.faint }, subtitle)),
|
|
14454
|
+
/* @__PURE__ */ React20.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text16, { bold: true, color: TONE.err }, "$ "), /* @__PURE__ */ React20.createElement(Text16, { bold: true, color: FG.strong }, command)),
|
|
14455
|
+
/* @__PURE__ */ React20.createElement(
|
|
14377
14456
|
SingleSelect,
|
|
14378
14457
|
{
|
|
14379
14458
|
initialValue: "run_once",
|
|
@@ -14433,8 +14512,8 @@ function derivePrefix(command) {
|
|
|
14433
14512
|
}
|
|
14434
14513
|
|
|
14435
14514
|
// src/cli/ui/SlashArgPicker.tsx
|
|
14436
|
-
import { Box as
|
|
14437
|
-
import
|
|
14515
|
+
import { Box as Box18, Text as Text17 } from "ink";
|
|
14516
|
+
import React21 from "react";
|
|
14438
14517
|
function SlashArgPicker({
|
|
14439
14518
|
matches,
|
|
14440
14519
|
selectedIndex,
|
|
@@ -14442,13 +14521,13 @@ function SlashArgPicker({
|
|
|
14442
14521
|
kind,
|
|
14443
14522
|
partial
|
|
14444
14523
|
}) {
|
|
14445
|
-
const headerRow = /* @__PURE__ */
|
|
14524
|
+
const headerRow = /* @__PURE__ */ React21.createElement(Box18, null, /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.accent, bold: true }, "/ "), /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.accent, bold: true }, `/${spec.cmd}`), spec.argsHint ? /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, ` ${spec.argsHint}`) : null, /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, ` ${spec.summary}`));
|
|
14446
14525
|
if (kind === "hint") {
|
|
14447
|
-
return /* @__PURE__ */
|
|
14526
|
+
return /* @__PURE__ */ React21.createElement(Box18, { paddingX: 1, marginTop: 1 }, headerRow);
|
|
14448
14527
|
}
|
|
14449
14528
|
if (matches === null) return null;
|
|
14450
14529
|
if (matches.length === 0) {
|
|
14451
|
-
return /* @__PURE__ */
|
|
14530
|
+
return /* @__PURE__ */ React21.createElement(Box18, { flexDirection: "column", paddingX: 1, marginTop: 1 }, headerRow, /* @__PURE__ */ React21.createElement(Box18, null, /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.warn }, ` no match for "${partial}"`), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, " \u2014 keep typing, or Backspace to edit")));
|
|
14452
14531
|
}
|
|
14453
14532
|
const MAX = 8;
|
|
14454
14533
|
const total = matches.length;
|
|
@@ -14456,22 +14535,22 @@ function SlashArgPicker({
|
|
|
14456
14535
|
const shown = matches.slice(windowStart, windowStart + MAX);
|
|
14457
14536
|
const hiddenAbove = windowStart;
|
|
14458
14537
|
const hiddenBelow = total - windowStart - shown.length;
|
|
14459
|
-
return /* @__PURE__ */
|
|
14538
|
+
return /* @__PURE__ */ React21.createElement(Box18, { flexDirection: "column", paddingX: 1, marginTop: 1 }, headerRow, hiddenAbove > 0 ? /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null, shown.map((value, i) => /* @__PURE__ */ React21.createElement(ArgRow, { key: value, value, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, ` \u2193 ${hiddenBelow} below`) : null, /* @__PURE__ */ React21.createElement(Box18, { marginTop: 0 }, /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, " \u2191\u2193 navigate \xB7 Tab / \u23CE pick \xB7 esc cancel")));
|
|
14460
14539
|
}
|
|
14461
14540
|
function ArgRow({ value, isSelected }) {
|
|
14462
|
-
return /* @__PURE__ */
|
|
14541
|
+
return /* @__PURE__ */ React21.createElement(Box18, null, /* @__PURE__ */ React21.createElement(Text17, { color: isSelected ? COLOR.primary : COLOR.info, bold: isSelected }, isSelected ? `${GLYPH.cur} ` : " "), /* @__PURE__ */ React21.createElement(Text17, { color: isSelected ? COLOR.user : COLOR.info, bold: isSelected, dimColor: !isSelected }, value));
|
|
14463
14542
|
}
|
|
14464
14543
|
|
|
14465
14544
|
// src/cli/ui/SlashSuggestions.tsx
|
|
14466
|
-
import { Box as
|
|
14467
|
-
import
|
|
14545
|
+
import { Box as Box19, Text as Text18 } from "ink";
|
|
14546
|
+
import React22 from "react";
|
|
14468
14547
|
function SlashSuggestions({
|
|
14469
14548
|
matches,
|
|
14470
14549
|
selectedIndex
|
|
14471
14550
|
}) {
|
|
14472
14551
|
if (matches === null) return null;
|
|
14473
14552
|
if (matches.length === 0) {
|
|
14474
|
-
return /* @__PURE__ */
|
|
14553
|
+
return /* @__PURE__ */ React22.createElement(Box19, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, { color: COLOR.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React22.createElement(Text18, null, " "), /* @__PURE__ */ React22.createElement(Text18, { color: COLOR.warn }, "no slash command matches that prefix"), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, " \u2014 Backspace to edit, or /help for the full list"));
|
|
14475
14554
|
}
|
|
14476
14555
|
const MAX = 8;
|
|
14477
14556
|
const total = matches.length;
|
|
@@ -14479,17 +14558,17 @@ function SlashSuggestions({
|
|
|
14479
14558
|
const shown = matches.slice(windowStart, windowStart + MAX);
|
|
14480
14559
|
const hiddenAbove = windowStart;
|
|
14481
14560
|
const hiddenBelow = total - windowStart - shown.length;
|
|
14482
|
-
return /* @__PURE__ */
|
|
14561
|
+
return /* @__PURE__ */ React22.createElement(Box19, { flexDirection: "column", paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React22.createElement(Box19, null, /* @__PURE__ */ React22.createElement(Text18, { color: COLOR.accent, bold: true }, "/ "), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, `${total} command${total === 1 ? "" : "s"}`), hiddenAbove > 0 ? /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null), shown.map((spec, i) => /* @__PURE__ */ React22.createElement(SuggestionRow, { key: spec.cmd, spec, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, ` \u2193 ${hiddenBelow} below`) : null, /* @__PURE__ */ React22.createElement(Box19, { marginTop: 0 }, /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, " \u2191\u2193 navigate \xB7 Tab / \u23CE pick \xB7 esc cancel")));
|
|
14483
14562
|
}
|
|
14484
14563
|
function SuggestionRow({ spec, isSelected }) {
|
|
14485
14564
|
const name = `/${spec.cmd}`;
|
|
14486
14565
|
const argsSuffix = spec.argsHint ? spec.argsHint : "";
|
|
14487
|
-
return /* @__PURE__ */
|
|
14566
|
+
return /* @__PURE__ */ React22.createElement(Box19, null, /* @__PURE__ */ React22.createElement(Text18, { color: isSelected ? COLOR.primary : COLOR.info, bold: isSelected }, isSelected ? `${GLYPH.cur} ` : " "), /* @__PURE__ */ React22.createElement(Text18, { color: COLOR.accent, bold: isSelected }, name.padEnd(14)), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, argsSuffix.padEnd(14)), /* @__PURE__ */ React22.createElement(Text18, null, " "), /* @__PURE__ */ React22.createElement(Text18, { color: isSelected ? COLOR.user : COLOR.info, dimColor: !isSelected }, spec.summary));
|
|
14488
14567
|
}
|
|
14489
14568
|
|
|
14490
14569
|
// src/cli/ui/WelcomeBanner.tsx
|
|
14491
|
-
import { Box as
|
|
14492
|
-
import
|
|
14570
|
+
import { Box as Box20, Text as Text19, useStdout as useStdout6 } from "ink";
|
|
14571
|
+
import React23 from "react";
|
|
14493
14572
|
var TAGLINE_CHAT = "DeepSeek-native agent";
|
|
14494
14573
|
var TAGLINE_CODE = "DeepSeek-native coding agent";
|
|
14495
14574
|
var TAGLINE_SUB = "cache-first \xB7 flash-first";
|
|
@@ -14510,22 +14589,22 @@ function WelcomeBanner({
|
|
|
14510
14589
|
const hintsIndent = Math.max(2, Math.floor((cols - hintsRow.length) / 2));
|
|
14511
14590
|
const startTextRaw = "type a message to start your session";
|
|
14512
14591
|
const startIndent = Math.max(2, Math.floor((cols - startTextRaw.length) / 2));
|
|
14513
|
-
return /* @__PURE__ */
|
|
14592
|
+
return /* @__PURE__ */ React23.createElement(Box20, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React23.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React23.createElement(Text19, { color: TONE.brand }, top)), /* @__PURE__ */ React23.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React23.createElement(BoxLine, { pad: BOX_INNER_WIDTH }, "")), /* @__PURE__ */ React23.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React23.createElement(BoxLine, { pad: BOX_INNER_WIDTH }, /* @__PURE__ */ React23.createElement(Text19, { bold: true, color: TONE.brand }, centerInside("\u25C8 REASONIX", BOX_INNER_WIDTH)))), /* @__PURE__ */ React23.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React23.createElement(BoxLine, { pad: BOX_INNER_WIDTH }, "")), /* @__PURE__ */ React23.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React23.createElement(BoxLine, { pad: BOX_INNER_WIDTH }, /* @__PURE__ */ React23.createElement(Text19, { color: FG.sub }, centerInside(tagline, BOX_INNER_WIDTH)))), /* @__PURE__ */ React23.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React23.createElement(BoxLine, { pad: BOX_INNER_WIDTH }, /* @__PURE__ */ React23.createElement(Text19, { color: FG.meta }, centerInside(TAGLINE_SUB, BOX_INNER_WIDTH)))), /* @__PURE__ */ React23.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React23.createElement(BoxLine, { pad: BOX_INNER_WIDTH }, "")), /* @__PURE__ */ React23.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React23.createElement(Text19, { color: TONE.brand }, bot)), /* @__PURE__ */ React23.createElement(Box20, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, null, " ".repeat(startIndent)), /* @__PURE__ */ React23.createElement(Text19, { color: FG.sub }, startTextRaw)), /* @__PURE__ */ React23.createElement(Box20, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, null, " ".repeat(hintsIndent)), HINTS.map((cmd, i) => /* @__PURE__ */ React23.createElement(React23.Fragment, { key: cmd }, /* @__PURE__ */ React23.createElement(Text19, { color: FG.meta }, cmd), i < HINTS.length - 1 && /* @__PURE__ */ React23.createElement(Text19, { color: FG.faint }, " \xB7 ")))), dashboardUrl ? /* @__PURE__ */ React23.createElement(Box20, { marginTop: 1, flexDirection: "row", justifyContent: "center" }, /* @__PURE__ */ React23.createElement(Text19, { color: TONE.brand, bold: true }, "\u25B8 web \xB7 "), /* @__PURE__ */ React23.createElement(Text19, { color: TONE.accent }, dashboardUrl)) : null);
|
|
14514
14593
|
}
|
|
14515
14594
|
function BoxRow({
|
|
14516
14595
|
indent,
|
|
14517
14596
|
children
|
|
14518
14597
|
}) {
|
|
14519
|
-
return /* @__PURE__ */
|
|
14598
|
+
return /* @__PURE__ */ React23.createElement(Box20, null, /* @__PURE__ */ React23.createElement(Text19, null, " ".repeat(indent)), children);
|
|
14520
14599
|
}
|
|
14521
14600
|
function BoxLine({
|
|
14522
14601
|
pad: pad3,
|
|
14523
14602
|
children
|
|
14524
14603
|
}) {
|
|
14525
14604
|
if (children === "" || children === void 0) {
|
|
14526
|
-
return /* @__PURE__ */
|
|
14605
|
+
return /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(Text19, { color: TONE.brand }, "\u2551"), /* @__PURE__ */ React23.createElement(Text19, null, " ".repeat(pad3)), /* @__PURE__ */ React23.createElement(Text19, { color: TONE.brand }, "\u2551"));
|
|
14527
14606
|
}
|
|
14528
|
-
return /* @__PURE__ */
|
|
14607
|
+
return /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(Text19, { color: TONE.brand }, "\u2551"), children, /* @__PURE__ */ React23.createElement(Text19, { color: TONE.brand }, "\u2551"));
|
|
14529
14608
|
}
|
|
14530
14609
|
function centerInside(text, pad3) {
|
|
14531
14610
|
if (text.length >= pad3) return text.slice(0, pad3);
|
|
@@ -14547,12 +14626,12 @@ ${output}`;
|
|
|
14547
14626
|
}
|
|
14548
14627
|
|
|
14549
14628
|
// src/cli/ui/cards/PlanCard.tsx
|
|
14550
|
-
import { Box as
|
|
14551
|
-
import
|
|
14629
|
+
import { Box as Box23, Text as Text22 } from "ink";
|
|
14630
|
+
import React26 from "react";
|
|
14552
14631
|
|
|
14553
14632
|
// src/cli/ui/primitives/BarRow.tsx
|
|
14554
|
-
import { Box as
|
|
14555
|
-
import
|
|
14633
|
+
import { Box as Box21, Text as Text20 } from "ink";
|
|
14634
|
+
import React24 from "react";
|
|
14556
14635
|
|
|
14557
14636
|
// src/cli/ui/cards/glyphs.ts
|
|
14558
14637
|
var STRUCT = {
|
|
@@ -14572,17 +14651,17 @@ function BarRow({
|
|
|
14572
14651
|
children
|
|
14573
14652
|
}) {
|
|
14574
14653
|
const t2 = CARD[tone];
|
|
14575
|
-
return /* @__PURE__ */
|
|
14654
|
+
return /* @__PURE__ */ React24.createElement(Box21, { flexDirection: "row" }, /* @__PURE__ */ React24.createElement(Text20, null, " "), /* @__PURE__ */ React24.createElement(Text20, { color: t2.color }, STRUCT.bar), glyph !== void 0 ? /* @__PURE__ */ React24.createElement(Text20, { bold: glyphBold, color: t2.color }, " ", glyph, indent === 3 ? " " : " ") : indent > 0 ? /* @__PURE__ */ React24.createElement(Text20, null, " ".repeat(indent + 1)) : null, children);
|
|
14576
14655
|
}
|
|
14577
14656
|
function CursorBlock() {
|
|
14578
14657
|
const tick = useTick();
|
|
14579
14658
|
const on = Math.floor(tick / 4) % 2 === 0;
|
|
14580
|
-
return /* @__PURE__ */
|
|
14659
|
+
return /* @__PURE__ */ React24.createElement(Text20, { inverse: on, color: CARD.streaming.color }, " ");
|
|
14581
14660
|
}
|
|
14582
14661
|
|
|
14583
14662
|
// src/cli/ui/cards/CardHeader.tsx
|
|
14584
|
-
import { Box as
|
|
14585
|
-
import
|
|
14663
|
+
import { Box as Box22, Text as Text21 } from "ink";
|
|
14664
|
+
import React25 from "react";
|
|
14586
14665
|
function CardHeader({
|
|
14587
14666
|
tone,
|
|
14588
14667
|
glyph,
|
|
@@ -14596,7 +14675,7 @@ function CardHeader({
|
|
|
14596
14675
|
}) {
|
|
14597
14676
|
const t2 = CARD[tone];
|
|
14598
14677
|
const bar2 = barColor ?? t2.color;
|
|
14599
|
-
return /* @__PURE__ */
|
|
14678
|
+
return /* @__PURE__ */ React25.createElement(Box22, { flexDirection: "row" }, /* @__PURE__ */ React25.createElement(Text21, null, " "), /* @__PURE__ */ React25.createElement(Text21, { color: bar2 }, STRUCT.bar), /* @__PURE__ */ React25.createElement(Text21, null, " "), /* @__PURE__ */ React25.createElement(Text21, { bold: true, color: t2.color }, glyph), /* @__PURE__ */ React25.createElement(Text21, { bold: true, color: titleColor ?? FG.strong }, ` ${title}`), inline2 && /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(Text21, null, " "), inline2), subtitle && /* @__PURE__ */ React25.createElement(Text21, { color: FG.sub }, ` ${subtitle}`), /* @__PURE__ */ React25.createElement(Box22, { flexGrow: 1 }), meta && /* @__PURE__ */ React25.createElement(Text21, { color: FG.faint }, meta), trailing && /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(Text21, null, " "), trailing));
|
|
14600
14679
|
}
|
|
14601
14680
|
|
|
14602
14681
|
// src/cli/ui/cards/PlanCard.tsx
|
|
@@ -14622,11 +14701,11 @@ function PlanCard({ card }) {
|
|
|
14622
14701
|
const variantTag = card.variant === "resumed" ? " \xB7 resumed" : card.variant === "replay" ? " \xB7 \u23EA archive" : "";
|
|
14623
14702
|
const meta = `${variantTag} \xB7 ${doneCount} of ${card.steps.length} done`;
|
|
14624
14703
|
const showFooter = card.variant === "active";
|
|
14625
|
-
return /* @__PURE__ */
|
|
14704
|
+
return /* @__PURE__ */ React26.createElement(Box23, { flexDirection: "column" }, /* @__PURE__ */ React26.createElement(CardHeader, { tone: "plan", glyph: "\u229E", title: card.title, meta }), /* @__PURE__ */ React26.createElement(BarRow, { tone: "plan", indent: 0 }), card.steps.map((step, i) => {
|
|
14626
14705
|
const isActive = step.status === "running";
|
|
14627
14706
|
const titleColor = isActive ? FG.strong : step.status === "queued" ? FG.sub : FG.sub;
|
|
14628
|
-
return /* @__PURE__ */
|
|
14629
|
-
}), showFooter && /* @__PURE__ */
|
|
14707
|
+
return /* @__PURE__ */ React26.createElement(BarRow, { key: step.id, tone: "plan" }, /* @__PURE__ */ React26.createElement(Text22, { color: STATUS_COLOR[step.status] }, `[${STATUS_GLYPH[step.status]}]`), /* @__PURE__ */ React26.createElement(Text22, { bold: isActive, color: titleColor }, ` ${i + 1}. ${step.title}`), isActive && /* @__PURE__ */ React26.createElement(Text22, { color: TONE.brand }, " \u2190 in progress"));
|
|
14708
|
+
}), showFooter && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(BarRow, { tone: "plan", indent: 0 }), /* @__PURE__ */ React26.createElement(BarRow, { tone: "plan" }, /* @__PURE__ */ React26.createElement(Text22, { color: FG.meta }, ACTIVE_PLAN_FOOTER))));
|
|
14630
14709
|
}
|
|
14631
14710
|
|
|
14632
14711
|
// src/cli/ui/edit-history.ts
|
|
@@ -15069,7 +15148,7 @@ function useAgentSession({
|
|
|
15069
15148
|
import { useMemo as useMemo3 } from "react";
|
|
15070
15149
|
|
|
15071
15150
|
// src/cli/ui/state/provider.tsx
|
|
15072
|
-
import
|
|
15151
|
+
import React27 from "react";
|
|
15073
15152
|
|
|
15074
15153
|
// src/cli/ui/state/reducer.ts
|
|
15075
15154
|
function reduce(state, event) {
|
|
@@ -15408,26 +15487,26 @@ function createStore(session, initialCards) {
|
|
|
15408
15487
|
}
|
|
15409
15488
|
|
|
15410
15489
|
// src/cli/ui/state/provider.tsx
|
|
15411
|
-
var StoreCtx =
|
|
15490
|
+
var StoreCtx = React27.createContext(null);
|
|
15412
15491
|
function AgentStoreProvider({
|
|
15413
15492
|
session,
|
|
15414
15493
|
initialCards,
|
|
15415
15494
|
children
|
|
15416
15495
|
}) {
|
|
15417
|
-
const initialCardsRef =
|
|
15418
|
-
const store =
|
|
15419
|
-
return /* @__PURE__ */
|
|
15496
|
+
const initialCardsRef = React27.useRef(initialCards);
|
|
15497
|
+
const store = React27.useMemo(() => createStore(session, initialCardsRef.current), [session]);
|
|
15498
|
+
return /* @__PURE__ */ React27.createElement(StoreCtx.Provider, { value: store }, children);
|
|
15420
15499
|
}
|
|
15421
15500
|
function useAgentStore() {
|
|
15422
|
-
const store =
|
|
15501
|
+
const store = React27.useContext(StoreCtx);
|
|
15423
15502
|
if (!store) throw new Error("useAgentStore must be used inside AgentStoreProvider");
|
|
15424
15503
|
return store;
|
|
15425
15504
|
}
|
|
15426
15505
|
function useAgentState(selector) {
|
|
15427
15506
|
const store = useAgentStore();
|
|
15428
|
-
const subscribe =
|
|
15429
|
-
const getSnapshot =
|
|
15430
|
-
return
|
|
15507
|
+
const subscribe = React27.useCallback((cb) => store.subscribe(cb), [store]);
|
|
15508
|
+
const getSnapshot = React27.useCallback(() => selector(store.getState()), [store, selector]);
|
|
15509
|
+
return React27.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
15431
15510
|
}
|
|
15432
15511
|
function useDispatch() {
|
|
15433
15512
|
return useAgentStore().dispatch;
|
|
@@ -15679,22 +15758,22 @@ function useSyntheticSubmit(deps) {
|
|
|
15679
15758
|
|
|
15680
15759
|
// src/cli/ui/layout/CardStream.tsx
|
|
15681
15760
|
import { Static } from "ink";
|
|
15682
|
-
import
|
|
15761
|
+
import React47 from "react";
|
|
15683
15762
|
|
|
15684
15763
|
// src/cli/ui/cards/CardRenderer.tsx
|
|
15685
|
-
import { Box as
|
|
15686
|
-
import
|
|
15764
|
+
import { Box as Box41, Text as Text41 } from "ink";
|
|
15765
|
+
import React46 from "react";
|
|
15687
15766
|
|
|
15688
15767
|
// src/cli/ui/cards/BranchCard.tsx
|
|
15689
|
-
import { Text as
|
|
15690
|
-
import { Box as
|
|
15691
|
-
import
|
|
15768
|
+
import { Text as Text23 } from "ink";
|
|
15769
|
+
import { Box as Box24 } from "ink";
|
|
15770
|
+
import React28 from "react";
|
|
15692
15771
|
var BAR_CELLS = 28;
|
|
15693
15772
|
function BranchCard({ card }) {
|
|
15694
15773
|
const ratio = card.total > 0 ? card.completed / card.total : 0;
|
|
15695
15774
|
const filled = Math.max(0, Math.min(BAR_CELLS, Math.round(ratio * BAR_CELLS)));
|
|
15696
15775
|
const tone = card.done ? TONE.ok : CARD.streaming.color;
|
|
15697
|
-
return /* @__PURE__ */
|
|
15776
|
+
return /* @__PURE__ */ React28.createElement(Box24, { flexDirection: "column" }, /* @__PURE__ */ React28.createElement(
|
|
15698
15777
|
CardHeader,
|
|
15699
15778
|
{
|
|
15700
15779
|
tone: "streaming",
|
|
@@ -15703,27 +15782,27 @@ function BranchCard({ card }) {
|
|
|
15703
15782
|
meta: `\xB7 ${card.completed} of ${card.total} samples`,
|
|
15704
15783
|
barColor: tone
|
|
15705
15784
|
}
|
|
15706
|
-
), /* @__PURE__ */
|
|
15785
|
+
), /* @__PURE__ */ React28.createElement(BarRow, { tone: "streaming", indent: 0 }), /* @__PURE__ */ React28.createElement(BarRow, { tone: "streaming" }, /* @__PURE__ */ React28.createElement(Text23, { color: tone }, "\u2588".repeat(filled)), /* @__PURE__ */ React28.createElement(Text23, { color: FG.faint }, "\u2591".repeat(BAR_CELLS - filled)), /* @__PURE__ */ React28.createElement(Text23, { color: FG.faint }, ` ${(ratio * 100).toFixed(0)}%`)), !card.done && card.completed > 0 && /* @__PURE__ */ React28.createElement(BarRow, { tone: "streaming" }, /* @__PURE__ */ React28.createElement(Text23, { color: FG.faint }, `latest: #${card.latestIndex} \xB7 T=${card.latestTemperature.toFixed(2)} \xB7 ${card.latestUncertainties} unc`)));
|
|
15707
15786
|
}
|
|
15708
15787
|
|
|
15709
15788
|
// src/cli/ui/cards/CtxCard.tsx
|
|
15710
|
-
import { Box as
|
|
15711
|
-
import
|
|
15789
|
+
import { Box as Box25, Text as Text24 } from "ink";
|
|
15790
|
+
import React29 from "react";
|
|
15712
15791
|
var BAR_CELLS2 = 32;
|
|
15713
15792
|
function row2(label, tokens, ratio, color2) {
|
|
15714
15793
|
const filled = Math.max(0, Math.min(BAR_CELLS2, Math.round(ratio * BAR_CELLS2)));
|
|
15715
|
-
return /* @__PURE__ */
|
|
15794
|
+
return /* @__PURE__ */ React29.createElement(BarRow, { tone: "usage" }, /* @__PURE__ */ React29.createElement(Text24, { color: FG.sub }, label.padEnd(8)), /* @__PURE__ */ React29.createElement(Text24, { color: color2 }, "\u2588".repeat(filled)), /* @__PURE__ */ React29.createElement(Text24, { color: FG.faint }, "\u2591".repeat(BAR_CELLS2 - filled)), /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: FG.body }, ` ${tokens.toLocaleString()}`), /* @__PURE__ */ React29.createElement(Text24, { color: FG.faint }, ` ${(ratio * 100).toFixed(1)}%`));
|
|
15716
15795
|
}
|
|
15717
15796
|
function CtxCard({ card }) {
|
|
15718
15797
|
const cap = Math.max(1, card.ctxMax);
|
|
15719
15798
|
const used = card.systemTokens + card.toolsTokens + card.logTokens + card.inputTokens;
|
|
15720
15799
|
const usedPct = used / cap * 100;
|
|
15721
|
-
return /* @__PURE__ */
|
|
15800
|
+
return /* @__PURE__ */ React29.createElement(Box25, { flexDirection: "column" }, /* @__PURE__ */ React29.createElement(Box25, { flexDirection: "row" }, /* @__PURE__ */ React29.createElement(Text24, null, " "), /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: CARD.usage.color }, "\u2318 Context window"), /* @__PURE__ */ React29.createElement(Text24, { color: FG.faint }, ` \xB7 ${used.toLocaleString()} / ${cap.toLocaleString()} (${usedPct.toFixed(1)}%)`)), /* @__PURE__ */ React29.createElement(BarRow, { tone: "usage", indent: 0 }), row2("system", card.systemTokens, card.systemTokens / cap, TONE.brand), row2("tools", card.toolsTokens, card.toolsTokens / cap, TONE.warn), row2("log", card.logTokens, card.logTokens / cap, TONE.ok), row2("input", card.inputTokens, card.inputTokens / cap, TONE.accent), card.topTools.length > 0 && /* @__PURE__ */ React29.createElement(React29.Fragment, null, /* @__PURE__ */ React29.createElement(BarRow, { tone: "usage", indent: 0 }), /* @__PURE__ */ React29.createElement(BarRow, { tone: "usage" }, /* @__PURE__ */ React29.createElement(Text24, { color: FG.faint }, `top tools (${card.toolsCount} total \xB7 ${card.logMessages} log msgs):`)), card.topTools.slice(0, 5).map((t2) => /* @__PURE__ */ React29.createElement(BarRow, { key: `${t2.turn}-${t2.name}`, tone: "usage" }, /* @__PURE__ */ React29.createElement(Text24, { color: FG.sub }, ` ${t2.name}`), /* @__PURE__ */ React29.createElement(Text24, { color: FG.faint }, ` \xB7 turn ${t2.turn} \xB7 ${t2.tokens.toLocaleString()}`)))));
|
|
15722
15801
|
}
|
|
15723
15802
|
|
|
15724
15803
|
// src/cli/ui/cards/DiffCard.tsx
|
|
15725
|
-
import { Box as
|
|
15726
|
-
import
|
|
15804
|
+
import { Box as Box26, Text as Text25 } from "ink";
|
|
15805
|
+
import React30 from "react";
|
|
15727
15806
|
var LINE_COLOR = {
|
|
15728
15807
|
ctx: FG.sub,
|
|
15729
15808
|
add: TONE.ok,
|
|
@@ -15731,14 +15810,14 @@ var LINE_COLOR = {
|
|
|
15731
15810
|
fold: FG.faint
|
|
15732
15811
|
};
|
|
15733
15812
|
function DiffCard({ card }) {
|
|
15734
|
-
const meta = /* @__PURE__ */
|
|
15813
|
+
const meta = /* @__PURE__ */ React30.createElement(React30.Fragment, null, /* @__PURE__ */ React30.createElement(Text25, { color: TONE.ok }, `+${card.stats.add}`), /* @__PURE__ */ React30.createElement(Text25, { color: FG.faint }, " / "), /* @__PURE__ */ React30.createElement(Text25, { color: TONE.err }, `-${card.stats.del}`));
|
|
15735
15814
|
const showFooter = card.hunks.length > 0;
|
|
15736
|
-
return /* @__PURE__ */
|
|
15815
|
+
return /* @__PURE__ */ React30.createElement(Box26, { flexDirection: "column" }, /* @__PURE__ */ React30.createElement(CardHeader, { tone: "diff", glyph: "\xB1", title: "Edit", subtitle: card.file, trailing: meta }), card.hunks.map((hunk) => /* @__PURE__ */ React30.createElement(Box26, { key: `${card.id}:${hunk.header}`, flexDirection: "column" }, /* @__PURE__ */ React30.createElement(BarRow, { tone: "diff", indent: 0 }), /* @__PURE__ */ React30.createElement(BarRow, { tone: "diff" }, /* @__PURE__ */ React30.createElement(Text25, { italic: true, color: FG.faint }, hunk.header)), hunk.lines.map((line, li) => /* @__PURE__ */ React30.createElement(BarRow, { key: `${card.id}:${hunk.header}:${li}`, tone: "diff" }, /* @__PURE__ */ React30.createElement(Text25, { color: LINE_COLOR[line.kind] }, line.text))))), showFooter && /* @__PURE__ */ React30.createElement(React30.Fragment, null, /* @__PURE__ */ React30.createElement(BarRow, { tone: "diff", indent: 0 }), /* @__PURE__ */ React30.createElement(BarRow, { tone: "diff" }, /* @__PURE__ */ React30.createElement(Text25, { bold: true, color: TONE.ok }, "[a] apply"), /* @__PURE__ */ React30.createElement(Text25, { color: FG.sub }, " [s] skip "), /* @__PURE__ */ React30.createElement(Text25, { bold: true, color: TONE.err }, "[r] reject"))));
|
|
15737
15816
|
}
|
|
15738
15817
|
|
|
15739
15818
|
// src/cli/ui/cards/DoctorCard.tsx
|
|
15740
|
-
import { Box as
|
|
15741
|
-
import
|
|
15819
|
+
import { Box as Box27, Text as Text26 } from "ink";
|
|
15820
|
+
import React31 from "react";
|
|
15742
15821
|
var LEVEL_COLOR = {
|
|
15743
15822
|
ok: TONE.ok,
|
|
15744
15823
|
warn: TONE.warn,
|
|
@@ -15760,12 +15839,12 @@ function DoctorCard({ card }) {
|
|
|
15760
15839
|
const fail = card.checks.filter((c) => c.level === "fail").length;
|
|
15761
15840
|
const summary = `${card.checks.length} checks \xB7 ${ok} passed${warn > 0 ? ` \xB7 ${warn} warn` : ""}${fail > 0 ? ` \xB7 ${fail} fail` : ""}`;
|
|
15762
15841
|
const labelWidth = card.checks.reduce((m, c) => Math.max(m, c.label.length), 0);
|
|
15763
|
-
return /* @__PURE__ */
|
|
15842
|
+
return /* @__PURE__ */ React31.createElement(Box27, { flexDirection: "column" }, /* @__PURE__ */ React31.createElement(CardHeader, { tone: "tool", glyph: "\u2695", title: "Doctor", meta: summary, barColor: CARD.tool.color }), /* @__PURE__ */ React31.createElement(BarRow, { tone: "tool", indent: 0 }), card.checks.map((c) => /* @__PURE__ */ React31.createElement(BarRow, { key: c.label, tone: "tool" }, /* @__PURE__ */ React31.createElement(Text26, { color: LEVEL_COLOR[c.level] }, LEVEL_GLYPH[c.level]), /* @__PURE__ */ React31.createElement(Text26, { bold: true, color: FG.body }, ` ${c.label.padEnd(labelWidth + 1)}`), /* @__PURE__ */ React31.createElement(Text26, { color: FG.sub }, c.detail), /* @__PURE__ */ React31.createElement(Text26, { color: LEVEL_COLOR[c.level] }, ` ${LEVEL_TAG[c.level]}`))));
|
|
15764
15843
|
}
|
|
15765
15844
|
|
|
15766
15845
|
// src/cli/ui/cards/ErrorCard.tsx
|
|
15767
|
-
import { Box as
|
|
15768
|
-
import
|
|
15846
|
+
import { Box as Box28, Text as Text27 } from "ink";
|
|
15847
|
+
import React32 from "react";
|
|
15769
15848
|
var STACK_TAIL = 5;
|
|
15770
15849
|
function ErrorCard({ card }) {
|
|
15771
15850
|
const meta = card.retries !== void 0 && card.retries > 0 ? `\xB7 ${card.retries} retr${card.retries === 1 ? "y" : "ies"}` : void 0;
|
|
@@ -15774,16 +15853,16 @@ function ErrorCard({ card }) {
|
|
|
15774
15853
|
const stackVisible = stackTrunc ? stackLines.slice(-STACK_TAIL) : stackLines;
|
|
15775
15854
|
const stackHidden = stackTrunc ? stackLines.length - stackVisible.length : 0;
|
|
15776
15855
|
const hasStack = stackVisible.length > 0;
|
|
15777
|
-
return /* @__PURE__ */
|
|
15856
|
+
return /* @__PURE__ */ React32.createElement(Box28, { flexDirection: "column" }, /* @__PURE__ */ React32.createElement(CardHeader, { tone: "error", glyph: "\u2716", title: "Error", subtitle: card.title, meta }), /* @__PURE__ */ React32.createElement(BarRow, { tone: "error", indent: 0 }), card.message.split("\n").map((line, i) => /* @__PURE__ */ React32.createElement(BarRow, { key: `${card.id}:msg:${i}`, tone: "error" }, /* @__PURE__ */ React32.createElement(Text27, { color: CARD.error.color }, line))), hasStack && /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement(BarRow, { tone: "error", indent: 0 }), /* @__PURE__ */ React32.createElement(BarRow, { tone: "error" }, /* @__PURE__ */ React32.createElement(Text27, { color: FG.meta }, "stack trace")), stackHidden > 0 && /* @__PURE__ */ React32.createElement(BarRow, { tone: "error" }, /* @__PURE__ */ React32.createElement(Text27, { color: FG.faint }, `\u22EE ${stackHidden} earlier stack line${stackHidden === 1 ? "" : "s"} hidden`)), stackVisible.map((line, i) => /* @__PURE__ */ React32.createElement(BarRow, { key: `${card.id}:stk:${stackHidden + i}`, tone: "error" }, /* @__PURE__ */ React32.createElement(Text27, { color: FG.meta }, line)))), /* @__PURE__ */ React32.createElement(BarRow, { tone: "error", indent: 0 }), /* @__PURE__ */ React32.createElement(BarRow, { tone: "error" }, /* @__PURE__ */ React32.createElement(Text27, { bold: true, color: TONE.err }, "[r] retry"), /* @__PURE__ */ React32.createElement(Text27, { color: FG.sub }, " [s] skip")));
|
|
15778
15857
|
}
|
|
15779
15858
|
|
|
15780
15859
|
// src/cli/ui/cards/LiveCard.tsx
|
|
15781
|
-
import { Box as
|
|
15782
|
-
import
|
|
15860
|
+
import { Box as Box29, Text as Text29 } from "ink";
|
|
15861
|
+
import React34 from "react";
|
|
15783
15862
|
|
|
15784
15863
|
// src/cli/ui/primitives/Spinner.tsx
|
|
15785
|
-
import { Text as
|
|
15786
|
-
import
|
|
15864
|
+
import { Text as Text28 } from "ink";
|
|
15865
|
+
import React33 from "react";
|
|
15787
15866
|
var FRAMES = {
|
|
15788
15867
|
circle: ["\u25D0", "\u25D3", "\u25D1", "\u25D2"],
|
|
15789
15868
|
braille: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827"]
|
|
@@ -15794,12 +15873,12 @@ var CADENCE_MS = {
|
|
|
15794
15873
|
};
|
|
15795
15874
|
function Spinner({ kind = "circle", color: color2, bold }) {
|
|
15796
15875
|
const frames = FRAMES[kind];
|
|
15797
|
-
const [frame, setFrame] =
|
|
15798
|
-
|
|
15876
|
+
const [frame, setFrame] = React33.useState(0);
|
|
15877
|
+
React33.useEffect(() => {
|
|
15799
15878
|
const id = setInterval(() => setFrame((f) => (f + 1) % frames.length), CADENCE_MS[kind]);
|
|
15800
15879
|
return () => clearInterval(id);
|
|
15801
15880
|
}, [kind, frames.length]);
|
|
15802
|
-
return /* @__PURE__ */
|
|
15881
|
+
return /* @__PURE__ */ React33.createElement(Text28, { bold, color: color2 }, frames[frame]);
|
|
15803
15882
|
}
|
|
15804
15883
|
|
|
15805
15884
|
// src/cli/ui/cards/LiveCard.tsx
|
|
@@ -15826,12 +15905,12 @@ var VARIANT_GLYPH = {
|
|
|
15826
15905
|
function LiveCard({ card }) {
|
|
15827
15906
|
const color2 = TONE_TO_COLOR[card.tone];
|
|
15828
15907
|
const glyph = VARIANT_GLYPH[card.variant];
|
|
15829
|
-
return /* @__PURE__ */
|
|
15908
|
+
return /* @__PURE__ */ React34.createElement(Box29, { flexDirection: "row" }, /* @__PURE__ */ React34.createElement(Text29, null, " "), card.variant === "thinking" ? /* @__PURE__ */ React34.createElement(Spinner, { kind: "circle", color: color2, bold: true }) : /* @__PURE__ */ React34.createElement(Text29, { bold: true, color: color2 }, glyph), /* @__PURE__ */ React34.createElement(Text29, { color: FG.body }, ` ${card.text}`), card.meta !== void 0 && /* @__PURE__ */ React34.createElement(Text29, { color: FG.faint }, ` ${card.meta}`));
|
|
15830
15909
|
}
|
|
15831
15910
|
|
|
15832
15911
|
// src/cli/ui/cards/MemoryCard.tsx
|
|
15833
|
-
import { Box as
|
|
15834
|
-
import
|
|
15912
|
+
import { Box as Box30, Text as Text30 } from "ink";
|
|
15913
|
+
import React35 from "react";
|
|
15835
15914
|
var CATEGORY_ORDER = [
|
|
15836
15915
|
"user",
|
|
15837
15916
|
"feedback",
|
|
@@ -15860,7 +15939,7 @@ function MemoryCard({ card }) {
|
|
|
15860
15939
|
const counts = countByCategory(card.entries);
|
|
15861
15940
|
const summary = CATEGORY_ORDER.filter((c) => counts[c] > 0).map((c) => `${counts[c]} ${c}`).join(" \xB7 ");
|
|
15862
15941
|
const tokens = card.tokens > 1024 ? `~${(card.tokens / 1024).toFixed(1)}K tok` : `~${card.tokens} tok`;
|
|
15863
|
-
return /* @__PURE__ */
|
|
15942
|
+
return /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "column" }, /* @__PURE__ */ React35.createElement(
|
|
15864
15943
|
CardHeader,
|
|
15865
15944
|
{
|
|
15866
15945
|
tone: "memory",
|
|
@@ -15874,7 +15953,7 @@ function MemoryCard({ card }) {
|
|
|
15874
15953
|
const all = card.entries.filter((e) => e.category === category);
|
|
15875
15954
|
const shown = all.slice(0, 5);
|
|
15876
15955
|
const remaining = all.length - shown.length;
|
|
15877
|
-
return /* @__PURE__ */
|
|
15956
|
+
return /* @__PURE__ */ React35.createElement(Box30, { key: category, flexDirection: "column" }, /* @__PURE__ */ React35.createElement(BarRow, { tone: "memory", indent: 0 }), /* @__PURE__ */ React35.createElement(BarRow, { tone: "memory" }, /* @__PURE__ */ React35.createElement(Text30, { color: FG.faint }, CATEGORY_LABEL[category], " (", counts[category], ")")), shown.map((entry) => /* @__PURE__ */ React35.createElement(BarRow, { key: `${category}:${entry.summary}`, tone: "memory" }, /* @__PURE__ */ React35.createElement(Text30, { color: CATEGORY_GLYPH_COLOR[category] }, CATEGORY_GLYPH[category], " "), /* @__PURE__ */ React35.createElement(Text30, { color: FG.sub }, entry.summary))), remaining > 0 && /* @__PURE__ */ React35.createElement(BarRow, { tone: "memory" }, /* @__PURE__ */ React35.createElement(Text30, { color: FG.faint }, `\u22EE +${remaining} more`)));
|
|
15878
15957
|
}));
|
|
15879
15958
|
}
|
|
15880
15959
|
function countByCategory(entries) {
|
|
@@ -15889,8 +15968,8 @@ function countByCategory(entries) {
|
|
|
15889
15968
|
}
|
|
15890
15969
|
|
|
15891
15970
|
// src/cli/ui/cards/ReasoningCard.tsx
|
|
15892
|
-
import { Box as
|
|
15893
|
-
import
|
|
15971
|
+
import { Box as Box31, Text as Text31, useStdout as useStdout7 } from "ink";
|
|
15972
|
+
import React36 from "react";
|
|
15894
15973
|
|
|
15895
15974
|
// src/frame/width.ts
|
|
15896
15975
|
import stringWidthLib from "string-width";
|
|
@@ -15939,19 +16018,19 @@ function ReasoningCard({
|
|
|
15939
16018
|
const visible = overflows ? allLines.slice(-lineSlots) : allLines;
|
|
15940
16019
|
const headDropped = overflows ? allLines.length - visible.length : 0;
|
|
15941
16020
|
const showBody = expanded && allLines.length > 0;
|
|
15942
|
-
return /* @__PURE__ */
|
|
16021
|
+
return /* @__PURE__ */ React36.createElement(Box31, { flexDirection: "column" }, /* @__PURE__ */ React36.createElement(CardHeader, { tone: "reasoning", glyph: "\u25C6", title: "Reasoning", meta: `\xB7 ${meta}` }), showBody && /* @__PURE__ */ React36.createElement(React36.Fragment, null, /* @__PURE__ */ React36.createElement(BarRow, { tone: "reasoning", indent: 0 }), headDropped > 0 && /* @__PURE__ */ React36.createElement(BarRow, { tone: "reasoning" }, /* @__PURE__ */ React36.createElement(Text31, { color: FG.faint }, card.streaming ? `\u2026 ${headDropped} earlier line${headDropped === 1 ? "" : "s"} (will appear in scrollback)` : `\u22EE ${headDropped} earlier line${headDropped === 1 ? "" : "s"}`)), visible.map((line, i) => {
|
|
15943
16022
|
const isLast = i === visible.length - 1;
|
|
15944
|
-
return /* @__PURE__ */
|
|
16023
|
+
return /* @__PURE__ */ React36.createElement(BarRow, { key: `${card.id}:${headDropped + i}`, tone: "reasoning" }, /* @__PURE__ */ React36.createElement(Text31, { italic: true, color: FG.meta }, clipToCells(line, lineCells)), isLast && card.streaming && /* @__PURE__ */ React36.createElement(CursorBlock, null));
|
|
15945
16024
|
})));
|
|
15946
16025
|
}
|
|
15947
16026
|
|
|
15948
16027
|
// src/cli/ui/cards/SearchCard.tsx
|
|
15949
|
-
import { Box as
|
|
15950
|
-
import
|
|
16028
|
+
import { Box as Box32, Text as Text32 } from "ink";
|
|
16029
|
+
import React37 from "react";
|
|
15951
16030
|
function SearchCard({ card }) {
|
|
15952
16031
|
const fileCount = new Set(card.hits.map((h) => h.file)).size;
|
|
15953
16032
|
const meta = `${card.hits.length} hit${card.hits.length === 1 ? "" : "s"} in ${fileCount} file${fileCount === 1 ? "" : "s"} \xB7 ${(card.elapsedMs / 1e3).toFixed(2)}s`;
|
|
15954
|
-
return /* @__PURE__ */
|
|
16033
|
+
return /* @__PURE__ */ React37.createElement(Box32, { flexDirection: "column" }, /* @__PURE__ */ React37.createElement(CardHeader, { tone: "search", glyph: "\u2299", title: "Search", subtitle: `"${card.query}"`, meta }), card.hits.length > 0 && /* @__PURE__ */ React37.createElement(React37.Fragment, null, /* @__PURE__ */ React37.createElement(BarRow, { tone: "search", indent: 0 }), groupByFile(card.hits.slice(0, 10)).map(([file, hits]) => /* @__PURE__ */ React37.createElement(Box32, { key: file, flexDirection: "column" }, /* @__PURE__ */ React37.createElement(BarRow, { tone: "search" }, /* @__PURE__ */ React37.createElement(Text32, { bold: true, color: FG.strong }, file)), hits.map((h, i) => /* @__PURE__ */ React37.createElement(BarRow, { key: `${file}:${h.line}:${i}`, tone: "search" }, /* @__PURE__ */ React37.createElement(Text32, { color: FG.faint }, `${h.line.toString().padStart(4)} \u2502 `), /* @__PURE__ */ React37.createElement(HighlightedLine, { text: h.preview, start: h.matchStart, end: h.matchEnd }))))), card.hits.length > 10 && /* @__PURE__ */ React37.createElement(BarRow, { tone: "search" }, /* @__PURE__ */ React37.createElement(Text32, { color: FG.faint }, `\u22EE +${card.hits.length - 10} more hits`))));
|
|
15955
16034
|
}
|
|
15956
16035
|
function HighlightedLine({
|
|
15957
16036
|
text,
|
|
@@ -15959,9 +16038,9 @@ function HighlightedLine({
|
|
|
15959
16038
|
end
|
|
15960
16039
|
}) {
|
|
15961
16040
|
if (start < 0 || end <= start || end > text.length) {
|
|
15962
|
-
return /* @__PURE__ */
|
|
16041
|
+
return /* @__PURE__ */ React37.createElement(Text32, { color: FG.sub }, text);
|
|
15963
16042
|
}
|
|
15964
|
-
return /* @__PURE__ */
|
|
16043
|
+
return /* @__PURE__ */ React37.createElement(React37.Fragment, null, /* @__PURE__ */ React37.createElement(Text32, { color: FG.sub }, text.slice(0, start)), /* @__PURE__ */ React37.createElement(Text32, { bold: true, inverse: true }, text.slice(start, end)), /* @__PURE__ */ React37.createElement(Text32, { color: FG.sub }, text.slice(end)));
|
|
15965
16044
|
}
|
|
15966
16045
|
function groupByFile(hits) {
|
|
15967
16046
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -15974,12 +16053,12 @@ function groupByFile(hits) {
|
|
|
15974
16053
|
}
|
|
15975
16054
|
|
|
15976
16055
|
// src/cli/ui/cards/StreamingCard.tsx
|
|
15977
|
-
import { Box as
|
|
15978
|
-
import
|
|
16056
|
+
import { Box as Box34, Text as Text34, useStdout as useStdout8 } from "ink";
|
|
16057
|
+
import React39 from "react";
|
|
15979
16058
|
|
|
15980
16059
|
// src/cli/ui/markdown.tsx
|
|
15981
16060
|
import { highlight, supportsLanguage } from "cli-highlight";
|
|
15982
|
-
import { Box as
|
|
16061
|
+
import { Box as Box33, Text as Text33 } from "ink";
|
|
15983
16062
|
|
|
15984
16063
|
// node_modules/marked/lib/marked.esm.js
|
|
15985
16064
|
function _getDefaults() {
|
|
@@ -17991,7 +18070,7 @@ var parser = _Parser.parse;
|
|
|
17991
18070
|
var lexer = _Lexer.lex;
|
|
17992
18071
|
|
|
17993
18072
|
// src/cli/ui/markdown.tsx
|
|
17994
|
-
import
|
|
18073
|
+
import React38 from "react";
|
|
17995
18074
|
import stringWidth from "string-width";
|
|
17996
18075
|
function padToCells(text, cells) {
|
|
17997
18076
|
const w = stringWidth(text);
|
|
@@ -18000,41 +18079,41 @@ function padToCells(text, cells) {
|
|
|
18000
18079
|
}
|
|
18001
18080
|
marked.setOptions({ gfm: true, breaks: false });
|
|
18002
18081
|
function Markdown({ text }) {
|
|
18003
|
-
const tokens =
|
|
18004
|
-
return /* @__PURE__ */
|
|
18082
|
+
const tokens = React38.useMemo(() => marked.lexer(text), [text]);
|
|
18083
|
+
return /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column", gap: 1 }, tokens.map((token, i) => /* @__PURE__ */ React38.createElement(BlockToken, { key: `${i}-${token.type}`, token })));
|
|
18005
18084
|
}
|
|
18006
18085
|
function BlockToken({ token }) {
|
|
18007
18086
|
switch (token.type) {
|
|
18008
18087
|
case "heading":
|
|
18009
|
-
return /* @__PURE__ */
|
|
18088
|
+
return /* @__PURE__ */ React38.createElement(Heading, { token });
|
|
18010
18089
|
case "paragraph":
|
|
18011
|
-
return /* @__PURE__ */
|
|
18090
|
+
return /* @__PURE__ */ React38.createElement(Paragraph, { token });
|
|
18012
18091
|
case "list":
|
|
18013
|
-
return /* @__PURE__ */
|
|
18092
|
+
return /* @__PURE__ */ React38.createElement(List, { token, depth: 0 });
|
|
18014
18093
|
case "code":
|
|
18015
|
-
return /* @__PURE__ */
|
|
18094
|
+
return /* @__PURE__ */ React38.createElement(CodeBlock, { token });
|
|
18016
18095
|
case "blockquote":
|
|
18017
|
-
return /* @__PURE__ */
|
|
18096
|
+
return /* @__PURE__ */ React38.createElement(Blockquote, { token });
|
|
18018
18097
|
case "hr":
|
|
18019
|
-
return /* @__PURE__ */
|
|
18098
|
+
return /* @__PURE__ */ React38.createElement(HorizontalRule, null);
|
|
18020
18099
|
case "table":
|
|
18021
|
-
return /* @__PURE__ */
|
|
18100
|
+
return /* @__PURE__ */ React38.createElement(Table, { token });
|
|
18022
18101
|
case "html":
|
|
18023
|
-
return /* @__PURE__ */
|
|
18102
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: FG.body }, token.text);
|
|
18024
18103
|
case "space":
|
|
18025
18104
|
return null;
|
|
18026
18105
|
default:
|
|
18027
|
-
return /* @__PURE__ */
|
|
18106
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: FG.body }, token.raw ?? "");
|
|
18028
18107
|
}
|
|
18029
18108
|
}
|
|
18030
18109
|
function Heading({ token }) {
|
|
18031
|
-
return /* @__PURE__ */
|
|
18110
|
+
return /* @__PURE__ */ React38.createElement(Box33, null, /* @__PURE__ */ React38.createElement(Text33, { bold: true, color: FG.strong, backgroundColor: SURFACE.bgElev }, ` ${plainText(token.tokens)} `));
|
|
18032
18111
|
}
|
|
18033
18112
|
function Paragraph({ token }) {
|
|
18034
|
-
return /* @__PURE__ */
|
|
18113
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: FG.body }, /* @__PURE__ */ React38.createElement(Inline, { tokens: token.tokens ?? [] }));
|
|
18035
18114
|
}
|
|
18036
18115
|
function List({ token, depth }) {
|
|
18037
|
-
return /* @__PURE__ */
|
|
18116
|
+
return /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column" }, token.items.map((item, i) => /* @__PURE__ */ React38.createElement(
|
|
18038
18117
|
ListItem,
|
|
18039
18118
|
{
|
|
18040
18119
|
key: `${i}-${item.text.slice(0, 24)}`,
|
|
@@ -18055,27 +18134,27 @@ function ListItem({
|
|
|
18055
18134
|
const markerColor = item.task ? item.checked ? TONE.ok : FG.faint : FG.meta;
|
|
18056
18135
|
const dim = item.task && item.checked === true;
|
|
18057
18136
|
const indent = " ".repeat(depth + 1);
|
|
18058
|
-
return /* @__PURE__ */
|
|
18137
|
+
return /* @__PURE__ */ React38.createElement(Box33, null, /* @__PURE__ */ React38.createElement(Text33, { color: markerColor }, `${indent}${marker} `), /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column" }, item.tokens.map((tok, i) => {
|
|
18059
18138
|
if (tok.type === "text") {
|
|
18060
18139
|
const inner = tok.tokens;
|
|
18061
18140
|
return (
|
|
18062
18141
|
// biome-ignore lint/suspicious/noArrayIndexKey: list-item children are positional and stable per render
|
|
18063
|
-
/* @__PURE__ */
|
|
18142
|
+
/* @__PURE__ */ React38.createElement(Text33, { key: `t-${i}`, color: dim ? FG.faint : FG.body, strikethrough: dim }, inner ? /* @__PURE__ */ React38.createElement(Inline, { tokens: inner }) : tok.text)
|
|
18064
18143
|
);
|
|
18065
18144
|
}
|
|
18066
18145
|
if (tok.type === "list") {
|
|
18067
|
-
return /* @__PURE__ */
|
|
18146
|
+
return /* @__PURE__ */ React38.createElement(List, { key: `l-${i}`, token: tok, depth: depth + 1 });
|
|
18068
18147
|
}
|
|
18069
|
-
return /* @__PURE__ */
|
|
18148
|
+
return /* @__PURE__ */ React38.createElement(BlockToken, { key: `b-${i}-${tok.type}`, token: tok });
|
|
18070
18149
|
})));
|
|
18071
18150
|
}
|
|
18072
18151
|
function CodeBlock({ token }) {
|
|
18073
18152
|
const lang = token.lang?.split(/\s+/)[0] ?? "";
|
|
18074
18153
|
const colored = highlightCode(token.text, lang);
|
|
18075
18154
|
const lines = colored.split("\n");
|
|
18076
|
-
return /* @__PURE__ */
|
|
18155
|
+
return /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column" }, lang ? /* @__PURE__ */ React38.createElement(Box33, null, /* @__PURE__ */ React38.createElement(Text33, { color: FG.meta }, ` ${lang}`)) : null, /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column" }, lines.map((line, i) => (
|
|
18077
18156
|
// biome-ignore lint/suspicious/noArrayIndexKey: code lines are positional and stable per render
|
|
18078
|
-
/* @__PURE__ */
|
|
18157
|
+
/* @__PURE__ */ React38.createElement(Text33, { key: `code-${i}`, backgroundColor: SURFACE.bgElev }, ` ${line} `)
|
|
18079
18158
|
))));
|
|
18080
18159
|
}
|
|
18081
18160
|
function highlightCode(source, lang) {
|
|
@@ -18088,10 +18167,10 @@ function highlightCode(source, lang) {
|
|
|
18088
18167
|
}
|
|
18089
18168
|
}
|
|
18090
18169
|
function Blockquote({ token }) {
|
|
18091
|
-
return /* @__PURE__ */
|
|
18170
|
+
return /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column" }, (token.tokens ?? []).map((child, i) => /* @__PURE__ */ React38.createElement(Box33, { key: `${i}-${child.type}`, flexDirection: "row" }, /* @__PURE__ */ React38.createElement(Text33, { color: TONE.brand }, " \u258E "), /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column", flexGrow: 1 }, child.type === "paragraph" ? /* @__PURE__ */ React38.createElement(Text33, { italic: true, color: FG.sub }, /* @__PURE__ */ React38.createElement(Inline, { tokens: child.tokens ?? [] })) : /* @__PURE__ */ React38.createElement(BlockToken, { token: child })))));
|
|
18092
18171
|
}
|
|
18093
18172
|
function HorizontalRule() {
|
|
18094
|
-
return /* @__PURE__ */
|
|
18173
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: FG.faint }, " \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
18095
18174
|
}
|
|
18096
18175
|
function Table({ token }) {
|
|
18097
18176
|
const colCount = token.header.length;
|
|
@@ -18106,29 +18185,29 @@ function Table({ token }) {
|
|
|
18106
18185
|
}
|
|
18107
18186
|
const GAP = " ";
|
|
18108
18187
|
const ruleRow = widths.map((w) => "\u2500".repeat(w)).join(GAP);
|
|
18109
|
-
return /* @__PURE__ */
|
|
18188
|
+
return /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column" }, /* @__PURE__ */ React38.createElement(Box33, null, /* @__PURE__ */ React38.createElement(Text33, null, " "), headerCells.map((cell, i) => (
|
|
18110
18189
|
// biome-ignore lint/suspicious/noArrayIndexKey: header cells positional
|
|
18111
|
-
/* @__PURE__ */
|
|
18112
|
-
))), /* @__PURE__ */
|
|
18190
|
+
/* @__PURE__ */ React38.createElement(React38.Fragment, { key: `h-${i}` }, /* @__PURE__ */ React38.createElement(Text33, { bold: true, color: FG.sub }, padToCells(cell, widths[i])), i < colCount - 1 ? /* @__PURE__ */ React38.createElement(Text33, null, GAP) : null)
|
|
18191
|
+
))), /* @__PURE__ */ React38.createElement(Box33, null, /* @__PURE__ */ React38.createElement(Text33, null, " "), /* @__PURE__ */ React38.createElement(Text33, { color: FG.faint }, ruleRow)), bodyCells.map((row3, ri) => (
|
|
18113
18192
|
// biome-ignore lint/suspicious/noArrayIndexKey: body rows positional
|
|
18114
|
-
/* @__PURE__ */
|
|
18193
|
+
/* @__PURE__ */ React38.createElement(Box33, { key: `tr-${ri}` }, /* @__PURE__ */ React38.createElement(Text33, null, " "), row3.map((cell, i) => (
|
|
18115
18194
|
// biome-ignore lint/suspicious/noArrayIndexKey: cells positional
|
|
18116
|
-
/* @__PURE__ */
|
|
18195
|
+
/* @__PURE__ */ React38.createElement(React38.Fragment, { key: `c-${ri}-${i}` }, /* @__PURE__ */ React38.createElement(Text33, { color: FG.body }, padToCells(cell ?? "", widths[i])), i < colCount - 1 ? /* @__PURE__ */ React38.createElement(Text33, null, GAP) : null)
|
|
18117
18196
|
)))
|
|
18118
18197
|
)));
|
|
18119
18198
|
}
|
|
18120
18199
|
function Inline({ tokens }) {
|
|
18121
|
-
return /* @__PURE__ */
|
|
18200
|
+
return /* @__PURE__ */ React38.createElement(React38.Fragment, null, tokens.map((tok, i) => /* @__PURE__ */ React38.createElement(InlineToken, { key: `${i}-${tok.type}`, token: tok })));
|
|
18122
18201
|
}
|
|
18123
18202
|
var FILE_REF_RE = /\b([A-Za-z0-9_./@\-]+\.[A-Za-z0-9]{1,6})(?::(\d+)(?:-(\d+))?)?\b/g;
|
|
18124
18203
|
var MENTION_RE = /(?<![A-Za-z0-9_])@([A-Za-z0-9_./\-]+\.[A-Za-z0-9]{1,6})/g;
|
|
18125
18204
|
function osc8(label, target, color2) {
|
|
18126
18205
|
const open = `\x1B]8;;${target}\x07`;
|
|
18127
18206
|
const close = "\x1B]8;;\x07";
|
|
18128
|
-
return /* @__PURE__ */
|
|
18207
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: color2, underline: true }, `${open}${label}${close}`);
|
|
18129
18208
|
}
|
|
18130
18209
|
function renderInlineText(raw) {
|
|
18131
|
-
if (!raw) return /* @__PURE__ */
|
|
18210
|
+
if (!raw) return /* @__PURE__ */ React38.createElement(Text33, null, raw);
|
|
18132
18211
|
const out = [];
|
|
18133
18212
|
let cursor = 0;
|
|
18134
18213
|
const hits = [];
|
|
@@ -18139,7 +18218,7 @@ function renderInlineText(raw) {
|
|
|
18139
18218
|
hits.push({
|
|
18140
18219
|
start,
|
|
18141
18220
|
end,
|
|
18142
|
-
node: /* @__PURE__ */
|
|
18221
|
+
node: /* @__PURE__ */ React38.createElement(Text33, { color: TONE.warn, underline: true }, `@${path5}`)
|
|
18143
18222
|
});
|
|
18144
18223
|
}
|
|
18145
18224
|
for (const m of raw.matchAll(FILE_REF_RE)) {
|
|
@@ -18155,44 +18234,44 @@ function renderInlineText(raw) {
|
|
|
18155
18234
|
let key = 0;
|
|
18156
18235
|
for (const h of hits) {
|
|
18157
18236
|
if (h.start > cursor) {
|
|
18158
|
-
out.push(/* @__PURE__ */
|
|
18237
|
+
out.push(/* @__PURE__ */ React38.createElement(Text33, { key: `t-${key++}` }, raw.slice(cursor, h.start)));
|
|
18159
18238
|
}
|
|
18160
|
-
out.push(/* @__PURE__ */
|
|
18239
|
+
out.push(/* @__PURE__ */ React38.createElement(React38.Fragment, { key: `r-${key++}` }, h.node));
|
|
18161
18240
|
cursor = h.end;
|
|
18162
18241
|
}
|
|
18163
|
-
if (cursor < raw.length) out.push(/* @__PURE__ */
|
|
18164
|
-
return /* @__PURE__ */
|
|
18242
|
+
if (cursor < raw.length) out.push(/* @__PURE__ */ React38.createElement(Text33, { key: `t-${key++}` }, raw.slice(cursor)));
|
|
18243
|
+
return /* @__PURE__ */ React38.createElement(React38.Fragment, null, out);
|
|
18165
18244
|
}
|
|
18166
18245
|
function InlineToken({ token }) {
|
|
18167
18246
|
switch (token.type) {
|
|
18168
18247
|
case "text": {
|
|
18169
18248
|
const t2 = token;
|
|
18170
|
-
return t2.tokens ? /* @__PURE__ */
|
|
18249
|
+
return t2.tokens ? /* @__PURE__ */ React38.createElement(Inline, { tokens: t2.tokens }) : renderInlineText(t2.text);
|
|
18171
18250
|
}
|
|
18172
18251
|
case "strong":
|
|
18173
|
-
return /* @__PURE__ */
|
|
18252
|
+
return /* @__PURE__ */ React38.createElement(Text33, { bold: true, color: FG.strong }, /* @__PURE__ */ React38.createElement(Inline, { tokens: token.tokens }));
|
|
18174
18253
|
case "em":
|
|
18175
|
-
return /* @__PURE__ */
|
|
18254
|
+
return /* @__PURE__ */ React38.createElement(Text33, { italic: true }, /* @__PURE__ */ React38.createElement(Inline, { tokens: token.tokens }));
|
|
18176
18255
|
case "codespan":
|
|
18177
|
-
return /* @__PURE__ */
|
|
18256
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: FG.strong, backgroundColor: SURFACE.bgElev }, ` ${token.text} `);
|
|
18178
18257
|
case "del":
|
|
18179
|
-
return /* @__PURE__ */
|
|
18258
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: TONE.err, strikethrough: true }, /* @__PURE__ */ React38.createElement(Inline, { tokens: token.tokens }));
|
|
18180
18259
|
case "link": {
|
|
18181
18260
|
const l = token;
|
|
18182
|
-
return /* @__PURE__ */
|
|
18261
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: TONE.brand, underline: true }, /* @__PURE__ */ React38.createElement(Inline, { tokens: l.tokens }));
|
|
18183
18262
|
}
|
|
18184
18263
|
case "image": {
|
|
18185
18264
|
const im = token;
|
|
18186
|
-
return /* @__PURE__ */
|
|
18265
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: TONE.brand }, `[image: ${im.text || im.href}]`);
|
|
18187
18266
|
}
|
|
18188
18267
|
case "br":
|
|
18189
|
-
return /* @__PURE__ */
|
|
18268
|
+
return /* @__PURE__ */ React38.createElement(Text33, null, "\n");
|
|
18190
18269
|
case "escape":
|
|
18191
|
-
return /* @__PURE__ */
|
|
18270
|
+
return /* @__PURE__ */ React38.createElement(Text33, null, token.text);
|
|
18192
18271
|
case "html":
|
|
18193
|
-
return /* @__PURE__ */
|
|
18272
|
+
return /* @__PURE__ */ React38.createElement(Text33, null, token.text);
|
|
18194
18273
|
default:
|
|
18195
|
-
return /* @__PURE__ */
|
|
18274
|
+
return /* @__PURE__ */ React38.createElement(Text33, null, token.raw ?? "");
|
|
18196
18275
|
}
|
|
18197
18276
|
}
|
|
18198
18277
|
function plainText(tokens) {
|
|
@@ -18230,7 +18309,7 @@ var RESERVED_CHROME_ROWS = 14;
|
|
|
18230
18309
|
var BODY_INDENT_CELLS2 = 5;
|
|
18231
18310
|
function StreamingCard({ card }) {
|
|
18232
18311
|
if (card.done && !card.aborted) {
|
|
18233
|
-
return /* @__PURE__ */
|
|
18312
|
+
return /* @__PURE__ */ React39.createElement(Box34, { flexDirection: "column", paddingLeft: 3 }, /* @__PURE__ */ React39.createElement(Markdown, { text: card.text }));
|
|
18234
18313
|
}
|
|
18235
18314
|
const { stdout: stdout4 } = useStdout8();
|
|
18236
18315
|
const rows = stdout4?.rows ?? 40;
|
|
@@ -18243,8 +18322,8 @@ function StreamingCard({ card }) {
|
|
|
18243
18322
|
const overflows = !card.done && allLines.length > lineSlots;
|
|
18244
18323
|
const visible = overflows ? allLines.slice(-lineSlots) : allLines;
|
|
18245
18324
|
const headDropped = overflows ? allLines.length - visible.length : 0;
|
|
18246
|
-
return /* @__PURE__ */
|
|
18247
|
-
|
|
18325
|
+
return /* @__PURE__ */ React39.createElement(Box34, { flexDirection: "column" }, card.aborted && /* @__PURE__ */ React39.createElement(BarRow, { tone: "streaming", glyph: "\u2014" }, /* @__PURE__ */ React39.createElement(Text34, { color: FG.faint, bold: true }, "\u2014 aborted \u2014"), /* @__PURE__ */ React39.createElement(Text34, { color: TONE.warn }, " stopped")), headDropped > 0 && /* @__PURE__ */ React39.createElement(BarRow, { tone: "streaming", glyph: "\u25BE" }, /* @__PURE__ */ React39.createElement(
|
|
18326
|
+
Text34,
|
|
18248
18327
|
{
|
|
18249
18328
|
color: FG.faint
|
|
18250
18329
|
},
|
|
@@ -18252,58 +18331,58 @@ function StreamingCard({ card }) {
|
|
|
18252
18331
|
)), visible.map((line, i) => {
|
|
18253
18332
|
const isLast = i === visible.length - 1;
|
|
18254
18333
|
const isFirstRendered = !card.aborted && headDropped === 0 && i === 0;
|
|
18255
|
-
return /* @__PURE__ */
|
|
18334
|
+
return /* @__PURE__ */ React39.createElement(
|
|
18256
18335
|
BarRow,
|
|
18257
18336
|
{
|
|
18258
18337
|
key: `${card.id}:${headDropped + i}`,
|
|
18259
18338
|
tone: "streaming",
|
|
18260
18339
|
glyph: isFirstRendered ? "\u25B6" : void 0
|
|
18261
18340
|
},
|
|
18262
|
-
/* @__PURE__ */
|
|
18263
|
-
isLast && !card.done && /* @__PURE__ */
|
|
18341
|
+
/* @__PURE__ */ React39.createElement(Text34, { color: card.aborted ? FG.meta : FG.body }, clipToCells(line, lineCells)),
|
|
18342
|
+
isLast && !card.done && /* @__PURE__ */ React39.createElement(CursorBlock, null)
|
|
18264
18343
|
);
|
|
18265
|
-
}), card.aborted && /* @__PURE__ */
|
|
18344
|
+
}), card.aborted && /* @__PURE__ */ React39.createElement(BarRow, { tone: "streaming" }, /* @__PURE__ */ React39.createElement(Text34, { color: FG.faint }, "[truncated by esc]")));
|
|
18266
18345
|
}
|
|
18267
18346
|
|
|
18268
18347
|
// src/cli/ui/cards/SubAgentCard.tsx
|
|
18269
|
-
import { Box as
|
|
18270
|
-
import
|
|
18348
|
+
import { Box as Box35, Text as Text35 } from "ink";
|
|
18349
|
+
import React40 from "react";
|
|
18271
18350
|
var STATUS_COLOR2 = {
|
|
18272
18351
|
running: TONE.violet,
|
|
18273
18352
|
done: TONE.ok,
|
|
18274
18353
|
failed: TONE.err
|
|
18275
18354
|
};
|
|
18276
18355
|
function SubAgentCard({ card }) {
|
|
18277
|
-
return /* @__PURE__ */
|
|
18356
|
+
return /* @__PURE__ */ React40.createElement(Box35, { flexDirection: "column" }, /* @__PURE__ */ React40.createElement(
|
|
18278
18357
|
CardHeader,
|
|
18279
18358
|
{
|
|
18280
18359
|
tone: "subagent",
|
|
18281
18360
|
glyph: "\u232C",
|
|
18282
18361
|
title: `Sub-agent \xB7 ${card.name}`,
|
|
18283
|
-
trailing: /* @__PURE__ */
|
|
18362
|
+
trailing: /* @__PURE__ */ React40.createElement(Text35, { color: STATUS_COLOR2[card.status] }, card.status)
|
|
18284
18363
|
}
|
|
18285
|
-
), /* @__PURE__ */
|
|
18364
|
+
), /* @__PURE__ */ React40.createElement(BarRow, { tone: "subagent", indent: 0 }), /* @__PURE__ */ React40.createElement(BarRow, { tone: "subagent" }, /* @__PURE__ */ React40.createElement(Text35, { color: FG.faint }, "Task "), /* @__PURE__ */ React40.createElement(Text35, { color: FG.sub }, card.task)), card.tools && card.tools.length > 0 && /* @__PURE__ */ React40.createElement(BarRow, { tone: "subagent" }, /* @__PURE__ */ React40.createElement(Text35, { color: FG.faint }, "Tools "), /* @__PURE__ */ React40.createElement(Text35, { color: FG.sub }, card.tools.join(", "))), card.children.length > 0 && /* @__PURE__ */ React40.createElement(React40.Fragment, null, /* @__PURE__ */ React40.createElement(BarRow, { tone: "subagent", indent: 0 }), /* @__PURE__ */ React40.createElement(BarRow, { tone: "subagent" }, /* @__PURE__ */ React40.createElement(Text35, { color: FG.meta }, "sub-agent stream")), card.children.map((child) => /* @__PURE__ */ React40.createElement(BarRow, { key: child.id, tone: "subagent" }, /* @__PURE__ */ React40.createElement(Text35, { color: CARD.subagent.color }, "\u258E "), /* @__PURE__ */ React40.createElement(ChildSummary, { card: child })))));
|
|
18286
18365
|
}
|
|
18287
18366
|
function ChildSummary({ card }) {
|
|
18288
18367
|
switch (card.kind) {
|
|
18289
18368
|
case "reasoning":
|
|
18290
|
-
return /* @__PURE__ */
|
|
18369
|
+
return /* @__PURE__ */ React40.createElement(React40.Fragment, null, /* @__PURE__ */ React40.createElement(Text35, { color: CARD.reasoning.color }, "\u25C6 "), /* @__PURE__ */ React40.createElement(Text35, { italic: true, color: FG.meta }, `Reasoning \xB7 ${card.paragraphs} paragraph${card.paragraphs === 1 ? "" : "s"}`));
|
|
18291
18370
|
case "tool":
|
|
18292
|
-
return /* @__PURE__ */
|
|
18371
|
+
return /* @__PURE__ */ React40.createElement(React40.Fragment, null, /* @__PURE__ */ React40.createElement(Text35, { color: CARD.tool.color }, "\u25A3 "), /* @__PURE__ */ React40.createElement(Text35, { bold: true, color: FG.body }, card.name), card.elapsedMs > 0 && /* @__PURE__ */ React40.createElement(Text35, { color: FG.faint }, ` ${(card.elapsedMs / 1e3).toFixed(2)}s`));
|
|
18293
18372
|
case "streaming":
|
|
18294
|
-
return /* @__PURE__ */
|
|
18373
|
+
return /* @__PURE__ */ React40.createElement(React40.Fragment, null, /* @__PURE__ */ React40.createElement(Text35, { color: CARD.streaming.color }, "\u25B6 "), /* @__PURE__ */ React40.createElement(Text35, { color: card.done ? FG.sub : TONE.brand }, card.done ? "response" : "streaming response \u2026"));
|
|
18295
18374
|
case "diff":
|
|
18296
|
-
return /* @__PURE__ */
|
|
18375
|
+
return /* @__PURE__ */ React40.createElement(React40.Fragment, null, /* @__PURE__ */ React40.createElement(Text35, { color: CARD.diff.color }, "\xB1 "), /* @__PURE__ */ React40.createElement(Text35, { color: FG.sub }, card.file));
|
|
18297
18376
|
case "error":
|
|
18298
|
-
return /* @__PURE__ */
|
|
18377
|
+
return /* @__PURE__ */ React40.createElement(React40.Fragment, null, /* @__PURE__ */ React40.createElement(Text35, { color: CARD.error.color }, "\u2716 "), /* @__PURE__ */ React40.createElement(Text35, { color: FG.sub }, card.title));
|
|
18299
18378
|
default:
|
|
18300
|
-
return /* @__PURE__ */
|
|
18379
|
+
return /* @__PURE__ */ React40.createElement(Text35, { color: FG.faint }, `\xB7 ${card.kind}`);
|
|
18301
18380
|
}
|
|
18302
18381
|
}
|
|
18303
18382
|
|
|
18304
18383
|
// src/cli/ui/cards/TaskCard.tsx
|
|
18305
|
-
import { Box as
|
|
18306
|
-
import
|
|
18384
|
+
import { Box as Box36, Text as Text36 } from "ink";
|
|
18385
|
+
import React41 from "react";
|
|
18307
18386
|
var STEP_GLYPH = {
|
|
18308
18387
|
queued: "\u25CB",
|
|
18309
18388
|
running: "\u25B6",
|
|
@@ -18329,22 +18408,22 @@ var TASK_GLYPH = {
|
|
|
18329
18408
|
function TaskCard({ card }) {
|
|
18330
18409
|
const elapsed = `${(card.elapsedMs / 1e3).toFixed(1)}s`;
|
|
18331
18410
|
const showSteps = card.steps.length > 0;
|
|
18332
|
-
return /* @__PURE__ */
|
|
18411
|
+
return /* @__PURE__ */ React41.createElement(Box36, { flexDirection: "column" }, /* @__PURE__ */ React41.createElement(
|
|
18333
18412
|
CardHeader,
|
|
18334
18413
|
{
|
|
18335
18414
|
tone: "task",
|
|
18336
18415
|
glyph: TASK_GLYPH[card.status],
|
|
18337
18416
|
title: `Step ${card.index} of ${card.total} \xB7 ${card.title}`,
|
|
18338
18417
|
meta: `${elapsed} \xB7 `,
|
|
18339
|
-
trailing: /* @__PURE__ */
|
|
18418
|
+
trailing: /* @__PURE__ */ React41.createElement(Text36, { color: TASK_COLOR[card.status] }, card.status),
|
|
18340
18419
|
barColor: TASK_COLOR[card.status]
|
|
18341
18420
|
}
|
|
18342
|
-
), showSteps && /* @__PURE__ */
|
|
18421
|
+
), showSteps && /* @__PURE__ */ React41.createElement(React41.Fragment, null, /* @__PURE__ */ React41.createElement(BarRow, { tone: "task", indent: 0 }), card.steps.map((step) => /* @__PURE__ */ React41.createElement(BarRow, { key: step.id, tone: "task" }, /* @__PURE__ */ React41.createElement(Text36, { color: STEP_COLOR[step.status] }, STEP_GLYPH[step.status]), /* @__PURE__ */ React41.createElement(Text36, { bold: true, color: FG.body }, ` ${(step.toolName ?? "step").padEnd(7)} `), /* @__PURE__ */ React41.createElement(Text36, { color: FG.sub }, step.title), step.detail && /* @__PURE__ */ React41.createElement(Text36, { color: FG.faint }, ` ${step.detail}`), step.elapsedMs !== void 0 && /* @__PURE__ */ React41.createElement(Text36, { color: FG.faint }, ` ${(step.elapsedMs / 1e3).toFixed(2)}s`)))));
|
|
18343
18422
|
}
|
|
18344
18423
|
|
|
18345
18424
|
// src/cli/ui/cards/ToolCard.tsx
|
|
18346
|
-
import { Box as
|
|
18347
|
-
import
|
|
18425
|
+
import { Box as Box37, Text as Text37, useStdout as useStdout9 } from "ink";
|
|
18426
|
+
import React42 from "react";
|
|
18348
18427
|
var READ_TAIL = 2;
|
|
18349
18428
|
var OTHER_TAIL = 5;
|
|
18350
18429
|
var BODY_INDENT_CELLS3 = 5;
|
|
@@ -18365,7 +18444,7 @@ function ToolCard({ card }) {
|
|
|
18365
18444
|
const hidden = truncated ? allLines.length - visible.length : 0;
|
|
18366
18445
|
const errColor = card.exitCode && card.exitCode !== 0 ? CARD.error.color : FG.sub;
|
|
18367
18446
|
const showBody = visible.length > 0;
|
|
18368
|
-
return /* @__PURE__ */
|
|
18447
|
+
return /* @__PURE__ */ React42.createElement(Box37, { flexDirection: "column" }, /* @__PURE__ */ React42.createElement(
|
|
18369
18448
|
CardHeader,
|
|
18370
18449
|
{
|
|
18371
18450
|
tone: "tool",
|
|
@@ -18373,10 +18452,10 @@ function ToolCard({ card }) {
|
|
|
18373
18452
|
title: card.name,
|
|
18374
18453
|
subtitle: argsLabel || void 0,
|
|
18375
18454
|
meta: meta || void 0,
|
|
18376
|
-
inline: !card.done ? /* @__PURE__ */
|
|
18377
|
-
trailing: card.retry ? /* @__PURE__ */
|
|
18455
|
+
inline: !card.done ? /* @__PURE__ */ React42.createElement(Spinner, { kind: "braille", color: CARD.tool.color, bold: true }) : void 0,
|
|
18456
|
+
trailing: card.retry ? /* @__PURE__ */ React42.createElement(Text37, { color: TONE.warn, bold: true }, `\u21BB retry ${card.retry.attempt}/${card.retry.max}`) : void 0
|
|
18378
18457
|
}
|
|
18379
|
-
), showBody && /* @__PURE__ */
|
|
18458
|
+
), showBody && /* @__PURE__ */ React42.createElement(React42.Fragment, null, /* @__PURE__ */ React42.createElement(BarRow, { tone: "tool", indent: 0 }), hidden > 0 && /* @__PURE__ */ React42.createElement(BarRow, { tone: "tool" }, /* @__PURE__ */ React42.createElement(Text37, { color: FG.faint }, `\u22EE ${hidden} earlier line${hidden === 1 ? "" : "s"} (use /tool to read full)`)), visible.map((line, i) => /* @__PURE__ */ React42.createElement(BarRow, { key: `${card.id}:${hidden + i}`, tone: "tool" }, /* @__PURE__ */ React42.createElement(Text37, { color: errColor }, clipToCells(line, lineCells))))));
|
|
18380
18459
|
}
|
|
18381
18460
|
function formatArgsSummary(args) {
|
|
18382
18461
|
if (typeof args === "string") return args.length > 60 ? `${args.slice(0, 60)}\u2026` : args;
|
|
@@ -18408,8 +18487,8 @@ function formatMeta(card) {
|
|
|
18408
18487
|
}
|
|
18409
18488
|
|
|
18410
18489
|
// src/cli/ui/cards/UsageCard.tsx
|
|
18411
|
-
import { Box as
|
|
18412
|
-
import
|
|
18490
|
+
import { Box as Box38, Text as Text38 } from "ink";
|
|
18491
|
+
import React43 from "react";
|
|
18413
18492
|
var BAR_CELLS3 = 30;
|
|
18414
18493
|
function compactNum(n) {
|
|
18415
18494
|
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
@@ -18419,32 +18498,32 @@ function compactNum(n) {
|
|
|
18419
18498
|
function bar(ratio, color2) {
|
|
18420
18499
|
const filled = Math.max(0, Math.min(BAR_CELLS3, Math.round(ratio * BAR_CELLS3)));
|
|
18421
18500
|
const empty = BAR_CELLS3 - filled;
|
|
18422
|
-
return /* @__PURE__ */
|
|
18501
|
+
return /* @__PURE__ */ React43.createElement(React43.Fragment, null, /* @__PURE__ */ React43.createElement(Text38, { color: color2 }, "\u2588".repeat(filled)), /* @__PURE__ */ React43.createElement(Text38, { color: FG.faint }, "\u2591".repeat(empty)));
|
|
18423
18502
|
}
|
|
18424
18503
|
function UsageCard({ card }) {
|
|
18425
|
-
if (card.compact) return /* @__PURE__ */
|
|
18504
|
+
if (card.compact) return /* @__PURE__ */ React43.createElement(CompactUsageRow, { card });
|
|
18426
18505
|
const cap = Math.max(1, card.tokens.promptCap);
|
|
18427
18506
|
const promptRatio = card.tokens.prompt / cap;
|
|
18428
18507
|
const reasonRatio = card.tokens.reason / cap;
|
|
18429
18508
|
const outputRatio = card.tokens.output / cap;
|
|
18430
18509
|
const elapsed = card.elapsedMs !== void 0 ? ` \xB7 ${(card.elapsedMs / 1e3).toFixed(1)}s` : "";
|
|
18431
18510
|
const meta = `${formatCNY(card.cost)}${elapsed}`;
|
|
18432
|
-
return /* @__PURE__ */
|
|
18511
|
+
return /* @__PURE__ */ React43.createElement(Box38, { flexDirection: "column" }, /* @__PURE__ */ React43.createElement(CardHeader, { tone: "usage", glyph: "\u03A3", title: "Usage", subtitle: `turn ${card.turn}`, meta }), /* @__PURE__ */ React43.createElement(BarRow, { tone: "usage", indent: 0 }), /* @__PURE__ */ React43.createElement(BarRow, { tone: "usage" }, /* @__PURE__ */ React43.createElement(Text38, { color: FG.sub }, "prompt "), bar(promptRatio, TONE.brand), /* @__PURE__ */ React43.createElement(Text38, { bold: true, color: FG.body }, ` ${card.tokens.prompt.toLocaleString()}`), /* @__PURE__ */ React43.createElement(Text38, { color: FG.faint }, ` / 1M \xB7 ${(promptRatio * 100).toFixed(1)}%`)), /* @__PURE__ */ React43.createElement(BarRow, { tone: "usage" }, /* @__PURE__ */ React43.createElement(Text38, { color: FG.sub }, "reason "), bar(reasonRatio, TONE.accent), /* @__PURE__ */ React43.createElement(Text38, { bold: true, color: FG.body }, ` ${card.tokens.reason.toLocaleString()}`)), /* @__PURE__ */ React43.createElement(BarRow, { tone: "usage" }, /* @__PURE__ */ React43.createElement(Text38, { color: FG.sub }, "output "), bar(outputRatio, TONE.brand), /* @__PURE__ */ React43.createElement(Text38, { bold: true, color: FG.body }, ` ${card.tokens.output.toLocaleString()}`)), /* @__PURE__ */ React43.createElement(BarRow, { tone: "usage", indent: 0 }), /* @__PURE__ */ React43.createElement(BarRow, { tone: "usage" }, /* @__PURE__ */ React43.createElement(Text38, { color: FG.sub }, "cache hit "), bar(card.cacheHit, TONE.ok), /* @__PURE__ */ React43.createElement(Text38, { bold: true, color: TONE.ok }, ` ${(card.cacheHit * 100).toFixed(1)}%`)), /* @__PURE__ */ React43.createElement(BarRow, { tone: "usage", indent: 0 }), /* @__PURE__ */ React43.createElement(BarRow, { tone: "usage" }, /* @__PURE__ */ React43.createElement(Text38, { color: FG.faint }, "session "), /* @__PURE__ */ React43.createElement(Text38, { bold: true, color: FG.body }, `\u26C1 ${formatCNY(card.sessionCost, 3)}`), card.balance !== void 0 && /* @__PURE__ */ React43.createElement(React43.Fragment, null, /* @__PURE__ */ React43.createElement(Text38, { color: FG.meta }, " \xB7 "), /* @__PURE__ */ React43.createElement(Text38, { color: FG.faint }, "balance "), /* @__PURE__ */ React43.createElement(Text38, { bold: true, color: TONE.brand }, `\xA5${card.balance.toFixed(2)}`))));
|
|
18433
18512
|
}
|
|
18434
18513
|
function CompactUsageRow({ card }) {
|
|
18435
18514
|
const elapsed = card.elapsedMs !== void 0 ? ` \xB7 ${(card.elapsedMs / 1e3).toFixed(1)}s` : "";
|
|
18436
|
-
return /* @__PURE__ */
|
|
18437
|
-
|
|
18515
|
+
return /* @__PURE__ */ React43.createElement(Box38, null, /* @__PURE__ */ React43.createElement(Text38, { color: FG.faint }, ` \u03A3 turn ${card.turn} \xB7 `), /* @__PURE__ */ React43.createElement(
|
|
18516
|
+
Text38,
|
|
18438
18517
|
{
|
|
18439
18518
|
color: FG.meta
|
|
18440
18519
|
},
|
|
18441
18520
|
`${compactNum(card.tokens.prompt)} prompt \xB7 ${compactNum(card.tokens.output)} out`
|
|
18442
|
-
), /* @__PURE__ */
|
|
18521
|
+
), /* @__PURE__ */ React43.createElement(Text38, { color: FG.faint }, " \xB7 cache "), /* @__PURE__ */ React43.createElement(Text38, { color: TONE.ok }, `${(card.cacheHit * 100).toFixed(0)}%`), /* @__PURE__ */ React43.createElement(Text38, { color: FG.faint }, ` \xB7 ${formatCNY(card.cost)}${elapsed}`), card.balance !== void 0 && /* @__PURE__ */ React43.createElement(React43.Fragment, null, /* @__PURE__ */ React43.createElement(Text38, { color: FG.faint }, " \xB7 "), /* @__PURE__ */ React43.createElement(Text38, { color: TONE.brand }, `\xA5${card.balance.toFixed(2)}`)));
|
|
18443
18522
|
}
|
|
18444
18523
|
|
|
18445
18524
|
// src/cli/ui/cards/UserCard.tsx
|
|
18446
|
-
import { Box as
|
|
18447
|
-
import
|
|
18525
|
+
import { Box as Box39, Text as Text39 } from "ink";
|
|
18526
|
+
import React44 from "react";
|
|
18448
18527
|
|
|
18449
18528
|
// src/cli/ui/cards/time.ts
|
|
18450
18529
|
function formatRelativeTime(ts, now = Date.now()) {
|
|
@@ -18461,15 +18540,15 @@ function formatRelativeTime(ts, now = Date.now()) {
|
|
|
18461
18540
|
|
|
18462
18541
|
// src/cli/ui/cards/UserCard.tsx
|
|
18463
18542
|
function UserCard({ card }) {
|
|
18464
|
-
return /* @__PURE__ */
|
|
18543
|
+
return /* @__PURE__ */ React44.createElement(Box39, { flexDirection: "column" }, /* @__PURE__ */ React44.createElement(Box39, { flexDirection: "row" }, /* @__PURE__ */ React44.createElement(Text39, null, " "), /* @__PURE__ */ React44.createElement(Text39, { color: FG.meta }, "\u25C7"), /* @__PURE__ */ React44.createElement(Text39, { bold: true, color: FG.sub }, " you"), /* @__PURE__ */ React44.createElement(Text39, { color: FG.faint }, ` \xB7 ${formatRelativeTime(card.ts)}`)), /* @__PURE__ */ React44.createElement(Box39, { flexDirection: "column", paddingLeft: 4 }, /* @__PURE__ */ React44.createElement(Markdown, { text: card.text })));
|
|
18465
18544
|
}
|
|
18466
18545
|
|
|
18467
18546
|
// src/cli/ui/cards/WarnCard.tsx
|
|
18468
|
-
import { Box as
|
|
18469
|
-
import
|
|
18547
|
+
import { Box as Box40, Text as Text40 } from "ink";
|
|
18548
|
+
import React45 from "react";
|
|
18470
18549
|
function WarnCard({ card }) {
|
|
18471
18550
|
const showBody = card.message.length > 0;
|
|
18472
|
-
return /* @__PURE__ */
|
|
18551
|
+
return /* @__PURE__ */ React45.createElement(Box40, { flexDirection: "column" }, /* @__PURE__ */ React45.createElement(
|
|
18473
18552
|
CardHeader,
|
|
18474
18553
|
{
|
|
18475
18554
|
tone: "warn",
|
|
@@ -18477,7 +18556,7 @@ function WarnCard({ card }) {
|
|
|
18477
18556
|
title: card.title,
|
|
18478
18557
|
meta: card.detail ? `\xB7 ${card.detail}` : void 0
|
|
18479
18558
|
}
|
|
18480
|
-
), showBody && /* @__PURE__ */
|
|
18559
|
+
), showBody && /* @__PURE__ */ React45.createElement(React45.Fragment, null, /* @__PURE__ */ React45.createElement(BarRow, { tone: "warn", indent: 0 }), card.message.split("\n").map((line, i) => /* @__PURE__ */ React45.createElement(BarRow, { key: `${card.id}:${i}`, tone: "warn" }, /* @__PURE__ */ React45.createElement(Text40, { color: FG.body }, line)))));
|
|
18481
18560
|
}
|
|
18482
18561
|
|
|
18483
18562
|
// src/cli/ui/cards/CardRenderer.tsx
|
|
@@ -18485,52 +18564,52 @@ function CardRenderer({ card }) {
|
|
|
18485
18564
|
const contentStreaming = useAgentState(
|
|
18486
18565
|
(s) => s.cards.some((c) => c.kind === "streaming" && c.text.length > 0 && !c.done)
|
|
18487
18566
|
);
|
|
18488
|
-
return /* @__PURE__ */
|
|
18567
|
+
return /* @__PURE__ */ React46.createElement(Box41, { flexDirection: "column", marginTop: 1 }, renderCard(card, contentStreaming));
|
|
18489
18568
|
}
|
|
18490
18569
|
function renderCard(card, contentStreaming) {
|
|
18491
18570
|
switch (card.kind) {
|
|
18492
18571
|
case "user":
|
|
18493
|
-
return /* @__PURE__ */
|
|
18572
|
+
return /* @__PURE__ */ React46.createElement(UserCard, { card });
|
|
18494
18573
|
case "reasoning":
|
|
18495
|
-
return /* @__PURE__ */
|
|
18574
|
+
return /* @__PURE__ */ React46.createElement(ReasoningCard, { card, expanded: !(card.streaming && contentStreaming) });
|
|
18496
18575
|
case "streaming":
|
|
18497
|
-
return /* @__PURE__ */
|
|
18576
|
+
return /* @__PURE__ */ React46.createElement(StreamingCard, { card });
|
|
18498
18577
|
case "tool":
|
|
18499
|
-
return /* @__PURE__ */
|
|
18578
|
+
return /* @__PURE__ */ React46.createElement(ToolCard, { card });
|
|
18500
18579
|
case "task":
|
|
18501
|
-
return /* @__PURE__ */
|
|
18580
|
+
return /* @__PURE__ */ React46.createElement(TaskCard, { card });
|
|
18502
18581
|
case "plan":
|
|
18503
|
-
return /* @__PURE__ */
|
|
18582
|
+
return /* @__PURE__ */ React46.createElement(PlanCard, { card });
|
|
18504
18583
|
case "diff":
|
|
18505
|
-
return /* @__PURE__ */
|
|
18584
|
+
return /* @__PURE__ */ React46.createElement(DiffCard, { card });
|
|
18506
18585
|
case "error":
|
|
18507
|
-
return /* @__PURE__ */
|
|
18586
|
+
return /* @__PURE__ */ React46.createElement(ErrorCard, { card });
|
|
18508
18587
|
case "warn":
|
|
18509
|
-
return /* @__PURE__ */
|
|
18588
|
+
return /* @__PURE__ */ React46.createElement(WarnCard, { card });
|
|
18510
18589
|
case "usage":
|
|
18511
|
-
return /* @__PURE__ */
|
|
18590
|
+
return /* @__PURE__ */ React46.createElement(UsageCard, { card });
|
|
18512
18591
|
case "memory":
|
|
18513
|
-
return /* @__PURE__ */
|
|
18592
|
+
return /* @__PURE__ */ React46.createElement(MemoryCard, { card });
|
|
18514
18593
|
case "subagent":
|
|
18515
|
-
return /* @__PURE__ */
|
|
18594
|
+
return /* @__PURE__ */ React46.createElement(SubAgentCard, { card });
|
|
18516
18595
|
case "search":
|
|
18517
|
-
return /* @__PURE__ */
|
|
18596
|
+
return /* @__PURE__ */ React46.createElement(SearchCard, { card });
|
|
18518
18597
|
case "approval":
|
|
18519
|
-
return /* @__PURE__ */
|
|
18598
|
+
return /* @__PURE__ */ React46.createElement(FallbackCard, { card });
|
|
18520
18599
|
case "live":
|
|
18521
|
-
return /* @__PURE__ */
|
|
18600
|
+
return /* @__PURE__ */ React46.createElement(LiveCard, { card });
|
|
18522
18601
|
case "ctx":
|
|
18523
|
-
return /* @__PURE__ */
|
|
18602
|
+
return /* @__PURE__ */ React46.createElement(CtxCard, { card });
|
|
18524
18603
|
case "doctor":
|
|
18525
|
-
return /* @__PURE__ */
|
|
18604
|
+
return /* @__PURE__ */ React46.createElement(DoctorCard, { card });
|
|
18526
18605
|
case "branch":
|
|
18527
|
-
return /* @__PURE__ */
|
|
18606
|
+
return /* @__PURE__ */ React46.createElement(BranchCard, { card });
|
|
18528
18607
|
default:
|
|
18529
|
-
return /* @__PURE__ */
|
|
18608
|
+
return /* @__PURE__ */ React46.createElement(FallbackCard, { card });
|
|
18530
18609
|
}
|
|
18531
18610
|
}
|
|
18532
18611
|
function FallbackCard({ card }) {
|
|
18533
|
-
return /* @__PURE__ */
|
|
18612
|
+
return /* @__PURE__ */ React46.createElement(Box41, { flexDirection: "row" }, /* @__PURE__ */ React46.createElement(Text41, { color: FG.faint }, ` \xB7 ${card.kind} card \xB7 not yet migrated`));
|
|
18534
18613
|
}
|
|
18535
18614
|
|
|
18536
18615
|
// src/cli/ui/layout/CardStream.tsx
|
|
@@ -18561,16 +18640,16 @@ function CardStream({ excludeId } = {}) {
|
|
|
18561
18640
|
}
|
|
18562
18641
|
const committed = filtered.slice(0, cutoff);
|
|
18563
18642
|
const live = filtered.slice(cutoff);
|
|
18564
|
-
return /* @__PURE__ */
|
|
18643
|
+
return /* @__PURE__ */ React47.createElement(React47.Fragment, null, /* @__PURE__ */ React47.createElement(Static, { items: committed }, (card) => /* @__PURE__ */ React47.createElement(CardRenderer, { key: card.id, card })), live.map((card) => /* @__PURE__ */ React47.createElement(CardRenderer, { key: card.id, card })));
|
|
18565
18644
|
}
|
|
18566
18645
|
|
|
18567
18646
|
// src/cli/ui/layout/LiveRows.tsx
|
|
18568
|
-
import { Box as
|
|
18569
|
-
import
|
|
18647
|
+
import { Box as Box42, Text as Text42, useStdout as useStdout10 } from "ink";
|
|
18648
|
+
import React48 from "react";
|
|
18570
18649
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
18571
18650
|
function ThinkingRow({ text }) {
|
|
18572
18651
|
const elapsed = useElapsedSeconds();
|
|
18573
|
-
return /* @__PURE__ */
|
|
18652
|
+
return /* @__PURE__ */ React48.createElement(Box42, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React48.createElement(Spinner, { kind: "circle", color: TONE.brand, bold: true }), /* @__PURE__ */ React48.createElement(Text42, null, " "), /* @__PURE__ */ React48.createElement(Text42, { color: TONE.brand }, text), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, ` \xB7 ${elapsed}s`));
|
|
18574
18653
|
}
|
|
18575
18654
|
function ModeStatusBar({
|
|
18576
18655
|
editMode,
|
|
@@ -18582,27 +18661,27 @@ function ModeStatusBar({
|
|
|
18582
18661
|
}) {
|
|
18583
18662
|
useSlowTick();
|
|
18584
18663
|
const running = jobs2?.runningCount() ?? 0;
|
|
18585
|
-
const jobsTag = running > 0 ? /* @__PURE__ */
|
|
18664
|
+
const jobsTag = running > 0 ? /* @__PURE__ */ React48.createElement(Text42, { color: TONE.warn, bold: true }, ` \xB7 \u23F5 ${running} job${running === 1 ? "" : "s"}`) : null;
|
|
18586
18665
|
if (planMode) {
|
|
18587
|
-
return /* @__PURE__ */
|
|
18666
|
+
return /* @__PURE__ */ React48.createElement(ModeBarFrame, null, /* @__PURE__ */ React48.createElement(ModePill, { label: "PLAN MODE", color: TONE.err, flash }), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, " writes gated \xB7 /plan off to leave"), jobsTag);
|
|
18588
18667
|
}
|
|
18589
18668
|
const label = editMode === "yolo" ? "YOLO" : editMode === "auto" ? "AUTO" : "REVIEW";
|
|
18590
18669
|
const pillColor = editMode === "yolo" ? TONE.err : editMode === "auto" ? TONE.accent : TONE.brand;
|
|
18591
18670
|
const mid = editMode === "yolo" ? "edits + shell auto \xB7 /undo to roll back" : editMode === "auto" ? "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";
|
|
18592
|
-
return /* @__PURE__ */
|
|
18671
|
+
return /* @__PURE__ */ React48.createElement(ModeBarFrame, null, /* @__PURE__ */ React48.createElement(ModePill, { label, color: pillColor, flash }), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, ` ${mid} \xB7 Shift+Tab to flip`), jobsTag);
|
|
18593
18672
|
}
|
|
18594
18673
|
function ModeBarFrame({ children }) {
|
|
18595
18674
|
const { stdout: stdout4 } = useStdout10();
|
|
18596
18675
|
const cols = stdout4?.columns ?? 80;
|
|
18597
18676
|
const ruleWidth = Math.max(20, cols - 2);
|
|
18598
|
-
return /* @__PURE__ */
|
|
18677
|
+
return /* @__PURE__ */ React48.createElement(Box42, { flexDirection: "column" }, /* @__PURE__ */ React48.createElement(Box42, { paddingX: 1 }, /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, "\u254C".repeat(ruleWidth))), /* @__PURE__ */ React48.createElement(Box42, { paddingX: 1 }, children));
|
|
18599
18678
|
}
|
|
18600
18679
|
function ModePill({
|
|
18601
18680
|
label,
|
|
18602
18681
|
color: color2,
|
|
18603
18682
|
flash
|
|
18604
18683
|
}) {
|
|
18605
|
-
return /* @__PURE__ */
|
|
18684
|
+
return /* @__PURE__ */ React48.createElement(Text42, { color: color2, bold: true, inverse: flash }, `[${label}]`);
|
|
18606
18685
|
}
|
|
18607
18686
|
function UndoBanner({
|
|
18608
18687
|
banner
|
|
@@ -18616,7 +18695,7 @@ function UndoBanner({
|
|
|
18616
18695
|
const urgent = remainingSec <= 1;
|
|
18617
18696
|
const pct2 = remainingMs / totalMs * 100;
|
|
18618
18697
|
const tone = urgent ? TONE.err : TONE.accent;
|
|
18619
|
-
return /* @__PURE__ */
|
|
18698
|
+
return /* @__PURE__ */ React48.createElement(Box42, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React48.createElement(Text42, { backgroundColor: TONE.accent, color: "black", bold: true }, ` \u2713 AUTO-APPLIED ${ok}/${total} `), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, " press "), /* @__PURE__ */ React48.createElement(Text42, { backgroundColor: TONE.brand, color: "black", bold: true }, " u "), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, " to undo "), /* @__PURE__ */ React48.createElement(CharBar, { pct: pct2, width: 20, color: tone, showLabel: false }), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, " "), /* @__PURE__ */ React48.createElement(Text42, { color: tone, bold: urgent }, `${remainingSec}s`));
|
|
18620
18699
|
}
|
|
18621
18700
|
function subagentPhaseLabel(phase, iter, elapsedMs) {
|
|
18622
18701
|
if (phase === "summarising") return "summarising findings\u2026";
|
|
@@ -18636,7 +18715,7 @@ function SubagentRow({
|
|
|
18636
18715
|
const seconds = (activity.elapsedMs / 1e3).toFixed(1);
|
|
18637
18716
|
const phase = subagentPhaseLabel(activity.phase, activity.iter, activity.elapsedMs);
|
|
18638
18717
|
const last = activity.lastInner;
|
|
18639
|
-
return /* @__PURE__ */
|
|
18718
|
+
return /* @__PURE__ */ React48.createElement(Box42, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React48.createElement(Box42, null, /* @__PURE__ */ React48.createElement(Text42, null, " "), /* @__PURE__ */ React48.createElement(Text42, { color: CARD.subagent.color }, "\u258E "), /* @__PURE__ */ React48.createElement(Text42, { bold: true, color: CARD.subagent.color }, `\u232C ${subagentTitle(activity.skillName, activity.task)}`), /* @__PURE__ */ React48.createElement(Box42, { flexGrow: 1 }), /* @__PURE__ */ React48.createElement(Text42, { color: CARD.subagent.color }, `iter ${activity.iter} \xB7 ${seconds}s`), /* @__PURE__ */ React48.createElement(Text42, null, " "), /* @__PURE__ */ React48.createElement(Text42, { color: CARD.subagent.color, bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length])), /* @__PURE__ */ React48.createElement(Box42, null, /* @__PURE__ */ React48.createElement(Text42, null, " "), /* @__PURE__ */ React48.createElement(Text42, { color: CARD.subagent.color }, "\u258E")), /* @__PURE__ */ React48.createElement(Box42, null, /* @__PURE__ */ React48.createElement(Text42, null, " "), /* @__PURE__ */ React48.createElement(Text42, { color: CARD.subagent.color }, "\u258E "), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, "Task "), /* @__PURE__ */ React48.createElement(Text42, { color: FG.sub }, activity.task)), /* @__PURE__ */ React48.createElement(Box42, null, /* @__PURE__ */ React48.createElement(Text42, null, " "), /* @__PURE__ */ React48.createElement(Text42, { color: CARD.subagent.color }, "\u258E "), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, "Model "), /* @__PURE__ */ React48.createElement(Text42, { color: FG.sub }, activity.model ?? "\u2014")), /* @__PURE__ */ React48.createElement(Box42, null, /* @__PURE__ */ React48.createElement(Text42, null, " "), /* @__PURE__ */ React48.createElement(Text42, { color: CARD.subagent.color }, "\u258E")), /* @__PURE__ */ React48.createElement(Box42, null, /* @__PURE__ */ React48.createElement(Text42, null, " "), /* @__PURE__ */ React48.createElement(Text42, { color: CARD.subagent.color }, "\u258E "), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, "Last "), last ? /* @__PURE__ */ React48.createElement(React48.Fragment, null, /* @__PURE__ */ React48.createElement(Text42, { color: last.color }, `${last.glyph} `), /* @__PURE__ */ React48.createElement(Text42, { color: FG.body }, last.label), last.meta ? /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, ` ${last.meta}`) : null) : /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, "queued\u2026")), /* @__PURE__ */ React48.createElement(Box42, null, /* @__PURE__ */ React48.createElement(Text42, null, " "), /* @__PURE__ */ React48.createElement(Text42, { color: CARD.subagent.color }, "\u258E")), /* @__PURE__ */ React48.createElement(Box42, null, /* @__PURE__ */ React48.createElement(Text42, null, " "), /* @__PURE__ */ React48.createElement(Text42, { color: CARD.subagent.color }, "\u258E "), /* @__PURE__ */ React48.createElement(Text42, { bold: true, color: TONE.brand }, "\u25B6 "), /* @__PURE__ */ React48.createElement(Text42, { color: TONE.brand }, phase)));
|
|
18640
18719
|
}
|
|
18641
18720
|
function OngoingToolRow({
|
|
18642
18721
|
tool: tool2,
|
|
@@ -18645,7 +18724,7 @@ function OngoingToolRow({
|
|
|
18645
18724
|
const tick = useTick();
|
|
18646
18725
|
const elapsed = useElapsedSeconds();
|
|
18647
18726
|
const summary = summarizeToolArgs(tool2.name, tool2.args);
|
|
18648
|
-
return /* @__PURE__ */
|
|
18727
|
+
return /* @__PURE__ */ React48.createElement(Box42, { marginY: 1, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React48.createElement(Box42, null, /* @__PURE__ */ React48.createElement(Text42, { color: CARD.tool.color, bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React48.createElement(Text42, null, " "), /* @__PURE__ */ React48.createElement(Text42, { color: CARD.tool.color, bold: true }, `\u25A3 ${tool2.name}`), /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, ` running \xB7 ${elapsed}s`)), progress ? /* @__PURE__ */ React48.createElement(Box42, { paddingLeft: 3 }, /* @__PURE__ */ React48.createElement(Text42, { color: TONE.brand }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ React48.createElement(Box42, { paddingLeft: 3 }, /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, summary)) : null);
|
|
18649
18728
|
}
|
|
18650
18729
|
function renderProgressLine(p) {
|
|
18651
18730
|
const msg = p.message ? ` ${p.message}` : "";
|
|
@@ -18701,16 +18780,16 @@ function summarizeToolArgs(name, args) {
|
|
|
18701
18780
|
}
|
|
18702
18781
|
|
|
18703
18782
|
// src/cli/ui/layout/StatusRow.tsx
|
|
18704
|
-
import { Box as
|
|
18705
|
-
import
|
|
18783
|
+
import { Box as Box43, Text as Text44, useStdout as useStdout11 } from "ink";
|
|
18784
|
+
import React50 from "react";
|
|
18706
18785
|
|
|
18707
18786
|
// src/cli/ui/primitives/Countdown.tsx
|
|
18708
|
-
import { Text as
|
|
18709
|
-
import
|
|
18787
|
+
import { Text as Text43 } from "ink";
|
|
18788
|
+
import React49 from "react";
|
|
18710
18789
|
function Countdown({ endsAt, color: color2 = TONE.brand }) {
|
|
18711
18790
|
useSlowTick();
|
|
18712
18791
|
const remainingSec = Math.max(0, Math.ceil((endsAt - Date.now()) / 1e3));
|
|
18713
|
-
return /* @__PURE__ */
|
|
18792
|
+
return /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: color2 }, String(remainingSec));
|
|
18714
18793
|
}
|
|
18715
18794
|
|
|
18716
18795
|
// src/cli/ui/layout/StatusRow.tsx
|
|
@@ -18730,7 +18809,7 @@ function StatusRow() {
|
|
|
18730
18809
|
const turnCny = status3.cost * USD_TO_CNY;
|
|
18731
18810
|
const sessionCny = status3.sessionCost * USD_TO_CNY;
|
|
18732
18811
|
const hasTurn = status3.cost > 0;
|
|
18733
|
-
return /* @__PURE__ */
|
|
18812
|
+
return /* @__PURE__ */ React50.createElement(Box43, { flexDirection: "column" }, /* @__PURE__ */ React50.createElement(Box43, null, /* @__PURE__ */ React50.createElement(Text44, null, " "), /* @__PURE__ */ React50.createElement(Text44, { color: FG.faint }, "\u2500".repeat(ruleWidth))), /* @__PURE__ */ React50.createElement(Box43, { flexDirection: "row" }, /* @__PURE__ */ React50.createElement(Text44, null, " "), status3.recording ? /* @__PURE__ */ React50.createElement(RecordingPill, { rec: status3.recording }) : status3.countdownSeconds !== void 0 ? /* @__PURE__ */ React50.createElement(CountdownRow, { mode: status3.mode, secondsLeft: status3.countdownSeconds }) : /* @__PURE__ */ React50.createElement(ModePill2, { mode: status3.mode, network: status3.network, detail: status3.networkDetail }), /* @__PURE__ */ React50.createElement(Sep, null), /* @__PURE__ */ React50.createElement(Text44, { color: FG.sub }, `${session.id} \xB7 ${session.branch}`), hasTurn && /* @__PURE__ */ React50.createElement(React50.Fragment, null, /* @__PURE__ */ React50.createElement(Sep, null), /* @__PURE__ */ React50.createElement(Text44, { bold: true, color: TONE.brand }, "\u25B8 "), /* @__PURE__ */ React50.createElement(Text44, { bold: true, color: FG.body }, `\xA5${turnCny.toFixed(4)} turn`)), /* @__PURE__ */ React50.createElement(Sep, null), /* @__PURE__ */ React50.createElement(Text44, { color: FG.sub }, `\xA5${sessionCny.toFixed(3)} session`), status3.balance !== void 0 && /* @__PURE__ */ React50.createElement(React50.Fragment, null, /* @__PURE__ */ React50.createElement(Sep, null), /* @__PURE__ */ React50.createElement(Text44, { color: FG.faint }, "wallet "), /* @__PURE__ */ React50.createElement(Text44, { bold: true, color: balanceColor(status3.balance) }, `\xA5${status3.balance.toFixed(2)}`)), /* @__PURE__ */ React50.createElement(Sep, null), /* @__PURE__ */ React50.createElement(Text44, { color: TONE.accent }, `cache ${Math.round(status3.cacheHit * 100)}%`)));
|
|
18734
18813
|
}
|
|
18735
18814
|
function ModePill2({
|
|
18736
18815
|
mode: mode2,
|
|
@@ -18739,18 +18818,18 @@ function ModePill2({
|
|
|
18739
18818
|
}) {
|
|
18740
18819
|
if (network === "online") {
|
|
18741
18820
|
const pill = modeGlyph(mode2);
|
|
18742
|
-
return /* @__PURE__ */
|
|
18821
|
+
return /* @__PURE__ */ React50.createElement(Box43, { flexDirection: "row" }, /* @__PURE__ */ React50.createElement(Text44, { color: pill.color }, pill.glyph), /* @__PURE__ */ React50.createElement(Text44, { color: FG.sub }, ` ${mode2}`));
|
|
18743
18822
|
}
|
|
18744
18823
|
const dot2 = networkDot(network);
|
|
18745
18824
|
if (network === "slow") {
|
|
18746
18825
|
const tail = detail ? ` \xB7 ${detail}` : "";
|
|
18747
|
-
return /* @__PURE__ */
|
|
18826
|
+
return /* @__PURE__ */ React50.createElement(Box43, { flexDirection: "row" }, /* @__PURE__ */ React50.createElement(Text44, { color: dot2.color }, dot2.glyph), /* @__PURE__ */ React50.createElement(Text44, { color: dot2.color }, ` ${mode2} \xB7 slow${tail}`));
|
|
18748
18827
|
}
|
|
18749
18828
|
if (network === "disconnected") {
|
|
18750
18829
|
const tail = detail ? ` \xB7 ${detail}` : "";
|
|
18751
|
-
return /* @__PURE__ */
|
|
18830
|
+
return /* @__PURE__ */ React50.createElement(Box43, { flexDirection: "row" }, /* @__PURE__ */ React50.createElement(Text44, { color: dot2.color }, dot2.glyph), /* @__PURE__ */ React50.createElement(Text44, { color: dot2.color }, ` disconnect${tail}`));
|
|
18752
18831
|
}
|
|
18753
|
-
return /* @__PURE__ */
|
|
18832
|
+
return /* @__PURE__ */ React50.createElement(Box43, { flexDirection: "row" }, /* @__PURE__ */ React50.createElement(Text44, { color: dot2.color }, dot2.glyph), /* @__PURE__ */ React50.createElement(Text44, { color: dot2.color }, " reconnecting\u2026"));
|
|
18754
18833
|
}
|
|
18755
18834
|
function CountdownRow({
|
|
18756
18835
|
mode: mode2,
|
|
@@ -18758,14 +18837,14 @@ function CountdownRow({
|
|
|
18758
18837
|
}) {
|
|
18759
18838
|
const pill = modeGlyph(mode2);
|
|
18760
18839
|
const endsAt = Date.now() + secondsLeft * 1e3;
|
|
18761
|
-
return /* @__PURE__ */
|
|
18840
|
+
return /* @__PURE__ */ React50.createElement(Box43, { flexDirection: "row" }, /* @__PURE__ */ React50.createElement(Text44, { color: pill.color }, pill.glyph), /* @__PURE__ */ React50.createElement(Text44, { color: FG.sub }, ` ${mode2} \xB7 `), /* @__PURE__ */ React50.createElement(Text44, { color: TONE.warn }, "approving in "), /* @__PURE__ */ React50.createElement(Countdown, { endsAt }), /* @__PURE__ */ React50.createElement(Text44, { color: TONE.warn }, "s \xB7 esc to interrupt"));
|
|
18762
18841
|
}
|
|
18763
18842
|
function RecordingPill({ rec }) {
|
|
18764
18843
|
const sizeMb = (rec.sizeBytes / (1024 * 1024)).toFixed(1);
|
|
18765
|
-
return /* @__PURE__ */
|
|
18844
|
+
return /* @__PURE__ */ React50.createElement(Box43, { flexDirection: "row" }, /* @__PURE__ */ React50.createElement(Text44, { bold: true, color: TONE.err }, "\u25CFREC"), /* @__PURE__ */ React50.createElement(Text44, { color: TONE.err }, ` ${sizeMb} MB \xB7 ${rec.events} evt`));
|
|
18766
18845
|
}
|
|
18767
18846
|
function Sep() {
|
|
18768
|
-
return /* @__PURE__ */
|
|
18847
|
+
return /* @__PURE__ */ React50.createElement(Text44, { color: FG.meta }, " \xB7 ");
|
|
18769
18848
|
}
|
|
18770
18849
|
function modeGlyph(mode2) {
|
|
18771
18850
|
switch (mode2) {
|
|
@@ -18793,8 +18872,8 @@ function networkDot(state) {
|
|
|
18793
18872
|
}
|
|
18794
18873
|
|
|
18795
18874
|
// src/cli/ui/layout/ToastRail.tsx
|
|
18796
|
-
import { Box as
|
|
18797
|
-
import
|
|
18875
|
+
import { Box as Box44, Text as Text45, useStdout as useStdout12 } from "ink";
|
|
18876
|
+
import React51, { useEffect as useEffect3 } from "react";
|
|
18798
18877
|
var TONE_COLOR = {
|
|
18799
18878
|
ok: TONE.ok,
|
|
18800
18879
|
info: TONE.brand,
|
|
@@ -18832,12 +18911,12 @@ function ToastRail() {
|
|
|
18832
18911
|
}, [toasts, dispatch2]);
|
|
18833
18912
|
const visible = toasts.filter((t2) => now - t2.bornAt < t2.ttlMs);
|
|
18834
18913
|
if (visible.length === 0) return null;
|
|
18835
|
-
return /* @__PURE__ */
|
|
18914
|
+
return /* @__PURE__ */ React51.createElement(Box44, { flexDirection: "column" }, visible.map((t2) => {
|
|
18836
18915
|
const color2 = TONE_COLOR[t2.tone];
|
|
18837
18916
|
const glyph = TONE_GLYPH[t2.tone];
|
|
18838
18917
|
const body = bodyColor(t2, now);
|
|
18839
18918
|
const remainingSec = Math.max(0, Math.ceil((t2.ttlMs - (now - t2.bornAt)) / 1e3));
|
|
18840
|
-
return /* @__PURE__ */
|
|
18919
|
+
return /* @__PURE__ */ React51.createElement(Box44, { key: t2.id, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React51.createElement(Text45, { color: color2 }, rule), /* @__PURE__ */ React51.createElement(Box44, { flexDirection: "row" }, /* @__PURE__ */ React51.createElement(Text45, { color: color2 }, glyph), /* @__PURE__ */ React51.createElement(Text45, { bold: true, color: body }, ` ${t2.title}`), t2.detail !== void 0 && /* @__PURE__ */ React51.createElement(Text45, { color: FG.sub }, ` \xB7 ${t2.detail}`), /* @__PURE__ */ React51.createElement(Box44, { flexGrow: 1 }), /* @__PURE__ */ React51.createElement(Text45, { color: FG.faint }, `${remainingSec}s`)));
|
|
18841
18920
|
}));
|
|
18842
18921
|
}
|
|
18843
18922
|
|
|
@@ -20519,15 +20598,23 @@ var handlers6 = {
|
|
|
20519
20598
|
};
|
|
20520
20599
|
|
|
20521
20600
|
// src/cli/ui/slash/handlers/mcp.ts
|
|
20522
|
-
var mcp = (
|
|
20601
|
+
var mcp = (args, loop2, ctx) => {
|
|
20523
20602
|
const servers = ctx.mcpServers ?? [];
|
|
20524
20603
|
const specs = ctx.mcpSpecs ?? [];
|
|
20525
20604
|
const toolSpecs = loop2.prefix.toolSpecs ?? [];
|
|
20605
|
+
const sub = args[0];
|
|
20606
|
+
if (sub === "disable" || sub === "enable") {
|
|
20607
|
+
return toggleDisabled(sub, args[1], { servers, specs });
|
|
20608
|
+
}
|
|
20609
|
+
const wantsTextDump = sub === "text";
|
|
20526
20610
|
if (servers.length === 0 && specs.length === 0 && toolSpecs.length === 0) {
|
|
20527
20611
|
return {
|
|
20528
20612
|
info: 'no MCP servers attached. Run `reasonix setup` to pick some, or launch with --mcp "<spec>". `reasonix mcp list` shows the catalog.'
|
|
20529
20613
|
};
|
|
20530
20614
|
}
|
|
20615
|
+
if (!wantsTextDump && servers.length > 0) {
|
|
20616
|
+
return { openMcpBrowser: true };
|
|
20617
|
+
}
|
|
20531
20618
|
if (servers.length > 0) {
|
|
20532
20619
|
const lines2 = [];
|
|
20533
20620
|
let anyResources = false;
|
|
@@ -20536,7 +20623,7 @@ var mcp = (_args, loop2, ctx) => {
|
|
|
20536
20623
|
const { report } = s;
|
|
20537
20624
|
const serverName = report.serverInfo.name || "(unknown)";
|
|
20538
20625
|
const serverVer = report.serverInfo.version ? ` v${report.serverInfo.version}` : "";
|
|
20539
|
-
const health =
|
|
20626
|
+
const health = healthBadge2(report.elapsedMs);
|
|
20540
20627
|
lines2.push(`${health} [${s.label}] ${serverName}${serverVer} \u2014 ${s.spec}`);
|
|
20541
20628
|
lines2.push(` tools ${s.toolCount}`);
|
|
20542
20629
|
appendSection(lines2, "resources", report.resources);
|
|
@@ -20574,11 +20661,49 @@ var mcp = (_args, loop2, ctx) => {
|
|
|
20574
20661
|
lines.push("To change this set, exit and run `reasonix setup`.");
|
|
20575
20662
|
return { info: lines.join("\n") };
|
|
20576
20663
|
};
|
|
20577
|
-
function
|
|
20664
|
+
function healthBadge2(elapsedMs) {
|
|
20578
20665
|
if (elapsedMs < 500) return `\u25CF healthy \xB7 ${elapsedMs}ms`;
|
|
20579
20666
|
if (elapsedMs < 3e3) return `\u25CC slow \xB7 ${elapsedMs}ms`;
|
|
20580
20667
|
return `\u2717 very slow \xB7 ${elapsedMs}ms`;
|
|
20581
20668
|
}
|
|
20669
|
+
function toggleDisabled(action, rawName, ctx) {
|
|
20670
|
+
const name = rawName?.trim();
|
|
20671
|
+
if (!name) {
|
|
20672
|
+
return {
|
|
20673
|
+
info: `usage: /mcp ${action} <name> \xB7 pick a name shown in /mcp (anonymous servers can't be named-toggled).`
|
|
20674
|
+
};
|
|
20675
|
+
}
|
|
20676
|
+
const known = /* @__PURE__ */ new Set([
|
|
20677
|
+
...ctx.servers.map((s) => s.label),
|
|
20678
|
+
...ctx.specs.map((spec) => parseLabelFromSpec(spec)).filter((n) => n !== null)
|
|
20679
|
+
]);
|
|
20680
|
+
if (!known.has(name)) {
|
|
20681
|
+
const list2 = [...known].sort().join(", ") || "(none)";
|
|
20682
|
+
return { info: `unknown MCP server "${name}". Known: ${list2}.` };
|
|
20683
|
+
}
|
|
20684
|
+
const cfg = readConfig();
|
|
20685
|
+
const current = new Set(cfg.mcpDisabled ?? []);
|
|
20686
|
+
if (action === "disable") {
|
|
20687
|
+
if (current.has(name)) {
|
|
20688
|
+
return { info: `\u25B8 ${name} is already disabled \u2014 restart to apply, or /mcp enable ${name}.` };
|
|
20689
|
+
}
|
|
20690
|
+
current.add(name);
|
|
20691
|
+
writeConfig({ ...cfg, mcpDisabled: [...current].sort() });
|
|
20692
|
+
return {
|
|
20693
|
+
info: `\u25B8 ${name} disabled \u2014 takes effect on next launch. /mcp enable ${name} to revert.`
|
|
20694
|
+
};
|
|
20695
|
+
}
|
|
20696
|
+
if (!current.has(name)) {
|
|
20697
|
+
return { info: `\u25B8 ${name} is not disabled.` };
|
|
20698
|
+
}
|
|
20699
|
+
current.delete(name);
|
|
20700
|
+
writeConfig({ ...cfg, mcpDisabled: current.size > 0 ? [...current].sort() : void 0 });
|
|
20701
|
+
return { info: `\u25B8 ${name} re-enabled \u2014 takes effect on next launch.` };
|
|
20702
|
+
}
|
|
20703
|
+
function parseLabelFromSpec(spec) {
|
|
20704
|
+
const match = spec.match(/^([a-zA-Z_][a-zA-Z0-9_-]*)=/);
|
|
20705
|
+
return match ? match[1] ?? null : null;
|
|
20706
|
+
}
|
|
20582
20707
|
var handlers7 = { mcp };
|
|
20583
20708
|
|
|
20584
20709
|
// src/cli/ui/slash/handlers/memory.ts
|
|
@@ -20919,17 +21044,17 @@ var handlers9 = {
|
|
|
20919
21044
|
};
|
|
20920
21045
|
|
|
20921
21046
|
// src/cli/ui/ctx-breakdown.tsx
|
|
20922
|
-
import { Box as
|
|
20923
|
-
import
|
|
21047
|
+
import { Box as Box45, Text as Text47 } from "ink";
|
|
21048
|
+
import React53 from "react";
|
|
20924
21049
|
|
|
20925
21050
|
// src/cli/ui/primitives.tsx
|
|
20926
|
-
import { Text as
|
|
20927
|
-
import
|
|
21051
|
+
import { Text as Text46, useStdout as useStdout13 } from "ink";
|
|
21052
|
+
import React52 from "react";
|
|
20928
21053
|
function ChromeRule() {
|
|
20929
21054
|
const { stdout: stdout4 } = useStdout13();
|
|
20930
21055
|
const cols = stdout4?.columns ?? 80;
|
|
20931
21056
|
const w = Math.max(20, cols - 2);
|
|
20932
|
-
return /* @__PURE__ */
|
|
21057
|
+
return /* @__PURE__ */ React52.createElement(Text46, { dimColor: true }, "\u2500".repeat(w));
|
|
20933
21058
|
}
|
|
20934
21059
|
function Bar({
|
|
20935
21060
|
ratio,
|
|
@@ -20938,7 +21063,7 @@ function Bar({
|
|
|
20938
21063
|
dim
|
|
20939
21064
|
}) {
|
|
20940
21065
|
const filled = Math.max(0, Math.min(cells, Math.round(ratio * cells)));
|
|
20941
|
-
return /* @__PURE__ */
|
|
21066
|
+
return /* @__PURE__ */ React52.createElement(Text46, null, /* @__PURE__ */ React52.createElement(Text46, { color: color2, dimColor: dim }, "\u25B0".repeat(filled)), /* @__PURE__ */ React52.createElement(Text46, { dimColor: true }, "\u25B1".repeat(cells - filled)));
|
|
20942
21067
|
}
|
|
20943
21068
|
|
|
20944
21069
|
// src/cli/ui/ctx-breakdown.tsx
|
|
@@ -21957,7 +22082,7 @@ function hydrateCardsFromMessages(messages) {
|
|
|
21957
22082
|
}
|
|
21958
22083
|
|
|
21959
22084
|
// src/cli/ui/useCompletionPickers.ts
|
|
21960
|
-
import { useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo5, useRef as useRef3, useState as
|
|
22085
|
+
import { useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo5, useRef as useRef3, useState as useState11 } from "react";
|
|
21961
22086
|
function useCompletionPickers({
|
|
21962
22087
|
input,
|
|
21963
22088
|
setInput,
|
|
@@ -21966,7 +22091,7 @@ function useCompletionPickers({
|
|
|
21966
22091
|
models: models2,
|
|
21967
22092
|
mcpServers
|
|
21968
22093
|
}) {
|
|
21969
|
-
const [slashSelected, setSlashSelected] =
|
|
22094
|
+
const [slashSelected, setSlashSelected] = useState11(0);
|
|
21970
22095
|
const slashMatches = useMemo5(() => {
|
|
21971
22096
|
if (!input.startsWith("/") || input.includes(" ")) return null;
|
|
21972
22097
|
return suggestSlashCommands(input.slice(1), !!codeMode);
|
|
@@ -21978,8 +22103,8 @@ function useCompletionPickers({
|
|
|
21978
22103
|
return prev;
|
|
21979
22104
|
});
|
|
21980
22105
|
}, [slashMatches]);
|
|
21981
|
-
const [atSelected, setAtSelected] =
|
|
21982
|
-
const [atFiles, setAtFiles] =
|
|
22106
|
+
const [atSelected, setAtSelected] = useState11(0);
|
|
22107
|
+
const [atFiles, setAtFiles] = useState11([]);
|
|
21983
22108
|
useEffect4(() => {
|
|
21984
22109
|
if (!codeMode) {
|
|
21985
22110
|
setAtFiles([]);
|
|
@@ -22030,7 +22155,7 @@ function useCompletionPickers({
|
|
|
22030
22155
|
},
|
|
22031
22156
|
[atPicker, input, setInput]
|
|
22032
22157
|
);
|
|
22033
|
-
const [slashArgSelected, setSlashArgSelected] =
|
|
22158
|
+
const [slashArgSelected, setSlashArgSelected] = useState11(0);
|
|
22034
22159
|
const slashArgContext = useMemo5(() => {
|
|
22035
22160
|
if (!input.startsWith("/")) return null;
|
|
22036
22161
|
if (slashMatches !== null) return null;
|
|
@@ -22110,12 +22235,12 @@ function useCompletionPickers({
|
|
|
22110
22235
|
}
|
|
22111
22236
|
|
|
22112
22237
|
// src/cli/ui/useEditHistory.ts
|
|
22113
|
-
import { useCallback as useCallback3, useRef as useRef4, useState as
|
|
22238
|
+
import { useCallback as useCallback3, useRef as useRef4, useState as useState12 } from "react";
|
|
22114
22239
|
function useEditHistory(codeMode) {
|
|
22115
22240
|
const editHistory = useRef4([]);
|
|
22116
22241
|
const nextHistoryId = useRef4(1);
|
|
22117
22242
|
const currentTurnEntry = useRef4(null);
|
|
22118
|
-
const [undoBanner, setUndoBanner] =
|
|
22243
|
+
const [undoBanner, setUndoBanner] = useState12(null);
|
|
22119
22244
|
const undoTimeoutRef = useRef4(null);
|
|
22120
22245
|
const recordEdit = useCallback3(
|
|
22121
22246
|
(source, blocks, results, snaps) => {
|
|
@@ -22320,11 +22445,11 @@ function useEditHistory(codeMode) {
|
|
|
22320
22445
|
}
|
|
22321
22446
|
|
|
22322
22447
|
// src/cli/ui/useSessionInfo.ts
|
|
22323
|
-
import { useCallback as useCallback4, useEffect as useEffect5, useState as
|
|
22448
|
+
import { useCallback as useCallback4, useEffect as useEffect5, useState as useState13 } from "react";
|
|
22324
22449
|
function useSessionInfo(loop2) {
|
|
22325
|
-
const [balance, setBalance] =
|
|
22326
|
-
const [models2, setModels] =
|
|
22327
|
-
const [latestVersion, setLatestVersion] =
|
|
22450
|
+
const [balance, setBalance] = useState13(null);
|
|
22451
|
+
const [models2, setModels] = useState13(null);
|
|
22452
|
+
const [latestVersion, setLatestVersion] = useState13(null);
|
|
22328
22453
|
useEffect5(() => {
|
|
22329
22454
|
let cancelled = false;
|
|
22330
22455
|
void (async () => {
|
|
@@ -22393,7 +22518,7 @@ function useSessionInfo(loop2) {
|
|
|
22393
22518
|
}
|
|
22394
22519
|
|
|
22395
22520
|
// src/cli/ui/useSubagent.ts
|
|
22396
|
-
import { useEffect as useEffect6, useRef as useRef5, useState as
|
|
22521
|
+
import { useEffect as useEffect6, useRef as useRef5, useState as useState14 } from "react";
|
|
22397
22522
|
function summariseInner(ev) {
|
|
22398
22523
|
if (ev.role === "tool_start") {
|
|
22399
22524
|
return {
|
|
@@ -22420,7 +22545,7 @@ function summariseInner(ev) {
|
|
|
22420
22545
|
return null;
|
|
22421
22546
|
}
|
|
22422
22547
|
function useSubagent({ session, log }) {
|
|
22423
|
-
const [activity, setActivity] =
|
|
22548
|
+
const [activity, setActivity] = useState14(null);
|
|
22424
22549
|
const sinkRef = useRef5({ current: null });
|
|
22425
22550
|
useEffect6(() => {
|
|
22426
22551
|
sinkRef.current.current = (ev) => {
|
|
@@ -22503,13 +22628,13 @@ var PLAIN_UI = process.env.REASONIX_UI === "plain";
|
|
|
22503
22628
|
function LoopStatusRow({
|
|
22504
22629
|
loop: loop2
|
|
22505
22630
|
}) {
|
|
22506
|
-
const [, setTick] =
|
|
22507
|
-
|
|
22631
|
+
const [, setTick] = React54.useState(0);
|
|
22632
|
+
React54.useEffect(() => {
|
|
22508
22633
|
const id = setInterval(() => setTick((t2) => t2 + 1), 1e3);
|
|
22509
22634
|
return () => clearInterval(id);
|
|
22510
22635
|
}, []);
|
|
22511
22636
|
const nextFireMs = Math.max(0, loop2.nextFireAt - Date.now());
|
|
22512
|
-
return /* @__PURE__ */
|
|
22637
|
+
return /* @__PURE__ */ React54.createElement(Box46, null, /* @__PURE__ */ React54.createElement(Text48, { color: "cyan" }, `\u25B8 ${formatLoopStatus(loop2.prompt, nextFireMs, loop2.iter)} \xB7 /loop stop or type to cancel`));
|
|
22513
22638
|
}
|
|
22514
22639
|
function App(props) {
|
|
22515
22640
|
const session = useAgentSession({
|
|
@@ -22517,11 +22642,11 @@ function App(props) {
|
|
|
22517
22642
|
model: props.model,
|
|
22518
22643
|
workspace: props.codeMode?.rootDir ?? process.cwd()
|
|
22519
22644
|
});
|
|
22520
|
-
const initialCards =
|
|
22645
|
+
const initialCards = React54.useMemo(
|
|
22521
22646
|
() => props.session ? hydrateCardsFromMessages(loadSessionMessages(props.session)) : [],
|
|
22522
22647
|
[props.session]
|
|
22523
22648
|
);
|
|
22524
|
-
return /* @__PURE__ */
|
|
22649
|
+
return /* @__PURE__ */ React54.createElement(AgentStoreProvider, { session, initialCards }, /* @__PURE__ */ React54.createElement(AppInner, { ...props }));
|
|
22525
22650
|
}
|
|
22526
22651
|
function AppInner({
|
|
22527
22652
|
model: model2,
|
|
@@ -22554,14 +22679,14 @@ function AppInner({
|
|
|
22554
22679
|
}
|
|
22555
22680
|
return null;
|
|
22556
22681
|
});
|
|
22557
|
-
const [input, setInput] =
|
|
22558
|
-
const [busy, setBusy] =
|
|
22682
|
+
const [input, setInput] = useState15("");
|
|
22683
|
+
const [busy, setBusy] = useState15(false);
|
|
22559
22684
|
const abortedThisTurn = useRef6(false);
|
|
22560
22685
|
useEffect7(() => {
|
|
22561
22686
|
busyRef.current = busy;
|
|
22562
22687
|
}, [busy]);
|
|
22563
|
-
const [ongoingTool, setOngoingTool] =
|
|
22564
|
-
const [toolProgress, setToolProgress] =
|
|
22688
|
+
const [ongoingTool, setOngoingTool] = useState15(null);
|
|
22689
|
+
const [toolProgress, setToolProgress] = useState15(null);
|
|
22565
22690
|
const { stdout: stdout4 } = useStdout14();
|
|
22566
22691
|
useEffect7(() => {
|
|
22567
22692
|
if (!stdout4 || !stdout4.isTTY) return;
|
|
@@ -22572,7 +22697,7 @@ function AppInner({
|
|
|
22572
22697
|
stdout4.write("\x1B[>4m");
|
|
22573
22698
|
};
|
|
22574
22699
|
}, [stdout4]);
|
|
22575
|
-
const [isResizing, setIsResizing] =
|
|
22700
|
+
const [isResizing, setIsResizing] = useState15(false);
|
|
22576
22701
|
useEffect7(() => {
|
|
22577
22702
|
if (!stdout4 || !stdout4.isTTY) return;
|
|
22578
22703
|
let timer = null;
|
|
@@ -22594,11 +22719,11 @@ function AppInner({
|
|
|
22594
22719
|
session,
|
|
22595
22720
|
log
|
|
22596
22721
|
});
|
|
22597
|
-
const [statusLine, setStatusLine] =
|
|
22598
|
-
const [currentRootDir, setCurrentRootDir] =
|
|
22722
|
+
const [statusLine, setStatusLine] = useState15(null);
|
|
22723
|
+
const [currentRootDir, setCurrentRootDir] = useState15(
|
|
22599
22724
|
() => codeMode?.rootDir ?? process.cwd()
|
|
22600
22725
|
);
|
|
22601
|
-
const [hookList, setHookList] =
|
|
22726
|
+
const [hookList, setHookList] = useState15(
|
|
22602
22727
|
() => loadHooks({ projectRoot: codeMode?.rootDir })
|
|
22603
22728
|
);
|
|
22604
22729
|
const {
|
|
@@ -22613,13 +22738,13 @@ function AppInner({
|
|
|
22613
22738
|
touchedPaths
|
|
22614
22739
|
} = useEditHistory(codeMode);
|
|
22615
22740
|
const pendingEdits = useRef6([]);
|
|
22616
|
-
const [pendingCount, setPendingCount] =
|
|
22741
|
+
const [pendingCount, setPendingCount] = useState15(0);
|
|
22617
22742
|
const syncPendingCount = useCallback5(() => {
|
|
22618
22743
|
setPendingCount(pendingEdits.current.length);
|
|
22619
22744
|
setPendingTick((t2) => t2 + 1);
|
|
22620
22745
|
}, []);
|
|
22621
|
-
const [editMode, setEditMode] =
|
|
22622
|
-
const [preset2, setPreset] =
|
|
22746
|
+
const [editMode, setEditMode] = useState15(() => codeMode ? loadEditMode() : "review");
|
|
22747
|
+
const [preset2, setPreset] = useState15(() => {
|
|
22623
22748
|
if (model2 === "deepseek-v4-pro") return "pro";
|
|
22624
22749
|
return "auto";
|
|
22625
22750
|
});
|
|
@@ -22631,12 +22756,12 @@ function AppInner({
|
|
|
22631
22756
|
const planModeRef = useRef6(false);
|
|
22632
22757
|
const currentRootDirRef = useRef6("");
|
|
22633
22758
|
const latestVersionRef = useRef6(null);
|
|
22634
|
-
const [pendingEditReview, setPendingEditReview] =
|
|
22635
|
-
const [walkthroughActive, setWalkthroughActive] =
|
|
22636
|
-
const [pendingTick, setPendingTick] =
|
|
22759
|
+
const [pendingEditReview, setPendingEditReview] = useState15(null);
|
|
22760
|
+
const [walkthroughActive, setWalkthroughActive] = useState15(false);
|
|
22761
|
+
const [pendingTick, setPendingTick] = useState15(0);
|
|
22637
22762
|
const editReviewResolveRef = useRef6(null);
|
|
22638
22763
|
const turnEditPolicyRef = useRef6("ask");
|
|
22639
|
-
const [modeFlash, setModeFlash] =
|
|
22764
|
+
const [modeFlash, setModeFlash] = useState15(false);
|
|
22640
22765
|
const modeFlashTimeoutRef = useRef6(null);
|
|
22641
22766
|
const prevEditModeRef = useRef6(editMode);
|
|
22642
22767
|
useEffect7(() => {
|
|
@@ -22649,26 +22774,27 @@ function AppInner({
|
|
|
22649
22774
|
modeFlashTimeoutRef.current = null;
|
|
22650
22775
|
}, 1200);
|
|
22651
22776
|
}, [editMode]);
|
|
22652
|
-
const [pendingShell, setPendingShell] =
|
|
22653
|
-
const [pendingPlan, setPendingPlan] =
|
|
22654
|
-
const [pendingReviseEditor, setPendingReviseEditor] =
|
|
22655
|
-
const [pendingSessionsPicker, setPendingSessionsPicker] =
|
|
22656
|
-
const [sessionsPickerList, setSessionsPickerList] =
|
|
22657
|
-
const [
|
|
22658
|
-
const [
|
|
22659
|
-
const [
|
|
22660
|
-
const [
|
|
22661
|
-
const [
|
|
22662
|
-
const [
|
|
22663
|
-
const [
|
|
22664
|
-
const [
|
|
22665
|
-
const [
|
|
22666
|
-
const [
|
|
22777
|
+
const [pendingShell, setPendingShell] = useState15(null);
|
|
22778
|
+
const [pendingPlan, setPendingPlan] = useState15(null);
|
|
22779
|
+
const [pendingReviseEditor, setPendingReviseEditor] = useState15(null);
|
|
22780
|
+
const [pendingSessionsPicker, setPendingSessionsPicker] = useState15(false);
|
|
22781
|
+
const [sessionsPickerList, setSessionsPickerList] = useState15([]);
|
|
22782
|
+
const [pendingMcpBrowser, setPendingMcpBrowser] = useState15(false);
|
|
22783
|
+
const [stagedInput, setStagedInput] = useState15(null);
|
|
22784
|
+
const [pendingCheckpoint, setPendingCheckpoint] = useState15(null);
|
|
22785
|
+
const [stagedCheckpointRevise, setStagedCheckpointRevise] = useState15(null);
|
|
22786
|
+
const [pendingRevision, setPendingRevision] = useState15(null);
|
|
22787
|
+
const [pendingChoice, setPendingChoice] = useState15(null);
|
|
22788
|
+
const [stagedChoiceCustom, setStagedChoiceCustom] = useState15(null);
|
|
22789
|
+
const [planMode, setPlanMode] = useState15(false);
|
|
22790
|
+
const [proArmed, setProArmed] = useState15(false);
|
|
22791
|
+
const [turnOnPro, setTurnOnPro] = useState15(false);
|
|
22792
|
+
const [queuedSubmit, setQueuedSubmit] = useState15(null);
|
|
22667
22793
|
const promptHistory = useRef6([]);
|
|
22668
22794
|
const historyCursor = useRef6(-1);
|
|
22669
22795
|
const assistantIterCounter = useRef6(0);
|
|
22670
22796
|
const atUrlCache = useRef6(/* @__PURE__ */ new Map());
|
|
22671
|
-
const [activeLoop, setActiveLoop] =
|
|
22797
|
+
const [activeLoop, setActiveLoop] = useState15(null);
|
|
22672
22798
|
const loopTimerRef = useRef6(null);
|
|
22673
22799
|
const handleSubmitRef = useRef6(null);
|
|
22674
22800
|
const busyRef = useRef6(false);
|
|
@@ -22698,7 +22824,7 @@ function AppInner({
|
|
|
22698
22824
|
if (planSummaryRef.current) extras.summary = planSummaryRef.current;
|
|
22699
22825
|
savePlanState(session, steps, completedStepIdsRef.current, extras);
|
|
22700
22826
|
}, [session]);
|
|
22701
|
-
const [summary, setSummary] =
|
|
22827
|
+
const [summary, setSummary] = useState15({
|
|
22702
22828
|
turns: 0,
|
|
22703
22829
|
totalCostUsd: 0,
|
|
22704
22830
|
totalInputCostUsd: 0,
|
|
@@ -23053,7 +23179,7 @@ function AppInner({
|
|
|
23053
23179
|
);
|
|
23054
23180
|
return;
|
|
23055
23181
|
}
|
|
23056
|
-
if (codeMode && key.shift && key.tab && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !stagedInput && !pendingEditReview && !walkthroughActive && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision) {
|
|
23182
|
+
if (codeMode && key.shift && key.tab && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingMcpBrowser && !stagedInput && !pendingEditReview && !walkthroughActive && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision) {
|
|
23057
23183
|
const cur = editModeRef.current;
|
|
23058
23184
|
const next = cur === "review" ? "auto" : cur === "auto" ? "yolo" : "review";
|
|
23059
23185
|
setEditMode(next);
|
|
@@ -23061,7 +23187,7 @@ function AppInner({
|
|
|
23061
23187
|
log.pushInfo(message);
|
|
23062
23188
|
return;
|
|
23063
23189
|
}
|
|
23064
|
-
if (codeMode && input.length === 0 && (chKey === "u" || chKey === "U") && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !stagedInput && !pendingEditReview && !walkthroughActive && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision && // Fire when EITHER the banner is up OR there's any non-undone
|
|
23190
|
+
if (codeMode && input.length === 0 && (chKey === "u" || chKey === "U") && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingMcpBrowser && !stagedInput && !pendingEditReview && !walkthroughActive && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision && // Fire when EITHER the banner is up OR there's any non-undone
|
|
23065
23191
|
// history entry — the keybind is useful long after the 5-second
|
|
23066
23192
|
// banner expires, which users rightly want.
|
|
23067
23193
|
(undoBanner || hasUndoable())) {
|
|
@@ -23515,7 +23641,7 @@ function AppInner({
|
|
|
23515
23641
|
const getDashboardUrl = useCallback5(() => {
|
|
23516
23642
|
return dashboardRef.current?.url ?? null;
|
|
23517
23643
|
}, []);
|
|
23518
|
-
const [dashboardUrl, setDashboardUrlState] =
|
|
23644
|
+
const [dashboardUrl, setDashboardUrlState] = useState15(null);
|
|
23519
23645
|
useEffect7(() => {
|
|
23520
23646
|
if (noDashboard) return;
|
|
23521
23647
|
if (dashboardRef.current) return;
|
|
@@ -23717,6 +23843,11 @@ function AppInner({
|
|
|
23717
23843
|
promptHistory.current.push(text);
|
|
23718
23844
|
return;
|
|
23719
23845
|
}
|
|
23846
|
+
if (result.openMcpBrowser) {
|
|
23847
|
+
setPendingMcpBrowser(true);
|
|
23848
|
+
promptHistory.current.push(text);
|
|
23849
|
+
return;
|
|
23850
|
+
}
|
|
23720
23851
|
const outcome = applySlashResult(result, {
|
|
23721
23852
|
log,
|
|
23722
23853
|
stdoutWrite: (chunk) => stdout4?.write(chunk),
|
|
@@ -24417,10 +24548,10 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24417
24548
|
async (choice) => handleReviseConfirmRef.current(choice),
|
|
24418
24549
|
[]
|
|
24419
24550
|
);
|
|
24420
|
-
return /* @__PURE__ */
|
|
24551
|
+
return /* @__PURE__ */ React54.createElement(React54.Fragment, null, /* @__PURE__ */ React54.createElement(
|
|
24421
24552
|
TickerProvider,
|
|
24422
24553
|
{
|
|
24423
|
-
disabled: PLAIN_UI || isResizing || !!pendingPlan || !!pendingReviseEditor || pendingSessionsPicker || !!pendingShell || !!pendingEditReview || walkthroughActive || !!pendingCheckpoint || !!stagedCheckpointRevise || !!pendingChoice || !!stagedChoiceCustom || !!pendingRevision || // Idle gate: when nothing is actively happening, suspend the
|
|
24554
|
+
disabled: PLAIN_UI || isResizing || !!pendingPlan || !!pendingReviseEditor || pendingSessionsPicker || pendingMcpBrowser || !!pendingShell || !!pendingEditReview || walkthroughActive || !!pendingCheckpoint || !!stagedCheckpointRevise || !!pendingChoice || !!stagedChoiceCustom || !!pendingRevision || // Idle gate: when nothing is actively happening, suspend the
|
|
24424
24555
|
// 8Hz/1Hz heartbeats. The cursor blink, gradient pulse, and
|
|
24425
24556
|
// spinner glyphs are pure cosmetics — running them at idle
|
|
24426
24557
|
// forces Ink to repaint the screen ~8x/sec, which erases any
|
|
@@ -24430,28 +24561,28 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24430
24561
|
// changes (incoming stream, key press, modal popup).
|
|
24431
24562
|
!busy && !isStreaming
|
|
24432
24563
|
},
|
|
24433
|
-
/* @__PURE__ */
|
|
24564
|
+
/* @__PURE__ */ React54.createElement(Box46, { flexDirection: "column" }, /* @__PURE__ */ React54.createElement(Box46, { flexDirection: "column" }, /* @__PURE__ */ React54.createElement(CardStream, { excludeId: activePlanCard?.id }), !hasConversation && !busy && !isStreaming ? /* @__PURE__ */ React54.createElement(WelcomeBanner, { inCodeMode: !!codeMode, dashboardUrl }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingMcpBrowser && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && ongoingTool ? /* @__PURE__ */ React54.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingMcpBrowser && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && subagentActivity ? /* @__PURE__ */ React54.createElement(SubagentRow, { activity: subagentActivity }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingMcpBrowser && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !ongoingTool && statusLine ? /* @__PURE__ */ React54.createElement(ThinkingRow, { text: statusLine }) : null, !PLAIN_UI && undoBanner && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingMcpBrowser && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision ? /* @__PURE__ */ React54.createElement(UndoBanner, { banner: undoBanner }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingMcpBrowser && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && busy && !isStreaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React54.createElement(ThinkingRow, { text: "processing\u2026" }) : null, /* @__PURE__ */ React54.createElement(ToastRail, null)), !PLAIN_UI && activePlanCard ? /* @__PURE__ */ React54.createElement(Box46, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React54.createElement(PlanCard, { card: activePlanCard })) : null, stagedInput ? /* @__PURE__ */ React54.createElement(
|
|
24434
24565
|
PlanRefineInput,
|
|
24435
24566
|
{
|
|
24436
24567
|
mode: stagedInput.mode,
|
|
24437
24568
|
onSubmit: handleStagedInputSubmit,
|
|
24438
24569
|
onCancel: handleStagedInputCancel
|
|
24439
24570
|
}
|
|
24440
|
-
) : stagedCheckpointRevise ? /* @__PURE__ */
|
|
24571
|
+
) : stagedCheckpointRevise ? /* @__PURE__ */ React54.createElement(
|
|
24441
24572
|
PlanRefineInput,
|
|
24442
24573
|
{
|
|
24443
24574
|
mode: "checkpoint-revise",
|
|
24444
24575
|
onSubmit: handleCheckpointReviseSubmit,
|
|
24445
24576
|
onCancel: handleCheckpointReviseCancel
|
|
24446
24577
|
}
|
|
24447
|
-
) : stagedChoiceCustom ? /* @__PURE__ */
|
|
24578
|
+
) : stagedChoiceCustom ? /* @__PURE__ */ React54.createElement(
|
|
24448
24579
|
PlanRefineInput,
|
|
24449
24580
|
{
|
|
24450
24581
|
mode: "choice-custom",
|
|
24451
24582
|
onSubmit: handleChoiceCustomSubmit,
|
|
24452
24583
|
onCancel: handleChoiceCustomCancel
|
|
24453
24584
|
}
|
|
24454
|
-
) : pendingChoice ? /* @__PURE__ */
|
|
24585
|
+
) : pendingChoice ? /* @__PURE__ */ React54.createElement(
|
|
24455
24586
|
ChoiceConfirm,
|
|
24456
24587
|
{
|
|
24457
24588
|
question: pendingChoice.question,
|
|
@@ -24459,7 +24590,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24459
24590
|
allowCustom: pendingChoice.allowCustom,
|
|
24460
24591
|
onChoose: stableHandleChoiceConfirm
|
|
24461
24592
|
}
|
|
24462
|
-
) : pendingRevision ? /* @__PURE__ */
|
|
24593
|
+
) : pendingRevision ? /* @__PURE__ */ React54.createElement(
|
|
24463
24594
|
PlanReviseConfirm,
|
|
24464
24595
|
{
|
|
24465
24596
|
reason: pendingRevision.reason,
|
|
@@ -24470,7 +24601,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24470
24601
|
summary: pendingRevision.summary,
|
|
24471
24602
|
onChoose: stableHandleReviseConfirm
|
|
24472
24603
|
}
|
|
24473
|
-
) : pendingCheckpoint ? /* @__PURE__ */
|
|
24604
|
+
) : pendingCheckpoint ? /* @__PURE__ */ React54.createElement(
|
|
24474
24605
|
PlanCheckpointConfirm,
|
|
24475
24606
|
{
|
|
24476
24607
|
stepId: pendingCheckpoint.stepId,
|
|
@@ -24481,7 +24612,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24481
24612
|
completedStepIds: completedStepIdsRef.current,
|
|
24482
24613
|
onChoose: stableHandleCheckpointConfirm
|
|
24483
24614
|
}
|
|
24484
|
-
) : pendingSessionsPicker ? /* @__PURE__ */
|
|
24615
|
+
) : pendingSessionsPicker ? /* @__PURE__ */ React54.createElement(
|
|
24485
24616
|
SessionPicker,
|
|
24486
24617
|
{
|
|
24487
24618
|
sessions: sessionsPickerList,
|
|
@@ -24524,7 +24655,14 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24524
24655
|
}
|
|
24525
24656
|
}
|
|
24526
24657
|
}
|
|
24527
|
-
) :
|
|
24658
|
+
) : pendingMcpBrowser ? /* @__PURE__ */ React54.createElement(
|
|
24659
|
+
McpBrowser,
|
|
24660
|
+
{
|
|
24661
|
+
servers: mcpServers ?? [],
|
|
24662
|
+
configPath: defaultConfigPath(),
|
|
24663
|
+
onClose: () => setPendingMcpBrowser(false)
|
|
24664
|
+
}
|
|
24665
|
+
) : pendingPlan ? /* @__PURE__ */ React54.createElement(
|
|
24528
24666
|
PlanConfirm,
|
|
24529
24667
|
{
|
|
24530
24668
|
plan: pendingPlan,
|
|
@@ -24533,7 +24671,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24533
24671
|
onChoose: stableHandlePlanConfirm,
|
|
24534
24672
|
projectRoot: currentRootDir
|
|
24535
24673
|
}
|
|
24536
|
-
) : pendingReviseEditor ? /* @__PURE__ */
|
|
24674
|
+
) : pendingReviseEditor ? /* @__PURE__ */ React54.createElement(
|
|
24537
24675
|
PlanReviseEditor,
|
|
24538
24676
|
{
|
|
24539
24677
|
steps: planStepsRef.current ?? [],
|
|
@@ -24552,7 +24690,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24552
24690
|
setPendingPlan(planText);
|
|
24553
24691
|
}
|
|
24554
24692
|
}
|
|
24555
|
-
) : pendingShell ? /* @__PURE__ */
|
|
24693
|
+
) : pendingShell ? /* @__PURE__ */ React54.createElement(
|
|
24556
24694
|
ShellConfirm,
|
|
24557
24695
|
{
|
|
24558
24696
|
command: pendingShell.command,
|
|
@@ -24560,7 +24698,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24560
24698
|
kind: pendingShell.kind,
|
|
24561
24699
|
onChoose: handleShellConfirm
|
|
24562
24700
|
}
|
|
24563
|
-
) : pendingEditReview ? /* @__PURE__ */
|
|
24701
|
+
) : pendingEditReview ? /* @__PURE__ */ React54.createElement(
|
|
24564
24702
|
EditConfirm,
|
|
24565
24703
|
{
|
|
24566
24704
|
block: pendingEditReview,
|
|
@@ -24572,14 +24710,14 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24572
24710
|
}
|
|
24573
24711
|
}
|
|
24574
24712
|
}
|
|
24575
|
-
) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */
|
|
24713
|
+
) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */ React54.createElement(
|
|
24576
24714
|
EditConfirm,
|
|
24577
24715
|
{
|
|
24578
24716
|
key: `walk-${pendingTick}`,
|
|
24579
24717
|
block: pendingEdits.current[0],
|
|
24580
24718
|
onChoose: handleWalkChoice
|
|
24581
24719
|
}
|
|
24582
|
-
) : /* @__PURE__ */
|
|
24720
|
+
) : /* @__PURE__ */ React54.createElement(React54.Fragment, null, codeMode ? /* @__PURE__ */ React54.createElement(
|
|
24583
24721
|
ModeStatusBar,
|
|
24584
24722
|
{
|
|
24585
24723
|
editMode,
|
|
@@ -24589,7 +24727,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24589
24727
|
undoArmed: !!undoBanner || hasUndoable(),
|
|
24590
24728
|
jobs: codeMode.jobs
|
|
24591
24729
|
}
|
|
24592
|
-
) : null, activeLoop ? /* @__PURE__ */
|
|
24730
|
+
) : null, activeLoop ? /* @__PURE__ */ React54.createElement(LoopStatusRow, { loop: activeLoop }) : null, /* @__PURE__ */ React54.createElement(StatusRow, null), /* @__PURE__ */ React54.createElement(
|
|
24593
24731
|
PromptInput,
|
|
24594
24732
|
{
|
|
24595
24733
|
value: input,
|
|
@@ -24599,14 +24737,14 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24599
24737
|
onHistoryPrev: recallPrev,
|
|
24600
24738
|
onHistoryNext: recallNext
|
|
24601
24739
|
}
|
|
24602
|
-
), slashMatches !== null ? /* @__PURE__ */
|
|
24740
|
+
), slashMatches !== null ? /* @__PURE__ */ React54.createElement(SlashSuggestions, { matches: slashMatches, selectedIndex: slashSelected }) : null, atMatches !== null ? /* @__PURE__ */ React54.createElement(
|
|
24603
24741
|
AtMentionSuggestions,
|
|
24604
24742
|
{
|
|
24605
24743
|
matches: atMatches,
|
|
24606
24744
|
selectedIndex: atSelected,
|
|
24607
24745
|
query: atPicker?.query ?? ""
|
|
24608
24746
|
}
|
|
24609
|
-
) : null, slashArgContext ? /* @__PURE__ */
|
|
24747
|
+
) : null, slashArgContext ? /* @__PURE__ */ React54.createElement(
|
|
24610
24748
|
SlashArgPicker,
|
|
24611
24749
|
{
|
|
24612
24750
|
matches: slashArgMatches,
|
|
@@ -24620,12 +24758,12 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24620
24758
|
}
|
|
24621
24759
|
|
|
24622
24760
|
// src/cli/ui/Setup.tsx
|
|
24623
|
-
import { Box as
|
|
24761
|
+
import { Box as Box47, Text as Text49, useApp } from "ink";
|
|
24624
24762
|
import TextInput from "ink-text-input";
|
|
24625
|
-
import
|
|
24763
|
+
import React55, { useState as useState16 } from "react";
|
|
24626
24764
|
function Setup({ onReady }) {
|
|
24627
|
-
const [value, setValue] =
|
|
24628
|
-
const [error, setError] =
|
|
24765
|
+
const [value, setValue] = useState16("");
|
|
24766
|
+
const [error, setError] = useState16(null);
|
|
24629
24767
|
const { exit: exit2 } = useApp();
|
|
24630
24768
|
const handleSubmit2 = (raw) => {
|
|
24631
24769
|
const trimmed = raw.trim();
|
|
@@ -24646,7 +24784,7 @@ function Setup({ onReady }) {
|
|
|
24646
24784
|
}
|
|
24647
24785
|
onReady(trimmed);
|
|
24648
24786
|
};
|
|
24649
|
-
return /* @__PURE__ */
|
|
24787
|
+
return /* @__PURE__ */ React55.createElement(Box47, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React55.createElement(Box47, null, /* @__PURE__ */ React55.createElement(Text49, { bold: true, color: GRADIENT[0] }, GLYPH.brand), /* @__PURE__ */ React55.createElement(Text49, null, " "), /* @__PURE__ */ React55.createElement(Text49, { bold: true }, "Welcome to "), /* @__PURE__ */ React55.createElement(Text49, { bold: true, color: GRADIENT[2] }, "REASONIX")), /* @__PURE__ */ React55.createElement(Box47, { marginTop: 1 }, /* @__PURE__ */ React55.createElement(Text49, { color: COLOR.info }, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React55.createElement(Box47, null, /* @__PURE__ */ React55.createElement(Text49, { dimColor: true }, " sign up at \xB7 "), /* @__PURE__ */ React55.createElement(Text49, { color: COLOR.primary }, "https://platform.deepseek.com/api_keys")), /* @__PURE__ */ React55.createElement(Box47, null, /* @__PURE__ */ React55.createElement(Text49, { dimColor: true }, " saved to "), /* @__PURE__ */ React55.createElement(Text49, { dimColor: true }, defaultConfigPath())), /* @__PURE__ */ React55.createElement(Box47, { marginTop: 1 }, /* @__PURE__ */ React55.createElement(Text49, { bold: true, color: COLOR.brand }, GLYPH.bar), /* @__PURE__ */ React55.createElement(Text49, { bold: true, color: COLOR.primary }, " \u203A "), /* @__PURE__ */ React55.createElement(
|
|
24650
24788
|
TextInput,
|
|
24651
24789
|
{
|
|
24652
24790
|
value,
|
|
@@ -24655,7 +24793,40 @@ function Setup({ onReady }) {
|
|
|
24655
24793
|
mask: "\u2022",
|
|
24656
24794
|
placeholder: "sk-..."
|
|
24657
24795
|
}
|
|
24658
|
-
)), error ? /* @__PURE__ */
|
|
24796
|
+
)), error ? /* @__PURE__ */ React55.createElement(Box47, { marginTop: 1 }, /* @__PURE__ */ React55.createElement(Text49, { color: COLOR.err, bold: true }, GLYPH.err), /* @__PURE__ */ React55.createElement(Text49, { color: COLOR.err }, ` ${error}`)) : value ? /* @__PURE__ */ React55.createElement(Box47, { marginTop: 1 }, /* @__PURE__ */ React55.createElement(Text49, { dimColor: true }, ` preview \xB7 ${redactKey(value)}`)) : null, /* @__PURE__ */ React55.createElement(Box47, { marginTop: 1 }, /* @__PURE__ */ React55.createElement(Text49, { dimColor: true }, " /exit to abort")));
|
|
24797
|
+
}
|
|
24798
|
+
|
|
24799
|
+
// src/cli/ui/mcp-lifecycle.ts
|
|
24800
|
+
var STATE = {
|
|
24801
|
+
handshake: { glyph: "\u21BB", label: "handshake\u2026" },
|
|
24802
|
+
connected: { glyph: "\u2713", label: "connected" },
|
|
24803
|
+
failed: { glyph: "\u2716", label: "failed" },
|
|
24804
|
+
disabled: { glyph: "\u25CB", label: "disabled" }
|
|
24805
|
+
};
|
|
24806
|
+
var NAME_COL = 22;
|
|
24807
|
+
var STATE_COL = 15;
|
|
24808
|
+
function formatMcpLifecycleEvent(ev) {
|
|
24809
|
+
const { glyph, label } = STATE[ev.state];
|
|
24810
|
+
const namePart = `MCP \xB7 ${ev.name}`;
|
|
24811
|
+
const namePad = " ".repeat(Math.max(1, NAME_COL - namePart.length));
|
|
24812
|
+
const stateField = `${glyph} ${label}`.padEnd(STATE_COL);
|
|
24813
|
+
return `\u2318 ${namePart}${namePad}${stateField}${describeDetail(ev)}`;
|
|
24814
|
+
}
|
|
24815
|
+
function describeDetail(ev) {
|
|
24816
|
+
if (ev.state === "handshake") return "initialise \u2192 tools/list \u2192 resources/list";
|
|
24817
|
+
if (ev.state === "failed") return ev.reason;
|
|
24818
|
+
if (ev.state === "disabled") return `via /mcp disable ${ev.name}`;
|
|
24819
|
+
const parts = [`${ev.tools} tools`];
|
|
24820
|
+
if (ev.resources && ev.resources > 0) parts.push(`${ev.resources} resources`);
|
|
24821
|
+
if (ev.prompts && ev.prompts > 0) parts.push(`${ev.prompts} prompts`);
|
|
24822
|
+
parts.push(`${ev.ms}ms`);
|
|
24823
|
+
return parts.join(" \xB7 ");
|
|
24824
|
+
}
|
|
24825
|
+
|
|
24826
|
+
// src/cli/ui/mcp-toast.ts
|
|
24827
|
+
function formatMcpSlowToast(t2) {
|
|
24828
|
+
const seconds = (t2.p95Ms / 1e3).toFixed(1);
|
|
24829
|
+
return `\u26A0 MCP \`${t2.name}\` slow \xB7 ${seconds}s p95 over the last ${t2.sampleSize} calls`;
|
|
24659
24830
|
}
|
|
24660
24831
|
|
|
24661
24832
|
// src/cli/commands/chat.tsx
|
|
@@ -24668,13 +24839,13 @@ function Root({
|
|
|
24668
24839
|
showPicker,
|
|
24669
24840
|
...appProps
|
|
24670
24841
|
}) {
|
|
24671
|
-
const [key, setKey] =
|
|
24672
|
-
const [pickerOpen, setPickerOpen] =
|
|
24673
|
-
const [activeSession, setActiveSession] =
|
|
24842
|
+
const [key, setKey] = useState17(initialKey);
|
|
24843
|
+
const [pickerOpen, setPickerOpen] = useState17(showPicker);
|
|
24844
|
+
const [activeSession, setActiveSession] = useState17(appProps.session);
|
|
24674
24845
|
const workspaceRoot = appProps.codeMode?.rootDir ?? process.cwd();
|
|
24675
|
-
const [sessions2, setSessions] =
|
|
24846
|
+
const [sessions2, setSessions] = useState17(() => listSessionsForWorkspace(workspaceRoot));
|
|
24676
24847
|
if (!key) {
|
|
24677
|
-
return /* @__PURE__ */
|
|
24848
|
+
return /* @__PURE__ */ React56.createElement(
|
|
24678
24849
|
Setup,
|
|
24679
24850
|
{
|
|
24680
24851
|
onReady: (k) => {
|
|
@@ -24686,7 +24857,7 @@ function Root({
|
|
|
24686
24857
|
}
|
|
24687
24858
|
process.env.DEEPSEEK_API_KEY = key;
|
|
24688
24859
|
if (pickerOpen) {
|
|
24689
|
-
return /* @__PURE__ */
|
|
24860
|
+
return /* @__PURE__ */ React56.createElement(KeystrokeProvider, null, /* @__PURE__ */ React56.createElement(
|
|
24690
24861
|
SessionPicker,
|
|
24691
24862
|
{
|
|
24692
24863
|
sessions: sessions2,
|
|
@@ -24719,7 +24890,7 @@ function Root({
|
|
|
24719
24890
|
}
|
|
24720
24891
|
));
|
|
24721
24892
|
}
|
|
24722
|
-
return /* @__PURE__ */
|
|
24893
|
+
return /* @__PURE__ */ React56.createElement(KeystrokeProvider, null, /* @__PURE__ */ React56.createElement(
|
|
24723
24894
|
App,
|
|
24724
24895
|
{
|
|
24725
24896
|
key: activeSession ?? "__new__",
|
|
@@ -24750,11 +24921,22 @@ async function chatCommand(opts) {
|
|
|
24750
24921
|
const mcpServers = [];
|
|
24751
24922
|
const progressSink = { current: null };
|
|
24752
24923
|
let tools = opts.seedTools;
|
|
24924
|
+
const disabledNames = new Set(readConfig().mcpDisabled ?? []);
|
|
24753
24925
|
if (requestedSpecs.length > 0) {
|
|
24754
24926
|
if (!tools) tools = new ToolRegistry();
|
|
24755
24927
|
for (const raw of requestedSpecs) {
|
|
24928
|
+
let label = "anon";
|
|
24756
24929
|
try {
|
|
24757
24930
|
const spec = parseMcpSpec(raw);
|
|
24931
|
+
label = spec.name ?? "anon";
|
|
24932
|
+
if (spec.name && disabledNames.has(spec.name)) {
|
|
24933
|
+
process.stderr.write(`${formatMcpLifecycleEvent({ state: "disabled", name: label })}
|
|
24934
|
+
`);
|
|
24935
|
+
continue;
|
|
24936
|
+
}
|
|
24937
|
+
process.stderr.write(`${formatMcpLifecycleEvent({ state: "handshake", name: label })}
|
|
24938
|
+
`);
|
|
24939
|
+
const t0 = Date.now();
|
|
24758
24940
|
const prefix = spec.name ? `${spec.name}_` : requestedSpecs.length === 1 && opts.mcpPrefix ? opts.mcpPrefix : "";
|
|
24759
24941
|
const transport = spec.transport === "sse" ? new SseTransport({ url: spec.url }) : spec.transport === "streamable-http" ? new StreamableHttpTransport({ url: spec.url }) : new StdioTransport({ command: spec.command, args: spec.args });
|
|
24760
24942
|
const mcp3 = new McpClient({ transport });
|
|
@@ -24762,7 +24944,12 @@ async function chatCommand(opts) {
|
|
|
24762
24944
|
const bridge = await bridgeMcpTools(mcp3, {
|
|
24763
24945
|
registry: tools,
|
|
24764
24946
|
namePrefix: prefix,
|
|
24765
|
-
|
|
24947
|
+
serverName: label,
|
|
24948
|
+
onProgress: (info) => progressSink.current?.(info),
|
|
24949
|
+
onSlow: (info) => process.stderr.write(
|
|
24950
|
+
`${formatMcpSlowToast({ name: info.serverName, p95Ms: info.p95Ms, sampleSize: info.sampleSize })}
|
|
24951
|
+
`
|
|
24952
|
+
)
|
|
24766
24953
|
});
|
|
24767
24954
|
let report;
|
|
24768
24955
|
try {
|
|
@@ -24778,10 +24965,18 @@ async function chatCommand(opts) {
|
|
|
24778
24965
|
elapsedMs: 0
|
|
24779
24966
|
};
|
|
24780
24967
|
}
|
|
24781
|
-
const
|
|
24782
|
-
const
|
|
24968
|
+
const ms = Date.now() - t0;
|
|
24969
|
+
const resourceCount = report.resources.supported ? report.resources.items.length : 0;
|
|
24970
|
+
const promptCount = report.prompts.supported ? report.prompts.items.length : 0;
|
|
24783
24971
|
process.stderr.write(
|
|
24784
|
-
|
|
24972
|
+
`${formatMcpLifecycleEvent({
|
|
24973
|
+
state: "connected",
|
|
24974
|
+
name: label,
|
|
24975
|
+
tools: bridge.registeredNames.length,
|
|
24976
|
+
resources: resourceCount,
|
|
24977
|
+
prompts: promptCount,
|
|
24978
|
+
ms
|
|
24979
|
+
})}
|
|
24785
24980
|
`
|
|
24786
24981
|
);
|
|
24787
24982
|
clients.push(mcp3);
|
|
@@ -24797,8 +24992,8 @@ async function chatCommand(opts) {
|
|
|
24797
24992
|
const reason = err.message;
|
|
24798
24993
|
failedSpecs.push({ spec: raw, reason });
|
|
24799
24994
|
process.stderr.write(
|
|
24800
|
-
|
|
24801
|
-
\u2192
|
|
24995
|
+
`${formatMcpLifecycleEvent({ state: "failed", name: label, reason })}
|
|
24996
|
+
\u2192 run \`reasonix setup\` to remove this entry, or fix the underlying issue (missing npm package, network, etc.).
|
|
24802
24997
|
`
|
|
24803
24998
|
);
|
|
24804
24999
|
}
|
|
@@ -24825,7 +25020,7 @@ async function chatCommand(opts) {
|
|
|
24825
25020
|
const launchWorkspace = opts.codeMode?.rootDir ?? process.cwd();
|
|
24826
25021
|
const showPicker = !opts.session && !opts.forceResume && listSessionsForWorkspace(launchWorkspace).length > 0;
|
|
24827
25022
|
const { waitUntilExit } = render(
|
|
24828
|
-
/* @__PURE__ */
|
|
25023
|
+
/* @__PURE__ */ React56.createElement(
|
|
24829
25024
|
Root,
|
|
24830
25025
|
{
|
|
24831
25026
|
initialKey,
|
|
@@ -25201,19 +25396,19 @@ async function commitCommand(opts = {}) {
|
|
|
25201
25396
|
import { writeFileSync as writeFileSync14 } from "fs";
|
|
25202
25397
|
import { basename as basename3 } from "path";
|
|
25203
25398
|
import { render as render2 } from "ink";
|
|
25204
|
-
import
|
|
25399
|
+
import React60 from "react";
|
|
25205
25400
|
|
|
25206
25401
|
// src/cli/ui/DiffApp.tsx
|
|
25207
|
-
import { Box as
|
|
25208
|
-
import
|
|
25402
|
+
import { Box as Box50, Static as Static2, Text as Text52, useApp as useApp2, useInput as useInput2 } from "ink";
|
|
25403
|
+
import React59, { useState as useState18 } from "react";
|
|
25209
25404
|
|
|
25210
25405
|
// src/cli/ui/RecordView.tsx
|
|
25211
|
-
import { Box as
|
|
25212
|
-
import
|
|
25406
|
+
import { Box as Box49, Text as Text51 } from "ink";
|
|
25407
|
+
import React58 from "react";
|
|
25213
25408
|
|
|
25214
25409
|
// src/cli/ui/PlanStateBlock.tsx
|
|
25215
|
-
import { Box as
|
|
25216
|
-
import
|
|
25410
|
+
import { Box as Box48, Text as Text50 } from "ink";
|
|
25411
|
+
import React57 from "react";
|
|
25217
25412
|
function PlanStateBlock({ planState }) {
|
|
25218
25413
|
const fields = [];
|
|
25219
25414
|
if (planState.subgoals.length)
|
|
@@ -25225,7 +25420,7 @@ function PlanStateBlock({ planState }) {
|
|
|
25225
25420
|
if (planState.rejectedPaths.length)
|
|
25226
25421
|
fields.push(["rejected", planState.rejectedPaths, COLOR.info, true]);
|
|
25227
25422
|
if (fields.length === 0) return null;
|
|
25228
|
-
return /* @__PURE__ */
|
|
25423
|
+
return /* @__PURE__ */ React57.createElement(Box48, { flexDirection: "column", marginBottom: 1 }, fields.map(([label, items, color2, dim]) => /* @__PURE__ */ React57.createElement(Box48, { key: label }, /* @__PURE__ */ React57.createElement(Text50, { color: color2, bold: true, dimColor: dim }, label), /* @__PURE__ */ React57.createElement(Text50, { dimColor: true }, ` (${items.length})`), /* @__PURE__ */ React57.createElement(Text50, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React57.createElement(Text50, { dimColor: dim, color: dim ? void 0 : COLOR.info }, items.join(" \xB7 ")))));
|
|
25229
25424
|
}
|
|
25230
25425
|
|
|
25231
25426
|
// src/cli/ui/RecordView.tsx
|
|
@@ -25234,21 +25429,21 @@ function RecordView({ rec, compact: compact2 = false }) {
|
|
|
25234
25429
|
const toolContentMax = compact2 ? 200 : 400;
|
|
25235
25430
|
if (rec.role === "user") {
|
|
25236
25431
|
const content = rec.content.includes("\n") ? rec.content.split("\n").join("\n ") : rec.content;
|
|
25237
|
-
return /* @__PURE__ */
|
|
25432
|
+
return /* @__PURE__ */ React58.createElement(Box49, { marginTop: 1 }, /* @__PURE__ */ React58.createElement(Text51, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React58.createElement(Text51, null, content));
|
|
25238
25433
|
}
|
|
25239
25434
|
if (rec.role === "assistant_final") {
|
|
25240
|
-
return /* @__PURE__ */
|
|
25435
|
+
return /* @__PURE__ */ React58.createElement(Box49, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React58.createElement(Box49, null, /* @__PURE__ */ React58.createElement(Text51, { bold: true, color: "green" }, "assistant"), rec.cost !== void 0 ? /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, " $", rec.cost.toFixed(6)) : null, rec.usage ? /* @__PURE__ */ React58.createElement(CacheBadge, { usage: rec.usage }) : null), rec.planState ? /* @__PURE__ */ React58.createElement(PlanStateBlock, { planState: rec.planState }) : null, rec.content ? /* @__PURE__ */ React58.createElement(Text51, null, rec.content) : /* @__PURE__ */ React58.createElement(Text51, { dimColor: true, italic: true }, "(tool-call response only)"));
|
|
25241
25436
|
}
|
|
25242
25437
|
if (rec.role === "tool") {
|
|
25243
|
-
return /* @__PURE__ */
|
|
25438
|
+
return /* @__PURE__ */ React58.createElement(Box49, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React58.createElement(Text51, { color: "yellow" }, "tool<", rec.tool ?? "?", ">"), rec.args ? /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, " args: ", truncate3(rec.args, toolArgsMax)) : null, /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, " \u2192 ", truncate3(rec.content, toolContentMax)));
|
|
25244
25439
|
}
|
|
25245
25440
|
if (rec.role === "error") {
|
|
25246
|
-
return /* @__PURE__ */
|
|
25441
|
+
return /* @__PURE__ */ React58.createElement(Box49, { marginTop: 1 }, /* @__PURE__ */ React58.createElement(Text51, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React58.createElement(Text51, { color: "red" }, rec.error ?? rec.content));
|
|
25247
25442
|
}
|
|
25248
25443
|
if (rec.role === "done" || rec.role === "assistant_delta") {
|
|
25249
25444
|
return null;
|
|
25250
25445
|
}
|
|
25251
|
-
return /* @__PURE__ */
|
|
25446
|
+
return /* @__PURE__ */ React58.createElement(Box49, null, /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, "[", rec.role, "] ", rec.content));
|
|
25252
25447
|
}
|
|
25253
25448
|
function CacheBadge({ usage }) {
|
|
25254
25449
|
const hit = usage.prompt_cache_hit_tokens ?? 0;
|
|
@@ -25257,7 +25452,7 @@ function CacheBadge({ usage }) {
|
|
|
25257
25452
|
if (total === 0) return null;
|
|
25258
25453
|
const pct2 = hit / total * 100;
|
|
25259
25454
|
const color2 = pct2 >= 70 ? "green" : pct2 >= 40 ? "yellow" : "red";
|
|
25260
|
-
return /* @__PURE__ */
|
|
25455
|
+
return /* @__PURE__ */ React58.createElement(Text51, null, /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, " \xB7 cache "), /* @__PURE__ */ React58.createElement(Text51, { color: color2 }, pct2.toFixed(1), "%"));
|
|
25261
25456
|
}
|
|
25262
25457
|
function truncate3(s, max) {
|
|
25263
25458
|
return s.length <= max ? s : `${s.slice(0, max)}\u2026 (+${s.length - max} chars)`;
|
|
@@ -25268,7 +25463,7 @@ function DiffApp({ report }) {
|
|
|
25268
25463
|
const { exit: exit2 } = useApp2();
|
|
25269
25464
|
const maxIdx = Math.max(0, report.pairs.length - 1);
|
|
25270
25465
|
const initialIdx = report.firstDivergenceTurn ? report.pairs.findIndex((p) => p.turn === report.firstDivergenceTurn) : 0;
|
|
25271
|
-
const [idx, setIdx] =
|
|
25466
|
+
const [idx, setIdx] = useState18(Math.max(0, initialIdx));
|
|
25272
25467
|
useInput2((input, key) => {
|
|
25273
25468
|
if (input === "q" || key.ctrl && input === "c") {
|
|
25274
25469
|
exit2();
|
|
@@ -25291,7 +25486,7 @@ function DiffApp({ report }) {
|
|
|
25291
25486
|
}
|
|
25292
25487
|
});
|
|
25293
25488
|
const pair = report.pairs[idx];
|
|
25294
|
-
return /* @__PURE__ */
|
|
25489
|
+
return /* @__PURE__ */ React59.createElement(Box50, { flexDirection: "column" }, /* @__PURE__ */ React59.createElement(DiffHeader, { report }), /* @__PURE__ */ React59.createElement(Box50, { marginTop: 1, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ React59.createElement(Text52, { color: "cyan", bold: true }, "turn ", pair?.turn ?? "?", " (", idx + 1, " / ", report.pairs.length, ")"), /* @__PURE__ */ React59.createElement(Text52, null, pair ? /* @__PURE__ */ React59.createElement(KindBadge, { kind: pair.kind }) : null)), /* @__PURE__ */ React59.createElement(Box50, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React59.createElement(Pane, { label: report.a.label, headerColor: "blue", records: paneRecords(pair, "a") }), /* @__PURE__ */ React59.createElement(Pane, { label: report.b.label, headerColor: "magenta", records: paneRecords(pair, "b") })), pair?.divergenceNote ? /* @__PURE__ */ React59.createElement(Box50, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React59.createElement(Text52, { color: "yellow" }, "\u2605 "), /* @__PURE__ */ React59.createElement(Text52, null, pair.divergenceNote)) : null, /* @__PURE__ */ React59.createElement(Box50, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React59.createElement(Text52, { dimColor: true }, /* @__PURE__ */ React59.createElement(Text52, { bold: true }, "j"), "/", /* @__PURE__ */ React59.createElement(Text52, { bold: true }, "\u2193"), " next \xB7 ", /* @__PURE__ */ React59.createElement(Text52, { bold: true }, "k"), "/", /* @__PURE__ */ React59.createElement(Text52, { bold: true }, "\u2191"), " ", "prev \xB7 ", /* @__PURE__ */ React59.createElement(Text52, { bold: true }, "n"), " next-diverge \xB7 ", /* @__PURE__ */ React59.createElement(Text52, { bold: true }, "N"), "/", /* @__PURE__ */ React59.createElement(Text52, { bold: true }, "p"), " ", "prev-diverge \xB7 ", /* @__PURE__ */ React59.createElement(Text52, { bold: true }, "g"), "/", /* @__PURE__ */ React59.createElement(Text52, { bold: true }, "G"), " first/last \xB7 ", /* @__PURE__ */ React59.createElement(Text52, { bold: true }, "q"), " ", "quit")));
|
|
25295
25490
|
}
|
|
25296
25491
|
function DiffHeader({ report }) {
|
|
25297
25492
|
const a = report.a;
|
|
@@ -25309,15 +25504,15 @@ function DiffHeader({ report }) {
|
|
|
25309
25504
|
} else if (a.stats.prefixHashes[0] && a.stats.prefixHashes[0] === b.stats.prefixHashes[0]) {
|
|
25310
25505
|
prefixLine = `shared prefix hash ${a.stats.prefixHashes[0].slice(0, 12)}\u2026 \u2014 cache delta attributable to log stability, not prompt change.`;
|
|
25311
25506
|
}
|
|
25312
|
-
return /* @__PURE__ */
|
|
25507
|
+
return /* @__PURE__ */ React59.createElement(Box50, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React59.createElement(Box50, { justifyContent: "space-between" }, /* @__PURE__ */ React59.createElement(Text52, null, /* @__PURE__ */ React59.createElement(Text52, { color: "cyan", bold: true }, "reasonix diff"), /* @__PURE__ */ React59.createElement(Text52, { dimColor: true }, " \xB7 A="), /* @__PURE__ */ React59.createElement(Text52, { color: "blue" }, a.label), /* @__PURE__ */ React59.createElement(Text52, { dimColor: true }, " vs B="), /* @__PURE__ */ React59.createElement(Text52, { color: "magenta" }, b.label)), /* @__PURE__ */ React59.createElement(Text52, { dimColor: true }, report.pairs.length, " turns aligned")), /* @__PURE__ */ React59.createElement(Box50, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React59.createElement(Text52, null, /* @__PURE__ */ React59.createElement(Text52, { dimColor: true }, "cache "), /* @__PURE__ */ React59.createElement(Text52, null, (a.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React59.createElement(Text52, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React59.createElement(Text52, null, (b.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React59.createElement(Text52, { color: cacheDelta >= 0 ? "green" : "red", bold: true }, " ", cacheDelta >= 0 ? "+" : "", (cacheDelta * 100).toFixed(1), "pp")), /* @__PURE__ */ React59.createElement(Text52, null, /* @__PURE__ */ React59.createElement(Text52, { dimColor: true }, "cost "), /* @__PURE__ */ React59.createElement(Text52, null, "$", a.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React59.createElement(Text52, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React59.createElement(Text52, null, "$", b.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React59.createElement(Text52, { color: costDelta2 <= 0 ? "green" : "red", bold: true }, " ", costDelta2 >= 0 ? "+" : "", costDelta2.toFixed(1), "%")), /* @__PURE__ */ React59.createElement(Text52, null, /* @__PURE__ */ React59.createElement(Text52, { dimColor: true }, "model calls "), /* @__PURE__ */ React59.createElement(Text52, null, a.stats.turns, " \u2192 ", b.stats.turns))), prefixLine ? /* @__PURE__ */ React59.createElement(Box50, { marginTop: 1 }, /* @__PURE__ */ React59.createElement(Text52, { dimColor: true, italic: true }, prefixLine)) : null);
|
|
25313
25508
|
}
|
|
25314
25509
|
function Pane({
|
|
25315
25510
|
label,
|
|
25316
25511
|
headerColor,
|
|
25317
25512
|
records
|
|
25318
25513
|
}) {
|
|
25319
|
-
return /* @__PURE__ */
|
|
25320
|
-
|
|
25514
|
+
return /* @__PURE__ */ React59.createElement(
|
|
25515
|
+
Box50,
|
|
25321
25516
|
{
|
|
25322
25517
|
flexDirection: "column",
|
|
25323
25518
|
flexGrow: 1,
|
|
@@ -25325,21 +25520,21 @@ function Pane({
|
|
|
25325
25520
|
borderStyle: "single",
|
|
25326
25521
|
borderColor: headerColor
|
|
25327
25522
|
},
|
|
25328
|
-
/* @__PURE__ */
|
|
25329
|
-
records.length === 0 ? /* @__PURE__ */
|
|
25523
|
+
/* @__PURE__ */ React59.createElement(Text52, { color: headerColor, bold: true }, label),
|
|
25524
|
+
records.length === 0 ? /* @__PURE__ */ React59.createElement(Box50, { marginTop: 1 }, /* @__PURE__ */ React59.createElement(Text52, { dimColor: true, italic: true }, "(no records on this side for this turn)")) : /* @__PURE__ */ React59.createElement(Static2, { items: records.map((rec, i) => ({ key: `${label}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React59.createElement(RecordView, { key, rec, compact: true }))
|
|
25330
25525
|
);
|
|
25331
25526
|
}
|
|
25332
25527
|
function KindBadge({ kind }) {
|
|
25333
25528
|
if (kind === "match") {
|
|
25334
|
-
return /* @__PURE__ */
|
|
25529
|
+
return /* @__PURE__ */ React59.createElement(Text52, { color: "green" }, "\u2713 match");
|
|
25335
25530
|
}
|
|
25336
25531
|
if (kind === "diverge") {
|
|
25337
|
-
return /* @__PURE__ */
|
|
25532
|
+
return /* @__PURE__ */ React59.createElement(Text52, { color: "yellow" }, "\u2605 diverge");
|
|
25338
25533
|
}
|
|
25339
25534
|
if (kind === "only_in_a") {
|
|
25340
|
-
return /* @__PURE__ */
|
|
25535
|
+
return /* @__PURE__ */ React59.createElement(Text52, { color: "blue" }, "\u2190 only in A");
|
|
25341
25536
|
}
|
|
25342
|
-
return /* @__PURE__ */
|
|
25537
|
+
return /* @__PURE__ */ React59.createElement(Text52, { color: "magenta" }, "\u2192 only in B");
|
|
25343
25538
|
}
|
|
25344
25539
|
function paneRecords(pair, side) {
|
|
25345
25540
|
if (!pair) return [];
|
|
@@ -25370,7 +25565,7 @@ markdown report written to ${opts.mdPath}`);
|
|
|
25370
25565
|
return;
|
|
25371
25566
|
}
|
|
25372
25567
|
if (wantTui) {
|
|
25373
|
-
const { waitUntilExit } = render2(
|
|
25568
|
+
const { waitUntilExit } = render2(React60.createElement(DiffApp, { report }), {
|
|
25374
25569
|
exitOnCtrlC: true,
|
|
25375
25570
|
patchConsole: false
|
|
25376
25571
|
});
|
|
@@ -26041,16 +26236,16 @@ function pad2(s, width) {
|
|
|
26041
26236
|
|
|
26042
26237
|
// src/cli/commands/replay.ts
|
|
26043
26238
|
import { render as render3 } from "ink";
|
|
26044
|
-
import
|
|
26239
|
+
import React63 from "react";
|
|
26045
26240
|
|
|
26046
26241
|
// src/cli/ui/ReplayApp.tsx
|
|
26047
|
-
import { Box as
|
|
26048
|
-
import
|
|
26242
|
+
import { Box as Box52, Static as Static3, Text as Text54, useApp as useApp3, useInput as useInput3 } from "ink";
|
|
26243
|
+
import React62, { useMemo as useMemo7, useState as useState19 } from "react";
|
|
26049
26244
|
|
|
26050
26245
|
// src/cli/ui/StatsPanel.tsx
|
|
26051
26246
|
import { basename as basename4 } from "path";
|
|
26052
|
-
import { Box as
|
|
26053
|
-
import
|
|
26247
|
+
import { Box as Box51, Text as Text53, useStdout as useStdout15 } from "ink";
|
|
26248
|
+
import React61 from "react";
|
|
26054
26249
|
import stringWidth2 from "string-width";
|
|
26055
26250
|
var COLD_START_TURNS = 3;
|
|
26056
26251
|
function StatsPanel({
|
|
@@ -26066,7 +26261,7 @@ function StatsPanel({
|
|
|
26066
26261
|
sessionName
|
|
26067
26262
|
}) {
|
|
26068
26263
|
const coldStart = summary.turns <= COLD_START_TURNS;
|
|
26069
|
-
return /* @__PURE__ */
|
|
26264
|
+
return /* @__PURE__ */ React61.createElement(Box51, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React61.createElement(
|
|
26070
26265
|
ChromeRow,
|
|
26071
26266
|
{
|
|
26072
26267
|
editMode,
|
|
@@ -26080,7 +26275,7 @@ function StatsPanel({
|
|
|
26080
26275
|
updateAvailable,
|
|
26081
26276
|
balance: balance ?? null
|
|
26082
26277
|
}
|
|
26083
|
-
), /* @__PURE__ */
|
|
26278
|
+
), /* @__PURE__ */ React61.createElement(ChromeRule, null), budgetUsd !== null && budgetUsd !== void 0 ? /* @__PURE__ */ React61.createElement(BudgetRow, { spent: summary.totalCostUsd, cap: budgetUsd }) : null);
|
|
26084
26279
|
}
|
|
26085
26280
|
function ChromeRow({
|
|
26086
26281
|
editMode,
|
|
@@ -26125,15 +26320,15 @@ function ChromeRow({
|
|
|
26125
26320
|
if (showSession) budget3 -= sessionW;
|
|
26126
26321
|
const showUpdate = updateW > 0 && budget3 >= updateW;
|
|
26127
26322
|
if (showUpdate) budget3 -= updateW;
|
|
26128
|
-
return /* @__PURE__ */
|
|
26129
|
-
|
|
26323
|
+
return /* @__PURE__ */ React61.createElement(Box51, null, /* @__PURE__ */ React61.createElement(Text53, { bold: true, color: GRADIENT[0] }, "\u25C8 "), /* @__PURE__ */ React61.createElement(Text53, { color: COLOR.brand, bold: true }, "reasonix"), projectName ? /* @__PURE__ */ React61.createElement(React61.Fragment, null, /* @__PURE__ */ React61.createElement(Text53, { color: COLOR.info, dimColor: true }, " \xB7 "), /* @__PURE__ */ React61.createElement(Text53, null, projectName), showSession && sessionName ? /* @__PURE__ */ React61.createElement(React61.Fragment, null, /* @__PURE__ */ React61.createElement(Text53, { color: COLOR.info, dimColor: true }, " \u203A "), /* @__PURE__ */ React61.createElement(Text53, { color: COLOR.info }, sessionName)) : null) : null, /* @__PURE__ */ React61.createElement(Box51, { flexGrow: 1 }), showUpdate ? /* @__PURE__ */ React61.createElement(React61.Fragment, null, /* @__PURE__ */ React61.createElement(Text53, { color: COLOR.warn, bold: true }, updateLabel), /* @__PURE__ */ React61.createElement(Text53, null, " ")) : null, modePill ? /* @__PURE__ */ React61.createElement(React61.Fragment, null, /* @__PURE__ */ React61.createElement(Text53, { color: modePill.color, bold: true }, `[${modePill.label}]`), /* @__PURE__ */ React61.createElement(Text53, null, " ")) : null, proPill ? /* @__PURE__ */ React61.createElement(React61.Fragment, null, /* @__PURE__ */ React61.createElement(Text53, { color: proPill.color, bold: true }, `[${proPill.label}]`), /* @__PURE__ */ React61.createElement(Text53, null, " ")) : null, /* @__PURE__ */ React61.createElement(
|
|
26324
|
+
Text53,
|
|
26130
26325
|
{
|
|
26131
26326
|
color: summary.turns === 0 || coldStart ? COLOR.info : sessionCostColor(summary.totalCostUsd),
|
|
26132
26327
|
bold: summary.turns > 0 && !coldStart,
|
|
26133
26328
|
dimColor: summary.turns === 0 || coldStart
|
|
26134
26329
|
},
|
|
26135
26330
|
costLabel
|
|
26136
|
-
), showBalance && balance ? /* @__PURE__ */
|
|
26331
|
+
), showBalance && balance ? /* @__PURE__ */ React61.createElement(React61.Fragment, null, /* @__PURE__ */ React61.createElement(Text53, null, " "), /* @__PURE__ */ React61.createElement(Text53, { color: balance.total < 1 ? COLOR.err : balance.total < 5 ? COLOR.warn : COLOR.ok }, balanceLabel)) : null, showCache ? /* @__PURE__ */ React61.createElement(React61.Fragment, null, /* @__PURE__ */ React61.createElement(Text53, null, " "), /* @__PURE__ */ React61.createElement(Text53, { dimColor: true }, "["), /* @__PURE__ */ React61.createElement(Text53, { dimColor: true }, "c "), /* @__PURE__ */ React61.createElement(
|
|
26137
26332
|
Bar,
|
|
26138
26333
|
{
|
|
26139
26334
|
ratio: summary.cacheHitRatio,
|
|
@@ -26141,7 +26336,7 @@ function ChromeRow({
|
|
|
26141
26336
|
cells: 6,
|
|
26142
26337
|
dim: coldStart
|
|
26143
26338
|
}
|
|
26144
|
-
), /* @__PURE__ */
|
|
26339
|
+
), /* @__PURE__ */ React61.createElement(Text53, null, " "), /* @__PURE__ */ React61.createElement(Text53, { color: coldStart ? void 0 : cacheColor, dimColor: coldStart }, coldStart && summary.turns === 0 ? "\u2014" : `${cachePct}%`), /* @__PURE__ */ React61.createElement(Text53, { dimColor: true }, "]")) : null);
|
|
26145
26340
|
}
|
|
26146
26341
|
function pickModePill(planMode, editMode) {
|
|
26147
26342
|
if (planMode) return { label: "PLAN", color: COLOR.err };
|
|
@@ -26153,7 +26348,7 @@ function pickModePill(planMode, editMode) {
|
|
|
26153
26348
|
function BudgetRow({ spent, cap }) {
|
|
26154
26349
|
const pct2 = Math.max(0, spent / cap * 100);
|
|
26155
26350
|
const color2 = pct2 >= 100 ? "#f87171" : pct2 >= 80 ? "#fbbf24" : "#94a3b8";
|
|
26156
|
-
return /* @__PURE__ */
|
|
26351
|
+
return /* @__PURE__ */ React61.createElement(Box51, null, /* @__PURE__ */ React61.createElement(Text53, { dimColor: true }, " budget "), /* @__PURE__ */ React61.createElement(Text53, { color: color2 }, `$${spent.toFixed(4)} / $${cap.toFixed(2)}`, /* @__PURE__ */ React61.createElement(Text53, { dimColor: true }, ` (${pct2.toFixed(0)}%)`)));
|
|
26157
26352
|
}
|
|
26158
26353
|
function sessionCostColor(cost2) {
|
|
26159
26354
|
if (cost2 <= 0) return void 0;
|
|
@@ -26166,7 +26361,7 @@ function sessionCostColor(cost2) {
|
|
|
26166
26361
|
function ReplayApp({ meta, pages }) {
|
|
26167
26362
|
const { exit: exit2 } = useApp3();
|
|
26168
26363
|
const maxIdx = Math.max(0, pages.length - 1);
|
|
26169
|
-
const [idx, setIdx] =
|
|
26364
|
+
const [idx, setIdx] = useState19(maxIdx);
|
|
26170
26365
|
useInput3((input, key) => {
|
|
26171
26366
|
if (input === "q" || key.ctrl && input === "c") {
|
|
26172
26367
|
exit2();
|
|
@@ -26202,7 +26397,7 @@ function ReplayApp({ meta, pages }) {
|
|
|
26202
26397
|
const prefixHash = cumStats.prefixHashes.length === 1 ? cumStats.prefixHashes[0].slice(0, 16) : cumStats.prefixHashes.length === 0 ? "(untracked)" : `(churned \xD7${cumStats.prefixHashes.length})`;
|
|
26203
26398
|
const currentPage = pages[idx];
|
|
26204
26399
|
const progressLabel = pages.length === 0 ? "empty transcript" : `turn ${idx + 1} / ${pages.length}`;
|
|
26205
|
-
return /* @__PURE__ */
|
|
26400
|
+
return /* @__PURE__ */ React62.createElement(Box52, { flexDirection: "column" }, /* @__PURE__ */ React62.createElement(StatsPanel, { summary }), /* @__PURE__ */ React62.createElement(Box52, { flexDirection: "column", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React62.createElement(Box52, { justifyContent: "space-between" }, /* @__PURE__ */ React62.createElement(Text54, { color: "cyan", bold: true }, progressLabel), meta ? /* @__PURE__ */ React62.createElement(Text54, { dimColor: true }, meta.source, meta.task ? ` \xB7 ${meta.task}` : "", meta.mode ? ` \xB7 ${meta.mode}` : "") : null), currentPage ? /* @__PURE__ */ React62.createElement(Static3, { items: currentPage.records.map((rec, i) => ({ key: `${idx}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React62.createElement(RecordView, { key, rec })) : /* @__PURE__ */ React62.createElement(Text54, { dimColor: true, italic: true }, "no records")), /* @__PURE__ */ React62.createElement(Box52, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React62.createElement(Text54, { dimColor: true }, /* @__PURE__ */ React62.createElement(Text54, { bold: true }, "j"), "/", /* @__PURE__ */ React62.createElement(Text54, { bold: true }, "\u2193"), "/", /* @__PURE__ */ React62.createElement(Text54, { bold: true }, "space"), " next \xB7 ", /* @__PURE__ */ React62.createElement(Text54, { bold: true }, "k"), "/", /* @__PURE__ */ React62.createElement(Text54, { bold: true }, "\u2191"), " prev \xB7 ", /* @__PURE__ */ React62.createElement(Text54, { bold: true }, "g"), " first \xB7 ", /* @__PURE__ */ React62.createElement(Text54, { bold: true }, "G"), " last \xB7", " ", /* @__PURE__ */ React62.createElement(Text54, { bold: true }, "q"), " quit")));
|
|
26206
26401
|
}
|
|
26207
26402
|
|
|
26208
26403
|
// src/cli/commands/replay.ts
|
|
@@ -26214,7 +26409,7 @@ async function replayCommand(opts) {
|
|
|
26214
26409
|
}
|
|
26215
26410
|
const { parsed } = replayFromFile(opts.path);
|
|
26216
26411
|
const pages = groupRecordsByTurn(parsed.records);
|
|
26217
|
-
const { waitUntilExit } = render3(
|
|
26412
|
+
const { waitUntilExit } = render3(React63.createElement(ReplayApp, { meta: parsed.meta, pages }), {
|
|
26218
26413
|
exitOnCtrlC: true,
|
|
26219
26414
|
patchConsole: false
|
|
26220
26415
|
});
|
|
@@ -26349,26 +26544,49 @@ async function runCommand2(opts) {
|
|
|
26349
26544
|
const clients = [];
|
|
26350
26545
|
let tools;
|
|
26351
26546
|
let successCount = 0;
|
|
26547
|
+
const disabledNames = new Set(readConfig().mcpDisabled ?? []);
|
|
26352
26548
|
if (requestedSpecs.length > 0) {
|
|
26353
26549
|
tools = new ToolRegistry();
|
|
26354
26550
|
for (const raw of requestedSpecs) {
|
|
26551
|
+
let label = "anon";
|
|
26355
26552
|
try {
|
|
26356
26553
|
const spec = parseMcpSpec(raw);
|
|
26554
|
+
label = spec.name ?? "anon";
|
|
26555
|
+
if (spec.name && disabledNames.has(spec.name)) {
|
|
26556
|
+
process.stderr.write(`${formatMcpLifecycleEvent({ state: "disabled", name: label })}
|
|
26557
|
+
`);
|
|
26558
|
+
continue;
|
|
26559
|
+
}
|
|
26560
|
+
process.stderr.write(`${formatMcpLifecycleEvent({ state: "handshake", name: label })}
|
|
26561
|
+
`);
|
|
26562
|
+
const t0 = Date.now();
|
|
26357
26563
|
const prefix2 = spec.name ? `${spec.name}_` : requestedSpecs.length === 1 && opts.mcpPrefix ? opts.mcpPrefix : "";
|
|
26358
26564
|
const transport = spec.transport === "sse" ? new SseTransport({ url: spec.url }) : spec.transport === "streamable-http" ? new StreamableHttpTransport({ url: spec.url }) : new StdioTransport({ command: spec.command, args: spec.args });
|
|
26359
26565
|
const mcp3 = new McpClient({ transport });
|
|
26360
26566
|
await mcp3.initialize();
|
|
26361
|
-
const bridge = await bridgeMcpTools(mcp3, {
|
|
26362
|
-
|
|
26567
|
+
const bridge = await bridgeMcpTools(mcp3, {
|
|
26568
|
+
registry: tools,
|
|
26569
|
+
namePrefix: prefix2,
|
|
26570
|
+
serverName: label,
|
|
26571
|
+
onSlow: (info) => process.stderr.write(
|
|
26572
|
+
`${formatMcpSlowToast({ name: info.serverName, p95Ms: info.p95Ms, sampleSize: info.sampleSize })}
|
|
26573
|
+
`
|
|
26574
|
+
)
|
|
26575
|
+
});
|
|
26363
26576
|
process.stderr.write(
|
|
26364
|
-
|
|
26577
|
+
`${formatMcpLifecycleEvent({
|
|
26578
|
+
state: "connected",
|
|
26579
|
+
name: label,
|
|
26580
|
+
tools: bridge.registeredNames.length,
|
|
26581
|
+
ms: Date.now() - t0
|
|
26582
|
+
})}
|
|
26365
26583
|
`
|
|
26366
26584
|
);
|
|
26367
26585
|
clients.push(mcp3);
|
|
26368
26586
|
successCount++;
|
|
26369
26587
|
} catch (err) {
|
|
26370
26588
|
process.stderr.write(
|
|
26371
|
-
|
|
26589
|
+
`${formatMcpLifecycleEvent({ state: "failed", name: label, reason: err.message })}
|
|
26372
26590
|
\u2192 run \`reasonix setup\` to remove broken entries from your saved config.
|
|
26373
26591
|
`
|
|
26374
26592
|
);
|
|
@@ -26520,28 +26738,28 @@ function truncate5(s, max) {
|
|
|
26520
26738
|
|
|
26521
26739
|
// src/cli/commands/setup.tsx
|
|
26522
26740
|
import { render as render4 } from "ink";
|
|
26523
|
-
import
|
|
26741
|
+
import React65 from "react";
|
|
26524
26742
|
|
|
26525
26743
|
// src/cli/ui/Wizard.tsx
|
|
26526
|
-
import { Box as
|
|
26744
|
+
import { Box as Box53, Text as Text55, useApp as useApp4, useInput as useInput4 } from "ink";
|
|
26527
26745
|
import TextInput2 from "ink-text-input";
|
|
26528
|
-
import
|
|
26746
|
+
import React64, { useState as useState20 } from "react";
|
|
26529
26747
|
var CATALOG_BY_NAME = new Map(MCP_CATALOG.map((e) => [e.name, e]));
|
|
26530
26748
|
function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
26531
26749
|
const { exit: exit2 } = useApp4();
|
|
26532
|
-
const [step, setStep] =
|
|
26533
|
-
const [data, setData] =
|
|
26750
|
+
const [step, setStep] = useState20(existingApiKey ? "preset" : "apiKey");
|
|
26751
|
+
const [data, setData] = useState20({
|
|
26534
26752
|
apiKey: existingApiKey ?? "",
|
|
26535
26753
|
preset: initial?.preset ?? "auto",
|
|
26536
26754
|
selectedCatalog: deriveInitialCatalog(initial?.mcp ?? []),
|
|
26537
26755
|
catalogArgs: {}
|
|
26538
26756
|
});
|
|
26539
|
-
const [error, setError] =
|
|
26757
|
+
const [error, setError] = useState20(null);
|
|
26540
26758
|
useInput4((_input, key) => {
|
|
26541
26759
|
if (key.escape && step !== "saved" && onCancel) onCancel();
|
|
26542
26760
|
});
|
|
26543
26761
|
if (step === "apiKey") {
|
|
26544
|
-
return /* @__PURE__ */
|
|
26762
|
+
return /* @__PURE__ */ React64.createElement(
|
|
26545
26763
|
ApiKeyStep,
|
|
26546
26764
|
{
|
|
26547
26765
|
onSubmit: (key) => {
|
|
@@ -26555,7 +26773,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
26555
26773
|
);
|
|
26556
26774
|
}
|
|
26557
26775
|
if (step === "preset") {
|
|
26558
|
-
return /* @__PURE__ */
|
|
26776
|
+
return /* @__PURE__ */ React64.createElement(StepFrame, { title: "Pick a preset", step: 1, total: 3 }, /* @__PURE__ */ React64.createElement(
|
|
26559
26777
|
SingleSelect,
|
|
26560
26778
|
{
|
|
26561
26779
|
items: presetItems(),
|
|
@@ -26565,10 +26783,10 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
26565
26783
|
setStep("mcp");
|
|
26566
26784
|
}
|
|
26567
26785
|
}
|
|
26568
|
-
), /* @__PURE__ */
|
|
26786
|
+
), /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, { dimColor: true }, "[\u2191\u2193] navigate \xB7 [Enter] confirm \xB7 [Esc] cancel")));
|
|
26569
26787
|
}
|
|
26570
26788
|
if (step === "mcp") {
|
|
26571
|
-
return /* @__PURE__ */
|
|
26789
|
+
return /* @__PURE__ */ React64.createElement(StepFrame, { title: "Which MCP servers should Reasonix wire up for you?", step: 2, total: 3 }, /* @__PURE__ */ React64.createElement(
|
|
26572
26790
|
MultiSelect,
|
|
26573
26791
|
{
|
|
26574
26792
|
items: mcpItems(),
|
|
@@ -26593,7 +26811,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
26593
26811
|
}
|
|
26594
26812
|
const currentName = pending[0];
|
|
26595
26813
|
const entry = CATALOG_BY_NAME.get(currentName);
|
|
26596
|
-
return /* @__PURE__ */
|
|
26814
|
+
return /* @__PURE__ */ React64.createElement(
|
|
26597
26815
|
McpArgsStep,
|
|
26598
26816
|
{
|
|
26599
26817
|
entry,
|
|
@@ -26611,7 +26829,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
26611
26829
|
}
|
|
26612
26830
|
if (step === "review") {
|
|
26613
26831
|
const specs = data.selectedCatalog.map((name) => buildSpec(name, data.catalogArgs));
|
|
26614
|
-
return /* @__PURE__ */
|
|
26832
|
+
return /* @__PURE__ */ React64.createElement(StepFrame, { title: "Ready to save", step: 3, total: 3 }, /* @__PURE__ */ React64.createElement(Box53, { flexDirection: "column" }, /* @__PURE__ */ React64.createElement(SummaryLine, { label: "API key", value: redactKey(data.apiKey) }), /* @__PURE__ */ React64.createElement(SummaryLine, { label: "Preset", value: data.preset }), /* @__PURE__ */ React64.createElement(
|
|
26615
26833
|
SummaryLine,
|
|
26616
26834
|
{
|
|
26617
26835
|
label: "MCP",
|
|
@@ -26619,8 +26837,8 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
26619
26837
|
}
|
|
26620
26838
|
), specs.map((spec, i) => (
|
|
26621
26839
|
// biome-ignore lint/suspicious/noArrayIndexKey: review-only render, order fixed
|
|
26622
|
-
/* @__PURE__ */
|
|
26623
|
-
)), /* @__PURE__ */
|
|
26840
|
+
/* @__PURE__ */ React64.createElement(Box53, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React64.createElement(Text55, { dimColor: true }, "\xB7 ", spec))
|
|
26841
|
+
)), /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, null, "Saves to ", defaultConfigPath())), error ? /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, { color: "red" }, error)) : null, /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, { dimColor: true }, "[Enter] save \xB7 [Esc] cancel"))), /* @__PURE__ */ React64.createElement(
|
|
26624
26842
|
ReviewConfirm,
|
|
26625
26843
|
{
|
|
26626
26844
|
onConfirm: () => {
|
|
@@ -26646,15 +26864,15 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
26646
26864
|
}
|
|
26647
26865
|
));
|
|
26648
26866
|
}
|
|
26649
|
-
return /* @__PURE__ */
|
|
26867
|
+
return /* @__PURE__ */ React64.createElement(Box53, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React64.createElement(Text55, { bold: true, color: "green" }, "\u25B8 Saved."), /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, null, "Run `reasonix` any time to start chatting \u2014 your settings are remembered.")), /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, { dimColor: true }, "[Enter] to exit")), /* @__PURE__ */ React64.createElement(ExitOnEnter, { onExit: exit2 }));
|
|
26650
26868
|
}
|
|
26651
26869
|
function ApiKeyStep({
|
|
26652
26870
|
onSubmit,
|
|
26653
26871
|
error,
|
|
26654
26872
|
onError
|
|
26655
26873
|
}) {
|
|
26656
|
-
const [value, setValue] =
|
|
26657
|
-
return /* @__PURE__ */
|
|
26874
|
+
const [value, setValue] = useState20("");
|
|
26875
|
+
return /* @__PURE__ */ React64.createElement(Box53, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React64.createElement(Text55, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React64.createElement(Text55, { dimColor: true }, "Get one at: https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React64.createElement(Text55, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React64.createElement(
|
|
26658
26876
|
TextInput2,
|
|
26659
26877
|
{
|
|
26660
26878
|
value,
|
|
@@ -26671,7 +26889,7 @@ function ApiKeyStep({
|
|
|
26671
26889
|
mask: "\u2022",
|
|
26672
26890
|
placeholder: "sk-..."
|
|
26673
26891
|
}
|
|
26674
|
-
)), error ? /* @__PURE__ */
|
|
26892
|
+
)), error ? /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, { color: "red" }, error)) : value ? /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, { dimColor: true }, "preview: ", redactKey(value))) : null);
|
|
26675
26893
|
}
|
|
26676
26894
|
function McpArgsStep({
|
|
26677
26895
|
entry,
|
|
@@ -26679,8 +26897,8 @@ function McpArgsStep({
|
|
|
26679
26897
|
onSubmit,
|
|
26680
26898
|
onError
|
|
26681
26899
|
}) {
|
|
26682
|
-
const [value, setValue] =
|
|
26683
|
-
return /* @__PURE__ */
|
|
26900
|
+
const [value, setValue] = useState20("");
|
|
26901
|
+
return /* @__PURE__ */ React64.createElement(StepFrame, { title: `Configure ${entry.name}`, step: 2, total: 3 }, /* @__PURE__ */ React64.createElement(Box53, { flexDirection: "column" }, /* @__PURE__ */ React64.createElement(Text55, null, entry.summary), entry.note ? /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, { dimColor: true }, entry.note)) : null, /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, null, "Required parameter: "), /* @__PURE__ */ React64.createElement(Text55, { bold: true }, entry.userArgs)), /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, { bold: true, color: "cyan" }, entry.userArgs, " \u203A "), /* @__PURE__ */ React64.createElement(
|
|
26684
26902
|
TextInput2,
|
|
26685
26903
|
{
|
|
26686
26904
|
value,
|
|
@@ -26696,7 +26914,7 @@ function McpArgsStep({
|
|
|
26696
26914
|
},
|
|
26697
26915
|
placeholder: placeholderFor(entry)
|
|
26698
26916
|
}
|
|
26699
|
-
)), error ? /* @__PURE__ */
|
|
26917
|
+
)), error ? /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, { color: "red" }, error)) : null));
|
|
26700
26918
|
}
|
|
26701
26919
|
function ReviewConfirm({ onConfirm }) {
|
|
26702
26920
|
useInput4((_i, key) => {
|
|
@@ -26716,10 +26934,10 @@ function StepFrame({
|
|
|
26716
26934
|
total,
|
|
26717
26935
|
children
|
|
26718
26936
|
}) {
|
|
26719
|
-
return /* @__PURE__ */
|
|
26937
|
+
return /* @__PURE__ */ React64.createElement(Box53, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React64.createElement(Box53, null, /* @__PURE__ */ React64.createElement(Text55, { dimColor: true }, "Step ", step, "/", total, " \xB7", " "), /* @__PURE__ */ React64.createElement(Text55, { bold: true, color: "cyan" }, title)), /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1, flexDirection: "column" }, children));
|
|
26720
26938
|
}
|
|
26721
26939
|
function SummaryLine({ label, value }) {
|
|
26722
|
-
return /* @__PURE__ */
|
|
26940
|
+
return /* @__PURE__ */ React64.createElement(Box53, null, /* @__PURE__ */ React64.createElement(Text55, null, label.padEnd(12)), /* @__PURE__ */ React64.createElement(Text55, { bold: true }, value));
|
|
26723
26941
|
}
|
|
26724
26942
|
function presetItems() {
|
|
26725
26943
|
return ["auto", "flash", "pro"].map((name) => ({
|
|
@@ -26775,7 +26993,7 @@ async function setupCommand(_opts = {}) {
|
|
|
26775
26993
|
const existingKey = loadApiKey();
|
|
26776
26994
|
const existing = readConfig();
|
|
26777
26995
|
const { waitUntilExit, unmount } = render4(
|
|
26778
|
-
/* @__PURE__ */
|
|
26996
|
+
/* @__PURE__ */ React65.createElement(
|
|
26779
26997
|
Wizard,
|
|
26780
26998
|
{
|
|
26781
26999
|
existingApiKey: existingKey,
|