n8n-nodes-vlm 3.1.2 → 3.2.0

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.
@@ -91,6 +91,25 @@ class VLMComplexityWorkflow {
91
91
  placeholder: 'Add Option',
92
92
  default: {},
93
93
  options: [
94
+ {
95
+ displayName: 'Image Source',
96
+ name: 'imageSource',
97
+ type: 'options',
98
+ options: [
99
+ {
100
+ name: 'From Binary',
101
+ value: 'binary',
102
+ description: 'Extract image from binary field (n8n standard)',
103
+ },
104
+ {
105
+ name: 'From Base64 Field',
106
+ value: 'base64field',
107
+ description: 'Use base64 string from JSON field (with or without Data URI prefix)',
108
+ },
109
+ ],
110
+ default: 'binary',
111
+ description: 'Where to get the image data from',
112
+ },
94
113
  {
95
114
  displayName: 'Binary Field',
96
115
  name: 'binaryField',
@@ -99,13 +118,40 @@ class VLMComplexityWorkflow {
99
118
  placeholder: 'e.g. data (auto-detect if empty)',
100
119
  description: 'Name of the binary field to use for classification. Leave empty to auto-detect first image.',
101
120
  },
121
+ {
122
+ displayName: 'Base64 Field',
123
+ name: 'base64Field',
124
+ type: 'string',
125
+ default: 'data',
126
+ placeholder: 'e.g. data, base64Image',
127
+ description: 'JSON field containing base64 string (auto-detects Data URI prefix)',
128
+ },
102
129
  {
103
130
  displayName: 'Output Base64 Field',
104
131
  name: 'outputBase64Field',
105
132
  type: 'string',
106
133
  default: '',
107
134
  placeholder: 'e.g. base64Image',
108
- description: 'If set, the base64 image string will be added to output JSON under this field name.',
135
+ description: 'If set, the base64 image will be added to output JSON under this field name.',
136
+ },
137
+ {
138
+ displayName: 'Output Base64 Format',
139
+ name: 'outputBase64Format',
140
+ type: 'options',
141
+ options: [
142
+ {
143
+ name: 'Raw Base64',
144
+ value: 'raw',
145
+ description: 'iVBORw0KGgo... (like n8n native)',
146
+ },
147
+ {
148
+ name: 'Data URI',
149
+ value: 'datauri',
150
+ description: 'data:image/png;base64,iVBORw0KGgo...',
151
+ },
152
+ ],
153
+ default: 'raw',
154
+ description: 'Format of the base64 output (only applies if Output Base64 Field is set)',
109
155
  },
110
156
  {
111
157
  displayName: 'Request Timeout (ms)',
@@ -140,8 +186,11 @@ class VLMComplexityWorkflow {
140
186
  const model = this.getNodeParameter('model', 0);
141
187
  const options = this.getNodeParameter('options', 0, {});
142
188
  const timeout = (_a = options.timeout) !== null && _a !== void 0 ? _a : 30000;
189
+ const imageSource = options.imageSource || 'binary';
143
190
  const binaryField = options.binaryField || '';
191
+ const base64Field = options.base64Field || 'data';
144
192
  const outputBase64Field = options.outputBase64Field || '';
193
+ const outputBase64Format = options.outputBase64Format || 'raw';
145
194
  // Verify server has classifier capability (optional check)
146
195
  const status = await (0, vlm_logic_1.checkServerStatus)(this, serverUrl, timeout);
147
196
  if (status.status === 'error') {
@@ -156,31 +205,59 @@ class VLMComplexityWorkflow {
156
205
  // Process each input item
157
206
  for (let i = 0; i < items.length; i++) {
158
207
  const item = items[i];
159
- // Extract base64 image from binary
160
- let base64Image;
161
- if (item.binary) {
162
- if (binaryField && item.binary[binaryField]) {
163
- // Use specified binary field
164
- const data = item.binary[binaryField];
165
- if (data.data) {
166
- base64Image = `data:${data.mimeType || 'image/png'};base64,${data.data}`;
167
- this.logger.debug(`Item ${i}: Using specified binary field '${binaryField}' (${data.mimeType || 'unknown'})`);
208
+ // Extract base64 image - track both raw and Data URI formats
209
+ let base64Image; // Data URI format for API
210
+ let rawBase64; // Raw base64 without prefix
211
+ let mimeType = 'image/png';
212
+ if (imageSource === 'base64field') {
213
+ // Extract from JSON field
214
+ const fieldValue = item.json[base64Field];
215
+ if (fieldValue) {
216
+ // Auto-detect if it's already a Data URI
217
+ const dataUriMatch = fieldValue.match(/^data:([^;]+);base64,(.+)$/);
218
+ if (dataUriMatch) {
219
+ mimeType = dataUriMatch[1];
220
+ rawBase64 = dataUriMatch[2];
221
+ base64Image = fieldValue; // Already in Data URI format
222
+ }
223
+ else {
224
+ // Raw base64, wrap in Data URI
225
+ rawBase64 = fieldValue;
226
+ base64Image = `data:${mimeType};base64,${rawBase64}`;
168
227
  }
228
+ this.logger.debug(`Item ${i}: Using base64 from JSON field '${base64Field}' (${mimeType})`);
169
229
  }
170
- else {
171
- // Auto-detect first image (default behavior)
172
- for (const [binaryKey, binaryData] of Object.entries(item.binary)) {
173
- const data = binaryData;
174
- if (data.mimeType && data.mimeType.startsWith('image/') && data.data) {
175
- base64Image = `data:${data.mimeType};base64,${data.data}`;
176
- this.logger.debug(`Item ${i}: Auto-detected image from binary '${binaryKey}' (${data.mimeType})`);
177
- break;
230
+ }
231
+ else {
232
+ // Extract from binary (default)
233
+ if (item.binary) {
234
+ if (binaryField && item.binary[binaryField]) {
235
+ // Use specified binary field
236
+ const data = item.binary[binaryField];
237
+ if (data.data) {
238
+ mimeType = data.mimeType || 'image/png';
239
+ rawBase64 = data.data;
240
+ base64Image = `data:${mimeType};base64,${rawBase64}`;
241
+ this.logger.debug(`Item ${i}: Using specified binary field '${binaryField}' (${mimeType})`);
242
+ }
243
+ }
244
+ else {
245
+ // Auto-detect first image (default behavior)
246
+ for (const [binaryKey, binaryData] of Object.entries(item.binary)) {
247
+ const data = binaryData;
248
+ if (data.mimeType && data.mimeType.startsWith('image/') && data.data) {
249
+ mimeType = data.mimeType;
250
+ rawBase64 = data.data;
251
+ base64Image = `data:${mimeType};base64,${rawBase64}`;
252
+ this.logger.debug(`Item ${i}: Auto-detected image from binary '${binaryKey}' (${mimeType})`);
253
+ break;
254
+ }
178
255
  }
179
256
  }
180
257
  }
181
258
  }
182
259
  if (!base64Image) {
183
- this.logger.warn(`Item ${i}: No image found in binary data`);
260
+ this.logger.warn(`Item ${i}: No image found (source: ${imageSource})`);
184
261
  }
185
262
  // Classify the document
186
263
  const classification = await (0, vlm_logic_1.classifySingleDocument)(this, {
@@ -189,6 +266,8 @@ class VLMComplexityWorkflow {
189
266
  timeout,
190
267
  });
191
268
  this.logger.debug(`Item ${i}: Classified as ${classification.complexity} (confidence: ${classification.confidence})`);
269
+ // Determine base64 output value based on format preference
270
+ const outputBase64Value = outputBase64Format === 'raw' ? rawBase64 : base64Image;
192
271
  // Build output item with BOTH json AND binary
193
272
  const outputItem = {
194
273
  json: {
@@ -201,8 +280,8 @@ class VLMComplexityWorkflow {
201
280
  ...item.json,
202
281
  // Item tracking
203
282
  _itemIndex: i,
204
- // Optional: include base64 in output JSON
205
- ...(outputBase64Field && base64Image ? { [outputBase64Field]: base64Image } : {}),
283
+ // Optional: include base64 in output JSON (format depends on outputBase64Format)
284
+ ...(outputBase64Field && outputBase64Value ? { [outputBase64Field]: outputBase64Value } : {}),
206
285
  },
207
286
  // ALWAYS preserve binary data
208
287
  binary: item.binary,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-vlm",
3
- "version": "3.1.2",
3
+ "version": "3.2.0",
4
4
  "description": "Vision-Language Models for n8n - Lightweight specialized VLMs for document analysis and classification",
5
5
  "main": "dist/index.js",
6
6
  "author": "Nicolas Geysse",