fix(tui): persist dashboard/TUI conversations on WS disconnect/restart - #62052
Merged
teknium1 merged 2 commits intoJul 10, 2026
Merged
Conversation
…s chat finalize passed conversation_history=history aliasing the snapshot so flush skipped every message and wrote nothing. now flush _session_messages via marker dedup like gateway shutdown. add real db e2e tests.
WilsonKinyua
force-pushed
the
fix/dashboard-session-persistence
branch
from
July 10, 2026 12:09
6d1f04f to
78daac8
Compare
19 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Dashboard/TUI WebSocket conversations could contain many events yet be absent from
state.dbacross a disconnect/restart. On teardown,_finalize_sessionis the safety-net that flushes any un-persisted transcript, but it called:where
snapshot(agent._session_messages) andhistory(session["history"]) reference the same list once a turn completes. Inside_flush_messages_to_session_db, every message whose identity appears inconversation_historyis treated as already-durable and skipped — so the call wrote nothing. When_finalize_sessionwas the sole persist path (e.g. an in-turn flush hit a transient SQLite failure, then the WS disconnected/the gateway restarted), the whole conversation was lost.Fix
Flush
agent._session_messagesvia_persist_session's intrinsic_DB_PERSISTED_MARKERdedup — the same contract the gateway-shutdown flush already uses (#13121):conversation_history=history(it aliased the snapshot and neutered the write).or historyfallback (it wrote a markerless copy of already-durable resumed rows → duplicates).Markers persist the genuinely-unflushed tail while leaving durable rows untouched (including a resumed-but-not-run session's already-in-DB transcript), so no duplicates are appended.
Scope: reliability slice 1 only — no changes to cron, Telegram outbox, reconnect protocol, or monitoring. Stamping resumed history durable at load time is a noted follow-up (shared with the gateway path).
Test plan
New real-DB E2E tests in
tests/tui_gateway/test_finalize_session_persist.py(drive the actualAIAgentflush against a realSessionDB— the prior tests only mocked_persist_session, so they asserted the call but not the write):test_unflushed_turn_survives_disconnect— completed turn whose flush didn't durably land is persisted on disconnect (was 0 rows before the fix).test_resumed_session_not_reflushed_as_duplicates— resumed, no turn run → no duplicate rows.test_resumed_then_run_turn_not_duplicated— resumed and runs a turn: in-turn flush marker-stamps the loaded prefix, finalize re-appends nothing.Mock-based contract tests updated to the corrected call shape.
Ran locally:
pytest tests/tui_gateway/test_finalize_session_persist.py→ 14 passedtest_finalize_session_persist+test_13121_shutdown_inflight_transcript_flush+test_7100_transient_failure_transcript+test_42039_duplicate_user_message+test_hermes_state+test_empty_session_hygiene→ 386 passedInfographic