HTML 77.2%
TypeScript 10.5%
Python 9.6%
JavaScript 2.5%
1import type { Metadata } from 'next';2import Link from 'next/link';3import { Sparkline } from '@/components/charts';4import { ChangeRow } from '@/components/changes/change-row';5import { Methodology, TrustChip } from '@/components/intelligence/bits';6import { DataStrip, type StripItem } from '@/components/layout/terminal';7import { PriceMovers } from '@/components/prices/movers';8import { ChipRow } from '@/components/timeline/chip-row';9import { DataTable, EmptyRow, Td, Th } from '@/components/ui/data-table';10import { EntityLink } from '@/components/ui/entity';11import { Container, Note, PageHeader, Section } from '@/components/ui/section';12import { EmptyState, Unavailable } from '@/components/ui/unavailable';13import { api, intel, safe } from '@/lib/api';14import { fmtDate, fmtDateTime, fmtInt, fmtScore, fmtTokens, num } from '@/lib/format';15import { routes, SITE_NAME, SITE_URL } from '@/lib/site';16import type { ChangeEvent, EntitySummary, PulseLeaderItem } from '@/lib/types';1718export const revalidate = 120;1920const WINDOWS = [7, 30, 90];21type SP = Record<string, string | undefined>;22const pickDays = (sp: SP) => (WINDOWS.includes(Number(sp.days)) ? Number(sp.days) : 7);2324const LABELS: Record<string, string> = {25 new_models: 'New models',26 new_open_weight_models: 'New open-weight models',27 new_artifacts: 'New artifacts',28 new_papers: 'New papers',29 provider_listings: 'Provider listings',30 provider_delistings: 'Delistings',31 price_changes: 'Price changes',32 new_models_1m_context: 'New ≥ 1M-context models',33 new_benchmark_leaders: 'New benchmark leaders',34 documents_changed: 'Documents changed',35 sources_observed: 'Sources observed',36 events_total: 'Events total',37};38const HREF: Record<string, (days: number) => string> = {39 new_models: () => `${routes.changes()}?type=NEW_MODEL`,40 new_open_weight_models: () => `${routes.open()}`,41 new_papers: () => `${routes.papers()}?sort=published`,42 provider_listings: () => `${routes.changes()}?type=PROVIDER_LISTED`,43 provider_delistings: () => `${routes.changes()}?type=PROVIDER_DELISTED`,44 price_changes: () => `${routes.prices()}`,45 new_benchmark_leaders: () => routes.benchmarks(),46 documents_changed: () => `${routes.changes()}?type=DOCUMENT_CHANGED&include_documents=1`,47 sources_observed: () => routes.sources(),48 events_total: () => routes.changes(),49};50/** stats/history series key per counter (only where the history payload carries one). */51const HISTORY_KEY: Record<string, (c: Record<string, unknown>) => number | null> = {52 new_models: (c) => num((c.entities as Record<string, unknown> | undefined)?.model),53 new_papers: (c) => num((c.entities as Record<string, unknown> | undefined)?.paper),54 price_changes: (c) => num(c.prices_current),55 events_total: (c) => num(c.change_events),56 documents_changed: (c) => num(c.documents),57 sources_observed: (c) => num(c.sources),58};5960const TITLE = 'Ecosystem Pulse — what happened in AI this week';61const DESC = 'Deterministic counters over events that occurred in the window (7, 30 or 90 days) and are not back-filled history: new models, open-weight releases, artifacts, papers, provider listings and delistings, price changes, new 1M-context models, new benchmark leaders, documents and sources observed — each with its definition.';62export async function generateMetadata({ searchParams }: { searchParams: Promise<SP> }): Promise<Metadata> {63 const days = pickDays(await searchParams);64 const title = days === 7 ? TITLE : `Ecosystem Pulse — the last ${days} days in AI`;65 return { title, description: DESC, alternates: { canonical: routes.pulse() }, openGraph: { title: `${title} | ${SITE_NAME}`, description: DESC, url: `${SITE_URL}${routes.pulse()}`, type: 'website', siteName: SITE_NAME }, twitter: { card: 'summary_large_image', title, description: DESC }, robots: days !== 7 ? { index: false, follow: true } : undefined };66}6768const isLeader = (x: unknown): x is PulseLeaderItem => !!x && typeof x === 'object' && 'benchmark' in (x as object);69const isEvent = (x: unknown): x is ChangeEvent => !!x && typeof x === 'object' && 'event_type' in (x as object);70const isModel = (x: unknown): x is EntitySummary => !!x && typeof x === 'object' && 'entity_type' in (x as object) && 'slug' in (x as object);7172export default async function PulsePage({ searchParams }: { searchParams: Promise<SP> }) {73 const days = pickDays(await searchParams);74 const since = new Date(Date.now() - days * 86400000).toISOString().slice(0, 10);75 const [pulse, history, priceFallback, ctxFallback] = await Promise.all([safe(intel.pulse(days)), safe(api.statsHistory(Math.max(days, 14))), safe(api.changes({ type: 'PRICE_CHANGED', since, limit: 30 })), safe(api.models({ min_context: 1_000_000, sort: 'release', limit: 12 }))]);76 const href = (d: number) => (d === 7 ? routes.pulse() : `${routes.pulse()}?days=${d}`);7778 if (!pulse) {79 return (80 <Container wide>81 <PageHeader eyebrow="Ecosystem pulse" title="Pulse" lede="Deterministic counters over what occurred in the window." />82 <Unavailable what="Pulse" reason="GET /pulse did not answer. Counters are never cached or hardcoded." />83 </Container>84 );85 }86 const counters = pulse.counters ?? {};87 const hist = history?.items ?? [];88 const spark = (key: string): number[] => {89 const f = HISTORY_KEY[key];90 if (!f) return [];91 return hist.map((h) => f(h.counts as Record<string, unknown>)).filter((v): v is number => v !== null);92 };93 const strip: StripItem[] = Object.entries(counters).map(([key, c]) => {94 const vals = spark(key);95 return {96 label: LABELS[key] ?? key.replace(/_/g, ' '),97 value: fmtInt(c.value),98 definition: c.definition,99 href: HREF[key]?.(days),100 hint: vals.length >= 2 ? <Sparkline values={vals} width={64} height={16} stroke="var(--accent)" title={`${LABELS[key] ?? key} · daily stats history`} /> : num(c.median_percent) !== null ? `median ${fmtScore(c.median_percent)} %` : undefined,101 };102 });103 const leaders = (counters.new_benchmark_leaders?.items ?? []).filter(isLeader);104 const priceItems = (counters.price_changes?.items ?? []).filter(isEvent);105 const priceRows = priceItems.length ? priceItems : (priceFallback?.items ?? []);106 const ctxItems = (counters.new_models_1m_context?.items ?? []);107 const ctxModels: EntitySummary[] = ctxItems.filter(isModel);108 const ctxEvents: ChangeEvent[] = ctxItems.filter(isEvent);109 const historyDays = hist.length;110 const ld = { '@context': 'https://schema.org', '@type': 'Dataset', name: `AI Atlas Pulse · ${days} days`, description: DESC, url: `${SITE_URL}${routes.pulse()}`, temporalCoverage: `${pulse.since}/${pulse.until}`, creator: { '@type': 'Organization', name: SITE_NAME, url: SITE_URL } };111112 return (113 <Container wide>114 <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(ld) }} />115 <PageHeader eyebrow="Ecosystem pulse" title={`The last ${days} days in AI`} lede="Deterministic counters over events that occurred in the window — historical backfill excluded, so a re-crawl of old pages never inflates them. Hover a label for how each one is counted." aside={<p className="tnum text-sm text-ink-3" title={`${pulse.since} → ${pulse.until}`}>{fmtDate(pulse.since)} → {fmtDateTime(pulse.until)}</p>}>116 <div className="mt-6">117 <p className="eyebrow mb-1.5">Window</p>118 <ChipRow label="Window" items={WINDOWS.map((d) => ({ href: href(d), label: `${d} days`, active: days === d }))} />119 </div>120 </PageHeader>121122 <DataStrip items={strip} />123 <p className="tnum mt-2 text-xs text-ink-3">124 All counters use <span className="mono">is_backfill = false</span> and <span className="mono">occurred_at</span> inside the window. Sparklines show the daily stats history where a series exists ({historyDays} day{historyDays === 1 ? '' : 's'} recorded so far{historyDays < 2 ? ' — a line needs two' : ''}).125 </p>126 <Methodology text={pulse.note} className="mt-1" />127128 {/* --------------------------------------------------------------------------------------------- leaders */}129 <Section eyebrow="Benchmark leadership" title={`New benchmark leaders · ${fmtInt(counters.new_benchmark_leaders?.value)}`} lede={counters.new_benchmark_leaders?.definition} action={{ href: routes.benchmarks(), label: 'All leaderboards' }}>130 {leaders.length === 0 ? (131 <EmptyState title="No leadership change in the window">The primary-group leader of every benchmark is unchanged over these {days} days.</EmptyState>132 ) : (133 <div className="md:overflow-x-auto">134 <DataTable caption="New benchmark leaders">135 <thead>136 <tr>137 <Th>Benchmark</Th>138 <Th>Current leader</Th>139 <Th num>Score</Th>140 <Th>Previous leader</Th>141 <Th>Group</Th>142 <Th>Trust</Th>143 </tr>144 </thead>145 <tbody>146 {leaders.map((l) => (147 <tr key={l.benchmark.id}>148 <Td primary>149 <Link href={routes.benchmark(l.benchmark.slug)} className="text-ink hover:text-accent hover:underline">150 {l.benchmark.name}151 </Link>152 </Td>153 <Td label="Current leader">154 {l.current ? (155 <>156 <Link href={routes.entity({ entity_type: l.current.model.entity_type ?? 'model', slug: l.current.model.slug })} className="font-medium text-ink hover:text-accent hover:underline">157 {l.current.model.name}158 </Link>159 {l.current.model.organization && <span className="ml-1.5 text-xs text-ink-3">{l.current.model.organization.name}</span>}160 </>161 ) : (162 '—'163 )}164 </Td>165 <Td num label="Score" className="tnum font-medium">{l.current ? `${fmtScore(l.current.score)}${l.current.metric ? ` ${l.current.metric}` : ''}` : '—'}</Td>166 <Td label="Previous leader" className="text-ink-2">167 {l.previous ? (168 <>169 <Link href={routes.entity({ entity_type: l.previous.model.entity_type ?? 'model', slug: l.previous.model.slug })} className="hover:text-accent">170 {l.previous.model.name}171 </Link>{' '}172 <span className="tnum text-xs text-ink-3">{fmtScore(l.previous.score)}</span>173 </>174 ) : (175 <span className="text-ink-3">first leader recorded</span>176 )}177 </Td>178 <Td label="Group" className="mono text-[11px] text-ink-3">179 {l.current?.group_label ?? '—'}180 {num(l.current?.n_models) !== null && <span> · n={fmtInt(l.current?.n_models)}</span>}181 </Td>182 <Td label="Trust"><TrustChip level={l.current?.trust_level} /></Td>183 </tr>184 ))}185 </tbody>186 </DataTable>187 </div>188 )}189 </Section>190191 {/* ---------------------------------------------------------------------------------------------- prices */}192 <Section eyebrow="Prices" title={`Price changes · ${fmtInt(counters.price_changes?.value)}${num(counters.price_changes?.median_percent) !== null ? ` · median ${fmtScore(counters.price_changes?.median_percent)} %` : ''}`} lede={counters.price_changes?.definition} action={{ href: routes.prices(), label: 'Price terminal' }}>193 {!priceItems.length && priceRows.length > 0 && <Note className="mb-2">The pulse returns the count only; the rows below are PRICE_CHANGED events since {fmtDate(since)} from the change feed (same window, same backfill rule).</Note>}194 <PriceMovers movers={priceRows} limit={30} />195 </Section>196197 {/* --------------------------------------------------------------------------------------------- context */}198 <Section eyebrow="Long context" title={`New ≥ 1M-context models · ${fmtInt(counters.new_models_1m_context?.value)}`} lede={counters.new_models_1m_context?.definition}>199 {ctxModels.length > 0 ? (200 <ul className="border-t border-rule">201 {ctxModels.map((m) => (202 <li key={m.id} className="flex flex-wrap items-baseline gap-x-3 border-b border-rule py-2.5 text-sm">203 <EntityLink e={m} className="font-medium" />204 {m.organization && <span className="text-xs text-ink-3">{m.organization.name}</span>}205 <span className="tnum ml-auto text-xs text-ink-2">{fmtTokens(m.attributes?.context_length)} · {typeof m.attributes?.release_date === 'string' ? fmtDate(m.attributes.release_date) : '—'}</span>206 </li>207 ))}208 </ul>209 ) : ctxEvents.length > 0 ? (210 <ul className="border-t border-rule">{ctxEvents.map((e) => <ChangeRow key={e.id} e={e} showDate live={false} />)}</ul>211 ) : num(counters.new_models_1m_context?.value) === 0 ? (212 <>213 <EmptyState title={`No new model with a ≥ 1M-token context in the last ${days} days`}>214 {ctxFallback?.items.length ? <>For reference, the most recently released models with a sourced context of at least 1M tokens (any date):</> : null}215 </EmptyState>216 {ctxFallback?.items.length ? (217 <ul className="border-b border-rule">218 {ctxFallback.items.slice(0, 8).map((m) => (219 <li key={m.id} className="flex flex-wrap items-baseline gap-x-3 border-b border-rule py-2 text-sm last:border-b-0">220 <EntityLink e={m} />221 {m.organization && <span className="text-xs text-ink-3">{m.organization.name}</span>}222 <span className="tnum ml-auto text-xs text-ink-2">{fmtTokens(m.attributes?.context_length)} · {typeof m.attributes?.release_date === 'string' ? fmtDate(m.attributes.release_date) : 'release date unavailable'}</span>223 </li>224 ))}225 </ul>226 ) : null}227 </>228 ) : (229 <EmptyState title={`${fmtInt(counters.new_models_1m_context?.value)} new ≥ 1M-context models`}>The pulse returns the count only; the list is not part of the API response yet.</EmptyState>230 )}231 </Section>232233 <Section eyebrow="Reading the pulse" title="Definitions" hairline>234 <dl className="grid gap-x-8 gap-y-3 md:grid-cols-2">235 {Object.entries(counters).map(([k, c]) => (236 <div key={k} className="border-b border-rule pb-2">237 <dt className="flex items-baseline justify-between gap-3 text-sm font-medium text-ink">238 {LABELS[k] ?? k.replace(/_/g, ' ')} <span className="tnum text-ink-2">{fmtInt(c.value)}</span>239 </dt>240 <dd className="mt-0.5 text-xs leading-relaxed text-ink-3">{c.definition}</dd>241 </div>242 ))}243 </dl>244 <Note className="mt-3">245 Source: <Link href="/developers" className="link">GET /pulse?days={days}</Link>. Nothing on this page is a projection.246 </Note>247 </Section>248 </Container>249 );250}251