/** * Terminal input arrives as byte chunks, and one chunk can carry several * keypresses: a fast space-then-enter, a bridged stdin that batches reads, a * middle-click paste. Ink parses each chunk as exactly one keypress — * `parseKeypress(' \r')` matches neither member, so both keys silently * vanish (a multi-select question answered with an empty set). The splitter * below cuts every chunk into the individual keypress units Ink's parser * expects, keeping escape sequences and bracketed-paste blocks intact, and * the stdin proxy feeds the split stream to the Ink mount. * * @module @deepseek-ai/dsh-tui/input-split */ import { PassThrough } from 'node:stream'; /** One keypress cut from the input stream. */ export interface KeypressSplitter { /** Feed one chunk; returns every keypress unit this chunk completed. */ push(chunk: string): string[]; /** Whether an unterminated bracketed-paste block is currently held. */ openPaste(): boolean; /** * Last-resort escape hatch for a paste whose end marker never arrived: * drop the start marker and emit the held bytes as plain keypress units so * nothing (Esc and Ctrl+C included) stays hostage. Inert when no paste is * open. */ releaseStalePaste(): string[]; } /** * Build a stateful chunk splitter. A partial unit at the end of one chunk * (a cut CSI sequence, an open paste block) waits in the buffer for the * rest. A chunk-trailing lone ESC emits as the Escape key right away: * terminals send Escape as its own chunk, and holding it hostage for a * sequence that may never continue would break every Esc cancel. */ export declare function createKeypressSplitter(): KeypressSplitter; /** The stdin-shaped stream the Ink mount renders through. */ export interface TuiStdin extends PassThrough { /** Mirrors the real stdin so Ink's raw-mode gate passes. */ isTTY: boolean; /** Forwarded to the real stdin; Ink toggles it around focus. */ setRawMode(value: boolean): unknown; ref(): void; unref(): void; } /** * Wrap one real stdin in the splitting proxy: keypress units flow into a * PassThrough Ink reads, while raw-mode/ref calls forward to the source. * @param source - the process (or harness) input stream in raw mode. * @returns the proxy stream plus a dispose that detaches the tap. */ export declare function createSplitStdin(source: NodeJS.ReadStream): { stdin: TuiStdin; dispose: () => void; };