























@@ -343,6 +343,10 @@ export async function dispatchReplyFromConfig(
343343recordProcessed("skipped", { reason: "duplicate" });
344344return { queuedFinal: false, counts: dispatcher.getQueuedCounts() };
345345}
346+let inboundDedupeReplayUnsafe = false;
347+const markInboundDedupeReplayUnsafe = () => {
348+inboundDedupeReplayUnsafe = true;
349+};
346350347351const initialSessionStoreEntry = resolveSessionStoreLookup(ctx, cfg);
348352const boundAcpDispatchSessionKey = resolveBoundAcpDispatchSessionKey({ ctx, cfg });
@@ -473,6 +477,7 @@ export async function dispatchReplyFromConfig(
473477if (!shouldRouteToOriginating || !routeReplyChannel || !routeReplyTo || !routeReplyRuntime) {
474478return null;
475479}
480+markInboundDedupeReplayUnsafe();
476481return await routeReplyRuntime.routeReply({
477482 payload,
478483channel: routeReplyChannel,
@@ -538,6 +543,7 @@ export async function dispatchReplyFromConfig(
538543}
539544return result.ok;
540545}
546+markInboundDedupeReplayUnsafe();
541547return mode === "additive"
542548 ? dispatcher.sendToolResult(payload)
543549 : dispatcher.sendFinalReply(payload);
@@ -721,6 +727,7 @@ export async function dispatchReplyFromConfig(
721727);
722728}
723729} else {
730+markInboundDedupeReplayUnsafe();
724731queuedFinal = dispatcher.sendFinalReply(payload);
725732}
726733} else {
@@ -744,6 +751,9 @@ export async function dispatchReplyFromConfig(
744751const sendFinalPayload = async (
745752payload: ReplyPayload,
746753): Promise<{ queuedFinal: boolean; routedFinalCount: number }> => {
754+if (resolveSendableOutboundReplyParts(payload).hasContent) {
755+markInboundDedupeReplayUnsafe();
756+}
747757const ttsPayload = await maybeApplyTtsToReplyPayload({
748758 payload,
749759 cfg,
@@ -767,6 +777,7 @@ export async function dispatchReplyFromConfig(
767777routedFinalCount: result.ok ? 1 : 0,
768778};
769779}
780+markInboundDedupeReplayUnsafe();
770781return {
771782queuedFinal: dispatcher.sendFinalReply(normalizedPayload),
772783routedFinalCount: 0,
@@ -898,6 +909,7 @@ export async function dispatchReplyFromConfig(
898909await sendPayloadAsync(payload, undefined, false);
899910return;
900911}
912+markInboundDedupeReplayUnsafe();
901913dispatcher.sendToolResult(payload);
902914};
903915const sendPlanUpdate = async (payload: {
@@ -914,6 +926,7 @@ export async function dispatchReplyFromConfig(
914926await sendPayloadAsync(replyPayload, undefined, false);
915927return;
916928}
929+markInboundDedupeReplayUnsafe();
917930dispatcher.sendToolResult(replyPayload);
918931};
919932const summarizeApprovalLabel = (payload: {
@@ -1019,6 +1032,7 @@ export async function dispatchReplyFromConfig(
10191032suppressTyping: typing.suppressTyping,
10201033onToolResult: (payload: ReplyPayload) => {
10211034const run = async () => {
1035+markInboundDedupeReplayUnsafe();
10221036await onToolResultFromReplyOptions?.(payload);
10231037if (suppressDelivery) {
10241038return;
@@ -1055,19 +1069,22 @@ export async function dispatchReplyFromConfig(
10551069if (shouldRouteToOriginating) {
10561070await sendPayloadAsync(deliveryPayload, undefined, false);
10571071} else {
1072+markInboundDedupeReplayUnsafe();
10581073dispatcher.sendToolResult(deliveryPayload);
10591074}
10601075};
10611076return run();
10621077},
10631078onPlanUpdate: async (payload) => {
1079+markInboundDedupeReplayUnsafe();
10641080await onPlanUpdateFromReplyOptions?.(payload);
10651081if (payload.phase !== "update" || suppressDefaultToolProgressMessages) {
10661082return;
10671083}
10681084await sendPlanUpdate({ explanation: payload.explanation, steps: payload.steps });
10691085},
10701086onApprovalEvent: async (payload) => {
1087+markInboundDedupeReplayUnsafe();
10711088await onApprovalEventFromReplyOptions?.(payload);
10721089if (payload.phase !== "requested" || suppressDefaultToolProgressMessages) {
10731090return;
@@ -1083,6 +1100,7 @@ export async function dispatchReplyFromConfig(
10831100await maybeSendWorkingStatus(label);
10841101},
10851102onPatchSummary: async (payload) => {
1103+markInboundDedupeReplayUnsafe();
10861104await onPatchSummaryFromReplyOptions?.(payload);
10871105if (payload.phase !== "end" || suppressDefaultToolProgressMessages) {
10881106return;
@@ -1095,6 +1113,12 @@ export async function dispatchReplyFromConfig(
10951113},
10961114onBlockReply: (payload: ReplyPayload, context?: BlockReplyContext) => {
10971115const run = async () => {
1116+if (
1117+payload.isReasoning !== true &&
1118+resolveSendableOutboundReplyParts(payload).hasContent
1119+) {
1120+markInboundDedupeReplayUnsafe();
1121+}
10981122if (suppressDelivery) {
10991123return;
11001124}
@@ -1156,6 +1180,7 @@ export async function dispatchReplyFromConfig(
11561180if (shouldRouteToOriginating) {
11571181await sendPayloadAsync(normalizedPayload, context?.abortSignal, false);
11581182} else {
1183+markInboundDedupeReplayUnsafe();
11591184dispatcher.sendBlockReply(normalizedPayload);
11601185}
11611186};
@@ -1268,6 +1293,7 @@ export async function dispatchReplyFromConfig(
12681293);
12691294}
12701295} else {
1296+markInboundDedupeReplayUnsafe();
12711297const didQueue = dispatcher.sendFinalReply(normalizedTtsOnlyPayload);
12721298queuedFinal = didQueue || queuedFinal;
12731299}
@@ -1293,7 +1319,11 @@ export async function dispatchReplyFromConfig(
12931319return { queuedFinal, counts };
12941320} catch (err) {
12951321if (inboundDedupeClaim.status === "claimed") {
1296-releaseInboundDedupe(inboundDedupeClaim.key);
1322+if (inboundDedupeReplayUnsafe) {
1323+commitInboundDedupe(inboundDedupeClaim.key);
1324+} else {
1325+releaseInboundDedupe(inboundDedupeClaim.key);
1326+}
12971327}
12981328recordProcessed("error", { error: String(err) });
12991329markIdle("message_error");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。