import { SchemaResolver, KindStreamEvent, IrTreeNode } from './core.js'; import { CanonicalBlockIR } from './core.js'; import { KindSchema } from './core.js'; /** * ParseSession — one live region parse per stream identity. * * Owns the parser + IrTree OUTSIDE React and Redux. Writers push chunks; * N readers subscribe per path (useIrNode / selectors) and are notified on * the host's flush cadence — never per token. * * Notification contract: `write()`/`end()` never notify. The host (demo rAF * loop, process-stream's dispatchBatch tick) calls `flushNotify()` to publish * dirty paths. Late schema arrivals (registry cold fetch) notify themselves — * they happen outside any streaming tick. */ interface ParseSessionOptions { identity: string; schemas: Record | SchemaResolver; expectedRootKind?: string; /** * Registry hook: subscribe to cold-fetch answers, return an unsubscribe. * The session forwards arrivals into the parser (upgrade-in-place) and * notifies affected readers immediately. */ onSchemaArrived?: (deliver: (kind: string, schema: KindSchema | null) => void) => () => void; /** Observe every parser event (demo inspector, telemetry). */ onEvent?: (event: KindStreamEvent) => void; } type Listener = () => void; declare class ParseSession { readonly identity: string; private readonly parser; private readonly tree; private readonly listeners; private readonly anyListeners; private readonly unsubscribeSchemaArrivals; private readonly fingerprinter; private ended; constructor(options: ParseSessionOptions); /** The single writer's input. Does NOT notify — host flushes on its cadence. */ write(chunk: string): void; end(): void; get isEnded(): boolean; get status(): "streaming" | "complete" | "error"; getNode(pathKey: string): IrTreeNode | null; listNodes(): IrTreeNode[]; isRawPath(pathKey: string): boolean; subscribe(pathKey: string, listener: Listener): () => void; /** Structural subscription: fires when ANY node changes (mount lists). */ subscribeAny(listener: Listener): () => void; /** Publish dirty paths to their readers. Host-cadence, coalesced. */ flushNotify(): void; buildEnvelope(): CanonicalBlockIR; dispose(): void; } /** * Session manager — one writer per stream identity, N readers, mechanically * enforced: a second `openParseSession` for a live identity THROWS. Readers * resolve sessions by identity and never gain write access. * * Identities: `"{requestId}:{blockId}"` for agent-stream regions; any unique * string for other hosts (demo runs, notes, one-shot upgrades). * * Ended sessions stay resolvable for late readers (reload happens via the * persisted envelope, but in-session remounts read here) until disposed. */ declare function openParseSession(options: ParseSessionOptions): ParseSession; declare function getParseSession(identity: string): ParseSession | null; declare function disposeParseSession(identity: string): void; export { ParseSession, disposeParseSession, getParseSession, openParseSession }; export type { ParseSessionOptions };