feat: add MiniMax-M2.7 and MiniMax-M2.7-highspeed model pricing

Adds FALLBACK_PRICING entries plus display names so MiniMax sessions
show up with the right cost and readable labels when users route MiniMax
through providers like OpenCode. Pricing verified against the live
MiniMax paygo page:

  MiniMax-M2.7           input $0.3/M  output $1.2/M  cache-read $0.06/M  cache-write $0.375/M
  MiniMax-M2.7-highspeed input $0.6/M  output $2.4/M  cache-read $0.06/M  cache-write $0.375/M
This commit is contained in:
iamtoruk 2026-04-21 05:50:52 -07:00
parent 8ee84b0041
commit 81b5cda173
2 changed files with 52 additions and 0 deletions

View file

@ -49,6 +49,8 @@ const FALLBACK_PRICING: Record<string, ModelCosts> = {
'gpt-4.1-nano': { inputCostPerToken: 0.1e-6, outputCostPerToken: 0.4e-6, cacheWriteCostPerToken: 0.1e-6, cacheReadCostPerToken: 0.025e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },
'o3': { inputCostPerToken: 10e-6, outputCostPerToken: 40e-6, cacheWriteCostPerToken: 10e-6, cacheReadCostPerToken: 2.5e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },
'o4-mini': { inputCostPerToken: 1.1e-6, outputCostPerToken: 4.4e-6, cacheWriteCostPerToken: 1.1e-6, cacheReadCostPerToken: 0.275e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },
'MiniMax-M2.7-highspeed': { inputCostPerToken: 0.6e-6, outputCostPerToken: 2.4e-6, cacheWriteCostPerToken: 0.375e-6, cacheReadCostPerToken: 0.06e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },
'MiniMax-M2.7': { inputCostPerToken: 0.3e-6, outputCostPerToken: 1.2e-6, cacheWriteCostPerToken: 0.375e-6, cacheReadCostPerToken: 0.06e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },
}
let pricingCache: Map<string, ModelCosts> | null = null
@ -201,6 +203,8 @@ export function getShortModelName(model: string): string {
'gemini-2.5-pro': 'Gemini 2.5 Pro',
'o4-mini': 'o4-mini',
'o3': 'o3',
'MiniMax-M2.7-highspeed': 'MiniMax M2.7 Highspeed',
'MiniMax-M2.7': 'MiniMax M2.7',
}
for (const [key, name] of Object.entries(shortNames)) {
if (canonical.startsWith(key)) return name

48
tests/minimax.test.ts Normal file
View file

@ -0,0 +1,48 @@
import { describe, it, expect } from 'vitest'
import { getModelCosts, getShortModelName } from '../src/models.js'
// Verifies MiniMax pricing loaded from FALLBACK_PRICING (no network call).
// pricingCache stays null until loadPricing() runs, so getModelCosts falls
// through to FALLBACK_PRICING which is what we want to validate here.
describe('MiniMax model pricing', () => {
it('returns pricing for MiniMax-M2.7', () => {
const costs = getModelCosts('MiniMax-M2.7')
expect(costs).not.toBeNull()
expect(costs!.inputCostPerToken).toBe(0.3e-6)
expect(costs!.outputCostPerToken).toBe(1.2e-6)
expect(costs!.cacheReadCostPerToken).toBe(0.06e-6)
expect(costs!.cacheWriteCostPerToken).toBe(0.375e-6)
expect(costs!.fastMultiplier).toBe(1)
})
it('returns pricing for MiniMax-M2.7-highspeed', () => {
const costs = getModelCosts('MiniMax-M2.7-highspeed')
expect(costs).not.toBeNull()
expect(costs!.inputCostPerToken).toBe(0.6e-6)
expect(costs!.outputCostPerToken).toBe(2.4e-6)
expect(costs!.cacheReadCostPerToken).toBe(0.06e-6)
expect(costs!.cacheWriteCostPerToken).toBe(0.375e-6)
expect(costs!.fastMultiplier).toBe(1)
})
it('highspeed pricing is distinct from base model pricing', () => {
const base = getModelCosts('MiniMax-M2.7')
const fast = getModelCosts('MiniMax-M2.7-highspeed')
expect(fast!.inputCostPerToken).toBeGreaterThan(base!.inputCostPerToken)
expect(fast!.outputCostPerToken).toBeGreaterThan(base!.outputCostPerToken)
})
it('returns short name for MiniMax-M2.7', () => {
expect(getShortModelName('MiniMax-M2.7')).toBe('MiniMax M2.7')
})
it('returns short name for MiniMax-M2.7-highspeed', () => {
expect(getShortModelName('MiniMax-M2.7-highspeed')).toBe('MiniMax M2.7 Highspeed')
})
it('handles MiniMax model ID with date suffix', () => {
expect(getShortModelName('MiniMax-M2.7-20260101')).toBe('MiniMax M2.7')
})
})