diff --git a/cli.py b/cli.py index 0d0d312292..5ebd46843b 100755 --- a/cli.py +++ b/cli.py @@ -2101,8 +2101,10 @@ class HermesCLI: validation = {"accepted": True, "persist": True, "recognized": False, "message": None} if not validation.get("accepted"): - print(f"(^_^) Warning: {validation.get('message')}") - print(f"(^_^) Current model unchanged: {self.model}") + print(f"(>_<) {validation.get('message')}") + print(f" Model unchanged: {self.model}") + if "Did you mean" not in (validation.get("message") or ""): + print(" Tip: Use /model to see available models, /provider to see providers") else: self.model = new_model self.agent = None # Force re-init @@ -2123,13 +2125,13 @@ class HermesCLI: if saved_model: print(f"(^_^)b Model changed to: {new_model}{provider_note} (saved to config)") else: - print(f"(^_^) Model changed to: {new_model}{provider_note} (session only)") + print(f"(^_^) Model changed to: {new_model}{provider_note} (this session only)") else: - print(f"(^_^) Model changed to: {new_model}{provider_note} (session only)") - - message = validation.get("message") - if message: - print(f" Warning: {message}") + message = validation.get("message") or "" + print(f"(^_^) Model changed to: {new_model}{provider_note} (this session only)") + if message: + print(f" Reason: {message}") + print(" Note: Model will revert on restart. Use a verified model to save to config.") else: from hermes_cli.models import curated_models_for_provider, normalize_provider, _PROVIDER_LABELS from hermes_cli.auth import resolve_provider as _resolve_provider diff --git a/gateway/run.py b/gateway/run.py index a79c86eeb7..379c4ef1f6 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -1414,7 +1414,9 @@ class GatewayRunner: validation = {"accepted": True, "persist": True, "recognized": False, "message": None} if not validation.get("accepted"): - return f"⚠️ {validation.get('message')}" + msg = validation.get("message", "Invalid model") + tip = "\n\nUse `/model` to see available models, `/provider` to see providers" if "Did you mean" not in msg else "" + return f"⚠️ {msg}{tip}" # Persist to config only if validation approves if validation.get("persist"): @@ -1445,7 +1447,10 @@ class GatewayRunner: if validation.get("message"): warning = f"\n⚠️ {validation['message']}" - persist_note = "saved to config" if validation.get("persist") else "session only" + if validation.get("persist"): + persist_note = "saved to config" + else: + persist_note = "this session only — will revert on restart" return f"🤖 Model changed to `{new_model}` ({persist_note}){provider_note}{warning}\n_(takes effect on next message)_" async def _handle_provider_command(self, event: MessageEvent) -> str: diff --git a/tests/test_cli_model_command.py b/tests/test_cli_model_command.py index 13c4f0f220..b8b8e8d2d7 100644 --- a/tests/test_cli_model_command.py +++ b/tests/test_cli_model_command.py @@ -41,10 +41,11 @@ class TestModelCommand: output = capsys.readouterr().out assert "not a valid model" in output + assert "Model unchanged" in output assert cli_obj.model == "anthropic/claude-opus-4.6" save_mock.assert_not_called() - def test_model_when_api_unreachable_falls_back_session_only(self, capsys): + def test_api_unreachable_falls_back_session_only(self, capsys): cli_obj = self._make_cli() with patch("hermes_cli.models.fetch_api_models", return_value=None), \ @@ -53,6 +54,7 @@ class TestModelCommand: output = capsys.readouterr().out assert "session only" in output + assert "will revert on restart" in output assert cli_obj.model == "anthropic/claude-sonnet-next" save_mock.assert_not_called() @@ -66,8 +68,9 @@ class TestModelCommand: output = capsys.readouterr().out assert "not a valid model" in output - assert cli_obj.model == "anthropic/claude-opus-4.6" - fetch_mock.assert_called_once() + assert "Model unchanged" in output + assert cli_obj.model == "anthropic/claude-opus-4.6" # unchanged + assert cli_obj.agent is not None # not reset save_mock.assert_not_called() def test_validation_crash_falls_back_to_save(self, capsys): diff --git a/website/docs/reference/cli-commands.md b/website/docs/reference/cli-commands.md index bb40bbdebc..55fd8504f4 100644 --- a/website/docs/reference/cli-commands.md +++ b/website/docs/reference/cli-commands.md @@ -139,7 +139,8 @@ Type `/` in the interactive CLI to see an autocomplete dropdown. |---------|-------------| | `/tools` | List all available tools | | `/toolsets` | List available toolsets | -| `/model [name]` | Show or change the current model | +| `/model [provider:model]` | Show or change the current model (supports `provider:model` syntax to switch providers) | +| `/provider` | Show available providers with auth status | | `/config` | Show current configuration | | `/prompt [text]` | View/set custom system prompt | | `/personality [name]` | Set a predefined personality | diff --git a/website/docs/user-guide/cli.md b/website/docs/user-guide/cli.md index ec89c7b58e..d80b178b5d 100644 --- a/website/docs/user-guide/cli.md +++ b/website/docs/user-guide/cli.md @@ -95,7 +95,8 @@ Type `/` to see an autocomplete dropdown of all available commands. |---------|-------------| | `/tools` | List all available tools grouped by toolset | | `/toolsets` | List available toolsets with descriptions | -| `/model [name]` | Show or change the current model | +| `/model [provider:model]` | Show or change the current model (supports `provider:model` syntax) | +| `/provider` | Show available providers with auth status | | `/config` | Show current configuration | | `/prompt [text]` | View/set/clear custom system prompt | | `/personality [name]` | Set a predefined personality | diff --git a/website/docs/user-guide/messaging/index.md b/website/docs/user-guide/messaging/index.md index 12fec3fd2e..f93275c865 100644 --- a/website/docs/user-guide/messaging/index.md +++ b/website/docs/user-guide/messaging/index.md @@ -63,7 +63,8 @@ hermes gateway status # Check service status | Command | Description | |---------|-------------| | `/new` or `/reset` | Start fresh conversation | -| `/model [name]` | Show or change the model | +| `/model [provider:model]` | Show or change the model (supports `provider:model` syntax) | +| `/provider` | Show available providers with auth status | | `/personality [name]` | Set a personality | | `/retry` | Retry the last message | | `/undo` | Remove the last exchange |