superlocalmemory 3.6.22 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/README.md +275 -72
- package/bin/slm-npm +43 -89
- package/docs/pi-dev-integration.md +43 -0
- package/ide/configs/antigravity-mcp.json +2 -2
- package/ide/configs/chatgpt-desktop-mcp.json +1 -1
- package/ide/configs/claude-desktop-mcp.json +2 -2
- package/ide/configs/windsurf-mcp.json +2 -2
- package/ide/hooks/context-hook.js +6 -2
- package/ide/hooks/post-recall-hook.js +7 -3
- package/ide/hooks/tool-event-hook.sh +2 -1
- package/package.json +19 -10
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/_GENERATED.md +1 -1
- package/plugin/agents/slm-memory-advisor.md +1 -1
- package/plugin/requirements.txt +1 -1
- package/plugin/skills/slm-session/SKILL.md +1 -1
- package/plugin-src/rules/AGENTS.md +1 -1
- package/pyproject.toml +40 -8
- package/scripts/postinstall-interactive.js +17 -94
- package/scripts/postinstall.js +185 -258
- package/scripts/preuninstall.js +9 -50
- package/src/superlocalmemory/__init__.py +2 -2
- package/src/superlocalmemory/attribution/mathematical_dna.py +1 -1
- package/src/superlocalmemory/attribution/signer.py +34 -19
- package/src/superlocalmemory/attribution/watermark.py +1 -1
- package/src/superlocalmemory/cli/_lazy_init.py +3 -5
- package/src/superlocalmemory/cli/commands.py +490 -195
- package/src/superlocalmemory/cli/context_commands.py +5 -4
- package/src/superlocalmemory/cli/daemon.py +282 -187
- package/src/superlocalmemory/cli/db_migrate.py +3 -1
- package/src/superlocalmemory/cli/diagnostics_cmd.py +28 -0
- package/src/superlocalmemory/cli/evidence_cmd.py +103 -0
- package/src/superlocalmemory/cli/ingest_cmd.py +7 -3
- package/src/superlocalmemory/cli/main.py +128 -31
- package/src/superlocalmemory/cli/pending_store.py +54 -38
- package/src/superlocalmemory/cli/scale_engine_cmd.py +37 -0
- package/src/superlocalmemory/cli/service_installer.py +57 -52
- package/src/superlocalmemory/cli/setup_wizard.py +142 -88
- package/src/superlocalmemory/cli/version_banner.py +2 -1
- package/src/superlocalmemory/code_graph/config.py +3 -1
- package/src/superlocalmemory/core/backend_orchestrator.py +81 -21
- package/src/superlocalmemory/core/config.py +65 -20
- package/src/superlocalmemory/core/consolidation_engine.py +9 -7
- package/src/superlocalmemory/core/context_cache.py +56 -8
- package/src/superlocalmemory/core/derivation_lineage.py +246 -0
- package/src/superlocalmemory/core/embedding_worker.py +32 -20
- package/src/superlocalmemory/core/embeddings.py +54 -18
- package/src/superlocalmemory/core/engine.py +150 -104
- package/src/superlocalmemory/core/engine_ingestion.py +513 -0
- package/src/superlocalmemory/core/engine_wiring.py +2 -0
- package/src/superlocalmemory/core/evidence_bundle.py +526 -0
- package/src/superlocalmemory/core/fact_consolidator.py +5 -11
- package/src/superlocalmemory/core/graph_analyzer.py +2 -2
- package/src/superlocalmemory/core/health_monitor.py +4 -2
- package/src/superlocalmemory/core/ingestion_command.py +636 -0
- package/src/superlocalmemory/core/injection.py +69 -18
- package/src/superlocalmemory/core/lifecycle_state.py +153 -0
- package/src/superlocalmemory/core/maintenance.py +23 -22
- package/src/superlocalmemory/core/maintenance_scheduler.py +51 -35
- package/src/superlocalmemory/core/mutations.py +143 -0
- package/src/superlocalmemory/core/platform_utils.py +7 -4
- package/src/superlocalmemory/core/ram_lock.py +16 -5
- package/src/superlocalmemory/core/rate_limit.py +1 -1
- package/src/superlocalmemory/core/recall_pipeline.py +60 -101
- package/src/superlocalmemory/core/recall_worker.py +76 -59
- package/src/superlocalmemory/core/registry.py +1 -1
- package/src/superlocalmemory/core/scale_engine.py +293 -0
- package/src/superlocalmemory/core/score_contract.py +62 -0
- package/src/superlocalmemory/core/security_primitives.py +3 -1
- package/src/superlocalmemory/core/slm_disabled.py +3 -5
- package/src/superlocalmemory/core/store_pipeline.py +172 -40
- package/src/superlocalmemory/core/tier_manager.py +32 -20
- package/src/superlocalmemory/core/worker_pool.py +13 -4
- package/src/superlocalmemory/dynamics/activation_guided_quantization.py +1 -1
- package/src/superlocalmemory/dynamics/eap_scheduler.py +10 -3
- package/src/superlocalmemory/dynamics/ebbinghaus_langevin_coupling.py +1 -1
- package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +1 -1
- package/src/superlocalmemory/encoding/auto_linker.py +1 -1
- package/src/superlocalmemory/encoding/cognitive_consolidator.py +7 -16
- package/src/superlocalmemory/encoding/consolidator.py +22 -5
- package/src/superlocalmemory/encoding/fact_extractor.py +1 -1
- package/src/superlocalmemory/encoding/foresight.py +2 -0
- package/src/superlocalmemory/encoding/graph_builder.py +1 -1
- package/src/superlocalmemory/encoding/temporal_parser.py +2 -0
- package/src/superlocalmemory/evaluation/__init__.py +13 -0
- package/src/superlocalmemory/evaluation/calibration.py +308 -0
- package/src/superlocalmemory/evolution/skill_evolver.py +2 -1
- package/src/superlocalmemory/graph/cozo_backend.py +256 -23
- package/src/superlocalmemory/hooks/_outcome_common.py +21 -11
- package/src/superlocalmemory/hooks/antigravity_adapter.py +10 -31
- package/src/superlocalmemory/hooks/auto_invoker.py +25 -27
- package/src/superlocalmemory/hooks/auto_recall.py +31 -6
- package/src/superlocalmemory/hooks/auto_recall_hook.py +13 -33
- package/src/superlocalmemory/hooks/before_web_hook.py +9 -7
- package/src/superlocalmemory/hooks/claude_code_hooks.py +126 -39
- package/src/superlocalmemory/hooks/codex_assets.py +59 -0
- package/src/superlocalmemory/hooks/codex_hooks.py +186 -0
- package/src/superlocalmemory/hooks/context_payload.py +1 -1
- package/src/superlocalmemory/hooks/copilot_adapter.py +9 -24
- package/src/superlocalmemory/hooks/cursor_adapter.py +10 -32
- package/src/superlocalmemory/hooks/hook_daemon.py +4 -2
- package/src/superlocalmemory/hooks/hook_handlers.py +241 -55
- package/src/superlocalmemory/hooks/memory_protocol.py +5 -3
- package/src/superlocalmemory/hooks/post_tool_async_hook.py +4 -2
- package/src/superlocalmemory/hooks/session_registry.py +15 -8
- package/src/superlocalmemory/hooks/stop_outcome_hook.py +10 -6
- package/src/superlocalmemory/hooks/topic_shift_hook.py +42 -12
- package/src/superlocalmemory/hooks/user_prompt_hook.py +9 -14
- package/src/superlocalmemory/hooks/user_prompt_rehash_hook.py +19 -11
- package/src/superlocalmemory/infra/auth_middleware.py +38 -5
- package/src/superlocalmemory/infra/backup.py +7 -5
- package/src/superlocalmemory/infra/cloud_backup.py +18 -8
- package/src/superlocalmemory/infra/daemon_identity.py +248 -0
- package/src/superlocalmemory/infra/data_root.py +199 -0
- package/src/superlocalmemory/infra/event_bus.py +3 -1
- package/src/superlocalmemory/infra/local_diagnostics.py +327 -0
- package/src/superlocalmemory/infra/process_reaper.py +23 -0
- package/src/superlocalmemory/ingestion/adapter_manager.py +27 -9
- package/src/superlocalmemory/ingestion/base_adapter.py +25 -31
- package/src/superlocalmemory/ingestion/calendar_adapter.py +13 -4
- package/src/superlocalmemory/ingestion/credentials.py +14 -7
- package/src/superlocalmemory/ingestion/gmail_adapter.py +13 -4
- package/src/superlocalmemory/ingestion/transcript_adapter.py +7 -2
- package/src/superlocalmemory/learning/consolidation_quantization_worker.py +1 -1
- package/src/superlocalmemory/learning/ensemble.py +11 -0
- package/src/superlocalmemory/learning/entity_compiler.py +1 -1
- package/src/superlocalmemory/learning/feedback.py +1 -1
- package/src/superlocalmemory/learning/forgetting_scheduler.py +12 -7
- package/src/superlocalmemory/learning/quantization_scheduler.py +1 -1
- package/src/superlocalmemory/learning/ranker.py +4 -1
- package/src/superlocalmemory/learning/source_quality.py +1 -1
- package/src/superlocalmemory/learning/trigram_index.py +3 -2
- package/src/superlocalmemory/llm/backbone.py +13 -8
- package/src/superlocalmemory/math/ebbinghaus.py +1 -1
- package/src/superlocalmemory/math/fisher.py +1 -1
- package/src/superlocalmemory/math/fisher_quantized.py +1 -1
- package/src/superlocalmemory/math/hopfield.py +1 -1
- package/src/superlocalmemory/math/langevin.py +1 -1
- package/src/superlocalmemory/math/polar_quant.py +3 -4
- package/src/superlocalmemory/math/qjl.py +1 -1
- package/src/superlocalmemory/math/sheaf.py +1 -1
- package/src/superlocalmemory/math/turbo_quant.py +3 -2
- package/src/superlocalmemory/mcp/_daemon_proxy.py +12 -11
- package/src/superlocalmemory/mcp/_pool_adapter.py +27 -0
- package/src/superlocalmemory/mcp/http_transport.py +53 -0
- package/src/superlocalmemory/mcp/server.py +39 -13
- package/src/superlocalmemory/mcp/shared.py +69 -3
- package/src/superlocalmemory/mcp/tools_active.py +141 -31
- package/src/superlocalmemory/mcp/tools_core.py +128 -29
- package/src/superlocalmemory/mcp/tools_evolution.py +5 -7
- package/src/superlocalmemory/mcp/tools_learning.py +42 -2
- package/src/superlocalmemory/mcp/tools_mesh.py +7 -23
- package/src/superlocalmemory/mcp/tools_optimize.py +8 -1
- package/src/superlocalmemory/mcp/tools_v28.py +23 -2
- package/src/superlocalmemory/mcp/tools_v3.py +26 -1
- package/src/superlocalmemory/mcp/tools_v33.py +56 -17
- package/src/superlocalmemory/mesh/broker.py +2 -0
- package/src/superlocalmemory/mesh/remote_sync.py +50 -12
- package/src/superlocalmemory/optimize/cache/manager.py +77 -1
- package/src/superlocalmemory/optimize/cache/semantic.py +23 -3
- package/src/superlocalmemory/optimize/compress/ccr.py +4 -0
- package/src/superlocalmemory/optimize/compress/router.py +6 -1
- package/src/superlocalmemory/optimize/config/__init__.py +5 -0
- package/src/superlocalmemory/optimize/config/store.py +6 -4
- package/src/superlocalmemory/optimize/proxy/_helpers.py +15 -5
- package/src/superlocalmemory/optimize/proxy/capture.py +3 -2
- package/src/superlocalmemory/optimize/proxy/server.py +2 -2
- package/src/superlocalmemory/optimize/storage/db.py +14 -13
- package/src/superlocalmemory/retrieval/agentic.py +1 -1
- package/src/superlocalmemory/retrieval/ann_index.py +1 -1
- package/src/superlocalmemory/retrieval/bm25_channel.py +35 -11
- package/src/superlocalmemory/retrieval/bridge_discovery.py +73 -8
- package/src/superlocalmemory/retrieval/engine.py +169 -79
- package/src/superlocalmemory/retrieval/entity_channel.py +289 -67
- package/src/superlocalmemory/retrieval/forgetting_filter.py +1 -1
- package/src/superlocalmemory/retrieval/fusion.py +1 -1
- package/src/superlocalmemory/retrieval/hopfield_channel.py +118 -30
- package/src/superlocalmemory/retrieval/profile_channel.py +1 -1
- package/src/superlocalmemory/retrieval/quantization_aware_search.py +16 -10
- package/src/superlocalmemory/retrieval/reranker.py +56 -20
- package/src/superlocalmemory/retrieval/scope_policy.py +85 -0
- package/src/superlocalmemory/retrieval/semantic_channel.py +122 -14
- package/src/superlocalmemory/retrieval/spreading_activation.py +141 -25
- package/src/superlocalmemory/retrieval/strategy.py +1 -1
- package/src/superlocalmemory/retrieval/temporal_channel.py +30 -15
- package/src/superlocalmemory/retrieval/vector_store.py +1 -1
- package/src/superlocalmemory/server/api.py +10 -7
- package/src/superlocalmemory/server/bandit_loops.py +4 -2
- package/src/superlocalmemory/server/recall_serializer.py +24 -0
- package/src/superlocalmemory/server/route_mutations.py +84 -0
- package/src/superlocalmemory/server/routes/agents.py +8 -6
- package/src/superlocalmemory/server/routes/brain.py +14 -12
- package/src/superlocalmemory/server/routes/chat.py +29 -12
- package/src/superlocalmemory/server/routes/data_io.py +55 -24
- package/src/superlocalmemory/server/routes/helpers.py +29 -4
- package/src/superlocalmemory/server/routes/ingest.py +53 -36
- package/src/superlocalmemory/server/routes/memories.py +104 -43
- package/src/superlocalmemory/server/routes/mesh.py +31 -0
- package/src/superlocalmemory/server/routes/profiles.py +26 -4
- package/src/superlocalmemory/server/routes/tiers.py +43 -11
- package/src/superlocalmemory/server/routes/timeline.py +5 -1
- package/src/superlocalmemory/server/routes/v3_api.py +76 -21
- package/src/superlocalmemory/server/security_middleware.py +1 -1
- package/src/superlocalmemory/server/ui.py +6 -3
- package/src/superlocalmemory/server/unified_daemon.py +680 -293
- package/src/superlocalmemory/server/write_identity.py +147 -0
- package/src/superlocalmemory/storage/access_log.py +4 -3
- package/src/superlocalmemory/storage/database.py +118 -25
- package/src/superlocalmemory/storage/migration_runner.py +84 -1
- package/src/superlocalmemory/storage/migration_v33.py +1 -1
- package/src/superlocalmemory/storage/migrations/M002_model_state_history.py +6 -60
- package/src/superlocalmemory/storage/migrations/M018_ingestion_operations.py +120 -0
- package/src/superlocalmemory/storage/migrations/M019_derivation_lineage.py +54 -0
- package/src/superlocalmemory/storage/migrations/M020_model_state_integrity.py +52 -0
- package/src/superlocalmemory/storage/migrations/__init__.py +5 -0
- package/src/superlocalmemory/storage/models.py +16 -0
- package/src/superlocalmemory/storage/quantized_store.py +20 -3
- package/src/superlocalmemory/storage/v2_migrator.py +5 -3
- package/src/superlocalmemory/ui/favicon.svg +5 -0
- package/src/superlocalmemory/ui/index.html +1 -0
- package/src/superlocalmemory/ui/js/compliance.js +1 -1
- package/src/superlocalmemory/ui/js/core.js +49 -8
- package/src/superlocalmemory/ui/js/dashboard.js +23 -2
- package/src/superlocalmemory/ui/js/feedback.js +1 -1
- package/src/superlocalmemory/ui/js/graph-filters.js +1 -1
- package/src/superlocalmemory/ui/js/graph-ui.js +1 -1
- package/src/superlocalmemory/ui/js/lifecycle.js +1 -1
- package/src/superlocalmemory/ui/js/ng-mesh.js +15 -49
- package/src/superlocalmemory/ui/js/settings.js +4 -2
- package/src/superlocalmemory/vector/lancedb_backend.py +57 -9
- package/bin/slm +0 -59
- package/bin/slm.bat +0 -77
- package/bin/slm.cmd +0 -5
- package/ide/integrations/langchain/README.md +0 -106
- package/ide/integrations/langchain/langchain_superlocalmemory/__init__.py +0 -9
- package/ide/integrations/langchain/langchain_superlocalmemory/chat_message_history.py +0 -201
- package/ide/integrations/langchain/pyproject.toml +0 -38
- package/ide/integrations/langchain/tests/__init__.py +0 -3
- package/ide/integrations/langchain/tests/test_chat_message_history.py +0 -215
- package/ide/integrations/langchain/tests/test_security.py +0 -117
- package/ide/integrations/llamaindex/README.md +0 -81
- package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/__init__.py +0 -9
- package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/base.py +0 -316
- package/ide/integrations/llamaindex/pyproject.toml +0 -43
- package/ide/integrations/llamaindex/tests/__init__.py +0 -3
- package/ide/integrations/llamaindex/tests/test_chat_store.py +0 -294
- package/ide/integrations/llamaindex/tests/test_security.py +0 -241
- package/plugin-src/.mcp.json +0 -12
- package/plugin-src/agents/slm-memory-advisor.md +0 -44
- package/plugin-src/agents/slm-optimize-advisor.md +0 -38
- package/plugin-src/hooks/.gitkeep +0 -0
- package/plugin-src/hooks/hooks.json +0 -23
- package/plugin-src/manifest.json +0 -25
- package/plugin-src/requirements.txt +0 -1
- package/plugin-src/rules/CLAUDE.md.fragment +0 -44
- package/plugin-src/scripts/ensure-venv.bat +0 -122
- package/plugin-src/scripts/ensure-venv.sh +0 -105
- package/plugin-src/scripts/slm-launch +0 -15
- package/plugin-src/scripts/slm-launch.bat +0 -17
- package/plugin-src/settings.json +0 -16
- package/plugin-src/skills/slm-cache/SKILL.md +0 -140
- package/plugin-src/skills/slm-compress/SKILL.md +0 -143
- package/plugin-src/skills/slm-graph/SKILL.md +0 -300
- package/plugin-src/skills/slm-recall/SKILL.md +0 -204
- package/plugin-src/skills/slm-remember/SKILL.md +0 -194
- package/plugin-src/skills/slm-session/SKILL.md +0 -207
- package/plugin-src/skills/slm-status/SKILL.md +0 -149
- package/scripts/__tests__/build-plugin.test.mjs +0 -613
- package/scripts/_savings_math.py +0 -270
- package/scripts/build-dmg.sh +0 -417
- package/scripts/build-plugin.js +0 -742
- package/scripts/build-slm-hook.ps1 +0 -40
- package/scripts/build-slm-hook.sh +0 -45
- package/scripts/build_entry.py +0 -452
- package/scripts/ci/stage5b_gate.sh +0 -50
- package/scripts/dogfood_savings.py +0 -490
- package/scripts/generate-thumbnails.py +0 -218
- package/scripts/install-skills.ps1 +0 -4
- package/scripts/install-skills.sh +0 -5
- package/scripts/install.ps1 +0 -701
- package/scripts/install.sh +0 -1015
- package/scripts/postinstall_binary.js +0 -287
- package/scripts/prepack.js +0 -33
- package/scripts/release_manifest.py +0 -273
- package/scripts/slm-hook.spec +0 -56
- package/scripts/start-dashboard.ps1 +0 -52
- package/scripts/start-dashboard.sh +0 -41
- package/scripts/sync-wiki.ps1 +0 -127
- package/scripts/sync-wiki.sh +0 -82
- package/scripts/test-dmg.sh +0 -161
- package/scripts/test-npm-package.ps1 +0 -252
- package/scripts/test-npm-package.sh +0 -207
- package/scripts/verify-install.ps1 +0 -294
- package/scripts/verify-install.sh +0 -266
- package/scripts/verify-v27.ps1 +0 -301
- package/scripts/verify-v27.sh +0 -233
- package/src/superlocalmemory.egg-info/PKG-INFO +0 -513
- package/src/superlocalmemory.egg-info/SOURCES.txt +0 -529
- package/src/superlocalmemory.egg-info/dependency_links.txt +0 -1
- package/src/superlocalmemory.egg-info/entry_points.txt +0 -2
- package/src/superlocalmemory.egg-info/requires.txt +0 -71
- package/src/superlocalmemory.egg-info/top_level.txt +0 -1
|
@@ -17,15 +17,14 @@ Part of Qualixar | Author: Varun Pratap Bhardwaj
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
import logging
|
|
20
|
-
from pathlib import Path
|
|
21
20
|
from typing import Callable
|
|
22
21
|
|
|
23
22
|
from mcp.types import ToolAnnotations
|
|
24
23
|
|
|
25
24
|
logger = logging.getLogger(__name__)
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
from superlocalmemory.infra.data_root import state_path
|
|
27
|
+
from superlocalmemory.mcp.shared import authorize_mcp_mutation
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
def _try_daemon_post(path: str, body: dict, timeout_s: float = 60.0) -> dict | None:
|
|
@@ -62,7 +61,7 @@ def _emit_event(event_type: str, payload: dict | None = None,
|
|
|
62
61
|
"""Emit an event to the EventBus (best-effort, never raises)."""
|
|
63
62
|
try:
|
|
64
63
|
from superlocalmemory.infra.event_bus import EventBus
|
|
65
|
-
bus = EventBus.get_instance(str(
|
|
64
|
+
bus = EventBus.get_instance(str(state_path("memory.db")))
|
|
66
65
|
bus.emit(event_type, payload=payload, source_agent=source_agent,
|
|
67
66
|
source_protocol="mcp")
|
|
68
67
|
except Exception:
|
|
@@ -121,14 +120,22 @@ def register_v33_tools(server, get_engine: Callable) -> None:
|
|
|
121
120
|
total += int(r["cnt"])
|
|
122
121
|
result = {"total": total, "transitions": 0, "dry_run_zones": zones}
|
|
123
122
|
else:
|
|
123
|
+
authorization = authorize_mcp_mutation(
|
|
124
|
+
engine,
|
|
125
|
+
"delete",
|
|
126
|
+
mutation_source="mcp-forgetting-cycle",
|
|
127
|
+
profile_id=pid,
|
|
128
|
+
)
|
|
124
129
|
result = scheduler.run_decay_cycle(pid, force=True)
|
|
130
|
+
authorization.complete()
|
|
125
131
|
|
|
126
|
-
|
|
127
|
-
"
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
+
if not dry_run:
|
|
133
|
+
_emit_event("forgetting.cycle_complete", {
|
|
134
|
+
"profile_id": pid,
|
|
135
|
+
"dry_run": False,
|
|
136
|
+
"total": result.get("total", 0),
|
|
137
|
+
"transitions": result.get("transitions", 0),
|
|
138
|
+
})
|
|
132
139
|
|
|
133
140
|
return {"success": True, "dry_run": dry_run, **result}
|
|
134
141
|
|
|
@@ -183,15 +190,23 @@ def register_v33_tools(server, get_engine: Callable) -> None:
|
|
|
183
190
|
facts = engine._db.get_all_facts(pid)
|
|
184
191
|
result = {"total": len(facts), "would_quantize": 0, "dry_run": True}
|
|
185
192
|
else:
|
|
193
|
+
authorization = authorize_mcp_mutation(
|
|
194
|
+
engine,
|
|
195
|
+
"update",
|
|
196
|
+
mutation_source="mcp-quantization-cycle",
|
|
197
|
+
profile_id=pid,
|
|
198
|
+
)
|
|
186
199
|
result = scheduler.run_eap_cycle(pid)
|
|
200
|
+
authorization.complete()
|
|
187
201
|
|
|
188
|
-
|
|
189
|
-
"
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
202
|
+
if not dry_run:
|
|
203
|
+
_emit_event("eap.cycle_complete", {
|
|
204
|
+
"profile_id": pid,
|
|
205
|
+
"dry_run": False,
|
|
206
|
+
"total": result.get("total", 0),
|
|
207
|
+
"downgrades": result.get("downgrades", 0),
|
|
208
|
+
"upgrades": result.get("upgrades", 0),
|
|
209
|
+
})
|
|
195
210
|
|
|
196
211
|
return {"success": True, "dry_run": dry_run, **result}
|
|
197
212
|
|
|
@@ -245,8 +260,15 @@ def register_v33_tools(server, get_engine: Callable) -> None:
|
|
|
245
260
|
CognitiveConsolidator,
|
|
246
261
|
)
|
|
247
262
|
|
|
263
|
+
authorization = authorize_mcp_mutation(
|
|
264
|
+
engine,
|
|
265
|
+
"update",
|
|
266
|
+
mutation_source="mcp-cognitive-consolidation",
|
|
267
|
+
profile_id=pid,
|
|
268
|
+
)
|
|
248
269
|
consolidator = CognitiveConsolidator(db=engine._db)
|
|
249
270
|
result = consolidator.run_pipeline(pid)
|
|
271
|
+
authorization.complete()
|
|
250
272
|
|
|
251
273
|
_emit_event("ccq.consolidation_complete", {
|
|
252
274
|
"profile_id": pid,
|
|
@@ -338,6 +360,14 @@ def register_v33_tools(server, get_engine: Callable) -> None:
|
|
|
338
360
|
dry_run: If True, report orphans but don't kill them.
|
|
339
361
|
"""
|
|
340
362
|
try:
|
|
363
|
+
engine = get_engine()
|
|
364
|
+
authorization = None
|
|
365
|
+
if not dry_run:
|
|
366
|
+
authorization = authorize_mcp_mutation(
|
|
367
|
+
engine,
|
|
368
|
+
"delete",
|
|
369
|
+
mutation_source="mcp-process-reaper",
|
|
370
|
+
)
|
|
341
371
|
from superlocalmemory.infra.process_reaper import (
|
|
342
372
|
cleanup_all_orphans,
|
|
343
373
|
ReaperConfig,
|
|
@@ -345,6 +375,8 @@ def register_v33_tools(server, get_engine: Callable) -> None:
|
|
|
345
375
|
|
|
346
376
|
config = ReaperConfig()
|
|
347
377
|
result = cleanup_all_orphans(config, dry_run=dry_run)
|
|
378
|
+
if authorization is not None:
|
|
379
|
+
authorization.complete()
|
|
348
380
|
|
|
349
381
|
return {
|
|
350
382
|
"success": True,
|
|
@@ -446,6 +478,12 @@ def register_v33_tools(server, get_engine: Callable) -> None:
|
|
|
446
478
|
daemon_result["via"] = "daemon"
|
|
447
479
|
return daemon_result
|
|
448
480
|
|
|
481
|
+
authorization = authorize_mcp_mutation(
|
|
482
|
+
engine,
|
|
483
|
+
"update",
|
|
484
|
+
mutation_source="mcp-maintenance-cycle",
|
|
485
|
+
profile_id=pid,
|
|
486
|
+
)
|
|
449
487
|
results = {}
|
|
450
488
|
|
|
451
489
|
# 1. Langevin dynamics step (lifecycle evolution)
|
|
@@ -476,6 +514,7 @@ def register_v33_tools(server, get_engine: Callable) -> None:
|
|
|
476
514
|
except Exception as exc:
|
|
477
515
|
results["behavioral"] = {"error": str(exc)}
|
|
478
516
|
|
|
517
|
+
authorization.complete()
|
|
479
518
|
return {"success": True, "profile": pid, **results}
|
|
480
519
|
|
|
481
520
|
except Exception as exc:
|
|
@@ -301,6 +301,7 @@ class MeshBroker:
|
|
|
301
301
|
"FROM mesh_messages m "
|
|
302
302
|
"LEFT JOIN mesh_reads r ON m.id = r.message_id AND r.peer_id = ? "
|
|
303
303
|
"WHERE m.target_type='broadcast' AND m.from_peer != ? "
|
|
304
|
+
"AND r.peer_id IS NULL "
|
|
304
305
|
"AND (m.expires_at IS NULL OR m.expires_at > ?) "
|
|
305
306
|
"ORDER BY m.created_at DESC LIMIT 50",
|
|
306
307
|
(peer_id, peer_id, now),
|
|
@@ -316,6 +317,7 @@ class MeshBroker:
|
|
|
316
317
|
"FROM mesh_messages m "
|
|
317
318
|
"LEFT JOIN mesh_reads r ON m.id = r.message_id AND r.peer_id = ? "
|
|
318
319
|
"WHERE m.target_type='project' AND m.project_path=? AND m.from_peer != ? "
|
|
320
|
+
"AND r.peer_id IS NULL "
|
|
319
321
|
"AND (m.expires_at IS NULL OR m.expires_at > ?) "
|
|
320
322
|
"ORDER BY m.created_at DESC LIMIT 50",
|
|
321
323
|
(peer_id, project_path, peer_id, now),
|
|
@@ -21,12 +21,52 @@ import logging
|
|
|
21
21
|
import os
|
|
22
22
|
import threading
|
|
23
23
|
import time
|
|
24
|
+
import ipaddress
|
|
24
25
|
from typing import Any
|
|
25
26
|
|
|
26
27
|
import httpx
|
|
27
28
|
|
|
28
29
|
logger = logging.getLogger("superlocalmemory.mesh.remote_sync")
|
|
29
30
|
|
|
31
|
+
|
|
32
|
+
def _service_ip_addresses(info: Any) -> list[str]:
|
|
33
|
+
"""Return validated textual IPs from current and older Zeroconf APIs."""
|
|
34
|
+
candidates: list[Any] = []
|
|
35
|
+
parsed = getattr(info, "parsed_addresses", None)
|
|
36
|
+
if callable(parsed):
|
|
37
|
+
try:
|
|
38
|
+
candidates.extend(parsed())
|
|
39
|
+
except (OSError, TypeError, ValueError):
|
|
40
|
+
pass
|
|
41
|
+
candidates.extend(getattr(info, "addresses", None) or [])
|
|
42
|
+
|
|
43
|
+
addresses: list[str] = []
|
|
44
|
+
for candidate in candidates:
|
|
45
|
+
try:
|
|
46
|
+
address = ipaddress.ip_address(candidate)
|
|
47
|
+
except (TypeError, ValueError):
|
|
48
|
+
continue
|
|
49
|
+
# An mDNS peer must name a routable endpoint, never a wildcard or
|
|
50
|
+
# multicast destination. Authentication is still enforced by mesh.
|
|
51
|
+
if address.is_unspecified or address.is_multicast:
|
|
52
|
+
continue
|
|
53
|
+
rendered = str(address)
|
|
54
|
+
if rendered not in addresses:
|
|
55
|
+
addresses.append(rendered)
|
|
56
|
+
return addresses
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _peer_url(host: str, port: int) -> str:
|
|
60
|
+
"""Format an IP literal safely for an HTTP authority."""
|
|
61
|
+
address = ipaddress.ip_address(host)
|
|
62
|
+
rendered = str(address)
|
|
63
|
+
if address.version == 6:
|
|
64
|
+
# RFC 6874 requires a percent sign in an IPv6 zone identifier to be
|
|
65
|
+
# escaped when the literal appears inside a URI authority.
|
|
66
|
+
rendered = rendered.replace("%", "%25")
|
|
67
|
+
rendered = f"[{rendered}]"
|
|
68
|
+
return f"http://{rendered}:{int(port)}"
|
|
69
|
+
|
|
30
70
|
# Optional zeroconf for mDNS discovery
|
|
31
71
|
try:
|
|
32
72
|
from zeroconf import ServiceBrowser, ServiceInfo, Zeroconf
|
|
@@ -236,17 +276,15 @@ class RemoteSyncClient:
|
|
|
236
276
|
if not ZEROCONF_AVAILABLE:
|
|
237
277
|
return
|
|
238
278
|
info = zeroconf.get_service_info(service_type, name)
|
|
239
|
-
if info
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
)
|
|
249
|
-
return
|
|
279
|
+
if info:
|
|
280
|
+
for addr in _service_ip_addresses(info):
|
|
281
|
+
port = info.port or 8765
|
|
282
|
+
peer_url = _peer_url(addr, port)
|
|
283
|
+
self._update_peer_url(addr, port)
|
|
284
|
+
logger.info(
|
|
285
|
+
"RemoteSyncClient: discovered SLM at %s", peer_url
|
|
286
|
+
)
|
|
287
|
+
return
|
|
250
288
|
except Exception as e:
|
|
251
289
|
logger.debug("RemoteSyncClient: mDNS add_service error: %s", e)
|
|
252
290
|
|
|
@@ -260,7 +298,7 @@ class RemoteSyncClient:
|
|
|
260
298
|
|
|
261
299
|
def _update_peer_url(self, host: str, port: int) -> None:
|
|
262
300
|
"""Update peer URL from discovery."""
|
|
263
|
-
new_url =
|
|
301
|
+
new_url = _peer_url(host, port)
|
|
264
302
|
if self._peer_url != new_url:
|
|
265
303
|
self._peer_url = new_url
|
|
266
304
|
logger.info("RemoteSyncClient: updated peer URL to %s", new_url)
|
|
@@ -79,6 +79,33 @@ class NoOpSemantic(SemanticTier):
|
|
|
79
79
|
return False
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
class _LazySemanticEmbedder:
|
|
83
|
+
"""Start the canonical embedding service only after an opted-in lookup."""
|
|
84
|
+
|
|
85
|
+
def __init__(self) -> None:
|
|
86
|
+
self._lock = threading.Lock()
|
|
87
|
+
self._service = None
|
|
88
|
+
|
|
89
|
+
def __call__(self, text: str) -> list[float] | None:
|
|
90
|
+
if self._service is None:
|
|
91
|
+
with self._lock:
|
|
92
|
+
if self._service is None:
|
|
93
|
+
from superlocalmemory.core.config import SLMConfig
|
|
94
|
+
from superlocalmemory.core.embeddings import EmbeddingService
|
|
95
|
+
|
|
96
|
+
self._service = EmbeddingService(SLMConfig.load().embedding)
|
|
97
|
+
return self._service.embed(text)
|
|
98
|
+
|
|
99
|
+
def close(self) -> None:
|
|
100
|
+
service = self._service
|
|
101
|
+
self._service = None
|
|
102
|
+
if service is not None:
|
|
103
|
+
try:
|
|
104
|
+
service.unload()
|
|
105
|
+
except Exception:
|
|
106
|
+
pass
|
|
107
|
+
|
|
108
|
+
|
|
82
109
|
# ---------------------------------------------------------------------------
|
|
83
110
|
# Metrics
|
|
84
111
|
# ---------------------------------------------------------------------------
|
|
@@ -130,13 +157,23 @@ class CacheManager:
|
|
|
130
157
|
self._metrics = CacheMetrics()
|
|
131
158
|
|
|
132
159
|
@classmethod
|
|
133
|
-
def get_instance(
|
|
160
|
+
def get_instance(
|
|
161
|
+
cls,
|
|
162
|
+
*,
|
|
163
|
+
optimize_config: Any | None = None,
|
|
164
|
+
semantic_embedder: Callable[[str], list[float] | None] | None = None,
|
|
165
|
+
) -> "CacheManager":
|
|
134
166
|
if cls._instance is None:
|
|
135
167
|
with cls._instance_lock:
|
|
136
168
|
if cls._instance is None:
|
|
137
169
|
from superlocalmemory.optimize.storage.db import CacheDB as _CacheDB
|
|
138
170
|
_db = _CacheDB.get_default()
|
|
139
171
|
cls._instance = cls(db=_db)
|
|
172
|
+
if optimize_config is not None:
|
|
173
|
+
cls._instance.configure_semantic(
|
|
174
|
+
optimize_config,
|
|
175
|
+
embedder=semantic_embedder,
|
|
176
|
+
)
|
|
140
177
|
return cls._instance
|
|
141
178
|
|
|
142
179
|
@classmethod
|
|
@@ -149,6 +186,7 @@ class CacheManager:
|
|
|
149
186
|
"""Reset the singleton (testing only)."""
|
|
150
187
|
with cls._instance_lock:
|
|
151
188
|
if cls._instance is not None:
|
|
189
|
+
cls._instance._close_semantic()
|
|
152
190
|
try:
|
|
153
191
|
cls._instance._db.close() # type: ignore[attr-defined]
|
|
154
192
|
except Exception:
|
|
@@ -416,8 +454,46 @@ class CacheManager:
|
|
|
416
454
|
MetricsCollector.get_instance().on_miss()
|
|
417
455
|
|
|
418
456
|
def set_semantic_tier(self, tier: SemanticTier) -> None:
|
|
457
|
+
self._close_semantic()
|
|
419
458
|
self._semantic = tier
|
|
420
459
|
|
|
460
|
+
def _close_semantic(self) -> None:
|
|
461
|
+
close = getattr(self._semantic, "close", None)
|
|
462
|
+
if callable(close):
|
|
463
|
+
try:
|
|
464
|
+
close()
|
|
465
|
+
except Exception:
|
|
466
|
+
pass
|
|
467
|
+
|
|
468
|
+
def configure_semantic(
|
|
469
|
+
self,
|
|
470
|
+
optimize_config: Any,
|
|
471
|
+
*,
|
|
472
|
+
embedder: Callable[[str], list[float] | None] | None = None,
|
|
473
|
+
) -> None:
|
|
474
|
+
"""Wire or disable the real semantic tier from live proxy config."""
|
|
475
|
+
enabled = bool(getattr(optimize_config, "semantic_enabled", False))
|
|
476
|
+
if not enabled:
|
|
477
|
+
if not isinstance(self._semantic, NoOpSemantic):
|
|
478
|
+
self.set_semantic_tier(NoOpSemantic())
|
|
479
|
+
return
|
|
480
|
+
|
|
481
|
+
from superlocalmemory.optimize.cache.semantic import VCacheSemantic
|
|
482
|
+
|
|
483
|
+
desired_embedder = embedder or _LazySemanticEmbedder()
|
|
484
|
+
current = self._semantic
|
|
485
|
+
if (
|
|
486
|
+
isinstance(current, VCacheSemantic)
|
|
487
|
+
and current._config == optimize_config
|
|
488
|
+
and (embedder is None or current._embedder is embedder)
|
|
489
|
+
):
|
|
490
|
+
return
|
|
491
|
+
self.set_semantic_tier(VCacheSemantic(
|
|
492
|
+
db=self._db,
|
|
493
|
+
config=optimize_config,
|
|
494
|
+
embedder=desired_embedder,
|
|
495
|
+
))
|
|
496
|
+
|
|
421
497
|
# ---- core request path ----
|
|
422
498
|
|
|
423
499
|
def get_or_call(
|
|
@@ -22,7 +22,7 @@ import logging
|
|
|
22
22
|
import random
|
|
23
23
|
import threading
|
|
24
24
|
import time
|
|
25
|
-
from typing import TYPE_CHECKING, Any
|
|
25
|
+
from typing import TYPE_CHECKING, Any, Callable
|
|
26
26
|
|
|
27
27
|
import numpy as np
|
|
28
28
|
|
|
@@ -77,9 +77,12 @@ class VCacheSemantic(SemanticTier):
|
|
|
77
77
|
self,
|
|
78
78
|
db: "CacheDB",
|
|
79
79
|
config: "OptimizeConfig",
|
|
80
|
+
*,
|
|
81
|
+
embedder: Callable[[str], list[float] | np.ndarray | None] | None = None,
|
|
80
82
|
) -> None:
|
|
81
83
|
self._db = db
|
|
82
84
|
self._config = config
|
|
85
|
+
self._embedder = embedder
|
|
83
86
|
# TODO(v3.7): when entry_count > 10_000, promote to sqlite-vec. Config flag: semantic_use_vec.
|
|
84
87
|
|
|
85
88
|
self._boundary_store = BoundaryStore(
|
|
@@ -134,7 +137,13 @@ class VCacheSemantic(SemanticTier):
|
|
|
134
137
|
return None
|
|
135
138
|
try:
|
|
136
139
|
if embed is None:
|
|
137
|
-
|
|
140
|
+
if self._embedder is None:
|
|
141
|
+
return None
|
|
142
|
+
messages = _extract_messages(req)
|
|
143
|
+
system = _extract_system(req)
|
|
144
|
+
embed = self._embedder(self._build_query_text(messages, system))
|
|
145
|
+
if embed is None:
|
|
146
|
+
return None
|
|
138
147
|
vec = np.asarray(embed, dtype=np.float32)
|
|
139
148
|
if vec.shape[0] != _EMBED_DIM:
|
|
140
149
|
logger.debug(
|
|
@@ -190,7 +199,13 @@ class VCacheSemantic(SemanticTier):
|
|
|
190
199
|
return
|
|
191
200
|
try:
|
|
192
201
|
if embed is None:
|
|
193
|
-
|
|
202
|
+
if self._embedder is None:
|
|
203
|
+
return
|
|
204
|
+
messages = _extract_messages(req)
|
|
205
|
+
system = _extract_system(req)
|
|
206
|
+
embed = self._embedder(self._build_query_text(messages, system))
|
|
207
|
+
if embed is None:
|
|
208
|
+
return
|
|
194
209
|
messages = _extract_messages(req)
|
|
195
210
|
system = _extract_system(req)
|
|
196
211
|
query_text = self._build_query_text(messages, system)
|
|
@@ -247,6 +262,11 @@ class VCacheSemantic(SemanticTier):
|
|
|
247
262
|
tenant_id, exc, exc_info=True,
|
|
248
263
|
)
|
|
249
264
|
|
|
265
|
+
def close(self) -> None:
|
|
266
|
+
close = getattr(self._embedder, "close", None)
|
|
267
|
+
if callable(close):
|
|
268
|
+
close()
|
|
269
|
+
|
|
250
270
|
# ------------------------------------------------------------------
|
|
251
271
|
# Internal lookup
|
|
252
272
|
# ------------------------------------------------------------------
|
|
@@ -17,6 +17,10 @@ from __future__ import annotations
|
|
|
17
17
|
import logging
|
|
18
18
|
import re
|
|
19
19
|
import threading
|
|
20
|
+
from typing import TYPE_CHECKING
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from superlocalmemory.optimize.storage.db import CacheDB
|
|
20
24
|
|
|
21
25
|
logger = logging.getLogger("slm.optimize.compress.ccr")
|
|
22
26
|
|
|
@@ -18,11 +18,16 @@ import json
|
|
|
18
18
|
import logging
|
|
19
19
|
import threading
|
|
20
20
|
from dataclasses import dataclass
|
|
21
|
-
from typing import Any
|
|
21
|
+
from typing import TYPE_CHECKING, Any
|
|
22
22
|
|
|
23
23
|
from superlocalmemory.optimize.proxy.lifecycle import ProxyRequest, CompressHook
|
|
24
24
|
from superlocalmemory.optimize.config.store import ConfigStore
|
|
25
25
|
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
from superlocalmemory.optimize.compress.align import CacheAligner
|
|
28
|
+
from superlocalmemory.optimize.compress.ccr import CCRStore
|
|
29
|
+
from superlocalmemory.optimize.compress.prose_llmlingua import LLMLinguaCompressor
|
|
30
|
+
|
|
26
31
|
logger = logging.getLogger("slm.optimize.compress.router")
|
|
27
32
|
|
|
28
33
|
_MIN_CHARS_FOR_COMPRESSION: int = 500
|
|
@@ -6,8 +6,13 @@ module. They NEVER construct ConfigStore themselves or read optimize.json direct
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
9
11
|
from superlocalmemory.optimize.config.schema import OptimizeConfig
|
|
10
12
|
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from superlocalmemory.optimize.config.store import ConfigStore
|
|
15
|
+
|
|
11
16
|
_store: "ConfigStore | None" = None
|
|
12
17
|
|
|
13
18
|
|
|
@@ -17,16 +17,16 @@ import json
|
|
|
17
17
|
import logging
|
|
18
18
|
import os
|
|
19
19
|
import threading
|
|
20
|
-
import time
|
|
21
20
|
from pathlib import Path
|
|
22
21
|
from typing import Any, Callable
|
|
23
22
|
|
|
24
|
-
from superlocalmemory.
|
|
23
|
+
from superlocalmemory.infra.data_root import DynamicStatePath
|
|
25
24
|
from superlocalmemory.optimize.config.defaults import DEFAULT_OPTIMIZE_CONFIG
|
|
25
|
+
from superlocalmemory.optimize.config.schema import OptimizeConfig
|
|
26
26
|
|
|
27
27
|
logger = logging.getLogger(__name__)
|
|
28
28
|
|
|
29
|
-
_DEFAULT_CONFIG_PATH
|
|
29
|
+
_DEFAULT_CONFIG_PATH = DynamicStatePath("optimize.json")
|
|
30
30
|
_POLL_INTERVAL_SECONDS: float = 2.0
|
|
31
31
|
|
|
32
32
|
|
|
@@ -38,7 +38,9 @@ class ConfigStore:
|
|
|
38
38
|
config_path: Path | None = None,
|
|
39
39
|
poll_interval: float = _POLL_INTERVAL_SECONDS,
|
|
40
40
|
) -> None:
|
|
41
|
-
self._config_path = Path(
|
|
41
|
+
self._config_path = Path(
|
|
42
|
+
config_path if config_path is not None else _DEFAULT_CONFIG_PATH
|
|
43
|
+
)
|
|
42
44
|
self._poll_interval_seconds = float(poll_interval)
|
|
43
45
|
self._lock = threading.RLock()
|
|
44
46
|
self._change_callbacks: list[Callable[[OptimizeConfig], None]] = []
|
|
@@ -7,6 +7,7 @@ import inspect
|
|
|
7
7
|
import json
|
|
8
8
|
import logging
|
|
9
9
|
from typing import Any, AsyncIterator, Callable
|
|
10
|
+
from weakref import WeakKeyDictionary
|
|
10
11
|
|
|
11
12
|
import httpx
|
|
12
13
|
from fastapi.requests import Request
|
|
@@ -24,8 +25,10 @@ _get_running_loop = asyncio.get_running_loop
|
|
|
24
25
|
logger = logging.getLogger("slm.optimize.proxy.helpers")
|
|
25
26
|
|
|
26
27
|
# Per-callable cache of "does this hook method accept a tenant_id kwarg?".
|
|
27
|
-
#
|
|
28
|
-
|
|
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()
|
|
29
32
|
|
|
30
33
|
|
|
31
34
|
def _accepts_tenant_id(fn: Callable) -> bool:
|
|
@@ -42,8 +45,12 @@ def _accepts_tenant_id(fn: Callable) -> bool:
|
|
|
42
45
|
raises fails open to a cache MISS, never the shared namespace.
|
|
43
46
|
"""
|
|
44
47
|
target = getattr(fn, "__func__", fn)
|
|
45
|
-
|
|
46
|
-
|
|
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
|
|
47
54
|
if cached is None:
|
|
48
55
|
try:
|
|
49
56
|
params = inspect.signature(fn).parameters
|
|
@@ -53,7 +60,10 @@ def _accepts_tenant_id(fn: Callable) -> bool:
|
|
|
53
60
|
except (ValueError, TypeError):
|
|
54
61
|
# Builtins / C callables without a signature — assume legacy.
|
|
55
62
|
cached = False
|
|
56
|
-
|
|
63
|
+
try:
|
|
64
|
+
_HOOK_TENANT_SUPPORT[target] = cached
|
|
65
|
+
except TypeError:
|
|
66
|
+
pass
|
|
57
67
|
return cached
|
|
58
68
|
|
|
59
69
|
# SEC-M-02 (CWE-400): reject oversized bodies to prevent compression-bomb DoS.
|
|
@@ -28,9 +28,10 @@ import threading
|
|
|
28
28
|
from pathlib import Path
|
|
29
29
|
from typing import Any
|
|
30
30
|
|
|
31
|
+
from superlocalmemory.infra.data_root import state_path
|
|
32
|
+
|
|
31
33
|
logger = logging.getLogger("slm.optimize.proxy.capture")
|
|
32
34
|
|
|
33
|
-
_CAPTURE_DIRNAME = ".superlocalmemory"
|
|
34
35
|
_CAPTURE_FILENAME = "optimize_capture.jsonl"
|
|
35
36
|
_CAPTURE_ENV = "SLM_OPTIMIZE_CAPTURE"
|
|
36
37
|
_TRUTHY = frozenset({"1", "true", "yes", "on"})
|
|
@@ -51,7 +52,7 @@ def capture_enabled() -> bool:
|
|
|
51
52
|
|
|
52
53
|
|
|
53
54
|
def _capture_path() -> Path:
|
|
54
|
-
return
|
|
55
|
+
return state_path(_CAPTURE_FILENAME)
|
|
55
56
|
|
|
56
57
|
|
|
57
58
|
class ShadowCapture:
|
|
@@ -17,7 +17,7 @@ from superlocalmemory.optimize.proxy.lifecycle import HookChain
|
|
|
17
17
|
|
|
18
18
|
logger = logging.getLogger("slm.optimize.proxy")
|
|
19
19
|
|
|
20
|
-
_PROXY_VERSION = "3.
|
|
20
|
+
_PROXY_VERSION = "3.7.0"
|
|
21
21
|
_REQUEST_TIMEOUT_S = 300.0
|
|
22
22
|
_CONNECT_TIMEOUT_S = 10.0
|
|
23
23
|
_MAX_CONNECTIONS = 100
|
|
@@ -178,7 +178,7 @@ def _load_hooks(config: OptimizeConfig) -> HookChain:
|
|
|
178
178
|
if config.cache_enabled:
|
|
179
179
|
try:
|
|
180
180
|
from superlocalmemory.optimize.cache.manager import CacheManager
|
|
181
|
-
cache_hook = CacheManager.get_instance()
|
|
181
|
+
cache_hook = CacheManager.get_instance(optimize_config=config)
|
|
182
182
|
except Exception as exc:
|
|
183
183
|
logger.warning(
|
|
184
184
|
"cache hook load failed (proxy continues without cache): %s", exc
|