export interface BananaImageModelPreset { modelId: string; displayName: string; description: string; supportsVision: boolean; supportsImageGen: boolean; capabilities?: Record; defaultParams?: Record; imageGenConfig?: Record; sortOrder: number; } export const BANANAIMAGE_BASE_URL = "https://bananaimage.aigenmedia.art"; const BANANAIMAGE_STANDARD_RATIOS = [ "auto", "1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9", ]; const BANANAIMAGE_EXTENDED_RATIOS = [ "auto", "1:1", "1:4", "1:8", "2:3", "3:2", "3:4", "4:1", "4:3", "4:5", "5:4", "8:1", "9:16", "16:9", "21:9", ]; const BANANAIMAGE_GPT_IMAGE_2_RATIOS = [ "auto", "1:1", "4:5", "5:4", "3:4", "4:3", "2:3", "3:2", "9:16", "16:9", "1:2", "2:1", "9:21", "21:9", ]; const BANANAIMAGE_IMAGE_SIZES = ["1K", "2K", "4K"]; const BANANAIMAGE_IMAGE_CONFIG = { maxImages: 1, supportsSize: true, supports1K: true, supports2K: true, supports4K: true, supportsPromptExtend: false, supportsNegativePrompt: false, supportsWatermark: false, supportsSeed: false, maxReferenceImages: 14, supportedImageSizes: BANANAIMAGE_IMAGE_SIZES, enableLoadingPlaceholder: true, loadingColor: "yellow", }; function buildBananaImagePreset(params: { modelId: string; displayName: string; description: string; apiFormat: "bananaimage-gemini" | "bananaimage-gpt-image-2"; supportedAspectRatios: string[]; sortOrder: number; }) { return { modelId: params.modelId, displayName: params.displayName, description: params.description, supportsVision: true, supportsImageGen: true, capabilities: { provider: "bananaimage", apiFormat: params.apiFormat, supportedModes: ["text-to-image", "image-to-image", "reference-images"], supportedAspectRatios: params.supportedAspectRatios, supportedImageSizes: BANANAIMAGE_IMAGE_SIZES, supportsMultiImageReference: true, maxReferenceImages: 14, fourKAllowedRatios: params.apiFormat === "bananaimage-gpt-image-2" ? BANANAIMAGE_GPT_IMAGE_2_RATIOS.filter((ratio) => ratio !== "auto") : undefined, }, defaultParams: { provider: "bananaimage", apiFormat: params.apiFormat, endpoint: params.modelId, imageSize: "2K", aspectRatio: "auto", supportedModes: ["text-to-image", "image-to-image", "reference-images"], }, imageGenConfig: { ...BANANAIMAGE_IMAGE_CONFIG, apiFormat: params.apiFormat, supportedAspectRatios: params.supportedAspectRatios, }, sortOrder: params.sortOrder, } satisfies BananaImageModelPreset; } export const BANANAIMAGE_MODEL_PRESETS: BananaImageModelPreset[] = [ buildBananaImagePreset({ modelId: "gemini-3-pro-image-preview", displayName: "BananaImage Nano Banana Pro", description: "BananaImage Nano Banana Pro。支持文生图、图片编辑、多图参考、比例选择和 1K/2K/4K 输出。", apiFormat: "bananaimage-gemini", supportedAspectRatios: BANANAIMAGE_STANDARD_RATIOS, sortOrder: 10, }), buildBananaImagePreset({ modelId: "gemini-3.1-flash-image-preview", displayName: "BananaImage Nano Banana 2", description: "BananaImage Nano Banana 2。支持文生图、图片编辑、多图参考、极端比例和 1K/2K/4K 输出。", apiFormat: "bananaimage-gemini", supportedAspectRatios: BANANAIMAGE_EXTENDED_RATIOS, sortOrder: 20, }), buildBananaImagePreset({ modelId: "gemini-3-pro-image-preview-plus", displayName: "BananaImage Nano Banana Pro+", description: "BananaImage Nano Banana Pro+ 放宽限制版。支持文生图、图片编辑、多图参考、比例选择和 1K/2K/4K 输出。", apiFormat: "bananaimage-gemini", supportedAspectRatios: BANANAIMAGE_STANDARD_RATIOS, sortOrder: 30, }), buildBananaImagePreset({ modelId: "gemini-3.1-flash-image-preview-plus", displayName: "BananaImage Nano Banana 2+", description: "BananaImage Nano Banana 2+ 放宽限制版。支持文生图、图片编辑、多图参考、极端比例和 1K/2K/4K 输出。", apiFormat: "bananaimage-gemini", supportedAspectRatios: BANANAIMAGE_EXTENDED_RATIOS, sortOrder: 40, }), buildBananaImagePreset({ modelId: "gpt-image-2", displayName: "BananaImage GPT Image 2", description: "BananaImage GPT Image 2。支持文生图、图片编辑、最多 14 张参考图、比例选择和 1K/2K/4K 输出。", apiFormat: "bananaimage-gpt-image-2", supportedAspectRatios: BANANAIMAGE_GPT_IMAGE_2_RATIOS, sortOrder: 50, }), ]; export function getBananaImageModelPresetById(modelId: string) { return BANANAIMAGE_MODEL_PRESETS.find( (preset) => preset.modelId === String(modelId || "").trim() ); } export function resolveBananaImageRuntimeModelId(modelId: string) { const preset = getBananaImageModelPresetById(modelId); const endpoint = preset?.defaultParams?.endpoint; if (typeof endpoint === "string" && endpoint.trim()) { return endpoint.trim(); } return modelId; }