Bug Description
Description
The current model-switching logic in hermes_cli makes it difficult to maintain a stable connection to local/custom OpenAI-compatible endpoints (e.g., Ollama, LM Studio). Even after successfully configuring a custom endpoint, the CLI frequently "forgets" these settings, defaults back to cloud providers (like OpenRouter) due to environment variable precedence, and requires manual re-entry of the Base URL and API Key in every interactive session.
Current Behavior
- No Pre-filling: Running
hermes model and selecting "Custom endpoint" always presents an empty prompt for the API base URL, ignoring existing values stored in ~/.hermes/config.yaml.
- Environment Overrides: If an
OPENROUTER_API_KEY exists in the .env file, the runtime_provider logic often prioritizes it over a manually configured model.base_url, causing the "Active Provider" to flip back to OpenRouter unexpectedly.
- Silent Validation Failures: In
hermes_cli/model_switch.py, the validation step uses a broad try/except block that returns success=True even when a connection to a local endpoint fails (e.g., connection refused or 404). This prevents users from seeing why their custom setup isn't working.
Steps to Reproduce
Steps to Reproduce
- Run
hermes model and configure a custom URL (e.g., http://localhost:11434/v1).
- Verify the model works in a chat session.
- Exit the CLI and run
hermes model again.
- Observe that the "Active provider" has reverted
Expected Behavior
Expected Behavior
- Interactive Pre-filling: When running
hermes model and selecting "Custom endpoint," the CLI should pull the existing base_url and api_key from ~/.hermes/config.yaml and offer them as default values in the prompt (e.g., API base URL [http://localhost:11434/v1]: ).
- Configuration Precedence: An explicitly configured
model.base_url in config.yaml should take precedence over environment-level API keys (like OPENROUTER_API_KEY) when the active provider is set to custom.
- Transparent Validation: The model-switching pipeline should surface connection errors (e.g., "Connection Refused," "401 Unauthorized," or "Model Not Found") instead of catching exceptions and returning a silent
success=True.
- Persistent State: A successfully configured custom model should remain the "Active provider" across CLI restarts unless explicitly changed by the user.
Actual Behavior
Actual Behavior
- Empty Interactive Prompts: Running
hermes model and selecting "Custom endpoint" always presents a blank prompt for API base URL and API Key, even when these values are already correctly defined in ~/.hermes/config.yaml.
- Environment Variable Precedence: If an
OPENROUTER_API_KEY is present in the .env file, the runtime_provider logic defaults the "Active Provider" to OpenRouter, effectively "losing" the custom endpoint configuration in the UI.
- Silent Validation Failures: The
switch_model pipeline in hermes_cli/model_switch.py uses a broad try/except block that returns success=True for almost any connection error (e.g., 404, Connection Refused, or invalid JSON). This results in the CLI reporting a "Successful switch" to a model that is actually unreachable.
- Non-Persistent State: Because the interactive flow does not check or display the current configuration as a default, users are forced to re-type the full Base URL and API Key every time they wish to verify or tweak their custom setup.
Affected Component
CLI (interactive chat)
Messaging Platform (if gateway-related)
No response
Operating System
macOS Tahoe 26.2 (25C56)
Python Version
3.9.6
Hermes Version
Hermes Agent v0.4.0 (2026.3.23)
Relevant Logs / Traceback
Root Cause Analysis (optional)
The issue stems from a combination of silent error handling in the switching pipeline and a lack of state-awareness in the CLI entry point.
1. Silent Validation Failures
File: hermes_cli/model_switch.py
Lines: ~110-120
The validation step catches all exceptions (network timeouts, 401s, 404s) and returns a "success" state with recognized: False. This prevents the caller from knowing the switch failed technically.
try:
validation = validate_requested_model(...)
except Exception:
# This block effectively hides all connection/config issues
validation = {
"accepted": True,
"persist": True,
"recognized": False,
"message": None,
}
### Proposed Fix (optional)
### **Proposed Fixes**
#### **1. Surface Validation Errors**
**File:** `hermes_cli/model_switch.py`
Update Step 5 to return the actual error message from the exception so the user knows why the connection failed (e.g., 404 or Connection Refused).
```python
# Proposed change
try:
validation = validate_requested_model(
new_model,
target_provider,
api_key=api_key,
base_url=base_url,
)
except Exception as e:
# Stop returning "accepted: True" for failed connections
return ModelSwitchResult(
success=False,
new_model=new_model,
target_provider=target_provider,
error_message=f"Connection failed: {str(e)}",
)
### Are you willing to submit a PR for this?
- [ ] I'd like to fix this myself and submit a PR
Bug Description
Description
The current model-switching logic in
hermes_climakes it difficult to maintain a stable connection to local/custom OpenAI-compatible endpoints (e.g., Ollama, LM Studio). Even after successfully configuring a custom endpoint, the CLI frequently "forgets" these settings, defaults back to cloud providers (like OpenRouter) due to environment variable precedence, and requires manual re-entry of the Base URL and API Key in every interactive session.Current Behavior
hermes modeland selecting "Custom endpoint" always presents an empty prompt for theAPI base URL, ignoring existing values stored in~/.hermes/config.yaml.OPENROUTER_API_KEYexists in the.envfile, theruntime_providerlogic often prioritizes it over a manually configuredmodel.base_url, causing the "Active Provider" to flip back to OpenRouter unexpectedly.hermes_cli/model_switch.py, the validation step uses a broadtry/exceptblock that returnssuccess=Trueeven when a connection to a local endpoint fails (e.g., connection refused or 404). This prevents users from seeing why their custom setup isn't working.Steps to Reproduce
Steps to Reproduce
hermes modeland configure a custom URL (e.g.,http://localhost:11434/v1).hermes modelagain.Expected Behavior
Expected Behavior
hermes modeland selecting "Custom endpoint," the CLI should pull the existingbase_urlandapi_keyfrom~/.hermes/config.yamland offer them as default values in the prompt (e.g.,API base URL [http://localhost:11434/v1]:).model.base_urlinconfig.yamlshould take precedence over environment-level API keys (likeOPENROUTER_API_KEY) when the active provider is set tocustom.success=True.Actual Behavior
Actual Behavior
hermes modeland selecting "Custom endpoint" always presents a blank prompt forAPI base URLandAPI Key, even when these values are already correctly defined in~/.hermes/config.yaml.OPENROUTER_API_KEYis present in the.envfile, theruntime_providerlogic defaults the "Active Provider" to OpenRouter, effectively "losing" the custom endpoint configuration in the UI.switch_modelpipeline inhermes_cli/model_switch.pyuses a broadtry/exceptblock that returnssuccess=Truefor almost any connection error (e.g., 404, Connection Refused, or invalid JSON). This results in the CLI reporting a "Successful switch" to a model that is actually unreachable.Affected Component
CLI (interactive chat)
Messaging Platform (if gateway-related)
No response
Operating System
macOS Tahoe 26.2 (25C56)
Python Version
3.9.6
Hermes Version
Hermes Agent v0.4.0 (2026.3.23)
Relevant Logs / Traceback
Root Cause Analysis (optional)
The issue stems from a combination of silent error handling in the switching pipeline and a lack of state-awareness in the CLI entry point.
1. Silent Validation Failures
File:
hermes_cli/model_switch.pyLines: ~110-120
The validation step catches all exceptions (network timeouts, 401s, 404s) and returns a "success" state with
recognized: False. This prevents the caller from knowing the switch failed technically.