claude-cortex 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dashboard/README.md +36 -0
  2. package/dashboard/components.json +22 -0
  3. package/dashboard/eslint.config.mjs +18 -0
  4. package/dashboard/next.config.ts +7 -0
  5. package/dashboard/package-lock.json +7784 -0
  6. package/dashboard/package.json +42 -0
  7. package/dashboard/postcss.config.mjs +7 -0
  8. package/dashboard/public/file.svg +1 -0
  9. package/dashboard/public/globe.svg +1 -0
  10. package/dashboard/public/next.svg +1 -0
  11. package/dashboard/public/vercel.svg +1 -0
  12. package/dashboard/public/window.svg +1 -0
  13. package/dashboard/src/app/favicon.ico +0 -0
  14. package/dashboard/src/app/globals.css +125 -0
  15. package/dashboard/src/app/layout.tsx +35 -0
  16. package/dashboard/src/app/page.tsx +338 -0
  17. package/dashboard/src/components/Providers.tsx +27 -0
  18. package/dashboard/src/components/brain/ActivityPulseSystem.tsx +229 -0
  19. package/dashboard/src/components/brain/BrainMesh.tsx +118 -0
  20. package/dashboard/src/components/brain/BrainRegions.tsx +254 -0
  21. package/dashboard/src/components/brain/BrainScene.tsx +255 -0
  22. package/dashboard/src/components/brain/CategoryLabels.tsx +103 -0
  23. package/dashboard/src/components/brain/CoreSphere.tsx +215 -0
  24. package/dashboard/src/components/brain/DataFlowParticles.tsx +123 -0
  25. package/dashboard/src/components/brain/DataStreamRings.tsx +161 -0
  26. package/dashboard/src/components/brain/ElectronFlow.tsx +323 -0
  27. package/dashboard/src/components/brain/HolographicGrid.tsx +235 -0
  28. package/dashboard/src/components/brain/MemoryLinks.tsx +271 -0
  29. package/dashboard/src/components/brain/MemoryNode.tsx +245 -0
  30. package/dashboard/src/components/brain/NeuralPathways.tsx +441 -0
  31. package/dashboard/src/components/brain/SynapseNodes.tsx +306 -0
  32. package/dashboard/src/components/brain/TimelineControls.tsx +205 -0
  33. package/dashboard/src/components/chip/ChipScene.tsx +497 -0
  34. package/dashboard/src/components/chip/ChipSubstrate.tsx +238 -0
  35. package/dashboard/src/components/chip/CortexCore.tsx +210 -0
  36. package/dashboard/src/components/chip/DataBus.tsx +416 -0
  37. package/dashboard/src/components/chip/MemoryCell.tsx +225 -0
  38. package/dashboard/src/components/chip/MemoryGrid.tsx +328 -0
  39. package/dashboard/src/components/chip/QuantumCell.tsx +316 -0
  40. package/dashboard/src/components/chip/SectionLabel.tsx +113 -0
  41. package/dashboard/src/components/chip/index.ts +14 -0
  42. package/dashboard/src/components/controls/ControlPanel.tsx +100 -0
  43. package/dashboard/src/components/dashboard/StatsPanel.tsx +164 -0
  44. package/dashboard/src/components/debug/ActivityLog.tsx +238 -0
  45. package/dashboard/src/components/debug/DebugPanel.tsx +101 -0
  46. package/dashboard/src/components/debug/QueryTester.tsx +192 -0
  47. package/dashboard/src/components/debug/RelationshipGraph.tsx +403 -0
  48. package/dashboard/src/components/debug/SqlConsole.tsx +313 -0
  49. package/dashboard/src/components/memory/MemoryDetail.tsx +325 -0
  50. package/dashboard/src/components/ui/button.tsx +62 -0
  51. package/dashboard/src/components/ui/card.tsx +92 -0
  52. package/dashboard/src/components/ui/input.tsx +21 -0
  53. package/dashboard/src/hooks/useDebouncedValue.ts +24 -0
  54. package/dashboard/src/hooks/useMemories.ts +276 -0
  55. package/dashboard/src/hooks/useSuggestions.ts +46 -0
  56. package/dashboard/src/lib/category-colors.ts +84 -0
  57. package/dashboard/src/lib/position-algorithm.ts +177 -0
  58. package/dashboard/src/lib/simplex-noise.ts +217 -0
  59. package/dashboard/src/lib/store.ts +88 -0
  60. package/dashboard/src/lib/utils.ts +6 -0
  61. package/dashboard/src/lib/websocket.ts +216 -0
  62. package/dashboard/src/types/memory.ts +73 -0
  63. package/dashboard/tsconfig.json +34 -0
  64. package/dist/api/control.d.ts +27 -0
  65. package/dist/api/control.d.ts.map +1 -0
  66. package/dist/api/control.js +60 -0
  67. package/dist/api/control.js.map +1 -0
  68. package/dist/api/visualization-server.d.ts.map +1 -1
  69. package/dist/api/visualization-server.js +109 -2
  70. package/dist/api/visualization-server.js.map +1 -1
  71. package/dist/index.d.ts +2 -1
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +80 -4
  74. package/dist/index.js.map +1 -1
  75. package/dist/memory/store.d.ts +6 -0
  76. package/dist/memory/store.d.ts.map +1 -1
  77. package/dist/memory/store.js +14 -0
  78. package/dist/memory/store.js.map +1 -1
  79. package/package.json +7 -3
@@ -0,0 +1,229 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * Activity Pulse System
5
+ *
6
+ * Creates visual pulses when memory events occur:
7
+ * - memory_created: Green expanding pulse at memory position
8
+ * - memory_accessed: Blue flash at memory position
9
+ * - link_discovered: Cyan line connecting two memories
10
+ */
11
+
12
+ import { useRef, useMemo } from 'react';
13
+ import { useFrame } from '@react-three/fiber';
14
+ import * as THREE from 'three';
15
+
16
+ interface Pulse {
17
+ id: number;
18
+ type: 'created' | 'accessed' | 'linked';
19
+ position: [number, number, number];
20
+ targetPosition?: [number, number, number]; // For links
21
+ startTime: number;
22
+ duration: number;
23
+ color: string;
24
+ }
25
+
26
+ interface ActivityPulseSystemProps {
27
+ pulses: Pulse[];
28
+ onPulseComplete: (id: number) => void;
29
+ }
30
+
31
+ // Shared geometry
32
+ const PULSE_GEOMETRY = new THREE.RingGeometry(0.1, 0.15, 32);
33
+ const SPHERE_GEOMETRY = new THREE.SphereGeometry(0.1, 16, 16);
34
+
35
+ function CreatedPulse({
36
+ pulse,
37
+ onComplete,
38
+ }: {
39
+ pulse: Pulse;
40
+ onComplete: () => void;
41
+ }) {
42
+ const meshRef = useRef<THREE.Mesh>(null);
43
+ const startTimeRef = useRef<number | null>(null);
44
+
45
+ useFrame((state) => {
46
+ if (!meshRef.current) return;
47
+
48
+ // Initialize start time on first frame
49
+ if (startTimeRef.current === null) {
50
+ startTimeRef.current = state.clock.elapsedTime;
51
+ }
52
+
53
+ const elapsed = state.clock.elapsedTime - startTimeRef.current;
54
+ const progress = elapsed / (pulse.duration / 1000); // Convert ms to seconds
55
+
56
+ if (progress >= 1) {
57
+ onComplete();
58
+ return;
59
+ }
60
+
61
+ // Expanding ring that fades out
62
+ const scale = 0.5 + progress * 3;
63
+ const opacity = (1 - progress) * 0.8;
64
+
65
+ meshRef.current.scale.setScalar(scale);
66
+ (meshRef.current.material as THREE.MeshBasicMaterial).opacity = opacity;
67
+ });
68
+
69
+ return (
70
+ <mesh
71
+ ref={meshRef}
72
+ position={pulse.position}
73
+ rotation={[Math.PI / 2, 0, 0]}
74
+ geometry={PULSE_GEOMETRY}
75
+ >
76
+ <meshBasicMaterial
77
+ color={pulse.color}
78
+ transparent
79
+ opacity={0.8}
80
+ side={THREE.DoubleSide}
81
+ depthWrite={false}
82
+ />
83
+ </mesh>
84
+ );
85
+ }
86
+
87
+ function AccessedPulse({
88
+ pulse,
89
+ onComplete,
90
+ }: {
91
+ pulse: Pulse;
92
+ onComplete: () => void;
93
+ }) {
94
+ const meshRef = useRef<THREE.Mesh>(null);
95
+ const startTimeRef = useRef<number | null>(null);
96
+
97
+ useFrame((state) => {
98
+ if (!meshRef.current) return;
99
+
100
+ // Initialize start time on first frame
101
+ if (startTimeRef.current === null) {
102
+ startTimeRef.current = state.clock.elapsedTime;
103
+ }
104
+
105
+ const elapsed = state.clock.elapsedTime - startTimeRef.current;
106
+ const progress = elapsed / (pulse.duration / 1000); // Convert ms to seconds
107
+
108
+ if (progress >= 1) {
109
+ onComplete();
110
+ return;
111
+ }
112
+
113
+ // Flash that expands slightly then fades
114
+ const flash = Math.sin(progress * Math.PI);
115
+ const scale = 0.8 + flash * 0.6;
116
+ const opacity = flash * 0.9;
117
+
118
+ meshRef.current.scale.setScalar(scale);
119
+ (meshRef.current.material as THREE.MeshBasicMaterial).opacity = opacity;
120
+ });
121
+
122
+ return (
123
+ <mesh ref={meshRef} position={pulse.position} geometry={SPHERE_GEOMETRY}>
124
+ <meshBasicMaterial
125
+ color={pulse.color}
126
+ transparent
127
+ opacity={0.9}
128
+ depthWrite={false}
129
+ />
130
+ </mesh>
131
+ );
132
+ }
133
+
134
+ function LinkedPulse({
135
+ pulse,
136
+ onComplete,
137
+ }: {
138
+ pulse: Pulse;
139
+ onComplete: () => void;
140
+ }) {
141
+ const groupRef = useRef<THREE.Group>(null);
142
+ const startTimeRef = useRef<number | null>(null);
143
+ const lineRef = useRef<THREE.Line | null>(null);
144
+
145
+ // Create line object once
146
+ const lineObject = useMemo(() => {
147
+ const points = [
148
+ new THREE.Vector3(...pulse.position),
149
+ new THREE.Vector3(...(pulse.targetPosition || pulse.position)),
150
+ ];
151
+ const geometry = new THREE.BufferGeometry().setFromPoints(points);
152
+ const material = new THREE.LineBasicMaterial({
153
+ color: pulse.color,
154
+ transparent: true,
155
+ opacity: 0.8,
156
+ });
157
+ return new THREE.Line(geometry, material);
158
+ }, [pulse.position, pulse.targetPosition, pulse.color]);
159
+
160
+ useFrame((state) => {
161
+ if (!lineRef.current) {
162
+ // Add line to group on first render
163
+ if (groupRef.current && !groupRef.current.children.length) {
164
+ groupRef.current.add(lineObject);
165
+ lineRef.current = lineObject;
166
+ }
167
+ return;
168
+ }
169
+
170
+ // Initialize start time on first frame
171
+ if (startTimeRef.current === null) {
172
+ startTimeRef.current = state.clock.elapsedTime;
173
+ }
174
+
175
+ const elapsed = state.clock.elapsedTime - startTimeRef.current;
176
+ const progress = elapsed / (pulse.duration / 1000); // Convert ms to seconds
177
+
178
+ if (progress >= 1) {
179
+ onComplete();
180
+ return;
181
+ }
182
+
183
+ // Line that appears then fades
184
+ const flash = Math.sin(progress * Math.PI);
185
+ (lineRef.current.material as THREE.LineBasicMaterial).opacity = flash * 0.8;
186
+ });
187
+
188
+ return <group ref={groupRef} />;
189
+ }
190
+
191
+ export function ActivityPulseSystem({ pulses, onPulseComplete }: ActivityPulseSystemProps) {
192
+ return (
193
+ <group name="activity-pulses">
194
+ {pulses.map((pulse) => {
195
+ switch (pulse.type) {
196
+ case 'created':
197
+ return (
198
+ <CreatedPulse
199
+ key={pulse.id}
200
+ pulse={pulse}
201
+ onComplete={() => onPulseComplete(pulse.id)}
202
+ />
203
+ );
204
+ case 'accessed':
205
+ return (
206
+ <AccessedPulse
207
+ key={pulse.id}
208
+ pulse={pulse}
209
+ onComplete={() => onPulseComplete(pulse.id)}
210
+ />
211
+ );
212
+ case 'linked':
213
+ return (
214
+ <LinkedPulse
215
+ key={pulse.id}
216
+ pulse={pulse}
217
+ onComplete={() => onPulseComplete(pulse.id)}
218
+ />
219
+ );
220
+ default:
221
+ return null;
222
+ }
223
+ })}
224
+ </group>
225
+ );
226
+ }
227
+
228
+ // Type export for use in parent components
229
+ export type { Pulse };
@@ -0,0 +1,118 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * Brain Mesh
5
+ * Ghost wireframe outline of a brain shape for subtle context
6
+ * Uses simplex noise to create organic cortex-like surface folds
7
+ */
8
+
9
+ import { useMemo, useEffect } from 'react';
10
+ import * as THREE from 'three';
11
+ import { fbm3D, ridged3D } from '@/lib/simplex-noise';
12
+
13
+ interface BrainMeshProps {
14
+ opacity?: number;
15
+ showWireframe?: boolean;
16
+ pulseIntensity?: number;
17
+ }
18
+
19
+ /**
20
+ * Creates a brain-like geometry with cortex folds
21
+ */
22
+ function createBrainGeometry(): THREE.BufferGeometry {
23
+ // Start with icosahedron for smooth organic base
24
+ const geo = new THREE.IcosahedronGeometry(3.5, 5);
25
+ const positions = geo.attributes.position.array as Float32Array;
26
+ const colors = new Float32Array(positions.length);
27
+
28
+ for (let i = 0; i < positions.length; i += 3) {
29
+ let x = positions[i];
30
+ let y = positions[i + 1];
31
+ let z = positions[i + 2];
32
+
33
+ // Normalize to get direction
34
+ const length = Math.sqrt(x * x + y * y + z * z);
35
+ const nx = x / length;
36
+ const ny = y / length;
37
+ const nz = z / length;
38
+
39
+ // Multi-scale noise for cortex folds
40
+ // Large folds (gyri)
41
+ const largeNoise = fbm3D(nx * 2, ny * 2, nz * 2, 3, 2, 0.5) * 0.4;
42
+ // Medium detail
43
+ const mediumNoise = fbm3D(nx * 4, ny * 4, nz * 4, 2, 2, 0.5) * 0.15;
44
+ // Fine sulci (ridged for sharp creases)
45
+ const fineNoise = ridged3D(nx * 6, ny * 6, nz * 6, 2, 2, 0.5) * 0.08;
46
+
47
+ const totalNoise = largeNoise + mediumNoise + fineNoise * 0.5;
48
+
49
+ // Brain shape modifications:
50
+ // 1. Elongate front-to-back (Z axis) - frontal lobe
51
+ // 2. Slightly flatten top-bottom (Y axis)
52
+ // 3. Hemisphere bulges on sides (X axis)
53
+ const shapeX = 1.2 + Math.abs(nz) * 0.15; // Wider at sides
54
+ const shapeY = 0.85 + Math.abs(nx) * 0.1; // Slightly flat
55
+ const shapeZ = 1.1 - Math.abs(ny) * 0.1; // Elongated front-back
56
+
57
+ // Central fissure (divide hemispheres)
58
+ const centralFissure = Math.abs(nx) < 0.1 ? -0.15 * (1 - Math.abs(nx) / 0.1) : 0;
59
+
60
+ // Temporal lobe bulge
61
+ const temporalBulge = (Math.abs(nx) > 0.5 && nz < 0) ? 0.15 : 0;
62
+
63
+ // Apply all modifications
64
+ const radius = length * (1 + totalNoise + centralFissure + temporalBulge);
65
+
66
+ positions[i] = nx * radius * shapeX;
67
+ positions[i + 1] = ny * radius * shapeY;
68
+ positions[i + 2] = nz * radius * shapeZ;
69
+
70
+ // Color based on region (for visual depth)
71
+ // Front (STM) = orange tint, Middle (Episodic) = purple, Back (LTM) = blue
72
+ const normalizedZ = (nz + 1) / 2; // 0 to 1
73
+ colors[i] = 0.1 + normalizedZ * 0.2; // R: more red in front
74
+ colors[i + 1] = 0.05 + (1 - normalizedZ) * 0.15; // G: more green in back
75
+ colors[i + 2] = 0.2 + (1 - normalizedZ) * 0.3; // B: more blue in back
76
+ }
77
+
78
+ geo.computeVertexNormals();
79
+ geo.setAttribute('color', new THREE.BufferAttribute(colors, 3));
80
+
81
+ return geo;
82
+ }
83
+
84
+ export function BrainMesh({
85
+ opacity = 0.05,
86
+ showWireframe = true,
87
+ }: BrainMeshProps) {
88
+ // Create geometry once
89
+ const brainGeometry = useMemo(() => createBrainGeometry(), []);
90
+
91
+ // Ghost wireframe material - very faint gray
92
+ const wireframeMaterial = useMemo(
93
+ () =>
94
+ new THREE.MeshBasicMaterial({
95
+ color: '#333333',
96
+ wireframe: true,
97
+ transparent: true,
98
+ opacity: opacity,
99
+ }),
100
+ [opacity]
101
+ );
102
+
103
+ // Cleanup on unmount to prevent GPU memory leaks
104
+ useEffect(() => {
105
+ return () => {
106
+ brainGeometry.dispose();
107
+ wireframeMaterial.dispose();
108
+ };
109
+ }, [brainGeometry, wireframeMaterial]);
110
+
111
+ // Only render wireframe - no solid surface, no core, no animation
112
+ if (!showWireframe) return null;
113
+
114
+ return (
115
+ <mesh geometry={brainGeometry} material={wireframeMaterial} />
116
+ );
117
+ }
118
+
@@ -0,0 +1,254 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * Brain Regions
5
+ * Volumetric cloud-like regions representing different memory types
6
+ * - Short-term (front/orange): Active working memory
7
+ * - Episodic (middle/purple): Session and event memories
8
+ * - Long-term (back/blue): Consolidated stable memories
9
+ */
10
+
11
+ import { useRef, useMemo } from 'react';
12
+ import { useFrame } from '@react-three/fiber';
13
+ import { Html } from '@react-three/drei';
14
+ import * as THREE from 'three';
15
+
16
+ interface MemoryRegionProps {
17
+ type: 'short_term' | 'episodic' | 'long_term';
18
+ position: [number, number, number];
19
+ color: string;
20
+ memoryCount?: number;
21
+ label: string;
22
+ showLabel?: boolean;
23
+ }
24
+
25
+ /**
26
+ * Single volumetric memory region
27
+ * Uses multiple overlapping transparent spheres for cloud effect
28
+ */
29
+ function MemoryRegion({
30
+ type,
31
+ position,
32
+ color,
33
+ memoryCount = 0,
34
+ label,
35
+ showLabel = true,
36
+ }: MemoryRegionProps) {
37
+ const groupRef = useRef<THREE.Group>(null);
38
+ const innerRef = useRef<THREE.Mesh>(null);
39
+
40
+ // Scale based on memory count (more memories = larger region)
41
+ const scale = useMemo(() => {
42
+ const baseScale = 1;
43
+ const countScale = Math.min(memoryCount / 30, 0.5); // Max 50% increase
44
+ return baseScale + countScale;
45
+ }, [memoryCount]);
46
+
47
+ // Create multiple sphere layers for volumetric effect
48
+ const layers = useMemo(() => {
49
+ return [
50
+ { radius: 1.8, opacity: 0.03, offset: [0, 0, 0] },
51
+ { radius: 1.5, opacity: 0.04, offset: [0.2, 0.1, 0.1] },
52
+ { radius: 1.2, opacity: 0.05, offset: [-0.1, 0.15, -0.1] },
53
+ { radius: 0.9, opacity: 0.06, offset: [0.1, -0.1, 0.15] },
54
+ { radius: 0.6, opacity: 0.08, offset: [0, 0.05, 0] },
55
+ ];
56
+ }, []);
57
+
58
+ // Animation
59
+ useFrame((state) => {
60
+ if (!groupRef.current) return;
61
+
62
+ const time = state.clock.elapsedTime;
63
+ const typeOffset = type === 'short_term' ? 0 : type === 'episodic' ? 1 : 2;
64
+
65
+ // Gentle floating motion
66
+ groupRef.current.position.y =
67
+ position[1] + Math.sin(time * 0.3 + typeOffset) * 0.15;
68
+
69
+ // Subtle rotation
70
+ groupRef.current.rotation.y = Math.sin(time * 0.2 + typeOffset) * 0.1;
71
+
72
+ // Inner core pulsing
73
+ if (innerRef.current) {
74
+ const pulse = Math.sin(time * 1.5 + typeOffset * 2) * 0.15 + 0.85;
75
+ innerRef.current.scale.setScalar(pulse);
76
+ (innerRef.current.material as THREE.MeshBasicMaterial).opacity =
77
+ 0.15 + pulse * 0.1;
78
+ }
79
+ });
80
+
81
+ return (
82
+ <group ref={groupRef} position={position}>
83
+ {/* Volumetric cloud layers */}
84
+ {layers.map((layer, i) => (
85
+ <mesh
86
+ key={i}
87
+ position={[
88
+ layer.offset[0] * scale,
89
+ layer.offset[1] * scale,
90
+ layer.offset[2] * scale,
91
+ ]}
92
+ scale={scale}
93
+ >
94
+ <sphereGeometry args={[layer.radius, 24, 24]} />
95
+ <meshStandardMaterial
96
+ color={color}
97
+ transparent
98
+ opacity={layer.opacity}
99
+ emissive={color}
100
+ emissiveIntensity={0.15}
101
+ side={THREE.DoubleSide}
102
+ depthWrite={false}
103
+ />
104
+ </mesh>
105
+ ))}
106
+
107
+ {/* Bright inner core */}
108
+ <mesh ref={innerRef} scale={scale * 0.4}>
109
+ <sphereGeometry args={[1, 16, 16]} />
110
+ <meshBasicMaterial
111
+ color={color}
112
+ transparent
113
+ opacity={0.2}
114
+ depthWrite={false}
115
+ />
116
+ </mesh>
117
+
118
+ {/* Region label */}
119
+ {showLabel && (
120
+ <Html position={[0, 2.2 * scale, 0]} center style={{ pointerEvents: 'none' }}>
121
+ <div
122
+ className="px-3 py-1.5 rounded-full text-xs font-bold whitespace-nowrap backdrop-blur-sm"
123
+ style={{
124
+ backgroundColor: `${color}25`,
125
+ color: color,
126
+ border: `1px solid ${color}40`,
127
+ boxShadow: `0 0 20px ${color}30`,
128
+ }}
129
+ >
130
+ {label}
131
+ {memoryCount > 0 && (
132
+ <span className="ml-2 opacity-70">({memoryCount})</span>
133
+ )}
134
+ </div>
135
+ </Html>
136
+ )}
137
+ </group>
138
+ );
139
+ }
140
+
141
+ /**
142
+ * Energy field connecting regions
143
+ */
144
+ function EnergyField() {
145
+ const meshRef = useRef<THREE.Mesh>(null);
146
+
147
+ useFrame((state) => {
148
+ if (!meshRef.current) return;
149
+ const time = state.clock.elapsedTime;
150
+
151
+ // Slow rotation
152
+ meshRef.current.rotation.y = time * 0.05;
153
+ meshRef.current.rotation.x = Math.sin(time * 0.1) * 0.1;
154
+
155
+ // Pulsing opacity
156
+ (meshRef.current.material as THREE.MeshBasicMaterial).opacity =
157
+ 0.02 + Math.sin(time * 0.5) * 0.01;
158
+ });
159
+
160
+ return (
161
+ <mesh ref={meshRef}>
162
+ <torusGeometry args={[3.5, 0.8, 8, 48]} />
163
+ <meshBasicMaterial
164
+ color="#6366f1"
165
+ transparent
166
+ opacity={0.025}
167
+ side={THREE.DoubleSide}
168
+ depthWrite={false}
169
+ />
170
+ </mesh>
171
+ );
172
+ }
173
+
174
+ /**
175
+ * Orbital ring around the brain
176
+ */
177
+ function OrbitalRing({ radius = 4.5, color = '#4488ff' }: { radius?: number; color?: string }) {
178
+ const ringRef = useRef<THREE.Mesh>(null);
179
+
180
+ useFrame((state) => {
181
+ if (!ringRef.current) return;
182
+ ringRef.current.rotation.z = state.clock.elapsedTime * 0.1;
183
+ });
184
+
185
+ return (
186
+ <mesh ref={ringRef} rotation={[Math.PI / 2, 0, 0]}>
187
+ <torusGeometry args={[radius, 0.015, 8, 64]} />
188
+ <meshBasicMaterial color={color} transparent opacity={0.3} />
189
+ </mesh>
190
+ );
191
+ }
192
+
193
+ interface BrainRegionsProps {
194
+ shortTermCount?: number;
195
+ episodicCount?: number;
196
+ longTermCount?: number;
197
+ showLabels?: boolean;
198
+ }
199
+
200
+ /**
201
+ * All brain regions combined
202
+ */
203
+ export function BrainRegions({
204
+ shortTermCount = 0,
205
+ episodicCount = 0,
206
+ longTermCount = 0,
207
+ showLabels = false,
208
+ }: BrainRegionsProps) {
209
+ return (
210
+ <group name="brain-regions">
211
+ {/* Short-term memory region (front) */}
212
+ <MemoryRegion
213
+ type="short_term"
214
+ position={[0, 0, 2.8]}
215
+ color="#F97316"
216
+ memoryCount={shortTermCount}
217
+ label="Short-Term"
218
+ showLabel={showLabels}
219
+ />
220
+
221
+ {/* Episodic memory region (middle) */}
222
+ <MemoryRegion
223
+ type="episodic"
224
+ position={[0, 0.3, 0]}
225
+ color="#8B5CF6"
226
+ memoryCount={episodicCount}
227
+ label="Episodic"
228
+ showLabel={showLabels}
229
+ />
230
+
231
+ {/* Long-term memory region (back) */}
232
+ <MemoryRegion
233
+ type="long_term"
234
+ position={[0, 0, -2.8]}
235
+ color="#3B82F6"
236
+ memoryCount={longTermCount}
237
+ label="Long-Term"
238
+ showLabel={showLabels}
239
+ />
240
+
241
+ {/* Energy field connecting regions */}
242
+ <EnergyField />
243
+
244
+ {/* Orbital rings for sci-fi effect */}
245
+ <OrbitalRing radius={4.2} color="#3B82F6" />
246
+ <group rotation={[0, 0, Math.PI / 6]}>
247
+ <OrbitalRing radius={4.5} color="#8B5CF6" />
248
+ </group>
249
+ <group rotation={[0, 0, -Math.PI / 6]}>
250
+ <OrbitalRing radius={4.8} color="#F97316" />
251
+ </group>
252
+ </group>
253
+ );
254
+ }