refactor(cli): route /model picker through shared inventory module

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.<task>.*) 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.
This commit is contained in:
teknium1 2026-05-13 22:26:52 -07:00 committed by Teknium
parent efc32ab639
commit 563077a47a

38
cli.py
View file

@ -6614,7 +6614,7 @@ class HermesCLI:
/model <name> --provider <provider> switch provider + model /model <name> --provider <provider> switch provider + model
/model --provider <provider> switch to provider, auto-detect model /model --provider <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 from hermes_cli.providers import get_label
# Parse args from the original command # Parse args from the original command
@ -6624,16 +6624,25 @@ class HermesCLI:
# Parse --provider and --global flags # Parse --provider and --global flags
model_input, explicit_provider, persist_global = parse_model_flags(raw_args) model_input, explicit_provider, persist_global = parse_model_flags(raw_args)
# Load providers for switch_model (picker path needs them below) # Single inventory context — replaces the inline config-slice the
user_provs = None # dashboard / TUI used to duplicate. Overlay live session state
custom_provs = None # 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: try:
from hermes_cli.config import get_compatible_custom_providers, load_config ctx = load_picker_context().with_overrides(
cfg = load_config() current_provider=self.provider or "",
user_provs = cfg.get("providers") current_model=self.model or "",
custom_provs = get_compatible_custom_providers(cfg) current_base_url=self.base_url or "",
)
except Exception: 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 # No args at all: open prompt_toolkit-native picker modal
if not model_input and not explicit_provider: 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" provider_display = get_label(self.provider) if self.provider else "unknown"
try: try:
providers = list_authenticated_providers( if ctx is None:
current_provider=self.provider or "", raise RuntimeError("inventory context unavailable")
current_base_url=self.base_url or "", providers = build_models_payload(ctx, max_models=50)["providers"]
current_model=self.model or "",
user_providers=user_provs,
custom_providers=custom_provs,
max_models=50,
)
except Exception: except Exception:
providers = [] providers = []