superlocalmemory 3.0.5 → 3.0.7

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/README.md CHANGED
@@ -85,13 +85,35 @@ Query ──► Strategy Classifier ──► 4 Parallel Channels:
85
85
 
86
86
  ---
87
87
 
88
+ ## Prerequisites
89
+
90
+ | Requirement | Version | Why |
91
+ |:-----------|:--------|:----|
92
+ | **Node.js** | 14+ | npm package manager |
93
+ | **Python** | 3.11+ | V3 engine runtime |
94
+ | **pip** | Latest | Python dependency installer |
95
+
96
+ > All Python dependencies are installed automatically during `npm install`. You don't need to run pip manually. If any dependency fails, the installer shows clear instructions.
97
+
98
+ ---
99
+
88
100
  ## Quick Start
89
101
 
90
- ### Install via npm (recommended)
102
+ ### Install via npm (recommended — one command, everything included)
91
103
 
92
104
  ```bash
93
105
  npm install -g superlocalmemory
94
- slm setup
106
+ ```
107
+
108
+ This single command:
109
+ - Installs the V3 engine and CLI
110
+ - Auto-installs all Python dependencies (numpy, scipy, networkx, sentence-transformers, etc.)
111
+ - Creates the data directory at `~/.superlocalmemory/`
112
+ - Detects and guides V2 migration if applicable
113
+
114
+ Then configure:
115
+ ```bash
116
+ slm setup # Choose mode, configure provider
95
117
  ```
96
118
 
97
119
  ### Install via pip
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superlocalmemory",
3
- "version": "3.0.5",
3
+ "version": "3.0.7",
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",
@@ -2,9 +2,11 @@
2
2
  /**
3
3
  * SuperLocalMemory V3 - NPM Postinstall Script
4
4
  *
5
+ * ONE COMMAND INSTALL. Everything the user needs.
6
+ * Python deps auto-installed. Embeddings auto-downloaded.
7
+ *
5
8
  * Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
6
9
  * Licensed under MIT License
7
- * Repository: https://github.com/qualixar/superlocalmemory
8
10
  */
9
11
 
10
12
  const { spawnSync } = require('child_process');
@@ -13,7 +15,7 @@ const os = require('os');
13
15
  const fs = require('fs');
14
16
 
15
17
  console.log('\n════════════════════════════════════════════════════════════');
16
- console.log(' SuperLocalMemory V3 - Post-Installation');
18
+ console.log(' SuperLocalMemory V3 Post-Installation');
17
19
  console.log(' by Varun Pratap Bhardwaj / Qualixar');
18
20
  console.log(' https://github.com/qualixar/superlocalmemory');
19
21
  console.log('════════════════════════════════════════════════════════════\n');
@@ -29,77 +31,99 @@ if (!fs.existsSync(SLM_HOME)) {
29
31
 
30
32
  // --- Step 2: Find Python 3 ---
31
33
  function findPython() {
32
- const candidates = ['python3', 'python', '/opt/homebrew/bin/python3', '/usr/local/bin/python3', '/usr/bin/python3'];
34
+ const candidates = [
35
+ 'python3', 'python',
36
+ '/opt/homebrew/bin/python3', '/usr/local/bin/python3', '/usr/bin/python3',
37
+ ];
33
38
  if (os.platform() === 'win32') candidates.push('py -3');
34
39
  for (const cmd of candidates) {
35
40
  try {
36
41
  const parts = cmd.split(' ');
37
- const r = spawnSync(parts[0], [...parts.slice(1), '--version'], { stdio: 'pipe', timeout: 5000 });
38
- if (r.status === 0 && (r.stdout || '').toString().includes('3.')) return cmd;
42
+ const r = spawnSync(parts[0], [...parts.slice(1), '--version'], {
43
+ stdio: 'pipe', timeout: 5000,
44
+ env: { ...process.env, PATH: '/opt/homebrew/bin:/usr/local/bin:/usr/bin:' + (process.env.PATH || '') },
45
+ });
46
+ if (r.status === 0 && (r.stdout || '').toString().includes('3.')) return parts;
39
47
  } catch (e) { /* next */ }
40
48
  }
41
49
  return null;
42
50
  }
43
51
 
44
- const python = findPython();
45
- if (!python) {
46
- console.log('⚠ Python 3.11+ not found. Install from https://python.org/downloads/');
52
+ const pythonParts = findPython();
53
+ if (!pythonParts) {
54
+ console.log('');
55
+ console.log('╔══════════════════════════════════════════════════════════╗');
56
+ console.log('║ ⚠ Python 3.11+ Required ║');
57
+ console.log('╚══════════════════════════════════════════════════════════╝');
58
+ console.log('');
59
+ console.log(' SuperLocalMemory V3 requires Python 3.11+');
60
+ console.log(' Install from: https://python.org/downloads/');
47
61
  console.log(' After installing Python, run: slm setup');
62
+ console.log('');
48
63
  process.exit(0); // Don't fail npm install
49
64
  }
50
- console.log('✓ Found Python: ' + python);
65
+ console.log('✓ Found Python: ' + pythonParts.join(' '));
66
+
67
+ // --- Step 3: Install ALL Python dependencies ---
68
+ console.log('\nInstalling Python dependencies (this may take 1-2 minutes)...\n');
69
+
70
+ // Detect if --user or --break-system-packages is needed
71
+ function pipInstall(packages, label) {
72
+ // Try normal install first
73
+ let result = spawnSync(pythonParts[0], [
74
+ ...pythonParts.slice(1), '-m', 'pip', 'install', '--quiet', '--disable-pip-version-check',
75
+ ...packages,
76
+ ], { stdio: 'pipe', timeout: 300000, env: { ...process.env, PATH: '/opt/homebrew/bin:/usr/local/bin:/usr/bin:' + (process.env.PATH || '') } });
51
77
 
52
- // --- Step 3: Install Python dependencies ---
53
- console.log('\nInstalling Python dependencies...');
54
- const PKG_ROOT = path.join(__dirname, '..');
55
- const requirementsFile = path.join(PKG_ROOT, 'src', 'superlocalmemory', 'requirements-install.txt');
78
+ if (result.status === 0) return true;
56
79
 
57
- // Create a minimal requirements file for core operation
80
+ // If PEP 668 blocks it, try --user
81
+ const stderr = (result.stderr || '').toString();
82
+ if (stderr.includes('externally-managed') || stderr.includes('PEP 668')) {
83
+ result = spawnSync(pythonParts[0], [
84
+ ...pythonParts.slice(1), '-m', 'pip', 'install', '--quiet', '--disable-pip-version-check',
85
+ '--user', ...packages,
86
+ ], { stdio: 'pipe', timeout: 300000, env: { ...process.env, PATH: '/opt/homebrew/bin:/usr/local/bin:/usr/bin:' + (process.env.PATH || '') } });
87
+ if (result.status === 0) return true;
88
+
89
+ // Last resort: --break-system-packages
90
+ result = spawnSync(pythonParts[0], [
91
+ ...pythonParts.slice(1), '-m', 'pip', 'install', '--quiet', '--disable-pip-version-check',
92
+ '--break-system-packages', ...packages,
93
+ ], { stdio: 'pipe', timeout: 300000, env: { ...process.env, PATH: '/opt/homebrew/bin:/usr/local/bin:/usr/bin:' + (process.env.PATH || '') } });
94
+ return result.status === 0;
95
+ }
96
+
97
+ return false;
98
+ }
99
+
100
+ // Core dependencies (REQUIRED — product won't work without these)
58
101
  const coreDeps = [
59
- 'numpy>=1.26.0',
60
- 'scipy>=1.12.0',
61
- 'networkx>=3.0',
62
- 'httpx>=0.24.0',
63
- 'python-dateutil>=2.9.0',
64
- 'rank-bm25>=0.2.2',
65
- 'vaderSentiment>=3.3.2',
66
- ].join('\n');
67
-
68
- // Write temp requirements file
69
- const tmpReq = path.join(SLM_HOME, '.install-requirements.txt');
70
- fs.writeFileSync(tmpReq, coreDeps);
71
-
72
- const pythonParts = python.split(' ');
73
- const pipResult = spawnSync(pythonParts[0], [
74
- ...pythonParts.slice(1), '-m', 'pip', 'install', '--quiet', '--disable-pip-version-check',
75
- '-r', tmpReq,
76
- ], { stdio: 'inherit', timeout: 120000 });
77
-
78
- if (pipResult.status === 0) {
79
- console.log('✓ Core Python dependencies installed');
102
+ 'numpy>=1.26.0', 'scipy>=1.12.0', 'networkx>=3.0',
103
+ 'httpx>=0.24.0', 'python-dateutil>=2.9.0',
104
+ 'rank-bm25>=0.2.2', 'vaderSentiment>=3.3.2',
105
+ ];
106
+
107
+ if (pipInstall(coreDeps, 'core')) {
108
+ console.log('✓ Core dependencies installed (math, search, NLP)');
80
109
  } else {
81
- console.log('⚠ Some Python dependencies failed to install.');
82
- console.log(' Run manually: ' + python + ' -m pip install numpy scipy networkx httpx python-dateutil rank-bm25 vaderSentiment');
110
+ console.log('⚠ Core dependency installation failed.');
111
+ console.log(' Run manually: pip install ' + coreDeps.join(' '));
83
112
  }
84
113
 
85
- // Clean up temp file
86
- try { fs.unlinkSync(tmpReq); } catch (e) { /* ok */ }
114
+ // Search dependencies (IMPORTANT — enables semantic search, 4-channel retrieval)
115
+ const searchDeps = ['sentence-transformers>=2.5.0', 'geoopt>=0.5.0'];
87
116
 
88
- // --- Step 4: Optional search dependencies (sentence-transformers) ---
89
- console.log('\nChecking optional search dependencies...');
90
- const stCheck = spawnSync(pythonParts[0], [
91
- ...pythonParts.slice(1), '-c', 'import sentence_transformers; print("ok")',
92
- ], { stdio: 'pipe', timeout: 10000 });
93
-
94
- if (stCheck.status === 0) {
95
- console.log('✓ sentence-transformers already installed (semantic search enabled)');
117
+ console.log('\nInstalling semantic search engine (downloads ~500MB on first use)...');
118
+ if (pipInstall(searchDeps, 'search')) {
119
+ console.log('✓ Semantic search engine installed (sentence-transformers + Fisher-Rao)');
96
120
  } else {
97
- console.log(' sentence-transformers not installed (BM25-only search mode)');
98
- console.log(' For semantic search, run: ' + python + ' -m pip install sentence-transformers');
99
- console.log(' This downloads ~1.5GB of ML models on first use.');
121
+ console.log(' Semantic search installation failed (BM25 keyword search still works).');
122
+ console.log(' For full 4-channel retrieval, run:');
123
+ console.log(' pip install sentence-transformers geoopt');
100
124
  }
101
125
 
102
- // --- Step 5: Detect V2 installation ---
126
+ // --- Step 4: Detect V2 installation ---
103
127
  const V2_HOME = path.join(os.homedir(), '.claude-memory');
104
128
  if (fs.existsSync(V2_HOME) && fs.existsSync(path.join(V2_HOME, 'memory.db'))) {
105
129
  console.log('');
@@ -125,5 +149,10 @@ console.log(' slm status # Check system status');
125
149
  console.log(' slm remember "..." # Store a memory');
126
150
  console.log(' slm recall "..." # Search memories');
127
151
  console.log('');
128
- console.log(' Documentation: https://github.com/qualixar/superlocalmemory/wiki');
152
+ console.log(' Prerequisites satisfied:');
153
+ console.log(' ✓ Python 3.11+');
154
+ console.log(' ✓ Core math & search libraries');
155
+ console.log(' ✓ Data directory (~/.superlocalmemory/)');
156
+ console.log('');
157
+ console.log(' Docs: https://github.com/qualixar/superlocalmemory/wiki');
129
158
  console.log('════════════════════════════════════════════════════════════\n');
@@ -198,7 +198,7 @@ class EmbeddingService:
198
198
  self._available = False
199
199
  return
200
200
  model = SentenceTransformer(
201
- self._config.model_name, trust_remote_code=False,
201
+ self._config.model_name, trust_remote_code=True,
202
202
  )
203
203
  actual_dim = model.get_sentence_embedding_dimension()
204
204
  if actual_dim != self._config.dimension:
@@ -302,6 +302,33 @@ class V2Migrator:
302
302
  conn.commit()
303
303
  except Exception:
304
304
  pass # Schema handles this on engine init
305
+ # Step 4b: Convert V2 memories → V3 atomic_facts
306
+ try:
307
+ now = datetime.now(UTC).isoformat()
308
+ rows = conn.execute("SELECT memory_id, profile_id, content, created_at FROM memories").fetchall()
309
+ converted = 0
310
+ for row in rows:
311
+ mid, pid, content, created = row[0], row[1], row[2], row[3]
312
+ if not content or not content.strip():
313
+ continue
314
+ fid = f"v2_fact_{mid}"
315
+ conn.execute(
316
+ "INSERT OR IGNORE INTO atomic_facts "
317
+ "(fact_id, memory_id, profile_id, content, fact_type, "
318
+ " entities_json, canonical_entities_json, confidence, importance, "
319
+ " evidence_count, access_count, source_turn_ids_json, session_id, "
320
+ " lifecycle, emotional_valence, emotional_arousal, signal_type, created_at) "
321
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
322
+ (fid, mid, pid or "default", content, "factual",
323
+ "[]", "[]", 0.8, 0.5, 1, 0, "[]", "",
324
+ "active", 0.0, 0.0, "factual", created or now),
325
+ )
326
+ converted += 1
327
+ conn.commit()
328
+ stats["steps"].append(f"Converted {converted} V2 memories to V3 facts")
329
+ except Exception as exc:
330
+ stats["steps"].append(f"V2 conversion partial: {exc}")
331
+
305
332
  conn.close()
306
333
  stats["steps"].append("Created V3 schema")
307
334