import { GatewayConfig } from './gateway-config.js'; import { NewMessage } from './types.js'; import type { GatewayCommandDefinitionPayload, GatewayTraceEventPayload, GatewayUsageReportPayload } from './gateway-protocol.js'; export declare function directHttpOriginsForGatewayReport(): string[]; export declare function parseGatewaySseFrame(frame: string): { id?: string; data: string; } | null; export interface GatewayCallbacks { onMessage: (chatJid: string, msg: NewMessage) => void; onChatMetadata: (chatJid: string, timestamp: string, name?: string, channel?: string, isGroup?: boolean) => void; onEnrollmentSuccess?: (daemonId: string) => void; } /** * Gateway — the daemon's outbound uplink to the Supen Gateway. * * Architecture: * - Daemons connect outward to the gateway and receive instructions from it. * - The gateway accepts connections from controller platforms (Supen, etc.) * that drive the daemons via channels (Discord, HTTP, …). * * This is core infrastructure, not a consumer channel. * Instantiated directly in index.ts, not via the channel registry. */ export declare class Gateway { private ws; private _connected; private config; private callbacks; private reconnectTimeout; private reportingInterval; private connectionTimeout; private heartbeatInterval; private heartbeatTimeout; private activeSseSubscriptions; private llmToken; private llmTokenExpiresAt; private tokenRenewalTimeout; private intentionalShutdown; private socketCloseHandled; private channelReplyThreads; private pendingReplyStarts; private localBridgeRelays; constructor(callbacks: GatewayCallbacks); getConfig(): GatewayConfig; reloadConfigAndReconnect(): Promise; connect(): Promise; private initiateConnection; private authenticate; /** * Build a HMAC token for gateway authentication. * Format: `${daemonId}.${timestampMs}.${hmacHex}` * Uses the persisted computer gateway secret first, then the launch-time env secret. */ private buildGatewayToken; private startReporting; private stopReporting; private sendGatewayFrame; private destroyActiveStreamRelays; private startHeartbeat; private stopHeartbeat; private rejectPendingReplyStarts; private handleSocketClosed; private handleMessage; private localBridgeSessionId; private localBridgeKey; private localBridgePrefix; /** * Open one loopback relay to the daemon's own Codex app-server bridge. Both * the Desktop SSH ingress (`desktop_bridge_*`) and the gateway WS ingress * (`codex_bridge_*`) carry identical bytes over an identical WebSocket; only * the gateway frame-type prefix differs, so they share this single path. */ private openLocalBridgeRelay; private forwardLocalBridgeFrame; private closeLocalBridgeRelay; private handleDesktopBridgeOpen; private handleDesktopBridgeData; private handleDesktopBridgeEnd; private handleCodexBridgeOpen; private handleCodexBridgeData; private handleCodexBridgeEnd; private destroyLocalBridgeRelays; private handleLlmToken; private scheduleTokenRenewal; /** Get the current LLM token (null if not yet received from gateway). */ getLlmToken(): string | null; private handleApiRequest; private handleSseSubscribe; private handleChatStreamRequest; /** Send a message back to the gateway (from a local agent reply). */ sendMessage(chatJid: string, text: string): Promise; /** * Send a reply to be delivered via an external channel (Discord, DingTalk, Feishu). * The gateway routes this to the appropriate channel instance. */ sendChannelReply(channel: string, jid: string, content: string, inReplyTo?: string, traceId?: string): Promise; private getChannelReplyThread; startChannelReplyForChat(chatJid: string, content: string): Promise; updateChannelReply(replyHandle: string, content: string, traceId?: string): Promise; finalizeChannelReply(replyHandle: string, traceId?: string): Promise; failChannelReply(replyHandle: string, content: string, traceId?: string): Promise; /** * Send a reply for a chat JID. If the chat originated from a channel message, * uses sendChannelReply; otherwise uses sendMessage. */ sendReplyForChat(chatJid: string, text: string, inReplyTo?: string, traceId?: string): Promise; emitTraceEvent(event: Omit): void; reportUsage(event: Omit): void; emitPushEvent(threadId: string, event: unknown): void; /** * Clear channel context for a thread (e.g., when a thread ends). */ clearChannelThread(chatJid: string): void; /** Check if this JID belongs to a gateway thread. */ ownsJid(jid: string): boolean; isConnected(): boolean; publishRoutingConfig(input?: { routeTargetIds?: string[]; channelThreads?: string[]; channelThreadOwners?: Array<{ channel_thread: string; runtime_agent_id?: string; space_id?: string; daemon_id?: string; task_id?: string; thread_id?: string; }>; commands?: GatewayCommandDefinitionPayload[]; directHttpOrigins?: string[]; }): Promise; disconnect(): Promise; } /** Set the gateway singleton (called once in index.ts after construction). */ export declare function setGatewayInstance(gw: Gateway): void; /** Check if a gateway URL was configured (regardless of connection state). */ export declare function isGatewayConfigured(): boolean; /** Get the gateway singleton (for routing channel replies). */ export declare function getGatewayInstance(): Gateway | null; /** Get the current LLM token. Returns null if gateway hasn't issued one yet. */ export declare function getLlmToken(): string | null; /** * Wait for an LLM token to become available. * Polls every 500ms up to timeoutMs (default 10s). * Useful at startup when tasks may queue before the gateway connection is established. * Rejects immediately if no gateway is configured (standalone mode). */ export declare function getLlmTokenOrWait(timeoutMs?: number): Promise; //# sourceMappingURL=gateway.d.ts.map