import type { VoicePacket } from "./packets.js"; export declare enum Route { Critical = 0,// interrupts, turn changes — drained first, never bounded Main = 1,// pipeline flow: audio in, STT results, LLM deltas, TTS audio Background = 2 } export type PacketHandler = (pkt: T) => void | Promise; export interface PipelineBus { /** Push one or more packets into a priority route. */ push(route: Route, ...packets: T): void; /** * Register a handler for a specific packet kind. Returns unsubscribe function. * * By default handlers are awaited in registration order (consumer semantics — the * handler's state mutations are visible to the next packet's handlers). Pass * `{ concurrent: true }` for a long-running PRODUCER handler (e.g. an LLM-generation * loop that emits its own packets over time): it is dispatched fire-and-forget so it * does not park the drain loop and defer subsequent Main packets / Critical interrupts * behind it. Concurrent handler errors are surfaced as `pipeline.error`, like async packets. */ on(kind: T["kind"], handler: PacketHandler, opts?: { concurrent?: boolean; }): () => void; /** Start draining the bus. Resolves when stop() is called and final drain completes. */ start(): Promise; /** Stop draining. Flushes Critical+Main, discards Background. */ stop(): void; /** Readonly stream of every packet pushed into the bus, before route dispatch. */ readonly allPackets: ReadableStream<{ route: Route; packet: VoicePacket; }>; } /** * Configuration for PipelineBusImpl. * Critical is always unbounded. Main and Background can be configured. */ export interface PipelineBusConfig { /** Maximum Main queue size. Default 4096. Throws on overflow. */ mainCapacity?: number; /** Maximum Background queue size. Default 2048. Drops oldest on overflow. */ bgCapacity?: number; /** Maximum Critical packets to batch per tick before yielding to I/O. Default 4. */ criticalBatchSize?: number; /** Called when a Background packet is dropped. For metrics emission. */ onBackgroundDrop?: (dropped: VoicePacket) => void; /** * Observe how long each packet waited between push and dispatch. Diagnostic only — * a handler awaiting long I/O parks the drain loop, and packet `timestampMs` is * stamped at creation, so nothing downstream can otherwise see the delay. */ onQueueDelay?: (kind: string, delayMs: number) => void; /** Called for every packet pushed into the bus. */ onPacket?: (route: Route, packet: VoicePacket) => void; } export declare class PipelineBusImpl implements PipelineBus { private critical; private main; private background; private handlers; private concurrentHandlers; private running; private resolver; private drainedCount; private allPacketsController; readonly allPackets: ReadableStream<{ route: Route; packet: VoicePacket; }>; private readonly mainCapacity; private readonly bgCapacity; private readonly criticalBatchSize; private readonly onBgDrop; /** * Opt-in queue-delay observer: how long a packet waited between being pushed and * being dispatched to handlers. * * Without this, a handler that awaits long I/O parks the drain loop and every * packet behind it is delivered late — but each packet carries its OWN * `timestampMs`, stamped at creation, so latency metrics derived from packet * timestamps cannot see the delay at all. That blindness hid a real defect in the * openai-tts plugin. Off unless a callback is supplied; the WeakMap is only * written when observing, so the hot path is untouched otherwise. */ private readonly onQueueDelay; private readonly enqueuedAt; private readonly onPacket; constructor(config?: PipelineBusConfig); push(route: Route, ...packets: T): void; on(kind: T["kind"], handler: PacketHandler, opts?: { concurrent?: boolean; }): () => void; start(): Promise; stop(): void; private queueFor; private publishAllPackets; private enqueueBackgroundDropMetric; private capacityFor; /** * Dequeue a batch of packets. Always drains Critical first. * Critical batches up to `criticalBatchSize` per tick before yielding to I/O. * Main and Background drain one packet per tick. */ private dequeueBatch; /** Dispatch one packet to registered handlers. */ private dispatch; private emitHandlerError; /** Synchronous dispatch for drain-on-stop. Swallows errors. */ private dispatchSync; } //# sourceMappingURL=pipeline-bus.d.ts.map