// Reconstruction d'écran via @xterm/headless : terminal headless PERSISTANT par session, alimenté // incrémentalement par le flux PTY. Remplace le strip ANSI naïf (qui « mange les espaces » et casse // la détection des dialogues — verdict S1/S3). Aucune dépendance DOM (usage Node). import { Terminal } from '@xterm/headless'; export class ScreenReader { private readonly term: Terminal; constructor(cols = 120, rows = 40) { this.term = new Terminal({ cols, rows, scrollback: 0, allowProposedApi: true }); } /** * Alimente le terminal avec un chunk PTY brut (la frontière UTF-8 et les séquences ANSI coupées * sont gérées par xterm). La promesse se résout quand le chunk a été parsé (snapshot fiable ensuite). */ feed(chunk: Uint8Array | string): Promise { return new Promise((resolve) => this.term.write(chunk as Uint8Array, resolve)); } resize(cols: number, rows: number): void { this.term.resize(cols, rows); } /** Lignes visibles du viewport courant, espaces préservés (trim à droite uniquement). */ snapshotLines(): string[] { const buf = this.term.buffer.active; const lines: string[] = []; for (let y = 0; y < this.term.rows; y++) { const line = buf.getLine(buf.baseY + y); lines.push(line ? line.translateToString(true) : ''); } return lines; } dispose(): void { this.term.dispose(); } }