/** * The v2 event feed — the seam `tm_join`'s settle detection was missing (#8). * * v1 handed the plugin a host `event` hook and `src/host/v1.ts` pumped every * `session.idle` / `session.error` / `session.status` into * `tmRuntime.observeDispatchEvent`. The v2 personality never subscribed to * anything, so on 2.x the child registry learned nothing: a child that finished * two seconds after the dispatch stayed "running" for the whole `waitMs` budget, * `tm_join` answered 仍在运行 about a session that had already settled, and the * lead's second wait was cut short by a streak counter that was measuring our own * deafness. That is goal #6's failure shape — a tool reporting a state it never * observed — and it was a bug, not a limitation. * * `ctx.event.subscribe()` is an async iterable on the Promise-based plugin API: * measured on a live 2.0.16 (docs/research/agent-data-exchange.md), with no Effect * runtime and no new dependency. Two properties of it are load-bearing here: * * · the stream is SERVER-WIDE. Every session on the host appears in it, so the * feed forwards only event types on the whitelist below and the dispatcher * ignores any session id it has no record of — the plugin never reads a * stranger's session state into our context or trajectory. * · event NAMES changed wholesale between generations. So the whitelist is a * living list with a counter behind it: an unseen type is counted and stays * unseen, rather than being forwarded on a guess or swallowed silently. After * the next host upgrade, `tm_stats` is where the renamed events show up. * * Nothing in here may break a session: every subscription and iteration step is * wrapped, and a stream that throws ends the feed with a recorded reason instead * of an exception in the host's event loop. */ import type { HostEvent } from "../types.js"; import type { V2Registration } from "./v2-types.js"; /** The types the dispatcher understands, plus the v2 spellings we have observed. * Anything else is counted, not forwarded. * * The `session.execution.*` entries are the 2.0.28 spellings, read off a live * `v2-surface` row's `event_unknown_types` (measured, not guessed): the host * publishes `session.execution.succeeded` / `.failed` / `.interrupted` where * older generations said `session.idle` / `session.error`. They are listed * because they were observed; a name we have not seen still stays counted. */ export declare const FEED_TYPES: readonly ["session.idle", "session.error", "session.status", "session.statused", "session.updated", "session.execution.succeeded", "session.execution.failed", "session.execution.interrupted"]; export interface V2EventFeedReport { /** subscribe() existed and returned something iterable */ active: boolean; received: number; forwarded: number; /** type → count, for every type we did not recognise (names only, no payload) */ unknown: Record; /** what killed the loop, if anything — the difference between "no events" and * "we stopped listening" */ stopped?: string; } export interface V2EventFeed { readonly report: V2EventFeedReport; registrations: V2Registration[]; stop: () => Promise; } export declare function applyV2EventFeed(ctx: unknown, opts: { onEvent: (event: HostEvent) => void; types?: readonly string[]; onError?: (data: unknown) => void; onIdle?: (sessionID: string) => void; onRetryScheduled?: (data: unknown) => void; }): Promise; //# sourceMappingURL=v2-events.d.ts.map