fix(desktop): dedupe Nostr session deep link imports - #9918
Conversation
Signed-off-by: harrykamboj1 <singhharnoor116@gmail.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3f0e62bc81
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (!pendingDeepLinks.has(targetWindow.id)) { | ||
| pendingDeepLinks.set(targetWindow.id, url); | ||
| } |
There was a problem hiding this comment.
Avoid dropping newer pending deep links
When the target window is still loading, this has guard keeps the first pending URL and silently ignores every later extension/session deep link for the same window, even when the URL is different. During startup or a renderer reload, opening an extension link and then a Nostr/session link before react-ready means only the stale first URL is delivered at react-ready; the newer user action is lost. The dedupe should only collapse identical URLs or queue/replace distinct pending links.
Useful? React with 👍 / 👎.
|
Thanks for the fix and the detailed issue (#9917) — nice to see a small, well-scoped change with repro and before/after screenshots. A couple of things before this can land:
I'll snooze this for a few days to give you a chance to respond. |
Signed-off-by: harrykamboj1 <singhharnoor116@gmail.com>
|
Hi @DOsinga
Let me know if you'd like anything else adjusted. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0a5ec09466
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| } | ||
|
|
||
| const DEEPLINK_BURST_DEDUP_MS = 2000; | ||
| let lastSentSessionDeepLink: { url: string; at: number } | null = null; |
There was a problem hiding this comment.
Track all recent session links during burst dedup
With two different session/Nostr links opened during the same 2s macOS duplicate burst, this single-slot cache only suppresses adjacent duplicates. For an event order A, B, A, sending B overwrites A's timestamp, so the later duplicate A is sent to the renderer again and can still create a duplicate Nostr import. Keep recent send times keyed by URL until the burst window expires instead of storing only the last URL.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 99fa652b3e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| window.webContents.send('add-extension', deepLinkUrl); | ||
| } else if (parsedUrl.hostname === 'sessions') { | ||
| window.webContents.send('open-shared-session', deepLinkUrl); | ||
| sendOpenSharedSession(window, deepLinkUrl, { skipBurstDedup: true }); |
There was a problem hiding this comment.
Deduplicate pending session links before replaying
When macOS delivers duplicate open-url events during cold start before any BrowserWindow is constructed, each handler can enter the no-window path, await createChat, and queue the same Nostr URL for a different loading window. Replaying those pending links with skipBurstDedup bypasses the new burst guard, so each window still sends open-shared-session and imports the same deep link. Let pending session replays use the burst dedup, or otherwise suppress duplicate pending URLs across windows.
Useful? React with 👍 / 👎.
Signed-off-by: harrykamboj1 <singhharnoor116@gmail.com>
|
Thanks for iterating on this so quickly! There's one open codex comment left — the cold-start race where the |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 626adde010
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| log.info('[Main] Ignoring burst duplicate session deep link'); | ||
| return; | ||
| } | ||
| recordSessionDeepLinkSend(url); |
There was a problem hiding this comment.
Defer session-link dedup until renderer readiness
When a goose://sessions/... URL arrives just after a window's main frame stops loading but before React has installed the open-shared-session listener, this records the URL even though the IPC sent on the next line can be missed. The macOS duplicate delivered once the renderer is ready is then treated as a burst duplicate and dropped, so the user gets no import; queue until react-ready or an acknowledgement before recording the URL as sent.
Useful? React with 👍 / 👎.
…nderer readiness Signed-off-by: harrykamboj1 <singhharnoor116@gmail.com>
|
Thanks @DOsinga — pushed an update addressing the remaining items: Cold-start replay race (the open Codex comment): removed skipBurstDedup: true from the react-ready pending-link replay, so cold-start windows now send open-shared-session through the same burst dedup as every other path. Combined with the URL-keyed recentSessionDeepLinkSends map, two windows opened for the same link in one burst no longer double-import. Defer dedup until renderer readiness (latest Codex P2): added a reactReadyWindows set. Extension/session deep links are now queued until the window emits react-ready, so we never record a URL as "sent" before the open-shared-session listener exists — the macOS duplicate that arrives once the renderer is ready is no longer mistaken for a burst duplicate and dropped. Removed the now-unused skipBurstDedup option from sendOpenSharedSession since nothing sets it anymore. |
DOsinga
left a comment
There was a problem hiding this comment.
Thanks for the careful iteration here — you addressed all the codex feedback and the simplification requests cleanly. The two-layer dedup (burst dedup in main.ts keyed by URL, plus the in-flight guard in App.tsx) and gating delivery on reactReadyWindows is the right approach. Nice first contribution!
* main: (26 commits) Fix MCP app sandbox bridge lifecycle (#10064) fix(bedrock): send inference config (max_tokens, temperature) on Converse (#9889) feat(providers): support OpenRouter request parameters (#9276) Migrate local inference model management to ACP (#10124) (attempt to) fix disk space errors in linux release builds (#10024) feat: add --edit session flag to edit conversation before forking (#9799) feat: add iFlytek Spark and Astron MaaS providers (#9837) fix(desktop): dedupe Nostr session deep link imports (#9918) [codex] Add SessionStart hook parity outside CLI (#9970) feat(providers): add Fireworks AI declarative provider (#9990) fix(providers): don't retry deterministically-permanent 400s (thinking-block immutability) (#10005) fix(deps): downgrade pkcs8 to v0.10 to match sec1/pkcs1 v0.7 (#10119) chore(deps): bump actions/cache from 5.0.2 to 6.0.0 (#10051) Make OpenAI Responses API store param configurable (#10040) remove unsupported model (#10121) chore(release): bump version to 1.40.0 (minor) (#10099) move ollama provider into goose-providers (#9986) UI acp migratoin: Decouple desktop UI types from generated OpenAPI types (#10109) fix(otel): use async reqwest client so OTLP export works in `goose serve` mode (#10100) feat (acp): exposed available tools in acp schema (#10097) ...
* main: (42 commits) Fix MCP app sandbox bridge lifecycle (#10064) fix(bedrock): send inference config (max_tokens, temperature) on Converse (#9889) feat(providers): support OpenRouter request parameters (#9276) Migrate local inference model management to ACP (#10124) (attempt to) fix disk space errors in linux release builds (#10024) feat: add --edit session flag to edit conversation before forking (#9799) feat: add iFlytek Spark and Astron MaaS providers (#9837) fix(desktop): dedupe Nostr session deep link imports (#9918) [codex] Add SessionStart hook parity outside CLI (#9970) feat(providers): add Fireworks AI declarative provider (#9990) fix(providers): don't retry deterministically-permanent 400s (thinking-block immutability) (#10005) fix(deps): downgrade pkcs8 to v0.10 to match sec1/pkcs1 v0.7 (#10119) chore(deps): bump actions/cache from 5.0.2 to 6.0.0 (#10051) Make OpenAI Responses API store param configurable (#10040) remove unsupported model (#10121) chore(release): bump version to 1.40.0 (minor) (#10099) move ollama provider into goose-providers (#9986) UI acp migratoin: Decouple desktop UI types from generated OpenAPI types (#10109) fix(otel): use async reqwest client so OTLP export works in `goose serve` mode (#10100) feat (acp): exposed available tools in acp schema (#10097) ...
* main: (31 commits) test: generic validator for declarative providers (#10010) UI acp migratoin: Decouple desktop UI types from generated OpenAPI types (Part 2) (#10149) Remove MCP sampling support (#10087) Support TLS for ACP serve (#10088) feat (ui): Migrate dictation local model manager to ACP (#10131) Fix MCP app sandbox bridge lifecycle (#10064) fix(bedrock): send inference config (max_tokens, temperature) on Converse (#9889) feat(providers): support OpenRouter request parameters (#9276) Migrate local inference model management to ACP (#10124) (attempt to) fix disk space errors in linux release builds (#10024) feat: add --edit session flag to edit conversation before forking (#9799) feat: add iFlytek Spark and Astron MaaS providers (#9837) fix(desktop): dedupe Nostr session deep link imports (#9918) [codex] Add SessionStart hook parity outside CLI (#9970) feat(providers): add Fireworks AI declarative provider (#9990) fix(providers): don't retry deterministically-permanent 400s (thinking-block immutability) (#10005) fix(deps): downgrade pkcs8 to v0.10 to match sec1/pkcs1 v0.7 (#10119) chore(deps): bump actions/cache from 5.0.2 to 6.0.0 (#10051) Make OpenAI Responses API store param configurable (#10040) remove unsupported model (#10121) ...
Summary
Fix duplicate Nostr session imports from
goose://sessions/nostrdeep links.macOS could deliver multiple
open-urlevents for one Chrome paste, triggeringseveral
POST /sessions/import/nostrcalls.Changes:
main.ts: queue links while window loading, 2s burst dedup, align macOS with Windows behaviorApp.tsx: in-flight + post-success dedup for Nostr deep link imports onlyTesting
Manual testing on macOS:
Related Issues
Fixes #9917
Screenshots
Before: multiple identical sessions in Chat History from one link

After: single session imported
