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.
Files changed (377) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +282 -0
  3. package/dashboard/components.json +22 -0
  4. package/dashboard/eslint.config.mjs +42 -0
  5. package/dashboard/next.config.ts +7 -0
  6. package/dashboard/package-lock.json +8053 -0
  7. package/dashboard/package.json +44 -0
  8. package/dashboard/postcss.config.mjs +7 -0
  9. package/dashboard/public/file.svg +1 -0
  10. package/dashboard/public/globe.svg +1 -0
  11. package/dashboard/public/next.svg +1 -0
  12. package/dashboard/public/vercel.svg +1 -0
  13. package/dashboard/public/window.svg +1 -0
  14. package/dashboard/scripts/ensure-api.mjs +76 -0
  15. package/dashboard/src/app/error.tsx +49 -0
  16. package/dashboard/src/app/favicon.ico +0 -0
  17. package/dashboard/src/app/globals.css +130 -0
  18. package/dashboard/src/app/layout.tsx +35 -0
  19. package/dashboard/src/app/page.tsx +364 -0
  20. package/dashboard/src/components/Providers.tsx +27 -0
  21. package/dashboard/src/components/brain/ActivityPulseSystem.tsx +229 -0
  22. package/dashboard/src/components/brain/BrainMesh.tsx +133 -0
  23. package/dashboard/src/components/brain/BrainRegions.tsx +254 -0
  24. package/dashboard/src/components/brain/BrainScene.tsx +255 -0
  25. package/dashboard/src/components/brain/CategoryLabels.tsx +103 -0
  26. package/dashboard/src/components/brain/CoreSphere.tsx +215 -0
  27. package/dashboard/src/components/brain/DataFlowParticles.tsx +123 -0
  28. package/dashboard/src/components/brain/DataStreamRings.tsx +161 -0
  29. package/dashboard/src/components/brain/ElectronFlow.tsx +323 -0
  30. package/dashboard/src/components/brain/HolographicGrid.tsx +235 -0
  31. package/dashboard/src/components/brain/MemoryLinks.tsx +271 -0
  32. package/dashboard/src/components/brain/MemoryNode.tsx +245 -0
  33. package/dashboard/src/components/brain/NeuralPathways.tsx +441 -0
  34. package/dashboard/src/components/brain/SynapseNodes.tsx +312 -0
  35. package/dashboard/src/components/brain/TimelineControls.tsx +205 -0
  36. package/dashboard/src/components/chip/ChipScene.tsx +497 -0
  37. package/dashboard/src/components/chip/ChipSubstrate.tsx +238 -0
  38. package/dashboard/src/components/chip/CortexCore.tsx +210 -0
  39. package/dashboard/src/components/chip/DataBus.tsx +416 -0
  40. package/dashboard/src/components/chip/MemoryCell.tsx +225 -0
  41. package/dashboard/src/components/chip/MemoryGrid.tsx +328 -0
  42. package/dashboard/src/components/chip/QuantumCell.tsx +316 -0
  43. package/dashboard/src/components/chip/SectionLabel.tsx +113 -0
  44. package/dashboard/src/components/chip/index.ts +14 -0
  45. package/dashboard/src/components/controls/ControlPanel.tsx +106 -0
  46. package/dashboard/src/components/controls/VersionPanel.tsx +185 -0
  47. package/dashboard/src/components/dashboard/StatsPanel.tsx +164 -0
  48. package/dashboard/src/components/debug/ActivityLog.tsx +250 -0
  49. package/dashboard/src/components/debug/DebugPanel.tsx +101 -0
  50. package/dashboard/src/components/debug/QueryTester.tsx +192 -0
  51. package/dashboard/src/components/debug/RelationshipGraph.tsx +403 -0
  52. package/dashboard/src/components/debug/SqlConsole.tsx +319 -0
  53. package/dashboard/src/components/graph/KnowledgeGraph.tsx +230 -0
  54. package/dashboard/src/components/graph/OntologyGraph.tsx +631 -0
  55. package/dashboard/src/components/insights/ActivityHeatmap.tsx +131 -0
  56. package/dashboard/src/components/insights/InsightsView.tsx +46 -0
  57. package/dashboard/src/components/insights/KnowledgeMapPanel.tsx +80 -0
  58. package/dashboard/src/components/insights/QualityPanel.tsx +116 -0
  59. package/dashboard/src/components/memories/MemoriesView.tsx +150 -0
  60. package/dashboard/src/components/memories/MemoryCard.tsx +103 -0
  61. package/dashboard/src/components/memory/MemoryDetail.tsx +325 -0
  62. package/dashboard/src/components/nav/NavRail.tsx +54 -0
  63. package/dashboard/src/components/ui/button.tsx +62 -0
  64. package/dashboard/src/components/ui/card.tsx +92 -0
  65. package/dashboard/src/components/ui/input.tsx +21 -0
  66. package/dashboard/src/hooks/useDebouncedValue.ts +24 -0
  67. package/dashboard/src/hooks/useMemories.ts +458 -0
  68. package/dashboard/src/hooks/useSuggestions.ts +46 -0
  69. package/dashboard/src/lib/category-colors.ts +84 -0
  70. package/dashboard/src/lib/position-algorithm.ts +177 -0
  71. package/dashboard/src/lib/simplex-noise.ts +217 -0
  72. package/dashboard/src/lib/store.ts +88 -0
  73. package/dashboard/src/lib/utils.ts +6 -0
  74. package/dashboard/src/lib/websocket.ts +249 -0
  75. package/dashboard/src/types/memory.ts +73 -0
  76. package/dashboard/tsconfig.json +34 -0
  77. package/dist/__tests__/consolidation-merge.test.d.ts +9 -0
  78. package/dist/__tests__/consolidation-merge.test.d.ts.map +1 -0
  79. package/dist/__tests__/consolidation-merge.test.js +137 -0
  80. package/dist/__tests__/consolidation-merge.test.js.map +1 -0
  81. package/dist/__tests__/contradictions.test.d.ts +8 -0
  82. package/dist/__tests__/contradictions.test.d.ts.map +1 -0
  83. package/dist/__tests__/contradictions.test.js +78 -0
  84. package/dist/__tests__/contradictions.test.js.map +1 -0
  85. package/dist/__tests__/salience-evolution.test.d.ts +7 -0
  86. package/dist/__tests__/salience-evolution.test.d.ts.map +1 -0
  87. package/dist/__tests__/salience-evolution.test.js +151 -0
  88. package/dist/__tests__/salience-evolution.test.js.map +1 -0
  89. package/dist/__tests__/store.test.d.ts +7 -0
  90. package/dist/__tests__/store.test.d.ts.map +1 -0
  91. package/dist/__tests__/store.test.js +582 -0
  92. package/dist/__tests__/store.test.js.map +1 -0
  93. package/dist/api/control.d.ts +27 -0
  94. package/dist/api/control.d.ts.map +1 -0
  95. package/dist/api/control.js +60 -0
  96. package/dist/api/control.js.map +1 -0
  97. package/dist/api/events.d.ts +159 -0
  98. package/dist/api/events.d.ts.map +1 -0
  99. package/dist/api/events.js +155 -0
  100. package/dist/api/events.js.map +1 -0
  101. package/dist/api/version.d.ts +36 -0
  102. package/dist/api/version.d.ts.map +1 -0
  103. package/dist/api/version.js +146 -0
  104. package/dist/api/version.js.map +1 -0
  105. package/dist/api/visualization-server.d.ts +11 -0
  106. package/dist/api/visualization-server.d.ts.map +1 -0
  107. package/dist/api/visualization-server.js +1186 -0
  108. package/dist/api/visualization-server.js.map +1 -0
  109. package/dist/context/project-context.d.ts +57 -0
  110. package/dist/context/project-context.d.ts.map +1 -0
  111. package/dist/context/project-context.js +135 -0
  112. package/dist/context/project-context.js.map +1 -0
  113. package/dist/database/init.d.ts +49 -0
  114. package/dist/database/init.d.ts.map +1 -0
  115. package/dist/database/init.js +567 -0
  116. package/dist/database/init.js.map +1 -0
  117. package/dist/defence/__tests__/firewall.test.d.ts +8 -0
  118. package/dist/defence/__tests__/firewall.test.d.ts.map +1 -0
  119. package/dist/defence/__tests__/firewall.test.js +123 -0
  120. package/dist/defence/__tests__/firewall.test.js.map +1 -0
  121. package/dist/defence/__tests__/fragmentation.test.d.ts +7 -0
  122. package/dist/defence/__tests__/fragmentation.test.d.ts.map +1 -0
  123. package/dist/defence/__tests__/fragmentation.test.js +51 -0
  124. package/dist/defence/__tests__/fragmentation.test.js.map +1 -0
  125. package/dist/defence/__tests__/pipeline.test.d.ts +8 -0
  126. package/dist/defence/__tests__/pipeline.test.d.ts.map +1 -0
  127. package/dist/defence/__tests__/pipeline.test.js +61 -0
  128. package/dist/defence/__tests__/pipeline.test.js.map +1 -0
  129. package/dist/defence/__tests__/sensitivity.test.d.ts +7 -0
  130. package/dist/defence/__tests__/sensitivity.test.d.ts.map +1 -0
  131. package/dist/defence/__tests__/sensitivity.test.js +61 -0
  132. package/dist/defence/__tests__/sensitivity.test.js.map +1 -0
  133. package/dist/defence/__tests__/trust.test.d.ts +7 -0
  134. package/dist/defence/__tests__/trust.test.d.ts.map +1 -0
  135. package/dist/defence/__tests__/trust.test.js +49 -0
  136. package/dist/defence/__tests__/trust.test.js.map +1 -0
  137. package/dist/defence/audit/index.d.ts +4 -0
  138. package/dist/defence/audit/index.d.ts.map +1 -0
  139. package/dist/defence/audit/index.js +3 -0
  140. package/dist/defence/audit/index.js.map +1 -0
  141. package/dist/defence/audit/logger.d.ts +14 -0
  142. package/dist/defence/audit/logger.d.ts.map +1 -0
  143. package/dist/defence/audit/logger.js +54 -0
  144. package/dist/defence/audit/logger.js.map +1 -0
  145. package/dist/defence/audit/queries.d.ts +33 -0
  146. package/dist/defence/audit/queries.d.ts.map +1 -0
  147. package/dist/defence/audit/queries.js +103 -0
  148. package/dist/defence/audit/queries.js.map +1 -0
  149. package/dist/defence/firewall/anomaly-scorer.d.ts +8 -0
  150. package/dist/defence/firewall/anomaly-scorer.d.ts.map +1 -0
  151. package/dist/defence/firewall/anomaly-scorer.js +58 -0
  152. package/dist/defence/firewall/anomaly-scorer.js.map +1 -0
  153. package/dist/defence/firewall/encoding-detector.d.ts +13 -0
  154. package/dist/defence/firewall/encoding-detector.d.ts.map +1 -0
  155. package/dist/defence/firewall/encoding-detector.js +120 -0
  156. package/dist/defence/firewall/encoding-detector.js.map +1 -0
  157. package/dist/defence/firewall/index.d.ts +21 -0
  158. package/dist/defence/firewall/index.d.ts.map +1 -0
  159. package/dist/defence/firewall/index.js +133 -0
  160. package/dist/defence/firewall/index.js.map +1 -0
  161. package/dist/defence/firewall/instruction-detector.d.ts +12 -0
  162. package/dist/defence/firewall/instruction-detector.d.ts.map +1 -0
  163. package/dist/defence/firewall/instruction-detector.js +99 -0
  164. package/dist/defence/firewall/instruction-detector.js.map +1 -0
  165. package/dist/defence/firewall/privilege-detector.d.ts +13 -0
  166. package/dist/defence/firewall/privilege-detector.d.ts.map +1 -0
  167. package/dist/defence/firewall/privilege-detector.js +89 -0
  168. package/dist/defence/firewall/privilege-detector.js.map +1 -0
  169. package/dist/defence/fragmentation/assembly-detector.d.ts +18 -0
  170. package/dist/defence/fragmentation/assembly-detector.d.ts.map +1 -0
  171. package/dist/defence/fragmentation/assembly-detector.js +72 -0
  172. package/dist/defence/fragmentation/assembly-detector.js.map +1 -0
  173. package/dist/defence/fragmentation/entity-extractor.d.ts +19 -0
  174. package/dist/defence/fragmentation/entity-extractor.d.ts.map +1 -0
  175. package/dist/defence/fragmentation/entity-extractor.js +86 -0
  176. package/dist/defence/fragmentation/entity-extractor.js.map +1 -0
  177. package/dist/defence/fragmentation/index.d.ts +23 -0
  178. package/dist/defence/fragmentation/index.d.ts.map +1 -0
  179. package/dist/defence/fragmentation/index.js +49 -0
  180. package/dist/defence/fragmentation/index.js.map +1 -0
  181. package/dist/defence/fragmentation/temporal-analyzer.d.ts +28 -0
  182. package/dist/defence/fragmentation/temporal-analyzer.d.ts.map +1 -0
  183. package/dist/defence/fragmentation/temporal-analyzer.js +41 -0
  184. package/dist/defence/fragmentation/temporal-analyzer.js.map +1 -0
  185. package/dist/defence/index.d.ts +12 -0
  186. package/dist/defence/index.d.ts.map +1 -0
  187. package/dist/defence/index.js +18 -0
  188. package/dist/defence/index.js.map +1 -0
  189. package/dist/defence/pipeline.d.ts +9 -0
  190. package/dist/defence/pipeline.d.ts.map +1 -0
  191. package/dist/defence/pipeline.js +115 -0
  192. package/dist/defence/pipeline.js.map +1 -0
  193. package/dist/defence/scanner/index.d.ts +5 -0
  194. package/dist/defence/scanner/index.d.ts.map +1 -0
  195. package/dist/defence/scanner/index.js +5 -0
  196. package/dist/defence/scanner/index.js.map +1 -0
  197. package/dist/defence/scanner/scan-existing.d.ts +34 -0
  198. package/dist/defence/scanner/scan-existing.d.ts.map +1 -0
  199. package/dist/defence/scanner/scan-existing.js +136 -0
  200. package/dist/defence/scanner/scan-existing.js.map +1 -0
  201. package/dist/defence/sensitivity/classifier.d.ts +6 -0
  202. package/dist/defence/sensitivity/classifier.d.ts.map +1 -0
  203. package/dist/defence/sensitivity/classifier.js +50 -0
  204. package/dist/defence/sensitivity/classifier.js.map +1 -0
  205. package/dist/defence/sensitivity/index.d.ts +11 -0
  206. package/dist/defence/sensitivity/index.d.ts.map +1 -0
  207. package/dist/defence/sensitivity/index.js +13 -0
  208. package/dist/defence/sensitivity/index.js.map +1 -0
  209. package/dist/defence/sensitivity/patterns.d.ts +14 -0
  210. package/dist/defence/sensitivity/patterns.d.ts.map +1 -0
  211. package/dist/defence/sensitivity/patterns.js +67 -0
  212. package/dist/defence/sensitivity/patterns.js.map +1 -0
  213. package/dist/defence/sensitivity/redaction.d.ts +17 -0
  214. package/dist/defence/sensitivity/redaction.d.ts.map +1 -0
  215. package/dist/defence/sensitivity/redaction.js +47 -0
  216. package/dist/defence/sensitivity/redaction.js.map +1 -0
  217. package/dist/defence/trust/index.d.ts +3 -0
  218. package/dist/defence/trust/index.d.ts.map +1 -0
  219. package/dist/defence/trust/index.js +3 -0
  220. package/dist/defence/trust/index.js.map +1 -0
  221. package/dist/defence/trust/recall-filter.d.ts +10 -0
  222. package/dist/defence/trust/recall-filter.d.ts.map +1 -0
  223. package/dist/defence/trust/recall-filter.js +38 -0
  224. package/dist/defence/trust/recall-filter.js.map +1 -0
  225. package/dist/defence/trust/source-scorer.d.ts +6 -0
  226. package/dist/defence/trust/source-scorer.d.ts.map +1 -0
  227. package/dist/defence/trust/source-scorer.js +34 -0
  228. package/dist/defence/trust/source-scorer.js.map +1 -0
  229. package/dist/defence/types.d.ts +88 -0
  230. package/dist/defence/types.d.ts.map +1 -0
  231. package/dist/defence/types.js +15 -0
  232. package/dist/defence/types.js.map +1 -0
  233. package/dist/embeddings/generator.d.ts +20 -0
  234. package/dist/embeddings/generator.d.ts.map +1 -0
  235. package/dist/embeddings/generator.js +83 -0
  236. package/dist/embeddings/generator.js.map +1 -0
  237. package/dist/embeddings/index.d.ts +2 -0
  238. package/dist/embeddings/index.d.ts.map +1 -0
  239. package/dist/embeddings/index.js +2 -0
  240. package/dist/embeddings/index.js.map +1 -0
  241. package/dist/errors.d.ts +74 -0
  242. package/dist/errors.d.ts.map +1 -0
  243. package/dist/errors.js +131 -0
  244. package/dist/errors.js.map +1 -0
  245. package/dist/graph/backfill.d.ts +6 -0
  246. package/dist/graph/backfill.d.ts.map +1 -0
  247. package/dist/graph/backfill.js +33 -0
  248. package/dist/graph/backfill.js.map +1 -0
  249. package/dist/graph/extract.d.ts +21 -0
  250. package/dist/graph/extract.d.ts.map +1 -0
  251. package/dist/graph/extract.js +231 -0
  252. package/dist/graph/extract.js.map +1 -0
  253. package/dist/graph/resolve.d.ts +6 -0
  254. package/dist/graph/resolve.d.ts.map +1 -0
  255. package/dist/graph/resolve.js +126 -0
  256. package/dist/graph/resolve.js.map +1 -0
  257. package/dist/index.d.ts +31 -0
  258. package/dist/index.d.ts.map +1 -0
  259. package/dist/index.js +248 -0
  260. package/dist/index.js.map +1 -0
  261. package/dist/memory/activation.d.ts +69 -0
  262. package/dist/memory/activation.d.ts.map +1 -0
  263. package/dist/memory/activation.js +168 -0
  264. package/dist/memory/activation.js.map +1 -0
  265. package/dist/memory/consolidate.d.ts +98 -0
  266. package/dist/memory/consolidate.d.ts.map +1 -0
  267. package/dist/memory/consolidate.js +511 -0
  268. package/dist/memory/consolidate.js.map +1 -0
  269. package/dist/memory/contradiction.d.ts +69 -0
  270. package/dist/memory/contradiction.d.ts.map +1 -0
  271. package/dist/memory/contradiction.js +286 -0
  272. package/dist/memory/contradiction.js.map +1 -0
  273. package/dist/memory/decay.d.ts +62 -0
  274. package/dist/memory/decay.d.ts.map +1 -0
  275. package/dist/memory/decay.js +184 -0
  276. package/dist/memory/decay.js.map +1 -0
  277. package/dist/memory/salience.d.ts +36 -0
  278. package/dist/memory/salience.d.ts.map +1 -0
  279. package/dist/memory/salience.js +216 -0
  280. package/dist/memory/salience.js.map +1 -0
  281. package/dist/memory/similarity.d.ts +57 -0
  282. package/dist/memory/similarity.d.ts.map +1 -0
  283. package/dist/memory/similarity.js +114 -0
  284. package/dist/memory/similarity.js.map +1 -0
  285. package/dist/memory/store.d.ts +179 -0
  286. package/dist/memory/store.d.ts.map +1 -0
  287. package/dist/memory/store.js +1184 -0
  288. package/dist/memory/store.js.map +1 -0
  289. package/dist/memory/types.d.ts +97 -0
  290. package/dist/memory/types.d.ts.map +1 -0
  291. package/dist/memory/types.js +30 -0
  292. package/dist/memory/types.js.map +1 -0
  293. package/dist/server.d.ts +12 -0
  294. package/dist/server.d.ts.map +1 -0
  295. package/dist/server.js +568 -0
  296. package/dist/server.js.map +1 -0
  297. package/dist/service/install.d.ts +15 -0
  298. package/dist/service/install.d.ts.map +1 -0
  299. package/dist/service/install.js +178 -0
  300. package/dist/service/install.js.map +1 -0
  301. package/dist/service/templates.d.ts +13 -0
  302. package/dist/service/templates.d.ts.map +1 -0
  303. package/dist/service/templates.js +58 -0
  304. package/dist/service/templates.js.map +1 -0
  305. package/dist/setup/claude-md.d.ts +12 -0
  306. package/dist/setup/claude-md.d.ts.map +1 -0
  307. package/dist/setup/claude-md.js +68 -0
  308. package/dist/setup/claude-md.js.map +1 -0
  309. package/dist/setup/clawdbot.d.ts +15 -0
  310. package/dist/setup/clawdbot.d.ts.map +1 -0
  311. package/dist/setup/clawdbot.js +118 -0
  312. package/dist/setup/clawdbot.js.map +1 -0
  313. package/dist/setup/doctor.d.ts +5 -0
  314. package/dist/setup/doctor.d.ts.map +1 -0
  315. package/dist/setup/doctor.js +141 -0
  316. package/dist/setup/doctor.js.map +1 -0
  317. package/dist/setup/hooks.d.ts +6 -0
  318. package/dist/setup/hooks.d.ts.map +1 -0
  319. package/dist/setup/hooks.js +36 -0
  320. package/dist/setup/hooks.js.map +1 -0
  321. package/dist/setup/migrate.d.ts +16 -0
  322. package/dist/setup/migrate.d.ts.map +1 -0
  323. package/dist/setup/migrate.js +164 -0
  324. package/dist/setup/migrate.js.map +1 -0
  325. package/dist/setup/settings-hooks.d.ts +7 -0
  326. package/dist/setup/settings-hooks.d.ts.map +1 -0
  327. package/dist/setup/settings-hooks.js +83 -0
  328. package/dist/setup/settings-hooks.js.map +1 -0
  329. package/dist/setup/uninstall.d.ts +12 -0
  330. package/dist/setup/uninstall.d.ts.map +1 -0
  331. package/dist/setup/uninstall.js +125 -0
  332. package/dist/setup/uninstall.js.map +1 -0
  333. package/dist/tools/context.d.ts +135 -0
  334. package/dist/tools/context.d.ts.map +1 -0
  335. package/dist/tools/context.js +273 -0
  336. package/dist/tools/context.js.map +1 -0
  337. package/dist/tools/forget.d.ts +53 -0
  338. package/dist/tools/forget.d.ts.map +1 -0
  339. package/dist/tools/forget.js +179 -0
  340. package/dist/tools/forget.js.map +1 -0
  341. package/dist/tools/graph.d.ts +46 -0
  342. package/dist/tools/graph.d.ts.map +1 -0
  343. package/dist/tools/graph.js +206 -0
  344. package/dist/tools/graph.js.map +1 -0
  345. package/dist/tools/recall.d.ts +79 -0
  346. package/dist/tools/recall.d.ts.map +1 -0
  347. package/dist/tools/recall.js +156 -0
  348. package/dist/tools/recall.js.map +1 -0
  349. package/dist/tools/remember.d.ts +83 -0
  350. package/dist/tools/remember.d.ts.map +1 -0
  351. package/dist/tools/remember.js +151 -0
  352. package/dist/tools/remember.js.map +1 -0
  353. package/dist/worker/brain-worker.d.ts +100 -0
  354. package/dist/worker/brain-worker.d.ts.map +1 -0
  355. package/dist/worker/brain-worker.js +283 -0
  356. package/dist/worker/brain-worker.js.map +1 -0
  357. package/dist/worker/link-discovery.d.ts +47 -0
  358. package/dist/worker/link-discovery.d.ts.map +1 -0
  359. package/dist/worker/link-discovery.js +103 -0
  360. package/dist/worker/link-discovery.js.map +1 -0
  361. package/dist/worker/predictive-consolidation.d.ts +46 -0
  362. package/dist/worker/predictive-consolidation.d.ts.map +1 -0
  363. package/dist/worker/predictive-consolidation.js +110 -0
  364. package/dist/worker/predictive-consolidation.js.map +1 -0
  365. package/dist/worker/types.d.ts +91 -0
  366. package/dist/worker/types.d.ts.map +1 -0
  367. package/dist/worker/types.js +22 -0
  368. package/dist/worker/types.js.map +1 -0
  369. package/hooks/clawdbot/cortex-memory/HOOK.md +71 -0
  370. package/hooks/clawdbot/cortex-memory/handler.js +279 -0
  371. package/package.json +73 -0
  372. package/scripts/pre-compact-hook.mjs +716 -0
  373. package/scripts/session-end-hook.mjs +548 -0
  374. package/scripts/session-start-hook.mjs +221 -0
  375. package/scripts/start-dashboard.sh +41 -0
  376. package/scripts/stop-dashboard.sh +21 -0
  377. 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
+ }