mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
fix: remove hardcoded OpenRouter/opus defaults
No model, base_url, or provider is assumed when the user hasn't configured one. Previously the defaults dict in cli.py, AIAgent constructor args, and several fallback paths all hardcoded anthropic/claude-opus-4.6 + openrouter.ai/api/v1 — silently routing unconfigured users to OpenRouter, which 404s for anyone using a different provider. Now empty defaults force the setup wizard to run, and existing users who already completed setup are unaffected (their config.yaml has the model they chose). Files changed: - cli.py: defaults dict, _DEFAULT_CONFIG_MODEL - run_agent.py: AIAgent.__init__ defaults, main() defaults - hermes_cli/config.py: DEFAULT_CONFIG - hermes_cli/runtime_provider.py: is_fallback sentinel - acp_adapter/session.py: default_model - tests: updated to reflect empty defaults
This commit is contained in:
parent
3628ccc8c4
commit
de9bba8d7c
7 changed files with 19 additions and 20 deletions
|
|
@ -426,7 +426,7 @@ class SessionManager:
|
||||||
|
|
||||||
config = load_config()
|
config = load_config()
|
||||||
model_cfg = config.get("model")
|
model_cfg = config.get("model")
|
||||||
default_model = "anthropic/claude-opus-4.6"
|
default_model = ""
|
||||||
config_provider = None
|
config_provider = None
|
||||||
if isinstance(model_cfg, dict):
|
if isinstance(model_cfg, dict):
|
||||||
default_model = str(model_cfg.get("default") or default_model)
|
default_model = str(model_cfg.get("default") or default_model)
|
||||||
|
|
|
||||||
6
cli.py
6
cli.py
|
|
@ -144,8 +144,8 @@ def load_cli_config() -> Dict[str, Any]:
|
||||||
# Default configuration
|
# Default configuration
|
||||||
defaults = {
|
defaults = {
|
||||||
"model": {
|
"model": {
|
||||||
"default": "anthropic/claude-opus-4.6",
|
"default": "",
|
||||||
"base_url": OPENROUTER_BASE_URL,
|
"base_url": "",
|
||||||
"provider": "auto",
|
"provider": "auto",
|
||||||
},
|
},
|
||||||
"terminal": {
|
"terminal": {
|
||||||
|
|
@ -1103,7 +1103,7 @@ class HermesCLI:
|
||||||
# env vars would stomp each other.
|
# env vars would stomp each other.
|
||||||
_model_config = CLI_CONFIG.get("model", {})
|
_model_config = CLI_CONFIG.get("model", {})
|
||||||
_config_model = (_model_config.get("default") or _model_config.get("model") or "") if isinstance(_model_config, dict) else (_model_config or "")
|
_config_model = (_model_config.get("default") or _model_config.get("model") or "") if isinstance(_model_config, dict) else (_model_config or "")
|
||||||
_DEFAULT_CONFIG_MODEL = "anthropic/claude-opus-4.6"
|
_DEFAULT_CONFIG_MODEL = ""
|
||||||
self.model = model or _config_model or _DEFAULT_CONFIG_MODEL
|
self.model = model or _config_model or _DEFAULT_CONFIG_MODEL
|
||||||
# Auto-detect model from local server if still on default
|
# Auto-detect model from local server if still on default
|
||||||
if self.model == _DEFAULT_CONFIG_MODEL:
|
if self.model == _DEFAULT_CONFIG_MODEL:
|
||||||
|
|
|
||||||
|
|
@ -196,7 +196,7 @@ def ensure_hermes_home():
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
DEFAULT_CONFIG = {
|
DEFAULT_CONFIG = {
|
||||||
"model": "anthropic/claude-opus-4.6",
|
"model": "",
|
||||||
"fallback_providers": [],
|
"fallback_providers": [],
|
||||||
"credential_pool_strategies": {},
|
"credential_pool_strategies": {},
|
||||||
"toolsets": ["hermes-cli"],
|
"toolsets": ["hermes-cli"],
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ def _get_model_config() -> Dict[str, Any]:
|
||||||
default = (cfg.get("default") or "").strip()
|
default = (cfg.get("default") or "").strip()
|
||||||
base_url = (cfg.get("base_url") or "").strip()
|
base_url = (cfg.get("base_url") or "").strip()
|
||||||
is_local = "localhost" in base_url or "127.0.0.1" in base_url
|
is_local = "localhost" in base_url or "127.0.0.1" in base_url
|
||||||
is_fallback = not default or default == "anthropic/claude-opus-4.6"
|
is_fallback = not default
|
||||||
if is_local and is_fallback and base_url:
|
if is_local and is_fallback and base_url:
|
||||||
detected = _auto_detect_local_model(base_url)
|
detected = _auto_detect_local_model(base_url)
|
||||||
if detected:
|
if detected:
|
||||||
|
|
|
||||||
11
run_agent.py
11
run_agent.py
|
|
@ -471,7 +471,7 @@ class AIAgent:
|
||||||
acp_args: list[str] | None = None,
|
acp_args: list[str] | None = None,
|
||||||
command: str = None,
|
command: str = None,
|
||||||
args: list[str] | None = None,
|
args: list[str] | None = None,
|
||||||
model: str = "anthropic/claude-opus-4.6", # OpenRouter format
|
model: str = "",
|
||||||
max_iterations: int = 90, # Default tool-calling iterations (shared with subagents)
|
max_iterations: int = 90, # Default tool-calling iterations (shared with subagents)
|
||||||
tool_delay: float = 1.0,
|
tool_delay: float = 1.0,
|
||||||
enabled_toolsets: List[str] = None,
|
enabled_toolsets: List[str] = None,
|
||||||
|
|
@ -586,10 +586,9 @@ class AIAgent:
|
||||||
self.log_prefix_chars = log_prefix_chars
|
self.log_prefix_chars = log_prefix_chars
|
||||||
self.log_prefix = f"{log_prefix} " if log_prefix else ""
|
self.log_prefix = f"{log_prefix} " if log_prefix else ""
|
||||||
# Store effective base URL for feature detection (prompt caching, reasoning, etc.)
|
# Store effective base URL for feature detection (prompt caching, reasoning, etc.)
|
||||||
# When no base_url is provided, the client defaults to OpenRouter, so reflect that here.
|
self.base_url = base_url or ""
|
||||||
self.base_url = base_url or OPENROUTER_BASE_URL
|
|
||||||
provider_name = provider.strip().lower() if isinstance(provider, str) and provider.strip() else None
|
provider_name = provider.strip().lower() if isinstance(provider, str) and provider.strip() else None
|
||||||
self.provider = provider_name or "openrouter"
|
self.provider = provider_name or ""
|
||||||
self.acp_command = acp_command or command
|
self.acp_command = acp_command or command
|
||||||
self.acp_args = list(acp_args or args or [])
|
self.acp_args = list(acp_args or args or [])
|
||||||
if api_mode in {"chat_completions", "codex_responses", "anthropic_messages"}:
|
if api_mode in {"chat_completions", "codex_responses", "anthropic_messages"}:
|
||||||
|
|
@ -8520,9 +8519,9 @@ class AIAgent:
|
||||||
|
|
||||||
def main(
|
def main(
|
||||||
query: str = None,
|
query: str = None,
|
||||||
model: str = "anthropic/claude-opus-4.6",
|
model: str = "",
|
||||||
api_key: str = None,
|
api_key: str = None,
|
||||||
base_url: str = "https://openrouter.ai/api/v1",
|
base_url: str = "",
|
||||||
max_turns: int = 10,
|
max_turns: int = 10,
|
||||||
enabled_toolsets: str = None,
|
enabled_toolsets: str = None,
|
||||||
disabled_toolsets: str = None,
|
disabled_toolsets: str = None,
|
||||||
|
|
|
||||||
|
|
@ -704,14 +704,14 @@ class TestHasAnyProviderConfigured:
|
||||||
assert _has_any_provider_configured() is True
|
assert _has_any_provider_configured() is True
|
||||||
|
|
||||||
def test_config_dict_no_provider_no_creds_still_false(self, monkeypatch, tmp_path):
|
def test_config_dict_no_provider_no_creds_still_false(self, monkeypatch, tmp_path):
|
||||||
"""config.yaml model dict with only 'default' key and no creds stays false."""
|
"""config.yaml model dict with empty default and no creds stays false."""
|
||||||
import yaml
|
import yaml
|
||||||
from hermes_cli import config as config_module
|
from hermes_cli import config as config_module
|
||||||
hermes_home = tmp_path / ".hermes"
|
hermes_home = tmp_path / ".hermes"
|
||||||
hermes_home.mkdir()
|
hermes_home.mkdir()
|
||||||
config_file = hermes_home / "config.yaml"
|
config_file = hermes_home / "config.yaml"
|
||||||
config_file.write_text(yaml.dump({
|
config_file.write_text(yaml.dump({
|
||||||
"model": {"default": "anthropic/claude-opus-4.6"},
|
"model": {"default": ""},
|
||||||
}))
|
}))
|
||||||
monkeypatch.setattr(config_module, "get_env_path", lambda: hermes_home / ".env")
|
monkeypatch.setattr(config_module, "get_env_path", lambda: hermes_home / ".env")
|
||||||
monkeypatch.setattr(config_module, "get_hermes_home", lambda: hermes_home)
|
monkeypatch.setattr(config_module, "get_hermes_home", lambda: hermes_home)
|
||||||
|
|
|
||||||
|
|
@ -187,12 +187,12 @@ class TestNormalizeModelForProvider:
|
||||||
assert cli.model == "claude-opus-4.6"
|
assert cli.model == "claude-opus-4.6"
|
||||||
|
|
||||||
def test_default_model_replaced(self):
|
def test_default_model_replaced(self):
|
||||||
"""The untouched default (anthropic/claude-opus-4.6) gets swapped."""
|
"""No model configured (empty default) gets swapped for codex."""
|
||||||
import cli as _cli_mod
|
import cli as _cli_mod
|
||||||
_clean_config = {
|
_clean_config = {
|
||||||
"model": {
|
"model": {
|
||||||
"default": "anthropic/claude-opus-4.6",
|
"default": "",
|
||||||
"base_url": "https://openrouter.ai/api/v1",
|
"base_url": "",
|
||||||
"provider": "auto",
|
"provider": "auto",
|
||||||
},
|
},
|
||||||
"display": {"compact": False, "tool_progress": "all", "resume_display": "full"},
|
"display": {"compact": False, "tool_progress": "all", "resume_display": "full"},
|
||||||
|
|
@ -219,12 +219,12 @@ class TestNormalizeModelForProvider:
|
||||||
assert cli.model == "gpt-5.3-codex"
|
assert cli.model == "gpt-5.3-codex"
|
||||||
|
|
||||||
def test_default_fallback_when_api_fails(self):
|
def test_default_fallback_when_api_fails(self):
|
||||||
"""Default model falls back to gpt-5.3-codex when API unreachable."""
|
"""No model configured falls back to gpt-5.3-codex when API unreachable."""
|
||||||
import cli as _cli_mod
|
import cli as _cli_mod
|
||||||
_clean_config = {
|
_clean_config = {
|
||||||
"model": {
|
"model": {
|
||||||
"default": "anthropic/claude-opus-4.6",
|
"default": "",
|
||||||
"base_url": "https://openrouter.ai/api/v1",
|
"base_url": "",
|
||||||
"provider": "auto",
|
"provider": "auto",
|
||||||
},
|
},
|
||||||
"display": {"compact": False, "tool_progress": "all", "resume_display": "full"},
|
"display": {"compact": False, "tool_progress": "all", "resume_display": "full"},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue