diff --git a/src/models.ts b/src/models.ts index bc5d6f6..baa8f04 100644 --- a/src/models.ts +++ b/src/models.ts @@ -49,6 +49,8 @@ const FALLBACK_PRICING: Record = { '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 | 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 diff --git a/tests/minimax.test.ts b/tests/minimax.test.ts new file mode 100644 index 0000000..043027e --- /dev/null +++ b/tests/minimax.test.ts @@ -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') + }) +})