image-providers.ts 4.7 KB

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