ai slop but still true:
Describe the bug
Setting any static options on an Agent subclass silently disables hibernation.
Agent.options defaults hibernate: true, and the docs state that "Child classes can override specific options without spreading" (dist/index.js:285, and in the shipped .d.ts:3050). But a subclass static replaces the inherited object rather than merging, and partyserver selects the connection manager from the raw static with no defaulting:
// partyserver@0.5.9 dist/index.js:546,549
static options = { hibernate: false };
#ParentClass = Object.getPrototypeOf(this).constructor;
#connectionManager = this.#ParentClass.options.hibernate
? new HibernatingConnectionManager(this.ctx)
: new InMemoryConnectionManager();
So static options = { sendIdentityOnConnect: false } leaves hibernate === undefined → InMemoryConnectionManager. Meanwhile _resolvedOptions (agents dist/index.js:461) does apply the default, so the SDK still reports hibernate: true. Two layers read the same static; only the one that doesn't pick the connection manager defaults it.
This is especially easy to hit because the SDK itself recommends the offending line. agents dist/index.js:957 warns:
[Agent] ${ctor.name}: sending instance name "${this.name}" to clients via sendIdentityOnConnect ... If this name is sensitive, add static options = { sendIdentityOnConnect: false } to opt out.
Following that advice, to fix a stated privacy concern, silently turns off hibernation.
To Reproduce
Steps to reproduce the behavior:
- Define an Agent subclass that overrides a single option without spreading, exactly as the docs describe:
class MyAgent extends Agent {
static options = { sendIdentityOnConnect: false };
}
- Connect a WebSocket to it.
- Inspect
MyAgent.options.hibernate — it is undefined, so partyserver constructs an InMemoryConnectionManager and accepts via connection.accept() instead of ctx.acceptWebSocket(...).
- Note that
_resolvedOptions.hibernate still reports true, so nothing surfaces the mismatch.
- Add
hibernate: true back into the same object and the HibernatingConnectionManager is selected again.
Expected behavior
Overriding one option should leave the others at their documented defaults, so hibernate stays true unless explicitly set to false. At minimum, _resolvedOptions and the connection-manager selection should agree.
Screenshots
N/A.
Version:
agents@0.20.1 with partyserver@0.5.9. Also present in agents@0.19.0 / partyserver@0.5.8 — the relevant partyserver lines are unchanged between the two.
Additional context
The impact is silent and billing-related rather than functional: HibernatingConnectionManager.accept calls ctx.acceptWebSocket(...), while InMemoryConnectionManager.accept calls connection.accept(), so the Durable Object stays resident for the life of every WebSocket and bills wall-clock duration while idle. There is no error, and the SDK's own resolved options report the opposite.
Suggested fix: merge subclass statics into the defaults at class-definition time, so the raw options object partyserver reads is always complete — which is what the docs already promise. A dev-mode warning when options is set without hibernate would also catch it cheaply.
ai slop but still true:
Describe the bug
Setting any
static optionson anAgentsubclass silently disables hibernation.Agent.optionsdefaultshibernate: true, and the docs state that "Child classes can override specific options without spreading" (dist/index.js:285, and in the shipped.d.ts:3050). But a subclass static replaces the inherited object rather than merging, andpartyserverselects the connection manager from the raw static with no defaulting:So
static options = { sendIdentityOnConnect: false }leaveshibernate === undefined→InMemoryConnectionManager. Meanwhile_resolvedOptions(agents dist/index.js:461) does apply the default, so the SDK still reportshibernate: true. Two layers read the same static; only the one that doesn't pick the connection manager defaults it.This is especially easy to hit because the SDK itself recommends the offending line.
agents dist/index.js:957warns:Following that advice, to fix a stated privacy concern, silently turns off hibernation.
To Reproduce
Steps to reproduce the behavior:
MyAgent.options.hibernate— it isundefined, sopartyserverconstructs anInMemoryConnectionManagerand accepts viaconnection.accept()instead ofctx.acceptWebSocket(...)._resolvedOptions.hibernatestill reportstrue, so nothing surfaces the mismatch.hibernate: trueback into the same object and theHibernatingConnectionManageris selected again.Expected behavior
Overriding one option should leave the others at their documented defaults, so
hibernatestaystrueunless explicitly set tofalse. At minimum,_resolvedOptionsand the connection-manager selection should agree.Screenshots
N/A.
Version:
agents@0.20.1withpartyserver@0.5.9. Also present inagents@0.19.0/partyserver@0.5.8— the relevantpartyserverlines are unchanged between the two.Additional context
The impact is silent and billing-related rather than functional:
HibernatingConnectionManager.acceptcallsctx.acceptWebSocket(...), whileInMemoryConnectionManager.acceptcallsconnection.accept(), so the Durable Object stays resident for the life of every WebSocket and bills wall-clock duration while idle. There is no error, and the SDK's own resolved options report the opposite.Suggested fix: merge subclass statics into the defaults at class-definition time, so the raw
optionsobjectpartyserverreads is always complete — which is what the docs already promise. A dev-mode warning whenoptionsis set withouthibernatewould also catch it cheaply.