Skip to content

Bug: _norm_model_id incorrectly handles @provider:model format with multiple colons #1453

@happy5318

Description

@happy5318

Bug Description

The _norm_model_id function in api/config.py incorrectly normalizes model IDs that have the @provider:model format with nested provider names (e.g., @custom:jingdong:GLM-5).

Current Behavior

# Current code:
if s.startswith("@") and ":" in s:
    s = s.split(":", 1)[1]  # Only removes first segment

For @custom:jingdong:GLM-5:

  • Result: jingdong:glm.5 (incorrect)
  • Expected: glm.5

Impact

This bug causes the duplicate "Default" group to appear in the model dropdown when:

  1. Using custom providers with @custom:provider:model format
  2. The default model is configured in config.yaml

The default model injection check at line ~2072 fails because:

_norm("@custom:jingdong:GLM-5") = "jingdong:glm.5"  # doesn't match
_norm("GLM-5") = "glm.5"  # doesn't match either!

So the code thinks the model doesn't exist and adds a duplicate "Default" group.

Expected Behavior

_norm_model_id("@custom:jingdong:GLM-5") should return glm.5.

Proposed Fix

def _norm_model_id(model_id: str) -> str:
    s = str(model_id or "").strip().lower()
    # Strip @provider: prefix (e.g., @custom:jingdong:GLM-5 -> GLM-5)
    if s.startswith("@") and ":" in s:
        # Split on all colons and take the last part
        s = s.split(":")[-1]
    # Strip provider/model prefix (e.g., custom:jingdong/GLM-5 -> GLM-5)
    if "/" in s:
        s = s.split("/")[-1]
    return s.replace("-", ".")

Environment

  • Hermes WebUI version: latest (post v2.65)
  • Config: Multiple custom_providers with same base_url

Test Case

def test_norm_model_id_nested_provider():
    from api.config import get_available_models
    # ... setup config with custom provider ...
    result = get_available_models()
    # Should NOT have duplicate "Default" group
    providers = [g["provider"] for g in result["groups"]]
    assert providers.count("Default") == 0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsprint-candidateStrong candidate for next sprint

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions