mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
fix(telegram): describe reaction emoji syntax (#129080)
* fix(telegram): describe reaction emoji syntax * fix(telegram): keep reactions cross-channel * test(telegram): verify disabled reactions remove emoji guidance --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
@@ -498,6 +498,56 @@ describe("telegramMessageActions", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("advertises Telegram reaction syntax and emoji discovery in message tool schema", () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
telegram: {
|
||||
botToken: "tok",
|
||||
actions: { reactions: true },
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
const discovery = telegramMessageActions.describeMessageTool?.({ cfg });
|
||||
const contributions = Array.isArray(discovery?.schema)
|
||||
? discovery.schema
|
||||
: discovery?.schema
|
||||
? [discovery.schema]
|
||||
: [];
|
||||
const reactionSchema = contributions.find((entry) => "emoji" in entry.properties);
|
||||
const emojiDescription = (
|
||||
reactionSchema?.properties.emoji as { description?: string } | undefined
|
||||
)?.description;
|
||||
|
||||
expect(discovery?.actions).toEqual(expect.arrayContaining(["react", "emoji-list"]));
|
||||
expect(reactionSchema?.actions).toEqual([]);
|
||||
expect(reactionSchema?.properties.emoji).toMatchObject({
|
||||
type: "string",
|
||||
description: expect.stringContaining("custom_emoji_id"),
|
||||
});
|
||||
expect(emojiDescription).toContain('action:"emoji-list"');
|
||||
expect(emojiDescription).toContain("arbitrary Unicode may be rejected");
|
||||
|
||||
const disabledDiscovery = telegramMessageActions.describeMessageTool?.({
|
||||
cfg: {
|
||||
channels: {
|
||||
telegram: {
|
||||
botToken: "tok",
|
||||
actions: { reactions: false },
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig,
|
||||
});
|
||||
const disabledContributions = Array.isArray(disabledDiscovery?.schema)
|
||||
? disabledDiscovery.schema
|
||||
: disabledDiscovery?.schema
|
||||
? [disabledDiscovery.schema]
|
||||
: [];
|
||||
expect(disabledDiscovery?.actions).not.toContain("react");
|
||||
expect(disabledDiscovery?.actions).not.toContain("emoji-list");
|
||||
expect(disabledContributions.find((entry) => "emoji" in entry.properties)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("matches runtime account-key normalization during SecretRef-tolerant discovery", () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
import { isTelegramInlineButtonsEnabled } from "./inline-buttons.js";
|
||||
import {
|
||||
createTelegramPollExtraToolSchemas,
|
||||
createTelegramReactionEmojiSchema,
|
||||
createTelegramRichSendExtraToolSchemas,
|
||||
} from "./message-tool-schema.js";
|
||||
import { rejectTelegramNativeButtonParams } from "./native-button-params.js";
|
||||
@@ -204,6 +205,14 @@ function describeTelegramMessageTool({
|
||||
visibility: "all-configured",
|
||||
});
|
||||
}
|
||||
if (discovery.isEnabled("reactions")) {
|
||||
schema.push({
|
||||
properties: createTelegramReactionEmojiSchema(),
|
||||
// The shared emoji parameter keeps react valid across channels; this
|
||||
// contribution only adds Telegram-specific guidance for that parameter.
|
||||
actions: [],
|
||||
});
|
||||
}
|
||||
if (discovery.isEnabled("sendMessage")) {
|
||||
schema.push({
|
||||
properties: createTelegramRichSendExtraToolSchemas(),
|
||||
|
||||
@@ -20,6 +20,19 @@ export function createTelegramPollExtraToolSchemas() {
|
||||
};
|
||||
}
|
||||
|
||||
/** Schema additions for Telegram reactions through the existing react action. */
|
||||
export function createTelegramReactionEmojiSchema() {
|
||||
return {
|
||||
emoji: Type.Optional(
|
||||
Type.String({
|
||||
description:
|
||||
'Telegram reaction emoji: use a supported Unicode reaction, or pass the numeric custom_emoji_id identifier returned by action:"emoji-list" directly as emoji. ' +
|
||||
'Use action:"emoji-list" to inspect reactions allowed in the current chat; arbitrary Unicode may be rejected by Telegram.',
|
||||
}),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/** Schema additions for Telegram-native rich sends through the existing send action. */
|
||||
export function createTelegramRichSendExtraToolSchemas() {
|
||||
return {
|
||||
|
||||
@@ -4191,6 +4191,48 @@ describe("message tool description", () => {
|
||||
expect(tool.description).not.toContain("telegram (");
|
||||
});
|
||||
|
||||
it("keeps cross-channel Telegram reactions available when emoji schema is metadata-only", () => {
|
||||
const signalPlugin = createChannelPlugin({
|
||||
id: "signal",
|
||||
label: "Signal",
|
||||
docsPath: "/channels/signal",
|
||||
blurb: "Signal test plugin.",
|
||||
actions: ["send"],
|
||||
});
|
||||
const telegramPlugin = createChannelPlugin({
|
||||
id: "telegram",
|
||||
label: "Telegram",
|
||||
docsPath: "/channels/telegram",
|
||||
blurb: "Telegram test plugin.",
|
||||
actions: ["send", "react"],
|
||||
toolSchema: {
|
||||
actions: [],
|
||||
properties: {
|
||||
emoji: Type.Optional(Type.String()),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
setActivePluginRegistry(
|
||||
createTestRegistry([
|
||||
{ pluginId: "signal", source: "test", plugin: signalPlugin },
|
||||
{ pluginId: "telegram", source: "test", plugin: telegramPlugin },
|
||||
]),
|
||||
);
|
||||
|
||||
const tool = createMessageTool({
|
||||
config: {} as never,
|
||||
currentChannelProvider: "signal",
|
||||
});
|
||||
|
||||
const properties = getToolProperties(tool);
|
||||
expect(getActionEnum(properties)).toContain("react");
|
||||
expect(properties.emoji).toMatchObject({ type: "string" });
|
||||
expect((properties.emoji as { description?: string }).description).not.toContain(
|
||||
"custom_emoji_id",
|
||||
);
|
||||
});
|
||||
|
||||
it("does not advertise cross-channel actions whose params are hidden by current-channel schema", () => {
|
||||
const signalPlugin = createChannelPlugin({
|
||||
id: "signal",
|
||||
|
||||
Reference in New Issue
Block a user