Telegram: dedupe message action discovery state

This commit is contained in:
Gustavo Madeira Santana 2026-03-17 23:55:05 +00:00
parent a32c7e16d2
commit 5ce3eb3ff3
No known key found for this signature in database

View File

@ -16,6 +16,7 @@ import {
import type { import type {
ChannelMessageActionAdapter, ChannelMessageActionAdapter,
ChannelMessageActionName, ChannelMessageActionName,
ChannelMessageToolSchemaContribution,
} from "openclaw/plugin-sdk/channel-runtime"; } from "openclaw/plugin-sdk/channel-runtime";
import type { TelegramActionConfig } from "openclaw/plugin-sdk/config-runtime"; import type { TelegramActionConfig } from "openclaw/plugin-sdk/config-runtime";
import { resolveTelegramPollVisibility } from "openclaw/plugin-sdk/telegram"; import { resolveTelegramPollVisibility } from "openclaw/plugin-sdk/telegram";
@ -34,6 +35,35 @@ export const telegramMessageActionRuntime = {
handleTelegramAction, handleTelegramAction,
}; };
function resolveTelegramActionDiscovery(cfg: Parameters<typeof listEnabledTelegramAccounts>[0]) {
const accounts = listTokenSourcedAccounts(listEnabledTelegramAccounts(cfg));
if (accounts.length === 0) {
return null;
}
const unionGate = createUnionActionGate(accounts, (account) =>
createTelegramActionGate({
cfg,
accountId: account.accountId,
}),
);
const pollEnabled = accounts.some((account) => {
const accountGate = createTelegramActionGate({
cfg,
accountId: account.accountId,
});
return resolveTelegramPollActionGateState(accountGate).enabled;
});
const buttonsEnabled = accounts.some((account) =>
isTelegramInlineButtonsEnabled({ cfg, accountId: account.accountId }),
);
return {
isEnabled: (key: keyof TelegramActionConfig, defaultValue = true) =>
unionGate(key, defaultValue),
pollEnabled,
buttonsEnabled,
};
}
function readTelegramSendParams(params: Record<string, unknown>) { function readTelegramSendParams(params: Record<string, unknown>) {
const to = readStringParam(params, "to", { required: true }); const to = readStringParam(params, "to", { required: true });
const mediaUrl = readStringParam(params, "media", { trim: false }); const mediaUrl = readStringParam(params, "media", { trim: false });
@ -89,85 +119,56 @@ function readTelegramMessageIdParam(params: Record<string, unknown>): number {
export const telegramMessageActions: ChannelMessageActionAdapter = { export const telegramMessageActions: ChannelMessageActionAdapter = {
listActions: ({ cfg }) => { listActions: ({ cfg }) => {
const accounts = listTokenSourcedAccounts(listEnabledTelegramAccounts(cfg)); const discovery = resolveTelegramActionDiscovery(cfg);
if (accounts.length === 0) { if (!discovery) {
return []; return [];
} }
// Union of all accounts' action gates (any account enabling an action makes it available)
const gate = createUnionActionGate(accounts, (account) =>
createTelegramActionGate({
cfg,
accountId: account.accountId,
}),
);
const isEnabled = (key: keyof TelegramActionConfig, defaultValue = true) =>
gate(key, defaultValue);
const actions = new Set<ChannelMessageActionName>(["send"]); const actions = new Set<ChannelMessageActionName>(["send"]);
const pollEnabledForAnyAccount = accounts.some((account) => { if (discovery.pollEnabled) {
const accountGate = createTelegramActionGate({
cfg,
accountId: account.accountId,
});
return resolveTelegramPollActionGateState(accountGate).enabled;
});
if (pollEnabledForAnyAccount) {
actions.add("poll"); actions.add("poll");
} }
if (isEnabled("reactions")) { if (discovery.isEnabled("reactions")) {
actions.add("react"); actions.add("react");
} }
if (isEnabled("deleteMessage")) { if (discovery.isEnabled("deleteMessage")) {
actions.add("delete"); actions.add("delete");
} }
if (isEnabled("editMessage")) { if (discovery.isEnabled("editMessage")) {
actions.add("edit"); actions.add("edit");
} }
if (isEnabled("sticker", false)) { if (discovery.isEnabled("sticker", false)) {
actions.add("sticker"); actions.add("sticker");
actions.add("sticker-search"); actions.add("sticker-search");
} }
if (isEnabled("createForumTopic")) { if (discovery.isEnabled("createForumTopic")) {
actions.add("topic-create"); actions.add("topic-create");
} }
if (isEnabled("editForumTopic")) { if (discovery.isEnabled("editForumTopic")) {
actions.add("topic-edit"); actions.add("topic-edit");
} }
return Array.from(actions); return Array.from(actions);
}, },
getCapabilities: ({ cfg }) => { getCapabilities: ({ cfg }) => {
const accounts = listTokenSourcedAccounts(listEnabledTelegramAccounts(cfg)); const discovery = resolveTelegramActionDiscovery(cfg);
if (accounts.length === 0) { if (!discovery) {
return []; return [];
} }
const buttonsEnabled = accounts.some((account) => return discovery.buttonsEnabled ? (["interactive", "buttons"] as const) : [];
isTelegramInlineButtonsEnabled({ cfg, accountId: account.accountId }),
);
return buttonsEnabled ? (["interactive", "buttons"] as const) : [];
}, },
getToolSchema: ({ cfg }) => { getToolSchema: ({ cfg }) => {
const accounts = listTokenSourcedAccounts(listEnabledTelegramAccounts(cfg)); const discovery = resolveTelegramActionDiscovery(cfg);
if (accounts.length === 0) { if (!discovery) {
return null; return null;
} }
const buttonsEnabled = accounts.some((account) => const entries: ChannelMessageToolSchemaContribution[] = [];
isTelegramInlineButtonsEnabled({ cfg, accountId: account.accountId }), if (discovery.buttonsEnabled) {
);
const pollEnabledForAnyAccount = accounts.some((account) => {
const accountGate = createTelegramActionGate({
cfg,
accountId: account.accountId,
});
return resolveTelegramPollActionGateState(accountGate).enabled;
});
const entries = [];
if (buttonsEnabled) {
entries.push({ entries.push({
properties: { properties: {
buttons: createMessageToolButtonsSchema(), buttons: createMessageToolButtonsSchema(),
}, },
}); });
} }
if (pollEnabledForAnyAccount) { if (discovery.pollEnabled) {
entries.push({ entries.push({
properties: createTelegramPollExtraToolSchemas(), properties: createTelegramPollExtraToolSchemas(),
visibility: "all-configured" as const, visibility: "all-configured" as const,