From 3f0f6580800fbc4127680e1b6b569eca7206db91 Mon Sep 17 00:00:00 2001 From: Xu Zimo Date: Tue, 3 Mar 2026 22:10:30 +0800 Subject: [PATCH] fix: normalize Feishu delivery.to before comparing with messaging tool targets - Add normalizeDeliveryTarget helper to strip user:/chat: prefixes for Feishu - Apply normalization in matchesMessagingToolDeliveryTarget before comparison - This ensures cron duplicate suppression works when session uses prefixed targets (user:ou_xxx) but messaging tool extract uses normalized bare IDs (ou_xxx) Fixes review comment on PR #32755 (cherry picked from commit fc20106f16ccc88a5f02e58922bb7b7999fe9dcd) --- src/cron/isolated-agent/delivery-dispatch.ts | 25 ++++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/cron/isolated-agent/delivery-dispatch.ts b/src/cron/isolated-agent/delivery-dispatch.ts index 272f327fd8e..39ab40843c4 100644 --- a/src/cron/isolated-agent/delivery-dispatch.ts +++ b/src/cron/isolated-agent/delivery-dispatch.ts @@ -21,6 +21,21 @@ import { waitForDescendantSubagentSummary, } from "./subagent-followup.js"; +function normalizeDeliveryTarget(channel: string, to: string): string { + const channelLower = channel.trim().toLowerCase(); + const toTrimmed = to.trim(); + if (channelLower === "feishu" || channelLower === "lark") { + const lowered = toTrimmed.toLowerCase(); + if (lowered.startsWith("user:")) { + return toTrimmed.slice("user:".length).trim(); + } + if (lowered.startsWith("chat:")) { + return toTrimmed.slice("chat:".length).trim(); + } + } + return toTrimmed; +} + export function matchesMessagingToolDeliveryTarget( target: { provider?: string; to?: string; accountId?: string }, delivery: { channel?: string; to?: string; accountId?: string }, @@ -36,11 +51,11 @@ export function matchesMessagingToolDeliveryTarget( if (target.accountId && delivery.accountId && target.accountId !== delivery.accountId) { return false; } - // Strip :topic:NNN suffix from target.to before comparing — the cron delivery.to - // is already stripped to chatId only, but the agent's message tool may pass a - // topic-qualified target (e.g. "-1003597428309:topic:462"). - const normalizedTargetTo = target.to.replace(/:topic:\d+$/, ""); - return normalizedTargetTo === delivery.to; + // Strip :topic:NNN from message targets and normalize Feishu/Lark prefixes on + // both sides so cron duplicate suppression compares canonical IDs. + const normalizedTargetTo = normalizeDeliveryTarget(channel, target.to.replace(/:topic:\d+$/, "")); + const normalizedDeliveryTo = normalizeDeliveryTarget(channel, delivery.to); + return normalizedTargetTo === normalizedDeliveryTo; } export function resolveCronDeliveryBestEffort(job: CronJob): boolean {