|
| 1 | +// npx vitest run src/api/providers/__tests__/gemini-tier-config.spec.ts |
| 2 | + |
| 3 | +import { geminiModels } from "@roo-code/types" |
| 4 | + |
| 5 | +describe("Gemini 2.5 Pro Tier Configuration", () => { |
| 6 | + const gemini25ProModels = [ |
| 7 | + "gemini-2.5-pro", |
| 8 | + "gemini-2.5-pro-preview-03-25", |
| 9 | + "gemini-2.5-pro-preview-05-06", |
| 10 | + "gemini-2.5-pro-preview-06-05", |
| 11 | + ] as const |
| 12 | + |
| 13 | + gemini25ProModels.forEach((modelId) => { |
| 14 | + describe(`${modelId}`, () => { |
| 15 | + it("should have a free tier with 125k context window", () => { |
| 16 | + const model = geminiModels[modelId] |
| 17 | + expect(model).toBeDefined() |
| 18 | + expect(model.tiers).toBeDefined() |
| 19 | + expect(model.tiers!.length).toBeGreaterThanOrEqual(3) |
| 20 | + |
| 21 | + // Check the first tier is the free tier |
| 22 | + const freeTier = model.tiers![0] |
| 23 | + expect(freeTier.contextWindow).toBe(125_000) |
| 24 | + expect(freeTier.inputPrice).toBe(0) |
| 25 | + expect(freeTier.outputPrice).toBe(0) |
| 26 | + expect(freeTier.cacheReadsPrice).toBe(0) |
| 27 | + }) |
| 28 | + |
| 29 | + it("should have correct tier ordering", () => { |
| 30 | + const model = geminiModels[modelId] |
| 31 | + const tiers = model.tiers! |
| 32 | + |
| 33 | + // Verify tier ordering: 125k (free) -> 200k -> Infinity |
| 34 | + expect(tiers[0].contextWindow).toBe(125_000) |
| 35 | + expect(tiers[1].contextWindow).toBe(200_000) |
| 36 | + expect(tiers[2].contextWindow).toBe(Infinity) |
| 37 | + }) |
| 38 | + |
| 39 | + it("should have correct pricing for paid tiers", () => { |
| 40 | + const model = geminiModels[modelId] |
| 41 | + const tiers = model.tiers! |
| 42 | + |
| 43 | + // 200k tier pricing |
| 44 | + expect(tiers[1].inputPrice).toBe(1.25) |
| 45 | + expect(tiers[1].outputPrice).toBe(10) |
| 46 | + expect(tiers[1].cacheReadsPrice).toBe(0.31) |
| 47 | + |
| 48 | + // Infinity tier pricing |
| 49 | + expect(tiers[2].inputPrice).toBe(2.5) |
| 50 | + expect(tiers[2].outputPrice).toBe(15) |
| 51 | + expect(tiers[2].cacheReadsPrice).toBe(0.625) |
| 52 | + }) |
| 53 | + |
| 54 | + it("should trigger context condensing before hitting 125k limit", () => { |
| 55 | + const model = geminiModels[modelId] |
| 56 | + const freeTierLimit = model.tiers![0].contextWindow |
| 57 | + |
| 58 | + // With a typical context condensing threshold of 50-80%, |
| 59 | + // the condensing should trigger well before reaching 125k tokens |
| 60 | + const typicalCondenseThreshold = 0.7 // 70% |
| 61 | + const expectedTriggerPoint = freeTierLimit * typicalCondenseThreshold |
| 62 | + |
| 63 | + // Verify that the free tier limit is correctly set to prevent 429 errors |
| 64 | + expect(freeTierLimit).toBe(125_000) |
| 65 | + expect(expectedTriggerPoint).toBeLessThan(freeTierLimit) |
| 66 | + expect(expectedTriggerPoint).toBe(87_500) // 70% of 125k |
| 67 | + }) |
| 68 | + }) |
| 69 | + }) |
| 70 | + |
| 71 | + describe("Other Gemini models", () => { |
| 72 | + it("should not have free tier for non-2.5-pro models", () => { |
| 73 | + // Check a few other models to ensure we didn't accidentally add free tier to them |
| 74 | + const otherModels = [ |
| 75 | + "gemini-2.0-flash-001", |
| 76 | + "gemini-1.5-flash-002", |
| 77 | + "gemini-2.0-flash-thinking-exp-01-21", |
| 78 | + ] as const |
| 79 | + |
| 80 | + otherModels.forEach((modelId) => { |
| 81 | + const model = geminiModels[modelId] |
| 82 | + if ("tiers" in model && model.tiers) { |
| 83 | + // If tiers exist, verify none have 125k context window |
| 84 | + const has125kTier = model.tiers.some((tier: any) => tier.contextWindow === 125_000) |
| 85 | + expect(has125kTier).toBe(false) |
| 86 | + } |
| 87 | + }) |
| 88 | + }) |
| 89 | + }) |
| 90 | +}) |
0 commit comments