From 81b5cda173e39d3221a0c475f84317c514eefed7 Mon Sep 17 00:00:00 2001 From: iamtoruk Date: Tue, 21 Apr 2026 05:50:52 -0700 Subject: [PATCH] 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 --- src/models.ts | 4 ++++ tests/minimax.test.ts | 48 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 tests/minimax.test.ts 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') + }) +})