vterm.js 0.5.0 → 0.6.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/dist/index.d.mts CHANGED
@@ -33,21 +33,44 @@
33
33
  * @see https://terminfo.dev for the feature matrix
34
34
  * @see https://github.com/beorn/vterm for the monorepo
35
35
  */
36
- interface CellColor {
36
+ /**
37
+ * An RGB color, identity-preserving. `r`/`g`/`b` are always present (painters read
38
+ * them unconditionally); `index` is optional palette provenance. Named `Color` per the
39
+ * §9 naming ruling (rule 5: flat progressive shape over a discriminated union — a type
40
+ * named `RGB` that carries `.index` would lie).
41
+ */
42
+ interface Color {
37
43
  r: number;
38
44
  g: number;
39
45
  b: number;
46
+ /**
47
+ * The palette index (0-255) this RGB was resolved from, when the color came
48
+ * from an INDEXED SGR (`31`, `91`, `38;5;N`, `48;5;N`, `58;5;N`, …). Absent
49
+ * for true 24-bit RGB (`38;2;R;G;B`) and for OSC-sourced colors (OSC 4/10/11),
50
+ * which are genuine RGB with no themeable index.
51
+ *
52
+ * Why it exists: vterm resolves every indexed SGR to `palette256[idx]` at parse
53
+ * time. Without keeping the origin index, {@link serializeSnapshot} can only
54
+ * re-emit `38;2;R;G;B`, which bakes vterm's built-in ANSI values and defeats the
55
+ * outer terminal's theme on reattach. Preserving `index` lets the serializer
56
+ * re-emit the faithful indexed form so a themeable receiver themes it again.
57
+ *
58
+ * It rides {@link Snapshot} as plain optional data (like
59
+ * `scrollbackSoftWrapped`) and is stripped at the {@link VtermScreen.getCell} /
60
+ * {@link VtermScreen.getRow} read boundary, whose contract is the resolved RGB.
61
+ */
62
+ index?: number;
40
63
  }
41
64
  type UnderlineStyle = "none" | "single" | "double" | "curly" | "dotted" | "dashed";
42
65
  interface ScreenCell {
43
66
  char: string;
44
- fg: CellColor | null;
45
- bg: CellColor | null;
67
+ fg: Color | null;
68
+ bg: Color | null;
46
69
  bold: boolean;
47
70
  faint: boolean;
48
71
  italic: boolean;
49
72
  underline: UnderlineStyle;
50
- underlineColor: CellColor | null;
73
+ underlineColor: Color | null;
51
74
  overline: boolean;
52
75
  strikethrough: boolean;
53
76
  inverse: boolean;
@@ -62,7 +85,16 @@ interface ScreenOptions {
62
85
  scrollbackLimit?: number;
63
86
  /** Callback for DA1/DA2/DSR responses — write these back to the PTY */
64
87
  onResponse?: (data: string) => void;
88
+ /**
89
+ * Maximum UTF-16 code units retained for one APC or DCS string sequence.
90
+ * Image protocols use ASCII/base64 payloads, so this is also their byte
91
+ * bound. Longer sequences are consumed without buffering or dispatch and
92
+ * surface one typed `string-overflow` parser event at their terminator.
93
+ */
94
+ maxStringSequenceLength?: number;
65
95
  }
96
+ /** Default retained payload bound for one APC/DCS sequence (16 MiB of ASCII/base64). */
97
+ declare const DEFAULT_MAX_STRING_SEQUENCE_LENGTH: number;
66
98
  interface SemanticZone {
67
99
  type: "prompt" | "command" | "output";
68
100
  startRow: number;
@@ -73,20 +105,419 @@ interface SixelImage {
73
105
  row: number;
74
106
  col: number;
75
107
  }
108
+ interface ScreenAttrsSnapshot {
109
+ fg: Color | null;
110
+ bg: Color | null;
111
+ bold: boolean;
112
+ faint: boolean;
113
+ italic: boolean;
114
+ underline: UnderlineStyle;
115
+ underlineColor: Color | null;
116
+ overline: boolean;
117
+ strikethrough: boolean;
118
+ inverse: boolean;
119
+ hidden: boolean;
120
+ blink: boolean;
121
+ url: string | null;
122
+ }
123
+ interface ScreenColorStateSnapshot {
124
+ palette256: Color[];
125
+ defaultFgColor: Color | null;
126
+ defaultBgColor: Color | null;
127
+ cursorColor: Color | null;
128
+ specialColors: [number, Color][];
129
+ pointerFgColor: Color | null;
130
+ pointerBgColor: Color | null;
131
+ highlightBgColor: Color | null;
132
+ highlightFgColor: Color | null;
133
+ }
134
+ type ScreenParserState = "ground" | "escape" | "escape_charset" | "escape_hash" | "csi" | "osc" | "dcs" | "dcs_passthrough" | "osc_st" | "dcs_st" | "apc" | "apc_st";
135
+ interface ScreenBufferSnapshot {
136
+ grid: ScreenCell[][];
137
+ softWrapped: boolean[];
138
+ }
139
+ /**
140
+ * The whole-world persist/restore value — grids, ranges, modes, cursor, colors,
141
+ * parser transients, wrap bits. JSON-safe plain data; the persist boundary, not the
142
+ * incremental read path. Named `Snapshot` per §9 (the namespace supplies the context).
143
+ *
144
+ * Note: `cursor`/`savedState` still carry `x`/`y` (not `col`/`row`) — the §9
145
+ * `Cursor{col,row}` field rename is DEFERRED here because these fields are the wire
146
+ * shape read by the binary codec (`encodeScreenSnapshotBinary`); renaming them silently
147
+ * changes the persisted format. The {@link Cursor} read type + `getCursor()` accessor
148
+ * carry the col/row vocabulary at the read boundary instead.
149
+ */
150
+ interface Snapshot {
151
+ version: 1;
152
+ cols: number;
153
+ rows: number;
154
+ scrollbackLimit: number;
155
+ activeBuffer: "main" | "alt";
156
+ main: ScreenBufferSnapshot;
157
+ alt: ScreenBufferSnapshot;
158
+ scrollback: ScreenCell[][];
159
+ /**
160
+ * Per-scrollback-row soft-wrap bit: true when the row soft-wraps INTO the
161
+ * following row (autowrap continued the same logical line below it) — the
162
+ * same semantics as `ScreenBufferSnapshot.softWrapped`. Parallel to
163
+ * `scrollback`. Absent in snapshots taken before this field existed —
164
+ * `restore()` treats missing as all-false (hard-wrapped).
165
+ */
166
+ scrollbackSoftWrapped: boolean[];
167
+ cursor: {
168
+ x: number;
169
+ y: number;
170
+ visible: boolean;
171
+ shape: "block" | "underline" | "bar";
172
+ blinking: boolean;
173
+ savedX: number;
174
+ savedY: number;
175
+ };
176
+ savedState: {
177
+ x: number;
178
+ y: number;
179
+ attrs: ScreenAttrsSnapshot;
180
+ originMode: boolean;
181
+ autoWrap: boolean;
182
+ charsetG0: boolean;
183
+ };
184
+ attrs: ScreenAttrsSnapshot;
185
+ modes: {
186
+ bracketedPaste: boolean;
187
+ applicationCursor: boolean;
188
+ applicationKeypad: boolean;
189
+ autoWrap: boolean;
190
+ mouseTracking: boolean;
191
+ mouseTrackingMode: number;
192
+ sgrMouse: boolean;
193
+ focusTracking: boolean;
194
+ origin: boolean;
195
+ insert: boolean;
196
+ reverseVideo: boolean;
197
+ syncOutput: boolean;
198
+ kittyKeyboardFlags: number;
199
+ kittyKeyboardStack: number[];
200
+ kittyGraphics: boolean;
201
+ colorSchemeReporting: boolean;
202
+ decColumn: boolean;
203
+ altScroll: boolean;
204
+ utf8Mouse: boolean;
205
+ };
206
+ margins: {
207
+ scrollTop: number;
208
+ scrollBottom: number;
209
+ leftRight: boolean;
210
+ left: number;
211
+ right: number;
212
+ };
213
+ colors: {
214
+ current: ScreenColorStateSnapshot;
215
+ stack: ScreenColorStateSnapshot[];
216
+ };
217
+ tabStops: number[];
218
+ title: string;
219
+ clipboard: string;
220
+ cwd: string;
221
+ notifications: string[];
222
+ viewportOffset: number;
223
+ parser: {
224
+ state: ScreenParserState;
225
+ esc: string;
226
+ osc: string;
227
+ dcs: string;
228
+ dcsStart: {
229
+ row: number;
230
+ col: number;
231
+ };
232
+ dcsReceivedLength?: number;
233
+ dcsOverflow?: boolean;
234
+ apc: string;
235
+ apcStart?: {
236
+ row: number;
237
+ col: number;
238
+ };
239
+ apcReceivedLength?: number;
240
+ apcOverflow?: boolean;
241
+ utf8PendingBytes: number[];
242
+ };
243
+ unicode: {
244
+ charsetG0: boolean;
245
+ lastChar: string;
246
+ pendingRegionalIndicator: string | null;
247
+ afterZWJ: boolean;
248
+ };
249
+ }
250
+ /**
251
+ * The cursor position at the read boundary, in the grid's own `col`/`row` vocabulary
252
+ * (§9 naming ruling: `x`/`y` contradicted the row/col naming used everywhere else, and
253
+ * the `State` suffix was redundant). Returned by {@link VtermScreen.getCursor}.
254
+ */
255
+ interface Cursor {
256
+ col: number;
257
+ row: number;
258
+ }
259
+ /**
260
+ * A terminal write as serializable data — the coarse WRITE vocabulary, symmetric with the
261
+ * Hab session journal and termless `Recording`. Bytes remain the CANONICAL encoding of an
262
+ * `output` op (they are what the journal persists and what {@link Screen.tapOps} delivers);
263
+ * a `string` is a convenience input to {@link Screen.apply} that is UTF-8-encoded before it
264
+ * is applied. This is deliberately NOT a per-VT-action reification — fine-grained parsed
265
+ * actions are surfaced by {@link ParserEvent} through {@link Screen.tapParser}.
266
+ */
267
+ type TerminalOp = {
268
+ type: "output";
269
+ data: Uint8Array | string;
270
+ } | {
271
+ type: "resize";
272
+ cols: number;
273
+ rows: number;
274
+ };
275
+ /**
276
+ * A single parsed VT action, emitted by {@link Screen.tapParser} AFTER the engine applies it,
277
+ * in stream order. A minimal, stable union over what the parser dispatches:
278
+ *
279
+ * - `print` — a run of consecutive printable graphemes, coalesced within one {@link
280
+ * Screen.process}/{@link Screen.apply} flood and flushed before the next control
281
+ * event (and at end-of-flood).
282
+ * - `execute` — a recognized C0 control byte (BEL, BS, HT, LF, VT, FF, CR); `code` is the byte.
283
+ * - `csi` — a complete CSI sequence; `final` is the dispatching byte, `params` are the
284
+ * `;`-separated numeric parameters (empty → `0`, matching the engine's own parse),
285
+ * `prefix` is the private marker (`?`/`>`/`<`/`=`) when present, `intermediates`
286
+ * are the `0x20`–`0x2f` bytes when present. (Colon sub-parameters collapse to
287
+ * their leading integer — the top-level view the non-SGR dispatchers also use.)
288
+ * - `osc` — a complete OSC with a numeric `code`; `data` is everything after the first `;`.
289
+ * - `esc` — a complete non-CSI/OSC escape (`ESC c`/`D`/`M`/`7`/`8`/`E`/`H`/`=`/`>` and the
290
+ * charset/`#` designators); `final` is the dispatching byte, `intermediates`
291
+ * carries the `(`/`)`/`#` designator byte when present.
292
+ *
293
+ * - `dcs` / `apc` — a complete bounded string sequence with the guest-local cursor anchor at
294
+ * sequence start. Payloads beyond `maxStringSequenceLength` are not dispatched;
295
+ * their terminator emits one typed `string-overflow` event instead.
296
+ *
297
+ * A listener MUST NOT throw — taps are fail-loud: an exception propagates out of the write call
298
+ * (the engine state stays consistent).
299
+ */
300
+ type ParserEvent = {
301
+ kind: "print";
302
+ text: string;
303
+ } | {
304
+ kind: "execute";
305
+ code: number;
306
+ } | {
307
+ kind: "csi";
308
+ final: string;
309
+ params: number[];
310
+ prefix?: string;
311
+ intermediates?: string;
312
+ } | {
313
+ kind: "osc";
314
+ code: number;
315
+ data: string;
316
+ } | {
317
+ kind: "esc";
318
+ final: string;
319
+ intermediates?: string;
320
+ } | {
321
+ kind: "apc";
322
+ data: string;
323
+ row: number;
324
+ col: number;
325
+ } | {
326
+ kind: "dcs";
327
+ data: string;
328
+ row: number;
329
+ col: number;
330
+ } | {
331
+ kind: "string-overflow";
332
+ sequence: "apc" | "dcs";
333
+ maxLength: number;
334
+ receivedLength: number;
335
+ row: number;
336
+ col: number;
337
+ };
338
+ /**
339
+ * Accumulated per-row damage since the previous {@link Screen.takeDirty} call — the PULL-plane
340
+ * observation surface for renderers that read on their own schedule (distinct from the push-plane
341
+ * {@link Screen.tapOps}/{@link Screen.tapParser}). Absolute-row indexed, consistent with
342
+ * {@link Screen.getRowAbsolute}.
343
+ *
344
+ * - `rows` — the changed rows as retained-relative ABSOLUTE indices (row 0 = oldest retained
345
+ * scrollback line), OR the literal `"all"` when the whole visible buffer changed structurally
346
+ * (resize, full clear, alt-screen switch, reset, restore). The `Set` is freshly OWNED by the
347
+ * caller — the engine keeps a separate empty accumulator after the take.
348
+ * - `cursor` — `true` when the cursor position/visibility/shape/blink changed since the last take.
349
+ * - `scrolled` — number of lines that entered scrollback since the last take (a renderer shifts
350
+ * its viewport by this and repaints only the rows in `rows`).
351
+ *
352
+ * Contract note on trimming: a retention trim shifts every absolute index down by the trimmed
353
+ * count; `rows` are valid against the buffer AT take time. Pair with {@link Screen.firstRetainedRow}
354
+ * (which bumps by the trimmed count) to rebase indices cached across a take that spanned a trim.
355
+ */
356
+ interface DirtyRegion {
357
+ rows: Set<number> | "all";
358
+ cursor: boolean;
359
+ scrolled: number;
360
+ }
361
+ /**
362
+ * A minimal read-signal — the atom of the REACTIVE read plane (§4). Defined IN vterm.js, which
363
+ * stays dependency-free (§9 rule 7: compatible SHAPES over shared imports). A consumer wraps it in
364
+ * `alien-signals`, a zustand store, or React's `useSyncExternalStore` trivially, because the shape
365
+ * is exactly `{ get, subscribe }` — nothing here imports a reactive library.
366
+ *
367
+ * - `get()` returns the CURRENT value, computed live from engine state. It is pull-safe and
368
+ * independent of subscription: calling it never schedules, consumes, or resets a delivery.
369
+ * - `subscribe(listener)` registers for change delivery and returns an unsubscribe function. The
370
+ * listener fires at most once per flush boundary (see {@link ScreenSignals}), and only when the
371
+ * value actually changed since the last delivery (equality-gated). Subscribing does NOT fire
372
+ * immediately — the baseline is the value at subscribe time, so only later changes deliver.
373
+ * Fail-loud: a throwing listener propagates out of the write call.
374
+ */
375
+ interface ReadSignal<T> {
376
+ get(): T;
377
+ subscribe(listener: (value: T) => void): () => void;
378
+ }
379
+ /** The terminal's screen size (its column/row dimensions). Emitted by {@link ScreenSignals.size$}. */
380
+ interface Size {
381
+ cols: number;
382
+ rows: number;
383
+ }
384
+ /**
385
+ * The closed DEC/xterm private-mode set at the OBSERVATION boundary — everything a guest previously
386
+ * discovered by regex-scanning the DECSET byte stream. Emitted by {@link ScreenSignals.modes$}
387
+ * (equality-gated: one emission per flush that actually flips a mode). Mirrors the string keys of
388
+ * {@link Screen.getMode}, plus the numeric mouse-tracking protocol level.
389
+ */
390
+ interface TerminalModes {
391
+ altScreen: boolean;
392
+ cursorVisible: boolean;
393
+ bracketedPaste: boolean;
394
+ applicationCursor: boolean;
395
+ applicationKeypad: boolean;
396
+ autoWrap: boolean;
397
+ mouseTracking: boolean;
398
+ /** The active mouse-tracking protocol: `0` = off; `1000`/`1002`/`1003` = X10/button/any-event. */
399
+ mouseTrackingMode: number;
400
+ sgrMouse: boolean;
401
+ utf8Mouse: boolean;
402
+ focusTracking: boolean;
403
+ originMode: boolean;
404
+ insertMode: boolean;
405
+ reverseVideo: boolean;
406
+ syncOutput: boolean;
407
+ leftRightMargin: boolean;
408
+ colorSchemeReporting: boolean;
409
+ kittyKeyboard: boolean;
410
+ kittyGraphics: boolean;
411
+ sixel: boolean;
412
+ }
413
+ /**
414
+ * The REACTIVE read plane (§4): five equality-gated signals over the SAME state the pull plane
415
+ * ({@link Screen.getRowAbsolute}/{@link Screen.takeDirty}) and the push plane ({@link Screen.tapOps})
416
+ * expose. It replaces consumers' title-polling and DECSET regex scanning.
417
+ *
418
+ * Zero overhead when unused: `.signals` is lazily created (the getter allocates nothing until first
419
+ * read), and each signal is lazily created on first access (per-signal laziness). The write core does
420
+ * NO signal bookkeeping until `.signals` is read, and NO per-write damage accumulation until
421
+ * `damage$` actually has a subscriber.
422
+ *
423
+ * Flush boundary: every signal coalesces to AT MOST ONE emission per public state-mutating call
424
+ * (`process`/`apply`/`resize`/`reset`/`restore`; `apply` inherits it via `process`/`resize`) — the
425
+ * natural batch. `title$`/`modes$`/`cursor$`/`size$` fire only when their value actually changed
426
+ * across the call; `damage$` publishes the BATCHED dirty-set accumulated during the call.
427
+ *
428
+ * Two-plane coexistence: `damage$` runs on an accumulator INDEPENDENT of {@link Screen.takeDirty}.
429
+ * Subscribing never steals or resets the pull-plane epoch, so a `damage$` renderer and a
430
+ * `takeDirty()` differ observe the same damage without draining each other.
431
+ */
432
+ interface ScreenSignals {
433
+ /** The window title (OSC 0/2). Replaces title-diff polling. */
434
+ title$: ReadSignal<string>;
435
+ /** The closed DEC/xterm mode set. Replaces the guest's DECSET regex scanner. */
436
+ modes$: ReadSignal<TerminalModes>;
437
+ /** The cursor position in grid `col`/`row` (§9). Visibility rides {@link modes$}`.cursorVisible`. */
438
+ cursor$: ReadSignal<Cursor>;
439
+ /** The screen size. */
440
+ size$: ReadSignal<Size>;
441
+ /**
442
+ * The per-flush BATCHED dirty region — the union of rows changed during the call (or `"all"` on a
443
+ * structural change), with the cursor/scroll deltas. Same shape as {@link Screen.takeDirty}, but
444
+ * drained on its OWN epoch (see the interface note); this is precisely what a future canvas/DOM
445
+ * renderer subscribes to. The emitted region (including its `rows` `Set`) is SHARED across all
446
+ * `damage$` subscribers for that flush — treat it as read-only.
447
+ */
448
+ damage$: ReadSignal<DirtyRegion>;
449
+ }
76
450
  interface Screen {
77
451
  readonly cols: number;
78
452
  readonly rows: number;
453
+ /** The reactive read plane (§4). Lazily created; zero write-path overhead until used. */
454
+ readonly signals: ScreenSignals;
79
455
  process(data: Uint8Array): void;
80
456
  resize(cols: number, rows: number): void;
457
+ /**
458
+ * Apply one {@link TerminalOp} — the single public write entry, symmetric with the journal.
459
+ * `output` routes to {@link process} (a `string` payload is UTF-8-encoded first); `resize`
460
+ * routes to {@link resize}. Additive over `process`/`resize`, which remain public.
461
+ */
462
+ apply(op: TerminalOp): void;
463
+ /**
464
+ * Observe applied ops (opt-in). The listener fires exactly once per applied op — one per
465
+ * `process`/`apply`/`resize` call — with the CANONICAL payload (an `output` op always carries
466
+ * a `Uint8Array`). Returns an unsubscribe function. Zero overhead when no listener is
467
+ * registered. Enables symmetric journaling of the write stream.
468
+ */
469
+ tapOps(listener: (op: TerminalOp) => void): () => void;
470
+ /**
471
+ * Observe parsed VT actions (opt-in), delivered AFTER each is applied, in stream order.
472
+ * Returns an unsubscribe function. Zero overhead when no listener is registered — no {@link
473
+ * ParserEvent} is allocated on the byte-flood path unless a listener exists.
474
+ */
475
+ tapParser(listener: (event: ParserEvent) => void): () => void;
81
476
  reset(): void;
477
+ snapshot(): Snapshot;
478
+ restore(snapshot: Snapshot): void;
479
+ /** Serialize the current state to minimal ANSI — `serializeSnapshot(this.snapshot(), options)`. */
480
+ serialize(options?: SerializeOptions): string;
82
481
  getCell(row: number, col: number): ScreenCell;
83
- getLine(row: number): ScreenCell[];
482
+ /**
483
+ * The cells of a screen-relative row (§9: **row = cells, line = text**). Colors are
484
+ * stripped of palette-origin index at the read boundary.
485
+ */
486
+ getRow(row: number): ScreenCell[];
84
487
  getText(): string;
488
+ /** Scrollback rows above the visible grid, oldest first, rendered like getText(). */
489
+ getScrollbackText(): string;
85
490
  getTextRange(startRow: number, startCol: number, endRow: number, endCol: number): string;
86
- getCursorPosition(): {
87
- x: number;
88
- y: number;
89
- };
491
+ /** Total rows in the buffer: retained scrollback + screen. */
492
+ totalRows(): number;
493
+ /** Number of visible screen rows (the terminal's row dimension). */
494
+ screenRows(): number;
495
+ /**
496
+ * Absolute row where the viewport's top line sits. At the bottom (no scroll):
497
+ * `totalRows() - screenRows()`. Scrolled fully up: `0`.
498
+ */
499
+ viewportTop(): number;
500
+ /**
501
+ * The row at ABSOLUTE index `row` (row 0 = oldest retained scrollback line; the screen occupies
502
+ * the last `screenRows()` rows). Colors are stripped of palette-origin index like {@link getRow}.
503
+ * Out-of-range indices return a blank row (matching the {@link getRow} read-boundary contract).
504
+ */
505
+ getRowAbsolute(row: number): ScreenCell[];
506
+ /**
507
+ * The GLOBAL index of retained absolute row 0 — i.e. the number of scrollback lines permanently
508
+ * evicted by retention trimming since creation (0 initially). Increases only when trimming drops
509
+ * lines; resets on {@link reset}/{@link restore}. A stable global row id is
510
+ * `firstRetainedRow() + <absolute row>`; an increase since a prior read signals a trim.
511
+ */
512
+ firstRetainedRow(): number;
513
+ /**
514
+ * Take and reset the accumulated per-row damage since the previous call — the pull-plane damage
515
+ * surface for renderers. See {@link DirtyRegion}. Always-on (independent of {@link tapOps}); the
516
+ * write path costs at most one Set membership update per row-run.
517
+ */
518
+ takeDirty(): DirtyRegion;
519
+ /** Cursor position in the grid's `col`/`row` vocabulary (§9). See {@link Cursor}. */
520
+ getCursor(): Cursor;
90
521
  getCursorVisible(): boolean;
91
522
  getCursorShape(): "block" | "underline" | "bar";
92
523
  getCursorBlinking(): boolean;
@@ -102,5 +533,45 @@ interface Screen {
102
533
  getSixelImages(): SixelImage[];
103
534
  }
104
535
  declare function createScreen(options?: ScreenOptions): Screen;
536
+ interface SerializeOptions {
537
+ /** Emit scrollback history rows before the screen paint. Default: true. */
538
+ includeScrollback?: boolean;
539
+ /** Emit the window title (OSC 0) when non-empty. Default: false. */
540
+ includeTitle?: boolean;
541
+ /** Emit OSC 8 hyperlinks for cell and pending-pen urls. Default: true. */
542
+ hyperlinks?: boolean;
543
+ /**
544
+ * Snapshot mode keys to skip during emission (e.g. `"bracketedPaste"`,
545
+ * `"mouseTracking"`, `"kittyKeyboardFlags"`, `"origin"`, `"insert"`).
546
+ * The receiver keeps its fresh default for excluded keys — an explicit,
547
+ * caller-requested divergence from the snapshot. DECAWM paint discipline
548
+ * is correctness, not configuration, and cannot be excluded.
549
+ */
550
+ excludeModes?: readonly string[];
551
+ }
552
+ /**
553
+ * Serialize a snapshot to minimal ANSI a FRESH same-size terminal can replay.
554
+ * Phase order + the hard exclusion set are documented on the section header
555
+ * above; every ordering constraint is pinned by the mode round-trip matrix.
556
+ *
557
+ * Intended divergences (documented, not silent): syncOutput/decColumn are
558
+ * never emitted; the inactive buffer, SCP saved cursor, DECSC saved state,
559
+ * color stack, and parser/pending-wrap/mid-parse state are unserializable to
560
+ * a VT byte stream by design — the binary snapshot carries them.
561
+ */
562
+ declare function serializeSnapshot(snapshot: Snapshot, options?: SerializeOptions): string;
563
+ //#endregion
564
+ //#region src/snapshot-codec.d.ts
565
+ /**
566
+ * Encode a {@link Snapshot} to a compact binary buffer. Output is
567
+ * deterministic for identical input and decodes back to a deep-equal snapshot.
568
+ */
569
+ declare function encodeScreenSnapshotBinary(snapshot: Snapshot): Uint8Array;
570
+ /**
571
+ * Decode a buffer produced by {@link encodeScreenSnapshotBinary} back into a
572
+ * {@link Snapshot}. Throws loudly on an unknown version byte, truncated
573
+ * input, or any internal inconsistency — never returns a partial/normalized result.
574
+ */
575
+ declare function decodeScreenSnapshotBinary(bytes: Uint8Array): Snapshot;
105
576
  //#endregion
106
- export { type CellColor, type ScreenCell, type SemanticZone, type SixelImage, type UnderlineStyle, type Screen as VtermScreen, type ScreenOptions as VtermScreenOptions, createScreen as createVtermScreen };
577
+ export { type Color, type Cursor, DEFAULT_MAX_STRING_SEQUENCE_LENGTH, type DirtyRegion, type ParserEvent, type ReadSignal, type ScreenCell, type ScreenSignals, type SemanticZone, type SerializeOptions, type SixelImage, type Size, type Snapshot, type TerminalModes, type TerminalOp, type UnderlineStyle, type Screen as VtermScreen, type ScreenAttrsSnapshot as VtermScreenAttrsSnapshot, type ScreenBufferSnapshot as VtermScreenBufferSnapshot, type ScreenColorStateSnapshot as VtermScreenColorStateSnapshot, type ScreenOptions as VtermScreenOptions, type ScreenParserState as VtermScreenParserState, createScreen as createVtermScreen, decodeScreenSnapshotBinary, encodeScreenSnapshotBinary, serializeSnapshot };