fix: restore vip98k text image models
This commit is contained in:
parent
79705c4360
commit
2dbb14bb6b
@ -181,6 +181,7 @@ const IMAGE_TOOL_OPERATION_BY_MODEL_ID: Record<string, string> = {
|
||||
// available to backend routing but remain hidden until their 2026+ release is verified.
|
||||
const VERIFIED_2026_IMAGE_MODEL_PATTERNS = [
|
||||
/^nano-banana-2(?:$|[-/])/,
|
||||
/^nano-banana-fast$/,
|
||||
/^nano-banana-pro$/,
|
||||
/^gpt-image-2(?:$|[-/])/,
|
||||
/^alibaba\/wan-2\.(?:6|7)(?:$|[-/])/,
|
||||
@ -425,8 +426,14 @@ export function isVip98kCatalogModelAvailable(model: Vip98kCatalogModel) {
|
||||
export function isVip98kCatalogModelEligible(model: Vip98kCatalogModel) {
|
||||
if (!getModelId(model) || !isVip98kCatalogModelAvailable(model)) return false;
|
||||
const type = resolvePresetType(model);
|
||||
if (type !== "image" && type !== "video") return true;
|
||||
return hasMediaReferenceInput(model, type);
|
||||
if (type === "image") {
|
||||
return (
|
||||
hasMediaReferenceInput(model, type) ||
|
||||
isVip98kTextToImageCatalogModel(model)
|
||||
);
|
||||
}
|
||||
if (type === "video") return hasMediaReferenceInput(model, type);
|
||||
return true;
|
||||
}
|
||||
|
||||
export function filterVip98kCatalogModels(models: Vip98kCatalogModel[]) {
|
||||
@ -652,7 +659,7 @@ function createImagePreset(
|
||||
type: "image",
|
||||
supportsVision: supportsReferenceImages,
|
||||
supportsImageGen: true,
|
||||
isHidden: !isVip98kImageModelVisible(model) || !supportsReferenceImages,
|
||||
isHidden: !isVip98kImageModelVisible(model),
|
||||
capabilities: {
|
||||
provider: "vip98k",
|
||||
kind: "image",
|
||||
|
||||
@ -19,12 +19,7 @@ function toJsonValue(value: unknown): postgres.JSONValue {
|
||||
}
|
||||
|
||||
function isQualifiedVip98kImagePreset(preset: Vip98kModelPreset) {
|
||||
const capabilities = preset.capabilities as Record<string, unknown>;
|
||||
return (
|
||||
preset.supportsImageGen &&
|
||||
!preset.isHidden &&
|
||||
capabilities.supportsMultiImageReference === true
|
||||
);
|
||||
return preset.supportsImageGen && !preset.isHidden;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
@ -40,7 +35,7 @@ async function main() {
|
||||
});
|
||||
const qualifiedVip98kPresets = presets.filter(isQualifiedVip98kImagePreset);
|
||||
if (qualifiedVip98kPresets.length === 0) {
|
||||
throw new Error("VIP98K catalog contains no qualified multi-image model");
|
||||
throw new Error("VIP98K catalog contains no qualified image model");
|
||||
}
|
||||
|
||||
const sql = postgres(databaseUrl, { prepare: false, max: 1 });
|
||||
@ -64,23 +59,15 @@ async function main() {
|
||||
Array<{
|
||||
id: string;
|
||||
modelId: string;
|
||||
healthStatus: string | null;
|
||||
}>
|
||||
>`
|
||||
select id, "modelId", "healthStatus"
|
||||
select id, "modelId"
|
||||
from "AiModel"
|
||||
where "providerId" = ${vip98kProvider.id}::uuid
|
||||
`;
|
||||
const existingVip98kByModelId = new Map(
|
||||
existingVip98kModels.map((model) => [model.modelId, model]),
|
||||
);
|
||||
const autoDisabledQualifiedModelIds = qualifiedVip98kPresets
|
||||
.filter(
|
||||
(preset) =>
|
||||
existingVip98kByModelId.get(preset.modelId)?.healthStatus ===
|
||||
"auto_disabled",
|
||||
)
|
||||
.map((preset) => preset.modelId);
|
||||
|
||||
const disallowedImageModels = await sql<
|
||||
Array<{ id: string; providerType: string; modelId: string }>
|
||||
@ -123,7 +110,9 @@ async function main() {
|
||||
mode: apply ? "apply" : "dry-run",
|
||||
allowedImageProviderTypes: ALLOWED_IMAGE_PROVIDER_TYPES,
|
||||
qualifiedVip98kModels: qualifiedVip98kPresets.map((preset) => preset.modelId),
|
||||
autoDisabledVip98kModelsPreserved: autoDisabledQualifiedModelIds,
|
||||
protectedVip98kModels: qualifiedVip98kPresets.map(
|
||||
(preset) => preset.modelId,
|
||||
),
|
||||
disallowedImageModelsToDisable: disallowedImageModels.length,
|
||||
staleVip98kImageModelsToDisable: staleVip98kImageModels.length,
|
||||
imageOnlyProvidersToDisable: imageOnlyProviders.map((provider) => ({
|
||||
@ -148,11 +137,21 @@ async function main() {
|
||||
update "AiProvider" set "isEnabled" = true, "updatedAt" = now()
|
||||
where type = 'alibaba-image'
|
||||
`;
|
||||
await tx`
|
||||
update "AiModel" m set
|
||||
"isEnabled" = true, "excludeFromHealthBan" = true,
|
||||
"healthStatus" = 'healthy', "healthConsecutiveFailures" = 0,
|
||||
"healthLastEventType" = null, "healthLastError" = null,
|
||||
"healthAutoDisabledAt" = null, "healthAutoDisabledReason" = null,
|
||||
"healthRecoverySuccessStreak" = 0,
|
||||
"healthObservationStartedAt" = null,
|
||||
"healthUpdatedAt" = now(), "updatedAt" = now()
|
||||
from "AiProvider" p
|
||||
where p.id = m."providerId" and p.type = 'alibaba-image'
|
||||
and m."supportsImageGen" and not m."isHidden"
|
||||
`;
|
||||
|
||||
for (const preset of qualifiedVip98kPresets) {
|
||||
const preserveAutoDisabled = autoDisabledQualifiedModelIds.includes(
|
||||
preset.modelId,
|
||||
);
|
||||
const capabilities = tx.json(toJsonValue(preset.capabilities));
|
||||
const defaultParams = tx.json(toJsonValue(preset.defaultParams));
|
||||
const imageGenConfig = preset.imageGenConfig
|
||||
@ -164,7 +163,12 @@ async function main() {
|
||||
update "AiModel" set
|
||||
"displayName" = ${preset.displayName}, description = ${preset.description},
|
||||
"supportsVision" = ${preset.supportsVision}, "supportsImageGen" = true,
|
||||
"isEnabled" = ${!preserveAutoDisabled}, "isHidden" = false,
|
||||
"isEnabled" = true, "isHidden" = false,
|
||||
"excludeFromHealthBan" = true, "healthStatus" = 'healthy',
|
||||
"healthConsecutiveFailures" = 0, "healthLastEventType" = null,
|
||||
"healthLastError" = null, "healthAutoDisabledAt" = null,
|
||||
"healthAutoDisabledReason" = null, "healthRecoverySuccessStreak" = 0,
|
||||
"healthObservationStartedAt" = null, "healthUpdatedAt" = now(),
|
||||
"sortOrder" = ${preset.sortOrder},
|
||||
capabilities = ${capabilities}, "defaultParams" = ${defaultParams},
|
||||
"imageGenConfig" = ${imageGenConfig}, "fallbackModelId1" = null,
|
||||
@ -176,11 +180,13 @@ async function main() {
|
||||
insert into "AiModel" (
|
||||
"providerId", "modelId", "displayName", description, "supportsVision",
|
||||
"supportsImageGen", "isEnabled", "isHidden", "sortOrder", capabilities,
|
||||
"defaultParams", "imageGenConfig", "isDefault", "isDefaultTextEditModel"
|
||||
"defaultParams", "imageGenConfig", "isDefault", "isDefaultTextEditModel",
|
||||
"excludeFromHealthBan", "healthStatus"
|
||||
) values (
|
||||
${vip98kProvider.id}::uuid, ${preset.modelId}, ${preset.displayName},
|
||||
${preset.description}, ${preset.supportsVision}, true, true, false,
|
||||
${preset.sortOrder}, ${capabilities}, ${defaultParams}, ${imageGenConfig}, false, false
|
||||
${preset.sortOrder}, ${capabilities}, ${defaultParams}, ${imageGenConfig},
|
||||
false, false, true, 'healthy'
|
||||
)
|
||||
`;
|
||||
}
|
||||
@ -227,9 +233,7 @@ async function main() {
|
||||
if (invalidModels.length > 0) {
|
||||
throw new Error("Disallowed image models remain enabled after apply");
|
||||
}
|
||||
const expectedActiveVip98kCount =
|
||||
qualifiedVip98kPresets.length - autoDisabledQualifiedModelIds.length;
|
||||
if (activeVip98kModels.length !== expectedActiveVip98kCount) {
|
||||
if (activeVip98kModels.length !== qualifiedVip98kPresets.length) {
|
||||
throw new Error("VIP98K active image model count does not match qualified catalog");
|
||||
}
|
||||
console.log(
|
||||
|
||||
@ -355,10 +355,10 @@ test.describe("VIP98K reference-image routing", () => {
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test("excludes text-only VIP98K image models from editing workflows", () => {
|
||||
test("publishes text-only VIP98K models without reference-image support", () => {
|
||||
const [preset] = buildVip98kModelPresets([
|
||||
{
|
||||
id: "nano-banana-pro",
|
||||
id: "gpt-image-2-vip",
|
||||
type: "image",
|
||||
capabilities: ["openai.images.generations", "text_to_image"],
|
||||
invocation: {
|
||||
@ -366,12 +366,22 @@ test.describe("VIP98K reference-image routing", () => {
|
||||
method: "POST",
|
||||
path: "/v1/images/generations",
|
||||
content_type: "application/json",
|
||||
request_example: { model: "nano-banana-pro", n: 1, prompt: "Generate" },
|
||||
request_example: { model: "gpt-image-2-vip", n: 1, prompt: "Generate" },
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
expect(preset).toBeUndefined();
|
||||
expect(preset).toMatchObject({
|
||||
modelId: "gpt-image-2-vip",
|
||||
supportsVision: false,
|
||||
supportsImageGen: true,
|
||||
isHidden: false,
|
||||
capabilities: {
|
||||
supportedModes: ["text-to-image"],
|
||||
supportsMultiImageReference: false,
|
||||
maxReferenceImages: 0,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("does not inherit multi-image support from broad authorized metadata", () => {
|
||||
@ -395,6 +405,15 @@ test.describe("VIP98K reference-image routing", () => {
|
||||
},
|
||||
]);
|
||||
|
||||
expect(presets).toEqual([]);
|
||||
expect(presets).toHaveLength(1);
|
||||
expect(presets[0]).toMatchObject({
|
||||
modelId: "nano-banana-2-lite",
|
||||
supportsVision: false,
|
||||
capabilities: {
|
||||
supportedModes: ["text-to-image"],
|
||||
supportsMultiImageReference: false,
|
||||
maxReferenceImages: 0,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user