@zaofan/dsh-qqbot 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/qqbot-settings.js +571 -52
- package/dist/api/group-admin.d.ts +22 -0
- package/dist/api/group-admin.d.ts.map +1 -1
- package/dist/api/group-admin.js +32 -0
- package/dist/api/group-admin.js.map +1 -1
- package/dist/channel-tools.d.ts.map +1 -1
- package/dist/channel-tools.js +192 -77
- package/dist/channel-tools.js.map +1 -1
- package/dist/commands/botplay.d.ts.map +1 -1
- package/dist/commands/botplay.js +6 -2
- package/dist/commands/botplay.js.map +1 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +6 -2
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/inject.d.ts +17 -0
- package/dist/commands/inject.d.ts.map +1 -0
- package/dist/commands/inject.js +70 -0
- package/dist/commands/inject.js.map +1 -0
- package/dist/commands/misc.d.ts +1 -1
- package/dist/commands/misc.d.ts.map +1 -1
- package/dist/commands/misc.js +25 -3
- package/dist/commands/misc.js.map +1 -1
- package/dist/commands/session.d.ts +2 -0
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +41 -3
- package/dist/commands/session.js.map +1 -1
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/features/botplay-store.d.ts +13 -0
- package/dist/features/botplay-store.d.ts.map +1 -0
- package/dist/features/botplay-store.js +99 -0
- package/dist/features/botplay-store.js.map +1 -0
- package/dist/features/botplay.d.ts +8 -0
- package/dist/features/botplay.d.ts.map +1 -1
- package/dist/features/botplay.js +22 -7
- package/dist/features/botplay.js.map +1 -1
- package/dist/features/broadcast.d.ts +63 -0
- package/dist/features/broadcast.d.ts.map +1 -0
- package/dist/features/broadcast.js +225 -0
- package/dist/features/broadcast.js.map +1 -0
- package/dist/features/card-callback.d.ts +52 -0
- package/dist/features/card-callback.d.ts.map +1 -0
- package/dist/features/card-callback.js +133 -0
- package/dist/features/card-callback.js.map +1 -0
- package/dist/features/group-hub.d.ts +2 -0
- package/dist/features/group-hub.d.ts.map +1 -1
- package/dist/features/group-hub.js +2 -3
- package/dist/features/group-hub.js.map +1 -1
- package/dist/features/group-join-request.d.ts.map +1 -1
- package/dist/features/group-join-request.js +7 -1
- package/dist/features/group-join-request.js.map +1 -1
- package/dist/features/preset-switcher.d.ts +39 -0
- package/dist/features/preset-switcher.d.ts.map +1 -0
- package/dist/features/preset-switcher.js +172 -0
- package/dist/features/preset-switcher.js.map +1 -0
- package/dist/features/session-registry.d.ts +1 -1
- package/dist/features/session-registry.d.ts.map +1 -1
- package/dist/features/session-registry.js +30 -1
- package/dist/features/session-registry.js.map +1 -1
- package/dist/gateway/bootstrap.d.ts.map +1 -1
- package/dist/gateway/bootstrap.js +51 -4
- package/dist/gateway/bootstrap.js.map +1 -1
- package/dist/gateway/debounce.d.ts.map +1 -1
- package/dist/gateway/debounce.js +7 -0
- package/dist/gateway/debounce.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -5
- package/dist/index.js.map +1 -1
- package/dist/middleware/media-history.d.ts.map +1 -1
- package/dist/middleware/media-history.js +23 -6
- package/dist/middleware/media-history.js.map +1 -1
- package/dist/session/session-manager.d.ts +10 -0
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +45 -0
- package/dist/session/session-manager.js.map +1 -1
- package/dist/transport/inbound.d.ts.map +1 -1
- package/dist/transport/inbound.js +46 -50
- package/dist/transport/inbound.js.map +1 -1
- package/dist/transport/inject-rules.d.ts.map +1 -1
- package/dist/transport/inject-rules.js +8 -2
- package/dist/transport/inject-rules.js.map +1 -1
- package/dist/transport/media-kind.d.ts +37 -0
- package/dist/transport/media-kind.d.ts.map +1 -0
- package/dist/transport/media-kind.js +60 -0
- package/dist/transport/media-kind.js.map +1 -0
- package/dist/transport/outbound-buffer.d.ts +20 -2
- package/dist/transport/outbound-buffer.d.ts.map +1 -1
- package/dist/transport/outbound-buffer.js +25 -5
- package/dist/transport/outbound-buffer.js.map +1 -1
- package/dist/transport/outbound.d.ts.map +1 -1
- package/dist/transport/outbound.js +68 -4
- package/dist/transport/outbound.js.map +1 -1
- package/package.json +1 -1
- package/settings-host.js +401 -20
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inject-rules.d.ts","sourceRoot":"","sources":["../../src/transport/inject-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"inject-rules.d.ts","sourceRoot":"","sources":["../../src/transport/inject-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMzD,mBAAmB;AACnB,UAAU,OAAO;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,aAAa,EAAE,CAAC;CAC/B;AAoDD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,gBAAgB,EAAE,GAAG,SAAS,EACrC,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAmBR"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { inferMediaKind } from './media-kind.js';
|
|
1
2
|
/** 单轮累计注入预算(字符), 防爆上下文 */
|
|
2
3
|
const BUDGET_CHARS = 1500;
|
|
3
4
|
/** 原写死读图提示(内置兜底规则: 用户未配任何 enabled 的 hasImage 规则时自动追加) */
|
|
@@ -13,9 +14,14 @@ const LEGACY_IMAGE_RULE = {
|
|
|
13
14
|
},
|
|
14
15
|
prompt: '上方消息包含图片链接(URL),请直接把该URL传给桥接视觉工具(modlens_read_image / analyze_image)看图并描述内容,不要只复述链接。',
|
|
15
16
|
};
|
|
16
|
-
/**
|
|
17
|
+
/** 消息是否含附件图片。
|
|
18
|
+
* ⚠️ 2026-09-10 根因修复(主人实测:自定义小提醒配了「消息里带图片」却**永不触发**):
|
|
19
|
+
* QQ 群聊里图片附件的 `content_type` 实测是 `'file'`(不是 `image/jpeg`),
|
|
20
|
+
* 原判定要求 content_type 含 'image' 或 URL 带图片扩展名 —— 两条都不成立 → hasImage=false
|
|
21
|
+
* → 规则不命中;又因"存在启用的 hasImage 规则"而不追加内置兜底 → 读图提示彻底消失。
|
|
22
|
+
* 现统一走 inbound 同款 `inferMediaKind()`(单一真源),不再各写一份判定。 */
|
|
17
23
|
function hasImage(msg) {
|
|
18
|
-
return (msg.attachments ?? []).some(a =>
|
|
24
|
+
return (msg.attachments ?? []).some(a => !!a.url && inferMediaKind(a) === 'image');
|
|
19
25
|
}
|
|
20
26
|
/** 消息正文是否含 http(s) 链接 */
|
|
21
27
|
function hasLink(text) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inject-rules.js","sourceRoot":"","sources":["../../src/transport/inject-rules.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"inject-rules.js","sourceRoot":"","sources":["../../src/transport/inject-rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* media-kind.ts — 附件真实媒体类型推断(单一真源)
|
|
3
|
+
*
|
|
4
|
+
* ⚠️ 2026-09-10 根因修复(主人实测 + dock 接口取证):
|
|
5
|
+
* QQ 群消息里「图片 / 视频」附件的 `content_type` 实测为 `'file'`(**不是** 'image'/'video'),
|
|
6
|
+
* 直接按 content_type 分支会让图片和视频全程被当文件:
|
|
7
|
+
* ① Layer 1 `describeAttachments` 只给 `[File: 名 (大小)]`;
|
|
8
|
+
* ② Layer 4 给 `- File: 名 → url`;
|
|
9
|
+
* ③ dock(chatAttachmentKind 见 `- File:`) 渲染成 `📎 download` —— 图片不显示、视频不能播;
|
|
10
|
+
* ④ `inject-rules` 的 hasImage() 依赖 content_type 含 'image' → 读图小提醒**永不触发**。
|
|
11
|
+
* 取证: GET /api/qqbot-settings/chat/history 返回
|
|
12
|
+
* {kind:'file', name:'download', url:'https://multimedia.nt.qq.com.cn/download?appid=1415&format=origin&orgfmt=t264…'}
|
|
13
|
+
* (name='download' 只能出自 chatFileDisplayName(URL 尾段),即 dock 走了 `- File:` 分支。)
|
|
14
|
+
*
|
|
15
|
+
* 因此类型判定必须综合多路证据,**不能盲信 content_type**:
|
|
16
|
+
* MIME → 文件名/URL 扩展名 → 宽高(QQ 只给图片带尺寸) → QQ 媒体 URL 特征(appid/orgfmt)。
|
|
17
|
+
*/
|
|
18
|
+
import type { RawAttachment } from '../types.js';
|
|
19
|
+
/** 归一化后的媒体类型(inbound / 历史折叠 / 类型推断 共用的四种) */
|
|
20
|
+
export type MediaKind = 'image' | 'video' | 'voice' | 'file';
|
|
21
|
+
/** 推断所需的最小形状:RawAttachment 与 media-history 的折叠对象都能直接传入 */
|
|
22
|
+
export interface KindableAttachment {
|
|
23
|
+
content_type?: string;
|
|
24
|
+
filename?: string;
|
|
25
|
+
url?: string;
|
|
26
|
+
width?: number;
|
|
27
|
+
height?: number;
|
|
28
|
+
asr_refer_text?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 推断附件的真实媒体类型。
|
|
32
|
+
* 顺序即优先级:显式 MIME > 扩展名 > 宽高 > QQ URL 特征 > 兜底 file。
|
|
33
|
+
*/
|
|
34
|
+
export declare function inferMediaKind(att: KindableAttachment | RawAttachment): MediaKind;
|
|
35
|
+
/** 人类可读的类型名(写进 AI 上下文用) */
|
|
36
|
+
export declare function mediaKindLabel(kind: MediaKind): string;
|
|
37
|
+
//# sourceMappingURL=media-kind.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-kind.d.ts","sourceRoot":"","sources":["../../src/transport/media-kind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,6CAA6C;AAC7C,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7D,0DAA0D;AAC1D,MAAM,WAAW,kBAAkB;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAaD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,kBAAkB,GAAG,aAAa,GAAG,SAAS,CA8BjF;AAED,2BAA2B;AAC3B,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAOtD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// 扩展名匹配: 后面必须是查询串/锚点/空白/结尾 —— 因为判定用的 haystack 是
|
|
2
|
+
// `${filename} ${url}` 的拼接串, 文件名后面紧跟的是空格而不是行尾(踩坑: 漏了 \s 会导致 .mp4 判不出视频)
|
|
3
|
+
const EXT_IMAGE = /\.(?:jpe?g|png|gif|webp|bmp|heic|heif|avif|tiff?)(?:[?#\s]|$)/i;
|
|
4
|
+
const EXT_VIDEO = /\.(?:mp4|mov|m4v|webm|avi|mkv|flv|wmv|mpe?g|3gp)(?:[?#\s]|$)/i;
|
|
5
|
+
const EXT_VOICE = /\.(?:silk|amr|mp3|wav|ogg|oga|opus|m4a|aac|flac|wma)(?:[?#\s]|$)/i;
|
|
6
|
+
/** QQ 富媒体下载 URL 的业务 appid(实测样本: 1403 语音 / 1407 图片 / 1415 视频) */
|
|
7
|
+
const APPID_VOICE = new Set(['1403']);
|
|
8
|
+
const APPID_IMAGE = new Set(['1406', '1407']);
|
|
9
|
+
const APPID_VIDEO = new Set(['1415']);
|
|
10
|
+
/**
|
|
11
|
+
* 推断附件的真实媒体类型。
|
|
12
|
+
* 顺序即优先级:显式 MIME > 扩展名 > 宽高 > QQ URL 特征 > 兜底 file。
|
|
13
|
+
*/
|
|
14
|
+
export function inferMediaKind(att) {
|
|
15
|
+
const ct = String(att.content_type ?? '').toLowerCase().trim();
|
|
16
|
+
// ① 显式类型 / MIME(语音最可靠:官方给 'voice')
|
|
17
|
+
if (ct === 'voice' || ct.startsWith('audio/'))
|
|
18
|
+
return 'voice';
|
|
19
|
+
if (ct === 'image' || ct.startsWith('image/'))
|
|
20
|
+
return 'image';
|
|
21
|
+
if (ct === 'video' || ct.startsWith('video/'))
|
|
22
|
+
return 'video';
|
|
23
|
+
// ② 文件名 / URL 扩展名(次可靠)
|
|
24
|
+
const hay = `${att.filename ?? ''} ${att.url ?? ''}`;
|
|
25
|
+
if (EXT_IMAGE.test(hay))
|
|
26
|
+
return 'image';
|
|
27
|
+
if (EXT_VIDEO.test(hay))
|
|
28
|
+
return 'video';
|
|
29
|
+
if (EXT_VOICE.test(hay))
|
|
30
|
+
return 'voice';
|
|
31
|
+
// ③ 带宽高 → 图片(QQ 只在图片附件上给 width/height)
|
|
32
|
+
if (att.width && att.height)
|
|
33
|
+
return 'image';
|
|
34
|
+
// ④ QQ 媒体下载 URL 特征
|
|
35
|
+
const url = String(att.url ?? '');
|
|
36
|
+
if (url) {
|
|
37
|
+
// orgfmt= 是"原始编码格式"参数,视频实测带 orgfmt=t264(H.264);图片 URL 没有该参数
|
|
38
|
+
if (/[?&]orgfmt=/i.test(url))
|
|
39
|
+
return 'video';
|
|
40
|
+
const appid = (url.match(/[?&]appid=(\d+)/) ?? [])[1];
|
|
41
|
+
if (appid && APPID_VOICE.has(appid))
|
|
42
|
+
return 'voice';
|
|
43
|
+
if (appid && APPID_IMAGE.has(appid))
|
|
44
|
+
return 'image';
|
|
45
|
+
if (appid && APPID_VIDEO.has(appid))
|
|
46
|
+
return 'video';
|
|
47
|
+
}
|
|
48
|
+
// ⑤ 兜底:content_type='file' 或未知 → 文件
|
|
49
|
+
return 'file';
|
|
50
|
+
}
|
|
51
|
+
/** 人类可读的类型名(写进 AI 上下文用) */
|
|
52
|
+
export function mediaKindLabel(kind) {
|
|
53
|
+
switch (kind) {
|
|
54
|
+
case 'image': return 'Image';
|
|
55
|
+
case 'video': return 'Video';
|
|
56
|
+
case 'voice': return 'Voice';
|
|
57
|
+
default: return 'File';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=media-kind.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-kind.js","sourceRoot":"","sources":["../../src/transport/media-kind.ts"],"names":[],"mappings":"AAgCA,gDAAgD;AAChD,wEAAwE;AACxE,MAAM,SAAS,GAAG,gEAAgE,CAAC;AACnF,MAAM,SAAS,GAAG,+DAA+D,CAAC;AAClF,MAAM,SAAS,GAAG,mEAAmE,CAAC;AAEtF,gEAAgE;AAChE,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AACtC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAC9C,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAEtC;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAAuC;IACpE,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAE/D,mCAAmC;IACnC,IAAI,EAAE,KAAK,OAAO,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,OAAO,CAAC;IAC9D,IAAI,EAAE,KAAK,OAAO,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,OAAO,CAAC;IAC9D,IAAI,EAAE,KAAK,OAAO,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,OAAO,CAAC;IAE9D,uBAAuB;IACvB,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,QAAQ,IAAI,EAAE,IAAI,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC;IACrD,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IAExC,uCAAuC;IACvC,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC;IAE5C,mBAAmB;IACnB,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;IAClC,IAAI,GAAG,EAAE,CAAC;QACR,4DAA4D;QAC5D,IAAI,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,OAAO,CAAC;QAC7C,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,IAAI,KAAK,IAAI,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC;QACpD,IAAI,KAAK,IAAI,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC;QACpD,IAAI,KAAK,IAAI,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC;IACtD,CAAC;IAED,oCAAoC;IACpC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,2BAA2B;AAC3B,MAAM,UAAU,cAAc,CAAC,IAAe;IAC5C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO,CAAC,CAAC,OAAO,OAAO,CAAC;QAC7B,KAAK,OAAO,CAAC,CAAC,OAAO,OAAO,CAAC;QAC7B,KAAK,OAAO,CAAC,CAAC,OAAO,OAAO,CAAC;QAC7B,OAAO,CAAC,CAAC,OAAO,MAAM,CAAC;IACzB,CAAC;AACH,CAAC"}
|
|
@@ -28,6 +28,8 @@ export interface QQBotSender {
|
|
|
28
28
|
recallLast(target: ReplyTarget): Promise<boolean>;
|
|
29
29
|
/** 撤本 bot 发给该 peer 的最近第 index 条(index=1 最近一条, 2 倒数第二条...);成功返回 true */
|
|
30
30
|
recallByIndex(target: ReplyTarget, index: number): Promise<boolean>;
|
|
31
|
+
/** c2c 主动召回消息(官方 is_wakeup:true, 30天窗; 群聊目标应走 sendMarkdown)。2026-09-10 修跨会话 c2c 发送 */
|
|
32
|
+
sendC2cWakeup(target: ReplyTarget, content: string): Promise<unknown>;
|
|
31
33
|
}
|
|
32
34
|
/**
|
|
33
35
|
* 富媒体感知发送一段完整文本:
|
|
@@ -39,7 +41,15 @@ export interface QQBotSender {
|
|
|
39
41
|
* 用于「适配主动」出站: 同一条入站消息的连续回复数到限后自动切主动(去掉 msg_id)。
|
|
40
42
|
* 注意: [RECALL] 撤回动作不消耗计数, 固定用传入 target。
|
|
41
43
|
*/
|
|
42
|
-
export declare function sendRichOutbound(bot: QQBotSender, target: ReplyTarget, text: string, limit: number, cwd: string | undefined, logError?: (msg: string) => void, resolveTarget?: () => ReplyTarget
|
|
44
|
+
export declare function sendRichOutbound(bot: QQBotSender, target: ReplyTarget, text: string, limit: number, cwd: string | undefined, logError?: (msg: string) => void, resolveTarget?: () => ReplyTarget,
|
|
45
|
+
/** 逐文本块目标(2026-09-10 主人定 passive 收尾): 传 (块序号i, 总块数total)=>ReplyTarget,
|
|
46
|
+
* 用于「正文块>5 时第 6 块起转主动发送」; undefined=所有块用 resolveTarget/固定 target */
|
|
47
|
+
chunkTarget?: (i: number, total: number) => ReplyTarget,
|
|
48
|
+
/** 每成功发出一个正文块后回调(2026-09-10 主人定 passive 收尾 A 方案): outbound.ts 用它统计
|
|
49
|
+
* 「**同一个 msg_id 下**已发出几个正文块」, 回合结束时决定是否把最后一块复制一份主动补发。
|
|
50
|
+
* 带上 target 是因为 QQ 的被动回复 5 条上限**按 msg_id 计** —— msg_id 一变(群友中途发言)
|
|
51
|
+
* 配额即重置, 计数必须跟着归零, 否则会误补发(2026-09-10 主人指出)。 */
|
|
52
|
+
onBlockSent?: (text: string, target: ReplyTarget) => void): Promise<void>;
|
|
43
53
|
export declare class OutboundBuffer {
|
|
44
54
|
private readonly record;
|
|
45
55
|
private readonly bot;
|
|
@@ -47,10 +57,18 @@ export declare class OutboundBuffer {
|
|
|
47
57
|
private readonly logger;
|
|
48
58
|
private readonly cwd;
|
|
49
59
|
private readonly resolveTarget?;
|
|
60
|
+
/** 逐文本块目标(2026-09-10 passive 收尾; 正文块>5 第6块起转主动) */
|
|
61
|
+
private readonly chunkTarget?;
|
|
62
|
+
/** 每成功发出一个正文块后回调(见 sendRichOutbound 同名参数) */
|
|
63
|
+
private readonly onBlockSent?;
|
|
50
64
|
private buffer;
|
|
51
65
|
private flushing;
|
|
52
66
|
private readonly writer;
|
|
53
|
-
constructor(record: SessionRecord, bot: QQBotSender, limit: number, logger: Logger, streamingEnabled: boolean, cwd?: string | undefined, resolveTarget?: (() => ReplyTarget) | undefined
|
|
67
|
+
constructor(record: SessionRecord, bot: QQBotSender, limit: number, logger: Logger, streamingEnabled: boolean, cwd?: string | undefined, resolveTarget?: (() => ReplyTarget) | undefined,
|
|
68
|
+
/** 逐文本块目标(2026-09-10 passive 收尾; 正文块>5 第6块起转主动) */
|
|
69
|
+
chunkTarget?: ((i: number, total: number) => ReplyTarget) | undefined,
|
|
70
|
+
/** 每成功发出一个正文块后回调(见 sendRichOutbound 同名参数) */
|
|
71
|
+
onBlockSent?: ((text: string, target: ReplyTarget) => void) | undefined);
|
|
54
72
|
/** 追加文本增量 */
|
|
55
73
|
append(text: string): void;
|
|
56
74
|
/** 获取当前累积文本 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbound-buffer.d.ts","sourceRoot":"","sources":["../../src/transport/outbound-buffer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAevD,6BAA6B;AAC7B,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1C,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9B;AAED,kBAAkB;AAClB,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrE,mDAAmD;IACnD,wBAAwB,CACtB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,OAAO,GAChB,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,CAAC;IACnD,yDAAyD;IACzD,SAAS,CACP,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,EAC1C,MAAM,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3C,OAAO,CAAC;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5B,sCAAsC;IACtC,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,uEAAuE;IACvE,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"outbound-buffer.d.ts","sourceRoot":"","sources":["../../src/transport/outbound-buffer.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,7 +14,15 @@ const STREAM_THROTTLE_MS = 200;
|
|
|
14
14
|
* 用于「适配主动」出站: 同一条入站消息的连续回复数到限后自动切主动(去掉 msg_id)。
|
|
15
15
|
* 注意: [RECALL] 撤回动作不消耗计数, 固定用传入 target。
|
|
16
16
|
*/
|
|
17
|
-
export async function sendRichOutbound(bot, target, text, limit, cwd, logError, resolveTarget
|
|
17
|
+
export async function sendRichOutbound(bot, target, text, limit, cwd, logError, resolveTarget,
|
|
18
|
+
/** 逐文本块目标(2026-09-10 主人定 passive 收尾): 传 (块序号i, 总块数total)=>ReplyTarget,
|
|
19
|
+
* 用于「正文块>5 时第 6 块起转主动发送」; undefined=所有块用 resolveTarget/固定 target */
|
|
20
|
+
chunkTarget,
|
|
21
|
+
/** 每成功发出一个正文块后回调(2026-09-10 主人定 passive 收尾 A 方案): outbound.ts 用它统计
|
|
22
|
+
* 「**同一个 msg_id 下**已发出几个正文块」, 回合结束时决定是否把最后一块复制一份主动补发。
|
|
23
|
+
* 带上 target 是因为 QQ 的被动回复 5 条上限**按 msg_id 计** —— msg_id 一变(群友中途发言)
|
|
24
|
+
* 配额即重置, 计数必须跟着归零, 否则会误补发(2026-09-10 主人指出)。 */
|
|
25
|
+
onBlockSent) {
|
|
18
26
|
const eff = () => (resolveTarget ? resolveTarget() : target);
|
|
19
27
|
const hasRecall = containsRecall(text);
|
|
20
28
|
const displayable = stripDirectives(text);
|
|
@@ -73,8 +81,12 @@ export async function sendRichOutbound(bot, target, text, limit, cwd, logError,
|
|
|
73
81
|
const chunks = chunkMarkdownText(clean, limit).map((c) => String(c || '')).filter((c) => c.trim());
|
|
74
82
|
for (let ci = 0; ci < chunks.length; ci++) {
|
|
75
83
|
const chunk = chunks[ci];
|
|
76
|
-
if (chunk.trim())
|
|
77
|
-
|
|
84
|
+
if (!chunk.trim())
|
|
85
|
+
continue;
|
|
86
|
+
// 逐块目标: passive 收尾(正文块>5 第6块起转主动)由 chunkTarget 决定; 缺省用 eff()
|
|
87
|
+
const tgt = chunkTarget ? chunkTarget(ci, chunks.length) : eff();
|
|
88
|
+
await bot.sendMarkdown(tgt, chunk);
|
|
89
|
+
onBlockSent?.(chunk, tgt);
|
|
78
90
|
if (ci < chunks.length - 1)
|
|
79
91
|
await new Promise((r) => setTimeout(r, 500));
|
|
80
92
|
}
|
|
@@ -88,16 +100,24 @@ export class OutboundBuffer {
|
|
|
88
100
|
logger;
|
|
89
101
|
cwd;
|
|
90
102
|
resolveTarget;
|
|
103
|
+
chunkTarget;
|
|
104
|
+
onBlockSent;
|
|
91
105
|
buffer = '';
|
|
92
106
|
flushing = false;
|
|
93
107
|
writer;
|
|
94
|
-
constructor(record, bot, limit, logger, streamingEnabled, cwd = undefined, resolveTarget
|
|
108
|
+
constructor(record, bot, limit, logger, streamingEnabled, cwd = undefined, resolveTarget,
|
|
109
|
+
/** 逐文本块目标(2026-09-10 passive 收尾; 正文块>5 第6块起转主动) */
|
|
110
|
+
chunkTarget,
|
|
111
|
+
/** 每成功发出一个正文块后回调(见 sendRichOutbound 同名参数) */
|
|
112
|
+
onBlockSent) {
|
|
95
113
|
this.record = record;
|
|
96
114
|
this.bot = bot;
|
|
97
115
|
this.limit = limit;
|
|
98
116
|
this.logger = logger;
|
|
99
117
|
this.cwd = cwd;
|
|
100
118
|
this.resolveTarget = resolveTarget;
|
|
119
|
+
this.chunkTarget = chunkTarget;
|
|
120
|
+
this.onBlockSent = onBlockSent;
|
|
101
121
|
this.writer = streamingEnabled
|
|
102
122
|
? new StreamingWriter({ bot, target: record.replyTarget, logger, throttleMs: STREAM_THROTTLE_MS })
|
|
103
123
|
: null;
|
|
@@ -124,7 +144,7 @@ export class OutboundBuffer {
|
|
|
124
144
|
return;
|
|
125
145
|
}
|
|
126
146
|
// 降级:静态发送(writer 不存在 or 流式失败)→ 富媒体感知发送
|
|
127
|
-
await sendRichOutbound(this.bot, this.record.replyTarget, this.buffer, this.limit, this.cwd, (m) => this.logger.error(m), this.resolveTarget);
|
|
147
|
+
await sendRichOutbound(this.bot, this.record.replyTarget, this.buffer, this.limit, this.cwd, (m) => this.logger.error(m), this.resolveTarget, this.chunkTarget, this.onBlockSent);
|
|
128
148
|
}
|
|
129
149
|
catch (err) {
|
|
130
150
|
this.logger.error(`im-qqbot: flush failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbound-buffer.js","sourceRoot":"","sources":["../../src/transport/outbound-buffer.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE,wCAAwC;AACxC,MAAM,kBAAkB,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"outbound-buffer.js","sourceRoot":"","sources":["../../src/transport/outbound-buffer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbound.d.ts","sourceRoot":"","sources":["../../src/transport/outbound.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,qBAAqB,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,aAAa,CAAC;AACvD,OAAO,EAAoC,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EAAoB,KAAK,iBAAiB,EAAuB,MAAM,qBAAqB,CAAC;AACpG,OAAO,EAQL,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,2CAA2C;AAC3C,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;AAErF,uBAAuB;AACvB,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CACxB;
|
|
1
|
+
{"version":3,"file":"outbound.d.ts","sourceRoot":"","sources":["../../src/transport/outbound.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,qBAAqB,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,aAAa,CAAC;AACvD,OAAO,EAAoC,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EAAoB,KAAK,iBAAiB,EAAuB,MAAM,qBAAqB,CAAC;AACpG,OAAO,EAQL,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,2CAA2C;AAC3C,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;AAErF,uBAAuB;AACvB,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CACxB;AA+RD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,cAAc,EACvB,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,iBAAiB,GAChC,eAAe,CAGjB"}
|
|
@@ -20,6 +20,10 @@ class OutboundRouter {
|
|
|
20
20
|
toolCalls = new Map();
|
|
21
21
|
/** 适配主动状态: sessionKey → 当前入站 msg_id 及已被动回复条数 */
|
|
22
22
|
adaptiveState = new Map();
|
|
23
|
+
/** passive 收尾(2026-09-10 主人定 A 方案): **同一个 msg_id 下**已发出的正文块计数 + 最后一块文本。
|
|
24
|
+
* ⚠️ 必须按 msgId 分组: QQ 的被动回复 5 条上限是**按 msg_id 计**的, 群友中途发言会让
|
|
25
|
+
* record.replyTarget 换成新 msgId、配额随之重置 —— 那时后面的块本来就送得到, 不该再补发。 */
|
|
26
|
+
turnBlocks = new Map();
|
|
23
27
|
constructor(manager, bot, config, logger, toolsRegistry) {
|
|
24
28
|
this.manager = manager;
|
|
25
29
|
this.bot = bot;
|
|
@@ -28,7 +32,9 @@ class OutboundRouter {
|
|
|
28
32
|
this.toolsRegistry = toolsRegistry;
|
|
29
33
|
}
|
|
30
34
|
/** 出站目标(每次实际发送前逐条调用, [RECALL] 除外):
|
|
31
|
-
* passive → 一律带 msg_id
|
|
35
|
+
* passive → 一律带 msg_id 回复(其余行为不变; 唯一例外: 回合主回复正文块>5 时
|
|
36
|
+
* 第 6 块起转主动, 见 chunkTargetFn——2026-09-10 主人定);
|
|
37
|
+
* adaptive(默认)/active → 智能: 最近 5 分钟内收到过消息
|
|
32
38
|
* (lastActivity 新鲜)且同一条入站消息(msg_id)回复未超过 ADAPTIVE_MAX_PASSIVE 条 → 带 msg_id
|
|
33
39
|
* 被动回复(有引用感); 超出/无近期入站(定时推送等) → 自动去 msg_id 转主动(防 QQ 吞/引用失效)。
|
|
34
40
|
* 新入站消息(msg_id 变化)自动重置被动配额。 */
|
|
@@ -57,6 +63,55 @@ class OutboundRouter {
|
|
|
57
63
|
// 已连续被动 5 条 → 本条起转主动(去掉 msg_id, 不再被 QQ 回复上限吞)
|
|
58
64
|
return { scope: rt.scope, targetId: rt.targetId };
|
|
59
65
|
}
|
|
66
|
+
/** 主动目标(去 msg_id 独立发送): 回合主回复正文块>5 时的收尾块用 */
|
|
67
|
+
activeTarget(record) {
|
|
68
|
+
const rt = record.replyTarget;
|
|
69
|
+
return { scope: rt.scope, targetId: rt.targetId };
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 回合主回复的「块级目标」: passive 模式正文块>5 时仅最后一块(总结)转主动发送,
|
|
73
|
+
* 中途不改模式(前 total-1 块全被动带引用) —— 2026-09-10 主人最终语义:
|
|
74
|
+
* 回合结束判断最后一个正文块>5 → 获取其内容单独主动发到 QQ。
|
|
75
|
+
* 返回 undefined = 不启用(adaptive 走自身 resolveTarget 计数, 无需此处干预)。
|
|
76
|
+
*/
|
|
77
|
+
chunkTargetFn(record) {
|
|
78
|
+
if ((this.config.outboundMode || 'adaptive') !== 'passive')
|
|
79
|
+
return undefined;
|
|
80
|
+
return (i, total) => (total > 5 && i === total - 1) ? this.activeTarget(record) : this.resolveTarget(record);
|
|
81
|
+
}
|
|
82
|
+
/** 记账(**生成侧**, 2026-09-10 修正): 每产生一块正文就登记, **与发送成败解耦**。
|
|
83
|
+
* ⚠️ 原实现挂在「发送成功之后」(sendRichOutbound 的 onBlockSent), 一旦 QQ 吞消息
|
|
84
|
+
* (在这里表现为 sendMarkdown 抛错), await 就炸 → 记账中断(实测 count 停在第 4 条, 补发永不触发)。
|
|
85
|
+
* 按 msgId 分组: 同一 msgId 才算同一批被动回复配额, msgId 变化(群友中途发言)即重新计数。 */
|
|
86
|
+
noteGenerated(sessionKey, msgId, text) {
|
|
87
|
+
const cur = this.turnBlocks.get(sessionKey);
|
|
88
|
+
if (!cur || cur.msgId !== msgId) {
|
|
89
|
+
this.turnBlocks.set(sessionKey, { msgId, count: 1, last: text });
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
cur.count += 1;
|
|
93
|
+
cur.last = text;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* passive 回合收尾(2026-09-10 主人定 **A 方案**):
|
|
97
|
+
* **同一个 msg_id 下**发出的正文块 > 5 时, 把**最后一块的文本复制一份**, 用主动目标(去掉
|
|
98
|
+
* msg_id)单独再发一次 —— QQ 对同一条入站消息的被动回复上限约 5 条, 前 5 块之后的可能被吞,
|
|
99
|
+
* 而最后一块通常是结论/总结, 值得保住。
|
|
100
|
+
* ⚠️ 计数按 msgId 分组: 群友中途发言 → msgId 变 → 5 条配额重置 → 后面的块送得到 → **不补发**
|
|
101
|
+
* (2026-09-10 主人指出原按"回合总块数"判定会白白重复推一条)。
|
|
102
|
+
* 注: adaptive 模式本身「第 6 条起自动转主动」= 主人说的 B 方案, 已内建, 故此处只处理 passive。
|
|
103
|
+
*/
|
|
104
|
+
maybeResendLastBlock(sessionKey, record) {
|
|
105
|
+
const st = this.turnBlocks.get(sessionKey);
|
|
106
|
+
this.turnBlocks.delete(sessionKey);
|
|
107
|
+
if (!st)
|
|
108
|
+
return;
|
|
109
|
+
if ((this.config.outboundMode || 'adaptive') !== 'passive')
|
|
110
|
+
return;
|
|
111
|
+
if (st.count <= 5 || !st.last.trim())
|
|
112
|
+
return;
|
|
113
|
+
void this.bot.sendMarkdown(this.activeTarget(record), st.last).then(() => this.logger.info(`im-qqbot: [passive 收尾] 回合正文 ${st.count} 块 > 5, 已把最后一块单独补发(主动)`), (err) => this.logger.warn(`im-qqbot: [passive 收尾] 最后一块补发失败: ${err instanceof Error ? err.message : String(err)}`));
|
|
114
|
+
}
|
|
60
115
|
/** 事件分发入口 */
|
|
61
116
|
route(session, raw) {
|
|
62
117
|
const event = parseEvent(raw);
|
|
@@ -109,7 +164,7 @@ class OutboundRouter {
|
|
|
109
164
|
onChunk(sessionId, record, event) {
|
|
110
165
|
let buffer = this.buffers.get(sessionId);
|
|
111
166
|
if (buffer === undefined) {
|
|
112
|
-
buffer = new OutboundBuffer(record, this.bot, this.config.textChunkLimit, this.logger, this.shouldStream(record), this.config.cwd, () => this.resolveTarget(record));
|
|
167
|
+
buffer = new OutboundBuffer(record, this.bot, this.config.textChunkLimit, this.logger, this.shouldStream(record), this.config.cwd, () => this.resolveTarget(record), this.chunkTargetFn(record));
|
|
113
168
|
this.buffers.set(sessionId, buffer);
|
|
114
169
|
}
|
|
115
170
|
buffer.append(event.text);
|
|
@@ -124,6 +179,8 @@ class OutboundRouter {
|
|
|
124
179
|
onMessage(sessionId, record, event) {
|
|
125
180
|
const buffer = this.buffers.get(sessionId);
|
|
126
181
|
if (buffer !== undefined && buffer.text.trim()) {
|
|
182
|
+
// 记账放**生成侧**(不看发送成败): 这块正文已经产生了, 就该入账
|
|
183
|
+
this.noteGenerated(record.sessionKey, record.replyTarget.msgId ?? '', buffer.text);
|
|
127
184
|
void buffer.flush();
|
|
128
185
|
this.buffers.delete(sessionId);
|
|
129
186
|
return;
|
|
@@ -136,6 +193,7 @@ class OutboundRouter {
|
|
|
136
193
|
const fullText = textParts.join('\n');
|
|
137
194
|
if (!fullText.trim())
|
|
138
195
|
return;
|
|
196
|
+
this.noteGenerated(record.sessionKey, record.replyTarget.msgId ?? '', fullText);
|
|
139
197
|
void this.send(record, fullText, 'sendMarkdown');
|
|
140
198
|
this.buffers.delete(sessionId);
|
|
141
199
|
}
|
|
@@ -159,15 +217,21 @@ class OutboundRouter {
|
|
|
159
217
|
/** 轮次结束:清理 buffer,异常结束时告知用户 */
|
|
160
218
|
onTurnEnd(sessionId, _record, event) {
|
|
161
219
|
const buffer = this.buffers.get(sessionId);
|
|
220
|
+
// 先让残留 buffer flush 完(记账在 flush 里发生), 再判断 passive 收尾补发
|
|
221
|
+
const finish = () => this.maybeResendLastBlock(_record.sessionKey, _record);
|
|
162
222
|
if (buffer !== undefined) {
|
|
163
223
|
if (buffer.text.trim()) {
|
|
164
|
-
void buffer.flush();
|
|
224
|
+
void buffer.flush().then(finish, finish);
|
|
165
225
|
}
|
|
166
226
|
else {
|
|
167
227
|
buffer.cancel();
|
|
228
|
+
finish();
|
|
168
229
|
}
|
|
169
230
|
this.buffers.delete(sessionId);
|
|
170
231
|
}
|
|
232
|
+
else {
|
|
233
|
+
finish();
|
|
234
|
+
}
|
|
171
235
|
const failure = extractTurnError(event.reason);
|
|
172
236
|
if (failure !== undefined && !SILENT_TURN_ERROR_CODES.has(failure.code)) {
|
|
173
237
|
void this.send(_record, `⚠️ 本轮异常结束\n\`${failure.code}\`: ${failure.message}`, 'sendTurnEndError');
|
|
@@ -177,7 +241,7 @@ class OutboundRouter {
|
|
|
177
241
|
/** 统一发送:逐条自适应目标(适配主动) + 富媒体感知分块;媒体指令([MEDIA:..]/[RECALL])被剔除,失败降级记录 */
|
|
178
242
|
async send(_record, text, tag) {
|
|
179
243
|
try {
|
|
180
|
-
await sendRichOutbound(this.bot, _record.replyTarget, text, this.config.textChunkLimit, this.config.cwd, (m) => this.logger.error(m), () => this.resolveTarget(_record));
|
|
244
|
+
await sendRichOutbound(this.bot, _record.replyTarget, text, this.config.textChunkLimit, this.config.cwd, (m) => this.logger.error(m), () => this.resolveTarget(_record), this.chunkTargetFn(_record));
|
|
181
245
|
}
|
|
182
246
|
catch (err) {
|
|
183
247
|
this.logger.error(`im-qqbot: ${tag} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbound.js","sourceRoot":"","sources":["../../src/transport/outbound.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAoB,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAA+C,MAAM,qBAAqB,CAAC;AACpG,OAAO,EACL,UAAU,EACV,gBAAgB,GAOjB,MAAM,aAAa,CAAC;AAmBrB,6CAA6C;AAC7C,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;AAE3D,gEAAgE;AAChE,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAC/B,sEAAsE;AACtE,MAAM,kBAAkB,GAAG,CAAC,GAAG,MAAM,CAAC;AAEtC;;GAEG;AACH,MAAM,cAAc;
|
|
1
|
+
{"version":3,"file":"outbound.js","sourceRoot":"","sources":["../../src/transport/outbound.ts"],"names":[],"mappings":"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"}
|