Add hibernatable WebSockets - #37
Merged
Merged
Conversation
Capture the pinned runtime's acceptance, attachment, dispatch, close, auto-response, timeout, tag, and eviction behavior before changing do-runtime. The shared host now exposes connection and eviction affordances so the same oracle spec can drive the Node and browser implementations.
Exercise host mirroring, constructor-visible rehydration, socket lifecycle, quiescence, and gate hook injection through the public container surface. These tests intentionally fail on the current throwing stubs before implementation begins.
Replace the fail-closed state stubs with runtime-owned WebSocketPair endpoints, attachment and tag storage, class-handler dispatch, auto responses, and close-state handling. Add the mirror-out HibernationHost and pre-constructor rehydration option so an embedder can rebuild a container without reconnecting a live client. Node and browser lane hosts now exercise that same lifecycle, including a real eviction-and-wake cycle.
Remove the hibernate:false overrides and the duplicate in-memory WebSocketPair now that the runtime supplies both. Keep only the embedder-owned Response 101 adapter, and teach the MessagePort bridge to announce socket halves that are already OPEN so Agents RPC does not wait forever for a synthetic open event.
Describe the host mirror and rehydration handoff, the non-blocking quiescence signal, and the measured pair and close semantics. Record the breaking API replacement as a minor changeset for the 0.5.0 release.
Represent socket acceptance and delivery as explicit states so registry-dependent behavior cannot exist without its registry. Route raw listeners through the current registry after a hibernation rebuild, and keep attachment serialization local after close instead of calling a host that no longer owns the socket. Reuse Workers platform types and one conformance mirror to remove duplicated adapters and unsafe casts.
The hibernation contract was covered by conformance embedders, but the copyable MV3 host still did not preserve an Agents connection when its root container was replaced. Share the in-memory mirror with the extension, rebuild placements from its snapshot, and prove the same AgentClient can receive and send state after eviction. That lifecycle exposed a timer bookkeeping bug: a host may model cancel-by-drop with an unsettled delay promise, leaving a cleared interval permanently counted in waitUntil. Settle the runtime-owned cancellation race and pin it with a regression so quiescence remains a truthful eviction signal. Document the same-Worker boundary explicitly: container replacement rehydrates, while Worker or offscreen destruction removes the raw transport and reconnects.
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.
Why
Rook currently pins Agents to non-hibernating sockets because the TypeScript runtime could not preserve a live transport across actor eviction. This ports the observable Cloudflare Durable Objects WebSocket hibernation contract, with workerd as the oracle, so embedders can evict idle actors without reconnecting their clients.
This release unblocks the Rook host cutover that depends on socket rehydration and explicit quiescence.
What changed
WebSocketPair, all Durable Object WebSocket state methods, tags, structured-clone attachments, auto-responses, event timeouts, close/error/message dispatch, and actor-scoped globals.ActorContainer.quiescence()for eviction decisions and gate hooks for embedder observability.AgentClientremains readable and writable across root-container eviction.waitUntilbookkeeping even when the host cancels by leaving its delay promise unsettled.Verification
check:package: greencheck:oracle: greenRelease
The included Changeset publishes
@mcp-b/do-runtimeas the next minor (0.6.0).