n8n-nodes-supermachine 0.3.2 → 0.4.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.
@@ -301,61 +301,85 @@ class Supermachine {
301
301
  // ACCOUNT OPERATIONS
302
302
  // ══════════════════════════════════════════════════════
303
303
  if (resource === 'account') {
304
- let requestOptions = {
305
- method: 'GET',
306
- url: '',
307
- json: true,
308
- };
309
- if (operation === 'getProfile') {
310
- requestOptions.url = 'https://dev.supermachine.art/v1/user';
311
- }
312
- else if (operation === 'listModels') {
313
- requestOptions.url = 'https://dev.supermachine.art/v1/models';
314
- if (!this.getNodeParameter('returnAll', i, false)) {
315
- requestOptions.qs = {
316
- perPage: this.getNodeParameter('limit', i, 20),
317
- page: 1,
318
- };
319
- }
320
- }
321
- else if (operation === 'getModelDetail') {
322
- const modelTitle = this.getNodeParameter('modelId', i);
323
- const modelsResponse = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', { method: 'GET', url: 'https://dev.supermachine.art/v1/models', json: true });
324
- const models = modelsResponse.items;
325
- const model = models.find((m) => m.title === modelTitle);
326
- if (!model) {
327
- throw new Error(`Model "${modelTitle}" not found`);
328
- }
329
- requestOptions.url = `https://dev.supermachine.art/v1/models/gems/id/${model.id}`;
330
- }
331
- else if (operation === 'listModelCategories') {
332
- requestOptions.url = 'https://dev.supermachine.art/v1/models/categories';
333
- }
334
- else if (operation === 'listLoras') {
335
- const modelTitle = this.getNodeParameter('modelId', i);
336
- const modelsResponse = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', { method: 'GET', url: 'https://dev.supermachine.art/v1/models', json: true });
337
- const models = modelsResponse.items;
338
- const model = models.find((m) => m.title === modelTitle);
339
- if (!model) {
340
- throw new Error(`Model "${modelTitle}" not found`);
341
- }
342
- requestOptions.url = `https://dev.supermachine.art/v1/loras?modelId=${model.id}`;
343
- }
344
- else if (operation === 'listLoraCategories') {
345
- requestOptions.url = 'https://dev.supermachine.art/v1/loras/categories';
346
- }
347
- else if (operation === 'listCharacterCategories') {
348
- requestOptions.url = 'https://dev.supermachine.art/v1/characters/categories';
349
- }
350
- const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', requestOptions);
351
- let jsonData;
352
- if (operation === 'listModels' || operation === 'listLoras') {
353
- jsonData = responseData;
304
+ if (operation === 'getToken') {
305
+ const email = this.getNodeParameter('email', i);
306
+ const password = this.getNodeParameter('password', i);
307
+ const responseData = await this.helpers.httpRequest({
308
+ method: 'POST',
309
+ url: 'https://x21u-twbn-azx4.n7c.xano.io/api:0dlVn2Lk/auth/login',
310
+ headers: {
311
+ 'accept': 'application/json, text/plain, */*',
312
+ 'accept-language': 'en-US,en;q=0.9',
313
+ 'content-type': 'application/json',
314
+ 'origin': 'https://supermachine.art',
315
+ 'referer': 'https://supermachine.art/',
316
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36',
317
+ },
318
+ json: true,
319
+ body: {
320
+ email,
321
+ password,
322
+ },
323
+ });
324
+ returnData.push({ json: responseData });
354
325
  }
355
326
  else {
356
- jsonData = responseData.items || responseData;
327
+ let requestOptions = {
328
+ method: 'GET',
329
+ url: '',
330
+ json: true,
331
+ };
332
+ if (operation === 'getProfile') {
333
+ requestOptions.url = 'https://dev.supermachine.art/v1/user';
334
+ }
335
+ else if (operation === 'listModels') {
336
+ requestOptions.url = 'https://dev.supermachine.art/v1/models';
337
+ if (!this.getNodeParameter('returnAll', i, false)) {
338
+ requestOptions.qs = {
339
+ perPage: this.getNodeParameter('limit', i, 20),
340
+ page: 1,
341
+ };
342
+ }
343
+ }
344
+ else if (operation === 'getModelDetail') {
345
+ const modelTitle = this.getNodeParameter('modelId', i);
346
+ const modelsResponse = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', { method: 'GET', url: 'https://dev.supermachine.art/v1/models', json: true });
347
+ const models = modelsResponse.items;
348
+ const model = models.find((m) => m.title === modelTitle);
349
+ if (!model) {
350
+ throw new Error(`Model "${modelTitle}" not found`);
351
+ }
352
+ requestOptions.url = `https://dev.supermachine.art/v1/models/gems/id/${model.id}`;
353
+ }
354
+ else if (operation === 'listModelCategories') {
355
+ requestOptions.url = 'https://dev.supermachine.art/v1/models/categories';
356
+ }
357
+ else if (operation === 'listLoras') {
358
+ const modelTitle = this.getNodeParameter('modelId', i);
359
+ const modelsResponse = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', { method: 'GET', url: 'https://dev.supermachine.art/v1/models', json: true });
360
+ const models = modelsResponse.items;
361
+ const model = models.find((m) => m.title === modelTitle);
362
+ if (!model) {
363
+ throw new Error(`Model "${modelTitle}" not found`);
364
+ }
365
+ requestOptions.url = `https://dev.supermachine.art/v1/loras?modelId=${model.id}`;
366
+ }
367
+ else if (operation === 'listLoraCategories') {
368
+ requestOptions.url = 'https://dev.supermachine.art/v1/loras/categories';
369
+ }
370
+ else if (operation === 'listCharacterCategories') {
371
+ requestOptions.url = 'https://dev.supermachine.art/v1/characters/categories';
372
+ }
373
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', requestOptions);
374
+ let jsonData;
375
+ if (operation === 'listModels' || operation === 'listLoras') {
376
+ jsonData = responseData;
377
+ }
378
+ else {
379
+ jsonData = responseData.items || responseData;
380
+ }
381
+ returnData.push({ json: jsonData });
357
382
  }
358
- returnData.push({ json: jsonData });
359
383
  }
360
384
  // ══════════════════════════════════════════════════════
361
385
  // CHARACTER OPERATIONS
@@ -477,7 +501,100 @@ class Supermachine {
477
501
  // IMAGE OPERATIONS
478
502
  // ══════════════════════════════════════════════════════
479
503
  else if (resource === 'image') {
480
- if (operation === 'generate') {
504
+ if (operation === 'generateV3') {
505
+ const authToken = this.getNodeParameter('authToken', i);
506
+ const additionalFieldsV3 = this.getNodeParameter('additionalFieldsV3', i, {});
507
+ const body = {
508
+ prompt: this.getNodeParameter('promptV3', i),
509
+ modelName: this.getNodeParameter('modelNameV3', i),
510
+ width: this.getNodeParameter('widthV3', i, 576),
511
+ height: this.getNodeParameter('heightV3', i, 1024),
512
+ steps: additionalFieldsV3.steps || 20,
513
+ imageNumber: additionalFieldsV3.imageNumber || 1,
514
+ generationMode: 'GENERATE',
515
+ negativePrompt: additionalFieldsV3.negativePrompt || '',
516
+ randomSeed: additionalFieldsV3.randomSeed !== undefined ? additionalFieldsV3.randomSeed : true,
517
+ guidance: additionalFieldsV3.guidance || 7,
518
+ tiling: additionalFieldsV3.tiling || false,
519
+ faceEnhance: additionalFieldsV3.faceEnhance || false,
520
+ imageStrength: additionalFieldsV3.imageStrength || null,
521
+ initImage: additionalFieldsV3.initImage || '',
522
+ folderId: additionalFieldsV3.folderId || 0,
523
+ homeUrl: 'https://supermachine.art',
524
+ refImage: '',
525
+ controlMode: 0,
526
+ controlType: '',
527
+ faceswapImage: '',
528
+ controlnetmodule_id: '0',
529
+ preset: null,
530
+ toolType: '',
531
+ sampler: additionalFieldsV3.sampler || 'Euler a',
532
+ upscaleFactor: null,
533
+ promptEnhance: additionalFieldsV3.promptEnhance || false,
534
+ };
535
+ const generateResponse = await this.helpers.httpRequest({
536
+ method: 'POST',
537
+ url: 'https://x21u-twbn-azx4.n7c.xano.io/api:0dlVn2Lk/generate/v3',
538
+ headers: {
539
+ 'accept': 'application/json, text/plain, */*',
540
+ 'accept-language': 'en-US,en;q=0.9',
541
+ 'authorization': `Bearer ${authToken}`,
542
+ 'content-type': 'application/json',
543
+ 'origin': 'https://supermachine.art',
544
+ 'referer': 'https://supermachine.art/',
545
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36',
546
+ },
547
+ json: true,
548
+ body,
549
+ });
550
+ const batchID = generateResponse.batchID;
551
+ if (!batchID) {
552
+ throw new Error('No batchID returned from generate API v3');
553
+ }
554
+ const pollingInterval = additionalFieldsV3.pollingInterval || 2;
555
+ const maxPollingTime = additionalFieldsV3.maxPollingTime || 120;
556
+ const startTime = Date.now();
557
+ let completedImage = null;
558
+ while (!completedImage) {
559
+ if ((Date.now() - startTime) / 1000 > maxPollingTime) {
560
+ throw new Error(`Image generation timed out after ${maxPollingTime} seconds. BatchID: ${batchID}`);
561
+ }
562
+ await new Promise((resolve) => setTimeout(resolve, pollingInterval * 1000));
563
+ const credentials = await this.getCredentials('supermachineApi');
564
+ const apiKey = credentials.apiKey;
565
+ const pollResponse = await this.helpers.httpRequest({
566
+ method: 'GET',
567
+ url: `https://dev.supermachine.art/v1/images?batchId=${batchID}`,
568
+ headers: {
569
+ 'Authorization': `Bearer ${apiKey}`,
570
+ 'Content-Type': 'application/json',
571
+ },
572
+ json: true,
573
+ });
574
+ const pollItems = pollResponse.items;
575
+ if (Array.isArray(pollItems) && pollItems.length > 0) {
576
+ const firstItem = pollItems[0];
577
+ const status = firstItem.status;
578
+ if (status === 'completed') {
579
+ completedImage = firstItem;
580
+ break;
581
+ }
582
+ else if (status === 'failed') {
583
+ throw new Error(`Image generation failed. BatchID: ${batchID}. Error: ${firstItem.error || 'Unknown error'}`);
584
+ }
585
+ }
586
+ }
587
+ returnData.push({
588
+ json: {
589
+ batchID,
590
+ method: generateResponse.method,
591
+ type: generateResponse.type,
592
+ finalPrompt: body.prompt,
593
+ ...completedImage,
594
+ }
595
+ });
596
+ }
597
+ else if (operation === 'generate') {
481
598
  const additionalFields = this.getNodeParameter('additionalFields', i, {});
482
599
  let prompt = this.getNodeParameter('prompt', i);
483
600
  if (additionalFields.characterId) {
@@ -16,27 +16,95 @@ exports.getAccountOperations = [
16
16
  {
17
17
  name: 'Get Profile',
18
18
  value: 'getProfile',
19
- description: 'Lấy thông tin tài khoản và credit còn lại',
19
+ description: 'Get your account information',
20
20
  action: 'Get account profile',
21
21
  },
22
+ {
23
+ name: 'Get Token (Login)',
24
+ value: 'getToken',
25
+ description: 'Get authentication token using email and password',
26
+ action: 'Get auth token',
27
+ },
22
28
  {
23
29
  name: 'List Models',
24
30
  value: 'listModels',
25
- description: 'Liệt tất cả models có sẵn',
26
- action: 'List available models',
31
+ description: 'List all available AI models',
32
+ action: 'List all models',
27
33
  },
28
34
  {
29
- name: 'Get Model Categories',
35
+ name: 'Get Model Detail',
36
+ value: 'getModelDetail',
37
+ description: 'Get detailed information about a specific model',
38
+ action: 'Get model details',
39
+ },
40
+ {
41
+ name: 'List Model Categories',
30
42
  value: 'listModelCategories',
31
- description: 'Lấy danh mục models',
43
+ description: 'List all model categories',
32
44
  action: 'List model categories',
33
45
  },
46
+ {
47
+ name: 'List LoRAs',
48
+ value: 'listLoras',
49
+ description: 'List LoRAs for a specific model',
50
+ action: 'List loras for model',
51
+ },
52
+ {
53
+ name: 'List LoRA Categories',
54
+ value: 'listLoraCategories',
55
+ description: 'List all LoRA categories',
56
+ action: 'List lora categories',
57
+ },
58
+ {
59
+ name: 'List Character Categories',
60
+ value: 'listCharacterCategories',
61
+ description: 'List all character categories',
62
+ action: 'List character categories',
63
+ },
34
64
  ],
35
65
  default: 'getProfile',
36
66
  },
37
67
  ];
38
68
  exports.getAccountFields = [
39
- // Get Profile - không cần fields
69
+ // ═══════════════════════════════════════════════════════════
70
+ // GET TOKEN (LOGIN)
71
+ // ═══════════════════════════════════════════════════════════
72
+ {
73
+ displayName: 'Email',
74
+ name: 'email',
75
+ type: 'string',
76
+ displayOptions: {
77
+ show: {
78
+ resource: ['account'],
79
+ operation: ['getToken'],
80
+ },
81
+ },
82
+ default: '',
83
+ required: true,
84
+ placeholder: 'your-email@example.com',
85
+ description: 'Your Supermachine account email',
86
+ },
87
+ {
88
+ displayName: 'Password',
89
+ name: 'password',
90
+ type: 'string',
91
+ typeOptions: {
92
+ password: true,
93
+ },
94
+ displayOptions: {
95
+ show: {
96
+ resource: ['account'],
97
+ operation: ['getToken'],
98
+ },
99
+ },
100
+ default: '',
101
+ required: true,
102
+ placeholder: 'Your password',
103
+ description: 'Your Supermachine account password',
104
+ },
105
+ // ═══════════════════════════════════════════════════════════
106
+ // LIST MODELS
107
+ // ═══════════════════════════════════════════════════════════
40
108
  {
41
109
  displayName: 'Return All',
42
110
  name: 'returnAll',
@@ -44,28 +112,45 @@ exports.getAccountFields = [
44
112
  displayOptions: {
45
113
  show: {
46
114
  resource: ['account'],
47
- operation: ['listModels', 'listModelCategories'],
115
+ operation: ['listModels'],
48
116
  },
49
117
  },
50
118
  default: false,
51
- description: 'Trả về tất cả kết quả hay chỉ giới hạn',
119
+ description: 'Whether to return all results or only up to a given limit',
52
120
  },
53
121
  {
54
122
  displayName: 'Limit',
55
123
  name: 'limit',
56
124
  type: 'number',
57
- typeOptions: {
58
- minValue: 1,
59
- maxValue: 100,
60
- },
125
+ typeOptions: { minValue: 1, maxValue: 100 },
61
126
  displayOptions: {
62
127
  show: {
63
128
  resource: ['account'],
64
- operation: ['listModels', 'listModelCategories'],
129
+ operation: ['listModels'],
65
130
  returnAll: [false],
66
131
  },
67
132
  },
68
133
  default: 20,
69
- description: 'Số lượng items trả về mỗi trang',
134
+ description: 'Max number of results to return',
135
+ },
136
+ // ═══════════════════════════════════════════════════════════
137
+ // GET MODEL DETAIL & LIST LORAS
138
+ // ═══════════════════════════════════════════════════════════
139
+ {
140
+ displayName: 'Model Name or ID',
141
+ name: 'modelId',
142
+ type: 'options',
143
+ typeOptions: {
144
+ loadOptionsMethod: 'getModels',
145
+ },
146
+ displayOptions: {
147
+ show: {
148
+ resource: ['account'],
149
+ operation: ['getModelDetail', 'listLoras'],
150
+ },
151
+ },
152
+ default: '',
153
+ required: true,
154
+ description: 'Select model. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
70
155
  },
71
156
  ];
@@ -16,9 +16,15 @@ exports.getImageOperations = [
16
16
  {
17
17
  name: 'Generate an Image',
18
18
  value: 'generate',
19
- description: 'Tạo ảnh mới từ text prompt (tự động chờ hoàn tất)',
19
+ description: 'Generate image using API v1 (requires API Key)',
20
20
  action: 'Generate an image',
21
21
  },
22
+ {
23
+ name: 'Generate an Image v3',
24
+ value: 'generateV3',
25
+ description: 'Generate image using API v3 (requires Auth Token)',
26
+ action: 'Generate an image v3',
27
+ },
22
28
  {
23
29
  name: 'List Images',
24
30
  value: 'listImages',
@@ -49,7 +55,7 @@ exports.getImageOperations = [
49
55
  ];
50
56
  exports.getImageFields = [
51
57
  // ═══════════════════════════════════════════════════════════
52
- // GENERATE OPERATION (giữ nguyên code cũ)
58
+ // GENERATE V1 (existing fields - giữ nguyên)
53
59
  // ═══════════════════════════════════════════════════════════
54
60
  {
55
61
  displayName: 'Model Name or ID',
@@ -321,7 +327,223 @@ exports.getImageFields = [
321
327
  ],
322
328
  },
323
329
  // ═══════════════════════════════════════════════════════════
324
- // LIST IMAGES
330
+ // GENERATE V3 (NEW)
331
+ // ═══════════════════════════════════════════════════════════
332
+ {
333
+ displayName: 'Auth Token',
334
+ name: 'authToken',
335
+ type: 'string',
336
+ displayOptions: {
337
+ show: {
338
+ resource: ['image'],
339
+ operation: ['generateV3'],
340
+ },
341
+ },
342
+ default: '',
343
+ required: true,
344
+ placeholder: 'eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIi...',
345
+ description: 'Authentication token from Get Token operation',
346
+ },
347
+ {
348
+ displayName: 'Model Name',
349
+ name: 'modelNameV3',
350
+ type: 'string',
351
+ displayOptions: {
352
+ show: {
353
+ resource: ['image'],
354
+ operation: ['generateV3'],
355
+ },
356
+ },
357
+ default: 'Supermachine NextGen',
358
+ required: true,
359
+ placeholder: 'Supermachine NextGen',
360
+ description: 'Model name (e.g. "Supermachine NextGen", "Supermachine Reality")',
361
+ },
362
+ {
363
+ displayName: 'Prompt',
364
+ name: 'promptV3',
365
+ type: 'string',
366
+ typeOptions: {
367
+ rows: 4,
368
+ },
369
+ displayOptions: {
370
+ show: {
371
+ resource: ['image'],
372
+ operation: ['generateV3'],
373
+ },
374
+ },
375
+ default: '',
376
+ placeholder: 'A beautiful sunset over mountains, photorealistic, 8k',
377
+ description: 'Image description',
378
+ required: true,
379
+ },
380
+ {
381
+ displayName: 'Width',
382
+ name: 'widthV3',
383
+ type: 'number',
384
+ typeOptions: {
385
+ minValue: 256,
386
+ maxValue: 2048,
387
+ },
388
+ displayOptions: {
389
+ show: {
390
+ resource: ['image'],
391
+ operation: ['generateV3'],
392
+ },
393
+ },
394
+ default: 576,
395
+ description: 'Image width (pixels)',
396
+ },
397
+ {
398
+ displayName: 'Height',
399
+ name: 'heightV3',
400
+ type: 'number',
401
+ typeOptions: {
402
+ minValue: 256,
403
+ maxValue: 2048,
404
+ },
405
+ displayOptions: {
406
+ show: {
407
+ resource: ['image'],
408
+ operation: ['generateV3'],
409
+ },
410
+ },
411
+ default: 1024,
412
+ description: 'Image height (pixels)',
413
+ },
414
+ {
415
+ displayName: 'Additional Fields V3',
416
+ name: 'additionalFieldsV3',
417
+ type: 'collection',
418
+ placeholder: 'Add Field',
419
+ default: {},
420
+ displayOptions: {
421
+ show: {
422
+ resource: ['image'],
423
+ operation: ['generateV3'],
424
+ },
425
+ },
426
+ options: [
427
+ {
428
+ displayName: 'Negative Prompt',
429
+ name: 'negativePrompt',
430
+ type: 'string',
431
+ typeOptions: { rows: 2 },
432
+ default: '',
433
+ placeholder: 'blurry, low quality, distorted',
434
+ description: 'What NOT to include in image',
435
+ },
436
+ {
437
+ displayName: 'Steps',
438
+ name: 'steps',
439
+ type: 'number',
440
+ typeOptions: { minValue: 1, maxValue: 80 },
441
+ default: 20,
442
+ description: 'Number of inference steps',
443
+ },
444
+ {
445
+ displayName: 'Guidance',
446
+ name: 'guidance',
447
+ type: 'number',
448
+ typeOptions: {
449
+ minValue: 1,
450
+ maxValue: 20,
451
+ numberPrecision: 1,
452
+ },
453
+ default: 7,
454
+ description: 'CFG Scale (guidance strength)',
455
+ },
456
+ {
457
+ displayName: 'Image Number',
458
+ name: 'imageNumber',
459
+ type: 'number',
460
+ typeOptions: { minValue: 1, maxValue: 4 },
461
+ default: 1,
462
+ description: 'Number of images to generate (1-4)',
463
+ },
464
+ {
465
+ displayName: 'Random Seed',
466
+ name: 'randomSeed',
467
+ type: 'boolean',
468
+ default: true,
469
+ description: 'Whether to use random seed',
470
+ },
471
+ {
472
+ displayName: 'Sampler',
473
+ name: 'sampler',
474
+ type: 'string',
475
+ default: 'Euler a',
476
+ placeholder: 'Euler a',
477
+ description: 'Sampling method',
478
+ },
479
+ {
480
+ displayName: 'Folder ID',
481
+ name: 'folderId',
482
+ type: 'number',
483
+ default: 0,
484
+ description: 'Folder ID to save image (0 = root)',
485
+ },
486
+ {
487
+ displayName: 'Face Enhance',
488
+ name: 'faceEnhance',
489
+ type: 'boolean',
490
+ default: false,
491
+ description: 'Whether to enhance faces',
492
+ },
493
+ {
494
+ displayName: 'Tiling',
495
+ name: 'tiling',
496
+ type: 'boolean',
497
+ default: false,
498
+ description: 'Whether to enable tiling',
499
+ },
500
+ {
501
+ displayName: 'Prompt Enhance',
502
+ name: 'promptEnhance',
503
+ type: 'boolean',
504
+ default: false,
505
+ description: 'Whether to enhance prompt automatically',
506
+ },
507
+ {
508
+ displayName: 'Init Image URL',
509
+ name: 'initImage',
510
+ type: 'string',
511
+ default: '',
512
+ placeholder: 'https://example.com/image.png',
513
+ description: 'Initial image URL for img2img',
514
+ },
515
+ {
516
+ displayName: 'Image Strength',
517
+ name: 'imageStrength',
518
+ type: 'number',
519
+ typeOptions: {
520
+ minValue: 0,
521
+ maxValue: 1,
522
+ numberPrecision: 2,
523
+ },
524
+ default: 0.75,
525
+ description: 'Image strength for img2img (0-1)',
526
+ },
527
+ {
528
+ displayName: 'Polling Interval (seconds)',
529
+ name: 'pollingInterval',
530
+ type: 'number',
531
+ typeOptions: { minValue: 1, maxValue: 10 },
532
+ default: 2,
533
+ description: 'Time between polling checks',
534
+ },
535
+ {
536
+ displayName: 'Max Polling Time (seconds)',
537
+ name: 'maxPollingTime',
538
+ type: 'number',
539
+ typeOptions: { minValue: 10, maxValue: 300 },
540
+ default: 120,
541
+ description: 'Maximum time to wait for completion',
542
+ },
543
+ ],
544
+ },
545
+ // ═══════════════════════════════════════════════════════════
546
+ // REST OF IMAGE OPERATIONS (giữ nguyên existing fields)
325
547
  // ═══════════════════════════════════════════════════════════
326
548
  {
327
549
  displayName: 'Return All',
@@ -394,9 +616,6 @@ exports.getImageFields = [
394
616
  },
395
617
  ],
396
618
  },
397
- // ═══════════════════════════════════════════════════════════
398
- // GET IMAGE
399
- // ═══════════════════════════════════════════════════════════
400
619
  {
401
620
  displayName: 'Image ID',
402
621
  name: 'imageId',
@@ -412,9 +631,6 @@ exports.getImageFields = [
412
631
  placeholder: '8870379',
413
632
  description: 'ID của ảnh',
414
633
  },
415
- // ═══════════════════════════════════════════════════════════
416
- // MOVE IMAGE
417
- // ═══════════════════════════════════════════════════════════
418
634
  {
419
635
  displayName: 'Target Folder Name or ID',
420
636
  name: 'targetFolderId',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-supermachine",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
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",