import type { ObserveBackend, SpawnOpts } from './types.js';
export declare class ZellijObserveBackend implements ObserveBackend {
    private readonly session;
    private readonly paneId;
    private readonly cliPid;
    private cols;
    private rows;
    private dataCbs;
    private exitCbs;
    private pollTimer;
    private livenessTimer;
    private lastSnapshot;
    private exited;
    /** # of live web-terminal `zellij attach` clients currently connected. While
     *  >0 the pollers go quiet — see setLiveAttach. */
    private liveAttachCount;
    claudeJsonlPath?: string;
    cliCwd?: string;
    constructor(session: string, paneId: string, opts?: {
        cliPid?: number;
    });
    /** bin/args are ignored — we observe an existing pane, we don't launch. */
    spawn(_bin: string, _args: string[], opts: SpawnOpts): void;
    private poll;
    private checkLiveness;
    /**
     * Mark a live web-terminal `zellij attach` client as (dis)connected.
     *
     * Every `zellij action` the pollers run (dump-screen poll @700ms, list-panes
     * liveness @1000ms) connects a transient client to the server, which makes the
     * server repaint ALL attached clients — so an attached web client redraws its
     * zellij chrome ~2×/s, i.e. the flicker 申晗 saw. While ≥1 attach client is up
     * the dump-screen poll is redundant (the attach IS the live view) so we stop
     * it, and liveness degrades to the churn-free pid syscall (see checkLiveness).
     * Reference-counted so multiple browser tabs compose; resumes on the last one.
     */
    setLiveAttach(active: boolean): void;
    /** True while ≥1 live web-attach client is up — the dump-screen poller is
     *  paused (see setLiveAttach), so screen changes flow only to the attach PTY
     *  and never bump the worker's onData/onPtyData activity watermark. Consumers
     *  that gate on that watermark must capture unconditionally in this window. */
    isLiveAttachActive(): boolean;
    /** Whether the adopted CLI process is still running. Unknown pid → defer to
     *  pane liveness only. EPERM (exists, not ours) counts as alive; ESRCH = gone. */
    private isCliPidAlive;
    private handlePaneExit;
    write(data: string): void;
    /** Literal text via write-chars (preserves UTF-8). */
    sendText(text: string): void;
    /** Special keys by tmux-style name → raw bytes → `action write`. */
    sendSpecialKeys(...keys: string[]): void;
    /** Bracketed paste — wrap so TUIs detect the boundary (mirrors paste-buffer -p). */
    pasteText(text: string): void;
    /** Write arbitrary bytes via `action write <decimal>…` (handles control/escape).
     *  Chunked so a large web-terminal paste can't blow the argv limit; zellij
     *  serialises the writes in arrival order. */
    private writeBytes;
    /** Resize is a NO-OP in observe mode — the pane size is the user's, and
     *  resizing it would disturb their layout. The transient snapshot reads the
     *  real pane size via getPaneSize(). */
    resize(_cols: number, _rows: number): void;
    onData(cb: (data: string) => void): void;
    onExit(cb: (code: number | null, signal: string | null) => void): void;
    getChildPid(): number | null;
    /** Detach observer — stop polling. Never touches the user's zellij session. */
    kill(): void;
    /** Adopt owns nothing — destroy == detach (don't kill the user's session). */
    destroySession(): void;
    private stopTimers;
    captureCurrentScreen(): string;
    captureViewport(): string;
    getPaneSize(): {
        cols: number;
        rows: number;
    } | null;
    isPaneAlive(): boolean;
    private dumpScreen;
    private listPane;
    /** Run a `zellij --session S action …`, returning stdout or null on failure. */
    private action;
}
//# sourceMappingURL=zellij-observe-backend.d.ts.map