mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-02 11:17:13 +00:00
fix(routing): unify session delivery invariants for duplicate suppression (#33786)
* Routing: unify session delivery invariants * Routing: address PR review feedback * Routing: tighten topic and session-scope suppression * fix(chat): inherit routes for per-account channel-peer sessions
This commit is contained in:
@@ -4,6 +4,7 @@ import { normalizeChannelId } from "../../channels/plugins/index.js";
|
||||
import type { ReplyToMode } from "../../config/types.js";
|
||||
import { normalizeTargetForProvider } from "../../infra/outbound/target-normalization.js";
|
||||
import { normalizeOptionalAccountId } from "../../routing/account-id.js";
|
||||
import { parseTelegramTarget } from "../../telegram/targets.js";
|
||||
import type { OriginatingChannelType } from "../templating.js";
|
||||
import type { ReplyPayload } from "../types.js";
|
||||
import { extractReplyToTag } from "./reply-tags.js";
|
||||
@@ -162,6 +163,62 @@ function normalizeProviderForComparison(value?: string): string | undefined {
|
||||
return PROVIDER_ALIAS_MAP[lowered] ?? lowered;
|
||||
}
|
||||
|
||||
function normalizeThreadIdForComparison(value?: string): string | undefined {
|
||||
const trimmed = value?.trim();
|
||||
if (!trimmed) {
|
||||
return undefined;
|
||||
}
|
||||
if (/^-?\d+$/.test(trimmed)) {
|
||||
return String(Number.parseInt(trimmed, 10));
|
||||
}
|
||||
return trimmed.toLowerCase();
|
||||
}
|
||||
|
||||
function resolveTargetProviderForComparison(params: {
|
||||
currentProvider: string;
|
||||
targetProvider?: string;
|
||||
}): string {
|
||||
const targetProvider = normalizeProviderForComparison(params.targetProvider);
|
||||
if (!targetProvider || targetProvider === "message") {
|
||||
return params.currentProvider;
|
||||
}
|
||||
return targetProvider;
|
||||
}
|
||||
|
||||
function targetsMatchForSuppression(params: {
|
||||
provider: string;
|
||||
originTarget: string;
|
||||
targetKey: string;
|
||||
targetThreadId?: string;
|
||||
}): boolean {
|
||||
if (params.provider !== "telegram") {
|
||||
return params.targetKey === params.originTarget;
|
||||
}
|
||||
|
||||
const origin = parseTelegramTarget(params.originTarget);
|
||||
const target = parseTelegramTarget(params.targetKey);
|
||||
const explicitTargetThreadId = normalizeThreadIdForComparison(params.targetThreadId);
|
||||
const targetThreadId =
|
||||
explicitTargetThreadId ??
|
||||
(target.messageThreadId != null ? String(target.messageThreadId) : undefined);
|
||||
const originThreadId =
|
||||
origin.messageThreadId != null ? String(origin.messageThreadId) : undefined;
|
||||
if (origin.chatId.trim().toLowerCase() !== target.chatId.trim().toLowerCase()) {
|
||||
return false;
|
||||
}
|
||||
if (originThreadId && targetThreadId != null) {
|
||||
return originThreadId === targetThreadId;
|
||||
}
|
||||
if (originThreadId && targetThreadId == null) {
|
||||
return false;
|
||||
}
|
||||
if (!originThreadId && targetThreadId != null) {
|
||||
return false;
|
||||
}
|
||||
// chatId already matched and neither side carries thread context.
|
||||
return true;
|
||||
}
|
||||
|
||||
export function shouldSuppressMessagingToolReplies(params: {
|
||||
messageProvider?: string;
|
||||
messagingToolSentTargets?: MessagingToolSend[];
|
||||
@@ -182,16 +239,14 @@ export function shouldSuppressMessagingToolReplies(params: {
|
||||
return false;
|
||||
}
|
||||
return sentTargets.some((target) => {
|
||||
const targetProvider = normalizeProviderForComparison(target?.provider);
|
||||
if (!targetProvider) {
|
||||
const targetProvider = resolveTargetProviderForComparison({
|
||||
currentProvider: provider,
|
||||
targetProvider: target?.provider,
|
||||
});
|
||||
if (targetProvider !== provider) {
|
||||
return false;
|
||||
}
|
||||
const isGenericMessageProvider = targetProvider === "message";
|
||||
if (!isGenericMessageProvider && targetProvider !== provider) {
|
||||
return false;
|
||||
}
|
||||
const targetNormalizationProvider = isGenericMessageProvider ? provider : targetProvider;
|
||||
const targetKey = normalizeTargetForProvider(targetNormalizationProvider, target.to);
|
||||
const targetKey = normalizeTargetForProvider(targetProvider, target.to);
|
||||
if (!targetKey) {
|
||||
return false;
|
||||
}
|
||||
@@ -199,6 +254,11 @@ export function shouldSuppressMessagingToolReplies(params: {
|
||||
if (originAccount && targetAccount && originAccount !== targetAccount) {
|
||||
return false;
|
||||
}
|
||||
return targetKey === originTarget;
|
||||
return targetsMatchForSuppression({
|
||||
provider,
|
||||
originTarget,
|
||||
targetKey,
|
||||
targetThreadId: target.threadId,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user