Repository navigation
feat(admin): accept the cache-write price in the model editor - #434
Merged
Merged
Conversation
#433 added `models.cache_write_input_per_m` and made billing charge it, but the admin model editor never wrote the column: a model created or edited at `POST /api/admin/models` (or `PATCH /api/admin/models/:id`) always carried `cache_write_input_per_m = 0`, so an operator billing cache-write tokens had no supported way to set the fifth price through the API. The field now behaves exactly like its sibling prices: present in the create and patch request bodies (default 0, which does not fall back to `input_per_m`), rejected when negative by the same `validate_common` check that guards the other six, written by both the INSERT and the UPDATE, and returned by both readback paths — the single-row SELECT shared by create and patch, and `dao::list_all_models` behind `GET /api/admin/models`. The test creates a model with seven distinct prices so any divergence between a SELECT's column order and its `r.get(i)` indices reddens on the wrong value rather than passing silently.
This was referenced Oct 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
#433 added a fifth model price —
models.cache_write_input_per_m— and made billing charge cache-write (cache-creation) tokens against it. The admin model editor was left out of that change: it never wrote the column, so a model created or edited throughPOST /api/admin/modelsorPATCH /api/admin/models/:idalways carriedcache_write_input_per_m = 0, and an operator who bills cache writes had no supported way to set that price through the API.This closes that gap. The field now behaves exactly like its sibling prices, and nothing beyond that is changed.
Related Issue
None open. #432 was already closed by #433, and this PR closes the deliberate boundary #433 left in its own scope ("the admin model editor does not accept
cache_write_input_per_m"), so there is no issue to close here.Changes
POST /api/admin/modelsandPATCH /api/admin/models/:idacceptcache_write_input_per_m— optional, default0.validate_commonrejects a negative value with the same400the other six prices get. The admin endpoint keeps its own request struct on purpose, soConfig::validateis not reused — importing it would drag config-only fields into an API body.ROW_SELECTshared by the create and patch responses, anddao::list_all_modelsbehindGET /api/admin/models.cache_hit_input_per_min every column list, matching the ordering feat(billing): bill cache-write (cache-creation) tokens #433 established indb.rsanddao::ModelPrice.Tests
cargo test— 583 passed, 0 failed (baseline 582, plus the one new test).cargo fmt --check— clean.cargo clippy --all-targets -- -D warnings— clean (this is the CI invocation).admin_models_cache_write_price_round_trip: create with a value and read it back through both paths; create without the field and get0;PATCHsets it and the response reflects it while the sibling prices stay put; a negative value on either entry point is a400and the rejected write never reaches the database.The test gives all seven prices a distinct value, so a SELECT whose column order drifts from its
r.get(i)indices shows up as the wrong value instead of passing quietly. Checked by mutation: pointing the readback at the neighbouring column yieldsleft: 1.5, right: 0.25and fails the test.Deliberate boundaries
0and does not fall back toinput_per_m— a fallback would silently re-price every deployment that never opted in.seed_modelsstill treatsconfig.toml [[models]]as the source of truth, so an admin-side edit of this price, like every other admin-side edit, is overwritten at the next startup. That is documented behaviour, not a regression introduced here.UsageCapture::finishapplies the OpenAI-shapedinput_tokens - cached_tokenscorrection to a protocol whoseinput_tokensalready excludes cache reads. It is pinned by a test today and will land as its own PR, since correcting it raises existing bills.Checklist
feat/)