Bug Description
When the active provider in config.yaml is set to bare "custom", the /model picker (both in the WebUI Dashboard and gateway-based UIs like Telegram/Discord) displays a different provider as the current one instead of the actual custom provider.
For example, if the user's active provider is "custom" pointing to a local Ollama/llama-swap instance, the picker may show copilot (or another built-in provider) with the ● current marker, while the actual custom provider is shown as a non-current option.
Root Cause
The issue is in hermes_cli/model_switch.py in the list_authenticated_providers() function, specifically in the custom providers section (section 4).
When a custom provider's base_url matches the currently active endpoint, the slug is resolved to "custom:<name>" form (e.g. "custom:llama-swap"), but the is_current check only does a direct string comparison:
Original line ~1672:
"is_current": slug == current_provider, # "custom:llama-swap" == "custom" → False!
When current_provider == "custom" and the slug resolves to "custom:llama-swap", the comparison fails, so the actual custom provider is not marked as current.
Verified Fix
Replace the slug-only is_current check with a dual check — slug OR endpoint URL:
# Match by slug OR by endpoint URL. This handles the case where
# current_provider is the bare "custom" string but the slug has
# been resolved to "custom:<name>" (e.g. "custom:llama-swap").
# The URL-based fallback guarantees the active endpoint is
# always highlighted as current in the picker.
_cur_base_norm = (current_base_url or "").strip().rstrip("/")
is_current = slug == current_provider or (
_cur_base_norm and _grp_url_norm == _cur_base_norm.lower()
)
results.append({
"slug": slug,
"name": grp["name"],
"is_current": is_current, # <-- uses the dual check
"is_user_defined": True,
...
})
Key details:
_grp_url_norm comes from _pair_key[1] which is already .lower() (line 1657)
_cur_base_norm is lowercased at comparison time to ensure case-insensitive match
- The original slug comparison is preserved as the primary check (fast path)
- The URL comparison is a fallback — it only activates when the slug doesn't match
Expected Behavior
When current_provider is "custom" and a custom provider group matches the active current_base_url, that provider group is marked as is_current: true and displayed first in the picker with the current marker.
Reproduction Steps
- Configure a custom provider in
config.yaml with a local endpoint (e.g., Ollama, llama-swap)
- Set the active provider to
"custom"
- Open the
/model picker (in WebUI or any gateway UI)
- Before fix: the actual custom endpoint is NOT highlighted as current
- After fix: the active endpoint is correctly highlighted
Impact
- Affects all gateway UIs (WebUI Dashboard, Telegram, Discord, etc.) that use the
/model picker
- Users may accidentally switch providers thinking they are selecting the current one
- Provider picker sorting is affected (
is_current controls sort priority at line 1693)
Bug Description
When the active provider in config.yaml is set to bare
"custom", the/modelpicker (both in the WebUI Dashboard and gateway-based UIs like Telegram/Discord) displays a different provider as the current one instead of the actual custom provider.For example, if the user's active provider is
"custom"pointing to a local Ollama/llama-swap instance, the picker may showcopilot(or another built-in provider) with the● currentmarker, while the actual custom provider is shown as a non-current option.Root Cause
The issue is in
hermes_cli/model_switch.pyin thelist_authenticated_providers()function, specifically in the custom providers section (section 4).When a custom provider's
base_urlmatches the currently active endpoint, the slug is resolved to"custom:<name>"form (e.g."custom:llama-swap"), but theis_currentcheck only does a direct string comparison:Original line ~1672:
When
current_provider == "custom"and the slug resolves to"custom:llama-swap", the comparison fails, so the actual custom provider is not marked as current.Verified Fix
Replace the slug-only
is_currentcheck with a dual check — slug OR endpoint URL:Key details:
_grp_url_normcomes from_pair_key[1]which is already.lower()(line 1657)_cur_base_normis lowercased at comparison time to ensure case-insensitive matchExpected Behavior
When
current_provideris"custom"and a custom provider group matches the activecurrent_base_url, that provider group is marked asis_current: trueand displayed first in the picker with the current marker.Reproduction Steps
config.yamlwith a local endpoint (e.g., Ollama, llama-swap)"custom"/modelpicker (in WebUI or any gateway UI)Impact
/modelpickeris_currentcontrols sort priority at line 1693)