@vrs-soft/wecom-aibot-mcp 1.5.0 → 2.3.0
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/README.md +50 -337
- package/dist/bin.js +172 -85
- package/dist/channel-server.d.ts +15 -0
- package/dist/channel-server.js +492 -0
- package/dist/channel-server.test.d.ts +5 -0
- package/dist/channel-server.test.js +324 -0
- package/dist/client-pool.js +4 -3
- package/dist/client.js +49 -49
- package/dist/config-wizard.d.ts +13 -3
- package/dist/config-wizard.js +424 -141
- package/dist/connection-log.js +7 -6
- package/dist/connection-manager.d.ts +0 -8
- package/dist/connection-manager.js +11 -23
- package/dist/daemon.js +7 -6
- package/dist/headless-state.d.ts +0 -12
- package/dist/headless-state.js +11 -35
- package/dist/http-server.d.ts +21 -2
- package/dist/http-server.js +421 -88
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/keepalive-monitor.js +5 -4
- package/dist/logger.d.ts +51 -0
- package/dist/logger.js +84 -0
- package/dist/message-bus.d.ts +13 -1
- package/dist/message-bus.js +56 -3
- package/dist/project-config.d.ts +16 -0
- package/dist/project-config.js +91 -12
- package/dist/tools/index.js +226 -57
- package/package.json +1 -1
- package/skills/headless-mode/SKILL.md +136 -181
|
@@ -5,257 +5,212 @@ description: 当用户说「现在开始通过微信联系」时触发,进入
|
|
|
5
5
|
|
|
6
6
|
# Headless 微信交互模式
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
**触发词**:「现在开始通过微信联系」「我要离开电脑前」「切换到微信模式」
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## 进入微信模式流程
|
|
11
11
|
|
|
12
|
-
MCP
|
|
12
|
+
> **关键原则**:模式决定 MCP 前缀。Channel 模式全程用 `mcp__wecom-aibot-channel__`,HTTP 模式全程用 `mcp__wecom-aibot__`。**必须先确定模式,再进行后续操作。**
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
### 1. 确定运行模式
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
**必须首先用 AskUserQuestion 让用户选择**(或读取 `.claude/wecom-aibot.json` 中已保存的 mode):
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
- **Channel 模式**:消息自动推送唤醒,需要用以下命令启动 Claude(研究预览阶段):
|
|
19
|
+
`claude --dangerously-load-development-channels server:wecom-aibot-channel`
|
|
20
|
+
- **HTTP 模式**:心跳轮询,兼容所有环境(API Key、中转服务均可)
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
## 启动时自动恢复
|
|
23
|
-
|
|
24
|
-
**检查文件**:`项目目录/.claude/wecom-aibot.json`
|
|
22
|
+
> 如果当前会话是通过 `--dangerously-load-development-channels` 启动的,默认选 Channel 模式。
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
1. 读取 wecom-aibot.json 获取 robotName(用于选择机器人)
|
|
30
|
-
2. 调用 enter_headless_mode(agent_name, robot_id=robotName)
|
|
31
|
-
3. 服务端返回新的 ccId(如 cc-1)
|
|
32
|
-
4. 发送消息:【进度】已自动恢复微信模式
|
|
33
|
-
5. 开始长轮询
|
|
34
|
-
```
|
|
24
|
+
根据选择,确定后续所有工具调用的 **MCP 前缀**:
|
|
25
|
+
- Channel 模式 → `MCP = mcp__wecom-aibot-channel__`
|
|
26
|
+
- HTTP 模式 → `MCP = mcp__wecom-aibot__`
|
|
35
27
|
|
|
36
|
-
|
|
28
|
+
### 2. 检查配置文件
|
|
37
29
|
|
|
38
|
-
|
|
30
|
+
检查项目目录 `.claude/wecom-aibot.json`:
|
|
39
31
|
|
|
40
|
-
|
|
32
|
+
**a) 文件存在**
|
|
33
|
+
- 读取 robotName 和 ccId,直接跳到步骤 4
|
|
41
34
|
|
|
42
|
-
|
|
35
|
+
**b) 文件不存在**
|
|
36
|
+
- 执行以下准备步骤:
|
|
43
37
|
|
|
44
|
-
|
|
38
|
+
#### 2.1 生成 ccId
|
|
45
39
|
|
|
46
|
-
|
|
47
|
-
- **sessionId**: MCP HTTP Transport 要求在 `initialize` 请求时获取 sessionId,后续所有请求必须在 `mcp-session-id` header 中传递。Claude Code **自动处理** sessionId,智能体无需手动管理。
|
|
48
|
-
- **工具命名**: 所有工具名称格式为 `mcp__wecom-aibot__<tool_name>`(例如 `mcp__wecom-aibot__send_message`)
|
|
40
|
+
格式:`${项目名}`(如 `wecom-aibot-mcp`)
|
|
49
41
|
|
|
50
|
-
|
|
42
|
+
**禁止自动编号**,如有冲突提示用户改名。
|
|
51
43
|
|
|
52
|
-
|
|
53
|
-
- ❌ 不需要手动传递 HTTP headers
|
|
54
|
-
- ❌ 不需要了解 MCP 协议细节
|
|
55
|
-
- ✅ 只需调用 MCP 工具,Claude Code 自动处理底层通信
|
|
44
|
+
#### 2.2 选择机器人
|
|
56
45
|
|
|
57
|
-
|
|
46
|
+
调用 `${MCP}list_robots`:
|
|
58
47
|
|
|
59
|
-
|
|
48
|
+
- 机器人数量 = 1 → 直接使用
|
|
49
|
+
- 机器人数量 > 1 → **必须用 AskUserQuestion 让用户选择**
|
|
60
50
|
|
|
61
|
-
|
|
62
|
-
|------|-------------|----------|
|
|
63
|
-
| 进入微信模式 | `mcp__wecom-aibot__enter_headless_mode` | agent_name, project_dir |
|
|
64
|
-
| 发送消息 | `mcp__wecom-aibot__send_message` | cc_id, content |
|
|
65
|
-
| 获取消息(长轮询默认30秒间隔) | `mcp__wecom-aibot__get_pending_messages` | cc_id |
|
|
66
|
-
| 退出微信模式 | `mcp__wecom-aibot__exit_headless_mode` | cc_id, project_dir |
|
|
51
|
+
### 3. 调用 enter_headless_mode
|
|
67
52
|
|
|
68
|
-
|
|
53
|
+
使用步骤 1 确定的 MCP 前缀:
|
|
69
54
|
|
|
70
|
-
|
|
55
|
+
```
|
|
56
|
+
${MCP}enter_headless_mode(
|
|
57
|
+
cc_id="<项目名>",
|
|
58
|
+
robot_id="<机器人名称>",
|
|
59
|
+
mode="<channel 或 http>",
|
|
60
|
+
project_dir="<项目目录>"
|
|
61
|
+
)
|
|
62
|
+
```
|
|
71
63
|
|
|
72
|
-
|
|
64
|
+
例如 Channel 模式:
|
|
65
|
+
```
|
|
66
|
+
mcp__wecom-aibot-channel__enter_headless_mode(cc_id="知识库", robot_id="CC", mode="channel", project_dir="...")
|
|
67
|
+
```
|
|
73
68
|
|
|
74
|
-
|
|
69
|
+
例如 HTTP 模式:
|
|
70
|
+
```
|
|
71
|
+
mcp__wecom-aibot__enter_headless_mode(cc_id="知识库", robot_id="CC", mode="http", project_dir="...")
|
|
72
|
+
```
|
|
75
73
|
|
|
76
|
-
|
|
77
|
-
- **文件存在且有 robotName** → 直接使用该 robotName,跳过机器人选择
|
|
78
|
-
- **文件不存在或没有 robotName** → 需要用户选择机器人
|
|
74
|
+
### 2. 处理返回结果
|
|
79
75
|
|
|
80
|
-
|
|
76
|
+
**返回字段**:
|
|
77
|
+
- `status: 'entered'` → 进入成功(重连时直接覆盖,无需改名)
|
|
81
78
|
|
|
82
|
-
|
|
79
|
+
### 3. HTTP 模式:立即执行心跳
|
|
83
80
|
|
|
84
|
-
|
|
81
|
+
**强制步骤,必须执行**:
|
|
85
82
|
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
1. 执行定时任务:
|
|
84
|
+
```
|
|
85
|
+
/loop 1m mcp__wecom-aibot__heartbeat_check
|
|
86
|
+
```
|
|
88
87
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
```
|
|
88
|
+
返回示例:
|
|
89
|
+
```
|
|
90
|
+
已创建定时任务,job ID: abc12345
|
|
91
|
+
每 1 分钟执行一次
|
|
92
|
+
```
|
|
94
93
|
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
1. 检查项目目录下的 .claude/wecom-aibot.json 是否存在
|
|
98
|
-
- 存在 → 读取 robotName
|
|
99
|
-
- 不存在 → robotName = null
|
|
100
|
-
2. 调用 list_robots 获取机器人列表
|
|
101
|
-
3. 判断:
|
|
102
|
-
- 如果 robotName 存在 → 使用该 robotName
|
|
103
|
-
- 如果机器人数量 = 1 → 使用该机器人
|
|
104
|
-
- 如果机器人数量 > 1 且没有 robotName → 使用 AskUserQuestion 让用户选择
|
|
105
|
-
4. 调用 enter_headless_mode(agent_name, robot_id=确定的机器人名称)
|
|
106
|
-
```
|
|
94
|
+
2. 提取返回中的 job ID(如 `abc12345`)
|
|
107
95
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
-
|
|
111
|
-
|
|
112
|
-
- ❌ 忽略项目配置文件中的 robotName
|
|
96
|
+
3. 调用 MCP 工具保存 job ID:
|
|
97
|
+
```
|
|
98
|
+
mcp__wecom-aibot__update_heartbeat_job_id(cc_id="<ccId>", job_id="abc12345")
|
|
99
|
+
```
|
|
113
100
|
|
|
114
|
-
|
|
101
|
+
**注意**:此步骤必须在进入微信模式后立即执行,否则无法接收消息。
|
|
115
102
|
|
|
116
|
-
|
|
103
|
+
### 4. 开始轮询
|
|
117
104
|
|
|
105
|
+
**HTTP 模式**:
|
|
118
106
|
```
|
|
119
|
-
|
|
107
|
+
while (true):
|
|
108
|
+
result = mcp__wecom-aibot__get_pending_messages(timeout_ms=30000)
|
|
109
|
+
if result.messages → 处理消息,回复,继续轮询
|
|
110
|
+
if result.timeout → 立即重新调用
|
|
120
111
|
```
|
|
121
112
|
|
|
122
|
-
|
|
123
|
-
- `agent_name`: **必填**,智能体名称(使用当前项目名称或任务名称,如 "wecom-aibot-mcp"、"ModuleStudio")
|
|
124
|
-
- `robot_id`: **必填**(多机器人场景),指定机器人名称
|
|
125
|
-
- `project_dir`: **必填**,项目目录路径(用于写入 `.claude/wecom-aibot.json` 配置文件)
|
|
113
|
+
**Channel 模式**:等待推送,无需轮询。消息到达时 Claude 会被自动唤醒。
|
|
126
114
|
|
|
127
|
-
|
|
128
|
-
- `entered` → 返回 `ccId`(服务端生成),继续下一步
|
|
129
|
-
|
|
130
|
-
**注意**:
|
|
131
|
-
- ccId 由 MCP Server 自动生成(如 `cc-1`),无需手动指定
|
|
132
|
-
- 如果正确执行了步骤 1(机器人选择),不会收到 `select_robot` 状态
|
|
133
|
-
- **进入微信模式时,MCP 会自动写入 `.claude/wecom-aibot.json`,设置 `wechatMode: true` 和 `robotName`**
|
|
115
|
+
---
|
|
134
116
|
|
|
135
|
-
|
|
117
|
+
## 消息处理
|
|
136
118
|
|
|
137
|
-
|
|
119
|
+
### 收到消息后
|
|
138
120
|
|
|
139
|
-
|
|
121
|
+
**HTTP 模式**:
|
|
122
|
+
1. 立即发送确认:`mcp__wecom-aibot__send_message(cc_id, "收到...", target_user=<chatid>)`
|
|
123
|
+
2. 执行操作(Bash/Edit/Write)
|
|
124
|
+
3. 发送结果:`mcp__wecom-aibot__send_message(cc_id, "【完成】...", target_user=<chatid>)`
|
|
125
|
+
4. 继续轮询
|
|
140
126
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
{
|
|
146
|
-
"matcher": "",
|
|
147
|
-
"hooks": [{ "type": "command", "command": "~/.wecom-aibot-mcp/permission-hook.sh" }]
|
|
148
|
-
}
|
|
149
|
-
]
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
```
|
|
127
|
+
**Channel 模式**(收到 `<channel>` 标签时):
|
|
128
|
+
1. 立即发送确认:`mcp__wecom-aibot-channel__send_message(cc_id, "收到...", target_user=<chatid>)`
|
|
129
|
+
2. 执行操作(Bash/Edit/Write)
|
|
130
|
+
3. 发送结果:`mcp__wecom-aibot-channel__send_message(cc_id, "【完成】...", target_user=<chatid>)`
|
|
153
131
|
|
|
154
|
-
|
|
132
|
+
### 回复路由
|
|
155
133
|
|
|
156
|
-
|
|
134
|
+
`get_pending_messages` 返回的每条消息包含:
|
|
135
|
+
- `from`:发送者用户 ID
|
|
136
|
+
- `chatid`:会话 ID(单聊=用户ID,群聊=群ID,如 `wr0Q...`)
|
|
137
|
+
- `chattype`:`single` 或 `group`
|
|
157
138
|
|
|
158
|
-
|
|
139
|
+
**回复时必须将 `chatid` 作为 `target_user` 传入**,确保回复到正确的会话:
|
|
159
140
|
|
|
160
141
|
```
|
|
161
|
-
|
|
142
|
+
msg = messages[0]
|
|
143
|
+
send_message(cc_id, content, target_user=msg.chatid)
|
|
162
144
|
```
|
|
163
145
|
|
|
164
|
-
|
|
146
|
+
- 单聊:`chatid` = 发送者的用户 ID,等同于默认目标,可省略
|
|
147
|
+
- 群聊:`chatid` = 群 ID,**必须传入**,否则会发到默认的单聊用户
|
|
165
148
|
|
|
166
|
-
|
|
149
|
+
### 消息格式
|
|
167
150
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if result.timeout → 立即重新调用(不需要 sleep,不需要任何等待)
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
**timeout 不是停止信号**:
|
|
176
|
-
- `timeout: true` 只表示"这 30 秒内没有消息"
|
|
177
|
-
- 收到 timeout 后立即重新调用 `get_pending_messages`
|
|
178
|
-
- 长轮询会阻塞等待,有消息立即唤醒,无消息等满超时后才消耗 token
|
|
179
|
-
- 比短轮询节省约 6 倍 token
|
|
151
|
+
- `【进度】` - 里程碑汇报
|
|
152
|
+
- `【完成】` - 任务完成
|
|
153
|
+
- `【问题】` - 需用户决策
|
|
154
|
+
- `【需要确认】` - 二次确认
|
|
180
155
|
|
|
181
156
|
---
|
|
182
157
|
|
|
183
|
-
##
|
|
158
|
+
## 任务完成检查
|
|
184
159
|
|
|
185
|
-
|
|
186
|
-
2. 理解意图
|
|
187
|
-
3. 执行操作(Bash/Edit/Write 等)— Hook 自动处理审批,Claude 阻塞等待用户点击
|
|
188
|
-
4. 用 `mcp__wecom-aibot__send_message` 汇报结果
|
|
189
|
-
5. 继续轮询
|
|
160
|
+
**每次完成任务后必须执行**:
|
|
190
161
|
|
|
191
|
-
|
|
162
|
+
1. 检查 `.claude/wecom-aibot.json`
|
|
163
|
+
2. 如果 `autoApprove: true`:
|
|
164
|
+
- 发送结果到微信
|
|
165
|
+
- 恢复轮询(HTTP 模式)
|
|
192
166
|
|
|
193
167
|
---
|
|
194
168
|
|
|
195
|
-
##
|
|
196
|
-
|
|
197
|
-
**每次完成用户任务后,必须执行以下检查:**
|
|
198
|
-
|
|
199
|
-
```python
|
|
200
|
-
def on_task_complete():
|
|
201
|
-
# 步骤 1: 检查配置文件
|
|
202
|
-
config = read_file(".claude/wecom-aibot.json")
|
|
203
|
-
|
|
204
|
-
if config and config.get("autoApprove") == True:
|
|
205
|
-
# 步骤 2: 必须通过 MCP 发送结果
|
|
206
|
-
send_message("【完成】任务结果...")
|
|
207
|
-
|
|
208
|
-
# 步骤 3: 必须恢复轮询
|
|
209
|
-
while True:
|
|
210
|
-
msg = get_pending_messages(timeout_ms=60000)
|
|
211
|
-
if msg:
|
|
212
|
-
handle_message(msg)
|
|
213
|
-
# timeout 后立即重新调用,不需要 sleep
|
|
214
|
-
```
|
|
169
|
+
## 退出微信模式
|
|
215
170
|
|
|
216
|
-
|
|
217
|
-
- 配置文件存在且 `autoApprove: true` = 用户期望通过微信接收结果
|
|
218
|
-
- 不执行 = 用户收不到结果,CC 被判定为离线
|
|
171
|
+
**触发词**:「结束微信模式」「我回来了」
|
|
219
172
|
|
|
220
|
-
|
|
173
|
+
1. **停止心跳定时任务**(HTTP 模式)
|
|
174
|
+
|
|
175
|
+
a) 读取 `.claude/wecom-aibot.json` 中的 `heartbeatJobId`
|
|
176
|
+
|
|
177
|
+
b) 执行删除:
|
|
178
|
+
```
|
|
179
|
+
/loop stop <heartbeatJobId>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
c) 删除配置文件中的 `heartbeatJobId` 字段
|
|
221
183
|
|
|
222
|
-
|
|
184
|
+
2. 调用 `mcp__wecom-aibot__exit_headless_mode(cc_id, project_dir)`
|
|
223
185
|
|
|
224
|
-
|
|
186
|
+
3. 删除 PermissionRequest hook
|
|
225
187
|
|
|
226
|
-
|
|
188
|
+
4. 发送退出通知
|
|
227
189
|
|
|
228
|
-
1. 调用 `mcp__wecom-aibot__exit_headless_mode(cc_id, project_dir)`
|
|
229
|
-
2. **MCP 自动更新 `.claude/wecom-aibot.json` 的 `wechatMode` 为 `false`**
|
|
230
|
-
3. 从 `.claude/settings.json` 删除 `hooks.PermissionRequest` 字段(如果之前配置了)
|
|
231
|
-
4. 发送 `mcp__wecom-aibot__send_message("【进度】已退出微信模式,恢复终端交互。")`
|
|
232
190
|
5. 停止轮询
|
|
233
191
|
|
|
234
|
-
**「我已经回到电脑旁了」** → 先确认:
|
|
235
|
-
```
|
|
236
|
-
mcp__wecom-aibot__send_message("【需要确认】是否结束微信模式?回复「是」退出,「否」继续。")
|
|
237
|
-
```
|
|
238
|
-
|
|
239
192
|
---
|
|
240
193
|
|
|
241
|
-
##
|
|
242
|
-
|
|
243
|
-
**正确格式**:`【标签】消息内容`
|
|
194
|
+
## MCP 工具列表
|
|
244
195
|
|
|
245
|
-
|
|
|
246
|
-
|
|
247
|
-
|
|
|
248
|
-
|
|
|
249
|
-
|
|
|
250
|
-
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
196
|
+
| 工具 | 用途 | 参数 |
|
|
197
|
+
|------|------|------|
|
|
198
|
+
| `get_setup_requirements` | 获取配置需求 | 无 |
|
|
199
|
+
| `enter_headless_mode` | 进入微信模式 | cc_id, robot_id, mode, project_dir |
|
|
200
|
+
| `send_message` | 发送消息 | cc_id, content, target_user(可选) |
|
|
201
|
+
| `get_pending_messages` | 获取消息(HTTP模式) | cc_id, timeout_ms |
|
|
202
|
+
| `heartbeat_check` | 心跳检查(HTTP模式) | 无 |
|
|
203
|
+
| `update_heartbeat_job_id` | 保存心跳 job ID(HTTP模式) | cc_id, job_id |
|
|
204
|
+
| `get_skill` | 获取 skill 文件 | 无(远程部署用) |
|
|
205
|
+
| `exit_headless_mode` | 退出微信模式 | cc_id, project_dir |
|
|
255
206
|
|
|
256
207
|
---
|
|
257
208
|
|
|
258
|
-
##
|
|
209
|
+
## 运行模式对比
|
|
259
210
|
|
|
260
|
-
|
|
261
|
-
|
|
211
|
+
| 特性 | Channel 模式 | HTTP 模式 |
|
|
212
|
+
|------|-------------|----------|
|
|
213
|
+
| 消息接收 | SSE 自动推送 | 主动轮询 |
|
|
214
|
+
| 唤醒方式 | notification 自动 | heartbeat + 轮询 |
|
|
215
|
+
| 启动要求 | `--dangerously-load-development-channels server:wecom-aibot-channel` | 无特殊要求 |
|
|
216
|
+
| 适用 LLM | 仅 Claude | 所有 LLM |
|