Skip to content

fix(opencode): show which OpenCode provider each model uses in the model picker - #17776

Closed
g3r4n wants to merge 4 commits into
pingdotgg:mainfrom
g3r4n:feat/opencode-go-model-picker-sections
Closed

g3r4n wants to merge 4 commits into
pingdotgg:mainfrom
g3r4n:feat/opencode-go-model-picker-sections

Conversation

@g3r4n

@g3r4n g3r4n commented Oct 10, 2026 •

Copy link
Copy Markdown

Problem

Fixes #17100.

One OpenCode instance in T3 Code serves models from every provider the user connected inside OpenCode: Anthropic, OpenAI, OpenRouter, OpenCode Go (subscription), OpenCode Zen (pay-per-token), and so on. Many models exist under several of them with the same name (Claude Sonnet 5 via Anthropic and via Zen, DeepSeek V4 Flash / Kimi K2.6 via Go and via Zen, ...). The catalog is sorted by model name, so these copies sit next to each other in the picker and you can't tell which account or subscription a model will use.

Two things cause it:

  1. With OpenCode 2.x, the status check builds the catalog from model.list only, so models carry no subProvider. The row footer just says "OpenCode" for every model (this is what [Bug]: Composer no longer allows user to differentiate between OpenCode sub-providers #17100 reports; the 1.x path already filled subProvider from the provider name).
  2. Even with the label, same-named models from different providers are interleaved, and the only difference is a small footer line.

Repro: OpenCode 2.x with several providers connected (e.g. Anthropic, OpenAI, OpenCode Go, OpenCode Zen), open the model picker, select the OpenCode instance.

Change

Scoped to the OpenCode provider only. Nothing is specific to Go or Zen: sections follow whatever providers OpenCode reports, using OpenCode's own display names.

  • packages/provider-opencode: the OpenCode 2 model loader also reads provider.list and sets each model's subProvider to its OpenCode provider name ("Anthropic", "OpenAI", "OpenRouter", "OpenCode Go", "OpenCode Zen", ...), matching what the 1.x path already does. If provider.list fails, the catalog still loads without names.
  • apps/web (ModelPickerContent): when the OpenCode instance is selected in the picker sidebar and its models come from more than one OpenCode provider, the list gets one section per provider, with a small heading, inside the OpenCode section. Sections are ordered by provider name (models without a provider name last, under "Other"); order inside a section is unchanged, so favorites-first and saved model order still apply within a section. The heading is rendered above the first row of the section, not as a combobox item, so keyboard navigation and jump shortcuts are unchanged.
  • apps/mobile (ThreadSettingsSheet model catalog, used by the thread settings sheet and the scheduled task model picker): the native app has its own picker, so it gets the same OpenCode-only split. openCodeModelSections in lib/modelOptions.ts builds the sections (the row subtitle already carries the provider name), and the catalog renders a small header per section inside the OpenCode provider group.
  • Desktop (Electron) renders the apps/web UI, so it is covered by the web change.
  • No change for other drivers (Codex, Claude, Copilot, ...) or for an OpenCode catalog with a single provider. On web, the Favorites view and search results (which mix providers) are also unchanged; on mobile those views stay grouped by provider as before, so the sections still apply inside the OpenCode group.

These are needed for the same problem: the server change provides the provider label, and the web and mobile picker changes make it readable when names collide.

Not included: telling a subscription login apart from an API key for the same provider (e.g. Claude Pro/Max vs an Anthropic API key). OpenCode 2's provider.list and model.list don't say which auth a provider uses. credential.list does (oauth vs key per integration), but it returns the raw tokens and keys, and it doesn't cover keys that come from environment variables. So I left it out. The section is named after the provider only.

Scope and approval

Linked bug: #17100 (open, not triaged yet). Part 1 is the regression it describes. Part 2, the sections (web and mobile), is a small OpenCode-only presentation change on top of it. If you'd rather keep this to the label fix, I can drop the picker commits.

Verification

  • packages/provider-opencode: test in status.test.ts checks that OpenCode 2 models get subProvider from their provider name (Anthropic, OpenAI, OpenCode Zen and OpenCode Go, including the same model id under Zen and Go; a blank name is ignored). vp test run src/server: 185 passed, 2 skipped. tsc --noEmit: clean.
  • apps/web: tests in ModelPickerContent.test.ts: five providers (Anthropic, OpenAI, OpenCode Go, OpenCode Zen, OpenRouter) give five sections ordered by name, with stable order inside each and headings on the first row of each; single-provider OpenCode and non-OpenCode drivers are untouched; unlabeled models go last. vp test run src/components/chat/ModelPickerContent.test.ts: 21 passed. tsc --noEmit: clean. vp lint on changed files: only the pre-existing react(set-state-in-effect) warning on the scroll-fade effect. vp fmt --check: clean.
  • apps/mobile: test in lib/modelOptions.test.ts with the same six cases (five providers plus unlabeled). vp test run src/lib/modelOptions.test.ts: 19 passed. tsc --noEmit: clean. vp lint on changed files: no new warnings (same 5 pre-existing memo-dependencies warnings in ThreadSettingsSheet.tsx).
  • Manual UI check: rendered the real ProviderModelPicker locally (Vite dev, Chromium) with Codex, Claude and OpenCode instances. The OpenCode catalog had Anthropic, OpenAI, OpenCode Go and OpenCode Zen models, using real model and provider names from models.dev, sorted the way the OpenCode driver sorts them. The provider data was stubbed, not from a live OpenCode server. The "before" image uses the same stubbed labels, so it shows the interleaving; on a real OpenCode 2 server before this change, the footers would all just say "OpenCode".

Web, desktop-size window (left: before; then the OpenCode instance after, scrolled top / middle / bottom; Codex and Claude stay in the sidebar):

OpenCode model picker with several providers, before and after

Web picker at a phone viewport (iPhone 13 emulation in Chromium), top / middle / bottom:

OpenCode model picker with several providers at a phone viewport

Codex instance, unchanged:

Codex instance unchanged

Not checked: a live OpenCode 2 server with real credentials (so the exact provider names it returns were not observed live), the Electron desktop shell itself (it renders the same web component), and the native mobile app on a device or simulator: no iOS/Android build environment was available, so the mobile change is covered by its unit test only, with no screenshot.

Prepared with an AI coding agent. Model and harness: Grok Bot (Cursor).

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Oct 10, 2026
@g3r4n
g3r4n marked this pull request as ready for review October 10, 2026 09:15
@g3r4n g3r4n changed the title feat(web): split OpenCode Zen and OpenCode Go models in the model picker fix(opencode): tell OpenCode Zen and OpenCode Go models apart in the model picker Oct 10, 2026
@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Oct 10, 2026
@g3r4n g3r4n changed the title fix(opencode): tell OpenCode Zen and OpenCode Go models apart in the model picker fix(opencode): show which OpenCode provider each model uses in the model picker Oct 10, 2026
@coderabbitai

coderabbitai Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 400810be-53e1-44a9-aa5f-f3bc7bef3c25



📥 Commits

Reviewing files that changed from the base of the PR and between c77a7b7 and 56878a9.




📒 Files selected for processing (8)
  • apps/mobile/src/features/threads/ThreadSettingsSheet.tsx
  • apps/mobile/src/lib/modelOptions.test.ts
  • apps/mobile/src/lib/modelOptions.ts
  • apps/web/src/components/chat/ModelPickerContent.test.ts
  • apps/web/src/components/chat/ModelPickerContent.tsx
  • packages/provider-opencode/src/server/driver.ts
  • packages/provider-opencode/src/server/status.test.ts
  • packages/provider-opencode/src/server/status.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

OpenCode 2 model loading now attaches provider display names to model metadata. Mobile and web model pickers group eligible OpenCode models by provider and render section headings. The web picker suppresses headings during search and in Favorites.

Changes

OpenCode provider sections

Layer / File(s) Summary
Attach provider names to models
packages/provider-opencode/src/server/status.ts, packages/provider-opencode/src/server/driver.ts, packages/provider-opencode/src/server/status.test.ts
The model loader fetches model and provider data concurrently. Model conversion adds a trimmed, nonempty provider name as subProvider. Tests cover provider-specific names and whitespace-only names.
Group models and identify sections
apps/mobile/src/lib/modelOptions.ts, apps/mobile/src/lib/modelOptions.test.ts, apps/web/src/components/chat/ModelPickerContent.tsx, apps/web/src/components/chat/ModelPickerContent.test.ts
The mobile and web helpers group eligible OpenCode models by provider name, sort named sections alphabetically, and keep model order within each section. Tests cover unchanged catalogs and unlabeled models.
Apply groups and render section labels
apps/mobile/src/features/threads/ThreadSettingsSheet.tsx, apps/web/src/components/chat/ModelPickerContent.tsx
The mobile picker renders accessible section headers. The web picker groups non-favorite results and renders headings above model rows; headings are suppressed during search and in Favorites.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix · Severity of issue fixed: Low

Possibly related PRs

  • pingdotgg/t3code#15327: Adds OpenCode provider labels to model records and uses them in web and mobile picker presentation.

Suggested reviewers: juliusmarminge





Merge Risk: ⚪ Minimal · up to 56878

This change adds OpenCode provider labels and grouped headings to the model pickers. No concrete merge-blocking problem was found. The live OpenCode server, Electron shell and native mobile app were not checked, which is ordinary validation uncertainty.

Pre-merge checks | Passed 3 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check Warning The description includes complete Problem, Change, Scope and approval, and Verification sections. However, the linked issue is explicitly not triaged, and the description provides no explicit maintain… Add a link to a triaged issue or maintainer discussion with explicit approval for the grouping changes. If the change qualifies as an obvious focused fix without prior approval, explain why that exemption applies.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check Passed Issue #17100 requires an easy way to distinguish models from multiple OpenCode sub-providers in the composer picker. packages/provider-opencode/src/server/driver.ts now reads provider.list with `m…
Out of Scope Changes check Passed The changes stay within the OpenCode model-identification problem in #17100. Server changes provide OpenCode sub-provider names. Web and mobile changes present those names without changing other drive…
Title check Passed The title clearly and concisely describes the main change: showing the OpenCode provider for each model in the model picker.

Full details: Description check

Explanation

The description includes complete Problem, Change, Scope and approval, and Verification sections. However, the linked issue is explicitly not triaged, and the description provides no explicit maintainer approval for the added web and mobile grouping scope.


  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR





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

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

@juliusmarminge

Copy link
Copy Markdown
Member

Note

Grok responding on behalf of Julius.

Thanks for working on this, @g3r4n! #17424 just merged and fixed #17100: the OpenCode 2.x model loader now reads provider.list and attaches each model's provider name as subProvider, so the composer, mobile picker, and search show which OpenCode provider a model comes from. That's the core of this PR, so I'm closing it as superseded.

If you still want the per-provider sections in the picker, please open a smaller follow-up rebased on current main that covers just that UI change.

@g3r4n

g3r4n commented Oct 10, 2026

Copy link
Copy Markdown
Author

@juliusmarminge oh perfect ! Sorry for the noise, I should have look at the current open PRs.

@g3r4n
g3r4n deleted the feat/opencode-go-model-picker-sections branch October 10, 2026 11:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Composer no longer allows user to differentiate between OpenCode sub-providers

2 participants