fix(app): refresh open session messages on resume/reconnect#1418
Open
chphch wants to merge 1 commit into
Open
Conversation
The SessionView effect that re-fetches an open session's messages depends on realtimeStatus, but realtimeStatus tracks the LiveKit voice session — not the data socket (that is the separate socketStatus / useSocketStatus). So when the app is backgrounded and resumed, or the socket simply drops and reconnects, the effect never re-runs and the open chat stays stale until a fresh SessionView mount. Messages an agent produced while the app was in the background never appear until you leave and re-enter the session. The onReconnected handler explicitly skipped refreshing messages, relying on that dead trigger. Refresh the currently-viewing session's messages on both AppState -> 'active' and socket onReconnected via onSessionVisible(currentViewingSessionId), which runs a bounded forward sync. Also covers a foreground network blip that reconnects with recovered=false. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
Contributor
Author
Proof — before / afterCaptured on a standalone
Without the fix (top): after reconnect A is stale — the message that arrived while A was away is missing; it only appears after leaving and re-entering the session. With the fix (bottom): the missed message renders automatically on reconnect, no remount. The only change between the two runs is |
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.

Messages an agent produces while the Happy app is backgrounded don't appear when you return to the app — the open chat stays stale until you leave and re-enter the session. The cause is a misdirected refresh trigger:
SessionView's effect that re-fetches an open session's messages depends onrealtimeStatus, butrealtimeStatustracks the LiveKit voice session (storage.tsuseRealtimeStatus, written only byRealtimeVoiceSession*/RealtimeSession) — not the data socket, whose status lives in the separatesocketStatus/useSocketStatus. So on app resume (or any socket reconnect), that effect never re-runs, andsync.ts'sonReconnectedhandler deliberately skipped refreshing the open session's messages, with a comment that relied on exactly this dead trigger (onSessionVisible"called by SessionView when realtimeStatus changes"). Re-entering the session works only because a fresh mount re-fetches. This fix refreshes the currently-viewing session's messages on bothAppState → 'active'and the socketonReconnectedpath viaonSessionVisible(currentViewingSessionId)(a bounded forward sync). It also covers a foreground network blip that reconnects withrecovered=false(server connection-state recovery off), which had the same gap.Proof
Verified end-to-end on a throwaway standalone
happy-server(PGlite) + Expo web + a pairedhappy-clidaemon, driven with Playwright. Two browser contexts on one account: context A opens a session then goes offline (simulating the app being backgrounded); context B (online) sends a marked message to that session; context A comes back online. The missed message now renders on A on reconnect without a remount (onSessionVisible→fetchForwardSince). Screenshots/GIF in the PR comment below — A shows "No messages yet" while offline, then the full conversation (including the message it missed) after reconnect.pnpm typecheckclean.