feat: notify when a chat needs input (desktop + web) - #14
Merged
Conversation
…ification surface Adds the `notifyOnNeedsInput` client setting (default on, opt-out) to `ClientSettingsSchema` and `ClientSettingsPatch`, plus the renderer-facing `DesktopNotificationRequest` / `DesktopNotificationActivation` types and the optional `showNotification` / `onNotificationActivated` members on `DesktopBridge`. Both bridge members are optional like `preview` so a newer web bundle can run inside an older desktop shell and feature-detect. The desktop `ClientSettings` test fixture gains the new required field so the repo still typechecks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tion Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…avigate Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…top coalescing, draft-route suppression Guard `new Notification(...)` against Android Chrome's illegal-constructor throw, coalesce desktop notifications by request id, resolve the active thread through the draft route, hide the denied hint while the toggle is off, and pin the shim's platform routing with tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced Jul 27, 2026
radroid
added a commit
that referenced
this pull request
Jul 27, 2026
… push) Closes the accepted v1 gap from #14: notifications previously only fired while a T3 tab was open. This delivers a push when the tab is fully closed. Client (apps/web): - PWA manifest + icons + installability (required for iOS Safari Web Push). - Push-only service worker (no fetch handler, so no offline/stale-asset risk): shows a notification on push, focuses/opens the waiting thread on click, and suppresses when any T3 tab is open so the in-page NotificationCoordinator stays the single source while a tab is alive. - PushSubscriptionManager keeps the subscription in sync with the existing notifyOnNeedsInput setting + permission (reacts to a post-mount grant via the Permissions API). Pure, tested VAPID/subscription helpers. Server (apps/server/src/t3x/webPush — fork-seam clean, no upstream edits): - Reactor taps OrchestrationEngine.streamDomainEvents, recomputes the awareness phase with the shared projectThreadAwareness, edge-detects the same transitions the web client does (waiting_for_input/approval; running-> completed), and sends Web Push to registered subscriptions, pruning expired (404/410) ones. - JSON subscription store in the state dir; VAPID keypair via ServerSecretStore (T3X_VAPID_* env override supported); raw /api/t3x/push/{subscribe,unsubscribe,vapid-public-key} routes mounted through the existing T3xRoutesLive seam. Verified: apps/web + apps/server typecheck clean (0 errors); web + server unit tests pass; web-push loads at runtime; server+bin construction tests (277) pass. Browser end-to-end (grant permission, close tab, receive push) is manual QA. Closes #19 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
radroid
added a commit
that referenced
this pull request
Jul 28, 2026
… push) Closes the accepted v1 gap from #14: notifications previously only fired while a T3 tab was open. This delivers a push when the tab is fully closed. Client (apps/web): - PWA manifest + icons + installability (required for iOS Safari Web Push). - Push-only service worker (no fetch handler, so no offline/stale-asset risk): shows a notification on push, focuses/opens the waiting thread on click, and suppresses when any T3 tab is open so the in-page NotificationCoordinator stays the single source while a tab is alive. - PushSubscriptionManager keeps the subscription in sync with the existing notifyOnNeedsInput setting + permission (reacts to a post-mount grant via the Permissions API). Pure, tested VAPID/subscription helpers. Server (apps/server/src/t3x/webPush — fork-seam clean, no upstream edits): - Reactor taps OrchestrationEngine.streamDomainEvents, recomputes the awareness phase with the shared projectThreadAwareness, edge-detects the same transitions the web client does (waiting_for_input/approval; running-> completed), and sends Web Push to registered subscriptions, pruning expired (404/410) ones. - JSON subscription store in the state dir; VAPID keypair via ServerSecretStore (T3X_VAPID_* env override supported); raw /api/t3x/push/{subscribe,unsubscribe,vapid-public-key} routes mounted through the existing T3xRoutesLive seam. Verified: apps/web + apps/server typecheck clean (0 errors); web + server unit tests pass; web-push loads at runtime; server+bin construction tests (277) pass. Browser end-to-end (grant permission, close tab, receive push) is manual QA. Closes #19 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.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.
Closes #11
What
Fires a notification when a chat transitions into a state that needs you — approval requested, agent question (waiting for input), or turn finished — on both surfaces:
How
projectThreadAwareness()phase ladder (@t3tools/shared/agentAwareness) — the same source of truth the mobile push pipeline uses. A pure edge-detecting tracker (apps/web/src/notifications/needsAttention.logic.ts) diffs phases acrossthread-upsertedshell updates: fires on transitions intowaiting_for_approval/waiting_for_input, and onrunning → completedonly (which also kills the spurious "Done" at thread birth). First observation of a thread never fires, so reloading with an already-waiting thread stays silent.<NotificationCoordinator/>in the root route watches all threads across all connected environments and dispatches through a platform shim —desktopBridge.showNotification(...)when present, elsenew Notification(...)(guarded: Android Chrome's page-scope constructor throw is swallowed).desktop:show-notification/desktop:notification-activatedchannels, anElectronNotificationEffect service (coalesces per-thread via the request id, retains live references), preload bridge members typed in@t3tools/contracts(optional, so older shells hosting newer bundles degrade to the web path).notifyOnNeedsInputclient setting (default on), row in Settings → General ("Notify when an agent needs input"). On web, enabling requests browser permission from the toggle gesture; a denied permission shows an inline hint; a once-per-session toast nudges permission when a notification would have fired but permission was never asked.Out of scope (per issue): Web Push for closed tabs (needs service worker + push infra; iOS Safari additionally requires an installed PWA).
Testing
--home-dirinstance): turn-completion and agent-question notifications fire exactly once with correct title/body/tag while the tab is genuinely blurred; startup grace on reload; suppression when viewing the firing chat (and the converse — other-route transitions do notify); settings toggle gates and persists; notification click navigates to the right thread. Re-smoked after the final fix wave.pnpm build:desktop+pnpm test:desktop-smokepass. (Native notification click path is unit-tested via fakes; not OS-driven e2e.)Review process
Built task-by-task with per-task spec+quality reviews, a final whole-branch review, and a verified fix wave (notably: Android Chrome constructor guard, desktop Notification Center coalescing, draft-route suppression). Known accepted edges: notifications for since-deleted threads navigate to a dead route; a macOS click with zero open windows doesn't recreate one; permission state in the settings panel refreshes on interaction, not on browser-chrome changes.
🤖 Generated with Claude Code