SPB Git forge

spb/ai-atlas

Public
41commits 1branches 0releases
4.6 MBsize
maindefault branch
12 days agolast push
HTML 77.2% TypeScript 10.5% Python 9.6% JavaScript 2.5%
6.0 KB · 83 lines tsx
Raw Blame History
1import type { Metadata } from 'next';2import Link from 'next/link';3import { Dash, IntelListing, list, str } from '@/components/intelligence/listing-table';4import { Chip, EntityBadge } from '@/components/ui/badges';5import { EntityLink, QualityMark } from '@/components/ui/entity';6import { api, safe } from '@/lib/api';7import { fmtDate } from '@/lib/format';8import { routes, SITE_NAME, SITE_URL } from '@/lib/site';9import type { EntitySummary } from '@/lib/types';1011export const metadata: Metadata = { title: 'AI agents — developer, kind, underlying models, platform, licence', description: 'Agents recorded in the atlas: developer, agent kind, the models they run on (relations), platform, repository, licence and release date — from official sources only.', alternates: { canonical: routes.agents() }, openGraph: { title: `AI agents | ${SITE_NAME}`, url: `${SITE_URL}${routes.agents()}`, siteName: SITE_NAME } };12export const revalidate = 300;1314type Extra = { models: EntitySummary[]; total: number };15const AGENT_KINDS: Record<string, string> = { coding: 'Coding agent', browser: 'Browser agent', computer_use: 'Computer use', research: 'Research agent', assistant: 'Assistant', workflow: 'Workflow', voice: 'Voice agent', mcp_server: 'MCP server' };1617export default async function AgentsPage({ searchParams }: { searchParams: Promise<Record<string, string | undefined>> }) {18  const sp = await searchParams;19  return (20    <IntelListing<Extra>21      title="Agents"22      eyebrow="Agents & tools"23      lede={<>Autonomous and semi-autonomous systems built on the models in the atlas: who develops them, what kind they are, which models they run on, where they run. Related software lives under <Link href={routes.frameworks()} className="link">Frameworks</Link>; developer tools under <Link href={routes.tools()} className="link">Tools</Link>.</>}24      basePath="/agents"25      searchParams={sp}26      fetch={(q) => api.explore('agent', q)}27      sorts={[28        { value: 'updated', label: 'Recently updated' },29        { value: 'release', label: 'Release date' },30        { value: 'stars', label: 'Stars' },31        { value: 'name', label: 'Name' },32      ]}33      filters={sp.org ? [{ kind: 'hidden', name: 'org', value: sp.org }] : []}34      connectors={['github (agent repositories)', 'official product pages', 'mcp registries']}35      emptyHint={<>The atlas declares the <span className="mono">agent</span> entity type but no connector has produced one yet. <Link href={routes.frameworks()} className="link">Agent frameworks</Link> (LangChain, CrewAI, …) are listed under Frameworks.</>}36      enrich={async (items) => {37        const details = await Promise.all(items.map((e) => safe(api.entity(e.slug))));38        const m = new Map<string, Extra>();39        details.forEach((d, i) => {40          if (!d) return;41          const rel = (d.relations ?? []).filter((g) => g.direction === 'out' && ['uses', 'runs_on', 'derived_from', 'integrates'].includes(g.predicate));42          const models = rel.flatMap((g) => g.items.filter((x) => x.entity_type === 'model'));43          m.set(items[i]!.slug, { models, total: rel.reduce((n, g) => n + g.total, 0) });44        });45        return m;46      }}47      columns={[48        {49          key: 'name',50          label: 'Agent',51          primary: true,52          render: (e) => (53            <>54              <span className="flex flex-wrap items-center gap-x-2 gap-y-0.5">55                <EntityLink e={e} />56                {e.entity_type !== 'agent' && <EntityBadge type={e.entity_type} small />}57              </span>58              {e.description && <span className="block max-w-md truncate text-xs text-ink-3">{e.description}</span>}59            </>60          ),61        },62        { key: 'developer', label: 'Developer', className: 'text-ink-2', render: (e) => (e.organization ? <Link href={routes.entity({ entity_type: 'company', slug: e.organization.slug })} className="hover:text-accent">{e.organization.name}</Link> : str(e.attributes?.developer) ?? <Dash />) },63        { key: 'kind', label: 'Agent kind', render: (e) => { const k = str(e.attributes?.agent_kind) ?? str(e.attributes?.kind) ?? str(e.attributes?.category); return k ? <Chip>{AGENT_KINDS[k] ?? k.replace(/_/g, ' ')}</Chip> : <Dash />; } },64        {65          key: 'models',66          label: 'Underlying models',67          render: (e, x) => {68            const fromAttr = list(e.attributes?.models ?? e.attributes?.underlying_models);69            if (x?.models.length) return <span className="flex flex-wrap gap-1">{x.models.slice(0, 4).map((m) => <EntityLink key={m.id} e={m} className="text-xs" />)}{x.models.length > 4 && <span className="text-xs text-ink-3">+{x.models.length - 4}</span>}</span>;70            return fromAttr.length ? <span className="text-xs text-ink-2">{fromAttr.join(', ')}</span> : <Dash />;71          },72        },73        { key: 'platform', label: 'Platform', className: 'text-ink-2 text-xs', render: (e) => { const p = list(e.attributes?.platforms ?? e.attributes?.platform); return p.length ? p.join(' · ') : <Dash />; } },74        { key: 'repo', label: 'Repository', className: 'text-xs', render: (e) => { const u = str(e.attributes?.repository_url) ?? str(e.attributes?.official_url); return u ? <a href={u} target="_blank" rel="noopener noreferrer" className="text-ink-2 hover:text-accent">{u.replace(/^https?:\/\/(www\.)?/, '').replace(/\/$/, '').slice(0, 40)}</a> : <Dash />; } },75        { key: 'license', label: 'Licence', className: 'max-w-[10rem] truncate text-ink-2', render: (e) => str(e.attributes?.license) ?? <Dash /> },76        { key: 'release', label: 'Release', className: 'tnum text-ink-2 whitespace-nowrap', render: (e) => (str(e.attributes?.release_date) ? fmtDate(str(e.attributes.release_date)) : <Dash />) },77        { key: 'quality', label: 'Quality', num: true, render: (e) => <QualityMark q={e.quality?.score} /> },78      ]}79      note="Underlying models come from graph relations (uses · runs_on · derived_from · integrates) on each agent, else from the agent's stated attributes; a dash means no source has stated it."80    />81  );82}83