fix(pricing): price Claude Opus 5, correct Sonnet 5, drop retired models

Claude Opus 5 had no pricing row at all, so every token it burned was costed
at $0 — the pattern list stopped at the 4.x Opus family and nothing matched
`claude-opus-5`. Add it (5/25, fast mode 10/50, same shape as 4.8).

Sonnet 5's launch discount expired 2026-08-31 and the discounted rate became
the published standard, so the row's 3/15 standard rate started overcharging
the day after. Fold 2/10 into DEFAULT_PRICING and empty DEFAULT_INTRO_PRICING;
no model ships a promo today.

Fable/Mythos 5.1 fell through to the `claude-fable-5%` row, which caches at
$1/MTok against 5.1's $0.25 — give them their own rows. That overlap is only
resolvable if the lookup prefers the more specific pattern, and `matchPricing`
took `LIMIT 1` with no ORDER BY, i.e. whichever row was inserted first. Order
by pattern length descending, which is what docs/DATABASE.md already claimed.
(The nested REPLACE(model_pattern, '%', '%') it dropped was a no-op.)

Retire Claude 3.x, Opus 4/4.1 and Sonnet 4 from the defaults. The startup
top-up only ever ADDS missing rows, so removing them from DEFAULT_PRICING
would leave every existing install untouched — prune them once, guarded by
PRAGMA user_version (0 -> 1) so a model deliberately re-added in Settings
survives later restarts. The same one-shot migration corrects the existing
Sonnet 5 row. Only rates are deleted; token_usage is never touched, and
Reset Defaults still restores the full current set.
This commit is contained in:
2026-09-15 15:17:55 +07:00
parent fb3796f064
commit 9128352d1b
2 changed files with 57 additions and 19 deletions
+10 -4
View File
@@ -430,11 +430,17 @@ CREATE TABLE model_pricing (
Standard rates and intro rates are edited independently: the pricing update path writes intro columns only when the caller sends intro fields, so a standard-rate edit never disturbs a promo (and vice versa). Clearing `intro_until` also zeroes the intro rates.
**Example default rule (Claude Sonnet 5, with its launch promo):**
**Example default rules:**
| Pattern | Input | Output | Intro Input | Intro Output | Intro Until |
|---------|-------|--------|-------------|--------------|-------------|
| `claude-sonnet-5%` | $3.00 | $15.00 | $2.00 | $10.00 | `2026-08-31` |
| Pattern | Input | Output | Cache read | Fast in/out |
|---------|-------|--------|------------|-------------|
| `claude-opus-5%` | $5.00 | $25.00 | $0.50 | $10 / $50 |
| `claude-sonnet-5%` | $2.00 | $10.00 | $0.20 | — |
| `claude-fable-5-1%` | $10.00 | $50.00 | $0.25 | — |
No rule ships an intro rate today: Sonnet 5's launch promo ran through `2026-08-31` and its discounted rate became the standard one, so `DEFAULT_INTRO_PRICING` is empty. `claude-fable-5-1%` exists alongside `claude-fable-5%` only because 5.1 caches cheaper — that overlap is what the longest-pattern-first match rule above resolves.
**Retired models.** Claude 3.x, Opus 4/4.1 and Sonnet 4 were dropped from the defaults. Because the startup top-up only *adds* missing rows, those rows are also deleted once from existing databases, guarded by `PRAGMA user_version` (0 → 1) so a model you deliberately re-add in Settings survives later restarts. The same one-shot migration corrects the pre-existing Sonnet 5 row to its post-promo $2 / $10 standard rate. Deleting a rule never touches `token_usage` — only the rates used to price it.
---