Repository navigation
Startup probe and image delivery: end on DA1, never type a late reply, resend undelivered uploads - #533
Draft
raiseCatError wants to merge 3 commits into
Conversation
… reply The probe always waited a fixed 80 ms. A slower reply (SSH, a busy Mac) reached the key decoder, which turned Kitty's APC graphics reply into Escape + '_Gi=31;OK\' + Escape: the text was typed and the key stopped the welcome as character art; in Ghostty images stayed character art for the session. - DA1 is the last query and ends the probe as soon as it answers; a slow terminal gets up to 750 ms; a timer that fires late lets waiting input in. - Replies after that are taken out of the input for 10 s and a late graphics OK still enables native images. - The key decoder never decodes a Kitty graphics reply as keys, even split.
TerminalRenderer.sendRaw drops bytes before NMSh has entered the screen (and while suspended), but GraphicsService recorded the Kitty upload anyway: a welcome image that loaded during startup was drawn as empty placeholder cells for the whole session. sendRaw now reports whether it wrote; an undelivered upload is not recorded and the next paint sends it. Review follow-ups: a held start of a graphics reply is short (64) and is flushed on the Escape pause like a lone ESC; a late DA1 or pixel-size reply is removed too, so it never reaches a program that has the screen.
…ered renderer Found in Ghostty with replies delayed 1.5 s: a late graphics OK called renderer.setCapabilities after entry, which throws, and NMSh exited. Images read the live host capabilities, so that call was not needed.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #532.
Bug (reproduced in Kitty 0.49.2 with a relay that delays the terminal's replies by 0.3 s or 1.5 s): the startup probe always waited a fixed 80 ms. A later Kitty graphics reply reached the key decoder as Escape, then the text
_Gi=31;OK\, then another Escape. The text was typed into the composer, and the key press stopped the welcome as character art. In Ghostty, which has no graphics hint, the session would draw every image as character art. Any SSH session or busy Mac hits this.Fix
src/terminal/TerminalRenderer.tsandsrc/graphics/service.ts(commit 2):sendRawdrops bytes before NMSh has entered the screen, but the service still recorded the Kitty upload. A welcome image that loaded during startup was then drawn as empty placeholder cells for the whole session. The longer probe wait in commit 1 made this race likely: it was blank at a 1.5 s delay. Undelivered uploads are no longer recorded, so the next paint sends them.src/host/probe.ts: DA1 is now the last query (DISPLAY_QUERYreordered) and ends the probe as soon as it answers, so there's no fixed wait. A slow terminal gets up to 750 ms (HOST_PROBE_REPLY_TIMEOUT_MS). A timer that fires late, after a blocked event loop, first lets waiting input in. The result haspendingwhen the end marker didn't arrive.takeLateProbeRepliesplusTerminalApp: for 10 s after a pending probe, late id-31 graphics replies are removed from the input, and a lateOKturns native images on and repaints. The window closes when DA1 arrives.src/terminal/keys.ts: a complete Kitty graphics reply (ESC _ G … ST) is never decoded as keys, and an incomplete one at the end of a read is held until it completes.Tests
renderer.setCapabilitiesafter the renderer had entered the screen; that throws, and NMSh exited. The fix updates only the live host capabilities. Regression test intests/hostProbeExtended.test.ts: it fails on commit 2 and passes now (33/33 related).tests/graphicsService.test.ts(an undelivered upload is sent again) andtests/keys.test.ts(a held partial reply is flushed like Escape). Both fail without the fix.tests/hostProbeExtended.test.tscover the end marker, the early finish, the late reply as evidence, and that the reply is never typed.tests/keys.test.tscovers a whole reply and one split across reads.tscis clean. The full suite is left to CI.Physical QA (disposable Kitty, private HOME and Kitty config, Auto graphics,
slow-relay.py):Results are judged by screenshot pixels in the logo area, not by placeholder counts. Placeholder cells can be present while the picture is missing.
c3620236_Gi=31;OK\typed_Gi=31;OK\typed/appearanceopenNothing was typed in any of the commit 2 runs.
Ghostty 1.3.1, isolated instance (
--config-default-files=false, private HOME); screenshots in the contact sheetshots/gm-sheet.png:c3620236: the welcome is character art even with no delay. With 0.3 s or 1.5 s it says "This terminal did not confirm a graphics protocol", and_Gi=31;OK\is typed into the composer./appearance(the QA driver's typed text was garbled in Ghostty, so those shots don't count).Not tested: Ghostty physically, and a terminal that never answers DA1. That terminal would wait 750 ms once at startup instead of 80 ms.