superlocalmemory 2.8.5 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/LICENSE +9 -1
- package/NOTICE +63 -0
- package/README.md +165 -480
- package/bin/slm +17 -449
- package/bin/slm-npm +2 -2
- package/bin/slm.bat +4 -2
- 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/{install.ps1 → scripts/install.ps1} +36 -4
- package/{install.sh → scripts/install.sh} +14 -13
- 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/docs/SECURITY-QUICK-REFERENCE.md +0 -214
- 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 -1800
- 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 -266
- /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
|
@@ -0,0 +1,189 @@
|
|
|
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
|
+
"""Steganographic watermarking using zero-width Unicode characters.
|
|
6
|
+
|
|
7
|
+
Embeds an invisible binary payload (derived from a key string) into
|
|
8
|
+
visible text. The watermark is undetectable to end users but can be
|
|
9
|
+
extracted programmatically to prove provenance.
|
|
10
|
+
|
|
11
|
+
Encoding scheme
|
|
12
|
+
---------------
|
|
13
|
+
1. Convert the key to binary (each char -> 8-bit representation).
|
|
14
|
+
2. Map binary digits to zero-width characters:
|
|
15
|
+
|
|
16
|
+
- ``0`` -> U+200B (zero-width space)
|
|
17
|
+
- ``1`` -> U+200C (zero-width non-joiner)
|
|
18
|
+
|
|
19
|
+
3. Frame the bit sequence with markers:
|
|
20
|
+
|
|
21
|
+
- Start: U+FEFF (byte-order mark)
|
|
22
|
+
- End: U+200D (zero-width joiner)
|
|
23
|
+
|
|
24
|
+
4. Insert the entire encoded sequence immediately after the first
|
|
25
|
+
visible character of the host text.
|
|
26
|
+
|
|
27
|
+
Part of Qualixar | Author: Varun Pratap Bhardwaj
|
|
28
|
+
License: MIT
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
from typing import Optional
|
|
34
|
+
|
|
35
|
+
# ---- Zero-width character constants ----
|
|
36
|
+
_BIT_ZERO: str = "\u200b" # Zero-width space
|
|
37
|
+
_BIT_ONE: str = "\u200c" # Zero-width non-joiner
|
|
38
|
+
_END_MARKER: str = "\u200d" # Zero-width joiner
|
|
39
|
+
_START_MARKER: str = "\ufeff" # Byte-order mark
|
|
40
|
+
|
|
41
|
+
# All zero-width characters used by this module (for stripping).
|
|
42
|
+
_ALL_ZW: set[str] = {_BIT_ZERO, _BIT_ONE, _END_MARKER, _START_MARKER}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class QualixarWatermark:
|
|
46
|
+
"""Embed and detect invisible watermarks in text.
|
|
47
|
+
|
|
48
|
+
Typical usage::
|
|
49
|
+
|
|
50
|
+
wm = QualixarWatermark()
|
|
51
|
+
watermarked = wm.embed("Hello world")
|
|
52
|
+
assert wm.detect(watermarked) is True
|
|
53
|
+
assert wm.extract(watermarked) == "qualixar"
|
|
54
|
+
assert wm.strip(watermarked) == "Hello world"
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
key: The string payload to embed. On extraction, this exact
|
|
58
|
+
string is recovered if the watermark is intact.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
def __init__(self, key: str = "qualixar") -> None:
|
|
62
|
+
if not key:
|
|
63
|
+
raise ValueError("key must be a non-empty string")
|
|
64
|
+
self._key: str = key
|
|
65
|
+
self._encoded: str = self._encode_key(key)
|
|
66
|
+
|
|
67
|
+
# ------------------------------------------------------------------
|
|
68
|
+
# Public API
|
|
69
|
+
# ------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
def embed(self, text: str) -> str:
|
|
72
|
+
"""Embed an invisible watermark into *text*.
|
|
73
|
+
|
|
74
|
+
The returned string is visually identical to the original when
|
|
75
|
+
rendered — zero-width characters are invisible in all standard
|
|
76
|
+
fonts and terminals.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
text: The visible text to watermark.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
A new string containing the embedded watermark. If *text*
|
|
83
|
+
is empty, returns the empty string unchanged (nowhere to
|
|
84
|
+
insert the payload).
|
|
85
|
+
"""
|
|
86
|
+
if not text:
|
|
87
|
+
return text
|
|
88
|
+
|
|
89
|
+
# Insert the encoded payload after the first visible character.
|
|
90
|
+
return text[0] + self._encoded + text[1:]
|
|
91
|
+
|
|
92
|
+
def detect(self, text: str) -> bool:
|
|
93
|
+
"""Check whether *text* contains a valid watermark for this key.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
text: The text to inspect.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
``True`` if the watermark is present and matches the key,
|
|
100
|
+
``False`` otherwise.
|
|
101
|
+
"""
|
|
102
|
+
extracted = self.extract(text)
|
|
103
|
+
return extracted == self._key
|
|
104
|
+
|
|
105
|
+
def extract(self, text: str) -> Optional[str]:
|
|
106
|
+
"""Extract the watermark payload from *text*.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
text: The text to inspect.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
The decoded key string if a valid watermark is found,
|
|
113
|
+
``None`` if no watermark is present or it is malformed.
|
|
114
|
+
"""
|
|
115
|
+
start_idx = text.find(_START_MARKER)
|
|
116
|
+
if start_idx == -1:
|
|
117
|
+
return None
|
|
118
|
+
|
|
119
|
+
end_idx = text.find(_END_MARKER, start_idx + 1)
|
|
120
|
+
if end_idx == -1:
|
|
121
|
+
return None
|
|
122
|
+
|
|
123
|
+
payload = text[start_idx + 1 : end_idx]
|
|
124
|
+
return self._decode_payload(payload)
|
|
125
|
+
|
|
126
|
+
def strip(self, text: str) -> str:
|
|
127
|
+
"""Remove all zero-width characters, returning clean text.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
text: The potentially watermarked text.
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
A copy of *text* with every zero-width character removed.
|
|
134
|
+
"""
|
|
135
|
+
return "".join(ch for ch in text if ch not in _ALL_ZW)
|
|
136
|
+
|
|
137
|
+
# ------------------------------------------------------------------
|
|
138
|
+
# Internal helpers
|
|
139
|
+
# ------------------------------------------------------------------
|
|
140
|
+
|
|
141
|
+
@staticmethod
|
|
142
|
+
def _encode_key(key: str) -> str:
|
|
143
|
+
"""Convert *key* to a framed zero-width character sequence.
|
|
144
|
+
|
|
145
|
+
Each character of *key* is converted to 8 binary digits, each
|
|
146
|
+
digit is mapped to a zero-width char, and the whole thing is
|
|
147
|
+
wrapped with start/end markers.
|
|
148
|
+
"""
|
|
149
|
+
bits: list[str] = []
|
|
150
|
+
for char in key:
|
|
151
|
+
byte_val = ord(char)
|
|
152
|
+
for bit_pos in range(7, -1, -1):
|
|
153
|
+
if (byte_val >> bit_pos) & 1:
|
|
154
|
+
bits.append(_BIT_ONE)
|
|
155
|
+
else:
|
|
156
|
+
bits.append(_BIT_ZERO)
|
|
157
|
+
|
|
158
|
+
return _START_MARKER + "".join(bits) + _END_MARKER
|
|
159
|
+
|
|
160
|
+
@staticmethod
|
|
161
|
+
def _decode_payload(payload: str) -> Optional[str]:
|
|
162
|
+
"""Decode a zero-width bit sequence back to a string.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
payload: The raw zero-width characters between the start
|
|
166
|
+
and end markers (exclusive).
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
The decoded string, or ``None`` if the payload length is
|
|
170
|
+
not a multiple of 8 or contains unexpected characters.
|
|
171
|
+
"""
|
|
172
|
+
if len(payload) % 8 != 0:
|
|
173
|
+
return None
|
|
174
|
+
|
|
175
|
+
chars: list[str] = []
|
|
176
|
+
for i in range(0, len(payload), 8):
|
|
177
|
+
byte_bits = payload[i : i + 8]
|
|
178
|
+
byte_val = 0
|
|
179
|
+
for bit_char in byte_bits:
|
|
180
|
+
byte_val <<= 1
|
|
181
|
+
if bit_char == _BIT_ONE:
|
|
182
|
+
byte_val |= 1
|
|
183
|
+
elif bit_char == _BIT_ZERO:
|
|
184
|
+
pass # bit stays 0
|
|
185
|
+
else:
|
|
186
|
+
return None # unexpected character in payload
|
|
187
|
+
chars.append(chr(byte_val))
|
|
188
|
+
|
|
189
|
+
return "".join(chars)
|
|
@@ -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
|
+
"""CLI command implementations.
|
|
6
|
+
|
|
7
|
+
Each function handles one CLI command. Dispatch routes by name.
|
|
8
|
+
|
|
9
|
+
Part of Qualixar | Author: Varun Pratap Bhardwaj
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import sys
|
|
15
|
+
from argparse import Namespace
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def dispatch(args: Namespace) -> None:
|
|
19
|
+
"""Route CLI command to the appropriate handler."""
|
|
20
|
+
handlers = {
|
|
21
|
+
"setup": cmd_setup,
|
|
22
|
+
"mode": cmd_mode,
|
|
23
|
+
"provider": cmd_provider,
|
|
24
|
+
"connect": cmd_connect,
|
|
25
|
+
"migrate": cmd_migrate,
|
|
26
|
+
"remember": cmd_remember,
|
|
27
|
+
"recall": cmd_recall,
|
|
28
|
+
"forget": cmd_forget,
|
|
29
|
+
"status": cmd_status,
|
|
30
|
+
"health": cmd_health,
|
|
31
|
+
"trace": cmd_trace,
|
|
32
|
+
"profile": cmd_profile,
|
|
33
|
+
}
|
|
34
|
+
handler = handlers.get(args.command)
|
|
35
|
+
if handler:
|
|
36
|
+
handler(args)
|
|
37
|
+
else:
|
|
38
|
+
print(f"Unknown command: {args.command}")
|
|
39
|
+
sys.exit(1)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def cmd_setup(_args: Namespace) -> None:
|
|
43
|
+
"""Run the interactive setup wizard."""
|
|
44
|
+
from superlocalmemory.cli.setup_wizard import run_wizard
|
|
45
|
+
|
|
46
|
+
run_wizard()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def cmd_mode(args: Namespace) -> None:
|
|
50
|
+
"""Get or set the operating mode."""
|
|
51
|
+
from superlocalmemory.core.config import SLMConfig
|
|
52
|
+
from superlocalmemory.storage.models import Mode
|
|
53
|
+
|
|
54
|
+
config = SLMConfig.load()
|
|
55
|
+
|
|
56
|
+
if args.value:
|
|
57
|
+
updated = SLMConfig.for_mode(
|
|
58
|
+
Mode(args.value),
|
|
59
|
+
llm_provider=config.llm.provider,
|
|
60
|
+
llm_model=config.llm.model,
|
|
61
|
+
llm_api_key=config.llm.api_key,
|
|
62
|
+
llm_api_base=config.llm.api_base,
|
|
63
|
+
)
|
|
64
|
+
updated.save()
|
|
65
|
+
print(f"Mode set to: {args.value.upper()}")
|
|
66
|
+
else:
|
|
67
|
+
print(f"Current mode: {config.mode.value.upper()}")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def cmd_provider(args: Namespace) -> None:
|
|
71
|
+
"""Get or set the LLM provider."""
|
|
72
|
+
from superlocalmemory.core.config import SLMConfig
|
|
73
|
+
|
|
74
|
+
config = SLMConfig.load()
|
|
75
|
+
|
|
76
|
+
if args.action == "set":
|
|
77
|
+
from superlocalmemory.cli.setup_wizard import configure_provider
|
|
78
|
+
|
|
79
|
+
configure_provider(config)
|
|
80
|
+
else:
|
|
81
|
+
print(f"Provider: {config.llm.provider or 'none (Mode A)'}")
|
|
82
|
+
if config.llm.model:
|
|
83
|
+
print(f"Model: {config.llm.model}")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def cmd_connect(args: Namespace) -> None:
|
|
87
|
+
"""Configure IDE integrations."""
|
|
88
|
+
from superlocalmemory.hooks.ide_connector import IDEConnector
|
|
89
|
+
|
|
90
|
+
connector = IDEConnector()
|
|
91
|
+
if getattr(args, "list", False):
|
|
92
|
+
status = connector.get_status()
|
|
93
|
+
for s in status:
|
|
94
|
+
mark = "[+]" if s["installed"] else "[-]"
|
|
95
|
+
print(f" {mark} {s['name']:20s} {s['config_path']}")
|
|
96
|
+
return
|
|
97
|
+
if getattr(args, "ide", None):
|
|
98
|
+
success = connector.connect(args.ide)
|
|
99
|
+
print(f"{'Connected' if success else 'Failed'}: {args.ide}")
|
|
100
|
+
else:
|
|
101
|
+
results = connector.connect_all()
|
|
102
|
+
for ide_id, ide_status in results.items():
|
|
103
|
+
print(f" {ide_id}: {ide_status}")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def cmd_migrate(args: Namespace) -> None:
|
|
107
|
+
"""Run V2 to V3 migration."""
|
|
108
|
+
from superlocalmemory.cli.migrate_cmd import cmd_migrate as _migrate
|
|
109
|
+
|
|
110
|
+
_migrate(args)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def cmd_remember(args: Namespace) -> None:
|
|
114
|
+
"""Store a memory via the engine."""
|
|
115
|
+
from superlocalmemory.core.config import SLMConfig
|
|
116
|
+
from superlocalmemory.core.engine import MemoryEngine
|
|
117
|
+
|
|
118
|
+
config = SLMConfig.load()
|
|
119
|
+
engine = MemoryEngine(config)
|
|
120
|
+
engine.initialize()
|
|
121
|
+
|
|
122
|
+
metadata = {"tags": args.tags} if args.tags else {}
|
|
123
|
+
fact_ids = engine.store(args.content, metadata=metadata)
|
|
124
|
+
print(f"Stored {len(fact_ids)} facts.")
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def cmd_recall(args: Namespace) -> None:
|
|
128
|
+
"""Search memories via the engine."""
|
|
129
|
+
from superlocalmemory.core.config import SLMConfig
|
|
130
|
+
from superlocalmemory.core.engine import MemoryEngine
|
|
131
|
+
|
|
132
|
+
config = SLMConfig.load()
|
|
133
|
+
engine = MemoryEngine(config)
|
|
134
|
+
engine.initialize()
|
|
135
|
+
|
|
136
|
+
response = engine.recall(args.query, limit=args.limit)
|
|
137
|
+
if not response.results:
|
|
138
|
+
print("No memories found.")
|
|
139
|
+
return
|
|
140
|
+
for i, r in enumerate(response.results, 1):
|
|
141
|
+
print(f" {i}. [{r.score:.2f}] {r.fact.content[:120]}")
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def cmd_forget(args: Namespace) -> None:
|
|
145
|
+
"""Delete memories matching a query."""
|
|
146
|
+
from superlocalmemory.core.engine import MemoryEngine
|
|
147
|
+
from superlocalmemory.core.config import SLMConfig
|
|
148
|
+
|
|
149
|
+
config = SLMConfig.load()
|
|
150
|
+
engine = MemoryEngine(config)
|
|
151
|
+
facts = engine._db.get_all_facts(engine.profile_id)
|
|
152
|
+
query_lower = args.query.lower()
|
|
153
|
+
matches = [f for f in facts if query_lower in f.content.lower()]
|
|
154
|
+
if not matches:
|
|
155
|
+
print(f"No memories matching '{args.query}'")
|
|
156
|
+
return
|
|
157
|
+
print(f"Found {len(matches)} matching memories:")
|
|
158
|
+
for f in matches[:10]:
|
|
159
|
+
print(f" - {f.fact_id[:8]}... {f.content[:80]}")
|
|
160
|
+
confirm = input(f"Delete {len(matches)} memories? [y/N] ").strip().lower()
|
|
161
|
+
if confirm in ("y", "yes"):
|
|
162
|
+
for f in matches:
|
|
163
|
+
engine._db.delete_fact(f.fact_id)
|
|
164
|
+
print(f"Deleted {len(matches)} memories.")
|
|
165
|
+
else:
|
|
166
|
+
print("Cancelled.")
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def cmd_status(_args: Namespace) -> None:
|
|
170
|
+
"""Show system status."""
|
|
171
|
+
from superlocalmemory.core.config import SLMConfig
|
|
172
|
+
|
|
173
|
+
config = SLMConfig.load()
|
|
174
|
+
print("SuperLocalMemory V3")
|
|
175
|
+
print(f" Mode: {config.mode.value.upper()}")
|
|
176
|
+
print(f" Provider: {config.llm.provider or 'none'}")
|
|
177
|
+
print(f" Base dir: {config.base_dir}")
|
|
178
|
+
print(f" Database: {config.db_path}")
|
|
179
|
+
if config.db_path.exists():
|
|
180
|
+
size_mb = round(config.db_path.stat().st_size / 1024 / 1024, 2)
|
|
181
|
+
print(f" DB size: {size_mb} MB")
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def cmd_health(_args: Namespace) -> None:
|
|
185
|
+
"""Show math layer health status."""
|
|
186
|
+
from superlocalmemory.core.engine import MemoryEngine
|
|
187
|
+
from superlocalmemory.core.config import SLMConfig
|
|
188
|
+
|
|
189
|
+
config = SLMConfig.load()
|
|
190
|
+
engine = MemoryEngine(config)
|
|
191
|
+
facts = engine._db.get_all_facts(engine.profile_id)
|
|
192
|
+
fisher_count = sum(1 for f in facts if f.fisher_mean is not None)
|
|
193
|
+
langevin_count = sum(1 for f in facts if f.langevin_position is not None)
|
|
194
|
+
print("Math Layer Health:")
|
|
195
|
+
print(f" Total facts: {len(facts)}")
|
|
196
|
+
print(f" Fisher-Rao indexed: {fisher_count}/{len(facts)}")
|
|
197
|
+
print(f" Langevin positioned: {langevin_count}/{len(facts)}")
|
|
198
|
+
print(f" Mode: {config.mode.value.upper()}")
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def cmd_trace(args: Namespace) -> None:
|
|
202
|
+
"""Recall with per-channel score breakdown."""
|
|
203
|
+
from superlocalmemory.core.engine import MemoryEngine
|
|
204
|
+
from superlocalmemory.core.config import SLMConfig
|
|
205
|
+
|
|
206
|
+
config = SLMConfig.load()
|
|
207
|
+
engine = MemoryEngine(config)
|
|
208
|
+
response = engine.recall(args.query, limit=5)
|
|
209
|
+
print(f"Query: {args.query}")
|
|
210
|
+
print(f"Type: {response.query_type} | Time: {response.retrieval_time_ms:.0f}ms")
|
|
211
|
+
print(f"Results: {len(response.results)}")
|
|
212
|
+
for i, r in enumerate(response.results, 1):
|
|
213
|
+
print(f"\n {i}. [{r.score:.3f}] {r.fact.content[:100]}")
|
|
214
|
+
if hasattr(r, "channel_scores") and r.channel_scores:
|
|
215
|
+
for ch, sc in r.channel_scores.items():
|
|
216
|
+
print(f" {ch}: {sc:.3f}")
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def cmd_profile(args: Namespace) -> None:
|
|
220
|
+
"""Profile management (list, switch, create)."""
|
|
221
|
+
from superlocalmemory.core.config import SLMConfig
|
|
222
|
+
from superlocalmemory.storage.database import DatabaseManager
|
|
223
|
+
from superlocalmemory.storage import schema
|
|
224
|
+
|
|
225
|
+
config = SLMConfig.load()
|
|
226
|
+
db = DatabaseManager(config.db_path)
|
|
227
|
+
db.initialize(schema)
|
|
228
|
+
|
|
229
|
+
if args.action == "list":
|
|
230
|
+
rows = db.execute("SELECT profile_id, name FROM profiles")
|
|
231
|
+
print("Profiles:")
|
|
232
|
+
for r in rows:
|
|
233
|
+
d = dict(r)
|
|
234
|
+
print(f" - {d['profile_id']}: {d.get('name', '')}")
|
|
235
|
+
elif args.action == "switch":
|
|
236
|
+
config.active_profile = args.name
|
|
237
|
+
config.save()
|
|
238
|
+
print(f"Switched to profile: {args.name}")
|
|
239
|
+
elif args.action == "create":
|
|
240
|
+
from superlocalmemory.storage.models import _new_id
|
|
241
|
+
db.execute(
|
|
242
|
+
"INSERT OR IGNORE INTO profiles (profile_id, name) VALUES (?, ?)",
|
|
243
|
+
(args.name, args.name),
|
|
244
|
+
)
|
|
245
|
+
print(f"Created profile: {args.name}")
|
|
@@ -0,0 +1,89 @@
|
|
|
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 — CLI entry point.
|
|
6
|
+
|
|
7
|
+
Usage: slm <command> [options]
|
|
8
|
+
|
|
9
|
+
Part of Qualixar | Author: Varun Pratap Bhardwaj
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def main() -> None:
|
|
19
|
+
"""Parse CLI arguments and dispatch to command handlers."""
|
|
20
|
+
parser = argparse.ArgumentParser(prog="slm", description="SuperLocalMemory V3")
|
|
21
|
+
sub = parser.add_subparsers(dest="command")
|
|
22
|
+
|
|
23
|
+
# Setup
|
|
24
|
+
sub.add_parser("setup", help="Run setup wizard")
|
|
25
|
+
|
|
26
|
+
# Mode
|
|
27
|
+
mode_p = sub.add_parser("mode", help="Get or set operating mode")
|
|
28
|
+
mode_p.add_argument(
|
|
29
|
+
"value", nargs="?", choices=["a", "b", "c"], help="Mode to set",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Provider
|
|
33
|
+
provider_p = sub.add_parser("provider", help="Get or set LLM provider")
|
|
34
|
+
provider_p.add_argument(
|
|
35
|
+
"action", nargs="?", choices=["set"], help="Action",
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# Connect
|
|
39
|
+
connect_p = sub.add_parser("connect", help="Configure IDE integrations")
|
|
40
|
+
connect_p.add_argument("ide", nargs="?", help="Specific IDE to configure")
|
|
41
|
+
connect_p.add_argument(
|
|
42
|
+
"--list", action="store_true", help="List all supported IDEs",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Migrate
|
|
46
|
+
migrate_p = sub.add_parser("migrate", help="Migrate from V2")
|
|
47
|
+
migrate_p.add_argument(
|
|
48
|
+
"--rollback", action="store_true", help="Rollback migration",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Memory ops
|
|
52
|
+
remember_p = sub.add_parser("remember", help="Store a memory")
|
|
53
|
+
remember_p.add_argument("content", help="Content to remember")
|
|
54
|
+
remember_p.add_argument("--tags", default="", help="Comma-separated tags")
|
|
55
|
+
|
|
56
|
+
recall_p = sub.add_parser("recall", help="Search memories")
|
|
57
|
+
recall_p.add_argument("query", help="Search query")
|
|
58
|
+
recall_p.add_argument("--limit", type=int, default=10, help="Max results")
|
|
59
|
+
|
|
60
|
+
forget_p = sub.add_parser("forget", help="Delete memories matching query")
|
|
61
|
+
forget_p.add_argument("query", help="Query to match")
|
|
62
|
+
|
|
63
|
+
# Status & diagnostics
|
|
64
|
+
sub.add_parser("status", help="System status")
|
|
65
|
+
sub.add_parser("health", help="Math layer health")
|
|
66
|
+
|
|
67
|
+
trace_p = sub.add_parser("trace", help="Recall with channel breakdown")
|
|
68
|
+
trace_p.add_argument("query", help="Search query")
|
|
69
|
+
|
|
70
|
+
# Profiles
|
|
71
|
+
profile_p = sub.add_parser("profile", help="Profile management")
|
|
72
|
+
profile_p.add_argument(
|
|
73
|
+
"action", choices=["list", "switch", "create"], help="Action",
|
|
74
|
+
)
|
|
75
|
+
profile_p.add_argument("name", nargs="?", help="Profile name")
|
|
76
|
+
|
|
77
|
+
args = parser.parse_args()
|
|
78
|
+
|
|
79
|
+
if not args.command:
|
|
80
|
+
parser.print_help()
|
|
81
|
+
sys.exit(0)
|
|
82
|
+
|
|
83
|
+
from superlocalmemory.cli.commands import dispatch
|
|
84
|
+
|
|
85
|
+
dispatch(args)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
if __name__ == "__main__":
|
|
89
|
+
main()
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
"""Migration CLI command implementation."""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def cmd_migrate(args):
|
|
11
|
+
"""Run V2 to V3 migration or rollback."""
|
|
12
|
+
from superlocalmemory.storage.v2_migrator import V2Migrator
|
|
13
|
+
|
|
14
|
+
migrator = V2Migrator()
|
|
15
|
+
|
|
16
|
+
if getattr(args, "rollback", False):
|
|
17
|
+
print("Rolling back V3 migration...")
|
|
18
|
+
result = migrator.rollback()
|
|
19
|
+
if result.get("success"):
|
|
20
|
+
for step in result.get("steps", []):
|
|
21
|
+
print(f" [ok] {step}")
|
|
22
|
+
print("Rollback complete. V2 restored.")
|
|
23
|
+
else:
|
|
24
|
+
print(f"Rollback failed: {result.get('error', 'unknown')}")
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
if not migrator.detect_v2():
|
|
28
|
+
print("No V2 installation found. Nothing to migrate.")
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
if migrator.is_already_migrated():
|
|
32
|
+
print("Already migrated to V3.")
|
|
33
|
+
return
|
|
34
|
+
|
|
35
|
+
stats = migrator.get_v2_stats()
|
|
36
|
+
print("V2 installation found:")
|
|
37
|
+
print(f" Memories: {stats.get('memory_count', 'unknown')}")
|
|
38
|
+
print(f" Size: {stats.get('db_size_mb', '?')} MB")
|
|
39
|
+
print()
|
|
40
|
+
|
|
41
|
+
import sys
|
|
42
|
+
if sys.stdin.isatty():
|
|
43
|
+
confirm = input("Proceed with migration? [Y/n] ").strip().lower()
|
|
44
|
+
if confirm not in ("", "y", "yes"):
|
|
45
|
+
print("Migration cancelled.")
|
|
46
|
+
return
|
|
47
|
+
|
|
48
|
+
result = migrator.migrate()
|
|
49
|
+
if result.get("success"):
|
|
50
|
+
for step in result.get("steps", []):
|
|
51
|
+
print(f" [ok] {step}")
|
|
52
|
+
print()
|
|
53
|
+
print("Migration complete!")
|
|
54
|
+
else:
|
|
55
|
+
print(f"Migration failed: {result.get('error', 'unknown')}")
|
|
@@ -0,0 +1,99 @@
|
|
|
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
|
+
"""Post-install script for npm package.
|
|
6
|
+
|
|
7
|
+
Runs after `npm install -g superlocalmemory`. Detects V2 installations,
|
|
8
|
+
prompts for migration, and runs the setup wizard for new users.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def run_post_install():
|
|
18
|
+
"""Main post-install entry point."""
|
|
19
|
+
print()
|
|
20
|
+
print("SuperLocalMemory V3")
|
|
21
|
+
print("=" * 30)
|
|
22
|
+
print()
|
|
23
|
+
|
|
24
|
+
# Step 1: Check for V2 installation
|
|
25
|
+
from superlocalmemory.storage.v2_migrator import V2Migrator
|
|
26
|
+
|
|
27
|
+
migrator = V2Migrator()
|
|
28
|
+
|
|
29
|
+
if migrator.detect_v2() and not migrator.is_already_migrated():
|
|
30
|
+
_handle_v2_upgrade(migrator)
|
|
31
|
+
else:
|
|
32
|
+
_handle_fresh_install()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _handle_v2_upgrade(migrator):
|
|
36
|
+
"""Handle upgrade from V2."""
|
|
37
|
+
stats = migrator.get_v2_stats()
|
|
38
|
+
|
|
39
|
+
print("Existing V2 installation detected!")
|
|
40
|
+
print(f" Database: {stats.get('db_path', '~/.claude-memory/memory.db')}")
|
|
41
|
+
print(f" Memories: {stats.get('memory_count', 'unknown')}")
|
|
42
|
+
print(f" Profiles: {stats.get('profile_count', 1)}")
|
|
43
|
+
print()
|
|
44
|
+
print("V3 requires a one-time migration to upgrade your database.")
|
|
45
|
+
print("Your data will be preserved. A backup is created automatically.")
|
|
46
|
+
print("You can rollback anytime within 30 days.")
|
|
47
|
+
print()
|
|
48
|
+
|
|
49
|
+
choice = input("Run migration now? [Y/n]: ").strip().lower()
|
|
50
|
+
|
|
51
|
+
if choice in ("", "y", "yes"):
|
|
52
|
+
print()
|
|
53
|
+
print("Migrating...")
|
|
54
|
+
result = migrator.migrate()
|
|
55
|
+
|
|
56
|
+
if result.get("success"):
|
|
57
|
+
print()
|
|
58
|
+
for step in result.get("steps", []):
|
|
59
|
+
print(f" [ok] {step}")
|
|
60
|
+
print()
|
|
61
|
+
print("Migration complete!")
|
|
62
|
+
print(f" V3 database: {result.get('v3_db', '')}")
|
|
63
|
+
print(f" Backup: {result.get('backup_db', '')}")
|
|
64
|
+
print()
|
|
65
|
+
# Run setup wizard after migration
|
|
66
|
+
_run_setup()
|
|
67
|
+
else:
|
|
68
|
+
print(f"Migration failed: {result.get('error', 'unknown')}")
|
|
69
|
+
print("Your V2 data is untouched. Run `slm migrate` to try again.")
|
|
70
|
+
sys.exit(1)
|
|
71
|
+
else:
|
|
72
|
+
print()
|
|
73
|
+
print("Migration skipped. Run `slm migrate` when ready.")
|
|
74
|
+
print("Note: V3 features are unavailable until you migrate.")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _handle_fresh_install():
|
|
78
|
+
"""Handle fresh install (no V2 detected)."""
|
|
79
|
+
from superlocalmemory.storage.v2_migrator import V2Migrator
|
|
80
|
+
|
|
81
|
+
migrator = V2Migrator()
|
|
82
|
+
|
|
83
|
+
if migrator.is_already_migrated():
|
|
84
|
+
print("V3 already configured. Run `slm setup` to reconfigure.")
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
print("Welcome! Let's set up SuperLocalMemory V3.")
|
|
88
|
+
_run_setup()
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _run_setup():
|
|
92
|
+
"""Run the interactive setup wizard."""
|
|
93
|
+
from superlocalmemory.cli.setup_wizard import run_wizard
|
|
94
|
+
|
|
95
|
+
run_wizard()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
if __name__ == "__main__":
|
|
99
|
+
run_post_install()
|