superlocalmemory 3.0.36 → 3.1.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/package.json +1 -1
- package/pyproject.toml +2 -1
- package/src/superlocalmemory/cli/commands.py +96 -0
- package/src/superlocalmemory/cli/main.py +13 -0
- package/src/superlocalmemory/core/engine.py +63 -0
- package/src/superlocalmemory/core/summarizer.py +4 -26
- package/src/superlocalmemory/hooks/claude_code_hooks.py +175 -0
- package/src/superlocalmemory/learning/consolidation_worker.py +289 -0
- package/src/superlocalmemory/learning/signals.py +326 -0
- package/src/superlocalmemory/llm/backbone.py +19 -25
- package/src/superlocalmemory/mcp/resources.py +26 -1
- package/src/superlocalmemory/mcp/server.py +2 -0
- package/src/superlocalmemory/mcp/tools_active.py +205 -0
- package/src/superlocalmemory/mcp/tools_core.py +51 -0
- package/src/superlocalmemory/server/routes/behavioral.py +20 -5
- package/src/superlocalmemory/server/routes/learning.py +69 -12
- package/src/superlocalmemory/server/routes/stats.py +33 -5
- package/src/superlocalmemory/server/routes/v3_api.py +93 -0
|
@@ -339,6 +339,13 @@ async def recall_trace(request: Request):
|
|
|
339
339
|
except Exception:
|
|
340
340
|
pass
|
|
341
341
|
|
|
342
|
+
# Record learning signals (non-blocking, non-critical)
|
|
343
|
+
try:
|
|
344
|
+
_record_learning_signals(query, result.get("results", []))
|
|
345
|
+
except Exception as _sig_exc:
|
|
346
|
+
import logging as _log
|
|
347
|
+
_log.getLogger(__name__).warning("Learning signal error: %s", _sig_exc)
|
|
348
|
+
|
|
342
349
|
return {
|
|
343
350
|
"query": query,
|
|
344
351
|
"query_type": result.get("query_type", "unknown"),
|
|
@@ -351,6 +358,44 @@ async def recall_trace(request: Request):
|
|
|
351
358
|
return JSONResponse({"error": str(e)}, status_code=500)
|
|
352
359
|
|
|
353
360
|
|
|
361
|
+
def _record_learning_signals(query: str, results: list) -> None:
|
|
362
|
+
"""Record feedback + co-retrieval + confidence boost for any recall."""
|
|
363
|
+
from pathlib import Path
|
|
364
|
+
from superlocalmemory.core.config import SLMConfig
|
|
365
|
+
|
|
366
|
+
slm_dir = Path.home() / ".superlocalmemory"
|
|
367
|
+
config = SLMConfig.load()
|
|
368
|
+
pid = config.active_profile
|
|
369
|
+
fact_ids = [r.get("fact_id", "") for r in results[:10] if r.get("fact_id")]
|
|
370
|
+
if not fact_ids:
|
|
371
|
+
return
|
|
372
|
+
|
|
373
|
+
try:
|
|
374
|
+
from superlocalmemory.learning.feedback import FeedbackCollector
|
|
375
|
+
collector = FeedbackCollector(slm_dir / "learning.db")
|
|
376
|
+
collector.record_implicit(
|
|
377
|
+
profile_id=pid, query=query,
|
|
378
|
+
fact_ids_returned=fact_ids, fact_ids_available=fact_ids,
|
|
379
|
+
)
|
|
380
|
+
except Exception:
|
|
381
|
+
pass
|
|
382
|
+
|
|
383
|
+
try:
|
|
384
|
+
from superlocalmemory.learning.signals import LearningSignals
|
|
385
|
+
signals = LearningSignals(slm_dir / "learning.db")
|
|
386
|
+
signals.record_co_retrieval(pid, fact_ids)
|
|
387
|
+
except Exception:
|
|
388
|
+
pass
|
|
389
|
+
|
|
390
|
+
try:
|
|
391
|
+
from superlocalmemory.learning.signals import LearningSignals
|
|
392
|
+
mem_db = str(slm_dir / "memory.db")
|
|
393
|
+
for fid in fact_ids[:5]:
|
|
394
|
+
LearningSignals.boost_confidence(mem_db, fid)
|
|
395
|
+
except Exception:
|
|
396
|
+
pass
|
|
397
|
+
|
|
398
|
+
|
|
354
399
|
# ── Trust Dashboard ──────────────────────────────────────────
|
|
355
400
|
|
|
356
401
|
@router.get("/trust/dashboard")
|
|
@@ -521,3 +566,51 @@ async def ide_connect(request: Request):
|
|
|
521
566
|
return {"results": results}
|
|
522
567
|
except Exception as e:
|
|
523
568
|
return JSONResponse({"error": str(e)}, status_code=500)
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
# ── Active Memory (V3.1) ────────────────────────────────────
|
|
572
|
+
|
|
573
|
+
@router.get("/learning/signals")
|
|
574
|
+
async def learning_signals():
|
|
575
|
+
"""Get zero-cost learning signal statistics."""
|
|
576
|
+
try:
|
|
577
|
+
from superlocalmemory.learning.signals import LearningSignals
|
|
578
|
+
from superlocalmemory.core.config import SLMConfig
|
|
579
|
+
from superlocalmemory.server.routes.helpers import DB_PATH
|
|
580
|
+
learning_db = DB_PATH.parent / "learning.db"
|
|
581
|
+
signals = LearningSignals(learning_db)
|
|
582
|
+
config = SLMConfig.load()
|
|
583
|
+
pid = config.active_profile
|
|
584
|
+
return {"success": True, **signals.get_signal_stats(pid)}
|
|
585
|
+
except Exception as exc:
|
|
586
|
+
return {"success": False, "error": str(exc)}
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
@router.post("/learning/consolidate")
|
|
590
|
+
async def run_consolidation(request: Request):
|
|
591
|
+
"""Run sleep-time consolidation. Body: {dry_run: true/false}."""
|
|
592
|
+
try:
|
|
593
|
+
body = await request.json()
|
|
594
|
+
dry_run = body.get("dry_run", False)
|
|
595
|
+
from superlocalmemory.learning.consolidation_worker import ConsolidationWorker
|
|
596
|
+
from superlocalmemory.core.config import SLMConfig
|
|
597
|
+
from superlocalmemory.server.routes.helpers import DB_PATH
|
|
598
|
+
worker = ConsolidationWorker(
|
|
599
|
+
memory_db=str(DB_PATH),
|
|
600
|
+
learning_db=str(DB_PATH.parent / "learning.db"),
|
|
601
|
+
)
|
|
602
|
+
config = SLMConfig.load()
|
|
603
|
+
stats = worker.run(config.active_profile, dry_run=dry_run)
|
|
604
|
+
return {"success": True, **stats}
|
|
605
|
+
except Exception as exc:
|
|
606
|
+
return {"success": False, "error": str(exc)}
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
@router.get("/hooks/status")
|
|
610
|
+
async def hooks_status():
|
|
611
|
+
"""Check if Claude Code hooks are installed."""
|
|
612
|
+
try:
|
|
613
|
+
from superlocalmemory.hooks.claude_code_hooks import check_status
|
|
614
|
+
return {"success": True, **check_status()}
|
|
615
|
+
except Exception as exc:
|
|
616
|
+
return {"success": False, "error": str(exc)}
|