feat(telegram): add customFirst option for command menu ordering

Adds a new `commands.customFirst` config option for Telegram that allows
custom commands to appear before native commands in the bot's menu.

When `channels.telegram.commands.customFirst: true`, the Telegram command
menu shows user-defined custom commands first, followed by native commands.
Default behavior (false) keeps native commands first for backwards compat.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
zorrohk 2026-01-29 16:30:34 +08:00
parent 6859e1e6a6
commit 84066dc0d5
5 changed files with 16 additions and 7 deletions

View File

@ -604,6 +604,8 @@ const FIELD_HELP: Record<string, string> = {
"channels.telegram.commands.native": 'Override native commands for Telegram (bool or "auto").',
"channels.telegram.commands.nativeSkills":
'Override native skill commands for Telegram (bool or "auto").',
"channels.telegram.commands.customFirst":
"If true, custom commands appear before native commands in the Telegram menu (default: false).",
"channels.slack.commands.native": 'Override native commands for Slack (bool or "auto").',
"channels.slack.commands.nativeSkills":
'Override native skill commands for Slack (bool or "auto").',

View File

@ -114,4 +114,6 @@ export type ProviderCommandsConfig = {
native?: NativeCommandsSetting;
/** Override native skill command registration for this provider (bool or "auto"). */
nativeSkills?: NativeCommandsSetting;
/** If true, custom commands appear before native commands in the menu. Default: false (native first). */
customFirst?: boolean;
};

View File

@ -497,6 +497,7 @@ export const ProviderCommandsSchema = z
.object({
native: NativeCommandsSettingSchema.optional(),
nativeSkills: NativeCommandsSettingSchema.optional(),
customFirst: z.boolean().optional(),
})
.strict()
.optional();

View File

@ -56,6 +56,7 @@ type RegisterTelegramNativeCommandsParams = {
nativeEnabled: boolean;
nativeSkillsEnabled: boolean;
nativeDisabledExplicit: boolean;
customFirst: boolean;
resolveGroupPolicy: (chatId: string | number) => ChannelGroupPolicy;
resolveTelegramGroupConfig: (
chatId: string | number,
@ -79,6 +80,7 @@ export const registerTelegramNativeCommands = ({
nativeEnabled,
nativeSkillsEnabled,
nativeDisabledExplicit,
customFirst,
resolveGroupPolicy,
resolveTelegramGroupConfig,
shouldSkipUpdate,
@ -103,13 +105,13 @@ export const registerTelegramNativeCommands = ({
runtime.error?.(danger(issue.message));
}
const customCommands = customResolution.commands;
const allCommands: Array<{ command: string; description: string }> = [
...nativeCommands.map((command) => ({
command: command.name,
description: command.description,
})),
...customCommands,
];
const nativeCommandItems = nativeCommands.map((command) => ({
command: command.name,
description: command.description,
}));
const allCommands: Array<{ command: string; description: string }> = customFirst
? [...customCommands, ...nativeCommandItems]
: [...nativeCommandItems, ...customCommands];
if (allCommands.length > 0) {
bot.api.setMyCommands(allCommands).catch((err) => {

View File

@ -236,6 +236,7 @@ export function createTelegramBot(opts: TelegramBotOptions) {
providerSetting: telegramCfg.commands?.native,
globalSetting: cfg.commands?.native,
});
const customFirst = telegramCfg.commands?.customFirst === true;
const useAccessGroups = cfg.commands?.useAccessGroups !== false;
const ackReactionScope = cfg.messages?.ackReactionScope ?? "group-mentions";
const mediaMaxBytes = (opts.mediaMaxMb ?? telegramCfg.mediaMaxMb ?? 5) * 1024 * 1024;
@ -341,6 +342,7 @@ export function createTelegramBot(opts: TelegramBotOptions) {
nativeEnabled,
nativeSkillsEnabled,
nativeDisabledExplicit,
customFirst,
resolveGroupPolicy,
resolveTelegramGroupConfig,
shouldSkipUpdate,