Replies: 1 comment
|
Verified every claim against current master (49a606b, the alpha.5 line) — your report is accurate. This is the seventh independent report of this exact gap, and yours is the cleanest statement of it so far. Some context that changes the calculus, plus a refinement of your Option 1: 1. One naming evolution on the read side. 2. Seven independent authors, and the deferral's precondition is saturated. Lineage, all out-of-repo plugin authors hitting the same wall: #1538 (2026-08-14), #1584 (2026-08-15), #1619 (2026-08-15), #2778 (2026-08-17), #3191 (2026-08-18), #5463 (2026-09-02, workspace-restore), and now #5474. Yours is the first to document the removal casualty (the event deleted from 3. Request 2 is the option ruled out by design — your own quote contains the reason. The known-event set is generated from in-repo 4. Request 1 is right — and the refined shape already exists. In #5463 (same week, same gap, a workspace-restore plugin author) we converged on a merge-extensible append<T extends SessionEventType>(
type: T,
data: SessionEventMap[T],
...opts: T extends SurfaceEventType
? [opts: SurfaceIntent]
: T extends keyof IgnorableSessionEventMap
? [opts?: { ignorable: true }]
: []
): SessionEvent<T>Runtime is a passthrough — append is the only envelope producer (declaration merging erases at runtime), so the change is roughly: opts tuple + envelope passthrough + the mergeable map + two regression tests. The read side stays untouched and fail-closed (it already honours 5. Interim pattern until the channel reopens. antst's #5463 workaround is the safe one: encode the durable structured fact as a flat first-party event (e.g. |
Uh oh!
There was an error while loading. Please reload this page.
Summary
A downstream (out-of-repo) plugin cannot emit a custom session event type without making every session it touches unloadable after a restart. The persistence read path refuses unknown event types unless the envelope carries
ignorable: true, butSession.appendoffers no way to set that marker, and the known-event set is built from the harness repository's ownSessionEventMapmerges. The deferred "registration surface for downstream plugin events" now has a consumer.Observed (harness packages
0.1.0-rc.5, session format version 0)@deepseek-ai/dsh-session-persistenceassertEventsSupported: for every stored event,KNOWN_SESSION_EVENT_TYPES.has(event.type) || event.ignorable === true, otherwise it throwsSessionFormatUnsupportedError: session "…" contains event type "…" (seq N) unknown to this harness and not marked ignorable; refusing to interpret the log.@deepseek-ai/dsh-sessionknown-event-types.d.ts: the set is "everySessionEventMapmember declared in this repository"; "downstream (out-of-repo) plugin events are outside this list by construction; a registration surface for them is deferred until such a consumer exists."@deepseek-ai/dsh-sessionappend(type, data, ...opts): builds{ type, seq, time, data, ...surfaceMetadata }; the only caller-supplied metadata issourceEventSeqs/surfaceOpfor surface events.ignorablecannot be set by a caller.@deepseek-ai/dsh-web-search-deepseekprovider appendsweb/deepseek-search-llm-requestbefore each search request; itsdeclare module '@deepseek-ai/dsh-session/types'merge lands in the harness build, so its event is known.Reproduction
ctx.get('agents')?.currentInitiator()?.session.append('example/custom-event', { ok: true })(the same mechanism the DeepSeek search provider uses).
session.historyreads fine while the session is in memory.SessionFormatUnsupportedError … event type "example/custom-event" … not marked ignorable; history and resume both fail for that session.We hit this with
@apexphere/dsh-web-search-anthropic, a WebSearchProvider mirroring the DeepSeek provider's request event; we have removed the event from that package because no safe shape exists for it today.Request (either would resolve it)
append({ ignorable: true }) that sets the envelope field the reader already honours; orSessionEventMapmerges feedKNOWN_SESSION_EVENT_TYPES), so downstream events participate in the same read-side validation as first-party ones.Option 1 is the smaller change and matches the envelope contract's own description of
ignorableas the guard for vocabulary growth.All reactions