Repository navigation
fix(opencode): price long-context steps at the catalog tier, including config-named models - #34
Merged
Merged
Conversation
A config entry that names a catalog model rebuilt cost from input, output and cache only, dropping the catalog's tiers and experimentalOver200K, so every step above 200K context was priced at the base rate. Carry both through, and map a config context_over_200k when one is given. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 2 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
|
The following comment was made by an LLM, it may be inaccurate: |
…k itself Session.getUsage consults cost.tiers before experimentalOver200K, so a config entry that supplied its own context_over_200k would still be priced at the catalog tier above that tier's size. When config prices the long-context range itself, the merged model now carries no catalog context tiers, and the override test asserts the price through Session.getUsage at 300K tokens. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Author
|
/devin review |
…g cost converter The config cost shape is a structural subset of the models.dev cost, so the existing cost() helper builds experimentalOver200K instead of a second hand-copied mapping. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Author
|
/devin review |
… price Dropping every catalog tier lost sub-200K tiers such as grok-4's 128K tier, while keeping them would let them outrank the configured price above 200K because Session.getUsage consults tiers first. The config context_over_200k is now carried as a 200K context tier above the catalog tiers below it, mirroring the v1 config migration. Covered at 100K, 150K and 300K tokens against the fixture's x-ai/grok-4. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Author
|
/devin review |
…er-200k field models.dev spells a model's single long-context tier as context_over_200k even when its tiers place the threshold elsewhere: OpenRouter's override for openai/gpt-5.4 and gpt-5.6-terra starts at 272K, Gemini 3.1 Pro at 200K. Session.getUsage consults tiers first but falls back to experimentalOver200K below the tier size, so a 250K-token step on gpt-5.x was priced at the tier rate while OpenRouter bills it at base. The catalog converter now sets experimentalOver200K only when the model has no tiers, which makes catalog-only and config-named models agree. Tracks the same defect as anomalyco#44224. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Author
|
/devin review |
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Author
|
/devin review |
goleary
added a commit
that referenced
this pull request
Sep 2, 2026
#35) Andrew's simplification of #34: a single price() maps models.dev and config cost shapes to {input, output, cache}, the merge no longer sets experimentalOver200K alongside a config-derived 200K tier, and the two override tests collapse into one covering gpt-5.4 and grok-4. Co-Authored-By: Andrew Wang <andrew@replo.app>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Steps that run above a model's long-context threshold are now priced at the provider's tier instead of the base rate, so the
costrecorded on each assistant message matches what OpenRouter actually bills. The threshold is per model: OpenRouter'spricing.overridesstarts at 272K foropenai/gpt-5.6-terraandopenai/gpt-5.4, at 200K forgoogle/gemini-3.1-pro-preview, andanthropic/claude-sonnet-5has none.Context
Replo's sandbox config declares every selectable model under
provider.openrouter.models(most entries are just{ options: {} }). When a config entry names a model that also exists in the models.dev catalog, the merge inprovider.tsrebuildscostfrominput,outputandcacheonly —tiersandexperimentalOver200Knever make it onto the merged model, even though the catalog carried them andsession.tswould have used them.Found while comparing GPT-5.6 Terra to Sonnet on the agent-models dashboard: our recorded Terra cost fit flat base pricing to six decimals across 2,229 steps, while OpenRouter's analytics API billed the >200K tier. Recomputing our steps with the tier landed within 5% of the invoice; flat was 18% short. Pairs with replohq/andytown#26545, which pins a 200K compaction ceiling so Terra stops reaching the tier in the first place; this change keeps the cost honest for any model that still does.
Changes
tiersfrom the catalog model, so a config entry that only names a model prices its long-context steps at the catalog tier.context_over_200k, that price has to win everywhere above 200K, butSession.getUsageconsultstiersbeforeexperimentalOver200K. The merge keeps catalog tiers below 200K and carries the configured price as a 200K context tier above them, the same shape the v1 config migration uses. The override maps through the existingcost()converter.context_over_200keven when itstiersput the threshold at 272K, andSession.getUsagefalls back to that field below the tier size, so a 250K step on gpt-5.x was priced at the tier rate while OpenRouter bills it at base. The catalog converter now setsexperimentalOver200Konly when the model has notiers, which keeps catalog-only and config-named models in agreement. Upstream tracks this as Local cost estimate uses the 200k price below a model's real context threshold anomalyco/opencode#44224.Testing Done
it.instancecases intest/provider/provider.test.ts, each priced throughSession.getUsage: a config entry that only namesopenrouter/openai/gpt-5.4keeps the fixture's 272K tier, drops the legacy field, and prices 250K tokens at base and 300K at the tier; a config entry with its owncontext_over_200kreplaces the catalog's 272K tier with a 200K tier and prices 300K at the configured rate; a config override onx-ai/grok-4keeps the fixture's 128K tier and prices 100K, 150K and 300K at base, 128K-tier and configured rates. Each fails without its source change.bun run typecheckclean.No release is cut here; this lands in the next
v1.17.14-Ntag perRELEASING.md, and the andytown Dockerfile and sandbox-upgrader pins move separately.Summary by cubic
Model cost merging now follows each provider’s context-tier thresholds instead of pricing config-named models at the base rate or applying long-context pricing too early. A configured
context_over_200kprice becomes the 200K tier while preserving catalog tiers below it.context_over_200kis used only when the model has no explicit context tiers.bun run typecheckpasses.Written for commit 34663af. Summary will update on new commits.