@linxiraos/pi-tui 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +18 -5
  2. package/dist/types/autocomplete.d.ts +116 -0
  3. package/dist/types/bracketed-paste.d.ts +51 -0
  4. package/dist/types/components/box.d.ts +31 -0
  5. package/dist/types/components/cancellable-loader.d.ts +21 -0
  6. package/dist/types/components/editor.d.ts +166 -0
  7. package/dist/types/components/image.d.ts +165 -0
  8. package/dist/types/components/input.d.ts +25 -0
  9. package/dist/types/components/loader.d.ts +25 -0
  10. package/dist/types/components/markdown.d.ts +92 -0
  11. package/dist/types/components/scroll-view.d.ts +62 -0
  12. package/dist/types/components/select-list.d.ts +69 -0
  13. package/dist/types/components/settings-list.d.ts +123 -0
  14. package/dist/types/components/spacer.d.ts +11 -0
  15. package/dist/types/components/tab-bar.d.ts +89 -0
  16. package/dist/types/components/text.d.ts +28 -0
  17. package/dist/types/components/truncated-text.d.ts +10 -0
  18. package/dist/types/deccara.d.ts +49 -0
  19. package/dist/types/desktop-notify.d.ts +52 -0
  20. package/dist/types/editor-component.d.ts +38 -0
  21. package/dist/types/fuzzy.d.ts +48 -0
  22. package/dist/types/index.d.ts +32 -0
  23. package/dist/types/keybindings.d.ts +197 -0
  24. package/dist/types/keys.d.ts +210 -0
  25. package/dist/types/kill-ring.d.ts +20 -0
  26. package/dist/types/kitty-graphics.d.ts +76 -0
  27. package/dist/types/latex-block.d.ts +8 -0
  28. package/dist/types/latex-to-unicode.d.ts +50 -0
  29. package/dist/types/loop-watchdog.d.ts +49 -0
  30. package/dist/types/mouse.d.ts +67 -0
  31. package/dist/types/stdin-buffer.d.ts +60 -0
  32. package/dist/types/symbols.d.ts +25 -0
  33. package/dist/types/terminal-capabilities.d.ts +324 -0
  34. package/dist/types/terminal.d.ts +175 -0
  35. package/dist/types/tmux.d.ts +6 -0
  36. package/dist/types/ttyid.d.ts +9 -0
  37. package/dist/types/tui.d.ts +480 -0
  38. package/dist/types/utils.d.ts +112 -0
  39. package/package.json +70 -69
  40. package/src/keys.ts +1 -1
  41. package/src/loop-watchdog.ts +32 -6
  42. package/src/terminal.ts +15 -8
  43. package/src/tui.ts +70 -16
@@ -0,0 +1,49 @@
1
+ export interface LoopWatchdogOptions {
2
+ /** How far ahead each probe tick is scheduled, in ms. Default 250. */
3
+ intervalMs?: number;
4
+ /** A tick later than this past its deadline counts as a block. Default 250. */
5
+ thresholdMs?: number;
6
+ /** Overshoot beyond this is suppressed only when the process burned negligible CPU. Default 60_000. */
7
+ sleepMs?: number;
8
+ /** Monotonic clock source; injectable for tests. Default `performance.now`. */
9
+ now?: () => number;
10
+ /** Process CPU time in ms; injectable for tests. Default `process.cpuUsage`. */
11
+ cpuNow?: () => number;
12
+ /** Timer source; injectable for tests. Default `setTimeout`. */
13
+ schedule?: (cb: () => void, ms: number) => LoopWatchdogTimer;
14
+ }
15
+ /**
16
+ * Timer handle the watchdog arms. `cancel`, when present, is invoked on stop()
17
+ * so a stopped watchdog leaves no armed timer to wake the loop even once.
18
+ */
19
+ interface LoopWatchdogTimer {
20
+ unref?(): void;
21
+ cancel?(): void;
22
+ }
23
+ /**
24
+ * Always-on event-loop lag probe. Each tick is scheduled `intervalMs` ahead of
25
+ * a recorded deadline; a tick that fires `thresholdMs` past its deadline means
26
+ * the loop was blocked that long. The overshoot is logged once on the rising
27
+ * edge (one block ⇒ one line, deduped via `#wasBlocked`), tagged with the phase
28
+ * active during the elapsed interval via {@link takeRecentLoopPhase} — which
29
+ * survives the synchronous push/pop the instrumented hot paths do before this
30
+ * delayed tick can run — so the stall names its cause instead of "unknown".
31
+ *
32
+ * The handle is `unref`'d so the probe never keeps the process alive, and stop()
33
+ * cancels the armed timer when the handle exposes `cancel` (the default
34
+ * `setTimeout` handle does, via `clearTimeout`). The `#generation` guard remains
35
+ * as a fallback for injected handles that cannot cancel.
36
+ *
37
+ * A long overshoot is classified by CPU time rather than by duration. System
38
+ * sleep and a CPU-bound wedge both produce an arbitrarily large gap, so duration
39
+ * alone cannot tell them apart, and suppressing on duration discards exactly the
40
+ * worst stalls. Only a gap the process spent negligible CPU on is treated as
41
+ * sleep. CPU accounting is process-wide, so worker activity errs toward logging.
42
+ */
43
+ export declare class LoopWatchdog {
44
+ #private;
45
+ constructor(options?: LoopWatchdogOptions);
46
+ start(): void;
47
+ stop(): void;
48
+ }
49
+ export {};
@@ -0,0 +1,67 @@
1
+ /**
2
+ * SGR mouse report parsing (`\x1b[<button;col;rowM` / `…m`).
3
+ *
4
+ * Mouse tracking is enabled only while a fullscreen overlay holds the
5
+ * alternate screen (see tui.ts MOUSE_TRACKING_ON), so consumers are
6
+ * fullscreen components hit-testing against their own rendered frame:
7
+ * the frame paints from screen row 0, hence `row`/`col` are exposed
8
+ * 0-based for direct indexing into rendered lines.
9
+ */
10
+ /** A decoded SGR mouse report. */
11
+ export interface SgrMouseEvent {
12
+ /** Raw button code (bit 32 = motion, bit 64 = wheel, low bits = button). */
13
+ button: number;
14
+ /** 0-based column of the event. */
15
+ col: number;
16
+ /** 0-based row of the event. */
17
+ row: number;
18
+ /** True for a release report (`m` suffix). */
19
+ release: boolean;
20
+ /** Wheel direction: -1 up, 1 down, null when not a wheel event. */
21
+ wheel: -1 | 1 | null;
22
+ /** True when the pointer moved (hover or drag) rather than clicked. */
23
+ motion: boolean;
24
+ /** True for a left-button press (not motion, not release, not wheel). */
25
+ leftClick: boolean;
26
+ }
27
+ /**
28
+ * Decode an SGR mouse report, or return null when `data` is not one.
29
+ * Callers on hot keypress paths should pre-check `data.startsWith("\x1b[<")`
30
+ * before paying for the regex.
31
+ */
32
+ export declare function parseSgrMouse(data: string): SgrMouseEvent | null;
33
+ /** Handler invoked with a decoded SGR event; returning `false` reports unhandled. */
34
+ export type SgrMouseHandler = (event: SgrMouseEvent) => boolean | undefined;
35
+ /**
36
+ * Decode an SGR mouse report and forward it to `handler`. Returns `false` when
37
+ * `data` is not an SGR mouse report (or fails to parse), so callers can fall
38
+ * through to other input handling. Centralizes the repeated
39
+ * `data.startsWith("\x1b[<")` + `parseSgrMouse()` pattern.
40
+ */
41
+ export declare function routeSgrMouseInput(data: string, handler: SgrMouseHandler): boolean;
42
+ /**
43
+ * Structural view of a SelectList-like target for mouse routing. Declared here
44
+ * (rather than importing the component) to keep this core module free of any
45
+ * component-to-core import cycle.
46
+ */
47
+ export interface SelectListMouseTarget {
48
+ handleWheel(delta: -1 | 1): void;
49
+ hitTest(line: number): number | undefined;
50
+ setHoverIndex(index: number | null): void;
51
+ clickItem(index: number): void;
52
+ }
53
+ /**
54
+ * Route a decoded mouse event against a SelectList-like target at the given
55
+ * 0-based frame-local `line`. Centralizes the repeated wheel/hit-test/hover/
56
+ * click pattern. Returns `true` when the event was consumed.
57
+ */
58
+ export declare function routeSelectListMouse(target: SelectListMouseTarget, event: SgrMouseEvent, line: number): boolean;
59
+ /**
60
+ * Implemented by components that accept routed mouse events at frame-local
61
+ * coordinates. Hosts translate screen coordinates to the component's own
62
+ * rendered lines before forwarding.
63
+ */
64
+ export interface MouseRoutable {
65
+ /** `line`/`col` are 0-based within the component's rendered output. */
66
+ routeMouse(event: SgrMouseEvent, line: number, col: number): void;
67
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * StdinBuffer buffers input and emits complete sequences.
3
+ *
4
+ * This is necessary because stdin data events can arrive in partial chunks,
5
+ * especially for escape sequences like mouse events. Without buffering,
6
+ * partial sequences can be misinterpreted as regular keypresses.
7
+ *
8
+ * For example, the mouse SGR sequence `\x1b[<35;20;5m` might arrive as:
9
+ * - Event 1: `\x1b`
10
+ * - Event 2: `[<35`
11
+ * - Event 3: `;20;5m`
12
+ *
13
+ * The buffer accumulates these until a complete sequence is detected.
14
+ * Call the `process()` method to feed input data.
15
+ *
16
+ * Based on code from OpenTUI (https://github.com/anomalyco/opentui)
17
+ * MIT License - Copyright (c) 2025 opentui
18
+ */
19
+ import { EventEmitter } from "events";
20
+ export type StdinBufferOptions = {
21
+ /**
22
+ * Maximum time to wait for sequence completion (default: 75ms).
23
+ * After this time, a genuinely incomplete escape is flushed.
24
+ */
25
+ timeout?: number;
26
+ /**
27
+ * Maximum extra time (default: 150ms) an unambiguous escape partial — an
28
+ * SGR mouse prefix, or any dangling escape while the kitty keyboard
29
+ * protocol is active — is held past `timeout` waiting for its tail.
30
+ */
31
+ partialHoldTimeout?: number;
32
+ /**
33
+ * Paste-mode inactivity watchdog (default: 1000ms). If no input arrives for
34
+ * this long while waiting for the bracketed-paste end marker, the paste is
35
+ * assumed truncated: accumulated bytes are delivered and input recovers.
36
+ */
37
+ pasteTimeout?: number;
38
+ /**
39
+ * Paste-mode byte cap (default: 64 MiB). Exceeding it aborts paste mode the
40
+ * same way, bounding memory when the end marker never arrives.
41
+ */
42
+ pasteByteLimit?: number;
43
+ };
44
+ export type StdinBufferEventMap = {
45
+ data: [string];
46
+ paste: [string];
47
+ };
48
+ /**
49
+ * Buffers stdin input and emits complete sequences via the 'data' event.
50
+ * Handles partial escape sequences that arrive across multiple chunks.
51
+ */
52
+ export declare class StdinBuffer extends EventEmitter<StdinBufferEventMap> {
53
+ #private;
54
+ constructor(options?: StdinBufferOptions);
55
+ process(data: string | Buffer): void;
56
+ flush(): string[];
57
+ clear(): void;
58
+ getBuffer(): string;
59
+ destroy(): void;
60
+ }
@@ -0,0 +1,25 @@
1
+ export interface BoxSymbols {
2
+ topLeft: string;
3
+ topRight: string;
4
+ bottomLeft: string;
5
+ bottomRight: string;
6
+ horizontal: string;
7
+ vertical: string;
8
+ teeDown: string;
9
+ teeUp: string;
10
+ teeLeft: string;
11
+ teeRight: string;
12
+ cross: string;
13
+ }
14
+ export interface SymbolTheme {
15
+ cursor: string;
16
+ inputCursor: string;
17
+ boxRound: Omit<BoxSymbols, "teeDown" | "teeUp" | "teeLeft" | "teeRight" | "cross">;
18
+ boxSharp: BoxSymbols;
19
+ table: BoxSymbols;
20
+ quoteBorder: string;
21
+ hrChar: string;
22
+ /** Chip glyph drawn (painted with the referenced color) before inline hex colors. */
23
+ colorSwatch?: string;
24
+ spinnerFrames: string[];
25
+ }
@@ -0,0 +1,324 @@
1
+ import type { HangulCompatibilityJamoWidth } from "./utils.js";
2
+ export { isInsideTmux, wrapTmuxPassthrough } from "./tmux.js";
3
+ export declare enum ImageProtocol {
4
+ Kitty = "\u001B_G",
5
+ Iterm2 = "\u001B]1337;File=",
6
+ Sixel = "\u001BPq"
7
+ }
8
+ export declare enum NotifyProtocol {
9
+ Bell = "\u0007",
10
+ Osc99 = "\u001B]99;;",
11
+ Osc9 = "\u001B]9;"
12
+ }
13
+ export type TerminalId = "kitty" | "ghostty" | "wezterm" | "iterm2" | "vscode" | "alacritty" | "warp" | "base" | "trueColor";
14
+ /** Terminal capability details used for rendering and protocol selection. */
15
+ export declare class TerminalInfo {
16
+ readonly id: TerminalId;
17
+ readonly imageProtocol: ImageProtocol | null;
18
+ readonly trueColor: boolean;
19
+ readonly hyperlinks: boolean;
20
+ readonly notifyProtocol: NotifyProtocol;
21
+ readonly deccara: boolean;
22
+ readonly supportsScreenToScrollback: boolean;
23
+ /** Renders the Kitty OSC 66 text-sizing protocol (scaled spans). Kitty only. */
24
+ readonly textSizing: boolean;
25
+ /**
26
+ * Hangul Compatibility Jamo (U+3131..=U+318E) cell width. Ghostty follows
27
+ * UAX#11 (2 cells); Warp paints 1; "platform" keeps the OS default
28
+ * (macOS narrow, otherwise UAX#11).
29
+ */
30
+ readonly hangulJamoWidth: HangulCompatibilityJamoWidth;
31
+ constructor(id: TerminalId, imageProtocol: ImageProtocol | null, trueColor: boolean, hyperlinks: boolean, notifyProtocol?: NotifyProtocol, deccara?: boolean, supportsScreenToScrollback?: boolean,
32
+ /** Renders the Kitty OSC 66 text-sizing protocol (scaled spans). Kitty only. */
33
+ textSizing?: boolean,
34
+ /**
35
+ * Hangul Compatibility Jamo (U+3131..=U+318E) cell width. Ghostty follows
36
+ * UAX#11 (2 cells); Warp paints 1; "platform" keeps the OS default
37
+ * (macOS narrow, otherwise UAX#11).
38
+ */
39
+ hangulJamoWidth?: HangulCompatibilityJamoWidth);
40
+ /**
41
+ * Mutable clone for the {@link TERMINAL} singleton: copies every field and
42
+ * keeps the prototype methods, so the builder and runtime setters flip
43
+ * runtime-resolved {@link RuntimeTerminal} capabilities in place instead of
44
+ * reconstructing positional constructor args.
45
+ */
46
+ clone(): RuntimeTerminal;
47
+ isImageLine(line: string): boolean;
48
+ formatNotification(message: string | TerminalNotification): string;
49
+ sendNotification(message: string | TerminalNotification): void;
50
+ }
51
+ /** Detect terminal multiplexers where scrollback clearing and height-change redraws are hostile. */
52
+ export declare function isInsideTerminalMultiplexer(env?: NodeJS.ProcessEnv): boolean;
53
+ /**
54
+ * Whether the agent process is running inside a Zellij session. Read fresh on
55
+ * each call (like {@link isInsideTmux}) so a session attached/detached mid-run
56
+ * is observed and tests can toggle `Bun.env.ZELLIJ` per case.
57
+ */
58
+ export declare function isInsideZellij(env?: NodeJS.ProcessEnv): boolean;
59
+ export declare function isNotificationSuppressed(): boolean;
60
+ /**
61
+ * Returns true when running in Windows Terminal with known SIXEL support.
62
+ *
63
+ * Windows Terminal introduced SIXEL support in preview 1.22.
64
+ */
65
+ export declare function isWindowsTerminalPreviewSixelSupported(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): boolean;
66
+ /**
67
+ * Resolve an explicit user override for DEC 2026 synchronized output. Returns
68
+ * `false` for an opt-out, `true` for a force-on, or `null` when the user has
69
+ * expressed no preference. Shared by the static default and the runtime DECRQM
70
+ * probe so both honor the same precedence — an opt-out beats a force-on.
71
+ */
72
+ export declare function synchronizedOutputUserOverride(env?: NodeJS.ProcessEnv): boolean | null;
73
+ /**
74
+ * Whether DEC 2026 synchronized-output wrappers should be enabled by default.
75
+ *
76
+ * Policy (highest precedence first):
77
+ * 1. Explicit user override (`PI_NO_SYNC_OUTPUT`/`PI_TUI_SYNC_OUTPUT=0` off,
78
+ * `PI_FORCE_SYNC_OUTPUT=1`/`PI_TUI_SYNC_OUTPUT=1` on).
79
+ * 2. Positive `TERM_FEATURES` advertisement (`Sy`) — survives SSH/mux wrapping.
80
+ * 3. Windows Terminal (1.24+) via `WT_SESSION`, on native win32 and the
81
+ * WSL/SSH-fronted host alike.
82
+ * 4. Known direct terminals with confirmed support. SSH does *not* disable —
83
+ * DEC 2026 passes through SSH when the outer terminal honors it.
84
+ * 5. Everything else starts off, including risky multiplexers; the runtime
85
+ * DECRQM probe upgrades any of them when the terminal actually reports
86
+ * `?2026` supported (current zellij, tmux master, foot, contour, mintty…).
87
+ */
88
+ export declare function shouldEnableSynchronizedOutputByDefault(env?: NodeJS.ProcessEnv, terminalId?: TerminalId): boolean;
89
+ /**
90
+ * Whether the terminal applies Kitty-style DECCARA rectangular SGR changes
91
+ * (`CSI Pt ; Pl ; Pb ; Pr ; <sgr> $ r`) extended to background color, so large
92
+ * filled regions can be painted as rectangles instead of background-padded
93
+ * strings on every row.
94
+ *
95
+ * Verified against terminal sources rather than terminfo, because a bare
96
+ * `Cara`/DECCARA terminfo capability does not imply the Kitty SGR-background
97
+ * extension:
98
+ * - Kitty implements it for *all* SGR attributes including background (see
99
+ * kitty `docs/deccara.rst` and the `test_deccara` parser test).
100
+ * - Ghostty does NOT: its `CSI $ r` dispatch falls through to an "unknown CSI"
101
+ * warning and DECCARA/DECSACE are tracked as unsupported
102
+ * (ghostty-org/ghostty#632). Enabling it there would silently drop panel
103
+ * backgrounds, so ghostty stays on the padded-string fallback.
104
+ *
105
+ * Disabled under tmux/screen/zellij multiplexers — screen-coordinate rectangle
106
+ * protocols are not safe to assume through a multiplexer — and via the
107
+ * `PI_NO_DECCARA` kill switch. Pure helper for tests and `TERMINAL` construction.
108
+ */
109
+ export declare function detectRectangularSgrSupport(terminalId: TerminalId, env?: NodeJS.ProcessEnv): boolean;
110
+ /**
111
+ * Resolve an explicit user override for OSC 8 hyperlinks. Returns `false` for
112
+ * an opt-out, `true` for a force-on, or `null` when the user has expressed no
113
+ * preference. Opt-out beats force-on so a kill switch is unambiguous, mirroring
114
+ * {@link synchronizedOutputUserOverride}.
115
+ */
116
+ export declare function hyperlinksUserOverride(env?: NodeJS.ProcessEnv): boolean | null;
117
+ /**
118
+ * Whether OSC 8 hyperlinks should be enabled by default.
119
+ *
120
+ * Policy (highest precedence first):
121
+ * 1. Explicit user override (`PI_NO_HYPERLINKS=1` off, `PI_FORCE_HYPERLINKS=1`
122
+ * on). Opt-out wins ties.
123
+ * 2. Static terminal capability — terminals whose {@link TerminalInfo} marks
124
+ * `hyperlinks: false` (e.g. `base`) stay off unless the user forced on.
125
+ * 3. GNU screen's explicit session marker (`STY`) always off, even if tmux is
126
+ * also present: a screen layer anywhere in the path cannot forward OSC 8.
127
+ * 4. tmux session (`TMUX` set): enabled when tmux self-reports >= 3.4 via
128
+ * `TERM_PROGRAM_VERSION` (tmux 3.4 stores OSC 8 as a cell attribute and
129
+ * forwards it to outer terminals whose `terminal-features` include
130
+ * `hyperlinks`). Older or unknown versions stay off; on outer terminals
131
+ * without the feature configured, tmux silently drops the sequence —
132
+ * identical to today. Checked before the screen-family TERM heuristic
133
+ * because tmux's historical `default-terminal` is `screen-256color`, so
134
+ * `TERM=screen*` inside a tmux session must NOT short-circuit to off.
135
+ * 5. screen-family TERM without `TMUX` always off: screen never gained OSC 8
136
+ * support.
137
+ * 6. tmux-family TERM without `TMUX` env — unusual (e.g. inspection scripts);
138
+ * no version available, so off.
139
+ * 7. Otherwise honor the static terminal capability.
140
+ */
141
+ export declare function shouldEnableHyperlinksByDefault(env?: NodeJS.ProcessEnv, terminalId?: TerminalId): boolean;
142
+ /**
143
+ * Warp implements the Kitty graphics protocol only on macOS/Linux; its Windows
144
+ * build (including Warp-hosted WSL shells) renders the same APC sequences as
145
+ * visible garbage. Keep platform/env injectable so the carve-out is testable
146
+ * without mutating `process.platform`.
147
+ */
148
+ export declare function resolveWarpImageProtocol(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): ImageProtocol | null;
149
+ /** Resolve terminal identity from environment markers used by common emulators. */
150
+ export declare function detectTerminalId(env?: NodeJS.ProcessEnv): TerminalId;
151
+ export declare const TERMINAL_ID: TerminalId;
152
+ /**
153
+ * The process-wide {@link TERMINAL} singleton: a {@link TerminalInfo} whose
154
+ * post-construction capabilities — the image protocol and the probe-driven
155
+ * flags — are writable, so the runtime setters and tests mutate them directly
156
+ * instead of through an unsound cast. Every other field stays readonly.
157
+ */
158
+ export interface RuntimeTerminal extends TerminalInfo {
159
+ imageProtocol: ImageProtocol | null;
160
+ hyperlinks: boolean;
161
+ deccara: boolean;
162
+ supportsScreenToScrollback: boolean;
163
+ textSizing: boolean;
164
+ }
165
+ export declare const TERMINAL: RuntimeTerminal;
166
+ /**
167
+ * Override terminal image protocol at runtime after capability probes complete.
168
+ */
169
+ export declare function setTerminalImageProtocol(imageProtocol: ImageProtocol | null): void;
170
+ /**
171
+ * Override DECCARA rectangular-SGR capability at runtime. Used by tests to
172
+ * exercise the optimizer and fallback paths deterministically — the default is
173
+ * resolved once at import and force-disabled under the test runtime.
174
+ */
175
+ export declare function setTerminalDeccara(enabled: boolean): void;
176
+ /** Override screen-to-scrollback clear support for targeted renderer tests. */
177
+ export declare function setTerminalScreenToScrollback(enabled: boolean): void;
178
+ /**
179
+ * Enable/disable OSC 66 text-sizing at runtime. The coding-agent calls this from
180
+ * the `tui.textSizing` setting (gated on the terminal's static `textSizing`
181
+ * capability); tests flip it directly to exercise the scaled-heading path.
182
+ */
183
+ export declare function setTerminalTextSizing(enabled: boolean): void;
184
+ export declare function getTerminalInfo(terminalId: TerminalId, platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): TerminalInfo;
185
+ export interface CellDimensions {
186
+ widthPx: number;
187
+ heightPx: number;
188
+ }
189
+ export interface ImageDimensions {
190
+ widthPx: number;
191
+ heightPx: number;
192
+ }
193
+ export interface ImageRenderOptions {
194
+ maxWidthCells?: number;
195
+ maxHeightCells?: number;
196
+ preserveAspectRatio?: boolean;
197
+ /**
198
+ * Stable Kitty image id (`i=`). When set, the image is displayed via a
199
+ * transmit-once + placement scheme keyed off this id instead of re-sending the
200
+ * base64 each frame.
201
+ */
202
+ imageId?: number;
203
+ /** Stable Kitty placement id (`p=`); defaults to {@link imageId}. */
204
+ placementId?: number;
205
+ /** When true (Kitty + {@link imageId}), also return the one-time transmit sequence. */
206
+ includeTransmit?: boolean;
207
+ }
208
+ export declare function getCellDimensions(): CellDimensions;
209
+ export declare function setCellDimensions(dims: CellDimensions): void;
210
+ /** Transmit-and-display (`a=T`) — the self-contained form used when no stable id is available. */
211
+ export declare function encodeKitty(base64Data: string, options?: {
212
+ columns?: number;
213
+ rows?: number;
214
+ imageId?: number;
215
+ }): string;
216
+ /**
217
+ * Transmit image data only (`a=t`), keyed by `imageId`, without displaying it.
218
+ * Sent once per image; the data then persists in the terminal's store (it
219
+ * survives scroll-off and text clears for images with a non-zero id), so
220
+ * subsequent frames display it with the tiny {@link encodeKittyPlacement}
221
+ * sequence instead of re-sending the base64.
222
+ */
223
+ export declare function encodeKittyTransmit(base64Data: string, imageId: number): string;
224
+ /**
225
+ * Display a previously transmitted image (`a=p`) at the cursor. `C=1` keeps
226
+ * the terminal cursor anchored at the placement origin so the renderer's
227
+ * explicit cursor movement remains the only row accounting. Carrying a stable
228
+ * `placementId` (`p=`) means re-emitting the sequence on a repaint *replaces*
229
+ * the existing placement (moving/resizing it without flicker) rather than
230
+ * stacking a duplicate.
231
+ */
232
+ export declare function encodeKittyPlacement(options: {
233
+ imageId: number;
234
+ placementId?: number;
235
+ columns?: number;
236
+ rows?: number;
237
+ }): string;
238
+ export interface ParsedKittyPlacementLine {
239
+ imageId: number;
240
+ placementId: number | undefined;
241
+ columns: number;
242
+ rows: number;
243
+ }
244
+ /**
245
+ * Parse a frame line that consists solely of a Kitty direct placement (the
246
+ * last line of an {@link Image} block). Returns null for anything else —
247
+ * placeholder grids, tmux-wrapped placements, sixel/iTerm2 payloads — so
248
+ * callers fall back to writing the line verbatim.
249
+ */
250
+ export declare function parseKittyDirectPlacementLine(line: string): ParsedKittyPlacementLine | null;
251
+ /**
252
+ * Rebuild an {@link Image} direct-placement line for the viewport row it is
253
+ * written at. The component-rendered line encodes `CUU(rows-1)`, which clamps
254
+ * at the viewport top once the block's leading rows have scrolled out — the
255
+ * placement then re-anchors the full image shifted down over foreign rows.
256
+ * Anchor at the block's first *visible* row instead, clipping the source
257
+ * rectangle (`y=`/`h=`, image pixels) to the visible bottom slice.
258
+ */
259
+ export declare function encodeKittyPlacementLine(options: {
260
+ imageId: number;
261
+ placementId: number;
262
+ columns: number;
263
+ /** Total cell rows of the image block. */
264
+ rows: number;
265
+ /** Viewport row the block's last line is being written at. */
266
+ screenRow: number;
267
+ /** Source image height in pixels, for the clipped source rectangle. */
268
+ imageHeightPx: number;
269
+ }): string;
270
+ /**
271
+ * Kitty graphics delete command for a single image id. Uses `d=I` (capital)
272
+ * which removes the image and every one of its placements — on screen *and* in
273
+ * scrollback — and frees the backing data. `q=2` suppresses the terminal reply.
274
+ * Text-clearing escapes (`CSI 2 J` / `CSI 3 J`) do not remove Kitty graphics, so
275
+ * this is the only way to actually purge a placed image.
276
+ */
277
+ export declare function encodeKittyDeleteImage(imageId: number): string;
278
+ /**
279
+ * Delete a single placement of an image (`d=i`, lowercase): removes its cells
280
+ * and registry entry but keeps the transmitted data, so a later `a=p` under a
281
+ * fresh placement id needs no retransmit. Used to clear stale placement-epoch
282
+ * entries after a destructive history clear.
283
+ */
284
+ export declare function encodeKittyDeletePlacement(imageId: number, placementId: number): string;
285
+ export declare function encodeITerm2(base64Data: string, options?: {
286
+ width?: number | string;
287
+ height?: number | string;
288
+ name?: string;
289
+ preserveAspectRatio?: boolean;
290
+ inline?: boolean;
291
+ }): string;
292
+ export declare function calculateImageRows(imageDimensions: ImageDimensions, targetWidthCells: number, cellDimensions?: CellDimensions): number;
293
+ export declare function getPngDimensions(base64Data: string): ImageDimensions | null;
294
+ export declare function getJpegDimensions(base64Data: string): ImageDimensions | null;
295
+ export declare function getGifDimensions(base64Data: string): ImageDimensions | null;
296
+ export declare function getWebpDimensions(base64Data: string): ImageDimensions | null;
297
+ export declare function getImageDimensions(base64Data: string, mimeType: string): ImageDimensions | null;
298
+ export declare function renderImage(base64Data: string, imageDimensions: ImageDimensions, options?: ImageRenderOptions): {
299
+ sequence?: string;
300
+ lines?: string[];
301
+ rows: number;
302
+ transmit?: string;
303
+ } | null;
304
+ export declare function imageFallback(mimeType: string, dimensions?: ImageDimensions, filename?: string): string;
305
+ /**
306
+ * Structured terminal notification. Rich fields are honored only by OSC 99
307
+ * (Kitty) once support is confirmed; other protocols and the unconfirmed Kitty
308
+ * path collapse to a single `title: body` line.
309
+ */
310
+ export interface TerminalNotification {
311
+ title?: string;
312
+ body?: string;
313
+ id?: string;
314
+ type?: string | string[];
315
+ urgency?: "low" | "normal" | "critical";
316
+ iconName?: string;
317
+ sound?: "silent" | "system" | "info" | "warning" | "error" | "question";
318
+ actions?: "focus" | "report" | "focus-report" | "none";
319
+ expiresMs?: number;
320
+ }
321
+ /** Record the OSC 99 capability-probe result (called by ProcessTerminal). */
322
+ export declare function setOsc99Supported(supported: boolean): void;
323
+ /** True when OSC 99 structured notifications have been confirmed available. */
324
+ export declare function isOsc99Supported(): boolean;