TypeScript 97.4%
SQL 1%
JavaScript 0.9%
CSS 0.6%
1import "server-only";2import { cache } from "react";3import type { PolyModel } from "@/lib/ai/core/types";4import { listRegistryModels } from "@/lib/ai/registry";5import { buildBadgeContext, sortWeightOf, type BadgeContext } from "./badges";6import { compareSlug } from "./slug";7import { log } from "@/lib/log";89export interface PublicModelsData {10 models: PolyModel[];11 ctx: BadgeContext;12 /** False when the registry could not be read (DB down) — pages render an honest empty state. */13 ok: boolean;14}1516/** Registry snapshot for the public SEO pages (no auth, no user data). Memoized per request via React `cache`. */17export const getPublicModels = cache(async (): Promise<PublicModelsData> => {18 const now = Date.now();19 try {20 const models = await listRegistryModels();21 return { models, ctx: buildBadgeContext(models, now), ok: true };22 } catch (e) {23 log.warn("public models: registry unavailable", { error: (e as Error).message });24 return { models: [], ctx: buildBadgeContext([], now), ok: false };25 }26});2728/** Best active model per native provider (highest sort weight). */29export function flagshipModels(models: PolyModel[], limit = 6): PolyModel[] {30 const seen = new Set<string>();31 const out: PolyModel[] = [];32 for (const m of [...models].filter((m) => m.status === "active" && m.provider !== "openrouter").sort((a, b) => sortWeightOf(b) - sortWeightOf(a))) {33 if (seen.has(m.provider)) continue;34 seen.add(m.provider);35 out.push(m);36 if (out.length >= limit) break;37 }38 return out;39}4041/** Pairwise comparison slugs between flagships (for "Popular comparisons"). */42export function popularComparisons(models: PolyModel[], limit = 8): { slug: string; a: PolyModel; b: PolyModel }[] {43 const flags = flagshipModels(models, 5);44 const out: { slug: string; a: PolyModel; b: PolyModel }[] = [];45 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] });46 return out.slice(0, limit);47}48