From ca2ab303ba8614054d06d66e810fec22a1346b0c Mon Sep 17 00:00:00 2001 From: Solvely-Colin <211764741+Solvely-Colin@users.noreply.github.com> Date: Thu, 29 Jan 2026 14:12:06 +0000 Subject: [PATCH] discord: allow embeds/components in message tool send --- src/agents/tools/discord-actions-messaging.ts | 5 ++++ src/agents/tools/message-tool.ts | 24 +++++++++++++++++++ .../plugins/actions/discord/handle-action.ts | 2 ++ src/discord/send.outbound.ts | 3 +++ src/discord/send.shared.ts | 6 +++++ 5 files changed, 40 insertions(+) diff --git a/src/agents/tools/discord-actions-messaging.ts b/src/agents/tools/discord-actions-messaging.ts index 562baa50e..31b3ff002 100644 --- a/src/agents/tools/discord-actions-messaging.ts +++ b/src/agents/tools/discord-actions-messaging.ts @@ -233,11 +233,16 @@ export async function handleDiscordMessagingAction( const replyTo = readStringParam(params, "replyTo"); const embeds = Array.isArray(params.embeds) && params.embeds.length > 0 ? params.embeds : undefined; + const components = + Array.isArray(params.components) && params.components.length > 0 + ? params.components + : undefined; const result = await sendMessageDiscord(to, content, { ...(accountId ? { accountId } : {}), mediaUrl, replyTo, embeds, + components, }); return jsonResult({ ok: true, result }); } diff --git a/src/agents/tools/message-tool.ts b/src/agents/tools/message-tool.ts index 4ea178a54..4fc457b40 100644 --- a/src/agents/tools/message-tool.ts +++ b/src/agents/tools/message-tool.ts @@ -87,6 +87,30 @@ function buildSendSchema(options: { includeButtons: boolean; includeCards: boole }, ), ), + embeds: Type.Optional( + Type.Array( + Type.Object( + {}, + { + additionalProperties: true, + description: + "Provider-specific embed objects (Discord embeds, etc.). Passed through to the channel adapter when supported.", + }, + ), + ), + ), + components: Type.Optional( + Type.Array( + Type.Object( + {}, + { + additionalProperties: true, + description: + "Provider-specific message components (Discord buttons/selects, etc.). Passed through when supported.", + }, + ), + ), + ), }; if (!options.includeButtons) delete props.buttons; if (!options.includeCards) delete props.card; diff --git a/src/channels/plugins/actions/discord/handle-action.ts b/src/channels/plugins/actions/discord/handle-action.ts index 94189eef0..f4f06be27 100644 --- a/src/channels/plugins/actions/discord/handle-action.ts +++ b/src/channels/plugins/actions/discord/handle-action.ts @@ -37,6 +37,7 @@ export async function handleDiscordMessageAction( const mediaUrl = readStringParam(params, "media", { trim: false }); const replyTo = readStringParam(params, "replyTo"); const embeds = Array.isArray(params.embeds) ? params.embeds : undefined; + const components = Array.isArray(params.components) ? params.components : undefined; return await handleDiscordAction( { action: "sendMessage", @@ -46,6 +47,7 @@ export async function handleDiscordMessageAction( mediaUrl: mediaUrl ?? undefined, replyTo: replyTo ?? undefined, embeds, + components, }, cfg, ); diff --git a/src/discord/send.outbound.ts b/src/discord/send.outbound.ts index a47d0f4f1..c42d9c809 100644 --- a/src/discord/send.outbound.ts +++ b/src/discord/send.outbound.ts @@ -29,6 +29,7 @@ type DiscordSendOpts = { replyTo?: string; retry?: RetryConfig; embeds?: unknown[]; + components?: unknown[]; }; export async function sendMessageDiscord( @@ -63,6 +64,7 @@ export async function sendMessageDiscord( request, accountInfo.config.maxLinesPerMessage, opts.embeds, + opts.components, chunkMode, ); } else { @@ -74,6 +76,7 @@ export async function sendMessageDiscord( request, accountInfo.config.maxLinesPerMessage, opts.embeds, + opts.components, chunkMode, ); } diff --git a/src/discord/send.shared.ts b/src/discord/send.shared.ts index 4919be29d..26d975657 100644 --- a/src/discord/send.shared.ts +++ b/src/discord/send.shared.ts @@ -232,6 +232,7 @@ async function sendDiscordText( request: DiscordRequest, maxLinesPerMessage?: number, embeds?: unknown[], + components?: unknown[], chunkMode?: ChunkMode, ) { if (!text.trim()) { @@ -252,6 +253,7 @@ async function sendDiscordText( content: chunks[0], message_reference: messageReference, ...(embeds?.length ? { embeds } : {}), + ...(components?.length ? { components } : {}), }, }) as Promise<{ id: string; channel_id: string }>, "text", @@ -268,6 +270,7 @@ async function sendDiscordText( content: chunk, message_reference: isFirst ? messageReference : undefined, ...(isFirst && embeds?.length ? { embeds } : {}), + ...(isFirst && components?.length ? { components } : {}), }, }) as Promise<{ id: string; channel_id: string }>, "text", @@ -289,6 +292,7 @@ async function sendDiscordMedia( request: DiscordRequest, maxLinesPerMessage?: number, embeds?: unknown[], + components?: unknown[], chunkMode?: ChunkMode, ) { const media = await loadWebMedia(mediaUrl); @@ -309,6 +313,7 @@ async function sendDiscordMedia( content: caption || undefined, message_reference: messageReference, ...(embeds?.length ? { embeds } : {}), + ...(components?.length ? { components } : {}), files: [ { data: media.buffer, @@ -329,6 +334,7 @@ async function sendDiscordMedia( request, maxLinesPerMessage, undefined, + undefined, chunkMode, ); }