From 07a07b4cb03944122a44edf750af37393c25c4a2 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 1 May 2026 04:07:14 +0100 Subject: [PATCH] fix(discord): harden component sends --- .../discord/src/actions/handle-action.test.ts | 30 +++++++++++++++++++ .../discord/src/actions/handle-action.ts | 1 + 2 files changed, 31 insertions(+) diff --git a/extensions/discord/src/actions/handle-action.test.ts b/extensions/discord/src/actions/handle-action.test.ts index b6c2620e97c..1798be6bcbe 100644 --- a/extensions/discord/src/actions/handle-action.test.ts +++ b/extensions/discord/src/actions/handle-action.test.ts @@ -216,6 +216,36 @@ describe("handleDiscordMessageAction", () => { expect(handleDiscordActionMock).not.toHaveBeenCalled(); }); + it("forwards top-level components on sends", async () => { + const components = { blocks: [{ type: "text", text: "Pick one" }] }; + + await handleDiscordMessageAction({ + action: "send", + params: { + message: "hello", + components, + }, + cfg: { + channels: { discord: { token: "tok" } }, + } as OpenClawConfig, + toolContext: { + currentChannelProvider: "discord", + currentChannelId: "channel:123", + }, + }); + + expect(handleDiscordActionMock).toHaveBeenCalledWith( + expect.objectContaining({ + action: "sendMessage", + to: "channel:123", + content: "hello", + components, + }), + expect.any(Object), + expect.any(Object), + ); + }); + it("does not use another provider's current target for Discord sends", async () => { await expect( handleDiscordMessageAction({ diff --git a/extensions/discord/src/actions/handle-action.ts b/extensions/discord/src/actions/handle-action.ts index dda640aa26e..5d9c24db91a 100644 --- a/extensions/discord/src/actions/handle-action.ts +++ b/extensions/discord/src/actions/handle-action.ts @@ -81,6 +81,7 @@ export async function handleDiscordMessageAction( const to = readSendTarget(); const asVoice = readBooleanParam(params, "asVoice") === true; const rawComponents = + params.components ?? buildDiscordPresentationComponents(normalizeMessagePresentation(params.presentation)) ?? buildDiscordInteractiveComponents(normalizeInteractiveReply(params.interactive)); const hasComponents =