genmix 1.2.2 → 1.2.4
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.
- package/generators/FalGenerator.js +42 -10
- package/generators/GeminiGenerator.js +44 -12
- package/package.json +4 -2
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const axios = require('axios');
|
|
2
1
|
const BaseGenerator = require('./BaseGenerator');
|
|
3
2
|
const fs = require('fs');
|
|
4
3
|
const path = require('path');
|
|
@@ -280,14 +279,26 @@ class FalGenerator extends BaseGenerator {
|
|
|
280
279
|
payload.image_urls = imageUrls;
|
|
281
280
|
|
|
282
281
|
try {
|
|
283
|
-
const response = await
|
|
282
|
+
const response = await fetch(this.apiUrl, {
|
|
283
|
+
method: 'POST',
|
|
284
284
|
headers: {
|
|
285
285
|
Authorization: `Key ${this.apiKey}`,
|
|
286
286
|
'Content-Type': 'application/json'
|
|
287
|
-
}
|
|
287
|
+
},
|
|
288
|
+
body: JSON.stringify(payload)
|
|
288
289
|
});
|
|
289
290
|
|
|
290
|
-
const
|
|
291
|
+
const responseBody = await this._parseResponseBody(response);
|
|
292
|
+
if (!response.ok) {
|
|
293
|
+
const apiError = responseBody && typeof responseBody === 'object' ? responseBody : null;
|
|
294
|
+
const message = apiError?.detail
|
|
295
|
+
|| apiError?.error
|
|
296
|
+
|| (typeof responseBody === 'string' ? responseBody : null)
|
|
297
|
+
|| `HTTP ${response.status} ${response.statusText}`;
|
|
298
|
+
throw new Error(message);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const result = await this.processResponse(responseBody);
|
|
291
302
|
this.lastGeneration = {
|
|
292
303
|
prompt: String(prompt).trim(),
|
|
293
304
|
images: result.images,
|
|
@@ -300,9 +311,25 @@ class FalGenerator extends BaseGenerator {
|
|
|
300
311
|
this.references = [];
|
|
301
312
|
return result;
|
|
302
313
|
} catch (error) {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
314
|
+
throw new Error(`Fal API Error: ${error.message}`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async _parseResponseBody(response) {
|
|
319
|
+
const contentType = response.headers.get('content-type') || '';
|
|
320
|
+
if (contentType.includes('application/json')) {
|
|
321
|
+
return response.json();
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const textBody = await response.text();
|
|
325
|
+
if (!textBody) {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
return JSON.parse(textBody);
|
|
331
|
+
} catch (error) {
|
|
332
|
+
return textBody;
|
|
306
333
|
}
|
|
307
334
|
}
|
|
308
335
|
|
|
@@ -315,9 +342,14 @@ class FalGenerator extends BaseGenerator {
|
|
|
315
342
|
continue;
|
|
316
343
|
}
|
|
317
344
|
|
|
318
|
-
const mediaResponse = await
|
|
319
|
-
|
|
320
|
-
|
|
345
|
+
const mediaResponse = await fetch(entry.url);
|
|
346
|
+
if (!mediaResponse.ok) {
|
|
347
|
+
throw new Error(`Failed to download generated media: HTTP ${mediaResponse.status} ${mediaResponse.statusText}`);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const binaryData = await mediaResponse.arrayBuffer();
|
|
351
|
+
const contentType = entry.content_type || mediaResponse.headers.get('content-type') || 'image/png';
|
|
352
|
+
const base64 = Buffer.from(binaryData).toString('base64');
|
|
321
353
|
images.push(`data:${contentType};base64,${base64}`);
|
|
322
354
|
}
|
|
323
355
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const axios = require('axios');
|
|
2
1
|
const BaseGenerator = require('./BaseGenerator');
|
|
3
2
|
const fs = require('fs');
|
|
4
3
|
const path = require('path');
|
|
@@ -183,9 +182,14 @@ class GeminiGenerator extends BaseGenerator {
|
|
|
183
182
|
} else if (imageInput.startsWith('http://') || imageInput.startsWith('https://')) {
|
|
184
183
|
// It's a URL - download it
|
|
185
184
|
try {
|
|
186
|
-
const response = await
|
|
187
|
-
|
|
188
|
-
|
|
185
|
+
const response = await fetch(imageInput);
|
|
186
|
+
if (!response.ok) {
|
|
187
|
+
throw new Error(`HTTP ${response.status} ${response.statusText}`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const binaryData = await response.arrayBuffer();
|
|
191
|
+
base64Data = Buffer.from(binaryData).toString('base64');
|
|
192
|
+
mimeType = response.headers.get('content-type') || 'image/png';
|
|
189
193
|
} catch (error) {
|
|
190
194
|
throw new Error(`Failed to download reference image from URL: ${error.message}`);
|
|
191
195
|
}
|
|
@@ -405,20 +409,48 @@ class GeminiGenerator extends BaseGenerator {
|
|
|
405
409
|
// data.tools = ... (removed)
|
|
406
410
|
|
|
407
411
|
try {
|
|
408
|
-
const response = await
|
|
412
|
+
const response = await fetch(url, {
|
|
413
|
+
method: 'POST',
|
|
409
414
|
headers: {
|
|
410
415
|
'Content-Type': 'application/json',
|
|
411
416
|
},
|
|
417
|
+
body: JSON.stringify(data),
|
|
412
418
|
});
|
|
413
419
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
+
const responseBody = await this._parseResponseBody(response);
|
|
421
|
+
if (!response.ok) {
|
|
422
|
+
const apiError = responseBody && typeof responseBody === 'object' ? responseBody : null;
|
|
423
|
+
const errorMessage = apiError?.error?.message
|
|
424
|
+
|| (typeof responseBody === 'string' ? responseBody : null)
|
|
425
|
+
|| `HTTP ${response.status} ${response.statusText}`;
|
|
426
|
+
|
|
427
|
+
if (apiError) {
|
|
428
|
+
console.error("API Error Details:", JSON.stringify(apiError, null, 2));
|
|
429
|
+
}
|
|
430
|
+
throw new Error(errorMessage);
|
|
420
431
|
}
|
|
421
|
-
|
|
432
|
+
|
|
433
|
+
return this.processResponse(responseBody);
|
|
434
|
+
} catch (error) {
|
|
435
|
+
throw new Error(`Gemini API Error: ${error.message}`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
async _parseResponseBody(response) {
|
|
440
|
+
const contentType = response.headers.get('content-type') || '';
|
|
441
|
+
if (contentType.includes('application/json')) {
|
|
442
|
+
return response.json();
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const textBody = await response.text();
|
|
446
|
+
if (!textBody) {
|
|
447
|
+
return null;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
try {
|
|
451
|
+
return JSON.parse(textBody);
|
|
452
|
+
} catch (error) {
|
|
453
|
+
return textBody;
|
|
422
454
|
}
|
|
423
455
|
}
|
|
424
456
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genmix",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"description": "AI-powered image generator supporting Google Gemini and Fal Nano Banana 2.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Martin Clasen",
|
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
],
|
|
26
26
|
"type": "commonjs",
|
|
27
27
|
"main": "index.js",
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18"
|
|
30
|
+
},
|
|
28
31
|
"bin": {
|
|
29
32
|
"genmix": "./cli.js"
|
|
30
33
|
},
|
|
@@ -32,7 +35,6 @@
|
|
|
32
35
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
33
36
|
},
|
|
34
37
|
"dependencies": {
|
|
35
|
-
"axios": "^1.13.6",
|
|
36
38
|
"hash-factory": "^1.1.2",
|
|
37
39
|
"sharp": "^0.33.5"
|
|
38
40
|
}
|