Merge pull request #46078 from xxxigm/fix/discord-slash-command-100-cap
fix(discord): cap slash commands at Discord's 100-command limit
This commit is contained in:
@@ -31,6 +31,12 @@ _DISCORD_COMMAND_SYNC_STATE_SUBDIR = "gateway"
|
||||
_DISCORD_COMMAND_SYNC_STATE_FILENAME = "discord_command_sync_state.json"
|
||||
_DISCORD_COMMAND_SYNC_MUTATION_INTERVAL_SECONDS = 4.5
|
||||
_DISCORD_COMMAND_SYNC_MAX_RATE_LIMIT_SLEEP_SECONDS = 30.0
|
||||
# Discord enforces a hard cap of 100 global application (slash) commands per
|
||||
# app. Registering more makes the ENTIRE sync fail with error 30032
|
||||
# ("Maximum number of application commands reached"), which silently breaks
|
||||
# every slash command — not just the overflow ones. We keep the desired set
|
||||
# at or below this limit at registration time.
|
||||
_DISCORD_MAX_APP_COMMANDS = 100
|
||||
|
||||
try:
|
||||
import discord
|
||||
@@ -3518,6 +3524,11 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||
)
|
||||
|
||||
already_registered: set[str] = set()
|
||||
# Native commands above are registered first and are the highest
|
||||
# priority, so they always survive the 100-command cap. Reserve one
|
||||
# slot for the consolidated ``/skill`` group registered further below.
|
||||
slot_cap = _DISCORD_MAX_APP_COMMANDS - 1
|
||||
dropped_over_cap = 0
|
||||
try:
|
||||
from hermes_cli.commands import COMMAND_REGISTRY, _is_gateway_available, _resolve_config_gates
|
||||
|
||||
@@ -3535,6 +3546,9 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||
discord_name = cmd_def.name.lower()[:32]
|
||||
if discord_name in already_registered:
|
||||
continue
|
||||
if len(already_registered) >= slot_cap:
|
||||
dropped_over_cap += 1
|
||||
continue
|
||||
auto_cmd = _build_auto_slash_command(
|
||||
cmd_def.name,
|
||||
cmd_def.description,
|
||||
@@ -3567,6 +3581,9 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||
discord_name = plugin_name.lower()[:32]
|
||||
if discord_name in already_registered:
|
||||
continue
|
||||
if len(already_registered) >= slot_cap:
|
||||
dropped_over_cap += 1
|
||||
continue
|
||||
auto_cmd = _build_auto_slash_command(
|
||||
plugin_name,
|
||||
plugin_desc,
|
||||
@@ -3589,6 +3606,20 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||
# supporting up to 25 categories × 25 skills = 625 skills.
|
||||
self._register_skill_group(tree)
|
||||
|
||||
if dropped_over_cap:
|
||||
# Staying under the cap keeps the whole sync succeeding; without
|
||||
# this guard a single over-limit command makes Discord reject the
|
||||
# entire batch (error 30032), breaking every slash command.
|
||||
logger.warning(
|
||||
"[%s] Reached Discord's limit of %d slash commands; skipped %d "
|
||||
"lower-priority command(s) to keep the command sync working. "
|
||||
"Disable slash commands you don't need or trim installed plugins "
|
||||
"to surface them all.",
|
||||
self.name,
|
||||
_DISCORD_MAX_APP_COMMANDS,
|
||||
dropped_over_cap,
|
||||
)
|
||||
|
||||
# Optional defense-in-depth: hide every slash command from non-admin
|
||||
# guild members in Discord's slash picker. Server-side authorization
|
||||
# (``_check_slash_authorization``) is the actual gate; this is purely
|
||||
|
||||
Reference in New Issue
Block a user