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
JavaScript
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
;