@gajae-code/tui 0.10.0 → 0.10.1
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 +7 -0
- package/dist/types/terminal-capabilities.d.ts +23 -0
- package/dist/types/tui.d.ts +12 -0
- package/package.json +3 -3
- package/src/terminal-capabilities.ts +77 -4
- package/src/tui.ts +50 -21
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.10.1] - 2026-07-13
|
|
6
|
+
### Fixed
|
|
7
|
+
|
|
8
|
+
- Terminal graphics protocols are no longer assumed under terminal multiplexers: the blind Kitty fallback for `TERM=tmux-*`/`screen-*` (and detected kitty/iTerm2 protocols leaking through multiplexer env) emitted raw graphics escapes the multiplexer consumed, leaving the Gajae composer pet invisible while its out-of-band cursor writes intermittently corrupted the TUI frame. Image protocols are now unconditionally dropped under tmux/screen/zellij (shared multiplexer predicate with the renderer host policy, including `$TMUX_PANE`, `$STY`, `$ZELLIJ`, and `GJC_TMUX_LAUNCHED`) unless `PI_FORCE_IMAGE_PROTOCOL` explicitly forces a protocol, which remains an expert override.
|
|
9
|
+
- Fixed the startup sixel capability probe's response parsing and authority: XTSMGRAPHICS replies are read per spec (`Ps=0` success; `1/2/3` errors — tmux's `CSI ?2;3;0S` error no longer counts as support), the DA1 device-class parameter is no longer misread as the sixel extension attribute (`CSI ?4;6c` identifies a VT132, not sixel), an explicit `PI_FORCE_IMAGE_PROTOCOL` (including `off`) suppresses probing entirely, and the probe never runs inside a multiplexer because tmux advertises DA1 `;4` from compile-time support regardless of the attached client.
|
|
10
|
+
- A configured Gajae pet now re-applies automatically when the asynchronous sixel probe enables graphics after startup (new `onImageProtocolChanged` subscription), instead of staying hidden until `/pet` is re-run; `/pet` also reports multiplexer graphics suppression explicitly instead of suggesting a different terminal.
|
|
11
|
+
|
|
5
12
|
## [0.10.0] - 2026-07-12
|
|
6
13
|
### Fixed
|
|
7
14
|
|
|
@@ -22,6 +22,15 @@ export declare class TerminalInfo {
|
|
|
22
22
|
sendNotification(message: string): void;
|
|
23
23
|
}
|
|
24
24
|
export declare function isNotificationSuppressed(): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Returns whether the process runs under a terminal multiplexer (tmux, GNU
|
|
27
|
+
* screen, or zellij). Recognizes the same host markers as the renderer's
|
|
28
|
+
* multiplexer predicate in tui.ts so capability selection and viewport-repaint
|
|
29
|
+
* policy agree on what counts as a multiplexed host. Multiplexers intercept
|
|
30
|
+
* graphics escapes and OSC 8 hyperlinks instead of forwarding them to the
|
|
31
|
+
* outer terminal.
|
|
32
|
+
*/
|
|
33
|
+
export declare function isUnderTerminalMultiplexer(env?: NodeJS.ProcessEnv): boolean;
|
|
25
34
|
export interface TerminalGraphicsFallbackOptions {
|
|
26
35
|
/**
|
|
27
36
|
* Permit cursor-neutral image escapes (kitty `a=p,C=1` placements) to render
|
|
@@ -43,6 +52,12 @@ export declare function isTerminalGraphicsFallbackActive(): boolean;
|
|
|
43
52
|
* graphics-fallback scope. True only when every active fallback scope opted in.
|
|
44
53
|
*/
|
|
45
54
|
export declare function isCursorNeutralImagePermittedInFallback(): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Returns whether PI_FORCE_IMAGE_PROTOCOL explicitly configures the image
|
|
57
|
+
* protocol, including an explicit "off". An explicit configuration is
|
|
58
|
+
* authoritative: runtime capability probes must not override it.
|
|
59
|
+
*/
|
|
60
|
+
export declare function isImageProtocolForced(): boolean;
|
|
46
61
|
/**
|
|
47
62
|
* Returns true when running in Windows Terminal with known SIXEL support.
|
|
48
63
|
*
|
|
@@ -51,6 +66,13 @@ export declare function isCursorNeutralImagePermittedInFallback(): boolean;
|
|
|
51
66
|
export declare function isWindowsTerminalPreviewSixelSupported(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): boolean;
|
|
52
67
|
export declare const TERMINAL_ID: TerminalId;
|
|
53
68
|
export declare const TERMINAL: TerminalInfo;
|
|
69
|
+
type ImageProtocolChangeListener = (imageProtocol: ImageProtocol | null) => void;
|
|
70
|
+
/**
|
|
71
|
+
* Subscribe to runtime image-protocol changes (e.g. the asynchronous sixel
|
|
72
|
+
* capability probe enabling graphics after startup). Returns an unsubscribe
|
|
73
|
+
* function. Listeners fire only on actual changes.
|
|
74
|
+
*/
|
|
75
|
+
export declare function onImageProtocolChanged(listener: ImageProtocolChangeListener): () => void;
|
|
54
76
|
/**
|
|
55
77
|
* Override terminal image protocol at runtime after capability probes complete.
|
|
56
78
|
*/
|
|
@@ -162,3 +184,4 @@ export interface RenderedImage {
|
|
|
162
184
|
}
|
|
163
185
|
export declare function renderImage(base64Data: string, imageDimensions: ImageDimensions, options?: ImageRenderOptions): RenderedImage | null;
|
|
164
186
|
export declare function imageFallback(mimeType: string, dimensions?: ImageDimensions, filename?: string): string;
|
|
187
|
+
export {};
|
package/dist/types/tui.d.ts
CHANGED
|
@@ -98,6 +98,18 @@ export interface OverlayMargin {
|
|
|
98
98
|
}
|
|
99
99
|
/** Value that can be absolute (number) or percentage (string like "50%") */
|
|
100
100
|
export type SizeValue = number | `${number}%`;
|
|
101
|
+
/**
|
|
102
|
+
* Startup sixel capability probe policy (pure; exported for tests):
|
|
103
|
+
* - Never probe when PI_FORCE_IMAGE_PROTOCOL is set — an explicit
|
|
104
|
+
* configuration (including "off") is authoritative.
|
|
105
|
+
* - Never probe inside a terminal multiplexer: tmux advertises DA1 ";4"
|
|
106
|
+
* whenever it was compiled with sixel support, regardless of whether the
|
|
107
|
+
* attached client terminal can render sixel, so a positive reply is not
|
|
108
|
+
* end-to-end evidence. Graphics under a multiplexer are strictly opt-in
|
|
109
|
+
* via PI_FORCE_IMAGE_PROTOCOL=sixel.
|
|
110
|
+
* - Probe Windows Terminal (>=1.22 renders sixel but exposes no env marker).
|
|
111
|
+
*/
|
|
112
|
+
export declare function shouldProbeSixelCapability(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): boolean;
|
|
101
113
|
/**
|
|
102
114
|
* True when repainting only the live viewport is safer than clearing/replaying
|
|
103
115
|
* the full transcript. Native Windows console hosts are included even when
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/tui",
|
|
4
|
-
"version": "0.10.
|
|
4
|
+
"version": "0.10.1",
|
|
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",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"fmt": "biome format --write ."
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@gajae-code/natives": "0.10.
|
|
39
|
-
"@gajae-code/utils": "0.10.
|
|
38
|
+
"@gajae-code/natives": "0.10.1",
|
|
39
|
+
"@gajae-code/utils": "0.10.1",
|
|
40
40
|
"lru-cache": "11.3.6",
|
|
41
41
|
"marked": "^18.0.3"
|
|
42
42
|
},
|
|
@@ -53,6 +53,35 @@ export function isNotificationSuppressed(): boolean {
|
|
|
53
53
|
return value === "off" || value === "0" || value === "false";
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
const MULTIPLEXER_DISABLED_ENV_VALUES = new Set(["0", "false", "off", "no"]);
|
|
57
|
+
|
|
58
|
+
function multiplexerEnvEnabled(value: string | undefined): boolean {
|
|
59
|
+
const normalized = value?.trim().toLowerCase();
|
|
60
|
+
return normalized !== undefined && normalized.length > 0 && !MULTIPLEXER_DISABLED_ENV_VALUES.has(normalized);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Returns whether the process runs under a terminal multiplexer (tmux, GNU
|
|
65
|
+
* screen, or zellij). Recognizes the same host markers as the renderer's
|
|
66
|
+
* multiplexer predicate in tui.ts so capability selection and viewport-repaint
|
|
67
|
+
* policy agree on what counts as a multiplexed host. Multiplexers intercept
|
|
68
|
+
* graphics escapes and OSC 8 hyperlinks instead of forwarding them to the
|
|
69
|
+
* outer terminal.
|
|
70
|
+
*/
|
|
71
|
+
export function isUnderTerminalMultiplexer(env: NodeJS.ProcessEnv = Bun.env): boolean {
|
|
72
|
+
if (
|
|
73
|
+
multiplexerEnvEnabled(env.TMUX) ||
|
|
74
|
+
multiplexerEnvEnabled(env.TMUX_PANE) ||
|
|
75
|
+
multiplexerEnvEnabled(env.STY) ||
|
|
76
|
+
multiplexerEnvEnabled(env.ZELLIJ) ||
|
|
77
|
+
multiplexerEnvEnabled(env.GJC_TMUX_LAUNCHED)
|
|
78
|
+
) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
const term = env.TERM?.trim().toLowerCase() ?? "";
|
|
82
|
+
return term.startsWith("tmux") || term.startsWith("screen");
|
|
83
|
+
}
|
|
84
|
+
|
|
56
85
|
let terminalGraphicsFallbackDepth = 0;
|
|
57
86
|
let cursorNeutralImageAllowedDepth = 0;
|
|
58
87
|
|
|
@@ -105,6 +134,15 @@ function getForcedImageProtocol(): ImageProtocol | null | undefined {
|
|
|
105
134
|
return null;
|
|
106
135
|
}
|
|
107
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Returns whether PI_FORCE_IMAGE_PROTOCOL explicitly configures the image
|
|
139
|
+
* protocol, including an explicit "off". An explicit configuration is
|
|
140
|
+
* authoritative: runtime capability probes must not override it.
|
|
141
|
+
*/
|
|
142
|
+
export function isImageProtocolForced(): boolean {
|
|
143
|
+
return getForcedImageProtocol() !== undefined;
|
|
144
|
+
}
|
|
145
|
+
|
|
108
146
|
function parseMajorMinorVersion(versionRaw?: string): { major: number; minor: number } | null {
|
|
109
147
|
if (!versionRaw) return null;
|
|
110
148
|
const match = /^(\d+)\.(\d+)/u.exec(versionRaw.trim());
|
|
@@ -137,7 +175,7 @@ function getFallbackImageProtocol(terminalId: TerminalId): ImageProtocol | null
|
|
|
137
175
|
if (!process.stdout.isTTY) return null;
|
|
138
176
|
if (terminalId === "vscode" || terminalId === "alacritty") return null;
|
|
139
177
|
const term = Bun.env.TERM?.toLowerCase() ?? "";
|
|
140
|
-
if (term.includes("
|
|
178
|
+
if (term.includes("ghostty")) {
|
|
141
179
|
return ImageProtocol.Kitty;
|
|
142
180
|
}
|
|
143
181
|
return null;
|
|
@@ -220,10 +258,10 @@ export const TERMINAL = (() => {
|
|
|
220
258
|
);
|
|
221
259
|
}
|
|
222
260
|
}
|
|
261
|
+
const underMultiplexer = isUnderTerminalMultiplexer();
|
|
223
262
|
// tmux and screen multiplexers do not reliably forward OSC 8 hyperlinks
|
|
224
263
|
// to the outer terminal, so force them off regardless of detected terminal.
|
|
225
|
-
|
|
226
|
-
if (resolved.hyperlinks && (Bun.env.TMUX || term.startsWith("tmux") || term.startsWith("screen"))) {
|
|
264
|
+
if (resolved.hyperlinks && underMultiplexer) {
|
|
227
265
|
resolved = new TerminalInfo(
|
|
228
266
|
resolved.id,
|
|
229
267
|
resolved.imageProtocol,
|
|
@@ -232,6 +270,17 @@ export const TERMINAL = (() => {
|
|
|
232
270
|
resolved.notifyProtocol,
|
|
233
271
|
);
|
|
234
272
|
}
|
|
273
|
+
// Multiplexers (tmux/screen/zellij) consume raw kitty/iTerm2 graphics
|
|
274
|
+
// escapes instead of forwarding them (no DCS passthrough wrapping is
|
|
275
|
+
// emitted), so a detected image protocol draws nothing while its
|
|
276
|
+
// out-of-band cursor writes corrupt the frame. Graphics are therefore
|
|
277
|
+
// unconditionally suppressed under a multiplexer; the runtime sixel probe
|
|
278
|
+
// never runs there (tmux advertises DA1 ";4" from compile-time support
|
|
279
|
+
// regardless of the attached client), and PI_FORCE_IMAGE_PROTOCOL=sixel
|
|
280
|
+
// is the only opt-in for chains that render sixel end-to-end.
|
|
281
|
+
if (resolved.imageProtocol && forcedImageProtocol === undefined && underMultiplexer) {
|
|
282
|
+
resolved = new TerminalInfo(resolved.id, null, resolved.trueColor, resolved.hyperlinks, resolved.notifyProtocol);
|
|
283
|
+
}
|
|
235
284
|
return resolved;
|
|
236
285
|
})();
|
|
237
286
|
|
|
@@ -239,11 +288,35 @@ type MutableTerminalInfo = {
|
|
|
239
288
|
imageProtocol: ImageProtocol | null;
|
|
240
289
|
};
|
|
241
290
|
|
|
291
|
+
type ImageProtocolChangeListener = (imageProtocol: ImageProtocol | null) => void;
|
|
292
|
+
const imageProtocolChangeListeners = new Set<ImageProtocolChangeListener>();
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Subscribe to runtime image-protocol changes (e.g. the asynchronous sixel
|
|
296
|
+
* capability probe enabling graphics after startup). Returns an unsubscribe
|
|
297
|
+
* function. Listeners fire only on actual changes.
|
|
298
|
+
*/
|
|
299
|
+
export function onImageProtocolChanged(listener: ImageProtocolChangeListener): () => void {
|
|
300
|
+
imageProtocolChangeListeners.add(listener);
|
|
301
|
+
return () => {
|
|
302
|
+
imageProtocolChangeListeners.delete(listener);
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
242
306
|
/**
|
|
243
307
|
* Override terminal image protocol at runtime after capability probes complete.
|
|
244
308
|
*/
|
|
245
309
|
export function setTerminalImageProtocol(imageProtocol: ImageProtocol | null): void {
|
|
246
|
-
|
|
310
|
+
const mutable = TERMINAL as unknown as MutableTerminalInfo;
|
|
311
|
+
if (mutable.imageProtocol === imageProtocol) return;
|
|
312
|
+
mutable.imageProtocol = imageProtocol;
|
|
313
|
+
for (const listener of imageProtocolChangeListeners) {
|
|
314
|
+
try {
|
|
315
|
+
listener(imageProtocol);
|
|
316
|
+
} catch {
|
|
317
|
+
// Listener failures must not break protocol switching.
|
|
318
|
+
}
|
|
319
|
+
}
|
|
247
320
|
}
|
|
248
321
|
|
|
249
322
|
export function getTerminalInfo(terminalId: TerminalId): TerminalInfo {
|
package/src/tui.ts
CHANGED
|
@@ -9,7 +9,14 @@ import { getKeybindings } from "./keybindings";
|
|
|
9
9
|
import { isKeyRelease } from "./keys";
|
|
10
10
|
import { renderMetrics } from "./metrics";
|
|
11
11
|
import type { Terminal } from "./terminal";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
ImageProtocol,
|
|
14
|
+
isImageProtocolForced,
|
|
15
|
+
isUnderTerminalMultiplexer,
|
|
16
|
+
setCellDimensions,
|
|
17
|
+
setTerminalImageProtocol,
|
|
18
|
+
TERMINAL,
|
|
19
|
+
} from "./terminal-capabilities";
|
|
13
20
|
import {
|
|
14
21
|
Ellipsis,
|
|
15
22
|
extractSegments,
|
|
@@ -217,7 +224,6 @@ function isTermuxSession(env: Record<string, string | undefined> = Bun.env): boo
|
|
|
217
224
|
return Boolean(env.TERMUX_VERSION);
|
|
218
225
|
}
|
|
219
226
|
|
|
220
|
-
const GJC_TMUX_LAUNCHED_ENV = "GJC_TMUX_LAUNCHED";
|
|
221
227
|
const DISABLED_ENV_VALUES = new Set(["0", "false", "off", "no"]);
|
|
222
228
|
const TRUTHY_ENV_VALUES = new Set(["1", "true", "yes", "on", "y"]);
|
|
223
229
|
|
|
@@ -231,25 +237,38 @@ function envFlagEnabled(value: string | undefined): boolean {
|
|
|
231
237
|
return normalized !== undefined && TRUTHY_ENV_VALUES.has(normalized);
|
|
232
238
|
}
|
|
233
239
|
|
|
234
|
-
function termLooksMultiplexed(value: string | undefined): boolean {
|
|
235
|
-
const term = value?.trim().toLowerCase() ?? "";
|
|
236
|
-
return term.startsWith("tmux") || term.startsWith("screen");
|
|
237
|
-
}
|
|
238
|
-
|
|
239
240
|
function isWindowsTerminalSession(env: Record<string, string | undefined> = Bun.env): boolean {
|
|
240
241
|
return envIsEnabled(env.WT_SESSION) || env.TERM_PROGRAM === "Windows_Terminal";
|
|
241
242
|
}
|
|
242
243
|
|
|
243
|
-
/**
|
|
244
|
+
/**
|
|
245
|
+
* Detect terminal multiplexers where scrollback clearing and height-change
|
|
246
|
+
* redraws are hostile. Delegates to the shared capability predicate so the
|
|
247
|
+
* renderer and graphics-protocol selection agree on what counts as a
|
|
248
|
+
* multiplexed host.
|
|
249
|
+
*/
|
|
244
250
|
function isMultiplexerSession(env: Record<string, string | undefined> = Bun.env): boolean {
|
|
245
|
-
return
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
251
|
+
return isUnderTerminalMultiplexer(env as NodeJS.ProcessEnv);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Startup sixel capability probe policy (pure; exported for tests):
|
|
256
|
+
* - Never probe when PI_FORCE_IMAGE_PROTOCOL is set — an explicit
|
|
257
|
+
* configuration (including "off") is authoritative.
|
|
258
|
+
* - Never probe inside a terminal multiplexer: tmux advertises DA1 ";4"
|
|
259
|
+
* whenever it was compiled with sixel support, regardless of whether the
|
|
260
|
+
* attached client terminal can render sixel, so a positive reply is not
|
|
261
|
+
* end-to-end evidence. Graphics under a multiplexer are strictly opt-in
|
|
262
|
+
* via PI_FORCE_IMAGE_PROTOCOL=sixel.
|
|
263
|
+
* - Probe Windows Terminal (>=1.22 renders sixel but exposes no env marker).
|
|
264
|
+
*/
|
|
265
|
+
export function shouldProbeSixelCapability(
|
|
266
|
+
env: NodeJS.ProcessEnv = Bun.env,
|
|
267
|
+
platform: NodeJS.Platform = process.platform,
|
|
268
|
+
): boolean {
|
|
269
|
+
if (isImageProtocolForced()) return false;
|
|
270
|
+
if (isUnderTerminalMultiplexer(env)) return false;
|
|
271
|
+
return platform === "win32" && Boolean(env.WT_SESSION?.trim());
|
|
253
272
|
}
|
|
254
273
|
|
|
255
274
|
function useLegacyMultiplexerFullRender(env: Record<string, string | undefined> = Bun.env): boolean {
|
|
@@ -1008,8 +1027,7 @@ export class TUI extends Container {
|
|
|
1008
1027
|
|
|
1009
1028
|
#querySixelSupport(): void {
|
|
1010
1029
|
if (TERMINAL.imageProtocol) return;
|
|
1011
|
-
if (
|
|
1012
|
-
if (!Bun.env.WT_SESSION) return;
|
|
1030
|
+
if (!this.#isSixelProbeCandidate()) return;
|
|
1013
1031
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return;
|
|
1014
1032
|
|
|
1015
1033
|
this.#clearSixelProbeState();
|
|
@@ -1023,6 +1041,10 @@ export class TUI extends Container {
|
|
|
1023
1041
|
}, 250);
|
|
1024
1042
|
}
|
|
1025
1043
|
|
|
1044
|
+
#isSixelProbeCandidate(): boolean {
|
|
1045
|
+
return shouldProbeSixelCapability();
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1026
1048
|
#handleSixelProbeInput(data: string): InputListenerResult {
|
|
1027
1049
|
if (!this.#sixelProbePendingDa && !this.#sixelProbePendingGraphics) {
|
|
1028
1050
|
return undefined;
|
|
@@ -1049,11 +1071,15 @@ export class TUI extends Container {
|
|
|
1049
1071
|
|
|
1050
1072
|
if (useDa && this.#sixelProbePendingDa) {
|
|
1051
1073
|
this.#sixelProbePendingDa = false;
|
|
1052
|
-
const
|
|
1074
|
+
const params = (match[1] ?? "")
|
|
1053
1075
|
.split(";")
|
|
1054
1076
|
.map(value => Number.parseInt(value, 10))
|
|
1055
1077
|
.filter(value => Number.isFinite(value));
|
|
1056
|
-
|
|
1078
|
+
// The first DA1 parameter is the device/operating class (e.g. 1,
|
|
1079
|
+
// 62, 64), not an extension attribute: `CSI ?4;6c` identifies a
|
|
1080
|
+
// VT132, it does not advertise sixel. Only the parameters after
|
|
1081
|
+
// the class carry attributes like 4 (sixel graphics).
|
|
1082
|
+
const hasSixelAttribute = params.slice(1).includes(4);
|
|
1057
1083
|
if (hasSixelAttribute) {
|
|
1058
1084
|
this.#sixelProbePendingGraphics = false;
|
|
1059
1085
|
probeOutcome = true;
|
|
@@ -1062,8 +1088,11 @@ export class TUI extends Container {
|
|
|
1062
1088
|
}
|
|
1063
1089
|
} else if (!useDa && this.#sixelProbePendingGraphics) {
|
|
1064
1090
|
this.#sixelProbePendingGraphics = false;
|
|
1091
|
+
// XTSMGRAPHICS reply is `CSI ? 2 ; Ps ; ... S` where Ps=0 means
|
|
1092
|
+
// success and 1/2/3 are errors (tmux answers our unsupported
|
|
1093
|
+
// read with `CSI ?2;3;0S`). Only a success reply proves sixel.
|
|
1065
1094
|
const status = Number.parseInt(match[1] ?? "", 10);
|
|
1066
|
-
const supportsSixel =
|
|
1095
|
+
const supportsSixel = status === 0;
|
|
1067
1096
|
if (supportsSixel) {
|
|
1068
1097
|
this.#sixelProbePendingDa = false;
|
|
1069
1098
|
probeOutcome = true;
|