import { type QuestionChatActivationResponse, type QuestionChatAvailabilityError, type QuestionChatEvent, type QuestionChatSendPayload, type QuestionChatSendResponse, type QuestionChatSnapshot, type QuestionChatStreamEvent, type QuestionChatSource, type QuestionChatStopPayload, type QuestionChatStopResponse } from "../protocol.js"; import type { WebSocket } from "ws"; export interface QuestionChatRelayOptions { commandTimeoutMs?: number; now?: () => number; authorize?: (requestId: string, ownerSessionId: string) => QuestionChatAvailabilityError | undefined; commandRateLimitMax?: number; commandRateLimitWindowMs?: number; commandDedupeTtlMs?: number; commandDedupeCapacity?: number; } export interface QuestionChatIdentity { requestId: string; ownerSessionId: string; forkKind: "fresh"; } export type QuestionChatCommandResult = { status: "ok"; value: T; } | { status: "unavailable"; error: QuestionChatAvailabilityError; }; export type QuestionChatTerminalReason = "answered" | "cancelled" | "expired" | "session_shutdown"; type QuestionChatCleanupReason = QuestionChatTerminalReason | "missing" | "wrong_owner"; export declare class QuestionChatRelay { private readonly extensions; private readonly pending; private readonly activeChats; private readonly reconcilingSessions; private readonly subscribers; private readonly deferredCleanup; private readonly retainedBrowserCommands; private readonly rateBuckets; private readonly commandTimeoutMs; private readonly now; private readonly authorize; private readonly commandRateLimitMax; private readonly commandRateLimitWindowMs; private readonly commandDedupeTtlMs; private readonly commandDedupeCapacity; constructor(options?: QuestionChatRelayOptions | number); bind(sessionId: string, connectionId: string, socket: WebSocket): void; unbind(connectionId: string): void; finishRecovery(sessionId: string): void; isLiveOwner(connectionId: string, ownerSessionId: string, requestId: string): boolean; restore(connectionId: string, ownerSessionId: string, forkKind: QuestionChatIdentity["forkKind"], snapshot: QuestionChatSnapshot): boolean; activate(requestId: string, ownerSessionId: string, source: QuestionChatSource, callerKey?: string): Promise; private activateKind; snapshot(requestId: string, ownerSessionId: string): Promise>; sendMessage(requestId: string, ownerSessionId: string, command: QuestionChatSendPayload, callerKey?: string): Promise>; stop(requestId: string, ownerSessionId: string, command: QuestionChatStopPayload, callerKey?: string): Promise>; replaySend(requestId: string, command: QuestionChatSendPayload): Promise> | undefined; replayStop(requestId: string, command: QuestionChatStopPayload): Promise> | undefined; resolveReady(commandId: string, connectionId: string, snapshot: QuestionChatSnapshot): void; resolveSnapshot(commandId: string, connectionId: string, snapshot: QuestionChatSnapshot): void; resolveSend(commandId: string, connectionId: string, requestId: string, response: QuestionChatSendResponse): void; resolveStop(commandId: string, connectionId: string, requestId: string, response: QuestionChatStopResponse): void; resolveError(commandId: string, connectionId: string, requestId: string, error: QuestionChatAvailabilityError): void; publishEvent(connectionId: string, event: QuestionChatEvent): void; subscribe(requestId: string, listener: (event: QuestionChatStreamEvent) => void): () => void; cleanup(requestId: string, ownerSessionId: string, reason: QuestionChatTerminalReason): void; disposeNonTerminal(requestId: string): void; rejectRecovery(identity: QuestionChatIdentity, reason: QuestionChatCleanupReason): void; close(): void; private dispatch; private dispatchPrepared; private preflight; private resolve; private replayBrowserCommand; private retainBrowserCommand; private commandCapacityError; private pruneRetainedCommands; private consumeRateLimit; private send; private assertOwner; private inactiveResult; private activeRequestIds; private publishTransport; } export {}; //# sourceMappingURL=questionChatRelay.d.ts.map