Skip to content

feat(models): admin drag-and-drop sort order for the model picker - #1248

Merged
philmerrell merged 1 commit into
developfrom
claude/model-picker-sort-order-6eb6b2
Sep 23, 2026
Merged

philmerrell merged 1 commit into
developfrom
claude/model-picker-sort-order-6eb6b2

Conversation

@philmerrell

Copy link
Copy Markdown
Contributor

Why

The chat model picker shows models newest-first, so its order depends on when each model happened to be added. Admins had no way to put the models they want people to choose at the top.

What changed

Backend

  • ManagedModel has a new read-only field, sortOrder (optional int). Only the new endpoint writes it. Create and update never touch it, so saving the model form can't undo a drag.
  • New endpoint PUT /admin/managed-models/order takes { "modelIds": [...] }, the full list of model IDs in order, and sets each model's position.
    • It returns 409 if the IDs repeat or don't match the current table exactly. That means the admin reordered a stale copy, for example after another tab added or deleted a model.
    • It checks against a fresh table scan, not the 60s config cache.
    • It only writes rows whose position changed. Each write is conditional on the row still existing, so a model deleted mid-reorder isn't recreated as a bare row.
    • It clears the cache even if it fails partway.
    • It's declared before PUT /managed-models/{model_id}, so order isn't treated as a model ID. A test covers this.
  • Sorting happens in _list_managed_models_cloud: ordered models first, lowest number first, then unordered models newest first. /models and the admin list therefore return the same order, and the picker keeps rendering what the server sends.
    • No migration. With nothing ordered, the list comes back exactly as it does today.
    • A newly added model goes to the bottom until an admin places it.

Frontend (Manage Models page)

  • Each row has a CDK drag handle (cdkDropList / cdkDrag, locked to the vertical axis).
  • Keyboard reordering on the handle: arrow keys move one place, Home/End move to the top or bottom. Focus returns to the handle after each move, and a live region announces each move to screen readers.
  • Reordering is off while a search or filter is active, because dropping a row into a filtered subset has no clear meaning for the hidden models. The page shows "Clear filters to reorder" instead.
  • ManagedModelsService.reorderModels updates the list immediately. Saves go out one at a time, and moves made while a save is in flight are merged into one follow-up save of the latest order, so a late response can't overwrite a newer local order. If a save fails, the list reloads from the server.
  • Which model new chats start with is still set by isDefault. It doesn't depend on list position, so reordering doesn't change anyone's default model.

Testing

  • Backend: 7 new storage tests (moto) and 4 new route tests. tests/routes, tests/shared and tests/architecture pass.
    • Locally, 8 inference/quota route tests errored because a dev .env was copied into the worktree to run a local server. They pass 40/40 with that file moved aside. It's a local-environment issue, not caused by this PR.
  • Frontend: 3 new ManagedModelsService specs (optimistic update, coalescing, reload on failure). The manage-models, model picker (model-dropdown) and model-service specs pass (104). ng build is clean.
  • ⚠️ Not yet checked by hand in the browser. The local sign-in needed Entra credentials. Worth one drag and one keyboard move on dev after merge.

🤖 Generated with Claude Code

Models were listed newest-first everywhere, so the chat picker's order was
an accident of creation time. Admins can now drag rows on the Manage Models
page to set the order both the admin list and the chat picker use.

- ManagedModel gains a read-only `sortOrder`, written only by the new
  `PUT /admin/managed-models/order` (full catalog of ids; a partial or stale
  list is a 409). Unordered models sort after ordered ones, newest first, so
  an uncurated catalog keeps today's order.
- Sorting happens in the shared list path, so /models and the admin list
  agree and the SPA renders server order as-is.
- Manage Models: CDK drag handle per row, keyboard reorder (arrows,
  Home/End) with a live-region announcement, disabled while filtered.
  Saves are optimistic, serialized and coalesced; a failure reloads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@philmerrell
philmerrell merged commit 1e046bd into develop Sep 23, 2026
6 checks passed
@philmerrell
philmerrell deleted the claude/model-picker-sort-order-6eb6b2 branch September 23, 2026 05:28
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