Your Name cd91094b0f
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
feat: add fal provider for realtime canvas
2026-03-31 13:36:28 +08:00

66 lines
2.0 KiB
TypeScript

import { z } from "zod";
import { requireAdmin } from "@/lib/middleware/admin";
import { ChatSDKError } from "@/lib/errors";
import { probeBflModelSupport } from "@/lib/realtime/bfl-capability";
import { probeFalModelSupport } from "@/lib/realtime/fal-capability";
import { probeReplicateModelSupport } from "@/lib/realtime/replicate-capability";
import type { RealtimeProviderType } from "@/lib/realtime/config";
const schema = z.object({
providerType: z.enum(["bfl", "replicate", "fal"]).optional(),
apiKey: z.string().min(1),
modelId: z.string().min(1),
baseUrl: z.string().optional(),
});
function mapStatus(code: string) {
if (code === "UPSTREAM_ERROR") return 502;
return 400;
}
export async function POST(request: Request) {
try {
await requireAdmin();
const body = await request.json();
const data = schema.parse(body);
const providerType: RealtimeProviderType =
data.providerType === "replicate"
? "replicate"
: data.providerType === "fal"
? "fal"
: "bfl";
const result =
providerType === "replicate"
? await probeReplicateModelSupport({
apiKey: data.apiKey,
modelId: data.modelId,
baseUrl: data.baseUrl,
})
: providerType === "fal"
? await probeFalModelSupport({
apiKey: data.apiKey,
modelId: data.modelId,
})
: await probeBflModelSupport({
apiKey: data.apiKey,
modelId: data.modelId,
baseUrl: data.baseUrl,
});
if (!result.supported) {
return Response.json(result, { status: mapStatus(result.code) });
}
return Response.json(result);
} catch (error) {
if (error instanceof ChatSDKError) {
return error.toResponse();
}
if (error instanceof z.ZodError) {
return new ChatSDKError("bad_request:api", error.message).toResponse();
}
return new ChatSDKError("offline:admin").toResponse();
}
}