reasonix 0.5.6 → 0.5.7

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
@@ -2570,9 +2570,79 @@ function formatLoopError(err) {
2570
2570
  }
2571
2571
 
2572
2572
  // src/at-mentions.ts
2573
- import { existsSync as existsSync4, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
2574
- import { isAbsolute, relative, resolve } from "path";
2573
+ import { existsSync as existsSync4, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
2574
+ import { isAbsolute, join as join5, relative, resolve } from "path";
2575
2575
  var DEFAULT_AT_MENTION_MAX_BYTES = 64 * 1024;
2576
+ var DEFAULT_PICKER_IGNORE_DIRS = [
2577
+ "node_modules",
2578
+ ".git",
2579
+ "dist",
2580
+ "build",
2581
+ ".next",
2582
+ "out",
2583
+ "coverage",
2584
+ ".cache",
2585
+ ".vscode",
2586
+ ".idea",
2587
+ "target",
2588
+ ".venv",
2589
+ "venv",
2590
+ "__pycache__"
2591
+ ];
2592
+ function listFilesSync(root, opts = {}) {
2593
+ const maxResults = Math.max(1, opts.maxResults ?? 500);
2594
+ const ignore = new Set(opts.ignoreDirs ?? DEFAULT_PICKER_IGNORE_DIRS);
2595
+ const rootAbs = resolve(root);
2596
+ const out = [];
2597
+ const walk2 = (dirAbs, dirRel) => {
2598
+ if (out.length >= maxResults) return;
2599
+ let entries;
2600
+ try {
2601
+ entries = readdirSync2(dirAbs, { withFileTypes: true });
2602
+ } catch {
2603
+ return;
2604
+ }
2605
+ entries.sort((a, b) => a.name.localeCompare(b.name));
2606
+ for (const ent of entries) {
2607
+ if (out.length >= maxResults) return;
2608
+ const relPath = dirRel ? `${dirRel}/${ent.name}` : ent.name;
2609
+ if (ent.isDirectory()) {
2610
+ if (ent.name.startsWith(".") || ignore.has(ent.name)) continue;
2611
+ walk2(join5(dirAbs, ent.name), relPath);
2612
+ } else if (ent.isFile()) {
2613
+ out.push(relPath);
2614
+ }
2615
+ }
2616
+ };
2617
+ walk2(rootAbs, "");
2618
+ return out;
2619
+ }
2620
+ var AT_PICKER_PREFIX = /(?:^|\s)@([a-zA-Z0-9_./\\-]*)$/;
2621
+ function detectAtPicker(input) {
2622
+ const m = AT_PICKER_PREFIX.exec(input);
2623
+ if (!m) return null;
2624
+ const query = m[1] ?? "";
2625
+ const atOffset = input.length - query.length - 1;
2626
+ return { query, atOffset };
2627
+ }
2628
+ function rankPickerCandidates(files, query, limit = 40) {
2629
+ if (!query) return files.slice(0, limit);
2630
+ const needle = query.toLowerCase();
2631
+ const scored = [];
2632
+ for (const f of files) {
2633
+ const lower = f.toLowerCase();
2634
+ const hit = lower.indexOf(needle);
2635
+ if (hit < 0) continue;
2636
+ const slash = lower.lastIndexOf("/");
2637
+ const base = slash >= 0 ? lower.slice(slash + 1) : lower;
2638
+ let score = 2;
2639
+ if (base.startsWith(needle)) score = 0;
2640
+ else if (lower.startsWith(needle)) score = 1;
2641
+ scored.push({ path: f, score: score * 1e4 + hit });
2642
+ }
2643
+ scored.sort((a, b) => a.score - b.score);
2644
+ return scored.slice(0, limit).map((s) => s.path);
2645
+ }
2576
2646
  var AT_MENTION_PATTERN = /(?<=^|\s)@([a-zA-Z0-9_./\\-]+)/g;
2577
2647
  function expandAtMentions(text, rootDir, opts = {}) {
2578
2648
  const maxBytes = opts.maxBytes ?? DEFAULT_AT_MENTION_MAX_BYTES;
@@ -5309,7 +5379,7 @@ function sep() {
5309
5379
  // src/version.ts
5310
5380
  import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "fs";
5311
5381
  import { homedir as homedir4 } from "os";
5312
- import { dirname as dirname6, join as join6 } from "path";
5382
+ import { dirname as dirname6, join as join7 } from "path";
5313
5383
  import { fileURLToPath as fileURLToPath2 } from "url";
5314
5384
  var REGISTRY_URL = "https://registry.npmjs.org/reasonix/latest";
5315
5385
  var LATEST_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
@@ -5318,7 +5388,7 @@ function readPackageVersion() {
5318
5388
  try {
5319
5389
  let dir = dirname6(fileURLToPath2(import.meta.url));
5320
5390
  for (let i = 0; i < 6; i++) {
5321
- const p = join6(dir, "package.json");
5391
+ const p = join7(dir, "package.json");
5322
5392
  if (existsSync7(p)) {
5323
5393
  const pkg = JSON.parse(readFileSync9(p, "utf8"));
5324
5394
  if (pkg?.name === "reasonix" && typeof pkg.version === "string") {
@@ -5335,7 +5405,7 @@ function readPackageVersion() {
5335
5405
  }
5336
5406
  var VERSION = readPackageVersion();
5337
5407
  function cachePath(homeDirOverride) {
5338
- return join6(homeDirOverride ?? homedir4(), ".reasonix", "version-cache.json");
5408
+ return join7(homeDirOverride ?? homedir4(), ".reasonix", "version-cache.json");
5339
5409
  }
5340
5410
  function readCache(homeDirOverride) {
5341
5411
  try {
@@ -5410,9 +5480,9 @@ function isNpxInstall() {
5410
5480
  // src/usage.ts
5411
5481
  import { appendFileSync as appendFileSync2, existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync10, statSync as statSync4 } from "fs";
5412
5482
  import { homedir as homedir5 } from "os";
5413
- import { dirname as dirname7, join as join7 } from "path";
5483
+ import { dirname as dirname7, join as join8 } from "path";
5414
5484
  function defaultUsageLogPath(homeDirOverride) {
5415
- return join7(homeDirOverride ?? homedir5(), ".reasonix", "usage.jsonl");
5485
+ return join8(homeDirOverride ?? homedir5(), ".reasonix", "usage.jsonl");
5416
5486
  }
5417
5487
  function appendUsage(input) {
5418
5488
  const record = {
@@ -5536,11 +5606,11 @@ function formatLogSize(path = defaultUsageLogPath()) {
5536
5606
  // src/cli/commands/chat.tsx
5537
5607
  import { existsSync as existsSync10, statSync as statSync6 } from "fs";
5538
5608
  import { render } from "ink";
5539
- import React15, { useState as useState7 } from "react";
5609
+ import React16, { useState as useState7 } from "react";
5540
5610
 
5541
5611
  // src/cli/ui/App.tsx
5542
- import { Box as Box11, Static, Text as Text11, useApp, useInput as useInput4 } from "ink";
5543
- import React12, { useCallback, useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState5 } from "react";
5612
+ import { Box as Box12, Static, Text as Text12, useApp, useInput as useInput4 } from "ink";
5613
+ import React13, { useCallback, useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState5 } from "react";
5544
5614
 
5545
5615
  // src/tools/skills.ts
5546
5616
  function registerSkillTools(registry, opts = {}) {
@@ -5611,13 +5681,44 @@ ${skill.body}${argsBlock}`;
5611
5681
  return registry;
5612
5682
  }
5613
5683
 
5684
+ // src/cli/ui/AtMentionSuggestions.tsx
5685
+ import { Box, Text } from "ink";
5686
+ import React from "react";
5687
+ function AtMentionSuggestions({
5688
+ matches,
5689
+ selectedIndex,
5690
+ query
5691
+ }) {
5692
+ if (matches === null) return null;
5693
+ if (matches.length === 0) {
5694
+ return /* @__PURE__ */ React.createElement(Box, { paddingX: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, 'no files match "@', query, '"'), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " ", "\u2014 keep typing, or Backspace to edit. Paths resolve from the code root."));
5695
+ }
5696
+ const MAX = 8;
5697
+ const total = matches.length;
5698
+ const windowStart = total <= MAX ? 0 : Math.max(0, Math.min(selectedIndex - Math.floor(MAX / 2), total - MAX));
5699
+ const shown = matches.slice(windowStart, windowStart + MAX);
5700
+ const hiddenAbove = windowStart;
5701
+ const hiddenBelow = total - windowStart - shown.length;
5702
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingX: 1 }, hiddenAbove > 0 ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " \u2191 ", hiddenAbove, " more above") : null, shown.map((path, i) => /* @__PURE__ */ React.createElement(FileRow, { key: path, path, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " \u2193 ", hiddenBelow, " more below") : null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " [\u2191\u2193] navigate \xB7 [Tab]/[Enter] pick \xB7 file content inlined on send"));
5703
+ }
5704
+ function FileRow({ path, isSelected }) {
5705
+ const marker = isSelected ? "\u25B8" : " ";
5706
+ const slash = path.lastIndexOf("/");
5707
+ const dir = slash >= 0 ? `${path.slice(0, slash)}/` : "";
5708
+ const base = slash >= 0 ? path.slice(slash + 1) : path;
5709
+ if (isSelected) {
5710
+ return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { bold: true, color: "cyan" }, marker, " ", base), /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, dir ? ` ${dir}` : ""));
5711
+ }
5712
+ return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, marker, " ", base, dir ? ` ${dir}` : ""));
5713
+ }
5714
+
5614
5715
  // src/cli/ui/EventLog.tsx
5615
- import { Box as Box3, Text as Text3, useStdout } from "ink";
5616
- import React4 from "react";
5716
+ import { Box as Box4, Text as Text4, useStdout } from "ink";
5717
+ import React5 from "react";
5617
5718
 
5618
5719
  // src/cli/ui/PlanStateBlock.tsx
5619
- import { Box, Text } from "ink";
5620
- import React from "react";
5720
+ import { Box as Box2, Text as Text2 } from "ink";
5721
+ import React2 from "react";
5621
5722
  function PlanStateBlock({ planState }) {
5622
5723
  const fields = [];
5623
5724
  if (planState.subgoals.length) fields.push(["subgoals", planState.subgoals, "cyan", false]);
@@ -5628,14 +5729,14 @@ function PlanStateBlock({ planState }) {
5628
5729
  if (planState.rejectedPaths.length)
5629
5730
  fields.push(["rejected", planState.rejectedPaths, "red", true]);
5630
5731
  if (fields.length === 0) return null;
5631
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginBottom: 1 }, fields.map(([label, items, color, dim]) => /* @__PURE__ */ React.createElement(Text, { key: label }, /* @__PURE__ */ React.createElement(Text, { color, bold: true, dimColor: dim }, "\u2039 ", label), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, ` (${items.length})`), /* @__PURE__ */ React.createElement(Text, null, `: ${items.join(" \xB7 ")}`))));
5732
+ return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", marginBottom: 1 }, fields.map(([label, items, color, dim]) => /* @__PURE__ */ React2.createElement(Text2, { key: label }, /* @__PURE__ */ React2.createElement(Text2, { color, bold: true, dimColor: dim }, "\u2039 ", label), /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, ` (${items.length})`), /* @__PURE__ */ React2.createElement(Text2, null, `: ${items.join(" \xB7 ")}`))));
5632
5733
  }
5633
5734
 
5634
5735
  // src/cli/ui/markdown.tsx
5635
5736
  import { readFileSync as readFileSync11, statSync as statSync5 } from "fs";
5636
- import { isAbsolute as isAbsolute4, join as join8 } from "path";
5637
- import { Box as Box2, Text as Text2 } from "ink";
5638
- import React2 from "react";
5737
+ import { isAbsolute as isAbsolute4, join as join9 } from "path";
5738
+ import { Box as Box3, Text as Text3 } from "ink";
5739
+ import React3 from "react";
5639
5740
  var SUPERSCRIPT = {
5640
5741
  "0": "\u2070",
5641
5742
  "1": "\xB9",
@@ -5711,7 +5812,7 @@ function parseCitationUrl(url) {
5711
5812
  function validateCitation(url, projectRoot) {
5712
5813
  const parts = parseCitationUrl(url);
5713
5814
  if (!parts || !parts.path) return { ok: false, reason: "empty path" };
5714
- const fullPath = isAbsolute4(parts.path) ? parts.path : join8(projectRoot, parts.path);
5815
+ const fullPath = isAbsolute4(parts.path) ? parts.path : join9(projectRoot, parts.path);
5715
5816
  let stat;
5716
5817
  try {
5717
5818
  stat = statSync5(fullPath);
@@ -5759,57 +5860,57 @@ function InlineMd({
5759
5860
  for (const m of text.matchAll(INLINE_RE)) {
5760
5861
  const start = m.index ?? 0;
5761
5862
  if (start > last) {
5762
- parts.push(/* @__PURE__ */ React2.createElement(Text2, { key: `t${idx++}` }, text.slice(last, start)));
5863
+ parts.push(/* @__PURE__ */ React3.createElement(Text3, { key: `t${idx++}` }, text.slice(last, start)));
5763
5864
  }
5764
5865
  if (m[2] !== void 0 && m[3] !== void 0) {
5765
5866
  const linkText = m[2];
5766
5867
  const url = m[3];
5767
5868
  if (isExternalUrl(url)) {
5768
5869
  parts.push(
5769
- /* @__PURE__ */ React2.createElement(Text2, { key: `l${idx++}`, color: "blue", underline: true }, linkText)
5870
+ /* @__PURE__ */ React3.createElement(Text3, { key: `l${idx++}`, color: "blue", underline: true }, linkText)
5770
5871
  );
5771
5872
  } else {
5772
5873
  const status = citations?.get(url);
5773
5874
  if (status && !status.ok) {
5774
5875
  parts.push(
5775
- /* @__PURE__ */ React2.createElement(Text2, { key: `l${idx++}`, color: "red", strikethrough: true }, `${linkText} \u2717`)
5876
+ /* @__PURE__ */ React3.createElement(Text3, { key: `l${idx++}`, color: "red", strikethrough: true }, `${linkText} \u2717`)
5776
5877
  );
5777
5878
  } else {
5778
5879
  parts.push(
5779
- /* @__PURE__ */ React2.createElement(Text2, { key: `l${idx++}`, color: "cyan", underline: true }, linkText)
5880
+ /* @__PURE__ */ React3.createElement(Text3, { key: `l${idx++}`, color: "cyan", underline: true }, linkText)
5780
5881
  );
5781
5882
  }
5782
5883
  }
5783
5884
  } else if (m[4] !== void 0) {
5784
5885
  parts.push(
5785
- /* @__PURE__ */ React2.createElement(Text2, { key: `b${idx++}`, bold: true }, m[4])
5886
+ /* @__PURE__ */ React3.createElement(Text3, { key: `b${idx++}`, bold: true }, m[4])
5786
5887
  );
5787
5888
  } else if (m[5] !== void 0) {
5788
5889
  const stripped = m[5].replace(/^(\w+)\s+/, "");
5789
5890
  parts.push(
5790
- /* @__PURE__ */ React2.createElement(Text2, { key: `c${idx++}`, color: "yellow" }, stripped)
5891
+ /* @__PURE__ */ React3.createElement(Text3, { key: `c${idx++}`, color: "yellow" }, stripped)
5791
5892
  );
5792
5893
  } else if (m[6] !== void 0) {
5793
5894
  parts.push(
5794
- /* @__PURE__ */ React2.createElement(Text2, { key: `c${idx++}`, color: "yellow" }, m[6])
5895
+ /* @__PURE__ */ React3.createElement(Text3, { key: `c${idx++}`, color: "yellow" }, m[6])
5795
5896
  );
5796
5897
  } else if (m[7] !== void 0) {
5797
5898
  parts.push(
5798
- /* @__PURE__ */ React2.createElement(Text2, { key: `i${idx++}`, italic: true }, m[7])
5899
+ /* @__PURE__ */ React3.createElement(Text3, { key: `i${idx++}`, italic: true }, m[7])
5799
5900
  );
5800
5901
  }
5801
5902
  last = start + m[0].length;
5802
5903
  }
5803
5904
  if (last < text.length) {
5804
- parts.push(/* @__PURE__ */ React2.createElement(Text2, { key: `t${idx++}` }, text.slice(last)));
5905
+ parts.push(/* @__PURE__ */ React3.createElement(Text3, { key: `t${idx++}` }, text.slice(last)));
5805
5906
  }
5806
5907
  if (padTo !== void 0) {
5807
5908
  const seen = visibleWidth(text);
5808
5909
  if (seen < padTo) {
5809
- parts.push(/* @__PURE__ */ React2.createElement(Text2, { key: `pad${idx++}` }, " ".repeat(padTo - seen)));
5910
+ parts.push(/* @__PURE__ */ React3.createElement(Text3, { key: `pad${idx++}` }, " ".repeat(padTo - seen)));
5810
5911
  }
5811
5912
  }
5812
- return /* @__PURE__ */ React2.createElement(Text2, null, parts);
5913
+ return /* @__PURE__ */ React3.createElement(Text3, null, parts);
5813
5914
  }
5814
5915
  function stripInlineMarkup(s) {
5815
5916
  return s.replace(/\[([^\]\n]+)\]\(([^)\n]+)\)/g, "$1").replace(/\*\*([^*\n]+?)\*\*/g, "$1").replace(/```([^\n]+?)```/g, (_m, c) => c.replace(/^(\w+)\s+/, "")).replace(/`([^`\n]+?)`/g, "$1").replace(/(?<![*\w])\*([^*\n]+?)\*(?!\w)/g, "$1");
@@ -6005,19 +6106,19 @@ function parseBlocks(raw) {
6005
6106
  function BlockView({ block, citations }) {
6006
6107
  switch (block.kind) {
6007
6108
  case "heading":
6008
- return /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "cyan" }, /* @__PURE__ */ React2.createElement(InlineMd, { text: block.text, citations }));
6109
+ return /* @__PURE__ */ React3.createElement(Text3, { bold: true, color: "cyan" }, /* @__PURE__ */ React3.createElement(InlineMd, { text: block.text, citations }));
6009
6110
  case "paragraph":
6010
- return /* @__PURE__ */ React2.createElement(InlineMd, { text: block.text, citations });
6111
+ return /* @__PURE__ */ React3.createElement(InlineMd, { text: block.text, citations });
6011
6112
  case "bullet":
6012
- return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column" }, block.items.map((item, i) => /* @__PURE__ */ React2.createElement(Box2, { key: `${i}-${item.slice(0, 24)}` }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan" }, block.ordered ? ` ${block.start + i}. ` : " \u2022 "), /* @__PURE__ */ React2.createElement(InlineMd, { text: item, citations }))));
6113
+ return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, block.items.map((item, i) => /* @__PURE__ */ React3.createElement(Box3, { key: `${i}-${item.slice(0, 24)}` }, /* @__PURE__ */ React3.createElement(Text3, { color: "cyan" }, block.ordered ? ` ${block.start + i}. ` : " \u2022 "), /* @__PURE__ */ React3.createElement(InlineMd, { text: item, citations }))));
6013
6114
  case "code":
6014
- return /* @__PURE__ */ React2.createElement(Box2, { borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "yellow" }, block.text));
6115
+ return /* @__PURE__ */ React3.createElement(Box3, { borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: "yellow" }, block.text));
6015
6116
  case "edit-block":
6016
- return /* @__PURE__ */ React2.createElement(EditBlockRow, { block });
6117
+ return /* @__PURE__ */ React3.createElement(EditBlockRow, { block });
6017
6118
  case "table":
6018
- return /* @__PURE__ */ React2.createElement(TableBlockRow, { block, citations });
6119
+ return /* @__PURE__ */ React3.createElement(TableBlockRow, { block, citations });
6019
6120
  case "hr":
6020
- return /* @__PURE__ */ React2.createElement(Text2, { 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");
6121
+ return /* @__PURE__ */ React3.createElement(Text3, { 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");
6021
6122
  }
6022
6123
  }
6023
6124
  function splitTableRow(line) {
@@ -6035,14 +6136,14 @@ function TableBlockRow({ block, citations }) {
6035
6136
  widths.push(Math.min(40, Math.max(3, ...cellLengths)));
6036
6137
  }
6037
6138
  const separator = widths.map((w) => "\u2500".repeat(w)).join("\u2500\u253C\u2500");
6038
- return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column" }, /* @__PURE__ */ React2.createElement(Box2, null, block.header.map((cell, ci) => (
6139
+ return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Box3, null, block.header.map((cell, ci) => (
6039
6140
  // biome-ignore lint/suspicious/noArrayIndexKey: table columns never reorder — derived from a static header array
6040
- /* @__PURE__ */ React2.createElement(Text2, { key: `h-${ci}`, bold: true, color: "cyan" }, /* @__PURE__ */ React2.createElement(InlineMd, { text: cell, padTo: widths[ci] ?? 3, citations }), ci < colCount - 1 ? " \u2502 " : "")
6041
- ))), /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, separator), block.rows.map((row2, ri) => (
6141
+ /* @__PURE__ */ React3.createElement(Text3, { key: `h-${ci}`, bold: true, color: "cyan" }, /* @__PURE__ */ React3.createElement(InlineMd, { text: cell, padTo: widths[ci] ?? 3, citations }), ci < colCount - 1 ? " \u2502 " : "")
6142
+ ))), /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, separator), block.rows.map((row2, ri) => (
6042
6143
  // biome-ignore lint/suspicious/noArrayIndexKey: table rows render in source order and don't reorder
6043
- /* @__PURE__ */ React2.createElement(Box2, { key: `r-${ri}` }, Array.from({ length: colCount }).map((_, ci) => (
6144
+ /* @__PURE__ */ React3.createElement(Box3, { key: `r-${ri}` }, Array.from({ length: colCount }).map((_, ci) => (
6044
6145
  // biome-ignore lint/suspicious/noArrayIndexKey: same — column axis is fixed by the table shape
6045
- /* @__PURE__ */ React2.createElement(Text2, { key: `c-${ri}-${ci}` }, /* @__PURE__ */ React2.createElement(InlineMd, { text: row2[ci] ?? "", padTo: widths[ci] ?? 3, citations }), ci < colCount - 1 ? " \u2502 " : "")
6146
+ /* @__PURE__ */ React3.createElement(Text3, { key: `c-${ri}-${ci}` }, /* @__PURE__ */ React3.createElement(InlineMd, { text: row2[ci] ?? "", padTo: widths[ci] ?? 3, citations }), ci < colCount - 1 ? " \u2502 " : "")
6046
6147
  )))
6047
6148
  )));
6048
6149
  }
@@ -6062,28 +6163,28 @@ function EditBlockRow({ block }) {
6062
6163
  const isNewFile = block.search.length === 0;
6063
6164
  const searchLines = block.search.split("\n");
6064
6165
  const replaceLines = block.replace.split("\n");
6065
- return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React2.createElement(Box2, null, /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "cyan" }, block.filename), isNewFile ? /* @__PURE__ */ React2.createElement(Text2, { color: "green", bold: true }, " (new file)") : null), isNewFile ? null : /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", marginTop: 1 }, searchLines.map((line, i) => /* @__PURE__ */ React2.createElement(Text2, { key: `s-${i}-${line.length}`, color: "red" }, `- ${line}`))), /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", marginTop: isNewFile ? 1 : 0 }, replaceLines.map((line, i) => /* @__PURE__ */ React2.createElement(Text2, { key: `r-${i}-${line.length}`, color: "green" }, `+ ${line}`))));
6166
+ return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { bold: true, color: "cyan" }, block.filename), isNewFile ? /* @__PURE__ */ React3.createElement(Text3, { color: "green", bold: true }, " (new file)") : null), isNewFile ? null : /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", marginTop: 1 }, searchLines.map((line, i) => /* @__PURE__ */ React3.createElement(Text3, { key: `s-${i}-${line.length}`, color: "red" }, `- ${line}`))), /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", marginTop: isNewFile ? 1 : 0 }, replaceLines.map((line, i) => /* @__PURE__ */ React3.createElement(Text3, { key: `r-${i}-${line.length}`, color: "green" }, `+ ${line}`))));
6066
6167
  }
6067
6168
  function Markdown({ text, projectRoot }) {
6068
6169
  const cleaned = stripMath(text);
6069
6170
  const root = projectRoot ?? process.cwd();
6070
- const citations = React2.useMemo(() => collectCitations(cleaned, root), [cleaned, root]);
6071
- const blocks = React2.useMemo(() => parseBlocks(cleaned), [cleaned]);
6171
+ const citations = React3.useMemo(() => collectCitations(cleaned, root), [cleaned, root]);
6172
+ const blocks = React3.useMemo(() => parseBlocks(cleaned), [cleaned]);
6072
6173
  const broken = [];
6073
6174
  for (const [url, status] of citations) {
6074
6175
  if (!status.ok) broken.push({ url, reason: status.reason });
6075
6176
  }
6076
- return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", gap: 1 }, blocks.map((b, i) => /* @__PURE__ */ React2.createElement(BlockView, { key: `${i}-${b.kind}`, block: b, citations })), broken.length > 0 ? /* @__PURE__ */ React2.createElement(BrokenCitationsBlock, { items: broken }) : null);
6177
+ return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", gap: 1 }, blocks.map((b, i) => /* @__PURE__ */ React3.createElement(BlockView, { key: `${i}-${b.kind}`, block: b, citations })), broken.length > 0 ? /* @__PURE__ */ React3.createElement(BrokenCitationsBlock, { items: broken }) : null);
6077
6178
  }
6078
6179
  function BrokenCitationsBlock({ items }) {
6079
- return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 1 }, /* @__PURE__ */ React2.createElement(Text2, { 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) => (
6180
+ return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 1 }, /* @__PURE__ */ React3.createElement(Text3, { 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) => (
6080
6181
  // biome-ignore lint/suspicious/noArrayIndexKey: list is derived from a Map iteration order, stable per render
6081
- /* @__PURE__ */ React2.createElement(Text2, { key: `bc-${i}`, color: "red" }, ` \u2717 ${b.url} \u2192 ${b.reason}`)
6182
+ /* @__PURE__ */ React3.createElement(Text3, { key: `bc-${i}`, color: "red" }, ` \u2717 ${b.url} \u2192 ${b.reason}`)
6082
6183
  )));
6083
6184
  }
6084
6185
 
6085
6186
  // src/cli/ui/ticker.tsx
6086
- import React3, { createContext, useContext, useEffect, useState } from "react";
6187
+ import React4, { createContext, useContext, useEffect, useState } from "react";
6087
6188
  var TICK_MS = 120;
6088
6189
  var TickContext = createContext(0);
6089
6190
  function TickerProvider({ children, disabled }) {
@@ -6093,7 +6194,7 @@ function TickerProvider({ children, disabled }) {
6093
6194
  const id = setInterval(() => setTick((t) => t + 1), TICK_MS);
6094
6195
  return () => clearInterval(id);
6095
6196
  }, [disabled]);
6096
- return /* @__PURE__ */ React3.createElement(TickContext.Provider, { value: tick }, children);
6197
+ return /* @__PURE__ */ React4.createElement(TickContext.Provider, { value: tick }, children);
6097
6198
  }
6098
6199
  function useTick() {
6099
6200
  return useContext(TickContext);
@@ -6119,18 +6220,18 @@ function RoleGlyph({
6119
6220
  glyph,
6120
6221
  color
6121
6222
  }) {
6122
- return /* @__PURE__ */ React4.createElement(Text3, { color, bold: true }, glyph);
6223
+ return /* @__PURE__ */ React5.createElement(Text4, { color, bold: true }, glyph);
6123
6224
  }
6124
- var EventRow = React4.memo(function EventRow2({
6225
+ var EventRow = React5.memo(function EventRow2({
6125
6226
  event,
6126
6227
  projectRoot
6127
6228
  }) {
6128
6229
  if (event.role === "user") {
6129
- return /* @__PURE__ */ React4.createElement(Box3, { marginTop: event.leadSeparator ? 1 : 0 }, /* @__PURE__ */ React4.createElement(RoleGlyph, { glyph: ROLE_GLYPH.user, color: "cyan" }), /* @__PURE__ */ React4.createElement(Text3, null, " ", event.text));
6230
+ return /* @__PURE__ */ React5.createElement(Box4, { marginTop: event.leadSeparator ? 1 : 0 }, /* @__PURE__ */ React5.createElement(RoleGlyph, { glyph: ROLE_GLYPH.user, color: "cyan" }), /* @__PURE__ */ React5.createElement(Text4, null, " ", event.text));
6130
6231
  }
6131
6232
  if (event.role === "assistant") {
6132
- if (event.streaming) return /* @__PURE__ */ React4.createElement(StreamingAssistant, { event });
6133
- return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(RoleGlyph, { glyph: ROLE_GLYPH.assistant, color: "green" }), event.stats ? /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, ` ${event.stats.model}`) : null), /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", paddingLeft: 2, marginTop: 1 }, event.branch ? /* @__PURE__ */ React4.createElement(BranchBlock, { branch: event.branch }) : null, event.reasoning ? /* @__PURE__ */ React4.createElement(ReasoningBlock, { reasoning: event.reasoning }) : null, !isPlanStateEmpty(event.planState) ? /* @__PURE__ */ React4.createElement(PlanStateBlock, { planState: event.planState }) : null, event.text ? /* @__PURE__ */ React4.createElement(Markdown, { text: event.text, projectRoot }) : /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, "(no content)"), event.stats ? /* @__PURE__ */ React4.createElement(StatsLine, { stats: event.stats }) : null, event.repair ? /* @__PURE__ */ React4.createElement(Text3, { color: "magenta" }, event.repair) : null));
6233
+ if (event.streaming) return /* @__PURE__ */ React5.createElement(StreamingAssistant, { event });
6234
+ return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(RoleGlyph, { glyph: ROLE_GLYPH.assistant, color: "green" }), event.stats ? /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, ` ${event.stats.model}`) : null), /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column", paddingLeft: 2, marginTop: 1 }, event.branch ? /* @__PURE__ */ React5.createElement(BranchBlock, { branch: event.branch }) : null, event.reasoning ? /* @__PURE__ */ React5.createElement(ReasoningBlock, { reasoning: event.reasoning }) : null, !isPlanStateEmpty(event.planState) ? /* @__PURE__ */ React5.createElement(PlanStateBlock, { planState: event.planState }) : null, event.text ? /* @__PURE__ */ React5.createElement(Markdown, { text: event.text, projectRoot }) : /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, "(no content)"), event.stats ? /* @__PURE__ */ React5.createElement(StatsLine, { stats: event.stats }) : null, event.repair ? /* @__PURE__ */ React5.createElement(Text4, { color: "magenta" }, event.repair) : null));
6134
6235
  }
6135
6236
  if (event.role === "tool") {
6136
6237
  const isError = event.text.startsWith("ERROR:");
@@ -6138,31 +6239,31 @@ var EventRow = React4.memo(function EventRow2({
6138
6239
  const glyph = isError ? ROLE_GLYPH.toolErr : ROLE_GLYPH.toolOk;
6139
6240
  const marker = isError ? "\u2717" : "\u2192";
6140
6241
  const isEditFile = (event.toolName === "edit_file" || event.toolName?.endsWith("_edit_file")) && !isError;
6141
- return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(RoleGlyph, { glyph, color }), /* @__PURE__ */ React4.createElement(Text3, { color, bold: true }, ` ${event.toolName ?? "?"}`), /* @__PURE__ */ React4.createElement(Text3, { color, dimColor: true }, ` ${marker}`)), /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", paddingLeft: 2, marginTop: 1 }, isEditFile ? /* @__PURE__ */ React4.createElement(EditFileDiff, { text: event.text }) : /* @__PURE__ */ React4.createElement(Text3, { color: isError ? "red" : void 0, dimColor: !isError }, truncate2(event.text, 400))));
6242
+ return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(RoleGlyph, { glyph, color }), /* @__PURE__ */ React5.createElement(Text4, { color, bold: true }, ` ${event.toolName ?? "?"}`), /* @__PURE__ */ React5.createElement(Text4, { color, dimColor: true }, ` ${marker}`)), /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column", paddingLeft: 2, marginTop: 1 }, isEditFile ? /* @__PURE__ */ React5.createElement(EditFileDiff, { text: event.text }) : /* @__PURE__ */ React5.createElement(Text4, { color: isError ? "red" : void 0, dimColor: !isError }, truncate2(event.text, 400))));
6142
6243
  }
6143
6244
  if (event.role === "error") {
6144
- return /* @__PURE__ */ React4.createElement(Box3, { marginTop: 1 }, /* @__PURE__ */ React4.createElement(RoleGlyph, { glyph: ROLE_GLYPH.error, color: "red" }), /* @__PURE__ */ React4.createElement(Text3, { color: "red" }, " ", event.text));
6245
+ return /* @__PURE__ */ React5.createElement(Box4, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(RoleGlyph, { glyph: ROLE_GLYPH.error, color: "red" }), /* @__PURE__ */ React5.createElement(Text4, { color: "red" }, " ", event.text));
6145
6246
  }
6146
6247
  if (event.role === "info") {
6147
- return /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, event.text));
6248
+ return /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, event.text));
6148
6249
  }
6149
6250
  if (event.role === "warning") {
6150
- return /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(RoleGlyph, { glyph: ROLE_GLYPH.warning, color: "yellow" }), /* @__PURE__ */ React4.createElement(Text3, { color: "yellow" }, " ", event.text));
6251
+ return /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(RoleGlyph, { glyph: ROLE_GLYPH.warning, color: "yellow" }), /* @__PURE__ */ React5.createElement(Text4, { color: "yellow" }, " ", event.text));
6151
6252
  }
6152
- return /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(Text3, null, event.text));
6253
+ return /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text4, null, event.text));
6153
6254
  });
6154
6255
  function EditFileDiff({ text }) {
6155
6256
  const lines = text.split(/\r?\n/);
6156
6257
  const [statusHeader, hunkHeader, ...body] = lines;
6157
- return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, ` ${statusHeader ?? ""}`), hunkHeader !== void 0 ? /* @__PURE__ */ React4.createElement(Text3, { color: "cyan", bold: true }, hunkHeader) : null, body.map((line, i) => {
6258
+ return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, ` ${statusHeader ?? ""}`), hunkHeader !== void 0 ? /* @__PURE__ */ React5.createElement(Text4, { color: "cyan", bold: true }, hunkHeader) : null, body.map((line, i) => {
6158
6259
  const key = `${i}-${line.slice(0, 32)}`;
6159
6260
  if (line.startsWith("- ")) {
6160
- return /* @__PURE__ */ React4.createElement(Text3, { key, color: "red" }, line);
6261
+ return /* @__PURE__ */ React5.createElement(Text4, { key, color: "red" }, line);
6161
6262
  }
6162
6263
  if (line.startsWith("+ ")) {
6163
- return /* @__PURE__ */ React4.createElement(Text3, { key, color: "green" }, line);
6264
+ return /* @__PURE__ */ React5.createElement(Text4, { key, color: "green" }, line);
6164
6265
  }
6165
- return /* @__PURE__ */ React4.createElement(Text3, { key, dimColor: true }, line);
6266
+ return /* @__PURE__ */ React5.createElement(Text4, { key, dimColor: true }, line);
6166
6267
  }));
6167
6268
  }
6168
6269
  function BranchBlock({ branch }) {
@@ -6171,33 +6272,33 @@ function BranchBlock({ branch }) {
6171
6272
  const t = (branch.temperatures[i] ?? 0).toFixed(1);
6172
6273
  return `${marker} #${i} T=${t} u=${u}`;
6173
6274
  }).join(" ");
6174
- return /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(Text3, { color: "blue" }, "\u2387 branched ", /* @__PURE__ */ React4.createElement(Text3, { bold: true }, branch.budget), ` samples \u2192 picked #${branch.chosenIndex} `, /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, per)));
6275
+ return /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text4, { color: "blue" }, "\u2387 branched ", /* @__PURE__ */ React5.createElement(Text4, { bold: true }, branch.budget), ` samples \u2192 picked #${branch.chosenIndex} `, /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, per)));
6175
6276
  }
6176
6277
  function ReasoningBlock({ reasoning }) {
6177
6278
  const max = 260;
6178
6279
  const flat = reasoning.replace(/\s+/g, " ").trim();
6179
6280
  const preview = flat.length <= max ? flat : `\u2026 (+${flat.length - max} earlier chars) ${flat.slice(-max)}`;
6180
- return /* @__PURE__ */ React4.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, "\u258F "), /* @__PURE__ */ React4.createElement(Text3, { dimColor: true, italic: true }, "thinking ", preview));
6281
+ return /* @__PURE__ */ React5.createElement(Box4, { marginBottom: 1 }, /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, "\u258F "), /* @__PURE__ */ React5.createElement(Text4, { dimColor: true, italic: true }, "thinking ", preview));
6181
6282
  }
6182
6283
  function Elapsed() {
6183
6284
  const s = useElapsedSeconds();
6184
6285
  const mm = String(Math.floor(s / 60)).padStart(2, "0");
6185
6286
  const ss = String(s % 60).padStart(2, "0");
6186
- return /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, `${mm}:${ss}`);
6287
+ return /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, `${mm}:${ss}`);
6187
6288
  }
6188
6289
  function PulsingAssistantGlyph() {
6189
6290
  const tick = useTick();
6190
6291
  const on = Math.floor(tick / 4) % 2 === 0;
6191
- return /* @__PURE__ */ React4.createElement(Text3, { color: "green", bold: true }, on ? ROLE_GLYPH.assistant : ROLE_GLYPH.assistantPulse);
6292
+ return /* @__PURE__ */ React5.createElement(Text4, { color: "green", bold: true }, on ? ROLE_GLYPH.assistant : ROLE_GLYPH.assistantPulse);
6192
6293
  }
6193
6294
  function StreamingAssistant({ event }) {
6194
6295
  if (event.branchProgress) {
6195
6296
  const p = event.branchProgress;
6196
6297
  if (p.completed === 0) {
6197
- return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React4.createElement(Text3, { color: "blue" }, " \u2387 launching ", p.total, " parallel samples (R1 thinking in parallel)\u2026 "), /* @__PURE__ */ React4.createElement(Elapsed, null)), /* @__PURE__ */ React4.createElement(Text3, { color: "yellow" }, " ", "spread across T=0.0/0.5/1.0 \xB7 reasoner typically takes 30-90s \u2014 this is normal"));
6298
+ return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React5.createElement(Text4, { color: "blue" }, " \u2387 launching ", p.total, " parallel samples (R1 thinking in parallel)\u2026 "), /* @__PURE__ */ React5.createElement(Elapsed, null)), /* @__PURE__ */ React5.createElement(Text4, { color: "yellow" }, " ", "spread across T=0.0/0.5/1.0 \xB7 reasoner typically takes 30-90s \u2014 this is normal"));
6198
6299
  }
6199
6300
  const pct2 = Math.round(p.completed / p.total * 100);
6200
- return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React4.createElement(Text3, { color: "blue" }, " \u2387 branching ", p.completed, "/", p.total, " (", pct2, "%) "), /* @__PURE__ */ React4.createElement(Elapsed, null)), /* @__PURE__ */ React4.createElement(Text3, { 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"));
6301
+ return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React5.createElement(Text4, { color: "blue" }, " \u2387 branching ", p.completed, "/", p.total, " (", pct2, "%) "), /* @__PURE__ */ React5.createElement(Elapsed, null)), /* @__PURE__ */ React5.createElement(Text4, { 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"));
6201
6302
  }
6202
6303
  const tail = lastLine(event.text, 140);
6203
6304
  const reasoningTail = event.reasoning ? lastLine(event.reasoning, 120) : "";
@@ -6225,16 +6326,16 @@ function StreamingAssistant({ event }) {
6225
6326
  label = parts.join(" \xB7 ");
6226
6327
  labelColor = "green";
6227
6328
  }
6228
- return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React4.createElement(Text3, null, " "), /* @__PURE__ */ React4.createElement(Pulse, null), /* @__PURE__ */ React4.createElement(Text3, { color: labelColor }, ` ${label} `), /* @__PURE__ */ React4.createElement(Elapsed, null)), reasoningTail ? /* @__PURE__ */ React4.createElement(Text3, { dimColor: true, italic: true }, "\u21B3 thinking: ", reasoningTail) : null, tail ? /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, "\u25B8 ", tail) : preFirstByte ? (
6329
+ return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(PulsingAssistantGlyph, null), /* @__PURE__ */ React5.createElement(Text4, null, " "), /* @__PURE__ */ React5.createElement(Pulse, null), /* @__PURE__ */ React5.createElement(Text4, { color: labelColor }, ` ${label} `), /* @__PURE__ */ React5.createElement(Elapsed, null)), reasoningTail ? /* @__PURE__ */ React5.createElement(Text4, { dimColor: true, italic: true }, "\u21B3 thinking: ", reasoningTail) : null, tail ? /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, "\u25B8 ", tail) : preFirstByte ? (
6229
6330
  // Non-dim yellow: first-time users misread the dim version as
6230
6331
  // "app frozen". The reassurance has to be VISIBLE to do its job.
6231
- /* @__PURE__ */ React4.createElement(Text3, { color: "yellow", italic: true }, " waiting for first byte \u2014 this is normal, typically 5-60s depending on model + load")
6232
- ) : reasoningOnly ? /* @__PURE__ */ React4.createElement(Text3, { color: "yellow", italic: true }, " R1 is thinking before it speaks \u2014 body text arrives when reasoning finishes (typically 20-90s, this is normal)") : toolCallOnly ? /* @__PURE__ */ React4.createElement(Text3, { color: "magenta", italic: true }, " tool-call arguments streaming \u2014 the model is about to dispatch a tool") : event.reasoning ? /* @__PURE__ */ React4.createElement(Text3, { color: "yellow", italic: true }, " R1 still reasoning \u2014 body text or tool call arrives when thinking finishes") : null);
6332
+ /* @__PURE__ */ React5.createElement(Text4, { color: "yellow", italic: true }, " waiting for first byte \u2014 this is normal, typically 5-60s depending on model + load")
6333
+ ) : reasoningOnly ? /* @__PURE__ */ React5.createElement(Text4, { color: "yellow", italic: true }, " R1 is thinking before it speaks \u2014 body text arrives when reasoning finishes (typically 20-90s, this is normal)") : toolCallOnly ? /* @__PURE__ */ React5.createElement(Text4, { color: "magenta", italic: true }, " tool-call arguments streaming \u2014 the model is about to dispatch a tool") : event.reasoning ? /* @__PURE__ */ React5.createElement(Text4, { color: "yellow", italic: true }, " R1 still reasoning \u2014 body text or tool call arrives when thinking finishes") : null);
6233
6334
  }
6234
6335
  function Pulse() {
6235
6336
  const tick = useTick();
6236
6337
  const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
6237
- return /* @__PURE__ */ React4.createElement(Text3, { color: "cyan" }, frames[Math.floor(tick / 4) % frames.length]);
6338
+ return /* @__PURE__ */ React5.createElement(Text4, { color: "cyan" }, frames[Math.floor(tick / 4) % frames.length]);
6238
6339
  }
6239
6340
  function lastLine(s, maxChars) {
6240
6341
  const flat = s.replace(/\s+/g, " ").trim();
@@ -6243,7 +6344,7 @@ function lastLine(s, maxChars) {
6243
6344
  }
6244
6345
  function StatsLine({ stats }) {
6245
6346
  const hit = (stats.cacheHitRatio * 100).toFixed(1);
6246
- return /* @__PURE__ */ React4.createElement(Box3, null, /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, "\u258F "), /* @__PURE__ */ React4.createElement(Text3, { dimColor: true }, "cache ", hit, "% \xB7 tokens ", stats.usage.promptTokens, " \u2192 ", stats.usage.completionTokens, " \xB7 $", stats.cost.toFixed(6)));
6347
+ return /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, "\u258F "), /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, "cache ", hit, "% \xB7 tokens ", stats.usage.promptTokens, " \u2192 ", stats.usage.completionTokens, " \xB7 $", stats.cost.toFixed(6)));
6247
6348
  }
6248
6349
  function truncate2(s, max) {
6249
6350
  if (s.length <= max) return s;
@@ -6266,12 +6367,12 @@ ${s.slice(-max)}`;
6266
6367
  }
6267
6368
 
6268
6369
  // src/cli/ui/PlanConfirm.tsx
6269
- import { Box as Box5, Text as Text5 } from "ink";
6270
- import React6 from "react";
6370
+ import { Box as Box6, Text as Text6 } from "ink";
6371
+ import React7 from "react";
6271
6372
 
6272
6373
  // src/cli/ui/Select.tsx
6273
- import { Box as Box4, Text as Text4, useInput } from "ink";
6274
- import React5, { useState as useState2 } from "react";
6374
+ import { Box as Box5, Text as Text5, useInput } from "ink";
6375
+ import React6, { useState as useState2 } from "react";
6275
6376
  function SingleSelect({
6276
6377
  items,
6277
6378
  initialValue,
@@ -6296,7 +6397,7 @@ function SingleSelect({
6296
6397
  onCancel();
6297
6398
  }
6298
6399
  });
6299
- return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column" }, items.map((item, i) => /* @__PURE__ */ React5.createElement(
6400
+ return /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column" }, items.map((item, i) => /* @__PURE__ */ React6.createElement(
6300
6401
  SelectRow,
6301
6402
  {
6302
6403
  key: item.value,
@@ -6304,7 +6405,7 @@ function SingleSelect({
6304
6405
  active: i === index,
6305
6406
  marker: i === index ? "\u25B8" : " "
6306
6407
  }
6307
- )), footer ? /* @__PURE__ */ React5.createElement(Box4, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, footer)) : null);
6408
+ )), footer ? /* @__PURE__ */ React6.createElement(Box5, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text5, { dimColor: true }, footer)) : null);
6308
6409
  }
6309
6410
  function MultiSelect({
6310
6411
  items,
@@ -6339,10 +6440,10 @@ function MultiSelect({
6339
6440
  onCancel();
6340
6441
  }
6341
6442
  });
6342
- return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column" }, items.map((item, i) => {
6443
+ return /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column" }, items.map((item, i) => {
6343
6444
  const checked = selected.has(item.value);
6344
6445
  const marker = checked ? "[x]" : "[ ]";
6345
- return /* @__PURE__ */ React5.createElement(
6446
+ return /* @__PURE__ */ React6.createElement(
6346
6447
  SelectRow,
6347
6448
  {
6348
6449
  key: item.value,
@@ -6351,7 +6452,7 @@ function MultiSelect({
6351
6452
  marker: `${i === index ? "\u25B8" : " "} ${marker}`
6352
6453
  }
6353
6454
  );
6354
- }), footer ? /* @__PURE__ */ React5.createElement(Box4, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, footer)) : null);
6455
+ }), footer ? /* @__PURE__ */ React6.createElement(Box5, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text5, { dimColor: true }, footer)) : null);
6355
6456
  }
6356
6457
  function SelectRow({
6357
6458
  item,
@@ -6359,7 +6460,7 @@ function SelectRow({
6359
6460
  marker
6360
6461
  }) {
6361
6462
  const color = item.disabled ? "gray" : active ? "cyan" : void 0;
6362
- return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text4, { color }, marker, " ", item.label)), item.hint ? /* @__PURE__ */ React5.createElement(Box4, { paddingLeft: marker.length + 1 }, /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, item.hint)) : null);
6463
+ return /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text5, { color }, marker, " ", item.label)), item.hint ? /* @__PURE__ */ React6.createElement(Box5, { paddingLeft: marker.length + 1 }, /* @__PURE__ */ React6.createElement(Text5, { dimColor: true }, item.hint)) : null);
6363
6464
  }
6364
6465
  function findNextEnabled(items, from, step) {
6365
6466
  if (items.length === 0) return 0;
@@ -6380,7 +6481,7 @@ function PlanConfirm({ plan, onChoose, maxRenderedChars, projectRoot }) {
6380
6481
 
6381
6482
  \u2026 (${plan.length - cap} chars truncated \u2014 use /tool to view the full proposal)` : plan;
6382
6483
  const hasOpenQuestions = /^#{1,6}\s*(open[-\s]?questions?|risks?|unknowns?|assumptions?|unclear)/im.test(plan) || /^#{1,6}\s*(待确认|开放问题|风险|未知|假设|不确定)/im.test(plan);
6383
- return /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text5, { bold: true, color: "cyan" }, "\u25B8 plan submitted \u2014 awaiting your review")), /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text5, { color: "cyan", 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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")), /* @__PURE__ */ React6.createElement(Box5, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Markdown, { text: visible, projectRoot })), hasOpenQuestions ? /* @__PURE__ */ React6.createElement(Box5, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text5, { color: "yellow" }, "\u25B2 the plan has open questions or flagged risks \u2014 pick", " ", /* @__PURE__ */ React6.createElement(Text5, { bold: true }, "Refine / answer questions"), " to write concrete answers before the model moves on.")) : null, /* @__PURE__ */ React6.createElement(Box5, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(
6484
+ return /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React7.createElement(Box6, null, /* @__PURE__ */ React7.createElement(Text6, { bold: true, color: "cyan" }, "\u25B8 plan submitted \u2014 awaiting your review")), /* @__PURE__ */ React7.createElement(Box6, null, /* @__PURE__ */ React7.createElement(Text6, { color: "cyan", 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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")), /* @__PURE__ */ React7.createElement(Box6, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React7.createElement(Markdown, { text: visible, projectRoot })), hasOpenQuestions ? /* @__PURE__ */ React7.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React7.createElement(Text6, { color: "yellow" }, "\u25B2 the plan has open questions or flagged risks \u2014 pick", " ", /* @__PURE__ */ React7.createElement(Text6, { bold: true }, "Refine / answer questions"), " to write concrete answers before the model moves on.")) : null, /* @__PURE__ */ React7.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React7.createElement(
6384
6485
  SingleSelect,
6385
6486
  {
6386
6487
  initialValue: hasOpenQuestions ? "refine" : "approve",
@@ -6409,8 +6510,8 @@ function PlanConfirm({ plan, onChoose, maxRenderedChars, projectRoot }) {
6409
6510
  }
6410
6511
 
6411
6512
  // src/cli/ui/PlanRefineInput.tsx
6412
- import { Box as Box6, Text as Text6, useInput as useInput2 } from "ink";
6413
- import React7, { useState as useState3 } from "react";
6513
+ import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
6514
+ import React8, { useState as useState3 } from "react";
6414
6515
  function PlanRefineInput({ mode, onSubmit, onCancel }) {
6415
6516
  const [value, setValue] = useState3("");
6416
6517
  useInput2((input, key) => {
@@ -6433,12 +6534,12 @@ function PlanRefineInput({ mode, onSubmit, onCancel }) {
6433
6534
  const title = mode === "approve" ? "\u25B8 approving \u2014 any last instructions or answers to open questions?" : "\u25B8 refining \u2014 what should the model change?";
6434
6535
  const hint = mode === "approve" ? "Answer questions the plan raised, add constraints, or just press Enter to approve as-is." : "Describe what's wrong or missing, or answer questions the plan raised.";
6435
6536
  const blankHint = mode === "approve" ? " (Enter with blank = approve without extra instructions.)" : " (Enter with blank = ask the model to list concrete questions.)";
6436
- return /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React7.createElement(Box6, null, /* @__PURE__ */ React7.createElement(Text6, { bold: true, color: "yellow" }, title)), /* @__PURE__ */ React7.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React7.createElement(Text6, { dimColor: true }, hint, " Enter to send \xB7 Esc to return to the picker.", value === "" ? blankHint : "")), /* @__PURE__ */ React7.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React7.createElement(Text6, null, /* @__PURE__ */ React7.createElement(Text6, { color: "yellow" }, "\u203A "), /* @__PURE__ */ React7.createElement(Text6, null, value || " "), /* @__PURE__ */ React7.createElement(Text6, { color: "yellow" }, "\u258D"))));
6537
+ return /* @__PURE__ */ React8.createElement(Box7, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React8.createElement(Box7, null, /* @__PURE__ */ React8.createElement(Text7, { bold: true, color: "yellow" }, title)), /* @__PURE__ */ React8.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, hint, " Enter to send \xB7 Esc to return to the picker.", value === "" ? blankHint : "")), /* @__PURE__ */ React8.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text7, null, /* @__PURE__ */ React8.createElement(Text7, { color: "yellow" }, "\u203A "), /* @__PURE__ */ React8.createElement(Text7, null, value || " "), /* @__PURE__ */ React8.createElement(Text7, { color: "yellow" }, "\u258D"))));
6437
6538
  }
6438
6539
 
6439
6540
  // src/cli/ui/PromptInput.tsx
6440
- import { Box as Box7, Text as Text7, useInput as useInput3 } from "ink";
6441
- import React8, { useRef, useState as useState4 } from "react";
6541
+ import { Box as Box8, Text as Text8, useInput as useInput3 } from "ink";
6542
+ import React9, { useRef, useState as useState4 } from "react";
6442
6543
 
6443
6544
  // src/cli/ui/multiline-keys.ts
6444
6545
  var BACKSLASH_SUFFIX = /\\$/;
@@ -6598,13 +6699,13 @@ function PromptInput({
6598
6699
  const lines = value.length > 0 ? value.split("\n") : [""];
6599
6700
  const borderColor = disabled ? "gray" : "cyan";
6600
6701
  const { line: cursorLine, col: cursorCol } = lineAndColumn(value, cursor);
6601
- return /* @__PURE__ */ React8.createElement(Box7, { borderStyle: "round", borderColor, paddingX: 1, flexDirection: "column" }, lines.map((line, i) => {
6702
+ return /* @__PURE__ */ React9.createElement(Box8, { borderStyle: "round", borderColor, paddingX: 1, flexDirection: "column" }, lines.map((line, i) => {
6602
6703
  const isFirst = i === 0;
6603
6704
  const showPlaceholder = isFirst && value.length === 0;
6604
6705
  const isCursorLine = i === cursorLine;
6605
6706
  return (
6606
6707
  // biome-ignore lint/suspicious/noArrayIndexKey: stable by construction — lines are derived from `value.split("\n")` and never reordered
6607
- /* @__PURE__ */ React8.createElement(Box7, { key: i }, isFirst ? /* @__PURE__ */ React8.createElement(Text7, { bold: true, color: borderColor }, "you \u203A", " ") : /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, " "), showPlaceholder ? /* @__PURE__ */ React8.createElement(React8.Fragment, null, isCursorLine && !disabled ? /* @__PURE__ */ React8.createElement(Text7, { color: borderColor }, showCursor ? "\u258C" : " ") : null, /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, effectivePlaceholder)) : isCursorLine && !disabled ? /* @__PURE__ */ React8.createElement(
6708
+ /* @__PURE__ */ React9.createElement(Box8, { key: i }, isFirst ? /* @__PURE__ */ React9.createElement(Text8, { bold: true, color: borderColor }, "you \u203A", " ") : /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, " "), showPlaceholder ? /* @__PURE__ */ React9.createElement(React9.Fragment, null, isCursorLine && !disabled ? /* @__PURE__ */ React9.createElement(Text8, { color: borderColor }, showCursor ? "\u258C" : " ") : null, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, effectivePlaceholder)) : isCursorLine && !disabled ? /* @__PURE__ */ React9.createElement(
6608
6709
  LineWithCursor,
6609
6710
  {
6610
6711
  line,
@@ -6612,7 +6713,7 @@ function PromptInput({
6612
6713
  showCursor,
6613
6714
  borderColor
6614
6715
  }
6615
- ) : /* @__PURE__ */ React8.createElement(Text7, null, line))
6716
+ ) : /* @__PURE__ */ React9.createElement(Text8, null, line))
6616
6717
  );
6617
6718
  }));
6618
6719
  }
@@ -6626,16 +6727,16 @@ function LineWithCursor({
6626
6727
  const atCursor = line.slice(col, col + 1);
6627
6728
  const after = line.slice(col + 1);
6628
6729
  if (atCursor.length === 0) {
6629
- return /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(Text7, null, before), /* @__PURE__ */ React8.createElement(Text7, { color: borderColor }, showCursor ? "\u258C" : " "));
6730
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(Text8, null, before), /* @__PURE__ */ React9.createElement(Text8, { color: borderColor }, showCursor ? "\u258C" : " "));
6630
6731
  }
6631
- return /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(Text7, null, before), /* @__PURE__ */ React8.createElement(Text7, { inverse: showCursor }, atCursor), /* @__PURE__ */ React8.createElement(Text7, null, after));
6732
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(Text8, null, before), /* @__PURE__ */ React9.createElement(Text8, { inverse: showCursor }, atCursor), /* @__PURE__ */ React9.createElement(Text8, null, after));
6632
6733
  }
6633
6734
 
6634
6735
  // src/cli/ui/ShellConfirm.tsx
6635
- import { Box as Box8, Text as Text8 } from "ink";
6636
- import React9 from "react";
6736
+ import { Box as Box9, Text as Text9 } from "ink";
6737
+ import React10 from "react";
6637
6738
  function ShellConfirm({ command, allowPrefix, onChoose }) {
6638
- return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React9.createElement(Box8, null, /* @__PURE__ */ React9.createElement(Text8, { bold: true, color: "yellow" }, "\u25B8 model wants to run a shell command")), /* @__PURE__ */ React9.createElement(Box8, null, /* @__PURE__ */ React9.createElement(Text8, { color: "yellow", 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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")), /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text8, null, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, "$ "), /* @__PURE__ */ React9.createElement(Text8, { color: "cyan" }, command))), /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(
6739
+ return /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React10.createElement(Box9, null, /* @__PURE__ */ React10.createElement(Text9, { bold: true, color: "yellow" }, "\u25B8 model wants to run a shell command")), /* @__PURE__ */ React10.createElement(Box9, null, /* @__PURE__ */ React10.createElement(Text9, { color: "yellow", 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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")), /* @__PURE__ */ React10.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text9, null, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, "$ "), /* @__PURE__ */ React10.createElement(Text9, { color: "cyan" }, command))), /* @__PURE__ */ React10.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
6639
6740
  SingleSelect,
6640
6741
  {
6641
6742
  initialValue: "run_once",
@@ -6692,15 +6793,15 @@ function derivePrefix(command) {
6692
6793
  }
6693
6794
 
6694
6795
  // src/cli/ui/SlashSuggestions.tsx
6695
- import { Box as Box9, Text as Text9 } from "ink";
6696
- import React10 from "react";
6796
+ import { Box as Box10, Text as Text10 } from "ink";
6797
+ import React11 from "react";
6697
6798
  function SlashSuggestions({
6698
6799
  matches,
6699
6800
  selectedIndex
6700
6801
  }) {
6701
6802
  if (matches === null) return null;
6702
6803
  if (matches.length === 0) {
6703
- return /* @__PURE__ */ React10.createElement(Box9, { paddingX: 1 }, /* @__PURE__ */ React10.createElement(Text9, { color: "yellow" }, "no slash command matches that prefix"), /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, " \u2014 Backspace to edit, or /help for the full list"));
6804
+ return /* @__PURE__ */ React11.createElement(Box10, { paddingX: 1 }, /* @__PURE__ */ React11.createElement(Text10, { color: "yellow" }, "no slash command matches that prefix"), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " \u2014 Backspace to edit, or /help for the full list"));
6704
6805
  }
6705
6806
  const MAX = 8;
6706
6807
  const total = matches.length;
@@ -6708,21 +6809,21 @@ function SlashSuggestions({
6708
6809
  const shown = matches.slice(windowStart, windowStart + MAX);
6709
6810
  const hiddenAbove = windowStart;
6710
6811
  const hiddenBelow = total - windowStart - shown.length;
6711
- return /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "column", paddingX: 1 }, hiddenAbove > 0 ? /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, " \u2191 ", hiddenAbove, " more above") : null, shown.map((spec, i) => /* @__PURE__ */ React10.createElement(SuggestionRow, { key: spec.cmd, spec, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, " \u2193 ", hiddenBelow, " more below") : null, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, " [\u2191\u2193] navigate \xB7 [Tab]/[Enter] pick"));
6812
+ return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column", paddingX: 1 }, hiddenAbove > 0 ? /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " \u2191 ", hiddenAbove, " more above") : null, shown.map((spec, i) => /* @__PURE__ */ React11.createElement(SuggestionRow, { key: spec.cmd, spec, isSelected: windowStart + i === selectedIndex })), hiddenBelow > 0 ? /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " \u2193 ", hiddenBelow, " more below") : null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " [\u2191\u2193] navigate \xB7 [Tab]/[Enter] pick"));
6712
6813
  }
6713
6814
  function SuggestionRow({ spec, isSelected }) {
6714
6815
  const marker = isSelected ? "\u25B8" : " ";
6715
6816
  const name = `/${spec.cmd}`;
6716
6817
  const argsSuffix = spec.argsHint ? ` ${spec.argsHint}` : "";
6717
6818
  if (isSelected) {
6718
- return /* @__PURE__ */ React10.createElement(Box9, null, /* @__PURE__ */ React10.createElement(Text9, { bold: true, color: "cyan" }, marker, " ", name.padEnd(12), argsSuffix.padEnd(16)), /* @__PURE__ */ React10.createElement(Text9, { color: "cyan" }, " ", spec.summary));
6819
+ return /* @__PURE__ */ React11.createElement(Box10, null, /* @__PURE__ */ React11.createElement(Text10, { bold: true, color: "cyan" }, marker, " ", name.padEnd(12), argsSuffix.padEnd(16)), /* @__PURE__ */ React11.createElement(Text10, { color: "cyan" }, " ", spec.summary));
6719
6820
  }
6720
- return /* @__PURE__ */ React10.createElement(Box9, null, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, marker, " ", name.padEnd(12), argsSuffix.padEnd(16), " ", spec.summary));
6821
+ return /* @__PURE__ */ React11.createElement(Box10, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, marker, " ", name.padEnd(12), argsSuffix.padEnd(16), " ", spec.summary));
6721
6822
  }
6722
6823
 
6723
6824
  // src/cli/ui/StatsPanel.tsx
6724
- import { Box as Box10, Text as Text10, useStdout as useStdout2 } from "ink";
6725
- import React11 from "react";
6825
+ import { Box as Box11, Text as Text11, useStdout as useStdout2 } from "ink";
6826
+ import React12 from "react";
6726
6827
  var WORDMARK_STYLES = [
6727
6828
  { ch: "\u25C8", color: "#5eead4", isLogo: true },
6728
6829
  // teal — brand mark
@@ -6748,7 +6849,7 @@ function Wordmark({ busy }) {
6748
6849
  const tick = useTick();
6749
6850
  const period = busy ? 5 : 12;
6750
6851
  const bright = Math.floor(tick / period) % 2 === 0;
6751
- return /* @__PURE__ */ React11.createElement(Text10, null, WORDMARK_STYLES.map((c) => /* @__PURE__ */ React11.createElement(Text10, { key: `${c.ch}-${c.color}`, color: c.color, bold: c.isLogo ? bright : true }, c.ch)));
6852
+ return /* @__PURE__ */ React12.createElement(Text11, null, WORDMARK_STYLES.map((c) => /* @__PURE__ */ React12.createElement(Text11, { key: `${c.ch}-${c.color}`, color: c.color, bold: c.isLogo ? bright : true }, c.ch)));
6752
6853
  }
6753
6854
  var NARROW_BREAKPOINT = 120;
6754
6855
  var COLD_START_TURNS = 3;
@@ -6770,7 +6871,7 @@ function StatsPanel({
6770
6871
  const columns = stdout2?.columns ?? 80;
6771
6872
  const narrow = columns < NARROW_BREAKPOINT;
6772
6873
  const coldStart = summary.turns <= COLD_START_TURNS;
6773
- return /* @__PURE__ */ React11.createElement(Box10, { borderStyle: "round", borderColor: "cyan", flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React11.createElement(
6874
+ return /* @__PURE__ */ React12.createElement(Box11, { borderStyle: "round", borderColor: "cyan", flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React12.createElement(
6774
6875
  Header,
6775
6876
  {
6776
6877
  model,
@@ -6784,7 +6885,7 @@ function StatsPanel({
6784
6885
  narrow,
6785
6886
  busy: busy ?? false
6786
6887
  }
6787
- ), narrow ? /* @__PURE__ */ React11.createElement(
6888
+ ), narrow ? /* @__PURE__ */ React12.createElement(
6788
6889
  StackedMetrics,
6789
6890
  {
6790
6891
  summary,
@@ -6793,7 +6894,7 @@ function StatsPanel({
6793
6894
  balance,
6794
6895
  coldStart
6795
6896
  }
6796
- ) : /* @__PURE__ */ React11.createElement(
6897
+ ) : /* @__PURE__ */ React12.createElement(
6797
6898
  InlineMetrics,
6798
6899
  {
6799
6900
  summary,
@@ -6816,7 +6917,7 @@ function Header({
6816
6917
  narrow,
6817
6918
  busy
6818
6919
  }) {
6819
- return /* @__PURE__ */ React11.createElement(Box10, { justifyContent: "space-between" }, /* @__PURE__ */ React11.createElement(Box10, null, /* @__PURE__ */ React11.createElement(Wordmark, { busy }), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, ` v${VERSION}`), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React11.createElement(Text10, { color: "yellow" }, model), narrow ? null : /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, prefixHash)), harvestOn ? /* @__PURE__ */ React11.createElement(Text10, { color: "magenta" }, " \xB7 harvest") : null, branchOn ? /* @__PURE__ */ React11.createElement(Text10, { color: "blue" }, " \xB7 branch", branchBudget) : null, planMode ? /* @__PURE__ */ React11.createElement(Text10, { color: "red", bold: true }, " \xB7 PLAN") : null), /* @__PURE__ */ React11.createElement(Text10, null, updateAvailable ? /* @__PURE__ */ React11.createElement(Text10, { color: "yellow", bold: true }, `update: ${updateAvailable} \xB7 `) : null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, narrow ? `turn ${turns}` : `turn ${turns} \xB7 /help`)));
6920
+ return /* @__PURE__ */ React12.createElement(Box11, { justifyContent: "space-between" }, /* @__PURE__ */ React12.createElement(Box11, null, /* @__PURE__ */ React12.createElement(Wordmark, { busy }), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, ` v${VERSION}`), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React12.createElement(Text11, { color: "yellow" }, model), narrow ? null : /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, prefixHash)), harvestOn ? /* @__PURE__ */ React12.createElement(Text11, { color: "magenta" }, " \xB7 harvest") : null, branchOn ? /* @__PURE__ */ React12.createElement(Text11, { color: "blue" }, " \xB7 branch", branchBudget) : null, planMode ? /* @__PURE__ */ React12.createElement(Text11, { color: "red", bold: true }, " \xB7 PLAN") : null), /* @__PURE__ */ React12.createElement(Text11, null, updateAvailable ? /* @__PURE__ */ React12.createElement(Text11, { color: "yellow", bold: true }, `update: ${updateAvailable} \xB7 `) : null, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, narrow ? `turn ${turns}` : `turn ${turns} \xB7 /help`)));
6820
6921
  }
6821
6922
  function InlineMetrics({
6822
6923
  summary,
@@ -6825,7 +6926,7 @@ function InlineMetrics({
6825
6926
  balance,
6826
6927
  coldStart
6827
6928
  }) {
6828
- return /* @__PURE__ */ React11.createElement(Box10, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React11.createElement(ContextCell, { ratio: ctxRatio, promptTokens: summary.lastPromptTokens, ctxMax }), /* @__PURE__ */ React11.createElement(CacheCell, { hitRatio: summary.cacheHitRatio, coldStart, turns: summary.turns }), /* @__PURE__ */ React11.createElement(CostCell, { summary, coldStart }), balance ? /* @__PURE__ */ React11.createElement(BalanceCell, { balance }) : null);
6929
+ return /* @__PURE__ */ React12.createElement(Box11, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React12.createElement(ContextCell, { ratio: ctxRatio, promptTokens: summary.lastPromptTokens, ctxMax }), /* @__PURE__ */ React12.createElement(CacheCell, { hitRatio: summary.cacheHitRatio, coldStart, turns: summary.turns }), /* @__PURE__ */ React12.createElement(CostCell, { summary, coldStart }), balance ? /* @__PURE__ */ React12.createElement(BalanceCell, { balance }) : null);
6829
6930
  }
6830
6931
  function StackedMetrics({
6831
6932
  summary,
@@ -6834,7 +6935,7 @@ function StackedMetrics({
6834
6935
  balance,
6835
6936
  coldStart
6836
6937
  }) {
6837
- return /* @__PURE__ */ React11.createElement(Box10, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React11.createElement(
6938
+ return /* @__PURE__ */ React12.createElement(Box11, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React12.createElement(
6838
6939
  ContextCell,
6839
6940
  {
6840
6941
  ratio: ctxRatio,
@@ -6842,7 +6943,7 @@ function StackedMetrics({
6842
6943
  ctxMax,
6843
6944
  showBar: true
6844
6945
  }
6845
- ), balance ? /* @__PURE__ */ React11.createElement(BalanceCell, { balance }) : null, /* @__PURE__ */ React11.createElement(CacheCell, { hitRatio: summary.cacheHitRatio, coldStart, turns: summary.turns }), /* @__PURE__ */ React11.createElement(CostCell, { summary, coldStart }));
6946
+ ), balance ? /* @__PURE__ */ React12.createElement(BalanceCell, { balance }) : null, /* @__PURE__ */ React12.createElement(CacheCell, { hitRatio: summary.cacheHitRatio, coldStart, turns: summary.turns }), /* @__PURE__ */ React12.createElement(CostCell, { summary, coldStart }));
6846
6947
  }
6847
6948
  function ContextCell({
6848
6949
  ratio,
@@ -6851,11 +6952,11 @@ function ContextCell({
6851
6952
  showBar
6852
6953
  }) {
6853
6954
  if (promptTokens === 0) {
6854
- return /* @__PURE__ */ React11.createElement(Text10, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "ctx "), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "\u2014 (no turns yet)"));
6955
+ return /* @__PURE__ */ React12.createElement(Text11, null, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "ctx "), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "\u2014 (no turns yet)"));
6855
6956
  }
6856
6957
  const color = ratio >= 0.8 ? "red" : ratio >= 0.6 ? "yellow" : "green";
6857
6958
  const pct2 = Math.round(ratio * 100);
6858
- return /* @__PURE__ */ React11.createElement(Text10, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "ctx "), showBar ? /* @__PURE__ */ React11.createElement(Bar, { ratio, color }) : null, showBar ? /* @__PURE__ */ React11.createElement(Text10, null, " ") : null, /* @__PURE__ */ React11.createElement(Text10, { color, bold: true }, formatTokens(promptTokens), "/", formatTokens(ctxMax)), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " (", pct2, "%)"), ratio >= 0.8 ? /* @__PURE__ */ React11.createElement(Text10, { color: "red", bold: true }, " \xB7 /compact") : null);
6959
+ return /* @__PURE__ */ React12.createElement(Text11, null, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "ctx "), showBar ? /* @__PURE__ */ React12.createElement(Bar, { ratio, color }) : null, showBar ? /* @__PURE__ */ React12.createElement(Text11, null, " ") : null, /* @__PURE__ */ React12.createElement(Text11, { color, bold: true }, formatTokens(promptTokens), "/", formatTokens(ctxMax)), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, " (", pct2, "%)"), ratio >= 0.8 ? /* @__PURE__ */ React12.createElement(Text11, { color: "red", bold: true }, " \xB7 /compact") : null);
6859
6960
  }
6860
6961
  function CacheCell({
6861
6962
  hitRatio,
@@ -6864,33 +6965,33 @@ function CacheCell({
6864
6965
  }) {
6865
6966
  const pct2 = (hitRatio * 100).toFixed(1);
6866
6967
  if (turns === 0) {
6867
- return /* @__PURE__ */ React11.createElement(Text10, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "cache "), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "\u2014"));
6968
+ return /* @__PURE__ */ React12.createElement(Text11, null, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "cache "), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "\u2014"));
6868
6969
  }
6869
6970
  if (coldStart) {
6870
- return /* @__PURE__ */ React11.createElement(Text10, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "cache "), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, pct2, "% "), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true, italic: true }, "(cold start)"));
6971
+ return /* @__PURE__ */ React12.createElement(Text11, null, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "cache "), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, pct2, "% "), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true, italic: true }, "(cold start)"));
6871
6972
  }
6872
6973
  const color = hitRatio >= 0.7 ? "green" : hitRatio >= 0.4 ? "yellow" : "red";
6873
- return /* @__PURE__ */ React11.createElement(Text10, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "cache "), /* @__PURE__ */ React11.createElement(Text10, { color, bold: true }, pct2, "%"));
6974
+ return /* @__PURE__ */ React12.createElement(Text11, null, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "cache "), /* @__PURE__ */ React12.createElement(Text11, { color, bold: true }, pct2, "%"));
6874
6975
  }
6875
6976
  function CostCell({
6876
6977
  summary,
6877
6978
  coldStart
6878
6979
  }) {
6879
6980
  if (summary.turns === 0) {
6880
- return /* @__PURE__ */ React11.createElement(Text10, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "cost "), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "\u2014"));
6981
+ return /* @__PURE__ */ React12.createElement(Text11, null, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "cost "), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "\u2014"));
6881
6982
  }
6882
6983
  const primaryColor = coldStart ? void 0 : "green";
6883
- return /* @__PURE__ */ React11.createElement(Text10, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "cost "), /* @__PURE__ */ React11.createElement(Text10, { color: primaryColor, bold: !coldStart, dimColor: coldStart }, "$", summary.totalCostUsd.toFixed(6)), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " (in ", "$", summary.totalInputCostUsd.toFixed(6), " \xB7 out ", "$", summary.totalOutputCostUsd.toFixed(6), ")"));
6984
+ return /* @__PURE__ */ React12.createElement(Text11, null, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "cost "), /* @__PURE__ */ React12.createElement(Text11, { color: primaryColor, bold: !coldStart, dimColor: coldStart }, "$", summary.totalCostUsd.toFixed(6)), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, " (in ", "$", summary.totalInputCostUsd.toFixed(6), " \xB7 out ", "$", summary.totalOutputCostUsd.toFixed(6), ")"));
6884
6985
  }
6885
6986
  function BalanceCell({ balance }) {
6886
6987
  const color = balance.total < 1 ? "red" : balance.total < 5 ? "yellow" : "green";
6887
- return /* @__PURE__ */ React11.createElement(Text10, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "balance "), /* @__PURE__ */ React11.createElement(Text10, { color, bold: true }, balance.currency === "USD" ? "$" : "", balance.total.toFixed(2), balance.currency !== "USD" ? ` ${balance.currency}` : ""));
6988
+ return /* @__PURE__ */ React12.createElement(Text11, null, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "balance "), /* @__PURE__ */ React12.createElement(Text11, { color, bold: true }, balance.currency === "USD" ? "$" : "", balance.total.toFixed(2), balance.currency !== "USD" ? ` ${balance.currency}` : ""));
6888
6989
  }
6889
6990
  function Bar({ ratio, color }) {
6890
6991
  const cells = 10;
6891
6992
  const filled = Math.max(0, Math.min(cells, Math.round(ratio * cells)));
6892
6993
  const bar = "\u2588".repeat(filled) + "\u2591".repeat(cells - filled);
6893
- return /* @__PURE__ */ React11.createElement(Text10, { color }, bar);
6994
+ return /* @__PURE__ */ React12.createElement(Text11, { color }, bar);
6894
6995
  }
6895
6996
  function formatTokens(n) {
6896
6997
  if (n < 1024) return String(n);
@@ -8051,6 +8152,39 @@ function App({
8051
8152
  return prev;
8052
8153
  });
8053
8154
  }, [slashMatches]);
8155
+ const [atSelected, setAtSelected] = useState5(0);
8156
+ const atFiles = useMemo(() => {
8157
+ if (!codeMode?.rootDir) return [];
8158
+ try {
8159
+ return listFilesSync(codeMode.rootDir, { maxResults: 500 });
8160
+ } catch {
8161
+ return [];
8162
+ }
8163
+ }, [codeMode?.rootDir]);
8164
+ const atPicker = useMemo(() => {
8165
+ if (!codeMode?.rootDir) return null;
8166
+ if (slashMatches !== null) return null;
8167
+ return detectAtPicker(input);
8168
+ }, [codeMode?.rootDir, input, slashMatches]);
8169
+ const atMatches = useMemo(() => {
8170
+ if (!atPicker) return null;
8171
+ return rankPickerCandidates(atFiles, atPicker.query, 40);
8172
+ }, [atPicker, atFiles]);
8173
+ useEffect2(() => {
8174
+ setAtSelected((prev) => {
8175
+ if (!atMatches || atMatches.length === 0) return 0;
8176
+ if (prev >= atMatches.length) return atMatches.length - 1;
8177
+ return prev;
8178
+ });
8179
+ }, [atMatches]);
8180
+ const pickAtMention = useCallback(
8181
+ (chosenPath) => {
8182
+ if (!atPicker) return;
8183
+ const before = input.slice(0, atPicker.atOffset);
8184
+ setInput(`${before}@${chosenPath} `);
8185
+ },
8186
+ [atPicker, input]
8187
+ );
8054
8188
  const loopRef = useRef2(null);
8055
8189
  const subagentSinkRef = useRef2({ current: null });
8056
8190
  const loop = useMemo(() => {
@@ -8220,6 +8354,21 @@ function App({
8220
8354
  }
8221
8355
  if (busy) return;
8222
8356
  if (pendingShell) return;
8357
+ if (atMatches && atMatches.length > 0) {
8358
+ if (key.upArrow) {
8359
+ setAtSelected((i) => Math.max(0, i - 1));
8360
+ return;
8361
+ }
8362
+ if (key.downArrow) {
8363
+ setAtSelected((i) => Math.min(atMatches.length - 1, i + 1));
8364
+ return;
8365
+ }
8366
+ if (key.tab) {
8367
+ const sel = atMatches[atSelected] ?? atMatches[0];
8368
+ if (sel) pickAtMention(sel);
8369
+ return;
8370
+ }
8371
+ }
8223
8372
  if (slashMatches && slashMatches.length > 0) {
8224
8373
  if (key.upArrow) {
8225
8374
  setSlashSelected((i) => Math.max(0, i - 1));
@@ -8305,6 +8454,13 @@ function App({
8305
8454
  async (raw) => {
8306
8455
  let text = raw.trim();
8307
8456
  if (!text || busy) return;
8457
+ if (atMatches && atMatches.length > 0 && atPicker) {
8458
+ const sel = atMatches[atSelected] ?? atMatches[0];
8459
+ if (sel) {
8460
+ pickAtMention(sel);
8461
+ return;
8462
+ }
8463
+ }
8308
8464
  if (text.startsWith("/") && !text.includes(" ")) {
8309
8465
  const typed = text.slice(1).toLowerCase();
8310
8466
  const matches = suggestSlashCommands(typed, !!codeMode);
@@ -8659,6 +8815,10 @@ function App({
8659
8815
  planMode,
8660
8816
  session,
8661
8817
  slashSelected,
8818
+ atMatches,
8819
+ atPicker,
8820
+ atSelected,
8821
+ pickAtMention,
8662
8822
  togglePlanMode,
8663
8823
  writeTranscript
8664
8824
  ]
@@ -8809,7 +8969,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
8809
8969
  if (stagedInput?.plan) setPendingPlan(stagedInput.plan);
8810
8970
  setStagedInput(null);
8811
8971
  }, [stagedInput]);
8812
- return /* @__PURE__ */ React12.createElement(TickerProvider, { disabled: PLAIN_UI }, /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column" }, /* @__PURE__ */ React12.createElement(
8972
+ return /* @__PURE__ */ React13.createElement(TickerProvider, { disabled: PLAIN_UI }, /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React13.createElement(
8813
8973
  StatsPanel,
8814
8974
  {
8815
8975
  summary,
@@ -8822,21 +8982,21 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
8822
8982
  busy,
8823
8983
  updateAvailable
8824
8984
  }
8825
- ), /* @__PURE__ */ React12.createElement(Static, { items: historical }, (item) => /* @__PURE__ */ React12.createElement(EventRow, { key: item.id, event: item, projectRoot: hookCwd })), !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && streaming ? /* @__PURE__ */ React12.createElement(Box11, { marginY: 1 }, /* @__PURE__ */ React12.createElement(EventRow, { event: streaming, projectRoot: hookCwd })) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && ongoingTool ? /* @__PURE__ */ React12.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && subagentActivity ? /* @__PURE__ */ React12.createElement(SubagentRow, { activity: subagentActivity }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && !ongoingTool && statusLine ? /* @__PURE__ */ React12.createElement(StatusRow, { text: statusLine }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && busy && !streaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React12.createElement(StatusRow, { text: "processing\u2026" }) : null, stagedInput ? /* @__PURE__ */ React12.createElement(
8985
+ ), /* @__PURE__ */ React13.createElement(Static, { items: historical }, (item) => /* @__PURE__ */ React13.createElement(EventRow, { key: item.id, event: item, projectRoot: hookCwd })), !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && streaming ? /* @__PURE__ */ React13.createElement(Box12, { marginY: 1 }, /* @__PURE__ */ React13.createElement(EventRow, { event: streaming, projectRoot: hookCwd })) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && ongoingTool ? /* @__PURE__ */ React13.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && subagentActivity ? /* @__PURE__ */ React13.createElement(SubagentRow, { activity: subagentActivity }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && !ongoingTool && statusLine ? /* @__PURE__ */ React13.createElement(StatusRow, { text: statusLine }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !stagedInput && busy && !streaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React13.createElement(StatusRow, { text: "processing\u2026" }) : null, stagedInput ? /* @__PURE__ */ React13.createElement(
8826
8986
  PlanRefineInput,
8827
8987
  {
8828
8988
  mode: stagedInput.mode,
8829
8989
  onSubmit: handleStagedInputSubmit,
8830
8990
  onCancel: handleStagedInputCancel
8831
8991
  }
8832
- ) : pendingPlan ? /* @__PURE__ */ React12.createElement(PlanConfirm, { plan: pendingPlan, onChoose: handlePlanConfirm, projectRoot: hookCwd }) : pendingShell ? /* @__PURE__ */ React12.createElement(
8992
+ ) : pendingPlan ? /* @__PURE__ */ React13.createElement(PlanConfirm, { plan: pendingPlan, onChoose: handlePlanConfirm, projectRoot: hookCwd }) : pendingShell ? /* @__PURE__ */ React13.createElement(
8833
8993
  ShellConfirm,
8834
8994
  {
8835
8995
  command: pendingShell,
8836
8996
  allowPrefix: derivePrefix(pendingShell),
8837
8997
  onChoose: handleShellConfirm
8838
8998
  }
8839
- ) : /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(
8999
+ ) : /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(
8840
9000
  PromptInput,
8841
9001
  {
8842
9002
  value: input,
@@ -8844,20 +9004,27 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
8844
9004
  onSubmit: handleSubmit,
8845
9005
  disabled: busy
8846
9006
  }
8847
- ), /* @__PURE__ */ React12.createElement(SlashSuggestions, { matches: slashMatches, selectedIndex: slashSelected }))));
9007
+ ), /* @__PURE__ */ React13.createElement(SlashSuggestions, { matches: slashMatches, selectedIndex: slashSelected }), /* @__PURE__ */ React13.createElement(
9008
+ AtMentionSuggestions,
9009
+ {
9010
+ matches: atMatches,
9011
+ selectedIndex: atSelected,
9012
+ query: atPicker?.query ?? ""
9013
+ }
9014
+ ))));
8848
9015
  }
8849
9016
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
8850
9017
  function StatusRow({ text }) {
8851
9018
  const tick = useTick();
8852
9019
  const elapsed = useElapsedSeconds();
8853
- return /* @__PURE__ */ React12.createElement(Box11, { marginY: 1 }, /* @__PURE__ */ React12.createElement(Text11, { color: "magenta" }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React12.createElement(Text11, { color: "magenta" }, ` ${text}`), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, ` ${elapsed}s`));
9020
+ return /* @__PURE__ */ React13.createElement(Box12, { marginY: 1 }, /* @__PURE__ */ React13.createElement(Text12, { color: "magenta" }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React13.createElement(Text12, { color: "magenta" }, ` ${text}`), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, ` ${elapsed}s`));
8854
9021
  }
8855
9022
  function SubagentRow({
8856
9023
  activity
8857
9024
  }) {
8858
9025
  const tick = useTick();
8859
9026
  const seconds = (activity.elapsedMs / 1e3).toFixed(1);
8860
- return /* @__PURE__ */ React12.createElement(Box11, { paddingLeft: 2 }, /* @__PURE__ */ React12.createElement(Text11, { color: "magenta" }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React12.createElement(Text11, { color: "magenta" }, ` \u232C subagent: ${activity.task}`), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, ` \xB7 iter ${activity.iter} \xB7 ${seconds}s`));
9027
+ return /* @__PURE__ */ React13.createElement(Box12, { paddingLeft: 2 }, /* @__PURE__ */ React13.createElement(Text12, { color: "magenta" }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React13.createElement(Text12, { color: "magenta" }, ` \u232C subagent: ${activity.task}`), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, ` \xB7 iter ${activity.iter} \xB7 ${seconds}s`));
8861
9028
  }
8862
9029
  function OngoingToolRow({
8863
9030
  tool,
@@ -8866,7 +9033,7 @@ function OngoingToolRow({
8866
9033
  const tick = useTick();
8867
9034
  const elapsed = useElapsedSeconds();
8868
9035
  const summary = summarizeToolArgs(tool.name, tool.args);
8869
- return /* @__PURE__ */ React12.createElement(Box11, { marginY: 1, flexDirection: "column" }, /* @__PURE__ */ React12.createElement(Box11, null, /* @__PURE__ */ React12.createElement(Text11, { color: "cyan" }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React12.createElement(Text11, { color: "yellow" }, ` tool<${tool.name}> running\u2026`), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, ` ${elapsed}s`)), progress ? /* @__PURE__ */ React12.createElement(Box11, { paddingLeft: 2 }, /* @__PURE__ */ React12.createElement(Text11, { color: "cyan" }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ React12.createElement(Box11, { paddingLeft: 2 }, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, summary)) : null);
9036
+ return /* @__PURE__ */ React13.createElement(Box12, { marginY: 1, flexDirection: "column" }, /* @__PURE__ */ React13.createElement(Box12, null, /* @__PURE__ */ React13.createElement(Text12, { color: "cyan" }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ React13.createElement(Text12, { color: "yellow" }, ` tool<${tool.name}> running\u2026`), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, ` ${elapsed}s`)), progress ? /* @__PURE__ */ React13.createElement(Box12, { paddingLeft: 2 }, /* @__PURE__ */ React13.createElement(Text12, { color: "cyan" }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ React13.createElement(Box12, { paddingLeft: 2 }, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, summary)) : null);
8870
9037
  }
8871
9038
  function renderProgressLine(p) {
8872
9039
  const msg = p.message ? ` ${p.message}` : "";
@@ -8962,15 +9129,15 @@ function describeRepair(repair) {
8962
9129
  }
8963
9130
 
8964
9131
  // src/cli/ui/SessionPicker.tsx
8965
- import { Box as Box12, Text as Text12 } from "ink";
8966
- import React13 from "react";
9132
+ import { Box as Box13, Text as Text13 } from "ink";
9133
+ import React14 from "react";
8967
9134
  function SessionPicker({
8968
9135
  sessionName,
8969
9136
  messageCount,
8970
9137
  lastActive,
8971
9138
  onChoose
8972
9139
  }) {
8973
- return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React13.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text12, { bold: true, color: "cyan" }, `Session "${sessionName}" has ${messageCount} prior message${messageCount === 1 ? "" : "s"}`), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, ` \xB7 last active ${relativeTime(lastActive)}`)), /* @__PURE__ */ React13.createElement(
9140
+ return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text13, { bold: true, color: "cyan" }, `Session "${sessionName}" has ${messageCount} prior message${messageCount === 1 ? "" : "s"}`), /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, ` \xB7 last active ${relativeTime(lastActive)}`)), /* @__PURE__ */ React14.createElement(
8974
9141
  SingleSelect,
8975
9142
  {
8976
9143
  initialValue: "new",
@@ -8993,7 +9160,7 @@ function SessionPicker({
8993
9160
  ],
8994
9161
  onSubmit: (v) => onChoose(v)
8995
9162
  }
8996
- ), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "\u2191\u2193 to move \xB7 Enter to pick")));
9163
+ ), /* @__PURE__ */ React14.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, "\u2191\u2193 to move \xB7 Enter to pick")));
8997
9164
  }
8998
9165
  function relativeTime(date) {
8999
9166
  const ms = Date.now() - date.getTime();
@@ -9009,9 +9176,9 @@ function relativeTime(date) {
9009
9176
  }
9010
9177
 
9011
9178
  // src/cli/ui/Setup.tsx
9012
- import { Box as Box13, Text as Text13, useApp as useApp2 } from "ink";
9179
+ import { Box as Box14, Text as Text14, useApp as useApp2 } from "ink";
9013
9180
  import TextInput from "ink-text-input";
9014
- import React14, { useState as useState6 } from "react";
9181
+ import React15, { useState as useState6 } from "react";
9015
9182
  function Setup({ onReady }) {
9016
9183
  const [value, setValue] = useState6("");
9017
9184
  const [error, setError] = useState6(null);
@@ -9035,7 +9202,7 @@ function Setup({ onReady }) {
9035
9202
  }
9036
9203
  onReady(trimmed);
9037
9204
  };
9038
- return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React14.createElement(Text13, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React14.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text13, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React14.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text13, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React14.createElement(
9205
+ return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React15.createElement(Text14, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text14, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React15.createElement(Text14, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React15.createElement(Text14, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text14, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React15.createElement(
9039
9206
  TextInput,
9040
9207
  {
9041
9208
  value,
@@ -9044,7 +9211,7 @@ function Setup({ onReady }) {
9044
9211
  mask: "\u2022",
9045
9212
  placeholder: "sk-..."
9046
9213
  }
9047
- )), error ? /* @__PURE__ */ React14.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text13, { color: "red" }, error)) : value ? /* @__PURE__ */ React14.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, "preview: ", redactKey(value))) : null, /* @__PURE__ */ React14.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, "(Type /exit to abort.)")));
9214
+ )), error ? /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text14, { color: "red" }, error)) : value ? /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text14, { dimColor: true }, "preview: ", redactKey(value))) : null, /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text14, { dimColor: true }, "(Type /exit to abort.)")));
9048
9215
  }
9049
9216
 
9050
9217
  // src/cli/commands/chat.tsx
@@ -9060,7 +9227,7 @@ function Root({
9060
9227
  const [key, setKey] = useState7(initialKey);
9061
9228
  const [pending, setPending] = useState7(sessionPreview);
9062
9229
  if (!key) {
9063
- return /* @__PURE__ */ React15.createElement(
9230
+ return /* @__PURE__ */ React16.createElement(
9064
9231
  Setup,
9065
9232
  {
9066
9233
  onReady: (k) => {
@@ -9072,7 +9239,7 @@ function Root({
9072
9239
  }
9073
9240
  process.env.DEEPSEEK_API_KEY = key;
9074
9241
  if (pending && appProps.session) {
9075
- return /* @__PURE__ */ React15.createElement(
9242
+ return /* @__PURE__ */ React16.createElement(
9076
9243
  SessionPicker,
9077
9244
  {
9078
9245
  sessionName: appProps.session,
@@ -9087,7 +9254,7 @@ function Root({
9087
9254
  }
9088
9255
  );
9089
9256
  }
9090
- return /* @__PURE__ */ React15.createElement(
9257
+ return /* @__PURE__ */ React16.createElement(
9091
9258
  App,
9092
9259
  {
9093
9260
  model: appProps.model,
@@ -9190,7 +9357,7 @@ async function chatCommand(opts) {
9190
9357
  rewriteSession(opts.session, []);
9191
9358
  }
9192
9359
  const { waitUntilExit } = render(
9193
- /* @__PURE__ */ React15.createElement(
9360
+ /* @__PURE__ */ React16.createElement(
9194
9361
  Root,
9195
9362
  {
9196
9363
  initialKey,
@@ -9253,34 +9420,34 @@ async function codeCommand(opts = {}) {
9253
9420
  import { writeFileSync as writeFileSync5 } from "fs";
9254
9421
  import { basename as basename2 } from "path";
9255
9422
  import { render as render2 } from "ink";
9256
- import React18 from "react";
9423
+ import React19 from "react";
9257
9424
 
9258
9425
  // src/cli/ui/DiffApp.tsx
9259
- import { Box as Box15, Static as Static2, Text as Text15, useApp as useApp3, useInput as useInput5 } from "ink";
9260
- import React17, { useState as useState8 } from "react";
9426
+ import { Box as Box16, Static as Static2, Text as Text16, useApp as useApp3, useInput as useInput5 } from "ink";
9427
+ import React18, { useState as useState8 } from "react";
9261
9428
 
9262
9429
  // src/cli/ui/RecordView.tsx
9263
- import { Box as Box14, Text as Text14 } from "ink";
9264
- import React16 from "react";
9430
+ import { Box as Box15, Text as Text15 } from "ink";
9431
+ import React17 from "react";
9265
9432
  function RecordView({ rec, compact = false }) {
9266
9433
  const toolArgsMax = compact ? 120 : 200;
9267
9434
  const toolContentMax = compact ? 200 : 400;
9268
9435
  if (rec.role === "user") {
9269
- return /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text14, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React16.createElement(Text14, null, rec.content));
9436
+ return /* @__PURE__ */ React17.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text15, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React17.createElement(Text15, null, rec.content));
9270
9437
  }
9271
9438
  if (rec.role === "assistant_final") {
9272
- return /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Text14, { bold: true, color: "green" }, "assistant"), rec.cost !== void 0 ? /* @__PURE__ */ React16.createElement(Text14, { dimColor: true }, " $", rec.cost.toFixed(6)) : null, rec.usage ? /* @__PURE__ */ React16.createElement(CacheBadge, { usage: rec.usage }) : null), rec.planState ? /* @__PURE__ */ React16.createElement(PlanStateBlock, { planState: rec.planState }) : null, rec.content ? /* @__PURE__ */ React16.createElement(Text14, null, rec.content) : /* @__PURE__ */ React16.createElement(Text14, { dimColor: true, italic: true }, "(tool-call response only)"));
9439
+ return /* @__PURE__ */ React17.createElement(Box15, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React17.createElement(Box15, null, /* @__PURE__ */ React17.createElement(Text15, { bold: true, color: "green" }, "assistant"), rec.cost !== void 0 ? /* @__PURE__ */ React17.createElement(Text15, { dimColor: true }, " $", rec.cost.toFixed(6)) : null, rec.usage ? /* @__PURE__ */ React17.createElement(CacheBadge, { usage: rec.usage }) : null), rec.planState ? /* @__PURE__ */ React17.createElement(PlanStateBlock, { planState: rec.planState }) : null, rec.content ? /* @__PURE__ */ React17.createElement(Text15, null, rec.content) : /* @__PURE__ */ React17.createElement(Text15, { dimColor: true, italic: true }, "(tool-call response only)"));
9273
9440
  }
9274
9441
  if (rec.role === "tool") {
9275
- return /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text14, { color: "yellow" }, "tool<", rec.tool ?? "?", ">"), rec.args ? /* @__PURE__ */ React16.createElement(Text14, { dimColor: true }, " args: ", truncate3(rec.args, toolArgsMax)) : null, /* @__PURE__ */ React16.createElement(Text14, { dimColor: true }, " \u2192 ", truncate3(rec.content, toolContentMax)));
9442
+ return /* @__PURE__ */ React17.createElement(Box15, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text15, { color: "yellow" }, "tool<", rec.tool ?? "?", ">"), rec.args ? /* @__PURE__ */ React17.createElement(Text15, { dimColor: true }, " args: ", truncate3(rec.args, toolArgsMax)) : null, /* @__PURE__ */ React17.createElement(Text15, { dimColor: true }, " \u2192 ", truncate3(rec.content, toolContentMax)));
9276
9443
  }
9277
9444
  if (rec.role === "error") {
9278
- return /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text14, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React16.createElement(Text14, { color: "red" }, rec.error ?? rec.content));
9445
+ return /* @__PURE__ */ React17.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text15, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React17.createElement(Text15, { color: "red" }, rec.error ?? rec.content));
9279
9446
  }
9280
9447
  if (rec.role === "done" || rec.role === "assistant_delta") {
9281
9448
  return null;
9282
9449
  }
9283
- return /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Text14, { dimColor: true }, "[", rec.role, "] ", rec.content));
9450
+ return /* @__PURE__ */ React17.createElement(Box15, null, /* @__PURE__ */ React17.createElement(Text15, { dimColor: true }, "[", rec.role, "] ", rec.content));
9284
9451
  }
9285
9452
  function CacheBadge({ usage }) {
9286
9453
  const hit = usage.prompt_cache_hit_tokens ?? 0;
@@ -9289,7 +9456,7 @@ function CacheBadge({ usage }) {
9289
9456
  if (total === 0) return null;
9290
9457
  const pct2 = hit / total * 100;
9291
9458
  const color = pct2 >= 70 ? "green" : pct2 >= 40 ? "yellow" : "red";
9292
- return /* @__PURE__ */ React16.createElement(Text14, null, /* @__PURE__ */ React16.createElement(Text14, { dimColor: true }, " \xB7 cache "), /* @__PURE__ */ React16.createElement(Text14, { color }, pct2.toFixed(1), "%"));
9459
+ return /* @__PURE__ */ React17.createElement(Text15, null, /* @__PURE__ */ React17.createElement(Text15, { dimColor: true }, " \xB7 cache "), /* @__PURE__ */ React17.createElement(Text15, { color }, pct2.toFixed(1), "%"));
9293
9460
  }
9294
9461
  function truncate3(s, max) {
9295
9462
  return s.length <= max ? s : `${s.slice(0, max)}\u2026 (+${s.length - max} chars)`;
@@ -9323,7 +9490,7 @@ function DiffApp({ report }) {
9323
9490
  }
9324
9491
  });
9325
9492
  const pair = report.pairs[idx];
9326
- return /* @__PURE__ */ React17.createElement(Box15, { flexDirection: "column" }, /* @__PURE__ */ React17.createElement(DiffHeader, { report }), /* @__PURE__ */ React17.createElement(Box15, { marginTop: 1, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ React17.createElement(Text15, { color: "cyan", bold: true }, "turn ", pair?.turn ?? "?", " (", idx + 1, " / ", report.pairs.length, ")"), /* @__PURE__ */ React17.createElement(Text15, null, pair ? /* @__PURE__ */ React17.createElement(KindBadge, { kind: pair.kind }) : null)), /* @__PURE__ */ React17.createElement(Box15, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React17.createElement(Pane, { label: report.a.label, headerColor: "blue", records: paneRecords(pair, "a") }), /* @__PURE__ */ React17.createElement(Pane, { label: report.b.label, headerColor: "magenta", records: paneRecords(pair, "b") })), pair?.divergenceNote ? /* @__PURE__ */ React17.createElement(Box15, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React17.createElement(Text15, { color: "yellow" }, "\u2605 "), /* @__PURE__ */ React17.createElement(Text15, null, pair.divergenceNote)) : null, /* @__PURE__ */ React17.createElement(Box15, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React17.createElement(Text15, { dimColor: true }, /* @__PURE__ */ React17.createElement(Text15, { bold: true }, "j"), "/", /* @__PURE__ */ React17.createElement(Text15, { bold: true }, "\u2193"), " next \xB7 ", /* @__PURE__ */ React17.createElement(Text15, { bold: true }, "k"), "/", /* @__PURE__ */ React17.createElement(Text15, { bold: true }, "\u2191"), " ", "prev \xB7 ", /* @__PURE__ */ React17.createElement(Text15, { bold: true }, "n"), " next-diverge \xB7 ", /* @__PURE__ */ React17.createElement(Text15, { bold: true }, "N"), "/", /* @__PURE__ */ React17.createElement(Text15, { bold: true }, "p"), " ", "prev-diverge \xB7 ", /* @__PURE__ */ React17.createElement(Text15, { bold: true }, "g"), "/", /* @__PURE__ */ React17.createElement(Text15, { bold: true }, "G"), " first/last \xB7 ", /* @__PURE__ */ React17.createElement(Text15, { bold: true }, "q"), " ", "quit")));
9493
+ return /* @__PURE__ */ React18.createElement(Box16, { flexDirection: "column" }, /* @__PURE__ */ React18.createElement(DiffHeader, { report }), /* @__PURE__ */ React18.createElement(Box16, { marginTop: 1, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ React18.createElement(Text16, { color: "cyan", bold: true }, "turn ", pair?.turn ?? "?", " (", idx + 1, " / ", report.pairs.length, ")"), /* @__PURE__ */ React18.createElement(Text16, null, pair ? /* @__PURE__ */ React18.createElement(KindBadge, { kind: pair.kind }) : null)), /* @__PURE__ */ React18.createElement(Box16, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React18.createElement(Pane, { label: report.a.label, headerColor: "blue", records: paneRecords(pair, "a") }), /* @__PURE__ */ React18.createElement(Pane, { label: report.b.label, headerColor: "magenta", records: paneRecords(pair, "b") })), pair?.divergenceNote ? /* @__PURE__ */ React18.createElement(Box16, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React18.createElement(Text16, { color: "yellow" }, "\u2605 "), /* @__PURE__ */ React18.createElement(Text16, null, pair.divergenceNote)) : null, /* @__PURE__ */ React18.createElement(Box16, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React18.createElement(Text16, { dimColor: true }, /* @__PURE__ */ React18.createElement(Text16, { bold: true }, "j"), "/", /* @__PURE__ */ React18.createElement(Text16, { bold: true }, "\u2193"), " next \xB7 ", /* @__PURE__ */ React18.createElement(Text16, { bold: true }, "k"), "/", /* @__PURE__ */ React18.createElement(Text16, { bold: true }, "\u2191"), " ", "prev \xB7 ", /* @__PURE__ */ React18.createElement(Text16, { bold: true }, "n"), " next-diverge \xB7 ", /* @__PURE__ */ React18.createElement(Text16, { bold: true }, "N"), "/", /* @__PURE__ */ React18.createElement(Text16, { bold: true }, "p"), " ", "prev-diverge \xB7 ", /* @__PURE__ */ React18.createElement(Text16, { bold: true }, "g"), "/", /* @__PURE__ */ React18.createElement(Text16, { bold: true }, "G"), " first/last \xB7 ", /* @__PURE__ */ React18.createElement(Text16, { bold: true }, "q"), " ", "quit")));
9327
9494
  }
9328
9495
  function DiffHeader({ report }) {
9329
9496
  const a = report.a;
@@ -9341,15 +9508,15 @@ function DiffHeader({ report }) {
9341
9508
  } else if (a.stats.prefixHashes[0] && a.stats.prefixHashes[0] === b.stats.prefixHashes[0]) {
9342
9509
  prefixLine = `shared prefix hash ${a.stats.prefixHashes[0].slice(0, 12)}\u2026 \u2014 cache delta attributable to log stability, not prompt change.`;
9343
9510
  }
9344
- return /* @__PURE__ */ React17.createElement(Box15, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React17.createElement(Box15, { justifyContent: "space-between" }, /* @__PURE__ */ React17.createElement(Text15, null, /* @__PURE__ */ React17.createElement(Text15, { color: "cyan", bold: true }, "reasonix diff"), /* @__PURE__ */ React17.createElement(Text15, { dimColor: true }, " \xB7 A="), /* @__PURE__ */ React17.createElement(Text15, { color: "blue" }, a.label), /* @__PURE__ */ React17.createElement(Text15, { dimColor: true }, " vs B="), /* @__PURE__ */ React17.createElement(Text15, { color: "magenta" }, b.label)), /* @__PURE__ */ React17.createElement(Text15, { dimColor: true }, report.pairs.length, " turns aligned")), /* @__PURE__ */ React17.createElement(Box15, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React17.createElement(Text15, null, /* @__PURE__ */ React17.createElement(Text15, { dimColor: true }, "cache "), /* @__PURE__ */ React17.createElement(Text15, null, (a.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React17.createElement(Text15, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React17.createElement(Text15, null, (b.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React17.createElement(Text15, { color: cacheDelta >= 0 ? "green" : "red", bold: true }, " ", cacheDelta >= 0 ? "+" : "", (cacheDelta * 100).toFixed(1), "pp")), /* @__PURE__ */ React17.createElement(Text15, null, /* @__PURE__ */ React17.createElement(Text15, { dimColor: true }, "cost "), /* @__PURE__ */ React17.createElement(Text15, null, "$", a.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React17.createElement(Text15, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React17.createElement(Text15, null, "$", b.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React17.createElement(Text15, { color: costDelta2 <= 0 ? "green" : "red", bold: true }, " ", costDelta2 >= 0 ? "+" : "", costDelta2.toFixed(1), "%")), /* @__PURE__ */ React17.createElement(Text15, null, /* @__PURE__ */ React17.createElement(Text15, { dimColor: true }, "model calls "), /* @__PURE__ */ React17.createElement(Text15, null, a.stats.turns, " \u2192 ", b.stats.turns))), prefixLine ? /* @__PURE__ */ React17.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text15, { dimColor: true, italic: true }, prefixLine)) : null);
9511
+ return /* @__PURE__ */ React18.createElement(Box16, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React18.createElement(Box16, { justifyContent: "space-between" }, /* @__PURE__ */ React18.createElement(Text16, null, /* @__PURE__ */ React18.createElement(Text16, { color: "cyan", bold: true }, "reasonix diff"), /* @__PURE__ */ React18.createElement(Text16, { dimColor: true }, " \xB7 A="), /* @__PURE__ */ React18.createElement(Text16, { color: "blue" }, a.label), /* @__PURE__ */ React18.createElement(Text16, { dimColor: true }, " vs B="), /* @__PURE__ */ React18.createElement(Text16, { color: "magenta" }, b.label)), /* @__PURE__ */ React18.createElement(Text16, { dimColor: true }, report.pairs.length, " turns aligned")), /* @__PURE__ */ React18.createElement(Box16, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React18.createElement(Text16, null, /* @__PURE__ */ React18.createElement(Text16, { dimColor: true }, "cache "), /* @__PURE__ */ React18.createElement(Text16, null, (a.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React18.createElement(Text16, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React18.createElement(Text16, null, (b.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React18.createElement(Text16, { color: cacheDelta >= 0 ? "green" : "red", bold: true }, " ", cacheDelta >= 0 ? "+" : "", (cacheDelta * 100).toFixed(1), "pp")), /* @__PURE__ */ React18.createElement(Text16, null, /* @__PURE__ */ React18.createElement(Text16, { dimColor: true }, "cost "), /* @__PURE__ */ React18.createElement(Text16, null, "$", a.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React18.createElement(Text16, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React18.createElement(Text16, null, "$", b.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React18.createElement(Text16, { color: costDelta2 <= 0 ? "green" : "red", bold: true }, " ", costDelta2 >= 0 ? "+" : "", costDelta2.toFixed(1), "%")), /* @__PURE__ */ React18.createElement(Text16, null, /* @__PURE__ */ React18.createElement(Text16, { dimColor: true }, "model calls "), /* @__PURE__ */ React18.createElement(Text16, null, a.stats.turns, " \u2192 ", b.stats.turns))), prefixLine ? /* @__PURE__ */ React18.createElement(Box16, { marginTop: 1 }, /* @__PURE__ */ React18.createElement(Text16, { dimColor: true, italic: true }, prefixLine)) : null);
9345
9512
  }
9346
9513
  function Pane({
9347
9514
  label,
9348
9515
  headerColor,
9349
9516
  records
9350
9517
  }) {
9351
- return /* @__PURE__ */ React17.createElement(
9352
- Box15,
9518
+ return /* @__PURE__ */ React18.createElement(
9519
+ Box16,
9353
9520
  {
9354
9521
  flexDirection: "column",
9355
9522
  flexGrow: 1,
@@ -9357,21 +9524,21 @@ function Pane({
9357
9524
  borderStyle: "single",
9358
9525
  borderColor: headerColor
9359
9526
  },
9360
- /* @__PURE__ */ React17.createElement(Text15, { color: headerColor, bold: true }, label),
9361
- records.length === 0 ? /* @__PURE__ */ React17.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text15, { dimColor: true, italic: true }, "(no records on this side for this turn)")) : /* @__PURE__ */ React17.createElement(Static2, { items: records.map((rec, i) => ({ key: `${label}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React17.createElement(RecordView, { key, rec, compact: true }))
9527
+ /* @__PURE__ */ React18.createElement(Text16, { color: headerColor, bold: true }, label),
9528
+ records.length === 0 ? /* @__PURE__ */ React18.createElement(Box16, { marginTop: 1 }, /* @__PURE__ */ React18.createElement(Text16, { dimColor: true, italic: true }, "(no records on this side for this turn)")) : /* @__PURE__ */ React18.createElement(Static2, { items: records.map((rec, i) => ({ key: `${label}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React18.createElement(RecordView, { key, rec, compact: true }))
9362
9529
  );
9363
9530
  }
9364
9531
  function KindBadge({ kind }) {
9365
9532
  if (kind === "match") {
9366
- return /* @__PURE__ */ React17.createElement(Text15, { color: "green" }, "\u2713 match");
9533
+ return /* @__PURE__ */ React18.createElement(Text16, { color: "green" }, "\u2713 match");
9367
9534
  }
9368
9535
  if (kind === "diverge") {
9369
- return /* @__PURE__ */ React17.createElement(Text15, { color: "yellow" }, "\u2605 diverge");
9536
+ return /* @__PURE__ */ React18.createElement(Text16, { color: "yellow" }, "\u2605 diverge");
9370
9537
  }
9371
9538
  if (kind === "only_in_a") {
9372
- return /* @__PURE__ */ React17.createElement(Text15, { color: "blue" }, "\u2190 only in A");
9539
+ return /* @__PURE__ */ React18.createElement(Text16, { color: "blue" }, "\u2190 only in A");
9373
9540
  }
9374
- return /* @__PURE__ */ React17.createElement(Text15, { color: "magenta" }, "\u2192 only in B");
9541
+ return /* @__PURE__ */ React18.createElement(Text16, { color: "magenta" }, "\u2192 only in B");
9375
9542
  }
9376
9543
  function paneRecords(pair, side) {
9377
9544
  if (!pair) return [];
@@ -9402,7 +9569,7 @@ markdown report written to ${opts.mdPath}`);
9402
9569
  return;
9403
9570
  }
9404
9571
  if (wantTui) {
9405
- const { waitUntilExit } = render2(React18.createElement(DiffApp, { report }), {
9572
+ const { waitUntilExit } = render2(React19.createElement(DiffApp, { report }), {
9406
9573
  exitOnCtrlC: true,
9407
9574
  patchConsole: false
9408
9575
  });
@@ -9543,11 +9710,11 @@ function pad2(s, width) {
9543
9710
 
9544
9711
  // src/cli/commands/replay.ts
9545
9712
  import { render as render3 } from "ink";
9546
- import React20 from "react";
9713
+ import React21 from "react";
9547
9714
 
9548
9715
  // src/cli/ui/ReplayApp.tsx
9549
- import { Box as Box16, Static as Static3, Text as Text16, useApp as useApp4, useInput as useInput6 } from "ink";
9550
- import React19, { useMemo as useMemo2, useState as useState9 } from "react";
9716
+ import { Box as Box17, Static as Static3, Text as Text17, useApp as useApp4, useInput as useInput6 } from "ink";
9717
+ import React20, { useMemo as useMemo2, useState as useState9 } from "react";
9551
9718
  function ReplayApp({ meta, pages }) {
9552
9719
  const { exit } = useApp4();
9553
9720
  const maxIdx = Math.max(0, pages.length - 1);
@@ -9586,14 +9753,14 @@ function ReplayApp({ meta, pages }) {
9586
9753
  const prefixHash = cumStats.prefixHashes.length === 1 ? cumStats.prefixHashes[0].slice(0, 16) : cumStats.prefixHashes.length === 0 ? "(untracked)" : `(churned \xD7${cumStats.prefixHashes.length})`;
9587
9754
  const currentPage = pages[idx];
9588
9755
  const progressLabel = pages.length === 0 ? "empty transcript" : `turn ${idx + 1} / ${pages.length}`;
9589
- return /* @__PURE__ */ React19.createElement(Box16, { flexDirection: "column" }, /* @__PURE__ */ React19.createElement(
9756
+ return /* @__PURE__ */ React20.createElement(Box17, { flexDirection: "column" }, /* @__PURE__ */ React20.createElement(
9590
9757
  StatsPanel,
9591
9758
  {
9592
9759
  summary,
9593
9760
  model: cumStats.models[0] ?? meta?.model ?? "?",
9594
9761
  prefixHash
9595
9762
  }
9596
- ), /* @__PURE__ */ React19.createElement(Box16, { flexDirection: "column", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React19.createElement(Box16, { justifyContent: "space-between" }, /* @__PURE__ */ React19.createElement(Text16, { color: "cyan", bold: true }, progressLabel), meta ? /* @__PURE__ */ React19.createElement(Text16, { dimColor: true }, meta.source, meta.task ? ` \xB7 ${meta.task}` : "", meta.mode ? ` \xB7 ${meta.mode}` : "") : null), currentPage ? /* @__PURE__ */ React19.createElement(Static3, { items: currentPage.records.map((rec, i) => ({ key: `${idx}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React19.createElement(RecordView, { key, rec })) : /* @__PURE__ */ React19.createElement(Text16, { dimColor: true, italic: true }, "no records")), /* @__PURE__ */ React19.createElement(Box16, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React19.createElement(Text16, { dimColor: true }, /* @__PURE__ */ React19.createElement(Text16, { bold: true }, "j"), "/", /* @__PURE__ */ React19.createElement(Text16, { bold: true }, "\u2193"), "/", /* @__PURE__ */ React19.createElement(Text16, { bold: true }, "space"), " next \xB7 ", /* @__PURE__ */ React19.createElement(Text16, { bold: true }, "k"), "/", /* @__PURE__ */ React19.createElement(Text16, { bold: true }, "\u2191"), " prev \xB7 ", /* @__PURE__ */ React19.createElement(Text16, { bold: true }, "g"), " first \xB7 ", /* @__PURE__ */ React19.createElement(Text16, { bold: true }, "G"), " last \xB7", " ", /* @__PURE__ */ React19.createElement(Text16, { bold: true }, "q"), " quit")));
9763
+ ), /* @__PURE__ */ React20.createElement(Box17, { flexDirection: "column", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React20.createElement(Box17, { justifyContent: "space-between" }, /* @__PURE__ */ React20.createElement(Text17, { color: "cyan", bold: true }, progressLabel), meta ? /* @__PURE__ */ React20.createElement(Text17, { dimColor: true }, meta.source, meta.task ? ` \xB7 ${meta.task}` : "", meta.mode ? ` \xB7 ${meta.mode}` : "") : null), currentPage ? /* @__PURE__ */ React20.createElement(Static3, { items: currentPage.records.map((rec, i) => ({ key: `${idx}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React20.createElement(RecordView, { key, rec })) : /* @__PURE__ */ React20.createElement(Text17, { dimColor: true, italic: true }, "no records")), /* @__PURE__ */ React20.createElement(Box17, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React20.createElement(Text17, { dimColor: true }, /* @__PURE__ */ React20.createElement(Text17, { bold: true }, "j"), "/", /* @__PURE__ */ React20.createElement(Text17, { bold: true }, "\u2193"), "/", /* @__PURE__ */ React20.createElement(Text17, { bold: true }, "space"), " next \xB7 ", /* @__PURE__ */ React20.createElement(Text17, { bold: true }, "k"), "/", /* @__PURE__ */ React20.createElement(Text17, { bold: true }, "\u2191"), " prev \xB7 ", /* @__PURE__ */ React20.createElement(Text17, { bold: true }, "g"), " first \xB7 ", /* @__PURE__ */ React20.createElement(Text17, { bold: true }, "G"), " last \xB7", " ", /* @__PURE__ */ React20.createElement(Text17, { bold: true }, "q"), " quit")));
9597
9764
  }
9598
9765
 
9599
9766
  // src/cli/commands/replay.ts
@@ -9605,7 +9772,7 @@ async function replayCommand(opts) {
9605
9772
  }
9606
9773
  const { parsed } = replayFromFile(opts.path);
9607
9774
  const pages = groupRecordsByTurn(parsed.records);
9608
- const { waitUntilExit } = render3(React20.createElement(ReplayApp, { meta: parsed.meta, pages }), {
9775
+ const { waitUntilExit } = render3(React21.createElement(ReplayApp, { meta: parsed.meta, pages }), {
9609
9776
  exitOnCtrlC: true,
9610
9777
  patchConsole: false
9611
9778
  });
@@ -9910,12 +10077,12 @@ function truncate4(s, max) {
9910
10077
 
9911
10078
  // src/cli/commands/setup.tsx
9912
10079
  import { render as render4 } from "ink";
9913
- import React22 from "react";
10080
+ import React23 from "react";
9914
10081
 
9915
10082
  // src/cli/ui/Wizard.tsx
9916
- import { Box as Box17, Text as Text17, useApp as useApp5, useInput as useInput7 } from "ink";
10083
+ import { Box as Box18, Text as Text18, useApp as useApp5, useInput as useInput7 } from "ink";
9917
10084
  import TextInput2 from "ink-text-input";
9918
- import React21, { useState as useState10 } from "react";
10085
+ import React22, { useState as useState10 } from "react";
9919
10086
 
9920
10087
  // src/cli/ui/presets.ts
9921
10088
  var PRESETS = {
@@ -9954,7 +10121,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
9954
10121
  if (key.escape && step !== "saved" && onCancel) onCancel();
9955
10122
  });
9956
10123
  if (step === "apiKey") {
9957
- return /* @__PURE__ */ React21.createElement(
10124
+ return /* @__PURE__ */ React22.createElement(
9958
10125
  ApiKeyStep,
9959
10126
  {
9960
10127
  onSubmit: (key) => {
@@ -9968,7 +10135,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
9968
10135
  );
9969
10136
  }
9970
10137
  if (step === "preset") {
9971
- return /* @__PURE__ */ React21.createElement(StepFrame, { title: "Pick a preset", step: 1, total: 3 }, /* @__PURE__ */ React21.createElement(
10138
+ return /* @__PURE__ */ React22.createElement(StepFrame, { title: "Pick a preset", step: 1, total: 3 }, /* @__PURE__ */ React22.createElement(
9972
10139
  SingleSelect,
9973
10140
  {
9974
10141
  items: presetItems(),
@@ -9978,10 +10145,10 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
9978
10145
  setStep("mcp");
9979
10146
  }
9980
10147
  }
9981
- ), /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, "\u2191/\u2193 move \xB7 enter confirm \xB7 esc cancel")));
10148
+ ), /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, "\u2191/\u2193 move \xB7 enter confirm \xB7 esc cancel")));
9982
10149
  }
9983
10150
  if (step === "mcp") {
9984
- return /* @__PURE__ */ React21.createElement(StepFrame, { title: "Which MCP servers should Reasonix wire up for you?", step: 2, total: 3 }, /* @__PURE__ */ React21.createElement(
10151
+ return /* @__PURE__ */ React22.createElement(StepFrame, { title: "Which MCP servers should Reasonix wire up for you?", step: 2, total: 3 }, /* @__PURE__ */ React22.createElement(
9985
10152
  MultiSelect,
9986
10153
  {
9987
10154
  items: mcpItems(),
@@ -10006,7 +10173,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
10006
10173
  }
10007
10174
  const currentName = pending[0];
10008
10175
  const entry = CATALOG_BY_NAME.get(currentName);
10009
- return /* @__PURE__ */ React21.createElement(
10176
+ return /* @__PURE__ */ React22.createElement(
10010
10177
  McpArgsStep,
10011
10178
  {
10012
10179
  entry,
@@ -10024,7 +10191,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
10024
10191
  }
10025
10192
  if (step === "review") {
10026
10193
  const specs = data.selectedCatalog.map((name) => buildSpec(name, data.catalogArgs));
10027
- return /* @__PURE__ */ React21.createElement(StepFrame, { title: "Ready to save", step: 3, total: 3 }, /* @__PURE__ */ React21.createElement(Box17, { flexDirection: "column" }, /* @__PURE__ */ React21.createElement(SummaryLine, { label: "API key", value: redactKey(data.apiKey) }), /* @__PURE__ */ React21.createElement(SummaryLine, { label: "Preset", value: data.preset }), /* @__PURE__ */ React21.createElement(
10194
+ return /* @__PURE__ */ React22.createElement(StepFrame, { title: "Ready to save", step: 3, total: 3 }, /* @__PURE__ */ React22.createElement(Box18, { flexDirection: "column" }, /* @__PURE__ */ React22.createElement(SummaryLine, { label: "API key", value: redactKey(data.apiKey) }), /* @__PURE__ */ React22.createElement(SummaryLine, { label: "Preset", value: data.preset }), /* @__PURE__ */ React22.createElement(
10028
10195
  SummaryLine,
10029
10196
  {
10030
10197
  label: "MCP",
@@ -10032,8 +10199,8 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
10032
10199
  }
10033
10200
  ), specs.map((spec, i) => (
10034
10201
  // biome-ignore lint/suspicious/noArrayIndexKey: review-only render, order fixed
10035
- /* @__PURE__ */ React21.createElement(Box17, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, "\xB7 ", spec))
10036
- )), /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, null, "Saves to ", defaultConfigPath())), error ? /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, { color: "red" }, error)) : null, /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, "enter save \xB7 esc cancel"))), /* @__PURE__ */ React21.createElement(
10202
+ /* @__PURE__ */ React22.createElement(Box18, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, "\xB7 ", spec))
10203
+ )), /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, null, "Saves to ", defaultConfigPath())), error ? /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, { color: "red" }, error)) : null, /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, "enter save \xB7 esc cancel"))), /* @__PURE__ */ React22.createElement(
10037
10204
  ReviewConfirm,
10038
10205
  {
10039
10206
  onConfirm: () => {
@@ -10059,7 +10226,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
10059
10226
  }
10060
10227
  ));
10061
10228
  }
10062
- return /* @__PURE__ */ React21.createElement(Box17, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React21.createElement(Text17, { bold: true, color: "green" }, "\u25B8 Saved."), /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, null, "Run `reasonix` any time to start chatting \u2014 your settings are remembered.")), /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, "Press enter to exit.")), /* @__PURE__ */ React21.createElement(ExitOnEnter, { onExit: exit }));
10229
+ return /* @__PURE__ */ React22.createElement(Box18, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: "green" }, "\u25B8 Saved."), /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, null, "Run `reasonix` any time to start chatting \u2014 your settings are remembered.")), /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, "Press enter to exit.")), /* @__PURE__ */ React22.createElement(ExitOnEnter, { onExit: exit }));
10063
10230
  }
10064
10231
  function ApiKeyStep({
10065
10232
  onSubmit,
@@ -10067,7 +10234,7 @@ function ApiKeyStep({
10067
10234
  onError
10068
10235
  }) {
10069
10236
  const [value, setValue] = useState10("");
10070
- return /* @__PURE__ */ React21.createElement(Box17, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React21.createElement(Text17, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React21.createElement(
10237
+ return /* @__PURE__ */ React22.createElement(Box18, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React22.createElement(
10071
10238
  TextInput2,
10072
10239
  {
10073
10240
  value,
@@ -10084,7 +10251,7 @@ function ApiKeyStep({
10084
10251
  mask: "\u2022",
10085
10252
  placeholder: "sk-..."
10086
10253
  }
10087
- )), error ? /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, { color: "red" }, error)) : value ? /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, "preview: ", redactKey(value))) : null);
10254
+ )), error ? /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, { color: "red" }, error)) : value ? /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, "preview: ", redactKey(value))) : null);
10088
10255
  }
10089
10256
  function McpArgsStep({
10090
10257
  entry,
@@ -10093,7 +10260,7 @@ function McpArgsStep({
10093
10260
  onError
10094
10261
  }) {
10095
10262
  const [value, setValue] = useState10("");
10096
- return /* @__PURE__ */ React21.createElement(StepFrame, { title: `Configure ${entry.name}`, step: 2, total: 3 }, /* @__PURE__ */ React21.createElement(Box17, { flexDirection: "column" }, /* @__PURE__ */ React21.createElement(Text17, null, entry.summary), entry.note ? /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, entry.note)) : null, /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, null, "Required parameter: "), /* @__PURE__ */ React21.createElement(Text17, { bold: true }, entry.userArgs)), /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, { bold: true, color: "cyan" }, entry.userArgs, " \u203A "), /* @__PURE__ */ React21.createElement(
10263
+ return /* @__PURE__ */ React22.createElement(StepFrame, { title: `Configure ${entry.name}`, step: 2, total: 3 }, /* @__PURE__ */ React22.createElement(Box18, { flexDirection: "column" }, /* @__PURE__ */ React22.createElement(Text18, null, entry.summary), entry.note ? /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, entry.note)) : null, /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, null, "Required parameter: "), /* @__PURE__ */ React22.createElement(Text18, { bold: true }, entry.userArgs)), /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: "cyan" }, entry.userArgs, " \u203A "), /* @__PURE__ */ React22.createElement(
10097
10264
  TextInput2,
10098
10265
  {
10099
10266
  value,
@@ -10109,7 +10276,7 @@ function McpArgsStep({
10109
10276
  },
10110
10277
  placeholder: placeholderFor(entry)
10111
10278
  }
10112
- )), error ? /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text17, { color: "red" }, error)) : null));
10279
+ )), error ? /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, { color: "red" }, error)) : null));
10113
10280
  }
10114
10281
  function ReviewConfirm({ onConfirm }) {
10115
10282
  useInput7((_i, key) => {
@@ -10129,10 +10296,10 @@ function StepFrame({
10129
10296
  total,
10130
10297
  children
10131
10298
  }) {
10132
- return /* @__PURE__ */ React21.createElement(Box17, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React21.createElement(Box17, null, /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, "Step ", step, "/", total, " \xB7", " "), /* @__PURE__ */ React21.createElement(Text17, { bold: true, color: "cyan" }, title)), /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1, flexDirection: "column" }, children));
10299
+ return /* @__PURE__ */ React22.createElement(Box18, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React22.createElement(Box18, null, /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, "Step ", step, "/", total, " \xB7", " "), /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: "cyan" }, title)), /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1, flexDirection: "column" }, children));
10133
10300
  }
10134
10301
  function SummaryLine({ label, value }) {
10135
- return /* @__PURE__ */ React21.createElement(Box17, null, /* @__PURE__ */ React21.createElement(Text17, null, label.padEnd(12)), /* @__PURE__ */ React21.createElement(Text17, { bold: true }, value));
10302
+ return /* @__PURE__ */ React22.createElement(Box18, null, /* @__PURE__ */ React22.createElement(Text18, null, label.padEnd(12)), /* @__PURE__ */ React22.createElement(Text18, { bold: true }, value));
10136
10303
  }
10137
10304
  function presetItems() {
10138
10305
  return ["fast", "smart", "max"].map((name) => ({
@@ -10188,7 +10355,7 @@ async function setupCommand(_opts = {}) {
10188
10355
  const existingKey = loadApiKey();
10189
10356
  const existing = readConfig();
10190
10357
  const { waitUntilExit, unmount } = render4(
10191
- /* @__PURE__ */ React22.createElement(
10358
+ /* @__PURE__ */ React23.createElement(
10192
10359
  Wizard,
10193
10360
  {
10194
10361
  existingApiKey: existingKey,