mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-05-25 19:20:16 +00:00
Merge PR #1415 from Thanatos-Z: fix named custom provider routing in model picker
This commit is contained in:
+4
-1
@@ -1966,8 +1966,11 @@ def get_available_models() -> dict:
|
||||
if _slug not in _named_custom_groups:
|
||||
_named_custom_groups[_slug] = (_cp_name, [])
|
||||
detected_providers.add(_slug)
|
||||
_cp_option_id = _cp_model
|
||||
if active_provider != _slug and not _cp_option_id.startswith("@"):
|
||||
_cp_option_id = f"@{_slug}:{_cp_option_id}"
|
||||
_named_custom_groups[_slug][1].append(
|
||||
{"id": _cp_model, "label": _cp_label}
|
||||
{"id": _cp_option_id, "label": _cp_label}
|
||||
)
|
||||
else:
|
||||
auto_detected_models.append({"id": _cp_model, "label": _cp_label})
|
||||
|
||||
@@ -196,3 +196,26 @@ class TestCustomProvidersModelsDict:
|
||||
# No cross-contamination
|
||||
assert "model-b1" not in ids_a
|
||||
assert "model-a1" not in ids_b
|
||||
|
||||
def test_named_custom_models_are_prefixed_when_not_active_provider(self):
|
||||
"""Named custom provider models must carry a routing prefix when DeepSeek is active."""
|
||||
result = _models_with_cfg(
|
||||
model_cfg={"provider": "deepseek", "default": "deepseek-v4-pro"},
|
||||
custom_providers=[
|
||||
{
|
||||
"name": "sub2api",
|
||||
"base_url": "http://127.0.0.1:8080/v1",
|
||||
"model": "gpt-5.4-mini",
|
||||
"models": {
|
||||
"gpt-5.4-mini": {},
|
||||
"gpt-5.4": {},
|
||||
},
|
||||
}
|
||||
],
|
||||
)
|
||||
group = _group_for(result, "sub2api")
|
||||
assert group is not None, "sub2api group missing"
|
||||
assert group["provider_id"] == "custom:sub2api"
|
||||
ids = [m["id"] for m in group["models"]]
|
||||
assert "@custom:sub2api:gpt-5.4-mini" in ids
|
||||
assert "@custom:sub2api:gpt-5.4" in ids
|
||||
|
||||
@@ -751,6 +751,49 @@ def test_issue1253_duplicate_model_id_active_provider_hint_preserved(monkeypatch
|
||||
)
|
||||
|
||||
|
||||
def test_named_custom_provider_hint_with_colon_is_preserved(monkeypatch):
|
||||
"""@custom:name:model must survive chat/start normalization for WebUI routing."""
|
||||
import api.routes as routes
|
||||
|
||||
monkeypatch.setattr(
|
||||
routes,
|
||||
"get_available_models",
|
||||
lambda: {
|
||||
"active_provider": "deepseek",
|
||||
"default_model": "deepseek-v4-pro",
|
||||
"groups": [
|
||||
{
|
||||
"provider": "sub2api",
|
||||
"provider_id": "custom:sub2api",
|
||||
"models": [
|
||||
{
|
||||
"id": "@custom:sub2api:gpt-5.4-mini",
|
||||
"label": "GPT 5.4 Mini",
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"provider": "DeepSeek",
|
||||
"provider_id": "deepseek",
|
||||
"models": [
|
||||
{
|
||||
"id": "deepseek-v4-pro",
|
||||
"label": "DeepSeek V4 Pro",
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
effective, changed = routes._resolve_compatible_session_model(
|
||||
"@custom:sub2api:gpt-5.4-mini"
|
||||
)
|
||||
|
||||
assert changed is False
|
||||
assert effective == "@custom:sub2api:gpt-5.4-mini"
|
||||
|
||||
|
||||
def test_stale_at_provider_model_falls_back_when_family_mismatches(monkeypatch):
|
||||
"""Unroutable @provider:model should not invent a bare model for another family."""
|
||||
import api.routes as routes
|
||||
|
||||
@@ -11,8 +11,10 @@ Tests run against the isolated test test_server on port 8788.
|
||||
"""
|
||||
|
||||
import json
|
||||
import importlib
|
||||
import pathlib
|
||||
import sys
|
||||
import types
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
import pytest
|
||||
@@ -105,6 +107,28 @@ def test_redact_value_list():
|
||||
assert result[1]["content"] == "safe text"
|
||||
|
||||
|
||||
def test_redact_value_works_with_legacy_agent_redact_signature(monkeypatch):
|
||||
"""_redact_text must tolerate older redact_sensitive_text(text) signatures."""
|
||||
fake_agent = types.ModuleType("agent")
|
||||
fake_redact = types.ModuleType("agent.redact")
|
||||
|
||||
def _legacy_redact_sensitive_text(text):
|
||||
return text
|
||||
|
||||
fake_redact.redact_sensitive_text = _legacy_redact_sensitive_text
|
||||
monkeypatch.setitem(sys.modules, "agent", fake_agent)
|
||||
monkeypatch.setitem(sys.modules, "agent.redact", fake_redact)
|
||||
|
||||
import api.helpers as helpers
|
||||
helpers = importlib.reload(helpers)
|
||||
try:
|
||||
result = helpers._redact_value(f"token={_FAKE_GITHUB_PAT}")
|
||||
assert _FAKE_GITHUB_PAT not in result
|
||||
assert "ghp_Te" in result
|
||||
finally:
|
||||
importlib.reload(helpers)
|
||||
|
||||
|
||||
def test_redact_session_data_messages():
|
||||
"""redact_session_data masks credentials in messages[]."""
|
||||
from api.helpers import redact_session_data
|
||||
|
||||
Reference in New Issue
Block a user