"use client"; import Link from "next/link"; import { useCallback, useEffect, useState } from "react"; import { ArrowRight, Brain, Layers, Network, RefreshCw, Sparkles, Workflow, type LucideIcon, } from "lucide-react"; import { useTranslation } from "react-i18next"; import { apiFetch, apiUrl } from "@/lib/api"; import MemoryArchivedBanner from "@/components/memory/MemoryArchivedBanner"; interface DocOverview { layer: "L2" | "L3"; key: string; exists: boolean; updated_at: string | null; entry_count: number; backlog: number; } interface OverviewResponse { docs: DocOverview[]; backups: string[]; } interface SnapshotResponse { surface: string; entities: unknown[]; } const SURFACES = [ "chat", "notebook", "quiz", "kb", "book", "partner", "cowriter", ] as const; const L3_VISIBLE = ["recent", "profile", "scope"] as const; export default function MemoryHub() { const { t } = useTranslation(); const [overview, setOverview] = useState(null); const [l1Total, setL1Total] = useState(null); const [loading, setLoading] = useState(true); const load = useCallback(async () => { setLoading(true); try { const [ovRes, ...l1Counts] = await Promise.all([ apiFetch(apiUrl("/api/v1/memory/overview")).then((r) => r.json()), ...SURFACES.map((s) => apiFetch(apiUrl(`/api/v1/memory/snapshot/${s}`)) .then((r) => r.json()) .then((d: SnapshotResponse) => d?.entities?.length ?? 0) .catch(() => 0), ), ]); setOverview(ovRes as OverviewResponse); setL1Total(l1Counts.reduce((acc, n) => acc + (n as number), 0)); } finally { setLoading(false); } }, []); useEffect(() => { void load(); }, [load]); const l2Docs = (overview?.docs || []).filter((d) => d.layer === "L2"); const l3Docs = (overview?.docs || []).filter( (d) => d.layer === "L3" && d.key !== "preferences", ); const l2Total = l2Docs.reduce((acc, d) => acc + d.entry_count, 0); const l3Total = l3Docs.reduce((acc, d) => acc + d.entry_count, 0); const latestBackup = overview?.backups?.[overview.backups.length - 1] ?? null; return (

{t("Memory")}

{t( "Everything DeepTutor remembers about you, organised across three layers. Click into any layer to inspect or curate it.", )}

{t("Memory settings")}
); } function GraphCallout() { const { t } = useTranslation(); return (

{t("Memory graph")}

{t("New")}

{t( "See all three layers at once — L3 synthesis at the centre, L2 facts in the middle, L1 traces on the outside. Hover any node for a preview.", )}

); } interface LayerCardProps { href: string; icon: LucideIcon; title: string; tag: string; stat: string; statLabel: string; detail: string; } function LayerCard({ href, icon: Icon, title, tag, stat, statLabel, detail, }: LayerCardProps) { return (
{tag}

{title}

{stat} {statLabel}

{detail}

{tag}
); }