diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.test.ts b/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.test.ts index 8decf352c69..de0a20d05b0 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.test.ts @@ -49,6 +49,12 @@ const mockResponse = { { name: 'models/gemini-3.1-flash-image-preview', }, + { + name: 'models/gemini-nano-banana-2.1', + }, + { + name: 'models/gemini-3.1-flash-lite-image', + }, ], }; @@ -153,6 +159,16 @@ describe('GoogleGemini -> listSearch', () => { name: 'models/gemini-3.1-flash-image-preview (Nano Banana 2)', value: 'models/gemini-3.1-flash-image-preview', }, + { + // eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased + name: 'models/gemini-nano-banana-2.1 (Nano Banana 2.1)', + value: 'models/gemini-nano-banana-2.1', + }, + { + // eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased + name: 'models/gemini-3.1-flash-lite-image (Nano Banana 2 Lite)', + value: 'models/gemini-3.1-flash-lite-image', + }, ], }); }); @@ -196,6 +212,16 @@ describe('GoogleGemini -> listSearch', () => { name: 'models/gemini-3.1-flash-image-preview (Nano Banana 2)', value: 'models/gemini-3.1-flash-image-preview', }, + { + // eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased + name: 'models/gemini-nano-banana-2.1 (Nano Banana 2.1)', + value: 'models/gemini-nano-banana-2.1', + }, + { + // eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased + name: 'models/gemini-3.1-flash-lite-image (Nano Banana 2 Lite)', + value: 'models/gemini-3.1-flash-lite-image', + }, ], }); }); diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.ts b/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.ts index 518fd5dc8bd..70ebd266fec 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.ts @@ -2,6 +2,11 @@ import type { ILoadOptionsFunctions, INodeListSearchResult } from 'n8n-workflow' import { apiRequest } from '../transport'; +/** Nano Banana ids do not contain the word "image". */ +function isImageModel(model: string): boolean { + return model.includes('image') || model.includes('nano-banana'); +} + async function baseModelSearch( this: ILoadOptionsFunctions, modelFilter: (model: string) => boolean, @@ -32,9 +37,9 @@ export async function modelSearch( return await baseModelSearch.call( this, (model) => + !isImageModel(model) && !model.includes('embedding') && !model.includes('aqa') && - !model.includes('image') && !model.includes('vision') && !model.includes('veo') && !model.includes('audio') && @@ -50,9 +55,9 @@ export async function audioModelSearch( return await baseModelSearch.call( this, (model) => + !isImageModel(model) && !model.includes('embedding') && !model.includes('aqa') && - !model.includes('image') && !model.includes('vision') && !model.includes('veo') && !model.includes('tts'), // we don't have a tts operation @@ -64,8 +69,17 @@ export async function imageGenerationModelSearch( this: ILoadOptionsFunctions, filter?: string, ): Promise { - const rawResult = await baseModelSearch.call(this, (model) => model.includes('image')); + const rawResult = await baseModelSearch.call(this, isImageModel); let results = rawResult.results.map((r) => { + if (r.name.includes('gemini-nano-banana-2.1')) { + return { name: `${r.name} (Nano Banana 2.1)`, value: r.value }; + } + + // The Lite id also contains "gemini-3.1-flash-image". Match it first. + if (r.name.includes('gemini-3.1-flash-lite-image')) { + return { name: `${r.name} (Nano Banana 2 Lite)`, value: r.value }; + } + if (r.name.includes('gemini-3.1-flash-image')) { return { name: `${r.name} (Nano Banana 2)`, value: r.value }; }