import "server-only"; import type { DiscountableImageGenConfigLike } from "@/lib/ai/image-model-pricing"; import { getImageCreditCostFromConfig, getImageModelCreditDiscountLabel, } from "@/lib/ai/image-model-pricing"; import { getAiModelFrontendAvailability, type ModelFrontendAvailabilityStatus, } from "@/lib/ai/model-frontend-availability"; import { isStillImageGenerationModelDescriptor } from "@/lib/ai/model-classification"; import { getEnabledAiModelsWithProvider, getFrontendDisplayAiModelsWithProvider, } from "@/lib/db/queries"; export type StyleProModelEntry = Awaited< ReturnType >[number]; export type StyleProDisplayModelEntry = Awaited< ReturnType >[number]; export type PublicStyleProModelOption = { id: string; modelId: string; displayName: string; avatarUrl: string | null; providerName: string; providerType: string; isDefault: boolean; unitCost: number; creditDiscountLabel: string | null; availabilityStatus: ModelFrontendAvailabilityStatus; availabilityLabel: string | null; selectable: boolean; disabledReason: string | null; }; export function isStyleProImageModel( entry: StyleProModelEntry | StyleProDisplayModelEntry ) { return isStillImageGenerationModelDescriptor({ providerType: entry.provider.type, modelId: entry.model.modelId, capabilities: entry.model.capabilities, supportsImageGen: entry.model.supportsImageGen, }); } export async function getStyleProImageModelEntries(options?: { includeHidden?: boolean; }) { const models = await getEnabledAiModelsWithProvider( false, options?.includeHidden === true ); return models.filter(isStyleProImageModel); } export async function getStyleProImageModelDisplayEntries(options?: { includeHidden?: boolean; }) { const models = await getFrontendDisplayAiModelsWithProvider( false, options?.includeHidden === true ); return models.filter(isStyleProImageModel); } export function findStyleProImageModelByRef( entries: Array, modelRef?: string | null ) { const normalized = String(modelRef || "").trim(); if (!normalized) return null; return ( entries.find( ({ model }) => model.id === normalized || model.modelId === normalized ) || null ); } export function sortStyleProImageModelEntries< T extends StyleProModelEntry | StyleProDisplayModelEntry, >(entries: T[]) { return [...entries].sort((left, right) => { const leftOrder = Number.isFinite(Number(left.model.sortOrder)) ? Number(left.model.sortOrder) : 0; const rightOrder = Number.isFinite(Number(right.model.sortOrder)) ? Number(right.model.sortOrder) : 0; if (leftOrder !== rightOrder) return leftOrder - rightOrder; const leftName = String(left.model.displayName || left.model.modelId || ""); const rightName = String(right.model.displayName || right.model.modelId || ""); return leftName.localeCompare(rightName, "zh-Hans-CN"); }); } export function toPublicStyleProModelOption( entry: StyleProModelEntry | StyleProDisplayModelEntry ): PublicStyleProModelOption { const imageGenConfig = (entry.model.imageGenConfig || null) as DiscountableImageGenConfigLike | null; const availability = getAiModelFrontendAvailability(entry.model); return { id: entry.model.id, modelId: entry.model.modelId, displayName: entry.model.displayName, avatarUrl: entry.model.avatarUrl || null, providerName: entry.provider.name, providerType: entry.provider.type, isDefault: entry.model.isDefault, unitCost: getImageCreditCostFromConfig(imageGenConfig), creditDiscountLabel: getImageModelCreditDiscountLabel(imageGenConfig), ...availability, }; }