Skip to content

cmux NEXT model menu: one row per model, its provider at the row's end - #24530

Merged
teamleaderleo merged 36 commits into
feat-cmux-nextfrom
composer-look-picker-spacing
Oct 26, 2026
Merged

teamleaderleo merged 36 commits into
feat-cmux-nextfrom
composer-look-picker-spacing

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Leo-ask: ask-a8b97f1201

#24224 has landed. The branch's base merge (a40f4e8) resolves to feat-cmux-next plus only this PR's own two commits (d3eea1c test, 5160f68 fix), re-applied onto base's current model menu (its search field, New Tab inline More models, fork rows and grid trailing column stay). Adopted from the original lane after it closed.

Leo, exact words: "the thing i had in the henlo chat was just pasting some images lawrence said and this: ... and also the tab unread + simultaneous ongoing thing feels I weird idk if there's a way to combine + the spacing is off ..."

Lawrence posted a thumbnail of the model menu showing many near-duplicate DeepSeek rows, such as "DeepSeek V4 Pro [New] OpenCode", "DeepSeek V4.1 Flash OpenCode" and "OpenRouter/DeepSeek Chat OpenCode". His caption: "spacing + needs search". He also wrote "we should just have a standard model picker".

This PR covers provider variants and spacing. Search landed separately in base. Focus after a pick comes in its own PR.

What changes

A harness that routes to several providers (OpenCode, Pi) reports a model once per provider: openrouter/deepseek/deepseek-v4-pro, deepseek/deepseek-v4-pro, and so on. The menu drew each of these as its own row, with the provider pasted into the name.

  • One row per model. modelVariants.ts (new, pure functions) reads the provider from the id path or from a "Provider/" prefix in the name. It groups rows that share the last id segment into one model. Only rows that name a provider join a group; two bare ids stay two models. The row's name drops the provider prefix. A bracketed note such as "[New]" becomes a quiet tag after the name.
  • The provider sits at the row's end in secondary text, in the same place a filtered row names its harness. The row lands the running provider's id if that provider is one of the offers, else the first one listed.
  • A Provider row switches providers. When the running model has several offers, a Provider row (after Effort) names the running provider and opens a submenu that lists every provider, with the running one checked. It uses the existing picker.provider string, which already has all 21 languages.
  • Even spacing. A row's detail (its provider, or a searched row's harness) sits at the end of the label column with a 16 px gap, so details line up from row to row. Base's grid already gives the check and number key one fixed 24 px column, so this PR's earlier check/key width rules were dropped in the base merge.
  • Top four. quickSections (from cmux NEXT model menu: four models, each once, the rest under More models; Effort and Fast name their state; submenus open up from the composer #24224) counts a model as a top one if any of its offers is among the latest, so one model with three providers no longer takes three of the four top slots.

Look: the menu's glass is unchanged (rgba(30,30,46,0.6), blur(20px) saturate(1.4)). Theme tokens only, with no orange, no system blue and no dots.

Versions (gallery agent-pane.model-menu-providers, an OpenCode chat on DeepSeek V4 Pro)

  • A, ships: each model once, its provider at the row's end, plus a Provider row for the running model (provider-row, provider-row-open).
  • B: a model with several providers becomes a submenu of them, so picking takes one more hover (provider-submenu, provider-submenu-open).
  • C: the model's name heads a list of its providers, indented underneath, one row per provider (provider-expanded).

I picked A. It is the "standard model picker" Lawrence asked for: a short list of models, one row each, with the provider as a detail rather than part of the name. Picking a model is still one click, and changing provider is the second choice, next to Effort. B hides which provider a row lands behind a hover, and its rows stop being one-click picks. C brings back the long list Lawrence flagged, just reorganised. The version is one prop (quick.providers), so B or C is a one-line switch.

Tests

bun test test/model-menu-providers.test.tsx (new) on huge-blue:

What the six tests cover:

  • groupVariants keeps bare ids apart.
  • It joins a model's providers and lands the running provider.
  • It strips the tag and the provider prefix.
  • The menu shows one row per model, with the provider and the "New" tag.
  • The Provider submenu lists OpenCode, OpenRouter and DeepSeek, and picking OpenRouter lands its id.
  • A chat running deepseek/deepseek-v4-pro checks the single row and names DeepSeek.

Neighbours on the head: model-menu*, model-picker* and composer-fast-toggle, 9 files, 76 pass, 1 fail. The one failure, model-menu-short-list "a model its profile declares with no effort levels shows no Effort row…", fails the same way without this PR. vp lint and vp check types pass.

Observed / Not run

  • Observed: gallery captures before and after in headless Chromium on huge-blue (Catppuccin Mocha, 760 px). Before: OpenCode's list of ten provider-prefixed rows. After: one row per model, details aligned, a Provider row, and glass unchanged. The captures are kept off this PR.
  • Not run: the native app (webview-only change) and the browser test files.

No capture: webview-only change; gallery compare https://cmux-lawrences-mac-mini.tail137216.ts.net:18796/compare/composer-look-picker-spacing/ (entry agent-pane.model-menu-providers; agent-pane.model-picker for the Claude and Codex menus, which don't change).

Size

613 added lines: about 290 source, 223 test and 105 gallery. That's over the brief's ~300 because the tests and gallery are in their own new files, which keeps them clear of the sibling PRs that edit model-menu-compact.test.tsx.

Overlap

The sibling PRs this used to overlap (#24224, #24355 merged; #24521, #24487 closed) are all settled; the base merge resolved their hunks.

Re-run on the merged head (huge-blue)

  • bun run check: format, types and protocol pass; vp lint exits non-zero only on warnings in DynamicWorkflow.gallery.tsx, which this PR doesn't touch (same on base).
  • model-menu-providers, model-menu-compact, model-menu-short-list, model-menu-submenu-up, composer-fast-toggle, model-catalog-alias-fold: 87 pass, 0 fail.
  • All model-menu*, model-picker*, quick*, new-tab* tests: 466 pass, 3 fail. The 3 (new-tab-widget-edit, new-tab-minimal-default, new-tab-no-entry-motion) fail the same way with base's sources.

Changelog

  • Changed: the composer's model menu lists a model that several providers serve once, with its provider at the row's end and a Provider row to switch providers. Its rows line up evenly.

Agent session: agent session

🤖 Generated with Claude Code

teamleaderleo and others added 25 commits October 22, 2026 04:44
…me their state; submenus grow up from the composer (failing)

Leo 2026-10-21 on the nightly: his claude-sr2 chat's model menu listed nine
numbered models, Opus 5.5 twice, and its Effort submenu opened downward toward
the window's edge. These tests hold the menu to at most four models (the running
one among them, each once, numbered 1 to 4), the Effort row naming its level with
the submenu checking it, the Fast mode row naming On or Off, and the Effort
submenu growing up from its row when the composer sits at the window's foot.

Leo-ask: ask-98ecbe7758

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…els; Effort and Fast name their state; submenus grow up from the composer

Leo 2026-10-21: "why are there so many models!? it should be truncating and then
showing more models.. this effort should open up top instead of bottom" and
"this should just show the effort too right?".

- Opus 5.5 twice: foldAliases (modelCatalogData.ts) left the catalog release a
  session pins (claude-opus-5-5) beside Claude Code's `opus` alias, which Claude
  Code names "Opus 5.5" (0fe538a), and a Claude profile the catalog does not
  map (claude-sr2) skipped the alias fold and the curated top list entirely.
  The fold now keeps the running release's row and folds the alias into it, and
  a profile of a catalogued agent folds against that agent's releases (`kin`)
  and lists its curated top models.
- The compact menu lists at most four models (QUICK_ROWS): the top picks, plain
  models before variants, and the running model always among them. Number keys
  name only those rows. Everything else is under More models.
- Submenus (ui/Menu.tsx Submenu) grow toward the room their row has: up from the
  row's bottom when the row sits in the lower half of the menu's box, down from
  its top otherwise; Base UI's collision avoidance still flips them.
- The Fast mode row names Off or On (On in the accent) where Effort and Account
  name their values.

Leo-ask: ask-98ecbe7758

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rted pinned release keeps its row (failing at 7ab8d7b)

Codex review of #24224 at 7ab8d7b (BLOCK, two findings): folding a profile's
`opus` alias into the release claude-opus-5-5 dropped the user's overrides of
`claude-sr2/opus` (fast off, one effort), and a session that reports running the
pinned release with no model option lost that release's row.

Leo-ask: ask-98ecbe7758

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…idden for it; the reported running model keeps its row

- aliasRow layers the release's catalog row (and its own declared and user
  layers), then what the harness declares for the alias and the user's
  overrides of the alias, so `<harness>/opus` overrides still apply after the
  alias takes the release's row.
- The fold's running model is the session's model option, else the model the
  session reports (summary.model, which direct.ts sends without a model
  option). The picker catalog's session now carries `model`.

Leo-ask: ask-98ecbe7758

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…errides

Codex review of #24224 at 850d374: a started profile on claude-opus-5-5 that
also lists Claude Code's `opus` alias ("Opus 5.5") kept the release row
unchanged, so what the harness declares for `opus` and the user's overrides of
`<harness>/opus` (no Fast, one effort) were dropped. The running row now takes
the alias's layers and keeps its own id, so it stays the checked row. The
short-list test and the gallery's Claude stage pass the running model to the
picker session too.

Test: test/model-catalog-alias-fold.test.ts "the running release keeps the
folded alias's overrides" fails at 850d374 and passes here.

Leo-ask: ask-98ecbe7758

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e the session options

withLiveOptions read any row with no efforts as one the catalog does not describe, so a session
offering fast mode marked it Fast-capable and gave it every effort the adapter lists. That undid
an alias declaration or agentPane.models.overrides entry that set fast: false and efforts: [].
layeredModel now records which of efforts and fast the profile or the user set (PickerModel.own);
withLiveOptions only narrows those efforts and leaves that fast alone.

Codex review at a3f9e52.

Leo-ask: ask-98ecbe7758

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sts as an alias shows it checked

A direct session (direct.ts) has no model option and reports the release it runs in summary.model,
while the live Claude probe lists only the bare opus alias. foldAliases found no row for the
release, gave the alias the release's catalog row, and kept the alias id, so the running model was
missing, no row was checked, and picking the apparent current row chose the alias. The alias now
takes the release's id when the session runs that release, and a running release nothing lists
still gets its row.

Codex review at 6638fbc.

Leo-ask: ask-98ecbe7758

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… row

reasoningChoices read an empty efforts list as "no restriction", so a folded alias its profile
declares (or the user overrides) with efforts: [] still showed every level the session lists,
and a pick sent a level the profile says the model does not take. A row whose levels its profile
or user set (PickerModel.own.efforts) is now held to them: none means no Effort row.

Codex review at 87da5d1.

Leo-ask: ask-98ecbe7758

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on the fold and the running release

Codex review at a14ff11, and a sweep of every path this PR adds
against every override field:
- hidden: a profile the catalog does not map (claude-sr2) rebuilt its kin's releases without the
  user's hides, so with claude-sr2/opus hidden the running claude-opus-5-5 came back, checked. A
  release hidden here by its id, a catalog alias, or an alias the harness reports as it is no
  longer one of the profile's releases, as applyUserLayer drops it from its own harness.
- fast and efforts: an override keyed by a catalog alias (claude/opus, */opus) reached the release
  through applyUserLayer but was not recorded as the user's, so the session's options undid it.
  layeredModel now layers a release's catalog-alias overrides, then its own.
- name: the fold matched the user's display names, so renaming the alias or the release listed
  Opus 5.5 twice. It matches the harness's reported name against the catalog's own names.

Leo-ask: ask-98ecbe7758

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lawrence on an OpenCode chat's model menu, which listed DeepSeek V4 Pro once
per provider: "spacing + needs search", "we should just have a standard
model picker". The menu should list each model once, name the provider its
row lands, and offer a Provider row for the running model.

Red on base: 6 fail, 0 pass (bun test test/model-menu-providers.test.tsx).

Leo-ask: ask-a8b97f1201

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16027-99fc-73f0-9482-5a4babfe1b0a&host=cosmic-gray
Lawrence on an OpenCode chat's model menu, which listed DeepSeek V4 Pro once
per provider ("DeepSeek V4 Pro [New]", "OpenRouter/DeepSeek V4 Pro",
"DeepSeek/DeepSeek V4 Pro"): "spacing + needs search", "we should just have a
standard model picker".

modelVariants.ts groups a harness's "provider/model" rows by model: the menu
lists each model once, by its name, with the provider its row lands in
secondary ink at the trailing edge (one column, where a filtered row names its
harness) and a bracketed note as a quiet word. A Provider row (after Effort)
names the running model's provider and switches among the ones that serve
it. The four rows are four models, not four providers of one.

The gallery (agent-pane.model-menu-providers) shows three versions: the
Provider row (ships), each grouped model as a submenu of providers, and
providers listed under their model.

Leo-ask: ask-a8b97f1201

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16027-99fc-73f0-9482-5a4babfe1b0a&host=cosmic-gray
@teamleaderleo teamleaderleo added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 23, 2026
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 74f3c8f: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr24530 -f ref=composer-look-picker-spacing -f platform=macos -f backend_mode=local

Probably yours: agent-pane-stream-jitter.test.ts, agent-pane-stream-jitter.test.ts, agent-pane-queue-collapse.test.ts fails here but not on main's latest full suite. Seen on other PRs too (likely flaky): agent-pane-peer-chat.test.ts, agent-pane-question-records.test.ts, agent-pane-queue-steer.test.ts and 26 more. This PR merged before its CI finished: fix forward on main.

CI failed on 74f3c8f042 (run 40316188427 attempt 2): 4 code, 1 unknown.

Job Verdict Why
web / react-apps-base-check (1) code a web test failed
web / react-apps-base-check (2) code a web test failed
web / react-apps-base-check (4) code a web test failed
web / react-apps-base-check (3) code a web test failed
web / react-apps-check unknown no known signature; failed step: Check webview test shards

Failures:

  • seen on other PRs agent-pane-peer-chat.test.ts a chat on an SSH machine > counts its running turn from the prompt and offers no machine switch mid-...: failed (job)
  • seen on other PRs agent-pane-question-records.test.ts answered live, the card goes and the record takes its place: failed (job)
  • seen on other PRs agent-pane-queue-steer.test.ts queued and steering prompts > the queue takes its own place in the stack: nothing is cut off or draw...: failed (job)
  • seen on other PRs agent-pane-stream-jitter.test.ts chromium: settling short, long, and tool-ending replies does not move the message or composer: failed (job)
  • seen on other PRs agent-pane-stream-jitter.test.ts chromium: a queued prompt deleted while the turn runs a tool leaves no gap for long: failed (job)
  • new in this PR agent-pane-stream-jitter.test.ts webkit: a queued prompt deleted while the turn runs a tool leaves no gap for long: failed (job)
  • new in this PR agent-pane-stream-jitter.test.ts chromium event first: a deleted queued prompt leaves no gap under the last row: failed (job)
  • seen on other PRs chat-inspector-overlay-toggle.test.ts chromium, header: the toggle is above the open overlay and a click on it closes the Inspector: failed (job)
  • seen on other PRs claimPaint.test.tsx a pooled Settings page claimed by the host reports its paint once its first screen is in: failed (job)
  • seen on other PRs claimPaint.test.tsx a Settings page loaded fresh reports its first paint once its first screen is in: failed (job)
  • ... 22 more in the job logs
Matched log lines
web / react-apps-base-check (1): (fail) a chat on an SSH machine > counts its running turn from the prompt and offers no machine switch mid-chat [30922.33ms]
web / react-apps-base-check (2): (fail) a pooled Settings page claimed by the host reports its paint once its first screen is in [191.10ms]
web / react-apps-base-check (4): (fail) the summary card lists the chat's background tasks: running ones first, the finished folded [962.04ms]
web / react-apps-base-check (3): (fail) every block in the chat column starts on the column's left edge [8179.37ms]

Not re-run automatically: web / react-apps-base-check (1), web / react-apps-base-check (2), web / react-apps-base-check (4), web / react-apps-base-check (3), web / react-apps-check are not machine failures.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

red: web / Web status; NEW: green on the base b247631; do not merge until green; see lane-rules
red: web / react-apps-base-check (1); no finished base run on b247631 to compare; do not merge until green; see lane-rules
red: web / react-apps-base-check (2); no finished base run on b247631 to compare; do not merge until green; see lane-rules
red: web / react-apps-base-check (3); no finished base run on b247631 to compare; do not merge until green; see lane-rules
red: web / react-apps-base-check (4); no finished base run on b247631 to compare; do not merge until green; see lane-rules
red: web / react-apps-check; no finished base run on b247631 to compare; do not merge until green; see lane-rules

Gallery before/after for 74f3c8f: 16 states rendered, 4 images differ, 1023 more touched states not rendered. Images are in the run's artifact, not on this public PR.

gh run download 40316188239 -R manaflow-ai/cmux -n gallery-advisory-24530-74f3c8f0428c33119adb521ae582ca09a4166dfd (then read gallery-review.json)

States
State Theme Status Diff Picked by
agent-pane.composer-pickers/closed Apple System Colors Light unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/closed Apple System Colors unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/pill-rail Apple System Colors Light unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/pill-rail Apple System Colors unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/model-menu Apple System Colors Light unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/model-menu Apple System Colors unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/model-more Apple System Colors Light unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/model-more Apple System Colors unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/model-focus Apple System Colors Light unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/model-focus Apple System Colors unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/model-press-drag-release Apple System Colors Light unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/model-press-drag-release Apple System Colors unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/effort-menu Apple System Colors Light unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/effort-menu Apple System Colors unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/effort-focus Apple System Colors Light unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-pickers/effort-focus Apple System Colors unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-row/claude-auto Apple System Colors Light unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-row/claude-auto Apple System Colors unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-row/long-model Apple System Colors Light unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-row/long-model Apple System Colors unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-row/leo-report Apple System Colors Light unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-row/leo-report Apple System Colors unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-row/granted Apple System Colors Light unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-row/granted Apple System Colors unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-row/fast-off Apple System Colors Light changed 0.0859% own QuickModelMenu.tsx
agent-pane.composer-row/fast-off Apple System Colors changed 0.0855% own QuickModelMenu.tsx
agent-pane.composer-row/fast-on Apple System Colors Light changed 0.0861% own QuickModelMenu.tsx
agent-pane.composer-row/fast-on Apple System Colors changed 0.0845% own QuickModelMenu.tsx
agent-pane.composer-row/queued Apple System Colors Light unchanged 0% own QuickModelMenu.tsx
agent-pane.composer-row/queued Apple System Colors unchanged 0% own QuickModelMenu.tsx
agent-pane.model-button-default-effort/profile-default Apple System Colors Light unchanged 0% own modelPicker.css
agent-pane.model-button-default-effort/profile-default Apple System Colors unchanged 0% own modelPicker.css

Pick other states with a Gallery: entry.id, entry.id/variant line in the PR body.

@teamleaderleo

teamleaderleo commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · session

@blacksmith-sh

blacksmith-sh Bot commented Oct 23, 2026

Copy link
Copy Markdown

Found 8 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmpfd0wqg0q/summary-missing.json (live):/summary-missing.json (live): View Logs
/tmp/tmpgmigzbgh/summary-fail.json (live):/summary-fail.json (live): View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
test_base_passes (main.NoticesPairTests.test_base_passes)/
test_base_passes (main.NoticesPairTests.test_base_passes)
View Logs
test_targets_outside_the_app_go_to_the_mac_canary (main.SwiftCanaryFleetCoverage.te
st_targets_outside_the_app_go_to_the_mac_canary)/
test_targets_outside_the_app_go_to_the_mac_canary (main.SwiftCanaryFleetCoverage.te
st_targets_outside_the_app_go_to_the_mac_canary)
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

rust workspaces / plan (changed Cargo workspaces) is red on 20 of 20 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

#24224 landed squashed, so its pre-squash commits on this branch conflicted
with base. This merge resolves to base plus only this PR's own two commits
(d3eea1c, 5160f68) re-applied onto base's current model menu: base's
search, New Tab and fork rows and its grid trailing column stay; the
provider grouping, Provider row, tag and detail-at-end are added on top.
The PR's own check/shortcut width rules are dropped because base's grid
column already lines them up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-6516c08f19030a26c4eb
@teamleaderleo
teamleaderleo marked this pull request as ready for review October 26, 2026 09:23
@cursor

cursor Bot commented Oct 26, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex): FIX FIRST at a40f4e8

  • webviews/src/agent-session/acpmux/modelVariants.ts:48-55 — Grouping uses only the final ID segment. openrouter/qwen/coder-3 and together/mistral/coder-3 collapse into one row, hiding one model and landing the first offer.
  • webviews/src/agent-session/acpmux/ModelPicker.tsx:100-108 — The first offer’s unavailable flag disables the entire group. In New Tab, an unavailable first provider hides an available second provider.
  • webviews/src/agent-session/acpmux/QuickModelMenu.tsx:142-160, 444-470 — Held height and width probes omit the Provider row and provider/tag detail, so switching tabs can move or clip the menu.
  • webviews/src/agent-session/acpmux/ModelPicker.tsx:686-709 — Search still returns raw provider rows, so searching a grouped model shows duplicates with provider prefixes.
  • webviews/src/agent-session/acpmux/ModelPicker.tsx:726-729 — Starred rows bypass grouping; favoriting multiple offers of one model produces duplicate rows.
  • webviews/src/agent-session/acpmux/QuickModelMenu.tsx:699-708 — More models drops provider and tag, so grouped entries there lose their trailing provider and [New] tag.

teamleaderleo and others added 4 commits October 26, 2026 09:50
…ls and vendors (red)

Codex review of #24530: rows of two vendors sharing an id tail merged,
an unavailable first provider disabled the whole model on New Tab, search
and Starred listed every provider's row, and More models dropped the
provider and tag. Red on a40f4e8: 6 fail, 5 pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-6516c08f19030a26c4eb
…keep vendors apart

- modelVariants: rows whose ids name different vendors (openrouter/qwen/x,
  together/mistral/x) stay two models.
- A grouped model lands its running provider, else its first available one,
  so an unavailable first provider no longer disables it.
- Search and Starred group a model's providers into one row; a search row
  names its provider in its detail.
- More models rows show the tag and provider.
- The held height and width probes count the Provider row and each row's
  provider and tag.

bun test test/model-menu-providers.test.tsx: 11 pass (6 fail before).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-6516c08f19030a26c4eb
…ning one is unavailable (red)

Codex review of 924b529. Red on 924b529: 1 fail, 11 pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-6516c08f19030a26c4eb
…ailable

A search has no Provider row, so a running provider that is unavailable left
the model's other providers out of reach. bun test
test/model-menu-providers.test.tsx: 12 pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-6516c08f19030a26c4eb
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex): FIX FIRST at 924b529

  • ModelPicker.tsx:96-99, 703-724 — Search can make an available provider unreachable. If the running offer is unavailable but another offer for the same model is available, groupChoices preserves the unavailable current offer; search emits that sole row as disabled, and the Provider submenu is hidden while searching. Typing the model name therefore cannot switch to the available provider.

[exited with code 0]

teamleaderleo and others added 2 commits October 26, 2026 10:23
…odel in any order (red)

Codex review of 34bace1. Red on 34bace1: 1 fail, 12 pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-6516c08f19030a26c4eb
…do not

A two-segment id (qwen/coder-3) names no vendor, so it joined whichever
group with its last segment came first: after together/mistral/coder-3 it
merged direct Qwen into Mistral. Rows that name a vendor group first; a row
that does not joins the model of the vendor its provider is, else the only
model with its last segment, else stands alone. bun test
test/model-menu-providers.test.tsx: 13 pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-6516c08f19030a26c4eb
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex): FIX FIRST at 34bace1

  • modelVariants.ts:77: Two-segment IDs have no vendor and match any group sharing their suffix. Reordering the existing fixture to together/mistral/coder-3, openrouter/qwen/coder-3, qwen/coder-3 incorrectly groups direct Qwen with Mistral. With Mistral running, selecting Provider → Qwen therefore changes the model vendor instead of only its provider.

[exited with code 0]

teamleaderleo and others added 2 commits October 26, 2026 10:48
…ing one is unavailable (red)

Codex review of 3992645. Red on 3992645: 1 fail, 13 pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-6516c08f19030a26c4eb
… it is available

Lists with no Provider row (search, Starred) left an unavailable running
provider as the model's only row. groupChoices now lands the first available
provider whenever the running one is unavailable, so search no longer needs
its own special case. bun test test/model-menu-providers.test.tsx: 14 pass;
model-menu*, model-picker*, quick* and composer pickers: 116 pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-6516c08f19030a26c4eb
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex): FIX FIRST at 3992645

  • webviews/src/agent-session/acpmux/ModelPicker.tsx:759 — [P2] Starred pins an unavailable running offer. If unavailable opencode/deepseek-v4-pro is current and both it and available openrouter/deepseek/deepseek-v4-pro are favorites, grouping produces one disabled row. Starred has no Provider submenu, so the available favorite becomes unselectable.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

cmux-next fast gates / post cmux-next/fast-gates is red on 16 of 20 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

high-signal review link / link is red on 19 of 20 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex): FIX FIRST at 2c2cd8c

  • QuickModelMenu.tsx:331-334 — Provider detection only matches model.id === current. If the running provider is unavailable but two alternate providers remain available, groupChoices selects one fallback row with offers, yet runningRow is undefined, so the Provider submenu is omitted and the other available provider cannot be selected from the compact menu. The same strict check affects tabExtent and width probing at lines 161 and 464.

teamleaderleo and others added 2 commits October 26, 2026 11:30
…ne is unavailable

Red at 2c2cd8c: bun test test/model-menu-providers.test.tsx (Provider row missing).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-6516c08f19030a26c4eb
…available

The fixed-harness list dropped the unavailable running offer before grouping, and the
running row, its Provider row, tabExtent and the width probe matched only the row's own id.
They now match any of the row's offers, and the list filters after grouping.

Green: bun test test/model-menu-providers.test.tsx (15 pass); model menu, picker, quick and
composer-picker suites 108 pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-6516c08f19030a26c4eb
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex): SHIP at 74f3c8f

  • No correctness findings.

@teamleaderleo
teamleaderleo merged commit a7a5104 into feat-cmux-next Oct 26, 2026
129 of 134 checks passed
@teamleaderleo
teamleaderleo deleted the composer-look-picker-spacing branch October 26, 2026 11:47
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

teamleaderleo added a commit that referenced this pull request Oct 27, 2026
…picker-height

Every commit of this branch, through 724ea2d, already landed on feat-cmux-next as #24676
(f1f6ba2, "follow-up: carry #24194 stable model menu fix"), and later base PRs (#24224,
#24530, #25182, #25183, #25167) built on that code. The conflicts in QuickModelMenu.tsx and
model-menu-compact.test.tsx are base's later edits to the same lines, so they resolve to base's
side; the height spacer, width probe and check-in-probe behaviour are all in base's version.
The branch now matches feat-cmux-next.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-f68ebdd9a3c1704ffb42
teamleaderleo added a commit that referenced this pull request Oct 29, 2026
#24530 landed this feature's first version, and base since replaced the
compact menu's held width/height probes (#26615) and its provider search
grouping (#27303). The conflicting menu files (QuickModelMenu, ModelPicker,
gallery, CSS, the providers and compact tests) take base. What this PR
still adds on top: modelVariants.ts's grouping (the route prefix names the
provider, rows join by owner, one offer per provider preferring the
available and running row, ids/count per group) with its tests, and the
reasoning slider focusing on mount (EffortTrack/EffortPicker). The
modelSections dedupe flag and the groupVariants `preferred` set had no
caller left, so they are dropped.

Verified: bun test model-variants (13/13), model-menu-providers (15/15),
model-menu-compact (42/42), effort-picker-slider (18/18); bun run check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d7590af53de4742a1808
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant