UNPKG

n8n-nodes-openai-gpt5

Version:

n8n node for OpenAI GPT-5 with PDF processing, web search, and timeout configuration via Responses API

298 lines 12.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.OpenAiGpt5 = void 0; const n8n_workflow_1 = require("n8n-workflow"); class OpenAiGpt5 { constructor() { this.description = { displayName: 'OpenAI GPT-5', name: 'openAiGpt5', icon: 'file:openai.svg', group: ['transform'], version: 1, subtitle: 'Process files with GPT-5', description: 'Process PDFs and images with OpenAI GPT-5', defaults: { name: 'OpenAI GPT-5', }, inputs: ['main'], outputs: ['main'], credentials: [ { name: 'openAiGpt5Api', required: true, }, ], properties: [ { displayName: 'Prompt', name: 'prompt', type: 'string', typeOptions: { rows: 4, }, default: 'Analyze these files and provide insights.', required: true, description: 'What you want GPT-5 to do with the files', }, { displayName: 'PDF Files', name: 'pdfFiles', type: 'json', default: '', placeholder: 'file_abc123 or ["file_1", "file_2"] or {{ $json.pdfIds }}', description: 'PDF file IDs (upload PDFs first to get IDs). Single ID, array, or expression.', }, { displayName: 'Images', name: 'imageFiles', type: 'json', default: '', placeholder: 'https://url.jpg or ["url1", "url2"] or {{ $json.images }}', description: 'Image URLs or file IDs. Single value, array, or expression.', }, { displayName: 'Options', name: 'options', type: 'collection', placeholder: 'Add Option', default: {}, options: [ { displayName: 'Model', name: 'model', type: 'options', options: [ { name: 'GPT-5', value: 'gpt-5', description: 'Most capable GPT-5 model', }, { name: 'GPT-5 Mini', value: 'gpt-5-mini', description: 'Smaller, faster GPT-5 variant', }, { name: 'O3', value: 'o3', description: 'Advanced reasoning model', }, { name: 'O3 Mini', value: 'o3-mini', description: 'Smaller O3 variant', }, ], default: 'gpt-5', description: 'The OpenAI model to use', }, { displayName: 'Max Tokens', name: 'maxTokens', type: 'number', default: 4096, description: 'Maximum number of tokens to generate', }, { displayName: 'Reasoning Effort', name: 'reasoningEffort', type: 'options', options: [ { name: 'Low', value: 'low', description: 'Faster responses', }, { name: 'Medium', value: 'medium', description: 'Balanced (default)', }, { name: 'High', value: 'high', description: 'Maximum reasoning', }, ], default: 'medium', description: 'Reasoning effort level', }, ], }, ], }; } async execute() { const items = this.getInputData(); const returnData = []; const credentials = await this.getCredentials('openAiGpt5Api'); const baseUrl = credentials.baseUrl || 'https://api.openai.com'; // Helper function to parse file inputs const parseFileInput = (input) => { if (!input) return []; // Already an array if (Array.isArray(input)) { return input.map(item => String(item).trim()).filter(item => item); } // String input if (typeof input === 'string') { const trimmed = input.trim(); if (!trimmed) return []; // Check if it's comma-separated if (trimmed.includes(',')) { return trimmed.split(',').map(s => s.trim()).filter(s => s); } // Single item return [trimmed]; } // Other types - try to convert to string const str = String(input).trim(); return str ? [str] : []; }; for (let i = 0; i < items.length; i++) { try { const prompt = this.getNodeParameter('prompt', i); const pdfFiles = this.getNodeParameter('pdfFiles', i, ''); const imageFiles = this.getNodeParameter('imageFiles', i, ''); const options = this.getNodeParameter('options', i, {}); const model = options.model || 'gpt-5'; // Build request body const requestBody = { model, }; // Parse file inputs const pdfIds = parseFileInput(pdfFiles); const images = parseFileInput(imageFiles); // Build content array const contentArray = [ { type: 'input_text', text: prompt, }, ]; // Add PDF files for (const pdfId of pdfIds) { if (pdfId.startsWith('file_')) { contentArray.push({ type: 'input_file', file_id: pdfId, }); } } // Add images for (const image of images) { if (image.startsWith('file_')) { // File ID contentArray.push({ type: 'input_image', file_id: image, }); } else if (image.includes('http://') || image.includes('https://')) { // URL contentArray.push({ type: 'input_image', image: { url: image, }, }); } } // Use array structure if we have files, otherwise simple string if (pdfIds.length > 0 || images.length > 0) { requestBody.input = [ { role: 'user', content: contentArray, }, ]; } else { // Text-only request requestBody.input = prompt; } // Add optional parameters if (options.maxTokens) { requestBody.max_tokens = options.maxTokens; } // Add reasoning configuration for supported models if (options.reasoningEffort && String(model).startsWith('gpt-5')) { requestBody.reasoning = { effort: options.reasoningEffort, }; } // Make API request const responseOptions = { method: 'POST', url: `${baseUrl}/v1/responses`, headers: { 'Authorization': `Bearer ${credentials.apiKey}`, 'Content-Type': 'application/json', }, body: requestBody, json: true, }; if (credentials.organizationId) { responseOptions.headers['OpenAI-Organization'] = credentials.organizationId; } const response = await this.helpers.httpRequest(responseOptions); // Extract text from response let textContent = ''; if (response.output && response.output[0]) { const output = response.output[0]; if (output.content && output.content[0]) { textContent = output.content[0].text || ''; } } // Fallback to other possible structures if (!textContent && response.choices?.[0]?.message?.content) { textContent = response.choices[0].message.content; } const outputData = { text: textContent, model: response.model || model, usage: response.usage, pdfCount: pdfIds.length, imageCount: images.length, }; const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(outputData), { itemData: { item: i } }); returnData.push(...executionData); } catch (error) { // Error handling let errorMessage = 'Unknown error'; let errorDetails = {}; if (error.response) { errorMessage = error.response.statusText || `HTTP ${error.response.status}`; if (error.response.body) { errorDetails = error.response.body; if (error.response.body.error) { errorMessage = error.response.body.error.message || errorMessage; } } } else if (error.message) { errorMessage = error.message; } if (this.continueOnFail()) { const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ error: errorMessage, details: errorDetails, }), { itemData: { item: i } }); returnData.push(...executionData); continue; } const nodeError = new n8n_workflow_1.NodeOperationError(this.getNode(), errorMessage, { description: errorDetails.error?.message || undefined, }); throw nodeError; } } return [returnData]; } } exports.OpenAiGpt5 = OpenAiGpt5; //# sourceMappingURL=OpenAiGpt5.node.simple.js.map