Skip to content

Commit 5f326c4

Browse files
committed
fix: progressive migration to new Gemini naming conventions on both frontend and backend
1 parent 2816191 commit 5f326c4

File tree

6 files changed

+274
-60
lines changed

6 files changed

+274
-60
lines changed

packages/types/src/providers/gemini.ts

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -152,60 +152,6 @@ export const geminiModels = {
152152
} as const satisfies Record<string, ModelInfo>
153153

154154
export const legacyGeminiModels = {
155-
"gemini-2.5-flash-preview-04-17:thinking": {
156-
maxTokens: 65_535,
157-
contextWindow: 1_048_576,
158-
supportsImages: true,
159-
supportsPromptCache: false,
160-
inputPrice: 0.15,
161-
outputPrice: 3.5,
162-
maxThinkingTokens: 24_576,
163-
supportsReasoningBudget: true,
164-
requiredReasoningBudget: true,
165-
},
166-
"gemini-2.5-flash-preview-04-17": {
167-
maxTokens: 65_535,
168-
contextWindow: 1_048_576,
169-
supportsImages: true,
170-
supportsPromptCache: false,
171-
inputPrice: 0.15,
172-
outputPrice: 0.6,
173-
},
174-
"gemini-2.5-flash-preview-05-20:thinking": {
175-
maxTokens: 65_535,
176-
contextWindow: 1_048_576,
177-
supportsImages: true,
178-
supportsPromptCache: true,
179-
inputPrice: 0.15,
180-
outputPrice: 3.5,
181-
cacheReadsPrice: 0.0375,
182-
cacheWritesPrice: 1.0,
183-
maxThinkingTokens: 24_576,
184-
supportsReasoningBudget: true,
185-
requiredReasoningBudget: true,
186-
},
187-
"gemini-2.5-flash-preview-05-20": {
188-
maxTokens: 65_535,
189-
contextWindow: 1_048_576,
190-
supportsImages: true,
191-
supportsPromptCache: true,
192-
inputPrice: 0.15,
193-
outputPrice: 0.6,
194-
cacheReadsPrice: 0.0375,
195-
cacheWritesPrice: 1.0,
196-
},
197-
"gemini-2.5-flash": {
198-
maxTokens: 64_000,
199-
contextWindow: 1_048_576,
200-
supportsImages: true,
201-
supportsPromptCache: true,
202-
inputPrice: 0.3,
203-
outputPrice: 2.5,
204-
cacheReadsPrice: 0.075,
205-
cacheWritesPrice: 1.0,
206-
maxThinkingTokens: 24_576,
207-
supportsReasoningBudget: true,
208-
},
209155
"gemini-2.5-pro-exp-03-25": {
210156
maxTokens: 65_535,
211157
contextWindow: 1_048_576,

src/api/providers/__tests__/gemini.spec.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,62 @@ describe("GeminiHandler", () => {
163163
})
164164
})
165165

166+
describe("legacy model migration", () => {
167+
it("should map gemini-2.5-pro-preview-{dates} to gemini-2.5-pro", () => {
168+
const legacyHandler = new GeminiHandler({
169+
apiModelId: "gemini-2.5-pro-preview-03-25",
170+
geminiApiKey: "test-key",
171+
})
172+
const modelInfo = legacyHandler.getModel()
173+
expect(modelInfo.id).toBe("gemini-2.5-pro")
174+
})
175+
176+
it("should map gemini-1.5-pro-{variants} to gemini-2.0-pro-exp-02-05", () => {
177+
const legacyHandler = new GeminiHandler({
178+
apiModelId: "gemini-1.5-pro-002",
179+
geminiApiKey: "test-key",
180+
})
181+
const modelInfo = legacyHandler.getModel()
182+
expect(modelInfo.id).toBe("gemini-2.0-pro-exp-02-05")
183+
})
184+
185+
it("should map gemini-1.5-flash-{variants} to gemini-2.0-flash-001", () => {
186+
const legacyHandler = new GeminiHandler({
187+
apiModelId: "gemini-1.5-flash-002",
188+
geminiApiKey: "test-key",
189+
})
190+
const modelInfo = legacyHandler.getModel()
191+
expect(modelInfo.id).toBe("gemini-2.0-flash-001")
192+
})
193+
194+
it("should map experimental gemini-2.5-pro-exp-03-25 to gemini-2.5-pro", () => {
195+
const legacyHandler = new GeminiHandler({
196+
apiModelId: "gemini-2.5-pro-exp-03-25",
197+
geminiApiKey: "test-key",
198+
})
199+
const modelInfo = legacyHandler.getModel()
200+
expect(modelInfo.id).toBe("gemini-2.5-pro")
201+
})
202+
203+
it("should map gemini-exp-1206 to gemini-2.0-pro-exp-02-05", () => {
204+
const legacyHandler = new GeminiHandler({
205+
apiModelId: "gemini-exp-1206",
206+
geminiApiKey: "test-key",
207+
})
208+
const modelInfo = legacyHandler.getModel()
209+
expect(modelInfo.id).toBe("gemini-2.0-pro-exp-02-05")
210+
})
211+
212+
it("should keep current models as-is", () => {
213+
const currentHandler = new GeminiHandler({
214+
apiModelId: "gemini-2.5-pro",
215+
geminiApiKey: "test-key",
216+
})
217+
const modelInfo = currentHandler.getModel()
218+
expect(modelInfo.id).toBe("gemini-2.5-pro")
219+
})
220+
})
221+
166222
describe("calculateCost", () => {
167223
// Mock ModelInfo based on gemini-1.5-flash-latest pricing (per 1M tokens)
168224
// Removed 'id' and 'name' as they are not part of ModelInfo type directly

src/api/providers/__tests__/vertex.spec.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,4 +137,66 @@ describe("VertexHandler", () => {
137137
expect(modelInfo.info.contextWindow).toBe(1048576)
138138
})
139139
})
140+
141+
describe("legacy model migration", () => {
142+
it("should map gemini-2.5-pro-preview-{dates} to gemini-2.5-pro", () => {
143+
const legacyHandler = new VertexHandler({
144+
apiModelId: "gemini-2.5-pro-preview-03-25",
145+
vertexProjectId: "test-project",
146+
vertexRegion: "us-central1",
147+
})
148+
const modelInfo = legacyHandler.getModel()
149+
expect(modelInfo.id).toBe("gemini-2.5-pro")
150+
})
151+
152+
it("should map gemini-1.5-pro-{variants} to gemini-2.0-pro-exp-02-05", () => {
153+
const legacyHandler = new VertexHandler({
154+
apiModelId: "gemini-1.5-pro-002",
155+
vertexProjectId: "test-project",
156+
vertexRegion: "us-central1",
157+
})
158+
const modelInfo = legacyHandler.getModel()
159+
expect(modelInfo.id).toBe("gemini-2.0-pro-exp-02-05")
160+
})
161+
162+
it("should map gemini-1.5-flash-{variants} to gemini-2.0-flash-001", () => {
163+
const legacyHandler = new VertexHandler({
164+
apiModelId: "gemini-1.5-flash-002",
165+
vertexProjectId: "test-project",
166+
vertexRegion: "us-central1",
167+
})
168+
const modelInfo = legacyHandler.getModel()
169+
expect(modelInfo.id).toBe("gemini-2.0-flash-001")
170+
})
171+
172+
it("should map experimental gemini-2.5-pro-exp-03-25 to gemini-2.5-pro", () => {
173+
const legacyHandler = new VertexHandler({
174+
apiModelId: "gemini-2.5-pro-exp-03-25",
175+
vertexProjectId: "test-project",
176+
vertexRegion: "us-central1",
177+
})
178+
const modelInfo = legacyHandler.getModel()
179+
expect(modelInfo.id).toBe("gemini-2.5-pro")
180+
})
181+
182+
it("should keep current vertex models as-is", () => {
183+
const currentHandler = new VertexHandler({
184+
apiModelId: "gemini-2.5-pro",
185+
vertexProjectId: "test-project",
186+
vertexRegion: "us-central1",
187+
})
188+
const modelInfo = currentHandler.getModel()
189+
expect(modelInfo.id).toBe("gemini-2.5-pro")
190+
})
191+
192+
it("should keep claude models as-is", () => {
193+
const claudeHandler = new VertexHandler({
194+
apiModelId: "claude-sonnet-4@20250514",
195+
vertexProjectId: "test-project",
196+
vertexRegion: "us-central1",
197+
})
198+
const modelInfo = claudeHandler.getModel()
199+
expect(modelInfo.id).toBe("claude-sonnet-4@20250514")
200+
})
201+
})
140202
})

src/api/providers/gemini.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ import {
77
} from "@google/genai"
88
import type { JWTInput } from "google-auth-library"
99

10-
import { type ModelInfo, type GeminiModelId, geminiDefaultModelId, geminiModels } from "@roo-code/types"
10+
import {
11+
type ModelInfo,
12+
type GeminiModelId,
13+
geminiDefaultModelId,
14+
geminiModels,
15+
legacyGeminiModels,
16+
} from "@roo-code/types"
1117

1218
import type { ApiHandlerOptions } from "../../shared/api"
1319
import { safeJsonParse } from "../../shared/safeJsonParse"
@@ -28,6 +34,39 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
2834

2935
private client: GoogleGenAI
3036

37+
/**
38+
* Maps legacy Gemini model IDs to current supported models
39+
*/
40+
private mapLegacyGeminiModel(modelId: string): GeminiModelId {
41+
if (modelId in geminiModels) {
42+
return modelId as GeminiModelId
43+
}
44+
45+
if (modelId in legacyGeminiModels) {
46+
if (modelId.startsWith("gemini-2.5-pro-preview-")) {
47+
return "gemini-2.5-pro"
48+
}
49+
50+
if (modelId.startsWith("gemini-1.5-pro-")) {
51+
return "gemini-2.0-pro-exp-02-05"
52+
}
53+
54+
if (modelId.startsWith("gemini-1.5-flash-")) {
55+
return "gemini-2.0-flash-001"
56+
}
57+
58+
if (modelId === "gemini-2.5-pro-exp-") {
59+
return "gemini-2.5-pro"
60+
}
61+
62+
if (modelId === "gemini-exp-1206") {
63+
return "gemini-2.0-pro-exp-02-05"
64+
}
65+
}
66+
67+
return geminiDefaultModelId
68+
}
69+
3170
constructor({ isVertex, ...options }: GeminiHandlerOptions) {
3271
super()
3372

@@ -131,7 +170,12 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
131170

132171
override getModel() {
133172
const modelId = this.options.apiModelId
134-
let id = modelId && modelId in geminiModels ? (modelId as GeminiModelId) : geminiDefaultModelId
173+
let id = modelId ? this.mapLegacyGeminiModel(modelId) : geminiDefaultModelId
174+
175+
if (modelId && modelId !== id) {
176+
this.options.apiModelId = id
177+
}
178+
135179
const info: ModelInfo = geminiModels[id]
136180
const params = getModelParams({ format: "gemini", modelId: id, model: info, settings: this.options })
137181

src/api/providers/vertex.ts

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { type ModelInfo, type VertexModelId, vertexDefaultModelId, vertexModels } from "@roo-code/types"
1+
import {
2+
type ModelInfo,
3+
type VertexModelId,
4+
vertexDefaultModelId,
5+
vertexModels,
6+
legacyVertexModels,
7+
} from "@roo-code/types"
28

39
import type { ApiHandlerOptions } from "../../shared/api"
410

@@ -12,9 +18,43 @@ export class VertexHandler extends GeminiHandler implements SingleCompletionHand
1218
super({ ...options, isVertex: true })
1319
}
1420

21+
/**
22+
* Maps legacy Vertex model IDs to current supported models
23+
*/
24+
private mapLegacyVertexModel(modelId: string): VertexModelId {
25+
if (modelId in vertexModels) {
26+
return modelId as VertexModelId
27+
}
28+
29+
if (modelId in legacyVertexModels) {
30+
if (modelId.startsWith("gemini-2.5-pro-preview-")) {
31+
return "gemini-2.5-pro"
32+
}
33+
34+
if (modelId.startsWith("gemini-1.5-pro-")) {
35+
return "gemini-2.0-pro-exp-02-05"
36+
}
37+
38+
if (modelId.startsWith("gemini-1.5-flash-")) {
39+
return "gemini-2.0-flash-001"
40+
}
41+
42+
if (modelId === "gemini-2.5-pro-exp-") {
43+
return "gemini-2.5-pro"
44+
}
45+
}
46+
47+
return vertexDefaultModelId
48+
}
49+
1550
override getModel() {
1651
const modelId = this.options.apiModelId
17-
let id = modelId && modelId in vertexModels ? (modelId as VertexModelId) : vertexDefaultModelId
52+
let id = modelId ? this.mapLegacyVertexModel(modelId) : vertexDefaultModelId
53+
54+
if (modelId && id && modelId !== id) {
55+
this.options.apiModelId = id
56+
}
57+
1858
const info: ModelInfo = vertexModels[id]
1959
const params = getModelParams({ format: "gemini", modelId: id, model: info, settings: this.options })
2060

0 commit comments

Comments
 (0)