fix(tui): prevent ws_orphan_reap from ending gateway-originated sessions

Guard _finalize_session's db.end_session() call against gateway-owned
sessions (telegram, bluebubbles, discord, etc.).  The TUI is a viewer
for these sessions, not the lifecycle owner.  Unconditionally ending
them in state.db creates a Groundhog Day routing loop: the gateway's
#54878 self-heal detects the stale entry, recovers to the parent
session, context compression splits back to the reaped child, and the
cycle repeats on every inbound message — causing complete conversational
context amnesia.

Fixes #60609
This commit is contained in:
AIalliAI 2026-07-08 01:47:26 +00:00 committed by Teknium
parent ecc6725855
commit f5ef7ee9da

View file

@ -586,7 +586,23 @@ def _finalize_session(session: dict | None, end_reason: str = "tui_close") -> No
try:
db = _get_db()
if db is not None:
db.end_session(session_id, end_reason)
# Don't end gateway-originated sessions — the gateway owns their
# lifecycle. The TUI is a viewer, not the owner. Ending a
# gateway session in state.db triggers a Groundhog Day routing
# loop: the gateway's #54878 self-heal detects the stale entry,
# recovers to the parent session, context compression splits
# back to the reaped child, and the cycle repeats on every
# inbound message. (#60609)
_GATEWAY_SOURCES = frozenset({
"bluebubbles", "telegram", "discord", "signal",
"whatsapp", "sms", "slack", "mattermost",
"matrix", "line", "wechat", "facebook",
"imessage", "googlechat",
})
row = db.get_session(session_id)
source = (row or {}).get("source", "")
if source not in _GATEWAY_SOURCES:
db.end_session(session_id, end_reason)
except Exception:
pass