@pcircle/memesh 2.10.1 → 3.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 (818) hide show
  1. package/.mcp.json +2 -5
  2. package/README.md +122 -221
  3. package/dist/cli/assets/d3.v7.min.js +2 -0
  4. package/dist/cli/view.d.ts +4 -0
  5. package/dist/cli/view.d.ts.map +1 -0
  6. package/dist/cli/view.js +2672 -0
  7. package/dist/cli/view.js.map +1 -0
  8. package/dist/core/config.d.ts +33 -0
  9. package/dist/core/config.d.ts.map +1 -0
  10. package/dist/core/config.js +70 -0
  11. package/dist/core/config.js.map +1 -0
  12. package/dist/core/extractor.d.ts +26 -0
  13. package/dist/core/extractor.d.ts.map +1 -0
  14. package/dist/core/extractor.js +106 -0
  15. package/dist/core/extractor.js.map +1 -0
  16. package/dist/core/lifecycle.d.ts +9 -0
  17. package/dist/core/lifecycle.d.ts.map +1 -0
  18. package/dist/core/lifecycle.js +51 -0
  19. package/dist/core/lifecycle.js.map +1 -0
  20. package/dist/core/operations.d.ts +9 -0
  21. package/dist/core/operations.d.ts.map +1 -0
  22. package/dist/core/operations.js +342 -0
  23. package/dist/core/operations.js.map +1 -0
  24. package/dist/core/query-expander.d.ts +4 -0
  25. package/dist/core/query-expander.d.ts.map +1 -0
  26. package/dist/core/query-expander.js +114 -0
  27. package/dist/core/query-expander.js.map +1 -0
  28. package/dist/core/schema-export.d.ts +2 -0
  29. package/dist/core/schema-export.d.ts.map +1 -0
  30. package/dist/core/schema-export.js +67 -0
  31. package/dist/core/schema-export.js.map +1 -0
  32. package/dist/core/scoring.d.ts +25 -0
  33. package/dist/core/scoring.d.ts.map +1 -0
  34. package/dist/core/scoring.js +40 -0
  35. package/dist/core/scoring.js.map +1 -0
  36. package/dist/core/types.d.ts +116 -58
  37. package/dist/core/types.d.ts.map +1 -1
  38. package/dist/core/types.js +1 -10
  39. package/dist/core/types.js.map +1 -1
  40. package/dist/core/version-check.d.ts +10 -0
  41. package/dist/core/version-check.d.ts.map +1 -0
  42. package/dist/core/version-check.js +44 -0
  43. package/dist/core/version-check.js.map +1 -0
  44. package/dist/db.d.ts +5 -0
  45. package/dist/db.d.ts.map +1 -0
  46. package/dist/db.js +113 -0
  47. package/dist/db.js.map +1 -0
  48. package/dist/index.d.ts +3 -6
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +2 -33
  51. package/dist/index.js.map +1 -1
  52. package/dist/knowledge-graph.d.ts +34 -0
  53. package/dist/knowledge-graph.d.ts.map +1 -0
  54. package/dist/knowledge-graph.js +367 -0
  55. package/dist/knowledge-graph.js.map +1 -0
  56. package/dist/mcp/server.d.ts +1 -25
  57. package/dist/mcp/server.d.ts.map +1 -1
  58. package/dist/mcp/server.js +39 -318
  59. package/dist/mcp/server.js.map +1 -1
  60. package/dist/mcp/tools.d.ts +2 -0
  61. package/dist/mcp/tools.d.ts.map +1 -0
  62. package/dist/mcp/tools.js +2 -0
  63. package/dist/mcp/tools.js.map +1 -0
  64. package/dist/transports/cli/cli.d.ts +3 -0
  65. package/dist/transports/cli/cli.d.ts.map +1 -0
  66. package/dist/transports/cli/cli.js +378 -0
  67. package/dist/transports/cli/cli.js.map +1 -0
  68. package/dist/transports/http/server.d.ts +5 -0
  69. package/dist/transports/http/server.d.ts.map +1 -0
  70. package/dist/transports/http/server.js +314 -0
  71. package/dist/transports/http/server.js.map +1 -0
  72. package/dist/transports/mcp/handlers.d.ts +184 -0
  73. package/dist/transports/mcp/handlers.d.ts.map +1 -0
  74. package/dist/transports/mcp/handlers.js +271 -0
  75. package/dist/transports/mcp/handlers.js.map +1 -0
  76. package/hooks/hooks.json +8 -24
  77. package/package.json +26 -90
  78. package/plugin.json +7 -10
  79. package/scripts/hooks/post-commit.js +160 -298
  80. package/scripts/hooks/pre-compact.js +198 -0
  81. package/scripts/hooks/session-start.js +130 -627
  82. package/scripts/hooks/session-summary.js +255 -0
  83. package/README.de.md +0 -212
  84. package/README.es.md +0 -212
  85. package/README.fr.md +0 -212
  86. package/README.id.md +0 -212
  87. package/README.ja.md +0 -212
  88. package/README.ko.md +0 -212
  89. package/README.th.md +0 -212
  90. package/README.vi.md +0 -212
  91. package/README.zh-CN.md +0 -212
  92. package/README.zh-TW.md +0 -286
  93. package/dist/cli/config.d.ts +0 -36
  94. package/dist/cli/config.d.ts.map +0 -1
  95. package/dist/cli/config.js +0 -398
  96. package/dist/cli/config.js.map +0 -1
  97. package/dist/cli/credentials.d.ts +0 -12
  98. package/dist/cli/credentials.d.ts.map +0 -1
  99. package/dist/cli/credentials.js +0 -44
  100. package/dist/cli/credentials.js.map +0 -1
  101. package/dist/cli/daemon.d.ts +0 -3
  102. package/dist/cli/daemon.d.ts.map +0 -1
  103. package/dist/cli/daemon.js +0 -413
  104. package/dist/cli/daemon.js.map +0 -1
  105. package/dist/cli/dashboard.d.ts +0 -2
  106. package/dist/cli/dashboard.d.ts.map +0 -1
  107. package/dist/cli/dashboard.js +0 -300
  108. package/dist/cli/dashboard.js.map +0 -1
  109. package/dist/cli/index.d.ts +0 -3
  110. package/dist/cli/index.d.ts.map +0 -1
  111. package/dist/cli/index.js +0 -188
  112. package/dist/cli/index.js.map +0 -1
  113. package/dist/cli/login.d.ts +0 -4
  114. package/dist/cli/login.d.ts.map +0 -1
  115. package/dist/cli/login.js +0 -230
  116. package/dist/cli/login.js.map +0 -1
  117. package/dist/cli/logout.d.ts +0 -3
  118. package/dist/cli/logout.d.ts.map +0 -1
  119. package/dist/cli/logout.js +0 -23
  120. package/dist/cli/logout.js.map +0 -1
  121. package/dist/cli/setup-wizard.d.ts +0 -18
  122. package/dist/cli/setup-wizard.d.ts.map +0 -1
  123. package/dist/cli/setup-wizard.js +0 -267
  124. package/dist/cli/setup-wizard.js.map +0 -1
  125. package/dist/cli/stats.d.ts +0 -34
  126. package/dist/cli/stats.d.ts.map +0 -1
  127. package/dist/cli/stats.js +0 -479
  128. package/dist/cli/stats.js.map +0 -1
  129. package/dist/cli/tutorial.d.ts +0 -27
  130. package/dist/cli/tutorial.d.ts.map +0 -1
  131. package/dist/cli/tutorial.js +0 -430
  132. package/dist/cli/tutorial.js.map +0 -1
  133. package/dist/cloud/MeMeshCloudClient.d.ts +0 -88
  134. package/dist/cloud/MeMeshCloudClient.d.ts.map +0 -1
  135. package/dist/cloud/MeMeshCloudClient.js +0 -177
  136. package/dist/cloud/MeMeshCloudClient.js.map +0 -1
  137. package/dist/cloud/index.d.ts +0 -3
  138. package/dist/cloud/index.d.ts.map +0 -1
  139. package/dist/cloud/index.js +0 -2
  140. package/dist/cloud/index.js.map +0 -1
  141. package/dist/config/index.d.ts +0 -61
  142. package/dist/config/index.d.ts.map +0 -1
  143. package/dist/config/index.js +0 -105
  144. package/dist/config/index.js.map +0 -1
  145. package/dist/config/models.d.ts +0 -47
  146. package/dist/config/models.d.ts.map +0 -1
  147. package/dist/config/models.js +0 -57
  148. package/dist/config/models.js.map +0 -1
  149. package/dist/config/simple-config.d.ts +0 -35
  150. package/dist/config/simple-config.d.ts.map +0 -1
  151. package/dist/config/simple-config.js +0 -246
  152. package/dist/config/simple-config.js.map +0 -1
  153. package/dist/core/AgentRegistry.d.ts +0 -31
  154. package/dist/core/AgentRegistry.d.ts.map +0 -1
  155. package/dist/core/AgentRegistry.js +0 -281
  156. package/dist/core/AgentRegistry.js.map +0 -1
  157. package/dist/core/CheckpointDetector.d.ts +0 -25
  158. package/dist/core/CheckpointDetector.d.ts.map +0 -1
  159. package/dist/core/CheckpointDetector.js +0 -67
  160. package/dist/core/CheckpointDetector.js.map +0 -1
  161. package/dist/core/GitCommandParser.d.ts +0 -11
  162. package/dist/core/GitCommandParser.d.ts.map +0 -1
  163. package/dist/core/GitCommandParser.js +0 -43
  164. package/dist/core/GitCommandParser.js.map +0 -1
  165. package/dist/core/HealthCheck.d.ts +0 -39
  166. package/dist/core/HealthCheck.d.ts.map +0 -1
  167. package/dist/core/HealthCheck.js +0 -219
  168. package/dist/core/HealthCheck.js.map +0 -1
  169. package/dist/core/HookIntegration.d.ts +0 -47
  170. package/dist/core/HookIntegration.d.ts.map +0 -1
  171. package/dist/core/HookIntegration.js +0 -275
  172. package/dist/core/HookIntegration.js.map +0 -1
  173. package/dist/core/MCPToolInterface.d.ts +0 -120
  174. package/dist/core/MCPToolInterface.d.ts.map +0 -1
  175. package/dist/core/MCPToolInterface.js +0 -376
  176. package/dist/core/MCPToolInterface.js.map +0 -1
  177. package/dist/core/MistakePatternManager.d.ts +0 -31
  178. package/dist/core/MistakePatternManager.d.ts.map +0 -1
  179. package/dist/core/MistakePatternManager.js +0 -137
  180. package/dist/core/MistakePatternManager.js.map +0 -1
  181. package/dist/core/ResourceMonitor.d.ts +0 -32
  182. package/dist/core/ResourceMonitor.d.ts.map +0 -1
  183. package/dist/core/ResourceMonitor.js +0 -243
  184. package/dist/core/ResourceMonitor.js.map +0 -1
  185. package/dist/core/ServiceLocator.d.ts +0 -10
  186. package/dist/core/ServiceLocator.d.ts.map +0 -1
  187. package/dist/core/ServiceLocator.js +0 -30
  188. package/dist/core/ServiceLocator.js.map +0 -1
  189. package/dist/core/TestOutputParser.d.ts +0 -20
  190. package/dist/core/TestOutputParser.d.ts.map +0 -1
  191. package/dist/core/TestOutputParser.js +0 -144
  192. package/dist/core/TestOutputParser.js.map +0 -1
  193. package/dist/db/ConnectionPool.d.ts +0 -50
  194. package/dist/db/ConnectionPool.d.ts.map +0 -1
  195. package/dist/db/ConnectionPool.js +0 -569
  196. package/dist/db/ConnectionPool.js.map +0 -1
  197. package/dist/db/IDatabaseAdapter.d.ts +0 -25
  198. package/dist/db/IDatabaseAdapter.d.ts.map +0 -1
  199. package/dist/db/IDatabaseAdapter.js +0 -2
  200. package/dist/db/IDatabaseAdapter.js.map +0 -1
  201. package/dist/db/QueryCache.d.ts +0 -46
  202. package/dist/db/QueryCache.d.ts.map +0 -1
  203. package/dist/db/QueryCache.js +0 -232
  204. package/dist/db/QueryCache.js.map +0 -1
  205. package/dist/db/adapters/BetterSqlite3Adapter.d.ts +0 -15
  206. package/dist/db/adapters/BetterSqlite3Adapter.d.ts.map +0 -1
  207. package/dist/db/adapters/BetterSqlite3Adapter.js +0 -127
  208. package/dist/db/adapters/BetterSqlite3Adapter.js.map +0 -1
  209. package/dist/embeddings/EmbeddingService.d.ts +0 -23
  210. package/dist/embeddings/EmbeddingService.d.ts.map +0 -1
  211. package/dist/embeddings/EmbeddingService.js +0 -131
  212. package/dist/embeddings/EmbeddingService.js.map +0 -1
  213. package/dist/embeddings/InMemoryVectorAdapter.d.ts +0 -15
  214. package/dist/embeddings/InMemoryVectorAdapter.d.ts.map +0 -1
  215. package/dist/embeddings/InMemoryVectorAdapter.js +0 -58
  216. package/dist/embeddings/InMemoryVectorAdapter.js.map +0 -1
  217. package/dist/embeddings/ModelManager.d.ts +0 -18
  218. package/dist/embeddings/ModelManager.d.ts.map +0 -1
  219. package/dist/embeddings/ModelManager.js +0 -84
  220. package/dist/embeddings/ModelManager.js.map +0 -1
  221. package/dist/embeddings/SqliteVecAdapter.d.ts +0 -15
  222. package/dist/embeddings/SqliteVecAdapter.d.ts.map +0 -1
  223. package/dist/embeddings/SqliteVecAdapter.js +0 -107
  224. package/dist/embeddings/SqliteVecAdapter.js.map +0 -1
  225. package/dist/embeddings/VectorExtension.d.ts +0 -17
  226. package/dist/embeddings/VectorExtension.d.ts.map +0 -1
  227. package/dist/embeddings/VectorExtension.js +0 -107
  228. package/dist/embeddings/VectorExtension.js.map +0 -1
  229. package/dist/embeddings/VectorSearchAdapter.d.ts +0 -17
  230. package/dist/embeddings/VectorSearchAdapter.d.ts.map +0 -1
  231. package/dist/embeddings/VectorSearchAdapter.js +0 -2
  232. package/dist/embeddings/VectorSearchAdapter.js.map +0 -1
  233. package/dist/embeddings/index.d.ts +0 -9
  234. package/dist/embeddings/index.d.ts.map +0 -1
  235. package/dist/embeddings/index.js +0 -7
  236. package/dist/embeddings/index.js.map +0 -1
  237. package/dist/errors/ErrorClassifier.d.ts +0 -60
  238. package/dist/errors/ErrorClassifier.d.ts.map +0 -1
  239. package/dist/errors/ErrorClassifier.js +0 -415
  240. package/dist/errors/ErrorClassifier.js.map +0 -1
  241. package/dist/errors/index.d.ts +0 -63
  242. package/dist/errors/index.d.ts.map +0 -1
  243. package/dist/errors/index.js +0 -127
  244. package/dist/errors/index.js.map +0 -1
  245. package/dist/i18n/index.d.ts +0 -9
  246. package/dist/i18n/index.d.ts.map +0 -1
  247. package/dist/i18n/index.js +0 -78
  248. package/dist/i18n/index.js.map +0 -1
  249. package/dist/i18n/locales/en.d.ts +0 -3
  250. package/dist/i18n/locales/en.d.ts.map +0 -1
  251. package/dist/i18n/locales/en.js +0 -32
  252. package/dist/i18n/locales/en.js.map +0 -1
  253. package/dist/i18n/locales/index.d.ts +0 -5
  254. package/dist/i18n/locales/index.d.ts.map +0 -1
  255. package/dist/i18n/locales/index.js +0 -5
  256. package/dist/i18n/locales/index.js.map +0 -1
  257. package/dist/i18n/locales/ja.d.ts +0 -3
  258. package/dist/i18n/locales/ja.d.ts.map +0 -1
  259. package/dist/i18n/locales/ja.js +0 -30
  260. package/dist/i18n/locales/ja.js.map +0 -1
  261. package/dist/i18n/locales/zh-CN.d.ts +0 -3
  262. package/dist/i18n/locales/zh-CN.d.ts.map +0 -1
  263. package/dist/i18n/locales/zh-CN.js +0 -30
  264. package/dist/i18n/locales/zh-CN.js.map +0 -1
  265. package/dist/i18n/locales/zh-TW.d.ts +0 -3
  266. package/dist/i18n/locales/zh-TW.d.ts.map +0 -1
  267. package/dist/i18n/locales/zh-TW.js +0 -30
  268. package/dist/i18n/locales/zh-TW.js.map +0 -1
  269. package/dist/i18n/types.d.ts +0 -11
  270. package/dist/i18n/types.d.ts.map +0 -1
  271. package/dist/i18n/types.js +0 -3
  272. package/dist/i18n/types.js.map +0 -1
  273. package/dist/integrations/session-memory/SessionContextInjector.d.ts +0 -30
  274. package/dist/integrations/session-memory/SessionContextInjector.d.ts.map +0 -1
  275. package/dist/integrations/session-memory/SessionContextInjector.js +0 -192
  276. package/dist/integrations/session-memory/SessionContextInjector.js.map +0 -1
  277. package/dist/integrations/session-memory/SessionMemoryIngester.d.ts +0 -15
  278. package/dist/integrations/session-memory/SessionMemoryIngester.d.ts.map +0 -1
  279. package/dist/integrations/session-memory/SessionMemoryIngester.js +0 -229
  280. package/dist/integrations/session-memory/SessionMemoryIngester.js.map +0 -1
  281. package/dist/integrations/session-memory/SessionMemoryParser.d.ts +0 -16
  282. package/dist/integrations/session-memory/SessionMemoryParser.d.ts.map +0 -1
  283. package/dist/integrations/session-memory/SessionMemoryParser.js +0 -271
  284. package/dist/integrations/session-memory/SessionMemoryParser.js.map +0 -1
  285. package/dist/integrations/session-memory/SessionMemoryPipeline.d.ts +0 -20
  286. package/dist/integrations/session-memory/SessionMemoryPipeline.d.ts.map +0 -1
  287. package/dist/integrations/session-memory/SessionMemoryPipeline.js +0 -60
  288. package/dist/integrations/session-memory/SessionMemoryPipeline.js.map +0 -1
  289. package/dist/integrations/session-memory/SessionMemoryWatcher.d.ts +0 -27
  290. package/dist/integrations/session-memory/SessionMemoryWatcher.d.ts.map +0 -1
  291. package/dist/integrations/session-memory/SessionMemoryWatcher.js +0 -145
  292. package/dist/integrations/session-memory/SessionMemoryWatcher.js.map +0 -1
  293. package/dist/integrations/session-memory/index.d.ts +0 -9
  294. package/dist/integrations/session-memory/index.d.ts.map +0 -1
  295. package/dist/integrations/session-memory/index.js +0 -6
  296. package/dist/integrations/session-memory/index.js.map +0 -1
  297. package/dist/integrations/session-memory/types.d.ts +0 -74
  298. package/dist/integrations/session-memory/types.d.ts.map +0 -1
  299. package/dist/integrations/session-memory/types.js +0 -22
  300. package/dist/integrations/session-memory/types.js.map +0 -1
  301. package/dist/knowledge-graph/ContentHasher.d.ts +0 -4
  302. package/dist/knowledge-graph/ContentHasher.d.ts.map +0 -1
  303. package/dist/knowledge-graph/ContentHasher.js +0 -8
  304. package/dist/knowledge-graph/ContentHasher.js.map +0 -1
  305. package/dist/knowledge-graph/KGSearchEngine.d.ts +0 -37
  306. package/dist/knowledge-graph/KGSearchEngine.d.ts.map +0 -1
  307. package/dist/knowledge-graph/KGSearchEngine.js +0 -257
  308. package/dist/knowledge-graph/KGSearchEngine.js.map +0 -1
  309. package/dist/knowledge-graph/index.d.ts +0 -64
  310. package/dist/knowledge-graph/index.d.ts.map +0 -1
  311. package/dist/knowledge-graph/index.js +0 -681
  312. package/dist/knowledge-graph/index.js.map +0 -1
  313. package/dist/knowledge-graph/types.d.ts +0 -38
  314. package/dist/knowledge-graph/types.d.ts.map +0 -1
  315. package/dist/knowledge-graph/types.js +0 -2
  316. package/dist/knowledge-graph/types.js.map +0 -1
  317. package/dist/management/UninstallManager.d.ts +0 -23
  318. package/dist/management/UninstallManager.d.ts.map +0 -1
  319. package/dist/management/UninstallManager.js +0 -186
  320. package/dist/management/UninstallManager.js.map +0 -1
  321. package/dist/management/index.d.ts +0 -3
  322. package/dist/management/index.d.ts.map +0 -1
  323. package/dist/management/index.js +0 -2
  324. package/dist/management/index.js.map +0 -1
  325. package/dist/mcp/BuddyCommands.d.ts +0 -24
  326. package/dist/mcp/BuddyCommands.d.ts.map +0 -1
  327. package/dist/mcp/BuddyCommands.js +0 -423
  328. package/dist/mcp/BuddyCommands.js.map +0 -1
  329. package/dist/mcp/ClaudeMdReloader.d.ts +0 -37
  330. package/dist/mcp/ClaudeMdReloader.d.ts.map +0 -1
  331. package/dist/mcp/ClaudeMdReloader.js +0 -92
  332. package/dist/mcp/ClaudeMdReloader.js.map +0 -1
  333. package/dist/mcp/HumanInLoopUI.d.ts +0 -23
  334. package/dist/mcp/HumanInLoopUI.d.ts.map +0 -1
  335. package/dist/mcp/HumanInLoopUI.js +0 -92
  336. package/dist/mcp/HumanInLoopUI.js.map +0 -1
  337. package/dist/mcp/ProgressReporter.d.ts +0 -14
  338. package/dist/mcp/ProgressReporter.d.ts.map +0 -1
  339. package/dist/mcp/ProgressReporter.js +0 -22
  340. package/dist/mcp/ProgressReporter.js.map +0 -1
  341. package/dist/mcp/SamplingClient.d.ts +0 -32
  342. package/dist/mcp/SamplingClient.d.ts.map +0 -1
  343. package/dist/mcp/SamplingClient.js +0 -63
  344. package/dist/mcp/SamplingClient.js.map +0 -1
  345. package/dist/mcp/ServerInitializer.d.ts +0 -40
  346. package/dist/mcp/ServerInitializer.d.ts.map +0 -1
  347. package/dist/mcp/ServerInitializer.js +0 -147
  348. package/dist/mcp/ServerInitializer.js.map +0 -1
  349. package/dist/mcp/SessionBootstrapper.d.ts +0 -13
  350. package/dist/mcp/SessionBootstrapper.d.ts.map +0 -1
  351. package/dist/mcp/SessionBootstrapper.js +0 -82
  352. package/dist/mcp/SessionBootstrapper.js.map +0 -1
  353. package/dist/mcp/StdinBufferManager.d.ts +0 -11
  354. package/dist/mcp/StdinBufferManager.d.ts.map +0 -1
  355. package/dist/mcp/StdinBufferManager.js +0 -62
  356. package/dist/mcp/StdinBufferManager.js.map +0 -1
  357. package/dist/mcp/ToolDefinitions.d.ts +0 -44
  358. package/dist/mcp/ToolDefinitions.d.ts.map +0 -1
  359. package/dist/mcp/ToolDefinitions.js +0 -445
  360. package/dist/mcp/ToolDefinitions.js.map +0 -1
  361. package/dist/mcp/ToolRouter.d.ts +0 -27
  362. package/dist/mcp/ToolRouter.d.ts.map +0 -1
  363. package/dist/mcp/ToolRouter.js +0 -179
  364. package/dist/mcp/ToolRouter.js.map +0 -1
  365. package/dist/mcp/daemon/DaemonBootstrap.d.ts +0 -33
  366. package/dist/mcp/daemon/DaemonBootstrap.d.ts.map +0 -1
  367. package/dist/mcp/daemon/DaemonBootstrap.js +0 -155
  368. package/dist/mcp/daemon/DaemonBootstrap.js.map +0 -1
  369. package/dist/mcp/daemon/DaemonLockManager.d.ts +0 -47
  370. package/dist/mcp/daemon/DaemonLockManager.d.ts.map +0 -1
  371. package/dist/mcp/daemon/DaemonLockManager.js +0 -417
  372. package/dist/mcp/daemon/DaemonLockManager.js.map +0 -1
  373. package/dist/mcp/daemon/DaemonProtocol.d.ts +0 -127
  374. package/dist/mcp/daemon/DaemonProtocol.d.ts.map +0 -1
  375. package/dist/mcp/daemon/DaemonProtocol.js +0 -452
  376. package/dist/mcp/daemon/DaemonProtocol.js.map +0 -1
  377. package/dist/mcp/daemon/DaemonSocketServer.d.ts +0 -71
  378. package/dist/mcp/daemon/DaemonSocketServer.d.ts.map +0 -1
  379. package/dist/mcp/daemon/DaemonSocketServer.js +0 -384
  380. package/dist/mcp/daemon/DaemonSocketServer.js.map +0 -1
  381. package/dist/mcp/daemon/GracefulShutdownCoordinator.d.ts +0 -67
  382. package/dist/mcp/daemon/GracefulShutdownCoordinator.d.ts.map +0 -1
  383. package/dist/mcp/daemon/GracefulShutdownCoordinator.js +0 -206
  384. package/dist/mcp/daemon/GracefulShutdownCoordinator.js.map +0 -1
  385. package/dist/mcp/daemon/IpcTransport.d.ts +0 -42
  386. package/dist/mcp/daemon/IpcTransport.d.ts.map +0 -1
  387. package/dist/mcp/daemon/IpcTransport.js +0 -231
  388. package/dist/mcp/daemon/IpcTransport.js.map +0 -1
  389. package/dist/mcp/daemon/StdioProxyClient.d.ts +0 -84
  390. package/dist/mcp/daemon/StdioProxyClient.d.ts.map +0 -1
  391. package/dist/mcp/daemon/StdioProxyClient.js +0 -574
  392. package/dist/mcp/daemon/StdioProxyClient.js.map +0 -1
  393. package/dist/mcp/daemon/VersionManager.d.ts +0 -35
  394. package/dist/mcp/daemon/VersionManager.d.ts.map +0 -1
  395. package/dist/mcp/daemon/VersionManager.js +0 -169
  396. package/dist/mcp/daemon/VersionManager.js.map +0 -1
  397. package/dist/mcp/daemon/index.d.ts +0 -9
  398. package/dist/mcp/daemon/index.d.ts.map +0 -1
  399. package/dist/mcp/daemon/index.js +0 -9
  400. package/dist/mcp/daemon/index.js.map +0 -1
  401. package/dist/mcp/handlers/BuddyHandlers.d.ts +0 -18
  402. package/dist/mcp/handlers/BuddyHandlers.d.ts.map +0 -1
  403. package/dist/mcp/handlers/BuddyHandlers.js +0 -179
  404. package/dist/mcp/handlers/BuddyHandlers.js.map +0 -1
  405. package/dist/mcp/handlers/BuddyRecordMistake.d.ts +0 -17
  406. package/dist/mcp/handlers/BuddyRecordMistake.d.ts.map +0 -1
  407. package/dist/mcp/handlers/BuddyRecordMistake.js +0 -147
  408. package/dist/mcp/handlers/BuddyRecordMistake.js.map +0 -1
  409. package/dist/mcp/handlers/HookToolHandler.d.ts +0 -10
  410. package/dist/mcp/handlers/HookToolHandler.d.ts.map +0 -1
  411. package/dist/mcp/handlers/HookToolHandler.js +0 -92
  412. package/dist/mcp/handlers/HookToolHandler.js.map +0 -1
  413. package/dist/mcp/handlers/MemoryToolHandler.d.ts +0 -21
  414. package/dist/mcp/handlers/MemoryToolHandler.d.ts.map +0 -1
  415. package/dist/mcp/handlers/MemoryToolHandler.js +0 -433
  416. package/dist/mcp/handlers/MemoryToolHandler.js.map +0 -1
  417. package/dist/mcp/handlers/ResourceHandlers.d.ts +0 -3
  418. package/dist/mcp/handlers/ResourceHandlers.d.ts.map +0 -1
  419. package/dist/mcp/handlers/ResourceHandlers.js +0 -133
  420. package/dist/mcp/handlers/ResourceHandlers.js.map +0 -1
  421. package/dist/mcp/handlers/SystemToolHandler.d.ts +0 -14
  422. package/dist/mcp/handlers/SystemToolHandler.d.ts.map +0 -1
  423. package/dist/mcp/handlers/SystemToolHandler.js +0 -224
  424. package/dist/mcp/handlers/SystemToolHandler.js.map +0 -1
  425. package/dist/mcp/handlers/ToolHandlers.d.ts +0 -26
  426. package/dist/mcp/handlers/ToolHandlers.d.ts.map +0 -1
  427. package/dist/mcp/handlers/ToolHandlers.js +0 -41
  428. package/dist/mcp/handlers/ToolHandlers.js.map +0 -1
  429. package/dist/mcp/handlers/index.d.ts +0 -7
  430. package/dist/mcp/handlers/index.d.ts.map +0 -1
  431. package/dist/mcp/handlers/index.js +0 -7
  432. package/dist/mcp/handlers/index.js.map +0 -1
  433. package/dist/mcp/index.d.ts +0 -5
  434. package/dist/mcp/index.d.ts.map +0 -1
  435. package/dist/mcp/index.js +0 -3
  436. package/dist/mcp/index.js.map +0 -1
  437. package/dist/mcp/resources/ResourceRegistry.d.ts +0 -23
  438. package/dist/mcp/resources/ResourceRegistry.d.ts.map +0 -1
  439. package/dist/mcp/resources/ResourceRegistry.js +0 -26
  440. package/dist/mcp/resources/ResourceRegistry.js.map +0 -1
  441. package/dist/mcp/resources/URITemplateHandler.d.ts +0 -8
  442. package/dist/mcp/resources/URITemplateHandler.d.ts.map +0 -1
  443. package/dist/mcp/resources/URITemplateHandler.js +0 -29
  444. package/dist/mcp/resources/URITemplateHandler.js.map +0 -1
  445. package/dist/mcp/resources/best-practices.md +0 -53
  446. package/dist/mcp/resources/buddy-do-skill.md +0 -84
  447. package/dist/mcp/resources/ccb-complete-guide.md +0 -247
  448. package/dist/mcp/resources/examples.md +0 -47
  449. package/dist/mcp/resources/handlers/AgentStatusHandler.d.ts +0 -7
  450. package/dist/mcp/resources/handlers/AgentStatusHandler.d.ts.map +0 -1
  451. package/dist/mcp/resources/handlers/AgentStatusHandler.js +0 -41
  452. package/dist/mcp/resources/handlers/AgentStatusHandler.js.map +0 -1
  453. package/dist/mcp/resources/handlers/TaskLogsHandler.d.ts +0 -7
  454. package/dist/mcp/resources/handlers/TaskLogsHandler.d.ts.map +0 -1
  455. package/dist/mcp/resources/handlers/TaskLogsHandler.js +0 -35
  456. package/dist/mcp/resources/handlers/TaskLogsHandler.js.map +0 -1
  457. package/dist/mcp/resources/quick-reference.md +0 -71
  458. package/dist/mcp/resources/usage-guide.md +0 -74
  459. package/dist/mcp/schemas/OutputSchemas.d.ts +0 -437
  460. package/dist/mcp/schemas/OutputSchemas.d.ts.map +0 -1
  461. package/dist/mcp/schemas/OutputSchemas.js +0 -215
  462. package/dist/mcp/schemas/OutputSchemas.js.map +0 -1
  463. package/dist/mcp/server-bootstrap.d.ts +0 -3
  464. package/dist/mcp/server-bootstrap.d.ts.map +0 -1
  465. package/dist/mcp/server-bootstrap.js +0 -391
  466. package/dist/mcp/server-bootstrap.js.map +0 -1
  467. package/dist/mcp/tools/add-observations.d.ts +0 -48
  468. package/dist/mcp/tools/add-observations.d.ts.map +0 -1
  469. package/dist/mcp/tools/add-observations.js +0 -64
  470. package/dist/mcp/tools/add-observations.js.map +0 -1
  471. package/dist/mcp/tools/buddy-do.d.ts +0 -15
  472. package/dist/mcp/tools/buddy-do.d.ts.map +0 -1
  473. package/dist/mcp/tools/buddy-do.js +0 -191
  474. package/dist/mcp/tools/buddy-do.js.map +0 -1
  475. package/dist/mcp/tools/buddy-help.d.ts +0 -13
  476. package/dist/mcp/tools/buddy-help.d.ts.map +0 -1
  477. package/dist/mcp/tools/buddy-help.js +0 -44
  478. package/dist/mcp/tools/buddy-help.js.map +0 -1
  479. package/dist/mcp/tools/buddy-remember.d.ts +0 -24
  480. package/dist/mcp/tools/buddy-remember.d.ts.map +0 -1
  481. package/dist/mcp/tools/buddy-remember.js +0 -304
  482. package/dist/mcp/tools/buddy-remember.js.map +0 -1
  483. package/dist/mcp/tools/create-entities.d.ts +0 -66
  484. package/dist/mcp/tools/create-entities.d.ts.map +0 -1
  485. package/dist/mcp/tools/create-entities.js +0 -224
  486. package/dist/mcp/tools/create-entities.js.map +0 -1
  487. package/dist/mcp/tools/create-relations.d.ts +0 -60
  488. package/dist/mcp/tools/create-relations.d.ts.map +0 -1
  489. package/dist/mcp/tools/create-relations.js +0 -84
  490. package/dist/mcp/tools/create-relations.js.map +0 -1
  491. package/dist/mcp/tools/generate-tests.d.ts +0 -11
  492. package/dist/mcp/tools/generate-tests.d.ts.map +0 -1
  493. package/dist/mcp/tools/generate-tests.js +0 -19
  494. package/dist/mcp/tools/generate-tests.js.map +0 -1
  495. package/dist/mcp/tools/health-check.d.ts +0 -10
  496. package/dist/mcp/tools/health-check.d.ts.map +0 -1
  497. package/dist/mcp/tools/health-check.js +0 -37
  498. package/dist/mcp/tools/health-check.js.map +0 -1
  499. package/dist/mcp/tools/memesh-agent-register.d.ts +0 -20
  500. package/dist/mcp/tools/memesh-agent-register.d.ts.map +0 -1
  501. package/dist/mcp/tools/memesh-agent-register.js +0 -80
  502. package/dist/mcp/tools/memesh-agent-register.js.map +0 -1
  503. package/dist/mcp/tools/memesh-cloud-sync.d.ts +0 -30
  504. package/dist/mcp/tools/memesh-cloud-sync.d.ts.map +0 -1
  505. package/dist/mcp/tools/memesh-cloud-sync.js +0 -257
  506. package/dist/mcp/tools/memesh-cloud-sync.js.map +0 -1
  507. package/dist/mcp/tools/memesh-metrics.d.ts +0 -13
  508. package/dist/mcp/tools/memesh-metrics.d.ts.map +0 -1
  509. package/dist/mcp/tools/memesh-metrics.js +0 -193
  510. package/dist/mcp/tools/memesh-metrics.js.map +0 -1
  511. package/dist/mcp/tools/recall-memory.d.ts +0 -31
  512. package/dist/mcp/tools/recall-memory.d.ts.map +0 -1
  513. package/dist/mcp/tools/recall-memory.js +0 -31
  514. package/dist/mcp/tools/recall-memory.js.map +0 -1
  515. package/dist/mcp/validation.d.ts +0 -76
  516. package/dist/mcp/validation.d.ts.map +0 -1
  517. package/dist/mcp/validation.js +0 -106
  518. package/dist/mcp/validation.js.map +0 -1
  519. package/dist/memory/AutoMemoryRecorder.d.ts +0 -35
  520. package/dist/memory/AutoMemoryRecorder.d.ts.map +0 -1
  521. package/dist/memory/AutoMemoryRecorder.js +0 -164
  522. package/dist/memory/AutoMemoryRecorder.js.map +0 -1
  523. package/dist/memory/AutoTagger.d.ts +0 -9
  524. package/dist/memory/AutoTagger.d.ts.map +0 -1
  525. package/dist/memory/AutoTagger.js +0 -149
  526. package/dist/memory/AutoTagger.js.map +0 -1
  527. package/dist/memory/BuiltInRules.d.ts +0 -54
  528. package/dist/memory/BuiltInRules.d.ts.map +0 -1
  529. package/dist/memory/BuiltInRules.js +0 -161
  530. package/dist/memory/BuiltInRules.js.map +0 -1
  531. package/dist/memory/EnhancedRetrieval.d.ts +0 -22
  532. package/dist/memory/EnhancedRetrieval.d.ts.map +0 -1
  533. package/dist/memory/EnhancedRetrieval.js +0 -63
  534. package/dist/memory/EnhancedRetrieval.js.map +0 -1
  535. package/dist/memory/EntityTypes.d.ts +0 -14
  536. package/dist/memory/EntityTypes.d.ts.map +0 -1
  537. package/dist/memory/EntityTypes.js +0 -19
  538. package/dist/memory/EntityTypes.js.map +0 -1
  539. package/dist/memory/MemorySearchEngine.d.ts +0 -17
  540. package/dist/memory/MemorySearchEngine.d.ts.map +0 -1
  541. package/dist/memory/MemorySearchEngine.js +0 -88
  542. package/dist/memory/MemorySearchEngine.js.map +0 -1
  543. package/dist/memory/MistakePatternEngine.d.ts +0 -15
  544. package/dist/memory/MistakePatternEngine.d.ts.map +0 -1
  545. package/dist/memory/MistakePatternEngine.js +0 -99
  546. package/dist/memory/MistakePatternEngine.js.map +0 -1
  547. package/dist/memory/PreventionHook.d.ts +0 -28
  548. package/dist/memory/PreventionHook.d.ts.map +0 -1
  549. package/dist/memory/PreventionHook.js +0 -21
  550. package/dist/memory/PreventionHook.js.map +0 -1
  551. package/dist/memory/ProactiveRecaller.d.ts +0 -26
  552. package/dist/memory/ProactiveRecaller.d.ts.map +0 -1
  553. package/dist/memory/ProactiveRecaller.js +0 -96
  554. package/dist/memory/ProactiveRecaller.js.map +0 -1
  555. package/dist/memory/ProjectAutoTracker.d.ts +0 -80
  556. package/dist/memory/ProjectAutoTracker.d.ts.map +0 -1
  557. package/dist/memory/ProjectAutoTracker.js +0 -386
  558. package/dist/memory/ProjectAutoTracker.js.map +0 -1
  559. package/dist/memory/ProjectMemoryCleanup.d.ts +0 -17
  560. package/dist/memory/ProjectMemoryCleanup.d.ts.map +0 -1
  561. package/dist/memory/ProjectMemoryCleanup.js +0 -57
  562. package/dist/memory/ProjectMemoryCleanup.js.map +0 -1
  563. package/dist/memory/ProjectMemoryManager.d.ts +0 -19
  564. package/dist/memory/ProjectMemoryManager.d.ts.map +0 -1
  565. package/dist/memory/ProjectMemoryManager.js +0 -62
  566. package/dist/memory/ProjectMemoryManager.js.map +0 -1
  567. package/dist/memory/SmartMemoryQuery.d.ts +0 -9
  568. package/dist/memory/SmartMemoryQuery.d.ts.map +0 -1
  569. package/dist/memory/SmartMemoryQuery.js +0 -66
  570. package/dist/memory/SmartMemoryQuery.js.map +0 -1
  571. package/dist/memory/UnifiedMemoryStore.d.ts +0 -27
  572. package/dist/memory/UnifiedMemoryStore.d.ts.map +0 -1
  573. package/dist/memory/UnifiedMemoryStore.js +0 -536
  574. package/dist/memory/UnifiedMemoryStore.js.map +0 -1
  575. package/dist/memory/UserPreferenceEngine.d.ts +0 -18
  576. package/dist/memory/UserPreferenceEngine.d.ts.map +0 -1
  577. package/dist/memory/UserPreferenceEngine.js +0 -117
  578. package/dist/memory/UserPreferenceEngine.js.map +0 -1
  579. package/dist/memory/config/semantic-groups.d.ts +0 -9
  580. package/dist/memory/config/semantic-groups.d.ts.map +0 -1
  581. package/dist/memory/config/semantic-groups.js +0 -22
  582. package/dist/memory/config/semantic-groups.js.map +0 -1
  583. package/dist/memory/index.d.ts +0 -16
  584. package/dist/memory/index.d.ts.map +0 -1
  585. package/dist/memory/index.js +0 -12
  586. package/dist/memory/index.js.map +0 -1
  587. package/dist/memory/types/index.d.ts +0 -7
  588. package/dist/memory/types/index.d.ts.map +0 -1
  589. package/dist/memory/types/index.js +0 -4
  590. package/dist/memory/types/index.js.map +0 -1
  591. package/dist/memory/types/memory-scope.d.ts +0 -27
  592. package/dist/memory/types/memory-scope.d.ts.map +0 -1
  593. package/dist/memory/types/memory-scope.js +0 -67
  594. package/dist/memory/types/memory-scope.js.map +0 -1
  595. package/dist/memory/types/pattern-types.d.ts +0 -66
  596. package/dist/memory/types/pattern-types.d.ts.map +0 -1
  597. package/dist/memory/types/pattern-types.js +0 -2
  598. package/dist/memory/types/pattern-types.js.map +0 -1
  599. package/dist/memory/types/preference-types.d.ts +0 -28
  600. package/dist/memory/types/preference-types.d.ts.map +0 -1
  601. package/dist/memory/types/preference-types.js +0 -2
  602. package/dist/memory/types/preference-types.js.map +0 -1
  603. package/dist/memory/types/unified-memory.d.ts +0 -29
  604. package/dist/memory/types/unified-memory.d.ts.map +0 -1
  605. package/dist/memory/types/unified-memory.js +0 -21
  606. package/dist/memory/types/unified-memory.js.map +0 -1
  607. package/dist/prompts/templates/PromptTemplates.d.ts +0 -11
  608. package/dist/prompts/templates/PromptTemplates.d.ts.map +0 -1
  609. package/dist/prompts/templates/PromptTemplates.js +0 -942
  610. package/dist/prompts/templates/PromptTemplates.js.map +0 -1
  611. package/dist/prompts/templates/index.d.ts +0 -2
  612. package/dist/prompts/templates/index.d.ts.map +0 -1
  613. package/dist/prompts/templates/index.js +0 -2
  614. package/dist/prompts/templates/index.js.map +0 -1
  615. package/dist/skills/SkillManager.d.ts +0 -33
  616. package/dist/skills/SkillManager.d.ts.map +0 -1
  617. package/dist/skills/SkillManager.js +0 -153
  618. package/dist/skills/SkillManager.js.map +0 -1
  619. package/dist/skills/index.d.ts +0 -3
  620. package/dist/skills/index.d.ts.map +0 -1
  621. package/dist/skills/index.js +0 -2
  622. package/dist/skills/index.js.map +0 -1
  623. package/dist/telemetry/TelemetryCollector.d.ts +0 -19
  624. package/dist/telemetry/TelemetryCollector.d.ts.map +0 -1
  625. package/dist/telemetry/TelemetryCollector.js +0 -62
  626. package/dist/telemetry/TelemetryCollector.js.map +0 -1
  627. package/dist/telemetry/TelemetryStore.d.ts +0 -20
  628. package/dist/telemetry/TelemetryStore.d.ts.map +0 -1
  629. package/dist/telemetry/TelemetryStore.js +0 -127
  630. package/dist/telemetry/TelemetryStore.js.map +0 -1
  631. package/dist/telemetry/index.d.ts +0 -8
  632. package/dist/telemetry/index.d.ts.map +0 -1
  633. package/dist/telemetry/index.js +0 -33
  634. package/dist/telemetry/index.js.map +0 -1
  635. package/dist/telemetry/sanitization.d.ts +0 -6
  636. package/dist/telemetry/sanitization.d.ts.map +0 -1
  637. package/dist/telemetry/sanitization.js +0 -180
  638. package/dist/telemetry/sanitization.js.map +0 -1
  639. package/dist/telemetry/types.d.ts +0 -73
  640. package/dist/telemetry/types.d.ts.map +0 -1
  641. package/dist/telemetry/types.js +0 -16
  642. package/dist/telemetry/types.js.map +0 -1
  643. package/dist/tools/TestGenerator.d.ts +0 -8
  644. package/dist/tools/TestGenerator.d.ts.map +0 -1
  645. package/dist/tools/TestGenerator.js +0 -54
  646. package/dist/tools/TestGenerator.js.map +0 -1
  647. package/dist/types/AgentClassification.d.ts +0 -30
  648. package/dist/types/AgentClassification.d.ts.map +0 -1
  649. package/dist/types/AgentClassification.js +0 -19
  650. package/dist/types/AgentClassification.js.map +0 -1
  651. package/dist/types/Checkpoint.d.ts +0 -12
  652. package/dist/types/Checkpoint.d.ts.map +0 -1
  653. package/dist/types/Checkpoint.js +0 -13
  654. package/dist/types/Checkpoint.js.map +0 -1
  655. package/dist/types/toonify.d.ts +0 -91
  656. package/dist/types/toonify.d.ts.map +0 -1
  657. package/dist/types/toonify.js +0 -18
  658. package/dist/types/toonify.js.map +0 -1
  659. package/dist/ui/AsciiProgressBar.d.ts +0 -29
  660. package/dist/ui/AsciiProgressBar.d.ts.map +0 -1
  661. package/dist/ui/AsciiProgressBar.js +0 -130
  662. package/dist/ui/AsciiProgressBar.js.map +0 -1
  663. package/dist/ui/AttributionManager.d.ts +0 -19
  664. package/dist/ui/AttributionManager.d.ts.map +0 -1
  665. package/dist/ui/AttributionManager.js +0 -107
  666. package/dist/ui/AttributionManager.js.map +0 -1
  667. package/dist/ui/Dashboard.d.ts +0 -24
  668. package/dist/ui/Dashboard.d.ts.map +0 -1
  669. package/dist/ui/Dashboard.js +0 -135
  670. package/dist/ui/Dashboard.js.map +0 -1
  671. package/dist/ui/LoadingIndicator.d.ts +0 -53
  672. package/dist/ui/LoadingIndicator.d.ts.map +0 -1
  673. package/dist/ui/LoadingIndicator.js +0 -211
  674. package/dist/ui/LoadingIndicator.js.map +0 -1
  675. package/dist/ui/MetricsStore.d.ts +0 -15
  676. package/dist/ui/MetricsStore.d.ts.map +0 -1
  677. package/dist/ui/MetricsStore.js +0 -131
  678. package/dist/ui/MetricsStore.js.map +0 -1
  679. package/dist/ui/ProgressIndicator.d.ts +0 -35
  680. package/dist/ui/ProgressIndicator.d.ts.map +0 -1
  681. package/dist/ui/ProgressIndicator.js +0 -177
  682. package/dist/ui/ProgressIndicator.js.map +0 -1
  683. package/dist/ui/ProgressRenderer.d.ts +0 -24
  684. package/dist/ui/ProgressRenderer.d.ts.map +0 -1
  685. package/dist/ui/ProgressRenderer.js +0 -143
  686. package/dist/ui/ProgressRenderer.js.map +0 -1
  687. package/dist/ui/ResponseFormatter.d.ts +0 -57
  688. package/dist/ui/ResponseFormatter.d.ts.map +0 -1
  689. package/dist/ui/ResponseFormatter.js +0 -513
  690. package/dist/ui/ResponseFormatter.js.map +0 -1
  691. package/dist/ui/UIEventBus.d.ts +0 -38
  692. package/dist/ui/UIEventBus.d.ts.map +0 -1
  693. package/dist/ui/UIEventBus.js +0 -173
  694. package/dist/ui/UIEventBus.js.map +0 -1
  695. package/dist/ui/accessibility.d.ts +0 -28
  696. package/dist/ui/accessibility.d.ts.map +0 -1
  697. package/dist/ui/accessibility.js +0 -97
  698. package/dist/ui/accessibility.js.map +0 -1
  699. package/dist/ui/design-tokens.d.ts +0 -36
  700. package/dist/ui/design-tokens.d.ts.map +0 -1
  701. package/dist/ui/design-tokens.js +0 -94
  702. package/dist/ui/design-tokens.js.map +0 -1
  703. package/dist/ui/index.d.ts +0 -8
  704. package/dist/ui/index.d.ts.map +0 -1
  705. package/dist/ui/index.js +0 -6
  706. package/dist/ui/index.js.map +0 -1
  707. package/dist/ui/theme.d.ts +0 -313
  708. package/dist/ui/theme.d.ts.map +0 -1
  709. package/dist/ui/theme.js +0 -198
  710. package/dist/ui/theme.js.map +0 -1
  711. package/dist/ui/types.d.ts +0 -146
  712. package/dist/ui/types.d.ts.map +0 -1
  713. package/dist/ui/types.js +0 -16
  714. package/dist/ui/types.js.map +0 -1
  715. package/dist/utils/ILogger.d.ts +0 -7
  716. package/dist/utils/ILogger.d.ts.map +0 -1
  717. package/dist/utils/ILogger.js +0 -2
  718. package/dist/utils/ILogger.js.map +0 -1
  719. package/dist/utils/MinHeap.d.ts +0 -15
  720. package/dist/utils/MinHeap.d.ts.map +0 -1
  721. package/dist/utils/MinHeap.js +0 -69
  722. package/dist/utils/MinHeap.js.map +0 -1
  723. package/dist/utils/PathResolver.d.ts +0 -13
  724. package/dist/utils/PathResolver.d.ts.map +0 -1
  725. package/dist/utils/PathResolver.js +0 -77
  726. package/dist/utils/PathResolver.js.map +0 -1
  727. package/dist/utils/RateLimiter.d.ts +0 -28
  728. package/dist/utils/RateLimiter.d.ts.map +0 -1
  729. package/dist/utils/RateLimiter.js +0 -115
  730. package/dist/utils/RateLimiter.js.map +0 -1
  731. package/dist/utils/SystemResources.d.ts +0 -40
  732. package/dist/utils/SystemResources.d.ts.map +0 -1
  733. package/dist/utils/SystemResources.js +0 -216
  734. package/dist/utils/SystemResources.js.map +0 -1
  735. package/dist/utils/errorHandler.d.ts +0 -49
  736. package/dist/utils/errorHandler.d.ts.map +0 -1
  737. package/dist/utils/errorHandler.js +0 -397
  738. package/dist/utils/errorHandler.js.map +0 -1
  739. package/dist/utils/index.d.ts +0 -17
  740. package/dist/utils/index.d.ts.map +0 -1
  741. package/dist/utils/index.js +0 -15
  742. package/dist/utils/index.js.map +0 -1
  743. package/dist/utils/json.d.ts +0 -13
  744. package/dist/utils/json.d.ts.map +0 -1
  745. package/dist/utils/json.js +0 -95
  746. package/dist/utils/json.js.map +0 -1
  747. package/dist/utils/logger.d.ts +0 -16
  748. package/dist/utils/logger.d.ts.map +0 -1
  749. package/dist/utils/logger.js +0 -125
  750. package/dist/utils/logger.js.map +0 -1
  751. package/dist/utils/lru-cache.d.ts +0 -47
  752. package/dist/utils/lru-cache.d.ts.map +0 -1
  753. package/dist/utils/lru-cache.js +0 -239
  754. package/dist/utils/lru-cache.js.map +0 -1
  755. package/dist/utils/memory.d.ts +0 -20
  756. package/dist/utils/memory.d.ts.map +0 -1
  757. package/dist/utils/memory.js +0 -53
  758. package/dist/utils/memory.js.map +0 -1
  759. package/dist/utils/money.d.ts +0 -10
  760. package/dist/utils/money.d.ts.map +0 -1
  761. package/dist/utils/money.js +0 -25
  762. package/dist/utils/money.js.map +0 -1
  763. package/dist/utils/pathValidation.d.ts +0 -2
  764. package/dist/utils/pathValidation.d.ts.map +0 -1
  765. package/dist/utils/pathValidation.js +0 -62
  766. package/dist/utils/pathValidation.js.map +0 -1
  767. package/dist/utils/paths.d.ts +0 -4
  768. package/dist/utils/paths.d.ts.map +0 -1
  769. package/dist/utils/paths.js +0 -28
  770. package/dist/utils/paths.js.map +0 -1
  771. package/dist/utils/requestId.d.ts +0 -4
  772. package/dist/utils/requestId.d.ts.map +0 -1
  773. package/dist/utils/requestId.js +0 -17
  774. package/dist/utils/requestId.js.map +0 -1
  775. package/dist/utils/retry.d.ts +0 -20
  776. package/dist/utils/retry.d.ts.map +0 -1
  777. package/dist/utils/retry.js +0 -226
  778. package/dist/utils/retry.js.map +0 -1
  779. package/dist/utils/safeMath.d.ts +0 -11
  780. package/dist/utils/safeMath.d.ts.map +0 -1
  781. package/dist/utils/safeMath.js +0 -92
  782. package/dist/utils/safeMath.js.map +0 -1
  783. package/dist/utils/toonify-adapter.d.ts +0 -77
  784. package/dist/utils/toonify-adapter.d.ts.map +0 -1
  785. package/dist/utils/toonify-adapter.js +0 -282
  786. package/dist/utils/toonify-adapter.js.map +0 -1
  787. package/dist/utils/tracing/TraceContext.d.ts +0 -23
  788. package/dist/utils/tracing/TraceContext.d.ts.map +0 -1
  789. package/dist/utils/tracing/TraceContext.js +0 -127
  790. package/dist/utils/tracing/TraceContext.js.map +0 -1
  791. package/dist/utils/tracing/index.d.ts +0 -2
  792. package/dist/utils/tracing/index.d.ts.map +0 -1
  793. package/dist/utils/tracing/index.js +0 -2
  794. package/dist/utils/tracing/index.js.map +0 -1
  795. package/dist/utils/tracing/middleware.d.ts +0 -15
  796. package/dist/utils/tracing/middleware.d.ts.map +0 -1
  797. package/dist/utils/tracing/middleware.js +0 -49
  798. package/dist/utils/tracing/middleware.js.map +0 -1
  799. package/dist/utils/validation.d.ts +0 -12
  800. package/dist/utils/validation.d.ts.map +0 -1
  801. package/dist/utils/validation.js +0 -87
  802. package/dist/utils/validation.js.map +0 -1
  803. package/scripts/health-check.js +0 -331
  804. package/scripts/hooks/README.md +0 -230
  805. package/scripts/hooks/__tests__/hook-test-harness.js +0 -218
  806. package/scripts/hooks/__tests__/hooks.test.js +0 -267
  807. package/scripts/hooks/__tests__/post-tool-use-recall.test.js +0 -192
  808. package/scripts/hooks/__tests__/session-start-recall.test.js +0 -86
  809. package/scripts/hooks/hook-utils.js +0 -899
  810. package/scripts/hooks/post-tool-use-recall-utils.js +0 -74
  811. package/scripts/hooks/post-tool-use.js +0 -895
  812. package/scripts/hooks/pre-tool-use.js +0 -491
  813. package/scripts/hooks/session-start-recall-utils.js +0 -40
  814. package/scripts/hooks/stop.js +0 -673
  815. package/scripts/hooks/subagent-stop.js +0 -184
  816. package/scripts/postinstall-lib.js +0 -242
  817. package/scripts/postinstall-new.js +0 -191
  818. package/scripts/skills/comprehensive-code-review/SKILL.md +0 -276
@@ -0,0 +1,2672 @@
1
+ #!/usr/bin/env node
2
+ import Database from 'better-sqlite3';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import os from 'os';
6
+ import { execFile } from 'child_process';
7
+ import { fileURLToPath } from 'url';
8
+ const moduleDir = path.dirname(fileURLToPath(import.meta.url));
9
+ const bundledD3 = fs
10
+ .readFileSync(path.join(moduleDir, 'assets', 'd3.v7.min.js'), 'utf8')
11
+ .replace(/<\/script/gi, '<\\/script');
12
+ function queryData(dbPath) {
13
+ const emptyData = {
14
+ entities: [],
15
+ relations: [],
16
+ stats: {
17
+ totalEntities: 0,
18
+ totalObservations: 0,
19
+ totalRelations: 0,
20
+ totalTags: 0,
21
+ typeDistribution: {},
22
+ tagDistribution: {},
23
+ },
24
+ };
25
+ if (!fs.existsSync(dbPath)) {
26
+ return emptyData;
27
+ }
28
+ let db;
29
+ try {
30
+ db = new Database(dbPath, { readonly: true });
31
+ }
32
+ catch (err) {
33
+ console.error(`[memesh-view] Cannot open database at ${dbPath}: ${err.message}`);
34
+ return emptyData;
35
+ }
36
+ try {
37
+ const tables = db
38
+ .prepare("SELECT name FROM sqlite_master WHERE type='table' AND name IN ('entities', 'observations', 'relations', 'tags')")
39
+ .all()
40
+ .map((r) => r.name);
41
+ if (!tables.includes('entities')) {
42
+ return emptyData;
43
+ }
44
+ const hasStatus = db.prepare('PRAGMA table_info(entities)').all()
45
+ .some((col) => col.name === 'status');
46
+ const statusSelect = hasStatus ? ', status' : ", 'active' AS status";
47
+ const entityRows = db
48
+ .prepare(`SELECT id, name, type${statusSelect} FROM entities LIMIT 5000`)
49
+ .all();
50
+ const obsRows = tables.includes('observations')
51
+ ? db
52
+ .prepare('SELECT entity_id, content FROM observations')
53
+ .all()
54
+ : [];
55
+ const tagRows = tables.includes('tags')
56
+ ? db.prepare('SELECT entity_id, tag FROM tags').all()
57
+ : [];
58
+ const relationRows = tables.includes('relations')
59
+ ? db
60
+ .prepare('SELECT from_entity_id, to_entity_id, relation_type FROM relations')
61
+ .all()
62
+ : [];
63
+ const entityMap = new Map();
64
+ for (const e of entityRows) {
65
+ entityMap.set(e.id, e.name);
66
+ }
67
+ const obsByEntity = new Map();
68
+ for (const o of obsRows) {
69
+ const arr = obsByEntity.get(o.entity_id) ?? [];
70
+ arr.push(o.content);
71
+ obsByEntity.set(o.entity_id, arr);
72
+ }
73
+ const tagsByEntity = new Map();
74
+ for (const t of tagRows) {
75
+ const arr = tagsByEntity.get(t.entity_id) ?? [];
76
+ arr.push(t.tag);
77
+ tagsByEntity.set(t.entity_id, arr);
78
+ }
79
+ const entities = entityRows.map((e) => ({
80
+ id: e.id,
81
+ name: e.name,
82
+ type: e.type,
83
+ status: e.status,
84
+ observations: obsByEntity.get(e.id) ?? [],
85
+ tags: tagsByEntity.get(e.id) ?? [],
86
+ }));
87
+ const relations = relationRows
88
+ .filter((r) => entityMap.has(r.from_entity_id) && entityMap.has(r.to_entity_id))
89
+ .map((r) => ({
90
+ from: entityMap.get(r.from_entity_id),
91
+ to: entityMap.get(r.to_entity_id),
92
+ type: r.relation_type,
93
+ }));
94
+ const typeDistribution = {};
95
+ for (const e of entityRows) {
96
+ typeDistribution[e.type] = (typeDistribution[e.type] ?? 0) + 1;
97
+ }
98
+ const tagDistribution = {};
99
+ for (const t of tagRows) {
100
+ tagDistribution[t.tag] = (tagDistribution[t.tag] ?? 0) + 1;
101
+ }
102
+ return {
103
+ entities,
104
+ relations,
105
+ stats: {
106
+ totalEntities: entityRows.length,
107
+ totalObservations: obsRows.length,
108
+ totalRelations: relationRows.length,
109
+ totalTags: tagRows.length,
110
+ typeDistribution,
111
+ tagDistribution,
112
+ },
113
+ };
114
+ }
115
+ finally {
116
+ db.close();
117
+ }
118
+ }
119
+ function escapeJsonForHtml(json) {
120
+ return json
121
+ .replace(/&/g, '\\u0026')
122
+ .replace(/</g, '\\u003c')
123
+ .replace(/>/g, '\\u003e')
124
+ .replace(/\u2028/g, '\\u2028')
125
+ .replace(/\u2029/g, '\\u2029');
126
+ }
127
+ export function generateDashboardHtml(dbPath) {
128
+ const resolvedPath = dbPath ??
129
+ process.env.MEMESH_DB_PATH ??
130
+ path.join(os.homedir(), '.memesh', 'knowledge-graph.db');
131
+ const data = queryData(resolvedPath);
132
+ const dataJson = escapeJsonForHtml(JSON.stringify(data));
133
+ return `<!DOCTYPE html>
134
+ <html lang="en">
135
+ <head>
136
+ <meta charset="UTF-8">
137
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
138
+ <title>MeMesh LLM Memory — Dashboard</title>
139
+ <!-- bundled d3.js -->
140
+ <script>
141
+ ${bundledD3}
142
+ <\/script>
143
+ <style>
144
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
145
+ body {
146
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
147
+ background: #0d1117; color: #c9d1d9; line-height: 1.5;
148
+ }
149
+ .container { max-width: 1400px; margin: 0 auto; padding: 24px; }
150
+ h1 { font-size: 28px; margin-bottom: 24px; color: #f0f6fc; }
151
+ h2 { font-size: 20px; margin-bottom: 12px; color: #f0f6fc; }
152
+
153
+ /* Stats cards */
154
+ .stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 16px; margin-bottom: 32px; }
155
+ .stat-card {
156
+ background: #161b22; border: 1px solid #30363d; border-radius: 8px;
157
+ padding: 20px; text-align: center;
158
+ }
159
+ .stat-card .value { font-size: 36px; font-weight: 700; color: #58a6ff; }
160
+ .stat-card .label { font-size: 14px; color: #8b949e; margin-top: 4px; }
161
+
162
+ /* Graph */
163
+ .graph-container {
164
+ background: #161b22; border: 1px solid #30363d; border-radius: 8px;
165
+ margin-bottom: 32px; overflow: hidden;
166
+ }
167
+ .graph-container svg { width: 100%; height: 500px; display: block; }
168
+ .graph-container svg text { fill: #c9d1d9; font-size: 11px; pointer-events: none; }
169
+ .link-label { fill: #484f58; font-size: 9px; }
170
+
171
+ /* Tables */
172
+ .tables { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin-bottom: 32px; }
173
+ @media (max-width: 800px) { .tables { grid-template-columns: 1fr; } }
174
+ .table-section { background: #161b22; border: 1px solid #30363d; border-radius: 8px; padding: 16px; }
175
+ table { width: 100%; border-collapse: collapse; }
176
+ th, td { padding: 8px 12px; text-align: left; border-bottom: 1px solid #21262d; }
177
+ th { color: #8b949e; font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px; }
178
+ td { font-size: 14px; }
179
+
180
+ /* Entity table */
181
+ .entity-section { margin-bottom: 32px; }
182
+ .search-box {
183
+ width: 100%; padding: 10px 14px; margin-bottom: 16px;
184
+ background: #0d1117; border: 1px solid #30363d; border-radius: 6px;
185
+ color: #c9d1d9; font-size: 14px; outline: none;
186
+ }
187
+ .search-box:focus { border-color: #58a6ff; }
188
+ .entity-table-wrap {
189
+ background: #161b22; border: 1px solid #30363d; border-radius: 8px;
190
+ overflow: auto; max-height: 500px;
191
+ }
192
+
193
+ /* Tooltip */
194
+ .tooltip {
195
+ position: absolute; pointer-events: none; background: #1c2128;
196
+ border: 1px solid #30363d; border-radius: 6px; padding: 10px 14px;
197
+ font-size: 13px; max-width: 300px; display: none; z-index: 10;
198
+ }
199
+ .tooltip .tt-name { font-weight: 600; color: #f0f6fc; }
200
+ .tooltip .tt-type { color: #8b949e; font-size: 12px; }
201
+ .tooltip .tt-obs { margin-top: 6px; color: #c9d1d9; white-space: pre-line; }
202
+ </style>
203
+ </head>
204
+ <body>
205
+ <div class="container">
206
+ <h1>MeMesh LLM Memory</h1>
207
+ <p style="font-size:12px;color:#8b949e;margin-bottom:20px;">powered by pcircle.ai</p>
208
+
209
+ <div class="stats" id="stats"></div>
210
+
211
+ <h2>Knowledge Graph</h2>
212
+ <div class="graph-container"><svg id="graph"></svg></div>
213
+
214
+ <div class="entity-section">
215
+ <h2>Entities</h2>
216
+ <input class="search-box" id="search" type="text" placeholder="Search entities...">
217
+ <div class="entity-table-wrap">
218
+ <table>
219
+ <thead><tr><th>Name</th><th>Type</th><th>Status</th><th>Observations</th><th>Tags</th></tr></thead>
220
+ <tbody id="entity-tbody"></tbody>
221
+ </table>
222
+ </div>
223
+ </div>
224
+
225
+ <div class="tables">
226
+ <div class="table-section">
227
+ <h2>Type Distribution</h2>
228
+ <table><thead><tr><th>Type</th><th>Count</th></tr></thead><tbody id="type-tbody"></tbody></table>
229
+ </div>
230
+ <div class="table-section">
231
+ <h2>Tag Distribution</h2>
232
+ <table><thead><tr><th>Tag</th><th>Count</th></tr></thead><tbody id="tag-tbody"></tbody></table>
233
+ </div>
234
+ </div>
235
+ </div>
236
+
237
+ <div class="tooltip" id="tooltip">
238
+ <div class="tt-name"></div>
239
+ <div class="tt-type"></div>
240
+ <div class="tt-obs"></div>
241
+ </div>
242
+
243
+ <script>
244
+ const DATA = ${dataJson};
245
+
246
+ // Safe text escaping for DOM insertion
247
+ function esc(s) { var d = document.createElement('div'); d.textContent = s; return d.innerHTML; }
248
+
249
+ // --- Stats ---
250
+ (function renderStats() {
251
+ var s = DATA.stats;
252
+ var cards = [
253
+ { label: 'Entities', value: s.totalEntities },
254
+ { label: 'Observations', value: s.totalObservations },
255
+ { label: 'Relations', value: s.totalRelations },
256
+ { label: 'Tags', value: s.totalTags },
257
+ ];
258
+ var el = document.getElementById('stats');
259
+ el.textContent = '';
260
+ cards.forEach(function(c) {
261
+ var card = document.createElement('div');
262
+ card.className = 'stat-card';
263
+ var val = document.createElement('div');
264
+ val.className = 'value';
265
+ val.textContent = String(c.value);
266
+ var lbl = document.createElement('div');
267
+ lbl.className = 'label';
268
+ lbl.textContent = c.label;
269
+ card.appendChild(val);
270
+ card.appendChild(lbl);
271
+ el.appendChild(card);
272
+ });
273
+ })();
274
+
275
+ // --- Entity table ---
276
+ function renderEntityTable(filter) {
277
+ var f = (filter || '').toLowerCase();
278
+ var tbody = document.getElementById('entity-tbody');
279
+ tbody.textContent = '';
280
+ var filtered = DATA.entities.filter(function(e) {
281
+ return !f || e.name.toLowerCase().includes(f) || e.type.toLowerCase().includes(f);
282
+ });
283
+ if (filtered.length === 0) {
284
+ var tr = document.createElement('tr');
285
+ var td = document.createElement('td');
286
+ td.colSpan = 4;
287
+ td.style.textAlign = 'center';
288
+ td.style.color = '#8b949e';
289
+ td.textContent = 'No entities';
290
+ tr.appendChild(td);
291
+ tbody.appendChild(tr);
292
+ return;
293
+ }
294
+ filtered.forEach(function(e) {
295
+ var isArchived = e.status === 'archived';
296
+ var tr = document.createElement('tr');
297
+ if (isArchived) { tr.style.opacity = '0.4'; }
298
+ var tdName = document.createElement('td');
299
+ tdName.textContent = isArchived ? e.name + ' [archived]' : e.name;
300
+ var tdType = document.createElement('td'); tdType.textContent = e.type;
301
+ var tdStatus = document.createElement('td'); tdStatus.textContent = e.status || 'active';
302
+ var tdObs = document.createElement('td'); tdObs.textContent = String(e.observations.length);
303
+ var tdTags = document.createElement('td'); tdTags.textContent = e.tags.join(', ');
304
+ tr.appendChild(tdName); tr.appendChild(tdType); tr.appendChild(tdStatus); tr.appendChild(tdObs); tr.appendChild(tdTags);
305
+ tbody.appendChild(tr);
306
+ });
307
+ }
308
+ document.getElementById('search').addEventListener('input', function() { renderEntityTable(this.value); });
309
+ renderEntityTable('');
310
+
311
+ // --- Distribution tables ---
312
+ (function renderDistributions() {
313
+ function fillTable(tbodyId, data) {
314
+ var tbody = document.getElementById(tbodyId);
315
+ tbody.textContent = '';
316
+ var entries = Object.entries(data).sort(function(a, b) { return b[1] - a[1]; });
317
+ if (entries.length === 0) {
318
+ var tr = document.createElement('tr');
319
+ var td = document.createElement('td');
320
+ td.colSpan = 2; td.style.textAlign = 'center'; td.style.color = '#8b949e';
321
+ td.textContent = 'No data';
322
+ tr.appendChild(td); tbody.appendChild(tr);
323
+ return;
324
+ }
325
+ entries.forEach(function(pair) {
326
+ var tr = document.createElement('tr');
327
+ var tdKey = document.createElement('td'); tdKey.textContent = pair[0];
328
+ var tdVal = document.createElement('td'); tdVal.textContent = String(pair[1]);
329
+ tr.appendChild(tdKey); tr.appendChild(tdVal); tbody.appendChild(tr);
330
+ });
331
+ }
332
+ fillTable('type-tbody', DATA.stats.typeDistribution);
333
+ fillTable('tag-tbody', DATA.stats.tagDistribution);
334
+ })();
335
+
336
+ // --- D3.js Force Graph ---
337
+ (function renderGraph() {
338
+ if (DATA.relations.length === 0 && DATA.entities.length === 0) return;
339
+
340
+ var svg = d3.select('#graph');
341
+ var width = svg.node().getBoundingClientRect().width || 800;
342
+
343
+ // Only show the most connected entities to keep graph readable
344
+ var MAX_GRAPH_NODES = 40;
345
+ var degreeMap = {};
346
+ DATA.relations.forEach(function(r) {
347
+ degreeMap[r.from] = (degreeMap[r.from] || 0) + 1;
348
+ degreeMap[r.to] = (degreeMap[r.to] || 0) + 1;
349
+ });
350
+
351
+ // Sort by connection count, take top N
352
+ var topNames = Object.entries(degreeMap)
353
+ .sort(function(a, b) { return b[1] - a[1]; })
354
+ .slice(0, MAX_GRAPH_NODES)
355
+ .map(function(e) { return e[0]; });
356
+ var topSet = new Set(topNames);
357
+
358
+ // If no relations, show top 50 entities instead
359
+ var graphEntities = topSet.size > 0
360
+ ? DATA.entities.filter(function(e) { return topSet.has(e.name); })
361
+ : DATA.entities.slice(0, 50);
362
+
363
+ if (graphEntities.length === 0) return;
364
+
365
+ // Scale height based on node count
366
+ var height = Math.max(500, Math.min(700, graphEntities.length * 6));
367
+ svg.attr('viewBox', [0, 0, width, height]);
368
+ svg.style('height', height + 'px');
369
+
370
+ var color = d3.scaleOrdinal(d3.schemeTableau10);
371
+
372
+ var nodes = graphEntities.map(function(e) {
373
+ return {
374
+ id: e.name,
375
+ type: e.type,
376
+ status: e.status,
377
+ observations: e.observations,
378
+ radius: 6 + Math.min(e.observations.length, 5),
379
+ };
380
+ });
381
+
382
+ var nameSet = new Set(nodes.map(function(n) { return n.id; }));
383
+ var links = DATA.relations
384
+ .filter(function(r) { return nameSet.has(r.from) && nameSet.has(r.to); })
385
+ .map(function(r) { return { source: r.from, target: r.to, type: r.type }; });
386
+
387
+ var simulation = d3.forceSimulation(nodes)
388
+ .force('link', d3.forceLink(links).id(function(d) { return d.id; }).distance(200))
389
+ .force('charge', d3.forceManyBody().strength(-500))
390
+ .force('center', d3.forceCenter(width / 2, height / 2))
391
+ .force('collision', d3.forceCollide().radius(function(d) { return d.radius + 4; }));
392
+
393
+ var g = svg.append('g');
394
+
395
+ // Zoom
396
+ svg.call(d3.zoom().scaleExtent([0.2, 5]).on('zoom', function(event) {
397
+ g.attr('transform', event.transform);
398
+ }));
399
+
400
+ // Links
401
+ var link = g.append('g')
402
+ .selectAll('line')
403
+ .data(links)
404
+ .join('line')
405
+ .attr('stroke', '#30363d')
406
+ .attr('stroke-width', 1.5);
407
+
408
+ // Link labels
409
+ var linkLabel = g.append('g')
410
+ .selectAll('text')
411
+ .data(links)
412
+ .join('text')
413
+ .attr('class', 'link-label')
414
+ .text(function(d) { return d.type; });
415
+
416
+ // Nodes
417
+ var node = g.append('g')
418
+ .selectAll('circle')
419
+ .data(nodes)
420
+ .join('circle')
421
+ .attr('r', function(d) { return d.radius; })
422
+ .attr('fill', function(d) { return color(d.type); })
423
+ .attr('stroke', '#0d1117')
424
+ .attr('stroke-width', 1.5)
425
+ .style('opacity', function(d) { return d.status === 'archived' ? 0.4 : 1; })
426
+ .call(drag(simulation));
427
+
428
+ // Node labels
429
+ var label = g.append('g')
430
+ .selectAll('text')
431
+ .data(nodes)
432
+ .join('text')
433
+ .text(function(d) { return d.id.length > 35 ? d.id.slice(0, 35) + '...' : d.id; })
434
+ .attr('dx', function(d) { return d.radius + 4; })
435
+ .attr('dy', 4);
436
+
437
+ // Tooltip
438
+ var tooltipEl = document.getElementById('tooltip');
439
+ node.on('mouseover', function(event, d) {
440
+ tooltipEl.style.display = 'block';
441
+ tooltipEl.querySelector('.tt-name').textContent = d.id;
442
+ tooltipEl.querySelector('.tt-type').textContent = d.type;
443
+ tooltipEl.querySelector('.tt-obs').textContent = d.observations.slice(0, 3).join('\\n');
444
+ }).on('mousemove', function(event) {
445
+ tooltipEl.style.left = (event.pageX + 12) + 'px';
446
+ tooltipEl.style.top = (event.pageY - 10) + 'px';
447
+ }).on('mouseout', function() {
448
+ tooltipEl.style.display = 'none';
449
+ });
450
+
451
+ simulation.on('tick', function() {
452
+ link
453
+ .attr('x1', function(d) { return d.source.x; }).attr('y1', function(d) { return d.source.y; })
454
+ .attr('x2', function(d) { return d.target.x; }).attr('y2', function(d) { return d.target.y; });
455
+ linkLabel
456
+ .attr('x', function(d) { return (d.source.x + d.target.x) / 2; })
457
+ .attr('y', function(d) { return (d.source.y + d.target.y) / 2; });
458
+ node.attr('cx', function(d) { return d.x; }).attr('cy', function(d) { return d.y; });
459
+ label.attr('x', function(d) { return d.x; }).attr('y', function(d) { return d.y; });
460
+ });
461
+
462
+ function drag(simulation) {
463
+ return d3.drag()
464
+ .on('start', function(event, d) {
465
+ if (!event.active) simulation.alphaTarget(0.3).restart();
466
+ d.fx = d.x; d.fy = d.y;
467
+ })
468
+ .on('drag', function(event, d) { d.fx = event.x; d.fy = event.y; })
469
+ .on('end', function(event, d) {
470
+ if (!event.active) simulation.alphaTarget(0);
471
+ d.fx = null; d.fy = null;
472
+ });
473
+ }
474
+ })();
475
+ <\/script>
476
+ </body>
477
+ </html>`;
478
+ }
479
+ export function generateLiveDashboardHtml() {
480
+ const CSS = `
481
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');
482
+
483
+ :root {
484
+ --bg-primary: #09090b;
485
+ --bg-secondary: #111113;
486
+ --bg-card: rgba(17,17,19,0.8);
487
+ --bg-hover: rgba(39,39,42,0.5);
488
+ --border: rgba(39,39,42,0.8);
489
+ --border-subtle: rgba(39,39,42,0.4);
490
+ --text-primary: #fafafa;
491
+ --text-secondary: #a1a1aa;
492
+ --text-muted: #71717a;
493
+ --accent: #3b82f6;
494
+ --accent-glow: rgba(59,130,246,0.15);
495
+ --accent-hover: #60a5fa;
496
+ --danger: #ef4444;
497
+ --success: #22c55e;
498
+ --warning: #f59e0b;
499
+ --radius: 12px;
500
+ --radius-sm: 8px;
501
+ --radius-xs: 6px;
502
+ --font-sans: 'Inter', system-ui, -apple-system, sans-serif;
503
+ --font-mono: 'JetBrains Mono', ui-monospace, monospace;
504
+ --shadow-sm: 0 1px 2px rgba(0,0,0,0.3);
505
+ --shadow-md: 0 4px 12px rgba(0,0,0,0.4);
506
+ --shadow-lg: 0 8px 32px rgba(0,0,0,0.5);
507
+ --shadow-glow: 0 0 20px var(--accent-glow);
508
+ }
509
+
510
+ * { margin: 0; padding: 0; box-sizing: border-box; }
511
+
512
+ body {
513
+ font-family: var(--font-sans);
514
+ background: var(--bg-primary);
515
+ color: var(--text-primary);
516
+ line-height: 1.6;
517
+ -webkit-font-smoothing: antialiased;
518
+ }
519
+
520
+ /* Light mode overrides */
521
+ body.light {
522
+ --bg-primary: #fafafa;
523
+ --bg-secondary: #ffffff;
524
+ --bg-card: rgba(255,255,255,0.9);
525
+ --bg-hover: rgba(0,0,0,0.04);
526
+ --border: rgba(0,0,0,0.08);
527
+ --border-subtle: rgba(0,0,0,0.04);
528
+ --text-primary: #09090b;
529
+ --text-secondary: #52525b;
530
+ --text-muted: #a1a1aa;
531
+ --shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
532
+ --shadow-md: 0 4px 12px rgba(0,0,0,0.08);
533
+ --shadow-lg: 0 8px 32px rgba(0,0,0,0.12);
534
+ }
535
+
536
+ /* Header */
537
+ .header {
538
+ background: var(--bg-secondary);
539
+ border-bottom: 1px solid var(--border);
540
+ padding: 16px 24px;
541
+ display: flex;
542
+ align-items: center;
543
+ justify-content: space-between;
544
+ backdrop-filter: blur(12px);
545
+ position: sticky;
546
+ top: 0;
547
+ z-index: 100;
548
+ }
549
+ .header h1 {
550
+ font-size: 17px;
551
+ font-weight: 700;
552
+ letter-spacing: -0.02em;
553
+ color: var(--text-primary);
554
+ }
555
+ .subtitle {
556
+ font-size: 11px;
557
+ color: var(--text-muted);
558
+ font-weight: 400;
559
+ letter-spacing: 0.02em;
560
+ }
561
+ .version {
562
+ font-family: var(--font-mono);
563
+ font-size: 11px;
564
+ color: var(--text-muted);
565
+ background: var(--bg-hover);
566
+ padding: 2px 8px;
567
+ border-radius: var(--radius-xs);
568
+ }
569
+ .header-right { display: flex; align-items: center; gap: 12px; }
570
+ .header .meta { display: flex; align-items: center; gap: 12px; }
571
+
572
+ .dot {
573
+ width: 7px; height: 7px; border-radius: 50%;
574
+ display: inline-block; margin-right: 6px;
575
+ background: var(--text-muted);
576
+ }
577
+ .dot.connected { background: var(--success); box-shadow: 0 0 6px rgba(34,197,94,0.4); }
578
+ .dot.error { background: var(--danger); }
579
+
580
+ /* Navigation */
581
+ .nav {
582
+ display: flex;
583
+ background: var(--bg-secondary);
584
+ border-bottom: 1px solid var(--border);
585
+ padding: 0 24px;
586
+ gap: 2px;
587
+ overflow-x: auto;
588
+ scrollbar-width: none;
589
+ }
590
+ .nav::-webkit-scrollbar { display: none; }
591
+ .nav button {
592
+ padding: 12px 16px;
593
+ border: none;
594
+ background: none;
595
+ cursor: pointer;
596
+ font-size: 13px;
597
+ font-weight: 500;
598
+ color: var(--text-muted);
599
+ border-bottom: 2px solid transparent;
600
+ transition: all 0.2s ease;
601
+ white-space: nowrap;
602
+ font-family: var(--font-sans);
603
+ }
604
+ .nav button:hover { color: var(--text-secondary); background: var(--bg-hover); }
605
+ .nav button.active { color: var(--text-primary); border-bottom-color: var(--accent); }
606
+
607
+ /* Content */
608
+ .content { max-width: 1280px; margin: 0 auto; padding: 24px; }
609
+
610
+ /* Tab panels */
611
+ .tab-content { display: none; }
612
+ .tab-content.active { display: block; }
613
+
614
+ /* Cards */
615
+ .card {
616
+ background: var(--bg-card);
617
+ border: 1px solid var(--border);
618
+ border-radius: var(--radius);
619
+ padding: 20px;
620
+ margin-bottom: 16px;
621
+ backdrop-filter: blur(8px);
622
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
623
+ }
624
+ .card:hover { border-color: rgba(59,130,246,0.2); box-shadow: var(--shadow-glow); }
625
+ .card h2 { font-size: 15px; font-weight: 600; margin-bottom: 16px; color: var(--text-primary); letter-spacing: -0.01em; }
626
+
627
+ /* Forms */
628
+ input, button, textarea { font-family: var(--font-sans); font-size: 14px; }
629
+ .search-row { display: flex; gap: 8px; margin-bottom: 20px; }
630
+ .search-input {
631
+ flex: 1;
632
+ padding: 10px 14px;
633
+ background: var(--bg-primary);
634
+ border: 1px solid var(--border);
635
+ border-radius: var(--radius-sm);
636
+ color: var(--text-primary);
637
+ font-size: 14px;
638
+ font-family: var(--font-sans);
639
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
640
+ outline: none;
641
+ }
642
+ .search-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }
643
+ .search-input::placeholder { color: var(--text-muted); }
644
+
645
+ /* Buttons */
646
+ .btn {
647
+ padding: 8px 16px;
648
+ border: 1px solid var(--border);
649
+ border-radius: var(--radius-sm);
650
+ cursor: pointer;
651
+ font-size: 13px;
652
+ font-weight: 500;
653
+ font-family: var(--font-sans);
654
+ transition: all 0.15s ease;
655
+ background: var(--bg-secondary);
656
+ color: var(--text-primary);
657
+ }
658
+ .btn:hover { background: var(--bg-hover); border-color: var(--text-muted); }
659
+ .btn-primary { background: var(--accent); border-color: var(--accent); color: white; }
660
+ .btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
661
+ .btn-secondary { background: var(--bg-secondary); color: var(--text-secondary); border-color: var(--border); }
662
+ .btn-secondary:hover { background: var(--bg-hover); color: var(--text-primary); }
663
+ .btn-danger { border-color: var(--danger); color: var(--danger); background: transparent; }
664
+ .btn-danger:hover { background: rgba(239,68,68,0.1); }
665
+ .btn:disabled { opacity: 0.4; cursor: not-allowed; }
666
+ .btn-sm { padding: 6px 12px; font-size: 12px; }
667
+
668
+ /* Tables */
669
+ .table-wrap { overflow-x: auto; border-radius: var(--radius); border: 1px solid var(--border); -webkit-overflow-scrolling: touch; }
670
+ table { width: 100%; border-collapse: collapse; min-width: 500px; table-layout: auto; }
671
+ th {
672
+ text-align: left;
673
+ padding: 10px 14px;
674
+ font-size: 11px;
675
+ font-weight: 600;
676
+ color: var(--text-muted);
677
+ text-transform: uppercase;
678
+ letter-spacing: 0.05em;
679
+ background: var(--bg-secondary);
680
+ border-bottom: 1px solid var(--border);
681
+ }
682
+ td {
683
+ padding: 10px 14px;
684
+ border-bottom: 1px solid var(--border-subtle);
685
+ font-size: 13px;
686
+ color: var(--text-secondary);
687
+ word-break: break-word;
688
+ }
689
+ tbody tr { transition: background 0.15s ease; }
690
+ tbody tr:hover { background: var(--bg-hover); }
691
+ tbody tr:last-child td { border-bottom: none; }
692
+
693
+ /* Badges */
694
+ .badge { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 11px; font-weight: 500; letter-spacing: 0.02em; }
695
+ .badge-active { background: rgba(34,197,94,0.12); color: #4ade80; }
696
+ .badge-archived { background: rgba(239,68,68,0.12); color: #f87171; }
697
+ .badge-type { background: var(--accent-glow); color: var(--accent-hover); }
698
+
699
+ /* Entity name */
700
+ .entity-name { font-weight: 500; color: var(--text-primary); }
701
+ .entity-obs { color: var(--text-muted); font-size: 12px; font-family: var(--font-mono); }
702
+
703
+ /* Tag pills */
704
+ .tag-pill {
705
+ display: inline-block; padding: 2px 8px; margin: 2px;
706
+ border-radius: 999px; font-size: 11px;
707
+ font-family: var(--font-mono);
708
+ background: var(--bg-hover);
709
+ color: var(--text-secondary);
710
+ border: 1px solid var(--border-subtle);
711
+ cursor: default;
712
+ }
713
+
714
+ /* Placeholder */
715
+ .placeholder { text-align: center; padding: 60px 20px; color: var(--text-muted); font-size: 14px; }
716
+ .placeholder .icon { font-size: 32px; margin-bottom: 12px; display: block; }
717
+
718
+ /* Result / error box */
719
+ .result-box { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 14px; margin-top: 12px; font-size: 13px; font-family: var(--font-mono); white-space: pre-wrap; max-height: 400px; overflow: auto; color: var(--text-secondary); }
720
+ .result-box.error { background: rgba(239,68,68,0.08); border-color: rgba(239,68,68,0.2); color: #f87171; }
721
+
722
+ /* Loading spinner */
723
+ .loading { display: inline-block; width: 16px; height: 16px; border: 2px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.7s linear infinite; vertical-align: middle; }
724
+ @keyframes spin { to { transform: rotate(360deg); } }
725
+
726
+ /* Settings */
727
+ .settings-section { margin-bottom: 28px; }
728
+ .settings-section h3 { font-size: 13px; font-weight: 600; color: var(--text-muted); margin-bottom: 12px; padding-bottom: 8px; border-bottom: 1px solid var(--border); text-transform: uppercase; letter-spacing: 0.05em; }
729
+ .form-group { margin-bottom: 14px; }
730
+ .form-label { display: block; font-size: 13px; font-weight: 500; color: var(--text-primary); margin-bottom: 5px; }
731
+ .form-hint { font-size: 12px; color: var(--text-muted); margin-top: 4px; }
732
+ .provider-radio-group { display: flex; gap: 8px; flex-wrap: wrap; }
733
+ .provider-radio { display: flex; align-items: center; gap: 6px; padding: 8px 14px; border: 1px solid var(--border); border-radius: var(--radius-sm); cursor: pointer; transition: border-color 0.15s; color: var(--text-secondary); font-size: 13px; }
734
+ .provider-radio:hover { border-color: var(--accent); color: var(--text-primary); }
735
+ .provider-radio.selected { border-color: var(--accent); background: var(--accent-glow); color: var(--accent-hover); }
736
+ .provider-radio input[type=radio] { accent-color: var(--accent); }
737
+ .cap-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; margin-bottom: 16px; }
738
+ .cap-item { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 10px 12px; font-size: 12px; }
739
+ .cap-item .cap-label { color: var(--text-muted); margin-bottom: 2px; }
740
+ .cap-item .cap-value { font-weight: 600; color: var(--text-primary); font-family: var(--font-mono); }
741
+ .status-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 5px; }
742
+ .status-dot.ok { background: var(--success); box-shadow: 0 0 5px rgba(34,197,94,0.4); }
743
+ .status-dot.warn { background: var(--warning); }
744
+
745
+ /* Welcome wizard modal */
746
+ .wizard-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.7); display: flex; align-items: center; justify-content: center; z-index: 1000; backdrop-filter: blur(4px); }
747
+ .wizard-overlay.hidden { display: none; }
748
+ .wizard-modal { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: var(--radius); padding: 32px; max-width: 520px; width: 90%; box-shadow: var(--shadow-lg); }
749
+ .wizard-modal h2 { font-size: 22px; font-weight: 700; margin-bottom: 8px; color: var(--text-primary); letter-spacing: -0.02em; }
750
+ .wizard-modal .subtitle { color: var(--text-secondary); font-size: 14px; margin-bottom: 24px; line-height: 1.6; }
751
+ .wizard-steps { display: flex; gap: 6px; margin-bottom: 28px; }
752
+ .wizard-step-dot { flex: 1; height: 3px; background: var(--border); border-radius: 2px; transition: background 0.2s; }
753
+ .wizard-step-dot.active { background: var(--accent); }
754
+ .wizard-step-dot.done { background: var(--success); }
755
+ .wizard-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 24px; }
756
+
757
+ /* Analytics */
758
+ .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; margin-bottom: 20px; }
759
+ .stat-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px; text-align: center; backdrop-filter: blur(8px); }
760
+ .stat-card .stat-value { font-size: 32px; font-weight: 700; color: var(--accent); font-family: var(--font-mono); line-height: 1.2; }
761
+ .stat-card .stat-label { font-size: 11px; color: var(--text-muted); margin-top: 4px; text-transform: uppercase; letter-spacing: 0.05em; }
762
+ .bar-chart { margin-bottom: 20px; }
763
+ .bar-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; font-size: 13px; }
764
+ .bar-label { width: 140px; flex-shrink: 0; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
765
+ .bar-track { flex: 1; background: var(--bg-hover); border-radius: 4px; height: 8px; overflow: hidden; }
766
+ .bar-fill { height: 100%; background: var(--accent); border-radius: 4px; transition: width 0.3s ease; opacity: 0.8; }
767
+ .bar-count { width: 36px; text-align: right; color: var(--text-muted); flex-shrink: 0; font-family: var(--font-mono); font-size: 12px; }
768
+ .tag-cloud { display: flex; flex-wrap: wrap; gap: 8px; }
769
+
770
+ /* Timeline */
771
+ .chain { display: flex; align-items: center; flex-wrap: wrap; gap: 0; margin-bottom: 16px; padding: 16px; background: var(--bg-secondary); border: 1px solid var(--border); border-radius: var(--radius); }
772
+ .chain-node { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 8px 14px; font-size: 13px; position: relative; transition: border-color 0.15s; }
773
+ .chain-node:hover { border-color: var(--accent); }
774
+ .chain-node.archived { opacity: 0.4; }
775
+ .chain-node .cn-name { font-weight: 600; color: var(--text-primary); }
776
+ .chain-node .cn-type { font-size: 11px; color: var(--text-muted); font-family: var(--font-mono); }
777
+ .chain-arrow { font-size: 16px; color: var(--accent); padding: 0 8px; flex-shrink: 0; opacity: 0.6; }
778
+
779
+ /* Graph */
780
+ .graph-svg-wrap { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; position: relative; }
781
+ .graph-svg-wrap svg { width: 100%; height: 520px; display: block; }
782
+ .graph-controls { display: flex; gap: 8px; margin-bottom: 12px; align-items: center; font-size: 12px; color: var(--text-muted); }
783
+
784
+ /* Graph tooltip */
785
+ .graph-tooltip {
786
+ position: absolute;
787
+ background: var(--bg-card);
788
+ border: 1px solid var(--border);
789
+ border-radius: var(--radius-sm);
790
+ padding: 12px 16px;
791
+ font-size: 12px;
792
+ pointer-events: none;
793
+ backdrop-filter: blur(12px);
794
+ box-shadow: var(--shadow-lg);
795
+ max-width: 280px;
796
+ z-index: 10;
797
+ }
798
+
799
+ /* Manage */
800
+ .manage-action-cell { display: flex; gap: 6px; flex-wrap: wrap; }
801
+
802
+ /* Feedback widget */
803
+ #feedback-btn {
804
+ position: fixed; bottom: 24px; right: 24px;
805
+ background: var(--accent); color: white;
806
+ border: none; padding: 10px 16px;
807
+ border-radius: 999px; cursor: pointer;
808
+ font-size: 13px; font-weight: 500;
809
+ box-shadow: var(--shadow-md), var(--shadow-glow);
810
+ transition: all 0.2s ease; z-index: 50;
811
+ font-family: var(--font-sans);
812
+ }
813
+ #feedback-btn:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg), 0 0 30px var(--accent-glow); }
814
+ #feedback-panel {
815
+ position: fixed; bottom: 72px; right: 24px;
816
+ width: 340px; background: var(--bg-secondary);
817
+ border: 1px solid var(--border); border-radius: var(--radius);
818
+ padding: 20px; box-shadow: var(--shadow-lg);
819
+ z-index: 51; backdrop-filter: blur(16px); display: none;
820
+ }
821
+ #feedback-panel.open { display: block; }
822
+ #feedback-panel h3 { font-size: 14px; font-weight: 600; margin-bottom: 14px; color: var(--text-primary); }
823
+ .fb-radio-group { display: flex; gap: 8px; margin-bottom: 12px; }
824
+ .fb-radio { display: flex; align-items: center; gap: 5px; padding: 5px 10px; border: 1px solid var(--border); border-radius: var(--radius-xs); cursor: pointer; font-size: 12px; color: var(--text-secondary); }
825
+ .fb-radio.selected { border-color: var(--accent); background: var(--accent-glow); color: var(--accent-hover); }
826
+ .fb-radio input { accent-color: var(--accent); }
827
+ #fb-desc { width: 100%; height: 80px; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius-xs); font-size: 13px; resize: vertical; outline: none; margin-bottom: 10px; background: var(--bg-primary); color: var(--text-primary); font-family: var(--font-sans); }
828
+ #fb-desc:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }
829
+ .fb-sys-row { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted); margin-bottom: 12px; }
830
+
831
+ /* Highlight */
832
+ mark { background: rgba(59,130,246,0.2); color: inherit; padding: 1px 3px; border-radius: 3px; }
833
+
834
+ /* Hidden */
835
+ .hidden { display: none !important; }
836
+
837
+ /* Scrollbar */
838
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
839
+ ::-webkit-scrollbar-track { background: transparent; }
840
+ ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
841
+ ::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
842
+
843
+ /* Responsive */
844
+ @media (max-width: 768px) {
845
+ .content { padding: 16px; }
846
+ .nav button { padding: 10px 12px; font-size: 12px; }
847
+ .header h1 { font-size: 15px; }
848
+ .search-row { flex-direction: column; }
849
+ .stats-grid { grid-template-columns: 1fr 1fr; }
850
+ #feedback-panel { width: calc(100vw - 48px); }
851
+ #feedback-btn { bottom: 16px; right: 16px; }
852
+ }
853
+ @media (max-width: 480px) {
854
+ .nav { gap: 0; }
855
+ .nav button { flex: 1; font-size: 11px; padding: 10px 6px; }
856
+ .stats-grid { grid-template-columns: 1fr; }
857
+ .header { padding: 12px 16px; }
858
+ }
859
+ `.trim();
860
+ const SCRIPT = `
861
+ (function () {
862
+ 'use strict';
863
+
864
+ var _currentVersion = '';
865
+ var _currentSearchLevel = '';
866
+
867
+ // ---- API ----
868
+ async function apiCall(method, path, body) {
869
+ var controller = new AbortController();
870
+ var timeout = setTimeout(function() { controller.abort(); }, 10000);
871
+ try {
872
+ var opts = { method: method, headers: { 'Content-Type': 'application/json' }, signal: controller.signal };
873
+ if (body !== undefined) opts.body = JSON.stringify(body);
874
+ var res = await fetch(path, opts);
875
+ clearTimeout(timeout);
876
+ if (!res.ok) throw new Error('HTTP ' + res.status);
877
+ return await res.json();
878
+ } catch (err) {
879
+ clearTimeout(timeout);
880
+ if (err.name === 'AbortError') throw new Error('Request timed out (10s)');
881
+ throw err;
882
+ }
883
+ }
884
+
885
+ // ---- Theme (dark default, light class toggles light mode) ----
886
+ (function initTheme() {
887
+ var saved = localStorage.getItem('memesh-theme');
888
+ if (saved === 'light') { document.body.classList.add('light'); }
889
+ var themeBtn = document.getElementById('theme-btn');
890
+ if (themeBtn) {
891
+ themeBtn.textContent = document.body.classList.contains('light') ? '\\ud83c\\udf19' : '\\u2600\\ufe0f';
892
+ themeBtn.addEventListener('click', function () {
893
+ document.body.classList.toggle('light');
894
+ var isLight = document.body.classList.contains('light');
895
+ themeBtn.textContent = isLight ? '\\ud83c\\udf19' : '\\u2600\\ufe0f';
896
+ localStorage.setItem('memesh-theme', isLight ? 'light' : 'dark');
897
+ try { apiCall('POST', '/v1/config', { theme: isLight ? 'light' : 'dark' }); } catch (_) {}
898
+ // Update graph label colors if graph has been rendered
899
+ var newLabelColor = isLight ? '#09090b' : '#fafafa';
900
+ var graphWrap = document.getElementById('graph-svg-wrap');
901
+ if (graphWrap) {
902
+ graphWrap.querySelectorAll('svg g text:not([font-size="9"])').forEach(function(el) {
903
+ el.setAttribute('fill', newLabelColor);
904
+ });
905
+ }
906
+ });
907
+ }
908
+ })();
909
+
910
+ // ---- Tab switching ----
911
+ document.getElementById('nav').addEventListener('click', function (e) {
912
+ var btn = e.target.closest('button[data-tab]');
913
+ if (!btn) return;
914
+ var tab = btn.dataset.tab;
915
+ document.querySelectorAll('.nav button').forEach(function (b) { b.classList.remove('active'); });
916
+ btn.classList.add('active');
917
+ document.querySelectorAll('.tab-content').forEach(function (el) { el.classList.remove('active'); });
918
+ document.getElementById('tab-' + tab).classList.add('active');
919
+ if (tab === 'browse') loadBrowse();
920
+ if (tab === 'graph') loadGraph();
921
+ if (tab === 'analytics') loadAnalytics();
922
+ if (tab === 'timeline') loadTimeline();
923
+ if (tab === 'manage') loadManage();
924
+ if (tab === 'settings') loadSettings();
925
+ });
926
+
927
+ // ---- Health check ----
928
+ async function checkHealth() {
929
+ var indicator = document.getElementById('health-indicator');
930
+ var versionLabel = document.getElementById('version-label');
931
+ try {
932
+ var data = await apiCall('GET', '/v1/health');
933
+ if (!data.success) throw new Error(data.error || 'API error');
934
+ _currentVersion = data.data.version || '';
935
+ var dot = document.createElement('span');
936
+ dot.className = 'dot';
937
+ indicator.textContent = '';
938
+ indicator.appendChild(dot);
939
+ indicator.appendChild(document.createTextNode('Connected'));
940
+ versionLabel.textContent = 'v' + data.data.version + ' \u00b7 ' + data.data.entity_count + ' entities';
941
+ } catch (_err) {
942
+ var dot2 = document.createElement('span');
943
+ dot2.className = 'dot error';
944
+ indicator.textContent = '';
945
+ indicator.appendChild(dot2);
946
+ indicator.appendChild(document.createTextNode('Disconnected'));
947
+ }
948
+ }
949
+
950
+ // ---- Shared: build entity table from array using only DOM APIs ----
951
+ // Redesigned: shows Time (locale) | Memory Preview | Source/Type | Status | Tags
952
+ // Entity name is secondary — first observation preview is the primary content
953
+ function buildEntityTable(entities, highlightTerm) {
954
+ var table = document.createElement('table');
955
+ var thead = document.createElement('thead');
956
+ var hrow = document.createElement('tr');
957
+ ['Time', 'Memory', 'Type', 'Status', 'Tags'].forEach(function (h) {
958
+ var th = document.createElement('th');
959
+ th.textContent = h;
960
+ if (h === 'Memory') th.style.width = '45%';
961
+ if (h === 'Time') th.style.width = '140px';
962
+ hrow.appendChild(th);
963
+ });
964
+ thead.appendChild(hrow);
965
+ table.appendChild(thead);
966
+ var tbody = document.createElement('tbody');
967
+ entities.forEach(function (e) {
968
+ var status = e.archived ? 'archived' : (e.status || 'active');
969
+ var tr = document.createElement('tr');
970
+ if (status === 'archived') tr.style.opacity = '0.5';
971
+
972
+ // Time column — locale-formatted timestamp
973
+ var tdTime = document.createElement('td');
974
+ tdTime.style.cssText = 'font-family:var(--font-mono);font-size:11px;color:var(--text-muted);white-space:nowrap;';
975
+ try {
976
+ var d = new Date(e.created_at);
977
+ tdTime.textContent = d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' }) + ' ' + d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
978
+ } catch (_) {
979
+ tdTime.textContent = e.created_at || '—';
980
+ }
981
+ tdTime.title = e.created_at || '';
982
+ tr.appendChild(tdTime);
983
+
984
+ // Memory column — first observation as preview, entity name as secondary
985
+ var tdMemory = document.createElement('td');
986
+ var memoryContent = document.createElement('div');
987
+
988
+ // Primary: first observation (the actual useful content)
989
+ var preview = document.createElement('div');
990
+ preview.style.cssText = 'font-size:13px;line-height:1.5;margin-bottom:2px;';
991
+ var firstObs = (e.observations && e.observations.length > 0) ? e.observations[0] : '(no observations)';
992
+ var previewText = firstObs.length > 120 ? firstObs.slice(0, 120) + '\\u2026' : firstObs;
993
+ if (highlightTerm) {
994
+ highlightText(preview, previewText, highlightTerm);
995
+ } else {
996
+ preview.textContent = previewText;
997
+ }
998
+ memoryContent.appendChild(preview);
999
+
1000
+ // Secondary: entity name (technical identifier) + observation count
1001
+ var meta = document.createElement('div');
1002
+ meta.style.cssText = 'font-size:11px;color:var(--text-muted);font-family:var(--font-mono);';
1003
+ var obsCount = e.observations ? e.observations.length : 0;
1004
+ meta.textContent = e.name + (obsCount > 1 ? ' \\u00b7 ' + obsCount + ' observations' : '');
1005
+ memoryContent.appendChild(meta);
1006
+
1007
+ tdMemory.appendChild(memoryContent);
1008
+ tr.appendChild(tdMemory);
1009
+
1010
+ // Type badge
1011
+ var tdType = document.createElement('td');
1012
+ var typeBadge = document.createElement('span');
1013
+ typeBadge.className = 'badge badge-type';
1014
+ typeBadge.textContent = e.type;
1015
+ tdType.appendChild(typeBadge);
1016
+ tr.appendChild(tdType);
1017
+
1018
+ // Status badge
1019
+ var tdStatus = document.createElement('td');
1020
+ var statusBadge = document.createElement('span');
1021
+ statusBadge.className = 'badge badge-' + (status === 'archived' ? 'archived' : 'active');
1022
+ statusBadge.textContent = status;
1023
+ tdStatus.appendChild(statusBadge);
1024
+ tr.appendChild(tdStatus);
1025
+
1026
+ // Tags
1027
+ var tdTags = document.createElement('td');
1028
+ if (e.tags && e.tags.length > 0) {
1029
+ e.tags.slice(0, 3).forEach(function (t) {
1030
+ var pill = document.createElement('span');
1031
+ pill.className = 'tag-pill';
1032
+ pill.textContent = t;
1033
+ tdTags.appendChild(pill);
1034
+ });
1035
+ if (e.tags.length > 3) {
1036
+ var more = document.createElement('span');
1037
+ more.className = 'tag-pill';
1038
+ more.style.opacity = '0.6';
1039
+ more.textContent = '+' + (e.tags.length - 3);
1040
+ tdTags.appendChild(more);
1041
+ }
1042
+ }
1043
+ tr.appendChild(tdTags);
1044
+
1045
+ tbody.appendChild(tr);
1046
+ });
1047
+ table.appendChild(tbody);
1048
+ var wrap = document.createElement('div');
1049
+ wrap.className = 'table-wrap';
1050
+ wrap.appendChild(table);
1051
+ return wrap;
1052
+ }
1053
+
1054
+ function showError(container, msg) {
1055
+ container.textContent = '';
1056
+ var box = document.createElement('div');
1057
+ box.className = 'result-box error';
1058
+ box.textContent = msg;
1059
+ container.appendChild(box);
1060
+ }
1061
+
1062
+ function showPlaceholder(container, text) {
1063
+ container.textContent = '';
1064
+ var ph = document.createElement('div');
1065
+ ph.className = 'placeholder';
1066
+ ph.textContent = text;
1067
+ container.appendChild(ph);
1068
+ }
1069
+
1070
+ function showSpinner(container) {
1071
+ container.textContent = '';
1072
+ var wrap = document.createElement('div');
1073
+ wrap.className = 'placeholder';
1074
+ var sp = document.createElement('div');
1075
+ sp.className = 'loading';
1076
+ wrap.appendChild(sp);
1077
+ container.appendChild(wrap);
1078
+ }
1079
+
1080
+ // ---- Search term highlighting (XSS-safe via createElement/textContent) ----
1081
+ function highlightText(container, text, term) {
1082
+ if (!term) { container.textContent = text; return; }
1083
+ var lower = text.toLowerCase();
1084
+ var lowerTerm = term.toLowerCase();
1085
+ var termLen = lowerTerm.length;
1086
+ if (termLen === 0) { container.textContent = text; return; }
1087
+ var pos = 0;
1088
+ while (pos < text.length) {
1089
+ var idx = lower.indexOf(lowerTerm, pos);
1090
+ if (idx === -1) {
1091
+ container.appendChild(document.createTextNode(text.slice(pos)));
1092
+ break;
1093
+ }
1094
+ if (idx > pos) {
1095
+ container.appendChild(document.createTextNode(text.slice(pos, idx)));
1096
+ }
1097
+ var mark = document.createElement('mark');
1098
+ mark.textContent = text.slice(idx, idx + termLen);
1099
+ container.appendChild(mark);
1100
+ pos = idx + termLen;
1101
+ }
1102
+ }
1103
+
1104
+ // ---- Search tab ----
1105
+ var searchInput = document.getElementById('search-query');
1106
+ var searchBtn = document.getElementById('search-btn');
1107
+ var searchResults = document.getElementById('search-results');
1108
+
1109
+ async function doSearch() {
1110
+ var q = searchInput.value.trim();
1111
+ if (!q) return;
1112
+ showSpinner(searchResults);
1113
+ try {
1114
+ var data = await apiCall('POST', '/v1/recall', { query: q, limit: 20 });
1115
+ searchResults.textContent = '';
1116
+ if (!data.success) { showError(searchResults, data.error || 'Unknown error'); return; }
1117
+ var entities = Array.isArray(data.data) ? data.data : (data.data.entities || []);
1118
+ if (entities.length === 0) { showPlaceholder(searchResults, 'No results for "' + q + '"'); return; }
1119
+ searchResults.appendChild(buildEntityTable(entities, q));
1120
+ } catch (err) {
1121
+ showError(searchResults, err.message);
1122
+ }
1123
+ }
1124
+
1125
+ searchBtn.addEventListener('click', doSearch);
1126
+ searchInput.addEventListener('keydown', function (e) { if (e.key === 'Enter') doSearch(); });
1127
+
1128
+ // ---- Browse tab ----
1129
+ var allEntities = [];
1130
+ var browseFilter = document.getElementById('browse-filter');
1131
+ var browseWrap = document.getElementById('browse-table-wrap');
1132
+
1133
+ async function loadBrowse() {
1134
+ showSpinner(browseWrap);
1135
+ try {
1136
+ var data = await apiCall('GET', '/v1/entities?limit=200');
1137
+ if (!data.success) throw new Error(data.error || 'Failed to load entities');
1138
+ allEntities = data.data || [];
1139
+ renderBrowseTable(browseFilter.value);
1140
+ } catch (err) {
1141
+ showError(browseWrap, err.message);
1142
+ }
1143
+ }
1144
+
1145
+ function renderBrowseTable(filter) {
1146
+ var f = (filter || '').toLowerCase();
1147
+ var rows = allEntities.filter(function (e) {
1148
+ return !f || e.name.toLowerCase().includes(f) || e.type.toLowerCase().includes(f);
1149
+ });
1150
+ browseWrap.textContent = '';
1151
+ if (rows.length === 0) { showPlaceholder(browseWrap, 'No entities found'); return; }
1152
+ browseWrap.appendChild(buildEntityTable(rows, filter || ''));
1153
+ }
1154
+
1155
+ browseFilter.addEventListener('input', function () { renderBrowseTable(this.value); });
1156
+ document.getElementById('browse-refresh').addEventListener('click', loadBrowse);
1157
+
1158
+ // ---- Graph tab ----
1159
+ var graphLoaded = false;
1160
+
1161
+ async function loadGraph() {
1162
+ if (graphLoaded) return;
1163
+ graphLoaded = true;
1164
+ var wrap = document.getElementById('graph-svg-wrap');
1165
+ showSpinner(wrap);
1166
+ try {
1167
+ var data = await apiCall('GET', '/v1/graph');
1168
+ if (!data.success) throw new Error(data.error || 'Failed to load graph');
1169
+ renderGraph(data.data.entities || [], data.data.relations || [], wrap);
1170
+ } catch (err) {
1171
+ showError(wrap, err.message);
1172
+ graphLoaded = false;
1173
+ }
1174
+ }
1175
+
1176
+ function renderGraph(entities, relations, container) {
1177
+ container.textContent = '';
1178
+
1179
+ if (entities.length === 0) {
1180
+ showPlaceholder(container, 'No entities yet. Start remembering to build your graph.');
1181
+ return;
1182
+ }
1183
+
1184
+ var svgNS = 'http://www.w3.org/2000/svg';
1185
+ var svg = document.createElementNS(svgNS, 'svg');
1186
+ svg.setAttribute('width', '100%');
1187
+ svg.setAttribute('height', '520');
1188
+ container.appendChild(svg);
1189
+
1190
+ var width = container.clientWidth || 900;
1191
+ var height = 520;
1192
+
1193
+ // Only show top connected nodes to keep graph readable
1194
+ var MAX_NODES = 60;
1195
+ var degreeMap = {};
1196
+ relations.forEach(function (r) {
1197
+ degreeMap[r.from] = (degreeMap[r.from] || 0) + 1;
1198
+ degreeMap[r.to] = (degreeMap[r.to] || 0) + 1;
1199
+ });
1200
+
1201
+ var topNames;
1202
+ if (Object.keys(degreeMap).length > 0) {
1203
+ topNames = new Set(
1204
+ Object.entries(degreeMap)
1205
+ .sort(function (a, b) { return b[1] - a[1]; })
1206
+ .slice(0, MAX_NODES)
1207
+ .map(function (e) { return e[0]; })
1208
+ );
1209
+ } else {
1210
+ topNames = new Set(entities.slice(0, MAX_NODES).map(function (e) { return e.name; }));
1211
+ }
1212
+
1213
+ var graphEntities = entities.filter(function (e) { return topNames.has(e.name); });
1214
+ if (graphEntities.length === 0) graphEntities = entities.slice(0, MAX_NODES);
1215
+
1216
+ var colorPalette = ['#3b82f6','#8b5cf6','#10b981','#f59e0b','#ef4444','#06b6d4','#ec4899','#84cc16','#f97316','#6366f1'];
1217
+ var typeColorMap = {};
1218
+ var colorIdx = 0;
1219
+ graphEntities.forEach(function (e) {
1220
+ if (!typeColorMap[e.type]) {
1221
+ typeColorMap[e.type] = colorPalette[colorIdx % colorPalette.length];
1222
+ colorIdx++;
1223
+ }
1224
+ });
1225
+
1226
+ // Build nodes and links
1227
+ var nodeMap = {};
1228
+ var nodes = graphEntities.map(function (e, i) {
1229
+ var firstObs = (e.observations && e.observations.length > 0) ? e.observations[0] : null;
1230
+ var n = { id: e.name, type: e.type, status: e.status, obs: e.observations ? e.observations.length : 0, firstObs: firstObs, x: 0, y: 0, vx: 0, vy: 0, fx: null, fy: null };
1231
+ nodeMap[e.name] = n;
1232
+ return n;
1233
+ });
1234
+
1235
+ var links = relations
1236
+ .filter(function (r) { return nodeMap[r.from] && nodeMap[r.to]; })
1237
+ .map(function (r) { return { source: r.from, target: r.to, type: r.type }; });
1238
+
1239
+ // Force simulation using pure JS (no D3 needed for basic layout)
1240
+ // Initialize positions in a circle
1241
+ nodes.forEach(function (n, i) {
1242
+ var angle = (2 * Math.PI * i) / nodes.length;
1243
+ var r = Math.min(width, height) * 0.35;
1244
+ n.x = width / 2 + r * Math.cos(angle);
1245
+ n.y = height / 2 + r * Math.sin(angle);
1246
+ });
1247
+
1248
+ // Create SVG elements using D3 (bundled)
1249
+ var d3svg = d3.select(svg);
1250
+ d3svg.attr('viewBox', [0, 0, width, height]);
1251
+
1252
+ // Defs: arrow marker + glow filter + grid pattern
1253
+ var defs = d3svg.append('defs');
1254
+
1255
+ // Arrow marker
1256
+ defs.append('marker')
1257
+ .attr('id', 'arrow')
1258
+ .attr('viewBox', '0 0 10 10').attr('refX', 20).attr('refY', 5)
1259
+ .attr('markerWidth', 6).attr('markerHeight', 6).attr('orient', 'auto')
1260
+ .append('path').attr('d', 'M 0 0 L 10 5 L 0 10 z').attr('fill', 'rgba(59,130,246,0.4)');
1261
+
1262
+ // Glow filter
1263
+ var filter = defs.append('filter').attr('id', 'node-glow').attr('x', '-50%').attr('y', '-50%').attr('width', '200%').attr('height', '200%');
1264
+ filter.append('feGaussianBlur').attr('stdDeviation', '3').attr('result', 'coloredBlur');
1265
+ var feMerge = filter.append('feMerge');
1266
+ feMerge.append('feMergeNode').attr('in', 'coloredBlur');
1267
+ feMerge.append('feMergeNode').attr('in', 'SourceGraphic');
1268
+
1269
+ // Grid pattern background
1270
+ var gridSize = 32;
1271
+ var gridPattern = defs.append('pattern')
1272
+ .attr('id', 'grid').attr('width', gridSize).attr('height', gridSize)
1273
+ .attr('patternUnits', 'userSpaceOnUse');
1274
+ gridPattern.append('path')
1275
+ .attr('d', 'M ' + gridSize + ' 0 L 0 0 0 ' + gridSize)
1276
+ .attr('fill', 'none').attr('stroke', 'rgba(39,39,42,0.4)').attr('stroke-width', '0.5');
1277
+
1278
+ // Background rect with grid
1279
+ d3svg.append('rect')
1280
+ .attr('width', width).attr('height', height)
1281
+ .attr('fill', 'url(#grid)');
1282
+
1283
+ var g = d3svg.append('g');
1284
+
1285
+ d3svg.call(d3.zoom().scaleExtent([0.2, 5]).on('zoom', function (event) {
1286
+ g.attr('transform', event.transform);
1287
+ }));
1288
+
1289
+ var linkSel = g.append('g')
1290
+ .selectAll('line').data(links).join('line')
1291
+ .attr('stroke', 'rgba(59,130,246,0.25)').attr('stroke-width', 1.5)
1292
+ .attr('marker-end', 'url(#arrow)');
1293
+
1294
+ var linkLabel = g.append('g')
1295
+ .selectAll('text').data(links).join('text')
1296
+ .attr('font-size', 9).attr('fill', 'rgba(113,113,122,0.8)').attr('text-anchor', 'middle')
1297
+ .attr('font-family', 'JetBrains Mono, ui-monospace, monospace')
1298
+ .text(function (d) { return d.type; });
1299
+
1300
+ var nodeSel = g.append('g')
1301
+ .selectAll('circle').data(nodes).join('circle')
1302
+ .attr('r', function (d) { return Math.max(6, Math.min(20, 6 + d.obs * 1.5)); })
1303
+ .attr('fill', function (d) { return typeColorMap[d.type] || '#3b82f6'; })
1304
+ .attr('stroke', 'rgba(9,9,11,0.8)').attr('stroke-width', 1.5)
1305
+ .attr('opacity', function (d) { return d.status === 'archived' ? 0.3 : 0.9; })
1306
+ .attr('filter', function (d) { return d.status === 'archived' ? null : 'url(#node-glow)'; })
1307
+ .style('cursor', 'pointer')
1308
+ .call(d3.drag()
1309
+ .on('start', function (event, d) { if (!event.active) sim.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; })
1310
+ .on('drag', function (event, d) { d.fx = event.x; d.fy = event.y; })
1311
+ .on('end', function (event, d) { if (!event.active) sim.alphaTarget(0); d.fx = null; d.fy = null; }));
1312
+
1313
+ // Hover pulse effect
1314
+ nodeSel.on('mouseenter', function () {
1315
+ d3.select(this).attr('stroke', '#3b82f6').attr('stroke-width', 2.5);
1316
+ }).on('mouseleave', function () {
1317
+ d3.select(this).attr('stroke', 'rgba(9,9,11,0.8)').attr('stroke-width', 1.5);
1318
+ });
1319
+
1320
+ var labelColor = document.body.classList.contains('light') ? '#09090b' : '#fafafa';
1321
+ var labelSel = g.append('g')
1322
+ .selectAll('text').data(nodes).join('text')
1323
+ .attr('font-size', 11).attr('fill', labelColor).attr('dy', 4)
1324
+ .attr('font-family', 'Inter, system-ui, sans-serif').attr('font-weight', '500')
1325
+ .text(function (d) {
1326
+ var label = d.firstObs ? d.firstObs : d.id;
1327
+ return label.length > 25 ? label.slice(0, 25) + '\u2026' : label;
1328
+ });
1329
+
1330
+ // Tooltip
1331
+ var ttEl = document.getElementById('live-tooltip');
1332
+ nodeSel.on('mouseover', function (event, d) {
1333
+ ttEl.style.display = 'block';
1334
+ var obsPreview = d.firstObs ? (d.firstObs.length > 80 ? d.firstObs.slice(0, 80) + '\u2026' : d.firstObs) : '(no observations)';
1335
+ ttEl.querySelector('.tt-name').textContent = obsPreview;
1336
+ ttEl.querySelector('.tt-type').textContent = d.type + (d.status === 'archived' ? ' \u2014 archived' : '');
1337
+ ttEl.querySelector('.tt-obs').textContent = d.id + ' \u00b7 ' + d.obs + ' observation' + (d.obs !== 1 ? 's' : '');
1338
+ }).on('mousemove', function (event) {
1339
+ ttEl.style.left = (event.pageX + 14) + 'px';
1340
+ ttEl.style.top = (event.pageY - 10) + 'px';
1341
+ }).on('mouseout', function () { ttEl.style.display = 'none'; });
1342
+
1343
+ var sim = d3.forceSimulation(nodes)
1344
+ .force('link', d3.forceLink(links).id(function (d) { return d.id; }).distance(150))
1345
+ .force('charge', d3.forceManyBody().strength(-400))
1346
+ .force('center', d3.forceCenter(width / 2, height / 2))
1347
+ .force('collision', d3.forceCollide().radius(22));
1348
+
1349
+ sim.on('tick', function () {
1350
+ linkSel
1351
+ .attr('x1', function (d) { return d.source.x; }).attr('y1', function (d) { return d.source.y; })
1352
+ .attr('x2', function (d) { return d.target.x; }).attr('y2', function (d) { return d.target.y; });
1353
+ linkLabel
1354
+ .attr('x', function (d) { return (d.source.x + d.target.x) / 2; })
1355
+ .attr('y', function (d) { return (d.source.y + d.target.y) / 2; });
1356
+ nodeSel.attr('cx', function (d) { return d.x; }).attr('cy', function (d) { return d.y; });
1357
+ labelSel.attr('x', function (d) { return d.x + 10; }).attr('y', function (d) { return d.y; });
1358
+ });
1359
+
1360
+ // Legend
1361
+ var legend = document.createElement('div');
1362
+ legend.style.cssText = 'display:flex;flex-wrap:wrap;gap:10px;margin-top:12px;font-size:12px;padding:0 2px;font-family:Inter,system-ui,sans-serif;';
1363
+ Object.entries(typeColorMap).forEach(function (pair) {
1364
+ var item = document.createElement('span');
1365
+ item.style.cssText = 'display:flex;align-items:center;gap:5px;color:var(--text-secondary,#a1a1aa);';
1366
+ var dot = document.createElement('span');
1367
+ dot.style.cssText = 'width:8px;height:8px;border-radius:50%;display:inline-block;background:' + pair[1] + ';box-shadow:0 0 4px ' + pair[1] + '66;';
1368
+ var lbl = document.createElement('span');
1369
+ lbl.textContent = pair[0];
1370
+ item.appendChild(dot);
1371
+ item.appendChild(lbl);
1372
+ legend.appendChild(item);
1373
+ });
1374
+ container.appendChild(legend);
1375
+ }
1376
+
1377
+ // ---- Analytics tab ----
1378
+ var analyticsLoaded = false;
1379
+
1380
+ async function loadAnalytics() {
1381
+ if (analyticsLoaded) return;
1382
+ analyticsLoaded = true;
1383
+ var container = document.getElementById('analytics-body');
1384
+ showSpinner(container);
1385
+ try {
1386
+ var statsRes = await apiCall('GET', '/v1/stats');
1387
+ if (!statsRes.success) throw new Error(statsRes.error || 'Failed to load stats');
1388
+ // Also fetch entities for actionable insight calculations
1389
+ var entitiesRes = await apiCall('GET', '/v1/entities?limit=500&status=all');
1390
+ var allEntitiesForAnalytics = (entitiesRes.success && entitiesRes.data) ? entitiesRes.data : [];
1391
+ renderAnalytics(statsRes.data, allEntitiesForAnalytics, container);
1392
+ } catch (err) {
1393
+ showError(container, err.message);
1394
+ analyticsLoaded = false;
1395
+ }
1396
+ }
1397
+
1398
+ function renderAnalytics(stats, entities, container) {
1399
+ container.textContent = '';
1400
+
1401
+ // Stats grid
1402
+ var grid = document.createElement('div');
1403
+ grid.className = 'stats-grid';
1404
+ [
1405
+ { label: 'Total Memories', value: stats.totalEntities },
1406
+ { label: 'Knowledge Facts', value: stats.totalObservations },
1407
+ { label: 'Connections', value: stats.totalRelations },
1408
+ { label: 'Topics', value: stats.totalTags },
1409
+ ].forEach(function (c) {
1410
+ var card = document.createElement('div');
1411
+ card.className = 'stat-card';
1412
+ var val = document.createElement('div');
1413
+ val.className = 'stat-value';
1414
+ val.textContent = String(c.value);
1415
+ var lbl = document.createElement('div');
1416
+ lbl.className = 'stat-label';
1417
+ lbl.textContent = c.label;
1418
+ card.appendChild(val);
1419
+ card.appendChild(lbl);
1420
+ grid.appendChild(card);
1421
+ });
1422
+ container.appendChild(grid);
1423
+
1424
+ // Status distribution
1425
+ if (stats.statusDistribution && stats.statusDistribution.length > 0) {
1426
+ var statusTitle = document.createElement('h3');
1427
+ statusTitle.style.cssText = 'font-size:11px;font-weight:600;margin-bottom:10px;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.05em;';
1428
+ statusTitle.textContent = 'Status Distribution';
1429
+ container.appendChild(statusTitle);
1430
+ var statusGrid = document.createElement('div');
1431
+ statusGrid.className = 'stats-grid';
1432
+ stats.statusDistribution.forEach(function (s) {
1433
+ var card = document.createElement('div');
1434
+ card.className = 'stat-card';
1435
+ var val = document.createElement('div');
1436
+ val.className = 'stat-value';
1437
+ val.textContent = String(s.count);
1438
+ var lbl = document.createElement('div');
1439
+ lbl.className = 'stat-label';
1440
+ lbl.textContent = s.status || 'active';
1441
+ card.appendChild(val);
1442
+ card.appendChild(lbl);
1443
+ statusGrid.appendChild(card);
1444
+ });
1445
+ container.appendChild(statusGrid);
1446
+ }
1447
+
1448
+ // Actionable insights section
1449
+ if (entities && entities.length > 0) {
1450
+ var insightsTitle = document.createElement('h3');
1451
+ insightsTitle.style.cssText = 'font-size:11px;font-weight:600;margin:16px 0 10px;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.05em;';
1452
+ insightsTitle.textContent = 'Recent Activity';
1453
+ container.appendChild(insightsTitle);
1454
+
1455
+ var now = Date.now();
1456
+ var sevenDays = 7 * 24 * 60 * 60 * 1000;
1457
+ var thirtyDays = 30 * 24 * 60 * 60 * 1000;
1458
+
1459
+ // Count this week
1460
+ var thisWeek = entities.filter(function (e) {
1461
+ try { return (now - new Date(e.created_at).getTime()) < sevenDays; } catch (_) { return false; }
1462
+ }).length;
1463
+
1464
+ // Stale: not accessed in 30+ days (or never accessed)
1465
+ var stale = entities.filter(function (e) {
1466
+ if (!e.last_accessed_at) return true;
1467
+ try { return (now - new Date(e.last_accessed_at).getTime()) > thirtyDays; } catch (_) { return true; }
1468
+ }).length;
1469
+
1470
+ // Archived count
1471
+ var archived = entities.filter(function (e) {
1472
+ return e.status === 'archived' || e.archived === true;
1473
+ }).length;
1474
+
1475
+ // Most recalled (top 1)
1476
+ var topRecalled = entities
1477
+ .filter(function (e) { return e.access_count && e.access_count > 0; })
1478
+ .sort(function (a, b) { return (b.access_count || 0) - (a.access_count || 0); })
1479
+ .slice(0, 1);
1480
+
1481
+ var insightCards = [
1482
+ { icon: '\ud83d\udcdd', label: 'This Week', value: thisWeek + ' new memories' },
1483
+ { icon: '\ud83d\udca4', label: 'Stale Memories', value: stale + ' not accessed in 30+ days' },
1484
+ { icon: '\ud83d\udce6', label: 'Archived', value: archived + ' memories' },
1485
+ ];
1486
+ if (topRecalled.length > 0) {
1487
+ var tr = topRecalled[0];
1488
+ var trPreview = (tr.observations && tr.observations[0])
1489
+ ? (tr.observations[0].length > 40 ? tr.observations[0].slice(0, 40) + '\u2026' : tr.observations[0])
1490
+ : tr.name;
1491
+ insightCards.unshift({ icon: '\ud83d\udd25', label: 'Most Recalled', value: '\u201c' + trPreview + '\u201d (' + tr.access_count + 'x)' });
1492
+ }
1493
+
1494
+ var insightGrid = document.createElement('div');
1495
+ insightGrid.style.cssText = 'display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px;margin-bottom:20px;';
1496
+ insightCards.forEach(function (ic) {
1497
+ var card = document.createElement('div');
1498
+ card.style.cssText = 'background:var(--bg-secondary);border:1px solid var(--border);border-radius:var(--radius-sm);padding:14px 16px;font-size:13px;';
1499
+ var iconRow = document.createElement('div');
1500
+ iconRow.style.cssText = 'font-size:18px;margin-bottom:6px;';
1501
+ iconRow.textContent = ic.icon;
1502
+ var labelEl = document.createElement('div');
1503
+ labelEl.style.cssText = 'font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.04em;margin-bottom:2px;';
1504
+ labelEl.textContent = ic.label;
1505
+ var valueEl = document.createElement('div');
1506
+ valueEl.style.cssText = 'color:var(--text-primary);font-weight:500;font-size:13px;';
1507
+ valueEl.textContent = ic.value;
1508
+ card.appendChild(iconRow);
1509
+ card.appendChild(labelEl);
1510
+ card.appendChild(valueEl);
1511
+ insightGrid.appendChild(card);
1512
+ });
1513
+ container.appendChild(insightGrid);
1514
+ }
1515
+
1516
+ // Type distribution bar chart
1517
+ if (stats.typeDistribution && stats.typeDistribution.length > 0) {
1518
+ var typeTitle = document.createElement('h3');
1519
+ typeTitle.style.cssText = 'font-size:11px;font-weight:600;margin:16px 0 10px;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.05em;';
1520
+ typeTitle.textContent = 'Memory Types';
1521
+ container.appendChild(typeTitle);
1522
+
1523
+ var maxCount = stats.typeDistribution[0].count || 1;
1524
+ var barChart = document.createElement('div');
1525
+ barChart.className = 'bar-chart';
1526
+ stats.typeDistribution.forEach(function (t) {
1527
+ var row = document.createElement('div');
1528
+ row.className = 'bar-row';
1529
+ var lbl = document.createElement('div');
1530
+ lbl.className = 'bar-label';
1531
+ lbl.textContent = t.type;
1532
+ lbl.title = t.type;
1533
+ var track = document.createElement('div');
1534
+ track.className = 'bar-track';
1535
+ var fill = document.createElement('div');
1536
+ fill.className = 'bar-fill';
1537
+ fill.style.width = Math.round((t.count / maxCount) * 100) + '%';
1538
+ track.appendChild(fill);
1539
+ var cnt = document.createElement('div');
1540
+ cnt.className = 'bar-count';
1541
+ cnt.textContent = String(t.count);
1542
+ row.appendChild(lbl);
1543
+ row.appendChild(track);
1544
+ row.appendChild(cnt);
1545
+ barChart.appendChild(row);
1546
+ });
1547
+ container.appendChild(barChart);
1548
+ }
1549
+
1550
+ // Tag cloud
1551
+ if (stats.tagDistribution && stats.tagDistribution.length > 0) {
1552
+ var tagTitle = document.createElement('h3');
1553
+ tagTitle.style.cssText = 'font-size:11px;font-weight:600;margin:16px 0 10px;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.05em;';
1554
+ tagTitle.textContent = 'Topics';
1555
+ container.appendChild(tagTitle);
1556
+
1557
+ var maxTagCount = stats.tagDistribution[0].count || 1;
1558
+ var tagCloud = document.createElement('div');
1559
+ tagCloud.className = 'tag-cloud';
1560
+ stats.tagDistribution.forEach(function (t) {
1561
+ var pill = document.createElement('span');
1562
+ pill.className = 'tag-pill';
1563
+ var scale = 0.8 + (t.count / maxTagCount) * 0.9;
1564
+ pill.style.fontSize = Math.round(scale * 13) + 'px';
1565
+ pill.title = t.count + ' entities';
1566
+ pill.textContent = t.tag;
1567
+ tagCloud.appendChild(pill);
1568
+ });
1569
+ container.appendChild(tagCloud);
1570
+ }
1571
+
1572
+ if (!stats.typeDistribution || stats.typeDistribution.length === 0) {
1573
+ showPlaceholder(container, 'No data yet. Start adding entities.');
1574
+ }
1575
+ }
1576
+
1577
+ // ---- Timeline tab ----
1578
+ var timelineLoaded = false;
1579
+
1580
+ async function loadTimeline() {
1581
+ if (timelineLoaded) return;
1582
+ timelineLoaded = true;
1583
+ var container = document.getElementById('timeline-body');
1584
+ showSpinner(container);
1585
+ try {
1586
+ var data = await apiCall('GET', '/v1/graph');
1587
+ if (!data.success) throw new Error(data.error || 'Failed to load graph');
1588
+ renderTimeline(data.data.entities || [], data.data.relations || [], container);
1589
+ } catch (err) {
1590
+ showError(container, err.message);
1591
+ timelineLoaded = false;
1592
+ }
1593
+ }
1594
+
1595
+ function renderTimeline(entities, relations, container) {
1596
+ container.textContent = '';
1597
+
1598
+ // Build entity map
1599
+ var entityMap = {};
1600
+ entities.forEach(function (e) { entityMap[e.name] = e; });
1601
+
1602
+ // Find supersedes relations
1603
+ var supersedes = relations.filter(function (r) { return r.type === 'supersedes'; });
1604
+
1605
+ if (supersedes.length === 0) {
1606
+ showPlaceholder(container, 'No evolution chains yet. Use "supersedes" relations to track knowledge evolution.');
1607
+ return;
1608
+ }
1609
+
1610
+ // Build chains: find roots (nodes that are not a "to" in any supersedes)
1611
+ var hasIncoming = new Set(supersedes.map(function (r) { return r.to; }));
1612
+ var roots = [...new Set(supersedes.map(function (r) { return r.from; }))].filter(function (name) {
1613
+ return !hasIncoming.has(name);
1614
+ });
1615
+
1616
+ // If no pure roots, just use all froms
1617
+ if (roots.length === 0) {
1618
+ roots = [...new Set(supersedes.map(function (r) { return r.from; }))];
1619
+ }
1620
+
1621
+ // Build adjacency: from -> [to, ...]
1622
+ var nextMap = {};
1623
+ supersedes.forEach(function (r) {
1624
+ if (!nextMap[r.from]) nextMap[r.from] = [];
1625
+ nextMap[r.from].push(r.to);
1626
+ });
1627
+
1628
+ // Walk each chain
1629
+ var visited = new Set();
1630
+ var chainCount = 0;
1631
+
1632
+ roots.forEach(function (root) {
1633
+ if (visited.has(root)) return;
1634
+ var chain = [];
1635
+ var cursor = root;
1636
+ var safety = 0;
1637
+ while (cursor && !visited.has(cursor) && safety < 50) {
1638
+ visited.add(cursor);
1639
+ chain.push(cursor);
1640
+ var nexts = nextMap[cursor];
1641
+ cursor = nexts && nexts[0];
1642
+ safety++;
1643
+ }
1644
+ if (chain.length < 2) return;
1645
+ chainCount++;
1646
+
1647
+ var chainEl = document.createElement('div');
1648
+ chainEl.className = 'chain';
1649
+
1650
+ chain.forEach(function (name, idx) {
1651
+ if (idx > 0) {
1652
+ var arrow = document.createElement('span');
1653
+ arrow.className = 'chain-arrow';
1654
+ arrow.textContent = '\\u2192';
1655
+ chainEl.appendChild(arrow);
1656
+ }
1657
+ var node = document.createElement('div');
1658
+ var ent = entityMap[name];
1659
+ node.className = 'chain-node' + (ent && ent.status === 'archived' ? ' archived' : '');
1660
+ var nameEl = document.createElement('div');
1661
+ nameEl.className = 'cn-name';
1662
+ // Show first observation as primary content, fall back to entity name
1663
+ var obsContent = (ent && ent.observations && ent.observations[0])
1664
+ ? ent.observations[0]
1665
+ : name;
1666
+ nameEl.textContent = obsContent.length > 60 ? obsContent.slice(0, 60) + '\u2026' : obsContent;
1667
+ nameEl.title = obsContent; // full text on hover
1668
+ var typeEl = document.createElement('div');
1669
+ typeEl.className = 'cn-type';
1670
+ typeEl.textContent = (ent ? ent.type : '') + (ent ? ' \u00b7 ' : '');
1671
+ // Add timestamp
1672
+ if (ent && ent.created_at) {
1673
+ try {
1674
+ var tDate = new Date(ent.created_at);
1675
+ var timeSpan = document.createElement('span');
1676
+ timeSpan.style.cssText = 'font-size:11px;color:var(--text-muted);font-family:var(--font-mono);';
1677
+ timeSpan.textContent = tDate.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' });
1678
+ typeEl.textContent = (ent ? ent.type + ' \u00b7 ' : '');
1679
+ typeEl.appendChild(timeSpan);
1680
+ } catch (_) {}
1681
+ }
1682
+ // Add entity name as secondary metadata
1683
+ var entityNameEl = document.createElement('div');
1684
+ entityNameEl.style.cssText = 'font-size:10px;color:var(--text-muted);font-family:var(--font-mono);opacity:0.7;margin-top:2px;';
1685
+ entityNameEl.textContent = name;
1686
+ node.appendChild(nameEl);
1687
+ node.appendChild(typeEl);
1688
+ node.appendChild(entityNameEl);
1689
+ chainEl.appendChild(node);
1690
+ });
1691
+
1692
+ container.appendChild(chainEl);
1693
+ });
1694
+
1695
+ if (chainCount === 0) {
1696
+ showPlaceholder(container, 'No multi-step evolution chains found.');
1697
+ }
1698
+ }
1699
+
1700
+ // ---- Manage tab ----
1701
+ var allManageEntities = [];
1702
+ var manageFilter = '';
1703
+
1704
+ async function loadManage() {
1705
+ var tableWrap = document.getElementById('manage-table-wrap');
1706
+ if (!tableWrap) return;
1707
+ showSpinner(tableWrap);
1708
+ try {
1709
+ var data = await apiCall('GET', '/v1/entities?limit=500&status=all');
1710
+ if (!data.success) throw new Error(data.error || 'Failed to load');
1711
+ allManageEntities = data.data || [];
1712
+ renderManageTable();
1713
+ } catch (err) {
1714
+ showError(tableWrap, err.message);
1715
+ }
1716
+ }
1717
+
1718
+ function renderManageTable() {
1719
+ var filterInput = document.getElementById('manage-filter');
1720
+ var f = (filterInput ? filterInput.value : manageFilter).toLowerCase();
1721
+ var rows = allManageEntities.filter(function (e) {
1722
+ return !f || e.name.toLowerCase().includes(f) || e.type.toLowerCase().includes(f);
1723
+ });
1724
+
1725
+ var tableWrap = document.getElementById('manage-table-wrap');
1726
+ if (!tableWrap) return;
1727
+ tableWrap.textContent = '';
1728
+
1729
+ if (rows.length === 0) {
1730
+ showPlaceholder(tableWrap, 'No entities found');
1731
+ return;
1732
+ }
1733
+
1734
+ var table = document.createElement('table');
1735
+ var thead = document.createElement('thead');
1736
+ var hrow = document.createElement('tr');
1737
+ [['Time', '140px'], ['Memory', '40%'], ['Type', ''], ['Status', ''], ['Tags', ''], ['Actions', '']].forEach(function (hDef) {
1738
+ var th = document.createElement('th');
1739
+ th.textContent = hDef[0];
1740
+ if (hDef[1]) th.style.width = hDef[1];
1741
+ hrow.appendChild(th);
1742
+ });
1743
+ thead.appendChild(hrow);
1744
+ table.appendChild(thead);
1745
+
1746
+ var tbody = document.createElement('tbody');
1747
+ rows.forEach(function (e) {
1748
+ var status = e.status || 'active';
1749
+ var tr = document.createElement('tr');
1750
+ if (status === 'archived') tr.style.opacity = '0.6';
1751
+
1752
+ // Time column
1753
+ var tdTime = document.createElement('td');
1754
+ tdTime.style.cssText = 'font-family:var(--font-mono);font-size:11px;color:var(--text-muted);white-space:nowrap;';
1755
+ try {
1756
+ var d = new Date(e.created_at);
1757
+ tdTime.textContent = d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' }) + ' ' + d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
1758
+ } catch (_) {
1759
+ tdTime.textContent = e.created_at || '\u2014';
1760
+ }
1761
+ tdTime.title = e.created_at || '';
1762
+ tr.appendChild(tdTime);
1763
+
1764
+ // Memory column — first observation as primary, entity name as metadata
1765
+ var tdMemory = document.createElement('td');
1766
+ var memContent = document.createElement('div');
1767
+ var preview = document.createElement('div');
1768
+ preview.style.cssText = 'font-size:13px;line-height:1.5;margin-bottom:2px;';
1769
+ var firstObs = (e.observations && e.observations.length > 0) ? e.observations[0] : '(no observations)';
1770
+ preview.textContent = firstObs.length > 100 ? firstObs.slice(0, 100) + '\u2026' : firstObs;
1771
+ memContent.appendChild(preview);
1772
+ var meta = document.createElement('div');
1773
+ meta.style.cssText = 'font-size:11px;color:var(--text-muted);font-family:var(--font-mono);';
1774
+ var obsCount = e.observations ? e.observations.length : 0;
1775
+ meta.textContent = e.name + (obsCount > 1 ? ' \u00b7 ' + obsCount + ' observations' : '');
1776
+ memContent.appendChild(meta);
1777
+ tdMemory.appendChild(memContent);
1778
+ tr.appendChild(tdMemory);
1779
+
1780
+ var tdType = document.createElement('td');
1781
+ var typeBadge = document.createElement('span');
1782
+ typeBadge.className = 'badge badge-type';
1783
+ typeBadge.textContent = e.type;
1784
+ tdType.appendChild(typeBadge);
1785
+ tr.appendChild(tdType);
1786
+
1787
+ var tdStatus = document.createElement('td');
1788
+ var sb = document.createElement('span');
1789
+ sb.className = 'badge badge-' + (status === 'archived' ? 'archived' : 'active');
1790
+ sb.textContent = status;
1791
+ tdStatus.appendChild(sb);
1792
+ tr.appendChild(tdStatus);
1793
+
1794
+ var tdTags = document.createElement('td');
1795
+ if (e.tags && e.tags.length > 0) {
1796
+ e.tags.slice(0, 3).forEach(function (t) {
1797
+ var pill = document.createElement('span');
1798
+ pill.className = 'tag-pill';
1799
+ pill.textContent = t;
1800
+ tdTags.appendChild(pill);
1801
+ });
1802
+ if (e.tags.length > 3) {
1803
+ var moreTag = document.createElement('span');
1804
+ moreTag.className = 'tag-pill';
1805
+ moreTag.style.opacity = '0.6';
1806
+ moreTag.textContent = '+' + (e.tags.length - 3);
1807
+ tdTags.appendChild(moreTag);
1808
+ }
1809
+ }
1810
+ tr.appendChild(tdTags);
1811
+
1812
+ var tdActions = document.createElement('td');
1813
+ var actCell = document.createElement('div');
1814
+ actCell.className = 'manage-action-cell';
1815
+
1816
+ if (status === 'archived') {
1817
+ var restoreBtn = document.createElement('button');
1818
+ restoreBtn.className = 'btn btn-sm btn-secondary';
1819
+ restoreBtn.textContent = 'Restore';
1820
+ restoreBtn.addEventListener('click', function () {
1821
+ restoreBtn.disabled = true;
1822
+ restoreBtn.textContent = '...';
1823
+ apiCall('POST', '/v1/remember', { name: e.name, type: e.type, observations: [], tags: [] })
1824
+ .then(function () { loadManage(); })
1825
+ .catch(function (err) {
1826
+ restoreBtn.disabled = false;
1827
+ restoreBtn.textContent = 'Restore';
1828
+ var errEl = document.createElement('div');
1829
+ errEl.style.cssText = 'color:var(--danger);padding:8px 12px;background:rgba(239,68,68,0.08);border:1px solid rgba(239,68,68,0.2);border-radius:var(--radius-xs);margin-top:8px;font-size:13px;';
1830
+ errEl.textContent = 'Error: ' + err.message;
1831
+ actCell.appendChild(errEl);
1832
+ setTimeout(function() { errEl.remove(); }, 5000);
1833
+ });
1834
+ });
1835
+ actCell.appendChild(restoreBtn);
1836
+ } else {
1837
+ var archiveBtn = document.createElement('button');
1838
+ archiveBtn.className = 'btn btn-sm btn-danger';
1839
+ archiveBtn.textContent = 'Archive';
1840
+ archiveBtn.addEventListener('click', function () {
1841
+ if (!confirm('Archive entity "' + e.name + '"? It will be hidden but not deleted.')) return;
1842
+ archiveBtn.disabled = true;
1843
+ archiveBtn.textContent = '...';
1844
+ apiCall('POST', '/v1/forget', { name: e.name })
1845
+ .then(function () { loadManage(); })
1846
+ .catch(function (err) {
1847
+ archiveBtn.disabled = false;
1848
+ archiveBtn.textContent = 'Archive';
1849
+ var errEl = document.createElement('div');
1850
+ errEl.style.cssText = 'color:var(--danger);padding:8px 12px;background:rgba(239,68,68,0.08);border:1px solid rgba(239,68,68,0.2);border-radius:var(--radius-xs);margin-top:8px;font-size:13px;';
1851
+ errEl.textContent = 'Error: ' + err.message;
1852
+ actCell.appendChild(errEl);
1853
+ setTimeout(function() { errEl.remove(); }, 5000);
1854
+ });
1855
+ });
1856
+ actCell.appendChild(archiveBtn);
1857
+ }
1858
+
1859
+ // Remove observation button (only if entity has observations)
1860
+ if (e.observations && e.observations.length > 0) {
1861
+ var rmObsBtn = document.createElement('button');
1862
+ rmObsBtn.className = 'btn btn-sm btn-secondary';
1863
+ rmObsBtn.textContent = 'Remove obs';
1864
+ rmObsBtn.addEventListener('click', function () {
1865
+ var modal = document.createElement('div');
1866
+ modal.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.7);display:flex;align-items:center;justify-content:center;z-index:1000;backdrop-filter:blur(4px);';
1867
+ var box = document.createElement('div');
1868
+ box.className = 'card';
1869
+ box.style.cssText = 'max-width:500px;width:90%;max-height:80vh;overflow-y:auto;';
1870
+ var title = document.createElement('h3');
1871
+ title.textContent = 'Remove Observation';
1872
+ title.style.cssText = 'margin-bottom:12px;font-size:14px;font-weight:600;color:var(--text-primary);';
1873
+ box.appendChild(title);
1874
+ e.observations.forEach(function(obsText) {
1875
+ var label = document.createElement('label');
1876
+ label.style.cssText = 'display:block;padding:8px 10px;margin:4px 0;border:1px solid var(--border);border-radius:var(--radius-xs);cursor:pointer;font-size:13px;color:var(--text-secondary);transition:border-color 0.15s;';
1877
+ var radio = document.createElement('input');
1878
+ radio.type = 'radio';
1879
+ radio.name = 'obs-select-' + e.name;
1880
+ radio.value = obsText;
1881
+ radio.style.marginRight = '8px';
1882
+ radio.style.accentColor = 'var(--accent)';
1883
+ label.appendChild(radio);
1884
+ label.appendChild(document.createTextNode(obsText.length > 120 ? obsText.slice(0, 120) + '...' : obsText));
1885
+ box.appendChild(label);
1886
+ });
1887
+ var modalErrEl = document.createElement('div');
1888
+ modalErrEl.style.cssText = 'color:var(--danger);font-size:13px;min-height:18px;margin-top:8px;';
1889
+ box.appendChild(modalErrEl);
1890
+ var btnRow = document.createElement('div');
1891
+ btnRow.style.cssText = 'display:flex;gap:8px;margin-top:12px;justify-content:flex-end;';
1892
+ var cancelBtn = document.createElement('button');
1893
+ cancelBtn.className = 'btn btn-secondary';
1894
+ cancelBtn.textContent = 'Cancel';
1895
+ cancelBtn.addEventListener('click', function() { modal.remove(); });
1896
+ btnRow.appendChild(cancelBtn);
1897
+ var removeBtn = document.createElement('button');
1898
+ removeBtn.className = 'btn btn-danger';
1899
+ removeBtn.textContent = 'Remove Selected';
1900
+ removeBtn.addEventListener('click', function() {
1901
+ var selected = box.querySelector('input[name="obs-select-' + e.name + '"]:checked');
1902
+ if (!selected) { modalErrEl.textContent = 'Select an observation first.'; return; }
1903
+ removeBtn.disabled = true;
1904
+ removeBtn.textContent = '...';
1905
+ apiCall('POST', '/v1/forget', { name: e.name, observation: selected.value })
1906
+ .then(function() { modal.remove(); loadManage(); })
1907
+ .catch(function(err) {
1908
+ removeBtn.disabled = false;
1909
+ removeBtn.textContent = 'Remove Selected';
1910
+ modalErrEl.textContent = 'Error: ' + err.message;
1911
+ });
1912
+ });
1913
+ btnRow.appendChild(removeBtn);
1914
+ box.appendChild(btnRow);
1915
+ modal.appendChild(box);
1916
+ modal.addEventListener('click', function(ev) { if (ev.target === modal) modal.remove(); });
1917
+ document.body.appendChild(modal);
1918
+ });
1919
+ actCell.appendChild(rmObsBtn);
1920
+ }
1921
+
1922
+ tdActions.appendChild(actCell);
1923
+ tr.appendChild(tdActions);
1924
+ tbody.appendChild(tr);
1925
+ });
1926
+
1927
+ table.appendChild(tbody);
1928
+ var manageTableOuter = document.createElement('div');
1929
+ manageTableOuter.className = 'table-wrap';
1930
+ manageTableOuter.appendChild(table);
1931
+ tableWrap.appendChild(manageTableOuter);
1932
+ }
1933
+
1934
+ document.getElementById('manage-filter').addEventListener('input', function () { renderManageTable(); });
1935
+ document.getElementById('manage-refresh').addEventListener('click', loadManage);
1936
+
1937
+ // ---- Feedback widget ----
1938
+ (function initFeedback() {
1939
+ var btn = document.getElementById('feedback-btn');
1940
+ var panel = document.getElementById('feedback-panel');
1941
+ if (!btn || !panel) return;
1942
+
1943
+ var fbType = 'bug';
1944
+
1945
+ btn.addEventListener('click', function () {
1946
+ panel.classList.toggle('open');
1947
+ });
1948
+
1949
+ // Radio group selection
1950
+ panel.querySelectorAll('.fb-radio input').forEach(function (radio) {
1951
+ radio.addEventListener('change', function () {
1952
+ panel.querySelectorAll('.fb-radio').forEach(function (el) { el.classList.remove('selected'); });
1953
+ radio.parentElement.classList.add('selected');
1954
+ fbType = radio.value;
1955
+ });
1956
+ });
1957
+
1958
+ var submitBtn = document.getElementById('fb-submit');
1959
+ if (submitBtn) {
1960
+ submitBtn.addEventListener('click', function () {
1961
+ var desc = document.getElementById('fb-desc').value.trim();
1962
+ if (!desc) { document.getElementById('fb-desc').focus(); return; }
1963
+ var includeSys = document.getElementById('fb-sys').checked;
1964
+ var labels = 'feedback,from-dashboard,' + fbType;
1965
+ var title = encodeURIComponent('[' + fbType + '] ' + desc.slice(0, 50));
1966
+ var bodyText = '## Description\\n' + desc;
1967
+ if (includeSys) {
1968
+ bodyText += '\\n\\n## System Info\\nVersion: ' + _currentVersion + '\\nSearch Level: ' + _currentSearchLevel;
1969
+ }
1970
+ var body = encodeURIComponent(bodyText);
1971
+ window.open('https://github.com/PCIRCLE-AI/memesh-llm-memory/issues/new?title=' + title + '&body=' + body + '&labels=' + labels, '_blank');
1972
+ panel.classList.remove('open');
1973
+ document.getElementById('fb-desc').value = '';
1974
+ });
1975
+ }
1976
+
1977
+ // Close panel on outside click
1978
+ document.addEventListener('click', function (e) {
1979
+ if (!panel.contains(e.target) && e.target !== btn) {
1980
+ panel.classList.remove('open');
1981
+ }
1982
+ });
1983
+ })();
1984
+
1985
+ // ---- Settings tab ----
1986
+ var settingsLoaded = false;
1987
+
1988
+ async function loadSettings() {
1989
+ if (settingsLoaded) return;
1990
+ settingsLoaded = false; // allow re-render on each visit to reflect saved state
1991
+ var body = document.getElementById('settings-body');
1992
+ body.textContent = '';
1993
+
1994
+ var configRes;
1995
+ try {
1996
+ configRes = await apiCall('GET', '/v1/config');
1997
+ } catch (err) {
1998
+ showError(body, 'Failed to load config: ' + err.message);
1999
+ return;
2000
+ }
2001
+
2002
+ var currentConfig = (configRes.success && configRes.data && configRes.data.config) || {};
2003
+ var caps = (configRes.success && configRes.data && configRes.data.capabilities) || {};
2004
+
2005
+ // --- Capabilities section ---
2006
+ var capSection = document.createElement('div');
2007
+ capSection.className = 'settings-section';
2008
+ var capH3 = document.createElement('h3');
2009
+ capH3.textContent = 'Current Capabilities';
2010
+ capSection.appendChild(capH3);
2011
+
2012
+ var capGrid = document.createElement('div');
2013
+ capGrid.className = 'cap-grid';
2014
+
2015
+ function addCap(label, value, good) {
2016
+ var item = document.createElement('div');
2017
+ item.className = 'cap-item';
2018
+ var lbl = document.createElement('div');
2019
+ lbl.className = 'cap-label';
2020
+ lbl.textContent = label;
2021
+ var val = document.createElement('div');
2022
+ val.className = 'cap-value';
2023
+ if (good !== undefined) {
2024
+ var dot = document.createElement('span');
2025
+ dot.className = 'status-dot ' + (good ? 'ok' : 'warn');
2026
+ val.appendChild(dot);
2027
+ }
2028
+ val.appendChild(document.createTextNode(String(value)));
2029
+ item.appendChild(lbl);
2030
+ item.appendChild(val);
2031
+ capGrid.appendChild(item);
2032
+ }
2033
+
2034
+ var searchLevel = caps.searchLevel !== undefined ? caps.searchLevel : '?';
2035
+ _currentSearchLevel = String(searchLevel);
2036
+ addCap('Search Level', searchLevel === 1 ? 'Smart Mode' : 'Core FTS5', searchLevel === 1);
2037
+ addCap('Embeddings', caps.embeddings || 'tfidf', caps.embeddings && caps.embeddings !== 'tfidf');
2038
+ var llmProvider = (caps.llm && caps.llm.provider) ? caps.llm.provider : 'None';
2039
+ addCap('LLM Provider', llmProvider, !!caps.llm);
2040
+ var llmModel = (caps.llm && caps.llm.model) ? caps.llm.model : '\u2014';
2041
+ addCap('LLM Model', llmModel, !!caps.llm);
2042
+
2043
+ capSection.appendChild(capGrid);
2044
+ body.appendChild(capSection);
2045
+
2046
+ // --- LLM Provider section ---
2047
+ var llmSection = document.createElement('div');
2048
+ llmSection.className = 'settings-section';
2049
+ var llmH3 = document.createElement('h3');
2050
+ llmH3.textContent = 'LLM Provider';
2051
+ llmSection.appendChild(llmH3);
2052
+
2053
+ var providerGroup = document.createElement('div');
2054
+ providerGroup.className = 'form-group';
2055
+ var providerLabel = document.createElement('label');
2056
+ providerLabel.className = 'form-label';
2057
+ providerLabel.textContent = 'Provider';
2058
+ providerGroup.appendChild(providerLabel);
2059
+
2060
+ var radioGroup = document.createElement('div');
2061
+ radioGroup.className = 'provider-radio-group';
2062
+ var currentProvider = (currentConfig.llm && currentConfig.llm.provider) || '';
2063
+
2064
+ ['anthropic', 'openai', 'ollama'].forEach(function (p) {
2065
+ var wrapper = document.createElement('label');
2066
+ wrapper.className = 'provider-radio' + (currentProvider === p ? ' selected' : '');
2067
+
2068
+ var radio = document.createElement('input');
2069
+ radio.type = 'radio';
2070
+ radio.name = 'llm-provider';
2071
+ radio.value = p;
2072
+ if (currentProvider === p) radio.checked = true;
2073
+
2074
+ radio.addEventListener('change', function () {
2075
+ document.querySelectorAll('.provider-radio').forEach(function (el) { el.classList.remove('selected'); });
2076
+ wrapper.classList.add('selected');
2077
+ apiKeyGroup.style.display = p === 'ollama' ? 'none' : 'block';
2078
+ modelGroup.style.display = 'block';
2079
+ });
2080
+
2081
+ wrapper.appendChild(radio);
2082
+ wrapper.appendChild(document.createTextNode(p.charAt(0).toUpperCase() + p.slice(1)));
2083
+ radioGroup.appendChild(wrapper);
2084
+ });
2085
+
2086
+ providerGroup.appendChild(radioGroup);
2087
+ llmSection.appendChild(providerGroup);
2088
+
2089
+ // API Key input
2090
+ var apiKeyGroup = document.createElement('div');
2091
+ apiKeyGroup.className = 'form-group';
2092
+ apiKeyGroup.style.display = currentProvider && currentProvider !== 'ollama' ? 'block' : (currentProvider === 'ollama' ? 'none' : 'none');
2093
+
2094
+ var apiKeyLabel = document.createElement('label');
2095
+ apiKeyLabel.className = 'form-label';
2096
+ apiKeyLabel.textContent = 'API Key';
2097
+ apiKeyGroup.appendChild(apiKeyLabel);
2098
+
2099
+ var apiKeyInput = document.createElement('input');
2100
+ apiKeyInput.type = 'password';
2101
+ apiKeyInput.className = 'search-input';
2102
+ apiKeyInput.placeholder = 'sk-ant-api03-\u2026 or sk-\u2026';
2103
+ apiKeyInput.style.width = '100%';
2104
+ apiKeyInput.autocomplete = 'off';
2105
+ apiKeyGroup.appendChild(apiKeyInput);
2106
+
2107
+ var apiKeyHint = document.createElement('div');
2108
+ apiKeyHint.className = 'form-hint';
2109
+ apiKeyHint.textContent = 'Leave blank to keep existing key. Key is stored in ~/.memesh/config.json (mode 600).';
2110
+ apiKeyGroup.appendChild(apiKeyHint);
2111
+ llmSection.appendChild(apiKeyGroup);
2112
+
2113
+ // Model input
2114
+ var modelGroup = document.createElement('div');
2115
+ modelGroup.className = 'form-group';
2116
+ modelGroup.style.display = currentProvider ? 'block' : 'none';
2117
+
2118
+ var modelLabel = document.createElement('label');
2119
+ modelLabel.className = 'form-label';
2120
+ modelLabel.textContent = 'Model (optional)';
2121
+ modelGroup.appendChild(modelLabel);
2122
+
2123
+ var modelInput = document.createElement('input');
2124
+ modelInput.type = 'text';
2125
+ modelInput.className = 'search-input';
2126
+ modelInput.placeholder = 'e.g. claude-haiku-4-5, gpt-4o-mini, llama3.2';
2127
+ modelInput.style.width = '100%';
2128
+ if (currentConfig.llm && currentConfig.llm.model) modelInput.value = currentConfig.llm.model;
2129
+ modelGroup.appendChild(modelInput);
2130
+ llmSection.appendChild(modelGroup);
2131
+
2132
+ // Save button row
2133
+ var saveRow = document.createElement('div');
2134
+ saveRow.style.display = 'flex';
2135
+ saveRow.style.gap = '10px';
2136
+ saveRow.style.alignItems = 'center';
2137
+ saveRow.style.marginTop = '4px';
2138
+
2139
+ var saveBtn = document.createElement('button');
2140
+ saveBtn.className = 'btn btn-primary btn-sm';
2141
+ saveBtn.textContent = 'Save';
2142
+
2143
+ var saveMsg = document.createElement('span');
2144
+ saveMsg.style.fontSize = '13px';
2145
+ saveMsg.style.color = 'var(--success)';
2146
+
2147
+ saveBtn.addEventListener('click', async function () {
2148
+ var selectedProvider = document.querySelector('input[name=llm-provider]:checked');
2149
+ if (!selectedProvider) { saveMsg.style.color = 'var(--danger)'; saveMsg.textContent = 'Select a provider first.'; return; }
2150
+ var prov = selectedProvider.value;
2151
+ var llmUpdate = { provider: prov };
2152
+ if (modelInput.value.trim()) llmUpdate.model = modelInput.value.trim();
2153
+ if (apiKeyInput.value.trim()) llmUpdate.apiKey = apiKeyInput.value.trim();
2154
+
2155
+ saveBtn.disabled = true;
2156
+ saveBtn.textContent = 'Saving\u2026';
2157
+ try {
2158
+ var res = await apiCall('POST', '/v1/config', { llm: llmUpdate });
2159
+ if (!res.success) throw new Error(res.error || 'Save failed');
2160
+ saveMsg.style.color = 'var(--success)';
2161
+ saveMsg.textContent = 'Saved! Restart the server to apply LLM changes.';
2162
+ apiKeyInput.value = '';
2163
+ settingsLoaded = false; // force re-render on next visit
2164
+ } catch (err) {
2165
+ saveMsg.style.color = 'var(--danger)';
2166
+ saveMsg.textContent = 'Error: ' + err.message;
2167
+ } finally {
2168
+ saveBtn.disabled = false;
2169
+ saveBtn.textContent = 'Save';
2170
+ }
2171
+ });
2172
+
2173
+ saveRow.appendChild(saveBtn);
2174
+ saveRow.appendChild(saveMsg);
2175
+ llmSection.appendChild(saveRow);
2176
+ body.appendChild(llmSection);
2177
+
2178
+ // --- General settings section ---
2179
+ var genSection = document.createElement('div');
2180
+ genSection.className = 'settings-section';
2181
+ var genH3 = document.createElement('h3');
2182
+ genH3.textContent = 'General';
2183
+ genSection.appendChild(genH3);
2184
+
2185
+ // Auto-capture toggle
2186
+ var autoGroup = document.createElement('div');
2187
+ autoGroup.className = 'form-group';
2188
+ autoGroup.style.display = 'flex';
2189
+ autoGroup.style.alignItems = 'center';
2190
+ autoGroup.style.gap = '10px';
2191
+
2192
+ var autoCheck = document.createElement('input');
2193
+ autoCheck.type = 'checkbox';
2194
+ autoCheck.id = 'auto-capture';
2195
+ autoCheck.style.accentColor = 'var(--accent)';
2196
+ autoCheck.checked = currentConfig.autoCapture !== false;
2197
+
2198
+ var autoLabel = document.createElement('label');
2199
+ autoLabel.htmlFor = 'auto-capture';
2200
+ autoLabel.style.fontSize = '13px';
2201
+ autoLabel.style.fontWeight = '600';
2202
+ autoLabel.style.cursor = 'pointer';
2203
+ autoLabel.textContent = 'Auto-capture (session-start hook)';
2204
+
2205
+ autoGroup.appendChild(autoCheck);
2206
+ autoGroup.appendChild(autoLabel);
2207
+ genSection.appendChild(autoGroup);
2208
+
2209
+ var autoHint = document.createElement('div');
2210
+ autoHint.className = 'form-hint';
2211
+ autoHint.style.marginLeft = '28px';
2212
+ autoHint.textContent = 'Automatically recall project memories at the start of each Claude Code session.';
2213
+ genSection.appendChild(autoHint);
2214
+
2215
+ var genSaveRow = document.createElement('div');
2216
+ genSaveRow.style.marginTop = '12px';
2217
+
2218
+ var genSaveBtn = document.createElement('button');
2219
+ genSaveBtn.className = 'btn btn-primary btn-sm';
2220
+ genSaveBtn.textContent = 'Save';
2221
+
2222
+ var genMsg = document.createElement('span');
2223
+ genMsg.style.fontSize = '13px';
2224
+ genMsg.style.marginLeft = '10px';
2225
+ genMsg.style.color = 'var(--success)';
2226
+
2227
+ genSaveBtn.addEventListener('click', async function () {
2228
+ genSaveBtn.disabled = true;
2229
+ genSaveBtn.textContent = 'Saving\u2026';
2230
+ try {
2231
+ var res = await apiCall('POST', '/v1/config', { autoCapture: autoCheck.checked });
2232
+ if (!res.success) throw new Error(res.error || 'Save failed');
2233
+ genMsg.style.color = 'var(--success)';
2234
+ genMsg.textContent = 'Saved!';
2235
+ setTimeout(function () { genMsg.textContent = ''; }, 3000);
2236
+ } catch (err) {
2237
+ genMsg.style.color = 'var(--danger)';
2238
+ genMsg.textContent = 'Error: ' + err.message;
2239
+ } finally {
2240
+ genSaveBtn.disabled = false;
2241
+ genSaveBtn.textContent = 'Save';
2242
+ }
2243
+ });
2244
+
2245
+ genSaveRow.appendChild(genSaveBtn);
2246
+ genSaveRow.appendChild(genMsg);
2247
+ genSection.appendChild(genSaveRow);
2248
+ body.appendChild(genSection);
2249
+ }
2250
+
2251
+ // ---- Welcome Wizard ----
2252
+ var wizardStep = 0;
2253
+ var wizardProvider = '';
2254
+ var wizardApiKey = '';
2255
+ var wizardModel = '';
2256
+
2257
+ function updateWizardStepDots(totalSteps) {
2258
+ var dotsEl = document.getElementById('wizard-steps');
2259
+ dotsEl.textContent = '';
2260
+ for (var i = 0; i < totalSteps; i++) {
2261
+ var dot = document.createElement('div');
2262
+ dot.className = 'wizard-step-dot' + (i < wizardStep ? ' done' : (i === wizardStep ? ' active' : ''));
2263
+ dotsEl.appendChild(dot);
2264
+ }
2265
+ }
2266
+
2267
+ function renderWizardStep() {
2268
+ var content = document.getElementById('wizard-content');
2269
+ var actions = document.getElementById('wizard-actions');
2270
+ content.textContent = '';
2271
+ actions.textContent = '';
2272
+ updateWizardStepDots(3);
2273
+
2274
+ if (wizardStep === 0) {
2275
+ var title = document.createElement('h2');
2276
+ title.textContent = 'Welcome to MeMesh';
2277
+ content.appendChild(title);
2278
+
2279
+ var sub = document.createElement('p');
2280
+ sub.className = 'subtitle';
2281
+ sub.textContent = 'MeMesh gives Claude a persistent knowledge graph. Set up an LLM provider to unlock Smart Mode \u2014 semantic search, conflict detection, and knowledge evolution.';
2282
+ content.appendChild(sub);
2283
+
2284
+ var capList = document.createElement('ul');
2285
+ capList.style.listStyle = 'none';
2286
+ capList.style.marginBottom = '8px';
2287
+ [
2288
+ ['Core FTS5 search \u2014 always available', true],
2289
+ ['Smart Mode (LLM) \u2014 requires API key', false],
2290
+ ['Auto-capture on session start', true],
2291
+ ].forEach(function (item) {
2292
+ var li = document.createElement('li');
2293
+ li.style.cssText = 'display:flex;align-items:center;gap:8px;padding:6px 0;font-size:14px;';
2294
+ var dot = document.createElement('span');
2295
+ dot.className = 'status-dot ' + (item[1] ? 'ok' : 'warn');
2296
+ li.appendChild(dot);
2297
+ li.appendChild(document.createTextNode(String(item[0])));
2298
+ capList.appendChild(li);
2299
+ });
2300
+ content.appendChild(capList);
2301
+
2302
+ var skipBtn = document.createElement('button');
2303
+ skipBtn.className = 'btn btn-secondary';
2304
+ skipBtn.textContent = 'Skip for now';
2305
+ skipBtn.addEventListener('click', closeWizard);
2306
+
2307
+ var nextBtn = document.createElement('button');
2308
+ nextBtn.className = 'btn btn-primary';
2309
+ nextBtn.textContent = 'Set up Smart Mode \u2192';
2310
+ nextBtn.addEventListener('click', function () { wizardStep = 1; renderWizardStep(); });
2311
+
2312
+ actions.appendChild(skipBtn);
2313
+ actions.appendChild(nextBtn);
2314
+
2315
+ } else if (wizardStep === 1) {
2316
+ var title2 = document.createElement('h2');
2317
+ title2.textContent = 'Choose a Provider';
2318
+ content.appendChild(title2);
2319
+
2320
+ var sub2 = document.createElement('p');
2321
+ sub2.className = 'subtitle';
2322
+ sub2.textContent = 'Select your LLM provider and enter your API key. Keys are stored locally in ~/.memesh/config.json (mode 600).';
2323
+ content.appendChild(sub2);
2324
+
2325
+ // Provider radios
2326
+ var radioGroupW = document.createElement('div');
2327
+ radioGroupW.className = 'provider-radio-group';
2328
+ radioGroupW.style.marginBottom = '16px';
2329
+
2330
+ ['anthropic', 'openai', 'ollama'].forEach(function (p) {
2331
+ var wrapper = document.createElement('label');
2332
+ wrapper.className = 'provider-radio' + (wizardProvider === p ? ' selected' : '');
2333
+
2334
+ var radio = document.createElement('input');
2335
+ radio.type = 'radio';
2336
+ radio.name = 'wizard-provider';
2337
+ radio.value = p;
2338
+ if (wizardProvider === p) radio.checked = true;
2339
+
2340
+ radio.addEventListener('change', function () {
2341
+ document.querySelectorAll('.provider-radio').forEach(function (el) { el.classList.remove('selected'); });
2342
+ wrapper.classList.add('selected');
2343
+ wizardProvider = p;
2344
+ keyInput.style.display = p === 'ollama' ? 'none' : 'block';
2345
+ keyLabel.style.display = p === 'ollama' ? 'none' : 'block';
2346
+ });
2347
+
2348
+ wrapper.appendChild(radio);
2349
+ wrapper.appendChild(document.createTextNode(p.charAt(0).toUpperCase() + p.slice(1)));
2350
+ radioGroupW.appendChild(wrapper);
2351
+ });
2352
+ content.appendChild(radioGroupW);
2353
+
2354
+ // API Key
2355
+ var keyLabel = document.createElement('label');
2356
+ keyLabel.className = 'form-label';
2357
+ keyLabel.textContent = 'API Key';
2358
+ keyLabel.style.display = wizardProvider && wizardProvider !== 'ollama' ? 'block' : 'none';
2359
+ content.appendChild(keyLabel);
2360
+
2361
+ var keyInput = document.createElement('input');
2362
+ keyInput.type = 'password';
2363
+ keyInput.className = 'search-input';
2364
+ keyInput.placeholder = 'Paste your API key\u2026';
2365
+ keyInput.style.width = '100%';
2366
+ keyInput.style.marginBottom = '12px';
2367
+ keyInput.style.display = wizardProvider && wizardProvider !== 'ollama' ? 'block' : 'none';
2368
+ keyInput.value = wizardApiKey;
2369
+ keyInput.addEventListener('input', function () { wizardApiKey = keyInput.value; });
2370
+ content.appendChild(keyInput);
2371
+
2372
+ // Error message
2373
+ var errMsg = document.createElement('div');
2374
+ errMsg.style.cssText = 'font-size:13px;color:var(--danger);min-height:18px;margin-bottom:8px;';
2375
+ content.appendChild(errMsg);
2376
+
2377
+ var backBtn = document.createElement('button');
2378
+ backBtn.className = 'btn btn-secondary';
2379
+ backBtn.textContent = '\u2190 Back';
2380
+ backBtn.addEventListener('click', function () { wizardStep = 0; renderWizardStep(); });
2381
+
2382
+ var testBtn = document.createElement('button');
2383
+ testBtn.className = 'btn btn-secondary';
2384
+ testBtn.textContent = 'Test Connection';
2385
+ testBtn.addEventListener('click', async function () {
2386
+ if (!wizardProvider) { errMsg.textContent = 'Select a provider.'; return; }
2387
+ if (wizardProvider !== 'ollama' && !wizardApiKey.trim()) { errMsg.textContent = 'Enter an API key.'; return; }
2388
+ testBtn.disabled = true;
2389
+ testBtn.textContent = 'Testing\u2026';
2390
+ errMsg.textContent = '';
2391
+ try {
2392
+ // Save to config and check capabilities
2393
+ var payload = { llm: { provider: wizardProvider } };
2394
+ if (wizardApiKey.trim()) payload.llm.apiKey = wizardApiKey.trim();
2395
+ var res = await apiCall('POST', '/v1/config', payload);
2396
+ if (!res.success) throw new Error(res.error || 'Config save failed');
2397
+ errMsg.style.color = 'var(--success)';
2398
+ errMsg.textContent = 'Connection config saved!';
2399
+ } catch (err) {
2400
+ errMsg.style.color = 'var(--danger)';
2401
+ errMsg.textContent = 'Error: ' + err.message;
2402
+ } finally {
2403
+ testBtn.disabled = false;
2404
+ testBtn.textContent = 'Test Connection';
2405
+ }
2406
+ });
2407
+
2408
+ var nextBtn2 = document.createElement('button');
2409
+ nextBtn2.className = 'btn btn-primary';
2410
+ nextBtn2.textContent = 'Next \u2192';
2411
+ nextBtn2.addEventListener('click', async function () {
2412
+ if (!wizardProvider) { errMsg.textContent = 'Select a provider.'; return; }
2413
+ nextBtn2.disabled = true;
2414
+ nextBtn2.textContent = 'Saving\u2026';
2415
+ try {
2416
+ var payload2 = { llm: { provider: wizardProvider }, setupCompleted: true };
2417
+ if (wizardApiKey.trim()) payload2.llm.apiKey = wizardApiKey.trim();
2418
+ var res2 = await apiCall('POST', '/v1/config', payload2);
2419
+ if (!res2.success) throw new Error(res2.error || 'Save failed');
2420
+ wizardStep = 2;
2421
+ renderWizardStep();
2422
+ } catch (err) {
2423
+ errMsg.style.color = 'var(--danger)';
2424
+ errMsg.textContent = 'Error: ' + err.message;
2425
+ nextBtn2.disabled = false;
2426
+ nextBtn2.textContent = 'Next \u2192';
2427
+ }
2428
+ });
2429
+
2430
+ actions.appendChild(backBtn);
2431
+ actions.appendChild(testBtn);
2432
+ actions.appendChild(nextBtn2);
2433
+
2434
+ } else if (wizardStep === 2) {
2435
+ var title3 = document.createElement('h2');
2436
+ title3.textContent = "You're all set!";
2437
+ content.appendChild(title3);
2438
+
2439
+ var sub3 = document.createElement('p');
2440
+ sub3.className = 'subtitle';
2441
+ sub3.textContent = 'MeMesh Smart Mode is configured. Restart the server for LLM changes to take effect. Start using the Search and Browse tabs to explore your knowledge graph.';
2442
+ content.appendChild(sub3);
2443
+
2444
+ var tipBox = document.createElement('div');
2445
+ tipBox.style.cssText = 'background:var(--accent-glow);border:1px solid rgba(59,130,246,0.2);border-radius:var(--radius-sm);padding:14px 16px;font-size:13px;line-height:1.6;color:var(--text-secondary);';
2446
+ var tipLines = [
2447
+ '\u2022 Use the Search tab to find anything across all your memories.',
2448
+ '\u2022 Browse tab shows all entities with filter controls.',
2449
+ '\u2022 Settings tab lets you change your provider anytime.',
2450
+ ];
2451
+ tipLines.forEach(function (line) {
2452
+ var p = document.createElement('p');
2453
+ p.textContent = line;
2454
+ tipBox.appendChild(p);
2455
+ });
2456
+ content.appendChild(tipBox);
2457
+
2458
+ var doneBtn = document.createElement('button');
2459
+ doneBtn.className = 'btn btn-primary';
2460
+ doneBtn.textContent = 'Go to Dashboard';
2461
+ doneBtn.addEventListener('click', closeWizard);
2462
+ actions.appendChild(doneBtn);
2463
+ }
2464
+ }
2465
+
2466
+ function showWelcomeWizard() {
2467
+ wizardStep = 0;
2468
+ document.getElementById('wizard-overlay').classList.remove('hidden');
2469
+ renderWizardStep();
2470
+ }
2471
+
2472
+ function closeWizard() {
2473
+ document.getElementById('wizard-overlay').classList.add('hidden');
2474
+ // Mark setup completed so wizard doesn't reappear
2475
+ apiCall('POST', '/v1/config', { setupCompleted: true });
2476
+ }
2477
+
2478
+ // Overlay click does NOT close wizard — user must use Skip or complete setup
2479
+ document.getElementById('wizard-overlay').addEventListener('click', function (e) {
2480
+ if (e.target === this) {
2481
+ // Intentionally do nothing — prevent accidental dismissal
2482
+ }
2483
+ });
2484
+
2485
+ // ---- Init ----
2486
+ checkHealth();
2487
+ loadBrowse();
2488
+
2489
+ // Check if first-run wizard should appear
2490
+ (async function checkFirstRun() {
2491
+ try {
2492
+ var res = await apiCall('GET', '/v1/config');
2493
+ if (res.success && res.data && res.data.config && !res.data.config.setupCompleted) {
2494
+ showWelcomeWizard();
2495
+ }
2496
+ } catch (_err) {
2497
+ // Silently ignore — wizard is optional
2498
+ }
2499
+ })();
2500
+ })();
2501
+ `.trim();
2502
+ return `<!DOCTYPE html>
2503
+ <html lang="en">
2504
+ <head>
2505
+ <meta charset="UTF-8">
2506
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
2507
+ <title>MeMesh LLM Memory — Dashboard</title>
2508
+ <style>${CSS}</style>
2509
+ <!-- bundled d3.js -->
2510
+ <script>
2511
+ ${bundledD3}
2512
+ <\/script>
2513
+ </head>
2514
+ <body>
2515
+
2516
+ <div class="header">
2517
+ <div>
2518
+ <h1 style="margin:0;line-height:1.2">MeMesh LLM Memory</h1>
2519
+ <span class="subtitle">powered by pcircle.ai</span>
2520
+ </div>
2521
+ <div class="header-right">
2522
+ <div class="meta">
2523
+ <span id="health-indicator"><span class="dot"></span>Connecting\u2026</span>
2524
+ <span id="version-label" class="version"></span>
2525
+ </div>
2526
+ <button id="theme-btn" title="Toggle theme" style="background:none;border:1px solid var(--border);border-radius:var(--radius-xs);padding:6px 10px;cursor:pointer;color:var(--text-secondary);font-size:14px;transition:border-color 0.2s ease;">\u2600\ufe0f</button>
2527
+ </div>
2528
+ </div>
2529
+
2530
+ <nav class="nav" id="nav">
2531
+ <button class="active" data-tab="search">Search</button>
2532
+ <button data-tab="browse">Browse</button>
2533
+ <button data-tab="graph">Graph</button>
2534
+ <button data-tab="analytics">Analytics</button>
2535
+ <button data-tab="timeline">Timeline</button>
2536
+ <button data-tab="manage">Manage</button>
2537
+ <button data-tab="settings">Settings</button>
2538
+ </nav>
2539
+
2540
+ <div class="content">
2541
+
2542
+ <div class="tab-content active" id="tab-search">
2543
+ <div class="card">
2544
+ <h2>Search Knowledge</h2>
2545
+ <div class="search-row">
2546
+ <input class="search-input" id="search-query" type="text" placeholder="Search your memories\u2026 (e.g., \u201cauth\u201d, \u201cdatabase\u201d, \u201cbug fix\u201d)" />
2547
+ <button class="btn btn-primary" id="search-btn">Search</button>
2548
+ </div>
2549
+ <div id="search-results"></div>
2550
+ </div>
2551
+ </div>
2552
+
2553
+ <div class="tab-content" id="tab-browse">
2554
+ <div class="card">
2555
+ <h2>All Memories</h2>
2556
+ <div class="search-row">
2557
+ <input class="search-input" id="browse-filter" type="text" placeholder="Filter by name or type\u2026" />
2558
+ <button class="btn btn-secondary" id="browse-refresh">Refresh</button>
2559
+ </div>
2560
+ <div id="browse-table-wrap"></div>
2561
+ </div>
2562
+ </div>
2563
+
2564
+ <div class="tab-content" id="tab-graph">
2565
+ <div class="card">
2566
+ <h2>Knowledge Graph</h2>
2567
+ <div class="graph-controls">
2568
+ <span>Scroll to zoom \u00b7 Drag nodes \u00b7 Pan with mouse</span>
2569
+ </div>
2570
+ <div class="graph-svg-wrap" id="graph-svg-wrap"></div>
2571
+ </div>
2572
+ </div>
2573
+
2574
+ <div class="tab-content" id="tab-analytics">
2575
+ <div class="card">
2576
+ <h2>Analytics</h2>
2577
+ <div id="analytics-body"></div>
2578
+ </div>
2579
+ </div>
2580
+
2581
+ <div class="tab-content" id="tab-timeline">
2582
+ <div class="card">
2583
+ <h2>Evolution Timeline</h2>
2584
+ <p style="font-size:13px;color:var(--text-muted);margin-bottom:16px;">Entities connected by \u201csupersedes\u201d relations, showing knowledge evolution chains.</p>
2585
+ <div id="timeline-body"></div>
2586
+ </div>
2587
+ </div>
2588
+
2589
+ <div class="tab-content" id="tab-manage">
2590
+ <div class="card">
2591
+ <h2>Manage Memories</h2>
2592
+ <div class="search-row">
2593
+ <input class="search-input" id="manage-filter" type="text" placeholder="Filter by name or type\u2026" />
2594
+ <button class="btn btn-secondary" id="manage-refresh">Refresh</button>
2595
+ </div>
2596
+ <div id="manage-body">
2597
+ <div id="manage-table-wrap"></div>
2598
+ </div>
2599
+ </div>
2600
+ </div>
2601
+
2602
+ <div class="tab-content" id="tab-settings">
2603
+ <div class="card" id="settings-card">
2604
+ <h2>Settings</h2>
2605
+ <div id="settings-body"></div>
2606
+ </div>
2607
+ </div>
2608
+
2609
+ </div>
2610
+
2611
+ <!-- Welcome Wizard Modal -->
2612
+ <div class="wizard-overlay hidden" id="wizard-overlay">
2613
+ <div class="wizard-modal">
2614
+ <div class="wizard-steps" id="wizard-steps"></div>
2615
+ <div id="wizard-content"></div>
2616
+ <div class="wizard-actions" id="wizard-actions"></div>
2617
+ </div>
2618
+ </div>
2619
+
2620
+ <!-- Graph tooltip -->
2621
+ <div id="live-tooltip" class="graph-tooltip" style="display:none;">
2622
+ <div class="tt-name" style="font-weight:600;color:var(--text-primary);font-size:13px;margin-bottom:3px;"></div>
2623
+ <div class="tt-type" style="color:var(--accent-hover);font-size:11px;font-family:var(--font-mono);margin-bottom:4px;"></div>
2624
+ <div class="tt-obs" style="color:var(--text-muted);font-size:12px;"></div>
2625
+ </div>
2626
+
2627
+ <!-- Feedback widget -->
2628
+ <button id="feedback-btn">&#x1f4ac; Feedback</button>
2629
+ <div id="feedback-panel">
2630
+ <h3>Send Feedback</h3>
2631
+ <div class="fb-radio-group">
2632
+ <label class="fb-radio selected"><input type="radio" name="fb-type" value="bug" checked /> Bug</label>
2633
+ <label class="fb-radio"><input type="radio" name="fb-type" value="feature" /> Feature</label>
2634
+ <label class="fb-radio"><input type="radio" name="fb-type" value="question" /> Question</label>
2635
+ </div>
2636
+ <textarea id="fb-desc" placeholder="Describe your feedback\u2026"></textarea>
2637
+ <div class="fb-sys-row">
2638
+ <input type="checkbox" id="fb-sys" checked style="accent-color:var(--accent);" />
2639
+ <label for="fb-sys">Include system info</label>
2640
+ </div>
2641
+ <button class="btn btn-primary" id="fb-submit" style="width:100%;">Open GitHub Issue</button>
2642
+ </div>
2643
+
2644
+ <script>${SCRIPT}<\/script>
2645
+ </body>
2646
+ </html>`;
2647
+ }
2648
+ const isDirectRun = process.argv[1] &&
2649
+ fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
2650
+ if (isDirectRun) {
2651
+ const dbPath = process.env.MEMESH_DB_PATH ??
2652
+ path.join(os.homedir(), '.memesh', 'knowledge-graph.db');
2653
+ const html = generateDashboardHtml(dbPath);
2654
+ const dashboardDir = path.join(os.homedir(), '.memesh');
2655
+ fs.mkdirSync(dashboardDir, { recursive: true });
2656
+ const outPath = path.join(dashboardDir, 'dashboard.html');
2657
+ fs.writeFileSync(outPath, html, { encoding: 'utf-8', mode: 0o600 });
2658
+ const platform = process.platform;
2659
+ const cmd = platform === 'darwin' ? 'open' : 'xdg-open';
2660
+ const args = platform === 'win32' ? ['/c', 'start', '', outPath] : [outPath];
2661
+ const bin = platform === 'win32' ? 'cmd.exe' : cmd;
2662
+ execFile(bin, args, (err) => {
2663
+ if (err) {
2664
+ console.error(`Could not open browser: ${err.message}`);
2665
+ console.log(`Dashboard written to: ${outPath}`);
2666
+ }
2667
+ else {
2668
+ console.log(`Dashboard opened: ${outPath}`);
2669
+ }
2670
+ });
2671
+ }
2672
+ //# sourceMappingURL=view.js.map