GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — feat: add organization AI model price API by SasSwart · Pull Request #30720 · coder/coder

Conversation

@SasSwart

@SasSwart SasSwart commented Oct 13, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Adds experimental, AI Gateway licensed routes to manage an organization's AI model prices: GET, POST and DELETE on /api/experimental/organizations/{organization}/ai/model-prices. They authorize against ResourceAiModelPrice.InOrg(org), so only owners and org admins can use them. The site-wide routes are unchanged.

  • GET returns one of the organization's prices, keyed by provider_id and model in the query string. It returns 404 when there is no such price.
  • POST sets one price: provider_id (a live provider), model and the four prices. Invalid requests return 400 and write nothing.
  • DELETE takes the same key as GET. The key is in the query string because model names can contain slashes.

Adds the matching codersdk types and ExperimentalClient methods. Swagger, API docs and TypeScript types are regenerated.

This is the top of the stack. Closes AIGOV-612. Replaces #30690 and #30396.


This PR was generated by Coder Agents on behalf of @SasSwart.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@linear-code

linear-code Bot commented Oct 13, 2026

Copy link
Copy Markdown

AIGOV-612

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@SasSwart SasSwart mentioned this pull request Oct 13, 2026
refactor(enterprise/coderd): extract AI model price body decoding and validation #30716
Merged
@github-actions github-actions Bot assigned SasSwart Oct 13, 2026
This was referenced Oct 13, 2026
feat(coderd/database): add organization AI model config table #30717
Merged
feat(coderd): add queries for organization AI model prices #30718
Merged
feat(coderd): price token usage with organization prices #30719
Merged
feat: add organization-scoped AI model prices #30690
Closed
@SasSwart
SasSwart added this pull request to stack #30737 October 14, 2026 06:51
@SasSwart
SasSwart force-pushed the sdlcgraph/aigov-612-5-api branch from 2bb1898 to fca688a Compare October 14, 2026 12:42
@SasSwart
SasSwart force-pushed the sdlcgraph/aigov-612-5-api branch from fca688a to 1c1f8ee Compare October 15, 2026 07:53
@SasSwart
SasSwart force-pushed the sdlcgraph/aigov-612-5-api branch from 1c1f8ee to 3f3c081 Compare October 15, 2026 11:12
@SasSwart
SasSwart force-pushed the sdlcgraph/aigov-612-5-api branch from 3f3c081 to f2a98ad Compare October 16, 2026 10:22
@SasSwart
SasSwart force-pushed the sdlcgraph/aigov-612-5-api branch from f2a98ad to dbad92e Compare October 19, 2026 08:56
SasSwart added a commit that referenced this pull request Oct 19, 2026
@SasSwart
refactor(enterprise/coderd): extract AI model price body decoding and…
41e5b2d
… validation (#30716)

Moves request body decoding and per-price validation out of the
site-wide `upsertAIModelPrices` handler, so the organization price
handler later in this stack can reuse them.

- The handler still reads the body and writes the HTTP errors.
`writeAIModelPricesBodyReadError` picks 413 or 400.
- `decodeAIModelPricesBody` only decodes, and returns an error.
- `aiModelPriceKeys` holds the JSON keys present in one price, so
validation can tell an explicit `null` apart from a missing price.
- `validateAIModelPriceValues` checks the four prices of one model
price. It takes them as an `aiModelTokenPrices` struct, so callers set
each price by name and cannot pass them in the wrong order.

No behavior change. The existing `TestUpsertAIModelPrices`,
`TestListAIModelPrices` and `TestValidateAIModelPrices` cover the
site-wide handler.

**Used later:** #30720 reuses the body read error, the price keys and
the value validation for its single-price upsert.

---

*This PR was generated by Coder Agents on behalf of @SasSwart.*
@SasSwart
SasSwart force-pushed the sdlcgraph/aigov-612-5-api branch 2 times, most recently from 19145a1 to d280997 Compare October 19, 2026 12:22
SasSwart added 5 commits October 21, 2026 06:30
@SasSwart
feat(coderd): add queries for organization AI model prices
117bf23
@SasSwart
feat(coderd/database): drop organization provider type price queries
4f65379
Organization prices are only per configured provider, so remove the
upsert and delete queries for provider type prices and their listing
branch.
@SasSwart
feat(coderd/database): upsert one organization AI model price at a time
bf4938d
Org admins edit prices one model at a time, so the upsert takes typed
params instead of a JSON batch. The org price listing tells organization
and site-wide rows apart by provider_id instead of a price kind.
@SasSwart
feat(coderd/database): keep organization AI model price queries to CRUD
0caf54d
Replace GetOrganizationAIModelPrices, which listed every price that
applies to an organization, with GetOrganizationAIProviderModelPrice,
which reads one price by organization, provider and model. Queries
target the renamed ai_model_configs table.

Split the tests per query, and cover that an identical upsert leaves
updated_at unchanged and that an empty model is rejected.

Leave a TODO to authorize these queries against a resource for AI
Governance model config rather than ResourceAiModelPrice.
@SasSwart
feat(coderd/database): soft delete organization AI model prices
1e4ae6b
DeleteOrganizationAIProviderModelPrice now flags the live row as deleted
instead of removing it. Reads and upserts only match live rows, so an
upsert after a delete inserts a new live row and leaves the soft-deleted
one untouched.
@SasSwart
SasSwart force-pushed the sdlcgraph/aigov-612-5-api branch from d280997 to 09b9751 Compare October 21, 2026 06:38
SasSwart added 3 commits October 21, 2026 07:18
@SasSwart
test(coderd/database): pass the subtest context to the upsert price h…
6140bcb
…elper

The get helper captured the parent test's context and testing.T, which
paralleltestctx flags once the subtests call t.Parallel.
@SasSwart
feat(coderd): price token usage with organization prices
6c5f0ad
@SasSwart
feat(coderd/database): drop organization provider type prices from lo…
e5b34f1
…okup

The lookup now ranks an organization's price for the configured provider,
then site-wide custom and default prices.
SasSwart added 7 commits October 21, 2026 07:18
@SasSwart
feat(coderd): simplify organization AI model price lookup
642f168
Drop the price kind from the lookup and token usage records, remove the
unused GetAIModelPriceByProviderModel query, and stop counting
organization prices in the unpriced-models report until they apply at
runtime.
@SasSwart
feat(coderd): read organization prices from ai_model_configs
c72d1b2
Follow the rename of the organization price table to ai_model_configs.
Link the TODO for passing the organization to the price lookup to
AIGOV-716.
@SasSwart
fix(coderd/database): ignore soft-deleted organization prices in lookup
ae98f91
GetAIModelPriceForProvider read ai_model_configs without the deleted
filter, so a deleted organization price kept pricing token usage
instead of falling back to the site-wide price.
@SasSwart
feat: add organization AI model price API
64bb60b
@SasSwart
feat: price organization AI models only per configured provider
3165306
Organization upserts and deletes take a required provider_id. The
provider type field and the organization_provider_type scope are gone.
@SasSwart
feat: set one organization AI model price per request
897cf4f
POST on the organization route takes a single price for one configured
provider, matching how org admins edit prices. The listing scope comes
from provider_id now that the price kind is gone.
@SasSwart
feat: get one organization AI model price per request
753930e
GetOrganizationAIModelPrices is gone, so the organization GET route now
returns one price, keyed like DELETE by the provider_id and model query
parameters, and 404s when the organization has no such price.
OrganizationAIModelPrice drops the fields that only described a merged
listing: scope, provider type, provider name, and source.

Validate the organization price through aiModelTokenPrices.
@SasSwart
SasSwart force-pushed the sdlcgraph/aigov-612-5-api branch from 09b9751 to 753930e Compare October 21, 2026 07:20
@SasSwart
fix(codersdk): annotate the organization AI model price key provider …
40bff47
…ID as a UUID

TestSDKFieldsFormatted requires uuid.UUID fields to carry format:"uuid".
SasSwart added a commit that referenced this pull request Oct 22, 2026
@SasSwart
feat(coderd): add queries for organization AI model prices (#30718)
da78c88
Adds the store queries for organization AI model prices in
`ai_model_configs`, with authorization. They cover basic CRUD on one
price, keyed by `(organization_id, provider_id, model)`.

- `GetOrganizationAIProviderModelPrice` reads one price.
- `UpsertOrganizationAIProviderModelPrice` sets one price, with typed
params. It rewrites an existing row only when a price differs, so
`updated_at` records the last change.
- `DeleteOrganizationAIProviderModelPrice` soft deletes one price. Reads
and upserts only match live rows, so setting a price after a delete
inserts a new live row.

All three authorize against `ResourceAiModelPrice.InOrg(org)`. The new
`AiModelPriceInOrg` case in `TestRolePermissions` pins that only owners
and org admins pass. A TODO in dbauthz notes that this should become a
resource for AI Governance model config.

Each query has its own test. The upsert tests cover that identical
prices leave `updated_at` unchanged, that changed prices advance it, and
that an empty model is rejected.

**Used later:** #30719 seeds its lookup tests with the upsert. #30720
serves all three through the org price API.

---

*This PR was generated by Coder Agents on behalf of @SasSwart.*
Base automatically changed from sdlcgraph/aigov-612-4-lookup to main October 22, 2026 15:13
SasSwart added a commit that referenced this pull request Oct 22, 2026
@SasSwart
feat(coderd): price token usage with organization prices (#30719)
837c2e1
Prices token usage by the most specific match: the organization's price
for the configured provider, then a site-wide custom price, then the
price book. The requested model is still preferred over the model the
provider reports.

- `GetAIModelPriceForProvider` replaces
`GetAIModelPriceByProviderModel`, which is removed. It is one `UNION
ALL` of primary-key lookups, ordered by requested model first, then by
specificity. dbauthz checks `ResourceAiModelPrice`, scoped to the org
when one is given.
- `coderd/aibridge/prices` tests read seeded prices through
`GetAIModelPrices`.

Interceptions don't carry an organization yet, so
`resolveTokenUsageCost` passes none and only site-wide prices apply at
runtime for now (AIGOV-716). Org matching is covered by database tests
with explicit org IDs. For the same reason, the unpriced-models report
still counts only site-wide prices.

**Used later:** prices set through the API in #30720 take effect here
once interceptions carry an organization.

---

*This PR was generated by Coder Agents on behalf of @SasSwart.*
@SasSwart

SasSwart commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

Closing at the author's request.


This comment was generated by Coder Agents.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@SasSwart SasSwart closed this Oct 26, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 26, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Reviewers

@ibetitsmike ibetitsmike Awaiting requested review from ibetitsmike ibetitsmike will be requested when the pull request is marked ready for review ibetitsmike is a code owner
@johnstcn johnstcn Awaiting requested review from johnstcn johnstcn will be requested when the pull request is marked ready for review johnstcn is a code owner
@ssncferreira ssncferreira Awaiting requested review from ssncferreira ssncferreira will be requested when the pull request is marked ready for review ssncferreira is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@SasSwart SasSwart

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@SasSwart
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.