shieldcortex 2.0.0
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/LICENSE +21 -0
- package/README.md +282 -0
- package/dashboard/components.json +22 -0
- package/dashboard/eslint.config.mjs +42 -0
- package/dashboard/next.config.ts +7 -0
- package/dashboard/package-lock.json +8053 -0
- package/dashboard/package.json +44 -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/scripts/ensure-api.mjs +76 -0
- package/dashboard/src/app/error.tsx +49 -0
- package/dashboard/src/app/favicon.ico +0 -0
- package/dashboard/src/app/globals.css +130 -0
- package/dashboard/src/app/layout.tsx +35 -0
- package/dashboard/src/app/page.tsx +364 -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 +133 -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 +312 -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 +106 -0
- package/dashboard/src/components/controls/VersionPanel.tsx +185 -0
- package/dashboard/src/components/dashboard/StatsPanel.tsx +164 -0
- package/dashboard/src/components/debug/ActivityLog.tsx +250 -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 +319 -0
- package/dashboard/src/components/graph/KnowledgeGraph.tsx +230 -0
- package/dashboard/src/components/graph/OntologyGraph.tsx +631 -0
- package/dashboard/src/components/insights/ActivityHeatmap.tsx +131 -0
- package/dashboard/src/components/insights/InsightsView.tsx +46 -0
- package/dashboard/src/components/insights/KnowledgeMapPanel.tsx +80 -0
- package/dashboard/src/components/insights/QualityPanel.tsx +116 -0
- package/dashboard/src/components/memories/MemoriesView.tsx +150 -0
- package/dashboard/src/components/memories/MemoryCard.tsx +103 -0
- package/dashboard/src/components/memory/MemoryDetail.tsx +325 -0
- package/dashboard/src/components/nav/NavRail.tsx +54 -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 +458 -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 +249 -0
- package/dashboard/src/types/memory.ts +73 -0
- package/dashboard/tsconfig.json +34 -0
- package/dist/__tests__/consolidation-merge.test.d.ts +9 -0
- package/dist/__tests__/consolidation-merge.test.d.ts.map +1 -0
- package/dist/__tests__/consolidation-merge.test.js +137 -0
- package/dist/__tests__/consolidation-merge.test.js.map +1 -0
- package/dist/__tests__/contradictions.test.d.ts +8 -0
- package/dist/__tests__/contradictions.test.d.ts.map +1 -0
- package/dist/__tests__/contradictions.test.js +78 -0
- package/dist/__tests__/contradictions.test.js.map +1 -0
- package/dist/__tests__/salience-evolution.test.d.ts +7 -0
- package/dist/__tests__/salience-evolution.test.d.ts.map +1 -0
- package/dist/__tests__/salience-evolution.test.js +151 -0
- package/dist/__tests__/salience-evolution.test.js.map +1 -0
- package/dist/__tests__/store.test.d.ts +7 -0
- package/dist/__tests__/store.test.d.ts.map +1 -0
- package/dist/__tests__/store.test.js +582 -0
- package/dist/__tests__/store.test.js.map +1 -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/events.d.ts +159 -0
- package/dist/api/events.d.ts.map +1 -0
- package/dist/api/events.js +155 -0
- package/dist/api/events.js.map +1 -0
- package/dist/api/version.d.ts +36 -0
- package/dist/api/version.d.ts.map +1 -0
- package/dist/api/version.js +146 -0
- package/dist/api/version.js.map +1 -0
- package/dist/api/visualization-server.d.ts +11 -0
- package/dist/api/visualization-server.d.ts.map +1 -0
- package/dist/api/visualization-server.js +1186 -0
- package/dist/api/visualization-server.js.map +1 -0
- package/dist/context/project-context.d.ts +57 -0
- package/dist/context/project-context.d.ts.map +1 -0
- package/dist/context/project-context.js +135 -0
- package/dist/context/project-context.js.map +1 -0
- package/dist/database/init.d.ts +49 -0
- package/dist/database/init.d.ts.map +1 -0
- package/dist/database/init.js +567 -0
- package/dist/database/init.js.map +1 -0
- package/dist/defence/__tests__/firewall.test.d.ts +8 -0
- package/dist/defence/__tests__/firewall.test.d.ts.map +1 -0
- package/dist/defence/__tests__/firewall.test.js +123 -0
- package/dist/defence/__tests__/firewall.test.js.map +1 -0
- package/dist/defence/__tests__/fragmentation.test.d.ts +7 -0
- package/dist/defence/__tests__/fragmentation.test.d.ts.map +1 -0
- package/dist/defence/__tests__/fragmentation.test.js +51 -0
- package/dist/defence/__tests__/fragmentation.test.js.map +1 -0
- package/dist/defence/__tests__/pipeline.test.d.ts +8 -0
- package/dist/defence/__tests__/pipeline.test.d.ts.map +1 -0
- package/dist/defence/__tests__/pipeline.test.js +61 -0
- package/dist/defence/__tests__/pipeline.test.js.map +1 -0
- package/dist/defence/__tests__/sensitivity.test.d.ts +7 -0
- package/dist/defence/__tests__/sensitivity.test.d.ts.map +1 -0
- package/dist/defence/__tests__/sensitivity.test.js +61 -0
- package/dist/defence/__tests__/sensitivity.test.js.map +1 -0
- package/dist/defence/__tests__/trust.test.d.ts +7 -0
- package/dist/defence/__tests__/trust.test.d.ts.map +1 -0
- package/dist/defence/__tests__/trust.test.js +49 -0
- package/dist/defence/__tests__/trust.test.js.map +1 -0
- package/dist/defence/audit/index.d.ts +4 -0
- package/dist/defence/audit/index.d.ts.map +1 -0
- package/dist/defence/audit/index.js +3 -0
- package/dist/defence/audit/index.js.map +1 -0
- package/dist/defence/audit/logger.d.ts +14 -0
- package/dist/defence/audit/logger.d.ts.map +1 -0
- package/dist/defence/audit/logger.js +54 -0
- package/dist/defence/audit/logger.js.map +1 -0
- package/dist/defence/audit/queries.d.ts +33 -0
- package/dist/defence/audit/queries.d.ts.map +1 -0
- package/dist/defence/audit/queries.js +103 -0
- package/dist/defence/audit/queries.js.map +1 -0
- package/dist/defence/firewall/anomaly-scorer.d.ts +8 -0
- package/dist/defence/firewall/anomaly-scorer.d.ts.map +1 -0
- package/dist/defence/firewall/anomaly-scorer.js +58 -0
- package/dist/defence/firewall/anomaly-scorer.js.map +1 -0
- package/dist/defence/firewall/encoding-detector.d.ts +13 -0
- package/dist/defence/firewall/encoding-detector.d.ts.map +1 -0
- package/dist/defence/firewall/encoding-detector.js +120 -0
- package/dist/defence/firewall/encoding-detector.js.map +1 -0
- package/dist/defence/firewall/index.d.ts +21 -0
- package/dist/defence/firewall/index.d.ts.map +1 -0
- package/dist/defence/firewall/index.js +133 -0
- package/dist/defence/firewall/index.js.map +1 -0
- package/dist/defence/firewall/instruction-detector.d.ts +12 -0
- package/dist/defence/firewall/instruction-detector.d.ts.map +1 -0
- package/dist/defence/firewall/instruction-detector.js +99 -0
- package/dist/defence/firewall/instruction-detector.js.map +1 -0
- package/dist/defence/firewall/privilege-detector.d.ts +13 -0
- package/dist/defence/firewall/privilege-detector.d.ts.map +1 -0
- package/dist/defence/firewall/privilege-detector.js +89 -0
- package/dist/defence/firewall/privilege-detector.js.map +1 -0
- package/dist/defence/fragmentation/assembly-detector.d.ts +18 -0
- package/dist/defence/fragmentation/assembly-detector.d.ts.map +1 -0
- package/dist/defence/fragmentation/assembly-detector.js +72 -0
- package/dist/defence/fragmentation/assembly-detector.js.map +1 -0
- package/dist/defence/fragmentation/entity-extractor.d.ts +19 -0
- package/dist/defence/fragmentation/entity-extractor.d.ts.map +1 -0
- package/dist/defence/fragmentation/entity-extractor.js +86 -0
- package/dist/defence/fragmentation/entity-extractor.js.map +1 -0
- package/dist/defence/fragmentation/index.d.ts +23 -0
- package/dist/defence/fragmentation/index.d.ts.map +1 -0
- package/dist/defence/fragmentation/index.js +49 -0
- package/dist/defence/fragmentation/index.js.map +1 -0
- package/dist/defence/fragmentation/temporal-analyzer.d.ts +28 -0
- package/dist/defence/fragmentation/temporal-analyzer.d.ts.map +1 -0
- package/dist/defence/fragmentation/temporal-analyzer.js +41 -0
- package/dist/defence/fragmentation/temporal-analyzer.js.map +1 -0
- package/dist/defence/index.d.ts +12 -0
- package/dist/defence/index.d.ts.map +1 -0
- package/dist/defence/index.js +18 -0
- package/dist/defence/index.js.map +1 -0
- package/dist/defence/pipeline.d.ts +9 -0
- package/dist/defence/pipeline.d.ts.map +1 -0
- package/dist/defence/pipeline.js +115 -0
- package/dist/defence/pipeline.js.map +1 -0
- package/dist/defence/scanner/index.d.ts +5 -0
- package/dist/defence/scanner/index.d.ts.map +1 -0
- package/dist/defence/scanner/index.js +5 -0
- package/dist/defence/scanner/index.js.map +1 -0
- package/dist/defence/scanner/scan-existing.d.ts +34 -0
- package/dist/defence/scanner/scan-existing.d.ts.map +1 -0
- package/dist/defence/scanner/scan-existing.js +136 -0
- package/dist/defence/scanner/scan-existing.js.map +1 -0
- package/dist/defence/sensitivity/classifier.d.ts +6 -0
- package/dist/defence/sensitivity/classifier.d.ts.map +1 -0
- package/dist/defence/sensitivity/classifier.js +50 -0
- package/dist/defence/sensitivity/classifier.js.map +1 -0
- package/dist/defence/sensitivity/index.d.ts +11 -0
- package/dist/defence/sensitivity/index.d.ts.map +1 -0
- package/dist/defence/sensitivity/index.js +13 -0
- package/dist/defence/sensitivity/index.js.map +1 -0
- package/dist/defence/sensitivity/patterns.d.ts +14 -0
- package/dist/defence/sensitivity/patterns.d.ts.map +1 -0
- package/dist/defence/sensitivity/patterns.js +67 -0
- package/dist/defence/sensitivity/patterns.js.map +1 -0
- package/dist/defence/sensitivity/redaction.d.ts +17 -0
- package/dist/defence/sensitivity/redaction.d.ts.map +1 -0
- package/dist/defence/sensitivity/redaction.js +47 -0
- package/dist/defence/sensitivity/redaction.js.map +1 -0
- package/dist/defence/trust/index.d.ts +3 -0
- package/dist/defence/trust/index.d.ts.map +1 -0
- package/dist/defence/trust/index.js +3 -0
- package/dist/defence/trust/index.js.map +1 -0
- package/dist/defence/trust/recall-filter.d.ts +10 -0
- package/dist/defence/trust/recall-filter.d.ts.map +1 -0
- package/dist/defence/trust/recall-filter.js +38 -0
- package/dist/defence/trust/recall-filter.js.map +1 -0
- package/dist/defence/trust/source-scorer.d.ts +6 -0
- package/dist/defence/trust/source-scorer.d.ts.map +1 -0
- package/dist/defence/trust/source-scorer.js +34 -0
- package/dist/defence/trust/source-scorer.js.map +1 -0
- package/dist/defence/types.d.ts +88 -0
- package/dist/defence/types.d.ts.map +1 -0
- package/dist/defence/types.js +15 -0
- package/dist/defence/types.js.map +1 -0
- package/dist/embeddings/generator.d.ts +20 -0
- package/dist/embeddings/generator.d.ts.map +1 -0
- package/dist/embeddings/generator.js +83 -0
- package/dist/embeddings/generator.js.map +1 -0
- package/dist/embeddings/index.d.ts +2 -0
- package/dist/embeddings/index.d.ts.map +1 -0
- package/dist/embeddings/index.js +2 -0
- package/dist/embeddings/index.js.map +1 -0
- package/dist/errors.d.ts +74 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +131 -0
- package/dist/errors.js.map +1 -0
- package/dist/graph/backfill.d.ts +6 -0
- package/dist/graph/backfill.d.ts.map +1 -0
- package/dist/graph/backfill.js +33 -0
- package/dist/graph/backfill.js.map +1 -0
- package/dist/graph/extract.d.ts +21 -0
- package/dist/graph/extract.d.ts.map +1 -0
- package/dist/graph/extract.js +231 -0
- package/dist/graph/extract.js.map +1 -0
- package/dist/graph/resolve.d.ts +6 -0
- package/dist/graph/resolve.d.ts.map +1 -0
- package/dist/graph/resolve.js +126 -0
- package/dist/graph/resolve.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +248 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/activation.d.ts +69 -0
- package/dist/memory/activation.d.ts.map +1 -0
- package/dist/memory/activation.js +168 -0
- package/dist/memory/activation.js.map +1 -0
- package/dist/memory/consolidate.d.ts +98 -0
- package/dist/memory/consolidate.d.ts.map +1 -0
- package/dist/memory/consolidate.js +511 -0
- package/dist/memory/consolidate.js.map +1 -0
- package/dist/memory/contradiction.d.ts +69 -0
- package/dist/memory/contradiction.d.ts.map +1 -0
- package/dist/memory/contradiction.js +286 -0
- package/dist/memory/contradiction.js.map +1 -0
- package/dist/memory/decay.d.ts +62 -0
- package/dist/memory/decay.d.ts.map +1 -0
- package/dist/memory/decay.js +184 -0
- package/dist/memory/decay.js.map +1 -0
- package/dist/memory/salience.d.ts +36 -0
- package/dist/memory/salience.d.ts.map +1 -0
- package/dist/memory/salience.js +216 -0
- package/dist/memory/salience.js.map +1 -0
- package/dist/memory/similarity.d.ts +57 -0
- package/dist/memory/similarity.d.ts.map +1 -0
- package/dist/memory/similarity.js +114 -0
- package/dist/memory/similarity.js.map +1 -0
- package/dist/memory/store.d.ts +179 -0
- package/dist/memory/store.d.ts.map +1 -0
- package/dist/memory/store.js +1184 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/memory/types.d.ts +97 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +30 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/server.d.ts +12 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +568 -0
- package/dist/server.js.map +1 -0
- package/dist/service/install.d.ts +15 -0
- package/dist/service/install.d.ts.map +1 -0
- package/dist/service/install.js +178 -0
- package/dist/service/install.js.map +1 -0
- package/dist/service/templates.d.ts +13 -0
- package/dist/service/templates.d.ts.map +1 -0
- package/dist/service/templates.js +58 -0
- package/dist/service/templates.js.map +1 -0
- package/dist/setup/claude-md.d.ts +12 -0
- package/dist/setup/claude-md.d.ts.map +1 -0
- package/dist/setup/claude-md.js +68 -0
- package/dist/setup/claude-md.js.map +1 -0
- package/dist/setup/clawdbot.d.ts +15 -0
- package/dist/setup/clawdbot.d.ts.map +1 -0
- package/dist/setup/clawdbot.js +118 -0
- package/dist/setup/clawdbot.js.map +1 -0
- package/dist/setup/doctor.d.ts +5 -0
- package/dist/setup/doctor.d.ts.map +1 -0
- package/dist/setup/doctor.js +141 -0
- package/dist/setup/doctor.js.map +1 -0
- package/dist/setup/hooks.d.ts +6 -0
- package/dist/setup/hooks.d.ts.map +1 -0
- package/dist/setup/hooks.js +36 -0
- package/dist/setup/hooks.js.map +1 -0
- package/dist/setup/migrate.d.ts +16 -0
- package/dist/setup/migrate.d.ts.map +1 -0
- package/dist/setup/migrate.js +164 -0
- package/dist/setup/migrate.js.map +1 -0
- package/dist/setup/settings-hooks.d.ts +7 -0
- package/dist/setup/settings-hooks.d.ts.map +1 -0
- package/dist/setup/settings-hooks.js +83 -0
- package/dist/setup/settings-hooks.js.map +1 -0
- package/dist/setup/uninstall.d.ts +12 -0
- package/dist/setup/uninstall.d.ts.map +1 -0
- package/dist/setup/uninstall.js +125 -0
- package/dist/setup/uninstall.js.map +1 -0
- package/dist/tools/context.d.ts +135 -0
- package/dist/tools/context.d.ts.map +1 -0
- package/dist/tools/context.js +273 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/forget.d.ts +53 -0
- package/dist/tools/forget.d.ts.map +1 -0
- package/dist/tools/forget.js +179 -0
- package/dist/tools/forget.js.map +1 -0
- package/dist/tools/graph.d.ts +46 -0
- package/dist/tools/graph.d.ts.map +1 -0
- package/dist/tools/graph.js +206 -0
- package/dist/tools/graph.js.map +1 -0
- package/dist/tools/recall.d.ts +79 -0
- package/dist/tools/recall.d.ts.map +1 -0
- package/dist/tools/recall.js +156 -0
- package/dist/tools/recall.js.map +1 -0
- package/dist/tools/remember.d.ts +83 -0
- package/dist/tools/remember.d.ts.map +1 -0
- package/dist/tools/remember.js +151 -0
- package/dist/tools/remember.js.map +1 -0
- package/dist/worker/brain-worker.d.ts +100 -0
- package/dist/worker/brain-worker.d.ts.map +1 -0
- package/dist/worker/brain-worker.js +283 -0
- package/dist/worker/brain-worker.js.map +1 -0
- package/dist/worker/link-discovery.d.ts +47 -0
- package/dist/worker/link-discovery.d.ts.map +1 -0
- package/dist/worker/link-discovery.js +103 -0
- package/dist/worker/link-discovery.js.map +1 -0
- package/dist/worker/predictive-consolidation.d.ts +46 -0
- package/dist/worker/predictive-consolidation.d.ts.map +1 -0
- package/dist/worker/predictive-consolidation.js +110 -0
- package/dist/worker/predictive-consolidation.js.map +1 -0
- package/dist/worker/types.d.ts +91 -0
- package/dist/worker/types.d.ts.map +1 -0
- package/dist/worker/types.js +22 -0
- package/dist/worker/types.js.map +1 -0
- package/hooks/clawdbot/cortex-memory/HOOK.md +71 -0
- package/hooks/clawdbot/cortex-memory/handler.js +279 -0
- package/package.json +73 -0
- package/scripts/pre-compact-hook.mjs +716 -0
- package/scripts/session-end-hook.mjs +548 -0
- package/scripts/session-start-hook.mjs +221 -0
- package/scripts/start-dashboard.sh +41 -0
- package/scripts/stop-dashboard.sh +21 -0
- package/scripts/stop-hook.mjs +163 -0
|
@@ -0,0 +1,133 @@
|
|
|
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, useRef } 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
|
+
const x = positions[i];
|
|
30
|
+
const y = positions[i + 1];
|
|
31
|
+
const 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
|
+
// Use refs to track resources for proper cleanup
|
|
89
|
+
const geometryRef = useRef<THREE.BufferGeometry | null>(null);
|
|
90
|
+
const materialRef = useRef<THREE.MeshBasicMaterial | null>(null);
|
|
91
|
+
|
|
92
|
+
// Create geometry once
|
|
93
|
+
const brainGeometry = useMemo(() => {
|
|
94
|
+
const geo = createBrainGeometry();
|
|
95
|
+
geometryRef.current = geo;
|
|
96
|
+
return geo;
|
|
97
|
+
}, []);
|
|
98
|
+
|
|
99
|
+
// Ghost wireframe material - very faint gray
|
|
100
|
+
const wireframeMaterial = useMemo(() => {
|
|
101
|
+
const mat = new THREE.MeshBasicMaterial({
|
|
102
|
+
color: '#333333',
|
|
103
|
+
wireframe: true,
|
|
104
|
+
transparent: true,
|
|
105
|
+
opacity: opacity,
|
|
106
|
+
});
|
|
107
|
+
materialRef.current = mat;
|
|
108
|
+
return mat;
|
|
109
|
+
}, [opacity]);
|
|
110
|
+
|
|
111
|
+
// Cleanup on unmount to prevent GPU memory leaks
|
|
112
|
+
// Use refs to ensure we always dispose the actual resources
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
return () => {
|
|
115
|
+
if (geometryRef.current) {
|
|
116
|
+
geometryRef.current.dispose();
|
|
117
|
+
geometryRef.current = null;
|
|
118
|
+
}
|
|
119
|
+
if (materialRef.current) {
|
|
120
|
+
materialRef.current.dispose();
|
|
121
|
+
materialRef.current = null;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}, []);
|
|
125
|
+
|
|
126
|
+
// Only render wireframe - no solid surface, no core, no animation
|
|
127
|
+
if (!showWireframe) return null;
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<mesh geometry={brainGeometry} material={wireframeMaterial} />
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Brain Scene
|
|
5
|
+
* Main 3D visualization of the memory brain
|
|
6
|
+
* Composes all brain visualization components into a cohesive scene
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Real-time activity pulses on memory events
|
|
10
|
+
* - Category region labels
|
|
11
|
+
* - Color modes: category, health (decay), age
|
|
12
|
+
* - Timeline filtering
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { Suspense, useMemo, useState, useCallback } from 'react';
|
|
16
|
+
import { Canvas } from '@react-three/fiber';
|
|
17
|
+
import { OrbitControls } from '@react-three/drei';
|
|
18
|
+
// Post-processing disabled for cleaner appearance
|
|
19
|
+
// import { EffectComposer, Bloom, Vignette, ChromaticAberration, Noise } from '@react-three/postprocessing';
|
|
20
|
+
import { Memory, MemoryLink } from '@/types/memory';
|
|
21
|
+
import { MemoryNode } from './MemoryNode';
|
|
22
|
+
import { MemoryLinks } from './MemoryLinks';
|
|
23
|
+
import { BrainMesh } from './BrainMesh';
|
|
24
|
+
import { ActivityPulseSystem, Pulse } from './ActivityPulseSystem';
|
|
25
|
+
import { TimelineControls } from './TimelineControls';
|
|
26
|
+
// Removed for cleaner design: BrainRegions, Stars
|
|
27
|
+
import { calculateMemoryPosition } from '@/lib/position-algorithm';
|
|
28
|
+
import { useMemoryWebSocket } from '@/lib/websocket';
|
|
29
|
+
|
|
30
|
+
type ColorMode = 'category' | 'health' | 'age' | 'holographic';
|
|
31
|
+
|
|
32
|
+
interface BrainSceneProps {
|
|
33
|
+
memories: Memory[];
|
|
34
|
+
links?: MemoryLink[];
|
|
35
|
+
selectedMemory: Memory | null;
|
|
36
|
+
onSelectMemory: (memory: Memory | null) => void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface BrainContentProps extends BrainSceneProps {
|
|
40
|
+
colorMode: ColorMode;
|
|
41
|
+
pulses: Pulse[];
|
|
42
|
+
onPulseComplete: (id: number) => void;
|
|
43
|
+
memoryCategoryCounts: Record<string, number>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function BrainContent({
|
|
47
|
+
memories = [],
|
|
48
|
+
links = [],
|
|
49
|
+
selectedMemory,
|
|
50
|
+
onSelectMemory,
|
|
51
|
+
colorMode,
|
|
52
|
+
pulses,
|
|
53
|
+
onPulseComplete,
|
|
54
|
+
memoryCategoryCounts: _memoryCategoryCounts,
|
|
55
|
+
}: BrainContentProps) {
|
|
56
|
+
// Calculate positions for all memories (deduplicate by ID to prevent React key errors)
|
|
57
|
+
const memoryPositions = useMemo(() => {
|
|
58
|
+
if (!memories || memories.length === 0) return [];
|
|
59
|
+
// Use Map to deduplicate by memory ID
|
|
60
|
+
const uniqueMemories = new Map(memories.map(m => [m.id, m]));
|
|
61
|
+
return Array.from(uniqueMemories.values()).map((memory) => ({
|
|
62
|
+
memory,
|
|
63
|
+
position: calculateMemoryPosition(memory),
|
|
64
|
+
}));
|
|
65
|
+
}, [memories]);
|
|
66
|
+
|
|
67
|
+
// Create a map for quick position lookup by memory ID
|
|
68
|
+
const positionMap = useMemo(() => {
|
|
69
|
+
const map = new Map<number, { x: number; y: number; z: number }>();
|
|
70
|
+
memoryPositions.forEach(({ memory, position }) => {
|
|
71
|
+
map.set(memory.id, position);
|
|
72
|
+
});
|
|
73
|
+
return map;
|
|
74
|
+
}, [memoryPositions]);
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<>
|
|
78
|
+
{/* Simple, even lighting for maximum clarity */}
|
|
79
|
+
<ambientLight intensity={0.6} color="#ffffff" />
|
|
80
|
+
<directionalLight position={[5, 5, 5]} intensity={0.3} color="#ffffff" />
|
|
81
|
+
|
|
82
|
+
{/* Ghost brain outline - barely visible context */}
|
|
83
|
+
<BrainMesh opacity={0.05} showWireframe={true} pulseIntensity={0} />
|
|
84
|
+
|
|
85
|
+
{/* Neural connections - the main visual feature */}
|
|
86
|
+
<MemoryLinks
|
|
87
|
+
memories={memories}
|
|
88
|
+
links={links}
|
|
89
|
+
memoryPositions={positionMap}
|
|
90
|
+
/>
|
|
91
|
+
|
|
92
|
+
{/* Memory nodes - clear, colored spheres */}
|
|
93
|
+
{memoryPositions.map(({ memory, position }) => (
|
|
94
|
+
<MemoryNode
|
|
95
|
+
key={memory.id}
|
|
96
|
+
memory={memory}
|
|
97
|
+
position={[position.x, position.y, position.z]}
|
|
98
|
+
onSelect={onSelectMemory}
|
|
99
|
+
isSelected={selectedMemory?.id === memory.id}
|
|
100
|
+
colorMode={colorMode}
|
|
101
|
+
/>
|
|
102
|
+
))}
|
|
103
|
+
|
|
104
|
+
{/* Activity pulses for real-time events */}
|
|
105
|
+
<ActivityPulseSystem pulses={pulses} onPulseComplete={onPulseComplete} />
|
|
106
|
+
|
|
107
|
+
{/* Camera controls - user controlled, no auto-rotate */}
|
|
108
|
+
<OrbitControls
|
|
109
|
+
enablePan={true}
|
|
110
|
+
enableZoom={true}
|
|
111
|
+
enableRotate={true}
|
|
112
|
+
minDistance={5}
|
|
113
|
+
maxDistance={25}
|
|
114
|
+
autoRotate={false}
|
|
115
|
+
dampingFactor={0.05}
|
|
116
|
+
enableDamping
|
|
117
|
+
/>
|
|
118
|
+
</>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function BrainScene({
|
|
123
|
+
memories = [],
|
|
124
|
+
links = [],
|
|
125
|
+
selectedMemory,
|
|
126
|
+
onSelectMemory,
|
|
127
|
+
}: BrainSceneProps) {
|
|
128
|
+
const [colorMode, setColorMode] = useState<ColorMode>('category');
|
|
129
|
+
const [pulses, setPulses] = useState<Pulse[]>([]);
|
|
130
|
+
const [timeRange, setTimeRange] = useState<{ start: Date | null; end: Date | null }>({
|
|
131
|
+
start: null,
|
|
132
|
+
end: null,
|
|
133
|
+
});
|
|
134
|
+
const pulseIdRef = { current: 0 };
|
|
135
|
+
|
|
136
|
+
// Calculate memory counts by category
|
|
137
|
+
const memoryCategoryCounts = useMemo(() => {
|
|
138
|
+
const counts: Record<string, number> = {};
|
|
139
|
+
memories.forEach((m) => {
|
|
140
|
+
counts[m.category] = (counts[m.category] || 0) + 1;
|
|
141
|
+
});
|
|
142
|
+
return counts;
|
|
143
|
+
}, [memories]);
|
|
144
|
+
|
|
145
|
+
// Filter memories by time range
|
|
146
|
+
const filteredMemories = useMemo(() => {
|
|
147
|
+
if (!timeRange.start && !timeRange.end) return memories;
|
|
148
|
+
|
|
149
|
+
return memories.filter((m) => {
|
|
150
|
+
const createdAt = new Date(m.createdAt).getTime();
|
|
151
|
+
if (timeRange.start && createdAt < timeRange.start.getTime()) return false;
|
|
152
|
+
if (timeRange.end && createdAt > timeRange.end.getTime()) return false;
|
|
153
|
+
return true;
|
|
154
|
+
});
|
|
155
|
+
}, [memories, timeRange]);
|
|
156
|
+
|
|
157
|
+
// Create position map for pulse positioning
|
|
158
|
+
const positionMap = useMemo(() => {
|
|
159
|
+
const map = new Map<number, { x: number; y: number; z: number }>();
|
|
160
|
+
memories.forEach((memory) => {
|
|
161
|
+
map.set(memory.id, calculateMemoryPosition(memory));
|
|
162
|
+
});
|
|
163
|
+
return map;
|
|
164
|
+
}, [memories]);
|
|
165
|
+
|
|
166
|
+
// Create a pulse for memory events
|
|
167
|
+
const createPulse = useCallback(
|
|
168
|
+
(type: Pulse['type'], memoryId: number, targetMemoryId?: number) => {
|
|
169
|
+
const position = positionMap.get(memoryId);
|
|
170
|
+
if (!position) return;
|
|
171
|
+
|
|
172
|
+
const targetPosition = targetMemoryId ? positionMap.get(targetMemoryId) : undefined;
|
|
173
|
+
|
|
174
|
+
const pulse: Pulse = {
|
|
175
|
+
id: pulseIdRef.current++,
|
|
176
|
+
type,
|
|
177
|
+
position: [position.x, position.y, position.z],
|
|
178
|
+
targetPosition: targetPosition
|
|
179
|
+
? [targetPosition.x, targetPosition.y, targetPosition.z]
|
|
180
|
+
: undefined,
|
|
181
|
+
startTime: Date.now(),
|
|
182
|
+
duration: type === 'created' ? 2000 : type === 'accessed' ? 1000 : 1500,
|
|
183
|
+
color: type === 'created' ? '#22c55e' : type === 'accessed' ? '#3b82f6' : '#a855f7',
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
setPulses((prev) => [...prev, pulse]);
|
|
187
|
+
},
|
|
188
|
+
[positionMap]
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
// Handle pulse completion
|
|
192
|
+
const handlePulseComplete = useCallback((id: number) => {
|
|
193
|
+
setPulses((prev) => prev.filter((p) => p.id !== id));
|
|
194
|
+
}, []);
|
|
195
|
+
|
|
196
|
+
// Listen for WebSocket events to trigger pulses
|
|
197
|
+
useMemoryWebSocket({
|
|
198
|
+
onMessage: (event) => {
|
|
199
|
+
const data = event.data as Record<string, unknown> | undefined;
|
|
200
|
+
switch (event.type) {
|
|
201
|
+
case 'memory_created':
|
|
202
|
+
if (data?.memoryId) createPulse('created', data.memoryId as number);
|
|
203
|
+
break;
|
|
204
|
+
case 'memory_accessed':
|
|
205
|
+
if (data?.memoryId) createPulse('accessed', data.memoryId as number);
|
|
206
|
+
break;
|
|
207
|
+
case 'link_discovered':
|
|
208
|
+
if (data?.sourceId && data?.targetId)
|
|
209
|
+
createPulse('linked', data.sourceId as number, data.targetId as number);
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
return (
|
|
216
|
+
<div className="w-full h-full bg-slate-950">
|
|
217
|
+
<Canvas
|
|
218
|
+
camera={{ position: [0, 2, 12], fov: 55 }}
|
|
219
|
+
gl={{ antialias: true, alpha: true }}
|
|
220
|
+
onClick={() => onSelectMemory(null)}
|
|
221
|
+
>
|
|
222
|
+
<Suspense fallback={null}>
|
|
223
|
+
<BrainContent
|
|
224
|
+
memories={filteredMemories}
|
|
225
|
+
links={links}
|
|
226
|
+
selectedMemory={selectedMemory}
|
|
227
|
+
onSelectMemory={onSelectMemory}
|
|
228
|
+
colorMode={colorMode}
|
|
229
|
+
pulses={pulses}
|
|
230
|
+
onPulseComplete={handlePulseComplete}
|
|
231
|
+
memoryCategoryCounts={memoryCategoryCounts}
|
|
232
|
+
/>
|
|
233
|
+
</Suspense>
|
|
234
|
+
</Canvas>
|
|
235
|
+
|
|
236
|
+
{/* Simple info overlay */}
|
|
237
|
+
<div className="absolute bottom-4 left-4 bg-slate-900/90 border border-slate-700 rounded-lg p-3 text-xs backdrop-blur-sm">
|
|
238
|
+
<p className="text-slate-300">
|
|
239
|
+
{filteredMemories.length} memories
|
|
240
|
+
</p>
|
|
241
|
+
<p className="text-slate-500 mt-1">
|
|
242
|
+
Click to select • Drag to rotate
|
|
243
|
+
</p>
|
|
244
|
+
</div>
|
|
245
|
+
|
|
246
|
+
{/* Timeline and color controls */}
|
|
247
|
+
<TimelineControls
|
|
248
|
+
memories={memories}
|
|
249
|
+
onTimeRangeChange={setTimeRange}
|
|
250
|
+
colorMode={colorMode}
|
|
251
|
+
onColorModeChange={setColorMode}
|
|
252
|
+
/>
|
|
253
|
+
</div>
|
|
254
|
+
);
|
|
255
|
+
}
|