feat: add verified VIP98K multi-image models

This commit is contained in:
134 2026-09-10 10:08:13 +08:00
parent 6f5a444756
commit 821b8658a8
4 changed files with 95 additions and 2 deletions

View File

@ -1427,6 +1427,7 @@ function buildTaskBody(params: Vip98kTaskParams, invocation: Vip98kInvocation |
videoParams.resolution || imageParams.size || imageParams.imageSize || "",
).trim();
const negativePrompt = String(videoParams.negativePrompt || imageParams.negativePrompt || "").trim();
const quality = String(imageParams.quality || "").trim().toLowerCase();
const outputConstraintFallbacks: string[] = [];
let hasNativeAspectRatio = false;
let hasNativeResolution = false;
@ -1481,6 +1482,9 @@ function buildTaskBody(params: Vip98kTaskParams, invocation: Vip98kInvocation |
if ("negativePrompt" in body || !invocation) body.negativePrompt = negativePrompt;
if ("negative_prompt" in body || !invocation) body.negative_prompt = negativePrompt;
}
if (quality && invocationSupportsBodyField(invocation, "quality")) {
body.quality = quality;
}
const imageToolParamAliases = [
["scaleFactor", "scale_factor"],
["xScale", "x_scale"],

View File

@ -185,6 +185,8 @@ const VERIFIED_2026_IMAGE_MODEL_PATTERNS = [
/^nano-banana-fast$/,
/^nano-banana-pro$/,
/^gpt-image-2(?:$|[-/])/,
/^gpt-image-2\.5$/,
/^gpt-image-2\.5-flare$/,
/^alibaba\/wan-2\.(?:6|7)(?:$|[-/])/,
/^black-forest-labs\/flux-2(?:$|[-/])/,
/^bytedance\/seedream-v5(?:$|[.\-/])/,
@ -689,6 +691,7 @@ function createImagePreset(
"ratio",
"aspect-ratio",
].some((key) => invocationKeys.has(key)) || supportsNativeSize;
const supportsQuality = invocationKeys.has("quality");
const supportedModes = [
...(capabilities.includes("text-to-image") || capabilities.length === 0
? ["text-to-image"]
@ -738,6 +741,7 @@ function createImagePreset(
taskApi: "external-task",
supportedModes,
...(supportsNativeSize ? { imageSize: defaultImageSize } : {}),
...(supportsQuality ? { quality: "auto" } : {}),
aspectRatio: "auto",
imageCount: 1,
},
@ -745,6 +749,7 @@ function createImagePreset(
maxImages: 1,
maxReferenceImages,
supportsSize: supportsNativeSize,
supportsQuality,
supports1K: supportsNativeSize && supportedImageSizes.includes("1K"),
supports2K: supportsNativeSize && supportedImageSizes.includes("2K"),
supports4K: supportsNativeSize && supportedImageSizes.includes("4K"),

View File

@ -99,14 +99,15 @@ export function getVip98kSubmissionRetryDelay(params: {
maxAttempts: number;
retryAfterMs?: number | null;
}) {
const recoverableGatewayFailure = params.status === 502 || params.status === 504;
const recoverableSubmission =
/pending\s+safe\s+reconciliation/i.test(params.message) ||
/request\s+outcome\s+(?:is\s+)?unknown/i.test(params.message) ||
/final\s+outcome\s+could\s+not\s+be\s+confirmed/i.test(params.message);
if (
params.status !== 503 ||
params.attempt >= params.maxAttempts ||
!recoverableSubmission
(!recoverableGatewayFailure &&
(params.status !== 503 || !recoverableSubmission))
) {
return null;
}

View File

@ -193,6 +193,23 @@ test.describe("VIP98K reference-image routing", () => {
maxAttempts: 3,
}),
).toBeNull();
expect(
getVip98kSubmissionRetryDelay({
status: 502,
message: "Bad Gateway",
attempt: 1,
maxAttempts: 3,
}),
).toBe(15_000);
expect(
getVip98kSubmissionRetryDelay({
status: 504,
message: "Gateway Timeout",
attempt: 2,
maxAttempts: 3,
retryAfterMs: 6_000,
}),
).toBe(6_000);
});
test("shows the newly published Nano Banana Pro image editor", () => {
@ -523,6 +540,72 @@ test.describe("VIP98K reference-image routing", () => {
});
});
test("publishes only the verified GPT Image 2.5 multi-image variants", () => {
const models = [
"gpt-image-2.5",
"gpt-image-2.5-flare",
"gpt-image-2.5-sunburst",
].map((modelId) => ({
id: modelId,
type: "image",
capabilities: ["image_to_image", "openai.images.generations"],
invocation: {
kind: "tool",
method: "POST",
path: "/v1/images/generations",
content_type: "application/json",
request_example: {
image: ["https://api.vip98k.com/logo.png"],
model: modelId,
n: 1,
prompt: "Edit",
quality: "auto",
stream: false,
},
},
}));
expect(models.map((model) => isVip98kImageModelVisible(model))).toEqual([
true,
true,
false,
]);
const presets = buildVip98kModelPresets(models);
expect(
presets.map((preset) => ({
modelId: preset.modelId,
isHidden: preset.isHidden,
supportsQuality: preset.imageGenConfig?.supportsQuality,
quality: preset.defaultParams.quality,
supportedAspectRatios:
preset.imageGenConfig?.supportedAspectRatios,
})),
).toEqual([
{
modelId: "gpt-image-2.5",
isHidden: false,
supportsQuality: true,
quality: "auto",
supportedAspectRatios: ["auto"],
},
{
modelId: "gpt-image-2.5-flare",
isHidden: false,
supportsQuality: true,
quality: "auto",
supportedAspectRatios: ["auto"],
},
{
modelId: "gpt-image-2.5-sunburst",
isHidden: true,
supportsQuality: true,
quality: "auto",
supportedAspectRatios: ["auto"],
},
]);
});
test("does not inherit multi-image support from broad authorized metadata", () => {
const presets = buildVip98kModelPresets([
{