import type { WsEvent } from "@jait/shared";
import type { UICommandPayload } from "@jait/shared";
import type { ScreenShareSessionState, FsNode, FsBrowseEntry, NodeRegistrySnapshot } from "@jait/shared";
import type { AppConfig } from "./config.js";
import type { Server as HttpServer } from "node:http";
import type { ToolOutputStreamMetadata } from "./tools/contracts.js";
export declare class WsControlPlane {
    private config;
    private wss;
    private clients;
    private jwtSecret;
    /** Server-side keepalive: pings clients and terminates dead sockets. */
    private heartbeatTimer;
    /** Filesystem nodes registered by clients (keyed by node ID) */
    private fsNodes;
    /** Pending fs browse requests waiting for a response from a remote node */
    private pendingFsBrowse;
    /** Generic pending fs operations (stat, read, write, list) waiting for remote node response */
    private pendingFsOps;
    /** Pending remote provider operation requests */
    private pendingProviderOps;
    /** Pending remote tool execution requests */
    private pendingToolOps;
    /** Pending remote interactive terminal operation requests */
    private pendingTerminalOps;
    private nodeStates;
    private terminalStreamState;
    private providerStreamState;
    private toolStreamState;
    private pendingArchitectureRenders;
    getThreadSnapshot?: (userId: string) => {
        serverTime: string;
        threads: unknown[];
        hasMore?: boolean;
    };
    getSurfaceSnapshot?: () => {
        serverTime: string;
        surfaces: unknown[];
    };
    getBrowserSnapshot?: (userId?: string | null) => {
        serverTime: string;
        sessions: unknown[];
        interventions: unknown[];
    };
    constructor(config: AppConfig);
    /**
     * Attach the WebSocket server to an existing HTTP server (shares port).
     * Falls back to standalone port if no httpServer is provided.
     */
    start(httpServer?: HttpServer): void;
    private extractBearerToken;
    private extractCookieToken;
    private authenticateClient;
    private handleMessage;
    /** Send an event to a specific client by ID */
    sendToClient(clientId: string, event: WsEvent): void;
    /** Broadcast an event to all clients subscribed to a session */
    broadcast(sessionId: string, event: WsEvent): void;
    /** Broadcast to all connected clients */
    broadcastAll(event: WsEvent): void;
    /** Send a typed UI command to all clients subscribed to the session (server → frontend) */
    sendUICommand(command: UICommandPayload, sessionId?: string): void;
    waitForArchitectureRenderResult(requestId: string, timeoutMs?: number): Promise<{
        ok: true;
    } | {
        ok: false;
        error: string;
    }>;
    /**
     * Broadcast to all clients subscribed to a session, excluding one client.
     * Used to relay state changes to other clients without echoing back to the sender.
     */
    broadcastExcluding(sessionId: string, excludeClientId: string, event: WsEvent): void;
    /** Send terminal output data to all clients subscribed to this terminal */
    broadcastTerminalOutput(terminalId: string, data: string): void;
    /** Callback for terminal input from WS clients */
    onTerminalInput?: (terminalId: string, data: string) => void;
    /** Callback for terminal resize from WS clients */
    onTerminalResize?: (terminalId: string, cols: number, rows: number) => void;
    /** Callback to replay buffered output when a client subscribes to a terminal */
    onTerminalReplay?: (terminalId: string) => string | null;
    /** Callback for consent approval from WS clients */
    onConsentApprove?: (requestId: string) => void;
    /** Callback for consent rejection from WS clients */
    onConsentReject?: (requestId: string, reason?: string) => void;
    /** Callback when a client updates UI component state (panel open/close) */
    onUIStateUpdate?: (sessionId: string, key: string, value: unknown | null, clientId: string) => void;
    /** Callback when a client subscribes to a session — used to push full state */
    onClientSubscribe?: (sessionId: string, clientId: string) => void;
    /** Callback when a screen-share start is requested via WS */
    onScreenShareStart?: (hostDeviceId: string, viewerDeviceIds?: string[]) => void;
    /** Callback when a screen-share stop is requested via WS */
    onScreenShareStop?: (sessionId: string) => void;
    /** Callback when a remote node sends a provider event (token, tool.start, etc.) */
    onRemoteProviderEvent?: (sessionId: string, event: unknown, metadata?: {
        streamId: string;
        seq: number;
    }) => void;
    /** Callback when a remote node emits interactive terminal output. */
    onRemoteTerminalOutput?: (terminalId: string, data: string, nodeId?: string) => void;
    /** Callback when a remote node reports interactive terminal exit. */
    onRemoteTerminalExit?: (terminalId: string, exitCode: number | null, signal: number | string | null, nodeId?: string) => void;
    /** Called when a filesystem node (desktop/mobile) registers. */
    onFsNodeRegistered?: (node: FsNode) => void;
    private getTerminalStreamState;
    private nextTerminalStreamEvent;
    private currentTerminalStreamEvent;
    private nextOrderedStreamEvent;
    /** Relay a signaling message to a specific device ID */
    private relayToDevice;
    /** Broadcast a screen-share state update to all connected clients */
    broadcastScreenShareState(state: ScreenShareSessionState): void;
    /**
     * Send a screen-share start-request to the host and viewer devices only.
     * Used by tools/routes when the session is created server-side and the host
     * device needs to be told to begin capture (and viewers to prepare).
     */
    sendScreenShareStartRequest(sessionId: string, hostDeviceId: string, viewerDeviceIds?: string[]): void;
    /** Broadcast an fs.node-disconnected event when a client with FsNodes disconnects. */
    private broadcastFsNodeChange;
    /** Find all connected device IDs */
    getConnectedDeviceIds(): string[];
    /** List all registered filesystem nodes */
    getFsNodes(): FsNode[];
    /** Register the gateway itself as a filesystem node */
    registerGatewayFsNode(node: FsNode): void;
    getNodeRegistry(): NodeRegistrySnapshot;
    /**
     * Proxy a browse request to a remote filesystem node.
     * Sends a WS message to the owning client and waits for a response.
     */
    proxyFsBrowse(nodeId: string, path: string): Promise<{
        path: string;
        parent: string | null;
        entries: FsBrowseEntry[];
    }>;
    /**
     * Proxy a roots request to a remote filesystem node.
     */
    proxyFsRoots(nodeId: string): Promise<FsBrowseEntry[]>;
    /**
     * Send a filesystem operation request to a remote node and wait for the response.
     * Used for stat, read, write, list, exists, readdir, mkdir, etc.
     */
    proxyFsOp<T = unknown>(nodeId: string, op: string, params: Record<string, unknown>, timeoutMs?: number): Promise<T>;
    /** Check if a node ID refers to a remote (non-gateway) node */
    isRemoteNode(nodeId: string): boolean;
    /**
     * Find the remote node whose device ID matches a given filesystem path's origin.
     * Used to route provider operations to the device that owns a repo.
     * Returns undefined if the path belongs to the gateway or no matching node is found.
     */
    findNodeByDeviceId(deviceId: string): FsNode | undefined;
    /**
     * Send an acknowledged interactive terminal operation to a remote node.
     * Used for terminal creation and shutdown where callers need failure details.
     */
    proxyTerminalOp<T = unknown>(nodeId: string, op: string, params: Record<string, unknown>, timeoutMs?: number): Promise<T>;
    /**
     * Send a fire-and-forget interactive terminal operation to a remote node.
     * Used for high-volume input and resize events.
     */
    sendTerminalOp(nodeId: string, op: string, params: Record<string, unknown>): void;
    /**
     * Send a tool execution request to a remote node and wait for the result.
     * Used to delegate Jait tool calls (terminal.run, file.write, etc.) to nodes.
     */
    proxyToolOp<T = unknown>(nodeId: string, tool: string, args: Record<string, unknown>, options?: {
        timeoutMs?: number;
        sessionId?: string;
        projectRoot?: string;
        onOutputChunk?: (chunk: string, metadata?: ToolOutputStreamMetadata) => void;
    }): Promise<T>;
    /**
     * Send a provider operation request to a remote node and wait for the response.
     * Used by RemoteCliProvider to proxy session lifecycle and turn operations.
     */
    proxyProviderOp<T = unknown>(nodeId: string, op: string, params: Record<string, unknown>, timeoutMs?: number): Promise<T>;
    get clientCount(): number;
    private send;
    private sendNodeRegistrySnapshot;
    private broadcastNodeUpdate;
    private broadcastDisconnectedNodes;
    stop(): void;
}
//# sourceMappingURL=ws.d.ts.map