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.
- package/LICENSE +9 -1
- package/NOTICE +63 -0
- package/README.md +165 -480
- package/bin/slm +17 -449
- package/bin/slm-npm +62 -48
- 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,293 @@
|
|
|
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 — Embedding Service.
|
|
6
|
+
|
|
7
|
+
Thread-safe, dimension-validated embedding with Fisher variance computation.
|
|
8
|
+
Supports local (768-dim nomic) and cloud (3072-dim) models with EXPLICIT errors
|
|
9
|
+
on dimension mismatch — NEVER silently falls back to a different dimension.
|
|
10
|
+
|
|
11
|
+
Part of Qualixar | Author: Varun Pratap Bhardwaj
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import threading
|
|
18
|
+
import time
|
|
19
|
+
from typing import TYPE_CHECKING
|
|
20
|
+
|
|
21
|
+
import numpy as np
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from numpy.typing import NDArray
|
|
25
|
+
|
|
26
|
+
from superlocalmemory.core.config import EmbeddingConfig
|
|
27
|
+
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
# ---------------------------------------------------------------------------
|
|
31
|
+
# Fisher variance constants
|
|
32
|
+
# ---------------------------------------------------------------------------
|
|
33
|
+
_FISHER_VAR_MIN = 0.05
|
|
34
|
+
_FISHER_VAR_MAX = 2.0
|
|
35
|
+
_FISHER_VAR_RANGE = _FISHER_VAR_MAX - _FISHER_VAR_MIN # 1.95
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class DimensionMismatchError(RuntimeError):
|
|
39
|
+
"""Raised when the actual embedding dimension differs from config.
|
|
40
|
+
|
|
41
|
+
This is a HARD failure — V1 silently fell back to local embeddings
|
|
42
|
+
when Azure failed, changing dimension from 3072 to 768 mid-run.
|
|
43
|
+
We crash loudly instead.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class EmbeddingService:
|
|
48
|
+
"""Thread-safe embedding service with strict dimension validation.
|
|
49
|
+
|
|
50
|
+
Lazy-loads the underlying model on first embed call.
|
|
51
|
+
Validates every output dimension against the configured expectation.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(self, config: EmbeddingConfig) -> None:
|
|
55
|
+
self._config = config
|
|
56
|
+
self._model: object | None = None
|
|
57
|
+
self._lock = threading.Lock()
|
|
58
|
+
self._loaded = False
|
|
59
|
+
|
|
60
|
+
# ------------------------------------------------------------------
|
|
61
|
+
# Public API
|
|
62
|
+
# ------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def dimension(self) -> int:
|
|
66
|
+
"""Expected embedding dimension (from config)."""
|
|
67
|
+
return self._config.dimension
|
|
68
|
+
|
|
69
|
+
def embed(self, text: str) -> list[float]:
|
|
70
|
+
"""Embed a single text string.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
L2-normalized embedding of exactly ``self.dimension`` floats.
|
|
74
|
+
|
|
75
|
+
Raises:
|
|
76
|
+
ValueError: If text is empty.
|
|
77
|
+
DimensionMismatchError: If output dimension != config.
|
|
78
|
+
"""
|
|
79
|
+
if not text or not text.strip():
|
|
80
|
+
raise ValueError("Cannot embed empty text")
|
|
81
|
+
vec = self._encode_single(text)
|
|
82
|
+
self._validate_dimension(vec)
|
|
83
|
+
return vec.tolist()
|
|
84
|
+
|
|
85
|
+
def embed_batch(self, texts: list[str]) -> list[list[float]]:
|
|
86
|
+
"""Embed a batch of texts.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
List of L2-normalized embeddings, each ``self.dimension`` floats.
|
|
90
|
+
|
|
91
|
+
Raises:
|
|
92
|
+
ValueError: If any text is empty or list is empty.
|
|
93
|
+
DimensionMismatchError: If any output dimension != config.
|
|
94
|
+
"""
|
|
95
|
+
if not texts:
|
|
96
|
+
raise ValueError("Cannot embed empty batch")
|
|
97
|
+
for i, t in enumerate(texts):
|
|
98
|
+
if not t or not t.strip():
|
|
99
|
+
raise ValueError(f"Text at index {i} is empty")
|
|
100
|
+
|
|
101
|
+
vectors = self._encode_batch(texts)
|
|
102
|
+
for vec in vectors:
|
|
103
|
+
self._validate_dimension(vec)
|
|
104
|
+
return [v.tolist() for v in vectors]
|
|
105
|
+
|
|
106
|
+
def compute_fisher_params(
|
|
107
|
+
self,
|
|
108
|
+
embedding: list[float],
|
|
109
|
+
) -> tuple[list[float], list[float]]:
|
|
110
|
+
"""Compute Fisher-Rao parameters from a raw embedding.
|
|
111
|
+
|
|
112
|
+
Variance is content-derived (NOT uniform). Dimensions with strong
|
|
113
|
+
signal (high absolute value) get LOW variance (high confidence).
|
|
114
|
+
Weak-signal dimensions get HIGH variance (uncertainty).
|
|
115
|
+
|
|
116
|
+
This heterogeneous variance is what gives Fisher-Rao metric
|
|
117
|
+
discriminative power beyond simple cosine similarity.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
embedding: Raw embedding vector (already L2-normalized).
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
(mean, variance) — both lists of ``self.dimension`` floats.
|
|
124
|
+
Variance values are clamped to [0.3, 2.0].
|
|
125
|
+
"""
|
|
126
|
+
arr = np.asarray(embedding, dtype=np.float64)
|
|
127
|
+
norm = float(np.linalg.norm(arr))
|
|
128
|
+
|
|
129
|
+
if norm < 1e-10:
|
|
130
|
+
mean = np.zeros(len(arr), dtype=np.float64)
|
|
131
|
+
variance = np.full(len(arr), _FISHER_VAR_MAX, dtype=np.float64)
|
|
132
|
+
return mean.tolist(), variance.tolist()
|
|
133
|
+
|
|
134
|
+
mean = arr / norm
|
|
135
|
+
|
|
136
|
+
# Content-derived heterogeneous variance
|
|
137
|
+
abs_mean = np.abs(mean)
|
|
138
|
+
max_val = float(np.max(abs_mean)) + 1e-10
|
|
139
|
+
signal_strength = abs_mean / max_val # [0, 1]
|
|
140
|
+
|
|
141
|
+
# Inverse: strong signal -> low variance, weak -> high
|
|
142
|
+
variance = _FISHER_VAR_MAX - _FISHER_VAR_RANGE * signal_strength
|
|
143
|
+
variance = np.clip(variance, _FISHER_VAR_MIN, _FISHER_VAR_MAX)
|
|
144
|
+
|
|
145
|
+
return mean.tolist(), variance.tolist()
|
|
146
|
+
|
|
147
|
+
# ------------------------------------------------------------------
|
|
148
|
+
# Internals — model loading
|
|
149
|
+
# ------------------------------------------------------------------
|
|
150
|
+
|
|
151
|
+
def _ensure_loaded(self) -> None:
|
|
152
|
+
"""Lazy-load the model on first use (thread-safe)."""
|
|
153
|
+
if self._loaded:
|
|
154
|
+
return
|
|
155
|
+
with self._lock:
|
|
156
|
+
if self._loaded:
|
|
157
|
+
return
|
|
158
|
+
if self._config.is_cloud:
|
|
159
|
+
# Cloud mode: no local model needed, validate config
|
|
160
|
+
if not self._config.api_endpoint or not self._config.api_key:
|
|
161
|
+
raise RuntimeError(
|
|
162
|
+
"Cloud embedding requires api_endpoint and api_key"
|
|
163
|
+
)
|
|
164
|
+
logger.info(
|
|
165
|
+
"EmbeddingService: cloud mode (%s, %d-dim)",
|
|
166
|
+
self._config.deployment_name,
|
|
167
|
+
self._config.dimension,
|
|
168
|
+
)
|
|
169
|
+
else:
|
|
170
|
+
self._load_local_model()
|
|
171
|
+
self._loaded = True
|
|
172
|
+
|
|
173
|
+
def _load_local_model(self) -> None:
|
|
174
|
+
"""Load sentence-transformers model for local embedding."""
|
|
175
|
+
try:
|
|
176
|
+
from sentence_transformers import SentenceTransformer
|
|
177
|
+
except ImportError:
|
|
178
|
+
raise ImportError(
|
|
179
|
+
"sentence-transformers required: "
|
|
180
|
+
"pip install sentence-transformers"
|
|
181
|
+
)
|
|
182
|
+
model = SentenceTransformer(
|
|
183
|
+
self._config.model_name, trust_remote_code=False,
|
|
184
|
+
)
|
|
185
|
+
actual_dim = model.get_sentence_embedding_dimension()
|
|
186
|
+
if actual_dim != self._config.dimension:
|
|
187
|
+
raise DimensionMismatchError(
|
|
188
|
+
f"Model '{self._config.model_name}' produces {actual_dim}-dim "
|
|
189
|
+
f"embeddings but config expects {self._config.dimension}-dim"
|
|
190
|
+
)
|
|
191
|
+
self._model = model
|
|
192
|
+
logger.info(
|
|
193
|
+
"EmbeddingService: local model loaded (%s, %d-dim)",
|
|
194
|
+
self._config.model_name,
|
|
195
|
+
actual_dim,
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
# ------------------------------------------------------------------
|
|
199
|
+
# Internals — encoding
|
|
200
|
+
# ------------------------------------------------------------------
|
|
201
|
+
|
|
202
|
+
def _encode_single(self, text: str) -> NDArray[np.float32]:
|
|
203
|
+
"""Encode one text. Dispatches to local or cloud."""
|
|
204
|
+
self._ensure_loaded()
|
|
205
|
+
if self._config.is_cloud:
|
|
206
|
+
return self._cloud_embed([text])[0]
|
|
207
|
+
return self._local_embed_batch([text])[0]
|
|
208
|
+
|
|
209
|
+
def _encode_batch(self, texts: list[str]) -> list[NDArray[np.float32]]:
|
|
210
|
+
"""Encode a batch. Dispatches to local or cloud."""
|
|
211
|
+
self._ensure_loaded()
|
|
212
|
+
if self._config.is_cloud:
|
|
213
|
+
return self._cloud_embed(texts)
|
|
214
|
+
return self._local_embed_batch(texts)
|
|
215
|
+
|
|
216
|
+
def _local_embed_batch(
|
|
217
|
+
self,
|
|
218
|
+
texts: list[str],
|
|
219
|
+
) -> list[NDArray[np.float32]]:
|
|
220
|
+
"""Encode via local sentence-transformers (L2-normalized)."""
|
|
221
|
+
if self._model is None:
|
|
222
|
+
raise RuntimeError("Local model not loaded")
|
|
223
|
+
vecs = self._model.encode(texts, normalize_embeddings=True)
|
|
224
|
+
if isinstance(vecs, np.ndarray) and vecs.ndim == 2:
|
|
225
|
+
return [vecs[i] for i in range(vecs.shape[0])]
|
|
226
|
+
return [np.asarray(v, dtype=np.float32) for v in vecs]
|
|
227
|
+
|
|
228
|
+
def _cloud_embed(
|
|
229
|
+
self,
|
|
230
|
+
texts: list[str],
|
|
231
|
+
*,
|
|
232
|
+
max_retries: int = 3,
|
|
233
|
+
) -> list[NDArray[np.float32]]:
|
|
234
|
+
"""Encode via Azure OpenAI embedding API with retry logic.
|
|
235
|
+
|
|
236
|
+
Raises on failure — NEVER falls back to local model.
|
|
237
|
+
"""
|
|
238
|
+
import httpx
|
|
239
|
+
|
|
240
|
+
url = (
|
|
241
|
+
f"{self._config.api_endpoint.rstrip('/')}/openai/deployments/"
|
|
242
|
+
f"{self._config.deployment_name}/embeddings"
|
|
243
|
+
f"?api-version={self._config.api_version}"
|
|
244
|
+
)
|
|
245
|
+
headers = {
|
|
246
|
+
"Content-Type": "application/json",
|
|
247
|
+
"api-key": self._config.api_key,
|
|
248
|
+
}
|
|
249
|
+
body = {"input": texts, "model": self._config.deployment_name}
|
|
250
|
+
|
|
251
|
+
last_error: Exception | None = None
|
|
252
|
+
for attempt in range(max_retries):
|
|
253
|
+
try:
|
|
254
|
+
with httpx.Client(timeout=httpx.Timeout(30.0)) as client:
|
|
255
|
+
resp = client.post(url, headers=headers, json=body)
|
|
256
|
+
resp.raise_for_status()
|
|
257
|
+
data = resp.json()
|
|
258
|
+
results: list[NDArray[np.float32]] = []
|
|
259
|
+
for item in sorted(data["data"], key=lambda d: d["index"]):
|
|
260
|
+
vec = np.asarray(item["embedding"], dtype=np.float32)
|
|
261
|
+
results.append(vec)
|
|
262
|
+
return results
|
|
263
|
+
except Exception as exc:
|
|
264
|
+
last_error = exc
|
|
265
|
+
wait = 2 ** attempt # 1s, 2s, 4s
|
|
266
|
+
logger.warning(
|
|
267
|
+
"Cloud embed attempt %d/%d failed: %s (retry in %ds)",
|
|
268
|
+
attempt + 1,
|
|
269
|
+
max_retries,
|
|
270
|
+
exc,
|
|
271
|
+
wait,
|
|
272
|
+
)
|
|
273
|
+
if attempt < max_retries - 1:
|
|
274
|
+
time.sleep(wait)
|
|
275
|
+
|
|
276
|
+
raise RuntimeError(
|
|
277
|
+
f"Cloud embedding failed after {max_retries} attempts: "
|
|
278
|
+
f"{last_error}"
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
# ------------------------------------------------------------------
|
|
282
|
+
# Validation
|
|
283
|
+
# ------------------------------------------------------------------
|
|
284
|
+
|
|
285
|
+
def _validate_dimension(self, vec: NDArray) -> None:
|
|
286
|
+
"""Hard validation — crash on mismatch, never silently fall back."""
|
|
287
|
+
actual = len(vec)
|
|
288
|
+
if actual != self._config.dimension:
|
|
289
|
+
raise DimensionMismatchError(
|
|
290
|
+
f"Embedding dimension {actual} != "
|
|
291
|
+
f"expected {self._config.dimension}. "
|
|
292
|
+
f"This is a HARD failure — check your model/API config."
|
|
293
|
+
)
|