Repository navigation
Share chat options read ownership across desktop and phone - #36582
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review.
|
Reads were coalesced on one queue for the whole view, so after a reconnect, provider restart, phone path change or chat switch the current read waited behind the previous context's request, up to the transport timeout. Each attachment now has its own queue: reads still coalesce to one active and one trailing request within a context, while a new context reads immediately and the old context's reply stays inert. Restores the shared option refresh contract and the reopen test to their original expectations.
The shared read queue starts a read one microtask after it is scheduled, where the old desktop runner started it synchronously. The selection lifetime and context usage tests now wait for each read to start before asserting on it, keeping every original assertion, including one active and one trailing refresh. The paired server test compares transport targets by value, since the options view memoizes an equal target per environment.
Desktop and phone rebuilt the conversation, image and command support objects every render, and a host that omits commands produced a fresh empty list each time. Project them once per accepted answer.
Replacing the selection controller, as a desktop re-pair does, cleared the last accepted support, so slash commands, the goal row and the context meter disappeared until the next options answer. On the phone, returning to a chat before the other chat answered showed fallbacks. The support stays tagged with its session and every consumer already filters by session, so it is now kept, as before the shared owner.
There was a problem hiding this comment.
Actionable comments posted: 1

Review info
-
Run configuration-
- Source mode: Auto
- Repository: Unavailable
- Branch: Unavailable
- File: No configuration file from this repository applied
- Commit: Unavailable
- Layers: Repository UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
5c936035-94a9-4eeb-a0c9-e17acf7d4201
Files selected for processing: 9-
mobile/src/session/use-mobile-structured-option-state.tssrc/renderer/src/components/native-chat/use-structured-agent-session-context-usage.test.tsxsrc/renderer/src/components/native-chat/use-structured-agent-session-option-state.tssrc/renderer/src/components/native-chat/use-structured-agent-session-options.test.tsxsrc/renderer/src/components/native-chat/use-structured-agent-session-paired-runtime.test.tsxsrc/renderer/src/components/native-chat/use-structured-session-selection-reads.performance.test.tsxsrc/renderer/src/lib/structured-agent-session-selection-lifetime.test.tsxsrc/shared/structured-agent-session-options-read-owner.test.tssrc/shared/structured-agent-session-options-read-owner.ts
Files skipped from review as they are similar to previous changes: 1-
- src/renderer/src/components/native-chat/use-structured-session-selection-reads.performance.test.tsx
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 1 remain after this review.
-
Each new turn or host status change re-attached the phone's options reader, so a quick run of turns sent one parallel options request per turn. These changes now reread within the current context, as on desktop: one request runs and at most one waits behind it, and only the latest answer publishes. A status change that arrives while a read is in flight now waits for that read, which the transport bounds.
A refused pick is dropped rather than kept as a finished operation, and the path change replaced the options record, so no revalidation read is in flight when the status wake arrives. The wake therefore reads at once, as the original test asserted. The burst test's superseded answer now carries a real conversation command.
Review loop status: #36582The problem. Desktop and the phone app each loaded a native chat's options (models, effort, permission modes, image support, slash commands) through their own copy of the same request, check, publish and release logic. The copies drifted. On the phone, a slow answer that was already out of date could still update image support and the permission evidence, and clear the new-chat bookkeeping, even though the model menu correctly refused it. Each fix to this logic had to be made twice. What changes for users. Nothing visible in normal use. An out-of-date options answer on the phone now changes nothing, the same as on desktop. On older hosts without per-chat permission modes, the read-only permission row appears only from a current answer. Both apps now share one options reader. Fixed during review
Deferred / follow-ups
Verified
Not verified: no real app run (tests row). Open PR #31241 edits the same two desktop hooks, and whichever lands second integrates; the PR body lists what it must route through the shared reader. For Brennan's review
|
Problem
Desktop and the phone app each load a native chat's options (models, effort, permission modes, image support, slash commands) from the host through their own copy of the same logic: send the request, check the answer is still current, publish it, and release the picks it confirmed. The two copies drifted. On the phone, a slow answer that was already out of date could still update image support and the permission evidence, and clear the new-chat bookkeeping, even though it was correctly refused for the model menu. Every fix to this logic had to be made twice.
What changes for users
Nothing visible in normal use. An out-of-date options answer on the phone now changes nothing, the same as on desktop. On an older host without per-chat permission modes, the read-only permission row now appears only from a current answer. Pickers, Send, first paint and the declared default effort display behave as before.
How it works
One shared options reader in
src/shared/structured-agent-session-options-read-owner.tsnow owns the whole read for both apps. It captures the picks that are already settled, sends the request, checks the answer against the current chat, host connection and context, and only then applies the options, support and phone bookkeeping together and releases the captured picks. Within one context, reads run one at a time with at most one queued behind. A new context (reconnect, agent restart, chat switch) starts its read at once, and the old answer is ignored. The last good answer stays on screen across a reconnect or a controller change. Desktop and phone keep thin adapters for what really differs: desktop's paired-host routing and first-frame seed, the phone's connection generation and legacy permission fallback, and each app's own support display.No saved data, wire format, RPC or capability changes.
Differences from the common pattern
Not in this PR
The write side (marking a pick pending while it is sent, and settling it) is still written separately on desktop and phone. That is a different mechanism; the clean fix is to derive the pending pick from the selection controller instead of storing it, which changes both apps' views. It is left for its own PR.
Overlap
#31241 is still open and edits the same two desktop hooks. Whichever lands second must route its transport gating, target-scoped support, account-switch evidence and current-read-failure clearing through this shared reader, not restore a second publication path.
Verification
Shared, desktop and phone hook suites run in CI, including stale-answer rejection, same-chat retention, a new context reading at once, release of captured picks, Pi refresh ordering, declared-effort display and Send parity, the existing reconnect and stable-client lifetime suites, and N/10N transport and render bounds. QA classification: tests.