From ede6f080a2f879de464d4bb9ef1e7dcdfbdee154 Mon Sep 17 00:00:00 2001 From: 134 Date: Mon, 13 Jul 2026 22:59:34 +0800 Subject: [PATCH] feat: add BananaImage image provider --- app/(admin)/settings/_lib/types.ts | 1 + .../settings/admin-settings-client.tsx | 75 ++ app/(chat)/api/chat/_lib/image-failover.ts | 2 + app/(chat)/api/chat/_lib/image-media.ts | 1 + app/(chat)/api/chat/_lib/stream.ts | 1 + app/(chat)/api/chat/route.ts | 13 + app/api/admin/ai-providers/route.ts | 4 + app/api/admin/bananaimage-models/route.ts | 128 ++++ app/api/canvas/text-edit/route.ts | 4 + app/api/scene-fusion/route.ts | 49 ++ components/image-generation-loading.tsx | 1 + components/image-params-bar.tsx | 1 + components/image-preview.tsx | 3 + lib/ai/bananaimage-models.ts | 184 +++++ lib/ai/dynamic-provider.ts | 13 + lib/ai/model-classification.ts | 1 + lib/ai/model-router.ts | 13 +- lib/ai/provider-defaults.ts | 1 + lib/ai/providers/bananaimage.ts | 664 ++++++++++++++++++ lib/ai/runtime/generated-image-persistence.ts | 2 + lib/canvas/generate-image.ts | 29 +- lib/db/migrate.ts | 3 +- .../0090_add_bananaimage_provider_type.sql | 38 + lib/db/migrations/meta/_journal.json | 7 + lib/db/queries.ts | 4 +- lib/db/schema.ts | 2 +- lib/external-image-api/service.ts | 5 + lib/image-url.ts | 6 +- lib/scene-fusion/output-capabilities.ts | 2 + 29 files changed, 1244 insertions(+), 13 deletions(-) create mode 100644 app/api/admin/bananaimage-models/route.ts create mode 100644 lib/ai/bananaimage-models.ts create mode 100644 lib/ai/providers/bananaimage.ts create mode 100644 lib/db/migrations/0090_add_bananaimage_provider_type.sql diff --git a/app/(admin)/settings/_lib/types.ts b/app/(admin)/settings/_lib/types.ts index e491153fb..5b05bb5a6 100644 --- a/app/(admin)/settings/_lib/types.ts +++ b/app/(admin)/settings/_lib/types.ts @@ -88,6 +88,7 @@ export type AdminAiProvider = { | "fal-image" | "snapgen-image" | "openai-image" + | "bananaimage" | "stepfun-image" | "midjourney" | "fal-video" diff --git a/app/(admin)/settings/admin-settings-client.tsx b/app/(admin)/settings/admin-settings-client.tsx index f4834ca33..4a6be57e6 100644 --- a/app/(admin)/settings/admin-settings-client.tsx +++ b/app/(admin)/settings/admin-settings-client.tsx @@ -165,6 +165,7 @@ import { import { FAL_IMAGE_MODEL_PRESETS } from "@/lib/ai/fal-image-models"; import { RUXA_IMAGE_MODEL_PRESETS } from "@/lib/ai/ruxa-image-models"; import { SNAPGEN_IMAGE_MODEL_PRESETS } from "@/lib/ai/snapgen-image-models"; +import { BANANAIMAGE_MODEL_PRESETS } from "@/lib/ai/bananaimage-models"; import { formatImageModelCreditDiscountLabel, getGenerationCreditCostFromImageGenConfig, @@ -621,6 +622,7 @@ type AiProvider = { | "fal-image" | "snapgen-image" | "openai-image" + | "bananaimage" | "stepfun-image" | "midjourney" | "fal-video" @@ -1579,6 +1581,7 @@ const PROVIDER_TYPES = [ { value: "fal-image", label: "FAL 图片生成/编辑" }, { value: "snapgen-image", label: "SnapGen 生图" }, { value: "openai-image", label: "OpenAI 图片兼容" }, + { value: "bananaimage", label: "BananaImage 生图" }, { value: "stepfun-image", label: "阶跃星辰 Step Image Edit" }, { value: "bltcy-video", label: "柏拉图统一视频" }, { value: "grsai-gpt-image", label: "Grsai GPT Image" }, @@ -1613,6 +1616,7 @@ const PROVIDER_DEFAULT_BASE_URL: Record = { "fal-image": "https://fal.run", "snapgen-image": "https://api.snapgen.ai", "openai-image": "https://api.openai.com/v1", + bananaimage: "https://bananaimage.aigenmedia.art", "stepfun-image": "https://api.stepfun.com", "bltcy-video": "https://api.bltcy.ai", "grsai-gpt-image": "https://grsai.dakka.com.cn", @@ -4029,6 +4033,7 @@ export function AdminSettingsClient() { | "fal-image" | "snapgen-image" | "openai-image" + | "bananaimage" | "stepfun-image" | "midjourney" | "fal-video" @@ -6265,6 +6270,7 @@ export function AdminSettingsClient() { const isFalImageProvider = providerForm.type === "fal-image"; const isRuxaImageProvider = providerForm.type === "ruxa-image"; const isSnapgenImageProvider = providerForm.type === "snapgen-image"; + const isBananaImageProvider = providerForm.type === "bananaimage"; const isBltcyVideoProvider = providerForm.type === "bltcy-video"; const isLemonProvider = providerForm.type === "openai" && @@ -6407,6 +6413,17 @@ export function AdminSettingsClient() { } } + if (isNewProvider && isBananaImageProvider && providerId) { + try { + await handleQuickAddBananaImageModels(providerId, { skipConfirm: true }); + } catch (modelError) { + console.error("[Auto Add BananaImage Models] Error:", modelError); + toast.warning( + 'BananaImage 预设模型添加失败,请手动点击"快速添加 BananaImage 图片预设"按钮' + ); + } + } + if (isNewProvider && isBltcyVideoProvider && providerId) { try { await handleQuickAddBltcyVideoModels(providerId, { @@ -7381,6 +7398,43 @@ export function AdminSettingsClient() { } }; + const handleQuickAddBananaImageModels = async ( + providerId: string, + options?: { skipConfirm?: boolean } + ) => { + if ( + !options?.skipConfirm && + !confirm( + `将同步 ${BANANAIMAGE_MODEL_PRESETS.length} 个 BananaImage 生图模型,支持多图参考、比例选择和 1K/2K/4K。\n\n继续吗?` + ) + ) { + return; + } + + try { + toast.info("正在同步 BananaImage 生图预设模型..."); + const response = await fetch("/api/admin/bananaimage-models", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ providerId }), + }); + const data = await response.json(); + if (!response.ok) throw new Error(data.error || "同步失败"); + + const totalSynced = Number(data.addedCount || 0) + Number(data.updatedCount || 0); + if (totalSynced > 0) { + toast.success(`成功同步 ${totalSynced} 个 BananaImage 生图预设模型`); + mutateModels(); + } + if (data.errors?.length) { + toast.warning(`${data.errors.length} 个 BananaImage 模型同步失败`); + } + } catch (error: any) { + console.error("[Quick Add BananaImage Models] Error:", error); + toast.error(error.message || "同步 BananaImage 生图预设模型失败"); + } + }; + const handleUseFalImageProviderPreset = () => { setProviderForm({ id: "", @@ -15581,6 +15635,14 @@ export function AdminSettingsClient() { https://api.snapgen.ai。保存后会自动添加文档里的全部生图模型预设。

)} + {providerForm.type === "bananaimage" && ( +

+ BananaImage 使用 Bearer API Key 认证,默认地址 + https://bananaimage.aigenmedia.art。保存后自动同步 Nano + Banana 与 GPT Image 2 全部模型,支持最多 14 张参考图、比例选择和 + 1K/2K/4K 输出。 +

+ )} {providerForm.type === "bfl-image" && isBltcyBflBaseUrl(providerForm.baseUrl) && (

@@ -15701,6 +15763,19 @@ export function AdminSettingsClient() { 快速添加 SnapGen 图片预设 )} + {provider.type === "bananaimage" && ( + + )} {provider.type === "bltcy-video" && (