import { useMemo, useState } from "react" import { GraphCanvas, darkTheme } from "reagraph" import { Trash2, Sparkles, Share2 } from "lucide-react" import { type MemoryGraph } from "@/lib/api" const CAT_COLOR: Record = { identity: "#22d3ee", knowledge: "#6366f1", rules: "#a78bfa", events: "#fbbf24", } const CAT_LABEL: Record = { identity: "Identität", knowledge: "Wissen", rules: "Regeln", events: "Ereignisse", } const AUTO = new Set(["auto", "agent", "hermes"]) export function GraphView({ data, onDelete }: { data: MemoryGraph; onDelete: (id: string) => void }) { const [selected, setSelected] = useState(null) const degree = useMemo(() => { const d: Record = {} data.edges.forEach((e) => { d[e.source] = (d[e.source] || 0) + 1; d[e.target] = (d[e.target] || 0) + 1 }) return d }, [data]) const nodes = useMemo(() => data.nodes.map((n) => ({ id: n.id, label: n.content.length > 26 ? n.content.slice(0, 25) + "…" : n.content, fill: CAT_COLOR[n.category] || "#64748b", size: 6 + Math.min(degree[n.id] || 0, 6) * 2, })), [data, degree]) const edges = useMemo(() => data.edges.map((e) => ({ id: `${e.source}->${e.target}`, source: e.source, target: e.target, size: 0.4 + e.weight, })), [data]) const sel = selected ? data.nodes.find((n) => n.id === selected) ?? null : null const neighbors = useMemo(() => { if (!selected) return [] const ids = new Set() data.edges.forEach((e) => { if (e.source === selected) ids.add(e.target) if (e.target === selected) ids.add(e.source) }) return data.nodes.filter((n) => ids.has(n.id)) }, [selected, data]) if (!data.nodes.length) { return (
Noch keine Fakten — der Graph füllt sich, sobald Hermes lernt oder du Einträge anlegst.
) } return (
setSelected(n.id)} onCanvasClick={() => setSelected(null)} />
{sel ? ( <>
{CAT_LABEL[sel.category] || sel.category} {AUTO.has(sel.source) && }{sel.source}
{sel.content}
verwandte Fakten
{neighbors.length ? neighbors.map((n) => ( )) : }
) : (
Einen Knoten wählen, um den Fakt und seine semantischen Nachbarn zu sehen.
)}
) }