/** * Layout engine — exact line-count, character-count, and overflow computation * per history entry kind + terminal width. * * Pure functions (no React, no Ink, no DOM). Each entry's layout is computed * from its content and the current terminal width alone, so it can be cached, * serialised, and reused across re-renders and session resumes without * mounting the component tree just to discover row heights. * * The engine replaces the vague `estimateRenderGroupRows` heuristics with * deterministic line counts for every entry kind, handling: * - Text wrapping at a given terminal column width * - Tool card chrome (header, rail, footer) * - Code blocks and syntax-highlighted diffs * - Banners (compact / full artwork variant) * - Model-switch cards, brain cards, memory cards, etc. */ export interface EntryLayout { /** Entry id the layout belongs to. */ id: number; /** Terminal columns this layout was computed for. */ termWidth: number; /** Computed terminal rows this entry occupies. */ rows: number; /** Total character count of the entry's content. */ chars: number; /** Rows of this entry that overflow above the viewport, 0 at top. */ overflowBefore: number; /** Rows of this entry that overflow below the viewport after clipping. */ overflowAfter: number; /** * `estimated` when the layout was seeded from a heuristic (before first * real measurement), `measured` after the actual ink component rendered. */ kind: 'estimated' | 'measured'; /** Version of the scoring function. Bump to invalidate stale caches. */ version: number; } /** * Snapshot for one session: map of entry id → layout data computed at a * specific terminal width. Persisted alongside the session so resumed * sessions restore accurate layout without remounting every entry. */ export interface LayoutSnapshot { /** Terminal columns at snapshot time. */ termWidth: number; /** Layout version — increment to force re-computation. */ version: number; /** Per-entry layout data. */ entries: Record; } /** Current layout computation version. Bump when the algorithm changes. */ export declare const LAYOUT_VERSION = 2; /** Default fallback row count for entries without computed layout. */ export declare const FALLBACK_ROWS = 3; /** * Count the number of terminal rows a multi-line string occupies when wrapped * at `width` columns. Empty strings produce 1 row. * * Pure — no allocations beyond the row accumulator. */ export declare function wrappedRows(text: string, width: number, maxRows?: number): number; /** * Count the raw characters (code points) in a string that contribute to * visible output. Strips ANSI escape sequences before counting. */ export declare function visibleChars(text: string): number; /** * Compute the exact terminal rows an entry occupies at the given terminal * width. This is the core of the layout engine — it mirrors what the Ink * component tree actually produces, but runs in O(1) and does not mount * React elements. */ export declare function computeEntryRows(kind: string, text: string, termWidth: number, meta?: { /** For 'tool' entries: hasBody (whether result body is expanded). */ hasBody?: boolean; /** For 'tool' entries: resultRenderMode. */ resultRenderMode?: 'simple' | 'extend'; /** For 'tool' entries: output preview byte length. */ outputBytes?: number; /** For 'banner' entries: whether to render full artwork. */ fullArtwork?: boolean; /** For 'tool-group': entry count in the group. */ groupCount?: number; /** For 'assistant': whether a next-steps panel is rendered. */ hasNextSteps?: boolean; /** For 'assistant' content: how many code blocks, approximate. */ codeBlockCount?: number; /** For 'memory-activation': how many memories were injected (proof rows). */ memoryInjectedCount?: number; /** For 'memory-activation': whether the searched-query line is rendered. */ memoryHasQuery?: boolean; }): number; /** * Count the total characters across all display-relevant fields of an entry. * Accounts for the primary text field as well as secondary fields (pasteContent, * output preview, detail strings) that contribute to visual length. */ export declare function computeEntryChars(kind: string, entry: { text?: string; [key: string]: unknown; }): number; /** * Compute a full EntryLayout for one entry. Pure — deterministic from inputs. */ export declare function computeLayout(id: number, kind: string, text: string, termWidth: number, meta?: Parameters[3]): EntryLayout; /** * Update overflow values for a list of layouts arranged in content order. * Each entry gets its `overflowBefore` (rows clipped above viewport) and * `overflowAfter` (rows clipped below) computed from the given viewport * window. * * Clip coordinates are in total-content rows. Layout array is in display order. */ export declare function computeOverflow(layouts: EntryLayout[], viewportTop: number, viewportBottom: number): EntryLayout[]; //# sourceMappingURL=layout-engine.d.ts.map