




















@@ -57,6 +57,7 @@ import {
5757resolveAgentDir,
5858resolveDefaultModelForAgent,
5959} from "./bot-message-dispatch.agent.runtime.js";
60+import { deduplicateBlockSentMedia } from "./bot-message-dispatch.media-dedup.js";
6061import { pruneStickerMediaFromContext } from "./bot-message-dispatch.media.js";
6162import {
6263generateTopicLabel,
@@ -1164,8 +1165,14 @@ export const dispatchTelegramMessage = async ({
11641165 ctxPayload,
11651166recordInboundSession: context.turn.recordInboundSession,
11661167record: context.turn.record,
1167-runDispatch: () =>
1168-telegramDeps.dispatchReplyWithBufferedBlockDispatcher({
1168+runDispatch: () => {
1169+// Track media URLs delivered via block replies so final replies
1170+// can skip duplicates. Without this, non-streaming Telegram
1171+// delivers each MEDIA: attachment twice — once from the
1172+// media-only block reply and once from the final reply.
1173+const sentBlockMediaUrls = new Set<string>();
1174+1175+return telegramDeps.dispatchReplyWithBufferedBlockDispatcher({
11691176ctx: ctxPayload,
11701177 cfg,
11711178dispatcherOptions: {
@@ -1178,6 +1185,25 @@ export const dispatchTelegramMessage = async ({
11781185if (payload.isError === true) {
11791186hadErrorReplyFailureOrSkip = true;
11801187}
1188+1189+// Track media URLs from block replies so final replies
1190+// can skip duplicates (non-streaming MEDIA: dedup).
1191+if (info.kind === "block" && payload.mediaUrls?.length) {
1192+for (const url of payload.mediaUrls) {
1193+sentBlockMediaUrls.add(url);
1194+}
1195+}
1196+1197+// Filter out media already sent via block reply.
1198+const deduped =
1199+info.kind === "final"
1200+ ? deduplicateBlockSentMedia(payload, sentBlockMediaUrls)
1201+ : payload;
1202+if (deduped === undefined) {
1203+return;
1204+}
1205+const effectivePayload = deduped;
1206+11811207if (info.kind === "final") {
11821208await enqueueDraftLaneEvent(async () => {});
11831209}
@@ -1192,16 +1218,16 @@ export const dispatchTelegramMessage = async ({
11921218return;
11931219}
11941220const telegramButtons = (
1195-payload.channelData?.telegram as
1221+effectivePayload.channelData?.telegram as
11961222| { buttons?: TelegramInlineButtons }
11971223| undefined
11981224)?.buttons;
11991225const split = splitTextIntoLaneSegments(
1200-{ text: payload.text },
1226+{ text: effectivePayload.text },
12011227payload.isReasoning,
12021228);
12031229const segments = split.segments;
1204-const reply = resolveSendableOutboundReplyParts(payload);
1230+const reply = resolveSendableOutboundReplyParts(effectivePayload);
12051231const _hasMedia = reply.hasMedia;
1206123212071233const flushBufferedFinalAnswer = async () => {
@@ -1232,7 +1258,7 @@ export const dispatchTelegramMessage = async ({
12321258reasoningStepState.shouldBufferFinalAnswer()
12331259) {
12341260reasoningStepState.bufferFinalAnswer({
1235- payload,
1261+payload: effectivePayload,
12361262text: segment.update.text,
12371263bufferedGeneration: replyFenceGeneration,
12381264});
@@ -1245,11 +1271,14 @@ export const dispatchTelegramMessage = async ({
12451271streamMode === "progress" &&
12461272segment.lane === "answer" &&
12471273info.kind === "final"
1248- ? await deliverProgressModeFinalAnswer(payload, segment.update.text)
1274+ ? await deliverProgressModeFinalAnswer(
1275+effectivePayload,
1276+segment.update.text,
1277+)
12491278 : await deliverLaneText({
12501279laneName: segment.lane,
12511280text: segment.update.text,
1252- payload,
1281+payload: effectivePayload,
12531282infoKind: info.kind,
12541283buttons: telegramButtons,
12551284});
@@ -1273,7 +1302,9 @@ export const dispatchTelegramMessage = async ({
12731302if (split.suppressedReasoningOnly) {
12741303if (reply.hasMedia) {
12751304const payloadWithoutSuppressedReasoning =
1276-typeof payload.text === "string" ? { ...payload, text: "" } : payload;
1305+typeof effectivePayload.text === "string"
1306+ ? { ...effectivePayload, text: "" }
1307+ : effectivePayload;
12771308await sendPayload(payloadWithoutSuppressedReasoning, {
12781309durable: info.kind === "final",
12791310});
@@ -1296,7 +1327,7 @@ export const dispatchTelegramMessage = async ({
12961327}
12971328return;
12981329}
1299-await sendPayload(payload, { durable: info.kind === "final" });
1330+await sendPayload(effectivePayload, { durable: info.kind === "final" });
13001331if (info.kind === "final") {
13011332await flushBufferedFinalAnswer();
13021333}
@@ -1488,7 +1519,8 @@ export const dispatchTelegramMessage = async ({
14881519 : undefined,
14891520 onModelSelected,
14901521},
1491-}),
1522+});
1523+},
14921524}),
14931525},
14941526});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。