fix: no retroactive notifications — visibility-stamped consumption - #12
Open
coda-rho-bot wants to merge 3 commits into
Open
fix: no retroactive notifications — visibility-stamped consumption#12coda-rho-bot wants to merge 3 commits into
coda-rho-bot wants to merge 3 commits into
Conversation
Adds a notification mode per conversation — All messages (every run completion, from any client), Mobile only (runs started from this app), Off — selected from a sheet off a composer chip, persisted in AsyncStorage, resolved against the app-wide default. Run completions post a system notification when the app is backgrounded, gated by the conversation's mode: ChatSession exposes onRunCompleted (fired for local result frames and external-run loop_status idle transitions) and the chat screen decides visibility + mode. Groundwork for background run-completion notifications; the always-on native poller that builds on this arrives separately. Co-authored-by: Letta Code <noreply@letta.com>
A foreground service polls /v1/runs on a 20s cadence and posts a notification when a watched conversation's turn ends — with the agent's final reply as the body, conversation-channel styling, and the profile picture as the large icon. Runs while the app is backgrounded or closed; JS timers never fire in backgrounded RN contexts, so the poller is native. Cost model: ONE unfiltered sweep per cycle regardless of watched-count (run objects carry conversation_id; the watched-set filter is client-side). The reply text chases the messages endpoint's write lag: a completed run with no visible reply defers up to 30s across sweeps before falling back to generic text. Suppression is per-conversation and foreground-only: the chat screen reports the visible conversation; leaving the screen or backgrounding the app re-enables notifications. The JS-side notification path defers to the poller for natively-watched conversations (no doubles). Stacked on the per-conversation notification settings PR (the poller's watched set comes from those modes). Verified on Android emulator and physical device across two weeks of daily use. Co-authored-by: Letta Code <noreply@letta.com>
A turn completing while the user watched the conversation was consumed only if a SWEEP ran while they were still there. With 20s sweep intervals, leaving the screen 10-20s after the response landed in the gap — the next sweep saw the run fresh + screen gone and notified retroactively. Fix: visibility transitions stamp when the user last left each conversation (reportVisibleConversation). A run whose completion predates that stamp played out live and is consumed regardless of sweep timing (5s clock-skew margin). Stacked on the background-notifications PR (touches its service). Co-authored-by: Letta Code <noreply@letta.com>
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.
Summary
Stacks on #11 (native poller) — review that first.
Fixes retroactive notifications: a turn completing while the user watched the conversation was consumed only if a sweep ran while they were still on the screen. With 20s sweep intervals, leaving the screen 10–20s after the response landed exactly in that gap — the next sweep saw the run as fresh (screen gone) and posted a notification for a turn the user had already watched play out live.
Fix: visibility transitions stamp when the user last left each conversation (
reportVisibleConversation). A run whosecompleted_atpredates that stamp played out live and is consumed regardless of sweep timing (5s clock-skew margin).Test plan
AI Disclosure: