From 563077a47ad32b9fadd7ed302827c7083e25a2e0 Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Wed, 13 May 2026 22:26:52 -0700 Subject: [PATCH] refactor(cli): route /model picker through shared inventory module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The interactive CLI /model picker was the third call-site duplicating the inline config-slice + list_authenticated_providers pattern that PR #23666 consolidated for the dashboard and TUI. Route it through load_picker_context() + build_models_payload() too so all surfaces that show authenticated providers share one substrate. Side effect: cli.py now also benefits from the latent v12+ keyed providers fix (custom_providers populated via get_compatible_custom_providers, not cfg.get raw). The aux-task switcher (hermes_cli/main.py) and gateway model switcher (gateway/run.py) deliberately stay on the legacy path — they use different config sections (auxiliary..*) and a different config loader (_load_gateway_config) respectively, so forcing them through ConfigContext would either overload its semantics or grow the module past the clean refactor scope. --- cli.py | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/cli.py b/cli.py index 5560846320d..f2d0d019df2 100644 --- a/cli.py +++ b/cli.py @@ -6614,7 +6614,7 @@ class HermesCLI: /model --provider — switch provider + model /model --provider — switch to provider, auto-detect model """ - from hermes_cli.model_switch import switch_model, parse_model_flags, list_authenticated_providers + from hermes_cli.model_switch import switch_model, parse_model_flags from hermes_cli.providers import get_label # Parse args from the original command @@ -6624,16 +6624,25 @@ class HermesCLI: # Parse --provider and --global flags model_input, explicit_provider, persist_global = parse_model_flags(raw_args) - # Load providers for switch_model (picker path needs them below) - user_provs = None - custom_provs = None + # Single inventory context — replaces the inline config-slice the + # dashboard / TUI used to duplicate. Overlay live session state + # via with_overrides (truthy-only) so empty self.* attrs don't + # clobber disk config. + from hermes_cli.inventory import build_models_payload, load_picker_context + try: - from hermes_cli.config import get_compatible_custom_providers, load_config - cfg = load_config() - user_provs = cfg.get("providers") - custom_provs = get_compatible_custom_providers(cfg) + ctx = load_picker_context().with_overrides( + current_provider=self.provider or "", + current_model=self.model or "", + current_base_url=self.base_url or "", + ) except Exception: - pass + ctx = None + + # switch_model() + _open_model_picker still need the raw provider + # dicts; ConfigContext is the canonical source for both. + user_provs = ctx.user_providers if ctx is not None else None + custom_provs = ctx.custom_providers if ctx is not None else None # No args at all: open prompt_toolkit-native picker modal if not model_input and not explicit_provider: @@ -6641,14 +6650,9 @@ class HermesCLI: provider_display = get_label(self.provider) if self.provider else "unknown" try: - providers = list_authenticated_providers( - current_provider=self.provider or "", - current_base_url=self.base_url or "", - current_model=self.model or "", - user_providers=user_provs, - custom_providers=custom_provs, - max_models=50, - ) + if ctx is None: + raise RuntimeError("inventory context unavailable") + providers = build_models_payload(ctx, max_models=50)["providers"] except Exception: providers = []