feat(site): show best-effort model pricing on the model form - #28290
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: da823a4f1d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Show a loading placeholder in each cost estimate box while the live price-book query is in flight, and only fall back to the baked-in catalog after a successful response confirms no row exists.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c2a41becc5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Show a load failure message in the cost estimate section instead of falling back to the catalog when the price book request errors, and render positive prices below four decimals as a threshold rather than $0.00 so they are not read as free.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 997dac6fc1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
|
Codex Review: Didn't find any major issues. Delightful! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Documentation CheckUpdates Needed
Automated review via Coder Agents |
johnstcn
left a comment
There was a problem hiding this comment.
Thanks @DanielleMaywood!
Potential follow-up: do we need a premium license banner in case of lack of license entitlement?
Unsure. It does gracefully fall back to the models.dev pricing list that is embedded in the frontend if you don't have a premium license. |
ssncferreira
left a comment
There was a problem hiding this comment.
I think there is a different behaviour here when I'm adding a new model vs when I'm editing an existing model. When I'm adding a new model, the API call only happens once I click somewhere outside the model identifier textbox, however, when I'm editing an existing model, the API call happens whenever I update the model identifier textbox (each new character results in an API call). Is this expected? 🤔
| expect(formatPricePerMillionTokens(0.0001)).toBe("$0.0001"); | ||
| }); | ||
|
|
||
| it("formats zero", () => { |
There was a problem hiding this comment.
nit: should we also add a test that if a price is null it shows as empty?
| const cost = costs?.[key]; | ||
| const fieldId = `${fieldIdPrefix}-${label.toLowerCase().replace(/\s+/g, "-")}`; | ||
| const displayValue = | ||
| cost === undefined ? "" : formatPricePerMillionTokens(cost).slice(1); |

Adds a read-only "Cost estimate" section to the Coder Agents model form (AI Settings > Models > add/edit). It revives the per-token pricing layout removed in #27330, but the fields are immutable and populated rather than editable.
Prices come from the live
GET /api/experimental/ai/model-pricesprice book when the AI Gateway feature is entitled, so admin price overrides are reflected. Otherwise they fall back to the models.dev catalog already bundled for the model identifier autocomplete. A price book row wins outright, a null category means the model bills as zero there, and the catalog only fills in when the model has no row at all. Models with no price data get an empty state instead of a blank box.No backend changes. The model-prices endpoint is enterprise-gated, so unlicensed deployments never call it and see catalog prices, which are always accurate there since overrides cannot exist.
Implementation plan and review notes
Data sources
GET /api/experimental/ai/model-prices(?provider=&model=, exact match, micro-units per million tokens). Used only whenuseFeatureVisibility().aibridge.knownModels/knownModelsGenerated.json, the static models.dev catalog the autocomplete already loads. ItsKnownModeltype carriesinputCost,outputCost,cacheReadCost,cacheWriteCost.Key decisions
coderd/aibridgedserver/cost.go) treats a null price on a present row as "bills as zero", so a row is the deployment's deliberate pricing for that model and the catalog must not fill its null categories.Boolean(useFeatureVisibility().aibridge).aibridgeisundefined(notfalse) when unlicensed, and TanStack only disables whenenabled === false, so without theBoolean()the not-entitled path would still fire a doomed request.readOnlywithoutdisabledso screen readers still announce the values.formatPricePerMillionTokenskeeps two decimals for cents ($0.10) and up to four for sub-cent prices ($0.075,$0.0036) so small prices are not rounded to$0.00.Self-review
Three reviewers (GLM 5.3, Kimi K3, Qwen 3.8 Max) plus an FE1 to FE10 audit. Fixed: sub-cent rounding to
$0.00, the entitlement gate leak, per-field to row-level precedence, per-keystroke requests, empty state, and a vacuous not-entitled test that now asserts the endpoint is not called. 25 story tests and 24 unit tests pass, typecheck and lint clean.