import { useEffect, useState, useRef } from 'react'; import ForceGraph3D from 'react-force-graph-3d'; import * as THREE from 'three'; import { apiFetch } from '../api'; import './KnowledgeGraph.css'; // Stunning conceptual mock graph representing SOMA's cognitive architecture const MOCK_GRAPH = { nodes: [ { id: 'SOMA', label: 'SOMA (Core)', connections: 10, type: 'core' }, { id: 'Cortex', label: 'Cortex Layer', connections: 8, type: 'core' }, { id: 'Thalamus', label: 'Thalamus (Routing)', connections: 6, type: 'entity' }, { id: 'Hippocampus', label: 'Hippocampus', connections: 7, type: 'entity' }, { id: 'Neocortex', label: 'Neocortex', connections: 6, type: 'entity' }, { id: 'Sensory Cortex', label: 'Sensory Cortex', connections: 4, type: 'concept' }, { id: 'Working Memory', label: 'Working Memory', connections: 5, type: 'concept' }, { id: 'Episodic Memory', label: 'Episodic Memory', connections: 4, type: 'concept' }, { id: 'Sleep Cycle', label: 'Sleep Cycle', connections: 3, type: 'method' }, { id: 'Neural Inscription', label: 'Inscription Layer', connections: 3, type: 'method' }, { id: 'Llama 3.1', label: 'Llama 3.1', connections: 3, type: 'metric' }, { id: 'Groq API', label: 'Groq API', connections: 2, type: 'metric' } ], links: [ { source: 'SOMA', target: 'Cortex', label: 'ORCHESTRATES' }, { source: 'SOMA', target: 'Neural Inscription', label: 'ACCEPTS' }, { source: 'Cortex', target: 'Thalamus', label: 'ROUTES_BY' }, { source: 'Cortex', target: 'Hippocampus', label: 'CONSOLIDATES' }, { source: 'Cortex', target: 'Neocortex', label: 'STORES_IN' }, { source: 'Sensory Cortex', target: 'Hippocampus', label: 'WRITES_TO' }, { source: 'Working Memory', target: 'Thalamus', label: 'SYNCS_WITH' }, { source: 'Episodic Memory', target: 'Hippocampus', label: 'LOGS_IN' }, { source: 'Sleep Cycle', target: 'Hippocampus', label: 'OPTIMIZES' }, { source: 'Sleep Cycle', target: 'Neocortex', label: 'REINFORCES' }, { source: 'Cortex', target: 'Llama 3.1', label: 'COMPUTES' }, { source: 'Llama 3.1', target: 'Groq API', label: 'HOSTED_ON' } ] }; function KnowledgeGraph({ refreshTick }) { const [graphData, setGraphData] = useState({ nodes: [], links: [] }); const [loading, setLoading] = useState(true); const [dbStatus, setDbStatus] = useState('connecting'); const [dimensions, setDimensions] = useState({ width: 800, height: 500 }); const [stats, setStats] = useState({ node_count: 0, edge_count: 0, top_entities: [] }); const [physicsActive, setPhysicsActive] = useState(true); const [hudCollapsed, setHudCollapsed] = useState(false); const containerRef = useRef(null); const fgRef = useRef(); // Measure container dimensions to auto-resize the canvas useEffect(() => { if (!containerRef.current) return; const resizeObserver = new ResizeObserver((entries) => { for (let entry of entries) { const { width, height } = entry.contentRect; const isMobile = window.innerWidth < 768; const adjustedWidth = isMobile ? (window.innerWidth - 32) : width; const adjustedHeight = isMobile ? 700 : height; setDimensions({ width: adjustedWidth || 800, height: adjustedHeight || 500 }); } }); resizeObserver.observe(containerRef.current); return () => resizeObserver.disconnect(); }, []); // Fetch graph database from backend const fetchGraph = async () => { setLoading(true); try { const res = await apiFetch('/api/v1/graph'); if (!res.ok) { throw new Error('Graph fetch returned unhealthy status'); } const data = await res.json(); if (data.status === 'offline' || data.status === 'error' || !data.nodes || data.nodes.length === 0) { setDbStatus(data.status || 'offline'); const nodes = MOCK_GRAPH.nodes.map(n => ({ ...n })); const links = MOCK_GRAPH.links.map(l => ({ ...l })); setGraphData({ nodes, links }); } else { setDbStatus('online'); const nodes = data.nodes.map(n => ({ id: n.id, label: n.label || n.id, connections: n.connections || 1, type: 'entity' })); const links = data.edges.map(e => ({ source: e.source, target: e.target, label: e.label || 'RELATED_TO' })); setGraphData({ nodes, links }); } } catch (error) { console.error('Graph fetch failed', error); setDbStatus('offline'); setGraphData({ nodes: MOCK_GRAPH.nodes.map(n => ({ ...n })), links: MOCK_GRAPH.links.map(l => ({ ...l })) }); } finally { setLoading(false); } }; const fetchStats = async () => { try { const res = await apiFetch('/api/v1/graph/stats'); if (res.ok) { const data = await res.json(); if (data.status === 'online') { setStats(data); } } } catch (err) { console.error('Stats fetch failed', err); } }; useEffect(() => { fetchGraph(); fetchStats(); }, [refreshTick]); // Physics force configurations to pull the neural cluster into a tight, brain-like shape useEffect(() => { if (fgRef.current) { const d3Force = fgRef.current.d3Force; if (d3Force) { d3Force('charge').strength(-20).distanceMax(100); d3Force('link').distance(30); // Custom gravity force to pull unconnected clusters to the center d3Force('gravity', (alpha) => { graphData.nodes.forEach(node => { node.vx = (node.vx || 0) + (0 - node.x) * 0.05 * alpha; node.vy = (node.vy || 0) + (0 - node.y) * 0.05 * alpha; node.vz = (node.vz || 0) + (0 - node.z) * 0.05 * alpha; }); }); } // Auto-fit camera with appropriate padding to ensure complete visibility setTimeout(() => { if (window.innerWidth < 768) { // Shift camera down on mobile to make objects at (0,0,0) appear higher (reduced shift) fgRef.current.cameraPosition({ x: 0, y: -80, z: 300 }, { x: 0, y: -80, z: 0 }, 600); } else { const padding = 20; fgRef.current.zoomToFit(800, padding); } }, 600); } }, [graphData]); // Calculate max connections dynamically to scale color thresholds const maxConnections = graphData.nodes && graphData.nodes.length > 0 ? Math.max(...graphData.nodes.map(n => n.connections || 1), 1) : 1; // Color mapper based on node type & degree const getNodeColor = (node) => { if (node.id === 'SOMA') return '#ff6b35'; // Core Hub is SOMA Orange // For offline/mock mode, retain the pre-assigned structural category colors if (dbStatus !== 'online') { if (node.type === 'core') return '#ff6b35'; // Orange if (node.type === 'method') return '#ff8b54'; // Soft Orange if (node.type === 'concept') return '#ffa67c'; // Pale Orange if (node.type === 'metric') return '#a3a3a3'; // Neutral Grey return '#737373'; // Darker Grey } // For live Neo4j data, dynamically scale colors based on relative synaptic density! const connections = node.connections || 1; const ratio = connections / maxConnections; if (ratio >= 0.8) return '#ff6b35'; // High centrality (Orange) if (ratio >= 0.4) return '#ff9c7a'; // Medium centrality (Soft Orange) return '#a3a3a3'; // Low centrality (Silver/Grey) }; return (
{dbStatus !== 'online' && ( Neo4j Offline - Displaying Interactive System Concept )} {dbStatus === 'online' && ( Neo4j Synchronized (Live) )}
{/* Live Telemetry HUD Overlay */}
analytics Semantic Telemetry
setHudCollapsed(!hudCollapsed)}> {hudCollapsed ? 'expand_more' : 'expand_less'}
{!hudCollapsed && ( <>
Nodes: {dbStatus === 'online' ? stats.node_count : graphData.nodes.length}
Synapses: {dbStatus === 'online' ? stats.edge_count : graphData.links.length}
Storage: {dbStatus === 'online' ? 'LTM (Neo4j)' : 'STM (Cache)'}
)}
{!hudCollapsed && dbStatus === 'online' && stats.top_entities && stats.top_entities.length > 0 && (
star Primary Hubs
{stats.top_entities.map((ent, idx) => (
#{idx+1} {ent.entity} {ent.connections} rx
))}
)}
{ const size = Math.max(3.2, Math.min(node.connections * 1.6, 9.5)); // Perfectly scaled spheres const geom = new THREE.SphereGeometry(size, 24, 24); const mat = new THREE.MeshLambertMaterial({ color: getNodeColor(node), transparent: true, opacity: 0.95, emissive: getNodeColor(node), emissiveIntensity: 0.45 }); return new THREE.Mesh(geom, mat); }} // Outlined holographic label rendered natively floating beside cursor on hover (100% stable!) nodeLabel={node => ` ${node.label || node.id} `} // Outlined relationship tag rendered on link hover (100% stable!) linkLabel={link => ` ${link.label || 'RELATED_TO'} `} nodeRelSize={3} linkColor={() => 'rgba(255, 107, 53, 0.25)'} // Soft, clean axon link fibers linkWidth={1.8} // Sleek link line thickness // Glowing Thought Flows (sliding directional particles along axons) linkDirectionalParticles={3} linkDirectionalParticleSpeed={0.006} linkDirectionalParticleWidth={1.5} linkDirectionalParticleColor={() => '#ff6b35'} showNavInfo={false} enablePointerInteraction={true} enableNodeDrag={true} /> {/* Legend removed per user request */} {loading && (
refresh Synchronizing cognitive mesh...
)}
); } export default KnowledgeGraph;