shieldcortex 2.1.1 → 2.1.3

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 (87) hide show
  1. package/README.md +1 -1
  2. package/dist/defence/firewall/encoding-detector.js +1 -1
  3. package/dist/defence/firewall/encoding-detector.js.map +1 -1
  4. package/dist/defence/firewall/index.js +22 -0
  5. package/dist/defence/firewall/index.js.map +1 -1
  6. package/dist/defence/firewall/instruction-detector.d.ts.map +1 -1
  7. package/dist/defence/firewall/instruction-detector.js +26 -0
  8. package/dist/defence/firewall/instruction-detector.js.map +1 -1
  9. package/dist/defence/pipeline.d.ts.map +1 -1
  10. package/dist/defence/pipeline.js +8 -0
  11. package/dist/defence/pipeline.js.map +1 -1
  12. package/hooks/clawdbot/cortex-memory/HOOK.md +2 -2
  13. package/package.json +13 -9
  14. package/dashboard/components.json +0 -22
  15. package/dashboard/eslint.config.mjs +0 -42
  16. package/dashboard/next.config.ts +0 -7
  17. package/dashboard/package-lock.json +0 -8053
  18. package/dashboard/package.json +0 -44
  19. package/dashboard/postcss.config.mjs +0 -7
  20. package/dashboard/public/file.svg +0 -1
  21. package/dashboard/public/globe.svg +0 -1
  22. package/dashboard/public/next.svg +0 -1
  23. package/dashboard/public/vercel.svg +0 -1
  24. package/dashboard/public/window.svg +0 -1
  25. package/dashboard/scripts/ensure-api.mjs +0 -76
  26. package/dashboard/src/app/error.tsx +0 -49
  27. package/dashboard/src/app/favicon.ico +0 -0
  28. package/dashboard/src/app/globals.css +0 -130
  29. package/dashboard/src/app/layout.tsx +0 -35
  30. package/dashboard/src/app/page.tsx +0 -364
  31. package/dashboard/src/components/Providers.tsx +0 -27
  32. package/dashboard/src/components/brain/ActivityPulseSystem.tsx +0 -229
  33. package/dashboard/src/components/brain/BrainMesh.tsx +0 -133
  34. package/dashboard/src/components/brain/BrainRegions.tsx +0 -254
  35. package/dashboard/src/components/brain/BrainScene.tsx +0 -255
  36. package/dashboard/src/components/brain/CategoryLabels.tsx +0 -103
  37. package/dashboard/src/components/brain/CoreSphere.tsx +0 -215
  38. package/dashboard/src/components/brain/DataFlowParticles.tsx +0 -123
  39. package/dashboard/src/components/brain/DataStreamRings.tsx +0 -161
  40. package/dashboard/src/components/brain/ElectronFlow.tsx +0 -323
  41. package/dashboard/src/components/brain/HolographicGrid.tsx +0 -235
  42. package/dashboard/src/components/brain/MemoryLinks.tsx +0 -271
  43. package/dashboard/src/components/brain/MemoryNode.tsx +0 -245
  44. package/dashboard/src/components/brain/NeuralPathways.tsx +0 -441
  45. package/dashboard/src/components/brain/SynapseNodes.tsx +0 -312
  46. package/dashboard/src/components/brain/TimelineControls.tsx +0 -205
  47. package/dashboard/src/components/chip/ChipScene.tsx +0 -497
  48. package/dashboard/src/components/chip/ChipSubstrate.tsx +0 -238
  49. package/dashboard/src/components/chip/CortexCore.tsx +0 -210
  50. package/dashboard/src/components/chip/DataBus.tsx +0 -416
  51. package/dashboard/src/components/chip/MemoryCell.tsx +0 -225
  52. package/dashboard/src/components/chip/MemoryGrid.tsx +0 -328
  53. package/dashboard/src/components/chip/QuantumCell.tsx +0 -316
  54. package/dashboard/src/components/chip/SectionLabel.tsx +0 -113
  55. package/dashboard/src/components/chip/index.ts +0 -14
  56. package/dashboard/src/components/controls/ControlPanel.tsx +0 -106
  57. package/dashboard/src/components/controls/VersionPanel.tsx +0 -185
  58. package/dashboard/src/components/dashboard/StatsPanel.tsx +0 -164
  59. package/dashboard/src/components/debug/ActivityLog.tsx +0 -250
  60. package/dashboard/src/components/debug/DebugPanel.tsx +0 -101
  61. package/dashboard/src/components/debug/QueryTester.tsx +0 -192
  62. package/dashboard/src/components/debug/RelationshipGraph.tsx +0 -403
  63. package/dashboard/src/components/debug/SqlConsole.tsx +0 -319
  64. package/dashboard/src/components/graph/KnowledgeGraph.tsx +0 -230
  65. package/dashboard/src/components/graph/OntologyGraph.tsx +0 -631
  66. package/dashboard/src/components/insights/ActivityHeatmap.tsx +0 -131
  67. package/dashboard/src/components/insights/InsightsView.tsx +0 -46
  68. package/dashboard/src/components/insights/KnowledgeMapPanel.tsx +0 -80
  69. package/dashboard/src/components/insights/QualityPanel.tsx +0 -116
  70. package/dashboard/src/components/memories/MemoriesView.tsx +0 -150
  71. package/dashboard/src/components/memories/MemoryCard.tsx +0 -103
  72. package/dashboard/src/components/memory/MemoryDetail.tsx +0 -325
  73. package/dashboard/src/components/nav/NavRail.tsx +0 -54
  74. package/dashboard/src/components/ui/button.tsx +0 -62
  75. package/dashboard/src/components/ui/card.tsx +0 -92
  76. package/dashboard/src/components/ui/input.tsx +0 -21
  77. package/dashboard/src/hooks/useDebouncedValue.ts +0 -24
  78. package/dashboard/src/hooks/useMemories.ts +0 -458
  79. package/dashboard/src/hooks/useSuggestions.ts +0 -46
  80. package/dashboard/src/lib/category-colors.ts +0 -84
  81. package/dashboard/src/lib/position-algorithm.ts +0 -177
  82. package/dashboard/src/lib/simplex-noise.ts +0 -217
  83. package/dashboard/src/lib/store.ts +0 -88
  84. package/dashboard/src/lib/utils.ts +0 -6
  85. package/dashboard/src/lib/websocket.ts +0 -249
  86. package/dashboard/src/types/memory.ts +0 -73
  87. package/dashboard/tsconfig.json +0 -34
@@ -1,416 +0,0 @@
1
- 'use client';
2
-
3
- /**
4
- * Data Bus
5
- * Trace lines connecting the Cortex Core to memory banks
6
- * Supports pulse animations for access events
7
- */
8
-
9
- import { useMemo, useRef } from 'react';
10
- import { useFrame } from '@react-three/fiber';
11
- import * as THREE from 'three';
12
-
13
- interface DataBusProps {
14
- chipWidth?: number;
15
- chipHeight?: number;
16
- coreWidth?: number;
17
- coreHeight?: number;
18
- }
19
-
20
- interface BusLineProps {
21
- start: [number, number, number];
22
- end: [number, number, number];
23
- color?: string;
24
- }
25
-
26
- // Single bus trace line
27
- function BusLine({ start, end, color = '#FFB347' }: BusLineProps) {
28
- const geometry = useMemo(() => {
29
- const points = [new THREE.Vector3(...start), new THREE.Vector3(...end)];
30
- return new THREE.BufferGeometry().setFromPoints(points);
31
- }, [start, end]);
32
-
33
- return (
34
- <line>
35
- <primitive object={geometry} />
36
- <lineBasicMaterial color={color} opacity={0.6} transparent linewidth={2} />
37
- </line>
38
- );
39
- }
40
-
41
- // Branching bus traces (main trunk + branches)
42
- function BusBranch({
43
- trunk,
44
- branches,
45
- color = '#FFB347',
46
- }: {
47
- trunk: { start: [number, number, number]; end: [number, number, number] };
48
- branches: { start: [number, number, number]; end: [number, number, number] }[];
49
- color?: string;
50
- }) {
51
- return (
52
- <group>
53
- <BusLine start={trunk.start} end={trunk.end} color={color} />
54
- {branches.map((branch, i) => (
55
- <BusLine key={i} start={branch.start} end={branch.end} color={color} />
56
- ))}
57
- </group>
58
- );
59
- }
60
-
61
- export function DataBus({
62
- chipWidth = 16,
63
- chipHeight = 12,
64
- coreWidth = 2,
65
- coreHeight = 1.2,
66
- }: DataBusProps) {
67
- const sectionHeight = chipHeight / 3;
68
- const halfChipHeight = chipHeight / 2;
69
- const halfCoreHeight = coreHeight / 2;
70
- const halfCoreWidth = coreWidth / 2;
71
-
72
- // Z position for all traces (slightly above substrate)
73
- const z = 0.05;
74
-
75
- // Generate bus traces
76
- const busTraces = useMemo(() => {
77
- // Main vertical trunk to STM (top)
78
- const stmTrunk = {
79
- start: [0, halfCoreHeight + 0.1, z] as [number, number, number],
80
- end: [0, halfChipHeight - sectionHeight * 0.3, z] as [number, number, number],
81
- };
82
-
83
- // Branches to STM grid columns
84
- const stmBranches: { start: [number, number, number]; end: [number, number, number] }[] = [];
85
- const branchY = halfChipHeight - sectionHeight * 0.5;
86
- for (let i = -3; i <= 3; i++) {
87
- if (i !== 0) {
88
- const x = i * 1.5;
89
- stmBranches.push({
90
- start: [0, branchY, z],
91
- end: [x, branchY, z],
92
- });
93
- // Vertical segment to grid
94
- stmBranches.push({
95
- start: [x, branchY, z],
96
- end: [x, halfChipHeight - sectionHeight * 0.2, z],
97
- });
98
- }
99
- }
100
-
101
- // Main vertical trunk to LTM (bottom)
102
- const ltmTrunk = {
103
- start: [0, -halfCoreHeight - 0.1, z] as [number, number, number],
104
- end: [0, -halfChipHeight + sectionHeight * 0.3, z] as [number, number, number],
105
- };
106
-
107
- // Branches to LTM grid columns
108
- const ltmBranches: { start: [number, number, number]; end: [number, number, number] }[] = [];
109
- const ltmBranchY = -halfChipHeight + sectionHeight * 0.5;
110
- for (let i = -3; i <= 3; i++) {
111
- if (i !== 0) {
112
- const x = i * 1.5;
113
- ltmBranches.push({
114
- start: [0, ltmBranchY, z],
115
- end: [x, ltmBranchY, z],
116
- });
117
- // Vertical segment to grid
118
- ltmBranches.push({
119
- start: [x, ltmBranchY, z],
120
- end: [x, -halfChipHeight + sectionHeight * 0.2, z],
121
- });
122
- }
123
- }
124
-
125
- // Horizontal traces to Episodic (left)
126
- const episodicLeftTrunk = {
127
- start: [-halfCoreWidth - 0.1, 0, z] as [number, number, number],
128
- end: [-chipWidth / 2 + 1.5, 0, z] as [number, number, number],
129
- };
130
-
131
- const episodicLeftBranches: { start: [number, number, number]; end: [number, number, number] }[] = [];
132
- for (let i = 0; i < 3; i++) {
133
- const x = -halfCoreWidth - 1 - i * 1.5;
134
- episodicLeftBranches.push({
135
- start: [x, 0, z],
136
- end: [x, sectionHeight * 0.3, z],
137
- });
138
- episodicLeftBranches.push({
139
- start: [x, 0, z],
140
- end: [x, -sectionHeight * 0.3, z],
141
- });
142
- }
143
-
144
- // Horizontal traces to Episodic (right)
145
- const episodicRightTrunk = {
146
- start: [halfCoreWidth + 0.1, 0, z] as [number, number, number],
147
- end: [chipWidth / 2 - 1.5, 0, z] as [number, number, number],
148
- };
149
-
150
- const episodicRightBranches: { start: [number, number, number]; end: [number, number, number] }[] = [];
151
- for (let i = 0; i < 3; i++) {
152
- const x = halfCoreWidth + 1 + i * 1.5;
153
- episodicRightBranches.push({
154
- start: [x, 0, z],
155
- end: [x, sectionHeight * 0.3, z],
156
- });
157
- episodicRightBranches.push({
158
- start: [x, 0, z],
159
- end: [x, -sectionHeight * 0.3, z],
160
- });
161
- }
162
-
163
- return {
164
- stm: { trunk: stmTrunk, branches: stmBranches },
165
- ltm: { trunk: ltmTrunk, branches: ltmBranches },
166
- episodicLeft: { trunk: episodicLeftTrunk, branches: episodicLeftBranches },
167
- episodicRight: { trunk: episodicRightTrunk, branches: episodicRightBranches },
168
- };
169
- }, [chipWidth, chipHeight, halfChipHeight, halfCoreHeight, halfCoreWidth, sectionHeight]);
170
-
171
- return (
172
- <group>
173
- {/* STM bus (top) */}
174
- <BusBranch trunk={busTraces.stm.trunk} branches={busTraces.stm.branches} color="#FFB347" />
175
-
176
- {/* LTM bus (bottom) */}
177
- <BusBranch trunk={busTraces.ltm.trunk} branches={busTraces.ltm.branches} color="#FFB347" />
178
-
179
- {/* Episodic bus (left) */}
180
- <BusBranch trunk={busTraces.episodicLeft.trunk} branches={busTraces.episodicLeft.branches} color="#FFB347" />
181
-
182
- {/* Episodic bus (right) */}
183
- <BusBranch trunk={busTraces.episodicRight.trunk} branches={busTraces.episodicRight.branches} color="#FFB347" />
184
-
185
- {/* Junction nodes at branch points */}
186
- <JunctionNodes chipWidth={chipWidth} chipHeight={chipHeight} coreWidth={coreWidth} />
187
- </group>
188
- );
189
- }
190
-
191
- // Small glowing nodes at bus junctions
192
- function JunctionNodes({
193
- chipWidth,
194
- chipHeight,
195
- coreWidth,
196
- }: {
197
- chipWidth: number;
198
- chipHeight: number;
199
- coreWidth: number;
200
- }) {
201
- const nodesRef = useRef<THREE.InstancedMesh>(null);
202
- const nodeGeometry = useMemo(() => new THREE.CircleGeometry(0.06, 8), []);
203
- const nodeMaterial = useMemo(
204
- () =>
205
- new THREE.MeshBasicMaterial({
206
- color: '#FFD700',
207
- transparent: true,
208
- opacity: 0.8,
209
- }),
210
- []
211
- );
212
-
213
- const positions = useMemo(() => {
214
- const sectionHeight = chipHeight / 3;
215
- const halfChipHeight = chipHeight / 2;
216
- const halfCoreWidth = coreWidth / 2;
217
- const z = 0.06;
218
-
219
- const nodes: [number, number, number][] = [
220
- // Core connection points
221
- [0, halfCoreWidth * 0.6 + 0.1, z],
222
- [0, -halfCoreWidth * 0.6 - 0.1, z],
223
- [-halfCoreWidth - 0.1, 0, z],
224
- [halfCoreWidth + 0.1, 0, z],
225
- ];
226
-
227
- // STM branch junctions
228
- const stmBranchY = halfChipHeight - sectionHeight * 0.5;
229
- for (let i = -3; i <= 3; i++) {
230
- if (i !== 0) {
231
- nodes.push([i * 1.5, stmBranchY, z]);
232
- }
233
- }
234
-
235
- // LTM branch junctions
236
- const ltmBranchY = -halfChipHeight + sectionHeight * 0.5;
237
- for (let i = -3; i <= 3; i++) {
238
- if (i !== 0) {
239
- nodes.push([i * 1.5, ltmBranchY, z]);
240
- }
241
- }
242
-
243
- // Episodic branch junctions
244
- for (let i = 0; i < 3; i++) {
245
- nodes.push([-halfCoreWidth - 1 - i * 1.5, 0, z]);
246
- nodes.push([halfCoreWidth + 1 + i * 1.5, 0, z]);
247
- }
248
-
249
- return nodes;
250
- }, [chipHeight, coreWidth]);
251
-
252
- // Animate junction glow
253
- useFrame((state) => {
254
- if (nodesRef.current) {
255
- const material = nodesRef.current.material as THREE.MeshBasicMaterial;
256
- const pulse = Math.sin(state.clock.elapsedTime * 3) * 0.5 + 0.5;
257
- material.opacity = 0.5 + pulse * 0.3;
258
- }
259
- });
260
-
261
- return (
262
- <instancedMesh
263
- ref={nodesRef}
264
- args={[nodeGeometry, nodeMaterial, positions.length]}
265
- >
266
- {positions.map((pos, i) => {
267
- const matrix = new THREE.Matrix4().setPosition(...pos);
268
- nodesRef.current?.setMatrixAt(i, matrix);
269
- return null;
270
- })}
271
- </instancedMesh>
272
- );
273
- }
274
-
275
- // Pulse that travels along the data bus
276
- export interface AccessPulseData {
277
- id: number;
278
- memoryId: number;
279
- section: 'stm' | 'episodic' | 'ltm';
280
- gridPosition: [number, number]; // Column, row in grid
281
- color: string;
282
- startTime: number;
283
- }
284
-
285
- interface DataBusPulseProps {
286
- pulse: AccessPulseData;
287
- chipWidth: number;
288
- chipHeight: number;
289
- onComplete: (id: number) => void;
290
- }
291
-
292
- export function DataBusPulse({
293
- pulse,
294
- chipWidth,
295
- chipHeight,
296
- onComplete,
297
- }: DataBusPulseProps) {
298
- const pulseRef = useRef<THREE.Mesh>(null);
299
- const trailRef = useRef<THREE.Mesh>(null);
300
- const startTimeRef = useRef(pulse.startTime);
301
-
302
- const sectionHeight = chipHeight / 3;
303
- const halfChipHeight = chipHeight / 2;
304
-
305
- // Calculate path based on section
306
- const path = useMemo(() => {
307
- const z = 0.1;
308
- const [col] = pulse.gridPosition;
309
- const targetX = (col - 3) * 1.5; // Map grid column to x position
310
-
311
- let targetY: number;
312
- let midY: number;
313
-
314
- switch (pulse.section) {
315
- case 'stm':
316
- targetY = halfChipHeight - sectionHeight * 0.3;
317
- midY = halfChipHeight - sectionHeight * 0.5;
318
- return [
319
- [0, 0, z], // Start at core
320
- [0, midY, z], // Up the trunk
321
- [targetX, midY, z], // Along branch
322
- [targetX, targetY, z], // To memory
323
- ];
324
- case 'ltm':
325
- targetY = -halfChipHeight + sectionHeight * 0.3;
326
- midY = -halfChipHeight + sectionHeight * 0.5;
327
- return [
328
- [0, 0, z],
329
- [0, midY, z],
330
- [targetX, midY, z],
331
- [targetX, targetY, z],
332
- ];
333
- case 'episodic':
334
- default:
335
- const side = col < 3 ? -1 : 1;
336
- targetX;
337
- return [
338
- [0, 0, z],
339
- [side * (Math.abs(targetX) + 1), 0, z],
340
- [side * (Math.abs(targetX) + 1), pulse.gridPosition[1] * 0.8, z],
341
- ];
342
- }
343
- }, [pulse, halfChipHeight, sectionHeight]);
344
-
345
- const duration = 500; // ms
346
-
347
- useFrame(() => {
348
- if (!pulseRef.current) return;
349
-
350
- const elapsed = Date.now() - startTimeRef.current;
351
- const progress = Math.min(elapsed / duration, 1);
352
-
353
- if (progress >= 1) {
354
- onComplete(pulse.id);
355
- return;
356
- }
357
-
358
- // Interpolate position along path
359
- const totalSegments = path.length - 1;
360
- const segmentProgress = progress * totalSegments;
361
- const segmentIndex = Math.floor(segmentProgress);
362
- const segmentT = segmentProgress - segmentIndex;
363
-
364
- const currentIdx = Math.min(segmentIndex, totalSegments - 1);
365
- const start = path[currentIdx];
366
- const end = path[Math.min(currentIdx + 1, path.length - 1)];
367
-
368
- pulseRef.current.position.set(
369
- start[0] + (end[0] - start[0]) * segmentT,
370
- start[1] + (end[1] - start[1]) * segmentT,
371
- start[2] + (end[2] - start[2]) * segmentT
372
- );
373
-
374
- // Scale down as it travels
375
- const scale = 1 - progress * 0.3;
376
- pulseRef.current.scale.setScalar(scale);
377
-
378
- // Trail follows slightly behind
379
- if (trailRef.current && progress > 0.1) {
380
- const trailProgress = Math.max(0, progress - 0.1);
381
- const trailSegmentProgress = trailProgress * totalSegments;
382
- const trailSegmentIndex = Math.floor(trailSegmentProgress);
383
- const trailSegmentT = trailSegmentProgress - trailSegmentIndex;
384
-
385
- const trailIdx = Math.min(trailSegmentIndex, totalSegments - 1);
386
- const trailStart = path[trailIdx];
387
- const trailEnd = path[Math.min(trailIdx + 1, path.length - 1)];
388
-
389
- trailRef.current.position.set(
390
- trailStart[0] + (trailEnd[0] - trailStart[0]) * trailSegmentT,
391
- trailStart[1] + (trailEnd[1] - trailStart[1]) * trailSegmentT,
392
- trailStart[2] + (trailEnd[2] - trailStart[2]) * trailSegmentT
393
- );
394
- trailRef.current.scale.setScalar(scale * 0.6);
395
-
396
- const trailMaterial = trailRef.current.material as THREE.MeshBasicMaterial;
397
- trailMaterial.opacity = 0.4 * (1 - progress);
398
- }
399
- });
400
-
401
- return (
402
- <group>
403
- {/* Main pulse */}
404
- <mesh ref={pulseRef} position={[0, 0, 0.1]}>
405
- <circleGeometry args={[0.12, 16]} />
406
- <meshBasicMaterial color={pulse.color} transparent opacity={0.9} />
407
- </mesh>
408
-
409
- {/* Trail */}
410
- <mesh ref={trailRef} position={[0, 0, 0.1]}>
411
- <circleGeometry args={[0.08, 12]} />
412
- <meshBasicMaterial color={pulse.color} transparent opacity={0.4} />
413
- </mesh>
414
- </group>
415
- );
416
- }
@@ -1,225 +0,0 @@
1
- 'use client';
2
-
3
- /**
4
- * Memory Cell
5
- * Standard rectangular memory node for the chip grid
6
- * Color-coded by category with glow based on salience
7
- */
8
-
9
- import { useRef, useMemo, useState, useCallback } from 'react';
10
- import { useFrame, ThreeEvent } from '@react-three/fiber';
11
- import { Html } from '@react-three/drei';
12
- import * as THREE from 'three';
13
- import { Memory, MemoryCategory } from '@/types/memory';
14
-
15
- // Category color mapping
16
- const CATEGORY_COLORS: Record<MemoryCategory, string> = {
17
- architecture: '#06b6d4', // cyan
18
- pattern: '#22c55e', // green
19
- preference: '#eab308', // yellow
20
- error: '#ef4444', // red
21
- context: '#f97316', // orange
22
- learning: '#84cc16', // lime
23
- todo: '#a855f7', // purple
24
- note: '#3b82f6', // blue
25
- relationship: '#6366f1', // indigo
26
- custom: '#ec4899', // pink
27
- };
28
-
29
- interface MemoryCellProps {
30
- memory: Memory;
31
- position: [number, number, number];
32
- onSelect?: (memory: Memory | null) => void;
33
- isSelected?: boolean;
34
- size?: number;
35
- }
36
-
37
- // Shared geometry for performance
38
- const CELL_GEOMETRY = new THREE.BoxGeometry(0.8, 0.5, 0.15);
39
-
40
- export function MemoryCell({
41
- memory,
42
- position,
43
- onSelect,
44
- isSelected = false,
45
- size = 1,
46
- }: MemoryCellProps) {
47
- const meshRef = useRef<THREE.Mesh>(null);
48
- const glowRef = useRef<THREE.Mesh>(null);
49
- const [isHovered, setIsHovered] = useState(false);
50
-
51
- const color = CATEGORY_COLORS[memory.category] || CATEGORY_COLORS.custom;
52
-
53
- // Main material
54
- const material = useMemo(() => {
55
- return new THREE.MeshStandardMaterial({
56
- color: color,
57
- emissive: color,
58
- emissiveIntensity: 0.3 + memory.salience * 0.4,
59
- metalness: 0.2,
60
- roughness: 0.6,
61
- });
62
- }, [color, memory.salience]);
63
-
64
- // Glow material
65
- const glowMaterial = useMemo(() => {
66
- return new THREE.MeshBasicMaterial({
67
- color: color,
68
- transparent: true,
69
- opacity: 0.15 + memory.salience * 0.2,
70
- side: THREE.BackSide,
71
- });
72
- }, [color, memory.salience]);
73
-
74
- // Selection ring material
75
- const selectionMaterial = useMemo(() => {
76
- return new THREE.MeshBasicMaterial({
77
- color: '#ffffff',
78
- transparent: true,
79
- opacity: 0.8,
80
- side: THREE.DoubleSide,
81
- });
82
- }, []);
83
-
84
- // Animate pulse
85
- useFrame((state) => {
86
- if (!meshRef.current) return;
87
-
88
- const time = state.clock.elapsedTime;
89
- const mat = meshRef.current.material as THREE.MeshStandardMaterial;
90
-
91
- // Base pulse based on salience (higher salience = faster pulse)
92
- const pulseSpeed = 1 + memory.salience * 2;
93
- const pulse = Math.sin(time * pulseSpeed) * 0.5 + 0.5;
94
-
95
- // Adjust emissive intensity
96
- mat.emissiveIntensity = 0.2 + memory.salience * 0.3 + pulse * 0.15;
97
-
98
- // Hover effect
99
- if (isHovered || isSelected) {
100
- mat.emissiveIntensity += 0.3;
101
- }
102
-
103
- // Glow pulse
104
- if (glowRef.current) {
105
- const glowMat = glowRef.current.material as THREE.MeshBasicMaterial;
106
- glowMat.opacity = 0.1 + pulse * 0.1 + memory.salience * 0.15;
107
- if (isHovered || isSelected) {
108
- glowMat.opacity += 0.15;
109
- }
110
- }
111
- });
112
-
113
- const handleClick = useCallback(
114
- (e: ThreeEvent<MouseEvent>) => {
115
- e.stopPropagation();
116
- onSelect?.(isSelected ? null : memory);
117
- },
118
- [memory, onSelect, isSelected]
119
- );
120
-
121
- const handlePointerOver = useCallback((e: ThreeEvent<PointerEvent>) => {
122
- e.stopPropagation();
123
- setIsHovered(true);
124
- document.body.style.cursor = 'pointer';
125
- }, []);
126
-
127
- const handlePointerOut = useCallback(() => {
128
- setIsHovered(false);
129
- document.body.style.cursor = 'auto';
130
- }, []);
131
-
132
- return (
133
- <group position={position} scale={size}>
134
- {/* Main cell */}
135
- <mesh
136
- ref={meshRef}
137
- geometry={CELL_GEOMETRY}
138
- material={material}
139
- onClick={handleClick}
140
- onPointerOver={handlePointerOver}
141
- onPointerOut={handlePointerOut}
142
- />
143
-
144
- {/* Glow layer */}
145
- <mesh ref={glowRef} scale={1.15}>
146
- <boxGeometry args={[0.85, 0.55, 0.2]} />
147
- <primitive object={glowMaterial} />
148
- </mesh>
149
-
150
- {/* Selection indicator */}
151
- {isSelected && (
152
- <mesh rotation={[Math.PI / 2, 0, 0]} position={[0, 0, 0.1]}>
153
- <ringGeometry args={[0.5, 0.55, 4]} />
154
- <primitive object={selectionMaterial} />
155
- </mesh>
156
- )}
157
-
158
- {/* Tooltip on hover */}
159
- {isHovered && (
160
- <Html
161
- position={[0, 0.5, 0]}
162
- center
163
- style={{
164
- pointerEvents: 'none',
165
- transform: 'translateY(-100%)',
166
- }}
167
- >
168
- <div className="bg-slate-900/95 border border-slate-600 rounded-lg px-3 py-2 text-xs max-w-[200px] backdrop-blur-sm shadow-lg">
169
- <div className="font-semibold text-white truncate">{memory.title}</div>
170
- <div className="text-slate-400 mt-1 flex items-center gap-2">
171
- <span
172
- className="w-2 h-2 rounded-full"
173
- style={{ backgroundColor: color }}
174
- />
175
- <span className="capitalize">{memory.category}</span>
176
- <span className="text-slate-500">|</span>
177
- <span>{Math.round(memory.salience * 100)}%</span>
178
- </div>
179
- </div>
180
- </Html>
181
- )}
182
- </group>
183
- );
184
- }
185
-
186
- // Flash effect when memory is accessed
187
- export function MemoryCellFlash({
188
- position,
189
- color,
190
- onComplete,
191
- }: {
192
- position: [number, number, number];
193
- color: string;
194
- onComplete: () => void;
195
- }) {
196
- const meshRef = useRef<THREE.Mesh>(null);
197
- const startTime = useRef(Date.now());
198
-
199
- useFrame(() => {
200
- if (!meshRef.current) return;
201
-
202
- const elapsed = Date.now() - startTime.current;
203
- const duration = 400;
204
- const progress = elapsed / duration;
205
-
206
- if (progress >= 1) {
207
- onComplete();
208
- return;
209
- }
210
-
211
- // Expand and fade
212
- const scale = 1 + progress * 0.5;
213
- meshRef.current.scale.setScalar(scale);
214
-
215
- const mat = meshRef.current.material as THREE.MeshBasicMaterial;
216
- mat.opacity = 0.8 * (1 - progress);
217
- });
218
-
219
- return (
220
- <mesh ref={meshRef} position={position}>
221
- <boxGeometry args={[0.9, 0.6, 0.2]} />
222
- <meshBasicMaterial color={color} transparent opacity={0.8} />
223
- </mesh>
224
- );
225
- }