n8n-nodes-supermachine 0.1.4 → 0.2.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.
@@ -23,6 +23,7 @@ class Supermachine {
23
23
  noDataExpression: true,
24
24
  options: [
25
25
  { name: 'Account', value: 'account' },
26
+ { name: 'Folder', value: 'folder' },
26
27
  { name: 'Image', value: 'image' },
27
28
  { name: 'Tools', value: 'tools' },
28
29
  ],
@@ -30,6 +31,8 @@ class Supermachine {
30
31
  },
31
32
  ...descriptions_1.getAccountOperations,
32
33
  ...descriptions_1.getAccountFields,
34
+ ...descriptions_1.getFolderOperations,
35
+ ...descriptions_1.getFolderFields,
33
36
  ...descriptions_1.getImageOperations,
34
37
  ...descriptions_1.getImageFields,
35
38
  ...descriptions_1.getToolsOperations,
@@ -38,9 +41,6 @@ class Supermachine {
38
41
  };
39
42
  methods = {
40
43
  loadOptions: {
41
- // ═══════════════════════════════════════════════════════════
42
- // Load danh sách Models
43
- // ═══════════════════════════════════════════════════════════
44
44
  async getModels() {
45
45
  const credentials = await this.getCredentials('supermachineApi');
46
46
  const apiKey = credentials.apiKey;
@@ -69,9 +69,6 @@ class Supermachine {
69
69
  return [{ name: `⚠️ Error: ${error.message}`, value: '' }];
70
70
  }
71
71
  },
72
- // ═══════════════════════════════════════════════════════════
73
- // Load danh sách LoRAs theo modelId được chọn
74
- // ═══════════════════════════════════════════════════════════
75
72
  async getLoras() {
76
73
  const credentials = await this.getCredentials('supermachineApi');
77
74
  const apiKey = credentials.apiKey;
@@ -141,9 +138,6 @@ class Supermachine {
141
138
  }];
142
139
  }
143
140
  },
144
- // ═══════════════════════════════════════════════════════════
145
- // Load danh sách Character Categories
146
- // ═══════════════════════════════════════════════════════════
147
141
  async getCharacterCategories() {
148
142
  const credentials = await this.getCredentials('supermachineApi');
149
143
  const apiKey = credentials.apiKey;
@@ -180,9 +174,6 @@ class Supermachine {
180
174
  }];
181
175
  }
182
176
  },
183
- // ═══════════════════════════════════════════════════════════
184
- // Load danh sách Characters (phụ thuộc category + model)
185
- // ═══════════════════════════════════════════════════════════
186
177
  async getCharacters() {
187
178
  const credentials = await this.getCredentials('supermachineApi');
188
179
  const apiKey = credentials.apiKey;
@@ -242,11 +233,10 @@ class Supermachine {
242
233
  }
243
234
  return items.map((character) => {
244
235
  const embedCode = character.embedCode;
245
- const embedHint = embedCode ? ` | Use: "${embedCode}"` : '';
246
236
  return {
247
237
  name: character.name,
248
- value: String(character.id),
249
- description: `${character.slug}${embedHint}`,
238
+ value: embedCode || String(character.id),
239
+ description: embedCode ? `Embed: "${embedCode}" (auto-add to prompt)` : character.slug,
250
240
  };
251
241
  });
252
242
  }
@@ -259,6 +249,45 @@ class Supermachine {
259
249
  }];
260
250
  }
261
251
  },
252
+ // ═══════════════════════════════════════════════════════════
253
+ // Load Folders
254
+ // ═══════════════════════════════════════════════════════════
255
+ async getFolders() {
256
+ const credentials = await this.getCredentials('supermachineApi');
257
+ const apiKey = credentials.apiKey;
258
+ try {
259
+ const response = await this.helpers.httpRequest({
260
+ method: 'GET',
261
+ url: 'https://dev.supermachine.art/v1/folders',
262
+ headers: {
263
+ 'Authorization': `Bearer ${apiKey}`,
264
+ 'Content-Type': 'application/json',
265
+ },
266
+ json: true,
267
+ });
268
+ const items = response.items;
269
+ if (!Array.isArray(items) || items.length === 0) {
270
+ return [{
271
+ name: 'No folders available',
272
+ value: '',
273
+ description: 'Create a folder first'
274
+ }];
275
+ }
276
+ return items.map((folder) => ({
277
+ name: folder.name,
278
+ value: String(folder.id),
279
+ description: `ID: ${folder.id} | Created: ${folder.createdAt}`,
280
+ }));
281
+ }
282
+ catch (error) {
283
+ console.error('Supermachine getFolders error:', error);
284
+ return [{
285
+ name: `⚠️ Error: ${error.message}`,
286
+ value: '',
287
+ description: 'Check your API key and permissions'
288
+ }];
289
+ }
290
+ },
262
291
  },
263
292
  };
264
293
  async execute() {
@@ -329,13 +358,93 @@ class Supermachine {
329
358
  returnData.push({ json: jsonData });
330
359
  }
331
360
  // ══════════════════════════════════════════════════════
361
+ // FOLDER OPERATIONS
362
+ // ══════════════════════════════════════════════════════
363
+ else if (resource === 'folder') {
364
+ if (operation === 'listFolders') {
365
+ const requestOptions = {
366
+ method: 'GET',
367
+ url: 'https://dev.supermachine.art/v1/folders',
368
+ json: true,
369
+ };
370
+ if (!this.getNodeParameter('returnAll', i, false)) {
371
+ requestOptions.qs = {
372
+ limit: this.getNodeParameter('limit', i, 20),
373
+ };
374
+ }
375
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', requestOptions);
376
+ returnData.push({ json: responseData });
377
+ }
378
+ else if (operation === 'getFolder') {
379
+ const folderId = this.getNodeParameter('folderId', i);
380
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
381
+ method: 'GET',
382
+ url: `https://dev.supermachine.art/v1/folders/${folderId}`,
383
+ json: true,
384
+ });
385
+ returnData.push({ json: responseData });
386
+ }
387
+ else if (operation === 'createFolder') {
388
+ const folderName = this.getNodeParameter('folderName', i);
389
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
390
+ method: 'POST',
391
+ url: 'https://dev.supermachine.art/v1/folders',
392
+ json: true,
393
+ body: {
394
+ name: folderName,
395
+ },
396
+ });
397
+ returnData.push({ json: responseData });
398
+ }
399
+ else if (operation === 'renameFolder') {
400
+ const folderId = this.getNodeParameter('folderId', i);
401
+ const newFolderName = this.getNodeParameter('newFolderName', i);
402
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
403
+ method: 'PUT',
404
+ url: `https://dev.supermachine.art/v1/folders/${folderId}`,
405
+ json: true,
406
+ body: {
407
+ name: newFolderName,
408
+ },
409
+ });
410
+ returnData.push({ json: responseData });
411
+ }
412
+ else if (operation === 'deleteFolder') {
413
+ const folderId = this.getNodeParameter('folderId', i);
414
+ const deleteMode = this.getNodeParameter('deleteMode', i);
415
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
416
+ method: 'DELETE',
417
+ url: `https://dev.supermachine.art/v1/folders/${folderId}`,
418
+ json: true,
419
+ qs: {
420
+ deleteImages: deleteMode === 'deleteImages',
421
+ },
422
+ });
423
+ returnData.push({
424
+ json: {
425
+ success: true,
426
+ folderId,
427
+ deleteMode,
428
+ message: `Folder deleted successfully${deleteMode === 'deleteImages' ? ' (including images)' : ' (images kept)'}`,
429
+ }
430
+ });
431
+ }
432
+ }
433
+ // ══════════════════════════════════════════════════════
332
434
  // IMAGE OPERATIONS
333
435
  // ══════════════════════════════════════════════════════
334
436
  else if (resource === 'image') {
335
437
  if (operation === 'generate') {
336
438
  const additionalFields = this.getNodeParameter('additionalFields', i, {});
439
+ let prompt = this.getNodeParameter('prompt', i);
440
+ if (additionalFields.characterId) {
441
+ const characterEmbedCode = additionalFields.characterId;
442
+ if (characterEmbedCode) {
443
+ prompt = `${prompt} a photo of ${characterEmbedCode}`.trim();
444
+ }
445
+ }
337
446
  const body = {
338
- prompt: this.getNodeParameter('prompt', i),
447
+ prompt: prompt,
339
448
  model: this.getNodeParameter('model', i),
340
449
  width: this.getNodeParameter('width', i, 1024),
341
450
  height: this.getNodeParameter('height', i, 768),
@@ -358,6 +467,9 @@ class Supermachine {
358
467
  if (additionalFields.cfgScale) {
359
468
  body.cfgScale = additionalFields.cfgScale;
360
469
  }
470
+ if (additionalFields.folderId) {
471
+ body.folderId = additionalFields.folderId;
472
+ }
361
473
  if (additionalFields.loras) {
362
474
  const lorasData = additionalFields.loras;
363
475
  const loraValues = lorasData.loraValues;
@@ -368,9 +480,6 @@ class Supermachine {
368
480
  }));
369
481
  }
370
482
  }
371
- if (additionalFields.characterId) {
372
- body.characterId = additionalFields.characterId;
373
- }
374
483
  if (additionalFields.img2img) {
375
484
  const img2imgData = additionalFields.img2img;
376
485
  const img2imgValues = img2imgData.img2imgValues;
@@ -422,29 +531,17 @@ class Supermachine {
422
531
  returnData.push({
423
532
  json: {
424
533
  batchId,
534
+ finalPrompt: prompt,
425
535
  ...completedImage,
426
536
  }
427
537
  });
428
538
  }
429
- else if (operation === 'listImages') {
430
- const batchId = this.getNodeParameter('batchId', i);
431
- const listResponse = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
432
- method: 'GET',
433
- url: `https://dev.supermachine.art/v1/images?batchId=${batchId}`,
434
- json: true,
435
- qs: !this.getNodeParameter('returnAll', i, false) ? {
436
- limit: this.getNodeParameter('limit', i, 20),
437
- page: this.getNodeParameter('page', i, 1),
438
- } : undefined,
439
- });
440
- returnData.push({ json: listResponse });
441
- }
442
539
  }
443
540
  // ══════════════════════════════════════════════════════
444
541
  // TOOLS OPERATIONS
445
542
  // ══════════════════════════════════════════════════════
446
543
  else if (resource === 'tools') {
447
- throw new Error('Tools operations chưa endpoints chính thức từ Supermachine API docs.');
544
+ throw new Error('⚠️ Tools operations are coming soon. These features will be available when Supermachine API provides official endpoints.');
448
545
  }
449
546
  }
450
547
  catch (error) {
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getFolderFields = exports.getFolderOperations = void 0;
4
+ exports.getFolderOperations = [
5
+ {
6
+ displayName: 'Operation',
7
+ name: 'operation',
8
+ type: 'options',
9
+ noDataExpression: true,
10
+ displayOptions: {
11
+ show: {
12
+ resource: ['folder'],
13
+ },
14
+ },
15
+ options: [
16
+ {
17
+ name: 'List Folders',
18
+ value: 'listFolders',
19
+ description: 'List all your folders',
20
+ action: 'List all folders',
21
+ },
22
+ {
23
+ name: 'Get Folder',
24
+ value: 'getFolder',
25
+ description: 'Get a single folder by ID',
26
+ action: 'Get a folder by ID',
27
+ },
28
+ {
29
+ name: 'Create Folder',
30
+ value: 'createFolder',
31
+ description: 'Create a new folder',
32
+ action: 'Create a new folder',
33
+ },
34
+ {
35
+ name: 'Rename Folder',
36
+ value: 'renameFolder',
37
+ description: 'Rename an existing folder',
38
+ action: 'Rename a folder',
39
+ },
40
+ {
41
+ name: 'Delete Folder',
42
+ value: 'deleteFolder',
43
+ description: 'Delete a folder with options',
44
+ action: 'Delete a folder',
45
+ },
46
+ ],
47
+ default: 'listFolders',
48
+ },
49
+ ];
50
+ exports.getFolderFields = [
51
+ // ═══════════════════════════════════════════════════════════
52
+ // LIST FOLDERS
53
+ // ═══════════════════════════════════════════════════════════
54
+ {
55
+ displayName: 'Return All',
56
+ name: 'returnAll',
57
+ type: 'boolean',
58
+ displayOptions: {
59
+ show: {
60
+ resource: ['folder'],
61
+ operation: ['listFolders'],
62
+ },
63
+ },
64
+ default: false,
65
+ description: 'Whether to return all results or only up to a given limit',
66
+ },
67
+ {
68
+ displayName: 'Limit',
69
+ name: 'limit',
70
+ type: 'number',
71
+ typeOptions: { minValue: 1, maxValue: 100 },
72
+ displayOptions: {
73
+ show: {
74
+ resource: ['folder'],
75
+ operation: ['listFolders'],
76
+ returnAll: [false],
77
+ },
78
+ },
79
+ default: 20,
80
+ description: 'Max number of results to return',
81
+ },
82
+ // ═══════════════════════════════════════════════════════════
83
+ // GET FOLDER
84
+ // ═══════════════════════════════════════════════════════════
85
+ {
86
+ displayName: 'Folder Name or ID',
87
+ name: 'folderId',
88
+ type: 'options',
89
+ typeOptions: {
90
+ loadOptionsMethod: 'getFolders',
91
+ },
92
+ displayOptions: {
93
+ show: {
94
+ resource: ['folder'],
95
+ operation: ['getFolder', 'renameFolder', 'deleteFolder'],
96
+ },
97
+ },
98
+ default: '',
99
+ required: true,
100
+ description: 'Select folder. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
101
+ },
102
+ // ═══════════════════════════════════════════════════════════
103
+ // CREATE FOLDER
104
+ // ═══════════════════════════════════════════════════════════
105
+ {
106
+ displayName: 'Folder Name',
107
+ name: 'folderName',
108
+ type: 'string',
109
+ displayOptions: {
110
+ show: {
111
+ resource: ['folder'],
112
+ operation: ['createFolder'],
113
+ },
114
+ },
115
+ default: '',
116
+ required: true,
117
+ placeholder: 'My New Folder',
118
+ description: 'Name for the new folder',
119
+ },
120
+ // ═══════════════════════════════════════════════════════════
121
+ // RENAME FOLDER
122
+ // ═══════════════════════════════════════════════════════════
123
+ {
124
+ displayName: 'New Name',
125
+ name: 'newFolderName',
126
+ type: 'string',
127
+ displayOptions: {
128
+ show: {
129
+ resource: ['folder'],
130
+ operation: ['renameFolder'],
131
+ },
132
+ },
133
+ default: '',
134
+ required: true,
135
+ placeholder: 'Renamed Folder',
136
+ description: 'New name for the folder',
137
+ },
138
+ // ═══════════════════════════════════════════════════════════
139
+ // DELETE FOLDER
140
+ // ═══════════════════════════════════════════════════════════
141
+ {
142
+ displayName: 'Delete Mode',
143
+ name: 'deleteMode',
144
+ type: 'options',
145
+ options: [
146
+ {
147
+ name: 'Delete Folder, Keep Images',
148
+ value: 'keepImages',
149
+ description: 'Delete folder but keep all images inside',
150
+ },
151
+ {
152
+ name: 'Delete Folder AND Images',
153
+ value: 'deleteImages',
154
+ description: 'Delete folder and all images inside (cannot be undone)',
155
+ },
156
+ ],
157
+ displayOptions: {
158
+ show: {
159
+ resource: ['folder'],
160
+ operation: ['deleteFolder'],
161
+ },
162
+ },
163
+ default: 'keepImages',
164
+ required: true,
165
+ description: 'Choose what to do with images in the folder',
166
+ },
167
+ ];
@@ -19,20 +19,12 @@ exports.getImageOperations = [
19
19
  description: 'Tạo ảnh mới từ text prompt (tự động chờ hoàn tất)',
20
20
  action: 'Generate an image',
21
21
  },
22
- {
23
- name: 'List Generated Images',
24
- value: 'listImages',
25
- description: 'Liệt kê tất cả ảnh theo batchId',
26
- action: 'List generated images',
27
- },
28
22
  ],
29
23
  default: 'generate',
30
24
  },
31
25
  ];
32
26
  exports.getImageFields = [
33
- // ═══════════════════════════════════════════════════════════
34
- // GENERATE OPERATION
35
- // ═══════════════════════════════════════════════════════════
27
+ // Model, Prompt, Width, Height fields giữ nguyên...
36
28
  {
37
29
  displayName: 'Model Name or ID',
38
30
  name: 'model',
@@ -47,7 +39,7 @@ exports.getImageFields = [
47
39
  },
48
40
  },
49
41
  default: '',
50
- description: 'Model AI dùng để generate ảnh. Chọn từ danh sách. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
42
+ description: 'Model AI dùng để generate ảnh. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
51
43
  required: true,
52
44
  },
53
45
  {
@@ -83,7 +75,7 @@ exports.getImageFields = [
83
75
  },
84
76
  },
85
77
  default: 1024,
86
- description: 'Chiều rộng ảnh tính bằng pixels (256-2048)',
78
+ description: 'Chiều rộng ảnh (pixels)',
87
79
  },
88
80
  {
89
81
  displayName: 'Height',
@@ -100,7 +92,7 @@ exports.getImageFields = [
100
92
  },
101
93
  },
102
94
  default: 768,
103
- description: 'Chiều cao ảnh tính bằng pixels (256-2048)',
95
+ description: 'Chiều cao ảnh (pixels)',
104
96
  },
105
97
  {
106
98
  displayName: 'Additional Fields',
@@ -130,7 +122,7 @@ exports.getImageFields = [
130
122
  type: 'number',
131
123
  typeOptions: { minValue: 1, maxValue: 4 },
132
124
  default: 1,
133
- description: 'Số ảnh tạo cùng lúc (1-4). Mỗi ảnh tốn 1 credit.',
125
+ description: 'Số ảnh tạo cùng lúc (1-4)',
134
126
  },
135
127
  {
136
128
  displayName: 'Output Format',
@@ -142,7 +134,7 @@ exports.getImageFields = [
142
134
  { name: 'JPEG', value: 'JPEG' },
143
135
  ],
144
136
  default: 'PNG',
145
- description: 'Định dạng file ảnh đầu ra',
137
+ description: 'Định dạng file ảnh',
146
138
  },
147
139
  {
148
140
  displayName: 'Seed',
@@ -150,7 +142,7 @@ exports.getImageFields = [
150
142
  type: 'number',
151
143
  typeOptions: { minValue: 0, maxValue: 2147483647 },
152
144
  default: 0,
153
- description: 'Seed cố định để tái tạo kết quả giống nhau (0 = random)',
145
+ description: 'Seed (0 = random)',
154
146
  },
155
147
  {
156
148
  displayName: 'Steps',
@@ -158,7 +150,7 @@ exports.getImageFields = [
158
150
  type: 'number',
159
151
  typeOptions: { minValue: 1, maxValue: 80 },
160
152
  default: 30,
161
- description: 'Số bước inference. Nhiều hơn = chất lượng cao hơn nhưng chậm hơn (20-50 recommended).',
153
+ description: 'Số bước inference (20-50 recommended)',
162
154
  },
163
155
  {
164
156
  displayName: 'CFG Scale',
@@ -170,7 +162,17 @@ exports.getImageFields = [
170
162
  numberPrecision: 1,
171
163
  },
172
164
  default: 7,
173
- description: 'Độ tuân thủ prompt. Cao hơn = tuân thủ strict hơn (7-9 recommended).',
165
+ description: 'Độ tuân thủ prompt (7-9 recommended)',
166
+ },
167
+ {
168
+ displayName: 'Move to Folder',
169
+ name: 'folderId',
170
+ type: 'options',
171
+ typeOptions: {
172
+ loadOptionsMethod: 'getFolders',
173
+ },
174
+ default: '',
175
+ description: 'Move generated image to this folder. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
174
176
  },
175
177
  {
176
178
  displayName: 'Polling Interval (seconds)',
@@ -178,7 +180,7 @@ exports.getImageFields = [
178
180
  type: 'number',
179
181
  typeOptions: { minValue: 1, maxValue: 10 },
180
182
  default: 2,
181
- description: 'Thời gian chờ giữa các lần kiểm tra status (giây). Default: 2 giây.',
183
+ description: 'Thời gian chờ giữa các lần check (giây)',
182
184
  },
183
185
  {
184
186
  displayName: 'Max Polling Time (seconds)',
@@ -186,7 +188,7 @@ exports.getImageFields = [
186
188
  type: 'number',
187
189
  typeOptions: { minValue: 10, maxValue: 300 },
188
190
  default: 120,
189
- description: 'Thời gian tối đa chờ hoàn thành (giây). Default: 120 giây (2 phút).',
191
+ description: 'Thời gian tối đa chờ hoàn thành (giây)',
190
192
  },
191
193
  {
192
194
  displayName: 'LoRAs',
@@ -196,7 +198,7 @@ exports.getImageFields = [
196
198
  multipleValues: true,
197
199
  },
198
200
  default: {},
199
- description: 'Thêm LoRA để điều chỉnh style. ⚠️ Phải chọn Model trước!',
201
+ description: 'Thêm LoRA để điều chỉnh style',
200
202
  options: [
201
203
  {
202
204
  name: 'loraValues',
@@ -211,7 +213,7 @@ exports.getImageFields = [
211
213
  loadOptionsDependsOn: ['model'],
212
214
  },
213
215
  default: '',
214
- description: 'Chọn LoRA. Dropdown sẽ load sau khi chọn Model. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
216
+ description: 'Chọn LoRA. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
215
217
  },
216
218
  {
217
219
  displayName: 'Strength',
@@ -223,7 +225,7 @@ exports.getImageFields = [
223
225
  numberPrecision: 1,
224
226
  },
225
227
  default: 1,
226
- description: 'Độ mạnh của LoRA (0-2). Default: 1.0',
228
+ description: 'Độ mạnh của LoRA (0-2)',
227
229
  },
228
230
  ],
229
231
  },
@@ -237,7 +239,7 @@ exports.getImageFields = [
237
239
  loadOptionsMethod: 'getCharacterCategories',
238
240
  },
239
241
  default: '',
240
- description: 'Chọn category để filter characters (Female, Male, Young Adult, Middle Aged). Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
242
+ description: 'Chọn category để filter characters. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
241
243
  },
242
244
  {
243
245
  displayName: 'Character',
@@ -253,14 +255,14 @@ exports.getImageFields = [
253
255
  },
254
256
  },
255
257
  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>.',
258
+ description: 'Chọn character. Embed code sẽ tự động thêm vào prompt. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
257
259
  },
258
260
  {
259
261
  displayName: 'Image to Image',
260
262
  name: 'img2img',
261
263
  type: 'fixedCollection',
262
264
  default: {},
263
- description: 'Dùng ảnh có sẵn làm base để generate',
265
+ description: 'Dùng ảnh có sẵn làm base',
264
266
  options: [
265
267
  {
266
268
  name: 'img2imgValues',
@@ -272,7 +274,7 @@ exports.getImageFields = [
272
274
  type: 'string',
273
275
  default: '',
274
276
  placeholder: 'https://example.com/image.png',
275
- description: 'URL của ảnh gốc dùng làm base',
277
+ description: 'URL của ảnh gốc',
276
278
  },
277
279
  {
278
280
  displayName: 'Denoising Strength',
@@ -284,7 +286,7 @@ exports.getImageFields = [
284
286
  numberPrecision: 2,
285
287
  },
286
288
  default: 0.75,
287
- description: 'Mức độ thay đổi so với ảnh gốc (0=giữ nguyên, 1=thay đổi hoàn toàn)',
289
+ description: 'Mức độ thay đổi (0-1)',
288
290
  },
289
291
  ],
290
292
  },
@@ -292,64 +294,4 @@ exports.getImageFields = [
292
294
  },
293
295
  ],
294
296
  },
295
- // ═══════════════════════════════════════════════════════════
296
- // LIST IMAGES OPERATION
297
- // ═══════════════════════════════════════════════════════════
298
- {
299
- displayName: 'Batch ID',
300
- name: 'batchId',
301
- type: 'string',
302
- displayOptions: {
303
- show: {
304
- resource: ['image'],
305
- operation: ['listImages'],
306
- },
307
- },
308
- default: '',
309
- placeholder: '1994761',
310
- description: 'batchId nhận được từ Generate operation response',
311
- required: true,
312
- },
313
- {
314
- displayName: 'Return All',
315
- name: 'returnAll',
316
- type: 'boolean',
317
- displayOptions: {
318
- show: {
319
- resource: ['image'],
320
- operation: ['listImages'],
321
- },
322
- },
323
- default: false,
324
- description: 'Whether to return all results or only up to a given limit',
325
- },
326
- {
327
- displayName: 'Limit',
328
- name: 'limit',
329
- type: 'number',
330
- typeOptions: { minValue: 1, maxValue: 100 },
331
- displayOptions: {
332
- show: {
333
- resource: ['image'],
334
- operation: ['listImages'],
335
- returnAll: [false],
336
- },
337
- },
338
- default: 20,
339
- description: 'Max number of results to return',
340
- },
341
- {
342
- displayName: 'Page',
343
- name: 'page',
344
- type: 'number',
345
- typeOptions: { minValue: 1 },
346
- displayOptions: {
347
- show: {
348
- resource: ['image'],
349
- operation: ['listImages'],
350
- },
351
- },
352
- default: 1,
353
- description: 'Số trang để fetch (bắt đầu từ 1)',
354
- },
355
297
  ];
@@ -14,226 +14,50 @@ exports.getToolsOperations = [
14
14
  },
15
15
  options: [
16
16
  {
17
- name: 'Instruct Edit an Image',
18
- value: 'instructEdit',
19
- description: 'Chỉnh sửa ảnh theo text instruction',
20
- action: 'Instruct edit an image',
17
+ name: 'Image to Prompt (Coming Soon)',
18
+ value: 'imageToPrompt',
19
+ description: 'Generate text prompt from an image',
20
+ action: 'Image to prompt',
21
21
  },
22
22
  {
23
- name: 'Upscale an Image',
24
- value: 'upscale',
25
- description: 'Tăng độ phân giải ảnh',
26
- action: 'Upscale an image',
23
+ name: 'Remove Background (Coming Soon)',
24
+ value: 'removeBackground',
25
+ description: 'Remove background from an image',
26
+ action: 'Remove background',
27
27
  },
28
28
  {
29
- name: 'Face Swap an Image',
29
+ name: 'Face Swap (Coming Soon)',
30
30
  value: 'faceSwap',
31
- description: 'Hoán đổi khuôn mặt trong ảnh',
32
- action: 'Face swap an image',
33
- },
34
- ],
35
- default: 'instructEdit',
36
- },
37
- ];
38
- exports.getToolsFields = [
39
- // ─── INSTRUCT EDIT ───────────────────────────────────────
40
- {
41
- displayName: 'Input Image URL',
42
- name: 'inputImageUrl',
43
- type: 'string',
44
- displayOptions: {
45
- show: {
46
- resource: ['tools'],
47
- operation: ['instructEdit'],
48
- },
49
- },
50
- default: '',
51
- placeholder: 'https://riku-assets.com/generations/xxx.png',
52
- description: 'URL ảnh gốc muốn chỉnh sửa (từ List Images hoặc URL ngoài)',
53
- required: true,
54
- },
55
- {
56
- displayName: 'Edit Instruction',
57
- name: 'editPrompt',
58
- type: 'string',
59
- typeOptions: { rows: 3 },
60
- displayOptions: {
61
- show: {
62
- resource: ['tools'],
63
- operation: ['instructEdit'],
64
- },
65
- },
66
- default: '',
67
- placeholder: 'Add a red hat to the person, keep the background the same',
68
- description: 'Mô tả thay đổi muốn áp dụng lên ảnh',
69
- required: true,
70
- },
71
- {
72
- displayName: 'Additional Fields',
73
- name: 'additionalFields',
74
- type: 'collection',
75
- placeholder: 'Add Field',
76
- default: {},
77
- displayOptions: {
78
- show: {
79
- resource: ['tools'],
80
- operation: ['instructEdit'],
81
- },
82
- },
83
- options: [
84
- {
85
- displayName: 'Model Name or ID',
86
- name: 'model',
87
- type: 'options',
88
- typeOptions: {
89
- loadOptionsMethod: 'getModels',
90
- },
91
- default: '',
92
- description: 'Model AI dùng để edit ảnh',
93
- },
94
- {
95
- displayName: 'Steps',
96
- name: 'steps',
97
- type: 'number',
98
- typeOptions: { minValue: 1, maxValue: 50 },
99
- default: 20,
100
- description: 'Số bước inference',
31
+ description: 'Swap faces in images',
32
+ action: 'Face swap',
101
33
  },
102
34
  {
103
- displayName: 'CFG Scale',
104
- name: 'cfgScale',
105
- type: 'number',
106
- typeOptions: { minValue: 1, maxValue: 10 },
107
- default: 7,
108
- description: 'Độ tuân thủ instruction',
109
- },
110
- {
111
- displayName: 'Callback URL',
112
- name: 'callbackUrl',
113
- type: 'string',
114
- default: '',
115
- placeholder: 'https://your-n8n.com/webhook/supermachine-callback',
116
- description: 'Webhook URL nhận kết quả async',
117
- },
118
- ],
119
- },
120
- // ─── UPSCALE ─────────────────────────────────────────────
121
- {
122
- displayName: 'Input Image URL',
123
- name: 'inputImageUrl',
124
- type: 'string',
125
- displayOptions: {
126
- show: {
127
- resource: ['tools'],
128
- operation: ['upscale'],
129
- },
130
- },
131
- default: '',
132
- placeholder: 'https://riku-assets.com/generations/xxx.png',
133
- description: 'URL ảnh muốn upscale',
134
- required: true,
135
- },
136
- {
137
- displayName: 'Upscale Factor',
138
- name: 'upscaleFactor',
139
- type: 'options',
140
- displayOptions: {
141
- show: {
142
- resource: ['tools'],
143
- operation: ['upscale'],
144
- },
145
- },
146
- options: [
147
- { name: '2x', value: 2 },
148
- { name: '4x', value: 4 },
149
- { name: '8x', value: 8 },
150
- ],
151
- default: 2,
152
- description: 'Tăng kích thước ảnh bao nhiêu lần',
153
- },
154
- {
155
- displayName: 'Additional Fields',
156
- name: 'additionalFields',
157
- type: 'collection',
158
- placeholder: 'Add Field',
159
- default: {},
160
- displayOptions: {
161
- show: {
162
- resource: ['tools'],
163
- operation: ['upscale'],
35
+ name: 'Upscale (Coming Soon)',
36
+ value: 'upscale',
37
+ description: 'Upscale image resolution up to 2x',
38
+ action: 'Upscale image',
164
39
  },
165
- },
166
- options: [
167
40
  {
168
- displayName: 'Callback URL',
169
- name: 'callbackUrl',
170
- type: 'string',
171
- default: '',
172
- placeholder: 'https://your-n8n.com/webhook/supermachine-callback',
173
- description: 'Webhook URL nhận kết quả async',
41
+ name: 'Instruct Edit (Coming Soon)',
42
+ value: 'instructEdit',
43
+ description: 'Edit image using text instructions',
44
+ action: 'Instruct edit',
174
45
  },
175
46
  ],
47
+ default: 'imageToPrompt',
176
48
  },
177
- // ─── FACE SWAP ───────────────────────────────────────────
178
- {
179
- displayName: 'Target Image URL',
180
- name: 'inputImageUrl',
181
- type: 'string',
182
- displayOptions: {
183
- show: {
184
- resource: ['tools'],
185
- operation: ['faceSwap'],
186
- },
187
- },
188
- default: '',
189
- placeholder: 'https://riku-assets.com/generations/xxx.png',
190
- description: 'URL ảnh đích (ảnh sẽ được swap khuôn mặt vào)',
191
- required: true,
192
- },
49
+ ];
50
+ exports.getToolsFields = [
193
51
  {
194
- displayName: 'Face Image URL',
195
- name: 'faceImageUrl',
196
- type: 'string',
52
+ displayName: 'Coming Soon',
53
+ name: 'comingSoonNotice',
54
+ type: 'notice',
197
55
  displayOptions: {
198
56
  show: {
199
57
  resource: ['tools'],
200
- operation: ['faceSwap'],
201
58
  },
202
59
  },
203
60
  default: '',
204
- placeholder: 'https://example.com/face.png',
205
- description: 'URL ảnh khuôn mặt nguồn muốn swap vào ảnh đích',
206
- required: true,
207
- },
208
- {
209
- displayName: 'Additional Fields',
210
- name: 'additionalFields',
211
- type: 'collection',
212
- placeholder: 'Add Field',
213
- default: {},
214
- displayOptions: {
215
- show: {
216
- resource: ['tools'],
217
- operation: ['faceSwap'],
218
- },
219
- },
220
- options: [
221
- {
222
- displayName: 'Strength',
223
- name: 'strength',
224
- type: 'number',
225
- typeOptions: { minValue: 0, maxValue: 1 },
226
- default: 0.8,
227
- description: 'Độ mạnh face swap (0.0 - 1.0)',
228
- },
229
- {
230
- displayName: 'Callback URL',
231
- name: 'callbackUrl',
232
- type: 'string',
233
- default: '',
234
- placeholder: 'https://your-n8n.com/webhook/supermachine-callback',
235
- description: 'Webhook URL nhận kết quả async',
236
- },
237
- ],
61
+ description: '⚠️ Tools operations are coming soon. These features will be available in a future update when Supermachine API provides official endpoints.',
238
62
  },
239
63
  ];
@@ -15,5 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./AccountDescription"), exports);
18
+ __exportStar(require("./FolderDescription"), exports);
18
19
  __exportStar(require("./ImageDescription"), exports);
19
20
  __exportStar(require("./ToolsDescription"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-supermachine",
3
- "version": "0.1.4",
3
+ "version": "0.2.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",