diff --git a/hermes_cli/banner.py b/hermes_cli/banner.py index addcf98c2..21c577dd3 100644 --- a/hermes_cli/banner.py +++ b/hermes_cli/banner.py @@ -228,6 +228,17 @@ def _format_context_length(tokens: int) -> str: return str(tokens) +def _display_toolset_name(toolset_name: str) -> str: + """Normalize internal/legacy toolset identifiers for banner display.""" + if not toolset_name: + return "unknown" + return ( + toolset_name[:-6] + if toolset_name.endswith("_tools") + else toolset_name + ) + + def build_welcome_banner(console: Console, model: str, cwd: str, tools: List[dict] = None, enabled_toolsets: List[str] = None, @@ -292,12 +303,12 @@ def build_welcome_banner(console: Console, model: str, cwd: str, for tool in tools: tool_name = tool["function"]["name"] - toolset = get_toolset_for_tool(tool_name) or "other" + toolset = _display_toolset_name(get_toolset_for_tool(tool_name) or "other") toolsets_dict.setdefault(toolset, []).append(tool_name) for item in unavailable_toolsets: toolset_id = item.get("id", item.get("name", "unknown")) - display_name = f"{toolset_id}_tools" if not toolset_id.endswith("_tools") else toolset_id + display_name = _display_toolset_name(toolset_id) if display_name not in toolsets_dict: toolsets_dict[display_name] = [] for tool_name in item.get("tools", []): @@ -337,10 +348,10 @@ def build_welcome_banner(console: Console, model: str, cwd: str, colored_names.append(f"[{text}]{name}[/]") tools_str = ", ".join(colored_names) - right_lines.append(f"[dim #B8860B]{toolset}:[/] {tools_str}") + right_lines.append(f"[dim {dim}]{toolset}:[/] {tools_str}") if remaining_toolsets > 0: - right_lines.append(f"[dim #B8860B](and {remaining_toolsets} more toolsets...)[/]") + right_lines.append(f"[dim {dim}](and {remaining_toolsets} more toolsets...)[/]") # MCP Servers section (only if configured) try: @@ -351,12 +362,12 @@ def build_welcome_banner(console: Console, model: str, cwd: str, if mcp_status: right_lines.append("") - right_lines.append("[bold #FFBF00]MCP Servers[/]") + right_lines.append(f"[bold {accent}]MCP Servers[/]") for srv in mcp_status: if srv["connected"]: right_lines.append( - f"[dim #B8860B]{srv['name']}[/] [#FFF8DC]({srv['transport']})[/] " - f"[dim #B8860B]—[/] [#FFF8DC]{srv['tools']} tool(s)[/]" + f"[dim {dim}]{srv['name']}[/] [{text}]({srv['transport']})[/] " + f"[dim {dim}]—[/] [{text}]{srv['tools']} tool(s)[/]" ) else: right_lines.append( diff --git a/tests/hermes_cli/test_banner.py b/tests/hermes_cli/test_banner.py new file mode 100644 index 000000000..4ea089fd0 --- /dev/null +++ b/tests/hermes_cli/test_banner.py @@ -0,0 +1,70 @@ +"""Tests for banner toolset name normalization and skin color usage.""" + +from unittest.mock import patch + +from rich.console import Console + +import hermes_cli.banner as banner +import model_tools +import tools.mcp_tool + + +def test_display_toolset_name_strips_legacy_suffix(): + assert banner._display_toolset_name("homeassistant_tools") == "homeassistant" + assert banner._display_toolset_name("honcho_tools") == "honcho" + assert banner._display_toolset_name("web_tools") == "web" + + +def test_display_toolset_name_preserves_clean_names(): + assert banner._display_toolset_name("browser") == "browser" + assert banner._display_toolset_name("file") == "file" + assert banner._display_toolset_name("terminal") == "terminal" + + +def test_display_toolset_name_handles_empty(): + assert banner._display_toolset_name("") == "unknown" + assert banner._display_toolset_name(None) == "unknown" + + +def test_build_welcome_banner_uses_normalized_toolset_names(): + """Unavailable toolsets should not have '_tools' appended in banner output.""" + with ( + patch.object( + model_tools, + "check_tool_availability", + return_value=( + ["web"], + [ + {"name": "homeassistant", "tools": ["ha_call_service"]}, + {"name": "honcho", "tools": ["honcho_conclude"]}, + ], + ), + ), + patch.object(banner, "get_available_skills", return_value={}), + patch.object(banner, "get_update_result", return_value=None), + patch.object(tools.mcp_tool, "get_mcp_status", return_value=[]), + ): + console = Console( + record=True, force_terminal=False, color_system=None, width=160 + ) + banner.build_welcome_banner( + console=console, + model="anthropic/test-model", + cwd="/tmp/project", + tools=[ + {"function": {"name": "web_search"}}, + {"function": {"name": "read_file"}}, + ], + get_toolset_for_tool=lambda name: { + "web_search": "web_tools", + "read_file": "file", + }.get(name), + ) + + output = console.export_text() + assert "homeassistant:" in output + assert "honcho:" in output + assert "web:" in output + assert "homeassistant_tools:" not in output + assert "honcho_tools:" not in output + assert "web_tools:" not in output