@zaofan/dsh-qqbot 0.6.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 (227) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +308 -0
  3. package/README_EN.md +273 -0
  4. package/client/qqbot-settings.js +1463 -0
  5. package/cordis.patch.yml +36 -0
  6. package/dist/api/group-admin.d.ts +112 -0
  7. package/dist/api/group-admin.d.ts.map +1 -0
  8. package/dist/api/group-admin.js +179 -0
  9. package/dist/api/group-admin.js.map +1 -0
  10. package/dist/channel-tools.d.ts +14 -0
  11. package/dist/channel-tools.d.ts.map +1 -0
  12. package/dist/channel-tools.js +880 -0
  13. package/dist/channel-tools.js.map +1 -0
  14. package/dist/commands/help.d.ts +11 -0
  15. package/dist/commands/help.d.ts.map +1 -0
  16. package/dist/commands/help.js +21 -0
  17. package/dist/commands/help.js.map +1 -0
  18. package/dist/commands/index.d.ts +13 -0
  19. package/dist/commands/index.d.ts.map +1 -0
  20. package/dist/commands/index.js +29 -0
  21. package/dist/commands/index.js.map +1 -0
  22. package/dist/commands/misc.d.ts +14 -0
  23. package/dist/commands/misc.d.ts.map +1 -0
  24. package/dist/commands/misc.js +39 -0
  25. package/dist/commands/misc.js.map +1 -0
  26. package/dist/commands/model.d.ts +7 -0
  27. package/dist/commands/model.d.ts.map +1 -0
  28. package/dist/commands/model.js +58 -0
  29. package/dist/commands/model.js.map +1 -0
  30. package/dist/commands/session.d.ts +10 -0
  31. package/dist/commands/session.d.ts.map +1 -0
  32. package/dist/commands/session.js +26 -0
  33. package/dist/commands/session.js.map +1 -0
  34. package/dist/commands/status.d.ts +8 -0
  35. package/dist/commands/status.d.ts.map +1 -0
  36. package/dist/commands/status.js +24 -0
  37. package/dist/commands/status.js.map +1 -0
  38. package/dist/commands/types.d.ts +12 -0
  39. package/dist/commands/types.d.ts.map +1 -0
  40. package/dist/commands/types.js +2 -0
  41. package/dist/commands/types.js.map +1 -0
  42. package/dist/config.d.ts +205 -0
  43. package/dist/config.d.ts.map +1 -0
  44. package/dist/config.js +203 -0
  45. package/dist/config.js.map +1 -0
  46. package/dist/features/chat-ledger.d.ts +53 -0
  47. package/dist/features/chat-ledger.d.ts.map +1 -0
  48. package/dist/features/chat-ledger.js +185 -0
  49. package/dist/features/chat-ledger.js.map +1 -0
  50. package/dist/features/face-tags.d.ts +17 -0
  51. package/dist/features/face-tags.d.ts.map +1 -0
  52. package/dist/features/face-tags.js +79 -0
  53. package/dist/features/face-tags.js.map +1 -0
  54. package/dist/features/group-join-request.d.ts +65 -0
  55. package/dist/features/group-join-request.d.ts.map +1 -0
  56. package/dist/features/group-join-request.js +190 -0
  57. package/dist/features/group-join-request.js.map +1 -0
  58. package/dist/features/history-store.d.ts +8 -0
  59. package/dist/features/history-store.d.ts.map +1 -0
  60. package/dist/features/history-store.js +24 -0
  61. package/dist/features/history-store.js.map +1 -0
  62. package/dist/features/qq-approval.d.ts +78 -0
  63. package/dist/features/qq-approval.d.ts.map +1 -0
  64. package/dist/features/qq-approval.js +165 -0
  65. package/dist/features/qq-approval.js.map +1 -0
  66. package/dist/features/schedule-store.d.ts +62 -0
  67. package/dist/features/schedule-store.d.ts.map +1 -0
  68. package/dist/features/schedule-store.js +253 -0
  69. package/dist/features/schedule-store.js.map +1 -0
  70. package/dist/features/scheduler.d.ts +9 -0
  71. package/dist/features/scheduler.d.ts.map +1 -0
  72. package/dist/features/scheduler.js +146 -0
  73. package/dist/features/scheduler.js.map +1 -0
  74. package/dist/features/sticker-gate.d.ts +90 -0
  75. package/dist/features/sticker-gate.d.ts.map +1 -0
  76. package/dist/features/sticker-gate.js +391 -0
  77. package/dist/features/sticker-gate.js.map +1 -0
  78. package/dist/features/sticker-store.d.ts +158 -0
  79. package/dist/features/sticker-store.d.ts.map +1 -0
  80. package/dist/features/sticker-store.js +676 -0
  81. package/dist/features/sticker-store.js.map +1 -0
  82. package/dist/features/sticker-tagger.d.ts +10 -0
  83. package/dist/features/sticker-tagger.d.ts.map +1 -0
  84. package/dist/features/sticker-tagger.js +139 -0
  85. package/dist/features/sticker-tagger.js.map +1 -0
  86. package/dist/gateway/bootstrap.d.ts +12 -0
  87. package/dist/gateway/bootstrap.d.ts.map +1 -0
  88. package/dist/gateway/bootstrap.js +346 -0
  89. package/dist/gateway/bootstrap.js.map +1 -0
  90. package/dist/gateway/debounce.d.ts +40 -0
  91. package/dist/gateway/debounce.d.ts.map +1 -0
  92. package/dist/gateway/debounce.js +262 -0
  93. package/dist/gateway/debounce.js.map +1 -0
  94. package/dist/gateway/index.d.ts +3 -0
  95. package/dist/gateway/index.d.ts.map +1 -0
  96. package/dist/gateway/index.js +3 -0
  97. package/dist/gateway/index.js.map +1 -0
  98. package/dist/gateway/middleware-setup.d.ts +12 -0
  99. package/dist/gateway/middleware-setup.d.ts.map +1 -0
  100. package/dist/gateway/middleware-setup.js +156 -0
  101. package/dist/gateway/middleware-setup.js.map +1 -0
  102. package/dist/index.d.ts +14 -0
  103. package/dist/index.d.ts.map +1 -0
  104. package/dist/index.js +187 -0
  105. package/dist/index.js.map +1 -0
  106. package/dist/middleware/attachment.d.ts +11 -0
  107. package/dist/middleware/attachment.d.ts.map +1 -0
  108. package/dist/middleware/attachment.js +17 -0
  109. package/dist/middleware/attachment.js.map +1 -0
  110. package/dist/middleware/media-history.d.ts +30 -0
  111. package/dist/middleware/media-history.d.ts.map +1 -0
  112. package/dist/middleware/media-history.js +54 -0
  113. package/dist/middleware/media-history.js.map +1 -0
  114. package/dist/middleware/sticker-capture.d.ts +17 -0
  115. package/dist/middleware/sticker-capture.d.ts.map +1 -0
  116. package/dist/middleware/sticker-capture.js +97 -0
  117. package/dist/middleware/sticker-capture.js.map +1 -0
  118. package/dist/model/index.d.ts +10 -0
  119. package/dist/model/index.d.ts.map +1 -0
  120. package/dist/model/index.js +9 -0
  121. package/dist/model/index.js.map +1 -0
  122. package/dist/model/model-resolver.d.ts +88 -0
  123. package/dist/model/model-resolver.d.ts.map +1 -0
  124. package/dist/model/model-resolver.js +151 -0
  125. package/dist/model/model-resolver.js.map +1 -0
  126. package/dist/model/prefs-store.d.ts +24 -0
  127. package/dist/model/prefs-store.d.ts.map +1 -0
  128. package/dist/model/prefs-store.js +126 -0
  129. package/dist/model/prefs-store.js.map +1 -0
  130. package/dist/model/settings-reader.d.ts +19 -0
  131. package/dist/model/settings-reader.d.ts.map +1 -0
  132. package/dist/model/settings-reader.js +76 -0
  133. package/dist/model/settings-reader.js.map +1 -0
  134. package/dist/model/types.d.ts +15 -0
  135. package/dist/model/types.d.ts.map +1 -0
  136. package/dist/model/types.js +5 -0
  137. package/dist/model/types.js.map +1 -0
  138. package/dist/session/idle-evictor.d.ts +18 -0
  139. package/dist/session/idle-evictor.d.ts.map +1 -0
  140. package/dist/session/idle-evictor.js +31 -0
  141. package/dist/session/idle-evictor.js.map +1 -0
  142. package/dist/session/index.d.ts +9 -0
  143. package/dist/session/index.d.ts.map +1 -0
  144. package/dist/session/index.js +8 -0
  145. package/dist/session/index.js.map +1 -0
  146. package/dist/session/session-manager.d.ts +97 -0
  147. package/dist/session/session-manager.d.ts.map +1 -0
  148. package/dist/session/session-manager.js +624 -0
  149. package/dist/session/session-manager.js.map +1 -0
  150. package/dist/session/types.d.ts +130 -0
  151. package/dist/session/types.d.ts.map +1 -0
  152. package/dist/session/types.js +2 -0
  153. package/dist/session/types.js.map +1 -0
  154. package/dist/session/workspace-attach.d.ts +22 -0
  155. package/dist/session/workspace-attach.d.ts.map +1 -0
  156. package/dist/session/workspace-attach.js +21 -0
  157. package/dist/session/workspace-attach.js.map +1 -0
  158. package/dist/setup.d.ts +25 -0
  159. package/dist/setup.d.ts.map +1 -0
  160. package/dist/setup.js +198 -0
  161. package/dist/setup.js.map +1 -0
  162. package/dist/shared/index.d.ts +7 -0
  163. package/dist/shared/index.d.ts.map +1 -0
  164. package/dist/shared/index.js +7 -0
  165. package/dist/shared/index.js.map +1 -0
  166. package/dist/shared/scope.d.ts +14 -0
  167. package/dist/shared/scope.d.ts.map +1 -0
  168. package/dist/shared/scope.js +12 -0
  169. package/dist/shared/scope.js.map +1 -0
  170. package/dist/shared/send-helper.d.ts +11 -0
  171. package/dist/shared/send-helper.d.ts.map +1 -0
  172. package/dist/shared/send-helper.js +13 -0
  173. package/dist/shared/send-helper.js.map +1 -0
  174. package/dist/shared/utils.d.ts +28 -0
  175. package/dist/shared/utils.d.ts.map +1 -0
  176. package/dist/shared/utils.js +143 -0
  177. package/dist/shared/utils.js.map +1 -0
  178. package/dist/transport/attachment.d.ts +18 -0
  179. package/dist/transport/attachment.d.ts.map +1 -0
  180. package/dist/transport/attachment.js +106 -0
  181. package/dist/transport/attachment.js.map +1 -0
  182. package/dist/transport/chunker.d.ts +14 -0
  183. package/dist/transport/chunker.d.ts.map +1 -0
  184. package/dist/transport/chunker.js +78 -0
  185. package/dist/transport/chunker.js.map +1 -0
  186. package/dist/transport/events.d.ts +80 -0
  187. package/dist/transport/events.d.ts.map +1 -0
  188. package/dist/transport/events.js +62 -0
  189. package/dist/transport/events.js.map +1 -0
  190. package/dist/transport/inbound.d.ts +8 -0
  191. package/dist/transport/inbound.d.ts.map +1 -0
  192. package/dist/transport/inbound.js +292 -0
  193. package/dist/transport/inbound.js.map +1 -0
  194. package/dist/transport/index.d.ts +10 -0
  195. package/dist/transport/index.d.ts.map +1 -0
  196. package/dist/transport/index.js +10 -0
  197. package/dist/transport/index.js.map +1 -0
  198. package/dist/transport/inject-rules.d.ts +24 -0
  199. package/dist/transport/inject-rules.d.ts.map +1 -0
  200. package/dist/transport/inject-rules.js +72 -0
  201. package/dist/transport/inject-rules.js.map +1 -0
  202. package/dist/transport/outbound-buffer.d.ts +56 -0
  203. package/dist/transport/outbound-buffer.d.ts.map +1 -0
  204. package/dist/transport/outbound-buffer.js +131 -0
  205. package/dist/transport/outbound-buffer.js.map +1 -0
  206. package/dist/transport/outbound.d.ts +30 -0
  207. package/dist/transport/outbound.d.ts.map +1 -0
  208. package/dist/transport/outbound.js +139 -0
  209. package/dist/transport/outbound.js.map +1 -0
  210. package/dist/transport/rich-media.d.ts +41 -0
  211. package/dist/transport/rich-media.d.ts.map +1 -0
  212. package/dist/transport/rich-media.js +104 -0
  213. package/dist/transport/rich-media.js.map +1 -0
  214. package/dist/transport/streaming-writer.d.ts +47 -0
  215. package/dist/transport/streaming-writer.d.ts.map +1 -0
  216. package/dist/transport/streaming-writer.js +110 -0
  217. package/dist/transport/streaming-writer.js.map +1 -0
  218. package/dist/transport/tool-presenter.d.ts +38 -0
  219. package/dist/transport/tool-presenter.d.ts.map +1 -0
  220. package/dist/transport/tool-presenter.js +121 -0
  221. package/dist/transport/tool-presenter.js.map +1 -0
  222. package/dist/types.d.ts +45 -0
  223. package/dist/types.d.ts.map +1 -0
  224. package/dist/types.js +5 -0
  225. package/dist/types.js.map +1 -0
  226. package/package.json +106 -0
  227. package/settings-host.js +927 -0
@@ -0,0 +1,40 @@
1
+ /**
2
+ * debounce.ts — 延迟聚合回复(2026-09-05 新增; 与"群冷却"融合的终版)
3
+ *
4
+ * 要解决的问题: 用户连发 N 句, AI 只回第一句 / 上下文顺序倒置。
5
+ *
6
+ * 链路位置: 插在群冷却中间件**之前**(middleware-setup 第6.6步)。所有群消息(普通/@)与私聊
7
+ * 先聚合进 per-peer 窗口(peerKey = group:<groupOpenid> | c2c:<senderId>), 冷却中间件收不到被吞的消息。
8
+ *
9
+ * 窗口/触发: 有新消息(按 QQ 服务器时间戳更新)就重置计时; 静默 X 秒 或 攒满 Y 条 → 尝试派发。
10
+ *
11
+ * 派发判定(与群冷却融合):
12
+ * - 窗口含 @: @ 无视冷却, 随时整批派发(只多等 debounce 静默)。
13
+ * - 群普通(无@): 距上次普通派发不足 freeIntervalSec → 窗口保留继续攒, 冷却结束再整批
14
+ * 按服务器时间序一次综合回(两次"批派发"仍 ≥60s, 防刷屏语义保留; 冷却是 60s 级的、聚合是 3s 级的, 不再打架)。
15
+ * - 私聊: 无冷却, 直接派发。
16
+ *
17
+ * 派发内容(防倒序): 以 store(mediaHistoryBuffer 记录的全量, 含被吞消息)为权威,
18
+ * 与窗口合并去重后按服务器时间戳升序: current = 时间序最后一条; 窗口内更早的 @ 消息在 history 里补
19
+ * " (@you)" 标注(与 current 同款 @ 事实标注, 回不回由 AI 按守则判, 插件不注入回复指令);
20
+ * 其余按序进 [Chat history]。私聊无 store → 窗口文本按序拼接+合并附件成合成消息直连。
21
+ *
22
+ * 斜杠命令(以 / 开头)不聚合直放行: 保 /approve /bot-stop 等命令的即时性。
23
+ * debounce.enabled=false 或 @ 秒回(mentionDelayed=false) → 直放行, 交回下方群冷却中间件与既有链路。
24
+ *
25
+ * 配置: config.behavior.debounce { enabled, silenceSec, maxMsgs, mentionDelayed } + behavior.freeIntervalSec, 每次现读(live 热更)。
26
+ * ⚠️ 本地手改功能: 同步纪律同 middleware-setup.ts 内群冷却中间件(改完保持 src 与部署 dist 一致)。
27
+ */
28
+ import type { Middleware } from '@tencent-connect/qqbot-nodejs';
29
+ import type { ImQQBotConfig } from '../config.js';
30
+ import type { SessionManager } from '../session/index.js';
31
+ import type { Logger } from '../types.js';
32
+ /**
33
+ * 构造延迟聚合中间件(与群冷却融合, 2026-09-05 终版)。
34
+ * 插在群冷却中间件**之前**: 所有群消息(普通/@)与私聊先聚合进 per-peer 窗口;
35
+ * flush 时群普通消息仍受 60s 冷却约束(未过则窗口保留等冷却结束整批按时间序派发),
36
+ * @ 消息无视冷却随时派发。
37
+ * cooldownAt: 与 middleware-setup 群冷却中间件共享的 lastDispatchAt(groupOpenid -> 上次普通派发 ms)。
38
+ */
39
+ export declare function debounceLayer(config: ImQQBotConfig, manager: SessionManager, logger: Logger, cooldownAt: Map<string, number>): Middleware;
40
+ //# sourceMappingURL=debounce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../../src/gateway/debounce.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,UAAU,EAAmC,MAAM,+BAA+B,CAAC;AACjG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAyC1C;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,UAAU,CAuPZ"}
@@ -0,0 +1,262 @@
1
+ import { handleInbound } from '../transport/inbound.js';
2
+ import { getHistoryStore, historyGroupKey } from '../features/history-store.js';
3
+ import { appendFileSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ const DEFAULTS = { enabled: true, silenceSec: 3, maxMsgs: 10, mentionDelayed: true };
6
+ /** 解析消息服务器时间戳(ISO 字符串或 ms 数字; 解析失败回落"到达时刻"兜底) */
7
+ function msgTs(msg) {
8
+ const raw = msg.timestamp;
9
+ const n = typeof raw === 'number' ? raw : Date.parse(String(raw ?? ''));
10
+ return Number.isFinite(n) ? n : Date.now();
11
+ }
12
+ function num(v, d) {
13
+ const n = Number(v);
14
+ return Number.isFinite(n) ? n : d;
15
+ }
16
+ /**
17
+ * 构造延迟聚合中间件(与群冷却融合, 2026-09-05 终版)。
18
+ * 插在群冷却中间件**之前**: 所有群消息(普通/@)与私聊先聚合进 per-peer 窗口;
19
+ * flush 时群普通消息仍受 60s 冷却约束(未过则窗口保留等冷却结束整批按时间序派发),
20
+ * @ 消息无视冷却随时派发。
21
+ * cooldownAt: 与 middleware-setup 群冷却中间件共享的 lastDispatchAt(groupOpenid -> 上次普通派发 ms)。
22
+ */
23
+ export function debounceLayer(config, manager, logger, cooldownAt) {
24
+ const windows = new Map();
25
+ /** 调序调试日志(临时, 定位官方帧序用; 排查完删除): {cwd}/.qqbot/debounce-dbg.log */
26
+ const dbgFile = join(config.cwd || process.cwd(), '.qqbot', 'debounce-dbg.log');
27
+ function dbg(line) {
28
+ try {
29
+ appendFileSync(dbgFile, `${new Date().toISOString()} ${line}\n`, 'utf8');
30
+ }
31
+ catch { /* ignore */ }
32
+ }
33
+ const cfg = () => {
34
+ const d = config.behavior?.debounce;
35
+ return d ?? DEFAULTS;
36
+ };
37
+ function clearTimer(w) {
38
+ if (w.timer) {
39
+ clearTimeout(w.timer);
40
+ w.timer = null;
41
+ }
42
+ }
43
+ /** 尝试派发一批(窗口内全部消息 → AI 一次综合回复)。
44
+ * 群普通(无@)受 60s 冷却约束: 未过冷却 → 窗口保留、重排计时器, 冷却结束再整批按时间序派发。
45
+ * @ 消息(窗口含@)/私聊: 随时派发。 */
46
+ async function flush(key, w) {
47
+ const pre = w.entries;
48
+ if (pre.length === 0) {
49
+ clearTimer(w);
50
+ windows.delete(key);
51
+ return;
52
+ }
53
+ const f0 = pre[0];
54
+ if (!f0) {
55
+ clearTimer(w);
56
+ windows.delete(key);
57
+ return;
58
+ }
59
+ const fKind = String(f0.msg.kind ?? '');
60
+ const hasMention = pre.some(e => e.wasMentioned);
61
+ if (fKind === 'group' && !hasMention) {
62
+ // 群普通消息: 距上次普通派发不足 freeIntervalSec → 冷却中, 窗口保留继续攒
63
+ const gid = String(f0.msg.groupOpenid ?? f0.msg.senderId ?? '');
64
+ const freeSec = Math.max(0, num(config.behavior?.freeIntervalSec, 0));
65
+ if (gid && freeSec > 0) {
66
+ const nowMs = Date.now();
67
+ const lastAt = cooldownAt.get(gid) ?? 0;
68
+ const passedMs = nowMs - lastAt;
69
+ if (passedMs < freeSec * 1000) {
70
+ clearTimer(w);
71
+ const retryMs = Math.max(500, freeSec * 1000 - passedMs);
72
+ w.timer = setTimeout(() => void flush(key, w), retryMs);
73
+ w.timer.unref?.();
74
+ dbg(`flush 冷却中 defer ${Math.round(retryMs / 1000)}s key=${key} n=${pre.length}`);
75
+ return; // 窗口保留, 不派发
76
+ }
77
+ }
78
+ }
79
+ clearTimer(w);
80
+ windows.delete(key);
81
+ const entries = w.entries;
82
+ if (entries.length === 0)
83
+ return;
84
+ // QQ 官方推送可能乱序: 派发前统一按服务器时间戳升序排(旧→新)
85
+ entries.sort((a, b) => a.ts - b.ts);
86
+ // 触发消息形状(仅取 kind/gid 参考; 真正的 current 在群分支按时间序从 merged 里取)
87
+ const trigger = entries[entries.length - 1];
88
+ if (!trigger)
89
+ return;
90
+ const kind = String(trigger.msg.kind ?? '');
91
+ dbg(`flush key=${key} n=${entries.length} sorted-order=[${entries.map(e => JSON.stringify(String(e.msg.content ?? '').slice(0, 24))).join(',')}] hasMention=${hasMention}`);
92
+ try {
93
+ if (kind === 'group') {
94
+ const gid = String(trigger.msg.groupOpenid ?? trigger.msg.senderId ?? '');
95
+ if (!gid)
96
+ return;
97
+ // 群冷却吞掉的消息也已被 mediaHistoryBuffer(链第4步, 冷却/debounce 之前)记录进 store。
98
+ // 因此以 store 为权威全量: 与窗口合并去重、按服务器时间序排列后,
99
+ // current 取"时间上真正最后一条"(窗口含@时取最后一条被@的), 其余按序进 history ——
100
+ // 避免 current 取成"群冷却放行的第一条"导致上下文整体倒序。
101
+ let storeHist = [];
102
+ try {
103
+ storeHist = await getHistoryStore().list(historyGroupKey(config.appId, gid), num(config.historyLimit, 20));
104
+ }
105
+ catch (err) {
106
+ logger.warn?.(`[debounce] 拉群历史失败: ${err instanceof Error ? err.message : String(err)}`);
107
+ }
108
+ dbg(` store-raw=[${storeHist.map(h => JSON.stringify(String(h.content).slice(0, 24))).join(',')}]`);
109
+ const merged = storeHist.map(h => ({
110
+ messageId: h.messageId,
111
+ ts: h.timestamp || 0,
112
+ content: h.content,
113
+ senderId: h.senderId,
114
+ senderName: h.senderName,
115
+ }));
116
+ for (const e of entries) {
117
+ const id = String(e.msg.messageId ?? '');
118
+ const hit = merged.find(m => m.messageId === id);
119
+ if (hit) {
120
+ if (e.wasMentioned)
121
+ hit.wasMentioned = true;
122
+ }
123
+ else {
124
+ merged.push({ messageId: id, ts: e.ts, msg: e.msg, wasMentioned: e.wasMentioned });
125
+ }
126
+ }
127
+ merged.sort((a, b) => a.ts - b.ts);
128
+ // current 恒取时间序最后一条(纯时间序, 上下文永不倒置)。
129
+ const cur = merged[merged.length - 1];
130
+ if (!cur)
131
+ return;
132
+ // 忠实还原 store 原文进 history; 窗口内曾 @ 机器人的消息(时间上早于 current)
133
+ // 补 " (@you)" 标注 —— 与 current 的 (@you) 同款格式, 还原"这条@了bot"的事实,
134
+ // 由 AI 按自身守则决定是否开口(插件不注入回复指令, 保持通用)。
135
+ const hist = merged
136
+ .filter(m => m.messageId !== cur.messageId)
137
+ .map(m => {
138
+ const baseContent = m.content ?? String(m.msg?.content ?? '');
139
+ return {
140
+ senderId: m.senderId ?? '',
141
+ senderName: m.senderName,
142
+ content: m.wasMentioned ? `${baseContent} (@you)` : baseContent,
143
+ timestamp: m.ts,
144
+ messageId: m.messageId,
145
+ };
146
+ });
147
+ // current 消息: 窗口条目有完整 msg; store 来源的只有 HistoryEntry 字段,
148
+ // 从群窗口消息继承 kind/groupOpenid/attachments 等再补齐本人字段。
149
+ const curMsg = cur.msg ?? {
150
+ ...(entries[entries.length - 1] ?? trigger).msg,
151
+ messageId: cur.messageId,
152
+ content: cur.content ?? '',
153
+ senderId: cur.senderId,
154
+ senderName: cur.senderName,
155
+ timestamp: new Date(cur.ts).toISOString(),
156
+ };
157
+ const state = { history: hist };
158
+ if (cur.wasMentioned) {
159
+ // current 本身就是 @ 消息 → 走正常 mention, AI 见 (@you)
160
+ state.mention = { wasMentioned: true };
161
+ }
162
+ else {
163
+ state.batchDispatch = true;
164
+ }
165
+ dbg(` merged-order=[${merged.map(m => JSON.stringify(String(m.content ?? m.msg?.content ?? '').slice(0, 16))).join(',')}] cur=${JSON.stringify(String(cur.content ?? cur.msg?.content ?? '').slice(0, 16))} hasMention=${hasMention}`);
166
+ // 群普通(无@)批派发 → 记冷却(与群冷却中间件共享 lastDispatchAt, 防刷屏语义保留)
167
+ if (!hasMention)
168
+ cooldownAt.set(gid, Date.now());
169
+ logger.info(`[debounce] flush(group ${gid}) 窗口${entries.length}条/store${storeHist.length}条 → handleInbound`);
170
+ await handleInbound(curMsg, manager, config, logger, state);
171
+ }
172
+ else {
173
+ // 私聊: 无群历史缓冲, 窗口自缓冲 → 文本按序拼接 + 合并附件成一条合成消息
174
+ const textLines = entries
175
+ .map(e => String(e.msg.content ?? '').trim())
176
+ .filter(Boolean);
177
+ const allAtts = [];
178
+ for (const e of entries) {
179
+ const a = e.msg.attachments;
180
+ if (Array.isArray(a) && a.length > 0)
181
+ allAtts.push(...a);
182
+ }
183
+ const lastEntry = entries[entries.length - 1];
184
+ const base = (lastEntry ?? trigger).msg;
185
+ const merged = {
186
+ ...base,
187
+ content: textLines.join('\n'),
188
+ attachments: allAtts.length > 0 ? allAtts : undefined,
189
+ };
190
+ logger.info(`[debounce] flush(c2c ${String(base.senderId ?? '')}) ${entries.length}条 → handleInbound`);
191
+ await handleInbound(merged, manager, config, logger, undefined);
192
+ }
193
+ }
194
+ catch (err) {
195
+ logger.error(`[debounce] flush 失败: ${err instanceof Error ? err.message : String(err)}`);
196
+ }
197
+ }
198
+ return async (ctx, next) => {
199
+ const c = cfg();
200
+ if (!c.enabled)
201
+ return next();
202
+ const msg = ctx.message;
203
+ const kind = String(msg.kind ?? '');
204
+ if (kind !== 'group' && kind !== 'c2c')
205
+ return next();
206
+ // 斜杠命令不聚合: 保 /approve、/bot-stop、/help 等即时响应
207
+ const content = String(msg.content ?? '').trim();
208
+ if (content.startsWith('/'))
209
+ return next();
210
+ const wasMentioned = ctx.state?.mention?.wasMentioned === true;
211
+ // @ 可配置为不走延迟(秒回)
212
+ if (wasMentioned && c.mentionDelayed === false)
213
+ return next();
214
+ const peerId = kind === 'group'
215
+ ? (msg.groupOpenid ?? msg.senderId)
216
+ : msg.senderId;
217
+ if (!peerId)
218
+ return next();
219
+ const key = `${kind}:${String(peerId)}`;
220
+ const silenceMs = Math.max(0, num(c.silenceSec, DEFAULTS.silenceSec)) * 1000;
221
+ const maxMsgs = Math.max(1, Math.floor(num(c.maxMsgs, DEFAULTS.maxMsgs)));
222
+ if (silenceMs <= 0)
223
+ return next(); // 0=不停顿: 保持原链路立即派发
224
+ let w = windows.get(key);
225
+ if (!w) {
226
+ w = { entries: [], timer: null };
227
+ windows.set(key, w);
228
+ }
229
+ // 防御: 窗口保留等冷却期间可能持续进消息 → 超上限丢最老(只留最近 100 条)
230
+ if (w.entries.length >= 100) {
231
+ w.entries.splice(0, w.entries.length - 80);
232
+ }
233
+ const ts = msgTs(msg);
234
+ const arrivedAt = Date.now();
235
+ // 到达日志: 记录"到达本中间件的时刻"+"服务器时间戳", 用于对比官方帧序与真实发送序
236
+ dbg(`arrive key=${key} at=${arrivedAt} ts=${String(msg.timestamp ?? '')} parsedTs=${ts} id=${String(msg.messageId ?? '').slice(0, 14)} mention=${wasMentioned} content=${JSON.stringify(content.slice(0, 30))}`);
237
+ // 只有"比窗口现有消息更新"的消息才算最近说话者继续开口 → 重置静默计时;
238
+ // 乱序补到的旧消息(服务器时间更早)只入窗口, 不延长等待。
239
+ let maxTs = 0;
240
+ for (let i = 0; i < w.entries.length; i++) {
241
+ const e = w.entries[i];
242
+ if (e && e.ts > maxTs)
243
+ maxTs = e.ts;
244
+ }
245
+ const isNewer = ts >= maxTs;
246
+ w.entries.push({ msg: { ...msg }, wasMentioned, ts });
247
+ dbg(` win=${w.entries.length} new=${isNewer} order=[${w.entries.map(e => JSON.stringify(String(e.msg.content ?? '').slice(0, 16))).join(',')}]`);
248
+ if (isNewer) {
249
+ // 最近说话者(按服务器时间)刚又开口 → 重新等 ta 停口 silenceMs
250
+ clearTimer(w);
251
+ w.timer = setTimeout(() => void flush(key, w), silenceMs);
252
+ w.timer.unref?.();
253
+ }
254
+ // 攒满上限立即发, 不等对方停
255
+ if (w.entries.length >= maxMsgs) {
256
+ void flush(key, w);
257
+ return;
258
+ }
259
+ // 吞掉本消息(不调 next): 群消息已被链第4步 mediaHistoryBuffer 记录, 延迟到 flush 直连派发
260
+ };
261
+ }
262
+ //# sourceMappingURL=debounce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.js","sourceRoot":"","sources":["../../src/gateway/debounce.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAUjC,MAAM,QAAQ,GAA0B,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;AAe5G,iDAAiD;AACjD,SAAS,KAAK,CAAC,GAA4B;IACzC,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;IACxE,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;AAC7C,CAAC;AAED,SAAS,GAAG,CAAC,CAAU,EAAE,CAAS;IAChC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAqB,EACrB,OAAuB,EACvB,MAAc,EACd,UAA+B;IAE/B,MAAM,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;IAElD,gEAAgE;IAChE,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC;IAChF,SAAS,GAAG,CAAC,IAAY;QACvB,IAAI,CAAC;YACH,cAAc,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,IAAI,IAAI,EAAE,MAAM,CAAC,CAAC;QAC3E,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,GAAG,GAAG,GAAgB,EAAE;QAC5B,MAAM,CAAC,GAAI,MAAM,CAAC,QAAuC,EAAE,QAAQ,CAAC;QACpE,OAAO,CAAC,IAAI,QAAQ,CAAC;IACvB,CAAC,CAAC;IAEF,SAAS,UAAU,CAAC,CAAiB;QACnC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YACZ,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC;QACjB,CAAC;IACH,CAAC;IAED;;+BAE2B;IAC3B,KAAK,UAAU,KAAK,CAAC,GAAW,EAAE,CAAiB;QACjD,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC;QACtB,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,UAAU,CAAC,CAAC,CAAC,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QACD,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,UAAU,CAAC,CAAC,CAAC,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QACxC,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QACjD,IAAI,KAAK,KAAK,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC;YACrC,kDAAkD;YAClD,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;YAChE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAE,MAAM,CAAC,QAA0C,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC;YACzG,IAAI,GAAG,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;gBACvB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACzB,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACxC,MAAM,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;gBAChC,IAAI,QAAQ,GAAG,OAAO,GAAG,IAAI,EAAE,CAAC;oBAC9B,UAAU,CAAC,CAAC,CAAC,CAAC;oBACd,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,GAAG,QAAQ,CAAC,CAAC;oBACzD,CAAC,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;oBACxD,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;oBAClB,GAAG,CAAC,mBAAmB,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;oBACjF,OAAO,CAAC,YAAY;gBACtB,CAAC;YACH,CAAC;QACH,CAAC;QACD,UAAU,CAAC,CAAC,CAAC,CAAC;QACd,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpB,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;QAC1B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAEjC,oCAAoC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QAEpC,0DAA0D;QAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAC5C,GAAG,CAAC,aAAa,GAAG,MAAM,OAAO,CAAC,MAAM,kBAAkB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,gBAAgB,UAAU,EAAE,CAAC,CAAC;QAE5K,IAAI,CAAC;YACH,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;gBAC1E,IAAI,CAAC,GAAG;oBAAE,OAAO;gBACjB,iEAAiE;gBACjE,uCAAuC;gBACvC,wDAAwD;gBACxD,qCAAqC;gBACrC,IAAI,SAAS,GAAmB,EAAE,CAAC;gBACnC,IAAI,CAAC;oBACH,SAAS,GAAG,MAAM,eAAe,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,CAAC;gBAC7G,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,CAAC,IAAI,EAAE,CAAC,sBAAsB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC1F,CAAC;gBACD,GAAG,CAAC,gBAAgB,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAWrG,MAAM,MAAM,GAAiB,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC/C,SAAS,EAAE,CAAC,CAAC,SAAS;oBACtB,EAAE,EAAE,CAAC,CAAC,SAAS,IAAI,CAAC;oBACpB,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,QAAQ,EAAE,CAAC,CAAC,QAAQ;oBACpB,UAAU,EAAE,CAAC,CAAC,UAAU;iBACzB,CAAC,CAAC,CAAC;gBACJ,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;oBACxB,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;oBACzC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC;oBACjD,IAAI,GAAG,EAAE,CAAC;wBACR,IAAI,CAAC,CAAC,YAAY;4BAAE,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC;oBAC9C,CAAC;yBAAM,CAAC;wBACN,MAAM,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;oBACrF,CAAC;gBACH,CAAC;gBACD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;gBAEnC,oCAAoC;gBACpC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBACtC,IAAI,CAAC,GAAG;oBAAE,OAAO;gBAEjB,uDAAuD;gBACvD,6DAA6D;gBAC7D,qCAAqC;gBACrC,MAAM,IAAI,GAAmB,MAAM;qBAChC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,GAAG,CAAC,SAAS,CAAC;qBAC1C,GAAG,CAAC,CAAC,CAAC,EAAE;oBACP,MAAM,WAAW,GAAG,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;oBAC9D,OAAO;wBACL,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,EAAE;wBAC1B,UAAU,EAAE,CAAC,CAAC,UAAU;wBACxB,OAAO,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,WAAW,SAAS,CAAC,CAAC,CAAC,WAAW;wBAC/D,SAAS,EAAE,CAAC,CAAC,EAAE;wBACf,SAAS,EAAE,CAAC,CAAC,SAAS;qBACvB,CAAC;gBACJ,CAAC,CAAC,CAAC;gBAEL,wDAAwD;gBACxD,kDAAkD;gBAClD,MAAM,MAAM,GAA4B,GAAG,CAAC,GAAG,IAAI;oBACjD,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,GAAG;oBAC/C,SAAS,EAAE,GAAG,CAAC,SAAS;oBACxB,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE;oBAC1B,QAAQ,EAAE,GAAG,CAAC,QAAQ;oBACtB,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE;iBAC1C,CAAC;gBACF,MAAM,KAAK,GAA4B,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;gBACzD,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;oBACrB,+CAA+C;oBAC/C,KAAK,CAAC,OAAO,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;gBACzC,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;gBAC7B,CAAC;gBACD,GAAG,CAAC,mBAAmB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,GAAG,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,eAAe,UAAU,EAAE,CAAC,CAAC;gBACxO,sDAAsD;gBACtD,IAAI,CAAC,UAAU;oBAAE,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;gBACjD,MAAM,CAAC,IAAI,CAAC,0BAA0B,GAAG,OAAO,OAAO,CAAC,MAAM,UAAU,SAAS,CAAC,MAAM,mBAAmB,CAAC,CAAC;gBAC7G,MAAM,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YAC9D,CAAC;iBAAM,CAAC;gBACN,2CAA2C;gBAC3C,MAAM,SAAS,GAAG,OAAO;qBACtB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;qBAC5C,MAAM,CAAC,OAAO,CAAC,CAAC;gBACnB,MAAM,OAAO,GAAc,EAAE,CAAC;gBAC9B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;oBACxB,MAAM,CAAC,GAAI,CAAC,CAAC,GAAmC,CAAC,WAAW,CAAC;oBAC7D,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;wBAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC3D,CAAC;gBACD,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAC9C,MAAM,IAAI,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC,GAAG,CAAC;gBACxC,MAAM,MAAM,GAA4B;oBACtC,GAAG,IAAI;oBACP,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC7B,WAAW,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;iBACtD,CAAC;gBACF,MAAM,CAAC,IAAI,CAAC,wBAAwB,MAAM,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,MAAM,mBAAmB,CAAC,CAAC;gBACvG,MAAM,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,wBAAwB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;IAED,OAAO,KAAK,EAAE,GAAsB,EAAE,IAAyB,EAAiB,EAAE;QAChF,MAAM,CAAC,GAAG,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,CAAC,CAAC,OAAO;YAAE,OAAO,IAAI,EAAE,CAAC;QAE9B,MAAM,GAAG,GAAG,GAAG,CAAC,OAA6C,CAAC;QAC9D,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QACpC,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK;YAAE,OAAO,IAAI,EAAE,CAAC;QAEtD,4CAA4C;QAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACjD,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,EAAE,CAAC;QAE3C,MAAM,YAAY,GACf,GAAG,CAAC,KAAkD,EAAE,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;QAC1F,iBAAiB;QACjB,IAAI,YAAY,IAAI,CAAC,CAAC,cAAc,KAAK,KAAK;YAAE,OAAO,IAAI,EAAE,CAAC;QAE9D,MAAM,MAAM,GAAG,IAAI,KAAK,OAAO;YAC7B,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,QAAQ,CAAC;YACnC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC;QACjB,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAExC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC;QAC7E,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC1E,IAAI,SAAS,IAAI,CAAC;YAAE,OAAO,IAAI,EAAE,CAAC,CAAC,mBAAmB;QAEtD,IAAI,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACtB,CAAC;QACD,4CAA4C;QAC5C,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YAC5B,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,+CAA+C;QAC/C,GAAG,CAAC,cAAc,GAAG,OAAO,SAAS,OAAO,MAAM,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,aAAa,EAAE,OAAO,MAAM,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,YAAY,YAAY,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACjN,wCAAwC;QACxC,gCAAgC;QAChC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,KAAK;gBAAE,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC;QACtC,CAAC;QACD,MAAM,OAAO,GAAG,EAAE,IAAI,KAAK,CAAC;QAC5B,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,GAAG,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC;QACtD,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,MAAM,QAAQ,OAAO,WAAW,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClJ,IAAI,OAAO,EAAE,CAAC;YACZ,0CAA0C;YAC1C,UAAU,CAAC,CAAC,CAAC,CAAC;YACd,CAAC,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,KAAK,CAAC,GAAG,EAAE,CAAmB,CAAC,EAAE,SAAS,CAAC,CAAC;YAC5E,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QACpB,CAAC;QAED,iBAAiB;QACjB,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,EAAE,CAAC;YAChC,KAAK,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QACD,kEAAkE;IACpE,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { setupMiddlewares } from './middleware-setup.js';
2
+ export { bootstrapGateway } from './bootstrap.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gateway/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { setupMiddlewares } from './middleware-setup.js';
2
+ export { bootstrapGateway } from './bootstrap.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gateway/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * SDK 中间件编排
3
+ *
4
+ * 根据插件配置组装 SDK 内置中间件链(洋葱模型)。
5
+ * 中间件负责过滤与上下文富化;最终消息统一由 bot.on('message') 处理转发。
6
+ */
7
+ import type { QQBot } from '@tencent-connect/qqbot-nodejs';
8
+ import type { ImQQBotConfig } from '../config.js';
9
+ import type { SessionManager } from '../session/index.js';
10
+ import type { Logger } from '../types.js';
11
+ export declare function setupMiddlewares(bot: QQBot, config: ImQQBotConfig, manager: SessionManager, logger: Logger): void;
12
+ //# sourceMappingURL=middleware-setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware-setup.d.ts","sourceRoot":"","sources":["../../src/gateway/middleware-setup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,KAAK,EAAqB,MAAM,+BAA+B,CAAC;AAa9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAY1C,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,KAAK,EACV,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,MAAM,GACb,IAAI,CAgKN"}
@@ -0,0 +1,156 @@
1
+ import { errorHandler, messageFilter, accessPolicy, mentionGate, contentSanitizer, slashCommand, concurrencyGuard, typingIndicator, quoteRef, envelopeFormatter, } from '@tencent-connect/qqbot-nodejs';
2
+ import { buildCommandList } from '../commands/index.js';
3
+ import { attachmentProcessor } from '../middleware/attachment.js';
4
+ import { mediaHistoryBuffer } from '../middleware/media-history.js';
5
+ import { stickerCapture } from '../middleware/sticker-capture.js';
6
+ import { getHistoryStore, historyGroupKey } from '../features/history-store.js';
7
+ import { stickerActivityRecorder } from '../features/sticker-gate.js';
8
+ import { chatLedgerRecorder } from '../features/chat-ledger.js';
9
+ import { debounceLayer } from './debounce.js';
10
+ import { faceTagResolver } from '../features/face-tags.js';
11
+ import { join } from 'node:path';
12
+ export function setupMiddlewares(bot, config, manager, logger) {
13
+ // 1. 错误兜底(最外层洋葱皮)
14
+ bot.use(errorHandler());
15
+ // 1.2 表情标签名字解析(本地实现, 2026-09-06): 必须挂在**最顶层**(任何历史/缓冲之前)——
16
+ // mediaHistoryBuffer(第4步)会把 content 原文存进群历史, AI 上下文读的是历史里的文本,
17
+ // 若解析放后面, 历史里存的就是 <faceType=...> 原文, AI 永远看不到名字。
18
+ // 这里把 <faceType=N,faceId="X",ext="b64"> / [<face,id=N/>] 转成【表情: 名字】:
19
+ // ext.text 优先(官方名字最准), 空则按 faceId 查 QQ 经典表情名表(0=微笑…160+),
20
+ // SDK contentSanitizer(parseFaceTags) 只解 ext.text, text 空会丢 faceId → 本层先吃掉标签。
21
+ bot.use(faceTagResolver());
22
+ // 1.5 消息串行闸(本地手改, 2026-09-05):
23
+ // SDK 收帧处 `void Promise.resolve(onMessage(...))` 不等待 → 快速连发时多条消息的
24
+ // 中间件链并发执行、在各 await 处交错 → 到达下游(历史缓冲/debounce/派发)的顺序
25
+ // ≠ 官方推送顺序(即真实发送序)。这里把每条消息的整条下游链排队串行:
26
+ // 前一条消息处理完才放行下一条, 恢复官方帧序。零 SDK 改动, 只作用于本 bot 实例。
27
+ // ⚠️ 本地手改功能, 同步纪律同群冷却中间件。
28
+ // ── 群普通消息"上次派发时刻"(冷却中间件与 debounce 融合层共享) ──
29
+ const lastDispatchAt = new Map(); // groupOpenid -> 上次普通派发时间(ms)
30
+ let inboundTail = Promise.resolve();
31
+ bot.use(async (_ctx, next) => {
32
+ const run = inboundTail.then(() => next());
33
+ inboundTail = run.catch(() => undefined);
34
+ await run;
35
+ });
36
+ // 2. 消息过滤:bot 回声 + 消息去重
37
+ bot.use(messageFilter({ skipSelfEcho: false }));
38
+ // 3. 访问控制(白名单/开放/禁用)
39
+ bot.use(accessPolicy({
40
+ c2c: {
41
+ mode: config.access.c2cMode,
42
+ allow: config.access.c2cAllow.length > 0 ? config.access.c2cAllow : ['*'],
43
+ },
44
+ group: {
45
+ mode: config.access.groupMode,
46
+ allow: config.access.groupAllow.length > 0 ? config.access.groupAllow : ['*'],
47
+ },
48
+ onBlock: (_mCtx, reason) => {
49
+ if (config.debug) {
50
+ logger.debug(`Access blocked: ${reason}`);
51
+ }
52
+ },
53
+ }));
54
+ // 4. 群历史缓冲 — 放在门控之前,确保所有消息(含未 @bot)都计入上下文
55
+ // store 走共享单例(getHistoryStore),groupKey 带 appId 前缀,供回复后清空
56
+ // ⚠️ 用增强版 mediaHistoryBuffer(本地手改,替代 SDK historyBuffer):
57
+ // 记历史时把带 URL 的附件折叠进 content,冷却期群友发的图/媒体在历史里也带链接
58
+ bot.use(mediaHistoryBuffer({
59
+ limit: config.historyLimit,
60
+ store: getHistoryStore(),
61
+ recordOnSkip: true,
62
+ groupKey: (ctx) => {
63
+ const gid = ctx.message.groupOpenid;
64
+ if (ctx.message.kind !== 'group' || !gid)
65
+ return undefined;
66
+ return historyGroupKey(config.appId, gid);
67
+ },
68
+ }));
69
+ // 4.5. 表情包自动收藏(P0):群图片 → 本地图库(fire-and-forget,不阻塞主链)
70
+ bot.use(stickerCapture(config, logger));
71
+ // 4.6. 表情包闸门活性计数(P1):记录所有群消息时间戳 → RingBuffer,供"热闹才发"判定。
72
+ // ⚠️ 必须在 mentionGate(第5步) 之前:未@消息被门控截断也照样计数。
73
+ // 多账号: 每实例传自己 dataDir(各号各闸门状态)。
74
+ bot.use(stickerActivityRecorder(config.sticker.dataDir || join(config.cwd || process.cwd(), '表情包')));
75
+ // 4.7. 聊天台账(M3):记录机器人见过的群/私聊(带昵称) → known-chats.jsonl,
76
+ // 供 Web ④区定时唤醒"点选聊天对象"(不用抄 openid)。也在 mentionGate 之前。
77
+ const ledgerDataDir = config.sticker.dataDir || join(config.cwd || process.cwd(), '表情包');
78
+ bot.use(chatLedgerRecorder(ledgerDataDir));
79
+ // 5. 群聊 @bot 门控
80
+ bot.use(mentionGate({
81
+ requireMentionInGroup: config.requireMention,
82
+ }));
83
+ // 6. 内容清洗(去 @marker、表情标签、多余空白)
84
+ bot.use(contentSanitizer({
85
+ parseFaceTags: true,
86
+ }));
87
+ // 6.6 延迟聚合(debounce)融合层(本地手改, 2026-09-05):在群冷却**之前**拦截。
88
+ // 消息(群普通/@ + 私聊)先进 per-peer 窗口攒着(不进冷却中间件), 最近说话者停口 X 秒
89
+ // 或攒满 Y 条 → 尝试派发一次: 群普通受 60s 冷却约束(未过则窗口保留继续等, 到点整批
90
+ // 按服务器时间序综合回, 不再出现"current 早于 history"的倒序); @ 消息无视冷却随时派发。
91
+ // debounce.enabled=false 或 @ 秒回(mentionDelayed=false)/斜杠命令 → 直放行, 交下方群冷却中间件
92
+ // 与既有链路处理(原 60s 冷却语义完整保留)。配置 config.behavior.debounce(live 热更)。
93
+ // ⚠️ 本地手改功能, 同步纪律同下方群冷却中间件。
94
+ bot.use(debounceLayer(config, manager, logger, lastDispatchAt));
95
+ // 7. 回复冷却调度(配置化, 替代写死 REPLY_COOLDOWN_MS=60000):照常接收并记录所有群消息
96
+ // (mediaHistoryBuffer 已在上方记录), 但每群按 config.behavior 间隔才真正派发一次给 AI。
97
+ // 注: debounce 开启时群消息被其拦截, 此中间件仅兜底 debounce 直放行的消息(命令/@秒回/功能关闭)。
98
+ // ⚠️ 本地手改功能(曾被重编译冲掉),改完务必保持 src 与部署 dist 同步。
99
+ // ⚠️ 每次调用现读 config.behavior(勿外层解构)——支持 Web settings live 热更新。
100
+ bot.use(async (ctx, next) => {
101
+ // 私聊/无群号:不纳入调度,直接放行
102
+ if (ctx.message.kind !== 'group' || !ctx.message.groupOpenid) {
103
+ return next();
104
+ }
105
+ const { freeIntervalSec, mentionIntervalSec } = config.behavior;
106
+ const gid = ctx.message.groupOpenid;
107
+ const wasMentioned = ctx.state.mention?.wasMentioned === true;
108
+ const intervalSec = wasMentioned ? mentionIntervalSec : freeIntervalSec;
109
+ // 适用间隔=0:不冷却直接放行(@立即回;无@放行后是否到 AI 由 requireMention 门控决定)
110
+ if (intervalSec <= 0) {
111
+ return next();
112
+ }
113
+ const now = Date.now();
114
+ const last = lastDispatchAt.get(gid) ?? 0;
115
+ if (now - last < intervalSec * 1000) {
116
+ // 冷却期内:消息已被 mediaHistoryBuffer 记进群历史,本次不派发 → 不调 next()
117
+ return;
118
+ }
119
+ // 冷却结束:派发当前消息。用独立的 batchDispatch 标记,让下游把累积的群历史一起打包
120
+ //(不伪装成 @you,避免出现假 (@you) 标签误导 AI)
121
+ lastDispatchAt.set(gid, now);
122
+ ctx.state.batchDispatch = true;
123
+ return next();
124
+ });
125
+ // 8. 斜杠命令(在 concurrencyGuard 之前,命令匹配后不排队直接响应)
126
+ const slash = slashCommand({
127
+ autoHelp: true,
128
+ commands: buildCommandList({ manager, config }),
129
+ });
130
+ bot.use(slash.middleware);
131
+ // 9. 并发串行 + 消息合并(同 peer 排队,避免 session 冲突)
132
+ bot.use(concurrencyGuard({
133
+ strategy: 'merge',
134
+ maxQueue: config.maxQueue,
135
+ maxProcessingMs: config.processingTimeoutMs,
136
+ urgentPredicate: (mCtx) => {
137
+ return (mCtx.message.content ?? '').trim() === '/bot-stop';
138
+ },
139
+ }));
140
+ // 10. C2C 输入状态指示
141
+ bot.use(typingIndicator());
142
+ // 11. 引用消息解析(记录 + 解析被引用原文)
143
+ bot.use(quoteRef({
144
+ maxSize: 500,
145
+ preferMsgElements: true,
146
+ }));
147
+ // 11.5. 附件下载(file 附件下载到本地,供 @提及 / 工具访问)
148
+ bot.use(attachmentProcessor(config, logger));
149
+ // 12. 上下文组装(将 history + quote + sender 组成 envelope)
150
+ bot.use(envelopeFormatter({
151
+ historyLimit: config.historyLimit,
152
+ includeQuote: true,
153
+ includeSender: true,
154
+ }));
155
+ }
156
+ //# sourceMappingURL=middleware-setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware-setup.js","sourceRoot":"","sources":["../../src/gateway/middleware-setup.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,QAAQ,EACR,iBAAiB,GAClB,MAAM,+BAA+B,CAAC;AAIvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,gBAAgB,CAC9B,GAAU,EACV,MAAqB,EACrB,OAAuB,EACvB,MAAc;IAEd,kBAAkB;IAClB,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC;IAExB,2DAA2D;IAC3D,kEAAkE;IAClE,qDAAqD;IACrD,yEAAyE;IACzE,8DAA8D;IAC9D,kFAAkF;IAClF,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC;IAE3B,+BAA+B;IAC/B,sEAAsE;IACtE,wDAAwD;IACxD,0CAA0C;IAC1C,qDAAqD;IACrD,8BAA8B;IAC9B,6CAA6C;IAC7C,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAC,8BAA8B;IAChF,IAAI,WAAW,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IACnD,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,IAAuB,EAAE,IAAyB,EAAE,EAAE;QACnE,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3C,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAkB,CAAC;QAC1D,MAAM,GAAG,CAAC;IACZ,CAAC,CAAC,CAAC;IAEH,wBAAwB;IACxB,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAEhD,qBAAqB;IACrB,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC;QACnB,GAAG,EAAE;YACH,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;YAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;SAC1E;QACD,KAAK,EAAE;YACL,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS;YAC7B,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;SAC9E;QACD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YACzB,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,MAAM,CAAC,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;KACF,CAAC,CAAC,CAAC;IAEJ,0CAA0C;IAC1C,6DAA6D;IAC7D,4DAA4D;IAC5D,sDAAsD;IACtD,GAAG,CAAC,GAAG,CAAC,kBAAkB,CAAC;QACzB,KAAK,EAAE,MAAM,CAAC,YAAY;QAC1B,KAAK,EAAE,eAAe,EAAE;QACxB,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE;YAChB,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC;YACpC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,GAAG;gBAAE,OAAO,SAAS,CAAC;YAC3D,OAAO,eAAe,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC5C,CAAC;KACF,CAAC,CAAC,CAAC;IAEJ,qDAAqD;IACrD,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAExC,wDAAwD;IACxD,iDAAiD;IACjD,oCAAoC;IACpC,GAAG,CAAC,GAAG,CAAC,uBAAuB,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAErG,uDAAuD;IACvD,0DAA0D;IAC1D,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;IACzF,GAAG,CAAC,GAAG,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC,CAAC;IAE3C,gBAAgB;IAChB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC;QAClB,qBAAqB,EAAE,MAAM,CAAC,cAAc;KAC7C,CAAC,CAAC,CAAC;IAEJ,+BAA+B;IAC/B,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACvB,aAAa,EAAE,IAAI;KACpB,CAAC,CAAC,CAAC;IAEJ,wDAAwD;IACxD,2DAA2D;IAC3D,uDAAuD;IACvD,8DAA8D;IAC9D,gFAAgF;IAChF,oEAAoE;IACpE,gCAAgC;IAChC,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;IAEhE,4DAA4D;IAC5D,sEAAsE;IACtE,mEAAmE;IACnE,gDAAgD;IAChD,iEAAiE;IACjE,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,GAAsB,EAAE,IAAyB,EAAE,EAAE;QAClE,oBAAoB;QACpB,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YAC7D,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QACD,MAAM,EAAE,eAAe,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC;QAChE,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC;QACpC,MAAM,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;QAC9D,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,eAAe,CAAC;QACxE,yDAAyD;QACzD,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC;YACrB,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,GAAG,GAAG,IAAI,GAAG,WAAW,GAAG,IAAI,EAAE,CAAC;YACpC,uDAAuD;YACvD,OAAO;QACT,CAAC;QACD,mDAAmD;QACnD,kCAAkC;QAClC,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC7B,GAAG,CAAC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;QAC/B,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,8CAA8C;IAC9C,MAAM,KAAK,GAAG,YAAY,CAAC;QACzB,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,gBAAgB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;KAChD,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAE1B,0CAA0C;IAC1C,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACvB,QAAQ,EAAE,OAAO;QACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,eAAe,EAAE,MAAM,CAAC,mBAAmB;QAC3C,eAAe,EAAE,CAAC,IAAuB,EAAE,EAAE;YAC3C,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,WAAW,CAAC;QAC7D,CAAC;KACF,CAAC,CAAC,CAAC;IAEJ,iBAAiB;IACjB,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC;IAE3B,2BAA2B;IAC3B,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC;QACf,OAAO,EAAE,GAAG;QACZ,iBAAiB,EAAE,IAAI;KACxB,CAAC,CAAC,CAAC;IAEJ,wCAAwC;IACxC,GAAG,CAAC,GAAG,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAE7C,oDAAoD;IACpD,GAAG,CAAC,GAAG,CAAC,iBAAiB,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,IAAI;KACpB,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * dsh-im-qqbot — QQ Bot IM channel plugin for deepseek-harness
3
+ *
4
+ * Cordis 插件入口。将 QQ 消息平台作为 dsh 的前端协议驱动。
5
+ * 网关组装(中间件编排 + 事件 + 出站 + 生命周期)见 src/gateway/。
6
+ */
7
+ import type { Context } from '@deepseek-ai/cordis';
8
+ import { type ImQQBotConfig } from './config.js';
9
+ export declare const name = "im-qqbot";
10
+ export declare const inject: string[];
11
+ export declare const Config: import("@deepseek-ai/schemastery").default<ImQQBotConfig>;
12
+ export type { ImQQBotConfig } from './config.js';
13
+ export declare function apply(ctx: Context, config: ImQQBotConfig): Promise<void>;
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAA2D,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAe1G,eAAO,MAAM,IAAI,aAAa,CAAC;AAC/B,eAAO,MAAM,MAAM,UAAa,CAAC;AACjC,eAAO,MAAM,MAAM,2DAAe,CAAC;AAEnC,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA4E9E"}