Skip to content

fix(native-chat): keep the model picker on an agent's first chat - #27327

Closed
AmoabaKelvin wants to merge 1 commit into
stablyai:mainfrom
AmoabaKelvin:keep-model-picker-while-list-loads
Closed

AmoabaKelvin wants to merge 1 commit into
stablyai:mainfrom
AmoabaKelvin:keep-model-picker-while-list-loads

Conversation

@AmoabaKelvin

@AmoabaKelvin AmoabaKelvin commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator
Files Added Deleted Net
Test 2 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​32 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​32
Prod 3 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​35 $\color{#cf222e}{\Huge{\mathbf{−}}}$​10 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​25

ELI5

The first time you open a chat for an agent like OpenCode, Orca has to fetch that agent's model list, which takes about a second. The new chat asked "what are my options?" before the fetch finished, got "no models" back, and hid the model picker for good. Now Orca answers "I don't know yet", and the picker fills in when the list arrives.

What Changed

Before. On the first OpenCode chat for an account, the Model pill appeared for under half a second and then vanished. It stayed gone until you switched tabs and came back. Later chats were fine, because the list was saved by then.

After. The Model pill stays, and about a second later it lists the agent's models.

Mechanism.

  • A new chat does not start its agent until the first message, so the host answers its options read from the saved model list. With no saved list yet, that answer had zero models and looked the same as a running agent reporting that it offers none.
  • The picker treats an answer from a running agent as final. So it hid itself, and ignored the fetched list when it landed.
  • The host now marks that answer with a new optional field, modelsUnknown. When the picker sees it, it stays on the agent's built-in list (for OpenCode, the quiet Model pill) and keeps the saved model's fallback effort choices, so the fetched list can still fill it.
  • A running agent that really offers no models sends no flag, so its picker stays hidden as before.

This started with #26587, which stopped the host from naming a placeholder model in that answer.

Why

The host is the only side that knows whether "no models" means "none" or "not fetched yet", so it should say which. The picker code is shared, so desktop and mobile both get the fix from one rule.

Alternatives considered:

  • Make the host wait for the fetch before answering. Rejected: that read also carries the goal, slash commands and rewind support, and the fetch can take up to 15 seconds. The host answers without waiting on purpose, and a test pins that.
  • Let a late list replace any empty answer. Rejected: an empty answer from a running agent is meaningful, and without a flag the picker cannot tell the two apart.
  • Have each client guess whether the agent is running. Rejected: two clients would each need the guess, and mobile has nothing to base it on.

Visual Proof

No attachments. Observed in a dev build on a fresh profile, OpenCode 1.18.35:

  • Before: Model pill at ~0.5s, gone by ~0.9s, still gone at 12s.
  • After: Model pill stays; opening it lists 11 OpenCode models.

Testing

  • Dev build on a fresh profile (macOS), OpenCode 1.18.35: first and second chats keep the pill and list 11 models; a first Codex chat shows its model and effort.

  • Same check on OpenCode 2.0.26: the pill stays as the Model placeholder. The list does not fill before the first message, because 2.0.26 rejects opencode models --verbose and the fetch fails. That is a separate bug, not changed here.

  • New test: a "no list yet" answer followed by the fetched list fills the picker. It fails without the fix.

  • New test: a saved model outside the built-in list keeps its effort picker when the host has no list.

  • The host test for a chat at rest now asserts the flag.

  • pnpm lint, pnpm tc and the three audits pass. Related test areas pass (shared, native-chat, claude, codex, acp, pi, mobile session).

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

Review

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • Backwards compatibility: modelsUnknown is a new optional field. An older client ignores it. A new client on an older host never receives it, so that pairing keeps the old behaviour until the host updates.
  • SSH / mobile: the host change is on the execution host and the picker rule is shared code, so both follow the same path. Not run on either.
  • Overlap: fix(native-chat): a new chat's model and effort pickers match their first frame before the agent starts #27031 edits the same host function for the effort picker. It does not fix this bug; whichever lands second needs a rebase check.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

@AmoabaKelvin
AmoabaKelvin marked this pull request as ready for review October 10, 2026 23:00
@coderabbitai

coderabbitai Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3efadcb0-5394-4765-bd16-c3d2ea75b6f4

📥 Commits

Reviewing files that changed from the base of the PR and between 1f6a593 and b43a52f.


You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c3e83aaf-a143-407a-89b1-5f50676f8859



📥 Commits

Reviewing files that changed from the base of the PR and between 68519e6 and 1f6a593.




📒 Files selected for processing (5)
  • src/main/native-chat/agent-session-wire/structured-agent-session-options-read.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-options-read.ts
  • src/shared/agent-session-wire.ts
  • src/shared/structured-agent-session-model-catalog-application.test.ts
  • src/shared/structured-agent-session-options.ts



Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.





📝 Walkthrough
📝 Walkthrough
📝 Walkthrough

Walkthrough

Resting session options now identify when the host has no model listing. Option application retains the built-in catalog and adds a reported current model when needed. Tests cover a later host listing populating the model picker and a saved model with its effort options remaining available.





Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to 1f6a5

No actionable merge-blocking issue is established; the change is mergeable after normal checks.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 5 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Title check Passed The title clearly describes the primary change: keeping the model picker visible during an agent's first chat while the model list loads.
Description check Passed The description is detailed and covers the user impact, mechanism, rationale, alternatives, testing, compatibility, and scope. It references issue #26587, but it does not include the required Linked I…



✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR





  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

A chat opened before its agent's first model listing finished took the
host's empty at-rest answer as final and hid the picker.
@AmoabaKelvin

Copy link
Copy Markdown
Collaborator Author

Closing: fixed on main by #26116. When the model list finishes loading, the chat now reads its options again, so the picker comes back on an agent's first chat. Checked on main (36913fd) with OpenCode 1.19.0 on a fresh profile: the first and second OpenCode chats list all 10 models, and a first Codex chat shows model and effort. On the first chat the picker still disappears for about a second before it returns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant