feat(site/src): add Known Model autocomplete and frontend defaults - #24842
Conversation
…d Known Model design decisions
…odel identifier suggestions
|
/coder-agents-review |
There was a problem hiding this comment.
The catalog architecture is well-designed: pure helpers separated from UI rendering, satisfies constraints catching structural drift at compile time, and initial-value comparison instead of Formik touched state for safe default application. The test suite for the pure layer is thorough. CONTEXT.md and the ADR are genuinely useful documentation that resolves the "model" term ambiguity and preserves design rationale.
1 P1, 3 P2, 6 P3, 1 P4, 6 Nit.
The critical cluster (DEREM-4, DEREM-5) stems from conflating the popover's search text with the Formik model field. handleInputChange writes every keystroke to form.values.model, and handleOpenChange(false) reads a stale currentModel from the render-time closure. Together these create two data-correctness bugs: re-selecting a different model can revert to the old selection (DEREM-4), and dismissing the popover after browsing replaces the model with search text (DEREM-5). Separating search state from form state fixes both.
A related but independent issue (DEREM-3) is that the Radix portal focus transfer fires the wrapper's onBlur, calling markTouched() and flashing "Model ID is required." before the admin has done anything. 7 of 17 reviewers independently found this.
The three duplication findings (DEREM-7, DEREM-8, DEREM-13) all occur in applyKnownModelDefaults.ts. snakeToCamel, getPath/setPath, and formPathForPricingField each have identical implementations in sibling files. These are one-line imports.
"This asymmetry between the selection path (safe by accident of stale closures) and the typing path (correct only if React re-rendered) is subtle, fragile, and completely unproven by any test." (Bisky)
🤖 This review was automatically generated with Coder Agents.
…euse Known Model helpers Rename KnownModel.model to modelIdentifier and reuse shared provider, path, and deep object helpers for Known Model default application. Addresses DEREM-2, DEREM-7, DEREM-8, DEREM-13, DEREM-14, DEREM-15, DEREM-16. _Generated with mux_ • Model: `openai:gpt-5.5` • Thinking: `high`
DEREM-1 DEREM-3 DEREM-4 DEREM-5 DEREM-6 DEREM-9 DEREM-11 DEREM-17
… Known Model autocomplete edges Add Storybook play coverage for Known Model autocomplete review edges: - DEREM-1: assert autocomplete trigger aria error linkage. - DEREM-3: assert opening the empty popover does not show required errors. - DEREM-5: assert Escape cancels transient search without drifting the committed model. - DEREM-6: assert no-options copy for unmatched Known Model searches. - DEREM-10: assert sequential defaults replacement, double-apply guarding, exact canonical blur, alias cancellation, and provider-change reset behavior. _Generated with mux • Model: openai:gpt-5.5 • Thinking: high_
…EREM-4/-10 stories
|
/coder-agents-review |
There was a problem hiding this comment.
All 17 R1 findings addressed. The fix commits are solid: search state separated from form state (DEREM-4/5), portal blur guarded (DEREM-3), React Compiler compatibility restored (DEREM-11), helper duplication eliminated (DEREM-7/8/13), and 9 new Storybook interaction tests covering each plan-listed scenario (DEREM-10). R1 fixes verified by panel.
1 P2, 1 P3 new. R1 findings all closed.
The new P2 (DEREM-19) is a regression introduced by the DEREM-5 fix: the close handler uses searchKnownModels (normalized substring matching) to decide whether typed text is search text or a committable identifier. Any off-catalog string like "gpt-5", "mini", "codex", "opus" that substring-matches a catalog entry is silently discarded with no feedback. 8 of 14 reviewers independently found this. It violates the PR's own acceptance criterion: "Off-catalog Model Identifiers remain valid and non-blocking."
The P3 (DEREM-20) is a shared-component change: the Autocomplete's Escape handler was moved to capture phase with unconditional stopPropagation, changing the event contract for all 5 current consumers. No consumer is affected today, but the change is broader than needed.
Process note: the PR description claims "No edits to modelConfigFormLogic.ts" but the R2 commit exported deepGet/deepSet from that file. The test counts (31/34/3) are also stale after R2 (actual: 32/43/12). Consider updating the description.
"What happens at three thousand admins typing model IDs the catalog hasn't heard of?" (Hisoka)
🤖 This review was automatically generated with Coder Agents.
|
/coder-agents-review |
There was a problem hiding this comment.
All 19 R1/R2 findings addressed and verified by panel. 6 of 13 reviewers reported clean. The fix quality is high: DEREM-19 (off-catalog discard) was replaced with exact-alias-only cancellation via findKnownModelByAlias, and DEREM-20 (Escape stopPropagation) was gated on onEscapeKeyDown opt-in.
0 P2, 1 P3, 1 Nit new.
The remaining P3 (DEREM-24) is a state-tracking edge case in previouslyAppliedRef: the ref is overwritten wholesale on each selection, so a three-model sequence can leave stale pricing from an earlier model. Three reviewers found this independently via different paths (stale cost field, off-catalog interleaving, chain tracking loss). The consequence is visible to the admin (pricing fields are in the form, and the inline feedback says "Review and adjust before saving"), so the risk is bounded.
The Nit (DEREM-25) is a test coverage gap: no Storybook play function exercises keyboard selection (arrow-down + Enter) despite the plan calling for one.
Neither finding blocks merge. This needs a human decision on whether to address them in this PR or defer.
🤖 This review was automatically generated with Coder Agents.
…late Known Model default state
|
/coder-agents-review |
There was a problem hiding this comment.
All 21 R1-R3 findings addressed and verified. The DEREM-24 fix (cumulative field tracking with stale-field cleanup) and DEREM-25 fix (keyboard selection test) are solid. 2 of 7 R4 reviewers reported completely clean.
1 P3 new.
The remaining P3 (DEREM-26) is a one-line fix: the Autocomplete renders with clearable={true} (default), so re-clicking the selected model toggles it off, clearing the required field and leaving orphaned defaults. Pass clearable={false}. Three reviewers found this independently.
This does not block merge. The validation catches the empty model field, and the admin must actively type a replacement before submitting. The orphaned-defaults risk is the same class as DEREM-24 (stale metadata visible in the form), which the cumulative tracking now handles for the Known Model selection path.
🤖 This review was automatically generated with Coder Agents.
…e Autocomplete clearable for required Model Identifier (DEREM-26)
|
/coder-agents-review |
There was a problem hiding this comment.
All 22 R1-R4 findings addressed and verified. DEREM-26 fix (clearable={false}) confirmed by 4/7 clean reviewers (Hisoka, Mafuuu, Nami, Pariston).
1 P3 new. 4/7 clean.
The new P3 (DEREM-27) is a narrow edge case in the alias detection on the blur-commit path: findKnownModelByAlias uses normalized comparison (strips hyphens, dots, underscores), so an off-catalog value like claude.haiku.4.5.20251001 (dots instead of hyphens) silently matches the alias and gets discarded. The fix is to check canonical ID first and use exact string comparison for alias detection on the commit path. This does not block merge; the affected input set is small (values that differ from known aliases only in punctuation).
Across 5 rounds: 28 findings tracked. 22 addressed by author, 5 dropped, 1 open (DEREM-27, P3). The PR is ready for human review.
🤖 This review was automatically generated with Coder Agents.
…cal-first commit-path alias detection (DEREM-27)
|
/coder-agents-review |
There was a problem hiding this comment.
All 23 R1-R5 findings addressed and verified. DEREM-27 fix (canonical-first ordering with findKnownModelByExactAlias) confirmed correct. 3 of 5 R6 reviewers reported fully clean.
0 P3+, 1 Nit new. No open findings above Nit.
The Nit (DEREM-29) is a dead-code cleanup: findKnownModelByAlias (normalized matching) is still exported and tested but has no production consumer after DEREM-27 replaced it with findKnownModelByExactAlias. Remove the export and its tests, or keep it as a tested utility for future use.
Process note (recurring): the PR description test counts are stale. Actual at HEAD: 42 knownModels unit tests, 139 ChatModelAdminPanel unit tests, 50 Storybook stories with play functions.
Across 6 rounds: 29 findings tracked. 23 addressed by author, 5 dropped, 1 Nit open. The PR is ready for merge.
🤖 This review was automatically generated with Coder Agents.
…emove unused findKnownModelByAlias (DEREM-29)
|
/coder-agents-review |
There was a problem hiding this comment.
All 24 R1-R6 findings addressed. DEREM-29 cleanup confirmed. 4 of 5 R7 reviewers reported clean.
1 P3 new. No open findings above P3.
The P3 (DEREM-30) is a cosmetic feedback issue: when the admin opens the popover, types any character, presses Escape, then tabs away, the "Defaults applied from X" message reappears despite no value change. The cause is handleInputChange clearing lastAppliedProviderModelRef, which survives the Escape cancellation. The fix is to snapshot and restore the guard on Escape. No data corruption; purely a misleading feedback flash.
This does not block merge. The PR has been thoroughly reviewed across 7 rounds with 30 findings tracked, 24 posted and addressed. This needs a human decision on whether to address DEREM-30 in this PR or defer.
🤖 This review was automatically generated with Coder Agents.
…ve last-applied tracking across Escape (DEREM-30)
|
/coder-agents-review |
… Anthropic happy-path reasoningEffort is medium DEREM-33: AnthropicKnownModelHappyPath asserted all Reasoning Effort radios unchecked, but the Anthropic catalog now sets effort=medium (commit ae75425). Switch to expectReasoningEffort(body, "medium") matching the OpenAI happy-path pattern. Fixes the UI Tests CI failure. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `anthropic:claude-opus-4-7` • Thinking: `max`_
|
/coder-agents-review |
There was a problem hiding this comment.
All 28 posted findings from R1-R12 addressed and verified. DEREM-33 fix confirmed (53/53 storybook tests pass per author). 1/3 panel clean, remaining 2 reported only previously-noted Nits.
No new findings. 0 open.
Across 13 rounds: 33 findings tracked (1 P1, 4 P2, 11 P3, 1 P4, 10 Nit, 1 Note). 28 posted and addressed by author. 5 dropped by orchestrator. 0 open. Clean board. The review is complete.
🤖 This review was automatically generated with Coder Agents.
|
/coder-agents-review |
There was a problem hiding this comment.
The inline autocomplete search rewrite (9f641e6c3) introduces 2 P2 and 6 P3 findings. The shared Autocomplete component gained ~220 lines of new inlineSearch behavior with no dedicated Storybook story, and the keyboard event handling has gaps.
2 P2, 6 P3 new.
DEREM-34 (P2): Enter with no highlighted option does not preventDefault(), so the surrounding form submits. Confirmed by Netero and Meruem.
DEREM-37 (P2): onMouseDown on the inline input unconditionally calls handleOpenChange(true) even when the popover is already open, triggering the parent's open handler and silently resetting in-progress search text.
DEREM-36/38/39/40/41 (P3): keyboard selection stories still use click (DEREM-25 regression), aria-selected tracks cursor not committed value, Escape in inline mode doesn't stopPropagation, ArrowDown reads stale closure on rapid key-repeat, close path re-applies defaults without the double-apply guard.
🤖 This review was automatically generated with Coder Agents.
…dress R13 review Inline search popovers now render only while loading or when suggestions exist, so the Chat Model Admin Panel no longer shows the "No matching known models" copy for off-catalog identifiers. - DEREM-34: prevent form submit for every inline Enter key path and keep off-catalog Enter commits covered. - DEREM-35: add an Autocomplete inlineSearch story that covers typing, keyboard selection, empty Enter, focus retention, Escape, and aria-expanded. - DEREM-36: exercise ArrowDown plus Enter selection in Storybook instead of clicking an option. - DEREM-37: avoid reopening an already-open inline input from focus or mousedown. - DEREM-38: keep aria-selected tied to the committed value rather than the highlighted cursor. - DEREM-39: stop Escape propagation in inline mode only when a caller handles Escape. - DEREM-40: use the highlighted ref for rapid ArrowDown and ArrowUp repeats. - DEREM-41: skip duplicate close-path default application for the same known model.
…inking budget for Haiku 4.5 and Sonnet 4.5 Anthropic adaptive thinking is only supported on Opus 4.7, Opus 4.6, and Sonnet 4.6 in this catalog. Haiku 4.5 and Sonnet 4.5 now use thinkingBudgetTokens=8192 instead of reasoningEffort so Coder defaults them onto the legacy budget_tokens path. Also remove the "(latest)" suffix from the Haiku 4.5 and Sonnet 4.5 display names.
|
/coder-agents-review |
1 similar comment
|
/coder-agents-review |
There was a problem hiding this comment.
All 36 R1-R14 findings addressed and verified. The R14 fix commit (e86b6bfb6) is comprehensive: Enter/preventDefault, onMouseDown guard, inlineSearch story, keyboard selection via Enter, aria-selected, Escape stopPropagation, ArrowDown ref, and close-path guard all addressed in one commit.
3 P3 new. No P2+.
DEREM-42: The DEREM-38 fix (aria-selected={isSelected(option)}) is a dead store. cmdk's CommandItem spreads user props first, then unconditionally sets aria-selected to the keyboard cursor position, overwriting the fix. This is a cmdk limitation, not fixable without patching or replacing cmdk.
DEREM-43: The DEREM-6 no-match reassurance message is absent in inlineSearch mode because the popover auto-hides when no results match. The admin can still submit any value (the inline input stays focused and editable), but the explicit reassurance is lost.
DEREM-44: ArrowDown/ArrowUp in handleInlineKeyDown unconditionally calls handleOpenChange(true), the same pattern DEREM-37 fixed for onMouseDown/focus. Guard with if (!isOpen).
None block merge. The core functionality is solid across 15 rounds of review.
🤖 This review was automatically generated with Coder Agents.
…p dead aria-selected DEREM-44: ArrowDown/ArrowUp inside the inline-search keyboard handler now mirror the DEREM-37 onMouseDown/onFocus pattern, only calling handleOpenChange(true) when the popover is not already open. Prevents resetting parent search snapshot state via a stray arrow keypress mid-search. DEREM-42: Drop the explicit aria-selected prop on CommandItem in inline-search mode. cmdk's CommandItem spreads consumer props before its own aria-selected (which it ties to the keyboard cursor for the listbox pattern), so the override was a dead store. The CheckIcon rendered by renderOptionContent for isSelected options remains the visible indicator of the committed value. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `anthropic:claude-opus-4-7` • Thinking: `max`_
|
/coder-agents-review |
There was a problem hiding this comment.
DEREM-42 and DEREM-44 addressed. DEREM-43 contested by author (product decision: inline search auto-hides, no empty state); panel closed it 2/3 (Mafuuu and Pariston accept, Bisky did not vote on the contested finding directly).
1 P3 new. 0 open above P3.
DEREM-45 is a test gap: the blur-after-auto-hide path for off-catalog identifiers (tab/click away when popover is auto-hidden) has no Storybook story. Only Enter-based commit is tested. The code handles this path explicitly (comment at line 346-348), but a mutation flipping the guard would silently drop off-catalog identifiers for tab/click-away users.
This does not block merge. Across 16 rounds: 45 findings tracked, 38 addressed, 5 dropped, 1 contested and closed by panel, 1 P3 open (DEREM-45).
🤖 This review was automatically generated with Coder Agents.
… blur-after-auto-hide off-catalog commit DEREM-45: add Storybook story exercising the handleBlur branch that commits an off-catalog identifier when the popover is auto-hidden (zero matches) and focus leaves the field via Tab. Complements the existing Enter-based off-catalog commit coverage from DEREM-42. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `anthropic:claude-opus-4-7` • Thinking: `max`_
|
/coder-agents-review |
There was a problem hiding this comment.
DEREM-45 addressed. All 39 prior posted findings closed. Netero clean (1 pre-existing Nit). Mafuuu clean.
1 P2 new.
DEREM-46: the DEREM-45 story (KnownModelBlurAfterAutoHideCommitsOffCatalog) has vacuous assertions. Removing the if (openRef.current) { handleOpenChange(false); } branch from handleBlur still passes both assertions because the inline input shows the search text in both the fixed and buggy paths. The DOM value is identical; only form.values.model differs. Adding expect(queryByText("Model ID is required.")).not.toBeInTheDocument() after the tab-away would distinguish the paths: the mount-time error surfaces via markTouched() in the buggy path but is cleared by setFieldValue in the correct path.
Across 17 rounds: 46 findings tracked. 39 addressed, 5 dropped, 1 contested and panel-closed, 1 P2 open (DEREM-46).
🤖 This review was automatically generated with Coder Agents.
…t no required-field error after blur-commit (DEREM-46) DEREM-46: the original DEREM-45 assertions were vacuous because the controlled inline-search inputValue keeps rendering the typed search text in both the buggy and fixed paths; only form.values.model differs, which the DOM-value assertion couldn't observe. Add an explicit "Model ID is required." not-in-document assertion plus an inline comment explaining the buggy-path mechanic. In the buggy variant, markTouched() fires while form.values.model is still empty and the validation message surfaces; in the fixed path, handleOpenChange(false) commits the typed text via setFieldValue first. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `anthropic:claude-opus-4-7` • Thinking: `max`_
|
/coder-agents-review |
There was a problem hiding this comment.
All 40 posted findings from R1-R17 addressed or closed. DEREM-46 fix verified (negative assertion for mount-time validation error added). Netero flagged 1 P3 (potentially vacuous Anthropic off-catalog story) not corroborated by panel. Pariston: 1 Nit (comment ordering).
No new findings posted. 0 open.
Across 18 rounds: 46 findings tracked. 40 posted and addressed/closed by author, 5 dropped, 1 contested and panel-closed. 0 open. Clean board. The review is complete.
🤖 This review was automatically generated with Coder Agents.
…t flagship models to high reasoning effort Bump reasoningEffort to high for the flagship Pro/Opus tier per @ibetitsmike review feedback: claude-opus-4-7, claude-opus-4-6, and gpt-5.5-pro. Mid-tier and smaller models (claude-sonnet-4-6, gpt-5.5, gpt-5.4-mini, gpt-5.3-codex) remain at medium. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `anthropic:claude-opus-4-7` • Thinking: `max`_
…ss required error on click-off without committing QA flagged that opening the Model Identifier popover and clicking off without typing or selecting still surfaces "Model ID is required." The close path in handleOpenChange unconditionally marked the field touched, and the bottom path of handleBlur did the same. Validation then fired against the still-empty value, so an admin who merely focused the field and changed their mind saw the same error as a failed submit. Gate markTouched on whether the interaction committed (or attempted to commit) a value: selection commits via handleSelect, exact-canonical and off-catalog typing commit via the close path, and Escape or open-and-close-without-typing leave validation untouched. handleBlur's bottom path now skips markTouched when currentModel is empty, so a click-off after a focus-only interaction stays quiet. Formik continues to flip touched on submit, so the required error still appears at the appropriate time. Add DEREM-47 Storybook story covering the QA flow (click input, click off empty, no error). Rewrite DEREM-1 to surface the required-field validation through a real user path (type then clear then click off, which legitimately commits an empty value) so the existing aria-invalid/aria-describedby parity assertions remain meaningful under the new gating. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `anthropic:claude-opus-4-7` • Thinking: `max`_
Replaces the blank Model Identifier free-text input on the Add Model page with provider-scoped Known Model autocomplete and frontend-only metadata defaults for native OpenAI and Anthropic providers. Selecting a Known Model, or typing an exact canonical identifier and blurring the field, prefills
contextLimit, the appropriate max-output-tokens field, and flat base pricing in the existing form. Edit mode, duplicate mode, and unsupported providers preserve the existing plainInputbehavior and submit payload byte-for-byte.The catalog is curated TypeScript records sourced from
models.dev, scoped initially to 6 OpenAI and 5 Anthropic models in declared display order. The pureapplyKnownModelDefaultshelper only writes a field when its current value still equals the form's initial value (or was last applied by Known Model defaulting in this form session, tracked cumulatively across selections). It never setscompressionThresholdor any reasoning/thinking fields, ignores tiered pricing, and never writes to themodelfield (canonicalization is the caller's responsibility).This PR also makes two narrow, additive changes outside the panel directory:
site/src/components/Autocomplete/Autocomplete.tsxgains optionaltriggerAriaInvalid,triggerAriaDescribedBy, andonEscapeKeyDownprops so the new catalog branch can preservearia-invalid/aria-describedbyparity with the plain input and observe Escape close intent reliably across the Radix portal. ExistingAutocompleteconsumers are unaffected;stopPropagationis gated ononEscapeKeyDownbeing provided.site/src/pages/AgentsPage/components/ChatModelAdminPanel/modelConfigFormLogic.tsexportsdeepGet/deepSetso the defaulting helper can reuse them instead of re-implementing the same path traversal.No backend, API, SDK, or DB changes. No edits to
ModelsSection.tsx,ModelConfigFields.tsx,pricingFields.ts, orproviderPolicyDefaults.ts.Validation
knownModels/(catalog, search, exact-canonical lookup, exact-alias lookup, badge, defaulting helper).ChatModelAdminPanel.stories.tsxpass, including 17 DEREM-traceable interaction tests covering each plan-listed and review-driven scenario (open-no-error, Escape cancellation, sequential selection, double-apply guard, blur-canonical, alias cancellation, provider-change reset, ARIA parity, no-options copy, off-catalog substring commit, stale-cost-field, off-catalog interleaving, chain tracking, keyboard selection, clearable-disabled, off-catalog punctuation variant).tsc -p .passes.Dogfooding
Storybook was run locally and the user-facing flows were exercised end-to-end via
agent-browser, capturing screenshots for:5.4filters to GPT-5.4 / 5.4 mini / 5.4 nano).Model ID is required.error.aria-invalid="true"andaria-describedbymatching the rendered error element.No matching known models. You can still use this identifier.copy.📋 Implementation Plan
Plan: Known Model autocomplete and frontend-only defaults for Chat Model Admin
Goal
Improve the admin Add Model onboarding flow by replacing the blank Model Identifier experience with provider-scoped Known Model discovery suggestions for native OpenAI and Anthropic providers. Selecting a Known Model, or typing an exact canonical Known Model identifier and blurring the field, should prefill safe objective model metadata in the existing form without changing backend APIs, database schema, or runtime behavior.
The primary UX goal is discovery for admins who do not know exact provider model identifiers or metadata. Typing convenience is a secondary benefit.
Evidence and current code facts
Inputinsite/src/pages/AgentsPage/components/ChatModelAdminPanel/ModelForm.tsx. It submits asmodeland is only validated as a non-empty string.ModelsSection.tsxkeys the form by provider, so provider changes remountModelForm.site/src/components/Autocomplete/Autocomplete.tsxprimitive already supports free-text input with suggestions and is the right UI primitive for this feature.modelConfigFormLogic.tsowns form initialization viabuildInitialModelFormValues(...), andmodelConfigFormLogic.test.tsalready covers this pure logic area.(provider, model)index, not a uniqueness constraint. Multiple Model Configs can share the same Provider and Model Identifier, so suggestions must not hide already-configured models.models.dev/api.jsonhas provider-keyed model metadata with canonical IDs, names, limits, pricing, release dates, andlast_updatedvalues. The Phase 1 catalog should copy a curated subset into TypeScript records, not fetch at runtime.Domain language
Use these terms consistently in code, tests, docs, and review discussion:
openaioranthropic.model, such asgpt-5.5.Resolved design decisions
UX scope
Autocompleteonly when all are true:openaior nativeanthropic;Suggestion behavior
No matching known models. You can still use this identifier.1.05M context.200K context,400K context, and1.05M context.Recommendedbadge.Canonical IDs and aliases
gpt-5.5orclaude-sonnet-4-6.best,cheap,fast,coding, orreasoning.Default application rules
gpt-5.5while the admin is typinggpt-5.5-pro.initialValuesRefatModelFormmount/remount and compare against that snapshot for safe default application. Do not compare against a live Formik reference that can drift.appliedFieldstracks populated metadata/form paths only, not themodelfield change caused by selecting a Known Model.appliedFields.length > 0, such as:Defaults applied from GPT-5.5. Review and adjust before saving.Initial Model Catalog
Use curated TypeScript records with source metadata copied from models.dev. Do not check in the full
models.dev/api.jsonsnapshot and do not add a generator in Phase 1. Add a file-level comment that array order controls suggestion order so future cleanup does not accidentally change onboarding UX.Initial native OpenAI entries, in display order:
gpt-5.5gpt-5.5-progpt-5.4gpt-5.4-minigpt-5.4-nanogpt-5.3-codexInitial native Anthropic entries, in display order:
claude-opus-4-7claude-opus-4-6claude-sonnet-4-6claude-haiku-4-5claude-sonnet-4-5Do not include GPT-4.x, pre-5.3 GPT models, or Claude models older than 4.5 in this onboarding catalog unless product intentionally expands scope.
Each Known Model record should include:
sourceName: "models.dev",sourceRetrievedAt, and the model record'slast_updatedvalue;contextLimitfromlimit.context;maxOutputTokensfromlimit.output;cost.*fields.Field mapping
models.dev.limit.contextmaps tocontextLimit.models.dev.limit.outputmaps to the selected provider's exact max-output-tokens field when one exists, otherwise to genericconfig.maxOutputTokens.models.dev.limit.inputunless the current form schema already exposes an exact matching field.cost.input;cost.output;cost.cache_read;cost.cache_write.pricingFields.tsor the existing pricing field descriptors instead of hard-coding cost form paths.cache_readorcache_writeis absent from a models.dev entry, leave the corresponding field at its initial value and do not include it inappliedFields.context_over_200kin Phase 1. Add a code comment in the adapter explaining that Coder currently persists flat pricing only.compressionThresholdfrom Known Models.reasoningEffortandreasoningSummary;sendReasoning,effort, andthinking.budgetTokens.Proposed file structure
Use
knownModels/rather thanmodelDefaults/because the data powers both discovery and default application.New files:
site/src/pages/AgentsPage/components/ChatModelAdminPanel/knownModels/types.tssite/src/pages/AgentsPage/components/ChatModelAdminPanel/knownModels/openai.tssite/src/pages/AgentsPage/components/ChatModelAdminPanel/knownModels/anthropic.tssite/src/pages/AgentsPage/components/ChatModelAdminPanel/knownModels/index.tssite/src/pages/AgentsPage/components/ChatModelAdminPanel/knownModels/applyKnownModelDefaults.tssite/src/pages/AgentsPage/components/ChatModelAdminPanel/ModelIdentifierField.tsxExisting files to modify:
site/src/pages/AgentsPage/components/ChatModelAdminPanel/ModelForm.tsxsite/src/pages/AgentsPage/components/ChatModelAdminPanel/modelConfigFormLogic.tssite/src/pages/AgentsPage/components/ChatModelAdminPanel/modelConfigFormLogic.test.tssite/src/pages/AgentsPage/components/ChatModelAdminPanel/ChatModelAdminPanel.stories.tsxDocumentation artifacts to keep in sync if implementing from a clean workspace:
site/src/pages/AgentsPage/components/ChatModelAdminPanel/CONTEXT.mdsite/src/pages/AgentsPage/components/ChatModelAdminPanel/docs/adr/0001-frontend-known-model-catalog.mdImplementation plan
Phase 1: Red, define pure behavior first
modelConfigFormLogic.test.tsor a colocatedknownModelstest file for:appliedFieldsoutput that excludes Model Identifier canonicalization;initialValuesRef,lastAppliedProviderModelRef, and inline default-feedback state.gpt-5.5then blurring does not apply defaults a second time;gpt-5.5-prothen blurring applies only pro defaults, never prefixgpt-5.5defaults;Quality gate: targeted unit tests fail for missing implementation.
Phase 2: Green, add Known Model catalog and pure helpers
knownModels/types.tswith readonly types for catalog records and source metadata.knownModels/openai.tsandknownModels/anthropic.tswith the initial catalog entries and file-level refresh comments.knownModels/index.ts.applyKnownModelDefaults(...)as a pure helper that accepts:Quality gate: targeted unit tests pass.
Phase 3: Wire Model Identifier autocomplete UX
Autocomplete integration constraints:
AutocompletewithinputValuefor the free-text Model Identifier string andvalue: KnownModel | nullfor selected suggestions.Autocomplete; do not rely oncmdkinternal filtering onceinputValueis controlled.KnownModel | nullvalue whenever the admin types arbitrary text that no longer corresponds to the selected Known Model.name, validation error rendering,aria-invalid,aria-describedby, disabled state, Formik blur/touched behavior, and submitted request shape.ModelIdentifierField.tsx.Inputmarkup for edit mode, duplicate mode, and unsupported providers.Autocompletewith:modelfield;Autocomplete.modelfield to the canonical ID;Quality gate: Storybook stories compile and the main interaction paths work locally.
Phase 4: Storybook and UX coverage
Add or extend
ChatModelAdminPanel.stories.tsxwith three user-visible flows:GPT-5.5;gpt-5.5is in the input;Claude Opus 4.7;If practical, include one keyboard selection path in Storybook or manual dogfooding:
Quality gate: Storybook interaction tests pass for touched stories.
Phase 5: Refactor and documentation pass
CONTEXT.mdand ADR if implementation changes any design decision captured there.Quality gate: no broad refactors beyond this feature's files.
Validation commands
Use the repo's existing frontend validation commands, scoped where possible:
pnpm -C site test <targeted ChatModelAdminPanel pattern>pnpm -C site test <targeted modelConfigFormLogic pattern>pnpm -C site test:storybookpnpm -C site lint:typespnpm -C site checkIf command names differ in this workspace, inspect
site/package.jsonand use the closest existing targeted commands. Do not claim success until the actual commands run and pass.Dogfooding plan
Primary dogfood path is Storybook because this is a form-level UI improvement using mocked admin data.
GPT-5.5, defaults note appears, fields populate;Claude Opus 4.7, fields populate, reasoning/thinking fields remain blank;ModelsSectionURL state, or provider pages, also run the local UI and record/agents/settings/models?newModel=openaiexercising the same OpenAI flow.Acceptance criteria
Risks and mitigations
Generated with
mux• Model:anthropic:claude-opus-4-7• Thinking:max