refactor(opencode): one price mapper for catalog and config cost tiers

Merged
GO
2mo ago
+41-100

Follow-up to #34, applying the simplification patch Andrew posted in Slack verbatim. No merge until Andrew and Gabe have reviewed.

Context

#34 landed the tiered-pricing fix with four hand-written mappings from models.dev / config cost shapes (cache_read, cache_write) to the model's { input, output, cache }, and the config merge still set experimentalOver200K alongside the 200K tier it synthesizes from a config context_over_200k, contradicting the converter's rule that the legacy field exists only when a model has no tiers.

Changes

  • One price() mapper handles base cost, catalog tiers, the catalog's context_over_200k, and a config context_over_200k.
  • The merge sets experimentalOver200K to undefined whenever it synthesizes the 200K tier, so catalog-only and config-named models follow the same rule.
  • Every comment is one line.
  • The two config-override tests collapse into one that covers openai/gpt-5.4 (catalog tier at 272K replaced by the 200K tier) and x-ai/grok-4 (catalog tier at 128K kept below it), priced through Session.getUsage at 150K and 300K.

Testing Done

  • cd packages/opencode && bun test test/provider/provider.test.ts: 97 pass (one fewer test than #34 by design).
  • bun run typecheck in packages/opencode: clean.
  • Behavior is unchanged from #34 except that a config-override model now reports experimentalOver200K: undefined next to its tiers, which Session.getUsage never read in that case.

Patch by Andrew Wang, from the Slack thread on #34.

šŸ¤– Generated with Claude Code


Devin Review

Summary by cubic

Uses one price() mapper to normalize catalog and config cost tiers. Previously, a config context_over_200k override populated both a synthesized 200K tier and experimentalOver200K; now it creates only the tier and clears the legacy field, while usage pricing remains unchanged.

Refactors

  • Reuses price() for base costs, catalog tiers, and long-context overrides.
  • Tests cover replacing the openai/gpt-5.4 catalog tier and retaining the lower x-ai/grok-4 tier.
  • Provider tests pass, and package typechecking is clean.