superlocalmemory 2.8.6 → 3.0.1

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 (431) hide show
  1. package/LICENSE +9 -1
  2. package/NOTICE +63 -0
  3. package/README.md +165 -480
  4. package/bin/slm +17 -449
  5. package/bin/slm-npm +62 -48
  6. package/conftest.py +5 -0
  7. package/docs/api-reference.md +284 -0
  8. package/docs/architecture.md +149 -0
  9. package/docs/auto-memory.md +150 -0
  10. package/docs/cli-reference.md +276 -0
  11. package/docs/compliance.md +191 -0
  12. package/docs/configuration.md +182 -0
  13. package/docs/getting-started.md +102 -0
  14. package/docs/ide-setup.md +261 -0
  15. package/docs/mcp-tools.md +220 -0
  16. package/docs/migration-from-v2.md +170 -0
  17. package/docs/profiles.md +173 -0
  18. package/docs/troubleshooting.md +310 -0
  19. package/{configs → ide/configs}/antigravity-mcp.json +3 -3
  20. package/ide/configs/chatgpt-desktop-mcp.json +16 -0
  21. package/{configs → ide/configs}/claude-desktop-mcp.json +3 -3
  22. package/{configs → ide/configs}/codex-mcp.toml +4 -4
  23. package/{configs → ide/configs}/continue-mcp.yaml +4 -3
  24. package/{configs → ide/configs}/continue-skills.yaml +6 -6
  25. package/ide/configs/cursor-mcp.json +15 -0
  26. package/{configs → ide/configs}/gemini-cli-mcp.json +2 -2
  27. package/{configs → ide/configs}/jetbrains-mcp.json +2 -2
  28. package/{configs → ide/configs}/opencode-mcp.json +2 -2
  29. package/{configs → ide/configs}/perplexity-mcp.json +2 -2
  30. package/{configs → ide/configs}/vscode-copilot-mcp.json +2 -2
  31. package/{configs → ide/configs}/windsurf-mcp.json +3 -3
  32. package/{configs → ide/configs}/zed-mcp.json +2 -2
  33. package/{hooks → ide/hooks}/context-hook.js +9 -20
  34. package/ide/hooks/memory-list-skill.js +70 -0
  35. package/ide/hooks/memory-profile-skill.js +101 -0
  36. package/ide/hooks/memory-recall-skill.js +62 -0
  37. package/ide/hooks/memory-remember-skill.js +68 -0
  38. package/ide/hooks/memory-reset-skill.js +160 -0
  39. package/{hooks → ide/hooks}/post-recall-hook.js +2 -2
  40. package/ide/integrations/langchain/README.md +106 -0
  41. package/ide/integrations/langchain/langchain_superlocalmemory/__init__.py +9 -0
  42. package/ide/integrations/langchain/langchain_superlocalmemory/chat_message_history.py +201 -0
  43. package/ide/integrations/langchain/pyproject.toml +38 -0
  44. package/{src/learning → ide/integrations/langchain}/tests/__init__.py +1 -0
  45. package/ide/integrations/langchain/tests/test_chat_message_history.py +215 -0
  46. package/ide/integrations/langchain/tests/test_security.py +117 -0
  47. package/ide/integrations/llamaindex/README.md +81 -0
  48. package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/__init__.py +9 -0
  49. package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/base.py +316 -0
  50. package/ide/integrations/llamaindex/pyproject.toml +43 -0
  51. package/{src/lifecycle → ide/integrations/llamaindex}/tests/__init__.py +1 -2
  52. package/ide/integrations/llamaindex/tests/test_chat_store.py +294 -0
  53. package/ide/integrations/llamaindex/tests/test_security.py +241 -0
  54. package/{skills → ide/skills}/slm-build-graph/SKILL.md +6 -6
  55. package/{skills → ide/skills}/slm-list-recent/SKILL.md +5 -5
  56. package/{skills → ide/skills}/slm-recall/SKILL.md +5 -5
  57. package/{skills → ide/skills}/slm-remember/SKILL.md +6 -6
  58. package/{skills → ide/skills}/slm-show-patterns/SKILL.md +7 -7
  59. package/{skills → ide/skills}/slm-status/SKILL.md +9 -9
  60. package/{skills → ide/skills}/slm-switch-profile/SKILL.md +9 -9
  61. package/package.json +13 -22
  62. package/pyproject.toml +85 -0
  63. package/scripts/build-dmg.sh +417 -0
  64. package/scripts/install-skills.ps1 +334 -0
  65. package/scripts/postinstall.js +2 -2
  66. package/scripts/start-dashboard.ps1 +52 -0
  67. package/scripts/start-dashboard.sh +41 -0
  68. package/scripts/sync-wiki.ps1 +127 -0
  69. package/scripts/sync-wiki.sh +82 -0
  70. package/scripts/test-dmg.sh +161 -0
  71. package/scripts/test-npm-package.ps1 +252 -0
  72. package/scripts/test-npm-package.sh +207 -0
  73. package/scripts/verify-install.ps1 +294 -0
  74. package/scripts/verify-install.sh +266 -0
  75. package/src/superlocalmemory/__init__.py +0 -0
  76. package/src/superlocalmemory/attribution/__init__.py +9 -0
  77. package/src/superlocalmemory/attribution/mathematical_dna.py +235 -0
  78. package/src/superlocalmemory/attribution/signer.py +153 -0
  79. package/src/superlocalmemory/attribution/watermark.py +189 -0
  80. package/src/superlocalmemory/cli/__init__.py +5 -0
  81. package/src/superlocalmemory/cli/commands.py +245 -0
  82. package/src/superlocalmemory/cli/main.py +89 -0
  83. package/src/superlocalmemory/cli/migrate_cmd.py +55 -0
  84. package/src/superlocalmemory/cli/post_install.py +99 -0
  85. package/src/superlocalmemory/cli/setup_wizard.py +129 -0
  86. package/src/superlocalmemory/compliance/__init__.py +0 -0
  87. package/src/superlocalmemory/compliance/abac.py +204 -0
  88. package/src/superlocalmemory/compliance/audit.py +314 -0
  89. package/src/superlocalmemory/compliance/eu_ai_act.py +131 -0
  90. package/src/superlocalmemory/compliance/gdpr.py +294 -0
  91. package/src/superlocalmemory/compliance/lifecycle.py +158 -0
  92. package/src/superlocalmemory/compliance/retention.py +232 -0
  93. package/src/superlocalmemory/compliance/scheduler.py +148 -0
  94. package/src/superlocalmemory/core/__init__.py +0 -0
  95. package/src/superlocalmemory/core/config.py +391 -0
  96. package/src/superlocalmemory/core/embeddings.py +293 -0
  97. package/src/superlocalmemory/core/engine.py +701 -0
  98. package/src/superlocalmemory/core/hooks.py +65 -0
  99. package/src/superlocalmemory/core/maintenance.py +172 -0
  100. package/src/superlocalmemory/core/modes.py +140 -0
  101. package/src/superlocalmemory/core/profiles.py +234 -0
  102. package/src/superlocalmemory/core/registry.py +117 -0
  103. package/src/superlocalmemory/dynamics/__init__.py +0 -0
  104. package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +223 -0
  105. package/src/superlocalmemory/encoding/__init__.py +0 -0
  106. package/src/superlocalmemory/encoding/consolidator.py +485 -0
  107. package/src/superlocalmemory/encoding/emotional.py +125 -0
  108. package/src/superlocalmemory/encoding/entity_resolver.py +525 -0
  109. package/src/superlocalmemory/encoding/entropy_gate.py +104 -0
  110. package/src/superlocalmemory/encoding/fact_extractor.py +775 -0
  111. package/src/superlocalmemory/encoding/foresight.py +91 -0
  112. package/src/superlocalmemory/encoding/graph_builder.py +302 -0
  113. package/src/superlocalmemory/encoding/observation_builder.py +160 -0
  114. package/src/superlocalmemory/encoding/scene_builder.py +183 -0
  115. package/src/superlocalmemory/encoding/signal_inference.py +90 -0
  116. package/src/superlocalmemory/encoding/temporal_parser.py +426 -0
  117. package/src/superlocalmemory/encoding/type_router.py +235 -0
  118. package/src/superlocalmemory/hooks/__init__.py +3 -0
  119. package/src/superlocalmemory/hooks/auto_capture.py +111 -0
  120. package/src/superlocalmemory/hooks/auto_recall.py +93 -0
  121. package/src/superlocalmemory/hooks/ide_connector.py +204 -0
  122. package/src/superlocalmemory/hooks/rules_engine.py +99 -0
  123. package/src/superlocalmemory/infra/__init__.py +3 -0
  124. package/src/superlocalmemory/infra/auth_middleware.py +82 -0
  125. package/src/superlocalmemory/infra/backup.py +317 -0
  126. package/src/superlocalmemory/infra/cache_manager.py +267 -0
  127. package/src/superlocalmemory/infra/event_bus.py +381 -0
  128. package/src/superlocalmemory/infra/rate_limiter.py +135 -0
  129. package/src/{webhook_dispatcher.py → superlocalmemory/infra/webhook_dispatcher.py} +104 -101
  130. package/src/superlocalmemory/learning/__init__.py +0 -0
  131. package/src/superlocalmemory/learning/adaptive.py +172 -0
  132. package/src/superlocalmemory/learning/behavioral.py +490 -0
  133. package/src/superlocalmemory/learning/behavioral_listener.py +94 -0
  134. package/src/superlocalmemory/learning/bootstrap.py +298 -0
  135. package/src/superlocalmemory/learning/cross_project.py +399 -0
  136. package/src/superlocalmemory/learning/database.py +376 -0
  137. package/src/superlocalmemory/learning/engagement.py +323 -0
  138. package/src/superlocalmemory/learning/features.py +138 -0
  139. package/src/superlocalmemory/learning/feedback.py +316 -0
  140. package/src/superlocalmemory/learning/outcomes.py +255 -0
  141. package/src/superlocalmemory/learning/project_context.py +366 -0
  142. package/src/superlocalmemory/learning/ranker.py +155 -0
  143. package/src/superlocalmemory/learning/source_quality.py +303 -0
  144. package/src/superlocalmemory/learning/workflows.py +309 -0
  145. package/src/superlocalmemory/llm/__init__.py +0 -0
  146. package/src/superlocalmemory/llm/backbone.py +316 -0
  147. package/src/superlocalmemory/math/__init__.py +0 -0
  148. package/src/superlocalmemory/math/fisher.py +356 -0
  149. package/src/superlocalmemory/math/langevin.py +398 -0
  150. package/src/superlocalmemory/math/sheaf.py +257 -0
  151. package/src/superlocalmemory/mcp/__init__.py +0 -0
  152. package/src/superlocalmemory/mcp/resources.py +245 -0
  153. package/src/superlocalmemory/mcp/server.py +61 -0
  154. package/src/superlocalmemory/mcp/tools.py +18 -0
  155. package/src/superlocalmemory/mcp/tools_core.py +305 -0
  156. package/src/superlocalmemory/mcp/tools_v28.py +223 -0
  157. package/src/superlocalmemory/mcp/tools_v3.py +286 -0
  158. package/src/superlocalmemory/retrieval/__init__.py +0 -0
  159. package/src/superlocalmemory/retrieval/agentic.py +295 -0
  160. package/src/superlocalmemory/retrieval/ann_index.py +223 -0
  161. package/src/superlocalmemory/retrieval/bm25_channel.py +185 -0
  162. package/src/superlocalmemory/retrieval/bridge_discovery.py +170 -0
  163. package/src/superlocalmemory/retrieval/engine.py +390 -0
  164. package/src/superlocalmemory/retrieval/entity_channel.py +179 -0
  165. package/src/superlocalmemory/retrieval/fusion.py +78 -0
  166. package/src/superlocalmemory/retrieval/profile_channel.py +105 -0
  167. package/src/superlocalmemory/retrieval/reranker.py +154 -0
  168. package/src/superlocalmemory/retrieval/semantic_channel.py +232 -0
  169. package/src/superlocalmemory/retrieval/strategy.py +96 -0
  170. package/src/superlocalmemory/retrieval/temporal_channel.py +175 -0
  171. package/src/superlocalmemory/server/__init__.py +1 -0
  172. package/src/superlocalmemory/server/api.py +248 -0
  173. package/src/superlocalmemory/server/routes/__init__.py +4 -0
  174. package/src/superlocalmemory/server/routes/agents.py +107 -0
  175. package/src/superlocalmemory/server/routes/backup.py +91 -0
  176. package/src/superlocalmemory/server/routes/behavioral.py +127 -0
  177. package/src/superlocalmemory/server/routes/compliance.py +160 -0
  178. package/src/superlocalmemory/server/routes/data_io.py +188 -0
  179. package/src/superlocalmemory/server/routes/events.py +183 -0
  180. package/src/superlocalmemory/server/routes/helpers.py +85 -0
  181. package/src/superlocalmemory/server/routes/learning.py +273 -0
  182. package/src/superlocalmemory/server/routes/lifecycle.py +116 -0
  183. package/src/superlocalmemory/server/routes/memories.py +399 -0
  184. package/src/superlocalmemory/server/routes/profiles.py +219 -0
  185. package/src/superlocalmemory/server/routes/stats.py +346 -0
  186. package/src/superlocalmemory/server/routes/v3_api.py +365 -0
  187. package/src/superlocalmemory/server/routes/ws.py +82 -0
  188. package/src/superlocalmemory/server/security_middleware.py +57 -0
  189. package/src/superlocalmemory/server/ui.py +245 -0
  190. package/src/superlocalmemory/storage/__init__.py +0 -0
  191. package/src/superlocalmemory/storage/access_control.py +182 -0
  192. package/src/superlocalmemory/storage/database.py +594 -0
  193. package/src/superlocalmemory/storage/migrations.py +303 -0
  194. package/src/superlocalmemory/storage/models.py +406 -0
  195. package/src/superlocalmemory/storage/schema.py +726 -0
  196. package/src/superlocalmemory/storage/v2_migrator.py +317 -0
  197. package/src/superlocalmemory/trust/__init__.py +0 -0
  198. package/src/superlocalmemory/trust/gate.py +130 -0
  199. package/src/superlocalmemory/trust/provenance.py +124 -0
  200. package/src/superlocalmemory/trust/scorer.py +347 -0
  201. package/src/superlocalmemory/trust/signals.py +153 -0
  202. package/ui/index.html +278 -5
  203. package/ui/js/auto-settings.js +70 -0
  204. package/ui/js/dashboard.js +90 -0
  205. package/ui/js/fact-detail.js +92 -0
  206. package/ui/js/feedback.js +2 -2
  207. package/ui/js/ide-status.js +102 -0
  208. package/ui/js/math-health.js +98 -0
  209. package/ui/js/recall-lab.js +127 -0
  210. package/ui/js/settings.js +2 -2
  211. package/ui/js/trust-dashboard.js +73 -0
  212. package/api_server.py +0 -724
  213. package/bin/aider-smart +0 -72
  214. package/bin/superlocalmemoryv2-learning +0 -4
  215. package/bin/superlocalmemoryv2-list +0 -3
  216. package/bin/superlocalmemoryv2-patterns +0 -4
  217. package/bin/superlocalmemoryv2-profile +0 -3
  218. package/bin/superlocalmemoryv2-recall +0 -3
  219. package/bin/superlocalmemoryv2-remember +0 -3
  220. package/bin/superlocalmemoryv2-reset +0 -3
  221. package/bin/superlocalmemoryv2-status +0 -3
  222. package/configs/chatgpt-desktop-mcp.json +0 -16
  223. package/configs/cursor-mcp.json +0 -15
  224. package/hooks/memory-list-skill.js +0 -139
  225. package/hooks/memory-profile-skill.js +0 -273
  226. package/hooks/memory-recall-skill.js +0 -114
  227. package/hooks/memory-remember-skill.js +0 -127
  228. package/hooks/memory-reset-skill.js +0 -274
  229. package/mcp_server.py +0 -1808
  230. package/requirements-core.txt +0 -22
  231. package/requirements-learning.txt +0 -12
  232. package/requirements.txt +0 -12
  233. package/src/agent_registry.py +0 -411
  234. package/src/auth_middleware.py +0 -61
  235. package/src/auto_backup.py +0 -459
  236. package/src/behavioral/__init__.py +0 -49
  237. package/src/behavioral/behavioral_listener.py +0 -203
  238. package/src/behavioral/behavioral_patterns.py +0 -275
  239. package/src/behavioral/cross_project_transfer.py +0 -206
  240. package/src/behavioral/outcome_inference.py +0 -194
  241. package/src/behavioral/outcome_tracker.py +0 -193
  242. package/src/behavioral/tests/__init__.py +0 -4
  243. package/src/behavioral/tests/test_behavioral_integration.py +0 -108
  244. package/src/behavioral/tests/test_behavioral_patterns.py +0 -150
  245. package/src/behavioral/tests/test_cross_project_transfer.py +0 -142
  246. package/src/behavioral/tests/test_mcp_behavioral.py +0 -139
  247. package/src/behavioral/tests/test_mcp_report_outcome.py +0 -117
  248. package/src/behavioral/tests/test_outcome_inference.py +0 -107
  249. package/src/behavioral/tests/test_outcome_tracker.py +0 -96
  250. package/src/cache_manager.py +0 -518
  251. package/src/compliance/__init__.py +0 -48
  252. package/src/compliance/abac_engine.py +0 -149
  253. package/src/compliance/abac_middleware.py +0 -116
  254. package/src/compliance/audit_db.py +0 -215
  255. package/src/compliance/audit_logger.py +0 -148
  256. package/src/compliance/retention_manager.py +0 -289
  257. package/src/compliance/retention_scheduler.py +0 -186
  258. package/src/compliance/tests/__init__.py +0 -4
  259. package/src/compliance/tests/test_abac_enforcement.py +0 -95
  260. package/src/compliance/tests/test_abac_engine.py +0 -124
  261. package/src/compliance/tests/test_abac_mcp_integration.py +0 -118
  262. package/src/compliance/tests/test_audit_db.py +0 -123
  263. package/src/compliance/tests/test_audit_logger.py +0 -98
  264. package/src/compliance/tests/test_mcp_audit.py +0 -128
  265. package/src/compliance/tests/test_mcp_retention_policy.py +0 -125
  266. package/src/compliance/tests/test_retention_manager.py +0 -131
  267. package/src/compliance/tests/test_retention_scheduler.py +0 -99
  268. package/src/compression/__init__.py +0 -25
  269. package/src/compression/cli.py +0 -150
  270. package/src/compression/cold_storage.py +0 -217
  271. package/src/compression/config.py +0 -72
  272. package/src/compression/orchestrator.py +0 -133
  273. package/src/compression/tier2_compressor.py +0 -228
  274. package/src/compression/tier3_compressor.py +0 -153
  275. package/src/compression/tier_classifier.py +0 -148
  276. package/src/db_connection_manager.py +0 -536
  277. package/src/embedding_engine.py +0 -63
  278. package/src/embeddings/__init__.py +0 -47
  279. package/src/embeddings/cache.py +0 -70
  280. package/src/embeddings/cli.py +0 -113
  281. package/src/embeddings/constants.py +0 -47
  282. package/src/embeddings/database.py +0 -91
  283. package/src/embeddings/engine.py +0 -247
  284. package/src/embeddings/model_loader.py +0 -145
  285. package/src/event_bus.py +0 -562
  286. package/src/graph/__init__.py +0 -36
  287. package/src/graph/build_helpers.py +0 -74
  288. package/src/graph/cli.py +0 -87
  289. package/src/graph/cluster_builder.py +0 -188
  290. package/src/graph/cluster_summary.py +0 -148
  291. package/src/graph/constants.py +0 -47
  292. package/src/graph/edge_builder.py +0 -162
  293. package/src/graph/entity_extractor.py +0 -95
  294. package/src/graph/graph_core.py +0 -226
  295. package/src/graph/graph_search.py +0 -231
  296. package/src/graph/hierarchical.py +0 -207
  297. package/src/graph/schema.py +0 -99
  298. package/src/graph_engine.py +0 -52
  299. package/src/hnsw_index.py +0 -628
  300. package/src/hybrid_search.py +0 -46
  301. package/src/learning/__init__.py +0 -217
  302. package/src/learning/adaptive_ranker.py +0 -682
  303. package/src/learning/bootstrap/__init__.py +0 -69
  304. package/src/learning/bootstrap/constants.py +0 -93
  305. package/src/learning/bootstrap/db_queries.py +0 -316
  306. package/src/learning/bootstrap/sampling.py +0 -82
  307. package/src/learning/bootstrap/text_utils.py +0 -71
  308. package/src/learning/cross_project_aggregator.py +0 -857
  309. package/src/learning/db/__init__.py +0 -40
  310. package/src/learning/db/constants.py +0 -44
  311. package/src/learning/db/schema.py +0 -279
  312. package/src/learning/engagement_tracker.py +0 -628
  313. package/src/learning/feature_extractor.py +0 -708
  314. package/src/learning/feedback_collector.py +0 -806
  315. package/src/learning/learning_db.py +0 -915
  316. package/src/learning/project_context_manager.py +0 -572
  317. package/src/learning/ranking/__init__.py +0 -33
  318. package/src/learning/ranking/constants.py +0 -84
  319. package/src/learning/ranking/helpers.py +0 -278
  320. package/src/learning/source_quality_scorer.py +0 -676
  321. package/src/learning/synthetic_bootstrap.py +0 -755
  322. package/src/learning/tests/test_adaptive_ranker.py +0 -325
  323. package/src/learning/tests/test_adaptive_ranker_v28.py +0 -60
  324. package/src/learning/tests/test_aggregator.py +0 -306
  325. package/src/learning/tests/test_auto_retrain_v28.py +0 -35
  326. package/src/learning/tests/test_e2e_ranking_v28.py +0 -82
  327. package/src/learning/tests/test_feature_extractor_v28.py +0 -93
  328. package/src/learning/tests/test_feedback_collector.py +0 -294
  329. package/src/learning/tests/test_learning_db.py +0 -602
  330. package/src/learning/tests/test_learning_db_v28.py +0 -110
  331. package/src/learning/tests/test_learning_init_v28.py +0 -48
  332. package/src/learning/tests/test_outcome_signals.py +0 -48
  333. package/src/learning/tests/test_project_context.py +0 -292
  334. package/src/learning/tests/test_schema_migration.py +0 -319
  335. package/src/learning/tests/test_signal_inference.py +0 -397
  336. package/src/learning/tests/test_source_quality.py +0 -351
  337. package/src/learning/tests/test_synthetic_bootstrap.py +0 -429
  338. package/src/learning/tests/test_workflow_miner.py +0 -318
  339. package/src/learning/workflow_pattern_miner.py +0 -655
  340. package/src/lifecycle/__init__.py +0 -54
  341. package/src/lifecycle/bounded_growth.py +0 -239
  342. package/src/lifecycle/compaction_engine.py +0 -226
  343. package/src/lifecycle/lifecycle_engine.py +0 -355
  344. package/src/lifecycle/lifecycle_evaluator.py +0 -257
  345. package/src/lifecycle/lifecycle_scheduler.py +0 -130
  346. package/src/lifecycle/retention_policy.py +0 -285
  347. package/src/lifecycle/tests/test_bounded_growth.py +0 -193
  348. package/src/lifecycle/tests/test_compaction.py +0 -179
  349. package/src/lifecycle/tests/test_lifecycle_engine.py +0 -137
  350. package/src/lifecycle/tests/test_lifecycle_evaluation.py +0 -177
  351. package/src/lifecycle/tests/test_lifecycle_scheduler.py +0 -127
  352. package/src/lifecycle/tests/test_lifecycle_search.py +0 -109
  353. package/src/lifecycle/tests/test_mcp_compact.py +0 -149
  354. package/src/lifecycle/tests/test_mcp_lifecycle_status.py +0 -114
  355. package/src/lifecycle/tests/test_retention_policy.py +0 -162
  356. package/src/mcp_tools_v28.py +0 -281
  357. package/src/memory/__init__.py +0 -36
  358. package/src/memory/cli.py +0 -205
  359. package/src/memory/constants.py +0 -39
  360. package/src/memory/helpers.py +0 -28
  361. package/src/memory/schema.py +0 -166
  362. package/src/memory-profiles.py +0 -595
  363. package/src/memory-reset.py +0 -491
  364. package/src/memory_compression.py +0 -989
  365. package/src/memory_store_v2.py +0 -1155
  366. package/src/migrate_v1_to_v2.py +0 -629
  367. package/src/pattern_learner.py +0 -34
  368. package/src/patterns/__init__.py +0 -24
  369. package/src/patterns/analyzers.py +0 -251
  370. package/src/patterns/learner.py +0 -271
  371. package/src/patterns/scoring.py +0 -171
  372. package/src/patterns/store.py +0 -225
  373. package/src/patterns/terminology.py +0 -140
  374. package/src/provenance_tracker.py +0 -312
  375. package/src/qualixar_attribution.py +0 -139
  376. package/src/qualixar_watermark.py +0 -78
  377. package/src/query_optimizer.py +0 -511
  378. package/src/rate_limiter.py +0 -83
  379. package/src/search/__init__.py +0 -20
  380. package/src/search/cli.py +0 -77
  381. package/src/search/constants.py +0 -26
  382. package/src/search/engine.py +0 -241
  383. package/src/search/fusion.py +0 -122
  384. package/src/search/index_loader.py +0 -114
  385. package/src/search/methods.py +0 -162
  386. package/src/search_engine_v2.py +0 -401
  387. package/src/setup_validator.py +0 -482
  388. package/src/subscription_manager.py +0 -391
  389. package/src/tree/__init__.py +0 -59
  390. package/src/tree/builder.py +0 -185
  391. package/src/tree/nodes.py +0 -202
  392. package/src/tree/queries.py +0 -257
  393. package/src/tree/schema.py +0 -80
  394. package/src/tree_manager.py +0 -19
  395. package/src/trust/__init__.py +0 -45
  396. package/src/trust/constants.py +0 -66
  397. package/src/trust/queries.py +0 -157
  398. package/src/trust/schema.py +0 -95
  399. package/src/trust/scorer.py +0 -299
  400. package/src/trust/signals.py +0 -95
  401. package/src/trust_scorer.py +0 -44
  402. package/ui/app.js +0 -1588
  403. package/ui/js/graph-cytoscape-monolithic-backup.js +0 -1168
  404. package/ui/js/graph-cytoscape.js +0 -1168
  405. package/ui/js/graph-d3-backup.js +0 -32
  406. package/ui/js/graph.js +0 -32
  407. package/ui_server.py +0 -286
  408. /package/docs/{ACCESSIBILITY.md → v2-archive/ACCESSIBILITY.md} +0 -0
  409. /package/docs/{ARCHITECTURE.md → v2-archive/ARCHITECTURE.md} +0 -0
  410. /package/docs/{CLI-COMMANDS-REFERENCE.md → v2-archive/CLI-COMMANDS-REFERENCE.md} +0 -0
  411. /package/docs/{COMPRESSION-README.md → v2-archive/COMPRESSION-README.md} +0 -0
  412. /package/docs/{FRAMEWORK-INTEGRATIONS.md → v2-archive/FRAMEWORK-INTEGRATIONS.md} +0 -0
  413. /package/docs/{MCP-MANUAL-SETUP.md → v2-archive/MCP-MANUAL-SETUP.md} +0 -0
  414. /package/docs/{MCP-TROUBLESHOOTING.md → v2-archive/MCP-TROUBLESHOOTING.md} +0 -0
  415. /package/docs/{PATTERN-LEARNING.md → v2-archive/PATTERN-LEARNING.md} +0 -0
  416. /package/docs/{PROFILES-GUIDE.md → v2-archive/PROFILES-GUIDE.md} +0 -0
  417. /package/docs/{RESET-GUIDE.md → v2-archive/RESET-GUIDE.md} +0 -0
  418. /package/docs/{SEARCH-ENGINE-V2.2.0.md → v2-archive/SEARCH-ENGINE-V2.2.0.md} +0 -0
  419. /package/docs/{SEARCH-INTEGRATION-GUIDE.md → v2-archive/SEARCH-INTEGRATION-GUIDE.md} +0 -0
  420. /package/docs/{UI-SERVER.md → v2-archive/UI-SERVER.md} +0 -0
  421. /package/docs/{UNIVERSAL-INTEGRATION.md → v2-archive/UNIVERSAL-INTEGRATION.md} +0 -0
  422. /package/docs/{V2.2.0-OPTIONAL-SEARCH.md → v2-archive/V2.2.0-OPTIONAL-SEARCH.md} +0 -0
  423. /package/docs/{WINDOWS-INSTALL-README.txt → v2-archive/WINDOWS-INSTALL-README.txt} +0 -0
  424. /package/docs/{WINDOWS-POST-INSTALL.txt → v2-archive/WINDOWS-POST-INSTALL.txt} +0 -0
  425. /package/docs/{example_graph_usage.py → v2-archive/example_graph_usage.py} +0 -0
  426. /package/{completions → ide/completions}/slm.bash +0 -0
  427. /package/{completions → ide/completions}/slm.zsh +0 -0
  428. /package/{configs → ide/configs}/cody-commands.json +0 -0
  429. /package/{install-skills.sh → scripts/install-skills.sh} +0 -0
  430. /package/{install.ps1 → scripts/install.ps1} +0 -0
  431. /package/{install.sh → scripts/install.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)