Skip to content

Commit e2e4f00

Browse files
committed
fix: add free tier (125k tokens) for Gemini 2.5 Pro models
- Added a new tier with 125k context window for free tier users - This prevents 429 errors when using Gemini 2.5 Pro with the free tier - The free tier has 0 cost for input/output/cache operations - Added comprehensive tests to verify tier configuration Fixes #7753
1 parent 247da38 commit e2e4f00

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

packages/types/src/providers/gemini.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ export const geminiModels = {
7878
cacheReadsPrice: 0.625,
7979
cacheWritesPrice: 4.5,
8080
tiers: [
81+
{
82+
// Free tier: 125k input tokens per minute quota
83+
contextWindow: 125_000,
84+
inputPrice: 0,
85+
outputPrice: 0,
86+
cacheReadsPrice: 0,
87+
},
8188
{
8289
contextWindow: 200_000,
8390
inputPrice: 1.25,
@@ -102,6 +109,13 @@ export const geminiModels = {
102109
cacheReadsPrice: 0.625,
103110
cacheWritesPrice: 4.5,
104111
tiers: [
112+
{
113+
// Free tier: 125k input tokens per minute quota
114+
contextWindow: 125_000,
115+
inputPrice: 0,
116+
outputPrice: 0,
117+
cacheReadsPrice: 0,
118+
},
105119
{
106120
contextWindow: 200_000,
107121
inputPrice: 1.25,
@@ -128,6 +142,13 @@ export const geminiModels = {
128142
maxThinkingTokens: 32_768,
129143
supportsReasoningBudget: true,
130144
tiers: [
145+
{
146+
// Free tier: 125k input tokens per minute quota
147+
contextWindow: 125_000,
148+
inputPrice: 0,
149+
outputPrice: 0,
150+
cacheReadsPrice: 0,
151+
},
131152
{
132153
contextWindow: 200_000,
133154
inputPrice: 1.25,
@@ -155,6 +176,13 @@ export const geminiModels = {
155176
supportsReasoningBudget: true,
156177
requiredReasoningBudget: true,
157178
tiers: [
179+
{
180+
// Free tier: 125k input tokens per minute quota
181+
contextWindow: 125_000,
182+
inputPrice: 0,
183+
outputPrice: 0,
184+
cacheReadsPrice: 0,
185+
},
158186
{
159187
contextWindow: 200_000,
160188
inputPrice: 1.25,
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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

Comments
 (0)