dynamic-interaction
Version:
Dynamic interaction 动态交互mcp,用于cursor、windsurf、trae 等 AI 智能编辑器 Agent 运行时交互使用
155 lines (154 loc) • 5.63 kB
JavaScript
;
/**
* WebSocket 连接管理
* 负责管理WebSocket连接的生命周期
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.webSocketManager = exports.WebSocketManager = void 0;
const ws_1 = require("ws");
const logger_1 = require("../../logger");
const errors_1 = require("../utils/errors");
const crypto_1 = require("crypto");
class WebSocketManager {
static instance;
wss = null;
connections = new Map();
constructor() { }
static getInstance() {
if (!WebSocketManager.instance) {
WebSocketManager.instance = new WebSocketManager();
}
return WebSocketManager.instance;
}
initialize(server) {
if (this.wss) {
logger_1.logger.warn('WebSocket服务器已经初始化');
return;
}
this.wss = new ws_1.WebSocketServer({ server });
(0, logger_1.setWebSocketServer)(this.wss);
logger_1.logger.info('WebSocket服务器已附加到HTTP服务器');
this.setupEventHandlers();
}
setupEventHandlers() {
if (!this.wss)
return;
this.wss.on('connection', (ws) => {
const connectionId = this.addConnection(ws);
logger_1.logger.info(`新客户端连接成功,连接ID: ${connectionId}`);
// 设置连接事件处理器
this.setupConnectionHandlers(ws, connectionId);
});
}
setupConnectionHandlers(ws, connectionId) {
ws.on('message', (message) => {
this.updateConnectionActivity(connectionId);
this.handleMessage(ws, message);
});
ws.on('close', () => {
logger_1.logger.info(`客户端连接已关闭,连接ID: ${connectionId}`);
this.removeConnection(connectionId);
this.handleDisconnection(ws);
});
ws.on('error', (error) => {
logger_1.logger.error(`WebSocket连接出错,连接ID: ${connectionId}:`, error);
this.removeConnection(connectionId);
this.handleDisconnection(ws);
});
ws.on('pong', () => {
this.updateConnectionActivity(connectionId);
});
}
addConnection(ws) {
const connectionId = (0, crypto_1.randomUUID)();
const now = Date.now();
const connectionInfo = {
id: connectionId,
ws,
connectedAt: now,
lastActivity: now
};
this.connections.set(connectionId, connectionInfo);
return connectionId;
}
removeConnection(connectionId) {
this.connections.delete(connectionId);
}
updateConnectionActivity(connectionId) {
const connection = this.connections.get(connectionId);
if (connection) {
connection.lastActivity = Date.now();
}
}
handleMessage(ws, message) {
try {
const messageStr = Buffer.isBuffer(message) ? message.toString() :
message instanceof ArrayBuffer ? Buffer.from(message).toString() :
Array.isArray(message) ? Buffer.concat(message).toString() :
String(message);
const parsedMessage = JSON.parse(messageStr);
logger_1.logger.debug('收到WebSocket消息:', parsedMessage);
// 导入消息处理器(避免循环依赖)
const { messageProcessor } = require('../messaging/processor');
messageProcessor.process(ws, parsedMessage);
}
catch (error) {
logger_1.logger.error('解析WebSocket消息失败:', error);
const errorResponse = {
type: 'error',
data: {
message: 'JSON解析失败',
code: errors_1.ErrorCodes.JSON_PARSE_ERROR
}
};
ws.send(JSON.stringify(errorResponse));
}
}
handleDisconnection(ws) {
// 导入会话管理器(避免循环依赖)
const { sessionManager } = require('../session/manager');
sessionManager.handleDisconnection(ws);
// 检查服务器空闲状态
const { lifecycleManager } = require('../core/lifecycle');
lifecycleManager.checkAndStopIfIdle();
}
getAvailableConnection() {
// 导入会话管理器(避免循环依赖)
const { sessionManager } = require('../session/manager');
for (const connection of this.connections.values()) {
if (!sessionManager.hasSession(connection.ws)) {
return connection.ws;
}
}
return null;
}
getConnectionCount() {
return this.connections.size;
}
getConnections() {
return Array.from(this.connections.values());
}
closeAll() {
logger_1.logger.info(`关闭所有WebSocket连接 (${this.connections.size}个)`);
for (const connection of this.connections.values()) {
try {
connection.ws.close();
}
catch (error) {
logger_1.logger.error(`关闭WebSocket连接失败:`, error);
}
}
this.connections.clear();
}
startHeartbeat(intervalMs = 30000) {
setInterval(() => {
for (const connection of this.connections.values()) {
if (connection.ws.readyState === ws_1.WebSocket.OPEN) {
connection.ws.ping();
}
}
}, intervalMs);
}
}
exports.WebSocketManager = WebSocketManager;
exports.webSocketManager = WebSocketManager.getInstance();