myaidev-method 0.2.18 → 0.2.22

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.
Files changed (31) hide show
  1. package/.claude/mcp/sparc-orchestrator-server.js +0 -0
  2. package/.claude/mcp/wordpress-server.js +0 -0
  3. package/CHANGELOG.md +145 -0
  4. package/README.md +205 -13
  5. package/TECHNICAL_ARCHITECTURE.md +64 -2
  6. package/bin/cli.js +169 -2
  7. package/dist/mcp/mcp-config.json +138 -1
  8. package/dist/mcp/openstack-server.js +1607 -0
  9. package/package.json +2 -2
  10. package/src/config/workflows.js +532 -0
  11. package/src/lib/payloadcms-utils.js +343 -10
  12. package/src/lib/visual-generation-utils.js +445 -294
  13. package/src/lib/workflow-installer.js +512 -0
  14. package/src/libs/security/authorization-checker.js +606 -0
  15. package/src/mcp/openstack-server.js +1607 -0
  16. package/src/scripts/openstack-setup.sh +110 -0
  17. package/src/scripts/security/environment-detect.js +425 -0
  18. package/src/templates/claude/agents/openstack-vm-manager.md +281 -0
  19. package/src/templates/claude/agents/osint-researcher.md +1075 -0
  20. package/src/templates/claude/agents/penetration-tester.md +908 -0
  21. package/src/templates/claude/agents/security-auditor.md +244 -0
  22. package/src/templates/claude/agents/security-setup.md +1094 -0
  23. package/src/templates/claude/agents/webapp-security-tester.md +581 -0
  24. package/src/templates/claude/commands/myai-configure.md +84 -0
  25. package/src/templates/claude/commands/myai-openstack.md +229 -0
  26. package/src/templates/claude/commands/sc:security-exploit.md +464 -0
  27. package/src/templates/claude/commands/sc:security-recon.md +281 -0
  28. package/src/templates/claude/commands/sc:security-report.md +756 -0
  29. package/src/templates/claude/commands/sc:security-scan.md +441 -0
  30. package/src/templates/claude/commands/sc:security-setup.md +501 -0
  31. package/src/templates/claude/mcp_config.json +44 -0
@@ -2,10 +2,17 @@
2
2
  * Visual Content Generation Utilities
3
3
  *
4
4
  * Provides image and video generation capabilities using:
5
- * - Google Gemini 2.5 Flash Image ("Nano Banana")
6
- * - Google Imagen 3
7
- * - OpenAI GPT-Image-1 (GPT-4o Image Generation)
8
- * - Google Veo 2 (video)
5
+ *
6
+ * RECOMMENDED SOTA MODELS:
7
+ * - Google Gemini 3.0 Pro Image ("Nano Banana") - fast, cost-effective
8
+ * - OpenAI GPT Image 1.5 - state-of-the-art quality, best text rendering
9
+ *
10
+ * ADDITIONAL MODELS:
11
+ * - Google Imagen 3 - premium quality via Gemini API
12
+ * - Black Forest Labs FLUX 2 (pro, flex, dev) - excellent quality
13
+ * - Google Veo 3 - latest video generation
14
+ *
15
+ * Authentication: Uses simple API keys (GEMINI_API_KEY, OPENAI_API_KEY, FAL_KEY)
9
16
  *
10
17
  * Platform support: Claude Code, Gemini CLI, Codex CLI
11
18
  *
@@ -16,92 +23,91 @@ import fetch from 'node-fetch';
16
23
  import fs from 'fs-extra';
17
24
  import path from 'path';
18
25
  import dotenv from 'dotenv';
19
- import { GoogleAuth } from 'google-auth-library';
20
26
 
21
27
  dotenv.config();
22
28
 
23
29
  // API Configuration
24
- const GOOGLE_API_BASE = 'https://generativelanguage.googleapis.com/v1beta';
30
+ const GEMINI_API_BASE = 'https://generativelanguage.googleapis.com/v1beta';
25
31
  const OPENAI_API_BASE = 'https://api.openai.com/v1';
26
32
 
27
- /**
28
- * Get OAuth2 access token for Vertex AI
29
- * Uses Google Application Default Credentials (ADC)
30
- *
31
- * @returns {Promise<string>} OAuth2 access token
32
- * @throws {Error} If authentication fails
33
- */
34
- async function getVertexAIToken() {
35
- try {
36
- const auth = new GoogleAuth({
37
- scopes: ['https://www.googleapis.com/auth/cloud-platform']
38
- });
39
-
40
- const client = await auth.getClient();
41
- const tokenResponse = await client.getAccessToken();
33
+ // Gemini Models for image generation
34
+ const GEMINI_IMAGE_MODEL = 'gemini-3-pro-image-preview'; // Gemini 3.0 "Nano Banana" preview
35
+ const GEMINI_IMAGEN_MODEL = 'imagen-3.0-generate-002'; // Imagen via Gemini API
42
36
 
43
- if (!tokenResponse.token) {
44
- throw new Error('Failed to obtain access token');
45
- }
37
+ // OpenAI GPT Image Models (SOTA)
38
+ const OPENAI_IMAGE_MODELS = {
39
+ 'gpt-image-1.5': 'gpt-image-1.5', // State-of-the-art (recommended)
40
+ 'gpt-image-1': 'gpt-image-1', // Main model
41
+ 'gpt-image-1-mini': 'gpt-image-1-mini' // Cost-effective option
42
+ };
46
43
 
47
- return tokenResponse.token;
48
- } catch (error) {
49
- throw new Error(`Vertex AI authentication failed: ${error.message}`);
50
- }
51
- }
44
+ // FLUX 2 Models (via Fal.ai or BFL API)
45
+ const FLUX2_MODELS = {
46
+ 'flux2-pro': 'fal-ai/flux-2/pro', // State-of-the-art quality, fastest, lowest cost
47
+ 'flux2-flex': 'fal-ai/flux-2/flex', // Developer-controlled parameters
48
+ 'flux2-dev': 'fal-ai/flux-2/dev', // 32B open-weight model
49
+ // Legacy FLUX 1.x models (still available)
50
+ 'flux-pro': 'fal-ai/flux-pro/v1.1-ultra',
51
+ 'flux-dev': 'fal-ai/flux/dev'
52
+ };
52
53
 
53
- // Pricing (USD per image/video) - GPT-Image-1 pricing
54
+ // Pricing (USD per image/video)
54
55
  const PRICING = {
55
- gemini: 0.02, // Gemini 2.5 Flash Image (direct Google API)
56
- imagen: 0.03, // Imagen 3 (direct Google API)
57
- dalle_low: 0.02, // GPT-Image-1 low quality
58
- dalle_medium: 0.07, // GPT-Image-1 medium quality
59
- dalle_standard: 0.07, // GPT-Image-1 medium quality (alias for standard)
60
- dalle_high: 0.19, // GPT-Image-1 high quality
61
- dalle_hd: 0.19, // GPT-Image-1 high quality (alias for hd)
62
- veo: 0.10, // Veo 2 (estimated per video)
63
- // Fal.ai pricing
64
- flux_pro: 0.06, // FLUX Pro v1.1 Ultra
65
- flux_dev: 0.025, // FLUX Dev (per megapixel)
66
- veo3: 0.40, // Veo 3 (per second)
67
- gemini_fal: 0.0398, // Gemini via fal.ai (fallback)
68
- imagen_fal: 0.05 // Imagen via fal.ai (fallback)
56
+ // SOTA Models (Recommended)
57
+ gemini: 0.02, // Gemini 3.0 Pro Image "Nano Banana" - fast, cheap
58
+ 'gpt-image-1.5': 0.19, // OpenAI GPT Image 1.5 - SOTA quality (high quality)
59
+ 'gpt-image-1.5-medium': 0.07, // GPT Image 1.5 medium quality
60
+ 'gpt-image-1.5-low': 0.02, // GPT Image 1.5 low quality
61
+ 'gpt-image-1': 0.19, // OpenAI GPT Image 1 (high quality)
62
+ 'gpt-image-1-mini': 0.02, // OpenAI GPT Image 1 Mini - budget option
63
+ // Additional Models
64
+ imagen: 0.03, // Imagen 3 (Gemini API)
65
+ // FLUX 2 pricing
66
+ flux2_pro: 0.05, // FLUX 2 Pro
67
+ flux2_flex: 0.04, // FLUX 2 Flex
68
+ flux2_dev: 0.025, // FLUX 2 Dev
69
+ // Legacy FLUX 1.x
70
+ flux_pro: 0.06, // FLUX Pro v1.1 Ultra
71
+ flux_dev: 0.025, // FLUX Dev (per megapixel)
72
+ // Video
73
+ veo3: 0.40 // Veo 3 (per second)
69
74
  };
70
75
 
71
76
  /**
72
77
  * Validate that required API keys are configured
73
78
  *
74
79
  * @returns {Object} Validation results
75
- * @returns {boolean} hasGoogle - Google API key is configured
76
- * @returns {boolean} hasOpenAI - OpenAI API key is configured
77
- * @returns {boolean} hasAny - At least one API key is configured
78
- * @returns {Array<string>} availableServices - List of available services
79
80
  */
80
81
  export function validateAPIKeys() {
81
- const googleKey = process.env.GOOGLE_API_KEY;
82
+ // Support both GEMINI_API_KEY (preferred) and GOOGLE_API_KEY (legacy)
83
+ const geminiKey = process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY;
82
84
  const openaiKey = process.env.OPENAI_API_KEY;
83
85
  const falKey = process.env.FAL_KEY;
86
+ const bflKey = process.env.BFL_API_KEY; // Black Forest Labs direct API
84
87
 
85
- const hasGoogle = !!(googleKey && googleKey.length > 20);
88
+ const hasGemini = !!(geminiKey && geminiKey.length > 20);
86
89
  const hasOpenAI = !!(openaiKey && openaiKey.length > 20);
87
90
  const hasFal = !!(falKey && falKey.length > 20);
91
+ const hasBFL = !!(bflKey && bflKey.length > 20);
88
92
 
89
93
  const availableServices = [];
90
- if (hasGoogle) {
91
- availableServices.push('gemini', 'imagen', 'veo');
94
+ if (hasGemini) {
95
+ availableServices.push('gemini', 'imagen');
92
96
  }
93
97
  if (hasOpenAI) {
94
- availableServices.push('dalle');
98
+ availableServices.push('gpt-image-1.5', 'gpt-image-1', 'gpt-image-1-mini');
95
99
  }
96
- if (hasFal) {
97
- availableServices.push('flux', 'flux-pro', 'flux-dev', 'veo3');
100
+ if (hasFal || hasBFL) {
101
+ availableServices.push('flux2-pro', 'flux2-flex', 'flux2-dev', 'flux-pro', 'flux-dev', 'veo3');
98
102
  }
99
103
 
100
104
  return {
101
- hasGoogle,
105
+ hasGemini,
106
+ hasGoogle: hasGemini, // Legacy compatibility
102
107
  hasOpenAI,
103
108
  hasFal,
104
- hasAny: hasGoogle || hasOpenAI || hasFal,
109
+ hasBFL,
110
+ hasAny: hasGemini || hasOpenAI || hasFal || hasBFL,
105
111
  availableServices
106
112
  };
107
113
  }
@@ -109,14 +115,12 @@ export function validateAPIKeys() {
109
115
  /**
110
116
  * Estimate cost for image/video generation
111
117
  *
112
- * @param {string} service - Service name (gemini, imagen, dalle, veo)
118
+ * @param {string} service - Service name
113
119
  * @param {Object} options - Generation options
114
- * @param {string} options.quality - Quality level (standard, hd)
115
- * @param {string} options.size - Image size
116
120
  * @returns {number} Estimated cost in USD
117
121
  */
118
122
  export function estimateCost(service, options = {}) {
119
- const { quality = 'high', size = '1024x1024' } = options;
123
+ const { quality = 'high' } = options;
120
124
 
121
125
  switch (service) {
122
126
  case 'gemini':
@@ -125,19 +129,26 @@ export function estimateCost(service, options = {}) {
125
129
  case 'imagen':
126
130
  return PRICING.imagen;
127
131
 
128
- case 'dalle':
129
- // GPT-Image-1 quality-based pricing
130
- if (quality === 'low') {
131
- return PRICING.dalle_low;
132
- } else if (quality === 'medium' || quality === 'standard') {
133
- return PRICING.dalle_medium;
134
- } else if (quality === 'high' || quality === 'hd') {
135
- return PRICING.dalle_high;
136
- }
137
- return PRICING.dalle_high; // default to high quality
132
+ // OpenAI GPT Image models - cost varies by quality
133
+ case 'gpt-image-1.5':
134
+ if (quality === 'low') return PRICING['gpt-image-1.5-low'];
135
+ if (quality === 'medium') return PRICING['gpt-image-1.5-medium'];
136
+ return PRICING['gpt-image-1.5']; // high quality default
138
137
 
139
- case 'veo':
140
- return PRICING.veo;
138
+ case 'gpt-image-1':
139
+ return PRICING['gpt-image-1'];
140
+
141
+ case 'gpt-image-1-mini':
142
+ return PRICING['gpt-image-1-mini'];
143
+
144
+ case 'flux2-pro':
145
+ return PRICING.flux2_pro;
146
+
147
+ case 'flux2-flex':
148
+ return PRICING.flux2_flex;
149
+
150
+ case 'flux2-dev':
151
+ return PRICING.flux2_dev;
141
152
 
142
153
  case 'flux':
143
154
  case 'flux-pro':
@@ -166,7 +177,7 @@ export function selectBestService(preferred = 'gemini') {
166
177
  const { availableServices, hasAny } = validateAPIKeys();
167
178
 
168
179
  if (!hasAny) {
169
- throw new Error('No API keys configured. Run /myai-configure visual to set up image generation.');
180
+ throw new Error('No API keys configured. Set GEMINI_API_KEY, OPENAI_API_KEY, or FAL_KEY in your environment.');
170
181
  }
171
182
 
172
183
  // Return preferred service if available
@@ -179,38 +190,44 @@ export function selectBestService(preferred = 'gemini') {
179
190
  }
180
191
 
181
192
  /**
182
- * Generate image using Google Gemini 2.5 Flash Image ("Nano Banana")
183
- * Fast and cost-effective image generation
193
+ * Generate image using Google Gemini API
194
+ * Uses gemini-3-pro-image-preview model ("Nano Banana") with simple API key auth
184
195
  *
185
196
  * @param {string} prompt - Image description
186
197
  * @param {Object} options - Generation options
187
- * @param {number} options.aspectRatio - Aspect ratio (1 for square, 16/9 for wide)
198
+ * @param {string} options.imageSize - Image size (1K, 2K)
188
199
  * @param {number} options.maxRetries - Maximum retry attempts
189
200
  * @returns {Promise<Object>} Generated image data
190
201
  */
191
202
  export async function generateImageGemini(prompt, options = {}) {
192
203
  const {
193
- aspectRatio = 1,
204
+ imageSize = '1K',
194
205
  maxRetries = 3
195
206
  } = options;
196
207
 
197
- const apiKey = process.env.GOOGLE_API_KEY;
208
+ const apiKey = process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY;
198
209
  if (!apiKey) {
199
- throw new Error('GOOGLE_API_KEY not configured');
210
+ throw new Error('GEMINI_API_KEY not configured. Set GEMINI_API_KEY in your environment.');
200
211
  }
201
212
 
202
- const endpoint = `${GOOGLE_API_BASE}/models/gemini-2.0-flash-exp:generateContent`;
213
+ const endpoint = `${GEMINI_API_BASE}/models/${GEMINI_IMAGE_MODEL}:generateContent`;
203
214
 
204
215
  const requestBody = {
205
- contents: [{
206
- parts: [{
207
- text: `Generate an image: ${prompt}\n\nAspect ratio: ${aspectRatio === 16/9 ? '16:9' : '1:1'}\nStyle: Professional, high quality, suitable for article content`
208
- }]
209
- }],
216
+ contents: [
217
+ {
218
+ role: 'user',
219
+ parts: [
220
+ {
221
+ text: prompt
222
+ }
223
+ ]
224
+ }
225
+ ],
210
226
  generationConfig: {
211
- temperature: 0.4,
212
- topP: 0.95,
213
- topK: 40
227
+ responseModalities: ['IMAGE', 'TEXT'],
228
+ imageConfig: {
229
+ image_size: imageSize
230
+ }
214
231
  }
215
232
  };
216
233
 
@@ -232,21 +249,38 @@ export async function generateImageGemini(prompt, options = {}) {
232
249
 
233
250
  const data = await response.json();
234
251
 
235
- // Extract image data from response
236
- if (data.candidates && data.candidates[0]) {
237
- const candidate = data.candidates[0];
238
-
239
- // Gemini returns inline data or content references
240
- if (candidate.content && candidate.content.parts) {
241
- for (const part of candidate.content.parts) {
242
- if (part.inlineData && part.inlineData.data) {
243
- return {
244
- data: part.inlineData.data,
245
- mimeType: part.inlineData.mimeType || 'image/png',
246
- service: 'gemini',
247
- cost: PRICING.gemini
248
- };
249
- }
252
+ // Handle streaming response format (array of candidates)
253
+ const candidates = Array.isArray(data) ? data : (data.candidates || [data]);
254
+
255
+ for (const candidate of candidates) {
256
+ const content = candidate.content || candidate;
257
+ const parts = content.parts || [];
258
+
259
+ for (const part of parts) {
260
+ // Check for inline image data
261
+ if (part.inlineData && part.inlineData.data) {
262
+ return {
263
+ data: part.inlineData.data,
264
+ mimeType: part.inlineData.mimeType || 'image/png',
265
+ service: 'gemini',
266
+ model: GEMINI_IMAGE_MODEL,
267
+ cost: PRICING.gemini
268
+ };
269
+ }
270
+
271
+ // Check for file data reference
272
+ if (part.fileData && part.fileData.fileUri) {
273
+ const imageResponse = await fetch(part.fileData.fileUri);
274
+ const imageBuffer = await imageResponse.arrayBuffer();
275
+ const base64Data = Buffer.from(imageBuffer).toString('base64');
276
+
277
+ return {
278
+ data: base64Data,
279
+ mimeType: part.fileData.mimeType || 'image/png',
280
+ service: 'gemini',
281
+ model: GEMINI_IMAGE_MODEL,
282
+ cost: PRICING.gemini
283
+ };
250
284
  }
251
285
  }
252
286
  }
@@ -258,7 +292,7 @@ export async function generateImageGemini(prompt, options = {}) {
258
292
 
259
293
  if (attempt < maxRetries) {
260
294
  const backoff = Math.pow(2, attempt) * 1000;
261
- console.log(`⚠️ Gemini attempt ${attempt} failed. Retrying in ${backoff/1000}s...`);
295
+ console.log(`⚠️ Gemini attempt ${attempt} failed: ${error.message}. Retrying in ${backoff / 1000}s...`);
262
296
  await sleep(backoff);
263
297
  }
264
298
  }
@@ -268,59 +302,45 @@ export async function generateImageGemini(prompt, options = {}) {
268
302
  }
269
303
 
270
304
  /**
271
- * Generate image using Google Imagen 4 (via Vertex AI)
272
- * Premium quality image generation
273
- *
274
- * Requires Vertex AI setup:
275
- * - GOOGLE_CLOUD_PROJECT_ID environment variable
276
- * - GOOGLE_CLOUD_LOCATION environment variable (default: us-central1)
277
- * - GOOGLE_APPLICATION_CREDENTIALS pointing to service account key JSON
305
+ * Generate image using Google Imagen 3 (via Gemini API)
306
+ * Premium quality image generation with simple API key authentication
278
307
  *
279
308
  * @param {string} prompt - Image description
280
309
  * @param {Object} options - Generation options
281
- * @param {string} options.size - Image size (256x256, 1024x1024)
310
+ * @param {string} options.aspectRatio - Aspect ratio (1:1, 16:9, 9:16, 4:3, 3:4)
311
+ * @param {number} options.numberOfImages - Number of images to generate (1-4)
282
312
  * @param {number} options.maxRetries - Maximum retry attempts
283
313
  * @returns {Promise<Object>} Generated image data
284
314
  */
285
315
  export async function generateImageImagen(prompt, options = {}) {
286
316
  const {
287
- size = '1024x1024',
317
+ aspectRatio = '1:1',
318
+ numberOfImages = 1,
288
319
  maxRetries = 3
289
320
  } = options;
290
321
 
291
- // Vertex AI configuration
292
- const projectId = process.env.GOOGLE_CLOUD_PROJECT_ID;
293
- const location = process.env.GOOGLE_CLOUD_LOCATION || 'us-central1';
294
-
295
- if (!projectId) {
296
- throw new Error('GOOGLE_CLOUD_PROJECT_ID not configured. Set up Vertex AI credentials.');
322
+ const apiKey = process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY;
323
+ if (!apiKey) {
324
+ throw new Error('GEMINI_API_KEY not configured. Set GEMINI_API_KEY in your environment.');
297
325
  }
298
326
 
299
- // Build Vertex AI endpoint
300
- const endpoint = `https://${location}-aiplatform.googleapis.com/v1/projects/${projectId}/locations/${location}/publishers/google/models/imagen-4.0-generate-001:predict`;
327
+ const endpoint = `${GEMINI_API_BASE}/models/${GEMINI_IMAGEN_MODEL}:generateImages`;
301
328
 
302
329
  const requestBody = {
303
- instances: [{
304
- prompt: prompt
305
- }],
306
- parameters: {
307
- sampleCount: 1,
308
- aspectRatio: size === '1024x1024' ? '1:1' : (size.includes('1792') ? '16:9' : '1:1'),
309
- safetyFilterLevel: 'block_some',
310
- personGeneration: 'allow_adult'
330
+ prompt: prompt,
331
+ config: {
332
+ numberOfImages: Math.min(numberOfImages, 4),
333
+ aspectRatio: aspectRatio,
334
+ safetyFilterLevel: 'BLOCK_MEDIUM_AND_ABOVE'
311
335
  }
312
336
  };
313
337
 
314
338
  let lastError;
315
339
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
316
340
  try {
317
- // Get OAuth2 access token
318
- const token = await getVertexAIToken();
319
-
320
- const response = await fetch(endpoint, {
341
+ const response = await fetch(`${endpoint}?key=${apiKey}`, {
321
342
  method: 'POST',
322
343
  headers: {
323
- 'Authorization': `Bearer ${token}`,
324
344
  'Content-Type': 'application/json'
325
345
  },
326
346
  body: JSON.stringify(requestBody)
@@ -333,15 +353,31 @@ export async function generateImageImagen(prompt, options = {}) {
333
353
 
334
354
  const data = await response.json();
335
355
 
336
- if (data.predictions && data.predictions[0]) {
337
- const prediction = data.predictions[0];
356
+ // Imagen returns images array with base64 encoded data
357
+ if (data.generatedImages && data.generatedImages[0]) {
358
+ const image = data.generatedImages[0];
338
359
 
339
- // Imagen 4 returns base64-encoded image in bytesBase64Encoded
340
- if (prediction.bytesBase64Encoded) {
360
+ if (image.image && image.image.imageBytes) {
341
361
  return {
342
- data: prediction.bytesBase64Encoded,
343
- mimeType: prediction.mimeType || 'image/png',
362
+ data: image.image.imageBytes,
363
+ mimeType: 'image/png',
344
364
  service: 'imagen',
365
+ model: GEMINI_IMAGEN_MODEL,
366
+ cost: PRICING.imagen
367
+ };
368
+ }
369
+ }
370
+
371
+ // Alternative response format
372
+ if (data.images && data.images[0]) {
373
+ const image = data.images[0];
374
+
375
+ if (image.bytesBase64Encoded || image.imageBytes) {
376
+ return {
377
+ data: image.bytesBase64Encoded || image.imageBytes,
378
+ mimeType: 'image/png',
379
+ service: 'imagen',
380
+ model: GEMINI_IMAGEN_MODEL,
345
381
  cost: PRICING.imagen
346
382
  };
347
383
  }
@@ -354,7 +390,7 @@ export async function generateImageImagen(prompt, options = {}) {
354
390
 
355
391
  if (attempt < maxRetries) {
356
392
  const backoff = Math.pow(2, attempt) * 1000;
357
- console.log(`⚠️ Imagen attempt ${attempt} failed. Retrying in ${backoff/1000}s...`);
393
+ console.log(`⚠️ Imagen attempt ${attempt} failed: ${error.message}. Retrying in ${backoff / 1000}s...`);
358
394
  await sleep(backoff);
359
395
  }
360
396
  }
@@ -364,42 +400,56 @@ export async function generateImageImagen(prompt, options = {}) {
364
400
  }
365
401
 
366
402
  /**
367
- * Generate image using OpenAI DALL-E 3
368
- * Creative, high-quality image generation
403
+ * Generate image using OpenAI GPT Image API
404
+ * State-of-the-art image generation with best text rendering
405
+ *
406
+ * Features:
407
+ * - Best-in-class text rendering in images
408
+ * - Multiple quality tiers (low, medium, high)
409
+ * - Transparency support (PNG with transparent background)
410
+ * - Multiple output formats (PNG, JPEG, WebP)
369
411
  *
370
412
  * @param {string} prompt - Image description
371
413
  * @param {Object} options - Generation options
372
- * @param {string} options.size - Image size (1024x1024, 1024x1792, 1792x1024)
373
- * @param {string} options.quality - Quality level (standard, hd)
374
- * @param {string} options.style - Style (vivid, natural)
414
+ * @param {string} options.model - Model (gpt-image-1.5, gpt-image-1, gpt-image-1-mini)
415
+ * @param {string} options.size - Image size (1024x1024, 1536x1024, 1024x1536, auto)
416
+ * @param {string} options.quality - Quality level (low, medium, high, auto)
417
+ * @param {string} options.outputFormat - Output format (png, jpeg, webp)
418
+ * @param {string} options.background - Background type (transparent, opaque, auto)
375
419
  * @param {number} options.maxRetries - Maximum retry attempts
376
- * @returns {Promise<Object>} Generated image data with URL
420
+ * @returns {Promise<Object>} Generated image data
377
421
  */
378
- export async function generateImageDALLE(prompt, options = {}) {
422
+ export async function generateImageOpenAI(prompt, options = {}) {
379
423
  const {
424
+ model = 'gpt-image-1.5',
380
425
  size = '1024x1024',
381
- quality = 'high', // low, medium, or high
426
+ quality = 'high',
427
+ outputFormat = 'png',
428
+ background = 'auto',
382
429
  maxRetries = 3
383
430
  } = options;
384
431
 
385
432
  const apiKey = process.env.OPENAI_API_KEY;
386
433
  if (!apiKey) {
387
- throw new Error('OPENAI_API_KEY not configured');
434
+ throw new Error('OPENAI_API_KEY not configured. Get your key from https://platform.openai.com/api-keys');
388
435
  }
389
436
 
390
437
  const endpoint = `${OPENAI_API_BASE}/images/generations`;
391
438
 
392
- // Try GPT-Image-1 first, fall back to DALL-E 3 if not available
393
- const model = 'dall-e-3'; // Will use gpt-image-1 once org is verified
394
-
395
439
  const requestBody = {
396
- model: model,
440
+ model: OPENAI_IMAGE_MODELS[model] || model,
397
441
  prompt: prompt,
398
442
  n: 1,
399
443
  size: size,
400
- ...(model === 'gpt-image-1' ? { quality } : { quality: quality === 'low' ? 'standard' : 'hd' })
444
+ quality: quality,
445
+ output_format: outputFormat
401
446
  };
402
447
 
448
+ // Add background for PNG format (transparency support)
449
+ if (outputFormat === 'png' && background !== 'auto') {
450
+ requestBody.background = background;
451
+ }
452
+
403
453
  let lastError;
404
454
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
405
455
  try {
@@ -413,37 +463,61 @@ export async function generateImageDALLE(prompt, options = {}) {
413
463
  });
414
464
 
415
465
  if (!response.ok) {
416
- const errorData = await response.json();
417
- throw new Error(`DALL-E API error: ${response.status} - ${errorData.error?.message || 'Unknown error'}`);
466
+ const errorText = await response.text();
467
+ let errorMessage = `OpenAI API error: ${response.status}`;
468
+ try {
469
+ const errorData = JSON.parse(errorText);
470
+ errorMessage = errorData.error?.message || errorMessage;
471
+ } catch {
472
+ errorMessage = `${errorMessage} - ${errorText}`;
473
+ }
474
+ throw new Error(errorMessage);
418
475
  }
419
476
 
420
477
  const data = await response.json();
421
478
 
479
+ // OpenAI returns base64-encoded image data
422
480
  if (data.data && data.data[0]) {
423
- const image = data.data[0];
481
+ const imageData = data.data[0];
424
482
 
425
- return {
426
- url: image.url,
427
- revisedPrompt: image.revised_prompt, // DALL-E often revises prompts
428
- mimeType: 'image/png',
429
- service: 'dalle',
430
- cost: estimateCost('dalle', { quality, size })
431
- };
483
+ // Handle base64 response (primary)
484
+ if (imageData.b64_json) {
485
+ return {
486
+ data: imageData.b64_json,
487
+ mimeType: outputFormat === 'jpeg' ? 'image/jpeg' : outputFormat === 'webp' ? 'image/webp' : 'image/png',
488
+ service: 'openai',
489
+ model: model,
490
+ cost: estimateCost(model, { quality }),
491
+ revisedPrompt: imageData.revised_prompt
492
+ };
493
+ }
494
+
495
+ // Handle URL response (fallback)
496
+ if (imageData.url) {
497
+ const imageResponse = await fetch(imageData.url);
498
+ const imageBuffer = await imageResponse.arrayBuffer();
499
+ const base64Data = Buffer.from(imageBuffer).toString('base64');
500
+
501
+ return {
502
+ data: base64Data,
503
+ mimeType: outputFormat === 'jpeg' ? 'image/jpeg' : outputFormat === 'webp' ? 'image/webp' : 'image/png',
504
+ service: 'openai',
505
+ model: model,
506
+ cost: estimateCost(model, { quality }),
507
+ revisedPrompt: imageData.revised_prompt
508
+ };
509
+ }
432
510
  }
433
511
 
434
- throw new Error('No image data in DALL-E response');
512
+ throw new Error('No image data in OpenAI response');
435
513
 
436
514
  } catch (error) {
437
515
  lastError = error;
438
516
 
439
- if (error.message.includes('rate_limit')) {
440
- if (attempt < maxRetries) {
441
- const backoff = Math.pow(2, attempt) * 1000;
442
- console.log(`⚠️ DALL-E rate limited. Retrying in ${backoff/1000}s...`);
443
- await sleep(backoff);
444
- }
445
- } else {
446
- throw error; // Don't retry on other errors
517
+ if (attempt < maxRetries) {
518
+ const backoff = Math.pow(2, attempt) * 1000;
519
+ console.log(`⚠️ OpenAI attempt ${attempt} failed: ${error.message}. Retrying in ${backoff / 1000}s...`);
520
+ await sleep(backoff);
447
521
  }
448
522
  }
449
523
  }
@@ -452,83 +526,110 @@ export async function generateImageDALLE(prompt, options = {}) {
452
526
  }
453
527
 
454
528
  /**
455
- * Generate video using Google Veo 2
456
- * AI video generation from text prompts
529
+ * Generate image using FLUX 2 (via Fal.ai)
530
+ * State-of-the-art image generation from Black Forest Labs
457
531
  *
458
- * @param {string} prompt - Video description
532
+ * Features:
533
+ * - Multi-reference support (up to 10 images)
534
+ * - Enhanced photorealism
535
+ * - Complex typography and UI mockups
536
+ * - Image editing up to 4 megapixels
537
+ *
538
+ * @param {string} prompt - Image description
459
539
  * @param {Object} options - Generation options
460
- * @param {number} options.duration - Video duration in seconds (max 8)
461
- * @param {string} options.aspectRatio - Aspect ratio (16:9, 9:16, 1:1)
540
+ * @param {string} options.model - FLUX 2 model (flux2-pro, flux2-flex, flux2-dev)
541
+ * @param {string} options.size - Image size (square, landscape, portrait)
542
+ * @param {number} options.steps - Number of inference steps (flux2-flex only)
543
+ * @param {number} options.guidance - Guidance scale (flux2-flex only)
544
+ * @param {Array<string>} options.referenceImages - Reference image URLs (up to 10)
462
545
  * @param {number} options.maxRetries - Maximum retry attempts
463
- * @returns {Promise<Object>} Generated video data
546
+ * @returns {Promise<Object>} Generated image data
464
547
  */
465
- export async function generateVideoVeo(prompt, options = {}) {
548
+ export async function generateImageFlux2(prompt, options = {}) {
466
549
  const {
467
- duration = 5,
468
- aspectRatio = '16:9',
550
+ model = 'flux2-pro',
551
+ size = 'square',
552
+ steps = 28,
553
+ guidance = 3.5,
554
+ referenceImages = [],
469
555
  maxRetries = 3
470
556
  } = options;
471
557
 
472
- const apiKey = process.env.GOOGLE_API_KEY;
558
+ const apiKey = process.env.FAL_KEY || process.env.BFL_API_KEY;
473
559
  if (!apiKey) {
474
- throw new Error('GOOGLE_API_KEY not configured');
560
+ throw new Error('FAL_KEY not configured. Get your key from https://fal.ai/dashboard/keys');
475
561
  }
476
562
 
477
- const endpoint = `${GOOGLE_API_BASE}/models/veo-2.0-generate-001:predict`;
563
+ // Import fal.ai client
564
+ const { fal } = await import('@fal-ai/client');
565
+ fal.config({ credentials: apiKey });
478
566
 
479
- const requestBody = {
480
- instances: [{
481
- prompt: prompt
482
- }],
483
- parameters: {
484
- duration: Math.min(duration, 8), // Max 8 seconds
485
- aspectRatio: aspectRatio,
486
- quality: '720p'
487
- }
567
+ // Get endpoint for model
568
+ const endpoint = FLUX2_MODELS[model] || FLUX2_MODELS['flux2-pro'];
569
+
570
+ // Build input based on model capabilities
571
+ const input = {
572
+ prompt: prompt,
573
+ image_size: size === '1024x1024' ? 'square' : size,
574
+ num_images: 1
488
575
  };
489
576
 
577
+ // FLUX 2 Flex supports custom parameters
578
+ if (model === 'flux2-flex') {
579
+ input.num_inference_steps = steps;
580
+ input.guidance_scale = guidance;
581
+ }
582
+
583
+ // Add reference images if provided (FLUX 2 multi-reference feature)
584
+ if (referenceImages.length > 0) {
585
+ input.reference_images = referenceImages.slice(0, 10); // Max 10
586
+ }
587
+
490
588
  let lastError;
491
589
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
492
590
  try {
493
- const response = await fetch(`${endpoint}?key=${apiKey}`, {
494
- method: 'POST',
495
- headers: {
496
- 'Content-Type': 'application/json'
497
- },
498
- body: JSON.stringify(requestBody)
591
+ const result = await fal.subscribe(endpoint, {
592
+ input,
593
+ logs: false
499
594
  });
500
595
 
501
- if (!response.ok) {
502
- const errorText = await response.text();
503
- throw new Error(`Veo API error: ${response.status} - ${errorText}`);
504
- }
596
+ // Extract image from result
597
+ let imageUrl;
598
+ let contentType = 'image/png';
505
599
 
506
- const data = await response.json();
600
+ if (result.data?.images?.[0]) {
601
+ imageUrl = result.data.images[0].url;
602
+ contentType = result.data.images[0].content_type || 'image/png';
603
+ } else if (result.images?.[0]) {
604
+ imageUrl = result.images[0].url;
605
+ contentType = result.images[0].content_type || 'image/png';
606
+ } else if (result.image?.url) {
607
+ imageUrl = result.image.url;
608
+ }
507
609
 
508
- if (data.predictions && data.predictions[0]) {
509
- const prediction = data.predictions[0];
610
+ if (imageUrl) {
611
+ // Fetch and convert to base64
612
+ const imageResponse = await fetch(imageUrl);
613
+ const imageBuffer = await imageResponse.arrayBuffer();
614
+ const base64Data = Buffer.from(imageBuffer).toString('base64');
510
615
 
511
- // Veo returns video data or URL
512
- if (prediction.videoData || prediction.url) {
513
- return {
514
- data: prediction.videoData,
515
- url: prediction.url,
516
- mimeType: 'video/mp4',
517
- service: 'veo',
518
- cost: PRICING.veo,
519
- duration: duration
520
- };
521
- }
616
+ return {
617
+ data: base64Data,
618
+ mimeType: contentType,
619
+ service: 'flux2',
620
+ model: model,
621
+ cost: PRICING[model.replace('-', '_')] || PRICING.flux2_pro
622
+ };
522
623
  }
523
624
 
524
- throw new Error('No video data in Veo response');
625
+ throw new Error('No image data in FLUX 2 response');
525
626
 
526
627
  } catch (error) {
527
628
  lastError = error;
528
629
 
529
630
  if (attempt < maxRetries) {
530
- const backoff = Math.pow(2, attempt) * 2000; // Longer backoff for video
531
- console.log(`⚠️ Veo attempt ${attempt} failed. Retrying in ${backoff/1000}s...`);
631
+ const backoff = Math.pow(2, attempt) * 1000;
632
+ console.log(`⚠️ FLUX 2 attempt ${attempt} failed: ${error.message}. Retrying in ${backoff / 1000}s...`);
532
633
  await sleep(backoff);
533
634
  }
534
635
  }
@@ -538,12 +639,12 @@ export async function generateVideoVeo(prompt, options = {}) {
538
639
  }
539
640
 
540
641
  /**
541
- * Generate image using Fal.ai
542
- * Access to FLUX and other premium models
642
+ * Generate image using legacy FLUX 1.x (via Fal.ai)
643
+ * Still available for backwards compatibility
543
644
  *
544
645
  * @param {string} prompt - Image description
545
646
  * @param {Object} options - Generation options
546
- * @param {string} options.model - Fal.ai model (flux-pro, flux-dev, nano-banana, imagen-3-fast)
647
+ * @param {string} options.model - FLUX model (flux-pro, flux-dev)
547
648
  * @param {string} options.size - Image size
548
649
  * @param {number} options.maxRetries - Maximum retry attempts
549
650
  * @returns {Promise<Object>} Generated image data
@@ -560,21 +661,10 @@ export async function generateImageFal(prompt, options = {}) {
560
661
  throw new Error('FAL_KEY not configured. Get your key from https://fal.ai/dashboard/keys');
561
662
  }
562
663
 
563
- // Import fal.ai client
564
664
  const { fal } = await import('@fal-ai/client');
565
-
566
- // Configure credentials
567
665
  fal.config({ credentials: apiKey });
568
666
 
569
- // Map model names to fal.ai endpoints
570
- const modelMap = {
571
- 'flux-pro': 'fal-ai/flux-pro/v1.1-ultra',
572
- 'flux-dev': 'fal-ai/flux/dev',
573
- 'nano-banana': 'fal-ai/nano-banana',
574
- 'imagen-3-fast': 'fal-ai/fast-imagen'
575
- };
576
-
577
- const endpoint = modelMap[model] || modelMap['flux-pro'];
667
+ const endpoint = FLUX2_MODELS[model] || FLUX2_MODELS['flux-pro'];
578
668
 
579
669
  let lastError;
580
670
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
@@ -588,26 +678,20 @@ export async function generateImageFal(prompt, options = {}) {
588
678
  logs: false
589
679
  });
590
680
 
591
- // Fal.ai can return images in different formats
592
681
  let imageUrl;
593
682
  let contentType = 'image/png';
594
683
 
595
- if (result.data && result.data.images && result.data.images[0]) {
684
+ if (result.data?.images?.[0]) {
596
685
  imageUrl = result.data.images[0].url;
597
686
  contentType = result.data.images[0].content_type || 'image/png';
598
- } else if (result.images && result.images[0]) {
687
+ } else if (result.images?.[0]) {
599
688
  imageUrl = result.images[0].url;
600
689
  contentType = result.images[0].content_type || 'image/png';
601
- } else if (result.image && result.image.url) {
690
+ } else if (result.image?.url) {
602
691
  imageUrl = result.image.url;
603
- } else if (result.data && result.data[0] && result.data[0].url) {
604
- imageUrl = result.data[0].url;
605
- } else if (typeof result === 'string') {
606
- imageUrl = result;
607
692
  }
608
693
 
609
694
  if (imageUrl) {
610
- // Fal.ai returns URL, need to fetch and convert to base64
611
695
  const imageResponse = await fetch(imageUrl);
612
696
  const imageBuffer = await imageResponse.arrayBuffer();
613
697
  const base64Data = Buffer.from(imageBuffer).toString('base64');
@@ -617,7 +701,7 @@ export async function generateImageFal(prompt, options = {}) {
617
701
  mimeType: contentType,
618
702
  service: 'fal',
619
703
  model: model,
620
- cost: PRICING[`${model.replace('-', '_')}`] || PRICING.flux_pro
704
+ cost: PRICING[model.replace('-', '_')] || PRICING.flux_pro
621
705
  };
622
706
  }
623
707
 
@@ -628,7 +712,7 @@ export async function generateImageFal(prompt, options = {}) {
628
712
 
629
713
  if (attempt < maxRetries) {
630
714
  const backoff = Math.pow(2, attempt) * 1000;
631
- console.log(`⚠️ Fal.ai attempt ${attempt} failed. Retrying in ${backoff/1000}s...`);
715
+ console.log(`⚠️ Fal.ai attempt ${attempt} failed: ${error.message}. Retrying in ${backoff / 1000}s...`);
632
716
  await sleep(backoff);
633
717
  }
634
718
  }
@@ -638,8 +722,8 @@ export async function generateImageFal(prompt, options = {}) {
638
722
  }
639
723
 
640
724
  /**
641
- * Generate video using Fal.ai (Veo 3)
642
- * Latest video generation models
725
+ * Generate video using Veo 3 (via Fal.ai)
726
+ * Latest video generation with outstanding quality
643
727
  *
644
728
  * @param {string} prompt - Video description
645
729
  * @param {Object} options - Generation options
@@ -649,7 +733,7 @@ export async function generateImageFal(prompt, options = {}) {
649
733
  * @param {number} options.maxRetries - Maximum retry attempts
650
734
  * @returns {Promise<Object>} Generated video data
651
735
  */
652
- export async function generateVideoFal(prompt, options = {}) {
736
+ export async function generateVideoVeo3(prompt, options = {}) {
653
737
  const {
654
738
  model = 'veo3',
655
739
  duration = 5,
@@ -662,10 +746,7 @@ export async function generateVideoFal(prompt, options = {}) {
662
746
  throw new Error('FAL_KEY not configured. Get your key from https://fal.ai/dashboard/keys');
663
747
  }
664
748
 
665
- // Import fal.ai client
666
749
  const { fal } = await import('@fal-ai/client');
667
-
668
- // Configure credentials
669
750
  fal.config({ credentials: apiKey });
670
751
 
671
752
  const endpoint = model === 'veo3-fast' ? 'fal-ai/veo3-fast' : 'fal-ai/veo3';
@@ -682,29 +763,30 @@ export async function generateVideoFal(prompt, options = {}) {
682
763
  logs: false
683
764
  });
684
765
 
685
- if (result.video && result.video.url) {
686
- // Fal.ai returns video URL
766
+ if (result.video?.url) {
687
767
  const videoResponse = await fetch(result.video.url);
688
768
  const videoBuffer = await videoResponse.arrayBuffer();
689
769
  const base64Data = Buffer.from(videoBuffer).toString('base64');
690
770
 
691
771
  return {
692
772
  data: base64Data,
773
+ url: result.video.url,
693
774
  mimeType: 'video/mp4',
694
- service: 'fal',
775
+ service: 'veo3',
695
776
  model: model,
696
- cost: PRICING.veo3 * duration
777
+ cost: PRICING.veo3 * duration,
778
+ duration: duration
697
779
  };
698
780
  }
699
781
 
700
- throw new Error('No video data in Fal.ai response');
782
+ throw new Error('No video data in Veo 3 response');
701
783
 
702
784
  } catch (error) {
703
785
  lastError = error;
704
786
 
705
787
  if (attempt < maxRetries) {
706
788
  const backoff = Math.pow(2, attempt) * 1000;
707
- console.log(`⚠️ Fal.ai video attempt ${attempt} failed. Retrying in ${backoff/1000}s...`);
789
+ console.log(`⚠️ Veo 3 attempt ${attempt} failed: ${error.message}. Retrying in ${backoff / 1000}s...`);
708
790
  await sleep(backoff);
709
791
  }
710
792
  }
@@ -736,7 +818,7 @@ export async function downloadImage(url) {
736
818
  *
737
819
  * @param {string} prompt - Image description
738
820
  * @param {Object} options - Generation options
739
- * @param {string} options.preferredService - Preferred service (gemini, imagen, dalle)
821
+ * @param {string} options.preferredService - Preferred service
740
822
  * @param {string} options.type - Image type for optimization (hero, illustration, diagram)
741
823
  * @returns {Promise<Object>} Generated image data with buffer
742
824
  */
@@ -763,8 +845,17 @@ export async function generateImage(prompt, options = {}) {
763
845
  result = await generateImageImagen(enhancedPrompt, serviceOptions);
764
846
  break;
765
847
 
766
- case 'dalle':
767
- result = await generateImageDALLE(enhancedPrompt, serviceOptions);
848
+ // OpenAI GPT Image models (SOTA)
849
+ case 'gpt-image-1.5':
850
+ case 'gpt-image-1':
851
+ case 'gpt-image-1-mini':
852
+ result = await generateImageOpenAI(enhancedPrompt, { ...serviceOptions, model: service });
853
+ break;
854
+
855
+ case 'flux2-pro':
856
+ case 'flux2-flex':
857
+ case 'flux2-dev':
858
+ result = await generateImageFlux2(enhancedPrompt, { ...serviceOptions, model: service });
768
859
  break;
769
860
 
770
861
  case 'flux':
@@ -780,10 +871,8 @@ export async function generateImage(prompt, options = {}) {
780
871
  // Convert to buffer
781
872
  let buffer;
782
873
  if (result.data) {
783
- // Base64 encoded data
784
874
  buffer = Buffer.from(result.data, 'base64');
785
875
  } else if (result.url) {
786
- // Download from URL
787
876
  buffer = await downloadImage(result.url);
788
877
  } else {
789
878
  throw new Error('No image data or URL in response');
@@ -797,6 +886,21 @@ export async function generateImage(prompt, options = {}) {
797
886
  };
798
887
  }
799
888
 
889
+ /**
890
+ * Generate video using auto-selected service
891
+ *
892
+ * @param {string} prompt - Video description
893
+ * @param {Object} options - Generation options
894
+ * @returns {Promise<Object>} Generated video data
895
+ */
896
+ export async function generateVideo(prompt, options = {}) {
897
+ const { preferredService = 'veo3', ...serviceOptions } = options;
898
+
899
+ console.log(`🎬 Generating video using ${preferredService}...`);
900
+
901
+ return await generateVideoVeo3(prompt, serviceOptions);
902
+ }
903
+
800
904
  /**
801
905
  * Enhance prompt based on image type
802
906
  *
@@ -836,13 +940,14 @@ function sleep(ms) {
836
940
  export function getServiceInfo(service) {
837
941
  const info = {
838
942
  gemini: {
839
- name: 'Gemini 2.5 Flash Image',
943
+ name: 'Gemini 3.0 Pro Image',
840
944
  nickname: 'Nano Banana',
841
945
  speed: 'Fast',
842
946
  cost: '$0.02/image',
843
947
  quality: 'Good',
844
948
  bestFor: 'Quick hero images, high volume',
845
- provider: 'Google AI (Direct)'
949
+ provider: 'Google Gemini API (API Key)',
950
+ model: GEMINI_IMAGE_MODEL
846
951
  },
847
952
  imagen: {
848
953
  name: 'Imagen 3',
@@ -851,51 +956,97 @@ export function getServiceInfo(service) {
851
956
  cost: '$0.03/image',
852
957
  quality: 'Excellent',
853
958
  bestFor: 'Premium hero images, photorealistic',
854
- provider: 'Google Vertex AI (Direct)'
959
+ provider: 'Google Gemini API (API Key)',
960
+ model: GEMINI_IMAGEN_MODEL
855
961
  },
856
- dalle: {
857
- name: 'DALL-E 3',
858
- nickname: 'Creative',
962
+ // OpenAI GPT Image Models (SOTA)
963
+ 'gpt-image-1.5': {
964
+ name: 'GPT Image 1.5',
965
+ nickname: 'State-of-the-Art',
859
966
  speed: 'Medium',
860
- cost: '$0.04-0.12/image',
861
- quality: 'Excellent',
862
- bestFor: 'Creative illustrations, concept art',
863
- provider: 'OpenAI (Direct)'
967
+ cost: '$0.02-$0.19/image',
968
+ quality: 'Outstanding',
969
+ bestFor: 'Best text rendering, highest quality, transparent backgrounds',
970
+ provider: 'OpenAI',
971
+ model: 'gpt-image-1.5',
972
+ features: ['Best-in-class text rendering', 'Transparency support', 'Multiple quality tiers', 'WebP/JPEG/PNG output'],
973
+ qualityTiers: {
974
+ low: '$0.02/image (~272 tokens)',
975
+ medium: '$0.07/image (~1056 tokens)',
976
+ high: '$0.19/image (~4160 tokens)'
977
+ }
864
978
  },
865
- veo: {
866
- name: 'Veo 2',
867
- nickname: 'Video Generation',
868
- speed: 'Slow',
869
- cost: '$0.10/video (estimated)',
979
+ 'gpt-image-1': {
980
+ name: 'GPT Image 1',
981
+ nickname: 'Premium Quality',
982
+ speed: 'Medium',
983
+ cost: '$0.19/image',
984
+ quality: 'Outstanding',
985
+ bestFor: 'High quality images, text rendering',
986
+ provider: 'OpenAI',
987
+ model: 'gpt-image-1',
988
+ features: ['Excellent text rendering', 'Multiple sizes', 'Transparency support']
989
+ },
990
+ 'gpt-image-1-mini': {
991
+ name: 'GPT Image 1 Mini',
992
+ nickname: 'Cost-Effective',
993
+ speed: 'Fast',
994
+ cost: '$0.02/image',
870
995
  quality: 'Good',
871
- bestFor: 'Product demos, animated diagrams',
872
- provider: 'Google AI (Direct)'
996
+ bestFor: 'Quick images, budget-conscious, high volume',
997
+ provider: 'OpenAI',
998
+ model: 'gpt-image-1-mini',
999
+ features: ['Fast generation', 'Low cost', 'Good quality']
873
1000
  },
874
- flux: {
875
- name: 'FLUX Pro v1.1 Ultra',
876
- nickname: 'Premium Artistic',
1001
+ 'flux2-pro': {
1002
+ name: 'FLUX 2 Pro',
1003
+ nickname: 'State-of-the-Art',
1004
+ speed: 'Fast',
1005
+ cost: '$0.05/image',
1006
+ quality: 'Outstanding',
1007
+ bestFor: 'Best quality, fastest generation, lowest cost',
1008
+ provider: 'Black Forest Labs (Fal.ai)',
1009
+ model: 'flux-2/pro',
1010
+ features: ['Multi-reference (up to 10 images)', 'Enhanced photorealism', 'Complex typography', 'UI mockups']
1011
+ },
1012
+ 'flux2-flex': {
1013
+ name: 'FLUX 2 Flex',
1014
+ nickname: 'Developer Control',
877
1015
  speed: 'Medium',
878
- cost: '$0.06/image',
1016
+ cost: '$0.04/image',
879
1017
  quality: 'Outstanding',
880
- bestFor: 'Premium artistic images, highest quality',
881
- provider: 'Fal.ai'
1018
+ bestFor: 'Custom parameters, fine-tuned control',
1019
+ provider: 'Black Forest Labs (Fal.ai)',
1020
+ model: 'flux-2/flex',
1021
+ features: ['Custom inference steps', 'Guidance scale control', 'Developer-friendly']
1022
+ },
1023
+ 'flux2-dev': {
1024
+ name: 'FLUX 2 Dev',
1025
+ nickname: 'Open-Weight',
1026
+ speed: 'Fast',
1027
+ cost: '$0.025/image',
1028
+ quality: 'Excellent',
1029
+ bestFor: 'Developer workflows, local deployment option',
1030
+ provider: 'Black Forest Labs (Fal.ai)',
1031
+ model: 'flux-2/dev',
1032
+ features: ['32B parameters', 'Open-weight model', 'Local deployment available']
882
1033
  },
883
1034
  'flux-pro': {
884
1035
  name: 'FLUX Pro v1.1 Ultra',
885
- nickname: 'Premium Artistic',
1036
+ nickname: 'Legacy Premium',
886
1037
  speed: 'Medium',
887
1038
  cost: '$0.06/image',
888
1039
  quality: 'Outstanding',
889
- bestFor: 'Premium artistic images, highest quality',
1040
+ bestFor: 'Premium artistic images (legacy)',
890
1041
  provider: 'Fal.ai'
891
1042
  },
892
1043
  'flux-dev': {
893
1044
  name: 'FLUX Dev',
894
- nickname: 'Developer Friendly',
1045
+ nickname: 'Legacy Developer',
895
1046
  speed: 'Fast',
896
1047
  cost: '$0.025/MP',
897
1048
  quality: 'Excellent',
898
- bestFor: 'Developer workflows, rapid iteration',
1049
+ bestFor: 'Developer workflows (legacy)',
899
1050
  provider: 'Fal.ai'
900
1051
  },
901
1052
  veo3: {
@@ -905,7 +1056,7 @@ export function getServiceInfo(service) {
905
1056
  cost: '$0.40/second',
906
1057
  quality: 'Outstanding',
907
1058
  bestFor: 'Premium video content, latest features',
908
- provider: 'Fal.ai'
1059
+ provider: 'Google (Fal.ai)'
909
1060
  }
910
1061
  };
911
1062