UNPKG

n8n-nodes-gemini-search

Version:

n8n nodes to interact with Google Gemini API for search and content generation

266 lines 12.1 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.GeminiSearchTool = void 0; const GenericFunctions_1 = require("./GenericFunctions"); const axios_1 = __importDefault(require("axios")); const instructionBuilder_1 = require("./instructionBuilder"); class GeminiSearchTool { constructor() { this.description = { displayName: 'Gemini Search Tool', name: 'geminiSearchTool', icon: 'file:gemini.svg', group: ['transform'], version: 1, description: 'Use Google Gemini as a search tool', defaults: { name: 'Gemini Search Tool', }, inputs: [{ type: 'main', required: true }], outputs: [{ type: 'main', required: true }], usableAsTool: true, credentials: [ { name: 'geminiSearchApi', required: true, }, ], properties: [ { displayName: 'Query', name: 'query', type: 'string', default: '', required: true, description: 'The search query to execute with Gemini', }, { displayName: 'Model', name: 'model', type: 'options', options: [ { name: 'Gemini 1.0 Pro', value: 'gemini-1.0-pro', }, { name: 'Gemini 1.5 Pro', value: 'gemini-1.5-pro', }, { name: 'Gemini 2.0 Flash', value: 'gemini-2.0-flash', }, { name: 'Gemini 2.0 Pro', value: 'gemini-2.0-pro', }, { name: 'Gemini 2.5 Pro', value: 'gemini-2.5-pro', }, ], default: 'gemini-2.0-flash', description: 'The Gemini model to use', }, { displayName: 'Organization Context', name: 'organization', type: 'string', default: '', description: 'Optional organization name to use as context for search', }, { displayName: 'Restrict Search to URLs', name: 'restrictUrls', type: 'string', default: '', placeholder: 'example.com,docs.example.com', description: 'Optional comma-separated list of URLs to restrict search to', }, { displayName: 'Options', name: 'options', type: 'collection', placeholder: 'Add Option', default: {}, options: [ { displayName: 'Temperature', name: 'temperature', type: 'number', typeOptions: { minValue: 0, maxValue: 1, numberPrecision: 1, }, default: 0.6, description: 'Controls randomness in the response (0-1)', }, { displayName: 'Max Output Tokens', name: 'maxOutputTokens', type: 'number', default: 2048, description: 'Maximum number of tokens to generate', }, { displayName: 'Custom System Instruction', name: 'systemInstruction', type: 'string', typeOptions: { rows: 4, }, default: '', description: 'Override the default system instruction', }, { displayName: 'Return Full Response', name: 'returnFullResponse', type: 'boolean', default: false, description: 'Whether to return the full API response', }, { displayName: 'Extract Source URL', name: 'extractSourceUrl', type: 'boolean', default: false, description: 'Whether to extract the source URL from the response', }, ], }, ], }; } async execute() { var _a, _b, _c, _d, _e; const items = this.getInputData(); const returnData = []; for (let i = 0; i < items.length; i++) { try { const query = this.getNodeParameter('query', i); const model = this.getNodeParameter('model', i); const organization = this.getNodeParameter('organization', i, ''); const restrictUrls = this.getNodeParameter('restrictUrls', i, ''); const options = this.getNodeParameter('options', i, {}); const finalSystemInstruction = (0, instructionBuilder_1.buildSystemInstruction)({ systemInstruction: options.systemInstruction, organization, restrictUrls, }); const requestBody = { contents: [ { role: 'user', parts: [ { text: query, }, ], }, ], generationConfig: { temperature: options.temperature || 0.6, topP: 1, topK: 1, maxOutputTokens: options.maxOutputTokens || 2048, responseMimeType: 'text/plain', }, tools: [ { googleSearch: {}, }, ], }; if (finalSystemInstruction) { requestBody.systemInstruction = { parts: [ { text: finalSystemInstruction, }, ], }; } const response = await GenericFunctions_1.geminiRequest.call(this, model, requestBody); const extractSourceUrl = (responseObj) => { var _a, _b, _c, _d, _e, _f; const possiblePaths = [ (_f = (_e = (_d = (_c = (_b = (_a = responseObj === null || responseObj === void 0 ? void 0 : responseObj.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.groundingMetadata) === null || _c === void 0 ? void 0 : _c.groundingChunks) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.web) === null || _f === void 0 ? void 0 : _f.uri, ]; return (possiblePaths.find((url) => typeof url === 'string' && (url.startsWith('http://') || url.startsWith('https://'))) || ''); }; const getRedirectedUrl = async (url) => { var _a, _b, _c, _d; if (!url) return ''; try { const response = await axios_1.default.head(url, { maxRedirects: 10, timeout: 5000, validateStatus: null, headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', }, }); const finalUrl = ((_b = (_a = response.request) === null || _a === void 0 ? void 0 : _a.res) === null || _b === void 0 ? void 0 : _b.responseUrl) || ((_c = response.request) === null || _c === void 0 ? void 0 : _c.responseURL) || (typeof response.request === 'object' && 'res' in response.request ? (_d = response.request.res.headers) === null || _d === void 0 ? void 0 : _d.location : null) || url; return finalUrl; } catch (error) { console.error(`Error fetching redirected URL: ${error.message}`); return url; } }; const outputData = { result: ((_e = (_d = (_c = (_b = (_a = response.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.text) || '', query, organization, restrictedUrls: restrictUrls || undefined, }; if (options.extractSourceUrl) { const sourceUrl = extractSourceUrl(response); outputData.sourceUrl = sourceUrl; if (sourceUrl) { try { outputData.redirectedSourceUrl = await getRedirectedUrl(sourceUrl); } catch (error) { outputData.redirectedSourceUrl = sourceUrl; } } } if (options.returnFullResponse) { outputData.fullResponse = response; } returnData.push({ json: outputData, pairedItem: { item: i }, }); } catch (error) { if (this.continueOnFail()) { returnData.push({ json: { error: error.message, }, pairedItem: { item: i }, }); continue; } throw error; } } return [returnData]; } } exports.GeminiSearchTool = GeminiSearchTool; //# sourceMappingURL=GeminiSearchTool.node.js.map