Skip to content

Commit 544851d

Browse files
authored
Merge 6483c49 into 67e1d43
2 parents 67e1d43 + 6483c49 commit 544851d

4 files changed

Lines changed: 69 additions & 2 deletions

File tree

src/agents/embedded-agent-helpers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export { sanitizeSessionMessagesImages } from "./embedded-agent-helpers/images.j
6464
export {
6565
isMessagingToolDuplicate,
6666
isMessagingToolDuplicateNormalized,
67+
isPostToolSendMetaAck,
6768
normalizeTextForComparison,
6869
} from "./embedded-agent-helpers/messaging-dedupe.js";
6970

src/agents/embedded-agent-helpers/messaging-dedupe.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/st
55

66
const MIN_DUPLICATE_TEXT_LENGTH = 10;
77
const MIN_REVERSE_SUBSTRING_DUPLICATE_RATIO = 0.5;
8+
const MAX_POST_TOOL_SEND_META_ACK_LENGTH = 80;
9+
const POST_TOOL_SEND_META_ACK_PATTERNS: readonly RegExp[] = [
10+
/^(?:(?:||)?|(?:|)?||(?:|)?)(?:[\s,.!:-]*(?:[#][\p{L}\p{N}_-]+|\d+|\((?:[#][\p{L}\p{N}_-]+|\d+)\)|(?:||)?))?[\s.!]*$/iu,
11+
/^(?:|||(?:||)?)[\s.!:]*$/u,
12+
/^(?:sent(?:\s+(?:above|already|[#][\p{L}\p{N}_-]+))?|posted|done|ok(?:ay)?|roger|got\s+it|ack(?:nowledged)?|replied\s+above)(?:[\s,.!:-]*(?:replied\s+(?:above|in\s+thread)|that's\s+the\s+fix|no\s+more\s+content))?[\s.!]*$/iu,
13+
];
814

915
/**
1016
* Normalize text for duplicate comparison.
@@ -20,6 +26,14 @@ export function normalizeTextForComparison(text: string): string {
2026
.trim();
2127
}
2228

29+
export function isPostToolSendMetaAck(text: string): boolean {
30+
const normalized = normalizeTextForComparison(text);
31+
if (!normalized || normalized.length > MAX_POST_TOOL_SEND_META_ACK_LENGTH) {
32+
return false;
33+
}
34+
return POST_TOOL_SEND_META_ACK_PATTERNS.some((pattern) => pattern.test(normalized));
35+
}
36+
2337
/** Compare already-normalized message text against prior sends. */
2438
export function isMessagingToolDuplicateNormalized(
2539
normalized: string,

src/auto-reply/reply/followup-delivery.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,54 @@ describe("resolveFollowupDeliveryPayloads", () => {
321321
).toEqual([{ text: "hello world!" }]);
322322
});
323323

324+
it("drops short trailing meta acknowledgements after a same-route message tool send", () => {
325+
expect(
326+
resolveFollowupDeliveryPayloads({
327+
cfg: baseConfig,
328+
payloads: [
329+
{ text: "已发 #22141" },
330+
{ text: "Sent above" },
331+
{ text: "核心回答如下" },
332+
{ text: "OK" },
333+
],
334+
messageProvider: "telegram",
335+
originatingTo: "telegram:123",
336+
sentTargets: [
337+
{
338+
tool: "message",
339+
provider: "telegram",
340+
to: "telegram:123",
341+
text: "完整主回复内容已经通过 message tool 发出",
342+
},
343+
],
344+
}),
345+
).toStrictEqual([]);
346+
});
347+
348+
it("drops compound meta acknowledgements without dropping substantive short replies", () => {
349+
expect(
350+
resolveFollowupDeliveryPayloads({
351+
cfg: baseConfig,
352+
payloads: [
353+
{ text: "已发, 不再追加总结" },
354+
{ text: "Sent. Replied in thread." },
355+
{ text: "OK, that's the fix." },
356+
{ text: "OK, here is the actual answer." },
357+
],
358+
messageProvider: "telegram",
359+
originatingTo: "telegram:123",
360+
sentTargets: [
361+
{
362+
tool: "message",
363+
provider: "telegram",
364+
to: "telegram:123",
365+
text: "完整主回复内容已经通过 message tool 发出",
366+
},
367+
],
368+
}),
369+
).toEqual([{ text: "OK, here is the actual answer." }]);
370+
});
371+
324372
it("dedupes duplicate replies when a messaging tool already sent to the same provider and target", () => {
325373
expect(
326374
resolveFollowupDeliveryPayloads({

src/auto-reply/reply/reply-payloads-dedupe.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import {
33
normalizeLowercaseStringOrEmpty,
44
normalizeOptionalString,
55
} from "@openclaw/normalization-core/string-coerce";
6-
import { isMessagingToolDuplicate } from "../../agents/embedded-agent-helpers.js";
6+
import {
7+
isMessagingToolDuplicate,
8+
isPostToolSendMetaAck,
9+
} from "../../agents/embedded-agent-helpers.js";
710
import type { MessagingToolSend } from "../../agents/embedded-agent-messaging.types.js";
811
import { getChannelPlugin } from "../../channels/plugins/index.js";
912
import { getLoadedChannelPluginForRead } from "../../channels/plugins/registry-loaded-read.js";
@@ -31,7 +34,8 @@ export function filterMessagingToolDuplicates(params: {
3134
if (payload.mediaUrl || payload.mediaUrls?.length) {
3235
return true;
3336
}
34-
return !isMessagingToolDuplicate(payload.text ?? "", sentTexts);
37+
const text = payload.text ?? "";
38+
return !isMessagingToolDuplicate(text, sentTexts) && !isPostToolSendMetaAck(text);
3539
});
3640
}
3741

0 commit comments

Comments
 (0)