import { isProviderBalanceError } from "@/lib/request-error"; type BalanceState = { healthLastEventType?: unknown; healthLastError?: unknown; healthAutoDisabledReason?: unknown; }; export function isImageModelBalanceBlocked(model: BalanceState | null | undefined) { return Boolean( model && ((model.healthLastEventType === "quota" && isProviderBalanceError(model.healthLastError)) || isProviderBalanceError(model.healthAutoDisabledReason)), ); } export function resolveConfiguredImageBalanceFallback< T extends { model: BalanceState & { id: string; modelId: string; isEnabled: boolean; supportsImageGen: boolean; imageGenConfig?: unknown; }; provider: { isEnabled?: boolean }; }, >( requested: BalanceState & { fallbackModelId1?: string | null; fallbackModelId2?: string | null }, entries: T[], input: { imageSize?: unknown; aspectRatio?: unknown; referenceImageCount?: number; }, ) { if (!isImageModelBalanceBlocked(requested)) return undefined; for (const ref of [requested.fallbackModelId1, requested.fallbackModelId2]) { if (!ref) continue; const entry = entries.find(({ model }) => model.id === ref || model.modelId === ref); if ( !entry || !entry.model.isEnabled || entry.provider.isEnabled === false || !entry.model.supportsImageGen || isImageModelBalanceBlocked(entry.model) ) continue; const config = entry.model.imageGenConfig as Record | null; const size = String(input.imageSize || "").toUpperCase(); const ratio = String(input.aspectRatio || ""); if ( size && Array.isArray(config?.supportedImageSizes) && !config.supportedImageSizes.includes(size) ) continue; if ( ratio && ratio !== "auto" && Array.isArray(config?.supportedAspectRatios) && !config.supportedAspectRatios.includes(ratio) ) continue; if ( input.referenceImageCount && typeof config?.maxReferenceImages === "number" && input.referenceImageCount > config.maxReferenceImages ) continue; return entry; } return undefined; }