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,730 +0,0 @@
|
|
|
1
|
-
"""_helpers.py — Shared HTTP utilities used by all surface modules."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import asyncio
|
|
6
|
-
import inspect
|
|
7
|
-
import json
|
|
8
|
-
import logging
|
|
9
|
-
from typing import Any, AsyncIterator, Callable
|
|
10
|
-
from weakref import WeakKeyDictionary
|
|
11
|
-
|
|
12
|
-
import httpx
|
|
13
|
-
from fastapi.requests import Request
|
|
14
|
-
from fastapi.responses import Response, StreamingResponse
|
|
15
|
-
|
|
16
|
-
from superlocalmemory.optimize.proxy.lifecycle import (
|
|
17
|
-
CachedResponse,
|
|
18
|
-
HookChain,
|
|
19
|
-
ProviderResponse,
|
|
20
|
-
ProxyRequest,
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
_get_running_loop = asyncio.get_running_loop
|
|
24
|
-
|
|
25
|
-
logger = logging.getLogger("slm.optimize.proxy.helpers")
|
|
26
|
-
|
|
27
|
-
# Per-callable cache of "does this hook method accept a tenant_id kwarg?".
|
|
28
|
-
# Keep the callable itself as the key. Integer id() values can be reused after
|
|
29
|
-
# a hook class is collected, which can apply a stale legacy signature result
|
|
30
|
-
# to a new tenant-aware hook and silently drop tenant isolation.
|
|
31
|
-
_HOOK_TENANT_SUPPORT: WeakKeyDictionary[object, bool] = WeakKeyDictionary()
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def _accepts_tenant_id(fn: Callable) -> bool:
|
|
35
|
-
"""Return True if a hook method accepts a ``tenant_id`` keyword argument.
|
|
36
|
-
|
|
37
|
-
SECURITY (Stage-9 R1): the original WP-D shim used ``except TypeError`` to
|
|
38
|
-
detect legacy hooks, but that clause is structurally unable to tell a
|
|
39
|
-
signature mismatch from a TypeError raised *inside* a tenant-aware hook —
|
|
40
|
-
so an internal bug silently downgraded an authenticated request onto the
|
|
41
|
-
shared (tenant-less) path, re-opening cross-tenant disclosure. We instead
|
|
42
|
-
probe the signature ONCE (cached): a hook is treated as tenant-aware if it
|
|
43
|
-
has an explicit ``tenant_id`` parameter or accepts ``**kwargs``. A
|
|
44
|
-
tenant-aware hook is NEVER retried without the tenant_id; any error it
|
|
45
|
-
raises fails open to a cache MISS, never the shared namespace.
|
|
46
|
-
"""
|
|
47
|
-
target = getattr(fn, "__func__", fn)
|
|
48
|
-
try:
|
|
49
|
-
cached = _HOOK_TENANT_SUPPORT.get(target)
|
|
50
|
-
except TypeError:
|
|
51
|
-
# Some extension callables cannot be weak-referenced. Inspect them on
|
|
52
|
-
# every use instead of falling back to an unsafe integer identity.
|
|
53
|
-
cached = None
|
|
54
|
-
if cached is None:
|
|
55
|
-
try:
|
|
56
|
-
params = inspect.signature(fn).parameters
|
|
57
|
-
cached = "tenant_id" in params or any(
|
|
58
|
-
p.kind == inspect.Parameter.VAR_KEYWORD for p in params.values()
|
|
59
|
-
)
|
|
60
|
-
except (ValueError, TypeError):
|
|
61
|
-
# Builtins / C callables without a signature — assume legacy.
|
|
62
|
-
cached = False
|
|
63
|
-
try:
|
|
64
|
-
_HOOK_TENANT_SUPPORT[target] = cached
|
|
65
|
-
except TypeError:
|
|
66
|
-
pass
|
|
67
|
-
return cached
|
|
68
|
-
|
|
69
|
-
# SEC-M-02 (CWE-400): reject oversized bodies to prevent compression-bomb DoS.
|
|
70
|
-
_MAX_REQUEST_BODY_BYTES = 10 * 1024 * 1024 # 10 MB
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
# Test helper: in-test httpx mock transport. NOT used in production code.
|
|
74
|
-
from typing import Callable as _Callable
|
|
75
|
-
import httpx as _httpx
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
class _MockTransport(_httpx.AsyncBaseTransport):
|
|
79
|
-
"""Minimal in-test mock for httpx that records requests and returns canned responses.
|
|
80
|
-
|
|
81
|
-
Handler may be sync (returns Response) or async (returns coroutine).
|
|
82
|
-
"""
|
|
83
|
-
|
|
84
|
-
def __init__(self, handler: _Callable) -> None:
|
|
85
|
-
self._handler = handler
|
|
86
|
-
self.requests: list = []
|
|
87
|
-
|
|
88
|
-
async def handle_async_request(self, request: _httpx.Request) -> _httpx.Response:
|
|
89
|
-
self.requests.append(request)
|
|
90
|
-
result = self._handler(request)
|
|
91
|
-
if hasattr(result, "__await__"):
|
|
92
|
-
return await result
|
|
93
|
-
return result
|
|
94
|
-
|
|
95
|
-
_HOP_BY_HOP = frozenset([
|
|
96
|
-
"connection", "keep-alive", "proxy-authenticate", "proxy-authorization",
|
|
97
|
-
"te", "trailer", "transfer-encoding", "upgrade", "host",
|
|
98
|
-
"x-forwarded-for", "x-forwarded-host", "x-forwarded-proto",
|
|
99
|
-
"x-real-ip", "x-original-forwarded-for",
|
|
100
|
-
# ponytail: httpx decompresses gzip automatically; forwarding this header
|
|
101
|
-
# causes clients to double-decompress → ZlibError. Strip it here.
|
|
102
|
-
"content-encoding",
|
|
103
|
-
])
|
|
104
|
-
|
|
105
|
-
_ANTHROPIC_FORWARD_HEADERS = frozenset([
|
|
106
|
-
"x-api-key",
|
|
107
|
-
"anthropic-version",
|
|
108
|
-
"anthropic-beta",
|
|
109
|
-
"x-claude-code-session-id",
|
|
110
|
-
"x-claude-code-agent-id",
|
|
111
|
-
"x-claude-code-parent-agent-id",
|
|
112
|
-
"authorization",
|
|
113
|
-
"content-type",
|
|
114
|
-
])
|
|
115
|
-
|
|
116
|
-
_OPENAI_FORWARD_HEADERS = frozenset([
|
|
117
|
-
"authorization",
|
|
118
|
-
"content-type",
|
|
119
|
-
"openai-beta",
|
|
120
|
-
"openai-organization",
|
|
121
|
-
])
|
|
122
|
-
|
|
123
|
-
_GEMINI_NATIVE_FORWARD_HEADERS = frozenset([
|
|
124
|
-
"x-goog-api-key",
|
|
125
|
-
"content-type",
|
|
126
|
-
"authorization", # Antigravity ADC/OAuth bearer was previously dropped; explicitly add it back
|
|
127
|
-
])
|
|
128
|
-
|
|
129
|
-
# Vertex AI forward headers — Authorization is passed through untouched.
|
|
130
|
-
# x-goog-user-project required for quota attribution on Vertex calls.
|
|
131
|
-
_VERTEX_FORWARD_HEADERS = frozenset([
|
|
132
|
-
"authorization",
|
|
133
|
-
"content-type",
|
|
134
|
-
"x-goog-api-key",
|
|
135
|
-
"x-goog-user-project",
|
|
136
|
-
])
|
|
137
|
-
|
|
138
|
-
_GEMINI_OPENAI_COMPAT_FORWARD_HEADERS = frozenset([
|
|
139
|
-
"authorization",
|
|
140
|
-
"content-type",
|
|
141
|
-
])
|
|
142
|
-
|
|
143
|
-
_SENSITIVE_HEADER_KEYS = frozenset([
|
|
144
|
-
"authorization",
|
|
145
|
-
"x-api-key",
|
|
146
|
-
"x-goog-api-key",
|
|
147
|
-
])
|
|
148
|
-
_REDACTED = "[REDACTED]"
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
def _redact_headers(headers: dict) -> dict:
|
|
152
|
-
return {
|
|
153
|
-
k: (_REDACTED if k.lower() in _SENSITIVE_HEADER_KEYS else v)
|
|
154
|
-
for k, v in headers.items()
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
def _active_profile_for_cache() -> str:
|
|
159
|
-
"""Resolve the active memory profile for cache-tenant scoping.
|
|
160
|
-
|
|
161
|
-
Lazy import keeps the optimize layer free of a hard server dependency; any
|
|
162
|
-
failure falls back to 'default'. The profiles.json active_profile cache is
|
|
163
|
-
kept in sync on every switch, so this is correct for the daemon-mounted
|
|
164
|
-
proxy even outside an HTTP request context.
|
|
165
|
-
"""
|
|
166
|
-
try:
|
|
167
|
-
from superlocalmemory.server.routes.helpers import get_active_profile
|
|
168
|
-
return get_active_profile() or "default"
|
|
169
|
-
except Exception:
|
|
170
|
-
return "default"
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
def _derive_tenant_id(provider: str, raw_credential: "str | None") -> "str | None":
|
|
174
|
-
"""Derive a per-tenant isolation key from the raw (un-redacted) credential.
|
|
175
|
-
|
|
176
|
-
SECURITY (WP-D): Called at the surface-handler layer BEFORE _redact_headers
|
|
177
|
-
strips the credential from ProxyRequest.headers. The derived id is threaded
|
|
178
|
-
into CacheManager.check() / .store() so that two users sharing the same
|
|
179
|
-
prompt but using different API keys receive independent cache namespaces.
|
|
180
|
-
|
|
181
|
-
ISOLATION (I-5): the active memory profile is folded into the key so two
|
|
182
|
-
profiles sharing the SAME API key never serve each other's cached LLM
|
|
183
|
-
responses. Cross-profile cache reuse is intentionally sacrificed for
|
|
184
|
-
tenant isolation (the accepted cost tradeoff for a multi-tenant memory DB).
|
|
185
|
-
|
|
186
|
-
Returns None when no credential is present — callers must SKIP caching
|
|
187
|
-
(never collapse to the default tenant) to prevent cross-tenant disclosure.
|
|
188
|
-
|
|
189
|
-
Output: 64-char lowercase hex SHA-256 of
|
|
190
|
-
``f"{profile}:{provider}:{raw_credential}"``. Provider is folded in so
|
|
191
|
-
anthropic:K and openai:K are distinct tenants even if the literal key
|
|
192
|
-
string coincidentally matches.
|
|
193
|
-
"""
|
|
194
|
-
import hashlib as _hashlib
|
|
195
|
-
|
|
196
|
-
if not raw_credential:
|
|
197
|
-
return None
|
|
198
|
-
profile = _active_profile_for_cache()
|
|
199
|
-
return _hashlib.sha256(
|
|
200
|
-
f"{profile}:{provider}:{raw_credential}".encode()
|
|
201
|
-
).hexdigest()
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
def _body_has_tools(body: dict) -> bool:
|
|
205
|
-
tools = body.get("tools")
|
|
206
|
-
return isinstance(tools, list) and len(tools) > 0
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
def _build_forward_headers(request: Request, allowed: frozenset) -> dict:
|
|
210
|
-
result: dict = {}
|
|
211
|
-
for k, v in request.headers.items():
|
|
212
|
-
kl = k.lower()
|
|
213
|
-
if kl in _HOP_BY_HOP:
|
|
214
|
-
continue
|
|
215
|
-
if kl in allowed:
|
|
216
|
-
result[kl] = v
|
|
217
|
-
return result
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
def _filter_response_headers(headers) -> dict:
|
|
221
|
-
if hasattr(headers, "items"):
|
|
222
|
-
items = headers.items()
|
|
223
|
-
else:
|
|
224
|
-
items = headers
|
|
225
|
-
return {k: v for k, v in items if k.lower() not in _HOP_BY_HOP}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
# ---------------------------------------------------------------------------
|
|
229
|
-
# SSE → JSON converter (for streaming cache hits and post-stream storage)
|
|
230
|
-
# ---------------------------------------------------------------------------
|
|
231
|
-
|
|
232
|
-
def _parse_sse_to_json(sse_bytes: bytes) -> bytes | None:
|
|
233
|
-
"""Parse an accumulated Anthropic SSE stream into a single JSON message.
|
|
234
|
-
|
|
235
|
-
Used for two purposes:
|
|
236
|
-
1. After a streaming response completes — store the assembled JSON in the
|
|
237
|
-
cache so the next identical streaming request is served from cache.
|
|
238
|
-
2. Cache hit path — convert stored JSON back to SSE via _sse_from_cached_json
|
|
239
|
-
in anthropic_surface.py.
|
|
240
|
-
|
|
241
|
-
Returns None if the bytes are not a valid/complete Anthropic SSE stream
|
|
242
|
-
(e.g. error response, client-disconnected partial, or empty). The caller
|
|
243
|
-
MUST treat None as "do not cache".
|
|
244
|
-
|
|
245
|
-
BUG-FIX (v3.6.4): Previously returned None for any response containing
|
|
246
|
-
tool_use blocks, which meant Claude Code responses were NEVER cached (Claude
|
|
247
|
-
Code always uses tools). Now handles both text AND tool_use content blocks:
|
|
248
|
-
- text blocks: accumulated via text_delta events
|
|
249
|
-
- tool_use blocks: accumulated via input_json_delta events, stored with
|
|
250
|
-
full {id, name, input} so _sse_from_cached_json can replay them correctly.
|
|
251
|
-
"""
|
|
252
|
-
# content_blocks[index] = {"type": "text", "text_parts": [...]} OR
|
|
253
|
-
# {"type": "tool_use", "id": "...", "name": "...", "input_parts": [...]}
|
|
254
|
-
content_blocks: dict[int, dict] = {}
|
|
255
|
-
message_id = ""
|
|
256
|
-
model = ""
|
|
257
|
-
role = "assistant"
|
|
258
|
-
input_tokens = 0
|
|
259
|
-
output_tokens = 0
|
|
260
|
-
stop_reason = "end_turn"
|
|
261
|
-
message_start_seen = False
|
|
262
|
-
message_stop_seen = False
|
|
263
|
-
|
|
264
|
-
current_event = ""
|
|
265
|
-
for raw_line in sse_bytes.decode("utf-8", errors="replace").split("\n"):
|
|
266
|
-
line = raw_line.rstrip("\r")
|
|
267
|
-
if line.startswith("event: "):
|
|
268
|
-
current_event = line[7:].strip()
|
|
269
|
-
elif line.startswith("data: "):
|
|
270
|
-
data_str = line[6:].strip()
|
|
271
|
-
if not data_str or data_str == "[DONE]":
|
|
272
|
-
continue
|
|
273
|
-
try:
|
|
274
|
-
data = json.loads(data_str)
|
|
275
|
-
except json.JSONDecodeError:
|
|
276
|
-
continue
|
|
277
|
-
|
|
278
|
-
if current_event == "message_start":
|
|
279
|
-
message_start_seen = True
|
|
280
|
-
msg = data.get("message", {})
|
|
281
|
-
message_id = msg.get("id", "")
|
|
282
|
-
model = msg.get("model", "")
|
|
283
|
-
role = msg.get("role", "assistant")
|
|
284
|
-
usage = msg.get("usage", {})
|
|
285
|
-
input_tokens = usage.get("input_tokens", 0)
|
|
286
|
-
|
|
287
|
-
elif current_event == "content_block_start":
|
|
288
|
-
idx = data.get("index", 0)
|
|
289
|
-
cb = data.get("content_block", {})
|
|
290
|
-
block_type = cb.get("type", "text")
|
|
291
|
-
if block_type == "tool_use":
|
|
292
|
-
content_blocks[idx] = {
|
|
293
|
-
"type": "tool_use",
|
|
294
|
-
"id": cb.get("id", ""),
|
|
295
|
-
"name": cb.get("name", ""),
|
|
296
|
-
"input_parts": [],
|
|
297
|
-
}
|
|
298
|
-
else:
|
|
299
|
-
content_blocks[idx] = {"type": "text", "text_parts": []}
|
|
300
|
-
|
|
301
|
-
elif current_event == "content_block_delta":
|
|
302
|
-
idx = data.get("index", 0)
|
|
303
|
-
delta = data.get("delta", {})
|
|
304
|
-
block = content_blocks.get(idx)
|
|
305
|
-
if block is None:
|
|
306
|
-
continue
|
|
307
|
-
delta_type = delta.get("type", "")
|
|
308
|
-
if delta_type == "text_delta":
|
|
309
|
-
block.setdefault("text_parts", []).append(delta.get("text", ""))
|
|
310
|
-
elif delta_type == "input_json_delta":
|
|
311
|
-
block.setdefault("input_parts", []).append(delta.get("partial_json", ""))
|
|
312
|
-
|
|
313
|
-
elif current_event == "message_delta":
|
|
314
|
-
usage2 = data.get("usage", {})
|
|
315
|
-
output_tokens = usage2.get("output_tokens", 0)
|
|
316
|
-
stop = data.get("delta", {})
|
|
317
|
-
stop_reason = stop.get("stop_reason", stop_reason) or stop_reason
|
|
318
|
-
|
|
319
|
-
elif current_event == "message_stop":
|
|
320
|
-
message_stop_seen = True
|
|
321
|
-
|
|
322
|
-
if not message_start_seen or not message_stop_seen:
|
|
323
|
-
return None
|
|
324
|
-
|
|
325
|
-
# Assemble content array — preserve block ordering by index
|
|
326
|
-
content: list[dict] = []
|
|
327
|
-
for idx in sorted(content_blocks.keys()):
|
|
328
|
-
block = content_blocks[idx]
|
|
329
|
-
if block["type"] == "tool_use":
|
|
330
|
-
input_json_str = "".join(block.get("input_parts", []))
|
|
331
|
-
try:
|
|
332
|
-
input_obj = json.loads(input_json_str) if input_json_str else {}
|
|
333
|
-
except json.JSONDecodeError:
|
|
334
|
-
input_obj = {"_raw": input_json_str}
|
|
335
|
-
content.append({
|
|
336
|
-
"type": "tool_use",
|
|
337
|
-
"id": block["id"],
|
|
338
|
-
"name": block["name"],
|
|
339
|
-
"input": input_obj,
|
|
340
|
-
})
|
|
341
|
-
else:
|
|
342
|
-
text = "".join(block.get("text_parts", []))
|
|
343
|
-
content.append({"type": "text", "text": text})
|
|
344
|
-
|
|
345
|
-
result = {
|
|
346
|
-
"id": message_id,
|
|
347
|
-
"type": "message",
|
|
348
|
-
"role": role,
|
|
349
|
-
"content": content,
|
|
350
|
-
"model": model,
|
|
351
|
-
"stop_reason": stop_reason,
|
|
352
|
-
"stop_sequence": None,
|
|
353
|
-
"usage": {
|
|
354
|
-
"input_tokens": input_tokens,
|
|
355
|
-
"output_tokens": output_tokens,
|
|
356
|
-
},
|
|
357
|
-
}
|
|
358
|
-
return json.dumps(result, separators=(",", ":")).encode("utf-8")
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
# ---------------------------------------------------------------------------
|
|
362
|
-
# HTTP helpers
|
|
363
|
-
# ---------------------------------------------------------------------------
|
|
364
|
-
|
|
365
|
-
async def _fail_open_forward(proxy: Any, request: Request, upstream_url: str) -> Response:
|
|
366
|
-
if proxy.http_client is None:
|
|
367
|
-
logger.error(
|
|
368
|
-
"fail_open_forward: http_client is None — startup() was not called. "
|
|
369
|
-
"Check daemon lifespan wiring."
|
|
370
|
-
)
|
|
371
|
-
return Response(
|
|
372
|
-
content=b'{"type":"error","error":{"type":"api_error",'
|
|
373
|
-
b'"message":"SLM proxy not started - lifespan wiring error"}}',
|
|
374
|
-
status_code=502,
|
|
375
|
-
media_type="application/json",
|
|
376
|
-
)
|
|
377
|
-
try:
|
|
378
|
-
body_bytes = await request.body()
|
|
379
|
-
fwd_headers = {
|
|
380
|
-
k: v for k, v in request.headers.items()
|
|
381
|
-
if k.lower() not in _HOP_BY_HOP
|
|
382
|
-
}
|
|
383
|
-
upstream_resp = await proxy.http_client.request(
|
|
384
|
-
method=request.method,
|
|
385
|
-
url=upstream_url,
|
|
386
|
-
headers=fwd_headers,
|
|
387
|
-
content=body_bytes,
|
|
388
|
-
)
|
|
389
|
-
return Response(
|
|
390
|
-
content=upstream_resp.content,
|
|
391
|
-
status_code=upstream_resp.status_code,
|
|
392
|
-
headers=_filter_response_headers(dict(upstream_resp.headers)),
|
|
393
|
-
)
|
|
394
|
-
except Exception as exc:
|
|
395
|
-
logger.error("fail_open_forward failed upstream=%s exc=%r", upstream_url, exc)
|
|
396
|
-
return Response(
|
|
397
|
-
content=b'{"type":"error","error":{"type":"api_error",'
|
|
398
|
-
b'"message":"SLM proxy unreachable - check upstream"}}',
|
|
399
|
-
status_code=502,
|
|
400
|
-
media_type="application/json",
|
|
401
|
-
)
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
async def _stream_forward(
|
|
405
|
-
proxy: Any,
|
|
406
|
-
request_id: str,
|
|
407
|
-
fwd_headers: dict,
|
|
408
|
-
body_bytes: bytes,
|
|
409
|
-
upstream_url: str,
|
|
410
|
-
) -> Response | StreamingResponse:
|
|
411
|
-
"""Simple passthrough streaming — no cache accumulation."""
|
|
412
|
-
if proxy.http_client is None:
|
|
413
|
-
logger.error(
|
|
414
|
-
"[%s] _stream_forward: http_client is None - startup() was not called. "
|
|
415
|
-
"Check daemon lifespan wiring.",
|
|
416
|
-
request_id,
|
|
417
|
-
)
|
|
418
|
-
return Response(
|
|
419
|
-
content=b'{"type":"error","error":{"type":"api_error",'
|
|
420
|
-
b'"message":"SLM proxy not started - lifespan wiring error"}}',
|
|
421
|
-
status_code=502,
|
|
422
|
-
media_type="application/json",
|
|
423
|
-
)
|
|
424
|
-
|
|
425
|
-
async def _generate() -> AsyncIterator[bytes]:
|
|
426
|
-
try:
|
|
427
|
-
async with proxy.http_client.stream(
|
|
428
|
-
"POST", upstream_url, content=body_bytes, headers=fwd_headers,
|
|
429
|
-
) as upstream_resp:
|
|
430
|
-
async for chunk in upstream_resp.aiter_bytes():
|
|
431
|
-
if chunk:
|
|
432
|
-
yield chunk
|
|
433
|
-
except httpx.RemoteProtocolError as exc:
|
|
434
|
-
logger.warning("[%s] upstream stream closed early: %r", request_id, exc)
|
|
435
|
-
yield (
|
|
436
|
-
b'event: error\ndata: {"type":"error","error":{'
|
|
437
|
-
b'"type":"api_error","message":"upstream stream closed"}}\n\n'
|
|
438
|
-
)
|
|
439
|
-
except Exception as exc:
|
|
440
|
-
logger.error("[%s] stream forward error: %r", request_id, exc)
|
|
441
|
-
yield (
|
|
442
|
-
b'event: error\ndata: {"type":"error","error":{'
|
|
443
|
-
b'"type":"api_error","message":"SLM proxy stream error"}}\n\n'
|
|
444
|
-
)
|
|
445
|
-
|
|
446
|
-
return StreamingResponse(
|
|
447
|
-
_generate(),
|
|
448
|
-
media_type="text/event-stream",
|
|
449
|
-
headers={
|
|
450
|
-
"Cache-Control": "no-cache",
|
|
451
|
-
"Connection": "keep-alive",
|
|
452
|
-
"X-Accel-Buffering": "no",
|
|
453
|
-
},
|
|
454
|
-
)
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
async def _stream_and_cache_forward(
|
|
458
|
-
proxy: Any,
|
|
459
|
-
request_id: str,
|
|
460
|
-
fwd_headers: dict,
|
|
461
|
-
body_bytes: bytes,
|
|
462
|
-
upstream_url: str,
|
|
463
|
-
on_complete: "Callable[[bytes], Any] | None" = None,
|
|
464
|
-
max_accumulate: int | None = None,
|
|
465
|
-
) -> Response | StreamingResponse:
|
|
466
|
-
"""Stream-forward with optional post-stream cache-store callback.
|
|
467
|
-
|
|
468
|
-
BUG-FIX (v3.6.3): Claude Code exclusively uses streaming. The old
|
|
469
|
-
_stream_forward never accumulated the response body, so the cache was
|
|
470
|
-
NEVER populated — savings were permanently 0.
|
|
471
|
-
|
|
472
|
-
This helper tees the stream: each chunk is yielded to the client AND
|
|
473
|
-
appended to an in-memory accumulator. After the LAST chunk (detected by
|
|
474
|
-
``message_stop`` in the SSE bytes), ``on_complete`` is awaited with the
|
|
475
|
-
full accumulated bytes. The caller converts those bytes to a JSON message
|
|
476
|
-
via ``_parse_sse_to_json`` and stores them in the cache.
|
|
477
|
-
|
|
478
|
-
on_complete is only called when:
|
|
479
|
-
- the accumulated bytes contain ``b"message_stop"`` (complete response),
|
|
480
|
-
- the response did NOT error mid-stream.
|
|
481
|
-
"""
|
|
482
|
-
if proxy.http_client is None:
|
|
483
|
-
logger.error(
|
|
484
|
-
"[%s] _stream_and_cache_forward: http_client is None.",
|
|
485
|
-
request_id,
|
|
486
|
-
)
|
|
487
|
-
return Response(
|
|
488
|
-
content=b'{"type":"error","error":{"type":"api_error",'
|
|
489
|
-
b'"message":"SLM proxy not started - lifespan wiring error"}}',
|
|
490
|
-
status_code=502,
|
|
491
|
-
media_type="application/json",
|
|
492
|
-
)
|
|
493
|
-
|
|
494
|
-
acc: list[bytes] = []
|
|
495
|
-
acc_bytes = 0
|
|
496
|
-
acc_capped = False
|
|
497
|
-
complete_called = False
|
|
498
|
-
|
|
499
|
-
async def _generate() -> AsyncIterator[bytes]:
|
|
500
|
-
nonlocal complete_called, acc_bytes, acc_capped
|
|
501
|
-
stream_error = False
|
|
502
|
-
try:
|
|
503
|
-
async with proxy.http_client.stream(
|
|
504
|
-
"POST", upstream_url, content=body_bytes, headers=fwd_headers,
|
|
505
|
-
) as upstream_resp:
|
|
506
|
-
async for chunk in upstream_resp.aiter_bytes():
|
|
507
|
-
if chunk:
|
|
508
|
-
# Always forward to the client; only bound what we hold
|
|
509
|
-
# in memory for the on_complete callback (CWE-400).
|
|
510
|
-
if max_accumulate is None or acc_bytes < max_accumulate:
|
|
511
|
-
acc.append(chunk)
|
|
512
|
-
acc_bytes += len(chunk)
|
|
513
|
-
elif not acc_capped:
|
|
514
|
-
acc_capped = True
|
|
515
|
-
logger.debug(
|
|
516
|
-
"[%s] stream accumulator capped at %d bytes",
|
|
517
|
-
request_id, max_accumulate,
|
|
518
|
-
)
|
|
519
|
-
yield chunk
|
|
520
|
-
except httpx.RemoteProtocolError as exc:
|
|
521
|
-
stream_error = True
|
|
522
|
-
logger.warning("[%s] upstream stream closed early: %r", request_id, exc)
|
|
523
|
-
yield (
|
|
524
|
-
b'event: error\ndata: {"type":"error","error":{'
|
|
525
|
-
b'"type":"api_error","message":"upstream stream closed"}}\n\n'
|
|
526
|
-
)
|
|
527
|
-
except Exception as exc:
|
|
528
|
-
stream_error = True
|
|
529
|
-
logger.error("[%s] stream forward error: %r", request_id, exc)
|
|
530
|
-
yield (
|
|
531
|
-
b'event: error\ndata: {"type":"error","error":{'
|
|
532
|
-
b'"type":"api_error","message":"SLM proxy stream error"}}\n\n'
|
|
533
|
-
)
|
|
534
|
-
finally:
|
|
535
|
-
# BUG-FIX (v3.6.4): Removed surface-specific sentinel check
|
|
536
|
-
# ("message_stop" / "[DONE]"). Completeness is now validated
|
|
537
|
-
# inside each parser (_parse_sse_to_json, _parse_openai_sse_to_json,
|
|
538
|
-
# _parse_gemini_sse_to_json) which return None for incomplete
|
|
539
|
-
# streams. This makes _stream_and_cache_forward universal: it
|
|
540
|
-
# calls on_complete whenever the stream ends without error and
|
|
541
|
-
# lets the parser decide whether to store. Gemini SSE has neither
|
|
542
|
-
# sentinel — streams end by connection close after the final chunk
|
|
543
|
-
# containing "finishReason".
|
|
544
|
-
_joined = b"".join(acc)
|
|
545
|
-
if on_complete and acc and not complete_called and not stream_error:
|
|
546
|
-
complete_called = True
|
|
547
|
-
try:
|
|
548
|
-
await on_complete(_joined)
|
|
549
|
-
except Exception as exc:
|
|
550
|
-
logger.warning(
|
|
551
|
-
"[%s] cache store callback raised (fail-open): %r",
|
|
552
|
-
request_id, exc,
|
|
553
|
-
)
|
|
554
|
-
|
|
555
|
-
return StreamingResponse(
|
|
556
|
-
_generate(),
|
|
557
|
-
media_type="text/event-stream",
|
|
558
|
-
headers={
|
|
559
|
-
"Cache-Control": "no-cache",
|
|
560
|
-
"Connection": "keep-alive",
|
|
561
|
-
"X-Accel-Buffering": "no",
|
|
562
|
-
},
|
|
563
|
-
)
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
async def capture_passthrough_forward(
|
|
567
|
-
proxy: Any,
|
|
568
|
-
request: Request,
|
|
569
|
-
*,
|
|
570
|
-
provider: str,
|
|
571
|
-
upstream_url: str,
|
|
572
|
-
allowed_headers: frozenset,
|
|
573
|
-
request_id: str,
|
|
574
|
-
model_hint: str = "",
|
|
575
|
-
sse_parser: "Callable[[bytes], bytes | None] | None" = None,
|
|
576
|
-
is_stream: bool = False,
|
|
577
|
-
) -> Response | StreamingResponse:
|
|
578
|
-
"""Shadow-capture passthrough (v3.6.10, plan §7).
|
|
579
|
-
|
|
580
|
-
Pure passthrough to upstream + record the exchange to the capture corpus.
|
|
581
|
-
NO cache, NO compression — capture mode observes only authentic traffic.
|
|
582
|
-
Fail-open: a capture or forward error degrades to a normal forward/error
|
|
583
|
-
response; the user's request is never blocked by capture.
|
|
584
|
-
"""
|
|
585
|
-
from superlocalmemory.optimize.proxy.capture import (
|
|
586
|
-
extract_usage,
|
|
587
|
-
record_exchange_async,
|
|
588
|
-
)
|
|
589
|
-
|
|
590
|
-
body_bytes = await request.body()
|
|
591
|
-
fwd_headers = _build_forward_headers(request, allowed_headers)
|
|
592
|
-
fwd_headers["content-length"] = str(len(body_bytes))
|
|
593
|
-
|
|
594
|
-
if is_stream:
|
|
595
|
-
async def _on_complete(acc: bytes) -> None:
|
|
596
|
-
parsed = sse_parser(acc) if sse_parser else None
|
|
597
|
-
payload = parsed if parsed is not None else acc
|
|
598
|
-
itok, otok, mdl = extract_usage(provider, parsed)
|
|
599
|
-
await record_exchange_async(
|
|
600
|
-
provider=provider,
|
|
601
|
-
model=mdl or model_hint,
|
|
602
|
-
request_body=body_bytes,
|
|
603
|
-
response_body=payload,
|
|
604
|
-
content_type="text/event-stream",
|
|
605
|
-
input_tokens=itok,
|
|
606
|
-
output_tokens=otok,
|
|
607
|
-
status_code=200,
|
|
608
|
-
stream=True,
|
|
609
|
-
)
|
|
610
|
-
|
|
611
|
-
# Bound the in-memory accumulator (CWE-400): the corpus only keeps the
|
|
612
|
-
# first 1 MB per side anyway, so cap accumulation there.
|
|
613
|
-
from superlocalmemory.optimize.proxy.capture import _MAX_CAPTURE_BODY_BYTES
|
|
614
|
-
return await _stream_and_cache_forward(
|
|
615
|
-
proxy, request_id, fwd_headers, body_bytes, upstream_url,
|
|
616
|
-
on_complete=_on_complete,
|
|
617
|
-
max_accumulate=_MAX_CAPTURE_BODY_BYTES,
|
|
618
|
-
)
|
|
619
|
-
|
|
620
|
-
if proxy.http_client is None:
|
|
621
|
-
return await _fail_open_forward(proxy, request, upstream_url)
|
|
622
|
-
try:
|
|
623
|
-
upstream_resp = await proxy.http_client.post(
|
|
624
|
-
upstream_url, content=body_bytes, headers=fwd_headers,
|
|
625
|
-
)
|
|
626
|
-
except Exception as exc:
|
|
627
|
-
logger.error("[%s] capture passthrough upstream error: %r", request_id, exc)
|
|
628
|
-
return await _fail_open_forward(proxy, request, upstream_url)
|
|
629
|
-
|
|
630
|
-
resp_bytes = upstream_resp.content
|
|
631
|
-
itok, otok, mdl = extract_usage(provider, resp_bytes)
|
|
632
|
-
await record_exchange_async(
|
|
633
|
-
provider=provider,
|
|
634
|
-
model=mdl or model_hint,
|
|
635
|
-
request_body=body_bytes,
|
|
636
|
-
response_body=resp_bytes,
|
|
637
|
-
content_type="application/json",
|
|
638
|
-
input_tokens=itok,
|
|
639
|
-
output_tokens=otok,
|
|
640
|
-
status_code=upstream_resp.status_code,
|
|
641
|
-
stream=False,
|
|
642
|
-
)
|
|
643
|
-
return Response(
|
|
644
|
-
content=resp_bytes,
|
|
645
|
-
status_code=upstream_resp.status_code,
|
|
646
|
-
media_type="application/json",
|
|
647
|
-
headers=_filter_response_headers(dict(upstream_resp.headers)),
|
|
648
|
-
)
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
async def _safe_cache_check(
|
|
652
|
-
hooks: HookChain,
|
|
653
|
-
ctx: ProxyRequest,
|
|
654
|
-
tenant_id: "str | None" = None,
|
|
655
|
-
) -> CachedResponse:
|
|
656
|
-
"""Invoke cache.check(); fail-open on error.
|
|
657
|
-
|
|
658
|
-
SECURITY (WP-D): tenant_id is forwarded to the CacheHook so that the
|
|
659
|
-
credential-derived namespace is used. None signals "skip caching" — the
|
|
660
|
-
cache hook must not collapse to a default tenant for unauthenticated
|
|
661
|
-
requests. When tenant_id is None, return an empty miss immediately.
|
|
662
|
-
|
|
663
|
-
Backward compat: a genuinely legacy hook (no tenant_id parameter and no
|
|
664
|
-
**kwargs) is called without the kwarg. A tenant-aware hook is NEVER
|
|
665
|
-
downgraded to the tenant-less path — see _accepts_tenant_id (Stage-9 R1).
|
|
666
|
-
"""
|
|
667
|
-
miss = CachedResponse(hit=False, data=None, cache_key="", ttl_seconds=0)
|
|
668
|
-
if tenant_id is None:
|
|
669
|
-
return miss
|
|
670
|
-
try:
|
|
671
|
-
if _accepts_tenant_id(hooks.cache.check):
|
|
672
|
-
result = hooks.cache.check(ctx, tenant_id=tenant_id)
|
|
673
|
-
else:
|
|
674
|
-
# Genuine legacy hook — no tenant_id support at all.
|
|
675
|
-
result = hooks.cache.check(ctx)
|
|
676
|
-
return result if result is not None else miss
|
|
677
|
-
except Exception as exc:
|
|
678
|
-
# SECURITY: a tenant-aware hook that errors must fail-open to a MISS,
|
|
679
|
-
# never be retried on the shared (tenant-less) namespace.
|
|
680
|
-
logger.warning("cache.check failed (fail-open miss): %s", exc)
|
|
681
|
-
return miss
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
async def _safe_cache_store(
|
|
685
|
-
hooks: HookChain,
|
|
686
|
-
ctx: ProxyRequest,
|
|
687
|
-
resp: ProviderResponse,
|
|
688
|
-
tenant_id: "str | None" = None,
|
|
689
|
-
) -> None:
|
|
690
|
-
"""Invoke cache.store(); fail-open on error.
|
|
691
|
-
|
|
692
|
-
SECURITY (WP-D): tenant_id is forwarded. None means skip (unauthenticated).
|
|
693
|
-
|
|
694
|
-
Backward compat: a genuinely legacy hook (no tenant_id parameter and no
|
|
695
|
-
**kwargs) is called without the kwarg. A tenant-aware hook is NEVER
|
|
696
|
-
downgraded to the tenant-less path — see _accepts_tenant_id (Stage-9 R1).
|
|
697
|
-
"""
|
|
698
|
-
if tenant_id is None:
|
|
699
|
-
return
|
|
700
|
-
try:
|
|
701
|
-
if _accepts_tenant_id(hooks.cache.store):
|
|
702
|
-
hooks.cache.store(ctx, resp, tenant_id=tenant_id)
|
|
703
|
-
else:
|
|
704
|
-
hooks.cache.store(ctx, resp)
|
|
705
|
-
except Exception as exc:
|
|
706
|
-
# SECURITY: never retry a tenant-aware hook without tenant_id.
|
|
707
|
-
logger.warning("cache.store failed (fail-open): %s", exc)
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
async def _safe_cache_hit_callbacks(
|
|
711
|
-
hooks: HookChain,
|
|
712
|
-
ctx: ProxyRequest,
|
|
713
|
-
response_bytes: bytes,
|
|
714
|
-
tokens_saved: int,
|
|
715
|
-
) -> None:
|
|
716
|
-
try:
|
|
717
|
-
hooks.cache.on_hit(ctx, response_bytes, tokens_saved)
|
|
718
|
-
except Exception as exc:
|
|
719
|
-
logger.warning("cache.on_hit failed (fail-open): %s", exc)
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
async def _safe_compress(hooks: HookChain, ctx: ProxyRequest) -> ProxyRequest:
|
|
723
|
-
try:
|
|
724
|
-
result: ProxyRequest = hooks.compress.compress(ctx)
|
|
725
|
-
except Exception as exc:
|
|
726
|
-
logger.warning("compress.compress failed (fail-open): %s", exc)
|
|
727
|
-
return ctx
|
|
728
|
-
# on_compress is fired internally by CompressRouter.compress() with
|
|
729
|
-
# actual token counts — no duplicate fire here.
|
|
730
|
-
return result
|