fix(providers): resolve plugin-registered provider profiles in get_provider
Plugin-only providers (commandcode, tencent-tokenhub, ...) are absent from models.dev and HERMES_OVERLAYS, so resolve_provider_full returned None and /model switches failed with "Unknown provider ..." even though the picker lists them (CANONICAL_PROVIDERS auto-extends from the same registry). Fall back to providers.get_provider_profile() before giving up, mapping the profile api_mode to the ProviderDef transport.
This commit is contained in:
@@ -525,6 +525,31 @@ def get_provider(name: str, *, allow_network: bool = True) -> Optional[ProviderD
|
||||
source="hermes",
|
||||
)
|
||||
|
||||
# Plugin-registered provider profiles (plugins/model-providers/<name>/).
|
||||
# Providers that ship only as plugin profiles (e.g. commandcode,
|
||||
# tencent-tokenhub) are absent from models.dev and HERMES_OVERLAYS, so
|
||||
# without this fallback they resolve as "Unknown provider" in /model,
|
||||
# --provider, and the model-switch path even though the picker lists them
|
||||
# (CANONICAL_PROVIDERS auto-extends from the same plugin registry).
|
||||
try:
|
||||
from providers import get_provider_profile as _profile
|
||||
|
||||
_prof = _profile(canonical)
|
||||
if _prof is not None:
|
||||
_api_mode_to_transport = {v: k for k, v in TRANSPORT_TO_API_MODE.items()}
|
||||
_transport = _api_mode_to_transport.get(_prof.api_mode, "openai_chat")
|
||||
return ProviderDef(
|
||||
id=canonical,
|
||||
name=_prof.display_name or _prof.name or canonical,
|
||||
transport=_transport,
|
||||
api_key_env_vars=tuple(_prof.env_vars or ()),
|
||||
base_url=_prof.base_url or "",
|
||||
auth_type=_prof.auth_type or "api_key",
|
||||
source="plugin-profile",
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return None
|
||||
|
||||
|
||||
|
||||
@@ -256,3 +256,22 @@ class TestCommandCodeFetchModelsPickerContract:
|
||||
profile = providers.get_provider_profile(profile_name)
|
||||
assert profile is not None
|
||||
assert "base_url" in inspect.signature(profile.fetch_models).parameters
|
||||
|
||||
def test_resolve_provider_full(self):
|
||||
"""Both profiles must resolve through the model-switch path.
|
||||
|
||||
Regression: ``resolve_provider_full`` only knew models.dev + overlay
|
||||
providers, so plugin-only providers (commandcode) failed with
|
||||
"Unknown provider" on /model switches even though the picker listed
|
||||
them.
|
||||
"""
|
||||
from hermes_cli.providers import resolve_provider_full
|
||||
|
||||
chat = resolve_provider_full("commandcode", {}, [])
|
||||
assert chat is not None and chat.id == "commandcode"
|
||||
assert chat.transport == "openai_chat"
|
||||
assert "COMMANDCODE_API_KEY" in chat.api_key_env_vars
|
||||
|
||||
anth = resolve_provider_full("commandcode-anthropic", {}, [])
|
||||
assert anth is not None and anth.id == "commandcode-anthropic"
|
||||
assert anth.transport == "anthropic_messages"
|
||||
|
||||
Reference in New Issue
Block a user