get-claudia 1.34.1 → 1.34.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.
|
@@ -177,6 +177,11 @@ def main():
|
|
|
177
177
|
action="store_true",
|
|
178
178
|
help="Launch the Brain Monitor terminal dashboard (requires: pip install claudia-memory[tui])",
|
|
179
179
|
)
|
|
180
|
+
parser.add_argument(
|
|
181
|
+
"--backfill-embeddings",
|
|
182
|
+
action="store_true",
|
|
183
|
+
help="Generate embeddings for all memories that don't have them yet, then exit",
|
|
184
|
+
)
|
|
180
185
|
|
|
181
186
|
args = parser.parse_args()
|
|
182
187
|
|
|
@@ -220,6 +225,52 @@ def main():
|
|
|
220
225
|
run_brain_monitor(db_path=get_config().db_path)
|
|
221
226
|
return
|
|
222
227
|
|
|
228
|
+
if args.backfill_embeddings:
|
|
229
|
+
# One-shot: generate embeddings for memories missing them
|
|
230
|
+
setup_logging(debug=args.debug)
|
|
231
|
+
from .embeddings import get_embedding_service
|
|
232
|
+
|
|
233
|
+
db = get_db()
|
|
234
|
+
db.initialize()
|
|
235
|
+
|
|
236
|
+
# Find memories not in the memory_embeddings table
|
|
237
|
+
missing = db.execute(
|
|
238
|
+
"SELECT m.id, m.content FROM memories m "
|
|
239
|
+
"LEFT JOIN memory_embeddings me ON m.id = me.memory_id "
|
|
240
|
+
"WHERE me.memory_id IS NULL",
|
|
241
|
+
fetch=True,
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
if not missing:
|
|
245
|
+
print("All memories already have embeddings. Nothing to do.")
|
|
246
|
+
return
|
|
247
|
+
|
|
248
|
+
print(f"Found {len(missing)} memories without embeddings. Generating...")
|
|
249
|
+
svc = get_embedding_service()
|
|
250
|
+
if not svc.is_available_sync():
|
|
251
|
+
print("Error: Ollama is not available. Start Ollama and try again.")
|
|
252
|
+
sys.exit(1)
|
|
253
|
+
|
|
254
|
+
success = 0
|
|
255
|
+
failed = 0
|
|
256
|
+
for i, row in enumerate(missing, 1):
|
|
257
|
+
embedding = svc.embed_sync(row["content"])
|
|
258
|
+
if embedding:
|
|
259
|
+
import struct
|
|
260
|
+
blob = struct.pack(f"{len(embedding)}f", *embedding)
|
|
261
|
+
db.execute(
|
|
262
|
+
"INSERT OR REPLACE INTO memory_embeddings (memory_id, embedding) VALUES (?, ?)",
|
|
263
|
+
(row["id"], blob),
|
|
264
|
+
)
|
|
265
|
+
success += 1
|
|
266
|
+
else:
|
|
267
|
+
failed += 1
|
|
268
|
+
if i % 10 == 0 or i == len(missing):
|
|
269
|
+
print(f" Progress: {i}/{len(missing)} (success={success}, failed={failed})")
|
|
270
|
+
|
|
271
|
+
print(f"Backfill complete: {success} embedded, {failed} failed, {len(missing)} total.")
|
|
272
|
+
return
|
|
273
|
+
|
|
223
274
|
# Run the daemon
|
|
224
275
|
run_daemon(mcp_mode=not args.standalone, debug=args.debug, project_id=project_id)
|
|
225
276
|
|
|
@@ -55,9 +55,15 @@ class Database:
|
|
|
55
55
|
loaded = False
|
|
56
56
|
|
|
57
57
|
# Method 1: Try sqlite_vec Python package (recommended, works everywhere)
|
|
58
|
+
# Python 3.14+ requires explicit enable_load_extension() before any
|
|
59
|
+
# extension loading, even via the sqlite_vec helper package.
|
|
58
60
|
try:
|
|
59
61
|
import sqlite_vec
|
|
62
|
+
if hasattr(conn, "enable_load_extension"):
|
|
63
|
+
conn.enable_load_extension(True)
|
|
60
64
|
sqlite_vec.load(conn)
|
|
65
|
+
if hasattr(conn, "enable_load_extension"):
|
|
66
|
+
conn.enable_load_extension(False)
|
|
61
67
|
loaded = True
|
|
62
68
|
logger.debug("Loaded sqlite-vec via Python package")
|
|
63
69
|
except ImportError:
|
|
@@ -165,3 +165,39 @@ def test_migration_integrity_detects_missing_verification_status():
|
|
|
165
165
|
assert effective_version <= 4, f"Should return version <= 4 to re-run migration 5, got {effective_version}"
|
|
166
166
|
|
|
167
167
|
database.close()
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def test_sqlite_vec_loads_with_enable_extension():
|
|
171
|
+
"""sqlite-vec loads correctly with enable_load_extension (Python 3.14+ compat).
|
|
172
|
+
|
|
173
|
+
Verifies that the Database class can load sqlite-vec and create vec0
|
|
174
|
+
virtual tables. Skips if sqlite_vec isn't installed or if the Python
|
|
175
|
+
build omits extension loading support (SQLITE_OMIT_LOAD_EXTENSION).
|
|
176
|
+
"""
|
|
177
|
+
try:
|
|
178
|
+
import sqlite_vec # noqa: F401
|
|
179
|
+
except ImportError:
|
|
180
|
+
pytest.skip("sqlite_vec package not installed")
|
|
181
|
+
|
|
182
|
+
# Check if this Python build supports extension loading at all
|
|
183
|
+
import sqlite3 as _sqlite3
|
|
184
|
+
_test_conn = _sqlite3.connect(":memory:")
|
|
185
|
+
if not hasattr(_test_conn, "enable_load_extension"):
|
|
186
|
+
_test_conn.close()
|
|
187
|
+
pytest.skip("Python built without SQLITE_LOAD_EXTENSION support")
|
|
188
|
+
_test_conn.close()
|
|
189
|
+
|
|
190
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
191
|
+
db_path = Path(tmpdir) / "test_vec.db"
|
|
192
|
+
db = Database(db_path)
|
|
193
|
+
db.initialize()
|
|
194
|
+
|
|
195
|
+
# If sqlite-vec loaded, we should be able to query a vec0 table
|
|
196
|
+
# memory_embeddings is created in schema.sql as a vec0 virtual table
|
|
197
|
+
result = db.execute(
|
|
198
|
+
"SELECT name FROM sqlite_master WHERE type='table' AND name='memory_embeddings'",
|
|
199
|
+
fetch=True,
|
|
200
|
+
)
|
|
201
|
+
assert len(result) > 0, "memory_embeddings vec0 table should exist when sqlite-vec is loaded"
|
|
202
|
+
|
|
203
|
+
db.close()
|