mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
97 lines
3.5 KiB
Python
97 lines
3.5 KiB
Python
"""Invariant tests for registry-owned slash execution (CommandDef.execute).
|
|
|
|
Every ``CommandDef`` with ``execute`` set must:
|
|
* name a key that exists in :data:`hermes_cli.slash_exec.EXECUTORS`, and
|
|
* produce IDENTICAL core text across surfaces for a fixed context — the
|
|
executor may only vary on ``args``/``options``, never on ``surface``.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from hermes_cli.commands import COMMAND_REGISTRY, resolve_command
|
|
from hermes_cli.slash_exec import (
|
|
EXECUTORS,
|
|
CommandContext,
|
|
CommandReply,
|
|
execute_command,
|
|
resolve_executor,
|
|
run_execute,
|
|
)
|
|
|
|
MIGRATED = [cmd for cmd in COMMAND_REGISTRY if cmd.execute]
|
|
|
|
SURFACES = ("cli", "gateway", "tui")
|
|
|
|
|
|
def test_some_commands_are_migrated():
|
|
names = {cmd.name for cmd in MIGRATED}
|
|
# The thin-slice set — extend as more commands migrate.
|
|
assert {"version", "egress", "profile", "bundles", "help", "commands"} <= names
|
|
|
|
|
|
def test_every_execute_key_resolves():
|
|
for cmd in MIGRATED:
|
|
assert cmd.execute in EXECUTORS, (
|
|
f"/{cmd.name} names execute={cmd.execute!r} but no such key in "
|
|
f"hermes_cli.slash_exec.EXECUTORS"
|
|
)
|
|
assert resolve_executor(cmd) is EXECUTORS[cmd.execute]
|
|
|
|
|
|
def test_unmigrated_commands_have_no_executor():
|
|
for cmd in COMMAND_REGISTRY:
|
|
if not cmd.execute:
|
|
assert resolve_executor(cmd) is None
|
|
assert run_execute(cmd, CommandContext()) is None
|
|
|
|
|
|
@pytest.mark.parametrize("cmd", MIGRATED, ids=lambda c: c.name)
|
|
def test_core_text_is_surface_invariant(cmd):
|
|
"""Fixed context ⇒ identical CommandReply text on every surface."""
|
|
replies = []
|
|
for surface in SURFACES:
|
|
ctx = CommandContext(surface=surface, args="", options={"page_size": 20})
|
|
reply = run_execute(cmd, ctx)
|
|
assert isinstance(reply, CommandReply)
|
|
assert isinstance(reply.text, str) and reply.text
|
|
replies.append(reply.text)
|
|
assert replies[0] == replies[1] == replies[2], (
|
|
f"/{cmd.name} core text varies by surface — executors must not "
|
|
f"branch on ctx.surface"
|
|
)
|
|
|
|
|
|
def test_execute_command_helper_resolves_aliases():
|
|
# /v is an alias of /version — the helper resolves through the registry.
|
|
a = execute_command("version", CommandContext(surface="cli"))
|
|
b = execute_command("v", CommandContext(surface="gateway"))
|
|
assert a.text == b.text
|
|
|
|
|
|
def test_execute_command_raises_for_unmigrated():
|
|
with pytest.raises(LookupError):
|
|
execute_command("model", CommandContext())
|
|
with pytest.raises(LookupError):
|
|
execute_command("definitely-not-a-command", CommandContext())
|
|
|
|
|
|
def test_profile_options_override_process_values():
|
|
reply = run_execute(
|
|
resolve_command("profile"),
|
|
CommandContext(options={"profile_name": "work", "home_display": "~/.hermes-work"}),
|
|
)
|
|
assert reply.data == {"profile": "work", "home": "~/.hermes-work"}
|
|
assert reply.text == "Profile: work\nHome: ~/.hermes-work"
|
|
|
|
|
|
def test_commands_page_size_is_an_option_not_a_surface_branch():
|
|
"""Telegram's smaller page is parameterized — same option, same text."""
|
|
cmd = resolve_command("commands")
|
|
tg = run_execute(cmd, CommandContext(surface="gateway", options={"page_size": 15}))
|
|
cli = run_execute(cmd, CommandContext(surface="cli", options={"page_size": 15}))
|
|
assert tg.text == cli.text
|
|
|
|
|
|
def test_commands_bad_page_arg_returns_usage():
|
|
reply = run_execute(resolve_command("commands"), CommandContext(args="notanumber"))
|
|
assert "commands" in reply.text.lower() or "usage" in reply.text.lower()
|