import { ExternalLink, GitFork } from 'lucide-react'; import Link from 'next/link'; import { ChangeRow } from '@/components/changes/change-row'; import { CompareButton } from '@/components/compare/compare-button'; import { Identity, SourcesTable } from '@/components/entity/blocks'; import { DataStrip, SectionNav } from '@/components/layout/terminal'; import { ViewBeacon } from '@/components/layout/view-beacon'; import { BreadcrumbLd, Breadcrumbs } from '@/components/meta/breadcrumb-ld'; import { WatchButton } from '@/components/watchlist/watch-button'; import { Chip, EntityBadge, OpennessBadge, StatusBadge } from '@/components/ui/badges'; import { DataTable, EmptyRow, Td, Th } from '@/components/ui/data-table'; import { EntityLink, QualityMark } from '@/components/ui/entity'; import { Hint } from '@/components/ui/hint'; import { KeyValue } from '@/components/ui/key-value'; import { Container, Note, Section } from '@/components/ui/section'; import { EmptyState } from '@/components/ui/unavailable'; import { api, apiD1, apiD3, safe } from '@/lib/api'; import { fmtAgo, fmtDate, fmtInt, fmtParams, fmtTokens, num } from '@/lib/format'; import { PROSE_KEYS, routes, SITE_NAME, SITE_URL, typeLabel } from '@/lib/site'; import type { ChangeEvent, EntityDetail, EntitySummary, FamilyRow } from '@/lib/types'; /* Organization page 3.0 (server, async): footprint strip → models grouped by family → families → papers → researchers → providers operated → repositories/frameworks → timeline split CORPORATE NEWS vs MODEL EVENTS → sources. Counts come from the listing APIs (`/models?org=`, `/families?org=`, `/papers?org=`, `/explore/researcher?org=`) and the detail relations; what the API does not expose per organization (datasets, benchmarks) is shown as "—" with a definition. */ const ORG_TYPES = ['company', 'organization', 'lab', 'university']; const CORPORATE = new Set(['ANNOUNCEMENT', 'NEW_COMPANY', 'NEW_ORGANIZATION', 'NEW_LAB', 'NEW_UNIVERSITY', 'PROPERTY_CHANGED']); function relItems(d: EntityDetail, types: string[], predicates?: string[]): EntitySummary[] { const out: EntitySummary[] = []; const seen = new Set(); for (const g of d.relations ?? []) { if (predicates && !predicates.includes(g.predicate)) continue; for (const it of g.items) { if (!types.includes(it.entity_type) || seen.has(it.id)) continue; seen.add(it.id); out.push(it); } } return out; } type ModelRow = EntitySummary & { family?: { id: string; slug: string; name: string } | null }; function ModelsByFamily({ items, total, org }: { items: ModelRow[]; total: number; org: string }) { if (!items.length) return Models are attributed through a stated developer relation or an official model id.; const groups = new Map(); for (const m of items) { const fam = m.family ?? null; const label = fam?.name ?? (typeof m.attributes?.family === 'string' ? (m.attributes.family as string) : 'No family'); const key = fam?.slug ?? `label:${label}`; (groups.get(key) ?? groups.set(key, { label, href: fam ? routes.family(fam.slug) : null, items: [] }).get(key)!).items.push(m); } const ordered = [...groups.values()].sort((a, b) => b.items.length - a.items.length || a.label.localeCompare(b.label)); return ( <> Model Params Context Openness Status Released Quality {ordered.map((g) => ( ))} {total > items.length && ( Showing {fmtInt(items.length)} of {fmtInt(total)} — all models by this organization → )} ); } function FamilyRows({ g }: { g: { label: string; href: string | null; items: ModelRow[] } }) { return ( <> {g.href ? ( {g.label} ) : ( g.label )} {fmtInt(g.items.length)} {g.items.map((m) => { const a = m.attributes ?? {}; return ( {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) : '—'} ); })} ); } function FamiliesTable({ items }: { items: FamilyRow[] }) { if (!items.length) return

No family recorded for this organization.

; return ( Family Models First release Last release Modalities Canonical {items.map((f) => ( {f.canonical ? ( {f.name} ) : ( {f.name} )} {fmtInt(f.model_count)} {fmtDate(f.first_release)} {fmtDate(f.last_release)} {f.modalities?.length ? f.modalities.join(', ') : '—'} {f.canonical ? entity : legacy label} ))} ); } function List({ items, empty }: { items: EntitySummary[]; empty: React.ReactNode }) { if (!items.length) return

{empty}

; return (
    {items.map((e) => (
  • {typeof e.attributes?.published_at === 'string' && {fmtDate(e.attributes.published_at as string)}}
  • ))}
); } export async function OrganizationPage({ d, canonical }: { d: EntityDetail; canonical: string }) { const a = d.attributes ?? {}; const [models, families, papers, researchers, news, tl] = await Promise.all([ safe(api.models({ org: d.slug, limit: 200, sort: 'release' })), safe(apiD1.families({ org: d.slug, limit: 50, sort: 'models' })), safe(api.papers({ org: d.slug, limit: 30, sort: 'published' })), safe(api.explore('researcher', { org: d.slug, limit: 30 })), safe(apiD3.changes({ entity: d.slug, type: 'ANNOUNCEMENT', include_backfill: 1, limit: 30 })), safe(apiD3.entityTimeline(d.slug, { include_backfill: 1, limit: 100 })), ]); const modelItems = (models?.items ?? []) as ModelRow[]; const modelTotal = num(models?.total) ?? num(d.models?.total) ?? modelItems.length; const famItems = families?.items ?? []; const paperItems = papers?.items ?? d.papers ?? []; const researcherItems = (researchers?.items ?? []).filter((r) => r.entity_type === 'researcher'); const withIds = researcherItems.filter((r) => (r.counts?.claims ?? 0) > 0 || (r.organization && r.organization.slug === d.slug)); const providers = relItems(d, ['provider'], ['operates', 'owns']); const repos = [...(d.repositories ?? []), ...relItems(d, ['repository', 'framework', 'library'])].filter((x, i, arr) => arr.findIndex((y) => y.id === x.id) === i); const datasets = relItems(d, ['dataset']); const benchmarks = relItems(d, ['benchmark']); const newsItems: ChangeEvent[] = news?.items ?? []; const modelEvents: ChangeEvent[] = (tl?.items ?? []).filter((e) => !CORPORATE.has(e.event_type) && e.event_type !== 'ENTITY_MERGED'); const corporateFromTimeline: ChangeEvent[] = (tl?.items ?? []).filter((e) => CORPORATE.has(e.event_type) && !newsItems.some((n) => n.id === e.id)); const corporate = [...newsItems, ...corporateFromTimeline].sort((x, y) => ((y.occurred_at ?? y.observed_at) < (x.occurred_at ?? x.observed_at) ? -1 : 1)); const link = ['website', 'official_url'].map((k) => a[k]).find((v): v is string => typeof v === 'string' && /^https?:\/\//.test(v)) ?? null; const crumbs = [{ name: SITE_NAME, href: '/' }, { name: 'Organizations', href: '/companies' }, { name: d.name, href: canonical }]; const ld = { '@context': 'https://schema.org', '@type': 'Organization', name: d.name, url: `${SITE_URL}${canonical}`, description: d.description ?? undefined, alternateName: d.aliases?.length ? d.aliases : undefined, foundingDate: a.founded ? String(a.founded) : undefined, sameAs: link ? [link] : undefined, location: typeof a.headquarters === 'string' ? a.headquarters : undefined }; const specRows = Object.keys(a) .filter((k) => !PROSE_KEYS.has(k) && !['founders', 'leadership'].includes(k)) .map((k) => ({ key: k, raw: a[k] })); const sections = [ { id: 'models', label: 'Models' }, { id: 'families', label: 'Families' }, { id: 'papers', label: 'Papers' }, { id: 'researchers', label: 'Researchers' }, { id: 'providers', label: 'Providers' }, { id: 'repositories', label: 'Code' }, { id: 'news', label: 'Corporate news' }, { id: 'model-events', label: 'Model events' }, { id: 'sources', label: 'Sources' }, ]; return (