reasonix 0.13.2 → 0.13.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -500,13 +500,13 @@ async function harvest(reasoningContent, client, options = {}, signal) {
500
500
  }
501
501
  }
502
502
  function parsePlanState(raw, maxItems, maxItemLen) {
503
- const text = (raw ?? "").trim();
504
- if (!text) return emptyPlanState();
503
+ const text2 = (raw ?? "").trim();
504
+ if (!text2) return emptyPlanState();
505
505
  let parsed;
506
506
  try {
507
- parsed = JSON.parse(text);
507
+ parsed = JSON.parse(text2);
508
508
  } catch {
509
- const match = text.match(/\{[\s\S]*\}/);
509
+ const match = text2.match(/\{[\s\S]*\}/);
510
510
  if (!match) return emptyPlanState();
511
511
  try {
512
512
  parsed = JSON.parse(match[0]);
@@ -920,8 +920,8 @@ function bpeEncode(piece, mergeRank) {
920
920
  }
921
921
  return word;
922
922
  }
923
- function encode(text) {
924
- if (!text) return [];
923
+ function encode(text2) {
924
+ if (!text2) return [];
925
925
  const t2 = loadTokenizer();
926
926
  const ids = [];
927
927
  const process2 = (segment) => {
@@ -941,21 +941,21 @@ function encode(text) {
941
941
  if (t2.addedPattern) {
942
942
  t2.addedPattern.lastIndex = 0;
943
943
  let last = 0;
944
- for (const m of text.matchAll(t2.addedPattern)) {
944
+ for (const m of text2.matchAll(t2.addedPattern)) {
945
945
  const idx = m.index ?? 0;
946
- if (idx > last) process2(text.slice(last, idx));
946
+ if (idx > last) process2(text2.slice(last, idx));
947
947
  const id = t2.addedMap.get(m[0]);
948
948
  if (id !== void 0) ids.push(id);
949
949
  last = idx + m[0].length;
950
950
  }
951
- if (last < text.length) process2(text.slice(last));
951
+ if (last < text2.length) process2(text2.slice(last));
952
952
  } else {
953
- process2(text);
953
+ process2(text2);
954
954
  }
955
955
  return ids;
956
956
  }
957
- function countTokens(text) {
958
- return encode(text).length;
957
+ function countTokens(text2) {
958
+ return encode(text2).length;
959
959
  }
960
960
  function estimateConversationTokens(messages) {
961
961
  let total = 0;
@@ -1281,9 +1281,9 @@ function sizePrefixToTokens(s, budget2) {
1281
1281
  let size = Math.min(s.length, budget2 * 4);
1282
1282
  for (let iter = 0; iter < 6; iter++) {
1283
1283
  if (size <= 0) return "";
1284
- const slice = s.slice(0, size);
1285
- const count = countTokens(slice);
1286
- if (count <= budget2) return slice;
1284
+ const slice2 = s.slice(0, size);
1285
+ const count = countTokens(slice2);
1286
+ if (count <= budget2) return slice2;
1287
1287
  const next = Math.floor(size * (budget2 / count) * 0.95);
1288
1288
  if (next >= size) return s.slice(0, Math.max(0, size - 1));
1289
1289
  size = next;
@@ -1295,9 +1295,9 @@ function sizeSuffixToTokens(s, budget2) {
1295
1295
  let size = Math.min(s.length, budget2 * 4);
1296
1296
  for (let iter = 0; iter < 6; iter++) {
1297
1297
  if (size <= 0) return "";
1298
- const slice = s.slice(-size);
1299
- const count = countTokens(slice);
1300
- if (count <= budget2) return slice;
1298
+ const slice2 = s.slice(-size);
1299
+ const count = countTokens(slice2);
1300
+ if (count <= budget2) return slice2;
1301
1301
  const next = Math.floor(size * (budget2 / count) * 0.95);
1302
1302
  if (next >= size) return s.slice(-Math.max(0, size - 1));
1303
1303
  size = next;
@@ -1472,15 +1472,15 @@ function scavengeToolCalls(reasoningContent, opts) {
1472
1472
  }
1473
1473
  return { calls: out, notes };
1474
1474
  }
1475
- function stripDsmlBlocks(text) {
1476
- let out = text;
1475
+ function stripDsmlBlocks(text2) {
1476
+ let out = text2;
1477
1477
  out = out.replace(/<[||]DSML[||]function_calls>[\s\S]*?<\/?[||]DSML[||]function_calls>/g, "");
1478
1478
  out = out.replace(/<[||]DSML[||]invoke\s+[^>]*>[\s\S]*?<\/[||]DSML[||]invoke>/g, "");
1479
1479
  return out;
1480
1480
  }
1481
- function* iterateDsmlInvokes(text) {
1481
+ function* iterateDsmlInvokes(text2) {
1482
1482
  const INVOKE_RE = /<[||]DSML[||]invoke\s+name="([^"]+)">([\s\S]*?)<\/[||]DSML[||]invoke>/g;
1483
- for (const match of text.matchAll(INVOKE_RE)) {
1483
+ for (const match of text2.matchAll(INVOKE_RE)) {
1484
1484
  const name = match[1];
1485
1485
  const body = match[2];
1486
1486
  if (!name || body === void 0) continue;
@@ -1506,14 +1506,14 @@ function parseDsmlParameters(body) {
1506
1506
  }
1507
1507
  return args;
1508
1508
  }
1509
- function* iterateJsonObjects(text) {
1510
- for (let i = 0; i < text.length; i++) {
1511
- if (text[i] !== "{") continue;
1509
+ function* iterateJsonObjects(text2) {
1510
+ for (let i = 0; i < text2.length; i++) {
1511
+ if (text2[i] !== "{") continue;
1512
1512
  let depth = 0;
1513
1513
  let inString = false;
1514
1514
  let escaped = false;
1515
- for (let j = i; j < text.length; j++) {
1516
- const c = text[j];
1515
+ for (let j = i; j < text2.length; j++) {
1516
+ const c = text2[j];
1517
1517
  if (escaped) {
1518
1518
  escaped = false;
1519
1519
  continue;
@@ -1531,7 +1531,7 @@ function* iterateJsonObjects(text) {
1531
1531
  else if (c === "}") {
1532
1532
  depth--;
1533
1533
  if (depth === 0) {
1534
- yield text.slice(i, j + 1);
1534
+ yield text2.slice(i, j + 1);
1535
1535
  i = j;
1536
1536
  break;
1537
1537
  }
@@ -3532,13 +3532,13 @@ function rankPickerCandidates(files, query, limitOrOpts) {
3532
3532
  return scored.slice(0, limit).map((s) => s.path);
3533
3533
  }
3534
3534
  var AT_MENTION_PATTERN = /(?<=^|\s)@([a-zA-Z0-9_./\\-]+)/g;
3535
- function expandAtMentions(text, rootDir, opts = {}) {
3535
+ function expandAtMentions(text2, rootDir, opts = {}) {
3536
3536
  const maxBytes = opts.maxBytes ?? DEFAULT_AT_MENTION_MAX_BYTES;
3537
3537
  const fs6 = opts.fs ?? defaultFs;
3538
3538
  const root = resolve(rootDir);
3539
3539
  const seen = /* @__PURE__ */ new Map();
3540
3540
  const expansions = [];
3541
- for (const match of text.matchAll(AT_MENTION_PATTERN)) {
3541
+ for (const match of text2.matchAll(AT_MENTION_PATTERN)) {
3542
3542
  const rawPath = match[1] ?? "";
3543
3543
  const cleaned = rawPath.replace(/\.+$/, "");
3544
3544
  if (!cleaned) continue;
@@ -3548,7 +3548,7 @@ function expandAtMentions(text, rootDir, opts = {}) {
3548
3548
  seen.set(token, expansion);
3549
3549
  expansions.push(expansion);
3550
3550
  }
3551
- if (expansions.length === 0) return { text, expansions };
3551
+ if (expansions.length === 0) return { text: text2, expansions };
3552
3552
  const blocks = [];
3553
3553
  for (const ex of expansions) {
3554
3554
  if (ex.ok) {
@@ -3560,7 +3560,7 @@ ${content}
3560
3560
  blocks.push(`<file path="${ex.path}" skipped="${ex.skip}" />`);
3561
3561
  }
3562
3562
  }
3563
- const augmented = `${text}
3563
+ const augmented = `${text2}
3564
3564
 
3565
3565
  [Referenced files]
3566
3566
  ${blocks.join("\n\n")}`;
@@ -3615,7 +3615,7 @@ var defaultFs = {
3615
3615
  };
3616
3616
  var AT_URL_PATTERN = /(?<=^|\s)@(https?:\/\/\S+)/g;
3617
3617
  var DEFAULT_AT_URL_MAX_CHARS = 32e3;
3618
- async function expandAtUrls(text, opts = {}) {
3618
+ async function expandAtUrls(text2, opts = {}) {
3619
3619
  const maxChars = opts.maxChars ?? DEFAULT_AT_URL_MAX_CHARS;
3620
3620
  const fetcher = opts.fetcher;
3621
3621
  if (!fetcher) {
@@ -3624,7 +3624,7 @@ async function expandAtUrls(text, opts = {}) {
3624
3624
  const seen = /* @__PURE__ */ new Map();
3625
3625
  const bodies = /* @__PURE__ */ new Map();
3626
3626
  const order = [];
3627
- for (const match of text.matchAll(AT_URL_PATTERN)) {
3627
+ for (const match of text2.matchAll(AT_URL_PATTERN)) {
3628
3628
  const rawUrl = match[1] ?? "";
3629
3629
  const url = stripUrlTail(rawUrl);
3630
3630
  if (!url) continue;
@@ -3671,7 +3671,7 @@ async function expandAtUrls(text, opts = {}) {
3671
3671
  if (opts.cache) opts.cache.set(url, { ...expansion, body });
3672
3672
  order.push(url);
3673
3673
  }
3674
- if (seen.size === 0) return { text, expansions: [] };
3674
+ if (seen.size === 0) return { text: text2, expansions: [] };
3675
3675
  const expansions = order.map((u) => seen.get(u)).filter(Boolean);
3676
3676
  const blocks = [];
3677
3677
  for (const ex of expansions) {
@@ -3687,7 +3687,7 @@ ${body}
3687
3687
  blocks.push(`<url href="${ex.url}" skipped="${reasonAttr}" />`);
3688
3688
  }
3689
3689
  }
3690
- const augmented = `${text}
3690
+ const augmented = `${text2}
3691
3691
 
3692
3692
  [Referenced URLs]
3693
3693
  ${blocks.join("\n\n")}`;
@@ -3848,34 +3848,34 @@ When none of these is given AND the file is longer than ${DEFAULT_AUTO_PREVIEW_L
3848
3848
 
3849
3849
  [\u2026truncated ${raw.length - maxReadBytes} bytes \u2014 file is ${raw.length} B, cap ${maxReadBytes} B. Retry with head/tail/range for targeted view.]`;
3850
3850
  }
3851
- const text = raw.toString("utf8");
3852
- let lines = text.split(/\r?\n/);
3851
+ const text2 = raw.toString("utf8");
3852
+ let lines = text2.split(/\r?\n/);
3853
3853
  if (lines.length > 0 && lines[lines.length - 1] === "") lines = lines.slice(0, -1);
3854
3854
  const totalLines = lines.length;
3855
3855
  if (typeof args.range === "string" && /^\d+\s*-\s*\d+$/.test(args.range)) {
3856
3856
  const [rawStart, rawEnd] = args.range.split("-").map((s) => Number.parseInt(s, 10));
3857
3857
  const start = Math.max(1, rawStart ?? 1);
3858
3858
  const end = Math.min(totalLines, Math.max(start, rawEnd ?? totalLines));
3859
- const slice = lines.slice(start - 1, end);
3859
+ const slice2 = lines.slice(start - 1, end);
3860
3860
  const label = `[range ${start}-${end} of ${totalLines} lines]`;
3861
3861
  return `${label}
3862
- ${slice.join("\n")}`;
3862
+ ${slice2.join("\n")}`;
3863
3863
  }
3864
3864
  if (typeof args.head === "number" && args.head > 0) {
3865
3865
  const count = Math.min(args.head, totalLines);
3866
- const slice = lines.slice(0, count);
3866
+ const slice2 = lines.slice(0, count);
3867
3867
  const marker = count < totalLines ? `
3868
3868
 
3869
3869
  [\u2026head ${count} of ${totalLines} lines \u2014 call again with range / tail for more]` : "";
3870
- return slice.join("\n") + marker;
3870
+ return slice2.join("\n") + marker;
3871
3871
  }
3872
3872
  if (typeof args.tail === "number" && args.tail > 0) {
3873
3873
  const count = Math.min(args.tail, totalLines);
3874
- const slice = lines.slice(totalLines - count);
3874
+ const slice2 = lines.slice(totalLines - count);
3875
3875
  const marker = count < totalLines ? `[\u2026tail ${count} of ${totalLines} lines \u2014 call again with range / head for more]
3876
3876
 
3877
3877
  ` : "";
3878
- return marker + slice.join("\n");
3878
+ return marker + slice2.join("\n");
3879
3879
  }
3880
3880
  if (totalLines <= DEFAULT_AUTO_PREVIEW_LINES) return lines.join("\n");
3881
3881
  const head = lines.slice(0, AUTO_PREVIEW_HEAD_LINES).join("\n");
@@ -4122,9 +4122,9 @@ Prefer \`list_directory\` for a single-level view, \`search_files\` to find spec
4122
4122
  }
4123
4123
  const firstNul = raw.indexOf(0);
4124
4124
  if (firstNul !== -1 && firstNul < 8 * 1024) continue;
4125
- const text = raw.toString("utf8");
4125
+ const text2 = raw.toString("utf8");
4126
4126
  const rel = pathMod.relative(rootDir, full);
4127
- const lines = text.split(/\r?\n/);
4127
+ const lines = text2.split(/\r?\n/);
4128
4128
  for (let li = 0; li < lines.length; li++) {
4129
4129
  const line = lines[li];
4130
4130
  const lineForCheck = caseSensitive ? line : line.toLowerCase();
@@ -5159,17 +5159,17 @@ ${job.output.slice(start)}`;
5159
5159
  const job = this.jobs.get(id);
5160
5160
  if (!job) return null;
5161
5161
  const full = job.output;
5162
- let slice = full;
5162
+ let slice2 = full;
5163
5163
  if (typeof opts.since === "number" && opts.since >= 0 && opts.since < full.length) {
5164
- slice = full.slice(opts.since);
5164
+ slice2 = full.slice(opts.since);
5165
5165
  }
5166
5166
  if (typeof opts.tailLines === "number" && opts.tailLines > 0) {
5167
- const lines = slice.split("\n");
5167
+ const lines = slice2.split("\n");
5168
5168
  const keep = lines.slice(Math.max(0, lines.length - opts.tailLines));
5169
- slice = keep.join("\n");
5169
+ slice2 = keep.join("\n");
5170
5170
  }
5171
5171
  return {
5172
- output: slice,
5172
+ output: slice2,
5173
5173
  byteLength: full.length,
5174
5174
  running: job.running,
5175
5175
  exitCode: job.exitCode,
@@ -5882,11 +5882,11 @@ async function webFetch(url, opts = {}) {
5882
5882
  }
5883
5883
  const raw = await readBodyCapped(resp, FETCH_MAX_BYTES);
5884
5884
  const title = extractTitle(raw);
5885
- const text = contentType.includes("text/html") ? htmlToText(raw) : raw;
5886
- const truncated = text.length > maxChars;
5887
- const finalText = truncated ? `${text.slice(0, maxChars)}
5885
+ const text2 = contentType.includes("text/html") ? htmlToText(raw) : raw;
5886
+ const truncated = text2.length > maxChars;
5887
+ const finalText = truncated ? `${text2.slice(0, maxChars)}
5888
5888
 
5889
- [\u2026 truncated ${text.length - maxChars} chars \u2026]` : text;
5889
+ [\u2026 truncated ${text2.length - maxChars} chars \u2026]` : text2;
5890
5890
  return { url, title, text: finalText, truncated };
5891
5891
  }
5892
5892
  async function readBodyCapped(resp, maxBytes) {
@@ -7436,10 +7436,10 @@ async function trySection(load) {
7436
7436
  import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync9, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "fs";
7437
7437
  import { dirname as dirname6, resolve as resolve6 } from "path";
7438
7438
  var BLOCK_RE = /^(\S[^\n]*)\n<{7} SEARCH\n([\s\S]*?)\n?={7}\n([\s\S]*?)\n?>{7} REPLACE/gm;
7439
- function parseEditBlocks(text) {
7439
+ function parseEditBlocks(text2) {
7440
7440
  const out = [];
7441
7441
  BLOCK_RE.lastIndex = 0;
7442
- let m = BLOCK_RE.exec(text);
7442
+ let m = BLOCK_RE.exec(text2);
7443
7443
  while (m !== null) {
7444
7444
  out.push({
7445
7445
  path: m[1].trim(),
@@ -7447,7 +7447,7 @@ function parseEditBlocks(text) {
7447
7447
  replace: m[3],
7448
7448
  offset: m.index
7449
7449
  });
7450
- m = BLOCK_RE.exec(text);
7450
+ m = BLOCK_RE.exec(text2);
7451
7451
  }
7452
7452
  return out;
7453
7453
  }
@@ -7767,12 +7767,12 @@ function formatLogSize(path5 = defaultUsageLogPath()) {
7767
7767
  // src/cli/commands/chat.tsx
7768
7768
  import { existsSync as existsSync23, statSync as statSync13 } from "fs";
7769
7769
  import { render } from "ink";
7770
- import React30, { useState as useState12 } from "react";
7770
+ import React31, { useState as useState12 } from "react";
7771
7771
 
7772
7772
  // src/cli/ui/App.tsx
7773
7773
  import * as pathMod7 from "path";
7774
- import { Box as Box25, Text as Text23, useStdout as useStdout9 } from "ink";
7775
- import React27, { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo3, useRef as useRef6, useState as useState10 } from "react";
7774
+ import { Box as Box26, Text as Text24, useStdout as useStdout9 } from "ink";
7775
+ import React28, { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo3, useRef as useRef6, useState as useState10 } from "react";
7776
7776
 
7777
7777
  // src/code/pending-edits.ts
7778
7778
  import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync11, unlinkSync as unlinkSync3, writeFileSync as writeFileSync6 } from "fs";
@@ -8765,7 +8765,7 @@ async function handleModal(method, rest, body, ctx) {
8765
8765
  };
8766
8766
  }
8767
8767
  if (method === "POST" && rest[0] === "resolve") {
8768
- const { kind, choice, text } = parseBody6(body);
8768
+ const { kind, choice, text: text2 } = parseBody6(body);
8769
8769
  if (kind === "shell") {
8770
8770
  if (!ctx.resolveShellConfirm) {
8771
8771
  return { status: 503, body: { error: "shell modal resolution not wired" } };
@@ -8808,7 +8808,7 @@ async function handleModal(method, rest, body, ctx) {
8808
8808
  if (choice !== "approve" && choice !== "refine" && choice !== "cancel") {
8809
8809
  return { status: 400, body: { error: "plan choice must be approve / refine / cancel" } };
8810
8810
  }
8811
- ctx.resolvePlanConfirm(choice, typeof text === "string" && text.trim() ? text : void 0);
8811
+ ctx.resolvePlanConfirm(choice, typeof text2 === "string" && text2.trim() ? text2 : void 0);
8812
8812
  return { status: 200, body: { resolved: true } };
8813
8813
  }
8814
8814
  if (kind === "edit-review") {
@@ -8843,7 +8843,7 @@ async function handleModal(method, rest, body, ctx) {
8843
8843
  }
8844
8844
  ctx.resolveCheckpointConfirm(
8845
8845
  choice,
8846
- typeof text === "string" && text.trim() ? text : void 0
8846
+ typeof text2 === "string" && text2.trim() ? text2 : void 0
8847
8847
  );
8848
8848
  return { status: 200, body: { resolved: true } };
8849
8849
  }
@@ -8943,15 +8943,15 @@ var BINARY_EXTS = /* @__PURE__ */ new Set([
8943
8943
  ".sqlite",
8944
8944
  ".db"
8945
8945
  ]);
8946
- function chunkText(text, filePath, windowLines, overlap, maxChunkChars = DEFAULT_MAX_CHUNK_CHARS) {
8947
- const lines = text.split(/\r?\n/);
8946
+ function chunkText(text2, filePath, windowLines, overlap, maxChunkChars = DEFAULT_MAX_CHUNK_CHARS) {
8947
+ const lines = text2.split(/\r?\n/);
8948
8948
  if (lines.length === 0 || lines.length === 1 && lines[0] === "") return [];
8949
8949
  const stride = Math.max(1, windowLines - overlap);
8950
8950
  const chunks = [];
8951
8951
  for (let start = 0; start < lines.length; start += stride) {
8952
8952
  const end = Math.min(lines.length, start + windowLines);
8953
- const slice = lines.slice(start, end).join("\n").trim();
8954
- if (slice.length === 0) {
8953
+ const slice2 = lines.slice(start, end).join("\n").trim();
8954
+ if (slice2.length === 0) {
8955
8955
  if (end >= lines.length) break;
8956
8956
  continue;
8957
8957
  }
@@ -8959,7 +8959,7 @@ function chunkText(text, filePath, windowLines, overlap, maxChunkChars = DEFAULT
8959
8959
  path: filePath,
8960
8960
  startLine: start + 1,
8961
8961
  endLine: end,
8962
- text: slice
8962
+ text: slice2
8963
8963
  };
8964
8964
  for (const sub of safeSplit(window, maxChunkChars)) chunks.push(sub);
8965
8965
  if (end >= lines.length) break;
@@ -9044,15 +9044,15 @@ async function* walkChunks(root, opts = {}) {
9044
9044
  continue;
9045
9045
  }
9046
9046
  if (stat2.size > maxFileBytes) continue;
9047
- let text;
9047
+ let text2;
9048
9048
  try {
9049
- text = await fs2.readFile(abs, "utf8");
9049
+ text2 = await fs2.readFile(abs, "utf8");
9050
9050
  } catch {
9051
9051
  continue;
9052
9052
  }
9053
- if (text.indexOf("\0") !== -1) continue;
9053
+ if (text2.indexOf("\0") !== -1) continue;
9054
9054
  const rel = path.relative(root, abs).split(path.sep).join("/");
9055
- for (const chunk of chunkText(text, rel, windowLines, overlap, maxChunkChars)) {
9055
+ for (const chunk of chunkText(text2, rel, windowLines, overlap, maxChunkChars)) {
9056
9056
  yield chunk;
9057
9057
  }
9058
9058
  }
@@ -9071,7 +9071,7 @@ var EmbeddingError = class extends Error {
9071
9071
  }
9072
9072
  cause;
9073
9073
  };
9074
- async function embed(text, opts = {}) {
9074
+ async function embed(text2, opts = {}) {
9075
9075
  const baseUrl = opts.baseUrl ?? process.env.OLLAMA_URL ?? DEFAULT_OLLAMA_URL;
9076
9076
  const model2 = opts.model ?? process.env.REASONIX_EMBED_MODEL ?? DEFAULT_EMBED_MODEL;
9077
9077
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
@@ -9087,7 +9087,7 @@ async function embed(text, opts = {}) {
9087
9087
  res = await fetch(`${baseUrl}/api/embeddings`, {
9088
9088
  method: "POST",
9089
9089
  headers: { "content-type": "application/json" },
9090
- body: JSON.stringify({ model: model2, prompt: text }),
9090
+ body: JSON.stringify({ model: model2, prompt: text2 }),
9091
9091
  signal: controller.signal
9092
9092
  });
9093
9093
  } catch (err) {
@@ -9134,10 +9134,10 @@ async function embedAll(texts, opts = {}) {
9134
9134
  if (opts.signal?.aborted) {
9135
9135
  throw new EmbeddingError("embedding aborted");
9136
9136
  }
9137
- const text = texts[i];
9138
- if (text === void 0) continue;
9137
+ const text2 = texts[i];
9138
+ if (text2 === void 0) continue;
9139
9139
  try {
9140
- out[i] = await embed(text, opts);
9140
+ out[i] = await embed(text2, opts);
9141
9141
  } catch (err) {
9142
9142
  opts.onError?.(i, err);
9143
9143
  }
@@ -9834,8 +9834,8 @@ ${i + 1}. ${entry.path}:${entry.startLine}-${entry.endLine} (score ${score.toFi
9834
9834
  });
9835
9835
  return lines.join("\n");
9836
9836
  }
9837
- function indentBlock(text, prefix) {
9838
- return text.split("\n").map((l) => prefix + l).join("\n");
9837
+ function indentBlock(text2, prefix) {
9838
+ return text2.split("\n").map((l) => prefix + l).join("\n");
9839
9839
  }
9840
9840
  async function bootstrapSemanticSearchInCodeMode(registry, rootDir, opts = {}) {
9841
9841
  if (await indexExists(rootDir)) {
@@ -11503,9 +11503,76 @@ function ChoiceConfirmInner({ question, options, allowCustom, onChoose }) {
11503
11503
  }
11504
11504
  var ChoiceConfirm = React5.memo(ChoiceConfirmInner);
11505
11505
 
11506
+ // src/cli/ui/ChromeBar.tsx
11507
+ import { Box as Box5, Text as Text4, useStdout as useStdout2 } from "ink";
11508
+ import React6 from "react";
11509
+ var NARROW_BREAKPOINT = 120;
11510
+ var COLD_START_TURNS = 3;
11511
+ var CACHE_BAR_CELLS = 10;
11512
+ function ChromeBar(props) {
11513
+ const { stdout: stdout4 } = useStdout2();
11514
+ const cols = stdout4?.columns ?? 80;
11515
+ const narrow = cols < NARROW_BREAKPOINT;
11516
+ const cold = props.summary.turns <= COLD_START_TURNS;
11517
+ const projectName = props.rootDir ? basename(props.rootDir) : null;
11518
+ const mode2 = pickModePill(props.planMode, props.preset);
11519
+ const proPill = props.escalated ? { label: "\u21E7 pro", color: COLOR.err } : props.proArmed ? { label: "\u21E7 pro", color: COLOR.warn } : null;
11520
+ const showCache = props.summary.turns > COLD_START_TURNS && !narrow;
11521
+ const showBalance = !!props.balance && !narrow;
11522
+ return /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text4, { bold: true, color: GRADIENT[0] }, "\u25C8 "), /* @__PURE__ */ React6.createElement(Text4, { color: COLOR.brand, bold: true }, "reasonix"), projectName ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text4, { color: COLOR.info, dimColor: true }, " \xB7 "), /* @__PURE__ */ React6.createElement(Text4, null, projectName), !narrow && props.sessionName ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text4, { color: COLOR.info, dimColor: true }, " \u203A "), /* @__PURE__ */ React6.createElement(Text4, { color: COLOR.info }, props.sessionName)) : null) : null, /* @__PURE__ */ React6.createElement(Box5, { flexGrow: 1 }), props.scrollRatio !== void 0 && props.scrollRatio > 0 ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text4, { color: COLOR.accent, bold: true }, `[\u2191 ${Math.round(props.scrollRatio * 100)}%]`), /* @__PURE__ */ React6.createElement(Text4, null, " ")) : null, props.updateAvailable ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text4, { color: COLOR.warn, bold: true }, `\u2191 ${props.updateAvailable}`), /* @__PURE__ */ React6.createElement(Text4, null, " ")) : null, mode2 ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text4, { color: mode2.color, bold: true }, `[${mode2.label}]`), /* @__PURE__ */ React6.createElement(Text4, null, " ")) : null, proPill ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text4, { color: proPill.color, bold: true }, `[${proPill.label}]`), /* @__PURE__ */ React6.createElement(Text4, null, " ")) : null, /* @__PURE__ */ React6.createElement(CostPill, { summary: props.summary, cold, budgetUsd: props.budgetUsd }), showBalance ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text4, null, " "), /* @__PURE__ */ React6.createElement(BalancePill, { balance: props.balance })) : null, showCache ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text4, null, " "), /* @__PURE__ */ React6.createElement(CachePill, { ratio: props.summary.cacheHitRatio })) : null), /* @__PURE__ */ React6.createElement(ChromeRule, null));
11523
+ }
11524
+ function ChromeRule() {
11525
+ const { stdout: stdout4 } = useStdout2();
11526
+ const cols = stdout4?.columns ?? 80;
11527
+ const w = Math.max(20, cols - 2);
11528
+ return /* @__PURE__ */ React6.createElement(Text4, { dimColor: true }, "\u2500".repeat(w));
11529
+ }
11530
+ function CostPill({
11531
+ summary,
11532
+ cold,
11533
+ budgetUsd
11534
+ }) {
11535
+ const cost = summary.totalCostUsd;
11536
+ const color2 = cold ? COLOR.info : sessionCostColor(cost);
11537
+ return /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text4, { color: color2, bold: !cold, dimColor: cold }, `$${cost.toFixed(4)}`), budgetUsd && budgetUsd > 0 ? /* @__PURE__ */ React6.createElement(Text4, { color: COLOR.info, dimColor: true }, ` / $${budgetUsd.toFixed(2)}`) : null);
11538
+ }
11539
+ function BalancePill({
11540
+ balance
11541
+ }) {
11542
+ const { currency, total } = balance;
11543
+ const color2 = total < 1 ? COLOR.err : total < 5 ? COLOR.warn : COLOR.ok;
11544
+ const sym = currency === "USD" ? "$" : currency === "CNY" ? "\xA5" : "";
11545
+ const suf = sym ? "" : ` ${currency}`;
11546
+ return /* @__PURE__ */ React6.createElement(Text4, { color: color2 }, `w ${sym}${total.toFixed(2)}${suf}`);
11547
+ }
11548
+ function CachePill({ ratio }) {
11549
+ const color2 = ratio >= 0.7 ? COLOR.ok : ratio >= 0.4 ? COLOR.warn : COLOR.err;
11550
+ const filled = Math.max(0, Math.min(CACHE_BAR_CELLS, Math.round(ratio * CACHE_BAR_CELLS)));
11551
+ const empty2 = CACHE_BAR_CELLS - filled;
11552
+ return /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text4, { color: COLOR.info, dimColor: true }, "cache "), /* @__PURE__ */ React6.createElement(Text4, { color: color2 }, "\u2588".repeat(filled)), /* @__PURE__ */ React6.createElement(Text4, { dimColor: true }, "\u2591".repeat(empty2)), /* @__PURE__ */ React6.createElement(Text4, { color: color2, bold: true }, ` ${Math.round(ratio * 100)}%`));
11553
+ }
11554
+ function pickModePill(planMode, preset2) {
11555
+ if (planMode) return { label: "PLAN", color: COLOR.err };
11556
+ if (!preset2) return null;
11557
+ if (preset2 === "pro") return { label: "pro", color: COLOR.accent };
11558
+ if (preset2 === "flash") return { label: "flash", color: COLOR.info };
11559
+ return { label: "auto", color: COLOR.primary };
11560
+ }
11561
+ function sessionCostColor(cost) {
11562
+ if (cost <= 0) return void 0;
11563
+ if (cost >= 5) return COLOR.err;
11564
+ if (cost >= 0.5) return COLOR.warn;
11565
+ return COLOR.ok;
11566
+ }
11567
+ function basename(path5) {
11568
+ const norm = path5.replace(/\\/g, "/");
11569
+ const i = norm.lastIndexOf("/");
11570
+ return i === -1 ? norm : norm.slice(i + 1);
11571
+ }
11572
+
11506
11573
  // src/cli/ui/EditConfirm.tsx
11507
- import { Box as Box6, Text as Text5, useStdout as useStdout3 } from "ink";
11508
- import React7, { useMemo, useState as useState2 } from "react";
11574
+ import { Box as Box7, Text as Text6, useStdout as useStdout4 } from "ink";
11575
+ import React8, { useMemo, useState as useState2 } from "react";
11509
11576
 
11510
11577
  // src/code/diff-preview.ts
11511
11578
  function formatEditBlockDiff(block, opts = {}) {
@@ -11657,14 +11724,14 @@ function capLines(lines, maxLines, indent) {
11657
11724
  }
11658
11725
 
11659
11726
  // src/cli/ui/SplitDiff.tsx
11660
- import { Box as Box5, Text as Text4, useStdout as useStdout2 } from "ink";
11661
- import React6 from "react";
11727
+ import { Box as Box6, Text as Text5, useStdout as useStdout3 } from "ink";
11728
+ import React7 from "react";
11662
11729
  function SplitDiff({ rows, totalCols }) {
11663
- const { stdout: stdout4 } = useStdout2();
11730
+ const { stdout: stdout4 } = useStdout3();
11664
11731
  const cols = totalCols ?? stdout4?.columns ?? 80;
11665
11732
  const innerCols = Math.max(40, cols - 6);
11666
11733
  const halfCols = Math.floor((innerCols - 3) / 2);
11667
- return /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column" }, rows.map((row2, i) => /* @__PURE__ */ React6.createElement(Box5, { key: `r-${i}-${row2.left.num ?? "p"}-${row2.right.num ?? "p"}` }, /* @__PURE__ */ React6.createElement(Cell, { side: row2.left, width: halfCols, which: "left" }), /* @__PURE__ */ React6.createElement(Text4, { color: COLOR.info, dimColor: true }, " \u2502 "), /* @__PURE__ */ React6.createElement(Cell, { side: row2.right, width: halfCols, which: "right" }))));
11734
+ return /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column" }, rows.map((row2, i) => /* @__PURE__ */ React7.createElement(Box6, { key: `r-${i}-${row2.left.num ?? "p"}-${row2.right.num ?? "p"}` }, /* @__PURE__ */ React7.createElement(Cell, { side: row2.left, width: halfCols, which: "left" }), /* @__PURE__ */ React7.createElement(Text5, { color: COLOR.info, dimColor: true }, " \u2502 "), /* @__PURE__ */ React7.createElement(Cell, { side: row2.right, width: halfCols, which: "right" }))));
11668
11735
  }
11669
11736
  function Cell({
11670
11737
  side,
@@ -11684,22 +11751,22 @@ function Cell({
11684
11751
  const truncated = raw.length > inner ? `${raw.slice(0, inner - 1)}\u2026` : raw;
11685
11752
  const padded = truncated.padEnd(inner);
11686
11753
  if (side.kind === "del") {
11687
- return /* @__PURE__ */ React6.createElement(Text4, { color: "#fbc8c8", backgroundColor: "#2a1212" }, `${numStr} ${sign} ${padded}`);
11754
+ return /* @__PURE__ */ React7.createElement(Text5, { color: "#fbc8c8", backgroundColor: "#2a1212" }, `${numStr} ${sign} ${padded}`);
11688
11755
  }
11689
11756
  if (side.kind === "add") {
11690
- return /* @__PURE__ */ React6.createElement(Text4, { color: "#bef0c8", backgroundColor: "#0c2718" }, `${numStr} ${sign} ${padded}`);
11757
+ return /* @__PURE__ */ React7.createElement(Text5, { color: "#bef0c8", backgroundColor: "#0c2718" }, `${numStr} ${sign} ${padded}`);
11691
11758
  }
11692
11759
  if (side.kind === "pad") {
11693
- return /* @__PURE__ */ React6.createElement(Text4, { color: COLOR.info, dimColor: true, italic: !!raw }, `${numStr} ${sign} ${padded}`);
11760
+ return /* @__PURE__ */ React7.createElement(Text5, { color: COLOR.info, dimColor: true, italic: !!raw }, `${numStr} ${sign} ${padded}`);
11694
11761
  }
11695
- return /* @__PURE__ */ React6.createElement(Text4, { dimColor: true }, `${numStr} ${sign} ${padded}`);
11762
+ return /* @__PURE__ */ React7.createElement(Text5, { dimColor: true }, `${numStr} ${sign} ${padded}`);
11696
11763
  }
11697
11764
 
11698
11765
  // src/cli/ui/EditConfirm.tsx
11699
11766
  var MODAL_OVERHEAD_ROWS = 18;
11700
11767
  var MIN_DIFF_ROWS = 8;
11701
11768
  function EditConfirm({ block, onChoose }) {
11702
- const { stdout: stdout4 } = useStdout3();
11769
+ const { stdout: stdout4 } = useStdout4();
11703
11770
  const rows = stdout4?.rows ?? 40;
11704
11771
  const budget2 = Math.max(MIN_DIFF_ROWS, rows - MODAL_OVERHEAD_ROWS);
11705
11772
  const allRows = useMemo(
@@ -11769,8 +11836,8 @@ function EditConfirm({ block, onChoose }) {
11769
11836
  `viewing ${effectiveScroll + 1}-${effectiveScroll + visibleRows.length}/${totalLines}`
11770
11837
  );
11771
11838
  }
11772
- const footer = /* @__PURE__ */ React7.createElement(Text5, { dimColor: true }, "[", /* @__PURE__ */ React7.createElement(Text5, { color: "#67e8f9", bold: true }, "y"), "/Enter] apply \xB7 [", /* @__PURE__ */ React7.createElement(Text5, { color: "#67e8f9", bold: true }, "n"), "] reject \xB7 [", /* @__PURE__ */ React7.createElement(Text5, { color: "#67e8f9", bold: true }, "a"), "] apply rest \xB7 [", /* @__PURE__ */ React7.createElement(Text5, { color: "#67e8f9", bold: true }, "A"), "] flip AUTO \xB7 [", /* @__PURE__ */ React7.createElement(Text5, { color: "#67e8f9", bold: true }, "\u2191\u2193/Space"), "] scroll \xB7 [Esc] abort");
11773
- return /* @__PURE__ */ React7.createElement(
11839
+ const footer = /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, "[", /* @__PURE__ */ React8.createElement(Text6, { color: "#67e8f9", bold: true }, "y"), "/Enter] apply \xB7 [", /* @__PURE__ */ React8.createElement(Text6, { color: "#67e8f9", bold: true }, "n"), "] reject \xB7 [", /* @__PURE__ */ React8.createElement(Text6, { color: "#67e8f9", bold: true }, "a"), "] apply rest \xB7 [", /* @__PURE__ */ React8.createElement(Text6, { color: "#67e8f9", bold: true }, "A"), "] flip AUTO \xB7 [", /* @__PURE__ */ React8.createElement(Text6, { color: "#67e8f9", bold: true }, "\u2191\u2193/Space"), "] scroll \xB7 [Esc] abort");
11840
+ return /* @__PURE__ */ React8.createElement(
11774
11841
  ModalCard,
11775
11842
  {
11776
11843
  accent: isNew ? "#86efac" : "#fcd34d",
@@ -11779,17 +11846,17 @@ function EditConfirm({ block, onChoose }) {
11779
11846
  subtitle: subtitleParts.join(" \xB7 "),
11780
11847
  footer
11781
11848
  },
11782
- hiddenAbove > 0 ? /* @__PURE__ */ React7.createElement(
11783
- Text5,
11849
+ hiddenAbove > 0 ? /* @__PURE__ */ React8.createElement(
11850
+ Text6,
11784
11851
  {
11785
11852
  dimColor: true
11786
11853
  },
11787
11854
  ` \u2191 ${hiddenAbove} line${hiddenAbove === 1 ? "" : "s"} above (\u2191/k or PgUp)`
11788
11855
  ) : null,
11789
- /* @__PURE__ */ React7.createElement(SplitDiff, { rows: visibleRows }),
11790
- /* @__PURE__ */ React7.createElement(Box6, null, /* @__PURE__ */ React7.createElement(Text5, { color: "#fbc8c8", backgroundColor: "#2a1212" }, " - old "), /* @__PURE__ */ React7.createElement(Text5, null, " "), /* @__PURE__ */ React7.createElement(Text5, { color: "#bef0c8", backgroundColor: "#0c2718" }, " + new "), /* @__PURE__ */ React7.createElement(Text5, { dimColor: true }, " side-by-side \xB7 removed lines on the left, added on the right \xB7 paired by offset")),
11791
- hiddenBelow > 0 ? /* @__PURE__ */ React7.createElement(
11792
- Text5,
11856
+ /* @__PURE__ */ React8.createElement(SplitDiff, { rows: visibleRows }),
11857
+ /* @__PURE__ */ React8.createElement(Box7, null, /* @__PURE__ */ React8.createElement(Text6, { color: "#fbc8c8", backgroundColor: "#2a1212" }, " - old "), /* @__PURE__ */ React8.createElement(Text6, null, " "), /* @__PURE__ */ React8.createElement(Text6, { color: "#bef0c8", backgroundColor: "#0c2718" }, " + new "), /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, " side-by-side \xB7 removed lines on the left, added on the right \xB7 paired by offset")),
11858
+ hiddenBelow > 0 ? /* @__PURE__ */ React8.createElement(
11859
+ Text6,
11793
11860
  {
11794
11861
  dimColor: true
11795
11862
  },
@@ -11799,12 +11866,12 @@ function EditConfirm({ block, onChoose }) {
11799
11866
  }
11800
11867
 
11801
11868
  // src/cli/ui/EventLog.tsx
11802
- import { Box as Box11, Text as Text10, useStdout as useStdout4 } from "ink";
11803
- import React13 from "react";
11869
+ import { Box as Box12, Text as Text11, useStdout as useStdout5 } from "ink";
11870
+ import React14 from "react";
11804
11871
 
11805
11872
  // src/cli/ui/PlanStateBlock.tsx
11806
- import { Box as Box7, Text as Text6 } from "ink";
11807
- import React8 from "react";
11873
+ import { Box as Box8, Text as Text7 } from "ink";
11874
+ import React9 from "react";
11808
11875
  function PlanStateBlock({ planState }) {
11809
11876
  const fields = [];
11810
11877
  if (planState.subgoals.length)
@@ -11816,16 +11883,16 @@ function PlanStateBlock({ planState }) {
11816
11883
  if (planState.rejectedPaths.length)
11817
11884
  fields.push(["rejected", planState.rejectedPaths, COLOR.info, true]);
11818
11885
  if (fields.length === 0) return null;
11819
- return /* @__PURE__ */ React8.createElement(Box7, { flexDirection: "column", marginBottom: 1 }, fields.map(([label, items, color2, dim]) => /* @__PURE__ */ React8.createElement(Box7, { key: label }, /* @__PURE__ */ React8.createElement(Text6, { color: color2, bold: true, dimColor: dim }, label), /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, ` (${items.length})`), /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React8.createElement(Text6, { dimColor: dim, color: dim ? void 0 : COLOR.info }, items.join(" \xB7 ")))));
11886
+ return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", marginBottom: 1 }, fields.map(([label, items, color2, dim]) => /* @__PURE__ */ React9.createElement(Box8, { key: label }, /* @__PURE__ */ React9.createElement(Text7, { color: color2, bold: true, dimColor: dim }, label), /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, ` (${items.length})`), /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React9.createElement(Text7, { dimColor: dim, color: dim ? void 0 : COLOR.info }, items.join(" \xB7 ")))));
11820
11887
  }
11821
11888
 
11822
11889
  // src/cli/ui/PlanStepList.tsx
11823
- import { Box as Box9, Text as Text8 } from "ink";
11824
- import React10 from "react";
11890
+ import { Box as Box10, Text as Text9 } from "ink";
11891
+ import React11 from "react";
11825
11892
 
11826
11893
  // src/cli/ui/char-bar.tsx
11827
- import { Box as Box8, Text as Text7 } from "ink";
11828
- import React9 from "react";
11894
+ import { Box as Box9, Text as Text8 } from "ink";
11895
+ import React10 from "react";
11829
11896
  function CharBar({
11830
11897
  pct: pct2,
11831
11898
  width = 24,
@@ -11837,7 +11904,7 @@ function CharBar({
11837
11904
  const total = Math.max(4, width);
11838
11905
  const clamped = Math.max(0, Math.min(100, Number.isFinite(pct2) ? pct2 : 0));
11839
11906
  const filled = Math.round(total * clamped / 100);
11840
- return /* @__PURE__ */ React9.createElement(Box8, 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);
11907
+ return /* @__PURE__ */ React10.createElement(Box9, 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);
11841
11908
  }
11842
11909
 
11843
11910
  // src/cli/ui/PlanStepList.tsx
@@ -11867,31 +11934,31 @@ function PlanStepListInner({ steps, statuses, focusStepId }) {
11867
11934
  const doneCount = statusList.filter((s) => s === "done").length;
11868
11935
  const pct2 = Math.round(doneCount / total * 100);
11869
11936
  const showProgress = doneCount > 0;
11870
- return /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Box9, 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(Box9, { flexDirection: "column" }, steps.map((step, i) => {
11937
+ return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Box10, 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(Box10, { flexDirection: "column" }, steps.map((step, i) => {
11871
11938
  const status2 = statusList[i];
11872
11939
  const isLast = i === total - 1;
11873
11940
  const isCur = focusStepId === step.id;
11874
11941
  const sg = statusGlyph(status2, isCur);
11875
11942
  const risk = riskLabel(step.risk);
11876
11943
  const titleDim = status2 === "done" || status2 === "skipped";
11877
- return /* @__PURE__ */ React10.createElement(Box9, { 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: status2 === "running" || isCur }, sg.glyph), /* @__PURE__ */ React10.createElement(Text8, null, " "), /* @__PURE__ */ React10.createElement(
11878
- Text8,
11944
+ return /* @__PURE__ */ React11.createElement(Box10, { 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: status2 === "running" || isCur }, sg.glyph), /* @__PURE__ */ React11.createElement(Text9, null, " "), /* @__PURE__ */ React11.createElement(
11945
+ Text9,
11879
11946
  {
11880
11947
  dimColor: titleDim,
11881
11948
  bold: isCur || status2 === "running",
11882
11949
  strikethrough: status2 === "done" || status2 === "skipped"
11883
11950
  },
11884
11951
  `${step.id} \xB7 ${step.title}`
11885
- ), risk ? /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Text8, null, " "), /* @__PURE__ */ React10.createElement(Text8, { color: risk.color }, risk.text)) : null);
11886
- })), showProgress ? /* @__PURE__ */ React10.createElement(Box9, null, /* @__PURE__ */ React10.createElement(Text8, null, " "), /* @__PURE__ */ React10.createElement(CharBar, { pct: pct2, width: 24 })) : null);
11952
+ ), risk ? /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(Text9, null, " "), /* @__PURE__ */ React11.createElement(Text9, { color: risk.color }, risk.text)) : null);
11953
+ })), showProgress ? /* @__PURE__ */ React11.createElement(Box10, null, /* @__PURE__ */ React11.createElement(Text9, null, " "), /* @__PURE__ */ React11.createElement(CharBar, { pct: pct2, width: 24 })) : null);
11887
11954
  }
11888
- var PlanStepList = React10.memo(PlanStepListInner);
11955
+ var PlanStepList = React11.memo(PlanStepListInner);
11889
11956
 
11890
11957
  // src/cli/ui/markdown.tsx
11891
11958
  import { readFileSync as readFileSync19, statSync as statSync11 } from "fs";
11892
11959
  import { isAbsolute as isAbsolute5, join as join16 } from "path";
11893
- import { Box as Box10, Text as Text9 } from "ink";
11894
- import React11 from "react";
11960
+ import { Box as Box11, Text as Text10 } from "ink";
11961
+ import React12 from "react";
11895
11962
  var SUPERSCRIPT = {
11896
11963
  "0": "\u2070",
11897
11964
  "1": "\xB9",
@@ -12190,10 +12257,10 @@ function shouldValidateAsCitation(url) {
12190
12257
  if (!/[/\\.]/.test(url)) return false;
12191
12258
  return true;
12192
12259
  }
12193
- function collectCitations(text, projectRoot) {
12260
+ function collectCitations(text2, projectRoot) {
12194
12261
  const map = /* @__PURE__ */ new Map();
12195
12262
  const re = /\[([^\]\n]+)\]\(([^)\n]+)\)/g;
12196
- for (const m of text.matchAll(re)) {
12263
+ for (const m of text2.matchAll(re)) {
12197
12264
  const url = m[2] ?? "";
12198
12265
  if (!url || isExternalUrl(url)) continue;
12199
12266
  if (!shouldValidateAsCitation(url)) continue;
@@ -12204,77 +12271,77 @@ function collectCitations(text, projectRoot) {
12204
12271
  }
12205
12272
  var INLINE_RE = /(\[([^\]\n]+)\]\(([^)\n]+)\)|\*\*\*([^*\n]+?)\*\*\*|\*\*([^*\n]+?)\*\*|```([^\n]+?)```|`([^`\n]+?)`|~~([^~\n]+?)~~|(?<![*\w])\*([^*\n]+?)\*(?!\w)|\\([*_~`[\](){}#+\-.!\\]))/g;
12206
12273
  function InlineMd({
12207
- text,
12274
+ text: text2,
12208
12275
  padTo,
12209
12276
  citations
12210
12277
  }) {
12211
12278
  const parts = [];
12212
12279
  let last = 0;
12213
12280
  let idx = 0;
12214
- for (const m of text.matchAll(INLINE_RE)) {
12281
+ for (const m of text2.matchAll(INLINE_RE)) {
12215
12282
  const start = m.index ?? 0;
12216
12283
  if (start > last) {
12217
- parts.push(/* @__PURE__ */ React11.createElement(Text9, { key: `t${idx++}` }, text.slice(last, start)));
12284
+ parts.push(/* @__PURE__ */ React12.createElement(Text10, { key: `t${idx++}` }, text2.slice(last, start)));
12218
12285
  }
12219
12286
  if (m[2] !== void 0 && m[3] !== void 0) {
12220
12287
  const linkText = m[2];
12221
12288
  const url = m[3];
12222
12289
  if (isExternalUrl(url)) {
12223
12290
  parts.push(
12224
- /* @__PURE__ */ React11.createElement(Text9, { key: `l${idx++}`, color: "blue", underline: true }, linkText)
12291
+ /* @__PURE__ */ React12.createElement(Text10, { key: `l${idx++}`, color: "blue", underline: true }, linkText)
12225
12292
  );
12226
12293
  } else {
12227
12294
  const status2 = citations?.get(url);
12228
12295
  if (status2 && !status2.ok) {
12229
12296
  parts.push(
12230
- /* @__PURE__ */ React11.createElement(Text9, { key: `l${idx++}`, color: "red", strikethrough: true }, `${linkText} \u2717`)
12297
+ /* @__PURE__ */ React12.createElement(Text10, { key: `l${idx++}`, color: "red", strikethrough: true }, `${linkText} \u2717`)
12231
12298
  );
12232
12299
  } else {
12233
12300
  parts.push(
12234
- /* @__PURE__ */ React11.createElement(Text9, { key: `l${idx++}`, color: "cyan", underline: true }, linkText)
12301
+ /* @__PURE__ */ React12.createElement(Text10, { key: `l${idx++}`, color: "cyan", underline: true }, linkText)
12235
12302
  );
12236
12303
  }
12237
12304
  }
12238
12305
  } else if (m[4] !== void 0) {
12239
12306
  parts.push(
12240
- /* @__PURE__ */ React11.createElement(Text9, { key: `bi${idx++}`, bold: true, italic: true }, m[4])
12307
+ /* @__PURE__ */ React12.createElement(Text10, { key: `bi${idx++}`, bold: true, italic: true }, m[4])
12241
12308
  );
12242
12309
  } else if (m[5] !== void 0) {
12243
12310
  parts.push(
12244
- /* @__PURE__ */ React11.createElement(Text9, { key: `b${idx++}`, bold: true }, m[5])
12311
+ /* @__PURE__ */ React12.createElement(Text10, { key: `b${idx++}`, bold: true }, m[5])
12245
12312
  );
12246
12313
  } else if (m[6] !== void 0) {
12247
12314
  const stripped = m[6].replace(/^(\w+)\s+/, "");
12248
12315
  parts.push(
12249
- /* @__PURE__ */ React11.createElement(Text9, { key: `c${idx++}`, color: "yellow" }, stripped)
12316
+ /* @__PURE__ */ React12.createElement(Text10, { key: `c${idx++}`, color: "yellow" }, stripped)
12250
12317
  );
12251
12318
  } else if (m[7] !== void 0) {
12252
12319
  parts.push(
12253
- /* @__PURE__ */ React11.createElement(Text9, { key: `c${idx++}`, color: "yellow" }, m[7])
12320
+ /* @__PURE__ */ React12.createElement(Text10, { key: `c${idx++}`, color: "yellow" }, m[7])
12254
12321
  );
12255
12322
  } else if (m[8] !== void 0) {
12256
12323
  parts.push(
12257
- /* @__PURE__ */ React11.createElement(Text9, { key: `s${idx++}`, strikethrough: true, dimColor: true }, m[8])
12324
+ /* @__PURE__ */ React12.createElement(Text10, { key: `s${idx++}`, strikethrough: true, dimColor: true }, m[8])
12258
12325
  );
12259
12326
  } else if (m[9] !== void 0) {
12260
12327
  parts.push(
12261
- /* @__PURE__ */ React11.createElement(Text9, { key: `i${idx++}`, italic: true }, m[9])
12328
+ /* @__PURE__ */ React12.createElement(Text10, { key: `i${idx++}`, italic: true }, m[9])
12262
12329
  );
12263
12330
  } else if (m[10] !== void 0) {
12264
- parts.push(/* @__PURE__ */ React11.createElement(Text9, { key: `esc${idx++}` }, m[10]));
12331
+ parts.push(/* @__PURE__ */ React12.createElement(Text10, { key: `esc${idx++}` }, m[10]));
12265
12332
  }
12266
12333
  last = start + m[0].length;
12267
12334
  }
12268
- if (last < text.length) {
12269
- parts.push(/* @__PURE__ */ React11.createElement(Text9, { key: `t${idx++}` }, text.slice(last)));
12335
+ if (last < text2.length) {
12336
+ parts.push(/* @__PURE__ */ React12.createElement(Text10, { key: `t${idx++}` }, text2.slice(last)));
12270
12337
  }
12271
12338
  if (padTo !== void 0) {
12272
- const seen = visibleWidth(text);
12339
+ const seen = visibleWidth(text2);
12273
12340
  if (seen < padTo) {
12274
- parts.push(/* @__PURE__ */ React11.createElement(Text9, { key: `pad${idx++}` }, " ".repeat(padTo - seen)));
12341
+ parts.push(/* @__PURE__ */ React12.createElement(Text10, { key: `pad${idx++}` }, " ".repeat(padTo - seen)));
12275
12342
  }
12276
12343
  }
12277
- return /* @__PURE__ */ React11.createElement(Text9, null, parts);
12344
+ return /* @__PURE__ */ React12.createElement(Text10, null, parts);
12278
12345
  }
12279
12346
  function stripInlineMarkup(s) {
12280
12347
  return s.replace(
@@ -12513,34 +12580,34 @@ function parseBulletItem(raw) {
12513
12580
  function BlockView({ block, citations }) {
12514
12581
  switch (block.kind) {
12515
12582
  case "heading":
12516
- return /* @__PURE__ */ React11.createElement(HeadingView, { level: block.level, text: block.text, citations });
12583
+ return /* @__PURE__ */ React12.createElement(HeadingView, { level: block.level, text: block.text, citations });
12517
12584
  case "paragraph":
12518
- return /* @__PURE__ */ React11.createElement(ParagraphView, { text: block.text, citations });
12585
+ return /* @__PURE__ */ React12.createElement(ParagraphView, { text: block.text, citations });
12519
12586
  case "bullet":
12520
- return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column" }, block.items.map((item, i) => /* @__PURE__ */ React11.createElement(Box10, { key: `${i}-${item.text.slice(0, 24)}` }, /* @__PURE__ */ React11.createElement(Text9, { color: item.task === "done" ? "green" : "cyan" }, bulletPrefix(block, i, item)), item.task === "done" ? /* @__PURE__ */ React11.createElement(Text9, { strikethrough: true, dimColor: true }, /* @__PURE__ */ React11.createElement(InlineMd, { text: item.text, citations })) : /* @__PURE__ */ React11.createElement(InlineMd, { text: item.text, citations }))));
12587
+ return /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column" }, block.items.map((item, i) => /* @__PURE__ */ React12.createElement(Box11, { key: `${i}-${item.text.slice(0, 24)}` }, /* @__PURE__ */ React12.createElement(Text10, { color: item.task === "done" ? "green" : "cyan" }, bulletPrefix(block, i, item)), item.task === "done" ? /* @__PURE__ */ React12.createElement(Text10, { strikethrough: true, dimColor: true }, /* @__PURE__ */ React12.createElement(InlineMd, { text: item.text, citations })) : /* @__PURE__ */ React12.createElement(InlineMd, { text: item.text, citations }))));
12521
12588
  case "quote":
12522
- return /* @__PURE__ */ React11.createElement(BlockquoteView, { block, citations });
12589
+ return /* @__PURE__ */ React12.createElement(BlockquoteView, { block, citations });
12523
12590
  case "code":
12524
12591
  if (DIAGRAM_LANGS.has(block.lang.toLowerCase())) {
12525
- return /* @__PURE__ */ React11.createElement(DiagramCodeBlock, { lang: block.lang, text: block.text });
12592
+ return /* @__PURE__ */ React12.createElement(DiagramCodeBlock, { lang: block.lang, text: block.text });
12526
12593
  }
12527
- return /* @__PURE__ */ React11.createElement(CodeBlockView, { lang: block.lang, text: block.text });
12594
+ return /* @__PURE__ */ React12.createElement(CodeBlockView, { lang: block.lang, text: block.text });
12528
12595
  case "edit-block":
12529
- return /* @__PURE__ */ React11.createElement(EditBlockRow, { block });
12596
+ return /* @__PURE__ */ React12.createElement(EditBlockRow, { block });
12530
12597
  case "table":
12531
- return /* @__PURE__ */ React11.createElement(TableBlockRow, { block, citations });
12598
+ return /* @__PURE__ */ React12.createElement(TableBlockRow, { block, citations });
12532
12599
  case "hr":
12533
- return /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
12600
+ return /* @__PURE__ */ React12.createElement(Text10, { dimColor: true }, "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
12534
12601
  }
12535
12602
  }
12536
- function ParagraphView({ text, citations }) {
12537
- if (!text.includes("\n")) {
12538
- return /* @__PURE__ */ React11.createElement(InlineMd, { text, citations });
12603
+ function ParagraphView({ text: text2, citations }) {
12604
+ if (!text2.includes("\n")) {
12605
+ return /* @__PURE__ */ React12.createElement(InlineMd, { text: text2, citations });
12539
12606
  }
12540
- const rows = text.split("\n");
12541
- return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column" }, rows.map((row2, i) => (
12607
+ const rows = text2.split("\n");
12608
+ return /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column" }, rows.map((row2, i) => (
12542
12609
  // biome-ignore lint/suspicious/noArrayIndexKey: hard-break rows are source-ordered and never reorder
12543
- /* @__PURE__ */ React11.createElement(InlineMd, { key: `ln-${i}`, text: row2, citations })
12610
+ /* @__PURE__ */ React12.createElement(InlineMd, { key: `ln-${i}`, text: row2, citations })
12544
12611
  )));
12545
12612
  }
12546
12613
  function bulletPrefix(block, i, item) {
@@ -12553,8 +12620,8 @@ function BlockquoteView({
12553
12620
  block,
12554
12621
  citations
12555
12622
  }) {
12556
- return /* @__PURE__ */ React11.createElement(
12557
- Box10,
12623
+ return /* @__PURE__ */ React12.createElement(
12624
+ Box11,
12558
12625
  {
12559
12626
  borderStyle: "single",
12560
12627
  borderColor: "#c4b5fd",
@@ -12565,7 +12632,7 @@ function BlockquoteView({
12565
12632
  flexDirection: "column",
12566
12633
  gap: 1
12567
12634
  },
12568
- block.children.map((child, i) => /* @__PURE__ */ React11.createElement(BlockView, { key: `q-${i}-${child.kind}`, block: child, citations }))
12635
+ block.children.map((child, i) => /* @__PURE__ */ React12.createElement(BlockView, { key: `q-${i}-${child.kind}`, block: child, citations }))
12569
12636
  );
12570
12637
  }
12571
12638
  function splitTableRow(line) {
@@ -12583,14 +12650,14 @@ function TableBlockRow({ block, citations }) {
12583
12650
  widths.push(Math.min(40, Math.max(3, ...cellLengths)));
12584
12651
  }
12585
12652
  const separator = widths.map((w) => "\u2500".repeat(w)).join("\u2500\u253C\u2500");
12586
- return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Box10, null, block.header.map((cell, ci) => (
12653
+ return /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column" }, /* @__PURE__ */ React12.createElement(Box11, null, block.header.map((cell, ci) => (
12587
12654
  // biome-ignore lint/suspicious/noArrayIndexKey: table columns never reorder — derived from a static header array
12588
- /* @__PURE__ */ React11.createElement(Text9, { key: `h-${ci}`, bold: true, color: "cyan" }, /* @__PURE__ */ React11.createElement(InlineMd, { text: cell, padTo: widths[ci] ?? 3, citations }), ci < colCount - 1 ? " \u2502 " : "")
12589
- ))), /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, separator), block.rows.map((row2, ri) => (
12655
+ /* @__PURE__ */ React12.createElement(Text10, { key: `h-${ci}`, bold: true, color: "cyan" }, /* @__PURE__ */ React12.createElement(InlineMd, { text: cell, padTo: widths[ci] ?? 3, citations }), ci < colCount - 1 ? " \u2502 " : "")
12656
+ ))), /* @__PURE__ */ React12.createElement(Text10, { dimColor: true }, separator), block.rows.map((row2, ri) => (
12590
12657
  // biome-ignore lint/suspicious/noArrayIndexKey: table rows render in source order and don't reorder
12591
- /* @__PURE__ */ React11.createElement(Box10, { key: `r-${ri}` }, Array.from({ length: colCount }).map((_, ci) => (
12658
+ /* @__PURE__ */ React12.createElement(Box11, { key: `r-${ri}` }, Array.from({ length: colCount }).map((_, ci) => (
12592
12659
  // biome-ignore lint/suspicious/noArrayIndexKey: same — column axis is fixed by the table shape
12593
- /* @__PURE__ */ React11.createElement(Text9, { key: `c-${ri}-${ci}` }, /* @__PURE__ */ React11.createElement(InlineMd, { text: row2[ci] ?? "", padTo: widths[ci] ?? 3, citations }), ci < colCount - 1 ? " \u2502 " : "")
12660
+ /* @__PURE__ */ React12.createElement(Text10, { key: `c-${ri}-${ci}` }, /* @__PURE__ */ React12.createElement(InlineMd, { text: row2[ci] ?? "", padTo: widths[ci] ?? 3, citations }), ci < colCount - 1 ? " \u2502 " : "")
12594
12661
  )))
12595
12662
  )));
12596
12663
  }
@@ -12610,7 +12677,7 @@ function EditBlockRow({ block }) {
12610
12677
  const isNewFile = block.search.length === 0;
12611
12678
  const searchLines = block.search.split("\n");
12612
12679
  const replaceLines = block.replace.split("\n");
12613
- return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React11.createElement(Box10, null, /* @__PURE__ */ React11.createElement(Text9, { bold: true, color: "cyan" }, block.filename), isNewFile ? /* @__PURE__ */ React11.createElement(Text9, { color: "green", bold: true }, " (new file)") : null), isNewFile ? null : /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column", marginTop: 1 }, searchLines.map((line, i) => /* @__PURE__ */ React11.createElement(Text9, { key: `s-${i}-${line.length}`, color: "red" }, `- ${line}`))), /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column", marginTop: isNewFile ? 1 : 0 }, replaceLines.map((line, i) => /* @__PURE__ */ React11.createElement(Text9, { key: `r-${i}-${line.length}`, color: "green" }, `+ ${line}`))));
12680
+ return /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React12.createElement(Box11, null, /* @__PURE__ */ React12.createElement(Text10, { bold: true, color: "cyan" }, block.filename), isNewFile ? /* @__PURE__ */ React12.createElement(Text10, { color: "green", bold: true }, " (new file)") : null), isNewFile ? null : /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column", marginTop: 1 }, searchLines.map((line, i) => /* @__PURE__ */ React12.createElement(Text10, { key: `s-${i}-${line.length}`, color: "red" }, `- ${line}`))), /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column", marginTop: isNewFile ? 1 : 0 }, replaceLines.map((line, i) => /* @__PURE__ */ React12.createElement(Text10, { key: `r-${i}-${line.length}`, color: "green" }, `+ ${line}`))));
12614
12681
  }
12615
12682
  var DIAGRAM_LANGS = /* @__PURE__ */ new Set([
12616
12683
  "mermaid",
@@ -12632,48 +12699,48 @@ var DIAGRAM_VIEWER_HINT = {
12632
12699
  };
12633
12700
  function HeadingView({
12634
12701
  level,
12635
- text,
12702
+ text: text2,
12636
12703
  citations
12637
12704
  }) {
12638
12705
  if (level === 1) {
12639
- return /* @__PURE__ */ React11.createElement(Box10, { marginY: 1 }, /* @__PURE__ */ React11.createElement(Text9, { backgroundColor: "#67e8f9", color: "black", bold: true }, ` ${text} `));
12706
+ return /* @__PURE__ */ React12.createElement(Box11, { marginY: 1 }, /* @__PURE__ */ React12.createElement(Text10, { backgroundColor: "#67e8f9", color: "black", bold: true }, ` ${text2} `));
12640
12707
  }
12641
12708
  if (level === 2) {
12642
- return /* @__PURE__ */ React11.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text9, { backgroundColor: "#c4b5fd", color: "black", bold: true }, ` ${text} `));
12709
+ return /* @__PURE__ */ React12.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React12.createElement(Text10, { backgroundColor: "#c4b5fd", color: "black", bold: true }, ` ${text2} `));
12643
12710
  }
12644
12711
  if (level === 3) {
12645
- return /* @__PURE__ */ React11.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text9, { backgroundColor: "#f0abfc", color: "black", bold: true }, ` ${text} `));
12712
+ return /* @__PURE__ */ React12.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React12.createElement(Text10, { backgroundColor: "#f0abfc", color: "black", bold: true }, ` ${text2} `));
12646
12713
  }
12647
- return /* @__PURE__ */ React11.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text9, { bold: true, color: "#f0abfc" }, "\u25B8", " "), /* @__PURE__ */ React11.createElement(Text9, { bold: true }, /* @__PURE__ */ React11.createElement(InlineMd, { text, citations })));
12714
+ return /* @__PURE__ */ React12.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React12.createElement(Text10, { bold: true, color: "#f0abfc" }, "\u25B8", " "), /* @__PURE__ */ React12.createElement(Text10, { bold: true }, /* @__PURE__ */ React12.createElement(InlineMd, { text: text2, citations })));
12648
12715
  }
12649
- function CodeBlockView({ lang, text }) {
12716
+ function CodeBlockView({ lang, text: text2 }) {
12650
12717
  const langLabel = lang.trim();
12651
- return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "#7dd3fc", paddingX: 1 }, langLabel ? /* @__PURE__ */ React11.createElement(Box10, null, /* @__PURE__ */ React11.createElement(Text9, { backgroundColor: "#7dd3fc", color: "black", bold: true }, ` ${langLabel} `)) : null, /* @__PURE__ */ React11.createElement(Text9, { color: "#fde68a" }, text));
12718
+ return /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column", borderStyle: "round", borderColor: "#7dd3fc", paddingX: 1 }, langLabel ? /* @__PURE__ */ React12.createElement(Box11, null, /* @__PURE__ */ React12.createElement(Text10, { backgroundColor: "#7dd3fc", color: "black", bold: true }, ` ${langLabel} `)) : null, /* @__PURE__ */ React12.createElement(Text10, { color: "#fde68a" }, text2));
12652
12719
  }
12653
- function DiagramCodeBlock({ lang, text }) {
12720
+ function DiagramCodeBlock({ lang, text: text2 }) {
12654
12721
  const hint = DIAGRAM_VIEWER_HINT[lang.toLowerCase()] ?? "\u2192 render with the matching viewer to view";
12655
- return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column", borderStyle: "double", borderColor: "magenta", paddingX: 1 }, /* @__PURE__ */ React11.createElement(Text9, { bold: true, color: "magenta" }, `\u25C7 ${lang} diagram (source \u2014 terminal can't draw the graph)`), /* @__PURE__ */ React11.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text9, { color: "yellow" }, text)), /* @__PURE__ */ React11.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, hint)));
12722
+ return /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column", borderStyle: "double", borderColor: "magenta", paddingX: 1 }, /* @__PURE__ */ React12.createElement(Text10, { bold: true, color: "magenta" }, `\u25C7 ${lang} diagram (source \u2014 terminal can't draw the graph)`), /* @__PURE__ */ React12.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React12.createElement(Text10, { color: "yellow" }, text2)), /* @__PURE__ */ React12.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React12.createElement(Text10, { dimColor: true }, hint)));
12656
12723
  }
12657
- function Markdown({ text, projectRoot }) {
12658
- const cleaned = expandAutolinks(expandEmoji(stripMath(text)));
12724
+ function Markdown({ text: text2, projectRoot }) {
12725
+ const cleaned = expandAutolinks(expandEmoji(stripMath(text2)));
12659
12726
  const root = projectRoot ?? process.cwd();
12660
- const citations = React11.useMemo(() => collectCitations(cleaned, root), [cleaned, root]);
12661
- const blocks = React11.useMemo(() => parseBlocks(cleaned), [cleaned]);
12727
+ const citations = React12.useMemo(() => collectCitations(cleaned, root), [cleaned, root]);
12728
+ const blocks = React12.useMemo(() => parseBlocks(cleaned), [cleaned]);
12662
12729
  const broken = [];
12663
12730
  for (const [url, status2] of citations) {
12664
12731
  if (!status2.ok) broken.push({ url, reason: status2.reason });
12665
12732
  }
12666
- return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column", gap: 1 }, blocks.map((b, i) => /* @__PURE__ */ React11.createElement(BlockView, { key: `${i}-${b.kind}`, block: b, citations })), broken.length > 0 ? /* @__PURE__ */ React11.createElement(BrokenCitationsBlock, { items: broken }) : null);
12733
+ return /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column", gap: 1 }, blocks.map((b, i) => /* @__PURE__ */ React12.createElement(BlockView, { key: `${i}-${b.kind}`, block: b, citations })), broken.length > 0 ? /* @__PURE__ */ React12.createElement(BrokenCitationsBlock, { items: broken }) : null);
12667
12734
  }
12668
12735
  function BrokenCitationsBlock({ items }) {
12669
- return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 1 }, /* @__PURE__ */ React11.createElement(Text9, { color: "red", bold: true }, `\u26A0 ${items.length} broken citation${items.length > 1 ? "s" : ""} \u2014 the model referenced paths or lines that don't exist`), items.map((b, i) => (
12736
+ return /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 1 }, /* @__PURE__ */ React12.createElement(Text10, { color: "red", bold: true }, `\u26A0 ${items.length} broken citation${items.length > 1 ? "s" : ""} \u2014 the model referenced paths or lines that don't exist`), items.map((b, i) => (
12670
12737
  // biome-ignore lint/suspicious/noArrayIndexKey: list is derived from a Map iteration order, stable per render
12671
- /* @__PURE__ */ React11.createElement(Text9, { key: `bc-${i}`, color: "red" }, ` \u2717 ${b.url} \u2192 ${b.reason}`)
12738
+ /* @__PURE__ */ React12.createElement(Text10, { key: `bc-${i}`, color: "red" }, ` \u2717 ${b.url} \u2192 ${b.reason}`)
12672
12739
  )));
12673
12740
  }
12674
12741
 
12675
12742
  // src/cli/ui/ticker.tsx
12676
- import React12, { createContext as createContext2, useContext as useContext2, useEffect as useEffect2, useState as useState3 } from "react";
12743
+ import React13, { createContext as createContext2, useContext as useContext2, useEffect as useEffect2, useState as useState3 } from "react";
12677
12744
  var FAST_TICK_MS = 120;
12678
12745
  var SLOW_TICK_MS = 1e3;
12679
12746
  var FastTickContext = createContext2(0);
@@ -12690,7 +12757,7 @@ function TickerProvider({ children, disabled }) {
12690
12757
  clearInterval(slowId);
12691
12758
  };
12692
12759
  }, [disabled]);
12693
- return /* @__PURE__ */ React12.createElement(FastTickContext.Provider, { value: fast }, /* @__PURE__ */ React12.createElement(SlowTickContext.Provider, { value: slow }, children));
12760
+ return /* @__PURE__ */ React13.createElement(FastTickContext.Provider, { value: fast }, /* @__PURE__ */ React13.createElement(SlowTickContext.Provider, { value: slow }, children));
12694
12761
  }
12695
12762
  function useTick() {
12696
12763
  return useContext2(FastTickContext);
@@ -12711,8 +12778,8 @@ function clip(s, max) {
12711
12778
  if (s.length <= max) return s;
12712
12779
  return s.slice(0, Math.max(1, max - TRAILING_ELLIPSIS.length)) + TRAILING_ELLIPSIS;
12713
12780
  }
12714
- function firstNonEmptyLine(text) {
12715
- for (const line of text.split(/\r?\n/)) {
12781
+ function firstNonEmptyLine(text2) {
12782
+ for (const line of text2.split(/\r?\n/)) {
12716
12783
  const trimmed = line.trim();
12717
12784
  if (trimmed) return trimmed;
12718
12785
  }
@@ -12734,8 +12801,8 @@ function formatBytes(n) {
12734
12801
  if (n < 1e6) return `${(n / 1e3).toFixed(1)}KB`;
12735
12802
  return `${(n / 1e6).toFixed(1)}MB`;
12736
12803
  }
12737
- function formatLineCount(text) {
12738
- const lines = text.split(/\r?\n/).length;
12804
+ function formatLineCount(text2) {
12805
+ const lines = text2.split(/\r?\n/).length;
12739
12806
  return `${lines} line${lines === 1 ? "" : "s"}`;
12740
12807
  }
12741
12808
  function summarizeStructured(content) {
@@ -12846,24 +12913,24 @@ function RoleGlyph({
12846
12913
  glyph,
12847
12914
  color: color2
12848
12915
  }) {
12849
- return /* @__PURE__ */ React13.createElement(Text10, { color: color2, bold: true }, glyph);
12916
+ return /* @__PURE__ */ React14.createElement(Text11, { color: color2, bold: true }, glyph);
12850
12917
  }
12851
12918
  function ToolPill({ label, status: status2 }) {
12852
12919
  const color2 = status2 === "err" ? COLOR.toolErr : COLOR.tool;
12853
12920
  const symbol = status2 === "err" ? GLYPH.toolErr : GLYPH.toolOk;
12854
- return /* @__PURE__ */ React13.createElement(Text10, { color: color2, bold: true }, `${symbol} ${label}`);
12921
+ return /* @__PURE__ */ React14.createElement(Text11, { color: color2, bold: true }, `${symbol} ${label}`);
12855
12922
  }
12856
- function indentContinuationLines(text) {
12857
- if (!text.includes("\n")) return text;
12858
- return text.split("\n").join("\n ");
12923
+ function indentContinuationLines(text2) {
12924
+ if (!text2.includes("\n")) return text2;
12925
+ return text2.split("\n").join("\n ");
12859
12926
  }
12860
- var EventRow = React13.memo(function EventRow2({
12927
+ var EventRow = React14.memo(function EventRow2({
12861
12928
  event,
12862
12929
  projectRoot
12863
12930
  }) {
12864
12931
  if (event.role === "user") {
12865
- return /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column" }, event.leadSeparator ? /* @__PURE__ */ React13.createElement(TurnSeparator, null) : null, /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(RoleGlyph, { glyph: ROLE_GLYPH.user, color: "cyan" }), /* @__PURE__ */ React13.createElement(Text10, null, " "), /* @__PURE__ */ React13.createElement(
12866
- Box11,
12932
+ return /* @__PURE__ */ React14.createElement(Box12, { flexDirection: "column" }, event.leadSeparator ? /* @__PURE__ */ React14.createElement(TurnSeparator, null) : null, /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(RoleGlyph, { glyph: ROLE_GLYPH.user, color: "cyan" }), /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(
12933
+ Box12,
12867
12934
  {
12868
12935
  flexDirection: "column",
12869
12936
  borderStyle: "single",
@@ -12873,13 +12940,13 @@ var EventRow = React13.memo(function EventRow2({
12873
12940
  borderColor: COLOR.user,
12874
12941
  paddingLeft: 1
12875
12942
  },
12876
- /* @__PURE__ */ React13.createElement(Text10, null, indentContinuationLines(event.text))
12943
+ /* @__PURE__ */ React14.createElement(Text11, null, indentContinuationLines(event.text))
12877
12944
  )));
12878
12945
  }
12879
12946
  if (event.role === "assistant") {
12880
- if (event.streaming) return /* @__PURE__ */ React13.createElement(StreamingAssistant, { event });
12881
- return /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(RoleGlyph, { glyph: ROLE_GLYPH.assistant, color: "green" }), event.stats ? /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(Text10, null, " "), /* @__PURE__ */ React13.createElement(Text10, { backgroundColor: COLOR.assistant, color: "black", bold: true }, ` ${event.stats.model.replace(/^deepseek-/, "")} `)) : null), /* @__PURE__ */ React13.createElement(
12882
- Box11,
12947
+ if (event.streaming) return /* @__PURE__ */ React14.createElement(StreamingAssistant, { event });
12948
+ return /* @__PURE__ */ React14.createElement(Box12, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(RoleGlyph, { glyph: ROLE_GLYPH.assistant, color: "green" }), event.stats ? /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Text11, { backgroundColor: COLOR.assistant, color: "black", bold: true }, ` ${event.stats.model.replace(/^deepseek-/, "")} `)) : null), /* @__PURE__ */ React14.createElement(
12949
+ Box12,
12883
12950
  {
12884
12951
  flexDirection: "column",
12885
12952
  marginTop: 1,
@@ -12890,20 +12957,20 @@ var EventRow = React13.memo(function EventRow2({
12890
12957
  borderColor: COLOR.assistant,
12891
12958
  paddingLeft: 1
12892
12959
  },
12893
- event.branch ? /* @__PURE__ */ React13.createElement(BranchBlock, { branch: event.branch }) : null,
12894
- event.reasoning ? /* @__PURE__ */ React13.createElement(ReasoningBlock, { reasoning: event.reasoning }) : null,
12895
- !isPlanStateEmpty(event.planState) ? /* @__PURE__ */ React13.createElement(PlanStateBlock, { planState: event.planState }) : null,
12896
- event.text ? /* @__PURE__ */ React13.createElement(Markdown, { text: event.text, projectRoot }) : /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, "(empty body \u2014 likely tool-call only)"),
12897
- event.stats ? /* @__PURE__ */ React13.createElement(StatsLine, { stats: event.stats }) : null,
12898
- event.repair ? /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.accent }, event.repair) : null
12960
+ event.branch ? /* @__PURE__ */ React14.createElement(BranchBlock, { branch: event.branch }) : null,
12961
+ event.reasoning ? /* @__PURE__ */ React14.createElement(ReasoningBlock, { reasoning: event.reasoning }) : null,
12962
+ !isPlanStateEmpty(event.planState) ? /* @__PURE__ */ React14.createElement(PlanStateBlock, { planState: event.planState }) : null,
12963
+ event.text ? /* @__PURE__ */ React14.createElement(Markdown, { text: event.text, projectRoot }) : /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, "(empty body \u2014 likely tool-call only)"),
12964
+ event.stats ? /* @__PURE__ */ React14.createElement(StatsLine, { stats: event.stats }) : null,
12965
+ event.repair ? /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.accent }, event.repair) : null
12899
12966
  ));
12900
12967
  }
12901
12968
  if (event.role === "tool") {
12902
12969
  const isExplicitError = event.text.startsWith("ERROR:");
12903
12970
  const isEditFile = (event.toolName === "edit_file" || event.toolName?.endsWith("_edit_file")) && !isExplicitError;
12904
12971
  if (isEditFile) {
12905
- return /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(ToolPill, { label: event.toolName ?? "?", status: "ok" }), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, " diff:")), /* @__PURE__ */ React13.createElement(
12906
- Box11,
12972
+ return /* @__PURE__ */ React14.createElement(Box12, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(ToolPill, { label: event.toolName ?? "?", status: "ok" }), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, " diff:")), /* @__PURE__ */ React14.createElement(
12973
+ Box12,
12907
12974
  {
12908
12975
  flexDirection: "column",
12909
12976
  marginTop: 1,
@@ -12914,15 +12981,15 @@ var EventRow = React13.memo(function EventRow2({
12914
12981
  borderColor: COLOR.tool,
12915
12982
  paddingLeft: 1
12916
12983
  },
12917
- /* @__PURE__ */ React13.createElement(EditFileDiff, { text: event.text })
12984
+ /* @__PURE__ */ React14.createElement(EditFileDiff, { text: event.text })
12918
12985
  ));
12919
12986
  }
12920
12987
  const summary = summarizeToolResult(event.toolName ?? "?", event.text);
12921
12988
  const status2 = summary.isError ? "err" : "ok";
12922
12989
  const durationLabel = event.durationMs !== void 0 && event.durationMs >= 100 ? formatDuration(event.durationMs) : "";
12923
12990
  const indexHint = event.toolIndex !== void 0 ? ` /tool ${event.toolIndex}` : "";
12924
- return /* @__PURE__ */ React13.createElement(
12925
- Box11,
12991
+ return /* @__PURE__ */ React14.createElement(
12992
+ Box12,
12926
12993
  {
12927
12994
  borderStyle: "single",
12928
12995
  borderTop: false,
@@ -12931,16 +12998,16 @@ var EventRow = React13.memo(function EventRow2({
12931
12998
  borderColor: status2 === "err" ? COLOR.toolErr : COLOR.tool,
12932
12999
  paddingLeft: 1
12933
13000
  },
12934
- /* @__PURE__ */ React13.createElement(ToolPill, { label: event.toolName ?? "?", status: status2 }),
12935
- durationLabel ? /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` ${durationLabel}`) : null,
12936
- /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, " "),
12937
- /* @__PURE__ */ React13.createElement(Text10, { color: status2 === "err" ? "red" : void 0, dimColor: status2 === "ok" }, summary.summary),
12938
- indexHint ? /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, indexHint) : null
13001
+ /* @__PURE__ */ React14.createElement(ToolPill, { label: event.toolName ?? "?", status: status2 }),
13002
+ durationLabel ? /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` ${durationLabel}`) : null,
13003
+ /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, " "),
13004
+ /* @__PURE__ */ React14.createElement(Text11, { color: status2 === "err" ? "red" : void 0, dimColor: status2 === "ok" }, summary.summary),
13005
+ indexHint ? /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, indexHint) : null
12939
13006
  );
12940
13007
  }
12941
13008
  if (event.role === "error") {
12942
- return /* @__PURE__ */ React13.createElement(
12943
- Box11,
13009
+ return /* @__PURE__ */ React14.createElement(
13010
+ Box12,
12944
13011
  {
12945
13012
  marginTop: 1,
12946
13013
  borderStyle: "single",
@@ -12950,9 +13017,9 @@ var EventRow = React13.memo(function EventRow2({
12950
13017
  borderColor: COLOR.err,
12951
13018
  paddingLeft: 1
12952
13019
  },
12953
- /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.err, bold: true }, "\u2726 error"),
12954
- /* @__PURE__ */ React13.createElement(Text10, null, " "),
12955
- /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.err }, indentContinuationLines(event.text))
13020
+ /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.err, bold: true }, "\u2726 error"),
13021
+ /* @__PURE__ */ React14.createElement(Text11, null, " "),
13022
+ /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.err }, indentContinuationLines(event.text))
12956
13023
  );
12957
13024
  }
12958
13025
  if (event.role === "info") {
@@ -12964,8 +13031,8 @@ var EventRow = React13.memo(function EventRow2({
12964
13031
  else if (lead === "\u2713") leadColor = COLOR.ok;
12965
13032
  else if (lead === "\u2717" || lead === "\u2716") leadColor = COLOR.err;
12966
13033
  else if (lead === "\u21BB") leadColor = COLOR.primary;
12967
- return /* @__PURE__ */ React13.createElement(
12968
- Box11,
13034
+ return /* @__PURE__ */ React14.createElement(
13035
+ Box12,
12969
13036
  {
12970
13037
  borderStyle: "single",
12971
13038
  borderTop: false,
@@ -12974,19 +13041,19 @@ var EventRow = React13.memo(function EventRow2({
12974
13041
  borderColor: leadColor,
12975
13042
  paddingLeft: 1
12976
13043
  },
12977
- /* @__PURE__ */ React13.createElement(Text10, { color: leadColor, bold: true }, lead),
12978
- /* @__PURE__ */ React13.createElement(Text10, null, " "),
12979
- /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, body)
13044
+ /* @__PURE__ */ React14.createElement(Text11, { color: leadColor, bold: true }, lead),
13045
+ /* @__PURE__ */ React14.createElement(Text11, null, " "),
13046
+ /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, body)
12980
13047
  );
12981
13048
  }
12982
13049
  if (event.role === "plan") {
12983
- return /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(Text10, { bold: true, color: "cyan" }, "\u{1F4CB} plan proposed \u2014 pick a choice below")), /* @__PURE__ */ React13.createElement(Box11, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React13.createElement(Markdown, { text: event.text, projectRoot })));
13050
+ return /* @__PURE__ */ React14.createElement(Box12, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(Text11, { bold: true, color: "cyan" }, "\u{1F4CB} plan proposed \u2014 pick a choice below")), /* @__PURE__ */ React14.createElement(Box12, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Markdown, { text: event.text, projectRoot })));
12984
13051
  }
12985
13052
  if (event.role === "step-progress") {
12986
13053
  const sp = event.stepProgress;
12987
13054
  const counter = sp && sp.total > 0 ? `${sp.completed}/${sp.total}` : "";
12988
13055
  const label = sp?.title ? `${sp.stepId} \xB7 ${sp.title}` : sp?.stepId ?? "";
12989
- return /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(Text10, { backgroundColor: "#4ade80", color: "black", bold: true }, " \u2713 STEP "), counter ? /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(Text10, null, " "), /* @__PURE__ */ React13.createElement(Text10, { color: "#4ade80", bold: true }, counter)) : null, /* @__PURE__ */ React13.createElement(Text10, null, " "), /* @__PURE__ */ React13.createElement(Text10, { color: "#86efac" }, label)), event.text ? /* @__PURE__ */ React13.createElement(Box11, { paddingLeft: 2 }, /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, event.text)) : null, sp?.notes ? /* @__PURE__ */ React13.createElement(Box11, { paddingLeft: 2 }, /* @__PURE__ */ React13.createElement(Text10, { color: "#fbbf24", dimColor: true }, `note: ${sp.notes}`)) : null);
13056
+ return /* @__PURE__ */ React14.createElement(Box12, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(Text11, { backgroundColor: "#4ade80", color: "black", bold: true }, " \u2713 STEP "), counter ? /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Text11, { color: "#4ade80", bold: true }, counter)) : null, /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Text11, { color: "#86efac" }, label)), event.text ? /* @__PURE__ */ React14.createElement(Box12, { paddingLeft: 2 }, /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, event.text)) : null, sp?.notes ? /* @__PURE__ */ React14.createElement(Box12, { paddingLeft: 2 }, /* @__PURE__ */ React14.createElement(Text11, { color: "#fbbf24", dimColor: true }, `note: ${sp.notes}`)) : null);
12990
13057
  }
12991
13058
  if (event.role === "plan-resumed") {
12992
13059
  const rp = event.resumedPlan;
@@ -13001,7 +13068,7 @@ var EventRow = React13.memo(function EventRow2({
13001
13068
  ])
13002
13069
  );
13003
13070
  const nextStep = rp.steps.find((s) => !completedSet.has(s.id));
13004
- return /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(Text10, { backgroundColor: "#67e8f9", color: "black", bold: true }, " \u21BB RESUMED PLAN "), /* @__PURE__ */ React13.createElement(Text10, null, " "), /* @__PURE__ */ React13.createElement(Text10, { color: "#67e8f9", bold: true }, `${done}/${total}`), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` done \xB7 last touched ${rp.relativeTime}`)), rp.summary ? /* @__PURE__ */ React13.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text10, { color: "#67e8f9" }, rp.summary)) : null, /* @__PURE__ */ React13.createElement(Box11, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React13.createElement(PlanStepList, { steps: rp.steps, statuses, focusStepId: nextStep?.id })));
13071
+ return /* @__PURE__ */ React14.createElement(Box12, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(Text11, { backgroundColor: "#67e8f9", color: "black", bold: true }, " \u21BB RESUMED PLAN "), /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Text11, { color: "#67e8f9", bold: true }, `${done}/${total}`), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` done \xB7 last touched ${rp.relativeTime}`)), rp.summary ? /* @__PURE__ */ React14.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text11, { color: "#67e8f9" }, rp.summary)) : null, /* @__PURE__ */ React14.createElement(Box12, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React14.createElement(PlanStepList, { steps: rp.steps, statuses, focusStepId: nextStep?.id })));
13005
13072
  }
13006
13073
  if (event.role === "plan-replay") {
13007
13074
  const r = event.replayPlan;
@@ -13013,11 +13080,11 @@ var EventRow = React13.memo(function EventRow2({
13013
13080
  r.steps.map((s) => [s.id, completedSet.has(s.id) ? "done" : "pending"])
13014
13081
  );
13015
13082
  const navHint = r.total > 1 ? ` \xB7 ${r.index}/${r.total}` : "";
13016
- return /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(Text10, { backgroundColor: "#94a3b8", color: "black", bold: true }, " \u23EA REPLAY "), /* @__PURE__ */ React13.createElement(Text10, null, " "), /* @__PURE__ */ React13.createElement(Text10, { color: "#94a3b8", bold: true }, `${done}/${total}`), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` done \xB7 ${r.relativeTime}${navHint}`)), r.summary ? /* @__PURE__ */ React13.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text10, { color: "#94a3b8" }, r.summary)) : null, /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, r.archiveBasename)), r.body ? /* @__PURE__ */ React13.createElement(Box11, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React13.createElement(Markdown, { text: r.body, projectRoot })) : null, /* @__PURE__ */ React13.createElement(Box11, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React13.createElement(PlanStepList, { steps: r.steps, statuses })), /* @__PURE__ */ React13.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, r.total > 1 ? `(read-only \xB7 /replay ${r.index === 1 ? 2 : 1} for the ${r.index === 1 ? "next" : "newest"} archive)` : "(read-only \xB7 this is an archived plan)")));
13083
+ return /* @__PURE__ */ React14.createElement(Box12, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(Text11, { backgroundColor: "#94a3b8", color: "black", bold: true }, " \u23EA REPLAY "), /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Text11, { color: "#94a3b8", bold: true }, `${done}/${total}`), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` done \xB7 ${r.relativeTime}${navHint}`)), r.summary ? /* @__PURE__ */ React14.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text11, { color: "#94a3b8" }, r.summary)) : null, /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, r.archiveBasename)), r.body ? /* @__PURE__ */ React14.createElement(Box12, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Markdown, { text: r.body, projectRoot })) : null, /* @__PURE__ */ React14.createElement(Box12, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React14.createElement(PlanStepList, { steps: r.steps, statuses })), /* @__PURE__ */ React14.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, r.total > 1 ? `(read-only \xB7 /replay ${r.index === 1 ? 2 : 1} for the ${r.index === 1 ? "next" : "newest"} archive)` : "(read-only \xB7 this is an archived plan)")));
13017
13084
  }
13018
13085
  if (event.role === "warning") {
13019
- return /* @__PURE__ */ React13.createElement(
13020
- Box11,
13086
+ return /* @__PURE__ */ React14.createElement(
13087
+ Box12,
13021
13088
  {
13022
13089
  borderStyle: "single",
13023
13090
  borderTop: false,
@@ -13026,53 +13093,53 @@ var EventRow = React13.memo(function EventRow2({
13026
13093
  borderColor: COLOR.warn,
13027
13094
  paddingLeft: 1
13028
13095
  },
13029
- /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.warn, bold: true }, "\u25B2 warn"),
13030
- /* @__PURE__ */ React13.createElement(Text10, null, " "),
13031
- /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.warn }, indentContinuationLines(event.text))
13096
+ /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.warn, bold: true }, "\u25B2 warn"),
13097
+ /* @__PURE__ */ React14.createElement(Text11, null, " "),
13098
+ /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.warn }, indentContinuationLines(event.text))
13032
13099
  );
13033
13100
  }
13034
13101
  if (event.role === "ctx-breakdown" && event.ctxBreakdown) {
13035
- return /* @__PURE__ */ React13.createElement(CtxBreakdownBlock, { data: event.ctxBreakdown });
13102
+ return /* @__PURE__ */ React14.createElement(CtxBreakdownBlock, { data: event.ctxBreakdown });
13036
13103
  }
13037
- return /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(Text10, null, event.text));
13104
+ return /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(Text11, null, event.text));
13038
13105
  });
13039
13106
  function TurnSeparator() {
13040
- const { stdout: stdout4 } = useStdout4();
13107
+ const { stdout: stdout4 } = useStdout5();
13041
13108
  const cols = stdout4?.columns ?? 80;
13042
13109
  const width = Math.max(16, cols - 2);
13043
13110
  const sideWidth = Math.max(2, Math.floor((width - 5) / 2));
13044
13111
  const leftCells = gradientCells(sideWidth, "\u2500");
13045
13112
  const rightCells = gradientCells(sideWidth, "\u2500");
13046
- return /* @__PURE__ */ React13.createElement(Box11, { marginTop: 1, marginBottom: 1 }, leftCells.map((c, i) => (
13113
+ return /* @__PURE__ */ React14.createElement(Box12, { marginTop: 1, marginBottom: 1 }, leftCells.map((c, i) => (
13047
13114
  // biome-ignore lint/suspicious/noArrayIndexKey: fixed-width gradient row
13048
- /* @__PURE__ */ React13.createElement(Text10, { key: `tsep-l-${i}`, color: c.color }, c.ch)
13049
- )), /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.brand, bold: true }, " \u25C6 "), rightCells.map((c, i) => (
13115
+ /* @__PURE__ */ React14.createElement(Text11, { key: `tsep-l-${i}`, color: c.color }, c.ch)
13116
+ )), /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.brand, bold: true }, " \u25C6 "), rightCells.map((c, i) => (
13050
13117
  // biome-ignore lint/suspicious/noArrayIndexKey: fixed-width gradient row
13051
- /* @__PURE__ */ React13.createElement(Text10, { key: `tsep-r-${i}`, color: c.color }, c.ch)
13118
+ /* @__PURE__ */ React14.createElement(Text11, { key: `tsep-r-${i}`, color: c.color }, c.ch)
13052
13119
  )));
13053
13120
  }
13054
- function EditFileDiff({ text }) {
13055
- const lines = text.split(/\r?\n/);
13121
+ function EditFileDiff({ text: text2 }) {
13122
+ const lines = text2.split(/\r?\n/);
13056
13123
  const [statusHeader, hunkHeader, ...body] = lines;
13057
- return /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column" }, /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` ${statusHeader ?? ""}`), hunkHeader !== void 0 ? /* @__PURE__ */ React13.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text10, { backgroundColor: "#c4b5fd", color: "black", bold: true }, ` ${hunkHeader.trim()} `)) : null, body.map((line, i) => {
13124
+ return /* @__PURE__ */ React14.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` ${statusHeader ?? ""}`), hunkHeader !== void 0 ? /* @__PURE__ */ React14.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text11, { backgroundColor: "#c4b5fd", color: "black", bold: true }, ` ${hunkHeader.trim()} `)) : null, body.map((line, i) => {
13058
13125
  const key = `${i}-${line.slice(0, 32)}`;
13059
13126
  const stripped = line.replace(/^ {2}/, "");
13060
13127
  if (stripped.startsWith("- ")) {
13061
- return /* @__PURE__ */ React13.createElement(Box11, { key }, /* @__PURE__ */ React13.createElement(Text10, { color: "#f87171", bold: true }, "\u2212 "), /* @__PURE__ */ React13.createElement(Text10, { color: "#fca5a5" }, stripped.slice(2)));
13128
+ return /* @__PURE__ */ React14.createElement(Box12, { key }, /* @__PURE__ */ React14.createElement(Text11, { color: "#f87171", bold: true }, "\u2212 "), /* @__PURE__ */ React14.createElement(Text11, { color: "#fca5a5" }, stripped.slice(2)));
13062
13129
  }
13063
13130
  if (stripped.startsWith("+ ")) {
13064
- return /* @__PURE__ */ React13.createElement(Box11, { key }, /* @__PURE__ */ React13.createElement(Text10, { color: "#4ade80", bold: true }, "+ "), /* @__PURE__ */ React13.createElement(Text10, { color: "#86efac" }, stripped.slice(2)));
13131
+ return /* @__PURE__ */ React14.createElement(Box12, { key }, /* @__PURE__ */ React14.createElement(Text11, { color: "#4ade80", bold: true }, "+ "), /* @__PURE__ */ React14.createElement(Text11, { color: "#86efac" }, stripped.slice(2)));
13065
13132
  }
13066
- return /* @__PURE__ */ React13.createElement(Box11, { key }, /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, " "), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, stripped));
13133
+ return /* @__PURE__ */ React14.createElement(Box12, { key }, /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, " "), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, stripped));
13067
13134
  }));
13068
13135
  }
13069
13136
  function BranchBlock({ branch: branch2 }) {
13070
- return /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(Text10, { backgroundColor: "#93c5fd", color: "black", bold: true }, ` \u2387 BRANCH \xD7${branch2.budget} `), /* @__PURE__ */ React13.createElement(Text10, null, " "), /* @__PURE__ */ React13.createElement(Text10, { color: "#93c5fd" }, "picked "), /* @__PURE__ */ React13.createElement(Text10, { color: "#93c5fd", bold: true }, "#", branch2.chosenIndex)), /* @__PURE__ */ React13.createElement(Box11, { paddingLeft: 2, marginTop: 1 }, branch2.uncertainties.map((u, i) => {
13137
+ return /* @__PURE__ */ React14.createElement(Box12, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(Text11, { backgroundColor: "#93c5fd", color: "black", bold: true }, ` \u2387 BRANCH \xD7${branch2.budget} `), /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Text11, { color: "#93c5fd" }, "picked "), /* @__PURE__ */ React14.createElement(Text11, { color: "#93c5fd", bold: true }, "#", branch2.chosenIndex)), /* @__PURE__ */ React14.createElement(Box12, { paddingLeft: 2, marginTop: 1 }, branch2.uncertainties.map((u, i) => {
13071
13138
  const chosen = i === branch2.chosenIndex;
13072
13139
  const t2 = (branch2.temperatures[i] ?? 0).toFixed(1);
13073
13140
  return (
13074
13141
  // biome-ignore lint/suspicious/noArrayIndexKey: branch index is positional and stable
13075
- /* @__PURE__ */ React13.createElement(Text10, { key: `b-${i}` }, /* @__PURE__ */ React13.createElement(Text10, { color: chosen ? "#93c5fd" : "#475569", bold: chosen }, chosen ? "\u25B8 " : " "), /* @__PURE__ */ React13.createElement(Text10, { color: chosen ? "#93c5fd" : "#94a3b8", bold: chosen }, `#${i}`), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` T=${t2} u=${u} `))
13142
+ /* @__PURE__ */ React14.createElement(Text11, { key: `b-${i}` }, /* @__PURE__ */ React14.createElement(Text11, { color: chosen ? "#93c5fd" : "#475569", bold: chosen }, chosen ? "\u25B8 " : " "), /* @__PURE__ */ React14.createElement(Text11, { color: chosen ? "#93c5fd" : "#94a3b8", bold: chosen }, `#${i}`), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` T=${t2} u=${u} `))
13076
13143
  );
13077
13144
  })));
13078
13145
  }
@@ -13090,8 +13157,8 @@ function CtxBreakdownBlock({
13090
13157
  const used = sysCells + toolsCells + logCells + inputCells;
13091
13158
  const freeCells = Math.max(0, barWidth - used);
13092
13159
  const sevColor = winPct >= 80 ? COLOR.err : winPct >= 60 ? COLOR.warn : COLOR.ok;
13093
- return /* @__PURE__ */ React13.createElement(
13094
- Box11,
13160
+ return /* @__PURE__ */ React14.createElement(
13161
+ Box12,
13095
13162
  {
13096
13163
  flexDirection: "column",
13097
13164
  marginY: 1,
@@ -13102,11 +13169,11 @@ function CtxBreakdownBlock({
13102
13169
  borderColor: COLOR.brand,
13103
13170
  paddingLeft: 1
13104
13171
  },
13105
- /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.brand, bold: true }, "\u25A3 context"), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` ${formatTokensCompact(total)} of ${formatTokensCompact(data.ctxMax)}`), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React13.createElement(Text10, { color: sevColor, bold: true }, `${winPct}%`), winPct >= 80 ? /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.err, bold: true }, " \xB7 /compact") : null),
13106
- /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.brand }, "\u2588".repeat(sysCells)), /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.accent }, "\u2588".repeat(toolsCells)), /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.primary }, "\u2588".repeat(logCells)), /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.tool }, "\u2588".repeat(inputCells)), /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.info, dimColor: true }, "\u2591".repeat(freeCells))),
13107
- /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.brand }, "\u25A0"), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` system ${formatTokensCompact(data.systemTokens)}`), /* @__PURE__ */ React13.createElement(Text10, null, " "), /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.accent }, "\u25A0"), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` tools ${formatTokensCompact(data.toolsTokens)}`), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` (${data.toolsCount})`), /* @__PURE__ */ React13.createElement(Text10, null, " "), /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.primary }, "\u25A0"), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` log ${formatTokensCompact(data.logTokens)}`), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` (${data.logMessages} msg)`), /* @__PURE__ */ React13.createElement(Text10, null, " "), /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.tool }, "\u25A0"), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` input ${formatTokensCompact(data.inputTokens)}`)),
13108
- data.topTools.length > 0 ? /* @__PURE__ */ React13.createElement(Box11, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` top tool results by cost (${data.topTools.length}):`), data.topTools.map((t2) => /* @__PURE__ */ React13.createElement(Box11, { key: `${t2.turn}-${t2.name}` }, /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` turn ${String(t2.turn).padStart(3)} `), /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.info }, t2.name.padEnd(22)), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` ${formatTokensCompact(t2.tokens).padStart(8)}`)))) : null,
13109
- /* @__PURE__ */ React13.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, " /compact shrinks oversized tool results \xB7 /new wipes log"))
13172
+ /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.brand, bold: true }, "\u25A3 context"), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` ${formatTokensCompact(total)} of ${formatTokensCompact(data.ctxMax)}`), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React14.createElement(Text11, { color: sevColor, bold: true }, `${winPct}%`), winPct >= 80 ? /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.err, bold: true }, " \xB7 /compact") : null),
13173
+ /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.brand }, "\u2588".repeat(sysCells)), /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.accent }, "\u2588".repeat(toolsCells)), /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.primary }, "\u2588".repeat(logCells)), /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.tool }, "\u2588".repeat(inputCells)), /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.info, dimColor: true }, "\u2591".repeat(freeCells))),
13174
+ /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.brand }, "\u25A0"), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` system ${formatTokensCompact(data.systemTokens)}`), /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.accent }, "\u25A0"), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` tools ${formatTokensCompact(data.toolsTokens)}`), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` (${data.toolsCount})`), /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.primary }, "\u25A0"), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` log ${formatTokensCompact(data.logTokens)}`), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` (${data.logMessages} msg)`), /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.tool }, "\u25A0"), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` input ${formatTokensCompact(data.inputTokens)}`)),
13175
+ data.topTools.length > 0 ? /* @__PURE__ */ React14.createElement(Box12, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` top tool results by cost (${data.topTools.length}):`), data.topTools.map((t2) => /* @__PURE__ */ React14.createElement(Box12, { key: `${t2.turn}-${t2.name}` }, /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` turn ${String(t2.turn).padStart(3)} `), /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.info }, t2.name.padEnd(22)), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` ${formatTokensCompact(t2.tokens).padStart(8)}`)))) : null,
13176
+ /* @__PURE__ */ React14.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, " /compact shrinks oversized tool results \xB7 /new wipes log"))
13110
13177
  );
13111
13178
  }
13112
13179
  function formatTokensCompact(n) {
@@ -13120,8 +13187,8 @@ function ReasoningBlock({ reasoning }) {
13120
13187
  const preview = flat.length <= max ? flat : `\u2026 (+${flat.length - max} earlier chars) ${flat.slice(-max)}`;
13121
13188
  const tokensApprox = Math.max(1, Math.round(flat.length / 4.5));
13122
13189
  const tokLabel = tokensApprox >= 1e3 ? `${(tokensApprox / 1e3).toFixed(1)}k` : `${tokensApprox}`;
13123
- return /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.accent, bold: true }, "R1 \u21AF"), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, ` reasoning \xB7 ~${tokLabel} tok \xB7 /think for full`)), /* @__PURE__ */ React13.createElement(
13124
- Box11,
13190
+ return /* @__PURE__ */ React14.createElement(Box12, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.accent, bold: true }, "R1 \u21AF"), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` reasoning \xB7 ~${tokLabel} tok \xB7 /think for full`)), /* @__PURE__ */ React14.createElement(
13191
+ Box12,
13125
13192
  {
13126
13193
  borderStyle: "single",
13127
13194
  borderTop: false,
@@ -13130,35 +13197,35 @@ function ReasoningBlock({ reasoning }) {
13130
13197
  borderColor: COLOR.accent,
13131
13198
  paddingLeft: 1
13132
13199
  },
13133
- /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.accent, italic: true, dimColor: true }, preview)
13200
+ /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.accent, italic: true, dimColor: true }, preview)
13134
13201
  ));
13135
13202
  }
13136
13203
  function Elapsed() {
13137
13204
  const s = useElapsedSeconds();
13138
13205
  const mm = String(Math.floor(s / 60)).padStart(2, "0");
13139
13206
  const ss = String(s % 60).padStart(2, "0");
13140
- return /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, `${mm}:${ss}`);
13207
+ return /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, `${mm}:${ss}`);
13141
13208
  }
13142
13209
  function PulsingAssistantGlyph() {
13143
- return /* @__PURE__ */ React13.createElement(Text10, { color: "green", bold: true }, ROLE_GLYPH.assistant);
13210
+ return /* @__PURE__ */ React14.createElement(Text11, { color: "green", bold: true }, ROLE_GLYPH.assistant);
13144
13211
  }
13145
13212
  function StreamingAssistant({ event }) {
13146
13213
  if (event.branchProgress) {
13147
13214
  const p = event.branchProgress;
13148
13215
  if (p.completed === 0) {
13149
- return /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React13.createElement(Text10, { color: "blue" }, " \u2387 launching ", p.total, " parallel samples (R1 thinking in parallel)\u2026 "), /* @__PURE__ */ React13.createElement(Elapsed, null)), /* @__PURE__ */ React13.createElement(Text10, { color: "yellow" }, " ", "spread across T=0.0/0.5/1.0 \xB7 reasoner typically takes 30-90s \u2014 this is normal"));
13216
+ return /* @__PURE__ */ React14.createElement(Box12, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React14.createElement(Text11, { color: "blue" }, " \u2387 launching ", p.total, " parallel samples (R1 thinking in parallel)\u2026 "), /* @__PURE__ */ React14.createElement(Elapsed, null)), /* @__PURE__ */ React14.createElement(Text11, { color: "yellow" }, " ", "spread across T=0.0/0.5/1.0 \xB7 reasoner typically takes 30-90s \u2014 this is normal"));
13150
13217
  }
13151
13218
  const pct2 = Math.round(p.completed / p.total * 100);
13152
- return /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React13.createElement(Text10, { color: "blue" }, " \u2387 branching ", p.completed, "/", p.total, " (", pct2, "%) "), /* @__PURE__ */ React13.createElement(Elapsed, null)), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, " latest #", p.latestIndex, " T=", p.latestTemperature.toFixed(1), " u=", p.latestUncertainties, p.completed < p.total ? " \xB7 waiting for other samples\u2026" : " \xB7 selecting winner\u2026"));
13219
+ return /* @__PURE__ */ React14.createElement(Box12, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React14.createElement(Text11, { color: "blue" }, " \u2387 branching ", p.completed, "/", p.total, " (", pct2, "%) "), /* @__PURE__ */ React14.createElement(Elapsed, null)), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, " latest #", p.latestIndex, " T=", p.latestTemperature.toFixed(1), " u=", p.latestUncertainties, p.completed < p.total ? " \xB7 waiting for other samples\u2026" : " \xB7 selecting winner\u2026"));
13153
13220
  }
13154
- const tail = lastLine(event.text, 140);
13155
- const reasoningTail = event.reasoning ? lastLine(event.reasoning, 120) : "";
13156
13221
  const toolCallBuild = event.toolCallBuild;
13157
- const preFirstByte = !event.text && !event.reasoning && !toolCallBuild;
13158
- const reasoningOnly = !event.text && !!event.reasoning && !toolCallBuild;
13159
- const toolCallOnly = !event.text && !event.reasoning && !!toolCallBuild;
13160
- let phaseVerb;
13161
- let phaseColor;
13222
+ const text2 = event.text;
13223
+ const reasoning = event.reasoning;
13224
+ const preFirstByte = !text2 && !reasoning && !toolCallBuild;
13225
+ const reasoningOnly = !text2 && !!reasoning && !toolCallBuild;
13226
+ const toolCallOnly = !text2 && !reasoning && !!toolCallBuild;
13227
+ let phaseVerb = null;
13228
+ let phaseColor = COLOR.assistant;
13162
13229
  if (preFirstByte) {
13163
13230
  phaseVerb = "waiting";
13164
13231
  phaseColor = COLOR.warn;
@@ -13168,13 +13235,11 @@ function StreamingAssistant({ event }) {
13168
13235
  } else if (toolCallOnly) {
13169
13236
  phaseVerb = `dispatching ${toolCallBuild.name}`;
13170
13237
  phaseColor = COLOR.accent;
13171
- } else {
13172
- phaseVerb = event.reasoning ? "writing (after R1)" : "writing";
13173
- phaseColor = COLOR.assistant;
13174
13238
  }
13175
- const detail = tail || (reasoningTail ? `\u21B3 ${reasoningTail}` : "") || (preFirstByte ? "waiting for first byte \u2014 5-60s typical" : reasoningOnly ? `R1 thinking \xB7 ~${Math.round((event.reasoning?.length ?? 0) / 4)} tok so far` : toolCallOnly ? `assembling ${toolCallBuild.name}${formatToolCallIndex(toolCallBuild)} \xB7 ${toolCallBuild.chars} chars${formatReadyTail(toolCallBuild)}` : event.reasoning ? "R1 still reasoning \u2014 body or tool call arrives when thinking finishes" : "");
13176
- return /* @__PURE__ */ React13.createElement(Box11, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React13.createElement(Box11, null, /* @__PURE__ */ React13.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React13.createElement(Text10, null, " "), /* @__PURE__ */ React13.createElement(Pulse, null), /* @__PURE__ */ React13.createElement(Text10, null, " "), /* @__PURE__ */ React13.createElement(Text10, { color: phaseColor, bold: true }, phaseVerb), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React13.createElement(Elapsed, null)), /* @__PURE__ */ React13.createElement(
13177
- Box11,
13239
+ const verb = phaseVerb ?? "responding";
13240
+ const verbColor = phaseVerb ? phaseColor : COLOR.info;
13241
+ return /* @__PURE__ */ React14.createElement(Box12, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Text11, { color: verbColor, dimColor: !phaseVerb }, verb), /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Marquee, null), /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Elapsed, null)), /* @__PURE__ */ React14.createElement(
13242
+ Box12,
13178
13243
  {
13179
13244
  marginTop: 1,
13180
13245
  borderStyle: "single",
@@ -13185,13 +13250,24 @@ function StreamingAssistant({ event }) {
13185
13250
  paddingLeft: 1,
13186
13251
  flexDirection: "column"
13187
13252
  },
13188
- detail ? /* @__PURE__ */ React13.createElement(Text10, { dimColor: true, wrap: "truncate-end" }, detail, /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.primary }, " \u258C")) : /* @__PURE__ */ React13.createElement(Text10, { color: COLOR.primary }, "\u258C")
13253
+ reasoning ? /* @__PURE__ */ React14.createElement(ReasoningBlock, { reasoning }) : null,
13254
+ text2 ? /* @__PURE__ */ React14.createElement(Text11, null, text2, /* @__PURE__ */ React14.createElement(BlinkingCursor, null)) : /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, preFirstByte ? "waiting for first byte \u2014 5-60s typical" : reasoningOnly ? `R1 thinking \xB7 ~${Math.round((reasoning?.length ?? 0) / 4)} tok so far` : toolCallOnly ? `assembling ${toolCallBuild.name}${formatToolCallIndex(toolCallBuild)} \xB7 ${toolCallBuild.chars} chars${formatReadyTail(toolCallBuild)}` : "", /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(BlinkingCursor, null))
13189
13255
  ));
13190
13256
  }
13191
- function Pulse() {
13257
+ function BlinkingCursor() {
13192
13258
  const tick = useTick();
13193
- const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
13194
- return /* @__PURE__ */ React13.createElement(Text10, { color: "cyan" }, frames[Math.floor(tick / 4) % frames.length]);
13259
+ const visible = Math.floor(tick / 4) % 2 === 0;
13260
+ return /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.primary }, visible ? "\u258C" : " ");
13261
+ }
13262
+ var MARQUEE_W = 12;
13263
+ var MARQUEE_WAVE = ["\u2592", "\u2593", "\u2588", "\u2593", "\u2592"];
13264
+ function Marquee() {
13265
+ const tick = useTick();
13266
+ const cells = new Array(MARQUEE_W).fill("\u2591");
13267
+ for (let i = 0; i < MARQUEE_WAVE.length; i++) {
13268
+ cells[(tick + i) % MARQUEE_W] = MARQUEE_WAVE[i];
13269
+ }
13270
+ return /* @__PURE__ */ React14.createElement(Text11, { color: COLOR.primary }, cells.join(""));
13195
13271
  }
13196
13272
  function formatToolCallIndex(tb) {
13197
13273
  if (!tb || tb.index === void 0) return "";
@@ -13203,26 +13279,20 @@ function formatReadyTail(tb) {
13203
13279
  if (n <= 0) return "";
13204
13280
  return ` \xB7 ${n} ready`;
13205
13281
  }
13206
- function lastLine(s, maxChars) {
13207
- const tailSlice = s.length > maxChars * 4 ? s.slice(-maxChars * 4) : s;
13208
- const flat = tailSlice.replace(/\s+/g, " ").trim();
13209
- if (!flat) return "";
13210
- return flat.length <= maxChars ? flat : `\u2026${flat.slice(-maxChars)}`;
13211
- }
13212
13282
  function StatsLine({ stats: stats2 }) {
13213
13283
  const hit = (stats2.cacheHitRatio * 100).toFixed(1);
13214
13284
  const hitColor = stats2.cacheHitRatio >= 0.7 ? "#4ade80" : stats2.cacheHitRatio >= 0.4 ? "#fcd34d" : "#f87171";
13215
- return /* @__PURE__ */ React13.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text10, { color: hitColor, bold: true }, `\u232C ${hit}%`), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React13.createElement(Text10, { color: "#94a3b8" }, "in ", /* @__PURE__ */ React13.createElement(Text10, { color: "#67e8f9", bold: true }, stats2.usage.promptTokens), " \u2192 out ", /* @__PURE__ */ React13.createElement(Text10, { color: "#c4b5fd", bold: true }, stats2.usage.completionTokens)), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React13.createElement(Text10, { color: "#86efac", bold: true }, `$${stats2.cost.toFixed(6)}`));
13285
+ return /* @__PURE__ */ React14.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text11, { color: hitColor, bold: true }, `\u232C ${hit}%`), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React14.createElement(Text11, { color: "#94a3b8" }, "in ", /* @__PURE__ */ React14.createElement(Text11, { color: "#67e8f9", bold: true }, stats2.usage.promptTokens), " \u2192 out ", /* @__PURE__ */ React14.createElement(Text11, { color: "#c4b5fd", bold: true }, stats2.usage.completionTokens)), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React14.createElement(Text11, { color: "#86efac", bold: true }, `$${stats2.cost.toFixed(6)}`));
13216
13286
  }
13217
13287
 
13218
13288
  // src/cli/ui/LiveRows.tsx
13219
- import { Box as Box12, Text as Text11, useStdout as useStdout5 } from "ink";
13220
- import React14 from "react";
13289
+ import { Box as Box13, Text as Text12, useStdout as useStdout6 } from "ink";
13290
+ import React15 from "react";
13221
13291
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
13222
- function StatusRow({ text }) {
13292
+ function StatusRow({ text: text2 }) {
13223
13293
  const tick = useTick();
13224
13294
  const elapsed = useElapsedSeconds();
13225
- return /* @__PURE__ */ React14.createElement(Box12, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React14.createElement(Text11, { color: "#c4b5fd", bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Text11, { color: "#c4b5fd" }, text), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` \xB7 ${elapsed}s`));
13295
+ return /* @__PURE__ */ React15.createElement(Box13, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React15.createElement(Text12, { color: "#c4b5fd", bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React15.createElement(Text12, null, " "), /* @__PURE__ */ React15.createElement(Text12, { color: "#c4b5fd" }, text2), /* @__PURE__ */ React15.createElement(Text12, { dimColor: true }, ` \xB7 ${elapsed}s`));
13226
13296
  }
13227
13297
  function ModeStatusBar({
13228
13298
  editMode,
@@ -13234,27 +13304,27 @@ function ModeStatusBar({
13234
13304
  }) {
13235
13305
  useSlowTick();
13236
13306
  const running = jobs2?.runningCount() ?? 0;
13237
- const jobsTag = running > 0 ? /* @__PURE__ */ React14.createElement(Text11, { color: "yellow", bold: true }, ` \xB7 \u23F5 ${running} job${running === 1 ? "" : "s"}`) : null;
13307
+ const jobsTag = running > 0 ? /* @__PURE__ */ React15.createElement(Text12, { color: "yellow", bold: true }, ` \xB7 \u23F5 ${running} job${running === 1 ? "" : "s"}`) : null;
13238
13308
  if (planMode) {
13239
- return /* @__PURE__ */ React14.createElement(ModeBarFrame, null, /* @__PURE__ */ React14.createElement(ModePill, { label: "PLAN MODE", bg: "red", flash }), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, " writes gated \xB7 /plan off to leave"), jobsTag);
13309
+ return /* @__PURE__ */ React15.createElement(ModeBarFrame, null, /* @__PURE__ */ React15.createElement(ModePill, { label: "PLAN MODE", bg: "red", flash }), /* @__PURE__ */ React15.createElement(Text12, { dimColor: true }, " writes gated \xB7 /plan off to leave"), jobsTag);
13240
13310
  }
13241
13311
  const label = editMode === "yolo" ? "YOLO" : editMode === "auto" ? "AUTO" : "REVIEW";
13242
13312
  const bg = editMode === "yolo" ? "red" : editMode === "auto" ? "magenta" : "cyan";
13243
13313
  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";
13244
- return /* @__PURE__ */ React14.createElement(ModeBarFrame, null, /* @__PURE__ */ React14.createElement(ModePill, { label, bg, flash }), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` ${mid} \xB7 Shift+Tab to flip`), jobsTag);
13314
+ return /* @__PURE__ */ React15.createElement(ModeBarFrame, null, /* @__PURE__ */ React15.createElement(ModePill, { label, bg, flash }), /* @__PURE__ */ React15.createElement(Text12, { dimColor: true }, ` ${mid} \xB7 Shift+Tab to flip`), jobsTag);
13245
13315
  }
13246
13316
  function ModeBarFrame({ children }) {
13247
- const { stdout: stdout4 } = useStdout5();
13317
+ const { stdout: stdout4 } = useStdout6();
13248
13318
  const cols = stdout4?.columns ?? 80;
13249
13319
  const ruleWidth = Math.max(20, cols - 2);
13250
- return /* @__PURE__ */ React14.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Box12, { paddingX: 1 }, /* @__PURE__ */ React14.createElement(Text11, { color: "#475569", dimColor: true }, "\u254C".repeat(ruleWidth))), /* @__PURE__ */ React14.createElement(Box12, { paddingX: 1 }, children));
13320
+ return /* @__PURE__ */ React15.createElement(Box13, { flexDirection: "column" }, /* @__PURE__ */ React15.createElement(Box13, { paddingX: 1 }, /* @__PURE__ */ React15.createElement(Text12, { color: "#475569", dimColor: true }, "\u254C".repeat(ruleWidth))), /* @__PURE__ */ React15.createElement(Box13, { paddingX: 1 }, children));
13251
13321
  }
13252
13322
  function ModePill({
13253
13323
  label,
13254
13324
  bg,
13255
13325
  flash
13256
13326
  }) {
13257
- return /* @__PURE__ */ React14.createElement(Text11, { color: bg, bold: true, inverse: flash }, `[${label}]`);
13327
+ return /* @__PURE__ */ React15.createElement(Text12, { color: bg, bold: true, inverse: flash }, `[${label}]`);
13258
13328
  }
13259
13329
  function UndoBanner({
13260
13330
  banner
@@ -13267,14 +13337,14 @@ function UndoBanner({
13267
13337
  const total = banner.results.length;
13268
13338
  const urgent = remainingSec <= 1;
13269
13339
  const pct2 = remainingMs / totalMs * 100;
13270
- return /* @__PURE__ */ React14.createElement(Box12, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React14.createElement(Text11, { backgroundColor: "#c4b5fd", color: "black", bold: true }, ` \u2713 AUTO-APPLIED ${ok}/${total} `), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, " press "), /* @__PURE__ */ React14.createElement(Text11, { backgroundColor: "#67e8f9", color: "black", bold: true }, " u "), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, " to undo "), /* @__PURE__ */ React14.createElement(CharBar, { pct: pct2, width: 20, color: urgent ? "#f87171" : "#c4b5fd", showLabel: false }), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, " "), /* @__PURE__ */ React14.createElement(Text11, { color: urgent ? "#f87171" : "#c4b5fd", bold: urgent }, `${remainingSec}s`));
13340
+ return /* @__PURE__ */ React15.createElement(Box13, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React15.createElement(Text12, { backgroundColor: "#c4b5fd", color: "black", bold: true }, ` \u2713 AUTO-APPLIED ${ok}/${total} `), /* @__PURE__ */ React15.createElement(Text12, { dimColor: true }, " press "), /* @__PURE__ */ React15.createElement(Text12, { backgroundColor: "#67e8f9", color: "black", bold: true }, " u "), /* @__PURE__ */ React15.createElement(Text12, { dimColor: true }, " to undo "), /* @__PURE__ */ React15.createElement(CharBar, { pct: pct2, width: 20, color: urgent ? "#f87171" : "#c4b5fd", showLabel: false }), /* @__PURE__ */ React15.createElement(Text12, { dimColor: true }, " "), /* @__PURE__ */ React15.createElement(Text12, { color: urgent ? "#f87171" : "#c4b5fd", bold: urgent }, `${remainingSec}s`));
13271
13341
  }
13272
13342
  function SubagentRow({
13273
13343
  activity
13274
13344
  }) {
13275
13345
  const tick = useTick();
13276
13346
  const seconds = (activity.elapsedMs / 1e3).toFixed(1);
13277
- return /* @__PURE__ */ React14.createElement(Box12, { paddingLeft: 3 }, /* @__PURE__ */ React14.createElement(Text11, { color: "#c4b5fd", bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Text11, { color: "#c4b5fd", bold: true }, "\u232C subagent"), /* @__PURE__ */ React14.createElement(Text11, { color: "#c4b5fd" }, ` ${activity.task}`), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` iter ${activity.iter} \xB7 ${seconds}s`));
13347
+ return /* @__PURE__ */ React15.createElement(Box13, { paddingLeft: 3 }, /* @__PURE__ */ React15.createElement(Text12, { color: "#c4b5fd", bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React15.createElement(Text12, null, " "), /* @__PURE__ */ React15.createElement(Text12, { color: "#c4b5fd", bold: true }, "\u232C subagent"), /* @__PURE__ */ React15.createElement(Text12, { color: "#c4b5fd" }, ` ${activity.task}`), /* @__PURE__ */ React15.createElement(Text12, { dimColor: true }, ` iter ${activity.iter} \xB7 ${seconds}s`));
13278
13348
  }
13279
13349
  function OngoingToolRow({
13280
13350
  tool: tool2,
@@ -13283,7 +13353,7 @@ function OngoingToolRow({
13283
13353
  const tick = useTick();
13284
13354
  const elapsed = useElapsedSeconds();
13285
13355
  const summary = summarizeToolArgs(tool2.name, tool2.args);
13286
- return /* @__PURE__ */ React14.createElement(Box12, { marginY: 1, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React14.createElement(Box12, null, /* @__PURE__ */ React14.createElement(Text11, { color: "#fcd34d", bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React14.createElement(Text11, null, " "), /* @__PURE__ */ React14.createElement(Text11, { color: "#fcd34d", bold: true }, `\u25A3 ${tool2.name}`), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, ` running \xB7 ${elapsed}s`)), progress ? /* @__PURE__ */ React14.createElement(Box12, { paddingLeft: 3 }, /* @__PURE__ */ React14.createElement(Text11, { color: "#67e8f9" }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ React14.createElement(Box12, { paddingLeft: 3 }, /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, summary)) : null);
13356
+ return /* @__PURE__ */ React15.createElement(Box13, { marginY: 1, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React15.createElement(Box13, null, /* @__PURE__ */ React15.createElement(Text12, { color: "#fcd34d", bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React15.createElement(Text12, null, " "), /* @__PURE__ */ React15.createElement(Text12, { color: "#fcd34d", bold: true }, `\u25A3 ${tool2.name}`), /* @__PURE__ */ React15.createElement(Text12, { dimColor: true }, ` running \xB7 ${elapsed}s`)), progress ? /* @__PURE__ */ React15.createElement(Box13, { paddingLeft: 3 }, /* @__PURE__ */ React15.createElement(Text12, { color: "#67e8f9" }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ React15.createElement(Box13, { paddingLeft: 3 }, /* @__PURE__ */ React15.createElement(Text12, { dimColor: true }, summary)) : null);
13287
13357
  }
13288
13358
  function renderProgressLine(p) {
13289
13359
  const msg = p.message ? ` ${p.message}` : "";
@@ -13339,8 +13409,8 @@ function summarizeToolArgs(name, args) {
13339
13409
  }
13340
13410
 
13341
13411
  // src/cli/ui/PlanCheckpointConfirm.tsx
13342
- import { Box as Box13 } from "ink";
13343
- import React15 from "react";
13412
+ import { Box as Box14 } from "ink";
13413
+ import React16 from "react";
13344
13414
  function PlanCheckpointConfirmInner({
13345
13415
  stepId,
13346
13416
  title,
@@ -13355,7 +13425,7 @@ function PlanCheckpointConfirmInner({
13355
13425
  const isLast = total > 0 && completed >= total;
13356
13426
  const statuses = buildStatusMap(steps, completedStepIds, stepId, isLast);
13357
13427
  const subtitle = counter ? `${counter} \xB7 ${label}` : label;
13358
- return /* @__PURE__ */ React15.createElement(ModalCard, { accent: "#86efac", icon: "\u2713", title: "checkpoint \u2014 step done", subtitle }, steps && steps.length > 0 ? /* @__PURE__ */ React15.createElement(Box13, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React15.createElement(PlanStepList, { steps, statuses, focusStepId: stepId })) : null, /* @__PURE__ */ React15.createElement(
13428
+ return /* @__PURE__ */ React16.createElement(ModalCard, { accent: "#86efac", icon: "\u2713", title: "checkpoint \u2014 step done", subtitle }, steps && steps.length > 0 ? /* @__PURE__ */ React16.createElement(Box14, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React16.createElement(PlanStepList, { steps, statuses, focusStepId: stepId })) : null, /* @__PURE__ */ React16.createElement(
13359
13429
  SingleSelect,
13360
13430
  {
13361
13431
  initialValue: isLast ? "stop" : "continue",
@@ -13382,7 +13452,7 @@ function PlanCheckpointConfirmInner({
13382
13452
  }
13383
13453
  ));
13384
13454
  }
13385
- var PlanCheckpointConfirm = React15.memo(PlanCheckpointConfirmInner);
13455
+ var PlanCheckpointConfirm = React16.memo(PlanCheckpointConfirmInner);
13386
13456
  function buildStatusMap(steps, completedStepIds, currentStepId, isLast) {
13387
13457
  const map = /* @__PURE__ */ new Map();
13388
13458
  if (!steps) return map;
@@ -13399,11 +13469,11 @@ function buildStatusMap(steps, completedStepIds, currentStepId, isLast) {
13399
13469
  }
13400
13470
 
13401
13471
  // src/cli/ui/PlanConfirm.tsx
13402
- import { Box as Box14, Text as Text12 } from "ink";
13403
- import React16 from "react";
13472
+ import { Box as Box15, Text as Text13 } from "ink";
13473
+ import React17 from "react";
13404
13474
  function PlanConfirmInner({ plan: plan2, steps, summary, onChoose }) {
13405
13475
  const hasOpenQuestions = /^#{1,6}\s*(open[-\s]?questions?|risks?|unknowns?|assumptions?|unclear)/im.test(plan2) || /^#{1,6}\s*(待确认|开放问题|风险|未知|假设|不确定)/im.test(plan2);
13406
- return /* @__PURE__ */ React16.createElement(
13476
+ return /* @__PURE__ */ React17.createElement(
13407
13477
  ModalCard,
13408
13478
  {
13409
13479
  accent: "#67e8f9",
@@ -13411,9 +13481,9 @@ function PlanConfirmInner({ plan: plan2, steps, summary, onChoose }) {
13411
13481
  title: "plan proposed",
13412
13482
  subtitle: summary ?? "approve / refine / cancel"
13413
13483
  },
13414
- hasOpenQuestions ? /* @__PURE__ */ React16.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text12, { color: "#fbbf24" }, "\u25B2 the plan flags open questions or risks \u2014 pick", " ", /* @__PURE__ */ React16.createElement(Text12, { bold: true }, "Refine / answer questions"), " to write concrete answers before the model moves on.")) : null,
13415
- steps && steps.length > 0 ? /* @__PURE__ */ React16.createElement(Box14, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React16.createElement(PlanStepList, { steps })) : null,
13416
- /* @__PURE__ */ React16.createElement(
13484
+ hasOpenQuestions ? /* @__PURE__ */ React17.createElement(Box15, { marginBottom: 1 }, /* @__PURE__ */ React17.createElement(Text13, { color: "#fbbf24" }, "\u25B2 the plan flags open questions or risks \u2014 pick", " ", /* @__PURE__ */ React17.createElement(Text13, { bold: true }, "Refine / answer questions"), " to write concrete answers before the model moves on.")) : null,
13485
+ steps && steps.length > 0 ? /* @__PURE__ */ React17.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React17.createElement(PlanStepList, { steps })) : null,
13486
+ /* @__PURE__ */ React17.createElement(
13417
13487
  SingleSelect,
13418
13488
  {
13419
13489
  initialValue: hasOpenQuestions ? "refine" : "approve",
@@ -13441,11 +13511,11 @@ function PlanConfirmInner({ plan: plan2, steps, summary, onChoose }) {
13441
13511
  )
13442
13512
  );
13443
13513
  }
13444
- var PlanConfirm = React16.memo(PlanConfirmInner);
13514
+ var PlanConfirm = React17.memo(PlanConfirmInner);
13445
13515
 
13446
13516
  // src/cli/ui/PlanRefineInput.tsx
13447
- import { Box as Box15, Text as Text13 } from "ink";
13448
- import React17, { useState as useState4 } from "react";
13517
+ import { Box as Box16, Text as Text14 } from "ink";
13518
+ import React18, { useState as useState4 } from "react";
13449
13519
  function PlanRefineInput({ mode: mode2, onSubmit, onCancel }) {
13450
13520
  const [value, setValue] = useState4("");
13451
13521
  useKeystroke((ev) => {
@@ -13490,12 +13560,12 @@ function PlanRefineInput({ mode: mode2, onSubmit, onCancel }) {
13490
13560
  };
13491
13561
  const hint = mode2 === "approve" ? "Answer questions the plan raised, add constraints, or just press Enter to approve as-is." : mode2 === "checkpoint-revise" ? "Scope change, skip steps, alternative approach \u2014 the model adjusts the remaining plan." : mode2 === "choice-custom" ? "Free-form reply. The model reads it verbatim and proceeds \u2014 no need to match the listed options." : "Describe what's wrong or missing, or answer questions the plan raised.";
13492
13562
  const blankHint = mode2 === "approve" ? " (Enter with blank = approve without extra instructions.)" : mode2 === "checkpoint-revise" ? " (Enter with blank = continue with the current plan.)" : mode2 === "choice-custom" ? " (Enter with blank = ask the model what you actually want.)" : " (Enter with blank = ask the model to list concrete questions.)";
13493
- return /* @__PURE__ */ React17.createElement(ModalCard, { accent: meta.accent, icon: meta.icon, title: meta.title }, /* @__PURE__ */ React17.createElement(Box15, { marginBottom: 1 }, /* @__PURE__ */ React17.createElement(Text13, { dimColor: true }, hint, " Enter to send \xB7 Esc to return to the picker.", value === "" ? blankHint : "")), /* @__PURE__ */ React17.createElement(Box15, null, /* @__PURE__ */ React17.createElement(Text13, { color: meta.accent, bold: true }, "\u203A "), /* @__PURE__ */ React17.createElement(Text13, null, value), /* @__PURE__ */ React17.createElement(Text13, { color: meta.accent, bold: true }, cursorOn ? "\u258D" : " ")));
13563
+ return /* @__PURE__ */ React18.createElement(ModalCard, { accent: meta.accent, icon: meta.icon, title: meta.title }, /* @__PURE__ */ React18.createElement(Box16, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Text14, { dimColor: true }, hint, " Enter to send \xB7 Esc to return to the picker.", value === "" ? blankHint : "")), /* @__PURE__ */ React18.createElement(Box16, null, /* @__PURE__ */ React18.createElement(Text14, { color: meta.accent, bold: true }, "\u203A "), /* @__PURE__ */ React18.createElement(Text14, null, value), /* @__PURE__ */ React18.createElement(Text14, { color: meta.accent, bold: true }, cursorOn ? "\u258D" : " ")));
13494
13564
  }
13495
13565
 
13496
13566
  // src/cli/ui/PlanReviseConfirm.tsx
13497
- import { Box as Box16, Text as Text14 } from "ink";
13498
- import React18 from "react";
13567
+ import { Box as Box17, Text as Text15 } from "ink";
13568
+ import React19 from "react";
13499
13569
  function computeDiff(oldSteps, newSteps) {
13500
13570
  const oldIds = new Set(oldSteps.map((s) => s.id));
13501
13571
  const newIds = new Set(newSteps.map((s) => s.id));
@@ -13531,7 +13601,7 @@ function PlanReviseConfirmInner({
13531
13601
  const removedCount = rows.filter((r) => r.kind === "removed").length;
13532
13602
  const addedCount = rows.filter((r) => r.kind === "added").length;
13533
13603
  const keptCount = rows.filter((r) => r.kind === "kept").length;
13534
- return /* @__PURE__ */ React18.createElement(
13604
+ return /* @__PURE__ */ React19.createElement(
13535
13605
  ModalCard,
13536
13606
  {
13537
13607
  accent: "#fbbf24",
@@ -13539,17 +13609,17 @@ function PlanReviseConfirmInner({
13539
13609
  title: "plan revision proposed",
13540
13610
  subtitle: `\u2212${removedCount} +${addedCount} \xB7 ${keptCount} kept`
13541
13611
  },
13542
- /* @__PURE__ */ React18.createElement(Box16, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Text14, null, reason)),
13543
- summary ? /* @__PURE__ */ React18.createElement(Box16, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Text14, { dimColor: true }, `updated summary: ${summary}`)) : null,
13544
- /* @__PURE__ */ React18.createElement(Box16, { marginBottom: 1, flexDirection: "column" }, rows.map((row2) => {
13612
+ /* @__PURE__ */ React19.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React19.createElement(Text15, null, reason)),
13613
+ summary ? /* @__PURE__ */ React19.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, `updated summary: ${summary}`)) : null,
13614
+ /* @__PURE__ */ React19.createElement(Box17, { marginBottom: 1, flexDirection: "column" }, rows.map((row2) => {
13545
13615
  const risk = riskDots(row2.step.risk);
13546
13616
  const prefix = row2.kind === "removed" ? "\u2212" : row2.kind === "added" ? "+" : " ";
13547
13617
  const prefixColor = row2.kind === "removed" ? "#f87171" : row2.kind === "added" ? "#4ade80" : "#94a3b8";
13548
13618
  const dim = row2.kind === "kept";
13549
13619
  const strike = row2.kind === "removed";
13550
- return /* @__PURE__ */ React18.createElement(Box16, { key: `${row2.kind}-${row2.step.id}` }, /* @__PURE__ */ React18.createElement(Text14, { color: prefixColor, bold: true }, `${prefix} `), /* @__PURE__ */ React18.createElement(Text14, { color: risk.color, bold: true, dimColor: dim }, risk.dots), /* @__PURE__ */ React18.createElement(Text14, { dimColor: dim, strikethrough: strike }, ` ${row2.step.id} \xB7 ${row2.step.title}`));
13620
+ return /* @__PURE__ */ React19.createElement(Box17, { key: `${row2.kind}-${row2.step.id}` }, /* @__PURE__ */ React19.createElement(Text15, { color: prefixColor, bold: true }, `${prefix} `), /* @__PURE__ */ React19.createElement(Text15, { color: risk.color, bold: true, dimColor: dim }, risk.dots), /* @__PURE__ */ React19.createElement(Text15, { dimColor: dim, strikethrough: strike }, ` ${row2.step.id} \xB7 ${row2.step.title}`));
13551
13621
  })),
13552
- /* @__PURE__ */ React18.createElement(
13622
+ /* @__PURE__ */ React19.createElement(
13553
13623
  SingleSelect,
13554
13624
  {
13555
13625
  initialValue: "accept",
@@ -13572,11 +13642,11 @@ function PlanReviseConfirmInner({
13572
13642
  )
13573
13643
  );
13574
13644
  }
13575
- var PlanReviseConfirm = React18.memo(PlanReviseConfirmInner);
13645
+ var PlanReviseConfirm = React19.memo(PlanReviseConfirmInner);
13576
13646
 
13577
13647
  // src/cli/ui/PromptInput.tsx
13578
- import { Box as Box17, Text as Text15, useStdout as useStdout6 } from "ink";
13579
- import React19, { useRef as useRef2, useState as useState5 } from "react";
13648
+ import { Box as Box18, Text as Text16, useStdout as useStdout7 } from "ink";
13649
+ import React20, { useRef as useRef2, useState as useState5 } from "react";
13580
13650
 
13581
13651
  // src/cli/ui/key-normalize.ts
13582
13652
  var CSI_TAIL_TO_FLAGS = [
@@ -13791,10 +13861,10 @@ function makePasteEntry(id, content) {
13791
13861
  charCount: content.length
13792
13862
  };
13793
13863
  }
13794
- function expandPasteSentinels(text, pastes) {
13864
+ function expandPasteSentinels(text2, pastes) {
13795
13865
  let out = "";
13796
- for (let i = 0; i < text.length; i++) {
13797
- const ch = text[i];
13866
+ for (let i = 0; i < text2.length; i++) {
13867
+ const ch = text2[i];
13798
13868
  const id = decodePasteSentinel(ch);
13799
13869
  if (id === null) {
13800
13870
  out += ch;
@@ -13805,10 +13875,10 @@ function expandPasteSentinels(text, pastes) {
13805
13875
  }
13806
13876
  return out;
13807
13877
  }
13808
- function listPasteIdsInBuffer(text) {
13878
+ function listPasteIdsInBuffer(text2) {
13809
13879
  const ids = [];
13810
- for (let i = 0; i < text.length; i++) {
13811
- const id = decodePasteSentinel(text[i]);
13880
+ for (let i = 0; i < text2.length; i++) {
13881
+ const id = decodePasteSentinel(text2[i]);
13812
13882
  if (id !== null) ids.push(id);
13813
13883
  }
13814
13884
  return ids;
@@ -14048,7 +14118,7 @@ function PromptInput({
14048
14118
  if (action.historyHandoff === "prev") onHistoryPrev?.();
14049
14119
  if (action.historyHandoff === "next") onHistoryNext?.();
14050
14120
  }, !disabled);
14051
- const { stdout: stdout4 } = useStdout6();
14121
+ const { stdout: stdout4 } = useStdout7();
14052
14122
  const cols = stdout4?.columns ?? 80;
14053
14123
  const narrow = cols <= 90;
14054
14124
  const promptBody = narrow ? "\u203A " : "you \u203A ";
@@ -14065,11 +14135,11 @@ function PromptInput({
14065
14135
  const { line: cursorLine, col: cursorCol } = lineAndColumn(value, cursor);
14066
14136
  const renderItems = collapseLinesForDisplay(lines, cursorLine);
14067
14137
  const showHugeBufferHints = lines.length > 20;
14068
- return /* @__PURE__ */ React19.createElement(Box17, { flexDirection: "column", paddingX: 1 }, renderItems.map((item, renderIdx) => {
14138
+ return /* @__PURE__ */ React20.createElement(Box18, { flexDirection: "column", paddingX: 1 }, renderItems.map((item, renderIdx) => {
14069
14139
  if (item.kind === "skip") {
14070
14140
  return (
14071
14141
  // biome-ignore lint/suspicious/noArrayIndexKey: stable — collapse markers derive from a fixed sliding window
14072
- /* @__PURE__ */ React19.createElement(Box17, { key: `skip-${renderIdx}` }, /* @__PURE__ */ React19.createElement(Text15, { color: barColorAt(renderIdx) }, BAR), /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, continuationIndent.slice(BAR.length)), /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, `[\u2026 ${item.linesHidden} line${item.linesHidden === 1 ? "" : "s"} hidden \u2014 full content kept, submitted on Enter \u2026]`))
14142
+ /* @__PURE__ */ React20.createElement(Box18, { key: `skip-${renderIdx}` }, /* @__PURE__ */ React20.createElement(Text16, { color: barColorAt(renderIdx) }, BAR), /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, continuationIndent.slice(BAR.length)), /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, `[\u2026 ${item.linesHidden} line${item.linesHidden === 1 ? "" : "s"} hidden \u2014 full content kept, submitted on Enter \u2026]`))
14073
14143
  );
14074
14144
  }
14075
14145
  const i = item.originalIndex;
@@ -14077,7 +14147,7 @@ function PromptInput({
14077
14147
  const isFirst = i === 0;
14078
14148
  const isCursorLine = i === cursorLine;
14079
14149
  const showPlaceholder = isFirst && value.length === 0;
14080
- return /* @__PURE__ */ React19.createElement(
14150
+ return /* @__PURE__ */ React20.createElement(
14081
14151
  PromptLine,
14082
14152
  {
14083
14153
  key: `ln-${i}`,
@@ -14097,7 +14167,7 @@ function PromptInput({
14097
14167
  disabled: disabled === true
14098
14168
  }
14099
14169
  );
14100
- }), showHugeBufferHints && !disabled ? /* @__PURE__ */ React19.createElement(Box17, null, /* @__PURE__ */ React19.createElement(Text15, { color: barColorAt(0) }, BAR), /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, continuationIndent.slice(BAR.length)), /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, `[${lines.length} lines \xB7 PageUp/PageDown jump to top/bottom \xB7 Ctrl+U clear \xB7 Ctrl+W del word]`)) : null, !disabled && !narrow && value.length > 0 && !value.includes("\n") ? /* @__PURE__ */ React19.createElement(Box17, null, /* @__PURE__ */ React19.createElement(Text15, { color: barColorAt(0) }, BAR), /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, continuationIndent.slice(BAR.length)), /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, "[Ctrl+J] newline \xB7 [Enter] submit \xB7 ends with \\ for line continuation")) : null, !disabled && !narrow && value.length === 0 ? /* @__PURE__ */ React19.createElement(Box17, null, /* @__PURE__ */ React19.createElement(Text15, { color: barColorAt(0) }, BAR), /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, continuationIndent.slice(BAR.length)), /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, "[PgUp/PgDn] scroll log \xB7 [End] jump to latest \xB7 drag to select & copy \xB7 /mouse on for wheel")) : null, disabled ? /* @__PURE__ */ React19.createElement(Box17, null, /* @__PURE__ */ React19.createElement(Text15, { color: barColorAt(0) }, BAR), /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, continuationIndent.slice(BAR.length)), /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, "[Esc] to stop")) : null);
14170
+ }), showHugeBufferHints && !disabled ? /* @__PURE__ */ React20.createElement(Box18, null, /* @__PURE__ */ React20.createElement(Text16, { color: barColorAt(0) }, BAR), /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, continuationIndent.slice(BAR.length)), /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, `[${lines.length} lines \xB7 PageUp/PageDown jump to top/bottom \xB7 Ctrl+U clear \xB7 Ctrl+W del word]`)) : null, !disabled && !narrow && value.length > 0 && !value.includes("\n") ? /* @__PURE__ */ React20.createElement(Box18, null, /* @__PURE__ */ React20.createElement(Text16, { color: barColorAt(0) }, BAR), /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, continuationIndent.slice(BAR.length)), /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, "[Ctrl+J] newline \xB7 [Enter] submit \xB7 ends with \\ for line continuation")) : null, !disabled && !narrow && value.length === 0 ? /* @__PURE__ */ React20.createElement(Box18, null, /* @__PURE__ */ React20.createElement(Text16, { color: barColorAt(0) }, BAR), /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, continuationIndent.slice(BAR.length)), /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, "[PgUp/PgDn] scroll log \xB7 [End] jump to latest \xB7 drag to select & copy \xB7 /mouse on for wheel")) : null, disabled ? /* @__PURE__ */ React20.createElement(Box18, null, /* @__PURE__ */ React20.createElement(Text16, { color: barColorAt(0) }, BAR), /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, continuationIndent.slice(BAR.length)), /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, "[Esc] to stop")) : null);
14101
14171
  }
14102
14172
  function PromptLine({
14103
14173
  line,
@@ -14119,18 +14189,18 @@ function PromptLine({
14119
14189
  const bodyPrefix = promptPrefix.slice(BAR.length);
14120
14190
  const bodyContinuation = continuationIndent.slice(BAR.length);
14121
14191
  if (showPlaceholder) {
14122
- return /* @__PURE__ */ React19.createElement(Box17, null, /* @__PURE__ */ React19.createElement(Text15, { color: barColor }, barText), /* @__PURE__ */ React19.createElement(Text15, { bold: true, color: accentColor }, bodyPrefix), !disabled ? /* @__PURE__ */ React19.createElement(Text15, { color: accentColor }, cursorVisible ? "\u258C" : " ") : null, /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, placeholderText));
14192
+ return /* @__PURE__ */ React20.createElement(Box18, null, /* @__PURE__ */ React20.createElement(Text16, { color: barColor }, barText), /* @__PURE__ */ React20.createElement(Text16, { bold: true, color: accentColor }, bodyPrefix), !disabled ? /* @__PURE__ */ React20.createElement(Text16, { color: accentColor }, cursorVisible ? "\u258C" : " ") : null, /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, placeholderText));
14123
14193
  }
14124
- const viewport = buildViewport(line, isCursorLine ? cursorCol : null, visibleCells, pastes);
14125
- return /* @__PURE__ */ React19.createElement(Box17, null, /* @__PURE__ */ React19.createElement(Text15, { color: barColor }, barText), isFirst ? /* @__PURE__ */ React19.createElement(Text15, { bold: true, color: accentColor }, bodyPrefix) : /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, bodyContinuation), viewport.hiddenLeft ? /* @__PURE__ */ React19.createElement(Text15, { color: "gray", dimColor: true }, "\u2039") : null, /* @__PURE__ */ React19.createElement(
14194
+ const viewport2 = buildViewport(line, isCursorLine ? cursorCol : null, visibleCells, pastes);
14195
+ return /* @__PURE__ */ React20.createElement(Box18, null, /* @__PURE__ */ React20.createElement(Text16, { color: barColor }, barText), isFirst ? /* @__PURE__ */ React20.createElement(Text16, { bold: true, color: accentColor }, bodyPrefix) : /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, bodyContinuation), viewport2.hiddenLeft ? /* @__PURE__ */ React20.createElement(Text16, { color: "gray", dimColor: true }, "\u2039") : null, /* @__PURE__ */ React20.createElement(
14126
14196
  ViewportContent,
14127
14197
  {
14128
- segments: viewport.segments,
14129
- cursorCell: isCursorLine ? viewport.cursorCell : null,
14198
+ segments: viewport2.segments,
14199
+ cursorCell: isCursorLine ? viewport2.cursorCell : null,
14130
14200
  accentColor,
14131
14201
  cursorVisible
14132
14202
  }
14133
- ), viewport.hiddenRight ? /* @__PURE__ */ React19.createElement(Text15, { color: "gray", dimColor: true }, "\u203A") : null);
14203
+ ), viewport2.hiddenRight ? /* @__PURE__ */ React20.createElement(Text16, { color: "gray", dimColor: true }, "\u203A") : null);
14134
14204
  }
14135
14205
  function ViewportContent({
14136
14206
  segments,
@@ -14139,7 +14209,7 @@ function ViewportContent({
14139
14209
  cursorVisible
14140
14210
  }) {
14141
14211
  if (cursorCell === null) {
14142
- return /* @__PURE__ */ React19.createElement(React19.Fragment, null, segments.map((seg, i) => renderSegment(seg, i, false)));
14212
+ return /* @__PURE__ */ React20.createElement(React20.Fragment, null, segments.map((seg, i) => renderSegment(seg, i, false)));
14143
14213
  }
14144
14214
  const out = [];
14145
14215
  let cells = 0;
@@ -14158,7 +14228,7 @@ function ViewportContent({
14158
14228
  }
14159
14229
  if (seg.kind === "paste") {
14160
14230
  out.push(
14161
- /* @__PURE__ */ React19.createElement(Text15, { key: `p-${i}-cursor`, color: "magenta", bold: true, inverse: cursorVisible }, seg.label)
14231
+ /* @__PURE__ */ React20.createElement(Text16, { key: `p-${i}-cursor`, color: "magenta", bold: true, inverse: cursorVisible }, seg.label)
14162
14232
  );
14163
14233
  placed = true;
14164
14234
  cells += segCells;
@@ -14167,48 +14237,48 @@ function ViewportContent({
14167
14237
  const offsetIntoSeg = cursorCell - cells;
14168
14238
  const split = splitTextByCells(seg.text, offsetIntoSeg);
14169
14239
  if (split.before.length > 0) {
14170
- out.push(/* @__PURE__ */ React19.createElement(Text15, { key: `t-${i}-b` }, split.before));
14240
+ out.push(/* @__PURE__ */ React20.createElement(Text16, { key: `t-${i}-b` }, split.before));
14171
14241
  }
14172
14242
  if (split.atCursor.length > 0) {
14173
14243
  out.push(
14174
- /* @__PURE__ */ React19.createElement(Text15, { key: `t-${i}-c`, inverse: cursorVisible, color: accentColor }, split.atCursor)
14244
+ /* @__PURE__ */ React20.createElement(Text16, { key: `t-${i}-c`, inverse: cursorVisible, color: accentColor }, split.atCursor)
14175
14245
  );
14176
14246
  } else {
14177
14247
  out.push(
14178
- /* @__PURE__ */ React19.createElement(Text15, { key: `t-${i}-c-eol`, color: accentColor }, cursorVisible ? "\u258C" : " ")
14248
+ /* @__PURE__ */ React20.createElement(Text16, { key: `t-${i}-c-eol`, color: accentColor }, cursorVisible ? "\u258C" : " ")
14179
14249
  );
14180
14250
  }
14181
14251
  if (split.after.length > 0) {
14182
- out.push(/* @__PURE__ */ React19.createElement(Text15, { key: `t-${i}-a` }, split.after));
14252
+ out.push(/* @__PURE__ */ React20.createElement(Text16, { key: `t-${i}-a` }, split.after));
14183
14253
  }
14184
14254
  placed = true;
14185
14255
  cells += segCells;
14186
14256
  }
14187
14257
  if (!placed) {
14188
14258
  out.push(
14189
- /* @__PURE__ */ React19.createElement(Text15, { key: "cursor-eol", color: accentColor }, cursorVisible ? "\u258C" : " ")
14259
+ /* @__PURE__ */ React20.createElement(Text16, { key: "cursor-eol", color: accentColor }, cursorVisible ? "\u258C" : " ")
14190
14260
  );
14191
14261
  }
14192
- return /* @__PURE__ */ React19.createElement(React19.Fragment, null, out);
14262
+ return /* @__PURE__ */ React20.createElement(React20.Fragment, null, out);
14193
14263
  }
14194
14264
  function segmentCells(seg) {
14195
14265
  if (seg.kind === "paste") return seg.label.length;
14196
14266
  return stringCells(seg.text);
14197
14267
  }
14198
- function splitTextByCells(text, cellOffset) {
14268
+ function splitTextByCells(text2, cellOffset) {
14199
14269
  let cells = 0;
14200
- for (let i = 0; i < text.length; i++) {
14201
- const ch = text[i];
14270
+ for (let i = 0; i < text2.length; i++) {
14271
+ const ch = text2[i];
14202
14272
  const cw = charCellsForText(ch);
14203
14273
  if (cells === cellOffset) {
14204
- return { before: text.slice(0, i), atCursor: ch, after: text.slice(i + 1) };
14274
+ return { before: text2.slice(0, i), atCursor: ch, after: text2.slice(i + 1) };
14205
14275
  }
14206
14276
  if (cells + cw > cellOffset) {
14207
- return { before: text.slice(0, i), atCursor: ch, after: text.slice(i + 1) };
14277
+ return { before: text2.slice(0, i), atCursor: ch, after: text2.slice(i + 1) };
14208
14278
  }
14209
14279
  cells += cw;
14210
14280
  }
14211
- return { before: text, atCursor: "", after: "" };
14281
+ return { before: text2, atCursor: "", after: "" };
14212
14282
  }
14213
14283
  function charCellsForText(ch) {
14214
14284
  const code = ch.charCodeAt(0);
@@ -14229,9 +14299,9 @@ function charCellsForText(ch) {
14229
14299
  }
14230
14300
  function renderSegment(seg, key, _inverse) {
14231
14301
  if (seg.kind === "text") {
14232
- return /* @__PURE__ */ React19.createElement(Text15, { key: `s-${key}` }, seg.text);
14302
+ return /* @__PURE__ */ React20.createElement(Text16, { key: `s-${key}` }, seg.text);
14233
14303
  }
14234
- return /* @__PURE__ */ React19.createElement(Text15, { key: `s-${key}`, backgroundColor: "#f0abfc", color: "black", bold: true }, seg.label);
14304
+ return /* @__PURE__ */ React20.createElement(Text16, { key: `s-${key}`, backgroundColor: "#f0abfc", color: "black", bold: true }, seg.label);
14235
14305
  }
14236
14306
  var COLLAPSE_THRESHOLD = 20;
14237
14307
  var COLLAPSE_HEAD_LINES = 3;
@@ -14258,12 +14328,12 @@ function collapseLinesForDisplay(lines, cursorLine) {
14258
14328
  }
14259
14329
 
14260
14330
  // src/cli/ui/ShellConfirm.tsx
14261
- import { Box as Box18, Text as Text16 } from "ink";
14262
- import React20 from "react";
14331
+ import { Box as Box19, Text as Text17 } from "ink";
14332
+ import React21 from "react";
14263
14333
  function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
14264
14334
  const isBackground = kind === "run_background";
14265
14335
  const subtitle = isBackground ? "long-running process \u2014 keeps running after approval, /kill to stop" : "model wants to run a shell command";
14266
- return /* @__PURE__ */ React20.createElement(
14336
+ return /* @__PURE__ */ React21.createElement(
14267
14337
  ModalCard,
14268
14338
  {
14269
14339
  accent: COLOR.err,
@@ -14271,8 +14341,8 @@ function ShellConfirm({ command, allowPrefix, kind, onChoose }) {
14271
14341
  title: isBackground ? "background process" : "shell command",
14272
14342
  subtitle
14273
14343
  },
14274
- /* @__PURE__ */ React20.createElement(Box18, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text16, { color: COLOR.primary, bold: true }, "$ "), /* @__PURE__ */ React20.createElement(Text16, { bold: true }, command)),
14275
- /* @__PURE__ */ React20.createElement(
14344
+ /* @__PURE__ */ React21.createElement(Box19, { marginBottom: 1 }, /* @__PURE__ */ React21.createElement(Text17, { color: COLOR.primary, bold: true }, "$ "), /* @__PURE__ */ React21.createElement(Text17, { bold: true }, command)),
14345
+ /* @__PURE__ */ React21.createElement(
14276
14346
  SingleSelect,
14277
14347
  {
14278
14348
  initialValue: "run_once",
@@ -14330,8 +14400,8 @@ function derivePrefix(command) {
14330
14400
  }
14331
14401
 
14332
14402
  // src/cli/ui/SlashArgPicker.tsx
14333
- import { Box as Box19, Text as Text17 } from "ink";
14334
- import React21 from "react";
14403
+ import { Box as Box20, Text as Text18 } from "ink";
14404
+ import React22 from "react";
14335
14405
  function SlashArgPicker({
14336
14406
  matches,
14337
14407
  selectedIndex,
@@ -14339,13 +14409,13 @@ function SlashArgPicker({
14339
14409
  kind,
14340
14410
  partial
14341
14411
  }) {
14342
- const headerRow = /* @__PURE__ */ React21.createElement(Box19, 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}`));
14412
+ const headerRow = /* @__PURE__ */ React22.createElement(Box20, null, /* @__PURE__ */ React22.createElement(Text18, { color: COLOR.accent, bold: true }, "/ "), /* @__PURE__ */ React22.createElement(Text18, { color: COLOR.accent, bold: true }, `/${spec.cmd}`), spec.argsHint ? /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, ` ${spec.argsHint}`) : null, /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, ` ${spec.summary}`));
14343
14413
  if (kind === "hint") {
14344
- return /* @__PURE__ */ React21.createElement(Box19, { paddingX: 1, marginTop: 1 }, headerRow);
14414
+ return /* @__PURE__ */ React22.createElement(Box20, { paddingX: 1, marginTop: 1 }, headerRow);
14345
14415
  }
14346
14416
  if (matches === null) return null;
14347
14417
  if (matches.length === 0) {
14348
- return /* @__PURE__ */ React21.createElement(Box19, { flexDirection: "column", paddingX: 1, marginTop: 1 }, headerRow, /* @__PURE__ */ React21.createElement(Box19, 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")));
14418
+ return /* @__PURE__ */ React22.createElement(Box20, { flexDirection: "column", paddingX: 1, marginTop: 1 }, headerRow, /* @__PURE__ */ React22.createElement(Box20, null, /* @__PURE__ */ React22.createElement(Text18, { color: COLOR.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React22.createElement(Text18, { color: COLOR.warn }, ` no match for "${partial}"`), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, " \u2014 keep typing, or Backspace to edit")));
14349
14419
  }
14350
14420
  const MAX = 8;
14351
14421
  const total = matches.length;
@@ -14353,22 +14423,22 @@ function SlashArgPicker({
14353
14423
  const shown = matches.slice(windowStart, windowStart + MAX);
14354
14424
  const hiddenAbove = windowStart;
14355
14425
  const hiddenBelow = total - windowStart - shown.length;
14356
- return /* @__PURE__ */ React21.createElement(Box19, { 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(Box19, { marginTop: 0 }, /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, " \u2191\u2193 navigate \xB7 Tab / \u23CE pick \xB7 esc cancel")));
14426
+ return /* @__PURE__ */ React22.createElement(Box20, { flexDirection: "column", paddingX: 1, marginTop: 1 }, headerRow, hiddenAbove > 0 ? /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null, shown.map((value, i) => /* @__PURE__ */ React22.createElement(ArgRow, { key: value, value, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, ` \u2193 ${hiddenBelow} below`) : null, /* @__PURE__ */ React22.createElement(Box20, { marginTop: 0 }, /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, " \u2191\u2193 navigate \xB7 Tab / \u23CE pick \xB7 esc cancel")));
14357
14427
  }
14358
14428
  function ArgRow({ value, isSelected }) {
14359
- return /* @__PURE__ */ React21.createElement(Box19, 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));
14429
+ return /* @__PURE__ */ React22.createElement(Box20, null, /* @__PURE__ */ React22.createElement(Text18, { color: isSelected ? COLOR.primary : COLOR.info, bold: isSelected }, isSelected ? `${GLYPH.cur} ` : " "), /* @__PURE__ */ React22.createElement(Text18, { color: isSelected ? COLOR.user : COLOR.info, bold: isSelected, dimColor: !isSelected }, value));
14360
14430
  }
14361
14431
 
14362
14432
  // src/cli/ui/SlashSuggestions.tsx
14363
- import { Box as Box20, Text as Text18 } from "ink";
14364
- import React22 from "react";
14433
+ import { Box as Box21, Text as Text19 } from "ink";
14434
+ import React23 from "react";
14365
14435
  function SlashSuggestions({
14366
14436
  matches,
14367
14437
  selectedIndex
14368
14438
  }) {
14369
14439
  if (matches === null) return null;
14370
14440
  if (matches.length === 0) {
14371
- return /* @__PURE__ */ React22.createElement(Box20, { 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"));
14441
+ return /* @__PURE__ */ React23.createElement(Box21, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, { color: COLOR.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React23.createElement(Text19, null, " "), /* @__PURE__ */ React23.createElement(Text19, { color: COLOR.warn }, "no slash command matches that prefix"), /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, " \u2014 Backspace to edit, or /help for the full list"));
14372
14442
  }
14373
14443
  const MAX = 8;
14374
14444
  const total = matches.length;
@@ -14376,121 +14446,12 @@ function SlashSuggestions({
14376
14446
  const shown = matches.slice(windowStart, windowStart + MAX);
14377
14447
  const hiddenAbove = windowStart;
14378
14448
  const hiddenBelow = total - windowStart - shown.length;
14379
- return /* @__PURE__ */ React22.createElement(Box20, { flexDirection: "column", paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React22.createElement(Box20, 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(Box20, { marginTop: 0 }, /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, " \u2191\u2193 navigate \xB7 Tab / \u23CE pick \xB7 esc cancel")));
14449
+ return /* @__PURE__ */ React23.createElement(Box21, { flexDirection: "column", paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React23.createElement(Box21, null, /* @__PURE__ */ React23.createElement(Text19, { color: COLOR.accent, bold: true }, "/ "), /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, `${total} command${total === 1 ? "" : "s"}`), hiddenAbove > 0 ? /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null), shown.map((spec, i) => /* @__PURE__ */ React23.createElement(SuggestionRow, { key: spec.cmd, spec, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, ` \u2193 ${hiddenBelow} below`) : null, /* @__PURE__ */ React23.createElement(Box21, { marginTop: 0 }, /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, " \u2191\u2193 navigate \xB7 Tab / \u23CE pick \xB7 esc cancel")));
14380
14450
  }
14381
14451
  function SuggestionRow({ spec, isSelected }) {
14382
14452
  const name = `/${spec.cmd}`;
14383
14453
  const argsSuffix = spec.argsHint ? spec.argsHint : "";
14384
- return /* @__PURE__ */ React22.createElement(Box20, 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));
14385
- }
14386
-
14387
- // src/cli/ui/StatsPanel.tsx
14388
- import { basename } from "path";
14389
- import { Box as Box21, Text as Text19, useStdout as useStdout7 } from "ink";
14390
- import React23 from "react";
14391
- var NARROW_BREAKPOINT = 120;
14392
- var COLD_START_TURNS = 3;
14393
- function StatsPanel({
14394
- summary,
14395
- model: model2,
14396
- prefixHash,
14397
- harvestOn,
14398
- branchBudget,
14399
- reasoningEffort,
14400
- planMode,
14401
- editMode,
14402
- balance,
14403
- updateAvailable,
14404
- busy,
14405
- proArmed,
14406
- escalated,
14407
- budgetUsd,
14408
- rootDir,
14409
- sessionName
14410
- }) {
14411
- const branchOn = (branchBudget ?? 1) > 1;
14412
- const ctxMax = DEEPSEEK_CONTEXT_TOKENS[model2] ?? DEFAULT_CONTEXT_TOKENS;
14413
- const ctxRatio = summary.lastPromptTokens / ctxMax;
14414
- const { stdout: stdout4 } = useStdout7();
14415
- const columns = stdout4?.columns ?? 80;
14416
- const narrow = columns < NARROW_BREAKPOINT;
14417
- const coldStart = summary.turns <= COLD_START_TURNS;
14418
- return /* @__PURE__ */ React23.createElement(Box21, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React23.createElement(
14419
- ChromeRow,
14420
- {
14421
- editMode,
14422
- planMode,
14423
- proArmed: proArmed ?? false,
14424
- escalated: escalated ?? false,
14425
- summary,
14426
- coldStart,
14427
- rootDir,
14428
- sessionName: sessionName ?? null,
14429
- updateAvailable,
14430
- balance: balance ?? null,
14431
- narrow
14432
- }
14433
- ), /* @__PURE__ */ React23.createElement(ChromeRule, null), budgetUsd !== null && budgetUsd !== void 0 ? /* @__PURE__ */ React23.createElement(BudgetRow, { spent: summary.totalCostUsd, cap: budgetUsd }) : null);
14434
- }
14435
- function ChromeRule() {
14436
- const { stdout: stdout4 } = useStdout7();
14437
- const cols = stdout4?.columns ?? 80;
14438
- const w = Math.max(20, cols - 2);
14439
- return /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "\u2500".repeat(w));
14440
- }
14441
- function ChromeRow({
14442
- editMode,
14443
- planMode,
14444
- proArmed,
14445
- escalated,
14446
- summary,
14447
- coldStart,
14448
- rootDir,
14449
- sessionName,
14450
- updateAvailable,
14451
- balance,
14452
- narrow
14453
- }) {
14454
- const modePill = pickModePill(planMode, editMode);
14455
- const proPill = escalated ? { label: "\u21E7 pro", color: COLOR.err } : proArmed ? { label: "\u21E7 pro", color: COLOR.warn } : null;
14456
- const projectName = rootDir ? basename(rootDir) : null;
14457
- const cachePct = Math.round(summary.cacheHitRatio * 100);
14458
- const cacheColor = summary.cacheHitRatio >= 0.7 ? COLOR.ok : summary.cacheHitRatio >= 0.4 ? COLOR.warn : COLOR.err;
14459
- return /* @__PURE__ */ React23.createElement(Box21, null, /* @__PURE__ */ React23.createElement(Text19, { bold: true, color: GRADIENT[0] }, "\u25C8 "), /* @__PURE__ */ React23.createElement(Text19, { color: COLOR.brand, bold: true }, "reasonix"), projectName ? /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(Text19, { color: COLOR.info, dimColor: true }, " \xB7 "), /* @__PURE__ */ React23.createElement(Text19, null, projectName), !narrow && sessionName ? /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(Text19, { color: COLOR.info, dimColor: true }, " \u203A "), /* @__PURE__ */ React23.createElement(Text19, { color: COLOR.info }, sessionName)) : null) : null, /* @__PURE__ */ React23.createElement(Box21, { flexGrow: 1 }), updateAvailable ? /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(Text19, { color: COLOR.warn, bold: true }, `\u2191 ${updateAvailable}`), /* @__PURE__ */ React23.createElement(Text19, null, " ")) : null, modePill ? /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(Text19, { color: modePill.color, bold: true }, `[${modePill.label}]`), /* @__PURE__ */ React23.createElement(Text19, null, " ")) : null, proPill ? /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(Text19, { color: proPill.color, bold: true }, `[${proPill.label}]`), /* @__PURE__ */ React23.createElement(Text19, null, " ")) : null, /* @__PURE__ */ React23.createElement(
14460
- Text19,
14461
- {
14462
- color: summary.turns === 0 || coldStart ? COLOR.info : sessionCostColor(summary.totalCostUsd),
14463
- bold: summary.turns > 0 && !coldStart,
14464
- dimColor: summary.turns === 0 || coldStart
14465
- },
14466
- `[$${summary.totalCostUsd.toFixed(4)}]`
14467
- ), balance && !narrow ? /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(Text19, null, " "), /* @__PURE__ */ React23.createElement(Text19, { color: balance.total < 1 ? COLOR.err : balance.total < 5 ? COLOR.warn : COLOR.ok }, `[w ${balance.currency === "USD" ? "$" : ""}${balance.total.toFixed(2)}${balance.currency !== "USD" ? ` ${balance.currency}` : ""}]`)) : null, summary.turns > 3 && !narrow ? /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(Text19, null, " "), /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "["), /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "c "), /* @__PURE__ */ React23.createElement(Bar, { ratio: summary.cacheHitRatio, color: cacheColor, cells: 6 }), /* @__PURE__ */ React23.createElement(Text19, null, " "), /* @__PURE__ */ React23.createElement(Text19, { color: cacheColor }, `${cachePct}%`), /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "]")) : null);
14468
- }
14469
- function pickModePill(planMode, editMode) {
14470
- if (planMode) return { label: "PLAN", color: COLOR.err };
14471
- if (editMode === "yolo") return { label: "yolo", color: COLOR.err };
14472
- if (editMode === "auto") return { label: "auto", color: COLOR.primary };
14473
- if (editMode === "review") return { label: "review", color: COLOR.info };
14474
- return null;
14475
- }
14476
- function BudgetRow({ spent, cap }) {
14477
- const pct2 = Math.max(0, spent / cap * 100);
14478
- const color2 = pct2 >= 100 ? "#f87171" : pct2 >= 80 ? "#fbbf24" : "#94a3b8";
14479
- return /* @__PURE__ */ React23.createElement(Box21, null, /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, " budget "), /* @__PURE__ */ React23.createElement(Text19, { color: color2 }, `$${spent.toFixed(4)} / $${cap.toFixed(2)}`, /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, ` (${pct2.toFixed(0)}%)`)));
14480
- }
14481
- function sessionCostColor(cost) {
14482
- if (cost <= 0) return void 0;
14483
- if (cost >= 5) return COLOR.err;
14484
- if (cost >= 0.5) return COLOR.warn;
14485
- return COLOR.ok;
14486
- }
14487
- function Bar({
14488
- ratio,
14489
- color: color2,
14490
- cells = 14
14491
- }) {
14492
- const filled = Math.max(0, Math.min(cells, Math.round(ratio * cells)));
14493
- return /* @__PURE__ */ React23.createElement(Text19, null, /* @__PURE__ */ React23.createElement(Text19, { color: color2 }, "\u25B0".repeat(filled)), /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "\u25B1".repeat(cells - filled)));
14454
+ return /* @__PURE__ */ React23.createElement(Box21, null, /* @__PURE__ */ React23.createElement(Text19, { color: isSelected ? COLOR.primary : COLOR.info, bold: isSelected }, isSelected ? `${GLYPH.cur} ` : " "), /* @__PURE__ */ React23.createElement(Text19, { color: COLOR.accent, bold: isSelected }, name.padEnd(14)), /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, argsSuffix.padEnd(14)), /* @__PURE__ */ React23.createElement(Text19, null, " "), /* @__PURE__ */ React23.createElement(Text19, { color: isSelected ? COLOR.user : COLOR.info, dimColor: !isSelected }, spec.summary));
14494
14455
  }
14495
14456
 
14496
14457
  // src/cli/ui/WelcomeBanner.tsx
@@ -14615,9 +14576,9 @@ function isMouseTrackingOn() {
14615
14576
  }
14616
14577
 
14617
14578
  // src/cli/ui/bang.ts
14618
- function detectBangCommand(text) {
14619
- if (!text.startsWith("!")) return null;
14620
- const body = text.slice(1).trim();
14579
+ function detectBangCommand(text2) {
14580
+ if (!text2.startsWith("!")) return null;
14581
+ const body = text2.slice(1).trim();
14621
14582
  if (!body) return null;
14622
14583
  return body;
14623
14584
  }
@@ -14723,20 +14684,20 @@ into every Reasonix session's prefix regardless of working directory.
14723
14684
  Private to this machine \u2014 not committed anywhere.
14724
14685
 
14725
14686
  `;
14726
- function detectHashMemory(text) {
14727
- if (text.startsWith("\\#")) {
14728
- return { kind: "escape", text: text.slice(1) };
14729
- }
14730
- if (!text.startsWith("#")) return null;
14731
- if (text.startsWith("##")) return null;
14732
- if (/^#g\s*$/.test(text)) return null;
14733
- const globalMatch = /^#g\s+(.+)$/s.exec(text);
14687
+ function detectHashMemory(text2) {
14688
+ if (text2.startsWith("\\#")) {
14689
+ return { kind: "escape", text: text2.slice(1) };
14690
+ }
14691
+ if (!text2.startsWith("#")) return null;
14692
+ if (text2.startsWith("##")) return null;
14693
+ if (/^#g\s*$/.test(text2)) return null;
14694
+ const globalMatch = /^#g\s+(.+)$/s.exec(text2);
14734
14695
  if (globalMatch) {
14735
14696
  const body2 = globalMatch[1].trim();
14736
14697
  if (!body2) return null;
14737
14698
  return { kind: "memory-global", note: body2 };
14738
14699
  }
14739
- const body = text.slice(1).trim();
14700
+ const body = text2.slice(1).trim();
14740
14701
  if (!body) return null;
14741
14702
  return { kind: "memory", note: body };
14742
14703
  }
@@ -14771,195 +14732,1070 @@ function appendBulletToFile(path5, note, newFileHeader) {
14771
14732
  return { path: path5, created: false };
14772
14733
  }
14773
14734
 
14774
- // src/cli/ui/log-rows.tsx
14735
+ // src/cli/ui/log-frame.tsx
14775
14736
  import { Box as Box24, Text as Text22 } from "ink";
14776
14737
  import React26 from "react";
14777
- function wrapToWidth(text, width) {
14778
- if (width <= 0) return [text];
14779
- const out = [];
14780
- for (const line of text.split("\n")) {
14738
+
14739
+ // src/frame/width.ts
14740
+ import stringWidthLib from "string-width";
14741
+ var segmenter = new Intl.Segmenter("en", { granularity: "grapheme" });
14742
+ function graphemes(s) {
14743
+ return Array.from(segmenter.segment(s), (seg) => seg.segment);
14744
+ }
14745
+ function graphemeWidth(g) {
14746
+ if (g.length === 0) return 0;
14747
+ const w = stringWidthLib(g);
14748
+ if (w <= 0) return 0;
14749
+ if (w >= 2) return 2;
14750
+ return 1;
14751
+ }
14752
+
14753
+ // src/frame/frame.ts
14754
+ var SPACE = { char: " ", width: 1 };
14755
+ var TAIL = { char: "", width: 1, tail: true };
14756
+ function empty(width = 0) {
14757
+ return { width, rows: [] };
14758
+ }
14759
+ function text(s, opts) {
14760
+ const { width, fg, bg, bold, dim, italic, underline, inverse, href } = opts;
14761
+ if (width <= 0) return empty(0);
14762
+ const styleOf = (g, w) => {
14763
+ const base = { char: g, width: w };
14764
+ if (fg !== void 0) base.fg = fg;
14765
+ if (bg !== void 0) base.bg = bg;
14766
+ if (bold) base.bold = true;
14767
+ if (dim) base.dim = true;
14768
+ if (italic) base.italic = true;
14769
+ if (underline) base.underline = true;
14770
+ if (inverse) base.inverse = true;
14771
+ if (href !== void 0) base.href = href;
14772
+ return base;
14773
+ };
14774
+ const rows = [];
14775
+ const lines = s.split("\n");
14776
+ for (const line of lines) {
14781
14777
  if (line.length === 0) {
14782
- out.push("");
14778
+ rows.push(padRowRight([], width));
14783
14779
  continue;
14784
14780
  }
14785
- if (line.length <= width) {
14786
- out.push(line);
14781
+ let buf = [];
14782
+ let bufWidth = 0;
14783
+ for (const g of graphemes(line)) {
14784
+ const w = graphemeWidth(g);
14785
+ if (w === 0) continue;
14786
+ if (bufWidth + w > width) {
14787
+ rows.push(padRowRight(buf, width - bufWidth));
14788
+ buf = [];
14789
+ bufWidth = 0;
14790
+ }
14791
+ buf.push(styleOf(g, w));
14792
+ if (w === 2) buf.push(TAIL);
14793
+ bufWidth += w;
14794
+ }
14795
+ rows.push(padRowRight(buf, width - bufWidth));
14796
+ }
14797
+ return { width, rows };
14798
+ }
14799
+ function padRowRight(cells, extraSpaces) {
14800
+ if (extraSpaces <= 0) return cells.slice();
14801
+ const out = cells.slice();
14802
+ for (let i = 0; i < extraSpaces; i++) out.push(SPACE);
14803
+ return out;
14804
+ }
14805
+ function spacerRow(width) {
14806
+ if (width <= 0) return [];
14807
+ return Array.from({ length: width }, () => SPACE);
14808
+ }
14809
+ function vstack(...frames) {
14810
+ if (frames.length === 0) return empty(0);
14811
+ const w = Math.max(...frames.map((f) => f.width));
14812
+ const rows = [];
14813
+ for (const f of frames) {
14814
+ if (f.width === w) {
14815
+ rows.push(...f.rows);
14816
+ } else {
14817
+ const extra = w - f.width;
14818
+ for (const r of f.rows) rows.push(padRowRight(r, extra));
14819
+ }
14820
+ }
14821
+ return { width: w, rows };
14822
+ }
14823
+ function hstack(...frames) {
14824
+ if (frames.length === 0) return empty(0);
14825
+ const h = Math.max(...frames.map((f) => f.rows.length));
14826
+ const w = frames.reduce((a, f) => a + f.width, 0);
14827
+ const rows = [];
14828
+ for (let i = 0; i < h; i++) {
14829
+ const cells = [];
14830
+ for (const f of frames) {
14831
+ const r = f.rows[i] ?? spacerRow(f.width);
14832
+ cells.push(...r);
14833
+ }
14834
+ rows.push(cells);
14835
+ }
14836
+ return { width: w, rows };
14837
+ }
14838
+ function pad(f, top, right, bottom2, left) {
14839
+ const newWidth = f.width + Math.max(0, left) + Math.max(0, right);
14840
+ const tPad = Math.max(0, top);
14841
+ const bPad = Math.max(0, bottom2);
14842
+ const blank2 = spacerRow(newWidth);
14843
+ const rows = [];
14844
+ for (let i = 0; i < tPad; i++) rows.push(blank2);
14845
+ if (left <= 0 && right <= 0) {
14846
+ rows.push(...f.rows);
14847
+ } else {
14848
+ const lPad = spacerRow(Math.max(0, left));
14849
+ const rPad = spacerRow(Math.max(0, right));
14850
+ for (const r of f.rows) rows.push([...lPad, ...r, ...rPad]);
14851
+ }
14852
+ for (let i = 0; i < bPad; i++) rows.push(blank2);
14853
+ return { width: newWidth, rows };
14854
+ }
14855
+ function borderLeft(f, color2, char = "\u2502") {
14856
+ const bar = { char, width: 1, fg: color2 };
14857
+ const newWidth = f.width + 1;
14858
+ const rows = [];
14859
+ for (const r of f.rows) rows.push([bar, ...r]);
14860
+ return { width: newWidth, rows };
14861
+ }
14862
+
14863
+ // src/frame/ansi.ts
14864
+ var ESC = "\x1B";
14865
+ var RESET = `${ESC}[0m`;
14866
+ function sameStyle(a, b) {
14867
+ return a.fg === b.fg && a.bg === b.bg && !!a.bold === !!b.bold && !!a.dim === !!b.dim && !!a.italic === !!b.italic && !!a.underline === !!b.underline && !!a.inverse === !!b.inverse && a.href === b.href;
14868
+ }
14869
+ function fgEscape(color2) {
14870
+ if (!color2) return null;
14871
+ const rgb = parseColor(color2);
14872
+ if (rgb) return `38;2;${rgb[0]};${rgb[1]};${rgb[2]}`;
14873
+ const named = NAMED_FG[color2.toLowerCase()];
14874
+ if (named !== void 0) return String(named);
14875
+ return null;
14876
+ }
14877
+ function bgEscape(color2) {
14878
+ if (!color2) return null;
14879
+ const rgb = parseColor(color2);
14880
+ if (rgb) return `48;2;${rgb[0]};${rgb[1]};${rgb[2]}`;
14881
+ const named = NAMED_BG[color2.toLowerCase()];
14882
+ if (named !== void 0) return String(named);
14883
+ return null;
14884
+ }
14885
+ function parseColor(s) {
14886
+ if (!s.startsWith("#")) return null;
14887
+ const hex = s.slice(1);
14888
+ if (hex.length !== 6) return null;
14889
+ const r = Number.parseInt(hex.slice(0, 2), 16);
14890
+ const g = Number.parseInt(hex.slice(2, 4), 16);
14891
+ const b = Number.parseInt(hex.slice(4, 6), 16);
14892
+ if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) return null;
14893
+ return [r, g, b];
14894
+ }
14895
+ var NAMED_FG = {
14896
+ black: 30,
14897
+ red: 31,
14898
+ green: 32,
14899
+ yellow: 33,
14900
+ blue: 34,
14901
+ magenta: 35,
14902
+ cyan: 36,
14903
+ white: 37,
14904
+ gray: 90,
14905
+ grey: 90,
14906
+ brightred: 91,
14907
+ brightgreen: 92,
14908
+ brightyellow: 93,
14909
+ brightblue: 94,
14910
+ brightmagenta: 95,
14911
+ brightcyan: 96,
14912
+ brightwhite: 97
14913
+ };
14914
+ var NAMED_BG = {
14915
+ black: 40,
14916
+ red: 41,
14917
+ green: 42,
14918
+ yellow: 43,
14919
+ blue: 44,
14920
+ magenta: 45,
14921
+ cyan: 46,
14922
+ white: 47,
14923
+ gray: 100,
14924
+ grey: 100
14925
+ };
14926
+ function styleToAnsi(s) {
14927
+ const codes = [];
14928
+ if (s.bold) codes.push("1");
14929
+ if (s.dim) codes.push("2");
14930
+ if (s.italic) codes.push("3");
14931
+ if (s.underline) codes.push("4");
14932
+ if (s.inverse) codes.push("7");
14933
+ const fg = fgEscape(s.fg);
14934
+ if (fg) codes.push(fg);
14935
+ const bg = bgEscape(s.bg);
14936
+ if (bg) codes.push(bg);
14937
+ if (codes.length === 0) return "";
14938
+ return `${ESC}[${codes.join(";")}m`;
14939
+ }
14940
+ var EMPTY_STYLE = {};
14941
+ function frameToAnsi(f, opts = {}) {
14942
+ const out = [];
14943
+ for (let i = 0; i < f.rows.length; i++) {
14944
+ out.push(rowToAnsi(f.rows[i], opts));
14945
+ }
14946
+ return out.join("\n");
14947
+ }
14948
+ function rowToAnsi(row2, opts) {
14949
+ if (opts.plain) {
14950
+ let s = "";
14951
+ for (const c of row2) {
14952
+ if (c.tail) continue;
14953
+ s += c.char;
14954
+ }
14955
+ return s;
14956
+ }
14957
+ let result = "";
14958
+ let curStyle = EMPTY_STYLE;
14959
+ let inHref = false;
14960
+ let curHref;
14961
+ for (const c of row2) {
14962
+ if (c.tail) continue;
14963
+ const cellStyle = {
14964
+ fg: c.fg,
14965
+ bg: c.bg,
14966
+ bold: c.bold,
14967
+ dim: c.dim,
14968
+ italic: c.italic,
14969
+ underline: c.underline,
14970
+ inverse: c.inverse,
14971
+ href: c.href
14972
+ };
14973
+ if (cellStyle.href !== curHref) {
14974
+ if (inHref) {
14975
+ result += `${ESC}]8;;${ESC}\\`;
14976
+ inHref = false;
14977
+ }
14978
+ if (cellStyle.href !== void 0) {
14979
+ result += `${ESC}]8;;${cellStyle.href}${ESC}\\`;
14980
+ inHref = true;
14981
+ }
14982
+ curHref = cellStyle.href;
14983
+ }
14984
+ if (!sameStyle(curStyle, cellStyle)) {
14985
+ result += RESET;
14986
+ result += styleToAnsi(cellStyle);
14987
+ curStyle = cellStyle;
14988
+ }
14989
+ result += c.char;
14990
+ }
14991
+ if (inHref) result += `${ESC}]8;;${ESC}\\`;
14992
+ result += RESET;
14993
+ return result;
14994
+ }
14995
+
14996
+ // src/cli/ui/markdown-frame.ts
14997
+ var INLINE_RE2 = /(\[([^\]\n]+)\]\(([^)\n]+)\)|\*\*\*([^*\n]+?)\*\*\*|\*\*([^*\n]+?)\*\*|```([^\n]+?)```|`([^`\n]+?)`|~~([^~\n]+?)~~|(?<![*\w])\*([^*\n]+?)\*(?!\w)|\\([*_~`[\](){}#+\-.!\\]))/g;
14998
+ function parseInline(input, baseOpts) {
14999
+ const out = [];
15000
+ let lastEnd = 0;
15001
+ INLINE_RE2.lastIndex = 0;
15002
+ for (let m = INLINE_RE2.exec(input); m !== null; m = INLINE_RE2.exec(input)) {
15003
+ if (m.index > lastEnd) {
15004
+ out.push({ text: input.slice(lastEnd, m.index), opts: baseOpts });
15005
+ }
15006
+ const linkText = m[2];
15007
+ const linkUrl = m[3];
15008
+ const boldItalic = m[4];
15009
+ const bold = m[5];
15010
+ const code3 = m[6];
15011
+ const code1 = m[7];
15012
+ const strike = m[8];
15013
+ const italic = m[9];
15014
+ const escapeChar = m[10];
15015
+ if (linkText !== void 0) {
15016
+ out.push({
15017
+ text: linkText,
15018
+ opts: { ...baseOpts, fg: COLOR.accent, underline: true, href: linkUrl }
15019
+ });
15020
+ } else if (boldItalic !== void 0) {
15021
+ out.push({ text: boldItalic, opts: { ...baseOpts, bold: true, italic: true } });
15022
+ } else if (bold !== void 0) {
15023
+ out.push({ text: bold, opts: { ...baseOpts, bold: true } });
15024
+ } else if (code3 !== void 0) {
15025
+ const stripped = code3.replace(/^(\w+)\s+/, "");
15026
+ out.push({ text: stripped, opts: { ...baseOpts, fg: "#67e8f9", bg: "#0f172a" } });
15027
+ } else if (code1 !== void 0) {
15028
+ out.push({ text: code1, opts: { ...baseOpts, fg: "#67e8f9", bg: "#0f172a" } });
15029
+ } else if (strike !== void 0) {
15030
+ out.push({ text: strike, opts: { ...baseOpts, dim: true } });
15031
+ } else if (italic !== void 0) {
15032
+ out.push({ text: italic, opts: { ...baseOpts, italic: true } });
15033
+ } else if (escapeChar !== void 0) {
15034
+ out.push({ text: escapeChar, opts: baseOpts });
15035
+ }
15036
+ lastEnd = m.index + m[0].length;
15037
+ }
15038
+ if (lastEnd < input.length) {
15039
+ out.push({ text: input.slice(lastEnd), opts: baseOpts });
15040
+ }
15041
+ return out;
15042
+ }
15043
+ function segmentsToFrame(segs, width) {
15044
+ if (width <= 0) return empty(0);
15045
+ const atoms = [];
15046
+ for (const seg of segs) {
15047
+ if (!seg.text) continue;
15048
+ const f = text(seg.text, { ...seg.opts, width: Math.max(width, seg.text.length * 2 + 4) });
15049
+ if (f.rows.length > 0) {
15050
+ let stop = f.rows[0].length;
15051
+ while (stop > 0 && f.rows[0][stop - 1].char === " " && f.rows[0][stop - 1].fg === void 0 && f.rows[0][stop - 1].bg === void 0) {
15052
+ stop--;
15053
+ }
15054
+ for (let i = 0; i < stop; i++) atoms.push(f.rows[0][i]);
15055
+ }
15056
+ for (let li = 1; li < f.rows.length; li++) {
15057
+ atoms.push({ char: "\n", width: 1 });
15058
+ let stop = f.rows[li].length;
15059
+ while (stop > 0 && f.rows[li][stop - 1].char === " " && f.rows[li][stop - 1].fg === void 0) {
15060
+ stop--;
15061
+ }
15062
+ for (let i = 0; i < stop; i++) atoms.push(f.rows[li][i]);
15063
+ }
15064
+ }
15065
+ const SPACE2 = { char: " ", width: 1 };
15066
+ const rows = [];
15067
+ let cur = [];
15068
+ let curW = 0;
15069
+ let lastSpaceIdx = -1;
15070
+ const flushRow = (forceNewline = false) => {
15071
+ while (curW < width) {
15072
+ cur.push(SPACE2);
15073
+ curW += 1;
15074
+ }
15075
+ rows.push(cur);
15076
+ cur = [];
15077
+ curW = 0;
15078
+ lastSpaceIdx = -1;
15079
+ if (forceNewline) return;
15080
+ };
15081
+ for (const a of atoms) {
15082
+ if (a.char === "\n") {
15083
+ flushRow(true);
14787
15084
  continue;
14788
15085
  }
14789
- let i = 0;
14790
- while (i < line.length) {
14791
- out.push(line.slice(i, i + width));
14792
- i += width;
15086
+ const w = a.tail ? 0 : a.width;
15087
+ if (curW + w > width) {
15088
+ if (lastSpaceIdx >= 0 && lastSpaceIdx > 0) {
15089
+ const overflow = cur.slice(lastSpaceIdx + 1);
15090
+ cur = cur.slice(0, lastSpaceIdx);
15091
+ let newW = 0;
15092
+ for (const c of cur) newW += c.tail ? 0 : c.width;
15093
+ while (newW < width) {
15094
+ cur.push(SPACE2);
15095
+ newW += 1;
15096
+ }
15097
+ rows.push(cur);
15098
+ cur = overflow;
15099
+ curW = 0;
15100
+ for (const c of cur) curW += c.tail ? 0 : c.width;
15101
+ lastSpaceIdx = -1;
15102
+ } else {
15103
+ flushRow();
15104
+ }
15105
+ }
15106
+ if (a.char === " ") lastSpaceIdx = cur.length;
15107
+ cur.push(a);
15108
+ curW += w;
15109
+ }
15110
+ if (cur.length > 0 || rows.length === 0) {
15111
+ flushRow();
15112
+ }
15113
+ return { width, rows };
15114
+ }
15115
+ function paragraphFrame(p, width) {
15116
+ const segs = parseInline(p.text, {});
15117
+ return segmentsToFrame(segs, width);
15118
+ }
15119
+ function headingFrame(h, width) {
15120
+ const isMajor = h.level <= 3;
15121
+ const fg = isMajor ? COLOR.brand : COLOR.accent;
15122
+ const segs = parseInline(h.text, { bold: true, fg, dim: !isMajor });
15123
+ return vstack(segmentsToFrame(segs, width), text("", { width }));
15124
+ }
15125
+ function bulletListFrame(b, width) {
15126
+ const rows = [];
15127
+ for (let i = 0; i < b.items.length; i++) {
15128
+ const item = b.items[i];
15129
+ let prefix;
15130
+ let prefixOpts;
15131
+ if (item.task === "done") {
15132
+ prefix = "[x] ";
15133
+ prefixOpts = { fg: COLOR.ok, bold: true };
15134
+ } else if (item.task === "todo") {
15135
+ prefix = "[ ] ";
15136
+ prefixOpts = { fg: COLOR.warn, bold: true };
15137
+ } else if (b.ordered) {
15138
+ prefix = `${i + 1}. `;
15139
+ prefixOpts = { fg: COLOR.info, bold: true };
15140
+ } else {
15141
+ prefix = "\u2022 ";
15142
+ prefixOpts = { fg: COLOR.info, bold: true };
15143
+ }
15144
+ const prefixWidth = prefix.length;
15145
+ const indentRow = " ".repeat(prefixWidth);
15146
+ const innerSegs = parseInline(item.text, {});
15147
+ const innerFrame = segmentsToFrame(innerSegs, Math.max(8, width - prefixWidth));
15148
+ const decoratedRows = innerFrame.rows.map((r, li) => {
15149
+ const indent = li === 0 ? text(prefix, { width: prefixWidth, ...prefixOpts }) : text(indentRow, { width: prefixWidth });
15150
+ return {
15151
+ width: prefixWidth + innerFrame.width,
15152
+ rows: [[...indent.rows[0], ...r]]
15153
+ };
15154
+ });
15155
+ rows.push(...decoratedRows);
15156
+ }
15157
+ return vstack(...rows);
15158
+ }
15159
+ function codeBlockFrame(c, width) {
15160
+ const lines = c.text.split("\n");
15161
+ const rows = [];
15162
+ if (c.lang) {
15163
+ rows.push(text(c.lang, { width, fg: COLOR.info, dim: true, italic: true }));
15164
+ }
15165
+ for (const line of lines) {
15166
+ rows.push(text(line || " ", { width, fg: "#67e8f9", bg: "#0f172a" }));
15167
+ }
15168
+ return vstack(...rows);
15169
+ }
15170
+ function blockquoteFrame(bq, width) {
15171
+ const inner = bq.children.map((child) => blockToFrame(child, Math.max(8, width - 2)));
15172
+ const stacked = inner.length === 0 ? empty(Math.max(8, width - 2)) : vstack(...inner);
15173
+ return borderLeft(pad(stacked, 0, 0, 0, 1), COLOR.info);
15174
+ }
15175
+ function hrFrame(width) {
15176
+ return text("\u2500".repeat(width), { width, fg: COLOR.info, dim: true });
15177
+ }
15178
+ function blockToFrame(b, width) {
15179
+ switch (b.kind) {
15180
+ case "paragraph":
15181
+ return paragraphFrame(b, width);
15182
+ case "heading":
15183
+ return headingFrame(b, width);
15184
+ case "bullet":
15185
+ return bulletListFrame(b, width);
15186
+ case "code":
15187
+ return codeBlockFrame(b, width);
15188
+ case "quote":
15189
+ return blockquoteFrame(b, width);
15190
+ case "hr":
15191
+ return hrFrame(width);
15192
+ case "table":
15193
+ return vstack(
15194
+ text(b.header.join(" | "), { width, bold: true }),
15195
+ text(b.header.map(() => "\u2500").join("\u2500\u253C\u2500"), { width, dim: true }),
15196
+ text(b.rows.map((r) => r.join(" | ")).join("\n"), { width, dim: true })
15197
+ );
15198
+ case "edit-block":
15199
+ return text(`${b.filename}
15200
+ <<< SEARCH
15201
+ ${b.search}
15202
+ =======
15203
+ ${b.replace}
15204
+ >>> REPLACE`, {
15205
+ width,
15206
+ dim: true
15207
+ });
15208
+ default:
15209
+ return empty(width);
15210
+ }
15211
+ }
15212
+ function markdownToFrame(markdown, width) {
15213
+ if (!markdown) return empty(width);
15214
+ const blocks = parseBlocks(markdown);
15215
+ if (blocks.length === 0) return empty(width);
15216
+ const frames = [];
15217
+ for (let i = 0; i < blocks.length; i++) {
15218
+ const b = blocks[i];
15219
+ frames.push(blockToFrame(b, width));
15220
+ const isLast = i === blocks.length - 1;
15221
+ const carriesOwnSpacer = b.kind === "heading";
15222
+ if (!isLast && !carriesOwnSpacer) {
15223
+ frames.push(text("", { width }));
15224
+ }
15225
+ }
15226
+ return vstack(...frames);
15227
+ }
15228
+
15229
+ // src/cli/ui/log-frame.tsx
15230
+ function formatTokensCompact2(n) {
15231
+ if (n < 1024) return String(n);
15232
+ const k = n / 1024;
15233
+ return k >= 100 ? `${k.toFixed(0)}K` : `${k.toFixed(1)}K`;
15234
+ }
15235
+ var ROLE_GLYPH2 = {
15236
+ user: "\u25C7",
15237
+ toolOk: GLYPH.toolOk,
15238
+ toolErr: GLYPH.toolErr
15239
+ };
15240
+ var SPACE_CELL = { char: " ", width: 1 };
15241
+ function rowFrame(parts, width) {
15242
+ const cells = [];
15243
+ for (const p of parts) {
15244
+ if (p.rows.length > 0) cells.push(...p.rows[0]);
15245
+ }
15246
+ const w = width ?? cells.reduce((a, c) => a + (c.tail ? 0 : c.width), 0);
15247
+ if (cells.length > w) cells.length = w;
15248
+ while (cells.reduce((a, c) => a + (c.tail ? 0 : c.width), 0) < w) cells.push(SPACE_CELL);
15249
+ return { width: w, rows: [cells] };
15250
+ }
15251
+ function atomRows(a) {
15252
+ return a.kind === "frame" ? a.frame.rows.length : a.rows;
15253
+ }
15254
+ function detectInfoTone(rawText) {
15255
+ const m = rawText.match(/^([▸▶▲⚠✓✗✖↻ⓘ])\s*(.*)$/s);
15256
+ const lead = m?.[1] ?? "\u25B8";
15257
+ const body = m?.[2] ?? rawText;
15258
+ let color2 = COLOR.info;
15259
+ if (lead === "\u25B2" || lead === "\u26A0") color2 = COLOR.warn;
15260
+ else if (lead === "\u2713") color2 = COLOR.ok;
15261
+ else if (lead === "\u2717" || lead === "\u2716") color2 = COLOR.err;
15262
+ else if (lead === "\u21BB") color2 = COLOR.primary;
15263
+ return { lead, color: color2, body };
15264
+ }
15265
+ function accentFrame(glyph, glyphColor, body, bodyColor, bodyDim, width) {
15266
+ const indentCells = 1 + glyph.length + 2;
15267
+ const inner = Math.max(8, width - indentCells);
15268
+ const bodyFrame = text(body, {
15269
+ width: inner,
15270
+ fg: bodyColor,
15271
+ dim: bodyDim
15272
+ });
15273
+ const rows = [];
15274
+ for (let i = 0; i < bodyFrame.rows.length; i++) {
15275
+ const indent = i === 0 ? text(`${glyph} `, { width: indentCells - 1, fg: glyphColor, bold: true }) : text(" ".repeat(indentCells - 1), { width: indentCells - 1 });
15276
+ rows.push({
15277
+ width: bodyFrame.width + indent.width,
15278
+ rows: [[...indent.rows[0], ...bodyFrame.rows[i]]]
15279
+ });
15280
+ }
15281
+ const stacked = vstack(...rows);
15282
+ return borderLeft(stacked, glyphColor);
15283
+ }
15284
+ function infoFrame(event, width) {
15285
+ const { lead, color: color2, body } = detectInfoTone(event.text);
15286
+ return accentFrame(lead, color2, body, void 0, true, width);
15287
+ }
15288
+ function warningFrame(event, width) {
15289
+ return accentFrame("\u25B2 warn", COLOR.warn, event.text, COLOR.warn, false, width);
15290
+ }
15291
+ function errorFrame(event, width) {
15292
+ return accentFrame("\u2726 error", COLOR.err, event.text, COLOR.err, false, width);
15293
+ }
15294
+ function stepProgressFrame(event, width) {
15295
+ const sp = event.stepProgress;
15296
+ const counter = sp && sp.total > 0 ? `${sp.completed}/${sp.total}` : "";
15297
+ const label = sp?.title ? `${sp.stepId} \xB7 ${sp.title}` : sp?.stepId ?? "";
15298
+ const pillFrame = text(" \u2713 STEP ", { width: 8, bg: "#4ade80", fg: "black", bold: true });
15299
+ const counterFrame = counter ? text(` ${counter}`, { width: 2 + counter.length, fg: "#4ade80", bold: true }) : empty(0);
15300
+ const labelFrame = text(` ${label}`, { width: width - 8 - counterFrame.width, fg: "#86efac" });
15301
+ const headerWidth = pillFrame.width + counterFrame.width + labelFrame.width;
15302
+ const headerRow = {
15303
+ width: headerWidth,
15304
+ rows: [[...pillFrame.rows[0], ...counterFrame.rows[0], ...labelFrame.rows[0]]]
15305
+ };
15306
+ const bodyParts = [];
15307
+ if (event.text) {
15308
+ bodyParts.push(pad(text(event.text, { width: width - 2, dim: true }), 0, 0, 0, 2));
15309
+ }
15310
+ if (sp?.notes) {
15311
+ bodyParts.push(
15312
+ pad(text(`note: ${sp.notes}`, { width: width - 2, fg: "#fbbf24", dim: true }), 0, 0, 0, 2)
15313
+ );
15314
+ }
15315
+ const spacer = text("", { width });
15316
+ return vstack(spacer, headerRow, ...bodyParts);
15317
+ }
15318
+ function simpleAssistantFrame(event, width) {
15319
+ const spacer = text("", { width });
15320
+ const glyph = text("\u25C6", { width: 1, fg: COLOR.assistant, bold: true });
15321
+ let header2 = glyph;
15322
+ if (event.stats) {
15323
+ const badge2 = text(` ${event.stats.model.replace(/^deepseek-/, "")} `, {
15324
+ width: 2 + event.stats.model.replace(/^deepseek-/, "").length,
15325
+ bg: COLOR.assistant,
15326
+ fg: "black",
15327
+ bold: true
15328
+ });
15329
+ const gap = text(" ", { width: 2 });
15330
+ header2 = {
15331
+ width: glyph.width + gap.width + badge2.width,
15332
+ rows: [[...glyph.rows[0], ...gap.rows[0], ...badge2.rows[0]]]
15333
+ };
15334
+ }
15335
+ const bodyInnerWidth = width - 1 - 2;
15336
+ const bodyInner = event.text ? markdownToFrame(event.text, bodyInnerWidth) : text("(empty body \u2014 likely tool-call only)", {
15337
+ width: bodyInnerWidth,
15338
+ fg: COLOR.assistant,
15339
+ dim: true
15340
+ });
15341
+ const bodyIndented = pad(bodyInner, 0, 0, 0, 2);
15342
+ const bodyBordered = borderLeft(bodyIndented, COLOR.assistant);
15343
+ const parts = [spacer, header2, bodyBordered];
15344
+ if (event.repair) {
15345
+ parts.push(pad(text(event.repair, { width: width - 2, fg: COLOR.accent }), 0, 0, 0, 2));
15346
+ }
15347
+ if (event.stats) {
15348
+ const hit = (event.stats.cacheHitRatio * 100).toFixed(1);
15349
+ const hitColor = event.stats.cacheHitRatio >= 0.7 ? "#4ade80" : event.stats.cacheHitRatio >= 0.4 ? "#fcd34d" : "#f87171";
15350
+ const statsLine = `\u232C ${hit}% \xB7 in ${event.stats.usage.promptTokens} \u2192 out ${event.stats.usage.completionTokens} \xB7 $${event.stats.cost.toFixed(6)}`;
15351
+ parts.push(pad(text(statsLine, { width: width - 2, fg: hitColor }), 0, 0, 0, 2));
15352
+ }
15353
+ return vstack(...parts);
15354
+ }
15355
+ function turnSeparatorFrame(width) {
15356
+ const w = Math.max(16, width - 2);
15357
+ const sideWidth = Math.max(2, Math.floor((w - 5) / 2));
15358
+ const left = gradientCells(sideWidth, "\u2500");
15359
+ const right = gradientCells(sideWidth, "\u2500");
15360
+ const sideCells = (cells) => cells.map(({ ch, color: color2 }) => ({ char: ch, width: 1, fg: color2 }));
15361
+ const center = [
15362
+ SPACE_CELL,
15363
+ SPACE_CELL,
15364
+ { char: "\u25C6", width: 1, fg: COLOR.brand, bold: true },
15365
+ SPACE_CELL,
15366
+ SPACE_CELL
15367
+ ];
15368
+ const totalUsed = sideWidth * 2 + 5;
15369
+ const padLeft = Math.max(0, Math.floor((width - totalUsed) / 2));
15370
+ const padRight2 = Math.max(0, width - totalUsed - padLeft);
15371
+ const padCells = (n) => Array.from({ length: n }, () => SPACE_CELL);
15372
+ return {
15373
+ width,
15374
+ rows: [
15375
+ [
15376
+ ...padCells(padLeft),
15377
+ ...sideCells(left),
15378
+ ...center,
15379
+ ...sideCells(right),
15380
+ ...padCells(padRight2)
15381
+ ]
15382
+ ]
15383
+ };
15384
+ }
15385
+ function userFrame(event, width) {
15386
+ const indentWidth = 3;
15387
+ const bodyInner = text(event.text, { width: Math.max(8, width - indentWidth - 2) });
15388
+ const padded = pad(bodyInner, 0, 0, 0, 1);
15389
+ const bordered = borderLeft(padded, COLOR.user);
15390
+ const indentRows = bordered.rows.map(
15391
+ (_, i) => i === 0 ? text(`${ROLE_GLYPH2.user} `, { width: indentWidth, fg: "cyan", bold: true }) : text(" ".repeat(indentWidth), { width: indentWidth })
15392
+ );
15393
+ const indentCol = vstack(...indentRows);
15394
+ let body = hstack(indentCol, bordered);
15395
+ if (event.leadSeparator) {
15396
+ body = vstack(turnSeparatorFrame(width), body);
15397
+ }
15398
+ return body;
15399
+ }
15400
+ function toolCompactFrame(event, width) {
15401
+ const summary = summarizeToolResult(event.toolName ?? "?", event.text);
15402
+ const status2 = summary.isError ? "err" : "ok";
15403
+ const symbol = status2 === "err" ? ROLE_GLYPH2.toolErr : ROLE_GLYPH2.toolOk;
15404
+ const pillFg = status2 === "err" ? "red" : "cyan";
15405
+ const accent = status2 === "err" ? COLOR.toolErr : COLOR.tool;
15406
+ const innerWidth = width - 2;
15407
+ const segments = [];
15408
+ const pillText = `${symbol} ${event.toolName ?? "?"}`;
15409
+ segments.push(text(pillText, { width: pillText.length, fg: pillFg, bold: true }));
15410
+ if (event.durationMs !== void 0 && event.durationMs >= 100) {
15411
+ const dur = ` ${formatDuration(event.durationMs)}`;
15412
+ segments.push(text(dur, { width: dur.length, dim: true }));
15413
+ }
15414
+ segments.push(text(" ", { width: 2, dim: true }));
15415
+ const used = segments.reduce((a, p) => a + p.width, 0);
15416
+ const indexHint = event.toolIndex !== void 0 ? ` /tool ${event.toolIndex}` : "";
15417
+ const summaryBudget = Math.max(8, innerWidth - used - indexHint.length);
15418
+ segments.push(
15419
+ text(summary.summary, {
15420
+ width: summaryBudget,
15421
+ fg: status2 === "err" ? "red" : void 0,
15422
+ dim: status2 === "ok"
15423
+ })
15424
+ );
15425
+ if (indexHint) {
15426
+ segments.push(text(indexHint, { width: indexHint.length, dim: true }));
15427
+ }
15428
+ const inner = rowFrame(
15429
+ segments.map((s) => ({ width: s.width, rows: [s.rows[0] ?? []] })),
15430
+ innerWidth
15431
+ );
15432
+ return borderLeft(pad(inner, 0, 0, 0, 1), accent);
15433
+ }
15434
+ function editFileDiffFrame(event, width) {
15435
+ const lines = event.text.split(/\r?\n/);
15436
+ const [statusHeader, hunkHeader, ...body] = lines;
15437
+ const innerWidth = width - 2;
15438
+ const parts = [];
15439
+ parts.push(
15440
+ rowFrame(
15441
+ [
15442
+ text(`${ROLE_GLYPH2.toolOk} ${event.toolName ?? "edit_file"}`, {
15443
+ width: 2 + (event.toolName ?? "edit_file").length,
15444
+ fg: "cyan",
15445
+ bold: true
15446
+ }),
15447
+ text(" diff:", { width: 8, dim: true })
15448
+ ],
15449
+ innerWidth
15450
+ )
15451
+ );
15452
+ if (statusHeader !== void 0) {
15453
+ parts.push(text(` ${statusHeader}`, { width: innerWidth, dim: true }));
15454
+ }
15455
+ parts.push(text("", { width: innerWidth }));
15456
+ if (hunkHeader !== void 0) {
15457
+ const hunk = hunkHeader.trim();
15458
+ parts.push(
15459
+ rowFrame(
15460
+ [
15461
+ text(` ${hunk} `, {
15462
+ width: hunk.length + 2,
15463
+ bg: "#c4b5fd",
15464
+ fg: "black",
15465
+ bold: true
15466
+ })
15467
+ ],
15468
+ innerWidth
15469
+ )
15470
+ );
15471
+ }
15472
+ for (const line of body) {
15473
+ const stripped = line.replace(/^ {2}/, "");
15474
+ if (stripped.startsWith("- ")) {
15475
+ parts.push(
15476
+ rowFrame(
15477
+ [
15478
+ text("\u2212 ", { width: 2, fg: "#f87171", bold: true }),
15479
+ text(stripped.slice(2), { width: innerWidth - 2, fg: "#fca5a5" })
15480
+ ],
15481
+ innerWidth
15482
+ )
15483
+ );
15484
+ } else if (stripped.startsWith("+ ")) {
15485
+ parts.push(
15486
+ rowFrame(
15487
+ [
15488
+ text("+ ", { width: 2, fg: "#4ade80", bold: true }),
15489
+ text(stripped.slice(2), { width: innerWidth - 2, fg: "#86efac" })
15490
+ ],
15491
+ innerWidth
15492
+ )
15493
+ );
15494
+ } else {
15495
+ parts.push(
15496
+ rowFrame(
15497
+ [
15498
+ text(" ", { width: 2, dim: true }),
15499
+ text(stripped, { width: innerWidth - 2, dim: true })
15500
+ ],
15501
+ innerWidth
15502
+ )
15503
+ );
14793
15504
  }
14794
15505
  }
14795
- return out;
15506
+ const inner = vstack(...parts);
15507
+ return borderLeft(pad(inner, 0, 0, 0, 1), COLOR.tool);
14796
15508
  }
14797
- function itemRows(item) {
14798
- return item.kind === "row" ? 1 : item.rows;
14799
- }
14800
- function detectInfoTone(text) {
14801
- const m = text.match(/^([▸▶▲⚠✓✗✖↻ⓘ])\s*(.*)$/s);
14802
- const lead = m?.[1] ?? "\u25B8";
14803
- const body = m?.[2] ?? text;
14804
- let color2 = COLOR.info;
14805
- if (lead === "\u25B2" || lead === "\u26A0") color2 = COLOR.warn;
14806
- else if (lead === "\u2713") color2 = COLOR.ok;
14807
- else if (lead === "\u2717" || lead === "\u2716") color2 = COLOR.err;
14808
- else if (lead === "\u21BB") color2 = COLOR.primary;
14809
- return { lead, color: color2, body };
15509
+ function reasoningFrame(reasoning, width) {
15510
+ const max = 260;
15511
+ const flat = reasoning.replace(/\s+/g, " ").trim();
15512
+ const preview = flat.length <= max ? flat : `\u2026 (+${flat.length - max} earlier chars) ${flat.slice(-max)}`;
15513
+ const tokensApprox = Math.max(1, Math.round(flat.length / 4.5));
15514
+ const tokLabel = tokensApprox >= 1e3 ? `${(tokensApprox / 1e3).toFixed(1)}k` : `${tokensApprox}`;
15515
+ const header2 = rowFrame(
15516
+ [
15517
+ text("R1 \u21AF", { width: 5, fg: COLOR.accent, bold: true }),
15518
+ text(` reasoning \xB7 ~${tokLabel} tok \xB7 /think for full`, {
15519
+ width: 28 + tokLabel.length,
15520
+ dim: true
15521
+ })
15522
+ ],
15523
+ width
15524
+ );
15525
+ const previewBody = pad(
15526
+ text(preview, { width: width - 2, fg: COLOR.accent, italic: true, dim: true }),
15527
+ 0,
15528
+ 0,
15529
+ 0,
15530
+ 1
15531
+ );
15532
+ const previewBordered = borderLeft(previewBody, COLOR.accent);
15533
+ const trail = text("", { width });
15534
+ return vstack(header2, previewBordered, trail);
14810
15535
  }
14811
- function AccentRow({
14812
- color: color2,
14813
- prefix,
14814
- body,
14815
- bodyColor,
14816
- bodyDim
14817
- }) {
14818
- return /* @__PURE__ */ React26.createElement(
14819
- Box24,
14820
- {
14821
- borderStyle: "single",
14822
- borderTop: false,
14823
- borderRight: false,
14824
- borderBottom: false,
14825
- borderColor: color2,
14826
- paddingLeft: 1
14827
- },
14828
- prefix,
14829
- /* @__PURE__ */ React26.createElement(Text22, { color: bodyColor, dimColor: bodyDim }, body)
15536
+ function branchFrame(branch2, width) {
15537
+ const pill = rowFrame(
15538
+ [
15539
+ text(` \u2387 BRANCH \xD7${branch2.budget} `, {
15540
+ width: 12 + String(branch2.budget).length,
15541
+ bg: "#93c5fd",
15542
+ fg: "black",
15543
+ bold: true
15544
+ }),
15545
+ text(" ", { width: 2 }),
15546
+ text("picked ", { width: 7, fg: "#93c5fd" }),
15547
+ text(`#${branch2.chosenIndex}`, {
15548
+ width: 1 + String(branch2.chosenIndex).length,
15549
+ fg: "#93c5fd",
15550
+ bold: true
15551
+ })
15552
+ ],
15553
+ width
14830
15554
  );
15555
+ const items = [];
15556
+ for (let i = 0; i < branch2.uncertainties.length; i++) {
15557
+ const u = branch2.uncertainties[i];
15558
+ const chosen = i === branch2.chosenIndex;
15559
+ const t2 = (branch2.temperatures[i] ?? 0).toFixed(1);
15560
+ items.push(
15561
+ pad(
15562
+ rowFrame(
15563
+ [
15564
+ text(chosen ? "\u25B8 " : " ", {
15565
+ width: 2,
15566
+ fg: chosen ? "#93c5fd" : "#475569",
15567
+ bold: chosen
15568
+ }),
15569
+ text(`#${i}`, {
15570
+ width: 1 + String(i).length,
15571
+ fg: chosen ? "#93c5fd" : "#94a3b8",
15572
+ bold: chosen
15573
+ }),
15574
+ text(` T=${t2} u=${u}`, {
15575
+ width: width - 2 - 1 - String(i).length,
15576
+ dim: true
15577
+ })
15578
+ ],
15579
+ width - 2
15580
+ ),
15581
+ 0,
15582
+ 0,
15583
+ 0,
15584
+ 2
15585
+ )
15586
+ );
15587
+ }
15588
+ const trail = text("", { width });
15589
+ return vstack(pill, ...items, trail);
14831
15590
  }
14832
- function accentRows(baseId, glyph, glyphColor, text, bodyColor, bodyDim, width) {
14833
- const indentCells = 1 + 1 + glyph.length + 2;
14834
- const inner = Math.max(8, width - indentCells);
14835
- const lines = wrapToWidth(text, inner);
14836
- return lines.map((line, i) => ({
14837
- kind: "row",
14838
- id: `${baseId}/${i}`,
14839
- content: i === 0 ? /* @__PURE__ */ React26.createElement(
14840
- AccentRow,
14841
- {
14842
- color: glyphColor,
14843
- prefix: /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(Text22, { color: glyphColor, bold: true }, glyph), /* @__PURE__ */ React26.createElement(Text22, null, " ")),
14844
- body: line,
14845
- bodyColor,
14846
- bodyDim
14847
- }
14848
- ) : /* @__PURE__ */ React26.createElement(
14849
- AccentRow,
14850
- {
14851
- color: glyphColor,
14852
- prefix: /* @__PURE__ */ React26.createElement(Text22, null, " ".repeat(glyph.length + 2)),
14853
- body: line,
14854
- bodyColor,
14855
- bodyDim
14856
- }
14857
- )
14858
- }));
15591
+ function planStateFrame(planState, width) {
15592
+ const fields = [];
15593
+ if (planState.subgoals.length)
15594
+ fields.push(["subgoals", planState.subgoals, COLOR.primary, false]);
15595
+ if (planState.hypotheses.length)
15596
+ fields.push(["hypotheses", planState.hypotheses, COLOR.assistant, false]);
15597
+ if (planState.uncertainties.length)
15598
+ fields.push(["uncertainties", planState.uncertainties, COLOR.warn, false]);
15599
+ if (planState.rejectedPaths.length)
15600
+ fields.push(["rejected", planState.rejectedPaths, COLOR.info, true]);
15601
+ if (fields.length === 0) return empty(width);
15602
+ const rows = fields.map(([label, items, color2, dim]) => {
15603
+ const header2 = `${label} (${items.length}) \xB7 `;
15604
+ const itemsStr = items.join(" \xB7 ");
15605
+ return rowFrame(
15606
+ [
15607
+ text(label, { width: label.length, fg: color2, bold: true, dim }),
15608
+ text(` (${items.length}) \xB7 `, { width: 7 + String(items.length).length, dim: true }),
15609
+ text(itemsStr, {
15610
+ width: Math.max(8, width - header2.length),
15611
+ fg: dim ? void 0 : COLOR.info,
15612
+ dim
15613
+ })
15614
+ ],
15615
+ width
15616
+ );
15617
+ });
15618
+ const trail = text("", { width });
15619
+ return vstack(...rows, trail);
14859
15620
  }
14860
- function assistantToRows(event, projectRoot, width = 80) {
14861
- const hasComplexSub = event.branch || event.reasoning || event.planState && Object.keys(event.planState).length > 0;
14862
- if (hasComplexSub) {
14863
- return [
14864
- {
14865
- kind: "block",
14866
- id: event.id,
14867
- rows: estimatedHeight(event),
14868
- content: /* @__PURE__ */ React26.createElement(EventRow, { event, projectRoot })
14869
- }
14870
- ];
15621
+ function ctxBreakdownFrame(data, width) {
15622
+ const total = data.systemTokens + data.toolsTokens + data.logTokens + data.inputTokens;
15623
+ const winPct = data.ctxMax > 0 ? Math.round(total / data.ctxMax * 100) : 0;
15624
+ const barWidth = 48;
15625
+ const cellOf = (n) => data.ctxMax > 0 ? Math.round(n / data.ctxMax * barWidth) : 0;
15626
+ const sysCells = cellOf(data.systemTokens);
15627
+ const toolsCells = cellOf(data.toolsTokens);
15628
+ const logCells = cellOf(data.logTokens);
15629
+ const inputCells = cellOf(data.inputTokens);
15630
+ const used = sysCells + toolsCells + logCells + inputCells;
15631
+ const freeCells = Math.max(0, barWidth - used);
15632
+ const sevColor = winPct >= 80 ? COLOR.err : winPct >= 60 ? COLOR.warn : COLOR.ok;
15633
+ const innerWidth = width - 2;
15634
+ const headerSegments = [
15635
+ text("\u25A3 context", { width: 9, fg: COLOR.brand, bold: true }),
15636
+ text(` ${formatTokensCompact2(total)} of ${formatTokensCompact2(data.ctxMax)}`, {
15637
+ width: 4 + formatTokensCompact2(total).length + formatTokensCompact2(data.ctxMax).length,
15638
+ dim: true
15639
+ }),
15640
+ text(" \xB7 ", { width: 5, dim: true }),
15641
+ text(`${winPct}%`, { width: 1 + String(winPct).length, fg: sevColor, bold: true })
15642
+ ];
15643
+ if (winPct >= 80) {
15644
+ headerSegments.push(text(" \xB7 /compact", { width: 13, fg: COLOR.err, bold: true }));
14871
15645
  }
14872
- const items = [];
14873
- items.push({
14874
- kind: "row",
14875
- id: `${event.id}/spacer-top`,
14876
- content: /* @__PURE__ */ React26.createElement(Text22, null, " ")
14877
- });
14878
- items.push({
14879
- kind: "row",
14880
- id: `${event.id}/head`,
14881
- content: /* @__PURE__ */ React26.createElement(Box24, null, /* @__PURE__ */ React26.createElement(Text22, { color: COLOR.assistant, bold: true }, "\u25C6"), event.stats ? /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(Text22, null, " "), /* @__PURE__ */ React26.createElement(Text22, { backgroundColor: COLOR.assistant, color: "black", bold: true }, ` ${event.stats.model.replace(/^deepseek-/, "")} `)) : null)
14882
- });
14883
- const body = event.text || "(empty body \u2014 likely tool-call only)";
14884
- const dim = !event.text;
14885
- items.push(...accentRows(event.id, "", COLOR.assistant, body, COLOR.assistant, dim, width));
14886
- if (event.repair) {
14887
- items.push({
14888
- kind: "row",
14889
- id: `${event.id}/repair`,
14890
- content: /* @__PURE__ */ React26.createElement(Box24, { paddingLeft: 2 }, /* @__PURE__ */ React26.createElement(Text22, { color: COLOR.accent }, event.repair))
14891
- });
15646
+ const header2 = rowFrame(headerSegments, innerWidth);
15647
+ const bar = rowFrame(
15648
+ [
15649
+ text("\u2588".repeat(sysCells), { width: sysCells, fg: COLOR.brand }),
15650
+ text("\u2588".repeat(toolsCells), { width: toolsCells, fg: COLOR.accent }),
15651
+ text("\u2588".repeat(logCells), { width: logCells, fg: COLOR.primary }),
15652
+ text("\u2588".repeat(inputCells), { width: inputCells, fg: COLOR.tool }),
15653
+ text("\u2591".repeat(freeCells), { width: freeCells, fg: COLOR.info, dim: true })
15654
+ ],
15655
+ innerWidth
15656
+ );
15657
+ const legend = rowFrame(
15658
+ [
15659
+ text("\u25A0", { width: 1, fg: COLOR.brand }),
15660
+ text(` system ${formatTokensCompact2(data.systemTokens)}`, {
15661
+ width: 8 + formatTokensCompact2(data.systemTokens).length,
15662
+ dim: true
15663
+ }),
15664
+ text(" ", { width: 3 }),
15665
+ text("\u25A0", { width: 1, fg: COLOR.accent }),
15666
+ text(` tools ${formatTokensCompact2(data.toolsTokens)}`, {
15667
+ width: 7 + formatTokensCompact2(data.toolsTokens).length,
15668
+ dim: true
15669
+ }),
15670
+ text(" ", { width: 3 }),
15671
+ text("\u25A0", { width: 1, fg: COLOR.primary }),
15672
+ text(` log ${formatTokensCompact2(data.logTokens)}`, {
15673
+ width: 5 + formatTokensCompact2(data.logTokens).length,
15674
+ dim: true
15675
+ }),
15676
+ text(" ", { width: 3 }),
15677
+ text("\u25A0", { width: 1, fg: COLOR.tool }),
15678
+ text(` input ${formatTokensCompact2(data.inputTokens)}`, {
15679
+ width: 7 + formatTokensCompact2(data.inputTokens).length,
15680
+ dim: true
15681
+ })
15682
+ ],
15683
+ innerWidth
15684
+ );
15685
+ const inner = vstack(header2, bar, legend);
15686
+ const spacer = text("", { width });
15687
+ return vstack(spacer, borderLeft(pad(inner, 0, 0, 0, 1), COLOR.brand), spacer);
15688
+ }
15689
+ function complexAssistantFrame(event, width) {
15690
+ const spacer = text("", { width });
15691
+ const headerSegs = [text("\u25C6", { width: 1, fg: COLOR.assistant, bold: true })];
15692
+ if (event.stats) {
15693
+ const modelName = event.stats.model.replace(/^deepseek-/, "");
15694
+ headerSegs.push(
15695
+ text(" ", { width: 2 }),
15696
+ text(` ${modelName} `, {
15697
+ width: 2 + modelName.length,
15698
+ bg: COLOR.assistant,
15699
+ fg: "black",
15700
+ bold: true
15701
+ })
15702
+ );
15703
+ }
15704
+ const header2 = rowFrame(headerSegs, width);
15705
+ const bodyParts = [];
15706
+ const bodyWidth = width - 2;
15707
+ if (event.branch) {
15708
+ bodyParts.push(branchFrame(event.branch, bodyWidth));
15709
+ }
15710
+ if (event.reasoning) {
15711
+ bodyParts.push(reasoningFrame(event.reasoning, bodyWidth));
15712
+ }
15713
+ if (event.planState && !isPlanStateEmpty(event.planState)) {
15714
+ bodyParts.push(planStateFrame(event.planState, bodyWidth));
14892
15715
  }
15716
+ bodyParts.push(
15717
+ event.text ? markdownToFrame(event.text, bodyWidth) : text("(empty body \u2014 likely tool-call only)", {
15718
+ width: bodyWidth,
15719
+ fg: COLOR.assistant,
15720
+ dim: true
15721
+ })
15722
+ );
14893
15723
  if (event.stats) {
14894
15724
  const hit = (event.stats.cacheHitRatio * 100).toFixed(1);
14895
15725
  const hitColor = event.stats.cacheHitRatio >= 0.7 ? "#4ade80" : event.stats.cacheHitRatio >= 0.4 ? "#fcd34d" : "#f87171";
14896
- items.push({
14897
- kind: "row",
14898
- id: `${event.id}/stats`,
14899
- content: /* @__PURE__ */ React26.createElement(Box24, { paddingLeft: 2 }, /* @__PURE__ */ React26.createElement(Text22, { color: hitColor, bold: true }, `\u232C ${hit}%`), /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React26.createElement(Text22, { color: "#94a3b8" }, "in "), /* @__PURE__ */ React26.createElement(Text22, { color: "#67e8f9", bold: true }, event.stats.usage.promptTokens), /* @__PURE__ */ React26.createElement(Text22, { color: "#94a3b8" }, " \u2192 out "), /* @__PURE__ */ React26.createElement(Text22, { color: "#c4b5fd", bold: true }, event.stats.usage.completionTokens), /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React26.createElement(Text22, { color: "#86efac", bold: true }, `$${event.stats.cost.toFixed(6)}`))
14900
- });
15726
+ const statsLine = `\u232C ${hit}% \xB7 in ${event.stats.usage.promptTokens} \u2192 out ${event.stats.usage.completionTokens} \xB7 $${event.stats.cost.toFixed(6)}`;
15727
+ bodyParts.push(text(statsLine, { width: bodyWidth, fg: hitColor }));
14901
15728
  }
14902
- return items;
15729
+ if (event.repair) {
15730
+ bodyParts.push(text(event.repair, { width: bodyWidth, fg: COLOR.accent }));
15731
+ }
15732
+ const inner = vstack(...bodyParts);
15733
+ const bordered = borderLeft(pad(inner, 0, 0, 0, 1), COLOR.assistant);
15734
+ return vstack(spacer, header2, spacer, bordered);
15735
+ }
15736
+ function planFrame(event, width) {
15737
+ const header2 = text("\u{1F4CB} plan proposed \u2014 pick a choice below", {
15738
+ width: 39,
15739
+ fg: "cyan",
15740
+ bold: true
15741
+ });
15742
+ const headerPadded = rowFrame([header2], width);
15743
+ const body = markdownToFrame(event.text, width - 2);
15744
+ const inner = vstack(headerPadded, text("", { width }), pad(body, 0, 0, 0, 1));
15745
+ const spacer = text("", { width });
15746
+ return vstack(spacer, inner, spacer);
14903
15747
  }
14904
- function eventToItems(event, projectRoot, width = 80) {
15748
+ function eventToAtom(event, projectRoot, width) {
14905
15749
  if (event.role === "info") {
14906
- const { lead, color: color2, body } = detectInfoTone(event.text);
14907
- return accentRows(event.id, lead, color2, body, void 0, true, width);
15750
+ return { kind: "frame", id: event.id, frame: infoFrame(event, width) };
14908
15751
  }
14909
15752
  if (event.role === "warning") {
14910
- return accentRows(event.id, "\u25B2 warn", COLOR.warn, event.text, COLOR.warn, false, width);
15753
+ return { kind: "frame", id: event.id, frame: warningFrame(event, width) };
14911
15754
  }
14912
15755
  if (event.role === "error") {
14913
- return accentRows(event.id, "\u2726 error", COLOR.err, event.text, COLOR.err, false, width);
14914
- }
14915
- if (event.role === "assistant" && !event.streaming) {
14916
- return assistantToRows(event, projectRoot, width);
15756
+ return { kind: "frame", id: event.id, frame: errorFrame(event, width) };
14917
15757
  }
14918
15758
  if (event.role === "step-progress") {
14919
- const sp = event.stepProgress;
14920
- const counter = sp && sp.total > 0 ? `${sp.completed}/${sp.total}` : "";
14921
- const label = sp?.title ? `${sp.stepId} \xB7 ${sp.title}` : sp?.stepId ?? "";
14922
- const rows = [];
14923
- rows.push({
14924
- kind: "row",
14925
- id: `${event.id}/spacer`,
14926
- content: /* @__PURE__ */ React26.createElement(Text22, null, " ")
14927
- });
14928
- rows.push({
14929
- kind: "row",
14930
- id: `${event.id}/head`,
14931
- content: /* @__PURE__ */ React26.createElement(Box24, null, /* @__PURE__ */ React26.createElement(Text22, { backgroundColor: "#4ade80", color: "black", bold: true }, " \u2713 STEP "), counter ? /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(Text22, null, " "), /* @__PURE__ */ React26.createElement(Text22, { color: "#4ade80", bold: true }, counter)) : null, /* @__PURE__ */ React26.createElement(Text22, null, " "), /* @__PURE__ */ React26.createElement(Text22, { color: "#86efac" }, label))
14932
- });
14933
- if (event.text) {
14934
- for (const [i, line] of event.text.split("\n").entries()) {
14935
- rows.push({
14936
- kind: "row",
14937
- id: `${event.id}/body/${i}`,
14938
- content: /* @__PURE__ */ React26.createElement(Box24, { paddingLeft: 2 }, /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, line))
14939
- });
14940
- }
15759
+ return { kind: "frame", id: event.id, frame: stepProgressFrame(event, width) };
15760
+ }
15761
+ if (event.role === "user") {
15762
+ return { kind: "frame", id: event.id, frame: userFrame(event, width) };
15763
+ }
15764
+ if (event.role === "tool") {
15765
+ const isExplicitError = event.text.startsWith("ERROR:");
15766
+ const isEditFile = (event.toolName === "edit_file" || event.toolName?.endsWith("_edit_file")) && !isExplicitError;
15767
+ if (isEditFile) {
15768
+ return { kind: "frame", id: event.id, frame: editFileDiffFrame(event, width) };
14941
15769
  }
14942
- if (sp?.notes) {
14943
- rows.push({
14944
- kind: "row",
14945
- id: `${event.id}/notes`,
14946
- content: /* @__PURE__ */ React26.createElement(Box24, { paddingLeft: 2 }, /* @__PURE__ */ React26.createElement(Text22, { color: "#fbbf24", dimColor: true }, `note: ${sp.notes}`))
14947
- });
15770
+ return { kind: "frame", id: event.id, frame: toolCompactFrame(event, width) };
15771
+ }
15772
+ if (event.role === "assistant" && !event.streaming) {
15773
+ const hasComplexSub = event.branch || event.reasoning || event.planState && !isPlanStateEmpty(event.planState);
15774
+ if (hasComplexSub) {
15775
+ return { kind: "frame", id: event.id, frame: complexAssistantFrame(event, width) };
14948
15776
  }
14949
- return rows;
15777
+ return { kind: "frame", id: event.id, frame: simpleAssistantFrame(event, width) };
14950
15778
  }
14951
- return [
14952
- {
14953
- kind: "block",
15779
+ if (event.role === "plan") {
15780
+ return { kind: "frame", id: event.id, frame: planFrame(event, width) };
15781
+ }
15782
+ if (event.role === "ctx-breakdown" && event.ctxBreakdown) {
15783
+ return {
15784
+ kind: "frame",
14954
15785
  id: event.id,
14955
- rows: estimatedHeight(event),
14956
- content: /* @__PURE__ */ React26.createElement(EventRow, { event, projectRoot })
14957
- }
14958
- ];
15786
+ frame: ctxBreakdownFrame(event.ctxBreakdown, width)
15787
+ };
15788
+ }
15789
+ return {
15790
+ kind: "ink",
15791
+ id: event.id,
15792
+ rows: estimatedHeight(event),
15793
+ element: /* @__PURE__ */ React26.createElement(EventRow, { event, projectRoot })
15794
+ };
14959
15795
  }
14960
15796
  function estimatedHeight(e) {
14961
- const text = e.text ?? "";
14962
- const wrapLines = Math.max(0, Math.floor(text.length / 80));
15797
+ const t2 = e.text ?? "";
15798
+ const wrapLines = Math.max(0, Math.floor(t2.length / 80));
14963
15799
  if (e.role === "user") return 3 + wrapLines;
14964
15800
  if (e.role === "assistant") {
14965
15801
  let h = 4 + wrapLines;
@@ -14970,7 +15806,7 @@ function estimatedHeight(e) {
14970
15806
  if (e.role === "tool") {
14971
15807
  const isEditFile = e.toolName === "edit_file" || e.toolName?.endsWith("_edit_file");
14972
15808
  if (isEditFile) {
14973
- const diffLines = (text.match(/\n/g)?.length ?? 0) + 1;
15809
+ const diffLines = (t2.match(/\n/g)?.length ?? 0) + 1;
14974
15810
  return 6 + Math.min(20, diffLines);
14975
15811
  }
14976
15812
  return 2;
@@ -14979,69 +15815,91 @@ function estimatedHeight(e) {
14979
15815
  if (e.role === "ctx-breakdown") return 7;
14980
15816
  return 2;
14981
15817
  }
14982
- function sliceLogItems(items, available, scrollOffsetRows) {
14983
- if (items.length === 0) {
14984
- return { items: [], maxScrollRows: 0, totalRows: 0 };
15818
+ function viewportLog(atoms, scrollOffset, available) {
15819
+ if (atoms.length === 0 || available <= 0) {
15820
+ return { atoms: [], topSkip: 0, bottomSkip: 0, totalRows: 0, maxScrollRows: 0 };
14985
15821
  }
14986
- const heights = items.map(itemRows);
15822
+ const heights = atoms.map(atomRows);
14987
15823
  const totalRows = heights.reduce((a, b) => a + b, 0);
14988
15824
  const maxScrollRows = Math.max(0, totalRows - available);
14989
- const offset = Math.max(0, Math.min(scrollOffsetRows, maxScrollRows));
15825
+ const offset = Math.max(0, Math.min(scrollOffset, maxScrollRows));
14990
15826
  const viewportBottom = totalRows - offset;
14991
15827
  const viewportTop = Math.max(0, viewportBottom - available);
14992
15828
  let cursor = 0;
14993
15829
  let firstIdx = -1;
15830
+ let firstStart = 0;
14994
15831
  let lastIdx = -1;
14995
- for (let i = 0; i < items.length; i++) {
14996
- const eStart = cursor;
14997
- const eEnd = cursor + heights[i];
14998
- cursor = eEnd;
14999
- if (eEnd <= viewportTop) continue;
15000
- if (eStart >= viewportBottom) break;
15001
- if (firstIdx === -1) firstIdx = i;
15832
+ let lastEnd = 0;
15833
+ for (let i = 0; i < atoms.length; i++) {
15834
+ const start = cursor;
15835
+ const end = cursor + heights[i];
15836
+ cursor = end;
15837
+ if (end <= viewportTop) continue;
15838
+ if (start >= viewportBottom) break;
15839
+ if (firstIdx === -1) {
15840
+ firstIdx = i;
15841
+ firstStart = start;
15842
+ }
15002
15843
  lastIdx = i;
15844
+ lastEnd = end;
15003
15845
  }
15004
15846
  if (firstIdx === -1) {
15005
- return { items: [items[items.length - 1]], maxScrollRows, totalRows };
15847
+ return {
15848
+ atoms: [atoms[atoms.length - 1]],
15849
+ topSkip: 0,
15850
+ bottomSkip: 0,
15851
+ totalRows,
15852
+ maxScrollRows
15853
+ };
15006
15854
  }
15007
- return {
15008
- items: items.slice(firstIdx, lastIdx + 1),
15009
- maxScrollRows,
15010
- totalRows
15011
- };
15012
- }
15013
- function renderLogItem(item) {
15014
- if (item.kind === "row") {
15015
- return /* @__PURE__ */ React26.createElement(Box24, { key: item.id, height: 1, flexShrink: 0 }, item.content);
15855
+ const sliced = atoms.slice(firstIdx, lastIdx + 1);
15856
+ const firstAtom = sliced[0];
15857
+ const lastAtom = sliced[sliced.length - 1];
15858
+ let topSkip = 0;
15859
+ let bottomSkip = 0;
15860
+ if (firstAtom.kind === "frame") {
15861
+ topSkip = Math.max(0, viewportTop - firstStart);
15016
15862
  }
15017
- return /* @__PURE__ */ React26.createElement(Box24, { key: item.id, flexShrink: 0 }, item.content);
15863
+ if (lastAtom.kind === "frame") {
15864
+ bottomSkip = Math.max(0, lastEnd - viewportBottom);
15865
+ }
15866
+ return { atoms: sliced, topSkip, bottomSkip, totalRows, maxScrollRows };
15867
+ }
15868
+ function renderViewport(v) {
15869
+ return /* @__PURE__ */ React26.createElement(React26.Fragment, null, v.atoms.map((atom, i) => {
15870
+ if (atom.kind === "ink") {
15871
+ return /* @__PURE__ */ React26.createElement(React26.Fragment, { key: atom.id }, atom.element);
15872
+ }
15873
+ const start = i === 0 ? v.topSkip : 0;
15874
+ const end = i === v.atoms.length - 1 ? atom.frame.rows.length - v.bottomSkip : atom.frame.rows.length;
15875
+ const rows = atom.frame.rows.slice(start, end);
15876
+ return /* @__PURE__ */ React26.createElement(React26.Fragment, { key: atom.id }, rows.map((row2, ri) => /* @__PURE__ */ React26.createElement(Box24, { key: `${atom.id}/${start + ri}`, height: 1, flexShrink: 0 }, /* @__PURE__ */ React26.createElement(Text22, null, frameToAnsi({ width: atom.frame.width, rows: [row2] })))));
15877
+ }));
15018
15878
  }
15019
- function ScrollBar({
15020
- height,
15879
+ function eventsToAtoms(events, projectRoot, width) {
15880
+ const out = [];
15881
+ for (const e of events) out.push(eventToAtom(e, projectRoot, width));
15882
+ return out;
15883
+ }
15884
+
15885
+ // src/cli/ui/log-rows.tsx
15886
+ import { Box as Box25, Text as Text23 } from "ink";
15887
+ import React27 from "react";
15888
+ function BottomHint({
15889
+ rowsBelow,
15021
15890
  totalRows,
15022
- viewportRows,
15023
- scrollOffsetRows
15891
+ viewportRows
15024
15892
  }) {
15025
- if (totalRows <= viewportRows || height <= 0) return null;
15026
- const maxScroll = Math.max(0, totalRows - viewportRows);
15027
- const offset = Math.max(0, Math.min(scrollOffsetRows, maxScroll));
15028
- const viewportBottomFrac = (totalRows - offset) / totalRows;
15029
- const viewportTopFrac = Math.max(0, viewportBottomFrac - viewportRows / totalRows);
15030
- const thumbStart = Math.floor(viewportTopFrac * height);
15031
- const thumbEnd = Math.min(height, Math.ceil(viewportBottomFrac * height));
15032
- const thumbSize = Math.max(1, thumbEnd - thumbStart);
15033
- const cells = [];
15034
- for (let i = 0; i < height; i++) {
15035
- const inThumb = i >= thumbStart && i < thumbStart + thumbSize;
15036
- cells.push(
15037
- /* @__PURE__ */ React26.createElement(Text22, { key: `sb-${i}`, color: inThumb ? COLOR.brand : COLOR.info, dimColor: !inThumb }, inThumb ? "\u2588" : "\u2502")
15038
- );
15039
- }
15040
- return /* @__PURE__ */ React26.createElement(Box24, { flexDirection: "column", width: 1, flexShrink: 0 }, cells);
15041
- }
15042
- function BottomHint({ rowsBelow }) {
15043
15893
  if (rowsBelow <= 0) return null;
15044
- return /* @__PURE__ */ React26.createElement(Box24, { height: 1, flexShrink: 0 }, /* @__PURE__ */ React26.createElement(Text22, { color: COLOR.primary, bold: true }, "\u2193"), /* @__PURE__ */ React26.createElement(Text22, null, " "), /* @__PURE__ */ React26.createElement(Text22, { color: COLOR.primary }, `${rowsBelow} row${rowsBelow === 1 ? "" : "s"} below`), /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, " \xB7 End to jump \xB7 wheel-down to scroll"));
15894
+ const maxScroll = Math.max(1, totalRows - viewportRows);
15895
+ const ratioFromTop = Math.max(0, Math.min(1, (totalRows - rowsBelow - viewportRows) / maxScroll));
15896
+ const pct2 = Math.round((1 - ratioFromTop) * 100);
15897
+ const rowsAbove = Math.max(0, totalRows - viewportRows - rowsBelow);
15898
+ const barCells = 16;
15899
+ const markerAt = Math.max(0, Math.min(barCells - 1, Math.round(ratioFromTop * (barCells - 1))));
15900
+ const left = "\u2500".repeat(markerAt);
15901
+ const right = "\u2500".repeat(barCells - 1 - markerAt);
15902
+ return /* @__PURE__ */ React27.createElement(Box25, { height: 1, flexShrink: 0 }, /* @__PURE__ */ React27.createElement(Text23, { color: COLOR.primary, bold: true }, `\u2191 ${rowsAbove}`), /* @__PURE__ */ React27.createElement(Text23, null, " "), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, "\u2595"), /* @__PURE__ */ React27.createElement(Text23, { color: COLOR.info, dimColor: true }, left), /* @__PURE__ */ React27.createElement(Text23, { color: COLOR.brand, bold: true }, "\u25CF"), /* @__PURE__ */ React27.createElement(Text23, { color: COLOR.info, dimColor: true }, right), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, "\u258F"), /* @__PURE__ */ React27.createElement(Text23, null, " "), /* @__PURE__ */ React27.createElement(Text23, { color: COLOR.primary, bold: true }, `${pct2}%`), /* @__PURE__ */ React27.createElement(Text23, null, " "), /* @__PURE__ */ React27.createElement(Text23, { color: COLOR.primary }, `\u2193 ${rowsBelow}`), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, " \xB7 End to jump \xB7 wheel to scroll"));
15045
15903
  }
15046
15904
 
15047
15905
  // src/cli/ui/loop.ts
@@ -15219,8 +16077,8 @@ ${formatOneResourceContent(block.resource)}`;
15219
16077
  }
15220
16078
  async function handleMcpBrowseSlash(kind, arg, servers, setHistorical) {
15221
16079
  const ts = Date.now();
15222
- const push = (role, text) => {
15223
- setHistorical((prev) => [...prev, { id: `mcp-${role}-${ts}-${prev.length}`, role, text }]);
16080
+ const push = (role, text2) => {
16081
+ setHistorical((prev) => [...prev, { id: `mcp-${role}-${ts}-${prev.length}`, role, text: text2 }]);
15224
16082
  };
15225
16083
  if (!arg) {
15226
16084
  push("info", kind === "resource" ? formatResourceList(servers) : formatPromptList(servers));
@@ -15624,9 +16482,9 @@ function detectSlashArgContext(input, codeMode = false) {
15624
16482
  kind: spec.argCompleter ? "picker" : "hint"
15625
16483
  };
15626
16484
  }
15627
- function parseSlash(text) {
15628
- if (!text.startsWith("/")) return null;
15629
- const parts = text.slice(1).trim().split(/\s+/);
16485
+ function parseSlash(text2) {
16486
+ if (!text2.startsWith("/")) return null;
16487
+ const parts = text2.slice(1).trim().split(/\s+/);
15630
16488
  const cmd = parts[0]?.toLowerCase() ?? "";
15631
16489
  if (!cmd) return null;
15632
16490
  return { cmd, args: parts.slice(1) };
@@ -15725,7 +16583,7 @@ function renderSubagentSection(sub) {
15725
16583
  for (const s of top) {
15726
16584
  const sec = (s.durationMs / 1e3).toFixed(1);
15727
16585
  lines.push(
15728
- ` ${pad(s.skillName, 18)} ${pad(`${s.count}`, 4, "right")} $${s.costUsd.toFixed(6)} ${sec}s`
16586
+ ` ${pad2(s.skillName, 18)} ${pad2(`${s.count}`, 4, "right")} $${s.costUsd.toFixed(6)} ${sec}s`
15729
16587
  );
15730
16588
  }
15731
16589
  if (sub.bySkill.length > top.length) {
@@ -15735,13 +16593,13 @@ function renderSubagentSection(sub) {
15735
16593
  }
15736
16594
  function header() {
15737
16595
  return [
15738
- pad("", 10),
15739
- pad("turns", 8, "right"),
15740
- pad("cache hit", 10, "right"),
15741
- pad("cost (USD)", 14, "right"),
15742
- pad("cache saved", 14, "right"),
15743
- pad("vs Claude", 14, "right"),
15744
- pad("saved", 10, "right")
16596
+ pad2("", 10),
16597
+ pad2("turns", 8, "right"),
16598
+ pad2("cache hit", 10, "right"),
16599
+ pad2("cost (USD)", 14, "right"),
16600
+ pad2("cache saved", 14, "right"),
16601
+ pad2("vs Claude", 14, "right"),
16602
+ pad2("saved", 10, "right")
15745
16603
  ].join(" ");
15746
16604
  }
15747
16605
  function divider() {
@@ -15751,20 +16609,20 @@ function bucketRow(b) {
15751
16609
  const hit = bucketCacheHitRatio(b);
15752
16610
  const savings = bucketSavingsFraction(b);
15753
16611
  return [
15754
- pad(b.label, 10),
15755
- pad(b.turns.toString(), 8, "right"),
15756
- pad(b.turns > 0 ? `${(hit * 100).toFixed(1)}%` : "\u2014", 10, "right"),
15757
- pad(b.turns > 0 ? `$${b.costUsd.toFixed(6)}` : "\u2014", 14, "right"),
15758
- pad(
16612
+ pad2(b.label, 10),
16613
+ pad2(b.turns.toString(), 8, "right"),
16614
+ pad2(b.turns > 0 ? `${(hit * 100).toFixed(1)}%` : "\u2014", 10, "right"),
16615
+ pad2(b.turns > 0 ? `$${b.costUsd.toFixed(6)}` : "\u2014", 14, "right"),
16616
+ pad2(
15759
16617
  b.turns > 0 && b.cacheSavingsUsd > 0 ? `$${b.cacheSavingsUsd.toFixed(4)}` : "\u2014",
15760
16618
  14,
15761
16619
  "right"
15762
16620
  ),
15763
- pad(b.turns > 0 ? `$${b.claudeEquivUsd.toFixed(4)}` : "\u2014", 14, "right"),
15764
- pad(b.turns > 0 && savings > 0 ? `${(savings * 100).toFixed(1)}%` : "\u2014", 10, "right")
16621
+ pad2(b.turns > 0 ? `$${b.claudeEquivUsd.toFixed(4)}` : "\u2014", 14, "right"),
16622
+ pad2(b.turns > 0 && savings > 0 ? `${(savings * 100).toFixed(1)}%` : "\u2014", 10, "right")
15765
16623
  ].join(" ");
15766
16624
  }
15767
- function pad(s, width, align = "left") {
16625
+ function pad2(s, width, align = "left") {
15768
16626
  if (s.length >= width) return s;
15769
16627
  const fill = " ".repeat(width - s.length);
15770
16628
  return align === "right" ? `${fill}${s}` : `${s}${fill}`;
@@ -18557,13 +19415,13 @@ var PLAIN_UI = process.env.REASONIX_UI === "plain";
18557
19415
  function LoopStatusRow({
18558
19416
  loop: loop2
18559
19417
  }) {
18560
- const [, setTick] = React27.useState(0);
18561
- React27.useEffect(() => {
19418
+ const [, setTick] = React28.useState(0);
19419
+ React28.useEffect(() => {
18562
19420
  const id = setInterval(() => setTick((t2) => t2 + 1), 1e3);
18563
19421
  return () => clearInterval(id);
18564
19422
  }, []);
18565
19423
  const nextFireMs = Math.max(0, loop2.nextFireAt - Date.now());
18566
- return /* @__PURE__ */ React27.createElement(Box25, null, /* @__PURE__ */ React27.createElement(Text23, { color: "cyan" }, `\u25B8 ${formatLoopStatus(loop2.prompt, nextFireMs, loop2.iter)} \xB7 /loop stop or type to cancel`));
19424
+ return /* @__PURE__ */ React28.createElement(Box26, null, /* @__PURE__ */ React28.createElement(Text24, { color: "cyan" }, `\u25B8 ${formatLoopStatus(loop2.prompt, nextFireMs, loop2.iter)} \xB7 /loop stop or type to cancel`));
18567
19425
  }
18568
19426
  function App({
18569
19427
  model: model2,
@@ -18629,10 +19487,8 @@ function App({
18629
19487
  if (curLen > prevLen && scrollTargetRef.current > 0) {
18630
19488
  const cols = stdout4?.columns ?? 80;
18631
19489
  let deltaRows = 0;
18632
- for (let i = prevLen; i < curLen; i++) {
18633
- for (const it of eventToItems(historical[i], void 0, cols)) {
18634
- deltaRows += it.kind === "row" ? 1 : it.rows;
18635
- }
19490
+ for (const a of eventsToAtoms(historical.slice(prevLen, curLen), void 0, cols)) {
19491
+ deltaRows += a.kind === "frame" ? a.frame.rows.length : a.rows;
18636
19492
  }
18637
19493
  if (deltaRows > 0) {
18638
19494
  scrollTargetRef.current += deltaRows;
@@ -18721,6 +19577,10 @@ function App({
18721
19577
  setPendingTick((t2) => t2 + 1);
18722
19578
  }, []);
18723
19579
  const [editMode, setEditMode] = useState10(() => codeMode ? loadEditMode() : "review");
19580
+ const [preset2, setPreset] = useState10(() => {
19581
+ if (model2 === "deepseek-v4-pro") return "pro";
19582
+ return "auto";
19583
+ });
18724
19584
  const editModeRef = useRef6(editMode);
18725
19585
  useEffect7(() => {
18726
19586
  editModeRef.current = editMode;
@@ -19558,6 +20418,8 @@ function App({
19558
20418
  autoEscalate: settings.autoEscalate,
19559
20419
  reasoningEffort: settings.reasoningEffort
19560
20420
  });
20421
+ const canonical = settings.model === "deepseek-v4-pro" ? "pro" : settings.autoEscalate ? "auto" : "flash";
20422
+ setPreset(canonical);
19561
20423
  },
19562
20424
  applyEffortLive: (effort2) => {
19563
20425
  loop2.configure({ reasoningEffort: effort2 });
@@ -19589,13 +20451,13 @@ function App({
19589
20451
  eventSubscribersRef.current.delete(handler);
19590
20452
  };
19591
20453
  },
19592
- submitPrompt: (text) => {
20454
+ submitPrompt: (text2) => {
19593
20455
  if (busyRef.current) {
19594
20456
  return { accepted: false, reason: "loop is busy with a turn" };
19595
20457
  }
19596
20458
  const fn = handleSubmitRef.current;
19597
20459
  if (!fn) return { accepted: false, reason: "TUI not ready" };
19598
- fn(text).catch(() => void 0);
20460
+ fn(text2).catch(() => void 0);
19599
20461
  return { accepted: true };
19600
20462
  },
19601
20463
  abortTurn: () => {
@@ -19696,13 +20558,13 @@ function App({
19696
20558
  const fn = handleChoiceConfirmRef.current;
19697
20559
  if (fn) fn(choice).catch(() => void 0);
19698
20560
  },
19699
- resolvePlanConfirm: (choice, text) => {
20561
+ resolvePlanConfirm: (choice, text2) => {
19700
20562
  if (choice === "cancel") {
19701
20563
  handlePlanConfirmRef.current("cancel").catch(() => void 0);
19702
20564
  return;
19703
20565
  }
19704
20566
  const plan2 = pendingPlanRef.current ?? "";
19705
- handleStagedInputSubmitRef.current(text ?? "", { plan: plan2, mode: choice }).catch(() => void 0);
20567
+ handleStagedInputSubmitRef.current(text2 ?? "", { plan: plan2, mode: choice }).catch(() => void 0);
19706
20568
  },
19707
20569
  resolveEditReview: (choice) => {
19708
20570
  const resolve15 = editReviewResolveRef.current;
@@ -19715,12 +20577,12 @@ function App({
19715
20577
  resolveWorkspaceConfirm: (choice) => {
19716
20578
  handleWorkspaceConfirmRef.current(choice).catch(() => void 0);
19717
20579
  },
19718
- resolveCheckpointConfirm: (choice, text) => {
19719
- if (choice === "revise" && typeof text === "string") {
20580
+ resolveCheckpointConfirm: (choice, text2) => {
20581
+ if (choice === "revise" && typeof text2 === "string") {
19720
20582
  const snap = pendingCheckpoint;
19721
20583
  setPendingCheckpoint(null);
19722
20584
  if (!snap) return;
19723
- handleCheckpointReviseSubmitRef.current(text, snap).catch(() => void 0);
20585
+ handleCheckpointReviseSubmitRef.current(text2, snap).catch(() => void 0);
19724
20586
  return;
19725
20587
  }
19726
20588
  handleCheckpointConfirmRef.current(choice).catch(() => void 0);
@@ -19849,8 +20711,8 @@ function App({
19849
20711
  }, []);
19850
20712
  const handleSubmit2 = useCallback4(
19851
20713
  async (raw) => {
19852
- let text = raw.trim();
19853
- if (!text) return;
20714
+ let text2 = raw.trim();
20715
+ if (!text2) return;
19854
20716
  if (activeLoopRef.current && !loopFiringRef.current) {
19855
20717
  stopLoop();
19856
20718
  }
@@ -19870,28 +20732,28 @@ function App({
19870
20732
  return;
19871
20733
  }
19872
20734
  }
19873
- if (text.startsWith("/") && !text.includes(" ")) {
19874
- const typed = text.slice(1).toLowerCase();
20735
+ if (text2.startsWith("/") && !text2.includes(" ")) {
20736
+ const typed = text2.slice(1).toLowerCase();
19875
20737
  const matches = suggestSlashCommands(typed, !!codeMode);
19876
20738
  const exact = matches.find((m) => m.cmd === typed);
19877
20739
  if (!exact && matches.length > 0) {
19878
20740
  const chosen = matches[slashSelected] ?? matches[0];
19879
- if (chosen) text = `/${chosen.cmd}`;
20741
+ if (chosen) text2 = `/${chosen.cmd}`;
19880
20742
  }
19881
20743
  }
19882
20744
  setInput("");
19883
20745
  historyCursor.current = -1;
19884
- if (codeMode && pendingEdits.current.length > 0 && (text === "y" || text === "n")) {
19885
- const out = text === "y" ? codeApply() : codeDiscard();
20746
+ if (codeMode && pendingEdits.current.length > 0 && (text2 === "y" || text2 === "n")) {
20747
+ const out = text2 === "y" ? codeApply() : codeDiscard();
19886
20748
  setHistorical((prev) => [...prev, { id: `sys-${Date.now()}`, role: "info", text: out }]);
19887
- promptHistory.current.push(text);
20749
+ promptHistory.current.push(text2);
19888
20750
  return;
19889
20751
  }
19890
- const hashParse = detectHashMemory(text);
20752
+ const hashParse = detectHashMemory(text2);
19891
20753
  if (hashParse?.kind === "memory" || hashParse?.kind === "memory-global") {
19892
20754
  const isGlobal = hashParse.kind === "memory-global";
19893
20755
  const memRoot = currentRootDir;
19894
- promptHistory.current.push(text);
20756
+ promptHistory.current.push(text2);
19895
20757
  try {
19896
20758
  const result = isGlobal ? appendGlobalMemory(hashParse.note) : appendProjectMemory(memRoot, hashParse.note);
19897
20759
  const verb = result.created ? "created" : "appended to";
@@ -19917,18 +20779,18 @@ function App({
19917
20779
  return;
19918
20780
  }
19919
20781
  if (hashParse?.kind === "escape") {
19920
- text = hashParse.text;
20782
+ text2 = hashParse.text;
19921
20783
  }
19922
- const bangCmd = detectBangCommand(text);
20784
+ const bangCmd = detectBangCommand(text2);
19923
20785
  if (bangCmd !== null) {
19924
20786
  const bangRoot = currentRootDir;
19925
- promptHistory.current.push(text);
20787
+ promptHistory.current.push(text2);
19926
20788
  setHistorical((prev) => [
19927
20789
  ...prev,
19928
20790
  {
19929
20791
  id: `bang-u-${Date.now()}`,
19930
20792
  role: "user",
19931
- text,
20793
+ text: text2,
19932
20794
  leadSeparator: prev.length > 0
19933
20795
  }
19934
20796
  ]);
@@ -19962,19 +20824,19 @@ function App({
19962
20824
  }
19963
20825
  return;
19964
20826
  }
19965
- const mcpBrowseMatch = /^\/(resource|prompt)(?:\s+([\s\S]*))?$/.exec(text);
20827
+ const mcpBrowseMatch = /^\/(resource|prompt)(?:\s+([\s\S]*))?$/.exec(text2);
19966
20828
  if (mcpBrowseMatch) {
19967
20829
  const kind = mcpBrowseMatch[1];
19968
20830
  const arg = mcpBrowseMatch[2]?.trim() ?? "";
19969
- promptHistory.current.push(text);
20831
+ promptHistory.current.push(text2);
19970
20832
  setHistorical((prev) => [
19971
20833
  ...prev,
19972
- { id: `mcp-u-${Date.now()}`, role: "user", text, leadSeparator: prev.length > 0 }
20834
+ { id: `mcp-u-${Date.now()}`, role: "user", text: text2, leadSeparator: prev.length > 0 }
19973
20835
  ]);
19974
20836
  await handleMcpBrowseSlash(kind, arg, mcpServers ?? [], setHistorical);
19975
20837
  return;
19976
20838
  }
19977
- const slash = parseSlash(text);
20839
+ const slash = parseSlash(text2);
19978
20840
  if (slash) {
19979
20841
  const result = handleSlash(slash.cmd, slash.args, loop2, {
19980
20842
  mcpSpecs,
@@ -20014,9 +20876,9 @@ function App({
20014
20876
  stopDashboard,
20015
20877
  getDashboardUrl,
20016
20878
  jobs: codeMode?.jobs,
20017
- postInfo: (text2) => setHistorical((prev) => [
20879
+ postInfo: (text3) => setHistorical((prev) => [
20018
20880
  ...prev,
20019
- { id: `sys-late-${Date.now()}-${Math.random()}`, role: "info", text: text2 }
20881
+ { id: `sys-late-${Date.now()}-${Math.random()}`, role: "info", text: text3 }
20020
20882
  ]),
20021
20883
  reloadHooks: () => {
20022
20884
  const fresh = loadHooks({ projectRoot: codeMode ? currentRootDir : void 0 });
@@ -20106,16 +20968,16 @@ function App({
20106
20968
  ]);
20107
20969
  }
20108
20970
  if (result.resubmit) {
20109
- text = result.resubmit;
20971
+ text2 = result.resubmit;
20110
20972
  } else {
20111
- promptHistory.current.push(text);
20973
+ promptHistory.current.push(text2);
20112
20974
  return;
20113
20975
  }
20114
20976
  }
20115
20977
  if (hookList.some((h) => h.event === "UserPromptSubmit")) {
20116
20978
  const promptReport = await runHooks({
20117
20979
  hooks: hookList,
20118
- payload: { event: "UserPromptSubmit", cwd: currentRootDir, prompt: text }
20980
+ payload: { event: "UserPromptSubmit", cwd: currentRootDir, prompt: text2 }
20119
20981
  });
20120
20982
  if (promptReport.outcomes.length > 0) {
20121
20983
  setHistorical((prev) => [
@@ -20129,8 +20991,8 @@ function App({
20129
20991
  }
20130
20992
  if (promptReport.blocked) return;
20131
20993
  }
20132
- promptHistory.current.push(text);
20133
- const pasteDisplay = formatLongPaste(text);
20994
+ promptHistory.current.push(text2);
20995
+ const pasteDisplay = formatLongPaste(text2);
20134
20996
  setHistorical((prev) => [
20135
20997
  ...prev,
20136
20998
  // `leadSeparator`: thin rule above this user turn when history
@@ -20145,7 +21007,7 @@ function App({
20145
21007
  }
20146
21008
  ]);
20147
21009
  const userId = `u-${Date.now()}`;
20148
- broadcastDashboardEvent({ kind: "user", id: userId, text });
21010
+ broadcastDashboardEvent({ kind: "user", id: userId, text: text2 });
20149
21011
  const assistantId = `a-${Date.now()}`;
20150
21012
  const streamRef = { id: assistantId, text: "", reasoning: "" };
20151
21013
  const contentBuf = { current: "" };
@@ -20184,9 +21046,9 @@ function App({
20184
21046
  });
20185
21047
  };
20186
21048
  const timer = PLAIN_UI ? null : setInterval(flush, FLUSH_INTERVAL_MS);
20187
- let modelInput = text;
21049
+ let modelInput = text2;
20188
21050
  if (codeMode) {
20189
- const expanded = expandAtMentions(text, currentRootDir);
21051
+ const expanded = expandAtMentions(text2, currentRootDir);
20190
21052
  if (expanded.expansions.length > 0) {
20191
21053
  modelInput = expanded.text;
20192
21054
  const inlined = expanded.expansions.filter((ex) => ex.ok).map((ex) => `${ex.path} (${(ex.bytes ?? 0).toLocaleString()} bytes)`);
@@ -20202,7 +21064,7 @@ function App({
20202
21064
  }
20203
21065
  }
20204
21066
  }
20205
- if (/(?:^|\s)@https?:\/\//.test(text)) {
21067
+ if (/(?:^|\s)@https?:\/\//.test(text2)) {
20206
21068
  try {
20207
21069
  const urlExpanded = await expandAtUrls(modelInput, {
20208
21070
  fetcher: webFetch,
@@ -20797,9 +21659,9 @@ ${body}`;
20797
21659
  );
20798
21660
  useEffect7(() => {
20799
21661
  if (!busy && queuedSubmit !== null) {
20800
- const text = queuedSubmit;
21662
+ const text2 = queuedSubmit;
20801
21663
  setQueuedSubmit(null);
20802
- void handleSubmit2(text);
21664
+ void handleSubmit2(text2);
20803
21665
  }
20804
21666
  }, [busy, queuedSubmit, handleSubmit2]);
20805
21667
  const handleWorkspaceConfirm = useCallback4(
@@ -21166,7 +22028,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21166
22028
  async (choice) => handleReviseConfirmRef.current(choice),
21167
22029
  []
21168
22030
  );
21169
- return /* @__PURE__ */ React27.createElement(React27.Fragment, null, /* @__PURE__ */ React27.createElement(
22031
+ return /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(
21170
22032
  TickerProvider,
21171
22033
  {
21172
22034
  disabled: PLAIN_UI || isResizing || !!pendingPlan || !!pendingShell || !!pendingWorkspace || !!pendingEditReview || walkthroughActive || !!pendingCheckpoint || !!stagedCheckpointRevise || !!pendingChoice || !!stagedChoiceCustom || !!pendingRevision || // Idle gate: when nothing is actively happening, suspend the
@@ -21179,44 +22041,40 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21179
22041
  // changes (incoming stream, key press, modal popup).
21180
22042
  !busy && !streaming
21181
22043
  },
21182
- /* @__PURE__ */ React27.createElement(
21183
- Box25,
22044
+ /* @__PURE__ */ React28.createElement(
22045
+ Box26,
21184
22046
  {
21185
22047
  flexDirection: "column",
21186
22048
  height: stdout4?.rows ?? 30,
21187
22049
  width: stdout4?.columns ?? 80,
21188
22050
  overflow: "hidden"
21189
22051
  },
21190
- /* @__PURE__ */ React27.createElement(
21191
- StatsPanel,
22052
+ /* @__PURE__ */ React28.createElement(
22053
+ ChromeBar,
21192
22054
  {
21193
22055
  summary,
21194
- model: loop2.model,
21195
- prefixHash,
21196
- harvestOn: loop2.harvestEnabled,
21197
- branchBudget: loop2.branchOptions.budget,
21198
- reasoningEffort: loop2.reasoningEffort,
21199
22056
  planMode,
21200
- editMode: codeMode ? editMode : void 0,
22057
+ preset: preset2,
21201
22058
  balance,
21202
- busy,
21203
22059
  updateAvailable,
21204
22060
  proArmed,
21205
22061
  escalated: turnOnPro,
21206
22062
  budgetUsd: loop2.budgetUsd,
21207
22063
  rootDir: codeMode ? currentRootDir : void 0,
21208
- sessionName: session ?? null
22064
+ sessionName: session ?? null,
22065
+ scrollRatio: scrollMaxRowsRef.current > 0 ? logScrollOffset / scrollMaxRowsRef.current : 0
21209
22066
  }
21210
22067
  ),
21211
- /* @__PURE__ */ React27.createElement(
21212
- Box25,
22068
+ /* @__PURE__ */ React28.createElement(
22069
+ Box26,
21213
22070
  {
21214
- flexDirection: "row",
22071
+ flexDirection: "column",
22072
+ flexGrow: 1,
21215
22073
  height: pendingShell || pendingWorkspace || pendingPlan || pendingEditReview || pendingCheckpoint || stagedCheckpointRevise || stagedInput || stagedChoiceCustom || pendingChoice || pendingRevision || walkthroughActive ? 0 : Math.max(5, (stdout4?.rows ?? 30) - 9),
21216
22074
  overflow: "hidden"
21217
22075
  },
21218
- /* @__PURE__ */ React27.createElement(Box25, { flexDirection: "column", flexGrow: 1, overflow: "hidden" }, /* @__PURE__ */ React27.createElement(
21219
- Box25,
22076
+ /* @__PURE__ */ React28.createElement(Box26, { flexDirection: "column", flexGrow: 1, overflow: "hidden" }, /* @__PURE__ */ React28.createElement(
22077
+ Box26,
21220
22078
  {
21221
22079
  flexDirection: "column",
21222
22080
  flexGrow: 1,
@@ -21224,55 +22082,56 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21224
22082
  overflow: "hidden"
21225
22083
  },
21226
22084
  (() => {
21227
- const reservedRows = 10;
21228
- const available = Math.max(8, (stdout4?.rows ?? 30) - reservedRows);
22085
+ const logHeight = Math.max(5, (stdout4?.rows ?? 30) - 9);
22086
+ const available = Math.max(4, logHeight - (logScrollOffset > 0 ? 1 : 0));
21229
22087
  const cols = stdout4?.columns ?? 80;
21230
- const items = historical.flatMap((e) => eventToItems(e, currentRootDir, cols));
21231
- const slice = sliceLogItems(items, available, logScrollOffset);
21232
- scrollMaxRowsRef.current = slice.maxScrollRows;
21233
- lastTotalRowsRef.current = slice.totalRows;
21234
- return /* @__PURE__ */ React27.createElement(React27.Fragment, null, slice.items.map(renderLogItem));
22088
+ const atoms = eventsToAtoms(historical, currentRootDir, cols);
22089
+ const v = viewportLog(atoms, logScrollOffset, available);
22090
+ scrollMaxRowsRef.current = v.maxScrollRows;
22091
+ lastTotalRowsRef.current = v.totalRows;
22092
+ return renderViewport(v);
21235
22093
  })(),
21236
- !historical.some((e) => e.role === "user" || e.role === "assistant") && !busy && !streaming ? /* @__PURE__ */ React27.createElement(WelcomeBanner, { inCodeMode: !!codeMode, dashboardUrl }) : null,
21237
- !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && streaming ? /* @__PURE__ */ React27.createElement(Box25, { marginY: 1 }, /* @__PURE__ */ React27.createElement(EventRow, { event: streaming, projectRoot: currentRootDir })) : null,
21238
- !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && ongoingTool ? /* @__PURE__ */ React27.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null,
21239
- !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && subagentActivity ? /* @__PURE__ */ React27.createElement(SubagentRow, { activity: subagentActivity }) : null,
21240
- !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !ongoingTool && statusLine ? /* @__PURE__ */ React27.createElement(StatusRow, { text: statusLine }) : null,
21241
- !PLAIN_UI && undoBanner && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision ? /* @__PURE__ */ React27.createElement(UndoBanner, { banner: undoBanner }) : null,
21242
- !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && busy && !streaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React27.createElement(StatusRow, { text: "processing\u2026" }) : null
21243
- ), /* @__PURE__ */ React27.createElement(BottomHint, { rowsBelow: logScrollOffset })),
21244
- /* @__PURE__ */ React27.createElement(
21245
- ScrollBar,
22094
+ !historical.some((e) => e.role === "user" || e.role === "assistant") && !busy && !streaming ? /* @__PURE__ */ React28.createElement(WelcomeBanner, { inCodeMode: !!codeMode, dashboardUrl }) : null,
22095
+ !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && streaming ? /* @__PURE__ */ React28.createElement(Box26, { marginY: 1 }, /* @__PURE__ */ React28.createElement(EventRow, { event: streaming, projectRoot: currentRootDir })) : null,
22096
+ !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && ongoingTool ? /* @__PURE__ */ React28.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null,
22097
+ !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && subagentActivity ? /* @__PURE__ */ React28.createElement(SubagentRow, { activity: subagentActivity }) : null,
22098
+ !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !ongoingTool && statusLine ? /* @__PURE__ */ React28.createElement(StatusRow, { text: statusLine }) : null,
22099
+ !PLAIN_UI && undoBanner && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision ? /* @__PURE__ */ React28.createElement(UndoBanner, { banner: undoBanner }) : null,
22100
+ !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && busy && !streaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React28.createElement(StatusRow, { text: "processing\u2026" }) : null
22101
+ ), /* @__PURE__ */ React28.createElement(
22102
+ BottomHint,
21246
22103
  {
21247
- height: Math.max(5, (stdout4?.rows ?? 30) - 9),
22104
+ rowsBelow: logScrollOffset,
21248
22105
  totalRows: lastTotalRowsRef.current,
21249
- viewportRows: Math.max(8, (stdout4?.rows ?? 30) - 10),
21250
- scrollOffsetRows: logScrollOffset
22106
+ viewportRows: Math.max(
22107
+ 4,
22108
+ Math.max(5, (stdout4?.rows ?? 30) - 9) - (logScrollOffset > 0 ? 1 : 0)
22109
+ )
21251
22110
  }
21252
- )
22111
+ ))
21253
22112
  ),
21254
- stagedInput ? /* @__PURE__ */ React27.createElement(
22113
+ stagedInput ? /* @__PURE__ */ React28.createElement(
21255
22114
  PlanRefineInput,
21256
22115
  {
21257
22116
  mode: stagedInput.mode,
21258
22117
  onSubmit: handleStagedInputSubmit,
21259
22118
  onCancel: handleStagedInputCancel
21260
22119
  }
21261
- ) : stagedCheckpointRevise ? /* @__PURE__ */ React27.createElement(
22120
+ ) : stagedCheckpointRevise ? /* @__PURE__ */ React28.createElement(
21262
22121
  PlanRefineInput,
21263
22122
  {
21264
22123
  mode: "checkpoint-revise",
21265
22124
  onSubmit: handleCheckpointReviseSubmit,
21266
22125
  onCancel: handleCheckpointReviseCancel
21267
22126
  }
21268
- ) : stagedChoiceCustom ? /* @__PURE__ */ React27.createElement(
22127
+ ) : stagedChoiceCustom ? /* @__PURE__ */ React28.createElement(
21269
22128
  PlanRefineInput,
21270
22129
  {
21271
22130
  mode: "choice-custom",
21272
22131
  onSubmit: handleChoiceCustomSubmit,
21273
22132
  onCancel: handleChoiceCustomCancel
21274
22133
  }
21275
- ) : pendingChoice ? /* @__PURE__ */ React27.createElement(
22134
+ ) : pendingChoice ? /* @__PURE__ */ React28.createElement(
21276
22135
  ChoiceConfirm,
21277
22136
  {
21278
22137
  question: pendingChoice.question,
@@ -21280,7 +22139,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21280
22139
  allowCustom: pendingChoice.allowCustom,
21281
22140
  onChoose: stableHandleChoiceConfirm
21282
22141
  }
21283
- ) : pendingRevision ? /* @__PURE__ */ React27.createElement(
22142
+ ) : pendingRevision ? /* @__PURE__ */ React28.createElement(
21284
22143
  PlanReviseConfirm,
21285
22144
  {
21286
22145
  reason: pendingRevision.reason,
@@ -21291,7 +22150,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21291
22150
  summary: pendingRevision.summary,
21292
22151
  onChoose: stableHandleReviseConfirm
21293
22152
  }
21294
- ) : pendingCheckpoint ? /* @__PURE__ */ React27.createElement(
22153
+ ) : pendingCheckpoint ? /* @__PURE__ */ React28.createElement(
21295
22154
  PlanCheckpointConfirm,
21296
22155
  {
21297
22156
  stepId: pendingCheckpoint.stepId,
@@ -21302,7 +22161,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21302
22161
  completedStepIds: completedStepIdsRef.current,
21303
22162
  onChoose: stableHandleCheckpointConfirm
21304
22163
  }
21305
- ) : pendingPlan ? /* @__PURE__ */ React27.createElement(
22164
+ ) : pendingPlan ? /* @__PURE__ */ React28.createElement(
21306
22165
  PlanConfirm,
21307
22166
  {
21308
22167
  plan: pendingPlan,
@@ -21311,7 +22170,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21311
22170
  onChoose: stableHandlePlanConfirm,
21312
22171
  projectRoot: currentRootDir
21313
22172
  }
21314
- ) : pendingShell ? /* @__PURE__ */ React27.createElement(
22173
+ ) : pendingShell ? /* @__PURE__ */ React28.createElement(
21315
22174
  ShellConfirm,
21316
22175
  {
21317
22176
  command: pendingShell.command,
@@ -21319,7 +22178,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21319
22178
  kind: pendingShell.kind,
21320
22179
  onChoose: handleShellConfirm
21321
22180
  }
21322
- ) : pendingWorkspace ? /* @__PURE__ */ React27.createElement(
22181
+ ) : pendingWorkspace ? /* @__PURE__ */ React28.createElement(
21323
22182
  WorkspaceConfirm,
21324
22183
  {
21325
22184
  path: pendingWorkspace.path,
@@ -21327,7 +22186,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21327
22186
  mcpServerCount: mcpServers?.length ?? 0,
21328
22187
  onChoose: handleWorkspaceConfirm
21329
22188
  }
21330
- ) : pendingEditReview ? /* @__PURE__ */ React27.createElement(
22189
+ ) : pendingEditReview ? /* @__PURE__ */ React28.createElement(
21331
22190
  EditConfirm,
21332
22191
  {
21333
22192
  block: pendingEditReview,
@@ -21339,14 +22198,14 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21339
22198
  }
21340
22199
  }
21341
22200
  }
21342
- ) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */ React27.createElement(
22201
+ ) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */ React28.createElement(
21343
22202
  EditConfirm,
21344
22203
  {
21345
22204
  key: `walk-${pendingTick}`,
21346
22205
  block: pendingEdits.current[0],
21347
22206
  onChoose: handleWalkChoice
21348
22207
  }
21349
- ) : /* @__PURE__ */ React27.createElement(React27.Fragment, null, codeMode ? /* @__PURE__ */ React27.createElement(
22208
+ ) : /* @__PURE__ */ React28.createElement(React28.Fragment, null, codeMode ? /* @__PURE__ */ React28.createElement(
21350
22209
  ModeStatusBar,
21351
22210
  {
21352
22211
  editMode,
@@ -21356,7 +22215,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21356
22215
  undoArmed: !!undoBanner || hasUndoable(),
21357
22216
  jobs: codeMode.jobs
21358
22217
  }
21359
- ) : null, activeLoop ? /* @__PURE__ */ React27.createElement(LoopStatusRow, { loop: activeLoop }) : null, /* @__PURE__ */ React27.createElement(
22218
+ ) : null, activeLoop ? /* @__PURE__ */ React28.createElement(LoopStatusRow, { loop: activeLoop }) : null, /* @__PURE__ */ React28.createElement(
21360
22219
  PromptInput,
21361
22220
  {
21362
22221
  value: input,
@@ -21366,14 +22225,14 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21366
22225
  onHistoryPrev: recallPrev,
21367
22226
  onHistoryNext: recallNext
21368
22227
  }
21369
- ), /* @__PURE__ */ React27.createElement(SlashSuggestions, { matches: slashMatches, selectedIndex: slashSelected }), /* @__PURE__ */ React27.createElement(
22228
+ ), /* @__PURE__ */ React28.createElement(SlashSuggestions, { matches: slashMatches, selectedIndex: slashSelected }), /* @__PURE__ */ React28.createElement(
21370
22229
  AtMentionSuggestions,
21371
22230
  {
21372
22231
  matches: atMatches,
21373
22232
  selectedIndex: atSelected,
21374
22233
  query: atPicker?.query ?? ""
21375
22234
  }
21376
- ), slashArgContext ? /* @__PURE__ */ React27.createElement(
22235
+ ), slashArgContext ? /* @__PURE__ */ React28.createElement(
21377
22236
  SlashArgPicker,
21378
22237
  {
21379
22238
  matches: slashArgMatches,
@@ -21388,15 +22247,15 @@ Continue executing from the next pending step. Call mark_step_complete after eac
21388
22247
  }
21389
22248
 
21390
22249
  // src/cli/ui/SessionPicker.tsx
21391
- import { Box as Box26, Text as Text24 } from "ink";
21392
- import React28 from "react";
22250
+ import { Box as Box27, Text as Text25 } from "ink";
22251
+ import React29 from "react";
21393
22252
  function SessionPicker({
21394
22253
  sessionName,
21395
22254
  messageCount,
21396
22255
  lastActive,
21397
22256
  onChoose
21398
22257
  }) {
21399
- return /* @__PURE__ */ React28.createElement(Box26, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React28.createElement(Box26, { marginBottom: 1 }, /* @__PURE__ */ React28.createElement(Text24, { color: COLOR.brand, bold: true }, GLYPH.brand), /* @__PURE__ */ React28.createElement(Text24, null, " "), /* @__PURE__ */ React28.createElement(Text24, { color: COLOR.primary, bold: true }, `"${sessionName}"`), /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, ` has ${messageCount} prior message${messageCount === 1 ? "" : "s"}`), /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, ` \xB7 last active ${relativeTime2(lastActive)}`)), /* @__PURE__ */ React28.createElement(
22258
+ return /* @__PURE__ */ React29.createElement(Box27, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React29.createElement(Box27, { marginBottom: 1 }, /* @__PURE__ */ React29.createElement(Text25, { color: COLOR.brand, bold: true }, GLYPH.brand), /* @__PURE__ */ React29.createElement(Text25, null, " "), /* @__PURE__ */ React29.createElement(Text25, { color: COLOR.primary, bold: true }, `"${sessionName}"`), /* @__PURE__ */ React29.createElement(Text25, { dimColor: true }, ` has ${messageCount} prior message${messageCount === 1 ? "" : "s"}`), /* @__PURE__ */ React29.createElement(Text25, { dimColor: true }, ` \xB7 last active ${relativeTime2(lastActive)}`)), /* @__PURE__ */ React29.createElement(
21400
22259
  SingleSelect,
21401
22260
  {
21402
22261
  initialValue: "new",
@@ -21419,7 +22278,7 @@ function SessionPicker({
21419
22278
  ],
21420
22279
  onSubmit: (v) => onChoose(v)
21421
22280
  }
21422
- ), /* @__PURE__ */ React28.createElement(Box26, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text24, { dimColor: true }, " \u2191\u2193 navigate \xB7 \u23CE select")));
22281
+ ), /* @__PURE__ */ React29.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text25, { dimColor: true }, " \u2191\u2193 navigate \xB7 \u23CE select")));
21423
22282
  }
21424
22283
  function relativeTime2(date) {
21425
22284
  const ms = Date.now() - date.getTime();
@@ -21435,9 +22294,9 @@ function relativeTime2(date) {
21435
22294
  }
21436
22295
 
21437
22296
  // src/cli/ui/Setup.tsx
21438
- import { Box as Box27, Text as Text25, useApp } from "ink";
22297
+ import { Box as Box28, Text as Text26, useApp } from "ink";
21439
22298
  import TextInput from "ink-text-input";
21440
- import React29, { useState as useState11 } from "react";
22299
+ import React30, { useState as useState11 } from "react";
21441
22300
  function Setup({ onReady }) {
21442
22301
  const [value, setValue] = useState11("");
21443
22302
  const [error, setError] = useState11(null);
@@ -21461,7 +22320,7 @@ function Setup({ onReady }) {
21461
22320
  }
21462
22321
  onReady(trimmed);
21463
22322
  };
21464
- return /* @__PURE__ */ React29.createElement(Box27, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React29.createElement(Box27, null, /* @__PURE__ */ React29.createElement(Text25, { bold: true, color: GRADIENT[0] }, GLYPH.brand), /* @__PURE__ */ React29.createElement(Text25, null, " "), /* @__PURE__ */ React29.createElement(Text25, { bold: true }, "Welcome to "), /* @__PURE__ */ React29.createElement(Text25, { bold: true, color: GRADIENT[2] }, "REASONIX")), /* @__PURE__ */ React29.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text25, { color: COLOR.info }, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React29.createElement(Box27, null, /* @__PURE__ */ React29.createElement(Text25, { dimColor: true }, " free credit on signup \xB7 "), /* @__PURE__ */ React29.createElement(Text25, { color: COLOR.primary }, "https://platform.deepseek.com/api_keys")), /* @__PURE__ */ React29.createElement(Box27, null, /* @__PURE__ */ React29.createElement(Text25, { dimColor: true }, " saved to "), /* @__PURE__ */ React29.createElement(Text25, { dimColor: true }, defaultConfigPath())), /* @__PURE__ */ React29.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text25, { bold: true, color: COLOR.brand }, GLYPH.bar), /* @__PURE__ */ React29.createElement(Text25, { bold: true, color: COLOR.primary }, " \u203A "), /* @__PURE__ */ React29.createElement(
22323
+ return /* @__PURE__ */ React30.createElement(Box28, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React30.createElement(Box28, null, /* @__PURE__ */ React30.createElement(Text26, { bold: true, color: GRADIENT[0] }, GLYPH.brand), /* @__PURE__ */ React30.createElement(Text26, null, " "), /* @__PURE__ */ React30.createElement(Text26, { bold: true }, "Welcome to "), /* @__PURE__ */ React30.createElement(Text26, { bold: true, color: GRADIENT[2] }, "REASONIX")), /* @__PURE__ */ React30.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(Text26, { color: COLOR.info }, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React30.createElement(Box28, null, /* @__PURE__ */ React30.createElement(Text26, { dimColor: true }, " free credit on signup \xB7 "), /* @__PURE__ */ React30.createElement(Text26, { color: COLOR.primary }, "https://platform.deepseek.com/api_keys")), /* @__PURE__ */ React30.createElement(Box28, null, /* @__PURE__ */ React30.createElement(Text26, { dimColor: true }, " saved to "), /* @__PURE__ */ React30.createElement(Text26, { dimColor: true }, defaultConfigPath())), /* @__PURE__ */ React30.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(Text26, { bold: true, color: COLOR.brand }, GLYPH.bar), /* @__PURE__ */ React30.createElement(Text26, { bold: true, color: COLOR.primary }, " \u203A "), /* @__PURE__ */ React30.createElement(
21465
22324
  TextInput,
21466
22325
  {
21467
22326
  value,
@@ -21470,7 +22329,7 @@ function Setup({ onReady }) {
21470
22329
  mask: "\u2022",
21471
22330
  placeholder: "sk-..."
21472
22331
  }
21473
- )), error ? /* @__PURE__ */ React29.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text25, { color: COLOR.err, bold: true }, GLYPH.err), /* @__PURE__ */ React29.createElement(Text25, { color: COLOR.err }, ` ${error}`)) : value ? /* @__PURE__ */ React29.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text25, { dimColor: true }, ` preview \xB7 ${redactKey(value)}`)) : null, /* @__PURE__ */ React29.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text25, { dimColor: true }, " /exit to abort")));
22332
+ )), error ? /* @__PURE__ */ React30.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(Text26, { color: COLOR.err, bold: true }, GLYPH.err), /* @__PURE__ */ React30.createElement(Text26, { color: COLOR.err }, ` ${error}`)) : value ? /* @__PURE__ */ React30.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(Text26, { dimColor: true }, ` preview \xB7 ${redactKey(value)}`)) : null, /* @__PURE__ */ React30.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(Text26, { dimColor: true }, " /exit to abort")));
21474
22333
  }
21475
22334
 
21476
22335
  // src/cli/commands/chat.tsx
@@ -21486,7 +22345,7 @@ function Root({
21486
22345
  const [key, setKey] = useState12(initialKey);
21487
22346
  const [pending, setPending] = useState12(sessionPreview);
21488
22347
  if (!key) {
21489
- return /* @__PURE__ */ React30.createElement(
22348
+ return /* @__PURE__ */ React31.createElement(
21490
22349
  Setup,
21491
22350
  {
21492
22351
  onReady: (k) => {
@@ -21498,7 +22357,7 @@ function Root({
21498
22357
  }
21499
22358
  process.env.DEEPSEEK_API_KEY = key;
21500
22359
  if (pending && appProps.session) {
21501
- return /* @__PURE__ */ React30.createElement(KeystrokeProvider, null, /* @__PURE__ */ React30.createElement(
22360
+ return /* @__PURE__ */ React31.createElement(KeystrokeProvider, null, /* @__PURE__ */ React31.createElement(
21502
22361
  SessionPicker,
21503
22362
  {
21504
22363
  sessionName: appProps.session,
@@ -21513,7 +22372,7 @@ function Root({
21513
22372
  }
21514
22373
  ));
21515
22374
  }
21516
- return /* @__PURE__ */ React30.createElement(KeystrokeProvider, null, /* @__PURE__ */ React30.createElement(
22375
+ return /* @__PURE__ */ React31.createElement(KeystrokeProvider, null, /* @__PURE__ */ React31.createElement(
21517
22376
  App,
21518
22377
  {
21519
22378
  model: appProps.model,
@@ -21620,7 +22479,7 @@ async function chatCommand(opts) {
21620
22479
  rewriteSession(opts.session, []);
21621
22480
  }
21622
22481
  const { waitUntilExit } = render(
21623
- /* @__PURE__ */ React30.createElement(
22482
+ /* @__PURE__ */ React31.createElement(
21624
22483
  Root,
21625
22484
  {
21626
22485
  initialKey,
@@ -21973,35 +22832,35 @@ async function commitCommand(opts = {}) {
21973
22832
  import { writeFileSync as writeFileSync15 } from "fs";
21974
22833
  import { basename as basename4 } from "path";
21975
22834
  import { render as render2 } from "ink";
21976
- import React33 from "react";
22835
+ import React34 from "react";
21977
22836
 
21978
22837
  // src/cli/ui/DiffApp.tsx
21979
- import { Box as Box29, Static, Text as Text27, useApp as useApp2, useInput } from "ink";
21980
- import React32, { useState as useState13 } from "react";
22838
+ import { Box as Box30, Static, Text as Text28, useApp as useApp2, useInput } from "ink";
22839
+ import React33, { useState as useState13 } from "react";
21981
22840
 
21982
22841
  // src/cli/ui/RecordView.tsx
21983
- import { Box as Box28, Text as Text26 } from "ink";
21984
- import React31 from "react";
22842
+ import { Box as Box29, Text as Text27 } from "ink";
22843
+ import React32 from "react";
21985
22844
  function RecordView({ rec, compact: compact2 = false }) {
21986
22845
  const toolArgsMax = compact2 ? 120 : 200;
21987
22846
  const toolContentMax = compact2 ? 200 : 400;
21988
22847
  if (rec.role === "user") {
21989
22848
  const content = rec.content.includes("\n") ? rec.content.split("\n").join("\n ") : rec.content;
21990
- return /* @__PURE__ */ React31.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React31.createElement(Text26, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React31.createElement(Text26, null, content));
22849
+ return /* @__PURE__ */ React32.createElement(Box29, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text27, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React32.createElement(Text27, null, content));
21991
22850
  }
21992
22851
  if (rec.role === "assistant_final") {
21993
- return /* @__PURE__ */ React31.createElement(Box28, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React31.createElement(Box28, null, /* @__PURE__ */ React31.createElement(Text26, { bold: true, color: "green" }, "assistant"), rec.cost !== void 0 ? /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, " $", rec.cost.toFixed(6)) : null, rec.usage ? /* @__PURE__ */ React31.createElement(CacheBadge, { usage: rec.usage }) : null), rec.planState ? /* @__PURE__ */ React31.createElement(PlanStateBlock, { planState: rec.planState }) : null, rec.content ? /* @__PURE__ */ React31.createElement(Text26, null, rec.content) : /* @__PURE__ */ React31.createElement(Text26, { dimColor: true, italic: true }, "(tool-call response only)"));
22852
+ return /* @__PURE__ */ React32.createElement(Box29, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React32.createElement(Box29, null, /* @__PURE__ */ React32.createElement(Text27, { bold: true, color: "green" }, "assistant"), rec.cost !== void 0 ? /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, " $", rec.cost.toFixed(6)) : null, rec.usage ? /* @__PURE__ */ React32.createElement(CacheBadge, { usage: rec.usage }) : null), rec.planState ? /* @__PURE__ */ React32.createElement(PlanStateBlock, { planState: rec.planState }) : null, rec.content ? /* @__PURE__ */ React32.createElement(Text27, null, rec.content) : /* @__PURE__ */ React32.createElement(Text27, { dimColor: true, italic: true }, "(tool-call response only)"));
21994
22853
  }
21995
22854
  if (rec.role === "tool") {
21996
- return /* @__PURE__ */ React31.createElement(Box28, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React31.createElement(Text26, { color: "yellow" }, "tool<", rec.tool ?? "?", ">"), rec.args ? /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, " args: ", truncate2(rec.args, toolArgsMax)) : null, /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, " \u2192 ", truncate2(rec.content, toolContentMax)));
22855
+ return /* @__PURE__ */ React32.createElement(Box29, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text27, { color: "yellow" }, "tool<", rec.tool ?? "?", ">"), rec.args ? /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, " args: ", truncate2(rec.args, toolArgsMax)) : null, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, " \u2192 ", truncate2(rec.content, toolContentMax)));
21997
22856
  }
21998
22857
  if (rec.role === "error") {
21999
- return /* @__PURE__ */ React31.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React31.createElement(Text26, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React31.createElement(Text26, { color: "red" }, rec.error ?? rec.content));
22858
+ return /* @__PURE__ */ React32.createElement(Box29, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text27, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React32.createElement(Text27, { color: "red" }, rec.error ?? rec.content));
22000
22859
  }
22001
22860
  if (rec.role === "done" || rec.role === "assistant_delta") {
22002
22861
  return null;
22003
22862
  }
22004
- return /* @__PURE__ */ React31.createElement(Box28, null, /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, "[", rec.role, "] ", rec.content));
22863
+ return /* @__PURE__ */ React32.createElement(Box29, null, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, "[", rec.role, "] ", rec.content));
22005
22864
  }
22006
22865
  function CacheBadge({ usage }) {
22007
22866
  const hit = usage.prompt_cache_hit_tokens ?? 0;
@@ -22010,7 +22869,7 @@ function CacheBadge({ usage }) {
22010
22869
  if (total === 0) return null;
22011
22870
  const pct2 = hit / total * 100;
22012
22871
  const color2 = pct2 >= 70 ? "green" : pct2 >= 40 ? "yellow" : "red";
22013
- return /* @__PURE__ */ React31.createElement(Text26, null, /* @__PURE__ */ React31.createElement(Text26, { dimColor: true }, " \xB7 cache "), /* @__PURE__ */ React31.createElement(Text26, { color: color2 }, pct2.toFixed(1), "%"));
22872
+ return /* @__PURE__ */ React32.createElement(Text27, null, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, " \xB7 cache "), /* @__PURE__ */ React32.createElement(Text27, { color: color2 }, pct2.toFixed(1), "%"));
22014
22873
  }
22015
22874
  function truncate2(s, max) {
22016
22875
  return s.length <= max ? s : `${s.slice(0, max)}\u2026 (+${s.length - max} chars)`;
@@ -22044,7 +22903,7 @@ function DiffApp({ report }) {
22044
22903
  }
22045
22904
  });
22046
22905
  const pair = report.pairs[idx];
22047
- return /* @__PURE__ */ React32.createElement(Box29, { flexDirection: "column" }, /* @__PURE__ */ React32.createElement(DiffHeader, { report }), /* @__PURE__ */ React32.createElement(Box29, { marginTop: 1, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ React32.createElement(Text27, { color: "cyan", bold: true }, "turn ", pair?.turn ?? "?", " (", idx + 1, " / ", report.pairs.length, ")"), /* @__PURE__ */ React32.createElement(Text27, null, pair ? /* @__PURE__ */ React32.createElement(KindBadge, { kind: pair.kind }) : null)), /* @__PURE__ */ React32.createElement(Box29, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React32.createElement(Pane, { label: report.a.label, headerColor: "blue", records: paneRecords(pair, "a") }), /* @__PURE__ */ React32.createElement(Pane, { label: report.b.label, headerColor: "magenta", records: paneRecords(pair, "b") })), pair?.divergenceNote ? /* @__PURE__ */ React32.createElement(Box29, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React32.createElement(Text27, { color: "yellow" }, "\u2605 "), /* @__PURE__ */ React32.createElement(Text27, null, pair.divergenceNote)) : null, /* @__PURE__ */ React32.createElement(Box29, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "j"), "/", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "\u2193"), " next \xB7 ", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "k"), "/", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "\u2191"), " ", "prev \xB7 ", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "n"), " next-diverge \xB7 ", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "N"), "/", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "p"), " ", "prev-diverge \xB7 ", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "g"), "/", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "G"), " first/last \xB7 ", /* @__PURE__ */ React32.createElement(Text27, { bold: true }, "q"), " ", "quit")));
22906
+ return /* @__PURE__ */ React33.createElement(Box30, { flexDirection: "column" }, /* @__PURE__ */ React33.createElement(DiffHeader, { report }), /* @__PURE__ */ React33.createElement(Box30, { marginTop: 1, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ React33.createElement(Text28, { color: "cyan", bold: true }, "turn ", pair?.turn ?? "?", " (", idx + 1, " / ", report.pairs.length, ")"), /* @__PURE__ */ React33.createElement(Text28, null, pair ? /* @__PURE__ */ React33.createElement(KindBadge, { kind: pair.kind }) : null)), /* @__PURE__ */ React33.createElement(Box30, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React33.createElement(Pane, { label: report.a.label, headerColor: "blue", records: paneRecords(pair, "a") }), /* @__PURE__ */ React33.createElement(Pane, { label: report.b.label, headerColor: "magenta", records: paneRecords(pair, "b") })), pair?.divergenceNote ? /* @__PURE__ */ React33.createElement(Box30, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React33.createElement(Text28, { color: "yellow" }, "\u2605 "), /* @__PURE__ */ React33.createElement(Text28, null, pair.divergenceNote)) : null, /* @__PURE__ */ React33.createElement(Box30, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React33.createElement(Text28, { dimColor: true }, /* @__PURE__ */ React33.createElement(Text28, { bold: true }, "j"), "/", /* @__PURE__ */ React33.createElement(Text28, { bold: true }, "\u2193"), " next \xB7 ", /* @__PURE__ */ React33.createElement(Text28, { bold: true }, "k"), "/", /* @__PURE__ */ React33.createElement(Text28, { bold: true }, "\u2191"), " ", "prev \xB7 ", /* @__PURE__ */ React33.createElement(Text28, { bold: true }, "n"), " next-diverge \xB7 ", /* @__PURE__ */ React33.createElement(Text28, { bold: true }, "N"), "/", /* @__PURE__ */ React33.createElement(Text28, { bold: true }, "p"), " ", "prev-diverge \xB7 ", /* @__PURE__ */ React33.createElement(Text28, { bold: true }, "g"), "/", /* @__PURE__ */ React33.createElement(Text28, { bold: true }, "G"), " first/last \xB7 ", /* @__PURE__ */ React33.createElement(Text28, { bold: true }, "q"), " ", "quit")));
22048
22907
  }
22049
22908
  function DiffHeader({ report }) {
22050
22909
  const a = report.a;
@@ -22062,15 +22921,15 @@ function DiffHeader({ report }) {
22062
22921
  } else if (a.stats.prefixHashes[0] && a.stats.prefixHashes[0] === b.stats.prefixHashes[0]) {
22063
22922
  prefixLine = `shared prefix hash ${a.stats.prefixHashes[0].slice(0, 12)}\u2026 \u2014 cache delta attributable to log stability, not prompt change.`;
22064
22923
  }
22065
- return /* @__PURE__ */ React32.createElement(Box29, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React32.createElement(Box29, { justifyContent: "space-between" }, /* @__PURE__ */ React32.createElement(Text27, null, /* @__PURE__ */ React32.createElement(Text27, { color: "cyan", bold: true }, "reasonix diff"), /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, " \xB7 A="), /* @__PURE__ */ React32.createElement(Text27, { color: "blue" }, a.label), /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, " vs B="), /* @__PURE__ */ React32.createElement(Text27, { color: "magenta" }, b.label)), /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, report.pairs.length, " turns aligned")), /* @__PURE__ */ React32.createElement(Box29, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React32.createElement(Text27, null, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, "cache "), /* @__PURE__ */ React32.createElement(Text27, null, (a.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React32.createElement(Text27, null, (b.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React32.createElement(Text27, { color: cacheDelta >= 0 ? "green" : "red", bold: true }, " ", cacheDelta >= 0 ? "+" : "", (cacheDelta * 100).toFixed(1), "pp")), /* @__PURE__ */ React32.createElement(Text27, null, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, "cost "), /* @__PURE__ */ React32.createElement(Text27, null, "$", a.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React32.createElement(Text27, null, "$", b.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React32.createElement(Text27, { color: costDelta2 <= 0 ? "green" : "red", bold: true }, " ", costDelta2 >= 0 ? "+" : "", costDelta2.toFixed(1), "%")), /* @__PURE__ */ React32.createElement(Text27, null, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true }, "model calls "), /* @__PURE__ */ React32.createElement(Text27, null, a.stats.turns, " \u2192 ", b.stats.turns))), prefixLine ? /* @__PURE__ */ React32.createElement(Box29, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true, italic: true }, prefixLine)) : null);
22924
+ return /* @__PURE__ */ React33.createElement(Box30, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React33.createElement(Box30, { justifyContent: "space-between" }, /* @__PURE__ */ React33.createElement(Text28, null, /* @__PURE__ */ React33.createElement(Text28, { color: "cyan", bold: true }, "reasonix diff"), /* @__PURE__ */ React33.createElement(Text28, { dimColor: true }, " \xB7 A="), /* @__PURE__ */ React33.createElement(Text28, { color: "blue" }, a.label), /* @__PURE__ */ React33.createElement(Text28, { dimColor: true }, " vs B="), /* @__PURE__ */ React33.createElement(Text28, { color: "magenta" }, b.label)), /* @__PURE__ */ React33.createElement(Text28, { dimColor: true }, report.pairs.length, " turns aligned")), /* @__PURE__ */ React33.createElement(Box30, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React33.createElement(Text28, null, /* @__PURE__ */ React33.createElement(Text28, { dimColor: true }, "cache "), /* @__PURE__ */ React33.createElement(Text28, null, (a.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React33.createElement(Text28, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React33.createElement(Text28, null, (b.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React33.createElement(Text28, { color: cacheDelta >= 0 ? "green" : "red", bold: true }, " ", cacheDelta >= 0 ? "+" : "", (cacheDelta * 100).toFixed(1), "pp")), /* @__PURE__ */ React33.createElement(Text28, null, /* @__PURE__ */ React33.createElement(Text28, { dimColor: true }, "cost "), /* @__PURE__ */ React33.createElement(Text28, null, "$", a.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React33.createElement(Text28, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React33.createElement(Text28, null, "$", b.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React33.createElement(Text28, { color: costDelta2 <= 0 ? "green" : "red", bold: true }, " ", costDelta2 >= 0 ? "+" : "", costDelta2.toFixed(1), "%")), /* @__PURE__ */ React33.createElement(Text28, null, /* @__PURE__ */ React33.createElement(Text28, { dimColor: true }, "model calls "), /* @__PURE__ */ React33.createElement(Text28, null, a.stats.turns, " \u2192 ", b.stats.turns))), prefixLine ? /* @__PURE__ */ React33.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text28, { dimColor: true, italic: true }, prefixLine)) : null);
22066
22925
  }
22067
22926
  function Pane({
22068
22927
  label,
22069
22928
  headerColor,
22070
22929
  records
22071
22930
  }) {
22072
- return /* @__PURE__ */ React32.createElement(
22073
- Box29,
22931
+ return /* @__PURE__ */ React33.createElement(
22932
+ Box30,
22074
22933
  {
22075
22934
  flexDirection: "column",
22076
22935
  flexGrow: 1,
@@ -22078,21 +22937,21 @@ function Pane({
22078
22937
  borderStyle: "single",
22079
22938
  borderColor: headerColor
22080
22939
  },
22081
- /* @__PURE__ */ React32.createElement(Text27, { color: headerColor, bold: true }, label),
22082
- records.length === 0 ? /* @__PURE__ */ React32.createElement(Box29, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text27, { dimColor: true, italic: true }, "(no records on this side for this turn)")) : /* @__PURE__ */ React32.createElement(Static, { items: records.map((rec, i) => ({ key: `${label}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React32.createElement(RecordView, { key, rec, compact: true }))
22940
+ /* @__PURE__ */ React33.createElement(Text28, { color: headerColor, bold: true }, label),
22941
+ records.length === 0 ? /* @__PURE__ */ React33.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text28, { dimColor: true, italic: true }, "(no records on this side for this turn)")) : /* @__PURE__ */ React33.createElement(Static, { items: records.map((rec, i) => ({ key: `${label}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React33.createElement(RecordView, { key, rec, compact: true }))
22083
22942
  );
22084
22943
  }
22085
22944
  function KindBadge({ kind }) {
22086
22945
  if (kind === "match") {
22087
- return /* @__PURE__ */ React32.createElement(Text27, { color: "green" }, "\u2713 match");
22946
+ return /* @__PURE__ */ React33.createElement(Text28, { color: "green" }, "\u2713 match");
22088
22947
  }
22089
22948
  if (kind === "diverge") {
22090
- return /* @__PURE__ */ React32.createElement(Text27, { color: "yellow" }, "\u2605 diverge");
22949
+ return /* @__PURE__ */ React33.createElement(Text28, { color: "yellow" }, "\u2605 diverge");
22091
22950
  }
22092
22951
  if (kind === "only_in_a") {
22093
- return /* @__PURE__ */ React32.createElement(Text27, { color: "blue" }, "\u2190 only in A");
22952
+ return /* @__PURE__ */ React33.createElement(Text28, { color: "blue" }, "\u2190 only in A");
22094
22953
  }
22095
- return /* @__PURE__ */ React32.createElement(Text27, { color: "magenta" }, "\u2192 only in B");
22954
+ return /* @__PURE__ */ React33.createElement(Text28, { color: "magenta" }, "\u2192 only in B");
22096
22955
  }
22097
22956
  function paneRecords(pair, side) {
22098
22957
  if (!pair) return [];
@@ -22123,7 +22982,7 @@ markdown report written to ${opts.mdPath}`);
22123
22982
  return;
22124
22983
  }
22125
22984
  if (wantTui) {
22126
- const { waitUntilExit } = render2(React33.createElement(DiffApp, { report }), {
22985
+ const { waitUntilExit } = render2(React34.createElement(DiffApp, { report }), {
22127
22986
  exitOnCtrlC: true,
22128
22987
  patchConsole: false
22129
22988
  });
@@ -22138,9 +22997,9 @@ import { existsSync as existsSync24, statSync as statSync14 } from "fs";
22138
22997
  import { homedir as homedir11 } from "os";
22139
22998
  import { dirname as dirname17, join as join23, resolve as resolve13 } from "path";
22140
22999
  var TTY = process.stdout.isTTY && process.env.TERM !== "dumb";
22141
- function color(text, code) {
22142
- if (!TTY) return text;
22143
- return `\x1B[${code}m${text}\x1B[0m`;
23000
+ function color(text2, code) {
23001
+ if (!TTY) return text2;
23002
+ return `\x1B[${code}m${text2}\x1B[0m`;
22144
23003
  }
22145
23004
  function badge(level) {
22146
23005
  if (level === "ok") return color("\u2713", "32");
@@ -22481,8 +23340,8 @@ async function ollamaPreflight(opts) {
22481
23340
  return false;
22482
23341
  }
22483
23342
  log(t("modelPulling", { model: opts.model }));
22484
- const ESC = String.fromCharCode(27);
22485
- const ANSI_CSI = new RegExp(`${ESC}\\[[0-9;]*[A-Za-z]`, "g");
23343
+ const ESC2 = String.fromCharCode(27);
23344
+ const ANSI_CSI = new RegExp(`${ESC2}\\[[0-9;]*[A-Za-z]`, "g");
22486
23345
  const code = await pullOllamaModel(opts.model, {
22487
23346
  onLine: (line) => {
22488
23347
  const cleaned = line.replace(ANSI_CSI, "").trim();
@@ -22744,7 +23603,7 @@ function mcpListCommand(opts) {
22744
23603
  console.log("Popular MCP servers you can bridge into Reasonix:");
22745
23604
  console.log("");
22746
23605
  for (const entry of MCP_CATALOG) {
22747
- console.log(` ${pad2(entry.name, 12)} ${entry.summary}`);
23606
+ console.log(` ${pad3(entry.name, 12)} ${entry.summary}`);
22748
23607
  console.log(` ${mcpCommandFor(entry)}`);
22749
23608
  if (entry.note) console.log(` \xB7 ${entry.note}`);
22750
23609
  console.log("");
@@ -22757,17 +23616,128 @@ function mcpListCommand(opts) {
22757
23616
  " https://mcp.so \u2014 community-maintained catalog"
22758
23617
  );
22759
23618
  }
22760
- function pad2(s, width) {
23619
+ function pad3(s, width) {
22761
23620
  return s.length >= width ? s : s + " ".repeat(width - s.length);
22762
23621
  }
22763
23622
 
22764
23623
  // src/cli/commands/replay.ts
22765
23624
  import { render as render3 } from "ink";
23625
+ import React37 from "react";
23626
+
23627
+ // src/cli/ui/ReplayApp.tsx
23628
+ import { Box as Box32, Static as Static2, Text as Text30, useApp as useApp3, useInput as useInput2 } from "ink";
23629
+ import React36, { useMemo as useMemo4, useState as useState14 } from "react";
23630
+
23631
+ // src/cli/ui/StatsPanel.tsx
23632
+ import { basename as basename5 } from "path";
23633
+ import { Box as Box31, Text as Text29, useStdout as useStdout10 } from "ink";
22766
23634
  import React35 from "react";
23635
+ var NARROW_BREAKPOINT2 = 120;
23636
+ var COLD_START_TURNS2 = 3;
23637
+ function StatsPanel({
23638
+ summary,
23639
+ model: model2,
23640
+ prefixHash,
23641
+ harvestOn,
23642
+ branchBudget,
23643
+ reasoningEffort,
23644
+ planMode,
23645
+ editMode,
23646
+ balance,
23647
+ updateAvailable,
23648
+ busy,
23649
+ proArmed,
23650
+ escalated,
23651
+ budgetUsd,
23652
+ rootDir,
23653
+ sessionName
23654
+ }) {
23655
+ const branchOn = (branchBudget ?? 1) > 1;
23656
+ const ctxMax = DEEPSEEK_CONTEXT_TOKENS[model2] ?? DEFAULT_CONTEXT_TOKENS;
23657
+ const ctxRatio = summary.lastPromptTokens / ctxMax;
23658
+ const { stdout: stdout4 } = useStdout10();
23659
+ const columns = stdout4?.columns ?? 80;
23660
+ const narrow = columns < NARROW_BREAKPOINT2;
23661
+ const coldStart = summary.turns <= COLD_START_TURNS2;
23662
+ return /* @__PURE__ */ React35.createElement(Box31, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React35.createElement(
23663
+ ChromeRow,
23664
+ {
23665
+ editMode,
23666
+ planMode,
23667
+ proArmed: proArmed ?? false,
23668
+ escalated: escalated ?? false,
23669
+ summary,
23670
+ coldStart,
23671
+ rootDir,
23672
+ sessionName: sessionName ?? null,
23673
+ updateAvailable,
23674
+ balance: balance ?? null,
23675
+ narrow
23676
+ }
23677
+ ), /* @__PURE__ */ React35.createElement(ChromeRule2, null), budgetUsd !== null && budgetUsd !== void 0 ? /* @__PURE__ */ React35.createElement(BudgetRow, { spent: summary.totalCostUsd, cap: budgetUsd }) : null);
23678
+ }
23679
+ function ChromeRule2() {
23680
+ const { stdout: stdout4 } = useStdout10();
23681
+ const cols = stdout4?.columns ?? 80;
23682
+ const w = Math.max(20, cols - 2);
23683
+ return /* @__PURE__ */ React35.createElement(Text29, { dimColor: true }, "\u2500".repeat(w));
23684
+ }
23685
+ function ChromeRow({
23686
+ editMode,
23687
+ planMode,
23688
+ proArmed,
23689
+ escalated,
23690
+ summary,
23691
+ coldStart,
23692
+ rootDir,
23693
+ sessionName,
23694
+ updateAvailable,
23695
+ balance,
23696
+ narrow
23697
+ }) {
23698
+ const modePill = pickModePill2(planMode, editMode);
23699
+ const proPill = escalated ? { label: "\u21E7 pro", color: COLOR.err } : proArmed ? { label: "\u21E7 pro", color: COLOR.warn } : null;
23700
+ const projectName = rootDir ? basename5(rootDir) : null;
23701
+ const cachePct = Math.round(summary.cacheHitRatio * 100);
23702
+ const cacheColor = summary.cacheHitRatio >= 0.7 ? COLOR.ok : summary.cacheHitRatio >= 0.4 ? COLOR.warn : COLOR.err;
23703
+ return /* @__PURE__ */ React35.createElement(Box31, null, /* @__PURE__ */ React35.createElement(Text29, { bold: true, color: GRADIENT[0] }, "\u25C8 "), /* @__PURE__ */ React35.createElement(Text29, { color: COLOR.brand, bold: true }, "reasonix"), projectName ? /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement(Text29, { color: COLOR.info, dimColor: true }, " \xB7 "), /* @__PURE__ */ React35.createElement(Text29, null, projectName), !narrow && sessionName ? /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement(Text29, { color: COLOR.info, dimColor: true }, " \u203A "), /* @__PURE__ */ React35.createElement(Text29, { color: COLOR.info }, sessionName)) : null) : null, /* @__PURE__ */ React35.createElement(Box31, { flexGrow: 1 }), updateAvailable ? /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement(Text29, { color: COLOR.warn, bold: true }, `\u2191 ${updateAvailable}`), /* @__PURE__ */ React35.createElement(Text29, null, " ")) : null, modePill ? /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement(Text29, { color: modePill.color, bold: true }, `[${modePill.label}]`), /* @__PURE__ */ React35.createElement(Text29, null, " ")) : null, proPill ? /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement(Text29, { color: proPill.color, bold: true }, `[${proPill.label}]`), /* @__PURE__ */ React35.createElement(Text29, null, " ")) : null, /* @__PURE__ */ React35.createElement(
23704
+ Text29,
23705
+ {
23706
+ color: summary.turns === 0 || coldStart ? COLOR.info : sessionCostColor2(summary.totalCostUsd),
23707
+ bold: summary.turns > 0 && !coldStart,
23708
+ dimColor: summary.turns === 0 || coldStart
23709
+ },
23710
+ `[$${summary.totalCostUsd.toFixed(4)}]`
23711
+ ), balance && !narrow ? /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement(Text29, null, " "), /* @__PURE__ */ React35.createElement(Text29, { color: balance.total < 1 ? COLOR.err : balance.total < 5 ? COLOR.warn : COLOR.ok }, `[w ${balance.currency === "USD" ? "$" : ""}${balance.total.toFixed(2)}${balance.currency !== "USD" ? ` ${balance.currency}` : ""}]`)) : null, summary.turns > 3 && !narrow ? /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement(Text29, null, " "), /* @__PURE__ */ React35.createElement(Text29, { dimColor: true }, "["), /* @__PURE__ */ React35.createElement(Text29, { dimColor: true }, "c "), /* @__PURE__ */ React35.createElement(Bar, { ratio: summary.cacheHitRatio, color: cacheColor, cells: 6 }), /* @__PURE__ */ React35.createElement(Text29, null, " "), /* @__PURE__ */ React35.createElement(Text29, { color: cacheColor }, `${cachePct}%`), /* @__PURE__ */ React35.createElement(Text29, { dimColor: true }, "]")) : null);
23712
+ }
23713
+ function pickModePill2(planMode, editMode) {
23714
+ if (planMode) return { label: "PLAN", color: COLOR.err };
23715
+ if (editMode === "yolo") return { label: "yolo", color: COLOR.err };
23716
+ if (editMode === "auto") return { label: "auto", color: COLOR.primary };
23717
+ if (editMode === "review") return { label: "review", color: COLOR.info };
23718
+ return null;
23719
+ }
23720
+ function BudgetRow({ spent, cap }) {
23721
+ const pct2 = Math.max(0, spent / cap * 100);
23722
+ const color2 = pct2 >= 100 ? "#f87171" : pct2 >= 80 ? "#fbbf24" : "#94a3b8";
23723
+ return /* @__PURE__ */ React35.createElement(Box31, null, /* @__PURE__ */ React35.createElement(Text29, { dimColor: true }, " budget "), /* @__PURE__ */ React35.createElement(Text29, { color: color2 }, `$${spent.toFixed(4)} / $${cap.toFixed(2)}`, /* @__PURE__ */ React35.createElement(Text29, { dimColor: true }, ` (${pct2.toFixed(0)}%)`)));
23724
+ }
23725
+ function sessionCostColor2(cost) {
23726
+ if (cost <= 0) return void 0;
23727
+ if (cost >= 5) return COLOR.err;
23728
+ if (cost >= 0.5) return COLOR.warn;
23729
+ return COLOR.ok;
23730
+ }
23731
+ function Bar({
23732
+ ratio,
23733
+ color: color2,
23734
+ cells = 14
23735
+ }) {
23736
+ const filled = Math.max(0, Math.min(cells, Math.round(ratio * cells)));
23737
+ return /* @__PURE__ */ React35.createElement(Text29, null, /* @__PURE__ */ React35.createElement(Text29, { color: color2 }, "\u25B0".repeat(filled)), /* @__PURE__ */ React35.createElement(Text29, { dimColor: true }, "\u25B1".repeat(cells - filled)));
23738
+ }
22767
23739
 
22768
23740
  // src/cli/ui/ReplayApp.tsx
22769
- import { Box as Box30, Static as Static2, Text as Text28, useApp as useApp3, useInput as useInput2 } from "ink";
22770
- import React34, { useMemo as useMemo4, useState as useState14 } from "react";
22771
23741
  function ReplayApp({ meta, pages }) {
22772
23742
  const { exit: exit2 } = useApp3();
22773
23743
  const maxIdx = Math.max(0, pages.length - 1);
@@ -22807,14 +23777,14 @@ function ReplayApp({ meta, pages }) {
22807
23777
  const prefixHash = cumStats.prefixHashes.length === 1 ? cumStats.prefixHashes[0].slice(0, 16) : cumStats.prefixHashes.length === 0 ? "(untracked)" : `(churned \xD7${cumStats.prefixHashes.length})`;
22808
23778
  const currentPage = pages[idx];
22809
23779
  const progressLabel = pages.length === 0 ? "empty transcript" : `turn ${idx + 1} / ${pages.length}`;
22810
- return /* @__PURE__ */ React34.createElement(Box30, { flexDirection: "column" }, /* @__PURE__ */ React34.createElement(
23780
+ return /* @__PURE__ */ React36.createElement(Box32, { flexDirection: "column" }, /* @__PURE__ */ React36.createElement(
22811
23781
  StatsPanel,
22812
23782
  {
22813
23783
  summary,
22814
23784
  model: cumStats.models[0] ?? meta?.model ?? "?",
22815
23785
  prefixHash
22816
23786
  }
22817
- ), /* @__PURE__ */ React34.createElement(Box30, { flexDirection: "column", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React34.createElement(Box30, { justifyContent: "space-between" }, /* @__PURE__ */ React34.createElement(Text28, { color: "cyan", bold: true }, progressLabel), meta ? /* @__PURE__ */ React34.createElement(Text28, { dimColor: true }, meta.source, meta.task ? ` \xB7 ${meta.task}` : "", meta.mode ? ` \xB7 ${meta.mode}` : "") : null), currentPage ? /* @__PURE__ */ React34.createElement(Static2, { items: currentPage.records.map((rec, i) => ({ key: `${idx}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React34.createElement(RecordView, { key, rec })) : /* @__PURE__ */ React34.createElement(Text28, { dimColor: true, italic: true }, "no records")), /* @__PURE__ */ React34.createElement(Box30, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React34.createElement(Text28, { dimColor: true }, /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "j"), "/", /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "\u2193"), "/", /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "space"), " next \xB7 ", /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "k"), "/", /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "\u2191"), " prev \xB7 ", /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "g"), " first \xB7 ", /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "G"), " last \xB7", " ", /* @__PURE__ */ React34.createElement(Text28, { bold: true }, "q"), " quit")));
23787
+ ), /* @__PURE__ */ React36.createElement(Box32, { flexDirection: "column", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React36.createElement(Box32, { justifyContent: "space-between" }, /* @__PURE__ */ React36.createElement(Text30, { color: "cyan", bold: true }, progressLabel), meta ? /* @__PURE__ */ React36.createElement(Text30, { dimColor: true }, meta.source, meta.task ? ` \xB7 ${meta.task}` : "", meta.mode ? ` \xB7 ${meta.mode}` : "") : null), currentPage ? /* @__PURE__ */ React36.createElement(Static2, { items: currentPage.records.map((rec, i) => ({ key: `${idx}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React36.createElement(RecordView, { key, rec })) : /* @__PURE__ */ React36.createElement(Text30, { dimColor: true, italic: true }, "no records")), /* @__PURE__ */ React36.createElement(Box32, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React36.createElement(Text30, { dimColor: true }, /* @__PURE__ */ React36.createElement(Text30, { bold: true }, "j"), "/", /* @__PURE__ */ React36.createElement(Text30, { bold: true }, "\u2193"), "/", /* @__PURE__ */ React36.createElement(Text30, { bold: true }, "space"), " next \xB7 ", /* @__PURE__ */ React36.createElement(Text30, { bold: true }, "k"), "/", /* @__PURE__ */ React36.createElement(Text30, { bold: true }, "\u2191"), " prev \xB7 ", /* @__PURE__ */ React36.createElement(Text30, { bold: true }, "g"), " first \xB7 ", /* @__PURE__ */ React36.createElement(Text30, { bold: true }, "G"), " last \xB7", " ", /* @__PURE__ */ React36.createElement(Text30, { bold: true }, "q"), " quit")));
22818
23788
  }
22819
23789
 
22820
23790
  // src/cli/commands/replay.ts
@@ -22826,7 +23796,7 @@ async function replayCommand(opts) {
22826
23796
  }
22827
23797
  const { parsed } = replayFromFile(opts.path);
22828
23798
  const pages = groupRecordsByTurn(parsed.records);
22829
- const { waitUntilExit } = render3(React35.createElement(ReplayApp, { meta: parsed.meta, pages }), {
23799
+ const { waitUntilExit } = render3(React37.createElement(ReplayApp, { meta: parsed.meta, pages }), {
22830
23800
  exitOnCtrlC: true,
22831
23801
  patchConsole: false
22832
23802
  });
@@ -23132,12 +24102,12 @@ function truncate3(s, max) {
23132
24102
 
23133
24103
  // src/cli/commands/setup.tsx
23134
24104
  import { render as render4 } from "ink";
23135
- import React37 from "react";
24105
+ import React39 from "react";
23136
24106
 
23137
24107
  // src/cli/ui/Wizard.tsx
23138
- import { Box as Box31, Text as Text29, useApp as useApp4, useInput as useInput3 } from "ink";
24108
+ import { Box as Box33, Text as Text31, useApp as useApp4, useInput as useInput3 } from "ink";
23139
24109
  import TextInput2 from "ink-text-input";
23140
- import React36, { useState as useState15 } from "react";
24110
+ import React38, { useState as useState15 } from "react";
23141
24111
  var CATALOG_BY_NAME = new Map(MCP_CATALOG.map((e) => [e.name, e]));
23142
24112
  function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
23143
24113
  const { exit: exit2 } = useApp4();
@@ -23153,7 +24123,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
23153
24123
  if (key.escape && step !== "saved" && onCancel) onCancel();
23154
24124
  });
23155
24125
  if (step === "apiKey") {
23156
- return /* @__PURE__ */ React36.createElement(
24126
+ return /* @__PURE__ */ React38.createElement(
23157
24127
  ApiKeyStep,
23158
24128
  {
23159
24129
  onSubmit: (key) => {
@@ -23167,7 +24137,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
23167
24137
  );
23168
24138
  }
23169
24139
  if (step === "preset") {
23170
- return /* @__PURE__ */ React36.createElement(StepFrame, { title: "Pick a preset", step: 1, total: 3 }, /* @__PURE__ */ React36.createElement(
24140
+ return /* @__PURE__ */ React38.createElement(StepFrame, { title: "Pick a preset", step: 1, total: 3 }, /* @__PURE__ */ React38.createElement(
23171
24141
  SingleSelect,
23172
24142
  {
23173
24143
  items: presetItems(),
@@ -23177,10 +24147,10 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
23177
24147
  setStep("mcp");
23178
24148
  }
23179
24149
  }
23180
- ), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "[\u2191\u2193] navigate \xB7 [Enter] confirm \xB7 [Esc] cancel")));
24150
+ ), /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text31, { dimColor: true }, "[\u2191\u2193] navigate \xB7 [Enter] confirm \xB7 [Esc] cancel")));
23181
24151
  }
23182
24152
  if (step === "mcp") {
23183
- return /* @__PURE__ */ React36.createElement(StepFrame, { title: "Which MCP servers should Reasonix wire up for you?", step: 2, total: 3 }, /* @__PURE__ */ React36.createElement(
24153
+ return /* @__PURE__ */ React38.createElement(StepFrame, { title: "Which MCP servers should Reasonix wire up for you?", step: 2, total: 3 }, /* @__PURE__ */ React38.createElement(
23184
24154
  MultiSelect,
23185
24155
  {
23186
24156
  items: mcpItems(),
@@ -23205,7 +24175,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
23205
24175
  }
23206
24176
  const currentName = pending[0];
23207
24177
  const entry = CATALOG_BY_NAME.get(currentName);
23208
- return /* @__PURE__ */ React36.createElement(
24178
+ return /* @__PURE__ */ React38.createElement(
23209
24179
  McpArgsStep,
23210
24180
  {
23211
24181
  entry,
@@ -23223,7 +24193,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
23223
24193
  }
23224
24194
  if (step === "review") {
23225
24195
  const specs = data.selectedCatalog.map((name) => buildSpec(name, data.catalogArgs));
23226
- return /* @__PURE__ */ React36.createElement(StepFrame, { title: "Ready to save", step: 3, total: 3 }, /* @__PURE__ */ React36.createElement(Box31, { flexDirection: "column" }, /* @__PURE__ */ React36.createElement(SummaryLine, { label: "API key", value: redactKey(data.apiKey) }), /* @__PURE__ */ React36.createElement(SummaryLine, { label: "Preset", value: data.preset }), /* @__PURE__ */ React36.createElement(
24196
+ return /* @__PURE__ */ React38.createElement(StepFrame, { title: "Ready to save", step: 3, total: 3 }, /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column" }, /* @__PURE__ */ React38.createElement(SummaryLine, { label: "API key", value: redactKey(data.apiKey) }), /* @__PURE__ */ React38.createElement(SummaryLine, { label: "Preset", value: data.preset }), /* @__PURE__ */ React38.createElement(
23227
24197
  SummaryLine,
23228
24198
  {
23229
24199
  label: "MCP",
@@ -23231,8 +24201,8 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
23231
24201
  }
23232
24202
  ), specs.map((spec, i) => (
23233
24203
  // biome-ignore lint/suspicious/noArrayIndexKey: review-only render, order fixed
23234
- /* @__PURE__ */ React36.createElement(Box31, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "\xB7 ", spec))
23235
- )), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, null, "Saves to ", defaultConfigPath())), error ? /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { color: "red" }, error)) : null, /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "[Enter] save \xB7 [Esc] cancel"))), /* @__PURE__ */ React36.createElement(
24204
+ /* @__PURE__ */ React38.createElement(Box33, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React38.createElement(Text31, { dimColor: true }, "\xB7 ", spec))
24205
+ )), /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text31, null, "Saves to ", defaultConfigPath())), error ? /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text31, { color: "red" }, error)) : null, /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text31, { dimColor: true }, "[Enter] save \xB7 [Esc] cancel"))), /* @__PURE__ */ React38.createElement(
23236
24206
  ReviewConfirm,
23237
24207
  {
23238
24208
  onConfirm: () => {
@@ -23258,7 +24228,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
23258
24228
  }
23259
24229
  ));
23260
24230
  }
23261
- return /* @__PURE__ */ React36.createElement(Box31, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React36.createElement(Text29, { bold: true, color: "green" }, "\u25B8 Saved."), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, null, "Run `reasonix` any time to start chatting \u2014 your settings are remembered.")), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "[Enter] to exit")), /* @__PURE__ */ React36.createElement(ExitOnEnter, { onExit: exit2 }));
24231
+ return /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React38.createElement(Text31, { bold: true, color: "green" }, "\u25B8 Saved."), /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text31, null, "Run `reasonix` any time to start chatting \u2014 your settings are remembered.")), /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text31, { dimColor: true }, "[Enter] to exit")), /* @__PURE__ */ React38.createElement(ExitOnEnter, { onExit: exit2 }));
23262
24232
  }
23263
24233
  function ApiKeyStep({
23264
24234
  onSubmit,
@@ -23266,7 +24236,7 @@ function ApiKeyStep({
23266
24236
  onError
23267
24237
  }) {
23268
24238
  const [value, setValue] = useState15("");
23269
- return /* @__PURE__ */ React36.createElement(Box31, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React36.createElement(Text29, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React36.createElement(
24239
+ return /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React38.createElement(Text31, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text31, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React38.createElement(Text31, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React38.createElement(Text31, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text31, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React38.createElement(
23270
24240
  TextInput2,
23271
24241
  {
23272
24242
  value,
@@ -23283,7 +24253,7 @@ function ApiKeyStep({
23283
24253
  mask: "\u2022",
23284
24254
  placeholder: "sk-..."
23285
24255
  }
23286
- )), error ? /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { color: "red" }, error)) : value ? /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "preview: ", redactKey(value))) : null);
24256
+ )), error ? /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text31, { color: "red" }, error)) : value ? /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text31, { dimColor: true }, "preview: ", redactKey(value))) : null);
23287
24257
  }
23288
24258
  function McpArgsStep({
23289
24259
  entry,
@@ -23292,7 +24262,7 @@ function McpArgsStep({
23292
24262
  onError
23293
24263
  }) {
23294
24264
  const [value, setValue] = useState15("");
23295
- return /* @__PURE__ */ React36.createElement(StepFrame, { title: `Configure ${entry.name}`, step: 2, total: 3 }, /* @__PURE__ */ React36.createElement(Box31, { flexDirection: "column" }, /* @__PURE__ */ React36.createElement(Text29, null, entry.summary), entry.note ? /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, entry.note)) : null, /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, null, "Required parameter: "), /* @__PURE__ */ React36.createElement(Text29, { bold: true }, entry.userArgs)), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { bold: true, color: "cyan" }, entry.userArgs, " \u203A "), /* @__PURE__ */ React36.createElement(
24265
+ return /* @__PURE__ */ React38.createElement(StepFrame, { title: `Configure ${entry.name}`, step: 2, total: 3 }, /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column" }, /* @__PURE__ */ React38.createElement(Text31, null, entry.summary), entry.note ? /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text31, { dimColor: true }, entry.note)) : null, /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text31, null, "Required parameter: "), /* @__PURE__ */ React38.createElement(Text31, { bold: true }, entry.userArgs)), /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text31, { bold: true, color: "cyan" }, entry.userArgs, " \u203A "), /* @__PURE__ */ React38.createElement(
23296
24266
  TextInput2,
23297
24267
  {
23298
24268
  value,
@@ -23308,7 +24278,7 @@ function McpArgsStep({
23308
24278
  },
23309
24279
  placeholder: placeholderFor(entry)
23310
24280
  }
23311
- )), error ? /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text29, { color: "red" }, error)) : null));
24281
+ )), error ? /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(Text31, { color: "red" }, error)) : null));
23312
24282
  }
23313
24283
  function ReviewConfirm({ onConfirm }) {
23314
24284
  useInput3((_i, key) => {
@@ -23328,10 +24298,10 @@ function StepFrame({
23328
24298
  total,
23329
24299
  children
23330
24300
  }) {
23331
- return /* @__PURE__ */ React36.createElement(Box31, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React36.createElement(Box31, null, /* @__PURE__ */ React36.createElement(Text29, { dimColor: true }, "Step ", step, "/", total, " \xB7", " "), /* @__PURE__ */ React36.createElement(Text29, { bold: true, color: "cyan" }, title)), /* @__PURE__ */ React36.createElement(Box31, { marginTop: 1, flexDirection: "column" }, children));
24301
+ return /* @__PURE__ */ React38.createElement(Box33, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React38.createElement(Box33, null, /* @__PURE__ */ React38.createElement(Text31, { dimColor: true }, "Step ", step, "/", total, " \xB7", " "), /* @__PURE__ */ React38.createElement(Text31, { bold: true, color: "cyan" }, title)), /* @__PURE__ */ React38.createElement(Box33, { marginTop: 1, flexDirection: "column" }, children));
23332
24302
  }
23333
24303
  function SummaryLine({ label, value }) {
23334
- return /* @__PURE__ */ React36.createElement(Box31, null, /* @__PURE__ */ React36.createElement(Text29, null, label.padEnd(12)), /* @__PURE__ */ React36.createElement(Text29, { bold: true }, value));
24304
+ return /* @__PURE__ */ React38.createElement(Box33, null, /* @__PURE__ */ React38.createElement(Text31, null, label.padEnd(12)), /* @__PURE__ */ React38.createElement(Text31, { bold: true }, value));
23335
24305
  }
23336
24306
  function presetItems() {
23337
24307
  return ["auto", "flash", "pro"].map((name) => ({
@@ -23387,7 +24357,7 @@ async function setupCommand(_opts = {}) {
23387
24357
  const existingKey = loadApiKey();
23388
24358
  const existing = readConfig();
23389
24359
  const { waitUntilExit, unmount } = render4(
23390
- /* @__PURE__ */ React37.createElement(
24360
+ /* @__PURE__ */ React39.createElement(
23391
24361
  Wizard,
23392
24362
  {
23393
24363
  existingApiKey: existingKey,