import { ExternalLink } from 'lucide-react'; import Link from 'next/link'; import type { ReactNode } from 'react'; import { ChangeRow } from '@/components/changes/change-row'; import { EntityBadge, ImportanceMark, OpennessBadge } from '@/components/ui/badges'; import { DataTable, EmptyRow, Td, Th } from '@/components/ui/data-table'; import { EntityLink } from '@/components/ui/entity'; import { Note, Section } from '@/components/ui/section'; import { EmptyState } from '@/components/ui/unavailable'; import { fmtDate, fmtDeltaPct, fmtInt, fmtParams, fmtScore, fmtTokens, fmtUsdPerM, hostOf, num } from '@/lib/format'; import { routes } from '@/lib/site'; import type { ChangeEvent, DiffPayload11, EntitySummary } from '@/lib/types'; /* Diff sections (server). Dense rows with typed deltas; every row keeps its source link and a History link. */ export function Capped({ shown, total, what }: { shown: number; total: number | null; what: string }) { if (total === null || total <= shown) return null; return Showing the first {fmtInt(shown)} of {fmtInt(total)} {what}. Narrow the scope or the dates to see everything.; } function SectionTitle({ title, n }: { title: string; n: number | null }) { return ( <> {title} {fmtInt(n)} ); } function Src({ url }: { url: string | null }) { if (!url) return —; return ( {hostOf(url) ?? 'source'} ); } function When({ e }: { e: ChangeEvent }) { const at = e.occurred_at ?? e.effective_at ?? e.observed_at; return ( ); } /** New entities of one type as a dense table. */ export function NewEntitiesSection({ id, title, items, total, empty, type }: { id: string; title: string; items: EntitySummary[]; total: number | null; empty: string; type: 'model' | 'paper' | 'other' }) { return (
}> {items.length === 0 ? ( ) : ( <> {type === 'paper' ? 'Paper' : type === 'model' ? 'Model' : 'Entity'} {type === 'other' && Type} Organization {type === 'model' && ( <> Params Context Openness Released )} {type === 'paper' && Published} First seen {items.map((e) => { const a = e.attributes ?? {}; return ( {type === 'other' && ( )} {e.organization ? {e.organization.name} : —} {type === 'model' && ( <> {fmtParams(a.parameter_count)} {num(a.context_length) === null ? '—' : fmtTokens(a.context_length)} {typeof a.openness === 'string' ? : —} {typeof a.release_date === 'string' ? fmtDate(a.release_date) : '—'} )} {type === 'paper' && {typeof a.published_at === 'string' ? fmtDate(a.published_at) : '—'}} {fmtDate(e.first_seen_at)} ); })} )}
); } type PriceObj = { input_per_mtok?: unknown; output_per_mtok?: unknown }; function priceOf(v: unknown): PriceObj | null { return v && typeof v === 'object' ? (v as PriceObj) : null; } function DeltaCell({ from, to, fmt }: { from: unknown; to: unknown; fmt: (v: unknown) => string }) { const a = num(from); const b = num(to); const pct = fmtDeltaPct(a, b); return ( {a === null ? '—' : fmt(a)} → {b === null ? '—' : fmt(b)} {pct && {pct}} ); } /** PRICE_CHANGED / PROVIDER_LISTED rows: old/new are `{ input_per_mtok, output_per_mtok }` objects. */ export function PriceChangesSection({ id, title, items, total, empty }: { id: string; title: string; items: ChangeEvent[]; total: number | null; empty: string }) { return (
}> {items.length === 0 ? ( ) : ( <> Date Model Provider Input / 1M Output / 1M Source {items.map((e) => { const o = priceOf(e.old_value); const n = priceOf(e.new_value); const provider = typeof e.meta?.provider === 'string' ? e.meta.provider : e.entity?.entity_type === 'provider' ? e.entity.name : null; return ( {e.entity ? : {e.summary}} {provider ?? '—'} {o || n ? fmtUsdPerM(v)} /> : '—'} {o || n ? fmtUsdPerM(v)} /> : '—'} ); })} )}
); } /** CONTEXT_CHANGED (and other numeric property events): old → new with %. */ export function ContextChangesSection({ id, title, items, total, empty }: { id: string; title: string; items: ChangeEvent[]; total: number | null; empty: string }) { return (
}> {items.length === 0 ? ( ) : ( <> Date Model Organization Context window Source History {items.map((e) => ( {e.entity ? : {e.summary}} {e.entity?.organization?.name ?? '—'} `${fmtTokens(v)} tokens`} /> {e.entity ? claims → : '—'} ))} )}
); } export function LeadersSection({ id, items, a, b }: { id: string; items: NonNullable; a: string; b: string }) { return (
} lede={`Benchmarks whose primary-group leader (computed from results observed by each date) differs between ${fmtDate(a)} and ${fmtDate(b)}.`}> {items.length === 0 ? ( ) : ( Benchmark Leader at {fmtDate(a)} Score Leader at {fmtDate(b)} Score Metric {items.map((l) => ( {l.benchmark.name} {l.benchmark.category && {l.benchmark.category}} {l.at_a ? : no result observed yet} {l.at_a ? fmtScore(l.at_a.score) : '—'} {l.at_b ? : —} {l.at_b ? fmtScore(l.at_b.score) : '—'} {l.at_b?.metric ?? l.at_a?.metric ?? '—'}{l.at_b?.trust_level ? {l.at_b.trust_level} : null} ))} )}
); } /** Generic event list section (property / provider / hardware changes). */ export function EventsSection({ id, title, items, total, empty, lede }: { id: string; title: string; items: ChangeEvent[]; total: number | null; empty: string; lede?: ReactNode }) { return (
} lede={lede}> {items.length === 0 ? ( ) : ( <>
    {items.map((e) => ( ))}
)}
); } export function EntitiesSection({ id, title, items, total, empty }: { id: string; title: string; items: EntitySummary[]; total: number | null; empty: string }) { return (
}> {items.length === 0 ? ( ) : ( <>
    {items.map((e) => (
  • {e.organization && {e.organization.name}}
  • ))}
)}
); }