@jerryliang122/openclaw-qqbot 1.0.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.
Files changed (120) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +967 -0
  3. package/README.zh.md +790 -0
  4. package/dist/index.cjs +18072 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.d.cts +1222 -0
  7. package/index.ts +92 -0
  8. package/openclaw.plugin.json +38 -0
  9. package/package.json +69 -0
  10. package/preload.cjs +19 -0
  11. package/scripts/link-sdk-core.cjs +268 -0
  12. package/scripts/proactive-api-server.ts +369 -0
  13. package/scripts/send-proactive.ts +293 -0
  14. package/scripts/test-sendmedia.ts +116 -0
  15. package/skills/qqbot-channel/SKILL.md +285 -0
  16. package/skills/qqbot-channel/references/api_references.md +521 -0
  17. package/skills/qqbot-remind/SKILL.md +159 -0
  18. package/skills/qqbot-upgrade/SKILL.md +56 -0
  19. package/src/adapter/contract.ts +63 -0
  20. package/src/adapter/lint.ts +144 -0
  21. package/src/adapter/media.ts +40 -0
  22. package/src/adapter/pairing.ts +95 -0
  23. package/src/adapter/resolve.ts +255 -0
  24. package/src/adapter/setup.ts +13 -0
  25. package/src/adapter/webhook.ts +248 -0
  26. package/src/adapter/workspace.ts +21 -0
  27. package/src/agent-prompt-adapter.ts +26 -0
  28. package/src/bot-instance.ts +60 -0
  29. package/src/channel.ts +230 -0
  30. package/src/commands/bot-approve.ts +143 -0
  31. package/src/commands/bot-clear-storage.ts +114 -0
  32. package/src/commands/bot-group-always.ts +62 -0
  33. package/src/commands/bot-group-info.ts +48 -0
  34. package/src/commands/bot-help.ts +40 -0
  35. package/src/commands/bot-logs.ts +248 -0
  36. package/src/commands/bot-me.ts +18 -0
  37. package/src/commands/bot-pairing.ts +50 -0
  38. package/src/commands/bot-ping.ts +33 -0
  39. package/src/commands/bot-streaming.ts +55 -0
  40. package/src/commands/bot-upgrade.ts +56 -0
  41. package/src/commands/bot-version.ts +41 -0
  42. package/src/commands/config-util.ts +96 -0
  43. package/src/commands/index.ts +51 -0
  44. package/src/config.ts +403 -0
  45. package/src/constants.ts +6 -0
  46. package/src/dispatch/body-assembler.ts +308 -0
  47. package/src/dispatch/ctx-builder.ts +127 -0
  48. package/src/dispatch/dispatch.ts +667 -0
  49. package/src/dispatch/envelope-builder.ts +112 -0
  50. package/src/dispatch/index.ts +2 -0
  51. package/src/features/approval-capability.ts +302 -0
  52. package/src/features/approval-helpers.ts +271 -0
  53. package/src/features/approval-utils.ts +21 -0
  54. package/src/features/command-panel.ts +301 -0
  55. package/src/features/credential-backup.ts +74 -0
  56. package/src/features/group-mode-store.ts +79 -0
  57. package/src/features/history-store.ts +75 -0
  58. package/src/features/msgid-cache.ts +55 -0
  59. package/src/features/outbound-echo-store.ts +46 -0
  60. package/src/features/proactive-budget.ts +57 -0
  61. package/src/features/proactive.ts +549 -0
  62. package/src/features/question-helpers.ts +771 -0
  63. package/src/features/quota-manager.ts +173 -0
  64. package/src/features/ref-index-store.ts +289 -0
  65. package/src/features/secret-input-store.ts +118 -0
  66. package/src/features/secret-store-cli.ts +324 -0
  67. package/src/features/typing-refresh.ts +51 -0
  68. package/src/features/update-checker.ts +166 -0
  69. package/src/gateway/event-handlers.ts +456 -0
  70. package/src/gateway/index.ts +3 -0
  71. package/src/gateway/lifecycle.ts +236 -0
  72. package/src/gateway/middleware-setup.ts +173 -0
  73. package/src/gateway/qqbot-gateway.ts +458 -0
  74. package/src/gateway-adapter.ts +44 -0
  75. package/src/heartbeat-adapter.ts +57 -0
  76. package/src/message-adapter.ts +40 -0
  77. package/src/messaging-adapter.ts +78 -0
  78. package/src/middleware/access-control.ts +125 -0
  79. package/src/middleware/attachment.ts +373 -0
  80. package/src/middleware/inbound-guard.ts +102 -0
  81. package/src/middleware/policy-injector.ts +71 -0
  82. package/src/middleware/secret-capture.ts +161 -0
  83. package/src/middleware/typing.ts +110 -0
  84. package/src/openclaw-plugin-sdk.d.ts +543 -0
  85. package/src/outbound/chunker.ts +80 -0
  86. package/src/outbound/debounce.ts +102 -0
  87. package/src/outbound/deliver-pipeline.ts +235 -0
  88. package/src/outbound/index.ts +3 -0
  89. package/src/outbound/local-file-router.ts +145 -0
  90. package/src/outbound/media-send.ts +408 -0
  91. package/src/outbound/outbound-service.ts +298 -0
  92. package/src/outbound/reply-limiter.ts +139 -0
  93. package/src/outbound/sanitize.ts +32 -0
  94. package/src/outbound/streaming-controller.ts +332 -0
  95. package/src/outbound/target.ts +109 -0
  96. package/src/outbound-adapter.ts +323 -0
  97. package/src/plugin-base.ts +42 -0
  98. package/src/request-context.ts +50 -0
  99. package/src/runtime.ts +42 -0
  100. package/src/setup/account-key.ts +41 -0
  101. package/src/setup/finalize.ts +110 -0
  102. package/src/setup/login.ts +197 -0
  103. package/src/setup/surface.ts +40 -0
  104. package/src/status-adapter.ts +56 -0
  105. package/src/tools/platform.ts +149 -0
  106. package/src/tools/remind.ts +308 -0
  107. package/src/tools/secret-input.ts +185 -0
  108. package/src/types-augment.d.ts +54 -0
  109. package/src/types-plugin.ts +82 -0
  110. package/src/types.ts +620 -0
  111. package/src/typing-lifecycle.ts +182 -0
  112. package/src/utils/mention.ts +52 -0
  113. package/src/utils/pkg-version.ts +23 -0
  114. package/src/utils/platform.ts +459 -0
  115. package/src/utils/plugin-logger.ts +104 -0
  116. package/src/utils/ssrf-guard.ts +132 -0
  117. package/src/utils/stt.ts +150 -0
  118. package/src/utils/voice-text.ts +61 -0
  119. package/tsconfig.json +17 -0
  120. package/tsup.config.ts +64 -0
package/README.zh.md ADDED
@@ -0,0 +1,790 @@
1
+ <div align="center">
2
+
3
+ **简体中文 | [English](README.md)**
4
+
5
+ <img width="120" src="https://img.shields.io/badge/🤖-QQ_Bot-blue?style=for-the-badge" alt="QQ Bot" />
6
+
7
+ # QQ Bot — OpenClaw 渠道插件
8
+
9
+
10
+ **让你的 AI 助手接入 QQ — 私聊、群聊、富媒体,一个插件全搞定。**
11
+
12
+ > 本仓库为**独立维护的 fork**,自 v1.0.0 起独立发版(与上游 2.x 版本线完全脱钩)。
13
+ > 运行要求:OpenClaw `>= 2026.9.2`;npm 包名 [`@jerryliang122/openclaw-qqbot`](https://www.npmjs.com/package/@jerryliang122/openclaw-qqbot)。
14
+ > 与旧版本的差异及升级指南见 [CHANGELOG](CHANGELOG.md)。上游仓库:[tencent-connect/openclaw-qqbot](https://github.com/tencent-connect/openclaw-qqbot)。
15
+
16
+ ### 🚀 当前版本: `v1.0.0`
17
+
18
+ [![License](https://img.shields.io/badge/license-MIT-green)](./LICENSE)
19
+ [![QQ Bot](https://img.shields.io/badge/QQ_Bot-API_v2-red)](https://bot.q.qq.com/wiki/)
20
+ [![Platform](https://img.shields.io/badge/OpenClaw-%3E%3D2026.9.2-orange)](https://github.com/jerryliang122/qqbot-openclaw)
21
+ [![Node.js](https://img.shields.io/badge/Node.js->=18-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
22
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
23
+
24
+ <br/>
25
+
26
+ 扫描二维码加入群聊,一起交流
27
+
28
+ <img width="400" alt="QQ 群二维码" src="./docs/images/developer-group.png" />
29
+
30
+ </div>
31
+
32
+ ---
33
+
34
+ ## ✨ 功能特性
35
+
36
+ | 功能 | 说明 |
37
+ |------|------|
38
+ | 🔄 **群消息排队** | 群消息即时进入框架,排队/合并交给 OpenClaw 框架队列(collect 模式)——正在处理的任务绝不被打断,突发消息合并成一批 |
39
+ | 👁️ **房间事件(可选)** | 全量模式群里,bot 像普通群成员一样读到每条消息;未 @ 的消息作为被动房间事件(只读,AI 想发言走主动 `message` 工具) |
40
+ | 🔔 **三种唤醒方式** | @提及、称呼唤醒(`mentionPatterns`,如「沈处」)、引用 bot 消息,均触发正常回复 |
41
+ | 📤 **被动优先出站** | 所有发送优先走被动回复(msg_id)以节省每天约 1000 条主动消息预算;配额感知降级,绝不硬失败 |
42
+ | 🔒 **多场景支持** | C2C 私聊、群聊(@提及 / 自主发言 / 房间事件模式) |
43
+ | 👥 **群聊精细管控** | 按群配置 @触发规则、工具权限、自定义提示词、历史模式、排队策略、房间事件策略 |
44
+ | 🌐 **双传输模式** | WebSocket(默认)或 Webhook(HTTP 回调)— 配置切换 |
45
+ | 🖼️ **富媒体消息** | 支持图片、语音、视频、文件的收发 |
46
+ | 🎙️ **语音能力 (STT/TTS)** | 语音转文字自动转录 & 文字转语音回复 |
47
+ | 🔄 **版本检查** | 私聊发送 `/bot-upgrade` 检查 npm 新版本并附升级指引 |
48
+ | ⏰ **定时推送** | 支持定时任务触发后主动推送消息 |
49
+ | 🔗 **URL 无限制** | 私聊可直接发送 URL |
50
+ | ⌨️ **输入状态** | 实时显示"Bot 正在输入中…"状态 |
51
+ | 📝 **Markdown** | 完整支持 Markdown 格式消息 |
52
+ | 🛠️ **原生命令** | 支持 OpenClaw 原生命令 |
53
+ | 💬 **引用上下文** | 解析用户回复的原始消息内容,注入 AI 上下文,让模型准确理解"在回复哪条消息" |
54
+ | 📦 **大文件支持** | 大文件自动分片并行上传,最大支持 100 MB |
55
+ | 🔐 **命令执行审批** | AI 执行命令前通过按钮消息请求审批,点击即可允许或拒绝 |
56
+
57
+ ---
58
+
59
+ ## 📸 功能展示
60
+
61
+ > **说明:** 本插件仅作为**消息通道**,负责在 QQ 和 OpenClaw 之间传递消息。图片理解、语音转录、AI 画图等能力取决于你配置的 **AI 模型**以及在 OpenClaw 中安装的 **skill**,而非插件本身提供。
62
+
63
+ ### 💬 引用消息上下文
64
+
65
+ 用户在 QQ 中引用某条消息发送时,插件会自动解析被引用的消息内容并注入 AI 上下文,让模型清楚地知道"用户在回复哪条消息",从而给出更准确的回复。支持文本及媒体消息(图片/语音/视频/文件),换设备后同样可用。
66
+
67
+ <img width="360" src="docs/images/ref-msg.png" alt="引用消息上下文演示" />
68
+
69
+ ### 🎙️ 语音消息(STT)
70
+
71
+ 配置 STT 后,插件会自动将语音转录为文字再交给 AI 处理。整个过程对用户完全透明——发语音就像发文字一样自然,AI 听得懂你在说什么。
72
+
73
+ > **你**:*(发送一段语音)*"明天深圳天气怎么样"
74
+ >
75
+ > **QQBot**:明天(3月7日 周六)深圳的天气预报 🌤️ ...
76
+
77
+ <img width="360" src="docs/images/voice-stt.jpg" alt="听语音演示" />
78
+
79
+ ### 📄 文件理解
80
+
81
+ 用户发文件给 AI,AI 同样能接住。不管是一本小说还是一份报告,AI 会自动识别文件内容并给出智能回复。
82
+
83
+ > **你**:*(发送《战争与和平》TXT 文件)*
84
+ >
85
+ > **QQBot**:收到!你上传了列夫·托尔斯泰的《战争与和平》中文版文本。从内容来看,这是第一章的开头……你想让我做什么?
86
+
87
+ <img width="360" src="docs/images/file-understand.jpg" alt="AI理解用户发送的文件" />
88
+
89
+ ### 🖼️ 图片理解
90
+
91
+ 如果主模型支持视觉(如腾讯混元 `hunyuan-vision`),用户发图片 AI 也能看懂。这是多模态模型的通用能力,非插件专属功能。
92
+
93
+ > **你**:*(发送一张图片)*
94
+ >
95
+ > **QQBot**:哈哈,好可爱!这是QQ企鹅穿上小龙虾套装吗?🦞🐧 ...
96
+
97
+ <img width="360" src="docs/images/image-understand.jpg" alt="图片理解演示" />
98
+
99
+ ### 🎨 图片发送
100
+
101
+ > **你**:画一只猫咪
102
+ >
103
+ > **QQBot**:画好啦!一只可爱的简笔小猫咪🐱🎨
104
+
105
+ AI 可直接发送图片,支持本地文件路径和网络 URL。格式:jpg/png/gif/webp/bmp。
106
+
107
+ <img width="360" src="docs/images/image-send.jpg" alt="发图片演示" />
108
+
109
+ ### 🔊 语音发送
110
+
111
+ > **你**:给我讲一个笑话
112
+ >
113
+ > **QQBot**:*(发送一条语音消息)*
114
+
115
+ AI 可直接发送语音消息。格式:mp3/wav/silk/ogg,无需安装 ffmpeg。
116
+
117
+ <img width="360" src="docs/images/voice-send.jpg" alt="发语音演示" />
118
+
119
+ ### ⏰ 定时提醒(主动消息)
120
+
121
+ > **你**:5分钟后提醒我吃饭
122
+ >
123
+ > **QQBot**:先确认已创建提醒,到点后再主动推送语音 + 文本提醒
124
+
125
+ 该能力依赖 OpenClaw cron 调度与主动消息能力。若未收到提醒,常见原因是 QQ 侧拦截了机器人主动消息。
126
+
127
+ <img width="360" src="docs/images/reminder.jpg" alt="定时提醒演示" />
128
+
129
+ ### 📎 文件发送
130
+
131
+ > **你**:战争与和平的第一章截取一下发文件给我
132
+ >
133
+ > **QQBot**:*(发送 .txt 文件)*
134
+
135
+ AI 可直接发送文件,任意格式均可。
136
+
137
+ <img width="360" src="docs/images/file-send.jpg" alt="发文件演示" />
138
+
139
+ v1.6.6 起支持大文件传输:图片最大 20MB,视频最大 30MB,附件最大 100MB,每日累计传输上限 2GB。
140
+
141
+ <img width="360" src="docs/images/large-file-transfer.jpg" alt="大文件传输演示" />
142
+
143
+ ### 🔐 命令执行审批
144
+
145
+ 当 AI 需要执行命令时,插件会通过 QQ 消息发送带按钮的审批请求,你可以点击 **✅ 允许一次**、**⭐ 始终允许** 或 **❌ 拒绝** 来控制命令是否执行。
146
+
147
+ 通过 `/bot-approve` 指令可以管理审批模式(白名单 / 关闭 / 严格模式)。
148
+
149
+ <img width="360" src="docs/images/approve.png" alt="命令执行审批演示" />
150
+
151
+ ### 🎬 视频发送
152
+
153
+ > **你**:发一个演示视频给我
154
+ >
155
+ > **QQBot**:*(发送视频)*
156
+
157
+ AI 可直接发送视频,支持本地文件和公网 URL。
158
+
159
+ <img width="360" src="docs/images/video-send.jpg" alt="发视频演示" />
160
+
161
+ > **底层细节:** 上传去重缓存、有序队列发送、音频格式多层降级。
162
+
163
+ ### 🛠️ 斜杠指令
164
+
165
+ 插件内置一组斜杠指令,在消息进入 AI 队列前拦截处理,即时响应,用于诊断和管理。
166
+
167
+ #### `/bot-ping` — 延迟测试
168
+
169
+ > **你**:`/bot-ping`
170
+ >
171
+ > **QQBot**:✅ pong!⏱ 延迟: 602ms(网络传输: 602ms,插件处理: 0ms)
172
+
173
+ 测量从 QQ 服务器推送到插件响应的端到端延迟,细分网络传输和插件处理两段耗时。
174
+
175
+ <img width="360" src="docs/images/slash-ping.jpg" alt="Ping 演示" />
176
+
177
+ #### `/bot-version` — 版本信息
178
+
179
+ > **你**:`/bot-version`
180
+ >
181
+ > **QQBot**:🦞框架版本:OpenClaw 2026.9.2 / 🤖QQBot 插件版本:v1.0.0 / 🌟GitHub 仓库
182
+
183
+ 一目了然查看框架版本、插件版本,并可直接跳转官方仓库。
184
+
185
+ <img width="360" src="docs/images/slash-version.jpg" alt="Version 演示" />
186
+
187
+ #### `/bot-help` — 指令列表
188
+
189
+ > **你**:`/bot-help`
190
+ >
191
+ > **QQBot**:列出所有可用的斜杠指令及说明,指令可点击快速输入。
192
+
193
+ <img width="360" src="docs/images/slash-help.jpg" alt="Help 演示" />
194
+
195
+ #### `/bot-upgrade` — 版本检查与升级指引
196
+
197
+ > **你**:`/bot-upgrade`
198
+ >
199
+ > **QQBot**:📌当前版本 v1.0.0 / 🆕发现新版本 / 📖升级指引链接
200
+
201
+ 对比 npm registry(`@jerryliang122/openclaw-qqbot`)上的最新版本,并返回升级指引链接(默认指向仓库 CHANGELOG,可用 `channels.qqbot.upgradeUrl` 覆盖)。实际升级在主机上通过 `openclaw plugins install` 完成,见[快速开始](#-快速开始)。
202
+
203
+ <img width="360" src="docs/images/hot-update.jpg" alt="升级检查演示" />
204
+
205
+ #### `/bot-logs` — 日志导出
206
+
207
+ > **你**:`/bot-logs`
208
+ >
209
+ > **QQBot**:📋 日志已打包(约 2000 行),正在发送文件… *(发送 .txt 文件)*
210
+
211
+ 导出最近约 2000 行网关日志为文件,方便快速排查问题。
212
+
213
+ <img width="360" src="docs/images/slash-logs.jpg" alt="Logs 演示" />
214
+
215
+ #### 用法查询
216
+
217
+ 所有指令都支持 `?` 后缀查看用法说明:
218
+
219
+ > **你**:`/bot-upgrade ?`
220
+ >
221
+ > **QQBot**:📖 /bot-upgrade 用法:…
222
+
223
+ #### `/bot-approve` — 审批配置管理
224
+
225
+ > **你**:`/bot-approve`
226
+ >
227
+ > **QQBot**:🔐 命令执行审批配置 — 开启审批 / 关闭审批 / 严格模式 / 恢复默认 / 查看当前配置
228
+
229
+ 管理 AI 命令执行审批策略,支持以下子命令:
230
+
231
+ | 子命令 | 说明 |
232
+ |--------|------|
233
+ | `/bot-approve on` | 开启审批(白名单模式,推荐) |
234
+ | `/bot-approve off` | 关闭审批,命令直接执行 |
235
+ | `/bot-approve always` | 严格模式,每次执行都需审批 |
236
+ | `/bot-approve reset` | 恢复框架默认值 |
237
+ | `/bot-approve status` | 查看当前审批配置 |
238
+
239
+ #### `/bot-clear-storage` — 清理通过 QQBot 对话产生的文件以及下载的资源(保存在 OpenClaw 运行环境的主机上)
240
+
241
+ `/bot-clear-storage` 列出对话产生的文件以及下载的资源目录里的文件,使用`/bot-clear-storage -- force`确定删除。
242
+
243
+ #### `/bot-group-always` — 群消息响应模式切换
244
+
245
+ > **你**:`/bot-group-always`
246
+ >
247
+ > **QQBot**:🤖 群自主发言状态:❌ 仅被 @ 时回复
248
+
249
+ 运行时动态切换群聊默认 @触发行为,修改即时持久化,无需重启:
250
+
251
+ | 子命令 | 说明 |
252
+ |--------|------|
253
+ | `/bot-group-always on` | AI 自主判断何时发言(无需 @) |
254
+ | `/bot-group-always off` | 仅在被 @ 时回复 |
255
+ | `/bot-group-always`(无参数) | 查看当前设置 |
256
+
257
+ > ⚠️ 此指令修改账户级 `defaultRequireMention`,优先级低于具体群的 `groups.{groupId}.requireMention` 配置。
258
+
259
+ #### `/bot-group-info` — 群推送模式与生效配置查询(群内使用)
260
+
261
+ > **你**:`/bot-group-info`(在群里发送)
262
+ >
263
+ > **QQBot**:🤖 群信息 — 推送模式推断(AT 系 / 全量)、requireMention、排队策略、历史模式、房间事件策略、今日主动消息用量
264
+
265
+ 回答「这个群为什么没上下文」这类排障问题:推送模式由**群主**拉 bot 进群时选择(仅 @ / @+最近N / 全量),此指令展示插件实际观测到的模式与所有生效配置值。
266
+
267
+ ---
268
+
269
+ ---
270
+
271
+ ## 🚀 快速开始
272
+
273
+ ### 第一步 — 在 QQ 开放平台创建机器人
274
+
275
+ 1. 前往 [QQ 开放平台](https://q.qq.com/),用**手机 QQ 扫描页面二维码**即可注册/登录。若尚未注册,扫码后系统会自动完成注册并绑定你的 QQ 账号。
276
+
277
+ <img width="3246" height="1886" alt="Clipboard_Screenshot_1772980354" src="https://github.com/user-attachments/assets/d8491859-57e8-47e4-9d39-b21138be54d0" />
278
+
279
+ 2. 手机 QQ 扫码后选择**同意**,即完成注册,进入 QQ 机器人配置页。
280
+ 3. 点击**创建机器人**,即可直接新建一个 QQ 机器人。
281
+
282
+ <img width="720" alt="创建机器人" src="docs/images/create-robot.png" />
283
+
284
+ > ⚠️ 机器人创建后会自动出现在你的 QQ 消息列表中,并发送第一条消息。但在完成下面的配置之前,发消息会提示"该机器人去火星了",属于正常现象。
285
+
286
+ <img width="400" alt="机器人打招呼" src="docs/images/bot-say-hello.jpg" />
287
+
288
+ 4. 在机器人页面中找到 **AppID** 和 **AppSecret**,分别点击右侧**复制**按钮,保存到记事本或备忘录中。**AppSecret 不支持明文保存,离开页面后再查看会强制重置,请务必妥善保存。**
289
+
290
+ <img width="720" alt="找到 AppID 和 AppSecret" src="docs/images/find-appid-secret.png" />
291
+
292
+ > 详细图文教程请参阅 [官方指南](https://cloud.tencent.com/developer/article/2626045)。
293
+
294
+ ### 第二步 — 安装 / 升级插件
295
+
296
+ > 无 scope 的 npm 包名 `openclaw-qqbot` 属于上游原项目——本 fork 以 `@jerryliang122/openclaw-qqbot` 发布。要求 OpenClaw >= 2026.9.2。
297
+
298
+ **方式 A:从 npm 安装(推荐)**
299
+
300
+ ```bash
301
+ openclaw plugins install @jerryliang122/openclaw-qqbot
302
+
303
+ # 或安装指定版本
304
+ openclaw plugins install @jerryliang122/openclaw-qqbot@1.0.0
305
+ ```
306
+
307
+ **方式 B:从 GitHub 安装**
308
+
309
+ ```bash
310
+ openclaw plugins install git+https://github.com/jerryliang122/qqbot-openclaw.git
311
+
312
+ # 或安装指定版本
313
+ openclaw plugins install git+https://github.com/jerryliang122/qqbot-openclaw.git#v1.0.0
314
+ ```
315
+
316
+ **方式 C:源码安装**
317
+
318
+ ```bash
319
+ git clone https://github.com/jerryliang122/qqbot-openclaw.git
320
+ cd openclaw-qqbot
321
+
322
+ # 构建
323
+ npm install
324
+ npm run build
325
+
326
+ # 安装到 OpenClaw(方式一:link)
327
+ openclaw plugins link .
328
+
329
+ # 或(方式二:pack)
330
+ npm pack
331
+ openclaw plugins install ./jerryliang122-openclaw-qqbot-1.0.0.tgz
332
+ ```
333
+
334
+ **配置凭证**
335
+
336
+ ```bash
337
+ # 扫码登录(推荐,无需手动填写凭证)
338
+ openclaw channels login --channel qqbot
339
+
340
+ # 或手动配置
341
+ openclaw channels add --channel qqbot --token "AppID:AppSecret"
342
+
343
+ # 启动 / 重启
344
+ openclaw gateway restart
345
+ ```
346
+
347
+ > 环境变量 `QQBOT_APPID` / `QQBOT_SECRET` 同样支持。
348
+
349
+ **从旧版本(上游 2.x)升级?** 请阅读 [CHANGELOG](CHANGELOG.md)——其中列出了全部破坏性变更(已移除的配置项、环境变量与行为)及迁移对照表。
350
+
351
+ ### 第三步 — 测试
352
+
353
+ 打开 QQ,找到你的机器人,发条消息试试!
354
+
355
+ <div align="center">
356
+ <img width="500" alt="聊天演示" src="https://github.com/user-attachments/assets/b2776c8b-de72-4e37-b34d-e8287ce45de1" />
357
+ </div>
358
+
359
+ ---
360
+
361
+ ## ⚙️ 进阶配置
362
+
363
+ ### 多账户配置(Multi-Bot)
364
+
365
+ 支持在同一个 OpenClaw 实例下同时运行多个 QQ 机器人。
366
+
367
+ #### 配置方式
368
+
369
+ 编辑 `~/.openclaw/openclaw.json`,在 `channels.qqbot` 下增加 `accounts` 字段:
370
+
371
+ ```json
372
+ {
373
+ "channels": {
374
+ "qqbot": {
375
+ "enabled": true,
376
+ "appId": "111111111",
377
+ "clientSecret": "secret-of-bot-1",
378
+
379
+ "accounts": {
380
+ "bot2": {
381
+ "enabled": true,
382
+ "appId": "222222222",
383
+ "clientSecret": "secret-of-bot-2"
384
+ },
385
+ "bot3": {
386
+ "enabled": true,
387
+ "appId": "333333333",
388
+ "clientSecret": "secret-of-bot-3"
389
+ }
390
+ }
391
+ }
392
+ }
393
+ }
394
+ ```
395
+
396
+ **说明:**
397
+
398
+ - 顶层的 `appId` / `clientSecret` 是**默认账户**(accountId = `"default"`)
399
+ - `accounts` 下的每个 key(如 `bot2`、`bot3`)就是该账户的 `accountId`
400
+ - 每个账户都可以独立配置 `enabled`、`name`、`allowFrom`、`systemPrompt` 等字段
401
+ - 也可以不配顶层默认账户,只在 `accounts` 里配置所有机器人
402
+
403
+ 通过 CLI 添加第二个机器人(如果框架支持 `--account` 参数):
404
+
405
+ ```bash
406
+ openclaw channels add --channel qqbot --account bot2 --token "222222222:secret-of-bot-2"
407
+ ```
408
+
409
+ #### 向指定账户的用户发送消息
410
+
411
+ 使用 `openclaw message send` 发消息时,需要通过 `--account` 参数指定使用哪个机器人发送:
412
+
413
+ ```bash
414
+ # 使用默认机器人发送(不指定 --account 时自动使用 default)
415
+ openclaw message send --channel "qqbot" \
416
+ --target "qqbot:c2c:OPENID" \
417
+ --message "hello from default bot"
418
+
419
+ # 使用 bot2 发送
420
+ openclaw message send --channel "qqbot" \
421
+ --account bot2 \
422
+ --target "qqbot:c2c:OPENID" \
423
+ --message "hello from bot2"
424
+ ```
425
+
426
+ **Target 格式支持:**
427
+
428
+ | 格式 | 说明 |
429
+ |------|------|
430
+ | `qqbot:c2c:OPENID` | 私聊 |
431
+ | `qqbot:group:GROUP_OPENID` | 群聊 |
432
+ | `qqbot:channel:CHANNEL_ID` | 频道 |
433
+
434
+ > ⚠️ **注意**:每个机器人的用户 OpenID 是不同的。机器人 A 收到的用户 OpenID 不能用机器人 B 去发消息,否则会返回 500 错误。必须用对应机器人的 accountId 去给该机器人的用户发消息。
435
+
436
+ #### 工作原理
437
+
438
+ - 启动 `openclaw gateway` 后,所有 `enabled: true` 的账户会同时启动连接(WebSocket 或 Webhook,取决于 `transport` 配置)
439
+ - 每个账户独立维护 Token 缓存(基于 `appId` 隔离),互不干扰
440
+ - 接收消息时,日志会带上 `[qqbot:accountId]` 前缀方便排查
441
+
442
+ ---
443
+
444
+ ### Webhook 传输模式
445
+
446
+ 默认情况下,插件通过 **WebSocket** 连接 QQ 平台(出站连接,无需公网 IP)。你也可以切换为 **Webhook** 模式,由 QQ 平台主动 POST 事件到你的 HTTP 端点。
447
+
448
+ | | WebSocket(默认) | Webhook |
449
+ |---|---|---|
450
+ | 连接方式 | 插件主动连接 QQ 网关 | QQ 平台 POST 到你的服务器 |
451
+ | 公网 IP | 不需要 | 需要 |
452
+ | 适用场景 | 开发调试、单实例部署 | 生产环境、水平扩展、Serverless |
453
+ | 会话恢复 | 支持 RESUME | 无状态,无需恢复 |
454
+ | 签名验证 | 平台内置 | 插件自动 Ed25519 验签 |
455
+
456
+ #### 配置方式
457
+
458
+ ```json
459
+ {
460
+ "channels": {
461
+ "qqbot": {
462
+ "appId": "111111111",
463
+ "clientSecret": "your-secret",
464
+ "transport": "webhook",
465
+ "webhook": {
466
+ "path": "/qqbot/webhook"
467
+ }
468
+ }
469
+ }
470
+ }
471
+ ```
472
+
473
+ | 字段 | 默认值 | 说明 |
474
+ |------|--------|------|
475
+ | `transport` | `"websocket"` | `"websocket"` 或 `"webhook"` |
476
+ | `webhook.path` | `"/qqbot/webhook"` | 接收回调的 HTTP 路径 |
477
+
478
+ #### 平台配置步骤
479
+
480
+ 1. 登录 [QQ 开放平台](https://q.qq.com/) → 开发设置 → 消息接收方式
481
+ 2. 选择 **HTTP 回调**
482
+ 3. 填写回调 URL:`https://your-domain.com/qqbot/webhook`
483
+ 4. 平台发送 `op:13` 验证请求,插件自动处理签名验证
484
+ 5. 验证通过后,所有事件将以 POST 方式推送到该地址
485
+
486
+ ---
487
+
488
+ ### 群聊配置
489
+
490
+ 插件提供灵活的群聊管控能力,支持按群定制触发规则、工具权限和 AI 行为策略。
491
+
492
+ #### @提及触发模式(requireMention)
493
+
494
+ 默认情况下,群聊中**必须 @机器人**才会触发 AI 回复。你可以通过配置让 AI 自主判断是否需要发言:
495
+
496
+ | 模式 | 配置值 | 行为 |
497
+ |------|--------|------|
498
+ | **仅 @时回复** | `true`(默认) | 群消息中只有 @了机器人才会触发回复 |
499
+ | **自主发言** | `false` | AI 自主判断每条消息是否需要回复,无需 @ |
500
+
501
+ **优先级链**(从高到低):
502
+
503
+ ```
504
+ 具体群 groups.{groupOpenid}.requireMention
505
+ > 通配符 groups."*".requireMention
506
+ > 账户级 defaultRequireMention
507
+ > 默认值 true
508
+ ```
509
+
510
+ **配置示例:**
511
+
512
+ ```json
513
+ {
514
+ "channels": {
515
+ "qqbot": {
516
+ // 账户级:所有群的默认行为
517
+ "defaultRequireMention": false,
518
+
519
+ "accounts": {
520
+ "default": {
521
+ "groups": {
522
+ "*": {
523
+ // 通配符:所有群的兜底规则
524
+ "requireMention": false
525
+ },
526
+ "GROUP_OPENID": {
527
+ // 单群覆盖:这个群仍然需要 @
528
+ "requireMention": true
529
+ }
530
+ }
531
+ }
532
+ }
533
+ }
534
+ }
535
+ }
536
+ ```
537
+
538
+ > **使用场景举例:**
539
+ >
540
+ > - 工作群设为 `requireMention: true` — 避免 AI 对每条闲聊都插嘴
541
+ > - 专属 AI 陪伴群设为 `requireMention: false` — 像真人一样自然参与对话
542
+ > - 通过 `/bot-group-always on|off` 指令可在运行时动态切换账户级默认值
543
+
544
+ #### 其他群配置项
545
+
546
+ 除 `requireMention` 外,每个群还支持以下配置:
547
+
548
+ | 字段 | 类型 | 默认值 | 说明 |
549
+ |------|------|--------|------|
550
+ | `ignoreOtherMentions` | `boolean` | `false` | 是否忽略 @了其他人但没 @机器人的消息。开启后这类消息直接丢弃,不记录历史、不触发 AI |
551
+ | `toolPolicy` | `"full" \| "restricted" \| "none"` | `"restricted"` | 群聊中 AI 可使用的工具范围。`full`=全部可用;`restricted`=限制敏感工具(如命令执行、文件操作);`none`=禁止所有工具调用 |
552
+ | `prompt` | `string` | 内置默认提示词 | 该群专属的系统提示词,会追加到全局 systemPrompt 之后 |
553
+ | `historyLimit` | `number` | `20` | 群历史消息缓存条数(0 禁用) |
554
+ | `historyMode` | `"clear" \| "rolling"` | `"clear"` | `clear`:每次回复后清空历史(旧行为)。`rolling`:bot 自己的发言也计入历史,回复后裁剪到 bot 最后一条发言之后(AI 能看到自己上次说到哪) |
555
+ | `unmentionedInbound` | `"user_request" \| "room_event"` | `"user_request"` | `room_event`:像普通群成员一样读到所有消息,未 @ 的作为被动房间事件(详见下文;需群主开启全量推送模式) |
556
+ | `coalesce` | `object` | `{enabled: true}` | 群消息排队配置,完全交给框架队列(`enabled=true`→collect 合并批处理;`false`→followup 排队不合并) |
557
+
558
+ #### 房间事件模式(全量模式群,可选)
559
+
560
+ > 前提:群主把该群的推送范围设为「接收所有消息」(全量模式)。AT 模式的群收不到未 @ 消息,此配置无效果。
561
+
562
+ ```json
563
+ "groups": {
564
+ "GROUP_OPENID": { "unmentionedInbound": "room_event" }
565
+ }
566
+ ```
567
+
568
+ 开启后的行为:
569
+
570
+ - **被 @ / 被称呼 / 引用 bot 消息** → 正常回复(完整回复权)
571
+ - **其余所有消息** → 被动房间事件:AI 只读上下文,最终文本**不投递**(结构性沉默),想发言必须主动调用 `message` 工具
572
+ - 房间事件绝不打断正在处理的任务,只排队
573
+ - ⚠️ 成本提示:每条消息跑一次推理(「读」消息),活跃群请按群显式开启
574
+
575
+ **称呼唤醒**(群友不打 @、直接叫名字):在 `agents` 段(不在 `channels.qqbot` 下)配置:
576
+
577
+ ```json
578
+ "agents": {
579
+ "list": [{ "id": "default", "groupChat": { "mentionPatterns": ["沈处"] } }]
580
+ }
581
+ ```
582
+
583
+ 误唤醒有兜底:LLM 判断「只是在聊我、不是在叫我」时可输出 `NO_REPLY` 保持沉默(框架自动注入该指引,无需改提示词)。
584
+
585
+ **完整群配置示例:**
586
+
587
+ ```json
588
+ {
589
+ "channels": {
590
+ "qqbot": {
591
+ "defaultRequireMention": false,
592
+ "accounts": {
593
+ "default": {
594
+ "groups": {
595
+ "*": {
596
+ "requireMention": true,
597
+ "toolPolicy": "restricted",
598
+ "ignoreOtherMentions": true
599
+ },
600
+ "WORK_GROUP_OPENID": {
601
+ "requireMention": true,
602
+ "toolPolicy": "none",
603
+ "prompt": "你是工作助手,只回答与工作相关的问题"
604
+ },
605
+ "FRIEND_GROUP_OPENID": {
606
+ "requireMention": false,
607
+ "toolPolicy": "full",
608
+ "prompt": "你是群里的朋友,轻松随意地聊天"
609
+ }
610
+ }
611
+ }
612
+ }
613
+ }
614
+ }
615
+ }
616
+ ```
617
+
618
+ #### 群访问控制(groupPolicy)
619
+
620
+ 通过 `groupPolicy` 控制哪些群允许机器人加入并接收消息:
621
+
622
+ | 策略 | 说明 |
623
+ |------|------|
624
+ | `"open"`(默认) | 所有群均可使用 |
625
+ | `"allowlist"` | 仅 `groupAllowFrom` 白名单中的群可使用 |
626
+ | `"disabled"` | 禁止所有群聊 |
627
+
628
+ ```json
629
+ {
630
+ "channels": {
631
+ "qqbot": {
632
+ "groupPolicy": "allowlist",
633
+ "groupAllowFrom": ["ALLOWED_GROUP_OPENID_1", "ALLOWED_GROUP_OPENID_2"]
634
+ }
635
+ }
636
+ }
637
+ ```
638
+
639
+ > 也可通过 [**`/bot-group-always`** 指令](#bot-group-always--群消息响应模式切换) 在运行时动态切换账户级默认值,无需重启。
640
+
641
+ ---
642
+
643
+ #### STT(语音转文字)— 自动转录用户发来的语音消息
644
+
645
+ STT 支持两级配置,按优先级查找:
646
+
647
+ | 优先级 | 配置路径 | 作用域 |
648
+ |--------|----------|--------|
649
+ | 1(highest) | `channels.qqbot.stt` | 插件专属 |
650
+ | 2(fallback) | `tools.media.audio.models[0]` | 框架级 |
651
+
652
+ ```json
653
+ {
654
+ "channels": {
655
+ "qqbot": {
656
+ "stt": {
657
+ "provider": "your-provider",
658
+ "model": "your-stt-model"
659
+ }
660
+ }
661
+ }
662
+ }
663
+ ```
664
+
665
+ - `provider` — 引用 `models.providers` 中的 key,自动继承 `baseUrl` 和 `apiKey`
666
+ - 设置 `enabled: false` 可禁用
667
+ - 配置后,用户发来的语音消息会自动转换(SILK→WAV)并转录为文字
668
+ - `asrFallback` — 平台转写(`asr_refer_text`)参与开关。**未显式设为 `true` 时,平台转写在所有场景下都被丢弃**:自有 STT 失败或返回空时不作兜底,STT 未配置时也不作为唯一来源(此时语音消息渲染为 `[Voice message - transcription unavailable]` 占位文本,音频 URL 仍通过 `- Voice:` 行引用)。该开关从 `channels.qqbot.stt.asrFallback` 读取,与 STT 凭证是否解析成功无关——仅写 `stt: { "asrFallback": true }` 即可恢复平台转写参与旧行为:
669
+
670
+ ```json
671
+ {
672
+ "channels": {
673
+ "qqbot": {
674
+ "stt": {
675
+ "provider": "your-provider",
676
+ "model": "your-stt-model",
677
+ "asrFallback": true
678
+ }
679
+ }
680
+ }
681
+ }
682
+ ```
683
+
684
+ #### TTS(文字转语音)— 机器人发送语音消息
685
+
686
+ | 优先级 | 配置路径 | 作用域 |
687
+ |--------|----------|--------|
688
+ | 1(highest) | `channels.qqbot.tts` | 插件专属 |
689
+ | 2(fallback) | `messages.tts` | 框架级 |
690
+
691
+ ```json
692
+ {
693
+ "channels": {
694
+ "qqbot": {
695
+ "tts": {
696
+ "provider": "your-provider",
697
+ "model": "your-tts-model",
698
+ "voice": "your-voice"
699
+ }
700
+ }
701
+ }
702
+ }
703
+ ```
704
+
705
+ - `provider` — 引用 `models.providers` 中的 key,自动继承 `baseUrl` 和 `apiKey`
706
+ - `voice` — 语音音色
707
+ - 设置 `enabled: false` 可禁用(默认:`true`)
708
+ - 配置后,AI 可生成并发送语音消息
709
+
710
+ #### 流式回复 — 仅 C2C 私聊
711
+
712
+ 通过 QQ 流式接口逐段下发回复(打字机效果)。群聊不支持流式(平台限制)。未配置即关闭。
713
+
714
+ ```json
715
+ {
716
+ "channels": {
717
+ "qqbot": {
718
+ "streaming": {
719
+ "mode": "partial",
720
+ "sendMode": "stream"
721
+ }
722
+ }
723
+ }
724
+ }
725
+ ```
726
+
727
+ | 字段 | 默认 | 说明 |
728
+ |------|------|------|
729
+ | `mode` | *(未配置 = 关闭)* | `"partial"` 开启流式接收;`"off"` 关闭 |
730
+ | `sendMode` | `"stream"` | `"stream"` — QQ 流式打印机(打字机;已下发前缀不可变,尾部重写合并为追加)。`"static"` — 生成期间只累积,结束时一条完整消息发出(无打字机) |
731
+
732
+ - 流式分片(`session.update`)仍消耗触发消息的被动回复配额
733
+ - 流式出错时控制器自动降级为单条静态消息
734
+
735
+ #### 正在输入指示器(typing)— 仅 C2C 私聊
736
+
737
+ 机器人收到私聊消息后会显示"正在输入中…",并在 AI 处理期间周期性续期。
738
+
739
+ ```json
740
+ {
741
+ "channels": {
742
+ "qqbot": {
743
+ "typing": {
744
+ "enabled": true,
745
+ "intervalMs": 20000
746
+ }
747
+ }
748
+ }
749
+ }
750
+ ```
751
+
752
+ - `enabled` — 是否启用(默认:`true`),设为 `false` 可完全关闭
753
+ - `intervalMs` — 续期间隔毫秒(默认:`20000`)。QQ 客户端退出聊天界面再进入后指示器会消失,只有新的推送才会重新显示,因此需要续期;受 QPS 限制,低于 `20000` 的值会被钳制到 `20000`
754
+ - **配额说明**:typing 通知与回复消息共享同一条用户消息的被动回复配额(QQ 开放平台同一条消息被动回复上限约 5 条)。被动配额耗尽后,typing 与回复消息一样自动降级为主动发送(不带 msg_id),续期不会中断
755
+ - **中间消息续期**:机器人发出消息(如思维链等中间输出)后 QQ 客户端会终止指示器显示;若框架任务仍在进行,插件会在消息发出 5 秒后自动补发一次续期恢复显示(同样受 20s QPS 间距保护)。最终回复发出后任务完成,不再补发
756
+
757
+ ---
758
+
759
+ ## 📚 文档与链接
760
+
761
+ - [更新日志](CHANGELOG.md) — 与旧版本的差异、破坏性变更与各版本记录
762
+ - [命令参考](docs/commands.md) — OpenClaw CLI 常用命令
763
+
764
+ ## 🤝 贡献者
765
+
766
+ 感谢所有为本项目做出贡献的开发者!上游贡献者见 [tencent-connect/openclaw-qqbot](https://github.com/tencent-connect/openclaw-qqbot/graphs/contributors)。
767
+
768
+ <a href="https://github.com/jerryliang122/qqbot-openclaw/graphs/contributors">
769
+ <img src="https://contrib.rocks/image?repo=jerryliang122/qqbot-openclaw" />
770
+ </a>
771
+
772
+ ## 💖 致谢
773
+
774
+ 特别感谢 [@sliverp](https://github.com/sliverp) 对项目的核心贡献!
775
+
776
+ <a href="https://github.com/sliverp"><img src="https://avatars.githubusercontent.com/u/38134380?v=4" width="48" height="48" alt="sliverp" title="sliverp"/></a>
777
+
778
+ 感谢[腾讯云Lighthouse](https://cloud.tencent.com/product/lighthouse)的深度合作,养小龙虾,首选腾讯云Lighthouse!
779
+
780
+ <a href="https://cloud.tencent.com/product/lighthouse">
781
+ <img alt="腾讯云 Lighthouse" src="./docs/images/lighthouse-head.png" height="500" style="max-width:80%; height:auto;"/>
782
+ </a>
783
+
784
+ ## ⭐ Star History
785
+
786
+ <div align="center">
787
+
788
+ [![Star History Chart](https://api.star-history.com/svg?repos=jerryliang122/qqbot-openclaw&type=date&legend=top-left)](https://www.star-history.com/#jerryliang122/qqbot-openclaw&type=date&legend=top-left)
789
+
790
+ </div>