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,217 +0,0 @@
1
- #!/usr/bin/env python3
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
4
- """
5
- Cold storage management for archived memories.
6
- Handles compression and archival to gzipped JSON files.
7
- """
8
-
9
- import sqlite3
10
- import json
11
- import gzip
12
- from datetime import datetime, timedelta
13
- from pathlib import Path
14
- from typing import List, Dict, Optional, Any
15
-
16
- from compression.config import CompressionConfig
17
-
18
-
19
- MEMORY_DIR = Path.home() / ".claude-memory"
20
- DB_PATH = MEMORY_DIR / "memory.db"
21
- COLD_STORAGE_PATH = MEMORY_DIR / "cold-storage"
22
-
23
-
24
- class ColdStorageManager:
25
- """Manage cold storage archives for very old memories."""
26
-
27
- def __init__(self, db_path: Path = DB_PATH, storage_path: Path = COLD_STORAGE_PATH):
28
- self.db_path = db_path
29
- self.storage_path = storage_path
30
- self.storage_path.mkdir(exist_ok=True)
31
- self.config = CompressionConfig()
32
-
33
- def move_to_cold_storage(self, memory_ids: List[int]) -> int:
34
- """
35
- Move archived memories to gzipped JSON file.
36
-
37
- Args:
38
- memory_ids: List of memory IDs to archive
39
-
40
- Returns:
41
- Number of memories archived
42
- """
43
- if not memory_ids:
44
- return 0
45
-
46
- conn = sqlite3.connect(self.db_path)
47
- try:
48
- cursor = conn.cursor()
49
-
50
- # Build placeholders for SQL query
51
- placeholders = ','.join('?' * len(memory_ids))
52
-
53
- # Get memories from archive table
54
- cursor.execute(f'''
55
- SELECT m.id, m.content, m.summary, m.tags, m.project_name,
56
- m.created_at, a.full_content
57
- FROM memories m
58
- LEFT JOIN memory_archive a ON m.id = a.memory_id
59
- WHERE m.id IN ({placeholders})
60
- ''', memory_ids)
61
-
62
- memories = cursor.fetchall()
63
-
64
- if not memories:
65
- return 0
66
-
67
- # Build JSON export
68
- export_data = []
69
-
70
- for memory in memories:
71
- mem_id, content, summary, tags, project_name, created_at, full_content = memory
72
-
73
- export_data.append({
74
- 'id': mem_id,
75
- 'tier3_content': self._safe_json_load(content),
76
- 'summary': summary,
77
- 'tags': self._safe_json_load(tags) if tags else [],
78
- 'project': project_name,
79
- 'created_at': created_at,
80
- 'full_content': full_content # May be None if not archived
81
- })
82
-
83
- # Write to gzipped file
84
- filename = f"archive-{datetime.now().strftime('%Y-%m')}.json.gz"
85
- filepath = self.storage_path / filename
86
-
87
- # If file exists, append to it
88
- existing_data = []
89
- if filepath.exists():
90
- try:
91
- with gzip.open(filepath, 'rt', encoding='utf-8') as f:
92
- existing_data = json.load(f)
93
- except Exception:
94
- pass # File might be corrupted, start fresh
95
-
96
- # Merge with existing data (avoid duplicates)
97
- existing_ids = {item['id'] for item in existing_data}
98
- for item in export_data:
99
- if item['id'] not in existing_ids:
100
- existing_data.append(item)
101
-
102
- # Write combined data
103
- with gzip.open(filepath, 'wt', encoding='utf-8') as f:
104
- json.dump(existing_data, f, indent=2)
105
-
106
- # Delete from archive table (keep Tier 3 version in main table)
107
- cursor.executemany('DELETE FROM memory_archive WHERE memory_id = ?',
108
- [(mid,) for mid in memory_ids])
109
-
110
- conn.commit()
111
- finally:
112
- conn.close()
113
-
114
- return len(export_data)
115
-
116
- def _safe_json_load(self, data: str) -> Any:
117
- """Safely load JSON data."""
118
- try:
119
- return json.loads(data)
120
- except (json.JSONDecodeError, TypeError):
121
- return data
122
-
123
- def restore_from_cold_storage(self, memory_id: int) -> Optional[str]:
124
- """
125
- Restore full content from cold storage archive.
126
-
127
- Args:
128
- memory_id: ID of memory to restore
129
-
130
- Returns:
131
- Full content if found, None otherwise
132
- """
133
- # Search all archive files
134
- for archive_file in self.storage_path.glob('archive-*.json.gz'):
135
- try:
136
- with gzip.open(archive_file, 'rt', encoding='utf-8') as f:
137
- data = json.load(f)
138
-
139
- for memory in data:
140
- if memory['id'] == memory_id:
141
- full_content = memory.get('full_content')
142
-
143
- if full_content:
144
- # Restore to archive table
145
- conn = sqlite3.connect(self.db_path)
146
- try:
147
- cursor = conn.cursor()
148
-
149
- cursor.execute('''
150
- INSERT OR REPLACE INTO memory_archive
151
- (memory_id, full_content, archived_at)
152
- VALUES (?, ?, CURRENT_TIMESTAMP)
153
- ''', (memory_id, full_content))
154
-
155
- conn.commit()
156
- finally:
157
- conn.close()
158
-
159
- return full_content
160
- except Exception as e:
161
- print(f"Error reading archive {archive_file}: {e}")
162
- continue
163
-
164
- return None
165
-
166
- def get_cold_storage_candidates(self) -> List[int]:
167
- """Get memory IDs that are candidates for cold storage."""
168
- threshold_date = datetime.now() - timedelta(days=self.config.cold_storage_threshold_days)
169
-
170
- conn = sqlite3.connect(self.db_path)
171
- try:
172
- cursor = conn.cursor()
173
-
174
- cursor.execute('''
175
- SELECT id FROM memories
176
- WHERE tier = 3
177
- AND created_at < ?
178
- AND importance < 8
179
- ''', (threshold_date.isoformat(),))
180
-
181
- memory_ids = [row[0] for row in cursor.fetchall()]
182
- finally:
183
- conn.close()
184
-
185
- return memory_ids
186
-
187
- def get_cold_storage_stats(self) -> Dict[str, Any]:
188
- """Get statistics about cold storage."""
189
- stats = {
190
- 'archive_count': 0,
191
- 'total_memories': 0,
192
- 'total_size_bytes': 0,
193
- 'archives': []
194
- }
195
-
196
- for archive_file in self.storage_path.glob('archive-*.json.gz'):
197
- try:
198
- size = archive_file.stat().st_size
199
-
200
- with gzip.open(archive_file, 'rt', encoding='utf-8') as f:
201
- data = json.load(f)
202
- memory_count = len(data)
203
-
204
- stats['archive_count'] += 1
205
- stats['total_memories'] += memory_count
206
- stats['total_size_bytes'] += size
207
-
208
- stats['archives'].append({
209
- 'filename': archive_file.name,
210
- 'memory_count': memory_count,
211
- 'size_bytes': size,
212
- 'size_mb': round(size / 1024 / 1024, 2)
213
- })
214
- except Exception:
215
- continue
216
-
217
- return stats
@@ -1,72 +0,0 @@
1
- #!/usr/bin/env python3
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
4
- """
5
- Compression configuration management.
6
- Handles loading and saving compression settings from config.json.
7
- """
8
-
9
- import json
10
- from pathlib import Path
11
- from typing import Dict, Any
12
-
13
-
14
- MEMORY_DIR = Path.home() / ".claude-memory"
15
- CONFIG_PATH = MEMORY_DIR / "config.json"
16
-
17
-
18
- class CompressionConfig:
19
- """Configuration for compression behavior."""
20
-
21
- def __init__(self):
22
- self.config = self._load_config()
23
- self.compression_settings = self.config.get('compression', {})
24
-
25
- def _load_config(self) -> Dict[str, Any]:
26
- """Load configuration from config.json."""
27
- if CONFIG_PATH.exists():
28
- with open(CONFIG_PATH, 'r') as f:
29
- return json.load(f)
30
- return {}
31
-
32
- def save(self):
33
- """Save configuration back to config.json."""
34
- with open(CONFIG_PATH, 'w') as f:
35
- json.dump(self.config, f, indent=2)
36
-
37
- @property
38
- def enabled(self) -> bool:
39
- return self.compression_settings.get('enabled', True)
40
-
41
- @property
42
- def tier2_threshold_days(self) -> int:
43
- return self.compression_settings.get('tier2_threshold_days', 30)
44
-
45
- @property
46
- def tier3_threshold_days(self) -> int:
47
- return self.compression_settings.get('tier3_threshold_days', 90)
48
-
49
- @property
50
- def cold_storage_threshold_days(self) -> int:
51
- return self.compression_settings.get('cold_storage_threshold_days', 365)
52
-
53
- @property
54
- def preserve_high_importance(self) -> bool:
55
- return self.compression_settings.get('preserve_high_importance', True)
56
-
57
- @property
58
- def preserve_recently_accessed(self) -> bool:
59
- return self.compression_settings.get('preserve_recently_accessed', True)
60
-
61
- def initialize_defaults(self):
62
- """Initialize compression settings in config if not present."""
63
- if 'compression' not in self.config:
64
- self.config['compression'] = {
65
- 'enabled': True,
66
- 'tier2_threshold_days': 30,
67
- 'tier3_threshold_days': 90,
68
- 'cold_storage_threshold_days': 365,
69
- 'preserve_high_importance': True,
70
- 'preserve_recently_accessed': True
71
- }
72
- self.save()
@@ -1,133 +0,0 @@
1
- #!/usr/bin/env python3
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
4
- """
5
- Compression orchestrator.
6
- Coordinates classification, compression, and archival operations.
7
- """
8
-
9
- import sqlite3
10
- from datetime import datetime
11
- from pathlib import Path
12
- from typing import Dict, Any
13
-
14
- from compression.config import CompressionConfig
15
- from compression.tier_classifier import TierClassifier
16
- from compression.tier2_compressor import Tier2Compressor
17
- from compression.tier3_compressor import Tier3Compressor
18
- from compression.cold_storage import ColdStorageManager
19
-
20
-
21
- MEMORY_DIR = Path.home() / ".claude-memory"
22
- DB_PATH = MEMORY_DIR / "memory.db"
23
-
24
-
25
- class CompressionOrchestrator:
26
- """Main orchestrator for compression operations."""
27
-
28
- def __init__(self, db_path: Path = DB_PATH):
29
- self.db_path = db_path
30
- self.config = CompressionConfig()
31
- self.classifier = TierClassifier(db_path)
32
- self.tier2_compressor = Tier2Compressor(db_path)
33
- self.tier3_compressor = Tier3Compressor(db_path)
34
- self.cold_storage = ColdStorageManager(db_path)
35
-
36
- def run_full_compression(self) -> Dict[str, Any]:
37
- """
38
- Run full compression cycle: classify, compress, and archive.
39
-
40
- Returns:
41
- Statistics about compression operation
42
- """
43
- if not self.config.enabled:
44
- return {'status': 'disabled', 'message': 'Compression is disabled in config'}
45
-
46
- stats = {
47
- 'started_at': datetime.now().isoformat(),
48
- 'tier_updates': 0,
49
- 'tier2_compressed': 0,
50
- 'tier3_compressed': 0,
51
- 'cold_stored': 0,
52
- 'errors': []
53
- }
54
-
55
- try:
56
- # Step 1: Classify memories into tiers
57
- tier_updates = self.classifier.classify_memories()
58
- stats['tier_updates'] = len(tier_updates)
59
-
60
- # Step 2: Compress Tier 2 memories
61
- stats['tier2_compressed'] = self.tier2_compressor.compress_all_tier2()
62
-
63
- # Step 3: Compress Tier 3 memories
64
- stats['tier3_compressed'] = self.tier3_compressor.compress_all_tier3()
65
-
66
- # Step 4: Move old memories to cold storage
67
- candidates = self.cold_storage.get_cold_storage_candidates()
68
- if candidates:
69
- stats['cold_stored'] = self.cold_storage.move_to_cold_storage(candidates)
70
-
71
- # Get final tier stats
72
- stats['tier_stats'] = self.classifier.get_tier_stats()
73
-
74
- # Calculate space savings
75
- stats['space_savings'] = self._calculate_space_savings()
76
-
77
- except Exception as e:
78
- stats['errors'].append(str(e))
79
-
80
- stats['completed_at'] = datetime.now().isoformat()
81
- return stats
82
-
83
- def _calculate_space_savings(self) -> Dict[str, Any]:
84
- """Calculate estimated space savings from compression."""
85
- conn = sqlite3.connect(self.db_path)
86
- try:
87
- cursor = conn.cursor()
88
-
89
- # Get size of compressed content
90
- cursor.execute('''
91
- SELECT
92
- tier,
93
- COUNT(*) as count,
94
- SUM(LENGTH(content)) as total_size
95
- FROM memories
96
- GROUP BY tier
97
- ''')
98
-
99
- tier_sizes = {}
100
- for tier, count, total_size in cursor.fetchall():
101
- tier_sizes[tier] = {
102
- 'count': count,
103
- 'size_bytes': total_size or 0
104
- }
105
-
106
- # Get size of archived content
107
- cursor.execute('''
108
- SELECT
109
- COUNT(*) as count,
110
- SUM(LENGTH(full_content)) as total_size
111
- FROM memory_archive
112
- ''')
113
- archive_count, archive_size = cursor.fetchone()
114
-
115
- finally:
116
- conn.close()
117
-
118
- # Estimate original size if all were Tier 1
119
- tier1_avg = tier_sizes.get(1, {}).get('size_bytes', 50000) / max(tier_sizes.get(1, {}).get('count', 1), 1)
120
- total_memories = sum(t.get('count', 0) for t in tier_sizes.values())
121
- estimated_original = int(tier1_avg * total_memories)
122
-
123
- current_size = sum(t.get('size_bytes', 0) for t in tier_sizes.values())
124
-
125
- return {
126
- 'estimated_original_bytes': estimated_original,
127
- 'current_size_bytes': current_size,
128
- 'savings_bytes': estimated_original - current_size,
129
- 'savings_percent': round((1 - current_size / max(estimated_original, 1)) * 100, 1),
130
- 'tier_breakdown': tier_sizes,
131
- 'archive_count': archive_count or 0,
132
- 'archive_size_bytes': archive_size or 0
133
- }
@@ -1,228 +0,0 @@
1
- #!/usr/bin/env python3
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
4
- """
5
- Tier 2 compression logic.
6
- Compresses memories to summary + key excerpts format.
7
- """
8
-
9
- import sqlite3
10
- import json
11
- import re
12
- from datetime import datetime
13
- from pathlib import Path
14
- from typing import List
15
-
16
-
17
- MEMORY_DIR = Path.home() / ".claude-memory"
18
- DB_PATH = MEMORY_DIR / "memory.db"
19
-
20
-
21
- class Tier2Compressor:
22
- """Compress memories to summary + key excerpts (Tier 2)."""
23
-
24
- def __init__(self, db_path: Path = DB_PATH):
25
- self.db_path = db_path
26
-
27
- def compress_to_tier2(self, memory_id: int) -> bool:
28
- """
29
- Compress memory to summary + excerpts.
30
-
31
- Args:
32
- memory_id: ID of memory to compress
33
-
34
- Returns:
35
- True if compression succeeded, False otherwise
36
- """
37
- conn = sqlite3.connect(self.db_path)
38
- try:
39
- cursor = conn.cursor()
40
-
41
- # Get full content
42
- cursor.execute('''
43
- SELECT content, summary, tier FROM memories WHERE id = ?
44
- ''', (memory_id,))
45
- result = cursor.fetchone()
46
-
47
- if not result:
48
- return False
49
-
50
- content, existing_summary, current_tier = result
51
-
52
- # Skip if already compressed or in wrong tier
53
- if current_tier != 2:
54
- return False
55
-
56
- # Check if already archived (don't re-compress)
57
- cursor.execute('''
58
- SELECT full_content FROM memory_archive WHERE memory_id = ?
59
- ''', (memory_id,))
60
- if cursor.fetchone():
61
- return True # Already compressed
62
-
63
- # Try to parse as JSON (might already be compressed)
64
- try:
65
- parsed = json.loads(content)
66
- if isinstance(parsed, dict) and 'summary' in parsed:
67
- return True # Already compressed
68
- except (json.JSONDecodeError, TypeError):
69
- pass # Not compressed yet
70
-
71
- # Generate/enhance summary if needed
72
- if not existing_summary or len(existing_summary) < 100:
73
- summary = self._generate_summary(content)
74
- else:
75
- summary = existing_summary
76
-
77
- # Extract key excerpts (important sentences, code blocks, lists)
78
- excerpts = self._extract_key_excerpts(content)
79
-
80
- # Store compressed version
81
- compressed_content = {
82
- 'summary': summary,
83
- 'excerpts': excerpts,
84
- 'original_length': len(content),
85
- 'compressed_at': datetime.now().isoformat()
86
- }
87
-
88
- # Move full content to archive table
89
- cursor.execute('''
90
- INSERT INTO memory_archive (memory_id, full_content, archived_at)
91
- VALUES (?, ?, CURRENT_TIMESTAMP)
92
- ''', (memory_id, content))
93
-
94
- # Update memory with compressed version
95
- cursor.execute('''
96
- UPDATE memories
97
- SET content = ?, tier = 2, updated_at = CURRENT_TIMESTAMP
98
- WHERE id = ?
99
- ''', (json.dumps(compressed_content), memory_id))
100
-
101
- conn.commit()
102
- return True
103
- finally:
104
- conn.close()
105
-
106
- def _generate_summary(self, content: str, max_length: int = 300) -> str:
107
- """
108
- Generate extractive summary from content.
109
- Uses sentence scoring based on heuristics (no external LLM).
110
-
111
- Args:
112
- content: Full content text
113
- max_length: Maximum summary length in characters
114
-
115
- Returns:
116
- Extracted summary
117
- """
118
- # Split into sentences
119
- sentences = re.split(r'[.!?]+', content)
120
-
121
- # Score sentences by importance (simple heuristic)
122
- scored_sentences = []
123
-
124
- for i, sent in enumerate(sentences):
125
- sent = sent.strip()
126
- if len(sent) < 10:
127
- continue
128
-
129
- score = 0
130
-
131
- # Boost if contains tech terms
132
- tech_terms = ['api', 'database', 'auth', 'component', 'function',
133
- 'class', 'method', 'variable', 'error', 'bug', 'fix',
134
- 'implement', 'refactor', 'test', 'deploy']
135
- score += sum(1 for term in tech_terms if term in sent.lower())
136
-
137
- # Boost if at start or end (thesis/conclusion)
138
- if i == 0 or i == len(sentences) - 1:
139
- score += 2
140
-
141
- # Boost if contains numbers/specifics
142
- if re.search(r'\d+', sent):
143
- score += 1
144
-
145
- # Boost if contains important keywords
146
- important_keywords = ['important', 'critical', 'note', 'remember',
147
- 'key', 'main', 'primary', 'must', 'should']
148
- score += sum(2 for kw in important_keywords if kw in sent.lower())
149
-
150
- scored_sentences.append((score, sent))
151
-
152
- # Take top sentences up to max_length
153
- scored_sentences.sort(reverse=True, key=lambda x: x[0])
154
-
155
- summary_parts = []
156
- current_length = 0
157
-
158
- for score, sent in scored_sentences:
159
- if current_length + len(sent) > max_length:
160
- break
161
-
162
- summary_parts.append(sent)
163
- current_length += len(sent)
164
-
165
- if not summary_parts:
166
- # Fallback: take first sentence
167
- return sentences[0][:max_length] if sentences else content[:max_length]
168
-
169
- return '. '.join(summary_parts) + '.'
170
-
171
- def _extract_key_excerpts(self, content: str, max_excerpts: int = 3) -> List[str]:
172
- """
173
- Extract key excerpts (code blocks, lists, important paragraphs).
174
-
175
- Args:
176
- content: Full content text
177
- max_excerpts: Maximum number of excerpts to extract
178
-
179
- Returns:
180
- List of excerpt strings
181
- """
182
- excerpts = []
183
-
184
- # Extract code blocks (markdown or indented)
185
- code_blocks = re.findall(r'```[\s\S]*?```', content)
186
- excerpts.extend(code_blocks[:2]) # Max 2 code blocks
187
-
188
- # Extract bullet lists
189
- list_pattern = r'(?:^|\n)(?:[-*•]|\d+\.)\s+.+(?:\n(?:[-*•]|\d+\.)\s+.+)*'
190
- lists = re.findall(list_pattern, content, re.MULTILINE)
191
- if lists and len(excerpts) < max_excerpts:
192
- excerpts.extend(lists[:1]) # Max 1 list
193
-
194
- # Extract paragraphs with important keywords if we need more
195
- if len(excerpts) < max_excerpts:
196
- paragraphs = content.split('\n\n')
197
- important_keywords = ['important', 'critical', 'note', 'remember', 'key']
198
-
199
- for para in paragraphs:
200
- if len(excerpts) >= max_excerpts:
201
- break
202
-
203
- if any(kw in para.lower() for kw in important_keywords):
204
- # Truncate long paragraphs
205
- if len(para) > 200:
206
- para = para[:197] + '...'
207
- excerpts.append(para)
208
-
209
- # Truncate if too many
210
- return excerpts[:max_excerpts]
211
-
212
- def compress_all_tier2(self) -> int:
213
- """Compress all memories that are in Tier 2."""
214
- conn = sqlite3.connect(self.db_path)
215
- try:
216
- cursor = conn.cursor()
217
-
218
- cursor.execute('SELECT id FROM memories WHERE tier = 2')
219
- memory_ids = [row[0] for row in cursor.fetchall()]
220
- finally:
221
- conn.close()
222
-
223
- compressed_count = 0
224
- for memory_id in memory_ids:
225
- if self.compress_to_tier2(memory_id):
226
- compressed_count += 1
227
-
228
- return compressed_count