superlocalmemory 3.7.0 → 3.7.1
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 +9 -0
- package/README.md +2 -2
- package/package.json +2 -2
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/requirements.txt +1 -1
- package/plugin-src/.mcp.json +12 -0
- package/plugin-src/agents/slm-memory-advisor.md +44 -0
- package/plugin-src/agents/slm-optimize-advisor.md +38 -0
- package/plugin-src/hooks/.gitkeep +0 -0
- package/plugin-src/hooks/hooks.json +23 -0
- package/plugin-src/manifest.json +25 -0
- package/plugin-src/requirements.txt +1 -0
- package/plugin-src/rules/CLAUDE.md.fragment +44 -0
- package/plugin-src/scripts/ensure-venv.bat +122 -0
- package/plugin-src/scripts/ensure-venv.sh +105 -0
- package/plugin-src/scripts/slm-launch +15 -0
- package/plugin-src/scripts/slm-launch.bat +17 -0
- package/plugin-src/settings.json +16 -0
- package/plugin-src/skills/slm-cache/SKILL.md +140 -0
- package/plugin-src/skills/slm-compress/SKILL.md +143 -0
- package/plugin-src/skills/slm-graph/SKILL.md +300 -0
- package/plugin-src/skills/slm-recall/SKILL.md +204 -0
- package/plugin-src/skills/slm-remember/SKILL.md +194 -0
- package/plugin-src/skills/slm-session/SKILL.md +207 -0
- package/plugin-src/skills/slm-status/SKILL.md +149 -0
- package/pyproject.toml +1 -1
- package/src/superlocalmemory/__init__.py +1 -1
- package/src/superlocalmemory/cli/_lazy_init.py +4 -2
- package/src/superlocalmemory/core/engine_wiring.py +30 -23
- package/src/superlocalmemory/hooks/claude_code_hooks.py +1 -1
- package/src/superlocalmemory/hooks/context_payload.py +1 -1
- package/src/superlocalmemory/mcp/http_transport.py +1 -1
- package/src/superlocalmemory/mcp/tools_core.py +2 -2
- package/src/superlocalmemory/optimize/proxy/server.py +1 -1
- package/src/superlocalmemory/server/routes/brain.py +1 -1
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: slm-status
|
|
3
|
+
description: Health and optimization stats for SuperLocalMemory — call slm_optimize_stats() for live compression and cache counters (compress_runs, tokens_saved_compress, cache_proxy_hits, cache_proxy_misses, cache_kv_hits, cache_kv_misses); run slm status [--json] for system state (mode, profile, DB size, fact/entity/edge counts) and slm doctor [--json] for preflight including the "Optimize (Surface B)" health line; use together to confirm optimization is actually saving tokens.
|
|
4
|
+
when_to_use: "check slm status, health check, is slm working, optimize stats, tokens saved, cache hits, compress runs, slm doctor, preflight, db size, slm info, diagnose slm"
|
|
5
|
+
allowed-tools: slm_optimize_stats, Bash
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# slm-status — Health and Optimize Stats
|
|
9
|
+
|
|
10
|
+
## Purpose
|
|
11
|
+
|
|
12
|
+
Use this skill to answer: "Is SLM healthy?", "Is compression/caching actually saving tokens?", and "What does the system look like right now?" It covers three surfaces: the MCP stats tool, the `slm status` CLI, and the `slm doctor` preflight.
|
|
13
|
+
|
|
14
|
+
## Primary MCP Tool: slm_optimize_stats
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
slm_optimize_stats() -> dict
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
No arguments. Returns counters from the current daemon and MCP process session.
|
|
21
|
+
|
|
22
|
+
### Return dict (all keys always present)
|
|
23
|
+
|
|
24
|
+
| Key | Type | Meaning |
|
|
25
|
+
|-----|------|---------|
|
|
26
|
+
| `ok` | bool | `True` on success; `False` on internal error |
|
|
27
|
+
| `compress_runs` | int | Total compress calls recorded by the daemon (persisted across restarts) |
|
|
28
|
+
| `tokens_saved_compress` | int | Cumulative tokens saved by compression (daemon-persisted) |
|
|
29
|
+
| `cache_proxy_hits` | int | Proxy-layer cache hits (daemon-persisted) |
|
|
30
|
+
| `cache_proxy_misses` | int | Proxy-layer cache misses (daemon-persisted) |
|
|
31
|
+
| `cache_kv_hits` | int | MCP KV cache hits — **this MCP process session only**, resets on restart |
|
|
32
|
+
| `cache_kv_misses` | int | MCP KV cache misses — **this MCP process session only**, resets on restart |
|
|
33
|
+
| `ccr_note` | str \| None | Note about CCR entry count (not tracked per-session; see daemon `/api/v1/metrics`) |
|
|
34
|
+
| `note` | str \| None | Scope clarification or error detail |
|
|
35
|
+
|
|
36
|
+
### Important scope distinction
|
|
37
|
+
|
|
38
|
+
`compress_runs`, `tokens_saved_compress`, `cache_proxy_hits`, and `cache_proxy_misses` are **daemon-persisted** — they survive MCP restarts and accumulate over the full install lifetime.
|
|
39
|
+
|
|
40
|
+
`cache_kv_hits` and `cache_kv_misses` are **in-process counters** — they reset to 0 each time the MCP server starts. Use them to gauge cache effectiveness within the current session only.
|
|
41
|
+
|
|
42
|
+
### Reading whether optimization is saving tokens
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
stats = await slm_optimize_stats()
|
|
46
|
+
if stats["ok"]:
|
|
47
|
+
savings = stats["tokens_saved_compress"]
|
|
48
|
+
kv_hit_rate = (
|
|
49
|
+
stats["cache_kv_hits"] / max(stats["cache_kv_hits"] + stats["cache_kv_misses"], 1)
|
|
50
|
+
)
|
|
51
|
+
# savings > 0 and kv_hit_rate > 0.5 means Surface B is actively reducing costs
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
If `compress_runs` is 0 after several sessions, compression is not being triggered — check daemon config and whether `slm_compress` is being called.
|
|
55
|
+
|
|
56
|
+
If `cache_kv_hits` is 0 after repeated work, verify key naming consistency (the same key string must be used for set and get).
|
|
57
|
+
|
|
58
|
+
## Secondary CLI: slm status
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
slm status [--json] [--verbose]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Reports system-level state — not optimization counters. Canonical fields (WP-02):
|
|
65
|
+
|
|
66
|
+
- **mode** — active operation mode (e.g. `local`)
|
|
67
|
+
- **profile** — current memory profile name
|
|
68
|
+
- **DB size** — database file size on disk
|
|
69
|
+
- **fact count** — number of stored memory facts
|
|
70
|
+
- **entity count** — entity graph node count
|
|
71
|
+
- **edge count** — entity graph edge count
|
|
72
|
+
|
|
73
|
+
`--verbose` / `-v` adds: migration log, daemon port, disabled marker, last version.
|
|
74
|
+
|
|
75
|
+
`--json` outputs a machine-readable dict with the same fields — preferred for agent consumption.
|
|
76
|
+
|
|
77
|
+
Example agent-native invocation:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
slm status --json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Typical JSON shape (exact field names depend on runtime; use `--json` and read what arrives):
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"mode": "local",
|
|
88
|
+
"profile": "code",
|
|
89
|
+
"db_size_mb": 12.4,
|
|
90
|
+
"facts": 384,
|
|
91
|
+
"entities": 201,
|
|
92
|
+
"edges": 519
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Do not rely on the human-readable format for parsing — always use `--json` when the output feeds another tool.
|
|
97
|
+
|
|
98
|
+
## Secondary CLI: slm doctor
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
slm doctor [--json] [--quick]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Preflight check covering dependencies, embedding worker, daemon connectivity, and Surface B health. The **"Optimize (Surface B)"** line (WP-03) confirms whether the compression and cache subsystem initialised correctly.
|
|
105
|
+
|
|
106
|
+
`--quick` skips the daemon and embedding probes — runs only dependency and config checks; faster but incomplete.
|
|
107
|
+
|
|
108
|
+
`--json` outputs structured results per check — use this in automated health pipelines.
|
|
109
|
+
|
|
110
|
+
A passing doctor output confirms:
|
|
111
|
+
- Python deps present
|
|
112
|
+
- Embedding worker reachable
|
|
113
|
+
- Daemon responding
|
|
114
|
+
- Surface B (Optimize) initialised
|
|
115
|
+
|
|
116
|
+
A failing "Optimize (Surface B)" line means `slm_compress`, `slm_cache_set`, and `slm_cache_get` may not function correctly — investigate daemon config before relying on those tools.
|
|
117
|
+
|
|
118
|
+
## Secondary CLI: slm optimize status
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
slm optimize status [--json]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Shows whether the Optimize module (cache + compress) is currently enabled or disabled at the daemon level. Available subcommands also include `optimize on`, `optimize off`, and `optimize savings`.
|
|
125
|
+
|
|
126
|
+
The `optimize savings` subcommand accepts:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
slm optimize savings [--since <days>] [--provider anthropic|openai|gemini] [--json]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`--since` defaults to 7 days. `--provider` filters by the target AI provider.
|
|
133
|
+
|
|
134
|
+
Note: the `slm optimize` subcommands have known pre-existing parse-test failures — if a subcommand errors, use `slm_optimize_stats()` via MCP as the authoritative source.
|
|
135
|
+
|
|
136
|
+
## Recommended Health Workflow
|
|
137
|
+
|
|
138
|
+
1. Run `slm doctor --json` at session start to confirm all subsystems are up.
|
|
139
|
+
2. Call `slm_optimize_stats()` after a batch of work to check token savings.
|
|
140
|
+
3. Run `slm status --json` when you need DB size or memory counts.
|
|
141
|
+
4. If `ok: false` on any MCP tool — check `note` field, then run `slm doctor` to isolate the failure.
|
|
142
|
+
|
|
143
|
+
## Fail-Open
|
|
144
|
+
|
|
145
|
+
`slm_optimize_stats()` never raises. On internal error it returns `ok: false` with all counters at 0. Continue the session — stats unavailability does not affect compression or caching operations.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
SuperLocalMemory v3.6.18 · Qualixar · AGPL-3.0-or-later
|
package/pyproject.toml
CHANGED
|
@@ -32,7 +32,7 @@ if "OMP_NUM_THREADS" not in os.environ:
|
|
|
32
32
|
os.environ["OMP_NUM_THREADS"] = "2"
|
|
33
33
|
# ---------------------------------------------------------------------------
|
|
34
34
|
|
|
35
|
-
__version__ = "3.7.
|
|
35
|
+
__version__ = "3.7.1"
|
|
36
36
|
|
|
37
37
|
_REQUIRED_VERSIONS = {
|
|
38
38
|
"sentence_transformers": "5.3.0",
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
"""WP-07 — Lazy first-run initialisation (pip cross-install).
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Lightweight import only — zero heavy imports, STDOUT-SILENT.
|
|
8
8
|
|
|
9
9
|
Public API
|
|
10
10
|
----------
|
|
@@ -25,6 +25,8 @@ import json
|
|
|
25
25
|
import os
|
|
26
26
|
from pathlib import Path
|
|
27
27
|
|
|
28
|
+
from superlocalmemory import __version__ as _RUNTIME_VERSION
|
|
29
|
+
|
|
28
30
|
|
|
29
31
|
# ---------------------------------------------------------------------------
|
|
30
32
|
# Public: home resolution
|
|
@@ -55,7 +57,7 @@ def slm_home() -> Path:
|
|
|
55
57
|
# Only mode + base_dir; everything else uses SLMConfig defaults.
|
|
56
58
|
_MINIMAL_CONFIG: dict = {
|
|
57
59
|
"mode": "a",
|
|
58
|
-
"version":
|
|
60
|
+
"version": _RUNTIME_VERSION,
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
|
|
@@ -22,6 +22,30 @@ if TYPE_CHECKING:
|
|
|
22
22
|
logger = logging.getLogger(__name__)
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
def _log_reranker_warmup_status(reranker: Any) -> None:
|
|
26
|
+
"""Record non-blocking reranker warmup state without alarming first-run users."""
|
|
27
|
+
ready = reranker.warmup_sync(timeout=180)
|
|
28
|
+
if ready:
|
|
29
|
+
logger.info("Cross-encoder reranker warm and ready")
|
|
30
|
+
return
|
|
31
|
+
try:
|
|
32
|
+
from superlocalmemory.retrieval.reranker import _is_reranker_worker_alive
|
|
33
|
+
|
|
34
|
+
if _is_reranker_worker_alive():
|
|
35
|
+
logger.info(
|
|
36
|
+
"Cross-encoder reranker worker held by another process "
|
|
37
|
+
"(machine-wide singleton — usually the unified daemon); "
|
|
38
|
+
"this process will route reranking through that worker"
|
|
39
|
+
)
|
|
40
|
+
return
|
|
41
|
+
except Exception:
|
|
42
|
+
pass
|
|
43
|
+
logger.info(
|
|
44
|
+
"Cross-encoder reranker did not become ready during background warmup; "
|
|
45
|
+
"recalls use fallback scoring. Run 'slm doctor' for diagnostics."
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
25
49
|
# ---------------------------------------------------------------------------
|
|
26
50
|
# init_embedder (was MemoryEngine._init_embedder + helpers)
|
|
27
51
|
# ---------------------------------------------------------------------------
|
|
@@ -552,29 +576,12 @@ def init_retrieval(
|
|
|
552
576
|
# trust in slm health / slm doctor output.
|
|
553
577
|
if reranker is not None:
|
|
554
578
|
import threading
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
# another process (benign), or (b) actual model load failure.
|
|
562
|
-
# Disambiguate by probing the singleton PID file.
|
|
563
|
-
try:
|
|
564
|
-
from superlocalmemory.retrieval.reranker import _is_reranker_worker_alive
|
|
565
|
-
if _is_reranker_worker_alive():
|
|
566
|
-
logger.info(
|
|
567
|
-
"Cross-encoder reranker worker held by another process "
|
|
568
|
-
"(machine-wide singleton — usually the unified daemon); "
|
|
569
|
-
"this process will route reranking through that worker"
|
|
570
|
-
)
|
|
571
|
-
return
|
|
572
|
-
except Exception:
|
|
573
|
-
pass
|
|
574
|
-
logger.warning(
|
|
575
|
-
"Cross-encoder reranker warmup failed — recalls will use fallback scoring"
|
|
576
|
-
)
|
|
577
|
-
t = threading.Thread(target=_log_warmup_status, daemon=True, name="ce-init-warmup")
|
|
579
|
+
t = threading.Thread(
|
|
580
|
+
target=_log_reranker_warmup_status,
|
|
581
|
+
args=(reranker,),
|
|
582
|
+
daemon=True,
|
|
583
|
+
name="ce-init-warmup",
|
|
584
|
+
)
|
|
578
585
|
t.start()
|
|
579
586
|
|
|
580
587
|
# Phase A: Register forgetting filter into the channel registry
|
|
@@ -40,7 +40,7 @@ _DEFAULT_DISABLED_FILE = _DEFAULT_VERSION_DIR / ".hooks-disabled"
|
|
|
40
40
|
VERSION_DIR = _DEFAULT_VERSION_DIR
|
|
41
41
|
VERSION_FILE = _DEFAULT_VERSION_FILE
|
|
42
42
|
DISABLED_FILE = _DEFAULT_DISABLED_FILE
|
|
43
|
-
HOOKS_VERSION = "3.7.
|
|
43
|
+
HOOKS_VERSION = "3.7.1"
|
|
44
44
|
|
|
45
45
|
# Cross-platform temp dir and backwards-compatible marker overrides. Runtime
|
|
46
46
|
# defaults are root-namespaced and resolved when hook definitions are built.
|
|
@@ -40,7 +40,7 @@ def install_streamable_http_resource_guard() -> None:
|
|
|
40
40
|
class SLMFastMCP(FastMCP):
|
|
41
41
|
"""FastMCP with SLM release identity and deterministic SSE cleanup."""
|
|
42
42
|
|
|
43
|
-
def __init__(self, *args, product_version: str = "3.7.
|
|
43
|
+
def __init__(self, *args, product_version: str = "3.7.1", **kwargs) -> None:
|
|
44
44
|
super().__init__(*args, **kwargs)
|
|
45
45
|
# FastMCP delegates the initialize response to the low-level MCP
|
|
46
46
|
# server. Without an explicit value it reports the installed ``mcp``
|
|
@@ -111,7 +111,7 @@ def register_core_tools(server, get_engine: Callable) -> None:
|
|
|
111
111
|
"""Store content to memory with intelligent indexing.
|
|
112
112
|
|
|
113
113
|
Extracts atomic facts, resolves entities, builds graph edges,
|
|
114
|
-
and indexes for
|
|
114
|
+
and indexes for hybrid retrieval with graph-aware enhancement.
|
|
115
115
|
|
|
116
116
|
Multi-scope: ``scope`` sets visibility (personal/shared/global).
|
|
117
117
|
``shared_with`` is a comma-separated list of profile_ids for
|
|
@@ -246,7 +246,7 @@ def register_core_tools(server, get_engine: Callable) -> None:
|
|
|
246
246
|
include_global: bool | None = None,
|
|
247
247
|
include_shared: bool | None = None,
|
|
248
248
|
) -> dict:
|
|
249
|
-
"""Search memories
|
|
249
|
+
"""Search memories through hybrid retrieval, RRF fusion, and reranking.
|
|
250
250
|
|
|
251
251
|
S9-DASH-02: optional ``session_id`` threads through to the
|
|
252
252
|
engine's outcome-queue so PostToolUse / Stop hooks can attach
|
|
@@ -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.7.
|
|
20
|
+
_PROXY_VERSION = "3.7.1"
|
|
21
21
|
_REQUEST_TIMEOUT_S = 300.0
|
|
22
22
|
_CONNECT_TIMEOUT_S = 10.0
|
|
23
23
|
_MAX_CONNECTIONS = 100
|
|
@@ -64,7 +64,7 @@ router = APIRouter(prefix="/api/v3", tags=["brain"])
|
|
|
64
64
|
# LLD-03 v2 stratum space = 4 query types × 3 entity bins × 4 time buckets.
|
|
65
65
|
_STRATA_TOTAL: int = 48
|
|
66
66
|
|
|
67
|
-
_VERSION: str = "3.7.
|
|
67
|
+
_VERSION: str = "3.7.1"
|
|
68
68
|
|
|
69
69
|
# Banned metric names (LLD-04 U4). Kept as a tuple for grep visibility;
|
|
70
70
|
# the source-level test asserts we don't accidentally reintroduce them.
|