fix: skip canonical providers when user has config-defined models - #21983
fix: skip canonical providers when user has config-defined models#21983rocktear wants to merge 1 commit into
Conversation
fix: skip canonical providers when user has config-defined models
|
Just wanted to add a bit of context on why this fix matters beyond my specific setup: The core tension here is between auto-discovery (CANONICAL_PROVIDERS auto-extending from plugins) and user control (explicit providers: config). Right now, the auto-extension wins unconditionally — even when the user has explicitly defined which models they want to see. This affects a few scenarios:
Without this fix, the user's explicit providers: config is silently overridden — which feels like a regression from the pre-plugin days when custom_providers at least respected what you wrote. Happy to adjust anything if the maintainers have suggestions! |
|
One more thought as a future direction — right now the plugin system does the heavy lifting of provider registration (name, base_url, env_vars), but model discovery still depends on either _PROVIDER_MODELS or the user's providers: config. The plugin's own fallback_models are never consulted during picker construction. Ideally, a plugin should be fully self-contained: ProviderProfile(
name="free-nvidia",
fallback_models=("deepseek-ai/deepseek-v4-pro", "minimaxai/minimax-m2.7", "z-ai/glm4.7"),
base_url="https://integrate.api.nvidia.com/v1",
)Drop it in, restart, and /model shows 3 models — no config.yaml changes needed. This would mean: if Section 2b finds a canonical provider with no _PROVIDER_MODELS entry, it falls back to profile.fallback_models from the registered plugin. Then discover_models: false could also live in the plugin itself rather than requiring config duplication. Totally understand if this is out of scope for this PR — just wanted to flag it as a natural next step for the plugin system. Happy to open a separate feature request if that's preferred! |
|
Thanks for isolating the Section 2b/Section 3 precedence collision. The underlying config-loss path remains on current main: Problems
Suggested changes
Automated hermes-sweeper review. |
… picker rows list_authenticated_providers() merges a providers.<slug>.models config block into a built-in (section 1, PROVIDER_TO_MODELS_DEV) row's discovered catalog, so a model declared there shows up in the /model picker. Section 2 (HERMES_OVERLAYS — nous, openai-codex, copilot, opencode-go, etc.) builds its model_ids the same way but never applies this merge: a model declared under providers.nous.models (or providers.opencode-go.models, etc.) is already typeable via /model <name> (_configured_provider_matches() scans user_providers generically, by design) but never appears in the picker list — inconsistent with the identical config surface working correctly for built-in providers. Fix: apply the same merge (configured models first, deduplicated against the discovered list) right before model_ids is capped to max_models, using hermes_slug as the config key — the same slug the row itself reports and the same namespace _configured_provider_matches() already scans generically (providers.nous, providers.openai-codex are documented config keys, see hermes_cli/auth.py's own comments). Scoped to section 2 only. Section 2b (CANONICAL_PROVIDERS) has the same "providers.<slug>.models is invisible to the picker" symptom for a different subset of providers, but two other open PRs (NousResearch#21983, NousResearch#60656) are already actively reworking that exact code region with a different approach (skip-and-defer to section 3 vs. merge) — not touching it here to avoid overlapping scope on the same lines. Adds a mapped-slug regression case: HERMES_OVERLAYS key "github-copilot" (a models.dev ID) that PROVIDER_TO_MODELS_DEV maps back to the Hermes/ config slug "copilot", with providers.copilot.models — proving the providers.<hermes_slug>.models lookup keys off the RESOLVED slug, not the raw overlay/pid key, and exercising the hermes_slug in {"openai-codex", "copilot", "copilot-acp"} special live-discovery branch specifically (the existing overlay tests only exercised the generic fallback branch via a synthetic 1:1 slug).
fix: skip canonical providers when user has config-defined models
What does this PR do?
Problem
Plugin-registered providers (e.g.
free-nvidia,free-router) auto-enterCANONICAL_PROVIDERSvia the auto-extension at line 826–841 ofmodels.py. When Section 2b oflist_authenticated_providers()processes them:_PROVIDER_MODELS— finds none (plugin providers have no curated entry)models = []and adds slug toseen_slugsproviders:inconfig.yaml) skips because slug is alreadyseen/modelwith 0 modelsFix
Before emitting a canonical row in Section 2b, check if the slug is defined in
user_providers(theproviders:section ofconfig.yaml). If so, skip and let Section 3 handle it — the user's explicitbase_url/api_key/modelsconfig always wins.Related Issue
Fixes a regression introduced by the CANONICAL_PROVIDERS auto-extension feature.
Type of Change
Changes Made
hermes_cli/model_switch.py: Inlist_authenticated_providers(), Section 2b — added a guard before emitting the results entry: if the slug exists inuser_providers, skip and let Section 3 provide the models list from config.How to Test
~/.hermes/plugins/model-providers/free-nvidia/with aProviderProfilefree-nvidia:underproviders:inconfig.yamlwith 3 models +discover_models: false/modelshowsfree-nvidiawith 0 models/modelshowsfree-nvidiawith 3 modelsChecklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — N/Acli-config.yaml.exampleif I added/changed config keys — N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/A