superlocalmemory 2.8.6 → 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.
- package/LICENSE +9 -1
- package/NOTICE +63 -0
- package/README.md +165 -480
- package/bin/slm +17 -449
- package/bin/slm-npm +1 -1
- package/conftest.py +5 -0
- package/docs/api-reference.md +284 -0
- package/docs/architecture.md +149 -0
- package/docs/auto-memory.md +150 -0
- package/docs/cli-reference.md +276 -0
- package/docs/compliance.md +191 -0
- package/docs/configuration.md +182 -0
- package/docs/getting-started.md +102 -0
- package/docs/ide-setup.md +261 -0
- package/docs/mcp-tools.md +220 -0
- package/docs/migration-from-v2.md +170 -0
- package/docs/profiles.md +173 -0
- package/docs/troubleshooting.md +310 -0
- package/{configs → ide/configs}/antigravity-mcp.json +3 -3
- package/ide/configs/chatgpt-desktop-mcp.json +16 -0
- package/{configs → ide/configs}/claude-desktop-mcp.json +3 -3
- package/{configs → ide/configs}/codex-mcp.toml +4 -4
- package/{configs → ide/configs}/continue-mcp.yaml +4 -3
- package/{configs → ide/configs}/continue-skills.yaml +6 -6
- package/ide/configs/cursor-mcp.json +15 -0
- package/{configs → ide/configs}/gemini-cli-mcp.json +2 -2
- package/{configs → ide/configs}/jetbrains-mcp.json +2 -2
- package/{configs → ide/configs}/opencode-mcp.json +2 -2
- package/{configs → ide/configs}/perplexity-mcp.json +2 -2
- package/{configs → ide/configs}/vscode-copilot-mcp.json +2 -2
- package/{configs → ide/configs}/windsurf-mcp.json +3 -3
- package/{configs → ide/configs}/zed-mcp.json +2 -2
- package/{hooks → ide/hooks}/context-hook.js +9 -20
- package/ide/hooks/memory-list-skill.js +70 -0
- package/ide/hooks/memory-profile-skill.js +101 -0
- package/ide/hooks/memory-recall-skill.js +62 -0
- package/ide/hooks/memory-remember-skill.js +68 -0
- package/ide/hooks/memory-reset-skill.js +160 -0
- package/{hooks → ide/hooks}/post-recall-hook.js +2 -2
- package/ide/integrations/langchain/README.md +106 -0
- package/ide/integrations/langchain/langchain_superlocalmemory/__init__.py +9 -0
- package/ide/integrations/langchain/langchain_superlocalmemory/chat_message_history.py +201 -0
- package/ide/integrations/langchain/pyproject.toml +38 -0
- package/{src/learning → ide/integrations/langchain}/tests/__init__.py +1 -0
- package/ide/integrations/langchain/tests/test_chat_message_history.py +215 -0
- package/ide/integrations/langchain/tests/test_security.py +117 -0
- package/ide/integrations/llamaindex/README.md +81 -0
- package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/__init__.py +9 -0
- package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/base.py +316 -0
- package/ide/integrations/llamaindex/pyproject.toml +43 -0
- package/{src/lifecycle → ide/integrations/llamaindex}/tests/__init__.py +1 -2
- package/ide/integrations/llamaindex/tests/test_chat_store.py +294 -0
- package/ide/integrations/llamaindex/tests/test_security.py +241 -0
- package/{skills → ide/skills}/slm-build-graph/SKILL.md +6 -6
- package/{skills → ide/skills}/slm-list-recent/SKILL.md +5 -5
- package/{skills → ide/skills}/slm-recall/SKILL.md +5 -5
- package/{skills → ide/skills}/slm-remember/SKILL.md +6 -6
- package/{skills → ide/skills}/slm-show-patterns/SKILL.md +7 -7
- package/{skills → ide/skills}/slm-status/SKILL.md +9 -9
- package/{skills → ide/skills}/slm-switch-profile/SKILL.md +9 -9
- package/package.json +13 -22
- package/pyproject.toml +85 -0
- package/scripts/build-dmg.sh +417 -0
- package/scripts/install-skills.ps1 +334 -0
- package/scripts/postinstall.js +2 -2
- package/scripts/start-dashboard.ps1 +52 -0
- package/scripts/start-dashboard.sh +41 -0
- package/scripts/sync-wiki.ps1 +127 -0
- package/scripts/sync-wiki.sh +82 -0
- package/scripts/test-dmg.sh +161 -0
- package/scripts/test-npm-package.ps1 +252 -0
- package/scripts/test-npm-package.sh +207 -0
- package/scripts/verify-install.ps1 +294 -0
- package/scripts/verify-install.sh +266 -0
- package/src/superlocalmemory/__init__.py +0 -0
- package/src/superlocalmemory/attribution/__init__.py +9 -0
- package/src/superlocalmemory/attribution/mathematical_dna.py +235 -0
- package/src/superlocalmemory/attribution/signer.py +153 -0
- package/src/superlocalmemory/attribution/watermark.py +189 -0
- package/src/superlocalmemory/cli/__init__.py +5 -0
- package/src/superlocalmemory/cli/commands.py +245 -0
- package/src/superlocalmemory/cli/main.py +89 -0
- package/src/superlocalmemory/cli/migrate_cmd.py +55 -0
- package/src/superlocalmemory/cli/post_install.py +99 -0
- package/src/superlocalmemory/cli/setup_wizard.py +129 -0
- package/src/superlocalmemory/compliance/__init__.py +0 -0
- package/src/superlocalmemory/compliance/abac.py +204 -0
- package/src/superlocalmemory/compliance/audit.py +314 -0
- package/src/superlocalmemory/compliance/eu_ai_act.py +131 -0
- package/src/superlocalmemory/compliance/gdpr.py +294 -0
- package/src/superlocalmemory/compliance/lifecycle.py +158 -0
- package/src/superlocalmemory/compliance/retention.py +232 -0
- package/src/superlocalmemory/compliance/scheduler.py +148 -0
- package/src/superlocalmemory/core/__init__.py +0 -0
- package/src/superlocalmemory/core/config.py +391 -0
- package/src/superlocalmemory/core/embeddings.py +293 -0
- package/src/superlocalmemory/core/engine.py +701 -0
- package/src/superlocalmemory/core/hooks.py +65 -0
- package/src/superlocalmemory/core/maintenance.py +172 -0
- package/src/superlocalmemory/core/modes.py +140 -0
- package/src/superlocalmemory/core/profiles.py +234 -0
- package/src/superlocalmemory/core/registry.py +117 -0
- package/src/superlocalmemory/dynamics/__init__.py +0 -0
- package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +223 -0
- package/src/superlocalmemory/encoding/__init__.py +0 -0
- package/src/superlocalmemory/encoding/consolidator.py +485 -0
- package/src/superlocalmemory/encoding/emotional.py +125 -0
- package/src/superlocalmemory/encoding/entity_resolver.py +525 -0
- package/src/superlocalmemory/encoding/entropy_gate.py +104 -0
- package/src/superlocalmemory/encoding/fact_extractor.py +775 -0
- package/src/superlocalmemory/encoding/foresight.py +91 -0
- package/src/superlocalmemory/encoding/graph_builder.py +302 -0
- package/src/superlocalmemory/encoding/observation_builder.py +160 -0
- package/src/superlocalmemory/encoding/scene_builder.py +183 -0
- package/src/superlocalmemory/encoding/signal_inference.py +90 -0
- package/src/superlocalmemory/encoding/temporal_parser.py +426 -0
- package/src/superlocalmemory/encoding/type_router.py +235 -0
- package/src/superlocalmemory/hooks/__init__.py +3 -0
- package/src/superlocalmemory/hooks/auto_capture.py +111 -0
- package/src/superlocalmemory/hooks/auto_recall.py +93 -0
- package/src/superlocalmemory/hooks/ide_connector.py +204 -0
- package/src/superlocalmemory/hooks/rules_engine.py +99 -0
- package/src/superlocalmemory/infra/__init__.py +3 -0
- package/src/superlocalmemory/infra/auth_middleware.py +82 -0
- package/src/superlocalmemory/infra/backup.py +317 -0
- package/src/superlocalmemory/infra/cache_manager.py +267 -0
- package/src/superlocalmemory/infra/event_bus.py +381 -0
- package/src/superlocalmemory/infra/rate_limiter.py +135 -0
- package/src/{webhook_dispatcher.py → superlocalmemory/infra/webhook_dispatcher.py} +104 -101
- package/src/superlocalmemory/learning/__init__.py +0 -0
- package/src/superlocalmemory/learning/adaptive.py +172 -0
- package/src/superlocalmemory/learning/behavioral.py +490 -0
- package/src/superlocalmemory/learning/behavioral_listener.py +94 -0
- package/src/superlocalmemory/learning/bootstrap.py +298 -0
- package/src/superlocalmemory/learning/cross_project.py +399 -0
- package/src/superlocalmemory/learning/database.py +376 -0
- package/src/superlocalmemory/learning/engagement.py +323 -0
- package/src/superlocalmemory/learning/features.py +138 -0
- package/src/superlocalmemory/learning/feedback.py +316 -0
- package/src/superlocalmemory/learning/outcomes.py +255 -0
- package/src/superlocalmemory/learning/project_context.py +366 -0
- package/src/superlocalmemory/learning/ranker.py +155 -0
- package/src/superlocalmemory/learning/source_quality.py +303 -0
- package/src/superlocalmemory/learning/workflows.py +309 -0
- package/src/superlocalmemory/llm/__init__.py +0 -0
- package/src/superlocalmemory/llm/backbone.py +316 -0
- package/src/superlocalmemory/math/__init__.py +0 -0
- package/src/superlocalmemory/math/fisher.py +356 -0
- package/src/superlocalmemory/math/langevin.py +398 -0
- package/src/superlocalmemory/math/sheaf.py +257 -0
- package/src/superlocalmemory/mcp/__init__.py +0 -0
- package/src/superlocalmemory/mcp/resources.py +245 -0
- package/src/superlocalmemory/mcp/server.py +61 -0
- package/src/superlocalmemory/mcp/tools.py +18 -0
- package/src/superlocalmemory/mcp/tools_core.py +305 -0
- package/src/superlocalmemory/mcp/tools_v28.py +223 -0
- package/src/superlocalmemory/mcp/tools_v3.py +286 -0
- package/src/superlocalmemory/retrieval/__init__.py +0 -0
- package/src/superlocalmemory/retrieval/agentic.py +295 -0
- package/src/superlocalmemory/retrieval/ann_index.py +223 -0
- package/src/superlocalmemory/retrieval/bm25_channel.py +185 -0
- package/src/superlocalmemory/retrieval/bridge_discovery.py +170 -0
- package/src/superlocalmemory/retrieval/engine.py +390 -0
- package/src/superlocalmemory/retrieval/entity_channel.py +179 -0
- package/src/superlocalmemory/retrieval/fusion.py +78 -0
- package/src/superlocalmemory/retrieval/profile_channel.py +105 -0
- package/src/superlocalmemory/retrieval/reranker.py +154 -0
- package/src/superlocalmemory/retrieval/semantic_channel.py +232 -0
- package/src/superlocalmemory/retrieval/strategy.py +96 -0
- package/src/superlocalmemory/retrieval/temporal_channel.py +175 -0
- package/src/superlocalmemory/server/__init__.py +1 -0
- package/src/superlocalmemory/server/api.py +248 -0
- package/src/superlocalmemory/server/routes/__init__.py +4 -0
- package/src/superlocalmemory/server/routes/agents.py +107 -0
- package/src/superlocalmemory/server/routes/backup.py +91 -0
- package/src/superlocalmemory/server/routes/behavioral.py +127 -0
- package/src/superlocalmemory/server/routes/compliance.py +160 -0
- package/src/superlocalmemory/server/routes/data_io.py +188 -0
- package/src/superlocalmemory/server/routes/events.py +183 -0
- package/src/superlocalmemory/server/routes/helpers.py +85 -0
- package/src/superlocalmemory/server/routes/learning.py +273 -0
- package/src/superlocalmemory/server/routes/lifecycle.py +116 -0
- package/src/superlocalmemory/server/routes/memories.py +399 -0
- package/src/superlocalmemory/server/routes/profiles.py +219 -0
- package/src/superlocalmemory/server/routes/stats.py +346 -0
- package/src/superlocalmemory/server/routes/v3_api.py +365 -0
- package/src/superlocalmemory/server/routes/ws.py +82 -0
- package/src/superlocalmemory/server/security_middleware.py +57 -0
- package/src/superlocalmemory/server/ui.py +245 -0
- package/src/superlocalmemory/storage/__init__.py +0 -0
- package/src/superlocalmemory/storage/access_control.py +182 -0
- package/src/superlocalmemory/storage/database.py +594 -0
- package/src/superlocalmemory/storage/migrations.py +303 -0
- package/src/superlocalmemory/storage/models.py +406 -0
- package/src/superlocalmemory/storage/schema.py +726 -0
- package/src/superlocalmemory/storage/v2_migrator.py +317 -0
- package/src/superlocalmemory/trust/__init__.py +0 -0
- package/src/superlocalmemory/trust/gate.py +130 -0
- package/src/superlocalmemory/trust/provenance.py +124 -0
- package/src/superlocalmemory/trust/scorer.py +347 -0
- package/src/superlocalmemory/trust/signals.py +153 -0
- package/ui/index.html +278 -5
- package/ui/js/auto-settings.js +70 -0
- package/ui/js/dashboard.js +90 -0
- package/ui/js/fact-detail.js +92 -0
- package/ui/js/feedback.js +2 -2
- package/ui/js/ide-status.js +102 -0
- package/ui/js/math-health.js +98 -0
- package/ui/js/recall-lab.js +127 -0
- package/ui/js/settings.js +2 -2
- package/ui/js/trust-dashboard.js +73 -0
- package/api_server.py +0 -724
- package/bin/aider-smart +0 -72
- package/bin/superlocalmemoryv2-learning +0 -4
- package/bin/superlocalmemoryv2-list +0 -3
- package/bin/superlocalmemoryv2-patterns +0 -4
- package/bin/superlocalmemoryv2-profile +0 -3
- package/bin/superlocalmemoryv2-recall +0 -3
- package/bin/superlocalmemoryv2-remember +0 -3
- package/bin/superlocalmemoryv2-reset +0 -3
- package/bin/superlocalmemoryv2-status +0 -3
- package/configs/chatgpt-desktop-mcp.json +0 -16
- package/configs/cursor-mcp.json +0 -15
- package/hooks/memory-list-skill.js +0 -139
- package/hooks/memory-profile-skill.js +0 -273
- package/hooks/memory-recall-skill.js +0 -114
- package/hooks/memory-remember-skill.js +0 -127
- package/hooks/memory-reset-skill.js +0 -274
- package/mcp_server.py +0 -1808
- package/requirements-core.txt +0 -22
- package/requirements-learning.txt +0 -12
- package/requirements.txt +0 -12
- package/src/agent_registry.py +0 -411
- package/src/auth_middleware.py +0 -61
- package/src/auto_backup.py +0 -459
- package/src/behavioral/__init__.py +0 -49
- package/src/behavioral/behavioral_listener.py +0 -203
- package/src/behavioral/behavioral_patterns.py +0 -275
- package/src/behavioral/cross_project_transfer.py +0 -206
- package/src/behavioral/outcome_inference.py +0 -194
- package/src/behavioral/outcome_tracker.py +0 -193
- package/src/behavioral/tests/__init__.py +0 -4
- package/src/behavioral/tests/test_behavioral_integration.py +0 -108
- package/src/behavioral/tests/test_behavioral_patterns.py +0 -150
- package/src/behavioral/tests/test_cross_project_transfer.py +0 -142
- package/src/behavioral/tests/test_mcp_behavioral.py +0 -139
- package/src/behavioral/tests/test_mcp_report_outcome.py +0 -117
- package/src/behavioral/tests/test_outcome_inference.py +0 -107
- package/src/behavioral/tests/test_outcome_tracker.py +0 -96
- package/src/cache_manager.py +0 -518
- package/src/compliance/__init__.py +0 -48
- package/src/compliance/abac_engine.py +0 -149
- package/src/compliance/abac_middleware.py +0 -116
- package/src/compliance/audit_db.py +0 -215
- package/src/compliance/audit_logger.py +0 -148
- package/src/compliance/retention_manager.py +0 -289
- package/src/compliance/retention_scheduler.py +0 -186
- package/src/compliance/tests/__init__.py +0 -4
- package/src/compliance/tests/test_abac_enforcement.py +0 -95
- package/src/compliance/tests/test_abac_engine.py +0 -124
- package/src/compliance/tests/test_abac_mcp_integration.py +0 -118
- package/src/compliance/tests/test_audit_db.py +0 -123
- package/src/compliance/tests/test_audit_logger.py +0 -98
- package/src/compliance/tests/test_mcp_audit.py +0 -128
- package/src/compliance/tests/test_mcp_retention_policy.py +0 -125
- package/src/compliance/tests/test_retention_manager.py +0 -131
- package/src/compliance/tests/test_retention_scheduler.py +0 -99
- package/src/compression/__init__.py +0 -25
- package/src/compression/cli.py +0 -150
- package/src/compression/cold_storage.py +0 -217
- package/src/compression/config.py +0 -72
- package/src/compression/orchestrator.py +0 -133
- package/src/compression/tier2_compressor.py +0 -228
- package/src/compression/tier3_compressor.py +0 -153
- package/src/compression/tier_classifier.py +0 -148
- package/src/db_connection_manager.py +0 -536
- package/src/embedding_engine.py +0 -63
- package/src/embeddings/__init__.py +0 -47
- package/src/embeddings/cache.py +0 -70
- package/src/embeddings/cli.py +0 -113
- package/src/embeddings/constants.py +0 -47
- package/src/embeddings/database.py +0 -91
- package/src/embeddings/engine.py +0 -247
- package/src/embeddings/model_loader.py +0 -145
- package/src/event_bus.py +0 -562
- package/src/graph/__init__.py +0 -36
- package/src/graph/build_helpers.py +0 -74
- package/src/graph/cli.py +0 -87
- package/src/graph/cluster_builder.py +0 -188
- package/src/graph/cluster_summary.py +0 -148
- package/src/graph/constants.py +0 -47
- package/src/graph/edge_builder.py +0 -162
- package/src/graph/entity_extractor.py +0 -95
- package/src/graph/graph_core.py +0 -226
- package/src/graph/graph_search.py +0 -231
- package/src/graph/hierarchical.py +0 -207
- package/src/graph/schema.py +0 -99
- package/src/graph_engine.py +0 -52
- package/src/hnsw_index.py +0 -628
- package/src/hybrid_search.py +0 -46
- package/src/learning/__init__.py +0 -217
- package/src/learning/adaptive_ranker.py +0 -682
- package/src/learning/bootstrap/__init__.py +0 -69
- package/src/learning/bootstrap/constants.py +0 -93
- package/src/learning/bootstrap/db_queries.py +0 -316
- package/src/learning/bootstrap/sampling.py +0 -82
- package/src/learning/bootstrap/text_utils.py +0 -71
- package/src/learning/cross_project_aggregator.py +0 -857
- package/src/learning/db/__init__.py +0 -40
- package/src/learning/db/constants.py +0 -44
- package/src/learning/db/schema.py +0 -279
- package/src/learning/engagement_tracker.py +0 -628
- package/src/learning/feature_extractor.py +0 -708
- package/src/learning/feedback_collector.py +0 -806
- package/src/learning/learning_db.py +0 -915
- package/src/learning/project_context_manager.py +0 -572
- package/src/learning/ranking/__init__.py +0 -33
- package/src/learning/ranking/constants.py +0 -84
- package/src/learning/ranking/helpers.py +0 -278
- package/src/learning/source_quality_scorer.py +0 -676
- package/src/learning/synthetic_bootstrap.py +0 -755
- package/src/learning/tests/test_adaptive_ranker.py +0 -325
- package/src/learning/tests/test_adaptive_ranker_v28.py +0 -60
- package/src/learning/tests/test_aggregator.py +0 -306
- package/src/learning/tests/test_auto_retrain_v28.py +0 -35
- package/src/learning/tests/test_e2e_ranking_v28.py +0 -82
- package/src/learning/tests/test_feature_extractor_v28.py +0 -93
- package/src/learning/tests/test_feedback_collector.py +0 -294
- package/src/learning/tests/test_learning_db.py +0 -602
- package/src/learning/tests/test_learning_db_v28.py +0 -110
- package/src/learning/tests/test_learning_init_v28.py +0 -48
- package/src/learning/tests/test_outcome_signals.py +0 -48
- package/src/learning/tests/test_project_context.py +0 -292
- package/src/learning/tests/test_schema_migration.py +0 -319
- package/src/learning/tests/test_signal_inference.py +0 -397
- package/src/learning/tests/test_source_quality.py +0 -351
- package/src/learning/tests/test_synthetic_bootstrap.py +0 -429
- package/src/learning/tests/test_workflow_miner.py +0 -318
- package/src/learning/workflow_pattern_miner.py +0 -655
- package/src/lifecycle/__init__.py +0 -54
- package/src/lifecycle/bounded_growth.py +0 -239
- package/src/lifecycle/compaction_engine.py +0 -226
- package/src/lifecycle/lifecycle_engine.py +0 -355
- package/src/lifecycle/lifecycle_evaluator.py +0 -257
- package/src/lifecycle/lifecycle_scheduler.py +0 -130
- package/src/lifecycle/retention_policy.py +0 -285
- package/src/lifecycle/tests/test_bounded_growth.py +0 -193
- package/src/lifecycle/tests/test_compaction.py +0 -179
- package/src/lifecycle/tests/test_lifecycle_engine.py +0 -137
- package/src/lifecycle/tests/test_lifecycle_evaluation.py +0 -177
- package/src/lifecycle/tests/test_lifecycle_scheduler.py +0 -127
- package/src/lifecycle/tests/test_lifecycle_search.py +0 -109
- package/src/lifecycle/tests/test_mcp_compact.py +0 -149
- package/src/lifecycle/tests/test_mcp_lifecycle_status.py +0 -114
- package/src/lifecycle/tests/test_retention_policy.py +0 -162
- package/src/mcp_tools_v28.py +0 -281
- package/src/memory/__init__.py +0 -36
- package/src/memory/cli.py +0 -205
- package/src/memory/constants.py +0 -39
- package/src/memory/helpers.py +0 -28
- package/src/memory/schema.py +0 -166
- package/src/memory-profiles.py +0 -595
- package/src/memory-reset.py +0 -491
- package/src/memory_compression.py +0 -989
- package/src/memory_store_v2.py +0 -1155
- package/src/migrate_v1_to_v2.py +0 -629
- package/src/pattern_learner.py +0 -34
- package/src/patterns/__init__.py +0 -24
- package/src/patterns/analyzers.py +0 -251
- package/src/patterns/learner.py +0 -271
- package/src/patterns/scoring.py +0 -171
- package/src/patterns/store.py +0 -225
- package/src/patterns/terminology.py +0 -140
- package/src/provenance_tracker.py +0 -312
- package/src/qualixar_attribution.py +0 -139
- package/src/qualixar_watermark.py +0 -78
- package/src/query_optimizer.py +0 -511
- package/src/rate_limiter.py +0 -83
- package/src/search/__init__.py +0 -20
- package/src/search/cli.py +0 -77
- package/src/search/constants.py +0 -26
- package/src/search/engine.py +0 -241
- package/src/search/fusion.py +0 -122
- package/src/search/index_loader.py +0 -114
- package/src/search/methods.py +0 -162
- package/src/search_engine_v2.py +0 -401
- package/src/setup_validator.py +0 -482
- package/src/subscription_manager.py +0 -391
- package/src/tree/__init__.py +0 -59
- package/src/tree/builder.py +0 -185
- package/src/tree/nodes.py +0 -202
- package/src/tree/queries.py +0 -257
- package/src/tree/schema.py +0 -80
- package/src/tree_manager.py +0 -19
- package/src/trust/__init__.py +0 -45
- package/src/trust/constants.py +0 -66
- package/src/trust/queries.py +0 -157
- package/src/trust/schema.py +0 -95
- package/src/trust/scorer.py +0 -299
- package/src/trust/signals.py +0 -95
- package/src/trust_scorer.py +0 -44
- package/ui/app.js +0 -1588
- package/ui/js/graph-cytoscape-monolithic-backup.js +0 -1168
- package/ui/js/graph-cytoscape.js +0 -1168
- package/ui/js/graph-d3-backup.js +0 -32
- package/ui/js/graph.js +0 -32
- package/ui_server.py +0 -286
- /package/docs/{ACCESSIBILITY.md → v2-archive/ACCESSIBILITY.md} +0 -0
- /package/docs/{ARCHITECTURE.md → v2-archive/ARCHITECTURE.md} +0 -0
- /package/docs/{CLI-COMMANDS-REFERENCE.md → v2-archive/CLI-COMMANDS-REFERENCE.md} +0 -0
- /package/docs/{COMPRESSION-README.md → v2-archive/COMPRESSION-README.md} +0 -0
- /package/docs/{FRAMEWORK-INTEGRATIONS.md → v2-archive/FRAMEWORK-INTEGRATIONS.md} +0 -0
- /package/docs/{MCP-MANUAL-SETUP.md → v2-archive/MCP-MANUAL-SETUP.md} +0 -0
- /package/docs/{MCP-TROUBLESHOOTING.md → v2-archive/MCP-TROUBLESHOOTING.md} +0 -0
- /package/docs/{PATTERN-LEARNING.md → v2-archive/PATTERN-LEARNING.md} +0 -0
- /package/docs/{PROFILES-GUIDE.md → v2-archive/PROFILES-GUIDE.md} +0 -0
- /package/docs/{RESET-GUIDE.md → v2-archive/RESET-GUIDE.md} +0 -0
- /package/docs/{SEARCH-ENGINE-V2.2.0.md → v2-archive/SEARCH-ENGINE-V2.2.0.md} +0 -0
- /package/docs/{SEARCH-INTEGRATION-GUIDE.md → v2-archive/SEARCH-INTEGRATION-GUIDE.md} +0 -0
- /package/docs/{UI-SERVER.md → v2-archive/UI-SERVER.md} +0 -0
- /package/docs/{UNIVERSAL-INTEGRATION.md → v2-archive/UNIVERSAL-INTEGRATION.md} +0 -0
- /package/docs/{V2.2.0-OPTIONAL-SEARCH.md → v2-archive/V2.2.0-OPTIONAL-SEARCH.md} +0 -0
- /package/docs/{WINDOWS-INSTALL-README.txt → v2-archive/WINDOWS-INSTALL-README.txt} +0 -0
- /package/docs/{WINDOWS-POST-INSTALL.txt → v2-archive/WINDOWS-POST-INSTALL.txt} +0 -0
- /package/docs/{example_graph_usage.py → v2-archive/example_graph_usage.py} +0 -0
- /package/{completions → ide/completions}/slm.bash +0 -0
- /package/{completions → ide/completions}/slm.zsh +0 -0
- /package/{configs → ide/configs}/cody-commands.json +0 -0
- /package/{install-skills.sh → scripts/install-skills.sh} +0 -0
- /package/{install.ps1 → scripts/install.ps1} +0 -0
- /package/{install.sh → scripts/install.sh} +0 -0
|
@@ -0,0 +1,245 @@
|
|
|
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
|
+
|
|
5
|
+
"""SuperLocalMemory V3 — MCP Resources (6 resources).
|
|
6
|
+
|
|
7
|
+
slm://recent, slm://stats, slm://clusters, slm://identity,
|
|
8
|
+
slm://learning, slm://engagement.
|
|
9
|
+
|
|
10
|
+
Part of Qualixar | Author: Varun Pratap Bhardwaj
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
import logging
|
|
17
|
+
from typing import Callable
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def register_resources(server, get_engine: Callable) -> None:
|
|
23
|
+
"""Register 6 MCP resources on *server*."""
|
|
24
|
+
|
|
25
|
+
# ------------------------------------------------------------------
|
|
26
|
+
# 1. slm://recent
|
|
27
|
+
# ------------------------------------------------------------------
|
|
28
|
+
@server.resource("slm://recent")
|
|
29
|
+
async def recent_memories() -> str:
|
|
30
|
+
"""Recent memories summary.
|
|
31
|
+
|
|
32
|
+
Returns a plain-text summary of the 20 most recent facts
|
|
33
|
+
stored in the active profile.
|
|
34
|
+
"""
|
|
35
|
+
try:
|
|
36
|
+
engine = get_engine()
|
|
37
|
+
pid = engine.profile_id
|
|
38
|
+
facts = engine._db.get_all_facts(pid)[:20]
|
|
39
|
+
if not facts:
|
|
40
|
+
return "No memories stored yet."
|
|
41
|
+
lines = [f"Recent memories for profile '{pid}' ({len(facts)} shown):"]
|
|
42
|
+
for f in facts:
|
|
43
|
+
preview = f.content[:100].replace("\n", " ")
|
|
44
|
+
lines.append(
|
|
45
|
+
f" [{f.fact_type.value}] {preview} "
|
|
46
|
+
f"(id={f.fact_id}, {f.created_at[:10]})"
|
|
47
|
+
)
|
|
48
|
+
return "\n".join(lines)
|
|
49
|
+
except Exception as exc:
|
|
50
|
+
return f"Error loading recent memories: {exc}"
|
|
51
|
+
|
|
52
|
+
# ------------------------------------------------------------------
|
|
53
|
+
# 2. slm://stats
|
|
54
|
+
# ------------------------------------------------------------------
|
|
55
|
+
@server.resource("slm://stats")
|
|
56
|
+
async def stats() -> str:
|
|
57
|
+
"""Memory system statistics.
|
|
58
|
+
|
|
59
|
+
Returns a text summary of fact counts, entity counts,
|
|
60
|
+
edge counts, and storage breakdown by type.
|
|
61
|
+
"""
|
|
62
|
+
try:
|
|
63
|
+
engine = get_engine()
|
|
64
|
+
pid = engine.profile_id
|
|
65
|
+
fact_count = engine._db.get_fact_count(pid)
|
|
66
|
+
|
|
67
|
+
entity_rows = engine._db.execute(
|
|
68
|
+
"SELECT COUNT(*) AS c FROM canonical_entities WHERE profile_id = ?",
|
|
69
|
+
(pid,),
|
|
70
|
+
)
|
|
71
|
+
entity_count = int(dict(entity_rows[0])["c"]) if entity_rows else 0
|
|
72
|
+
|
|
73
|
+
edge_rows = engine._db.execute(
|
|
74
|
+
"SELECT COUNT(*) AS c FROM graph_edges WHERE profile_id = ?",
|
|
75
|
+
(pid,),
|
|
76
|
+
)
|
|
77
|
+
edge_count = int(dict(edge_rows[0])["c"]) if edge_rows else 0
|
|
78
|
+
|
|
79
|
+
scene_rows = engine._db.execute(
|
|
80
|
+
"SELECT COUNT(*) AS c FROM memory_scenes WHERE profile_id = ?",
|
|
81
|
+
(pid,),
|
|
82
|
+
)
|
|
83
|
+
scene_count = int(dict(scene_rows[0])["c"]) if scene_rows else 0
|
|
84
|
+
|
|
85
|
+
lines = [
|
|
86
|
+
f"SuperLocalMemory V3 Statistics (profile: {pid})",
|
|
87
|
+
f" Mode: {engine._config.mode.value.upper()}",
|
|
88
|
+
f" Facts: {fact_count}",
|
|
89
|
+
f" Entities: {entity_count}",
|
|
90
|
+
f" Edges: {edge_count}",
|
|
91
|
+
f" Scenes: {scene_count}",
|
|
92
|
+
]
|
|
93
|
+
return "\n".join(lines)
|
|
94
|
+
except Exception as exc:
|
|
95
|
+
return f"Error loading stats: {exc}"
|
|
96
|
+
|
|
97
|
+
# ------------------------------------------------------------------
|
|
98
|
+
# 3. slm://clusters
|
|
99
|
+
# ------------------------------------------------------------------
|
|
100
|
+
@server.resource("slm://clusters")
|
|
101
|
+
async def clusters() -> str:
|
|
102
|
+
"""Memory scene clusters.
|
|
103
|
+
|
|
104
|
+
Returns a summary of memory scenes (topic clusters)
|
|
105
|
+
with their themes and fact counts.
|
|
106
|
+
"""
|
|
107
|
+
try:
|
|
108
|
+
engine = get_engine()
|
|
109
|
+
pid = engine.profile_id
|
|
110
|
+
scenes = engine._db.get_all_scenes(pid)
|
|
111
|
+
if not scenes:
|
|
112
|
+
return "No memory scenes/clusters formed yet."
|
|
113
|
+
lines = [f"Memory Scenes ({len(scenes)} clusters):"]
|
|
114
|
+
for s in scenes[:30]:
|
|
115
|
+
theme = s.theme[:80] if s.theme else "(no theme)"
|
|
116
|
+
lines.append(
|
|
117
|
+
f" [{s.scene_id[:8]}] {theme} "
|
|
118
|
+
f"({len(s.fact_ids)} facts, {len(s.entity_ids)} entities)"
|
|
119
|
+
)
|
|
120
|
+
return "\n".join(lines)
|
|
121
|
+
except Exception as exc:
|
|
122
|
+
return f"Error loading clusters: {exc}"
|
|
123
|
+
|
|
124
|
+
# ------------------------------------------------------------------
|
|
125
|
+
# 4. slm://identity
|
|
126
|
+
# ------------------------------------------------------------------
|
|
127
|
+
@server.resource("slm://identity")
|
|
128
|
+
async def coding_identity() -> str:
|
|
129
|
+
"""Active profile identity and coding context.
|
|
130
|
+
|
|
131
|
+
Returns profile name, personality description, mode, and
|
|
132
|
+
top entities with fact counts for context-aware assistance.
|
|
133
|
+
"""
|
|
134
|
+
try:
|
|
135
|
+
engine = get_engine()
|
|
136
|
+
pid = engine.profile_id
|
|
137
|
+
mode = engine._config.mode.value.upper()
|
|
138
|
+
|
|
139
|
+
# Top entities by fact count
|
|
140
|
+
entity_rows = engine._db.execute(
|
|
141
|
+
"SELECT canonical_name, fact_count FROM canonical_entities "
|
|
142
|
+
"WHERE profile_id = ? ORDER BY fact_count DESC LIMIT 10",
|
|
143
|
+
(pid,),
|
|
144
|
+
)
|
|
145
|
+
entities = [
|
|
146
|
+
f"{dict(r)['canonical_name']} ({dict(r)['fact_count']} facts)"
|
|
147
|
+
for r in entity_rows
|
|
148
|
+
]
|
|
149
|
+
|
|
150
|
+
lines = [
|
|
151
|
+
f"Profile: {pid}",
|
|
152
|
+
f"Mode: {mode}",
|
|
153
|
+
f"Top entities: {', '.join(entities) if entities else 'none yet'}",
|
|
154
|
+
]
|
|
155
|
+
return "\n".join(lines)
|
|
156
|
+
except Exception as exc:
|
|
157
|
+
return f"Error loading identity: {exc}"
|
|
158
|
+
|
|
159
|
+
# ------------------------------------------------------------------
|
|
160
|
+
# 5. slm://learning
|
|
161
|
+
# ------------------------------------------------------------------
|
|
162
|
+
@server.resource("slm://learning")
|
|
163
|
+
async def learning_status() -> str:
|
|
164
|
+
"""Learning system status.
|
|
165
|
+
|
|
166
|
+
Returns adaptive learning health, pattern summary, and
|
|
167
|
+
outcome tracking statistics.
|
|
168
|
+
"""
|
|
169
|
+
try:
|
|
170
|
+
engine = get_engine()
|
|
171
|
+
pid = engine.profile_id
|
|
172
|
+
|
|
173
|
+
# Behavioral patterns summary
|
|
174
|
+
try:
|
|
175
|
+
from superlocalmemory.learning.behavioral import BehavioralStore
|
|
176
|
+
store = BehavioralStore(engine._db.db_path)
|
|
177
|
+
summary = store.get_summary(pid)
|
|
178
|
+
except Exception:
|
|
179
|
+
summary = {}
|
|
180
|
+
|
|
181
|
+
# Outcome stats
|
|
182
|
+
try:
|
|
183
|
+
outcome_rows = engine._db.execute(
|
|
184
|
+
"SELECT outcome, COUNT(*) AS c FROM action_outcomes "
|
|
185
|
+
"WHERE profile_id = ? GROUP BY outcome",
|
|
186
|
+
(pid,),
|
|
187
|
+
)
|
|
188
|
+
outcomes = {dict(r)["outcome"]: dict(r)["c"] for r in outcome_rows}
|
|
189
|
+
except Exception:
|
|
190
|
+
outcomes = {}
|
|
191
|
+
|
|
192
|
+
lines = [
|
|
193
|
+
f"Learning Status (profile: {pid})",
|
|
194
|
+
f" Behavioral patterns: {json.dumps(summary) if summary else 'none detected'}",
|
|
195
|
+
f" Outcome tracking: {json.dumps(outcomes) if outcomes else 'no outcomes recorded'}",
|
|
196
|
+
]
|
|
197
|
+
return "\n".join(lines)
|
|
198
|
+
except Exception as exc:
|
|
199
|
+
return f"Error loading learning status: {exc}"
|
|
200
|
+
|
|
201
|
+
# ------------------------------------------------------------------
|
|
202
|
+
# 6. slm://engagement
|
|
203
|
+
# ------------------------------------------------------------------
|
|
204
|
+
@server.resource("slm://engagement")
|
|
205
|
+
async def engagement() -> str:
|
|
206
|
+
"""Engagement metrics.
|
|
207
|
+
|
|
208
|
+
Returns memory usage activity: recent stores, recalls,
|
|
209
|
+
and top-accessed facts.
|
|
210
|
+
"""
|
|
211
|
+
try:
|
|
212
|
+
engine = get_engine()
|
|
213
|
+
pid = engine.profile_id
|
|
214
|
+
|
|
215
|
+
# Recent activity via audit trail
|
|
216
|
+
try:
|
|
217
|
+
audit_rows = engine._db.execute(
|
|
218
|
+
"SELECT action, COUNT(*) AS c FROM compliance_audit "
|
|
219
|
+
"WHERE profile_id = ? GROUP BY action",
|
|
220
|
+
(pid,),
|
|
221
|
+
)
|
|
222
|
+
activity = {dict(r)["action"]: dict(r)["c"] for r in audit_rows}
|
|
223
|
+
except Exception:
|
|
224
|
+
activity = {}
|
|
225
|
+
|
|
226
|
+
# Top-accessed facts
|
|
227
|
+
top_rows = engine._db.execute(
|
|
228
|
+
"SELECT fact_id, content, access_count FROM atomic_facts "
|
|
229
|
+
"WHERE profile_id = ? AND access_count > 0 "
|
|
230
|
+
"ORDER BY access_count DESC LIMIT 5",
|
|
231
|
+
(pid,),
|
|
232
|
+
)
|
|
233
|
+
top_facts = [
|
|
234
|
+
f"{dict(r)['content'][:60]}... (accessed {dict(r)['access_count']}x)"
|
|
235
|
+
for r in top_rows
|
|
236
|
+
]
|
|
237
|
+
|
|
238
|
+
lines = [
|
|
239
|
+
f"Engagement (profile: {pid})",
|
|
240
|
+
f" Activity: {json.dumps(activity) if activity else 'no activity'}",
|
|
241
|
+
f" Top facts: {'; '.join(top_facts) if top_facts else 'none accessed'}",
|
|
242
|
+
]
|
|
243
|
+
return "\n".join(lines)
|
|
244
|
+
except Exception as exc:
|
|
245
|
+
return f"Error loading engagement: {exc}"
|
|
@@ -0,0 +1,61 @@
|
|
|
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
|
+
|
|
5
|
+
"""SuperLocalMemory V3 — MCP Server.
|
|
6
|
+
|
|
7
|
+
Clean MCP server calling V3 MemoryEngine. Supports all MCP-compatible IDEs.
|
|
8
|
+
|
|
9
|
+
Part of Qualixar | Author: Varun Pratap Bhardwaj
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
from mcp.server.fastmcp import FastMCP
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
server = FastMCP("SuperLocalMemory V3")
|
|
22
|
+
|
|
23
|
+
# Lazy engine singleton -------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
_engine = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_engine():
|
|
29
|
+
"""Return (or create) the singleton MemoryEngine."""
|
|
30
|
+
global _engine
|
|
31
|
+
if _engine is None:
|
|
32
|
+
from superlocalmemory.core.config import SLMConfig
|
|
33
|
+
from superlocalmemory.core.engine import MemoryEngine
|
|
34
|
+
|
|
35
|
+
config = SLMConfig.load()
|
|
36
|
+
_engine = MemoryEngine(config)
|
|
37
|
+
_engine.initialize()
|
|
38
|
+
return _engine
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def reset_engine():
|
|
42
|
+
"""Reset engine singleton (for testing or mode switch)."""
|
|
43
|
+
global _engine
|
|
44
|
+
_engine = None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# Register all tools and resources --------------------------------------------
|
|
48
|
+
|
|
49
|
+
from superlocalmemory.mcp.tools_core import register_core_tools
|
|
50
|
+
from superlocalmemory.mcp.tools_v28 import register_v28_tools
|
|
51
|
+
from superlocalmemory.mcp.tools_v3 import register_v3_tools
|
|
52
|
+
from superlocalmemory.mcp.resources import register_resources
|
|
53
|
+
|
|
54
|
+
register_core_tools(server, get_engine)
|
|
55
|
+
register_v28_tools(server, get_engine)
|
|
56
|
+
register_v3_tools(server, get_engine)
|
|
57
|
+
register_resources(server, get_engine)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
if __name__ == "__main__":
|
|
61
|
+
server.run(transport="stdio")
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
+
|
|
5
|
+
"""Backward compatibility — tools are now split across sub-modules.
|
|
6
|
+
|
|
7
|
+
tools_core: 13 core tools (remember, recall, search, etc.)
|
|
8
|
+
tools_v28: 6 V2.8-ported tools (report_outcome, lifecycle, audit, etc.)
|
|
9
|
+
tools_v3: 5 V3-only tools (set_mode, health, consistency, recall_trace)
|
|
10
|
+
|
|
11
|
+
Part of Qualixar | Author: Varun Pratap Bhardwaj
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from superlocalmemory.mcp.tools_core import register_core_tools
|
|
15
|
+
from superlocalmemory.mcp.tools_v28 import register_v28_tools
|
|
16
|
+
from superlocalmemory.mcp.tools_v3 import register_v3_tools
|
|
17
|
+
|
|
18
|
+
__all__ = ["register_core_tools", "register_v28_tools", "register_v3_tools"]
|
|
@@ -0,0 +1,305 @@
|
|
|
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
|
+
|
|
5
|
+
"""SuperLocalMemory V3 — Core MCP Tools (13 tools).
|
|
6
|
+
|
|
7
|
+
remember, recall, search, fetch, list_recent, get_status, build_graph,
|
|
8
|
+
switch_profile, backup_status, memory_used, get_learned_patterns,
|
|
9
|
+
correct_pattern, get_attribution.
|
|
10
|
+
|
|
11
|
+
Part of Qualixar | Author: Varun Pratap Bhardwaj
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
import logging
|
|
18
|
+
from typing import Any, Callable
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def register_core_tools(server, get_engine: Callable) -> None:
|
|
24
|
+
"""Register the 13 core MCP tools on *server*."""
|
|
25
|
+
|
|
26
|
+
@server.tool()
|
|
27
|
+
async def remember(
|
|
28
|
+
content: str, tags: str = "", project: str = "",
|
|
29
|
+
importance: int = 5, session_id: str = "",
|
|
30
|
+
agent_id: str = "mcp_client",
|
|
31
|
+
) -> dict:
|
|
32
|
+
"""Store content to memory with intelligent indexing.
|
|
33
|
+
|
|
34
|
+
Extracts atomic facts, resolves entities, builds graph edges,
|
|
35
|
+
and indexes for 4-channel retrieval.
|
|
36
|
+
"""
|
|
37
|
+
try:
|
|
38
|
+
engine = get_engine()
|
|
39
|
+
metadata: dict[str, Any] = {"tags": tags, "project": project, "importance": importance, "agent_id": agent_id}
|
|
40
|
+
fact_ids = engine.store(content, session_id=session_id, metadata=metadata)
|
|
41
|
+
return {"success": True, "fact_ids": fact_ids, "count": len(fact_ids)}
|
|
42
|
+
except Exception as exc:
|
|
43
|
+
logger.exception("remember failed")
|
|
44
|
+
return {"success": False, "error": str(exc)}
|
|
45
|
+
|
|
46
|
+
@server.tool()
|
|
47
|
+
async def recall(query: str, limit: int = 10, agent_id: str = "mcp_client") -> dict:
|
|
48
|
+
"""Search memories by semantic query with 4-channel retrieval, RRF fusion, and reranking."""
|
|
49
|
+
try:
|
|
50
|
+
engine = get_engine()
|
|
51
|
+
response = engine.recall(query, limit=limit)
|
|
52
|
+
results = _format_results(response.results[:limit])
|
|
53
|
+
return {"success": True, "results": results, "count": len(results), "query_type": response.query_type}
|
|
54
|
+
except Exception as exc:
|
|
55
|
+
logger.exception("recall failed")
|
|
56
|
+
return {"success": False, "error": str(exc)}
|
|
57
|
+
|
|
58
|
+
@server.tool()
|
|
59
|
+
async def search(query: str, limit: int = 10, profile_id: str = "") -> dict:
|
|
60
|
+
"""Full-text search across memories using FTS5 with BM25 ranking."""
|
|
61
|
+
try:
|
|
62
|
+
engine = get_engine()
|
|
63
|
+
pid = profile_id or engine.profile_id
|
|
64
|
+
facts = engine._db.search_facts_fts(query, pid, limit=limit)
|
|
65
|
+
items = []
|
|
66
|
+
for f in facts:
|
|
67
|
+
items.append({
|
|
68
|
+
"fact_id": f.fact_id,
|
|
69
|
+
"content": f.content,
|
|
70
|
+
"fact_type": f.fact_type.value,
|
|
71
|
+
"confidence": round(f.confidence, 3),
|
|
72
|
+
"date": f.observation_date,
|
|
73
|
+
})
|
|
74
|
+
return {"success": True, "results": items, "count": len(items)}
|
|
75
|
+
except Exception as exc:
|
|
76
|
+
logger.exception("search failed")
|
|
77
|
+
return {"success": False, "error": str(exc)}
|
|
78
|
+
|
|
79
|
+
@server.tool()
|
|
80
|
+
async def fetch(fact_ids: str) -> dict:
|
|
81
|
+
"""Fetch full details for specific fact IDs (comma-separated)."""
|
|
82
|
+
try:
|
|
83
|
+
engine = get_engine()
|
|
84
|
+
ids = [fid.strip() for fid in fact_ids.split(",") if fid.strip()]
|
|
85
|
+
facts = engine._db.get_facts_by_ids(ids, engine.profile_id)
|
|
86
|
+
items = []
|
|
87
|
+
for f in facts:
|
|
88
|
+
items.append({
|
|
89
|
+
"fact_id": f.fact_id,
|
|
90
|
+
"content": f.content,
|
|
91
|
+
"fact_type": f.fact_type.value,
|
|
92
|
+
"entities": f.canonical_entities,
|
|
93
|
+
"confidence": round(f.confidence, 3),
|
|
94
|
+
"importance": round(f.importance, 3),
|
|
95
|
+
"observation_date": f.observation_date,
|
|
96
|
+
"referenced_date": f.referenced_date,
|
|
97
|
+
"lifecycle": f.lifecycle.value,
|
|
98
|
+
"access_count": f.access_count,
|
|
99
|
+
})
|
|
100
|
+
return {"success": True, "results": items, "count": len(items)}
|
|
101
|
+
except Exception as exc:
|
|
102
|
+
logger.exception("fetch failed")
|
|
103
|
+
return {"success": False, "error": str(exc)}
|
|
104
|
+
|
|
105
|
+
@server.tool()
|
|
106
|
+
async def list_recent(limit: int = 20, profile_id: str = "") -> dict:
|
|
107
|
+
"""List most recently stored memories, newest first."""
|
|
108
|
+
try:
|
|
109
|
+
engine = get_engine()
|
|
110
|
+
pid = profile_id or engine.profile_id
|
|
111
|
+
facts = engine._db.get_all_facts(pid)[:limit]
|
|
112
|
+
items = []
|
|
113
|
+
for f in facts:
|
|
114
|
+
items.append({
|
|
115
|
+
"fact_id": f.fact_id,
|
|
116
|
+
"content": f.content[:120],
|
|
117
|
+
"fact_type": f.fact_type.value,
|
|
118
|
+
"created_at": f.created_at,
|
|
119
|
+
"session_id": f.session_id,
|
|
120
|
+
})
|
|
121
|
+
return {"success": True, "results": items, "count": len(items)}
|
|
122
|
+
except Exception as exc:
|
|
123
|
+
logger.exception("list_recent failed")
|
|
124
|
+
return {"success": False, "error": str(exc)}
|
|
125
|
+
|
|
126
|
+
@server.tool()
|
|
127
|
+
async def get_status() -> dict:
|
|
128
|
+
"""Get memory system status: fact count, entity count, mode, profile, db size."""
|
|
129
|
+
try:
|
|
130
|
+
engine = get_engine()
|
|
131
|
+
pid = engine.profile_id
|
|
132
|
+
fact_count = engine._db.get_fact_count(pid)
|
|
133
|
+
entities = engine._db.execute(
|
|
134
|
+
"SELECT COUNT(*) AS c FROM canonical_entities WHERE profile_id = ?",
|
|
135
|
+
(pid,),
|
|
136
|
+
)
|
|
137
|
+
entity_count = int(dict(entities[0])["c"]) if entities else 0
|
|
138
|
+
edges = engine._db.execute(
|
|
139
|
+
"SELECT COUNT(*) AS c FROM graph_edges WHERE profile_id = ?",
|
|
140
|
+
(pid,),
|
|
141
|
+
)
|
|
142
|
+
edge_count = int(dict(edges[0])["c"]) if edges else 0
|
|
143
|
+
|
|
144
|
+
import os
|
|
145
|
+
db_size_mb = 0.0
|
|
146
|
+
db_path = engine._db.db_path
|
|
147
|
+
if db_path.exists():
|
|
148
|
+
db_size_mb = round(os.path.getsize(db_path) / (1024 * 1024), 2)
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
"success": True,
|
|
152
|
+
"mode": engine._config.mode.value,
|
|
153
|
+
"profile": pid,
|
|
154
|
+
"fact_count": fact_count,
|
|
155
|
+
"entity_count": entity_count,
|
|
156
|
+
"edge_count": edge_count,
|
|
157
|
+
"db_size_mb": db_size_mb,
|
|
158
|
+
}
|
|
159
|
+
except Exception as exc:
|
|
160
|
+
logger.exception("get_status failed")
|
|
161
|
+
return {"success": False, "error": str(exc)}
|
|
162
|
+
|
|
163
|
+
@server.tool()
|
|
164
|
+
async def build_graph(profile_id: str = "") -> dict:
|
|
165
|
+
"""Rebuild knowledge graph edges for all facts in the active profile."""
|
|
166
|
+
try:
|
|
167
|
+
engine = get_engine()
|
|
168
|
+
pid = profile_id or engine.profile_id
|
|
169
|
+
facts = engine._db.get_all_facts(pid)
|
|
170
|
+
edge_count = 0
|
|
171
|
+
for fact in facts:
|
|
172
|
+
if engine._graph_builder:
|
|
173
|
+
engine._graph_builder.build_edges(fact, pid)
|
|
174
|
+
edge_count += 1
|
|
175
|
+
return {
|
|
176
|
+
"success": True,
|
|
177
|
+
"facts_processed": len(facts),
|
|
178
|
+
"edges_built": edge_count,
|
|
179
|
+
}
|
|
180
|
+
except Exception as exc:
|
|
181
|
+
logger.exception("build_graph failed")
|
|
182
|
+
return {"success": False, "error": str(exc)}
|
|
183
|
+
|
|
184
|
+
@server.tool()
|
|
185
|
+
async def switch_profile(profile_id: str) -> dict:
|
|
186
|
+
"""Switch the active memory profile. All operations scope to this profile."""
|
|
187
|
+
try:
|
|
188
|
+
engine = get_engine()
|
|
189
|
+
old = engine.profile_id
|
|
190
|
+
engine.profile_id = profile_id
|
|
191
|
+
return {
|
|
192
|
+
"success": True,
|
|
193
|
+
"previous_profile": old,
|
|
194
|
+
"current_profile": profile_id,
|
|
195
|
+
}
|
|
196
|
+
except Exception as exc:
|
|
197
|
+
logger.exception("switch_profile failed")
|
|
198
|
+
return {"success": False, "error": str(exc)}
|
|
199
|
+
|
|
200
|
+
@server.tool()
|
|
201
|
+
async def backup_status() -> dict:
|
|
202
|
+
"""Get backup system status, last backup time, and available backup files."""
|
|
203
|
+
try:
|
|
204
|
+
engine = get_engine()
|
|
205
|
+
from superlocalmemory.infra.backup import BackupManager
|
|
206
|
+
bm = BackupManager(engine._config.base_dir, engine._db.db_path)
|
|
207
|
+
return {"success": True, **bm.get_status()}
|
|
208
|
+
except Exception as exc:
|
|
209
|
+
logger.exception("backup_status failed")
|
|
210
|
+
return {"success": False, "error": str(exc)}
|
|
211
|
+
|
|
212
|
+
@server.tool()
|
|
213
|
+
async def memory_used() -> dict:
|
|
214
|
+
"""Get memory usage breakdown by fact type and lifecycle state."""
|
|
215
|
+
try:
|
|
216
|
+
engine = get_engine()
|
|
217
|
+
pid = engine.profile_id
|
|
218
|
+
facts = engine._db.get_all_facts(pid)
|
|
219
|
+
by_type: dict[str, int] = {}
|
|
220
|
+
by_lifecycle: dict[str, int] = {}
|
|
221
|
+
for f in facts:
|
|
222
|
+
by_type[f.fact_type.value] = by_type.get(f.fact_type.value, 0) + 1
|
|
223
|
+
by_lifecycle[f.lifecycle.value] = (
|
|
224
|
+
by_lifecycle.get(f.lifecycle.value, 0) + 1
|
|
225
|
+
)
|
|
226
|
+
return {
|
|
227
|
+
"success": True,
|
|
228
|
+
"total_facts": len(facts),
|
|
229
|
+
"by_type": by_type,
|
|
230
|
+
"by_lifecycle": by_lifecycle,
|
|
231
|
+
"profile": pid,
|
|
232
|
+
}
|
|
233
|
+
except Exception as exc:
|
|
234
|
+
logger.exception("memory_used failed")
|
|
235
|
+
return {"success": False, "error": str(exc)}
|
|
236
|
+
|
|
237
|
+
@server.tool()
|
|
238
|
+
async def get_learned_patterns(pattern_type: str = "", limit: int = 20) -> dict:
|
|
239
|
+
"""Get learned behavioral patterns (interests, refinements, archival habits)."""
|
|
240
|
+
try:
|
|
241
|
+
engine = get_engine()
|
|
242
|
+
from superlocalmemory.learning.behavioral import BehavioralStore
|
|
243
|
+
store = BehavioralStore(engine._db.db_path)
|
|
244
|
+
ptype = pattern_type if pattern_type else None
|
|
245
|
+
patterns = store.get_patterns(
|
|
246
|
+
engine.profile_id, pattern_type=ptype, limit=limit,
|
|
247
|
+
)
|
|
248
|
+
return {"success": True, "patterns": patterns, "count": len(patterns)}
|
|
249
|
+
except Exception as exc:
|
|
250
|
+
logger.exception("get_learned_patterns failed")
|
|
251
|
+
return {"success": False, "error": str(exc)}
|
|
252
|
+
|
|
253
|
+
@server.tool()
|
|
254
|
+
async def correct_pattern(pattern_id: str, correction: str) -> dict:
|
|
255
|
+
"""Correct or annotate a learned behavioral pattern to improve retrieval."""
|
|
256
|
+
try:
|
|
257
|
+
engine = get_engine()
|
|
258
|
+
from superlocalmemory.learning.behavioral import BehavioralStore
|
|
259
|
+
store = BehavioralStore(engine._db.db_path)
|
|
260
|
+
store.record(
|
|
261
|
+
engine.profile_id,
|
|
262
|
+
pattern_type="correction",
|
|
263
|
+
pattern_key=pattern_id,
|
|
264
|
+
metadata={"correction": correction},
|
|
265
|
+
)
|
|
266
|
+
return {"success": True, "pattern_id": pattern_id}
|
|
267
|
+
except Exception as exc:
|
|
268
|
+
logger.exception("correct_pattern failed")
|
|
269
|
+
return {"success": False, "error": str(exc)}
|
|
270
|
+
|
|
271
|
+
@server.tool()
|
|
272
|
+
async def get_attribution() -> dict:
|
|
273
|
+
"""Get system attribution: author, version, license, and provenance metadata."""
|
|
274
|
+
return {
|
|
275
|
+
"success": True,
|
|
276
|
+
"product": "SuperLocalMemory V3",
|
|
277
|
+
"author": "Varun Pratap Bhardwaj",
|
|
278
|
+
"organization": "Qualixar",
|
|
279
|
+
"license": "MIT",
|
|
280
|
+
"urls": {
|
|
281
|
+
"product": "https://superlocalmemory.com",
|
|
282
|
+
"author": "https://varunpratap.com",
|
|
283
|
+
"organization": "https://qualixar.com",
|
|
284
|
+
},
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
# -- Helpers ------------------------------------------------------------------
|
|
289
|
+
|
|
290
|
+
def _format_results(results) -> list[dict]:
|
|
291
|
+
"""Convert RetrievalResult list to serialisable dicts."""
|
|
292
|
+
items: list[dict] = []
|
|
293
|
+
for r in results:
|
|
294
|
+
items.append({
|
|
295
|
+
"fact_id": r.fact.fact_id,
|
|
296
|
+
"content": r.fact.content,
|
|
297
|
+
"score": round(r.score, 3),
|
|
298
|
+
"confidence": round(r.confidence, 3),
|
|
299
|
+
"trust_score": round(r.trust_score, 3),
|
|
300
|
+
"fact_type": r.fact.fact_type.value,
|
|
301
|
+
"channel_scores": {
|
|
302
|
+
k: round(v, 3) for k, v in r.channel_scores.items()
|
|
303
|
+
},
|
|
304
|
+
})
|
|
305
|
+
return items
|