Skip to content

feat(llm): odswiez modele i cennik - Claude 5, Gemini 3.7 Flash, GPT-5.6 - #54

Open
mjdch wants to merge 2 commits into
matematicsolutions:mainfrom
mjdch:feat/upgrade-llm-models-pricing
Open

mjdch wants to merge 2 commits into
matematicsolutions:mainfrom
mjdch:feat/upgrade-llm-models-pricing

Conversation

@mjdch

@mjdch mjdch commented Aug 26, 2026

Copy link
Copy Markdown

Summary

Refreshes which LLM models Patron offers and what they cost, replacing every
retired or mispriced entry in the model picker and the usage-panel pricing
table with live-catalog data, verified against the vendor pages and the
OpenRouter catalog on 2026-08-26.

Changes

Backend (backend/)

  • lib/llm/models.ts: CLAUDE_MAIN/MID_MODELS -> Opus 5 / Sonnet 5 (4.x
    removed - same price, weaker model). OPENAI_MAIN/MID/LOW_MODELS -> the
    5.6 family (sol/terra/luna) replacing 5.4/5.5. GEMINI_MAIN_MODELS gains
    gemini-3.7-flash alongside the existing 3-flash-preview (kept because
    it's cheaper direct-from-Google; 3.7 is only cheaper on OpenRouter).
    DEFAULT_MAIN/TITLE/TABULAR_MODEL moved to openrouter/google/gemini-3.7-flash.
    New LEGACY_MODEL_ALIASES in resolveModel() so a lawyer's saved
    tabular_model on a retired id resolves to its successor instead of
    silently falling back to a different vendor's default.
  • lib/llm/pricing.ts: PRICING rewritten keyed by the full model id
    (native and openrouter/... tracked separately) - the previous
    last-segment match never matched OpenRouter's dotted slugs against native
    dashed ids, so every OpenRouter-Anthropic model silently priced as
    "unpriced". Every rate re-sourced from the billing path that actually
    charges it (first-party for the own-key path, OpenRouter catalog for the
    openrouter/ path) rather than one catalog for everything. Retired
    models' price rows are kept (historical llm_route events still need
    pricing) and marked legacy in comments.
  • Tests: per-model pricing coverage, an OpenRouter-mirror-exists check, a
    regression for the dotted-slug match, and three resolveModel alias
    tests. Fixed a stale openrouter.test.ts assertion that used the now-
    retired gpt-5.5 as its example of "a valid native id".

Frontend (frontend/)

  • ModelToggle.tsx: picker entries updated to match (Opus 5 / Sonnet 5,
    Gemini 3.7 Flash added, GPT-5.6 sol/terra/luna), retired entries removed,
    DEFAULT_MODEL_ID synced to the new backend default.

Tooling (.claude/skills/)

  • New upgrade-llm-models skill capturing this as a repeatable playbook:
    the four files that must stay in sync, the decision table (cheaper/same
    -> replace, pricier -> add alongside, no newer model -> leave alone,
    governance blocker -> don't ship), the per-billing-path pricing rule, and
    a bundled script that caches the OpenRouter catalog and prints per-MTok
    prices for one vendor.

Why

Two of the three vendors had a strictly-better replacement sitting unused:
Claude Opus 5 costs exactly what Opus 4.8 cost, and OpenAI's 5.6 family
undercuts 5.4/5.5 by a wide margin (e.g. gpt-5.4-mini $0.75/$4.50 ->
gpt-5.6-luna $0.20/$1.20 for the same role). Gemini had no such upgrade
(3.1 Pro is already current; the newer Flash generation is pricier at
Google's own rates), so it was handled differently - added alongside, not
swapped in, and the OpenRouter route to it was still cheaper so the default
moved there specifically.

No contract promised by the Constitution changes (no SSE event, MCP
citation format, or audit log payload touched).

Testing

  • npm test --prefix backend - 1475 pass / 0 fail / 5 todo (was 1467)
  • npx tsc --noEmit - backend clean
  • npm test --prefix frontend - 43 pass / 0 fail
  • npx tsc --noEmit - frontend clean
  • Manually verified locally: started backend (sqlite/local mode) + frontend
    dev servers, confirmed /account/models compiles and serves 200 with no
    runtime errors in either dev log.

Governance / Constitution AI

  • No contracts were broken (SSE events, MCP citations, audit_log).
  • If a contract changed: ADR added under governance/adr/. (N/A - none changed)
  • If a Constitution principle changed: version bumped in CONSTITUTION.md + changelog row. (N/A)

Tests

  • npm test passes (1475/1475 backend, 43/43 frontend - both grew from baseline).
  • No new lint warnings.
  • tsc --noEmit clean on both backend and frontend.

License confirmation

By opening this PR I confirm my contribution is licensed under
AGPL-3.0-only (Patron shell). I followed the
DCO.

mjdch added 2 commits August 26, 2026 22:27
Wycofane modele kosztowaly tyle samo za slabszy wynik (Anthropic 4.x) albo
byla dostepna nowsza rodzina za wyrazna niedoplate na wlasnym kluczu OpenAI
(5.4 -> 5.6: gpt-5.4-mini 0.75/4.50 -> gpt-5.6-luna 0.20/1.20). Gemini nie
mial takiej okazji - Pro jest juz aktualny, a nowszy Flash jest drozszy w
cenniku Google, wiec zostal dodany obok starego, nie zamiast niego.

- CLAUDE_MAIN_MODELS/MID_MODELS: opus-5, sonnet-5; wycofane 4.x usuniete
  z pickera i z tierow (ta sama stawka 5/25 i 3/15 vs 2/10 za slabszy model).
- OPENAI_MAIN/MID/LOW_MODELS: rodzina 5.6 (sol/terra/luna) zamiast 5.4/5.5.
- GEMINI_MAIN_MODELS: dodany gemini-3.7-flash; 3-flash-preview zostaje bo
  jest tanszy bezposrednio u Google (3.7 jest tansze wylacznie na OpenRouterze).
  DEFAULT_MAIN/TITLE/TABULAR_MODEL przelaczone na openrouter/google/gemini-3.7-flash
  (nowszy i tanszy na tym samym kluczu Operatora).
- resolveModel(): LEGACY_MODEL_ALIASES mapuje kazdy wycofany id (natywny i
  openrouter/) na nastepce, zeby zapisany wybor mecenasa (tabular_model) nie
  spadal cicho na DEFAULT_TABULAR_MODEL, czyli na innego dostawce.
- pricing.ts: PRICING przepisany na klucz PELNEGO id (natywny + openrouter/
  osobno), bo pricingKey() dopasowywal tylko koncowy segment, a slug
  OpenRoutera ma kropki tam gdzie natywne id ma myslniki (nigdy nie trafial,
  model wpadal jako "unpriced"). Wpisy modeli wycofanych ZOSTAJA w tabeli -
  panel kosztow dalej wycenia stare zdarzenia llm_route.
  Zrodlo stawki idzie za sciezka rozliczenia: klucz wlasny -> cennik
  first-party dostawcy (platform.claude.com / ai.google.dev / developers.openai.com),
  openrouter/... -> katalog OpenRoutera. Zweryfikowano rozbieznosc miedzy
  sciezkami (gpt-5.6-sol: OpenRouter 2/10 vs OpenAI first-party 4/20 - realna,
  nie literowka) i promocje z data wygasniecia (gemini-3.7-flash 0.75/3.75
  do 2026-12-31, potem 1.5/7.5).
- Testy: pokrycie kazdego natywnego modelu w cenniku + lustro OpenRoutera +
  regresja na dopasowanie po pelnym id; naprawiony przyklad w openrouter.test.ts
  ktory uzywal wycofanego gpt-5.5 jako "aktualny natywny model".

Backend: 1475 pass / 0 fail / 5 todo (bylo 1467), tsc czysty.
Frontend: 43 pass / 0 fail, tsc czysty.

Swiadomie pominiete: Claude Fable 5 (wymaga 30-dniowej retencji, 400 pod
zero data retention - konfiguracja kancelarii pod tajemnica zawodowa).
Zapisuje jako powtarzalny playbook procedure z poprzedniego commita: cztery
mirrory id modelu ktore musza sie zgadzac, dwie sciezki rozliczenia i ktora
z nich daje cene, alias wycofanego modelu na nastepce zamiast cichego spadku
na DEFAULT, i tabela decyzyjna (tansze/tak samo -> wymien, drozsze -> dodaj
obok, brak nowszego -> nic nie rob, blokada governance -> nie wysylaj).

Dołączony skrypt scripts/catalog-prices.sh cachuje katalog OpenRouter (~700KB)
na dzien i liczy per-Mtok z per-token, zeby nie powtarzac tej samej gimnastyki
jq co refresh.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant