diff --git a/.changeset/gentle-owls-listen.md b/.changeset/gentle-owls-listen.md new file mode 100644 index 0000000..ca9b9b2 --- /dev/null +++ b/.changeset/gentle-owls-listen.md @@ -0,0 +1,5 @@ +--- +'@core-ai/google-genai': patch +--- + +Align the Gemini 3 capability table with the model ids Google serves. Add `gemini-3-flash-preview` with its four thinking levels; it previously fell back to the Gemini 2.5-style thinking-budget defaults. Remove `gemini-3-pro`, `gemini-3.1-pro` and `gemini-3.1-flash-lite-preview`, which are shut down or never existed under those ids, and update the docs and README examples to ids that resolve. diff --git a/README.md b/README.md index 8e2268d..397335b 100644 --- a/README.md +++ b/README.md @@ -329,7 +329,7 @@ import { generate } from '@core-ai/core-ai'; import { createGoogleGenAI } from '@core-ai/google-genai'; const google = createGoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY }); -const model = google.chatModel('gemini-3-flash'); +const model = google.chatModel('gemini-3-flash-preview'); const result = await generate({ model, diff --git a/docs/api/providers/google-genai.mdx b/docs/api/providers/google-genai.mdx index be5c2f8..df063f1 100644 --- a/docs/api/providers/google-genai.mdx +++ b/docs/api/providers/google-genai.mdx @@ -61,9 +61,9 @@ const google = createGoogleGenAI({ - **gemini-3.6-flash** - Token-efficient Flash model for agents and coding - **gemini-3.5-flash** - Previous generation Flash model - **gemini-3.5-flash-lite** - Cost-efficient model for high-volume tasks - - **gemini-3.1-pro** / **gemini-3.1-pro-preview** - Most capable multimodal model - - **gemini-3.1-flash-lite** / **gemini-3.1-flash-lite-preview** - Lightweight thinking-level model - - **gemini-3-pro** - Previous Gemini 3 generation + - **gemini-3.1-pro-preview** - Most capable multimodal model + - **gemini-3.1-flash-lite** - Lightweight thinking-level model + - **gemini-3-flash-preview** - Previous Gemini 3 generation Flash model @@ -95,7 +95,7 @@ import { generate } from '@core-ai/core-ai'; const google = createGoogleGenAI(); const result = await generate({ - model: google.chatModel('gemini-3.1-pro'), + model: google.chatModel('gemini-3.1-pro-preview'), messages: [{ role: 'user', content: 'Explain machine learning' }], }); @@ -106,7 +106,7 @@ console.log(result.content); ```typescript const result = await generate({ - model: google.chatModel('gemini-3.1-pro'), + model: google.chatModel('gemini-3.1-pro-preview'), messages: [{ role: 'user', content: 'Analyze this complex scenario...' }], reasoning: { effort: 'high', @@ -118,7 +118,7 @@ const result = await generate({ ```typescript const result = await generate({ - model: google.chatModel('gemini-3.1-pro'), + model: google.chatModel('gemini-3.1-pro-preview'), messages: [ { role: 'user', @@ -192,7 +192,7 @@ import { generate, defineTool } from '@core-ai/core-ai'; import { z } from 'zod'; const result = await generate({ - model: google.chatModel('gemini-3.1-pro'), + model: google.chatModel('gemini-3.1-pro-preview'), messages: [ { role: 'user', @@ -226,7 +226,7 @@ import { } from '@core-ai/google-genai'; const google = createGoogleGenAI(); -const model = google.chatModel('gemini-3.1-pro'); +const model = google.chatModel('gemini-3.1-pro-preview'); if (model.capabilities.reasoning.mode !== 'unsupported') { const effort = clampReasoningEffort( @@ -281,11 +281,10 @@ Gemini 3.x models steer thinking with named levels, and each model accepts its own subset. `capabilities.reasoning.supportedEfforts` lists the efforts a model has a level for: -| Models | Supported efforts | -| -------------------------------------------------------------------------------------------- | ---------------------------------- | -| `gemini-3.6-flash`, `gemini-3.5-flash`, `gemini-3.5-flash-lite`, `gemini-3.1-flash-lite` | `minimal`, `low`, `medium`, `high` | -| `gemini-3.8-flash`, `gemini-3.7-flash`, `gemini-3.1-pro` | `low`, `medium`, `high` | -| `gemini-3-pro` | `low`, `high` | +| Models | Supported efforts | +| ------------------------------------------------------------------------------------------------------------------ | ---------------------------------- | +| `gemini-3.6-flash`, `gemini-3.5-flash`, `gemini-3.5-flash-lite`, `gemini-3.1-flash-lite`, `gemini-3-flash-preview` | `minimal`, `low`, `medium`, `high` | +| `gemini-3.8-flash`, `gemini-3.7-flash`, `gemini-3.1-pro-preview` | `low`, `medium`, `high` | A supported effort is sent as the level of the same name. Any other effort is clamped to the nearest supported one first, so `max` always resolves to @@ -346,7 +345,7 @@ import { generate, getProviderMetadata } from '@core-ai/core-ai'; import type { GoogleReasoningMetadata } from '@core-ai/google-genai'; const result = await generate({ - model: google.chatModel('gemini-3.1-pro'), + model: google.chatModel('gemini-3.1-pro-preview'), messages: [{ role: 'user', content: 'Search for something.' }], tools: { /* ... */ @@ -385,7 +384,7 @@ Options are namespaced under `google` in `providerOptions`: ```typescript const result = await generate({ - model: google.chatModel('gemini-3.1-pro'), + model: google.chatModel('gemini-3.1-pro-preview'), messages: [{ role: 'user', content: 'Hello' }], providerOptions: { google: { @@ -467,7 +466,7 @@ import { ProviderError } from '@core-ai/core-ai'; try { const result = await generate({ - model: google.chatModel('gemini-3.1-pro'), + model: google.chatModel('gemini-3.1-pro-preview'), messages: [{ role: 'user', content: 'Hello!' }], }); } catch (error) { @@ -482,9 +481,9 @@ try { | Model | Thinking Control | Can Disable | Best For | | ----------------------------- | ---------------- | ----------- | ------------------------------ | -| Gemini 3.1 Pro | Level | No | Complex multimodal | -| Gemini 3.1 Flash Lite Preview | Level | No | Cost-efficient with thinking | -| Gemini 3 Pro | Level | No | Previous generation multimodal | +| Gemini 3.1 Pro Preview | Level | No | Complex multimodal | +| Gemini 3.1 Flash Lite | Level | No | Cost-efficient with thinking | +| Gemini 3 Flash Preview | Level | No | Previous generation Flash | | Gemini 2.5 Pro | Budget (tokens) | No | Controlled reasoning | | Gemini 2.5 Flash | Budget (tokens) | Yes | Fast + flexible | | Gemini 2.5 Flash Lite | Budget (tokens) | Yes | Lightweight tasks | diff --git a/docs/api/providers/google-vertex.mdx b/docs/api/providers/google-vertex.mdx index 9013db0..53fa82d 100644 --- a/docs/api/providers/google-vertex.mdx +++ b/docs/api/providers/google-vertex.mdx @@ -151,7 +151,7 @@ const googleVertex = createGoogleVertex({ const model = googleVertex.chatModel('gemini-2.5-flash'); const capabilities = model.capabilities; -const otherCapabilities = getGoogleModelCapabilities('gemini-3.1-pro'); +const otherCapabilities = getGoogleModelCapabilities('gemini-3.1-pro-preview'); ``` These fields describe reasoning effort, whether thinking can be disabled, which diff --git a/docs/concepts/providers.mdx b/docs/concepts/providers.mdx index b16a8f9..e5add3b 100644 --- a/docs/concepts/providers.mdx +++ b/docs/concepts/providers.mdx @@ -214,7 +214,7 @@ type GoogleGenAIProviderOptions = { ### Getting Models ```typescript -const gemini = google.chatModel('gemini-3.1-pro'); +const gemini = google.chatModel('gemini-3.1-pro-preview'); const embeddings = google.embeddingModel('text-embedding-004'); const image = google.imageModel('gemini-2.5-flash-image'); const imagen = google.imageModel('imagen-4.0-generate-001'); diff --git a/docs/guides/chat-completion.mdx b/docs/guides/chat-completion.mdx index 8cd12e1..38e1ef2 100644 --- a/docs/guides/chat-completion.mdx +++ b/docs/guides/chat-completion.mdx @@ -83,7 +83,7 @@ core-ai supports multiple providers with the same API: const google = createGoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY }); - const model = google.chatModel('gemini-3.1-pro'); + const model = google.chatModel('gemini-3.1-pro-preview'); const result = await generate({ model, diff --git a/docs/quickstart.mdx b/docs/quickstart.mdx index 5b90ceb..4f29e04 100644 --- a/docs/quickstart.mdx +++ b/docs/quickstart.mdx @@ -181,7 +181,7 @@ import { generate } from '@core-ai/core-ai'; import { createGoogleGenAI } from '@core-ai/google-genai'; const google = createGoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY }); -const model = google.chatModel('gemini-3.1-pro'); +const model = google.chatModel('gemini-3.1-pro-preview'); const result = await generate({ model, diff --git a/packages/google-genai/README.md b/packages/google-genai/README.md index cda981f..b416af7 100644 --- a/packages/google-genai/README.md +++ b/packages/google-genai/README.md @@ -17,7 +17,7 @@ import { generate } from '@core-ai/core-ai'; import { createGoogleGenAI } from '@core-ai/google-genai'; const google = createGoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY }); -const model = google.chatModel('gemini-3-flash'); +const model = google.chatModel('gemini-3-flash-preview'); const result = await generate({ model, diff --git a/packages/google-genai/src/chat-adapter.test.ts b/packages/google-genai/src/chat-adapter.test.ts index fcf2dad..6e3f718 100644 --- a/packages/google-genai/src/chat-adapter.test.ts +++ b/packages/google-genai/src/chat-adapter.test.ts @@ -619,7 +619,7 @@ describe('reasoning support', () => { }); it('should map reasoning config to thinkingLevel for Gemini 3', () => { - const request = createGenerateRequest('gemini-3-pro', { + const request = createGenerateRequest('gemini-3.1-pro-preview', { messages: [{ role: 'user', content: 'Hi' }], reasoning: { effort: 'high' }, }); @@ -695,7 +695,7 @@ describe('reasoning support', () => { }); it('should not reject small limits for thinking-level models', () => { - const request = createGenerateRequest('gemini-3-pro', { + const request = createGenerateRequest('gemini-3.1-pro-preview', { messages: [{ role: 'user', content: 'Hi' }], reasoning: { effort: 'high' }, maxTokens: 1000, @@ -708,7 +708,7 @@ describe('reasoning support', () => { }); it('should not allow provider reasoning config overrides', () => { - const request = createGenerateRequest('gemini-3-pro', { + const request = createGenerateRequest('gemini-3.1-pro-preview', { messages: [{ role: 'user', content: 'Hi' }], reasoning: { effort: 'high' }, }); diff --git a/packages/google-genai/src/chat-model.test.ts b/packages/google-genai/src/chat-model.test.ts index 40fea05..d3ca2f0 100644 --- a/packages/google-genai/src/chat-model.test.ts +++ b/packages/google-genai/src/chat-model.test.ts @@ -242,7 +242,7 @@ describe('generate', () => { }); const model = createGoogleGenAIChatModel( createMockClient({ generateContent }), - 'gemini-3-pro' + 'gemini-3.1-pro-preview' ); const result = await model.generate({ @@ -449,7 +449,7 @@ describe('generate', () => { }); const model = createGoogleGenAIChatModel( createMockClient({ generateContent }), - 'gemini-3-pro' + 'gemini-3.1-pro-preview' ); const result = await model.generate({ diff --git a/packages/google-genai/src/model-capabilities.test.ts b/packages/google-genai/src/model-capabilities.test.ts index d7390af..aada729 100644 --- a/packages/google-genai/src/model-capabilities.test.ts +++ b/packages/google-genai/src/model-capabilities.test.ts @@ -16,10 +16,13 @@ describe('normalizeModelId', () => { describe('getGoogleModelCapabilities', () => { it('should resolve known model capabilities', () => { - const capabilities = getGoogleModelCapabilities('gemini-3-pro'); + const capabilities = getGoogleModelCapabilities( + 'gemini-3.1-pro-preview' + ); expect(capabilities.reasoning.mode).toBe('always-on'); expect(capabilities.reasoning.supportedEfforts).toEqual([ 'low', + 'medium', 'high', ]); expect(capabilities.reasoning.restrictsSamplingParams).toBe(false); @@ -33,6 +36,7 @@ describe('getGoogleModelCapabilities', () => { ['gemini-3.1-flash-lite', ['minimal', 'low', 'medium', 'high']], ['gemini-3.8-flash', ['low', 'medium', 'high']], ['gemini-3.7-flash', ['low', 'medium', 'high']], + ['gemini-3-flash-preview', ['minimal', 'low', 'medium', 'high']], ['gemini-3.1-pro-preview', ['low', 'medium', 'high']], ])( 'should report the thinking levels of %s as efforts', @@ -61,11 +65,9 @@ describe('getGoogleModelCapabilities', () => { 'gemini-3.6-flash', 'gemini-3.5-flash', 'gemini-3.5-flash-lite', - 'gemini-3.1-pro', 'gemini-3.1-pro-preview', 'gemini-3.1-flash-lite', - 'gemini-3.1-flash-lite-preview', - 'gemini-3-pro', + 'gemini-3-flash-preview', ])('should resolve thinking-level capabilities for %s', (modelId) => { const capabilities = getGoogleModelCapabilities(modelId); expect(capabilities.reasoning.thinkingParam).toBe('thinkingLevel'); @@ -81,12 +83,12 @@ describe('getGoogleModelCapabilities', () => { }); it('should resolve dated model IDs to the same capabilities', () => { - expect(getGoogleModelCapabilities('gemini-3-pro-20260215')).toEqual( - getGoogleModelCapabilities('gemini-3-pro') + expect(getGoogleModelCapabilities('gemini-3.5-flash-20260215')).toEqual( + getGoogleModelCapabilities('gemini-3.5-flash') ); }); - it.each(['gemini-3-pro', 'gemini-2.5-pro', 'gemini-custom'])( + it.each(['gemini-3.5-flash', 'gemini-2.5-pro', 'gemini-custom'])( 'should report multimodal input as supported for %s', (modelId) => { expect( @@ -99,9 +101,9 @@ describe('getGoogleModelCapabilities', () => { ); it.each([ - 'gemini-3.1-pro', - 'gemini-3.1-flash-lite-preview', - 'gemini-3-pro', + 'gemini-3.1-pro-preview', + 'gemini-3.1-flash-lite', + 'gemini-3-flash-preview', 'gemini-2.5-pro', 'gemini-2.5-flash', 'gemini-2.5-flash-lite', @@ -132,9 +134,9 @@ describe('reasoning mapping', () => { ['gemini-3.8-flash', 'minimal', 'LOW'], ['gemini-3.8-flash', 'medium', 'MEDIUM'], ['gemini-3.8-flash', 'max', 'HIGH'], - ['gemini-3-pro', 'minimal', 'LOW'], - ['gemini-3-pro', 'medium', 'LOW'], - ['gemini-3-pro', 'max', 'HIGH'], + ['gemini-3-flash-preview', 'minimal', 'MINIMAL'], + ['gemini-3.1-pro-preview', 'minimal', 'LOW'], + ['gemini-3.1-pro-preview', 'max', 'HIGH'], ] as const)( 'should map %s effort %s to thinking level %s', (modelId, effort, level) => { @@ -173,7 +175,7 @@ describe('output ceilings', () => { 'gemini-3.8-flash', 'gemini-3.5-flash-lite', 'gemini-3.1-pro-preview', - 'gemini-3-pro', + 'gemini-3-flash-preview', 'gemini-2.5-pro', 'gemini-2.5-flash', 'gemini-2.5-flash-lite', diff --git a/packages/google-genai/src/model-capabilities.ts b/packages/google-genai/src/model-capabilities.ts index f5ec120..903f233 100644 --- a/packages/google-genai/src/model-capabilities.ts +++ b/packages/google-genai/src/model-capabilities.ts @@ -48,11 +48,6 @@ const THREE_LEVEL_EFFORTS = [ 'high', ] as const satisfies readonly ReasoningEffort[]; -const TWO_LEVEL_EFFORTS = [ - 'low', - 'high', -] as const satisfies readonly ReasoningEffort[]; - const GOOGLE_INPUT_MODALITIES = { input: ['text', 'image', 'file', 'audio'], output: ['text'], @@ -126,8 +121,6 @@ const FOUR_LEVEL_CAPABILITIES = createThinkingLevelCapabilities(FOUR_LEVEL_EFFORTS); const THREE_LEVEL_CAPABILITIES = createThinkingLevelCapabilities(THREE_LEVEL_EFFORTS); -const TWO_LEVEL_CAPABILITIES = - createThinkingLevelCapabilities(TWO_LEVEL_EFFORTS); const MODEL_CAPABILITIES: Record = { 'gemini-3.8-flash': THREE_LEVEL_CAPABILITIES, @@ -135,11 +128,9 @@ const MODEL_CAPABILITIES: Record = { 'gemini-3.6-flash': FOUR_LEVEL_CAPABILITIES, 'gemini-3.5-flash': FOUR_LEVEL_CAPABILITIES, 'gemini-3.5-flash-lite': FOUR_LEVEL_CAPABILITIES, - 'gemini-3.1-pro': THREE_LEVEL_CAPABILITIES, 'gemini-3.1-pro-preview': THREE_LEVEL_CAPABILITIES, 'gemini-3.1-flash-lite': FOUR_LEVEL_CAPABILITIES, - 'gemini-3.1-flash-lite-preview': FOUR_LEVEL_CAPABILITIES, - 'gemini-3-pro': TWO_LEVEL_CAPABILITIES, + 'gemini-3-flash-preview': FOUR_LEVEL_CAPABILITIES, 'gemini-2.5-pro': GEMINI_25_PRO_CAPABILITIES, 'gemini-2.5-flash': GEMINI_25_FLASH_CAPABILITIES, 'gemini-2.5-flash-lite': GEMINI_25_FLASH_LITE_CAPABILITIES,