Repository navigation
fix(native-chat): every new-chat request opens its own chat - #26782
Conversation
…ivers the same request
A request with text ("Send notes > New agent", browser annotations) used to take over a blank
chat that was still starting in the same tab group, so the same action landed in the just-opened
blank tab or in a new tab depending on how fast the first chat started. Every start now opens its
own chat unless it re-delivers the same request id (or resumes the same conversation).
Removes what only that claim read: the claim branch in the launch join, the attempt's blank flag,
the request's text/group fields, the launch options' targetGroupId and the launch target's
groupId (the tab still opens in the caller's group), the empty-chat and chat-tab-group modules,
and the draft-load-pending probe only the empty-chat check used.
Review summaryProblem. Picking a native-chat agent (+ menu, new-tab search, new-agent shortcut, dashboard) a second time without sending anything did not open a second chat: Orca refocused the empty chat, or joined it if it was still starting. Notes or a browser annotation sent to "New agent" while a blank chat of that agent was still starting went into that blank chat, so the result depended on how fast the chat started. User-facing change. Every new-chat request now opens its own chat. The same request delivered twice still opens one chat. What changed in review
Deferred
Verified
Not verified: Linux, Windows and SSH hosts, and agents other than OpenCode, were not run live. The changed code is shared by every native-chat agent and host. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (1)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthroughStructured agent launches now start separate chats instead of claiming an existing idle empty chat. Repeated attempts with the same request ID can join the existing launch. The launch request and target interfaces no longer carry the removed blank-state and target-group fields. Tests cover separate launches, repeated requests, prompt delivery, and split targeting. Draft-load tracking now uses the hydration promise, and the pending-state helper was removed. Priority: ⬇️ Low Merge Risk: ⚪ Minimal · up to Distinct new-chat requests open separate chats, duplicate delivery reuses its request’s chat, and draft loading retains its retry and bounded-wait behavior. No material merge risk is established. Pre-merge checks |
|
…nd-native-chat # Conflicts: # src/renderer/src/lib/structured-agent-session-launch.ts
ELI5
If you opened a native chat (Claude, Codex, OpenCode or another native-chat agent) and then asked for another chat with the same agent before sending anything in the first, Orca did not open a second chat. It brought the first, empty chat back to the front, or folded your pick into it if it was still starting. The same happened when you sent notes or a browser annotation to "New agent" while a blank chat of that agent was still starting: the notes went into that blank chat instead of a new one.
After this change, every "new chat" request opens its own chat.
What Changed
Before / after, as the user sees it
Mechanism
#24917 let a new-chat request end up in an existing chat in three ways. This PR removes two of them:
beginStructuredAgentLaunchSettlementaskedfindIdleEmptyStructuredChatfor an open chat nothing had been sent into and returned it instead of starting a launch. That lookup and its file are deleted.getJoinableStructuredLaunchStatelet a blank request join, and a request with text claim, the newest blank chat still starting in the same tab group. It now only returns a launch that the same request already started (structuredLaunchesHoldingIdentity(matches, request.id)).Everything that existed only for the two removed paths is deleted: the claim branch in
joinStructuredLaunchState, theblankflag on launch attempts, the launch request type with its text and tab-group fields, the tab-group field on launch options and targets (the tab itself still opens in the caller's split through the existing provisional-tab argument), the empty-chat check (structured-agent-session-launch-empty-chat.ts), the tab-group lookup (structured-agent-session-chat-tab-group.ts), and a draft-loading flag only the empty-chat check read.Why
Orca shows chats as tabs. Asking for a new tab, or sending notes to a "New agent", is an explicit request for a new chat; quietly reusing an empty one looked like the pick had failed and made notes land in a tab the user had just opened for something else.
Removing the join paths instead of narrowing them is the smaller change: after this PR, the only way a new start joins another is a repeat of the same request, which is also how the host-side launch path de-duplicates.
Differences from the common pattern:
Not in this PR:
main, so this matches them; where duplicate-click protection lives is part of STA-9920.agent.launch. Moving them is STA-9920.Linked Issue
None. This is a maintainer request. Follow-up: STA-9920.
Visual Proof
Live QA on a separate Mac (hidden dev builds, isolated profiles), with the real OpenCode 2.0.21 talking to a local test model and its start delayed 6 s so "still starting" can be hit reliably. An in-page log sampled every chat's launch state every 20 ms to confirm the timing. After = this PR at 3c0e7ac; before =
main(the before shots for the first two rows were taken on this Mac earlier at f01bd93).Picking OpenCode twice from the + menu, 0.5 s apart, while the first chat is still starting
Picking OpenCode again once the empty chats are ready and idle
"Send notes to > New agent > OpenCode" while a blank OpenCode chat is still starting
Testing
structured-agent-session-new-chat-own-launch.test.ts(renamed from...-empty-chat-reuse.test.ts) andstructured-agent-session-launch-different-request.test.ts: a second blank pick opens a second chat whether the first is idle or still starting; notes sent while a blank chat is starting open their own chat; notes delivered twice are sent once, in their own chat; the same pick delivered twice still opens one chat. Putting the text claim back fails 8 of these 17 tests; restoring the old idle-chat reuse fails the two "opens a second chat" tests.37 launch-related renderer test files, run one at a time: 290 tests pass.
orca-ci-checks: 23 of 23 pass, including the full typecheck. CI is green.Live: the three scenarios above on macOS with OpenCode. Not run live: Linux, Windows, SSH, and other agents; the changed code is shared by every native-chat agent and every host.
I manually tested these changes locally
Automated tests added/updated, or explained why not below
Agent skill upstream boundary
Notes
Renderer-only launch logic. Nothing sent to the host and no saved data changes, so SSH, WSL and mobile hosts are unaffected: the change only decides whether the desktop starts a new launch. Same behavior on macOS, Linux and Windows.
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)