From 78998572019b22c793bca880c967fda3e02f932e Mon Sep 17 00:00:00 2001 From: Ilya Gusev Date: Sun, 21 Jun 2026 16:41:40 +0000 Subject: [PATCH] refactor(cli): simplify onboard search-provider dispatch - Extract _set_field_from_choices for the shared pick-and-set tail used by both the LLM and search provider handlers. - Replace the single-entry _TYPED_FIELD_HANDLERS registry with a direct isinstance check in _resolve_field_handler (robust to renames, no class-name strings). - Drop a redundant str() in the search default computation. Co-Authored-By: Claude Opus 4.8 (1M context) --- nanobot/cli/onboard.py | 44 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/nanobot/cli/onboard.py b/nanobot/cli/onboard.py index cc21c4e5..a4a6d1e1 100644 --- a/nanobot/cli/onboard.py +++ b/nanobot/cli/onboard.py @@ -762,13 +762,11 @@ def _handle_model_preset_field( setattr(working_model, field_name, new_value) -def _handle_provider_field( - working_model: BaseModel, field_name: str, field_display: str, current_value: Any +def _set_field_from_choices( + working_model: BaseModel, field_name: str, field_display: str, + choices: list[str], default_choice: str ) -> None: - """Handle the 'provider' field with a list of registered providers.""" - provider_names = sorted(_get_provider_names().keys()) - choices = ["auto"] + provider_names - default_choice = str(current_value) if current_value else "auto" + """Prompt to pick one of ``choices`` and set the field (no-op on back/cancel).""" new_value = _select_with_back(field_display, choices, default=default_choice) if new_value is _BACK_PRESSED: return @@ -776,6 +774,15 @@ def _handle_provider_field( setattr(working_model, field_name, new_value) +def _handle_provider_field( + working_model: BaseModel, field_name: str, field_display: str, current_value: Any +) -> None: + """Handle the 'provider' field with a list of registered LLM providers.""" + choices = ["auto"] + sorted(_get_provider_names().keys()) + default_choice = str(current_value) if current_value else "auto" + _set_field_from_choices(working_model, field_name, field_display, choices, default_choice) + + def _handle_fallback_models_field( working_model: BaseModel, field_name: str, field_display: str, current_value: Any ) -> None: @@ -843,12 +850,8 @@ def _handle_search_provider_field( from nanobot.agent.tools.web import SEARCH_PROVIDER_OPTIONS choices = [opt["name"] for opt in SEARCH_PROVIDER_OPTIONS] - default_choice = str(current_value) if current_value in choices else choices[0] - new_value = _select_with_back(field_display, choices, default=default_choice) - if new_value is _BACK_PRESSED: - return - if new_value is not None: - setattr(working_model, field_name, new_value) + default_choice = current_value if current_value in choices else choices[0] + _set_field_from_choices(working_model, field_name, field_display, choices, default_choice) _FIELD_HANDLERS: dict[str, Any] = { @@ -859,18 +862,15 @@ _FIELD_HANDLERS: dict[str, Any] = { "fallback_models": _handle_fallback_models_field, } -# Handlers keyed by (model class name, field name); take precedence over the -# name-only handlers above. Needed because the bare "provider" field name is -# shared by LLM configs (LLM provider list) and WebSearchConfig (search engines). -_TYPED_FIELD_HANDLERS: dict[tuple[str, str], Any] = { - ("WebSearchConfig", "provider"): _handle_search_provider_field, -} - def _resolve_field_handler(model: BaseModel, field_name: str) -> Any: - """Resolve a field handler, preferring model-type-specific handlers.""" - typed = _TYPED_FIELD_HANDLERS.get((type(model).__name__, field_name)) - return typed or _FIELD_HANDLERS.get(field_name) + """Resolve the handler for a field. WebSearchConfig shares the bare "provider" + name with LLM configs but needs the search-engine picker, not the LLM list.""" + if field_name == "provider": + from nanobot.agent.tools.web import WebSearchConfig + if isinstance(model, WebSearchConfig): + return _handle_search_provider_field + return _FIELD_HANDLERS.get(field_name) def _is_str_or_none(annotation: Any) -> bool: