export declare enum ImageProtocol { Kitty = "\u001B_G", Iterm2 = "\u001B]1337;File=", Sixel = "\u001BPq" } export declare enum NotifyProtocol { Bell = "\u0007", Osc99 = "\u001B]99;;", Osc9 = "\u001B]9;" } export type TerminalId = "kitty" | "ghostty" | "wezterm" | "iterm2" | "vscode" | "alacritty" | "base" | "trueColor"; /** Terminal capability details used for rendering and protocol selection. */ export declare class TerminalInfo { readonly id: TerminalId; readonly imageProtocol: ImageProtocol | null; readonly trueColor: boolean; readonly hyperlinks: boolean; readonly notifyProtocol: NotifyProtocol; constructor(id: TerminalId, imageProtocol: ImageProtocol | null, trueColor: boolean, hyperlinks: boolean, notifyProtocol?: NotifyProtocol); isImageLine(line: string): boolean; formatNotification(message: string): string; sendNotification(message: string): void; } export declare function isNotificationSuppressed(): boolean; /** Returns whether stdout crosses an SSH transport, where animation bytes can outpace the link. */ export declare function isRemoteTerminalSession(env?: NodeJS.ProcessEnv): boolean; /** * Returns whether the process runs under a terminal multiplexer (tmux, GNU * screen, or zellij). Recognizes the same host markers as the renderer's * multiplexer predicate in tui.ts so capability selection and viewport-repaint * policy agree on what counts as a multiplexed host. Multiplexers intercept * graphics escapes and OSC 8 hyperlinks instead of forwarding them to the * outer terminal. */ export declare function isUnderTerminalMultiplexer(env?: NodeJS.ProcessEnv): boolean; export interface TerminalGraphicsFallbackOptions { /** * Permit cursor-neutral image escapes (kitty `a=p,C=1` placements) to render * inside this fallback scope. Cursor-advancing protocols (iTerm2/SIXEL) * remain suppressed. A nested scope without this option revokes the * permission for its own subtree. */ allowCursorNeutralImages?: boolean; } /** * Synchronously suppress terminal graphics while rendering a text-only surface. * Nested scopes remain active until the outermost scope exits. */ export declare function withTerminalGraphicsFallback(fn: () => T, options?: TerminalGraphicsFallbackOptions): T; /** Returns whether terminal graphics are currently suppressed by a render scope. */ export declare function isTerminalGraphicsFallbackActive(): boolean; /** * Returns whether cursor-neutral image escapes may render despite an active * graphics-fallback scope. True only when every active fallback scope opted in. */ export declare function isCursorNeutralImagePermittedInFallback(): boolean; /** * Returns whether PI_FORCE_IMAGE_PROTOCOL explicitly configures the image * protocol, including an explicit "off". An explicit configuration is * authoritative: runtime capability probes must not override it. */ export declare function isImageProtocolForced(): boolean; /** * Returns true when running in Windows Terminal with known SIXEL support. * * Windows Terminal introduced SIXEL support in preview 1.22. */ export declare function isWindowsTerminalPreviewSixelSupported(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): boolean; export declare const TERMINAL_ID: TerminalId; export declare const TERMINAL: TerminalInfo; type ImageProtocolChangeListener = (imageProtocol: ImageProtocol | null) => void; /** * Subscribe to runtime image-protocol changes (e.g. the asynchronous sixel * capability probe enabling graphics after startup). Returns an unsubscribe * function. Listeners fire only on actual changes. */ export declare function onImageProtocolChanged(listener: ImageProtocolChangeListener): () => void; /** * Override terminal image protocol at runtime after capability probes complete. */ export declare function setTerminalImageProtocol(imageProtocol: ImageProtocol | null): void; export declare function getTerminalInfo(terminalId: TerminalId): TerminalInfo; export interface CellDimensions { widthPx: number; heightPx: number; } export interface ImageDimensions { widthPx: number; heightPx: number; } export interface ImageRenderOptions { maxWidthCells?: number; maxHeightCells?: number; preserveAspectRatio?: boolean; /** * Kitty-only: stable placement id (`p=`). Re-emitting the same image id + * placement id *replaces* the existing placement instead of stacking a new * copy, which makes diff-renderer repaints idempotent. Callers that render * a persistent component should allocate one id per component instance. */ placementId?: number; /** * Kitty-only: stable image id (`i=`). Defaults to a content hash of the * base64 payload ({@link kittyImageId}). Pass a precomputed id to avoid * re-hashing large payloads on every render. */ imageId?: number; /** * Kitty-only: sink for the out-of-band data transmission (`a=t`) emitted * the first time an image id is rendered. Defaults to the process-wide * writer configured via {@link setKittyTransmitWriter} (stdout). */ onTransmit?: (sequence: string) => void; } /** * Derive a stable 32-bit non-zero kitty image id (`i=`) from image content * (FNV-1a over the base64 payload). Identical content maps to the same id, so * retransmission replaces the stored image instead of accumulating copies. */ export declare function kittyImageId(base64Data: string): number; export declare function getCellDimensions(): CellDimensions; export declare function setCellDimensions(dims: CellDimensions): void; export declare function encodeKitty(base64Data: string, options?: { columns?: number; rows?: number; imageId?: number; placementId?: number; }): string; /** Test hook: forget which kitty image ids were transmitted. */ export declare function resetKittyTransmissions(): void; /** * Override where out-of-band kitty data transmissions (`a=t`) are written. * The default writes directly to stdout: a transmit-only escape is * cursor-neutral (it uploads pixel data without drawing anything), so the * only ordering requirement is that it reaches the terminal before the * placement escape that references it — which the synchronous write during * render guarantees. Tests use this to capture transmissions. */ export declare function setKittyTransmitWriter(writer: (sequence: string) => void): void; /** * Encode a kitty transmit-only (`a=t`) escape: uploads image data under a * stable id without creating a placement. Chunked at 4096 bytes per spec. * * This is deliberately separate from placement: re-sending data (`a=t`/`a=T`) * for an existing image id deletes the image and ALL of its placements, so * data must be uploaded exactly once per id and repaints must go through * {@link encodeKittyPlacement} only. */ export declare function encodeKittyTransmit(base64Data: string, imageId: number): string; /** * Encode a kitty placement-only (`a=p`) escape referencing previously * transmitted data. Re-emitting the same i=/p= pair replaces that one * placement (never stacks, never touches sibling placements), and C=1 * keeps the cursor where it is so the escape can be emitted from the * component's first row without cursor-up tricks. */ export declare function encodeKittyPlacement(options: { imageId: number; placementId: number; columns: number; rows: number; }): string; export interface KittyPlacementReference { imageId: number; placementId: number; rows: number; } /** Extract bounded, named kitty placements from a rendered line. */ export declare function extractKittyPlacementReferences(line: string): KittyPlacementReference[]; /** Soft-delete one named kitty placement while retaining its transmitted pixels. */ export declare function encodeKittyPlacementDelete(reference: KittyPlacementReference): string; export declare function encodeITerm2(base64Data: string, options?: { width?: number | string; height?: number | string; name?: string; preserveAspectRatio?: boolean; inline?: boolean; }): string; export declare function calculateImageRows(imageDimensions: ImageDimensions, targetWidthCells: number, cellDimensions?: CellDimensions): number; export declare function getPngDimensions(base64Data: string): ImageDimensions | null; export declare function getJpegDimensions(base64Data: string): ImageDimensions | null; export declare function getGifDimensions(base64Data: string): ImageDimensions | null; export declare function getWebpDimensions(base64Data: string): ImageDimensions | null; export declare function getImageDimensions(base64Data: string, mimeType: string): ImageDimensions | null; export interface RenderedImage { sequence: string; rows: number; /** * True when the escape neither moves the cursor nor carries pixel data * (kitty `a=p,C=1` placements). Cursor-neutral sequences can be emitted * from the component's first row; cursor-advancing protocols * (iTerm2/SIXEL) must draw from the last reserved row instead. */ cursorNeutral?: boolean; } export declare function renderImage(base64Data: string, imageDimensions: ImageDimensions, options?: ImageRenderOptions): RenderedImage | null; export declare function imageFallback(mimeType: string, dimensions?: ImageDimensions, filename?: string): string; export type Iterm2Capability = { readonly key: string; readonly value: string; }; export type Iterm2CapabilityReply = "complete-f" | "missing-f" | "invalid-f" | undefined; /** * Classifies complete iTerm2 capability replies. An absent result means the * input does not yet contain a complete capability frame. */ export declare function parseITerm2CapabilityReply(input: Uint8Array | string): Iterm2CapabilityReply; export declare function encodeITerm2Multipart(base64Data: string, options?: { width?: number | string; height?: number | string; }): string[]; export declare function wrapITerm2RecordForTmux(record: string): string; export declare function wrapITerm2RecordsForTmux(records: readonly string[]): string[]; export declare function parseITerm2Capabilities(input: string): Iterm2Capability[]; export declare class Iterm2CapabilitiesParser { #private; push(input: Uint8Array | string): Iterm2Capability[]; reset(): void; } export {};