From 2fe78d1ae31c2ae18edf1b97b7d0a1c9e77e9187 Mon Sep 17 00:00:00 2001 From: Evo Date: Sat, 20 Jun 2026 01:09:46 +0800 Subject: [PATCH] fix(gateway): persist inline-keyboard model-picker selections by default #49066 made /model text and the CLI picker persist to config.yaml by default, but the gateway (Telegram/Discord/Matrix) inline-keyboard picker callback stayed session-only. Mirror the text path's persist block so a tapped model survives across launches like a typed one. --- gateway/slash_commands.py | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/gateway/slash_commands.py b/gateway/slash_commands.py index b2810096b20..afb5737151b 100644 --- a/gateway/slash_commands.py +++ b/gateway/slash_commands.py @@ -1152,7 +1152,7 @@ class GatewaySlashCommandsMixin: current_model=_cur_model, current_base_url=_cur_base_url, current_api_key=_cur_api_key, - is_global=False, + is_global=persist_global, explicit_provider=provider_slug, user_providers=user_provs, custom_providers=custom_provs, @@ -1216,6 +1216,34 @@ class GatewaySlashCommandsMixin: # stale cache signature to trigger a rebuild. _self._evict_cached_agent(_session_key) + # Persist to config (default) unless --session opted out, + # mirroring the text /model command path above so a picked + # model survives across sessions like a typed one (#49066). + if persist_global: + try: + if config_path.exists(): + with open(config_path, encoding="utf-8") as f: + _persist_cfg = yaml.safe_load(f) or {} + else: + _persist_cfg = {} + _raw_model = _persist_cfg.get("model") + if isinstance(_raw_model, dict): + _persist_model_cfg = _raw_model + elif isinstance(_raw_model, str) and _raw_model.strip(): + _persist_model_cfg = {"default": _raw_model.strip()} + _persist_cfg["model"] = _persist_model_cfg + else: + _persist_model_cfg = {} + _persist_cfg["model"] = _persist_model_cfg + _persist_model_cfg["default"] = result.new_model + _persist_model_cfg["provider"] = result.target_provider + if result.base_url: + _persist_model_cfg["base_url"] = result.base_url + from hermes_cli.config import save_config + save_config(_persist_cfg) + except Exception as e: + logger.warning("Failed to persist model switch: %s", e) + # Build confirmation text plabel = result.provider_label or result.target_provider lines = [t("gateway.model.switched", model=result.new_model)] @@ -1249,7 +1277,10 @@ class GatewaySlashCommandsMixin: if mi.has_cost_data(): lines.append(t("gateway.model.cost_label", cost=mi.format_cost())) lines.append(t("gateway.model.capabilities_label", capabilities=mi.format_capabilities())) - lines.append(t("gateway.model.session_only_hint")) + if persist_global: + lines.append(t("gateway.model.saved_global")) + else: + lines.append(t("gateway.model.session_only_hint")) return "\n".join(lines) metadata = self._thread_metadata_for_source(source, self._reply_anchor_for_event(event))