diff --git a/extensions/slack/src/channel-actions.ts b/extensions/slack/src/channel-actions.ts index 6a68d9f7036..22defb26750 100644 --- a/extensions/slack/src/channel-actions.ts +++ b/extensions/slack/src/channel-actions.ts @@ -24,15 +24,16 @@ export function createSlackActions( ): ChannelMessageActionAdapter { function describeMessageTool({ cfg, + accountId, }: Parameters< NonNullable >[0]): ChannelMessageToolDiscovery { - const actions = listSlackMessageActions(cfg); + const actions = listSlackMessageActions(cfg, accountId); const capabilities = new Set<"blocks" | "interactive">(); if (actions.includes("send")) { capabilities.add("blocks"); } - if (isSlackInteractiveRepliesEnabled({ cfg })) { + if (isSlackInteractiveRepliesEnabled({ cfg, accountId })) { capabilities.add("interactive"); } return { diff --git a/extensions/slack/src/channel.test.ts b/extensions/slack/src/channel.test.ts index 84e7d90453b..0c98b3c1383 100644 --- a/extensions/slack/src/channel.test.ts +++ b/extensions/slack/src/channel.test.ts @@ -109,6 +109,75 @@ describe("slackPlugin actions", () => { }); }); + it("honors the selected Slack account during message tool discovery", () => { + const cfg: OpenClawConfig = { + channels: { + slack: { + botToken: "xoxb-root", + appToken: "xapp-root", + actions: { + reactions: false, + messages: false, + pins: false, + memberInfo: false, + emojiList: false, + }, + capabilities: { + interactiveReplies: false, + }, + accounts: { + default: { + botToken: "xoxb-default", + appToken: "xapp-default", + actions: { + reactions: false, + messages: false, + pins: false, + memberInfo: false, + emojiList: false, + }, + capabilities: { + interactiveReplies: false, + }, + }, + work: { + botToken: "xoxb-work", + appToken: "xapp-work", + actions: { + reactions: true, + messages: true, + pins: false, + memberInfo: false, + emojiList: false, + }, + capabilities: { + interactiveReplies: true, + }, + }, + }, + }, + }, + }; + + expect(slackPlugin.actions?.describeMessageTool?.({ cfg, accountId: "default" })).toMatchObject({ + actions: ["send"], + capabilities: ["blocks"], + }); + expect(slackPlugin.actions?.describeMessageTool?.({ cfg, accountId: "work" })).toMatchObject({ + actions: [ + "send", + "react", + "reactions", + "read", + "edit", + "delete", + "download-file", + "upload-file", + ], + capabilities: expect.arrayContaining(["blocks", "interactive"]), + }); + }); + it("keeps blocks optional in the message tool schema", () => { const discovery = slackPlugin.actions?.describeMessageTool({ cfg: { diff --git a/extensions/slack/src/message-actions.test.ts b/extensions/slack/src/message-actions.test.ts index bd7fd66ed00..5b21e127cc2 100644 --- a/extensions/slack/src/message-actions.test.ts +++ b/extensions/slack/src/message-actions.test.ts @@ -19,4 +19,55 @@ describe("listSlackMessageActions", () => { expect.arrayContaining(["read", "edit", "delete", "download-file", "upload-file"]), ); }); + + it("honors the selected Slack account during discovery", () => { + const cfg = { + channels: { + slack: { + botToken: "xoxb-root", + actions: { + reactions: false, + messages: false, + pins: false, + memberInfo: false, + emojiList: false, + }, + accounts: { + default: { + botToken: "xoxb-default", + actions: { + reactions: false, + messages: false, + pins: false, + memberInfo: false, + emojiList: false, + }, + }, + work: { + botToken: "xoxb-work", + actions: { + reactions: true, + messages: true, + pins: false, + memberInfo: false, + emojiList: false, + }, + }, + }, + }, + }, + } as OpenClawConfig; + + expect(listSlackMessageActions(cfg, "default")).toEqual(["send"]); + expect(listSlackMessageActions(cfg, "work")).toEqual([ + "send", + "react", + "reactions", + "read", + "edit", + "delete", + "download-file", + "upload-file", + ]); + }); }); diff --git a/extensions/slack/src/message-actions.ts b/extensions/slack/src/message-actions.ts index b0bcce45327..b7423893a44 100644 --- a/extensions/slack/src/message-actions.ts +++ b/extensions/slack/src/message-actions.ts @@ -2,12 +2,16 @@ import { createActionGate } from "openclaw/plugin-sdk/agent-runtime"; import type { ChannelMessageActionName } from "openclaw/plugin-sdk/channel-contract"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; import type { ChannelToolSend } from "openclaw/plugin-sdk/tool-send"; -import { listEnabledSlackAccounts } from "./accounts.js"; +import { listEnabledSlackAccounts, resolveSlackAccount } from "./accounts.js"; -export function listSlackMessageActions(cfg: OpenClawConfig): ChannelMessageActionName[] { - const accounts = listEnabledSlackAccounts(cfg).filter( - (account) => account.botTokenSource !== "none", - ); +export function listSlackMessageActions( + cfg: OpenClawConfig, + accountId?: string | null, +): ChannelMessageActionName[] { + const accounts = (accountId + ? [resolveSlackAccount({ cfg, accountId })] + : listEnabledSlackAccounts(cfg) + ).filter((account) => account.enabled && account.botTokenSource !== "none"); if (accounts.length === 0) { return []; }