/**
 * SocketModeClient — WebSocket connection manager for Slack Socket Mode.
 *
 * Handles the full lifecycle: connect, receive events, acknowledge,
 * reconnect with hardened strategy (exponential backoff, active heartbeat,
 * too_many_websockets handling, proactive rotation).
 *
 * Uses Node's built-in WebSocket (Node 22+) or falls back to 'ws' package.
 *
 * CONTRACT-EVIDENCE: EXEMPT — net #1 (_safeSend containment) touches NO Slack
 * Socket Mode API-contract surface. The bytes sent to Slack are byte-identical
 * (the same ack `{ envelope_id }`, the same `{"type":"ping"}`, the same queued
 * payloads); only the local non-OPEN-send guarding (readyState check + try/catch)
 * and the reconnect policy changed. No wire-protocol / envelope shape change, so
 * live-API contract evidence does not apply. Remove this marker when the file's
 * actual API surface next changes.
 */
import { SlackApiClient } from './SlackApiClient.js';
export interface SocketModeHandlers {
    onEvent: (type: string, payload: Record<string, unknown>) => Promise<void>;
    onInteraction: (payload: Record<string, unknown>) => Promise<void>;
    onConnected: () => void;
    onDisconnected: (reason: string) => void;
    onError: (error: Error, permanent: boolean) => void;
}
export declare class SocketModeClient {
    private apiClient;
    private handlers;
    private ws;
    private started;
    private reconnecting;
    private epoch;
    private consecutiveErrors;
    private heartbeatTimer;
    private lastEventAt;
    private outboundQueue;
    private connectionTime;
    constructor(apiClient: SlackApiClient, handlers: SocketModeHandlers);
    get isConnected(): boolean;
    connect(): Promise<void>;
    disconnect(): Promise<void>;
    /** Force-reconnect: tear down existing connection and establish a new one. */
    reconnect(): Promise<void>;
    /**
     * Deliberately tear down the tracked socket. Bumps the epoch (so any
     * in-flight open/backoff aborts) and nulls `this.ws` BEFORE closing — the
     * socket's close event fires on a later tick, and the identity guard in the
     * close handler (`this.ws !== sock`) is what keeps that stale event from
     * touching whatever connection is current by then. A synchronous flag
     * save/restore cannot do this (#1076).
     */
    private _teardownSocket;
    /**
     * The single funnel for EVERY WebSocket send in this client (net #1). A
     * `send()` on a socket that is not OPEN (CONNECTING / CLOSING / CLOSED) throws
     * synchronously — `"WebSocket is not open: readyState N"` on the Node 22+
     * built-in, `"Sent before connected"` on the `ws` polyfill — and these sends
     * run inside un-awaited event-listener callbacks, where an escaping throw
     * becomes an uncaughtException / unhandledRejection that can crash the whole
     * process. `_safeSend` contains that at the source.
     *
     * Reads `this.ws` ONCE into a local and sends on THAT local, so the readyState
     * check and the send target the same socket (no internal TOCTOU). Returns true
     * iff the frame was handed to the socket.
     *
     * - Not-OPEN precheck (the EXPECTED transient state during reconnect): returns
     *   false silently — no log, no reconnect. A non-OPEN socket short-circuits
     *   here, so repeated sends against a dead socket can never flood the log.
     * - A genuine throw on an OPEN socket (a rare race): logged message-only (never
     *   the payload). Only the liveness path (`reconnectOnFailure`) reconnects, and
     *   only if the socket we sent on is still current (`this.ws === sock`) — so a
     *   throw after a teardown-and-replace can never tear down a fresh healthy
     *   socket. Reuses the existing `_forceReconnect` guard (epoch model, #1076);
     *   never resurrects a torn-down socket.
     */
    private _safeSend;
    /** Queue an outbound message for sending (or send immediately if connected). */
    queueOutbound(data: string): void;
    private _openConnection;
    private _connectWebSocket;
    private _handleRawMessage;
    private _handleDisconnect;
    private _backoffReconnect;
    private _startHeartbeat;
    private _forceReconnect;
    private _clearHeartbeat;
    private _drainQueue;
}
//# sourceMappingURL=SocketModeClient.d.ts.map