fix: honor slack action discovery account config

This commit is contained in:
Tak Hoffman 2026-04-03 11:33:12 -05:00
parent 2a19771c3c
commit d21ae7173f
No known key found for this signature in database
4 changed files with 132 additions and 7 deletions

View File

@ -24,15 +24,16 @@ export function createSlackActions(
): ChannelMessageActionAdapter {
function describeMessageTool({
cfg,
accountId,
}: Parameters<
NonNullable<ChannelMessageActionAdapter["describeMessageTool"]>
>[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 {

View File

@ -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: {

View File

@ -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",
]);
});
});

View File

@ -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 [];
}