n8n-nodes-vlm 3.1.2 → 3.2.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.
@@ -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,14 @@ 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';
194
+ // DEBUG: Log options to diagnose format bug
195
+ this.logger.debug(`VLM DEBUG OPTIONS: imageSource='${imageSource}', outputBase64Format='${outputBase64Format}', outputBase64Field='${outputBase64Field}'`);
196
+ this.logger.debug(`VLM DEBUG: outputBase64Format === 'raw' ? ${outputBase64Format === 'raw'}`);
145
197
  // Verify server has classifier capability (optional check)
146
198
  const status = await (0, vlm_logic_1.checkServerStatus)(this, serverUrl, timeout);
147
199
  if (status.status === 'error') {
@@ -156,31 +208,59 @@ class VLMComplexityWorkflow {
156
208
  // Process each input item
157
209
  for (let i = 0; i < items.length; i++) {
158
210
  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'})`);
211
+ // Extract base64 image - track both raw and Data URI formats
212
+ let base64Image; // Data URI format for API
213
+ let rawBase64; // Raw base64 without prefix
214
+ let mimeType = 'image/png';
215
+ if (imageSource === 'base64field') {
216
+ // Extract from JSON field
217
+ const fieldValue = item.json[base64Field];
218
+ if (fieldValue) {
219
+ // Auto-detect if it's already a Data URI
220
+ const dataUriMatch = fieldValue.match(/^data:([^;]+);base64,(.+)$/);
221
+ if (dataUriMatch) {
222
+ mimeType = dataUriMatch[1];
223
+ rawBase64 = dataUriMatch[2];
224
+ base64Image = fieldValue; // Already in Data URI format
225
+ }
226
+ else {
227
+ // Raw base64, wrap in Data URI
228
+ rawBase64 = fieldValue;
229
+ base64Image = `data:${mimeType};base64,${rawBase64}`;
168
230
  }
231
+ this.logger.debug(`Item ${i}: Using base64 from JSON field '${base64Field}' (${mimeType})`);
169
232
  }
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;
233
+ }
234
+ else {
235
+ // Extract from binary (default)
236
+ if (item.binary) {
237
+ if (binaryField && item.binary[binaryField]) {
238
+ // Use specified binary field
239
+ const data = item.binary[binaryField];
240
+ if (data.data) {
241
+ mimeType = data.mimeType || 'image/png';
242
+ rawBase64 = data.data;
243
+ base64Image = `data:${mimeType};base64,${rawBase64}`;
244
+ this.logger.debug(`Item ${i}: Using specified binary field '${binaryField}' (${mimeType})`);
245
+ }
246
+ }
247
+ else {
248
+ // Auto-detect first image (default behavior)
249
+ for (const [binaryKey, binaryData] of Object.entries(item.binary)) {
250
+ const data = binaryData;
251
+ if (data.mimeType && data.mimeType.startsWith('image/') && data.data) {
252
+ mimeType = data.mimeType;
253
+ rawBase64 = data.data;
254
+ base64Image = `data:${mimeType};base64,${rawBase64}`;
255
+ this.logger.debug(`Item ${i}: Auto-detected image from binary '${binaryKey}' (${mimeType})`);
256
+ break;
257
+ }
178
258
  }
179
259
  }
180
260
  }
181
261
  }
182
262
  if (!base64Image) {
183
- this.logger.warn(`Item ${i}: No image found in binary data`);
263
+ this.logger.warn(`Item ${i}: No image found (source: ${imageSource})`);
184
264
  }
185
265
  // Classify the document
186
266
  const classification = await (0, vlm_logic_1.classifySingleDocument)(this, {
@@ -189,6 +269,13 @@ class VLMComplexityWorkflow {
189
269
  timeout,
190
270
  });
191
271
  this.logger.debug(`Item ${i}: Classified as ${classification.complexity} (confidence: ${classification.confidence})`);
272
+ // Determine base64 output value based on format preference
273
+ // DEBUG: Log values before output decision
274
+ this.logger.debug(`VLM DEBUG OUTPUT: rawBase64 defined=${!!rawBase64}, rawBase64 prefix='${rawBase64 === null || rawBase64 === void 0 ? void 0 : rawBase64.substring(0, 25)}...'`);
275
+ this.logger.debug(`VLM DEBUG OUTPUT: base64Image prefix='${base64Image === null || base64Image === void 0 ? void 0 : base64Image.substring(0, 35)}...'`);
276
+ this.logger.debug(`VLM DEBUG OUTPUT: choosing ${outputBase64Format === 'raw' ? 'rawBase64' : 'base64Image'}`);
277
+ const outputBase64Value = outputBase64Format === 'raw' ? rawBase64 : base64Image;
278
+ this.logger.debug(`VLM DEBUG OUTPUT: outputBase64Value prefix='${outputBase64Value === null || outputBase64Value === void 0 ? void 0 : outputBase64Value.substring(0, 35)}...'`);
192
279
  // Build output item with BOTH json AND binary
193
280
  const outputItem = {
194
281
  json: {
@@ -201,8 +288,8 @@ class VLMComplexityWorkflow {
201
288
  ...item.json,
202
289
  // Item tracking
203
290
  _itemIndex: i,
204
- // Optional: include base64 in output JSON
205
- ...(outputBase64Field && base64Image ? { [outputBase64Field]: base64Image } : {}),
291
+ // Optional: include base64 in output JSON (format depends on outputBase64Format)
292
+ ...(outputBase64Field && outputBase64Value ? { [outputBase64Field]: outputBase64Value } : {}),
206
293
  },
207
294
  // ALWAYS preserve binary data
208
295
  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.1",
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",