n8n-nodes-gemini-grounding
Version:
n8n node with Gemini API grounding functionality
908 lines • 42.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GeminiIAStudio = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const axios_1 = __importDefault(require("axios"));
function prepareGenerationConfig(advancedParams) {
const generationConfig = {};
if (advancedParams.temperature !== undefined) {
generationConfig.temperature = advancedParams.temperature;
}
if (advancedParams.topP !== undefined) {
generationConfig.topP = advancedParams.topP;
}
if (advancedParams.topK !== undefined) {
generationConfig.topK = advancedParams.topK;
}
if (advancedParams.maxOutputTokens !== undefined) {
generationConfig.maxOutputTokens = advancedParams.maxOutputTokens;
}
if (advancedParams.responseMimeType !== undefined && advancedParams.responseMimeType !== 'auto') {
generationConfig.responseMimeType = advancedParams.responseMimeType;
}
if (advancedParams.stopSequences !== undefined && advancedParams.stopSequences !== '') {
let stopSequences = [];
if (typeof advancedParams.stopSequences === 'string') {
stopSequences = advancedParams.stopSequences.split(',').map((s) => s.trim());
}
else if (Array.isArray(advancedParams.stopSequences)) {
stopSequences = advancedParams.stopSequences;
}
if (stopSequences.length > 0) {
generationConfig.stopSequences = stopSequences;
}
}
return generationConfig;
}
function prepareSafetySettings(advancedParams) {
const safetySettings = [];
if (advancedParams.safetySettings &&
advancedParams.safetySettings.values &&
Array.isArray(advancedParams.safetySettings.values)) {
const safetyValues = advancedParams.safetySettings.values;
safetyValues.forEach((setting) => {
if (setting.category && setting.threshold) {
safetySettings.push({
category: setting.category,
threshold: setting.threshold,
});
}
});
}
return safetySettings;
}
async function generateContent(apiKey, apiEndpoint, model, prompt, advancedParams) {
const endpoint = `${apiEndpoint}/models/${model}:generateContent?key=${apiKey}`;
const generationConfig = prepareGenerationConfig(advancedParams);
const systemInstructions = advancedParams.systemPrompt
? { role: 'user', parts: [{ text: `SYSTEM: ${advancedParams.systemPrompt}` }] }
: undefined;
const safetySettings = prepareSafetySettings(advancedParams);
const requestBody = {
contents: [
...(systemInstructions ? [systemInstructions] : []),
{
role: 'user',
parts: [{ text: prompt }],
},
],
generationConfig,
};
if (advancedParams.toolSelection) {
const toolSelection = advancedParams.toolSelection;
if (toolSelection === 'structuredOutput') {
if (!requestBody.generationConfig) {
requestBody.generationConfig = {};
}
requestBody.generationConfig.response_mime_type = 'application/json';
if (advancedParams.jsonSchema) {
try {
const schema = JSON.parse(advancedParams.jsonSchema);
requestBody.generationConfig.response_schema = schema;
}
catch (error) {
console.error('Invalid JSON schema provided:', error);
}
}
}
else if (toolSelection === 'codeExecution') {
if (model === 'gemini-2.0-flash' ||
model === 'gemini-2.0-flash-lite' ||
model === 'gemini-2.0-pro-exp-02-05' ||
model === 'gemini-2.0-flash-thinking-exp-01-21' ||
model === 'gemini-1.5-pro' ||
model === 'gemini-1.5-flash' ||
model === 'gemini-1.5-flash-8b') {
requestBody.tools = [{ "code_execution": {} }];
}
}
else if (toolSelection === 'googleSearch') {
if (model === 'gemini-2.0-flash' ||
model === 'gemini-2.0-pro-exp-02-05' ||
model === 'gemini-1.5-pro' ||
model === 'gemini-1.5-flash' ||
model === 'gemini-1.5-flash-8b') {
requestBody.tools = [{ "google_search": {} }];
}
}
}
else {
if (advancedParams.responseMimeType === 'application/json') {
if (!requestBody.generationConfig) {
requestBody.generationConfig = {};
}
requestBody.generationConfig.response_mime_type = 'application/json';
}
if (advancedParams.enableCodeExecution === true) {
if (model === 'gemini-2.0-flash' ||
model === 'gemini-2.0-flash-lite' ||
model === 'gemini-2.0-pro-exp-02-05' ||
model === 'gemini-2.0-flash-thinking-exp-01-21' ||
model === 'gemini-1.5-pro' ||
model === 'gemini-1.5-flash' ||
model === 'gemini-1.5-flash-8b') {
requestBody.tools = [{ "code_execution": {} }];
}
}
else if (advancedParams.enableGoogleSearch === true) {
if (model === 'gemini-2.0-flash' ||
model === 'gemini-2.0-pro-exp-02-05' ||
model === 'gemini-1.5-pro' ||
model === 'gemini-1.5-flash' ||
model === 'gemini-1.5-flash-8b') {
requestBody.tools = [{ "google_search": {} }];
}
}
}
if (model === 'gemini-2.0-flash-exp-image-generation') {
if (!requestBody.generationConfig) {
requestBody.generationConfig = {};
}
requestBody.generationConfig.responseModalities = ['Text', 'Image'];
}
if (safetySettings.length > 0) {
requestBody.safetySettings = safetySettings;
}
return axios_1.default.post(endpoint, requestBody, {
headers: {
'Content-Type': 'application/json',
},
}).then((response) => response.data);
}
async function chatWithModel(apiKey, apiEndpoint, model, messages, advancedParams) {
const endpoint = `${apiEndpoint}/models/${model}:generateContent?key=${apiKey}`;
const generationConfig = prepareGenerationConfig(advancedParams);
if (advancedParams.systemPrompt) {
messages.unshift({
role: 'user',
parts: [{ text: `SYSTEM: ${advancedParams.systemPrompt}` }],
});
}
const safetySettings = prepareSafetySettings(advancedParams);
const requestBody = {
contents: messages,
generationConfig,
};
if (advancedParams.toolSelection) {
const toolSelection = advancedParams.toolSelection;
if (toolSelection === 'structuredOutput') {
if (!requestBody.generationConfig) {
requestBody.generationConfig = {};
}
requestBody.generationConfig.response_mime_type = 'application/json';
if (advancedParams.jsonSchema) {
try {
const schema = JSON.parse(advancedParams.jsonSchema);
requestBody.generationConfig.response_schema = schema;
}
catch (error) {
console.error('Invalid JSON schema provided:', error);
}
}
}
else if (toolSelection === 'codeExecution') {
if (model === 'gemini-2.0-flash' ||
model === 'gemini-2.0-flash-lite' ||
model === 'gemini-2.0-pro-exp-02-05' ||
model === 'gemini-2.0-flash-thinking-exp-01-21' ||
model === 'gemini-1.5-pro' ||
model === 'gemini-1.5-flash' ||
model === 'gemini-1.5-flash-8b') {
requestBody.tools = [{ "code_execution": {} }];
}
}
else if (toolSelection === 'googleSearch') {
if (model === 'gemini-2.0-flash' ||
model === 'gemini-2.0-pro-exp-02-05' ||
model === 'gemini-1.5-pro' ||
model === 'gemini-1.5-flash' ||
model === 'gemini-1.5-flash-8b') {
requestBody.tools = [{ "google_search": {} }];
}
}
}
else {
if (advancedParams.responseMimeType === 'application/json') {
if (!requestBody.generationConfig) {
requestBody.generationConfig = {};
}
requestBody.generationConfig.response_mime_type = 'application/json';
}
if (advancedParams.enableCodeExecution === true) {
if (model === 'gemini-2.0-flash' ||
model === 'gemini-2.0-flash-lite' ||
model === 'gemini-2.0-pro-exp-02-05' ||
model === 'gemini-2.0-flash-thinking-exp-01-21' ||
model === 'gemini-1.5-pro' ||
model === 'gemini-1.5-flash' ||
model === 'gemini-1.5-flash-8b') {
requestBody.tools = [{ "code_execution": {} }];
}
}
else if (advancedParams.enableGoogleSearch === true) {
if (model === 'gemini-2.0-flash' ||
model === 'gemini-2.0-pro-exp-02-05' ||
model === 'gemini-1.5-pro' ||
model === 'gemini-1.5-flash' ||
model === 'gemini-1.5-flash-8b') {
requestBody.tools = [{ "google_search": {} }];
}
}
}
if (model === 'gemini-2.0-flash-exp-image-generation') {
if (!requestBody.generationConfig) {
requestBody.generationConfig = {};
}
requestBody.generationConfig.responseModalities = ['Text', 'Image'];
}
if (safetySettings.length > 0) {
requestBody.safetySettings = safetySettings;
}
const response = await axios_1.default.post(endpoint, requestBody, {
headers: {
'Content-Type': 'application/json',
},
});
return response.data;
}
async function analyzeImage(apiKey, apiEndpoint, model, imageUrl, mediaType, imagePrompt, advancedParams) {
const endpoint = `${apiEndpoint}/models/${model}:generateContent?key=${apiKey}`;
if (!model.includes('vision') && !model.includes('2.0')) {
model = 'gemini-1.5-pro-vision';
}
const generationConfig = prepareGenerationConfig(advancedParams);
const safetySettings = prepareSafetySettings(advancedParams);
let mimeType = 'image/jpeg';
if (mediaType === 'video') {
mimeType = 'video/mp4';
}
else if (mediaType === 'audio') {
mimeType = 'audio/mp3';
}
const requestBody = {
contents: [
{
role: 'user',
parts: [
{ text: imagePrompt },
{
inline_data: {
mime_type: mimeType,
data: imageUrl,
},
},
],
},
],
generationConfig,
};
if (advancedParams.toolSelection) {
const toolSelection = advancedParams.toolSelection;
if (toolSelection === 'structuredOutput') {
if (!requestBody.generationConfig) {
requestBody.generationConfig = {};
}
requestBody.generationConfig.response_mime_type = 'application/json';
if (advancedParams.jsonSchema) {
try {
const schema = JSON.parse(advancedParams.jsonSchema);
requestBody.generationConfig.response_schema = schema;
}
catch (error) {
console.error('Invalid JSON schema provided:', error);
}
}
}
else if (toolSelection === 'codeExecution') {
if (model === 'gemini-2.0-flash' ||
model === 'gemini-2.0-flash-lite' ||
model === 'gemini-2.0-pro-exp-02-05' ||
model === 'gemini-2.0-flash-thinking-exp-01-21' ||
model === 'gemini-1.5-pro' ||
model === 'gemini-1.5-flash' ||
model === 'gemini-1.5-flash-8b') {
requestBody.tools = [{ "code_execution": {} }];
}
}
else if (toolSelection === 'googleSearch') {
if (model === 'gemini-2.0-flash' ||
model === 'gemini-2.0-pro-exp-02-05' ||
model === 'gemini-1.5-pro' ||
model === 'gemini-1.5-flash' ||
model === 'gemini-1.5-flash-8b') {
requestBody.tools = [{ "google_search": {} }];
}
}
}
else {
if (advancedParams.responseMimeType === 'application/json') {
if (!requestBody.generationConfig) {
requestBody.generationConfig = {};
}
requestBody.generationConfig.response_mime_type = 'application/json';
}
if (advancedParams.enableCodeExecution === true) {
if (model === 'gemini-2.0-flash' ||
model === 'gemini-2.0-flash-lite' ||
model === 'gemini-2.0-pro-exp-02-05' ||
model === 'gemini-2.0-flash-thinking-exp-01-21' ||
model === 'gemini-1.5-pro' ||
model === 'gemini-1.5-flash' ||
model === 'gemini-1.5-flash-8b') {
requestBody.tools = [{ "code_execution": {} }];
}
}
else if (advancedParams.enableGoogleSearch === true) {
if (model === 'gemini-2.0-flash' ||
model === 'gemini-2.0-pro-exp-02-05' ||
model === 'gemini-1.5-pro' ||
model === 'gemini-1.5-flash' ||
model === 'gemini-1.5-flash-8b') {
requestBody.tools = [{ "google_search": {} }];
}
}
}
if (model === 'gemini-2.0-flash-exp-image-generation') {
if (!requestBody.generationConfig) {
requestBody.generationConfig = {};
}
requestBody.generationConfig.responseModalities = ['Text', 'Image'];
}
if (safetySettings.length > 0) {
requestBody.safetySettings = safetySettings;
}
const response = await axios_1.default.post(endpoint, requestBody, {
headers: {
'Content-Type': 'application/json',
},
});
return response.data;
}
class GeminiIAStudio extends n8n_workflow_1.INodeType {
constructor() {
super();
this.description = {
displayName: 'Gemini AI Studio',
name: 'geminiIAStudio',
icon: 'file:google-gemini-icon.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["model"]}}',
description: 'Generate content using Google Gemini API',
defaults: {
name: 'Gemini AI Studio',
color: '#1A73E8',
},
inputs: [{ type: 'main' }],
outputs: [{ type: 'main' }],
credentials: [
{
name: 'geminiApi',
required: true,
},
],
properties: [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Generate Content',
value: 'generateContent',
description: 'Generate content with Gemini',
action: 'Generate content with Gemini',
},
{
name: 'Chat',
value: 'chat',
description: 'Have a multi-turn conversation with Gemini',
action: 'Chat with Gemini',
},
{
name: 'Analyze Media',
value: 'analyzeImage',
description: 'Analyze images, videos, or audio with Gemini',
action: 'Analyze media with Gemini',
},
],
default: 'generateContent',
},
{
displayName: 'Model',
name: 'model',
type: 'options',
options: [
{
name: 'Gemini 2.0 Flash',
value: 'gemini-2.0-flash',
description: 'Fast model with great balance of speed and capability, supports multimodal input/output',
},
{
name: 'Gemini 2.0 Flash-Lite',
value: 'gemini-2.0-flash-lite',
description: 'A Gemini 2.0 Flash model optimized for cost efficiency and low latency',
},
{
name: 'Gemini 2.0 Pro Experimental (02-05)',
value: 'gemini-2.0-pro-exp-02-05',
description: 'Experimental version with advanced capabilities',
},
{
name: 'Gemini 2.0 Flash Thinking Experimental (01-21)',
value: 'gemini-2.0-flash-thinking-exp-01-21',
description: 'Experimental version with enhanced reasoning capabilities',
},
{
name: 'Gemini 2.0 Flash Exp Image Generation',
value: 'gemini-2.0-flash-exp-image-generation',
description: 'Experimental version that can generate images',
},
{
name: 'Gemini 1.5 Flash',
value: 'gemini-1.5-flash',
description: 'Fast and versatile performance across a diverse variety of tasks',
},
{
name: 'Gemini 1.5 Flash-8B',
value: 'gemini-1.5-flash-8b',
description: 'High volume and lower intelligence tasks',
},
{
name: 'Gemini 1.5 Pro',
value: 'gemini-1.5-pro',
description: 'Complex reasoning tasks requiring more intelligence',
},
{
name: 'Gemma 3 27B',
value: 'gemma-3-27b',
description: 'Open model from Google with 27B parameters, great for various tasks',
}
],
default: 'gemini-2.0-flash',
description: 'The AI model to use',
},
{
displayName: 'Prompt',
name: 'prompt',
type: 'string',
typeOptions: {
rows: 4,
},
default: '',
required: true,
displayOptions: {
show: {
operation: ['generateContent', 'chat'],
},
},
description: 'The text prompt to send to Gemini',
},
{
displayName: 'Include Previous Messages',
name: 'includePreviousMessages',
type: 'boolean',
default: false,
displayOptions: {
show: {
operation: ['chat'],
},
},
description: 'Whether to include previous messages from input data',
},
{
displayName: 'Previous Messages Field',
name: 'previousMessagesField',
type: 'string',
default: 'messages',
displayOptions: {
show: {
operation: ['chat'],
includePreviousMessages: [true],
},
},
description: 'The name of the field in the input that contains previous messages',
},
{
displayName: 'Media URL Field',
name: 'imageUrlField',
type: 'string',
default: 'mediaUrl',
displayOptions: {
show: {
operation: ['analyzeImage'],
},
},
description: 'The field in the input that contains the image, video, or audio URL to analyze',
required: true,
},
{
displayName: 'Media Type',
name: 'mediaType',
type: 'options',
options: [
{
name: 'Image',
value: 'image',
description: 'Process an image file (JPEG, PNG, etc.)'
},
{
name: 'Video',
value: 'video',
description: 'Process a video file (MP4, etc.)'
},
{
name: 'Audio',
value: 'audio',
description: 'Process an audio file (MP3, etc.)'
},
],
default: 'image',
displayOptions: {
show: {
operation: ['analyzeImage'],
},
},
description: 'The type of media to analyze',
required: true,
},
{
displayName: 'Analysis Prompt',
name: 'imagePrompt',
type: 'string',
typeOptions: {
rows: 2,
},
default: 'Analyze this content in detail.',
displayOptions: {
show: {
operation: ['analyzeImage'],
},
},
description: 'The prompt to send with the media',
required: true,
},
{
displayName: 'Advanced Parameters',
name: 'advancedParameters',
type: 'collection',
placeholder: 'Add Parameter',
default: {},
options: [
{
displayName: 'Temperature',
name: 'temperature',
type: 'number',
typeOptions: {
minValue: 0,
maxValue: 2,
numberPrecision: 2,
},
default: 1,
description: 'Controls randomness (0 = deterministic, 2 = maximum randomness)',
},
{
displayName: 'Top P',
name: 'topP',
type: 'number',
typeOptions: {
minValue: 0,
maxValue: 1,
numberPrecision: 2,
},
default: 0.95,
description: 'Nucleus sampling - considers tokens with top_p probability mass (0.95 = 95% probability mass)',
},
{
displayName: 'Top K',
name: 'topK',
type: 'number',
typeOptions: {
minValue: 1,
maxValue: 100,
},
default: 40,
description: 'Consider only the top-k tokens (1 = greedy decoding)',
},
{
displayName: 'Maximum Output Tokens',
name: 'maxOutputTokens',
type: 'number',
typeOptions: {
minValue: 1,
maxValue: 8192,
},
default: 8192,
description: 'Maximum number of tokens to generate',
},
{
displayName: 'Stop Sequences',
name: 'stopSequences',
type: 'string',
typeOptions: {
multipleValues: true,
},
default: '',
description: 'Sequences that will cause the model to stop generating (comma separated)',
},
{
displayName: 'Tool Selection (Choose One)',
name: 'toolSelection',
type: 'options',
options: [
{
name: 'None',
value: 'none',
description: 'No special tools enabled',
},
{
name: 'Structured Output (JSON)',
value: 'structuredOutput',
description: 'Force model to return valid JSON',
},
{
name: 'Code Execution',
value: 'codeExecution',
description: 'Enable code execution capabilities',
},
{
name: 'Google Search',
value: 'googleSearch',
description: 'Enable Google Search grounding for factual responses',
},
],
default: 'none',
description: 'Select one special capability for the model (only one can be enabled at a time)',
displayOptions: {
show: {
'/model': [
'gemini-2.0-flash',
'gemini-2.0-flash-lite',
'gemini-2.0-pro-exp-02-05',
'gemini-2.0-flash-thinking-exp-01-21',
'gemini-1.5-flash',
'gemini-1.5-flash-8b',
'gemini-1.5-pro'
],
},
},
},
{
displayName: 'JSON Schema Definition',
name: 'jsonSchema',
type: 'string',
typeOptions: {
rows: 10,
},
default: '{\n "type": "object",\n "properties": {\n "response": {\n "type": "string"\n }\n }\n}',
description: 'Enter an OpenAPI schema object to constrain the model output. See the <a href="https://spec.openapis.org/oas/v3.0.3#schema" target="_blank">OpenAPI specification</a> and <a href="https://ai.google.dev/gemini-api/docs/api-overview#json" target="_blank">Gemini API documentation</a> for examples.',
displayOptions: {
show: {
toolSelection: ['structuredOutput'],
},
},
},
{
displayName: 'System Prompt',
name: 'systemPrompt',
type: 'string',
typeOptions: {
rows: 4,
},
default: '',
description: 'System prompt that helps set the behavior of the model',
},
{
displayName: 'Safety Settings',
name: 'safetySettings',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
},
default: {},
options: [
{
name: 'values',
displayName: 'Safety Setting',
values: [
{
displayName: 'Category',
name: 'category',
type: 'options',
options: [
{ name: 'Harassment', value: 'HARM_CATEGORY_HARASSMENT' },
{ name: 'Hate Speech', value: 'HARM_CATEGORY_HATE_SPEECH' },
{ name: 'Sexually Explicit', value: 'HARM_CATEGORY_SEXUALLY_EXPLICIT' },
{ name: 'Dangerous Content', value: 'HARM_CATEGORY_DANGEROUS_CONTENT' },
],
default: 'HARM_CATEGORY_HARASSMENT',
},
{
displayName: 'Threshold',
name: 'threshold',
type: 'options',
options: [
{ name: 'Block None', value: 'BLOCK_NONE' },
{ name: 'Block Low and Above', value: 'BLOCK_LOW_AND_ABOVE' },
{ name: 'Block Medium and Above', value: 'BLOCK_MEDIUM_AND_ABOVE' },
{ name: 'Block High and Above', value: 'BLOCK_HIGH_AND_ABOVE' },
{ name: 'Block All', value: 'BLOCK_ALL' },
],
default: 'BLOCK_MEDIUM_AND_ABOVE',
},
],
},
],
},
{
displayName: 'Response Format (Legacy)',
name: 'responseMimeType',
type: 'options',
options: [
{
name: 'Auto',
value: 'auto',
description: 'Let the model decide the appropriate format',
},
{
name: 'JSON',
value: 'application/json',
description: 'Force model to return valid JSON',
},
{
name: 'Text',
value: 'text/plain',
description: 'Plain text response',
},
{
name: 'Markdown',
value: 'text/markdown',
description: 'Markdown formatted text',
},
],
default: 'auto',
description: 'The desired format of the response',
displayOptions: {
show: {
toolSelection: ['none'],
},
},
},
{
displayName: 'Enable Google Search Grounding (Legacy)',
name: 'enableGoogleSearch',
type: 'boolean',
default: false,
description: 'Whether to enable Google Search grounding. Note: Only available for certain models and cannot be combined with other tools.',
displayOptions: {
show: {
toolSelection: ['none'],
},
},
},
{
displayName: 'Enable Code Execution (Legacy)',
name: 'enableCodeExecution',
type: 'boolean',
default: false,
description: 'Whether to enable code execution capabilities. Note: Only available for certain models and cannot be combined with other tools.',
displayOptions: {
show: {
toolSelection: ['none'],
},
},
},
],
},
],
};
}
async execute() {
var _a, _b, _c, _d;
const items = this.getInputData();
const returnData = [];
const credentials = await this.getCredentials('geminiApi');
const apiKey = credentials.apiKey;
const apiEndpoint = credentials.apiEndpoint || 'https://generativelanguage.googleapis.com/v1beta';
for (let i = 0; i < items.length; i++) {
try {
const operation = this.getNodeParameter('operation', i);
const model = this.getNodeParameter('model', i);
const advancedParams = this.getNodeParameter('advancedParameters', i, {});
let responseData;
if (operation === 'generateContent') {
const prompt = this.getNodeParameter('prompt', i);
responseData = await generateContent(apiKey, apiEndpoint, model, prompt, advancedParams);
}
else if (operation === 'chat') {
const prompt = this.getNodeParameter('prompt', i);
const includePreviousMessages = this.getNodeParameter('includePreviousMessages', i, false);
let messages = [{
role: 'user',
parts: [{ text: prompt }],
}];
if (includePreviousMessages) {
const previousMessagesField = this.getNodeParameter('previousMessagesField', i);
const previousMessages = items[i].json[previousMessagesField] || [];
if (Array.isArray(previousMessages) && previousMessages.length > 0) {
const convertedMessages = previousMessages.map(msg => ({
role: msg.role === 'user' ? 'user' : 'model',
parts: [{ text: msg.content }],
}));
messages = [...convertedMessages, ...messages];
}
}
responseData = await chatWithModel(apiKey, apiEndpoint, model, messages, advancedParams);
}
else if (operation === 'analyzeImage') {
const imageUrlField = this.getNodeParameter('imageUrlField', i);
const imageUrl = items[i].json[imageUrlField];
const mediaType = this.getNodeParameter('mediaType', i);
const imagePrompt = this.getNodeParameter('imagePrompt', i);
if (!imageUrl) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Image URL is required for image analysis', {
itemIndex: i,
});
}
responseData = await analyzeImage(apiKey, apiEndpoint, model, imageUrl, mediaType, imagePrompt, advancedParams);
}
let outputData = {
...items[i].json,
geminiResponse: responseData,
};
if ((operation === 'generateContent' || operation === 'chat') && advancedParams.toolSelection === 'googleSearch') {
let searchResultsSummary = 'Google Search Results:\n\n';
let foundResults = false;
if (responseData && responseData.candidates && responseData.candidates.length > 0 && responseData.candidates[0].content && responseData.candidates[0].content.parts) {
for (const part of responseData.candidates[0].content.parts) {
if (part.tool_code && part.tool_code.tool_code_results && part.tool_code.tool_code_results.length > 0) {
for (const result of part.tool_code.tool_code_results) {
if (result.search_results && result.search_results.results && result.search_results.results.length > 0) {
foundResults = true;
for (const searchResult of result.search_results.results) {
if (searchResult.title && searchResult.snippet && searchResult.link) {
searchResultsSummary += `Title: ${searchResult.title}\n`;
searchResultsSummary += `Snippet: ${searchResult.snippet}\n`;
searchResultsSummary += `Link: ${searchResult.link}\n\n`;
}
}
}
}
}
}
}
if (foundResults) {
outputData.googleSearchResultsSummary = searchResultsSummary;
}
else {
outputData.googleSearchResultsSummary = 'No Google Search results found in the response.';
}
}
const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(outputData), { itemData: { item: i } });
returnData.push(...executionData);
}
catch (error) {
if (error.response) {
const status = error.response.status;
const message = ((_c = (_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0 ? void 0 : _c.message) || 'Unknown API error';
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Gemini API Error: ${status} - ${message}`, {
itemIndex: i,
description: JSON.stringify(((_d = error.response) === null || _d === void 0 ? void 0 : _d.data) || {}),
});
}
else {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Error: ${error.message}`, {
itemIndex: i,
});
}
}
}
return [returnData];
}
}
exports.GeminiIAStudio = GeminiIAStudio;
//# sourceMappingURL=GeminiGrounding.node.js.map