Skip to content
This repository was archived by the owner on May 15, 2026. It is now read-only.

Commit 181f829

Browse files
committed
feat: add support for the Gemma-3 and Gemini Robotics models via the Gemini API
1 parent a3b258a commit 181f829

4 files changed

Lines changed: 80 additions & 3 deletions

File tree

packages/types/src/providers/gemini.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,44 @@ export const geminiModels = {
208208
supportsReasoningBudget: true,
209209
maxThinkingTokens: 24_576,
210210
},
211+
212+
// Robotics models
213+
"gemini-robotics-er-1.5-preview": {
214+
maxTokens: 8192,
215+
contextWindow: 1_000_000,
216+
supportsImages: true,
217+
supportsNativeTools: true,
218+
supportsPromptCache: false,
219+
inputPrice: 0.3,
220+
outputPrice: 2.5,
221+
},
222+
223+
// Gemma 3 models
224+
"gemma-3-27b-it": {
225+
maxTokens: 8192,
226+
contextWindow: 128_000,
227+
supportsImages: true,
228+
supportsNativeTools: false,
229+
supportsPromptCache: false,
230+
inputPrice: 0.07,
231+
outputPrice: 0.5,
232+
},
233+
"gemma-3-12b-it": {
234+
maxTokens: 8192,
235+
contextWindow: 128_000,
236+
supportsImages: true,
237+
supportsNativeTools: false,
238+
supportsPromptCache: false,
239+
inputPrice: 0.03,
240+
outputPrice: 0.1,
241+
},
242+
"gemma-3-4b-it": {
243+
maxTokens: 8192,
244+
contextWindow: 128_000,
245+
supportsImages: true,
246+
supportsNativeTools: false,
247+
supportsPromptCache: false,
248+
inputPrice: 0.02,
249+
outputPrice: 0.07,
250+
},
211251
} as const satisfies Record<string, ModelInfo>

src/api/providers/gemini.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,30 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
154154
? (this.options.modelTemperature ?? info.defaultTemperature ?? 1)
155155
: info.defaultTemperature
156156

157+
// Check if the model is a Gemma 3 model
158+
const isGemma3 = model.includes("gemma-3")
159+
160+
// Prepend system instruction to the first user message if it's a Gemma 3 model,
161+
// as they don't support the system instruction parameter.
162+
if (isGemma3 && systemInstruction) {
163+
if (contents.length > 0 && contents[0].role === "user") {
164+
const firstMessage = contents[0]
165+
// Create a new text part for the system instruction
166+
const systemPart = { text: systemInstruction }
167+
// Prepend it to the existing parts
168+
firstMessage.parts = [systemPart, ...firstMessage.parts]
169+
} else {
170+
// If no messages or first message is not user (e.g. starts with model),
171+
// prepend a new user message with the system instruction.
172+
contents.unshift({
173+
role: "user",
174+
parts: [{ text: systemInstruction }],
175+
})
176+
}
177+
}
178+
157179
const config: GenerateContentConfig = {
158-
systemInstruction,
180+
...(isGemma3 ? {} : { systemInstruction }),
159181
httpOptions: this.options.googleGeminiBaseUrl ? { baseUrl: this.options.googleGeminiBaseUrl } : undefined,
160182
thinkingConfig,
161183
maxOutputTokens,
@@ -339,6 +361,19 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
339361
}
340362
} catch (error) {
341363
if (error instanceof Error) {
364+
// Parse "limit: 15000, model: gemma-3-27b\nPlease retry in 31.714908887s"
365+
// Use a more flexible regex to handle potential variations in spacing or text
366+
const match = error.message.match(/limit:\s*(\d+)\s*,\s*model:\s*([^,\n]+).*?retry in\s*([\d.]+)/s)
367+
if (match) {
368+
const [, limit, model, retry] = match
369+
throw new Error(
370+
t("common:errors.gemini.resource_exhausted", {
371+
limit,
372+
model: model.trim(),
373+
retry: Math.round(Number(retry)),
374+
}),
375+
)
376+
}
342377
throw new Error(t("common:errors.gemini.generate_stream", { error: error.message }))
343378
}
344379

src/i18n/locales/en/common.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@
110110
"thinking_complete_no_output": "(Thinking complete, but no output was generated.)",
111111
"thinking_complete_truncated": "(Thinking complete, but output was truncated due to token limit.)",
112112
"thinking_complete_safety": "(Thinking complete, but output was blocked due to safety settings.)",
113-
"thinking_complete_recitation": "(Thinking complete, but output was blocked due to recitation check.)"
113+
"thinking_complete_recitation": "(Thinking complete, but output was blocked due to recitation check.)",
114+
"resource_exhausted": "Rate limit reached for {{model}}. The limit is {{limit}} requests per minute. Please retry in {{retry}} seconds."
114115
},
115116
"cerebras": {
116117
"authenticationFailed": "Cerebras API authentication failed. Please check your API key is valid and not expired.",

src/i18n/locales/ja/common.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)