import { EventEmitter } from "events"; import { A2AResponseMessage, WebSocketConnectionState, XiaoYiChannelConfig, ServerId, ServerConnectionState, SessionCleanupState } from "./types"; export declare class XiaoYiWebSocketManager extends EventEmitter { private ws1; private ws2; private state1; private state2; private sessionServerMap; private sessionCleanupStateMap; private static readonly DEFAULT_CLEANUP_TIMEOUT_MS; private auth; private config; private heartbeatTimeout1?; private heartbeatTimeout2?; private appHeartbeatInterval?; private reconnectTimeout1?; private reconnectTimeout2?; private stableConnectionTimer1?; private stableConnectionTimer2?; private static readonly STABLE_CONNECTION_THRESHOLD; private activeTasks; constructor(config: XiaoYiChannelConfig); /** * Check if URL is wss + IP format (skip certificate verification) */ private isWssWithIp; /** * Resolve configuration with defaults and backward compatibility */ private resolveConfig; /** * Connect to both WebSocket servers */ connect(): Promise; /** * Connect to server 1 */ private connectToServer1; /** * Connect to server 2 */ private connectToServer2; /** * Disconnect from all servers */ disconnect(): void; /** * Send init message to specific server */ private sendInitMessage; /** * Setup WebSocket event handlers for specific server */ private setupWebSocketHandlers; /** * Extract sessionId from message based on method type * Different methods have sessionId in different locations: * - message/stream: sessionId in params, fallback to top-level sessionId * - tasks/cancel: sessionId at top level * - clearContext: sessionId at top level */ private extractSessionId; /** * Handle incoming message from specific server */ private handleIncomingMessage; /** * Send A2A response message with automatic routing */ sendResponse(response: A2AResponseMessage, taskId: string, sessionId: string, isFinal?: boolean, append?: boolean): Promise; /** * Send clear context response to specific server */ sendClearContextResponse(requestId: string, sessionId: string, success?: boolean, targetServer?: ServerId): Promise; /** * Send status update (for intermediate status messages, e.g., timeout warnings) * This uses "status-update" event type which keeps the conversation active */ sendStatusUpdate(taskId: string, sessionId: string, message: string, targetServer?: ServerId): Promise; /** * Send PUSH message (主动推送) via HTTP API * * This is used when SubAgent completes execution and needs to push results to user * independently of the original A2A request-response flow. * * Unlike sendResponse (which responds to a specific request via WebSocket), push messages are * sent through HTTP API asynchronously. * * @param sessionId - User's session ID * @param message - Message content to push * * Reference: 华为小艺推送消息 API * TODO: 实现实际的推送消息发送逻辑 */ sendPushMessage(sessionId: string, message: string): Promise; /** * Send tasks cancel response to specific server */ sendTasksCancelResponse(requestId: string, sessionId: string, success?: boolean, targetServer?: ServerId): Promise; /** * Handle clearContext method */ private handleClearContext; /** * Handle clear message (legacy format) */ private handleClearMessage; /** * Handle tasks/cancel message */ private handleTasksCancelMessage; /** * Convert A2AResponseMessage to JSON-RPC 2.0 format */ private convertToJsonRpcFormat; /** * Check if at least one server is ready */ isReady(): boolean; /** * Get combined connection state */ getState(): WebSocketConnectionState; /** * Get individual server states */ getServerStates(): { server1: ServerConnectionState; server2: ServerConnectionState; }; /** * Start protocol-level heartbeat for specific server */ private startProtocolHeartbeat; /** * Clear protocol heartbeat for specific server */ private clearProtocolHeartbeat; /** * Start application-level heartbeat (shared across both servers) */ private startAppHeartbeat; /** * Schedule reconnection for specific server */ private scheduleReconnect; /** * Clear all timers */ private clearTimers; /** * Schedule a connection stability check * Only reset reconnect counter after connection has been stable for threshold time */ private scheduleStableConnectionCheck; /** * Clear the connection stability check timer */ private clearStableConnectionCheck; /** * Type guard for A2A request messages * sessionId can be in params OR at top level (fallback) */ private isA2ARequestMessage; /** * Get active tasks */ getActiveTasks(): Map; /** * Remove task from active tasks */ removeActiveTask(taskId: string): void; /** * Get server for a specific session */ getServerForSession(sessionId: string): ServerId | undefined; /** * Remove session mapping */ removeSession(sessionId: string): void; /** * Mark a session for delayed cleanup * @param sessionId The session ID to mark for cleanup * @param serverId The server ID associated with this session * @param timeoutMs Timeout in milliseconds before forcing cleanup */ private markSessionForCleanup; /** * Force cleanup a session immediately * @param sessionId The session ID to cleanup */ forceCleanupSession(sessionId: string): void; /** * Check if a session is pending cleanup * @param sessionId The session ID to check * @returns True if session is pending cleanup */ isSessionPendingCleanup(sessionId: string): boolean; /** * Get cleanup state for a session * @param sessionId The session ID to check * @returns Cleanup state if exists, undefined otherwise */ getSessionCleanupState(sessionId: string): SessionCleanupState | undefined; /** * Update accumulated text for a pending cleanup session * @param sessionId The session ID * @param text The accumulated text */ updateAccumulatedTextForCleanup(sessionId: string, text: string): void; }