AthelaPerk commited on
Commit
2003204
·
verified ·
1 Parent(s): e7c2bb6

Update mnemo_core.py

Browse files
Files changed (1) hide show
  1. mnemo_core.py +55 -0
mnemo_core.py CHANGED
@@ -1338,6 +1338,59 @@ class MnemoEngine:
1338
  self._dirty = True
1339
  return True
1340
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1341
  def add_knot(self, knot_id: str, name: str, thread_ids: List[str],
1342
  pivot_type: str = "collision", reason: str = "",
1343
  session_id: str = "",
@@ -1928,5 +1981,7 @@ class PersistentMnemo:
1928
  def trace_thread(self, *args, **kwargs): return self.engine.trace_thread(*args, **kwargs)
1929
  def get_active_threads(self): return self.engine.get_active_threads()
1930
  def delete_thread(self, *args, **kwargs): return self.engine.delete_thread(*args, **kwargs)
 
 
1931
  def add_knot(self, *args, **kwargs): return self.engine.add_knot(*args, **kwargs)
1932
  def get_knot_context(self, *args, **kwargs): return self.engine.get_knot_context(*args, **kwargs)
 
1338
  self._dirty = True
1339
  return True
1340
 
1341
+ def delete_knot(self, knot_id: str) -> bool:
1342
+ """Delete a knot and clean up references from its threads."""
1343
+ with self._lock:
1344
+ knot = self.knots.get(knot_id)
1345
+ if not knot:
1346
+ return False
1347
+ # Remove knot reference from threads
1348
+ for tid in knot.threads:
1349
+ thread = self.threads.get(tid)
1350
+ if thread and knot_id in thread.knots:
1351
+ thread.knots.remove(knot_id)
1352
+ thread.invalidate_cache()
1353
+ # Remove from thread_index
1354
+ for tid in knot.threads:
1355
+ knot_list = self.thread_index.by_thread.get(tid, [])
1356
+ if knot_id in knot_list:
1357
+ knot_list.remove(knot_id)
1358
+ self.thread_index.by_knot.pop(knot_id, None)
1359
+ del self.knots[knot_id]
1360
+ self._dirty = True
1361
+ return True
1362
+
1363
+ def delete_session_threads_and_knots(self, session_id: str) -> dict:
1364
+ """Delete all threads and knots belonging to a session.
1365
+
1366
+ Called after delete_session_points() to complete cascade.
1367
+ Threads from protected sources (file_upload, manual) are kept.
1368
+ """
1369
+ PROTECTED_SOURCES = {"file_upload", "manual_correction", "consolidation", "manual"}
1370
+ deleted_threads = 0
1371
+ deleted_knots = 0
1372
+
1373
+ # Find threads belonging to this session
1374
+ with self._lock:
1375
+ thread_ids = [tid for tid, t in self.threads.items()
1376
+ if t.session_id == session_id]
1377
+ knot_ids = [kid for kid, k in self.knots.items()
1378
+ if k.session_id == session_id]
1379
+
1380
+ for tid in thread_ids:
1381
+ if self.delete_thread(tid):
1382
+ deleted_threads += 1
1383
+
1384
+ for kid in knot_ids:
1385
+ if self.delete_knot(kid):
1386
+ deleted_knots += 1
1387
+
1388
+ if deleted_threads > 0 or deleted_knots > 0:
1389
+ with self._lock:
1390
+ self._dirty = True
1391
+
1392
+ return {"deleted_threads": deleted_threads, "deleted_knots": deleted_knots}
1393
+
1394
  def add_knot(self, knot_id: str, name: str, thread_ids: List[str],
1395
  pivot_type: str = "collision", reason: str = "",
1396
  session_id: str = "",
 
1981
  def trace_thread(self, *args, **kwargs): return self.engine.trace_thread(*args, **kwargs)
1982
  def get_active_threads(self): return self.engine.get_active_threads()
1983
  def delete_thread(self, *args, **kwargs): return self.engine.delete_thread(*args, **kwargs)
1984
+ def delete_knot(self, *args, **kwargs): return self.engine.delete_knot(*args, **kwargs)
1985
+ def delete_session_threads_and_knots(self, *args, **kwargs): return self.engine.delete_session_threads_and_knots(*args, **kwargs)
1986
  def add_knot(self, *args, **kwargs): return self.engine.add_knot(*args, **kwargs)
1987
  def get_knot_context(self, *args, **kwargs): return self.engine.get_knot_context(*args, **kwargs)