diff --git a/extensions/slack/src/message-action-dispatch.test.ts b/extensions/slack/src/message-action-dispatch.test.ts index 6194b5a9111b..059a6142fa8c 100644 --- a/extensions/slack/src/message-action-dispatch.test.ts +++ b/extensions/slack/src/message-action-dispatch.test.ts @@ -731,6 +731,26 @@ describe("handleSlackMessageAction", () => { }); it.each([ + { + name: "prefers an explicit reply target over an inherited Slack thread", + params: { + to: "channel:C1", + message: "Reply to the requested message", + threadId: "111.222", + replyTo: "999.000", + }, + expected: { content: "Reply to the requested message", threadTs: "999.000" }, + }, + { + name: "falls back to the Slack thread when the reply target is not a timestamp", + params: { + to: "channel:C1", + message: "Reply in the current thread", + threadId: "111.222", + replyTo: "msg-internal-1", + }, + expected: { content: "Reply in the current thread", threadTs: "111.222" }, + }, { name: "passes replyBroadcast through for Slack thread sends", params: { diff --git a/extensions/slack/src/message-action-dispatch.ts b/extensions/slack/src/message-action-dispatch.ts index 430cfb7b870e..3d1f03b41335 100644 --- a/extensions/slack/src/message-action-dispatch.ts +++ b/extensions/slack/src/message-action-dispatch.ts @@ -24,6 +24,7 @@ import { resolveSlackReplyDeliveryMessages, type SlackReplyDeliveryMessage, } from "./reply-blocks.js"; +import { resolveSlackThreadTsValue } from "./thread-ts.js"; import { countSlackTextUtf8Bytes } from "./truncate.js"; type SlackActionInvoke = ( @@ -140,7 +141,7 @@ export async function handleSlackMessageAction(params: { mediaUrl: mediaUrl ?? undefined, ...(readSlackForceDocument(actionParams) ? { forceDocument: true } : {}), accountId, - threadTs: threadId ?? replyTo ?? undefined, + threadTs: resolveSlackThreadTsValue({ replyToId: replyTo, threadId }), ...(topLevel ? { topLevel: true } : {}), ...(replyBroadcast ? { replyBroadcast } : {}), },