212 lines
6.6 KiB
TypeScript
212 lines
6.6 KiB
TypeScript
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<void>;
|
|
/**
|
|
* 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<void>;
|
|
/**
|
|
* Send clear context response to specific server
|
|
*/
|
|
sendClearContextResponse(requestId: string, sessionId: string, success?: boolean, targetServer?: ServerId): Promise<void>;
|
|
/**
|
|
* 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<void>;
|
|
/**
|
|
* 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<void>;
|
|
/**
|
|
* Send tasks cancel response to specific server
|
|
*/
|
|
sendTasksCancelResponse(requestId: string, sessionId: string, success?: boolean, targetServer?: ServerId): Promise<void>;
|
|
/**
|
|
* 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<string, any>;
|
|
/**
|
|
* 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;
|
|
}
|