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.
- package/dashboard/README.md +36 -0
- package/dashboard/components.json +22 -0
- package/dashboard/eslint.config.mjs +18 -0
- package/dashboard/next.config.ts +7 -0
- package/dashboard/package-lock.json +7784 -0
- package/dashboard/package.json +42 -0
- package/dashboard/postcss.config.mjs +7 -0
- package/dashboard/public/file.svg +1 -0
- package/dashboard/public/globe.svg +1 -0
- package/dashboard/public/next.svg +1 -0
- package/dashboard/public/vercel.svg +1 -0
- package/dashboard/public/window.svg +1 -0
- package/dashboard/src/app/favicon.ico +0 -0
- package/dashboard/src/app/globals.css +125 -0
- package/dashboard/src/app/layout.tsx +35 -0
- package/dashboard/src/app/page.tsx +338 -0
- package/dashboard/src/components/Providers.tsx +27 -0
- package/dashboard/src/components/brain/ActivityPulseSystem.tsx +229 -0
- package/dashboard/src/components/brain/BrainMesh.tsx +118 -0
- package/dashboard/src/components/brain/BrainRegions.tsx +254 -0
- package/dashboard/src/components/brain/BrainScene.tsx +255 -0
- package/dashboard/src/components/brain/CategoryLabels.tsx +103 -0
- package/dashboard/src/components/brain/CoreSphere.tsx +215 -0
- package/dashboard/src/components/brain/DataFlowParticles.tsx +123 -0
- package/dashboard/src/components/brain/DataStreamRings.tsx +161 -0
- package/dashboard/src/components/brain/ElectronFlow.tsx +323 -0
- package/dashboard/src/components/brain/HolographicGrid.tsx +235 -0
- package/dashboard/src/components/brain/MemoryLinks.tsx +271 -0
- package/dashboard/src/components/brain/MemoryNode.tsx +245 -0
- package/dashboard/src/components/brain/NeuralPathways.tsx +441 -0
- package/dashboard/src/components/brain/SynapseNodes.tsx +306 -0
- package/dashboard/src/components/brain/TimelineControls.tsx +205 -0
- package/dashboard/src/components/chip/ChipScene.tsx +497 -0
- package/dashboard/src/components/chip/ChipSubstrate.tsx +238 -0
- package/dashboard/src/components/chip/CortexCore.tsx +210 -0
- package/dashboard/src/components/chip/DataBus.tsx +416 -0
- package/dashboard/src/components/chip/MemoryCell.tsx +225 -0
- package/dashboard/src/components/chip/MemoryGrid.tsx +328 -0
- package/dashboard/src/components/chip/QuantumCell.tsx +316 -0
- package/dashboard/src/components/chip/SectionLabel.tsx +113 -0
- package/dashboard/src/components/chip/index.ts +14 -0
- package/dashboard/src/components/controls/ControlPanel.tsx +100 -0
- package/dashboard/src/components/dashboard/StatsPanel.tsx +164 -0
- package/dashboard/src/components/debug/ActivityLog.tsx +238 -0
- package/dashboard/src/components/debug/DebugPanel.tsx +101 -0
- package/dashboard/src/components/debug/QueryTester.tsx +192 -0
- package/dashboard/src/components/debug/RelationshipGraph.tsx +403 -0
- package/dashboard/src/components/debug/SqlConsole.tsx +313 -0
- package/dashboard/src/components/memory/MemoryDetail.tsx +325 -0
- package/dashboard/src/components/ui/button.tsx +62 -0
- package/dashboard/src/components/ui/card.tsx +92 -0
- package/dashboard/src/components/ui/input.tsx +21 -0
- package/dashboard/src/hooks/useDebouncedValue.ts +24 -0
- package/dashboard/src/hooks/useMemories.ts +276 -0
- package/dashboard/src/hooks/useSuggestions.ts +46 -0
- package/dashboard/src/lib/category-colors.ts +84 -0
- package/dashboard/src/lib/position-algorithm.ts +177 -0
- package/dashboard/src/lib/simplex-noise.ts +217 -0
- package/dashboard/src/lib/store.ts +88 -0
- package/dashboard/src/lib/utils.ts +6 -0
- package/dashboard/src/lib/websocket.ts +216 -0
- package/dashboard/src/types/memory.ts +73 -0
- package/dashboard/tsconfig.json +34 -0
- package/dist/api/control.d.ts +27 -0
- package/dist/api/control.d.ts.map +1 -0
- package/dist/api/control.js +60 -0
- package/dist/api/control.js.map +1 -0
- package/dist/api/visualization-server.d.ts.map +1 -1
- package/dist/api/visualization-server.js +109 -2
- package/dist/api/visualization-server.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +80 -4
- package/dist/index.js.map +1 -1
- package/dist/memory/store.d.ts +6 -0
- package/dist/memory/store.d.ts.map +1 -1
- package/dist/memory/store.js +14 -0
- package/dist/memory/store.js.map +1 -1
- package/package.json +7 -3
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Chip Scene - Circuit Board Style
|
|
5
|
+
* Clean top-down orthographic view of memory as a PCB
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Suspense, useMemo, useState, useCallback, useRef } from 'react';
|
|
9
|
+
import { Canvas } from '@react-three/fiber';
|
|
10
|
+
import { OrthographicCamera } from '@react-three/drei';
|
|
11
|
+
import { EffectComposer, Bloom } from '@react-three/postprocessing';
|
|
12
|
+
import { Memory, MemoryLink } from '@/types/memory';
|
|
13
|
+
import { useMemoryWebSocket } from '@/lib/websocket';
|
|
14
|
+
import * as THREE from 'three';
|
|
15
|
+
|
|
16
|
+
// Layout constants
|
|
17
|
+
const CHIP_WIDTH = 24;
|
|
18
|
+
const CHIP_HEIGHT = 16;
|
|
19
|
+
const NODE_SPACING = 1.2;
|
|
20
|
+
const SECTION_GAP = 2;
|
|
21
|
+
|
|
22
|
+
// Category colors
|
|
23
|
+
const CATEGORY_COLORS: Record<string, string> = {
|
|
24
|
+
architecture: '#06b6d4', // cyan
|
|
25
|
+
pattern: '#22c55e', // green
|
|
26
|
+
preference: '#eab308', // yellow
|
|
27
|
+
error: '#ef4444', // red
|
|
28
|
+
context: '#f97316', // orange
|
|
29
|
+
learning: '#84cc16', // lime
|
|
30
|
+
todo: '#a855f7', // purple
|
|
31
|
+
note: '#3b82f6', // blue
|
|
32
|
+
relationship: '#6366f1', // indigo
|
|
33
|
+
custom: '#ec4899', // pink
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
interface ChipSceneProps {
|
|
37
|
+
memories: Memory[];
|
|
38
|
+
links?: MemoryLink[];
|
|
39
|
+
selectedMemory: Memory | null;
|
|
40
|
+
onSelectMemory: (memory: Memory | null) => void;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function ChipScene({
|
|
44
|
+
memories = [],
|
|
45
|
+
links = [],
|
|
46
|
+
selectedMemory,
|
|
47
|
+
onSelectMemory,
|
|
48
|
+
}: ChipSceneProps) {
|
|
49
|
+
const [hoveredMemory, setHoveredMemory] = useState<Memory | null>(null);
|
|
50
|
+
|
|
51
|
+
// Group memories by type
|
|
52
|
+
const groupedMemories = useMemo(() => {
|
|
53
|
+
const stm = memories.filter((m) => m.type === 'short_term');
|
|
54
|
+
const episodic = memories.filter((m) => m.type === 'episodic');
|
|
55
|
+
const ltm = memories.filter((m) => m.type === 'long_term');
|
|
56
|
+
return { stm, episodic, ltm };
|
|
57
|
+
}, [memories]);
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<div className="w-full h-full bg-[#0a0a12]">
|
|
61
|
+
<Canvas
|
|
62
|
+
orthographic
|
|
63
|
+
camera={{ zoom: 40, position: [0, 0, 100], near: 0.1, far: 1000 }}
|
|
64
|
+
gl={{ antialias: true }}
|
|
65
|
+
onClick={() => onSelectMemory(null)}
|
|
66
|
+
>
|
|
67
|
+
<Suspense fallback={null}>
|
|
68
|
+
<ChipContent
|
|
69
|
+
memories={memories}
|
|
70
|
+
groupedMemories={groupedMemories}
|
|
71
|
+
links={links}
|
|
72
|
+
selectedMemory={selectedMemory}
|
|
73
|
+
hoveredMemory={hoveredMemory}
|
|
74
|
+
onSelectMemory={onSelectMemory}
|
|
75
|
+
onHoverMemory={setHoveredMemory}
|
|
76
|
+
/>
|
|
77
|
+
</Suspense>
|
|
78
|
+
</Canvas>
|
|
79
|
+
|
|
80
|
+
{/* Hover tooltip */}
|
|
81
|
+
{hoveredMemory && (
|
|
82
|
+
<div className="absolute top-4 left-1/2 -translate-x-1/2 bg-slate-900/95 border border-slate-600 rounded-lg px-4 py-2 text-sm backdrop-blur-sm pointer-events-none z-50">
|
|
83
|
+
<div className="font-semibold text-white">{hoveredMemory.title}</div>
|
|
84
|
+
<div className="text-slate-400 text-xs mt-1 flex items-center gap-2">
|
|
85
|
+
<span
|
|
86
|
+
className="w-2 h-2 rounded-full"
|
|
87
|
+
style={{ backgroundColor: CATEGORY_COLORS[hoveredMemory.category] }}
|
|
88
|
+
/>
|
|
89
|
+
<span className="capitalize">{hoveredMemory.category}</span>
|
|
90
|
+
<span className="text-slate-500">|</span>
|
|
91
|
+
<span>{Math.round(hoveredMemory.salience * 100)}% salience</span>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
)}
|
|
95
|
+
|
|
96
|
+
{/* Legend */}
|
|
97
|
+
<div className="absolute bottom-4 left-4 bg-slate-900/90 border border-slate-700 rounded-lg p-3 text-xs backdrop-blur-sm">
|
|
98
|
+
<h4 className="font-semibold text-white mb-2">Memory Banks</h4>
|
|
99
|
+
<div className="space-y-1.5">
|
|
100
|
+
<div className="flex items-center gap-2">
|
|
101
|
+
<div className="w-3 h-3 rounded-sm bg-orange-500/30 border border-orange-500" />
|
|
102
|
+
<span className="text-slate-300">STM</span>
|
|
103
|
+
<span className="text-slate-500 ml-auto">{groupedMemories.stm.length}</span>
|
|
104
|
+
</div>
|
|
105
|
+
<div className="flex items-center gap-2">
|
|
106
|
+
<div className="w-3 h-3 rounded-sm bg-purple-500/30 border border-purple-500" />
|
|
107
|
+
<span className="text-slate-300">Episodic</span>
|
|
108
|
+
<span className="text-slate-500 ml-auto">{groupedMemories.episodic.length}</span>
|
|
109
|
+
</div>
|
|
110
|
+
<div className="flex items-center gap-2">
|
|
111
|
+
<div className="w-3 h-3 rounded-sm bg-blue-500/30 border border-blue-500" />
|
|
112
|
+
<span className="text-slate-300">Long-Term</span>
|
|
113
|
+
<span className="text-slate-500 ml-auto">{groupedMemories.ltm.length}</span>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
<div className="mt-3 pt-2 border-t border-slate-700 text-slate-400">
|
|
117
|
+
{memories.length} total memories
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
{/* Status */}
|
|
122
|
+
<div className="absolute top-4 right-4 text-xs text-slate-500 font-mono">
|
|
123
|
+
CORTEX PCB v1.0
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
interface ChipContentProps {
|
|
130
|
+
memories: Memory[];
|
|
131
|
+
groupedMemories: { stm: Memory[]; episodic: Memory[]; ltm: Memory[] };
|
|
132
|
+
links: MemoryLink[];
|
|
133
|
+
selectedMemory: Memory | null;
|
|
134
|
+
hoveredMemory: Memory | null;
|
|
135
|
+
onSelectMemory: (memory: Memory | null) => void;
|
|
136
|
+
onHoverMemory: (memory: Memory | null) => void;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function ChipContent({
|
|
140
|
+
memories,
|
|
141
|
+
groupedMemories,
|
|
142
|
+
links,
|
|
143
|
+
selectedMemory,
|
|
144
|
+
hoveredMemory,
|
|
145
|
+
onSelectMemory,
|
|
146
|
+
onHoverMemory,
|
|
147
|
+
}: ChipContentProps) {
|
|
148
|
+
// Calculate grid layout for each section
|
|
149
|
+
const layoutConfig = useMemo(() => {
|
|
150
|
+
const cols = 12;
|
|
151
|
+
const stmRows = Math.ceil(groupedMemories.stm.length / cols) || 1;
|
|
152
|
+
const episodicRows = Math.ceil(groupedMemories.episodic.length / cols) || 1;
|
|
153
|
+
const ltmRows = Math.ceil(groupedMemories.ltm.length / cols) || 1;
|
|
154
|
+
|
|
155
|
+
const totalHeight = (stmRows + episodicRows + ltmRows) * NODE_SPACING + SECTION_GAP * 2;
|
|
156
|
+
const startY = totalHeight / 2;
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
cols,
|
|
160
|
+
stm: {
|
|
161
|
+
startY: startY - NODE_SPACING / 2,
|
|
162
|
+
rows: stmRows,
|
|
163
|
+
},
|
|
164
|
+
episodic: {
|
|
165
|
+
startY: startY - stmRows * NODE_SPACING - SECTION_GAP,
|
|
166
|
+
rows: episodicRows,
|
|
167
|
+
},
|
|
168
|
+
ltm: {
|
|
169
|
+
startY: startY - stmRows * NODE_SPACING - episodicRows * NODE_SPACING - SECTION_GAP * 2,
|
|
170
|
+
rows: ltmRows,
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
}, [groupedMemories]);
|
|
174
|
+
|
|
175
|
+
// Calculate positions for all memories
|
|
176
|
+
const memoryPositions = useMemo(() => {
|
|
177
|
+
const positions = new Map<number, [number, number]>();
|
|
178
|
+
const gridWidth = layoutConfig.cols * NODE_SPACING;
|
|
179
|
+
const startX = -gridWidth / 2 + NODE_SPACING / 2;
|
|
180
|
+
|
|
181
|
+
// STM positions
|
|
182
|
+
groupedMemories.stm.forEach((m, i) => {
|
|
183
|
+
const col = i % layoutConfig.cols;
|
|
184
|
+
const row = Math.floor(i / layoutConfig.cols);
|
|
185
|
+
const x = startX + col * NODE_SPACING;
|
|
186
|
+
const y = layoutConfig.stm.startY - row * NODE_SPACING;
|
|
187
|
+
positions.set(m.id, [x, y]);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Episodic positions
|
|
191
|
+
groupedMemories.episodic.forEach((m, i) => {
|
|
192
|
+
const col = i % layoutConfig.cols;
|
|
193
|
+
const row = Math.floor(i / layoutConfig.cols);
|
|
194
|
+
const x = startX + col * NODE_SPACING;
|
|
195
|
+
const y = layoutConfig.episodic.startY - row * NODE_SPACING;
|
|
196
|
+
positions.set(m.id, [x, y]);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// LTM positions
|
|
200
|
+
groupedMemories.ltm.forEach((m, i) => {
|
|
201
|
+
const col = i % layoutConfig.cols;
|
|
202
|
+
const row = Math.floor(i / layoutConfig.cols);
|
|
203
|
+
const x = startX + col * NODE_SPACING;
|
|
204
|
+
const y = layoutConfig.ltm.startY - row * NODE_SPACING;
|
|
205
|
+
positions.set(m.id, [x, y]);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
return positions;
|
|
209
|
+
}, [groupedMemories, layoutConfig]);
|
|
210
|
+
|
|
211
|
+
return (
|
|
212
|
+
<>
|
|
213
|
+
{/* Subtle ambient light */}
|
|
214
|
+
<ambientLight intensity={0.5} />
|
|
215
|
+
|
|
216
|
+
{/* PCB Background */}
|
|
217
|
+
<PCBBackground width={CHIP_WIDTH} height={CHIP_HEIGHT} />
|
|
218
|
+
|
|
219
|
+
{/* Section dividers and labels */}
|
|
220
|
+
<SectionDividers layoutConfig={layoutConfig} cols={layoutConfig.cols} />
|
|
221
|
+
|
|
222
|
+
{/* Memory links (PCB traces) */}
|
|
223
|
+
<MemoryTraces links={links} positions={memoryPositions} />
|
|
224
|
+
|
|
225
|
+
{/* Memory nodes */}
|
|
226
|
+
{memories.map((memory) => {
|
|
227
|
+
const pos = memoryPositions.get(memory.id);
|
|
228
|
+
if (!pos) return null;
|
|
229
|
+
|
|
230
|
+
return (
|
|
231
|
+
<MemoryNode
|
|
232
|
+
key={memory.id}
|
|
233
|
+
memory={memory}
|
|
234
|
+
position={pos}
|
|
235
|
+
isSelected={selectedMemory?.id === memory.id}
|
|
236
|
+
isHovered={hoveredMemory?.id === memory.id}
|
|
237
|
+
onSelect={onSelectMemory}
|
|
238
|
+
onHover={onHoverMemory}
|
|
239
|
+
/>
|
|
240
|
+
);
|
|
241
|
+
})}
|
|
242
|
+
|
|
243
|
+
{/* Post-processing - subtle bloom */}
|
|
244
|
+
<EffectComposer>
|
|
245
|
+
<Bloom
|
|
246
|
+
luminanceThreshold={0.6}
|
|
247
|
+
luminanceSmoothing={0.5}
|
|
248
|
+
intensity={0.4}
|
|
249
|
+
radius={0.4}
|
|
250
|
+
/>
|
|
251
|
+
</EffectComposer>
|
|
252
|
+
</>
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// PCB-style background with grid
|
|
257
|
+
function PCBBackground({ width, height }: { width: number; height: number }) {
|
|
258
|
+
const gridGeometry = useMemo(() => {
|
|
259
|
+
const points: THREE.Vector3[] = [];
|
|
260
|
+
const spacing = 1;
|
|
261
|
+
|
|
262
|
+
// Vertical lines
|
|
263
|
+
for (let x = -width / 2; x <= width / 2; x += spacing) {
|
|
264
|
+
points.push(new THREE.Vector3(x, -height / 2, 0));
|
|
265
|
+
points.push(new THREE.Vector3(x, height / 2, 0));
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Horizontal lines
|
|
269
|
+
for (let y = -height / 2; y <= height / 2; y += spacing) {
|
|
270
|
+
points.push(new THREE.Vector3(-width / 2, y, 0));
|
|
271
|
+
points.push(new THREE.Vector3(width / 2, y, 0));
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return new THREE.BufferGeometry().setFromPoints(points);
|
|
275
|
+
}, [width, height]);
|
|
276
|
+
|
|
277
|
+
return (
|
|
278
|
+
<group>
|
|
279
|
+
{/* Dark background */}
|
|
280
|
+
<mesh position={[0, 0, -1]}>
|
|
281
|
+
<planeGeometry args={[width + 4, height + 4]} />
|
|
282
|
+
<meshBasicMaterial color="#0d1117" />
|
|
283
|
+
</mesh>
|
|
284
|
+
|
|
285
|
+
{/* PCB substrate */}
|
|
286
|
+
<mesh position={[0, 0, -0.5]}>
|
|
287
|
+
<planeGeometry args={[width, height]} />
|
|
288
|
+
<meshBasicMaterial color="#1a1f2e" />
|
|
289
|
+
</mesh>
|
|
290
|
+
|
|
291
|
+
{/* Grid lines */}
|
|
292
|
+
<lineSegments geometry={gridGeometry}>
|
|
293
|
+
<lineBasicMaterial color="#252d3d" opacity={0.5} transparent />
|
|
294
|
+
</lineSegments>
|
|
295
|
+
|
|
296
|
+
{/* Border */}
|
|
297
|
+
<lineLoop>
|
|
298
|
+
<bufferGeometry>
|
|
299
|
+
<float32BufferAttribute
|
|
300
|
+
attach="attributes-position"
|
|
301
|
+
args={[
|
|
302
|
+
new Float32Array([
|
|
303
|
+
-width / 2, -height / 2, 0,
|
|
304
|
+
width / 2, -height / 2, 0,
|
|
305
|
+
width / 2, height / 2, 0,
|
|
306
|
+
-width / 2, height / 2, 0,
|
|
307
|
+
]),
|
|
308
|
+
3,
|
|
309
|
+
]}
|
|
310
|
+
/>
|
|
311
|
+
</bufferGeometry>
|
|
312
|
+
<lineBasicMaterial color="#3d4a5c" />
|
|
313
|
+
</lineLoop>
|
|
314
|
+
</group>
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Section dividers and labels
|
|
319
|
+
function SectionDividers({
|
|
320
|
+
layoutConfig,
|
|
321
|
+
cols,
|
|
322
|
+
}: {
|
|
323
|
+
layoutConfig: { stm: { startY: number; rows: number }; episodic: { startY: number; rows: number }; ltm: { startY: number; rows: number }; cols: number };
|
|
324
|
+
cols: number;
|
|
325
|
+
}) {
|
|
326
|
+
const gridWidth = cols * NODE_SPACING;
|
|
327
|
+
|
|
328
|
+
// Divider line between STM and Episodic
|
|
329
|
+
const divider1Y = layoutConfig.stm.startY - layoutConfig.stm.rows * NODE_SPACING - SECTION_GAP / 2 + NODE_SPACING / 2;
|
|
330
|
+
// Divider line between Episodic and LTM
|
|
331
|
+
const divider2Y = layoutConfig.episodic.startY - layoutConfig.episodic.rows * NODE_SPACING - SECTION_GAP / 2 + NODE_SPACING / 2;
|
|
332
|
+
|
|
333
|
+
return (
|
|
334
|
+
<group>
|
|
335
|
+
{/* STM label */}
|
|
336
|
+
<SectionLabel
|
|
337
|
+
text="STM"
|
|
338
|
+
position={[-gridWidth / 2 - 1.5, layoutConfig.stm.startY - (layoutConfig.stm.rows * NODE_SPACING) / 2 + NODE_SPACING / 2, 0]}
|
|
339
|
+
color="#f97316"
|
|
340
|
+
/>
|
|
341
|
+
|
|
342
|
+
{/* Divider 1 */}
|
|
343
|
+
<line>
|
|
344
|
+
<bufferGeometry>
|
|
345
|
+
<float32BufferAttribute
|
|
346
|
+
attach="attributes-position"
|
|
347
|
+
args={[new Float32Array([-gridWidth / 2 - 0.5, divider1Y, 0, gridWidth / 2 + 0.5, divider1Y, 0]), 3]}
|
|
348
|
+
/>
|
|
349
|
+
</bufferGeometry>
|
|
350
|
+
<lineBasicMaterial color="#3d4a5c" opacity={0.5} transparent />
|
|
351
|
+
</line>
|
|
352
|
+
|
|
353
|
+
{/* Episodic label */}
|
|
354
|
+
<SectionLabel
|
|
355
|
+
text="EPISODIC"
|
|
356
|
+
position={[-gridWidth / 2 - 1.5, layoutConfig.episodic.startY - (layoutConfig.episodic.rows * NODE_SPACING) / 2 + NODE_SPACING / 2, 0]}
|
|
357
|
+
color="#a855f7"
|
|
358
|
+
/>
|
|
359
|
+
|
|
360
|
+
{/* Divider 2 */}
|
|
361
|
+
<line>
|
|
362
|
+
<bufferGeometry>
|
|
363
|
+
<float32BufferAttribute
|
|
364
|
+
attach="attributes-position"
|
|
365
|
+
args={[new Float32Array([-gridWidth / 2 - 0.5, divider2Y, 0, gridWidth / 2 + 0.5, divider2Y, 0]), 3]}
|
|
366
|
+
/>
|
|
367
|
+
</bufferGeometry>
|
|
368
|
+
<lineBasicMaterial color="#3d4a5c" opacity={0.5} transparent />
|
|
369
|
+
</line>
|
|
370
|
+
|
|
371
|
+
{/* LTM label */}
|
|
372
|
+
<SectionLabel
|
|
373
|
+
text="LTM"
|
|
374
|
+
position={[-gridWidth / 2 - 1.5, layoutConfig.ltm.startY - (layoutConfig.ltm.rows * NODE_SPACING) / 2 + NODE_SPACING / 2, 0]}
|
|
375
|
+
color="#3b82f6"
|
|
376
|
+
/>
|
|
377
|
+
</group>
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Section label as 3D text alternative (simple box with color)
|
|
382
|
+
function SectionLabel({ text, position, color }: { text: string; position: [number, number, number]; color: string }) {
|
|
383
|
+
return (
|
|
384
|
+
<group position={position}>
|
|
385
|
+
<mesh>
|
|
386
|
+
<planeGeometry args={[0.1, 0.8]} />
|
|
387
|
+
<meshBasicMaterial color={color} />
|
|
388
|
+
</mesh>
|
|
389
|
+
</group>
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Memory traces (connections between related memories)
|
|
394
|
+
function MemoryTraces({
|
|
395
|
+
links,
|
|
396
|
+
positions,
|
|
397
|
+
}: {
|
|
398
|
+
links: MemoryLink[];
|
|
399
|
+
positions: Map<number, [number, number]>;
|
|
400
|
+
}) {
|
|
401
|
+
const traceGeometry = useMemo(() => {
|
|
402
|
+
const points: number[] = [];
|
|
403
|
+
|
|
404
|
+
links.forEach((link) => {
|
|
405
|
+
const sourcePos = positions.get(link.source_id);
|
|
406
|
+
const targetPos = positions.get(link.target_id);
|
|
407
|
+
if (sourcePos && targetPos) {
|
|
408
|
+
points.push(sourcePos[0], sourcePos[1], 0.1);
|
|
409
|
+
points.push(targetPos[0], targetPos[1], 0.1);
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
const geometry = new THREE.BufferGeometry();
|
|
414
|
+
geometry.setAttribute('position', new THREE.Float32BufferAttribute(points, 3));
|
|
415
|
+
return geometry;
|
|
416
|
+
}, [links, positions]);
|
|
417
|
+
|
|
418
|
+
if (links.length === 0) return null;
|
|
419
|
+
|
|
420
|
+
return (
|
|
421
|
+
<lineSegments geometry={traceGeometry}>
|
|
422
|
+
<lineBasicMaterial color="#FFB347" opacity={0.15} transparent />
|
|
423
|
+
</lineSegments>
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Individual memory node
|
|
428
|
+
function MemoryNode({
|
|
429
|
+
memory,
|
|
430
|
+
position,
|
|
431
|
+
isSelected,
|
|
432
|
+
isHovered,
|
|
433
|
+
onSelect,
|
|
434
|
+
onHover,
|
|
435
|
+
}: {
|
|
436
|
+
memory: Memory;
|
|
437
|
+
position: [number, number];
|
|
438
|
+
isSelected: boolean;
|
|
439
|
+
isHovered: boolean;
|
|
440
|
+
onSelect: (memory: Memory | null) => void;
|
|
441
|
+
onHover: (memory: Memory | null) => void;
|
|
442
|
+
}) {
|
|
443
|
+
const color = CATEGORY_COLORS[memory.category] || CATEGORY_COLORS.custom;
|
|
444
|
+
const isQuantum = memory.salience >= 0.7;
|
|
445
|
+
|
|
446
|
+
// Size based on salience
|
|
447
|
+
const baseSize = 0.25;
|
|
448
|
+
const size = baseSize + memory.salience * 0.15;
|
|
449
|
+
|
|
450
|
+
return (
|
|
451
|
+
<group position={[position[0], position[1], 0]}>
|
|
452
|
+
{/* Main node */}
|
|
453
|
+
<mesh
|
|
454
|
+
onClick={(e) => {
|
|
455
|
+
e.stopPropagation();
|
|
456
|
+
onSelect(isSelected ? null : memory);
|
|
457
|
+
}}
|
|
458
|
+
onPointerOver={(e) => {
|
|
459
|
+
e.stopPropagation();
|
|
460
|
+
onHover(memory);
|
|
461
|
+
document.body.style.cursor = 'pointer';
|
|
462
|
+
}}
|
|
463
|
+
onPointerOut={() => {
|
|
464
|
+
onHover(null);
|
|
465
|
+
document.body.style.cursor = 'auto';
|
|
466
|
+
}}
|
|
467
|
+
>
|
|
468
|
+
<circleGeometry args={[size, 16]} />
|
|
469
|
+
<meshBasicMaterial color={color} />
|
|
470
|
+
</mesh>
|
|
471
|
+
|
|
472
|
+
{/* Quantum glow ring */}
|
|
473
|
+
{isQuantum && (
|
|
474
|
+
<mesh>
|
|
475
|
+
<ringGeometry args={[size + 0.05, size + 0.12, 32]} />
|
|
476
|
+
<meshBasicMaterial color="#FFD700" transparent opacity={0.6} />
|
|
477
|
+
</mesh>
|
|
478
|
+
)}
|
|
479
|
+
|
|
480
|
+
{/* Selection ring */}
|
|
481
|
+
{isSelected && (
|
|
482
|
+
<mesh>
|
|
483
|
+
<ringGeometry args={[size + 0.15, size + 0.22, 32]} />
|
|
484
|
+
<meshBasicMaterial color="#ffffff" transparent opacity={0.8} />
|
|
485
|
+
</mesh>
|
|
486
|
+
)}
|
|
487
|
+
|
|
488
|
+
{/* Hover highlight */}
|
|
489
|
+
{isHovered && !isSelected && (
|
|
490
|
+
<mesh>
|
|
491
|
+
<ringGeometry args={[size + 0.08, size + 0.14, 32]} />
|
|
492
|
+
<meshBasicMaterial color={color} transparent opacity={0.5} />
|
|
493
|
+
</mesh>
|
|
494
|
+
)}
|
|
495
|
+
</group>
|
|
496
|
+
);
|
|
497
|
+
}
|