@xgjktech/xg_cwork_im 1.16.2 → 1.16.4

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 (50) hide show
  1. package/README.md +2 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +8 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/src/block-streaming-config.test.js +7 -1
  6. package/dist/src/block-streaming-config.test.js.map +1 -1
  7. package/dist/src/channel-config.d.ts +14 -3
  8. package/dist/src/channel-config.d.ts.map +1 -1
  9. package/dist/src/channel-config.js +12 -3
  10. package/dist/src/channel-config.js.map +1 -1
  11. package/dist/src/dispatch-mentioned-reply.d.ts.map +1 -1
  12. package/dist/src/dispatch-mentioned-reply.js +116 -11
  13. package/dist/src/dispatch-mentioned-reply.js.map +1 -1
  14. package/dist/src/recommended-system-prompt.d.ts +1 -1
  15. package/dist/src/recommended-system-prompt.d.ts.map +1 -1
  16. package/dist/src/recommended-system-prompt.js +6 -1
  17. package/dist/src/recommended-system-prompt.js.map +1 -1
  18. package/dist/src/resource-file.d.ts +26 -0
  19. package/dist/src/resource-file.d.ts.map +1 -1
  20. package/dist/src/resource-file.js +59 -5
  21. package/dist/src/resource-file.js.map +1 -1
  22. package/dist/src/send-file-tool.d.ts +81 -0
  23. package/dist/src/send-file-tool.d.ts.map +1 -0
  24. package/dist/src/send-file-tool.js +354 -0
  25. package/dist/src/send-file-tool.js.map +1 -0
  26. package/dist/src/send-file-tool.test.d.ts +2 -0
  27. package/dist/src/send-file-tool.test.d.ts.map +1 -0
  28. package/dist/src/send-file-tool.test.js +176 -0
  29. package/dist/src/send-file-tool.test.js.map +1 -0
  30. package/dist/src/send-group-message-tool.js +1 -1
  31. package/dist/src/send-group-message-tool.js.map +1 -1
  32. package/dist/src/send-service.d.ts +43 -4
  33. package/dist/src/send-service.d.ts.map +1 -1
  34. package/dist/src/send-service.js +62 -38
  35. package/dist/src/send-service.js.map +1 -1
  36. package/dist/src/send-service.test.d.ts +2 -0
  37. package/dist/src/send-service.test.d.ts.map +1 -0
  38. package/dist/src/send-service.test.js +40 -0
  39. package/dist/src/send-service.test.js.map +1 -0
  40. package/dist/src/turn-deliver-buffer.d.ts +18 -1
  41. package/dist/src/turn-deliver-buffer.d.ts.map +1 -1
  42. package/dist/src/turn-deliver-buffer.js +70 -2
  43. package/dist/src/turn-deliver-buffer.js.map +1 -1
  44. package/dist/src/turn-deliver-buffer.test.js +61 -8
  45. package/dist/src/turn-deliver-buffer.test.js.map +1 -1
  46. package/dist/src/types.d.ts +17 -5
  47. package/dist/src/types.d.ts.map +1 -1
  48. package/dist/src/types.js.map +1 -1
  49. package/openclaw.plugin.json +2 -1
  50. package/package.json +2 -2
@@ -5,7 +5,20 @@
5
5
  * 支持 RICH_TEXT 与带资源 fileId 的 FILE 类型(attachments)。
6
6
  */
7
7
  import type { Log } from "./auth.js";
8
- import type { SendMessageReply, XgImConfig } from "./types.js";
8
+ import type { SendMessageFileAttachment, SendMessageReply, XgImConfig } from "./types.js";
9
+ /**
10
+ * 生成一次投递的客户端幂等键。
11
+ *
12
+ * 服务端按 `clientMsgId + groupId + 最近 10 分钟` 去重:同一逻辑消息在其内部 6 次重试间
13
+ * 复用同一 `clientMsgId`,超时/断连重发会命中服务端已有消息,不产生重复气泡。
14
+ * 每个独立投递块生成一次(不同块必须不同)。
15
+ */
16
+ export declare function generateClientMsgId(): string;
17
+ /** 从发送接口响应中解析服务端消息 id(`data.id`)与回显 `clientMsgId`,用于对账日志。 */
18
+ export declare function extractSentMessageInfo(resData: unknown): {
19
+ serverMsgId?: string;
20
+ clientMsgId?: string;
21
+ };
9
22
  /** OpenClaw dispatch deliver 单块载荷:文本 + 可选媒体 URL(与 plugin-sdk 约定对齐)。 */
10
23
  export type ReplyDeliverPayload = {
11
24
  markdown?: string;
@@ -27,7 +40,33 @@ export type ReplyDeliverPayload = {
27
40
  * 用于在多沙箱 agent 场景下正确解析 /workspace/ 前缀路径。
28
41
  * 未传时回退到 process.cwd(),单 agent 部署下行为不变。
29
42
  */
30
- export declare function sendReplyDeliverBlock(config: XgImConfig, token: string, groupId: string, payload: ReplyDeliverPayload, atUserIds?: string[], log?: Log, msgId?: string, reply?: SendMessageReply, agentWorkspaceDir?: string): Promise<void>;
43
+ export declare function sendReplyDeliverBlock(config: XgImConfig, token: string, groupId: string, payload: ReplyDeliverPayload, atUserIds?: string[], log?: Log, _deprecatedMsgId?: string, reply?: SendMessageReply, agentWorkspaceDir?: string): Promise<void>;
44
+ /**
45
+ * 发送一条已上传资源的 FILE 消息到指定 IM 群聊。
46
+ *
47
+ * 与 {@link sendReplyDeliverBlock} 不同:本函数**不做** URL 下载 / 上传失败降级为文本的逻辑,
48
+ * 仅负责把已经拿到 fileId 的附件组装成 FILE 消息发出。失败直接抛出,由调用方(工具)返回明确错误,
49
+ * 不会产生「降级成文本却报成功」的假成功。上传步骤请在调用前用
50
+ * {@link uploadWholeResourceFileWithRetry} 完成。
51
+ *
52
+ * 复用 {@link postImMessage} 的 6 次网络重试与服务端 clientMsgId 去重。
53
+ */
54
+ export declare function sendUploadedFileMessage(args: {
55
+ config: XgImConfig;
56
+ token: string;
57
+ groupId: string;
58
+ /** 附件说明;为空时用单空格占位,避免部分 IM 接口拒收空文本 */
59
+ caption?: string;
60
+ attachment: SendMessageFileAttachment;
61
+ atUserIds?: string[];
62
+ /** 幂等键;省略时自动生成 */
63
+ clientMsgId?: string;
64
+ reply?: SendMessageReply;
65
+ log?: Log;
66
+ }): Promise<{
67
+ clientMsgId: string;
68
+ serverMsgId?: string;
69
+ }>;
31
70
  /**
32
71
  * 发送文本消息到指定 IM 群聊。
33
72
  *
@@ -37,8 +76,8 @@ export declare function sendReplyDeliverBlock(config: XgImConfig, token: string,
37
76
  * @param content 消息内容文本
38
77
  * @param atUserIds 需要 @ 的用户 ID 列表(可为空)
39
78
  * @param log 日志接口
40
- * @param msgId 可选的业务消息 ID(用于覆盖/更新已有消息)
79
+ * @param _deprecatedMsgId 已废弃的占位消息 ID 参数,不再使用(保留以兼容旧调用签名)
41
80
  * @param reply 可选的被回复消息信息(用于在 IM 中建立“回复某条消息”的关联)
42
81
  */
43
- export declare function sendTextMessage(config: XgImConfig, token: string, groupId: string, content: string, atUserIds?: string[], log?: Log, msgId?: string, reply?: SendMessageReply): Promise<void>;
82
+ export declare function sendTextMessage(config: XgImConfig, token: string, groupId: string, content: string, atUserIds?: string[], log?: Log, _deprecatedMsgId?: string, reply?: SendMessageReply): Promise<void>;
44
83
  //# sourceMappingURL=send-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"send-service.d.ts","sourceRoot":"","sources":["../../src/send-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAWrC,OAAO,KAAK,EAA8C,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA8M3G,uEAAuE;AACvE,MAAM,MAAM,mBAAmB,GAAG;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACvC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,mBAAmB,EAC5B,SAAS,GAAE,MAAM,EAAO,EACxB,GAAG,CAAC,EAAE,GAAG,EACT,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,gBAAgB,EACxB,iBAAiB,CAAC,EAAE,MAAM,GAC3B,OAAO,CAAC,IAAI,CAAC,CAgHf;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACjC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAAM,EAAO,EACxB,GAAG,CAAC,EAAE,GAAG,EACT,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,IAAI,CAAC,CAqBf"}
1
+ {"version":3,"file":"send-service.d.ts","sourceRoot":"","sources":["../../src/send-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAWrC,OAAO,KAAK,EAAmB,yBAAyB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA6B3G;;;;;;GAMG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,6DAA6D;AAC7D,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAQvG;AA0KD,uEAAuE;AACvE,MAAM,MAAM,mBAAmB,GAAG;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACvC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,mBAAmB,EAC5B,SAAS,GAAE,MAAM,EAAO,EACxB,GAAG,CAAC,EAAE,GAAG,EACT,gBAAgB,CAAC,EAAE,MAAM,EACzB,KAAK,CAAC,EAAE,gBAAgB,EACxB,iBAAiB,CAAC,EAAE,MAAM,GAC3B,OAAO,CAAC,IAAI,CAAC,CA2Gf;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAChD,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,yBAAyB,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,kBAAkB;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,GAAG,CAAC,EAAE,GAAG,CAAC;CACb,GAAG,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAkBzD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACjC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAAM,EAAO,EACxB,GAAG,CAAC,EAAE,GAAG,EACT,gBAAgB,CAAC,EAAE,MAAM,EACzB,KAAK,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,IAAI,CAAC,CAcf"}
@@ -4,6 +4,7 @@
4
4
  * 调用 IM 接口将 AI 回复发送到指定群聊,并 @ 原始发送者。
5
5
  * 支持 RICH_TEXT 与带资源 fileId 的 FILE 类型(attachments)。
6
6
  */
7
+ import { randomUUID } from "node:crypto";
7
8
  import axios from "axios";
8
9
  import { downloadMediaBuffer, formatFromFilename, parseWorkspaceRelativeMediaRef, resolveMaxAttachmentBytes, resolveResourceUploadUrl, uploadWholeResourceFile, } from "./resource-file.js";
9
10
  import { stripMediaDirectiveLines } from "./deliver-text.js";
@@ -35,23 +36,27 @@ function buildFileDeliverFallbackText(textToSend, mediaUrls, err) {
35
36
  }
36
37
  return errNote;
37
38
  }
38
- /** 用于合并流式占位消息:trim 后非空才写入请求体 `msgId` */
39
- function normalizePlaceholderMsgId(msgId) {
40
- if (msgId == null)
41
- return undefined;
42
- const t = String(msgId).trim();
43
- return t.length > 0 ? t : undefined;
39
+ /**
40
+ * 生成一次投递的客户端幂等键。
41
+ *
42
+ * 服务端按 `clientMsgId + groupId + 最近 10 分钟` 去重:同一逻辑消息在其内部 6 次重试间
43
+ * 复用同一 `clientMsgId`,超时/断连重发会命中服务端已有消息,不产生重复气泡。
44
+ * 每个独立投递块生成一次(不同块必须不同)。
45
+ */
46
+ export function generateClientMsgId() {
47
+ return `ocw_${Date.now()}_${randomUUID()}`;
44
48
  }
45
- /** 日志脱敏摘要:便于对照 IM 后台是否收到合并字段(不含完整密钥) */
46
- function summarizePlaceholderMsgId(raw) {
47
- if (raw == null)
48
- return "input=null";
49
- const n = normalizePlaceholderMsgId(raw);
50
- if (!n)
51
- return raw === "" ? "empty-string" : "whitespace-only";
52
- if (n.length <= 18)
53
- return `full=${n}`;
54
- return `len=${n.length} ${n.slice(0, 8)}…${n.slice(-4)}`;
49
+ /** 从发送接口响应中解析服务端消息 id(`data.id`)与回显 `clientMsgId`,用于对账日志。 */
50
+ export function extractSentMessageInfo(resData) {
51
+ if (!resData || typeof resData !== "object")
52
+ return {};
53
+ const data = resData.data;
54
+ if (!data || typeof data !== "object")
55
+ return {};
56
+ const d = data;
57
+ const serverMsgId = typeof d.id === "string" ? d.id : d.id != null ? String(d.id) : undefined;
58
+ const clientMsgId = typeof d.clientMsgId === "string" ? d.clientMsgId : undefined;
59
+ return { serverMsgId, clientMsgId };
55
60
  }
56
61
  /**
57
62
  * 发消息接口的重试参数。
@@ -132,12 +137,9 @@ async function postImMessage(config, token, groupId, body, atUserIds = [], log)
132
137
  groupId,
133
138
  ...(atUserIds.length > 0 ? { atUserIds } : {}),
134
139
  };
135
- const bodyMsgIdRaw = full.msgId;
136
- const bodyMsgId = typeof bodyMsgIdRaw === "string" ? bodyMsgIdRaw : undefined;
137
- const mergedPlaceholder = normalizePlaceholderMsgId(bodyMsgId);
140
+ const bodyClientMsgId = typeof full.clientMsgId === "string" ? full.clientMsgId : undefined;
138
141
  sendLogInfo(log, `[cwork_im:send] POST ${url} groupId=${groupId} type=${full.type} ` +
139
- `placeholderRaw=${summarizePlaceholderMsgId(bodyMsgId)} ` +
140
- `mergeFieldInJson=${mergedPlaceholder != null ? `yes(len=${mergedPlaceholder.length})` : "no"} ` +
142
+ `clientMsgId=${bodyClientMsgId ?? "none"} ` +
141
143
  `atUsers=${JSON.stringify(atUserIds)}`);
142
144
  sendLogDebug(log, config, `[cwork_im:send] Request body: ${JSON.stringify(full)}`);
143
145
  const totalAttempts = 1 + IM_SEND_MAX_RETRIES;
@@ -163,7 +165,13 @@ async function postImMessage(config, token, groupId, body, atUserIds = [], log)
163
165
  throw new Error(`IM API error resultCode=${resultCode}${resultMsg ? ` resultMsg=${resultMsg}` : ""}`);
164
166
  }
165
167
  }
166
- return;
168
+ // 对账日志:服务端消息 id(data.id)+ 回显 clientMsgId;重试命中去重时会返回既有消息。
169
+ const sent = extractSentMessageInfo(d);
170
+ sendLogInfo(log, `[cwork_im:send] Delivered groupId=${groupId} ` +
171
+ `serverMsgId=${sent.serverMsgId ?? "unknown"} ` +
172
+ `clientMsgId=${sent.clientMsgId ?? bodyClientMsgId ?? "none"} ` +
173
+ `(attempt=${attempt}/${totalAttempts})`);
174
+ return { serverMsgId: sent.serverMsgId, clientMsgId: sent.clientMsgId ?? bodyClientMsgId };
167
175
  }
168
176
  catch (err) {
169
177
  lastErr = err;
@@ -191,11 +199,9 @@ async function postImMessage(config, token, groupId, body, atUserIds = [], log)
191
199
  * 用于在多沙箱 agent 场景下正确解析 /workspace/ 前缀路径。
192
200
  * 未传时回退到 process.cwd(),单 agent 部署下行为不变。
193
201
  */
194
- export async function sendReplyDeliverBlock(config, token, groupId, payload, atUserIds = [], log, msgId, reply, agentWorkspaceDir) {
195
- const placeholderMsgId = normalizePlaceholderMsgId(msgId);
196
- if (msgId !== undefined && placeholderMsgId === undefined) {
197
- sendLogWarn(log, `[cwork_im:send] sendReplyDeliverBlock: placeholder msgId omitted (empty/whitespace only after trim) raw=${JSON.stringify(msgId)}`);
198
- }
202
+ export async function sendReplyDeliverBlock(config, token, groupId, payload, atUserIds = [], log, _deprecatedMsgId, reply, agentWorkspaceDir) {
203
+ // 一个投递块一个 clientMsgId:内部 6 次重试复用同值 → 命中服务端去重,不重复投递。
204
+ const clientMsgId = generateClientMsgId();
199
205
  const textToSend = stripMediaDirectiveLines((payload.markdown || payload.text || "").trim());
200
206
  const mediaList = [
201
207
  ...(payload.mediaUrl ? [payload.mediaUrl] : []),
@@ -206,7 +212,7 @@ export async function sendReplyDeliverBlock(config, token, groupId, payload, atU
206
212
  const formField = config.fileUploadFormField?.trim() || "file";
207
213
  const wantFile = uniqueUrls.length > 0 && !payload.isThinking;
208
214
  sendLogInfo(log, `[cwork_im:send] sendReplyDeliverBlock plan kind=${wantFile ? "FILE" : textToSend.length > 0 ? "RICH_TEXT" : "none"} ` +
209
- `placeholder=${placeholderMsgId != null ? `merge(len=${placeholderMsgId.length})` : "no-merge"} ` +
215
+ `clientMsgId=${clientMsgId} ` +
210
216
  `isThinking=${payload.isThinking ?? false}`);
211
217
  if (wantFile) {
212
218
  const fileUploadUrl = resolveResourceUploadUrl(config.baseUrl);
@@ -243,7 +249,7 @@ export async function sendReplyDeliverBlock(config, token, groupId, payload, atU
243
249
  type: "FILE",
244
250
  text: caption,
245
251
  attachments,
246
- ...(placeholderMsgId ? { msgId: placeholderMsgId } : {}),
252
+ clientMsgId,
247
253
  ...(reply ? { reply } : {}),
248
254
  }, atUserIds, log);
249
255
  return;
@@ -255,7 +261,7 @@ export async function sendReplyDeliverBlock(config, token, groupId, payload, atU
255
261
  await postImMessage(config, token, groupId, {
256
262
  type: "RICH_TEXT",
257
263
  text: fallbackText,
258
- ...(placeholderMsgId ? { msgId: placeholderMsgId } : {}),
264
+ clientMsgId,
259
265
  ...(reply ? { reply } : {}),
260
266
  }, atUserIds, log);
261
267
  return;
@@ -265,11 +271,33 @@ export async function sendReplyDeliverBlock(config, token, groupId, payload, atU
265
271
  await postImMessage(config, token, groupId, {
266
272
  type: "RICH_TEXT",
267
273
  text: textToSend,
268
- ...(placeholderMsgId ? { msgId: placeholderMsgId } : {}),
274
+ clientMsgId,
269
275
  ...(reply ? { reply } : {}),
270
276
  }, atUserIds, log);
271
277
  }
272
278
  }
279
+ /**
280
+ * 发送一条已上传资源的 FILE 消息到指定 IM 群聊。
281
+ *
282
+ * 与 {@link sendReplyDeliverBlock} 不同:本函数**不做** URL 下载 / 上传失败降级为文本的逻辑,
283
+ * 仅负责把已经拿到 fileId 的附件组装成 FILE 消息发出。失败直接抛出,由调用方(工具)返回明确错误,
284
+ * 不会产生「降级成文本却报成功」的假成功。上传步骤请在调用前用
285
+ * {@link uploadWholeResourceFileWithRetry} 完成。
286
+ *
287
+ * 复用 {@link postImMessage} 的 6 次网络重试与服务端 clientMsgId 去重。
288
+ */
289
+ export async function sendUploadedFileMessage(args) {
290
+ const caption = args.caption && args.caption.trim().length > 0 ? args.caption : " ";
291
+ const clientMsgId = args.clientMsgId ?? generateClientMsgId();
292
+ const sent = await postImMessage(args.config, args.token, args.groupId, {
293
+ type: "FILE",
294
+ text: caption,
295
+ attachments: [args.attachment],
296
+ clientMsgId,
297
+ ...(args.reply ? { reply: args.reply } : {}),
298
+ }, args.atUserIds ?? [], args.log);
299
+ return { clientMsgId, serverMsgId: sent.serverMsgId };
300
+ }
273
301
  /**
274
302
  * 发送文本消息到指定 IM 群聊。
275
303
  *
@@ -279,18 +307,14 @@ export async function sendReplyDeliverBlock(config, token, groupId, payload, atU
279
307
  * @param content 消息内容文本
280
308
  * @param atUserIds 需要 @ 的用户 ID 列表(可为空)
281
309
  * @param log 日志接口
282
- * @param msgId 可选的业务消息 ID(用于覆盖/更新已有消息)
310
+ * @param _deprecatedMsgId 已废弃的占位消息 ID 参数,不再使用(保留以兼容旧调用签名)
283
311
  * @param reply 可选的被回复消息信息(用于在 IM 中建立“回复某条消息”的关联)
284
312
  */
285
- export async function sendTextMessage(config, token, groupId, content, atUserIds = [], log, msgId, reply) {
286
- const placeholderMsgId = normalizePlaceholderMsgId(msgId);
287
- if (msgId !== undefined && placeholderMsgId === undefined) {
288
- sendLogWarn(log, `[cwork_im:send] sendTextMessage: placeholder msgId omitted (empty/whitespace only after trim) raw=${JSON.stringify(msgId)}`);
289
- }
313
+ export async function sendTextMessage(config, token, groupId, content, atUserIds = [], log, _deprecatedMsgId, reply) {
290
314
  await postImMessage(config, token, groupId, {
291
315
  type: "RICH_TEXT",
292
316
  text: content,
293
- ...(placeholderMsgId ? { msgId: placeholderMsgId } : {}),
317
+ clientMsgId: generateClientMsgId(),
294
318
  ...(reply ? { reply } : {}),
295
319
  }, atUserIds, log);
296
320
  }
@@ -1 +1 @@
1
- {"version":3,"file":"send-service.js","sourceRoot":"","sources":["../../src/send-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EACH,mBAAmB,EACnB,kBAAkB,EAClB,8BAA8B,EAC9B,yBAAyB,EACzB,wBAAwB,EACxB,uBAAuB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,iCAAiC,EAAE,MAAM,yBAAyB,CAAC;AAG5E,SAAS,kBAAkB,CAAC,GAAY;IACpC,IAAI,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5B,IAAI,GAAG,CAAC,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QAClD,IAAI,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAClF,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IACD,IAAI,GAAG,YAAY,KAAK;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC7C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,oDAAoD;AACpD,SAAS,4BAA4B,CAAC,UAAkB,EAAE,SAAmB,EAAE,GAAY;IACvF,MAAM,OAAO,GAAG,IAAI,iCAAiC,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC;IACzE,MAAM,QAAQ,GACV,SAAS,CAAC,MAAM,GAAG,CAAC;QAChB,CAAC,CAAC,0BAA0B,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAClF,CAAC,CAAC,EAAE,CAAC;IACb,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,GAAG,UAAU,GAAG,QAAQ,OAAO,OAAO,EAAE,CAAC;IACpD,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;QAClB,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,OAAO,OAAO,EAAE,CAAC;IAC9C,CAAC;IACD,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,wCAAwC;AACxC,SAAS,yBAAyB,CAAC,KAAyB;IACxD,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC;IACpC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/B,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACxC,CAAC;AAED,wCAAwC;AACxC,SAAS,yBAAyB,CAAC,GAAuB;IACtD,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,YAAY,CAAC;IACrC,MAAM,CAAC,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,CAAC,CAAC;QAAE,OAAO,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,iBAAiB,CAAC;IAC/D,IAAI,CAAC,CAAC,MAAM,IAAI,EAAE;QAAE,OAAO,QAAQ,CAAC,EAAE,CAAC;IACvC,OAAO,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC7D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,MAAM,2BAA2B,GAAG,KAAK,CAAC;AAC1C,MAAM,0BAA0B,GAAG,MAAM,CAAC;AAE1C,SAAS,oBAAoB,CAAC,OAAe;IACzC,MAAM,GAAG,GAAG,2BAA2B,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;IACxE,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,0BAA0B,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACrB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;GAKG;AACH,SAAS,oBAAoB,CAAC,GAAY;IACtC,IAAI,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC;QACpC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACtC,IAAI,MAAM,IAAI,GAAG;YAAE,OAAO,IAAI,CAAC;QAC/B,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAClD,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,gFAAgF;AAChF,SAAS,WAAW,CAAC,GAAoB,EAAE,GAAW;IAClD,IAAI,OAAO,GAAG,EAAE,IAAI,KAAK,UAAU,EAAE,CAAC;QAClC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACd,OAAO;IACX,CAAC;IACD,MAAM,GAAG,GAAG,GAAgD,CAAC;IAC7D,IAAI,OAAO,GAAG,EAAE,GAAG,KAAK,UAAU,EAAE,CAAC;QACjC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACb,OAAO;IACX,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,WAAW,CAAC,GAAoB,EAAE,GAAW;IAClD,IAAI,OAAO,GAAG,EAAE,IAAI,KAAK,UAAU,EAAE,CAAC;QAClC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACd,OAAO;IACX,CAAC;IACD,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,YAAY,CAAC,GAAoB,EAAE,GAAW;IACnD,IAAI,OAAO,GAAG,EAAE,KAAK,KAAK,UAAU,EAAE,CAAC;QACnC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACf,OAAO;IACX,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,YAAY,CAAC,GAAoB,EAAE,MAAkB,EAAE,GAAW;IACvE,IAAI,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO;IAC1B,IAAI,OAAO,GAAG,EAAE,KAAK,KAAK,UAAU,EAAE,CAAC;QACnC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACf,OAAO;IACX,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAC;AACxC,CAAC;AAED,KAAK,UAAU,aAAa,CACxB,MAAkB,EAClB,KAAa,EACb,OAAe,EACf,IAAqB,EACrB,YAAsB,EAAE,EACxB,GAAS;IAET,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,OAAO,kBAAkB,CAAC;IAChD,MAAM,IAAI,GAAoB;QAC1B,GAAG,IAAI;QACP,OAAO;QACP,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9B,CAAC;IAErB,MAAM,YAAY,GAAI,IAA4B,CAAC,KAAK,CAAC;IACzD,MAAM,SAAS,GAAG,OAAO,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,MAAM,iBAAiB,GAAG,yBAAyB,CAAC,SAAS,CAAC,CAAC;IAC/D,WAAW,CACP,GAAG,EACH,wBAAwB,GAAG,YAAY,OAAO,SAAS,IAAI,CAAC,IAAI,GAAG;QAC/D,kBAAkB,yBAAyB,CAAC,SAAS,CAAC,GAAG;QACzD,oBAAoB,iBAAiB,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG;QAChG,WAAW,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAC7C,CAAC;IACF,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,iCAAiC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEnF,MAAM,aAAa,GAAG,CAAC,GAAG,mBAAmB,CAAC;IAC9C,IAAI,OAAO,GAAY,SAAS,CAAC;IAEjC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,aAAa,EAAE,OAAO,EAAE,EAAE,CAAC;QACxD,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE;gBACpC,OAAO,EAAE;oBACL,cAAc,EAAE,kBAAkB;oBAClC,cAAc,EAAE,KAAK;iBACxB;gBACD,OAAO,EAAE,MAAM;aAClB,CAAC,CAAC;YAEH,WAAW,CAAC,GAAG,EAAE,mCAAmC,GAAG,CAAC,MAAM,aAAa,OAAO,IAAI,aAAa,GAAG,CAAC,CAAC;YACxG,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,kCAAkC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAExF,0DAA0D;YAC1D,gGAAgG;YAChG,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC;YACnB,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;gBAC7B,MAAM,UAAU,GAAI,CAA6B,CAAC,UAAU,CAAC;gBAC7D,MAAM,SAAS,GAAI,CAA6B,CAAC,SAAS,CAAC;gBAC3D,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;oBAC/C,MAAM,IAAI,KAAK,CACX,2BAA2B,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,cAAc,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACvF,CAAC;gBACN,CAAC;YACL,CAAC;YACD,OAAO;QACX,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACpB,OAAO,GAAG,GAAG,CAAC;YACd,MAAM,GAAG,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;YACpC,MAAM,SAAS,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAC5C,MAAM,MAAM,GAAG,OAAO,IAAI,aAAa,CAAC;YAExC,IAAI,CAAC,SAAS,IAAI,MAAM,EAAE,CAAC;gBACvB,YAAY,CACR,GAAG,EACH,qDAAqD,OAAO,GAAG;oBAC3D,YAAY,OAAO,IAAI,aAAa,eAAe,SAAS,MAAM,GAAG,EAAE,CAC9E,CAAC;gBACF,MAAM,GAAG,CAAC;YACd,CAAC;YAED,MAAM,YAAY,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;YACnD,WAAW,CACP,GAAG,EACH,wCAAwC,OAAO,IAAI,aAAa,KAAK;gBACjE,eAAe,YAAY,OAAO,GAAG,EAAE,CAC9C,CAAC;YACF,MAAM,KAAK,CAAC,YAAY,CAAC,CAAC;QAC9B,CAAC;IACL,CAAC;IAED,kDAAkD;IAClD,MAAM,OAAO,IAAI,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;AAC5E,CAAC;AAiBD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACvC,MAAkB,EAClB,KAAa,EACb,OAAe,EACf,OAA4B,EAC5B,YAAsB,EAAE,EACxB,GAAS,EACT,KAAc,EACd,KAAwB,EACxB,iBAA0B;IAE1B,MAAM,gBAAgB,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;IAC1D,IAAI,KAAK,KAAK,SAAS,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;QACxD,WAAW,CACP,GAAG,EACH,2GAA2G,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CACrI,CAAC;IACN,CAAC;IAED,MAAM,UAAU,GAAG,wBAAwB,CAAC,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7F,MAAM,SAAS,GAAG;QACd,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;KAClF,CAAC;IACF,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,MAAM,CAAC,mBAAmB,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC;IAE/D,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;IAE9D,WAAW,CACP,GAAG,EACH,mDAAmD,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,GAAG;QAClH,eAAe,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAC,aAAa,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,UAAU,GAAG;QACjG,cAAc,OAAO,CAAC,UAAU,IAAI,KAAK,EAAE,CAClD,CAAC;IAEF,IAAI,QAAQ,EAAE,CAAC;QACX,MAAM,aAAa,GAAG,wBAAwB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC/D,IAAI,CAAC,iBAAiB,EAAE,IAAI,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACpD,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YACnB,OAAO,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,8BAA8B,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QACnF,CAAC,CAAC,EAAE,CAAC;YACD,WAAW,CACP,GAAG,EACH,iEAAiE;gBAC7D,6EAA6E,UAAU,CAAC,MAAM,EAAE,CACvG,CAAC;QACN,CAAC;QACD,IAAI,CAAC;YACD,MAAM,WAAW,GAAgC,EAAE,CAAC;YACpD,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;gBACzB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,mBAAmB,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,iBAAiB,CAAC,CAAC;gBAC5F,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,uBAAuB,CAAC;oBAC7C,aAAa;oBACb,KAAK;oBACL,MAAM;oBACN,QAAQ;oBACR,SAAS;oBACT,GAAG;iBACN,CAAC,CAAC;gBACH,WAAW,CAAC,IAAI,CAAC;oBACb,MAAM;oBACN,QAAQ,EAAE,MAAM;oBAChB,MAAM,EAAE,kBAAkB,CAAC,QAAQ,CAAC;oBACpC,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,MAAM,CAAC,MAAM;oBACnB,MAAM,EAAE,UAAU;iBACrB,CAAC,CAAC;YACP,CAAC;YACD,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC;YACzD,MAAM,aAAa,CACf,MAAM,EACN,KAAK,EACL,OAAO,EACP;gBACI,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,OAAO;gBACb,WAAW;gBACX,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxD,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9B,EACD,SAAS,EACT,GAAG,CACN,CAAC;YACF,OAAO;QACX,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACpB,YAAY,CAAC,GAAG,EAAE,iEAAiE,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC9G,MAAM,YAAY,GAAG,4BAA4B,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;YAC/E,oCAAoC;YACpC,MAAM,aAAa,CACf,MAAM,EACN,KAAK,EACL,OAAO,EACP;gBACI,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,YAAY;gBAClB,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxD,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9B,EACD,SAAS,EACT,GAAG,CACN,CAAC;YACF,OAAO;QACX,CAAC;IACL,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,aAAa,CACf,MAAM,EACN,KAAK,EACL,OAAO,EACP;YACI,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,UAAU;YAChB,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxD,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9B,EACD,SAAS,EACT,GAAG,CACN,CAAC;IACN,CAAC;AACL,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACjC,MAAkB,EAClB,KAAa,EACb,OAAe,EACf,OAAe,EACf,YAAsB,EAAE,EACxB,GAAS,EACT,KAAc,EACd,KAAwB;IAExB,MAAM,gBAAgB,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;IAC1D,IAAI,KAAK,KAAK,SAAS,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;QACxD,WAAW,CACP,GAAG,EACH,qGAAqG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAC/H,CAAC;IACN,CAAC;IACD,MAAM,aAAa,CACf,MAAM,EACN,KAAK,EACL,OAAO,EACP;QACI,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,OAAO;QACb,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9B,EACD,SAAS,EACT,GAAG,CACN,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"send-service.js","sourceRoot":"","sources":["../../src/send-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=send-service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-service.test.d.ts","sourceRoot":"","sources":["../../src/send-service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,40 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { extractSentMessageInfo, generateClientMsgId } from "./send-service.js";
4
+ describe("generateClientMsgId", () => {
5
+ it("is unique per call (distinct logical messages)", () => {
6
+ const a = generateClientMsgId();
7
+ const b = generateClientMsgId();
8
+ assert.notEqual(a, b);
9
+ assert.match(a, /^ocw_\d+_/);
10
+ });
11
+ });
12
+ describe("extractSentMessageInfo", () => {
13
+ it("reads server id and echoed clientMsgId from real send response", () => {
14
+ const res = {
15
+ resultCode: 1,
16
+ resultMsg: null,
17
+ data: {
18
+ id: "2077657906769403905",
19
+ groupId: "2072518674467676162",
20
+ type: "TEXT",
21
+ text: "1",
22
+ clientMsgId: "temp_1784187222818_oe8fjl",
23
+ },
24
+ };
25
+ const info = extractSentMessageInfo(res);
26
+ assert.equal(info.serverMsgId, "2077657906769403905");
27
+ assert.equal(info.clientMsgId, "temp_1784187222818_oe8fjl");
28
+ });
29
+ it("coerces numeric id to string", () => {
30
+ const info = extractSentMessageInfo({ data: { id: 12345 } });
31
+ assert.equal(info.serverMsgId, "12345");
32
+ });
33
+ it("returns empty when data missing or malformed", () => {
34
+ assert.deepEqual(extractSentMessageInfo(null), {});
35
+ assert.deepEqual(extractSentMessageInfo({}), {});
36
+ assert.deepEqual(extractSentMessageInfo({ data: null }), {});
37
+ assert.deepEqual(extractSentMessageInfo({ data: "nope" }), {});
38
+ });
39
+ });
40
+ //# sourceMappingURL=send-service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-service.test.js","sourceRoot":"","sources":["../../src/send-service.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAEhF,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACtD,MAAM,CAAC,GAAG,mBAAmB,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,mBAAmB,EAAE,CAAC;QAChC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACtB,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACtE,MAAM,GAAG,GAAG;YACR,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,IAAI;YACf,IAAI,EAAE;gBACF,EAAE,EAAE,qBAAqB;gBACzB,OAAO,EAAE,qBAAqB;gBAC9B,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,GAAG;gBACT,WAAW,EAAE,2BAA2B;aAC3C;SACJ,CAAC;QACF,MAAM,IAAI,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC;QACtD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,2BAA2B,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACpC,MAAM,IAAI,GAAG,sBAAsB,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAC7D,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,SAAS,CAAC,sBAAsB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QACnD,MAAM,CAAC,SAAS,CAAC,sBAAsB,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,SAAS,CAAC,sBAAsB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7D,MAAM,CAAC,SAAS,CAAC,sBAAsB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -1,5 +1,8 @@
1
1
  /**
2
- * 一轮 dispatch 内的 assistant 正文段缓冲:同段多次 deliver 覆盖,在 tool 边界或轮次结束冲刷 HTTP。
2
+ * 一轮 dispatch 内的 assistant 正文段缓冲:
3
+ * - 同段修稿(新文延展/包住旧文)→ 覆盖
4
+ * - 流式分块新段 → 追加合并
5
+ * 在 tool 边界或轮次结束冲刷 HTTP。
3
6
  */
4
7
  import type { ReplyDeliverPayload } from "./send-service.js";
5
8
  export type DeliverFlushKind = "interim" | "final";
@@ -10,6 +13,10 @@ export type BufferedDeliverEntry = {
10
13
  };
11
14
  export type TurnDeliverBufferStats = {
12
15
  writeCount: number;
16
+ /** write 时判定为修稿并覆盖 */
17
+ revisionOverwriteCount: number;
18
+ /** write 时判定为新段并追加 */
19
+ segmentAppendCount: number;
13
20
  flushInterimCount: number;
14
21
  flushFinalCount: number;
15
22
  skippedDuplicateFlushCount: number;
@@ -29,6 +36,16 @@ export declare function isDeliverPayloadSendable(args: {
29
36
  hasMedia: boolean;
30
37
  isThinking?: boolean;
31
38
  }): boolean;
39
+ /**
40
+ * 新文是否像对旧文的「修稿/延展」(可安全覆盖),而非另一完整分块。
41
+ * 无权威 OpenClaw 标记,偏保守:宁可追加重复,不可覆盖丢段。
42
+ */
43
+ export declare function isDeliverTextRevision(oldText: string, newText: string): boolean;
44
+ /**
45
+ * 段边界 / 轮末 flush 时,判断是否可用 `onPartialReply` 全量快照覆盖 deliver 拼接文本。
46
+ * 仅当快照(归一化后)与缓冲文本相等或为其超集时才覆盖,避免流式竞态下快照落后导致截断丢内容。
47
+ */
48
+ export declare function snapshotSupersedesBufferText(snapshot: string, bufferText: string): boolean;
32
49
  export declare class TurnDeliverBuffer {
33
50
  private buffer;
34
51
  private lastFlushedComparable;
@@ -1 +1 @@
1
- {"version":3,"file":"turn-deliver-buffer.d.ts","sourceRoot":"","sources":["../../src/turn-deliver-buffer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,CAAC;AAEnD,MAAM,MAAM,oBAAoB,GAAG;IAC/B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,0BAA0B,EAAE,MAAM,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GACxB;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GACnB;IAAE,MAAM,EAAE,mBAAmB,CAAC;IAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,GAC5D;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,CAAC;AAEvD,2CAA2C;AAC3C,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB,GAAG,OAAO,CAEV;AAED,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,qBAAqB,CAAM;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAKpB;IAEF,UAAU,IAAI,OAAO;IAIrB,QAAQ,IAAI,sBAAsB;IAIlC,KAAK,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI;IAKxC,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,kBAAkB;IAiCxD,KAAK,IAAI,IAAI;CAGhB"}
1
+ {"version":3,"file":"turn-deliver-buffer.d.ts","sourceRoot":"","sources":["../../src/turn-deliver-buffer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,CAAC;AAEnD,MAAM,MAAM,oBAAoB,GAAG;IAC/B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,sBAAsB;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,0BAA0B,EAAE,MAAM,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GACxB;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GACnB;IAAE,MAAM,EAAE,mBAAmB,CAAC;IAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,GAC5D;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,CAAC;AAEvD,2CAA2C;AAC3C,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB,GAAG,OAAO,CAEV;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAS/E;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAM1F;AA4BD,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,qBAAqB,CAAM;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAOpB;IAEF,UAAU,IAAI,OAAO;IAIrB,QAAQ,IAAI,sBAAsB;IAIlC,KAAK,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI;IAiBxC,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,kBAAkB;IAiCxD,KAAK,IAAI,IAAI;CAGhB"}
@@ -1,16 +1,74 @@
1
1
  /**
2
- * 一轮 dispatch 内的 assistant 正文段缓冲:同段多次 deliver 覆盖,在 tool 边界或轮次结束冲刷 HTTP。
2
+ * 一轮 dispatch 内的 assistant 正文段缓冲:
3
+ * - 同段修稿(新文延展/包住旧文)→ 覆盖
4
+ * - 流式分块新段 → 追加合并
5
+ * 在 tool 边界或轮次结束冲刷 HTTP。
3
6
  */
4
7
  import { normalizeDeliverComparableText } from "./deliver-text.js";
5
8
  /** deliver 正文/附件是否值得写入 buffer 或立即 HTTP。 */
6
9
  export function isDeliverPayloadSendable(args) {
7
10
  return Boolean(args.textPart) || (args.hasMedia && !args.isThinking);
8
11
  }
12
+ /**
13
+ * 新文是否像对旧文的「修稿/延展」(可安全覆盖),而非另一完整分块。
14
+ * 无权威 OpenClaw 标记,偏保守:宁可追加重复,不可覆盖丢段。
15
+ */
16
+ export function isDeliverTextRevision(oldText, newText) {
17
+ const oldN = normalizeDeliverComparableText(oldText);
18
+ const newN = normalizeDeliverComparableText(newText);
19
+ if (!oldN)
20
+ return true;
21
+ if (!newN)
22
+ return true;
23
+ if (oldN === newN)
24
+ return true;
25
+ if (newN.startsWith(oldN) || newN.includes(oldN))
26
+ return true;
27
+ if (oldN.startsWith(newN))
28
+ return true;
29
+ return false;
30
+ }
31
+ /**
32
+ * 段边界 / 轮末 flush 时,判断是否可用 `onPartialReply` 全量快照覆盖 deliver 拼接文本。
33
+ * 仅当快照(归一化后)与缓冲文本相等或为其超集时才覆盖,避免流式竞态下快照落后导致截断丢内容。
34
+ */
35
+ export function snapshotSupersedesBufferText(snapshot, bufferText) {
36
+ const ns = normalizeDeliverComparableText(snapshot);
37
+ const nb = normalizeDeliverComparableText(bufferText);
38
+ if (!ns)
39
+ return false;
40
+ if (!nb)
41
+ return true;
42
+ return ns === nb || ns.includes(nb);
43
+ }
44
+ function mergeAppendedEntry(prev, next) {
45
+ const prevText = prev.textPart.trim();
46
+ const nextText = next.textPart.trim();
47
+ const textPart = prevText && nextText ? `${prevText}\n\n${nextText}` : prevText || nextText;
48
+ const hasMedia = prev.hasMedia || next.hasMedia;
49
+ const payload = {
50
+ ...prev.payload,
51
+ ...next.payload,
52
+ text: textPart,
53
+ };
54
+ if (prev.payload.markdown != null || next.payload.markdown != null) {
55
+ payload.markdown = textPart;
56
+ }
57
+ if (!next.hasMedia && prev.hasMedia) {
58
+ if (prev.payload.mediaUrl != null)
59
+ payload.mediaUrl = prev.payload.mediaUrl;
60
+ if (prev.payload.mediaUrls != null)
61
+ payload.mediaUrls = prev.payload.mediaUrls;
62
+ }
63
+ return { payload, textPart, hasMedia };
64
+ }
9
65
  export class TurnDeliverBuffer {
10
66
  buffer;
11
67
  lastFlushedComparable = "";
12
68
  stats = {
13
69
  writeCount: 0,
70
+ revisionOverwriteCount: 0,
71
+ segmentAppendCount: 0,
14
72
  flushInterimCount: 0,
15
73
  flushFinalCount: 0,
16
74
  skippedDuplicateFlushCount: 0,
@@ -22,8 +80,18 @@ export class TurnDeliverBuffer {
22
80
  return { ...this.stats };
23
81
  }
24
82
  write(entry) {
25
- this.buffer = entry;
26
83
  this.stats.writeCount++;
84
+ if (!this.buffer) {
85
+ this.buffer = entry;
86
+ return;
87
+ }
88
+ if (isDeliverTextRevision(this.buffer.textPart, entry.textPart)) {
89
+ this.stats.revisionOverwriteCount++;
90
+ this.buffer = entry;
91
+ return;
92
+ }
93
+ this.stats.segmentAppendCount++;
94
+ this.buffer = mergeAppendedEntry(this.buffer, entry);
27
95
  }
28
96
  takeForFlush(kind) {
29
97
  if (!this.buffer) {
@@ -1 +1 @@
1
- {"version":3,"file":"turn-deliver-buffer.js","sourceRoot":"","sources":["../../src/turn-deliver-buffer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,8BAA8B,EAAE,MAAM,mBAAmB,CAAC;AAuBnE,2CAA2C;AAC3C,MAAM,UAAU,wBAAwB,CAAC,IAIxC;IACG,OAAO,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,OAAO,iBAAiB;IAClB,MAAM,CAAmC;IACzC,qBAAqB,GAAG,EAAE,CAAC;IAClB,KAAK,GAA2B;QAC7C,UAAU,EAAE,CAAC;QACb,iBAAiB,EAAE,CAAC;QACpB,eAAe,EAAE,CAAC;QAClB,0BAA0B,EAAE,CAAC;KAChC,CAAC;IAEF,UAAU;QACN,OAAO,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC;IACrC,CAAC;IAED,QAAQ;QACJ,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,KAA2B;QAC7B,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;IAC5B,CAAC;IAED,YAAY,CAAC,IAAsB;QAC/B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACf,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QAC/B,CAAC;QAED,MAAM,UAAU,GAAG,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,sDAAsD;QACtD,IACI,UAAU,CAAC,MAAM,GAAG,CAAC;YACrB,UAAU,KAAK,IAAI,CAAC,qBAAqB;YACzC,CAAC,KAAK,CAAC,QAAQ,EACjB,CAAC;YACC,IAAI,CAAC,KAAK,CAAC,0BAA0B,EAAE,CAAC;YACxC,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC;QAClD,CAAC;QAED,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACrB,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC;QACnC,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC;QACjC,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,qBAAqB,GAAG,UAAU,CAAC;QAC5C,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACtC,CAAC;IAED,KAAK;QACD,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;IAC5B,CAAC;CACJ;AAED,SAAS,oBAAoB,CAAC,KAA2B;IACrD,MAAM,IAAI,GAAG,8BAA8B,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5D,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,KAAK,CAAC,QAAQ;QAAE,OAAO,cAAc,CAAC;IAC1C,OAAO,EAAE,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"turn-deliver-buffer.js","sourceRoot":"","sources":["../../src/turn-deliver-buffer.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { describe, it } from "node:test";
3
- import { isDeliverPayloadSendable, TurnDeliverBuffer, } from "./turn-deliver-buffer.js";
3
+ import { isDeliverPayloadSendable, isDeliverTextRevision, snapshotSupersedesBufferText, TurnDeliverBuffer, } from "./turn-deliver-buffer.js";
4
4
  const HOUTONG_BODY_LOOSE = `确实是这个问题:昨天那版虽然用了内嵌 SVG,但你现在的文档预览器没有把 SVG 正常渲染出来,所以流程看不到。
5
5
 
6
6
  我已经重新生成了一版**纯 Markdown 可读版**:
@@ -22,6 +22,16 @@ const WORLD_CUP_FULL = `| 场次 | 时间 |
22
22
  | 1 | 21:00 |
23
23
  | 2 | 00:00 |
24
24
  | 3 | 03:00 |`;
25
+ const RT002_PART1 = `BEGIN_123
26
+
27
+ ## 一、背景
28
+
29
+ 随着人工智能技术的快速发展,企业级AI助手在提升工作效率中发挥着日益重要的作用。`;
30
+ const RT002_PART2 = `- 工具调用的完整日志必须被记录,包括调用时间、调用者、工具名称。
31
+
32
+ ## 六、审计
33
+
34
+ 审计是AI助手治理的监督机制。`;
25
35
  function entry(textPart, hasMedia = false) {
26
36
  return {
27
37
  payload: { text: textPart, ...(hasMedia ? { mediaUrl: "/tmp/a.md" } : {}) },
@@ -37,8 +47,37 @@ describe("isDeliverPayloadSendable", () => {
37
47
  assert.equal(isDeliverPayloadSendable({ textPart: "", hasMedia: false }), false);
38
48
  });
39
49
  });
50
+ describe("isDeliverTextRevision", () => {
51
+ it("treats growth / containment as revision", () => {
52
+ assert.equal(isDeliverTextRevision(WORLD_CUP_PARTIAL, WORLD_CUP_FULL), true);
53
+ assert.equal(isDeliverTextRevision("abc", "abcdef"), true);
54
+ assert.equal(isDeliverTextRevision("abcdef", "abc"), true);
55
+ });
56
+ it("treats disjoint later chunk as not revision", () => {
57
+ assert.equal(isDeliverTextRevision(RT002_PART1, RT002_PART2), false);
58
+ });
59
+ });
60
+ describe("snapshotSupersedesBufferText", () => {
61
+ it("allows override when snapshot equals buffer after normalization", () => {
62
+ // buffer 用 \n\n 连接分块,snapshot 为连续段落(单 \n)→ 归一化后相等
63
+ const buffer = "第一段\n\n第二段";
64
+ const snapshot = "第一段\n第二段";
65
+ assert.equal(snapshotSupersedesBufferText(snapshot, buffer), true);
66
+ });
67
+ it("allows override when snapshot is a superset (full > chunk)", () => {
68
+ assert.equal(snapshotSupersedesBufferText(WORLD_CUP_FULL, WORLD_CUP_PARTIAL), true);
69
+ });
70
+ it("refuses override when snapshot lags behind buffer (would truncate)", () => {
71
+ // 竞态:快照还没追上 deliver 的完整块 → 不能覆盖,否则截断丢内容
72
+ assert.equal(snapshotSupersedesBufferText(WORLD_CUP_PARTIAL, WORLD_CUP_FULL), false);
73
+ });
74
+ it("empty snapshot never supersedes; empty buffer always superseded", () => {
75
+ assert.equal(snapshotSupersedesBufferText("", "abc"), false);
76
+ assert.equal(snapshotSupersedesBufferText("abc", ""), true);
77
+ });
78
+ });
40
79
  describe("TurnDeliverBuffer", () => {
41
- it("overwrites on multiple writes; final flush returns last version only", () => {
80
+ it("revision overwrite keeps last version (and media)", () => {
42
81
  const buf = new TurnDeliverBuffer();
43
82
  buf.write(entry(HOUTONG_BODY_LOOSE));
44
83
  buf.write(entry(HOUTONG_BODY_TIGHT));
@@ -49,12 +88,24 @@ describe("TurnDeliverBuffer", () => {
49
88
  assert.equal(final.entry.textPart, HOUTONG_BODY_TIGHT);
50
89
  assert.equal(final.entry.hasMedia, true);
51
90
  }
52
- assert.deepEqual(buf.getStats(), {
53
- writeCount: 3,
54
- flushInterimCount: 0,
55
- flushFinalCount: 1,
56
- skippedDuplicateFlushCount: 0,
57
- });
91
+ assert.equal(buf.getStats().writeCount, 3);
92
+ assert.ok(buf.getStats().revisionOverwriteCount >= 1);
93
+ assert.equal(buf.getStats().flushFinalCount, 1);
94
+ });
95
+ it("appends additive stream chunks so BEGIN is not lost", () => {
96
+ const buf = new TurnDeliverBuffer();
97
+ buf.write(entry(RT002_PART1));
98
+ buf.write(entry(RT002_PART2));
99
+ const final = buf.takeForFlush("final");
100
+ assert.equal(final.status, "ready");
101
+ if (final.status === "ready") {
102
+ assert.ok(final.entry.textPart.includes("BEGIN_123"));
103
+ assert.ok(final.entry.textPart.includes("## 六、审计"));
104
+ assert.ok(final.entry.textPart.includes(RT002_PART1.trim()));
105
+ assert.ok(final.entry.textPart.includes(RT002_PART2.trim()));
106
+ }
107
+ assert.equal(buf.getStats().segmentAppendCount, 1);
108
+ assert.equal(buf.getStats().revisionOverwriteCount, 0);
58
109
  });
59
110
  it("interim flush clears buffer; final holds post-tool segment", () => {
60
111
  const buf = new TurnDeliverBuffer();
@@ -114,6 +165,8 @@ describe("TurnDeliverBuffer", () => {
114
165
  if (final.status === "ready") {
115
166
  assert.equal(final.entry.textPart, WORLD_CUP_FULL);
116
167
  }
168
+ assert.equal(buf.getStats().revisionOverwriteCount, 1);
169
+ assert.equal(buf.getStats().segmentAppendCount, 0);
117
170
  });
118
171
  it("multi-tool: two interim + one final", () => {
119
172
  const buf = new TurnDeliverBuffer();