Say when a session's machine is offline, and keep its last screen - #168
Merged
Merged
Conversation
A viewer could be perfectly connected to a session whose machine was not there, and be shown nothing at all. The relay has always reported the machine's state on every status message; neither client acted on it. The standalone page dimmed a dot in the header to "Offline" and left the terminal blank, and the app pane ignored every status except "exited", so it stayed on "connected" and drew an empty screen with no banner. Both read as a terminal that failed to load rather than a laptop that closed. Reproduced with a session whose host was killed outright: it lives on the relay for its remaining twelve hours, and every viewer since gets a blank page. That is what a reboot, a lid, a dead battery or a lost network looks like from the browser today. Both surfaces now say it, in the same words, from one module: - The relay reports hostLastSeenAt and lastScreenAt alongside the status. - The relay keeps the last full screen a host sent, chunked under one storage prefix because a snapshot is larger than a Durable Object value, and replays it to a viewer that arrives while the machine is away. For an encrypted session those bytes are ciphertext it cannot read: the opcode is authenticated as associated data, so the frame is stored and replayed untouched. It goes with the session when that expires. - A host only produces a screen when asked, so the alarm asks for one every five minutes on behalf of viewer 0, which no viewer is. That caps how stale a kept screen can be at the cost of one snapshot per five minutes of a live session. Writes are throttled so a room filling up does not write one per person arriving. - The notice says which it is: waiting for a machine that has never connected, or temporarily offline with when it was last seen and how old the screen below it is. A kept screen is dimmed so it cannot be mistaken for a live one, and it all clears itself when the machine comes back. Verified end to end against a local relay: a live session renders, a SIGKILLed host turns the open viewer's screen into a dated kept screen with the notice, a viewer arriving afterwards gets both where it used to get a blank page, and a restarted persistent host clears the notice and goes live.
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.
The bug
A viewer can be perfectly connected to a session whose machine is not there, and be shown nothing at all.
Reported as "the terminal fails to appear, both in the app and in the standalone link". Reproduced on
https://shell.online/s/2cMN…: the relay says{"exists":true,"status":"disconnected"}, two viewers are attached, the header dims a dot to "Offline", and the terminal area is a blank white rectangle with no explanation. The machine hosting it had rebooted; the session lives on the relay for the rest of its twelve hours, so every viewer since gets that page.The relay has always reported the machine's state on every status message. Neither client acted on it:
handleControlread onlystatus === "exited"and dropped the rest, so the pane stayed onconnectedand drew an empty terminal with no banner at all.That is what a reboot, a closed lid, a flat battery or a lost network looks like from the browser today.
The fix
One module,
shared/host-presence.ts, vendored into the app the wayprotocol.tsandterminal-grid.tsalready are, so both surfaces say the same thing in the same words.Relay (
worker/index.ts)hostLastSeenAtandlastScreenAtalongside the status.Both viewers
Retention note
The relay now holds the last screen of each session, encrypted and unreadable by it, for as long as that session exists (12 hours, or 30 days for a persistent one). For a
--no-e2eesession those bytes are plaintext, which is the tradeoff that flag already makes in flight.Verification
Unit:
tests/host-presence.test.ts(9) for the copy and the elapsed-time wording, and four cases inapp/src/terminal/connection.test.tsfor the status mapping. The connection tests fail onmainand pass here.End to end against a local relay and a real CLI:
SIGKILLed — the open viewer keeps its screen, dimmed, under "Temporarily offline… last seen just now".Checked in both themes and in the app pane as well as the standalone page.
No CLI change, so no release is needed;
cmd/andinternal/are untouched.