fix(terminal): start PTY before viewport mounts without dropping output or startup replies

Terminal creation no longer waits for the Ghostty viewport to report its
size: it starts the PTY immediately with a container/font-derived
provisional size (falling back to 80x24), then resizes once the real
viewport dimensions are known, with a dedupe guard while sizing settles.

Starting the shell earlier means it can emit device/theme queries before
a browser terminal is attached to answer them, so the server now answers
primary device attribute queries itself (Fish blocks ~10s on this at
startup) and bun-pty buffers output emitted before a data subscriber
attaches. Also fixes a few WebSocket transport reconnect races surfaced
by session creation now overlapping renderer setup.
This commit is contained in:
Serhii Dziupin
2026-08-03 12:29:32 +03:00
parent aa1875b6f0
commit 88937ade72
12 changed files with 421 additions and 99 deletions
@@ -44,4 +44,27 @@ describe('terminal theme responses', () => {
'\u001b]10;rgb:1b1b/1b1b/1b1b\u001b\\',
]);
});
test('answers a primary device attribute query when the fallback is enabled', () => {
const attached = consumeTerminalThemeQueries('', '\u001b[0c', lightAppearance);
const unattached = consumeTerminalThemeQueries('', '\u001b[0c', lightAppearance, {
respondToPrimaryDeviceAttributes: true,
});
expect(attached.responses).toEqual([]);
expect(unattached.responses).toEqual(['\u001b[?1;2c']);
});
test('answers a primary device attribute query split across PTY chunks', () => {
const first = consumeTerminalThemeQueries('', '\u001b[0', lightAppearance, {
respondToPrimaryDeviceAttributes: true,
});
const second = consumeTerminalThemeQueries(first.pending, 'c', {
...lightAppearance,
modeEnabled: first.modeEnabled,
}, { respondToPrimaryDeviceAttributes: true });
expect(first.pending).toBe('\u001b[0');
expect(second.responses).toEqual(['\u001b[?1;2c']);
});
});