Repository navigation
fix(desktop): reuse existing window for recipe deep links - #9289
SarthakB11 wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6e6743c2e0
ℹ️ 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 newSession = await createSession(getInitialWorkingDir(), { | ||
| recipeDeeplink, | ||
| allExtensions: extensionsList, |
There was a problem hiding this comment.
Pass the recipe config instead of the full URL
When a goose://recipe?... link is opened into an existing window, this passes the full URL to createSession, but createSession forwards recipeDeeplink directly to decodeRecipe, whose backend decoder expects only the base64 recipe config string (the cold-start path still passes deeplinkData?.config). As a result, any recipe/bot deep link handled through this new IPC path fails to decode instead of opening the recipe; extract and pass the config value here, or update the decode path to accept full Goose URLs.
Useful? React with 👍 / 👎.
|
I merged During conflict resolution, I also fixed a bug that Codex flagged: the IPC payload was sending the full The fix: Items for human reviewer to check:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 76ead475d9
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const newSession = await createSession(getInitialWorkingDir(), { | ||
| recipeDeeplink, | ||
| allExtensions: extensionsList, | ||
| }); |
There was a problem hiding this comment.
Forward deeplink recipe parameters into session creation
This handler receives recipeParameters/scheduledJobId in the IPC payload but only passes recipeDeeplink to createSession, so recipe links opened in an already-running window lose their query-parameter context. That regresses behavior compared with the new-window path (which injects recipeParameters via appConfig) and means parameterized recipe links open without prefilled values in the parameter modal.
Useful? React with 👍 / 👎.
|
can you look at the codex comments |
|
Thanks @DOsinga, your On the two Codex items: P2 — P1 — IPC race when Pushing both shortly. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: de72a03d65
ℹ️ 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".
|
Sorry for going dark on this. Both fixes are in commit
Files touched: |
|
This pull request has been automatically marked as stale because it has not had recent activity for 23 days. What happens next?
Thank you for your contribution! 🚀 |
|
Merged latest What changed while this PR sat: the recipe-parameter machinery this PR built on was refactored away on How I resolved it:
Verified locally: typecheck ✓, lint ✓, all UI tests pass (including the Could you sanity-check a parameterized deep link on a warm window — i.e. with Goose already running, trigger |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 47c0aab03b
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
On the warm-window path the recipe param field opens blank, because the param store is written after the read that consumes it. Ordering:
Cold start works for the opposite reason: Fix: populate the store before Two smaller items in the same path:
|
|
Hi @SarthakB11 Thanks for your work! I did some testing on this branch and found that there are 2 issues with deeplink
Would you like to fix these? Thank you! |
Route the recipe/bot deep-link protocol handlers through a single openRecipeDeeplink helper that reuses the focused window instead of always spawning a new one, and defer the IPC send until the renderer signals react-ready. Bridge URL-supplied recipe parameters into the ACP recipe-parameter request so a warm-launched parameterized recipe keeps its values. Fixes aaif-goose#9143 Signed-off-by: SarthakB11 <[email protected]>
47c0aab to
8edd19b
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8edd19b9d6
ℹ️ 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".
|
Hi @lifeizhou-ap, thanks a lot for testing this and catching both. I pushed a fix for each and rebased onto latest main. 1. "Trust and Execute" window blinking 2. Parameter form not closing after submit I also dropped the dead Verified locally: the recipe-param unit tests pass (added two for the pre-fill and the one-shot consume), and the App and ParameterInputModal tests are green. I could not drive the full Electron window loop on my side, so a re-test of both flows would be great. One item still open from the earlier notes: |
DOsinga
left a comment
There was a problem hiding this comment.
Thanks for iterating on this. I think this is close, but there are a few remaining issues we should address before merging:
-
Please make the warm recipe/bot deeplink reuse path target only normal chat windows. Right now
openRecipeDeeplinkusesBrowserWindow.getFocusedWindow()or the newest window, which can be the launcher or a standalone app window. Those windows still mountAppInner, so a recipe session can end up being created in the tiny launcher/standalone window instead of a chat window. We should filter to the tracked chat windows (or create a chat window if none exists). -
Please clear or scope the pending recipe parameter stash when no ACP parameter request consumes it.
setPendingRecipeParameters()is read bytakePendingRecipeParameters()only ifrequestAcpRecipeParams()runs. If the recipe has URL params but no declared recipe params, or session creation fails before the ACP request, those values can leak into the next unrelated recipe param request. Afinally/success cleanup or more tightly scoped pending request would avoid that. -
scheduledJobIdis still only preserved on the coldcreateChatbranch. The warm IPC path drops it. If carrying this through needs an ACP option change, please either include that here or make a clear case for why scheduled recipe links into an existing window are intentionally out of scope and not regressing expected behavior. -
Please trim the longer explanatory comments added in
App.tsx,main.ts, andrecipeParametersStore.ts. Some explanation of the ACP timing is useful, but a lot of the current text documents the history of the fix rather than the resulting code.
The current checks look good, and the direction makes sense, but I would like these handled before approval.
Issues when opening a recipe deep link into an already running window: - The 'Trust and Execute' warning flashed twice because the OS can deliver one protocol URL more than once (macOS re-fires 'open-url'; Windows/Linux relay through both 'second-instance' and startup argv). Each delivery created its own session and modal. openRecipeDeeplink now drops burst duplicates, matching the existing shared-session deep-link guard. - A parameterized recipe opened its parameter form with empty fields, so submitting failed required-field validation and the form never closed. The URL values were stashed per session id only after createSession resolved, but the parameter request arrives mid-session/new before that id exists. The values are now stashed in a session-less pending slot before createSession and cleared in a finally, so the request prefills them and unconsumed values cannot leak into a later recipe. - The reuse path now targets only tracked chat windows. The launcher and standalone-app windows also mount AppInner but cannot host a chat session, so it falls through to createChat when no chat window exists. Also drops the unreachable existingWindows[0] fallback. Signed-off-by: SarthakB11 <[email protected]>
8edd19b to
c344d36
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c344d36b9e
ℹ️ 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".
| }); | ||
| toast.error(`Failed to open recipe: ${errorMessage(error, 'Unknown error')}`); | ||
| } finally { | ||
| setPendingRecipeParameters(undefined); |
There was a problem hiding this comment.
Scope pending recipe params per deeplink
When two different recipe deeplinks are opened into the same warm renderer while the first createSession() is still in flight, this finally can clear parameters that were just stashed by the second handler. For example, if link A is slow/no-params and link B sets pendingRecipeParameters before A completes, A reaches this line and erases B's values before B's ACP parameter request consumes them, so B's modal opens without the URL-supplied prefills. The stash needs ownership/scoping per deeplink/session attempt, or the cleanup should only clear the values written by this handler.
Useful? React with 👍 / 👎.
|
Thanks @DOsinga, all four done and pushed:
Tests pass; a re-test of the warm launcher case would be welcome. |
|
All handled by the follow-up commit c344d36: config sent instead of the full URL, params stashed before session creation, IPC deferred until the renderer is ready, and reuse scoped to tracked chat windows. |
|
Hi @SarthakB11, Thanks for the update. I tested this again, and the issue still seems to exist:
Could you please take another look? When you update the PR again, it would also be helpful to run through the recipe params flow end-to-end to make sure the submit behavior is working as expected. Thanks again for working on this. |
|
Closing due to that last followup not being addressed for two weeks #9289 (comment) |
Summary
Clicking a
goose://recipe/...orgoose://bot/...deep link while Goose Desktop is already running was spawning a freshBrowserWindowevery time instead of routing the deeplink into the focused window. Three protocol entry points inui/desktop/src/main.ts(app.on('second-instance'),processProtocolUrl,app.on('open-url')) each calledcreateChat(app, { recipeDeeplink, ... })unconditionally.This adds an
openRecipeDeeplink(url, openDir)helper next toprocessProtocolUrlinui/desktop/src/main.ts. It picks the most-recently-focusedBrowserWindow(falling back to the newest open window, then the oldest), restores and focuses it, and forwards the deeplink as anopen-recipe-deeplinkIPC payload (recipeDeeplinkURL string,recipeParameters,scheduledJobId). When no window exists it falls back tocreateChat(...)and threadswindowDeeplinkURLso the cold-start dir-picker path keeps its prior behavior. All three protocol call sites now go through the helper.On the renderer (
ui/desktop/src/App.tsx), a newopen-recipe-deeplinkIPC listener mirrors the existingrecipeDeeplinkFromConfigbranch inPairRouteWrapper: it callscreateSession(getInitialWorkingDir(), { recipeDeeplink, allExtensions }), dispatchesADD_ACTIVE_SESSION, and navigates to/pair?resumeSessionId=.... The payload sends the raw deeplink URL string so the renderer can route through the samedecodeRecipepath used at cold launch — the IPC contract stays compatible withcreateSession's existingrecipeDeeplink: stringsignature.Reuse is unconditional rather than opt-in; matches the behavior of the surrounding
goose://extension/goose://sessionsdeeplinks.Testing
Manual only. The change is pure routing in the Electron main process plus a new renderer-side IPC listener; there is no existing harness around
main.tsdeeplink dispatch. Reviewer test path: with Goose Desktop running, triggergoose://recipe/...from an external process and confirm the recipe loads as a new session in the focused window instead of opening a new one. Worth a quick check on both macOS (open-url) and Linux/Windows (second-instance).Related Issues
Closes #9143
Screenshots/Demos (for UX changes)
N/A