@tencent-connect/openclaw-qqbot 1.7.0 → 1.7.2

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 (45) hide show
  1. package/README.md +216 -49
  2. package/README.zh.md +216 -4
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.js +1 -0
  5. package/dist/src/api.d.ts +6 -0
  6. package/dist/src/api.js +33 -4
  7. package/dist/src/approval-handler.d.ts +47 -0
  8. package/dist/src/approval-handler.js +372 -0
  9. package/dist/src/channel.js +72 -0
  10. package/dist/src/config.d.ts +5 -1
  11. package/dist/src/config.js +12 -2
  12. package/dist/src/gateway.js +175 -170
  13. package/dist/src/slash-commands.d.ts +7 -2
  14. package/dist/src/slash-commands.js +354 -3
  15. package/dist/src/tools/channel.js +1 -4
  16. package/dist/src/tools/remind.js +0 -1
  17. package/dist/src/transport/index.d.ts +10 -0
  18. package/dist/src/transport/index.js +9 -0
  19. package/dist/src/transport/webhook-transport.d.ts +67 -0
  20. package/dist/src/transport/webhook-transport.js +245 -0
  21. package/dist/src/transport/webhook-verify.d.ts +48 -0
  22. package/dist/src/transport/webhook-verify.js +98 -0
  23. package/dist/src/types.d.ts +85 -0
  24. package/dist/src/utils/audio-convert.js +37 -9
  25. package/index.ts +1 -0
  26. package/package.json +1 -1
  27. package/scripts/postinstall-link-sdk.js +44 -0
  28. package/scripts/upgrade-via-npm.sh +358 -62
  29. package/scripts/upgrade-via-source.sh +122 -85
  30. package/src/api.ts +50 -5
  31. package/src/approval-handler.ts +505 -0
  32. package/src/channel.ts +76 -0
  33. package/src/config.ts +15 -2
  34. package/src/gateway.ts +181 -169
  35. package/src/onboarding.ts +8 -0
  36. package/src/openclaw-plugin-sdk.d.ts +127 -2
  37. package/src/slash-commands.ts +390 -5
  38. package/src/tools/channel.ts +1 -7
  39. package/src/tools/remind.ts +0 -2
  40. package/src/transport/index.ts +11 -0
  41. package/src/transport/webhook-transport.ts +332 -0
  42. package/src/transport/webhook-verify.ts +119 -0
  43. package/src/types.ts +100 -1
  44. package/src/typings/openclaw-webhook-ingress.d.ts +66 -0
  45. package/src/utils/audio-convert.ts +37 -9
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  **Connect your AI assistant to QQ — private chat, group chat, and rich media, all in one plugin.**
12
12
 
13
- ### 🚀 Current Version: `v1.7.0`
13
+ ### 🚀 Current Version: `v1.7.1`
14
14
 
15
15
  [![License](https://img.shields.io/badge/license-MIT-green)](./LICENSE)
16
16
  [![QQ Bot](https://img.shields.io/badge/QQ_Bot-API_v2-red)](https://bot.q.qq.com/wiki/)
@@ -36,7 +36,9 @@ Scan to join the QQ group chat
36
36
 
37
37
  | Feature | Description |
38
38
  |---------|-------------|
39
- | 🔒 **Multi-Scene** | C2C private chat, group @messages |
39
+ | 🔒 **Multi-Scene** | C2C private chat, group chat (@mention / autonomous dual mode) |
40
+ | 👥 **Group Fine-Tuning** | Per-group @trigger rules, tool policies, custom prompts, message filtering |
41
+ | 🌐 **Dual Transport** | WebSocket (default) or Webhook (HTTP callback) — switch via config |
40
42
  | 🖼️ **Rich Media** | Send & receive images, voice, video, and files |
41
43
  | 🎙️ **Voice (STT/TTS)** | Speech-to-text transcription & text-to-speech replies |
42
44
  | 🔥 **One-Click Hot Upgrade** | Send `/bot-upgrade` in private chat to upgrade — no server login needed |
@@ -47,45 +49,7 @@ Scan to join the QQ group chat
47
49
  | 🛠️ **Commands** | Native OpenClaw command integration |
48
50
  | 💬 **Quoted Context** | Parses the original message a user is replying to and injects it into AI context, so the model always knows exactly which message is being referenced |
49
51
  | 📦 **Large File Support** | Auto chunked upload for large files (parallel upload with retry), up to 100 MB |
50
-
51
- ---
52
-
53
- ## 🆚 Standalone Plugin vs OpenClaw Built-in: Which to Choose?
54
-
55
- Starting from **OpenClaw 2026.3.31**, a QQBot plugin is bundled with OpenClaw. The two plugins **cannot run at the same time** — choose one based on your needs.
56
-
57
- | Feature | This Plugin (Standalone) | OpenClaw Built-in |
58
- |---------|:------------------------:|:-----------------:|
59
- | 🔒 Multi-scene (C2C / Group) | ✅ | ✅ |
60
- | 🖼️ Rich media (image / voice / video / file) | ✅ | ✅ |
61
- | 🎙️ Voice STT / TTS | ✅ | ✅ |
62
- | 🔥 One-click hot upgrade (`/bot-upgrade`) | ✅ | ❌ |
63
- | ⏰ Scheduled push (proactive messages) | ✅ | ✅ |
64
- | 🔗 URL support | ✅ | ✅ |
65
- | ⌨️ Typing indicator | ✅ | ✅ |
66
- | 📝 Markdown | ✅ | ✅ |
67
- | 🛠️ Slash commands / native commands | ✅ | ✅ |
68
- | 💬 Quoted context (injected into AI) | ✅ | ✅ |
69
- | 📦 Large file support (up to 100MB) | ✅ | ❌ |
70
- | Installation | Requires separate install | Bundled, zero setup |
71
- | Update cadence | Independent releases, faster iteration | Ships with OpenClaw |
72
-
73
- ### Which should I pick?
74
-
75
- **Choose the OpenClaw built-in plugin if you:**
76
-
77
- - Want zero-setup out of the box
78
- - Are just getting started and want to try QQ Bot quickly
79
-
80
- **Choose this plugin (standalone) if you:**
81
-
82
- - Want faster feature iteration and more capabilities
83
-
84
- > ⚠️ Both plugins cannot run simultaneously. If you've upgraded to OpenClaw 2026.3.31+, run the following command to install this plugin — the built-in version will be disabled automatically:
85
- > ```bash
86
- > curl -fsSL https://raw.githubusercontent.com/tencent-connect/openclaw-qqbot/main/scripts/upgrade-via-npm.sh | bash
87
- > ```
88
- > After upgrading, you'll unlock large file transfers, message reference context, and all other advanced features.
52
+ | 🔐 **Command Execution Approval** | AI requests approval via Inline Keyboard buttons before executing commands — tap to allow or deny |
89
53
 
90
54
  ---
91
55
 
@@ -93,13 +57,9 @@ Starting from **OpenClaw 2026.3.31**, a QQBot plugin is bundled with OpenClaw. T
93
57
 
94
58
  > **Note:** This plugin serves as a **message channel** only — it relays messages between QQ and OpenClaw. Capabilities like image understanding, voice transcription, drawing, etc. depend on the **AI model** you configure and the **skills** installed in OpenClaw, not on this plugin itself.
95
59
 
96
- ### 💬 Quoted Message Context (REFIDX)
60
+ ### 💬 Quoted Message Context
97
61
 
98
- QQ quote events carry index keys (e.g. `REFIDX_xxx`) instead of full original message body. The plugin now resolves these indices from a local persistent store and injects quote context into AI input, so replies better understand “which message is being quoted”.
99
-
100
- - Inbound and outbound messages with `ref_idx` are automatically indexed.
101
- - Store path: `~/.openclaw/qqbot/data/ref-index.jsonl` (survives gateway restart).
102
- - Quote body may include text + media summary (image/voice/video/file).
62
+ When a user quotes a message in QQ, the plugin automatically parses the quoted message content and injects it into the AI context, so the model clearly knows "which message the user is replying to" and gives more accurate responses. Supports text and media messages (image/voice/video/file), and works across devices.
103
63
 
104
64
  <img width="360" src="docs/images/ref-msg.png" alt="Quoted Message Context Demo" />
105
65
 
@@ -177,6 +137,14 @@ Since v1.6.6, large file transfer is supported: images up to 20MB, videos up to
177
137
 
178
138
  <img width="360" src="docs/images/large-file-transfer.jpg" alt="Large File Transfer Demo" />
179
139
 
140
+ ### 🔐 Command Execution Approval
141
+
142
+ When the AI needs to execute a command, the plugin sends an approval request via QQ message with interactive buttons — tap **✅ Allow Once**, **⭐ Always Allow**, or **❌ Deny** to control whether the command runs.
143
+
144
+ Use the `/bot-approve` command to manage the approval mode (allowlist / off / strict).
145
+
146
+ <img width="360" src="docs/images/approve.png" alt="Command Execution Approval Demo" />
147
+
180
148
  ### 🎬 Video Sending
181
149
 
182
150
  > **You**: Send me a demo video
@@ -256,10 +224,42 @@ All commands support a `?` suffix to show usage:
256
224
  >
257
225
  > **QQBot**: 📖 /bot-upgrade usage: …
258
226
 
227
+ #### `/bot-approve` — Approval Configuration
228
+
229
+ > **You**: `/bot-approve`
230
+ >
231
+ > **QQBot**: 🔐 Command Execution Approval — Enable / Disable / Strict mode / Reset / View current config
232
+
233
+ Manage the AI command execution approval policy. Supported subcommands:
234
+
235
+ | Subcommand | Description |
236
+ |------------|-------------|
237
+ | `/bot-approve on` | Enable approval (allowlist mode, recommended) |
238
+ | `/bot-approve off` | Disable approval — commands execute directly |
239
+ | `/bot-approve always` | Strict mode — every execution requires approval |
240
+ | `/bot-approve reset` | Restore framework defaults |
241
+ | `/bot-approve status` | View current approval config |
242
+
259
243
  #### `/bot-clear-storage` — Clear files generated through QQBot conversations and downloaded resources (stored on the host running OpenClaw)
260
244
 
261
245
  `/bot-clear-storage` lists files generated by the conversation and files in the downloaded resources directory. Use `/bot-clear-storage --force` to confirm deletion.
262
246
 
247
+ #### `/bot-group-allways` — Group Response Mode Toggle
248
+
249
+ > **You**: `/bot-group-allways`
250
+ >
251
+ > **QQBot**: 🤖 Group autonomous mode: ❌ @mention required
252
+
253
+ Toggle group @trigger behavior at runtime — changes persist instantly, no restart needed:
254
+
255
+ | Subcommand | Description |
256
+ |------------|-------------|
257
+ | `/bot-group-allways on` | AI decides when to speak autonomously (no @ needed) |
258
+ | `/bot-group-allways off` | Only respond when @mentioned |
259
+ | `/bot-group-allways` (no arg) | View current setting |
260
+
261
+ > ⚠️ This command modifies the account-level `defaultRequireMention`. It has lower priority than per-group `groups.{groupId}.requireMention` settings.
262
+
263
263
  ---
264
264
 
265
265
  ## 🚀 Getting Started
@@ -426,13 +426,180 @@ openclaw message send --channel "qqbot" \
426
426
 
427
427
  #### How It Works
428
428
 
429
- - When `openclaw gateway` starts, all accounts with `enabled: true` launch their own WebSocket connections
429
+ - When `openclaw gateway` starts, all accounts with `enabled: true` launch their own connections (WebSocket or Webhook depending on `transport` config)
430
430
  - Each account maintains an independent Token cache (isolated by `appId`), preventing cross-contamination
431
431
  - Incoming message logs are prefixed with `[qqbot:accountId]` for easy debugging
432
432
 
433
433
  ---
434
434
 
435
- ### Voice Configuration (STT / TTS)
435
+ ### Webhook Transport Mode
436
+
437
+ By default, the plugin connects to QQ via **WebSocket** (outbound connection, no public IP required). You can switch to **Webhook** mode where QQ platform POSTs events to your HTTP endpoint.
438
+
439
+ | | WebSocket (default) | Webhook |
440
+ |---|---|---|
441
+ | Connection | Plugin connects to QQ gateway | QQ platform POSTs to your server |
442
+ | Public IP | Not required | Required |
443
+ | Use case | Development, single instance | Production, horizontal scaling, Serverless |
444
+ | Session resume | Supported (RESUME) | Stateless, no resume needed |
445
+ | Signature | Built-in | Ed25519 auto-verified by plugin |
446
+
447
+ #### Configuration
448
+
449
+ ```json
450
+ {
451
+ "channels": {
452
+ "qqbot": {
453
+ "appId": "111111111",
454
+ "clientSecret": "your-secret",
455
+ "transport": "webhook",
456
+ "webhook": {
457
+ "path": "/qqbot/webhook"
458
+ }
459
+ }
460
+ }
461
+ }
462
+ ```
463
+
464
+ | Field | Default | Description |
465
+ |-------|---------|-------------|
466
+ | `transport` | `"websocket"` | `"websocket"` or `"webhook"` |
467
+ | `webhook.path` | `"/qqbot/webhook"` | HTTP path for receiving callbacks |
468
+
469
+ #### Platform Setup
470
+
471
+ 1. Go to [QQ Open Platform](https://q.qq.com/) → Bot Settings → Message Receiving
472
+ 2. Select **HTTP Callback**
473
+ 3. Enter your callback URL: `https://your-domain.com/qqbot/webhook`
474
+ 4. The platform sends an `op:13` validation request — the plugin handles it automatically
475
+ 5. Once validated, all events will be POSTed to your endpoint
476
+
477
+ ---
478
+
479
+ ### Group Chat Configuration
480
+
481
+ The plugin provides flexible group chat controls, allowing you to customize trigger rules, tool permissions, and AI behavior per group.
482
+
483
+ #### @Mention Trigger Mode (`requireMention`)
484
+
485
+ By default, the bot **only responds when @mentioned** in a group. You can configure it to autonomously decide when to speak:
486
+
487
+ | Mode | Config Value | Behavior |
488
+ |------|-------------|----------|
489
+ | **@ only** | `true` (default) | Only messages that @mention the bot trigger a reply |
490
+ | **Autonomous** | `false` | AI decides on its own whether each message needs a reply — no @ required |
491
+
492
+ **Priority chain** (highest to lowest):
493
+
494
+ ```
495
+ groups.{groupOpenid}.requireMention
496
+ > groups."*".requireMention
497
+ > account-level defaultRequireMention
498
+ > default value true
499
+ ```
500
+
501
+ **Example:**
502
+
503
+ ```json
504
+ {
505
+ "channels": {
506
+ "qqbot": {
507
+ // Account-level default for all groups
508
+ "defaultRequireMention": false,
509
+
510
+ "accounts": {
511
+ "default": {
512
+ "groups": {
513
+ "*": {
514
+ // Wildcard fallback for all groups
515
+ "requireMention": false
516
+ },
517
+ "GROUP_OPENID": {
518
+ // Per-group override — this group still requires @
519
+ "requireMention": true
520
+ }
521
+ }
522
+ }
523
+ }
524
+ }
525
+ }
526
+ }
527
+ ```
528
+
529
+ > **Use cases:**
530
+ >
531
+ > - Work groups → `requireMention: true` — avoid AI chiming in on every casual message
532
+ > - Dedicated AI companion groups → `requireMention: false` — participate naturally like a real person
533
+ > - Use [`/bot-group-allways`](#bot-group-allways--group-response-mode-toggle) to toggle account-level defaults at runtime
534
+
535
+ #### Additional Group Config Fields
536
+
537
+ Besides `requireMention`, each group supports these settings:
538
+
539
+ | Field | Type | Default | Description |
540
+ |-------|------|---------|-------------|
541
+ | `ignoreOtherMentions` | `boolean` | `false` | If enabled, messages that @mention others but not the bot are silently dropped (not recorded, no AI trigger) |
542
+ | `toolPolicy` | `"full" \| "restricted" \| "none"` | `"restricted"` | Tool scope available to AI in this group. `full`=all tools; `restricted`=sensitive tools restricted (e.g., command execution, file ops); `none`=no tool calls allowed |
543
+ | `prompt` | `string` | built-in default | Group-specific system prompt, appended after global systemPrompt |
544
+ | `historyLimit` | `number` | `50` | Cached group history message count |
545
+
546
+ **Full example with multiple groups:**
547
+
548
+ ```json
549
+ {
550
+ "channels": {
551
+ "qqbot": {
552
+ "defaultRequireMention": false,
553
+ "accounts": {
554
+ "default": {
555
+ "groups": {
556
+ "*": {
557
+ "requireMention": true,
558
+ "toolPolicy": "restricted",
559
+ "ignoreOtherMentions": true
560
+ },
561
+ "WORK_GROUP_OPENID": {
562
+ "requireMention": true,
563
+ "toolPolicy": "none",
564
+ "prompt": "You are a work assistant. Only answer work-related questions."
565
+ },
566
+ "FRIEND_GROUP_OPENID": {
567
+ "requireMention": false,
568
+ "toolPolicy": "full",
569
+ "prompt": "You are a friend in the group. Chat casually and naturally."
570
+ }
571
+ }
572
+ }
573
+ }
574
+ }
575
+ }
576
+ }
577
+ ```
578
+
579
+ #### Group Access Control (`groupPolicy`)
580
+
581
+ Control which groups are allowed via `groupPolicy`:
582
+
583
+ | Policy | Description |
584
+ |--------|-------------|
585
+ | `"open"` (default) | All groups are allowed |
586
+ | `"allowlist"` | Only groups in `groupAllowFrom` are allowed |
587
+ | `"disabled"` | Group chats are disabled entirely |
588
+
589
+ ```json
590
+ {
591
+ "channels": {
592
+ "qqbot": {
593
+ "groupPolicy": "allowlist",
594
+ "groupAllowFrom": ["ALLOWED_GROUP_OPENID_1", "ALLOWED_GROUP_OPENID_2"]
595
+ }
596
+ }
597
+ }
598
+ ```
599
+
600
+ > You can also use [**`/bot-group-allways`**](#bot-group-allways--group-response-mode-toggle) to toggle account-level defaults at runtime without restarting.
601
+
602
+ ---
436
603
 
437
604
  #### STT (Speech-to-Text) — Transcribe Incoming Voice Messages
438
605
 
package/README.zh.md CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  **让你的 AI 助手接入 QQ — 私聊、群聊、富媒体,一个插件全搞定。**
11
11
 
12
- ### 🚀 当前版本: `v1.7.0`
12
+ ### 🚀 当前版本: `v1.7.1`
13
13
 
14
14
  [![License](https://img.shields.io/badge/license-MIT-green)](./LICENSE)
15
15
  [![QQ Bot](https://img.shields.io/badge/QQ_Bot-API_v2-red)](https://bot.q.qq.com/wiki/)
@@ -31,7 +31,9 @@
31
31
 
32
32
  | 功能 | 说明 |
33
33
  |------|------|
34
- | 🔒 **多场景支持** | C2C 私聊、群聊 @消息 |
34
+ | 🔒 **多场景支持** | C2C 私聊、群聊(@提及 / 自主发言双模式) |
35
+ | 👥 **群聊精细管控** | 按群配置 @触发规则、工具权限、自定义提示词、消息过滤 |
36
+ | 🌐 **双传输模式** | WebSocket(默认)或 Webhook(HTTP 回调)— 配置切换 |
35
37
  | 🖼️ **富媒体消息** | 支持图片、语音、视频、文件的收发 |
36
38
  | 🎙️ **语音能力 (STT/TTS)** | 语音转文字自动转录 & 文字转语音回复 |
37
39
  | 🔥 **一键热更新** | 私聊发送 `/bot-upgrade` 即可完成版本升级,无需登录服务器 |
@@ -42,6 +44,7 @@
42
44
  | 🛠️ **原生命令** | 支持 OpenClaw 原生命令 |
43
45
  | 💬 **引用上下文** | 解析用户回复的原始消息内容,注入 AI 上下文,让模型准确理解"在回复哪条消息" |
44
46
  | 📦 **大文件支持** | 大文件自动分片并行上传,最大支持 100 MB |
47
+ | 🔐 **命令执行审批** | AI 执行命令前通过按钮消息请求审批,点击即可允许或拒绝 |
45
48
 
46
49
  ---
47
50
 
@@ -129,6 +132,14 @@ v1.6.6 起支持大文件传输:图片最大 20MB,视频最大 30MB,附件
129
132
 
130
133
  <img width="360" src="docs/images/large-file-transfer.jpg" alt="大文件传输演示" />
131
134
 
135
+ ### 🔐 命令执行审批
136
+
137
+ 当 AI 需要执行命令时,插件会通过 QQ 消息发送带按钮的审批请求,你可以点击 **✅ 允许一次**、**⭐ 始终允许** 或 **❌ 拒绝** 来控制命令是否执行。
138
+
139
+ 通过 `/bot-approve` 指令可以管理审批模式(白名单 / 关闭 / 严格模式)。
140
+
141
+ <img width="360" src="docs/images/approve.png" alt="命令执行审批演示" />
142
+
132
143
  ### 🎬 视频发送
133
144
 
134
145
  > **你**:发一个演示视频给我
@@ -208,10 +219,44 @@ AI 可直接发送视频,支持本地文件和公网 URL。
208
219
  >
209
220
  > **QQBot**:📖 /bot-upgrade 用法:…
210
221
 
222
+ #### `/bot-approve` — 审批配置管理
223
+
224
+ > **你**:`/bot-approve`
225
+ >
226
+ > **QQBot**:🔐 命令执行审批配置 — 开启审批 / 关闭审批 / 严格模式 / 恢复默认 / 查看当前配置
227
+
228
+ 管理 AI 命令执行审批策略,支持以下子命令:
229
+
230
+ | 子命令 | 说明 |
231
+ |--------|------|
232
+ | `/bot-approve on` | 开启审批(白名单模式,推荐) |
233
+ | `/bot-approve off` | 关闭审批,命令直接执行 |
234
+ | `/bot-approve always` | 严格模式,每次执行都需审批 |
235
+ | `/bot-approve reset` | 恢复框架默认值 |
236
+ | `/bot-approve status` | 查看当前审批配置 |
237
+
211
238
  #### `/bot-clear-storage` — 清理通过 QQBot 对话产生的文件以及下载的资源(保存在 OpenClaw 运行环境的主机上)
212
239
 
213
240
  `/bot-clear-storage` 列出对话产生的文件以及下载的资源目录里的文件,使用`/bot-clear-storage -- force`确定删除。
214
241
 
242
+ #### `/bot-group-allways` — 群消息响应模式切换
243
+
244
+ > **你**:`/bot-group-allways`
245
+ >
246
+ > **QQBot**:🤖 群自主发言状态:❌ 仅被 @ 时回复
247
+
248
+ 运行时动态切换群聊默认 @触发行为,修改即时持久化,无需重启:
249
+
250
+ | 子命令 | 说明 |
251
+ |--------|------|
252
+ | `/bot-group-allways on` | AI 自主判断何时发言(无需 @) |
253
+ | `/bot-group-allways off` | 仅在被 @ 时回复 |
254
+ | `/bot-group-allways`(无参数) | 查看当前设置 |
255
+
256
+ > ⚠️ 此指令修改账户级 `defaultRequireMention`,优先级低于具体群的 `groups.{groupId}.requireMention` 配置。
257
+
258
+ ---
259
+
215
260
  ---
216
261
 
217
262
  ## 🚀 快速开始
@@ -378,13 +423,180 @@ openclaw message send --channel "qqbot" \
378
423
 
379
424
  #### 工作原理
380
425
 
381
- - 启动 `openclaw gateway` 后,所有 `enabled: true` 的账户会同时启动 WebSocket 连接
426
+ - 启动 `openclaw gateway` 后,所有 `enabled: true` 的账户会同时启动连接(WebSocket 或 Webhook,取决于 `transport` 配置)
382
427
  - 每个账户独立维护 Token 缓存(基于 `appId` 隔离),互不干扰
383
428
  - 接收消息时,日志会带上 `[qqbot:accountId]` 前缀方便排查
384
429
 
385
430
  ---
386
431
 
387
- ### 语音能力配置(STT / TTS)
432
+ ### Webhook 传输模式
433
+
434
+ 默认情况下,插件通过 **WebSocket** 连接 QQ 平台(出站连接,无需公网 IP)。你也可以切换为 **Webhook** 模式,由 QQ 平台主动 POST 事件到你的 HTTP 端点。
435
+
436
+ | | WebSocket(默认) | Webhook |
437
+ |---|---|---|
438
+ | 连接方式 | 插件主动连接 QQ 网关 | QQ 平台 POST 到你的服务器 |
439
+ | 公网 IP | 不需要 | 需要 |
440
+ | 适用场景 | 开发调试、单实例部署 | 生产环境、水平扩展、Serverless |
441
+ | 会话恢复 | 支持 RESUME | 无状态,无需恢复 |
442
+ | 签名验证 | 平台内置 | 插件自动 Ed25519 验签 |
443
+
444
+ #### 配置方式
445
+
446
+ ```json
447
+ {
448
+ "channels": {
449
+ "qqbot": {
450
+ "appId": "111111111",
451
+ "clientSecret": "your-secret",
452
+ "transport": "webhook",
453
+ "webhook": {
454
+ "path": "/qqbot/webhook"
455
+ }
456
+ }
457
+ }
458
+ }
459
+ ```
460
+
461
+ | 字段 | 默认值 | 说明 |
462
+ |------|--------|------|
463
+ | `transport` | `"websocket"` | `"websocket"` 或 `"webhook"` |
464
+ | `webhook.path` | `"/qqbot/webhook"` | 接收回调的 HTTP 路径 |
465
+
466
+ #### 平台配置步骤
467
+
468
+ 1. 登录 [QQ 开放平台](https://q.qq.com/) → 开发设置 → 消息接收方式
469
+ 2. 选择 **HTTP 回调**
470
+ 3. 填写回调 URL:`https://your-domain.com/qqbot/webhook`
471
+ 4. 平台发送 `op:13` 验证请求,插件自动处理签名验证
472
+ 5. 验证通过后,所有事件将以 POST 方式推送到该地址
473
+
474
+ ---
475
+
476
+ ### 群聊配置
477
+
478
+ 插件提供灵活的群聊管控能力,支持按群定制触发规则、工具权限和 AI 行为策略。
479
+
480
+ #### @提及触发模式(requireMention)
481
+
482
+ 默认情况下,群聊中**必须 @机器人**才会触发 AI 回复。你可以通过配置让 AI 自主判断是否需要发言:
483
+
484
+ | 模式 | 配置值 | 行为 |
485
+ |------|--------|------|
486
+ | **仅 @时回复** | `true`(默认) | 群消息中只有 @了机器人才会触发回复 |
487
+ | **自主发言** | `false` | AI 自主判断每条消息是否需要回复,无需 @ |
488
+
489
+ **优先级链**(从高到低):
490
+
491
+ ```
492
+ 具体群 groups.{groupOpenid}.requireMention
493
+ > 通配符 groups."*".requireMention
494
+ > 账户级 defaultRequireMention
495
+ > 默认值 true
496
+ ```
497
+
498
+ **配置示例:**
499
+
500
+ ```json
501
+ {
502
+ "channels": {
503
+ "qqbot": {
504
+ // 账户级:所有群的默认行为
505
+ "defaultRequireMention": false,
506
+
507
+ "accounts": {
508
+ "default": {
509
+ "groups": {
510
+ "*": {
511
+ // 通配符:所有群的兜底规则
512
+ "requireMention": false
513
+ },
514
+ "GROUP_OPENID": {
515
+ // 单群覆盖:这个群仍然需要 @
516
+ "requireMention": true
517
+ }
518
+ }
519
+ }
520
+ }
521
+ }
522
+ }
523
+ }
524
+ ```
525
+
526
+ > **使用场景举例:**
527
+ >
528
+ > - 工作群设为 `requireMention: true` — 避免 AI 对每条闲聊都插嘴
529
+ > - 专属 AI 陪伴群设为 `requireMention: false` — 像真人一样自然参与对话
530
+ > - 通过 `/bot-group-allways on|off` 指令可在运行时动态切换账户级默认值
531
+
532
+ #### 其他群配置项
533
+
534
+ 除 `requireMention` 外,每个群还支持以下配置:
535
+
536
+ | 字段 | 类型 | 默认值 | 说明 |
537
+ |------|------|--------|------|
538
+ | `ignoreOtherMentions` | `boolean` | `false` | 是否忽略 @了其他人但没 @机器人的消息。开启后这类消息直接丢弃,不记录历史、不触发 AI |
539
+ | `toolPolicy` | `"full" \| "restricted" \| "none"` | `"restricted"` | 群聊中 AI 可使用的工具范围。`full`=全部可用;`restricted`=限制敏感工具(如命令执行、文件操作);`none`=禁止所有工具调用 |
540
+ | `prompt` | `string` | 内置默认提示词 | 该群专属的系统提示词,会追加到全局 systemPrompt 之后 |
541
+ | `historyLimit` | `number` | `50` | 群历史消息缓存条数 |
542
+
543
+ **完整群配置示例:**
544
+
545
+ ```json
546
+ {
547
+ "channels": {
548
+ "qqbot": {
549
+ "defaultRequireMention": false,
550
+ "accounts": {
551
+ "default": {
552
+ "groups": {
553
+ "*": {
554
+ "requireMention": true,
555
+ "toolPolicy": "restricted",
556
+ "ignoreOtherMentions": true
557
+ },
558
+ "WORK_GROUP_OPENID": {
559
+ "requireMention": true,
560
+ "toolPolicy": "none",
561
+ "prompt": "你是工作助手,只回答与工作相关的问题"
562
+ },
563
+ "FRIEND_GROUP_OPENID": {
564
+ "requireMention": false,
565
+ "toolPolicy": "full",
566
+ "prompt": "你是群里的朋友,轻松随意地聊天"
567
+ }
568
+ }
569
+ }
570
+ }
571
+ }
572
+ }
573
+ }
574
+ ```
575
+
576
+ #### 群访问控制(groupPolicy)
577
+
578
+ 通过 `groupPolicy` 控制哪些群允许机器人加入并接收消息:
579
+
580
+ | 策略 | 说明 |
581
+ |------|------|
582
+ | `"open"`(默认) | 所有群均可使用 |
583
+ | `"allowlist"` | 仅 `groupAllowFrom` 白名单中的群可使用 |
584
+ | `"disabled"` | 禁止所有群聊 |
585
+
586
+ ```json
587
+ {
588
+ "channels": {
589
+ "qqbot": {
590
+ "groupPolicy": "allowlist",
591
+ "groupAllowFrom": ["ALLOWED_GROUP_OPENID_1", "ALLOWED_GROUP_OPENID_2"]
592
+ }
593
+ }
594
+ }
595
+ ```
596
+
597
+ > 也可通过 [**`/bot-group-allways`** 指令](#bot-group-allways--群消息响应模式切换) 在运行时动态切换账户级默认值,无需重启。
598
+
599
+ ---
388
600
 
389
601
  #### STT(语音转文字)— 自动转录用户发来的语音消息
390
602
 
package/dist/index.d.ts CHANGED
@@ -15,3 +15,4 @@ export * from "./src/api.js";
15
15
  export * from "./src/config.js";
16
16
  export * from "./src/gateway.js";
17
17
  export * from "./src/outbound.js";
18
+ export * from "./src/transport/index.js";
package/dist/index.js CHANGED
@@ -24,3 +24,4 @@ export * from "./src/api.js";
24
24
  export * from "./src/config.js";
25
25
  export * from "./src/gateway.js";
26
26
  export * from "./src/outbound.js";
27
+ export * from "./src/transport/index.js";
package/dist/src/api.d.ts CHANGED
@@ -27,6 +27,8 @@ export declare class ApiError extends Error {
27
27
  /** 回包中的原始 message 字段(用于向用户展示兜底文案) */
28
28
  bizMessage?: string | undefined);
29
29
  }
30
+ export declare const API_BASE: string;
31
+ export declare const TOKEN_URL: string;
30
32
  /** 由 setQQBotRuntime 调用,将 api.runtime.version 注入到 User-Agent */
31
33
  export declare function setOpenClawVersion(version: string): void;
32
34
  export declare function getPluginUserAgent(): string;
@@ -132,6 +134,10 @@ export declare function sendDmMessage(accessToken: string, guildId: string, cont
132
134
  timestamp: string;
133
135
  }>;
134
136
  export declare function sendGroupMessage(accessToken: string, groupOpenid: string, content: string, msgId?: string, messageReference?: string): Promise<MessageResponse>;
137
+ /** 发送带 Inline Keyboard 的 C2C 消息(回调型按钮,触发 INTERACTION_CREATE) */
138
+ export declare function sendC2CMessageWithInlineKeyboard(accessToken: string, openid: string, content: string, inlineKeyboard: import("./types.js").InlineKeyboard, msgId?: string): Promise<MessageResponse>;
139
+ /** 发送带 Inline Keyboard 的 Group 消息(回调型按钮,触发 INTERACTION_CREATE) */
140
+ export declare function sendGroupMessageWithInlineKeyboard(accessToken: string, groupOpenid: string, content: string, inlineKeyboard: import("./types.js").InlineKeyboard, msgId?: string): Promise<MessageResponse>;
135
141
  export declare function sendProactiveC2CMessage(accessToken: string, openid: string, content: string): Promise<MessageResponse>;
136
142
  export declare function sendProactiveGroupMessage(accessToken: string, groupOpenid: string, content: string): Promise<{
137
143
  id: string;