diff --git a/src/agents/tools/discord-actions-messaging.ts b/src/agents/tools/discord-actions-messaging.ts index f90fb60de..77812c533 100644 --- a/src/agents/tools/discord-actions-messaging.ts +++ b/src/agents/tools/discord-actions-messaging.ts @@ -284,13 +284,33 @@ export async function handleDiscordMessagingAction( typeof autoArchiveMinutesRaw === "number" && Number.isFinite(autoArchiveMinutesRaw) ? autoArchiveMinutesRaw : undefined; + + // Forum channel support: initial message content + const messageContent = readStringParam(params, "content"); + const appliedTags = readStringArrayParam(params, "appliedTags"); + const embeds = + Array.isArray(params.embeds) && params.embeds.length > 0 ? params.embeds : undefined; + + const payload: Parameters[1] = { + name, + messageId, + autoArchiveMinutes, + }; + + // Add forum-specific fields if content is provided + if (messageContent) { + payload.message = { + content: messageContent, + embeds, + }; + } + if (appliedTags?.length) { + payload.appliedTags = appliedTags; + } + const thread = accountId - ? await createThreadDiscord( - channelId, - { name, messageId, autoArchiveMinutes }, - { accountId }, - ) - : await createThreadDiscord(channelId, { name, messageId, autoArchiveMinutes }); + ? await createThreadDiscord(channelId, payload, { accountId }) + : await createThreadDiscord(channelId, payload); return jsonResult({ ok: true, thread }); } case "threadList": { diff --git a/src/channels/plugins/actions/discord/handle-action.ts b/src/channels/plugins/actions/discord/handle-action.ts index 90e95d14d..f3300a7e0 100644 --- a/src/channels/plugins/actions/discord/handle-action.ts +++ b/src/channels/plugins/actions/discord/handle-action.ts @@ -183,6 +183,10 @@ export async function handleDiscordMessageAction( const autoArchiveMinutes = readNumberParam(params, "autoArchiveMin", { integer: true, }); + // Forum channel support + const content = readStringParam(params, "message"); + const appliedTags = readStringArrayParam(params, "appliedTags"); + const embeds = Array.isArray(params.embeds) ? params.embeds : undefined; return await handleDiscordAction( { action: "threadCreate", @@ -191,6 +195,9 @@ export async function handleDiscordMessageAction( name, messageId, autoArchiveMinutes, + content, + appliedTags, + embeds, }, cfg, ); diff --git a/src/discord/send.messages.ts b/src/discord/send.messages.ts index 93bc378d7..7eb24b7ee 100644 --- a/src/discord/send.messages.ts +++ b/src/discord/send.messages.ts @@ -97,6 +97,22 @@ export async function createThreadDiscord( if (payload.autoArchiveMinutes) { body.auto_archive_duration = payload.autoArchiveMinutes; } + + // Forum channels require a message object for the initial post + if (payload.message) { + body.message = { + content: payload.message.content, + ...(payload.message.embeds?.length ? { embeds: payload.message.embeds } : {}), + }; + } + + // Forum tags + if (payload.appliedTags?.length) { + body.applied_tags = payload.appliedTags; + } + + // For forum channels without messageId, use the channel threads endpoint + // For regular channels with messageId, use the message-based thread endpoint const route = Routes.threads(channelId, payload.messageId); return await rest.post(route, { body }); } diff --git a/src/discord/send.types.ts b/src/discord/send.types.ts index 5ea63366a..fbc7a7c01 100644 --- a/src/discord/send.types.ts +++ b/src/discord/send.types.ts @@ -66,10 +66,19 @@ export type DiscordMessageEdit = { content?: string; }; +export type DiscordForumMessage = { + content: string; + embeds?: unknown[]; +}; + export type DiscordThreadCreate = { messageId?: string; name: string; autoArchiveMinutes?: number; + /** Initial message content for forum posts (required for forum channels) */ + message?: DiscordForumMessage; + /** Tag IDs to apply to forum posts */ + appliedTags?: string[]; }; export type DiscordThreadList = {