n8n-nodes-commandos-image 0.1.4 → 0.1.5
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.
- package/dist/nodes/CommandosImage.node.js +145 -24
- package/nodes/CommandosImage.node.ts +148 -23
- package/package.json +1 -1
|
@@ -15,10 +15,35 @@ const resolveGenerationUrl = (resolvedModel) => {
|
|
|
15
15
|
}
|
|
16
16
|
return GENERATION_URL_DEFAULT;
|
|
17
17
|
};
|
|
18
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Maps standard ratios to specific model requirements
|
|
20
|
+
*/
|
|
21
|
+
const mapRatio = (model, ratio) => {
|
|
22
|
+
if (model.includes('seedream')) {
|
|
23
|
+
if (ratio === '2:3')
|
|
24
|
+
return 'portrait_3_2';
|
|
25
|
+
if (ratio === '3:2')
|
|
26
|
+
return 'landscape_2_3';
|
|
27
|
+
}
|
|
28
|
+
return ratio;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Maps standard formats to specific model requirements (jpeg vs jpg)
|
|
32
|
+
*/
|
|
33
|
+
const mapFormat = (model, format) => {
|
|
34
|
+
if (model === 'nano-banana-pro') {
|
|
35
|
+
return format === 'jpeg' ? 'jpg' : format;
|
|
36
|
+
}
|
|
37
|
+
if (model.includes('google/nano-banana')) {
|
|
38
|
+
return format === 'jpg' ? 'jpeg' : format;
|
|
39
|
+
}
|
|
40
|
+
return format;
|
|
41
|
+
};
|
|
42
|
+
const buildGenerationRequest = ({ model, prompt, ratio, references, outputFormat = 'png', quality = 'basic', resolution = '1K', }) => {
|
|
19
43
|
const hasReferences = references.length > 0;
|
|
20
44
|
const requestedModel = model;
|
|
21
45
|
let resolvedModel = model;
|
|
46
|
+
// Model Resolution
|
|
22
47
|
if (requestedModel === 'flux-pro') {
|
|
23
48
|
resolvedModel = hasReferences ? 'flux-2/pro-image-to-image' : 'flux-2/pro-text-to-image';
|
|
24
49
|
}
|
|
@@ -29,11 +54,15 @@ const buildGenerationRequest = ({ model, prompt, ratio, references }) => {
|
|
|
29
54
|
resolvedModel = 'nano-banana-pro';
|
|
30
55
|
}
|
|
31
56
|
else if (requestedModel === 'seedream') {
|
|
32
|
-
resolvedModel = '
|
|
57
|
+
resolvedModel = hasReferences ? 'seedream/4.5-edit' : 'seedream/4.5';
|
|
33
58
|
}
|
|
59
|
+
// Fallback for MJ or generic seedream
|
|
34
60
|
if (!hasReferences && (requestedModel === 'seedream' || requestedModel === 'midjourney')) {
|
|
35
|
-
if (requestedModel
|
|
36
|
-
|
|
61
|
+
if (requestedModel === 'seedream') {
|
|
62
|
+
// Handled above for 4.5
|
|
63
|
+
}
|
|
64
|
+
else if (requestedModel === 'midjourney') {
|
|
65
|
+
resolvedModel = 'midjourney';
|
|
37
66
|
}
|
|
38
67
|
}
|
|
39
68
|
let body = {};
|
|
@@ -42,7 +71,7 @@ const buildGenerationRequest = ({ model, prompt, ratio, references }) => {
|
|
|
42
71
|
filesUrl: references,
|
|
43
72
|
prompt,
|
|
44
73
|
size: ratio,
|
|
45
|
-
callBackUrl: 'https://
|
|
74
|
+
callBackUrl: 'https://api.comandos.ai/internal/kie/callback', // Fixed to internal
|
|
46
75
|
fallbackModel: 'FLUX_MAX',
|
|
47
76
|
};
|
|
48
77
|
}
|
|
@@ -52,19 +81,30 @@ const buildGenerationRequest = ({ model, prompt, ratio, references }) => {
|
|
|
52
81
|
input: {
|
|
53
82
|
prompt,
|
|
54
83
|
aspect_ratio: ratio,
|
|
55
|
-
resolution
|
|
84
|
+
resolution,
|
|
56
85
|
...(hasReferences ? { input_urls: references } : {}),
|
|
57
86
|
},
|
|
58
87
|
};
|
|
59
88
|
}
|
|
89
|
+
else if (resolvedModel === 'seedream/4.5' || resolvedModel === 'seedream/4.5-edit') {
|
|
90
|
+
body = {
|
|
91
|
+
model: resolvedModel,
|
|
92
|
+
input: {
|
|
93
|
+
prompt,
|
|
94
|
+
aspect_ratio: mapRatio(resolvedModel, ratio),
|
|
95
|
+
quality,
|
|
96
|
+
...(hasReferences ? { image_urls: references } : {}),
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
60
100
|
else if (resolvedModel === 'nano-banana-pro') {
|
|
61
101
|
body = {
|
|
62
102
|
model: resolvedModel,
|
|
63
103
|
input: {
|
|
64
104
|
prompt,
|
|
65
105
|
aspect_ratio: ratio,
|
|
66
|
-
resolution
|
|
67
|
-
output_format:
|
|
106
|
+
resolution,
|
|
107
|
+
output_format: mapFormat(resolvedModel, outputFormat),
|
|
68
108
|
...(hasReferences ? { image_input: references } : {}),
|
|
69
109
|
},
|
|
70
110
|
};
|
|
@@ -75,7 +115,7 @@ const buildGenerationRequest = ({ model, prompt, ratio, references }) => {
|
|
|
75
115
|
input: {
|
|
76
116
|
prompt,
|
|
77
117
|
image_size: ratio,
|
|
78
|
-
output_format:
|
|
118
|
+
output_format: mapFormat(resolvedModel, outputFormat),
|
|
79
119
|
...(hasReferences ? { image_urls: references } : {}),
|
|
80
120
|
},
|
|
81
121
|
};
|
|
@@ -91,13 +131,13 @@ const buildGenerationRequest = ({ model, prompt, ratio, references }) => {
|
|
|
91
131
|
};
|
|
92
132
|
}
|
|
93
133
|
else {
|
|
134
|
+
// Default fallback (v4 edit style)
|
|
94
135
|
body = {
|
|
95
|
-
model: 'bytedance/seedream-v4-edit',
|
|
136
|
+
model: requestedModel === 'gpt4o-image' ? 'gpt-4o' : 'bytedance/seedream-v4-edit',
|
|
96
137
|
input: {
|
|
97
138
|
image_urls: references,
|
|
98
139
|
prompt,
|
|
99
|
-
image_size:
|
|
100
|
-
image_resolution: '1K',
|
|
140
|
+
image_size: mapRatio('seedream', ratio),
|
|
101
141
|
},
|
|
102
142
|
};
|
|
103
143
|
}
|
|
@@ -111,16 +151,24 @@ const buildGenerationRequest = ({ model, prompt, ratio, references }) => {
|
|
|
111
151
|
hasReferences,
|
|
112
152
|
};
|
|
113
153
|
};
|
|
114
|
-
const extractReferences = (raw) => {
|
|
154
|
+
const extractReferences = (raw, model) => {
|
|
115
155
|
if (!raw || typeof raw !== 'object') {
|
|
116
156
|
return [];
|
|
117
157
|
}
|
|
118
158
|
const collection = raw;
|
|
119
159
|
const items = Array.isArray(collection.reference) ? collection.reference : [];
|
|
160
|
+
// Dynamic limit based on model docs
|
|
161
|
+
let limit = 8;
|
|
162
|
+
if (model === 'seedream')
|
|
163
|
+
limit = 14;
|
|
164
|
+
if (model === 'gpt4o-image')
|
|
165
|
+
limit = 16;
|
|
166
|
+
if (model.includes('nano-banana'))
|
|
167
|
+
limit = 10;
|
|
120
168
|
return items
|
|
121
169
|
.map((entry) => String((entry === null || entry === void 0 ? void 0 : entry.url) || '').trim())
|
|
122
170
|
.filter((value) => value.length > 0 && /^https?:\/\//i.test(value))
|
|
123
|
-
.slice(0,
|
|
171
|
+
.slice(0, limit);
|
|
124
172
|
};
|
|
125
173
|
class CommandosImage {
|
|
126
174
|
constructor() {
|
|
@@ -165,14 +213,14 @@ class CommandosImage {
|
|
|
165
213
|
name: 'model',
|
|
166
214
|
type: 'options',
|
|
167
215
|
options: [
|
|
216
|
+
{ name: 'Seedream 4.5', value: 'seedream' },
|
|
168
217
|
{ name: 'Flux Pro', value: 'flux-pro' },
|
|
169
218
|
{ name: 'GPT-4o Image', value: 'gpt4o-image' },
|
|
170
219
|
{ name: 'Nano Banana', value: 'nano-banana' },
|
|
171
220
|
{ name: 'Nano Banana Pro', value: 'nano-banana-pro' },
|
|
172
|
-
{ name: 'Seedream', value: 'seedream' },
|
|
173
221
|
{ name: 'Midjourney', value: 'midjourney' },
|
|
174
222
|
],
|
|
175
|
-
default: '
|
|
223
|
+
default: 'seedream',
|
|
176
224
|
displayOptions: {
|
|
177
225
|
show: {
|
|
178
226
|
operation: ['create'],
|
|
@@ -204,6 +252,9 @@ class CommandosImage {
|
|
|
204
252
|
{ name: '4:5', value: '4:5' },
|
|
205
253
|
{ name: '16:9', value: '16:9' },
|
|
206
254
|
{ name: '9:16', value: '9:16' },
|
|
255
|
+
{ name: '4:3', value: '4:3' },
|
|
256
|
+
{ name: '3:4', value: '3:4' },
|
|
257
|
+
{ name: '21:9', value: '21:9' },
|
|
207
258
|
],
|
|
208
259
|
default: '2:3',
|
|
209
260
|
displayOptions: {
|
|
@@ -212,6 +263,56 @@ class CommandosImage {
|
|
|
212
263
|
},
|
|
213
264
|
},
|
|
214
265
|
},
|
|
266
|
+
{
|
|
267
|
+
displayName: 'Output Format',
|
|
268
|
+
name: 'outputFormat',
|
|
269
|
+
type: 'options',
|
|
270
|
+
options: [
|
|
271
|
+
{ name: 'PNG', value: 'png' },
|
|
272
|
+
{ name: 'JPEG', value: 'jpeg' },
|
|
273
|
+
],
|
|
274
|
+
default: 'png',
|
|
275
|
+
displayOptions: {
|
|
276
|
+
show: {
|
|
277
|
+
operation: ['create'],
|
|
278
|
+
model: ['nano-banana', 'nano-banana-pro'],
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
displayName: 'Quality',
|
|
284
|
+
name: 'quality',
|
|
285
|
+
type: 'options',
|
|
286
|
+
options: [
|
|
287
|
+
{ name: 'Basic (2K)', value: 'basic' },
|
|
288
|
+
{ name: 'High (4K)', value: 'high' },
|
|
289
|
+
{ name: 'Medium (Balanced)', value: 'medium' },
|
|
290
|
+
],
|
|
291
|
+
default: 'basic',
|
|
292
|
+
displayOptions: {
|
|
293
|
+
show: {
|
|
294
|
+
operation: ['create'],
|
|
295
|
+
model: ['seedream', 'gpt4o-image', 'flux-pro'],
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
displayName: 'Resolution',
|
|
301
|
+
name: 'resolution',
|
|
302
|
+
type: 'options',
|
|
303
|
+
options: [
|
|
304
|
+
{ name: '1K', value: '1K' },
|
|
305
|
+
{ name: '2K', value: '2K' },
|
|
306
|
+
{ name: '4K', value: '4K' },
|
|
307
|
+
],
|
|
308
|
+
default: '1K',
|
|
309
|
+
displayOptions: {
|
|
310
|
+
show: {
|
|
311
|
+
operation: ['create'],
|
|
312
|
+
model: ['flux-pro', 'nano-banana-pro'],
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
},
|
|
215
316
|
{
|
|
216
317
|
displayName: 'References',
|
|
217
318
|
name: 'references',
|
|
@@ -269,11 +370,35 @@ class CommandosImage {
|
|
|
269
370
|
const model = String(this.getNodeParameter('model', i));
|
|
270
371
|
const prompt = String(this.getNodeParameter('prompt', i) || '').trim();
|
|
271
372
|
const ratio = String(this.getNodeParameter('ratio', i));
|
|
272
|
-
const references = extractReferences(this.getNodeParameter('references', i, {}));
|
|
373
|
+
const references = extractReferences(this.getNodeParameter('references', i, {}), model);
|
|
374
|
+
// Get optional parameters with safe fallback
|
|
375
|
+
let outputFormat = 'png';
|
|
376
|
+
try {
|
|
377
|
+
outputFormat = String(this.getNodeParameter('outputFormat', i));
|
|
378
|
+
}
|
|
379
|
+
catch (e) { }
|
|
380
|
+
let quality = 'basic';
|
|
381
|
+
try {
|
|
382
|
+
quality = String(this.getNodeParameter('quality', i));
|
|
383
|
+
}
|
|
384
|
+
catch (e) { }
|
|
385
|
+
let resolution = '1K';
|
|
386
|
+
try {
|
|
387
|
+
resolution = String(this.getNodeParameter('resolution', i));
|
|
388
|
+
}
|
|
389
|
+
catch (e) { }
|
|
273
390
|
if (!prompt) {
|
|
274
391
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Prompt is required', { itemIndex: i });
|
|
275
392
|
}
|
|
276
|
-
const request = buildGenerationRequest({
|
|
393
|
+
const request = buildGenerationRequest({
|
|
394
|
+
model,
|
|
395
|
+
prompt,
|
|
396
|
+
ratio,
|
|
397
|
+
references,
|
|
398
|
+
outputFormat,
|
|
399
|
+
quality,
|
|
400
|
+
resolution
|
|
401
|
+
});
|
|
277
402
|
if (!request.url) {
|
|
278
403
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'URL генерации не настроен. Проверь переменные окружения COMMANDOS_IMAGE_URL_DEFAULT/COMMANDOS_IMAGE_URL_GPT4O/COMMANDOS_IMAGE_URL_MJ', { itemIndex: i });
|
|
279
404
|
}
|
|
@@ -316,17 +441,13 @@ class CommandosImage {
|
|
|
316
441
|
});
|
|
317
442
|
results.push({ json: response });
|
|
318
443
|
}
|
|
319
|
-
else {
|
|
320
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation: ${operation}`, {
|
|
321
|
-
itemIndex: i,
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
444
|
}
|
|
325
445
|
catch (error) {
|
|
326
446
|
if (error instanceof n8n_workflow_1.NodeOperationError) {
|
|
327
447
|
throw error;
|
|
328
448
|
}
|
|
329
|
-
|
|
449
|
+
const message = error instanceof Error ? error.message : 'Request failed';
|
|
450
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), message, { itemIndex: i });
|
|
330
451
|
}
|
|
331
452
|
}
|
|
332
453
|
return [results];
|
|
@@ -17,6 +17,9 @@ type BuildParams = {
|
|
|
17
17
|
prompt: string;
|
|
18
18
|
ratio: string;
|
|
19
19
|
references: string[];
|
|
20
|
+
outputFormat?: string;
|
|
21
|
+
quality?: string;
|
|
22
|
+
resolution?: string;
|
|
20
23
|
};
|
|
21
24
|
|
|
22
25
|
type BuildResult = {
|
|
@@ -39,11 +42,44 @@ const resolveGenerationUrl = (resolvedModel: string): string => {
|
|
|
39
42
|
return GENERATION_URL_DEFAULT;
|
|
40
43
|
};
|
|
41
44
|
|
|
42
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Maps standard ratios to specific model requirements
|
|
47
|
+
*/
|
|
48
|
+
const mapRatio = (model: string, ratio: string): string => {
|
|
49
|
+
if (model.includes('seedream')) {
|
|
50
|
+
if (ratio === '2:3') return 'portrait_3_2';
|
|
51
|
+
if (ratio === '3:2') return 'landscape_2_3';
|
|
52
|
+
}
|
|
53
|
+
return ratio;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Maps standard formats to specific model requirements (jpeg vs jpg)
|
|
58
|
+
*/
|
|
59
|
+
const mapFormat = (model: string, format: string): string => {
|
|
60
|
+
if (model === 'nano-banana-pro') {
|
|
61
|
+
return format === 'jpeg' ? 'jpg' : format;
|
|
62
|
+
}
|
|
63
|
+
if (model.includes('google/nano-banana')) {
|
|
64
|
+
return format === 'jpg' ? 'jpeg' : format;
|
|
65
|
+
}
|
|
66
|
+
return format;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const buildGenerationRequest = ({
|
|
70
|
+
model,
|
|
71
|
+
prompt,
|
|
72
|
+
ratio,
|
|
73
|
+
references,
|
|
74
|
+
outputFormat = 'png',
|
|
75
|
+
quality = 'basic',
|
|
76
|
+
resolution = '1K',
|
|
77
|
+
}: BuildParams): BuildResult => {
|
|
43
78
|
const hasReferences = references.length > 0;
|
|
44
79
|
const requestedModel = model;
|
|
45
80
|
let resolvedModel = model;
|
|
46
81
|
|
|
82
|
+
// Model Resolution
|
|
47
83
|
if (requestedModel === 'flux-pro') {
|
|
48
84
|
resolvedModel = hasReferences ? 'flux-2/pro-image-to-image' : 'flux-2/pro-text-to-image';
|
|
49
85
|
} else if (requestedModel === 'nano-banana') {
|
|
@@ -51,12 +87,15 @@ const buildGenerationRequest = ({ model, prompt, ratio, references }: BuildParam
|
|
|
51
87
|
} else if (requestedModel === 'nano-banana-pro') {
|
|
52
88
|
resolvedModel = 'nano-banana-pro';
|
|
53
89
|
} else if (requestedModel === 'seedream') {
|
|
54
|
-
resolvedModel = '
|
|
90
|
+
resolvedModel = hasReferences ? 'seedream/4.5-edit' : 'seedream/4.5';
|
|
55
91
|
}
|
|
56
92
|
|
|
93
|
+
// Fallback for MJ or generic seedream
|
|
57
94
|
if (!hasReferences && (requestedModel === 'seedream' || requestedModel === 'midjourney')) {
|
|
58
|
-
if (requestedModel
|
|
59
|
-
|
|
95
|
+
if (requestedModel === 'seedream') {
|
|
96
|
+
// Handled above for 4.5
|
|
97
|
+
} else if (requestedModel === 'midjourney') {
|
|
98
|
+
resolvedModel = 'midjourney';
|
|
60
99
|
}
|
|
61
100
|
}
|
|
62
101
|
|
|
@@ -67,7 +106,7 @@ const buildGenerationRequest = ({ model, prompt, ratio, references }: BuildParam
|
|
|
67
106
|
filesUrl: references,
|
|
68
107
|
prompt,
|
|
69
108
|
size: ratio,
|
|
70
|
-
callBackUrl: 'https://
|
|
109
|
+
callBackUrl: 'https://api.comandos.ai/internal/kie/callback', // Fixed to internal
|
|
71
110
|
fallbackModel: 'FLUX_MAX',
|
|
72
111
|
};
|
|
73
112
|
} else if (resolvedModel.includes('flux-2/')) {
|
|
@@ -76,18 +115,28 @@ const buildGenerationRequest = ({ model, prompt, ratio, references }: BuildParam
|
|
|
76
115
|
input: {
|
|
77
116
|
prompt,
|
|
78
117
|
aspect_ratio: ratio,
|
|
79
|
-
resolution
|
|
118
|
+
resolution,
|
|
80
119
|
...(hasReferences ? { input_urls: references } : {}),
|
|
81
120
|
},
|
|
82
121
|
};
|
|
122
|
+
} else if (resolvedModel === 'seedream/4.5' || resolvedModel === 'seedream/4.5-edit') {
|
|
123
|
+
body = {
|
|
124
|
+
model: resolvedModel,
|
|
125
|
+
input: {
|
|
126
|
+
prompt,
|
|
127
|
+
aspect_ratio: mapRatio(resolvedModel, ratio),
|
|
128
|
+
quality,
|
|
129
|
+
...(hasReferences ? { image_urls: references } : {}),
|
|
130
|
+
},
|
|
131
|
+
};
|
|
83
132
|
} else if (resolvedModel === 'nano-banana-pro') {
|
|
84
133
|
body = {
|
|
85
134
|
model: resolvedModel,
|
|
86
135
|
input: {
|
|
87
136
|
prompt,
|
|
88
137
|
aspect_ratio: ratio,
|
|
89
|
-
resolution
|
|
90
|
-
output_format:
|
|
138
|
+
resolution,
|
|
139
|
+
output_format: mapFormat(resolvedModel, outputFormat),
|
|
91
140
|
...(hasReferences ? { image_input: references } : {}),
|
|
92
141
|
},
|
|
93
142
|
};
|
|
@@ -97,7 +146,7 @@ const buildGenerationRequest = ({ model, prompt, ratio, references }: BuildParam
|
|
|
97
146
|
input: {
|
|
98
147
|
prompt,
|
|
99
148
|
image_size: ratio,
|
|
100
|
-
output_format:
|
|
149
|
+
output_format: mapFormat(resolvedModel, outputFormat),
|
|
101
150
|
...(hasReferences ? { image_urls: references } : {}),
|
|
102
151
|
},
|
|
103
152
|
};
|
|
@@ -111,13 +160,13 @@ const buildGenerationRequest = ({ model, prompt, ratio, references }: BuildParam
|
|
|
111
160
|
enableTranslation: true,
|
|
112
161
|
};
|
|
113
162
|
} else {
|
|
163
|
+
// Default fallback (v4 edit style)
|
|
114
164
|
body = {
|
|
115
|
-
model: 'bytedance/seedream-v4-edit',
|
|
165
|
+
model: requestedModel === 'gpt4o-image' ? 'gpt-4o' : 'bytedance/seedream-v4-edit',
|
|
116
166
|
input: {
|
|
117
167
|
image_urls: references,
|
|
118
168
|
prompt,
|
|
119
|
-
image_size:
|
|
120
|
-
image_resolution: '1K',
|
|
169
|
+
image_size: mapRatio('seedream', ratio),
|
|
121
170
|
},
|
|
122
171
|
};
|
|
123
172
|
}
|
|
@@ -133,16 +182,23 @@ const buildGenerationRequest = ({ model, prompt, ratio, references }: BuildParam
|
|
|
133
182
|
};
|
|
134
183
|
};
|
|
135
184
|
|
|
136
|
-
const extractReferences = (raw: unknown): string[] => {
|
|
185
|
+
const extractReferences = (raw: unknown, model: string): string[] => {
|
|
137
186
|
if (!raw || typeof raw !== 'object') {
|
|
138
187
|
return [];
|
|
139
188
|
}
|
|
140
189
|
const collection = raw as { reference?: Array<{ url?: string }> };
|
|
141
190
|
const items = Array.isArray(collection.reference) ? collection.reference : [];
|
|
191
|
+
|
|
192
|
+
// Dynamic limit based on model docs
|
|
193
|
+
let limit = 8;
|
|
194
|
+
if (model === 'seedream') limit = 14;
|
|
195
|
+
if (model === 'gpt4o-image') limit = 16;
|
|
196
|
+
if (model.includes('nano-banana')) limit = 10;
|
|
197
|
+
|
|
142
198
|
return items
|
|
143
199
|
.map((entry) => String(entry?.url || '').trim())
|
|
144
200
|
.filter((value) => value.length > 0 && /^https?:\/\//i.test(value))
|
|
145
|
-
.slice(0,
|
|
201
|
+
.slice(0, limit);
|
|
146
202
|
};
|
|
147
203
|
|
|
148
204
|
export class CommandosImage implements INodeType {
|
|
@@ -187,14 +243,14 @@ export class CommandosImage implements INodeType {
|
|
|
187
243
|
name: 'model',
|
|
188
244
|
type: 'options',
|
|
189
245
|
options: [
|
|
246
|
+
{ name: 'Seedream 4.5', value: 'seedream' },
|
|
190
247
|
{ name: 'Flux Pro', value: 'flux-pro' },
|
|
191
248
|
{ name: 'GPT-4o Image', value: 'gpt4o-image' },
|
|
192
249
|
{ name: 'Nano Banana', value: 'nano-banana' },
|
|
193
250
|
{ name: 'Nano Banana Pro', value: 'nano-banana-pro' },
|
|
194
|
-
{ name: 'Seedream', value: 'seedream' },
|
|
195
251
|
{ name: 'Midjourney', value: 'midjourney' },
|
|
196
252
|
],
|
|
197
|
-
default: '
|
|
253
|
+
default: 'seedream',
|
|
198
254
|
displayOptions: {
|
|
199
255
|
show: {
|
|
200
256
|
operation: ['create'],
|
|
@@ -226,6 +282,9 @@ export class CommandosImage implements INodeType {
|
|
|
226
282
|
{ name: '4:5', value: '4:5' },
|
|
227
283
|
{ name: '16:9', value: '16:9' },
|
|
228
284
|
{ name: '9:16', value: '9:16' },
|
|
285
|
+
{ name: '4:3', value: '4:3' },
|
|
286
|
+
{ name: '3:4', value: '3:4' },
|
|
287
|
+
{ name: '21:9', value: '21:9' },
|
|
229
288
|
],
|
|
230
289
|
default: '2:3',
|
|
231
290
|
displayOptions: {
|
|
@@ -234,6 +293,56 @@ export class CommandosImage implements INodeType {
|
|
|
234
293
|
},
|
|
235
294
|
},
|
|
236
295
|
},
|
|
296
|
+
{
|
|
297
|
+
displayName: 'Output Format',
|
|
298
|
+
name: 'outputFormat',
|
|
299
|
+
type: 'options',
|
|
300
|
+
options: [
|
|
301
|
+
{ name: 'PNG', value: 'png' },
|
|
302
|
+
{ name: 'JPEG', value: 'jpeg' },
|
|
303
|
+
],
|
|
304
|
+
default: 'png',
|
|
305
|
+
displayOptions: {
|
|
306
|
+
show: {
|
|
307
|
+
operation: ['create'],
|
|
308
|
+
model: ['nano-banana', 'nano-banana-pro'],
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
displayName: 'Quality',
|
|
314
|
+
name: 'quality',
|
|
315
|
+
type: 'options',
|
|
316
|
+
options: [
|
|
317
|
+
{ name: 'Basic (2K)', value: 'basic' },
|
|
318
|
+
{ name: 'High (4K)', value: 'high' },
|
|
319
|
+
{ name: 'Medium (Balanced)', value: 'medium' },
|
|
320
|
+
],
|
|
321
|
+
default: 'basic',
|
|
322
|
+
displayOptions: {
|
|
323
|
+
show: {
|
|
324
|
+
operation: ['create'],
|
|
325
|
+
model: ['seedream', 'gpt4o-image', 'flux-pro'],
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
displayName: 'Resolution',
|
|
331
|
+
name: 'resolution',
|
|
332
|
+
type: 'options',
|
|
333
|
+
options: [
|
|
334
|
+
{ name: '1K', value: '1K' },
|
|
335
|
+
{ name: '2K', value: '2K' },
|
|
336
|
+
{ name: '4K', value: '4K' },
|
|
337
|
+
],
|
|
338
|
+
default: '1K',
|
|
339
|
+
displayOptions: {
|
|
340
|
+
show: {
|
|
341
|
+
operation: ['create'],
|
|
342
|
+
model: ['flux-pro', 'nano-banana-pro'],
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
},
|
|
237
346
|
{
|
|
238
347
|
displayName: 'References',
|
|
239
348
|
name: 'references',
|
|
@@ -294,13 +403,32 @@ export class CommandosImage implements INodeType {
|
|
|
294
403
|
const model = String(this.getNodeParameter('model', i));
|
|
295
404
|
const prompt = String(this.getNodeParameter('prompt', i) || '').trim();
|
|
296
405
|
const ratio = String(this.getNodeParameter('ratio', i));
|
|
297
|
-
const references = extractReferences(this.getNodeParameter('references', i, {}));
|
|
406
|
+
const references = extractReferences(this.getNodeParameter('references', i, {}), model);
|
|
407
|
+
|
|
408
|
+
// Get optional parameters with safe fallback
|
|
409
|
+
let outputFormat = 'png';
|
|
410
|
+
try { outputFormat = String(this.getNodeParameter('outputFormat', i)); } catch (e) {}
|
|
411
|
+
|
|
412
|
+
let quality = 'basic';
|
|
413
|
+
try { quality = String(this.getNodeParameter('quality', i)); } catch (e) {}
|
|
414
|
+
|
|
415
|
+
let resolution = '1K';
|
|
416
|
+
try { resolution = String(this.getNodeParameter('resolution', i)); } catch (e) {}
|
|
298
417
|
|
|
299
418
|
if (!prompt) {
|
|
300
419
|
throw new NodeOperationError(this.getNode(), 'Prompt is required', { itemIndex: i });
|
|
301
420
|
}
|
|
302
421
|
|
|
303
|
-
const request = buildGenerationRequest({
|
|
422
|
+
const request = buildGenerationRequest({
|
|
423
|
+
model,
|
|
424
|
+
prompt,
|
|
425
|
+
ratio,
|
|
426
|
+
references,
|
|
427
|
+
outputFormat,
|
|
428
|
+
quality,
|
|
429
|
+
resolution
|
|
430
|
+
});
|
|
431
|
+
|
|
304
432
|
if (!request.url) {
|
|
305
433
|
throw new NodeOperationError(
|
|
306
434
|
this.getNode(),
|
|
@@ -350,16 +478,13 @@ export class CommandosImage implements INodeType {
|
|
|
350
478
|
});
|
|
351
479
|
|
|
352
480
|
results.push({ json: response as IDataObject });
|
|
353
|
-
} else {
|
|
354
|
-
throw new NodeOperationError(this.getNode(), `Unknown operation: ${operation}`, {
|
|
355
|
-
itemIndex: i,
|
|
356
|
-
});
|
|
357
481
|
}
|
|
358
482
|
} catch (error) {
|
|
359
483
|
if (error instanceof NodeOperationError) {
|
|
360
484
|
throw error;
|
|
361
485
|
}
|
|
362
|
-
|
|
486
|
+
const message = error instanceof Error ? error.message : 'Request failed';
|
|
487
|
+
throw new NodeOperationError(this.getNode(), message, { itemIndex: i });
|
|
363
488
|
}
|
|
364
489
|
}
|
|
365
490
|
|