@gajae-code/tui 0.13.3 → 0.14.0
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.
- package/CHANGELOG.md +16 -0
- package/dist/types/components/gajae-pet.d.ts +86 -5
- package/dist/types/terminal-capabilities.d.ts +22 -0
- package/dist/types/terminal.d.ts +9 -0
- package/dist/types/tui.d.ts +122 -4
- package/package.json +3 -3
- package/src/components/gajae-pet.ts +381 -26
- package/src/terminal-capabilities.ts +137 -0
- package/src/terminal.ts +33 -0
- package/src/tui.ts +989 -106
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.14.0] - 2026-08-17
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- iTerm2 pet capability probes now wait for pending input without disabling Kitty keyboard mode, disabling `modifyOtherKeys`, or detaching the live input handler.
|
|
9
|
+
- iTerm2 Gajae Pet frames now carry a dedicated filename, so dragging one retains iTerm's native drag behavior while the coding agent can discard only the temporary pet pathname pasted back into its composer.
|
|
10
|
+
- iTerm2 Gajae Pet now uses one animated GIF upload per meaningful state change and a raster lease that excludes its cell rectangle from generic TUI redraw erases, eliminating animation flicker while preserving geometry-derived art placement and leaving Kitty and Sixel encoding unchanged.
|
|
11
|
+
|
|
12
|
+
- Layout-only animation and selector frames can now reuse an unchanged revisioned transcript subtree instead of rebuilding every off-screen transcript component, anchor row, and Kitty placement on each tick. Ordinary render requests remain conservative, and transcript revision, width, identity, and global invalidation changes still force a full subtree render.
|
|
13
|
+
|
|
14
|
+
- A fast double-Esc (or triple-Esc) whose ESC bytes coalesce into one stdin chunk — which tmux always produces within its escape-time window, and SSH batching produces routinely — is now emitted as individual Escape key presses instead of a single `"\x1b\x1b"` sequence that parsed as the unbound `alt+escape` and silently swallowed both presses. This restores the double-Esc draft-clear and double-Esc selector gestures under tmux/SSH. Option-as-Meta sequences with a real continuation (e.g. Option+Up as `ESC ESC [ A`) remain atomic, and an ESC-cancelled incomplete sequence is still emitted whole.
|
|
15
|
+
- An ambiguous trailing run of Escape bytes now stays buffered until a continuation or the flush timeout resolves it, so `ESC ESC ESC` followed by `[A` in the next chunk still decodes as Escape then `alt+up` instead of two Escapes plus a plain Up that fired the destructive double-Escape gesture.
|
|
16
|
+
- Escape presses immediately followed by a bracketed paste in the same read are now emitted as individual Escape presses instead of one coalesced sequence that parsed as the unbound `alt+escape` and swallowed every press.
|
|
17
|
+
- A long run of Escape bytes arriving as many small reads no longer rescans the accumulated buffer on every read; only the two-byte ambiguous tail stays buffered, so 50,000 byte-by-byte Escape reads cost 50ms instead of 2.4s.
|
|
18
|
+
- A long run of Escape bytes followed by another key now decodes in linear time instead of rescanning the remaining input on every step, which blocked the event loop for over a second on a 50,000-byte run.
|
|
19
|
+
- Apple Terminal.app now retains its default keyboard mode when it does not support the Kitty keyboard protocol, avoiding the modifyOtherKeys fallback that breaks Korean/Hangul IME composition.
|
|
20
|
+
|
|
5
21
|
## [0.13.3] - 2026-08-15
|
|
6
22
|
|
|
7
23
|
### Added
|
|
@@ -56,7 +56,8 @@ export declare function resolvePetMode(value: string): PetMode;
|
|
|
56
56
|
export type GajaePixelFrameName = "base" | "gazeL" | "gazeR" | "flicker" | "flex" | "danceL" | "danceR" | "cry1" | "cry2" | "cry3";
|
|
57
57
|
export type PetFrameName = GajaePixelFrameName | OuroborosFrameName;
|
|
58
58
|
/** Para-para work dance beats: the working loop and each skin's burst "work-in" intro. */
|
|
59
|
-
export
|
|
59
|
+
export type GajaeGifFrameTuple = readonly [GajaePixelFrameName, number];
|
|
60
|
+
export declare const PARA_PARA_STEPS: readonly GajaeGifFrameTuple[];
|
|
60
61
|
export declare const GAJAE_IDLE_STEPS: ReadonlyArray<readonly [GajaePixelFrameName, number]>;
|
|
61
62
|
/**
|
|
62
63
|
* A skin's idle burst: a short intro sequence, then an optional looping tail. It drives
|
|
@@ -102,10 +103,77 @@ export declare function petBurstFrame(burst: PetBurst, elapsed: number, now: num
|
|
|
102
103
|
export declare const __gajaePetTestHooks: {
|
|
103
104
|
getPixelGrid(name: PetFrameName, skin?: PetSkinId): string[];
|
|
104
105
|
};
|
|
106
|
+
export interface GajaeGifFrame {
|
|
107
|
+
readonly name: PetFrameName;
|
|
108
|
+
readonly delayMs: number;
|
|
109
|
+
}
|
|
110
|
+
export type GajaeGifTimeline = readonly GajaeGifFrame[];
|
|
111
|
+
export interface GajaeGifRectangle {
|
|
112
|
+
readonly width?: number;
|
|
113
|
+
readonly height?: number;
|
|
114
|
+
}
|
|
115
|
+
export interface GajaeGifDisplaySize {
|
|
116
|
+
/** iTerm2 display width: bare numbers are terminal cells; strings may use px or auto. */
|
|
117
|
+
readonly width: number | string;
|
|
118
|
+
/** iTerm2 display height: bare numbers are terminal cells; strings may use px or auto. */
|
|
119
|
+
readonly height: number | string;
|
|
120
|
+
}
|
|
121
|
+
export interface GajaeGifContentInset {
|
|
122
|
+
/** Transparent top padding in source pixels. */
|
|
123
|
+
readonly topPx?: number;
|
|
124
|
+
/** Transparent bottom padding in source pixels. */
|
|
125
|
+
readonly bottomPx?: number;
|
|
126
|
+
}
|
|
127
|
+
export interface GajaePetGifArtifact {
|
|
128
|
+
readonly bytes: Uint8Array;
|
|
129
|
+
readonly base64: string;
|
|
130
|
+
readonly width: number;
|
|
131
|
+
readonly height: number;
|
|
132
|
+
readonly frames: readonly GajaeGifFrame[];
|
|
133
|
+
readonly skin: PetSkinId;
|
|
134
|
+
readonly multipart: readonly string[];
|
|
135
|
+
readonly tmuxDcs: readonly string[];
|
|
136
|
+
}
|
|
137
|
+
export interface GajaePetGifOptions {
|
|
138
|
+
readonly skin?: PetSkinId;
|
|
139
|
+
readonly timeline?: GajaeGifTimeline;
|
|
140
|
+
readonly cellWidthPx?: number;
|
|
141
|
+
readonly cellHeightPx?: number;
|
|
142
|
+
readonly targetRows?: number;
|
|
143
|
+
readonly rectangle?: GajaeGifRectangle;
|
|
144
|
+
readonly displaySize?: GajaeGifDisplaySize;
|
|
145
|
+
readonly contentInset?: GajaeGifContentInset;
|
|
146
|
+
}
|
|
147
|
+
export declare const idleTimeline: () => GajaeGifTimeline;
|
|
148
|
+
export declare const workingTimeline: () => GajaeGifTimeline;
|
|
149
|
+
export declare const burstTimeline: (skin?: PetSkinId) => GajaeGifTimeline;
|
|
150
|
+
export declare const previewTimeline: (skin?: PetSkinId) => GajaeGifTimeline;
|
|
151
|
+
export declare function encodeGajaePetGif(input?: GajaePetGifOptions | GajaeGifTimeline): GajaePetGifArtifact;
|
|
152
|
+
export declare function getGajaePetGifCached(input?: GajaePetGifOptions | GajaeGifTimeline): GajaePetGifArtifact;
|
|
153
|
+
export declare function getGajaePetGifCacheStats(): {
|
|
154
|
+
size: number;
|
|
155
|
+
bytes: number;
|
|
156
|
+
gifBytes: number;
|
|
157
|
+
base64Bytes: number;
|
|
158
|
+
multipartBytes: number;
|
|
159
|
+
tmuxDcsBytes: number;
|
|
160
|
+
evictions: number;
|
|
161
|
+
};
|
|
162
|
+
export declare function resetGajaePetGifCache(): void;
|
|
163
|
+
export declare const clearGajaePetGifCache: typeof resetGajaePetGifCache;
|
|
105
164
|
/** Encode a grid as a transparent SIXEL image, optionally bottom-aligned by top padding. */
|
|
106
165
|
export declare function encodeGridSixel(grid: string[], scale: number, topPaddingPx?: number, palette?: Palette): string;
|
|
107
|
-
/**
|
|
108
|
-
|
|
166
|
+
/**
|
|
167
|
+
* Encode a grid as an iTerm2 inline PNG spanning a terminal cell block.
|
|
168
|
+
*
|
|
169
|
+
* The escape's `width`/`height` are the reserved cell-block footprint in
|
|
170
|
+
* character cells (unitless numbers per the iTerm2 inline-images protocol).
|
|
171
|
+
* iTerm2 resolves cells against its own live font metrics, so the sprite
|
|
172
|
+
* scales with the real terminal geometry — including Retina, where iTerm2
|
|
173
|
+
* divides `Npx` values by the backing-scale factor and would render a fixed
|
|
174
|
+
* pixel box at half size.
|
|
175
|
+
*/
|
|
176
|
+
export declare function encodeGridIterm2(grid: string[], scale: number, columns: number, rows: number, topPaddingPx?: number, bottomPaddingPx?: number, leftPaddingPx?: number, rightPaddingPx?: number, palette?: Palette): string;
|
|
109
177
|
/** Encode a bottom-aligned grid as kitty raw RGBA at `scale`. */
|
|
110
178
|
export declare function encodeGridKitty(grid: string[], scale: number, imageId: number, cols: number, rows: number, topPaddingPx?: number, cellYOffsetPx?: number, leftPaddingPx?: number, rightPaddingPx?: number, palette?: Palette): string;
|
|
111
179
|
export interface GajaePixelFrames {
|
|
@@ -113,7 +181,9 @@ export interface GajaePixelFrames {
|
|
|
113
181
|
frames: Record<string, string>;
|
|
114
182
|
/** protocol the frames were encoded for */
|
|
115
183
|
protocol: "sixel" | "kitty" | "iterm2";
|
|
184
|
+
/** Scaled sprite width before transparent cell-block padding. */
|
|
116
185
|
widthPx: number;
|
|
186
|
+
/** Encoded raster height, including protocol-specific transparent padding. */
|
|
117
187
|
heightPx: number;
|
|
118
188
|
columns: number;
|
|
119
189
|
rows: number;
|
|
@@ -124,6 +194,17 @@ export interface GajaePixelFrames {
|
|
|
124
194
|
* Build overlay pixel frames exactly `targetRows` terminal rows tall when the
|
|
125
195
|
* terminal cells permit it. Each skin owns its source resolution so future
|
|
126
196
|
* additions can opt into denser art without changing the terminal footprint.
|
|
197
|
+
*
|
|
198
|
+
* Geometry contract:
|
|
199
|
+
* - `scale = max(1, targetRows * cellHeightPx / gridHeight)`
|
|
200
|
+
* - `columns = ceil(scaledSpriteWidthPx / cellWidthPx)`
|
|
201
|
+
* - `rows = ceil(scaledSpriteHeightPx / cellHeightPx)`
|
|
202
|
+
* - the square sprite is centered in a `columns * cellWidthPx` PNG canvas
|
|
203
|
+
*
|
|
204
|
+
* iTerm2 receives unitless `width=columns;height=rasterRows`, so it resolves the
|
|
205
|
+
* padded block with its live cell metrics. The PNG has that block's pixel aspect
|
|
206
|
+
* ratio, allowing `preserveAspectRatio=0` without stretching the authored square
|
|
207
|
+
* sprite. Kitty and Sixel retain their protocol-specific paths.
|
|
127
208
|
*/
|
|
128
209
|
export declare function buildGajaePixelFrames(options: {
|
|
129
210
|
protocol: "sixel" | "kitty" | "iterm2";
|
|
@@ -135,9 +216,9 @@ export declare function buildGajaePixelFrames(options: {
|
|
|
135
216
|
/** Native sub-cell `Y=` pixel offset that drops the kitty sprite within its first cell. */
|
|
136
217
|
kittyCellYOffsetPx?: number;
|
|
137
218
|
kittyImageId?: number;
|
|
138
|
-
/**
|
|
219
|
+
/** Additional transparent iTerm2-only top padding for sub-cell vertical alignment. */
|
|
139
220
|
iterm2TopPaddingPx?: number;
|
|
140
|
-
/** Transparent iTerm2-only bottom padding inside the
|
|
221
|
+
/** Transparent iTerm2-only bottom padding inside the canvas. */
|
|
141
222
|
iterm2BottomPaddingPx?: number;
|
|
142
223
|
/** Color skin for the sprite palette (default "red"). */
|
|
143
224
|
skin?: PetSkinId;
|
|
@@ -195,4 +195,26 @@ export interface RenderedImage {
|
|
|
195
195
|
}
|
|
196
196
|
export declare function renderImage(base64Data: string, imageDimensions: ImageDimensions, options?: ImageRenderOptions): RenderedImage | null;
|
|
197
197
|
export declare function imageFallback(mimeType: string, dimensions?: ImageDimensions, filename?: string): string;
|
|
198
|
+
export type Iterm2Capability = {
|
|
199
|
+
readonly key: string;
|
|
200
|
+
readonly value: string;
|
|
201
|
+
};
|
|
202
|
+
export type Iterm2CapabilityReply = "complete-f" | "missing-f" | "invalid-f" | undefined;
|
|
203
|
+
/**
|
|
204
|
+
* Classifies complete iTerm2 capability replies. An absent result means the
|
|
205
|
+
* input does not yet contain a complete capability frame.
|
|
206
|
+
*/
|
|
207
|
+
export declare function parseITerm2CapabilityReply(input: Uint8Array | string): Iterm2CapabilityReply;
|
|
208
|
+
export declare function encodeITerm2Multipart(base64Data: string, options?: {
|
|
209
|
+
width?: number | string;
|
|
210
|
+
height?: number | string;
|
|
211
|
+
}): string[];
|
|
212
|
+
export declare function wrapITerm2RecordForTmux(record: string): string;
|
|
213
|
+
export declare function wrapITerm2RecordsForTmux(records: readonly string[]): string[];
|
|
214
|
+
export declare function parseITerm2Capabilities(input: string): Iterm2Capability[];
|
|
215
|
+
export declare class Iterm2CapabilitiesParser {
|
|
216
|
+
#private;
|
|
217
|
+
push(input: Uint8Array | string): Iterm2Capability[];
|
|
218
|
+
reset(): void;
|
|
219
|
+
}
|
|
198
220
|
export {};
|
package/dist/types/terminal.d.ts
CHANGED
|
@@ -45,6 +45,14 @@ export interface Terminal {
|
|
|
45
45
|
* @param idleMs - Exit early if no input arrives within this time (default: 50ms)
|
|
46
46
|
*/
|
|
47
47
|
drainInput(maxMs?: number, idleMs?: number): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Wait for pending stdin to go quiet without changing terminal protocols or
|
|
50
|
+
* the active input handler. Capability probes use this non-destructive drain;
|
|
51
|
+
* shutdown paths must continue using drainInput().
|
|
52
|
+
* @param maxMs - Maximum time to wait (default: 1000ms)
|
|
53
|
+
* @param idleMs - Exit early if no input arrives within this time (default: 50ms)
|
|
54
|
+
*/
|
|
55
|
+
drainPendingInput?(maxMs?: number, idleMs?: number): Promise<void>;
|
|
48
56
|
write(data: string): void;
|
|
49
57
|
get available(): boolean;
|
|
50
58
|
readonly isProcessTerminal?: boolean;
|
|
@@ -90,6 +98,7 @@ export declare class ProcessTerminal implements Terminal {
|
|
|
90
98
|
onAppearanceChange(callback: (appearance: TerminalAppearance) => void): void;
|
|
91
99
|
setMouseEnabled(enabled: boolean): void;
|
|
92
100
|
start(onInput: (data: string) => void, onResize: () => void): void;
|
|
101
|
+
drainPendingInput(maxMs?: number, idleMs?: number): Promise<void>;
|
|
93
102
|
drainInput(maxMs?: number, idleMs?: number): Promise<void>;
|
|
94
103
|
stop(): void;
|
|
95
104
|
write(data: string): void;
|
package/dist/types/tui.d.ts
CHANGED
|
@@ -1,5 +1,82 @@
|
|
|
1
1
|
import type { Terminal } from "./terminal";
|
|
2
2
|
import { visibleWidth } from "./utils";
|
|
3
|
+
export type CellRect = Readonly<{
|
|
4
|
+
column: number;
|
|
5
|
+
row: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}>;
|
|
9
|
+
export type RasterLeaseToken = Readonly<{
|
|
10
|
+
ownerId: string;
|
|
11
|
+
generation: number;
|
|
12
|
+
rect: CellRect;
|
|
13
|
+
}>;
|
|
14
|
+
export type RasterLeaseInvalidatedNotification = Readonly<{
|
|
15
|
+
type: "raster-lease-invalidated";
|
|
16
|
+
queueId: number;
|
|
17
|
+
token: RasterLeaseToken;
|
|
18
|
+
cause: "intersecting-generic-output" | "full-redraw" | "resize" | "terminal-loss" | "capability-loss" | "mode-off" | "dispose" | "explicit" | "manual-viewport";
|
|
19
|
+
eraseAck: TerminalOutputAck;
|
|
20
|
+
}>;
|
|
21
|
+
export type RasterLeaseRequest = Readonly<{
|
|
22
|
+
ownerId: string;
|
|
23
|
+
rect: CellRect;
|
|
24
|
+
erase: Readonly<{
|
|
25
|
+
type: "raster-erase";
|
|
26
|
+
bytes: Uint8Array;
|
|
27
|
+
}>;
|
|
28
|
+
onInvalidated?: (notice: RasterLeaseInvalidatedNotification) => void;
|
|
29
|
+
}>;
|
|
30
|
+
export type TerminalOutputOperation = Readonly<{
|
|
31
|
+
type: "generic-render";
|
|
32
|
+
rect: CellRect;
|
|
33
|
+
bytes: Uint8Array;
|
|
34
|
+
}> | Readonly<{
|
|
35
|
+
type: "generic-full-redraw";
|
|
36
|
+
rect: CellRect;
|
|
37
|
+
bytes: Uint8Array;
|
|
38
|
+
}> | Readonly<{
|
|
39
|
+
type: "raster-multipart-batch";
|
|
40
|
+
records: readonly Uint8Array[];
|
|
41
|
+
prefix?: Uint8Array;
|
|
42
|
+
afterPrefix?: () => Promise<boolean>;
|
|
43
|
+
/** Synchronous freshness gate evaluated immediately before terminal output. */
|
|
44
|
+
shouldWrite?: () => boolean;
|
|
45
|
+
replayPrefix?: Uint8Array;
|
|
46
|
+
suffix?: Uint8Array;
|
|
47
|
+
abortSuffix?: Uint8Array;
|
|
48
|
+
restoreCursorVisibility?: boolean;
|
|
49
|
+
}> | Readonly<{
|
|
50
|
+
type: "raster-erase";
|
|
51
|
+
bytes: Uint8Array;
|
|
52
|
+
}> | Readonly<{
|
|
53
|
+
type: "raster-probe";
|
|
54
|
+
bytes: Uint8Array;
|
|
55
|
+
}> | Readonly<{
|
|
56
|
+
type: "queued-output";
|
|
57
|
+
bytes: Uint8Array;
|
|
58
|
+
shouldWrite?: () => boolean;
|
|
59
|
+
/** Runs synchronously at the terminal write boundary after a successful write. */
|
|
60
|
+
onWritten?: () => void;
|
|
61
|
+
}>;
|
|
62
|
+
export type TerminalOutputAck = Readonly<{
|
|
63
|
+
queueId: number;
|
|
64
|
+
operation: TerminalOutputOperation["type"];
|
|
65
|
+
status: "written" | "stale-token" | "revoked" | "failed";
|
|
66
|
+
token?: RasterLeaseToken;
|
|
67
|
+
}>;
|
|
68
|
+
export type LifecycleCleanupAck = Readonly<{
|
|
69
|
+
attempted: number;
|
|
70
|
+
written: number;
|
|
71
|
+
stillPending: number;
|
|
72
|
+
}>;
|
|
73
|
+
export type RasterLeaseAcquireResult = Readonly<{
|
|
74
|
+
status: "acquired";
|
|
75
|
+
token: RasterLeaseToken;
|
|
76
|
+
}> | Readonly<{
|
|
77
|
+
status: "rejected";
|
|
78
|
+
reason: "invalid-geometry" | "terminal-unavailable" | "owner-conflict" | "manual-viewport";
|
|
79
|
+
}>;
|
|
3
80
|
/** Discrete mouse-wheel notch size in terminal rows (xterm/less-style). */
|
|
4
81
|
export declare const DEFAULT_WHEEL_LINES = 3;
|
|
5
82
|
type InputListenerResult = {
|
|
@@ -7,6 +84,10 @@ type InputListenerResult = {
|
|
|
7
84
|
data?: string;
|
|
8
85
|
} | undefined;
|
|
9
86
|
type InputListener = (data: string) => InputListenerResult;
|
|
87
|
+
type PostRenderEmission = {
|
|
88
|
+
payload: string;
|
|
89
|
+
onWritten?: () => void;
|
|
90
|
+
};
|
|
10
91
|
/**
|
|
11
92
|
* Component interface - all components must implement this
|
|
12
93
|
*/
|
|
@@ -53,6 +134,12 @@ export interface Component {
|
|
|
53
134
|
* Default is false - release events are filtered out.
|
|
54
135
|
*/
|
|
55
136
|
wantsKeyRelease?: boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Optional monotonic revision for renderer-level subtree reuse. Components that
|
|
139
|
+
* expose this MUST advance it whenever render output can change without a
|
|
140
|
+
* width change. Unversioned components are always rendered normally.
|
|
141
|
+
*/
|
|
142
|
+
getRenderRevision?(): bigint;
|
|
56
143
|
/**
|
|
57
144
|
* Invalidate any cached rendering state.
|
|
58
145
|
* Called when theme changes or when component needs to re-render from scratch.
|
|
@@ -238,6 +325,7 @@ export interface OverlayHandle {
|
|
|
238
325
|
export declare class Container implements ViewportAnchorProvider {
|
|
239
326
|
#private;
|
|
240
327
|
children: Component[];
|
|
328
|
+
getRenderRevision(): bigint;
|
|
241
329
|
addChild(component: Component): void;
|
|
242
330
|
removeChild(component: Component): void;
|
|
243
331
|
/** Remove a child without disposing it (for detach-then-readd reuse). */
|
|
@@ -254,6 +342,8 @@ export declare class Container implements ViewportAnchorProvider {
|
|
|
254
342
|
clear(): void;
|
|
255
343
|
/** Remove all children without disposing them (for detach-then-readd reuse). */
|
|
256
344
|
detachAll(): void;
|
|
345
|
+
/** Replace direct children without disposing reusable components. */
|
|
346
|
+
replaceChildren(children: Component[]): void;
|
|
257
347
|
/** Registers a direct child as eligible for semantic viewport anchoring. */
|
|
258
348
|
setViewportAnchorSource(component: Component, source: ViewportAnchorSource | null): void;
|
|
259
349
|
dispose(): void;
|
|
@@ -344,6 +434,20 @@ export declare class TUI extends Container {
|
|
|
344
434
|
/** Check if there are any visible overlays */
|
|
345
435
|
hasOverlay(): boolean;
|
|
346
436
|
invalidate(): void;
|
|
437
|
+
acquireRasterLease(request: RasterLeaseRequest): Promise<RasterLeaseAcquireResult>;
|
|
438
|
+
submitTerminalOutput(request: Readonly<{
|
|
439
|
+
operation: TerminalOutputOperation;
|
|
440
|
+
token?: RasterLeaseToken;
|
|
441
|
+
}>): Promise<TerminalOutputAck>;
|
|
442
|
+
invalidateRasterLease(request: Readonly<{
|
|
443
|
+
token: RasterLeaseToken;
|
|
444
|
+
cause: RasterLeaseInvalidatedNotification["cause"];
|
|
445
|
+
}>): Promise<TerminalOutputAck>;
|
|
446
|
+
notifyTerminalLifecycle(event: {
|
|
447
|
+
kind: "availability-restored" | "explicit-cleanup";
|
|
448
|
+
source: "tui" | "interactive-mode" | "transport";
|
|
449
|
+
terminalGeneration: number;
|
|
450
|
+
}): Promise<LifecycleCleanupAck>;
|
|
347
451
|
start(): void;
|
|
348
452
|
/**
|
|
349
453
|
* Wait for a specific render request generation to be written successfully.
|
|
@@ -355,8 +459,15 @@ export declare class TUI extends Container {
|
|
|
355
459
|
*/
|
|
356
460
|
waitForRenderCommit(generation: number, timeoutMs?: number): Promise<boolean>;
|
|
357
461
|
get terminalAvailable(): boolean;
|
|
462
|
+
get isRunning(): boolean;
|
|
463
|
+
get terminalGeneration(): number;
|
|
464
|
+
get manualViewportActive(): boolean;
|
|
358
465
|
addInputListener(listener: InputListener): () => void;
|
|
466
|
+
drainInput(maxMs: number, quiescenceMs: number): Promise<void>;
|
|
467
|
+
drainPetProbeInput(maxMs: number, quiescenceMs: number): Promise<void>;
|
|
359
468
|
removeInputListener(listener: InputListener): void;
|
|
469
|
+
/** Refresh terminal cell metrics for a verified external image transport. */
|
|
470
|
+
refreshImageCellSize(): void;
|
|
360
471
|
stop(): void;
|
|
361
472
|
/**
|
|
362
473
|
* Viewport-repaint-aware resize render request.
|
|
@@ -372,6 +483,8 @@ export declare class TUI extends Container {
|
|
|
372
483
|
*/
|
|
373
484
|
requestResizeRender(): void;
|
|
374
485
|
requestRender(force?: boolean, source?: string): void;
|
|
486
|
+
/** Request a frame whose mutation is known to be outside the viewport-anchor subtree. */
|
|
487
|
+
requestLayoutRender(source?: string): void;
|
|
375
488
|
requestRenderWithGeneration(force?: boolean, source?: string): number;
|
|
376
489
|
getLineRenderCacheStats(): {
|
|
377
490
|
normalizationSize: number;
|
|
@@ -380,13 +493,18 @@ export declare class TUI extends Container {
|
|
|
380
493
|
truncationLimit: number;
|
|
381
494
|
};
|
|
382
495
|
/** Retain terminal cleanup until a write succeeds, even after its component is disposed. */
|
|
383
|
-
queueTerminalCleanup(payload: string, onDelivered?: () => void): void
|
|
384
|
-
/**
|
|
385
|
-
|
|
496
|
+
queueTerminalCleanup(payload: string, onDelivered?: () => void): Promise<void>;
|
|
497
|
+
/** Queue protocol-neutral output behind the same terminal ordering as renders. */
|
|
498
|
+
queueTerminalOutput(payload: string, options?: {
|
|
499
|
+
shouldWrite?: () => boolean;
|
|
500
|
+
onWritten?: () => void;
|
|
501
|
+
}): Promise<TerminalOutputAck>;
|
|
502
|
+
/** Retry retained cleanup after recovery or before shutdown. */
|
|
503
|
+
flushTerminalCleanup(restoreTerminalAvailability?: boolean): void;
|
|
386
504
|
/**
|
|
387
505
|
* Register an emitter whose payload is delivered after each shared render
|
|
388
506
|
* transaction. The emitter is an exempt physical overlay: its bytes are
|
|
389
507
|
* deliberately kept out of the shared transcript write.
|
|
390
508
|
*/
|
|
391
|
-
setPostRenderEmitter(emitter: (() => string | null) | undefined): void;
|
|
509
|
+
setPostRenderEmitter(emitter: (() => string | PostRenderEmission | null) | undefined): void;
|
|
392
510
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/tui",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.14.0",
|
|
5
5
|
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
|
|
6
6
|
"homepage": "https://gajae-code.com",
|
|
7
7
|
"author": "Yeachan-Heo and Gajae Code Contributors",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"fmt": "biome format --write ."
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@gajae-code/natives": "0.
|
|
40
|
-
"@gajae-code/utils": "0.
|
|
39
|
+
"@gajae-code/natives": "0.14.0",
|
|
40
|
+
"@gajae-code/utils": "0.14.0",
|
|
41
41
|
"lru-cache": "11.3.6",
|
|
42
42
|
"marked": "18.0.6"
|
|
43
43
|
},
|