fix(tui-gateway): log when a client model override beats the profile default at session.create
The desktop composer's manual model pick rides into session.create as a per-session override and silently wins over model.default for every new chat. Name the override and the profile default in agent.log so the choice is diagnosable from logs alone (#107410).
This commit is contained in:
@@ -4,6 +4,8 @@ Before the gate the session was minted and the FIRST turn died with the provider
|
||||
chat. Custom / unknown providers and same-family or unlisted names stay permissive.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@@ -55,3 +57,21 @@ def test_session_create_keeps_coherent_unlisted_and_custom_pairs(_create, params
|
||||
assert "error" not in response, response
|
||||
session = sessions[response["result"]["session_id"]]
|
||||
assert session["model_override"] == {"model": params["model"], "provider": params["provider"]}
|
||||
|
||||
|
||||
def test_session_create_logs_when_a_client_override_beats_the_profile_default(_create, caplog, monkeypatch):
|
||||
"""A composer pick silently decided every new chat's model; agent.log must name it (#107410)."""
|
||||
from tui_gateway import server
|
||||
|
||||
monkeypatch.setattr(server, "_session_default_model", lambda session: "deepseek-v4-flash")
|
||||
with caplog.at_level(logging.INFO):
|
||||
response, _ = _create({"model": "gpt-5.5", "provider": "openrouter"})
|
||||
pinned = [r.getMessage() for r in caplog.records if "client override" in r.getMessage()]
|
||||
caplog.clear()
|
||||
_create({})
|
||||
unpinned = [r.getMessage() for r in caplog.records if "client override" in r.getMessage()]
|
||||
|
||||
assert len(pinned) == 1
|
||||
assert response["result"]["stored_session_id"] in pinned[0]
|
||||
assert "gpt-5.5" in pinned[0] and "openrouter" in pinned[0] and "deepseek-v4-flash" in pinned[0]
|
||||
assert unpinned == []
|
||||
|
||||
@@ -402,6 +402,12 @@ def _create_session(rid, params: dict, *, copy_parent_history: bool = False) ->
|
||||
"transport": current_transport() or _stdio_transport,
|
||||
"auth_user_id": _transport_auth_user_id(current_transport())}
|
||||
_register_session_cwd(_sessions[sid])
|
||||
if session_model_override:
|
||||
# A composer pick rides in as this override and beats model.default for the whole session;
|
||||
# name both so agent.log alone explains which model a new chat runs, and why (#107410).
|
||||
logger.info("session.create %s: model=%s provider=%s source=client override (profile default: %s)",
|
||||
key, session_model_override["model"], session_model_override.get("provider") or "-",
|
||||
_session_default_model(_sessions[sid]))
|
||||
# No DB row here (drafts left "Untitled" litter): created on the first prompt — except seeded sessions.
|
||||
# NOTE: we intentionally do NOT persist a DB row here. Every TUI/desktop launch (and every "New agent" /
|
||||
# draft) opens a session here just to paint the composer, so eagerly creating a row left an "Untitled"
|
||||
|
||||
Reference in New Issue
Block a user