superlocalmemory 3.8.1 → 3.8.2
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 +2 -2
- package/package.json +1 -1
- 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 +2 -2
- 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 +3 -5
- 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/rules/AGENTS.md +2 -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-graph/SKILL.md +1 -1
- package/plugin-src/skills/slm-recall/SKILL.md +3 -5
- package/plugin-src/skills/slm-remember/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/pyproject.toml +1 -1
- package/scripts/postinstall.js +7 -1
- package/src/superlocalmemory/__init__.py +1 -1
- package/src/superlocalmemory/cli/commands.py +360 -2
- package/src/superlocalmemory/cli/main.py +62 -3
- package/src/superlocalmemory/cli/setup_wizard.py +142 -16
- package/src/superlocalmemory/core/component_healer.py +144 -0
- package/src/superlocalmemory/core/component_registry.py +487 -0
- package/src/superlocalmemory/core/config.py +21 -0
- package/src/superlocalmemory/core/embeddings.py +14 -1
- package/src/superlocalmemory/core/engine.py +9 -5
- package/src/superlocalmemory/core/ingestion_command.py +36 -16
- package/src/superlocalmemory/core/maintenance.py +43 -0
- package/src/superlocalmemory/core/maintenance_scheduler.py +28 -0
- package/src/superlocalmemory/core/recall_pipeline.py +39 -3
- package/src/superlocalmemory/core/store_pipeline.py +42 -0
- package/src/superlocalmemory/mcp/_daemon_proxy.py +6 -2
- package/src/superlocalmemory/mcp/_pool_adapter.py +4 -1
- package/src/superlocalmemory/mcp/tools_active.py +1 -1
- package/src/superlocalmemory/mcp/tools_core.py +17 -2
- package/src/superlocalmemory/retrieval/bridge_discovery.py +14 -0
- package/src/superlocalmemory/retrieval/spreading_activation.py +68 -38
- package/src/superlocalmemory/server/routes/behavioral.py +6 -2
- package/src/superlocalmemory/server/routes/learning.py +13 -3
- package/src/superlocalmemory/server/routes/memories.py +8 -3
- package/src/superlocalmemory/server/routes/v3_api.py +120 -0
- package/src/superlocalmemory/server/unified_daemon.py +266 -2
- package/src/superlocalmemory/storage/embedding_migrator.py +235 -0
- package/src/superlocalmemory/ui/index.html +3 -2
- package/src/superlocalmemory/ui/js/od-components.js +147 -0
- package/src/superlocalmemory/ui/js/od-entities.js +43 -0
- package/src/superlocalmemory/ui/js/od-graph.js +35 -0
- package/src/superlocalmemory/ui/js/od-health.js +18 -0
- package/src/superlocalmemory/ui/js/od-memories.js +37 -0
- package/src/superlocalmemory/ui/js/od-operations.js +36 -0
- package/src/superlocalmemory/ui/js/od-settings.js +72 -3
|
@@ -36,10 +36,138 @@ def _cmd_db_dispatch(args: Namespace) -> None:
|
|
|
36
36
|
if rc:
|
|
37
37
|
sys.exit(rc)
|
|
38
38
|
return
|
|
39
|
-
|
|
39
|
+
if sub == "reembed":
|
|
40
|
+
_cmd_db_reembed(args)
|
|
41
|
+
return
|
|
42
|
+
print(
|
|
43
|
+
"Usage: slm db migrate [--status] [--dry-run] "
|
|
44
|
+
"| slm db scale <action> "
|
|
45
|
+
"| slm db reembed [--missing-only] [--all-profiles] [--limit N]"
|
|
46
|
+
)
|
|
40
47
|
sys.exit(2)
|
|
41
48
|
|
|
42
49
|
|
|
50
|
+
def _cmd_db_reembed(args: Namespace) -> None:
|
|
51
|
+
"""Backfill NULL embeddings on atomic_facts.
|
|
52
|
+
|
|
53
|
+
Scans for atomic_facts rows with no embedding (facts stored while the
|
|
54
|
+
embedder was unavailable) and embeds them now. Safe to re-run — only
|
|
55
|
+
NULL rows are processed.
|
|
56
|
+
|
|
57
|
+
Usage:
|
|
58
|
+
slm db reembed --missing-only # backfill NULLs (default)
|
|
59
|
+
slm db reembed --missing-only --limit 500 # cap per run
|
|
60
|
+
slm db reembed --missing-only --all-profiles # cover every profile
|
|
61
|
+
"""
|
|
62
|
+
import time
|
|
63
|
+
|
|
64
|
+
from superlocalmemory.core.config import SLMConfig
|
|
65
|
+
from superlocalmemory.core.engine import MemoryEngine
|
|
66
|
+
from superlocalmemory.storage.embedding_migrator import backfill_missing_embeddings
|
|
67
|
+
|
|
68
|
+
use_json = getattr(args, "json", False)
|
|
69
|
+
missing_only = getattr(args, "missing_only", True)
|
|
70
|
+
all_profiles = getattr(args, "all_profiles", False)
|
|
71
|
+
limit = getattr(args, "limit", None)
|
|
72
|
+
|
|
73
|
+
if not missing_only:
|
|
74
|
+
if use_json:
|
|
75
|
+
from superlocalmemory.cli.json_output import json_print
|
|
76
|
+
json_print(
|
|
77
|
+
"db-reembed",
|
|
78
|
+
error={
|
|
79
|
+
"code": "NOT_IMPLEMENTED",
|
|
80
|
+
"message": "Only --missing-only is supported. "
|
|
81
|
+
"For full re-embed use 'slm db migrate'.",
|
|
82
|
+
},
|
|
83
|
+
)
|
|
84
|
+
else:
|
|
85
|
+
print("Only --missing-only mode is supported. "
|
|
86
|
+
"For full re-embed use 'slm db migrate'.")
|
|
87
|
+
sys.exit(2)
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
config = SLMConfig.load()
|
|
91
|
+
engine = MemoryEngine(config)
|
|
92
|
+
engine.initialize()
|
|
93
|
+
except Exception as exc:
|
|
94
|
+
if use_json:
|
|
95
|
+
from superlocalmemory.cli.json_output import json_print
|
|
96
|
+
json_print(
|
|
97
|
+
"db-reembed",
|
|
98
|
+
error={"code": "ENGINE_INIT_ERROR", "message": str(exc)},
|
|
99
|
+
)
|
|
100
|
+
else:
|
|
101
|
+
print(f"Error initializing engine: {exc}", file=sys.stderr)
|
|
102
|
+
sys.exit(1)
|
|
103
|
+
|
|
104
|
+
embedder = getattr(engine, "_embedder", None)
|
|
105
|
+
if embedder is None:
|
|
106
|
+
if use_json:
|
|
107
|
+
from superlocalmemory.cli.json_output import json_print
|
|
108
|
+
json_print(
|
|
109
|
+
"db-reembed",
|
|
110
|
+
error={
|
|
111
|
+
"code": "NO_EMBEDDER",
|
|
112
|
+
"message": "Embedder is not available. "
|
|
113
|
+
"Start the daemon first or check embedding configuration.",
|
|
114
|
+
},
|
|
115
|
+
)
|
|
116
|
+
else:
|
|
117
|
+
print(
|
|
118
|
+
"Embedder is not available. "
|
|
119
|
+
"Start the daemon ('slm serve') or check embedding config.",
|
|
120
|
+
file=sys.stderr,
|
|
121
|
+
)
|
|
122
|
+
engine.close()
|
|
123
|
+
sys.exit(1)
|
|
124
|
+
|
|
125
|
+
t0 = time.monotonic()
|
|
126
|
+
try:
|
|
127
|
+
result = backfill_missing_embeddings(
|
|
128
|
+
config,
|
|
129
|
+
engine._db,
|
|
130
|
+
embedder,
|
|
131
|
+
batch_size=50,
|
|
132
|
+
limit=limit,
|
|
133
|
+
all_profiles=all_profiles,
|
|
134
|
+
)
|
|
135
|
+
except Exception as exc:
|
|
136
|
+
if use_json:
|
|
137
|
+
from superlocalmemory.cli.json_output import json_print
|
|
138
|
+
json_print(
|
|
139
|
+
"db-reembed",
|
|
140
|
+
error={"code": "BACKFILL_ERROR", "message": str(exc)},
|
|
141
|
+
)
|
|
142
|
+
else:
|
|
143
|
+
print(f"Backfill error: {exc}", file=sys.stderr)
|
|
144
|
+
engine.close()
|
|
145
|
+
sys.exit(1)
|
|
146
|
+
|
|
147
|
+
elapsed = time.monotonic() - t0
|
|
148
|
+
engine.close()
|
|
149
|
+
|
|
150
|
+
if use_json:
|
|
151
|
+
from superlocalmemory.cli.json_output import json_print
|
|
152
|
+
json_print(
|
|
153
|
+
"db-reembed",
|
|
154
|
+
data={
|
|
155
|
+
"scanned": result["scanned"],
|
|
156
|
+
"embedded": result["embedded"],
|
|
157
|
+
"remaining_null": result["remaining_null"],
|
|
158
|
+
"elapsed_s": round(elapsed, 2),
|
|
159
|
+
},
|
|
160
|
+
)
|
|
161
|
+
else:
|
|
162
|
+
print(
|
|
163
|
+
f"Backfill complete — "
|
|
164
|
+
f"scanned={result['scanned']} "
|
|
165
|
+
f"embedded={result['embedded']} "
|
|
166
|
+
f"remaining_null={result['remaining_null']} "
|
|
167
|
+
f"elapsed={elapsed:.1f}s"
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
|
|
43
171
|
def _cmd_mesh_dispatch(args: Namespace) -> None:
|
|
44
172
|
"""Route ``slm mesh ...`` inspection subcommands (M-03)."""
|
|
45
173
|
from superlocalmemory.cli.mesh_cmd import cmd_mesh
|
|
@@ -238,6 +366,8 @@ def dispatch(args: Namespace) -> None:
|
|
|
238
366
|
"help-optimize": _cmd_help_optimize,
|
|
239
367
|
# V3.8.0 bounded loops (gate-verified agent loops, SLM-backed ledger)
|
|
240
368
|
"loop": _cmd_loop,
|
|
369
|
+
# V3.8.2 super-help — grouped overview of every command + topics
|
|
370
|
+
"help": cmd_help,
|
|
241
371
|
}
|
|
242
372
|
handler = handlers.get(args.command)
|
|
243
373
|
if handler:
|
|
@@ -1398,7 +1528,10 @@ def cmd_recall(args: Namespace) -> None:
|
|
|
1398
1528
|
|
|
1399
1529
|
response = engine.recall(
|
|
1400
1530
|
args.query, limit=args.limit,
|
|
1401
|
-
|
|
1531
|
+
# v3.8.2: --fast → True; unset → None so engine resolves the
|
|
1532
|
+
# client-driven-agentic default (parity with the daemon path, which
|
|
1533
|
+
# omits the fast query param when --fast is absent).
|
|
1534
|
+
fast=(True if getattr(args, "fast", False) else None),
|
|
1402
1535
|
include_global=include_global,
|
|
1403
1536
|
include_shared=include_shared,
|
|
1404
1537
|
window=getattr(args, "window", "") or None,
|
|
@@ -2140,6 +2273,175 @@ def _readline_with_timeout(
|
|
|
2140
2273
|
)
|
|
2141
2274
|
|
|
2142
2275
|
|
|
2276
|
+
# ---------------------------------------------------------------------------
|
|
2277
|
+
# Super-help (v3.8.2) — one place a non-technical user sees EVERYTHING.
|
|
2278
|
+
# Grouped so `slm help` is scannable; a drift test asserts every top-level
|
|
2279
|
+
# command in the parser appears here (see test_super_help).
|
|
2280
|
+
# ---------------------------------------------------------------------------
|
|
2281
|
+
|
|
2282
|
+
_COMMAND_GROUPS: list[tuple[str, list[tuple[str, str]]]] = [
|
|
2283
|
+
("Getting started", [
|
|
2284
|
+
("setup", "Guided first-time setup (models, mode, IDEs) — start here"),
|
|
2285
|
+
("init", "Set up + wire Claude Code hooks + connect IDEs"),
|
|
2286
|
+
("reconfigure", "Re-run setup / pick a performance profile"),
|
|
2287
|
+
("mode", "Switch memory mode: a (local) / b (Ollama) / c (cloud)"),
|
|
2288
|
+
("provider", "Configure the cloud LLM provider + API key (Mode C)"),
|
|
2289
|
+
("connect", "Auto-configure detected IDEs (Cursor, VS Code, …)"),
|
|
2290
|
+
("hooks", "Install/inspect Claude Code hooks"),
|
|
2291
|
+
("codex", "Configure the Codex / OpenAI integration"),
|
|
2292
|
+
]),
|
|
2293
|
+
("Store & recall memories", [
|
|
2294
|
+
("remember", "Store a memory (--tags to label)"),
|
|
2295
|
+
("recall", "Semantic + keyword search across memories"),
|
|
2296
|
+
("search", "Exact keyword / full-text search"),
|
|
2297
|
+
("list", "Show recent memories (-n N)"),
|
|
2298
|
+
("update", "Correct an existing memory by id"),
|
|
2299
|
+
("delete", "Delete a memory by id"),
|
|
2300
|
+
("forget", "Run the decay cycle (preview first)"),
|
|
2301
|
+
("trace", "Recall with a per-channel score breakdown"),
|
|
2302
|
+
("ingest", "Ingest external observations / documents"),
|
|
2303
|
+
]),
|
|
2304
|
+
("Run SLM (daemon & dashboard)", [
|
|
2305
|
+
("serve", "Start/stop the background daemon"),
|
|
2306
|
+
("restart", "Restart the daemon (applies restart-only settings)"),
|
|
2307
|
+
("dashboard", "Open the web dashboard (localhost:8765)"),
|
|
2308
|
+
("mcp", "Start the MCP server (used by IDEs)"),
|
|
2309
|
+
("warmup", "Pre-load models so the first recall is fast"),
|
|
2310
|
+
("status", "Show daemon status + memory counts"),
|
|
2311
|
+
]),
|
|
2312
|
+
("Health & self-healing", [
|
|
2313
|
+
("doctor", "Full pre-flight check (add --fix to auto-repair)"),
|
|
2314
|
+
("health", "Quick math/retrieval layer status"),
|
|
2315
|
+
("diagnostics", "Export a local diagnostics bundle"),
|
|
2316
|
+
("evidence", "Build/inspect evidence bundles"),
|
|
2317
|
+
("rotate-token", "Rotate the local dashboard install token"),
|
|
2318
|
+
]),
|
|
2319
|
+
("Configuration", [
|
|
2320
|
+
("config", "View/set configuration (see: slm help config)"),
|
|
2321
|
+
("enable", "Enable a feature/escape hatch"),
|
|
2322
|
+
("disable", "Disable a feature/escape hatch"),
|
|
2323
|
+
("clear-cache", "Clear caches"),
|
|
2324
|
+
]),
|
|
2325
|
+
("Profiles & sessions", [
|
|
2326
|
+
("profile", "Manage workspaces/profiles (add, switch, list)"),
|
|
2327
|
+
("session", "Open/close a work session"),
|
|
2328
|
+
("session-context", "Pre-stage session context for hooks"),
|
|
2329
|
+
]),
|
|
2330
|
+
("Multi-device mesh", [
|
|
2331
|
+
("mesh", "Inspect/manage the cross-device memory mesh"),
|
|
2332
|
+
]),
|
|
2333
|
+
("Token optimization", [
|
|
2334
|
+
("optimize", "Configure the Optimize surface (cache/compress/proxy)"),
|
|
2335
|
+
("cache", "Manage the LLM response cache"),
|
|
2336
|
+
("compress", "Manage prose compression"),
|
|
2337
|
+
("proxy", "Manage the optimizing LLM proxy"),
|
|
2338
|
+
("wrap", "Run an agent (claude, codex, …) through the proxy"),
|
|
2339
|
+
("help-optimize", "Detailed help for the Optimize surface"),
|
|
2340
|
+
]),
|
|
2341
|
+
("Learning & maintenance", [
|
|
2342
|
+
("evolve", "Skill-evolution controls"),
|
|
2343
|
+
("observe", "External observation / telemetry ingestion"),
|
|
2344
|
+
("decay", "Run a forgetting/decay pass"),
|
|
2345
|
+
("consolidate", "Merge/consolidate related memories"),
|
|
2346
|
+
("quantize", "Quantize embeddings to save space"),
|
|
2347
|
+
("soft-prompts", "Manage learned soft prompts"),
|
|
2348
|
+
("reap", "Clean up stale/dead records"),
|
|
2349
|
+
("adapters", "Manage ingestion adapters"),
|
|
2350
|
+
("benchmark", "Run local benchmarks"),
|
|
2351
|
+
]),
|
|
2352
|
+
("Data & migration", [
|
|
2353
|
+
("db", "Low-level database operations"),
|
|
2354
|
+
("migrate", "Migrate the data store to the current version"),
|
|
2355
|
+
]),
|
|
2356
|
+
("Automation", [
|
|
2357
|
+
("loop", "Run gate-verified bounded agent loops"),
|
|
2358
|
+
]),
|
|
2359
|
+
("Help", [
|
|
2360
|
+
("help", "This overview. Try: slm help config | modes | self-heal"),
|
|
2361
|
+
]),
|
|
2362
|
+
]
|
|
2363
|
+
|
|
2364
|
+
_HELP_TOPICS: dict[str, str] = {
|
|
2365
|
+
"modes": """\
|
|
2366
|
+
Operating modes
|
|
2367
|
+
a Local Guardian — no model-provider call in the core memory path.
|
|
2368
|
+
b Smart Local — uses a local Ollama LLM (auto-detected at setup).
|
|
2369
|
+
c Full Power — uses a cloud LLM (OpenAI/Anthropic/…), needs a key.
|
|
2370
|
+
|
|
2371
|
+
Switch any time: slm mode a (or b / c)
|
|
2372
|
+
""",
|
|
2373
|
+
"config": """\
|
|
2374
|
+
Configuration
|
|
2375
|
+
slm config Show current configuration
|
|
2376
|
+
slm config get <key> Read one setting
|
|
2377
|
+
slm config set <key> <val> Change a setting
|
|
2378
|
+
|
|
2379
|
+
Most day-to-day settings are editable live in the dashboard
|
|
2380
|
+
(Settings tab) and apply without a restart. Settings that need a
|
|
2381
|
+
restart show a one-click "apply & restart" banner.
|
|
2382
|
+
|
|
2383
|
+
Common runtime settings: recall depth (top_k), memory injection on/off,
|
|
2384
|
+
stale-memory suppression, idle consolidation, PII redaction, reranker.
|
|
2385
|
+
""",
|
|
2386
|
+
"self-heal": """\
|
|
2387
|
+
Self-healing (v3.8.2)
|
|
2388
|
+
SLM repairs itself. On every start the daemon checks that all models
|
|
2389
|
+
and dependencies are present and re-downloads/installs the fixable ones
|
|
2390
|
+
in the background — you don't run anything.
|
|
2391
|
+
|
|
2392
|
+
See what's present/missing:
|
|
2393
|
+
slm doctor Full report with fix commands
|
|
2394
|
+
slm doctor --fix Auto-repair everything fixable, then report
|
|
2395
|
+
Dashboard → Help → System Health Live "what's missing" report
|
|
2396
|
+
|
|
2397
|
+
Big or opt-in pieces (the local LLM 'Ollama', the large compression
|
|
2398
|
+
model, PyTorch) are never installed without you — SLM shows the exact
|
|
2399
|
+
command instead.
|
|
2400
|
+
""",
|
|
2401
|
+
}
|
|
2402
|
+
# Aliases so common phrasings resolve to a topic.
|
|
2403
|
+
_HELP_TOPICS["health"] = _HELP_TOPICS["self-heal"]
|
|
2404
|
+
_HELP_TOPICS["selfheal"] = _HELP_TOPICS["self-heal"]
|
|
2405
|
+
_HELP_TOPICS["mode"] = _HELP_TOPICS["modes"]
|
|
2406
|
+
|
|
2407
|
+
|
|
2408
|
+
def all_help_commands() -> set[str]:
|
|
2409
|
+
"""Every command name listed in the super-help (drift-test hook)."""
|
|
2410
|
+
return {cmd for _title, rows in _COMMAND_GROUPS for cmd, _desc in rows}
|
|
2411
|
+
|
|
2412
|
+
|
|
2413
|
+
def cmd_help(args: Namespace) -> None:
|
|
2414
|
+
"""Super-help: a grouped overview of every command, plus focused topics.
|
|
2415
|
+
|
|
2416
|
+
`slm help` → grouped command overview
|
|
2417
|
+
`slm help <topic>` → modes | config | self-heal
|
|
2418
|
+
"""
|
|
2419
|
+
topic = getattr(args, "topic", None)
|
|
2420
|
+
if topic:
|
|
2421
|
+
key = topic.strip().lower()
|
|
2422
|
+
text = _HELP_TOPICS.get(key)
|
|
2423
|
+
if text:
|
|
2424
|
+
print(text)
|
|
2425
|
+
else:
|
|
2426
|
+
print(f"No help topic '{topic}'. Available topics: "
|
|
2427
|
+
+ ", ".join(sorted(set(_HELP_TOPICS))))
|
|
2428
|
+
return
|
|
2429
|
+
|
|
2430
|
+
from superlocalmemory.cli.json_output import _get_version
|
|
2431
|
+
print(f"SuperLocalMemory V3 ({_get_version()}) — command overview")
|
|
2432
|
+
print("=" * 58)
|
|
2433
|
+
print("Run any command with -h for its options, e.g. slm recall -h\n")
|
|
2434
|
+
for title, rows in _COMMAND_GROUPS:
|
|
2435
|
+
print(f"{title}:")
|
|
2436
|
+
for cmd, desc in rows:
|
|
2437
|
+
print(f" {cmd:<16} {desc}")
|
|
2438
|
+
print()
|
|
2439
|
+
print("Health at a glance: slm doctor (auto-repair: slm doctor --fix)")
|
|
2440
|
+
print("Topics: slm help modes | slm help config | "
|
|
2441
|
+
"slm help self-heal")
|
|
2442
|
+
print("Docs: https://superlocalmemory.com")
|
|
2443
|
+
|
|
2444
|
+
|
|
2143
2445
|
def cmd_doctor(args: Namespace) -> None:
|
|
2144
2446
|
"""Comprehensive pre-flight check — verify everything works.
|
|
2145
2447
|
|
|
@@ -2177,6 +2479,34 @@ def cmd_doctor(args: Namespace) -> None:
|
|
|
2177
2479
|
print("=" * 50)
|
|
2178
2480
|
print()
|
|
2179
2481
|
|
|
2482
|
+
# v3.8.2 `--fix`: run the component healer (the SAME repair the daemon
|
|
2483
|
+
# self-heal performs) BEFORE the checks, so the report below reflects the
|
|
2484
|
+
# healed state. Re-downloads missing models / installs sqlite-vec; big or
|
|
2485
|
+
# opt-in items are left as manual fixes. Fail-open — never blocks doctor.
|
|
2486
|
+
if getattr(args, "fix", False):
|
|
2487
|
+
try:
|
|
2488
|
+
from superlocalmemory.core import component_healer
|
|
2489
|
+
from superlocalmemory.core.config import SLMConfig as _FixCfg
|
|
2490
|
+
try:
|
|
2491
|
+
_fcfg = _FixCfg.load()
|
|
2492
|
+
except Exception:
|
|
2493
|
+
_fcfg = None
|
|
2494
|
+
if not use_json:
|
|
2495
|
+
print("Auto-repair (--fix): repairing fixable components…")
|
|
2496
|
+
_fix_res = component_healer.heal_missing(
|
|
2497
|
+
_fcfg,
|
|
2498
|
+
on_progress=(None if use_json
|
|
2499
|
+
else (lambda k, m: print(f" [{k}] {m}"))),
|
|
2500
|
+
)
|
|
2501
|
+
if not use_json:
|
|
2502
|
+
print(
|
|
2503
|
+
f" repaired {_fix_res['healed']}/{_fix_res['attempted']} "
|
|
2504
|
+
f"(failed {_fix_res['failed']})\n"
|
|
2505
|
+
)
|
|
2506
|
+
except Exception as _fix_exc:
|
|
2507
|
+
if not use_json:
|
|
2508
|
+
print(f" auto-repair error: {_fix_exc}\n")
|
|
2509
|
+
|
|
2180
2510
|
# 1. Python version
|
|
2181
2511
|
v = sys.version_info
|
|
2182
2512
|
if v >= (3, 11):
|
|
@@ -2442,6 +2772,34 @@ def cmd_doctor(args: Namespace) -> None:
|
|
|
2442
2772
|
except Exception:
|
|
2443
2773
|
pass # advisory only — never fail doctor on this check
|
|
2444
2774
|
|
|
2775
|
+
# 12a. Component registry (v3.8.2) — models + optional vector/graph/
|
|
2776
|
+
# compression backends the older checks above did NOT cover
|
|
2777
|
+
# (embedder/reranker/compressor cache presence, sqlite-vec, lancedb,
|
|
2778
|
+
# cozo, llmlingua). Single source of truth shared with the daemon
|
|
2779
|
+
# self-heal and the dashboard "what's missing" report. Missing items
|
|
2780
|
+
# are advisory (WARN), never FAIL — the self-heal thread and
|
|
2781
|
+
# `slm doctor --fix` repair the auto-fixable ones. Runs BEFORE the
|
|
2782
|
+
# Optimize check so that check stays last (its ordering is pinned by
|
|
2783
|
+
# test_doctor_optimize).
|
|
2784
|
+
try:
|
|
2785
|
+
from superlocalmemory.core import component_registry as _cr
|
|
2786
|
+
try:
|
|
2787
|
+
from superlocalmemory.core.config import SLMConfig as _Cfg
|
|
2788
|
+
_dcfg = _Cfg.load()
|
|
2789
|
+
except Exception:
|
|
2790
|
+
_dcfg = None
|
|
2791
|
+
_already = {"python", "search_deps", "ollama"}
|
|
2792
|
+
for _c in _cr.probe_all(_dcfg):
|
|
2793
|
+
if _c.key in _already:
|
|
2794
|
+
continue # covered by checks 1/3/8 above — avoid duplicates
|
|
2795
|
+
_status = "PASS" if _c.status == _cr.STATUS_OK else "WARN"
|
|
2796
|
+
_detail = _c.detail or _c.status
|
|
2797
|
+
if _c.auto_fixable:
|
|
2798
|
+
_detail += " (auto-heals on daemon start)"
|
|
2799
|
+
_check(f"Component: {_c.label}", _status, _detail, _c.fix_cmd)
|
|
2800
|
+
except Exception as _cr_exc:
|
|
2801
|
+
_check("Component registry", "WARN", f"probe failed: {_cr_exc}")
|
|
2802
|
+
|
|
2445
2803
|
# 12. Optimize (Surface B) — reads daemon-persisted metrics (≤60s stale).
|
|
2446
2804
|
info = _gather_optimize_surface_b()
|
|
2447
2805
|
_enabled = info["enabled"]
|
|
@@ -82,6 +82,8 @@ _NO_DAEMON_COMMANDS = {
|
|
|
82
82
|
"optimize", "cache", "compress", "help-optimize",
|
|
83
83
|
# Bounded loops use an in-process engine store, not the daemon.
|
|
84
84
|
"loop",
|
|
85
|
+
# v3.8.2 super-help is pure text — never touch the daemon.
|
|
86
|
+
"help",
|
|
85
87
|
# Lifecycle orchestration must run before any global auto-start hook.
|
|
86
88
|
"serve", "restart",
|
|
87
89
|
}
|
|
@@ -283,6 +285,37 @@ def main() -> None:
|
|
|
283
285
|
db_scale_p.add_argument("--stage-id", help="Stage identifier required by verify/promote")
|
|
284
286
|
db_scale_p.add_argument("--backup-id", help="Backup identifier required by rollback")
|
|
285
287
|
|
|
288
|
+
db_reembed_p = db_sub.add_parser(
|
|
289
|
+
"reembed",
|
|
290
|
+
help="Backfill NULL embeddings (facts never embedded)",
|
|
291
|
+
)
|
|
292
|
+
db_reembed_p.add_argument(
|
|
293
|
+
"--missing-only",
|
|
294
|
+
action="store_true",
|
|
295
|
+
default=True,
|
|
296
|
+
dest="missing_only",
|
|
297
|
+
help="Only embed facts with NULL embedding (default and only mode)",
|
|
298
|
+
)
|
|
299
|
+
db_reembed_p.add_argument(
|
|
300
|
+
"--all-profiles",
|
|
301
|
+
action="store_true",
|
|
302
|
+
default=False,
|
|
303
|
+
dest="all_profiles",
|
|
304
|
+
help="Process all profiles (default: active profile only)",
|
|
305
|
+
)
|
|
306
|
+
db_reembed_p.add_argument(
|
|
307
|
+
"--limit",
|
|
308
|
+
type=int,
|
|
309
|
+
default=None,
|
|
310
|
+
metavar="N",
|
|
311
|
+
help="Maximum facts to embed per run (default: no limit)",
|
|
312
|
+
)
|
|
313
|
+
db_reembed_p.add_argument(
|
|
314
|
+
"--json",
|
|
315
|
+
action="store_true",
|
|
316
|
+
help="Output structured JSON",
|
|
317
|
+
)
|
|
318
|
+
|
|
286
319
|
# -- Mesh inspection (v3.7.9, M-03) --------------------------------
|
|
287
320
|
mesh_p = sub.add_parser("mesh", help="Inspect the local agent mesh (status/peers)")
|
|
288
321
|
mesh_p.add_argument(
|
|
@@ -327,9 +360,11 @@ def main() -> None:
|
|
|
327
360
|
)
|
|
328
361
|
recall_p.add_argument(
|
|
329
362
|
"--fast", action="store_true",
|
|
330
|
-
help="
|
|
331
|
-
"
|
|
332
|
-
"
|
|
363
|
+
help="Force-skip the internal agentic verification round (all six retrieval "
|
|
364
|
+
"channels + reranker still run). This is already the default (client-driven "
|
|
365
|
+
"agentic): SLM returns fast local results + confidence signals and lets the "
|
|
366
|
+
"calling LLM re-query on low confidence. Pass --fast to guarantee the fast "
|
|
367
|
+
"path even where the server is configured for internal agentic.",
|
|
333
368
|
)
|
|
334
369
|
# v3.6.15: shared memory is opt-in. Unset (None) → resolve the configured
|
|
335
370
|
# default (recall_include_global/shared, both False by default). Explicit
|
|
@@ -351,6 +386,15 @@ def main() -> None:
|
|
|
351
386
|
"--no-shared", dest="include_shared", action="store_false", default=None,
|
|
352
387
|
help="Exclude shared-scope facts from retrieval",
|
|
353
388
|
)
|
|
389
|
+
# v3.8.2 client-driven agentic: agents parsing --json should ACT on the
|
|
390
|
+
# confidence signals rather than expect a server-side LLM to reformulate.
|
|
391
|
+
recall_p.epilog = (
|
|
392
|
+
"AGENT GUIDANCE (--json): recall returns fast local results plus "
|
|
393
|
+
"confidence signals. If 'no_confident_match' is true or "
|
|
394
|
+
"'answer_confidence' is low, rewrite the query into 1-3 more specific "
|
|
395
|
+
"sub-queries and call recall again before concluding nothing was found. "
|
|
396
|
+
"Confident match -> use it directly."
|
|
397
|
+
)
|
|
354
398
|
|
|
355
399
|
forget_p = sub.add_parser("forget", help="Delete memories matching a query (fuzzy)")
|
|
356
400
|
forget_p.add_argument("query", nargs="?", default=None, help="Query to match for deletion. Optional with --dry-run (previews all memories).")
|
|
@@ -397,6 +441,21 @@ def main() -> None:
|
|
|
397
441
|
"--quick", action="store_true",
|
|
398
442
|
help="Run only the fast checks (deps + config); skip daemon/embedding probes",
|
|
399
443
|
)
|
|
444
|
+
doctor_p.add_argument(
|
|
445
|
+
"--fix", action="store_true",
|
|
446
|
+
help="Auto-repair fixable components (re-download missing models, "
|
|
447
|
+
"install sqlite-vec) before checking, then report",
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
# v3.8.2 super-help — grouped overview of every command + focused topics.
|
|
451
|
+
help_p = sub.add_parser(
|
|
452
|
+
"help",
|
|
453
|
+
help="Grouped overview of all commands + topics (modes, config, self-heal)",
|
|
454
|
+
)
|
|
455
|
+
help_p.add_argument(
|
|
456
|
+
"topic", nargs="?",
|
|
457
|
+
help="Optional topic: modes | config | self-heal",
|
|
458
|
+
)
|
|
400
459
|
|
|
401
460
|
# LLD-06 §6.6 — `slm wrap <agent> [args...]` activates the Optimize
|
|
402
461
|
# proxy for a specific agent. Supported agents: claude, claude-settings,
|