mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 01:21:43 +00:00
fix: propagate model through credential pool path + add tests
The cherry-picked fix from PR #7916 placed model propagation after the credential pool early-return in _resolve_named_custom_runtime(), making it dead code when a pool is active (which happens whenever custom_providers has an api_key that auto-seeds the pool). - Inject model into pool_result before returning - Add 5 regression tests covering direct path, pool path, empty model, and absent model scenarios - Add 'model' to _VALID_CUSTOM_PROVIDER_FIELDS for config validation
This commit is contained in:
parent
0e6354df50
commit
4bede272cf
3 changed files with 118 additions and 1 deletions
|
|
@ -1214,3 +1214,115 @@ def test_openrouter_provider_not_affected_by_custom_fix(monkeypatch):
|
|||
|
||||
resolved = rp.resolve_runtime_provider(requested="openrouter")
|
||||
assert resolved["provider"] == "openrouter"
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# fix #7828 — custom_providers model field must propagate to runtime
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_get_named_custom_provider_includes_model(monkeypatch):
|
||||
"""_get_named_custom_provider should include the model field from config."""
|
||||
monkeypatch.setattr(rp, "load_config", lambda: {
|
||||
"custom_providers": [{
|
||||
"name": "my-dashscope",
|
||||
"base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
||||
"api_key": "test-key",
|
||||
"api_mode": "chat_completions",
|
||||
"model": "qwen3.6-plus",
|
||||
}],
|
||||
})
|
||||
|
||||
result = rp._get_named_custom_provider("my-dashscope")
|
||||
assert result is not None
|
||||
assert result["model"] == "qwen3.6-plus"
|
||||
|
||||
|
||||
def test_get_named_custom_provider_excludes_empty_model(monkeypatch):
|
||||
"""Empty or whitespace-only model field should not appear in result."""
|
||||
for model_val in ["", " ", None]:
|
||||
entry = {
|
||||
"name": "test-ep",
|
||||
"base_url": "https://example.com/v1",
|
||||
"api_key": "key",
|
||||
}
|
||||
if model_val is not None:
|
||||
entry["model"] = model_val
|
||||
|
||||
monkeypatch.setattr(rp, "load_config", lambda e=entry: {
|
||||
"custom_providers": [e],
|
||||
})
|
||||
|
||||
result = rp._get_named_custom_provider("test-ep")
|
||||
assert result is not None
|
||||
assert "model" not in result, (
|
||||
f"model field {model_val!r} should not be included in result"
|
||||
)
|
||||
|
||||
|
||||
def test_named_custom_runtime_propagates_model_direct_path(monkeypatch):
|
||||
"""Model should propagate through the direct (non-pool) resolution path."""
|
||||
monkeypatch.setattr(rp, "resolve_provider", lambda *a, **k: "my-server")
|
||||
monkeypatch.setattr(
|
||||
rp, "_get_named_custom_provider",
|
||||
lambda p: {
|
||||
"name": "my-server",
|
||||
"base_url": "http://localhost:8000/v1",
|
||||
"api_key": "test-key",
|
||||
"model": "qwen3.6-plus",
|
||||
},
|
||||
)
|
||||
# Ensure pool doesn't intercept
|
||||
monkeypatch.setattr(rp, "_try_resolve_from_custom_pool", lambda *a, **k: None)
|
||||
|
||||
resolved = rp.resolve_runtime_provider(requested="my-server")
|
||||
assert resolved["model"] == "qwen3.6-plus"
|
||||
assert resolved["provider"] == "custom"
|
||||
|
||||
|
||||
def test_named_custom_runtime_propagates_model_pool_path(monkeypatch):
|
||||
"""Model should propagate even when credential pool handles credentials."""
|
||||
monkeypatch.setattr(rp, "resolve_provider", lambda *a, **k: "my-server")
|
||||
monkeypatch.setattr(
|
||||
rp, "_get_named_custom_provider",
|
||||
lambda p: {
|
||||
"name": "my-server",
|
||||
"base_url": "http://localhost:8000/v1",
|
||||
"api_key": "test-key",
|
||||
"model": "qwen3.6-plus",
|
||||
},
|
||||
)
|
||||
# Pool returns a result (intercepting the normal path)
|
||||
monkeypatch.setattr(
|
||||
rp, "_try_resolve_from_custom_pool",
|
||||
lambda *a, **k: {
|
||||
"provider": "custom",
|
||||
"api_mode": "chat_completions",
|
||||
"base_url": "http://localhost:8000/v1",
|
||||
"api_key": "pool-key",
|
||||
"source": "pool:custom:my-server",
|
||||
},
|
||||
)
|
||||
|
||||
resolved = rp.resolve_runtime_provider(requested="my-server")
|
||||
assert resolved["model"] == "qwen3.6-plus", (
|
||||
"model must be injected into pool result"
|
||||
)
|
||||
assert resolved["api_key"] == "pool-key", "pool credentials should be used"
|
||||
|
||||
|
||||
def test_named_custom_runtime_no_model_when_absent(monkeypatch):
|
||||
"""When custom_providers entry has no model field, runtime should not either."""
|
||||
monkeypatch.setattr(rp, "resolve_provider", lambda *a, **k: "my-server")
|
||||
monkeypatch.setattr(
|
||||
rp, "_get_named_custom_provider",
|
||||
lambda p: {
|
||||
"name": "my-server",
|
||||
"base_url": "http://localhost:8000/v1",
|
||||
"api_key": "test-key",
|
||||
},
|
||||
)
|
||||
monkeypatch.setattr(rp, "_try_resolve_from_custom_pool", lambda *a, **k: None)
|
||||
|
||||
resolved = rp.resolve_runtime_provider(requested="my-server")
|
||||
assert "model" not in resolved
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue