fix(tui_gateway): keep the session's /model pick across agent rebuild

_rebuild_session_agent built the replacement without the live
session model_override, then reset config_model_seen so the per-turn sync
never re-adopted it. Forward the pin unless the caller passes one; /new
still clears it before rebuilding.

Fixes #127449

(cherry picked from commit 484695a6ea813f46324d213740749c3d144ede4a)
This commit is contained in:
chelsealong
2026-09-29 06:22:11 +00:00
committed by Brooklyn Nicholson
parent a94b975831
commit bb9220ed7b
2 changed files with 26 additions and 0 deletions

View File

@@ -88,3 +88,25 @@ def test_rebuild_preparation_failure_keeps_reachable_owner(tmp_path, monkeypatch
for agent in built:
if agent._session_db is not db and agent._owns_session_db:
agent._session_db.close()
def test_rebuild_keeps_session_model_pick_but_new_clears_it(monkeypatch):
"""Regression for #127449: a rebuild is not a conversation boundary, /new is."""
from tui_gateway import server
pick = {"model": "pick-b", "provider": "openrouter"}
seen = []
def make_agent(*_args, **kwargs):
seen.append(kwargs.get("model_override"))
return SimpleNamespace(_session_db=None, _owns_session_db=False)
monkeypatch.setattr(server, "_make_agent", make_agent)
monkeypatch.setattr(server, "_config_model_target", lambda: "default-a")
session = {"agent": None, "session_key": "k", "model_override": dict(pick)}
server._rebuild_session_agent("sid", session, session_id="k")
assert seen == [pick]
assert session["model_override"] == pick
server._rebuild_session_agent("sid", session, model_override={"model": "explicit"})
assert seen[-1] == {"model": "explicit"}
session.pop("model_override")
server._rebuild_session_agent("sid", session)
assert seen[-1] is None

View File

@@ -545,6 +545,10 @@ def _rebuild_session_agent(sid: str, session: dict, **kwargs):
config_model_seen = _config_model_target()
if opened:
session_db = _open_profile_session_db(profile_home)
# A rebuild is not a conversation boundary (/new pops the pin before calling us): carry the
# session's /model pick, else config_model_seen below hides the reversion from the per-turn sync.
if "model_override" not in kwargs and isinstance(session.get("model_override"), dict):
kwargs["model_override"] = session["model_override"]
agent = _make_agent(sid, session["session_key"], session_db=session_db, **kwargs)
except BaseException:
if opened and session_db is not None: