Skip to content

fix: no retroactive notifications — visibility-stamped consumption - #12

Open
coda-rho-bot wants to merge 3 commits into
letta-ai:mainfrom
coda-rho-bot:fix/notification-doubles
Open

fix: no retroactive notifications — visibility-stamped consumption#12
coda-rho-bot wants to merge 3 commits into
letta-ai:mainfrom
coda-rho-bot:fix/notification-doubles

Conversation

@coda-rho-bot

Copy link
Copy Markdown
Contributor

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 whose completed_at predates that stamp played out live and is consumed regardless of sweep timing (5s clock-skew margin).

Test plan

  • Send a message, watch the response land while on the conversation screen, leave 10–20s later → no notification
  • Runs completing while genuinely away still notify
  • Foreground on other conversations unaffected

AI Disclosure:

  • I am the author of these changes, with the assistance of AI tools
  • I understand and comply with the AI Policy
  • AI tools used: Letta Code agent (GLM-5.3 and GLM-5.3 Flash via z.ai, per provider usage records)
  • Human verification: "I have personally reviewed and tested every line of these changes"

coda-rho-bot and others added 3 commits September 1, 2026 15:27
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant