anomalyco / anomalyco/models.dev
Cost schema cannot express time-based pricing (peak/off-peak), so estimates diverge from actual billing
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 6.9k
- Forks
- 1.7k
- Avg merge
- 3h 21m
- Merged PRs (30d)
- 873
Description
DeepSeek V4 bills peak/off-peak (peak 01:00–04:00 and 06:00–10:00 UTC, Mon–Fri; off-peak exactly half). #4891 works around this by storing the peak rate in [cost] and documenting the windows in a comment — reasonable given the current schema, but any flat rate is 2× off in one of the windows. Billing-level example: a session I reconciled against the provider's invoice was billed at exactly the peak rates during the peak window; the same session run off-peak would be estimated 2× above its bill with #4891's data.
CostTier already has a discriminated tier.type (z.literal("context"), packages/core/src/schema.ts), and consumers already select tiers at calculation time (opencode does this for context tiers in packages/opencode/src/session/session.ts, which carries a TODO: "update models.dev to have better pricing model"). A time tier would follow the same pattern:
[cost]
# base rates = off-peak (or peak — naming decision)
input = 0.66
output = 1.98
cache_read = 0.022
[[cost.tiers]]
input = 1.32
output = 3.96
cache_read = 0.044
[cost.tiers.tier]
type = "time"
windows = [
{ days = ["mon","tue","wed","thu","fri"], from = "01:00", to = "04:00" },
{ days = ["mon","tue","wed","thu","fri"], from = "06:00", to = "10:00" },
]
timezone = "UTC"
Design questions before any code:
- Explicit per-window rates vs multiplier (DeepSeek is exactly ½ off-peak; a
multiplier = 0.5on the tier is compact, explicit rates generalize better). - Base-rate semantics: is
[cost]the list price (peak) with tiers as discounts, or the floor (off-peak) with tiers as surcharges? #4891 argues list price; consumers that ignore tiers would then overestimate rather than underestimate — is overestimation the preferred failure mode? (I'd say yes.) - Compatibility:
Cost/CostTierare.strict(), so old SDK builds reject atimetier outright — data using it can't ship until consumers that validate are updated. How has the project handled adding discriminator values before — engine support first, data later? - Scope: timezone-aware windows only (provider schedules are published in UTC; DST/holiday calendars feel out of scope).
Context: opencode's pricing-correctness threads stalled (anomalyco/opencode#7387 auto-closed, RFC #12377 closed, PR #7763 closed unmerged), so this issue is also a place to decide the consumer-side rollout. I can prepare the schema PR plus the opencode engine change (timestamp-based tier selection) once the shape is agreed.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with CostTier in packages/core/src/schema.ts and the context-tier selection in packages/opencode/src/session/session.ts. Resolve the tier shape, base-rate semantics, compatibility order, and timezone scope before implementation. Done means the schema and consumer rollout decisions are agreed and the timestamp-based selection work has a defined path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100