Skip to content

chore: port admin Models settings into Settings > AI#26378

Draft
DanielleMaywood wants to merge 29 commits into
mainfrom
feat/ai-settings-models
Draft

chore: port admin Models settings into Settings > AI#26378
DanielleMaywood wants to merge 29 commits into
mainfrom
feat/ai-settings-models

Conversation

@DanielleMaywood

@DanielleMaywood DanielleMaywood commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Note

🤖 This PR was written by Coder Agent on behalf of Danielle Maywood

What

Ports the admin-level Models settings (currently under the Coder Agents area at /agents/settings/models) into the normal Settings > AI area at /ai/settings, as the first page of a multi-page migration.

This is not a lift-and-shift: the page is rebuilt following the existing Settings > AI patterns (the Providers page in particular) and the supplied Figma, not by moving the old markup/styling over.

Changes

  • List /ai/settings/models: Providers-style table with whole-row click-through. Columns: Name (provider icon + display name), Context limit, Status (Default / Disabled badges). "Add model" provider dropdown plus loading / empty / error states.
  • Detail pages: models/add (add, provider via ?provider=), models/:modelId (edit). Card layout matching the new design, Model identifier read-only on edit, retained collapsible Cost tracking / Provider configuration / Advanced sections for functional parity, enabled toggle + overflow menu (Set as default, Duplicate) on edit, Delete/Save vs Cancel/Add Model footer. Duplicate prefills the add form.
  • Routing/sidebar: routes nested under /ai/settings/models* (no collision with the provider add/:providerId routes); sidebar gains a Models item gated by editDeploymentConfig.
  • Shared refactor: the provider-state derivation previously inlined in ChatModelAdminPanel is extracted to site/src/modules/aiModels/providerStates.ts.
  • Old page removed: /agents/settings/models now redirects to /ai/settings/models. The dead ChatModelAdminPanel / ModelsSection / ProvidersSection and old model/provider forms are deleted (the still-used ProviderField was extracted), inbound links repointed, and knip-flagged dead chat provider mutations dropped.

Intentionally out of scope

  • Columns requiring data the backend does not expose for models (model cost, session share, last-used / stale status) are omitted for now.
  • Provider filter dropdown and pagination from the Figma are deferred.
  • (none for this page beyond the deferred columns/filters above)

Testing

  • pnpm check / tsc --noEmit: clean
  • pnpm lint (biome + types + circular deps + react-compiler): clean
  • pnpm exec vitest run src/modules/aiModels/providerStates.test.ts: 9 passed
  • pnpm test:storybook src/pages/AISettingsPage/ModelsPage: 18 passed
  • Existing ChatModelAdminPanel stories still pass (no regression)
Design and implementation plan

Key decisions (from design review)

  1. List follows the Providers page pattern: row click-through to a dedicated detail route, no inline action icons; Set-as-default and Duplicate moved into the detail page.
  2. Columns lacking backend support (model cost, session share, last-used/stale) omitted.
  3. Form keeps the Figma's visible layout and additionally retains Provider configuration and Advanced as collapsible sections for functional parity.
  4. Edit page reuses the add layout, adding enabled toggle, Set as default, Duplicate, Delete, and a read-only Model identifier.
  5. Permission gating: permissions.editDeploymentConfig, matching the current Models admin.

File layout

site/src/modules/aiModels/providerStates.ts (+ .test.ts)   # shared derivation
site/src/pages/AISettingsPage/ModelsPage/
  ModelsPage.tsx / ModelsPageView.tsx (+ stories)
  components/ModelRow.tsx, ModelForm.tsx (+ stories)
  AddModelPage/ + UpdateModelPage/ (container + view + stories)

Follow-ups

  • Backend for cost / session-share / stale-status columns, then surface them.
  • Provider filter + pagination.
  • Port the remaining Agents admin sections (Experiments, Lifecycle, Instructions, Templates, MCP, Spend, Insights).

@DanielleMaywood DanielleMaywood changed the title feat(site/src): port admin Models settings into Settings > AI chore: port admin Models settings into Settings > AI Jun 15, 2026
DanielleMaywood and others added 28 commits June 15, 2026 23:03
Add a Models page under /ai/settings mirroring the Providers page pattern:
list with row click-through, and add/edit/duplicate/delete model detail
pages following the new design. Extract the shared provider-state
derivation into site/src/modules/aiModels so the Agents page and the new
AI settings page use one implementation.

Columns requiring backend data (cost, session share, last-used/stale) are
intentionally omitted. The existing /agents/settings/models page is
unchanged.

Co-authored-by: Coder Agent <agent@coder.com>
…ings

Replace /agents/settings/models with a redirect to /ai/settings/models,
delete the now-dead ChatModelAdminPanel/ModelsSection/ProvidersSection and
old model/provider forms, extract the still-used ProviderField, repoint
inbound links, and drop dead chat provider mutations flagged by knip.

Co-authored-by: Coder Agent <agent@coder.com>
…nchronously

The submit button relied on Formik's isValid, which is briefly true under
validateOnMount because errors populate in a post-render effect. This raced
with the Add story's synchronous toBeDisabled assertion. Compute the
disabled state from the current values instead.

Co-authored-by: Coder Agent <agent@coder.com>
…dmin sidebar

Mirror the Providers external link with a Models item that points to
/ai/settings/models, using the arrow-up-right trailing icon.

Co-authored-by: Coder Agent <agent@coder.com>
Match the Providers page, which renders provider icons in a rounded-square
Avatar, in the Models list rows and the model form header for visual
consistency.

Co-authored-by: Coder Agent <agent@coder.com>
…ls page

The ChatModelAdminPanel ProviderIcon renders inside its own rounded-full
circle, so wrapping it in an Avatar still looked circular. Use the Providers
page ProviderIcon/getProviderIcon (plain logo in a rounded-square Avatar) in
the model rows, form header, provider select, and add-model dropdown so the
two settings pages match. Add the gemini icon mapping so model icons do not
regress.

Co-authored-by: Coder Agent <agent@coder.com>
…UX on Models

List rows now show an Enabled badge when enabled and no badge when disabled
(Default takes precedence), mirroring the Providers row. The model detail
page shows a Disabled badge by the title and moves the enabled toggle to a
Switch with an Enable label that persists immediately, instead of saving the
enabled state with the rest of the form.

Co-authored-by: Coder Agent <agent@coder.com>
…isabled status to model list

Add a Provider column showing each model's provider label, and present
status with the shared StatusIndicator (Active/Disabled with a status dot)
plus a Default sub-label, matching the new model list design. Model cost
remains omitted pending backend support.

Co-authored-by: Coder Agent <agent@coder.com>
Render the models table with client-side pagination (10 per page) using the
shared paginateItems helper and PaginationWidgetBase, plus a Showing X of Y
footer, matching the Figma.

Co-authored-by: Coder Agent <agent@coder.com>
Keep table rows a uniform 72px tall so the default model's 'Default'
sub-label no longer makes that row taller than the others, avoiding
layout shift on page changes.
…vatar spacing

Match the Figma spec: render the model name and provider name as
14px/24px medium text that truncates with an ellipsis (primary and
secondary content colors respectively), and give the provider avatar a
universal 16px of space by using a 40px (lg) avatar with 16px cell
padding in the 72px row.
The status label (Active/Disabled) rendered at text-xs (12px); bump it
to text-sm with a 24px line-height to match the Figma body
default/medium style. Color and weight already came from the success
StatusIndicator variant.
…der style

Render the context limit cell at text-sm/24px medium so it matches the
provider name typography.
… a dropdown

The Add model action was a dropdown that forced the admin to pick a
provider before opening the form. Replace it with a plain button that
links straight to the Add model page, and have that page default to the
first manageable provider so the provider becomes an in-form choice (it
remains selectable via the Provider field).
- Move the collapsible section chevrons (Cost tracking, Provider
  configuration, Advanced) to the left of their titles, with the
  description indented beneath the title.
- Group Cancel and Add Model together at the bottom-right; the edit-mode
  Delete button stays left-aligned.
- Drop the 'Configure connection details and credentials' subtitle that
  isn't in the design and right-align the edit-only enable toggle.
- Capitalize the context limit 'Tokens' suffix.
… form

Match the Figma input spec (40px tall, 12px horizontal padding) by
bumping the model form's inputs, selects, and input groups from h-9 to
h-10. The base Input/SelectTrigger already provide the 12px padding.
The provider-config segmented control grows to match (container h-10,
inner buttons h-9).
…puts

Match the Figma: each top-grid field shows its helper description
between the label and the input rather than below it. Adds the missing
'Unique identifier (used in urls, can't be changed)' description to the
model identifier field (replacing its info tooltip) and moves the
display name, context limit, and provider descriptions above their
controls.
…se switches

- Wrap Cost tracking, Provider configuration, and Advanced in a single
  rounded bordered panel, with interior padding and dividers between
  each section (instead of bare top-border separators).
- Render provider-configuration boolean options with the shared Switch
  component (switch + label + info icon), each on its own full-width
  row, replacing the On/Off segmented control.
…ith heading

Add pl-6 to each expanded section's content so the fields line up with
the section heading text rather than the chevron (chevron 16px + 8px
gap).
…downs

Reasoning effort and other enum options were shown as a segmented
button control; render them as a Select dropdown (matching the Figma)
with capitalized option labels. Removes the now-unused SegmentedField.
…switches

Make enum dropdowns compact (single grid column) instead of full-width
so the input and dropdown fields (thinking budget tokens, thinking
display, reasoning effort) sit inline in the grid row, with the
boolean switches stacked full-width below them.
…data

Drive conditional field visibility and mutual exclusivity from the
generated model-options schema instead of hardcoding field names in the
frontend.

- codersdk/chats.go: tag the web-search domain/context fields with
  visible_when="web_search_enabled", and mark anthropic allowed/blocked
  domains as conflicts_with each other.
- scripts/modeloptionsgen: emit the new visible_when and conflicts_with
  metadata; regenerate chatModelOptionsGenerated.json.
- site ModelConfigFields: generically hide fields until their
  visible_when sibling is enabled, and disable a field while a
  conflicts_with sibling holds a value (recoverable if both are set).

This keeps the source of truth in the Go structs, so new dependent or
mutually exclusive fields work without frontend changes.
Only show the JSON array/object validation error once the field has
been blurred, so typing a partial value like "[" no longer complains
mid-edit. Submit remains blocked while the value is invalid.
Remove the footer's top border so there's no extra divider line between
the enclosed configuration panel and the Cancel/Save buttons.
…iting

Drop the mr-auto so the edit-mode Delete button sits in the right-hand
button group next to Save instead of being pushed to the left.
…er color on display name

Generated by Coder Agents.
…re base component defaults

Remove redundant h-10 (base Input/SelectTrigger/InputGroup/Autocomplete
are already h-10) and redundant text-sm/font-medium on Labels (base Label
already sets them) across the model form fields.

Generated by Coder Agents.
…on base 14px/12px

Tailwind orders the arbitrary text-[13px] before the named text-sm/text-base
scale, so it never won over the base component font size. Removing it leaves
fields/labels at the base 14px (text-sm) and helper text at 12px (text-xs),
matching the Figma type scale.

Generated by Coder Agents.
Plain labels inherited the base leading-none (16px box) while the
inline-flex labels rendered at 24px, leaving Model identifier taller than
Display name. Standardize every field label on flex items-center gap-1
leading-6 for a consistent 24px height.

Generated by Coder Agents.
@DanielleMaywood DanielleMaywood force-pushed the feat/ai-settings-models branch from 4637fdc to 8f5794f Compare June 15, 2026 23:04
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