import { isOptionalApiRouteMissing } from "./apiErrorUtils"; import { isRecord, serverRequest } from "./serverConnection"; export interface ModelCapabilityOption { value: string; label: string; description?: string; badge?: string; enabled?: boolean; status?: "available" | "maintenance" | "disabled" | string; } export interface WebModelCapabilities { source: "server" | "fallback"; imageModels: ModelCapabilityOption[]; videoModels: ModelCapabilityOption[]; chatModels: ModelCapabilityOption[]; updatedAt?: string; } function toStringValue(value: unknown, fallback = ""): string { if (typeof value === "string") return value.trim() || fallback; if (typeof value === "number" && Number.isFinite(value)) return String(value); return fallback; } function normalizeModelOption(raw: unknown): ModelCapabilityOption | null { if (typeof raw === "string") { const value = raw.trim(); return value ? { value, label: value } : null; } if (!isRecord(raw)) return null; const value = toStringValue(raw.value ?? raw.id ?? raw.model ?? raw.modelKey ?? raw.model_key); if (!value) return null; const status = toStringValue(raw.status); const enabled = raw.enabled === undefined ? status !== "maintenance" && status !== "disabled" : Boolean(raw.enabled); if (!enabled) return null; return { value, label: toStringValue(raw.label ?? raw.displayName ?? raw.display_name ?? raw.name, value), description: toStringValue(raw.description) || undefined, badge: toStringValue(raw.badge) || undefined, enabled, status: status || "available", }; } function normalizeModelList(value: unknown): ModelCapabilityOption[] { return Array.isArray(value) ? value.map(normalizeModelOption).filter((item): item is ModelCapabilityOption => Boolean(item)) : []; } function createFallbackCapabilities(): WebModelCapabilities { return { source: "fallback", imageModels: [], videoModels: [], chatModels: [], }; } let modelCapabilitiesRouteMissing = false; export const modelCapabilitiesClient = { async get(name = "web-model-capabilities"): Promise { if (modelCapabilitiesRouteMissing) return createFallbackCapabilities(); let payload: unknown; try { payload = await serverRequest(`config/profile?name=${encodeURIComponent(name)}`); } catch (error) { if (isOptionalApiRouteMissing(error)) { modelCapabilitiesRouteMissing = true; return createFallbackCapabilities(); } throw error; } const raw = isRecord(payload) && isRecord(payload.config) ? payload.config : payload; const config = isRecord(raw) ? raw : {}; const models = isRecord(config.models) ? config.models : {}; return { source: "server", imageModels: normalizeModelList(config.imageModels ?? config.image_models ?? models.image), videoModels: normalizeModelList(config.videoModels ?? config.video_models ?? models.video), chatModels: normalizeModelList(config.chatModels ?? config.chat_models ?? models.chat ?? models.agent ?? models.text), updatedAt: toStringValue((payload as { updatedAt?: unknown; updated_at?: unknown })?.updatedAt ?? (payload as { updated_at?: unknown })?.updated_at), }; }, };