superlocalmemory 2.8.5 → 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 (434) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +9 -1
  3. package/NOTICE +63 -0
  4. package/README.md +165 -480
  5. package/bin/slm +17 -449
  6. package/bin/slm-npm +2 -2
  7. package/bin/slm.bat +4 -2
  8. package/conftest.py +5 -0
  9. package/docs/api-reference.md +284 -0
  10. package/docs/architecture.md +149 -0
  11. package/docs/auto-memory.md +150 -0
  12. package/docs/cli-reference.md +276 -0
  13. package/docs/compliance.md +191 -0
  14. package/docs/configuration.md +182 -0
  15. package/docs/getting-started.md +102 -0
  16. package/docs/ide-setup.md +261 -0
  17. package/docs/mcp-tools.md +220 -0
  18. package/docs/migration-from-v2.md +170 -0
  19. package/docs/profiles.md +173 -0
  20. package/docs/troubleshooting.md +310 -0
  21. package/{configs → ide/configs}/antigravity-mcp.json +3 -3
  22. package/ide/configs/chatgpt-desktop-mcp.json +16 -0
  23. package/{configs → ide/configs}/claude-desktop-mcp.json +3 -3
  24. package/{configs → ide/configs}/codex-mcp.toml +4 -4
  25. package/{configs → ide/configs}/continue-mcp.yaml +4 -3
  26. package/{configs → ide/configs}/continue-skills.yaml +6 -6
  27. package/ide/configs/cursor-mcp.json +15 -0
  28. package/{configs → ide/configs}/gemini-cli-mcp.json +2 -2
  29. package/{configs → ide/configs}/jetbrains-mcp.json +2 -2
  30. package/{configs → ide/configs}/opencode-mcp.json +2 -2
  31. package/{configs → ide/configs}/perplexity-mcp.json +2 -2
  32. package/{configs → ide/configs}/vscode-copilot-mcp.json +2 -2
  33. package/{configs → ide/configs}/windsurf-mcp.json +3 -3
  34. package/{configs → ide/configs}/zed-mcp.json +2 -2
  35. package/{hooks → ide/hooks}/context-hook.js +9 -20
  36. package/ide/hooks/memory-list-skill.js +70 -0
  37. package/ide/hooks/memory-profile-skill.js +101 -0
  38. package/ide/hooks/memory-recall-skill.js +62 -0
  39. package/ide/hooks/memory-remember-skill.js +68 -0
  40. package/ide/hooks/memory-reset-skill.js +160 -0
  41. package/{hooks → ide/hooks}/post-recall-hook.js +2 -2
  42. package/ide/integrations/langchain/README.md +106 -0
  43. package/ide/integrations/langchain/langchain_superlocalmemory/__init__.py +9 -0
  44. package/ide/integrations/langchain/langchain_superlocalmemory/chat_message_history.py +201 -0
  45. package/ide/integrations/langchain/pyproject.toml +38 -0
  46. package/{src/learning → ide/integrations/langchain}/tests/__init__.py +1 -0
  47. package/ide/integrations/langchain/tests/test_chat_message_history.py +215 -0
  48. package/ide/integrations/langchain/tests/test_security.py +117 -0
  49. package/ide/integrations/llamaindex/README.md +81 -0
  50. package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/__init__.py +9 -0
  51. package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/base.py +316 -0
  52. package/ide/integrations/llamaindex/pyproject.toml +43 -0
  53. package/{src/lifecycle → ide/integrations/llamaindex}/tests/__init__.py +1 -2
  54. package/ide/integrations/llamaindex/tests/test_chat_store.py +294 -0
  55. package/ide/integrations/llamaindex/tests/test_security.py +241 -0
  56. package/{skills → ide/skills}/slm-build-graph/SKILL.md +6 -6
  57. package/{skills → ide/skills}/slm-list-recent/SKILL.md +5 -5
  58. package/{skills → ide/skills}/slm-recall/SKILL.md +5 -5
  59. package/{skills → ide/skills}/slm-remember/SKILL.md +6 -6
  60. package/{skills → ide/skills}/slm-show-patterns/SKILL.md +7 -7
  61. package/{skills → ide/skills}/slm-status/SKILL.md +9 -9
  62. package/{skills → ide/skills}/slm-switch-profile/SKILL.md +9 -9
  63. package/package.json +13 -22
  64. package/pyproject.toml +85 -0
  65. package/scripts/build-dmg.sh +417 -0
  66. package/scripts/install-skills.ps1 +334 -0
  67. package/{install.ps1 → scripts/install.ps1} +36 -4
  68. package/{install.sh → scripts/install.sh} +14 -13
  69. package/scripts/postinstall.js +2 -2
  70. package/scripts/start-dashboard.ps1 +52 -0
  71. package/scripts/start-dashboard.sh +41 -0
  72. package/scripts/sync-wiki.ps1 +127 -0
  73. package/scripts/sync-wiki.sh +82 -0
  74. package/scripts/test-dmg.sh +161 -0
  75. package/scripts/test-npm-package.ps1 +252 -0
  76. package/scripts/test-npm-package.sh +207 -0
  77. package/scripts/verify-install.ps1 +294 -0
  78. package/scripts/verify-install.sh +266 -0
  79. package/src/superlocalmemory/__init__.py +0 -0
  80. package/src/superlocalmemory/attribution/__init__.py +9 -0
  81. package/src/superlocalmemory/attribution/mathematical_dna.py +235 -0
  82. package/src/superlocalmemory/attribution/signer.py +153 -0
  83. package/src/superlocalmemory/attribution/watermark.py +189 -0
  84. package/src/superlocalmemory/cli/__init__.py +5 -0
  85. package/src/superlocalmemory/cli/commands.py +245 -0
  86. package/src/superlocalmemory/cli/main.py +89 -0
  87. package/src/superlocalmemory/cli/migrate_cmd.py +55 -0
  88. package/src/superlocalmemory/cli/post_install.py +99 -0
  89. package/src/superlocalmemory/cli/setup_wizard.py +129 -0
  90. package/src/superlocalmemory/compliance/__init__.py +0 -0
  91. package/src/superlocalmemory/compliance/abac.py +204 -0
  92. package/src/superlocalmemory/compliance/audit.py +314 -0
  93. package/src/superlocalmemory/compliance/eu_ai_act.py +131 -0
  94. package/src/superlocalmemory/compliance/gdpr.py +294 -0
  95. package/src/superlocalmemory/compliance/lifecycle.py +158 -0
  96. package/src/superlocalmemory/compliance/retention.py +232 -0
  97. package/src/superlocalmemory/compliance/scheduler.py +148 -0
  98. package/src/superlocalmemory/core/__init__.py +0 -0
  99. package/src/superlocalmemory/core/config.py +391 -0
  100. package/src/superlocalmemory/core/embeddings.py +293 -0
  101. package/src/superlocalmemory/core/engine.py +701 -0
  102. package/src/superlocalmemory/core/hooks.py +65 -0
  103. package/src/superlocalmemory/core/maintenance.py +172 -0
  104. package/src/superlocalmemory/core/modes.py +140 -0
  105. package/src/superlocalmemory/core/profiles.py +234 -0
  106. package/src/superlocalmemory/core/registry.py +117 -0
  107. package/src/superlocalmemory/dynamics/__init__.py +0 -0
  108. package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +223 -0
  109. package/src/superlocalmemory/encoding/__init__.py +0 -0
  110. package/src/superlocalmemory/encoding/consolidator.py +485 -0
  111. package/src/superlocalmemory/encoding/emotional.py +125 -0
  112. package/src/superlocalmemory/encoding/entity_resolver.py +525 -0
  113. package/src/superlocalmemory/encoding/entropy_gate.py +104 -0
  114. package/src/superlocalmemory/encoding/fact_extractor.py +775 -0
  115. package/src/superlocalmemory/encoding/foresight.py +91 -0
  116. package/src/superlocalmemory/encoding/graph_builder.py +302 -0
  117. package/src/superlocalmemory/encoding/observation_builder.py +160 -0
  118. package/src/superlocalmemory/encoding/scene_builder.py +183 -0
  119. package/src/superlocalmemory/encoding/signal_inference.py +90 -0
  120. package/src/superlocalmemory/encoding/temporal_parser.py +426 -0
  121. package/src/superlocalmemory/encoding/type_router.py +235 -0
  122. package/src/superlocalmemory/hooks/__init__.py +3 -0
  123. package/src/superlocalmemory/hooks/auto_capture.py +111 -0
  124. package/src/superlocalmemory/hooks/auto_recall.py +93 -0
  125. package/src/superlocalmemory/hooks/ide_connector.py +204 -0
  126. package/src/superlocalmemory/hooks/rules_engine.py +99 -0
  127. package/src/superlocalmemory/infra/__init__.py +3 -0
  128. package/src/superlocalmemory/infra/auth_middleware.py +82 -0
  129. package/src/superlocalmemory/infra/backup.py +317 -0
  130. package/src/superlocalmemory/infra/cache_manager.py +267 -0
  131. package/src/superlocalmemory/infra/event_bus.py +381 -0
  132. package/src/superlocalmemory/infra/rate_limiter.py +135 -0
  133. package/src/{webhook_dispatcher.py → superlocalmemory/infra/webhook_dispatcher.py} +104 -101
  134. package/src/superlocalmemory/learning/__init__.py +0 -0
  135. package/src/superlocalmemory/learning/adaptive.py +172 -0
  136. package/src/superlocalmemory/learning/behavioral.py +490 -0
  137. package/src/superlocalmemory/learning/behavioral_listener.py +94 -0
  138. package/src/superlocalmemory/learning/bootstrap.py +298 -0
  139. package/src/superlocalmemory/learning/cross_project.py +399 -0
  140. package/src/superlocalmemory/learning/database.py +376 -0
  141. package/src/superlocalmemory/learning/engagement.py +323 -0
  142. package/src/superlocalmemory/learning/features.py +138 -0
  143. package/src/superlocalmemory/learning/feedback.py +316 -0
  144. package/src/superlocalmemory/learning/outcomes.py +255 -0
  145. package/src/superlocalmemory/learning/project_context.py +366 -0
  146. package/src/superlocalmemory/learning/ranker.py +155 -0
  147. package/src/superlocalmemory/learning/source_quality.py +303 -0
  148. package/src/superlocalmemory/learning/workflows.py +309 -0
  149. package/src/superlocalmemory/llm/__init__.py +0 -0
  150. package/src/superlocalmemory/llm/backbone.py +316 -0
  151. package/src/superlocalmemory/math/__init__.py +0 -0
  152. package/src/superlocalmemory/math/fisher.py +356 -0
  153. package/src/superlocalmemory/math/langevin.py +398 -0
  154. package/src/superlocalmemory/math/sheaf.py +257 -0
  155. package/src/superlocalmemory/mcp/__init__.py +0 -0
  156. package/src/superlocalmemory/mcp/resources.py +245 -0
  157. package/src/superlocalmemory/mcp/server.py +61 -0
  158. package/src/superlocalmemory/mcp/tools.py +18 -0
  159. package/src/superlocalmemory/mcp/tools_core.py +305 -0
  160. package/src/superlocalmemory/mcp/tools_v28.py +223 -0
  161. package/src/superlocalmemory/mcp/tools_v3.py +286 -0
  162. package/src/superlocalmemory/retrieval/__init__.py +0 -0
  163. package/src/superlocalmemory/retrieval/agentic.py +295 -0
  164. package/src/superlocalmemory/retrieval/ann_index.py +223 -0
  165. package/src/superlocalmemory/retrieval/bm25_channel.py +185 -0
  166. package/src/superlocalmemory/retrieval/bridge_discovery.py +170 -0
  167. package/src/superlocalmemory/retrieval/engine.py +390 -0
  168. package/src/superlocalmemory/retrieval/entity_channel.py +179 -0
  169. package/src/superlocalmemory/retrieval/fusion.py +78 -0
  170. package/src/superlocalmemory/retrieval/profile_channel.py +105 -0
  171. package/src/superlocalmemory/retrieval/reranker.py +154 -0
  172. package/src/superlocalmemory/retrieval/semantic_channel.py +232 -0
  173. package/src/superlocalmemory/retrieval/strategy.py +96 -0
  174. package/src/superlocalmemory/retrieval/temporal_channel.py +175 -0
  175. package/src/superlocalmemory/server/__init__.py +1 -0
  176. package/src/superlocalmemory/server/api.py +248 -0
  177. package/src/superlocalmemory/server/routes/__init__.py +4 -0
  178. package/src/superlocalmemory/server/routes/agents.py +107 -0
  179. package/src/superlocalmemory/server/routes/backup.py +91 -0
  180. package/src/superlocalmemory/server/routes/behavioral.py +127 -0
  181. package/src/superlocalmemory/server/routes/compliance.py +160 -0
  182. package/src/superlocalmemory/server/routes/data_io.py +188 -0
  183. package/src/superlocalmemory/server/routes/events.py +183 -0
  184. package/src/superlocalmemory/server/routes/helpers.py +85 -0
  185. package/src/superlocalmemory/server/routes/learning.py +273 -0
  186. package/src/superlocalmemory/server/routes/lifecycle.py +116 -0
  187. package/src/superlocalmemory/server/routes/memories.py +399 -0
  188. package/src/superlocalmemory/server/routes/profiles.py +219 -0
  189. package/src/superlocalmemory/server/routes/stats.py +346 -0
  190. package/src/superlocalmemory/server/routes/v3_api.py +365 -0
  191. package/src/superlocalmemory/server/routes/ws.py +82 -0
  192. package/src/superlocalmemory/server/security_middleware.py +57 -0
  193. package/src/superlocalmemory/server/ui.py +245 -0
  194. package/src/superlocalmemory/storage/__init__.py +0 -0
  195. package/src/superlocalmemory/storage/access_control.py +182 -0
  196. package/src/superlocalmemory/storage/database.py +594 -0
  197. package/src/superlocalmemory/storage/migrations.py +303 -0
  198. package/src/superlocalmemory/storage/models.py +406 -0
  199. package/src/superlocalmemory/storage/schema.py +726 -0
  200. package/src/superlocalmemory/storage/v2_migrator.py +317 -0
  201. package/src/superlocalmemory/trust/__init__.py +0 -0
  202. package/src/superlocalmemory/trust/gate.py +130 -0
  203. package/src/superlocalmemory/trust/provenance.py +124 -0
  204. package/src/superlocalmemory/trust/scorer.py +347 -0
  205. package/src/superlocalmemory/trust/signals.py +153 -0
  206. package/ui/index.html +278 -5
  207. package/ui/js/auto-settings.js +70 -0
  208. package/ui/js/dashboard.js +90 -0
  209. package/ui/js/fact-detail.js +92 -0
  210. package/ui/js/feedback.js +2 -2
  211. package/ui/js/ide-status.js +102 -0
  212. package/ui/js/math-health.js +98 -0
  213. package/ui/js/recall-lab.js +127 -0
  214. package/ui/js/settings.js +2 -2
  215. package/ui/js/trust-dashboard.js +73 -0
  216. package/api_server.py +0 -724
  217. package/bin/aider-smart +0 -72
  218. package/bin/superlocalmemoryv2-learning +0 -4
  219. package/bin/superlocalmemoryv2-list +0 -3
  220. package/bin/superlocalmemoryv2-patterns +0 -4
  221. package/bin/superlocalmemoryv2-profile +0 -3
  222. package/bin/superlocalmemoryv2-recall +0 -3
  223. package/bin/superlocalmemoryv2-remember +0 -3
  224. package/bin/superlocalmemoryv2-reset +0 -3
  225. package/bin/superlocalmemoryv2-status +0 -3
  226. package/configs/chatgpt-desktop-mcp.json +0 -16
  227. package/configs/cursor-mcp.json +0 -15
  228. package/docs/SECURITY-QUICK-REFERENCE.md +0 -214
  229. package/hooks/memory-list-skill.js +0 -139
  230. package/hooks/memory-profile-skill.js +0 -273
  231. package/hooks/memory-recall-skill.js +0 -114
  232. package/hooks/memory-remember-skill.js +0 -127
  233. package/hooks/memory-reset-skill.js +0 -274
  234. package/mcp_server.py +0 -1800
  235. package/requirements-core.txt +0 -22
  236. package/requirements-learning.txt +0 -12
  237. package/requirements.txt +0 -12
  238. package/src/agent_registry.py +0 -411
  239. package/src/auth_middleware.py +0 -61
  240. package/src/auto_backup.py +0 -459
  241. package/src/behavioral/__init__.py +0 -49
  242. package/src/behavioral/behavioral_listener.py +0 -203
  243. package/src/behavioral/behavioral_patterns.py +0 -275
  244. package/src/behavioral/cross_project_transfer.py +0 -206
  245. package/src/behavioral/outcome_inference.py +0 -194
  246. package/src/behavioral/outcome_tracker.py +0 -193
  247. package/src/behavioral/tests/__init__.py +0 -4
  248. package/src/behavioral/tests/test_behavioral_integration.py +0 -108
  249. package/src/behavioral/tests/test_behavioral_patterns.py +0 -150
  250. package/src/behavioral/tests/test_cross_project_transfer.py +0 -142
  251. package/src/behavioral/tests/test_mcp_behavioral.py +0 -139
  252. package/src/behavioral/tests/test_mcp_report_outcome.py +0 -117
  253. package/src/behavioral/tests/test_outcome_inference.py +0 -107
  254. package/src/behavioral/tests/test_outcome_tracker.py +0 -96
  255. package/src/cache_manager.py +0 -518
  256. package/src/compliance/__init__.py +0 -48
  257. package/src/compliance/abac_engine.py +0 -149
  258. package/src/compliance/abac_middleware.py +0 -116
  259. package/src/compliance/audit_db.py +0 -215
  260. package/src/compliance/audit_logger.py +0 -148
  261. package/src/compliance/retention_manager.py +0 -289
  262. package/src/compliance/retention_scheduler.py +0 -186
  263. package/src/compliance/tests/__init__.py +0 -4
  264. package/src/compliance/tests/test_abac_enforcement.py +0 -95
  265. package/src/compliance/tests/test_abac_engine.py +0 -124
  266. package/src/compliance/tests/test_abac_mcp_integration.py +0 -118
  267. package/src/compliance/tests/test_audit_db.py +0 -123
  268. package/src/compliance/tests/test_audit_logger.py +0 -98
  269. package/src/compliance/tests/test_mcp_audit.py +0 -128
  270. package/src/compliance/tests/test_mcp_retention_policy.py +0 -125
  271. package/src/compliance/tests/test_retention_manager.py +0 -131
  272. package/src/compliance/tests/test_retention_scheduler.py +0 -99
  273. package/src/compression/__init__.py +0 -25
  274. package/src/compression/cli.py +0 -150
  275. package/src/compression/cold_storage.py +0 -217
  276. package/src/compression/config.py +0 -72
  277. package/src/compression/orchestrator.py +0 -133
  278. package/src/compression/tier2_compressor.py +0 -228
  279. package/src/compression/tier3_compressor.py +0 -153
  280. package/src/compression/tier_classifier.py +0 -148
  281. package/src/db_connection_manager.py +0 -536
  282. package/src/embedding_engine.py +0 -63
  283. package/src/embeddings/__init__.py +0 -47
  284. package/src/embeddings/cache.py +0 -70
  285. package/src/embeddings/cli.py +0 -113
  286. package/src/embeddings/constants.py +0 -47
  287. package/src/embeddings/database.py +0 -91
  288. package/src/embeddings/engine.py +0 -247
  289. package/src/embeddings/model_loader.py +0 -145
  290. package/src/event_bus.py +0 -562
  291. package/src/graph/__init__.py +0 -36
  292. package/src/graph/build_helpers.py +0 -74
  293. package/src/graph/cli.py +0 -87
  294. package/src/graph/cluster_builder.py +0 -188
  295. package/src/graph/cluster_summary.py +0 -148
  296. package/src/graph/constants.py +0 -47
  297. package/src/graph/edge_builder.py +0 -162
  298. package/src/graph/entity_extractor.py +0 -95
  299. package/src/graph/graph_core.py +0 -226
  300. package/src/graph/graph_search.py +0 -231
  301. package/src/graph/hierarchical.py +0 -207
  302. package/src/graph/schema.py +0 -99
  303. package/src/graph_engine.py +0 -52
  304. package/src/hnsw_index.py +0 -628
  305. package/src/hybrid_search.py +0 -46
  306. package/src/learning/__init__.py +0 -217
  307. package/src/learning/adaptive_ranker.py +0 -682
  308. package/src/learning/bootstrap/__init__.py +0 -69
  309. package/src/learning/bootstrap/constants.py +0 -93
  310. package/src/learning/bootstrap/db_queries.py +0 -316
  311. package/src/learning/bootstrap/sampling.py +0 -82
  312. package/src/learning/bootstrap/text_utils.py +0 -71
  313. package/src/learning/cross_project_aggregator.py +0 -857
  314. package/src/learning/db/__init__.py +0 -40
  315. package/src/learning/db/constants.py +0 -44
  316. package/src/learning/db/schema.py +0 -279
  317. package/src/learning/engagement_tracker.py +0 -628
  318. package/src/learning/feature_extractor.py +0 -708
  319. package/src/learning/feedback_collector.py +0 -806
  320. package/src/learning/learning_db.py +0 -915
  321. package/src/learning/project_context_manager.py +0 -572
  322. package/src/learning/ranking/__init__.py +0 -33
  323. package/src/learning/ranking/constants.py +0 -84
  324. package/src/learning/ranking/helpers.py +0 -278
  325. package/src/learning/source_quality_scorer.py +0 -676
  326. package/src/learning/synthetic_bootstrap.py +0 -755
  327. package/src/learning/tests/test_adaptive_ranker.py +0 -325
  328. package/src/learning/tests/test_adaptive_ranker_v28.py +0 -60
  329. package/src/learning/tests/test_aggregator.py +0 -306
  330. package/src/learning/tests/test_auto_retrain_v28.py +0 -35
  331. package/src/learning/tests/test_e2e_ranking_v28.py +0 -82
  332. package/src/learning/tests/test_feature_extractor_v28.py +0 -93
  333. package/src/learning/tests/test_feedback_collector.py +0 -294
  334. package/src/learning/tests/test_learning_db.py +0 -602
  335. package/src/learning/tests/test_learning_db_v28.py +0 -110
  336. package/src/learning/tests/test_learning_init_v28.py +0 -48
  337. package/src/learning/tests/test_outcome_signals.py +0 -48
  338. package/src/learning/tests/test_project_context.py +0 -292
  339. package/src/learning/tests/test_schema_migration.py +0 -319
  340. package/src/learning/tests/test_signal_inference.py +0 -397
  341. package/src/learning/tests/test_source_quality.py +0 -351
  342. package/src/learning/tests/test_synthetic_bootstrap.py +0 -429
  343. package/src/learning/tests/test_workflow_miner.py +0 -318
  344. package/src/learning/workflow_pattern_miner.py +0 -655
  345. package/src/lifecycle/__init__.py +0 -54
  346. package/src/lifecycle/bounded_growth.py +0 -239
  347. package/src/lifecycle/compaction_engine.py +0 -226
  348. package/src/lifecycle/lifecycle_engine.py +0 -355
  349. package/src/lifecycle/lifecycle_evaluator.py +0 -257
  350. package/src/lifecycle/lifecycle_scheduler.py +0 -130
  351. package/src/lifecycle/retention_policy.py +0 -285
  352. package/src/lifecycle/tests/test_bounded_growth.py +0 -193
  353. package/src/lifecycle/tests/test_compaction.py +0 -179
  354. package/src/lifecycle/tests/test_lifecycle_engine.py +0 -137
  355. package/src/lifecycle/tests/test_lifecycle_evaluation.py +0 -177
  356. package/src/lifecycle/tests/test_lifecycle_scheduler.py +0 -127
  357. package/src/lifecycle/tests/test_lifecycle_search.py +0 -109
  358. package/src/lifecycle/tests/test_mcp_compact.py +0 -149
  359. package/src/lifecycle/tests/test_mcp_lifecycle_status.py +0 -114
  360. package/src/lifecycle/tests/test_retention_policy.py +0 -162
  361. package/src/mcp_tools_v28.py +0 -281
  362. package/src/memory/__init__.py +0 -36
  363. package/src/memory/cli.py +0 -205
  364. package/src/memory/constants.py +0 -39
  365. package/src/memory/helpers.py +0 -28
  366. package/src/memory/schema.py +0 -166
  367. package/src/memory-profiles.py +0 -595
  368. package/src/memory-reset.py +0 -491
  369. package/src/memory_compression.py +0 -989
  370. package/src/memory_store_v2.py +0 -1155
  371. package/src/migrate_v1_to_v2.py +0 -629
  372. package/src/pattern_learner.py +0 -34
  373. package/src/patterns/__init__.py +0 -24
  374. package/src/patterns/analyzers.py +0 -251
  375. package/src/patterns/learner.py +0 -271
  376. package/src/patterns/scoring.py +0 -171
  377. package/src/patterns/store.py +0 -225
  378. package/src/patterns/terminology.py +0 -140
  379. package/src/provenance_tracker.py +0 -312
  380. package/src/qualixar_attribution.py +0 -139
  381. package/src/qualixar_watermark.py +0 -78
  382. package/src/query_optimizer.py +0 -511
  383. package/src/rate_limiter.py +0 -83
  384. package/src/search/__init__.py +0 -20
  385. package/src/search/cli.py +0 -77
  386. package/src/search/constants.py +0 -26
  387. package/src/search/engine.py +0 -241
  388. package/src/search/fusion.py +0 -122
  389. package/src/search/index_loader.py +0 -114
  390. package/src/search/methods.py +0 -162
  391. package/src/search_engine_v2.py +0 -401
  392. package/src/setup_validator.py +0 -482
  393. package/src/subscription_manager.py +0 -391
  394. package/src/tree/__init__.py +0 -59
  395. package/src/tree/builder.py +0 -185
  396. package/src/tree/nodes.py +0 -202
  397. package/src/tree/queries.py +0 -257
  398. package/src/tree/schema.py +0 -80
  399. package/src/tree_manager.py +0 -19
  400. package/src/trust/__init__.py +0 -45
  401. package/src/trust/constants.py +0 -66
  402. package/src/trust/queries.py +0 -157
  403. package/src/trust/schema.py +0 -95
  404. package/src/trust/scorer.py +0 -299
  405. package/src/trust/signals.py +0 -95
  406. package/src/trust_scorer.py +0 -44
  407. package/ui/app.js +0 -1588
  408. package/ui/js/graph-cytoscape-monolithic-backup.js +0 -1168
  409. package/ui/js/graph-cytoscape.js +0 -1168
  410. package/ui/js/graph-d3-backup.js +0 -32
  411. package/ui/js/graph.js +0 -32
  412. package/ui_server.py +0 -266
  413. /package/docs/{ACCESSIBILITY.md → v2-archive/ACCESSIBILITY.md} +0 -0
  414. /package/docs/{ARCHITECTURE.md → v2-archive/ARCHITECTURE.md} +0 -0
  415. /package/docs/{CLI-COMMANDS-REFERENCE.md → v2-archive/CLI-COMMANDS-REFERENCE.md} +0 -0
  416. /package/docs/{COMPRESSION-README.md → v2-archive/COMPRESSION-README.md} +0 -0
  417. /package/docs/{FRAMEWORK-INTEGRATIONS.md → v2-archive/FRAMEWORK-INTEGRATIONS.md} +0 -0
  418. /package/docs/{MCP-MANUAL-SETUP.md → v2-archive/MCP-MANUAL-SETUP.md} +0 -0
  419. /package/docs/{MCP-TROUBLESHOOTING.md → v2-archive/MCP-TROUBLESHOOTING.md} +0 -0
  420. /package/docs/{PATTERN-LEARNING.md → v2-archive/PATTERN-LEARNING.md} +0 -0
  421. /package/docs/{PROFILES-GUIDE.md → v2-archive/PROFILES-GUIDE.md} +0 -0
  422. /package/docs/{RESET-GUIDE.md → v2-archive/RESET-GUIDE.md} +0 -0
  423. /package/docs/{SEARCH-ENGINE-V2.2.0.md → v2-archive/SEARCH-ENGINE-V2.2.0.md} +0 -0
  424. /package/docs/{SEARCH-INTEGRATION-GUIDE.md → v2-archive/SEARCH-INTEGRATION-GUIDE.md} +0 -0
  425. /package/docs/{UI-SERVER.md → v2-archive/UI-SERVER.md} +0 -0
  426. /package/docs/{UNIVERSAL-INTEGRATION.md → v2-archive/UNIVERSAL-INTEGRATION.md} +0 -0
  427. /package/docs/{V2.2.0-OPTIONAL-SEARCH.md → v2-archive/V2.2.0-OPTIONAL-SEARCH.md} +0 -0
  428. /package/docs/{WINDOWS-INSTALL-README.txt → v2-archive/WINDOWS-INSTALL-README.txt} +0 -0
  429. /package/docs/{WINDOWS-POST-INSTALL.txt → v2-archive/WINDOWS-POST-INSTALL.txt} +0 -0
  430. /package/docs/{example_graph_usage.py → v2-archive/example_graph_usage.py} +0 -0
  431. /package/{completions → ide/completions}/slm.bash +0 -0
  432. /package/{completions → ide/completions}/slm.zsh +0 -0
  433. /package/{configs → ide/configs}/cody-commands.json +0 -0
  434. /package/{install-skills.sh → scripts/install-skills.sh} +0 -0
@@ -1,391 +0,0 @@
1
- #!/usr/bin/env python3
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
4
- """
5
- SubscriptionManager — Manages durable and ephemeral event subscriptions.
6
-
7
- Subscribers register interest in specific event types and receive matching
8
- events via their chosen channel (SSE, WebSocket, Webhook).
9
-
10
- Subscription Types:
11
- Durable (default) — Persisted to DB, survives disconnect, auto-replay on reconnect
12
- Ephemeral (opt-in) — In-memory only, dies on disconnect
13
-
14
- Filter Syntax:
15
- {
16
- "event_types": ["memory.created", "memory.deleted"], // null = all types
17
- "min_importance": 5, // null = no filter
18
- "source_protocols": ["mcp", "cli"], // null = all protocols
19
- "projects": ["myapp"] // null = all projects
20
- }
21
- """
22
-
23
- import json
24
- import logging
25
- import threading
26
- from datetime import datetime
27
- from pathlib import Path
28
- from typing import Optional, List, Dict, Any
29
-
30
- logger = logging.getLogger("superlocalmemory.subscriptions")
31
-
32
-
33
- class SubscriptionManager:
34
- """
35
- Manages event subscriptions for the Event Bus.
36
-
37
- Thread-safe. Durable subscriptions persist to SQLite. Ephemeral
38
- subscriptions are in-memory only.
39
- """
40
-
41
- _instances: Dict[str, "SubscriptionManager"] = {}
42
- _instances_lock = threading.Lock()
43
-
44
- @classmethod
45
- def get_instance(cls, db_path: Optional[Path] = None) -> "SubscriptionManager":
46
- """Get or create the singleton SubscriptionManager."""
47
- if db_path is None:
48
- db_path = Path.home() / ".claude-memory" / "memory.db"
49
- key = str(db_path)
50
- with cls._instances_lock:
51
- if key not in cls._instances:
52
- cls._instances[key] = cls(db_path)
53
- return cls._instances[key]
54
-
55
- @classmethod
56
- def reset_instance(cls, db_path: Optional[Path] = None) -> None:
57
- """Remove singleton. Used for testing."""
58
- with cls._instances_lock:
59
- if db_path is None:
60
- cls._instances.clear()
61
- else:
62
- key = str(db_path)
63
- if key in cls._instances:
64
- del cls._instances[key]
65
-
66
- def __init__(self, db_path: Path):
67
- self.db_path = Path(db_path)
68
-
69
- # Ephemeral subscriptions (in-memory only)
70
- self._ephemeral: Dict[str, dict] = {}
71
- self._ephemeral_lock = threading.Lock()
72
-
73
- self._init_schema()
74
- logger.info("SubscriptionManager initialized: db=%s", self.db_path)
75
-
76
- def _init_schema(self):
77
- """Create subscriptions table if it doesn't exist."""
78
- try:
79
- from db_connection_manager import DbConnectionManager
80
- mgr = DbConnectionManager.get_instance(self.db_path)
81
-
82
- def _create(conn):
83
- conn.execute('''
84
- CREATE TABLE IF NOT EXISTS subscriptions (
85
- id INTEGER PRIMARY KEY AUTOINCREMENT,
86
- subscriber_id TEXT NOT NULL UNIQUE,
87
- channel TEXT NOT NULL,
88
- filter TEXT NOT NULL DEFAULT '{}',
89
- webhook_url TEXT,
90
- durable INTEGER DEFAULT 1,
91
- last_event_id INTEGER DEFAULT 0,
92
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
93
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
94
- )
95
- ''')
96
- conn.execute('''
97
- CREATE INDEX IF NOT EXISTS idx_subs_channel
98
- ON subscriptions(channel)
99
- ''')
100
- conn.commit()
101
-
102
- mgr.execute_write(_create)
103
- except ImportError:
104
- import sqlite3
105
- conn = sqlite3.connect(str(self.db_path))
106
- try:
107
- conn.execute('''
108
- CREATE TABLE IF NOT EXISTS subscriptions (
109
- id INTEGER PRIMARY KEY AUTOINCREMENT,
110
- subscriber_id TEXT NOT NULL UNIQUE,
111
- channel TEXT NOT NULL,
112
- filter TEXT NOT NULL DEFAULT '{}',
113
- webhook_url TEXT,
114
- durable INTEGER DEFAULT 1,
115
- last_event_id INTEGER DEFAULT 0,
116
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
117
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
118
- )
119
- ''')
120
- conn.execute('CREATE INDEX IF NOT EXISTS idx_subs_channel ON subscriptions(channel)')
121
- conn.commit()
122
- finally:
123
- conn.close()
124
-
125
- # =========================================================================
126
- # Subscribe / Unsubscribe
127
- # =========================================================================
128
-
129
- def subscribe(
130
- self,
131
- subscriber_id: str,
132
- channel: str = "sse",
133
- filter_obj: Optional[dict] = None,
134
- webhook_url: Optional[str] = None,
135
- durable: bool = True,
136
- ) -> dict:
137
- """
138
- Register a subscription.
139
-
140
- Args:
141
- subscriber_id: Unique identifier for the subscriber
142
- channel: Delivery channel — 'sse', 'websocket', 'webhook'
143
- filter_obj: Event filter (see module docstring for syntax)
144
- webhook_url: URL for webhook channel (required if channel='webhook')
145
- durable: If True, persists to DB; if False, in-memory only
146
-
147
- Returns:
148
- Subscription dict with id and details
149
-
150
- Raises:
151
- ValueError: If channel is invalid or webhook_url missing for webhook channel
152
- """
153
- if channel not in ("sse", "websocket", "webhook"):
154
- raise ValueError(f"Invalid channel: {channel}. Must be sse, websocket, or webhook")
155
-
156
- if channel == "webhook" and not webhook_url:
157
- raise ValueError("webhook_url is required for webhook channel")
158
-
159
- # Validate webhook URL format
160
- if webhook_url and not (webhook_url.startswith("http://") or webhook_url.startswith("https://")):
161
- raise ValueError("webhook_url must start with http:// or https://")
162
-
163
- filter_json = json.dumps(filter_obj or {})
164
- now = datetime.now().isoformat()
165
-
166
- sub = {
167
- "subscriber_id": subscriber_id,
168
- "channel": channel,
169
- "filter": filter_obj or {},
170
- "webhook_url": webhook_url,
171
- "durable": durable,
172
- "last_event_id": 0,
173
- "created_at": now,
174
- }
175
-
176
- if durable:
177
- self._persist_subscription(sub, filter_json)
178
- else:
179
- with self._ephemeral_lock:
180
- self._ephemeral[subscriber_id] = sub
181
-
182
- logger.info("Subscription created: id=%s, channel=%s, durable=%s", subscriber_id, channel, durable)
183
- return sub
184
-
185
- def _persist_subscription(self, sub: dict, filter_json: str):
186
- """Save durable subscription to database."""
187
- try:
188
- from db_connection_manager import DbConnectionManager
189
- mgr = DbConnectionManager.get_instance(self.db_path)
190
-
191
- def _upsert(conn):
192
- conn.execute('''
193
- INSERT INTO subscriptions (subscriber_id, channel, filter, webhook_url, durable, created_at, updated_at)
194
- VALUES (?, ?, ?, ?, 1, ?, ?)
195
- ON CONFLICT(subscriber_id) DO UPDATE SET
196
- channel = excluded.channel,
197
- filter = excluded.filter,
198
- webhook_url = excluded.webhook_url,
199
- updated_at = excluded.updated_at
200
- ''', (
201
- sub["subscriber_id"],
202
- sub["channel"],
203
- filter_json,
204
- sub.get("webhook_url"),
205
- sub["created_at"],
206
- sub["created_at"],
207
- ))
208
- conn.commit()
209
-
210
- mgr.execute_write(_upsert)
211
- except Exception as e:
212
- logger.error("Failed to persist subscription: %s", e)
213
-
214
- def unsubscribe(self, subscriber_id: str) -> bool:
215
- """
216
- Remove a subscription (durable or ephemeral).
217
-
218
- Args:
219
- subscriber_id: ID of the subscription to remove
220
-
221
- Returns:
222
- True if subscription was found and removed
223
- """
224
- removed = False
225
-
226
- # Remove ephemeral
227
- with self._ephemeral_lock:
228
- if subscriber_id in self._ephemeral:
229
- del self._ephemeral[subscriber_id]
230
- removed = True
231
-
232
- # Remove durable
233
- try:
234
- from db_connection_manager import DbConnectionManager
235
- mgr = DbConnectionManager.get_instance(self.db_path)
236
-
237
- def _delete(conn):
238
- conn.execute("DELETE FROM subscriptions WHERE subscriber_id = ?", (subscriber_id,))
239
- conn.commit()
240
- return conn.total_changes > 0
241
-
242
- if mgr.execute_write(_delete):
243
- removed = True
244
- except Exception as e:
245
- logger.error("Failed to delete subscription: %s", e)
246
-
247
- return removed
248
-
249
- def update_last_event_id(self, subscriber_id: str, event_id: int) -> None:
250
- """Update the last event ID received by a durable subscriber (for replay)."""
251
- try:
252
- from db_connection_manager import DbConnectionManager
253
- mgr = DbConnectionManager.get_instance(self.db_path)
254
-
255
- def _update(conn):
256
- conn.execute(
257
- "UPDATE subscriptions SET last_event_id = ?, updated_at = ? WHERE subscriber_id = ?",
258
- (event_id, datetime.now().isoformat(), subscriber_id)
259
- )
260
- conn.commit()
261
-
262
- mgr.execute_write(_update)
263
- except Exception as e:
264
- logger.error("Failed to update last_event_id: %s", e)
265
-
266
- # =========================================================================
267
- # Query Subscriptions
268
- # =========================================================================
269
-
270
- def get_matching_subscribers(self, event: dict) -> List[dict]:
271
- """
272
- Get all subscriptions that match a given event.
273
-
274
- Applies filter logic: event_types, min_importance, source_protocols.
275
-
276
- Args:
277
- event: Event dict with event_type, importance, source_protocol, etc.
278
-
279
- Returns:
280
- List of matching subscription dicts
281
- """
282
- all_subs = self.list_subscriptions()
283
- matching = []
284
-
285
- for sub in all_subs:
286
- if self._matches_filter(sub.get("filter", {}), event):
287
- matching.append(sub)
288
-
289
- return matching
290
-
291
- def _matches_filter(self, filter_obj: dict, event: dict) -> bool:
292
- """Check if an event matches a subscription filter."""
293
- if not filter_obj:
294
- return True # No filter = match all
295
-
296
- # Event type filter
297
- allowed_types = filter_obj.get("event_types")
298
- if allowed_types and event.get("event_type") not in allowed_types:
299
- return False
300
-
301
- # Importance filter
302
- min_importance = filter_obj.get("min_importance")
303
- if min_importance and (event.get("importance", 0) < min_importance):
304
- return False
305
-
306
- # Protocol filter
307
- allowed_protocols = filter_obj.get("source_protocols")
308
- if allowed_protocols and event.get("source_protocol") not in allowed_protocols:
309
- return False
310
-
311
- return True
312
-
313
- def list_subscriptions(self) -> List[dict]:
314
- """Get all active subscriptions (durable + ephemeral)."""
315
- subs = []
316
-
317
- # Ephemeral
318
- with self._ephemeral_lock:
319
- subs.extend(list(self._ephemeral.values()))
320
-
321
- # Durable (from DB)
322
- try:
323
- from db_connection_manager import DbConnectionManager
324
- mgr = DbConnectionManager.get_instance(self.db_path)
325
-
326
- with mgr.read_connection() as conn:
327
- cursor = conn.cursor()
328
- cursor.execute("""
329
- SELECT subscriber_id, channel, filter, webhook_url, durable,
330
- last_event_id, created_at, updated_at
331
- FROM subscriptions
332
- """)
333
- for row in cursor.fetchall():
334
- filter_obj = {}
335
- try:
336
- filter_obj = json.loads(row[2]) if row[2] else {}
337
- except (json.JSONDecodeError, TypeError):
338
- pass
339
-
340
- subs.append({
341
- "subscriber_id": row[0],
342
- "channel": row[1],
343
- "filter": filter_obj,
344
- "webhook_url": row[3],
345
- "durable": bool(row[4]),
346
- "last_event_id": row[5],
347
- "created_at": row[6],
348
- "updated_at": row[7],
349
- })
350
- except Exception as e:
351
- logger.error("Failed to list durable subscriptions: %s", e)
352
-
353
- return subs
354
-
355
- def get_subscription(self, subscriber_id: str) -> Optional[dict]:
356
- """Get a specific subscription by ID."""
357
- # Check ephemeral first
358
- with self._ephemeral_lock:
359
- if subscriber_id in self._ephemeral:
360
- return self._ephemeral[subscriber_id]
361
-
362
- # Check durable
363
- try:
364
- from db_connection_manager import DbConnectionManager
365
- mgr = DbConnectionManager.get_instance(self.db_path)
366
-
367
- with mgr.read_connection() as conn:
368
- cursor = conn.cursor()
369
- cursor.execute(
370
- "SELECT subscriber_id, channel, filter, webhook_url, durable, last_event_id FROM subscriptions WHERE subscriber_id = ?",
371
- (subscriber_id,)
372
- )
373
- row = cursor.fetchone()
374
- if row:
375
- filter_obj = {}
376
- try:
377
- filter_obj = json.loads(row[2]) if row[2] else {}
378
- except (json.JSONDecodeError, TypeError):
379
- pass
380
- return {
381
- "subscriber_id": row[0],
382
- "channel": row[1],
383
- "filter": filter_obj,
384
- "webhook_url": row[3],
385
- "durable": bool(row[4]),
386
- "last_event_id": row[5],
387
- }
388
- except Exception as e:
389
- logger.error("Failed to get subscription: %s", e)
390
-
391
- return None
@@ -1,59 +0,0 @@
1
- # SPDX-License-Identifier: MIT
2
- # Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
3
- """Tree — Hierarchical Memory Tree Management.
4
-
5
- Composes the TreeManager class from focused mixin modules:
6
- - schema.py : DB initialization and root-node bootstrap
7
- - nodes.py : Node CRUD and count aggregation
8
- - queries.py : Read-only tree traversal and statistics
9
- - builder.py : Full tree construction from memories table
10
- """
11
- from pathlib import Path
12
- from typing import Optional
13
-
14
- from .schema import TreeSchemaMixin, MEMORY_DIR, DB_PATH
15
- from .nodes import TreeNodesMixin
16
- from .queries import TreeQueriesMixin
17
- from .builder import TreeBuilderMixin
18
-
19
-
20
- class TreeManager(TreeSchemaMixin, TreeNodesMixin, TreeQueriesMixin, TreeBuilderMixin):
21
- """
22
- Manages hierarchical tree structure for memory navigation.
23
-
24
- Tree Structure:
25
- Root
26
- +-- Project: NextJS-App
27
- | +-- Category: Frontend
28
- | | +-- Memory: React Components
29
- | | +-- Memory: State Management
30
- | +-- Category: Backend
31
- | +-- Memory: API Routes
32
- +-- Project: Python-ML
33
-
34
- Materialized Path Format:
35
- - Root: "1"
36
- - Project: "1.2"
37
- - Category: "1.2.3"
38
- - Memory: "1.2.3.4"
39
-
40
- Benefits:
41
- - Fast subtree queries: WHERE tree_path LIKE '1.2.%'
42
- - O(1) depth calculation: count dots in path
43
- - O(1) parent lookup: parse path
44
- - No recursive CTEs needed
45
- """
46
-
47
- def __init__(self, db_path: Optional[Path] = None):
48
- """
49
- Initialize TreeManager.
50
-
51
- Args:
52
- db_path: Optional custom database path
53
- """
54
- self.db_path = db_path or DB_PATH
55
- self._init_db()
56
- self.root_id = self._ensure_root()
57
-
58
-
59
- __all__ = ['TreeManager', 'MEMORY_DIR', 'DB_PATH']
@@ -1,185 +0,0 @@
1
- # SPDX-License-Identifier: MIT
2
- # Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
3
- """Tree Builder — Constructs the full tree from the memories table.
4
-
5
- Provides TreeBuilderMixin with build_tree, plus the CLI entry point.
6
- """
7
- import sqlite3
8
-
9
-
10
- class TreeBuilderMixin:
11
- """Builds the hierarchical tree from flat memory records."""
12
-
13
- def build_tree(self):
14
- """
15
- Build complete tree structure from memories table.
16
-
17
- Process:
18
- 1. Clear existing tree (except root)
19
- 2. Group memories by project
20
- 3. Group by category within projects
21
- 4. Link individual memories as leaf nodes
22
- 5. Update aggregated counts
23
- """
24
- conn = sqlite3.connect(self.db_path)
25
- try:
26
- cursor = conn.cursor()
27
-
28
- # Clear existing tree (keep root)
29
- cursor.execute('DELETE FROM memory_tree WHERE node_type != ?', ('root',))
30
-
31
- # Step 1: Create project nodes
32
- cursor.execute('''
33
- SELECT DISTINCT project_path, project_name
34
- FROM memories
35
- WHERE project_path IS NOT NULL
36
- ORDER BY project_path
37
- ''')
38
- projects = cursor.fetchall()
39
-
40
- project_map = {} # project_path -> node_id
41
-
42
- for project_path, project_name in projects:
43
- name = project_name or project_path.split('/')[-1]
44
- node_id = self.add_node('project', name, self.root_id, description=project_path)
45
- project_map[project_path] = node_id
46
-
47
- # Step 2: Create category nodes within projects
48
- cursor.execute('''
49
- SELECT DISTINCT project_path, category
50
- FROM memories
51
- WHERE project_path IS NOT NULL AND category IS NOT NULL
52
- ORDER BY project_path, category
53
- ''')
54
- categories = cursor.fetchall()
55
-
56
- category_map = {} # (project_path, category) -> node_id
57
-
58
- for project_path, category in categories:
59
- parent_id = project_map.get(project_path)
60
- if parent_id:
61
- node_id = self.add_node('category', category, parent_id)
62
- category_map[(project_path, category)] = node_id
63
-
64
- # Step 3: Link memories as leaf nodes
65
- cursor.execute('''
66
- SELECT id, content, summary, project_path, category, importance, created_at
67
- FROM memories
68
- ORDER BY created_at DESC
69
- ''')
70
- memories = cursor.fetchall()
71
-
72
- for mem_id, content, summary, project_path, category, importance, created_at in memories:
73
- # Determine parent node
74
- if project_path and category and (project_path, category) in category_map:
75
- parent_id = category_map[(project_path, category)]
76
- elif project_path and project_path in project_map:
77
- parent_id = project_map[project_path]
78
- else:
79
- parent_id = self.root_id
80
-
81
- # Create memory node
82
- name = summary or content[:60].replace('\n', ' ')
83
- self.add_node('memory', name, parent_id, memory_id=mem_id, description=content[:200])
84
-
85
- # Step 4: Update aggregated counts
86
- self._update_all_counts()
87
-
88
- conn.commit()
89
- finally:
90
- conn.close()
91
-
92
-
93
- def run_cli():
94
- """CLI entry point for tree_manager."""
95
- import sys
96
- import json
97
- from src.tree import TreeManager
98
-
99
- tree_mgr = TreeManager()
100
-
101
- if len(sys.argv) < 2:
102
- print("TreeManager CLI")
103
- print("\nCommands:")
104
- print(" python tree_manager.py build # Build tree from memories")
105
- print(" python tree_manager.py show [project] [depth] # Show tree structure")
106
- print(" python tree_manager.py subtree <node_id> # Get subtree")
107
- print(" python tree_manager.py path <node_id> # Get path to root")
108
- print(" python tree_manager.py stats # Show statistics")
109
- print(" python tree_manager.py add <type> <name> <parent_id> # Add node")
110
- print(" python tree_manager.py delete <node_id> # Delete node")
111
- sys.exit(0)
112
-
113
- command = sys.argv[1]
114
-
115
- if command == "build":
116
- print("Building tree from memories...")
117
- tree_mgr.build_tree()
118
- stats = tree_mgr.get_stats()
119
- print(f"Tree built: {stats['total_nodes']} nodes, {stats['total_memories']} memories")
120
-
121
- elif command == "show":
122
- project = sys.argv[2] if len(sys.argv) > 2 else None
123
- max_depth = int(sys.argv[3]) if len(sys.argv) > 3 else None
124
-
125
- tree = tree_mgr.get_tree(project, max_depth)
126
-
127
- def print_tree(node, indent=0):
128
- if 'error' in node:
129
- print(node['error'])
130
- return
131
-
132
- prefix = " " * indent
133
- icon = {"root": "\U0001f333", "project": "\U0001f4c1", "category": "\U0001f4c2", "memory": "\U0001f4c4"}.get(node['type'], "\u2022")
134
-
135
- print(f"{prefix}{icon} {node['name']} (id={node['id']}, memories={node['memory_count']})")
136
-
137
- for child in node.get('children', []):
138
- print_tree(child, indent + 1)
139
-
140
- print_tree(tree)
141
-
142
- elif command == "subtree" and len(sys.argv) >= 3:
143
- node_id = int(sys.argv[2])
144
- nodes = tree_mgr.get_subtree(node_id)
145
-
146
- if not nodes:
147
- print(f"No subtree found for node {node_id}")
148
- else:
149
- print(f"Subtree of node {node_id}:")
150
- for node in nodes:
151
- indent = " " * (node['depth'] - nodes[0]['depth'] + 1)
152
- print(f"{indent}- {node['name']} (id={node['id']})")
153
-
154
- elif command == "path" and len(sys.argv) >= 3:
155
- node_id = int(sys.argv[2])
156
- path = tree_mgr.get_path_to_root(node_id)
157
-
158
- if not path:
159
- print(f"Node {node_id} not found")
160
- else:
161
- print("Path to root:")
162
- print(" > ".join([f"{n['name']} (id={n['id']})" for n in path]))
163
-
164
- elif command == "stats":
165
- stats = tree_mgr.get_stats()
166
- print(json.dumps(stats, indent=2))
167
-
168
- elif command == "add" and len(sys.argv) >= 5:
169
- node_type = sys.argv[2]
170
- name = sys.argv[3]
171
- parent_id = int(sys.argv[4])
172
-
173
- node_id = tree_mgr.add_node(node_type, name, parent_id)
174
- print(f"Node created with ID: {node_id}")
175
-
176
- elif command == "delete" and len(sys.argv) >= 3:
177
- node_id = int(sys.argv[2])
178
- if tree_mgr.delete_node(node_id):
179
- print(f"Node {node_id} deleted")
180
- else:
181
- print(f"Node {node_id} not found")
182
-
183
- else:
184
- print(f"Unknown command: {command}")
185
- sys.exit(1)