import "server-only"; import { cache } from "react"; import type { PolyModel } from "@/lib/ai/core/types"; import { listRegistryModels } from "@/lib/ai/registry"; import { buildBadgeContext, sortWeightOf, type BadgeContext } from "./badges"; import { compareSlug } from "./slug"; import { log } from "@/lib/log"; export interface PublicModelsData { models: PolyModel[]; ctx: BadgeContext; /** False when the registry could not be read (DB down) — pages render an honest empty state. */ ok: boolean; } /** Registry snapshot for the public SEO pages (no auth, no user data). Memoized per request via React `cache`. */ export const getPublicModels = cache(async (): Promise => { const now = Date.now(); try { const models = await listRegistryModels(); return { models, ctx: buildBadgeContext(models, now), ok: true }; } catch (e) { log.warn("public models: registry unavailable", { error: (e as Error).message }); return { models: [], ctx: buildBadgeContext([], now), ok: false }; } }); /** Best active model per native provider (highest sort weight). */ export function flagshipModels(models: PolyModel[], limit = 6): PolyModel[] { const seen = new Set(); const out: PolyModel[] = []; for (const m of [...models].filter((m) => m.status === "active" && m.provider !== "openrouter").sort((a, b) => sortWeightOf(b) - sortWeightOf(a))) { if (seen.has(m.provider)) continue; seen.add(m.provider); out.push(m); if (out.length >= limit) break; } return out; } /** Pairwise comparison slugs between flagships (for "Popular comparisons"). */ export function popularComparisons(models: PolyModel[], limit = 8): { slug: string; a: PolyModel; b: PolyModel }[] { const flags = flagshipModels(models, 5); const out: { slug: string; a: PolyModel; b: PolyModel }[] = []; for (let i = 0; i < flags.length; i++) for (let j = i + 1; j < flags.length; j++) out.push({ slug: compareSlug([flags[i], flags[j]]), a: flags[i], b: flags[j] }); return out.slice(0, limit); }