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,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