Conversation
With two windows open against the same daemon, every window posts its own banner for the same event. A click always focuses the window that sent the banner. It does not focus the window that shows the target agent. A workspace from one window's project could then appear in another window's Working list. The fix gives the main process a view of each window. Each window reports its visible agent ids. While the sidebar is active, it also reports the sidebar's workspace keys. A new lookup in AgentNavigationInbox ranks windows for a target: first by visible agent, then by the window's own URL, then by sidebar key. The window's URL already tracks in-app navigation, so this needs no extra report. The most recently focused window wins a tie. The notification click handler and openOrFocusAgent, which handles deep links, both use this lookup and fall back to today's focused-window order when no window matches. Duplicate banners and the shared sidebar-view storage key are separate, known issues. They stay out of scope here.
cleiter
force-pushed
the
route-notification-click-to-right-window
branch
from
September 2, 2026 12:48
6c49b63 to
613f178
Compare
Contributor
|
| Filename | Overview |
|---|---|
| packages/desktop/src/agent-navigation.ts | Adds per-window reports, focus ordering, lifecycle cleanup, and tiered target-window ranking. |
| packages/desktop/src/main.ts | Validates renderer view reports and integrates ranked window selection into notifications and deep links. |
| packages/desktop/src/features/notifications.ts | Routes notification clicks through the ranked candidate source while preserving sender fallback. |
| packages/app/src/desktop/use-report-window-view.ts | Combines renderer view state into deterministic reports and suppresses unchanged IPC updates. |
| packages/app/src/stores/desktop-window-view-store.ts | Introduces non-persisted per-window state for visible agents and sidebar workspaces. |
| packages/desktop/src/window/workspace-route-url.ts | Parses packaged and development workspace URLs for current-route ownership matching. |
Sequence Diagram
sequenceDiagram
participant Renderer as Renderer window
participant Main as Electron main
participant Inbox as Navigation inbox
participant OS as OS notification/deep link
Renderer->>Main: reportView(visible agents, workspace keys)
Main->>Inbox: setWindowView(windowId, report)
OS->>Main: notification click or deep link
Main->>Inbox: windowsShowingTarget(target, window URLs)
Inbox-->>Main: ranked matching windows
Main->>Renderer: focus selected window and deliver target
Note over Main,Renderer: If no window matches, retain focused/sending-window fallback
Reviews (1): Last reviewed commit: "fix(desktop): route notification clicks ..." | Re-trigger Greptile
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.
Type of change
Reasoning
With two desktop windows open against the same daemon, filtering the sidebar to different projects in each, a notification click could pull a workspace from the wrong window's project into view. Every connected window posts its own OS notification banner for the same daemon event, and a click always focused the window that sent the banner, not the window that actually showed the target agent. Whichever duplicate banner you happened to click decided where the app jumped.
Goals
paseo://deep links use the same window lookup as notification clicks, so both entry points pick the same window.Non-goals
QA
Tests:
packages/desktop/src/window/workspace-route-url.test.ts(new) - parses packaged and dev-server workspace route URLs, decodes percent-encoded ids, and rejects non-workspace or malformed URLs.packages/desktop/src/agent-navigation.test.ts(extended) - the tieredwindowsShowingTargetranking (visible agent, URL, sidebar key), the most-recently-focused tie-break, no match, and thatwindowLoading/removeWindowclear a window's recorded view.packages/desktop/src/features/notification-click.test.ts(new) - route resolution from notification data, and the fallback to the sending window when no candidate matches.packages/desktop/src/window/desktop-window-owner.test.ts(extended) -preferredWindowwins over the default focus order, and the existing fallback still applies when it returns null.packages/app/src/desktop/window-view-report.test.ts(new) - the report payload's sort and dedupe, and that an inactive sidebar reports no workspace keys.Ran two desktop windows against the same daemon for several days of normal work, each filtered to a different project. Before this change, clicking a notification could bring an agent from one window's project into the other window's Working list. After this change, notification clicks landed in the correct window throughout normal daily use. Did not separately exercise the deep-link path or the close-window fallback path by hand; those are covered by the unit tests above.
The additions to
workspace-screen.tsxandsidebar-model.tsxare additive effects that publish derived view state to a new store. They do not change existing render or filtering logic.Desktop-only change (Electron). Not applicable: iOS, Android, web browser.
Checklist
npm run typecheckpassesnpm run lintpassesnpm run formatpasses