fix(tui): harden Terminal.app render behavior

Avoid Terminal.app paint corruption by disabling fast-echo in that terminal, sanitizing non-SGR control sequences before ANSI rendering, and defaulting Apple Terminal back to the safer 256-color path unless truecolor is explicitly requested.
This commit is contained in:
Brooklyn Nicholson
2026-05-16 22:51:51 -05:00
parent 3b39096904
commit 290bf93104
9 changed files with 214 additions and 10 deletions

View File

@@ -8,12 +8,15 @@ import {
estimateRows,
estimateTokensRough,
fmtK,
hasAnsi,
isToolTrailResultLine,
lastCotTrailIndex,
parseToolTrailResultLine,
pasteTokenLabel,
sanitizeAnsiForRender,
sameToolTrailGroup,
splitToolDuration,
stripAnsi,
thinkingPreview
} from '../lib/text.js'
@@ -84,6 +87,27 @@ describe('estimateTokensRough', () => {
})
})
describe('ANSI sanitizers', () => {
const ESC = String.fromCharCode(27)
const BEL = String.fromCharCode(7)
it('strips CSI/OSC/control bytes from plain previews', () => {
const sample = `A${ESC}[31mB${ESC}[39m${ESC}[2J${ESC}]0;title${BEL}C${ESC}[?25lD`
expect(stripAnsi(sample)).toBe('ABCD')
})
it('keeps SGR color spans but removes cursor controls for Ansi rendering', () => {
const sample = `A${ESC}[31mB${ESC}[39m${ESC}[2J${ESC}]0;title${BEL}${ESC}[?25lC`
expect(sanitizeAnsiForRender(sample)).toBe(`A${ESC}[31mB${ESC}[39mC`)
})
it('detects non-CSI escape prefixes too', () => {
expect(hasAnsi(`ok${ESC}Ppayload${ESC}\\`)).toBe(true)
})
})
describe('thinkingPreview', () => {
it('adds paragraph breaks before markdown thinking headings', () => {
const raw =