Skip to content

fix: route slash-based custom provider models correctly - #189

Merged
nesquena-hermes merged 1 commit into
nesquena:masterfrom
smurmann:fix/custom-provider-slash-model-routing
Apr 10, 2026
Merged

fix: route slash-based custom provider models correctly#189
nesquena-hermes merged 1 commit into
nesquena:masterfrom
smurmann:fix/custom-provider-slash-model-routing

Conversation

@smurmann

@smurmann smurmann commented Apr 9, 2026

Copy link
Copy Markdown
Contributor

I faced an issue where using a gamma4 through lmstudio on mac via hermes cli chat was fine but through the web UI had issues. I asked my AI to provide a fix for it and this is the PR for it. I'm no expert of this tech stack but I can confirm that the fix worked, so i figured to make a PR.

Here's the AI's report

Summary:

  • check custom_providers for an exact model match before slash-based provider/model heuristics
  • prevent slash-containing custom endpoint models from being misrouted as OpenRouter models
  • add a regression test covering custom slash-based model ids

Repro:

  • configure a custom provider with model google/gemma-4-26b-a4b
  • select that model in Hermes WebUI
  • without this fix, the resolver can treat it as an OpenRouter/provider-path style id instead of routing to the named custom endpoint

Validation:

  • pytest -q /root/hermes-webui/tests/test_model_resolver.py

@smurmann
smurmann force-pushed the fix/custom-provider-slash-model-routing branch from 7fdf34a to 32f82e6 Compare April 9, 2026 08:01
@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Thanks for digging into this and sending a fix! The root cause is real and the fix is correct.

What the bug is

When config_provider is set to openrouter, resolve_model_provider() currently returns early with (model_id, 'openrouter', config_base_url) for any slash-containing model ID. This means a custom provider entry like google/gemma-4-26b-a4b gets silently misrouted to OpenRouter instead of the configured local endpoint.

Fix assessment

The fix inserts a custom-providers lookup before the slash-heuristic block, so named entries in config.yaml -> custom_providers win regardless of the slash format. The logic is sound:

# Custom providers declared in config.yaml should win over slash-based
# OpenRouter heuristics. Their model IDs commonly contain '/' too.
custom_providers = cfg.get('custom_providers', [])
if isinstance(custom_providers, list):
    for entry in custom_providers:
        ...
        if entry_model and entry_name and model_id == entry_model:
            provider_hint = 'custom:' + entry_name.lower().replace(' ', '-')
            return model_id, provider_hint, entry_base_url or None
  • ✅ Exact model-ID match guards against false positives
  • entry_base_url or None correctly handles missing base_url
  • entry_name.lower().replace(' ', '-') normalisation is consistent with how custom providers are resolved downstream
  • ✅ Test coverage added (test_custom_provider_model_with_slash_routes_to_named_custom_provider) with a realistic repro case

One minor note: the api_key field in custom_providers entries isn't extracted here, but that matches the existing pattern — resolve_model_provider only returns (model, provider, base_url), and the key lookup happens separately in resolve_runtime_provider. No issue.

No blockers

Clean fix, well-tested. Glad you confirmed it solved the problem against a real LM Studio + google/gemma-4-26b-a4b setup.

@nesquena nesquena left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Full Review: PR #189 — custom provider slash model routing

Thanks @smurmann for finding and fixing this! Real bug — slash-containing model IDs from custom providers (like google/gemma-4-26b-a4b) were being misrouted as OpenRouter models.

Security Audit

Clean. Python-only changes to model routing logic. No external resources, no injection vectors, no XSS.

Code Review

The fix is correct — custom_providers entries from config.yaml are checked for exact model match before the slash-based OpenRouter heuristic kicks in. This prevents models like google/gemma-4-26b-a4b from being sent to OpenRouter when they belong to a local LM Studio endpoint.

The custom:<name> provider hint format is a reasonable convention for routing through named custom endpoints. The test covers the key scenario well.

One minor note: If custom_providers grows large, the linear scan per model resolution could be slow. For now this is fine — most users have 0-3 custom providers.

Agent Review Verification

Agent approved, no fixes needed. Confirmed — the code matches the agent's description.

Tests

507 passed, 0 failed, 41 skipped. No regressions. New test test_custom_provider_model_with_slash_routes_to_named_custom_provider is well-structured.

Merge Order Note

This PR and #191 both touch api/config.py and test_model_resolver.py. They modify different functions (this one: resolve_model_provider(), #191: get_available_models()), but the test file may need a trivial rebase after whichever merges first.

Verdict

Approved. Ready to merge.

@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Rebased cleanly onto current master (post v0.41.0). All 15 model resolver tests pass including the new regression test for the slash-routing fix.

The fix is correct: custom provider entries in config.yaml → custom_providers now win over the OpenRouter slash-heuristic, so model IDs like google/gemma-4-26b-a4b route to their configured local endpoint rather than silently going to OpenRouter. Exact model-ID matching avoids false positives. Ready to merge.

@nesquena-hermes
nesquena-hermes merged commit fb19c7e into nesquena:master Apr 10, 2026
@smurmann
smurmann deleted the fix/custom-provider-slash-model-routing branch April 10, 2026 01:48
@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Thank you, @smurmann!

Custom provider model routing fix is live and working. That slash-heuristic was a real footgun for anyone running Ollama or LM Studio with multi-segment model IDs. You're in the Contributors section — thank you!

JKJameson pushed a commit to JKJameson/hermes-webui that referenced this pull request Apr 25, 2026
Co-authored-by: smurmann <smurmann@users.noreply.github.com>
SysAdminDoc pushed a commit to SysAdminDoc/hermes-webui that referenced this pull request Jun 26, 2026
Co-authored-by: smurmann <smurmann@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants