You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Feature] Collapsible provider sections in the composer model picker (patch + tests)
#12536
[Feature] Collapsible provider sections in the composer model picker (patch + tests)
Motivation
With several routes configured, the composer model seat opens one continuous scroll: every provider heading and every model under it. A provider heading is a label, not a section you can fold, so the resting card length is the sum of every provider's catalog — a profile with a local router, a subscription route and a few gateways easily overflows the 360px card and forces scrolling past routes the user is not choosing from. Search (#2352 / #5122, shipped) solves the "I know the model name" half; it does not shorten the list at rest.
This proposal makes each provider heading a disclosure control: a collapsed section keeps its heading (with its model count) and hides its models. It is deliberately the smallest mechanism that shortens the card — no new pane level, no change to selection, ids or persistence.
Related threads, so this does not read as a duplicate:
With more than one provider loaded, each provider heading is a toggle (chevron + name + model count), with aria-expanded on the toggle; the section is named by the provider name only.
Clicking a collapsed heading expands it, clicking again collapses it, and the menu stays open. Toggling never submits a selection.
The collapse choice persists per device (localStorage key dsh.model-select.collapsed-providers); corrupt or unavailable storage falls back to the first-open policy.
First-open policy: with three or more routes and a current route, every section except the current one starts collapsed; with two routes, or when the saved route is not in the catalog, everything starts open (the picker never opens onto headings only).
Typing in the search field expands every section so a match is never hidden, and the disclosure controls are not rendered while searching.
Choosing a model — including from a search result in a collapsed section — leaves that section expanded on the next open.
A single-provider catalog renders today's plain heading (no toggle).
The keyboard walk includes the heading toggles: ↑/↓ cycle headings and rows, Tab on a heading toggles it, and Escape / Shift+Tab semantics are unchanged.
No host, RPC or persistence change: a selection still submits provider + model (+ optional effort) through the existing session.selectModel path.
Implementation
packages/client/ui-primitives/src/MenuGroup.tsx (+ MenuGroup.module.css): optional expanded / onToggle / count / toggleLabel props. Without them the group renders exactly as today, so the /model popup keeps its flat, search-first list.
packages/client/ui-model-selection/src/client/ModelSelect.tsx: disclosure state, first-open policy, search override, reveal-on-select, and heading toggles joining the keyboard walk (data-menu-row rows read from the DOM).
packages/client/ui-model-selection/src/client/provider-collapse.ts (new): storage read/write and the first-open policy.
Locales (provider.expand / provider.collapse) and README (en/zh) updated.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
[Feature] Collapsible provider sections in the composer model picker (patch + tests)
Motivation
With several routes configured, the composer model seat opens one continuous scroll: every provider heading and every model under it. A provider heading is a label, not a section you can fold, so the resting card length is the sum of every provider's catalog — a profile with a local router, a subscription route and a few gateways easily overflows the 360px card and forces scrolling past routes the user is not choosing from. Search (#2352 / #5122, shipped) solves the "I know the model name" half; it does not shorten the list at rest.
This proposal makes each provider heading a disclosure control: a collapsed section keeps its heading (with its model count) and hides its models. It is deliberately the smallest mechanism that shortens the card — no new pane level, no change to selection, ids or persistence.
Related threads, so this does not read as a duplicate:
Behavior (acceptance criteria)
aria-expandedon the toggle; the section is named by the provider name only.dsh.model-select.collapsed-providers); corrupt or unavailable storage falls back to the first-open policy.↑/↓cycle headings and rows, Tab on a heading toggles it, and Escape / Shift+Tab semantics are unchanged.session.selectModelpath.Implementation
packages/client/ui-primitives/src/MenuGroup.tsx(+MenuGroup.module.css): optionalexpanded/onToggle/count/toggleLabelprops. Without them the group renders exactly as today, so the/modelpopup keeps its flat, search-first list.packages/client/ui-model-selection/src/client/ModelSelect.tsx: disclosure state, first-open policy, search override, reveal-on-select, and heading toggles joining the keyboard walk (data-menu-rowrows read from the DOM).packages/client/ui-model-selection/src/client/provider-collapse.ts(new): storage read/write and the first-open policy.provider.expand/provider.collapse) and README (en/zh) updated.Branch (rebased on current master):
KAN-H/deepseek-harness@master...KAN-H:deepseek-harness:feat/model-provider-sections
Commit
6cecf07245, 10 files, +480/−23. Happy to turn it into a PR if the direction is useful.Verification
pnpm exec vitest run packages/client/ui-model-selection/tests→ 98 passed (13 newprovider-collapseunit tests, 7 new disclosure behavior tests)pnpm exec vitest run packages/client/ui-primitives/tests/menu-group.client.spec.tsx packages/client/ui-commands/tests→ 160 passedpnpm exec oxlint packages/client/ui-model-selection/src packages/client/ui-model-selection/tests packages/client/ui-primitives/src/MenuGroup.tsx→ 0 warnings / 0 errorspnpm exec tsc -b tsconfig.client.json→ cleanpnpm run verify-translation-pairing→ README record re-recorded中文摘要
输入框的模型菜单把每个提供方的分组标题和全部模型铺在同一层滚动列表里;提供方越多,静止状态的列表越长,只能一路滚过去。本提案把提供方标题做成可折叠的分区:收起的分组保留标题(带模型数量)、隐藏模型。
行为:多提供方时标题可点击折叠/展开且不触发选择;折叠状态按设备记忆(localStorage);首次打开时,≥3 个路由只展开当前路由、其余收起,≤2 个路由或无当前路由则全部展开;搜索时强制展开全部分组,避免匹配项被折叠标题遮住;选中模型后该分组保持展开;单提供方保持现有标题。键盘
↑/↓会经过标题,Tab 在标题上即折叠/展开;无 Host/RPC/持久化契约变化。与 #7942(provider-first 两级选择)是同一问题的不同机制:本方案不加层级、一次点击即可看到任意路由的模型,两者可共存;与 #2352/#4211/#4842/#5122(搜索)正交。
实现只动
MenuGroup(可选 disclosure 属性,默认行为不变,/model弹窗仍为平铺+搜索)、ModelSelect与新增的provider-collapse.ts。分支已推送,98 个模型选择测试 + 160 个 primitives/commands 测试通过,lint 与类型检查干净。如方向认可,可整理为 PR。All reactions