@crazyhappyone/dsh-tui 0.1.0-alpha.26 → 0.1.0-alpha.27

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/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // tui-render/src/index.ts
2
2
  import { render, renderToString, Text as Text32 } from "ink";
3
- import { createElement as createElement3 } from "react";
3
+ import React, { createElement as createElement3 } from "react";
4
4
 
5
5
  // tui-render/src/app-shell.tsx
6
6
  import { Box, Text, useWindowSize } from "ink";
@@ -126,20 +126,20 @@ function wrapDisplayLines(text, maxCols) {
126
126
  const source = text.split("\n");
127
127
  if (maxCols <= 0) return source;
128
128
  const out = [];
129
- for (const line8 of source) {
130
- if (line8 === "" || displayWidth(line8) <= maxCols) {
131
- out.push(line8);
129
+ for (const line5 of source) {
130
+ if (line5 === "" || displayWidth(line5) <= maxCols) {
131
+ out.push(line5);
132
132
  continue;
133
133
  }
134
- if (/^[\x20-\x7e]*$/u.test(line8)) {
135
- for (let i = 0; i < line8.length; i += maxCols) {
136
- out.push(line8.slice(i, i + maxCols));
134
+ if (/^[\x20-\x7e]*$/u.test(line5)) {
135
+ for (let i = 0; i < line5.length; i += maxCols) {
136
+ out.push(line5.slice(i, i + maxCols));
137
137
  }
138
138
  continue;
139
139
  }
140
140
  let curLine = "";
141
141
  let curCols = 0;
142
- for (const { segment: segment2 } of GRAPHEME.segment(line8)) {
142
+ for (const { segment: segment2 } of GRAPHEME.segment(line5)) {
143
143
  const width = displayWidth(segment2);
144
144
  if (curCols + width > maxCols && curLine !== "") {
145
145
  out.push(curLine);
@@ -225,7 +225,7 @@ var THEME_LEVELS = {
225
225
  truecolor: {
226
226
  bg: "#151618",
227
227
  messageBg: "#25282C",
228
- toolBg: "#1A1C1F",
228
+ toolBg: "#252830",
229
229
  inputBg: "#23262B",
230
230
  codeBg: "#202328",
231
231
  fg: "#EEF0F2",
@@ -250,7 +250,7 @@ var THEME_LEVELS = {
250
250
  "256": {
251
251
  bg: "233",
252
252
  messageBg: "235",
253
- toolBg: "234",
253
+ toolBg: "236",
254
254
  inputBg: "235",
255
255
  codeBg: "235",
256
256
  fg: "255",
@@ -856,11 +856,11 @@ function trimPartialClosingFence(root, source) {
856
856
  }
857
857
 
858
858
  // tui-render/src/painted-line.ts
859
- function paintLineFromRenderLine(line8, hyperlinks2 = hyperlinksEnabled()) {
860
- if (line8.spans.length === 0) return paintRow([]);
859
+ function paintLineFromRenderLine(line5, hyperlinks2 = hyperlinksEnabled()) {
860
+ if (line5.spans.length === 0) return paintRow([]);
861
861
  const parts = [];
862
- for (const span of line8.spans) {
863
- const text = displayColumnSlice(line8.text, span.start, span.end);
862
+ for (const span of line5.spans) {
863
+ const text = displayColumnSlice(line5.text, span.start, span.end);
864
864
  if (text === "") continue;
865
865
  const styledText = styled(text, span.token, void 0, span.bold);
866
866
  if (span.href !== void 0 && hyperlinks2 && isOsc8Href(span.href)) {
@@ -869,11 +869,11 @@ function paintLineFromRenderLine(line8, hyperlinks2 = hyperlinksEnabled()) {
869
869
  parts.push(styledText);
870
870
  }
871
871
  }
872
- if (line8.background !== void 0 && line8.background !== "bg") {
872
+ if (line5.background !== void 0 && line5.background !== "bg") {
873
873
  return paintBackgroundRow(
874
874
  parts,
875
- line8.background,
876
- line8.backgroundColumns ?? Math.max(line8.displayWidth, 1)
875
+ line5.background,
876
+ line5.backgroundColumns ?? Math.max(line5.displayWidth, 1)
877
877
  );
878
878
  }
879
879
  return paintRow(parts);
@@ -893,10 +893,10 @@ var PLAIN_TEXT_RENDERER = {
893
893
  if (text === "") return [emptyLine(blockIndex)];
894
894
  const wrapped = wrapDisplayLines(text, scope.width);
895
895
  const startOffset = node.position?.start.offset ?? 0;
896
- return wrapped.map((line8, index) => ({
897
- text: line8,
898
- displayWidth: displayWidth(line8),
899
- spans: [{ start: 0, end: displayWidth(line8), token: "fg", bold: false }],
896
+ return wrapped.map((line5, index) => ({
897
+ text: line5,
898
+ displayWidth: displayWidth(line5),
899
+ spans: [{ start: 0, end: displayWidth(line5), token: "fg", bold: false }],
900
900
  rowInBlock: index,
901
901
  sourceStart: index === 0 ? startOffset : -1,
902
902
  sourceEnd: -1,
@@ -1410,7 +1410,7 @@ function appendedRowsPreserveTableMetrics(rows, metrics) {
1410
1410
  const metric = metrics[column];
1411
1411
  const values = rows.map((row) => row[column] ?? "");
1412
1412
  for (const value of values) {
1413
- if (value.split("\n").some((line8) => !metric.wrapWidths.includes(displayWidth(line8)))) return false;
1413
+ if (value.split("\n").some((line5) => !metric.wrapWidths.includes(displayWidth(line5)))) return false;
1414
1414
  if (longestFittingIdentifier(value, DEFAULT_WORD_CAP) > metric.minimum) return false;
1415
1415
  }
1416
1416
  const appendedCategory = classifyColumn(values);
@@ -1562,16 +1562,16 @@ function buildGridLayout(headerCells, bodyCells, metrics, widths, maxCols, divid
1562
1562
  const ruleMid = ruleText(widths, "mid", dividerChar);
1563
1563
  const ruleBottom = ruleText(widths, "bottom", dividerChar);
1564
1564
  lines.push({ kind: "rule", text: ruleTop });
1565
- for (const line8 of wrapRow(headerCells, widths, true)) {
1566
- lines.push(line8);
1565
+ for (const line5 of wrapRow(headerCells, widths, true)) {
1566
+ lines.push(line5);
1567
1567
  }
1568
1568
  lines.push({ kind: "rule", text: ruleMid });
1569
1569
  let previousMultiline = false;
1570
1570
  for (const [index, row] of bodyCells.entries()) {
1571
1571
  const multiline = isMultilineTableRow(row.map((cell) => cell.text), widths);
1572
1572
  if (index > 0 && (previousMultiline || multiline)) lines.push({ kind: "rule", text: ruleMid });
1573
- for (const line8 of wrapRow(row, widths, false)) {
1574
- lines.push(line8);
1573
+ for (const line5 of wrapRow(row, widths, false)) {
1574
+ lines.push(line5);
1575
1575
  }
1576
1576
  previousMultiline = multiline;
1577
1577
  }
@@ -1611,18 +1611,18 @@ function wrapTableCell(text, width) {
1611
1611
  if (width <= 0) return text.split("\n");
1612
1612
  const out = [];
1613
1613
  for (const source of text.split("\n")) {
1614
- let line8 = "";
1614
+ let line5 = "";
1615
1615
  for (const token of source.match(/\s+|\S+/gu) ?? []) {
1616
- if (displayWidth(line8 + token) <= width) {
1617
- line8 += token;
1616
+ if (displayWidth(line5 + token) <= width) {
1617
+ line5 += token;
1618
1618
  continue;
1619
1619
  }
1620
- if (line8.trimEnd() !== "") out.push(line8.trimEnd());
1620
+ if (line5.trimEnd() !== "") out.push(line5.trimEnd());
1621
1621
  const pieces = wrapDisplayLines(token.trimStart(), width);
1622
1622
  out.push(...pieces.slice(0, -1));
1623
- line8 = pieces.at(-1) ?? "";
1623
+ line5 = pieces.at(-1) ?? "";
1624
1624
  }
1625
- out.push(line8.trimEnd());
1625
+ out.push(line5.trimEnd());
1626
1626
  }
1627
1627
  return out;
1628
1628
  }
@@ -1827,9 +1827,9 @@ function renderHeading(node, width, rowOffset, sourceStart) {
1827
1827
  const prefix = depth ? "\u2501\u2501\u2501 " : "\u2501 ";
1828
1828
  const suffix = depth ? " \u2501\u2501\u2501" : "";
1829
1829
  const wrapped = wrapDisplayLines(`${prefix}${escapeContent(formatSymbolSpacing(text))}${suffix}`, width);
1830
- return wrapped.map((line8, index) => {
1830
+ return wrapped.map((line5, index) => {
1831
1831
  const buffer = makeBuffer();
1832
- appendSegment(buffer, { text: line8, token: "accentText", bold: true });
1832
+ appendSegment(buffer, { text: line5, token: "accentText", bold: true });
1833
1833
  return freezeLine(buffer, rowOffset + index, index === 0 ? sourceStart : -1);
1834
1834
  });
1835
1835
  }
@@ -1838,9 +1838,9 @@ function renderBlockquote(children, width, rowOffset, sourceStart, hyperlinks2)
1838
1838
  for (const child of children) segments.push(...inlineToSegments(child, hyperlinks2));
1839
1839
  const merged = segments.map((s) => s.text).join("");
1840
1840
  const wrapped = wrapDisplayLines(`\u2502 ${escapeContent(merged)}`, width);
1841
- return wrapped.map((line8, index) => {
1841
+ return wrapped.map((line5, index) => {
1842
1842
  const buffer = makeBuffer();
1843
- appendSegment(buffer, { text: line8, token: "fgDim", bold: false });
1843
+ appendSegment(buffer, { text: line5, token: "fgDim", bold: false });
1844
1844
  return freezeLine(buffer, rowOffset + index, index === 0 ? sourceStart : -1);
1845
1845
  });
1846
1846
  }
@@ -1860,8 +1860,8 @@ function renderCode(value, width, rowOffset, sourceStart) {
1860
1860
  const lines = value.split("\n");
1861
1861
  const out = [];
1862
1862
  let row = rowOffset;
1863
- for (const [index, line8] of lines.entries()) {
1864
- const wrapped = wrapDisplayLines(escapeContent(line8), Math.max(1, width - 2));
1863
+ for (const [index, line5] of lines.entries()) {
1864
+ const wrapped = wrapDisplayLines(escapeContent(line5), Math.max(1, width - 2));
1865
1865
  if (wrapped.length === 0) {
1866
1866
  out.push(freezeEmpty(row, index === 0 ? sourceStart : -1));
1867
1867
  row += 1;
@@ -1873,12 +1873,12 @@ function renderCode(value, width, rowOffset, sourceStart) {
1873
1873
  for (const tk of tokens) {
1874
1874
  appendSegment(buffer, { text: tk.text, token: tk.token, bold: tk.bold });
1875
1875
  }
1876
- const line9 = freezeLine(
1876
+ const line6 = freezeLine(
1877
1877
  buffer,
1878
1878
  row,
1879
1879
  index === 0 && partIndex === 0 ? sourceStart : -1
1880
1880
  );
1881
- out.push({ ...line9, background: "codeBg" });
1881
+ out.push({ ...line6, background: "codeBg" });
1882
1882
  row += 1;
1883
1883
  }
1884
1884
  }
@@ -1982,8 +1982,8 @@ function renderTableCells(cells, width, rowOffset, sourceStart) {
1982
1982
  renderRecordLayout(layout, Math.max(1, width), appendLine);
1983
1983
  return lines;
1984
1984
  }
1985
- for (const line8 of layout.lines) {
1986
- appendLine(gridLayoutSegments(line8));
1985
+ for (const line5 of layout.lines) {
1986
+ appendLine(gridLayoutSegments(line5));
1987
1987
  }
1988
1988
  return lines;
1989
1989
  }
@@ -2125,44 +2125,44 @@ function renderGridRow(row, widths, header, rowOffset, sourceStart) {
2125
2125
  }
2126
2126
  return out;
2127
2127
  }
2128
- function gridLayoutSegments(line8) {
2129
- if (line8.kind === "rule" || line8.kind === "plain") {
2130
- return [{ text: line8.text, token: line8.kind === "rule" ? "fgDim" : "fg", bold: false }];
2128
+ function gridLayoutSegments(line5) {
2129
+ if (line5.kind === "rule" || line5.kind === "plain") {
2130
+ return [{ text: line5.text, token: line5.kind === "rule" ? "fgDim" : "fg", bold: false }];
2131
2131
  }
2132
- if (line8.kind === "record") return [];
2132
+ if (line5.kind === "record") return [];
2133
2133
  const segments = [{ text: "\u2502 ", token: "fgDim", bold: false }];
2134
- for (const [index, cell] of line8.cells.entries()) {
2134
+ for (const [index, cell] of line5.cells.entries()) {
2135
2135
  if (index > 0) segments.push({ text: " \u2502 ", token: "fgDim", bold: false });
2136
2136
  segments.push({
2137
2137
  text: cell.text,
2138
- token: line8.header ? "accentText" : "fg",
2139
- bold: line8.header
2138
+ token: line5.header ? "accentText" : "fg",
2139
+ bold: line5.header
2140
2140
  });
2141
2141
  }
2142
2142
  segments.push({ text: " \u2502", token: "fgDim", bold: false });
2143
2143
  return segments;
2144
2144
  }
2145
2145
  function renderRecordLayout(layout, width, appendLine) {
2146
- const records = layout.lines.filter((line8) => line8.kind === "record");
2146
+ const records = layout.lines.filter((line5) => line5.kind === "record");
2147
2147
  if (records.length <= 1) {
2148
2148
  const header = layout.header.map((cell) => cell.text).join(" | ");
2149
- for (const line8 of wrapDisplayLines(header, width)) {
2150
- appendLine([{ text: line8, token: "accentText", bold: true }]);
2149
+ for (const line5 of wrapDisplayLines(header, width)) {
2150
+ appendLine([{ text: line5, token: "accentText", bold: true }]);
2151
2151
  }
2152
2152
  return;
2153
2153
  }
2154
- for (const line8 of layout.lines) {
2155
- if (line8.kind === "rule") {
2156
- appendLine([{ text: line8.text, token: "fgDim", bold: false }]);
2154
+ for (const line5 of layout.lines) {
2155
+ if (line5.kind === "rule") {
2156
+ appendLine([{ text: line5.text, token: "fgDim", bold: false }]);
2157
2157
  continue;
2158
2158
  }
2159
- if (line8.kind !== "record" || line8.key.row === 0) continue;
2159
+ if (line5.kind !== "record" || line5.key.row === 0) continue;
2160
2160
  const keyLabel = layout.header[0]?.text ?? "key";
2161
- const keyText = keyLabel === "" ? line8.key.text : `${keyLabel}: ${line8.key.text}`;
2161
+ const keyText = keyLabel === "" ? line5.key.text : `${keyLabel}: ${line5.key.text}`;
2162
2162
  for (const text of wrapTableCell(keyText, width)) {
2163
2163
  appendLine([{ text, token: "accentText", bold: true }]);
2164
2164
  }
2165
- for (const value of line8.values) {
2165
+ for (const value of line5.values) {
2166
2166
  const label = layout.header[value.column]?.text ?? `#${String(value.column + 1)}`;
2167
2167
  const indent = wcwidthSafeSlice(layout.valueIndent, Math.max(0, width - 1));
2168
2168
  for (const text of wrapTableCell(`${label}: ${value.text}`, width - displayWidth(indent))) {
@@ -2308,19 +2308,19 @@ var TableScanner = class {
2308
2308
  if (buf.charCodeAt(i) === 10) {
2309
2309
  let end = i;
2310
2310
  if (end > lineStart && buf.charCodeAt(end - 1) === 13) end -= 1;
2311
- const line8 = buf.slice(lineStart, end);
2311
+ const line5 = buf.slice(lineStart, end);
2312
2312
  const startOff = this.bufferBaseOffset + lineStart;
2313
2313
  const endOff = this.bufferBaseOffset + end;
2314
- this.handleLine(line8, startOff, endOff);
2314
+ this.handleLine(line5, startOff, endOff);
2315
2315
  lineStart = i + 1;
2316
2316
  }
2317
2317
  i += 1;
2318
2318
  }
2319
2319
  if (forceFlush && lineStart < buf.length) {
2320
- const line8 = buf.slice(lineStart);
2320
+ const line5 = buf.slice(lineStart);
2321
2321
  const startOff = this.bufferBaseOffset + lineStart;
2322
2322
  const endOff = this.bufferBaseOffset + buf.length;
2323
- this.handleLine(line8, startOff, endOff);
2323
+ this.handleLine(line5, startOff, endOff);
2324
2324
  lineStart = buf.length;
2325
2325
  }
2326
2326
  if (lineStart > 0) {
@@ -2329,8 +2329,8 @@ var TableScanner = class {
2329
2329
  }
2330
2330
  }
2331
2331
  /** Dispatch one completed line through the state machine. */
2332
- handleLine(line8, start, end) {
2333
- const fence = detectFence(line8);
2332
+ handleLine(line5, start, end) {
2333
+ const fence = detectFence(line5);
2334
2334
  if (fence !== null) {
2335
2335
  if (this.fenceMarker === null) {
2336
2336
  this.fenceMarker = fence.marker;
@@ -2343,20 +2343,20 @@ var TableScanner = class {
2343
2343
  return;
2344
2344
  }
2345
2345
  if (this.fenceMarker !== null) return;
2346
- const cells = parsePipeRow(line8);
2346
+ const cells = parsePipeRow(line5);
2347
2347
  if (cells === null) {
2348
2348
  this.closeTable();
2349
2349
  return;
2350
2350
  }
2351
2351
  if (this.stateKind === "none") {
2352
2352
  this.stateKind = "pending-header";
2353
- this.headerRow = { text: line8, cells, start, end, isDelimiter: false };
2353
+ this.headerRow = { text: line5, cells, start, end, isDelimiter: false };
2354
2354
  return;
2355
2355
  }
2356
2356
  if (this.stateKind === "pending-header" && this.headerRow) {
2357
2357
  if (isDelimiterRow(cells) && cells.length === this.headerRow.cells.length) {
2358
2358
  const delimiter = {
2359
- text: line8,
2359
+ text: line5,
2360
2360
  cells,
2361
2361
  start,
2362
2362
  end,
@@ -2367,12 +2367,12 @@ var TableScanner = class {
2367
2367
  this.bodyRows = [];
2368
2368
  return;
2369
2369
  }
2370
- this.headerRow = { text: line8, cells, start, end, isDelimiter: false };
2370
+ this.headerRow = { text: line5, cells, start, end, isDelimiter: false };
2371
2371
  return;
2372
2372
  }
2373
2373
  if (this.stateKind === "confirmed-table" && this.delimiterRow) {
2374
2374
  if (cells.length === this.delimiterRow.cells.length) {
2375
- this.bodyRows.push({ text: line8, cells, start, end, isDelimiter: false });
2375
+ this.bodyRows.push({ text: line5, cells, start, end, isDelimiter: false });
2376
2376
  return;
2377
2377
  }
2378
2378
  this.closeTable();
@@ -2418,26 +2418,26 @@ var TableScanner = class {
2418
2418
  return { kind: "none" };
2419
2419
  }
2420
2420
  };
2421
- function detectFence(line8) {
2421
+ function detectFence(line5) {
2422
2422
  let i = 0;
2423
- while (i < line8.length && (line8.charCodeAt(i) === 32 || line8.charCodeAt(i) === 9)) i += 1;
2423
+ while (i < line5.length && (line5.charCodeAt(i) === 32 || line5.charCodeAt(i) === 9)) i += 1;
2424
2424
  if (i >= 4) return null;
2425
- if (i >= line8.length) return null;
2426
- const ch = line8.charCodeAt(i);
2425
+ if (i >= line5.length) return null;
2426
+ const ch = line5.charCodeAt(i);
2427
2427
  if (ch !== 96 && ch !== 126) return null;
2428
2428
  const runStart = i;
2429
- while (i < line8.length && line8.charCodeAt(i) === ch) i += 1;
2429
+ while (i < line5.length && line5.charCodeAt(i) === ch) i += 1;
2430
2430
  const length = i - runStart;
2431
2431
  if (length < FENCE_MIN) return null;
2432
2432
  if (ch === 96) {
2433
- for (let j = i; j < line8.length; j += 1) {
2434
- if (line8.charCodeAt(j) === 96) return null;
2433
+ for (let j = i; j < line5.length; j += 1) {
2434
+ if (line5.charCodeAt(j) === 96) return null;
2435
2435
  }
2436
2436
  }
2437
2437
  return { marker: String.fromCharCode(ch), length };
2438
2438
  }
2439
- function parsePipeRow(line8) {
2440
- const trimmed = line8.trim();
2439
+ function parsePipeRow(line5) {
2440
+ const trimmed = line5.trim();
2441
2441
  if (trimmed === "") return null;
2442
2442
  let pipeCount = 0;
2443
2443
  for (let i2 = 0; i2 < trimmed.length; i2 += 1) {
@@ -2475,8 +2475,8 @@ function parsePipeRow(line8) {
2475
2475
  cells.push(current.trim());
2476
2476
  return cells;
2477
2477
  }
2478
- function parsePipeTableCells(line8) {
2479
- return parsePipeRow(line8) ?? void 0;
2478
+ function parsePipeTableCells(line5) {
2479
+ return parsePipeRow(line5) ?? void 0;
2480
2480
  }
2481
2481
  function isDelimiterRow(cells) {
2482
2482
  if (cells.length === 0) return false;
@@ -2595,7 +2595,7 @@ function tokenize(source, lang) {
2595
2595
  return cached;
2596
2596
  }
2597
2597
  tokenMisses += 1;
2598
- const tokens = source.split("\n").flatMap((line8) => tokenizeLine(line8));
2598
+ const tokens = source.split("\n").flatMap((line5) => tokenizeLine(line5));
2599
2599
  lruSet2(tokenCache, key, tokens, () => {
2600
2600
  tokenEvictions += 1;
2601
2601
  });
@@ -2642,10 +2642,10 @@ function CodeBlock({
2642
2642
  tail
2643
2643
  }) {
2644
2644
  const lines = source.split("\n");
2645
- return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: lines.map((line8, index) => /* @__PURE__ */ jsx2(
2645
+ return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: lines.map((line5, index) => /* @__PURE__ */ jsx2(
2646
2646
  HighlightedLine,
2647
2647
  {
2648
- source: line8,
2648
+ source: line5,
2649
2649
  lang,
2650
2650
  prefix: index === 0 ? lead : rest,
2651
2651
  tail: index === lines.length - 1 ? tail : void 0
@@ -2653,13 +2653,13 @@ function CodeBlock({
2653
2653
  index
2654
2654
  )) });
2655
2655
  }
2656
- function paintedLineFromRenderLine(line8, hyperlinks2) {
2657
- return paintLineFromRenderLine(line8, hyperlinks2 && hyperlinksEnabled());
2656
+ function paintedLineFromRenderLine(line5, hyperlinks2) {
2657
+ return paintLineFromRenderLine(line5, hyperlinks2 && hyperlinksEnabled());
2658
2658
  }
2659
2659
  function linesToJsx(lines, affixes, hyperlinks2) {
2660
2660
  if (lines.length === 0) return null;
2661
- return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", width: "100%", children: lines.map((line8, index) => {
2662
- const painted = paintedLineFromRenderLine(line8, hyperlinks2);
2661
+ return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", width: "100%", children: lines.map((line5, index) => {
2662
+ const painted = paintedLineFromRenderLine(line5, hyperlinks2);
2663
2663
  const prefix = index === 0 ? affixes.lead : affixes.rest;
2664
2664
  const tail = index === lines.length - 1 ? affixes.tail : void 0;
2665
2665
  return /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
@@ -2811,16 +2811,7 @@ function MarkdownBlock({
2811
2811
  ) }, "tail")
2812
2812
  );
2813
2813
  }
2814
- if (out.length === 0 && tail === void 0) {
2815
- return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", width: "100%" });
2816
- }
2817
- if (out.length === 0) {
2818
- return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", width: "100%", children: /* @__PURE__ */ jsxs2(Text2, { children: [
2819
- prefix?.first,
2820
- tail
2821
- ] }) });
2822
- }
2823
- return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", width: "100%", children: out });
2814
+ return wrapMarkdownOutput(out, tail, prefix);
2824
2815
  }
2825
2816
  function renderBlockEntry(block, affixes, state, _scope) {
2826
2817
  const rangeKey2 = `${block.range.start}:${block.range.end}`;
@@ -2899,6 +2890,9 @@ function renderFullSource(source, bodyWidth, prefix, tail, settled) {
2899
2890
  };
2900
2891
  out.push(/* @__PURE__ */ jsx2(Fragment, { children: renderActiveTable(snap.rows, bodyWidth, tableAffixes, hyperlinks2) }, "full-active-table"));
2901
2892
  }
2893
+ return wrapMarkdownOutput(out, tail, prefix);
2894
+ }
2895
+ function wrapMarkdownOutput(out, tail, prefix) {
2902
2896
  if (out.length === 0 && tail === void 0) {
2903
2897
  return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", width: "100%" });
2904
2898
  }
@@ -3051,18 +3045,18 @@ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
3051
3045
  function formatSeconds(ms) {
3052
3046
  return (ms / 1e3).toFixed(1);
3053
3047
  }
3054
- function thinkingHeader(durationMs, expanded, live = false) {
3048
+ function thinkingHeader(durationMs, expanded, live = false, width) {
3055
3049
  const mark = expanded ? "\u25BE " : "";
3056
3050
  const icon = live ? getBrailleSpinnerFrame(durationMs) : "\u273B";
3057
- return paintRow([
3058
- styled(
3059
- `${mark}${icon} \u601D\u8003 (${formatSeconds(durationMs)}s)`,
3060
- "fgDim"
3061
- )
3062
- ]);
3051
+ const parts = [
3052
+ ...mark !== "" ? [styled(mark, "accentText")] : [],
3053
+ styled(`${icon} \u601D\u8003`, "accentText"),
3054
+ styled(` (${formatSeconds(durationMs)}s)`, "fgDim")
3055
+ ];
3056
+ return paintBackgroundRow(parts, "toolBg", width !== void 0 && width > 0 ? width : 0);
3063
3057
  }
3064
- function bodyRow(line8, key) {
3065
- return /* @__PURE__ */ jsx3(Text3, { children: paintRow([styled(` ${escapeContent(line8)}`, "fgDim")]) }, key);
3058
+ function bodyRow(line5, key, width) {
3059
+ return /* @__PURE__ */ jsx3(Text3, { wrap: "truncate", children: paintBackgroundRow([styled("\u2502 ", "accentText"), styled(escapeContent(line5), "fgDim")], "toolBg", width !== void 0 && width > 0 ? width : 0) }, key);
3066
3060
  }
3067
3061
  function ReasoningBlock({
3068
3062
  text,
@@ -3073,11 +3067,12 @@ function ReasoningBlock({
3073
3067
  }) {
3074
3068
  const { columns } = useWindowSize3();
3075
3069
  if (collapsed || text === "") return null;
3070
+ const width = maxCols ?? columns;
3076
3071
  const escaped = escapeContent(text);
3077
- const body = wrapDisplayLines(escaped, Math.max(1, (maxCols ?? columns) - 4));
3078
- return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", width: "100%", children: [
3079
- /* @__PURE__ */ jsx3(Text3, { children: thinkingHeader(durationMs, !live, live) }),
3080
- body.map((line8, index) => bodyRow(line8, index))
3072
+ const body = wrapDisplayLines(escaped, Math.max(1, width - 4));
3073
+ return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", width: "100%", backgroundColor: inkColor("toolBg"), children: [
3074
+ /* @__PURE__ */ jsx3(Text3, { wrap: "truncate", children: thinkingHeader(durationMs, !live, live, width) }),
3075
+ body.map((line5, index) => bodyRow(line5, index, width))
3081
3076
  ] });
3082
3077
  }
3083
3078
 
@@ -3085,19 +3080,26 @@ function ReasoningBlock({
3085
3080
  import { Box as Box4, Text as Text4 } from "ink";
3086
3081
 
3087
3082
  // tui-render/src/row-source.ts
3083
+ function clampSliceOffset(index, length) {
3084
+ const truncated = Math.trunc(index);
3085
+ return Math.min(length, Math.max(0, index < 0 ? length + truncated : truncated));
3086
+ }
3087
+ function resolveItemIndex(index, length) {
3088
+ const integer = Math.trunc(index);
3089
+ const absolute = integer < 0 ? length + integer : integer;
3090
+ return absolute < 0 || absolute >= length ? void 0 : absolute;
3091
+ }
3088
3092
  function indexedRows(length, read) {
3089
- const offset = (index) => Math.min(length, Math.max(0, index < 0 ? length + Math.trunc(index) : Math.trunc(index)));
3090
3093
  return Object.freeze({
3091
3094
  length,
3092
3095
  at(index) {
3093
- const integer = Math.trunc(index);
3094
- const absolute = integer < 0 ? length + integer : integer;
3095
- return absolute < 0 || absolute >= length ? void 0 : read(absolute);
3096
+ const absolute = resolveItemIndex(index, length);
3097
+ return absolute === void 0 ? void 0 : read(absolute);
3096
3098
  },
3097
3099
  slice(start = 0, end = length) {
3098
3100
  const out = [];
3099
- const last = offset(end);
3100
- for (let index = offset(start); index < last; index += 1) out.push(read(index));
3101
+ const last = clampSliceOffset(end, length);
3102
+ for (let index = clampSliceOffset(start, length); index < last; index += 1) out.push(read(index));
3101
3103
  return out;
3102
3104
  }
3103
3105
  });
@@ -3142,19 +3144,17 @@ var RowSequence = class {
3142
3144
  }
3143
3145
  return low;
3144
3146
  };
3145
- const offset = (index) => Math.min(length, Math.max(0, index < 0 ? length + Math.trunc(index) : Math.trunc(index)));
3146
3147
  return Object.freeze({
3147
3148
  length,
3148
3149
  at(index) {
3149
- const integer = Math.trunc(index);
3150
- const absolute = integer < 0 ? length + integer : integer;
3151
- if (absolute < 0 || absolute >= length) return void 0;
3150
+ const absolute = resolveItemIndex(index, length);
3151
+ if (absolute === void 0) return void 0;
3152
3152
  const segment2 = segments[locate(absolute)];
3153
3153
  return segment2.rows.at(absolute - segment2.start);
3154
3154
  },
3155
3155
  slice(start = 0, end = length) {
3156
- const first = offset(start);
3157
- const last = offset(end);
3156
+ const first = clampSliceOffset(start, length);
3157
+ const last = clampSliceOffset(end, length);
3158
3158
  const out = [];
3159
3159
  for (let index = locate(first); index < segments.length; index += 1) {
3160
3160
  const segment2 = segments[index];
@@ -3195,8 +3195,8 @@ function splitDiffLines(text) {
3195
3195
  return normalized.split(/\r?\n/u);
3196
3196
  }
3197
3197
  function diffLines(oldLines, newLines) {
3198
- if (oldLines.length === 0) return newLines.map((line8) => `+${line8}`);
3199
- if (newLines.length === 0) return oldLines.map((line8) => `-${line8}`);
3198
+ if (oldLines.length === 0) return newLines.map((line5) => `+${line5}`);
3199
+ if (newLines.length === 0) return oldLines.map((line5) => `-${line5}`);
3200
3200
  const m = oldLines.length;
3201
3201
  const n = newLines.length;
3202
3202
  if (m * n > 5e5) {
@@ -3216,9 +3216,9 @@ function diffLines(oldLines, newLines) {
3216
3216
  const midN = trimmedNew.length;
3217
3217
  const middle = [];
3218
3218
  if (midM === 0) {
3219
- for (const line8 of trimmedNew) middle.push(`+${line8}`);
3219
+ for (const line5 of trimmedNew) middle.push(`+${line5}`);
3220
3220
  } else if (midN === 0) {
3221
- for (const line8 of trimmedOld) middle.push(`-${line8}`);
3221
+ for (const line5 of trimmedOld) middle.push(`-${line5}`);
3222
3222
  } else {
3223
3223
  const stride = midN + 1;
3224
3224
  const dp = new Int32Array((midM + 1) * stride);
@@ -3259,8 +3259,8 @@ function diffLines(oldLines, newLines) {
3259
3259
  for (let k = 0; k < prefixCount; k++) {
3260
3260
  result.push(` ${oldLines[k]}`);
3261
3261
  }
3262
- for (const line8 of middle) {
3263
- result.push(line8);
3262
+ for (const line5 of middle) {
3263
+ result.push(line5);
3264
3264
  }
3265
3265
  for (let k = m - suffixCount; k < m; k++) {
3266
3266
  result.push(` ${oldLines[k]}`);
@@ -3295,7 +3295,7 @@ function createToolBodyDocument(card, options) {
3295
3295
  let lastPath;
3296
3296
  for (const diff of diffs) {
3297
3297
  if (diff.path !== lastPath) {
3298
- source.push({ text: `--- ${diff.path}`, token: "codeBg" });
3298
+ source.push({ text: `--- ${diff.path}`, token: "codeBg", diffKind: "header" });
3299
3299
  lastPath = diff.path;
3300
3300
  }
3301
3301
  const oldStart = diff.oldStart ?? (diff.oldText === null ? 0 : 1);
@@ -3309,7 +3309,7 @@ function createToolBodyDocument(card, options) {
3309
3309
  newLinesCount ??= splitDiffLines(diff.newText).length;
3310
3310
  } else if (diff.oldText === null) {
3311
3311
  const split = splitDiffLines(diff.newText);
3312
- lines = split.map((line8) => `+${line8}`);
3312
+ lines = split.map((line5) => `+${line5}`);
3313
3313
  oldLinesCount = 0;
3314
3314
  newLinesCount = split.length;
3315
3315
  } else {
@@ -3321,7 +3321,7 @@ function createToolBodyDocument(card, options) {
3321
3321
  }
3322
3322
  const oldHunk = `${oldStart}${oldLinesCount !== 1 ? `,${oldLinesCount}` : ""}`;
3323
3323
  const newHunk = `${newStart}${newLinesCount !== 1 ? `,${newLinesCount}` : ""}`;
3324
- source.push({ text: `@@ -${oldHunk} +${newHunk} @@`, token: "codeBg" });
3324
+ source.push({ text: `@@ -${oldHunk} +${newHunk} @@`, token: "codeBg", diffKind: "hunk" });
3325
3325
  const maxLine = Math.max(oldStart + oldLinesCount, newStart + newLinesCount, 1);
3326
3326
  const gutterWidth = Math.max(3, String(maxLine).length);
3327
3327
  let curOld = oldStart === 0 ? 1 : oldStart;
@@ -3330,20 +3330,20 @@ function createToolBodyDocument(card, options) {
3330
3330
  if (raw.startsWith("\\")) continue;
3331
3331
  if (raw.startsWith("-")) {
3332
3332
  const num = String(curOld).padStart(gutterWidth, " ");
3333
- source.push({ text: `${num} \u2502 - ${raw.slice(1)}`, token: "codeBg" });
3333
+ source.push({ text: `${num} \u2502 - ${raw.slice(1)}`, token: "codeBg", diffKind: "delete" });
3334
3334
  curOld++;
3335
3335
  } else if (raw.startsWith("+")) {
3336
3336
  const num = String(curNew).padStart(gutterWidth, " ");
3337
- source.push({ text: `${num} \u2502 + ${raw.slice(1)}`, token: "codeBg" });
3337
+ source.push({ text: `${num} \u2502 + ${raw.slice(1)}`, token: "codeBg", diffKind: "add" });
3338
3338
  curNew++;
3339
3339
  } else if (raw.startsWith(" ")) {
3340
3340
  const num = String(curNew).padStart(gutterWidth, " ");
3341
- source.push({ text: `${num} \u2502 ${raw.slice(1)}`, token: "codeBg" });
3341
+ source.push({ text: `${num} \u2502 ${raw.slice(1)}`, token: "codeBg", diffKind: "context" });
3342
3342
  curOld++;
3343
3343
  curNew++;
3344
3344
  } else {
3345
3345
  const num = String(curNew).padStart(gutterWidth, " ");
3346
- source.push({ text: `${num} \u2502 ${raw}`, token: "codeBg" });
3346
+ source.push({ text: `${num} \u2502 ${raw}`, token: "codeBg", diffKind: "context" });
3347
3347
  curOld++;
3348
3348
  curNew++;
3349
3349
  }
@@ -3367,8 +3367,8 @@ function createToolBodyDocument(card, options) {
3367
3367
  }
3368
3368
  case "read":
3369
3369
  if (result?.card === "read") section(tuiCopy("result", options.locale), indexedRows(result.lines.length, (index) => {
3370
- const line8 = result.lines[index];
3371
- return { text: `${line8.number} ${line8.text}`, token: "codeBg" };
3370
+ const line5 = result.lines[index];
3371
+ return { text: `${line5.number} ${line5.text}`, token: "codeBg" };
3372
3372
  }));
3373
3373
  break;
3374
3374
  case "web":
@@ -3412,22 +3412,26 @@ function fragmentEnd(text, start, width) {
3412
3412
  }
3413
3413
  function planToolBodyWindow(document, cursor, width, maxRows) {
3414
3414
  const fragments = [];
3415
- let line8 = cursor.line;
3415
+ let line5 = cursor.line;
3416
3416
  let offset = cursor.offset;
3417
- while (line8 < document.length && fragments.length < maxRows) {
3418
- const source = document.at(line8);
3417
+ while (line5 < document.length && fragments.length < maxRows) {
3418
+ const source = document.at(line5);
3419
3419
  const end = fragmentEnd(source.text, offset, width);
3420
- fragments.push({ line: line8, start: offset, end });
3420
+ fragments.push({ line: line5, start: offset, end });
3421
3421
  if (end === source.text.length) {
3422
- line8 += 1;
3422
+ line5 += 1;
3423
3423
  offset = 0;
3424
3424
  } else offset = end;
3425
3425
  }
3426
- return { fragments, next: line8 < document.length ? { line: line8, offset } : void 0, remainingLines: document.length - line8 };
3426
+ return { fragments, next: line5 < document.length ? { line: line5, offset } : void 0, remainingLines: document.length - line5 };
3427
3427
  }
3428
3428
  function materializeToolBodyRow(document, fragment) {
3429
3429
  const source = document.at(fragment.line);
3430
- return { text: escapeToolText(source.text.slice(fragment.start, fragment.end)), token: source.token };
3430
+ return {
3431
+ text: escapeToolText(source.text.slice(fragment.start, fragment.end)),
3432
+ token: source.token,
3433
+ ...source.diffKind !== void 0 ? { diffKind: source.diffKind } : {}
3434
+ };
3431
3435
  }
3432
3436
  function toolCardOriginalText(card, options) {
3433
3437
  const parts = [card.name, tuiCopy("arguments", options.locale), card.arguments];
@@ -3448,8 +3452,8 @@ function toolCardDisplayStatus(card) {
3448
3452
  }
3449
3453
  function collapsedResultTail(text) {
3450
3454
  if (text === void 0) return void 0;
3451
- const line8 = text.split(/\r?\n/u).map((item) => item.trim()).filter(Boolean).at(-1);
3452
- return line8 === void 0 ? void 0 : escapeContent(line8);
3455
+ const line5 = text.split(/\r?\n/u).map((item) => item.trim()).filter(Boolean).at(-1);
3456
+ return line5 === void 0 ? void 0 : escapeContent(line5);
3453
3457
  }
3454
3458
  function collapsedFailureSummary(card) {
3455
3459
  const terminal = card.resultView?.card === "terminal" ? card.resultView : void 0;
@@ -3678,8 +3682,66 @@ function toolHeadingRow(card, width, expanded, locale) {
3678
3682
  if (summary !== void 0 && available >= 2) parts.push({ text: ` ${truncateDisplay(summary, available)}`, token: "fgDim", ...href === void 0 ? {} : { href } });
3679
3683
  return toolRow(parts, 0, width, "toolBg");
3680
3684
  }
3681
- function toolBodyRenderRow(line8, index, width) {
3682
- return toolRow([{ text: ` ${line8.text}`, token: line8.token === "codeBg" ? "fgSoft" : "fgDim" }], index, width, line8.token === "codeBg" ? "codeBg" : "toolBg");
3685
+ var GUTTER_SEPARATOR = " \u2502 ";
3686
+ function inferDiffKind(text) {
3687
+ if (text.startsWith("--- ")) return "header";
3688
+ if (/^@@ -\d+.* @@$/u.test(text)) return "hunk";
3689
+ if (text.includes(" \u2502 + ")) return "add";
3690
+ if (text.includes(" \u2502 - ")) return "delete";
3691
+ if (/^\s*\d+ │ /u.test(text)) return "context";
3692
+ return void 0;
3693
+ }
3694
+ function formatDiffParts(text, kind) {
3695
+ switch (kind) {
3696
+ case "header":
3697
+ return [{ text: ` ${text}`, token: "fgDim" }];
3698
+ case "hunk":
3699
+ return [{ text: ` ${text}`, token: "accentText" }];
3700
+ case "add": {
3701
+ const sepIndex = text.indexOf(GUTTER_SEPARATOR);
3702
+ if (sepIndex !== -1) {
3703
+ const gutter = text.slice(0, sepIndex + GUTTER_SEPARATOR.length);
3704
+ const content = text.slice(sepIndex + GUTTER_SEPARATOR.length);
3705
+ return [
3706
+ { text: ` ${gutter}`, token: "fgDim" },
3707
+ { text: content, token: "success" }
3708
+ ];
3709
+ }
3710
+ return [{ text: ` ${text}`, token: "success" }];
3711
+ }
3712
+ case "delete": {
3713
+ const sepIndex = text.indexOf(GUTTER_SEPARATOR);
3714
+ if (sepIndex !== -1) {
3715
+ const gutter = text.slice(0, sepIndex + GUTTER_SEPARATOR.length);
3716
+ const content = text.slice(sepIndex + GUTTER_SEPARATOR.length);
3717
+ return [
3718
+ { text: ` ${gutter}`, token: "fgDim" },
3719
+ { text: content, token: "error" }
3720
+ ];
3721
+ }
3722
+ return [{ text: ` ${text}`, token: "error" }];
3723
+ }
3724
+ case "context": {
3725
+ const sepIndex = text.indexOf(GUTTER_SEPARATOR);
3726
+ if (sepIndex !== -1) {
3727
+ const gutter = text.slice(0, sepIndex + GUTTER_SEPARATOR.length);
3728
+ const content = text.slice(sepIndex + GUTTER_SEPARATOR.length);
3729
+ return [
3730
+ { text: ` ${gutter}`, token: "fgDim" },
3731
+ { text: content, token: "fgSoft" }
3732
+ ];
3733
+ }
3734
+ return [{ text: ` ${text}`, token: "fgSoft" }];
3735
+ }
3736
+ }
3737
+ }
3738
+ function toolBodyRenderRow(line5, index, width) {
3739
+ const bg = line5.token === "codeBg" ? "codeBg" : "toolBg";
3740
+ const diffKind = line5.diffKind ?? inferDiffKind(line5.text);
3741
+ if (diffKind !== void 0) {
3742
+ return toolRow(formatDiffParts(line5.text, diffKind), index, width, bg);
3743
+ }
3744
+ return toolRow([{ text: ` ${line5.text}`, token: line5.token === "codeBg" ? "fgSoft" : "fgDim" }], index, width, bg);
3683
3745
  }
3684
3746
  function toolRemainingRow(remaining, width, index, locale) {
3685
3747
  const action = tuiCopy("toolDetails", locale);
@@ -3828,7 +3890,7 @@ import { jsx as jsx4 } from "react/jsx-runtime";
3828
3890
  function ToolCard({ card, expanded = false, maxCols = 80, locale = "zh-CN", policy = toolPolicyDefaults() }) {
3829
3891
  const cache2 = new ToolRowCache(policy);
3830
3892
  const rows = cache2.rows(card.callId, card, maxCols, expanded, locale).slice();
3831
- return /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", width: "100%", backgroundColor: inkColor("toolBg"), children: rows.map((line8, index) => /* @__PURE__ */ jsx4(Text4, { wrap: "truncate", children: paintLineFromRenderLine(line8, hyperlinksEnabled()) }, index)) });
3893
+ return /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", width: "100%", backgroundColor: inkColor("toolBg"), children: rows.map((line5, index) => /* @__PURE__ */ jsx4(Text4, { wrap: "truncate", children: paintLineFromRenderLine(line5, hyperlinksEnabled()) }, index)) });
3832
3894
  }
3833
3895
 
3834
3896
  // tui-render/src/tool-presenter-cache.ts
@@ -3899,10 +3961,12 @@ var PlainTextRowCache = class {
3899
3961
  * @param id - stable owning text id.
3900
3962
  * @param source - canonical, unabridged reasoning text.
3901
3963
  * @param width - body width excluding its two-column indentation.
3964
+ * @param backgroundColumns - optional surface width in terminal columns.
3965
+ * @param background - optional surface token painted behind every row.
3902
3966
  * @returns every physical body row; the main transcript owns clipping and scrolling.
3903
3967
  */
3904
- rows(id, source, width) {
3905
- const key = `${id}\0${width}`;
3968
+ rows(id, source, width, backgroundColumns, background = "toolBg") {
3969
+ const key = `${id}\0${width}\0${backgroundColumns ?? ""}\0${background}`;
3906
3970
  const cached = this.entries.get(key);
3907
3971
  if (cached?.source === source) {
3908
3972
  this.entries.delete(key);
@@ -3911,30 +3975,51 @@ var PlainTextRowCache = class {
3911
3975
  }
3912
3976
  if (cached !== void 0) this.remove(key, cached);
3913
3977
  for (const entry of this.entries.values()) {
3914
- if (entry.source === source && entry.naturalWidth <= Math.min(width, entry.width)) {
3978
+ if (entry.source === source && entry.naturalWidth <= Math.min(width, entry.width) && (backgroundColumns === void 0 || entry.backgroundColumns === backgroundColumns) && entry.background === background) {
3915
3979
  this.remember(key, entry);
3916
3980
  return entry.rows;
3917
3981
  }
3918
3982
  }
3919
3983
  const wrapped = [];
3920
3984
  let naturalWidth = 0;
3921
- for (const line8 of escapeContent(source).replace(/\t/gu, "\\t").split("\n")) {
3922
- const columns = displayWidth(line8);
3985
+ for (const line5 of escapeContent(source).replace(/\t/gu, "\\t").split("\n")) {
3986
+ const columns = displayWidth(line5);
3923
3987
  naturalWidth = Math.max(naturalWidth, columns);
3924
- if (columns <= width) wrapped.push(line8);
3925
- else wrapped.push(...wrapDisplayLines(line8, width));
3988
+ if (columns <= width) wrapped.push(line5);
3989
+ else wrapped.push(...wrapDisplayLines(line5, width));
3926
3990
  }
3927
3991
  const materialized = /* @__PURE__ */ new Map();
3928
3992
  const rows = indexedRows(wrapped.length, (index) => {
3929
3993
  const hit = materialized.get(index);
3930
3994
  if (hit !== void 0) return hit;
3931
- const text = ` ${wrapped[index]}`;
3995
+ const text = `\u2502 ${wrapped[index]}`;
3932
3996
  const columns = displayWidth(text);
3933
- const row = { text, displayWidth: columns, spans: [{ start: 0, end: columns, token: "fgDim", bold: false }], rowInBlock: index + 1, sourceStart: -1, sourceEnd: -1, rawTail: false };
3997
+ const row = {
3998
+ text,
3999
+ displayWidth: columns,
4000
+ spans: [
4001
+ { start: 0, end: 2, token: "accentText", bold: false },
4002
+ { start: 2, end: columns, token: "fgDim", bold: false }
4003
+ ],
4004
+ rowInBlock: index + 1,
4005
+ sourceStart: -1,
4006
+ sourceEnd: -1,
4007
+ rawTail: false,
4008
+ background,
4009
+ ...backgroundColumns !== void 0 ? { backgroundColumns } : {}
4010
+ };
3934
4011
  materialized.set(index, row);
3935
4012
  return row;
3936
4013
  });
3937
- this.remember(key, { source, rows, naturalWidth, width, bytes: Buffer.byteLength(source) + wrapped.length * 128 });
4014
+ this.remember(key, {
4015
+ source,
4016
+ rows,
4017
+ naturalWidth,
4018
+ width,
4019
+ bytes: Buffer.byteLength(source) + wrapped.length * 128,
4020
+ ...backgroundColumns !== void 0 ? { backgroundColumns } : {},
4021
+ background
4022
+ });
3938
4023
  return rows;
3939
4024
  }
3940
4025
  remember(key, entry) {
@@ -4287,6 +4372,19 @@ function layoutState(state, action) {
4287
4372
  if (state.contentRows === next.contentRows && state.viewportRows === next.viewportRows && state.offsetFromBottom === next.offsetFromBottom && state.unseenRows === next.unseenRows && state.anchor?.blockId === next.anchor?.blockId && state.anchor?.rowWithinBlock === next.anchor?.rowWithinBlock && state.anchor?.viewportRow === next.anchor?.viewportRow && sameBlocks(state.blocks, next.blocks)) return state;
4288
4373
  return next;
4289
4374
  }
4375
+ function applyOffsetAndFollow(state, offsetFromBottom, follow) {
4376
+ if (offsetFromBottom === state.offsetFromBottom && follow === state.follow && (follow ? 0 : state.unseenRows) === state.unseenRows) {
4377
+ return state;
4378
+ }
4379
+ const nextTop = topRow({ ...state, offsetFromBottom });
4380
+ return {
4381
+ ...state,
4382
+ follow,
4383
+ offsetFromBottom,
4384
+ unseenRows: follow ? 0 : state.unseenRows,
4385
+ anchor: follow ? void 0 : anchorForRow(nextTop, state.blocks)
4386
+ };
4387
+ }
4290
4388
  function reduceTranscriptViewport(state, action) {
4291
4389
  switch (action.kind) {
4292
4390
  case "layout":
@@ -4303,17 +4401,7 @@ function reduceTranscriptViewport(state, action) {
4303
4401
  state.viewportRows
4304
4402
  );
4305
4403
  const follow = offsetFromBottom === 0 ? true : action.delta > 0 ? false : state.follow;
4306
- if (offsetFromBottom === state.offsetFromBottom && follow === state.follow && (follow ? 0 : state.unseenRows) === state.unseenRows) {
4307
- return state;
4308
- }
4309
- const nextTop = topRow({ ...state, offsetFromBottom });
4310
- return {
4311
- ...state,
4312
- follow,
4313
- offsetFromBottom,
4314
- unseenRows: follow ? 0 : state.unseenRows,
4315
- anchor: follow ? void 0 : anchorForRow(nextTop, state.blocks)
4316
- };
4404
+ return applyOffsetAndFollow(state, offsetFromBottom, follow);
4317
4405
  }
4318
4406
  case "offset": {
4319
4407
  const offsetFromBottom = clampOffset(
@@ -4321,35 +4409,13 @@ function reduceTranscriptViewport(state, action) {
4321
4409
  state.contentRows,
4322
4410
  state.viewportRows
4323
4411
  );
4324
- const follow = offsetFromBottom === 0;
4325
- if (offsetFromBottom === state.offsetFromBottom && follow === state.follow && (follow ? 0 : state.unseenRows) === state.unseenRows) {
4326
- return state;
4327
- }
4328
- const nextTop = topRow({ ...state, offsetFromBottom });
4329
- return {
4330
- ...state,
4331
- follow,
4332
- offsetFromBottom,
4333
- unseenRows: follow ? 0 : state.unseenRows,
4334
- anchor: follow ? void 0 : anchorForRow(nextTop, state.blocks)
4335
- };
4412
+ return applyOffsetAndFollow(state, offsetFromBottom, offsetFromBottom === 0);
4336
4413
  }
4337
4414
  case "position": {
4338
4415
  const available = maxOffset(state.contentRows, state.viewportRows);
4339
4416
  const fraction = Math.max(0, Math.min(action.fraction, 1));
4340
4417
  const offsetFromBottom = Math.round(available * (1 - fraction));
4341
- const follow = offsetFromBottom === 0;
4342
- if (offsetFromBottom === state.offsetFromBottom && follow === state.follow && (follow ? 0 : state.unseenRows) === state.unseenRows) {
4343
- return state;
4344
- }
4345
- const nextTop = topRow({ ...state, offsetFromBottom });
4346
- return {
4347
- ...state,
4348
- follow,
4349
- offsetFromBottom,
4350
- unseenRows: follow ? 0 : state.unseenRows,
4351
- anchor: follow ? void 0 : anchorForRow(nextTop, state.blocks)
4352
- };
4418
+ return applyOffsetAndFollow(state, offsetFromBottom, offsetFromBottom === 0);
4353
4419
  }
4354
4420
  case "edge": {
4355
4421
  if (action.edge === "latest") {
@@ -4608,22 +4674,22 @@ function visibleFrameSnapshot() {
4608
4674
  return publishedSnapshot;
4609
4675
  }
4610
4676
  var lineIdentityCache = /* @__PURE__ */ new WeakMap();
4611
- function physicalLineIdentity(line8) {
4612
- let cached = lineIdentityCache.get(line8);
4677
+ function physicalLineIdentity(line5) {
4678
+ let cached = lineIdentityCache.get(line5);
4613
4679
  if (cached !== void 0) return cached;
4614
4680
  cached = JSON.stringify([
4615
- line8.text,
4616
- line8.displayWidth,
4617
- line8.background ?? "bg",
4618
- line8.backgroundColumns ?? line8.displayWidth,
4619
- line8.spans.map((span) => [
4681
+ line5.text,
4682
+ line5.displayWidth,
4683
+ line5.background ?? "bg",
4684
+ line5.backgroundColumns ?? line5.displayWidth,
4685
+ line5.spans.map((span) => [
4620
4686
  span.text,
4621
4687
  span.token,
4622
4688
  span.bold === true ? 1 : 0,
4623
4689
  span.href ?? ""
4624
4690
  ])
4625
4691
  ]);
4626
- lineIdentityCache.set(line8, cached);
4692
+ lineIdentityCache.set(line5, cached);
4627
4693
  return cached;
4628
4694
  }
4629
4695
  function createFrameSnapshotRow(input) {
@@ -4644,8 +4710,8 @@ function sameGeometry(a, b) {
4644
4710
  function screenRowKey(row) {
4645
4711
  return row.row << 16 | row.col;
4646
4712
  }
4647
- function paintedColumns(line8) {
4648
- return line8.backgroundColumns ?? line8.displayWidth;
4713
+ function paintedColumns(line5) {
4714
+ return line5.backgroundColumns ?? line5.displayWidth;
4649
4715
  }
4650
4716
  function diffVisibleFrameSnapshots(previous, next) {
4651
4717
  const forced = previous === void 0 || !sameGeometry(previous.geometry, next.geometry);
@@ -4761,24 +4827,24 @@ function railOverlay(tier, force = false) {
4761
4827
  return cells === "" ? "" : `\x1B7${cells}\x1B8`;
4762
4828
  }
4763
4829
  var paintedPhysicalLineCache = /* @__PURE__ */ new WeakMap();
4764
- function paintPhysicalLine(line8, tier) {
4830
+ function paintPhysicalLine(line5, tier) {
4765
4831
  const hyperlinks2 = hyperlinksEnabled();
4766
4832
  const cacheKey = `${tier}:${hyperlinks2 ? 1 : 0}`;
4767
- let byTier = paintedPhysicalLineCache.get(line8);
4833
+ let byTier = paintedPhysicalLineCache.get(line5);
4768
4834
  if (byTier === void 0) {
4769
4835
  byTier = /* @__PURE__ */ new Map();
4770
- paintedPhysicalLineCache.set(line8, byTier);
4836
+ paintedPhysicalLineCache.set(line5, byTier);
4771
4837
  }
4772
4838
  const cached = byTier.get(cacheKey);
4773
4839
  if (cached !== void 0) return cached;
4774
- const parts = line8.spans.map((span) => {
4840
+ const parts = line5.spans.map((span) => {
4775
4841
  const text = styled(span.text, span.token, tier, span.bold);
4776
4842
  return span.href !== void 0 && hyperlinks2 && isOsc8Href(span.href) ? wrapOsc8(text, span.href) : text;
4777
4843
  });
4778
- const painted = line8.background !== void 0 && line8.background !== "bg" ? paintBackgroundRow(
4844
+ const painted = line5.background !== void 0 && line5.background !== "bg" ? paintBackgroundRow(
4779
4845
  parts,
4780
- line8.background,
4781
- line8.backgroundColumns ?? Math.max(1, line8.displayWidth),
4846
+ line5.background,
4847
+ line5.backgroundColumns ?? Math.max(1, line5.displayWidth),
4782
4848
  tier
4783
4849
  ) : paintRow(parts, tier);
4784
4850
  byTier.set(cacheKey, painted);
@@ -4936,21 +5002,21 @@ function wrapStdoutForFrameBg(stdout, getTier = currentTier, frameMetrics) {
4936
5002
  var TERMINAL_CONTROL_PATTERN = /\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b\[[0-?]*[ -/]*[@-~]|\x1b./gu;
4937
5003
  function countWrittenCells(chunk) {
4938
5004
  const printable = chunk.replace(TERMINAL_CONTROL_PATTERN, (control) => control.startsWith("\x1B]") || control.startsWith("\x1B[") && control.endsWith("m") ? "" : "\n").replace(/[\u0000-\u0009\u000b-\u001f\u007f]/gu, "");
4939
- return printable.split("\n").reduce((cells, line8) => cells + displayWidth(line8), 0);
5005
+ return printable.split("\n").reduce((cells, line5) => cells + displayWidth(line5), 0);
4940
5006
  }
4941
5007
 
4942
5008
  // tui-render/src/screen-atlas.ts
4943
5009
  var GRAPHEME2 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
4944
- function paintSnapshotLine(line8) {
4945
- const parts = line8.spans.map((span) => {
5010
+ function paintSnapshotLine(line5) {
5011
+ const parts = line5.spans.map((span) => {
4946
5012
  const painted = styled(span.text, span.token, void 0, span.bold);
4947
- const href = span.href ?? line8.osc8?.href;
5013
+ const href = span.href ?? line5.osc8?.href;
4948
5014
  return href === void 0 || !hyperlinksEnabled() ? painted : wrapOsc8(painted, href);
4949
5015
  });
4950
- return line8.background !== void 0 && line8.background !== "bg" ? paintBackgroundRow(
5016
+ return line5.background !== void 0 && line5.background !== "bg" ? paintBackgroundRow(
4951
5017
  parts,
4952
- line8.background,
4953
- line8.backgroundColumns ?? Math.max(1, line8.displayWidth)
5018
+ line5.background,
5019
+ line5.backgroundColumns ?? Math.max(1, line5.displayWidth)
4954
5020
  ) : paintRow(parts);
4955
5021
  }
4956
5022
  function orderedPoints(a, b) {
@@ -5243,17 +5309,55 @@ var ScreenAtlas = class {
5243
5309
  for (let row = start.row; row <= end.row; row++) {
5244
5310
  const from = row === start.row ? start.col : 1;
5245
5311
  const to = row === end.row ? end.col : this.width;
5246
- let line8 = "";
5312
+ let line5 = "";
5247
5313
  for (let col = from; col <= to; col++) {
5248
5314
  if (this.isSnapshotRailControlCell(col, row)) continue;
5249
5315
  const cell = this.cellAt(col, row);
5250
5316
  if (cell === void 0 || cell.ch === "") continue;
5251
- line8 += cell.ch;
5317
+ line5 += cell.ch;
5252
5318
  }
5253
- lines.push(line8.replace(/ +$/u, ""));
5319
+ lines.push(line5.replace(/ +$/u, ""));
5254
5320
  }
5255
5321
  return lines.join("\n");
5256
5322
  }
5323
+ collectRowTextRuns(row, from, to, onRun) {
5324
+ let run = "";
5325
+ let runCol = 0;
5326
+ const flush = () => {
5327
+ if (run === "" || runCol === 0) return;
5328
+ onRun(runCol, run);
5329
+ run = "";
5330
+ runCol = 0;
5331
+ };
5332
+ for (let col = from; col <= to; col++) {
5333
+ if (this.isSnapshotRailControlCell(col, row)) {
5334
+ flush();
5335
+ continue;
5336
+ }
5337
+ const cell = this.cellAt(col, row);
5338
+ if (cell === void 0 || !cell.written || cell.ch === "") {
5339
+ flush();
5340
+ continue;
5341
+ }
5342
+ if (run === "") runCol = col;
5343
+ run += cell.ch;
5344
+ }
5345
+ flush();
5346
+ }
5347
+ /**
5348
+ * Iterate over screen rows within a selection range, calculating the column span.
5349
+ * @param a - one endpoint.
5350
+ * @param b - the other endpoint.
5351
+ * @param callback - visitor receiving row index and column bounds [from, to].
5352
+ */
5353
+ forEachRowInRange(a, b, callback) {
5354
+ const { start, end } = orderedPoints(a, b);
5355
+ for (let row = start.row; row <= end.row; row++) {
5356
+ const from = row === start.row ? start.col : 1;
5357
+ const to = row === end.row ? end.col : this.width;
5358
+ callback(row, from, to);
5359
+ }
5360
+ }
5257
5361
  /**
5258
5362
  * Reverse-video overlay that rewrites selectable cells. Published rail cells
5259
5363
  * are excluded. Empty when the range has no glyphs.
@@ -5262,34 +5366,12 @@ var ScreenAtlas = class {
5262
5366
  * @returns CUP + reverse SGR bytes.
5263
5367
  */
5264
5368
  selectionOverlay(a, b) {
5265
- const { start, end } = orderedPoints(a, b);
5266
5369
  let out = "";
5267
- for (let row = start.row; row <= end.row; row++) {
5268
- const from = row === start.row ? start.col : 1;
5269
- const to = row === end.row ? end.col : this.width;
5270
- let run = "";
5271
- let runCol = 0;
5272
- const flush = () => {
5273
- if (run === "" || runCol === 0) return;
5370
+ this.forEachRowInRange(a, b, (row, from, to) => {
5371
+ this.collectRowTextRuns(row, from, to, (runCol, run) => {
5274
5372
  out += `\x1B[${row};${runCol}H\x1B[7m${run}\x1B[27m`;
5275
- run = "";
5276
- runCol = 0;
5277
- };
5278
- for (let col = from; col <= to; col++) {
5279
- if (this.isSnapshotRailControlCell(col, row)) {
5280
- flush();
5281
- continue;
5282
- }
5283
- const cell = this.cellAt(col, row);
5284
- if (cell === void 0 || !cell.written || cell.ch === "") {
5285
- flush();
5286
- continue;
5287
- }
5288
- if (run === "") runCol = col;
5289
- run += cell.ch;
5290
- }
5291
- flush();
5292
- }
5373
+ });
5374
+ });
5293
5375
  return out;
5294
5376
  }
5295
5377
  /**
@@ -5301,39 +5383,17 @@ var ScreenAtlas = class {
5301
5383
  * @returns CUP + normal painted runs for the occupied cells.
5302
5384
  */
5303
5385
  restoreOverlay(a, b) {
5304
- const { start, end } = orderedPoints(a, b);
5305
5386
  let out = "";
5306
- for (let row = start.row; row <= end.row; row++) {
5307
- const from = row === start.row ? start.col : 1;
5308
- const to = row === end.row ? end.col : this.width;
5387
+ this.forEachRowInRange(a, b, (row, from, to) => {
5309
5388
  const snapshotRow = this.snapshotRows.get(row);
5310
5389
  if (snapshotRow !== void 0 && !this.snapshotRowOverlapsRailControl(snapshotRow) && from <= snapshotRow.col + snapshotRow.line.displayWidth - 1 && to >= snapshotRow.col) {
5311
5390
  out += `\x1B[${row};${snapshotRow.col}H${paintSnapshotLine(snapshotRow.line)}`;
5312
- continue;
5391
+ return;
5313
5392
  }
5314
- let run = "";
5315
- let runCol = 0;
5316
- const flush = () => {
5317
- if (run === "" || runCol === 0) return;
5393
+ this.collectRowTextRuns(row, from, to, (runCol, run) => {
5318
5394
  out += `\x1B[${row};${runCol}H${paintRow([styled(run, "fg")])}`;
5319
- run = "";
5320
- runCol = 0;
5321
- };
5322
- for (let col = from; col <= to; col++) {
5323
- if (this.isSnapshotRailControlCell(col, row)) {
5324
- flush();
5325
- continue;
5326
- }
5327
- const cell = this.cellAt(col, row);
5328
- if (cell === void 0 || !cell.written || cell.ch === "") {
5329
- flush();
5330
- continue;
5331
- }
5332
- if (run === "") runCol = col;
5333
- run += cell.ch;
5334
- }
5335
- flush();
5336
- }
5395
+ });
5396
+ });
5337
5397
  return out;
5338
5398
  }
5339
5399
  blank() {
@@ -6155,23 +6215,23 @@ function appendMarkdownBlock(out, lines) {
6155
6215
  if (out.length > 0) out.push(MARKDOWN_BLOCK_GAP_LINE);
6156
6216
  out.push(...lines);
6157
6217
  }
6158
- function wrapRawTailRows(line8, width) {
6159
- const pieces = wrapDisplayLines(line8.text, Math.max(1, width));
6160
- const style = line8.spans[0] ?? {
6218
+ function wrapRawTailRows(line5, width) {
6219
+ const pieces = wrapDisplayLines(line5.text, Math.max(1, width));
6220
+ const style = line5.spans[0] ?? {
6161
6221
  start: 0,
6162
- end: line8.displayWidth,
6222
+ end: line5.displayWidth,
6163
6223
  token: "fg",
6164
6224
  bold: false
6165
6225
  };
6166
6226
  return pieces.map((text, index) => {
6167
- const row = lineForText(text, style.token, style.bold, line8.rowInBlock + index);
6227
+ const row = lineForText(text, style.token, style.bold, line5.rowInBlock + index);
6168
6228
  return {
6169
6229
  ...row,
6170
- sourceStart: index === 0 ? line8.sourceStart : -1,
6171
- sourceEnd: index === pieces.length - 1 ? line8.sourceEnd : -1,
6230
+ sourceStart: index === 0 ? line5.sourceStart : -1,
6231
+ sourceEnd: index === pieces.length - 1 ? line5.sourceEnd : -1,
6172
6232
  rawTail: true,
6173
- ...line8.background === void 0 ? {} : { background: line8.background },
6174
- ...line8.backgroundColumns === void 0 ? {} : { backgroundColumns: line8.backgroundColumns }
6233
+ ...line5.background === void 0 ? {} : { background: line5.background },
6234
+ ...line5.backgroundColumns === void 0 ? {} : { backgroundColumns: line5.backgroundColumns }
6175
6235
  };
6176
6236
  });
6177
6237
  }
@@ -6196,22 +6256,40 @@ function projectReasoningEntry(entry, scope) {
6196
6256
  return { revision: 0, sourceLength: entry.source.length, lines: [] };
6197
6257
  }
6198
6258
  const icon = live ? getBrailleSpinnerFrame(reasoningDurationMs) : "\u273B";
6199
- const headerText = `${live ? "" : "\u25BE "}${icon} \u601D\u8003 (${secondsLabel}s)`;
6200
- const lines = [
6201
- lineForText(headerText, "fgDim", false, 0)
6202
- ];
6259
+ const prefix = live ? "" : "\u25BE ";
6260
+ const headerLine = surfaceLine([
6261
+ ...prefix !== "" ? [{ text: prefix, token: "accentText", bold: false }] : [],
6262
+ { text: `${icon} \u601D\u8003`, token: "accentText", bold: false },
6263
+ { text: ` (${secondsLabel}s)`, token: "fgDim", bold: false }
6264
+ ], 0, "toolBg", scope.width);
6265
+ const lines = [headerLine];
6203
6266
  const escaped = escapeContent(entry.source);
6204
6267
  const body = wrapDisplayLines(escaped, Math.max(1, scope.width - 4));
6205
6268
  for (const row of body) {
6206
- lines.push(lineForText(` ${row}`, "fgDim", false, lines.length));
6269
+ const text = `\u2502 ${row}`;
6270
+ const cols = displayWidth(text);
6271
+ lines.push({
6272
+ text,
6273
+ displayWidth: cols,
6274
+ spans: [
6275
+ { start: 0, end: 2, token: "accentText", bold: false },
6276
+ { start: 2, end: cols, token: "fgDim", bold: false }
6277
+ ],
6278
+ rowInBlock: lines.length,
6279
+ sourceStart: -1,
6280
+ sourceEnd: -1,
6281
+ rawTail: false,
6282
+ background: "toolBg",
6283
+ backgroundColumns: scope.width
6284
+ });
6207
6285
  }
6208
6286
  return { revision: 0, sourceLength: entry.source.length, lines };
6209
6287
  }
6210
6288
  function projectToolCardEntry(entry, scope) {
6211
6289
  const card = entry.meta?.toolCard;
6212
6290
  if (card === void 0) {
6213
- const line8 = lineForText(entry.source, "fg", false, 0);
6214
- return { revision: 0, sourceLength: entry.source.length, lines: [line8] };
6291
+ const line5 = lineForText(entry.source, "fg", false, 0);
6292
+ return { revision: 0, sourceLength: entry.source.length, lines: [line5] };
6215
6293
  }
6216
6294
  const cache2 = new ToolRowCache(toolPolicyDefaults());
6217
6295
  const lines = cache2.rows(entry.id, card, scope.width, scope.fold.tools, scope.locale ?? "zh-CN").slice();
@@ -6221,8 +6299,8 @@ function projectDividerEntry(entry, scope) {
6221
6299
  if (entry.source === "" || entry.source === "\u2500") {
6222
6300
  return { revision: 0, sourceLength: entry.source.length, lines: [messageSeparatorLine(scope.width)] };
6223
6301
  }
6224
- const line8 = lineForText(entry.source, "fgDim", false, 0);
6225
- return { revision: 0, sourceLength: entry.source.length, lines: [line8] };
6302
+ const line5 = lineForText(entry.source, "fgDim", false, 0);
6303
+ return { revision: 0, sourceLength: entry.source.length, lines: [line5] };
6226
6304
  }
6227
6305
  function projectCompactionEntry(entry) {
6228
6306
  const shadowed = entry.meta?.compactionShadowedCount;
@@ -6266,8 +6344,8 @@ function projectTurnTailEntry(entry, scope) {
6266
6344
  function projectToolSummaryEntry(entry, scope) {
6267
6345
  const status = entry.meta?.toolSummaryStatus;
6268
6346
  const token = status === "error" ? "error" : status === "running" ? "accentText" : "fgDim";
6269
- const line8 = lineForText(entry.source, token, false, 0, "toolBg", scope.width);
6270
- return { revision: 0, sourceLength: entry.source.length, lines: [line8] };
6347
+ const line5 = lineForText(entry.source, token, false, 0, "toolBg", scope.width);
6348
+ return { revision: 0, sourceLength: entry.source.length, lines: [line5] };
6271
6349
  }
6272
6350
  function projectActivePlaceholderEntry(entry) {
6273
6351
  const text = entry.meta?.activePlaceholder ?? "\u25CF \u6B63\u5728\u601D\u8003\u2026";
@@ -6279,8 +6357,8 @@ function projectActivePlaceholderEntry(entry) {
6279
6357
  ] : [
6280
6358
  { text, token: "fg", bold: false }
6281
6359
  ];
6282
- const line8 = mixedLine(segments, 0);
6283
- return { revision: 0, sourceLength: entry.source.length, lines: [line8] };
6360
+ const line5 = mixedLine(segments, 0);
6361
+ return { revision: 0, sourceLength: entry.source.length, lines: [line5] };
6284
6362
  }
6285
6363
  function lineForText(text, token, bold, blockRow, background, backgroundColumns) {
6286
6364
  const width = displayWidth(text);
@@ -6412,7 +6490,7 @@ function createPhysicalLine(input) {
6412
6490
  ...span.href === void 0 ? {} : { href: span.href }
6413
6491
  }))
6414
6492
  );
6415
- const line8 = {
6493
+ const line5 = {
6416
6494
  blockId: input.blockId,
6417
6495
  text,
6418
6496
  displayWidth: displayWidth(text),
@@ -6425,15 +6503,15 @@ function createPhysicalLine(input) {
6425
6503
  ...input.osc8 === void 0 ? {} : { osc8: Object.freeze({ href: input.osc8.href, id: input.osc8.id }) },
6426
6504
  ...input.graphemeSources === void 0 ? {} : { graphemeSources: Object.freeze([...input.graphemeSources]) }
6427
6505
  };
6428
- return Object.freeze(line8);
6506
+ return Object.freeze(line5);
6429
6507
  }
6430
- function physicalLineByteSize(line8) {
6508
+ function physicalLineByteSize(line5) {
6431
6509
  let bytes = 0;
6432
- bytes += line8.text.length;
6433
- for (const span of line8.spans) bytes += span.text.length + (span.href?.length ?? 0);
6434
- bytes += line8.sourceEnd - line8.sourceStart;
6435
- if (line8.osc8 !== void 0) bytes += line8.osc8.href.length + line8.osc8.id.length;
6436
- if (line8.graphemeSources !== void 0) bytes += line8.graphemeSources.length * 4;
6510
+ bytes += line5.text.length;
6511
+ for (const span of line5.spans) bytes += span.text.length + (span.href?.length ?? 0);
6512
+ bytes += line5.sourceEnd - line5.sourceStart;
6513
+ if (line5.osc8 !== void 0) bytes += line5.osc8.href.length + line5.osc8.id.length;
6514
+ if (line5.graphemeSources !== void 0) bytes += line5.graphemeSources.length * 4;
6437
6515
  return bytes;
6438
6516
  }
6439
6517
 
@@ -6669,7 +6747,7 @@ var TranscriptRenderStoreImpl = class {
6669
6747
  }
6670
6748
  cachedBlocks += 1;
6671
6749
  cachedRows += lines.length;
6672
- for (const line8 of lines) cachedBytes += physicalLineByteSize(line8);
6750
+ for (const line5 of lines) cachedBytes += physicalLineByteSize(line5);
6673
6751
  }
6674
6752
  return {
6675
6753
  hits: this.counters.hits,
@@ -6767,7 +6845,7 @@ var TranscriptRenderStoreImpl = class {
6767
6845
  const settled = entry.settledLines;
6768
6846
  const rowCount = settled.length;
6769
6847
  let byteCount = 0;
6770
- for (const line8 of settled) byteCount += physicalLineByteSize(line8);
6848
+ for (const line5 of settled) byteCount += physicalLineByteSize(line5);
6771
6849
  entry.settledLines = null;
6772
6850
  entry.lastAccess = 0;
6773
6851
  this.counters.evictions += 1;
@@ -6780,9 +6858,9 @@ var TranscriptRenderStoreImpl = class {
6780
6858
  let bytes = 0;
6781
6859
  for (const entry of this.entries.values()) {
6782
6860
  const lines = entry.activeRevision === null ? entry.settledLines ?? EMPTY_LINES : entry.activeRevision.lines;
6783
- for (const line8 of lines) {
6861
+ for (const line5 of lines) {
6784
6862
  rows += 1;
6785
- bytes += physicalLineByteSize(line8);
6863
+ bytes += physicalLineByteSize(line5);
6786
6864
  }
6787
6865
  }
6788
6866
  return { rows, bytes };
@@ -7333,7 +7411,7 @@ function liveDurationTarget(turn, status) {
7333
7411
  if (part?.kind === "card" && part.card.status !== "running" || part?.kind === "tool-summary" && part.summary.runningCount === 0) {
7334
7412
  return {
7335
7413
  identity: `turn-${String(turn.turn)}-pending-after-tool-${String(index)}`,
7336
- durationMs: turn.reasoningDurationMs ?? 0
7414
+ durationMs: turn.reasoningDurationMs
7337
7415
  };
7338
7416
  }
7339
7417
  return void 0;
@@ -7410,17 +7488,17 @@ function latestAssistantId(history, activeTurn) {
7410
7488
  return void 0;
7411
7489
  }
7412
7490
  var baseMarkdownLineCache = /* @__PURE__ */ new WeakMap();
7413
- function markdownLineToPhysicalLine(blockId, line8) {
7414
- let byBlock = baseMarkdownLineCache.get(line8);
7491
+ function markdownLineToPhysicalLine(blockId, line5) {
7492
+ let byBlock = baseMarkdownLineCache.get(line5);
7415
7493
  if (byBlock === void 0) {
7416
7494
  byBlock = /* @__PURE__ */ new Map();
7417
- baseMarkdownLineCache.set(line8, byBlock);
7495
+ baseMarkdownLineCache.set(line5, byBlock);
7418
7496
  }
7419
7497
  const cached = byBlock.get(blockId);
7420
7498
  if (cached !== void 0) return cached;
7421
7499
  const segments = [];
7422
- for (const span of line8.spans) {
7423
- const text = displayColumnSlice(line8.text, span.start, span.end);
7500
+ for (const span of line5.spans) {
7501
+ const text = displayColumnSlice(line5.text, span.start, span.end);
7424
7502
  if (text === "") continue;
7425
7503
  segments.push({
7426
7504
  text,
@@ -7429,16 +7507,16 @@ function markdownLineToPhysicalLine(blockId, line8) {
7429
7507
  ...span.href === void 0 ? {} : { href: span.href }
7430
7508
  });
7431
7509
  }
7432
- const sourceStart = Math.max(0, line8.sourceStart);
7433
- const sourceEnd = Math.max(sourceStart, line8.sourceEnd < 0 ? sourceStart : line8.sourceEnd);
7510
+ const sourceStart = Math.max(0, line5.sourceStart);
7511
+ const sourceEnd = Math.max(sourceStart, line5.sourceEnd < 0 ? sourceStart : line5.sourceEnd);
7434
7512
  const created = createPhysicalLine({
7435
7513
  blockId,
7436
7514
  spans: segments.length === 0 ? [{ text: "", token: "fg", bold: false }] : segments,
7437
7515
  sourceStart,
7438
7516
  sourceEnd,
7439
- blockRow: Math.max(0, line8.rowInBlock),
7440
- ...line8.background === void 0 ? {} : { background: line8.background },
7441
- ...line8.backgroundColumns === void 0 ? {} : { backgroundColumns: line8.backgroundColumns }
7517
+ blockRow: Math.max(0, line5.rowInBlock),
7518
+ ...line5.background === void 0 ? {} : { background: line5.background },
7519
+ ...line5.backgroundColumns === void 0 ? {} : { backgroundColumns: line5.backgroundColumns }
7442
7520
  });
7443
7521
  byBlock.set(blockId, created);
7444
7522
  return created;
@@ -7478,17 +7556,28 @@ function overlayPromptOnSpans(spans, prompt) {
7478
7556
  return result;
7479
7557
  }
7480
7558
  var frameLineCache = /* @__PURE__ */ new WeakMap();
7481
- function framePhysicalLine(blockId, line8, lead, active, prompt) {
7559
+ function clonePhysicalLineWithSpans(base, blockId, spans) {
7560
+ return createPhysicalLine({
7561
+ blockId,
7562
+ spans,
7563
+ sourceStart: base.sourceStart,
7564
+ sourceEnd: base.sourceEnd,
7565
+ blockRow: base.blockRow,
7566
+ ...base.background === void 0 ? {} : { background: base.background },
7567
+ ...base.backgroundColumns === void 0 ? {} : { backgroundColumns: base.backgroundColumns }
7568
+ });
7569
+ }
7570
+ function framePhysicalLine(blockId, line5, lead, active, prompt) {
7482
7571
  if (prompt === void 0) {
7483
- let byLine = frameLineCache.get(line8);
7572
+ let byLine = frameLineCache.get(line5);
7484
7573
  if (byLine === void 0) {
7485
7574
  byLine = /* @__PURE__ */ new Map();
7486
- frameLineCache.set(line8, byLine);
7575
+ frameLineCache.set(line5, byLine);
7487
7576
  }
7488
7577
  const key = `${blockId}:${lead}:${active ? "1" : "0"}`;
7489
7578
  const cached = byLine.get(key);
7490
7579
  if (cached !== void 0) return cached;
7491
- const base2 = markdownLineToPhysicalLine(blockId, line8);
7580
+ const base2 = markdownLineToPhysicalLine(blockId, line5);
7492
7581
  const spans2 = lead === "" ? base2.spans : [
7493
7582
  {
7494
7583
  text: lead,
@@ -7497,19 +7586,11 @@ function framePhysicalLine(blockId, line8, lead, active, prompt) {
7497
7586
  },
7498
7587
  ...base2.spans
7499
7588
  ];
7500
- const created = lead === "" ? base2 : createPhysicalLine({
7501
- blockId,
7502
- spans: spans2,
7503
- sourceStart: base2.sourceStart,
7504
- sourceEnd: base2.sourceEnd,
7505
- blockRow: base2.blockRow,
7506
- ...base2.background === void 0 ? {} : { background: base2.background },
7507
- ...base2.backgroundColumns === void 0 ? {} : { backgroundColumns: base2.backgroundColumns }
7508
- });
7589
+ const created = lead === "" ? base2 : clonePhysicalLineWithSpans(base2, blockId, spans2);
7509
7590
  byLine.set(key, created);
7510
7591
  return created;
7511
7592
  }
7512
- const base = markdownLineToPhysicalLine(blockId, line8);
7593
+ const base = markdownLineToPhysicalLine(blockId, line5);
7513
7594
  const initialSpans = [
7514
7595
  ...lead === "" ? [] : [{
7515
7596
  text: lead,
@@ -7519,15 +7600,7 @@ function framePhysicalLine(blockId, line8, lead, active, prompt) {
7519
7600
  ...base.spans
7520
7601
  ];
7521
7602
  const spans = overlayPromptOnSpans(initialSpans, prompt);
7522
- return createPhysicalLine({
7523
- blockId,
7524
- spans,
7525
- sourceStart: base.sourceStart,
7526
- sourceEnd: base.sourceEnd,
7527
- blockRow: base.blockRow,
7528
- ...base.background === void 0 ? {} : { background: base.background },
7529
- ...base.backgroundColumns === void 0 ? {} : { backgroundColumns: base.backgroundColumns }
7530
- });
7603
+ return clonePhysicalLineWithSpans(base, blockId, spans);
7531
7604
  }
7532
7605
  function projectorStateFor(cache2, blockId, scope, aliases = [], source) {
7533
7606
  const projectorScope = scope.scopeKey.replace(/\|(streaming|settled)$/u, "");
@@ -7607,15 +7680,15 @@ function intersectingLayoutIndexes(layouts, start, end) {
7607
7680
  return indexes;
7608
7681
  }
7609
7682
  var paintedRenderLineCache = /* @__PURE__ */ new WeakMap();
7610
- function cachedPaintedRenderLine(line8, cacheKey, hyperlinks2) {
7611
- let variants = paintedRenderLineCache.get(line8);
7683
+ function cachedPaintedRenderLine(line5, cacheKey, hyperlinks2) {
7684
+ let variants = paintedRenderLineCache.get(line5);
7612
7685
  if (variants === void 0) {
7613
7686
  variants = /* @__PURE__ */ new Map();
7614
- paintedRenderLineCache.set(line8, variants);
7687
+ paintedRenderLineCache.set(line5, variants);
7615
7688
  }
7616
7689
  const cached = variants.get(cacheKey);
7617
7690
  if (cached !== void 0) return cached;
7618
- const painted = paintLineFromRenderLine(line8, hyperlinks2);
7691
+ const painted = paintLineFromRenderLine(line5, hyperlinks2);
7619
7692
  variants.set(cacheKey, painted);
7620
7693
  return painted;
7621
7694
  }
@@ -7631,11 +7704,11 @@ var SlicedLinesBlock = memo(function SlicedLinesBlock2(props) {
7631
7704
  const hyperlinks2 = hyperlinksEnabled();
7632
7705
  const paintCacheKey = `${currentTier()}:${hyperlinks2 ? "links" : "plain"}`;
7633
7706
  for (let index = start; index < end; index += 1) {
7634
- const line8 = lines.at(index);
7635
- if (line8 === void 0) {
7707
+ const line5 = lines.at(index);
7708
+ if (line5 === void 0) {
7636
7709
  continue;
7637
7710
  }
7638
- const painted = cachedPaintedRenderLine(line8, paintCacheKey, hyperlinks2);
7711
+ const painted = cachedPaintedRenderLine(line5, paintCacheKey, hyperlinks2);
7639
7712
  const lead = slicedLead(prefix, textRanges, index);
7640
7713
  const trailing = index === effectiveTailRow ? tail : void 0;
7641
7714
  out.push(
@@ -7657,9 +7730,27 @@ function projectBlockEntry(deps, ownerId, entry, scope, state, active) {
7657
7730
  }
7658
7731
  if (entry.kind === "reasoning" && entry.meta?.reasoningExpanded === true && entry.source !== "") {
7659
7732
  const rows = new RowSequence();
7660
- const header = `${entry.meta.reasoningLive === true ? "" : "\u25BE "}\u273B ${tuiCopy("reasoning", deps.locale)} (${((entry.meta.reasoningDurationMs ?? 0) / 1e3).toFixed(1)}s)`;
7661
- rows.push({ ...GAP_LINE, text: header, displayWidth: displayWidth(header), spans: [{ start: 0, end: displayWidth(header), token: "fgDim", bold: false }] });
7662
- rows.append(deps.plainRows.rows(entry.id, entry.source, Math.max(1, scope.width - 4)));
7733
+ const prefix = entry.meta.reasoningLive === true ? "" : "\u25BE ";
7734
+ const title = `\u273B ${tuiCopy("reasoning", deps.locale)}`;
7735
+ const duration = ` (${((entry.meta.reasoningDurationMs ?? 0) / 1e3).toFixed(1)}s)`;
7736
+ const header = `${prefix}${title}${duration}`;
7737
+ const prefixWidth = displayWidth(prefix);
7738
+ const titleWidth = displayWidth(title);
7739
+ const totalWidth = displayWidth(header);
7740
+ const spans = [
7741
+ ...prefixWidth > 0 ? [{ start: 0, end: prefixWidth, token: "accentText", bold: false }] : [],
7742
+ { start: prefixWidth, end: prefixWidth + titleWidth, token: "accentText", bold: false },
7743
+ { start: prefixWidth + titleWidth, end: totalWidth, token: "fgDim", bold: false }
7744
+ ];
7745
+ rows.push({
7746
+ ...GAP_LINE,
7747
+ text: header,
7748
+ displayWidth: totalWidth,
7749
+ spans,
7750
+ background: "toolBg",
7751
+ backgroundColumns: scope.width
7752
+ });
7753
+ rows.append(deps.plainRows.rows(entry.id, entry.source, Math.max(1, scope.width - 4), scope.width, "toolBg"));
7663
7754
  return { lines: rows.build() };
7664
7755
  }
7665
7756
  const projection = projectBlockRows(entry, scope, state);
@@ -7672,6 +7763,36 @@ function projectBlockEntry(deps, ownerId, entry, scope, state, active) {
7672
7763
  });
7673
7764
  return projection;
7674
7765
  }
7766
+ function makeBlockProjector(deps, storeBlocks) {
7767
+ return (ownerId, entry, scope, state, active) => projectBlockEntry({ ...deps, storeBlocks }, ownerId, entry, scope, state, active);
7768
+ }
7769
+ function makeToolSummaryBlockEntry(id, summary, contentWidth) {
7770
+ return {
7771
+ id: `${id}-tool-summary`,
7772
+ kind: "tool-summary",
7773
+ source: toolSummaryText(summary, contentWidth),
7774
+ meta: { toolSummaryStatus: toolSummaryStatus(summary) }
7775
+ };
7776
+ }
7777
+ function makeToolCardBlockEntry(id, card) {
7778
+ return {
7779
+ id: `${id}-c-${card.callId}`,
7780
+ kind: "tool-card",
7781
+ source: "",
7782
+ meta: {
7783
+ toolCard: {
7784
+ name: card.name,
7785
+ arguments: card.arguments,
7786
+ status: card.status,
7787
+ ...card.resultText === void 0 ? {} : { resultText: card.resultText },
7788
+ ...card.meta === void 0 ? {} : { meta: card.meta },
7789
+ ...card.error === void 0 ? {} : { error: card.error },
7790
+ ...card.callView === void 0 ? {} : { callView: card.callView },
7791
+ ...card.resultView === void 0 ? {} : { resultView: card.resultView }
7792
+ }
7793
+ }
7794
+ };
7795
+ }
7675
7796
  function StreamView({
7676
7797
  model,
7677
7798
  presenters,
@@ -7727,7 +7848,7 @@ function StreamView({
7727
7848
  throw new Error(`TranscriptRenderStore: missing source descriptor for ${blockId}`);
7728
7849
  }
7729
7850
  const state = descriptor.entry.kind === "markdown" || descriptor.entry.kind === "assistant-prose" ? createMarkdownProjectorState(blockId, descriptor.scope) : void 0;
7730
- return projectBlockRows(descriptor.entry, descriptor.scope, state).lines.map((line8) => markdownLineToPhysicalLine(blockId, line8));
7851
+ return projectBlockRows(descriptor.entry, descriptor.scope, state).lines.map((line5) => markdownLineToPhysicalLine(blockId, line5));
7731
7852
  }
7732
7853
  });
7733
7854
  }
@@ -7907,7 +8028,7 @@ function StreamView({
7907
8028
  const textRanges = /* @__PURE__ */ new Map();
7908
8029
  const storeBlocks = /* @__PURE__ */ new Map();
7909
8030
  const projectorCache = projectorStates.current;
7910
- const project = (ownerId, entry, scope, state, active) => projectBlockEntry({ toolRows, plainRows, locale, storeBlocks }, ownerId, entry, scope, state, active);
8031
+ const project = makeBlockProjector({ toolRows, plainRows, locale }, storeBlocks);
7911
8032
  const latestAssistant = hasActiveTurn ? void 0 : latestAssistantId(history, void 0);
7912
8033
  for (const [index, row] of transcript.entries()) {
7913
8034
  const id = transcriptBlockId(row);
@@ -7960,33 +8081,23 @@ function StreamView({
7960
8081
  continue;
7961
8082
  }
7962
8083
  if (part.kind === "tool-summary") {
7963
- rows2.append(project(id, {
7964
- id: `${id}-tool-summary`,
7965
- kind: "tool-summary",
7966
- source: toolSummaryText(part.summary, contentWidth),
7967
- meta: { toolSummaryStatus: toolSummaryStatus(part.summary) }
7968
- }, settledBlockRowsScope, void 0, false).lines);
8084
+ rows2.append(project(
8085
+ id,
8086
+ makeToolSummaryBlockEntry(id, part.summary, contentWidth),
8087
+ settledBlockRowsScope,
8088
+ void 0,
8089
+ false
8090
+ ).lines);
7969
8091
  continue;
7970
8092
  }
7971
8093
  if (part.kind === "card") {
7972
- const card = part.card;
7973
- rows2.append(project(id, {
7974
- id: `${id}-c-${card.callId}`,
7975
- kind: "tool-card",
7976
- source: "",
7977
- meta: {
7978
- toolCard: {
7979
- name: card.name,
7980
- arguments: card.arguments,
7981
- status: card.status,
7982
- ...card.resultText === void 0 ? {} : { resultText: card.resultText },
7983
- ...card.meta === void 0 ? {} : { meta: card.meta },
7984
- ...card.error === void 0 ? {} : { error: card.error },
7985
- ...card.callView === void 0 ? {} : { callView: card.callView },
7986
- ...card.resultView === void 0 ? {} : { resultView: card.resultView }
7987
- }
7988
- }
7989
- }, settledBlockRowsScope, void 0, false).lines);
8094
+ rows2.append(project(
8095
+ id,
8096
+ makeToolCardBlockEntry(id, part.card),
8097
+ settledBlockRowsScope,
8098
+ void 0,
8099
+ false
8100
+ ).lines);
7990
8101
  continue;
7991
8102
  }
7992
8103
  const start = rows2.length;
@@ -8062,7 +8173,7 @@ function StreamView({
8062
8173
  } };
8063
8174
  const storeBlocks = /* @__PURE__ */ new Map();
8064
8175
  const projectorCache = projectorStates.current;
8065
- const project = (ownerId, entry, scope, state, active) => projectBlockEntry({ toolRows, plainRows, locale, storeBlocks }, ownerId, entry, scope, state, active);
8176
+ const project = makeBlockProjector({ toolRows, plainRows, locale }, storeBlocks);
8066
8177
  const id = `assistant-turn-${String(activeTurn.turn)}`;
8067
8178
  const rawParts = partsFromTurn(activeTurn);
8068
8179
  const visibleParts = displayedParts(rawParts, reasoningExpanded);
@@ -8110,33 +8221,23 @@ function StreamView({
8110
8221
  continue;
8111
8222
  }
8112
8223
  if (part.kind === "tool-summary") {
8113
- rows2.append(project(id, {
8114
- id: `${id}-tool-summary`,
8115
- kind: "tool-summary",
8116
- source: toolSummaryText(part.summary, contentWidth),
8117
- meta: { toolSummaryStatus: toolSummaryStatus(part.summary) }
8118
- }, blockRowsScope, void 0, status === "generating").lines);
8224
+ rows2.append(project(
8225
+ id,
8226
+ makeToolSummaryBlockEntry(id, part.summary, contentWidth),
8227
+ blockRowsScope,
8228
+ void 0,
8229
+ status === "generating"
8230
+ ).lines);
8119
8231
  continue;
8120
8232
  }
8121
8233
  if (part.kind === "card") {
8122
- const card = part.card;
8123
- rows2.append(project(id, {
8124
- id: `${id}-c-${card.callId}`,
8125
- kind: "tool-card",
8126
- source: "",
8127
- meta: {
8128
- toolCard: {
8129
- name: card.name,
8130
- arguments: card.arguments,
8131
- status: card.status,
8132
- ...card.resultText === void 0 ? {} : { resultText: card.resultText },
8133
- ...card.meta === void 0 ? {} : { meta: card.meta },
8134
- ...card.error === void 0 ? {} : { error: card.error },
8135
- ...card.callView === void 0 ? {} : { callView: card.callView },
8136
- ...card.resultView === void 0 ? {} : { resultView: card.resultView }
8137
- }
8138
- }
8139
- }, blockRowsScope, void 0, status === "generating").lines);
8234
+ rows2.append(project(
8235
+ id,
8236
+ makeToolCardBlockEntry(id, part.card),
8237
+ blockRowsScope,
8238
+ void 0,
8239
+ status === "generating"
8240
+ ).lines);
8140
8241
  continue;
8141
8242
  }
8142
8243
  const start = rows2.length;
@@ -8259,15 +8360,15 @@ function StreamView({
8259
8360
  String(descriptor.lines.length)
8260
8361
  ]);
8261
8362
  if (!descriptor.active && !activeLineRevisions.current.has(descriptor.entry.id) && storedLineSignatures.current.get(descriptor.entry.id) === signature) continue;
8262
- const physical = descriptor.lines.map((line8) => {
8263
- let byBlock = physicalLineCache.current.get(line8);
8363
+ const physical = descriptor.lines.map((line5) => {
8364
+ let byBlock = physicalLineCache.current.get(line5);
8264
8365
  if (byBlock === void 0) {
8265
8366
  byBlock = /* @__PURE__ */ new Map();
8266
- physicalLineCache.current.set(line8, byBlock);
8367
+ physicalLineCache.current.set(line5, byBlock);
8267
8368
  }
8268
8369
  let cached = byBlock.get(descriptor.entry.id);
8269
8370
  if (cached === void 0) {
8270
- cached = markdownLineToPhysicalLine(descriptor.entry.id, line8);
8371
+ cached = markdownLineToPhysicalLine(descriptor.entry.id, line5);
8271
8372
  byBlock.set(descriptor.entry.id, cached);
8272
8373
  }
8273
8374
  return cached;
@@ -8682,8 +8783,8 @@ function StreamView({
8682
8783
  const assistant = entry.kind === "active" || entry.row.kind === "message" && entry.row.message.kind === "assistant";
8683
8784
  const ranges = assistant ? activeEntryRows.textRanges.get(entry.id) ?? EMPTY_TEXT_RANGES : EMPTY_TEXT_RANGES;
8684
8785
  for (let index = start; index < end; index += 1) {
8685
- const line8 = entry.lines.at(index);
8686
- if (line8 === void 0) continue;
8786
+ const line5 = entry.lines.at(index);
8787
+ if (line5 === void 0) continue;
8687
8788
  const absoluteRow = 3 + verticalBase + layout.top + index - visibleTop;
8688
8789
  if (absoluteRow < 3 || absoluteRow >= 3 + effectiveViewportRows) continue;
8689
8790
  const isBottomRow = absoluteRow === 3 + effectiveViewportRows - 1;
@@ -8698,7 +8799,7 @@ function StreamView({
8698
8799
  id: `${entry.id}:${String(index)}`,
8699
8800
  row: absoluteRow,
8700
8801
  col: contentLeft + 1,
8701
- line: framePhysicalLine(entry.id, line8, lead, entry.kind === "active", promptOverlay)
8802
+ line: framePhysicalLine(entry.id, line5, lead, entry.kind === "active", promptOverlay)
8702
8803
  }));
8703
8804
  }
8704
8805
  }
@@ -9346,7 +9447,7 @@ function HelpPane({ lines, offset }) {
9346
9447
  safeOffset,
9347
9448
  " \u884C"
9348
9449
  ] }) : null,
9349
- visible.map((line8, index) => /* @__PURE__ */ jsx10(Text10, { children: escapeContent(line8) }, safeOffset + index)),
9450
+ visible.map((line5, index) => /* @__PURE__ */ jsx10(Text10, { children: escapeContent(line5) }, safeOffset + index)),
9350
9451
  /* @__PURE__ */ jsx10(Text10, { children: styled(escapeContent("\u2191\u2193/jk \u6EDA\u52A8 \xB7 Esc/Enter \u5173\u95ED"), "fgDim") })
9351
9452
  ] });
9352
9453
  }
@@ -9424,8 +9525,36 @@ function ApprovalPane({
9424
9525
  }
9425
9526
 
9426
9527
  // tui-render/src/permission-pane.tsx
9528
+ import { Box as Box13, Text as Text13 } from "ink";
9529
+
9530
+ // tui-render/src/overlay-shell.tsx
9427
9531
  import { Box as Box12, Text as Text12 } from "ink";
9428
9532
  import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
9533
+ var EMPTY_OVERLAY_PANE = { open: false };
9534
+ function renderPaneLine(text, token, bold = false) {
9535
+ return /* @__PURE__ */ jsx12(Text12, { children: paintRow([styled(escapeContent(text), token, void 0, bold)]) });
9536
+ }
9537
+ var line2 = renderPaneLine;
9538
+ function OverlayShell({
9539
+ title,
9540
+ body,
9541
+ footnote,
9542
+ error,
9543
+ errorNext,
9544
+ children
9545
+ }) {
9546
+ return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", width: "100%", children: [
9547
+ line2(title, "fg", true),
9548
+ body !== void 0 && body !== "" ? line2(body, "fg") : null,
9549
+ children,
9550
+ error !== void 0 && error !== "" ? line2(`\u2717 ${error}`, "error") : null,
9551
+ error !== void 0 && error !== "" && errorNext !== void 0 && errorNext !== "" ? line2(errorNext, "fgDim") : null,
9552
+ line2(footnote, "fgDim")
9553
+ ] });
9554
+ }
9555
+
9556
+ // tui-render/src/permission-pane.tsx
9557
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
9429
9558
  var TITLE = "\u6743\u9650\u9884\u8BBE";
9430
9559
  var FOOTNOTE = "\u2191\u2193/jk \u9009\u62E9 \xB7 1-3 \u76F4\u8FBE \xB7 Enter \u5E94\u7528 \xB7 Esc \u5173\u95ED";
9431
9560
  var CONFIRM = "\u786E\u8BA4\u5207\u6362\u5230 danger-full-access\uFF1F";
@@ -9439,9 +9568,6 @@ var EMPTY_PERMISSION_PANE = {
9439
9568
  currentName: "",
9440
9569
  confirmDanger: false
9441
9570
  };
9442
- function line2(text, token, bold = false) {
9443
- return /* @__PURE__ */ jsx12(Text12, { children: paintRow([styled(escapeContent(text), token, void 0, bold)]) });
9444
- }
9445
9571
  function PermissionPane({
9446
9572
  names,
9447
9573
  selectedIndex,
@@ -9451,38 +9577,38 @@ function PermissionPane({
9451
9577
  switchError
9452
9578
  }) {
9453
9579
  if (confirmDanger) {
9454
- return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", width: "100%", children: [
9455
- line2(CONFIRM, "fg", true),
9456
- line2(CONFIRM_FOOTNOTE, "fgDim")
9580
+ return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", width: "100%", children: [
9581
+ renderPaneLine(CONFIRM, "fg", true),
9582
+ renderPaneLine(CONFIRM_FOOTNOTE, "fgDim")
9457
9583
  ] });
9458
9584
  }
9459
9585
  const errorReason = switchError ?? (names.length === 0 ? EMPTY_TABLE_REASON : void 0);
9460
- return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", width: "100%", children: [
9461
- line2(TITLE, "fg", true),
9586
+ return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", width: "100%", children: [
9587
+ renderPaneLine(TITLE, "fg", true),
9462
9588
  names.map((name, index) => {
9463
9589
  const selected = index === selectedIndex;
9464
9590
  const current = name === currentName;
9465
9591
  const description = descriptions?.[index];
9466
9592
  const label = current ? `${name} \xB7 \u5F53\u524D` : name;
9467
- return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", width: "100%", children: [
9468
- /* @__PURE__ */ jsxs11(Box12, { width: "100%", children: [
9469
- /* @__PURE__ */ jsx12(Text12, { children: selected ? styled(escapeContent("\u203A "), "accent", void 0, true) : " " }),
9470
- /* @__PURE__ */ jsx12(Text12, { children: paintRow([styled(escapeContent(label), selected ? "fg" : "fgDim")]) })
9593
+ return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", width: "100%", children: [
9594
+ /* @__PURE__ */ jsxs12(Box13, { width: "100%", children: [
9595
+ /* @__PURE__ */ jsx13(Text13, { children: selected ? styled(escapeContent("\u203A "), "accent", void 0, true) : " " }),
9596
+ /* @__PURE__ */ jsx13(Text13, { children: paintRow([styled(escapeContent(label), selected ? "fg" : "fgDim")]) })
9471
9597
  ] }),
9472
- description !== void 0 && description !== "" ? line2(description, "fgDim") : null
9598
+ description !== void 0 && description !== "" ? renderPaneLine(description, "fgDim") : null
9473
9599
  ] }, name);
9474
9600
  }),
9475
- errorReason !== void 0 ? /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", width: "100%", children: [
9476
- line2(`\u2717 \u5207\u6362\u6743\u9650\u5931\u8D25\uFF1A${errorReason}`, "error"),
9477
- line2(FAIL_NEXT, "fgDim")
9601
+ errorReason !== void 0 ? /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", width: "100%", children: [
9602
+ renderPaneLine(`\u2717 \u5207\u6362\u6743\u9650\u5931\u8D25\uFF1A${errorReason}`, "error"),
9603
+ renderPaneLine(FAIL_NEXT, "fgDim")
9478
9604
  ] }) : null,
9479
- line2(FOOTNOTE, "fgDim")
9605
+ renderPaneLine(FOOTNOTE, "fgDim")
9480
9606
  ] });
9481
9607
  }
9482
9608
 
9483
9609
  // tui-render/src/settings-pane.tsx
9484
- import { Box as Box13, Text as Text13, useWindowSize as useWindowSize5 } from "ink";
9485
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
9610
+ import { Box as Box14, Text as Text14, useWindowSize as useWindowSize5 } from "ink";
9611
+ import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
9486
9612
  var TITLE2 = "\u8BBE\u7F6E";
9487
9613
  var ONBOARDING_TITLE = "\u9996\u6B21\u8BBE\u7F6E";
9488
9614
  var FOOTNOTE2 = "\u2191\u2193/jk \u9009\u62E9 \xB7 Enter \u7F16\u8F91 \xB7 e \u5BFC\u51FA \xB7 r \u91CD\u8F7D \xB7 Esc \u5173\u95ED";
@@ -9500,9 +9626,6 @@ var EMPTY_SETTINGS_PANE = {
9500
9626
  selectedIndex: 0,
9501
9627
  editing: false
9502
9628
  };
9503
- function line3(text, token, bold = false) {
9504
- return /* @__PURE__ */ jsx13(Text13, { children: paintRow([styled(escapeContent(text), token, void 0, bold)]) });
9505
- }
9506
9629
  function fitValue(value, maxCols) {
9507
9630
  if (maxCols <= 0) return "";
9508
9631
  if (displayWidth(value) <= maxCols) return value;
@@ -9560,57 +9683,30 @@ function SettingsPane({
9560
9683
  rows.length - size
9561
9684
  );
9562
9685
  const visible = rows.slice(start, start + size);
9563
- return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", width: "100%", children: [
9564
- line3(onboarding === true ? ONBOARDING_TITLE : TITLE2, "fg", true),
9565
- start > 0 ? line3(`\u2026 \u8FD8\u6709 ${String(start)} \u9879`, "fgDim") : null,
9686
+ return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", width: "100%", children: [
9687
+ renderPaneLine(onboarding === true ? ONBOARDING_TITLE : TITLE2, "fg", true),
9688
+ start > 0 ? renderPaneLine(`\u2026 \u8FD8\u6709 ${String(start)} \u9879`, "fgDim") : null,
9566
9689
  visible.map((row, index) => {
9567
9690
  const absolute = start + index;
9568
9691
  const selected = absolute === selectedIndex;
9569
9692
  const localized = row.namespace === "tui" && (row.field === "reasoning" || row.field === "scrollbar" || row.field === "statusDetails" || row.field === "locale") ? `${row.field} \xB7 ${tuiCopy(row.field, locale)}` : row.field === "apiKeyEnv" ? `${row.field} \xB7 \u73AF\u5883\u53D8\u91CF\u540D` : row.field;
9570
9693
  const label = `${row.namespace} \xB7 ${localized}`;
9571
- return /* @__PURE__ */ jsx13(Box13, { width: "100%", children: /* @__PURE__ */ jsx13(Text13, { children: paintRow(fieldRow(label, row.value, selected, width)) }) }, `${row.namespace}:${row.field}`);
9694
+ return /* @__PURE__ */ jsx14(Box14, { width: "100%", children: /* @__PURE__ */ jsx14(Text14, { children: paintRow(fieldRow(label, row.value, selected, width)) }) }, `${row.namespace}:${row.field}`);
9572
9695
  }),
9573
- rows.length > start + size ? line3(`\u2026 \u8FD8\u6709 ${String(rows.length - start - size)} \u9879`, "fgDim") : null,
9574
- errorReason !== void 0 ? /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", width: "100%", children: [
9575
- line3(
9696
+ rows.length > start + size ? renderPaneLine(`\u2026 \u8FD8\u6709 ${String(rows.length - start - size)} \u9879`, "fgDim") : null,
9697
+ errorReason !== void 0 ? /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", width: "100%", children: [
9698
+ renderPaneLine(
9576
9699
  errorReason === EMPTY_TABLE_REASON2 ? EMPTY_TABLE_REASON2 : `\u2717 \u66F4\u65B0\u5931\u8D25\uFF1A${errorReason}`,
9577
9700
  "error"
9578
9701
  ),
9579
- errorReason === EMPTY_TABLE_REASON2 ? null : line3(FAIL_NEXT2, "fgDim")
9702
+ errorReason === EMPTY_TABLE_REASON2 ? null : renderPaneLine(FAIL_NEXT2, "fgDim")
9580
9703
  ] }) : null,
9581
- line3(footnote, "fgDim")
9704
+ renderPaneLine(footnote, "fgDim")
9582
9705
  ] });
9583
9706
  }
9584
9707
 
9585
9708
  // tui-render/src/agent-hub-pane.tsx
9586
9709
  import { Box as Box15, Text as Text15 } from "ink";
9587
-
9588
- // tui-render/src/overlay-shell.tsx
9589
- import { Box as Box14, Text as Text14 } from "ink";
9590
- import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
9591
- var EMPTY_OVERLAY_PANE = { open: false };
9592
- function line4(text, token, bold = false) {
9593
- return /* @__PURE__ */ jsx14(Text14, { children: paintRow([styled(escapeContent(text), token, void 0, bold)]) });
9594
- }
9595
- function OverlayShell({
9596
- title,
9597
- body,
9598
- footnote,
9599
- error,
9600
- errorNext,
9601
- children
9602
- }) {
9603
- return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", width: "100%", children: [
9604
- line4(title, "fg", true),
9605
- body !== void 0 && body !== "" ? line4(body, "fg") : null,
9606
- children,
9607
- error !== void 0 && error !== "" ? line4(`\u2717 ${error}`, "error") : null,
9608
- error !== void 0 && error !== "" && errorNext !== void 0 && errorNext !== "" ? line4(errorNext, "fgDim") : null,
9609
- line4(footnote, "fgDim")
9610
- ] });
9611
- }
9612
-
9613
- // tui-render/src/agent-hub-pane.tsx
9614
9710
  import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
9615
9711
  function formatTokens(value) {
9616
9712
  const scaled = (next) => next >= 100 ? String(Math.round(next)) : String(Math.round(next * 10) / 10);
@@ -9685,8 +9781,8 @@ function AgentHubPane({
9685
9781
  }
9686
9782
  );
9687
9783
  }
9688
- const lines = (transcript ?? "").split("\n").filter((line8) => line8 !== "");
9689
- return /* @__PURE__ */ jsx15(OverlayShell, { title: "\u5B50\u4EE3\u7406", footnote: "Esc \u8FD4\u56DE", children: lines.map((line8, index) => /* @__PURE__ */ jsx15(Text15, { children: paintRow([styled(escapeContent(line8), "fg")]) }, index)) });
9784
+ const lines = (transcript ?? "").split("\n").filter((line5) => line5 !== "");
9785
+ return /* @__PURE__ */ jsx15(OverlayShell, { title: "\u5B50\u4EE3\u7406", footnote: "Esc \u8FD4\u56DE", children: lines.map((line5, index) => /* @__PURE__ */ jsx15(Text15, { children: paintRow([styled(escapeContent(line5), "fg")]) }, index)) });
9690
9786
  }
9691
9787
  if (error !== void 0 && error !== "") {
9692
9788
  return /* @__PURE__ */ jsx15(
@@ -9742,7 +9838,7 @@ function directoryRow(label, selected, current) {
9742
9838
  /* @__PURE__ */ jsx16(Text16, { children: paintRow([styled(escapeContent(text), selected ? "fg" : "fgDim")]) })
9743
9839
  ] }, label);
9744
9840
  }
9745
- function line5(text, token) {
9841
+ function line3(text, token) {
9746
9842
  return /* @__PURE__ */ jsx16(Text16, { children: paintRow([styled(escapeContent(text), token)]) });
9747
9843
  }
9748
9844
  function PlanDirectoryPane({
@@ -9770,8 +9866,8 @@ function PlanDirectoryPane({
9770
9866
  )
9771
9867
  ),
9772
9868
  switchError !== void 0 && switchError !== "" ? /* @__PURE__ */ jsxs15(Box16, { flexDirection: "column", width: "100%", children: [
9773
- line5(`\u2717 \u5207\u6362\u8BA1\u5212\u5931\u8D25\uFF1A${switchError}`, "error"),
9774
- line5(SWITCH_NEXT, "fgDim")
9869
+ line3(`\u2717 \u5207\u6362\u8BA1\u5212\u5931\u8D25\uFF1A${switchError}`, "error"),
9870
+ line3(SWITCH_NEXT, "fgDim")
9775
9871
  ] }) : null
9776
9872
  ] });
9777
9873
  }
@@ -9787,7 +9883,7 @@ var PLAN_REVIEW_WINDOW = 12;
9787
9883
  var EMPTY_PLAN_REVIEW_PANE = {
9788
9884
  open: false
9789
9885
  };
9790
- function line6(text, token, bold = false) {
9886
+ function line4(text, token, bold = false) {
9791
9887
  return /* @__PURE__ */ jsx17(Text17, { children: paintRow([styled(escapeContent(text), token, void 0, bold)]) });
9792
9888
  }
9793
9889
  function PlanReviewPane({
@@ -9800,14 +9896,14 @@ function PlanReviewPane({
9800
9896
  const safeOffset = Math.max(0, offset);
9801
9897
  const windowed = lines.slice(safeOffset, safeOffset + PLAN_REVIEW_WINDOW).join("\n");
9802
9898
  return /* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", width: "100%", children: [
9803
- line6(TITLE4, "fg", true),
9899
+ line4(TITLE4, "fg", true),
9804
9900
  deliveryError !== void 0 && deliveryError !== "" ? /* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", width: "100%", children: [
9805
- line6(`\u2717 \u8BA1\u5212\u8BC4\u5BA1\u672A\u80FD\u9001\u8FBE\uFF1A${deliveryError}`, "error"),
9806
- line6(DELIVERY_NEXT2, "fgDim")
9807
- ] }) : empty ? line6(EMPTY_BODY, "fg") : /* @__PURE__ */ jsx17(MarkdownBlock, { source: windowed }),
9808
- line6("\u6279\u51C6", "fg"),
9809
- line6("\u7EE7\u7EED\u89C4\u5212", "fg"),
9810
- line6(FOOTNOTE4, "fgDim")
9901
+ line4(`\u2717 \u8BA1\u5212\u8BC4\u5BA1\u672A\u80FD\u9001\u8FBE\uFF1A${deliveryError}`, "error"),
9902
+ line4(DELIVERY_NEXT2, "fgDim")
9903
+ ] }) : empty ? line4(EMPTY_BODY, "fg") : /* @__PURE__ */ jsx17(MarkdownBlock, { source: windowed }),
9904
+ line4("\u6279\u51C6", "fg"),
9905
+ line4("\u7EE7\u7EED\u89C4\u5212", "fg"),
9906
+ line4(FOOTNOTE4, "fgDim")
9811
9907
  ] });
9812
9908
  }
9813
9909
 
@@ -9823,9 +9919,6 @@ var EMPTY_ASK_USER_PANE = {
9823
9919
  options: [],
9824
9920
  selectedIndex: 0
9825
9921
  };
9826
- function line7(text, token, bold = false) {
9827
- return /* @__PURE__ */ jsx18(Text18, { children: paintRow([styled(escapeContent(text), token, void 0, bold)]) });
9828
- }
9829
9922
  function AskUserPane({
9830
9923
  header,
9831
9924
  options,
@@ -9833,13 +9926,13 @@ function AskUserPane({
9833
9926
  }) {
9834
9927
  if (options.length === 0) {
9835
9928
  return /* @__PURE__ */ jsxs17(Box18, { flexDirection: "column", width: "100%", children: [
9836
- line7(INVALID_TITLE, "error", true),
9837
- line7(INVALID_NEXT, "fgDim")
9929
+ renderPaneLine(INVALID_TITLE, "error", true),
9930
+ renderPaneLine(INVALID_NEXT, "fgDim")
9838
9931
  ] });
9839
9932
  }
9840
9933
  const footnote = FOOTNOTE5;
9841
9934
  return /* @__PURE__ */ jsxs17(Box18, { flexDirection: "column", width: "100%", children: [
9842
- header !== "" ? line7(header, "fg", true) : null,
9935
+ header !== "" ? renderPaneLine(header, "fg", true) : null,
9843
9936
  /* @__PURE__ */ jsx18(Box18, { flexDirection: "column", marginTop: header !== "" ? 1 : 0, width: "100%", children: options.map((label, index) => {
9844
9937
  const selected = index === selectedIndex;
9845
9938
  const numbered = `${index + 1} ${label}`;
@@ -9848,7 +9941,7 @@ function AskUserPane({
9848
9941
  /* @__PURE__ */ jsx18(Text18, { children: paintRow([styled(escapeContent(numbered), selected ? "fg" : "fgDim", void 0, selected)]) })
9849
9942
  ] }, `${index}:${label}`);
9850
9943
  }) }),
9851
- /* @__PURE__ */ jsx18(Box18, { marginTop: 1, width: "100%", children: line7(footnote, "fgDim") })
9944
+ /* @__PURE__ */ jsx18(Box18, { marginTop: 1, width: "100%", children: renderPaneLine(footnote, "fgDim") })
9852
9945
  ] });
9853
9946
  }
9854
9947
 
@@ -9888,8 +9981,8 @@ function TimelineView({
9888
9981
  ] });
9889
9982
  }
9890
9983
  function firstLine(text) {
9891
- const line8 = text.split("\n")[0];
9892
- return line8.length > FIRST_LINE_MAX ? `${line8.slice(0, FIRST_LINE_MAX)}\u2026` : line8;
9984
+ const line5 = text.split("\n")[0];
9985
+ return line5.length > FIRST_LINE_MAX ? `${line5.slice(0, FIRST_LINE_MAX)}\u2026` : line5;
9893
9986
  }
9894
9987
 
9895
9988
  // tui-render/src/input-bar.tsx
@@ -10085,8 +10178,8 @@ function InputBar({
10085
10178
  const caret = Math.max(0, Math.min(caretIndex ?? text.length, text.length));
10086
10179
  const caretLine = text.slice(0, caret).split("\n").length - 1;
10087
10180
  const caretLineStart = caret === 0 ? 0 : text.lastIndexOf("\n", caret - 1) + 1;
10088
- const windows = lines.map((line8, index) => composerLineWindow(
10089
- line8,
10181
+ const windows = lines.map((line5, index) => composerLineWindow(
10182
+ line5,
10090
10183
  index === caretLine ? caret - caretLineStart : void 0,
10091
10184
  Math.max(1, columns - 4)
10092
10185
  ));
@@ -10136,11 +10229,11 @@ function InputBar({
10136
10229
  backgroundColor: inkColor("inputBg"),
10137
10230
  children: [
10138
10231
  /* @__PURE__ */ jsx20(Text20, { wrap: "truncate", children: paintBackgroundRow(headerParts, "inputBg", columns) }),
10139
- lines.map((line8, lineIndex) => {
10232
+ lines.map((line5, lineIndex) => {
10140
10233
  const window = windows[lineIndex];
10141
10234
  let sourceColumn = 0;
10142
10235
  const endColumn = window.startColumn + displayWidth(window.text);
10143
- const tokenParts = tokenizeComposer(line8).map((token) => {
10236
+ const tokenParts = tokenizeComposer(line5).map((token) => {
10144
10237
  const safe = escapeContent(token.text).replace(/\t/gu, "\\t");
10145
10238
  const width = displayWidth(safe);
10146
10239
  const visible = displayColumnSlice(
@@ -10375,7 +10468,8 @@ function workspaceSegments(view, columns) {
10375
10468
  }
10376
10469
  if (view.gitBranch !== void 0 && view.gitBranch !== "") {
10377
10470
  const git = segment(`git: ${escapeContent(view.gitBranch)}`, "accentText");
10378
- const candidate = selected.length > 1 ? [selected[0], git, ...selected.slice(1)] : [...selected, git];
10471
+ const first = selected[0];
10472
+ const candidate = selected.length > 1 && first !== void 0 ? [first, git, ...selected.slice(1)] : [...selected, git];
10379
10473
  if (displayWidth(segmentsText(candidate)) <= columns) {
10380
10474
  selected = candidate;
10381
10475
  }
@@ -10916,7 +11010,7 @@ function ToolDetailsPane({ state, columns, maxRows, pageRows, locale }) {
10916
11010
  }
10917
11011
  return /* @__PURE__ */ jsxs21(Box23, { flexDirection: "column", width: "100%", children: [
10918
11012
  /* @__PURE__ */ jsx29(Text29, { wrap: "truncate", children: heading }),
10919
- lines.map((line8, index) => /* @__PURE__ */ jsx29(Text29, { wrap: "truncate", children: line8 }, index)),
11013
+ lines.map((line5, index) => /* @__PURE__ */ jsx29(Text29, { wrap: "truncate", children: line5 }, index)),
10920
11014
  /* @__PURE__ */ jsx29(Text29, { dimColor: true, wrap: "truncate", children: escapeContent(tuiCopy(state.detail ? "toolPageHint" : "toolListHint", locale)) })
10921
11015
  ] });
10922
11016
  }
@@ -10967,6 +11061,80 @@ function holdComposer(state, action) {
10967
11061
  historyDraft: state.historyDraft
10968
11062
  };
10969
11063
  }
11064
+ function resetComposerDispatch(state, action, text = "") {
11065
+ return {
11066
+ kind: "dispatch",
11067
+ action,
11068
+ text,
11069
+ commandQuery: state.commandQuery,
11070
+ prefixG: false,
11071
+ renaming: state.renaming
11072
+ };
11073
+ }
11074
+ function restoreHistoryDraft(state) {
11075
+ const restored = state.historyDraft ?? "";
11076
+ return {
11077
+ kind: "dispatch",
11078
+ action: { kind: "none" },
11079
+ text: restored,
11080
+ commandQuery: void 0,
11081
+ prefixG: false,
11082
+ renaming: state.renaming,
11083
+ caretIndex: restored.length,
11084
+ historyIndex: void 0,
11085
+ historyDraft: void 0
11086
+ };
11087
+ }
11088
+ function applySelectedMention(state, candidate) {
11089
+ if (candidate === void 0) return { kind: "none" };
11090
+ const inserted = normalizeMentionInsertion(candidate);
11091
+ return {
11092
+ kind: "dispatch",
11093
+ action: { kind: "none" },
11094
+ text: inserted,
11095
+ commandQuery: void 0,
11096
+ prefixG: false,
11097
+ renaming: state.renaming,
11098
+ mentionSelectedIndex: 0,
11099
+ mentionDismissed: false,
11100
+ commandSelectedIndex: 0,
11101
+ commandDismissed: false,
11102
+ caretIndex: inserted.length
11103
+ };
11104
+ }
11105
+ function verticalNavEffect(key, keyInfo, state, actionForDelta) {
11106
+ if (key === "j" || keyInfo.downArrow) {
11107
+ return holdComposer(state, actionForDelta(1));
11108
+ }
11109
+ if (key === "k" || keyInfo.upArrow) {
11110
+ return holdComposer(state, actionForDelta(-1));
11111
+ }
11112
+ return void 0;
11113
+ }
11114
+ function appendQueryFilterEffect(state, char, makeAction) {
11115
+ const appended = state.text + char;
11116
+ return {
11117
+ kind: "dispatch",
11118
+ action: makeAction(appended),
11119
+ text: appended,
11120
+ commandQuery: state.commandQuery,
11121
+ prefixG: false,
11122
+ renaming: state.renaming
11123
+ };
11124
+ }
11125
+ function moveCaretToEffect(state, caretIndex) {
11126
+ return {
11127
+ kind: "dispatch",
11128
+ action: { kind: "none" },
11129
+ text: state.text,
11130
+ commandQuery: state.commandQuery,
11131
+ prefixG: false,
11132
+ renaming: state.renaming,
11133
+ caretIndex,
11134
+ historyIndex: state.historyIndex,
11135
+ historyDraft: state.historyDraft
11136
+ };
11137
+ }
10970
11138
  function draftKeyEffect(state, key, keyInfo, actions) {
10971
11139
  if (keyInfo.escape) {
10972
11140
  return {
@@ -11306,34 +11474,13 @@ function mapKeyEvent(state, key, keyInfo, commands, pane, search, timeline = { o
11306
11474
  return holdComposer(state, { kind: "workflow-overlay-escape" });
11307
11475
  }
11308
11476
  if (modelPane.open) {
11309
- return {
11310
- kind: "dispatch",
11311
- action: { kind: "model-pane" },
11312
- text: "",
11313
- commandQuery: state.commandQuery,
11314
- prefixG: false,
11315
- renaming: state.renaming
11316
- };
11477
+ return resetComposerDispatch(state, { kind: "model-pane" });
11317
11478
  }
11318
11479
  if (helpPane.open) {
11319
- return {
11320
- kind: "dispatch",
11321
- action: { kind: "help-pane" },
11322
- text: state.text,
11323
- commandQuery: state.commandQuery,
11324
- prefixG: false,
11325
- renaming: state.renaming
11326
- };
11480
+ return holdComposer(state, { kind: "help-pane" });
11327
11481
  }
11328
11482
  if (search.open) {
11329
- return {
11330
- kind: "dispatch",
11331
- action: { kind: "search-pane" },
11332
- text: "",
11333
- commandQuery: state.commandQuery,
11334
- prefixG: false,
11335
- renaming: state.renaming
11336
- };
11483
+ return resetComposerDispatch(state, { kind: "search-pane" });
11337
11484
  }
11338
11485
  if (state.renaming) {
11339
11486
  return {
@@ -11366,18 +11513,7 @@ function mapKeyEvent(state, key, keyInfo, commands, pane, search, timeline = { o
11366
11513
  };
11367
11514
  }
11368
11515
  if (state.historyIndex !== void 0) {
11369
- const restored = state.historyDraft ?? "";
11370
- return {
11371
- kind: "dispatch",
11372
- action: { kind: "none" },
11373
- text: restored,
11374
- commandQuery: void 0,
11375
- prefixG: false,
11376
- renaming: state.renaming,
11377
- caretIndex: restored.length,
11378
- historyIndex: void 0,
11379
- historyDraft: void 0
11380
- };
11516
+ return restoreHistoryDraft(state);
11381
11517
  }
11382
11518
  return {
11383
11519
  kind: "dispatch",
@@ -11390,19 +11526,7 @@ function mapKeyEvent(state, key, keyInfo, commands, pane, search, timeline = { o
11390
11526
  }
11391
11527
  if (keyInfo.return) {
11392
11528
  if (mention.open) {
11393
- if (mention.selectedCandidate === void 0) return { kind: "none" };
11394
- const inserted = normalizeMentionInsertion(mention.selectedCandidate);
11395
- return {
11396
- kind: "dispatch",
11397
- action: { kind: "none" },
11398
- text: inserted,
11399
- commandQuery: void 0,
11400
- prefixG: false,
11401
- renaming: state.renaming,
11402
- mentionSelectedIndex: 0,
11403
- mentionDismissed: false,
11404
- caretIndex: inserted.length
11405
- };
11529
+ return applySelectedMention(state, mention.selectedCandidate);
11406
11530
  }
11407
11531
  if (agentHubOpen) {
11408
11532
  return holdComposer(state, { kind: "agent-hub-enter" });
@@ -11428,35 +11552,20 @@ function mapKeyEvent(state, key, keyInfo, commands, pane, search, timeline = { o
11428
11552
  }
11429
11553
  if (modelPane.open) {
11430
11554
  if (modelPane.selectedId === void 0) return { kind: "none" };
11431
- return {
11432
- kind: "dispatch",
11433
- action: { kind: "select-model", id: modelPane.selectedId },
11434
- text: "",
11435
- commandQuery: state.commandQuery,
11436
- prefixG: false,
11437
- renaming: state.renaming
11438
- };
11555
+ return resetComposerDispatch(state, {
11556
+ kind: "select-model",
11557
+ id: modelPane.selectedId
11558
+ });
11439
11559
  }
11440
11560
  if (helpPane.open) {
11441
- return {
11442
- kind: "dispatch",
11443
- action: { kind: "help-pane" },
11444
- text: state.text,
11445
- commandQuery: state.commandQuery,
11446
- prefixG: false,
11447
- renaming: state.renaming
11448
- };
11561
+ return holdComposer(state, { kind: "help-pane" });
11449
11562
  }
11450
11563
  if (search.open) {
11451
11564
  if (search.selectedId === void 0) return { kind: "none" };
11452
- return {
11453
- kind: "dispatch",
11454
- action: { kind: "select-session", id: search.selectedId },
11455
- text: "",
11456
- commandQuery: state.commandQuery,
11457
- prefixG: false,
11458
- renaming: state.renaming
11459
- };
11565
+ return resetComposerDispatch(state, {
11566
+ kind: "select-session",
11567
+ id: search.selectedId
11568
+ });
11460
11569
  }
11461
11570
  if (state.renaming) {
11462
11571
  return {
@@ -11574,21 +11683,7 @@ function mapKeyEvent(state, key, keyInfo, commands, pane, search, timeline = { o
11574
11683
  }
11575
11684
  if (key === " " || keyInfo.tab) {
11576
11685
  if (mention.open) {
11577
- if (mention.selectedCandidate === void 0) return { kind: "none" };
11578
- const inserted = normalizeMentionInsertion(mention.selectedCandidate);
11579
- return {
11580
- kind: "dispatch",
11581
- action: { kind: "none" },
11582
- text: inserted,
11583
- commandQuery: void 0,
11584
- prefixG: false,
11585
- renaming: state.renaming,
11586
- mentionSelectedIndex: 0,
11587
- mentionDismissed: false,
11588
- commandSelectedIndex: 0,
11589
- commandDismissed: false,
11590
- caretIndex: inserted.length
11591
- };
11686
+ return applySelectedMention(state, mention.selectedCandidate);
11592
11687
  }
11593
11688
  if (commandMode) {
11594
11689
  const query = state.commandQuery ?? state.text.slice(1);
@@ -11674,125 +11769,29 @@ function mapKeyEvent(state, key, keyInfo, commands, pane, search, timeline = { o
11674
11769
  }
11675
11770
  }
11676
11771
  if (search.open) {
11677
- if (key === "j" || keyInfo.downArrow) {
11678
- return {
11679
- kind: "dispatch",
11680
- action: { kind: "session-pane-move", delta: 1 },
11681
- text: state.text,
11682
- commandQuery: state.commandQuery,
11683
- prefixG: false,
11684
- renaming: state.renaming,
11685
- caretIndex: state.caretIndex
11686
- };
11687
- }
11688
- if (key === "k" || keyInfo.upArrow) {
11689
- return {
11690
- kind: "dispatch",
11691
- action: { kind: "session-pane-move", delta: -1 },
11692
- text: state.text,
11693
- commandQuery: state.commandQuery,
11694
- prefixG: false,
11695
- renaming: state.renaming,
11696
- caretIndex: state.caretIndex
11697
- };
11698
- }
11772
+ const nav = verticalNavEffect(key, keyInfo, state, (delta) => ({ kind: "session-pane-move", delta }));
11773
+ if (nav !== void 0) return nav;
11699
11774
  if (isTextInput(key, keyInfo)) {
11700
- const appended = state.text + key;
11701
- return {
11702
- kind: "dispatch",
11703
- action: { kind: "search", query: appended },
11704
- text: appended,
11705
- commandQuery: state.commandQuery,
11706
- prefixG: false,
11707
- renaming: state.renaming
11708
- };
11775
+ return appendQueryFilterEffect(state, key, (query) => ({ kind: "search", query }));
11709
11776
  }
11710
11777
  return { kind: "none" };
11711
11778
  }
11712
11779
  if (timeline.open) {
11713
- if (key === "j" || keyInfo.downArrow) {
11714
- return {
11715
- kind: "dispatch",
11716
- action: { kind: "timeline-scroll", delta: 1 },
11717
- text: state.text,
11718
- commandQuery: state.commandQuery,
11719
- prefixG: false,
11720
- renaming: state.renaming,
11721
- caretIndex: state.caretIndex
11722
- };
11723
- }
11724
- if (key === "k" || keyInfo.upArrow) {
11725
- return {
11726
- kind: "dispatch",
11727
- action: { kind: "timeline-scroll", delta: -1 },
11728
- text: state.text,
11729
- commandQuery: state.commandQuery,
11730
- prefixG: false,
11731
- renaming: state.renaming,
11732
- caretIndex: state.caretIndex
11733
- };
11734
- }
11780
+ const nav = verticalNavEffect(key, keyInfo, state, (delta) => ({ kind: "timeline-scroll", delta }));
11781
+ if (nav !== void 0) return nav;
11735
11782
  return { kind: "none" };
11736
11783
  }
11737
11784
  if (modelPane.open) {
11738
- if (key === "j" || keyInfo.downArrow) {
11739
- return {
11740
- kind: "dispatch",
11741
- action: { kind: "model-move", delta: 1 },
11742
- text: state.text,
11743
- commandQuery: state.commandQuery,
11744
- prefixG: false,
11745
- renaming: state.renaming,
11746
- caretIndex: state.caretIndex
11747
- };
11748
- }
11749
- if (key === "k" || keyInfo.upArrow) {
11750
- return {
11751
- kind: "dispatch",
11752
- action: { kind: "model-move", delta: -1 },
11753
- text: state.text,
11754
- commandQuery: state.commandQuery,
11755
- prefixG: false,
11756
- renaming: state.renaming,
11757
- caretIndex: state.caretIndex
11758
- };
11759
- }
11785
+ const nav = verticalNavEffect(key, keyInfo, state, (delta) => ({ kind: "model-move", delta }));
11786
+ if (nav !== void 0) return nav;
11760
11787
  if (isTextInput(key, keyInfo)) {
11761
- const appended = state.text + key;
11762
- return {
11763
- kind: "dispatch",
11764
- action: { kind: "model-filter", query: appended },
11765
- text: appended,
11766
- commandQuery: state.commandQuery,
11767
- prefixG: false,
11768
- renaming: state.renaming
11769
- };
11788
+ return appendQueryFilterEffect(state, key, (query) => ({ kind: "model-filter", query }));
11770
11789
  }
11771
11790
  return { kind: "none" };
11772
11791
  }
11773
11792
  if (helpPane.open) {
11774
- if (key === "j" || keyInfo.downArrow) {
11775
- return {
11776
- kind: "dispatch",
11777
- action: { kind: "help-scroll", delta: 1 },
11778
- text: state.text,
11779
- commandQuery: state.commandQuery,
11780
- prefixG: false,
11781
- renaming: state.renaming,
11782
- caretIndex: state.caretIndex
11783
- };
11784
- }
11785
- if (key === "k" || keyInfo.upArrow) {
11786
- return {
11787
- kind: "dispatch",
11788
- action: { kind: "help-scroll", delta: -1 },
11789
- text: state.text,
11790
- commandQuery: state.commandQuery,
11791
- prefixG: false,
11792
- renaming: state.renaming,
11793
- caretIndex: state.caretIndex
11794
- };
11795
- }
11793
+ const nav = verticalNavEffect(key, keyInfo, state, (delta) => ({ kind: "help-scroll", delta }));
11794
+ if (nav !== void 0) return nav;
11796
11795
  return { kind: "none" };
11797
11796
  }
11798
11797
  if (key === "g" && state.text === "") {
@@ -11895,28 +11894,8 @@ function mapKeyEvent(state, key, keyInfo, commands, pane, search, timeline = { o
11895
11894
  return { kind: "none" };
11896
11895
  }
11897
11896
  if (pane.open) {
11898
- if (key === "j" || keyInfo.downArrow) {
11899
- return {
11900
- kind: "dispatch",
11901
- action: { kind: "session-pane-move", delta: 1 },
11902
- text: state.text,
11903
- commandQuery: state.commandQuery,
11904
- prefixG: false,
11905
- renaming: state.renaming,
11906
- caretIndex: state.caretIndex
11907
- };
11908
- }
11909
- if (key === "k" || keyInfo.upArrow) {
11910
- return {
11911
- kind: "dispatch",
11912
- action: { kind: "session-pane-move", delta: -1 },
11913
- text: state.text,
11914
- commandQuery: state.commandQuery,
11915
- prefixG: false,
11916
- renaming: state.renaming,
11917
- caretIndex: state.caretIndex
11918
- };
11919
- }
11897
+ const nav = verticalNavEffect(key, keyInfo, state, (delta) => ({ kind: "session-pane-move", delta }));
11898
+ if (nav !== void 0) return nav;
11920
11899
  if (key === "r") {
11921
11900
  return {
11922
11901
  kind: "dispatch",
@@ -11981,17 +11960,7 @@ function mapKeyEvent(state, key, keyInfo, commands, pane, search, timeline = { o
11981
11960
  const caret = clampCaretIndex(state.text, state.caretIndex);
11982
11961
  const targetCaret = moveCaretUpLine(state.text, caret);
11983
11962
  if (targetCaret !== void 0) {
11984
- return {
11985
- kind: "dispatch",
11986
- action: { kind: "none" },
11987
- text: state.text,
11988
- commandQuery: state.commandQuery,
11989
- prefixG: false,
11990
- renaming: state.renaming,
11991
- caretIndex: targetCaret,
11992
- historyIndex: state.historyIndex,
11993
- historyDraft: state.historyDraft
11994
- };
11963
+ return moveCaretToEffect(state, targetCaret);
11995
11964
  }
11996
11965
  }
11997
11966
  if (state.text === "" && queuedDraft.headText !== void 0) {
@@ -12032,17 +12001,7 @@ function mapKeyEvent(state, key, keyInfo, commands, pane, search, timeline = { o
12032
12001
  const caret = clampCaretIndex(state.text, state.caretIndex);
12033
12002
  const targetCaret = moveCaretDownLine(state.text, caret);
12034
12003
  if (targetCaret !== void 0) {
12035
- return {
12036
- kind: "dispatch",
12037
- action: { kind: "none" },
12038
- text: state.text,
12039
- commandQuery: state.commandQuery,
12040
- prefixG: false,
12041
- renaming: state.renaming,
12042
- caretIndex: targetCaret,
12043
- historyIndex: state.historyIndex,
12044
- historyDraft: state.historyDraft
12045
- };
12004
+ return moveCaretToEffect(state, targetCaret);
12046
12005
  }
12047
12006
  }
12048
12007
  if (state.historyIndex !== void 0) {
@@ -12061,18 +12020,7 @@ function mapKeyEvent(state, key, keyInfo, commands, pane, search, timeline = { o
12061
12020
  historyDraft: state.historyDraft
12062
12021
  };
12063
12022
  }
12064
- const restored = state.historyDraft ?? "";
12065
- return {
12066
- kind: "dispatch",
12067
- action: { kind: "none" },
12068
- text: restored,
12069
- commandQuery: void 0,
12070
- prefixG: false,
12071
- renaming: state.renaming,
12072
- caretIndex: restored.length,
12073
- historyIndex: void 0,
12074
- historyDraft: void 0
12075
- };
12023
+ return restoreHistoryDraft(state);
12076
12024
  }
12077
12025
  return { kind: "none" };
12078
12026
  }
@@ -12251,7 +12199,9 @@ function TuiLoop({
12251
12199
  const timer = setInterval(() => {
12252
12200
  setGeneratingTick((t) => (t + 1) % 1e4);
12253
12201
  }, 100);
12254
- return () => clearInterval(timer);
12202
+ return () => {
12203
+ clearInterval(timer);
12204
+ };
12255
12205
  }, [model.status]);
12256
12206
  const footerSpinner = model.status === "generating" ? getBrailleSpinnerFrame(Date.now()) : void 0;
12257
12207
  const interaction = useSyncExternalStore(
@@ -12861,7 +12811,7 @@ function TuiLoop({
12861
12811
  const visibleLines = [
12862
12812
  truncateDisplay(workspace.join(" \xB7 "), Math.max(1, columns)),
12863
12813
  truncateDisplay(identity.join(" \xB7 "), Math.max(1, columns))
12864
- ].filter((line8) => line8 !== "");
12814
+ ].filter((line5) => line5 !== "");
12865
12815
  statusRowCount = visibleLines.length;
12866
12816
  status = createElement2(
12867
12817
  Box24,
@@ -12870,15 +12820,15 @@ function TuiLoop({
12870
12820
  width: "100%",
12871
12821
  backgroundColor: inkColor("bg")
12872
12822
  },
12873
- ...visibleLines.map((line8, index) => createElement2(
12823
+ ...visibleLines.map((line5, index) => createElement2(
12874
12824
  Text31,
12875
12825
  { key: `fallback-footer-${String(index)}` },
12876
- paintBackgroundRow([styled(line8, "fgDim")], "bg", columns)
12826
+ paintBackgroundRow([styled(line5, "fgDim")], "bg", columns)
12877
12827
  ))
12878
12828
  );
12879
12829
  }
12880
- const brandBlocked = state.text !== "" || model.status !== "idle" || pane.open || search.open || timelineOpen || modelPane.open || helpPane.open || toolDetailsPane.open || approvalPane.open || askUserPane.open || permissionPane.open || settingsPane.open || agentHubPane.open || planDirectoryPane.open || workspacePane.open || feedbackPane.open || workflowOverlay.open || planReviewPane.open;
12881
12830
  const viewportMotionPaused = pane.open || search.open || timelineOpen || modelPane.open || helpPane.open || toolDetailsPane.open || approvalPane.open || askUserPane.open || permissionPane.open || settingsPane.open || agentHubPane.open || planDirectoryPane.open || workspacePane.open || feedbackPane.open || workflowOverlay.open || planReviewPane.open;
12831
+ const brandBlocked = state.text !== "" || model.status !== "idle" || viewportMotionPaused;
12882
12832
  const brandLifecycleAllowed = !brandBlocked && (brandAnimationMode === "on" || brandAnimationMode === "auto" && brandAutoEligible);
12883
12833
  if (brandRevealStartedRef.current && !brandLifecycleAllowed) {
12884
12834
  brandRevealStoppedRef.current = true;
@@ -13191,16 +13141,16 @@ function lastFencedCode(text) {
13191
13141
  let openingLength;
13192
13142
  let bodyStart = 0;
13193
13143
  let latest;
13194
- for (const [index, line8] of lines.entries()) {
13144
+ for (const [index, line5] of lines.entries()) {
13195
13145
  if (openingLength === void 0) {
13196
- const opening = /^ {0,3}(`{3,})[^`]*$/u.exec(line8);
13146
+ const opening = /^ {0,3}(`{3,})[^`]*$/u.exec(line5);
13197
13147
  if (opening !== null) {
13198
13148
  openingLength = opening[1].length;
13199
13149
  bodyStart = index + 1;
13200
13150
  }
13201
13151
  continue;
13202
13152
  }
13203
- const closing = /^ {0,3}(`{3,})[ \t]*$/u.exec(line8);
13153
+ const closing = /^ {0,3}(`{3,})[ \t]*$/u.exec(line5);
13204
13154
  if (closing === null || closing[1].length < openingLength) continue;
13205
13155
  latest = lines.slice(bodyStart, index).join("\n");
13206
13156
  openingLength = void 0;
@@ -13642,6 +13592,10 @@ function reduceInteraction(state, event) {
13642
13592
  }
13643
13593
 
13644
13594
  // tui-render/src/index.ts
13595
+ if (typeof globalThis.React === "undefined") {
13596
+ ;
13597
+ globalThis.React = React;
13598
+ }
13645
13599
  function mountTuiRender(node, options = {}) {
13646
13600
  const env = options.env ?? process.env;
13647
13601
  const policy = options.renderPolicy ?? renderPolicyDefaults();