fix(tui): highlighted closed streamed diff tails

Detected closed transient diff fences and highlighted their full code token, including the final row before the closing fence, before rows can enter native scrollback.

Added regression coverage for a closed diff followed by streaming prose pushing the final diff row into history.
This commit is contained in:
roboomp
2026-07-11 00:28:36 +00:00
parent e41b32c87f
commit 936e83e3de
2 changed files with 81 additions and 5 deletions
@@ -148,4 +148,46 @@ describe("transcript streaming commit (assistant text)", () => {
await term.flush();
}
});
it("keeps the final closed diff row highlighted while following prose streams", async () => {
if (process.platform === "win32") return;
const rows = 6;
const term = new VirtualTerminal(52, rows);
Object.defineProperty(term, "isNativeViewportAtBottom", { configurable: true, value: () => undefined });
const scheduler = new StressRenderScheduler();
const tui = new TUI(term, undefined, { renderScheduler: scheduler });
const chat = new TranscriptContainer();
const block = new StreamingMarkdownBlock();
const diffLines = Array.from({ length: 18 }, (_value, index) => {
const sign = index % 2 === 0 ? "-" : "+";
return `${sign}closed-${String(index).padStart(2, "0")}`;
});
const finalDiffLine = "+closed-tail-no-extra-newline";
const codeBlockSource = [...diffLines, finalDiffLine].join("\n");
const streamingProse = Array.from(
{ length: 12 },
(_value, index) => `still streaming prose line ${String(index).padStart(2, "0")}`,
).join("\n");
const closedFenceWithLiveTail = `\`\`\`diff\n${codeBlockSource}\n\`\`\`\n${streamingProse}`;
chat.addChild(block);
tui.addChild(chat);
try {
tui.start();
await scheduler.drain(term);
block.setStreamingText(closedFenceWithLiveTail);
tui.requestRender();
await scheduler.drain(term);
const streamedRows = term.getScrollBuffer().map(row => Bun.stripANSI(row).trimEnd());
const finalDiffRow = streamedRows.findIndex(row => row.includes(finalDiffLine));
expect(finalDiffRow).toBeGreaterThanOrEqual(0);
expect(finalDiffRow).toBeLessThan(term.getBufferPosition().baseY);
expect(foregroundColumnsForBufferRow(term, finalDiffRow).length).toBeGreaterThan(0);
} finally {
tui.stop();
await term.flush();
}
});
});