Add BFL image provider option
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-03-21 01:05:40 +08:00
parent 404e50a4d6
commit 9727da4072
5 changed files with 13 additions and 5 deletions

View File

@ -158,7 +158,7 @@ type ToolConfig = {
type AiProvider = {
id: string;
name: string;
type: "alibaba" | "openai" | "custom" | "local" | "gemini" | "huanke-gemini" | "qianwen-video" | "doubao-video" | "ruxa-video" | "volcano-vision" | "volcano-video" | "alibaba-image" | "ruxa-image" | "fal-image" | "openai-image" | "midjourney" | "fal-video" | "zhipu" | "tripo-3d" | "runway" | "volcano-multimodal";
type: "alibaba" | "openai" | "custom" | "local" | "gemini" | "huanke-gemini" | "qianwen-video" | "doubao-video" | "ruxa-video" | "volcano-vision" | "volcano-video" | "alibaba-image" | "bfl-image" | "ruxa-image" | "fal-image" | "openai-image" | "midjourney" | "fal-video" | "zhipu" | "tripo-3d" | "runway" | "volcano-multimodal";
baseUrl: string;
apiKey: string;
isEnabled: boolean;
@ -464,6 +464,7 @@ const AVAILABLE_TOOLS = [
const PROVIDER_TYPES = [
{ value: "alibaba", label: "阿里云通义千问" },
{ value: "alibaba-image", label: "阿里生图模型" }, // 🆕 千问图片生成/编辑
{ value: "bfl-image", label: "BFL FLUX.2 图片编辑" },
{ value: "ruxa-image", label: "RUXA生图" },
{ value: "fal-image", label: "FAL 生图模型" },
{ value: "openai-image", label: "OpenAI 图片兼容" },
@ -489,6 +490,7 @@ const PROVIDER_DEFAULT_BASE_URL: Record<string, string> = {
alibaba: "https://dashscope.aliyuncs.com/compatible-mode/v1",
"alibaba-image":
"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation",
"bfl-image": "https://api.bfl.ai",
"ruxa-image": "https://api.ruxa.ai",
"fal-image": "https://fal.run",
"openai-image": "https://api.openai.com/v1",
@ -1475,7 +1477,7 @@ export function AdminSettingsClient() {
const [providerForm, setProviderForm] = useState({
id: "",
name: "",
type: "openai" as "alibaba" | "openai" | "custom" | "local" | "gemini" | "huanke-gemini" | "qianwen-video" | "doubao-video" | "ruxa-video" | "volcano-vision" | "volcano-video" | "alibaba-image" | "ruxa-image" | "fal-image" | "openai-image" | "midjourney" | "fal-video" | "zhipu" | "tripo-3d" | "runway" | "volcano-multimodal",
type: "openai" as "alibaba" | "openai" | "custom" | "local" | "gemini" | "huanke-gemini" | "qianwen-video" | "doubao-video" | "ruxa-video" | "volcano-vision" | "volcano-video" | "alibaba-image" | "bfl-image" | "ruxa-image" | "fal-image" | "openai-image" | "midjourney" | "fal-video" | "zhipu" | "tripo-3d" | "runway" | "volcano-multimodal",
baseUrl: "",
apiKey: "",
isEnabled: true,
@ -4012,6 +4014,7 @@ export function AdminSettingsClient() {
"ruxa-video": "bg-violet-500",
"alibaba": "bg-blue-500",
"alibaba-image": "bg-amber-500",
"bfl-image": "bg-cyan-600",
"ruxa-image": "bg-emerald-500",
"fal-image": "bg-sky-500",
"openai-image": "bg-green-600",

View File

@ -22,6 +22,7 @@ const providerTypes = [
"volcano-vision",
"volcano-video",
"alibaba-image",
"bfl-image",
"ruxa-image",
"fal-image",
"openai-image",
@ -58,6 +59,7 @@ const DOUBAO_VIDEO_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3";
const RUXA_VIDEO_BASE_URL = "https://api.ruxa.ai";
const RUXA_IMAGE_BASE_URL = "https://api.ruxa.ai";
const OPENAI_IMAGE_BASE_URL = "https://api.openai.com/v1";
const BFL_IMAGE_BASE_URL = "https://api.bfl.ai";
const MIDJOURNEY_BASE_URL = "https://your-midjourney-api.example.com";
const TRIPO_3D_BASE_URL = "https://api.tripo3d.ai/v2/openapi";
const RUNWAY_BASE_URL = "https://api.dev.runwayml.com";
@ -196,6 +198,8 @@ export async function POST(request: Request) {
? data.baseUrl || DOUBAO_VIDEO_BASE_URL
: data.type === "ruxa-video"
? data.baseUrl || RUXA_VIDEO_BASE_URL
: data.type === "bfl-image"
? data.baseUrl || BFL_IMAGE_BASE_URL
: data.type === "ruxa-image"
? data.baseUrl || RUXA_IMAGE_BASE_URL
: data.type === "openai-image"

View File

@ -14,6 +14,7 @@ const PROVIDER_DEFAULT_BASE_URL: Partial<Record<AiProvider["type"], string>> = {
"ruxa-image": "https://api.ruxa.ai",
"fal-image": "https://fal.run",
"openai-image": "https://api.openai.com/v1",
"bfl-image": "https://api.bfl.ai",
midjourney: "https://your-midjourney-api.example.com",
"fal-video": "https://fal.run",
"tripo-3d": "https://api.tripo3d.ai/v2/openapi",

View File

@ -3386,7 +3386,7 @@ export async function createAiProvider({
updatedBy,
}: {
name: string;
type: "alibaba" | "openai" | "custom" | "local" | "gemini" | "huanke-gemini" | "qianwen-video" | "doubao-video" | "ruxa-video" | "volcano-vision" | "volcano-video" | "alibaba-image" | "ruxa-image" | "fal-image" | "openai-image" | "midjourney" | "fal-video" | "zhipu" | "tripo-3d" | "runway";
type: "alibaba" | "openai" | "custom" | "local" | "gemini" | "huanke-gemini" | "qianwen-video" | "doubao-video" | "ruxa-video" | "volcano-vision" | "volcano-video" | "alibaba-image" | "bfl-image" | "ruxa-image" | "fal-image" | "openai-image" | "midjourney" | "fal-video" | "zhipu" | "tripo-3d" | "runway";
baseUrl: string;
apiKey: string;
isEnabled?: boolean;
@ -3424,7 +3424,7 @@ export async function updateAiProvider({
}: {
id: string;
name?: string;
type?: "alibaba" | "openai" | "custom" | "local" | "gemini" | "huanke-gemini" | "qianwen-video" | "doubao-video" | "ruxa-video" | "volcano-vision" | "volcano-video" | "alibaba-image" | "ruxa-image" | "fal-image" | "openai-image" | "midjourney" | "fal-video" | "zhipu" | "tripo-3d" | "runway";
type?: "alibaba" | "openai" | "custom" | "local" | "gemini" | "huanke-gemini" | "qianwen-video" | "doubao-video" | "ruxa-video" | "volcano-vision" | "volcano-video" | "alibaba-image" | "bfl-image" | "ruxa-image" | "fal-image" | "openai-image" | "midjourney" | "fal-video" | "zhipu" | "tripo-3d" | "runway";
baseUrl?: string;
apiKey?: string;
isEnabled?: boolean;

View File

@ -259,7 +259,7 @@ export type ToolConfig = InferSelectModel<typeof toolConfig>;
export const aiProvider = pgTable("AiProvider", {
id: uuid("id").primaryKey().notNull().defaultRandom(),
name: varchar("name", { length: 128 }).notNull(), // 提供商名称,如 "阿里云通义千问"
type: varchar("type", { enum: ["alibaba", "openai", "custom", "local", "gemini", "huanke-gemini", "qianwen-video", "doubao-video", "ruxa-video", "volcano-vision", "volcano-video", "alibaba-image", "ruxa-image", "fal-image", "openai-image", "midjourney", "fal-video", "zhipu", "tripo-3d", "runway"] })
type: varchar("type", { enum: ["alibaba", "openai", "custom", "local", "gemini", "huanke-gemini", "qianwen-video", "doubao-video", "ruxa-video", "volcano-vision", "volcano-video", "alibaba-image", "ruxa-image", "fal-image", "openai-image", "midjourney", "fal-video", "zhipu", "tripo-3d", "runway", "bfl-image"] })
.notNull()
.default("custom"), // 提供商类型
baseUrl: text("baseUrl").notNull(), // API 基础 URL