@zaofan/dsh-qqbot 1.9.2 → 1.10.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 +646 -554
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -1
- package/dist/config.js.map +1 -1
- package/dist/features/ext-capabilities.d.ts +9 -0
- package/dist/features/ext-capabilities.d.ts.map +1 -1
- package/dist/features/ext-capabilities.js +2 -0
- package/dist/features/ext-capabilities.js.map +1 -1
- package/dist/features/ext-tool-interaction.d.ts.map +1 -1
- package/dist/features/ext-tool-interaction.js +37 -5
- package/dist/features/ext-tool-interaction.js.map +1 -1
- package/dist/features/extension-store.d.ts.map +1 -1
- package/dist/features/extension-store.js +8 -0
- package/dist/features/extension-store.js.map +1 -1
- package/dist/gateway/middleware-setup.d.ts.map +1 -1
- package/dist/gateway/middleware-setup.js +6 -0
- package/dist/gateway/middleware-setup.js.map +1 -1
- package/docs/extension-contract.md +187 -0
- package/examples/ext-commands//345/255/220/344/274/232/350/257/235.mjs +598 -0
- package/examples/ext-hooks/session-watch-hook.mjs +53 -119
- package/examples/ext-tools/lib/session_watch_lib.mjs +767 -350
- package/examples/ext-tools/qq_send.mjs +201 -138
- package/examples/ext-tools/session_children.mjs +99 -0
- package/examples/ext-tools/session_create.mjs +219 -201
- package/examples/ext-tools/session_watch.mjs +139 -93
- package/examples/ext-tools/sessions_list.mjs +180 -180
- package/package.json +142 -141
package/README.md
CHANGED
|
@@ -1,554 +1,646 @@
|
|
|
1
|
-
# @zaofan/dsh-qqbot
|
|
2
|
-
|
|
3
|
-
[](./LICENSE) -blue)
|
|
4
|
-
|
|
5
|
-
基于 [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) (dsh) 的 QQ Bot IM 插件**增强 fork**:将 QQ 消息平台作为 dsh agent 的前端协议驱动,并加入表情包图库、富媒体收发、定时任务、多实例人格、好感度系统、可视化设置面板等能力。
|
|
6
|
-
|
|
7
|
-
📦 仓库: [zaofan-make/dsh-qqbot](https://github.com/zaofan-make/dsh-qqbot)(fork 自 [tencent-connect/dsh-qqbot](https://github.com/tencent-connect/dsh-qqbot);改动都在这一侧,升级/重装上游会被冲掉)
|
|
8
|
-
|
|
9
|
-
> ⭐ **用得顺手的话,麻烦点一下右上角的 Star** —— 它是这个项目"有人在用"的唯一可见信号,也是继续更新的动力。
|
|
10
|
-
|
|
11
|
-
中文 | [English](./README_EN.md) | 📖 **[用户手册](./docs/USER-GUIDE.md)**(配置项 / 内置命令 / 自定义扩展 / 群管理 / 智能回复 / 架构…)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
>
|
|
198
|
-
>
|
|
199
|
-
>
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
>
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
###
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
>
|
|
288
|
-
>
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
dsh
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
1
|
+
# @zaofan/dsh-qqbot
|
|
2
|
+
|
|
3
|
+
[](./LICENSE) -blue)
|
|
4
|
+
|
|
5
|
+
基于 [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) (dsh) 的 QQ Bot IM 插件**增强 fork**:将 QQ 消息平台作为 dsh agent 的前端协议驱动,并加入表情包图库、富媒体收发、定时任务、多实例人格、好感度系统、可视化设置面板等能力。
|
|
6
|
+
|
|
7
|
+
📦 仓库: [zaofan-make/dsh-qqbot](https://github.com/zaofan-make/dsh-qqbot)(fork 自 [tencent-connect/dsh-qqbot](https://github.com/tencent-connect/dsh-qqbot);改动都在这一侧,升级/重装上游会被冲掉)
|
|
8
|
+
|
|
9
|
+
> ⭐ **用得顺手的话,麻烦点一下右上角的 Star** —— 它是这个项目"有人在用"的唯一可见信号,也是继续更新的动力。
|
|
10
|
+
|
|
11
|
+
中文 | [English](./README_EN.md) | 📖 **[用户手册](./docs/USER-GUIDE.md)**(配置项 / 内置命令 / 自定义扩展 / 群管理 / 智能回复 / 架构…)
|
|
12
|
+
## 🐋 她能帮你……
|
|
13
|
+
|
|
14
|
+
**一句话**:把 dsh 的 QQ 机器人养成"活鱼"——会存表情包、会挑图回你、到点自己开口、记得住谁跟它亲疏远近,一台电脑还能同时养好几条性格不同的鲸鱼。
|
|
15
|
+
|
|
16
|
+
**🤳 群里发的图,她偷偷全存进小图库**
|
|
17
|
+
自动去重、分「待整理/收藏/回收站」;你说一句"发个开心点的图",她自己搜库、自己挑、自己发,还会挑场合出手(冷场不发、刷屏限量、同图不连发)。
|
|
18
|
+
|
|
19
|
+
**⏰ 到点她自己会开口**
|
|
20
|
+
"每天早 9 点去群里说早安""30 秒后提醒我喝水"——她说到做到,准点冒泡。
|
|
21
|
+
|
|
22
|
+
**🧑🤝🧑 一个电脑,N 条鲸鱼同时在线**
|
|
23
|
+
每条号独立 AppID、独立人格、独立图库/定时/闸门,互不串号;Web 页「扫码绑定」手机一扫就上岗。
|
|
24
|
+
|
|
25
|
+
**💗 她记得住谁亲谁疏**(v1.5.1)
|
|
26
|
+
两个维度分开算:**熟识度**(她把你记得多牢——来过几天、说过多少、被点名、接话,慢变量)与**好感度**(她对你什么态度——随每次互动可升可降)。面板里一行一个人,还能**一键导出 Excel** 拿去分享。
|
|
27
|
+
- 判定用一个跑在本机的小模型读她的「思考(内心)」与「正文(说出口的话)」:**心里不肯但话仍照顾 = 让步**、**心里亲近而嘴上冷淡 = 不算数**(扣不扣看内心,不看表面)
|
|
28
|
+
- 好感度只影响"她愿不愿意自己开口"的松紧:**负好感也只是少主动,绝不冷落、阴阳、攻击**
|
|
29
|
+
- 群消息聚合时按「价值 × 好感」**加权平均**综合判断,不会被一句话钓走
|
|
30
|
+
|
|
31
|
+
**💬 悬浮球 dock:她的随身控制台**
|
|
32
|
+
设置面板右下角的小球,点开就是一整个操作台:**💬 聊天**(像 QQ 一样回放群/私聊记录,气泡+头像,图能放大、本地视频能播、SILK 语音转 mp3 直接听、文件出下载卡,还能在聊天框里直接发文字/插图/发文件——长文本自动拆条连发不被吞);**📥 入群审批**、**🔨 锤子**(下面分 **🔇 禁言** 和 **👢 踢人** 两页;踢人用你自己的 QQ 号管群,扫码一次之后长期免扫,登录态与 AI 共享);**⚙️ 出站**(适配主动:刚收到真人消息时前几条带引用回你、连发自动转独立消息,定时/后台推送不打扰)。
|
|
33
|
+
|
|
34
|
+
**🛡️ 群主/群管好帮手**
|
|
35
|
+
入群审批 + 禁言 + 查成员,全走官方接口,出错给"人话"(不是管理员/不能禁群主……都告诉你为什么)。
|
|
36
|
+
|
|
37
|
+
**👢 踢人(v1.6.3)**
|
|
38
|
+
QQ 官方**没有开放踢人接口**,所以这一块走"你自己的 QQ 号 + 群官网":面板 **🔨 锤子 → 👢 踢人** 里刷新二维码、手机扫一次就登(之后长期免扫);登录态和 AI 共用 —— 你也可以直接在 QQ 里跟她说"把群里那个 X 踢了"。
|
|
39
|
+
|
|
40
|
+
**🗂️ 归档了也会自己回家**
|
|
41
|
+
不小心把她的会话点了「归档」藏进侧边栏深处?不用满世界找——那个会话**下次在 QQ 里被消息触发时**,会自己从归档里摘出来回到侧边栏(你主动归档的其它会话不受影响)。
|
|
42
|
+
|
|
43
|
+
**🔝 QQ 一有动静,她的会话自己爬到最上面**(v1.6.8)
|
|
44
|
+
侧边栏里正在跟你聊的那个会话,不该被别的压着 —— QQ 里一有消息、她**真的回了话**,对应会话就会自动插到「**还热着**」的那批之后(10 分钟内聊过的算热,**置顶的永不动**),冷掉的会话自然被它越过。全程事件驱动、不轮询;宿主没起来、或聊天页没开着时天然不排序。
|
|
45
|
+
|
|
46
|
+

|
|
47
|
+
|
|
48
|
+
**🖥️ 不碰配置文件,设置面板点点点**
|
|
49
|
+
怎么回、能发什么图、什么时候开口、什么人格——面板上改完保存即生效(只有增删账号才要重启)。还有 ✏️ 预设人格编辑器,直接在网页里改她的"性格文件"。
|
|
50
|
+
|
|
51
|
+
**📦 干净又利落**
|
|
52
|
+
发图/撤消息用纯文本就能驱动(回复里写 `[MEDIA:image|路径]` / `[RECALL]`);仓库不含任何机器人凭据与隐私。
|
|
53
|
+
|
|
54
|
+
**📱 不用开电脑 —— 手机也能 7×24 挂着**
|
|
55
|
+
配合社区的 [dsh-mobile-apk](https://github.com/kelai141/dsh-mobile-apk)(**dsh 安卓壳 APK**:WebView UI + 内嵌 Termux 运行时快照,解压即跑),把 dsh 和这只鲸鱼一起装进手机,就是一台**随身在线**的 QQ 机器人 —— 不用为了挂机常开一台电脑。(安卓上通常没有 ONNX 运行时,记得在设置里勾上「**程序兜底(不依赖小模型)**」,见下方说明。)
|
|
56
|
+
|
|
57
|
+
### 📸 效果展示
|
|
58
|
+
|
|
59
|
+
图①:dsh 运行后台——思考过程、工具调用、Token 用量一目了然(配合「回复闸门 reply_gate」可让机器人自主判断该开口还是静默吃瓜);
|
|
60
|
+
图②:QQ 群里的抓鬼游戏互动——该回就回、该藏就藏,角色扮演全自动;
|
|
61
|
+
图③:斗图实战——机器人用自己收藏的表情包接招回击,图、文分开两条连发。
|
|
62
|
+
|
|
63
|
+

|
|
64
|
+
|
|
65
|
+

|
|
66
|
+
|
|
67
|
+

|
|
68
|
+
|
|
69
|
+
图④:群管理·入群审批全流程——【群管·入群申请】事件注入 + 【审批轮询】双链路触发,AI 核对 openid 台账后自动放行;
|
|
70
|
+
图⑤:QQ 群内放行成功效果——小号申请入群被自动审批通过。
|
|
71
|
+
|
|
72
|
+

|
|
73
|
+
|
|
74
|
+

|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 🔌 用户扩展:想自己加功能,不用改插件源码
|
|
82
|
+
|
|
83
|
+
> **这是给"想自己加东西"的用户准备的接口** —— 往 `{数据根}/.qqbot-extensions/` 里丢一个 `.mjs` 就是一个扩展。
|
|
84
|
+
> 插件自带的能力、示例、文档**全都白送**,你只管写业务逻辑。
|
|
85
|
+
>
|
|
86
|
+
> **先把边界说清楚**:她现有的功能 —— **表情包图库、到点开口、好感度系统、群管理(禁言/踢人)、
|
|
87
|
+
> 悬浮球面板、智能回复闸门……这些是插件内置的**(写在插件源码里,随插件升级一起更新)。
|
|
88
|
+
> **扩展**是另一回事:你的 `.mjs` 放在自己的数据目录里,**不改插件源码、升级插件也不会被覆盖**。
|
|
89
|
+
>
|
|
90
|
+
> 两者的关系是:**能力一样,位置不同** —— 扩展拿到的那套能力包(发消息 / 发图 / 进她上下文 /
|
|
91
|
+
> 调官方 API / 持久化 / 身份…)就是插件内部模块在用的同一套封装,所以你写的东西不是"外挂",
|
|
92
|
+
> 只是**长在同一条链上的另一个模块**。
|
|
93
|
+
|
|
94
|
+
**🧩 五套扩展点,挑一个放进去就行**
|
|
95
|
+
|
|
96
|
+
| 你想做的事 | 放哪个目录 | 什么时候跑 |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| 让 AI 主动调用某个工具 | `tools/` | LLM 调它的时候 |
|
|
99
|
+
| 加一条 `/我的命令` | `commands/` | 用户敲这条命令 |
|
|
100
|
+
| 卡片按钮点了要做事 | `botplay/` | 有人点按钮 |
|
|
101
|
+
| 启动时恢复任务 / 起定时器 / 预取 | `hooks/` | 插件启动时跑一次 |
|
|
102
|
+
| **管每一条消息的命运** | `inbound/` | **每条消息都过一遍** |
|
|
103
|
+
|
|
104
|
+
**🧰 一套能力包,五套通用**(不用为每套各记一套 API)
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
await env.text('hi') / env.markdown('# 标题') / env.markdownCard(md, keyboard)
|
|
108
|
+
await env.image(src) / voice / video / file // src 可传 URL 或本地路径
|
|
109
|
+
env.at(openid) // 群里 @ 人
|
|
110
|
+
await env.api('/v2/users/@me') // ★ 官方 API:自带 token 与缓存,不用管 appId/secret
|
|
111
|
+
env.store.load() / env.store.save(obj) // ★ 持久化:升级插件不丢
|
|
112
|
+
await env.appendSilent('...') // ★ 进她上下文、不唤醒
|
|
113
|
+
await env.appendWake('...') // ★ 进上下文并唤醒一轮
|
|
114
|
+
env.user / env.owners / env.peer · env.log() · env.kernel(全权限遥控器)· await env.restart()
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**🚦 入站扩展独有:一条消息的"处置权"**
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
消灭 annihilate(不进群历史/不进上下文/不占冷却)
|
|
121
|
+
改写 rewrite(早挂点连群历史一起改)
|
|
122
|
+
强制入站 forceWake(跳过 @门控/价值评分/群冷却)
|
|
123
|
+
覆盖 @判定 decide · 静默进上下文 silentInto · 用户维禁言 muteUser 系列
|
|
124
|
+
只读视图 message.{text,sender,scope,groupId,isOwner,mentions,quoted,platform}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**🛡️ 四条保命件 —— 你的脚本出问题,也搞不坏群**
|
|
128
|
+
|
|
129
|
+
主人白名单最高优先(不可被静默/封) · 强唤醒优先于静默 · 熔断(扩展失控自动停手) ·
|
|
130
|
+
审计 + 可撤销(每次动作一行,带轮转) · **单个扩展抛错只告警并放行,永远不会吞掉消息**
|
|
131
|
+
|
|
132
|
+
**🎬 还有**
|
|
133
|
+
|
|
134
|
+
- **示例自动铺**:插件启动时把自带示例**只补不覆盖**地铺进你的扩展目录 —— 装上就有一份能跑的样板
|
|
135
|
+
- **改完即生效**:`/tools-reload` 一下就行(扩展命令需重启)
|
|
136
|
+
- 📘 **写扩展前先读**:[`docs/extension-contract.md`](./docs/extension-contract.md) —— 五套扩展点、能力包全表、
|
|
137
|
+
入站操控、安全红线、常见坑,一份写全
|
|
138
|
+
|
|
139
|
+
### 🎁 白送的扩展示例:装上就有能跑、能抄的样板
|
|
140
|
+
|
|
141
|
+
插件启动时会把这些示例**只补不覆盖**地铺进你的扩展目录 —— 不用自己从零写。
|
|
142
|
+
|
|
143
|
+
**让她多会几样本事(AI 能自己调用的工具)**
|
|
144
|
+
|
|
145
|
+
- **会自己联网搜**:一句话就能搜索并把结果整理回来,不用你接搜索接口
|
|
146
|
+
- **会替你给别人发消息**:指个群名或人名她就发;**认不准只回候选、绝不瞎发**
|
|
147
|
+
- **会在群里发起投票**:选项、票数、到点结束结算,一张卡搞定
|
|
148
|
+
- **会跨会话遥控**:列出你所有工作区与会话、给某个会话递话、临时开一个新会话(能指定工作区与人设、派初始任务)、
|
|
149
|
+
盯住子会话**把结果回灌过来并转进 QQ**
|
|
150
|
+
|
|
151
|
+
**让她在卡片上"有状态"**
|
|
152
|
+
|
|
153
|
+
- **签到统计**:谁签过、签了几次、只有主人能看、结束自动公布名单 —— 按钮点下去真的记账
|
|
154
|
+
|
|
155
|
+
**让她开机就干活(不用任何人触发)**
|
|
156
|
+
|
|
157
|
+
- **启动就跑一次**:打日志、计数落盘(跨重启累加);
|
|
158
|
+
- **注册监听并自己收尾**:演示怎么挂监听、怎么在卸载时清理干净
|
|
159
|
+
|
|
160
|
+
**让她管"每条消息的命运"**
|
|
161
|
+
|
|
162
|
+
- **引用子会话不叫醒她**:群里引用一条"子会话转发"的消息,不会被当成在叫她;
|
|
163
|
+
- **一个"辅导员"全套样板**:删广告、刷屏禁言、把手机号之类的敏感内容改掉、有人喊救命时**优先叫醒她**
|
|
164
|
+
—— **默认只观察不动手**,先看日志确认规则合不合意,再放开
|
|
165
|
+
|
|
166
|
+
> 示例是给人**看和抄**的:会真动手的那个(辅导员)**不会自动铺**,要自己拷过去 ——
|
|
167
|
+
> 示例不该在你没读过它之前就自己跑起来。
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 🆚 官方 Bot 方案 vs onbot / NapCat 等第三方协议端
|
|
172
|
+
|
|
173
|
+
本插件走的是**腾讯官方 QQ 机器人开放平台**(AppID + AppSecret + 官方 SDK),
|
|
174
|
+
**不是**"模拟 QQ 客户端协议"那条路。两者差别不小,先把话说清楚:
|
|
175
|
+
|
|
176
|
+
| | **本插件(官方 Bot API)** | 第三方协议端(onbot / NapCat / Lagrange…) |
|
|
177
|
+
|---|---|---|
|
|
178
|
+
| **登录方式** | 填 **AppID / AppSecret** 即可,**不扫码、不登录你的真人 QQ 号** | 扫码登录**你的个人 QQ 号**,常掉线、要保活 |
|
|
179
|
+
| **账号安全** | ✅ **完全不碰你的个人号**,无封号风险 | ⚠️ **有封号风险**:协议模拟违反 QQ 用户协议,腾讯明确禁止 |
|
|
180
|
+
| **稳定性** | ✅ 官方接口,腾讯自己在维护;变更会提前公告 | ⚠️ 协议一变就挂,得等签名服务(qsign 之类)跟进 |
|
|
181
|
+
| **资源占用** | ✅ **极低**:纯 HTTP + WebSocket,无浏览器、无协议端常驻 | ⚠️ 高:要挂 QQ 客户端 / 协议端,内存几百 MB 起 |
|
|
182
|
+
| **低配 / 手机部署** | ✅ **能跑**:安卓 Termux、树莓派、1 核 1G 的小机器都行(见下方「📱 装到手机上」) | ⚠️ 难:协议端对架构/内存有要求,安卓上尤其折腾 |
|
|
183
|
+
| **隐私** | ✅ 只与腾讯官方通信,没有中间人 | ⚠️ 要经过第三方协议实现 |
|
|
184
|
+
| **功能范围** | ⚠️ **受官方开放范围限制**(例:**踢人接口官方没开放**) | ✅ 全功能 |
|
|
185
|
+
|
|
186
|
+
**关于"功能受限",本插件的态度**:官方没开放的,能补就补、不能补就明说 ——
|
|
187
|
+
例如**踢人**:官方接口至今未开放,插件用 **🔨 锤子** 面板让你**用自己的号**走群官网接口把这块补上
|
|
188
|
+
(扫码一次、之后长期免扫,登录态还会和 AI 共享,详见下文)。
|
|
189
|
+
|
|
190
|
+
> **一句话**:想要**安全、省心、还能塞进手机或小机器**,就选官方 Bot 方案;
|
|
191
|
+
> 只有当你非要第三方协议端的"全家桶"、并且愿意承担封号风险时,才另说。
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## 安装
|
|
196
|
+
|
|
197
|
+
> ## ⚠️ 必须装到 `web` profile
|
|
198
|
+
>
|
|
199
|
+
> 本插件的**前端设置面板**(dock 球 + 「设置 → QQ 机器人」整页)只在 **`web` profile** 里生效。
|
|
200
|
+
> 装到别的 profile 会得到一个 **没有设置面板的裸环境** —— dock 球和设置页都不会出现,
|
|
201
|
+
> 表现为"插件装了但看不到任何界面"。
|
|
202
|
+
>
|
|
203
|
+
> **正常使用 `dsh web` 的用户不用关心**(`dsh web` 默认就是 `web` profile,插件页/插件市场装机也落在它上面)。
|
|
204
|
+
> 只有手动指定过 `--profile <其它名字>` 的场景才需要注意。
|
|
205
|
+
> 也不要 `add @tencent-connect/dsh-qqbot`——那会装上游官方版(无本 fork 增强功能)。
|
|
206
|
+
>
|
|
207
|
+
> ✅ **单包自含,装一个就全有**:QQ 机器人 + Web 可视化设置面板(host 桥 + 设置页 UI)都打包在
|
|
208
|
+
> 这一个包内——装完它,dsh Web「设置」里就会出现「QQ 机器人 (im-qqbot)」面板(多账号时每个实例各一页),
|
|
209
|
+
> **无需再单独安装 dsh-qqbot-settings**。
|
|
210
|
+
|
|
211
|
+
### 方式一(发布到 npm 后):一条命令
|
|
212
|
+
|
|
213
|
+
```powershell
|
|
214
|
+
npx @deepseek-ai/dsh plugin --profile web add @zaofan/dsh-qqbot
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
> 尚未发布到 npm 前,请用下面的方式二。
|
|
218
|
+
|
|
219
|
+
> ⚠️ **从 GitHub 直装(`github:zaofan-make/dsh-qqbot`)需要编译产物 `dist/`,而仓库不提交 `dist`。**
|
|
220
|
+
> 包已声明 `prepare` 脚本,pnpm 安装时会自动编译;
|
|
221
|
+
> 若你的包管理器没自动跑(或报 `failed to import` / 找不到 `dist/index.js`),
|
|
222
|
+
> 手动在插件目录执行一次 `npm run build` 即可。**最省事的做法是用 npm 上的发布版**(`@zaofan/dsh-qqbot`)。
|
|
223
|
+
|
|
224
|
+
### 方式二:源码分发(当前推荐)
|
|
225
|
+
|
|
226
|
+
**Windows(一键脚本)**:
|
|
227
|
+
|
|
228
|
+
```powershell
|
|
229
|
+
git clone https://github.com/zaofan-make/dsh-qqbot.git
|
|
230
|
+
cd dsh-qqbot
|
|
231
|
+
.\install.ps1 # 自动 install/build → pack → add tarball → 输出重启指引
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
> 若系统禁止运行脚本,改用:`powershell -ExecutionPolicy Bypass -File .\install.ps1`
|
|
235
|
+
|
|
236
|
+
**macOS / Linux(手动)**:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
git clone https://github.com/zaofan-make/dsh-qqbot.git
|
|
240
|
+
cd dsh-qqbot
|
|
241
|
+
npm install && npm run build
|
|
242
|
+
pnpm pack --pack-destination /tmp
|
|
243
|
+
npx @deepseek-ai/dsh plugin --profile web add /tmp/zaofan-dsh-qqbot-0.4.0.tgz
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
> 💡 为什么打 tarball、而不是 `add` 源码目录?实测教训:
|
|
247
|
+
> ① 目录路径含空格时 Windows 会把参数在空格处拆碎(pnpm 报 `- isn't supported`);
|
|
248
|
+
> ② `add` 目录 = pnpm link(junction),插件无法按"代码位置"反推 profile → 扫码凭据落不了盘,只能走环境变量。
|
|
249
|
+
|
|
250
|
+
### 构建与部署(源码)
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
npm install # 安装依赖(peer 依赖由 dsh 宿主解析)
|
|
254
|
+
npm run build # 或: node node_modules/typescript/lib/tsc.js -p tsconfig.json
|
|
255
|
+
npm run check:package # 发布前自检(单包四项家当齐全)
|
|
256
|
+
pnpm pack # 打 tarball(供 dsh plugin add 安装)
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
仓库根的 `install.ps1` 提供 Windows 一键安装(自动 pack 到无空格目录 → add → 重启提示)。
|
|
260
|
+
|
|
261
|
+
### 排障: npm 安装报 ERESOLVE(2026-09-06 移植上游 PR #42)
|
|
262
|
+
|
|
263
|
+
首次 `npm install` 可能报 `ERESOLVE could not resolve`——原因: `@deepseek-ai/dsh-tools`/`dsh-agent` 等 peer 依赖仍在 prerelease(-rc) 版本线,npm 7+ 严格解析拒绝不相交组合。**这是上游版本线问题,不是插件 bug**,两条绕过路:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
npm install --legacy-peer-deps # 仅安装期解析策略, 不改运行行为
|
|
267
|
+
# 或: 装完依赖后手动 build + pack(peer 由 dsh 宿主解析, 不受影响)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
> 跟踪中: 上游 #37 根治后此段可删(版本线收敛后 npm 不再报错)。
|
|
271
|
+
|
|
272
|
+
### 📱 装到手机上(安卓)—— 随身挂机方案
|
|
273
|
+
|
|
274
|
+
[dsh-mobile-apk](https://github.com/kelai141/dsh-mobile-apk) 是社区做的 **dsh 安卓壳 APK**
|
|
275
|
+
(WebView UI + 内嵌 Termux 运行时快照,解压即跑,为 dsh 本地运行设计)。
|
|
276
|
+
把 dsh 装进去之后,再按本文档把本插件装进那个 dsh —— 你就得到一台**不用电脑托管的、7×24 在线的 QQ 机器人**。
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
下载 APK: https://github.com/kelai141/dsh-mobile-apk/releases
|
|
280
|
+
(按手机 CPU 选 arm64 / x86_64)
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
装好之后,插件安装方式与电脑上一致(插件页填包名或 GitHub 地址,见上)。
|
|
284
|
+
|
|
285
|
+
> ⚠️ **安卓上务必打开这两个开关**(否则机器人半天不理人):
|
|
286
|
+
>
|
|
287
|
+
> 1. **设置 → 智能回复 → 勾选「程序兜底(不依赖小模型)」**
|
|
288
|
+
> 手机环境通常拿不到 ONNX 运行时,真实小模型会加载失败;勾上程序兜底后改用
|
|
289
|
+
> **字符 n-gram 字面相似**(零依赖、零 token),智能回复照常工作。
|
|
290
|
+
> 2. **系统设置 → 电池 → 允许后台运行 / 加入省电白名单**
|
|
291
|
+
> 否则系统会在息屏后杀掉 Termux 进程,机器人就离线了。
|
|
292
|
+
|
|
293
|
+
### 首次启动与绑定
|
|
294
|
+
|
|
295
|
+
启动 `dsh web` 后,若未配置凭据会自动进入**扫码引导**:终端输出二维码 → 手机 QQ 扫码绑定 → 凭据自动保存,重启不丢(设置面板里也可随时「扫码绑定」/改账号)。
|
|
296
|
+
|
|
297
|
+

|
|
298
|
+
|
|
299
|
+
> **提示**:建议使用 `0.4.0` 以上版本扫码,支持点击链接在浏览器打开,避免部分终端二维码渲染错位的问题。
|
|
300
|
+
|
|
301
|
+
### 还没有 QQ 机器人?先注册一个(拿 AppID / AppSecret)
|
|
302
|
+
|
|
303
|
+
1. 打开 [QQ 开放平台](https://q.qq.com),用 QQ 号登录;
|
|
304
|
+
2. 进入「机器人」→「创建机器人」,填好名称、头像、简介;
|
|
305
|
+
3. 创建完成后在机器人详情页拿到 **AppID** 与 **AppSecret**;
|
|
306
|
+
4. 在 dsh Web → 设置 →「QQ 机器人」→「账号与预设」里填入并保存
|
|
307
|
+
(或设为环境变量 `QQBOT_APPID` / `QQBOT_SECRET`);
|
|
308
|
+
5. 按需在平台开通**单聊/群聊**消息权限(群聊一般需要提交用途审核)。
|
|
309
|
+
|
|
310
|
+
> 💡 更省事:机器人建好即可,首次启动直接**扫码绑定**,不用手抄凭据。
|
|
311
|
+
|
|
312
|
+
## 常见问题
|
|
313
|
+
|
|
314
|
+
### 升级 dsh 0.1.6 后,恢复会话报 `workflow-worker-thread ... cannot be resolved`?
|
|
315
|
+
|
|
316
|
+
dsh **0.1.6** 把工作流执行器插件**改了名,且不保留别名**:
|
|
317
|
+
|
|
318
|
+
```
|
|
319
|
+
@deepseek-ai/dsh-workflow-worker-thread → @deepseek-ai/dsh-workflow-ptc
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
- **用官方预设的人不受影响** —— 官方预设文件随 dsh 升级一起更新(0.1.6 里已是 `workflow-ptc`)。
|
|
323
|
+
- **从旧版官方预设「复制」出来的自定义预设会挂** —— 副本不会跟着升级走,仍写着旧名,于是报:
|
|
324
|
+
|
|
325
|
+
```
|
|
326
|
+
preset "xxx" failed to mount: row "workflow-worker-thread"
|
|
327
|
+
names a plugin that cannot be resolved: @deepseek-ai/dsh-workflow-worker-thread
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
**修复**:把预设目录 `~/.dsh/.agent-presets/<预设名>/agent.cordis.yml` 里的旧名改成新名(`id` 与 `name` 各一处),或直接跑仓库里的一键脚本:
|
|
331
|
+
|
|
332
|
+
```powershell
|
|
333
|
+
# 先检查(不改任何文件)
|
|
334
|
+
pwsh -File scripts/fix-dsh-016-presets.ps1
|
|
335
|
+
|
|
336
|
+
# 确认后修复(自动备份为 *.bak-dsh016-<时间戳>)
|
|
337
|
+
pwsh -File scripts/fix-dsh-016-presets.ps1 -Apply
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
改完重启 dsh 让预设重新挂载。
|
|
341
|
+
|
|
342
|
+
> 同一批变更里还有几个已改名/移除的包,脚本会一并检测:
|
|
343
|
+
>
|
|
344
|
+
> | 旧名 | 处理 |
|
|
345
|
+
> |---|---|
|
|
346
|
+
> | `@deepseek-ai/dsh-code-runtime` | 改名为 `@deepseek-ai/dsh-ptc-runtime` |
|
|
347
|
+
> | `dsh-code-runtime-worker-thread` | 已移除,需删行 |
|
|
348
|
+
> | `dsh-tool-subagent-report` | 已移除,需删行 |
|
|
349
|
+
> | `dsh-agent-spine-demo` | 已移除,需删行 |
|
|
350
|
+
>
|
|
351
|
+
> ⚠️ 注意:**注释里**提到旧名字不会导致挂载失败(脚本也只检查非注释行)。
|
|
352
|
+
|
|
353
|
+
### 默认模型是哪个?
|
|
354
|
+
|
|
355
|
+
dsh 0.1.6 起默认模型为 `deepseek-official/deepseek-flash`(旧的 `deepseek-v4-flash` 已移出默认模型列表)。插件在「什么都没配」时的兜底也已同步为该值;你在设置里显式指定的 provider/model 优先级更高。
|
|
356
|
+
|
|
357
|
+
### 升级 dsh 0.1.7 后,恢复会话报「预设缺失」/ 机器人不理人?
|
|
358
|
+
|
|
359
|
+
dsh **0.1.7** 把 Agent 预设从「目录里的 yml 文件」换成了「**profile 配置里的声明行**」:
|
|
360
|
+
由 `@deepseek-ai/dsh-agent-preset-registry` + 每个预设一行 `@deepseek-ai/dsh-agent-preset` 组成。
|
|
361
|
+
官方明确:**注册表不扫描目录、不接受 preset 路径、没有任何接口接受 YAML 写回** —— 所以旧目录预设**必须迁移**,否则会话日志里记着的 preset ID 找不到定义,**恢复会话会被拒绝**。
|
|
362
|
+
|
|
363
|
+
**一键迁移**(仓库里 `scripts/migrate-presets-017.ps1`):
|
|
364
|
+
|
|
365
|
+
```powershell
|
|
366
|
+
# ① 先看看会迁移哪些预设(不写任何文件)
|
|
367
|
+
pwsh -File scripts/migrate-presets-017.ps1
|
|
368
|
+
|
|
369
|
+
# ② 生成「原 patch + 迁移片段」的合并版,核对一眼
|
|
370
|
+
pwsh -File scripts/migrate-presets-017.ps1 -Merge -Out "$env:TEMP\cordis.patch.yml.0.1.7-ready"
|
|
371
|
+
|
|
372
|
+
# ③ 升级 dsh 到 ≥0.1.7 之后启用(⚠️ 顺序不可反!0.1.6 读不了新声明会加载失败)
|
|
373
|
+
cd ~/.dsh/profiles/web
|
|
374
|
+
Copy-Item cordis.patch.yml cordis.patch.yml.bak-0.1.6
|
|
375
|
+
Move-Item "$env:TEMP\cordis.patch.yml.0.1.7-ready" cordis.patch.yml -Force
|
|
376
|
+
# 然后重启 dsh
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
> ⚠️ 两个坑(脚本已自动处理):patch 顶层若是空数组 `[]` 要**先删掉**再粘;新增条目必须用 `- insert:`(写成 `- id:` 会报 `entry not found`)。
|
|
380
|
+
> ⚠️ 0.1.7 会把**会话日志升级为 V4(不可回退)**、`settings.yaml` 也只导入一次 —— 升级前记得备份整个 `~/.dsh`。
|
|
381
|
+
|
|
382
|
+
### 升级 dsh 0.1.7 后,某些插件被「禁用 / 跳过」?
|
|
383
|
+
|
|
384
|
+
0.1.7 新增了**插件版本兼容检查**(比对各插件的 `peerDependencies`)。钉死在旧次版本的包会被跳过,或整行被禁用:
|
|
385
|
+
|
|
386
|
+
```
|
|
387
|
+
dsh: disabling profile plugin row "mcp-chrome": Plugin ... is incompatible with dsh 0.1.7-rc.1
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
常见两例:
|
|
391
|
+
|
|
392
|
+
- `@deepseek-ai/dsh-mcp-client@0.0.1-rc.1` → 让所有 `mcp-*` 行失效。**注意官方这个包的 `latest` 标签还停在旧版,`next` 才是新版** → 要显式装 `@deepseek-ai/dsh-mcp-client@0.1.7-rc.1`
|
|
393
|
+
- `@dhicoc/dsh-reverse-skill@1.0.5` → 跳过(作者尚未适配 0.1.7)
|
|
394
|
+
|
|
395
|
+
想强行运行,可用官方提供的**确切版本例外**(`dsh plugin allow-version`,或插件管理页里授予),但官方警告"可能崩溃或数据丢失",自行权衡。
|
|
396
|
+
|
|
397
|
+
## 🤖 自定义事件 + 「让 AI 写」(v1.6.7)
|
|
398
|
+
|
|
399
|
+
普通的互动卡片只能「点按钮 → 回一句固定文本」,能力被编辑器框死。
|
|
400
|
+
这一版让卡片**变成一个真的 JS 模块**(可以叫 AI 帮你写),于是它能做到编辑器做不到的事:
|
|
401
|
+
|
|
402
|
+
- **自己维护状态**:谁点过、点了几次、本轮名单 —— 落盘、升级不丢
|
|
403
|
+
- **自己判权限**:QQ 的按钮权限是"整张卡片一个",但模块里能用 `ctx.user.isOwner` 做到"这个按钮只有主人能点"
|
|
404
|
+
- **自己发消息**:文本 / markdown / 图片,还能 @ 某人
|
|
405
|
+
- **调 AI**:`ctx.appendSilent()` 静默记进上下文;或 `ctx.appendWake()` **把 AI 叫起来**
|
|
406
|
+
- **调官方 API**:模块拿到 `ctx.appId` / `ctx.appSecret`,自己换 token 就能 fetch 任意官方接口
|
|
407
|
+
|
|
408
|
+
### 📸 长什么样
|
|
409
|
+
|
|
410
|
+
**① 面板:事件列表 + 「让 AI 写」+ 自定义事件信息区**
|
|
411
|
+
|
|
412
|
+

|
|
413
|
+
|
|
414
|
+
**② 效果:签到统计 + 结束后唤醒 AI(AI 自己开口总结)**
|
|
415
|
+
|
|
416
|
+

|
|
417
|
+
|
|
418
|
+
**③ 那 AI 到底收到了什么?(这就是 `ctx.appendWake` 的内容)**
|
|
419
|
+
|
|
420
|
+

|
|
421
|
+
|
|
422
|
+
> 事件模块自己决定"什么时候叫醒 AI、告诉它什么",并顺手把"你只要补一句人话、别复述名单"
|
|
423
|
+
> 这种约束一起发过去 —— 所以 AI 的回复才既贴群气氛、又不啰嗦。
|
|
424
|
+
> **这一段不是插件写死的,是卡片模块(AI 写的那个 .mjs)自己组织的。**
|
|
425
|
+
|
|
426
|
+
> 上面第二张就是"第三方框架做不到的事":**卡片点完后 AI 也知道了结果**,
|
|
427
|
+
> 而且它会顺着群里的气氛自己说人话 —— 那段「带头营业(尾巴摇摇)」不是模板文案,是 AI 现场说的。
|
|
428
|
+
|
|
429
|
+
### 怎么用
|
|
430
|
+
|
|
431
|
+
1. 面板 → 📤 群发 → **互动事件** → 底部「🤖 让 AI 写自定义事件」输入框
|
|
432
|
+
2. 用大白话写你要什么,例如:
|
|
433
|
+
> 我想写一个签到人数统计,有两个按钮,按钮1是签到,所有人都能点且每个人只能点一次;
|
|
434
|
+
> 按钮2是结束,只能我点。我点结束后,bot 发送消息到 QQ 上,统计签到人数和所有签到者的名称
|
|
435
|
+
3. 点 **🤖 让 AI 写** —— 面板会把「你的需求 + 官方文档链接 + 契约 + 环境信息」发进当前会话;
|
|
436
|
+
AI 按契约写一个 `.mjs` 放进 `{dataRoot}/.qqbot-extensions/botplay/`,并登记到 `botplay-events.json`
|
|
437
|
+
4. 改完模块后,面板点 **🔄 重载模块** 即生效(**不用重启**)
|
|
438
|
+
5. 想让它回到普通编辑器:把事件 JSON 里的 `file` 字段删掉即可
|
|
439
|
+
|
|
440
|
+
### 契约在哪
|
|
441
|
+
|
|
442
|
+
`docs/botplay-contract.md` —— **纯文本、可直接改**(改完重启宿主生效)。
|
|
443
|
+
它定义了模块导出哪些钩子、`ctx` 有哪些能力(含上面那几条),也是「让 AI 写」时发给 AI 的那份说明。
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## 🧩 扩展工具:自己写 QQ 工具,还能"跨通道"(v1.8.0+)
|
|
448
|
+
|
|
449
|
+
把 `.mjs` 放进 `{dataRoot}/.qqbot-extensions/tools/`,AI 就能调用它(写完发 `/tools-reload` 即生效,无需重启)。
|
|
450
|
+
**默认**:扩展工具**只在 QQ 会话里存在**——别处的会话完全看不到它,所以也不占一点 token。
|
|
451
|
+
|
|
452
|
+
**加一行 `expose: 'all'`**,它就对**所有会话可见**(web 对话、终端…),并在那边**直接操作 QQ**:
|
|
453
|
+
|
|
454
|
+
```js
|
|
455
|
+
export default {
|
|
456
|
+
name: 'qq_send',
|
|
457
|
+
expose: 'all',
|
|
458
|
+
description: '查 QQ 聊天对象 / 向群或私聊发消息',
|
|
459
|
+
inputSchema: { action: { type: 'string' }, target: { type: 'string' }, text: { type: 'string' } },
|
|
460
|
+
run: async (args, env) => {
|
|
461
|
+
const qq = env.qq; // 账号包:appId / 群与私聊清单 / sender / sendText / apiCall…
|
|
462
|
+
return { ok: true, msg: (await qq.sendText('group', args.target, args.text)) ? '已发送 ✓' : '发送失败' };
|
|
463
|
+
},
|
|
464
|
+
};
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
- 注册名会带上**人设 id**(如 `qq_send__whale-girl`),归属一眼可见;
|
|
468
|
+
⚠️ **工具名只能用 `[a-zA-Z0-9_-]`** —— 用 `@` 之类的字符会被 LLM API **整轮拒绝**(会让机器人全面瘫痪)。插件现在会**直接拒绝注册**这类名字,不会再把整条链路带崩。
|
|
469
|
+
- 发送**被动优先、失败转主动**:先拿目标会话最近的 `msgId` 走被动回复(不吃主动配额、也不被 QQ 吞),失败再去掉 `msgId` 重发。冷群没有被动窗口,会直接走主动。
|
|
470
|
+
- **新用户不用自己搬示例**:插件启动时会把自带的 `examples/ext-tools`、`examples/botplay`、`examples/ext-hooks` **只补不覆盖**地铺进你的扩展目录 —— 装上就有能跑的工具(如 `qq_send`)、卡片示例和启动钩子示例。
|
|
471
|
+
|
|
472
|
+
细节见 **[用户手册](./docs/USER-GUIDE.md)** 的「自定义 QQ 工具」一节。
|
|
473
|
+
|
|
474
|
+
## 🪝 启动钩子:没人调用也自己跑(v1.8.9+)
|
|
475
|
+
|
|
476
|
+
前面的扩展都要「有人触发」才动:`commands/` 等用户敲命令、`tools/` 等 LLM 调用、`botplay/` 等人点卡片。
|
|
477
|
+
但有些事**没人触发也得跑** —— 恢复上次没跑完的长期任务、注册监听、起定时器、预取数据。
|
|
478
|
+
把 `.mjs` 放进 `{dataRoot}/.qqbot-extensions/hooks/`,它就会在**插件启动(apply)时自动执行一次**:
|
|
479
|
+
|
|
480
|
+
```js
|
|
481
|
+
// {dataRoot}/.qqbot-extensions/hooks/my-hook.mjs
|
|
482
|
+
export async function run(env) {
|
|
483
|
+
env.logger.info(`插件 v${env.pluginVersion} 起来了;数据根 = ${env.dataRoot}`);
|
|
484
|
+
const timer = setInterval(() => { /* 周期任务 */ }, 60_000);
|
|
485
|
+
timer.unref?.();
|
|
486
|
+
env.registerDispose(() => clearInterval(timer)); // 卸载时收尾
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
export async function dispose(env) { // 可选:卸载 / 宿主退出时调用
|
|
490
|
+
env.logger.info('收尾完成');
|
|
491
|
+
}
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
三种写法都认:`export function run(env)`、`export default { name, run, dispose }`、`export default async (env) => {}`。
|
|
495
|
+
|
|
496
|
+
| `env` 字段 | 说明 |
|
|
497
|
+
|---|---|
|
|
498
|
+
| `ctx` | 插件 cordis Context(`ctx.on()` / `ctx.get()` / `ctx.webServer.register()`…) |
|
|
499
|
+
| `logger` / `dataRoot` / `config` | 日志 / 数据根 / 当前实例配置(只读用途) |
|
|
500
|
+
| `registerDispose(fn)` | 注册清理函数(与导出的 `dispose()` 一样在卸载时调用,**逆序**执行) |
|
|
501
|
+
| `pluginVersion` | 插件版本号(如 `1.8.9`),可按版本分支 |
|
|
502
|
+
| `caps` / `store` | 与 tools / commands **同一套能力包**;`store.load()/save()` 落 `hooks/data/<文件名>.json` |
|
|
503
|
+
|
|
504
|
+
**和 tools / commands 的区别**:钩子**不需要任何人调用**,也不出现在工具列表里(不占 AI 的 token)。
|
|
505
|
+
`hooks/` 根下的 `*.mjs` 逐个执行;**子目录不扫描**(与 `tools/` 的既有约定一致,可安全放私有模块)。
|
|
506
|
+
|
|
507
|
+
**插件侧的硬保证**:
|
|
508
|
+
|
|
509
|
+
- 单个钩子抛错**绝不影响插件启动、也不影响其它钩子**(逐个独立 try/catch,失败只记警告);
|
|
510
|
+
- 单钩子超时 **30s**,超时只告警并放行 —— 异步钩子拖不死启动(注意:超时不会真的杀掉代码,
|
|
511
|
+
长任务请用定时器/后台异步跑,别直接写在 `run()` 里);
|
|
512
|
+
- `hooks/` 目录**不存在或为空完全安静**(不报错、不刷日志);每个钩子的名字与结果
|
|
513
|
+
(成功 / 失败 / 超时)都会写进日志。
|
|
514
|
+
|
|
515
|
+
示例见 [`examples/ext-hooks/`](./examples/ext-hooks/README.md)(`hello-hook.mjs` 最小可跑;
|
|
516
|
+
`session-watch-hook.mjs` 演示"注册监听 + dispose 清理");插件启动时会自动铺一份到你的扩展目录。
|
|
517
|
+
⚠️ 钩子**只在启动时跑一次**(没有热重载),改完要重启插件/宿主才生效。
|
|
518
|
+
|
|
519
|
+
## 🚦 入站中间件:让扩展管"每条消息的命运"(v1.9.0)
|
|
520
|
+
|
|
521
|
+
前面四套扩展都要**有人触发**才跑(敲命令 / LLM 调用 / 点卡片 / 启动)。但有些规则得管**每一条**消息:
|
|
522
|
+
这条广告别进群、这句敏感话换掉、这条必须叫醒她、这条引用的是子会话转发**不算 @ 她**。
|
|
523
|
+
|
|
524
|
+
把 `.mjs` 放进 `{dataRoot}/.qqbot-extensions/inbound/` 就生效:
|
|
525
|
+
|
|
526
|
+
```js
|
|
527
|
+
// {dataRoot}/.qqbot-extensions/inbound/my-rule.mjs
|
|
528
|
+
export async function onInbound(ctx, next) { // 早:记群历史之前
|
|
529
|
+
if (isAd(ctx.text)) {
|
|
530
|
+
ctx.silentInto(); // 内容仍静默进她上下文
|
|
531
|
+
ctx.annihilate({ reason: '广告' }); // 消灭:不进历史/不进上下文/不占冷却
|
|
532
|
+
return; // ★ 不调 next()
|
|
533
|
+
}
|
|
534
|
+
return next();
|
|
535
|
+
}
|
|
536
|
+
export default async function (ctx, next) { // 晚:@门控之后
|
|
537
|
+
if (isChildForwardQuote(ctx.state?.quote?.text)) {
|
|
538
|
+
ctx.decide({ mention: 'ignore', reason: '引用子会话转发' });
|
|
539
|
+
}
|
|
540
|
+
return next();
|
|
541
|
+
}
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
- **两个挂点**:早(引用解析后、**记群历史之前**)/晚(@门控之后,语义与旧契约一致);
|
|
545
|
+
- **四个动作**:`annihilate` 消灭 · `rewrite` 改写(早挂点连历史一起改)· `forceWake` 跳过 @门控/评分/冷却 ·
|
|
546
|
+
`decide` 覆盖 @ 判定;另有 `silentInto` 静默进上下文、`muteUser` 系列用户维禁言、`kv` 自己的持久化;
|
|
547
|
+
- **能力面对面齐平**:入站扩展和另外四套**共用同一套能力包**(`store` / `api()` / `markdown` /
|
|
548
|
+
`appendSilent` / `user` / `kernel` …),入站专属的那组走 `ctx.caps.inbound`;
|
|
549
|
+
- **四条保命件**:主人白名单最高优先(不可被消灭/禁言)、强唤醒优先于静默、熔断(扩展失控自动停手)、
|
|
550
|
+
审计 + 可撤销(每次动作一行,带轮转);
|
|
551
|
+
- 目录**不存在或为空完全安静**;单个扩展抛错只告警并放行 —— 你的脚本坏了**永远不会吞掉消息**。
|
|
552
|
+
|
|
553
|
+
示例见 [`examples/ext-inbound/`](./examples/ext-inbound/README.md)。⚠️ 自动铺到你目录的**只有**
|
|
554
|
+
`no-wake-on-child-quote.mjs`(它只改 @ 判定,不动手);`class-advisor.mjs`(辅导员:删广告/封人/改写/
|
|
555
|
+
求助优先)**不会自动铺**,要自己拷 —— 示例是给人**看和抄**的,不该在你没读过它之前就自己跑起来。
|
|
556
|
+
|
|
557
|
+
> 📘 **写扩展前先读**:[`docs/extension-contract.md`](./docs/extension-contract.md) —— 五套扩展点、
|
|
558
|
+
> 统一能力包、入站操控、安全红线和常见坑,一份写全。
|
|
559
|
+
|
|
560
|
+
## 🔨 锤子面板:禁言 / 踢人(v1.6.3)
|
|
561
|
+
|
|
562
|
+
dock 面板里的 **🔨 锤子**(原来叫「🔇 禁言」),下面分两页:
|
|
563
|
+
|
|
564
|
+
| 子页 | 走哪条路 | 说明 |
|
|
565
|
+
|---|---|---|
|
|
566
|
+
| **🔇 禁言** | 官方 Bot 接口 | 机器人为群管理员即可用,无需任何登录 |
|
|
567
|
+
| **👢 踢人** | **你自己的 QQ 号**(群官网接口) | 官方没开放踢人接口,所以这里要登一次 |
|
|
568
|
+
|
|
569
|
+
### 怎么用(踢人)
|
|
570
|
+
|
|
571
|
+
1. 面板 → **🔨 锤子** → **👢 踢人** → 点 **📱 刷新二维码**
|
|
572
|
+
2. 页面里**直接显示二维码** —— 拿手机 QQ「扫一扫」,**摄像头对着电脑屏幕**扫
|
|
573
|
+
> 腾讯只认摄像头:用相册选图 / 长按识别会提示「本次请求不支持图片识别或长按扫描二维码授权」
|
|
574
|
+
3. 扫完自动切到已登录界面:**选群 + 搜成员(uin 精确 / 昵称模糊)+ 点一下 👢 踢**
|
|
575
|
+
|
|
576
|
+

|
|
577
|
+
|
|
578
|
+
### 免扫码是怎么做到的
|
|
579
|
+
|
|
580
|
+
登录成功后凭据存在 `{dataRoot}/qun-cookie.json`。之后每次需要登录时:
|
|
581
|
+
|
|
582
|
+
```
|
|
583
|
+
静默起一个「无头」浏览器 → 把已存的凭据注入进去(CDP Network.setCookie)
|
|
584
|
+
→ 页面直接就是已登录状态 → 读出凭据 → 关掉浏览器
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
**全程不弹窗口、不用扫码**。只有第一次(或凭据彻底过期)才要扫一次;`skey` 约 1 天后过期,重登走的也是上面这套静默流程。
|
|
588
|
+
|
|
589
|
+
> 💡 实测彩蛋:**本机开着 QQ 客户端**时,登录页会直接显示你的头像,点一下就登 —— 连第一次都不用扫。
|
|
590
|
+
|
|
591
|
+
### 登录态与 AI 共享
|
|
592
|
+
|
|
593
|
+
面板和 AI 读写的是**同一个** `qun-cookie.json`,所以两边天然同步:
|
|
594
|
+
|
|
595
|
+
- 你在面板扫码登录 → 直接跟 AI 说「把群里那个 X 踢了」就能用
|
|
596
|
+
- AI 先登过 → 你打开面板就是已登录
|
|
597
|
+
|
|
598
|
+
AI 侧的工具叫 **`qq_group_admin`**:
|
|
599
|
+
|
|
600
|
+
| action | 作用 |
|
|
601
|
+
|---|---|
|
|
602
|
+
| `status` | 看登录状态 / 继续等扫码 |
|
|
603
|
+
| `login` | 登录(静默优先,需要才给二维码路径) |
|
|
604
|
+
| `groups` | 列出你创建/管理的群 |
|
|
605
|
+
| `members` | 查成员(uin 精确 / 昵称模糊 / 全量) |
|
|
606
|
+
| `kick` | 踢人 —— **必须带 `confirmed=true`**,否则只回一句「请先跟主人核对群和人」 |
|
|
607
|
+
|
|
608
|
+
### 隐私与进程
|
|
609
|
+
|
|
610
|
+
- 浏览器用**独立 profile**(在插件数据目录里),**看不到你日常浏览器的任何东西**
|
|
611
|
+
- **不常驻**:拿到凭据立刻关;等扫码最多留 5 分钟;宿主退出时会一起带走(不留孤儿进程)
|
|
612
|
+
- 凭据只存在你自己的机器上,仓库里不含任何凭据
|
|
613
|
+
|
|
614
|
+
## 🚫 无上下文模式(按会话省 token)
|
|
615
|
+
|
|
616
|
+
让某个 QQ 会话**每轮只记得最近几条对话**,更早的历史自动折叠 —— 群聊省 token 利器。
|
|
617
|
+
|
|
618
|
+
**怎么开**:dock 面板(右下角 🛡)→「⚙ 单会话设置」→ 子标签「🚫 无上下文」→ 勾选 + 填「带 @ 前 N 条」→ 保存。
|
|
619
|
+
|
|
620
|
+
**几点先说清**(细节见手册):
|
|
621
|
+
- **web 记录不删** —— 只多一行「上下文已压缩」折叠标记
|
|
622
|
+
- **N 计的是 dsh 侧的消息条数**,1 条可能含多条 QQ 消息(入站时会聚合)
|
|
623
|
+
- **零额外模型调用**(替身文本写死)
|
|
624
|
+
- **从下一轮起生效**(压缩发生在回合开始)
|
|
625
|
+
|
|
626
|
+
📖 完整说明(含易误解点、全局开关、存储位置)→ **[用户手册](docs/USER-GUIDE.md#无上下文模式按会话省-token)**
|
|
627
|
+
|
|
628
|
+
## ✅ QQ 审批卡片:谁可以点
|
|
629
|
+
|
|
630
|
+
发起审批的卡片**发到发起者所在的会话**(群里就发到群里),但**只有下列人能点按钮**:
|
|
631
|
+
**① 发起者本人 ② 主人白名单**(`groupAdmin.owners`)。
|
|
632
|
+
|
|
633
|
+
> ⚠️ **群聊场景一定要填白名单**:设置 → QQ 机器人 →「允许操作的主人 openid(逗号分隔,可留空=不校验)」。
|
|
634
|
+
> 否则别人发起的审批,主人点了没反应。
|
|
635
|
+
|
|
636
|
+
📖 细节 → **[用户手册](docs/USER-GUIDE.md#qq-审批卡片谁可以点)**
|
|
637
|
+
|
|
638
|
+
---
|
|
639
|
+
|
|
640
|
+
## 支持这个项目
|
|
641
|
+
|
|
642
|
+
如果这个插件帮你省了 token、或者让你家的鲸鱼更活蹦乱跳 —— **给个 ⭐ Star** 就是最实在的支持;有 bug / 想要的功能,欢迎开 [Issue](https://github.com/zaofan-make/dsh-qqbot/issues)。
|
|
643
|
+
|
|
644
|
+
## License
|
|
645
|
+
|
|
646
|
+
[MIT](./LICENSE)
|