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
@@ -0,0 +1,248 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
3
+ # Licensed under the MIT License - see LICENSE file
4
+ # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
5
+ """
6
+ SuperLocalMemory V3 - FastAPI API Server
7
+ Provides REST endpoints for memory visualization and exploration.
8
+ Uses V3 MemoryEngine for all operations.
9
+ """
10
+
11
+ import json
12
+ import logging
13
+ from pathlib import Path
14
+ from contextlib import asynccontextmanager
15
+ from typing import Optional
16
+
17
+ from fastapi import FastAPI, HTTPException, Query, Request
18
+ from fastapi.staticfiles import StaticFiles
19
+ from fastapi.responses import HTMLResponse
20
+ from fastapi.middleware.cors import CORSMiddleware
21
+ from fastapi.middleware.gzip import GZipMiddleware
22
+ from pydantic import BaseModel
23
+ import uvicorn
24
+
25
+ from superlocalmemory.server.security_middleware import SecurityHeadersMiddleware
26
+
27
+ logger = logging.getLogger("superlocalmemory.api_server")
28
+
29
+ # V3 paths
30
+ MEMORY_DIR = Path.home() / ".superlocalmemory"
31
+ DB_PATH = MEMORY_DIR / "memory.db"
32
+ # ui/ is at repo root, 4 levels up from src/superlocalmemory/server/api.py
33
+ UI_DIR = Path(__file__).resolve().parent.parent.parent.parent / "ui"
34
+
35
+
36
+ # ============================================================================
37
+ # Request/Response Models
38
+ # ============================================================================
39
+
40
+ class SearchRequest(BaseModel):
41
+ query: str
42
+ limit: int = 10
43
+ min_score: float = 0.3
44
+
45
+
46
+ class MemoryFilter(BaseModel):
47
+ category: Optional[str] = None
48
+ project_name: Optional[str] = None
49
+ cluster_id: Optional[int] = None
50
+ min_importance: Optional[int] = None
51
+
52
+
53
+ # ============================================================================
54
+ # V3 Engine Initialization (lifespan context)
55
+ # ============================================================================
56
+
57
+ @asynccontextmanager
58
+ async def lifespan(application: FastAPI):
59
+ """Initialize V3 engine on startup, cleanup on shutdown."""
60
+ try:
61
+ from superlocalmemory.core.config import SLMConfig
62
+ from superlocalmemory.core.engine import MemoryEngine
63
+
64
+ config = SLMConfig.load()
65
+ engine = MemoryEngine(config)
66
+ engine.initialize()
67
+ application.state.engine = engine
68
+ application.state.config = config
69
+ logger.info("V3 MemoryEngine initialized: mode=%s", config.mode.value)
70
+ except Exception as exc:
71
+ logger.warning("V3 engine init failed (API will use fallback): %s", exc)
72
+ application.state.engine = None
73
+ application.state.config = None
74
+
75
+ yield
76
+
77
+ # Cleanup
78
+ if hasattr(application.state, 'engine') and application.state.engine:
79
+ application.state.engine.close()
80
+
81
+
82
+ def create_app() -> FastAPI:
83
+ """Create and configure the FastAPI application."""
84
+ application = FastAPI(
85
+ title="SuperLocalMemory V3 API",
86
+ description="V3 Memory Engine REST API",
87
+ version="3.0.0",
88
+ lifespan=lifespan,
89
+ )
90
+
91
+ # Middleware
92
+ application.add_middleware(SecurityHeadersMiddleware)
93
+ application.add_middleware(GZipMiddleware, minimum_size=1000)
94
+ application.add_middleware(
95
+ CORSMiddleware,
96
+ allow_origins=[
97
+ "http://localhost:8765", "http://127.0.0.1:8765",
98
+ "http://localhost:8417", "http://127.0.0.1:8417",
99
+ ],
100
+ allow_credentials=True,
101
+ allow_methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
102
+ allow_headers=["Content-Type", "Authorization", "X-SLM-API-Key"],
103
+ )
104
+
105
+ # Rate limiting (graceful)
106
+ try:
107
+ from superlocalmemory.infra.rate_limiter import RateLimiter
108
+ _write_limiter = RateLimiter(max_requests=30, window_seconds=60)
109
+ _read_limiter = RateLimiter(max_requests=120, window_seconds=60)
110
+
111
+ @application.middleware("http")
112
+ async def rate_limit_middleware(request, call_next):
113
+ client_ip = request.client.host if request.client else "unknown"
114
+ is_write = request.method in ("POST", "PUT", "DELETE", "PATCH")
115
+ limiter = _write_limiter if is_write else _read_limiter
116
+ allowed, remaining = limiter.is_allowed(client_ip)
117
+ if not allowed:
118
+ from fastapi.responses import JSONResponse
119
+ return JSONResponse(
120
+ status_code=429,
121
+ content={"error": "Too many requests."},
122
+ headers={"Retry-After": str(limiter.window_seconds)},
123
+ )
124
+ response = await call_next(request)
125
+ response.headers["X-RateLimit-Remaining"] = str(remaining)
126
+ return response
127
+ except (ImportError, Exception):
128
+ pass
129
+
130
+ # Auth middleware (graceful)
131
+ try:
132
+ from superlocalmemory.infra.auth_middleware import check_api_key
133
+
134
+ @application.middleware("http")
135
+ async def auth_middleware(request, call_next):
136
+ is_write = request.method in ("POST", "PUT", "DELETE", "PATCH")
137
+ headers = dict(request.headers)
138
+ if not check_api_key(headers, is_write=is_write):
139
+ from fastapi.responses import JSONResponse
140
+ return JSONResponse(
141
+ status_code=401,
142
+ content={"error": "Invalid or missing API key."},
143
+ )
144
+ response = await call_next(request)
145
+ return response
146
+ except (ImportError, Exception):
147
+ pass
148
+
149
+ # Mount static files
150
+ UI_DIR.mkdir(exist_ok=True)
151
+ application.mount("/static", StaticFiles(directory=str(UI_DIR)), name="static")
152
+
153
+ # ========================================================================
154
+ # Register Route Modules
155
+ # ========================================================================
156
+ from superlocalmemory.server.routes.memories import router as memories_router
157
+ from superlocalmemory.server.routes.stats import router as stats_router
158
+ from superlocalmemory.server.routes.profiles import router as profiles_router
159
+ from superlocalmemory.server.routes.backup import router as backup_router
160
+ from superlocalmemory.server.routes.data_io import router as data_io_router
161
+ from superlocalmemory.server.routes.events import router as events_router, register_event_listener
162
+ from superlocalmemory.server.routes.agents import router as agents_router
163
+ from superlocalmemory.server.routes.ws import router as ws_router, manager as ws_manager
164
+ from superlocalmemory.server.routes.v3_api import router as v3_router
165
+
166
+ application.include_router(memories_router)
167
+ application.include_router(stats_router)
168
+ application.include_router(profiles_router)
169
+ application.include_router(backup_router)
170
+ application.include_router(data_io_router)
171
+ application.include_router(events_router)
172
+ application.include_router(agents_router)
173
+ application.include_router(ws_router)
174
+ application.include_router(v3_router)
175
+
176
+ # Graceful optional routers
177
+ for _module_name in ("learning", "lifecycle", "behavioral", "compliance"):
178
+ try:
179
+ _mod = __import__(f"superlocalmemory.server.routes.{_module_name}", fromlist=["router"])
180
+ application.include_router(_mod.router)
181
+ except (ImportError, Exception):
182
+ pass
183
+
184
+ # Wire WebSocket manager
185
+ import superlocalmemory.server.routes.profiles as _profiles_mod
186
+ import superlocalmemory.server.routes.data_io as _data_io_mod
187
+ _profiles_mod.ws_manager = ws_manager
188
+ _data_io_mod.ws_manager = ws_manager
189
+
190
+ # ========================================================================
191
+ # Basic Routes
192
+ # ========================================================================
193
+
194
+ @application.get("/", response_class=HTMLResponse)
195
+ async def root():
196
+ """Serve main UI page."""
197
+ index_path = UI_DIR / "index.html"
198
+ if not index_path.exists():
199
+ return (
200
+ "<html><head><title>SuperLocalMemory V3</title></head>"
201
+ "<body style='font-family:Arial;padding:40px'>"
202
+ "<h1>SuperLocalMemory V3 API Server Running</h1>"
203
+ "<p><a href='/docs'>API Documentation</a></p>"
204
+ "</body></html>"
205
+ )
206
+ return index_path.read_text()
207
+
208
+ @application.get("/health")
209
+ async def health_check():
210
+ """Health check."""
211
+ from datetime import datetime
212
+ engine = application.state.engine
213
+ return {
214
+ "status": "healthy",
215
+ "version": "3.0.0",
216
+ "engine": "initialized" if engine else "unavailable",
217
+ "database": "connected" if DB_PATH.exists() else "missing",
218
+ "timestamp": datetime.now().isoformat(),
219
+ }
220
+
221
+ @application.on_event("startup")
222
+ async def startup_event():
223
+ register_event_listener()
224
+
225
+ return application
226
+
227
+
228
+ app = create_app()
229
+
230
+
231
+ # ============================================================================
232
+ # Server Startup
233
+ # ============================================================================
234
+
235
+ if __name__ == "__main__":
236
+ print("=" * 60)
237
+ print("SuperLocalMemory V3 - API Server")
238
+ print("=" * 60)
239
+ print(f"Database: {DB_PATH}")
240
+ print(f"UI Directory: {UI_DIR}")
241
+ print("=" * 60)
242
+ print("\nStarting server on http://localhost:8000")
243
+ print("API Documentation: http://localhost:8000/docs")
244
+ print("\nPress Ctrl+C to stop\n")
245
+
246
+ uvicorn.run(
247
+ app, host="127.0.0.1", port=8000, log_level="info",
248
+ )
@@ -0,0 +1,4 @@
1
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
+ # Licensed under the MIT License - see LICENSE file
3
+ # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
+ # SuperLocalMemory V3 - API Routes Package
@@ -0,0 +1,107 @@
1
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
+ # Licensed under the MIT License - see LICENSE file
3
+ # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
+ """SuperLocalMemory V3 - Agent Registry + Trust Routes
5
+ - MIT License
6
+
7
+ Routes: /api/agents, /api/agents/stats, /api/trust/stats, /api/trust/signals/{agent_id}
8
+ Uses V3 TrustScorer and core.registry.
9
+ """
10
+ import logging
11
+ from typing import Optional
12
+
13
+ from fastapi import APIRouter, HTTPException, Query, Request
14
+
15
+ from .helpers import DB_PATH
16
+
17
+ logger = logging.getLogger("superlocalmemory.routes.agents")
18
+ router = APIRouter()
19
+
20
+ # Feature flag: V3 trust scorer
21
+ TRUST_AVAILABLE = False
22
+ try:
23
+ from superlocalmemory.trust.scorer import TrustScorer
24
+ TRUST_AVAILABLE = True
25
+ except ImportError:
26
+ pass
27
+
28
+ REGISTRY_AVAILABLE = False
29
+ try:
30
+ from superlocalmemory.core.registry import AgentRegistry
31
+ REGISTRY_AVAILABLE = True
32
+ except ImportError:
33
+ pass
34
+
35
+
36
+ @router.get("/api/agents")
37
+ async def get_agents(
38
+ request: Request,
39
+ protocol: Optional[str] = None,
40
+ limit: int = Query(50, ge=1, le=200),
41
+ ):
42
+ """List registered agents with optional protocol filter."""
43
+ if not REGISTRY_AVAILABLE:
44
+ return {"agents": [], "count": 0, "message": "Agent registry not available"}
45
+ try:
46
+ engine = getattr(request.app.state, "engine", None)
47
+ if engine and hasattr(engine, '_db'):
48
+ registry = AgentRegistry(engine._db)
49
+ agents = registry.list_agents(protocol=protocol, limit=limit)
50
+ stats = registry.get_stats()
51
+ return {"agents": agents, "count": len(agents), "stats": stats}
52
+ return {"agents": [], "count": 0, "message": "Engine not initialized"}
53
+ except Exception as e:
54
+ raise HTTPException(status_code=500, detail=f"Agent registry error: {str(e)}")
55
+
56
+
57
+ @router.get("/api/agents/stats")
58
+ async def get_agent_stats(request: Request):
59
+ """Get agent registry statistics."""
60
+ if not REGISTRY_AVAILABLE:
61
+ return {"total_agents": 0, "message": "Agent registry not available"}
62
+ try:
63
+ engine = getattr(request.app.state, "engine", None)
64
+ if engine and hasattr(engine, '_db'):
65
+ registry = AgentRegistry(engine._db)
66
+ return registry.get_stats()
67
+ return {"total_agents": 0, "message": "Engine not initialized"}
68
+ except Exception as e:
69
+ raise HTTPException(status_code=500, detail=f"Agent stats error: {str(e)}")
70
+
71
+
72
+ @router.get("/api/trust/stats")
73
+ async def get_trust_stats(request: Request):
74
+ """Get trust scoring statistics."""
75
+ if not TRUST_AVAILABLE:
76
+ return {"total_signals": 0, "message": "Trust scorer not available"}
77
+ try:
78
+ engine = getattr(request.app.state, "engine", None)
79
+ if engine and engine._trust_scorer:
80
+ scorer = engine._trust_scorer
81
+ return scorer.get_trust_stats()
82
+ return {"total_signals": 0, "message": "Trust scorer not initialized"}
83
+ except Exception as e:
84
+ raise HTTPException(status_code=500, detail=f"Trust stats error: {str(e)}")
85
+
86
+
87
+ @router.get("/api/trust/signals/{agent_id}")
88
+ async def get_agent_trust_signals(
89
+ request: Request, agent_id: str,
90
+ limit: int = Query(50, ge=1, le=200),
91
+ ):
92
+ """Get trust signal history for a specific agent."""
93
+ if not TRUST_AVAILABLE:
94
+ return {"signals": [], "count": 0}
95
+ try:
96
+ engine = getattr(request.app.state, "engine", None)
97
+ if engine and engine._trust_scorer:
98
+ scorer = engine._trust_scorer
99
+ signals = scorer.get_signals(agent_id, limit=limit)
100
+ score = scorer.get_trust_score(agent_id)
101
+ return {
102
+ "agent_id": agent_id, "trust_score": score,
103
+ "signals": signals, "count": len(signals),
104
+ }
105
+ return {"agent_id": agent_id, "signals": [], "count": 0}
106
+ except Exception as e:
107
+ raise HTTPException(status_code=500, detail=f"Trust signals error: {str(e)}")
@@ -0,0 +1,91 @@
1
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
+ # Licensed under the MIT License - see LICENSE file
3
+ # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
+ """SuperLocalMemory V3 - Backup Routes
5
+ - MIT License
6
+
7
+ Routes: /api/backup/status, /api/backup/create, /api/backup/configure, /api/backup/list
8
+ Uses V3 infra.backup.BackupManager.
9
+ """
10
+ import logging
11
+
12
+ from fastapi import APIRouter, HTTPException
13
+
14
+ from .helpers import BackupConfigRequest, DB_PATH, MEMORY_DIR
15
+
16
+ logger = logging.getLogger("superlocalmemory.routes.backup")
17
+ router = APIRouter()
18
+
19
+ # Feature flag
20
+ BACKUP_AVAILABLE = False
21
+ try:
22
+ from superlocalmemory.infra.backup import BackupManager
23
+ BACKUP_AVAILABLE = True
24
+ except ImportError:
25
+ pass
26
+
27
+
28
+ def _get_backup_manager() -> "BackupManager":
29
+ """Get V3 backup manager instance."""
30
+ return BackupManager(db_path=DB_PATH, base_dir=MEMORY_DIR)
31
+
32
+
33
+ @router.get("/api/backup/status")
34
+ async def backup_status():
35
+ """Get auto-backup system status."""
36
+ if not BACKUP_AVAILABLE:
37
+ return {"status": "not_implemented", "message": "Backup module not available"}
38
+ try:
39
+ manager = _get_backup_manager()
40
+ return manager.get_status()
41
+ except Exception as e:
42
+ raise HTTPException(status_code=500, detail=f"Backup status error: {str(e)}")
43
+
44
+
45
+ @router.post("/api/backup/create")
46
+ async def backup_create():
47
+ """Create a manual backup immediately."""
48
+ if not BACKUP_AVAILABLE:
49
+ return {"success": False, "message": "Backup module not available"}
50
+ try:
51
+ manager = _get_backup_manager()
52
+ filename = manager.create_backup(label='manual')
53
+ if filename:
54
+ return {
55
+ "success": True, "filename": str(filename),
56
+ "message": f"Backup created: {filename}",
57
+ "status": manager.get_status(),
58
+ }
59
+ return {"success": False, "message": "Backup failed"}
60
+ except Exception as e:
61
+ raise HTTPException(status_code=500, detail=f"Backup create error: {str(e)}")
62
+
63
+
64
+ @router.post("/api/backup/configure")
65
+ async def backup_configure(request: BackupConfigRequest):
66
+ """Update auto-backup configuration."""
67
+ if not BACKUP_AVAILABLE:
68
+ return {"success": False, "message": "Backup module not available"}
69
+ try:
70
+ manager = _get_backup_manager()
71
+ result = manager.configure(
72
+ interval_hours=request.interval_hours,
73
+ max_backups=request.max_backups,
74
+ enabled=request.enabled,
75
+ )
76
+ return {"success": True, "message": "Backup configuration updated", "status": result}
77
+ except Exception as e:
78
+ raise HTTPException(status_code=500, detail=f"Backup configure error: {str(e)}")
79
+
80
+
81
+ @router.get("/api/backup/list")
82
+ async def backup_list():
83
+ """List all available backups."""
84
+ if not BACKUP_AVAILABLE:
85
+ return {"backups": [], "count": 0, "message": "Backup module not available"}
86
+ try:
87
+ manager = _get_backup_manager()
88
+ backups = manager.list_backups()
89
+ return {"backups": backups, "count": len(backups)}
90
+ except Exception as e:
91
+ raise HTTPException(status_code=500, detail=f"Backup list error: {str(e)}")
@@ -0,0 +1,127 @@
1
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
+ # Licensed under the MIT License - see LICENSE file
3
+ # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
+ """SuperLocalMemory V3 - Behavioral Routes
5
+ - MIT License
6
+
7
+ Routes: /api/behavioral/status, /api/behavioral/report-outcome
8
+ Uses V3 learning.behavioral.BehavioralPatternStore and learning.outcomes.OutcomeTracker.
9
+ """
10
+ import json
11
+ import logging
12
+
13
+ from fastapi import APIRouter
14
+
15
+ from .helpers import get_active_profile, MEMORY_DIR
16
+
17
+ logger = logging.getLogger("superlocalmemory.routes.behavioral")
18
+ router = APIRouter()
19
+
20
+ LEARNING_DB = MEMORY_DIR / "learning.db"
21
+
22
+ # Feature detection
23
+ BEHAVIORAL_AVAILABLE = False
24
+ try:
25
+ from superlocalmemory.learning.behavioral import BehavioralPatternStore
26
+ from superlocalmemory.learning.outcomes import OutcomeTracker
27
+ BEHAVIORAL_AVAILABLE = True
28
+ except ImportError:
29
+ logger.info("V3 behavioral engine not available")
30
+
31
+
32
+ @router.get("/api/behavioral/status")
33
+ async def behavioral_status():
34
+ """Get behavioral learning status for active profile."""
35
+ if not BEHAVIORAL_AVAILABLE:
36
+ return {"available": False, "message": "Behavioral engine not available"}
37
+
38
+ try:
39
+ profile = get_active_profile()
40
+ db_path = str(LEARNING_DB)
41
+
42
+ # Outcomes
43
+ total_outcomes = 0
44
+ outcome_breakdown = {"success": 0, "failure": 0, "partial": 0}
45
+ recent_outcomes = []
46
+ try:
47
+ tracker = OutcomeTracker(db_path)
48
+ total_outcomes = tracker.get_outcome_count(profile=profile)
49
+ outcome_breakdown = tracker.get_outcome_breakdown(profile=profile)
50
+ recent_outcomes = tracker.get_recent_outcomes(profile=profile, limit=20)
51
+ except Exception as exc:
52
+ logger.debug("outcome tracker: %s", exc)
53
+
54
+ # Patterns
55
+ patterns = []
56
+ cross_project_transfers = 0
57
+ try:
58
+ store = BehavioralPatternStore(db_path)
59
+ patterns = store.get_patterns(profile=profile)
60
+ cross_project_transfers = store.get_cross_project_count(profile=profile)
61
+ except Exception as exc:
62
+ logger.debug("pattern store: %s", exc)
63
+
64
+ return {
65
+ "available": True,
66
+ "active_profile": profile,
67
+ "total_outcomes": total_outcomes,
68
+ "outcome_breakdown": outcome_breakdown,
69
+ "patterns": patterns,
70
+ "cross_project_transfers": cross_project_transfers,
71
+ "recent_outcomes": recent_outcomes,
72
+ }
73
+ except Exception as e:
74
+ logger.error("behavioral_status error: %s", e)
75
+ return {"available": False, "error": str(e)}
76
+
77
+
78
+ @router.post("/api/behavioral/report-outcome")
79
+ async def report_outcome(data: dict):
80
+ """Record an action outcome for behavioral learning.
81
+
82
+ Body: {
83
+ memory_ids: [str, ...],
84
+ outcome: "success" | "failure" | "partial",
85
+ action_type: str (optional),
86
+ context: str (optional)
87
+ }
88
+ """
89
+ if not BEHAVIORAL_AVAILABLE:
90
+ return {"success": False, "error": "Behavioral engine not available"}
91
+
92
+ memory_ids = data.get('memory_ids')
93
+ outcome = data.get('outcome')
94
+ action_type = data.get('action_type', 'other')
95
+ context_note = data.get('context', '')
96
+
97
+ if not memory_ids or not isinstance(memory_ids, list):
98
+ return {"success": False, "error": "memory_ids must be a non-empty list"}
99
+
100
+ valid_outcomes = ("success", "failure", "partial")
101
+ if outcome not in valid_outcomes:
102
+ return {"success": False, "error": f"outcome must be one of: {valid_outcomes}"}
103
+
104
+ try:
105
+ profile = get_active_profile()
106
+ tracker = OutcomeTracker(str(LEARNING_DB))
107
+
108
+ context_dict = {"note": context_note} if context_note else {}
109
+ row_id = tracker.record_outcome(
110
+ memory_ids=memory_ids,
111
+ outcome=outcome,
112
+ action_type=action_type,
113
+ context=context_dict,
114
+ project=profile,
115
+ )
116
+
117
+ if row_id is None:
118
+ return {"success": False, "error": "Failed to record outcome"}
119
+
120
+ return {
121
+ "success": True, "outcome_id": row_id,
122
+ "active_profile": profile,
123
+ "message": f"Recorded {outcome} outcome for {len(memory_ids)} memories",
124
+ }
125
+ except Exception as e:
126
+ logger.error("report_outcome error: %s", e)
127
+ return {"success": False, "error": str(e)}