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

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,26 @@
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 { spawn } from 'child_process';
17
+ import * as fs from 'fs';
18
+ import * as path from 'path';
19
+ import * as os from 'os';
20
+ import { runConfigWizard, loadConfig, saveConfig, deleteConfig, deleteMcpConfigInteractive, uninstall, addMcpConfig, detectUserIdFromMessage, ensureHookInstalled, listAllRobots, } from './config-wizard.js';
12
21
  import { initClient } from './client.js';
13
22
  import { registerTools } from './tools/index.js';
14
- import { startHttpServer, HTTP_PORT } from './http-server.js';
23
+ import { startHttpServer, stopHttpServer, HTTP_PORT } from './http-server.js';
15
24
  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
- }
25
+ import { clearAllProjectHooks, getAllHeadlessStates } from './headless-state.js';
26
+ import { loadStats, cleanupOldLogs } from './connection-log.js';
27
+ import { startKeepaliveMonitor, stopKeepaliveMonitor } from './keepalive-monitor.js';
28
+ const VERSION = '1.0.9';
29
+ const PID_FILE = path.join(os.homedir(), '.wecom-aibot-mcp', 'server.pid');
34
30
  function showHelp() {
35
31
  console.log(`
36
32
  企业微信智能机器人 MCP 服务 v${VERSION}
@@ -44,12 +40,27 @@ function showHelp() {
44
40
  选项:
45
41
  --help, -h 显示帮助信息
46
42
  --version, -v 显示版本号
43
+ --start 启动 MCP Server(后台服务模式)
44
+ --stop 停止 MCP Server
45
+ --status 显示服务状态和机器人配置
47
46
  --config 重新配置默认机器人(修改 Bot ID / Secret / 目标用户)
48
47
  --add 添加新的机器人配置(多机器人场景)
48
+ --list 列出所有已配置的机器人及其占用状态
49
49
  --delete [名称] 删除指定的机器人配置(无参数则显示列表选择)
50
- --status 显示当前配置状态
51
50
  --uninstall 卸载并删除所有配置(包括 MCP 配置、hook、skill)
52
51
 
52
+ 使用流程:
53
+ 1. 首次安装: npx @vrs-soft/wecom-aibot-mcp
54
+ (进入配置向导,完成后自动后台启动服务)
55
+
56
+ 2. 已有配置: npx @vrs-soft/wecom-aibot-mcp
57
+ (显示状态,提示使用 --start 启动)
58
+
59
+ 3. 启动服务: npx @vrs-soft/wecom-aibot-mcp --start
60
+ (后台启动 MCP HTTP Server)
61
+
62
+ 4. 停止服务: npx @vrs-soft/wecom-aibot-mcp --stop
63
+
53
64
  MCP 配置(HTTP Transport):
54
65
 
55
66
  编辑 ~/.claude.json:
@@ -58,7 +69,7 @@ MCP 配置(HTTP Transport):
58
69
  "mcpServers": {
59
70
  "wecom-aibot": {
60
71
  "type": "http",
61
- "url": "http://127.0.0.1:${HTTP_PORT}/mcp"
72
+ "url": "http://127.0.0.1:18963/mcp"
62
73
  }
63
74
  }
64
75
  }
@@ -80,16 +91,179 @@ function showVersion() {
80
91
  console.log(`wecom-aibot-mcp v${VERSION}`);
81
92
  }
82
93
  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}`);
94
+ const allRobots = listAllRobots();
95
+ const headlessStates = getAllHeadlessStates();
96
+ // 检查服务是否运行
97
+ const serverRunning = isServerRunning();
98
+ console.log(`\n服务状态: ${serverRunning ? '✅ 运行中' : '❌ 未启动'}\n`);
99
+ if (allRobots.length === 0) {
100
+ console.log('尚未配置机器人,请运行 npx @vrs-soft/wecom-aibot-mcp 启动配置向导');
101
+ return;
89
102
  }
90
- else {
91
- console.log('尚未配置,请运行 npx @vrs-soft/wecom-aibot-mcp 启动配置向导');
103
+ // 构建机器人占用信息
104
+ const robotUsage = new Map();
105
+ for (const { state } of headlessStates) {
106
+ if (state.robotName) {
107
+ robotUsage.set(state.robotName, {
108
+ agentName: state.agentName || '未知',
109
+ projectDir: state.projectDir,
110
+ });
111
+ }
112
+ }
113
+ console.log(`已配置 ${allRobots.length} 个机器人:\n`);
114
+ for (const robot of allRobots) {
115
+ const defaultTag = robot.isDefault ? ' (默认)' : '';
116
+ const usage = robotUsage.get(robot.name);
117
+ const statusTag = usage ? ` [使用中]` : '';
118
+ console.log(` ${robot.name}${defaultTag}${statusTag}`);
119
+ console.log(` Bot ID: ${robot.botId}`);
120
+ console.log(` 目标用户: ${robot.targetUserId}`);
121
+ if (usage) {
122
+ console.log(` 使用者: ${usage.agentName} (${usage.projectDir})`);
123
+ }
124
+ console.log('');
125
+ }
126
+ }
127
+ // 检查服务是否运行
128
+ function isServerRunning() {
129
+ if (!fs.existsSync(PID_FILE)) {
130
+ return false;
131
+ }
132
+ try {
133
+ const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8').trim());
134
+ // 检查进程是否存在
135
+ process.kill(pid, 0);
136
+ return true;
137
+ }
138
+ catch {
139
+ // 进程不存在,清理 PID 文件
140
+ fs.unlinkSync(PID_FILE);
141
+ return false;
142
+ }
143
+ }
144
+ // 停止服务
145
+ function stopServer() {
146
+ if (!fs.existsSync(PID_FILE)) {
147
+ console.log('[mcp] 服务未运行');
148
+ return false;
149
+ }
150
+ try {
151
+ const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8').trim());
152
+ process.kill(pid, 'SIGTERM');
153
+ // 等待进程退出
154
+ let attempts = 0;
155
+ while (attempts < 10) {
156
+ try {
157
+ process.kill(pid, 0);
158
+ // 进程还存在,等待
159
+ setTimeout(() => { }, 500);
160
+ attempts++;
161
+ }
162
+ catch {
163
+ // 进程已退出
164
+ break;
165
+ }
166
+ }
167
+ fs.unlinkSync(PID_FILE);
168
+ console.log('[mcp] 服务已停止');
169
+ return true;
170
+ }
171
+ catch (err) {
172
+ console.error('[mcp] 停止服务失败:', err);
173
+ fs.unlinkSync(PID_FILE);
174
+ return false;
175
+ }
176
+ }
177
+ // 等待连接验证(用于配置向导验证凭证)
178
+ async function waitForConnection(client, timeoutMs = 10000) {
179
+ return new Promise((resolve) => {
180
+ const startTime = Date.now();
181
+ const checkInterval = setInterval(() => {
182
+ if (client.isConnected()) {
183
+ clearInterval(checkInterval);
184
+ resolve(true);
185
+ }
186
+ else if (Date.now() - startTime > timeoutMs) {
187
+ clearInterval(checkInterval);
188
+ resolve(false);
189
+ }
190
+ }, 500);
191
+ });
192
+ }
193
+ // 启动 MCP Server(前台运行,供 --start 使用)
194
+ async function startMcpServerForeground() {
195
+ const savedConfig = loadConfig();
196
+ if (!savedConfig || !savedConfig.botId || !savedConfig.secret || !savedConfig.targetUserId) {
197
+ console.error('[mcp] 未找到配置,请先运行: npx @vrs-soft/wecom-aibot-mcp');
198
+ process.exit(1);
199
+ }
200
+ // 写入 PID 文件
201
+ fs.writeFileSync(PID_FILE, String(process.pid));
202
+ // 确保 hook 已安装
203
+ ensureHookInstalled();
204
+ // 清理残留的 headless 状态
205
+ clearAllProjectHooks();
206
+ // 加载统计并清理旧日志
207
+ loadStats();
208
+ cleanupOldLogs(1 / 24);
209
+ // 创建 MCP Server
210
+ const server = new McpServer({
211
+ name: 'wecom-aibot-mcp',
212
+ version: VERSION,
213
+ });
214
+ registerTools(server);
215
+ // 启动 HTTP 服务
216
+ console.log('');
217
+ console.log(' ╔════════════════════════════════════════════════════════╗');
218
+ console.log(` ║ 企业微信智能机器人 MCP 服务 v${VERSION} ║`);
219
+ console.log(' ║ Claude Code 审批通道 ║');
220
+ console.log(' ╚════════════════════════════════════════════════════════╝');
221
+ console.log('');
222
+ console.log(`[mcp] 启动 MCP HTTP Server (端口: ${HTTP_PORT})...`);
223
+ await startHttpServer(server);
224
+ startKeepaliveMonitor();
225
+ console.log(`[mcp] MCP Server 已就绪`);
226
+ console.log(`[mcp] HTTP endpoint: http://127.0.0.1:${HTTP_PORT}/mcp`);
227
+ console.log(`[mcp] 健康检查: http://127.0.0.1:${HTTP_PORT}/health`);
228
+ console.log(`[mcp] 微信模式:enter_headless_mode 时建立连接`);
229
+ console.log(`[mcp] PID: ${process.pid}`);
230
+ // 退出处理
231
+ const gracefulShutdown = () => {
232
+ console.log('[mcp] 正在关闭...');
233
+ stopKeepaliveMonitor();
234
+ stopHttpServer();
235
+ if (fs.existsSync(PID_FILE)) {
236
+ fs.unlinkSync(PID_FILE);
237
+ }
238
+ process.exit(0);
239
+ };
240
+ process.on('SIGINT', gracefulShutdown);
241
+ process.on('SIGTERM', gracefulShutdown);
242
+ }
243
+ // 后台启动 MCP Server(使用 spawn)
244
+ function startMcpServerBackground() {
245
+ // 检查配置是否存在
246
+ const savedConfig = loadConfig();
247
+ if (!savedConfig || !savedConfig.botId || !savedConfig.secret || !savedConfig.targetUserId) {
248
+ console.error('[mcp] 未找到配置,请先运行: npx @vrs-soft/wecom-aibot-mcp');
249
+ process.exit(1);
250
+ }
251
+ // 检查是否已运行
252
+ if (isServerRunning()) {
253
+ console.log('[mcp] 服务已在运行中');
254
+ return;
92
255
  }
256
+ const nodePath = process.execPath;
257
+ const scriptPath = process.argv[1];
258
+ const child = spawn(nodePath, [scriptPath, '--start', '--foreground'], {
259
+ detached: true,
260
+ stdio: 'ignore',
261
+ });
262
+ child.unref();
263
+ console.log('[mcp] MCP Server 已在后台启动');
264
+ console.log(`[mcp] HTTP endpoint: http://127.0.0.1:18963/mcp`);
265
+ console.log('[mcp] 健康检查: curl http://127.0.0.1:18963/health');
266
+ console.log('[mcp] 停止服务: npx @vrs-soft/wecom-aibot-mcp --stop');
93
267
  }
94
268
  async function main() {
95
269
  const args = process.argv.slice(2);
@@ -102,11 +276,21 @@ async function main() {
102
276
  showVersion();
103
277
  process.exit(0);
104
278
  }
105
- if (args.includes('--status')) {
279
+ if (args.includes('--status') || args.includes('--list')) {
106
280
  showStatus();
107
281
  process.exit(0);
108
282
  }
283
+ // --stop 命令:停止服务
284
+ if (args.includes('--stop')) {
285
+ stopServer();
286
+ process.exit(0);
287
+ }
288
+ // --uninstall 命令:先停止服务再卸载
109
289
  if (args.includes('--uninstall')) {
290
+ if (isServerRunning()) {
291
+ console.log('[mcp] 正在停止服务...');
292
+ stopServer();
293
+ }
110
294
  uninstall();
111
295
  process.exit(0);
112
296
  }
@@ -121,6 +305,16 @@ async function main() {
121
305
  await deleteMcpConfigInteractive(instanceName);
122
306
  process.exit(0);
123
307
  }
308
+ // --start --foreground:前台启动(内部调用)
309
+ if (args.includes('--start') && args.includes('--foreground')) {
310
+ await startMcpServerForeground();
311
+ return; // 保持运行,不 exit
312
+ }
313
+ // --start:后台启动
314
+ if (args.includes('--start')) {
315
+ startMcpServerBackground();
316
+ process.exit(0);
317
+ }
124
318
  const reconfig = args.includes('--config');
125
319
  const isInteractive = process.stdin.isTTY; // 是否为用户交互模式
126
320
  console.log('');
@@ -129,6 +323,9 @@ async function main() {
129
323
  console.log(' ║ Claude Code 审批通道 ║');
130
324
  console.log(' ╚════════════════════════════════════════════════════════╝');
131
325
  console.log('');
326
+ // 加载统计并清理旧日志(保留 1 小时)
327
+ loadStats();
328
+ cleanupOldLogs(1 / 24);
132
329
  // 获取或初始化配置
133
330
  let config;
134
331
  let ranWizard = false; // 是否运行了配置向导
@@ -165,35 +362,33 @@ async function main() {
165
362
  ensureHookInstalled();
166
363
  // 清理残留的 headless 状态和 Hook 配置
167
364
  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) {
365
+ // 配置向导模式:验证连接并识别用户 ID
366
+ if (isInteractive && (ranWizard || reconfig)) {
367
+ console.log('[mcp] 验证机器人连接...');
368
+ // 临时建立连接验证凭证
369
+ const tempClient = initClient(config.botId, config.secret, config.targetUserId || 'placeholder');
370
+ const connected = await waitForConnection(tempClient, 10000);
371
+ if (!connected) {
372
+ console.log('[mcp] 连接失败,可能是配置错误或机器人未授权');
373
+ console.log('[mcp] 请检查上面的错误提示,修复后重新配置');
374
+ // 删除无效配置,让用户重新输入
375
+ deleteConfig();
180
376
  console.log('\n请检查:');
181
377
  console.log(' 1. Bot ID 和 Secret 是否正确');
182
378
  console.log(' 2. 新建机器人需等待约 2 分钟同步');
183
379
  console.log(' 3. 是否已完成授权(机器人详情 → 可使用权限 → 授权)');
184
380
  console.log('\n修复后重新运行: npx @vrs-soft/wecom-aibot-mcp --config');
381
+ tempClient.disconnect();
382
+ process.exit(1);
185
383
  }
186
- process.exit(1);
187
- }
188
- // 连接成功
189
- if (isInteractive && (ranWizard || reconfig)) {
190
- // 需要通过消息自动识别用户 ID
384
+ // 连接成功
191
385
  console.log('\n[mcp] ✅ 机器人连接成功!');
192
386
  // 提示用户发送消息来识别用户 ID
193
- const userId = await detectUserIdFromMessage(wecomClient, 60);
387
+ const userId = await detectUserIdFromMessage(tempClient, 180);
194
388
  if (!userId) {
195
389
  console.log('\n[mcp] 未能在规定时间内识别用户 ID');
196
390
  console.log('[mcp] 请重新运行配置:npx @vrs-soft/wecom-aibot-mcp --config');
391
+ tempClient.disconnect();
197
392
  process.exit(1);
198
393
  }
199
394
  // 更新配置中的用户 ID
@@ -202,36 +397,18 @@ async function main() {
202
397
  saveConfig(config, instanceName);
203
398
  console.log('\n[mcp] ✅ 配置完成!');
204
399
  console.log(`[mcp] 用户 ID: ${userId}`);
400
+ // 配置完成后断开连接
401
+ tempClient.disconnect();
402
+ // 首次安装后自动后台启动服务
403
+ console.log('\n[mcp] 正在后台启动 MCP Server...');
404
+ startMcpServerBackground();
205
405
  console.log('[mcp] 请重启 Claude Code 以加载 MCP 服务\n');
206
406
  process.exit(0);
207
407
  }
208
- // 创建 MCP Server
209
- const server = new McpServer({
210
- name: 'wecom-aibot-mcp',
211
- version: VERSION,
212
- });
213
- // 注册工具
214
- registerTools(server, wecomClient);
215
- // 启动 HTTP 服务(包含 MCP endpoint)
216
- console.log(`[mcp] 启动 MCP HTTP Server (端口: ${HTTP_PORT})...`);
217
- await startHttpServer(wecomClient, server);
218
- // 定期清理过期消息
219
- const cleanupInterval = setInterval(() => {
220
- wecomClient.cleanupMessages();
221
- }, 60000);
222
- console.log(`[mcp] MCP Server 已就绪`);
223
- console.log(`[mcp] HTTP endpoint: http://127.0.0.1:${HTTP_PORT}/mcp`);
224
- console.log(`[mcp] 健康检查: http://127.0.0.1:${HTTP_PORT}/health`);
225
- // 退出处理:清理资源
226
- const gracefulShutdown = () => {
227
- console.log('[mcp] 正在关闭...');
228
- clearInterval(cleanupInterval);
229
- wecomClient.disconnect();
230
- process.exit(0);
231
- };
232
- // 监听进程信号
233
- process.on('SIGINT', gracefulShutdown);
234
- process.on('SIGTERM', gracefulShutdown);
408
+ // 已有配置,显示状态并提示启动命令
409
+ showStatus();
410
+ console.log('\n[mcp] 使用 --start 启动服务,--stop 停止服务');
411
+ console.log('[mcp] 命令: npx @vrs-soft/wecom-aibot-mcp --start\n');
235
412
  }
236
413
  main().catch((err) => {
237
414
  console.error('[mcp] 启动失败:', err);
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
  */