UNPKG

dynamic-interaction

Version:

Dynamic interaction 动态交互mcp,用于cursor、windsurf、trae 等 AI 智能编辑器 Agent 运行时交互使用

172 lines (171 loc) 6.46 kB
"use strict"; /** * 日志模块 (winston) * 提供一个全局的 logger 实例 */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.logger = void 0; exports.setWebSocketServer = setWebSocketServer; const winston = __importStar(require("winston")); const path = __importStar(require("path")); const fs = __importStar(require("fs")); const config_1 = require("./config"); const winston_daily_rotate_file_1 = __importDefault(require("winston-daily-rotate-file")); const winston_transport_1 = __importDefault(require("winston-transport")); // WebSocket传输类的简化实现 class WebSocketTransport extends winston_transport_1.default { clients = new Set(); constructor() { super(); } log(info, callback) { setImmediate(() => { this.emit('logged', info); }); // 广播日志到所有连接的客户端 const logMessage = JSON.stringify({ type: 'log', level: info.level, message: info.message, timestamp: info.timestamp, ...(info.stack && { stack: info.stack }), }); this.clients.forEach((client) => { if (client.readyState === 1) { // 1 = OPEN try { client.send(logMessage); } catch (error) { // 忽略发送错误,移除无效连接 this.clients.delete(client); } } }); callback(); } addClient(client) { this.clients.add(client); client.on('close', () => { this.clients.delete(client); }); } } const wsTransport = new WebSocketTransport(); // 设置WebSocket服务器函数 function setWebSocketServer(server) { server.on('connection', (ws) => { wsTransport.addClient(ws); }); } ; let logger; if (!config_1.LOG_CONFIG.enabled) { // 如果日志系统被禁用,创建一个静默的 logger exports.logger = logger = winston.createLogger({ transports: [new winston.transports.Console({ silent: true })] }); console.log('日志系统已禁用,WebSocket 日志传输将不会被初始化。'); } else { // 确保日志目录存在 let logDir = config_1.LOG_CONFIG.dir; if (config_1.LOG_CONFIG.fileLogging) { try { if (!fs.existsSync(logDir)) { fs.mkdirSync(logDir, { recursive: true }); } } catch (error) { console.warn(`无法创建日志目录: ${logDir},将使用临时目录`, error); try { const os = require('os'); logDir = path.join(os.tmpdir(), 'dynamic-interaction-logs'); if (!fs.existsSync(logDir)) { fs.mkdirSync(logDir, { recursive: true }); } console.info(`已切换到临时日志目录: ${logDir}`); } catch (fallbackError) { console.error(`无法创建临时日志目录,将禁用文件日志`, fallbackError); config_1.LOG_CONFIG.fileLogging = false; } } } // 准备传输器列表 const transports = [ new winston.transports.Console({ format: winston.format.combine(config_1.LOG_CONFIG.colorize ? winston.format.colorize() : winston.format.simple(), winston.format.simple()), }), new WebSocketTransport(), ]; if (config_1.LOG_CONFIG.fileLogging) { try { transports.push(new winston_daily_rotate_file_1.default({ filename: path.join(logDir, config_1.LOG_CONFIG.combinedFile), datePattern: 'YYYY-MM-DD', zippedArchive: true, maxSize: '20m', maxFiles: '14d', handleExceptions: true, }), new winston_daily_rotate_file_1.default({ filename: path.join(logDir, config_1.LOG_CONFIG.errorFile), datePattern: 'YYYY-MM-DD', zippedArchive: true, maxSize: '20m', maxFiles: '14d', level: 'error', handleExceptions: true, })); } catch (error) { console.error('添加文件日志传输器失败,将只使用控制台日志', error); } } exports.logger = logger = winston.createLogger({ level: config_1.LOG_CONFIG.level, format: winston.format.combine(winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.errors({ stack: true }), winston.format.splat(), winston.format.json()), transports, exitOnError: false, }); logger.info('日志系统已初始化', { logLevel: config_1.LOG_CONFIG.level, logDir: config_1.LOG_CONFIG.fileLogging ? logDir : 'disabled', fileLogging: config_1.LOG_CONFIG.fileLogging, }); }