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,550 +0,0 @@
|
|
|
1
|
-
"""capture.py — Lossless shadow-capture of real proxy traffic (v3.6.10, plan §7).
|
|
2
|
-
|
|
3
|
-
Purpose: build a dogfood corpus of real {request, response, model, tokens,
|
|
4
|
-
content_type} pairs so the cache + compression benchmark (benchmarks/optimize/)
|
|
5
|
-
can be replayed against authentic traffic instead of only synthetic prompts.
|
|
6
|
-
|
|
7
|
-
Activation: set ``SLM_OPTIMIZE_CAPTURE=1`` in the daemon's environment. When on:
|
|
8
|
-
* the proxy runs in PURE PASSTHROUGH — cache + compression hooks are disabled
|
|
9
|
-
at load time (see server._load_hooks), so capture never observes a mutated
|
|
10
|
-
request or a cache hit; every line is a genuine upstream exchange.
|
|
11
|
-
* each completed exchange is appended as one JSON line to
|
|
12
|
-
``~/.superlocalmemory/optimize_capture.jsonl`` (owner-only: POSIX 0600 or
|
|
13
|
-
Windows owner DACL, gitignored).
|
|
14
|
-
|
|
15
|
-
ISOLATION GUARANTEE: this module writes ONLY to optimize_capture.jsonl. It never
|
|
16
|
-
opens memory.db, llmcache.db, or any SLM memory store. (Plan §9 hard rule.)
|
|
17
|
-
|
|
18
|
-
FAIL-OPEN: a capture failure (disk full, permission, encode error) is logged and
|
|
19
|
-
swallowed — it MUST NOT break the proxied request the user is waiting on.
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
from __future__ import annotations
|
|
23
|
-
|
|
24
|
-
import asyncio
|
|
25
|
-
import errno
|
|
26
|
-
import json
|
|
27
|
-
import logging
|
|
28
|
-
import os
|
|
29
|
-
import stat
|
|
30
|
-
import threading
|
|
31
|
-
from pathlib import Path
|
|
32
|
-
from typing import Any
|
|
33
|
-
|
|
34
|
-
from superlocalmemory.infra.data_root import state_path
|
|
35
|
-
|
|
36
|
-
logger = logging.getLogger("slm.optimize.proxy.capture")
|
|
37
|
-
|
|
38
|
-
_CAPTURE_FILENAME = "optimize_capture.jsonl"
|
|
39
|
-
_CAPTURE_ENV = "SLM_OPTIMIZE_CAPTURE"
|
|
40
|
-
_TRUTHY = frozenset({"1", "true", "yes", "on"})
|
|
41
|
-
|
|
42
|
-
# Cap a single captured body so a pathological 10 MB request can't bloat the
|
|
43
|
-
# corpus line beyond what the replay harness will read back. Bodies above this
|
|
44
|
-
# are recorded truncated with a marker (capture is for benchmarking, not audit).
|
|
45
|
-
_MAX_CAPTURE_BODY_BYTES = 1 * 1024 * 1024 # 1 MB per side
|
|
46
|
-
|
|
47
|
-
# Providers whose response bodies follow the OpenAI usage schema
|
|
48
|
-
# ({"usage": {"prompt_tokens", "completion_tokens"}, "model"}).
|
|
49
|
-
_OPENAI_FORMAT_PROVIDERS = frozenset({"openai", "gemini-openai-compat"})
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def capture_enabled() -> bool:
|
|
53
|
-
"""True iff ``SLM_OPTIMIZE_CAPTURE`` is set to a truthy value."""
|
|
54
|
-
return os.environ.get(_CAPTURE_ENV, "").strip().lower() in _TRUTHY
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def _capture_path() -> Path:
|
|
58
|
-
return state_path(_CAPTURE_FILENAME)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def _is_windows() -> bool:
|
|
62
|
-
"""Return whether the running platform uses Windows DACLs."""
|
|
63
|
-
return os.name == "nt"
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def _is_link_or_reparse(info: os.stat_result) -> bool:
|
|
67
|
-
"""Reject POSIX symlinks and Windows reparse points before capture."""
|
|
68
|
-
reparse = getattr(stat, "FILE_ATTRIBUTE_REPARSE_POINT", 0)
|
|
69
|
-
attributes = getattr(info, "st_file_attributes", 0)
|
|
70
|
-
return stat.S_ISLNK(info.st_mode) or bool(reparse and attributes & reparse)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def _windows_owner_dacl(
|
|
74
|
-
win32api: Any,
|
|
75
|
-
win32con: Any,
|
|
76
|
-
win32security: Any,
|
|
77
|
-
) -> tuple[Any, Any]:
|
|
78
|
-
"""Build one protected owner-only DACL for a Windows capture file."""
|
|
79
|
-
import ntsecuritycon
|
|
80
|
-
|
|
81
|
-
token = win32security.OpenProcessToken(
|
|
82
|
-
win32api.GetCurrentProcess(),
|
|
83
|
-
win32con.TOKEN_QUERY,
|
|
84
|
-
)
|
|
85
|
-
try:
|
|
86
|
-
owner_sid = win32security.GetTokenInformation(
|
|
87
|
-
token,
|
|
88
|
-
win32security.TokenUser,
|
|
89
|
-
)[0]
|
|
90
|
-
finally:
|
|
91
|
-
token.Close()
|
|
92
|
-
dacl = win32security.ACL()
|
|
93
|
-
dacl.AddAccessAllowedAce(
|
|
94
|
-
win32security.ACL_REVISION,
|
|
95
|
-
ntsecuritycon.FILE_ALL_ACCESS,
|
|
96
|
-
owner_sid,
|
|
97
|
-
)
|
|
98
|
-
return owner_sid, dacl
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def _windows_dacl_is_owner_only(
|
|
102
|
-
security_descriptor: Any,
|
|
103
|
-
owner_sid: Any,
|
|
104
|
-
ntsecuritycon: Any,
|
|
105
|
-
win32security: Any,
|
|
106
|
-
) -> bool:
|
|
107
|
-
"""Return whether a live descriptor already matches the capture policy."""
|
|
108
|
-
def _same_sid(left: Any, right: Any) -> bool:
|
|
109
|
-
try:
|
|
110
|
-
return (
|
|
111
|
-
win32security.ConvertSidToStringSid(left)
|
|
112
|
-
== win32security.ConvertSidToStringSid(right)
|
|
113
|
-
)
|
|
114
|
-
except Exception:
|
|
115
|
-
return False
|
|
116
|
-
|
|
117
|
-
control, _revision = security_descriptor.GetSecurityDescriptorControl()
|
|
118
|
-
if not control & win32security.SE_DACL_PROTECTED:
|
|
119
|
-
return False
|
|
120
|
-
|
|
121
|
-
descriptor_owner = security_descriptor.GetSecurityDescriptorOwner()
|
|
122
|
-
if descriptor_owner is None or not _same_sid(
|
|
123
|
-
descriptor_owner,
|
|
124
|
-
owner_sid,
|
|
125
|
-
):
|
|
126
|
-
return False
|
|
127
|
-
|
|
128
|
-
dacl = security_descriptor.GetSecurityDescriptorDacl()
|
|
129
|
-
if dacl is None or dacl.GetAceCount() != 1:
|
|
130
|
-
return False
|
|
131
|
-
|
|
132
|
-
ace = dacl.GetAce(0)
|
|
133
|
-
if not isinstance(ace, tuple) or len(ace) != 3:
|
|
134
|
-
return False
|
|
135
|
-
ace_header, access_mask, ace_sid = ace
|
|
136
|
-
if (
|
|
137
|
-
not isinstance(ace_header, tuple)
|
|
138
|
-
or not ace_header
|
|
139
|
-
or ace_header[0] != win32security.ACCESS_ALLOWED_ACE_TYPE
|
|
140
|
-
):
|
|
141
|
-
return False
|
|
142
|
-
if access_mask & ntsecuritycon.FILE_ALL_ACCESS != ntsecuritycon.FILE_ALL_ACCESS:
|
|
143
|
-
return False
|
|
144
|
-
return _same_sid(ace_sid, owner_sid)
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def _open_windows_capture_append(path: Path) -> int:
|
|
148
|
-
"""Create/open a Windows file with append + WRITE_DAC on one handle."""
|
|
149
|
-
try:
|
|
150
|
-
import msvcrt
|
|
151
|
-
|
|
152
|
-
import ntsecuritycon
|
|
153
|
-
import win32api
|
|
154
|
-
import win32con
|
|
155
|
-
import win32file
|
|
156
|
-
import win32security
|
|
157
|
-
except ImportError as exc:
|
|
158
|
-
raise OSError("Windows capture ACL support is unavailable") from exc
|
|
159
|
-
|
|
160
|
-
handle = None
|
|
161
|
-
try:
|
|
162
|
-
# A creation-time descriptor prevents a newly created capture file from
|
|
163
|
-
# ever inheriting a broader parent DACL. For an existing file Windows
|
|
164
|
-
# ignores this descriptor; _enforce_owner_only_permissions replaces
|
|
165
|
-
# that DACL through the same WRITE_DAC-capable handle before writing.
|
|
166
|
-
owner_sid, dacl = _windows_owner_dacl(
|
|
167
|
-
win32api,
|
|
168
|
-
win32con,
|
|
169
|
-
win32security,
|
|
170
|
-
)
|
|
171
|
-
security_attributes = win32security.SECURITY_ATTRIBUTES()
|
|
172
|
-
security_attributes.bInheritHandle = False
|
|
173
|
-
security_attributes.SECURITY_DESCRIPTOR.SetSecurityDescriptorDacl(
|
|
174
|
-
1,
|
|
175
|
-
dacl,
|
|
176
|
-
0,
|
|
177
|
-
)
|
|
178
|
-
security_attributes.SECURITY_DESCRIPTOR.SetSecurityDescriptorControl(
|
|
179
|
-
win32security.SE_DACL_PROTECTED,
|
|
180
|
-
win32security.SE_DACL_PROTECTED,
|
|
181
|
-
)
|
|
182
|
-
desired_access = (
|
|
183
|
-
ntsecuritycon.FILE_APPEND_DATA
|
|
184
|
-
| ntsecuritycon.WRITE_DAC
|
|
185
|
-
| ntsecuritycon.READ_CONTROL
|
|
186
|
-
)
|
|
187
|
-
share_mode = (
|
|
188
|
-
win32con.FILE_SHARE_READ
|
|
189
|
-
| win32con.FILE_SHARE_WRITE
|
|
190
|
-
| win32con.FILE_SHARE_DELETE
|
|
191
|
-
)
|
|
192
|
-
file_flags = (
|
|
193
|
-
win32con.FILE_ATTRIBUTE_NORMAL
|
|
194
|
-
# pywin32 does not export this SDK constant from win32con on
|
|
195
|
-
# every supported Python build. Keep the Microsoft-defined value
|
|
196
|
-
# as a named fallback rather than silently following a reparse.
|
|
197
|
-
| getattr(win32con, "FILE_FLAG_OPEN_REPARSE_POINT", 0x00200000)
|
|
198
|
-
)
|
|
199
|
-
try:
|
|
200
|
-
# CREATE_NEW is the only race-safe proof that the protected
|
|
201
|
-
# SECURITY_ATTRIBUTES were applied to this exact file. OPEN_ALWAYS
|
|
202
|
-
# would require trusting GetLastError after the pywin32 wrapper has
|
|
203
|
-
# returned, which is not a documented preservation boundary.
|
|
204
|
-
handle = win32file.CreateFile(
|
|
205
|
-
os.fspath(path),
|
|
206
|
-
desired_access,
|
|
207
|
-
share_mode,
|
|
208
|
-
security_attributes,
|
|
209
|
-
getattr(win32con, "CREATE_NEW", 1),
|
|
210
|
-
file_flags,
|
|
211
|
-
None,
|
|
212
|
-
)
|
|
213
|
-
created_new = True
|
|
214
|
-
except Exception as exc:
|
|
215
|
-
winerror = getattr(exc, "winerror", None)
|
|
216
|
-
if winerror is None and exc.args:
|
|
217
|
-
winerror = exc.args[0]
|
|
218
|
-
if winerror != getattr(win32con, "ERROR_FILE_EXISTS", 80):
|
|
219
|
-
raise
|
|
220
|
-
# The creation descriptor is ignored for existing files. Reopen
|
|
221
|
-
# the exact path without following a reparse point, then replace
|
|
222
|
-
# its DACL through this WRITE_DAC-capable handle before appending.
|
|
223
|
-
handle = win32file.CreateFile(
|
|
224
|
-
os.fspath(path),
|
|
225
|
-
desired_access,
|
|
226
|
-
share_mode,
|
|
227
|
-
None,
|
|
228
|
-
getattr(win32con, "OPEN_EXISTING", 3),
|
|
229
|
-
file_flags,
|
|
230
|
-
None,
|
|
231
|
-
)
|
|
232
|
-
created_new = False
|
|
233
|
-
file_info = win32file.GetFileInformationByHandle(handle)
|
|
234
|
-
if file_info[0] & win32con.FILE_ATTRIBUTE_REPARSE_POINT:
|
|
235
|
-
raise OSError(
|
|
236
|
-
errno.ELOOP,
|
|
237
|
-
"capture path is a Windows reparse point",
|
|
238
|
-
path,
|
|
239
|
-
)
|
|
240
|
-
if not created_new:
|
|
241
|
-
try:
|
|
242
|
-
query_flags = (
|
|
243
|
-
win32security.OWNER_SECURITY_INFORMATION
|
|
244
|
-
| win32security.DACL_SECURITY_INFORMATION
|
|
245
|
-
)
|
|
246
|
-
descriptor = win32security.GetSecurityInfo(
|
|
247
|
-
handle,
|
|
248
|
-
win32security.SE_FILE_OBJECT,
|
|
249
|
-
query_flags,
|
|
250
|
-
)
|
|
251
|
-
if not _windows_dacl_is_owner_only(
|
|
252
|
-
descriptor,
|
|
253
|
-
owner_sid,
|
|
254
|
-
ntsecuritycon,
|
|
255
|
-
win32security,
|
|
256
|
-
):
|
|
257
|
-
# Existing files ignore the creation security descriptor,
|
|
258
|
-
# so repair an unsafe DACL while this is still the original
|
|
259
|
-
# CreateFile handle carrying WRITE_DAC. Avoid rewriting an
|
|
260
|
-
# already-protected DACL: Windows may correctly deny that
|
|
261
|
-
# redundant mutation even though append access is allowed.
|
|
262
|
-
win32security.SetSecurityInfo(
|
|
263
|
-
handle,
|
|
264
|
-
win32security.SE_FILE_OBJECT,
|
|
265
|
-
win32security.DACL_SECURITY_INFORMATION
|
|
266
|
-
| win32security.PROTECTED_DACL_SECURITY_INFORMATION,
|
|
267
|
-
None,
|
|
268
|
-
None,
|
|
269
|
-
dacl,
|
|
270
|
-
None,
|
|
271
|
-
)
|
|
272
|
-
descriptor = win32security.GetSecurityInfo(
|
|
273
|
-
handle,
|
|
274
|
-
win32security.SE_FILE_OBJECT,
|
|
275
|
-
query_flags,
|
|
276
|
-
)
|
|
277
|
-
if not _windows_dacl_is_owner_only(
|
|
278
|
-
descriptor,
|
|
279
|
-
owner_sid,
|
|
280
|
-
ntsecuritycon,
|
|
281
|
-
win32security,
|
|
282
|
-
):
|
|
283
|
-
raise OSError(
|
|
284
|
-
"Windows capture ACL verification failed after repair"
|
|
285
|
-
)
|
|
286
|
-
except Exception as exc:
|
|
287
|
-
raise OSError(
|
|
288
|
-
"Windows capture ACL could not be enforced "
|
|
289
|
-
f"({type(exc).__name__}: {exc})"
|
|
290
|
-
) from exc
|
|
291
|
-
|
|
292
|
-
# Transfer the native handle to Python's CRT descriptor exactly once.
|
|
293
|
-
raw_handle = handle.Detach()
|
|
294
|
-
handle = None
|
|
295
|
-
try:
|
|
296
|
-
return msvcrt.open_osfhandle(
|
|
297
|
-
raw_handle,
|
|
298
|
-
os.O_WRONLY | os.O_APPEND | getattr(os, "O_BINARY", 0),
|
|
299
|
-
)
|
|
300
|
-
except BaseException:
|
|
301
|
-
win32api.CloseHandle(raw_handle)
|
|
302
|
-
raise
|
|
303
|
-
except OSError:
|
|
304
|
-
raise
|
|
305
|
-
except Exception as exc:
|
|
306
|
-
raise OSError(f"Windows secure capture open failed: {exc}") from exc
|
|
307
|
-
finally:
|
|
308
|
-
if handle is not None:
|
|
309
|
-
handle.Close()
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
def _open_capture_append(path: Path) -> int:
|
|
313
|
-
"""Open one append descriptor without following or racing a link target."""
|
|
314
|
-
try:
|
|
315
|
-
before = path.lstat()
|
|
316
|
-
except FileNotFoundError:
|
|
317
|
-
before = None
|
|
318
|
-
if before is not None and _is_link_or_reparse(before):
|
|
319
|
-
raise OSError(errno.ELOOP, "capture path is a link or reparse point", path)
|
|
320
|
-
|
|
321
|
-
if _is_windows():
|
|
322
|
-
fd = _open_windows_capture_append(path)
|
|
323
|
-
else:
|
|
324
|
-
flags = os.O_CREAT | os.O_WRONLY | os.O_APPEND | getattr(os, "O_NOFOLLOW", 0)
|
|
325
|
-
fd = os.open(path, flags, 0o600)
|
|
326
|
-
try:
|
|
327
|
-
opened = os.fstat(fd)
|
|
328
|
-
current = path.lstat()
|
|
329
|
-
if (
|
|
330
|
-
_is_link_or_reparse(current)
|
|
331
|
-
or (opened.st_dev, opened.st_ino) != (current.st_dev, current.st_ino)
|
|
332
|
-
):
|
|
333
|
-
raise OSError(
|
|
334
|
-
errno.ELOOP,
|
|
335
|
-
"capture path changed during secure open",
|
|
336
|
-
path,
|
|
337
|
-
)
|
|
338
|
-
except BaseException:
|
|
339
|
-
os.close(fd)
|
|
340
|
-
raise
|
|
341
|
-
return fd
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
def _enforce_owner_only_permissions(fd: int) -> None:
|
|
345
|
-
"""Apply owner-only access control through the already-verified handle."""
|
|
346
|
-
if not _is_windows():
|
|
347
|
-
os.fchmod(fd, 0o600)
|
|
348
|
-
return
|
|
349
|
-
# _open_windows_capture_append applies the protected DACL on the original
|
|
350
|
-
# WRITE_DAC-capable CreateFile handle before CRT descriptor transfer.
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
class ShadowCapture:
|
|
354
|
-
"""Thread-safe append-only JSONL writer for proxy exchanges (singleton)."""
|
|
355
|
-
|
|
356
|
-
_instance: "ShadowCapture | None" = None
|
|
357
|
-
_instance_lock = threading.Lock()
|
|
358
|
-
|
|
359
|
-
def __init__(self, path: Path | None = None) -> None:
|
|
360
|
-
self._path = path or _capture_path()
|
|
361
|
-
self._write_lock = threading.Lock()
|
|
362
|
-
self._count = 0
|
|
363
|
-
|
|
364
|
-
@classmethod
|
|
365
|
-
def get_instance(cls) -> "ShadowCapture":
|
|
366
|
-
# Double-checked locking: cheap fast-path after first construction.
|
|
367
|
-
if cls._instance is None:
|
|
368
|
-
with cls._instance_lock:
|
|
369
|
-
if cls._instance is None:
|
|
370
|
-
cls._instance = cls()
|
|
371
|
-
return cls._instance
|
|
372
|
-
|
|
373
|
-
@classmethod
|
|
374
|
-
def reset_instance(cls) -> None:
|
|
375
|
-
"""Test hook — drop the singleton so a fresh path can be injected."""
|
|
376
|
-
with cls._instance_lock:
|
|
377
|
-
cls._instance = None
|
|
378
|
-
|
|
379
|
-
@property
|
|
380
|
-
def path(self) -> Path:
|
|
381
|
-
return self._path
|
|
382
|
-
|
|
383
|
-
@property
|
|
384
|
-
def count(self) -> int:
|
|
385
|
-
return self._count
|
|
386
|
-
|
|
387
|
-
def record(self, entry: dict[str, Any]) -> bool:
|
|
388
|
-
"""Append one capture entry as a JSON line. Returns True on success.
|
|
389
|
-
|
|
390
|
-
Fail-open: any error is logged and False is returned; never raised.
|
|
391
|
-
|
|
392
|
-
Security: opens with a single ``os.open`` carrying ``O_CREAT |
|
|
393
|
-
O_APPEND`` and mode ``0o600`` on every write. POSIX adds O_NOFOLLOW;
|
|
394
|
-
all platforms reject link/reparse metadata and verify that the opened
|
|
395
|
-
descriptor still identifies the current path. Permissions are then
|
|
396
|
-
enforced through that verified descriptor before any data is written.
|
|
397
|
-
"""
|
|
398
|
-
try:
|
|
399
|
-
line = json.dumps(entry, ensure_ascii=False, separators=(",", ":"))
|
|
400
|
-
except (TypeError, ValueError) as exc:
|
|
401
|
-
logger.warning("capture: entry not JSON-serialisable, dropped: %r", exc)
|
|
402
|
-
return False
|
|
403
|
-
|
|
404
|
-
try:
|
|
405
|
-
with self._write_lock:
|
|
406
|
-
self._path.parent.mkdir(parents=True, exist_ok=True)
|
|
407
|
-
fd = _open_capture_append(self._path)
|
|
408
|
-
try:
|
|
409
|
-
# Enforce the ACL through the verified descriptor so a
|
|
410
|
-
# pathname swap cannot redirect chmod/icacls elsewhere.
|
|
411
|
-
_enforce_owner_only_permissions(fd)
|
|
412
|
-
# fdopen transfers descriptor ownership only after it
|
|
413
|
-
# returns successfully. Keep this conversion inside the
|
|
414
|
-
# explicit-close boundary so an allocation/codec failure
|
|
415
|
-
# cannot leak one descriptor per captured request.
|
|
416
|
-
fh = os.fdopen(fd, "a", encoding="utf-8")
|
|
417
|
-
except BaseException:
|
|
418
|
-
os.close(fd)
|
|
419
|
-
raise
|
|
420
|
-
with fh:
|
|
421
|
-
fh.write(line + "\n")
|
|
422
|
-
self._count += 1
|
|
423
|
-
return True
|
|
424
|
-
except OSError as exc:
|
|
425
|
-
# PermissionError / symlink-refusal (ELOOP) are security-relevant —
|
|
426
|
-
# surface the errno but still fail open so the request is never blocked.
|
|
427
|
-
logger.warning("capture: write failed (fail-open): %r", exc)
|
|
428
|
-
return False
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
def _truncate(raw: bytes) -> tuple[str, bool]:
|
|
432
|
-
"""Decode bytes for storage; truncate beyond the per-side cap."""
|
|
433
|
-
truncated = len(raw) > _MAX_CAPTURE_BODY_BYTES
|
|
434
|
-
head = raw[:_MAX_CAPTURE_BODY_BYTES] if truncated else raw
|
|
435
|
-
return head.decode("utf-8", errors="replace"), truncated
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
def build_entry(
|
|
439
|
-
*,
|
|
440
|
-
provider: str,
|
|
441
|
-
model: str,
|
|
442
|
-
request_body: bytes,
|
|
443
|
-
response_body: bytes,
|
|
444
|
-
content_type: str,
|
|
445
|
-
input_tokens: int,
|
|
446
|
-
output_tokens: int,
|
|
447
|
-
status_code: int,
|
|
448
|
-
stream: bool,
|
|
449
|
-
) -> dict[str, Any]:
|
|
450
|
-
"""Construct a capture entry dict from a completed exchange.
|
|
451
|
-
|
|
452
|
-
No timestamp is stamped here (Date.now is intentionally avoided in some
|
|
453
|
-
runtimes); the replay harness keys on content, not time, and the file's own
|
|
454
|
-
line order preserves arrival sequence.
|
|
455
|
-
"""
|
|
456
|
-
req_str, req_trunc = _truncate(request_body)
|
|
457
|
-
resp_str, resp_trunc = _truncate(response_body)
|
|
458
|
-
return {
|
|
459
|
-
"provider": provider,
|
|
460
|
-
"model": model,
|
|
461
|
-
"content_type": content_type,
|
|
462
|
-
"stream": stream,
|
|
463
|
-
"status_code": status_code,
|
|
464
|
-
"input_tokens": int(input_tokens),
|
|
465
|
-
"output_tokens": int(output_tokens),
|
|
466
|
-
"request": req_str,
|
|
467
|
-
"response": resp_str,
|
|
468
|
-
"request_truncated": req_trunc,
|
|
469
|
-
"response_truncated": resp_trunc,
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
def extract_usage(provider: str, body: bytes | None) -> tuple[int, int, str]:
|
|
474
|
-
"""Best-effort (input_tokens, output_tokens, model) from a provider JSON body.
|
|
475
|
-
|
|
476
|
-
Works on the normalised JSON the SSE parsers emit AND on non-streaming
|
|
477
|
-
upstream JSON. Returns (0, 0, "") when the body is missing/unparseable —
|
|
478
|
-
capture must never fail because usage couldn't be read.
|
|
479
|
-
"""
|
|
480
|
-
if not body:
|
|
481
|
-
return 0, 0, ""
|
|
482
|
-
try:
|
|
483
|
-
data = json.loads(body)
|
|
484
|
-
except (json.JSONDecodeError, ValueError, TypeError):
|
|
485
|
-
return 0, 0, ""
|
|
486
|
-
if not isinstance(data, dict):
|
|
487
|
-
return 0, 0, ""
|
|
488
|
-
|
|
489
|
-
if provider == "gemini":
|
|
490
|
-
usage = data.get("usageMetadata") or {}
|
|
491
|
-
return (
|
|
492
|
-
int(usage.get("promptTokenCount", 0) or 0),
|
|
493
|
-
int(usage.get("candidatesTokenCount", 0) or 0),
|
|
494
|
-
str(data.get("modelVersion", "") or ""),
|
|
495
|
-
)
|
|
496
|
-
|
|
497
|
-
usage = data.get("usage") or {}
|
|
498
|
-
if provider == "anthropic":
|
|
499
|
-
return (
|
|
500
|
-
int(usage.get("input_tokens", 0) or 0),
|
|
501
|
-
int(usage.get("output_tokens", 0) or 0),
|
|
502
|
-
str(data.get("model", "") or ""),
|
|
503
|
-
)
|
|
504
|
-
# OpenAI-format providers (explicit allowlist so a future provider variant
|
|
505
|
-
# is not silently parsed with the wrong schema — it warns + returns zeros).
|
|
506
|
-
if provider not in _OPENAI_FORMAT_PROVIDERS:
|
|
507
|
-
logger.warning(
|
|
508
|
-
"capture.extract_usage: unknown provider %r — recording zero tokens", provider
|
|
509
|
-
)
|
|
510
|
-
return 0, 0, str(data.get("model", "") or "")
|
|
511
|
-
return (
|
|
512
|
-
int(usage.get("prompt_tokens", 0) or 0),
|
|
513
|
-
int(usage.get("completion_tokens", 0) or 0),
|
|
514
|
-
str(data.get("model", "") or ""),
|
|
515
|
-
)
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
def record_exchange(
|
|
519
|
-
*,
|
|
520
|
-
provider: str,
|
|
521
|
-
model: str,
|
|
522
|
-
request_body: bytes,
|
|
523
|
-
response_body: bytes,
|
|
524
|
-
content_type: str = "application/json",
|
|
525
|
-
input_tokens: int = 0,
|
|
526
|
-
output_tokens: int = 0,
|
|
527
|
-
status_code: int = 200,
|
|
528
|
-
stream: bool = False,
|
|
529
|
-
) -> bool:
|
|
530
|
-
"""Build + append a capture entry. Fail-open. Returns True on success."""
|
|
531
|
-
entry = build_entry(
|
|
532
|
-
provider=provider,
|
|
533
|
-
model=model,
|
|
534
|
-
request_body=request_body,
|
|
535
|
-
response_body=response_body,
|
|
536
|
-
content_type=content_type,
|
|
537
|
-
input_tokens=input_tokens,
|
|
538
|
-
output_tokens=output_tokens,
|
|
539
|
-
status_code=status_code,
|
|
540
|
-
stream=stream,
|
|
541
|
-
)
|
|
542
|
-
return ShadowCapture.get_instance().record(entry)
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
async def record_exchange_async(**kwargs: Any) -> bool:
|
|
546
|
-
"""Async wrapper for ``record_exchange`` that offloads the synchronous file
|
|
547
|
-
write to a worker thread so it never blocks the proxy event loop — relevant
|
|
548
|
-
when many streaming responses complete in the same loop iteration.
|
|
549
|
-
"""
|
|
550
|
-
return await asyncio.to_thread(lambda: record_exchange(**kwargs))
|