Skip to content

fix(model): match bare custom provider by active base URL#28908

Merged
teknium1 merged 1 commit into
NousResearch:mainfrom
helix4u:fix/hermes-model-custom-provider-base-url
May 19, 2026
Merged

fix(model): match bare custom provider by active base URL#28908
teknium1 merged 1 commit into
NousResearch:mainfrom
helix4u:fix/hermes-model-custom-provider-base-url

Conversation

@helix4u

@helix4u helix4u commented May 19, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes the top-level hermes model picker for configs where the active model is stored as bare provider: custom plus a model.base_url, while multiple custom_providers are saved.

Previously, hermes model resolved bare custom through the compatibility fallback before checking the active endpoint. That fallback returns the first saved custom provider, so a config with Cerebras first and NeuralWatt active could show Cerebras as current.

This PR makes the CLI model picker match bare custom providers by normalized active model.base_url before falling back to the first saved custom provider. It also preserves raw ${...} base URL templates when saving a named custom provider, matching the existing API-key template preservation behavior.

Related Issue

N/A - Discord support thread report from DrWayne.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • hermes_cli/main.py
    • Build the named custom provider map before resolving the active provider in select_provider_and_model().
    • When model.provider is bare custom and model.base_url is set, match the active custom provider by normalized loaded base URL before using the bare-custom compatibility fallback.
    • Track raw base_url env references alongside existing api_key_ref metadata.
    • Persist model.base_url using the raw ${VAR} template when the selected named custom provider came from an env-ref-backed config entry.
  • tests/hermes_cli/test_custom_provider_model_switch.py
    • Add regression coverage for Cerebras-first / NeuralWatt-active custom-provider configs.
    • Add regression coverage that selecting an env-backed custom provider preserves ${NEURALWATT_API_BASE} in model.base_url while still probing the expanded URL.

How to Test

  1. Configure model.provider: custom with model.base_url pointing at the second saved custom_providers entry.
  2. Run hermes model.
  3. Confirm the provider whose loaded base URL matches model.base_url is marked current, not the first saved custom provider.

Focused local checks run:

  • uv run --frozen pytest -q -o addopts='' tests/hermes_cli/test_custom_provider_model_switch.py -> 13 passed
  • uv run --frozen pytest -q -o addopts='' tests/hermes_cli/test_custom_provider_model_switch.py tests/hermes_cli/test_model_switch_custom_providers.py tests/hermes_cli/test_setup.py tests/hermes_cli/test_setup_model_provider.py -k 'custom_provider or custom_providers or named_custom or select_provider_and_model' -> 36 passed, 28 deselected
  • python -m py_compile hermes_cli/main.py tests/hermes_cli/test_custom_provider_model_switch.py -> passed
  • git diff --check -- hermes_cli/main.py tests/hermes_cli/test_custom_provider_model_switch.py -> passed

Full local suite run after opening this draft PR:

  • scripts/run_tests.sh -> failed: 16 failed, 24532 passed, 54 skipped, 250 warnings in 704.83s (0:11:44)
  • HERMES_HOME before and after the run was empty / unchanged.
  • Failing tests reported:
    • tests/gateway/test_api_server.py::TestAdapterInit::test_default_config
    • tests/gateway/test_approve_deny_commands.py::TestBlockingApprovalE2E::test_blocking_approval_approve_once
    • tests/gateway/test_approve_deny_commands.py::TestBlockingApprovalE2E::test_blocking_approval_deny
    • tests/gateway/test_config.py::TestLoadGatewayConfig::test_bridges_quoted_false_platform_enabled_from_config_yaml
    • tests/gateway/test_discord_bot_filter.py::TestDiscordBotFilter::test_default_is_none
    • tests/gateway/test_restart_resume_pending.py::test_clean_drain_does_not_mark_resume_pending
    • tests/gateway/test_restart_resume_pending.py::test_drain_timeout_only_marks_still_running_sessions
    • tests/gateway/test_runner_startup_failures.py::test_start_gateway_replace_force_uses_terminate_pid
    • tests/hermes_cli/test_update_gateway_restart.py::TestLaunchdPlistPath::test_plist_path_starts_with_venv_bin
    • tests/hermes_cli/test_update_hangup_protection.py::TestInstallHangupProtection::test_wraps_stdout_and_stderr_with_mirror
    • tests/tools/test_file_operations.py::TestGitBaselineCheck::test_git_not_available_returns_none
    • tests/tools/test_file_operations.py::TestGitBaselineCheck::test_not_in_git_repo_returns_none
    • tests/tools/test_file_operations.py::TestGitBaselineCheck::test_clean_repo_returns_none
    • tests/tools/test_file_operations.py::TestGitBaselineCheck::test_dirty_repo_returns_warning
    • tests/tools/test_file_operations.py::TestGitBaselineCheck::test_write_file_includes_git_warning_when_dirty
    • tests/tools/test_tirith_security.py::TestDiskFailureMarker::test_cosign_missing_marker_clears_when_cosign_appears

uv run --frozen ruff check hermes_cli/main.py tests/hermes_cli/test_custom_provider_model_switch.py could not run locally because ruff is not available in this uv environment.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: WSL2 / Linux

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

For New Skills

N/A

Screenshots / Logs

Focused local checks passed. Full local suite failure details are listed above.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard area/config Config system, migrations, profiles labels May 19, 2026
@helix4u helix4u marked this pull request as ready for review May 19, 2026 20:06
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related: #28860 (merged) fixes the is_current display bug for bare custom providers in model_switch.py. This PR addresses a separate code path in main.py (select_provider_and_model()) and additionally preserves ${...} base_url templates on save. Not a duplicate but overlapping area — verify the picker header label is correct after #28860 alone.

@teknium1 teknium1 merged commit d9829ab into NousResearch:main May 19, 2026
15 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants