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" && (