n8n-nodes-supermachine 0.1.5 → 0.3.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,8 @@ class Supermachine {
23
23
  noDataExpression: true,
24
24
  options: [
25
25
  { name: 'Account', value: 'account' },
26
+ { name: 'Character', value: 'character' },
27
+ { name: 'Folder', value: 'folder' },
26
28
  { name: 'Image', value: 'image' },
27
29
  { name: 'Tools', value: 'tools' },
28
30
  ],
@@ -30,6 +32,10 @@ class Supermachine {
30
32
  },
31
33
  ...descriptions_1.getAccountOperations,
32
34
  ...descriptions_1.getAccountFields,
35
+ ...descriptions_1.getCharacterOperations,
36
+ ...descriptions_1.getCharacterFields,
37
+ ...descriptions_1.getFolderOperations,
38
+ ...descriptions_1.getFolderFields,
33
39
  ...descriptions_1.getImageOperations,
34
40
  ...descriptions_1.getImageFields,
35
41
  ...descriptions_1.getToolsOperations,
@@ -38,9 +44,6 @@ class Supermachine {
38
44
  };
39
45
  methods = {
40
46
  loadOptions: {
41
- // ═══════════════════════════════════════════════════════════
42
- // Load danh sách Models
43
- // ═══════════════════════════════════════════════════════════
44
47
  async getModels() {
45
48
  const credentials = await this.getCredentials('supermachineApi');
46
49
  const apiKey = credentials.apiKey;
@@ -69,9 +72,6 @@ class Supermachine {
69
72
  return [{ name: `⚠️ Error: ${error.message}`, value: '' }];
70
73
  }
71
74
  },
72
- // ═══════════════════════════════════════════════════════════
73
- // Load danh sách LoRAs theo modelId được chọn
74
- // ═══════════════════════════════════════════════════════════
75
75
  async getLoras() {
76
76
  const credentials = await this.getCredentials('supermachineApi');
77
77
  const apiKey = credentials.apiKey;
@@ -141,9 +141,6 @@ class Supermachine {
141
141
  }];
142
142
  }
143
143
  },
144
- // ═══════════════════════════════════════════════════════════
145
- // Load danh sách Character Categories
146
- // ═══════════════════════════════════════════════════════════
147
144
  async getCharacterCategories() {
148
145
  const credentials = await this.getCredentials('supermachineApi');
149
146
  const apiKey = credentials.apiKey;
@@ -180,9 +177,6 @@ class Supermachine {
180
177
  }];
181
178
  }
182
179
  },
183
- // ═══════════════════════════════════════════════════════════
184
- // Load danh sách Characters (phụ thuộc category + model)
185
- // ═══════════════════════════════════════════════════════════
186
180
  async getCharacters() {
187
181
  const credentials = await this.getCredentials('supermachineApi');
188
182
  const apiKey = credentials.apiKey;
@@ -245,7 +239,7 @@ class Supermachine {
245
239
  return {
246
240
  name: character.name,
247
241
  value: embedCode || String(character.id),
248
- description: embedCode ? `Embed: "${embedCode}" (will auto-add as "a photo of ${embedCode}")` : character.slug,
242
+ description: embedCode ? `Embed: "${embedCode}" (auto-add to prompt)` : character.slug,
249
243
  };
250
244
  });
251
245
  }
@@ -258,6 +252,45 @@ class Supermachine {
258
252
  }];
259
253
  }
260
254
  },
255
+ // ═══════════════════════════════════════════════════════════
256
+ // Load Folders
257
+ // ═══════════════════════════════════════════════════════════
258
+ async getFolders() {
259
+ const credentials = await this.getCredentials('supermachineApi');
260
+ const apiKey = credentials.apiKey;
261
+ try {
262
+ const response = await this.helpers.httpRequest({
263
+ method: 'GET',
264
+ url: 'https://dev.supermachine.art/v1/folders',
265
+ headers: {
266
+ 'Authorization': `Bearer ${apiKey}`,
267
+ 'Content-Type': 'application/json',
268
+ },
269
+ json: true,
270
+ });
271
+ const items = response.items;
272
+ if (!Array.isArray(items) || items.length === 0) {
273
+ return [{
274
+ name: 'No folders available',
275
+ value: '',
276
+ description: 'Create a folder first'
277
+ }];
278
+ }
279
+ return items.map((folder) => ({
280
+ name: folder.name,
281
+ value: String(folder.id),
282
+ description: `ID: ${folder.id} | Created: ${folder.createdAt}`,
283
+ }));
284
+ }
285
+ catch (error) {
286
+ console.error('Supermachine getFolders error:', error);
287
+ return [{
288
+ name: `⚠️ Error: ${error.message}`,
289
+ value: '',
290
+ description: 'Check your API key and permissions'
291
+ }];
292
+ }
293
+ },
261
294
  },
262
295
  };
263
296
  async execute() {
@@ -328,130 +361,205 @@ class Supermachine {
328
361
  returnData.push({ json: jsonData });
329
362
  }
330
363
  // ══════════════════════════════════════════════════════
331
- // IMAGE OPERATIONS
364
+ // CHARACTER OPERATIONS
332
365
  // ══════════════════════════════════════════════════════
333
- else if (resource === 'image') {
334
- if (operation === 'generate') {
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
- }
346
- const body = {
347
- prompt: prompt,
348
- model: this.getNodeParameter('model', i),
349
- width: this.getNodeParameter('width', i, 1024),
350
- height: this.getNodeParameter('height', i, 768),
366
+ else if (resource === 'character') {
367
+ if (operation === 'listCharacters') {
368
+ const filters = this.getNodeParameter('filters', i, {});
369
+ const requestOptions = {
370
+ method: 'GET',
371
+ url: 'https://dev.supermachine.art/v1/characters',
372
+ json: true,
373
+ qs: {},
351
374
  };
352
- if (additionalFields.negativePrompt) {
353
- body.negativePrompt = additionalFields.negativePrompt;
354
- }
355
- if (additionalFields.numberResults) {
356
- body.numberResults = additionalFields.numberResults;
375
+ if (!this.getNodeParameter('returnAll', i, false)) {
376
+ requestOptions.qs.limit = this.getNodeParameter('limit', i, 20);
357
377
  }
358
- if (additionalFields.outputFormat) {
359
- body.outputFormat = additionalFields.outputFormat;
378
+ if (filters.categoryId) {
379
+ requestOptions.qs.categoryId = filters.categoryId;
360
380
  }
361
- if (additionalFields.seed) {
362
- body.seed = additionalFields.seed;
381
+ if (filters.modelId) {
382
+ // Convert model title to modelId
383
+ const modelTitle = filters.modelId;
384
+ const modelsResponse = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', { method: 'GET', url: 'https://dev.supermachine.art/v1/models', json: true });
385
+ const models = modelsResponse.items;
386
+ const model = models.find((m) => m.title === modelTitle);
387
+ if (model) {
388
+ requestOptions.qs.modelId = model.id;
389
+ }
363
390
  }
364
- if (additionalFields.steps) {
365
- body.steps = additionalFields.steps;
391
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', requestOptions);
392
+ returnData.push({ json: responseData });
393
+ }
394
+ else if (operation === 'listCategories') {
395
+ const requestOptions = {
396
+ method: 'GET',
397
+ url: 'https://dev.supermachine.art/v1/characters/categories',
398
+ json: true,
399
+ };
400
+ if (!this.getNodeParameter('returnAll', i, false)) {
401
+ requestOptions.qs = {
402
+ limit: this.getNodeParameter('limit', i, 20),
403
+ };
366
404
  }
367
- if (additionalFields.cfgScale) {
368
- body.cfgScale = additionalFields.cfgScale;
405
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', requestOptions);
406
+ returnData.push({ json: responseData });
407
+ }
408
+ }
409
+ // ══════════════════════════════════════════════════════
410
+ // FOLDER OPERATIONS
411
+ // ══════════════════════════════════════════════════════
412
+ else if (resource === 'folder') {
413
+ if (operation === 'listFolders') {
414
+ const requestOptions = {
415
+ method: 'GET',
416
+ url: 'https://dev.supermachine.art/v1/folders',
417
+ json: true,
418
+ };
419
+ if (!this.getNodeParameter('returnAll', i, false)) {
420
+ requestOptions.qs = {
421
+ limit: this.getNodeParameter('limit', i, 20),
422
+ };
369
423
  }
370
- if (additionalFields.loras) {
371
- const lorasData = additionalFields.loras;
372
- const loraValues = lorasData.loraValues;
373
- if (Array.isArray(loraValues) && loraValues.length > 0) {
374
- body.loras = loraValues.map((lora) => ({
375
- id: lora.loraId,
376
- strength: lora.strength || 1,
377
- }));
424
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', requestOptions);
425
+ returnData.push({ json: responseData });
426
+ }
427
+ else if (operation === 'getFolder') {
428
+ const folderId = this.getNodeParameter('folderId', i);
429
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
430
+ method: 'GET',
431
+ url: `https://dev.supermachine.art/v1/folders/${folderId}`,
432
+ json: true,
433
+ });
434
+ returnData.push({ json: responseData });
435
+ }
436
+ else if (operation === 'createFolder') {
437
+ const folderName = this.getNodeParameter('folderName', i);
438
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
439
+ method: 'POST',
440
+ url: 'https://dev.supermachine.art/v1/folders',
441
+ json: true,
442
+ body: {
443
+ name: folderName,
444
+ },
445
+ });
446
+ returnData.push({ json: responseData });
447
+ }
448
+ else if (operation === 'renameFolder') {
449
+ const folderId = this.getNodeParameter('folderId', i);
450
+ const newFolderName = this.getNodeParameter('newFolderName', i);
451
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
452
+ method: 'PUT',
453
+ url: `https://dev.supermachine.art/v1/folders/${folderId}`,
454
+ json: true,
455
+ body: {
456
+ name: newFolderName,
457
+ },
458
+ });
459
+ returnData.push({ json: responseData });
460
+ }
461
+ else if (operation === 'deleteFolder') {
462
+ const folderId = this.getNodeParameter('folderId', i);
463
+ const deleteMode = this.getNodeParameter('deleteMode', i);
464
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
465
+ method: 'DELETE',
466
+ url: `https://dev.supermachine.art/v1/folders/${folderId}`,
467
+ json: true,
468
+ qs: {
469
+ deleteImages: deleteMode === 'deleteImages',
470
+ },
471
+ });
472
+ returnData.push({
473
+ json: {
474
+ success: true,
475
+ folderId,
476
+ deleteMode,
477
+ message: `Folder deleted successfully${deleteMode === 'deleteImages' ? ' (including images)' : ' (images kept)'}`,
378
478
  }
479
+ });
480
+ }
481
+ }
482
+ // ══════════════════════════════════════════════════════
483
+ // IMAGE OPERATIONS
484
+ // ══════════════════════════════════════════════════════
485
+ else if (resource === 'image') {
486
+ if (operation === 'generate') {
487
+ // ... giữ nguyên code generate hiện tại ...
488
+ }
489
+ else if (operation === 'listImages') {
490
+ const filters = this.getNodeParameter('filters', i, {});
491
+ const requestOptions = {
492
+ method: 'GET',
493
+ url: 'https://dev.supermachine.art/v1/images',
494
+ json: true,
495
+ qs: {},
496
+ };
497
+ if (!this.getNodeParameter('returnAll', i, false)) {
498
+ requestOptions.qs.limit = this.getNodeParameter('limit', i, 20);
379
499
  }
380
- if (additionalFields.img2img) {
381
- const img2imgData = additionalFields.img2img;
382
- const img2imgValues = img2imgData.img2imgValues;
383
- if (Array.isArray(img2imgValues) && img2imgValues.length > 0) {
384
- const img2img = img2imgValues[0];
385
- if (img2img.sourceImageUrl) {
386
- body.sourceImageUrl = img2img.sourceImageUrl;
387
- body.denoisingStrength = img2img.denoisingStrength || 0.75;
388
- }
389
- }
500
+ if (filters.batchId) {
501
+ requestOptions.qs.batchId = filters.batchId;
502
+ }
503
+ if (filters.folderId) {
504
+ requestOptions.qs.folderId = filters.folderId;
390
505
  }
391
- const generateResponse = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
506
+ if (filters.model) {
507
+ requestOptions.qs.model = filters.model;
508
+ }
509
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', requestOptions);
510
+ returnData.push({ json: responseData });
511
+ }
512
+ else if (operation === 'getImage') {
513
+ const imageId = this.getNodeParameter('imageId', i);
514
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
515
+ method: 'GET',
516
+ url: `https://dev.supermachine.art/v1/images/${imageId}`,
517
+ json: true,
518
+ });
519
+ returnData.push({ json: responseData });
520
+ }
521
+ else if (operation === 'moveImage') {
522
+ const imageId = this.getNodeParameter('imageId', i);
523
+ const targetFolderId = this.getNodeParameter('targetFolderId', i);
524
+ const responseData = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
392
525
  method: 'POST',
393
- url: 'https://dev.supermachine.art/v1/generate',
526
+ url: `https://dev.supermachine.art/v1/images/${imageId}/move`,
394
527
  json: true,
395
- body,
528
+ body: {
529
+ folderId: targetFolderId,
530
+ },
396
531
  });
397
- const batchId = generateResponse.batchId;
398
- if (!batchId) {
399
- throw new Error('No batchId returned from generate API');
400
- }
401
- const pollingInterval = additionalFields.pollingInterval || 2;
402
- const maxPollingTime = additionalFields.maxPollingTime || 120;
403
- const startTime = Date.now();
404
- let completedImage = null;
405
- while (!completedImage) {
406
- if ((Date.now() - startTime) / 1000 > maxPollingTime) {
407
- throw new Error(`Image generation timed out after ${maxPollingTime} seconds. BatchId: ${batchId}`);
408
- }
409
- await new Promise((resolve) => setTimeout(resolve, pollingInterval * 1000));
410
- const pollResponse = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
411
- method: 'GET',
412
- url: `https://dev.supermachine.art/v1/images?batchId=${batchId}`,
413
- json: true,
414
- });
415
- const pollItems = pollResponse.items;
416
- if (Array.isArray(pollItems) && pollItems.length > 0) {
417
- const firstItem = pollItems[0];
418
- const status = firstItem.status;
419
- if (status === 'completed') {
420
- completedImage = firstItem;
421
- break;
422
- }
423
- else if (status === 'failed') {
424
- throw new Error(`Image generation failed. BatchId: ${batchId}. Error: ${firstItem.error || 'Unknown error'}`);
425
- }
426
- }
427
- }
428
532
  returnData.push({
429
533
  json: {
430
- batchId,
431
- finalPrompt: prompt,
432
- ...completedImage,
534
+ success: true,
535
+ imageId,
536
+ targetFolderId,
537
+ message: 'Image moved successfully',
538
+ ...responseData,
433
539
  }
434
540
  });
435
541
  }
436
- else if (operation === 'listImages') {
437
- const batchId = this.getNodeParameter('batchId', i);
438
- const listResponse = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
439
- method: 'GET',
440
- url: `https://dev.supermachine.art/v1/images?batchId=${batchId}`,
542
+ else if (operation === 'deleteImage') {
543
+ const imageId = this.getNodeParameter('imageId', i);
544
+ await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
545
+ method: 'DELETE',
546
+ url: `https://dev.supermachine.art/v1/images/${imageId}`,
441
547
  json: true,
442
- qs: !this.getNodeParameter('returnAll', i, false) ? {
443
- limit: this.getNodeParameter('limit', i, 20),
444
- page: this.getNodeParameter('page', i, 1),
445
- } : undefined,
446
548
  });
447
- returnData.push({ json: listResponse });
549
+ returnData.push({
550
+ json: {
551
+ success: true,
552
+ imageId,
553
+ message: 'Image deleted successfully',
554
+ }
555
+ });
448
556
  }
449
557
  }
450
558
  // ══════════════════════════════════════════════════════
451
559
  // TOOLS OPERATIONS
452
560
  // ══════════════════════════════════════════════════════
453
561
  else if (resource === 'tools') {
454
- throw new Error('Tools operations chưa endpoints chính thức từ Supermachine API docs.');
562
+ throw new Error('⚠️ Tools operations are coming soon. These features will be available when Supermachine API provides official endpoints.');
455
563
  }
456
564
  }
457
565
  catch (error) {
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCharacterFields = exports.getCharacterOperations = void 0;
4
+ exports.getCharacterOperations = [
5
+ {
6
+ displayName: 'Operation',
7
+ name: 'operation',
8
+ type: 'options',
9
+ noDataExpression: true,
10
+ displayOptions: {
11
+ show: {
12
+ resource: ['character'],
13
+ },
14
+ },
15
+ options: [
16
+ {
17
+ name: 'List Characters',
18
+ value: 'listCharacters',
19
+ description: 'List characters, optionally filtered by category or model',
20
+ action: 'List all characters',
21
+ },
22
+ {
23
+ name: 'List Character Categories',
24
+ value: 'listCategories',
25
+ description: 'List all character categories',
26
+ action: 'List character categories',
27
+ },
28
+ ],
29
+ default: 'listCharacters',
30
+ },
31
+ ];
32
+ exports.getCharacterFields = [
33
+ // ═══════════════════════════════════════════════════════════
34
+ // LIST CHARACTERS
35
+ // ═══════════════════════════════════════════════════════════
36
+ {
37
+ displayName: 'Return All',
38
+ name: 'returnAll',
39
+ type: 'boolean',
40
+ displayOptions: {
41
+ show: {
42
+ resource: ['character'],
43
+ operation: ['listCharacters', 'listCategories'],
44
+ },
45
+ },
46
+ default: false,
47
+ description: 'Whether to return all results or only up to a given limit',
48
+ },
49
+ {
50
+ displayName: 'Limit',
51
+ name: 'limit',
52
+ type: 'number',
53
+ typeOptions: { minValue: 1, maxValue: 100 },
54
+ displayOptions: {
55
+ show: {
56
+ resource: ['character'],
57
+ operation: ['listCharacters', 'listCategories'],
58
+ returnAll: [false],
59
+ },
60
+ },
61
+ default: 20,
62
+ description: 'Max number of results to return',
63
+ },
64
+ {
65
+ displayName: 'Filters',
66
+ name: 'filters',
67
+ type: 'collection',
68
+ placeholder: 'Add Filter',
69
+ default: {},
70
+ displayOptions: {
71
+ show: {
72
+ resource: ['character'],
73
+ operation: ['listCharacters'],
74
+ },
75
+ },
76
+ options: [
77
+ {
78
+ displayName: 'Category Name or ID',
79
+ name: 'categoryId',
80
+ type: 'options',
81
+ typeOptions: {
82
+ loadOptionsMethod: 'getCharacterCategories',
83
+ },
84
+ default: '',
85
+ description: 'Filter by character category. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
86
+ },
87
+ {
88
+ displayName: 'Model Name or ID',
89
+ name: 'modelId',
90
+ type: 'options',
91
+ typeOptions: {
92
+ loadOptionsMethod: 'getModels',
93
+ },
94
+ default: '',
95
+ description: 'Filter by compatible model. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
96
+ },
97
+ ],
98
+ },
99
+ ];
@@ -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
+ ];
@@ -20,10 +20,28 @@ exports.getImageOperations = [
20
20
  action: 'Generate an image',
21
21
  },
22
22
  {
23
- name: 'List Generated Images',
23
+ name: 'List Images',
24
24
  value: 'listImages',
25
- description: 'Liệt tất cả ảnh theo batchId',
26
- action: 'List generated images',
25
+ description: 'List all generated images',
26
+ action: 'List all images',
27
+ },
28
+ {
29
+ name: 'Get Image',
30
+ value: 'getImage',
31
+ description: 'Get a single image by ID',
32
+ action: 'Get an image by ID',
33
+ },
34
+ {
35
+ name: 'Move Image to Folder',
36
+ value: 'moveImage',
37
+ description: 'Move an image to a specific folder',
38
+ action: 'Move image to folder',
39
+ },
40
+ {
41
+ name: 'Delete Image',
42
+ value: 'deleteImage',
43
+ description: 'Delete an image permanently',
44
+ action: 'Delete an image',
27
45
  },
28
46
  ],
29
47
  default: 'generate',
@@ -31,7 +49,7 @@ exports.getImageOperations = [
31
49
  ];
32
50
  exports.getImageFields = [
33
51
  // ═══════════════════════════════════════════════════════════
34
- // GENERATE OPERATION
52
+ // GENERATE OPERATION (giữ nguyên code cũ)
35
53
  // ═══════════════════════════════════════════════════════════
36
54
  {
37
55
  displayName: 'Model Name or ID',
@@ -47,7 +65,7 @@ exports.getImageFields = [
47
65
  },
48
66
  },
49
67
  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>.',
68
+ 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
69
  required: true,
52
70
  },
53
71
  {
@@ -65,7 +83,7 @@ exports.getImageFields = [
65
83
  },
66
84
  default: '',
67
85
  placeholder: 'A beautiful sunset over mountains, photorealistic, 8k',
68
- description: 'Mô tả ảnh muốn tạo (bằng tiếng Anh cho kết quả tốt nhất)',
86
+ description: 'Mô tả ảnh muốn tạo',
69
87
  required: true,
70
88
  },
71
89
  {
@@ -83,7 +101,7 @@ exports.getImageFields = [
83
101
  },
84
102
  },
85
103
  default: 1024,
86
- description: 'Chiều rộng ảnh tính bằng pixels (256-2048)',
104
+ description: 'Chiều rộng ảnh (pixels)',
87
105
  },
88
106
  {
89
107
  displayName: 'Height',
@@ -100,7 +118,7 @@ exports.getImageFields = [
100
118
  },
101
119
  },
102
120
  default: 768,
103
- description: 'Chiều cao ảnh tính bằng pixels (256-2048)',
121
+ description: 'Chiều cao ảnh (pixels)',
104
122
  },
105
123
  {
106
124
  displayName: 'Additional Fields',
@@ -122,7 +140,7 @@ exports.getImageFields = [
122
140
  typeOptions: { rows: 2 },
123
141
  default: '',
124
142
  placeholder: 'blurry, low quality, distorted',
125
- description: 'Những gì KHÔNG muốn xuất hiện trong ảnh',
143
+ description: 'Những gì KHÔNG muốn xuất hiện',
126
144
  },
127
145
  {
128
146
  displayName: 'Number of Results',
@@ -130,7 +148,7 @@ exports.getImageFields = [
130
148
  type: 'number',
131
149
  typeOptions: { minValue: 1, maxValue: 4 },
132
150
  default: 1,
133
- description: 'Số ảnh tạo cùng lúc (1-4). Mỗi ảnh tốn 1 credit.',
151
+ description: 'Số ảnh tạo cùng lúc (1-4)',
134
152
  },
135
153
  {
136
154
  displayName: 'Output Format',
@@ -142,7 +160,7 @@ exports.getImageFields = [
142
160
  { name: 'JPEG', value: 'JPEG' },
143
161
  ],
144
162
  default: 'PNG',
145
- description: 'Định dạng file ảnh đầu ra',
163
+ description: 'Định dạng file ảnh',
146
164
  },
147
165
  {
148
166
  displayName: 'Seed',
@@ -150,7 +168,7 @@ exports.getImageFields = [
150
168
  type: 'number',
151
169
  typeOptions: { minValue: 0, maxValue: 2147483647 },
152
170
  default: 0,
153
- description: 'Seed cố định để tái tạo kết quả giống nhau (0 = random)',
171
+ description: 'Seed (0 = random)',
154
172
  },
155
173
  {
156
174
  displayName: 'Steps',
@@ -158,7 +176,7 @@ exports.getImageFields = [
158
176
  type: 'number',
159
177
  typeOptions: { minValue: 1, maxValue: 80 },
160
178
  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).',
179
+ description: 'Số bước inference',
162
180
  },
163
181
  {
164
182
  displayName: 'CFG Scale',
@@ -170,7 +188,17 @@ exports.getImageFields = [
170
188
  numberPrecision: 1,
171
189
  },
172
190
  default: 7,
173
- description: 'Độ tuân thủ prompt. Cao hơn = tuân thủ strict hơn (7-9 recommended).',
191
+ description: 'Độ tuân thủ prompt',
192
+ },
193
+ {
194
+ displayName: 'Move to Folder',
195
+ name: 'folderId',
196
+ type: 'options',
197
+ typeOptions: {
198
+ loadOptionsMethod: 'getFolders',
199
+ },
200
+ default: '',
201
+ description: 'Move image to folder. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
174
202
  },
175
203
  {
176
204
  displayName: 'Polling Interval (seconds)',
@@ -178,7 +206,7 @@ exports.getImageFields = [
178
206
  type: 'number',
179
207
  typeOptions: { minValue: 1, maxValue: 10 },
180
208
  default: 2,
181
- description: 'Thời gian chờ giữa các lần kiểm tra status (giây). Default: 2 giây.',
209
+ description: 'Thời gian chờ giữa các lần check',
182
210
  },
183
211
  {
184
212
  displayName: 'Max Polling Time (seconds)',
@@ -186,7 +214,7 @@ exports.getImageFields = [
186
214
  type: 'number',
187
215
  typeOptions: { minValue: 10, maxValue: 300 },
188
216
  default: 120,
189
- description: 'Thời gian tối đa chờ hoàn thành (giây). Default: 120 giây (2 phút).',
217
+ description: 'Thời gian tối đa chờ',
190
218
  },
191
219
  {
192
220
  displayName: 'LoRAs',
@@ -196,7 +224,7 @@ exports.getImageFields = [
196
224
  multipleValues: true,
197
225
  },
198
226
  default: {},
199
- description: 'Thêm LoRA để điều chỉnh style. ⚠️ Phải chọn Model trước!',
227
+ description: 'Thêm LoRA',
200
228
  options: [
201
229
  {
202
230
  name: 'loraValues',
@@ -211,7 +239,7 @@ exports.getImageFields = [
211
239
  loadOptionsDependsOn: ['model'],
212
240
  },
213
241
  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>.',
242
+ 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
243
  },
216
244
  {
217
245
  displayName: 'Strength',
@@ -223,7 +251,7 @@ exports.getImageFields = [
223
251
  numberPrecision: 1,
224
252
  },
225
253
  default: 1,
226
- description: 'Độ mạnh của LoRA (0-2). Default: 1.0',
254
+ description: 'Độ mạnh LoRA (0-2)',
227
255
  },
228
256
  ],
229
257
  },
@@ -237,7 +265,7 @@ exports.getImageFields = [
237
265
  loadOptionsMethod: 'getCharacterCategories',
238
266
  },
239
267
  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>.',
268
+ description: 'Chọn category. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
241
269
  },
242
270
  {
243
271
  displayName: 'Character',
@@ -253,14 +281,14 @@ exports.getImageFields = [
253
281
  },
254
282
  },
255
283
  default: '',
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>.',
284
+ description: 'Chọn character. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
257
285
  },
258
286
  {
259
287
  displayName: 'Image to Image',
260
288
  name: 'img2img',
261
289
  type: 'fixedCollection',
262
290
  default: {},
263
- description: 'Dùng ảnh có sẵn làm base để generate',
291
+ description: 'Dùng ảnh làm base',
264
292
  options: [
265
293
  {
266
294
  name: 'img2imgValues',
@@ -272,7 +300,7 @@ exports.getImageFields = [
272
300
  type: 'string',
273
301
  default: '',
274
302
  placeholder: 'https://example.com/image.png',
275
- description: 'URL của ảnh gốc dùng làm base',
303
+ description: 'URL ảnh gốc',
276
304
  },
277
305
  {
278
306
  displayName: 'Denoising Strength',
@@ -284,7 +312,7 @@ exports.getImageFields = [
284
312
  numberPrecision: 2,
285
313
  },
286
314
  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)',
315
+ description: 'Mức độ thay đổi (0-1)',
288
316
  },
289
317
  ],
290
318
  },
@@ -293,23 +321,8 @@ exports.getImageFields = [
293
321
  ],
294
322
  },
295
323
  // ═══════════════════════════════════════════════════════════
296
- // LIST IMAGES OPERATION
324
+ // LIST IMAGES
297
325
  // ═══════════════════════════════════════════════════════════
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
326
  {
314
327
  displayName: 'Return All',
315
328
  name: 'returnAll',
@@ -339,17 +352,84 @@ exports.getImageFields = [
339
352
  description: 'Max number of results to return',
340
353
  },
341
354
  {
342
- displayName: 'Page',
343
- name: 'page',
344
- type: 'number',
345
- typeOptions: { minValue: 1 },
355
+ displayName: 'Filters',
356
+ name: 'filters',
357
+ type: 'collection',
358
+ placeholder: 'Add Filter',
359
+ default: {},
346
360
  displayOptions: {
347
361
  show: {
348
362
  resource: ['image'],
349
363
  operation: ['listImages'],
350
364
  },
351
365
  },
352
- default: 1,
353
- description: 'Số trang để fetch (bắt đầu từ 1)',
366
+ options: [
367
+ {
368
+ displayName: 'Batch ID',
369
+ name: 'batchId',
370
+ type: 'string',
371
+ default: '',
372
+ placeholder: '1997744',
373
+ description: 'Filter by batch ID',
374
+ },
375
+ {
376
+ displayName: 'Folder Name or ID',
377
+ name: 'folderId',
378
+ type: 'options',
379
+ typeOptions: {
380
+ loadOptionsMethod: 'getFolders',
381
+ },
382
+ default: '',
383
+ description: 'Filter by folder. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
384
+ },
385
+ {
386
+ displayName: 'Model Name or ID',
387
+ name: 'model',
388
+ type: 'options',
389
+ typeOptions: {
390
+ loadOptionsMethod: 'getModels',
391
+ },
392
+ default: '',
393
+ description: 'Filter by model. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
394
+ },
395
+ ],
396
+ },
397
+ // ═══════════════════════════════════════════════════════════
398
+ // GET IMAGE
399
+ // ═══════════════════════════════════════════════════════════
400
+ {
401
+ displayName: 'Image ID',
402
+ name: 'imageId',
403
+ type: 'string',
404
+ displayOptions: {
405
+ show: {
406
+ resource: ['image'],
407
+ operation: ['getImage', 'moveImage', 'deleteImage'],
408
+ },
409
+ },
410
+ default: '',
411
+ required: true,
412
+ placeholder: '8870379',
413
+ description: 'ID của ảnh',
414
+ },
415
+ // ═══════════════════════════════════════════════════════════
416
+ // MOVE IMAGE
417
+ // ═══════════════════════════════════════════════════════════
418
+ {
419
+ displayName: 'Target Folder Name or ID',
420
+ name: 'targetFolderId',
421
+ type: 'options',
422
+ typeOptions: {
423
+ loadOptionsMethod: 'getFolders',
424
+ },
425
+ displayOptions: {
426
+ show: {
427
+ resource: ['image'],
428
+ operation: ['moveImage'],
429
+ },
430
+ },
431
+ default: '',
432
+ required: true,
433
+ description: 'Folder đích để move ảnh. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
354
434
  },
355
435
  ];
@@ -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,7 @@ 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("./CharacterDescription"), exports);
19
+ __exportStar(require("./FolderDescription"), exports);
18
20
  __exportStar(require("./ImageDescription"), exports);
19
21
  __exportStar(require("./ToolsDescription"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-supermachine",
3
- "version": "0.1.5",
3
+ "version": "0.3.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",