diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index 65d17307..8aa803b7 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed thinking levels for Gemma 4 models to use `thinkingLevel` and map Pi reasoning levels to the model's supported thinking levels ([#2903](https://github.com/badlogic/pi-mono/pull/2903) by [@aadishv](https://github.com/aadishv)) + ## [0.66.1] - 2026-04-08 ## [0.66.0] - 2026-04-08 diff --git a/packages/ai/src/providers/google.ts b/packages/ai/src/providers/google.ts index d1f1239a..46cc5ba6 100644 --- a/packages/ai/src/providers/google.ts +++ b/packages/ai/src/providers/google.ts @@ -293,12 +293,12 @@ export const streamSimpleGoogle: StreamFunction<"google-generative-ai", SimpleSt const effort = clampReasoning(options.reasoning)!; const googleModel = model as Model<"google-generative-ai">; - if (isGemini3ProModel(googleModel) || isGemini3FlashModel(googleModel)) { + if (isGemini3ProModel(googleModel) || isGemini3FlashModel(googleModel) || isGemma4Model(googleModel)) { return streamGoogle(model, context, { ...base, thinking: { enabled: true, - level: getGemini3ThinkingLevel(effort, googleModel), + level: getThinkingLevel(effort, googleModel), }, } satisfies GoogleOptions); } @@ -394,6 +394,10 @@ function buildParams( type ClampedThinkingLevel = Exclude; +function isGemma4Model(model: Model<"google-generative-ai">): boolean { + return /gemma-?4/.test(model.id.toLowerCase()); +} + function isGemini3ProModel(model: Model<"google-generative-ai">): boolean { return /gemini-3(?:\.\d+)?-pro/.test(model.id.toLowerCase()); } @@ -412,15 +416,15 @@ function getDisabledThinkingConfig(model: Model<"google-generative-ai">): Thinki if (isGemini3FlashModel(model)) { return { thinkingLevel: "MINIMAL" as any }; } + if (isGemma4Model(model)) { + return { thinkingLevel: "MINIMAL" as any }; + } // Gemini 2.x supports disabling via thinkingBudget = 0. return { thinkingBudget: 0 }; } -function getGemini3ThinkingLevel( - effort: ClampedThinkingLevel, - model: Model<"google-generative-ai">, -): GoogleThinkingLevel { +function getThinkingLevel(effort: ClampedThinkingLevel, model: Model<"google-generative-ai">): GoogleThinkingLevel { if (isGemini3ProModel(model)) { switch (effort) { case "minimal": @@ -431,6 +435,16 @@ function getGemini3ThinkingLevel( return "HIGH"; } } + if (isGemma4Model(model)) { + switch (effort) { + case "minimal": + case "low": + return "MINIMAL"; + case "medium": + case "high": + return "HIGH"; + } + } switch (effort) { case "minimal": return "MINIMAL"; diff --git a/packages/coding-agent/docs/models.md b/packages/coding-agent/docs/models.md index 4f99f04d..2fa48a69 100644 --- a/packages/coding-agent/docs/models.md +++ b/packages/coding-agent/docs/models.md @@ -90,6 +90,33 @@ Override defaults when you need specific values: The file reloads each time you open `/model`. Edit during session; no restart needed. +## Google AI Studio Example + +Use `google-generative-ai` with a `baseUrl` to add models from Google AI Studio, including custom Gemma 4 entries: + +```json +{ + "providers": { + "my-google": { + "baseUrl": "https://generativelanguage.googleapis.com/v1beta", + "api": "google-generative-ai", + "apiKey": "GEMINI_API_KEY", + "models": [ + { + "id": "gemma-4-31b-it", + "name": "Gemma 4 31B", + "input": ["text", "image"], + "contextWindow": 262144, + "reasoning": true + } + ] + } + } +} +``` + +The `baseUrl` is required when adding custom models to the `google-generative-ai` API type. + ## Supported APIs | API | Description |