fix(inventory): handle dict entries in provider models lists for model selector - #57411
Conversation
…l selector When a provider's `models:` config is a list of dicts (hand-edited config or legacy format with per-model metadata like context_length), the dicts were appended directly to the models list. Downstream code in `build_models_payload` calls `.lower()` on every model entry for deduplication, causing an `AttributeError: 'dict' object has no attribute 'lower'` crash in the Desktop model selector. Fix: extract the `id` field from dict entries in both Section 3 (providers:) and Section 4 (custom_providers:) of `list_authenticated_providers()`, and add defensive type guards in `build_models_payload()` dedup logic. Regression tests cover: list-of-dicts, flat string list, keyed dict, custom_providers list-of-dicts, and dicts without 'id' field.
Related: #57405 (the issue this fixes), and the competing open fix PRs #33372 (earliest — |
|
Thanks for the focused reproduction and regression coverage. This is an automated hermes-sweeper review; current
The related issue discussion also identifies this PR as part of the competing-fix cluster. Closing as implemented on main. |
What does this PR do?
Fixes a crash in the model selector dropdown when a provider's
models:config contains dict entries instead of plain strings. When users hand-editconfig.yamlwith per-model metadata (e.g.models: [{id: "gpt-4", context_length: 128000}]), the dicts leak into the model list. Downstream dedup logic inbuild_models_payload()calls.lower()on every entry, causingAttributeError: 'dict' object has no attribute 'lower'.The fix extracts the
idfield from dict entries at the source (list_authenticated_providers()Sections 3 and 4) and adds defensive type guards in the inventory dedup path.Related Issue
Fixes #57405
Type of Change
Changes Made
hermes_cli/model_switch.py: In Section 3 (providers:handling) and Section 4 (custom_providers:handling), whencfg_modelsis a list, extractm.get("id")from dict entries instead of appending the raw dict to the models list.hermes_cli/inventory.py: Addisinstance(m, str)guard inbuild_models_payload()dedup logic (lines 188 and 210) so non-string entries are filtered out instead of crashing.tests/hermes_cli/test_model_dict_entries.py: 5 regression tests covering list-of-dicts, flat string list, keyed dict, custom_providers list-of-dicts, and dicts withoutidfield.How to Test
providers:entry in~/.hermes/config.yamlwithmodels:as a list of dicts:pytest tests/hermes_cli/test_model_dict_entries.py -v— all 5 tests should pass.build_models_payload()returns all-string model entries with dict-in-list config.Checklist
Code
fix(scope):)pytest tests/ -qand all tests passDocumentation and Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AScreenshots / Logs
Reproduction test output: