From 9e6b45faab44200382bc34c4f14bea5ca24a289f Mon Sep 17 00:00:00 2001 From: Paul Pamment Date: Mon, 26 Jan 2026 17:00:34 +0000 Subject: [PATCH] fix(discord): honor threadId for thread-reply --- src/channels/plugins/actions/discord.test.ts | 26 +++++++++++++++++++ .../discord/handle-action.guild-admin.ts | 8 +++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/channels/plugins/actions/discord.test.ts b/src/channels/plugins/actions/discord.test.ts index 67047410e..9cc184e6c 100644 --- a/src/channels/plugins/actions/discord.test.ts +++ b/src/channels/plugins/actions/discord.test.ts @@ -127,4 +127,30 @@ describe("handleDiscordMessageAction", () => { }), ); }); + + it("accepts threadId for thread replies (tool compatibility)", async () => { + sendMessageDiscord.mockClear(); + const handleDiscordMessageAction = await loadHandleDiscordMessageAction(); + + await handleDiscordMessageAction({ + action: "thread-reply", + params: { + // The `message` tool uses `threadId`. + threadId: "999", + // Include a conflicting channelId to ensure threadId takes precedence. + channelId: "123", + message: "hi", + }, + cfg: {} as ClawdbotConfig, + accountId: "ops", + }); + + expect(sendMessageDiscord).toHaveBeenCalledWith( + "channel:999", + "hi", + expect.objectContaining({ + accountId: "ops", + }), + ); + }); }); diff --git a/src/channels/plugins/actions/discord/handle-action.guild-admin.ts b/src/channels/plugins/actions/discord/handle-action.guild-admin.ts index d65d044e2..5a3b13f61 100644 --- a/src/channels/plugins/actions/discord/handle-action.guild-admin.ts +++ b/src/channels/plugins/actions/discord/handle-action.guild-admin.ts @@ -393,11 +393,17 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: { }); const mediaUrl = readStringParam(actionParams, "media", { trim: false }); const replyTo = readStringParam(actionParams, "replyTo"); + + // `message.thread-reply` (tool) uses `threadId`, while the CLI historically used `to`/`channelId`. + // Prefer `threadId` when present to avoid accidentally replying in the parent channel. + const threadId = readStringParam(actionParams, "threadId"); + const channelId = threadId ?? resolveChannelId(); + return await handleDiscordAction( { action: "threadReply", accountId: accountId ?? undefined, - channelId: resolveChannelId(), + channelId, content, mediaUrl: mediaUrl ?? undefined, replyTo: replyTo ?? undefined,