fix(bot-mode): backfill follow-profile contract for legacy canonical Bot Chats

Bot Chats created before the follow_profile_config marker existed carry no
contract in model_config, so they would stay pinned to a stale stored
provider until deleted — the exact shape of the live reports (#89497,
#94818). Mirror the plugin's own identity rule (the profile's session
titled exactly 'Bot Chat') as a legacy fallback in
_stored_session_runtime_overrides, matching the room-plumbing legacy
'Group:' title fallback.

Follow-up to the salvaged #90343 (@curator8888) and #96111 (@lorzl).
This commit is contained in:
Teknium
2026-08-28 01:37:13 -07:00
parent 84e17db0bd
commit af53d02920
3 changed files with 48 additions and 0 deletions
@@ -0,0 +1 @@
curator8888
@@ -621,6 +621,43 @@ class TestFollowProfileConfigRuntimeOverrides:
assert overrides["model_override"]["model"] == "openai/gpt-5.6-luna-pro"
assert overrides["model_override"]["provider"] == "nous"
def test_legacy_bot_chat_title_backfills_contract(self):
"""Canonical Bot Chats created BEFORE the marker existed carry no
follow_profile_config, but they are still the plugin-owned forever-DM
(identified by the exact title "Bot Chat"). They must also rebuild
from the profile's CURRENT config — the live-report shape where every
pre-existing Bot Chat stayed pinned to a deleted provider."""
from tui_gateway.server import _stored_session_runtime_overrides
for hidden in (0, 1):
row = {
"title": "Bot Chat",
"hidden": hidden,
"model": "openai/gpt-5.6-luna-pro",
"billing_provider": "nous",
"model_config": json.dumps(
{"model": "openai/gpt-5.6-luna-pro", "provider": "nous"}
),
}
assert _stored_session_runtime_overrides(row) == {}
def test_bot_chat_prefix_title_is_not_backfilled(self):
"""Only the EXACT canonical title matches the legacy backfill — a
user chat that merely mentions bots keeps its stored runtime."""
from tui_gateway.server import _stored_session_runtime_overrides
row = {
"title": "Bot Chat ideas for my app",
"hidden": 0,
"model": "glm-5.1",
"billing_provider": "ollama-cloud",
"model_config": json.dumps(
{"model": "glm-5.1", "provider": "ollama-cloud"}
),
}
overrides = _stored_session_runtime_overrides(row)
assert overrides["model_override"]["model"] == "glm-5.1"
def test_ensure_db_row_persists_contract_marker(self, monkeypatch):
"""_ensure_session_db_row stamps follow_profile_config into the row's
model_config when the session carries the contract."""
+10
View File
@@ -5318,6 +5318,16 @@ def _stored_session_runtime_overrides(row: dict | None) -> dict:
_follow_marker = None
if _follow_marker:
return {}
# Legacy backfill: canonical Bot Chats created BEFORE the
# follow_profile_config contract existed carry no marker, yet they are
# still the plugin-owned forever-DM. The plugin's own identity rule is
# "the profile's session titled exactly 'Bot Chat'" (UNIQUE(title) makes
# that an exact registry, and pre-policy rows may be visible OR hidden),
# so mirror that rule here. Without this, every Bot Chat that already
# exists in the field stays pinned to its stale stored provider until
# the user deletes it — the exact live-report shape (#89497 / #94818).
if _row_title == "Bot Chat":
return {}
raw_config = row.get("model_config")
model_config: dict = {}