superlocalmemory 3.4.63 → 3.4.64

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 CHANGED
@@ -5,6 +5,29 @@ All notable changes to SuperLocalMemory V3 will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.4.64] - 2026-05-31 — Fix recall/trace endpoint (Recall Lab search)
9
+
10
+ The dashboard "Search memories" button (Recall Lab) calls `POST /api/v3/recall/trace`,
11
+ NOT `POST /api/search`. v3.4.63 fixed the wrong endpoint. This is the real fix.
12
+
13
+ ### Root Cause
14
+ `recall_trace()` called `WorkerPool.shared().recall()` — subprocess worker pool
15
+ that blocks the ASGI event loop and crashes (`Worker died`) after ~17s. The
16
+ 15s global fetch timeout in core.js fired first, aborting with "signal is aborted
17
+ without reason".
18
+
19
+ ### Fix
20
+ Same pattern as v3.4.63: `run_in_executor` + daemon engine + `fast=True`.
21
+ Synthesis removed (was using the crashed subprocess anyway).
22
+
23
+ ### Result
24
+ recall/trace: 7.2s cold, 1.1s warm. Zero browser aborts. No more "Worker died".
25
+
26
+ ### Changed
27
+ - `server/routes/v3_api.py`: `recall_trace` uses `run_in_executor` + daemon engine
28
+
29
+ ---
30
+
8
31
  ## [3.4.63] - 2026-05-31 — Dashboard search: fix async blocking + fast mode
9
32
 
10
33
  Fixes "signal is aborted without reason" in dashboard search (second root cause,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superlocalmemory",
3
- "version": "3.4.63",
3
+ "version": "3.4.64",
4
4
  "description": "Information-geometric agent memory with mathematical guarantees. 4-channel retrieval, Fisher-Rao similarity, zero-LLM mode, EU AI Act compliant. Works with Claude, Cursor, Windsurf, and 17+ AI tools.",
5
5
  "keywords": [
6
6
  "ai-memory",
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "superlocalmemory"
3
- version = "3.4.63"
3
+ version = "3.4.64"
4
4
  description = "Information-geometric agent memory with mathematical guarantees"
5
5
  readme = "README.md"
6
6
  license = {text = "AGPL-3.0-or-later"}
@@ -28,7 +28,7 @@ if "OMP_NUM_THREADS" not in os.environ:
28
28
  os.environ["OMP_NUM_THREADS"] = "2"
29
29
  # ---------------------------------------------------------------------------
30
30
 
31
- __version__ = "3.4.63"
31
+ __version__ = "3.4.64"
32
32
 
33
33
  _REQUIRED_VERSIONS = {
34
34
  "sentence_transformers": "5.3.0",
@@ -514,45 +514,60 @@ async def set_provider(request: Request):
514
514
 
515
515
  @router.post("/recall/trace")
516
516
  async def recall_trace(request: Request):
517
- """Recall with per-channel score breakdown."""
517
+ """Recall with per-channel score breakdown.
518
+
519
+ v3.4.64: Replaced WorkerPool.shared() (subprocess, blocks event loop,
520
+ worker crashes after ~15s) with daemon engine via run_in_executor.
521
+ Same fix as POST /api/search in v3.4.63.
522
+ """
523
+ import asyncio
524
+ import time as _time
518
525
  try:
519
526
  body = await request.json()
520
527
  query = body.get("query", "")
521
528
  limit = body.get("limit", 10)
522
529
 
523
- from superlocalmemory.core.worker_pool import WorkerPool
524
- pool = WorkerPool.shared()
525
- result = pool.recall(query, limit=limit)
526
-
527
- if not result.get("ok"):
528
- return JSONResponse(
529
- {"error": result.get("error", "Recall failed")},
530
- status_code=503,
531
- )
532
-
533
- # Optional: synthesize answer from results (Mode B/C only)
534
- synthesis = ""
535
- if body.get("synthesize") and result.get("results"):
536
- try:
537
- syn_result = pool.synthesize(query, result["results"][:5])
538
- synthesis = syn_result.get("synthesis", "") if syn_result.get("ok") else ""
539
- except Exception:
540
- pass
530
+ # Use daemon engine — already loaded, shares warm page cache.
531
+ # run_in_executor keeps event loop alive so browser doesn't abort.
532
+ from .helpers import get_engine_lazy
533
+ engine = get_engine_lazy(request.app.state)
534
+ if engine is None:
535
+ return JSONResponse({"error": "Engine not initialised"}, status_code=503)
536
+
537
+ loop = asyncio.get_event_loop()
538
+ t0 = _time.monotonic()
539
+ response = await loop.run_in_executor(
540
+ None,
541
+ lambda: engine.recall(query, limit=limit, fast=True),
542
+ )
543
+ elapsed_ms = round((_time.monotonic() - t0) * 1000, 1)
544
+
545
+ results = []
546
+ for r in response.results[:limit]:
547
+ results.append({
548
+ "fact_id": r.fact.fact_id,
549
+ "memory_id": getattr(r.fact, "memory_id", ""),
550
+ "content": r.fact.content[:300],
551
+ "score": round(r.score, 4),
552
+ "confidence": round(getattr(r, "confidence", 0.0), 4),
553
+ "channel_scores": getattr(r, "channel_scores", {}),
554
+ "created_at": getattr(r.fact, "created_at", ""),
555
+ })
541
556
 
542
557
  # Record learning signals (non-blocking, non-critical)
543
558
  try:
544
- _record_learning_signals(query, result.get("results", []))
559
+ _record_learning_signals(query, results)
545
560
  except Exception as _sig_exc:
546
561
  import logging as _log
547
562
  _log.getLogger(__name__).warning("Learning signal error: %s", _sig_exc)
548
563
 
549
564
  return {
550
565
  "query": query,
551
- "query_type": result.get("query_type", "unknown"),
552
- "result_count": result.get("result_count", 0),
553
- "retrieval_time_ms": result.get("retrieval_time_ms", 0),
554
- "results": result.get("results", []),
555
- "synthesis": synthesis,
566
+ "query_type": getattr(response, "query_type", "semantic"),
567
+ "result_count": len(results),
568
+ "retrieval_time_ms": elapsed_ms,
569
+ "results": results,
570
+ "synthesis": "",
556
571
  }
557
572
  except Exception as e:
558
573
  return JSONResponse({"error": str(e)}, status_code=500)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: superlocalmemory
3
- Version: 3.4.63
3
+ Version: 3.4.64
4
4
  Summary: Information-geometric agent memory with mathematical guarantees
5
5
  Author-email: Varun Pratap Bhardwaj <admin@superlocalmemory.com>
6
6
  License: AGPL-3.0-or-later