import type { Frame } from "../protocol/index.ts"; import type { Authenticator } from "./auth.ts"; import type { Clock } from "./clock.ts"; import type { ChannelTransport, CloseCode, HandshakeRequest } from "./connection.ts"; import { FamilyRouter } from "./dispatch.ts"; import { ConnectionRegistry } from "./registry.ts"; /** Application close code used when a connection ages out on the liveness TTL. */ export declare const LIVENESS_TIMEOUT = 4408; /** * The per-connection context threaded to every family handler. A handler * (S2/S5/S7) uses it to reply on the same connection and to attach presence in * the shared {@link ConnectionRegistry}. */ export interface HubConnection { /** The connection id. */ readonly id: string; /** The authenticated principal (ADR 0028 identity). */ readonly identity: string; /** What the transport captured at connect time. */ readonly handshake: HandshakeRequest; /** The shared registry — handlers attach presence via `registry.addInstance(id, …)`. */ readonly registry: ConnectionRegistry; /** Encode and send one frame back on this connection. */ send(frame: Frame): void; /** Close this connection. */ close(code?: CloseCode, reason?: string): void; } export interface AgenticHubOptions { /** The listening transport bound to the app's own port. */ transport: ChannelTransport; /** How connections authenticate. */ authenticator: Authenticator; /** A pre-populated router, or omit to let the hub create an empty one. */ router?: FamilyRouter; /** A shared registry, or omit to let the hub create one. */ registry?: ConnectionRegistry; /** * Injectable clock for the registry's liveness time. Ignored when a `registry` * is supplied — that registry owns time (it is the single source of truth for * liveness), so pass the clock to the {@link ConnectionRegistry} instead. */ clock?: Clock; /** * How often to sweep for aged-out connections, in ms. Default: a third of the * registry TTL. Pass 0 to disable the internal timer (tests call * {@link AgenticHub.sweepNow} explicitly). */ sweepIntervalMs?: number; /** Notified of a decode/handler error; the offending connection is kept. */ onError?: (err: unknown, connectionId?: string) => void; } export declare class AgenticHub { #private; readonly router: FamilyRouter; readonly registry: ConnectionRegistry; constructor(options: AgenticHubOptions); /** * Attach the handler that owns a message family. Convenience delegate to the * router's registration seam — this is the canonical extension point every * family module (S2/S5/S7) uses. */ registerFamilyHandler(...args: Parameters["registerFamilyHandler"]>): void; /** The bound address of the underlying transport once listening. */ get address(): { readonly port: number; } | null; /** The number of currently tracked connections. */ get connectionCount(): number; /** * Age out connections past the liveness TTL and close their sockets. Called * automatically by the internal timer; exposed for deterministic tests. Reads * "now" from the registry's own clock so liveness time has a single source of * truth — the hub keeps no separate clock to drift against `lastSeen`. */ sweepNow(): void; /** Stop the liveness sweep and release the transport's port. */ close(): Promise; }