@core-workspace/infoflow-openclaw-plugin 2026.3.9 → 2026.3.32
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/CHANGELOG.md +21 -0
- package/README.md +142 -50
- package/docs/qa-feature-list.md +413 -0
- package/index.ts +25 -1
- package/openclaw.plugin.json +22 -1
- package/package.json +15 -4
- package/publish.sh +221 -0
- package/scripts/deploy.sh +1 -1
- package/scripts/npm-tools/README.md +70 -0
- package/scripts/npm-tools/cli.js +262 -0
- package/scripts/npm-tools/package.json +21 -0
- package/skills/infoflow-dev/references/api.md +1 -1
- package/src/adapter/inbound/ws-receiver.ts +71 -29
- package/src/adapter/outbound/reply-dispatcher.ts +12 -19
- package/src/channel/accounts.ts +26 -6
- package/src/channel/channel.ts +5 -4
- package/src/channel/media.ts +8 -0
- package/src/channel/outbound.ts +15 -7
- package/src/commands/changelog.ts +53 -0
- package/src/commands/doctor.ts +391 -0
- package/src/commands/logs.ts +212 -0
- package/src/handler/message-handler.ts +77 -82
- package/src/security/group-policy.ts +2 -0
- package/src/types.ts +20 -4
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
# OpenClaw Infoflow 插件功能清单(提测文档)
|
|
2
|
+
|
|
3
|
+
> 版本:提测版本
|
|
4
|
+
> 日期:2026-03-17
|
|
5
|
+
> 提供方:研发
|
|
6
|
+
> 用途:QA 编写测试 Case 参考
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 一、功能模块总览
|
|
11
|
+
|
|
12
|
+
| 模块 | 功能概述 |
|
|
13
|
+
|------|----------|
|
|
14
|
+
| 连接管理 | 支持 Webhook / WebSocket 两种连接方式 |
|
|
15
|
+
| 私聊消息 | 接收、处理、回复私聊消息(文本 + 图片) |
|
|
16
|
+
| 群聊消息 | 接收、处理、回复群消息(文本 + 图片 + @mention + 引用) |
|
|
17
|
+
| 安全策略 | DM 权限策略、群组权限策略 |
|
|
18
|
+
| 群聊行为控制 | 5 种 replyMode、followUp 跟进窗口、watchMentions/watchRegex |
|
|
19
|
+
| 消息分片 | 长消息自动分片发送(Markdown 感知,默认 1800 字符/片) |
|
|
20
|
+
| 消息撤回 | 私聊/群聊消息撤回(按 ID 或按数量) |
|
|
21
|
+
| 图片处理 | 接收图片并传给 LLM;发送图片(含压缩降级、链接 fallback) |
|
|
22
|
+
| @mention | 发送时 @全体 / @指定用户;识别群消息中的 @机器人 |
|
|
23
|
+
| 引用回复 | 群聊支持 quote 模式引用回复 |
|
|
24
|
+
| 处理提示 | LLM 思考中自动发送"⏳ 处理中...",完成后发"任务完成 ✨" |
|
|
25
|
+
| 多账号 | 支持配置多个如流账号,独立启停 |
|
|
26
|
+
| infoflow-doctor | 一键自检命令,检查配置和 API 连通性 |
|
|
27
|
+
| infoflow-logs | 查看最近收发消息日志,支持翻页 |
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 二、连接管理
|
|
32
|
+
|
|
33
|
+
### 2.1 Webhook 模式(默认)
|
|
34
|
+
|
|
35
|
+
**配置项:**
|
|
36
|
+
|
|
37
|
+
| 参数 | 必填 | 说明 |
|
|
38
|
+
|------|------|------|
|
|
39
|
+
| `appKey` | 是 | 应用唯一标识 |
|
|
40
|
+
| `appSecret` | 是 | 应用密钥 |
|
|
41
|
+
| `checkToken` | 是 | Webhook 签名验证 Token |
|
|
42
|
+
| `encodingAESKey` | 是 | 消息 AES 解密密钥 |
|
|
43
|
+
| `apiHost` | 否 | 默认 `http://apiin.im.baidu.com` |
|
|
44
|
+
|
|
45
|
+
**行为:**
|
|
46
|
+
- 接收如流平台推送的 HTTP 回调请求
|
|
47
|
+
- 验证签名(checkToken 校验)后解密消息体(AES 解密)
|
|
48
|
+
- Webhook 路径:`POST /webhook/infoflow`
|
|
49
|
+
|
|
50
|
+
### 2.2 WebSocket 模式
|
|
51
|
+
|
|
52
|
+
**配置项:**
|
|
53
|
+
|
|
54
|
+
| 参数 | 必填 | 说明 |
|
|
55
|
+
|------|------|------|
|
|
56
|
+
| `connectionMode` | 是 | 设置为 `"websocket"` |
|
|
57
|
+
| `wsGateway` | 否 | WS Gateway 域名,默认 `infoflow-open-gateway.weiyun.baidu.com` |
|
|
58
|
+
|
|
59
|
+
**行为:**
|
|
60
|
+
- 建立 WebSocket 长连接,自动重连
|
|
61
|
+
- 日志中记录 `[ws:connect]` / `[ws:disconnect]` 事件
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 三、私聊消息
|
|
66
|
+
|
|
67
|
+
### 3.1 接收
|
|
68
|
+
|
|
69
|
+
| 场景 | 预期行为 |
|
|
70
|
+
|------|----------|
|
|
71
|
+
| 用户发纯文本消息 | 正常接收,传给 LLM 处理 |
|
|
72
|
+
| 用户发图片消息 | 下载图片(≤30MB)并传给 LLM,超限时告知 LLM 失败原因 |
|
|
73
|
+
| 用户发图文混合消息 | 文本和图片同时传给 LLM |
|
|
74
|
+
| 消息无内容(空文本且无图片)| 直接丢弃,不触发 LLM |
|
|
75
|
+
|
|
76
|
+
### 3.2 回复
|
|
77
|
+
|
|
78
|
+
| 场景 | 预期行为 |
|
|
79
|
+
|------|----------|
|
|
80
|
+
| 回复短文本 | 单条消息发送 |
|
|
81
|
+
| 回复长文本(>1800字符)| 自动分片为多条消息,每片 ≤ 1800 字符(或 `textChunkLimit` 配置值)|
|
|
82
|
+
| 回复含图片 | 先发文本消息,再发图片;图片 >1MB 时自动压缩,压缩失败降级为链接 |
|
|
83
|
+
| `dmMessageFormat: "markdown"` | 以 markdown 格式发送,支持富文本渲染 |
|
|
84
|
+
| `dmMessageFormat: "text"` | 以纯文本格式发送(默认) |
|
|
85
|
+
|
|
86
|
+
### 3.3 消息撤回(私聊)
|
|
87
|
+
|
|
88
|
+
**前置条件:** 必须配置 `appAgentId`
|
|
89
|
+
|
|
90
|
+
| 场景 | 预期行为 |
|
|
91
|
+
|------|----------|
|
|
92
|
+
| 撤回最近 1 条 | LLM 调用 delete action,撤回最近发送的一条消息 |
|
|
93
|
+
| 撤回最近 N 条 | LLM 指定 count=N,批量撤回最近 N 条 |
|
|
94
|
+
| 按 messageId 撤回 | LLM 指定 messageId,撤回指定消息 |
|
|
95
|
+
| 未配置 appAgentId | 撤回失败,返回错误提示 |
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 四、群聊消息
|
|
100
|
+
|
|
101
|
+
### 4.1 接收
|
|
102
|
+
|
|
103
|
+
| 场景 | 预期行为 |
|
|
104
|
+
|------|----------|
|
|
105
|
+
| TEXT 文本消息 | 正常接收 |
|
|
106
|
+
| IMAGE 图片消息 | 并发下载,最多 20 张,每张 ≤30MB,通过 SSRF 白名单校验 |
|
|
107
|
+
| LINK 消息 | 提取 label 文本传给 LLM |
|
|
108
|
+
| AT 机器人消息 | 识别 @机器人(通过 `robotName` 匹配),设置 `wasMentioned=true` |
|
|
109
|
+
| AT 其他用户的消息 | 提取被 @用户 ID,供 LLM 在回复中使用 |
|
|
110
|
+
| 引用回复消息(replyData)| 提取被引用消息内容,注入到 LLM 上下文中(支持多级引用) |
|
|
111
|
+
| 纯 AT 无文本消息 | 视作 "@提及",传给 LLM 处理 |
|
|
112
|
+
|
|
113
|
+
### 4.2 replyMode — 群聊触发模式
|
|
114
|
+
|
|
115
|
+
**配置:** `channels.infoflow.replyMode`(或 per-group `groups.<id>.replyMode`)
|
|
116
|
+
|
|
117
|
+
| replyMode | 触发条件 | 预期行为 |
|
|
118
|
+
|-----------|----------|----------|
|
|
119
|
+
| `ignore` | 任意消息 | 直接丢弃,不保存历史,不触发 LLM |
|
|
120
|
+
| `record` | 任意消息 | 仅追加到群历史记录,不触发 LLM |
|
|
121
|
+
| `mention-only` | @机器人 | 触发 LLM |
|
|
122
|
+
| `mention-only` | 未 @机器人,在 followUp 窗口内 | 触发 LLM(判断是否跟进回复)|
|
|
123
|
+
| `mention-only` | 未 @机器人,不在 followUp 窗口内 | 追加历史,不回复 |
|
|
124
|
+
| `mention-and-watch` | @机器人 | 触发 LLM |
|
|
125
|
+
| `mention-and-watch` | watchMentions 用户被 @ | 触发 LLM(含条件 Prompt,让 LLM 判断是否代为回复)|
|
|
126
|
+
| `mention-and-watch` | 消息内容命中 watchRegex | 触发 LLM(含条件 Prompt)|
|
|
127
|
+
| `mention-and-watch` | 在 followUp 窗口内 | 触发 LLM(含跟进判断 Prompt)|
|
|
128
|
+
| `mention-and-watch` | 均未命中 | 追加历史,不回复 |
|
|
129
|
+
| `proactive` | @机器人 | 正常触发 |
|
|
130
|
+
| `proactive` | watchMentions 命中 | 触发 LLM(含条件 Prompt)|
|
|
131
|
+
| `proactive` | 其他任意消息 | 触发 LLM(含 Proactive Prompt,LLM 判断是否有必要回复)|
|
|
132
|
+
|
|
133
|
+
**注意:** `mention-only` 和 `mention-and-watch` 的触发必须配置 `robotName` 才能识别 @机器人。`watchMentions` / `watchRegex` 触发下,LLM 输出 `NO_REPLY` 则不发送消息。
|
|
134
|
+
|
|
135
|
+
### 4.3 followUp 跟进窗口
|
|
136
|
+
|
|
137
|
+
**配置:**
|
|
138
|
+
- `followUp: true`(默认开启)
|
|
139
|
+
- `followUpWindow: 300`(默认 300 秒,即 5 分钟)
|
|
140
|
+
|
|
141
|
+
| 场景 | 预期行为 |
|
|
142
|
+
|------|----------|
|
|
143
|
+
| Bot 回复后,用户在窗口内发消息 | 触发 LLM 判断是否是跟进问题 |
|
|
144
|
+
| Bot 回复后,用户超出窗口发消息 | 不触发(仅记录历史) |
|
|
145
|
+
| `followUp: false` | 窗口机制完全关闭 |
|
|
146
|
+
|
|
147
|
+
### 4.4 群聊回复
|
|
148
|
+
|
|
149
|
+
| 场景 | 预期行为 |
|
|
150
|
+
|------|----------|
|
|
151
|
+
| 回复短文本 | 单条消息发送 |
|
|
152
|
+
| 回复长文本(>1800字符)| 自动分片,每片 ≤ 1800 字符 |
|
|
153
|
+
| `groupMessageFormat: "text"`(默认)| 纯文本 + 引用回复(quote)|
|
|
154
|
+
| `groupMessageFormat: "markdown"` | Markdown 格式,**不附加引用回复** |
|
|
155
|
+
| Bot 被 @时回复 | 回复消息自动 @回触发用户 |
|
|
156
|
+
| 引用回复(text模式)| 第一条出站消息附带引用上下文 |
|
|
157
|
+
| 后续分片消息 | 不重复附加引用 |
|
|
158
|
+
|
|
159
|
+
### 4.5 消息撤回(群聊)
|
|
160
|
+
|
|
161
|
+
| 场景 | 预期行为 |
|
|
162
|
+
|------|----------|
|
|
163
|
+
| 撤回最近 1 条 | 根据本地记录查询 msgseqid,调用撤回 API |
|
|
164
|
+
| 撤回最近 N 条 | 批量撤回,过滤无 msgseqid 的记录 |
|
|
165
|
+
| 按 messageId 撤回 | 按 ID 查询 msgseqid,撤回指定消息 |
|
|
166
|
+
| 消息 ID 精度 | 消息 ID 为大整数时,应正确处理(不因 JSON.parse 丢失精度)|
|
|
167
|
+
|
|
168
|
+
### 4.6 群会话模式
|
|
169
|
+
|
|
170
|
+
**配置:** `groupSessionMode`
|
|
171
|
+
|
|
172
|
+
| 模式 | 预期行为 |
|
|
173
|
+
|------|----------|
|
|
174
|
+
| `"group"`(默认)| 群内所有用户共享一个 LLM 会话 |
|
|
175
|
+
| `"user"` | 每个用户在群内有独立的 LLM 会话(互不干扰)|
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## 五、安全策略
|
|
180
|
+
|
|
181
|
+
### 5.1 DM 策略(私聊)
|
|
182
|
+
|
|
183
|
+
**配置:** `channels.infoflow.dmPolicy`
|
|
184
|
+
|
|
185
|
+
| 策略 | 预期行为 |
|
|
186
|
+
|------|----------|
|
|
187
|
+
| `"open"`(默认)| 允许任何用户发私聊 |
|
|
188
|
+
| `"pairing"` | 框架处理配对逻辑(由 OpenClaw 框架控制)|
|
|
189
|
+
| `"allowlist"` | 仅 `allowFrom` 名单内用户可发,其他用户收到拒绝提示 |
|
|
190
|
+
|
|
191
|
+
**拒绝响应文案:** "🚫 抱歉,您暂无使用权限,请联系龙虾主开通~"
|
|
192
|
+
|
|
193
|
+
### 5.2 群聊策略
|
|
194
|
+
|
|
195
|
+
**配置:** `channels.infoflow.groupPolicy`
|
|
196
|
+
|
|
197
|
+
| 策略 | 预期行为 |
|
|
198
|
+
|------|----------|
|
|
199
|
+
| `"open"`(默认)| 允许任何群触发机器人 |
|
|
200
|
+
| `"disabled"` | 所有群消息静默丢弃 |
|
|
201
|
+
| `"allowlist"` | 仅 `groupAllowFrom` 内的群 ID 可触发,其他群(被 @时)收到拒绝提示 |
|
|
202
|
+
|
|
203
|
+
**拒绝响应文案:** "🚫 抱歉,该群暂无使用权限,请联系龙虾主开通~"(仅在被 @时才回复,避免刷屏)
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 六、@mention 功能
|
|
208
|
+
|
|
209
|
+
### 6.1 出站 @mention(Bot 主动 @)
|
|
210
|
+
|
|
211
|
+
| 场景 | 预期行为 |
|
|
212
|
+
|------|----------|
|
|
213
|
+
| LLM 回复时 @全体 | 在群消息中附加 `AT:atall=true` 节点,触发全体提醒 |
|
|
214
|
+
| LLM 指定 @某用户 | `mentionUserIds` 传入 uuapName,回复中附加 AT 节点 |
|
|
215
|
+
| Bot 被 @时的自动回 @ | 第一条回复中自动 @回触发用户 |
|
|
216
|
+
| @mention 节点位置 | 仅附加在第一个分片,后续分片不重复 @ |
|
|
217
|
+
| 私聊中设置 atAll | 忽略(无效,仅群聊有效)|
|
|
218
|
+
|
|
219
|
+
### 6.2 入站 @mention(识别群消息中的 @)
|
|
220
|
+
|
|
221
|
+
| 场景 | 预期行为 |
|
|
222
|
+
|------|----------|
|
|
223
|
+
| 消息中 @机器人 | `wasMentioned=true`,触发 replyMode 判断 |
|
|
224
|
+
| 消息中 @其他用户 | 提取 userId 列表,注入 LLM 上下文(供 LLM 在回复中使用)|
|
|
225
|
+
| 消息中 @其他机器人 | 提取 agentId 列表,注入 LLM 上下文 |
|
|
226
|
+
| 未配置 robotName | 无法识别 @机器人,`wasMentioned` 始终为 false |
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 七、图片处理
|
|
231
|
+
|
|
232
|
+
### 7.1 入站图片(接收)
|
|
233
|
+
|
|
234
|
+
| 场景 | 预期行为 |
|
|
235
|
+
|------|----------|
|
|
236
|
+
| 单张图片(≤30MB)| 下载成功,传给 LLM |
|
|
237
|
+
| 单张图片(>30MB)| 下载失败,向 LLM 说明失败原因 |
|
|
238
|
+
| 多张图片(≤20张)| 并发下载,全部成功则全部传给 LLM |
|
|
239
|
+
| 多张图片(>20张)| 仅下载前 20 张 |
|
|
240
|
+
| 部分图片下载失败 | 成功的图片正常传给 LLM,失败的附加失败说明注释 |
|
|
241
|
+
| 全部图片下载失败 | 向 LLM 说明全部下载失败,不附加图片 |
|
|
242
|
+
|
|
243
|
+
### 7.2 出站图片(发送)
|
|
244
|
+
|
|
245
|
+
| 场景 | 预期行为 |
|
|
246
|
+
|------|----------|
|
|
247
|
+
| 图片 ≤1MB | 直接以 base64 发送 |
|
|
248
|
+
| 图片 >1MB(非GIF)| 自动压缩(多组合尝试),直到 ≤1MB |
|
|
249
|
+
| 图片 >1MB(GIF)| 直接降级为链接(GIF 压缩会丢失动画)|
|
|
250
|
+
| 所有压缩方案均超 1MB | 降级为链接发送 |
|
|
251
|
+
| 图片 URL 不可访问 | 降级为链接发送 |
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## 八、处理中提示
|
|
256
|
+
|
|
257
|
+
**配置:**
|
|
258
|
+
- `processingHint: true`(默认开启)
|
|
259
|
+
- `processingHintDelay: 5`(默认 5 秒,可设 0 表示立即发送)
|
|
260
|
+
|
|
261
|
+
| 场景 | 预期行为 |
|
|
262
|
+
|------|----------|
|
|
263
|
+
| LLM 在 5 秒内完成响应 | 不发送"处理中"提示 |
|
|
264
|
+
| LLM 超过 5 秒未开始发消息 | 发送"⏳ 处理中..."(引用用户消息,仅群聊引用) |
|
|
265
|
+
| 提示已发出,LLM 完成响应 | 追加发送"任务完成 ✨ (Xs)"(X 为实际耗时秒数) |
|
|
266
|
+
| 提示已发出,Bot 第一条消息发送时 | 取消后续提示定时器,不重复发提示 |
|
|
267
|
+
| `processingHint: false` | 完全关闭此功能 |
|
|
268
|
+
| `processingHintDelay: 0` | 收到消息立即发送提示 |
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## 九、多账号支持
|
|
273
|
+
|
|
274
|
+
| 场景 | 预期行为 |
|
|
275
|
+
|------|----------|
|
|
276
|
+
| 单账号配置(不设 accounts)| 使用 default 账号,正常工作 |
|
|
277
|
+
| 配置多个命名账号 | 各账号独立运行,不互相干扰 |
|
|
278
|
+
| 某账号 `enabled: false` | 该账号停止接收/发送,其他账号不受影响 |
|
|
279
|
+
| 子账号覆盖父级配置 | 子账号的字段优先于顶层字段(如 textChunkLimit)|
|
|
280
|
+
| 跨账号发送(infoflow_send 指定 accountId)| 通过指定账号发出消息 |
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## 十、内置命令
|
|
285
|
+
|
|
286
|
+
### 10.1 /infoflow-doctor 自检命令
|
|
287
|
+
|
|
288
|
+
**用法:** 在如流私聊或群聊中发送 `/infoflow-doctor`
|
|
289
|
+
|
|
290
|
+
| 检查项 | 预期行为 |
|
|
291
|
+
|--------|----------|
|
|
292
|
+
| 配置完整性检查 | 显示 appKey、appSecret、apiHost、connectionMode 等关键字段状态(✅/❌)|
|
|
293
|
+
| Access Token 获取 | 实际调用 Infoflow API,显示是否成功 |
|
|
294
|
+
| 发私聊自检 | 向触发命令的用户发送测试消息 |
|
|
295
|
+
| 发群聊自检 | 仅在群聊触发时执行,向当前群发测试消息 |
|
|
296
|
+
| 发图片自检 | 发送一张 48×48 绿色测试图片 |
|
|
297
|
+
| 自检报告末尾 | 附带 `/infoflow-logs` 命令使用说明 |
|
|
298
|
+
|
|
299
|
+
### 10.2 /infoflow-logs 日志查看命令
|
|
300
|
+
|
|
301
|
+
**日志来源:** `/tmp/openclaw/openclaw-YYYY-MM-DD.log`
|
|
302
|
+
|
|
303
|
+
| 用法 | 预期行为 |
|
|
304
|
+
|------|----------|
|
|
305
|
+
| `/infoflow-logs` | 显示最近 50 条 Infoflow 相关日志 |
|
|
306
|
+
| `/infoflow-logs 100` | 显示最近 100 条(最大 200 条)|
|
|
307
|
+
| `/infoflow-logs 50-100` | 跳过最近 50 条,往前再看 50 条 |
|
|
308
|
+
| `/infoflow-logs 200` | 最多展示 200 条(超出上限时取 200)|
|
|
309
|
+
| 日志文件不存在 | 返回提示"未找到日志文件"及预期路径 |
|
|
310
|
+
| 日志内容超 20,000 字符 | 丢弃最老的记录,附加超限提示 |
|
|
311
|
+
| 过滤规则 | 只显示含 `[inbound:`、`[outbound`、`[dispatch`、`[ws:`、`[infoflow]` 的行,心跳噪音(heartbeat/connected/disconnected)被过滤 |
|
|
312
|
+
| 长输出 | 自动分多条消息发送(框架分片)|
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## 十一、工具(LLM 可调用)
|
|
317
|
+
|
|
318
|
+
### 11.1 infoflow_send — 主动发消息
|
|
319
|
+
|
|
320
|
+
| 参数 | 类型 | 说明 |
|
|
321
|
+
|------|------|------|
|
|
322
|
+
| `to` | string,必填 | 目标:`username` 或 `group:<groupId>` |
|
|
323
|
+
| `message` | string,必填 | 消息内容(支持 Markdown)|
|
|
324
|
+
| `atAll` | boolean,可选 | 是否 @全体成员(仅群目标有效)|
|
|
325
|
+
| `mentionUserIds` | string,可选 | 逗号分隔的 uuapName,仅群目标有效,`atAll=true` 时忽略 |
|
|
326
|
+
| `accountId` | string,可选 | 多账号时指定账号 ID |
|
|
327
|
+
|
|
328
|
+
| 场景 | 预期行为 |
|
|
329
|
+
|------|----------|
|
|
330
|
+
| 发私聊消息 | `to=username`,消息发给该用户 |
|
|
331
|
+
| 发群聊消息 | `to=group:xxxxxx`,消息发到该群 |
|
|
332
|
+
| 群聊 @全体 | `atAll=true`,消息附加 @全体通知 |
|
|
333
|
+
| 群聊 @指定用户 | `mentionUserIds="user1,user2"`,消息 @指定用户 |
|
|
334
|
+
|
|
335
|
+
### 11.2 infoflow_recall — 撤回消息
|
|
336
|
+
|
|
337
|
+
| 参数 | 类型 | 说明 |
|
|
338
|
+
|------|------|------|
|
|
339
|
+
| `to` | string,必填 | 目标(同 send 格式)|
|
|
340
|
+
| `count` | number,可选 | 撤回最近 N 条(默认 1,`messageId` 未设置时生效)|
|
|
341
|
+
| `messageId` | string,可选 | 按 ID 撤回指定消息(优先级高于 count)|
|
|
342
|
+
| `accountId` | string,可选 | 多账号时指定账号 ID |
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## 十二、Per-Group 配置覆盖
|
|
347
|
+
|
|
348
|
+
可通过 `groups.<groupId>` 对单个群进行独立配置,覆盖账号级别默认值。
|
|
349
|
+
|
|
350
|
+
**支持覆盖的字段:**
|
|
351
|
+
|
|
352
|
+
| 字段 | 说明 |
|
|
353
|
+
|------|------|
|
|
354
|
+
| `replyMode` | 该群的回复模式 |
|
|
355
|
+
| `groupSessionMode` | 该群的会话粒度 |
|
|
356
|
+
| `systemPrompt` | 该群专属的系统 Prompt(追加到全局 systemPrompt 之后)|
|
|
357
|
+
| `followUp` | 该群是否启用跟进窗口 |
|
|
358
|
+
| `followUpWindow` | 该群的跟进窗口时长(秒)|
|
|
359
|
+
| `watchMentions` | 该群监视的 @提及名单 |
|
|
360
|
+
| `watchRegex` | 该群的消息内容监视正则 |
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## 十三、配置边界条件
|
|
365
|
+
|
|
366
|
+
以下边界情况需要重点关注:
|
|
367
|
+
|
|
368
|
+
| 场景 | 预期行为 |
|
|
369
|
+
|------|----------|
|
|
370
|
+
| `textChunkLimit` 设为很小值(如 100)| 每条消息最多 100 字符,长消息被切成很多条 |
|
|
371
|
+
| `textChunkLimit` 未配置 | 使用默认值 1800 |
|
|
372
|
+
| `robotName` 未配置 | 无法识别群 @机器人,`wasMentioned` 始终为 false;`mention-only` 模式下相当于永不触发 |
|
|
373
|
+
| `appAgentId` 未配置 | 私聊撤回失败,群聊撤回不受影响 |
|
|
374
|
+
| `apiHost` 填写了 HTTPS 地址 | 插件自动将 HTTP 协议升级为 HTTPS(`ensureHttps` 处理)|
|
|
375
|
+
| 账号 `enabled: false` | 该账号不处理任何消息,不对外发送 |
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## 附录:关键配置参数速查
|
|
380
|
+
|
|
381
|
+
```yaml
|
|
382
|
+
channels:
|
|
383
|
+
infoflow:
|
|
384
|
+
enabled: true
|
|
385
|
+
appKey: "xxx"
|
|
386
|
+
appSecret: "xxx"
|
|
387
|
+
checkToken: "xxx" # webhook 模式必填
|
|
388
|
+
encodingAESKey: "xxx" # webhook 模式必填
|
|
389
|
+
apiHost: "http://apiin.im.baidu.com"
|
|
390
|
+
connectionMode: "webhook" # "webhook" | "websocket"
|
|
391
|
+
wsGateway: "xxx" # websocket 模式可选
|
|
392
|
+
appAgentId: 123 # 私聊撤回必填
|
|
393
|
+
robotName: "机器人昵称" # @mention 识别必填
|
|
394
|
+
dmPolicy: "open" # "open" | "pairing" | "allowlist"
|
|
395
|
+
allowFrom: [] # dmPolicy=allowlist 时的白名单
|
|
396
|
+
groupPolicy: "open" # "open" | "allowlist" | "disabled"
|
|
397
|
+
groupAllowFrom: [] # groupPolicy=allowlist 时的群 ID 白名单
|
|
398
|
+
replyMode: "mention-only" # "ignore"|"record"|"mention-only"|"mention-and-watch"|"proactive"
|
|
399
|
+
groupSessionMode: "group" # "group" | "user"
|
|
400
|
+
followUp: true
|
|
401
|
+
followUpWindow: 300
|
|
402
|
+
watchMentions: []
|
|
403
|
+
watchRegex: ""
|
|
404
|
+
textChunkLimit: 1800
|
|
405
|
+
processingHint: true
|
|
406
|
+
processingHintDelay: 5
|
|
407
|
+
dmMessageFormat: "text" # "text" | "markdown"
|
|
408
|
+
groupMessageFormat: "text" # "text" | "markdown"
|
|
409
|
+
groups:
|
|
410
|
+
"12345678": # 按 groupId 的 per-group 配置
|
|
411
|
+
replyMode: "mention-only"
|
|
412
|
+
systemPrompt: "..."
|
|
413
|
+
```
|
package/index.ts
CHANGED
|
@@ -5,9 +5,12 @@ import { setInfoflowRuntime } from "./src/runtime.js";
|
|
|
5
5
|
import { registerInfoflowTools } from "./src/tools/index.js";
|
|
6
6
|
import { registerInfoflowHooks } from "./src/tools/hooks/index.js";
|
|
7
7
|
import { registerStoreListeners } from "./src/utils/store/message-store.js";
|
|
8
|
+
import { runDoctorCommand } from "./src/commands/doctor.js";
|
|
9
|
+
import { runLogsCommand } from "./src/commands/logs.js";
|
|
10
|
+
import { runChangelogCommand } from "./src/commands/changelog.js";
|
|
8
11
|
|
|
9
12
|
const plugin = {
|
|
10
|
-
id: "infoflow",
|
|
13
|
+
id: "infoflow-openclaw-plugin",
|
|
11
14
|
name: "Infoflow",
|
|
12
15
|
description: "OpenClaw Infoflow channel plugin",
|
|
13
16
|
configSchema: emptyPluginConfigSchema(),
|
|
@@ -23,6 +26,27 @@ const plugin = {
|
|
|
23
26
|
registerInfoflowTools(api);
|
|
24
27
|
registerInfoflowHooks(api);
|
|
25
28
|
registerStoreListeners();
|
|
29
|
+
|
|
30
|
+
api.registerCommand({
|
|
31
|
+
name: "infoflow-doctor",
|
|
32
|
+
description: "检查 Infoflow 插件配置和连通性,帮助排查收不到消息的问题",
|
|
33
|
+
acceptsArgs: false,
|
|
34
|
+
handler: (ctx) => runDoctorCommand({ config: ctx.config, senderId: ctx.senderId, to: ctx.to }),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
api.registerCommand({
|
|
38
|
+
name: "infoflow-logs",
|
|
39
|
+
description: "查看 Infoflow 最近收发消息日志。支持:/infoflow-logs 100(最近100条)、/infoflow-logs 50-100(翻页)",
|
|
40
|
+
acceptsArgs: true,
|
|
41
|
+
handler: (ctx) => runLogsCommand({ config: ctx.config, senderId: ctx.senderId, args: ctx.args }),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
api.registerCommand({
|
|
45
|
+
name: "infoflow-changelog",
|
|
46
|
+
description: "查看 Infoflow 插件更新日志。默认显示最近 5 次更新,/infoflow-changelog all 查看全部",
|
|
47
|
+
acceptsArgs: true,
|
|
48
|
+
handler: (ctx) => runChangelogCommand({ args: ctx.args }),
|
|
49
|
+
});
|
|
26
50
|
},
|
|
27
51
|
};
|
|
28
52
|
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"id": "infoflow",
|
|
2
|
+
"id": "infoflow-openclaw-plugin",
|
|
3
3
|
"channels": ["infoflow"],
|
|
4
4
|
"skills": ["./skills"],
|
|
5
5
|
"configSchema": {
|
|
@@ -38,6 +38,12 @@
|
|
|
38
38
|
"enum": ["ignore", "record", "mention-only", "mention-and-watch", "proactive"],
|
|
39
39
|
"default": "mention-and-watch"
|
|
40
40
|
},
|
|
41
|
+
"groupSessionMode": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"enum": ["group", "user"],
|
|
44
|
+
"default": "group",
|
|
45
|
+
"description": "群聊会话拆分模式:group=按群拆分,user=按群+人拆分"
|
|
46
|
+
},
|
|
41
47
|
"followUp": { "type": "boolean", "default": true },
|
|
42
48
|
"followUpWindow": { "type": "number", "default": 300 },
|
|
43
49
|
"watchMentions": { "type": "array", "items": { "type": "string" } },
|
|
@@ -51,6 +57,11 @@
|
|
|
51
57
|
"type": "string",
|
|
52
58
|
"enum": ["ignore", "record", "mention-only", "mention-and-watch", "proactive"]
|
|
53
59
|
},
|
|
60
|
+
"groupSessionMode": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"enum": ["group", "user"],
|
|
63
|
+
"description": "群聊会话拆分模式:group=按群拆分,user=按群+人拆分"
|
|
64
|
+
},
|
|
54
65
|
"watchMentions": { "type": "array", "items": { "type": "string" } },
|
|
55
66
|
"watchRegex": { "type": "string" },
|
|
56
67
|
"followUp": { "type": "boolean" },
|
|
@@ -91,6 +102,11 @@
|
|
|
91
102
|
"type": "string",
|
|
92
103
|
"enum": ["ignore", "record", "mention-only", "mention-and-watch", "proactive"]
|
|
93
104
|
},
|
|
105
|
+
"groupSessionMode": {
|
|
106
|
+
"type": "string",
|
|
107
|
+
"enum": ["group", "user"],
|
|
108
|
+
"description": "群聊会话拆分模式:group=按群拆分,user=按群+人拆分"
|
|
109
|
+
},
|
|
94
110
|
"followUp": { "type": "boolean" },
|
|
95
111
|
"followUpWindow": { "type": "number" },
|
|
96
112
|
"watchMentions": { "type": "array", "items": { "type": "string" } },
|
|
@@ -104,6 +120,11 @@
|
|
|
104
120
|
"type": "string",
|
|
105
121
|
"enum": ["ignore", "record", "mention-only", "mention-and-watch", "proactive"]
|
|
106
122
|
},
|
|
123
|
+
"groupSessionMode": {
|
|
124
|
+
"type": "string",
|
|
125
|
+
"enum": ["group", "user"],
|
|
126
|
+
"description": "群聊会话拆分模式:group=按群拆分,user=按群+人拆分"
|
|
127
|
+
},
|
|
107
128
|
"watchMentions": { "type": "array", "items": { "type": "string" } },
|
|
108
129
|
"watchRegex": { "type": "string" },
|
|
109
130
|
"followUp": { "type": "boolean" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@core-workspace/infoflow-openclaw-plugin",
|
|
3
|
-
"version": "2026.3.
|
|
3
|
+
"version": "2026.3.32",
|
|
4
4
|
"description": "OpenClaw Infoflow (如流) channel plugin for Baidu enterprise messaging",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"openclaw",
|
|
10
10
|
"openclaw-plugin",
|
|
11
11
|
"infoflow",
|
|
12
|
+
"infoflow-openclaw-plugin",
|
|
12
13
|
"baidu",
|
|
13
14
|
"chatbot",
|
|
14
15
|
"ai-agent",
|
|
@@ -19,17 +20,23 @@
|
|
|
19
20
|
"url": "https://github.com/BDlxj/infoflow"
|
|
20
21
|
},
|
|
21
22
|
"peerDependencies": {
|
|
22
|
-
"openclaw": ">=2026.3.2"
|
|
23
|
+
"openclaw": ">=2026.3.2",
|
|
24
|
+
"@core-workspace/infoflow-sdk-nodejs": "^0.1.5"
|
|
25
|
+
},
|
|
26
|
+
"peerDependenciesMeta": {
|
|
27
|
+
"@core-workspace/infoflow-sdk-nodejs": {
|
|
28
|
+
"optional": true
|
|
29
|
+
}
|
|
23
30
|
},
|
|
24
31
|
"dependencies": {
|
|
25
|
-
"@
|
|
32
|
+
"@sinclair/typebox": "0.34.48"
|
|
26
33
|
},
|
|
27
34
|
"openclaw": {
|
|
28
35
|
"extensions": [
|
|
29
36
|
"./index.ts"
|
|
30
37
|
],
|
|
31
38
|
"channel": {
|
|
32
|
-
"id": "infoflow",
|
|
39
|
+
"id": "infoflow-openclaw-plugin",
|
|
33
40
|
"label": "Infoflow",
|
|
34
41
|
"selectionLabel": "Infoflow (如流)",
|
|
35
42
|
"docsPath": "/channels/infoflow",
|
|
@@ -40,5 +47,9 @@
|
|
|
40
47
|
"npmSpec": "@core-workspace/infoflow-openclaw-plugin",
|
|
41
48
|
"defaultChoice": "npm"
|
|
42
49
|
}
|
|
50
|
+
},
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public",
|
|
53
|
+
"registry": "https://registry.npmjs.org/"
|
|
43
54
|
}
|
|
44
55
|
}
|