fix: honor discord action discovery account config

This commit is contained in:
Tak Hoffman
2026-04-03 11:18:11 -05:00
parent 8ffd1c0973
commit 832810a5bb
2 changed files with 68 additions and 2 deletions

View File

@@ -59,6 +59,47 @@ describe("discordMessageActions", () => {
expect(discovery?.actions).not.toContain("role-add");
});
it("honors account-scoped action gates during discovery", () => {
const cfg = {
channels: {
discord: {
token: "Bot token-main",
actions: {
reactions: false,
polls: true,
},
accounts: {
work: {
token: "Bot token-work",
actions: {
reactions: true,
polls: false,
},
},
},
},
},
} as OpenClawConfig;
const defaultDiscovery = discordMessageActions.describeMessageTool?.({
cfg,
accountId: "default",
});
const workDiscovery = discordMessageActions.describeMessageTool?.({
cfg,
accountId: "work",
});
expect(defaultDiscovery?.actions).toEqual(
expect.arrayContaining(["send", "poll"]),
);
expect(defaultDiscovery?.actions).not.toContain("react");
expect(workDiscovery?.actions).toEqual(
expect.arrayContaining(["send", "react", "reactions", "emoji-list"]),
);
expect(workDiscovery?.actions).not.toContain("poll");
});
it("keeps components optional in the message tool schema", () => {
const discovery = discordMessageActions.describeMessageTool?.({
cfg: {

View File

@@ -9,7 +9,11 @@ import type {
ChannelMessageToolDiscovery,
} from "openclaw/plugin-sdk/channel-contract";
import type { DiscordActionConfig } from "openclaw/plugin-sdk/config-runtime";
import { createDiscordActionGate, listEnabledDiscordAccounts } from "./accounts.js";
import {
createDiscordActionGate,
listEnabledDiscordAccounts,
resolveDiscordAccount,
} from "./accounts.js";
import { handleDiscordMessageAction } from "./actions/handle-action.js";
import { createDiscordMessageToolComponentsSchema } from "./message-tool-schema.js";
@@ -30,12 +34,33 @@ function resolveDiscordActionDiscovery(cfg: Parameters<typeof listEnabledDiscord
};
}
function resolveScopedDiscordActionDiscovery(params: {
cfg: Parameters<typeof listEnabledDiscordAccounts>[0];
accountId?: string | null;
}) {
if (!params.accountId) {
return resolveDiscordActionDiscovery(params.cfg);
}
const account = resolveDiscordAccount({ cfg: params.cfg, accountId: params.accountId });
if (!account.enabled || !account.token.trim()) {
return null;
}
const gate = createDiscordActionGate({
cfg: params.cfg,
accountId: account.accountId,
});
return {
isEnabled: (key: keyof DiscordActionConfig, defaultValue = true) => gate(key, defaultValue),
};
}
function describeDiscordMessageTool({
cfg,
accountId,
}: Parameters<
NonNullable<ChannelMessageActionAdapter["describeMessageTool"]>
>[0]): ChannelMessageToolDiscovery {
const discovery = resolveDiscordActionDiscovery(cfg);
const discovery = resolveScopedDiscordActionDiscovery({ cfg, accountId });
if (!discovery) {
return {
actions: [],