@crazyhappyone/dsh-tui 0.1.0-alpha.16 → 0.1.0-alpha.18

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.
Files changed (2) hide show
  1. package/dist/index.js +580 -257
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -38172,10 +38172,6 @@ var import_react40 = __toESM(require_react(), 1);
38172
38172
 
38173
38173
  // ../deepseek-harness/packages/tui/tui-render/src/content.ts
38174
38174
  var GRAPHEME = new Intl.Segmenter(void 0, { granularity: "grapheme" });
38175
- function firstGrapheme(text4) {
38176
- for (const part of GRAPHEME.segment(text4)) return part.segment;
38177
- return text4.slice(0, 1);
38178
- }
38179
38175
  function escapeContent(text4) {
38180
38176
  return text4.replace(
38181
38177
  /[\u0000-\u0008\u000B-\u001F\u007F]/g,
@@ -38185,7 +38181,20 @@ function escapeContent(text4) {
38185
38181
  var WIDE_SYMBOLS_OR_EMOJIS = /[\u26A0\u26A1\u2699\u2139\u23F1\u2328\u2709\u270F\u2712\u2702\u26C8\u2764\u2B50]/gu;
38186
38182
  function displayWidth(text4) {
38187
38183
  if (text4 === "") return 0;
38188
- if (/^[\x20-\x7e]*$/u.test(text4)) return text4.length;
38184
+ let cols = 0;
38185
+ let simple = true;
38186
+ for (let i = 0; i < text4.length; i += 1) {
38187
+ const code2 = text4.charCodeAt(i);
38188
+ if (code2 >= 32 && code2 <= 126) {
38189
+ cols += 1;
38190
+ } else if (code2 >= 19968 && code2 <= 40959 || code2 >= 13312 && code2 <= 19903 || code2 >= 12288 && code2 <= 12351 || code2 >= 65281 && code2 <= 65376) {
38191
+ cols += 2;
38192
+ } else {
38193
+ simple = false;
38194
+ break;
38195
+ }
38196
+ }
38197
+ if (simple) return cols;
38189
38198
  const base = stringWidth(text4);
38190
38199
  if (!/[\u26A0\u26A1\u2699\u2139\u23F1\u2328\u2709\u270F\u2712\u2702\u26C8\u2764\u2B50]/u.test(text4)) {
38191
38200
  return base;
@@ -38267,17 +38276,27 @@ function wrapDisplayLines(text4, maxCols) {
38267
38276
  out.push(line8);
38268
38277
  continue;
38269
38278
  }
38270
- let rest = line8;
38271
- while (rest !== "") {
38272
- const chunk = wcwidthSafeSlice(rest, maxCols);
38273
- if (chunk === "") {
38274
- const first = firstGrapheme(rest);
38275
- out.push(first);
38276
- rest = rest.slice(first.length);
38277
- continue;
38279
+ if (/^[\x20-\x7e]*$/u.test(line8)) {
38280
+ for (let i = 0; i < line8.length; i += maxCols) {
38281
+ out.push(line8.slice(i, i + maxCols));
38278
38282
  }
38279
- out.push(chunk);
38280
- rest = rest.slice(chunk.length);
38283
+ continue;
38284
+ }
38285
+ let curLine = "";
38286
+ let curCols = 0;
38287
+ for (const { segment: segment2 } of GRAPHEME.segment(line8)) {
38288
+ const width = displayWidth(segment2);
38289
+ if (curCols + width > maxCols && curLine !== "") {
38290
+ out.push(curLine);
38291
+ curLine = segment2;
38292
+ curCols = width;
38293
+ } else {
38294
+ curLine += segment2;
38295
+ curCols += width;
38296
+ }
38297
+ }
38298
+ if (curLine !== "") {
38299
+ out.push(curLine);
38281
38300
  }
38282
38301
  }
38283
38302
  return out;
@@ -38748,8 +38767,9 @@ function AppShell({ title, badge, children, status, input }) {
38748
38767
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexDirection: "row", width: "100%", flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: paintRow(titleParts) }) }),
38749
38768
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { width: "100%", flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: paintRow([styled(escapeContent("\u2500".repeat(columns)), "line")]) }) }),
38750
38769
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexDirection: "column", flexGrow: 1, width: "100%", overflow: "hidden", children }),
38751
- input !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexDirection: "row", width: "100%", flexShrink: 0, children: input }) : null,
38752
- status !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexDirection: "row", width: "100%", flexShrink: 0, children: status }) : null
38770
+ input !== void 0 && input !== null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexDirection: "row", width: "100%", flexShrink: 0, children: input }) : null,
38771
+ status !== void 0 && status !== null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { width: "100%", flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: paintRow([styled(escapeContent("\u2500".repeat(columns)), "line")]) }) }) : null,
38772
+ status !== void 0 && status !== null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexDirection: "row", width: "100%", flexShrink: 0, children: status }) : null
38753
38773
  ] });
38754
38774
  }
38755
38775
 
@@ -50185,6 +50205,84 @@ function textLines(text4, prefix = "") {
50185
50205
  return { text: prefix + text4.slice(lastStart, end < 0 ? text4.length : end), token: "codeBg" };
50186
50206
  });
50187
50207
  }
50208
+ function splitDiffLines(text4) {
50209
+ if (text4.length === 0) return [];
50210
+ const normalized = text4.endsWith("\n") ? text4.slice(0, -1) : text4;
50211
+ return normalized.split(/\r?\n/u);
50212
+ }
50213
+ function diffLines(oldLines, newLines) {
50214
+ if (oldLines.length === 0) return newLines.map((line8) => `+${line8}`);
50215
+ if (newLines.length === 0) return oldLines.map((line8) => `-${line8}`);
50216
+ const m = oldLines.length;
50217
+ const n = newLines.length;
50218
+ if (m * n > 5e5) {
50219
+ return [...oldLines.map((l) => `-${l}`), ...newLines.map((l) => `+${l}`)];
50220
+ }
50221
+ let prefixCount = 0;
50222
+ while (prefixCount < m && prefixCount < n && oldLines[prefixCount] === newLines[prefixCount]) {
50223
+ prefixCount++;
50224
+ }
50225
+ let suffixCount = 0;
50226
+ while (suffixCount < m - prefixCount && suffixCount < n - prefixCount && oldLines[m - 1 - suffixCount] === newLines[n - 1 - suffixCount]) {
50227
+ suffixCount++;
50228
+ }
50229
+ const trimmedOld = oldLines.slice(prefixCount, m - suffixCount);
50230
+ const trimmedNew = newLines.slice(prefixCount, n - suffixCount);
50231
+ const midM = trimmedOld.length;
50232
+ const midN = trimmedNew.length;
50233
+ const middle = [];
50234
+ if (midM === 0) {
50235
+ for (const line8 of trimmedNew) middle.push(`+${line8}`);
50236
+ } else if (midN === 0) {
50237
+ for (const line8 of trimmedOld) middle.push(`-${line8}`);
50238
+ } else {
50239
+ const stride = midN + 1;
50240
+ const dp = new Int32Array((midM + 1) * stride);
50241
+ for (let i2 = 0; i2 < midM; i2++) {
50242
+ for (let j2 = 0; j2 < midN; j2++) {
50243
+ const dest = (i2 + 1) * stride + (j2 + 1);
50244
+ if (trimmedOld[i2] === trimmedNew[j2]) {
50245
+ dp[dest] = (dp[i2 * stride + j2] ?? 0) + 1;
50246
+ } else {
50247
+ const up = dp[i2 * stride + (j2 + 1)] ?? 0;
50248
+ const left = dp[(i2 + 1) * stride + j2] ?? 0;
50249
+ dp[dest] = up > left ? up : left;
50250
+ }
50251
+ }
50252
+ }
50253
+ const rev = [];
50254
+ let i = midM;
50255
+ let j = midN;
50256
+ while (i > 0 || j > 0) {
50257
+ if (i > 0 && j > 0 && trimmedOld[i - 1] === trimmedNew[j - 1]) {
50258
+ rev.push(` ${trimmedOld[i - 1]}`);
50259
+ i--;
50260
+ j--;
50261
+ } else if (j > 0 && (i === 0 || (dp[i * stride + (j - 1)] ?? 0) >= (dp[(i - 1) * stride + j] ?? 0))) {
50262
+ rev.push(`+${trimmedNew[j - 1]}`);
50263
+ j--;
50264
+ } else if (i > 0) {
50265
+ rev.push(`-${trimmedOld[i - 1]}`);
50266
+ i--;
50267
+ }
50268
+ }
50269
+ for (let k = rev.length - 1; k >= 0; k--) {
50270
+ const item = rev[k];
50271
+ if (item !== void 0) middle.push(item);
50272
+ }
50273
+ }
50274
+ const result = [];
50275
+ for (let k = 0; k < prefixCount; k++) {
50276
+ result.push(` ${oldLines[k]}`);
50277
+ }
50278
+ for (const line8 of middle) {
50279
+ result.push(line8);
50280
+ }
50281
+ for (let k = m - suffixCount; k < m; k++) {
50282
+ result.push(` ${oldLines[k]}`);
50283
+ }
50284
+ return result;
50285
+ }
50188
50286
  function createToolBodyDocument(card, options) {
50189
50287
  const rows = new RowSequence();
50190
50288
  const section = (label, source) => {
@@ -50210,10 +50308,62 @@ function createToolBodyDocument(card, options) {
50210
50308
  const diffs = result?.card === "diff" ? result.diffs : card.callView?.card === "diff" ? card.callView.diffs : [];
50211
50309
  if (diffs.length === 0) break;
50212
50310
  const source = new RowSequence();
50311
+ let lastPath;
50213
50312
  for (const diff2 of diffs) {
50214
- source.push({ text: `--- ${diff2.path}`, token: "codeBg" });
50215
- if (diff2.oldText !== null) source.append(textLines(diff2.oldText, "- "));
50216
- source.append(textLines(diff2.newText, "+ "));
50313
+ if (diff2.path !== lastPath) {
50314
+ source.push({ text: `--- ${diff2.path}`, token: "codeBg" });
50315
+ lastPath = diff2.path;
50316
+ }
50317
+ const oldStart = diff2.oldStart ?? (diff2.oldText === null ? 0 : 1);
50318
+ const newStart = diff2.newStart ?? 1;
50319
+ let lines;
50320
+ let oldLinesCount = diff2.oldLines;
50321
+ let newLinesCount = diff2.newLines;
50322
+ if (diff2.lines !== void 0 && diff2.lines.length > 0) {
50323
+ lines = diff2.lines;
50324
+ oldLinesCount ??= diff2.oldText === null ? 0 : splitDiffLines(diff2.oldText).length;
50325
+ newLinesCount ??= splitDiffLines(diff2.newText).length;
50326
+ } else if (diff2.oldText === null) {
50327
+ const split = splitDiffLines(diff2.newText);
50328
+ lines = split.map((line8) => `+${line8}`);
50329
+ oldLinesCount = 0;
50330
+ newLinesCount = split.length;
50331
+ } else {
50332
+ const oldSplit = splitDiffLines(diff2.oldText);
50333
+ const newSplit = splitDiffLines(diff2.newText);
50334
+ lines = diffLines(oldSplit, newSplit);
50335
+ oldLinesCount ??= oldSplit.length;
50336
+ newLinesCount ??= newSplit.length;
50337
+ }
50338
+ const oldHunk = `${oldStart}${oldLinesCount !== 1 ? `,${oldLinesCount}` : ""}`;
50339
+ const newHunk = `${newStart}${newLinesCount !== 1 ? `,${newLinesCount}` : ""}`;
50340
+ source.push({ text: `@@ -${oldHunk} +${newHunk} @@`, token: "codeBg" });
50341
+ const maxLine = Math.max(oldStart + oldLinesCount, newStart + newLinesCount, 1);
50342
+ const gutterWidth = Math.max(3, String(maxLine).length);
50343
+ let curOld = oldStart === 0 ? 1 : oldStart;
50344
+ let curNew = newStart === 0 ? 1 : newStart;
50345
+ for (const raw of lines) {
50346
+ if (raw.startsWith("\\")) continue;
50347
+ if (raw.startsWith("-")) {
50348
+ const num = String(curOld).padStart(gutterWidth, " ");
50349
+ source.push({ text: `${num} \u2502 - ${raw.slice(1)}`, token: "codeBg" });
50350
+ curOld++;
50351
+ } else if (raw.startsWith("+")) {
50352
+ const num = String(curNew).padStart(gutterWidth, " ");
50353
+ source.push({ text: `${num} \u2502 + ${raw.slice(1)}`, token: "codeBg" });
50354
+ curNew++;
50355
+ } else if (raw.startsWith(" ")) {
50356
+ const num = String(curNew).padStart(gutterWidth, " ");
50357
+ source.push({ text: `${num} \u2502 ${raw.slice(1)}`, token: "codeBg" });
50358
+ curOld++;
50359
+ curNew++;
50360
+ } else {
50361
+ const num = String(curNew).padStart(gutterWidth, " ");
50362
+ source.push({ text: `${num} \u2502 ${raw}`, token: "codeBg" });
50363
+ curOld++;
50364
+ curNew++;
50365
+ }
50366
+ }
50217
50367
  }
50218
50368
  section("diff", source.build());
50219
50369
  break;
@@ -50585,7 +50735,9 @@ var ToolRowCache = class {
50585
50735
  }
50586
50736
  if (cached !== void 0) this.remove(key, cached);
50587
50737
  const document4 = expanded ? createToolBodyDocument(card, { diagnostics: false, includeArguments: false, locale }) : void 0;
50588
- const window2 = document4 === void 0 ? void 0 : planToolBodyWindow(document4, { line: 0, offset: 0 }, Math.max(1, width - 2), this.policy.previewRows);
50738
+ const isDiff = card.callView?.card === "diff" || card.resultView?.card === "diff";
50739
+ const rowBudget = isDiff ? this.policy.diffPreviewRows : this.policy.previewRows;
50740
+ const window2 = document4 === void 0 ? void 0 : planToolBodyWindow(document4, { line: 0, offset: 0 }, Math.max(1, width - 2), rowBudget);
50589
50741
  const entry = {
50590
50742
  card,
50591
50743
  document: document4,
@@ -50650,14 +50802,14 @@ var RENDER_POLICY_DEFAULT_SCROLL_STEP_PER_FRAME = 1;
50650
50802
  var RENDER_POLICY_DEFAULT_SCROLL_WHEEL_ROWS = 3;
50651
50803
  var RENDER_POLICY_DEFAULT_SCROLL_CATCH_UP_THRESHOLD = 10;
50652
50804
  var RENDER_POLICY_DEFAULT_SCROLL_MAX_CATCH_UP_STEP = 8;
50653
- var RENDER_POLICY_DEFAULT_CACHE_MAX_ROWS = 4096;
50654
- var RENDER_POLICY_DEFAULT_CACHE_MAX_BYTES = 4 * 1024 * 1024;
50805
+ var RENDER_POLICY_DEFAULT_CACHE_MAX_ROWS = 65536;
50806
+ var RENDER_POLICY_DEFAULT_CACHE_MAX_BYTES = 32 * 1024 * 1024;
50655
50807
  var RENDER_POLICY_DEFAULT_TRANSCRIPT_OVERSCAN = 16;
50656
50808
  var RENDER_POLICY_MAX_OVERSCAN = 50;
50657
50809
  var RENDER_POLICY_MAX_CACHE_ROWS = 1e6;
50658
- var RENDER_POLICY_MAX_CACHE_BYTES = 32 * 1024 * 1024;
50810
+ var RENDER_POLICY_MAX_CACHE_BYTES = 64 * 1024 * 1024;
50659
50811
  function toolPolicyDefaults() {
50660
- return { previewRows: 6, detailPageRows: 40, cacheEntries: 128, cacheRows: 2048 };
50812
+ return { previewRows: 6, diffPreviewRows: 200, detailPageRows: 40, cacheEntries: 512, cacheRows: 16384 };
50661
50813
  }
50662
50814
  function renderPolicyDefaults() {
50663
50815
  return {
@@ -50942,6 +51094,7 @@ function profilerOnRender(probe) {
50942
51094
  var import_jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
50943
51095
  var BRAND_FRAME_MS = 320;
50944
51096
  var BRAND_ART_ROWS = BRAND_HALF_BLOCK.length;
51097
+ var BRAND_MIN_HOME_ROWS = BRAND_ART_ROWS + 2;
50945
51098
  var BRAND_HOME_ROWS = BRAND_ART_ROWS + 3;
50946
51099
  var activeRevealTimers = 0;
50947
51100
  function activeBrandRevealTimerCount() {
@@ -50950,8 +51103,7 @@ function activeBrandRevealTimerCount() {
50950
51103
  var TIER_ORDER = [
50951
51104
  "half-block",
50952
51105
  "full-block",
50953
- "ascii",
50954
- "plain"
51106
+ "ascii"
50955
51107
  ];
50956
51108
  function rowsForTier(tier) {
50957
51109
  switch (tier) {
@@ -50964,12 +51116,13 @@ function rowsForTier(tier) {
50964
51116
  }
50965
51117
  }
50966
51118
  function rowsFit(rows, maxColumns, maxRows) {
50967
- return maxRows >= BRAND_HOME_ROWS && rows.length === BRAND_ART_ROWS && rows.every((row) => displayWidth(row) <= maxColumns);
51119
+ return maxRows >= BRAND_MIN_HOME_ROWS && rows.length === BRAND_ART_ROWS && rows.every((row) => displayWidth(row) <= maxColumns);
50968
51120
  }
50969
51121
  function selectBrandRenderTier(preferred, maxColumns, maxRows) {
51122
+ if (preferred === "plain") return "plain";
50970
51123
  const start = TIER_ORDER.indexOf(preferred);
50971
51124
  for (const tier of TIER_ORDER.slice(start)) {
50972
- if (tier === "plain" || rowsFit(rowsForTier(tier), maxColumns, maxRows)) return tier;
51125
+ if (rowsFit(rowsForTier(tier), maxColumns, maxRows)) return tier;
50973
51126
  }
50974
51127
  return "plain";
50975
51128
  }
@@ -51024,7 +51177,7 @@ function PixelFishHome({
51024
51177
  const home = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", alignItems: "center", width: "100%", children: [
51025
51178
  rows === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { flexDirection: "column", width: artWidth, children: rows.map((row, index2) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { children: paintRow([styled(row, "accent")]) }, `fish-${String(index2)}`)) }),
51026
51179
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { children: paintRow([styled(BRAND_PLAIN_WORDMARK, "accent", void 0, true)]) }),
51027
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { children: paintRow([styled(" ", "bg")]) }),
51180
+ maxRows >= BRAND_HOME_ROWS ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { children: paintRow([styled(" ", "bg")]) }) : null,
51028
51181
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { children: paintRow([styled(BRAND_HOME_LINE, "fg")]) })
51029
51182
  ] });
51030
51183
  return frameProbe === void 0 ? home : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FrameProbe, { probe: frameProbe, children: home });
@@ -51165,6 +51318,9 @@ function reduceTranscriptViewport(state, action) {
51165
51318
  state.viewportRows
51166
51319
  );
51167
51320
  const follow = offsetFromBottom === 0 ? true : action.delta > 0 ? false : state.follow;
51321
+ if (offsetFromBottom === state.offsetFromBottom && follow === state.follow && (follow ? 0 : state.unseenRows) === state.unseenRows) {
51322
+ return state;
51323
+ }
51168
51324
  const nextTop = topRow({ ...state, offsetFromBottom });
51169
51325
  return {
51170
51326
  ...state,
@@ -51181,6 +51337,9 @@ function reduceTranscriptViewport(state, action) {
51181
51337
  state.viewportRows
51182
51338
  );
51183
51339
  const follow = offsetFromBottom === 0;
51340
+ if (offsetFromBottom === state.offsetFromBottom && follow === state.follow && (follow ? 0 : state.unseenRows) === state.unseenRows) {
51341
+ return state;
51342
+ }
51184
51343
  const nextTop = topRow({ ...state, offsetFromBottom });
51185
51344
  return {
51186
51345
  ...state,
@@ -51195,6 +51354,9 @@ function reduceTranscriptViewport(state, action) {
51195
51354
  const fraction = Math.max(0, Math.min(action.fraction, 1));
51196
51355
  const offsetFromBottom = Math.round(available * (1 - fraction));
51197
51356
  const follow = offsetFromBottom === 0;
51357
+ if (offsetFromBottom === state.offsetFromBottom && follow === state.follow && (follow ? 0 : state.unseenRows) === state.unseenRows) {
51358
+ return state;
51359
+ }
51198
51360
  const nextTop = topRow({ ...state, offsetFromBottom });
51199
51361
  return {
51200
51362
  ...state,
@@ -51206,6 +51368,9 @@ function reduceTranscriptViewport(state, action) {
51206
51368
  }
51207
51369
  case "edge": {
51208
51370
  if (action.edge === "latest") {
51371
+ if (state.follow && state.offsetFromBottom === 0 && state.unseenRows === 0 && state.anchor === void 0) {
51372
+ return state;
51373
+ }
51209
51374
  return {
51210
51375
  ...state,
51211
51376
  follow: true,
@@ -51215,6 +51380,9 @@ function reduceTranscriptViewport(state, action) {
51215
51380
  };
51216
51381
  }
51217
51382
  const offsetFromBottom = maxOffset(state.contentRows, state.viewportRows);
51383
+ if (!state.follow && state.offsetFromBottom === offsetFromBottom) {
51384
+ return state;
51385
+ }
51218
51386
  return {
51219
51387
  ...state,
51220
51388
  follow: false,
@@ -51222,8 +51390,12 @@ function reduceTranscriptViewport(state, action) {
51222
51390
  anchor: anchorForRow(0, state.blocks)
51223
51391
  };
51224
51392
  }
51225
- case "reset":
51393
+ case "reset": {
51394
+ if (state.follow && state.offsetFromBottom === 0 && state.unseenRows === 0 && state.contentRows === 0 && state.viewportRows === 0 && state.blocks.length === 0 && state.anchor === void 0) {
51395
+ return state;
51396
+ }
51226
51397
  return EMPTY_TRANSCRIPT_VIEWPORT;
51398
+ }
51227
51399
  }
51228
51400
  }
51229
51401
  function physicalScrollRailGeometry(contentRows, viewportRows, offsetFromBottom) {
@@ -51450,8 +51622,11 @@ function setVisibleFrameSnapshot(snapshot) {
51450
51622
  function visibleFrameSnapshot() {
51451
51623
  return publishedSnapshot;
51452
51624
  }
51625
+ var lineIdentityCache = /* @__PURE__ */ new WeakMap();
51453
51626
  function physicalLineIdentity(line8) {
51454
- return JSON.stringify([
51627
+ let cached = lineIdentityCache.get(line8);
51628
+ if (cached !== void 0) return cached;
51629
+ cached = JSON.stringify([
51455
51630
  line8.text,
51456
51631
  line8.displayWidth,
51457
51632
  line8.background ?? "bg",
@@ -51463,6 +51638,8 @@ function physicalLineIdentity(line8) {
51463
51638
  span.href ?? ""
51464
51639
  ])
51465
51640
  ]);
51641
+ lineIdentityCache.set(line8, cached);
51642
+ return cached;
51466
51643
  }
51467
51644
  function createFrameSnapshotRow(input) {
51468
51645
  return Object.freeze({
@@ -51470,18 +51647,29 @@ function createFrameSnapshotRow(input) {
51470
51647
  identity: physicalLineIdentity(input.line)
51471
51648
  });
51472
51649
  }
51473
- function geometryIdentity(geometry) {
51474
- return JSON.stringify(geometry);
51650
+ function sameGeometry(a, b) {
51651
+ if (a === b) return true;
51652
+ if (a.columns !== b.columns || a.rows !== b.rows || a.transcriptTop !== b.transcriptTop || a.transcriptLeft !== b.transcriptLeft || a.transcriptWidth !== b.transcriptWidth || a.transcriptRows !== b.transcriptRows) return false;
51653
+ const rA = a.rail;
51654
+ const rB = b.rail;
51655
+ if (rA === rB) return true;
51656
+ if (rA === void 0 || rB === void 0) return false;
51657
+ return rA.col === rB.col && rA.topRow === rB.topRow && rA.rows === rB.rows;
51475
51658
  }
51476
51659
  function screenRowKey(row) {
51477
- return `${String(row.row)}:${String(row.col)}`;
51660
+ return row.row << 16 | row.col;
51478
51661
  }
51479
51662
  function paintedColumns(line8) {
51480
51663
  return line8.backgroundColumns ?? line8.displayWidth;
51481
51664
  }
51482
51665
  function diffVisibleFrameSnapshots(previous3, next) {
51483
- const forced = previous3 === void 0 || geometryIdentity(previous3.geometry) !== geometryIdentity(next.geometry);
51484
- const oldRows = new Map(previous3?.rows.map((row) => [screenRowKey(row), row]) ?? []);
51666
+ const forced = previous3 === void 0 || !sameGeometry(previous3.geometry, next.geometry);
51667
+ const oldRows = /* @__PURE__ */ new Map();
51668
+ if (previous3 !== void 0) {
51669
+ for (const row of previous3.rows) {
51670
+ oldRows.set(screenRowKey(row), row);
51671
+ }
51672
+ }
51485
51673
  const changes = [];
51486
51674
  let unchangedRows = 0;
51487
51675
  for (const row of next.rows) {
@@ -51549,10 +51737,16 @@ function railRow(row, col, text4, tier) {
51549
51737
  const guard = col > 1 ? railCell(row, col - 1, " ", tier) : "";
51550
51738
  return guard + railCell(row, col, text4, tier);
51551
51739
  }
51552
- function railOverlay(tier) {
51553
- let cells = "";
51740
+ function sameRail(a, b) {
51741
+ if (a === b) return true;
51742
+ if (a === void 0 || b === void 0) return false;
51743
+ return a.col === b.col && a.topRow === b.topRow && a.rows === b.rows && a.thumbStart === b.thumbStart && a.thumbRows === b.thumbRows;
51744
+ }
51745
+ function railOverlay(tier, force = false) {
51554
51746
  const next = frameRail;
51555
51747
  const previous3 = paintedFrameRail;
51748
+ if (!force && sameRail(previous3, next)) return "";
51749
+ let cells = "";
51556
51750
  const geometry = visibleFrameSnapshot()?.geometry;
51557
51751
  const clearPreviousRow = (row, col) => {
51558
51752
  if (geometry !== void 0 && (col > geometry.columns || row < geometry.transcriptTop || row >= geometry.transcriptTop + geometry.transcriptRows || row > geometry.rows)) return "";
@@ -51581,17 +51775,40 @@ function railOverlay(tier) {
51581
51775
  paintedFrameRail = next;
51582
51776
  return cells === "" ? "" : `\x1B7${cells}\x1B8`;
51583
51777
  }
51778
+ var paintedPhysicalLineCache = /* @__PURE__ */ new WeakMap();
51584
51779
  function paintPhysicalLine(line8, tier) {
51780
+ const hyperlinks2 = hyperlinksEnabled();
51781
+ const cacheKey = `${tier}:${hyperlinks2 ? 1 : 0}`;
51782
+ let byTier = paintedPhysicalLineCache.get(line8);
51783
+ if (byTier === void 0) {
51784
+ byTier = /* @__PURE__ */ new Map();
51785
+ paintedPhysicalLineCache.set(line8, byTier);
51786
+ }
51787
+ const cached = byTier.get(cacheKey);
51788
+ if (cached !== void 0) return cached;
51585
51789
  const parts = line8.spans.map((span) => {
51586
51790
  const text4 = styled(span.text, span.token, tier, span.bold);
51587
- return span.href !== void 0 && hyperlinksEnabled() && isOsc8Href(span.href) ? wrapOsc8(text4, span.href) : text4;
51791
+ return span.href !== void 0 && hyperlinks2 && isOsc8Href(span.href) ? wrapOsc8(text4, span.href) : text4;
51588
51792
  });
51589
- return line8.background !== void 0 && line8.background !== "bg" ? paintBackgroundRow(
51793
+ const painted = line8.background !== void 0 && line8.background !== "bg" ? paintBackgroundRow(
51590
51794
  parts,
51591
51795
  line8.background,
51592
51796
  line8.backgroundColumns ?? Math.max(1, line8.displayWidth),
51593
51797
  tier
51594
51798
  ) : paintRow(parts, tier);
51799
+ byTier.set(cacheKey, painted);
51800
+ return painted;
51801
+ }
51802
+ var blankPadCache = /* @__PURE__ */ new Map();
51803
+ function blankPad(count, tier) {
51804
+ if (count <= 0) return "";
51805
+ const key = `${tier}:${String(count)}`;
51806
+ let cached = blankPadCache.get(key);
51807
+ if (cached === void 0) {
51808
+ cached = styled(" ".repeat(count), "bg", tier);
51809
+ blankPadCache.set(key, cached);
51810
+ }
51811
+ return cached;
51595
51812
  }
51596
51813
  function transcriptOverlay(tier, synchronizedFrameEnded) {
51597
51814
  const next = visibleFrameSnapshot();
@@ -51600,6 +51817,9 @@ function transcriptOverlay(tier, synchronizedFrameEnded) {
51600
51817
  paintedTranscriptRepaintKey = void 0;
51601
51818
  return "";
51602
51819
  }
51820
+ if (paintedVisibleFrame === next && (next.repaintKey === void 0 || next.repaintKey === paintedTranscriptRepaintKey)) {
51821
+ return "";
51822
+ }
51603
51823
  const diff2 = diffVisibleFrameSnapshots(paintedVisibleFrame, next);
51604
51824
  if (diff2.forced && !synchronizedFrameEnded) return "";
51605
51825
  const repaintAll = synchronizedFrameEnded && (diff2.forced || next.repaintKey !== void 0 && next.repaintKey !== paintedTranscriptRepaintKey);
@@ -51608,7 +51828,7 @@ function transcriptOverlay(tier, synchronizedFrameEnded) {
51608
51828
  let cells = "";
51609
51829
  if (repaintAll) {
51610
51830
  const { columns, transcriptRows, transcriptTop } = next.geometry;
51611
- const blank = styled(" ".repeat(columns), "bg", tier);
51831
+ const blank = blankPad(columns, tier);
51612
51832
  for (let index2 = 0; index2 < transcriptRows; index2 += 1) {
51613
51833
  cells += `\x1B[${String(transcriptTop + index2)};1H${blank}`;
51614
51834
  }
@@ -51627,7 +51847,7 @@ function transcriptOverlay(tier, synchronizedFrameEnded) {
51627
51847
  cells += `\x1B[${String(change.row)};${String(change.col)}H` + paintPhysicalLine(change.line, tier);
51628
51848
  }
51629
51849
  if (padColumns > 0) {
51630
- cells += `\x1B[${String(change.row)};${String(change.col + nextWidth)}H` + styled(" ".repeat(padColumns), "bg", tier);
51850
+ cells += `\x1B[${String(change.row)};${String(change.col + nextWidth)}H` + blankPad(padColumns, tier);
51631
51851
  }
51632
51852
  }
51633
51853
  return cells === "" ? "" : `\x1B7${cells}\x1B8`;
@@ -51642,7 +51862,7 @@ function publishedCaretBytes() {
51642
51862
  }
51643
51863
  function writePublishedFrameSnapshot(stdout, tier = currentTier()) {
51644
51864
  const transcript = transcriptOverlay(tier, true);
51645
- const rail = railOverlay(tier);
51865
+ const rail = railOverlay(tier, false);
51646
51866
  const overlay = transcript + rail;
51647
51867
  if (overlay === "") return;
51648
51868
  const bytes = START_SYNC + overlay + caretSuffix() + END_SYNC;
@@ -51673,7 +51893,7 @@ function transformFrameChunk(chunk, tier = currentTier(), publishFrame = true) {
51673
51893
  }
51674
51894
  const isFrame = out.includes(END_SYNC) || out.includes(SHOW_CURSOR) || out.includes(HIDE_CURSOR);
51675
51895
  if (isFrame && publishFrame) {
51676
- const overlay = transcriptOverlay(tier, out.includes(END_SYNC)) + railOverlay(tier) + caretSuffix();
51896
+ const overlay = transcriptOverlay(tier, out.includes(END_SYNC)) + railOverlay(tier, true) + caretSuffix();
51677
51897
  const syncIndex = out.lastIndexOf(END_SYNC);
51678
51898
  out = syncIndex < 0 ? out + overlay : out.slice(0, syncIndex) + overlay + out.slice(syncIndex);
51679
51899
  }
@@ -54184,7 +54404,15 @@ function latestAssistantId(history, activeTurn) {
54184
54404
  }
54185
54405
  return void 0;
54186
54406
  }
54407
+ var baseMarkdownLineCache = /* @__PURE__ */ new WeakMap();
54187
54408
  function markdownLineToPhysicalLine(blockId, line8) {
54409
+ let byBlock = baseMarkdownLineCache.get(line8);
54410
+ if (byBlock === void 0) {
54411
+ byBlock = /* @__PURE__ */ new Map();
54412
+ baseMarkdownLineCache.set(line8, byBlock);
54413
+ }
54414
+ const cached = byBlock.get(blockId);
54415
+ if (cached !== void 0) return cached;
54188
54416
  const segments = [];
54189
54417
  for (const span of line8.spans) {
54190
54418
  const text4 = displayColumnSlice(line8.text, span.start, span.end);
@@ -54198,7 +54426,7 @@ function markdownLineToPhysicalLine(blockId, line8) {
54198
54426
  }
54199
54427
  const sourceStart = Math.max(0, line8.sourceStart);
54200
54428
  const sourceEnd = Math.max(sourceStart, line8.sourceEnd < 0 ? sourceStart : line8.sourceEnd);
54201
- return createPhysicalLine({
54429
+ const created = createPhysicalLine({
54202
54430
  blockId,
54203
54431
  spans: segments.length === 0 ? [{ text: "", token: "fg", bold: false }] : segments,
54204
54432
  sourceStart,
@@ -54207,6 +54435,8 @@ function markdownLineToPhysicalLine(blockId, line8) {
54207
54435
  ...line8.background === void 0 ? {} : { background: line8.background },
54208
54436
  ...line8.backgroundColumns === void 0 ? {} : { backgroundColumns: line8.backgroundColumns }
54209
54437
  });
54438
+ byBlock.set(blockId, created);
54439
+ return created;
54210
54440
  }
54211
54441
  function overlayPromptOnSpans(spans, prompt) {
54212
54442
  const result = [];
@@ -54242,7 +54472,38 @@ function overlayPromptOnSpans(spans, prompt) {
54242
54472
  });
54243
54473
  return result;
54244
54474
  }
54475
+ var frameLineCache = /* @__PURE__ */ new WeakMap();
54245
54476
  function framePhysicalLine(blockId, line8, lead, active, prompt) {
54477
+ if (prompt === void 0) {
54478
+ let byLine = frameLineCache.get(line8);
54479
+ if (byLine === void 0) {
54480
+ byLine = /* @__PURE__ */ new Map();
54481
+ frameLineCache.set(line8, byLine);
54482
+ }
54483
+ const key = `${blockId}:${lead}:${active ? "1" : "0"}`;
54484
+ const cached = byLine.get(key);
54485
+ if (cached !== void 0) return cached;
54486
+ const base2 = markdownLineToPhysicalLine(blockId, line8);
54487
+ const spans2 = lead === "" ? base2.spans : [
54488
+ {
54489
+ text: lead,
54490
+ token: lead.trim() === "" ? "bg" : "accentText",
54491
+ bold: active && lead.trim() !== ""
54492
+ },
54493
+ ...base2.spans
54494
+ ];
54495
+ const created = lead === "" ? base2 : createPhysicalLine({
54496
+ blockId,
54497
+ spans: spans2,
54498
+ sourceStart: base2.sourceStart,
54499
+ sourceEnd: base2.sourceEnd,
54500
+ blockRow: base2.blockRow,
54501
+ ...base2.background === void 0 ? {} : { background: base2.background },
54502
+ ...base2.backgroundColumns === void 0 ? {} : { backgroundColumns: base2.backgroundColumns }
54503
+ });
54504
+ byLine.set(key, created);
54505
+ return created;
54506
+ }
54246
54507
  const base = markdownLineToPhysicalLine(blockId, line8);
54247
54508
  const initialSpans = [
54248
54509
  ...lead === "" ? [] : [{
@@ -54252,7 +54513,7 @@ function framePhysicalLine(blockId, line8, lead, active, prompt) {
54252
54513
  }],
54253
54514
  ...base.spans
54254
54515
  ];
54255
- const spans = prompt !== void 0 ? overlayPromptOnSpans(initialSpans, prompt) : initialSpans;
54516
+ const spans = overlayPromptOnSpans(initialSpans, prompt);
54256
54517
  return createPhysicalLine({
54257
54518
  blockId,
54258
54519
  spans,
@@ -54353,6 +54614,9 @@ function cachedPaintedRenderLine(line8, cacheKey, hyperlinks2) {
54353
54614
  variants.set(cacheKey, painted);
54354
54615
  return painted;
54355
54616
  }
54617
+ function areSlicedLinesBlockPropsEqual(prev, next) {
54618
+ return prev.lines === next.lines && prev.sliceStart === next.sliceStart && prev.sliceEnd === next.sliceEnd && prev.textRanges === next.textRanges && prev.tailRow === next.tailRow && prev.tail === next.tail && prev.prefix.first === next.prefix.first && prev.prefix.rest === next.prefix.rest;
54619
+ }
54356
54620
  var SlicedLinesBlock = (0, import_react37.memo)(function SlicedLinesBlock2(props) {
54357
54621
  const { lines, sliceStart, sliceEnd, prefix, textRanges, tailRow, tail } = props;
54358
54622
  const end = Math.min(lines.length, Math.max(0, sliceEnd));
@@ -54381,7 +54645,28 @@ var SlicedLinesBlock = (0, import_react37.memo)(function SlicedLinesBlock2(props
54381
54645
  return null;
54382
54646
  }
54383
54647
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { flexDirection: "column", width: "100%", children: out });
54384
- });
54648
+ }, areSlicedLinesBlockPropsEqual);
54649
+ function projectBlockEntry(deps, ownerId, entry, scope, state, active) {
54650
+ if (entry.kind === "tool-card" && entry.meta?.toolCard !== void 0) {
54651
+ return { lines: deps.toolRows.rows(entry.id, entry.meta.toolCard, scope.width, scope.fold.tools, deps.locale) };
54652
+ }
54653
+ if (entry.kind === "reasoning" && entry.meta?.reasoningExpanded === true && entry.source !== "") {
54654
+ const rows = new RowSequence();
54655
+ const header = `${entry.meta.reasoningLive === true ? "" : "\u25BE "}\u273B ${tuiCopy("reasoning", deps.locale)} (${((entry.meta.reasoningDurationMs ?? 0) / 1e3).toFixed(1)}s)`;
54656
+ rows.push({ ...GAP_LINE, text: header, displayWidth: displayWidth(header), spans: [{ start: 0, end: displayWidth(header), token: "fgDim", bold: false }] });
54657
+ rows.append(deps.plainRows.rows(entry.id, entry.source, Math.max(1, scope.width - 4)));
54658
+ return { lines: rows.build() };
54659
+ }
54660
+ const projection = projectBlockRows(entry, scope, state);
54661
+ deps.storeBlocks.set(entry.id, {
54662
+ ownerId,
54663
+ entry,
54664
+ scope,
54665
+ lines: projection.lines,
54666
+ active
54667
+ });
54668
+ return projection;
54669
+ }
54385
54670
  function StreamView({
54386
54671
  model,
54387
54672
  presenters,
@@ -54400,6 +54685,7 @@ function StreamView({
54400
54685
  const policy = renderPolicy ?? renderPolicyDefaults();
54401
54686
  const toolRows = (0, import_react37.useMemo)(() => new ToolRowCache(policy.tools), [
54402
54687
  policy.tools.previewRows,
54688
+ policy.tools.diffPreviewRows,
54403
54689
  policy.tools.cacheEntries,
54404
54690
  policy.tools.cacheRows
54405
54691
  ]);
@@ -54452,6 +54738,7 @@ function StreamView({
54452
54738
  const presentationQueue = (0, import_react37.useRef)(void 0);
54453
54739
  const frameArbiter = (0, import_react37.useRef)(void 0);
54454
54740
  const pendingScrollInputAt = (0, import_react37.useRef)(void 0);
54741
+ const lastDispatchedOffset = (0, import_react37.useRef)(viewport.offsetFromBottom);
54455
54742
  (0, import_react37.useLayoutEffect)(() => {
54456
54743
  const scroll = createScrollScheduler({
54457
54744
  frameIntervalMs: policy.scroll.frameIntervalMs,
@@ -54483,12 +54770,11 @@ function StreamView({
54483
54770
  now: () => performance.now(),
54484
54771
  demandDriven: true
54485
54772
  });
54486
- let lastDispatchedOffset = -1;
54487
54773
  const unsubscribe = arbiter.onPublish((snapshot) => {
54488
54774
  const presented = snapshot.stream.at(-1);
54489
54775
  if (presented !== void 0) setPresentedEntryRows(presented);
54490
- if (snapshot.scroll.presented !== lastDispatchedOffset) {
54491
- lastDispatchedOffset = snapshot.scroll.presented;
54776
+ if (snapshot.scroll.presented !== lastDispatchedOffset.current) {
54777
+ lastDispatchedOffset.current = snapshot.scroll.presented;
54492
54778
  dispatchViewport({
54493
54779
  kind: "offset",
54494
54780
  offsetFromBottom: snapshot.scroll.presented
@@ -54605,7 +54891,8 @@ function StreamView({
54605
54891
  () => assistantProseScope(settledBlockRowsScope),
54606
54892
  [settledBlockRowsScope]
54607
54893
  );
54608
- const entryRows = (0, import_react37.useMemo)(() => {
54894
+ const hasActiveTurn = activeTurn !== void 0;
54895
+ const settledEntryRows = (0, import_react37.useMemo)(() => {
54609
54896
  const definitions = /* @__PURE__ */ new Map();
54610
54897
  const batchPresenters = presenters === void 0 ? void 0 : { get(name2) {
54611
54898
  if (!definitions.has(name2)) definitions.set(name2, presenters.get(name2));
@@ -54615,27 +54902,8 @@ function StreamView({
54615
54902
  const textRanges = /* @__PURE__ */ new Map();
54616
54903
  const storeBlocks = /* @__PURE__ */ new Map();
54617
54904
  const projectorCache = projectorStates.current;
54618
- const project = (ownerId, entry, scope, state, active) => {
54619
- if (entry.kind === "tool-card" && entry.meta?.toolCard !== void 0) {
54620
- return { lines: toolRows.rows(entry.id, entry.meta.toolCard, scope.width, scope.fold.tools, locale) };
54621
- }
54622
- if (entry.kind === "reasoning" && entry.meta?.reasoningExpanded === true && entry.source !== "") {
54623
- const rows2 = new RowSequence();
54624
- const header = `${entry.meta.reasoningLive === true ? "" : "\u25BE "}\u273B ${tuiCopy("reasoning", locale)} (${((entry.meta.reasoningDurationMs ?? 0) / 1e3).toFixed(1)}s)`;
54625
- rows2.push({ ...GAP_LINE, text: header, displayWidth: displayWidth(header), spans: [{ start: 0, end: displayWidth(header), token: "fgDim", bold: false }] });
54626
- rows2.append(plainRows.rows(entry.id, entry.source, Math.max(1, scope.width - 4)));
54627
- return { lines: rows2.build() };
54628
- }
54629
- const projection = projectBlockRows(entry, scope, state);
54630
- storeBlocks.set(entry.id, {
54631
- ownerId,
54632
- entry,
54633
- scope,
54634
- lines: projection.lines,
54635
- active
54636
- });
54637
- return projection;
54638
- };
54905
+ const project = (ownerId, entry, scope, state, active) => projectBlockEntry({ toolRows, plainRows, locale, storeBlocks }, ownerId, entry, scope, state, active);
54906
+ const latestAssistant = hasActiveTurn ? void 0 : latestAssistantId(history, void 0);
54639
54907
  for (const [index2, row] of transcript.entries()) {
54640
54908
  const id = transcriptBlockId(row);
54641
54909
  if (row.kind === "compaction") {
@@ -54654,7 +54922,7 @@ function StreamView({
54654
54922
  continue;
54655
54923
  }
54656
54924
  if (row.message.kind === "user") {
54657
- const hasSubsequent = index2 < transcript.length - 1 || activeTurn !== void 0;
54925
+ const hasSubsequent = index2 < transcript.length - 1 || hasActiveTurn;
54658
54926
  const projection = project(id, {
54659
54927
  id,
54660
54928
  kind: "user",
@@ -54732,7 +55000,7 @@ function StreamView({
54732
55000
  ranges.push({ start, end: rows2.length });
54733
55001
  }
54734
55002
  const tailMeta = {
54735
- ...latestAssistantId(history, activeTurn) === row.message.id ? { turnTailCompletionBoundary: true } : {},
55003
+ ...latestAssistant === row.message.id ? { turnTailCompletionBoundary: true } : {},
54736
55004
  ...(() => {
54737
55005
  const stats = formatTurnTailStats({
54738
55006
  turnOrdinal: row.message.turnOrdinal,
@@ -54762,123 +55030,154 @@ function StreamView({
54762
55030
  map.set(id, rows2.build());
54763
55031
  if (ranges.length > 0) textRanges.set(id, ranges);
54764
55032
  }
54765
- if (activeTurn !== void 0) {
54766
- const id = `assistant-turn-${String(activeTurn.turn)}`;
54767
- const rawParts = partsFromTurn(activeTurn);
54768
- const visibleParts = displayedParts(rawParts, reasoningExpanded);
54769
- if (status === "generating" && visibleParts.length === 0) {
54770
- const liveMs = liveDurationMs ?? activeTurn.reasoningDurationMs;
54771
- const fish = getSwimmingFishFrame(liveMs);
54772
- map.set(id, project(id, {
54773
- id,
54774
- kind: "active-placeholder",
54775
- source: "",
55033
+ return { rows: map, textRanges, storeBlocks };
55034
+ }, [
55035
+ contentWidth,
55036
+ expandedCompactionId,
55037
+ hasActiveTurn,
55038
+ history,
55039
+ locale,
55040
+ mode,
55041
+ plainRows,
55042
+ presenterCache,
55043
+ presenters,
55044
+ reasoningExpanded,
55045
+ settledAssistantBlockRowsScope,
55046
+ settledBlockRowsScope,
55047
+ toolCardsExpanded,
55048
+ toolRows,
55049
+ transcript
55050
+ ]);
55051
+ const activeTurnRows = (0, import_react37.useMemo)(() => {
55052
+ if (activeTurn === void 0) return void 0;
55053
+ const definitions = /* @__PURE__ */ new Map();
55054
+ const batchPresenters = presenters === void 0 ? void 0 : { get(name2) {
55055
+ if (!definitions.has(name2)) definitions.set(name2, presenters.get(name2));
55056
+ return definitions.get(name2);
55057
+ } };
55058
+ const storeBlocks = /* @__PURE__ */ new Map();
55059
+ const projectorCache = projectorStates.current;
55060
+ const project = (ownerId, entry, scope, state, active) => projectBlockEntry({ toolRows, plainRows, locale, storeBlocks }, ownerId, entry, scope, state, active);
55061
+ const id = `assistant-turn-${String(activeTurn.turn)}`;
55062
+ const rawParts = partsFromTurn(activeTurn);
55063
+ const visibleParts = displayedParts(rawParts, reasoningExpanded);
55064
+ if (status === "generating" && visibleParts.length === 0) {
55065
+ const liveMs = liveDurationMs ?? activeTurn.reasoningDurationMs;
55066
+ const fish = getSwimmingFishFrame(liveMs);
55067
+ const lines = project(id, {
55068
+ id,
55069
+ kind: "active-placeholder",
55070
+ source: "",
55071
+ meta: {
55072
+ activePlaceholder: `${fish} \u25CF \u6B63\u5728\u5904\u7406\u2026 (${formatSeconds(
55073
+ liveMs
55074
+ )}s)`
55075
+ }
55076
+ }, blockRowsScope, void 0, true).lines;
55077
+ return { id, lines, ranges: [], storeBlocks };
55078
+ }
55079
+ const parts = displayedParts(
55080
+ compactToolParts(rawParts, toolCardsExpanded, batchPresenters, mode, presenterCache),
55081
+ reasoningExpanded
55082
+ );
55083
+ const rows2 = new RowSequence();
55084
+ const ranges = [];
55085
+ let textIndex = 0;
55086
+ let lastVisiblePart = -1;
55087
+ for (const [partIndex, part] of parts.entries()) {
55088
+ if (isVisiblePart(part)) lastVisiblePart = partIndex;
55089
+ }
55090
+ for (const [partIndex, part] of parts.entries()) {
55091
+ if (turnPartGap(parts, partIndex) > 0) rows2.push(GAP_LINE);
55092
+ if (part.kind === "reasoning") {
55093
+ const live = status === "generating" && partIndex === lastVisiblePart;
55094
+ rows2.append(project(id, {
55095
+ id: `${id}-r-${String(partIndex)}`,
55096
+ kind: "reasoning",
55097
+ source: part.text,
54776
55098
  meta: {
54777
- activePlaceholder: `${fish} \u25CF \u6B63\u5728\u5904\u7406\u2026 (${formatSeconds(
54778
- liveMs
54779
- )}s)`
54780
- }
54781
- }, blockRowsScope, void 0, true).lines);
54782
- } else {
54783
- const parts = displayedParts(
54784
- compactToolParts(rawParts, toolCardsExpanded, batchPresenters, mode, presenterCache),
54785
- reasoningExpanded
54786
- );
54787
- const rows2 = new RowSequence();
54788
- const ranges = [];
54789
- let textIndex = 0;
54790
- let lastVisiblePart = -1;
54791
- for (const [partIndex, part] of parts.entries()) {
54792
- if (isVisiblePart(part)) lastVisiblePart = partIndex;
54793
- }
54794
- for (const [partIndex, part] of parts.entries()) {
54795
- if (turnPartGap(parts, partIndex) > 0) rows2.push(GAP_LINE);
54796
- if (part.kind === "reasoning") {
54797
- const live = status === "generating" && partIndex === lastVisiblePart;
54798
- rows2.append(project(id, {
54799
- id: `${id}-r-${String(partIndex)}`,
54800
- kind: "reasoning",
54801
- source: part.text,
54802
- meta: {
54803
- reasoningDurationMs: live ? liveDurationMs ?? part.durationMs : part.durationMs,
54804
- reasoningExpanded,
54805
- reasoningLive: live
54806
- }
54807
- }, blockRowsScope, void 0, status === "generating").lines);
54808
- continue;
54809
- }
54810
- if (part.kind === "tool-summary") {
54811
- rows2.append(project(id, {
54812
- id: `${id}-tool-summary`,
54813
- kind: "tool-summary",
54814
- source: toolSummaryText(part.summary, contentWidth),
54815
- meta: { toolSummaryStatus: toolSummaryStatus(part.summary) }
54816
- }, blockRowsScope, void 0, status === "generating").lines);
54817
- continue;
55099
+ reasoningDurationMs: live ? liveDurationMs ?? part.durationMs : part.durationMs,
55100
+ reasoningExpanded,
55101
+ reasoningLive: live
54818
55102
  }
54819
- if (part.kind === "card") {
54820
- const card = part.card;
54821
- rows2.append(project(id, {
54822
- id: `${id}-c-${card.callId}`,
54823
- kind: "tool-card",
54824
- source: "",
54825
- meta: {
54826
- toolCard: {
54827
- name: card.name,
54828
- arguments: card.arguments,
54829
- status: card.status,
54830
- ...card.resultText === void 0 ? {} : { resultText: card.resultText },
54831
- ...card.meta === void 0 ? {} : { meta: card.meta },
54832
- ...card.error === void 0 ? {} : { error: card.error },
54833
- ...card.callView === void 0 ? {} : { callView: card.callView },
54834
- ...card.resultView === void 0 ? {} : { resultView: card.resultView }
54835
- }
54836
- }
54837
- }, blockRowsScope, void 0, status === "generating").lines);
54838
- continue;
55103
+ }, blockRowsScope, void 0, status === "generating").lines);
55104
+ continue;
55105
+ }
55106
+ if (part.kind === "tool-summary") {
55107
+ rows2.append(project(id, {
55108
+ id: `${id}-tool-summary`,
55109
+ kind: "tool-summary",
55110
+ source: toolSummaryText(part.summary, contentWidth),
55111
+ meta: { toolSummaryStatus: toolSummaryStatus(part.summary) }
55112
+ }, blockRowsScope, void 0, status === "generating").lines);
55113
+ continue;
55114
+ }
55115
+ if (part.kind === "card") {
55116
+ const card = part.card;
55117
+ rows2.append(project(id, {
55118
+ id: `${id}-c-${card.callId}`,
55119
+ kind: "tool-card",
55120
+ source: "",
55121
+ meta: {
55122
+ toolCard: {
55123
+ name: card.name,
55124
+ arguments: card.arguments,
55125
+ status: card.status,
55126
+ ...card.resultText === void 0 ? {} : { resultText: card.resultText },
55127
+ ...card.meta === void 0 ? {} : { meta: card.meta },
55128
+ ...card.error === void 0 ? {} : { error: card.error },
55129
+ ...card.callView === void 0 ? {} : { callView: card.callView },
55130
+ ...card.resultView === void 0 ? {} : { resultView: card.resultView }
55131
+ }
54839
55132
  }
54840
- const start = rows2.length;
54841
- const partId = `${id}-t-${String(textIndex++)}`;
54842
- rows2.append(project(id, {
54843
- id: partId,
54844
- kind: "assistant-prose",
54845
- source: part.text
54846
- }, assistantBlockRowsScope, projectorStateFor(
54847
- projectorStates.current,
54848
- partId,
54849
- assistantBlockRowsScope
54850
- ), status === "generating").lines);
54851
- ranges.push({ start, end: rows2.length });
54852
- }
54853
- map.set(id, rows2.build());
54854
- if (ranges.length > 0) {
54855
- textRanges.set(id, ranges);
54856
- }
55133
+ }, blockRowsScope, void 0, status === "generating").lines);
55134
+ continue;
54857
55135
  }
54858
- }
54859
- return { rows: map, textRanges, storeBlocks };
55136
+ const start = rows2.length;
55137
+ const partId = `${id}-t-${String(textIndex++)}`;
55138
+ rows2.append(project(id, {
55139
+ id: partId,
55140
+ kind: "assistant-prose",
55141
+ source: part.text
55142
+ }, assistantBlockRowsScope, projectorStateFor(
55143
+ projectorCache,
55144
+ partId,
55145
+ assistantBlockRowsScope
55146
+ ), status === "generating").lines);
55147
+ ranges.push({ start, end: rows2.length });
55148
+ }
55149
+ return { id, lines: rows2.build(), ranges, storeBlocks };
54860
55150
  }, [
54861
- activeVersion,
54862
55151
  activeTurn,
55152
+ activeVersion,
54863
55153
  assistantBlockRowsScope,
54864
55154
  blockRowsScope,
54865
55155
  contentWidth,
54866
- expandedCompactionId,
54867
- history,
54868
55156
  liveDurationMs,
55157
+ locale,
55158
+ mode,
55159
+ plainRows,
55160
+ presenterCache,
54869
55161
  presenters,
54870
55162
  reasoningExpanded,
54871
55163
  status,
54872
- settledAssistantBlockRowsScope,
54873
- settledBlockRowsScope,
54874
55164
  toolCardsExpanded,
54875
- toolRows,
54876
- plainRows,
54877
- presenterCache,
54878
- locale,
54879
- transcript,
54880
- mode
55165
+ toolRows
54881
55166
  ]);
55167
+ const entryRows = (0, import_react37.useMemo)(() => {
55168
+ if (activeTurnRows === void 0) return settledEntryRows;
55169
+ const map = new Map(settledEntryRows.rows);
55170
+ map.set(activeTurnRows.id, activeTurnRows.lines);
55171
+ const textRanges = new Map(settledEntryRows.textRanges);
55172
+ if (activeTurnRows.ranges.length > 0) {
55173
+ textRanges.set(activeTurnRows.id, activeTurnRows.ranges);
55174
+ }
55175
+ const storeBlocks = new Map(settledEntryRows.storeBlocks);
55176
+ for (const [key, val] of activeTurnRows.storeBlocks) {
55177
+ storeBlocks.set(key, val);
55178
+ }
55179
+ return { rows: map, textRanges, storeBlocks };
55180
+ }, [settledEntryRows, activeTurnRows]);
54882
55181
  const [presentedEntryRows, setPresentedEntryRows] = (0, import_react37.useState)(entryRows);
54883
55182
  const activeEntryRows = status === "generating" ? presentedEntryRows : entryRows;
54884
55183
  (0, import_react37.useLayoutEffect)(() => {
@@ -55048,26 +55347,24 @@ function StreamView({
55048
55347
  ));
55049
55348
  lastProjectorMetrics.current = totals;
55050
55349
  }, [entryRows, frameMetrics]);
55350
+ const settledRenderEntries = (0, import_react37.useMemo)(() => transcript.flatMap((row, index2) => {
55351
+ const hasSubsequent = index2 < transcript.length - 1 || hasActiveTurn;
55352
+ const isUserWithGap = row.kind === "message" && row.message.kind === "user" && hasSubsequent;
55353
+ const gapRows = isUserWithGap ? 0 : hasSubsequent ? 2 : 0;
55354
+ const id = transcriptBlockId(row);
55355
+ const lines = settledEntryRows.rows.get(id) ?? [];
55356
+ return [{
55357
+ kind: "row",
55358
+ id,
55359
+ version: `${transcriptBlockVersion(row, revisions)}\0${hasSubsequent ? "gap" : "tail"}`,
55360
+ gapRows,
55361
+ estimatedRows: lines.length + gapRows,
55362
+ lines,
55363
+ row
55364
+ }];
55365
+ }), [hasActiveTurn, revisions, settledEntryRows, transcript]);
55051
55366
  const renderEntries = (0, import_react37.useMemo)(() => [
55052
- ...transcript.flatMap((row, index2) => {
55053
- const hasSubsequent = index2 < transcript.length - 1 || activeTurn !== void 0;
55054
- const isUserWithGap = row.kind === "message" && row.message.kind === "user" && hasSubsequent;
55055
- const gapRows = isUserWithGap ? 0 : hasSubsequent ? 2 : 0;
55056
- const id = transcriptBlockId(row);
55057
- if (activeTurn !== void 0 && id === `assistant-turn-${String(activeTurn.turn)}`) {
55058
- return [];
55059
- }
55060
- const lines = activeEntryRows.rows.get(id) ?? [];
55061
- return [{
55062
- kind: "row",
55063
- id,
55064
- version: `${transcriptBlockVersion(row, revisions)}\0${hasSubsequent ? "gap" : "tail"}`,
55065
- gapRows,
55066
- estimatedRows: lines.length + gapRows,
55067
- lines,
55068
- row
55069
- }];
55070
- }),
55367
+ ...settledRenderEntries.filter((entry) => activeTurn === void 0 || entry.id !== `assistant-turn-${String(activeTurn.turn)}`),
55071
55368
  ...activeTurn === void 0 ? [] : [{
55072
55369
  kind: "active",
55073
55370
  id: `assistant-turn-${String(activeTurn.turn)}`,
@@ -55081,7 +55378,7 @@ function StreamView({
55081
55378
  activeTurn,
55082
55379
  activeVersion,
55083
55380
  activeEntryRows,
55084
- transcript
55381
+ settledRenderEntries
55085
55382
  ]);
55086
55383
  const layoutScope = [
55087
55384
  contentWidth,
@@ -55179,16 +55476,22 @@ function StreamView({
55179
55476
  const idleHome = transcript.length === 0 && activeTurn === void 0;
55180
55477
  const generating = status === "generating";
55181
55478
  const latestSettledAssistantId = activeTurn === void 0 ? history.findLast((message) => message.kind === "assistant")?.id : void 0;
55182
- (0, import_react37.useLayoutEffect)(() => {
55183
- if (viewportCommand === void 0) return;
55184
- if (viewportCommand.sequence === lastCommandSequence.current) return;
55185
- if (viewportCommand.kind !== "reset" && (viewport.viewportRows === 0 || viewport.contentRows === 0)) return;
55186
- lastCommandSequence.current = viewportCommand.sequence;
55479
+ const viewportStateRef = (0, import_react37.useRef)(viewport);
55480
+ viewportStateRef.current = viewport;
55481
+ const virtualContentRowsRef = (0, import_react37.useRef)(virtualContentRows);
55482
+ virtualContentRowsRef.current = virtualContentRows;
55483
+ const effectiveViewportRowsRef = (0, import_react37.useRef)(effectiveViewportRows);
55484
+ effectiveViewportRowsRef.current = effectiveViewportRows;
55485
+ const executeViewportCommand = (0, import_react37.useCallback)((command) => {
55486
+ if (command.sequence === lastCommandSequence.current) return;
55487
+ const vp = viewportStateRef.current;
55488
+ if (command.kind !== "reset" && (vp.viewportRows === 0 || vp.contentRows === 0)) return;
55489
+ lastCommandSequence.current = command.sequence;
55187
55490
  const scheduler = scrollScheduler.current;
55188
55491
  const arbiter = frameArbiter.current;
55189
55492
  if (scheduler === void 0 || arbiter === void 0) return;
55190
- const effectiveContentRows = Math.max(viewport.contentRows, virtualContentRows);
55191
- const maximum = Math.max(0, effectiveContentRows - effectiveViewportRows);
55493
+ const effectiveContentRows = Math.max(vp.contentRows, virtualContentRowsRef.current);
55494
+ const maximum = Math.max(0, effectiveContentRows - effectiveViewportRowsRef.current);
55192
55495
  const clamp = (value) => Math.max(0, Math.min(maximum, value));
55193
55496
  const advance = (delta) => {
55194
55497
  const presented = scheduler.getPresented();
@@ -55199,43 +55502,53 @@ function StreamView({
55199
55502
  };
55200
55503
  if (pendingScrollInputAt.current !== void 0) frameMetrics?.recordCoalescedInput();
55201
55504
  pendingScrollInputAt.current ??= performance.now();
55202
- switch (viewportCommand.kind) {
55505
+ switch (command.kind) {
55203
55506
  case "scroll":
55204
- advance(viewportCommand.delta);
55507
+ advance(command.delta);
55205
55508
  break;
55206
55509
  case "page":
55207
- advance(viewportCommand.delta * Math.max(1, viewport.viewportRows - 1));
55510
+ advance(command.delta * Math.max(1, vp.viewportRows - 1));
55208
55511
  break;
55209
55512
  case "position":
55210
55513
  scheduler.snapTo(clamp(Math.round(
55211
- maximum * (1 - Math.max(0, Math.min(1, viewportCommand.fraction)))
55514
+ maximum * (1 - Math.max(0, Math.min(1, command.fraction)))
55212
55515
  )));
55213
55516
  break;
55214
55517
  case "edge":
55215
- scheduler.snapTo(viewportCommand.edge === "latest" ? 0 : maximum);
55518
+ scheduler.snapTo(command.edge === "latest" ? 0 : maximum);
55216
55519
  break;
55217
55520
  case "reset":
55218
55521
  scheduler.snapTo(0);
55522
+ lastDispatchedOffset.current = 0;
55219
55523
  pendingScrollInputAt.current = void 0;
55220
55524
  dispatchViewport({ kind: "reset" });
55221
55525
  return;
55222
55526
  }
55527
+ const presentedOffset = scheduler.getPresented();
55528
+ lastDispatchedOffset.current = presentedOffset;
55223
55529
  dispatchViewport({
55224
55530
  kind: "offset",
55225
- offsetFromBottom: scheduler.getPresented()
55531
+ offsetFromBottom: presentedOffset
55226
55532
  });
55227
55533
  arbiter.requestScroll();
55534
+ }, [frameMetrics]);
55535
+ (0, import_react37.useLayoutEffect)(() => {
55536
+ if (viewportCommand === void 0) return;
55537
+ if (viewportCommand.sequence === lastCommandSequence.current) return;
55538
+ executeViewportCommand(viewportCommand);
55228
55539
  }, [
55540
+ viewportCommand,
55541
+ executeViewportCommand,
55229
55542
  viewport.contentRows,
55230
55543
  viewport.viewportRows,
55231
55544
  effectiveViewportRows,
55232
- virtualContentRows,
55233
- viewportCommand
55545
+ virtualContentRows
55234
55546
  ]);
55235
55547
  (0, import_react37.useLayoutEffect)(() => {
55236
55548
  const scheduler = scrollScheduler.current;
55237
55549
  if (scheduler === void 0) return;
55238
- const maximum = Math.max(0, viewport.contentRows - viewport.viewportRows);
55550
+ const effectiveContentRows = Math.max(viewport.contentRows, virtualContentRows);
55551
+ const maximum = Math.max(0, effectiveContentRows - effectiveViewportRows);
55239
55552
  const presented = scheduler.getPresented();
55240
55553
  if (presented === viewport.offsetFromBottom) return;
55241
55554
  if (scheduler.isAnimating()) {
@@ -55243,19 +55556,23 @@ function StreamView({
55243
55556
  } else {
55244
55557
  scheduler.snapTo(Math.max(0, Math.min(maximum, viewport.offsetFromBottom)));
55245
55558
  }
55559
+ lastDispatchedOffset.current = viewport.offsetFromBottom;
55246
55560
  }, [
55561
+ effectiveViewportRows,
55247
55562
  viewport.contentRows,
55248
55563
  viewport.offsetFromBottom,
55249
- viewport.viewportRows
55564
+ virtualContentRows
55250
55565
  ]);
55251
55566
  (0, import_react37.useLayoutEffect)(() => {
55252
55567
  scrollScheduler.current?.snapTo(viewport.offsetFromBottom);
55568
+ lastDispatchedOffset.current = viewport.offsetFromBottom;
55253
55569
  }, [columns, rows]);
55254
55570
  (0, import_react37.useLayoutEffect)(() => {
55255
55571
  if (!motionPaused) return;
55256
55572
  const scheduler = scrollScheduler.current;
55257
55573
  if (scheduler === void 0) return;
55258
55574
  scheduler.snapTo(viewport.offsetFromBottom);
55575
+ lastDispatchedOffset.current = viewport.offsetFromBottom;
55259
55576
  }, [motionPaused, viewport.offsetFromBottom]);
55260
55577
  (0, import_react37.useLayoutEffect)(() => {
55261
55578
  const viewportElement = viewportRef.current;
@@ -55266,50 +55583,55 @@ function StreamView({
55266
55583
  const contentRows = layouts.at(-1) === void 0 ? 0 : layouts.at(-1).top + layouts.at(-1).rows;
55267
55584
  const contentChanged = contentRevision !== lastContentRevision.current;
55268
55585
  lastContentRevision.current = contentRevision;
55269
- dispatchViewport({
55270
- kind: "layout",
55271
- contentRows,
55272
- viewportRows: viewportBox.height,
55273
- blocks: layouts,
55274
- unseenRowsAdded: contentChanged ? Math.max(0, contentRows - viewport.contentRows) : 0
55275
- });
55276
- if (frameMetrics !== void 0) {
55277
- let mounted = 0;
55278
- for (const layoutIndex of visibleIndexes) {
55279
- const entry = renderEntries[layoutIndex];
55280
- if (entry === void 0) continue;
55281
- const layout = virtualLayouts[layoutIndex];
55282
- if (layout === void 0) {
55283
- continue;
55284
- }
55285
- let window2;
55286
- if (physicalViewport) {
55287
- window2 = sliceWindow(
55288
- entry.lines.length,
55289
- layout.top,
55290
- overscanTop,
55291
- overscanBottom
55292
- );
55293
- }
55294
- mounted += window2 === void 0 ? entry.lines.length : Math.max(0, window2.end - window2.start);
55295
- }
55296
- frameMetrics.addMountedRows(mounted);
55586
+ if (contentChanged || viewport.viewportRows !== viewportBox.height || viewport.contentRows !== contentRows) {
55587
+ dispatchViewport({
55588
+ kind: "layout",
55589
+ contentRows,
55590
+ viewportRows: viewportBox.height,
55591
+ blocks: layouts,
55592
+ unseenRowsAdded: contentChanged ? Math.max(0, contentRows - viewport.contentRows) : 0
55593
+ });
55297
55594
  }
55298
55595
  }, [
55299
55596
  columns,
55300
- rows,
55301
- layoutKey,
55302
- effectiveViewportRows,
55303
- frameMetrics,
55597
+ contentRevision,
55304
55598
  layoutInputs,
55599
+ layoutKey,
55305
55600
  layoutScope,
55601
+ rows,
55602
+ viewport.contentRows,
55603
+ viewport.viewportRows
55604
+ ]);
55605
+ (0, import_react37.useLayoutEffect)(() => {
55606
+ if (frameMetrics === void 0) return;
55607
+ let mounted = 0;
55608
+ for (const layoutIndex of visibleIndexes) {
55609
+ const entry = renderEntries[layoutIndex];
55610
+ if (entry === void 0) continue;
55611
+ const layout = virtualLayouts[layoutIndex];
55612
+ if (layout === void 0) {
55613
+ continue;
55614
+ }
55615
+ let window2;
55616
+ if (physicalViewport) {
55617
+ window2 = sliceWindow(
55618
+ entry.lines.length,
55619
+ layout.top,
55620
+ overscanTop,
55621
+ overscanBottom
55622
+ );
55623
+ }
55624
+ mounted += window2 === void 0 ? entry.lines.length : Math.max(0, window2.end - window2.start);
55625
+ }
55626
+ frameMetrics.addMountedRows(mounted);
55627
+ }, [
55628
+ frameMetrics,
55306
55629
  overscanBottom,
55307
- overscanRows,
55308
55630
  overscanTop,
55309
55631
  physicalViewport,
55310
55632
  renderEntries,
55311
55633
  virtualLayouts,
55312
- visibleEntries
55634
+ visibleIndexes
55313
55635
  ]);
55314
55636
  const rail = scrollbar ? physicalScrollRailGeometry(
55315
55637
  viewport.contentRows,
@@ -59097,12 +59419,12 @@ function TuiLoop({
59097
59419
  {
59098
59420
  flexDirection: "column",
59099
59421
  width: "100%",
59100
- backgroundColor: inkColor("inputBg")
59422
+ backgroundColor: inkColor("bg")
59101
59423
  },
59102
59424
  (0, import_react39.createElement)(
59103
59425
  Text,
59104
59426
  null,
59105
- paintBackgroundRow([feedbackLine(feedback)], "inputBg", columns)
59427
+ paintBackgroundRow([feedbackLine(feedback)], "bg", columns)
59106
59428
  )
59107
59429
  );
59108
59430
  } else if (adaptiveRows.length > 0) {
@@ -59142,14 +59464,14 @@ function TuiLoop({
59142
59464
  {
59143
59465
  flexDirection: "column",
59144
59466
  width: "100%",
59145
- backgroundColor: inkColor("inputBg")
59467
+ backgroundColor: inkColor("bg")
59146
59468
  },
59147
59469
  ...visibleRows.map((row, index2) => (0, import_react39.createElement)(
59148
59470
  Text,
59149
59471
  { key: `adaptive-footer-${String(index2)}` },
59150
59472
  paintBackgroundRow(
59151
59473
  row.runs.map((run2) => styled(run2.text, run2.token)),
59152
- "inputBg",
59474
+ "bg",
59153
59475
  columns
59154
59476
  )
59155
59477
  ))
@@ -59176,12 +59498,12 @@ function TuiLoop({
59176
59498
  {
59177
59499
  flexDirection: "column",
59178
59500
  width: "100%",
59179
- backgroundColor: inkColor("inputBg")
59501
+ backgroundColor: inkColor("bg")
59180
59502
  },
59181
59503
  ...visibleLines.map((line8, index2) => (0, import_react39.createElement)(
59182
59504
  Text,
59183
59505
  { key: `fallback-footer-${String(index2)}` },
59184
- paintBackgroundRow([styled(line8, "fgDim")], "inputBg", columns)
59506
+ paintBackgroundRow([styled(line8, "fgDim")], "bg", columns)
59185
59507
  ))
59186
59508
  );
59187
59509
  }
@@ -59212,7 +59534,7 @@ function TuiLoop({
59212
59534
  composerHud,
59213
59535
  queuedDraftCount
59214
59536
  ]);
59215
- const toolPaneRows = Math.max(4, rows - 2 - statusRowCount);
59537
+ const toolPaneRows = Math.max(4, rows - 3 - statusRowCount);
59216
59538
  const toolPageRows = Math.min((renderPolicy?.tools ?? toolPolicyDefaults()).detailPageRows, toolPaneRows - 3);
59217
59539
  toolDetailsSizeRef.current = { width: columns, pageRows: toolPageRows };
59218
59540
  const streamView = (0, import_react39.createElement)(StreamView, {
@@ -59306,7 +59628,7 @@ function TuiLoop({
59306
59628
  confirmDelete: pane.confirmDelete,
59307
59629
  deleteUnavailable: pane.deleteUnavailable,
59308
59630
  columns,
59309
- maxRows: rows - 2 - statusRowCount - (state.renaming ? state.text.split("\n").length + 1 : 0)
59631
+ maxRows: rows - 3 - statusRowCount - (state.renaming ? state.text.split("\n").length + 1 : 0)
59310
59632
  });
59311
59633
  } else if (search2.open) {
59312
59634
  content3 = (0, import_react39.createElement)(SearchPane, {
@@ -59349,7 +59671,7 @@ function TuiLoop({
59349
59671
  modelChip: adaptiveInfoFooter?.model,
59350
59672
  modeChip: currentMode,
59351
59673
  ...props,
59352
- rowsBelow: (props.rowsBelow ?? 0) + statusRowCount
59674
+ rowsBelow: (props.rowsBelow ?? 0) + statusRowCount + 1
59353
59675
  });
59354
59676
  let inputSlot;
59355
59677
  if (approvalPane.open) {
@@ -60315,6 +60637,7 @@ var Config = z.object({
60315
60637
  }),
60316
60638
  tools: z.object({
60317
60639
  previewRows: z.number().min(1).step(1).max(50).default(toolPolicyDefaults().previewRows),
60640
+ diffPreviewRows: z.number().min(1).step(1).max(2e3).default(toolPolicyDefaults().diffPreviewRows),
60318
60641
  detailPageRows: z.number().min(1).step(1).max(200).default(toolPolicyDefaults().detailPageRows),
60319
60642
  cacheEntries: z.number().min(1).step(1).max(4096).default(toolPolicyDefaults().cacheEntries),
60320
60643
  cacheRows: z.number().min(1).step(1).max(RENDER_POLICY_MAX_CACHE_ROWS).default(toolPolicyDefaults().cacheRows)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crazyhappyone/dsh-tui",
3
- "version": "0.1.0-alpha.16",
3
+ "version": "0.1.0-alpha.18",
4
4
  "description": "Source-runtime launcher for the DeepSeek Harness terminal interface",
5
5
  "type": "module",
6
6
  "license": "MIT",