From f6daceb449c4c4db33559dfd3cc5b8332c0c50e0 Mon Sep 17 00:00:00 2001 From: teknium1 Date: Fri, 20 Feb 2026 17:35:12 -0800 Subject: [PATCH] feat: add interactive model selection and saving functionality - Implemented a new interactive model selection feature after user login, allowing users to choose from available models or enter a custom model name. - Added functionality to save the selected model to the configuration file and environment variables, ensuring persistence across sessions. - Enhanced user experience by providing both menu-based and fallback number-based selection methods for model choice. --- hermes_cli/auth.py | 80 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 3 deletions(-) diff --git a/hermes_cli/auth.py b/hermes_cli/auth.py index 122cfe225..3e06c46dc 100644 --- a/hermes_cli/auth.py +++ b/hermes_cli/auth.py @@ -851,6 +851,79 @@ def _reset_config_provider() -> Path: return config_path +def _prompt_model_selection(model_ids: List[str]) -> Optional[str]: + """Interactive model selection after login. Returns chosen model ID or None.""" + print(f"Available models ({len(model_ids)}):") + for i, mid in enumerate(model_ids, 1): + print(f" {i}. {mid}") + print(f" {len(model_ids) + 1}. Custom model name") + print(f" {len(model_ids) + 2}. Skip (keep current)") + print() + + # Try arrow-key menu first, fall back to number input + try: + from simple_term_menu import TerminalMenu + choices = [f" {mid}" for mid in model_ids] + choices.append(" Custom model name") + choices.append(" Skip (keep current)") + menu = TerminalMenu( + choices, + cursor_index=0, + menu_cursor="-> ", + menu_cursor_style=("fg_green", "bold"), + menu_highlight_style=("fg_green",), + cycle_cursor=True, + clear_screen=False, + title="Select default model:", + ) + idx = menu.show() + if idx is None: + return None + print() + if idx < len(model_ids): + return model_ids[idx] + elif idx == len(model_ids): + custom = input("Enter model name: ").strip() + return custom if custom else None + return None + except ImportError: + pass + + # Fallback: number-based selection + while True: + try: + choice = input(f"Select model [1-{len(model_ids) + 2}] (default: skip): ").strip() + if not choice: + return None + idx = int(choice) + if 1 <= idx <= len(model_ids): + return model_ids[idx - 1] + elif idx == len(model_ids) + 1: + custom = input("Enter model name: ").strip() + return custom if custom else None + elif idx == len(model_ids) + 2: + return None + print(f"Please enter a number between 1 and {len(model_ids) + 2}") + except ValueError: + print("Please enter a number") + except (KeyboardInterrupt, EOFError): + return None + + +def _save_model_choice(model_id: str) -> None: + """Save the selected model to config.yaml and .env.""" + from hermes_cli.config import save_config, load_config, save_env_value + + config = load_config() + # Handle both string and dict model formats + if isinstance(config.get("model"), dict): + config["model"]["default"] = model_id + else: + config["model"] = model_id + save_config(config) + save_env_value("LLM_MODEL", model_id) + + def login_command(args) -> None: """Run OAuth device code login for the selected provider.""" provider_id = getattr(args, "provider", None) or "nous" @@ -1008,9 +1081,10 @@ def _login_nous(args, pconfig: ProviderConfig) -> None: print() if model_ids: - print(f"Available models ({len(model_ids)}):") - for mid in model_ids: - print(f" - {mid}") + selected_model = _prompt_model_selection(model_ids) + if selected_model: + _save_model_choice(selected_model) + print(f"Default model set to: {selected_model}") else: print("No models were returned by the inference API.") except Exception as exc: