import { Chip, TierBadge } from '@/components/ui/badges';
import { DataTable, Td, Th } from '@/components/ui/data-table';
import { EntityLink } from '@/components/ui/entity';
import { Note } from '@/components/ui/section';
import { cn } from '@/lib/cn';
import { fmtAgo, fmtDate, fmtScore, fmtUsdPerM, fmtValue, num } from '@/lib/format';
import { routes } from '@/lib/site';
import type { BenchmarkResult, CompareDimension, ComparePayload, Price, ProvenanceEntry } from '@/lib/types';
import { CompareButton } from './compare-button';
/* ------------------------------------------------------------------------------------------------------ helpers */
const PRICE_KEYS = new Set(['best_input_per_mtok', 'best_output_per_mtok', 'min_input_per_mtok', 'min_output_per_mtok']);
/** Numeric dimensions where lower is better. */
function lowerIsBetter(key: string): boolean {
return PRICE_KEYS.has(key) || /tdp|price|latency/.test(key);
}
function host(url: string | null | undefined): string | null {
if (!url) return null;
try {
return new URL(url).hostname.replace(/^www\./, '');
} catch {
return null;
}
}
/** Compact per-cell provenance: T1 · host · 3 h ago (full text in title). */
function CellProvenance({ p }: { p: ProvenanceEntry }) {
const h = p.source_name ?? host(p.url) ?? 'source';
return (
{p.url ? (
{h}
) : (
{h}
)}
· {fmtAgo(p.observed_at)}
);
}
function CellValue({ v, dim }: { v: unknown; dim: CompareDimension }) {
if (v === null || v === undefined || v === '' || (Array.isArray(v) && v.length === 0)) return Unavailable;
switch (dim.kind) {
case 'date':
return <>{fmtDate(String(v))}>;
case 'bool':
return <>{v ? 'Yes' : 'No'}>;
case 'list': {
const arr = Array.isArray(v) ? v : [v];
return (
{arr.map((x, i) => (
{typeof x === 'object' && x ? JSON.stringify(x) : String(x)}
))}
);
}
case 'number':
if (PRICE_KEYS.has(dim.key)) return {fmtUsdPerM(v)};
return <>{fmtValue(v, dim.key)}>;
default:
return <>{typeof v === 'string' ? v : fmtValue(v, dim.key)}>;
}
}
const STICKY = 'sticky left-0 z-10 bg-canvas';
/** First-column width: table layout ignores max-width, so set width + min-width explicitly. */
const FIRST = 'w-[9rem] min-w-[9rem] md:w-[12rem] md:min-w-[12rem]';
/** `.table-scroll td { white-space: nowrap }` out-specifies utilities — wrap the first column inline. */
const WRAP = { whiteSpace: 'normal' } as const;
/** Horizontal scroll wrapper without the negative page margins (so the sticky column pins at the very left edge). */
function ScrollTable({ children, caption, className }: { children: React.ReactNode; caption: string; className?: string }) {
return (
{children}
);
}
function EntityHead({ e }: { e: ComparePayload['items'][number]['entity'] }) {
return (
{e.organization && {e.organization.name}}
);
}
/* ------------------------------------------------------------------------------------------------------ matrix */
/** Dimension × entity matrix: sticky first column, horizontal scroll, kind-aware formatting, per-cell provenance. */
export function CompareMatrix({ res }: { res: ComparePayload }) {
return (
<>
| Dimension |
{res.items.map((it) => (
|
))}
{res.dimensions.map((dim) => {
const nums = res.items.map((it) => num(it.values[dim.key]));
const present = nums.filter((n): n is number => n !== null);
const best = dim.kind === 'number' && present.length > 1 ? (lowerIsBetter(dim.key) ? Math.min(...present) : Math.max(...present)) : null;
return (
|
{dim.label}
{dim.unit && {dim.unit}}
|
{res.items.map((it, i) => {
const v = it.values[dim.key];
const p = it.provenance?.[dim.key];
const isBest = best !== null && nums[i] === best;
return (
{p && }
|
);
})}
);
})}
Bold marks the best number in a row (highest, or lowest for prices); it is not a verdict. Each value carries its own source and tier; hover a cell for the observation date. Missing values are shown as unavailable, never estimated.
>
);
}
/* ------------------------------------------------------------------------------------------------------ shared benchmarks */
function configSummary(c: Record): string {
return Object.entries(c ?? {})
.filter(([, v]) => v !== null && v !== undefined && v !== '')
.slice(0, 4)
.map(([k, v]) => `${k}=${typeof v === 'object' ? JSON.stringify(v) : String(v)}`)
.join(' · ');
}
/** Benchmarks with a current result for every compared model (best result per model per benchmark). */
export function SharedBenchmarks({ res }: { res: ComparePayload }) {
const perItem = res.items.map((it) => {
const m = new Map();
for (const r of it.results ?? []) {
const prev = m.get(r.benchmark.slug);
if (!prev || (r.higher_is_better === false ? r.score < prev.score : r.score > prev.score)) m.set(r.benchmark.slug, r);
}
return m;
});
const first = perItem[0];
const shared = first ? [...first.values()].filter((r) => perItem.every((m) => m.has(r.benchmark.slug))) : [];
const anyResults = res.items.some((it) => (it.results?.length ?? 0) > 0);
if (shared.length === 0)
return (
{anyResults ? 'No benchmark has a published result for every compared model.' : 'No benchmark results recorded for these models.'} Per-model results are on each model page (Benchmarks tab).
);
shared.sort((a, b) => a.benchmark.name.localeCompare(b.benchmark.name));
return (
<>
| Benchmark |
{res.items.map((it) => (
|
))}
{shared.map((row) => {
const cells = perItem.map((m) => m.get(row.benchmark.slug) ?? null);
const scores = cells.map((c) => (c ? c.score : null)).filter((s): s is number => s !== null);
const best = scores.length > 1 ? (row.higher_is_better === false ? Math.min(...scores) : Math.max(...scores)) : null;
return (
|
{row.metric ?? '—'}
{row.higher_is_better === false ? ' · lower is better' : ''}
|
{cells.map((c, i) => (
{c ? (
<>
{fmtScore(c.score)}
{c.unit === '%' ? '%' : c.unit ? {c.unit} : ''}
{configSummary(c.config) || (c.evaluated_at ? fmtDate(c.evaluated_at) : '')}
>
) : (
—
)}
|
))}
);
})}
Only benchmarks with a result for every compared model are shown (best current result per model). Configurations may differ — hover a score for its config; scores under different configs are not strictly comparable.
>
);
}
/* ------------------------------------------------------------------------------------------------------ prices */
type Best = { input: number | null; output: number | null; observed: string; url: string | null; tier: number };
/** Provider × entity: cheapest current input / output per provider for each compared model. */
export function ComparePrices({ res }: { res: ComparePayload }) {
const providers = new Map();
const perItem = res.items.map((it) => {
const m = new Map();
for (const p of it.prices ?? []) {
providers.set(p.provider.slug, p.provider);
const cur = m.get(p.provider.slug) ?? { input: null, output: null, observed: p.observed_at, url: p.source_url, tier: p.tier };
const inp = num(p.input_per_mtok);
const out = num(p.output_per_mtok);
if (inp !== null && (cur.input === null || inp < cur.input)) cur.input = inp;
if (out !== null && (cur.output === null || out < cur.output)) cur.output = out;
if (p.observed_at > cur.observed) cur.observed = p.observed_at;
m.set(p.provider.slug, cur);
}
return m;
});
if (providers.size === 0) return No current prices recorded for these models.
;
const rows = [...providers.values()].sort((a, b) => a.name.localeCompare(b.name));
const bestOverall = res.items.map((_, i) => {
let best: number | null = null;
for (const b of perItem[i]!.values()) if (b.input !== null && (best === null || b.input < best)) best = b.input;
return best;
});
return (
<>
| Provider |
{res.items.map((it) => (
in / out per 1M
|
))}
{rows.map((prov) => (
|
|
{perItem.map((m, i) => {
const b = m.get(prov.slug);
if (!b) return — | ;
const cheapest = bestOverall[i] !== null && b.input === bestOverall[i];
return (
{fmtUsdPerM(b.input)} / {fmtUsdPerM(b.output)}
{b.url ? (
{host(b.url)}
) : null}
· {fmtAgo(b.observed)}
|
);
})}
))}
Cheapest current input / output price of each provider for each model, as published on the provider's pricing page (USD per 1M tokens). Bold = the model's cheapest provider. Full tables and history on each model page, or the price index.
>
);
}