File size: 5,975 Bytes
f56a29b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | /**
* Image Generation Service -- routes to provider adapters
*/
import type {
ImageProviderId,
ImageGenerationConfig,
ImageGenerationOptions,
ImageGenerationResult,
ImageProviderConfig,
} from './types';
import { generateWithSeedream, testSeedreamConnectivity } from './adapters/seedream-adapter';
import {
generateWithOpenAIImage,
testOpenAIImageConnectivity,
} from './adapters/openai-image-adapter';
import { generateWithQwenImage, testQwenImageConnectivity } from './adapters/qwen-image-adapter';
import { generateWithNanoBanana, testNanoBananaConnectivity } from './adapters/nano-banana-adapter';
import {
generateWithMiniMaxImage,
testMiniMaxImageConnectivity,
} from './adapters/minimax-image-adapter';
import { generateWithGrokImage, testGrokImageConnectivity } from './adapters/grok-image-adapter';
export const IMAGE_PROVIDERS: Record<ImageProviderId, ImageProviderConfig> = {
seedream: {
id: 'seedream',
name: 'Seedream',
requiresApiKey: true,
defaultBaseUrl: 'https://ark.cn-beijing.volces.com',
models: [
{ id: 'doubao-seedream-5-0-260128', name: 'Seedream 5.0 Lite' },
{ id: 'doubao-seedream-4-5-251128', name: 'Seedream 4.5' },
{ id: 'doubao-seedream-4-0-250828', name: 'Seedream 4.0' },
{ id: 'doubao-seedream-3-0-t2i-250415', name: 'Seedream 3.0' },
],
supportedAspectRatios: ['16:9', '4:3', '1:1', '9:16'],
},
'openai-image': {
id: 'openai-image',
name: 'OpenAI Image',
requiresApiKey: true,
defaultBaseUrl: 'https://api.openai.com/v1',
models: [
{ id: 'gpt-image-2', name: 'GPT Image 2' },
{ id: 'gpt-image-2-2026-04-21', name: 'GPT Image 2 (2026-04-21)' },
{ id: 'gpt-image-1.5', name: 'GPT Image 1.5' },
{ id: 'gpt-image-1', name: 'GPT Image 1' },
{ id: 'gpt-image-1-mini', name: 'GPT Image 1 Mini' },
{ id: 'chatgpt-image-latest', name: 'ChatGPT Image Latest' },
],
supportedAspectRatios: ['16:9', '4:3', '1:1', '9:16'],
},
'qwen-image': {
id: 'qwen-image',
name: 'Qwen Image',
requiresApiKey: true,
defaultBaseUrl: 'https://dashscope.aliyuncs.com',
models: [
{ id: 'qwen-image-2.0-pro', name: 'Qwen Image 2.0 Pro' },
{ id: 'qwen-image-2.0-pro-2026-03-03', name: 'Qwen Image 2.0 Pro (2026-03-03)' },
{ id: 'qwen-image-2.0', name: 'Qwen Image 2.0' },
{ id: 'qwen-image-2.0-2026-03-03', name: 'Qwen Image 2.0 (2026-03-03)' },
{ id: 'qwen-image-max', name: 'Qwen Image Max' },
{ id: 'qwen-image-max-2025-12-30', name: 'Qwen Image Max (2025-12-30)' },
{ id: 'qwen-image-plus', name: 'Qwen Image Plus' },
{
id: 'qwen-image-plus-2026-01-09',
name: 'Qwen Image Plus (2026-01-09)',
},
{ id: 'qwen-image', name: 'Qwen Image' },
{ id: 'z-image-turbo', name: 'Z-Image Turbo' },
],
supportedAspectRatios: ['16:9', '4:3', '1:1', '9:16'],
},
'nano-banana': {
id: 'nano-banana',
name: 'Nano Banana (Gemini)',
requiresApiKey: true,
defaultBaseUrl: 'https://generativelanguage.googleapis.com',
models: [
{
id: 'gemini-3.1-flash-image-preview',
name: 'Gemini 3.1 Flash Image (Nano Banana 2)',
},
{
id: 'gemini-3-pro-image-preview',
name: 'Gemini 3 Pro Image (Nano Banana Pro)',
},
{
id: 'gemini-2.5-flash-image',
name: 'Gemini 2.5 Flash Image (Nano Banana)',
},
],
supportedAspectRatios: ['16:9', '4:3', '1:1'],
},
'minimax-image': {
id: 'minimax-image',
name: 'MiniMax Image',
requiresApiKey: true,
defaultBaseUrl: 'https://api.minimaxi.com',
models: [
{ id: 'image-01', name: 'Image 01' },
{ id: 'image-01-live', name: 'Image 01 Live' },
],
supportedAspectRatios: ['16:9', '4:3', '1:1', '9:16'],
},
'grok-image': {
id: 'grok-image',
name: 'Grok Image (xAI)',
requiresApiKey: true,
defaultBaseUrl: 'https://api.x.ai/v1',
models: [
{ id: 'grok-imagine-image', name: 'Grok Imagine Image' },
{ id: 'grok-imagine-image-pro', name: 'Grok Imagine Image Pro' },
],
supportedAspectRatios: ['16:9', '4:3', '1:1', '9:16'],
},
};
export async function testImageConnectivity(
config: ImageGenerationConfig,
): Promise<{ success: boolean; message: string }> {
switch (config.providerId) {
case 'seedream':
return testSeedreamConnectivity(config);
case 'openai-image':
return testOpenAIImageConnectivity(config);
case 'qwen-image':
return testQwenImageConnectivity(config);
case 'nano-banana':
return testNanoBananaConnectivity(config);
case 'minimax-image':
return testMiniMaxImageConnectivity(config);
case 'grok-image':
return testGrokImageConnectivity(config);
default:
return {
success: false,
message: `Unsupported image provider: ${config.providerId}`,
};
}
}
export async function generateImage(
config: ImageGenerationConfig,
options: ImageGenerationOptions,
): Promise<ImageGenerationResult> {
switch (config.providerId) {
case 'seedream':
return generateWithSeedream(config, options);
case 'openai-image':
return generateWithOpenAIImage(config, options);
case 'qwen-image':
return generateWithQwenImage(config, options);
case 'nano-banana':
return generateWithNanoBanana(config, options);
case 'minimax-image':
return generateWithMiniMaxImage(config, options);
case 'grok-image':
return generateWithGrokImage(config, options);
default:
throw new Error(`Unsupported image provider: ${config.providerId}`);
}
}
export function aspectRatioToDimensions(
ratio: string,
maxWidth = 1024,
): { width: number; height: number } {
const [w, h] = ratio.split(':').map(Number);
if (!w || !h) return { width: maxWidth, height: Math.round((maxWidth * 9) / 16) };
return { width: maxWidth, height: Math.round((maxWidth * h) / w) };
}
|