"use client"; import { motion } from "framer-motion"; import { cn } from "@/lib/utils"; import { LAYERS } from "@/lib/constants"; import versionsData from "@/data/generated/versions.json"; const CLASS_DESCRIPTIONS: Record = { TodoManager: "Visible task planning with constraints", SkillLoader: "Dynamic knowledge injection from SKILL.md files", ContextManager: "Three-layer context compression pipeline", Task: "File-based persistent task with dependencies", TaskManager: "File-based persistent task CRUD with dependencies", BackgroundTask: "Single background execution unit", BackgroundManager: "Non-blocking thread execution + notification queue", TeammateManager: "Multi-agent team lifecycle and coordination", Teammate: "Individual agent identity and state tracking", SharedBoard: "Cross-agent shared state coordination", CronJob: "Durable recurring job definition", ProtocolState: "Pending team protocol requests and response matching", MCPClient: "External tool discovery and invocation client", RecoveryState: "Retry, fallback, and continuation state", }; interface ArchDiagramProps { version: string; } function getLayerColor(versionId: string): string { const layer = LAYERS.find((l) => (l.versions as readonly string[]).includes(versionId)); return layer?.color ?? "#71717a"; } function getLayerColorClasses(versionId: string): { border: string; bg: string; } { const v = versionsData.versions.find((v) => v.id === versionId) as { layer?: string } | undefined; const layer = v?.layer; switch (layer) { case "tools": return { border: "border-blue-500", bg: "bg-blue-500/10", }; case "planning": return { border: "border-emerald-500", bg: "bg-emerald-500/10", }; case "memory": return { border: "border-purple-500", bg: "bg-purple-500/10", }; case "concurrency": return { border: "border-amber-500", bg: "bg-amber-500/10", }; case "collaboration": return { border: "border-red-500", bg: "bg-red-500/10", }; default: return { border: "border-zinc-500", bg: "bg-zinc-500/10", }; } } function collectClassesForVersion( targetId: string ): { name: string; introducedIn: string }[] { const targetIndex = versionsData.versions.findIndex((v) => v.id === targetId); const version = targetIndex >= 0 ? versionsData.versions[targetIndex] : undefined; return ( version?.classes?.map((cls) => ({ name: cls.name, introducedIn: versionsData.versions .slice(0, targetIndex + 1) .find((candidate) => candidate.classes?.some((candidateCls) => candidateCls.name === cls.name) )?.id ?? targetId, })) ?? [] ); } function getNewClassNames(version: string): Set { const diff = versionsData.diffs.find((d) => d.to === version); if (!diff) { const v = versionsData.versions.find((ver) => ver.id === version); return new Set(v?.classes?.map((c) => c.name) ?? []); } return new Set(diff.newClasses ?? []); } export function ArchDiagram({ version }: ArchDiagramProps) { const allClasses = collectClassesForVersion(version); const newClassNames = getNewClassNames(version); const versionData = versionsData.versions.find((v) => v.id === version); const tools = versionData?.tools ?? []; const reversed = [...allClasses].reverse(); return (
{reversed.map((cls, i) => { const isNew = newClassNames.has(cls.name); const colorClasses = getLayerColorClasses(cls.introducedIn); return (
{i > 0 && (
)}
{cls.name}

{CLASS_DESCRIPTIONS[cls.name] || ""}

{cls.introducedIn} {isNew && ( NEW )}
); })} {allClasses.length === 0 && (
No classes in this version (functions only)
)} {tools.length > 0 && ( {tools.map((tool) => ( {tool} ))} )}
); }