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: `${character.slug}${embedHint}`,
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: this.getNodeParameter('prompt', i),
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 items = pollResponse.items;
411
- if (Array.isArray(items) && items.length > 0) {
412
- const firstItem = items[0];
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
- requestOptions.url = `https://dev.supermachine.art/v1/images?batchId=${batchId}`;
435
- if (!this.getNodeParameter('returnAll', i, false)) {
436
- requestOptions.qs = {
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
- const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', requestOptions);
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. Vui lòng check documentation.');
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ẽ hiện trong description. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
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",
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": {