n8n-nodes-supermachine 0.1.3 → 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.
|
@@ -242,11 +242,10 @@ class Supermachine {
|
|
|
242
242
|
}
|
|
243
243
|
return items.map((character) => {
|
|
244
244
|
const embedCode = character.embedCode;
|
|
245
|
-
const embedHint = embedCode ? ` | Use: "${embedCode}"` : '';
|
|
246
245
|
return {
|
|
247
246
|
name: character.name,
|
|
248
|
-
value: String(character.id),
|
|
249
|
-
description:
|
|
247
|
+
value: embedCode || String(character.id),
|
|
248
|
+
description: embedCode ? `Embed: "${embedCode}" (will auto-add as "a photo of ${embedCode}")` : character.slug,
|
|
250
249
|
};
|
|
251
250
|
});
|
|
252
251
|
}
|
|
@@ -268,15 +267,15 @@ class Supermachine {
|
|
|
268
267
|
try {
|
|
269
268
|
const resource = this.getNodeParameter('resource', i);
|
|
270
269
|
const operation = this.getNodeParameter('operation', i);
|
|
271
|
-
let requestOptions = {
|
|
272
|
-
method: 'GET',
|
|
273
|
-
url: '',
|
|
274
|
-
json: true,
|
|
275
|
-
};
|
|
276
270
|
// ══════════════════════════════════════════════════════
|
|
277
271
|
// ACCOUNT OPERATIONS
|
|
278
272
|
// ══════════════════════════════════════════════════════
|
|
279
273
|
if (resource === 'account') {
|
|
274
|
+
let requestOptions = {
|
|
275
|
+
method: 'GET',
|
|
276
|
+
url: '',
|
|
277
|
+
json: true,
|
|
278
|
+
};
|
|
280
279
|
if (operation === 'getProfile') {
|
|
281
280
|
requestOptions.url = 'https://dev.supermachine.art/v1/user';
|
|
282
281
|
}
|
|
@@ -318,21 +317,38 @@ class Supermachine {
|
|
|
318
317
|
else if (operation === 'listCharacterCategories') {
|
|
319
318
|
requestOptions.url = 'https://dev.supermachine.art/v1/characters/categories';
|
|
320
319
|
}
|
|
320
|
+
const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', requestOptions);
|
|
321
|
+
let jsonData;
|
|
322
|
+
if (operation === 'listModels' || operation === 'listLoras') {
|
|
323
|
+
jsonData = responseData;
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
jsonData = responseData.items || responseData;
|
|
327
|
+
}
|
|
328
|
+
returnData.push({ json: jsonData });
|
|
321
329
|
}
|
|
322
330
|
// ══════════════════════════════════════════════════════
|
|
323
331
|
// IMAGE OPERATIONS
|
|
324
332
|
// ══════════════════════════════════════════════════════
|
|
325
333
|
else if (resource === 'image') {
|
|
326
334
|
if (operation === 'generate') {
|
|
327
|
-
// BƯỚC 1: Start generation
|
|
328
335
|
const additionalFields = this.getNodeParameter('additionalFields', i, {});
|
|
336
|
+
// Get base prompt
|
|
337
|
+
let prompt = this.getNodeParameter('prompt', i);
|
|
338
|
+
// ✅ TỰ ĐỘNG THÊM CHARACTER EMBED CODE VÀO PROMPT
|
|
339
|
+
if (additionalFields.characterId) {
|
|
340
|
+
const characterEmbedCode = additionalFields.characterId;
|
|
341
|
+
if (characterEmbedCode) {
|
|
342
|
+
// Nối vào cuối prompt với format "a photo of <embedCode>"
|
|
343
|
+
prompt = `${prompt} a photo of ${characterEmbedCode}`.trim();
|
|
344
|
+
}
|
|
345
|
+
}
|
|
329
346
|
const body = {
|
|
330
|
-
prompt:
|
|
347
|
+
prompt: prompt,
|
|
331
348
|
model: this.getNodeParameter('model', i),
|
|
332
349
|
width: this.getNodeParameter('width', i, 1024),
|
|
333
350
|
height: this.getNodeParameter('height', i, 768),
|
|
334
351
|
};
|
|
335
|
-
// Add optional fields
|
|
336
352
|
if (additionalFields.negativePrompt) {
|
|
337
353
|
body.negativePrompt = additionalFields.negativePrompt;
|
|
338
354
|
}
|
|
@@ -351,7 +367,6 @@ class Supermachine {
|
|
|
351
367
|
if (additionalFields.cfgScale) {
|
|
352
368
|
body.cfgScale = additionalFields.cfgScale;
|
|
353
369
|
}
|
|
354
|
-
// Add LoRAs
|
|
355
370
|
if (additionalFields.loras) {
|
|
356
371
|
const lorasData = additionalFields.loras;
|
|
357
372
|
const loraValues = lorasData.loraValues;
|
|
@@ -362,11 +377,6 @@ class Supermachine {
|
|
|
362
377
|
}));
|
|
363
378
|
}
|
|
364
379
|
}
|
|
365
|
-
// Add character
|
|
366
|
-
if (additionalFields.characterId) {
|
|
367
|
-
body.characterId = additionalFields.characterId;
|
|
368
|
-
}
|
|
369
|
-
// Add img2img
|
|
370
380
|
if (additionalFields.img2img) {
|
|
371
381
|
const img2imgData = additionalFields.img2img;
|
|
372
382
|
const img2imgValues = img2imgData.img2imgValues;
|
|
@@ -378,7 +388,6 @@ class Supermachine {
|
|
|
378
388
|
}
|
|
379
389
|
}
|
|
380
390
|
}
|
|
381
|
-
// Start generation
|
|
382
391
|
const generateResponse = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
|
|
383
392
|
method: 'POST',
|
|
384
393
|
url: 'https://dev.supermachine.art/v1/generate',
|
|
@@ -389,27 +398,23 @@ class Supermachine {
|
|
|
389
398
|
if (!batchId) {
|
|
390
399
|
throw new Error('No batchId returned from generate API');
|
|
391
400
|
}
|
|
392
|
-
// BƯỚC 2: Poll for completion
|
|
393
401
|
const pollingInterval = additionalFields.pollingInterval || 2;
|
|
394
402
|
const maxPollingTime = additionalFields.maxPollingTime || 120;
|
|
395
403
|
const startTime = Date.now();
|
|
396
404
|
let completedImage = null;
|
|
397
405
|
while (!completedImage) {
|
|
398
|
-
// Check timeout
|
|
399
406
|
if ((Date.now() - startTime) / 1000 > maxPollingTime) {
|
|
400
407
|
throw new Error(`Image generation timed out after ${maxPollingTime} seconds. BatchId: ${batchId}`);
|
|
401
408
|
}
|
|
402
|
-
// Wait before polling
|
|
403
409
|
await new Promise((resolve) => setTimeout(resolve, pollingInterval * 1000));
|
|
404
|
-
// Poll status
|
|
405
410
|
const pollResponse = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
|
|
406
411
|
method: 'GET',
|
|
407
412
|
url: `https://dev.supermachine.art/v1/images?batchId=${batchId}`,
|
|
408
413
|
json: true,
|
|
409
414
|
});
|
|
410
|
-
const
|
|
411
|
-
if (Array.isArray(
|
|
412
|
-
const firstItem =
|
|
415
|
+
const pollItems = pollResponse.items;
|
|
416
|
+
if (Array.isArray(pollItems) && pollItems.length > 0) {
|
|
417
|
+
const firstItem = pollItems[0];
|
|
413
418
|
const status = firstItem.status;
|
|
414
419
|
if (status === 'completed') {
|
|
415
420
|
completedImage = firstItem;
|
|
@@ -418,45 +423,36 @@ class Supermachine {
|
|
|
418
423
|
else if (status === 'failed') {
|
|
419
424
|
throw new Error(`Image generation failed. BatchId: ${batchId}. Error: ${firstItem.error || 'Unknown error'}`);
|
|
420
425
|
}
|
|
421
|
-
// If status is 'pending' or 'processing', continue polling
|
|
422
426
|
}
|
|
423
427
|
}
|
|
424
|
-
// Return completed image data
|
|
425
428
|
returnData.push({
|
|
426
429
|
json: {
|
|
427
430
|
batchId,
|
|
431
|
+
finalPrompt: prompt,
|
|
428
432
|
...completedImage,
|
|
429
433
|
}
|
|
430
434
|
});
|
|
431
435
|
}
|
|
432
436
|
else if (operation === 'listImages') {
|
|
433
437
|
const batchId = this.getNodeParameter('batchId', i);
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
438
|
+
const listResponse = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
|
|
439
|
+
method: 'GET',
|
|
440
|
+
url: `https://dev.supermachine.art/v1/images?batchId=${batchId}`,
|
|
441
|
+
json: true,
|
|
442
|
+
qs: !this.getNodeParameter('returnAll', i, false) ? {
|
|
437
443
|
limit: this.getNodeParameter('limit', i, 20),
|
|
438
444
|
page: this.getNodeParameter('page', i, 1),
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
returnData.push({ json: responseData });
|
|
445
|
+
} : undefined,
|
|
446
|
+
});
|
|
447
|
+
returnData.push({ json: listResponse });
|
|
443
448
|
}
|
|
444
449
|
}
|
|
445
450
|
// ══════════════════════════════════════════════════════
|
|
446
451
|
// TOOLS OPERATIONS
|
|
447
452
|
// ══════════════════════════════════════════════════════
|
|
448
453
|
else if (resource === 'tools') {
|
|
449
|
-
throw new Error('Tools operations chưa có endpoints chính thức từ Supermachine API docs.
|
|
450
|
-
}
|
|
451
|
-
const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', requestOptions);
|
|
452
|
-
let jsonData;
|
|
453
|
-
if (operation === 'listModels' || operation === 'listImages' || operation === 'listLoras') {
|
|
454
|
-
jsonData = responseData;
|
|
455
|
-
}
|
|
456
|
-
else {
|
|
457
|
-
jsonData = responseData.items || responseData;
|
|
454
|
+
throw new Error('Tools operations chưa có endpoints chính thức từ Supermachine API docs.');
|
|
458
455
|
}
|
|
459
|
-
returnData.push({ json: jsonData });
|
|
460
456
|
}
|
|
461
457
|
catch (error) {
|
|
462
458
|
if (this.continueOnFail()) {
|
|
@@ -253,7 +253,7 @@ exports.getImageFields = [
|
|
|
253
253
|
},
|
|
254
254
|
},
|
|
255
255
|
default: '',
|
|
256
|
-
description: 'Chọn character. ⚠️ Phải chọn Model và Category trước! Embed code sẽ
|
|
256
|
+
description: 'Chọn character. ⚠️ Phải chọn Model và Category trước! Embed code (vd: h4kum1) sẽ tự động nối vào cuối prompt dưới dạng "a photo of <embedCode>". Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
|
|
257
257
|
},
|
|
258
258
|
{
|
|
259
259
|
displayName: 'Image to Image',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-supermachine",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "n8n community node for Supermachine AI Image API — Generate images, manage models, LoRAs, and characters",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"dist/credentials/SupermachineApi.credentials.js"
|
|
39
39
|
],
|
|
40
40
|
"nodes": [
|
|
41
|
-
"dist/nodes/Supermachine/Supermachine.node.js"
|
|
41
|
+
"dist/nodes/Supermachine/Supermachine.node.js"
|
|
42
42
|
]
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|