Repository navigation
fix(channel): fail workspace calls fast when the workspace host stops answering - #376
Merged
Merged
Conversation
… answering A frozen or unreachable workspace host kept its socket attached, so the instructions prompt section waited on AGENTS.md reads and blocked model-only runs until the host returned (#372). - Hosts ping the workspace socket every 5s; the hosted object answers through setWebSocketAutoResponse, so hibernation still works. - Link treats a socket whose last ping is older than three intervals as not responding: new calls fail at once and calls in flight fail (with a cancel sent for when the host resumes). - The instructions section throws when the workspace can't be read, so pi keeps the last-shown instructions and reports why, instead of dropping them. - Hosts reconnect when a service that has answered pings misses three. Hosts that predate pings have no auto-response timestamp and are treated as answering, as before. An older service ignores the ping frame, and a host only watches for pongs once one has arrived. Why: packages/channel/src/workspace.ts#class Link | a socket with no auto-response timestamp belongs to a host that predates pings and must never be declared stale Why: packages/channel/src/workspace.ts#const PING | PING and PONG are matched byte-for-byte by setWebSocketAutoResponse and must stay JSON objects an older Link.receive ignores Why: packages/channel/src/context.ts#function absent | only a missing file means no instructions; any other read failure must throw so pi keeps the last-shown section Why: apps/host/src/workspace.ts#function link | staleness counts unanswered pings, not elapsed time, so a host resuming from sleep does not drop a live socket, and only after a first pong so older services are not reconnected forever
This was referenced Oct 15, 2026
This was referenced Oct 15, 2026
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.
Fixes #372.
A frozen or unreachable workspace host kept its socket attached to the hosted channel, so the
instructionsprompt section waited on AGENTS.md reads and blocked model-only runs until the host returned.{"ping":true}on the workspace socket every 5s. The object answers{"pong":true}throughsetWebSocketAutoResponse, so hibernation is unaffected.Linktreats a socket whosegetWebSocketAutoResponseTimestampis older than 15s (three intervals) as not responding. New calls fail immediately with "The workspace is not responding". Calls already in flight fail on a watchdog that runs only while calls are pending, and each one gets a cancel for when the host resumes. Desktop and browser actions are refused without being dispatched.instructionsnow treats only a missing file or directory as absent. Any other read failure throws, so pi keeps the instructions it last showed and reports the error, where before it silently dropped them.Compatibility
Link.receiveignores. No pong comes back, so the host never starts watching for pongs. This was not run, only read from the code.ace-channel-studyneeds a redeploy from main to get liveness.Smoke test (
wrangler devplus a source host on its own port and data dir,openai/gpt-4.1-mini, with an AGENTS.md instruction the model has to follow):SIGSTOPof the host: answered in 16s. The pending read failed at the stale mark, and the kept instructions still applied.SIGCONT: tools worked again on the same socket, with no reconnect.SIGSTOPof workerd: the host loggedworkspace.drop(stale) about 16s later and reconnected afterSIGCONT. Tools worked afterward.Built in Ace
No — built with Claude Code outside Ace by an overnight issue watcher, because this Mac's Ace Canary is a participant in the running two-person study (#218); dogfooding gap tracked in #5.