diff --git a/extensions/discord/src/channel-actions.ts b/extensions/discord/src/channel-actions.ts index 89e5abf682d..c4be7728439 100644 --- a/extensions/discord/src/channel-actions.ts +++ b/extensions/discord/src/channel-actions.ts @@ -6,6 +6,7 @@ import { import type { ChannelMessageActionAdapter, ChannelMessageActionName, + ChannelMessageToolDiscovery, } from "openclaw/plugin-sdk/channel-runtime"; import type { DiscordActionConfig } from "openclaw/plugin-sdk/config-runtime"; import { createDiscordActionGate, listEnabledDiscordAccounts } from "./accounts.js"; @@ -28,103 +29,109 @@ function resolveDiscordActionDiscovery(cfg: Parameters +>[0]): ChannelMessageToolDiscovery { + const discovery = resolveDiscordActionDiscovery(cfg); + if (!discovery) { + return { + actions: [], + capabilities: [], + schema: null, + }; + } + const actions = new Set(["send"]); + if (discovery.isEnabled("polls")) { + actions.add("poll"); + } + if (discovery.isEnabled("reactions")) { + actions.add("react"); + actions.add("reactions"); + actions.add("emoji-list"); + } + if (discovery.isEnabled("messages")) { + actions.add("read"); + actions.add("edit"); + actions.add("delete"); + } + if (discovery.isEnabled("pins")) { + actions.add("pin"); + actions.add("unpin"); + actions.add("list-pins"); + } + if (discovery.isEnabled("permissions")) { + actions.add("permissions"); + } + if (discovery.isEnabled("threads")) { + actions.add("thread-create"); + actions.add("thread-list"); + actions.add("thread-reply"); + } + if (discovery.isEnabled("search")) { + actions.add("search"); + } + if (discovery.isEnabled("stickers")) { + actions.add("sticker"); + } + if (discovery.isEnabled("memberInfo")) { + actions.add("member-info"); + } + if (discovery.isEnabled("roleInfo")) { + actions.add("role-info"); + } + if (discovery.isEnabled("emojiUploads")) { + actions.add("emoji-upload"); + } + if (discovery.isEnabled("stickerUploads")) { + actions.add("sticker-upload"); + } + if (discovery.isEnabled("roles", false)) { + actions.add("role-add"); + actions.add("role-remove"); + } + if (discovery.isEnabled("channelInfo")) { + actions.add("channel-info"); + actions.add("channel-list"); + } + if (discovery.isEnabled("channels")) { + actions.add("channel-create"); + actions.add("channel-edit"); + actions.add("channel-delete"); + actions.add("channel-move"); + actions.add("category-create"); + actions.add("category-edit"); + actions.add("category-delete"); + } + if (discovery.isEnabled("voiceStatus")) { + actions.add("voice-status"); + } + if (discovery.isEnabled("events")) { + actions.add("event-list"); + actions.add("event-create"); + } + if (discovery.isEnabled("moderation", false)) { + actions.add("timeout"); + actions.add("kick"); + actions.add("ban"); + } + if (discovery.isEnabled("presence", false)) { + actions.add("set-presence"); + } + return { + actions: Array.from(actions), + capabilities: ["interactive", "components"], + schema: { + properties: { + components: createDiscordMessageToolComponentsSchema(), + }, + }, + }; +} + export const discordMessageActions: ChannelMessageActionAdapter = { - listActions: ({ cfg }) => { - const discovery = resolveDiscordActionDiscovery(cfg); - if (!discovery) { - return []; - } - const actions = new Set(["send"]); - if (discovery.isEnabled("polls")) { - actions.add("poll"); - } - if (discovery.isEnabled("reactions")) { - actions.add("react"); - actions.add("reactions"); - } - if (discovery.isEnabled("messages")) { - actions.add("read"); - actions.add("edit"); - actions.add("delete"); - } - if (discovery.isEnabled("pins")) { - actions.add("pin"); - actions.add("unpin"); - actions.add("list-pins"); - } - if (discovery.isEnabled("permissions")) { - actions.add("permissions"); - } - if (discovery.isEnabled("threads")) { - actions.add("thread-create"); - actions.add("thread-list"); - actions.add("thread-reply"); - } - if (discovery.isEnabled("search")) { - actions.add("search"); - } - if (discovery.isEnabled("stickers")) { - actions.add("sticker"); - } - if (discovery.isEnabled("memberInfo")) { - actions.add("member-info"); - } - if (discovery.isEnabled("roleInfo")) { - actions.add("role-info"); - } - if (discovery.isEnabled("reactions")) { - actions.add("emoji-list"); - } - if (discovery.isEnabled("emojiUploads")) { - actions.add("emoji-upload"); - } - if (discovery.isEnabled("stickerUploads")) { - actions.add("sticker-upload"); - } - if (discovery.isEnabled("roles", false)) { - actions.add("role-add"); - actions.add("role-remove"); - } - if (discovery.isEnabled("channelInfo")) { - actions.add("channel-info"); - actions.add("channel-list"); - } - if (discovery.isEnabled("channels")) { - actions.add("channel-create"); - actions.add("channel-edit"); - actions.add("channel-delete"); - actions.add("channel-move"); - actions.add("category-create"); - actions.add("category-edit"); - actions.add("category-delete"); - } - if (discovery.isEnabled("voiceStatus")) { - actions.add("voice-status"); - } - if (discovery.isEnabled("events")) { - actions.add("event-list"); - actions.add("event-create"); - } - if (discovery.isEnabled("moderation", false)) { - actions.add("timeout"); - actions.add("kick"); - actions.add("ban"); - } - if (discovery.isEnabled("presence", false)) { - actions.add("set-presence"); - } - return Array.from(actions); - }, - getCapabilities: ({ cfg }) => - resolveDiscordActionDiscovery(cfg) ? (["interactive", "components"] as const) : [], - getToolSchema: ({ cfg }) => - resolveDiscordActionDiscovery(cfg) - ? { - properties: { - components: createDiscordMessageToolComponentsSchema(), - }, - } - : null, + describeMessageTool: describeDiscordMessageTool, extractToolSend: ({ args }) => { const action = typeof args.action === "string" ? args.action.trim() : ""; if (action === "sendMessage") { diff --git a/extensions/discord/src/channel.ts b/extensions/discord/src/channel.ts index 780c04eb2e6..c555ff89382 100644 --- a/extensions/discord/src/channel.ts +++ b/extensions/discord/src/channel.ts @@ -77,6 +77,8 @@ function formatDiscordIntents(intents?: { } const discordMessageActions: ChannelMessageActionAdapter = { + describeMessageTool: (ctx) => + getDiscordRuntime().channel.discord.messageActions?.describeMessageTool?.(ctx) ?? null, listActions: (ctx) => getDiscordRuntime().channel.discord.messageActions?.listActions?.(ctx) ?? [], getCapabilities: (ctx) =>