@zaofan/dsh-qqbot 1.4.0 → 1.4.5

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 (86) hide show
  1. package/README.md +85 -0
  2. package/README_EN.md +15 -0
  3. package/client/qqbot-settings.js +452 -6
  4. package/dist/channel-tools.d.ts +15 -0
  5. package/dist/channel-tools.d.ts.map +1 -1
  6. package/dist/channel-tools.js +59 -1
  7. package/dist/channel-tools.js.map +1 -1
  8. package/dist/config.d.ts +41 -0
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/config.js +25 -1
  11. package/dist/config.js.map +1 -1
  12. package/dist/features/image-path-cache.d.ts +23 -0
  13. package/dist/features/image-path-cache.d.ts.map +1 -0
  14. package/dist/features/image-path-cache.js +38 -0
  15. package/dist/features/image-path-cache.js.map +1 -0
  16. package/dist/features/image-url-ledger.d.ts +19 -0
  17. package/dist/features/image-url-ledger.d.ts.map +1 -0
  18. package/dist/features/image-url-ledger.js +133 -0
  19. package/dist/features/image-url-ledger.js.map +1 -0
  20. package/dist/features/local-embed.d.ts +43 -0
  21. package/dist/features/local-embed.d.ts.map +1 -0
  22. package/dist/features/local-embed.js +143 -0
  23. package/dist/features/local-embed.js.map +1 -0
  24. package/dist/features/sticker-store.d.ts +48 -2
  25. package/dist/features/sticker-store.d.ts.map +1 -1
  26. package/dist/features/sticker-store.js +156 -1
  27. package/dist/features/sticker-store.js.map +1 -1
  28. package/dist/features/value-sample.d.ts +25 -0
  29. package/dist/features/value-sample.d.ts.map +1 -0
  30. package/dist/features/value-sample.js +122 -0
  31. package/dist/features/value-sample.js.map +1 -0
  32. package/dist/features/value-score.d.ts +36 -0
  33. package/dist/features/value-score.d.ts.map +1 -0
  34. package/dist/features/value-score.js +122 -0
  35. package/dist/features/value-score.js.map +1 -0
  36. package/dist/gateway/bootstrap.d.ts.map +1 -1
  37. package/dist/gateway/bootstrap.js +23 -0
  38. package/dist/gateway/bootstrap.js.map +1 -1
  39. package/dist/gateway/debounce.d.ts.map +1 -1
  40. package/dist/gateway/debounce.js +16 -5
  41. package/dist/gateway/debounce.js.map +1 -1
  42. package/dist/gateway/middleware-setup.d.ts.map +1 -1
  43. package/dist/gateway/middleware-setup.js +12 -1
  44. package/dist/gateway/middleware-setup.js.map +1 -1
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +8 -1
  47. package/dist/index.js.map +1 -1
  48. package/dist/middleware/sticker-capture.d.ts +8 -2
  49. package/dist/middleware/sticker-capture.d.ts.map +1 -1
  50. package/dist/middleware/sticker-capture.js +63 -45
  51. package/dist/middleware/sticker-capture.js.map +1 -1
  52. package/dist/model/model-resolver.js +12 -6
  53. package/dist/model/model-resolver.js.map +1 -1
  54. package/dist/session/session-manager.d.ts.map +1 -1
  55. package/dist/session/session-manager.js +4 -2
  56. package/dist/session/session-manager.js.map +1 -1
  57. package/dist/transport/attachment.d.ts +5 -1
  58. package/dist/transport/attachment.d.ts.map +1 -1
  59. package/dist/transport/attachment.js +16 -5
  60. package/dist/transport/attachment.js.map +1 -1
  61. package/dist/transport/inbound.d.ts.map +1 -1
  62. package/dist/transport/inbound.js +396 -15
  63. package/dist/transport/inbound.js.map +1 -1
  64. package/dist/transport/inject-rules.d.ts.map +1 -1
  65. package/dist/transport/inject-rules.js +3 -1
  66. package/dist/transport/inject-rules.js.map +1 -1
  67. package/dist/transport/msg-index.d.ts +29 -0
  68. package/dist/transport/msg-index.d.ts.map +1 -0
  69. package/dist/transport/msg-index.js +74 -0
  70. package/dist/transport/msg-index.js.map +1 -0
  71. package/dist/transport/outbound-buffer.d.ts +8 -2
  72. package/dist/transport/outbound-buffer.d.ts.map +1 -1
  73. package/dist/transport/outbound-buffer.js +37 -6
  74. package/dist/transport/outbound-buffer.js.map +1 -1
  75. package/dist/transport/outbound.d.ts.map +1 -1
  76. package/dist/transport/outbound.js +13 -2
  77. package/dist/transport/outbound.js.map +1 -1
  78. package/dist/transport/rich-media.d.ts +10 -1
  79. package/dist/transport/rich-media.d.ts.map +1 -1
  80. package/dist/transport/rich-media.js +21 -2
  81. package/dist/transport/rich-media.js.map +1 -1
  82. package/dist/types.d.ts +2 -0
  83. package/dist/types.d.ts.map +1 -1
  84. package/package.json +3 -2
  85. package/scripts/download-model.mjs +110 -0
  86. package/settings-host.js +337 -5
package/README.md CHANGED
@@ -253,6 +253,75 @@ npx @deepseek-ai/dsh web --patch /path/to/dsh-qqbot/cordis.dev.yml
253
253
 
254
254
  **配置项**(Web 面板 ⑥ 可改, 见下表 `groupAdmin.*`)
255
255
 
256
+ ## 🧠 本地小模型(可选,省 token)(v1.4.5+)
257
+
258
+ 让插件先用一个**跑在本机的小模型**给群消息打分(「价值评分」):分数低于门槛、又**没被 @** 的闲聊
259
+ **直接不唤醒 AI** → 那一轮 token 就省下来了;被 @ 的永远放行,**带图的消息一律放行**(群友发图多半是给她看的)。
260
+
261
+ - **模型**:`bge-small-zh-v1.5`(中文专训,ONNX 量化版 **≈ 23MB**,CPU 毫秒级,**零 token、完全离线**,不上传任何内容)
262
+ - **位置**:`{DSH_HOME | ~/.dsh}/models/bge-small-zh/`(用户级,跨工作区共用一份;也可在配置里指别的目录)
263
+ - **缺了也不影响使用**:检测不到模型就**自动静默关闭**评分,插件照常跑(只是不再省 token)
264
+
265
+ ### ① 一条命令下载(推荐)
266
+
267
+ ```bash
268
+ node scripts/download-model.mjs # 源码分发(在插件仓库根目录跑)
269
+ node node_modules/@zaofan/dsh-qqbot/scripts/download-model.mjs # npm 装的插件(npm 目录内)
270
+ ```
271
+
272
+ 默认**优先走国内镜像** `hf-mirror.com`(失败自动换官方源),下载完会校验体积并打印后续步骤。可选参数:
273
+
274
+ ```bash
275
+ node scripts/download-model.mjs --dir "D:\models\bge-small-zh" # 换目录(填进插件配置 localModel.modelDir)
276
+ node scripts/download-model.mjs --source hf # 强制官方源
277
+ ```
278
+
279
+ ### ② 手动下载(就三个文件)
280
+
281
+ 把 `<源>` 换成 `https://hf-mirror.com` 或 `https://huggingface.co`,文件放到 `~/.dsh/models/bge-small-zh/`:
282
+
283
+ | 下载地址 | 存放位置 | 体积参考 |
284
+ |---|---|---|
285
+ | `<源>/BAAI/bge-small-zh-v1.5/resolve/main/onnx/model_quantized.onnx` | `bge-small-zh/onnx/model_quantized.onnx` | ≈ 23MB |
286
+ | `<源>/BAAI/bge-small-zh-v1.5/resolve/main/tokenizer.json` | `bge-small-zh/tokenizer.json` | ≈ 430KB |
287
+ | `<源>/BAAI/bge-small-zh-v1.5/resolve/main/config.json` | `bge-small-zh/config.json` | < 1KB |
288
+
289
+ Windows PowerShell 例子:
290
+
291
+ ```powershell
292
+ $dir = "$env:USERPROFILE\.dsh\models\bge-small-zh"
293
+ $base = "https://hf-mirror.com/BAAI/bge-small-zh-v1.5/resolve/main"
294
+ New-Item -ItemType Directory -Force "$dir\onnx" | Out-Null
295
+ Invoke-WebRequest "$base/onnx/model_quantized.onnx" -OutFile "$dir\onnx\model_quantized.onnx"
296
+ Invoke-WebRequest "$base/tokenizer.json" -OutFile "$dir\tokenizer.json"
297
+ Invoke-WebRequest "$base/config.json" -OutFile "$dir\config.json"
298
+ ```
299
+
300
+ ### ③ 交给 AI 做(把下面这段直接粘给你的 AI / dsh 里的她)
301
+
302
+ ```text
303
+ 请帮我在本机装好 dsh 的 qqbot 插件要用的本地小模型(离线、不上传内容):
304
+ 1. 下载 BAAI/bge-small-zh-v1.5 的三个文件到 `~/.dsh/models/bge-small-zh/`:
305
+ onnx/model_quantized.onnx(≈23MB)、tokenizer.json、config.json;
306
+ 国内优先用 https://hf-mirror.com,失败再试 https://huggingface.co。
307
+ 2. 目录结构必须是:<模型目录>/onnx/model_quantized.onnx、<模型目录>/tokenizer.json、<模型目录>/config.json
308
+ 3. 下完自己校验:model_quantized.onnx ≥ 20MB、tokenizer.json ≥ 300KB;
309
+ 也可以直接跑插件仓库里的一键脚本:`node scripts/download-model.mjs`
310
+ 4. 最后告诉我:插件设置页「本地小模型」这一项该填什么、以及三个评分模式 off / log / block 分别什么行为。
311
+ ```
312
+
313
+ ### 评分模式怎么选
314
+
315
+ | 模式 | 行为 | 建议 |
316
+ |---|---|---|
317
+ | `off` | 完全不评分,所有消息照常唤醒 | 不想掺和 |
318
+ | `log` | **只记分,不拦** | **观察期**:先跑几天,在面板「最近评分」看分准不准 |
319
+ | `block` | 低于门槛(默认 `0.5`)**不唤醒** | 正式使用、省 token |
320
+
321
+ - **会话级覆盖**:dock「⚙ 单会话设置」里可以**按群单独设**模式 / 门槛 / 开关(存 `settings.yaml` 的 `localModel.overrides`),**保存即时生效,无需重启**(v1.4.5 起)。
322
+ - **拦截边界**:被 @ 的永远放行;带图一律放行;**只有被拦在唤醒之前**(没花 token)的那次才会**回滚**本群的回复冷却 —— 冷却本来就是用来省 token 的,token 花了就不算白花。
323
+ - **评分记录**:`{dataRoot}/.qqbot/value-scores.jsonl`,一行一条,字段 `score / worth / gate / min / conf / mention / img / lib / agg / top`。面板能直读,也可以让 AI 读它来维护样例库(`{dataRoot}/.qqbot/value-samples.jsonl`:`{"m":"消息文本","y":1|0}`,y=1 表示"她会想接话")。
324
+
256
325
  ## 配置项
257
326
 
258
327
  | 配置 | 类型 | 默认值 | 说明 |
@@ -275,6 +344,7 @@ npx @deepseek-ai/dsh web --patch /path/to/dsh-qqbot/cordis.dev.yml
275
344
  | `groupAdmin.manageGroup` | string | `''` | 对话内默认管理群 openid(web/非群会话时用) |
276
345
  | `groupAdmin.watchJoinRequests` | boolean | `false` | 订阅入群申请事件(改后需重启) |
277
346
  | `groupAdmin.notifyInGroup` | boolean | `true` | 收到申请时在群内发提醒 |
347
+ | `messageReference` | boolean | `true` | 引用消息总开关(v1.4.1): 开=入站消息带**短消息号** + 引用附原文 + 注入引用指令, AI 可用 `[rf:短号]` 引用对方; 关=完全不注入 |
278
348
 
279
349
  > 🔧 新版 Web 面板把群管理单开成「⑥ QQ 群管理」卡片(入群审批/禁言/成员信息/黑名单), 与上方 `groupAdmin.*` 配置同一份数据。
280
350
 
@@ -378,6 +448,7 @@ export default {
378
448
  | `[MEDIA:file\|来源]` | 发文件 | `[MEDIA:file\|D:\docs\计划.pdf]` |
379
449
  | `[RECALL]` | 撤回自己刚发的那条消息 | 单独一行写 `[RECALL]` |
380
450
  | `[RECALL:N]` | 撤回自己发的倒数第 N 条 | 如 `[RECALL:2]` 撤倒数第二条 |
451
+ | `[rf:短号]` | **引用**某条消息(以引用气泡形式发出) | `[rf:0913a]` 引用短号 `0913a` 那条 |
381
452
 
382
453
  要点:
383
454
  - 图片/文件可用**本机绝对路径**或**网络 URL**;语音本地路径若为 QQ SILK 格式也能转码发送。
@@ -385,6 +456,20 @@ export default {
385
456
  - 一次回复可混用多条 `[MEDIA:]`,配合长文本拆条连发使用。
386
457
  - 这些是"AI 会自己写"的暗号——正常聊天时她收到"发个开心点的图"这类指令,会自己调工具完成,不需要你手动写标记。
387
458
 
459
+ ### 引用消息(v1.4.1,默认开)
460
+
461
+ 每条入站消息都带一个**短消息号**(形如 `#0913a` = 月日 + 流水号):
462
+
463
+ ```
464
+ [做早饭 (E9020753…) #0913a] 帮我看看这个
465
+ ```
466
+
467
+ - AI 想引用某条消息时,在回复正文里写 `[rf:0913a]`,这条回复就会以**引用气泡**发出(对方能看到"她引用了这条")。
468
+ - 别人引用某条消息时,**被引用原文**会一并进上下文(`[Quoted message begins] … [Quoted message ends]`),AI 能读懂"他在回哪句话"。
469
+ - 短号 ↔ 完整 msg_id 的对应关系存在本地台账 `{dataRoot}/.qqbot/msg-index/{群|私聊}/refs.json`(**按会话分文件夹**,每份上限 500 条,超出丢最旧;带时间与发送者昵称,可直接打开查)。
470
+ - 好处:长 msg_id(60+ 字符)不再进上下文,**短号只花 1-2 token**。
471
+ - 关闭:设置面板 ③ 区块去掉「引用消息」勾选 → 不登记台账、不注入短号、不注入引用指令。
472
+
388
473
  ## 核心模块
389
474
 
390
475
  ```
package/README_EN.md CHANGED
@@ -221,6 +221,21 @@ auto-cancelled when the agent is cancelled or dsh exits.
221
221
  | `textChunkLimit` | number | `4500` | Max chars per message |
222
222
  | `sessionIdleTimeout` | number | `1800000` | Session idle timeout (ms), default 30 min |
223
223
  | `debug` | boolean | `false` | Debug mode |
224
+ | `messageReference` | boolean | `true` | Message-reference master switch (v1.4.1): inbound messages carry a **short message number** + quoted originals are included + the reference instruction is injected, so the AI can reply with a quote via `[rf:short-id]`; off = nothing injected |
225
+
226
+ ## Message Reference (v1.4.1, on by default)
227
+
228
+ Every inbound message carries a **short message number** (e.g. `#0913a` — month/day + rolling id):
229
+
230
+ ```
231
+ [做早饭 (E9020753…) #0913a] take a look at this
232
+ ```
233
+
234
+ - To quote a message, the AI writes `[rf:0913a]` in its reply body → the reply is sent as a **quote bubble** (the other side sees "she quoted this message"). The tag itself is never displayed.
235
+ - When someone quotes a message, the **quoted original** is included in the context (`[Quoted message begins] … [Quoted message ends]`), so the AI understands what is being replied to.
236
+ - The short-id ↔ full msg_id mapping lives in a local ledger at `{dataRoot}/.qqbot/msg-index/{group|dm}/refs.json` — **one folder per conversation**, capped at **500 entries** each (oldest dropped first), with timestamps and sender nicknames so it stays human-readable.
237
+ - Why: full msg_ids (60+ chars) no longer enter the context — a short id costs **1-2 tokens** instead of ~20+ per message.
238
+ - Turn it off in the settings panel (section ③, "引用消息"): no ledger, no short ids, no instruction injected.
224
239
 
225
240
  ## Built-in Commands
226
241