superlocalmemory 2.3.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/ATTRIBUTION.md +140 -0
- package/CHANGELOG.md +1749 -0
- package/LICENSE +21 -0
- package/README.md +600 -0
- package/bin/aider-smart +72 -0
- package/bin/slm +202 -0
- package/bin/slm-npm +73 -0
- package/bin/slm.bat +195 -0
- package/bin/slm.cmd +10 -0
- package/bin/superlocalmemoryv2:list +3 -0
- package/bin/superlocalmemoryv2:profile +3 -0
- package/bin/superlocalmemoryv2:recall +3 -0
- package/bin/superlocalmemoryv2:remember +3 -0
- package/bin/superlocalmemoryv2:reset +3 -0
- package/bin/superlocalmemoryv2:status +3 -0
- package/completions/slm.bash +58 -0
- package/completions/slm.zsh +76 -0
- package/configs/antigravity-mcp.json +13 -0
- package/configs/chatgpt-desktop-mcp.json +7 -0
- package/configs/claude-desktop-mcp.json +15 -0
- package/configs/codex-mcp.toml +13 -0
- package/configs/cody-commands.json +29 -0
- package/configs/continue-mcp.yaml +14 -0
- package/configs/continue-skills.yaml +26 -0
- package/configs/cursor-mcp.json +15 -0
- package/configs/gemini-cli-mcp.json +11 -0
- package/configs/jetbrains-mcp.json +11 -0
- package/configs/opencode-mcp.json +12 -0
- package/configs/perplexity-mcp.json +9 -0
- package/configs/vscode-copilot-mcp.json +12 -0
- package/configs/windsurf-mcp.json +16 -0
- package/configs/zed-mcp.json +12 -0
- package/docs/ARCHITECTURE.md +877 -0
- package/docs/CLI-COMMANDS-REFERENCE.md +425 -0
- package/docs/COMPETITIVE-ANALYSIS.md +210 -0
- package/docs/COMPRESSION-README.md +390 -0
- package/docs/GRAPH-ENGINE.md +503 -0
- package/docs/MCP-MANUAL-SETUP.md +720 -0
- package/docs/MCP-TROUBLESHOOTING.md +787 -0
- package/docs/PATTERN-LEARNING.md +363 -0
- package/docs/PROFILES-GUIDE.md +453 -0
- package/docs/RESET-GUIDE.md +353 -0
- package/docs/SEARCH-ENGINE-V2.2.0.md +748 -0
- package/docs/SEARCH-INTEGRATION-GUIDE.md +502 -0
- package/docs/UI-SERVER.md +254 -0
- package/docs/UNIVERSAL-INTEGRATION.md +432 -0
- package/docs/V2.2.0-OPTIONAL-SEARCH.md +666 -0
- package/docs/WINDOWS-INSTALL-README.txt +34 -0
- package/docs/WINDOWS-POST-INSTALL.txt +45 -0
- package/docs/example_graph_usage.py +148 -0
- package/hooks/memory-list-skill.js +130 -0
- package/hooks/memory-profile-skill.js +284 -0
- package/hooks/memory-recall-skill.js +109 -0
- package/hooks/memory-remember-skill.js +127 -0
- package/hooks/memory-reset-skill.js +274 -0
- package/install-skills.sh +436 -0
- package/install.ps1 +417 -0
- package/install.sh +755 -0
- package/mcp_server.py +585 -0
- package/package.json +94 -0
- package/requirements-core.txt +24 -0
- package/requirements.txt +10 -0
- package/scripts/postinstall.js +126 -0
- package/scripts/preuninstall.js +57 -0
- package/skills/slm-build-graph/SKILL.md +423 -0
- package/skills/slm-list-recent/SKILL.md +348 -0
- package/skills/slm-recall/SKILL.md +325 -0
- package/skills/slm-remember/SKILL.md +194 -0
- package/skills/slm-status/SKILL.md +363 -0
- package/skills/slm-switch-profile/SKILL.md +442 -0
- package/src/__pycache__/cache_manager.cpython-312.pyc +0 -0
- package/src/__pycache__/embedding_engine.cpython-312.pyc +0 -0
- package/src/__pycache__/graph_engine.cpython-312.pyc +0 -0
- package/src/__pycache__/hnsw_index.cpython-312.pyc +0 -0
- package/src/__pycache__/hybrid_search.cpython-312.pyc +0 -0
- package/src/__pycache__/memory-profiles.cpython-312.pyc +0 -0
- package/src/__pycache__/memory-reset.cpython-312.pyc +0 -0
- package/src/__pycache__/memory_compression.cpython-312.pyc +0 -0
- package/src/__pycache__/memory_store_v2.cpython-312.pyc +0 -0
- package/src/__pycache__/migrate_v1_to_v2.cpython-312.pyc +0 -0
- package/src/__pycache__/pattern_learner.cpython-312.pyc +0 -0
- package/src/__pycache__/query_optimizer.cpython-312.pyc +0 -0
- package/src/__pycache__/search_engine_v2.cpython-312.pyc +0 -0
- package/src/__pycache__/setup_validator.cpython-312.pyc +0 -0
- package/src/__pycache__/tree_manager.cpython-312.pyc +0 -0
- package/src/cache_manager.py +520 -0
- package/src/embedding_engine.py +671 -0
- package/src/graph_engine.py +970 -0
- package/src/hnsw_index.py +626 -0
- package/src/hybrid_search.py +693 -0
- package/src/memory-profiles.py +518 -0
- package/src/memory-reset.py +485 -0
- package/src/memory_compression.py +999 -0
- package/src/memory_store_v2.py +1088 -0
- package/src/migrate_v1_to_v2.py +638 -0
- package/src/pattern_learner.py +898 -0
- package/src/query_optimizer.py +513 -0
- package/src/search_engine_v2.py +403 -0
- package/src/setup_validator.py +479 -0
- package/src/tree_manager.py +720 -0
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
SuperLocalMemory V2 - Intelligent Local Memory System
|
|
4
|
+
Copyright (c) 2026 Varun Pratap Bhardwaj
|
|
5
|
+
Licensed under MIT License
|
|
6
|
+
|
|
7
|
+
Repository: https://github.com/varun369/SuperLocalMemoryV2
|
|
8
|
+
Author: Varun Pratap Bhardwaj (Solution Architect)
|
|
9
|
+
|
|
10
|
+
NOTICE: This software is protected by MIT License.
|
|
11
|
+
Attribution must be preserved in all copies or derivatives.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
"""
|
|
15
|
+
SuperLocalMemory V2 - Reset & Reinitialize Utility
|
|
16
|
+
|
|
17
|
+
Provides safe ways to reset the memory system:
|
|
18
|
+
1. Soft reset - Clear memories but keep schema
|
|
19
|
+
2. Hard reset - Delete everything and reinitialize
|
|
20
|
+
3. Selective reset - Clear specific layers only
|
|
21
|
+
4. Backup & reset - Always create backup first
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import sqlite3
|
|
25
|
+
import shutil
|
|
26
|
+
import os
|
|
27
|
+
import sys
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
from datetime import datetime
|
|
30
|
+
import argparse
|
|
31
|
+
|
|
32
|
+
MEMORY_DIR = Path.home() / ".claude-memory"
|
|
33
|
+
DB_PATH = MEMORY_DIR / "memory.db"
|
|
34
|
+
BACKUP_DIR = MEMORY_DIR / "backups"
|
|
35
|
+
VENV_PATH = MEMORY_DIR / "venv"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class MemoryReset:
|
|
39
|
+
def __init__(self, auto_backup=True):
|
|
40
|
+
self.db_path = DB_PATH
|
|
41
|
+
self.backup_dir = BACKUP_DIR
|
|
42
|
+
self.auto_backup = auto_backup
|
|
43
|
+
|
|
44
|
+
def create_backup(self) -> str:
|
|
45
|
+
"""Create timestamped backup before any reset operation."""
|
|
46
|
+
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
|
|
47
|
+
backup_file = self.backup_dir / f"pre-reset-{timestamp}.db"
|
|
48
|
+
|
|
49
|
+
self.backup_dir.mkdir(exist_ok=True)
|
|
50
|
+
|
|
51
|
+
if self.db_path.exists():
|
|
52
|
+
shutil.copy2(self.db_path, backup_file)
|
|
53
|
+
print(f"✓ Backup created: {backup_file}")
|
|
54
|
+
return str(backup_file)
|
|
55
|
+
else:
|
|
56
|
+
print("⚠ No database found to backup")
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
def soft_reset(self):
|
|
60
|
+
"""Clear all memories but keep V2 schema structure."""
|
|
61
|
+
print("\n" + "="*60)
|
|
62
|
+
print("SOFT RESET - Clear Memories, Keep Schema")
|
|
63
|
+
print("="*60)
|
|
64
|
+
|
|
65
|
+
if self.auto_backup:
|
|
66
|
+
self.create_backup()
|
|
67
|
+
|
|
68
|
+
conn = sqlite3.connect(self.db_path)
|
|
69
|
+
cursor = conn.cursor()
|
|
70
|
+
|
|
71
|
+
# Delete all data from tables (keeps schema)
|
|
72
|
+
tables = [
|
|
73
|
+
'pattern_examples',
|
|
74
|
+
'identity_patterns',
|
|
75
|
+
'memory_archive',
|
|
76
|
+
'graph_edges',
|
|
77
|
+
'graph_clusters',
|
|
78
|
+
'graph_nodes',
|
|
79
|
+
'memory_tree',
|
|
80
|
+
'memories',
|
|
81
|
+
'sessions'
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
for table in tables:
|
|
85
|
+
try:
|
|
86
|
+
cursor.execute(f'DELETE FROM {table}')
|
|
87
|
+
count = cursor.rowcount
|
|
88
|
+
print(f" ✓ Cleared {table}: {count} rows deleted")
|
|
89
|
+
except sqlite3.OperationalError as e:
|
|
90
|
+
print(f" - Skipped {table}: {e}")
|
|
91
|
+
|
|
92
|
+
# Reset sequences
|
|
93
|
+
cursor.execute('DELETE FROM sqlite_sequence')
|
|
94
|
+
print(f" ✓ Reset auto-increment sequences")
|
|
95
|
+
|
|
96
|
+
conn.commit()
|
|
97
|
+
conn.close()
|
|
98
|
+
|
|
99
|
+
print("\n✅ Soft reset complete!")
|
|
100
|
+
print(" Schema preserved, all memories cleared")
|
|
101
|
+
print(" You can now add new memories to clean system")
|
|
102
|
+
|
|
103
|
+
def hard_reset(self):
|
|
104
|
+
"""Delete database completely and reinitialize with V2 schema."""
|
|
105
|
+
print("\n" + "="*60)
|
|
106
|
+
print("HARD RESET - Delete Everything & Reinitialize")
|
|
107
|
+
print("="*60)
|
|
108
|
+
|
|
109
|
+
if self.auto_backup:
|
|
110
|
+
self.create_backup()
|
|
111
|
+
|
|
112
|
+
# Delete database file
|
|
113
|
+
if self.db_path.exists():
|
|
114
|
+
self.db_path.unlink()
|
|
115
|
+
print(f" ✓ Deleted database: {self.db_path}")
|
|
116
|
+
|
|
117
|
+
# Reinitialize with V2 schema
|
|
118
|
+
print("\n Reinitializing V2 schema...")
|
|
119
|
+
self._initialize_v2_schema()
|
|
120
|
+
|
|
121
|
+
print("\n✅ Hard reset complete!")
|
|
122
|
+
print(" Fresh V2 database created")
|
|
123
|
+
print(" Ready for new memories")
|
|
124
|
+
|
|
125
|
+
def layer_reset(self, layers: list):
|
|
126
|
+
"""Reset specific layers only."""
|
|
127
|
+
print("\n" + "="*60)
|
|
128
|
+
print(f"LAYER RESET - Clearing Layers: {', '.join(layers)}")
|
|
129
|
+
print("="*60)
|
|
130
|
+
|
|
131
|
+
if self.auto_backup:
|
|
132
|
+
self.create_backup()
|
|
133
|
+
|
|
134
|
+
conn = sqlite3.connect(self.db_path)
|
|
135
|
+
cursor = conn.cursor()
|
|
136
|
+
|
|
137
|
+
layer_tables = {
|
|
138
|
+
'graph': ['graph_edges', 'graph_clusters', 'graph_nodes'],
|
|
139
|
+
'patterns': ['identity_patterns', 'pattern_examples'],
|
|
140
|
+
'tree': ['memory_tree'],
|
|
141
|
+
'archive': ['memory_archive']
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
for layer in layers:
|
|
145
|
+
if layer in layer_tables:
|
|
146
|
+
print(f"\n Clearing Layer: {layer.upper()}")
|
|
147
|
+
for table in layer_tables[layer]:
|
|
148
|
+
try:
|
|
149
|
+
cursor.execute(f'DELETE FROM {table}')
|
|
150
|
+
count = cursor.rowcount
|
|
151
|
+
print(f" ✓ Cleared {table}: {count} rows")
|
|
152
|
+
except sqlite3.OperationalError as e:
|
|
153
|
+
print(f" - Skipped {table}: {e}")
|
|
154
|
+
|
|
155
|
+
# Clear related columns in memories table
|
|
156
|
+
if layer == 'graph':
|
|
157
|
+
cursor.execute('UPDATE memories SET cluster_id = NULL')
|
|
158
|
+
print(f" ✓ Cleared cluster_id from memories")
|
|
159
|
+
elif layer == 'tree':
|
|
160
|
+
cursor.execute('UPDATE memories SET parent_id = NULL, tree_path = NULL, depth = 0')
|
|
161
|
+
print(f" ✓ Cleared tree fields from memories")
|
|
162
|
+
else:
|
|
163
|
+
print(f" ⚠ Unknown layer: {layer}")
|
|
164
|
+
|
|
165
|
+
conn.commit()
|
|
166
|
+
conn.close()
|
|
167
|
+
|
|
168
|
+
print("\n✅ Layer reset complete!")
|
|
169
|
+
|
|
170
|
+
def _initialize_v2_schema(self):
|
|
171
|
+
"""Initialize fresh V2 database schema."""
|
|
172
|
+
conn = sqlite3.connect(self.db_path)
|
|
173
|
+
cursor = conn.cursor()
|
|
174
|
+
|
|
175
|
+
# Layer 1: Memories table
|
|
176
|
+
cursor.execute('''
|
|
177
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
178
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
179
|
+
content TEXT NOT NULL,
|
|
180
|
+
summary TEXT,
|
|
181
|
+
project_path TEXT,
|
|
182
|
+
project_name TEXT,
|
|
183
|
+
tags TEXT,
|
|
184
|
+
category TEXT,
|
|
185
|
+
memory_type TEXT DEFAULT 'session',
|
|
186
|
+
importance INTEGER DEFAULT 5,
|
|
187
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
188
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
189
|
+
last_accessed TIMESTAMP,
|
|
190
|
+
access_count INTEGER DEFAULT 0,
|
|
191
|
+
content_hash TEXT UNIQUE,
|
|
192
|
+
parent_id INTEGER,
|
|
193
|
+
tree_path TEXT,
|
|
194
|
+
depth INTEGER DEFAULT 0,
|
|
195
|
+
cluster_id INTEGER,
|
|
196
|
+
tier INTEGER DEFAULT 1,
|
|
197
|
+
FOREIGN KEY (parent_id) REFERENCES memories(id) ON DELETE CASCADE
|
|
198
|
+
)
|
|
199
|
+
''')
|
|
200
|
+
print(" ✓ Created memories table")
|
|
201
|
+
|
|
202
|
+
# FTS5 index
|
|
203
|
+
cursor.execute('''
|
|
204
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts
|
|
205
|
+
USING fts5(content, summary, tags, content='memories', content_rowid='id')
|
|
206
|
+
''')
|
|
207
|
+
print(" ✓ Created FTS index")
|
|
208
|
+
|
|
209
|
+
# Layer 2: Tree
|
|
210
|
+
cursor.execute('''
|
|
211
|
+
CREATE TABLE IF NOT EXISTS memory_tree (
|
|
212
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
213
|
+
node_type TEXT NOT NULL,
|
|
214
|
+
name TEXT NOT NULL,
|
|
215
|
+
description TEXT,
|
|
216
|
+
parent_id INTEGER,
|
|
217
|
+
tree_path TEXT NOT NULL,
|
|
218
|
+
depth INTEGER DEFAULT 0,
|
|
219
|
+
memory_count INTEGER DEFAULT 0,
|
|
220
|
+
total_size INTEGER DEFAULT 0,
|
|
221
|
+
last_updated TIMESTAMP,
|
|
222
|
+
memory_id INTEGER,
|
|
223
|
+
FOREIGN KEY (parent_id) REFERENCES memory_tree(id) ON DELETE CASCADE,
|
|
224
|
+
FOREIGN KEY (memory_id) REFERENCES memories(id) ON DELETE CASCADE
|
|
225
|
+
)
|
|
226
|
+
''')
|
|
227
|
+
print(" ✓ Created memory_tree table")
|
|
228
|
+
|
|
229
|
+
# Layer 3: Graph
|
|
230
|
+
cursor.execute('''
|
|
231
|
+
CREATE TABLE IF NOT EXISTS graph_nodes (
|
|
232
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
233
|
+
memory_id INTEGER UNIQUE NOT NULL,
|
|
234
|
+
entities TEXT,
|
|
235
|
+
embedding_vector TEXT,
|
|
236
|
+
FOREIGN KEY (memory_id) REFERENCES memories(id) ON DELETE CASCADE
|
|
237
|
+
)
|
|
238
|
+
''')
|
|
239
|
+
|
|
240
|
+
cursor.execute('''
|
|
241
|
+
CREATE TABLE IF NOT EXISTS graph_edges (
|
|
242
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
243
|
+
source_memory_id INTEGER NOT NULL,
|
|
244
|
+
target_memory_id INTEGER NOT NULL,
|
|
245
|
+
relationship_type TEXT,
|
|
246
|
+
weight REAL DEFAULT 1.0,
|
|
247
|
+
shared_entities TEXT,
|
|
248
|
+
similarity_score REAL,
|
|
249
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
250
|
+
FOREIGN KEY (source_memory_id) REFERENCES memories(id) ON DELETE CASCADE,
|
|
251
|
+
FOREIGN KEY (target_memory_id) REFERENCES memories(id) ON DELETE CASCADE,
|
|
252
|
+
UNIQUE(source_memory_id, target_memory_id)
|
|
253
|
+
)
|
|
254
|
+
''')
|
|
255
|
+
|
|
256
|
+
cursor.execute('''
|
|
257
|
+
CREATE TABLE IF NOT EXISTS graph_clusters (
|
|
258
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
259
|
+
name TEXT NOT NULL,
|
|
260
|
+
description TEXT,
|
|
261
|
+
member_count INTEGER DEFAULT 0,
|
|
262
|
+
avg_importance REAL,
|
|
263
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
264
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
265
|
+
)
|
|
266
|
+
''')
|
|
267
|
+
print(" ✓ Created graph tables")
|
|
268
|
+
|
|
269
|
+
# Layer 4: Patterns
|
|
270
|
+
cursor.execute('''
|
|
271
|
+
CREATE TABLE IF NOT EXISTS identity_patterns (
|
|
272
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
273
|
+
pattern_type TEXT NOT NULL,
|
|
274
|
+
key TEXT NOT NULL,
|
|
275
|
+
value TEXT NOT NULL,
|
|
276
|
+
confidence REAL DEFAULT 0.5,
|
|
277
|
+
evidence_count INTEGER DEFAULT 1,
|
|
278
|
+
memory_ids TEXT,
|
|
279
|
+
category TEXT,
|
|
280
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
281
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
282
|
+
UNIQUE(pattern_type, key, category)
|
|
283
|
+
)
|
|
284
|
+
''')
|
|
285
|
+
|
|
286
|
+
cursor.execute('''
|
|
287
|
+
CREATE TABLE IF NOT EXISTS pattern_examples (
|
|
288
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
289
|
+
pattern_id INTEGER NOT NULL,
|
|
290
|
+
memory_id INTEGER NOT NULL,
|
|
291
|
+
example_text TEXT,
|
|
292
|
+
FOREIGN KEY (pattern_id) REFERENCES identity_patterns(id) ON DELETE CASCADE,
|
|
293
|
+
FOREIGN KEY (memory_id) REFERENCES memories(id) ON DELETE CASCADE
|
|
294
|
+
)
|
|
295
|
+
''')
|
|
296
|
+
print(" ✓ Created pattern tables")
|
|
297
|
+
|
|
298
|
+
# Archive table
|
|
299
|
+
cursor.execute('''
|
|
300
|
+
CREATE TABLE IF NOT EXISTS memory_archive (
|
|
301
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
302
|
+
memory_id INTEGER UNIQUE NOT NULL,
|
|
303
|
+
full_content TEXT NOT NULL,
|
|
304
|
+
archived_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
305
|
+
FOREIGN KEY (memory_id) REFERENCES memories(id) ON DELETE CASCADE
|
|
306
|
+
)
|
|
307
|
+
''')
|
|
308
|
+
print(" ✓ Created archive table")
|
|
309
|
+
|
|
310
|
+
# Sessions table
|
|
311
|
+
cursor.execute('''
|
|
312
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
313
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
314
|
+
session_id TEXT UNIQUE,
|
|
315
|
+
project_path TEXT,
|
|
316
|
+
started_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
317
|
+
ended_at TIMESTAMP,
|
|
318
|
+
summary TEXT
|
|
319
|
+
)
|
|
320
|
+
''')
|
|
321
|
+
print(" ✓ Created sessions table")
|
|
322
|
+
|
|
323
|
+
# System metadata
|
|
324
|
+
cursor.execute('''
|
|
325
|
+
CREATE TABLE IF NOT EXISTS system_metadata (
|
|
326
|
+
key TEXT PRIMARY KEY,
|
|
327
|
+
value TEXT,
|
|
328
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
329
|
+
)
|
|
330
|
+
''')
|
|
331
|
+
|
|
332
|
+
cursor.execute('''
|
|
333
|
+
INSERT OR REPLACE INTO system_metadata (key, value)
|
|
334
|
+
VALUES ('schema_version', '2.0.0')
|
|
335
|
+
''')
|
|
336
|
+
print(" ✓ Created metadata table")
|
|
337
|
+
|
|
338
|
+
# Create indexes
|
|
339
|
+
indexes = [
|
|
340
|
+
'CREATE INDEX IF NOT EXISTS idx_project ON memories(project_path)',
|
|
341
|
+
'CREATE INDEX IF NOT EXISTS idx_category ON memories(category)',
|
|
342
|
+
'CREATE INDEX IF NOT EXISTS idx_cluster ON memories(cluster_id)',
|
|
343
|
+
'CREATE INDEX IF NOT EXISTS idx_tree_path ON memories(tree_path)',
|
|
344
|
+
'CREATE INDEX IF NOT EXISTS idx_tier ON memories(tier)',
|
|
345
|
+
'CREATE INDEX IF NOT EXISTS idx_graph_source ON graph_edges(source_memory_id)',
|
|
346
|
+
'CREATE INDEX IF NOT EXISTS idx_graph_target ON graph_edges(target_memory_id)',
|
|
347
|
+
]
|
|
348
|
+
|
|
349
|
+
for idx_sql in indexes:
|
|
350
|
+
cursor.execute(idx_sql)
|
|
351
|
+
print(" ✓ Created indexes")
|
|
352
|
+
|
|
353
|
+
conn.commit()
|
|
354
|
+
conn.close()
|
|
355
|
+
|
|
356
|
+
def show_stats(self):
|
|
357
|
+
"""Show current database statistics."""
|
|
358
|
+
print("\n" + "="*60)
|
|
359
|
+
print("CURRENT MEMORY SYSTEM STATUS")
|
|
360
|
+
print("="*60)
|
|
361
|
+
|
|
362
|
+
if not self.db_path.exists():
|
|
363
|
+
print("\n⚠ No database found!")
|
|
364
|
+
print(" Run 'hard_reset' to initialize fresh V2 system")
|
|
365
|
+
return
|
|
366
|
+
|
|
367
|
+
conn = sqlite3.connect(self.db_path)
|
|
368
|
+
cursor = conn.cursor()
|
|
369
|
+
|
|
370
|
+
# Get counts for all tables
|
|
371
|
+
tables = {
|
|
372
|
+
'Memories': 'memories',
|
|
373
|
+
'Tree Nodes': 'memory_tree',
|
|
374
|
+
'Graph Nodes': 'graph_nodes',
|
|
375
|
+
'Graph Edges': 'graph_edges',
|
|
376
|
+
'Graph Clusters': 'graph_clusters',
|
|
377
|
+
'Identity Patterns': 'identity_patterns',
|
|
378
|
+
'Archived Memories': 'memory_archive'
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
print("\nTable Statistics:")
|
|
382
|
+
for name, table in tables.items():
|
|
383
|
+
try:
|
|
384
|
+
cursor.execute(f'SELECT COUNT(*) FROM {table}')
|
|
385
|
+
count = cursor.fetchone()[0]
|
|
386
|
+
print(f" {name:20s}: {count:>5} rows")
|
|
387
|
+
except sqlite3.OperationalError:
|
|
388
|
+
print(f" {name:20s}: Table not found")
|
|
389
|
+
|
|
390
|
+
# Database size
|
|
391
|
+
db_size = self.db_path.stat().st_size / (1024 * 1024)
|
|
392
|
+
print(f"\nDatabase Size: {db_size:.2f} MB")
|
|
393
|
+
|
|
394
|
+
# Backup count
|
|
395
|
+
if self.backup_dir.exists():
|
|
396
|
+
backup_count = len(list(self.backup_dir.glob("*.db")))
|
|
397
|
+
print(f"Backups Available: {backup_count}")
|
|
398
|
+
|
|
399
|
+
conn.close()
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def main():
|
|
403
|
+
parser = argparse.ArgumentParser(
|
|
404
|
+
description='SuperLocalMemory V2 - Reset & Reinitialize Utility',
|
|
405
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
406
|
+
epilog='''
|
|
407
|
+
Examples:
|
|
408
|
+
# Show current status
|
|
409
|
+
python memory-reset.py status
|
|
410
|
+
|
|
411
|
+
# Soft reset (clear memories, keep schema)
|
|
412
|
+
python memory-reset.py soft
|
|
413
|
+
|
|
414
|
+
# Hard reset (delete everything, reinitialize)
|
|
415
|
+
python memory-reset.py hard --confirm
|
|
416
|
+
|
|
417
|
+
# Reset specific layers only
|
|
418
|
+
python memory-reset.py layer --layers graph patterns
|
|
419
|
+
|
|
420
|
+
# Reset without automatic backup
|
|
421
|
+
python memory-reset.py soft --no-backup
|
|
422
|
+
'''
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
parser.add_argument('command', choices=['status', 'soft', 'hard', 'layer'],
|
|
426
|
+
help='Reset command to execute')
|
|
427
|
+
parser.add_argument('--layers', nargs='+',
|
|
428
|
+
choices=['graph', 'patterns', 'tree', 'archive'],
|
|
429
|
+
help='Layers to reset (for layer command)')
|
|
430
|
+
parser.add_argument('--no-backup', action='store_true',
|
|
431
|
+
help='Skip automatic backup')
|
|
432
|
+
parser.add_argument('--confirm', action='store_true',
|
|
433
|
+
help='Confirm destructive operations (required for hard reset)')
|
|
434
|
+
|
|
435
|
+
args = parser.parse_args()
|
|
436
|
+
|
|
437
|
+
resetter = MemoryReset(auto_backup=not args.no_backup)
|
|
438
|
+
|
|
439
|
+
if args.command == 'status':
|
|
440
|
+
resetter.show_stats()
|
|
441
|
+
|
|
442
|
+
elif args.command == 'soft':
|
|
443
|
+
print("\n⚠️ WARNING: This will delete ALL memories but keep the V2 schema.")
|
|
444
|
+
print(" Backup will be created automatically unless --no-backup specified.")
|
|
445
|
+
response = input("\nProceed with soft reset? (yes/no): ")
|
|
446
|
+
|
|
447
|
+
if response.lower() == 'yes':
|
|
448
|
+
resetter.soft_reset()
|
|
449
|
+
else:
|
|
450
|
+
print("Cancelled.")
|
|
451
|
+
|
|
452
|
+
elif args.command == 'hard':
|
|
453
|
+
if not args.confirm:
|
|
454
|
+
print("\n❌ ERROR: Hard reset requires --confirm flag")
|
|
455
|
+
print(" This operation deletes EVERYTHING and reinitializes.")
|
|
456
|
+
print(" Use: python memory-reset.py hard --confirm")
|
|
457
|
+
sys.exit(1)
|
|
458
|
+
|
|
459
|
+
print("\n⚠️ WARNING: This will DELETE the entire database!")
|
|
460
|
+
print(" All memories, patterns, graphs will be permanently removed.")
|
|
461
|
+
print(" A backup will be created automatically unless --no-backup specified.")
|
|
462
|
+
response = input("\nType 'DELETE EVERYTHING' to confirm: ")
|
|
463
|
+
|
|
464
|
+
if response == 'DELETE EVERYTHING':
|
|
465
|
+
resetter.hard_reset()
|
|
466
|
+
else:
|
|
467
|
+
print("Cancelled.")
|
|
468
|
+
|
|
469
|
+
elif args.command == 'layer':
|
|
470
|
+
if not args.layers:
|
|
471
|
+
print("❌ ERROR: --layers required for layer reset")
|
|
472
|
+
print(" Example: python memory-reset.py layer --layers graph patterns")
|
|
473
|
+
sys.exit(1)
|
|
474
|
+
|
|
475
|
+
print(f"\n⚠️ WARNING: This will clear layers: {', '.join(args.layers)}")
|
|
476
|
+
response = input("\nProceed? (yes/no): ")
|
|
477
|
+
|
|
478
|
+
if response.lower() == 'yes':
|
|
479
|
+
resetter.layer_reset(args.layers)
|
|
480
|
+
else:
|
|
481
|
+
print("Cancelled.")
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
if __name__ == '__main__':
|
|
485
|
+
main()
|