Scrum4Me/docs/plans/sync-model-prices.md
Janpeter Visser eaabec8471
feat(PBI-66): wekelijkse sync van model_prices via Anthropic /v1/models (#167)
Nieuw script `npm run db:sync-model-prices` haalt de actuele Claude 4.x
modellijst op bij de Anthropic API en upsert prijzen in `model_prices`.
Anthropic biedt geen prijs-API, dus prijzen blijven onderhouden in een
PRICE_TABLE constante in het script. Cache-tier-prijzen worden afgeleid
via vaste multipliers (read 0.1x, write 1.25x). Nieuwe Claude 4.x modellen
worden gedetecteerd en gelogd als warning zodat duidelijk is wanneer de
tabel handmatig moet worden bijgewerkt.

- scripts/sync-model-prices.ts: idempotent upsert, --dry-run, retry op 5xx
- ANTHROPIC_API_KEY als optional env-var (.env.example, lib/env.ts)
- scripts/README.md: gebruiksinstructies + edge cases
- docs/plans/sync-model-prices.md: ontwerpdocument

Verificatie: `npm run lint`, `vitest` (563/563), TypeScript clean.
Echt gedraaid tegen DB: 3 created (eerste run) -> 3 unchanged (tweede run).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:38:33 +02:00

4.5 KiB
Raw Permalink Blame History

Plan: wekelijkse sync van model_prices (PBI-66 / ST-1296)

Context

De tabel model_prices (prisma/schema.prisma:465) bevat nu 3 hardcoded rijen via prisma/seed.ts:198 (Opus 4.7, Sonnet 4.6, Haiku 4.5). Die wordt door lib/insights/token-stats.ts en lib/insights/token-history.ts ge-LEFT JOIN-d voor kostberekening.

Probleem: prijzen + nieuwe modellen worden alleen bijgewerkt bij een full re-seed. Dat vergeet je. We willen een wekelijks handmatig draaibaar script dat:

  1. De actuele Claude 4.x modellijst ophaalt bij Anthropic (GET /v1/models),
  2. Per model de prijzen bepaalt uit een onderhouden tabel in code,
  3. Nieuwe modellen detecteert en logt (zodat we weten dat de tabel update nodig heeft),
  4. Idempotent upsert in model_prices.

Belangrijke realiteit: Anthropic biedt geen prijs-API. /v1/models levert id, display_name, max_tokens, capabilities — maar geen pricing. De prijzen onderhouden we daarom als constanten in het script. De API-call dient om de modellijst te valideren en nieuwe modellen op te merken.

Aanpak

Eén nieuw TypeScript-script scripts/sync-model-prices.ts in dezelfde stijl als scripts/insert-milestone.ts:

  • dotenv → DATABASE_URL + ANTHROPIC_API_KEY
  • pg.Pool + PrismaPg adapter + PrismaClient (zelfde patroon als bestaande scripts)
  • --dry-run flag voor preview zonder schrijven
  • Aangeroepen via npm run db:sync-model-prices

Datastromen

ANTHROPIC API /v1/models
        │
        ▼  (filter: model_id matcht /^claude-(opus|sonnet|haiku)-4/)
   API model list ───────────┐
                             │
   PRICE_TABLE (in script) ──┤── join op model_id
                             │
                             ▼
                    Per model:
                    - input_price = PRICE_TABLE[id].input
                    - output_price = PRICE_TABLE[id].output
                    - cache_read_price = input * 0.1
                    - cache_write_price = input * 1.25
                             │
                             ▼
                  prisma.modelPrice.upsert

PRICE_TABLE in script

const PRICE_TABLE: Record<string, { input: number; output: number }> = {
  'claude-opus-4-7': { input: 15.0, output: 75.0 },
  'claude-sonnet-4-6': { input: 3.0, output: 15.0 },
  'claude-haiku-4-5-20251001': { input: 0.8, output: 4.0 },
}

const CACHE_READ_RATIO = 0.1
const CACHE_WRITE_RATIO = 1.25 // 5-minute cache write

Cache-ratio's komen overeen met de huidige seed: 1.5/15 = 0.1 en 18.75/15 = 1.25 — dus geen waarde-shift voor bestaande rijen.

Filter Claude 4.x

Regex op id uit de API: /^claude-(opus|sonnet|haiku)-4/. Dit matcht claude-opus-4-7, claude-sonnet-4-6, claude-haiku-4-5-20251001 en toekomstige 4.x varianten. Filtert oudere 3.x modellen weg.

Detectie nieuwe modellen

Per Claude 4.x model uit de API:

  • In PRICE_TABLE → upsert met de prijs
  • Niet in PRICE_TABLE → log warning, sla over, exit code blijft 0

Bestanden

Bestand Actie
scripts/sync-model-prices.ts Nieuw — sync-script
package.json Wijzigen — entry "db:sync-model-prices" toevoegen
.env.example WijzigenANTHROPIC_API_KEY="" toevoegen
lib/env.ts WijzigenANTHROPIC_API_KEY als optional env var
scripts/README.md Wijzigen — sectie "Sync model prices" toevoegen
prisma/seed.ts regels 198229 Behouden — fallback voor verse DB

Edge cases

Geval Gedrag
ANTHROPIC_API_KEY ontbreekt Error + exit 1
API geeft 401 Error met hint "controleer API key"
API geeft 5xx Retry 1× met 2s delay, dan falen
API levert 0 Claude 4.x modellen Warning, exit 1
Model uit DB staat niet meer in API Niet verwijderen — alleen loggen
--dry-run API-call gewoon doen, alleen geen upsert

Verificatie

npm run db:sync-model-prices -- --dry-run
npm run db:sync-model-prices
psql $DATABASE_URL -c "SELECT model_id, input_price_per_1m, output_price_per_1m, updated_at FROM model_prices ORDER BY model_id"
npm run lint && npm test && npm run build

Buiten scope

  • Geen Vercel cron route — bewust gekozen: handmatig draaien geeft moment om PRICE_TABLE bij te werken.
  • Geen pricing-page scraping — fragiel.
  • Geen 1-uurs cache write tier — schema heeft één veld.