fix: prioritize bfl input image editing
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-07 22:09:06 +08:00
parent 449dd19d5f
commit 2b6342bc7f
2 changed files with 38 additions and 9 deletions

View File

@ -154,6 +154,12 @@ function toImagePromptValue(imageUrl: string) {
return trimmed;
}
function getBflImageFieldCandidates() {
// BFL's current FLUX/Kontext editing APIs use `input_image` as the canonical field.
// Keep `image_prompt` only as a legacy fallback in case an older compatible endpoint is used.
return ["input_image", "image_prompt"] as const;
}
type SubmitTaskResult = {
taskId: string;
pollingUrl: string;
@ -367,13 +373,9 @@ export async function POST(request: Request) {
);
}
const preferredImageField =
model.toLowerCase().includes("kontext") || model.toLowerCase().includes("edit")
? "input_image"
: "image_prompt";
const imageFieldCandidates = [preferredImageField, preferredImageField === "input_image" ? "image_prompt" : "input_image"];
const imageFieldCandidates = getBflImageFieldCandidates();
let selectedImageField = imageFieldCandidates[0];
let selectedImageField: "input_image" | "image_prompt" = imageFieldCandidates[0];
let submitResult: SubmitTaskResult | null = null;
let fallbackWarning = "";

View File

@ -1,6 +1,9 @@
import sharp from "sharp";
const DEFAULT_BFL_BASE_URL = "https://api.bfl.ai";
const DEFAULT_BFL_MODEL_ID = "flux-2-klein-4b";
const DEFAULT_TIMEOUT_MS = 15_000;
const PROBE_IMAGE_SIZE = 64;
export type BflCapabilityCode =
| "SUPPORTED"
@ -68,6 +71,28 @@ function hasTaskIdentity(payload: any) {
);
}
let cachedProbeImageBase64: string | null = null;
async function getProbeImageBase64() {
if (cachedProbeImageBase64) {
return cachedProbeImageBase64;
}
const buffer = await sharp({
create: {
width: PROBE_IMAGE_SIZE,
height: PROBE_IMAGE_SIZE,
channels: 3,
background: { r: 255, g: 255, b: 255 },
},
})
.png()
.toBuffer();
cachedProbeImageBase64 = buffer.toString("base64");
return cachedProbeImageBase64;
}
export async function probeBflModelSupport(params: BflProbeParams): Promise<BflModelProbeResult> {
const apiKey = String(params.apiKey || "").trim();
const modelId = String(params.modelId || DEFAULT_BFL_MODEL_ID).trim() || DEFAULT_BFL_MODEL_ID;
@ -87,6 +112,7 @@ export async function probeBflModelSupport(params: BflProbeParams): Promise<BflM
try {
const endpoint = `${baseUrl}/v1/${encodeModelPath(modelId)}`;
const inputImage = await getProbeImageBase64();
const response = await fetch(endpoint, {
method: "POST",
headers: {
@ -95,9 +121,10 @@ export async function probeBflModelSupport(params: BflProbeParams): Promise<BflM
Accept: "application/json",
},
body: JSON.stringify({
prompt: "probe image generation capability",
width: 512,
height: 512,
prompt: "probe image editing capability; preserve the input image composition",
input_image: inputImage,
width: PROBE_IMAGE_SIZE,
height: PROBE_IMAGE_SIZE,
safety_tolerance: 2,
}),
cache: "no-store",