fix: stop a revision variant inheriting its base family's rate

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
hugocasa
2026-08-18 16:37:24 +02:00
co-authored by Claude Opus 5
parent eee162b7c3
commit 9dbb5e237d
2 changed files with 12 additions and 0 deletions
@@ -150,6 +150,11 @@ export function buildModelMatchers<T>(
// a shipped default; `gpt-5-preview-pro` would be a different one again).
// Off by default: for a context window an inherited value is a safe
// approximation, for a price it is a wrong number.
// A further revision segment (`gpt-5` vs `gpt-5-4-mini`) is a different model
// too, and the entry-ends-on-a-digit guard above does not catch it once the
// separator is normalized. Only a short segment: a date is digits as well
// (`-20251101`) and stays a decoration.
strictVariants ? '(?!-\\d{1,3}(?:$|-))' : '',
strictVariants
? `(?!-(?!(?:v\\d|${DECORATIVE_SUFFIXES.join('|')})$)[a-z])`
: ''
@@ -36,6 +36,11 @@ describe('resolveModelPrice', () => {
expect(resolveModelPrice('openai', 'gpt-5-pro', undefined)).toBeUndefined()
expect(resolveModelPrice('openai', 'gpt-5.6', undefined)).toBeUndefined()
expect(resolveModelPrice('googleai', 'gemini-3.1', undefined)).toBeUndefined()
// A revision carrying a variant has to be caught by the matcher, not by an
// explicit entry: `gpt-5.4-mini` cannot match the `gpt-5.4` one (the `-mini`
// makes it a sub-model), so nothing but the guard stops it reaching `gpt-5`.
expect(resolveModelPrice('openai', 'gpt-5.4-mini', undefined)).toBeUndefined()
expect(resolveModelPrice('openai', 'gpt-5.5-pro', undefined)).toBeUndefined()
})
it('still resolves the route decorations that name the same model', () => {
@@ -43,6 +48,8 @@ describe('resolveModelPrice', () => {
// not sub-models. `claude-3-5-haiku-latest` is a shipped picker default, so
// unpricing it would silently disable cost tracking out of the box.
expect(resolveModelPrice('anthropic', 'claude-opus-4-5-20251101', undefined)?.price.input).toBe(5)
// The revision guard must not swallow a date, which is digits too.
expect(resolveModelPrice('openai', 'gpt-5-2026-01-01', undefined)?.price.input).toBe(1.25)
expect(
resolveModelPrice('bedrock', 'anthropic.claude-sonnet-4-6-20250101-v1:0', undefined)?.price
.input