/** * Token coalescer. Buffers stream tokens within a small time window before * dispatching a single aggregated chunk. Prevents 60+ re-renders per second * on fast streams. */ import { LIMITS } from '../constants'; export interface TokenBuffer { /** Append a delta. Returns immediately. */ push(delta: string): void; /** Force flush and resolve any pending timer. */ flush(): void; /** Stop accepting tokens; flush whatever is buffered. */ close(): void; } export function createTokenBuffer( onFlush: (delta: string) => void, windowMs = LIMITS.streamCoalesceMs, ): TokenBuffer { let pending = ''; let timer: ReturnType | null = null; let closed = false; const flush = () => { if (timer) { clearTimeout(timer); timer = null; } if (pending) { const out = pending; pending = ''; onFlush(out); } }; return { push(delta: string) { if (closed || !delta) return; pending += delta; if (windowMs <= 0) { flush(); return; } if (timer === null) { timer = setTimeout(flush, windowMs); } }, flush, close() { closed = true; flush(); }, }; }