const STATIC_VIDEO_PROVIDER_TYPES = new Set([ "doubao-video", "volcano-video", "qianwen-video", "fal-video", "ruxa-video", ]); const STATIC_IMAGE_PROVIDER_TYPES = new Set([ "gemini", "huanke-gemini", "alibaba-image", "bfl-image", "ruxa-image", "fal-image", "openai-image", "midjourney", "volcano-vision", ]); const RUNWAY_IMAGE_MODEL_IDS = new Set([ "gen4_image", "gen4_image_turbo", "gemini_2.5_flash", ]); const RUNWAY_VIDEO_MODEL_PREFIXES = [ "gen4.5", "gen4_turbo", "gen4_aleph", "gen3a_turbo", "veo3.1_fast", "veo3.1", "veo3", "act_two", "upscale_v1", ]; const VIDEO_MODE_KEYS = new Set([ "text-to-video", "first-frame", "first-last-frame", "reference-images", ]); function normalizeText(value?: string | null) { return String(value || "").trim().toLowerCase(); } function hasVideoModes(capabilities: unknown) { if (!capabilities || typeof capabilities !== "object") return false; const supportedModes = (capabilities as { supportedModes?: unknown }).supportedModes; if (!Array.isArray(supportedModes)) return false; return supportedModes.some((mode) => VIDEO_MODE_KEYS.has(String(mode || "").trim())); } export function inferRunwayModelKind(modelId?: string | null): "image" | "video" | null { const normalized = normalizeText(modelId); if (!normalized) return null; if (RUNWAY_IMAGE_MODEL_IDS.has(normalized)) return "image"; if (RUNWAY_VIDEO_MODEL_PREFIXES.some((prefix) => normalized === prefix || normalized.startsWith(`${prefix}_`))) { return "video"; } return null; } export function isStaticVideoProviderType(providerType?: string | null): boolean { return STATIC_VIDEO_PROVIDER_TYPES.has(normalizeText(providerType)); } export function isVideoModelDescriptor(params: { providerType?: string | null; modelId?: string | null; capabilities?: unknown; supportsImageGen?: boolean | null; }): boolean { const providerType = normalizeText(params.providerType); if (isStaticVideoProviderType(providerType)) { return true; } if (hasVideoModes(params.capabilities)) { return true; } if (providerType === "runway") { return inferRunwayModelKind(params.modelId) === "video"; } return false; } export function isImageGenerationModelDescriptor(params: { providerType?: string | null; modelId?: string | null; capabilities?: unknown; supportsImageGen?: boolean | null; }): boolean { const providerType = normalizeText(params.providerType); if (providerType === "runway") { const runwayModelKind = inferRunwayModelKind(params.modelId); if (runwayModelKind === "image") return true; if (runwayModelKind === "video") return false; } if (isVideoModelDescriptor(params)) { return false; } if (params.supportsImageGen === true) { return true; } return STATIC_IMAGE_PROVIDER_TYPES.has(providerType); }