@vrs-soft/wecom-aibot-mcp 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.d.ts CHANGED
@@ -7,5 +7,10 @@
7
7
  * 支持 HTTP Transport 模式:
8
8
  * - 固定端口 18963
9
9
  * - 支持多 Claude Code 同时连接
10
+ *
11
+ * 连接管理:
12
+ * - 启动时不建立 WebSocket 连接
13
+ * - enter_headless_mode 时按需建立连接
14
+ * - exit_headless_mode 时断开连接
10
15
  */
11
16
  export {};
package/dist/bin.js CHANGED
@@ -7,30 +7,21 @@
7
7
  * 支持 HTTP Transport 模式:
8
8
  * - 固定端口 18963
9
9
  * - 支持多 Claude Code 同时连接
10
+ *
11
+ * 连接管理:
12
+ * - 启动时不建立 WebSocket 连接
13
+ * - enter_headless_mode 时按需建立连接
14
+ * - exit_headless_mode 时断开连接
10
15
  */
11
- import { runConfigWizard, loadConfig, saveConfig, deleteConfig, deleteMcpConfigInteractive, uninstall, addMcpConfig, detectUserIdFromMessage, ensureHookInstalled, } from './config-wizard.js';
16
+ import { runConfigWizard, loadConfig, saveConfig, deleteConfig, deleteMcpConfigInteractive, uninstall, addMcpConfig, detectUserIdFromMessage, ensureHookInstalled, listAllRobots, } from './config-wizard.js';
12
17
  import { initClient } from './client.js';
13
18
  import { registerTools } from './tools/index.js';
14
19
  import { startHttpServer, HTTP_PORT } from './http-server.js';
15
20
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
16
- import { clearAllProjectHooks } from './headless-state.js';
17
- const VERSION = '1.0.6';
18
- // 等待连接验证(最多等待 10 秒)
19
- async function waitForConnection(client, timeoutMs = 10000) {
20
- return new Promise((resolve) => {
21
- const startTime = Date.now();
22
- const checkInterval = setInterval(() => {
23
- if (client.isConnected()) {
24
- clearInterval(checkInterval);
25
- resolve(true);
26
- }
27
- else if (Date.now() - startTime > timeoutMs) {
28
- clearInterval(checkInterval);
29
- resolve(false);
30
- }
31
- }, 500);
32
- });
33
- }
21
+ import { clearAllProjectHooks, getAllHeadlessStates } from './headless-state.js';
22
+ import { loadStats, cleanupOldLogs } from './connection-log.js';
23
+ import { startKeepaliveMonitor, stopKeepaliveMonitor } from './keepalive-monitor.js';
24
+ const VERSION = '1.0.7';
34
25
  function showHelp() {
35
26
  console.log(`
36
27
  企业微信智能机器人 MCP 服务 v${VERSION}
@@ -46,8 +37,8 @@ function showHelp() {
46
37
  --version, -v 显示版本号
47
38
  --config 重新配置默认机器人(修改 Bot ID / Secret / 目标用户)
48
39
  --add 添加新的机器人配置(多机器人场景)
40
+ --list 列出所有已配置的机器人
49
41
  --delete [名称] 删除指定的机器人配置(无参数则显示列表选择)
50
- --status 显示当前配置状态
51
42
  --uninstall 卸载并删除所有配置(包括 MCP 配置、hook、skill)
52
43
 
53
44
  MCP 配置(HTTP Transport):
@@ -80,16 +71,51 @@ function showVersion() {
80
71
  console.log(`wecom-aibot-mcp v${VERSION}`);
81
72
  }
82
73
  function showStatus() {
83
- const config = loadConfig();
84
- if (config) {
85
- console.log('当前配置:');
86
- console.log(` Bot ID: ${config.botId}`);
87
- console.log(` Secret: ${config.secret.slice(0, 8)}...${config.secret.slice(-4)}`);
88
- console.log(` 目标用户: ${config.targetUserId}`);
89
- }
90
- else {
74
+ const allRobots = listAllRobots();
75
+ const headlessStates = getAllHeadlessStates();
76
+ if (allRobots.length === 0) {
91
77
  console.log('尚未配置,请运行 npx @vrs-soft/wecom-aibot-mcp 启动配置向导');
78
+ return;
92
79
  }
80
+ // 构建机器人占用信息
81
+ const robotUsage = new Map();
82
+ for (const { state } of headlessStates) {
83
+ if (state.robotName) {
84
+ robotUsage.set(state.robotName, {
85
+ agentName: state.agentName || '未知',
86
+ projectDir: state.projectDir,
87
+ });
88
+ }
89
+ }
90
+ console.log(`已配置 ${allRobots.length} 个机器人:\n`);
91
+ for (const robot of allRobots) {
92
+ const defaultTag = robot.isDefault ? ' (默认)' : '';
93
+ const usage = robotUsage.get(robot.name);
94
+ const statusTag = usage ? ` [使用中]` : '';
95
+ console.log(` ${robot.name}${defaultTag}${statusTag}`);
96
+ console.log(` Bot ID: ${robot.botId}`);
97
+ console.log(` 目标用户: ${robot.targetUserId}`);
98
+ if (usage) {
99
+ console.log(` 使用者: ${usage.agentName} (${usage.projectDir})`);
100
+ }
101
+ console.log('');
102
+ }
103
+ }
104
+ // 等待连接验证(用于配置向导验证凭证)
105
+ async function waitForConnection(client, timeoutMs = 10000) {
106
+ return new Promise((resolve) => {
107
+ const startTime = Date.now();
108
+ const checkInterval = setInterval(() => {
109
+ if (client.isConnected()) {
110
+ clearInterval(checkInterval);
111
+ resolve(true);
112
+ }
113
+ else if (Date.now() - startTime > timeoutMs) {
114
+ clearInterval(checkInterval);
115
+ resolve(false);
116
+ }
117
+ }, 500);
118
+ });
93
119
  }
94
120
  async function main() {
95
121
  const args = process.argv.slice(2);
@@ -102,7 +128,7 @@ async function main() {
102
128
  showVersion();
103
129
  process.exit(0);
104
130
  }
105
- if (args.includes('--status')) {
131
+ if (args.includes('--status') || args.includes('--list')) {
106
132
  showStatus();
107
133
  process.exit(0);
108
134
  }
@@ -129,6 +155,9 @@ async function main() {
129
155
  console.log(' ║ Claude Code 审批通道 ║');
130
156
  console.log(' ╚════════════════════════════════════════════════════════╝');
131
157
  console.log('');
158
+ // 加载统计并清理旧日志(保留 1 小时)
159
+ loadStats();
160
+ cleanupOldLogs(1 / 24); // 保留 1 小时
132
161
  // 获取或初始化配置
133
162
  let config;
134
163
  let ranWizard = false; // 是否运行了配置向导
@@ -165,35 +194,33 @@ async function main() {
165
194
  ensureHookInstalled();
166
195
  // 清理残留的 headless 状态和 Hook 配置
167
196
  clearAllProjectHooks();
168
- // 初始化 WebSocket 客户端
169
- console.log(`[mcp] 初始化企业微信客户端...`);
170
- const wecomClient = initClient(config.botId, config.secret, config.targetUserId || 'placeholder');
171
- // 等待连接验证
172
- console.log('[mcp] 等待连接验证...');
173
- const connected = await waitForConnection(wecomClient, 10000);
174
- if (!connected) {
175
- console.log('[mcp] 连接失败,可能是配置错误或机器人未授权');
176
- console.log('[mcp] 请检查上面的错误提示,修复后重新配置');
177
- // 删除无效配置,让用户重新输入
178
- deleteConfig();
179
- if (isInteractive) {
197
+ // 配置向导模式:验证连接并识别用户 ID
198
+ if (isInteractive && (ranWizard || reconfig)) {
199
+ console.log('[mcp] 验证机器人连接...');
200
+ // 临时建立连接验证凭证
201
+ const tempClient = initClient(config.botId, config.secret, config.targetUserId || 'placeholder');
202
+ const connected = await waitForConnection(tempClient, 10000);
203
+ if (!connected) {
204
+ console.log('[mcp] 连接失败,可能是配置错误或机器人未授权');
205
+ console.log('[mcp] 请检查上面的错误提示,修复后重新配置');
206
+ // 删除无效配置,让用户重新输入
207
+ deleteConfig();
180
208
  console.log('\n请检查:');
181
209
  console.log(' 1. Bot ID 和 Secret 是否正确');
182
210
  console.log(' 2. 新建机器人需等待约 2 分钟同步');
183
211
  console.log(' 3. 是否已完成授权(机器人详情 → 可使用权限 → 授权)');
184
212
  console.log('\n修复后重新运行: npx @vrs-soft/wecom-aibot-mcp --config');
213
+ tempClient.disconnect();
214
+ process.exit(1);
185
215
  }
186
- process.exit(1);
187
- }
188
- // 连接成功
189
- if (isInteractive && (ranWizard || reconfig)) {
190
- // 需要通过消息自动识别用户 ID
216
+ // 连接成功
191
217
  console.log('\n[mcp] ✅ 机器人连接成功!');
192
218
  // 提示用户发送消息来识别用户 ID
193
- const userId = await detectUserIdFromMessage(wecomClient, 60);
219
+ const userId = await detectUserIdFromMessage(tempClient, 180);
194
220
  if (!userId) {
195
221
  console.log('\n[mcp] 未能在规定时间内识别用户 ID');
196
222
  console.log('[mcp] 请重新运行配置:npx @vrs-soft/wecom-aibot-mcp --config');
223
+ tempClient.disconnect();
197
224
  process.exit(1);
198
225
  }
199
226
  // 更新配置中的用户 ID
@@ -203,30 +230,30 @@ async function main() {
203
230
  console.log('\n[mcp] ✅ 配置完成!');
204
231
  console.log(`[mcp] 用户 ID: ${userId}`);
205
232
  console.log('[mcp] 请重启 Claude Code 以加载 MCP 服务\n');
233
+ // 配置完成后断开连接
234
+ tempClient.disconnect();
206
235
  process.exit(0);
207
236
  }
208
- // 创建 MCP Server
237
+ // 创建 MCP Server(不建立 WebSocket 连接)
209
238
  const server = new McpServer({
210
239
  name: 'wecom-aibot-mcp',
211
240
  version: VERSION,
212
241
  });
213
- // 注册工具
214
- registerTools(server, wecomClient);
215
- // 启动 HTTP 服务(包含 MCP endpoint)
242
+ // 注册工具(不传入 client,由 ConnectionManager 管理)
243
+ registerTools(server);
244
+ // 启动 HTTP 服务
216
245
  console.log(`[mcp] 启动 MCP HTTP Server (端口: ${HTTP_PORT})...`);
217
- await startHttpServer(wecomClient, server);
218
- // 定期清理过期消息
219
- const cleanupInterval = setInterval(() => {
220
- wecomClient.cleanupMessages();
221
- }, 60000);
246
+ await startHttpServer(server);
247
+ // 启动保活监控
248
+ startKeepaliveMonitor();
222
249
  console.log(`[mcp] MCP Server 已就绪`);
223
250
  console.log(`[mcp] HTTP endpoint: http://127.0.0.1:${HTTP_PORT}/mcp`);
224
251
  console.log(`[mcp] 健康检查: http://127.0.0.1:${HTTP_PORT}/health`);
225
- // 退出处理:清理资源
252
+ console.log(`[mcp] 微信模式:enter_headless_mode 时建立连接`);
253
+ // 退出处理
226
254
  const gracefulShutdown = () => {
227
255
  console.log('[mcp] 正在关闭...');
228
- clearInterval(cleanupInterval);
229
- wecomClient.disconnect();
256
+ stopKeepaliveMonitor();
230
257
  process.exit(0);
231
258
  };
232
259
  // 监听进程信号
package/dist/client.d.ts CHANGED
@@ -4,6 +4,10 @@ interface ApprovalRecord {
4
4
  result?: 'allow-once' | 'allow-always' | 'deny';
5
5
  timestamp: number;
6
6
  toolName?: string;
7
+ toolInput?: Record<string, unknown>;
8
+ projectDir?: string;
9
+ lastKeepaliveMinute?: number;
10
+ keepaliveCount?: number;
7
11
  }
8
12
  interface MessageRecord {
9
13
  msgid: string;
@@ -41,6 +45,8 @@ declare class WecomClient {
41
45
  sendApprovalRequest(title: string, description: string, requestId: string, targetUser?: string): Promise<string>;
42
46
  getApprovalResult(taskId: string): 'pending' | 'allow-once' | 'allow-always' | 'deny';
43
47
  getPendingApprovals(): string[];
48
+ getPendingApprovalsRecords(): ApprovalRecord[];
49
+ getApprovalRecord(taskId: string): ApprovalRecord | undefined;
44
50
  getLatestMessage(afterTimestamp: number): MessageRecord | undefined;
45
51
  getPendingMessages(clear?: boolean): MessageRecord[];
46
52
  cleanupMessages(maxAgeMs?: number): void;
package/dist/client.js CHANGED
@@ -5,6 +5,7 @@
5
5
  * 管理消息队列和审批状态。
6
6
  */
7
7
  import AiBot from '@wecom/aibot-node-sdk';
8
+ import { logConnected, logAuthenticated, logDisconnected, logReconnecting, logError, } from './connection-log.js';
8
9
  class WecomClient {
9
10
  wsClient;
10
11
  approvals = new Map();
@@ -22,7 +23,7 @@ class WecomClient {
22
23
  this.wsClient = new AiBot.WSClient({
23
24
  botId,
24
25
  secret,
25
- heartbeatInterval: 30000,
26
+ heartbeatInterval: 15000, // 15 秒心跳,更快检测断线
26
27
  maxReconnectAttempts: -1, // 无限重连
27
28
  });
28
29
  this.setupEventHandlers();
@@ -37,14 +38,14 @@ class WecomClient {
37
38
  }
38
39
  setupEventHandlers() {
39
40
  this.wsClient.on('connected', () => {
40
- console.log('[wecom] WebSocket 连接已建立');
41
+ logConnected();
41
42
  });
42
43
  this.wsClient.on('authenticated', () => {
43
44
  const wasReconnecting = this.wasReconnecting;
44
45
  this.connected = true;
45
46
  this.wasReconnecting = false;
46
47
  this.reconnectAttempt = 0;
47
- console.log('[wecom] 认证成功,长连接已就绪');
48
+ logAuthenticated();
48
49
  // 重连成功后发送通知
49
50
  if (wasReconnecting) {
50
51
  this.sendText('【系统】连接已恢复').catch(err => {
@@ -58,7 +59,7 @@ class WecomClient {
58
59
  this.connected = false;
59
60
  this.wasReconnecting = true;
60
61
  this.lastDisconnectTime = Date.now();
61
- console.log(`[wecom] 连接断开: ${reason}`);
62
+ logDisconnected(reason);
62
63
  // 发送断线通知
63
64
  this.sendText('【系统】连接中断,正在重连...').catch(err => {
64
65
  console.error('[wecom] 发送断线通知失败:', err);
@@ -66,10 +67,10 @@ class WecomClient {
66
67
  });
67
68
  this.wsClient.on('reconnecting', (attempt) => {
68
69
  this.reconnectAttempt = attempt;
69
- console.log(`[wecom] 正在重连 (第 ${attempt} 次)`);
70
+ logReconnecting(attempt);
70
71
  });
71
72
  this.wsClient.on('error', (err) => {
72
- console.error(`[wecom] 错误: ${err.message}`);
73
+ logError(err.message);
73
74
  // 检测授权相关错误(40058: invalid Request Parameter)
74
75
  if (err.message.includes('40058') || err.message.includes('invalid Request Parameter')) {
75
76
  console.log('');
@@ -90,6 +91,7 @@ class WecomClient {
90
91
  });
91
92
  // 监听模板卡片事件(审批结果)
92
93
  this.wsClient.on('event.template_card_event', (frame) => {
94
+ console.log('[wecom] 收到 template_card_event 事件');
93
95
  this.handleApprovalResponse(frame);
94
96
  });
95
97
  // 监听进入会话事件
@@ -304,6 +306,15 @@ class WecomClient {
304
306
  .filter(([_, a]) => !a.resolved)
305
307
  .map(([taskId, _]) => taskId);
306
308
  }
309
+ // 获取所有待处理审批记录(供保活监控使用)
310
+ getPendingApprovalsRecords() {
311
+ return Array.from(this.approvals.values())
312
+ .filter(a => !a.resolved);
313
+ }
314
+ // 获取单个审批记录
315
+ getApprovalRecord(taskId) {
316
+ return this.approvals.get(taskId);
317
+ }
307
318
  // 获取最新消息(用于等待回复)
308
319
  getLatestMessage(afterTimestamp) {
309
320
  return this.messages.find(m => m.timestamp > afterTimestamp && m.from_userid === this.targetUserId);
@@ -16,8 +16,18 @@ export declare function deleteMcpConfig(instanceName: string): boolean;
16
16
  export declare function deleteMcpConfigInteractive(instanceName?: string): Promise<void>;
17
17
  export declare function uninstall(): void;
18
18
  export declare function addMcpConfig(): Promise<void>;
19
+ export declare function listAllRobots(): Array<{
20
+ name: string;
21
+ botId: string;
22
+ targetUserId: string;
23
+ isDefault: boolean;
24
+ }>;
19
25
  export declare function ensureHookInstalled(): void;
20
26
  export declare function saveConfig(config: WecomConfig, instanceName?: string): void;
27
+ /**
28
+ * 安装 headless-mode skill 到项目目录
29
+ */
30
+ export declare function installSkill(projectDir: string): void;
21
31
  /**
22
32
  * 运行配置向导
23
33
  */
@@ -16,6 +16,9 @@ const BOT_CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
16
16
  const CLAUDE_CONFIG_FILE = path.join(os.homedir(), '.claude.json');
17
17
  const CLAUDE_SETTINGS_FILE = path.join(os.homedir(), '.claude', 'settings.local.json');
18
18
  const HOOK_SCRIPT_PATH = path.join(CONFIG_DIR, 'permission-hook.sh');
19
+ // Skill 模板路径(包内)
20
+ const SKILL_TEMPLATE_DIR = path.join(path.dirname(new URL(import.meta.url).pathname), '..', 'skills', 'headless-mode');
21
+ const SKILL_TEMPLATE_FILE = path.join(SKILL_TEMPLATE_DIR, 'SKILL.md');
19
22
  // MCP 工具权限列表(需要预授权以避免 headless 模式阻断)
20
23
  const MCP_TOOL_PERMISSIONS = [
21
24
  'mcp__wecom-aibot__*', // 允许所有 wecom-aibot 工具
@@ -222,10 +225,9 @@ function writeHookScript() {
222
225
  # HTTP Transport 版本
223
226
  #
224
227
  # 固定端口: 18963
225
- # headless-{PID} 读取 projectDir
228
+ # 直接检查 $(pwd)/.claude/headless.json
226
229
 
227
230
  MCP_PORT=18963
228
- CONFIG_DIR="$HOME/.wecom-aibot-mcp"
229
231
 
230
232
  INPUT=$(cat)
231
233
  TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
@@ -244,46 +246,12 @@ case "$TOOL_NAME" in
244
246
  ;;
245
247
  esac
246
248
 
247
- # 查找 headless 状态文件
248
- HEADLESS_FILE=""
249
- PARENT_PID=$PPID
250
-
251
- for i in {1..5}; do
252
- if [[ -z "$PARENT_PID" ]] || [[ "$PARENT_PID" -eq 1 ]]; then
253
- break
254
- fi
255
-
256
- CANDIDATE="$CONFIG_DIR/headless-$PARENT_PID"
257
- if [[ -f "$CANDIDATE" ]]; then
258
- HEADLESS_FILE="$CANDIDATE"
259
- break
260
- fi
261
-
262
- CHILD_PIDS=$(pgrep -P "$PARENT_PID" 2>/dev/null)
263
- for CHILD_PID in $CHILD_PIDS; do
264
- CANDIDATE="$CONFIG_DIR/headless-$CHILD_PID"
265
- if [[ -f "$CANDIDATE" ]]; then
266
- HEADLESS_FILE="$CANDIDATE"
267
- break 2
268
- fi
269
- done
270
-
271
- PARENT_PID=$(ps -o ppid= -p "$PARENT_PID" 2>/dev/null | tr -d ' ')
272
- done
273
-
274
- # Fallback: 使用最新的 headless 文件
275
- if [[ -z "$HEADLESS_FILE" ]]; then
276
- HEADLESS_FILE=$(ls -t "$CONFIG_DIR"/headless-* 2>/dev/null | head -1)
277
- fi
249
+ # 直接检查项目目录的 headless 状态文件
250
+ PROJECT_DIR=$(pwd)
251
+ HEADLESS_FILE="$PROJECT_DIR/.claude/headless.json"
278
252
 
279
253
  # 不在 headless 模式
280
- if [[ -z "$HEADLESS_FILE" ]] || [[ ! -f "$HEADLESS_FILE" ]]; then
281
- exit 0
282
- fi
283
-
284
- # 从 headless 文件读取 projectDir
285
- PROJECT_DIR=$(cat "$HEADLESS_FILE" 2>/dev/null | jq -r '.projectDir // empty')
286
- if [[ -z "$PROJECT_DIR" ]]; then
254
+ if [[ ! -f "$HEADLESS_FILE" ]]; then
287
255
  exit 0
288
256
  fi
289
257
 
@@ -293,7 +261,7 @@ if ! echo "$HEALTH" | jq -e '.status == "ok"' > /dev/null 2>&1; then
293
261
  exit 0
294
262
  fi
295
263
 
296
- # 发送审批请求
264
+ # 发送审批请求(使用 pwd 作为 projectDir)
297
265
  TOOL_INPUT=$(echo "$INPUT" | jq -c '.tool_input // {}')
298
266
  BODY=$(jq -n --arg tool_name "$TOOL_NAME" --argjson tool_input "$TOOL_INPUT" --arg project_dir "$PROJECT_DIR" \\
299
267
  '{"tool_name":$tool_name,"tool_input":$tool_input,"projectDir":$project_dir}')
@@ -493,7 +461,7 @@ export async function addMcpConfig() {
493
461
  return;
494
462
  }
495
463
  // 通过消息自动识别用户 ID
496
- const targetUserId = await detectUserIdFromMessage(client, 60);
464
+ const targetUserId = await detectUserIdFromMessage(client, 180);
497
465
  if (!targetUserId) {
498
466
  console.log('\n[config] 未能在规定时间内识别用户 ID');
499
467
  console.log('[config] 请重新运行: npx @vrs-soft/wecom-aibot-mcp --add');
@@ -536,7 +504,7 @@ export async function addMcpConfig() {
536
504
  }
537
505
  }
538
506
  // 列出所有机器人配置
539
- function listAllRobots() {
507
+ export function listAllRobots() {
540
508
  const robots = [];
541
509
  // 默认配置
542
510
  if (fs.existsSync(BOT_CONFIG_FILE)) {
@@ -663,6 +631,27 @@ export function saveConfig(config, instanceName) {
663
631
  writeMcpServerConfig(config, instanceName);
664
632
  // 写入 MCP 工具权限和 Hook 到 ~/.claude/settings.local.json
665
633
  writeMcpPermissions();
634
+ // 安装 skill 到项目目录
635
+ installSkill(process.cwd());
636
+ }
637
+ /**
638
+ * 安装 headless-mode skill 到项目目录
639
+ */
640
+ export function installSkill(projectDir) {
641
+ const skillDir = path.join(projectDir, '.claude', 'skills', 'headless-mode');
642
+ const skillFile = path.join(skillDir, 'SKILL.md');
643
+ // 确保 skill 目录存在
644
+ if (!fs.existsSync(skillDir)) {
645
+ fs.mkdirSync(skillDir, { recursive: true });
646
+ }
647
+ // 检查模板文件是否存在
648
+ if (!fs.existsSync(SKILL_TEMPLATE_FILE)) {
649
+ console.log('[config] Skill 模板文件不存在,跳过安装');
650
+ return;
651
+ }
652
+ // 写入 skill 文件
653
+ fs.copyFileSync(SKILL_TEMPLATE_FILE, skillFile);
654
+ console.log(`[config] 已安装 skill 到 ${skillFile}`);
666
655
  }
667
656
  // 创建 readline 接口
668
657
  function createRL() {
@@ -0,0 +1,36 @@
1
+ /**
2
+ * 连接状态日志模块
3
+ *
4
+ * 记录 WebSocket 连接状态变化,便于分析连接问题
5
+ */
6
+ interface ConnectionRecord {
7
+ event: 'connected' | 'authenticated' | 'disconnected' | 'reconnecting' | 'error';
8
+ timestamp: string;
9
+ isoTime: string;
10
+ reason?: string;
11
+ attempt?: number;
12
+ errorMessage?: string;
13
+ connectionDuration?: number;
14
+ }
15
+ interface ConnectionStats {
16
+ totalConnections: number;
17
+ totalDisconnections: number;
18
+ totalReconnects: number;
19
+ totalErrors: number;
20
+ lastConnectTime?: string;
21
+ lastDisconnectTime?: string;
22
+ longestConnection?: number;
23
+ totalConnectionTime?: number;
24
+ }
25
+ export declare function loadStats(): ConnectionStats;
26
+ export declare function logConnected(): void;
27
+ export declare function logAuthenticated(): void;
28
+ export declare function logDisconnected(reason: string): void;
29
+ export declare function logReconnecting(attempt: number): void;
30
+ export declare function logError(errorMessage: string): void;
31
+ export declare function getStats(): ConnectionStats;
32
+ export declare function getRecentLogs(count?: number): ConnectionRecord[];
33
+ export declare function cleanupOldLogs(daysToKeep?: number): void;
34
+ export declare function getLogFilePath(): string;
35
+ export declare function getStatsFilePath(): string;
36
+ export {};