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 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 = `${prefix}${mcpTool.name}`;
1304
- registry.register({
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 React55, { useState as useState16 } from "react";
7637
+ import React56, { useState as useState17 } from "react";
7595
7638
 
7596
7639
  // src/cli/ui/App.tsx
7597
- import { Box as Box45, Text as Text47, useStdout as useStdout14 } from "ink";
7598
- import React53, { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMemo6, useRef as useRef6, useState as useState14 } from "react";
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 Box9 } from "ink";
12943
- import React11 from "react";
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 Box8, Text as Text8 } from "ink";
12947
- import React10 from "react";
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 Box7, Text as Text7 } from "ink";
12951
- import React9 from "react";
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__ */ React9.createElement(Box7, null, /* @__PURE__ */ React9.createElement(Text7, { color: color2 }, GLYPH.block.repeat(filled)), /* @__PURE__ */ React9.createElement(Text7, { color: emptyColor ?? COLOR.info, dimColor: true }, GLYPH.shade1.repeat(total - filled)), showLabel ? /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, ` ${label ?? `${Math.round(clamped)}%`}`) : null);
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__ */ React10.createElement(Box8, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Box8, null, /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, showProgress ? `${doneCount}/${total} done (${pct2}%) \xB7 ${total} step${total === 1 ? "" : "s"}` : `${total} step${total === 1 ? "" : "s"}`)), /* @__PURE__ */ React10.createElement(Box8, { flexDirection: "column" }, steps.map((step, i) => {
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__ */ React10.createElement(Box8, { key: step.id }, /* @__PURE__ */ React10.createElement(Text8, { color: COLOR.info, dimColor: true }, isLast ? GLYPH.branchEnd : GLYPH.branch), /* @__PURE__ */ React10.createElement(Text8, null, " "), /* @__PURE__ */ React10.createElement(Text8, { color: sg.color, bold: status3 === "running" || isCur }, sg.glyph), /* @__PURE__ */ React10.createElement(Text8, null, " "), /* @__PURE__ */ React10.createElement(
13001
- Text8,
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__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Text8, null, " "), /* @__PURE__ */ React10.createElement(Text8, { color: risk.color }, risk.text)) : null);
13009
- })), showProgress ? /* @__PURE__ */ React10.createElement(Box8, null, /* @__PURE__ */ React10.createElement(Text8, null, " "), /* @__PURE__ */ React10.createElement(CharBar, { pct: pct2, width: 24 })) : null);
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 = React10.memo(PlanStepListInner);
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__ */ React11.createElement(ApprovalCard, { tone: "ok", glyph: "\u26C1", title: "Checkpoint \u2014 step done", metaRight: subtitle }, steps && steps.length > 0 ? /* @__PURE__ */ React11.createElement(Box9, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React11.createElement(PlanStepList, { steps, statuses, focusStepId: stepId })) : null, /* @__PURE__ */ React11.createElement(
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 = React11.memo(PlanCheckpointConfirmInner);
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 Box10, Text as Text9 } from "ink";
13071
- import React12 from "react";
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__ */ React12.createElement(
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__ */ React12.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React12.createElement(Text9, { color: TONE.warn }, "\u25B2 the plan flags open questions or risks \u2014 pick ", /* @__PURE__ */ React12.createElement(Text9, { bold: true }, "refine"), " to write concrete answers before the model moves on.")) : null,
13084
- steps && steps.length > 0 ? /* @__PURE__ */ React12.createElement(Box10, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React12.createElement(PlanStepList, { steps })) : null,
13085
- /* @__PURE__ */ React12.createElement(
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 = React12.memo(PlanConfirmInner);
13450
+ var PlanConfirm = React13.memo(PlanConfirmInner);
13118
13451
 
13119
13452
  // src/cli/ui/PlanRefineInput.tsx
13120
- import { Box as Box11, Text as Text10 } from "ink";
13121
- import React14, { useState as useState5 } from "react";
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 React13, { createContext as createContext2, useContext as useContext2, useEffect as useEffect2, useState as useState4 } from "react";
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] = useState4(0);
13131
- const [slow, setSlow] = useState4(0);
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__ */ React13.createElement(FastTickContext.Provider, { value: fast }, /* @__PURE__ */ React13.createElement(SlowTickContext.Provider, { value: slow }, children));
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] = useState4(() => Date.now());
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] = useState5("");
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__ */ React14.createElement(
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__ */ React14.createElement(Box11, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text10, { color: FG.sub }, meta.hint, value === "" ? meta.blankHint : "")),
13225
- /* @__PURE__ */ React14.createElement(Box11, null, /* @__PURE__ */ React14.createElement(Text10, { color: meta.cursorColor, bold: true }, "\u203A "), /* @__PURE__ */ React14.createElement(Text10, null, value), /* @__PURE__ */ React14.createElement(Text10, { color: meta.cursorColor, bold: true }, cursorOn ? "\u258D" : " "))
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 Box12, Text as Text11 } from "ink";
13231
- import React15 from "react";
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__ */ React15.createElement(
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__ */ React15.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text11, null, reason)),
13276
- summary ? /* @__PURE__ */ React15.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text11, { dimColor: true }, `updated summary: ${summary}`)) : null,
13277
- /* @__PURE__ */ React15.createElement(Box12, { marginBottom: 1, flexDirection: "column" }, rows.map((row3) => {
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__ */ React15.createElement(Box12, { key: `${row3.kind}-${row3.step.id}` }, /* @__PURE__ */ React15.createElement(Text11, { color: prefixColor, bold: true }, `${prefix} `), /* @__PURE__ */ React15.createElement(Text11, { color: risk.color, bold: true, dimColor: dim }, risk.dots), /* @__PURE__ */ React15.createElement(Text11, { dimColor: dim, strikethrough: strike }, ` ${row3.step.id} \xB7 ${row3.step.title}`));
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__ */ React15.createElement(
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 = React15.memo(PlanReviseConfirmInner);
13640
+ var PlanReviseConfirm = React16.memo(PlanReviseConfirmInner);
13308
13641
 
13309
13642
  // src/cli/ui/PlanReviseEditor.tsx
13310
- import { Box as Box13, Text as Text12 } from "ink";
13311
- import React16, { useState as useState6 } from "react";
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] = useState6(
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] = useState6(firstEditableIndex < 0 ? 0 : firstEditableIndex);
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__ */ React16.createElement(
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__ */ React16.createElement(ReviseRow, { key: r.step.id, row: r, index: i, focused: i === focus }))
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__ */ React16.createElement(Text12, { color: TONE.brand }, "\u25B8 ") : /* @__PURE__ */ React16.createElement(Text12, null, " ");
13404
- return /* @__PURE__ */ React16.createElement(Box13, null, focusGlyph, /* @__PURE__ */ React16.createElement(Text12, { color: markerColor }, marker), /* @__PURE__ */ React16.createElement(Text12, { color: titleColor, bold: focused, italic: row3.skipped, strikethrough: row3.skipped }, ` ${index + 1}. ${row3.step.title}`), row3.skipped ? /* @__PURE__ */ React16.createElement(Text12, { color: TONE.warn }, " \u2190 skipped") : null);
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 Box14, Text as Text13, useStdout as useStdout4 } from "ink";
13409
- import React17, { useRef as useRef2, useState as useState7 } from "react";
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] = useState7(value.length);
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__ */ React17.createElement(Box14, { flexDirection: "column", paddingX: 1 }, (() => {
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__ */ React17.createElement(Box14, { key: `skip-${renderIdx}` }, /* @__PURE__ */ React17.createElement(Text13, { color: FG.faint }, continuationIndent), /* @__PURE__ */ React17.createElement(Text13, { color: FG.faint }, `[\u2026 ${item.linesHidden} line${item.linesHidden === 1 ? "" : "s"} hidden \u2014 full content kept, submitted on Enter \u2026]`))
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__ */ React17.createElement(
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__ */ React17.createElement(
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__ */ React17.createElement(
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__ */ React17.createElement(
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__ */ React17.createElement(Box14, null, /* @__PURE__ */ React17.createElement(Text13, { color: FG.faint }, ` [${lines.length} lines \xB7 PgUp/PgDn jump \xB7 Ctrl+U clear \xB7 Ctrl+W del word]`)) : null, !disabled ? /* @__PURE__ */ React17.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, { color: FG.faint }, " \u23CE send \xB7 shift/alt+\u23CE newline \xB7 \u2191\u2193 history \xB7 esc abort \xB7 ctrl-c quit")) : /* @__PURE__ */ React17.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text13, { color: FG.faint }, " esc to stop")));
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__ */ React17.createElement(Box14, null, /* @__PURE__ */ React17.createElement(Text13, { bold: true, color: leadColor }, lead), /* @__PURE__ */ React17.createElement(Text13, { bold: true, color: accentColor }, "\u25B8 "), /* @__PURE__ */ React17.createElement(Text13, { bold: true, color: "black", backgroundColor: accentColor }, ` ${labelText} `));
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__ */ React17.createElement(Box14, null, /* @__PURE__ */ React17.createElement(Text13, { bold: true, color: leadColor }, lead), /* @__PURE__ */ React17.createElement(Text13, { color: FG.faint }, " "), /* @__PURE__ */ React17.createElement(Text13, { color: FG.meta }, "\u250C "), /* @__PURE__ */ React17.createElement(Text13, { color: FG.body, backgroundColor: SURFACE.bgElev }, `${labelText} `), /* @__PURE__ */ React17.createElement(Text13, { color: FG.meta }, " \u2510"));
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__ */ React17.createElement(Box14, null, /* @__PURE__ */ React17.createElement(Text13, { bold: true, color: accentColor }, promptPrefix), !disabled ? /* @__PURE__ */ React17.createElement(Text13, { color: accentColor }, cursorVisible ? "\u258C" : " ") : null, /* @__PURE__ */ React17.createElement(Text13, { color: FG.faint }, placeholderText));
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__ */ React17.createElement(Box14, null, isFirst ? /* @__PURE__ */ React17.createElement(Text13, { bold: true, color: accentColor }, promptPrefix) : /* @__PURE__ */ React17.createElement(Text13, { color: FG.faint }, continuationIndent), viewport.hiddenLeft ? /* @__PURE__ */ React17.createElement(Text13, { color: FG.faint }, "\u2039") : null, /* @__PURE__ */ React17.createElement(
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__ */ React17.createElement(Text13, { color: FG.faint }, "\u203A") : null);
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__ */ React17.createElement(React17.Fragment, null, segments.map((seg, i) => renderSegment(seg, i, false)));
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__ */ React17.createElement(
14138
- Text13,
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__ */ React17.createElement(Text13, { key: `t-${i}-b` }, split.before));
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__ */ React17.createElement(Text13, { key: `t-${i}-c`, inverse: cursorVisible, color: accentColor }, split.atCursor)
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__ */ React17.createElement(Text13, { key: `t-${i}-c-eol`, color: accentColor }, cursorVisible ? "\u258C" : " ")
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__ */ React17.createElement(Text13, { key: `t-${i}-a` }, split.after));
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__ */ React17.createElement(Text13, { key: "cursor-eol", color: accentColor }, cursorVisible ? "\u258C" : " ")
14507
+ /* @__PURE__ */ React18.createElement(Text14, { key: "cursor-eol", color: accentColor }, cursorVisible ? "\u258C" : " ")
14175
14508
  );
14176
14509
  }
14177
- return /* @__PURE__ */ React17.createElement(React17.Fragment, null, out);
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__ */ React17.createElement(Text13, { key: `s-${key}` }, seg.text);
14550
+ return /* @__PURE__ */ React18.createElement(Text14, { key: `s-${key}` }, seg.text);
14218
14551
  }
14219
- return /* @__PURE__ */ React17.createElement(Text13, { key: `s-${key}`, backgroundColor: SURFACE.bgElev, color: FG.body }, seg.label);
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 Box15, Text as Text14, useStdout as useStdout5 } from "ink";
14247
- import React18, { useState as useState8 } from "react";
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] = useState8(0);
14255
- const [renaming, setRenaming] = useState8(null);
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__ */ React18.createElement(Box15, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React18.createElement(Box15, null, /* @__PURE__ */ React18.createElement(Text14, { bold: true, color: TONE.brand }, " \u25C8 REASONIX \xB7 pick a session "), /* @__PURE__ */ React18.createElement(Text14, { color: FG.meta }, ` \xB7 ${workspace2}`)), /* @__PURE__ */ React18.createElement(Box15, { height: 1 }), sessions2.length === 0 ? /* @__PURE__ */ React18.createElement(Box15, null, /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, " no saved sessions in this workspace yet \u2014 press "), /* @__PURE__ */ React18.createElement(Text14, { bold: true, color: TONE.brand }, "\u23CE"), /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, " to start a new one")) : shown.map((s, i) => /* @__PURE__ */ React18.createElement(SessionRow, { key: s.name, info: s, focused: start + i === focus })), hiddenBelow > 0 ? /* @__PURE__ */ React18.createElement(Box15, null, /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, ` \u2026 ${hiddenBelow} more`)) : null, renaming ? /* @__PURE__ */ React18.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, ` rename "${renaming.from}" \u2192 `), /* @__PURE__ */ React18.createElement(Text14, { bold: true, color: TONE.brand }, renaming.buf), /* @__PURE__ */ React18.createElement(Text14, { backgroundColor: TONE.brand, color: "black" }, " ")) : null, /* @__PURE__ */ React18.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React18.createElement(Text14, { 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")));
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__ */ React18.createElement(Box15, null, /* @__PURE__ */ React18.createElement(Text14, { color: focused ? TONE.brand : FG.faint }, focused ? " \u25B8 " : " "), /* @__PURE__ */ React18.createElement(Text14, { bold: focused, color: focused ? FG.strong : FG.sub }, info.name.padEnd(12)), /* @__PURE__ */ React18.createElement(Text14, { color: FG.meta }, ` \xB7 ${branch2.padEnd(8)} \xB7 `), /* @__PURE__ */ React18.createElement(Text14, { color: focused ? FG.body : FG.sub }, truncate2(summary, 40)), /* @__PURE__ */ React18.createElement(Box15, { flexGrow: 1 }), /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, `${time.padStart(11)} `), /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, `${turns} turns`), costCny ? /* @__PURE__ */ React18.createElement(Text14, { color: FG.faint }, ` \xB7 ${costCny}`) : null);
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 Box16, Text as Text15 } from "ink";
14341
- import React19, { useState as useState9 } from "react";
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] = useState9("pick");
14678
+ const [phase, setPhase] = useState10("pick");
14346
14679
  if (phase === "deny") {
14347
- return /* @__PURE__ */ React19.createElement(
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__ */ React19.createElement(
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__ */ React19.createElement(
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__ */ React19.createElement(Box16, { marginBottom: 1 }, /* @__PURE__ */ React19.createElement(Text15, { color: FG.faint }, subtitle)),
14375
- /* @__PURE__ */ React19.createElement(Box16, { marginBottom: 1 }, /* @__PURE__ */ React19.createElement(Text15, { bold: true, color: TONE.err }, "$ "), /* @__PURE__ */ React19.createElement(Text15, { bold: true, color: FG.strong }, command)),
14376
- /* @__PURE__ */ React19.createElement(
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 Box17, Text as Text16 } from "ink";
14437
- import React20 from "react";
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__ */ React20.createElement(Box17, null, /* @__PURE__ */ React20.createElement(Text16, { color: COLOR.accent, bold: true }, "/ "), /* @__PURE__ */ React20.createElement(Text16, { color: COLOR.accent, bold: true }, `/${spec.cmd}`), spec.argsHint ? /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, ` ${spec.argsHint}`) : null, /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, ` ${spec.summary}`));
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__ */ React20.createElement(Box17, { paddingX: 1, marginTop: 1 }, headerRow);
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__ */ React20.createElement(Box17, { flexDirection: "column", paddingX: 1, marginTop: 1 }, headerRow, /* @__PURE__ */ React20.createElement(Box17, null, /* @__PURE__ */ React20.createElement(Text16, { color: COLOR.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React20.createElement(Text16, { color: COLOR.warn }, ` no match for "${partial}"`), /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, " \u2014 keep typing, or Backspace to edit")));
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__ */ React20.createElement(Box17, { flexDirection: "column", paddingX: 1, marginTop: 1 }, headerRow, hiddenAbove > 0 ? /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null, shown.map((value, i) => /* @__PURE__ */ React20.createElement(ArgRow, { key: value, value, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, ` \u2193 ${hiddenBelow} below`) : null, /* @__PURE__ */ React20.createElement(Box17, { marginTop: 0 }, /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, " \u2191\u2193 navigate \xB7 Tab / \u23CE pick \xB7 esc cancel")));
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__ */ React20.createElement(Box17, null, /* @__PURE__ */ React20.createElement(Text16, { color: isSelected ? COLOR.primary : COLOR.info, bold: isSelected }, isSelected ? `${GLYPH.cur} ` : " "), /* @__PURE__ */ React20.createElement(Text16, { color: isSelected ? COLOR.user : COLOR.info, bold: isSelected, dimColor: !isSelected }, value));
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 Box18, Text as Text17 } from "ink";
14467
- import React21 from "react";
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__ */ React21.createElement(Box18, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React21.createElement(Text17, null, " "), /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.warn }, "no slash command matches that prefix"), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, " \u2014 Backspace to edit, or /help for the full list"));
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__ */ React21.createElement(Box18, { flexDirection: "column", paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React21.createElement(Box18, null, /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.accent, bold: true }, "/ "), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, `${total} command${total === 1 ? "" : "s"}`), hiddenAbove > 0 ? /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null), shown.map((spec, i) => /* @__PURE__ */ React21.createElement(SuggestionRow, { key: spec.cmd, spec, 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")));
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__ */ React21.createElement(Box18, null, /* @__PURE__ */ React21.createElement(Text17, { color: isSelected ? COLOR.primary : COLOR.info, bold: isSelected }, isSelected ? `${GLYPH.cur} ` : " "), /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.accent, bold: isSelected }, name.padEnd(14)), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, argsSuffix.padEnd(14)), /* @__PURE__ */ React21.createElement(Text17, null, " "), /* @__PURE__ */ React21.createElement(Text17, { color: isSelected ? COLOR.user : COLOR.info, dimColor: !isSelected }, spec.summary));
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 Box19, Text as Text18, useStdout as useStdout6 } from "ink";
14492
- import React22 from "react";
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__ */ React22.createElement(Box19, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React22.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React22.createElement(Text18, { color: TONE.brand }, top)), /* @__PURE__ */ React22.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React22.createElement(BoxLine, { pad: BOX_INNER_WIDTH }, "")), /* @__PURE__ */ React22.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React22.createElement(BoxLine, { pad: BOX_INNER_WIDTH }, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: TONE.brand }, centerInside("\u25C8 REASONIX", BOX_INNER_WIDTH)))), /* @__PURE__ */ React22.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React22.createElement(BoxLine, { pad: BOX_INNER_WIDTH }, "")), /* @__PURE__ */ React22.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React22.createElement(BoxLine, { pad: BOX_INNER_WIDTH }, /* @__PURE__ */ React22.createElement(Text18, { color: FG.sub }, centerInside(tagline, BOX_INNER_WIDTH)))), /* @__PURE__ */ React22.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React22.createElement(BoxLine, { pad: BOX_INNER_WIDTH }, /* @__PURE__ */ React22.createElement(Text18, { color: FG.meta }, centerInside(TAGLINE_SUB, BOX_INNER_WIDTH)))), /* @__PURE__ */ React22.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React22.createElement(BoxLine, { pad: BOX_INNER_WIDTH }, "")), /* @__PURE__ */ React22.createElement(BoxRow, { indent: boxIndent }, /* @__PURE__ */ React22.createElement(Text18, { color: TONE.brand }, bot)), /* @__PURE__ */ React22.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, null, " ".repeat(startIndent)), /* @__PURE__ */ React22.createElement(Text18, { color: FG.sub }, startTextRaw)), /* @__PURE__ */ React22.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, null, " ".repeat(hintsIndent)), HINTS.map((cmd, i) => /* @__PURE__ */ React22.createElement(React22.Fragment, { key: cmd }, /* @__PURE__ */ React22.createElement(Text18, { color: FG.meta }, cmd), i < HINTS.length - 1 && /* @__PURE__ */ React22.createElement(Text18, { color: FG.faint }, " \xB7 ")))), dashboardUrl ? /* @__PURE__ */ React22.createElement(Box19, { marginTop: 1, flexDirection: "row", justifyContent: "center" }, /* @__PURE__ */ React22.createElement(Text18, { color: TONE.brand, bold: true }, "\u25B8 web \xB7 "), /* @__PURE__ */ React22.createElement(Text18, { color: TONE.accent }, dashboardUrl)) : null);
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__ */ React22.createElement(Box19, null, /* @__PURE__ */ React22.createElement(Text18, null, " ".repeat(indent)), children);
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__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(Text18, { color: TONE.brand }, "\u2551"), /* @__PURE__ */ React22.createElement(Text18, null, " ".repeat(pad3)), /* @__PURE__ */ React22.createElement(Text18, { color: TONE.brand }, "\u2551"));
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__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(Text18, { color: TONE.brand }, "\u2551"), children, /* @__PURE__ */ React22.createElement(Text18, { color: TONE.brand }, "\u2551"));
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 Box22, Text as Text21 } from "ink";
14551
- import React25 from "react";
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 Box20, Text as Text19 } from "ink";
14555
- import React23 from "react";
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__ */ React23.createElement(Box20, { flexDirection: "row" }, /* @__PURE__ */ React23.createElement(Text19, null, " "), /* @__PURE__ */ React23.createElement(Text19, { color: t2.color }, STRUCT.bar), glyph !== void 0 ? /* @__PURE__ */ React23.createElement(Text19, { bold: glyphBold, color: t2.color }, " ", glyph, indent === 3 ? " " : " ") : indent > 0 ? /* @__PURE__ */ React23.createElement(Text19, null, " ".repeat(indent + 1)) : null, children);
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__ */ React23.createElement(Text19, { inverse: on, color: CARD.streaming.color }, " ");
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 Box21, Text as Text20 } from "ink";
14585
- import React24 from "react";
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__ */ React24.createElement(Box21, { flexDirection: "row" }, /* @__PURE__ */ React24.createElement(Text20, null, " "), /* @__PURE__ */ React24.createElement(Text20, { color: bar2 }, STRUCT.bar), /* @__PURE__ */ React24.createElement(Text20, null, " "), /* @__PURE__ */ React24.createElement(Text20, { bold: true, color: t2.color }, glyph), /* @__PURE__ */ React24.createElement(Text20, { bold: true, color: titleColor ?? FG.strong }, ` ${title}`), inline2 && /* @__PURE__ */ React24.createElement(React24.Fragment, null, /* @__PURE__ */ React24.createElement(Text20, null, " "), inline2), subtitle && /* @__PURE__ */ React24.createElement(Text20, { color: FG.sub }, ` ${subtitle}`), /* @__PURE__ */ React24.createElement(Box21, { flexGrow: 1 }), meta && /* @__PURE__ */ React24.createElement(Text20, { color: FG.faint }, meta), trailing && /* @__PURE__ */ React24.createElement(React24.Fragment, null, /* @__PURE__ */ React24.createElement(Text20, null, " "), trailing));
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__ */ React25.createElement(Box22, { flexDirection: "column" }, /* @__PURE__ */ React25.createElement(CardHeader, { tone: "plan", glyph: "\u229E", title: card.title, meta }), /* @__PURE__ */ React25.createElement(BarRow, { tone: "plan", indent: 0 }), card.steps.map((step, i) => {
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__ */ React25.createElement(BarRow, { key: step.id, tone: "plan" }, /* @__PURE__ */ React25.createElement(Text21, { color: STATUS_COLOR[step.status] }, `[${STATUS_GLYPH[step.status]}]`), /* @__PURE__ */ React25.createElement(Text21, { bold: isActive, color: titleColor }, ` ${i + 1}. ${step.title}`), isActive && /* @__PURE__ */ React25.createElement(Text21, { color: TONE.brand }, " \u2190 in progress"));
14629
- }), showFooter && /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(BarRow, { tone: "plan", indent: 0 }), /* @__PURE__ */ React25.createElement(BarRow, { tone: "plan" }, /* @__PURE__ */ React25.createElement(Text21, { color: FG.meta }, ACTIVE_PLAN_FOOTER))));
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 React26 from "react";
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 = React26.createContext(null);
15744
+ var StoreCtx = React27.createContext(null);
15412
15745
  function AgentStoreProvider({
15413
15746
  session,
15414
15747
  initialCards,
15415
15748
  children
15416
15749
  }) {
15417
- const initialCardsRef = React26.useRef(initialCards);
15418
- const store = React26.useMemo(() => createStore(session, initialCardsRef.current), [session]);
15419
- return /* @__PURE__ */ React26.createElement(StoreCtx.Provider, { value: store }, children);
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 = React26.useContext(StoreCtx);
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 = React26.useCallback((cb) => store.subscribe(cb), [store]);
15429
- const getSnapshot = React26.useCallback(() => selector(store.getState()), [store, selector]);
15430
- return React26.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
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 React46 from "react";
16015
+ import React47 from "react";
15683
16016
 
15684
16017
  // src/cli/ui/cards/CardRenderer.tsx
15685
- import { Box as Box40, Text as Text40 } from "ink";
15686
- import React45 from "react";
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 Text22 } from "ink";
15690
- import { Box as Box23 } from "ink";
15691
- import React27 from "react";
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__ */ React27.createElement(Box23, { flexDirection: "column" }, /* @__PURE__ */ React27.createElement(
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__ */ React27.createElement(BarRow, { tone: "streaming", indent: 0 }), /* @__PURE__ */ React27.createElement(BarRow, { tone: "streaming" }, /* @__PURE__ */ React27.createElement(Text22, { color: tone }, "\u2588".repeat(filled)), /* @__PURE__ */ React27.createElement(Text22, { color: FG.faint }, "\u2591".repeat(BAR_CELLS - filled)), /* @__PURE__ */ React27.createElement(Text22, { color: FG.faint }, ` ${(ratio * 100).toFixed(0)}%`)), !card.done && card.completed > 0 && /* @__PURE__ */ React27.createElement(BarRow, { tone: "streaming" }, /* @__PURE__ */ React27.createElement(Text22, { color: FG.faint }, `latest: #${card.latestIndex} \xB7 T=${card.latestTemperature.toFixed(2)} \xB7 ${card.latestUncertainties} unc`)));
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 Box24, Text as Text23 } from "ink";
15711
- import React28 from "react";
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__ */ React28.createElement(BarRow, { tone: "usage" }, /* @__PURE__ */ React28.createElement(Text23, { color: FG.sub }, label.padEnd(8)), /* @__PURE__ */ React28.createElement(Text23, { color: color2 }, "\u2588".repeat(filled)), /* @__PURE__ */ React28.createElement(Text23, { color: FG.faint }, "\u2591".repeat(BAR_CELLS2 - filled)), /* @__PURE__ */ React28.createElement(Text23, { bold: true, color: FG.body }, ` ${tokens.toLocaleString()}`), /* @__PURE__ */ React28.createElement(Text23, { color: FG.faint }, ` ${(ratio * 100).toFixed(1)}%`));
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__ */ React28.createElement(Box24, { flexDirection: "column" }, /* @__PURE__ */ React28.createElement(Box24, { flexDirection: "row" }, /* @__PURE__ */ React28.createElement(Text23, null, " "), /* @__PURE__ */ React28.createElement(Text23, { bold: true, color: CARD.usage.color }, "\u2318 Context window"), /* @__PURE__ */ React28.createElement(Text23, { color: FG.faint }, ` \xB7 ${used.toLocaleString()} / ${cap.toLocaleString()} (${usedPct.toFixed(1)}%)`)), /* @__PURE__ */ React28.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__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(BarRow, { tone: "usage", indent: 0 }), /* @__PURE__ */ React28.createElement(BarRow, { tone: "usage" }, /* @__PURE__ */ React28.createElement(Text23, { color: FG.faint }, `top tools (${card.toolsCount} total \xB7 ${card.logMessages} log msgs):`)), card.topTools.slice(0, 5).map((t2) => /* @__PURE__ */ React28.createElement(BarRow, { key: `${t2.turn}-${t2.name}`, tone: "usage" }, /* @__PURE__ */ React28.createElement(Text23, { color: FG.sub }, ` ${t2.name}`), /* @__PURE__ */ React28.createElement(Text23, { color: FG.faint }, ` \xB7 turn ${t2.turn} \xB7 ${t2.tokens.toLocaleString()}`)))));
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 Box25, Text as Text24 } from "ink";
15726
- import React29 from "react";
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__ */ React29.createElement(React29.Fragment, null, /* @__PURE__ */ React29.createElement(Text24, { color: TONE.ok }, `+${card.stats.add}`), /* @__PURE__ */ React29.createElement(Text24, { color: FG.faint }, " / "), /* @__PURE__ */ React29.createElement(Text24, { color: TONE.err }, `-${card.stats.del}`));
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__ */ React29.createElement(Box25, { flexDirection: "column" }, /* @__PURE__ */ React29.createElement(CardHeader, { tone: "diff", glyph: "\xB1", title: "Edit", subtitle: card.file, trailing: meta }), card.hunks.map((hunk) => /* @__PURE__ */ React29.createElement(Box25, { key: `${card.id}:${hunk.header}`, flexDirection: "column" }, /* @__PURE__ */ React29.createElement(BarRow, { tone: "diff", indent: 0 }), /* @__PURE__ */ React29.createElement(BarRow, { tone: "diff" }, /* @__PURE__ */ React29.createElement(Text24, { italic: true, color: FG.faint }, hunk.header)), hunk.lines.map((line, li) => /* @__PURE__ */ React29.createElement(BarRow, { key: `${card.id}:${hunk.header}:${li}`, tone: "diff" }, /* @__PURE__ */ React29.createElement(Text24, { color: LINE_COLOR[line.kind] }, line.text))))), showFooter && /* @__PURE__ */ React29.createElement(React29.Fragment, null, /* @__PURE__ */ React29.createElement(BarRow, { tone: "diff", indent: 0 }), /* @__PURE__ */ React29.createElement(BarRow, { tone: "diff" }, /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: TONE.ok }, "[a] apply"), /* @__PURE__ */ React29.createElement(Text24, { color: FG.sub }, " [s] skip "), /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: TONE.err }, "[r] reject"))));
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 Box26, Text as Text25 } from "ink";
15741
- import React30 from "react";
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__ */ React30.createElement(Box26, { flexDirection: "column" }, /* @__PURE__ */ React30.createElement(CardHeader, { tone: "tool", glyph: "\u2695", title: "Doctor", meta: summary, barColor: CARD.tool.color }), /* @__PURE__ */ React30.createElement(BarRow, { tone: "tool", indent: 0 }), card.checks.map((c) => /* @__PURE__ */ React30.createElement(BarRow, { key: c.label, tone: "tool" }, /* @__PURE__ */ React30.createElement(Text25, { color: LEVEL_COLOR[c.level] }, LEVEL_GLYPH[c.level]), /* @__PURE__ */ React30.createElement(Text25, { bold: true, color: FG.body }, ` ${c.label.padEnd(labelWidth + 1)}`), /* @__PURE__ */ React30.createElement(Text25, { color: FG.sub }, c.detail), /* @__PURE__ */ React30.createElement(Text25, { color: LEVEL_COLOR[c.level] }, ` ${LEVEL_TAG[c.level]}`))));
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 Box27, Text as Text26 } from "ink";
15768
- import React31 from "react";
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__ */ React31.createElement(Box27, { flexDirection: "column" }, /* @__PURE__ */ React31.createElement(CardHeader, { tone: "error", glyph: "\u2716", title: "Error", subtitle: card.title, meta }), /* @__PURE__ */ React31.createElement(BarRow, { tone: "error", indent: 0 }), card.message.split("\n").map((line, i) => /* @__PURE__ */ React31.createElement(BarRow, { key: `${card.id}:msg:${i}`, tone: "error" }, /* @__PURE__ */ React31.createElement(Text26, { color: CARD.error.color }, line))), hasStack && /* @__PURE__ */ React31.createElement(React31.Fragment, null, /* @__PURE__ */ React31.createElement(BarRow, { tone: "error", indent: 0 }), /* @__PURE__ */ React31.createElement(BarRow, { tone: "error" }, /* @__PURE__ */ React31.createElement(Text26, { color: FG.meta }, "stack trace")), stackHidden > 0 && /* @__PURE__ */ React31.createElement(BarRow, { tone: "error" }, /* @__PURE__ */ React31.createElement(Text26, { color: FG.faint }, `\u22EE ${stackHidden} earlier stack line${stackHidden === 1 ? "" : "s"} hidden`)), stackVisible.map((line, i) => /* @__PURE__ */ React31.createElement(BarRow, { key: `${card.id}:stk:${stackHidden + i}`, tone: "error" }, /* @__PURE__ */ React31.createElement(Text26, { color: FG.meta }, line)))), /* @__PURE__ */ React31.createElement(BarRow, { tone: "error", indent: 0 }), /* @__PURE__ */ React31.createElement(BarRow, { tone: "error" }, /* @__PURE__ */ React31.createElement(Text26, { bold: true, color: TONE.err }, "[r] retry"), /* @__PURE__ */ React31.createElement(Text26, { color: FG.sub }, " [s] skip")));
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 Box28, Text as Text28 } from "ink";
15782
- import React33 from "react";
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 Text27 } from "ink";
15786
- import React32 from "react";
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] = React32.useState(0);
15798
- React32.useEffect(() => {
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__ */ React32.createElement(Text27, { bold, color: color2 }, frames[frame]);
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__ */ React33.createElement(Box28, { flexDirection: "row" }, /* @__PURE__ */ React33.createElement(Text28, null, " "), card.variant === "thinking" ? /* @__PURE__ */ React33.createElement(Spinner, { kind: "circle", color: color2, bold: true }) : /* @__PURE__ */ React33.createElement(Text28, { bold: true, color: color2 }, glyph), /* @__PURE__ */ React33.createElement(Text28, { color: FG.body }, ` ${card.text}`), card.meta !== void 0 && /* @__PURE__ */ React33.createElement(Text28, { color: FG.faint }, ` ${card.meta}`));
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 Box29, Text as Text29 } from "ink";
15834
- import React34 from "react";
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__ */ React34.createElement(Box29, { flexDirection: "column" }, /* @__PURE__ */ React34.createElement(
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__ */ React34.createElement(Box29, { key: category, flexDirection: "column" }, /* @__PURE__ */ React34.createElement(BarRow, { tone: "memory", indent: 0 }), /* @__PURE__ */ React34.createElement(BarRow, { tone: "memory" }, /* @__PURE__ */ React34.createElement(Text29, { color: FG.faint }, CATEGORY_LABEL[category], " (", counts[category], ")")), shown.map((entry) => /* @__PURE__ */ React34.createElement(BarRow, { key: `${category}:${entry.summary}`, tone: "memory" }, /* @__PURE__ */ React34.createElement(Text29, { color: CATEGORY_GLYPH_COLOR[category] }, CATEGORY_GLYPH[category], " "), /* @__PURE__ */ React34.createElement(Text29, { color: FG.sub }, entry.summary))), remaining > 0 && /* @__PURE__ */ React34.createElement(BarRow, { tone: "memory" }, /* @__PURE__ */ React34.createElement(Text29, { color: FG.faint }, `\u22EE +${remaining} more`)));
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 Box30, Text as Text30, useStdout as useStdout7 } from "ink";
15893
- import React35 from "react";
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__ */ React35.createElement(Box30, { flexDirection: "column" }, /* @__PURE__ */ React35.createElement(CardHeader, { tone: "reasoning", glyph: "\u25C6", title: "Reasoning", meta: `\xB7 ${meta}` }), showBody && /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement(BarRow, { tone: "reasoning", indent: 0 }), headDropped > 0 && /* @__PURE__ */ React35.createElement(BarRow, { tone: "reasoning" }, /* @__PURE__ */ React35.createElement(Text30, { 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) => {
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__ */ React35.createElement(BarRow, { key: `${card.id}:${headDropped + i}`, tone: "reasoning" }, /* @__PURE__ */ React35.createElement(Text30, { italic: true, color: FG.meta }, clipToCells(line, lineCells)), isLast && card.streaming && /* @__PURE__ */ React35.createElement(CursorBlock, null));
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 Box31, Text as Text31 } from "ink";
15950
- import React36 from "react";
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__ */ React36.createElement(Box31, { flexDirection: "column" }, /* @__PURE__ */ React36.createElement(CardHeader, { tone: "search", glyph: "\u2299", title: "Search", subtitle: `"${card.query}"`, meta }), card.hits.length > 0 && /* @__PURE__ */ React36.createElement(React36.Fragment, null, /* @__PURE__ */ React36.createElement(BarRow, { tone: "search", indent: 0 }), groupByFile(card.hits.slice(0, 10)).map(([file, hits]) => /* @__PURE__ */ React36.createElement(Box31, { key: file, flexDirection: "column" }, /* @__PURE__ */ React36.createElement(BarRow, { tone: "search" }, /* @__PURE__ */ React36.createElement(Text31, { bold: true, color: FG.strong }, file)), hits.map((h, i) => /* @__PURE__ */ React36.createElement(BarRow, { key: `${file}:${h.line}:${i}`, tone: "search" }, /* @__PURE__ */ React36.createElement(Text31, { color: FG.faint }, `${h.line.toString().padStart(4)} \u2502 `), /* @__PURE__ */ React36.createElement(HighlightedLine, { text: h.preview, start: h.matchStart, end: h.matchEnd }))))), card.hits.length > 10 && /* @__PURE__ */ React36.createElement(BarRow, { tone: "search" }, /* @__PURE__ */ React36.createElement(Text31, { color: FG.faint }, `\u22EE +${card.hits.length - 10} more hits`))));
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__ */ React36.createElement(Text31, { color: FG.sub }, text);
16295
+ return /* @__PURE__ */ React37.createElement(Text32, { color: FG.sub }, text);
15963
16296
  }
15964
- return /* @__PURE__ */ React36.createElement(React36.Fragment, null, /* @__PURE__ */ React36.createElement(Text31, { color: FG.sub }, text.slice(0, start)), /* @__PURE__ */ React36.createElement(Text31, { bold: true, inverse: true }, text.slice(start, end)), /* @__PURE__ */ React36.createElement(Text31, { color: FG.sub }, text.slice(end)));
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 Box33, Text as Text33, useStdout as useStdout8 } from "ink";
15978
- import React38 from "react";
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 Box32, Text as Text32 } from "ink";
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 React37 from "react";
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 = React37.useMemo(() => marked.lexer(text), [text]);
18004
- return /* @__PURE__ */ React37.createElement(Box32, { flexDirection: "column", gap: 1 }, tokens.map((token, i) => /* @__PURE__ */ React37.createElement(BlockToken, { key: `${i}-${token.type}`, token })));
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__ */ React37.createElement(Heading, { token });
18342
+ return /* @__PURE__ */ React38.createElement(Heading, { token });
18010
18343
  case "paragraph":
18011
- return /* @__PURE__ */ React37.createElement(Paragraph, { token });
18344
+ return /* @__PURE__ */ React38.createElement(Paragraph, { token });
18012
18345
  case "list":
18013
- return /* @__PURE__ */ React37.createElement(List, { token, depth: 0 });
18346
+ return /* @__PURE__ */ React38.createElement(List, { token, depth: 0 });
18014
18347
  case "code":
18015
- return /* @__PURE__ */ React37.createElement(CodeBlock, { token });
18348
+ return /* @__PURE__ */ React38.createElement(CodeBlock, { token });
18016
18349
  case "blockquote":
18017
- return /* @__PURE__ */ React37.createElement(Blockquote, { token });
18350
+ return /* @__PURE__ */ React38.createElement(Blockquote, { token });
18018
18351
  case "hr":
18019
- return /* @__PURE__ */ React37.createElement(HorizontalRule, null);
18352
+ return /* @__PURE__ */ React38.createElement(HorizontalRule, null);
18020
18353
  case "table":
18021
- return /* @__PURE__ */ React37.createElement(Table, { token });
18354
+ return /* @__PURE__ */ React38.createElement(Table, { token });
18022
18355
  case "html":
18023
- return /* @__PURE__ */ React37.createElement(Text32, { color: FG.body }, token.text);
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__ */ React37.createElement(Text32, { color: FG.body }, token.raw ?? "");
18360
+ return /* @__PURE__ */ React38.createElement(Text33, { color: FG.body }, token.raw ?? "");
18028
18361
  }
18029
18362
  }
18030
18363
  function Heading({ token }) {
18031
- return /* @__PURE__ */ React37.createElement(Box32, null, /* @__PURE__ */ React37.createElement(Text32, { bold: true, color: FG.strong, backgroundColor: SURFACE.bgElev }, ` ${plainText(token.tokens)} `));
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__ */ React37.createElement(Text32, { color: FG.body }, /* @__PURE__ */ React37.createElement(Inline, { tokens: token.tokens ?? [] }));
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__ */ React37.createElement(Box32, { flexDirection: "column" }, token.items.map((item, i) => /* @__PURE__ */ React37.createElement(
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__ */ React37.createElement(Box32, null, /* @__PURE__ */ React37.createElement(Text32, { color: markerColor }, `${indent}${marker} `), /* @__PURE__ */ React37.createElement(Box32, { flexDirection: "column" }, item.tokens.map((tok, i) => {
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__ */ React37.createElement(Text32, { key: `t-${i}`, color: dim ? FG.faint : FG.body, strikethrough: dim }, inner ? /* @__PURE__ */ React37.createElement(Inline, { tokens: inner }) : tok.text)
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__ */ React37.createElement(List, { key: `l-${i}`, token: tok, depth: depth + 1 });
18400
+ return /* @__PURE__ */ React38.createElement(List, { key: `l-${i}`, token: tok, depth: depth + 1 });
18068
18401
  }
18069
- return /* @__PURE__ */ React37.createElement(BlockToken, { key: `b-${i}-${tok.type}`, token: tok });
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__ */ React37.createElement(Box32, { flexDirection: "column" }, lang ? /* @__PURE__ */ React37.createElement(Box32, null, /* @__PURE__ */ React37.createElement(Text32, { color: FG.meta }, ` ${lang}`)) : null, /* @__PURE__ */ React37.createElement(Box32, { flexDirection: "column" }, lines.map((line, i) => (
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__ */ React37.createElement(Text32, { key: `code-${i}`, backgroundColor: SURFACE.bgElev }, ` ${line} `)
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__ */ React37.createElement(Box32, { flexDirection: "column" }, (token.tokens ?? []).map((child, i) => /* @__PURE__ */ React37.createElement(Box32, { key: `${i}-${child.type}`, flexDirection: "row" }, /* @__PURE__ */ React37.createElement(Text32, { color: TONE.brand }, " \u258E "), /* @__PURE__ */ React37.createElement(Box32, { flexDirection: "column", flexGrow: 1 }, child.type === "paragraph" ? /* @__PURE__ */ React37.createElement(Text32, { italic: true, color: FG.sub }, /* @__PURE__ */ React37.createElement(Inline, { tokens: child.tokens ?? [] })) : /* @__PURE__ */ React37.createElement(BlockToken, { token: child })))));
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__ */ React37.createElement(Text32, { 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");
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__ */ React37.createElement(Box32, { flexDirection: "column" }, /* @__PURE__ */ React37.createElement(Box32, null, /* @__PURE__ */ React37.createElement(Text32, null, " "), headerCells.map((cell, i) => (
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__ */ React37.createElement(React37.Fragment, { key: `h-${i}` }, /* @__PURE__ */ React37.createElement(Text32, { bold: true, color: FG.sub }, padToCells(cell, widths[i])), i < colCount - 1 ? /* @__PURE__ */ React37.createElement(Text32, null, GAP) : null)
18112
- ))), /* @__PURE__ */ React37.createElement(Box32, null, /* @__PURE__ */ React37.createElement(Text32, null, " "), /* @__PURE__ */ React37.createElement(Text32, { color: FG.faint }, ruleRow)), bodyCells.map((row3, ri) => (
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__ */ React37.createElement(Box32, { key: `tr-${ri}` }, /* @__PURE__ */ React37.createElement(Text32, null, " "), row3.map((cell, i) => (
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__ */ React37.createElement(React37.Fragment, { key: `c-${ri}-${i}` }, /* @__PURE__ */ React37.createElement(Text32, { color: FG.body }, padToCells(cell ?? "", widths[i])), i < colCount - 1 ? /* @__PURE__ */ React37.createElement(Text32, null, GAP) : null)
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__ */ React37.createElement(React37.Fragment, null, tokens.map((tok, i) => /* @__PURE__ */ React37.createElement(InlineToken, { key: `${i}-${tok.type}`, token: tok })));
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__ */ React37.createElement(Text32, { color: color2, underline: true }, `${open}${label}${close}`);
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__ */ React37.createElement(Text32, null, raw);
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__ */ React37.createElement(Text32, { color: TONE.warn, underline: true }, `@${path5}`)
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__ */ React37.createElement(Text32, { key: `t-${key++}` }, raw.slice(cursor, h.start)));
18491
+ out.push(/* @__PURE__ */ React38.createElement(Text33, { key: `t-${key++}` }, raw.slice(cursor, h.start)));
18159
18492
  }
18160
- out.push(/* @__PURE__ */ React37.createElement(React37.Fragment, { key: `r-${key++}` }, h.node));
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__ */ React37.createElement(Text32, { key: `t-${key++}` }, raw.slice(cursor)));
18164
- return /* @__PURE__ */ React37.createElement(React37.Fragment, null, out);
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__ */ React37.createElement(Inline, { tokens: t2.tokens }) : renderInlineText(t2.text);
18503
+ return t2.tokens ? /* @__PURE__ */ React38.createElement(Inline, { tokens: t2.tokens }) : renderInlineText(t2.text);
18171
18504
  }
18172
18505
  case "strong":
18173
- return /* @__PURE__ */ React37.createElement(Text32, { bold: true, color: FG.strong }, /* @__PURE__ */ React37.createElement(Inline, { tokens: token.tokens }));
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__ */ React37.createElement(Text32, { italic: true }, /* @__PURE__ */ React37.createElement(Inline, { tokens: token.tokens }));
18508
+ return /* @__PURE__ */ React38.createElement(Text33, { italic: true }, /* @__PURE__ */ React38.createElement(Inline, { tokens: token.tokens }));
18176
18509
  case "codespan":
18177
- return /* @__PURE__ */ React37.createElement(Text32, { color: FG.strong, backgroundColor: SURFACE.bgElev }, ` ${token.text} `);
18510
+ return /* @__PURE__ */ React38.createElement(Text33, { color: FG.strong, backgroundColor: SURFACE.bgElev }, ` ${token.text} `);
18178
18511
  case "del":
18179
- return /* @__PURE__ */ React37.createElement(Text32, { color: TONE.err, strikethrough: true }, /* @__PURE__ */ React37.createElement(Inline, { tokens: token.tokens }));
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__ */ React37.createElement(Text32, { color: TONE.brand, underline: true }, /* @__PURE__ */ React37.createElement(Inline, { tokens: l.tokens }));
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__ */ React37.createElement(Text32, { color: TONE.brand }, `[image: ${im.text || im.href}]`);
18519
+ return /* @__PURE__ */ React38.createElement(Text33, { color: TONE.brand }, `[image: ${im.text || im.href}]`);
18187
18520
  }
18188
18521
  case "br":
18189
- return /* @__PURE__ */ React37.createElement(Text32, null, "\n");
18522
+ return /* @__PURE__ */ React38.createElement(Text33, null, "\n");
18190
18523
  case "escape":
18191
- return /* @__PURE__ */ React37.createElement(Text32, null, token.text);
18524
+ return /* @__PURE__ */ React38.createElement(Text33, null, token.text);
18192
18525
  case "html":
18193
- return /* @__PURE__ */ React37.createElement(Text32, null, token.text);
18526
+ return /* @__PURE__ */ React38.createElement(Text33, null, token.text);
18194
18527
  default:
18195
- return /* @__PURE__ */ React37.createElement(Text32, null, token.raw ?? "");
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__ */ React38.createElement(Box33, { flexDirection: "column", paddingLeft: 3 }, /* @__PURE__ */ React38.createElement(Markdown, { text: card.text }));
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__ */ React38.createElement(Box33, { flexDirection: "column" }, card.aborted && /* @__PURE__ */ React38.createElement(BarRow, { tone: "streaming", glyph: "\u2014" }, /* @__PURE__ */ React38.createElement(Text33, { color: FG.faint, bold: true }, "\u2014 aborted \u2014"), /* @__PURE__ */ React38.createElement(Text33, { color: TONE.warn }, " stopped")), headDropped > 0 && /* @__PURE__ */ React38.createElement(BarRow, { tone: "streaming", glyph: "\u25BE" }, /* @__PURE__ */ React38.createElement(
18247
- Text33,
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__ */ React38.createElement(
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__ */ React38.createElement(Text33, { color: card.aborted ? FG.meta : FG.body }, clipToCells(line, lineCells)),
18263
- isLast && !card.done && /* @__PURE__ */ React38.createElement(CursorBlock, null)
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__ */ React38.createElement(BarRow, { tone: "streaming" }, /* @__PURE__ */ React38.createElement(Text33, { color: FG.faint }, "[truncated by esc]")));
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 Box34, Text as Text34 } from "ink";
18270
- import React39 from "react";
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__ */ React39.createElement(Box34, { flexDirection: "column" }, /* @__PURE__ */ React39.createElement(
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__ */ React39.createElement(Text34, { color: STATUS_COLOR2[card.status] }, card.status)
18616
+ trailing: /* @__PURE__ */ React40.createElement(Text35, { color: STATUS_COLOR2[card.status] }, card.status)
18284
18617
  }
18285
- ), /* @__PURE__ */ React39.createElement(BarRow, { tone: "subagent", indent: 0 }), /* @__PURE__ */ React39.createElement(BarRow, { tone: "subagent" }, /* @__PURE__ */ React39.createElement(Text34, { color: FG.faint }, "Task "), /* @__PURE__ */ React39.createElement(Text34, { color: FG.sub }, card.task)), card.tools && card.tools.length > 0 && /* @__PURE__ */ React39.createElement(BarRow, { tone: "subagent" }, /* @__PURE__ */ React39.createElement(Text34, { color: FG.faint }, "Tools "), /* @__PURE__ */ React39.createElement(Text34, { color: FG.sub }, card.tools.join(", "))), card.children.length > 0 && /* @__PURE__ */ React39.createElement(React39.Fragment, null, /* @__PURE__ */ React39.createElement(BarRow, { tone: "subagent", indent: 0 }), /* @__PURE__ */ React39.createElement(BarRow, { tone: "subagent" }, /* @__PURE__ */ React39.createElement(Text34, { color: FG.meta }, "sub-agent stream")), card.children.map((child) => /* @__PURE__ */ React39.createElement(BarRow, { key: child.id, tone: "subagent" }, /* @__PURE__ */ React39.createElement(Text34, { color: CARD.subagent.color }, "\u258E "), /* @__PURE__ */ React39.createElement(ChildSummary, { card: child })))));
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__ */ React39.createElement(React39.Fragment, null, /* @__PURE__ */ React39.createElement(Text34, { color: CARD.reasoning.color }, "\u25C6 "), /* @__PURE__ */ React39.createElement(Text34, { italic: true, color: FG.meta }, `Reasoning \xB7 ${card.paragraphs} paragraph${card.paragraphs === 1 ? "" : "s"}`));
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__ */ React39.createElement(React39.Fragment, null, /* @__PURE__ */ React39.createElement(Text34, { color: CARD.tool.color }, "\u25A3 "), /* @__PURE__ */ React39.createElement(Text34, { bold: true, color: FG.body }, card.name), card.elapsedMs > 0 && /* @__PURE__ */ React39.createElement(Text34, { color: FG.faint }, ` ${(card.elapsedMs / 1e3).toFixed(2)}s`));
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__ */ React39.createElement(React39.Fragment, null, /* @__PURE__ */ React39.createElement(Text34, { color: CARD.streaming.color }, "\u25B6 "), /* @__PURE__ */ React39.createElement(Text34, { color: card.done ? FG.sub : TONE.brand }, card.done ? "response" : "streaming response \u2026"));
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__ */ React39.createElement(React39.Fragment, null, /* @__PURE__ */ React39.createElement(Text34, { color: CARD.diff.color }, "\xB1 "), /* @__PURE__ */ React39.createElement(Text34, { color: FG.sub }, card.file));
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__ */ React39.createElement(React39.Fragment, null, /* @__PURE__ */ React39.createElement(Text34, { color: CARD.error.color }, "\u2716 "), /* @__PURE__ */ React39.createElement(Text34, { color: FG.sub }, card.title));
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__ */ React39.createElement(Text34, { color: FG.faint }, `\xB7 ${card.kind}`);
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 Box35, Text as Text35 } from "ink";
18306
- import React40 from "react";
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__ */ React40.createElement(Box35, { flexDirection: "column" }, /* @__PURE__ */ React40.createElement(
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__ */ React40.createElement(Text35, { color: TASK_COLOR[card.status] }, card.status),
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__ */ React40.createElement(React40.Fragment, null, /* @__PURE__ */ React40.createElement(BarRow, { tone: "task", indent: 0 }), card.steps.map((step) => /* @__PURE__ */ React40.createElement(BarRow, { key: step.id, tone: "task" }, /* @__PURE__ */ React40.createElement(Text35, { color: STEP_COLOR[step.status] }, STEP_GLYPH[step.status]), /* @__PURE__ */ React40.createElement(Text35, { bold: true, color: FG.body }, ` ${(step.toolName ?? "step").padEnd(7)} `), /* @__PURE__ */ React40.createElement(Text35, { color: FG.sub }, step.title), step.detail && /* @__PURE__ */ React40.createElement(Text35, { color: FG.faint }, ` ${step.detail}`), step.elapsedMs !== void 0 && /* @__PURE__ */ React40.createElement(Text35, { color: FG.faint }, ` ${(step.elapsedMs / 1e3).toFixed(2)}s`)))));
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 Box36, Text as Text36, useStdout as useStdout9 } from "ink";
18347
- import React41 from "react";
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__ */ React41.createElement(Box36, { flexDirection: "column" }, /* @__PURE__ */ React41.createElement(
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__ */ React41.createElement(Spinner, { kind: "braille", color: CARD.tool.color, bold: true }) : void 0,
18377
- trailing: card.retry ? /* @__PURE__ */ React41.createElement(Text36, { color: TONE.warn, bold: true }, `\u21BB retry ${card.retry.attempt}/${card.retry.max}`) : void 0
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__ */ React41.createElement(React41.Fragment, null, /* @__PURE__ */ React41.createElement(BarRow, { tone: "tool", indent: 0 }), hidden > 0 && /* @__PURE__ */ React41.createElement(BarRow, { tone: "tool" }, /* @__PURE__ */ React41.createElement(Text36, { color: FG.faint }, `\u22EE ${hidden} earlier line${hidden === 1 ? "" : "s"} (use /tool to read full)`)), visible.map((line, i) => /* @__PURE__ */ React41.createElement(BarRow, { key: `${card.id}:${hidden + i}`, tone: "tool" }, /* @__PURE__ */ React41.createElement(Text36, { color: errColor }, clipToCells(line, lineCells))))));
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 Box37, Text as Text37 } from "ink";
18412
- import React42 from "react";
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__ */ React42.createElement(React42.Fragment, null, /* @__PURE__ */ React42.createElement(Text37, { color: color2 }, "\u2588".repeat(filled)), /* @__PURE__ */ React42.createElement(Text37, { color: FG.faint }, "\u2591".repeat(empty)));
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__ */ React42.createElement(CompactUsageRow, { card });
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__ */ React42.createElement(Box37, { flexDirection: "column" }, /* @__PURE__ */ React42.createElement(CardHeader, { tone: "usage", glyph: "\u03A3", title: "Usage", subtitle: `turn ${card.turn}`, meta }), /* @__PURE__ */ React42.createElement(BarRow, { tone: "usage", indent: 0 }), /* @__PURE__ */ React42.createElement(BarRow, { tone: "usage" }, /* @__PURE__ */ React42.createElement(Text37, { color: FG.sub }, "prompt "), bar(promptRatio, TONE.brand), /* @__PURE__ */ React42.createElement(Text37, { bold: true, color: FG.body }, ` ${card.tokens.prompt.toLocaleString()}`), /* @__PURE__ */ React42.createElement(Text37, { color: FG.faint }, ` / 1M \xB7 ${(promptRatio * 100).toFixed(1)}%`)), /* @__PURE__ */ React42.createElement(BarRow, { tone: "usage" }, /* @__PURE__ */ React42.createElement(Text37, { color: FG.sub }, "reason "), bar(reasonRatio, TONE.accent), /* @__PURE__ */ React42.createElement(Text37, { bold: true, color: FG.body }, ` ${card.tokens.reason.toLocaleString()}`)), /* @__PURE__ */ React42.createElement(BarRow, { tone: "usage" }, /* @__PURE__ */ React42.createElement(Text37, { color: FG.sub }, "output "), bar(outputRatio, TONE.brand), /* @__PURE__ */ React42.createElement(Text37, { bold: true, color: FG.body }, ` ${card.tokens.output.toLocaleString()}`)), /* @__PURE__ */ React42.createElement(BarRow, { tone: "usage", indent: 0 }), /* @__PURE__ */ React42.createElement(BarRow, { tone: "usage" }, /* @__PURE__ */ React42.createElement(Text37, { color: FG.sub }, "cache hit "), bar(card.cacheHit, TONE.ok), /* @__PURE__ */ React42.createElement(Text37, { bold: true, color: TONE.ok }, ` ${(card.cacheHit * 100).toFixed(1)}%`)), /* @__PURE__ */ React42.createElement(BarRow, { tone: "usage", indent: 0 }), /* @__PURE__ */ React42.createElement(BarRow, { tone: "usage" }, /* @__PURE__ */ React42.createElement(Text37, { color: FG.faint }, "session "), /* @__PURE__ */ React42.createElement(Text37, { bold: true, color: FG.body }, `\u26C1 ${formatCNY(card.sessionCost, 3)}`), card.balance !== void 0 && /* @__PURE__ */ React42.createElement(React42.Fragment, null, /* @__PURE__ */ React42.createElement(Text37, { color: FG.meta }, " \xB7 "), /* @__PURE__ */ React42.createElement(Text37, { color: FG.faint }, "balance "), /* @__PURE__ */ React42.createElement(Text37, { bold: true, color: TONE.brand }, `\xA5${card.balance.toFixed(2)}`))));
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__ */ React42.createElement(Box37, null, /* @__PURE__ */ React42.createElement(Text37, { color: FG.faint }, ` \u03A3 turn ${card.turn} \xB7 `), /* @__PURE__ */ React42.createElement(
18437
- Text37,
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__ */ React42.createElement(Text37, { color: FG.faint }, " \xB7 cache "), /* @__PURE__ */ React42.createElement(Text37, { color: TONE.ok }, `${(card.cacheHit * 100).toFixed(0)}%`), /* @__PURE__ */ React42.createElement(Text37, { color: FG.faint }, ` \xB7 ${formatCNY(card.cost)}${elapsed}`), card.balance !== void 0 && /* @__PURE__ */ React42.createElement(React42.Fragment, null, /* @__PURE__ */ React42.createElement(Text37, { color: FG.faint }, " \xB7 "), /* @__PURE__ */ React42.createElement(Text37, { color: TONE.brand }, `\xA5${card.balance.toFixed(2)}`)));
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 Box38, Text as Text38 } from "ink";
18447
- import React43 from "react";
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__ */ React43.createElement(Box38, { flexDirection: "column" }, /* @__PURE__ */ React43.createElement(Box38, { flexDirection: "row" }, /* @__PURE__ */ React43.createElement(Text38, null, " "), /* @__PURE__ */ React43.createElement(Text38, { color: FG.meta }, "\u25C7"), /* @__PURE__ */ React43.createElement(Text38, { bold: true, color: FG.sub }, " you"), /* @__PURE__ */ React43.createElement(Text38, { color: FG.faint }, ` \xB7 ${formatRelativeTime(card.ts)}`)), /* @__PURE__ */ React43.createElement(Box38, { flexDirection: "column", paddingLeft: 4 }, /* @__PURE__ */ React43.createElement(Markdown, { text: card.text })));
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 Box39, Text as Text39 } from "ink";
18469
- import React44 from "react";
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__ */ React44.createElement(Box39, { flexDirection: "column" }, /* @__PURE__ */ React44.createElement(
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__ */ React44.createElement(React44.Fragment, null, /* @__PURE__ */ React44.createElement(BarRow, { tone: "warn", indent: 0 }), card.message.split("\n").map((line, i) => /* @__PURE__ */ React44.createElement(BarRow, { key: `${card.id}:${i}`, tone: "warn" }, /* @__PURE__ */ React44.createElement(Text39, { color: FG.body }, line)))));
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__ */ React45.createElement(Box40, { flexDirection: "column", marginTop: 1 }, renderCard(card, contentStreaming));
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__ */ React45.createElement(UserCard, { card });
18826
+ return /* @__PURE__ */ React46.createElement(UserCard, { card });
18494
18827
  case "reasoning":
18495
- return /* @__PURE__ */ React45.createElement(ReasoningCard, { card, expanded: !(card.streaming && contentStreaming) });
18828
+ return /* @__PURE__ */ React46.createElement(ReasoningCard, { card, expanded: !(card.streaming && contentStreaming) });
18496
18829
  case "streaming":
18497
- return /* @__PURE__ */ React45.createElement(StreamingCard, { card });
18830
+ return /* @__PURE__ */ React46.createElement(StreamingCard, { card });
18498
18831
  case "tool":
18499
- return /* @__PURE__ */ React45.createElement(ToolCard, { card });
18832
+ return /* @__PURE__ */ React46.createElement(ToolCard, { card });
18500
18833
  case "task":
18501
- return /* @__PURE__ */ React45.createElement(TaskCard, { card });
18834
+ return /* @__PURE__ */ React46.createElement(TaskCard, { card });
18502
18835
  case "plan":
18503
- return /* @__PURE__ */ React45.createElement(PlanCard, { card });
18836
+ return /* @__PURE__ */ React46.createElement(PlanCard, { card });
18504
18837
  case "diff":
18505
- return /* @__PURE__ */ React45.createElement(DiffCard, { card });
18838
+ return /* @__PURE__ */ React46.createElement(DiffCard, { card });
18506
18839
  case "error":
18507
- return /* @__PURE__ */ React45.createElement(ErrorCard, { card });
18840
+ return /* @__PURE__ */ React46.createElement(ErrorCard, { card });
18508
18841
  case "warn":
18509
- return /* @__PURE__ */ React45.createElement(WarnCard, { card });
18842
+ return /* @__PURE__ */ React46.createElement(WarnCard, { card });
18510
18843
  case "usage":
18511
- return /* @__PURE__ */ React45.createElement(UsageCard, { card });
18844
+ return /* @__PURE__ */ React46.createElement(UsageCard, { card });
18512
18845
  case "memory":
18513
- return /* @__PURE__ */ React45.createElement(MemoryCard, { card });
18846
+ return /* @__PURE__ */ React46.createElement(MemoryCard, { card });
18514
18847
  case "subagent":
18515
- return /* @__PURE__ */ React45.createElement(SubAgentCard, { card });
18848
+ return /* @__PURE__ */ React46.createElement(SubAgentCard, { card });
18516
18849
  case "search":
18517
- return /* @__PURE__ */ React45.createElement(SearchCard, { card });
18850
+ return /* @__PURE__ */ React46.createElement(SearchCard, { card });
18518
18851
  case "approval":
18519
- return /* @__PURE__ */ React45.createElement(FallbackCard, { card });
18852
+ return /* @__PURE__ */ React46.createElement(FallbackCard, { card });
18520
18853
  case "live":
18521
- return /* @__PURE__ */ React45.createElement(LiveCard, { card });
18854
+ return /* @__PURE__ */ React46.createElement(LiveCard, { card });
18522
18855
  case "ctx":
18523
- return /* @__PURE__ */ React45.createElement(CtxCard, { card });
18856
+ return /* @__PURE__ */ React46.createElement(CtxCard, { card });
18524
18857
  case "doctor":
18525
- return /* @__PURE__ */ React45.createElement(DoctorCard, { card });
18858
+ return /* @__PURE__ */ React46.createElement(DoctorCard, { card });
18526
18859
  case "branch":
18527
- return /* @__PURE__ */ React45.createElement(BranchCard, { card });
18860
+ return /* @__PURE__ */ React46.createElement(BranchCard, { card });
18528
18861
  default:
18529
- return /* @__PURE__ */ React45.createElement(FallbackCard, { card });
18862
+ return /* @__PURE__ */ React46.createElement(FallbackCard, { card });
18530
18863
  }
18531
18864
  }
18532
18865
  function FallbackCard({ card }) {
18533
- return /* @__PURE__ */ React45.createElement(Box40, { flexDirection: "row" }, /* @__PURE__ */ React45.createElement(Text40, { color: FG.faint }, ` \xB7 ${card.kind} card \xB7 not yet migrated`));
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__ */ React46.createElement(React46.Fragment, null, /* @__PURE__ */ React46.createElement(Static, { items: committed }, (card) => /* @__PURE__ */ React46.createElement(CardRenderer, { key: card.id, card })), live.map((card) => /* @__PURE__ */ React46.createElement(CardRenderer, { key: card.id, card })));
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 Box41, Text as Text41, useStdout as useStdout10 } from "ink";
18569
- import React47 from "react";
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__ */ React47.createElement(Box41, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React47.createElement(Spinner, { kind: "circle", color: TONE.brand, bold: true }), /* @__PURE__ */ React47.createElement(Text41, null, " "), /* @__PURE__ */ React47.createElement(Text41, { color: TONE.brand }, text), /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, ` \xB7 ${elapsed}s`));
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__ */ React47.createElement(Text41, { color: TONE.warn, bold: true }, ` \xB7 \u23F5 ${running} job${running === 1 ? "" : "s"}`) : null;
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__ */ React47.createElement(ModeBarFrame, null, /* @__PURE__ */ React47.createElement(ModePill, { label: "PLAN MODE", color: TONE.err, flash }), /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, " writes gated \xB7 /plan off to leave"), jobsTag);
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__ */ React47.createElement(ModeBarFrame, null, /* @__PURE__ */ React47.createElement(ModePill, { label, color: pillColor, flash }), /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, ` ${mid} \xB7 Shift+Tab to flip`), jobsTag);
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__ */ React47.createElement(Box41, { flexDirection: "column" }, /* @__PURE__ */ React47.createElement(Box41, { paddingX: 1 }, /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, "\u254C".repeat(ruleWidth))), /* @__PURE__ */ React47.createElement(Box41, { paddingX: 1 }, children));
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__ */ React47.createElement(Text41, { color: color2, bold: true, inverse: flash }, `[${label}]`);
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__ */ React47.createElement(Box41, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React47.createElement(Text41, { backgroundColor: TONE.accent, color: "black", bold: true }, ` \u2713 AUTO-APPLIED ${ok}/${total} `), /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, " press "), /* @__PURE__ */ React47.createElement(Text41, { backgroundColor: TONE.brand, color: "black", bold: true }, " u "), /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, " to undo "), /* @__PURE__ */ React47.createElement(CharBar, { pct: pct2, width: 20, color: tone, showLabel: false }), /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, " "), /* @__PURE__ */ React47.createElement(Text41, { color: tone, bold: urgent }, `${remainingSec}s`));
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__ */ React47.createElement(Box41, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React47.createElement(Box41, null, /* @__PURE__ */ React47.createElement(Text41, null, " "), /* @__PURE__ */ React47.createElement(Text41, { color: CARD.subagent.color }, "\u258E "), /* @__PURE__ */ React47.createElement(Text41, { bold: true, color: CARD.subagent.color }, `\u232C ${subagentTitle(activity.skillName, activity.task)}`), /* @__PURE__ */ React47.createElement(Box41, { flexGrow: 1 }), /* @__PURE__ */ React47.createElement(Text41, { color: CARD.subagent.color }, `iter ${activity.iter} \xB7 ${seconds}s`), /* @__PURE__ */ React47.createElement(Text41, null, " "), /* @__PURE__ */ React47.createElement(Text41, { color: CARD.subagent.color, bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length])), /* @__PURE__ */ React47.createElement(Box41, null, /* @__PURE__ */ React47.createElement(Text41, null, " "), /* @__PURE__ */ React47.createElement(Text41, { color: CARD.subagent.color }, "\u258E")), /* @__PURE__ */ React47.createElement(Box41, null, /* @__PURE__ */ React47.createElement(Text41, null, " "), /* @__PURE__ */ React47.createElement(Text41, { color: CARD.subagent.color }, "\u258E "), /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, "Task "), /* @__PURE__ */ React47.createElement(Text41, { color: FG.sub }, activity.task)), /* @__PURE__ */ React47.createElement(Box41, null, /* @__PURE__ */ React47.createElement(Text41, null, " "), /* @__PURE__ */ React47.createElement(Text41, { color: CARD.subagent.color }, "\u258E "), /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, "Model "), /* @__PURE__ */ React47.createElement(Text41, { color: FG.sub }, activity.model ?? "\u2014")), /* @__PURE__ */ React47.createElement(Box41, null, /* @__PURE__ */ React47.createElement(Text41, null, " "), /* @__PURE__ */ React47.createElement(Text41, { color: CARD.subagent.color }, "\u258E")), /* @__PURE__ */ React47.createElement(Box41, null, /* @__PURE__ */ React47.createElement(Text41, null, " "), /* @__PURE__ */ React47.createElement(Text41, { color: CARD.subagent.color }, "\u258E "), /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, "Last "), last ? /* @__PURE__ */ React47.createElement(React47.Fragment, null, /* @__PURE__ */ React47.createElement(Text41, { color: last.color }, `${last.glyph} `), /* @__PURE__ */ React47.createElement(Text41, { color: FG.body }, last.label), last.meta ? /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, ` ${last.meta}`) : null) : /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, "queued\u2026")), /* @__PURE__ */ React47.createElement(Box41, null, /* @__PURE__ */ React47.createElement(Text41, null, " "), /* @__PURE__ */ React47.createElement(Text41, { color: CARD.subagent.color }, "\u258E")), /* @__PURE__ */ React47.createElement(Box41, null, /* @__PURE__ */ React47.createElement(Text41, null, " "), /* @__PURE__ */ React47.createElement(Text41, { color: CARD.subagent.color }, "\u258E "), /* @__PURE__ */ React47.createElement(Text41, { bold: true, color: TONE.brand }, "\u25B6 "), /* @__PURE__ */ React47.createElement(Text41, { color: TONE.brand }, phase)));
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__ */ React47.createElement(Box41, { marginY: 1, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React47.createElement(Box41, null, /* @__PURE__ */ React47.createElement(Text41, { color: CARD.tool.color, bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React47.createElement(Text41, null, " "), /* @__PURE__ */ React47.createElement(Text41, { color: CARD.tool.color, bold: true }, `\u25A3 ${tool2.name}`), /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, ` running \xB7 ${elapsed}s`)), progress ? /* @__PURE__ */ React47.createElement(Box41, { paddingLeft: 3 }, /* @__PURE__ */ React47.createElement(Text41, { color: TONE.brand }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ React47.createElement(Box41, { paddingLeft: 3 }, /* @__PURE__ */ React47.createElement(Text41, { color: FG.faint }, summary)) : null);
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 Box42, Text as Text43, useStdout as useStdout11 } from "ink";
18705
- import React49 from "react";
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 Text42 } from "ink";
18709
- import React48 from "react";
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__ */ React48.createElement(Text42, { bold: true, color: color2 }, String(remainingSec));
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__ */ React49.createElement(Box42, { flexDirection: "column" }, /* @__PURE__ */ React49.createElement(Box42, null, /* @__PURE__ */ React49.createElement(Text43, null, " "), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, "\u2500".repeat(ruleWidth))), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row" }, /* @__PURE__ */ React49.createElement(Text43, null, " "), status3.recording ? /* @__PURE__ */ React49.createElement(RecordingPill, { rec: status3.recording }) : status3.countdownSeconds !== void 0 ? /* @__PURE__ */ React49.createElement(CountdownRow, { mode: status3.mode, secondsLeft: status3.countdownSeconds }) : /* @__PURE__ */ React49.createElement(ModePill2, { mode: status3.mode, network: status3.network, detail: status3.networkDetail }), /* @__PURE__ */ React49.createElement(Sep, null), /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, `${session.id} \xB7 ${session.branch}`), hasTurn && /* @__PURE__ */ React49.createElement(React49.Fragment, null, /* @__PURE__ */ React49.createElement(Sep, null), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: TONE.brand }, "\u25B8 "), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, `\xA5${turnCny.toFixed(4)} turn`)), /* @__PURE__ */ React49.createElement(Sep, null), /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, `\xA5${sessionCny.toFixed(3)} session`), status3.balance !== void 0 && /* @__PURE__ */ React49.createElement(React49.Fragment, null, /* @__PURE__ */ React49.createElement(Sep, null), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, "wallet "), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: balanceColor(status3.balance) }, `\xA5${status3.balance.toFixed(2)}`)), /* @__PURE__ */ React49.createElement(Sep, null), /* @__PURE__ */ React49.createElement(Text43, { color: TONE.accent }, `cache ${Math.round(status3.cacheHit * 100)}%`)));
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__ */ React49.createElement(Box42, { flexDirection: "row" }, /* @__PURE__ */ React49.createElement(Text43, { color: pill.color }, pill.glyph), /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, ` ${mode2}`));
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__ */ React49.createElement(Box42, { flexDirection: "row" }, /* @__PURE__ */ React49.createElement(Text43, { color: dot2.color }, dot2.glyph), /* @__PURE__ */ React49.createElement(Text43, { color: dot2.color }, ` ${mode2} \xB7 slow${tail}`));
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__ */ React49.createElement(Box42, { flexDirection: "row" }, /* @__PURE__ */ React49.createElement(Text43, { color: dot2.color }, dot2.glyph), /* @__PURE__ */ React49.createElement(Text43, { color: dot2.color }, ` disconnect${tail}`));
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__ */ React49.createElement(Box42, { flexDirection: "row" }, /* @__PURE__ */ React49.createElement(Text43, { color: dot2.color }, dot2.glyph), /* @__PURE__ */ React49.createElement(Text43, { color: dot2.color }, " reconnecting\u2026"));
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__ */ React49.createElement(Box42, { flexDirection: "row" }, /* @__PURE__ */ React49.createElement(Text43, { color: pill.color }, pill.glyph), /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, ` ${mode2} \xB7 `), /* @__PURE__ */ React49.createElement(Text43, { color: TONE.warn }, "approving in "), /* @__PURE__ */ React49.createElement(Countdown, { endsAt }), /* @__PURE__ */ React49.createElement(Text43, { color: TONE.warn }, "s \xB7 esc to interrupt"));
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__ */ React49.createElement(Box42, { flexDirection: "row" }, /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: TONE.err }, "\u25CFREC"), /* @__PURE__ */ React49.createElement(Text43, { color: TONE.err }, ` ${sizeMb} MB \xB7 ${rec.events} evt`));
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__ */ React49.createElement(Text43, { color: FG.meta }, " \xB7 ");
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 Box43, Text as Text44, useStdout as useStdout12 } from "ink";
18797
- import React50, { useEffect as useEffect3 } from "react";
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__ */ React50.createElement(Box43, { flexDirection: "column" }, visible.map((t2) => {
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__ */ React50.createElement(Box43, { key: t2.id, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React50.createElement(Text44, { color: color2 }, rule), /* @__PURE__ */ React50.createElement(Box43, { flexDirection: "row" }, /* @__PURE__ */ React50.createElement(Text44, { color: color2 }, glyph), /* @__PURE__ */ React50.createElement(Text44, { bold: true, color: body }, ` ${t2.title}`), t2.detail !== void 0 && /* @__PURE__ */ React50.createElement(Text44, { color: FG.sub }, ` \xB7 ${t2.detail}`), /* @__PURE__ */ React50.createElement(Box43, { flexGrow: 1 }), /* @__PURE__ */ React50.createElement(Text44, { color: FG.faint }, `${remainingSec}s`)));
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 = (_args, loop2, ctx) => {
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 = healthBadge(report.elapsedMs);
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 healthBadge(elapsedMs) {
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 Box44, Text as Text46 } from "ink";
20923
- import React52 from "react";
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 Text45, useStdout as useStdout13 } from "ink";
20927
- import React51 from "react";
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__ */ React51.createElement(Text45, { dimColor: true }, "\u2500".repeat(w));
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__ */ React51.createElement(Text45, null, /* @__PURE__ */ React51.createElement(Text45, { color: color2, dimColor: dim }, "\u25B0".repeat(filled)), /* @__PURE__ */ React51.createElement(Text45, { dimColor: true }, "\u25B1".repeat(cells - filled)));
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 useState10 } from "react";
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] = useState10(0);
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] = useState10(0);
21982
- const [atFiles, setAtFiles] = useState10([]);
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] = useState10(0);
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 useState11 } from "react";
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] = useState11(null);
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 useState12 } from "react";
22723
+ import { useCallback as useCallback4, useEffect as useEffect5, useState as useState13 } from "react";
22324
22724
  function useSessionInfo(loop2) {
22325
- const [balance, setBalance] = useState12(null);
22326
- const [models2, setModels] = useState12(null);
22327
- const [latestVersion, setLatestVersion] = useState12(null);
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 useState13 } from "react";
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] = useState13(null);
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] = React53.useState(0);
22507
- React53.useEffect(() => {
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__ */ React53.createElement(Box45, null, /* @__PURE__ */ React53.createElement(Text47, { color: "cyan" }, `\u25B8 ${formatLoopStatus(loop2.prompt, nextFireMs, loop2.iter)} \xB7 /loop stop or type to cancel`));
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 = React53.useMemo(
22920
+ const initialCards = React54.useMemo(
22521
22921
  () => props.session ? hydrateCardsFromMessages(loadSessionMessages(props.session)) : [],
22522
22922
  [props.session]
22523
22923
  );
22524
- return /* @__PURE__ */ React53.createElement(AgentStoreProvider, { session, initialCards }, /* @__PURE__ */ React53.createElement(AppInner, { ...props }));
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] = useState14("");
22558
- const [busy, setBusy] = useState14(false);
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] = useState14(null);
22564
- const [toolProgress, setToolProgress] = useState14(null);
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] = useState14(false);
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] = useState14(null);
22598
- const [currentRootDir, setCurrentRootDir] = useState14(
22997
+ const [statusLine, setStatusLine] = useState15(null);
22998
+ const [currentRootDir, setCurrentRootDir] = useState15(
22599
22999
  () => codeMode?.rootDir ?? process.cwd()
22600
23000
  );
22601
- const [hookList, setHookList] = useState14(
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] = useState14(0);
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] = useState14(() => codeMode ? loadEditMode() : "review");
22622
- const [preset2, setPreset] = useState14(() => {
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] = useState14(null);
22635
- const [walkthroughActive, setWalkthroughActive] = useState14(false);
22636
- const [pendingTick, setPendingTick] = useState14(0);
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] = useState14(false);
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] = useState14(null);
22653
- const [pendingPlan, setPendingPlan] = useState14(null);
22654
- const [pendingReviseEditor, setPendingReviseEditor] = useState14(null);
22655
- const [pendingSessionsPicker, setPendingSessionsPicker] = useState14(false);
22656
- const [sessionsPickerList, setSessionsPickerList] = useState14([]);
22657
- const [stagedInput, setStagedInput] = useState14(null);
22658
- const [pendingCheckpoint, setPendingCheckpoint] = useState14(null);
22659
- const [stagedCheckpointRevise, setStagedCheckpointRevise] = useState14(null);
22660
- const [pendingRevision, setPendingRevision] = useState14(null);
22661
- const [pendingChoice, setPendingChoice] = useState14(null);
22662
- const [stagedChoiceCustom, setStagedChoiceCustom] = useState14(null);
22663
- const [planMode, setPlanMode] = useState14(false);
22664
- const [proArmed, setProArmed] = useState14(false);
22665
- const [turnOnPro, setTurnOnPro] = useState14(false);
22666
- const [queuedSubmit, setQueuedSubmit] = useState14(null);
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] = useState14(null);
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] = useState14({
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] = useState14(null);
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__ */ React53.createElement(React53.Fragment, null, /* @__PURE__ */ React53.createElement(
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__ */ React53.createElement(Box45, { flexDirection: "column" }, /* @__PURE__ */ React53.createElement(Box45, { flexDirection: "column" }, /* @__PURE__ */ React53.createElement(CardStream, { excludeId: activePlanCard?.id }), !hasConversation && !busy && !isStreaming ? /* @__PURE__ */ React53.createElement(WelcomeBanner, { inCodeMode: !!codeMode, dashboardUrl }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && ongoingTool ? /* @__PURE__ */ React53.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && subagentActivity ? /* @__PURE__ */ React53.createElement(SubagentRow, { activity: subagentActivity }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !ongoingTool && statusLine ? /* @__PURE__ */ React53.createElement(ThinkingRow, { text: statusLine }) : null, !PLAIN_UI && undoBanner && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision ? /* @__PURE__ */ React53.createElement(UndoBanner, { banner: undoBanner }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && busy && !isStreaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React53.createElement(ThinkingRow, { text: "processing\u2026" }) : null, /* @__PURE__ */ React53.createElement(ToastRail, null)), !PLAIN_UI && activePlanCard ? /* @__PURE__ */ React53.createElement(Box45, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React53.createElement(PlanCard, { card: activePlanCard })) : null, stagedInput ? /* @__PURE__ */ React53.createElement(
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__ */ React53.createElement(
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__ */ React53.createElement(
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__ */ React53.createElement(
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__ */ React53.createElement(
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__ */ React53.createElement(
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__ */ React53.createElement(
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
- ) : pendingPlan ? /* @__PURE__ */ React53.createElement(
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__ */ React53.createElement(
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__ */ React53.createElement(
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__ */ React53.createElement(
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__ */ React53.createElement(
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__ */ React53.createElement(React53.Fragment, null, codeMode ? /* @__PURE__ */ React53.createElement(
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__ */ React53.createElement(LoopStatusRow, { loop: activeLoop }) : null, /* @__PURE__ */ React53.createElement(StatusRow, null), /* @__PURE__ */ React53.createElement(
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__ */ React53.createElement(SlashSuggestions, { matches: slashMatches, selectedIndex: slashSelected }) : null, atMatches !== null ? /* @__PURE__ */ React53.createElement(
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__ */ React53.createElement(
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 Box46, Text as Text48, useApp } from "ink";
25038
+ import { Box as Box47, Text as Text49, useApp } from "ink";
24624
25039
  import TextInput from "ink-text-input";
24625
- import React54, { useState as useState15 } from "react";
25040
+ import React55, { useState as useState16 } from "react";
24626
25041
  function Setup({ onReady }) {
24627
- const [value, setValue] = useState15("");
24628
- const [error, setError] = useState15(null);
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__ */ React54.createElement(Box46, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React54.createElement(Box46, null, /* @__PURE__ */ React54.createElement(Text48, { bold: true, color: GRADIENT[0] }, GLYPH.brand), /* @__PURE__ */ React54.createElement(Text48, null, " "), /* @__PURE__ */ React54.createElement(Text48, { bold: true }, "Welcome to "), /* @__PURE__ */ React54.createElement(Text48, { bold: true, color: GRADIENT[2] }, "REASONIX")), /* @__PURE__ */ React54.createElement(Box46, { marginTop: 1 }, /* @__PURE__ */ React54.createElement(Text48, { color: COLOR.info }, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React54.createElement(Box46, null, /* @__PURE__ */ React54.createElement(Text48, { dimColor: true }, " sign up at \xB7 "), /* @__PURE__ */ React54.createElement(Text48, { color: COLOR.primary }, "https://platform.deepseek.com/api_keys")), /* @__PURE__ */ React54.createElement(Box46, null, /* @__PURE__ */ React54.createElement(Text48, { dimColor: true }, " saved to "), /* @__PURE__ */ React54.createElement(Text48, { dimColor: true }, defaultConfigPath())), /* @__PURE__ */ React54.createElement(Box46, { marginTop: 1 }, /* @__PURE__ */ React54.createElement(Text48, { bold: true, color: COLOR.brand }, GLYPH.bar), /* @__PURE__ */ React54.createElement(Text48, { bold: true, color: COLOR.primary }, " \u203A "), /* @__PURE__ */ React54.createElement(
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__ */ React54.createElement(Box46, { marginTop: 1 }, /* @__PURE__ */ React54.createElement(Text48, { color: COLOR.err, bold: true }, GLYPH.err), /* @__PURE__ */ React54.createElement(Text48, { color: COLOR.err }, ` ${error}`)) : value ? /* @__PURE__ */ React54.createElement(Box46, { marginTop: 1 }, /* @__PURE__ */ React54.createElement(Text48, { dimColor: true }, ` preview \xB7 ${redactKey(value)}`)) : null, /* @__PURE__ */ React54.createElement(Box46, { marginTop: 1 }, /* @__PURE__ */ React54.createElement(Text48, { dimColor: true }, " /exit to abort")));
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] = useState16(initialKey);
24672
- const [pickerOpen, setPickerOpen] = useState16(showPicker);
24673
- const [activeSession, setActiveSession] = useState16(appProps.session);
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] = useState16(() => listSessionsForWorkspace(workspaceRoot));
25096
+ const [sessions2, setSessions] = useState17(() => listSessionsForWorkspace(workspaceRoot));
24676
25097
  if (!key) {
24677
- return /* @__PURE__ */ React55.createElement(
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__ */ React55.createElement(KeystrokeProvider, null, /* @__PURE__ */ React55.createElement(
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__ */ React55.createElement(KeystrokeProvider, null, /* @__PURE__ */ React55.createElement(
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
- onProgress: (info) => progressSink.current?.(info)
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 label = spec.name ?? "anon";
24782
- const source = spec.transport === "sse" || spec.transport === "streamable-http" ? spec.url : `${spec.command} ${spec.args.join(" ")}`;
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
- `\u25B8 MCP[${label}]: ${bridge.registeredNames.length} tool(s) from ${source}
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
- client: mcp3
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
- `\u25B8 MCP setup SKIPPED for "${raw}": ${reason}
24801
- \u2192 this server will not be available this session. Run \`reasonix setup\` to remove it, or fix the underlying issue (missing npm package, network, etc.).
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__ */ React55.createElement(
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 React59 from "react";
25652
+ import React60 from "react";
25205
25653
 
25206
25654
  // src/cli/ui/DiffApp.tsx
25207
- import { Box as Box49, Static as Static2, Text as Text51, useApp as useApp2, useInput as useInput2 } from "ink";
25208
- import React58, { useState as useState17 } from "react";
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 Box48, Text as Text50 } from "ink";
25212
- import React57 from "react";
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 Box47, Text as Text49 } from "ink";
25216
- import React56 from "react";
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__ */ React56.createElement(Box47, { flexDirection: "column", marginBottom: 1 }, fields.map(([label, items, color2, dim]) => /* @__PURE__ */ React56.createElement(Box47, { key: label }, /* @__PURE__ */ React56.createElement(Text49, { color: color2, bold: true, dimColor: dim }, label), /* @__PURE__ */ React56.createElement(Text49, { dimColor: true }, ` (${items.length})`), /* @__PURE__ */ React56.createElement(Text49, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React56.createElement(Text49, { dimColor: dim, color: dim ? void 0 : COLOR.info }, items.join(" \xB7 ")))));
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__ */ React57.createElement(Box48, { marginTop: 1 }, /* @__PURE__ */ React57.createElement(Text50, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React57.createElement(Text50, null, content));
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__ */ React57.createElement(Box48, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React57.createElement(Box48, null, /* @__PURE__ */ React57.createElement(Text50, { bold: true, color: "green" }, "assistant"), rec.cost !== void 0 ? /* @__PURE__ */ React57.createElement(Text50, { dimColor: true }, " $", rec.cost.toFixed(6)) : null, rec.usage ? /* @__PURE__ */ React57.createElement(CacheBadge, { usage: rec.usage }) : null), rec.planState ? /* @__PURE__ */ React57.createElement(PlanStateBlock, { planState: rec.planState }) : null, rec.content ? /* @__PURE__ */ React57.createElement(Text50, null, rec.content) : /* @__PURE__ */ React57.createElement(Text50, { dimColor: true, italic: true }, "(tool-call response only)"));
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__ */ React57.createElement(Box48, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React57.createElement(Text50, { color: "yellow" }, "tool<", rec.tool ?? "?", ">"), rec.args ? /* @__PURE__ */ React57.createElement(Text50, { dimColor: true }, " args: ", truncate3(rec.args, toolArgsMax)) : null, /* @__PURE__ */ React57.createElement(Text50, { dimColor: true }, " \u2192 ", truncate3(rec.content, toolContentMax)));
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__ */ React57.createElement(Box48, { marginTop: 1 }, /* @__PURE__ */ React57.createElement(Text50, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React57.createElement(Text50, { color: "red" }, rec.error ?? rec.content));
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__ */ React57.createElement(Box48, null, /* @__PURE__ */ React57.createElement(Text50, { dimColor: true }, "[", rec.role, "] ", rec.content));
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__ */ React57.createElement(Text50, null, /* @__PURE__ */ React57.createElement(Text50, { dimColor: true }, " \xB7 cache "), /* @__PURE__ */ React57.createElement(Text50, { color: color2 }, pct2.toFixed(1), "%"));
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] = useState17(Math.max(0, initialIdx));
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__ */ React58.createElement(Box49, { flexDirection: "column" }, /* @__PURE__ */ React58.createElement(DiffHeader, { report }), /* @__PURE__ */ React58.createElement(Box49, { marginTop: 1, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ React58.createElement(Text51, { color: "cyan", bold: true }, "turn ", pair?.turn ?? "?", " (", idx + 1, " / ", report.pairs.length, ")"), /* @__PURE__ */ React58.createElement(Text51, null, pair ? /* @__PURE__ */ React58.createElement(KindBadge, { kind: pair.kind }) : null)), /* @__PURE__ */ React58.createElement(Box49, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React58.createElement(Pane, { label: report.a.label, headerColor: "blue", records: paneRecords(pair, "a") }), /* @__PURE__ */ React58.createElement(Pane, { label: report.b.label, headerColor: "magenta", records: paneRecords(pair, "b") })), pair?.divergenceNote ? /* @__PURE__ */ React58.createElement(Box49, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React58.createElement(Text51, { color: "yellow" }, "\u2605 "), /* @__PURE__ */ React58.createElement(Text51, null, pair.divergenceNote)) : null, /* @__PURE__ */ React58.createElement(Box49, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, /* @__PURE__ */ React58.createElement(Text51, { bold: true }, "j"), "/", /* @__PURE__ */ React58.createElement(Text51, { bold: true }, "\u2193"), " next \xB7 ", /* @__PURE__ */ React58.createElement(Text51, { bold: true }, "k"), "/", /* @__PURE__ */ React58.createElement(Text51, { bold: true }, "\u2191"), " ", "prev \xB7 ", /* @__PURE__ */ React58.createElement(Text51, { bold: true }, "n"), " next-diverge \xB7 ", /* @__PURE__ */ React58.createElement(Text51, { bold: true }, "N"), "/", /* @__PURE__ */ React58.createElement(Text51, { bold: true }, "p"), " ", "prev-diverge \xB7 ", /* @__PURE__ */ React58.createElement(Text51, { bold: true }, "g"), "/", /* @__PURE__ */ React58.createElement(Text51, { bold: true }, "G"), " first/last \xB7 ", /* @__PURE__ */ React58.createElement(Text51, { bold: true }, "q"), " ", "quit")));
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__ */ React58.createElement(Box49, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React58.createElement(Box49, { justifyContent: "space-between" }, /* @__PURE__ */ React58.createElement(Text51, null, /* @__PURE__ */ React58.createElement(Text51, { color: "cyan", bold: true }, "reasonix diff"), /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, " \xB7 A="), /* @__PURE__ */ React58.createElement(Text51, { color: "blue" }, a.label), /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, " vs B="), /* @__PURE__ */ React58.createElement(Text51, { color: "magenta" }, b.label)), /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, report.pairs.length, " turns aligned")), /* @__PURE__ */ React58.createElement(Box49, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React58.createElement(Text51, null, /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, "cache "), /* @__PURE__ */ React58.createElement(Text51, null, (a.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React58.createElement(Text51, null, (b.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React58.createElement(Text51, { color: cacheDelta >= 0 ? "green" : "red", bold: true }, " ", cacheDelta >= 0 ? "+" : "", (cacheDelta * 100).toFixed(1), "pp")), /* @__PURE__ */ React58.createElement(Text51, null, /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, "cost "), /* @__PURE__ */ React58.createElement(Text51, null, "$", a.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React58.createElement(Text51, null, "$", b.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React58.createElement(Text51, { color: costDelta2 <= 0 ? "green" : "red", bold: true }, " ", costDelta2 >= 0 ? "+" : "", costDelta2.toFixed(1), "%")), /* @__PURE__ */ React58.createElement(Text51, null, /* @__PURE__ */ React58.createElement(Text51, { dimColor: true }, "model calls "), /* @__PURE__ */ React58.createElement(Text51, null, a.stats.turns, " \u2192 ", b.stats.turns))), prefixLine ? /* @__PURE__ */ React58.createElement(Box49, { marginTop: 1 }, /* @__PURE__ */ React58.createElement(Text51, { dimColor: true, italic: true }, prefixLine)) : null);
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__ */ React58.createElement(
25320
- Box49,
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__ */ React58.createElement(Text51, { color: headerColor, bold: true }, label),
25329
- records.length === 0 ? /* @__PURE__ */ React58.createElement(Box49, { marginTop: 1 }, /* @__PURE__ */ React58.createElement(Text51, { dimColor: true, italic: true }, "(no records on this side for this turn)")) : /* @__PURE__ */ React58.createElement(Static2, { items: records.map((rec, i) => ({ key: `${label}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React58.createElement(RecordView, { key, rec, compact: true }))
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__ */ React58.createElement(Text51, { color: "green" }, "\u2713 match");
25782
+ return /* @__PURE__ */ React59.createElement(Text52, { color: "green" }, "\u2713 match");
25335
25783
  }
25336
25784
  if (kind === "diverge") {
25337
- return /* @__PURE__ */ React58.createElement(Text51, { color: "yellow" }, "\u2605 diverge");
25785
+ return /* @__PURE__ */ React59.createElement(Text52, { color: "yellow" }, "\u2605 diverge");
25338
25786
  }
25339
25787
  if (kind === "only_in_a") {
25340
- return /* @__PURE__ */ React58.createElement(Text51, { color: "blue" }, "\u2190 only in A");
25788
+ return /* @__PURE__ */ React59.createElement(Text52, { color: "blue" }, "\u2190 only in A");
25341
25789
  }
25342
- return /* @__PURE__ */ React58.createElement(Text51, { color: "magenta" }, "\u2192 only in B");
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(React59.createElement(DiffApp, { report }), {
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 React62 from "react";
26492
+ import React63 from "react";
26045
26493
 
26046
26494
  // src/cli/ui/ReplayApp.tsx
26047
- import { Box as Box51, Static as Static3, Text as Text53, useApp as useApp3, useInput as useInput3 } from "ink";
26048
- import React61, { useMemo as useMemo7, useState as useState18 } from "react";
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 Box50, Text as Text52, useStdout as useStdout15 } from "ink";
26053
- import React60 from "react";
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__ */ React60.createElement(Box50, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React60.createElement(
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__ */ React60.createElement(ChromeRule, null), budgetUsd !== null && budgetUsd !== void 0 ? /* @__PURE__ */ React60.createElement(BudgetRow, { spent: summary.totalCostUsd, cap: budgetUsd }) : null);
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__ */ React60.createElement(Box50, null, /* @__PURE__ */ React60.createElement(Text52, { bold: true, color: GRADIENT[0] }, "\u25C8 "), /* @__PURE__ */ React60.createElement(Text52, { color: COLOR.brand, bold: true }, "reasonix"), projectName ? /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(Text52, { color: COLOR.info, dimColor: true }, " \xB7 "), /* @__PURE__ */ React60.createElement(Text52, null, projectName), showSession && sessionName ? /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(Text52, { color: COLOR.info, dimColor: true }, " \u203A "), /* @__PURE__ */ React60.createElement(Text52, { color: COLOR.info }, sessionName)) : null) : null, /* @__PURE__ */ React60.createElement(Box50, { flexGrow: 1 }), showUpdate ? /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(Text52, { color: COLOR.warn, bold: true }, updateLabel), /* @__PURE__ */ React60.createElement(Text52, null, " ")) : null, modePill ? /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(Text52, { color: modePill.color, bold: true }, `[${modePill.label}]`), /* @__PURE__ */ React60.createElement(Text52, null, " ")) : null, proPill ? /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(Text52, { color: proPill.color, bold: true }, `[${proPill.label}]`), /* @__PURE__ */ React60.createElement(Text52, null, " ")) : null, /* @__PURE__ */ React60.createElement(
26129
- Text52,
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__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(Text52, null, " "), /* @__PURE__ */ React60.createElement(Text52, { color: balance.total < 1 ? COLOR.err : balance.total < 5 ? COLOR.warn : COLOR.ok }, balanceLabel)) : null, showCache ? /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(Text52, null, " "), /* @__PURE__ */ React60.createElement(Text52, { dimColor: true }, "["), /* @__PURE__ */ React60.createElement(Text52, { dimColor: true }, "c "), /* @__PURE__ */ React60.createElement(
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__ */ React60.createElement(Text52, null, " "), /* @__PURE__ */ React60.createElement(Text52, { color: coldStart ? void 0 : cacheColor, dimColor: coldStart }, coldStart && summary.turns === 0 ? "\u2014" : `${cachePct}%`), /* @__PURE__ */ React60.createElement(Text52, { dimColor: true }, "]")) : null);
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__ */ React60.createElement(Box50, null, /* @__PURE__ */ React60.createElement(Text52, { dimColor: true }, " budget "), /* @__PURE__ */ React60.createElement(Text52, { color: color2 }, `$${spent.toFixed(4)} / $${cap.toFixed(2)}`, /* @__PURE__ */ React60.createElement(Text52, { dimColor: true }, ` (${pct2.toFixed(0)}%)`)));
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] = useState18(maxIdx);
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__ */ React61.createElement(Box51, { flexDirection: "column" }, /* @__PURE__ */ React61.createElement(StatsPanel, { summary }), /* @__PURE__ */ React61.createElement(Box51, { flexDirection: "column", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React61.createElement(Box51, { justifyContent: "space-between" }, /* @__PURE__ */ React61.createElement(Text53, { color: "cyan", bold: true }, progressLabel), meta ? /* @__PURE__ */ React61.createElement(Text53, { dimColor: true }, meta.source, meta.task ? ` \xB7 ${meta.task}` : "", meta.mode ? ` \xB7 ${meta.mode}` : "") : null), currentPage ? /* @__PURE__ */ React61.createElement(Static3, { items: currentPage.records.map((rec, i) => ({ key: `${idx}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React61.createElement(RecordView, { key, rec })) : /* @__PURE__ */ React61.createElement(Text53, { dimColor: true, italic: true }, "no records")), /* @__PURE__ */ React61.createElement(Box51, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React61.createElement(Text53, { dimColor: true }, /* @__PURE__ */ React61.createElement(Text53, { bold: true }, "j"), "/", /* @__PURE__ */ React61.createElement(Text53, { bold: true }, "\u2193"), "/", /* @__PURE__ */ React61.createElement(Text53, { bold: true }, "space"), " next \xB7 ", /* @__PURE__ */ React61.createElement(Text53, { bold: true }, "k"), "/", /* @__PURE__ */ React61.createElement(Text53, { bold: true }, "\u2191"), " prev \xB7 ", /* @__PURE__ */ React61.createElement(Text53, { bold: true }, "g"), " first \xB7 ", /* @__PURE__ */ React61.createElement(Text53, { bold: true }, "G"), " last \xB7", " ", /* @__PURE__ */ React61.createElement(Text53, { bold: true }, "q"), " quit")));
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(React62.createElement(ReplayApp, { meta: parsed.meta, pages }), {
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, { registry: tools, namePrefix: prefix2 });
26362
- const source = spec.transport === "sse" || spec.transport === "streamable-http" ? spec.url : `${spec.command} ${spec.args.join(" ")}`;
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
- `\u25B8 MCP[${spec.name ?? "anon"}]: ${bridge.registeredNames.length} tool(s) from ${source}
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
- `\u25B8 MCP setup SKIPPED for "${raw}": ${err.message}
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 React64 from "react";
26994
+ import React65 from "react";
26524
26995
 
26525
26996
  // src/cli/ui/Wizard.tsx
26526
- import { Box as Box52, Text as Text54, useApp as useApp4, useInput as useInput4 } from "ink";
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 React63, { useState as useState19 } from "react";
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] = useState19(existingApiKey ? "preset" : "apiKey");
26533
- const [data, setData] = useState19({
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] = useState19(null);
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__ */ React63.createElement(
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__ */ React63.createElement(StepFrame, { title: "Pick a preset", step: 1, total: 3 }, /* @__PURE__ */ React63.createElement(
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__ */ React63.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React63.createElement(Text54, { dimColor: true }, "[\u2191\u2193] navigate \xB7 [Enter] confirm \xB7 [Esc] cancel")));
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__ */ React63.createElement(StepFrame, { title: "Which MCP servers should Reasonix wire up for you?", step: 2, total: 3 }, /* @__PURE__ */ React63.createElement(
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__ */ React63.createElement(
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__ */ React63.createElement(StepFrame, { title: "Ready to save", step: 3, total: 3 }, /* @__PURE__ */ React63.createElement(Box52, { flexDirection: "column" }, /* @__PURE__ */ React63.createElement(SummaryLine, { label: "API key", value: redactKey(data.apiKey) }), /* @__PURE__ */ React63.createElement(SummaryLine, { label: "Preset", value: data.preset }), /* @__PURE__ */ React63.createElement(
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__ */ React63.createElement(Box52, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React63.createElement(Text54, { dimColor: true }, "\xB7 ", spec))
26623
- )), /* @__PURE__ */ React63.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React63.createElement(Text54, null, "Saves to ", defaultConfigPath())), error ? /* @__PURE__ */ React63.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React63.createElement(Text54, { color: "red" }, error)) : null, /* @__PURE__ */ React63.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React63.createElement(Text54, { dimColor: true }, "[Enter] save \xB7 [Esc] cancel"))), /* @__PURE__ */ React63.createElement(
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__ */ React63.createElement(Box52, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React63.createElement(Text54, { bold: true, color: "green" }, "\u25B8 Saved."), /* @__PURE__ */ React63.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React63.createElement(Text54, null, "Run `reasonix` any time to start chatting \u2014 your settings are remembered.")), /* @__PURE__ */ React63.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React63.createElement(Text54, { dimColor: true }, "[Enter] to exit")), /* @__PURE__ */ React63.createElement(ExitOnEnter, { onExit: exit2 }));
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] = useState19("");
26657
- return /* @__PURE__ */ React63.createElement(Box52, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React63.createElement(Text54, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React63.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React63.createElement(Text54, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React63.createElement(Text54, { dimColor: true }, "Get one at: https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React63.createElement(Text54, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React63.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React63.createElement(Text54, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React63.createElement(
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__ */ React63.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React63.createElement(Text54, { color: "red" }, error)) : value ? /* @__PURE__ */ React63.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React63.createElement(Text54, { dimColor: true }, "preview: ", redactKey(value))) : null);
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] = useState19("");
26683
- return /* @__PURE__ */ React63.createElement(StepFrame, { title: `Configure ${entry.name}`, step: 2, total: 3 }, /* @__PURE__ */ React63.createElement(Box52, { flexDirection: "column" }, /* @__PURE__ */ React63.createElement(Text54, null, entry.summary), entry.note ? /* @__PURE__ */ React63.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React63.createElement(Text54, { dimColor: true }, entry.note)) : null, /* @__PURE__ */ React63.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React63.createElement(Text54, null, "Required parameter: "), /* @__PURE__ */ React63.createElement(Text54, { bold: true }, entry.userArgs)), /* @__PURE__ */ React63.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React63.createElement(Text54, { bold: true, color: "cyan" }, entry.userArgs, " \u203A "), /* @__PURE__ */ React63.createElement(
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__ */ React63.createElement(Box52, { marginTop: 1 }, /* @__PURE__ */ React63.createElement(Text54, { color: "red" }, error)) : null));
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__ */ React63.createElement(Box52, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React63.createElement(Box52, null, /* @__PURE__ */ React63.createElement(Text54, { dimColor: true }, "Step ", step, "/", total, " \xB7", " "), /* @__PURE__ */ React63.createElement(Text54, { bold: true, color: "cyan" }, title)), /* @__PURE__ */ React63.createElement(Box52, { marginTop: 1, flexDirection: "column" }, children));
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__ */ React63.createElement(Box52, null, /* @__PURE__ */ React63.createElement(Text54, null, label.padEnd(12)), /* @__PURE__ */ React63.createElement(Text54, { bold: true }, value));
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__ */ React64.createElement(
27249
+ /* @__PURE__ */ React65.createElement(
26779
27250
  Wizard,
26780
27251
  {
26781
27252
  existingApiKey: existingKey,