From cd1480d637ab89190bdbfb82078df50cbbbcfd50 Mon Sep 17 00:00:00 2001 From: Lalit Singh Date: Wed, 28 Jan 2026 15:42:30 +0100 Subject: [PATCH 1/2] fix(discord): respect replyToMode in threads Previously, when replying in Discord threads, the replyToMode setting was ignored because existingId was checked before replyToMode. This caused reply references to be added even when replyToMode was set to 'off'. This fix moves the replyToMode check before the existingId check, ensuring that replyToMode: 'off' is respected in all contexts including threads. --- src/auto-reply/reply/reply-reference.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/auto-reply/reply/reply-reference.ts b/src/auto-reply/reply/reply-reference.ts index 33dda2098..4251309ac 100644 --- a/src/auto-reply/reply/reply-reference.ts +++ b/src/auto-reply/reply/reply-reference.ts @@ -11,7 +11,7 @@ export type ReplyReferencePlanner = { export function createReplyReferencePlanner(options: { replyToMode: ReplyToMode; - /** Existing thread/reference id (always used when present). */ + /** Existing thread/reference id (used when present, unless replyToMode is "off"). */ existingId?: string; /** Id to start a new thread/reference when allowed (e.g., parent message id). */ startId?: string; @@ -27,12 +27,12 @@ export function createReplyReferencePlanner(options: { const use = (): string | undefined => { if (!allowReference) return undefined; + if (options.replyToMode === "off") return undefined; if (existingId) { hasReplied = true; return existingId; } if (!startId) return undefined; - if (options.replyToMode === "off") return undefined; if (options.replyToMode === "all") { hasReplied = true; return startId; From 20e0a535fbb034548845034bc24c8f721104edf9 Mon Sep 17 00:00:00 2001 From: Lalit Singh Date: Wed, 28 Jan 2026 15:52:28 +0100 Subject: [PATCH 2/2] fix(discord): respect replyToMode in threads The issue was that Discord threads always included a message_reference (reply indicator) regardless of replyToMode setting. The fix is Discord-specific: don't pass existingId to the reply planner when replyToMode is 'off'. This prevents reply references in threads while preserving the existing Slack behavior where existingId (thread_ts) is needed to keep messages in the correct thread. - Updated resolveDiscordReplyDeliveryPlan to check replyToMode before setting existingId - Updated tests to reflect new behavior --- src/auto-reply/reply/reply-reference.ts | 4 ++-- src/discord/monitor/threading.test.ts | 13 ++++++++++++- src/discord/monitor/threading.ts | 9 +++++++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/auto-reply/reply/reply-reference.ts b/src/auto-reply/reply/reply-reference.ts index 4251309ac..33dda2098 100644 --- a/src/auto-reply/reply/reply-reference.ts +++ b/src/auto-reply/reply/reply-reference.ts @@ -11,7 +11,7 @@ export type ReplyReferencePlanner = { export function createReplyReferencePlanner(options: { replyToMode: ReplyToMode; - /** Existing thread/reference id (used when present, unless replyToMode is "off"). */ + /** Existing thread/reference id (always used when present). */ existingId?: string; /** Id to start a new thread/reference when allowed (e.g., parent message id). */ startId?: string; @@ -27,12 +27,12 @@ export function createReplyReferencePlanner(options: { const use = (): string | undefined => { if (!allowReference) return undefined; - if (options.replyToMode === "off") return undefined; if (existingId) { hasReplied = true; return existingId; } if (!startId) return undefined; + if (options.replyToMode === "off") return undefined; if (options.replyToMode === "all") { hasReplied = true; return startId; diff --git a/src/discord/monitor/threading.test.ts b/src/discord/monitor/threading.test.ts index 34377869f..6466581ef 100644 --- a/src/discord/monitor/threading.test.ts +++ b/src/discord/monitor/threading.test.ts @@ -74,7 +74,7 @@ describe("resolveDiscordReplyDeliveryPlan", () => { expect(plan.replyReference.use()).toBeUndefined(); }); - it("always uses existingId when inside a thread", () => { + it("respects replyToMode off when inside a thread", () => { const plan = resolveDiscordReplyDeliveryPlan({ replyTarget: "channel:thread", replyToMode: "off", @@ -82,6 +82,17 @@ describe("resolveDiscordReplyDeliveryPlan", () => { threadChannel: { id: "thread" }, createdThreadId: null, }); + expect(plan.replyReference.use()).toBeUndefined(); + }); + + it("uses message reference when inside a thread with replyToMode first", () => { + const plan = resolveDiscordReplyDeliveryPlan({ + replyTarget: "channel:thread", + replyToMode: "first", + messageId: "m1", + threadChannel: { id: "thread" }, + createdThreadId: null, + }); expect(plan.replyReference.use()).toBe("m1"); }); }); diff --git a/src/discord/monitor/threading.ts b/src/discord/monitor/threading.ts index 71af6408f..f311949a8 100644 --- a/src/discord/monitor/threading.ts +++ b/src/discord/monitor/threading.ts @@ -304,9 +304,14 @@ export function resolveDiscordReplyDeliveryPlan(params: { replyTarget = deliverTarget; } const allowReference = deliverTarget === originalReplyTarget; + const effectiveReplyToMode = allowReference ? params.replyToMode : "off"; + // Don't pass existingId when replyToMode is "off" - this prevents + // unwanted reply references in threads when the user has disabled them + const existingId = + params.threadChannel && effectiveReplyToMode !== "off" ? params.messageId : undefined; const replyReference = createReplyReferencePlanner({ - replyToMode: allowReference ? params.replyToMode : "off", - existingId: params.threadChannel ? params.messageId : undefined, + replyToMode: effectiveReplyToMode, + existingId, startId: params.messageId, allowReference, });