superlocalmemory 4.1.13 → 4.1.15
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/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +103 -0
- package/README.md +3 -3
- package/package.json +1 -8
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/CLAUDE.md +3 -3
- package/plugin/agents/slm-governance-advisor.md +1 -1
- package/plugin/agents/slm-loop-runner.md +1 -1
- package/plugin/agents/slm-memory-advisor.md +1 -1
- package/plugin/agents/slm-optimize-advisor.md +1 -1
- package/plugin/requirements.txt +1 -1
- package/plugin/skills/slm-cache/SKILL.md +1 -1
- package/plugin/skills/slm-compress/SKILL.md +1 -1
- package/plugin/skills/slm-governance/SKILL.md +1 -1
- package/plugin/skills/slm-graph/SKILL.md +1 -1
- package/plugin/skills/slm-loop/SKILL.md +1 -1
- package/plugin/skills/slm-mesh/SKILL.md +1 -1
- package/plugin/skills/slm-profile/SKILL.md +1 -1
- package/plugin/skills/slm-recall/SKILL.md +1 -1
- package/plugin/skills/slm-remember/SKILL.md +1 -1
- package/plugin/skills/slm-scope/SKILL.md +1 -1
- package/plugin/skills/slm-session/SKILL.md +1 -1
- package/plugin/skills/slm-status/SKILL.md +1 -1
- package/plugin-src/agents/slm-memory-advisor.md +1 -1
- package/plugin-src/agents/slm-optimize-advisor.md +1 -1
- package/plugin-src/rules/AGENTS.md +1 -1
- package/plugin-src/skills/slm-cache/SKILL.md +1 -1
- package/plugin-src/skills/slm-compress/SKILL.md +1 -1
- package/plugin-src/skills/slm-governance/SKILL.md +1 -1
- package/plugin-src/skills/slm-graph/SKILL.md +1 -1
- package/plugin-src/skills/slm-loop/SKILL.md +1 -1
- package/plugin-src/skills/slm-mesh/SKILL.md +1 -1
- package/plugin-src/skills/slm-profile/SKILL.md +1 -1
- package/plugin-src/skills/slm-recall/SKILL.md +1 -1
- package/plugin-src/skills/slm-remember/SKILL.md +1 -1
- package/plugin-src/skills/slm-scope/SKILL.md +1 -1
- package/plugin-src/skills/slm-session/SKILL.md +1 -1
- package/plugin-src/skills/slm-status/SKILL.md +1 -1
- package/scripts/postinstall.js +71 -2
- package/pyproject.toml +0 -250
- package/src/superlocalmemory/__init__.py +0 -82
- package/src/superlocalmemory/access/__init__.py +0 -3
- package/src/superlocalmemory/access/rbac.py +0 -575
- package/src/superlocalmemory/attribution/__init__.py +0 -9
- package/src/superlocalmemory/attribution/signer.py +0 -173
- package/src/superlocalmemory/attribution/watermark.py +0 -189
- package/src/superlocalmemory/brain/__init__.py +0 -5
- package/src/superlocalmemory/brain/truth.py +0 -418
- package/src/superlocalmemory/cli/__init__.py +0 -5
- package/src/superlocalmemory/cli/__main__.py +0 -17
- package/src/superlocalmemory/cli/_lazy_init.py +0 -115
- package/src/superlocalmemory/cli/cache_cmd.py +0 -198
- package/src/superlocalmemory/cli/commands.py +0 -4710
- package/src/superlocalmemory/cli/compress_cmd.py +0 -151
- package/src/superlocalmemory/cli/context_commands.py +0 -193
- package/src/superlocalmemory/cli/daemon.py +0 -909
- package/src/superlocalmemory/cli/db_migrate.py +0 -150
- package/src/superlocalmemory/cli/diagnostics_cmd.py +0 -101
- package/src/superlocalmemory/cli/escape_hatch.py +0 -220
- package/src/superlocalmemory/cli/evidence_cmd.py +0 -103
- package/src/superlocalmemory/cli/gdpr_cmd.py +0 -792
- package/src/superlocalmemory/cli/gdpr_io.py +0 -109
- package/src/superlocalmemory/cli/help_cmd.py +0 -197
- package/src/superlocalmemory/cli/host_upgrades.py +0 -189
- package/src/superlocalmemory/cli/ingest_cmd.py +0 -327
- package/src/superlocalmemory/cli/json_output.py +0 -81
- package/src/superlocalmemory/cli/loop_cmd.py +0 -187
- package/src/superlocalmemory/cli/main.py +0 -1145
- package/src/superlocalmemory/cli/mesh_cmd.py +0 -38
- package/src/superlocalmemory/cli/migrate_cmd.py +0 -55
- package/src/superlocalmemory/cli/ops_cmd.py +0 -281
- package/src/superlocalmemory/cli/optimize_cmd.py +0 -179
- package/src/superlocalmemory/cli/optimize_constants.py +0 -31
- package/src/superlocalmemory/cli/pending_store.py +0 -296
- package/src/superlocalmemory/cli/proxy_cmd.py +0 -108
- package/src/superlocalmemory/cli/scale_engine_cmd.py +0 -56
- package/src/superlocalmemory/cli/service_installer.py +0 -373
- package/src/superlocalmemory/cli/setup_wizard.py +0 -1162
- package/src/superlocalmemory/cli/summary_cmd.py +0 -215
- package/src/superlocalmemory/cli/version_banner.py +0 -202
- package/src/superlocalmemory/cli/wizard_v3426_options.py +0 -129
- package/src/superlocalmemory/code_graph/__init__.py +0 -46
- package/src/superlocalmemory/code_graph/blast_radius.py +0 -177
- package/src/superlocalmemory/code_graph/bridge/__init__.py +0 -36
- package/src/superlocalmemory/code_graph/bridge/entity_resolver.py +0 -490
- package/src/superlocalmemory/code_graph/bridge/event_listeners.py +0 -206
- package/src/superlocalmemory/code_graph/bridge/fact_enricher.py +0 -159
- package/src/superlocalmemory/code_graph/bridge/hebbian_linker.py +0 -170
- package/src/superlocalmemory/code_graph/bridge/maintenance.py +0 -220
- package/src/superlocalmemory/code_graph/bridge/temporal_checker.py +0 -152
- package/src/superlocalmemory/code_graph/changes.py +0 -363
- package/src/superlocalmemory/code_graph/communities.py +0 -299
- package/src/superlocalmemory/code_graph/config.py +0 -154
- package/src/superlocalmemory/code_graph/database.py +0 -526
- package/src/superlocalmemory/code_graph/extractors/__init__.py +0 -95
- package/src/superlocalmemory/code_graph/extractors/python.py +0 -413
- package/src/superlocalmemory/code_graph/extractors/typescript.py +0 -556
- package/src/superlocalmemory/code_graph/flows.py +0 -350
- package/src/superlocalmemory/code_graph/git_hooks.py +0 -226
- package/src/superlocalmemory/code_graph/graph_engine.py +0 -295
- package/src/superlocalmemory/code_graph/graph_store.py +0 -335
- package/src/superlocalmemory/code_graph/incremental.py +0 -200
- package/src/superlocalmemory/code_graph/models.py +0 -130
- package/src/superlocalmemory/code_graph/parser.py +0 -687
- package/src/superlocalmemory/code_graph/resolver.py +0 -321
- package/src/superlocalmemory/code_graph/search.py +0 -460
- package/src/superlocalmemory/code_graph/service.py +0 -95
- package/src/superlocalmemory/code_graph/watcher.py +0 -207
- package/src/superlocalmemory/compliance/__init__.py +0 -0
- package/src/superlocalmemory/compliance/abac.py +0 -204
- package/src/superlocalmemory/compliance/audit.py +0 -385
- package/src/superlocalmemory/compliance/eu_ai_act.py +0 -101
- package/src/superlocalmemory/compliance/gdpr.py +0 -1479
- package/src/superlocalmemory/compliance/lifecycle.py +0 -158
- package/src/superlocalmemory/compliance/retention.py +0 -415
- package/src/superlocalmemory/compliance/scheduler.py +0 -217
- package/src/superlocalmemory/contracts/__init__.py +0 -1
- package/src/superlocalmemory/contracts/schemas/agent-experience-v1.schema.json +0 -92
- package/src/superlocalmemory/contracts/schemas/agent-integration-contract-v2.schema.json +0 -46
- package/src/superlocalmemory/contracts/schemas/cognitive-turn-receipt-v1.schema.json +0 -59
- package/src/superlocalmemory/contracts/v402.py +0 -62
- package/src/superlocalmemory/core/__init__.py +0 -0
- package/src/superlocalmemory/core/actor_context.py +0 -166
- package/src/superlocalmemory/core/admission.py +0 -769
- package/src/superlocalmemory/core/backend_orchestrator.py +0 -637
- package/src/superlocalmemory/core/block_hygiene.py +0 -147
- package/src/superlocalmemory/core/community_summary.py +0 -267
- package/src/superlocalmemory/core/component_healer.py +0 -144
- package/src/superlocalmemory/core/component_registry.py +0 -514
- package/src/superlocalmemory/core/config.py +0 -2204
- package/src/superlocalmemory/core/consolidation_engine.py +0 -983
- package/src/superlocalmemory/core/context_cache.py +0 -574
- package/src/superlocalmemory/core/derivation_lineage.py +0 -246
- package/src/superlocalmemory/core/embedding_worker.py +0 -208
- package/src/superlocalmemory/core/embeddings.py +0 -1052
- package/src/superlocalmemory/core/engine.py +0 -1395
- package/src/superlocalmemory/core/engine_capabilities.py +0 -24
- package/src/superlocalmemory/core/engine_ingestion.py +0 -983
- package/src/superlocalmemory/core/engine_lock.py +0 -75
- package/src/superlocalmemory/core/engine_wiring.py +0 -776
- package/src/superlocalmemory/core/entity_community.py +0 -178
- package/src/superlocalmemory/core/error_envelope.py +0 -60
- package/src/superlocalmemory/core/evidence_bundle.py +0 -528
- package/src/superlocalmemory/core/fact_consolidator.py +0 -812
- package/src/superlocalmemory/core/file_lock.py +0 -92
- package/src/superlocalmemory/core/graph_analyzer.py +0 -456
- package/src/superlocalmemory/core/graph_metrics.py +0 -597
- package/src/superlocalmemory/core/graph_pruner.py +0 -939
- package/src/superlocalmemory/core/health_monitor.py +0 -338
- package/src/superlocalmemory/core/hooks.py +0 -65
- package/src/superlocalmemory/core/ingest_gate.py +0 -133
- package/src/superlocalmemory/core/ingest_policy.py +0 -38
- package/src/superlocalmemory/core/ingestion_command.py +0 -1042
- package/src/superlocalmemory/core/injection.py +0 -434
- package/src/superlocalmemory/core/install_detector.py +0 -131
- package/src/superlocalmemory/core/key_expander.py +0 -138
- package/src/superlocalmemory/core/lifecycle_state.py +0 -153
- package/src/superlocalmemory/core/maintenance.py +0 -777
- package/src/superlocalmemory/core/maintenance_scheduler.py +0 -507
- package/src/superlocalmemory/core/materialization_control.py +0 -20
- package/src/superlocalmemory/core/mcp_embedder_proxy.py +0 -89
- package/src/superlocalmemory/core/memory_health.py +0 -266
- package/src/superlocalmemory/core/mode_capability.py +0 -111
- package/src/superlocalmemory/core/modes.py +0 -168
- package/src/superlocalmemory/core/mutations.py +0 -688
- package/src/superlocalmemory/core/ollama_embedder.py +0 -266
- package/src/superlocalmemory/core/ollama_validator.py +0 -315
- package/src/superlocalmemory/core/operation_policy.py +0 -92
- package/src/superlocalmemory/core/operation_policy_registry.py +0 -542
- package/src/superlocalmemory/core/operation_request.py +0 -127
- package/src/superlocalmemory/core/ops_remediation.py +0 -542
- package/src/superlocalmemory/core/pii.py +0 -105
- package/src/superlocalmemory/core/platform_utils.py +0 -138
- package/src/superlocalmemory/core/profiles.py +0 -234
- package/src/superlocalmemory/core/progressive_abstraction.py +0 -208
- package/src/superlocalmemory/core/projection_drain.py +0 -380
- package/src/superlocalmemory/core/queue_consumer.py +0 -168
- package/src/superlocalmemory/core/ram_lock.py +0 -160
- package/src/superlocalmemory/core/rate_limit.py +0 -151
- package/src/superlocalmemory/core/recall_gate.py +0 -95
- package/src/superlocalmemory/core/recall_pipeline.py +0 -1337
- package/src/superlocalmemory/core/recall_queue.py +0 -377
- package/src/superlocalmemory/core/recall_worker.py +0 -414
- package/src/superlocalmemory/core/registry.py +0 -121
- package/src/superlocalmemory/core/remember_admission.py +0 -161
- package/src/superlocalmemory/core/remember_runtime.py +0 -1190
- package/src/superlocalmemory/core/remote_mode.py +0 -214
- package/src/superlocalmemory/core/reranker_worker.py +0 -338
- package/src/superlocalmemory/core/safe_fs.py +0 -108
- package/src/superlocalmemory/core/scale_autopromote.py +0 -196
- package/src/superlocalmemory/core/scale_engine.py +0 -915
- package/src/superlocalmemory/core/score_contract.py +0 -82
- package/src/superlocalmemory/core/security_primitives.py +0 -672
- package/src/superlocalmemory/core/session_identity.py +0 -98
- package/src/superlocalmemory/core/shadow_router.py +0 -319
- package/src/superlocalmemory/core/slm_disabled.py +0 -85
- package/src/superlocalmemory/core/status_contract.py +0 -108
- package/src/superlocalmemory/core/store_pipeline.py +0 -1404
- package/src/superlocalmemory/core/summarizer.py +0 -200
- package/src/superlocalmemory/core/tier_manager.py +0 -461
- package/src/superlocalmemory/core/topic_signature.py +0 -156
- package/src/superlocalmemory/core/transactions/__init__.py +0 -78
- package/src/superlocalmemory/core/transactions/concrete_owners.py +0 -604
- package/src/superlocalmemory/core/transactions/erasure.py +0 -825
- package/src/superlocalmemory/core/transactions/manifest.py +0 -255
- package/src/superlocalmemory/core/transactions/manifest_key.py +0 -155
- package/src/superlocalmemory/core/transactions/obligations.py +0 -272
- package/src/superlocalmemory/core/transactions/owners.py +0 -114
- package/src/superlocalmemory/core/transactions/reconciler.py +0 -285
- package/src/superlocalmemory/core/transactions/service.py +0 -330
- package/src/superlocalmemory/core/worker_pool.py +0 -377
- package/src/superlocalmemory/core/working_memory.py +0 -288
- package/src/superlocalmemory/dynamics/__init__.py +0 -0
- package/src/superlocalmemory/dynamics/activation_guided_quantization.py +0 -374
- package/src/superlocalmemory/dynamics/eap_scheduler.py +0 -294
- package/src/superlocalmemory/dynamics/ebbinghaus_langevin_coupling.py +0 -171
- package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +0 -227
- package/src/superlocalmemory/encoding/__init__.py +0 -0
- package/src/superlocalmemory/encoding/auto_linker.py +0 -308
- package/src/superlocalmemory/encoding/cognitive_consolidator.py +0 -899
- package/src/superlocalmemory/encoding/consolidator.py +0 -472
- package/src/superlocalmemory/encoding/context_generator.py +0 -175
- package/src/superlocalmemory/encoding/emotional.py +0 -189
- package/src/superlocalmemory/encoding/entity_reflexion.py +0 -200
- package/src/superlocalmemory/encoding/entity_resolver.py +0 -687
- package/src/superlocalmemory/encoding/entropy_gate.py +0 -101
- package/src/superlocalmemory/encoding/fact_extractor.py +0 -877
- package/src/superlocalmemory/encoding/foresight.py +0 -93
- package/src/superlocalmemory/encoding/graph_builder.py +0 -346
- package/src/superlocalmemory/encoding/observation_builder.py +0 -177
- package/src/superlocalmemory/encoding/prospective_markers.py +0 -262
- package/src/superlocalmemory/encoding/scene_builder.py +0 -410
- package/src/superlocalmemory/encoding/signal_inference.py +0 -90
- package/src/superlocalmemory/encoding/temporal_parser.py +0 -432
- package/src/superlocalmemory/encoding/temporal_validator.py +0 -572
- package/src/superlocalmemory/encoding/type_router.py +0 -237
- package/src/superlocalmemory/evaluation/__init__.py +0 -13
- package/src/superlocalmemory/evaluation/calibration.py +0 -308
- package/src/superlocalmemory/evolution/__init__.py +0 -29
- package/src/superlocalmemory/evolution/blind_verifier.py +0 -122
- package/src/superlocalmemory/evolution/budget.py +0 -356
- package/src/superlocalmemory/evolution/evolution_store.py +0 -619
- package/src/superlocalmemory/evolution/llm_dispatch.py +0 -559
- package/src/superlocalmemory/evolution/model_selection.py +0 -175
- package/src/superlocalmemory/evolution/mutation_generator.py +0 -226
- package/src/superlocalmemory/evolution/skill_activator.py +0 -270
- package/src/superlocalmemory/evolution/skill_evolver.py +0 -928
- package/src/superlocalmemory/evolution/triggers.py +0 -376
- package/src/superlocalmemory/evolution/types.py +0 -114
- package/src/superlocalmemory/graph/__init__.py +0 -9
- package/src/superlocalmemory/graph/cozo_adjacency.py +0 -122
- package/src/superlocalmemory/graph/cozo_backend.py +0 -751
- package/src/superlocalmemory/hooks/__init__.py +0 -3
- package/src/superlocalmemory/hooks/_outcome_common.py +0 -523
- package/src/superlocalmemory/hooks/adapter_base.py +0 -347
- package/src/superlocalmemory/hooks/antigravity_adapter.py +0 -171
- package/src/superlocalmemory/hooks/auto_capture.py +0 -133
- package/src/superlocalmemory/hooks/auto_invoker.py +0 -521
- package/src/superlocalmemory/hooks/auto_parameterize.py +0 -147
- package/src/superlocalmemory/hooks/auto_recall.py +0 -191
- package/src/superlocalmemory/hooks/auto_recall_hook.py +0 -251
- package/src/superlocalmemory/hooks/before_web_hook.py +0 -131
- package/src/superlocalmemory/hooks/claude_code_hooks.py +0 -637
- package/src/superlocalmemory/hooks/codex_assets.py +0 -251
- package/src/superlocalmemory/hooks/codex_hooks.py +0 -186
- package/src/superlocalmemory/hooks/context_payload.py +0 -311
- package/src/superlocalmemory/hooks/copilot_adapter.py +0 -208
- package/src/superlocalmemory/hooks/cross_platform_connector.py +0 -90
- package/src/superlocalmemory/hooks/cursor_adapter.py +0 -173
- package/src/superlocalmemory/hooks/hook_daemon.py +0 -295
- package/src/superlocalmemory/hooks/hook_handlers.py +0 -822
- package/src/superlocalmemory/hooks/ide_connector.py +0 -246
- package/src/superlocalmemory/hooks/memory_protocol.py +0 -158
- package/src/superlocalmemory/hooks/portable_kit.py +0 -755
- package/src/superlocalmemory/hooks/post_tool_async_hook.py +0 -183
- package/src/superlocalmemory/hooks/post_tool_outcome_hook.py +0 -351
- package/src/superlocalmemory/hooks/prewarm_auth.py +0 -187
- package/src/superlocalmemory/hooks/rules_engine.py +0 -99
- package/src/superlocalmemory/hooks/session_registry.py +0 -330
- package/src/superlocalmemory/hooks/stop_outcome_hook.py +0 -138
- package/src/superlocalmemory/hooks/sync_loop.py +0 -114
- package/src/superlocalmemory/hooks/topic_shift_hook.py +0 -302
- package/src/superlocalmemory/hooks/user_prompt_hook.py +0 -131
- package/src/superlocalmemory/hooks/user_prompt_rehash_hook.py +0 -210
- package/src/superlocalmemory/infra/__init__.py +0 -3
- package/src/superlocalmemory/infra/auth_middleware.py +0 -145
- package/src/superlocalmemory/infra/backup.py +0 -974
- package/src/superlocalmemory/infra/backup_obligations.py +0 -423
- package/src/superlocalmemory/infra/cache_manager.py +0 -267
- package/src/superlocalmemory/infra/cloud_backup.py +0 -788
- package/src/superlocalmemory/infra/daemon_identity.py +0 -300
- package/src/superlocalmemory/infra/data_root.py +0 -238
- package/src/superlocalmemory/infra/event_bus.py +0 -637
- package/src/superlocalmemory/infra/local_diagnostics.py +0 -327
- package/src/superlocalmemory/infra/pid_manager.py +0 -193
- package/src/superlocalmemory/infra/process_identity.py +0 -180
- package/src/superlocalmemory/infra/process_reaper.py +0 -624
- package/src/superlocalmemory/infra/rate_limiter.py +0 -228
- package/src/superlocalmemory/infra/self_heal.py +0 -401
- package/src/superlocalmemory/infra/version_integrity.py +0 -229
- package/src/superlocalmemory/ingestion/__init__.py +0 -13
- package/src/superlocalmemory/ingestion/adapter_manager.py +0 -255
- package/src/superlocalmemory/ingestion/base_adapter.py +0 -171
- package/src/superlocalmemory/ingestion/calendar_adapter.py +0 -349
- package/src/superlocalmemory/ingestion/credentials.py +0 -125
- package/src/superlocalmemory/ingestion/gmail_adapter.py +0 -378
- package/src/superlocalmemory/ingestion/parsers.py +0 -100
- package/src/superlocalmemory/ingestion/transcript_adapter.py +0 -161
- package/src/superlocalmemory/integrations/__init__.py +0 -1
- package/src/superlocalmemory/integrations/bounded_loops_mcp.py +0 -431
- package/src/superlocalmemory/integrations/bounded_loops_v051.py +0 -236
- package/src/superlocalmemory/learning/__init__.py +0 -0
- package/src/superlocalmemory/learning/adaptive.py +0 -172
- package/src/superlocalmemory/learning/arm_catalog.py +0 -97
- package/src/superlocalmemory/learning/assertion_miner.py +0 -403
- package/src/superlocalmemory/learning/bandit.py +0 -654
- package/src/superlocalmemory/learning/bandit_cache.py +0 -131
- package/src/superlocalmemory/learning/behavioral.py +0 -542
- package/src/superlocalmemory/learning/bootstrap.py +0 -298
- package/src/superlocalmemory/learning/consolidation_cycle.py +0 -398
- package/src/superlocalmemory/learning/consolidation_quantization_worker.py +0 -115
- package/src/superlocalmemory/learning/consolidation_worker.py +0 -261
- package/src/superlocalmemory/learning/cross_project.py +0 -408
- package/src/superlocalmemory/learning/database.py +0 -698
- package/src/superlocalmemory/learning/dedup_hnsw.py +0 -413
- package/src/superlocalmemory/learning/engagement.py +0 -487
- package/src/superlocalmemory/learning/engagement_features.py +0 -279
- package/src/superlocalmemory/learning/ensemble.py +0 -309
- package/src/superlocalmemory/learning/entity_compiler.py +0 -356
- package/src/superlocalmemory/learning/fact_outcome_joins.py +0 -207
- package/src/superlocalmemory/learning/features.py +0 -138
- package/src/superlocalmemory/learning/feedback.py +0 -724
- package/src/superlocalmemory/learning/forgetting_scheduler.py +0 -375
- package/src/superlocalmemory/learning/hnsw_dedup.py +0 -69
- package/src/superlocalmemory/learning/labeler.py +0 -85
- package/src/superlocalmemory/learning/legacy_migration.py +0 -316
- package/src/superlocalmemory/learning/lightgbm_subprocess.py +0 -236
- package/src/superlocalmemory/learning/memory_merge.py +0 -175
- package/src/superlocalmemory/learning/model_cache.py +0 -267
- package/src/superlocalmemory/learning/model_rollback.py +0 -281
- package/src/superlocalmemory/learning/outcome_queue.py +0 -306
- package/src/superlocalmemory/learning/outcomes.py +0 -286
- package/src/superlocalmemory/learning/pattern_miner.py +0 -465
- package/src/superlocalmemory/learning/pattern_miner_constants.py +0 -90
- package/src/superlocalmemory/learning/pcos.py +0 -291
- package/src/superlocalmemory/learning/project_context.py +0 -366
- package/src/superlocalmemory/learning/propensity.py +0 -131
- package/src/superlocalmemory/learning/ranker.py +0 -300
- package/src/superlocalmemory/learning/ranker_common.py +0 -163
- package/src/superlocalmemory/learning/ranker_retrain_legacy.py +0 -210
- package/src/superlocalmemory/learning/ranker_retrain_online.py +0 -423
- package/src/superlocalmemory/learning/reward.py +0 -888
- package/src/superlocalmemory/learning/reward_archive.py +0 -223
- package/src/superlocalmemory/learning/reward_boost.py +0 -211
- package/src/superlocalmemory/learning/reward_from_outcomes.py +0 -365
- package/src/superlocalmemory/learning/reward_model.py +0 -144
- package/src/superlocalmemory/learning/reward_proxy.py +0 -578
- package/src/superlocalmemory/learning/shadow_test.py +0 -524
- package/src/superlocalmemory/learning/signal_kinds.py +0 -79
- package/src/superlocalmemory/learning/signal_worker.py +0 -268
- package/src/superlocalmemory/learning/signals.py +0 -646
- package/src/superlocalmemory/learning/skill_performance_miner.py +0 -422
- package/src/superlocalmemory/learning/source_quality.py +0 -828
- package/src/superlocalmemory/learning/trigram_index.py +0 -548
- package/src/superlocalmemory/learning/workflows.py +0 -309
- package/src/superlocalmemory/llm/__init__.py +0 -0
- package/src/superlocalmemory/llm/backbone.py +0 -364
- package/src/superlocalmemory/loops/__init__.py +0 -58
- package/src/superlocalmemory/loops/budget.py +0 -58
- package/src/superlocalmemory/loops/engine.py +0 -174
- package/src/superlocalmemory/loops/ledger.py +0 -298
- package/src/superlocalmemory/loops/models.py +0 -152
- package/src/superlocalmemory/loops/rules.py +0 -52
- package/src/superlocalmemory/math/__init__.py +0 -0
- package/src/superlocalmemory/math/ebbinghaus.py +0 -352
- package/src/superlocalmemory/math/fisher.py +0 -356
- package/src/superlocalmemory/math/fisher_quantized.py +0 -255
- package/src/superlocalmemory/math/hopfield.py +0 -282
- package/src/superlocalmemory/math/langevin.py +0 -411
- package/src/superlocalmemory/math/polar_quant.py +0 -414
- package/src/superlocalmemory/math/qjl.py +0 -115
- package/src/superlocalmemory/math/sheaf.py +0 -261
- package/src/superlocalmemory/math/turbo_quant.py +0 -318
- package/src/superlocalmemory/mcp/__init__.py +0 -0
- package/src/superlocalmemory/mcp/_daemon_proxy.py +0 -203
- package/src/superlocalmemory/mcp/_pool_adapter.py +0 -181
- package/src/superlocalmemory/mcp/_stdin_guard.py +0 -60
- package/src/superlocalmemory/mcp/agent_context.py +0 -115
- package/src/superlocalmemory/mcp/cli_fallback.py +0 -602
- package/src/superlocalmemory/mcp/http_transport.py +0 -85
- package/src/superlocalmemory/mcp/profiles.py +0 -154
- package/src/superlocalmemory/mcp/resources.py +0 -281
- package/src/superlocalmemory/mcp/server.py +0 -480
- package/src/superlocalmemory/mcp/session_binding.py +0 -98
- package/src/superlocalmemory/mcp/shared.py +0 -112
- package/src/superlocalmemory/mcp/tools.py +0 -18
- package/src/superlocalmemory/mcp/tools_active.py +0 -958
- package/src/superlocalmemory/mcp/tools_brain.py +0 -298
- package/src/superlocalmemory/mcp/tools_code_graph.py +0 -1717
- package/src/superlocalmemory/mcp/tools_context.py +0 -239
- package/src/superlocalmemory/mcp/tools_core.py +0 -1112
- package/src/superlocalmemory/mcp/tools_evolution.py +0 -343
- package/src/superlocalmemory/mcp/tools_learning.py +0 -393
- package/src/superlocalmemory/mcp/tools_loops.py +0 -345
- package/src/superlocalmemory/mcp/tools_mesh.py +0 -429
- package/src/superlocalmemory/mcp/tools_ops.py +0 -115
- package/src/superlocalmemory/mcp/tools_optimize.py +0 -322
- package/src/superlocalmemory/mcp/tools_summaries.py +0 -147
- package/src/superlocalmemory/mcp/tools_v28.py +0 -292
- package/src/superlocalmemory/mcp/tools_v3.py +0 -398
- package/src/superlocalmemory/mcp/tools_v33.py +0 -507
- package/src/superlocalmemory/mesh/__init__.py +0 -12
- package/src/superlocalmemory/mesh/broker.py +0 -812
- package/src/superlocalmemory/mesh/broker_security.py +0 -470
- package/src/superlocalmemory/mesh/discovery.py +0 -365
- package/src/superlocalmemory/mesh/lock_protocol.py +0 -313
- package/src/superlocalmemory/mesh/node_identity.py +0 -97
- package/src/superlocalmemory/mesh/outbox_remote.py +0 -429
- package/src/superlocalmemory/mesh/remote_sync.py +0 -829
- package/src/superlocalmemory/mesh/state_sync.py +0 -286
- package/src/superlocalmemory/migrations/__init__.py +0 -5
- package/src/superlocalmemory/migrations/v3_4_25_to_v3_4_26.py +0 -144
- package/src/superlocalmemory/optimize/NOTICE +0 -6
- package/src/superlocalmemory/optimize/__init__.py +0 -0
- package/src/superlocalmemory/optimize/adapters/__init__.py +0 -68
- package/src/superlocalmemory/optimize/adapters/_agent_registry.py +0 -120
- package/src/superlocalmemory/optimize/adapters/anthropic_adapter.py +0 -112
- package/src/superlocalmemory/optimize/adapters/openai_adapter.py +0 -122
- package/src/superlocalmemory/optimize/adapters/wrap.py +0 -228
- package/src/superlocalmemory/optimize/cache/__init__.py +0 -31
- package/src/superlocalmemory/optimize/cache/boundary_store.py +0 -488
- package/src/superlocalmemory/optimize/cache/centroid_store.py +0 -199
- package/src/superlocalmemory/optimize/cache/context_key.py +0 -67
- package/src/superlocalmemory/optimize/cache/exact.py +0 -88
- package/src/superlocalmemory/optimize/cache/invalidation.py +0 -36
- package/src/superlocalmemory/optimize/cache/key_builder.py +0 -111
- package/src/superlocalmemory/optimize/cache/manager.py +0 -737
- package/src/superlocalmemory/optimize/cache/semantic.py +0 -637
- package/src/superlocalmemory/optimize/cache/stampede.py +0 -50
- package/src/superlocalmemory/optimize/compress/__init__.py +0 -17
- package/src/superlocalmemory/optimize/compress/align.py +0 -159
- package/src/superlocalmemory/optimize/compress/ccr.py +0 -116
- package/src/superlocalmemory/optimize/compress/prose_llmlingua.py +0 -71
- package/src/superlocalmemory/optimize/compress/router.py +0 -667
- package/src/superlocalmemory/optimize/config/__init__.py +0 -56
- package/src/superlocalmemory/optimize/config/defaults.py +0 -43
- package/src/superlocalmemory/optimize/config/schema.py +0 -327
- package/src/superlocalmemory/optimize/config/store.py +0 -270
- package/src/superlocalmemory/optimize/metrics/__init__.py +0 -8
- package/src/superlocalmemory/optimize/metrics/counters.py +0 -155
- package/src/superlocalmemory/optimize/metrics/estimator.py +0 -87
- package/src/superlocalmemory/optimize/metrics/exporters.py +0 -77
- package/src/superlocalmemory/optimize/metrics/persistence.py +0 -115
- package/src/superlocalmemory/optimize/proxy/__init__.py +0 -28
- package/src/superlocalmemory/optimize/proxy/_helpers.py +0 -730
- package/src/superlocalmemory/optimize/proxy/anthropic_surface.py +0 -375
- package/src/superlocalmemory/optimize/proxy/capture.py +0 -550
- package/src/superlocalmemory/optimize/proxy/gemini_surface.py +0 -528
- package/src/superlocalmemory/optimize/proxy/lifecycle.py +0 -126
- package/src/superlocalmemory/optimize/proxy/openai_surface.py +0 -465
- package/src/superlocalmemory/optimize/proxy/server.py +0 -199
- package/src/superlocalmemory/optimize/proxy/vertex_surface.py +0 -246
- package/src/superlocalmemory/optimize/storage/__init__.py +0 -0
- package/src/superlocalmemory/optimize/storage/db.py +0 -1185
- package/src/superlocalmemory/optimize/storage/schema.py +0 -205
- package/src/superlocalmemory/parameterization/__init__.py +0 -47
- package/src/superlocalmemory/parameterization/cross_project.py +0 -12
- package/src/superlocalmemory/parameterization/pattern_extractor.py +0 -584
- package/src/superlocalmemory/parameterization/pii_filter.py +0 -106
- package/src/superlocalmemory/parameterization/prompt_injector.py +0 -219
- package/src/superlocalmemory/parameterization/prompt_lifecycle.py +0 -281
- package/src/superlocalmemory/parameterization/soft_prompt_generator.py +0 -542
- package/src/superlocalmemory/parameterization/workflow_miner.py +0 -17
- package/src/superlocalmemory/reliability/__init__.py +0 -45
- package/src/superlocalmemory/reliability/join_liveness.py +0 -301
- package/src/superlocalmemory/reliability/prior_distance.py +0 -243
- package/src/superlocalmemory/retrieval/__init__.py +0 -0
- package/src/superlocalmemory/retrieval/agentic.py +0 -367
- package/src/superlocalmemory/retrieval/ann_index.py +0 -235
- package/src/superlocalmemory/retrieval/bm25_channel.py +0 -451
- package/src/superlocalmemory/retrieval/bridge_discovery.py +0 -253
- package/src/superlocalmemory/retrieval/channel_registry.py +0 -154
- package/src/superlocalmemory/retrieval/channel_status.py +0 -117
- package/src/superlocalmemory/retrieval/engine.py +0 -1615
- package/src/superlocalmemory/retrieval/entity_channel.py +0 -994
- package/src/superlocalmemory/retrieval/forgetting_filter.py +0 -160
- package/src/superlocalmemory/retrieval/fusion.py +0 -81
- package/src/superlocalmemory/retrieval/graph_adjacency.py +0 -219
- package/src/superlocalmemory/retrieval/hopfield_channel.py +0 -465
- package/src/superlocalmemory/retrieval/profile_channel.py +0 -105
- package/src/superlocalmemory/retrieval/quantization_aware_search.py +0 -147
- package/src/superlocalmemory/retrieval/remote_reranker.py +0 -758
- package/src/superlocalmemory/retrieval/reranker.py +0 -674
- package/src/superlocalmemory/retrieval/scope_policy.py +0 -126
- package/src/superlocalmemory/retrieval/semantic_channel.py +0 -638
- package/src/superlocalmemory/retrieval/spreading.py +0 -288
- package/src/superlocalmemory/retrieval/spreading_activation.py +0 -616
- package/src/superlocalmemory/retrieval/strategy.py +0 -248
- package/src/superlocalmemory/retrieval/temporal_channel.py +0 -433
- package/src/superlocalmemory/retrieval/temporal_frame.py +0 -102
- package/src/superlocalmemory/retrieval/temporal_utils.py +0 -122
- package/src/superlocalmemory/retrieval/temporal_validity_filter.py +0 -499
- package/src/superlocalmemory/retrieval/time_window.py +0 -181
- package/src/superlocalmemory/retrieval/vector_store.py +0 -863
- package/src/superlocalmemory/server/__init__.py +0 -1
- package/src/superlocalmemory/server/api.py +0 -310
- package/src/superlocalmemory/server/asset_versions.py +0 -171
- package/src/superlocalmemory/server/bandit_loops.py +0 -158
- package/src/superlocalmemory/server/config_file.py +0 -90
- package/src/superlocalmemory/server/consolidation_runner.py +0 -140
- package/src/superlocalmemory/server/egress_policy.py +0 -258
- package/src/superlocalmemory/server/loopback.py +0 -85
- package/src/superlocalmemory/server/middleware/__init__.py +0 -11
- package/src/superlocalmemory/server/middleware/security_headers.py +0 -144
- package/src/superlocalmemory/server/origin.py +0 -55
- package/src/superlocalmemory/server/profile_runtime.py +0 -515
- package/src/superlocalmemory/server/rbac_enforce.py +0 -194
- package/src/superlocalmemory/server/recall_health.py +0 -343
- package/src/superlocalmemory/server/recall_serializer.py +0 -320
- package/src/superlocalmemory/server/route_mutations.py +0 -104
- package/src/superlocalmemory/server/routes/__init__.py +0 -4
- package/src/superlocalmemory/server/routes/abstraction.py +0 -314
- package/src/superlocalmemory/server/routes/adapters.py +0 -63
- package/src/superlocalmemory/server/routes/agents.py +0 -303
- package/src/superlocalmemory/server/routes/backup.py +0 -869
- package/src/superlocalmemory/server/routes/behavioral.py +0 -659
- package/src/superlocalmemory/server/routes/brain.py +0 -1892
- package/src/superlocalmemory/server/routes/chat.py +0 -393
- package/src/superlocalmemory/server/routes/compliance.py +0 -533
- package/src/superlocalmemory/server/routes/config_api.py +0 -703
- package/src/superlocalmemory/server/routes/data_io.py +0 -329
- package/src/superlocalmemory/server/routes/entity.py +0 -237
- package/src/superlocalmemory/server/routes/events.py +0 -214
- package/src/superlocalmemory/server/routes/evolution.py +0 -510
- package/src/superlocalmemory/server/routes/helpers.py +0 -499
- package/src/superlocalmemory/server/routes/ingest.py +0 -137
- package/src/superlocalmemory/server/routes/insights.py +0 -366
- package/src/superlocalmemory/server/routes/learning.py +0 -834
- package/src/superlocalmemory/server/routes/learning_telemetry.py +0 -154
- package/src/superlocalmemory/server/routes/lifecycle.py +0 -184
- package/src/superlocalmemory/server/routes/memories.py +0 -1661
- package/src/superlocalmemory/server/routes/mesh.py +0 -517
- package/src/superlocalmemory/server/routes/mesh_lock.py +0 -54
- package/src/superlocalmemory/server/routes/mesh_state.py +0 -63
- package/src/superlocalmemory/server/routes/optimize.py +0 -197
- package/src/superlocalmemory/server/routes/prewarm.py +0 -173
- package/src/superlocalmemory/server/routes/profiles.py +0 -292
- package/src/superlocalmemory/server/routes/ratelimit.py +0 -132
- package/src/superlocalmemory/server/routes/rbac.py +0 -366
- package/src/superlocalmemory/server/routes/stats.py +0 -385
- package/src/superlocalmemory/server/routes/tiers.py +0 -222
- package/src/superlocalmemory/server/routes/timeline.py +0 -258
- package/src/superlocalmemory/server/routes/token.py +0 -90
- package/src/superlocalmemory/server/routes/v3_api.py +0 -3023
- package/src/superlocalmemory/server/routes/ws.py +0 -171
- package/src/superlocalmemory/server/security_middleware.py +0 -89
- package/src/superlocalmemory/server/ui.py +0 -354
- package/src/superlocalmemory/server/unified_daemon.py +0 -6326
- package/src/superlocalmemory/server/write_identity.py +0 -195
- package/src/superlocalmemory/storage/__init__.py +0 -0
- package/src/superlocalmemory/storage/_migration_internals.py +0 -638
- package/src/superlocalmemory/storage/_schema_version.py +0 -174
- package/src/superlocalmemory/storage/access_log.py +0 -170
- package/src/superlocalmemory/storage/admission_codec.py +0 -129
- package/src/superlocalmemory/storage/admission_journal.py +0 -843
- package/src/superlocalmemory/storage/agent_experience.py +0 -546
- package/src/superlocalmemory/storage/backup.py +0 -531
- package/src/superlocalmemory/storage/correction_cases.py +0 -670
- package/src/superlocalmemory/storage/database.py +0 -3180
- package/src/superlocalmemory/storage/deferred_writes.py +0 -209
- package/src/superlocalmemory/storage/embedding_codec.py +0 -200
- package/src/superlocalmemory/storage/embedding_migrator.py +0 -672
- package/src/superlocalmemory/storage/erasure_fence.py +0 -45
- package/src/superlocalmemory/storage/execution_learning.py +0 -285
- package/src/superlocalmemory/storage/external_evidence.py +0 -359
- package/src/superlocalmemory/storage/generation_fence.py +0 -63
- package/src/superlocalmemory/storage/lineage_retention.py +0 -236
- package/src/superlocalmemory/storage/logical_edges.py +0 -86
- package/src/superlocalmemory/storage/memory_write.py +0 -115
- package/src/superlocalmemory/storage/migration_runner.py +0 -895
- package/src/superlocalmemory/storage/migration_v33.py +0 -140
- package/src/superlocalmemory/storage/migrations/M001_add_signal_features_columns.py +0 -67
- package/src/superlocalmemory/storage/migrations/M002_model_state_history.py +0 -107
- package/src/superlocalmemory/storage/migrations/M003_migration_log.py +0 -38
- package/src/superlocalmemory/storage/migrations/M004_cross_platform_sync_log.py +0 -46
- package/src/superlocalmemory/storage/migrations/M005_bandit_tables.py +0 -75
- package/src/superlocalmemory/storage/migrations/M006_action_outcomes_reward.py +0 -75
- package/src/superlocalmemory/storage/migrations/M007_pending_outcomes.py +0 -63
- package/src/superlocalmemory/storage/migrations/M009_model_lineage.py +0 -94
- package/src/superlocalmemory/storage/migrations/M010_evolution_config.py +0 -80
- package/src/superlocalmemory/storage/migrations/M011_archive_and_merge.py +0 -87
- package/src/superlocalmemory/storage/migrations/M012_shadow_observations.py +0 -72
- package/src/superlocalmemory/storage/migrations/M013_bi_temporal_columns.py +0 -55
- package/src/superlocalmemory/storage/migrations/M014_v345_scale_ready.py +0 -45
- package/src/superlocalmemory/storage/migrations/M015_add_pinned_column.py +0 -58
- package/src/superlocalmemory/storage/migrations/M016_add_scope_support.py +0 -120
- package/src/superlocalmemory/storage/migrations/M017_ccq_scope_column.py +0 -79
- package/src/superlocalmemory/storage/migrations/M018_ingestion_operations.py +0 -120
- package/src/superlocalmemory/storage/migrations/M019_derivation_lineage.py +0 -54
- package/src/superlocalmemory/storage/migrations/M020_model_state_integrity.py +0 -52
- package/src/superlocalmemory/storage/migrations/M021_ingestion_log_profile.py +0 -108
- package/src/superlocalmemory/storage/migrations/M022_entity_aliases_profile.py +0 -86
- package/src/superlocalmemory/storage/migrations/M023_mesh_profile_isolation.py +0 -194
- package/src/superlocalmemory/storage/migrations/M024_rbac_users_roles.py +0 -87
- package/src/superlocalmemory/storage/migrations/M025_perf_indexes.py +0 -90
- package/src/superlocalmemory/storage/migrations/M026_rbac_memberships_fk.py +0 -136
- package/src/superlocalmemory/storage/migrations/M027_transferable_patterns_profile.py +0 -163
- package/src/superlocalmemory/storage/migrations/M028_fact_entity_associations.py +0 -305
- package/src/superlocalmemory/storage/migrations/M029_behavioral_history_indexes.py +0 -137
- package/src/superlocalmemory/storage/migrations/M030_entity_explorer_indexes.py +0 -93
- package/src/superlocalmemory/storage/migrations/M031_dead_letter_operations.py +0 -80
- package/src/superlocalmemory/storage/migrations/M032_write_coordinator_admission.py +0 -188
- package/src/superlocalmemory/storage/migrations/M033_projection_transactions.py +0 -148
- package/src/superlocalmemory/storage/migrations/M034_obligation_integrity.py +0 -58
- package/src/superlocalmemory/storage/migrations/M035_erasure_receipts.py +0 -113
- package/src/superlocalmemory/storage/migrations/M036_vector_row_map.py +0 -107
- package/src/superlocalmemory/storage/migrations/M037_manifest_hmac_version.py +0 -162
- package/src/superlocalmemory/storage/migrations/M038_learning_feedback_channel.py +0 -77
- package/src/superlocalmemory/storage/migrations/M039_scene_fact_members.py +0 -137
- package/src/superlocalmemory/storage/migrations/M040_agent_experience_receipts.py +0 -254
- package/src/superlocalmemory/storage/migrations/M041_external_evidence_receipts.py +0 -189
- package/src/superlocalmemory/storage/migrations/M042_correction_case_ledger.py +0 -245
- package/src/superlocalmemory/storage/migrations/M043_quarantine_display_summaries.py +0 -512
- package/src/superlocalmemory/storage/migrations/M044_play_carries_its_own_evidence.py +0 -127
- package/src/superlocalmemory/storage/migrations/M045_fact_outcome_score.py +0 -158
- package/src/superlocalmemory/storage/migrations/M046_prospective_memory_has_its_own_name.py +0 -620
- package/src/superlocalmemory/storage/migrations/M047_fisher_vectors_are_stored_like_every_other_vector.py +0 -306
- package/src/superlocalmemory/storage/migrations/M048_upcoming_holds_only_what_is_upcoming.py +0 -229
- package/src/superlocalmemory/storage/migrations/M049_a_schema_version_marker_is_one_row.py +0 -201
- package/src/superlocalmemory/storage/migrations/M050_execution_learning_v2.py +0 -70
- package/src/superlocalmemory/storage/migrations/__init__.py +0 -103
- package/src/superlocalmemory/storage/migrations.py +0 -333
- package/src/superlocalmemory/storage/models.py +0 -500
- package/src/superlocalmemory/storage/projection_outbox.py +0 -346
- package/src/superlocalmemory/storage/quantized_store.py +0 -280
- package/src/superlocalmemory/storage/read_connection.py +0 -115
- package/src/superlocalmemory/storage/retention_policy.py +0 -860
- package/src/superlocalmemory/storage/schema.py +0 -1108
- package/src/superlocalmemory/storage/schema_code_graph.py +0 -282
- package/src/superlocalmemory/storage/schema_v32.py +0 -382
- package/src/superlocalmemory/storage/schema_v3410.py +0 -159
- package/src/superlocalmemory/storage/schema_v3411.py +0 -149
- package/src/superlocalmemory/storage/schema_v343.py +0 -315
- package/src/superlocalmemory/storage/schema_v345.py +0 -109
- package/src/superlocalmemory/storage/schema_v347.py +0 -140
- package/src/superlocalmemory/storage/sqlite_vectors.py +0 -169
- package/src/superlocalmemory/storage/v2_migrator.py +0 -466
- package/src/superlocalmemory/storage/write_coordinator.py +0 -949
- package/src/superlocalmemory/storage/write_lock.py +0 -88
- package/src/superlocalmemory/summaries/__init__.py +0 -37
- package/src/superlocalmemory/summaries/base.py +0 -267
- package/src/superlocalmemory/summaries/daily_reflection.py +0 -340
- package/src/superlocalmemory/summaries/non_answer.py +0 -223
- package/src/superlocalmemory/summaries/project_work_log.py +0 -440
- package/src/superlocalmemory/summaries/session_summary.py +0 -311
- package/src/superlocalmemory/trust/__init__.py +0 -0
- package/src/superlocalmemory/trust/gate.py +0 -171
- package/src/superlocalmemory/trust/provenance.py +0 -124
- package/src/superlocalmemory/trust/scorer.py +0 -413
- package/src/superlocalmemory/trust/signals.py +0 -153
- package/src/superlocalmemory/ui/assets/slm-icon-white.svg +0 -64
- package/src/superlocalmemory/ui/assets/slm-icon.svg +0 -36
- package/src/superlocalmemory/ui/css/brain.css +0 -409
- package/src/superlocalmemory/ui/css/design-system.css +0 -696
- package/src/superlocalmemory/ui/css/legacy-dashboard.css +0 -663
- package/src/superlocalmemory/ui/css/neural-glass.css +0 -1599
- package/src/superlocalmemory/ui/css/od-bridge.css +0 -158
- package/src/superlocalmemory/ui/favicon.svg +0 -36
- package/src/superlocalmemory/ui/index.html +0 -1638
- package/src/superlocalmemory/ui/js/agents.js +0 -192
- package/src/superlocalmemory/ui/js/auto-settings.js +0 -624
- package/src/superlocalmemory/ui/js/brain.js +0 -1400
- package/src/superlocalmemory/ui/js/clusters.js +0 -326
- package/src/superlocalmemory/ui/js/compliance.js +0 -307
- package/src/superlocalmemory/ui/js/core.js +0 -566
- package/src/superlocalmemory/ui/js/dashboard.js +0 -503
- package/src/superlocalmemory/ui/js/event-delegation.js +0 -113
- package/src/superlocalmemory/ui/js/events.js +0 -178
- package/src/superlocalmemory/ui/js/fact-detail.js +0 -142
- package/src/superlocalmemory/ui/js/feedback.js +0 -339
- package/src/superlocalmemory/ui/js/graph-event-bus.js +0 -83
- package/src/superlocalmemory/ui/js/graph-filters.js +0 -220
- package/src/superlocalmemory/ui/js/graph-ui.js +0 -214
- package/src/superlocalmemory/ui/js/ide-status.js +0 -115
- package/src/superlocalmemory/ui/js/init.js +0 -54
- package/src/superlocalmemory/ui/js/knowledge-graph.js +0 -945
- package/src/superlocalmemory/ui/js/lifecycle.js +0 -387
- package/src/superlocalmemory/ui/js/math-health.js +0 -114
- package/src/superlocalmemory/ui/js/memories.js +0 -394
- package/src/superlocalmemory/ui/js/memory-chat.js +0 -371
- package/src/superlocalmemory/ui/js/memory-timeline.js +0 -265
- package/src/superlocalmemory/ui/js/modal.js +0 -733
- package/src/superlocalmemory/ui/js/ng-entities.js +0 -298
- package/src/superlocalmemory/ui/js/ng-health.js +0 -208
- package/src/superlocalmemory/ui/js/ng-ingestion.js +0 -203
- package/src/superlocalmemory/ui/js/ng-mesh.js +0 -374
- package/src/superlocalmemory/ui/js/ng-shell.js +0 -524
- package/src/superlocalmemory/ui/js/ng-skills.js +0 -663
- package/src/superlocalmemory/ui/js/od-agents.js +0 -588
- package/src/superlocalmemory/ui/js/od-auth-gate.js +0 -257
- package/src/superlocalmemory/ui/js/od-backup.js +0 -878
- package/src/superlocalmemory/ui/js/od-boundedloops.js +0 -324
- package/src/superlocalmemory/ui/js/od-brain.js +0 -1095
- package/src/superlocalmemory/ui/js/od-compliance-ext.js +0 -301
- package/src/superlocalmemory/ui/js/od-components.js +0 -147
- package/src/superlocalmemory/ui/js/od-entities.js +0 -622
- package/src/superlocalmemory/ui/js/od-graph.js +0 -776
- package/src/superlocalmemory/ui/js/od-health.js +0 -579
- package/src/superlocalmemory/ui/js/od-mcp.js +0 -508
- package/src/superlocalmemory/ui/js/od-memories.js +0 -1499
- package/src/superlocalmemory/ui/js/od-mesh.js +0 -645
- package/src/superlocalmemory/ui/js/od-operations.js +0 -1268
- package/src/superlocalmemory/ui/js/od-ops-health.js +0 -417
- package/src/superlocalmemory/ui/js/od-optimize.js +0 -828
- package/src/superlocalmemory/ui/js/od-settings.js +0 -1275
- package/src/superlocalmemory/ui/js/od-shell.js +0 -819
- package/src/superlocalmemory/ui/js/od-skills.js +0 -600
- package/src/superlocalmemory/ui/js/od-team.js +0 -265
- package/src/superlocalmemory/ui/js/optimize.js +0 -191
- package/src/superlocalmemory/ui/js/profiles.js +0 -362
- package/src/superlocalmemory/ui/js/quick-actions.js +0 -334
- package/src/superlocalmemory/ui/js/recall-lab.js +0 -373
- package/src/superlocalmemory/ui/js/search.js +0 -86
- package/src/superlocalmemory/ui/js/settings.js +0 -556
- package/src/superlocalmemory/ui/js/timeline.js +0 -62
- package/src/superlocalmemory/ui/js/trust-dashboard.js +0 -225
- package/src/superlocalmemory/ui/vendor/bootstrap-icons/bootstrap-icons.css +0 -2018
- package/src/superlocalmemory/ui/vendor/bootstrap-icons/fonts/bootstrap-icons.woff +0 -0
- package/src/superlocalmemory/ui/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 +0 -0
- package/src/superlocalmemory/ui/vendor/bootstrap.bundle.min.js +0 -7
- package/src/superlocalmemory/ui/vendor/bootstrap.min.css +0 -6
- package/src/superlocalmemory/ui/vendor/d3.v7.min.js +0 -2
- package/src/superlocalmemory/ui/vendor/graphology-library.min.js +0 -2
- package/src/superlocalmemory/ui/vendor/graphology.umd.min.js +0 -2
- package/src/superlocalmemory/ui/vendor/inter-ui/inter-variable.min.css +0 -8
- package/src/superlocalmemory/ui/vendor/inter-ui/variable/InterVariable-Italic.woff2 +0 -0
- package/src/superlocalmemory/ui/vendor/inter-ui/variable/InterVariable.woff2 +0 -0
- package/src/superlocalmemory/ui/vendor/sigma.min.js +0 -1
- package/src/superlocalmemory/vector/__init__.py +0 -9
- package/src/superlocalmemory/vector/lancedb_backend.py +0 -366
|
@@ -1,863 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
|
|
2
|
-
# Licensed under AGPL-3.0-or-later - see LICENSE file
|
|
3
|
-
# Part of SuperLocalMemory V3
|
|
4
|
-
|
|
5
|
-
"""VectorStore -- sqlite-vec backed KNN search with profile isolation.
|
|
6
|
-
|
|
7
|
-
Replaces full-table-scan in SemanticChannel with native vec0 KNN.
|
|
8
|
-
Falls back to ANNIndex if sqlite-vec is unavailable (Rule 03).
|
|
9
|
-
Implements ANNSearchable protocol for GraphBuilder compatibility (Rule 07).
|
|
10
|
-
|
|
11
|
-
Part of Qualixar | Author: Varun Pratap Bhardwaj
|
|
12
|
-
License: AGPL-3.0-or-later
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
from __future__ import annotations
|
|
16
|
-
|
|
17
|
-
import logging
|
|
18
|
-
import re
|
|
19
|
-
import sqlite3
|
|
20
|
-
import threading
|
|
21
|
-
from contextlib import contextmanager
|
|
22
|
-
from dataclasses import dataclass
|
|
23
|
-
from pathlib import Path
|
|
24
|
-
from typing import Generator
|
|
25
|
-
|
|
26
|
-
import numpy as np
|
|
27
|
-
|
|
28
|
-
from superlocalmemory.storage.embedding_codec import encode_embedding
|
|
29
|
-
from superlocalmemory.storage.write_lock import get_write_lock
|
|
30
|
-
|
|
31
|
-
logger = logging.getLogger(__name__)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
@dataclass(frozen=True) # Rule 10
|
|
35
|
-
class VectorStoreConfig:
|
|
36
|
-
"""Configuration for VectorStore."""
|
|
37
|
-
|
|
38
|
-
dimension: int = 768
|
|
39
|
-
binary_quantization_threshold: int = 100_000 # L4 fix
|
|
40
|
-
model_name: str = "nomic-embed-text-v1.5"
|
|
41
|
-
enabled: bool = True # Ships enabled by default
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
class VectorStore:
|
|
45
|
-
"""sqlite-vec backed vector store with profile-scoped KNN search.
|
|
46
|
-
|
|
47
|
-
- Loads sqlite-vec extension on init (try/except, Rule 03)
|
|
48
|
-
- Creates vec0 virtual table with profile_id PARTITION KEY
|
|
49
|
-
- Maps string fact_ids to integer rowids via embedding_metadata
|
|
50
|
-
- Implements ANNSearchable protocol (Rule 07)
|
|
51
|
-
- Thread-safe via lock on mutations
|
|
52
|
-
|
|
53
|
-
If sqlite-vec is unavailable, self.available is False and all
|
|
54
|
-
methods are no-ops (caller uses ANNIndex fallback).
|
|
55
|
-
"""
|
|
56
|
-
|
|
57
|
-
def __init__(self, db_path: Path, config: VectorStoreConfig) -> None:
|
|
58
|
-
self._db_path = Path(db_path)
|
|
59
|
-
self._config = config
|
|
60
|
-
self._lock = threading.Lock()
|
|
61
|
-
self._available = False
|
|
62
|
-
|
|
63
|
-
if not config.enabled:
|
|
64
|
-
logger.debug("VectorStore disabled by config (enabled=False)")
|
|
65
|
-
return
|
|
66
|
-
|
|
67
|
-
self._available = self._try_load_extension()
|
|
68
|
-
if self._available:
|
|
69
|
-
self._ensure_vec0_table()
|
|
70
|
-
|
|
71
|
-
@property
|
|
72
|
-
def available(self) -> bool:
|
|
73
|
-
"""True if sqlite-vec is loaded and vec0 table exists."""
|
|
74
|
-
return self._available
|
|
75
|
-
|
|
76
|
-
# -- Extension loading (Rule 03) ----------------------------------------
|
|
77
|
-
|
|
78
|
-
def _try_load_extension(self) -> bool:
|
|
79
|
-
"""Attempt to load sqlite-vec. Returns True on success.
|
|
80
|
-
|
|
81
|
-
Catches ImportError, AttributeError, and any other exception.
|
|
82
|
-
"""
|
|
83
|
-
try:
|
|
84
|
-
import sqlite_vec # noqa: F401
|
|
85
|
-
|
|
86
|
-
conn = self._connect()
|
|
87
|
-
conn.close()
|
|
88
|
-
return True
|
|
89
|
-
except ImportError:
|
|
90
|
-
logger.debug("sqlite-vec not installed. VectorStore unavailable.")
|
|
91
|
-
return False
|
|
92
|
-
except AttributeError:
|
|
93
|
-
logger.debug(
|
|
94
|
-
"enable_load_extension not available (macOS default Python). "
|
|
95
|
-
"VectorStore unavailable."
|
|
96
|
-
)
|
|
97
|
-
return False
|
|
98
|
-
except Exception as exc:
|
|
99
|
-
logger.debug("sqlite-vec load failed: %s", exc)
|
|
100
|
-
return False
|
|
101
|
-
|
|
102
|
-
def _connect(self) -> sqlite3.Connection:
|
|
103
|
-
"""Open a connection with sqlite-vec loaded.
|
|
104
|
-
|
|
105
|
-
Every connection loads the extension fresh (per-call model).
|
|
106
|
-
"""
|
|
107
|
-
import sqlite_vec
|
|
108
|
-
|
|
109
|
-
conn = sqlite3.connect(str(self._db_path))
|
|
110
|
-
conn.row_factory = sqlite3.Row
|
|
111
|
-
conn.execute("PRAGMA busy_timeout = 10000")
|
|
112
|
-
# FK enforcement is OFF here because VectorStore operates on its own
|
|
113
|
-
# tables (fact_embeddings + embedding_metadata). The store pipeline
|
|
114
|
-
# guarantees fact/profile exist before calling upsert.
|
|
115
|
-
conn.enable_load_extension(True)
|
|
116
|
-
sqlite_vec.load(conn)
|
|
117
|
-
conn.enable_load_extension(False)
|
|
118
|
-
return conn
|
|
119
|
-
|
|
120
|
-
@contextmanager
|
|
121
|
-
def _managed_connection(self) -> Generator[sqlite3.Connection, None, None]:
|
|
122
|
-
"""Close every sqlite-vec connection, rolling back abandoned writes.
|
|
123
|
-
|
|
124
|
-
sqlite-vec can reject a commit after its virtual-table shadow rows have
|
|
125
|
-
already opened a SQLite write transaction. A fail-soft caller must not
|
|
126
|
-
return while that connection still owns the WAL writer lock: the next
|
|
127
|
-
canonical/BM25 write would then wait behind an unreachable transaction.
|
|
128
|
-
"""
|
|
129
|
-
conn = self._connect()
|
|
130
|
-
try:
|
|
131
|
-
yield conn
|
|
132
|
-
finally:
|
|
133
|
-
if conn.in_transaction:
|
|
134
|
-
try:
|
|
135
|
-
conn.rollback()
|
|
136
|
-
except sqlite3.Error:
|
|
137
|
-
pass
|
|
138
|
-
conn.close()
|
|
139
|
-
|
|
140
|
-
# -- Table creation -----------------------------------------------------
|
|
141
|
-
|
|
142
|
-
@staticmethod
|
|
143
|
-
def _read_stored_dimension(conn: sqlite3.Connection) -> int | None:
|
|
144
|
-
"""Return the embedding dimension of the existing vec0 table, or None.
|
|
145
|
-
|
|
146
|
-
Reads the CREATE VIRTUAL TABLE DDL from sqlite_master and extracts the
|
|
147
|
-
float[N] declaration. Falls back to embedding_metadata.dimension if
|
|
148
|
-
the DDL is absent or unparseable. Returns None when the table does not
|
|
149
|
-
yet exist, which means no rebuild is needed.
|
|
150
|
-
"""
|
|
151
|
-
try:
|
|
152
|
-
row = conn.execute(
|
|
153
|
-
"SELECT sql FROM sqlite_master WHERE name = 'fact_embeddings'"
|
|
154
|
-
).fetchone()
|
|
155
|
-
if row is not None:
|
|
156
|
-
sql = row["sql"] or row[0]
|
|
157
|
-
if sql:
|
|
158
|
-
m = re.search(r'float\[(\d+)\]', sql, re.IGNORECASE)
|
|
159
|
-
if m:
|
|
160
|
-
return int(m.group(1))
|
|
161
|
-
except Exception:
|
|
162
|
-
pass
|
|
163
|
-
|
|
164
|
-
# Fallback: read dimension from the most recent metadata row.
|
|
165
|
-
try:
|
|
166
|
-
row = conn.execute(
|
|
167
|
-
"SELECT dimension FROM embedding_metadata LIMIT 1"
|
|
168
|
-
).fetchone()
|
|
169
|
-
if row is not None:
|
|
170
|
-
return int(row["dimension"])
|
|
171
|
-
except sqlite3.OperationalError:
|
|
172
|
-
pass # metadata table does not exist yet
|
|
173
|
-
|
|
174
|
-
return None
|
|
175
|
-
|
|
176
|
-
def _ensure_vec0_table(self) -> None:
|
|
177
|
-
"""Create or rebuild the vec0 virtual table and embedding_metadata.
|
|
178
|
-
|
|
179
|
-
If the existing vec0 table was built at a different embedding dimension
|
|
180
|
-
than self._config.dimension, both tables are dropped and recreated at
|
|
181
|
-
the new dimension. Old embeddings are lost; callers that want to
|
|
182
|
-
re-populate should call rebuild_from_facts() afterward.
|
|
183
|
-
|
|
184
|
-
Same-dimension opens are a no-op (IF NOT EXISTS guard).
|
|
185
|
-
"""
|
|
186
|
-
dim = self._config.dimension
|
|
187
|
-
vec0_ddl = (
|
|
188
|
-
f"CREATE VIRTUAL TABLE IF NOT EXISTS fact_embeddings USING vec0("
|
|
189
|
-
f"profile_id TEXT PARTITION KEY, "
|
|
190
|
-
f"embedding float[{dim}] distance_metric=cosine"
|
|
191
|
-
f")"
|
|
192
|
-
)
|
|
193
|
-
meta_ddl = (
|
|
194
|
-
"CREATE TABLE IF NOT EXISTS embedding_metadata ("
|
|
195
|
-
"vec_rowid INTEGER PRIMARY KEY, "
|
|
196
|
-
"fact_id TEXT NOT NULL UNIQUE, "
|
|
197
|
-
"profile_id TEXT NOT NULL DEFAULT 'default', "
|
|
198
|
-
"model_name TEXT NOT NULL DEFAULT '', "
|
|
199
|
-
"dimension INTEGER NOT NULL DEFAULT 768, "
|
|
200
|
-
"created_at TEXT NOT NULL DEFAULT (datetime('now'))"
|
|
201
|
-
")"
|
|
202
|
-
)
|
|
203
|
-
meta_idx_fact = (
|
|
204
|
-
"CREATE INDEX IF NOT EXISTS idx_embmeta_fact ON embedding_metadata (fact_id)"
|
|
205
|
-
)
|
|
206
|
-
meta_idx_profile = (
|
|
207
|
-
"CREATE INDEX IF NOT EXISTS idx_embmeta_profile ON embedding_metadata (profile_id)"
|
|
208
|
-
)
|
|
209
|
-
row_map_ddl = (
|
|
210
|
-
"CREATE TABLE IF NOT EXISTS vector_row_map ("
|
|
211
|
-
"fact_id TEXT NOT NULL PRIMARY KEY, "
|
|
212
|
-
"profile_id TEXT NOT NULL, "
|
|
213
|
-
"vec_rowid INTEGER NOT NULL"
|
|
214
|
-
")"
|
|
215
|
-
)
|
|
216
|
-
row_map_idx = (
|
|
217
|
-
"CREATE INDEX IF NOT EXISTS idx_vector_row_map_profile "
|
|
218
|
-
"ON vector_row_map (profile_id)"
|
|
219
|
-
)
|
|
220
|
-
try:
|
|
221
|
-
with self._managed_connection() as conn:
|
|
222
|
-
stored_dim = self._read_stored_dimension(conn)
|
|
223
|
-
if stored_dim is not None and stored_dim != dim:
|
|
224
|
-
logger.info(
|
|
225
|
-
"Embedding dimension changed %d→%d: rebuilding vector index",
|
|
226
|
-
stored_dim,
|
|
227
|
-
dim,
|
|
228
|
-
)
|
|
229
|
-
# Drop metadata first (no FK enforcement, but cleaner ordering).
|
|
230
|
-
# Indexes on embedding_metadata are dropped automatically.
|
|
231
|
-
conn.execute("DROP TABLE IF EXISTS embedding_metadata")
|
|
232
|
-
conn.execute("DROP TABLE IF EXISTS vector_row_map")
|
|
233
|
-
conn.execute("DROP TABLE IF EXISTS fact_embeddings")
|
|
234
|
-
# Commit the drops before recreating so that the virtual-table
|
|
235
|
-
# shadow tables are fully removed before the new CREATE runs.
|
|
236
|
-
conn.commit()
|
|
237
|
-
|
|
238
|
-
conn.execute(vec0_ddl)
|
|
239
|
-
conn.execute(meta_ddl)
|
|
240
|
-
conn.execute(meta_idx_fact)
|
|
241
|
-
conn.execute(meta_idx_profile)
|
|
242
|
-
conn.execute(row_map_ddl)
|
|
243
|
-
conn.execute(row_map_idx)
|
|
244
|
-
conn.commit()
|
|
245
|
-
except Exception as exc:
|
|
246
|
-
logger.debug("vec0 table creation failed: %s", exc)
|
|
247
|
-
self._available = False
|
|
248
|
-
|
|
249
|
-
# -- Serialization ------------------------------------------------------
|
|
250
|
-
|
|
251
|
-
@staticmethod
|
|
252
|
-
def _serialize_f32(vector: list[float]) -> bytes:
|
|
253
|
-
"""Serialize float list to raw bytes for sqlite-vec.
|
|
254
|
-
|
|
255
|
-
Delegates to the shared embedding codec so that a format change in
|
|
256
|
-
that codec propagates here automatically.
|
|
257
|
-
"""
|
|
258
|
-
result = encode_embedding(vector)
|
|
259
|
-
if result is None:
|
|
260
|
-
# encode_embedding returns None only for None input; _serialize_f32
|
|
261
|
-
# is never called with None, so this branch is unreachable in
|
|
262
|
-
# production. Return empty bytes rather than raising so the caller
|
|
263
|
-
# sees an empty query result rather than an unhandled exception.
|
|
264
|
-
return b""
|
|
265
|
-
return result
|
|
266
|
-
|
|
267
|
-
# -- CRUD Operations ----------------------------------------------------
|
|
268
|
-
|
|
269
|
-
def upsert(
|
|
270
|
-
self,
|
|
271
|
-
fact_id: str,
|
|
272
|
-
profile_id: str,
|
|
273
|
-
embedding: list[float],
|
|
274
|
-
model_name: str = "",
|
|
275
|
-
) -> bool:
|
|
276
|
-
"""Insert or update a vector in the vec0 table.
|
|
277
|
-
|
|
278
|
-
Thread-safe: acquires self._lock.
|
|
279
|
-
Returns True on success, False on failure or if unavailable.
|
|
280
|
-
"""
|
|
281
|
-
if not self._available:
|
|
282
|
-
return False
|
|
283
|
-
|
|
284
|
-
if len(embedding) != self._config.dimension:
|
|
285
|
-
logger.debug(
|
|
286
|
-
"Dimension mismatch: got %d, expected %d",
|
|
287
|
-
len(embedding),
|
|
288
|
-
self._config.dimension,
|
|
289
|
-
)
|
|
290
|
-
return False
|
|
291
|
-
|
|
292
|
-
# Embedding bytes computed OUTSIDE the lock — serialisation must not
|
|
293
|
-
# cover slow computation, only the sqlite3 write transaction itself.
|
|
294
|
-
vec_bytes = self._serialize_f32(embedding)
|
|
295
|
-
|
|
296
|
-
# Acquire the process-level write lock for this db file BEFORE opening
|
|
297
|
-
# the sqlite3 connection. This is the OUTERMOST lock (see write_lock.py
|
|
298
|
-
# ordering rule). self._lock is INNER and acquired inside. The write
|
|
299
|
-
# lock is the same RLock that DatabaseManager._lock references for this
|
|
300
|
-
# db_path, so the self-heal backfill pattern
|
|
301
|
-
# with db._lock: vs.upsert()
|
|
302
|
-
# simply re-enters the RLock (same thread — always safe).
|
|
303
|
-
_wl = get_write_lock(self._db_path)
|
|
304
|
-
with _wl: # OUTER: serialises all memory.db writers
|
|
305
|
-
with self._lock: # INNER: VectorStore per-instance state
|
|
306
|
-
try:
|
|
307
|
-
with self._managed_connection() as conn:
|
|
308
|
-
# Reserve SQLite's cross-process writer before reading
|
|
309
|
-
# either side of the row-id allocator. The Python
|
|
310
|
-
# RLocks above coordinate threads only; BEGIN IMMEDIATE
|
|
311
|
-
# plus the connection's bounded busy_timeout serializes
|
|
312
|
-
# independent MCP/agent processes as well.
|
|
313
|
-
conn.execute("BEGIN IMMEDIATE")
|
|
314
|
-
# Check if fact_id already exists in metadata
|
|
315
|
-
row = conn.execute(
|
|
316
|
-
"SELECT vec_rowid, profile_id "
|
|
317
|
-
"FROM embedding_metadata "
|
|
318
|
-
"WHERE fact_id = ?",
|
|
319
|
-
(fact_id,),
|
|
320
|
-
).fetchone()
|
|
321
|
-
|
|
322
|
-
if row is not None:
|
|
323
|
-
rowid = row["vec_rowid"]
|
|
324
|
-
vector_row = conn.execute(
|
|
325
|
-
"SELECT profile_id FROM fact_embeddings WHERE rowid = ?",
|
|
326
|
-
(rowid,),
|
|
327
|
-
).fetchone()
|
|
328
|
-
pair_matches_profile = (
|
|
329
|
-
vector_row is not None
|
|
330
|
-
and str(row["profile_id"]) == profile_id
|
|
331
|
-
and str(vector_row["profile_id"]) == profile_id
|
|
332
|
-
)
|
|
333
|
-
if pair_matches_profile:
|
|
334
|
-
conn.execute(
|
|
335
|
-
"UPDATE fact_embeddings SET embedding = ? WHERE rowid = ?",
|
|
336
|
-
(vec_bytes, rowid),
|
|
337
|
-
)
|
|
338
|
-
else:
|
|
339
|
-
# Older self-heal code could insert metadata
|
|
340
|
-
# before sqlite-vec, or row-id drift could point
|
|
341
|
-
# metadata at another profile's vector. Neither
|
|
342
|
-
# is a valid projection pair. Remove the stale
|
|
343
|
-
# pointer and rebuild at a fresh rowid; never
|
|
344
|
-
# overwrite the other profile's payload.
|
|
345
|
-
conn.execute(
|
|
346
|
-
"DELETE FROM embedding_metadata WHERE fact_id = ?",
|
|
347
|
-
(fact_id,),
|
|
348
|
-
)
|
|
349
|
-
# The old vec0 row is orphaned unless another
|
|
350
|
-
# projection pair still references it. Reclaim it
|
|
351
|
-
# so drift-repair never abandons raw payload.
|
|
352
|
-
still_referenced = conn.execute(
|
|
353
|
-
"SELECT 1 FROM embedding_metadata "
|
|
354
|
-
"WHERE vec_rowid = ? LIMIT 1",
|
|
355
|
-
(rowid,),
|
|
356
|
-
).fetchone()
|
|
357
|
-
if still_referenced is None:
|
|
358
|
-
conn.execute(
|
|
359
|
-
"DELETE FROM fact_embeddings WHERE rowid = ?",
|
|
360
|
-
(rowid,),
|
|
361
|
-
)
|
|
362
|
-
conn.execute(
|
|
363
|
-
"DELETE FROM vector_row_map WHERE fact_id = ?",
|
|
364
|
-
(fact_id,),
|
|
365
|
-
)
|
|
366
|
-
row = None
|
|
367
|
-
|
|
368
|
-
if row is None:
|
|
369
|
-
# Allocate from both sides of the projection pair.
|
|
370
|
-
# Mature databases can contain orphaned vec0 rows
|
|
371
|
-
# or metadata rows after older fail-soft releases.
|
|
372
|
-
# sqlite-vec's implicit last_insert_rowid() only
|
|
373
|
-
# considers the virtual table, so it can reuse a
|
|
374
|
-
# rowid that is still owned by embedding_metadata
|
|
375
|
-
# and make every later projection fail UNIQUE.
|
|
376
|
-
rowid = conn.execute(
|
|
377
|
-
"SELECT COALESCE(MAX(candidate), 0) + 1 "
|
|
378
|
-
"FROM ("
|
|
379
|
-
"SELECT MAX(rowid) AS candidate "
|
|
380
|
-
"FROM fact_embeddings "
|
|
381
|
-
"UNION ALL "
|
|
382
|
-
"SELECT MAX(vec_rowid) AS candidate "
|
|
383
|
-
"FROM embedding_metadata"
|
|
384
|
-
")"
|
|
385
|
-
).fetchone()[0]
|
|
386
|
-
conn.execute(
|
|
387
|
-
"INSERT INTO fact_embeddings"
|
|
388
|
-
"(rowid, profile_id, embedding) "
|
|
389
|
-
"VALUES (?, ?, ?)",
|
|
390
|
-
(rowid, profile_id, vec_bytes),
|
|
391
|
-
)
|
|
392
|
-
conn.execute(
|
|
393
|
-
"INSERT INTO embedding_metadata "
|
|
394
|
-
"(vec_rowid, fact_id, profile_id, model_name, dimension) "
|
|
395
|
-
"VALUES (?, ?, ?, ?, ?)",
|
|
396
|
-
(
|
|
397
|
-
rowid,
|
|
398
|
-
fact_id,
|
|
399
|
-
profile_id,
|
|
400
|
-
model_name or self._config.model_name,
|
|
401
|
-
self._config.dimension,
|
|
402
|
-
),
|
|
403
|
-
)
|
|
404
|
-
|
|
405
|
-
conn.execute(
|
|
406
|
-
"INSERT INTO vector_row_map (fact_id, profile_id, vec_rowid) "
|
|
407
|
-
"VALUES (?, ?, ?) "
|
|
408
|
-
"ON CONFLICT(fact_id) DO UPDATE SET "
|
|
409
|
-
"profile_id = excluded.profile_id, "
|
|
410
|
-
"vec_rowid = excluded.vec_rowid",
|
|
411
|
-
(fact_id, profile_id, rowid),
|
|
412
|
-
)
|
|
413
|
-
conn.commit()
|
|
414
|
-
return True
|
|
415
|
-
except Exception as exc:
|
|
416
|
-
logger.debug("upsert failed for fact_id=%s: %s", fact_id, exc)
|
|
417
|
-
return False
|
|
418
|
-
|
|
419
|
-
def _has_quarantine_column(self) -> bool:
|
|
420
|
-
"""Whether atomic_facts carries ``quarantined`` in this database.
|
|
421
|
-
|
|
422
|
-
Cached once True; re-probed while absent so a schema pass that lands
|
|
423
|
-
later is picked up. Mirrors DatabaseManager._has_quarantine_column --
|
|
424
|
-
an unmigrated store must degrade to the old query rather than raise on
|
|
425
|
-
every semantic search.
|
|
426
|
-
"""
|
|
427
|
-
cached = getattr(self, "_quarantine_col", None)
|
|
428
|
-
if cached is True:
|
|
429
|
-
return True
|
|
430
|
-
try:
|
|
431
|
-
with self._managed_connection() as conn:
|
|
432
|
-
present = any(
|
|
433
|
-
row[1] == "quarantined"
|
|
434
|
-
for row in conn.execute("PRAGMA table_info(atomic_facts)")
|
|
435
|
-
)
|
|
436
|
-
except Exception: # noqa: BLE001 -- a probe must never break search
|
|
437
|
-
return False
|
|
438
|
-
if present:
|
|
439
|
-
self._quarantine_col = True
|
|
440
|
-
return present
|
|
441
|
-
|
|
442
|
-
def search(
|
|
443
|
-
self,
|
|
444
|
-
query_embedding: list[float],
|
|
445
|
-
top_k: int = 30,
|
|
446
|
-
profile_id: str | None = None,
|
|
447
|
-
) -> list[tuple[str, float]]:
|
|
448
|
-
"""KNN search. Returns [(fact_id, similarity_score)].
|
|
449
|
-
|
|
450
|
-
Score is cosine similarity (1.0 - distance).
|
|
451
|
-
Returns empty list if unavailable, dim mismatch, or error.
|
|
452
|
-
"""
|
|
453
|
-
if not self._available:
|
|
454
|
-
return []
|
|
455
|
-
|
|
456
|
-
if len(query_embedding) != self._config.dimension:
|
|
457
|
-
return []
|
|
458
|
-
|
|
459
|
-
vec_bytes = self._serialize_f32(query_embedding)
|
|
460
|
-
|
|
461
|
-
try:
|
|
462
|
-
with self._managed_connection() as conn:
|
|
463
|
-
if top_k <= 0:
|
|
464
|
-
return []
|
|
465
|
-
# A withheld fact must not occupy a nearest-neighbour slot.
|
|
466
|
-
#
|
|
467
|
-
# Its vector stays in the index — quarantine is reversible and
|
|
468
|
-
# deleting the projection would cost a re-embed to undo — so it
|
|
469
|
-
# is filtered here instead.
|
|
470
|
-
#
|
|
471
|
-
# Measured on the author's store: 1,192 of 5,086 projections
|
|
472
|
-
# (23.4%) belong to withheld rows, and because model-written
|
|
473
|
-
# summaries of the same clusters land close together in
|
|
474
|
-
# embedding space they crowd each other. Searching with a vector
|
|
475
|
-
# taken from one of them returned 50 of 50 neighbours withheld
|
|
476
|
-
# without this join, and 0 of 50 with it. So for any query near
|
|
477
|
-
# that cluster the semantic channel was contributing nothing at
|
|
478
|
-
# all — every slot spent on a candidate that hydration would
|
|
479
|
-
# discard — while looking like it had answered.
|
|
480
|
-
#
|
|
481
|
-
# The expansion loop below already exists for exactly this
|
|
482
|
-
# shape of problem (orphaned vec0 rows losing a slot to the
|
|
483
|
-
# relational join) and compensates automatically: it doubles k
|
|
484
|
-
# until top_k surviving pairs are found. Nothing new is needed
|
|
485
|
-
# to make the slots back.
|
|
486
|
-
# LEFT, not INNER. An inner join would make a projection
|
|
487
|
-
# depend on its corpus row still existing, so a legacy orphan
|
|
488
|
-
# metadata row would stop being returned at all -- a behaviour
|
|
489
|
-
# change well beyond quarantine, and one the existing
|
|
490
|
-
# vector-store tests caught immediately by building a store
|
|
491
|
-
# with no matching facts. LEFT leaves af.quarantined NULL for a
|
|
492
|
-
# missing row, and COALESCE keeps it.
|
|
493
|
-
quarantine_join = (
|
|
494
|
-
" LEFT JOIN atomic_facts AS af ON af.fact_id = em.fact_id "
|
|
495
|
-
if self._has_quarantine_column() else ""
|
|
496
|
-
)
|
|
497
|
-
quarantine_filter = (
|
|
498
|
-
" AND COALESCE(af.quarantined, 0) = 0 "
|
|
499
|
-
if self._has_quarantine_column() else ""
|
|
500
|
-
)
|
|
501
|
-
if profile_id is not None:
|
|
502
|
-
sql = (
|
|
503
|
-
"SELECT fe.rowid, fe.distance, em.fact_id "
|
|
504
|
-
"FROM fact_embeddings AS fe "
|
|
505
|
-
"JOIN embedding_metadata AS em "
|
|
506
|
-
"ON em.vec_rowid = fe.rowid "
|
|
507
|
-
"AND em.profile_id = fe.profile_id "
|
|
508
|
-
+ quarantine_join +
|
|
509
|
-
"WHERE fe.embedding MATCH ? "
|
|
510
|
-
"AND fe.profile_id = ? "
|
|
511
|
-
+ quarantine_filter +
|
|
512
|
-
"AND fe.k = ?"
|
|
513
|
-
)
|
|
514
|
-
base_params: tuple[object, ...] = (vec_bytes, profile_id)
|
|
515
|
-
count_sql = "SELECT COUNT(*) AS c FROM fact_embeddings WHERE profile_id = ?"
|
|
516
|
-
count_params: tuple[object, ...] = (profile_id,)
|
|
517
|
-
else:
|
|
518
|
-
sql = (
|
|
519
|
-
"SELECT fe.rowid, fe.distance, em.fact_id "
|
|
520
|
-
"FROM fact_embeddings AS fe "
|
|
521
|
-
"JOIN embedding_metadata AS em "
|
|
522
|
-
"ON em.vec_rowid = fe.rowid "
|
|
523
|
-
"AND em.profile_id = fe.profile_id "
|
|
524
|
-
+ quarantine_join +
|
|
525
|
-
"WHERE fe.embedding MATCH ? "
|
|
526
|
-
+ quarantine_filter +
|
|
527
|
-
"AND fe.k = ?"
|
|
528
|
-
)
|
|
529
|
-
base_params = (vec_bytes,)
|
|
530
|
-
count_sql = "SELECT COUNT(*) AS c FROM fact_embeddings"
|
|
531
|
-
count_params = ()
|
|
532
|
-
|
|
533
|
-
# vec0 applies k before the relational join. A legacy orphan
|
|
534
|
-
# can therefore occupy a nearest-neighbour slot and then be
|
|
535
|
-
# discarded by the profile-safe join. Expand only when that
|
|
536
|
-
# happens, doubling until top_k valid pairs are found or the
|
|
537
|
-
# profile's vector population is exhausted.
|
|
538
|
-
search_k = top_k
|
|
539
|
-
rows = conn.execute(
|
|
540
|
-
sql,
|
|
541
|
-
(*base_params, search_k),
|
|
542
|
-
).fetchall()
|
|
543
|
-
if len(rows) < top_k:
|
|
544
|
-
count_row = conn.execute(
|
|
545
|
-
count_sql,
|
|
546
|
-
count_params,
|
|
547
|
-
).fetchone()
|
|
548
|
-
total_vectors = int(count_row["c"]) if count_row else 0
|
|
549
|
-
while len(rows) < top_k and search_k < total_vectors:
|
|
550
|
-
search_k = min(total_vectors, max(search_k + 1, search_k * 2))
|
|
551
|
-
rows = conn.execute(
|
|
552
|
-
sql,
|
|
553
|
-
(*base_params, search_k),
|
|
554
|
-
).fetchall()
|
|
555
|
-
|
|
556
|
-
# Rank the whole candidate list, THEN cut it. The expansion above
|
|
557
|
-
# can leave `rows` longer than top_k, and the SQL has no ORDER BY —
|
|
558
|
-
# vec0 applies k, then a relational join emits the survivors in an
|
|
559
|
-
# order SQLite is free to choose. Cutting first therefore cut by
|
|
560
|
-
# position and only ranked what survived, which can drop a nearer
|
|
561
|
-
# fact in favour of a farther one.
|
|
562
|
-
#
|
|
563
|
-
# Measured on the 0.95 GB archive: 29 of 60 queries do take the
|
|
564
|
-
# expansion path (orphan vectors are common), and the produced set
|
|
565
|
-
# matched the true nearest-k in all 29 — the join does emit in
|
|
566
|
-
# distance order in practice. So this was latent, not active. It is
|
|
567
|
-
# fixed because "the planner happens to" is not a guarantee: add an
|
|
568
|
-
# index, change SQLite, or change the join and the answer moves.
|
|
569
|
-
#
|
|
570
|
-
# The tie-break on fact_id makes the cut total, so two facts at
|
|
571
|
-
# equal distance cannot swap across the top_k boundary between runs.
|
|
572
|
-
results: list[tuple[str, float]] = [
|
|
573
|
-
(str(row["fact_id"]), max(0.0, 1.0 - row["distance"]))
|
|
574
|
-
for row in rows
|
|
575
|
-
]
|
|
576
|
-
results.sort(key=lambda x: (-x[1], x[0]))
|
|
577
|
-
return results[:top_k]
|
|
578
|
-
|
|
579
|
-
except Exception as exc:
|
|
580
|
-
logger.debug("search failed: %s", exc)
|
|
581
|
-
return []
|
|
582
|
-
|
|
583
|
-
def delete(self, fact_id: str) -> bool:
|
|
584
|
-
"""Remove a vector from vec0 and metadata.
|
|
585
|
-
|
|
586
|
-
Thread-safe: acquires the process-level write lock then self._lock.
|
|
587
|
-
Returns True if deleted, False if not found or error.
|
|
588
|
-
"""
|
|
589
|
-
if not self._available:
|
|
590
|
-
return False
|
|
591
|
-
|
|
592
|
-
_wl = get_write_lock(self._db_path)
|
|
593
|
-
with _wl: # OUTER: process-level write serialisation
|
|
594
|
-
with self._lock: # INNER: VectorStore per-instance state
|
|
595
|
-
try:
|
|
596
|
-
with self._managed_connection() as conn:
|
|
597
|
-
row = conn.execute(
|
|
598
|
-
"SELECT vec_rowid, profile_id "
|
|
599
|
-
"FROM embedding_metadata "
|
|
600
|
-
"WHERE fact_id = ?",
|
|
601
|
-
(fact_id,),
|
|
602
|
-
).fetchone()
|
|
603
|
-
|
|
604
|
-
rowid = None
|
|
605
|
-
owner_profile = None
|
|
606
|
-
if row is not None:
|
|
607
|
-
rowid = row["vec_rowid"]
|
|
608
|
-
owner_profile = str(row["profile_id"])
|
|
609
|
-
else:
|
|
610
|
-
# Metadata-less orphan: resolve the rowid via the
|
|
611
|
-
# fact-addressable map so the raw vec0 row is still
|
|
612
|
-
# removable by fact_id.
|
|
613
|
-
mrow = conn.execute(
|
|
614
|
-
"SELECT vec_rowid, profile_id "
|
|
615
|
-
"FROM vector_row_map WHERE fact_id = ?",
|
|
616
|
-
(fact_id,),
|
|
617
|
-
).fetchone()
|
|
618
|
-
if mrow is not None:
|
|
619
|
-
rowid = mrow["vec_rowid"]
|
|
620
|
-
owner_profile = str(mrow["profile_id"])
|
|
621
|
-
|
|
622
|
-
if rowid is None:
|
|
623
|
-
return False
|
|
624
|
-
|
|
625
|
-
vector_row = conn.execute(
|
|
626
|
-
"SELECT profile_id FROM fact_embeddings WHERE rowid = ?",
|
|
627
|
-
(rowid,),
|
|
628
|
-
).fetchone()
|
|
629
|
-
if vector_row is not None and (
|
|
630
|
-
str(vector_row["profile_id"]) == owner_profile
|
|
631
|
-
):
|
|
632
|
-
conn.execute(
|
|
633
|
-
"DELETE FROM fact_embeddings WHERE rowid = ?",
|
|
634
|
-
(rowid,),
|
|
635
|
-
)
|
|
636
|
-
conn.execute(
|
|
637
|
-
"DELETE FROM embedding_metadata WHERE vec_rowid = ?",
|
|
638
|
-
(rowid,),
|
|
639
|
-
)
|
|
640
|
-
conn.execute(
|
|
641
|
-
"DELETE FROM vector_row_map WHERE fact_id = ?",
|
|
642
|
-
(fact_id,),
|
|
643
|
-
)
|
|
644
|
-
conn.commit()
|
|
645
|
-
return True
|
|
646
|
-
except Exception as exc:
|
|
647
|
-
logger.debug("delete failed for fact_id=%s: %s", fact_id, exc)
|
|
648
|
-
return False
|
|
649
|
-
|
|
650
|
-
def raw_vector_present(self, fact_id: str) -> bool:
|
|
651
|
-
if not self._available:
|
|
652
|
-
try:
|
|
653
|
-
conn = sqlite3.connect(str(self._db_path))
|
|
654
|
-
try:
|
|
655
|
-
row = conn.execute(
|
|
656
|
-
"SELECT 1 FROM vector_row_map WHERE fact_id = ? LIMIT 1",
|
|
657
|
-
(fact_id,),
|
|
658
|
-
).fetchone()
|
|
659
|
-
return row is not None
|
|
660
|
-
finally:
|
|
661
|
-
conn.close()
|
|
662
|
-
except Exception:
|
|
663
|
-
return False
|
|
664
|
-
try:
|
|
665
|
-
with self._managed_connection() as conn:
|
|
666
|
-
row = conn.execute(
|
|
667
|
-
"SELECT 1 FROM vector_row_map vrm "
|
|
668
|
-
"WHERE vrm.fact_id = ? "
|
|
669
|
-
"AND EXISTS (SELECT 1 FROM fact_embeddings fe "
|
|
670
|
-
"WHERE fe.rowid = vrm.vec_rowid)",
|
|
671
|
-
(fact_id,),
|
|
672
|
-
).fetchone()
|
|
673
|
-
return row is not None
|
|
674
|
-
except Exception:
|
|
675
|
-
try:
|
|
676
|
-
conn2 = sqlite3.connect(str(self._db_path))
|
|
677
|
-
try:
|
|
678
|
-
row = conn2.execute(
|
|
679
|
-
"SELECT 1 FROM vector_row_map WHERE fact_id = ? LIMIT 1",
|
|
680
|
-
(fact_id,),
|
|
681
|
-
).fetchone()
|
|
682
|
-
return row is not None
|
|
683
|
-
finally:
|
|
684
|
-
conn2.close()
|
|
685
|
-
except Exception:
|
|
686
|
-
return False
|
|
687
|
-
|
|
688
|
-
def is_searchable_by_meaning(
|
|
689
|
-
self,
|
|
690
|
-
fact_id: str,
|
|
691
|
-
profile_id: str | None = None,
|
|
692
|
-
) -> bool:
|
|
693
|
-
"""Return True if search() would be able to return this fact.
|
|
694
|
-
|
|
695
|
-
The check mirrors search()'s own join:
|
|
696
|
-
|
|
697
|
-
FROM fact_embeddings AS fe
|
|
698
|
-
JOIN embedding_metadata AS em
|
|
699
|
-
ON em.vec_rowid = fe.rowid
|
|
700
|
-
AND em.profile_id = fe.profile_id
|
|
701
|
-
|
|
702
|
-
A fact that has a vector in fact_embeddings but no row in
|
|
703
|
-
embedding_metadata will NOT be returned by search(), so this method
|
|
704
|
-
returns False for it — even though raw_vector_present() would return
|
|
705
|
-
True. Callers that need to decide whether a fact requires re-embedding
|
|
706
|
-
must use this method, not raw_vector_present().
|
|
707
|
-
|
|
708
|
-
Returns False on any error or when the store is unavailable (fail-
|
|
709
|
-
closed: never optimistic).
|
|
710
|
-
"""
|
|
711
|
-
if not self._available:
|
|
712
|
-
return False
|
|
713
|
-
try:
|
|
714
|
-
with self._managed_connection() as conn:
|
|
715
|
-
if profile_id is not None:
|
|
716
|
-
sql = (
|
|
717
|
-
"SELECT 1 FROM fact_embeddings AS fe "
|
|
718
|
-
"JOIN embedding_metadata AS em "
|
|
719
|
-
"ON em.vec_rowid = fe.rowid "
|
|
720
|
-
"AND em.profile_id = fe.profile_id "
|
|
721
|
-
"WHERE em.fact_id = ? "
|
|
722
|
-
"AND fe.profile_id = ? "
|
|
723
|
-
"LIMIT 1"
|
|
724
|
-
)
|
|
725
|
-
row = conn.execute(sql, (fact_id, profile_id)).fetchone()
|
|
726
|
-
else:
|
|
727
|
-
sql = (
|
|
728
|
-
"SELECT 1 FROM fact_embeddings AS fe "
|
|
729
|
-
"JOIN embedding_metadata AS em "
|
|
730
|
-
"ON em.vec_rowid = fe.rowid "
|
|
731
|
-
"AND em.profile_id = fe.profile_id "
|
|
732
|
-
"WHERE em.fact_id = ? "
|
|
733
|
-
"LIMIT 1"
|
|
734
|
-
)
|
|
735
|
-
row = conn.execute(sql, (fact_id,)).fetchone()
|
|
736
|
-
return row is not None
|
|
737
|
-
except Exception:
|
|
738
|
-
return False
|
|
739
|
-
|
|
740
|
-
def count(self, profile_id: str | None = None) -> int:
|
|
741
|
-
"""Count complete metadata/vector pairs in the store.
|
|
742
|
-
|
|
743
|
-
Returns 0 if unavailable.
|
|
744
|
-
"""
|
|
745
|
-
if not self._available:
|
|
746
|
-
return 0
|
|
747
|
-
|
|
748
|
-
try:
|
|
749
|
-
with self._managed_connection() as conn:
|
|
750
|
-
if profile_id is not None:
|
|
751
|
-
row = conn.execute(
|
|
752
|
-
"SELECT COUNT(*) AS c "
|
|
753
|
-
"FROM embedding_metadata em "
|
|
754
|
-
"JOIN fact_embeddings fe "
|
|
755
|
-
"ON fe.rowid = em.vec_rowid "
|
|
756
|
-
"AND fe.profile_id = em.profile_id "
|
|
757
|
-
"WHERE em.profile_id = ?",
|
|
758
|
-
(profile_id,),
|
|
759
|
-
).fetchone()
|
|
760
|
-
else:
|
|
761
|
-
row = conn.execute(
|
|
762
|
-
"SELECT COUNT(*) AS c "
|
|
763
|
-
"FROM embedding_metadata em "
|
|
764
|
-
"JOIN fact_embeddings fe "
|
|
765
|
-
"ON fe.rowid = em.vec_rowid "
|
|
766
|
-
"AND fe.profile_id = em.profile_id",
|
|
767
|
-
).fetchone()
|
|
768
|
-
return int(row["c"]) if row else 0
|
|
769
|
-
except Exception as exc:
|
|
770
|
-
logger.debug("count failed: %s", exc)
|
|
771
|
-
return 0
|
|
772
|
-
|
|
773
|
-
def indexed_fact_ids(self, profile_id: str) -> set[str]:
|
|
774
|
-
"""Return fact IDs backed by both metadata and a vec0 payload."""
|
|
775
|
-
if not self._available:
|
|
776
|
-
return set()
|
|
777
|
-
try:
|
|
778
|
-
with self._managed_connection() as conn:
|
|
779
|
-
rows = conn.execute(
|
|
780
|
-
"SELECT em.fact_id "
|
|
781
|
-
"FROM embedding_metadata em "
|
|
782
|
-
"JOIN fact_embeddings fe "
|
|
783
|
-
"ON fe.rowid = em.vec_rowid "
|
|
784
|
-
"AND fe.profile_id = em.profile_id "
|
|
785
|
-
"WHERE em.profile_id = ?",
|
|
786
|
-
(profile_id,),
|
|
787
|
-
).fetchall()
|
|
788
|
-
return {str(row["fact_id"]) for row in rows}
|
|
789
|
-
except Exception as exc:
|
|
790
|
-
logger.debug("indexed_fact_ids failed: %s", exc)
|
|
791
|
-
return set()
|
|
792
|
-
|
|
793
|
-
def gc_orphaned_vectors(self, profile_id: str | None = None) -> int:
|
|
794
|
-
"""Physically remove vec0 rows not referenced by any fact-addressable
|
|
795
|
-
mapping (neither embedding_metadata nor vector_row_map).
|
|
796
|
-
|
|
797
|
-
Such rows are unreachable by fact_id and would otherwise persist forever.
|
|
798
|
-
Returns the count removed. No-op when the vector backend is unavailable.
|
|
799
|
-
"""
|
|
800
|
-
if not self._available:
|
|
801
|
-
return 0
|
|
802
|
-
|
|
803
|
-
_wl = get_write_lock(self._db_path)
|
|
804
|
-
with _wl:
|
|
805
|
-
with self._lock:
|
|
806
|
-
try:
|
|
807
|
-
with self._managed_connection() as conn:
|
|
808
|
-
conn.execute("BEGIN IMMEDIATE")
|
|
809
|
-
orphans = self._orphan_rowids(conn, profile_id)
|
|
810
|
-
for rowid in orphans:
|
|
811
|
-
conn.execute(
|
|
812
|
-
"DELETE FROM fact_embeddings WHERE rowid = ?",
|
|
813
|
-
(rowid,),
|
|
814
|
-
)
|
|
815
|
-
conn.commit()
|
|
816
|
-
return len(orphans)
|
|
817
|
-
except Exception as exc:
|
|
818
|
-
logger.debug("gc_orphaned_vectors failed: %s", exc)
|
|
819
|
-
return 0
|
|
820
|
-
|
|
821
|
-
@staticmethod
|
|
822
|
-
def _orphan_rowids(conn: sqlite3.Connection, profile_id: str | None) -> set[int]:
|
|
823
|
-
"""vec0 rowids not referenced by embedding_metadata or vector_row_map."""
|
|
824
|
-
if profile_id is not None:
|
|
825
|
-
all_rowids = {r[0] for r in conn.execute(
|
|
826
|
-
"SELECT rowid FROM fact_embeddings WHERE profile_id = ?",
|
|
827
|
-
(profile_id,)).fetchall()}
|
|
828
|
-
ref_meta = {r[0] for r in conn.execute(
|
|
829
|
-
"SELECT vec_rowid FROM embedding_metadata WHERE profile_id = ?",
|
|
830
|
-
(profile_id,)).fetchall()}
|
|
831
|
-
ref_map = {r[0] for r in conn.execute(
|
|
832
|
-
"SELECT vec_rowid FROM vector_row_map WHERE profile_id = ?",
|
|
833
|
-
(profile_id,)).fetchall()}
|
|
834
|
-
else:
|
|
835
|
-
all_rowids = {r[0] for r in conn.execute(
|
|
836
|
-
"SELECT rowid FROM fact_embeddings").fetchall()}
|
|
837
|
-
ref_meta = {r[0] for r in conn.execute(
|
|
838
|
-
"SELECT vec_rowid FROM embedding_metadata").fetchall()}
|
|
839
|
-
ref_map = {r[0] for r in conn.execute(
|
|
840
|
-
"SELECT vec_rowid FROM vector_row_map").fetchall()}
|
|
841
|
-
return all_rowids - ref_meta - ref_map
|
|
842
|
-
|
|
843
|
-
def rebuild_from_facts(
|
|
844
|
-
self,
|
|
845
|
-
facts: list[tuple[str, str, list[float]]],
|
|
846
|
-
) -> int:
|
|
847
|
-
"""Migrate existing facts from JSON TEXT embeddings to vec0.
|
|
848
|
-
|
|
849
|
-
Args:
|
|
850
|
-
facts: List of (fact_id, profile_id, embedding) tuples.
|
|
851
|
-
|
|
852
|
-
Returns:
|
|
853
|
-
Number of vectors successfully migrated.
|
|
854
|
-
"""
|
|
855
|
-
count = 0
|
|
856
|
-
for fact_id, profile_id, embedding in facts:
|
|
857
|
-
if self.upsert(fact_id, profile_id, embedding):
|
|
858
|
-
count += 1
|
|
859
|
-
return count
|
|
860
|
-
|
|
861
|
-
def needs_binary_quantization(self, profile_id: str) -> bool:
|
|
862
|
-
"""Check if BQ should be enabled (count >= 100K threshold)."""
|
|
863
|
-
return self.count(profile_id) >= self._config.binary_quantization_threshold
|