"""Expose hermes-agent's COMMAND_REGISTRY to the webui frontend. This module is the single integration point with hermes_cli.commands. If hermes-agent is unavailable the endpoint degrades to an empty list so the frontend can still load with WEBUI_ONLY commands. """ from __future__ import annotations import logging from typing import Any logger = logging.getLogger(__name__) # Commands that are gateway_only in the agent registry -- webui never # wants to expose them (sethome, restart, update etc.) even if a future # agent version drops the gateway_only flag. /commands is the agent's # own command-listing command; webui has its own /help that calls # cmdHelp() locally, so /commands would be redundant and confusing. _NEVER_EXPOSE: frozenset[str] = frozenset({ 'sethome', 'restart', 'update', 'commands', }) def list_commands(_registry=None) -> list[dict[str, Any]]: """Return COMMAND_REGISTRY entries as JSON-friendly dicts. Returns empty list if hermes_cli is not installed (graceful degradation -- the frontend has its own fallback minimum set). Args: _registry: Optional injected registry for testing. When None (production), imports COMMAND_REGISTRY from hermes_cli. """ if _registry is None: try: from hermes_cli.commands import COMMAND_REGISTRY as _registry except ImportError: logger.warning("hermes_cli.commands not importable -- /api/commands returns []") return [] out: list[dict[str, Any]] = [] for cmd in _registry: if cmd.gateway_only: continue if cmd.name in _NEVER_EXPOSE: continue out.append({ 'name': cmd.name, 'description': cmd.description, 'category': cmd.category, 'aliases': list(cmd.aliases), 'args_hint': cmd.args_hint, 'subcommands': list(cmd.subcommands), 'cli_only': bool(cmd.cli_only), 'gateway_only': bool(cmd.gateway_only), }) return out