mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-17 09:41:58 +00:00
test(discord): guard slash-command registration against the 100 cap
Registers 200 plugin commands on top of the native + COMMAND_REGISTRY set
and asserts the tree never exceeds Discord's 100-command limit, that native
high-priority commands survive the cap, and that overflow is actually
dropped. Regression guard for the recurring error 30032
("Maximum number of application commands reached") sync failures.
This commit is contained in:
parent
5e851bc6bc
commit
8f4a718f95
1 changed files with 52 additions and 0 deletions
|
|
@ -292,6 +292,58 @@ async def test_plugin_command_name_conflict_skipped(adapter):
|
|||
)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 100-command cap (Discord error 30032 guard)
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_slash_command_registration_stays_under_discord_limit(adapter):
|
||||
"""Registering far more commands than Discord allows must NOT push the
|
||||
tree over the 100-command hard cap.
|
||||
|
||||
Discord rejects the ENTIRE command sync with error 30032 once the
|
||||
desired set exceeds 100 global application commands, silently breaking
|
||||
every slash command. The adapter must bound the desired set instead.
|
||||
Regression guard for samuraiheart's recurring
|
||||
"Maximum number of application commands reached (100)" sync failures.
|
||||
"""
|
||||
from plugins.platforms.discord.adapter import _DISCORD_MAX_APP_COMMANDS
|
||||
|
||||
adapter._run_simple_slash = AsyncMock()
|
||||
|
||||
# 200 plugin commands — way past Discord's limit on their own.
|
||||
many_plugins = {
|
||||
f"plug{i:03d}": {
|
||||
"handler": lambda _a: "ok",
|
||||
"description": f"Plugin command {i}",
|
||||
"args_hint": "",
|
||||
"plugin": "stress-plugin",
|
||||
}
|
||||
for i in range(200)
|
||||
}
|
||||
|
||||
with patch("hermes_cli.plugins.get_plugin_commands", return_value=many_plugins):
|
||||
adapter._register_slash_commands()
|
||||
|
||||
tree_names = set(adapter._client.tree.commands.keys())
|
||||
|
||||
# Contract: never exceed Discord's hard cap.
|
||||
assert len(tree_names) <= _DISCORD_MAX_APP_COMMANDS, (
|
||||
f"registered {len(tree_names)} commands — exceeds Discord's "
|
||||
f"{_DISCORD_MAX_APP_COMMANDS} limit and would fail sync with 30032"
|
||||
)
|
||||
|
||||
# Native, high-priority commands are registered first and must survive
|
||||
# the cap — they are the core UX, not droppable overflow.
|
||||
for native in ("status", "stop", "new", "model", "help"):
|
||||
assert native in tree_names, f"/{native} (native) was dropped by the cap"
|
||||
|
||||
# The cap must actually have dropped overflow — not every plugin fit.
|
||||
registered_plugins = [n for n in tree_names if n.startswith("plug")]
|
||||
assert len(registered_plugins) < 200, "cap did not drop any overflow commands"
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# _handle_thread_create_slash — success, session dispatch, failure
|
||||
# ------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue