reasonix 0.20.0 → 0.22.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 +1001 -530
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +46 -1
- package/dist/index.js +67 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1286,45 +1286,88 @@ 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;
|
|
1325
|
+
function registerSingleMcpTool(mcpTool, env) {
|
|
1326
|
+
if (!mcpTool.name) return "";
|
|
1327
|
+
const registeredName = `${env.prefix}${mcpTool.name}`;
|
|
1328
|
+
env.registry.register({
|
|
1329
|
+
name: registeredName,
|
|
1330
|
+
description: mcpTool.description ?? "",
|
|
1331
|
+
parameters: mcpTool.inputSchema,
|
|
1332
|
+
fn: async (args, ctx) => {
|
|
1333
|
+
const t0 = env.tracker ? Date.now() : 0;
|
|
1334
|
+
const live = env.host.client;
|
|
1335
|
+
const toolResult = await live.callTool(mcpTool.name, args, {
|
|
1336
|
+
onProgress: env.onProgress ? (info) => env.onProgress({ toolName: registeredName, ...info }) : void 0,
|
|
1337
|
+
signal: ctx?.signal
|
|
1338
|
+
});
|
|
1339
|
+
if (env.tracker) env.tracker.record(Date.now() - t0);
|
|
1340
|
+
return flattenMcpResult(toolResult, { maxChars: env.maxResultChars });
|
|
1341
|
+
}
|
|
1342
|
+
});
|
|
1343
|
+
return registeredName;
|
|
1344
|
+
}
|
|
1292
1345
|
async function bridgeMcpTools(client, opts = {}) {
|
|
1293
1346
|
const registry = opts.registry ?? new ToolRegistry({ autoFlatten: opts.autoFlatten });
|
|
1294
1347
|
const prefix = opts.namePrefix ?? "";
|
|
1295
1348
|
const maxResultChars = opts.maxResultChars ?? DEFAULT_MAX_RESULT_CHARS;
|
|
1296
1349
|
const result = { registry, registeredNames: [], skipped: [] };
|
|
1350
|
+
const serverName = opts.serverName ?? prefix.replace(/_$/, "") ?? "anon";
|
|
1351
|
+
const tracker = opts.onSlow ? new LatencyTracker(serverName, { thresholdMs: opts.slowThresholdMs, onSlow: opts.onSlow }) : null;
|
|
1352
|
+
const host = opts.host ?? { client };
|
|
1353
|
+
const env = {
|
|
1354
|
+
registry,
|
|
1355
|
+
host,
|
|
1356
|
+
prefix,
|
|
1357
|
+
maxResultChars,
|
|
1358
|
+
tracker,
|
|
1359
|
+
onProgress: opts.onProgress
|
|
1360
|
+
};
|
|
1297
1361
|
const listed = await client.listTools();
|
|
1298
1362
|
for (const mcpTool of listed.tools) {
|
|
1299
1363
|
if (!mcpTool.name) {
|
|
1300
1364
|
result.skipped.push({ name: "?", reason: "empty tool name" });
|
|
1301
1365
|
continue;
|
|
1302
1366
|
}
|
|
1303
|
-
const registeredName =
|
|
1304
|
-
|
|
1305
|
-
name: registeredName,
|
|
1306
|
-
description: mcpTool.description ?? "",
|
|
1307
|
-
parameters: mcpTool.inputSchema,
|
|
1308
|
-
fn: async (args, ctx) => {
|
|
1309
|
-
const toolResult = await client.callTool(mcpTool.name, args, {
|
|
1310
|
-
// Forward server-side progress frames to the bridge caller,
|
|
1311
|
-
// tagged with the registered name so multi-server UIs can
|
|
1312
|
-
// disambiguate. No-op when `onProgress` isn't configured —
|
|
1313
|
-
// the client then also omits the _meta.progressToken and
|
|
1314
|
-
// the server won't emit progress.
|
|
1315
|
-
onProgress: opts.onProgress ? (info) => opts.onProgress({ toolName: registeredName, ...info }) : void 0,
|
|
1316
|
-
// Thread the tool-dispatch AbortSignal all the way down to
|
|
1317
|
-
// the MCP request so Esc truly cancels in flight — the
|
|
1318
|
-
// client will emit notifications/cancelled AND reject the
|
|
1319
|
-
// pending promise immediately, no "wait for subprocess".
|
|
1320
|
-
signal: ctx?.signal
|
|
1321
|
-
});
|
|
1322
|
-
return flattenMcpResult(toolResult, { maxChars: maxResultChars });
|
|
1323
|
-
}
|
|
1324
|
-
});
|
|
1325
|
-
result.registeredNames.push(registeredName);
|
|
1367
|
+
const registeredName = registerSingleMcpTool(mcpTool, env);
|
|
1368
|
+
if (registeredName) result.registeredNames.push(registeredName);
|
|
1326
1369
|
}
|
|
1327
|
-
return result;
|
|
1370
|
+
return { ...result, env };
|
|
1328
1371
|
}
|
|
1329
1372
|
function flattenMcpResult(result, opts = {}) {
|
|
1330
1373
|
const parts = result.content.map(blockToString);
|
|
@@ -7591,11 +7634,11 @@ function formatLogSize(path5 = defaultUsageLogPath()) {
|
|
|
7591
7634
|
|
|
7592
7635
|
// src/cli/commands/chat.tsx
|
|
7593
7636
|
import { render } from "ink";
|
|
7594
|
-
import
|
|
7637
|
+
import React56, { useState as useState17 } from "react";
|
|
7595
7638
|
|
|
7596
7639
|
// src/cli/ui/App.tsx
|
|
7597
|
-
import { Box as
|
|
7598
|
-
import
|
|
7640
|
+
import { Box as Box46, Text as Text48, useStdout as useStdout14 } from "ink";
|
|
7641
|
+
import React54, { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMemo6, useRef as useRef6, useState as useState15 } from "react";
|
|
7599
7642
|
|
|
7600
7643
|
// src/adapters/event-sink-jsonl.ts
|
|
7601
7644
|
import { chmodSync as chmodSync3, createWriteStream as createWriteStream2, mkdirSync as mkdirSync6 } from "fs";
|
|
@@ -12938,17 +12981,307 @@ function EditConfirm({ block: block2, onChoose }) {
|
|
|
12938
12981
|
);
|
|
12939
12982
|
}
|
|
12940
12983
|
|
|
12984
|
+
// src/cli/ui/McpBrowser.tsx
|
|
12985
|
+
import { Box as Box7, Text as Text7 } from "ink";
|
|
12986
|
+
import React9, { useState as useState4 } from "react";
|
|
12987
|
+
|
|
12988
|
+
// src/cli/ui/mcp-disable.ts
|
|
12989
|
+
function toggleMcpDisabled(action, name) {
|
|
12990
|
+
const trimmed = name.trim();
|
|
12991
|
+
if (!trimmed) {
|
|
12992
|
+
return `usage: /mcp ${action} <name> \xB7 pick a name shown in /mcp (anonymous servers can't be named-toggled).`;
|
|
12993
|
+
}
|
|
12994
|
+
const cfg = readConfig();
|
|
12995
|
+
const current = new Set(cfg.mcpDisabled ?? []);
|
|
12996
|
+
if (action === "disable") {
|
|
12997
|
+
if (current.has(trimmed)) {
|
|
12998
|
+
return `\u25B8 ${trimmed} is already disabled \u2014 restart to apply, or /mcp enable ${trimmed}.`;
|
|
12999
|
+
}
|
|
13000
|
+
current.add(trimmed);
|
|
13001
|
+
writeConfig({ ...cfg, mcpDisabled: [...current].sort() });
|
|
13002
|
+
return `\u25B8 ${trimmed} disabled \u2014 takes effect on next launch. /mcp enable ${trimmed} to revert.`;
|
|
13003
|
+
}
|
|
13004
|
+
if (!current.has(trimmed)) {
|
|
13005
|
+
return `\u25B8 ${trimmed} is not disabled.`;
|
|
13006
|
+
}
|
|
13007
|
+
current.delete(trimmed);
|
|
13008
|
+
writeConfig({ ...cfg, mcpDisabled: current.size > 0 ? [...current].sort() : void 0 });
|
|
13009
|
+
return `\u25B8 ${trimmed} re-enabled \u2014 takes effect on next launch.`;
|
|
13010
|
+
}
|
|
13011
|
+
|
|
13012
|
+
// src/mcp/drift.ts
|
|
13013
|
+
function classifyToolListDrift(before, after) {
|
|
13014
|
+
const beforeNames = before.map(nameOf);
|
|
13015
|
+
const afterNames = after.map(nameOf);
|
|
13016
|
+
const beforeSet = new Set(beforeNames);
|
|
13017
|
+
const afterSet = new Set(afterNames);
|
|
13018
|
+
const added = afterNames.filter((n) => !beforeSet.has(n));
|
|
13019
|
+
const removed = beforeNames.filter((n) => !afterSet.has(n));
|
|
13020
|
+
const edited = [];
|
|
13021
|
+
const sharedLen = Math.min(before.length, after.length);
|
|
13022
|
+
for (let i = 0; i < sharedLen; i++) {
|
|
13023
|
+
if (beforeNames[i] === afterNames[i] && hash(before[i]) !== hash(after[i])) {
|
|
13024
|
+
edited.push(beforeNames[i]);
|
|
13025
|
+
}
|
|
13026
|
+
}
|
|
13027
|
+
if (before.length === after.length && edited.length === 0 && beforeNames.every((n, i) => n === afterNames[i])) {
|
|
13028
|
+
return { kind: "identity", added: [], removed: [], edited: [] };
|
|
13029
|
+
}
|
|
13030
|
+
if (removed.length > 0) {
|
|
13031
|
+
return { kind: "remove", added, removed, edited };
|
|
13032
|
+
}
|
|
13033
|
+
if (after.length > before.length && beforeNames.every((n, i) => n === afterNames[i] && hash(before[i]) === hash(after[i]))) {
|
|
13034
|
+
return { kind: "append", added, removed: [], edited: [] };
|
|
13035
|
+
}
|
|
13036
|
+
const sameNameSet = beforeSet.size === afterSet.size && [...beforeSet].every((n) => afterSet.has(n));
|
|
13037
|
+
if (sameNameSet) {
|
|
13038
|
+
const positionsMatch = beforeNames.every((n, i) => n === afterNames[i]);
|
|
13039
|
+
if (positionsMatch) {
|
|
13040
|
+
return { kind: "edit", added: [], removed: [], edited };
|
|
13041
|
+
}
|
|
13042
|
+
return { kind: "reorder", added: [], removed: [], edited };
|
|
13043
|
+
}
|
|
13044
|
+
return { kind: "reorder", added, removed: [], edited };
|
|
13045
|
+
}
|
|
13046
|
+
function nameOf(spec) {
|
|
13047
|
+
return spec.function?.name ?? "";
|
|
13048
|
+
}
|
|
13049
|
+
function hash(spec) {
|
|
13050
|
+
return JSON.stringify(spec);
|
|
13051
|
+
}
|
|
13052
|
+
|
|
13053
|
+
// src/mcp/reconnect.ts
|
|
13054
|
+
async function reconnectMcpServer(args) {
|
|
13055
|
+
const t0 = Date.now();
|
|
13056
|
+
const accept = args.accept ?? ["identity"];
|
|
13057
|
+
let parsed;
|
|
13058
|
+
try {
|
|
13059
|
+
parsed = parseMcpSpec(args.spec);
|
|
13060
|
+
} catch (err) {
|
|
13061
|
+
return {
|
|
13062
|
+
ok: false,
|
|
13063
|
+
reason: "spec_parse",
|
|
13064
|
+
message: err.message,
|
|
13065
|
+
ms: Date.now() - t0
|
|
13066
|
+
};
|
|
13067
|
+
}
|
|
13068
|
+
const transport = parsed.transport === "sse" ? new SseTransport({ url: parsed.url }) : parsed.transport === "streamable-http" ? new StreamableHttpTransport({ url: parsed.url }) : new StdioTransport({ command: parsed.command, args: parsed.args });
|
|
13069
|
+
const next = new McpClient({ transport });
|
|
13070
|
+
try {
|
|
13071
|
+
await next.initialize();
|
|
13072
|
+
const listed = await next.listTools();
|
|
13073
|
+
const drift = classifyToolListDrift(toolsToSpecs(args.beforeTools), toolsToSpecs(listed.tools));
|
|
13074
|
+
const acceptedKind = drift.kind === "identity" ? "identity" : drift.kind === "append" && accept.includes("append") ? "append" : null;
|
|
13075
|
+
if (acceptedKind === null) {
|
|
13076
|
+
await next.close().catch(() => {
|
|
13077
|
+
});
|
|
13078
|
+
const refused = drift.kind;
|
|
13079
|
+
return {
|
|
13080
|
+
ok: false,
|
|
13081
|
+
reason: driftReason(refused),
|
|
13082
|
+
message: driftMessage(drift),
|
|
13083
|
+
ms: Date.now() - t0
|
|
13084
|
+
};
|
|
13085
|
+
}
|
|
13086
|
+
const addedTools = acceptedKind === "append" ? listed.tools.filter((t2) => drift.added.includes(t2.name)) : [];
|
|
13087
|
+
const old = args.host.client;
|
|
13088
|
+
args.host.client = next;
|
|
13089
|
+
await old.close().catch(() => {
|
|
13090
|
+
});
|
|
13091
|
+
return {
|
|
13092
|
+
ok: true,
|
|
13093
|
+
kind: acceptedKind,
|
|
13094
|
+
afterTools: listed.tools,
|
|
13095
|
+
addedTools,
|
|
13096
|
+
ms: Date.now() - t0
|
|
13097
|
+
};
|
|
13098
|
+
} catch (err) {
|
|
13099
|
+
await next.close().catch(() => {
|
|
13100
|
+
});
|
|
13101
|
+
return {
|
|
13102
|
+
ok: false,
|
|
13103
|
+
reason: "handshake",
|
|
13104
|
+
message: err.message,
|
|
13105
|
+
ms: Date.now() - t0
|
|
13106
|
+
};
|
|
13107
|
+
}
|
|
13108
|
+
}
|
|
13109
|
+
function driftReason(kind) {
|
|
13110
|
+
if (kind === "append") return "drift_added";
|
|
13111
|
+
if (kind === "edit") return "drift_edited";
|
|
13112
|
+
if (kind === "reorder") return "drift_reordered";
|
|
13113
|
+
return "drift_removed";
|
|
13114
|
+
}
|
|
13115
|
+
function driftMessage(drift) {
|
|
13116
|
+
if (drift.kind === "append") {
|
|
13117
|
+
return `tool list grew (${drift.added.length} added: ${drift.added.join(", ")}). Restart Reasonix to bridge the new tool(s).`;
|
|
13118
|
+
}
|
|
13119
|
+
if (drift.kind === "edit") {
|
|
13120
|
+
return `tool description/schema changed for ${drift.edited.join(", ")}. Restart Reasonix to apply.`;
|
|
13121
|
+
}
|
|
13122
|
+
if (drift.kind === "remove") {
|
|
13123
|
+
return `tool(s) removed: ${drift.removed.join(", ")}. Restart Reasonix to drop them from the registry.`;
|
|
13124
|
+
}
|
|
13125
|
+
return "tool list reordered or restructured \u2014 cache prefix would be invalidated. Restart Reasonix.";
|
|
13126
|
+
}
|
|
13127
|
+
function toolsToSpecs(tools) {
|
|
13128
|
+
return tools.map((t2) => ({
|
|
13129
|
+
type: "function",
|
|
13130
|
+
function: {
|
|
13131
|
+
name: t2.name,
|
|
13132
|
+
description: t2.description ?? "",
|
|
13133
|
+
parameters: t2.inputSchema
|
|
13134
|
+
}
|
|
13135
|
+
}));
|
|
13136
|
+
}
|
|
13137
|
+
|
|
13138
|
+
// src/cli/ui/mcp-lifecycle.ts
|
|
13139
|
+
var STATE = {
|
|
13140
|
+
handshake: { glyph: "\u21BB", label: "handshake\u2026" },
|
|
13141
|
+
connected: { glyph: "\u2713", label: "connected" },
|
|
13142
|
+
failed: { glyph: "\u2716", label: "failed" },
|
|
13143
|
+
disabled: { glyph: "\u25CB", label: "disabled" },
|
|
13144
|
+
reconnect: { glyph: "\u21BB", label: "reconnect\u2026" }
|
|
13145
|
+
};
|
|
13146
|
+
var NAME_COL = 22;
|
|
13147
|
+
var STATE_COL = 15;
|
|
13148
|
+
function formatMcpLifecycleEvent(ev) {
|
|
13149
|
+
const { glyph, label } = STATE[ev.state];
|
|
13150
|
+
const namePart = `MCP \xB7 ${ev.name}`;
|
|
13151
|
+
const namePad = " ".repeat(Math.max(1, NAME_COL - namePart.length));
|
|
13152
|
+
const stateField = `${glyph} ${label}`.padEnd(STATE_COL);
|
|
13153
|
+
return `\u2318 ${namePart}${namePad}${stateField}${describeDetail(ev)}`;
|
|
13154
|
+
}
|
|
13155
|
+
function describeDetail(ev) {
|
|
13156
|
+
if (ev.state === "handshake") return "initialise \u2192 tools/list \u2192 resources/list";
|
|
13157
|
+
if (ev.state === "failed") return ev.reason;
|
|
13158
|
+
if (ev.state === "disabled") return `via /mcp disable ${ev.name}`;
|
|
13159
|
+
if (ev.state === "reconnect") return "tearing down \xB7 re-handshake \xB7 listing tools";
|
|
13160
|
+
const parts = [`${ev.tools} tools`];
|
|
13161
|
+
if (ev.resources && ev.resources > 0) parts.push(`${ev.resources} resources`);
|
|
13162
|
+
if (ev.prompts && ev.prompts > 0) parts.push(`${ev.prompts} prompts`);
|
|
13163
|
+
parts.push(`${ev.ms}ms`);
|
|
13164
|
+
return parts.join(" \xB7 ");
|
|
13165
|
+
}
|
|
13166
|
+
|
|
13167
|
+
// src/cli/ui/mcp-reconnect-kickoff.ts
|
|
13168
|
+
function kickOffMcpReconnect(target, postInfo, applyAppend) {
|
|
13169
|
+
const beforeTools = target.report.tools.supported ? target.report.tools.items : [];
|
|
13170
|
+
const accept = applyAppend ? ["identity", "append"] : ["identity"];
|
|
13171
|
+
void (async () => {
|
|
13172
|
+
try {
|
|
13173
|
+
const result = await reconnectMcpServer({
|
|
13174
|
+
host: target.host,
|
|
13175
|
+
spec: target.spec,
|
|
13176
|
+
beforeTools,
|
|
13177
|
+
accept
|
|
13178
|
+
});
|
|
13179
|
+
if (result.ok) {
|
|
13180
|
+
if (result.kind === "append" && applyAppend) {
|
|
13181
|
+
applyAppend(target, result.addedTools);
|
|
13182
|
+
}
|
|
13183
|
+
postInfo(
|
|
13184
|
+
formatMcpLifecycleEvent({
|
|
13185
|
+
state: "connected",
|
|
13186
|
+
name: target.label,
|
|
13187
|
+
tools: result.afterTools.length,
|
|
13188
|
+
ms: result.ms
|
|
13189
|
+
})
|
|
13190
|
+
);
|
|
13191
|
+
if (result.kind === "append") {
|
|
13192
|
+
const names = result.addedTools.map((t2) => t2.name).join(", ");
|
|
13193
|
+
postInfo(`\u25B8 ${target.label}: added ${result.addedTools.length} tool(s) \u2014 ${names}`);
|
|
13194
|
+
}
|
|
13195
|
+
} else {
|
|
13196
|
+
postInfo(
|
|
13197
|
+
formatMcpLifecycleEvent({
|
|
13198
|
+
state: "failed",
|
|
13199
|
+
name: target.label,
|
|
13200
|
+
reason: `${result.reason} \xB7 ${result.message}`
|
|
13201
|
+
})
|
|
13202
|
+
);
|
|
13203
|
+
}
|
|
13204
|
+
} catch (err) {
|
|
13205
|
+
postInfo(
|
|
13206
|
+
formatMcpLifecycleEvent({
|
|
13207
|
+
state: "failed",
|
|
13208
|
+
name: target.label,
|
|
13209
|
+
reason: err.message
|
|
13210
|
+
})
|
|
13211
|
+
);
|
|
13212
|
+
}
|
|
13213
|
+
})();
|
|
13214
|
+
return formatMcpLifecycleEvent({ state: "reconnect", name: target.label });
|
|
13215
|
+
}
|
|
13216
|
+
|
|
13217
|
+
// src/cli/ui/McpBrowser.tsx
|
|
13218
|
+
function McpBrowser({
|
|
13219
|
+
servers,
|
|
13220
|
+
configPath,
|
|
13221
|
+
onClose,
|
|
13222
|
+
postInfo,
|
|
13223
|
+
applyAppend
|
|
13224
|
+
}) {
|
|
13225
|
+
const [index, setIndex] = useState4(0);
|
|
13226
|
+
const max = Math.max(0, servers.length - 1);
|
|
13227
|
+
useKeystroke((ev) => {
|
|
13228
|
+
if (ev.paste) return;
|
|
13229
|
+
if (ev.upArrow) setIndex((i) => Math.max(0, i - 1));
|
|
13230
|
+
else if (ev.downArrow) setIndex((i) => Math.min(max, i + 1));
|
|
13231
|
+
else if (ev.escape) onClose();
|
|
13232
|
+
else if (ev.input === "r") {
|
|
13233
|
+
const target = servers[index];
|
|
13234
|
+
if (!target) return;
|
|
13235
|
+
postInfo(kickOffMcpReconnect(target, postInfo, applyAppend));
|
|
13236
|
+
onClose();
|
|
13237
|
+
} else if (ev.input === "d") {
|
|
13238
|
+
const target = servers[index];
|
|
13239
|
+
if (!target) return;
|
|
13240
|
+
postInfo(toggleMcpDisabled("disable", target.label));
|
|
13241
|
+
onClose();
|
|
13242
|
+
}
|
|
13243
|
+
});
|
|
13244
|
+
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(
|
|
13245
|
+
Text7,
|
|
13246
|
+
{
|
|
13247
|
+
dimColor: true
|
|
13248
|
+
},
|
|
13249
|
+
` \xB7 ${configPath} \xB7 ${servers.length} server${servers.length === 1 ? "" : "s"}`
|
|
13250
|
+
)), /* @__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 \xB7 [d] disable \xB7 esc quit")));
|
|
13251
|
+
}
|
|
13252
|
+
function ServerRow({ server, active }) {
|
|
13253
|
+
const { label, toolCount, report } = server;
|
|
13254
|
+
const resourceCount = report.resources.supported ? report.resources.items.length : 0;
|
|
13255
|
+
const promptCount = report.prompts.supported ? report.prompts.items.length : 0;
|
|
13256
|
+
const elapsed = report.elapsedMs;
|
|
13257
|
+
const health = healthBadge(elapsed);
|
|
13258
|
+
const counts = `${toolCount} tools \xB7 ${resourceCount} resources \xB7 ${promptCount} prompts`;
|
|
13259
|
+
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);
|
|
13260
|
+
}
|
|
13261
|
+
function healthBadge(elapsedMs) {
|
|
13262
|
+
if (elapsedMs === 0) return { glyph: "\u2717", label: "no inspect data", color: COLOR.err };
|
|
13263
|
+
if (elapsedMs < 500) return { glyph: "\u25CF", label: `healthy \xB7 ${elapsedMs}ms`, color: COLOR.ok };
|
|
13264
|
+
if (elapsedMs < 3e3) return { glyph: "\u25CC", label: `slow \xB7 ${elapsedMs}ms`, color: COLOR.warn };
|
|
13265
|
+
return { glyph: "\u2717", label: `very slow \xB7 ${elapsedMs}ms`, color: COLOR.err };
|
|
13266
|
+
}
|
|
13267
|
+
function capabilityList(s) {
|
|
13268
|
+
const caps = ["tools/list", "tools/call"];
|
|
13269
|
+
if (s.report.resources.supported) caps.push("resources/list");
|
|
13270
|
+
if (s.report.prompts.supported) caps.push("prompts/list");
|
|
13271
|
+
return caps.join(" ");
|
|
13272
|
+
}
|
|
13273
|
+
|
|
12941
13274
|
// src/cli/ui/PlanCheckpointConfirm.tsx
|
|
12942
|
-
import { Box as
|
|
12943
|
-
import
|
|
13275
|
+
import { Box as Box10 } from "ink";
|
|
13276
|
+
import React12 from "react";
|
|
12944
13277
|
|
|
12945
13278
|
// src/cli/ui/PlanStepList.tsx
|
|
12946
|
-
import { Box as
|
|
12947
|
-
import
|
|
13279
|
+
import { Box as Box9, Text as Text9 } from "ink";
|
|
13280
|
+
import React11 from "react";
|
|
12948
13281
|
|
|
12949
13282
|
// src/cli/ui/char-bar.tsx
|
|
12950
|
-
import { Box as
|
|
12951
|
-
import
|
|
13283
|
+
import { Box as Box8, Text as Text8 } from "ink";
|
|
13284
|
+
import React10 from "react";
|
|
12952
13285
|
function CharBar({
|
|
12953
13286
|
pct: pct2,
|
|
12954
13287
|
width = 24,
|
|
@@ -12960,7 +13293,7 @@ function CharBar({
|
|
|
12960
13293
|
const total = Math.max(4, width);
|
|
12961
13294
|
const clamped = Math.max(0, Math.min(100, Number.isFinite(pct2) ? pct2 : 0));
|
|
12962
13295
|
const filled = Math.round(total * clamped / 100);
|
|
12963
|
-
return /* @__PURE__ */
|
|
13296
|
+
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
13297
|
}
|
|
12965
13298
|
|
|
12966
13299
|
// src/cli/ui/PlanStepList.tsx
|
|
@@ -12990,25 +13323,25 @@ function PlanStepListInner({ steps, statuses, focusStepId }) {
|
|
|
12990
13323
|
const doneCount = statusList.filter((s) => s === "done").length;
|
|
12991
13324
|
const pct2 = Math.round(doneCount / total * 100);
|
|
12992
13325
|
const showProgress = doneCount > 0;
|
|
12993
|
-
return /* @__PURE__ */
|
|
13326
|
+
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
13327
|
const status3 = statusList[i];
|
|
12995
13328
|
const isLast = i === total - 1;
|
|
12996
13329
|
const isCur = focusStepId === step.id;
|
|
12997
13330
|
const sg = statusGlyph(status3, isCur);
|
|
12998
13331
|
const risk = riskLabel(step.risk);
|
|
12999
13332
|
const titleDim = status3 === "done" || status3 === "skipped";
|
|
13000
|
-
return /* @__PURE__ */
|
|
13001
|
-
|
|
13333
|
+
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(
|
|
13334
|
+
Text9,
|
|
13002
13335
|
{
|
|
13003
13336
|
dimColor: titleDim,
|
|
13004
13337
|
bold: isCur || status3 === "running",
|
|
13005
13338
|
strikethrough: status3 === "done" || status3 === "skipped"
|
|
13006
13339
|
},
|
|
13007
13340
|
`${step.id} \xB7 ${step.title}`
|
|
13008
|
-
), risk ? /* @__PURE__ */
|
|
13009
|
-
})), showProgress ? /* @__PURE__ */
|
|
13341
|
+
), risk ? /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(Text9, null, " "), /* @__PURE__ */ React11.createElement(Text9, { color: risk.color }, risk.text)) : null);
|
|
13342
|
+
})), showProgress ? /* @__PURE__ */ React11.createElement(Box9, null, /* @__PURE__ */ React11.createElement(Text9, null, " "), /* @__PURE__ */ React11.createElement(CharBar, { pct: pct2, width: 24 })) : null);
|
|
13010
13343
|
}
|
|
13011
|
-
var PlanStepList =
|
|
13344
|
+
var PlanStepList = React11.memo(PlanStepListInner);
|
|
13012
13345
|
|
|
13013
13346
|
// src/cli/ui/PlanCheckpointConfirm.tsx
|
|
13014
13347
|
function PlanCheckpointConfirmInner({
|
|
@@ -13025,7 +13358,7 @@ function PlanCheckpointConfirmInner({
|
|
|
13025
13358
|
const isLast = total > 0 && completed >= total;
|
|
13026
13359
|
const statuses = buildStatusMap(steps, completedStepIds, stepId, isLast);
|
|
13027
13360
|
const subtitle = counter ? `${counter} \xB7 ${label}` : label;
|
|
13028
|
-
return /* @__PURE__ */
|
|
13361
|
+
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
13362
|
SingleSelect,
|
|
13030
13363
|
{
|
|
13031
13364
|
initialValue: isLast ? "stop" : "continue",
|
|
@@ -13051,7 +13384,7 @@ function PlanCheckpointConfirmInner({
|
|
|
13051
13384
|
}
|
|
13052
13385
|
));
|
|
13053
13386
|
}
|
|
13054
|
-
var PlanCheckpointConfirm =
|
|
13387
|
+
var PlanCheckpointConfirm = React12.memo(PlanCheckpointConfirmInner);
|
|
13055
13388
|
function buildStatusMap(steps, completedStepIds, currentStepId, isLast) {
|
|
13056
13389
|
const map = /* @__PURE__ */ new Map();
|
|
13057
13390
|
if (!steps) return map;
|
|
@@ -13067,11 +13400,11 @@ function buildStatusMap(steps, completedStepIds, currentStepId, isLast) {
|
|
|
13067
13400
|
}
|
|
13068
13401
|
|
|
13069
13402
|
// src/cli/ui/PlanConfirm.tsx
|
|
13070
|
-
import { Box as
|
|
13071
|
-
import
|
|
13403
|
+
import { Box as Box11, Text as Text10 } from "ink";
|
|
13404
|
+
import React13 from "react";
|
|
13072
13405
|
function PlanConfirmInner({ plan: plan3, steps, onChoose }) {
|
|
13073
13406
|
const hasOpenQuestions = /^#{1,6}\s*(open[-\s]?questions?|risks?|unknowns?|assumptions?|unclear)/im.test(plan3) || /^#{1,6}\s*(待确认|开放问题|风险|未知|假设|不确定)/im.test(plan3);
|
|
13074
|
-
return /* @__PURE__ */
|
|
13407
|
+
return /* @__PURE__ */ React13.createElement(
|
|
13075
13408
|
ApprovalCard,
|
|
13076
13409
|
{
|
|
13077
13410
|
tone: "accent",
|
|
@@ -13080,9 +13413,9 @@ function PlanConfirmInner({ plan: plan3, steps, onChoose }) {
|
|
|
13080
13413
|
metaRight: "awaiting",
|
|
13081
13414
|
metaRightColor: CARD.plan.color
|
|
13082
13415
|
},
|
|
13083
|
-
hasOpenQuestions ? /* @__PURE__ */
|
|
13084
|
-
steps && steps.length > 0 ? /* @__PURE__ */
|
|
13085
|
-
/* @__PURE__ */
|
|
13416
|
+
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,
|
|
13417
|
+
steps && steps.length > 0 ? /* @__PURE__ */ React13.createElement(Box11, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React13.createElement(PlanStepList, { steps })) : null,
|
|
13418
|
+
/* @__PURE__ */ React13.createElement(
|
|
13086
13419
|
SingleSelect,
|
|
13087
13420
|
{
|
|
13088
13421
|
initialValue: hasOpenQuestions ? "refine" : "approve",
|
|
@@ -13114,21 +13447,21 @@ function PlanConfirmInner({ plan: plan3, steps, onChoose }) {
|
|
|
13114
13447
|
)
|
|
13115
13448
|
);
|
|
13116
13449
|
}
|
|
13117
|
-
var PlanConfirm =
|
|
13450
|
+
var PlanConfirm = React13.memo(PlanConfirmInner);
|
|
13118
13451
|
|
|
13119
13452
|
// src/cli/ui/PlanRefineInput.tsx
|
|
13120
|
-
import { Box as
|
|
13121
|
-
import
|
|
13453
|
+
import { Box as Box12, Text as Text11 } from "ink";
|
|
13454
|
+
import React15, { useState as useState6 } from "react";
|
|
13122
13455
|
|
|
13123
13456
|
// src/cli/ui/ticker.tsx
|
|
13124
|
-
import
|
|
13457
|
+
import React14, { createContext as createContext2, useContext as useContext2, useEffect as useEffect2, useState as useState5 } from "react";
|
|
13125
13458
|
var FAST_TICK_MS = 120;
|
|
13126
13459
|
var SLOW_TICK_MS = 1e3;
|
|
13127
13460
|
var FastTickContext = createContext2(0);
|
|
13128
13461
|
var SlowTickContext = createContext2(0);
|
|
13129
13462
|
function TickerProvider({ children, disabled }) {
|
|
13130
|
-
const [fast, setFast] =
|
|
13131
|
-
const [slow, setSlow] =
|
|
13463
|
+
const [fast, setFast] = useState5(0);
|
|
13464
|
+
const [slow, setSlow] = useState5(0);
|
|
13132
13465
|
useEffect2(() => {
|
|
13133
13466
|
if (disabled) return;
|
|
13134
13467
|
const fastId = setInterval(() => setFast((t2) => t2 + 1), FAST_TICK_MS);
|
|
@@ -13138,7 +13471,7 @@ function TickerProvider({ children, disabled }) {
|
|
|
13138
13471
|
clearInterval(slowId);
|
|
13139
13472
|
};
|
|
13140
13473
|
}, [disabled]);
|
|
13141
|
-
return /* @__PURE__ */
|
|
13474
|
+
return /* @__PURE__ */ React14.createElement(FastTickContext.Provider, { value: fast }, /* @__PURE__ */ React14.createElement(SlowTickContext.Provider, { value: slow }, children));
|
|
13142
13475
|
}
|
|
13143
13476
|
function useTick() {
|
|
13144
13477
|
return useContext2(FastTickContext);
|
|
@@ -13147,7 +13480,7 @@ function useSlowTick() {
|
|
|
13147
13480
|
return useContext2(SlowTickContext);
|
|
13148
13481
|
}
|
|
13149
13482
|
function useElapsedSeconds() {
|
|
13150
|
-
const [start] =
|
|
13483
|
+
const [start] = useState5(() => Date.now());
|
|
13151
13484
|
useSlowTick();
|
|
13152
13485
|
return Math.floor((Date.now() - start) / 1e3);
|
|
13153
13486
|
}
|
|
@@ -13188,7 +13521,7 @@ var MODES = {
|
|
|
13188
13521
|
}
|
|
13189
13522
|
};
|
|
13190
13523
|
function PlanRefineInput({ mode: mode2, onSubmit, onCancel }) {
|
|
13191
|
-
const [value, setValue] =
|
|
13524
|
+
const [value, setValue] = useState6("");
|
|
13192
13525
|
useKeystroke((ev) => {
|
|
13193
13526
|
if (ev.paste) {
|
|
13194
13527
|
setValue((v) => v + ev.input.replace(/\r?\n/g, " "));
|
|
@@ -13213,7 +13546,7 @@ function PlanRefineInput({ mode: mode2, onSubmit, onCancel }) {
|
|
|
13213
13546
|
const tick = useTick();
|
|
13214
13547
|
const cursorOn = Math.floor(tick / 4) % 2 === 0;
|
|
13215
13548
|
const meta = MODES[mode2];
|
|
13216
|
-
return /* @__PURE__ */
|
|
13549
|
+
return /* @__PURE__ */ React15.createElement(
|
|
13217
13550
|
ApprovalCard,
|
|
13218
13551
|
{
|
|
13219
13552
|
tone: meta.tone,
|
|
@@ -13221,14 +13554,14 @@ function PlanRefineInput({ mode: mode2, onSubmit, onCancel }) {
|
|
|
13221
13554
|
title: meta.title,
|
|
13222
13555
|
footerHint: "\u23CE send \xB7 esc return to picker"
|
|
13223
13556
|
},
|
|
13224
|
-
/* @__PURE__ */
|
|
13225
|
-
/* @__PURE__ */
|
|
13557
|
+
/* @__PURE__ */ React15.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text11, { color: FG.sub }, meta.hint, value === "" ? meta.blankHint : "")),
|
|
13558
|
+
/* @__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
13559
|
);
|
|
13227
13560
|
}
|
|
13228
13561
|
|
|
13229
13562
|
// src/cli/ui/PlanReviseConfirm.tsx
|
|
13230
|
-
import { Box as
|
|
13231
|
-
import
|
|
13563
|
+
import { Box as Box13, Text as Text12 } from "ink";
|
|
13564
|
+
import React16 from "react";
|
|
13232
13565
|
function computeDiff(oldSteps, newSteps) {
|
|
13233
13566
|
const oldIds = new Set(oldSteps.map((s) => s.id));
|
|
13234
13567
|
const newIds = new Set(newSteps.map((s) => s.id));
|
|
@@ -13264,7 +13597,7 @@ function PlanReviseConfirmInner({
|
|
|
13264
13597
|
const removedCount = rows.filter((r) => r.kind === "removed").length;
|
|
13265
13598
|
const addedCount = rows.filter((r) => r.kind === "added").length;
|
|
13266
13599
|
const keptCount = rows.filter((r) => r.kind === "kept").length;
|
|
13267
|
-
return /* @__PURE__ */
|
|
13600
|
+
return /* @__PURE__ */ React16.createElement(
|
|
13268
13601
|
ApprovalCard,
|
|
13269
13602
|
{
|
|
13270
13603
|
tone: "warn",
|
|
@@ -13272,17 +13605,17 @@ function PlanReviseConfirmInner({
|
|
|
13272
13605
|
title: "plan revision proposed",
|
|
13273
13606
|
metaRight: `\u2212${removedCount} +${addedCount} \xB7 ${keptCount} kept`
|
|
13274
13607
|
},
|
|
13275
|
-
/* @__PURE__ */
|
|
13276
|
-
summary ? /* @__PURE__ */
|
|
13277
|
-
/* @__PURE__ */
|
|
13608
|
+
/* @__PURE__ */ React16.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text12, null, reason)),
|
|
13609
|
+
summary ? /* @__PURE__ */ React16.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text12, { dimColor: true }, `updated summary: ${summary}`)) : null,
|
|
13610
|
+
/* @__PURE__ */ React16.createElement(Box13, { marginBottom: 1, flexDirection: "column" }, rows.map((row3) => {
|
|
13278
13611
|
const risk = riskDots(row3.step.risk);
|
|
13279
13612
|
const prefix = row3.kind === "removed" ? "\u2212" : row3.kind === "added" ? "+" : " ";
|
|
13280
13613
|
const prefixColor = row3.kind === "removed" ? "#f87171" : row3.kind === "added" ? "#4ade80" : "#94a3b8";
|
|
13281
13614
|
const dim = row3.kind === "kept";
|
|
13282
13615
|
const strike = row3.kind === "removed";
|
|
13283
|
-
return /* @__PURE__ */
|
|
13616
|
+
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
13617
|
})),
|
|
13285
|
-
/* @__PURE__ */
|
|
13618
|
+
/* @__PURE__ */ React16.createElement(
|
|
13286
13619
|
SingleSelect,
|
|
13287
13620
|
{
|
|
13288
13621
|
initialValue: "accept",
|
|
@@ -13304,22 +13637,22 @@ function PlanReviseConfirmInner({
|
|
|
13304
13637
|
)
|
|
13305
13638
|
);
|
|
13306
13639
|
}
|
|
13307
|
-
var PlanReviseConfirm =
|
|
13640
|
+
var PlanReviseConfirm = React16.memo(PlanReviseConfirmInner);
|
|
13308
13641
|
|
|
13309
13642
|
// src/cli/ui/PlanReviseEditor.tsx
|
|
13310
|
-
import { Box as
|
|
13311
|
-
import
|
|
13643
|
+
import { Box as Box14, Text as Text13 } from "ink";
|
|
13644
|
+
import React17, { useState as useState7 } from "react";
|
|
13312
13645
|
function PlanReviseEditor({
|
|
13313
13646
|
steps,
|
|
13314
13647
|
completedStepIds,
|
|
13315
13648
|
onAccept,
|
|
13316
13649
|
onCancel
|
|
13317
13650
|
}) {
|
|
13318
|
-
const [rows, setRows] =
|
|
13651
|
+
const [rows, setRows] = useState7(
|
|
13319
13652
|
() => steps.map((s) => ({ step: s, done: completedStepIds?.has(s.id) ?? false, skipped: false }))
|
|
13320
13653
|
);
|
|
13321
13654
|
const firstEditableIndex = rows.findIndex((r) => !r.done);
|
|
13322
|
-
const [focus, setFocus] =
|
|
13655
|
+
const [focus, setFocus] = useState7(firstEditableIndex < 0 ? 0 : firstEditableIndex);
|
|
13323
13656
|
useKeystroke((ev) => {
|
|
13324
13657
|
if (ev.paste) return;
|
|
13325
13658
|
if (ev.escape) {
|
|
@@ -13380,7 +13713,7 @@ function PlanReviseEditor({
|
|
|
13380
13713
|
return;
|
|
13381
13714
|
}
|
|
13382
13715
|
});
|
|
13383
|
-
return /* @__PURE__ */
|
|
13716
|
+
return /* @__PURE__ */ React17.createElement(
|
|
13384
13717
|
ApprovalCard,
|
|
13385
13718
|
{
|
|
13386
13719
|
tone: "accent",
|
|
@@ -13389,7 +13722,7 @@ function PlanReviseEditor({
|
|
|
13389
13722
|
metaRight: `${rows.length} steps`,
|
|
13390
13723
|
footerHint: "\u2191\u2193 focus \xB7 space toggle skip \xB7 k/j move \xB7 \u23CE accept \xB7 esc cancel"
|
|
13391
13724
|
},
|
|
13392
|
-
rows.map((r, i) => /* @__PURE__ */
|
|
13725
|
+
rows.map((r, i) => /* @__PURE__ */ React17.createElement(ReviseRow, { key: r.step.id, row: r, index: i, focused: i === focus }))
|
|
13393
13726
|
);
|
|
13394
13727
|
}
|
|
13395
13728
|
function ReviseRow({
|
|
@@ -13400,13 +13733,13 @@ function ReviseRow({
|
|
|
13400
13733
|
const marker = row3.done ? "[\u2713]" : row3.skipped ? "[s]" : focused ? "[ ]" : "[ ]";
|
|
13401
13734
|
const markerColor = row3.done ? TONE.ok : row3.skipped ? FG.faint : focused ? TONE.brand : FG.faint;
|
|
13402
13735
|
const titleColor = row3.done ? FG.sub : row3.skipped ? FG.faint : focused ? FG.strong : FG.sub;
|
|
13403
|
-
const focusGlyph = focused ? /* @__PURE__ */
|
|
13404
|
-
return /* @__PURE__ */
|
|
13736
|
+
const focusGlyph = focused ? /* @__PURE__ */ React17.createElement(Text13, { color: TONE.brand }, "\u25B8 ") : /* @__PURE__ */ React17.createElement(Text13, null, " ");
|
|
13737
|
+
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
13738
|
}
|
|
13406
13739
|
|
|
13407
13740
|
// src/cli/ui/PromptInput.tsx
|
|
13408
|
-
import { Box as
|
|
13409
|
-
import
|
|
13741
|
+
import { Box as Box15, Text as Text14, useStdout as useStdout4 } from "ink";
|
|
13742
|
+
import React18, { useRef as useRef2, useState as useState8 } from "react";
|
|
13410
13743
|
|
|
13411
13744
|
// src/cli/ui/key-normalize.ts
|
|
13412
13745
|
var CSI_TAIL_TO_FLAGS = [
|
|
@@ -13812,7 +14145,7 @@ function PromptInput({
|
|
|
13812
14145
|
onHistoryPrev,
|
|
13813
14146
|
onHistoryNext
|
|
13814
14147
|
}) {
|
|
13815
|
-
const [cursor, setCursor] =
|
|
14148
|
+
const [cursor, setCursor] = useState8(value.length);
|
|
13816
14149
|
const pastesRef = useRef2(/* @__PURE__ */ new Map());
|
|
13817
14150
|
const nextPasteIdRef = useRef2(0);
|
|
13818
14151
|
const lastLocalValueRef = useRef2(value);
|
|
@@ -13899,14 +14232,14 @@ function PromptInput({
|
|
|
13899
14232
|
const { line: cursorLine, col: cursorCol } = lineAndColumn(value, cursor);
|
|
13900
14233
|
const renderItems = collapseLinesForDisplay(lines, cursorLine);
|
|
13901
14234
|
const showHugeBufferHints = lines.length > 20;
|
|
13902
|
-
return /* @__PURE__ */
|
|
14235
|
+
return /* @__PURE__ */ React18.createElement(Box15, { flexDirection: "column", paddingX: 1 }, (() => {
|
|
13903
14236
|
const rows = [];
|
|
13904
14237
|
let firstRowEmitted = false;
|
|
13905
14238
|
for (let renderIdx = 0; renderIdx < renderItems.length; renderIdx++) {
|
|
13906
14239
|
const item = renderItems[renderIdx];
|
|
13907
14240
|
if (item.kind === "skip") {
|
|
13908
14241
|
rows.push(
|
|
13909
|
-
/* @__PURE__ */
|
|
14242
|
+
/* @__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
14243
|
);
|
|
13911
14244
|
continue;
|
|
13912
14245
|
}
|
|
@@ -13916,7 +14249,7 @@ function PromptInput({
|
|
|
13916
14249
|
const showPlaceholder = i === 0 && value.length === 0;
|
|
13917
14250
|
if (showPlaceholder) {
|
|
13918
14251
|
rows.push(
|
|
13919
|
-
/* @__PURE__ */
|
|
14252
|
+
/* @__PURE__ */ React18.createElement(
|
|
13920
14253
|
PromptLine,
|
|
13921
14254
|
{
|
|
13922
14255
|
key: `ln-${i}-text-0`,
|
|
@@ -13947,7 +14280,7 @@ function PromptInput({
|
|
|
13947
14280
|
if (seg.kind === "paste") {
|
|
13948
14281
|
const cursorOnIt = isCursorLine && cursorCol >= seg.startOffset && cursorCol <= seg.startOffset + 1;
|
|
13949
14282
|
rows.push(
|
|
13950
|
-
/* @__PURE__ */
|
|
14283
|
+
/* @__PURE__ */ React18.createElement(
|
|
13951
14284
|
PasteChipRow,
|
|
13952
14285
|
{
|
|
13953
14286
|
key: `ln-${i}-paste-${segIdx}`,
|
|
@@ -13964,7 +14297,7 @@ function PromptInput({
|
|
|
13964
14297
|
}
|
|
13965
14298
|
const segHasCursor = isCursorLine && cursorCol >= seg.startOffset && cursorCol <= seg.startOffset + seg.text.length;
|
|
13966
14299
|
rows.push(
|
|
13967
|
-
/* @__PURE__ */
|
|
14300
|
+
/* @__PURE__ */ React18.createElement(
|
|
13968
14301
|
PromptLine,
|
|
13969
14302
|
{
|
|
13970
14303
|
key: `ln-${i}-text-${segIdx}`,
|
|
@@ -13989,7 +14322,7 @@ function PromptInput({
|
|
|
13989
14322
|
const isFirst = !firstRowEmitted;
|
|
13990
14323
|
firstRowEmitted = true;
|
|
13991
14324
|
rows.push(
|
|
13992
|
-
/* @__PURE__ */
|
|
14325
|
+
/* @__PURE__ */ React18.createElement(
|
|
13993
14326
|
PromptLine,
|
|
13994
14327
|
{
|
|
13995
14328
|
key: `ln-${i}-empty`,
|
|
@@ -14012,7 +14345,7 @@ function PromptInput({
|
|
|
14012
14345
|
}
|
|
14013
14346
|
}
|
|
14014
14347
|
return rows;
|
|
14015
|
-
})(), showHugeBufferHints && !disabled ? /* @__PURE__ */
|
|
14348
|
+
})(), 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
14349
|
}
|
|
14017
14350
|
function splitLineByPastes(line) {
|
|
14018
14351
|
const out = [];
|
|
@@ -14049,9 +14382,9 @@ function PasteChipRow({
|
|
|
14049
14382
|
const leadColor = isFirst ? accentColor : FG.faint;
|
|
14050
14383
|
const labelText = formatChipLabel(entry, pasteId, visibleCells - 6);
|
|
14051
14384
|
if (active) {
|
|
14052
|
-
return /* @__PURE__ */
|
|
14385
|
+
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
14386
|
}
|
|
14054
|
-
return /* @__PURE__ */
|
|
14387
|
+
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
14388
|
}
|
|
14056
14389
|
function formatChipLabel(entry, pasteId, budget3) {
|
|
14057
14390
|
if (!entry) return `\u{1F4CB} paste #${pasteId + 1} \xB7 (missing)`;
|
|
@@ -14095,10 +14428,10 @@ function PromptLine({
|
|
|
14095
14428
|
disabled
|
|
14096
14429
|
}) {
|
|
14097
14430
|
if (showPlaceholder) {
|
|
14098
|
-
return /* @__PURE__ */
|
|
14431
|
+
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
14432
|
}
|
|
14100
14433
|
const viewport = buildViewport(line, isCursorLine ? cursorCol : null, visibleCells, pastes);
|
|
14101
|
-
return /* @__PURE__ */
|
|
14434
|
+
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
14435
|
ViewportContent,
|
|
14103
14436
|
{
|
|
14104
14437
|
segments: viewport.segments,
|
|
@@ -14106,7 +14439,7 @@ function PromptLine({
|
|
|
14106
14439
|
accentColor,
|
|
14107
14440
|
cursorVisible
|
|
14108
14441
|
}
|
|
14109
|
-
), viewport.hiddenRight ? /* @__PURE__ */
|
|
14442
|
+
), viewport.hiddenRight ? /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, "\u203A") : null);
|
|
14110
14443
|
}
|
|
14111
14444
|
function ViewportContent({
|
|
14112
14445
|
segments,
|
|
@@ -14115,7 +14448,7 @@ function ViewportContent({
|
|
|
14115
14448
|
cursorVisible
|
|
14116
14449
|
}) {
|
|
14117
14450
|
if (cursorCell === null) {
|
|
14118
|
-
return /* @__PURE__ */
|
|
14451
|
+
return /* @__PURE__ */ React18.createElement(React18.Fragment, null, segments.map((seg, i) => renderSegment(seg, i, false)));
|
|
14119
14452
|
}
|
|
14120
14453
|
const out = [];
|
|
14121
14454
|
let cells = 0;
|
|
@@ -14134,8 +14467,8 @@ function ViewportContent({
|
|
|
14134
14467
|
}
|
|
14135
14468
|
if (seg.kind === "paste") {
|
|
14136
14469
|
out.push(
|
|
14137
|
-
/* @__PURE__ */
|
|
14138
|
-
|
|
14470
|
+
/* @__PURE__ */ React18.createElement(
|
|
14471
|
+
Text14,
|
|
14139
14472
|
{
|
|
14140
14473
|
key: `p-${i}-cursor`,
|
|
14141
14474
|
color: FG.body,
|
|
@@ -14152,29 +14485,29 @@ function ViewportContent({
|
|
|
14152
14485
|
const offsetIntoSeg = cursorCell - cells;
|
|
14153
14486
|
const split = splitTextByCells(seg.text, offsetIntoSeg);
|
|
14154
14487
|
if (split.before.length > 0) {
|
|
14155
|
-
out.push(/* @__PURE__ */
|
|
14488
|
+
out.push(/* @__PURE__ */ React18.createElement(Text14, { key: `t-${i}-b` }, split.before));
|
|
14156
14489
|
}
|
|
14157
14490
|
if (split.atCursor.length > 0) {
|
|
14158
14491
|
out.push(
|
|
14159
|
-
/* @__PURE__ */
|
|
14492
|
+
/* @__PURE__ */ React18.createElement(Text14, { key: `t-${i}-c`, inverse: cursorVisible, color: accentColor }, split.atCursor)
|
|
14160
14493
|
);
|
|
14161
14494
|
} else {
|
|
14162
14495
|
out.push(
|
|
14163
|
-
/* @__PURE__ */
|
|
14496
|
+
/* @__PURE__ */ React18.createElement(Text14, { key: `t-${i}-c-eol`, color: accentColor }, cursorVisible ? "\u258C" : " ")
|
|
14164
14497
|
);
|
|
14165
14498
|
}
|
|
14166
14499
|
if (split.after.length > 0) {
|
|
14167
|
-
out.push(/* @__PURE__ */
|
|
14500
|
+
out.push(/* @__PURE__ */ React18.createElement(Text14, { key: `t-${i}-a` }, split.after));
|
|
14168
14501
|
}
|
|
14169
14502
|
placed = true;
|
|
14170
14503
|
cells += segCells;
|
|
14171
14504
|
}
|
|
14172
14505
|
if (!placed) {
|
|
14173
14506
|
out.push(
|
|
14174
|
-
/* @__PURE__ */
|
|
14507
|
+
/* @__PURE__ */ React18.createElement(Text14, { key: "cursor-eol", color: accentColor }, cursorVisible ? "\u258C" : " ")
|
|
14175
14508
|
);
|
|
14176
14509
|
}
|
|
14177
|
-
return /* @__PURE__ */
|
|
14510
|
+
return /* @__PURE__ */ React18.createElement(React18.Fragment, null, out);
|
|
14178
14511
|
}
|
|
14179
14512
|
function segmentCells(seg) {
|
|
14180
14513
|
if (seg.kind === "paste") return seg.label.length;
|
|
@@ -14214,9 +14547,9 @@ function charCellsForText(ch) {
|
|
|
14214
14547
|
}
|
|
14215
14548
|
function renderSegment(seg, key, _inverse) {
|
|
14216
14549
|
if (seg.kind === "text") {
|
|
14217
|
-
return /* @__PURE__ */
|
|
14550
|
+
return /* @__PURE__ */ React18.createElement(Text14, { key: `s-${key}` }, seg.text);
|
|
14218
14551
|
}
|
|
14219
|
-
return /* @__PURE__ */
|
|
14552
|
+
return /* @__PURE__ */ React18.createElement(Text14, { key: `s-${key}`, backgroundColor: SURFACE.bgElev, color: FG.body }, seg.label);
|
|
14220
14553
|
}
|
|
14221
14554
|
var COLLAPSE_THRESHOLD = 20;
|
|
14222
14555
|
var COLLAPSE_HEAD_LINES = 3;
|
|
@@ -14243,16 +14576,16 @@ function collapseLinesForDisplay(lines, cursorLine) {
|
|
|
14243
14576
|
}
|
|
14244
14577
|
|
|
14245
14578
|
// src/cli/ui/SessionPicker.tsx
|
|
14246
|
-
import { Box as
|
|
14247
|
-
import
|
|
14579
|
+
import { Box as Box16, Text as Text15, useStdout as useStdout5 } from "ink";
|
|
14580
|
+
import React19, { useState as useState9 } from "react";
|
|
14248
14581
|
var PAGE_MARGIN = 6;
|
|
14249
14582
|
function SessionPicker({
|
|
14250
14583
|
sessions: sessions2,
|
|
14251
14584
|
workspace: workspace2,
|
|
14252
14585
|
onChoose
|
|
14253
14586
|
}) {
|
|
14254
|
-
const [focus, setFocus] =
|
|
14255
|
-
const [renaming, setRenaming] =
|
|
14587
|
+
const [focus, setFocus] = useState9(0);
|
|
14588
|
+
const [renaming, setRenaming] = useState9(null);
|
|
14256
14589
|
const { stdout: stdout4 } = useStdout5();
|
|
14257
14590
|
const rows = stdout4?.rows ?? 40;
|
|
14258
14591
|
const visibleCount = Math.max(3, rows - PAGE_MARGIN);
|
|
@@ -14306,7 +14639,7 @@ function SessionPicker({
|
|
|
14306
14639
|
const end = Math.min(sessions2.length, start + visibleCount);
|
|
14307
14640
|
const shown = sessions2.slice(start, end);
|
|
14308
14641
|
const hiddenBelow = sessions2.length - end;
|
|
14309
|
-
return /* @__PURE__ */
|
|
14642
|
+
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
14643
|
}
|
|
14311
14644
|
function SessionRow({
|
|
14312
14645
|
info,
|
|
@@ -14317,7 +14650,7 @@ function SessionRow({
|
|
|
14317
14650
|
const turns = info.meta.turnCount ?? Math.ceil(info.messageCount / 2);
|
|
14318
14651
|
const costCny = info.meta.totalCostUsd !== void 0 ? `\xA5${(info.meta.totalCostUsd * USD_TO_CNY).toFixed(2)}` : "";
|
|
14319
14652
|
const time = relativeTime2(info.mtime);
|
|
14320
|
-
return /* @__PURE__ */
|
|
14653
|
+
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
14654
|
}
|
|
14322
14655
|
function truncate2(s, max) {
|
|
14323
14656
|
if (s.length <= max) return s;
|
|
@@ -14337,14 +14670,14 @@ function relativeTime2(date) {
|
|
|
14337
14670
|
}
|
|
14338
14671
|
|
|
14339
14672
|
// src/cli/ui/ShellConfirm.tsx
|
|
14340
|
-
import { Box as
|
|
14341
|
-
import
|
|
14673
|
+
import { Box as Box17, Text as Text16 } from "ink";
|
|
14674
|
+
import React20, { useState as useState10 } from "react";
|
|
14342
14675
|
function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
|
|
14343
14676
|
const isBackground = kind === "run_background";
|
|
14344
14677
|
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] =
|
|
14678
|
+
const [phase, setPhase] = useState10("pick");
|
|
14346
14679
|
if (phase === "deny") {
|
|
14347
|
-
return /* @__PURE__ */
|
|
14680
|
+
return /* @__PURE__ */ React20.createElement(
|
|
14348
14681
|
ApprovalCard,
|
|
14349
14682
|
{
|
|
14350
14683
|
tone: "error",
|
|
@@ -14353,7 +14686,7 @@ function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
|
|
|
14353
14686
|
metaRight: "optional",
|
|
14354
14687
|
footerHint: "\u23CE submit \xB7 esc skip (deny without reason)"
|
|
14355
14688
|
},
|
|
14356
|
-
/* @__PURE__ */
|
|
14689
|
+
/* @__PURE__ */ React20.createElement(
|
|
14357
14690
|
DenyContextInput,
|
|
14358
14691
|
{
|
|
14359
14692
|
onSubmit: (context2) => onChoose("deny", context2 || void 0),
|
|
@@ -14362,7 +14695,7 @@ function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
|
|
|
14362
14695
|
)
|
|
14363
14696
|
);
|
|
14364
14697
|
}
|
|
14365
|
-
return /* @__PURE__ */
|
|
14698
|
+
return /* @__PURE__ */ React20.createElement(
|
|
14366
14699
|
ApprovalCard,
|
|
14367
14700
|
{
|
|
14368
14701
|
tone: "warn",
|
|
@@ -14371,9 +14704,9 @@ function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
|
|
|
14371
14704
|
metaRight: "awaiting",
|
|
14372
14705
|
footerHint: "\u2191\u2193 pick \xB7 \u23CE confirm \xB7 esc cancel"
|
|
14373
14706
|
},
|
|
14374
|
-
/* @__PURE__ */
|
|
14375
|
-
/* @__PURE__ */
|
|
14376
|
-
/* @__PURE__ */
|
|
14707
|
+
/* @__PURE__ */ React20.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text16, { color: FG.faint }, subtitle)),
|
|
14708
|
+
/* @__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)),
|
|
14709
|
+
/* @__PURE__ */ React20.createElement(
|
|
14377
14710
|
SingleSelect,
|
|
14378
14711
|
{
|
|
14379
14712
|
initialValue: "run_once",
|
|
@@ -14433,8 +14766,8 @@ function derivePrefix(command) {
|
|
|
14433
14766
|
}
|
|
14434
14767
|
|
|
14435
14768
|
// src/cli/ui/SlashArgPicker.tsx
|
|
14436
|
-
import { Box as
|
|
14437
|
-
import
|
|
14769
|
+
import { Box as Box18, Text as Text17 } from "ink";
|
|
14770
|
+
import React21 from "react";
|
|
14438
14771
|
function SlashArgPicker({
|
|
14439
14772
|
matches,
|
|
14440
14773
|
selectedIndex,
|
|
@@ -14442,13 +14775,13 @@ function SlashArgPicker({
|
|
|
14442
14775
|
kind,
|
|
14443
14776
|
partial
|
|
14444
14777
|
}) {
|
|
14445
|
-
const headerRow = /* @__PURE__ */
|
|
14778
|
+
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
14779
|
if (kind === "hint") {
|
|
14447
|
-
return /* @__PURE__ */
|
|
14780
|
+
return /* @__PURE__ */ React21.createElement(Box18, { paddingX: 1, marginTop: 1 }, headerRow);
|
|
14448
14781
|
}
|
|
14449
14782
|
if (matches === null) return null;
|
|
14450
14783
|
if (matches.length === 0) {
|
|
14451
|
-
return /* @__PURE__ */
|
|
14784
|
+
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
14785
|
}
|
|
14453
14786
|
const MAX = 8;
|
|
14454
14787
|
const total = matches.length;
|
|
@@ -14456,22 +14789,22 @@ function SlashArgPicker({
|
|
|
14456
14789
|
const shown = matches.slice(windowStart, windowStart + MAX);
|
|
14457
14790
|
const hiddenAbove = windowStart;
|
|
14458
14791
|
const hiddenBelow = total - windowStart - shown.length;
|
|
14459
|
-
return /* @__PURE__ */
|
|
14792
|
+
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
14793
|
}
|
|
14461
14794
|
function ArgRow({ value, isSelected }) {
|
|
14462
|
-
return /* @__PURE__ */
|
|
14795
|
+
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
14796
|
}
|
|
14464
14797
|
|
|
14465
14798
|
// src/cli/ui/SlashSuggestions.tsx
|
|
14466
|
-
import { Box as
|
|
14467
|
-
import
|
|
14799
|
+
import { Box as Box19, Text as Text18 } from "ink";
|
|
14800
|
+
import React22 from "react";
|
|
14468
14801
|
function SlashSuggestions({
|
|
14469
14802
|
matches,
|
|
14470
14803
|
selectedIndex
|
|
14471
14804
|
}) {
|
|
14472
14805
|
if (matches === null) return null;
|
|
14473
14806
|
if (matches.length === 0) {
|
|
14474
|
-
return /* @__PURE__ */
|
|
14807
|
+
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
14808
|
}
|
|
14476
14809
|
const MAX = 8;
|
|
14477
14810
|
const total = matches.length;
|
|
@@ -14479,17 +14812,17 @@ function SlashSuggestions({
|
|
|
14479
14812
|
const shown = matches.slice(windowStart, windowStart + MAX);
|
|
14480
14813
|
const hiddenAbove = windowStart;
|
|
14481
14814
|
const hiddenBelow = total - windowStart - shown.length;
|
|
14482
|
-
return /* @__PURE__ */
|
|
14815
|
+
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
14816
|
}
|
|
14484
14817
|
function SuggestionRow({ spec, isSelected }) {
|
|
14485
14818
|
const name = `/${spec.cmd}`;
|
|
14486
14819
|
const argsSuffix = spec.argsHint ? spec.argsHint : "";
|
|
14487
|
-
return /* @__PURE__ */
|
|
14820
|
+
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
14821
|
}
|
|
14489
14822
|
|
|
14490
14823
|
// src/cli/ui/WelcomeBanner.tsx
|
|
14491
|
-
import { Box as
|
|
14492
|
-
import
|
|
14824
|
+
import { Box as Box20, Text as Text19, useStdout as useStdout6 } from "ink";
|
|
14825
|
+
import React23 from "react";
|
|
14493
14826
|
var TAGLINE_CHAT = "DeepSeek-native agent";
|
|
14494
14827
|
var TAGLINE_CODE = "DeepSeek-native coding agent";
|
|
14495
14828
|
var TAGLINE_SUB = "cache-first \xB7 flash-first";
|
|
@@ -14510,22 +14843,22 @@ function WelcomeBanner({
|
|
|
14510
14843
|
const hintsIndent = Math.max(2, Math.floor((cols - hintsRow.length) / 2));
|
|
14511
14844
|
const startTextRaw = "type a message to start your session";
|
|
14512
14845
|
const startIndent = Math.max(2, Math.floor((cols - startTextRaw.length) / 2));
|
|
14513
|
-
return /* @__PURE__ */
|
|
14846
|
+
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
14847
|
}
|
|
14515
14848
|
function BoxRow({
|
|
14516
14849
|
indent,
|
|
14517
14850
|
children
|
|
14518
14851
|
}) {
|
|
14519
|
-
return /* @__PURE__ */
|
|
14852
|
+
return /* @__PURE__ */ React23.createElement(Box20, null, /* @__PURE__ */ React23.createElement(Text19, null, " ".repeat(indent)), children);
|
|
14520
14853
|
}
|
|
14521
14854
|
function BoxLine({
|
|
14522
14855
|
pad: pad3,
|
|
14523
14856
|
children
|
|
14524
14857
|
}) {
|
|
14525
14858
|
if (children === "" || children === void 0) {
|
|
14526
|
-
return /* @__PURE__ */
|
|
14859
|
+
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
14860
|
}
|
|
14528
|
-
return /* @__PURE__ */
|
|
14861
|
+
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
14862
|
}
|
|
14530
14863
|
function centerInside(text, pad3) {
|
|
14531
14864
|
if (text.length >= pad3) return text.slice(0, pad3);
|
|
@@ -14547,12 +14880,12 @@ ${output}`;
|
|
|
14547
14880
|
}
|
|
14548
14881
|
|
|
14549
14882
|
// src/cli/ui/cards/PlanCard.tsx
|
|
14550
|
-
import { Box as
|
|
14551
|
-
import
|
|
14883
|
+
import { Box as Box23, Text as Text22 } from "ink";
|
|
14884
|
+
import React26 from "react";
|
|
14552
14885
|
|
|
14553
14886
|
// src/cli/ui/primitives/BarRow.tsx
|
|
14554
|
-
import { Box as
|
|
14555
|
-
import
|
|
14887
|
+
import { Box as Box21, Text as Text20 } from "ink";
|
|
14888
|
+
import React24 from "react";
|
|
14556
14889
|
|
|
14557
14890
|
// src/cli/ui/cards/glyphs.ts
|
|
14558
14891
|
var STRUCT = {
|
|
@@ -14572,17 +14905,17 @@ function BarRow({
|
|
|
14572
14905
|
children
|
|
14573
14906
|
}) {
|
|
14574
14907
|
const t2 = CARD[tone];
|
|
14575
|
-
return /* @__PURE__ */
|
|
14908
|
+
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
14909
|
}
|
|
14577
14910
|
function CursorBlock() {
|
|
14578
14911
|
const tick = useTick();
|
|
14579
14912
|
const on = Math.floor(tick / 4) % 2 === 0;
|
|
14580
|
-
return /* @__PURE__ */
|
|
14913
|
+
return /* @__PURE__ */ React24.createElement(Text20, { inverse: on, color: CARD.streaming.color }, " ");
|
|
14581
14914
|
}
|
|
14582
14915
|
|
|
14583
14916
|
// src/cli/ui/cards/CardHeader.tsx
|
|
14584
|
-
import { Box as
|
|
14585
|
-
import
|
|
14917
|
+
import { Box as Box22, Text as Text21 } from "ink";
|
|
14918
|
+
import React25 from "react";
|
|
14586
14919
|
function CardHeader({
|
|
14587
14920
|
tone,
|
|
14588
14921
|
glyph,
|
|
@@ -14596,7 +14929,7 @@ function CardHeader({
|
|
|
14596
14929
|
}) {
|
|
14597
14930
|
const t2 = CARD[tone];
|
|
14598
14931
|
const bar2 = barColor ?? t2.color;
|
|
14599
|
-
return /* @__PURE__ */
|
|
14932
|
+
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
14933
|
}
|
|
14601
14934
|
|
|
14602
14935
|
// src/cli/ui/cards/PlanCard.tsx
|
|
@@ -14622,11 +14955,11 @@ function PlanCard({ card }) {
|
|
|
14622
14955
|
const variantTag = card.variant === "resumed" ? " \xB7 resumed" : card.variant === "replay" ? " \xB7 \u23EA archive" : "";
|
|
14623
14956
|
const meta = `${variantTag} \xB7 ${doneCount} of ${card.steps.length} done`;
|
|
14624
14957
|
const showFooter = card.variant === "active";
|
|
14625
|
-
return /* @__PURE__ */
|
|
14958
|
+
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
14959
|
const isActive = step.status === "running";
|
|
14627
14960
|
const titleColor = isActive ? FG.strong : step.status === "queued" ? FG.sub : FG.sub;
|
|
14628
|
-
return /* @__PURE__ */
|
|
14629
|
-
}), showFooter && /* @__PURE__ */
|
|
14961
|
+
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"));
|
|
14962
|
+
}), 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
14963
|
}
|
|
14631
14964
|
|
|
14632
14965
|
// src/cli/ui/edit-history.ts
|
|
@@ -15069,7 +15402,7 @@ function useAgentSession({
|
|
|
15069
15402
|
import { useMemo as useMemo3 } from "react";
|
|
15070
15403
|
|
|
15071
15404
|
// src/cli/ui/state/provider.tsx
|
|
15072
|
-
import
|
|
15405
|
+
import React27 from "react";
|
|
15073
15406
|
|
|
15074
15407
|
// src/cli/ui/state/reducer.ts
|
|
15075
15408
|
function reduce(state, event) {
|
|
@@ -15408,26 +15741,26 @@ function createStore(session, initialCards) {
|
|
|
15408
15741
|
}
|
|
15409
15742
|
|
|
15410
15743
|
// src/cli/ui/state/provider.tsx
|
|
15411
|
-
var StoreCtx =
|
|
15744
|
+
var StoreCtx = React27.createContext(null);
|
|
15412
15745
|
function AgentStoreProvider({
|
|
15413
15746
|
session,
|
|
15414
15747
|
initialCards,
|
|
15415
15748
|
children
|
|
15416
15749
|
}) {
|
|
15417
|
-
const initialCardsRef =
|
|
15418
|
-
const store =
|
|
15419
|
-
return /* @__PURE__ */
|
|
15750
|
+
const initialCardsRef = React27.useRef(initialCards);
|
|
15751
|
+
const store = React27.useMemo(() => createStore(session, initialCardsRef.current), [session]);
|
|
15752
|
+
return /* @__PURE__ */ React27.createElement(StoreCtx.Provider, { value: store }, children);
|
|
15420
15753
|
}
|
|
15421
15754
|
function useAgentStore() {
|
|
15422
|
-
const store =
|
|
15755
|
+
const store = React27.useContext(StoreCtx);
|
|
15423
15756
|
if (!store) throw new Error("useAgentStore must be used inside AgentStoreProvider");
|
|
15424
15757
|
return store;
|
|
15425
15758
|
}
|
|
15426
15759
|
function useAgentState(selector) {
|
|
15427
15760
|
const store = useAgentStore();
|
|
15428
|
-
const subscribe =
|
|
15429
|
-
const getSnapshot =
|
|
15430
|
-
return
|
|
15761
|
+
const subscribe = React27.useCallback((cb) => store.subscribe(cb), [store]);
|
|
15762
|
+
const getSnapshot = React27.useCallback(() => selector(store.getState()), [store, selector]);
|
|
15763
|
+
return React27.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
15431
15764
|
}
|
|
15432
15765
|
function useDispatch() {
|
|
15433
15766
|
return useAgentStore().dispatch;
|
|
@@ -15679,22 +16012,22 @@ function useSyntheticSubmit(deps) {
|
|
|
15679
16012
|
|
|
15680
16013
|
// src/cli/ui/layout/CardStream.tsx
|
|
15681
16014
|
import { Static } from "ink";
|
|
15682
|
-
import
|
|
16015
|
+
import React47 from "react";
|
|
15683
16016
|
|
|
15684
16017
|
// src/cli/ui/cards/CardRenderer.tsx
|
|
15685
|
-
import { Box as
|
|
15686
|
-
import
|
|
16018
|
+
import { Box as Box41, Text as Text41 } from "ink";
|
|
16019
|
+
import React46 from "react";
|
|
15687
16020
|
|
|
15688
16021
|
// src/cli/ui/cards/BranchCard.tsx
|
|
15689
|
-
import { Text as
|
|
15690
|
-
import { Box as
|
|
15691
|
-
import
|
|
16022
|
+
import { Text as Text23 } from "ink";
|
|
16023
|
+
import { Box as Box24 } from "ink";
|
|
16024
|
+
import React28 from "react";
|
|
15692
16025
|
var BAR_CELLS = 28;
|
|
15693
16026
|
function BranchCard({ card }) {
|
|
15694
16027
|
const ratio = card.total > 0 ? card.completed / card.total : 0;
|
|
15695
16028
|
const filled = Math.max(0, Math.min(BAR_CELLS, Math.round(ratio * BAR_CELLS)));
|
|
15696
16029
|
const tone = card.done ? TONE.ok : CARD.streaming.color;
|
|
15697
|
-
return /* @__PURE__ */
|
|
16030
|
+
return /* @__PURE__ */ React28.createElement(Box24, { flexDirection: "column" }, /* @__PURE__ */ React28.createElement(
|
|
15698
16031
|
CardHeader,
|
|
15699
16032
|
{
|
|
15700
16033
|
tone: "streaming",
|
|
@@ -15703,27 +16036,27 @@ function BranchCard({ card }) {
|
|
|
15703
16036
|
meta: `\xB7 ${card.completed} of ${card.total} samples`,
|
|
15704
16037
|
barColor: tone
|
|
15705
16038
|
}
|
|
15706
|
-
), /* @__PURE__ */
|
|
16039
|
+
), /* @__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
16040
|
}
|
|
15708
16041
|
|
|
15709
16042
|
// src/cli/ui/cards/CtxCard.tsx
|
|
15710
|
-
import { Box as
|
|
15711
|
-
import
|
|
16043
|
+
import { Box as Box25, Text as Text24 } from "ink";
|
|
16044
|
+
import React29 from "react";
|
|
15712
16045
|
var BAR_CELLS2 = 32;
|
|
15713
16046
|
function row2(label, tokens, ratio, color2) {
|
|
15714
16047
|
const filled = Math.max(0, Math.min(BAR_CELLS2, Math.round(ratio * BAR_CELLS2)));
|
|
15715
|
-
return /* @__PURE__ */
|
|
16048
|
+
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
16049
|
}
|
|
15717
16050
|
function CtxCard({ card }) {
|
|
15718
16051
|
const cap = Math.max(1, card.ctxMax);
|
|
15719
16052
|
const used = card.systemTokens + card.toolsTokens + card.logTokens + card.inputTokens;
|
|
15720
16053
|
const usedPct = used / cap * 100;
|
|
15721
|
-
return /* @__PURE__ */
|
|
16054
|
+
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
16055
|
}
|
|
15723
16056
|
|
|
15724
16057
|
// src/cli/ui/cards/DiffCard.tsx
|
|
15725
|
-
import { Box as
|
|
15726
|
-
import
|
|
16058
|
+
import { Box as Box26, Text as Text25 } from "ink";
|
|
16059
|
+
import React30 from "react";
|
|
15727
16060
|
var LINE_COLOR = {
|
|
15728
16061
|
ctx: FG.sub,
|
|
15729
16062
|
add: TONE.ok,
|
|
@@ -15731,14 +16064,14 @@ var LINE_COLOR = {
|
|
|
15731
16064
|
fold: FG.faint
|
|
15732
16065
|
};
|
|
15733
16066
|
function DiffCard({ card }) {
|
|
15734
|
-
const meta = /* @__PURE__ */
|
|
16067
|
+
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
16068
|
const showFooter = card.hunks.length > 0;
|
|
15736
|
-
return /* @__PURE__ */
|
|
16069
|
+
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
16070
|
}
|
|
15738
16071
|
|
|
15739
16072
|
// src/cli/ui/cards/DoctorCard.tsx
|
|
15740
|
-
import { Box as
|
|
15741
|
-
import
|
|
16073
|
+
import { Box as Box27, Text as Text26 } from "ink";
|
|
16074
|
+
import React31 from "react";
|
|
15742
16075
|
var LEVEL_COLOR = {
|
|
15743
16076
|
ok: TONE.ok,
|
|
15744
16077
|
warn: TONE.warn,
|
|
@@ -15760,12 +16093,12 @@ function DoctorCard({ card }) {
|
|
|
15760
16093
|
const fail = card.checks.filter((c) => c.level === "fail").length;
|
|
15761
16094
|
const summary = `${card.checks.length} checks \xB7 ${ok} passed${warn > 0 ? ` \xB7 ${warn} warn` : ""}${fail > 0 ? ` \xB7 ${fail} fail` : ""}`;
|
|
15762
16095
|
const labelWidth = card.checks.reduce((m, c) => Math.max(m, c.label.length), 0);
|
|
15763
|
-
return /* @__PURE__ */
|
|
16096
|
+
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
16097
|
}
|
|
15765
16098
|
|
|
15766
16099
|
// src/cli/ui/cards/ErrorCard.tsx
|
|
15767
|
-
import { Box as
|
|
15768
|
-
import
|
|
16100
|
+
import { Box as Box28, Text as Text27 } from "ink";
|
|
16101
|
+
import React32 from "react";
|
|
15769
16102
|
var STACK_TAIL = 5;
|
|
15770
16103
|
function ErrorCard({ card }) {
|
|
15771
16104
|
const meta = card.retries !== void 0 && card.retries > 0 ? `\xB7 ${card.retries} retr${card.retries === 1 ? "y" : "ies"}` : void 0;
|
|
@@ -15774,16 +16107,16 @@ function ErrorCard({ card }) {
|
|
|
15774
16107
|
const stackVisible = stackTrunc ? stackLines.slice(-STACK_TAIL) : stackLines;
|
|
15775
16108
|
const stackHidden = stackTrunc ? stackLines.length - stackVisible.length : 0;
|
|
15776
16109
|
const hasStack = stackVisible.length > 0;
|
|
15777
|
-
return /* @__PURE__ */
|
|
16110
|
+
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
16111
|
}
|
|
15779
16112
|
|
|
15780
16113
|
// src/cli/ui/cards/LiveCard.tsx
|
|
15781
|
-
import { Box as
|
|
15782
|
-
import
|
|
16114
|
+
import { Box as Box29, Text as Text29 } from "ink";
|
|
16115
|
+
import React34 from "react";
|
|
15783
16116
|
|
|
15784
16117
|
// src/cli/ui/primitives/Spinner.tsx
|
|
15785
|
-
import { Text as
|
|
15786
|
-
import
|
|
16118
|
+
import { Text as Text28 } from "ink";
|
|
16119
|
+
import React33 from "react";
|
|
15787
16120
|
var FRAMES = {
|
|
15788
16121
|
circle: ["\u25D0", "\u25D3", "\u25D1", "\u25D2"],
|
|
15789
16122
|
braille: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827"]
|
|
@@ -15794,12 +16127,12 @@ var CADENCE_MS = {
|
|
|
15794
16127
|
};
|
|
15795
16128
|
function Spinner({ kind = "circle", color: color2, bold }) {
|
|
15796
16129
|
const frames = FRAMES[kind];
|
|
15797
|
-
const [frame, setFrame] =
|
|
15798
|
-
|
|
16130
|
+
const [frame, setFrame] = React33.useState(0);
|
|
16131
|
+
React33.useEffect(() => {
|
|
15799
16132
|
const id = setInterval(() => setFrame((f) => (f + 1) % frames.length), CADENCE_MS[kind]);
|
|
15800
16133
|
return () => clearInterval(id);
|
|
15801
16134
|
}, [kind, frames.length]);
|
|
15802
|
-
return /* @__PURE__ */
|
|
16135
|
+
return /* @__PURE__ */ React33.createElement(Text28, { bold, color: color2 }, frames[frame]);
|
|
15803
16136
|
}
|
|
15804
16137
|
|
|
15805
16138
|
// src/cli/ui/cards/LiveCard.tsx
|
|
@@ -15826,12 +16159,12 @@ var VARIANT_GLYPH = {
|
|
|
15826
16159
|
function LiveCard({ card }) {
|
|
15827
16160
|
const color2 = TONE_TO_COLOR[card.tone];
|
|
15828
16161
|
const glyph = VARIANT_GLYPH[card.variant];
|
|
15829
|
-
return /* @__PURE__ */
|
|
16162
|
+
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
16163
|
}
|
|
15831
16164
|
|
|
15832
16165
|
// src/cli/ui/cards/MemoryCard.tsx
|
|
15833
|
-
import { Box as
|
|
15834
|
-
import
|
|
16166
|
+
import { Box as Box30, Text as Text30 } from "ink";
|
|
16167
|
+
import React35 from "react";
|
|
15835
16168
|
var CATEGORY_ORDER = [
|
|
15836
16169
|
"user",
|
|
15837
16170
|
"feedback",
|
|
@@ -15860,7 +16193,7 @@ function MemoryCard({ card }) {
|
|
|
15860
16193
|
const counts = countByCategory(card.entries);
|
|
15861
16194
|
const summary = CATEGORY_ORDER.filter((c) => counts[c] > 0).map((c) => `${counts[c]} ${c}`).join(" \xB7 ");
|
|
15862
16195
|
const tokens = card.tokens > 1024 ? `~${(card.tokens / 1024).toFixed(1)}K tok` : `~${card.tokens} tok`;
|
|
15863
|
-
return /* @__PURE__ */
|
|
16196
|
+
return /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "column" }, /* @__PURE__ */ React35.createElement(
|
|
15864
16197
|
CardHeader,
|
|
15865
16198
|
{
|
|
15866
16199
|
tone: "memory",
|
|
@@ -15874,7 +16207,7 @@ function MemoryCard({ card }) {
|
|
|
15874
16207
|
const all = card.entries.filter((e) => e.category === category);
|
|
15875
16208
|
const shown = all.slice(0, 5);
|
|
15876
16209
|
const remaining = all.length - shown.length;
|
|
15877
|
-
return /* @__PURE__ */
|
|
16210
|
+
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
16211
|
}));
|
|
15879
16212
|
}
|
|
15880
16213
|
function countByCategory(entries) {
|
|
@@ -15889,8 +16222,8 @@ function countByCategory(entries) {
|
|
|
15889
16222
|
}
|
|
15890
16223
|
|
|
15891
16224
|
// src/cli/ui/cards/ReasoningCard.tsx
|
|
15892
|
-
import { Box as
|
|
15893
|
-
import
|
|
16225
|
+
import { Box as Box31, Text as Text31, useStdout as useStdout7 } from "ink";
|
|
16226
|
+
import React36 from "react";
|
|
15894
16227
|
|
|
15895
16228
|
// src/frame/width.ts
|
|
15896
16229
|
import stringWidthLib from "string-width";
|
|
@@ -15939,19 +16272,19 @@ function ReasoningCard({
|
|
|
15939
16272
|
const visible = overflows ? allLines.slice(-lineSlots) : allLines;
|
|
15940
16273
|
const headDropped = overflows ? allLines.length - visible.length : 0;
|
|
15941
16274
|
const showBody = expanded && allLines.length > 0;
|
|
15942
|
-
return /* @__PURE__ */
|
|
16275
|
+
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
16276
|
const isLast = i === visible.length - 1;
|
|
15944
|
-
return /* @__PURE__ */
|
|
16277
|
+
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
16278
|
})));
|
|
15946
16279
|
}
|
|
15947
16280
|
|
|
15948
16281
|
// src/cli/ui/cards/SearchCard.tsx
|
|
15949
|
-
import { Box as
|
|
15950
|
-
import
|
|
16282
|
+
import { Box as Box32, Text as Text32 } from "ink";
|
|
16283
|
+
import React37 from "react";
|
|
15951
16284
|
function SearchCard({ card }) {
|
|
15952
16285
|
const fileCount = new Set(card.hits.map((h) => h.file)).size;
|
|
15953
16286
|
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__ */
|
|
16287
|
+
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
16288
|
}
|
|
15956
16289
|
function HighlightedLine({
|
|
15957
16290
|
text,
|
|
@@ -15959,9 +16292,9 @@ function HighlightedLine({
|
|
|
15959
16292
|
end
|
|
15960
16293
|
}) {
|
|
15961
16294
|
if (start < 0 || end <= start || end > text.length) {
|
|
15962
|
-
return /* @__PURE__ */
|
|
16295
|
+
return /* @__PURE__ */ React37.createElement(Text32, { color: FG.sub }, text);
|
|
15963
16296
|
}
|
|
15964
|
-
return /* @__PURE__ */
|
|
16297
|
+
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
16298
|
}
|
|
15966
16299
|
function groupByFile(hits) {
|
|
15967
16300
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -15974,12 +16307,12 @@ function groupByFile(hits) {
|
|
|
15974
16307
|
}
|
|
15975
16308
|
|
|
15976
16309
|
// src/cli/ui/cards/StreamingCard.tsx
|
|
15977
|
-
import { Box as
|
|
15978
|
-
import
|
|
16310
|
+
import { Box as Box34, Text as Text34, useStdout as useStdout8 } from "ink";
|
|
16311
|
+
import React39 from "react";
|
|
15979
16312
|
|
|
15980
16313
|
// src/cli/ui/markdown.tsx
|
|
15981
16314
|
import { highlight, supportsLanguage } from "cli-highlight";
|
|
15982
|
-
import { Box as
|
|
16315
|
+
import { Box as Box33, Text as Text33 } from "ink";
|
|
15983
16316
|
|
|
15984
16317
|
// node_modules/marked/lib/marked.esm.js
|
|
15985
16318
|
function _getDefaults() {
|
|
@@ -17991,7 +18324,7 @@ var parser = _Parser.parse;
|
|
|
17991
18324
|
var lexer = _Lexer.lex;
|
|
17992
18325
|
|
|
17993
18326
|
// src/cli/ui/markdown.tsx
|
|
17994
|
-
import
|
|
18327
|
+
import React38 from "react";
|
|
17995
18328
|
import stringWidth from "string-width";
|
|
17996
18329
|
function padToCells(text, cells) {
|
|
17997
18330
|
const w = stringWidth(text);
|
|
@@ -18000,41 +18333,41 @@ function padToCells(text, cells) {
|
|
|
18000
18333
|
}
|
|
18001
18334
|
marked.setOptions({ gfm: true, breaks: false });
|
|
18002
18335
|
function Markdown({ text }) {
|
|
18003
|
-
const tokens =
|
|
18004
|
-
return /* @__PURE__ */
|
|
18336
|
+
const tokens = React38.useMemo(() => marked.lexer(text), [text]);
|
|
18337
|
+
return /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column", gap: 1 }, tokens.map((token, i) => /* @__PURE__ */ React38.createElement(BlockToken, { key: `${i}-${token.type}`, token })));
|
|
18005
18338
|
}
|
|
18006
18339
|
function BlockToken({ token }) {
|
|
18007
18340
|
switch (token.type) {
|
|
18008
18341
|
case "heading":
|
|
18009
|
-
return /* @__PURE__ */
|
|
18342
|
+
return /* @__PURE__ */ React38.createElement(Heading, { token });
|
|
18010
18343
|
case "paragraph":
|
|
18011
|
-
return /* @__PURE__ */
|
|
18344
|
+
return /* @__PURE__ */ React38.createElement(Paragraph, { token });
|
|
18012
18345
|
case "list":
|
|
18013
|
-
return /* @__PURE__ */
|
|
18346
|
+
return /* @__PURE__ */ React38.createElement(List, { token, depth: 0 });
|
|
18014
18347
|
case "code":
|
|
18015
|
-
return /* @__PURE__ */
|
|
18348
|
+
return /* @__PURE__ */ React38.createElement(CodeBlock, { token });
|
|
18016
18349
|
case "blockquote":
|
|
18017
|
-
return /* @__PURE__ */
|
|
18350
|
+
return /* @__PURE__ */ React38.createElement(Blockquote, { token });
|
|
18018
18351
|
case "hr":
|
|
18019
|
-
return /* @__PURE__ */
|
|
18352
|
+
return /* @__PURE__ */ React38.createElement(HorizontalRule, null);
|
|
18020
18353
|
case "table":
|
|
18021
|
-
return /* @__PURE__ */
|
|
18354
|
+
return /* @__PURE__ */ React38.createElement(Table, { token });
|
|
18022
18355
|
case "html":
|
|
18023
|
-
return /* @__PURE__ */
|
|
18356
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: FG.body }, token.text);
|
|
18024
18357
|
case "space":
|
|
18025
18358
|
return null;
|
|
18026
18359
|
default:
|
|
18027
|
-
return /* @__PURE__ */
|
|
18360
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: FG.body }, token.raw ?? "");
|
|
18028
18361
|
}
|
|
18029
18362
|
}
|
|
18030
18363
|
function Heading({ token }) {
|
|
18031
|
-
return /* @__PURE__ */
|
|
18364
|
+
return /* @__PURE__ */ React38.createElement(Box33, null, /* @__PURE__ */ React38.createElement(Text33, { bold: true, color: FG.strong, backgroundColor: SURFACE.bgElev }, ` ${plainText(token.tokens)} `));
|
|
18032
18365
|
}
|
|
18033
18366
|
function Paragraph({ token }) {
|
|
18034
|
-
return /* @__PURE__ */
|
|
18367
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: FG.body }, /* @__PURE__ */ React38.createElement(Inline, { tokens: token.tokens ?? [] }));
|
|
18035
18368
|
}
|
|
18036
18369
|
function List({ token, depth }) {
|
|
18037
|
-
return /* @__PURE__ */
|
|
18370
|
+
return /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column" }, token.items.map((item, i) => /* @__PURE__ */ React38.createElement(
|
|
18038
18371
|
ListItem,
|
|
18039
18372
|
{
|
|
18040
18373
|
key: `${i}-${item.text.slice(0, 24)}`,
|
|
@@ -18055,27 +18388,27 @@ function ListItem({
|
|
|
18055
18388
|
const markerColor = item.task ? item.checked ? TONE.ok : FG.faint : FG.meta;
|
|
18056
18389
|
const dim = item.task && item.checked === true;
|
|
18057
18390
|
const indent = " ".repeat(depth + 1);
|
|
18058
|
-
return /* @__PURE__ */
|
|
18391
|
+
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
18392
|
if (tok.type === "text") {
|
|
18060
18393
|
const inner = tok.tokens;
|
|
18061
18394
|
return (
|
|
18062
18395
|
// biome-ignore lint/suspicious/noArrayIndexKey: list-item children are positional and stable per render
|
|
18063
|
-
/* @__PURE__ */
|
|
18396
|
+
/* @__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
18397
|
);
|
|
18065
18398
|
}
|
|
18066
18399
|
if (tok.type === "list") {
|
|
18067
|
-
return /* @__PURE__ */
|
|
18400
|
+
return /* @__PURE__ */ React38.createElement(List, { key: `l-${i}`, token: tok, depth: depth + 1 });
|
|
18068
18401
|
}
|
|
18069
|
-
return /* @__PURE__ */
|
|
18402
|
+
return /* @__PURE__ */ React38.createElement(BlockToken, { key: `b-${i}-${tok.type}`, token: tok });
|
|
18070
18403
|
})));
|
|
18071
18404
|
}
|
|
18072
18405
|
function CodeBlock({ token }) {
|
|
18073
18406
|
const lang = token.lang?.split(/\s+/)[0] ?? "";
|
|
18074
18407
|
const colored = highlightCode(token.text, lang);
|
|
18075
18408
|
const lines = colored.split("\n");
|
|
18076
|
-
return /* @__PURE__ */
|
|
18409
|
+
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
18410
|
// biome-ignore lint/suspicious/noArrayIndexKey: code lines are positional and stable per render
|
|
18078
|
-
/* @__PURE__ */
|
|
18411
|
+
/* @__PURE__ */ React38.createElement(Text33, { key: `code-${i}`, backgroundColor: SURFACE.bgElev }, ` ${line} `)
|
|
18079
18412
|
))));
|
|
18080
18413
|
}
|
|
18081
18414
|
function highlightCode(source, lang) {
|
|
@@ -18088,10 +18421,10 @@ function highlightCode(source, lang) {
|
|
|
18088
18421
|
}
|
|
18089
18422
|
}
|
|
18090
18423
|
function Blockquote({ token }) {
|
|
18091
|
-
return /* @__PURE__ */
|
|
18424
|
+
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
18425
|
}
|
|
18093
18426
|
function HorizontalRule() {
|
|
18094
|
-
return /* @__PURE__ */
|
|
18427
|
+
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
18428
|
}
|
|
18096
18429
|
function Table({ token }) {
|
|
18097
18430
|
const colCount = token.header.length;
|
|
@@ -18106,29 +18439,29 @@ function Table({ token }) {
|
|
|
18106
18439
|
}
|
|
18107
18440
|
const GAP = " ";
|
|
18108
18441
|
const ruleRow = widths.map((w) => "\u2500".repeat(w)).join(GAP);
|
|
18109
|
-
return /* @__PURE__ */
|
|
18442
|
+
return /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column" }, /* @__PURE__ */ React38.createElement(Box33, null, /* @__PURE__ */ React38.createElement(Text33, null, " "), headerCells.map((cell, i) => (
|
|
18110
18443
|
// biome-ignore lint/suspicious/noArrayIndexKey: header cells positional
|
|
18111
|
-
/* @__PURE__ */
|
|
18112
|
-
))), /* @__PURE__ */
|
|
18444
|
+
/* @__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)
|
|
18445
|
+
))), /* @__PURE__ */ React38.createElement(Box33, null, /* @__PURE__ */ React38.createElement(Text33, null, " "), /* @__PURE__ */ React38.createElement(Text33, { color: FG.faint }, ruleRow)), bodyCells.map((row3, ri) => (
|
|
18113
18446
|
// biome-ignore lint/suspicious/noArrayIndexKey: body rows positional
|
|
18114
|
-
/* @__PURE__ */
|
|
18447
|
+
/* @__PURE__ */ React38.createElement(Box33, { key: `tr-${ri}` }, /* @__PURE__ */ React38.createElement(Text33, null, " "), row3.map((cell, i) => (
|
|
18115
18448
|
// biome-ignore lint/suspicious/noArrayIndexKey: cells positional
|
|
18116
|
-
/* @__PURE__ */
|
|
18449
|
+
/* @__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
18450
|
)))
|
|
18118
18451
|
)));
|
|
18119
18452
|
}
|
|
18120
18453
|
function Inline({ tokens }) {
|
|
18121
|
-
return /* @__PURE__ */
|
|
18454
|
+
return /* @__PURE__ */ React38.createElement(React38.Fragment, null, tokens.map((tok, i) => /* @__PURE__ */ React38.createElement(InlineToken, { key: `${i}-${tok.type}`, token: tok })));
|
|
18122
18455
|
}
|
|
18123
18456
|
var FILE_REF_RE = /\b([A-Za-z0-9_./@\-]+\.[A-Za-z0-9]{1,6})(?::(\d+)(?:-(\d+))?)?\b/g;
|
|
18124
18457
|
var MENTION_RE = /(?<![A-Za-z0-9_])@([A-Za-z0-9_./\-]+\.[A-Za-z0-9]{1,6})/g;
|
|
18125
18458
|
function osc8(label, target, color2) {
|
|
18126
18459
|
const open = `\x1B]8;;${target}\x07`;
|
|
18127
18460
|
const close = "\x1B]8;;\x07";
|
|
18128
|
-
return /* @__PURE__ */
|
|
18461
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: color2, underline: true }, `${open}${label}${close}`);
|
|
18129
18462
|
}
|
|
18130
18463
|
function renderInlineText(raw) {
|
|
18131
|
-
if (!raw) return /* @__PURE__ */
|
|
18464
|
+
if (!raw) return /* @__PURE__ */ React38.createElement(Text33, null, raw);
|
|
18132
18465
|
const out = [];
|
|
18133
18466
|
let cursor = 0;
|
|
18134
18467
|
const hits = [];
|
|
@@ -18139,7 +18472,7 @@ function renderInlineText(raw) {
|
|
|
18139
18472
|
hits.push({
|
|
18140
18473
|
start,
|
|
18141
18474
|
end,
|
|
18142
|
-
node: /* @__PURE__ */
|
|
18475
|
+
node: /* @__PURE__ */ React38.createElement(Text33, { color: TONE.warn, underline: true }, `@${path5}`)
|
|
18143
18476
|
});
|
|
18144
18477
|
}
|
|
18145
18478
|
for (const m of raw.matchAll(FILE_REF_RE)) {
|
|
@@ -18155,44 +18488,44 @@ function renderInlineText(raw) {
|
|
|
18155
18488
|
let key = 0;
|
|
18156
18489
|
for (const h of hits) {
|
|
18157
18490
|
if (h.start > cursor) {
|
|
18158
|
-
out.push(/* @__PURE__ */
|
|
18491
|
+
out.push(/* @__PURE__ */ React38.createElement(Text33, { key: `t-${key++}` }, raw.slice(cursor, h.start)));
|
|
18159
18492
|
}
|
|
18160
|
-
out.push(/* @__PURE__ */
|
|
18493
|
+
out.push(/* @__PURE__ */ React38.createElement(React38.Fragment, { key: `r-${key++}` }, h.node));
|
|
18161
18494
|
cursor = h.end;
|
|
18162
18495
|
}
|
|
18163
|
-
if (cursor < raw.length) out.push(/* @__PURE__ */
|
|
18164
|
-
return /* @__PURE__ */
|
|
18496
|
+
if (cursor < raw.length) out.push(/* @__PURE__ */ React38.createElement(Text33, { key: `t-${key++}` }, raw.slice(cursor)));
|
|
18497
|
+
return /* @__PURE__ */ React38.createElement(React38.Fragment, null, out);
|
|
18165
18498
|
}
|
|
18166
18499
|
function InlineToken({ token }) {
|
|
18167
18500
|
switch (token.type) {
|
|
18168
18501
|
case "text": {
|
|
18169
18502
|
const t2 = token;
|
|
18170
|
-
return t2.tokens ? /* @__PURE__ */
|
|
18503
|
+
return t2.tokens ? /* @__PURE__ */ React38.createElement(Inline, { tokens: t2.tokens }) : renderInlineText(t2.text);
|
|
18171
18504
|
}
|
|
18172
18505
|
case "strong":
|
|
18173
|
-
return /* @__PURE__ */
|
|
18506
|
+
return /* @__PURE__ */ React38.createElement(Text33, { bold: true, color: FG.strong }, /* @__PURE__ */ React38.createElement(Inline, { tokens: token.tokens }));
|
|
18174
18507
|
case "em":
|
|
18175
|
-
return /* @__PURE__ */
|
|
18508
|
+
return /* @__PURE__ */ React38.createElement(Text33, { italic: true }, /* @__PURE__ */ React38.createElement(Inline, { tokens: token.tokens }));
|
|
18176
18509
|
case "codespan":
|
|
18177
|
-
return /* @__PURE__ */
|
|
18510
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: FG.strong, backgroundColor: SURFACE.bgElev }, ` ${token.text} `);
|
|
18178
18511
|
case "del":
|
|
18179
|
-
return /* @__PURE__ */
|
|
18512
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: TONE.err, strikethrough: true }, /* @__PURE__ */ React38.createElement(Inline, { tokens: token.tokens }));
|
|
18180
18513
|
case "link": {
|
|
18181
18514
|
const l = token;
|
|
18182
|
-
return /* @__PURE__ */
|
|
18515
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: TONE.brand, underline: true }, /* @__PURE__ */ React38.createElement(Inline, { tokens: l.tokens }));
|
|
18183
18516
|
}
|
|
18184
18517
|
case "image": {
|
|
18185
18518
|
const im = token;
|
|
18186
|
-
return /* @__PURE__ */
|
|
18519
|
+
return /* @__PURE__ */ React38.createElement(Text33, { color: TONE.brand }, `[image: ${im.text || im.href}]`);
|
|
18187
18520
|
}
|
|
18188
18521
|
case "br":
|
|
18189
|
-
return /* @__PURE__ */
|
|
18522
|
+
return /* @__PURE__ */ React38.createElement(Text33, null, "\n");
|
|
18190
18523
|
case "escape":
|
|
18191
|
-
return /* @__PURE__ */
|
|
18524
|
+
return /* @__PURE__ */ React38.createElement(Text33, null, token.text);
|
|
18192
18525
|
case "html":
|
|
18193
|
-
return /* @__PURE__ */
|
|
18526
|
+
return /* @__PURE__ */ React38.createElement(Text33, null, token.text);
|
|
18194
18527
|
default:
|
|
18195
|
-
return /* @__PURE__ */
|
|
18528
|
+
return /* @__PURE__ */ React38.createElement(Text33, null, token.raw ?? "");
|
|
18196
18529
|
}
|
|
18197
18530
|
}
|
|
18198
18531
|
function plainText(tokens) {
|
|
@@ -18230,7 +18563,7 @@ var RESERVED_CHROME_ROWS = 14;
|
|
|
18230
18563
|
var BODY_INDENT_CELLS2 = 5;
|
|
18231
18564
|
function StreamingCard({ card }) {
|
|
18232
18565
|
if (card.done && !card.aborted) {
|
|
18233
|
-
return /* @__PURE__ */
|
|
18566
|
+
return /* @__PURE__ */ React39.createElement(Box34, { flexDirection: "column", paddingLeft: 3 }, /* @__PURE__ */ React39.createElement(Markdown, { text: card.text }));
|
|
18234
18567
|
}
|
|
18235
18568
|
const { stdout: stdout4 } = useStdout8();
|
|
18236
18569
|
const rows = stdout4?.rows ?? 40;
|
|
@@ -18243,8 +18576,8 @@ function StreamingCard({ card }) {
|
|
|
18243
18576
|
const overflows = !card.done && allLines.length > lineSlots;
|
|
18244
18577
|
const visible = overflows ? allLines.slice(-lineSlots) : allLines;
|
|
18245
18578
|
const headDropped = overflows ? allLines.length - visible.length : 0;
|
|
18246
|
-
return /* @__PURE__ */
|
|
18247
|
-
|
|
18579
|
+
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(
|
|
18580
|
+
Text34,
|
|
18248
18581
|
{
|
|
18249
18582
|
color: FG.faint
|
|
18250
18583
|
},
|
|
@@ -18252,58 +18585,58 @@ function StreamingCard({ card }) {
|
|
|
18252
18585
|
)), visible.map((line, i) => {
|
|
18253
18586
|
const isLast = i === visible.length - 1;
|
|
18254
18587
|
const isFirstRendered = !card.aborted && headDropped === 0 && i === 0;
|
|
18255
|
-
return /* @__PURE__ */
|
|
18588
|
+
return /* @__PURE__ */ React39.createElement(
|
|
18256
18589
|
BarRow,
|
|
18257
18590
|
{
|
|
18258
18591
|
key: `${card.id}:${headDropped + i}`,
|
|
18259
18592
|
tone: "streaming",
|
|
18260
18593
|
glyph: isFirstRendered ? "\u25B6" : void 0
|
|
18261
18594
|
},
|
|
18262
|
-
/* @__PURE__ */
|
|
18263
|
-
isLast && !card.done && /* @__PURE__ */
|
|
18595
|
+
/* @__PURE__ */ React39.createElement(Text34, { color: card.aborted ? FG.meta : FG.body }, clipToCells(line, lineCells)),
|
|
18596
|
+
isLast && !card.done && /* @__PURE__ */ React39.createElement(CursorBlock, null)
|
|
18264
18597
|
);
|
|
18265
|
-
}), card.aborted && /* @__PURE__ */
|
|
18598
|
+
}), card.aborted && /* @__PURE__ */ React39.createElement(BarRow, { tone: "streaming" }, /* @__PURE__ */ React39.createElement(Text34, { color: FG.faint }, "[truncated by esc]")));
|
|
18266
18599
|
}
|
|
18267
18600
|
|
|
18268
18601
|
// src/cli/ui/cards/SubAgentCard.tsx
|
|
18269
|
-
import { Box as
|
|
18270
|
-
import
|
|
18602
|
+
import { Box as Box35, Text as Text35 } from "ink";
|
|
18603
|
+
import React40 from "react";
|
|
18271
18604
|
var STATUS_COLOR2 = {
|
|
18272
18605
|
running: TONE.violet,
|
|
18273
18606
|
done: TONE.ok,
|
|
18274
18607
|
failed: TONE.err
|
|
18275
18608
|
};
|
|
18276
18609
|
function SubAgentCard({ card }) {
|
|
18277
|
-
return /* @__PURE__ */
|
|
18610
|
+
return /* @__PURE__ */ React40.createElement(Box35, { flexDirection: "column" }, /* @__PURE__ */ React40.createElement(
|
|
18278
18611
|
CardHeader,
|
|
18279
18612
|
{
|
|
18280
18613
|
tone: "subagent",
|
|
18281
18614
|
glyph: "\u232C",
|
|
18282
18615
|
title: `Sub-agent \xB7 ${card.name}`,
|
|
18283
|
-
trailing: /* @__PURE__ */
|
|
18616
|
+
trailing: /* @__PURE__ */ React40.createElement(Text35, { color: STATUS_COLOR2[card.status] }, card.status)
|
|
18284
18617
|
}
|
|
18285
|
-
), /* @__PURE__ */
|
|
18618
|
+
), /* @__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
18619
|
}
|
|
18287
18620
|
function ChildSummary({ card }) {
|
|
18288
18621
|
switch (card.kind) {
|
|
18289
18622
|
case "reasoning":
|
|
18290
|
-
return /* @__PURE__ */
|
|
18623
|
+
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
18624
|
case "tool":
|
|
18292
|
-
return /* @__PURE__ */
|
|
18625
|
+
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
18626
|
case "streaming":
|
|
18294
|
-
return /* @__PURE__ */
|
|
18627
|
+
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
18628
|
case "diff":
|
|
18296
|
-
return /* @__PURE__ */
|
|
18629
|
+
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
18630
|
case "error":
|
|
18298
|
-
return /* @__PURE__ */
|
|
18631
|
+
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
18632
|
default:
|
|
18300
|
-
return /* @__PURE__ */
|
|
18633
|
+
return /* @__PURE__ */ React40.createElement(Text35, { color: FG.faint }, `\xB7 ${card.kind}`);
|
|
18301
18634
|
}
|
|
18302
18635
|
}
|
|
18303
18636
|
|
|
18304
18637
|
// src/cli/ui/cards/TaskCard.tsx
|
|
18305
|
-
import { Box as
|
|
18306
|
-
import
|
|
18638
|
+
import { Box as Box36, Text as Text36 } from "ink";
|
|
18639
|
+
import React41 from "react";
|
|
18307
18640
|
var STEP_GLYPH = {
|
|
18308
18641
|
queued: "\u25CB",
|
|
18309
18642
|
running: "\u25B6",
|
|
@@ -18329,22 +18662,22 @@ var TASK_GLYPH = {
|
|
|
18329
18662
|
function TaskCard({ card }) {
|
|
18330
18663
|
const elapsed = `${(card.elapsedMs / 1e3).toFixed(1)}s`;
|
|
18331
18664
|
const showSteps = card.steps.length > 0;
|
|
18332
|
-
return /* @__PURE__ */
|
|
18665
|
+
return /* @__PURE__ */ React41.createElement(Box36, { flexDirection: "column" }, /* @__PURE__ */ React41.createElement(
|
|
18333
18666
|
CardHeader,
|
|
18334
18667
|
{
|
|
18335
18668
|
tone: "task",
|
|
18336
18669
|
glyph: TASK_GLYPH[card.status],
|
|
18337
18670
|
title: `Step ${card.index} of ${card.total} \xB7 ${card.title}`,
|
|
18338
18671
|
meta: `${elapsed} \xB7 `,
|
|
18339
|
-
trailing: /* @__PURE__ */
|
|
18672
|
+
trailing: /* @__PURE__ */ React41.createElement(Text36, { color: TASK_COLOR[card.status] }, card.status),
|
|
18340
18673
|
barColor: TASK_COLOR[card.status]
|
|
18341
18674
|
}
|
|
18342
|
-
), showSteps && /* @__PURE__ */
|
|
18675
|
+
), 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
18676
|
}
|
|
18344
18677
|
|
|
18345
18678
|
// src/cli/ui/cards/ToolCard.tsx
|
|
18346
|
-
import { Box as
|
|
18347
|
-
import
|
|
18679
|
+
import { Box as Box37, Text as Text37, useStdout as useStdout9 } from "ink";
|
|
18680
|
+
import React42 from "react";
|
|
18348
18681
|
var READ_TAIL = 2;
|
|
18349
18682
|
var OTHER_TAIL = 5;
|
|
18350
18683
|
var BODY_INDENT_CELLS3 = 5;
|
|
@@ -18365,7 +18698,7 @@ function ToolCard({ card }) {
|
|
|
18365
18698
|
const hidden = truncated ? allLines.length - visible.length : 0;
|
|
18366
18699
|
const errColor = card.exitCode && card.exitCode !== 0 ? CARD.error.color : FG.sub;
|
|
18367
18700
|
const showBody = visible.length > 0;
|
|
18368
|
-
return /* @__PURE__ */
|
|
18701
|
+
return /* @__PURE__ */ React42.createElement(Box37, { flexDirection: "column" }, /* @__PURE__ */ React42.createElement(
|
|
18369
18702
|
CardHeader,
|
|
18370
18703
|
{
|
|
18371
18704
|
tone: "tool",
|
|
@@ -18373,10 +18706,10 @@ function ToolCard({ card }) {
|
|
|
18373
18706
|
title: card.name,
|
|
18374
18707
|
subtitle: argsLabel || void 0,
|
|
18375
18708
|
meta: meta || void 0,
|
|
18376
|
-
inline: !card.done ? /* @__PURE__ */
|
|
18377
|
-
trailing: card.retry ? /* @__PURE__ */
|
|
18709
|
+
inline: !card.done ? /* @__PURE__ */ React42.createElement(Spinner, { kind: "braille", color: CARD.tool.color, bold: true }) : void 0,
|
|
18710
|
+
trailing: card.retry ? /* @__PURE__ */ React42.createElement(Text37, { color: TONE.warn, bold: true }, `\u21BB retry ${card.retry.attempt}/${card.retry.max}`) : void 0
|
|
18378
18711
|
}
|
|
18379
|
-
), showBody && /* @__PURE__ */
|
|
18712
|
+
), 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
18713
|
}
|
|
18381
18714
|
function formatArgsSummary(args) {
|
|
18382
18715
|
if (typeof args === "string") return args.length > 60 ? `${args.slice(0, 60)}\u2026` : args;
|
|
@@ -18408,8 +18741,8 @@ function formatMeta(card) {
|
|
|
18408
18741
|
}
|
|
18409
18742
|
|
|
18410
18743
|
// src/cli/ui/cards/UsageCard.tsx
|
|
18411
|
-
import { Box as
|
|
18412
|
-
import
|
|
18744
|
+
import { Box as Box38, Text as Text38 } from "ink";
|
|
18745
|
+
import React43 from "react";
|
|
18413
18746
|
var BAR_CELLS3 = 30;
|
|
18414
18747
|
function compactNum(n) {
|
|
18415
18748
|
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
@@ -18419,32 +18752,32 @@ function compactNum(n) {
|
|
|
18419
18752
|
function bar(ratio, color2) {
|
|
18420
18753
|
const filled = Math.max(0, Math.min(BAR_CELLS3, Math.round(ratio * BAR_CELLS3)));
|
|
18421
18754
|
const empty = BAR_CELLS3 - filled;
|
|
18422
|
-
return /* @__PURE__ */
|
|
18755
|
+
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
18756
|
}
|
|
18424
18757
|
function UsageCard({ card }) {
|
|
18425
|
-
if (card.compact) return /* @__PURE__ */
|
|
18758
|
+
if (card.compact) return /* @__PURE__ */ React43.createElement(CompactUsageRow, { card });
|
|
18426
18759
|
const cap = Math.max(1, card.tokens.promptCap);
|
|
18427
18760
|
const promptRatio = card.tokens.prompt / cap;
|
|
18428
18761
|
const reasonRatio = card.tokens.reason / cap;
|
|
18429
18762
|
const outputRatio = card.tokens.output / cap;
|
|
18430
18763
|
const elapsed = card.elapsedMs !== void 0 ? ` \xB7 ${(card.elapsedMs / 1e3).toFixed(1)}s` : "";
|
|
18431
18764
|
const meta = `${formatCNY(card.cost)}${elapsed}`;
|
|
18432
|
-
return /* @__PURE__ */
|
|
18765
|
+
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
18766
|
}
|
|
18434
18767
|
function CompactUsageRow({ card }) {
|
|
18435
18768
|
const elapsed = card.elapsedMs !== void 0 ? ` \xB7 ${(card.elapsedMs / 1e3).toFixed(1)}s` : "";
|
|
18436
|
-
return /* @__PURE__ */
|
|
18437
|
-
|
|
18769
|
+
return /* @__PURE__ */ React43.createElement(Box38, null, /* @__PURE__ */ React43.createElement(Text38, { color: FG.faint }, ` \u03A3 turn ${card.turn} \xB7 `), /* @__PURE__ */ React43.createElement(
|
|
18770
|
+
Text38,
|
|
18438
18771
|
{
|
|
18439
18772
|
color: FG.meta
|
|
18440
18773
|
},
|
|
18441
18774
|
`${compactNum(card.tokens.prompt)} prompt \xB7 ${compactNum(card.tokens.output)} out`
|
|
18442
|
-
), /* @__PURE__ */
|
|
18775
|
+
), /* @__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
18776
|
}
|
|
18444
18777
|
|
|
18445
18778
|
// src/cli/ui/cards/UserCard.tsx
|
|
18446
|
-
import { Box as
|
|
18447
|
-
import
|
|
18779
|
+
import { Box as Box39, Text as Text39 } from "ink";
|
|
18780
|
+
import React44 from "react";
|
|
18448
18781
|
|
|
18449
18782
|
// src/cli/ui/cards/time.ts
|
|
18450
18783
|
function formatRelativeTime(ts, now = Date.now()) {
|
|
@@ -18461,15 +18794,15 @@ function formatRelativeTime(ts, now = Date.now()) {
|
|
|
18461
18794
|
|
|
18462
18795
|
// src/cli/ui/cards/UserCard.tsx
|
|
18463
18796
|
function UserCard({ card }) {
|
|
18464
|
-
return /* @__PURE__ */
|
|
18797
|
+
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
18798
|
}
|
|
18466
18799
|
|
|
18467
18800
|
// src/cli/ui/cards/WarnCard.tsx
|
|
18468
|
-
import { Box as
|
|
18469
|
-
import
|
|
18801
|
+
import { Box as Box40, Text as Text40 } from "ink";
|
|
18802
|
+
import React45 from "react";
|
|
18470
18803
|
function WarnCard({ card }) {
|
|
18471
18804
|
const showBody = card.message.length > 0;
|
|
18472
|
-
return /* @__PURE__ */
|
|
18805
|
+
return /* @__PURE__ */ React45.createElement(Box40, { flexDirection: "column" }, /* @__PURE__ */ React45.createElement(
|
|
18473
18806
|
CardHeader,
|
|
18474
18807
|
{
|
|
18475
18808
|
tone: "warn",
|
|
@@ -18477,7 +18810,7 @@ function WarnCard({ card }) {
|
|
|
18477
18810
|
title: card.title,
|
|
18478
18811
|
meta: card.detail ? `\xB7 ${card.detail}` : void 0
|
|
18479
18812
|
}
|
|
18480
|
-
), showBody && /* @__PURE__ */
|
|
18813
|
+
), 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
18814
|
}
|
|
18482
18815
|
|
|
18483
18816
|
// src/cli/ui/cards/CardRenderer.tsx
|
|
@@ -18485,52 +18818,52 @@ function CardRenderer({ card }) {
|
|
|
18485
18818
|
const contentStreaming = useAgentState(
|
|
18486
18819
|
(s) => s.cards.some((c) => c.kind === "streaming" && c.text.length > 0 && !c.done)
|
|
18487
18820
|
);
|
|
18488
|
-
return /* @__PURE__ */
|
|
18821
|
+
return /* @__PURE__ */ React46.createElement(Box41, { flexDirection: "column", marginTop: 1 }, renderCard(card, contentStreaming));
|
|
18489
18822
|
}
|
|
18490
18823
|
function renderCard(card, contentStreaming) {
|
|
18491
18824
|
switch (card.kind) {
|
|
18492
18825
|
case "user":
|
|
18493
|
-
return /* @__PURE__ */
|
|
18826
|
+
return /* @__PURE__ */ React46.createElement(UserCard, { card });
|
|
18494
18827
|
case "reasoning":
|
|
18495
|
-
return /* @__PURE__ */
|
|
18828
|
+
return /* @__PURE__ */ React46.createElement(ReasoningCard, { card, expanded: !(card.streaming && contentStreaming) });
|
|
18496
18829
|
case "streaming":
|
|
18497
|
-
return /* @__PURE__ */
|
|
18830
|
+
return /* @__PURE__ */ React46.createElement(StreamingCard, { card });
|
|
18498
18831
|
case "tool":
|
|
18499
|
-
return /* @__PURE__ */
|
|
18832
|
+
return /* @__PURE__ */ React46.createElement(ToolCard, { card });
|
|
18500
18833
|
case "task":
|
|
18501
|
-
return /* @__PURE__ */
|
|
18834
|
+
return /* @__PURE__ */ React46.createElement(TaskCard, { card });
|
|
18502
18835
|
case "plan":
|
|
18503
|
-
return /* @__PURE__ */
|
|
18836
|
+
return /* @__PURE__ */ React46.createElement(PlanCard, { card });
|
|
18504
18837
|
case "diff":
|
|
18505
|
-
return /* @__PURE__ */
|
|
18838
|
+
return /* @__PURE__ */ React46.createElement(DiffCard, { card });
|
|
18506
18839
|
case "error":
|
|
18507
|
-
return /* @__PURE__ */
|
|
18840
|
+
return /* @__PURE__ */ React46.createElement(ErrorCard, { card });
|
|
18508
18841
|
case "warn":
|
|
18509
|
-
return /* @__PURE__ */
|
|
18842
|
+
return /* @__PURE__ */ React46.createElement(WarnCard, { card });
|
|
18510
18843
|
case "usage":
|
|
18511
|
-
return /* @__PURE__ */
|
|
18844
|
+
return /* @__PURE__ */ React46.createElement(UsageCard, { card });
|
|
18512
18845
|
case "memory":
|
|
18513
|
-
return /* @__PURE__ */
|
|
18846
|
+
return /* @__PURE__ */ React46.createElement(MemoryCard, { card });
|
|
18514
18847
|
case "subagent":
|
|
18515
|
-
return /* @__PURE__ */
|
|
18848
|
+
return /* @__PURE__ */ React46.createElement(SubAgentCard, { card });
|
|
18516
18849
|
case "search":
|
|
18517
|
-
return /* @__PURE__ */
|
|
18850
|
+
return /* @__PURE__ */ React46.createElement(SearchCard, { card });
|
|
18518
18851
|
case "approval":
|
|
18519
|
-
return /* @__PURE__ */
|
|
18852
|
+
return /* @__PURE__ */ React46.createElement(FallbackCard, { card });
|
|
18520
18853
|
case "live":
|
|
18521
|
-
return /* @__PURE__ */
|
|
18854
|
+
return /* @__PURE__ */ React46.createElement(LiveCard, { card });
|
|
18522
18855
|
case "ctx":
|
|
18523
|
-
return /* @__PURE__ */
|
|
18856
|
+
return /* @__PURE__ */ React46.createElement(CtxCard, { card });
|
|
18524
18857
|
case "doctor":
|
|
18525
|
-
return /* @__PURE__ */
|
|
18858
|
+
return /* @__PURE__ */ React46.createElement(DoctorCard, { card });
|
|
18526
18859
|
case "branch":
|
|
18527
|
-
return /* @__PURE__ */
|
|
18860
|
+
return /* @__PURE__ */ React46.createElement(BranchCard, { card });
|
|
18528
18861
|
default:
|
|
18529
|
-
return /* @__PURE__ */
|
|
18862
|
+
return /* @__PURE__ */ React46.createElement(FallbackCard, { card });
|
|
18530
18863
|
}
|
|
18531
18864
|
}
|
|
18532
18865
|
function FallbackCard({ card }) {
|
|
18533
|
-
return /* @__PURE__ */
|
|
18866
|
+
return /* @__PURE__ */ React46.createElement(Box41, { flexDirection: "row" }, /* @__PURE__ */ React46.createElement(Text41, { color: FG.faint }, ` \xB7 ${card.kind} card \xB7 not yet migrated`));
|
|
18534
18867
|
}
|
|
18535
18868
|
|
|
18536
18869
|
// src/cli/ui/layout/CardStream.tsx
|
|
@@ -18561,16 +18894,16 @@ function CardStream({ excludeId } = {}) {
|
|
|
18561
18894
|
}
|
|
18562
18895
|
const committed = filtered.slice(0, cutoff);
|
|
18563
18896
|
const live = filtered.slice(cutoff);
|
|
18564
|
-
return /* @__PURE__ */
|
|
18897
|
+
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
18898
|
}
|
|
18566
18899
|
|
|
18567
18900
|
// src/cli/ui/layout/LiveRows.tsx
|
|
18568
|
-
import { Box as
|
|
18569
|
-
import
|
|
18901
|
+
import { Box as Box42, Text as Text42, useStdout as useStdout10 } from "ink";
|
|
18902
|
+
import React48 from "react";
|
|
18570
18903
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
18571
18904
|
function ThinkingRow({ text }) {
|
|
18572
18905
|
const elapsed = useElapsedSeconds();
|
|
18573
|
-
return /* @__PURE__ */
|
|
18906
|
+
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
18907
|
}
|
|
18575
18908
|
function ModeStatusBar({
|
|
18576
18909
|
editMode,
|
|
@@ -18582,27 +18915,27 @@ function ModeStatusBar({
|
|
|
18582
18915
|
}) {
|
|
18583
18916
|
useSlowTick();
|
|
18584
18917
|
const running = jobs2?.runningCount() ?? 0;
|
|
18585
|
-
const jobsTag = running > 0 ? /* @__PURE__ */
|
|
18918
|
+
const jobsTag = running > 0 ? /* @__PURE__ */ React48.createElement(Text42, { color: TONE.warn, bold: true }, ` \xB7 \u23F5 ${running} job${running === 1 ? "" : "s"}`) : null;
|
|
18586
18919
|
if (planMode) {
|
|
18587
|
-
return /* @__PURE__ */
|
|
18920
|
+
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
18921
|
}
|
|
18589
18922
|
const label = editMode === "yolo" ? "YOLO" : editMode === "auto" ? "AUTO" : "REVIEW";
|
|
18590
18923
|
const pillColor = editMode === "yolo" ? TONE.err : editMode === "auto" ? TONE.accent : TONE.brand;
|
|
18591
18924
|
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__ */
|
|
18925
|
+
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
18926
|
}
|
|
18594
18927
|
function ModeBarFrame({ children }) {
|
|
18595
18928
|
const { stdout: stdout4 } = useStdout10();
|
|
18596
18929
|
const cols = stdout4?.columns ?? 80;
|
|
18597
18930
|
const ruleWidth = Math.max(20, cols - 2);
|
|
18598
|
-
return /* @__PURE__ */
|
|
18931
|
+
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
18932
|
}
|
|
18600
18933
|
function ModePill({
|
|
18601
18934
|
label,
|
|
18602
18935
|
color: color2,
|
|
18603
18936
|
flash
|
|
18604
18937
|
}) {
|
|
18605
|
-
return /* @__PURE__ */
|
|
18938
|
+
return /* @__PURE__ */ React48.createElement(Text42, { color: color2, bold: true, inverse: flash }, `[${label}]`);
|
|
18606
18939
|
}
|
|
18607
18940
|
function UndoBanner({
|
|
18608
18941
|
banner
|
|
@@ -18616,7 +18949,7 @@ function UndoBanner({
|
|
|
18616
18949
|
const urgent = remainingSec <= 1;
|
|
18617
18950
|
const pct2 = remainingMs / totalMs * 100;
|
|
18618
18951
|
const tone = urgent ? TONE.err : TONE.accent;
|
|
18619
|
-
return /* @__PURE__ */
|
|
18952
|
+
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
18953
|
}
|
|
18621
18954
|
function subagentPhaseLabel(phase, iter, elapsedMs) {
|
|
18622
18955
|
if (phase === "summarising") return "summarising findings\u2026";
|
|
@@ -18636,7 +18969,7 @@ function SubagentRow({
|
|
|
18636
18969
|
const seconds = (activity.elapsedMs / 1e3).toFixed(1);
|
|
18637
18970
|
const phase = subagentPhaseLabel(activity.phase, activity.iter, activity.elapsedMs);
|
|
18638
18971
|
const last = activity.lastInner;
|
|
18639
|
-
return /* @__PURE__ */
|
|
18972
|
+
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
18973
|
}
|
|
18641
18974
|
function OngoingToolRow({
|
|
18642
18975
|
tool: tool2,
|
|
@@ -18645,7 +18978,7 @@ function OngoingToolRow({
|
|
|
18645
18978
|
const tick = useTick();
|
|
18646
18979
|
const elapsed = useElapsedSeconds();
|
|
18647
18980
|
const summary = summarizeToolArgs(tool2.name, tool2.args);
|
|
18648
|
-
return /* @__PURE__ */
|
|
18981
|
+
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
18982
|
}
|
|
18650
18983
|
function renderProgressLine(p) {
|
|
18651
18984
|
const msg = p.message ? ` ${p.message}` : "";
|
|
@@ -18701,16 +19034,16 @@ function summarizeToolArgs(name, args) {
|
|
|
18701
19034
|
}
|
|
18702
19035
|
|
|
18703
19036
|
// src/cli/ui/layout/StatusRow.tsx
|
|
18704
|
-
import { Box as
|
|
18705
|
-
import
|
|
19037
|
+
import { Box as Box43, Text as Text44, useStdout as useStdout11 } from "ink";
|
|
19038
|
+
import React50 from "react";
|
|
18706
19039
|
|
|
18707
19040
|
// src/cli/ui/primitives/Countdown.tsx
|
|
18708
|
-
import { Text as
|
|
18709
|
-
import
|
|
19041
|
+
import { Text as Text43 } from "ink";
|
|
19042
|
+
import React49 from "react";
|
|
18710
19043
|
function Countdown({ endsAt, color: color2 = TONE.brand }) {
|
|
18711
19044
|
useSlowTick();
|
|
18712
19045
|
const remainingSec = Math.max(0, Math.ceil((endsAt - Date.now()) / 1e3));
|
|
18713
|
-
return /* @__PURE__ */
|
|
19046
|
+
return /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: color2 }, String(remainingSec));
|
|
18714
19047
|
}
|
|
18715
19048
|
|
|
18716
19049
|
// src/cli/ui/layout/StatusRow.tsx
|
|
@@ -18730,7 +19063,7 @@ function StatusRow() {
|
|
|
18730
19063
|
const turnCny = status3.cost * USD_TO_CNY;
|
|
18731
19064
|
const sessionCny = status3.sessionCost * USD_TO_CNY;
|
|
18732
19065
|
const hasTurn = status3.cost > 0;
|
|
18733
|
-
return /* @__PURE__ */
|
|
19066
|
+
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
19067
|
}
|
|
18735
19068
|
function ModePill2({
|
|
18736
19069
|
mode: mode2,
|
|
@@ -18739,18 +19072,18 @@ function ModePill2({
|
|
|
18739
19072
|
}) {
|
|
18740
19073
|
if (network === "online") {
|
|
18741
19074
|
const pill = modeGlyph(mode2);
|
|
18742
|
-
return /* @__PURE__ */
|
|
19075
|
+
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
19076
|
}
|
|
18744
19077
|
const dot2 = networkDot(network);
|
|
18745
19078
|
if (network === "slow") {
|
|
18746
19079
|
const tail = detail ? ` \xB7 ${detail}` : "";
|
|
18747
|
-
return /* @__PURE__ */
|
|
19080
|
+
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
19081
|
}
|
|
18749
19082
|
if (network === "disconnected") {
|
|
18750
19083
|
const tail = detail ? ` \xB7 ${detail}` : "";
|
|
18751
|
-
return /* @__PURE__ */
|
|
19084
|
+
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
19085
|
}
|
|
18753
|
-
return /* @__PURE__ */
|
|
19086
|
+
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
19087
|
}
|
|
18755
19088
|
function CountdownRow({
|
|
18756
19089
|
mode: mode2,
|
|
@@ -18758,14 +19091,14 @@ function CountdownRow({
|
|
|
18758
19091
|
}) {
|
|
18759
19092
|
const pill = modeGlyph(mode2);
|
|
18760
19093
|
const endsAt = Date.now() + secondsLeft * 1e3;
|
|
18761
|
-
return /* @__PURE__ */
|
|
19094
|
+
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
19095
|
}
|
|
18763
19096
|
function RecordingPill({ rec }) {
|
|
18764
19097
|
const sizeMb = (rec.sizeBytes / (1024 * 1024)).toFixed(1);
|
|
18765
|
-
return /* @__PURE__ */
|
|
19098
|
+
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
19099
|
}
|
|
18767
19100
|
function Sep() {
|
|
18768
|
-
return /* @__PURE__ */
|
|
19101
|
+
return /* @__PURE__ */ React50.createElement(Text44, { color: FG.meta }, " \xB7 ");
|
|
18769
19102
|
}
|
|
18770
19103
|
function modeGlyph(mode2) {
|
|
18771
19104
|
switch (mode2) {
|
|
@@ -18793,8 +19126,8 @@ function networkDot(state) {
|
|
|
18793
19126
|
}
|
|
18794
19127
|
|
|
18795
19128
|
// src/cli/ui/layout/ToastRail.tsx
|
|
18796
|
-
import { Box as
|
|
18797
|
-
import
|
|
19129
|
+
import { Box as Box44, Text as Text45, useStdout as useStdout12 } from "ink";
|
|
19130
|
+
import React51, { useEffect as useEffect3 } from "react";
|
|
18798
19131
|
var TONE_COLOR = {
|
|
18799
19132
|
ok: TONE.ok,
|
|
18800
19133
|
info: TONE.brand,
|
|
@@ -18832,12 +19165,12 @@ function ToastRail() {
|
|
|
18832
19165
|
}, [toasts, dispatch2]);
|
|
18833
19166
|
const visible = toasts.filter((t2) => now - t2.bornAt < t2.ttlMs);
|
|
18834
19167
|
if (visible.length === 0) return null;
|
|
18835
|
-
return /* @__PURE__ */
|
|
19168
|
+
return /* @__PURE__ */ React51.createElement(Box44, { flexDirection: "column" }, visible.map((t2) => {
|
|
18836
19169
|
const color2 = TONE_COLOR[t2.tone];
|
|
18837
19170
|
const glyph = TONE_GLYPH[t2.tone];
|
|
18838
19171
|
const body = bodyColor(t2, now);
|
|
18839
19172
|
const remainingSec = Math.max(0, Math.ceil((t2.ttlMs - (now - t2.bornAt)) / 1e3));
|
|
18840
|
-
return /* @__PURE__ */
|
|
19173
|
+
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
19174
|
}));
|
|
18842
19175
|
}
|
|
18843
19176
|
|
|
@@ -18900,6 +19233,32 @@ function formatDuration(ms) {
|
|
|
18900
19233
|
return mm === 0 ? `${h}h` : `${h}h${mm}m`;
|
|
18901
19234
|
}
|
|
18902
19235
|
|
|
19236
|
+
// src/cli/ui/mcp-append.ts
|
|
19237
|
+
function applyMcpAppend(loop2, target, addedTools) {
|
|
19238
|
+
const accepted = [];
|
|
19239
|
+
for (const mcpTool of addedTools) {
|
|
19240
|
+
if (!mcpTool.name) continue;
|
|
19241
|
+
const registeredName = registerSingleMcpTool(mcpTool, target.bridgeEnv);
|
|
19242
|
+
if (!registeredName) continue;
|
|
19243
|
+
const spec = {
|
|
19244
|
+
type: "function",
|
|
19245
|
+
function: {
|
|
19246
|
+
name: registeredName,
|
|
19247
|
+
description: mcpTool.description ?? "",
|
|
19248
|
+
parameters: mcpTool.inputSchema
|
|
19249
|
+
}
|
|
19250
|
+
};
|
|
19251
|
+
loop2.prefix.addTool(spec);
|
|
19252
|
+
accepted.push(mcpTool);
|
|
19253
|
+
}
|
|
19254
|
+
if (accepted.length === 0) return;
|
|
19255
|
+
if (target.report.tools.supported) {
|
|
19256
|
+
const merged = [...target.report.tools.items, ...accepted];
|
|
19257
|
+
target.report.tools.items = merged;
|
|
19258
|
+
target.toolCount = merged.length;
|
|
19259
|
+
}
|
|
19260
|
+
}
|
|
19261
|
+
|
|
18903
19262
|
// src/cli/ui/mcp-browse.ts
|
|
18904
19263
|
function formatResourceList(servers) {
|
|
18905
19264
|
const lines = [];
|
|
@@ -19028,14 +19387,7 @@ async function handleMcpBrowseSlash(kind, arg, servers, log) {
|
|
|
19028
19387
|
);
|
|
19029
19388
|
return;
|
|
19030
19389
|
}
|
|
19031
|
-
const client2 = server2.client;
|
|
19032
|
-
if (!client2) {
|
|
19033
|
-
log.pushWarning(
|
|
19034
|
-
`server [${server2.label}] is not connected (display-only)`,
|
|
19035
|
-
"Resource read requires a live MCP client."
|
|
19036
|
-
);
|
|
19037
|
-
return;
|
|
19038
|
-
}
|
|
19390
|
+
const client2 = server2.host.client;
|
|
19039
19391
|
try {
|
|
19040
19392
|
const result = await client2.readResource(arg);
|
|
19041
19393
|
log.pushInfo(formatResourceContents(arg, result));
|
|
@@ -19052,14 +19404,7 @@ async function handleMcpBrowseSlash(kind, arg, servers, log) {
|
|
|
19052
19404
|
);
|
|
19053
19405
|
return;
|
|
19054
19406
|
}
|
|
19055
|
-
const client = server.client;
|
|
19056
|
-
if (!client) {
|
|
19057
|
-
log.pushWarning(
|
|
19058
|
-
`server [${server.label}] is not connected (display-only)`,
|
|
19059
|
-
"Prompt fetch requires a live MCP client."
|
|
19060
|
-
);
|
|
19061
|
-
return;
|
|
19062
|
-
}
|
|
19407
|
+
const client = server.host.client;
|
|
19063
19408
|
try {
|
|
19064
19409
|
const result = await client.getPrompt(arg);
|
|
19065
19410
|
log.pushInfo(formatPromptMessages(arg, result));
|
|
@@ -20519,15 +20864,26 @@ var handlers6 = {
|
|
|
20519
20864
|
};
|
|
20520
20865
|
|
|
20521
20866
|
// src/cli/ui/slash/handlers/mcp.ts
|
|
20522
|
-
var mcp = (
|
|
20867
|
+
var mcp = (args, loop2, ctx) => {
|
|
20523
20868
|
const servers = ctx.mcpServers ?? [];
|
|
20524
20869
|
const specs = ctx.mcpSpecs ?? [];
|
|
20525
20870
|
const toolSpecs = loop2.prefix.toolSpecs ?? [];
|
|
20871
|
+
const sub = args[0];
|
|
20872
|
+
if (sub === "disable" || sub === "enable") {
|
|
20873
|
+
return toggleDisabled(sub, args[1], { servers, specs });
|
|
20874
|
+
}
|
|
20875
|
+
if (sub === "reconnect") {
|
|
20876
|
+
return triggerReconnect(args[1], servers, ctx.postInfo, loop2);
|
|
20877
|
+
}
|
|
20878
|
+
const wantsTextDump = sub === "text";
|
|
20526
20879
|
if (servers.length === 0 && specs.length === 0 && toolSpecs.length === 0) {
|
|
20527
20880
|
return {
|
|
20528
20881
|
info: 'no MCP servers attached. Run `reasonix setup` to pick some, or launch with --mcp "<spec>". `reasonix mcp list` shows the catalog.'
|
|
20529
20882
|
};
|
|
20530
20883
|
}
|
|
20884
|
+
if (!wantsTextDump && servers.length > 0) {
|
|
20885
|
+
return { openMcpBrowser: true };
|
|
20886
|
+
}
|
|
20531
20887
|
if (servers.length > 0) {
|
|
20532
20888
|
const lines2 = [];
|
|
20533
20889
|
let anyResources = false;
|
|
@@ -20536,7 +20892,7 @@ var mcp = (_args, loop2, ctx) => {
|
|
|
20536
20892
|
const { report } = s;
|
|
20537
20893
|
const serverName = report.serverInfo.name || "(unknown)";
|
|
20538
20894
|
const serverVer = report.serverInfo.version ? ` v${report.serverInfo.version}` : "";
|
|
20539
|
-
const health =
|
|
20895
|
+
const health = healthBadge2(report.elapsedMs);
|
|
20540
20896
|
lines2.push(`${health} [${s.label}] ${serverName}${serverVer} \u2014 ${s.spec}`);
|
|
20541
20897
|
lines2.push(` tools ${s.toolCount}`);
|
|
20542
20898
|
appendSection(lines2, "resources", report.resources);
|
|
@@ -20574,11 +20930,55 @@ var mcp = (_args, loop2, ctx) => {
|
|
|
20574
20930
|
lines.push("To change this set, exit and run `reasonix setup`.");
|
|
20575
20931
|
return { info: lines.join("\n") };
|
|
20576
20932
|
};
|
|
20577
|
-
function
|
|
20933
|
+
function healthBadge2(elapsedMs) {
|
|
20578
20934
|
if (elapsedMs < 500) return `\u25CF healthy \xB7 ${elapsedMs}ms`;
|
|
20579
20935
|
if (elapsedMs < 3e3) return `\u25CC slow \xB7 ${elapsedMs}ms`;
|
|
20580
20936
|
return `\u2717 very slow \xB7 ${elapsedMs}ms`;
|
|
20581
20937
|
}
|
|
20938
|
+
function toggleDisabled(action, rawName, ctx) {
|
|
20939
|
+
const name = rawName?.trim();
|
|
20940
|
+
if (!name) {
|
|
20941
|
+
return {
|
|
20942
|
+
info: `usage: /mcp ${action} <name> \xB7 pick a name shown in /mcp (anonymous servers can't be named-toggled).`
|
|
20943
|
+
};
|
|
20944
|
+
}
|
|
20945
|
+
const known = /* @__PURE__ */ new Set([
|
|
20946
|
+
...ctx.servers.map((s) => s.label),
|
|
20947
|
+
...ctx.specs.map((spec) => parseLabelFromSpec(spec)).filter((n) => n !== null)
|
|
20948
|
+
]);
|
|
20949
|
+
if (!known.has(name)) {
|
|
20950
|
+
const list2 = [...known].sort().join(", ") || "(none)";
|
|
20951
|
+
return { info: `unknown MCP server "${name}". Known: ${list2}.` };
|
|
20952
|
+
}
|
|
20953
|
+
return { info: toggleMcpDisabled(action, name) };
|
|
20954
|
+
}
|
|
20955
|
+
function parseLabelFromSpec(spec) {
|
|
20956
|
+
const match = spec.match(/^([a-zA-Z_][a-zA-Z0-9_-]*)=/);
|
|
20957
|
+
return match ? match[1] ?? null : null;
|
|
20958
|
+
}
|
|
20959
|
+
function triggerReconnect(rawName, servers, postInfo, loop2) {
|
|
20960
|
+
const name = rawName?.trim();
|
|
20961
|
+
if (!name) {
|
|
20962
|
+
return {
|
|
20963
|
+
info: "usage: /mcp reconnect <name> \xB7 pick a name shown in /mcp."
|
|
20964
|
+
};
|
|
20965
|
+
}
|
|
20966
|
+
const target = servers.find((s) => s.label === name);
|
|
20967
|
+
if (!target) {
|
|
20968
|
+
const list2 = servers.map((s) => s.label).sort().join(", ");
|
|
20969
|
+
return { info: `unknown MCP server "${name}". Known: ${list2 || "(none)"}.` };
|
|
20970
|
+
}
|
|
20971
|
+
if (!postInfo) {
|
|
20972
|
+
return { info: "/mcp reconnect requires the interactive TUI (postInfo not wired)." };
|
|
20973
|
+
}
|
|
20974
|
+
return {
|
|
20975
|
+
info: kickOffMcpReconnect(
|
|
20976
|
+
target,
|
|
20977
|
+
postInfo,
|
|
20978
|
+
(t2, addedTools) => applyMcpAppend(loop2, t2, addedTools)
|
|
20979
|
+
)
|
|
20980
|
+
};
|
|
20981
|
+
}
|
|
20582
20982
|
var handlers7 = { mcp };
|
|
20583
20983
|
|
|
20584
20984
|
// src/cli/ui/slash/handlers/memory.ts
|
|
@@ -20919,17 +21319,17 @@ var handlers9 = {
|
|
|
20919
21319
|
};
|
|
20920
21320
|
|
|
20921
21321
|
// src/cli/ui/ctx-breakdown.tsx
|
|
20922
|
-
import { Box as
|
|
20923
|
-
import
|
|
21322
|
+
import { Box as Box45, Text as Text47 } from "ink";
|
|
21323
|
+
import React53 from "react";
|
|
20924
21324
|
|
|
20925
21325
|
// src/cli/ui/primitives.tsx
|
|
20926
|
-
import { Text as
|
|
20927
|
-
import
|
|
21326
|
+
import { Text as Text46, useStdout as useStdout13 } from "ink";
|
|
21327
|
+
import React52 from "react";
|
|
20928
21328
|
function ChromeRule() {
|
|
20929
21329
|
const { stdout: stdout4 } = useStdout13();
|
|
20930
21330
|
const cols = stdout4?.columns ?? 80;
|
|
20931
21331
|
const w = Math.max(20, cols - 2);
|
|
20932
|
-
return /* @__PURE__ */
|
|
21332
|
+
return /* @__PURE__ */ React52.createElement(Text46, { dimColor: true }, "\u2500".repeat(w));
|
|
20933
21333
|
}
|
|
20934
21334
|
function Bar({
|
|
20935
21335
|
ratio,
|
|
@@ -20938,7 +21338,7 @@ function Bar({
|
|
|
20938
21338
|
dim
|
|
20939
21339
|
}) {
|
|
20940
21340
|
const filled = Math.max(0, Math.min(cells, Math.round(ratio * cells)));
|
|
20941
|
-
return /* @__PURE__ */
|
|
21341
|
+
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
21342
|
}
|
|
20943
21343
|
|
|
20944
21344
|
// src/cli/ui/ctx-breakdown.tsx
|
|
@@ -21957,7 +22357,7 @@ function hydrateCardsFromMessages(messages) {
|
|
|
21957
22357
|
}
|
|
21958
22358
|
|
|
21959
22359
|
// src/cli/ui/useCompletionPickers.ts
|
|
21960
|
-
import { useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo5, useRef as useRef3, useState as
|
|
22360
|
+
import { useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo5, useRef as useRef3, useState as useState11 } from "react";
|
|
21961
22361
|
function useCompletionPickers({
|
|
21962
22362
|
input,
|
|
21963
22363
|
setInput,
|
|
@@ -21966,7 +22366,7 @@ function useCompletionPickers({
|
|
|
21966
22366
|
models: models2,
|
|
21967
22367
|
mcpServers
|
|
21968
22368
|
}) {
|
|
21969
|
-
const [slashSelected, setSlashSelected] =
|
|
22369
|
+
const [slashSelected, setSlashSelected] = useState11(0);
|
|
21970
22370
|
const slashMatches = useMemo5(() => {
|
|
21971
22371
|
if (!input.startsWith("/") || input.includes(" ")) return null;
|
|
21972
22372
|
return suggestSlashCommands(input.slice(1), !!codeMode);
|
|
@@ -21978,8 +22378,8 @@ function useCompletionPickers({
|
|
|
21978
22378
|
return prev;
|
|
21979
22379
|
});
|
|
21980
22380
|
}, [slashMatches]);
|
|
21981
|
-
const [atSelected, setAtSelected] =
|
|
21982
|
-
const [atFiles, setAtFiles] =
|
|
22381
|
+
const [atSelected, setAtSelected] = useState11(0);
|
|
22382
|
+
const [atFiles, setAtFiles] = useState11([]);
|
|
21983
22383
|
useEffect4(() => {
|
|
21984
22384
|
if (!codeMode) {
|
|
21985
22385
|
setAtFiles([]);
|
|
@@ -22030,7 +22430,7 @@ function useCompletionPickers({
|
|
|
22030
22430
|
},
|
|
22031
22431
|
[atPicker, input, setInput]
|
|
22032
22432
|
);
|
|
22033
|
-
const [slashArgSelected, setSlashArgSelected] =
|
|
22433
|
+
const [slashArgSelected, setSlashArgSelected] = useState11(0);
|
|
22034
22434
|
const slashArgContext = useMemo5(() => {
|
|
22035
22435
|
if (!input.startsWith("/")) return null;
|
|
22036
22436
|
if (slashMatches !== null) return null;
|
|
@@ -22110,12 +22510,12 @@ function useCompletionPickers({
|
|
|
22110
22510
|
}
|
|
22111
22511
|
|
|
22112
22512
|
// src/cli/ui/useEditHistory.ts
|
|
22113
|
-
import { useCallback as useCallback3, useRef as useRef4, useState as
|
|
22513
|
+
import { useCallback as useCallback3, useRef as useRef4, useState as useState12 } from "react";
|
|
22114
22514
|
function useEditHistory(codeMode) {
|
|
22115
22515
|
const editHistory = useRef4([]);
|
|
22116
22516
|
const nextHistoryId = useRef4(1);
|
|
22117
22517
|
const currentTurnEntry = useRef4(null);
|
|
22118
|
-
const [undoBanner, setUndoBanner] =
|
|
22518
|
+
const [undoBanner, setUndoBanner] = useState12(null);
|
|
22119
22519
|
const undoTimeoutRef = useRef4(null);
|
|
22120
22520
|
const recordEdit = useCallback3(
|
|
22121
22521
|
(source, blocks, results, snaps) => {
|
|
@@ -22320,11 +22720,11 @@ function useEditHistory(codeMode) {
|
|
|
22320
22720
|
}
|
|
22321
22721
|
|
|
22322
22722
|
// src/cli/ui/useSessionInfo.ts
|
|
22323
|
-
import { useCallback as useCallback4, useEffect as useEffect5, useState as
|
|
22723
|
+
import { useCallback as useCallback4, useEffect as useEffect5, useState as useState13 } from "react";
|
|
22324
22724
|
function useSessionInfo(loop2) {
|
|
22325
|
-
const [balance, setBalance] =
|
|
22326
|
-
const [models2, setModels] =
|
|
22327
|
-
const [latestVersion, setLatestVersion] =
|
|
22725
|
+
const [balance, setBalance] = useState13(null);
|
|
22726
|
+
const [models2, setModels] = useState13(null);
|
|
22727
|
+
const [latestVersion, setLatestVersion] = useState13(null);
|
|
22328
22728
|
useEffect5(() => {
|
|
22329
22729
|
let cancelled = false;
|
|
22330
22730
|
void (async () => {
|
|
@@ -22393,7 +22793,7 @@ function useSessionInfo(loop2) {
|
|
|
22393
22793
|
}
|
|
22394
22794
|
|
|
22395
22795
|
// src/cli/ui/useSubagent.ts
|
|
22396
|
-
import { useEffect as useEffect6, useRef as useRef5, useState as
|
|
22796
|
+
import { useEffect as useEffect6, useRef as useRef5, useState as useState14 } from "react";
|
|
22397
22797
|
function summariseInner(ev) {
|
|
22398
22798
|
if (ev.role === "tool_start") {
|
|
22399
22799
|
return {
|
|
@@ -22420,7 +22820,7 @@ function summariseInner(ev) {
|
|
|
22420
22820
|
return null;
|
|
22421
22821
|
}
|
|
22422
22822
|
function useSubagent({ session, log }) {
|
|
22423
|
-
const [activity, setActivity] =
|
|
22823
|
+
const [activity, setActivity] = useState14(null);
|
|
22424
22824
|
const sinkRef = useRef5({ current: null });
|
|
22425
22825
|
useEffect6(() => {
|
|
22426
22826
|
sinkRef.current.current = (ev) => {
|
|
@@ -22503,13 +22903,13 @@ var PLAIN_UI = process.env.REASONIX_UI === "plain";
|
|
|
22503
22903
|
function LoopStatusRow({
|
|
22504
22904
|
loop: loop2
|
|
22505
22905
|
}) {
|
|
22506
|
-
const [, setTick] =
|
|
22507
|
-
|
|
22906
|
+
const [, setTick] = React54.useState(0);
|
|
22907
|
+
React54.useEffect(() => {
|
|
22508
22908
|
const id = setInterval(() => setTick((t2) => t2 + 1), 1e3);
|
|
22509
22909
|
return () => clearInterval(id);
|
|
22510
22910
|
}, []);
|
|
22511
22911
|
const nextFireMs = Math.max(0, loop2.nextFireAt - Date.now());
|
|
22512
|
-
return /* @__PURE__ */
|
|
22912
|
+
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
22913
|
}
|
|
22514
22914
|
function App(props) {
|
|
22515
22915
|
const session = useAgentSession({
|
|
@@ -22517,11 +22917,11 @@ function App(props) {
|
|
|
22517
22917
|
model: props.model,
|
|
22518
22918
|
workspace: props.codeMode?.rootDir ?? process.cwd()
|
|
22519
22919
|
});
|
|
22520
|
-
const initialCards =
|
|
22920
|
+
const initialCards = React54.useMemo(
|
|
22521
22921
|
() => props.session ? hydrateCardsFromMessages(loadSessionMessages(props.session)) : [],
|
|
22522
22922
|
[props.session]
|
|
22523
22923
|
);
|
|
22524
|
-
return /* @__PURE__ */
|
|
22924
|
+
return /* @__PURE__ */ React54.createElement(AgentStoreProvider, { session, initialCards }, /* @__PURE__ */ React54.createElement(AppInner, { ...props }));
|
|
22525
22925
|
}
|
|
22526
22926
|
function AppInner({
|
|
22527
22927
|
model: model2,
|
|
@@ -22554,14 +22954,14 @@ function AppInner({
|
|
|
22554
22954
|
}
|
|
22555
22955
|
return null;
|
|
22556
22956
|
});
|
|
22557
|
-
const [input, setInput] =
|
|
22558
|
-
const [busy, setBusy] =
|
|
22957
|
+
const [input, setInput] = useState15("");
|
|
22958
|
+
const [busy, setBusy] = useState15(false);
|
|
22559
22959
|
const abortedThisTurn = useRef6(false);
|
|
22560
22960
|
useEffect7(() => {
|
|
22561
22961
|
busyRef.current = busy;
|
|
22562
22962
|
}, [busy]);
|
|
22563
|
-
const [ongoingTool, setOngoingTool] =
|
|
22564
|
-
const [toolProgress, setToolProgress] =
|
|
22963
|
+
const [ongoingTool, setOngoingTool] = useState15(null);
|
|
22964
|
+
const [toolProgress, setToolProgress] = useState15(null);
|
|
22565
22965
|
const { stdout: stdout4 } = useStdout14();
|
|
22566
22966
|
useEffect7(() => {
|
|
22567
22967
|
if (!stdout4 || !stdout4.isTTY) return;
|
|
@@ -22572,7 +22972,7 @@ function AppInner({
|
|
|
22572
22972
|
stdout4.write("\x1B[>4m");
|
|
22573
22973
|
};
|
|
22574
22974
|
}, [stdout4]);
|
|
22575
|
-
const [isResizing, setIsResizing] =
|
|
22975
|
+
const [isResizing, setIsResizing] = useState15(false);
|
|
22576
22976
|
useEffect7(() => {
|
|
22577
22977
|
if (!stdout4 || !stdout4.isTTY) return;
|
|
22578
22978
|
let timer = null;
|
|
@@ -22594,11 +22994,11 @@ function AppInner({
|
|
|
22594
22994
|
session,
|
|
22595
22995
|
log
|
|
22596
22996
|
});
|
|
22597
|
-
const [statusLine, setStatusLine] =
|
|
22598
|
-
const [currentRootDir, setCurrentRootDir] =
|
|
22997
|
+
const [statusLine, setStatusLine] = useState15(null);
|
|
22998
|
+
const [currentRootDir, setCurrentRootDir] = useState15(
|
|
22599
22999
|
() => codeMode?.rootDir ?? process.cwd()
|
|
22600
23000
|
);
|
|
22601
|
-
const [hookList, setHookList] =
|
|
23001
|
+
const [hookList, setHookList] = useState15(
|
|
22602
23002
|
() => loadHooks({ projectRoot: codeMode?.rootDir })
|
|
22603
23003
|
);
|
|
22604
23004
|
const {
|
|
@@ -22613,13 +23013,13 @@ function AppInner({
|
|
|
22613
23013
|
touchedPaths
|
|
22614
23014
|
} = useEditHistory(codeMode);
|
|
22615
23015
|
const pendingEdits = useRef6([]);
|
|
22616
|
-
const [pendingCount, setPendingCount] =
|
|
23016
|
+
const [pendingCount, setPendingCount] = useState15(0);
|
|
22617
23017
|
const syncPendingCount = useCallback5(() => {
|
|
22618
23018
|
setPendingCount(pendingEdits.current.length);
|
|
22619
23019
|
setPendingTick((t2) => t2 + 1);
|
|
22620
23020
|
}, []);
|
|
22621
|
-
const [editMode, setEditMode] =
|
|
22622
|
-
const [preset2, setPreset] =
|
|
23021
|
+
const [editMode, setEditMode] = useState15(() => codeMode ? loadEditMode() : "review");
|
|
23022
|
+
const [preset2, setPreset] = useState15(() => {
|
|
22623
23023
|
if (model2 === "deepseek-v4-pro") return "pro";
|
|
22624
23024
|
return "auto";
|
|
22625
23025
|
});
|
|
@@ -22631,12 +23031,12 @@ function AppInner({
|
|
|
22631
23031
|
const planModeRef = useRef6(false);
|
|
22632
23032
|
const currentRootDirRef = useRef6("");
|
|
22633
23033
|
const latestVersionRef = useRef6(null);
|
|
22634
|
-
const [pendingEditReview, setPendingEditReview] =
|
|
22635
|
-
const [walkthroughActive, setWalkthroughActive] =
|
|
22636
|
-
const [pendingTick, setPendingTick] =
|
|
23034
|
+
const [pendingEditReview, setPendingEditReview] = useState15(null);
|
|
23035
|
+
const [walkthroughActive, setWalkthroughActive] = useState15(false);
|
|
23036
|
+
const [pendingTick, setPendingTick] = useState15(0);
|
|
22637
23037
|
const editReviewResolveRef = useRef6(null);
|
|
22638
23038
|
const turnEditPolicyRef = useRef6("ask");
|
|
22639
|
-
const [modeFlash, setModeFlash] =
|
|
23039
|
+
const [modeFlash, setModeFlash] = useState15(false);
|
|
22640
23040
|
const modeFlashTimeoutRef = useRef6(null);
|
|
22641
23041
|
const prevEditModeRef = useRef6(editMode);
|
|
22642
23042
|
useEffect7(() => {
|
|
@@ -22649,26 +23049,27 @@ function AppInner({
|
|
|
22649
23049
|
modeFlashTimeoutRef.current = null;
|
|
22650
23050
|
}, 1200);
|
|
22651
23051
|
}, [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 [
|
|
23052
|
+
const [pendingShell, setPendingShell] = useState15(null);
|
|
23053
|
+
const [pendingPlan, setPendingPlan] = useState15(null);
|
|
23054
|
+
const [pendingReviseEditor, setPendingReviseEditor] = useState15(null);
|
|
23055
|
+
const [pendingSessionsPicker, setPendingSessionsPicker] = useState15(false);
|
|
23056
|
+
const [sessionsPickerList, setSessionsPickerList] = useState15([]);
|
|
23057
|
+
const [pendingMcpBrowser, setPendingMcpBrowser] = useState15(false);
|
|
23058
|
+
const [stagedInput, setStagedInput] = useState15(null);
|
|
23059
|
+
const [pendingCheckpoint, setPendingCheckpoint] = useState15(null);
|
|
23060
|
+
const [stagedCheckpointRevise, setStagedCheckpointRevise] = useState15(null);
|
|
23061
|
+
const [pendingRevision, setPendingRevision] = useState15(null);
|
|
23062
|
+
const [pendingChoice, setPendingChoice] = useState15(null);
|
|
23063
|
+
const [stagedChoiceCustom, setStagedChoiceCustom] = useState15(null);
|
|
23064
|
+
const [planMode, setPlanMode] = useState15(false);
|
|
23065
|
+
const [proArmed, setProArmed] = useState15(false);
|
|
23066
|
+
const [turnOnPro, setTurnOnPro] = useState15(false);
|
|
23067
|
+
const [queuedSubmit, setQueuedSubmit] = useState15(null);
|
|
22667
23068
|
const promptHistory = useRef6([]);
|
|
22668
23069
|
const historyCursor = useRef6(-1);
|
|
22669
23070
|
const assistantIterCounter = useRef6(0);
|
|
22670
23071
|
const atUrlCache = useRef6(/* @__PURE__ */ new Map());
|
|
22671
|
-
const [activeLoop, setActiveLoop] =
|
|
23072
|
+
const [activeLoop, setActiveLoop] = useState15(null);
|
|
22672
23073
|
const loopTimerRef = useRef6(null);
|
|
22673
23074
|
const handleSubmitRef = useRef6(null);
|
|
22674
23075
|
const busyRef = useRef6(false);
|
|
@@ -22698,7 +23099,7 @@ function AppInner({
|
|
|
22698
23099
|
if (planSummaryRef.current) extras.summary = planSummaryRef.current;
|
|
22699
23100
|
savePlanState(session, steps, completedStepIdsRef.current, extras);
|
|
22700
23101
|
}, [session]);
|
|
22701
|
-
const [summary, setSummary] =
|
|
23102
|
+
const [summary, setSummary] = useState15({
|
|
22702
23103
|
turns: 0,
|
|
22703
23104
|
totalCostUsd: 0,
|
|
22704
23105
|
totalInputCostUsd: 0,
|
|
@@ -23053,7 +23454,7 @@ function AppInner({
|
|
|
23053
23454
|
);
|
|
23054
23455
|
return;
|
|
23055
23456
|
}
|
|
23056
|
-
if (codeMode && key.shift && key.tab && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !stagedInput && !pendingEditReview && !walkthroughActive && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision) {
|
|
23457
|
+
if (codeMode && key.shift && key.tab && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingMcpBrowser && !stagedInput && !pendingEditReview && !walkthroughActive && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision) {
|
|
23057
23458
|
const cur = editModeRef.current;
|
|
23058
23459
|
const next = cur === "review" ? "auto" : cur === "auto" ? "yolo" : "review";
|
|
23059
23460
|
setEditMode(next);
|
|
@@ -23061,7 +23462,7 @@ function AppInner({
|
|
|
23061
23462
|
log.pushInfo(message);
|
|
23062
23463
|
return;
|
|
23063
23464
|
}
|
|
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
|
|
23465
|
+
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
23466
|
// history entry — the keybind is useful long after the 5-second
|
|
23066
23467
|
// banner expires, which users rightly want.
|
|
23067
23468
|
(undoBanner || hasUndoable())) {
|
|
@@ -23515,7 +23916,7 @@ function AppInner({
|
|
|
23515
23916
|
const getDashboardUrl = useCallback5(() => {
|
|
23516
23917
|
return dashboardRef.current?.url ?? null;
|
|
23517
23918
|
}, []);
|
|
23518
|
-
const [dashboardUrl, setDashboardUrlState] =
|
|
23919
|
+
const [dashboardUrl, setDashboardUrlState] = useState15(null);
|
|
23519
23920
|
useEffect7(() => {
|
|
23520
23921
|
if (noDashboard) return;
|
|
23521
23922
|
if (dashboardRef.current) return;
|
|
@@ -23717,6 +24118,11 @@ function AppInner({
|
|
|
23717
24118
|
promptHistory.current.push(text);
|
|
23718
24119
|
return;
|
|
23719
24120
|
}
|
|
24121
|
+
if (result.openMcpBrowser) {
|
|
24122
|
+
setPendingMcpBrowser(true);
|
|
24123
|
+
promptHistory.current.push(text);
|
|
24124
|
+
return;
|
|
24125
|
+
}
|
|
23720
24126
|
const outcome = applySlashResult(result, {
|
|
23721
24127
|
log,
|
|
23722
24128
|
stdoutWrite: (chunk) => stdout4?.write(chunk),
|
|
@@ -24417,10 +24823,10 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24417
24823
|
async (choice) => handleReviseConfirmRef.current(choice),
|
|
24418
24824
|
[]
|
|
24419
24825
|
);
|
|
24420
|
-
return /* @__PURE__ */
|
|
24826
|
+
return /* @__PURE__ */ React54.createElement(React54.Fragment, null, /* @__PURE__ */ React54.createElement(
|
|
24421
24827
|
TickerProvider,
|
|
24422
24828
|
{
|
|
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
|
|
24829
|
+
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
24830
|
// 8Hz/1Hz heartbeats. The cursor blink, gradient pulse, and
|
|
24425
24831
|
// spinner glyphs are pure cosmetics — running them at idle
|
|
24426
24832
|
// forces Ink to repaint the screen ~8x/sec, which erases any
|
|
@@ -24430,28 +24836,28 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24430
24836
|
// changes (incoming stream, key press, modal popup).
|
|
24431
24837
|
!busy && !isStreaming
|
|
24432
24838
|
},
|
|
24433
|
-
/* @__PURE__ */
|
|
24839
|
+
/* @__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
24840
|
PlanRefineInput,
|
|
24435
24841
|
{
|
|
24436
24842
|
mode: stagedInput.mode,
|
|
24437
24843
|
onSubmit: handleStagedInputSubmit,
|
|
24438
24844
|
onCancel: handleStagedInputCancel
|
|
24439
24845
|
}
|
|
24440
|
-
) : stagedCheckpointRevise ? /* @__PURE__ */
|
|
24846
|
+
) : stagedCheckpointRevise ? /* @__PURE__ */ React54.createElement(
|
|
24441
24847
|
PlanRefineInput,
|
|
24442
24848
|
{
|
|
24443
24849
|
mode: "checkpoint-revise",
|
|
24444
24850
|
onSubmit: handleCheckpointReviseSubmit,
|
|
24445
24851
|
onCancel: handleCheckpointReviseCancel
|
|
24446
24852
|
}
|
|
24447
|
-
) : stagedChoiceCustom ? /* @__PURE__ */
|
|
24853
|
+
) : stagedChoiceCustom ? /* @__PURE__ */ React54.createElement(
|
|
24448
24854
|
PlanRefineInput,
|
|
24449
24855
|
{
|
|
24450
24856
|
mode: "choice-custom",
|
|
24451
24857
|
onSubmit: handleChoiceCustomSubmit,
|
|
24452
24858
|
onCancel: handleChoiceCustomCancel
|
|
24453
24859
|
}
|
|
24454
|
-
) : pendingChoice ? /* @__PURE__ */
|
|
24860
|
+
) : pendingChoice ? /* @__PURE__ */ React54.createElement(
|
|
24455
24861
|
ChoiceConfirm,
|
|
24456
24862
|
{
|
|
24457
24863
|
question: pendingChoice.question,
|
|
@@ -24459,7 +24865,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24459
24865
|
allowCustom: pendingChoice.allowCustom,
|
|
24460
24866
|
onChoose: stableHandleChoiceConfirm
|
|
24461
24867
|
}
|
|
24462
|
-
) : pendingRevision ? /* @__PURE__ */
|
|
24868
|
+
) : pendingRevision ? /* @__PURE__ */ React54.createElement(
|
|
24463
24869
|
PlanReviseConfirm,
|
|
24464
24870
|
{
|
|
24465
24871
|
reason: pendingRevision.reason,
|
|
@@ -24470,7 +24876,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24470
24876
|
summary: pendingRevision.summary,
|
|
24471
24877
|
onChoose: stableHandleReviseConfirm
|
|
24472
24878
|
}
|
|
24473
|
-
) : pendingCheckpoint ? /* @__PURE__ */
|
|
24879
|
+
) : pendingCheckpoint ? /* @__PURE__ */ React54.createElement(
|
|
24474
24880
|
PlanCheckpointConfirm,
|
|
24475
24881
|
{
|
|
24476
24882
|
stepId: pendingCheckpoint.stepId,
|
|
@@ -24481,7 +24887,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24481
24887
|
completedStepIds: completedStepIdsRef.current,
|
|
24482
24888
|
onChoose: stableHandleCheckpointConfirm
|
|
24483
24889
|
}
|
|
24484
|
-
) : pendingSessionsPicker ? /* @__PURE__ */
|
|
24890
|
+
) : pendingSessionsPicker ? /* @__PURE__ */ React54.createElement(
|
|
24485
24891
|
SessionPicker,
|
|
24486
24892
|
{
|
|
24487
24893
|
sessions: sessionsPickerList,
|
|
@@ -24524,7 +24930,16 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24524
24930
|
}
|
|
24525
24931
|
}
|
|
24526
24932
|
}
|
|
24527
|
-
) :
|
|
24933
|
+
) : pendingMcpBrowser ? /* @__PURE__ */ React54.createElement(
|
|
24934
|
+
McpBrowser,
|
|
24935
|
+
{
|
|
24936
|
+
servers: mcpServers ?? [],
|
|
24937
|
+
configPath: defaultConfigPath(),
|
|
24938
|
+
onClose: () => setPendingMcpBrowser(false),
|
|
24939
|
+
postInfo: (text) => log.pushInfo(text),
|
|
24940
|
+
applyAppend: (target, addedTools) => applyMcpAppend(loop2, target, addedTools)
|
|
24941
|
+
}
|
|
24942
|
+
) : pendingPlan ? /* @__PURE__ */ React54.createElement(
|
|
24528
24943
|
PlanConfirm,
|
|
24529
24944
|
{
|
|
24530
24945
|
plan: pendingPlan,
|
|
@@ -24533,7 +24948,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24533
24948
|
onChoose: stableHandlePlanConfirm,
|
|
24534
24949
|
projectRoot: currentRootDir
|
|
24535
24950
|
}
|
|
24536
|
-
) : pendingReviseEditor ? /* @__PURE__ */
|
|
24951
|
+
) : pendingReviseEditor ? /* @__PURE__ */ React54.createElement(
|
|
24537
24952
|
PlanReviseEditor,
|
|
24538
24953
|
{
|
|
24539
24954
|
steps: planStepsRef.current ?? [],
|
|
@@ -24552,7 +24967,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24552
24967
|
setPendingPlan(planText);
|
|
24553
24968
|
}
|
|
24554
24969
|
}
|
|
24555
|
-
) : pendingShell ? /* @__PURE__ */
|
|
24970
|
+
) : pendingShell ? /* @__PURE__ */ React54.createElement(
|
|
24556
24971
|
ShellConfirm,
|
|
24557
24972
|
{
|
|
24558
24973
|
command: pendingShell.command,
|
|
@@ -24560,7 +24975,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24560
24975
|
kind: pendingShell.kind,
|
|
24561
24976
|
onChoose: handleShellConfirm
|
|
24562
24977
|
}
|
|
24563
|
-
) : pendingEditReview ? /* @__PURE__ */
|
|
24978
|
+
) : pendingEditReview ? /* @__PURE__ */ React54.createElement(
|
|
24564
24979
|
EditConfirm,
|
|
24565
24980
|
{
|
|
24566
24981
|
block: pendingEditReview,
|
|
@@ -24572,14 +24987,14 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24572
24987
|
}
|
|
24573
24988
|
}
|
|
24574
24989
|
}
|
|
24575
|
-
) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */
|
|
24990
|
+
) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */ React54.createElement(
|
|
24576
24991
|
EditConfirm,
|
|
24577
24992
|
{
|
|
24578
24993
|
key: `walk-${pendingTick}`,
|
|
24579
24994
|
block: pendingEdits.current[0],
|
|
24580
24995
|
onChoose: handleWalkChoice
|
|
24581
24996
|
}
|
|
24582
|
-
) : /* @__PURE__ */
|
|
24997
|
+
) : /* @__PURE__ */ React54.createElement(React54.Fragment, null, codeMode ? /* @__PURE__ */ React54.createElement(
|
|
24583
24998
|
ModeStatusBar,
|
|
24584
24999
|
{
|
|
24585
25000
|
editMode,
|
|
@@ -24589,7 +25004,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24589
25004
|
undoArmed: !!undoBanner || hasUndoable(),
|
|
24590
25005
|
jobs: codeMode.jobs
|
|
24591
25006
|
}
|
|
24592
|
-
) : null, activeLoop ? /* @__PURE__ */
|
|
25007
|
+
) : null, activeLoop ? /* @__PURE__ */ React54.createElement(LoopStatusRow, { loop: activeLoop }) : null, /* @__PURE__ */ React54.createElement(StatusRow, null), /* @__PURE__ */ React54.createElement(
|
|
24593
25008
|
PromptInput,
|
|
24594
25009
|
{
|
|
24595
25010
|
value: input,
|
|
@@ -24599,14 +25014,14 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24599
25014
|
onHistoryPrev: recallPrev,
|
|
24600
25015
|
onHistoryNext: recallNext
|
|
24601
25016
|
}
|
|
24602
|
-
), slashMatches !== null ? /* @__PURE__ */
|
|
25017
|
+
), slashMatches !== null ? /* @__PURE__ */ React54.createElement(SlashSuggestions, { matches: slashMatches, selectedIndex: slashSelected }) : null, atMatches !== null ? /* @__PURE__ */ React54.createElement(
|
|
24603
25018
|
AtMentionSuggestions,
|
|
24604
25019
|
{
|
|
24605
25020
|
matches: atMatches,
|
|
24606
25021
|
selectedIndex: atSelected,
|
|
24607
25022
|
query: atPicker?.query ?? ""
|
|
24608
25023
|
}
|
|
24609
|
-
) : null, slashArgContext ? /* @__PURE__ */
|
|
25024
|
+
) : null, slashArgContext ? /* @__PURE__ */ React54.createElement(
|
|
24610
25025
|
SlashArgPicker,
|
|
24611
25026
|
{
|
|
24612
25027
|
matches: slashArgMatches,
|
|
@@ -24620,12 +25035,12 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
24620
25035
|
}
|
|
24621
25036
|
|
|
24622
25037
|
// src/cli/ui/Setup.tsx
|
|
24623
|
-
import { Box as
|
|
25038
|
+
import { Box as Box47, Text as Text49, useApp } from "ink";
|
|
24624
25039
|
import TextInput from "ink-text-input";
|
|
24625
|
-
import
|
|
25040
|
+
import React55, { useState as useState16 } from "react";
|
|
24626
25041
|
function Setup({ onReady }) {
|
|
24627
|
-
const [value, setValue] =
|
|
24628
|
-
const [error, setError] =
|
|
25042
|
+
const [value, setValue] = useState16("");
|
|
25043
|
+
const [error, setError] = useState16(null);
|
|
24629
25044
|
const { exit: exit2 } = useApp();
|
|
24630
25045
|
const handleSubmit2 = (raw) => {
|
|
24631
25046
|
const trimmed = raw.trim();
|
|
@@ -24646,7 +25061,7 @@ function Setup({ onReady }) {
|
|
|
24646
25061
|
}
|
|
24647
25062
|
onReady(trimmed);
|
|
24648
25063
|
};
|
|
24649
|
-
return /* @__PURE__ */
|
|
25064
|
+
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
25065
|
TextInput,
|
|
24651
25066
|
{
|
|
24652
25067
|
value,
|
|
@@ -24655,7 +25070,13 @@ function Setup({ onReady }) {
|
|
|
24655
25070
|
mask: "\u2022",
|
|
24656
25071
|
placeholder: "sk-..."
|
|
24657
25072
|
}
|
|
24658
|
-
)), error ? /* @__PURE__ */
|
|
25073
|
+
)), 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")));
|
|
25074
|
+
}
|
|
25075
|
+
|
|
25076
|
+
// src/cli/ui/mcp-toast.ts
|
|
25077
|
+
function formatMcpSlowToast(t2) {
|
|
25078
|
+
const seconds = (t2.p95Ms / 1e3).toFixed(1);
|
|
25079
|
+
return `\u26A0 MCP \`${t2.name}\` slow \xB7 ${seconds}s p95 over the last ${t2.sampleSize} calls`;
|
|
24659
25080
|
}
|
|
24660
25081
|
|
|
24661
25082
|
// src/cli/commands/chat.tsx
|
|
@@ -24668,13 +25089,13 @@ function Root({
|
|
|
24668
25089
|
showPicker,
|
|
24669
25090
|
...appProps
|
|
24670
25091
|
}) {
|
|
24671
|
-
const [key, setKey] =
|
|
24672
|
-
const [pickerOpen, setPickerOpen] =
|
|
24673
|
-
const [activeSession, setActiveSession] =
|
|
25092
|
+
const [key, setKey] = useState17(initialKey);
|
|
25093
|
+
const [pickerOpen, setPickerOpen] = useState17(showPicker);
|
|
25094
|
+
const [activeSession, setActiveSession] = useState17(appProps.session);
|
|
24674
25095
|
const workspaceRoot = appProps.codeMode?.rootDir ?? process.cwd();
|
|
24675
|
-
const [sessions2, setSessions] =
|
|
25096
|
+
const [sessions2, setSessions] = useState17(() => listSessionsForWorkspace(workspaceRoot));
|
|
24676
25097
|
if (!key) {
|
|
24677
|
-
return /* @__PURE__ */
|
|
25098
|
+
return /* @__PURE__ */ React56.createElement(
|
|
24678
25099
|
Setup,
|
|
24679
25100
|
{
|
|
24680
25101
|
onReady: (k) => {
|
|
@@ -24686,7 +25107,7 @@ function Root({
|
|
|
24686
25107
|
}
|
|
24687
25108
|
process.env.DEEPSEEK_API_KEY = key;
|
|
24688
25109
|
if (pickerOpen) {
|
|
24689
|
-
return /* @__PURE__ */
|
|
25110
|
+
return /* @__PURE__ */ React56.createElement(KeystrokeProvider, null, /* @__PURE__ */ React56.createElement(
|
|
24690
25111
|
SessionPicker,
|
|
24691
25112
|
{
|
|
24692
25113
|
sessions: sessions2,
|
|
@@ -24719,7 +25140,7 @@ function Root({
|
|
|
24719
25140
|
}
|
|
24720
25141
|
));
|
|
24721
25142
|
}
|
|
24722
|
-
return /* @__PURE__ */
|
|
25143
|
+
return /* @__PURE__ */ React56.createElement(KeystrokeProvider, null, /* @__PURE__ */ React56.createElement(
|
|
24723
25144
|
App,
|
|
24724
25145
|
{
|
|
24725
25146
|
key: activeSession ?? "__new__",
|
|
@@ -24750,19 +25171,37 @@ async function chatCommand(opts) {
|
|
|
24750
25171
|
const mcpServers = [];
|
|
24751
25172
|
const progressSink = { current: null };
|
|
24752
25173
|
let tools = opts.seedTools;
|
|
25174
|
+
const disabledNames = new Set(readConfig().mcpDisabled ?? []);
|
|
24753
25175
|
if (requestedSpecs.length > 0) {
|
|
24754
25176
|
if (!tools) tools = new ToolRegistry();
|
|
24755
25177
|
for (const raw of requestedSpecs) {
|
|
25178
|
+
let label = "anon";
|
|
24756
25179
|
try {
|
|
24757
25180
|
const spec = parseMcpSpec(raw);
|
|
25181
|
+
label = spec.name ?? "anon";
|
|
25182
|
+
if (spec.name && disabledNames.has(spec.name)) {
|
|
25183
|
+
process.stderr.write(`${formatMcpLifecycleEvent({ state: "disabled", name: label })}
|
|
25184
|
+
`);
|
|
25185
|
+
continue;
|
|
25186
|
+
}
|
|
25187
|
+
process.stderr.write(`${formatMcpLifecycleEvent({ state: "handshake", name: label })}
|
|
25188
|
+
`);
|
|
25189
|
+
const t0 = Date.now();
|
|
24758
25190
|
const prefix = spec.name ? `${spec.name}_` : requestedSpecs.length === 1 && opts.mcpPrefix ? opts.mcpPrefix : "";
|
|
24759
25191
|
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
25192
|
const mcp3 = new McpClient({ transport });
|
|
24761
25193
|
await mcp3.initialize();
|
|
25194
|
+
const host = { client: mcp3 };
|
|
24762
25195
|
const bridge = await bridgeMcpTools(mcp3, {
|
|
24763
25196
|
registry: tools,
|
|
24764
25197
|
namePrefix: prefix,
|
|
24765
|
-
|
|
25198
|
+
serverName: label,
|
|
25199
|
+
host,
|
|
25200
|
+
onProgress: (info) => progressSink.current?.(info),
|
|
25201
|
+
onSlow: (info) => process.stderr.write(
|
|
25202
|
+
`${formatMcpSlowToast({ name: info.serverName, p95Ms: info.p95Ms, sampleSize: info.sampleSize })}
|
|
25203
|
+
`
|
|
25204
|
+
)
|
|
24766
25205
|
});
|
|
24767
25206
|
let report;
|
|
24768
25207
|
try {
|
|
@@ -24778,10 +25217,18 @@ async function chatCommand(opts) {
|
|
|
24778
25217
|
elapsedMs: 0
|
|
24779
25218
|
};
|
|
24780
25219
|
}
|
|
24781
|
-
const
|
|
24782
|
-
const
|
|
25220
|
+
const ms = Date.now() - t0;
|
|
25221
|
+
const resourceCount = report.resources.supported ? report.resources.items.length : 0;
|
|
25222
|
+
const promptCount = report.prompts.supported ? report.prompts.items.length : 0;
|
|
24783
25223
|
process.stderr.write(
|
|
24784
|
-
|
|
25224
|
+
`${formatMcpLifecycleEvent({
|
|
25225
|
+
state: "connected",
|
|
25226
|
+
name: label,
|
|
25227
|
+
tools: bridge.registeredNames.length,
|
|
25228
|
+
resources: resourceCount,
|
|
25229
|
+
prompts: promptCount,
|
|
25230
|
+
ms
|
|
25231
|
+
})}
|
|
24785
25232
|
`
|
|
24786
25233
|
);
|
|
24787
25234
|
clients.push(mcp3);
|
|
@@ -24791,14 +25238,15 @@ async function chatCommand(opts) {
|
|
|
24791
25238
|
spec: raw,
|
|
24792
25239
|
toolCount: bridge.registeredNames.length,
|
|
24793
25240
|
report,
|
|
24794
|
-
|
|
25241
|
+
host,
|
|
25242
|
+
bridgeEnv: bridge.env
|
|
24795
25243
|
});
|
|
24796
25244
|
} catch (err) {
|
|
24797
25245
|
const reason = err.message;
|
|
24798
25246
|
failedSpecs.push({ spec: raw, reason });
|
|
24799
25247
|
process.stderr.write(
|
|
24800
|
-
|
|
24801
|
-
\u2192
|
|
25248
|
+
`${formatMcpLifecycleEvent({ state: "failed", name: label, reason })}
|
|
25249
|
+
\u2192 run \`reasonix setup\` to remove this entry, or fix the underlying issue (missing npm package, network, etc.).
|
|
24802
25250
|
`
|
|
24803
25251
|
);
|
|
24804
25252
|
}
|
|
@@ -24825,7 +25273,7 @@ async function chatCommand(opts) {
|
|
|
24825
25273
|
const launchWorkspace = opts.codeMode?.rootDir ?? process.cwd();
|
|
24826
25274
|
const showPicker = !opts.session && !opts.forceResume && listSessionsForWorkspace(launchWorkspace).length > 0;
|
|
24827
25275
|
const { waitUntilExit } = render(
|
|
24828
|
-
/* @__PURE__ */
|
|
25276
|
+
/* @__PURE__ */ React56.createElement(
|
|
24829
25277
|
Root,
|
|
24830
25278
|
{
|
|
24831
25279
|
initialKey,
|
|
@@ -25201,19 +25649,19 @@ async function commitCommand(opts = {}) {
|
|
|
25201
25649
|
import { writeFileSync as writeFileSync14 } from "fs";
|
|
25202
25650
|
import { basename as basename3 } from "path";
|
|
25203
25651
|
import { render as render2 } from "ink";
|
|
25204
|
-
import
|
|
25652
|
+
import React60 from "react";
|
|
25205
25653
|
|
|
25206
25654
|
// src/cli/ui/DiffApp.tsx
|
|
25207
|
-
import { Box as
|
|
25208
|
-
import
|
|
25655
|
+
import { Box as Box50, Static as Static2, Text as Text52, useApp as useApp2, useInput as useInput2 } from "ink";
|
|
25656
|
+
import React59, { useState as useState18 } from "react";
|
|
25209
25657
|
|
|
25210
25658
|
// src/cli/ui/RecordView.tsx
|
|
25211
|
-
import { Box as
|
|
25212
|
-
import
|
|
25659
|
+
import { Box as Box49, Text as Text51 } from "ink";
|
|
25660
|
+
import React58 from "react";
|
|
25213
25661
|
|
|
25214
25662
|
// src/cli/ui/PlanStateBlock.tsx
|
|
25215
|
-
import { Box as
|
|
25216
|
-
import
|
|
25663
|
+
import { Box as Box48, Text as Text50 } from "ink";
|
|
25664
|
+
import React57 from "react";
|
|
25217
25665
|
function PlanStateBlock({ planState }) {
|
|
25218
25666
|
const fields = [];
|
|
25219
25667
|
if (planState.subgoals.length)
|
|
@@ -25225,7 +25673,7 @@ function PlanStateBlock({ planState }) {
|
|
|
25225
25673
|
if (planState.rejectedPaths.length)
|
|
25226
25674
|
fields.push(["rejected", planState.rejectedPaths, COLOR.info, true]);
|
|
25227
25675
|
if (fields.length === 0) return null;
|
|
25228
|
-
return /* @__PURE__ */
|
|
25676
|
+
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
25677
|
}
|
|
25230
25678
|
|
|
25231
25679
|
// src/cli/ui/RecordView.tsx
|
|
@@ -25234,21 +25682,21 @@ function RecordView({ rec, compact: compact2 = false }) {
|
|
|
25234
25682
|
const toolContentMax = compact2 ? 200 : 400;
|
|
25235
25683
|
if (rec.role === "user") {
|
|
25236
25684
|
const content = rec.content.includes("\n") ? rec.content.split("\n").join("\n ") : rec.content;
|
|
25237
|
-
return /* @__PURE__ */
|
|
25685
|
+
return /* @__PURE__ */ React58.createElement(Box49, { marginTop: 1 }, /* @__PURE__ */ React58.createElement(Text51, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React58.createElement(Text51, null, content));
|
|
25238
25686
|
}
|
|
25239
25687
|
if (rec.role === "assistant_final") {
|
|
25240
|
-
return /* @__PURE__ */
|
|
25688
|
+
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
25689
|
}
|
|
25242
25690
|
if (rec.role === "tool") {
|
|
25243
|
-
return /* @__PURE__ */
|
|
25691
|
+
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
25692
|
}
|
|
25245
25693
|
if (rec.role === "error") {
|
|
25246
|
-
return /* @__PURE__ */
|
|
25694
|
+
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
25695
|
}
|
|
25248
25696
|
if (rec.role === "done" || rec.role === "assistant_delta") {
|
|
25249
25697
|
return null;
|
|
25250
25698
|
}
|
|
25251
|
-
return /* @__PURE__ */
|
|
25699
|
+
return /* @__PURE__ */ React58.createElement(Box49, null, /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, "[", rec.role, "] ", rec.content));
|
|
25252
25700
|
}
|
|
25253
25701
|
function CacheBadge({ usage }) {
|
|
25254
25702
|
const hit = usage.prompt_cache_hit_tokens ?? 0;
|
|
@@ -25257,7 +25705,7 @@ function CacheBadge({ usage }) {
|
|
|
25257
25705
|
if (total === 0) return null;
|
|
25258
25706
|
const pct2 = hit / total * 100;
|
|
25259
25707
|
const color2 = pct2 >= 70 ? "green" : pct2 >= 40 ? "yellow" : "red";
|
|
25260
|
-
return /* @__PURE__ */
|
|
25708
|
+
return /* @__PURE__ */ React58.createElement(Text51, null, /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, " \xB7 cache "), /* @__PURE__ */ React58.createElement(Text51, { color: color2 }, pct2.toFixed(1), "%"));
|
|
25261
25709
|
}
|
|
25262
25710
|
function truncate3(s, max) {
|
|
25263
25711
|
return s.length <= max ? s : `${s.slice(0, max)}\u2026 (+${s.length - max} chars)`;
|
|
@@ -25268,7 +25716,7 @@ function DiffApp({ report }) {
|
|
|
25268
25716
|
const { exit: exit2 } = useApp2();
|
|
25269
25717
|
const maxIdx = Math.max(0, report.pairs.length - 1);
|
|
25270
25718
|
const initialIdx = report.firstDivergenceTurn ? report.pairs.findIndex((p) => p.turn === report.firstDivergenceTurn) : 0;
|
|
25271
|
-
const [idx, setIdx] =
|
|
25719
|
+
const [idx, setIdx] = useState18(Math.max(0, initialIdx));
|
|
25272
25720
|
useInput2((input, key) => {
|
|
25273
25721
|
if (input === "q" || key.ctrl && input === "c") {
|
|
25274
25722
|
exit2();
|
|
@@ -25291,7 +25739,7 @@ function DiffApp({ report }) {
|
|
|
25291
25739
|
}
|
|
25292
25740
|
});
|
|
25293
25741
|
const pair = report.pairs[idx];
|
|
25294
|
-
return /* @__PURE__ */
|
|
25742
|
+
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
25743
|
}
|
|
25296
25744
|
function DiffHeader({ report }) {
|
|
25297
25745
|
const a = report.a;
|
|
@@ -25309,15 +25757,15 @@ function DiffHeader({ report }) {
|
|
|
25309
25757
|
} else if (a.stats.prefixHashes[0] && a.stats.prefixHashes[0] === b.stats.prefixHashes[0]) {
|
|
25310
25758
|
prefixLine = `shared prefix hash ${a.stats.prefixHashes[0].slice(0, 12)}\u2026 \u2014 cache delta attributable to log stability, not prompt change.`;
|
|
25311
25759
|
}
|
|
25312
|
-
return /* @__PURE__ */
|
|
25760
|
+
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
25761
|
}
|
|
25314
25762
|
function Pane({
|
|
25315
25763
|
label,
|
|
25316
25764
|
headerColor,
|
|
25317
25765
|
records
|
|
25318
25766
|
}) {
|
|
25319
|
-
return /* @__PURE__ */
|
|
25320
|
-
|
|
25767
|
+
return /* @__PURE__ */ React59.createElement(
|
|
25768
|
+
Box50,
|
|
25321
25769
|
{
|
|
25322
25770
|
flexDirection: "column",
|
|
25323
25771
|
flexGrow: 1,
|
|
@@ -25325,21 +25773,21 @@ function Pane({
|
|
|
25325
25773
|
borderStyle: "single",
|
|
25326
25774
|
borderColor: headerColor
|
|
25327
25775
|
},
|
|
25328
|
-
/* @__PURE__ */
|
|
25329
|
-
records.length === 0 ? /* @__PURE__ */
|
|
25776
|
+
/* @__PURE__ */ React59.createElement(Text52, { color: headerColor, bold: true }, label),
|
|
25777
|
+
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
25778
|
);
|
|
25331
25779
|
}
|
|
25332
25780
|
function KindBadge({ kind }) {
|
|
25333
25781
|
if (kind === "match") {
|
|
25334
|
-
return /* @__PURE__ */
|
|
25782
|
+
return /* @__PURE__ */ React59.createElement(Text52, { color: "green" }, "\u2713 match");
|
|
25335
25783
|
}
|
|
25336
25784
|
if (kind === "diverge") {
|
|
25337
|
-
return /* @__PURE__ */
|
|
25785
|
+
return /* @__PURE__ */ React59.createElement(Text52, { color: "yellow" }, "\u2605 diverge");
|
|
25338
25786
|
}
|
|
25339
25787
|
if (kind === "only_in_a") {
|
|
25340
|
-
return /* @__PURE__ */
|
|
25788
|
+
return /* @__PURE__ */ React59.createElement(Text52, { color: "blue" }, "\u2190 only in A");
|
|
25341
25789
|
}
|
|
25342
|
-
return /* @__PURE__ */
|
|
25790
|
+
return /* @__PURE__ */ React59.createElement(Text52, { color: "magenta" }, "\u2192 only in B");
|
|
25343
25791
|
}
|
|
25344
25792
|
function paneRecords(pair, side) {
|
|
25345
25793
|
if (!pair) return [];
|
|
@@ -25370,7 +25818,7 @@ markdown report written to ${opts.mdPath}`);
|
|
|
25370
25818
|
return;
|
|
25371
25819
|
}
|
|
25372
25820
|
if (wantTui) {
|
|
25373
|
-
const { waitUntilExit } = render2(
|
|
25821
|
+
const { waitUntilExit } = render2(React60.createElement(DiffApp, { report }), {
|
|
25374
25822
|
exitOnCtrlC: true,
|
|
25375
25823
|
patchConsole: false
|
|
25376
25824
|
});
|
|
@@ -26041,16 +26489,16 @@ function pad2(s, width) {
|
|
|
26041
26489
|
|
|
26042
26490
|
// src/cli/commands/replay.ts
|
|
26043
26491
|
import { render as render3 } from "ink";
|
|
26044
|
-
import
|
|
26492
|
+
import React63 from "react";
|
|
26045
26493
|
|
|
26046
26494
|
// src/cli/ui/ReplayApp.tsx
|
|
26047
|
-
import { Box as
|
|
26048
|
-
import
|
|
26495
|
+
import { Box as Box52, Static as Static3, Text as Text54, useApp as useApp3, useInput as useInput3 } from "ink";
|
|
26496
|
+
import React62, { useMemo as useMemo7, useState as useState19 } from "react";
|
|
26049
26497
|
|
|
26050
26498
|
// src/cli/ui/StatsPanel.tsx
|
|
26051
26499
|
import { basename as basename4 } from "path";
|
|
26052
|
-
import { Box as
|
|
26053
|
-
import
|
|
26500
|
+
import { Box as Box51, Text as Text53, useStdout as useStdout15 } from "ink";
|
|
26501
|
+
import React61 from "react";
|
|
26054
26502
|
import stringWidth2 from "string-width";
|
|
26055
26503
|
var COLD_START_TURNS = 3;
|
|
26056
26504
|
function StatsPanel({
|
|
@@ -26066,7 +26514,7 @@ function StatsPanel({
|
|
|
26066
26514
|
sessionName
|
|
26067
26515
|
}) {
|
|
26068
26516
|
const coldStart = summary.turns <= COLD_START_TURNS;
|
|
26069
|
-
return /* @__PURE__ */
|
|
26517
|
+
return /* @__PURE__ */ React61.createElement(Box51, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React61.createElement(
|
|
26070
26518
|
ChromeRow,
|
|
26071
26519
|
{
|
|
26072
26520
|
editMode,
|
|
@@ -26080,7 +26528,7 @@ function StatsPanel({
|
|
|
26080
26528
|
updateAvailable,
|
|
26081
26529
|
balance: balance ?? null
|
|
26082
26530
|
}
|
|
26083
|
-
), /* @__PURE__ */
|
|
26531
|
+
), /* @__PURE__ */ React61.createElement(ChromeRule, null), budgetUsd !== null && budgetUsd !== void 0 ? /* @__PURE__ */ React61.createElement(BudgetRow, { spent: summary.totalCostUsd, cap: budgetUsd }) : null);
|
|
26084
26532
|
}
|
|
26085
26533
|
function ChromeRow({
|
|
26086
26534
|
editMode,
|
|
@@ -26125,15 +26573,15 @@ function ChromeRow({
|
|
|
26125
26573
|
if (showSession) budget3 -= sessionW;
|
|
26126
26574
|
const showUpdate = updateW > 0 && budget3 >= updateW;
|
|
26127
26575
|
if (showUpdate) budget3 -= updateW;
|
|
26128
|
-
return /* @__PURE__ */
|
|
26129
|
-
|
|
26576
|
+
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(
|
|
26577
|
+
Text53,
|
|
26130
26578
|
{
|
|
26131
26579
|
color: summary.turns === 0 || coldStart ? COLOR.info : sessionCostColor(summary.totalCostUsd),
|
|
26132
26580
|
bold: summary.turns > 0 && !coldStart,
|
|
26133
26581
|
dimColor: summary.turns === 0 || coldStart
|
|
26134
26582
|
},
|
|
26135
26583
|
costLabel
|
|
26136
|
-
), showBalance && balance ? /* @__PURE__ */
|
|
26584
|
+
), 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
26585
|
Bar,
|
|
26138
26586
|
{
|
|
26139
26587
|
ratio: summary.cacheHitRatio,
|
|
@@ -26141,7 +26589,7 @@ function ChromeRow({
|
|
|
26141
26589
|
cells: 6,
|
|
26142
26590
|
dim: coldStart
|
|
26143
26591
|
}
|
|
26144
|
-
), /* @__PURE__ */
|
|
26592
|
+
), /* @__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
26593
|
}
|
|
26146
26594
|
function pickModePill(planMode, editMode) {
|
|
26147
26595
|
if (planMode) return { label: "PLAN", color: COLOR.err };
|
|
@@ -26153,7 +26601,7 @@ function pickModePill(planMode, editMode) {
|
|
|
26153
26601
|
function BudgetRow({ spent, cap }) {
|
|
26154
26602
|
const pct2 = Math.max(0, spent / cap * 100);
|
|
26155
26603
|
const color2 = pct2 >= 100 ? "#f87171" : pct2 >= 80 ? "#fbbf24" : "#94a3b8";
|
|
26156
|
-
return /* @__PURE__ */
|
|
26604
|
+
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
26605
|
}
|
|
26158
26606
|
function sessionCostColor(cost2) {
|
|
26159
26607
|
if (cost2 <= 0) return void 0;
|
|
@@ -26166,7 +26614,7 @@ function sessionCostColor(cost2) {
|
|
|
26166
26614
|
function ReplayApp({ meta, pages }) {
|
|
26167
26615
|
const { exit: exit2 } = useApp3();
|
|
26168
26616
|
const maxIdx = Math.max(0, pages.length - 1);
|
|
26169
|
-
const [idx, setIdx] =
|
|
26617
|
+
const [idx, setIdx] = useState19(maxIdx);
|
|
26170
26618
|
useInput3((input, key) => {
|
|
26171
26619
|
if (input === "q" || key.ctrl && input === "c") {
|
|
26172
26620
|
exit2();
|
|
@@ -26202,7 +26650,7 @@ function ReplayApp({ meta, pages }) {
|
|
|
26202
26650
|
const prefixHash = cumStats.prefixHashes.length === 1 ? cumStats.prefixHashes[0].slice(0, 16) : cumStats.prefixHashes.length === 0 ? "(untracked)" : `(churned \xD7${cumStats.prefixHashes.length})`;
|
|
26203
26651
|
const currentPage = pages[idx];
|
|
26204
26652
|
const progressLabel = pages.length === 0 ? "empty transcript" : `turn ${idx + 1} / ${pages.length}`;
|
|
26205
|
-
return /* @__PURE__ */
|
|
26653
|
+
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
26654
|
}
|
|
26207
26655
|
|
|
26208
26656
|
// src/cli/commands/replay.ts
|
|
@@ -26214,7 +26662,7 @@ async function replayCommand(opts) {
|
|
|
26214
26662
|
}
|
|
26215
26663
|
const { parsed } = replayFromFile(opts.path);
|
|
26216
26664
|
const pages = groupRecordsByTurn(parsed.records);
|
|
26217
|
-
const { waitUntilExit } = render3(
|
|
26665
|
+
const { waitUntilExit } = render3(React63.createElement(ReplayApp, { meta: parsed.meta, pages }), {
|
|
26218
26666
|
exitOnCtrlC: true,
|
|
26219
26667
|
patchConsole: false
|
|
26220
26668
|
});
|
|
@@ -26349,26 +26797,49 @@ async function runCommand2(opts) {
|
|
|
26349
26797
|
const clients = [];
|
|
26350
26798
|
let tools;
|
|
26351
26799
|
let successCount = 0;
|
|
26800
|
+
const disabledNames = new Set(readConfig().mcpDisabled ?? []);
|
|
26352
26801
|
if (requestedSpecs.length > 0) {
|
|
26353
26802
|
tools = new ToolRegistry();
|
|
26354
26803
|
for (const raw of requestedSpecs) {
|
|
26804
|
+
let label = "anon";
|
|
26355
26805
|
try {
|
|
26356
26806
|
const spec = parseMcpSpec(raw);
|
|
26807
|
+
label = spec.name ?? "anon";
|
|
26808
|
+
if (spec.name && disabledNames.has(spec.name)) {
|
|
26809
|
+
process.stderr.write(`${formatMcpLifecycleEvent({ state: "disabled", name: label })}
|
|
26810
|
+
`);
|
|
26811
|
+
continue;
|
|
26812
|
+
}
|
|
26813
|
+
process.stderr.write(`${formatMcpLifecycleEvent({ state: "handshake", name: label })}
|
|
26814
|
+
`);
|
|
26815
|
+
const t0 = Date.now();
|
|
26357
26816
|
const prefix2 = spec.name ? `${spec.name}_` : requestedSpecs.length === 1 && opts.mcpPrefix ? opts.mcpPrefix : "";
|
|
26358
26817
|
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
26818
|
const mcp3 = new McpClient({ transport });
|
|
26360
26819
|
await mcp3.initialize();
|
|
26361
|
-
const bridge = await bridgeMcpTools(mcp3, {
|
|
26362
|
-
|
|
26820
|
+
const bridge = await bridgeMcpTools(mcp3, {
|
|
26821
|
+
registry: tools,
|
|
26822
|
+
namePrefix: prefix2,
|
|
26823
|
+
serverName: label,
|
|
26824
|
+
onSlow: (info) => process.stderr.write(
|
|
26825
|
+
`${formatMcpSlowToast({ name: info.serverName, p95Ms: info.p95Ms, sampleSize: info.sampleSize })}
|
|
26826
|
+
`
|
|
26827
|
+
)
|
|
26828
|
+
});
|
|
26363
26829
|
process.stderr.write(
|
|
26364
|
-
|
|
26830
|
+
`${formatMcpLifecycleEvent({
|
|
26831
|
+
state: "connected",
|
|
26832
|
+
name: label,
|
|
26833
|
+
tools: bridge.registeredNames.length,
|
|
26834
|
+
ms: Date.now() - t0
|
|
26835
|
+
})}
|
|
26365
26836
|
`
|
|
26366
26837
|
);
|
|
26367
26838
|
clients.push(mcp3);
|
|
26368
26839
|
successCount++;
|
|
26369
26840
|
} catch (err) {
|
|
26370
26841
|
process.stderr.write(
|
|
26371
|
-
|
|
26842
|
+
`${formatMcpLifecycleEvent({ state: "failed", name: label, reason: err.message })}
|
|
26372
26843
|
\u2192 run \`reasonix setup\` to remove broken entries from your saved config.
|
|
26373
26844
|
`
|
|
26374
26845
|
);
|
|
@@ -26520,28 +26991,28 @@ function truncate5(s, max) {
|
|
|
26520
26991
|
|
|
26521
26992
|
// src/cli/commands/setup.tsx
|
|
26522
26993
|
import { render as render4 } from "ink";
|
|
26523
|
-
import
|
|
26994
|
+
import React65 from "react";
|
|
26524
26995
|
|
|
26525
26996
|
// src/cli/ui/Wizard.tsx
|
|
26526
|
-
import { Box as
|
|
26997
|
+
import { Box as Box53, Text as Text55, useApp as useApp4, useInput as useInput4 } from "ink";
|
|
26527
26998
|
import TextInput2 from "ink-text-input";
|
|
26528
|
-
import
|
|
26999
|
+
import React64, { useState as useState20 } from "react";
|
|
26529
27000
|
var CATALOG_BY_NAME = new Map(MCP_CATALOG.map((e) => [e.name, e]));
|
|
26530
27001
|
function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
26531
27002
|
const { exit: exit2 } = useApp4();
|
|
26532
|
-
const [step, setStep] =
|
|
26533
|
-
const [data, setData] =
|
|
27003
|
+
const [step, setStep] = useState20(existingApiKey ? "preset" : "apiKey");
|
|
27004
|
+
const [data, setData] = useState20({
|
|
26534
27005
|
apiKey: existingApiKey ?? "",
|
|
26535
27006
|
preset: initial?.preset ?? "auto",
|
|
26536
27007
|
selectedCatalog: deriveInitialCatalog(initial?.mcp ?? []),
|
|
26537
27008
|
catalogArgs: {}
|
|
26538
27009
|
});
|
|
26539
|
-
const [error, setError] =
|
|
27010
|
+
const [error, setError] = useState20(null);
|
|
26540
27011
|
useInput4((_input, key) => {
|
|
26541
27012
|
if (key.escape && step !== "saved" && onCancel) onCancel();
|
|
26542
27013
|
});
|
|
26543
27014
|
if (step === "apiKey") {
|
|
26544
|
-
return /* @__PURE__ */
|
|
27015
|
+
return /* @__PURE__ */ React64.createElement(
|
|
26545
27016
|
ApiKeyStep,
|
|
26546
27017
|
{
|
|
26547
27018
|
onSubmit: (key) => {
|
|
@@ -26555,7 +27026,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
26555
27026
|
);
|
|
26556
27027
|
}
|
|
26557
27028
|
if (step === "preset") {
|
|
26558
|
-
return /* @__PURE__ */
|
|
27029
|
+
return /* @__PURE__ */ React64.createElement(StepFrame, { title: "Pick a preset", step: 1, total: 3 }, /* @__PURE__ */ React64.createElement(
|
|
26559
27030
|
SingleSelect,
|
|
26560
27031
|
{
|
|
26561
27032
|
items: presetItems(),
|
|
@@ -26565,10 +27036,10 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
26565
27036
|
setStep("mcp");
|
|
26566
27037
|
}
|
|
26567
27038
|
}
|
|
26568
|
-
), /* @__PURE__ */
|
|
27039
|
+
), /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, { dimColor: true }, "[\u2191\u2193] navigate \xB7 [Enter] confirm \xB7 [Esc] cancel")));
|
|
26569
27040
|
}
|
|
26570
27041
|
if (step === "mcp") {
|
|
26571
|
-
return /* @__PURE__ */
|
|
27042
|
+
return /* @__PURE__ */ React64.createElement(StepFrame, { title: "Which MCP servers should Reasonix wire up for you?", step: 2, total: 3 }, /* @__PURE__ */ React64.createElement(
|
|
26572
27043
|
MultiSelect,
|
|
26573
27044
|
{
|
|
26574
27045
|
items: mcpItems(),
|
|
@@ -26593,7 +27064,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
26593
27064
|
}
|
|
26594
27065
|
const currentName = pending[0];
|
|
26595
27066
|
const entry = CATALOG_BY_NAME.get(currentName);
|
|
26596
|
-
return /* @__PURE__ */
|
|
27067
|
+
return /* @__PURE__ */ React64.createElement(
|
|
26597
27068
|
McpArgsStep,
|
|
26598
27069
|
{
|
|
26599
27070
|
entry,
|
|
@@ -26611,7 +27082,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
26611
27082
|
}
|
|
26612
27083
|
if (step === "review") {
|
|
26613
27084
|
const specs = data.selectedCatalog.map((name) => buildSpec(name, data.catalogArgs));
|
|
26614
|
-
return /* @__PURE__ */
|
|
27085
|
+
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
27086
|
SummaryLine,
|
|
26616
27087
|
{
|
|
26617
27088
|
label: "MCP",
|
|
@@ -26619,8 +27090,8 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
26619
27090
|
}
|
|
26620
27091
|
), specs.map((spec, i) => (
|
|
26621
27092
|
// biome-ignore lint/suspicious/noArrayIndexKey: review-only render, order fixed
|
|
26622
|
-
/* @__PURE__ */
|
|
26623
|
-
)), /* @__PURE__ */
|
|
27093
|
+
/* @__PURE__ */ React64.createElement(Box53, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React64.createElement(Text55, { dimColor: true }, "\xB7 ", spec))
|
|
27094
|
+
)), /* @__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
27095
|
ReviewConfirm,
|
|
26625
27096
|
{
|
|
26626
27097
|
onConfirm: () => {
|
|
@@ -26646,15 +27117,15 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
26646
27117
|
}
|
|
26647
27118
|
));
|
|
26648
27119
|
}
|
|
26649
|
-
return /* @__PURE__ */
|
|
27120
|
+
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
27121
|
}
|
|
26651
27122
|
function ApiKeyStep({
|
|
26652
27123
|
onSubmit,
|
|
26653
27124
|
error,
|
|
26654
27125
|
onError
|
|
26655
27126
|
}) {
|
|
26656
|
-
const [value, setValue] =
|
|
26657
|
-
return /* @__PURE__ */
|
|
27127
|
+
const [value, setValue] = useState20("");
|
|
27128
|
+
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
27129
|
TextInput2,
|
|
26659
27130
|
{
|
|
26660
27131
|
value,
|
|
@@ -26671,7 +27142,7 @@ function ApiKeyStep({
|
|
|
26671
27142
|
mask: "\u2022",
|
|
26672
27143
|
placeholder: "sk-..."
|
|
26673
27144
|
}
|
|
26674
|
-
)), error ? /* @__PURE__ */
|
|
27145
|
+
)), 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
27146
|
}
|
|
26676
27147
|
function McpArgsStep({
|
|
26677
27148
|
entry,
|
|
@@ -26679,8 +27150,8 @@ function McpArgsStep({
|
|
|
26679
27150
|
onSubmit,
|
|
26680
27151
|
onError
|
|
26681
27152
|
}) {
|
|
26682
|
-
const [value, setValue] =
|
|
26683
|
-
return /* @__PURE__ */
|
|
27153
|
+
const [value, setValue] = useState20("");
|
|
27154
|
+
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
27155
|
TextInput2,
|
|
26685
27156
|
{
|
|
26686
27157
|
value,
|
|
@@ -26696,7 +27167,7 @@ function McpArgsStep({
|
|
|
26696
27167
|
},
|
|
26697
27168
|
placeholder: placeholderFor(entry)
|
|
26698
27169
|
}
|
|
26699
|
-
)), error ? /* @__PURE__ */
|
|
27170
|
+
)), error ? /* @__PURE__ */ React64.createElement(Box53, { marginTop: 1 }, /* @__PURE__ */ React64.createElement(Text55, { color: "red" }, error)) : null));
|
|
26700
27171
|
}
|
|
26701
27172
|
function ReviewConfirm({ onConfirm }) {
|
|
26702
27173
|
useInput4((_i, key) => {
|
|
@@ -26716,10 +27187,10 @@ function StepFrame({
|
|
|
26716
27187
|
total,
|
|
26717
27188
|
children
|
|
26718
27189
|
}) {
|
|
26719
|
-
return /* @__PURE__ */
|
|
27190
|
+
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
27191
|
}
|
|
26721
27192
|
function SummaryLine({ label, value }) {
|
|
26722
|
-
return /* @__PURE__ */
|
|
27193
|
+
return /* @__PURE__ */ React64.createElement(Box53, null, /* @__PURE__ */ React64.createElement(Text55, null, label.padEnd(12)), /* @__PURE__ */ React64.createElement(Text55, { bold: true }, value));
|
|
26723
27194
|
}
|
|
26724
27195
|
function presetItems() {
|
|
26725
27196
|
return ["auto", "flash", "pro"].map((name) => ({
|
|
@@ -26775,7 +27246,7 @@ async function setupCommand(_opts = {}) {
|
|
|
26775
27246
|
const existingKey = loadApiKey();
|
|
26776
27247
|
const existing = readConfig();
|
|
26777
27248
|
const { waitUntilExit, unmount } = render4(
|
|
26778
|
-
/* @__PURE__ */
|
|
27249
|
+
/* @__PURE__ */ React65.createElement(
|
|
26779
27250
|
Wizard,
|
|
26780
27251
|
{
|
|
26781
27252
|
existingApiKey: existingKey,
|