n8n-nodes-universal-llm-vision 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +131 -0
  3. package/dist/credentials/UniversalLlmVisionApi.credentials.d.ts +8 -0
  4. package/dist/credentials/UniversalLlmVisionApi.credentials.js +63 -0
  5. package/dist/credentials/UniversalLlmVisionApi.credentials.js.map +1 -0
  6. package/dist/docs/img/sample_analysis.png +0 -0
  7. package/dist/docs/img/sample_credential.png +0 -0
  8. package/dist/docs/img/sample_usage.png +0 -0
  9. package/dist/nodes/UniversalLlmVision/UniversalLlmVision.node.d.ts +5 -0
  10. package/dist/nodes/UniversalLlmVision/UniversalLlmVision.node.js +335 -0
  11. package/dist/nodes/UniversalLlmVision/UniversalLlmVision.node.js.map +1 -0
  12. package/dist/nodes/UniversalLlmVision/handlers/RequestHandler.d.ts +7 -0
  13. package/dist/nodes/UniversalLlmVision/handlers/RequestHandler.js +39 -0
  14. package/dist/nodes/UniversalLlmVision/handlers/RequestHandler.js.map +1 -0
  15. package/dist/nodes/UniversalLlmVision/processors/ImageProcessor.d.ts +28 -0
  16. package/dist/nodes/UniversalLlmVision/processors/ImageProcessor.js +280 -0
  17. package/dist/nodes/UniversalLlmVision/processors/ImageProcessor.js.map +1 -0
  18. package/dist/nodes/UniversalLlmVision/processors/ResponseProcessor.d.ts +3 -0
  19. package/dist/nodes/UniversalLlmVision/processors/ResponseProcessor.js +22 -0
  20. package/dist/nodes/UniversalLlmVision/processors/ResponseProcessor.js.map +1 -0
  21. package/dist/nodes/UniversalLlmVision/utils/GenericFunctions.d.ts +27 -0
  22. package/dist/nodes/UniversalLlmVision/utils/GenericFunctions.js +159 -0
  23. package/dist/nodes/UniversalLlmVision/utils/GenericFunctions.js.map +1 -0
  24. package/dist/nodes/UniversalLlmVision/utils/providers.d.ts +22 -0
  25. package/dist/nodes/UniversalLlmVision/utils/providers.js +150 -0
  26. package/dist/nodes/UniversalLlmVision/utils/providers.js.map +1 -0
  27. package/dist/nodes/UniversalLlmVision/vision.svg +18 -0
  28. package/dist/package.json +71 -0
  29. package/dist/tsconfig.tsbuildinfo +1 -0
  30. package/index.js +0 -0
  31. package/package.json +71 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alejandro Sanz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,131 @@
1
+ # n8n-nodes-universal-llm-vision
2
+
3
+ A comprehensive n8n community node for analyzing images using multiple LLM vision providers (OpenRouter, Groq, Grok, OpenAI, Anthropic, Google Gemini).
4
+
5
+ ## Installation
6
+
7
+ Install via n8n's community node interface:
8
+
9
+ 1. Open n8n in your browser
10
+ 2. Go to Settings > Community Nodes
11
+ 3. Search for "n8n-nodes-universal-llm-vision" and install
12
+
13
+ ## Features
14
+
15
+ - ✅ Image analysis using multiple LLM providers
16
+ - ✅ Support for binary data, URLs, and base64 images
17
+ - ✅ Flexible prompts and model parameters
18
+ - ✅ Metadata inclusion (usage, tokens)
19
+ - ✅ Custom headers and advanced parameters
20
+ - ✅ Comprehensive testing included
21
+ - ✅ n8n Agents compatible
22
+
23
+ ## Usage
24
+
25
+ ### Basic Setup
26
+
27
+ 1. Add the "Universal LLM Vision" node to your n8n workflow
28
+ 2. Configure your API credentials for the chosen provider
29
+ 3. Select image source and analysis parameters
30
+
31
+ ![Sample usage in a workflow](docs/img/sample_usage.png)
32
+
33
+ ### Supported Providers
34
+
35
+ - OpenAI
36
+ - Anthropic
37
+ - Groq
38
+ - Grok (X.AI)
39
+ - OpenRouter
40
+ - Google Gemini
41
+ - Custom
42
+
43
+ ### Supported Models
44
+
45
+ - GPT 5, GPT 4.1, GPT 4o, ... (OpenAI)
46
+ - Claude 4.5 Sonnet, Claude 4.5 Haiku, ... (Anthropic)
47
+ - Various vision models (OpenRouter)
48
+ - Gemini 3.0 Flash, ... (Google)
49
+ - Any compatible API (Custom)
50
+
51
+ ### Available Operations
52
+
53
+ - **Analyze Image**: Analyze images with custom prompts
54
+
55
+ ### Configuration
56
+
57
+ #### Credentials
58
+
59
+ Set up your API credentials:
60
+
61
+ - **Provider**: Select LLM provider (OpenAI, Anthropic, etc.)
62
+ - **API Key**: Your provider's API key
63
+ - **Base URL**: Custom API endpoint (optional, defaults provided)
64
+
65
+ #### Custom Provider Configuration
66
+
67
+ To use a custom OpenAI-compatible LLM vision API:
68
+
69
+ - Select "Custom Provider" and provide your API Key
70
+ - Set the Base URL (e.g., `https://your-api.com/v1`)
71
+
72
+ **Requirements**: API must support `/chat/completions` with OpenAI-style requests/responses and Bearer auth.
73
+
74
+ **Example**: Set Base URL to `https://my-vision-api.com/v1` and ensure vision support.
75
+
76
+ **Troubleshooting**: Check API key and endpoint for auth issues; verify OpenAI compatibility for format errors.
77
+
78
+ #### Node Parameters
79
+
80
+ - **Model**: Model identifier (e.g., gpt-4o)
81
+ - **Image Source**: Binary Data, URL, or Base64
82
+ - **Prompt**: Analysis prompt
83
+ - **Image Detail**: Auto/Low/High resolution
84
+ - **Model Parameters**: Temperature, Max Tokens, Top P
85
+ - **Advanced Options**: System prompt, response format, custom headers
86
+ - **Output**: Property name and metadata inclusion
87
+
88
+ ## Examples
89
+
90
+ ![Sample analysis result](docs/img/sample_analysis.png)
91
+
92
+ ### Analyze Image from Binary Data
93
+
94
+ 1. Use a "Download" node to fetch an image
95
+ 2. Connect to "Universal LLM Vision" node
96
+ 3. Set Image Source to "Binary Data"
97
+ 4. Configure prompt: "Describe this image in detail"
98
+
99
+ ### Analyze Image from URL
100
+
101
+ 1. Add "Universal LLM Vision" node
102
+ 2. Set Image Source to "URL"
103
+ 3. Provide image URL
104
+ 4. Use prompt: "Extract all text from this image (OCR)"
105
+
106
+
107
+ ## Development
108
+
109
+ This node was built using the [n8n-community-node-starter](https://github.com/alejandrosnz/n8n-community-node-starter) boilerplate, which provides:
110
+
111
+ - Programmatic node architecture for complex logic
112
+ - Built-in CI/CD pipelines
113
+ - Comprehensive testing framework
114
+ - AI-assisted development support
115
+
116
+ ### Contributing
117
+
118
+ 1. Fork the repository
119
+ 2. Create a feature branch
120
+ 3. Make your changes with tests
121
+ 4. Submit a pull request
122
+
123
+ ## License
124
+
125
+ MIT License - see LICENSE file.
126
+
127
+ ## Links
128
+
129
+ - [n8n Documentation](https://docs.n8n.io/)
130
+ - [Community Nodes Guide](https://docs.n8n.io/integrations/community-nodes/)
131
+ - [n8n-community-node-starter](https://github.com/alejandrosnz/n8n-community-node-starter) - The boilerplate this node is based on
@@ -0,0 +1,8 @@
1
+ import type { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class UniversalLlmVisionApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ properties: INodeProperties[];
6
+ authenticate: IAuthenticateGeneric;
7
+ test: ICredentialTestRequest;
8
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UniversalLlmVisionApi = void 0;
4
+ class UniversalLlmVisionApi {
5
+ constructor() {
6
+ this.name = 'universalLlmVisionApi';
7
+ this.displayName = 'Universal LLM Vision API';
8
+ this.properties = [
9
+ {
10
+ displayName: 'Provider',
11
+ name: 'provider',
12
+ type: 'options',
13
+ options: [
14
+ { name: 'OpenRouter', value: 'openrouter' },
15
+ { name: 'Groq', value: 'groq' },
16
+ { name: 'Grok (X.AI)', value: 'grok' },
17
+ { name: 'OpenAI', value: 'openai' },
18
+ { name: 'Anthropic', value: 'anthropic' },
19
+ { name: 'Google Gemini', value: 'gemini' },
20
+ { name: 'Custom Provider', value: 'custom' },
21
+ ],
22
+ default: 'openai',
23
+ required: true,
24
+ },
25
+ {
26
+ displayName: 'API Key',
27
+ name: 'apiKey',
28
+ type: 'string',
29
+ typeOptions: { password: true },
30
+ default: '',
31
+ required: true,
32
+ },
33
+ {
34
+ displayName: 'Base URL',
35
+ name: 'baseUrl',
36
+ type: 'string',
37
+ default: '',
38
+ placeholder: 'https://api.example.com/v1',
39
+ description: 'Leave empty to use default URL for the selected provider',
40
+ displayOptions: {
41
+ show: { provider: ['custom'] },
42
+ },
43
+ },
44
+ ];
45
+ this.authenticate = {
46
+ type: 'generic',
47
+ properties: {
48
+ headers: {
49
+ 'Authorization': '=Bearer {{$credentials.apiKey}}',
50
+ 'x-api-key': '={{$credentials.provider === "anthropic" ? $credentials.apiKey : undefined}}',
51
+ },
52
+ },
53
+ };
54
+ this.test = {
55
+ request: {
56
+ baseURL: '={{ $credentials.baseUrl || ($credentials.provider === "openrouter" ? "https://openrouter.ai/api/v1" : $credentials.provider === "groq" ? "https://api.groq.com/openai/v1" : $credentials.provider === "grok" ? "https://api.x.ai/v1" : $credentials.provider === "anthropic" ? "https://api.anthropic.com/v1" : "https://api.openai.com/v1") }}',
57
+ url: '/models',
58
+ },
59
+ };
60
+ }
61
+ }
62
+ exports.UniversalLlmVisionApi = UniversalLlmVisionApi;
63
+ //# sourceMappingURL=UniversalLlmVisionApi.credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UniversalLlmVisionApi.credentials.js","sourceRoot":"","sources":["../../credentials/UniversalLlmVisionApi.credentials.ts"],"names":[],"mappings":";;;AAOA,MAAa,qBAAqB;IAAlC;QACE,SAAI,GAAG,uBAAuB,CAAC;QAC/B,gBAAW,GAAG,0BAA0B,CAAC;QAEzC,eAAU,GAAsB;YAC9B;gBACE,WAAW,EAAE,UAAU;gBACvB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE;oBACP,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;oBAC3C,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;oBAC/B,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE;oBACtC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;oBACnC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE;oBACzC,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,QAAQ,EAAE;oBAC1C,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,QAAQ,EAAE;iBAC7C;gBACD,OAAO,EAAE,QAAQ;gBACjB,QAAQ,EAAE,IAAI;aACf;YACD;gBACE,WAAW,EAAE,SAAS;gBACtB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;aACf;YACD;gBACE,WAAW,EAAE,UAAU;gBACvB,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,4BAA4B;gBACzC,WAAW,EAAE,0DAA0D;gBACvE,cAAc,EAAE;oBACd,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE;iBAC/B;aACF;SACF,CAAC;QAEF,iBAAY,GAAyB;YACnC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACV,OAAO,EAAE;oBACP,eAAe,EAAE,iCAAiC;oBAClD,WAAW,EAAE,8EAA8E;iBAC5F;aACF;SACF,CAAC;QAEF,SAAI,GAA2B;YAC7B,OAAO,EAAE;gBACP,OAAO,EAAE,kVAAkV;gBAC3V,GAAG,EAAE,SAAS;aACf;SACF,CAAC;IACJ,CAAC;CAAA;AA1DD,sDA0DC"}
Binary file
@@ -0,0 +1,5 @@
1
+ import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class UniversalLlmVision implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,335 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UniversalLlmVision = void 0;
4
+ const ImageProcessor_1 = require("./processors/ImageProcessor");
5
+ const ResponseProcessor_1 = require("./processors/ResponseProcessor");
6
+ const RequestHandler_1 = require("./handlers/RequestHandler");
7
+ const ImageProcessor_2 = require("./processors/ImageProcessor");
8
+ class UniversalLlmVision {
9
+ constructor() {
10
+ this.description = {
11
+ displayName: 'Universal LLM Vision',
12
+ name: 'universalLlmVision',
13
+ icon: 'file:vision.svg',
14
+ group: ['transform'],
15
+ version: 1,
16
+ subtitle: '={{$parameter["model"] + " - " + $parameter["imageSource"]}}',
17
+ description: 'Analyze images using multiple LLM vision providers (OpenRouter, Groq, Grok, OpenAI, Anthropic, Google Gemini)',
18
+ defaults: {
19
+ name: 'Universal LLM Vision',
20
+ },
21
+ inputs: ['main'],
22
+ outputs: ['main'],
23
+ credentials: [
24
+ {
25
+ name: 'universalLlmVisionApi',
26
+ required: true,
27
+ },
28
+ ],
29
+ properties: [
30
+ {
31
+ displayName: 'Model',
32
+ name: 'model',
33
+ type: 'string',
34
+ required: true,
35
+ default: 'gpt-4-vision',
36
+ placeholder: 'gpt-4-vision',
37
+ description: 'Model identifier for the selected provider (e.g., gpt-4-vision, claude-3-sonnet)',
38
+ },
39
+ {
40
+ displayName: 'Image Source',
41
+ name: 'imageSource',
42
+ type: 'options',
43
+ required: true,
44
+ options: [
45
+ {
46
+ name: 'Binary Data (Uploaded File)',
47
+ value: 'binary',
48
+ description: 'Use file from previous node output',
49
+ },
50
+ {
51
+ name: 'Public URL',
52
+ value: 'url',
53
+ description: 'Provide image URL directly',
54
+ },
55
+ {
56
+ name: 'Base64 String',
57
+ value: 'base64',
58
+ description: 'Provide base64-encoded image data',
59
+ },
60
+ ],
61
+ default: 'binary',
62
+ },
63
+ {
64
+ displayName: 'Binary Property Name',
65
+ name: 'binaryPropertyName',
66
+ type: 'string',
67
+ default: 'data',
68
+ description: 'The name of the binary property containing the image',
69
+ displayOptions: {
70
+ show: { imageSource: ['binary'] },
71
+ },
72
+ },
73
+ {
74
+ displayName: 'Filename (Optional)',
75
+ name: 'filename',
76
+ type: 'string',
77
+ default: '',
78
+ description: 'Image filename (used for MIME type detection). If provided, overrides binary metadata',
79
+ displayOptions: {
80
+ show: { imageSource: ['binary'] },
81
+ },
82
+ },
83
+ {
84
+ displayName: 'Image URL',
85
+ name: 'imageUrl',
86
+ type: 'string',
87
+ default: '',
88
+ required: true,
89
+ placeholder: 'https://example.com/image.jpg',
90
+ description: 'HTTP(S) URL pointing to the image',
91
+ displayOptions: {
92
+ show: { imageSource: ['url'] },
93
+ },
94
+ },
95
+ {
96
+ displayName: 'Base64 Data',
97
+ name: 'base64Data',
98
+ type: 'string',
99
+ default: '',
100
+ required: true,
101
+ description: 'Base64-encoded image data (without data: URI prefix)',
102
+ displayOptions: {
103
+ show: { imageSource: ['base64'] },
104
+ },
105
+ },
106
+ {
107
+ displayName: 'Image Format (for Base64)',
108
+ name: 'base64MimeType',
109
+ type: 'options',
110
+ noDataExpression: true,
111
+ options: (0, ImageProcessor_2.getMimeTypeOptions)(),
112
+ default: 'image/jpeg',
113
+ description: 'MIME type of the base64-encoded image. Auto-detected if possible',
114
+ displayOptions: {
115
+ show: { imageSource: ['base64'] },
116
+ },
117
+ },
118
+ {
119
+ displayName: 'Prompt',
120
+ name: 'prompt',
121
+ type: 'string',
122
+ typeOptions: { rows: 4 },
123
+ required: true,
124
+ default: 'Describe what you see in this image in detail',
125
+ description: 'Question or instruction for analyzing the image',
126
+ placeholder: 'Describe the main objects, colors, composition, and any text visible in this image',
127
+ },
128
+ {
129
+ displayName: 'Model Parameters',
130
+ name: 'modelParameters',
131
+ type: 'collection',
132
+ placeholder: 'Add Parameter',
133
+ default: {},
134
+ options: [
135
+ {
136
+ displayName: 'Temperature',
137
+ name: 'temperature',
138
+ type: 'number',
139
+ typeOptions: {
140
+ minValue: 0,
141
+ maxValue: 2,
142
+ numberPrecision: 2,
143
+ },
144
+ default: 1,
145
+ description: 'Controls randomness (0=deterministic, 2=most random)',
146
+ },
147
+ {
148
+ displayName: 'Max Tokens',
149
+ name: 'maxTokens',
150
+ type: 'number',
151
+ default: 1024,
152
+ description: 'Maximum length of the response in tokens',
153
+ },
154
+ {
155
+ displayName: 'Top P',
156
+ name: 'topP',
157
+ type: 'number',
158
+ typeOptions: {
159
+ minValue: 0,
160
+ maxValue: 1,
161
+ numberPrecision: 2,
162
+ },
163
+ default: 1,
164
+ description: 'Controls diversity via nucleus sampling (0-1)',
165
+ },
166
+ {
167
+ displayName: 'Image Detail',
168
+ name: 'imageDetail',
169
+ type: 'options',
170
+ options: [
171
+ { name: 'Auto', value: 'auto' },
172
+ { name: 'Low (Fast)', value: 'low' },
173
+ { name: 'High (Detailed)', value: 'high' },
174
+ ],
175
+ default: 'auto',
176
+ description: 'Image resolution detail level (affects speed and cost). Not supported by all providers',
177
+ },
178
+ ],
179
+ },
180
+ {
181
+ displayName: 'Advanced Options',
182
+ name: 'advancedOptions',
183
+ type: 'collection',
184
+ placeholder: 'Add Option',
185
+ default: {},
186
+ options: [
187
+ {
188
+ displayName: 'System Prompt',
189
+ name: 'systemPrompt',
190
+ type: 'string',
191
+ typeOptions: { rows: 2 },
192
+ default: '',
193
+ description: 'System instructions for the model (overrides defaults)',
194
+ },
195
+ {
196
+ displayName: 'Response Format',
197
+ name: 'responseFormat',
198
+ type: 'options',
199
+ options: [
200
+ { name: 'Text', value: 'text' },
201
+ { name: 'JSON', value: 'json_object' },
202
+ ],
203
+ default: 'text',
204
+ description: 'Response format. Note: not all providers support JSON mode',
205
+ },
206
+ {
207
+ displayName: 'Custom Headers',
208
+ name: 'customHeaders',
209
+ type: 'fixedCollection',
210
+ typeOptions: { multipleValues: true },
211
+ description: 'Additional headers to include in API request',
212
+ default: {},
213
+ options: [
214
+ {
215
+ name: 'headers',
216
+ displayName: 'Headers',
217
+ values: [
218
+ {
219
+ displayName: 'Header Name',
220
+ name: 'name',
221
+ type: 'string',
222
+ default: '',
223
+ placeholder: 'X-Custom-Header',
224
+ },
225
+ {
226
+ displayName: 'Header Value',
227
+ name: 'value',
228
+ type: 'string',
229
+ default: '',
230
+ placeholder: 'custom-value',
231
+ },
232
+ ],
233
+ },
234
+ ],
235
+ },
236
+ {
237
+ displayName: 'Additional Parameters',
238
+ name: 'additionalParameters',
239
+ type: 'json',
240
+ default: '{}',
241
+ description: 'Extra API parameters as JSON (for advanced users)',
242
+ },
243
+ {
244
+ displayName: 'Include Metadata',
245
+ name: 'includeMetadata',
246
+ type: 'boolean',
247
+ default: false,
248
+ description: 'Include usage statistics and model information in output',
249
+ },
250
+ ],
251
+ },
252
+ {
253
+ displayName: 'Output Property Name',
254
+ name: 'outputPropertyName',
255
+ type: 'string',
256
+ default: 'analysis',
257
+ description: 'Property name for storing the analysis result',
258
+ },
259
+ ],
260
+ };
261
+ }
262
+ async execute() {
263
+ var _a;
264
+ const items = this.getInputData();
265
+ const returnData = [];
266
+ let credentials;
267
+ let credentialName;
268
+ let apiKey;
269
+ let customBaseUrl;
270
+ let provider;
271
+ try {
272
+ credentials = await this.getCredentials('openRouterApi');
273
+ credentialName = 'openRouterApi';
274
+ provider = 'openrouter';
275
+ apiKey = credentials.apiKey;
276
+ }
277
+ catch {
278
+ credentials = await this.getCredentials('universalLlmVisionApi');
279
+ credentialName = 'universalLlmVisionApi';
280
+ provider = credentials.provider || 'openai';
281
+ apiKey = credentials.apiKey;
282
+ customBaseUrl = credentials.baseUrl || undefined;
283
+ }
284
+ for (let i = 0; i < items.length; i++) {
285
+ try {
286
+ const model = this.getNodeParameter('model', i);
287
+ const prompt = this.getNodeParameter('prompt', i);
288
+ const modelParameters = this.getNodeParameter('modelParameters', i);
289
+ const advancedOptions = this.getNodeParameter('advancedOptions', i);
290
+ const outputPropertyName = this.getNodeParameter('outputPropertyName', i);
291
+ const includeMetadata = advancedOptions.includeMetadata || false;
292
+ const imageProcessor = new ImageProcessor_1.ImageProcessor(this);
293
+ const preparedImage = await imageProcessor.getPreparedImage(i);
294
+ const customHeadersRecord = {};
295
+ if ((_a = advancedOptions === null || advancedOptions === void 0 ? void 0 : advancedOptions.customHeaders) === null || _a === void 0 ? void 0 : _a.headers) {
296
+ for (const header of advancedOptions.customHeaders.headers) {
297
+ customHeadersRecord[header.name] = header.value;
298
+ }
299
+ }
300
+ if (credentialName === 'openRouterApi') {
301
+ if (credentials.httpReferer) {
302
+ customHeadersRecord['HTTP-Referer'] = credentials.httpReferer;
303
+ }
304
+ if (credentials.appTitle) {
305
+ customHeadersRecord['X-Title'] = credentials.appTitle;
306
+ }
307
+ }
308
+ const requestHandler = new RequestHandler_1.RequestHandler(this);
309
+ const response = await requestHandler.executeRequest(provider, apiKey, customBaseUrl, customHeadersRecord, model, preparedImage, prompt, modelParameters, advancedOptions);
310
+ const responseProcessor = new ResponseProcessor_1.ResponseProcessor();
311
+ const result = responseProcessor.processResponse(response, provider, includeMetadata, outputPropertyName);
312
+ returnData.push({
313
+ json: { ...items[i].json, ...result },
314
+ binary: items[i].binary,
315
+ });
316
+ }
317
+ catch (error) {
318
+ if (this.continueOnFail()) {
319
+ returnData.push({
320
+ json: {
321
+ error: error.message,
322
+ details: error.stack,
323
+ },
324
+ binary: items[i].binary,
325
+ });
326
+ continue;
327
+ }
328
+ throw error;
329
+ }
330
+ }
331
+ return [returnData];
332
+ }
333
+ }
334
+ exports.UniversalLlmVision = UniversalLlmVision;
335
+ //# sourceMappingURL=UniversalLlmVision.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UniversalLlmVision.node.js","sourceRoot":"","sources":["../../../nodes/UniversalLlmVision/UniversalLlmVision.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { IExecuteFunctions } from 'n8n-workflow';
2
+ import type { PreparedImage } from '../processors/ImageProcessor';
3
+ export declare class RequestHandler {
4
+ private executeFunctions;
5
+ constructor(executeFunctions: IExecuteFunctions);
6
+ executeRequest(provider: string, apiKey: string, customBaseUrl: string | undefined, customHeaders: Record<string, string>, model: string, preparedImage: PreparedImage, prompt: string, modelParameters: any, advancedOptions: any): Promise<any>;
7
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RequestHandler = void 0;
4
+ const GenericFunctions_1 = require("../utils/GenericFunctions");
5
+ class RequestHandler {
6
+ constructor(executeFunctions) {
7
+ this.executeFunctions = executeFunctions;
8
+ }
9
+ async executeRequest(provider, apiKey, customBaseUrl, customHeaders, model, preparedImage, prompt, modelParameters, advancedOptions) {
10
+ const requestOptions = {
11
+ provider,
12
+ model,
13
+ prompt,
14
+ image: preparedImage,
15
+ imageDetail: modelParameters === null || modelParameters === void 0 ? void 0 : modelParameters.imageDetail,
16
+ temperature: modelParameters === null || modelParameters === void 0 ? void 0 : modelParameters.temperature,
17
+ maxTokens: modelParameters === null || modelParameters === void 0 ? void 0 : modelParameters.maxTokens,
18
+ topP: modelParameters === null || modelParameters === void 0 ? void 0 : modelParameters.topP,
19
+ systemPrompt: advancedOptions === null || advancedOptions === void 0 ? void 0 : advancedOptions.systemPrompt,
20
+ responseFormat: advancedOptions === null || advancedOptions === void 0 ? void 0 : advancedOptions.responseFormat,
21
+ additionalParameters: (advancedOptions === null || advancedOptions === void 0 ? void 0 : advancedOptions.additionalParameters)
22
+ ? JSON.parse(advancedOptions.additionalParameters)
23
+ : undefined,
24
+ };
25
+ const { url, body } = (0, GenericFunctions_1.buildRequest)(requestOptions, customBaseUrl, customHeaders);
26
+ const headers = (0, GenericFunctions_1.getHeadersWithAuth)(provider, apiKey, customHeaders);
27
+ const response = await this.executeFunctions.helpers.request({
28
+ method: 'POST',
29
+ url,
30
+ headers,
31
+ body: JSON.stringify(body),
32
+ json: true,
33
+ timeout: 60000,
34
+ });
35
+ return response;
36
+ }
37
+ }
38
+ exports.RequestHandler = RequestHandler;
39
+ //# sourceMappingURL=RequestHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RequestHandler.js","sourceRoot":"","sources":["../../../../nodes/UniversalLlmVision/handlers/RequestHandler.ts"],"names":[],"mappings":";;;AAEA,gEAA6E;AAM7E,MAAa,cAAc;IAGzB,YAAY,gBAAmC;QAC7C,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;IAC3C,CAAC;IAgBD,KAAK,CAAC,cAAc,CAClB,QAAgB,EAChB,MAAc,EACd,aAAiC,EACjC,aAAqC,EACrC,KAAa,EACb,aAA4B,EAC5B,MAAc,EACd,eAAoB,EACpB,eAAoB;QAGpB,MAAM,cAAc,GAAG;YACrB,QAAQ;YACR,KAAK;YACL,MAAM;YACN,KAAK,EAAE,aAAa;YACpB,WAAW,EAAE,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,WAAW;YACzC,WAAW,EAAE,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,WAAW;YACzC,SAAS,EAAE,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,SAAS;YACrC,IAAI,EAAE,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,IAAI;YAC3B,YAAY,EAAE,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,YAAY;YAC3C,cAAc,EAAE,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,cAAc;YAC/C,oBAAoB,EAAE,CAAA,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,oBAAoB;gBACzD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,oBAAoB,CAAC;gBAClD,CAAC,CAAC,SAAS;SACd,CAAC;QAGF,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,IAAA,+BAAY,EAAC,cAAc,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;QAGjF,MAAM,OAAO,GAAG,IAAA,qCAAkB,EAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;QAGpE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC;YAC3D,MAAM,EAAE,MAAM;YACd,GAAG;YACH,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAC1B,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AAnED,wCAmEC"}