fix(android): keep chat model selection synchronized#100985
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 272e7ed98d
ℹ️ 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".
| if (chatMetadataAgentId != nextAgentId) { | ||
| _commands.value = emptyList() | ||
| commandsAgentId = null | ||
| _modelCatalog.value = emptyList() | ||
| chatMetadataAgentId = null | ||
| chatMetadataLoadState = ChatMetadataLoadState.Unloaded |
There was a problem hiding this comment.
Clear chat metadata on gateway scope changes
When the user connects to a different Gateway that uses the same active agent id (the common main case), beginConnect() only calls chat.onGatewayScopeChanging() before replacing sockets, and GatewaySession.connect() closes the old socket without necessarily firing onDisconnected(). Because this branch leaves chatMetadataLoadState and _modelCatalog intact when the agent id matches, the next health/bootstrap path sees hasCurrentChatMetadata() as true and skips chat.metadata; since ChatScreen now reads chatModelCatalog, the model picker can keep showing the previous Gateway's models.
Useful? React with 👍 / 👎.
9edf39d to
12ef50b
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 12ef50b74e
ℹ️ 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".
| chatMetadataLoadState = | ||
| when { | ||
| models.isNotEmpty() -> ChatMetadataLoadState.Loaded | ||
| chatMetadataLoadState == ChatMetadataLoadState.RetryEmptyCatalog -> ChatMetadataLoadState.Loaded | ||
| else -> ChatMetadataLoadState.RetryEmptyCatalog |
There was a problem hiding this comment.
Preserve the retry for a later metadata fetch
When the chat screen opens it calls both loadChat(...) and refreshChatCommands(), so fetchChatMetadata() can be in flight twice for the same agent before either response updates chatMetadataLoadState. If the model catalog read times out for both near-simultaneous chat.metadata calls, the first empty response moves the state to RetryEmptyCatalog and the second immediately marks it Loaded, so later health events skip the intended retry and the picker can stay empty for the session even after the catalog becomes available. Track the retry per completed fetch generation or serialize metadata loads so the second empty response is an actual later retry, not just a concurrent duplicate.
Useful? React with 👍 / 👎.
|
Land-ready review complete. Fixes verified:
Proof:
Known proof gap: the connected Pixel remained keyguard-locked, so no manual device interaction or screenshot proof was produced. No proof assets were committed or uploaded. |
|
Merged via squash.
|
* fix(android): harden chat model selection * fix(android): bound model metadata retries * fix(android): preserve newer model selections * chore: leave changelog to release workflow * chore: sync native i18n inventory
* fix(android): harden chat model selection * fix(android): bound model metadata retries * fix(android): preserve newer model selections * chore: leave changelog to release workflow * chore: sync native i18n inventory
Related: #100798
Related: #100699
What Problem This Solves
Fixes issues where Android users selecting a chat model could send on the previous model after a failed patch, see an accepted selection overwritten by stale history, or receive the default agent's model catalog while chatting with another agent. It also prevents a temporarily empty model catalog from remaining empty for the session.
Why This Change Was Made
The chat controller now owns the active agent's combined command/model metadata, treats model patch acceptance as the send-ordering boundary, hydrates the selected model from canonical session history, and rejects stale history model state after a newer local selection. Empty catalog metadata gets one bounded retry so timeout fallbacks recover without polling forever for a legitimately empty catalog.
User Impact
Android's in-chat model picker stays aligned with the active session and agent. Immediate sends wait for a successful model change; failed changes remain visible and do not send on the wrong model.
Evidence
tbx_01kwvyq0f7630vtfpjeeqwxt2d: focused Play-debug unit tests passed for model selection, command metadata, reconnect restoration, picker ordering, secure preferences, connection management, and bootstrap auth.git diff --check: clean.CronJobDetailTest.kt,InvokeErrorParserTest.kt, andNodeUtilsTest.kt; no touched file was reported.