flurryx-code-memory 0.4.0__py3-none-any.whl

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.
Files changed (53) hide show
  1. code_memory/__init__.py +1 -0
  2. code_memory/claims/__init__.py +32 -0
  3. code_memory/claims/extractor.py +325 -0
  4. code_memory/claims/indexer.py +258 -0
  5. code_memory/claims/resolver.py +186 -0
  6. code_memory/claims/store.py +424 -0
  7. code_memory/cli.py +1192 -0
  8. code_memory/config.py +268 -0
  9. code_memory/embed/__init__.py +224 -0
  10. code_memory/embed/cache.py +204 -0
  11. code_memory/embed/m3.py +174 -0
  12. code_memory/embed/ollama.py +92 -0
  13. code_memory/embed/tei.py +106 -0
  14. code_memory/episodic/__init__.py +3 -0
  15. code_memory/episodic/sqlite_store.py +278 -0
  16. code_memory/extractor/__init__.py +3 -0
  17. code_memory/extractor/csproj.py +166 -0
  18. code_memory/extractor/dll.py +385 -0
  19. code_memory/extractor/gitignore.py +162 -0
  20. code_memory/extractor/nuget.py +275 -0
  21. code_memory/extractor/sanity.py +124 -0
  22. code_memory/extractor/sln.py +108 -0
  23. code_memory/extractor/treesitter.py +1172 -0
  24. code_memory/graph/__init__.py +3 -0
  25. code_memory/graph/falkor_store.py +740 -0
  26. code_memory/mcp_server.py +1816 -0
  27. code_memory/metrics.py +260 -0
  28. code_memory/orchestrator/__init__.py +13 -0
  29. code_memory/orchestrator/git_delta.py +211 -0
  30. code_memory/orchestrator/ingest_state.py +71 -0
  31. code_memory/orchestrator/pipeline.py +1478 -0
  32. code_memory/orchestrator/reset.py +130 -0
  33. code_memory/orchestrator/resolver.py +825 -0
  34. code_memory/orchestrator/retrieve.py +505 -0
  35. code_memory/resilience.py +73 -0
  36. code_memory/sync/__init__.py +20 -0
  37. code_memory/sync/autostart/__init__.py +42 -0
  38. code_memory/sync/autostart/base.py +106 -0
  39. code_memory/sync/autostart/launchd.py +115 -0
  40. code_memory/sync/autostart/schtasks.py +155 -0
  41. code_memory/sync/autostart/systemd.py +113 -0
  42. code_memory/sync/hooks.py +164 -0
  43. code_memory/sync/safety.py +65 -0
  44. code_memory/sync/snapshot.py +461 -0
  45. code_memory/sync/store.py +399 -0
  46. code_memory/sync/sync.py +405 -0
  47. code_memory/sync/watcher.py +320 -0
  48. code_memory/vector/__init__.py +3 -0
  49. code_memory/vector/qdrant_store.py +302 -0
  50. flurryx_code_memory-0.4.0.dist-info/METADATA +26 -0
  51. flurryx_code_memory-0.4.0.dist-info/RECORD +53 -0
  52. flurryx_code_memory-0.4.0.dist-info/WHEEL +4 -0
  53. flurryx_code_memory-0.4.0.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,130 @@
1
+ """Project reset utilities.
2
+
3
+ Two scopes:
4
+
5
+ - **code index** — Qdrant code collection + FalkorDB graph + SQLite
6
+ ``ingest_state`` table. Wiping this leaves prior agent conversations
7
+ intact and is the common case (e.g. after broadening ignore rules).
8
+ - **episodes** — Qdrant episode collection + episodic SQLite DB. Wiping
9
+ this is destructive: it forgets every recorded task/episode for the
10
+ project. Opt-in via ``include_episodes=True``.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from dataclasses import dataclass
16
+ from pathlib import Path
17
+
18
+ from falkordb import FalkorDB
19
+
20
+ from ..config import CONFIG, slugify
21
+ from ..graph.falkor_store import FalkorStore
22
+ from ..vector.qdrant_store import QdrantStore
23
+
24
+
25
+ @dataclass
26
+ class ResetResult:
27
+ project: str
28
+ vectors_dropped: bool
29
+ graph_cleared: bool
30
+ state_cleared: bool
31
+ episodes_dropped: bool
32
+ episodic_db_removed: bool
33
+
34
+
35
+ def list_projects() -> list[str]:
36
+ """Discover every project slug known to the storage backends.
37
+
38
+ Union of:
39
+ - Qdrant collections named ``<qdrant_code>__<slug>``
40
+ - FalkorDB graphs named ``<falkor_graph>__<slug>``
41
+ - subdirectories of ``data_dir`` (one dir per slug)
42
+ """
43
+ slugs: set[str] = set()
44
+
45
+ code_prefix = f"{CONFIG.qdrant_code}__"
46
+ eps_prefix = f"{CONFIG.qdrant_episodes}__"
47
+ try:
48
+ client = QdrantStore().client
49
+ for c in client.get_collections().collections:
50
+ for prefix in (code_prefix, eps_prefix):
51
+ if c.name.startswith(prefix):
52
+ slugs.add(c.name[len(prefix) :])
53
+ except Exception:
54
+ pass
55
+
56
+ graph_prefix = f"{CONFIG.falkor_graph}__"
57
+ try:
58
+ db = FalkorDB(host=CONFIG.falkor_host, port=CONFIG.falkor_port)
59
+ for name in db.list_graphs():
60
+ if name.startswith(graph_prefix):
61
+ slugs.add(name[len(graph_prefix) :])
62
+ except Exception:
63
+ pass
64
+
65
+ if CONFIG.data_dir.is_dir():
66
+ for sub in CONFIG.data_dir.iterdir():
67
+ if sub.is_dir():
68
+ slugs.add(sub.name)
69
+
70
+ return sorted(slugs)
71
+
72
+
73
+ def reset_project(slug: str, *, include_episodes: bool = False) -> ResetResult:
74
+ """Wipe code index (and optionally episodic memory) for one project."""
75
+ slug = slugify(slug)
76
+ cfg = CONFIG.for_project(slug)
77
+
78
+ result = ResetResult(
79
+ project=slug,
80
+ vectors_dropped=False,
81
+ graph_cleared=False,
82
+ state_cleared=False,
83
+ episodes_dropped=False,
84
+ episodic_db_removed=False,
85
+ )
86
+
87
+ try:
88
+ vector = QdrantStore()
89
+ vector.recreate_collection(cfg.qdrant_code)
90
+ result.vectors_dropped = True
91
+ except Exception:
92
+ pass
93
+
94
+ try:
95
+ graph = FalkorStore(graph_name=cfg.falkor_graph)
96
+ graph.clear_graph()
97
+ result.graph_cleared = True
98
+ except Exception:
99
+ pass
100
+
101
+ if include_episodes:
102
+ try:
103
+ QdrantStore().recreate_collection(cfg.qdrant_episodes)
104
+ result.episodes_dropped = True
105
+ except Exception:
106
+ pass
107
+ db_path = Path(cfg.episodic_db)
108
+ if db_path.is_file():
109
+ db_path.unlink(missing_ok=True)
110
+ result.episodic_db_removed = True
111
+ result.state_cleared = True
112
+ else:
113
+ # keep episodes; just clear ingest_state rows for this project's DB
114
+ from .ingest_state import IngestStateStore
115
+
116
+ db_path = Path(cfg.episodic_db)
117
+ if db_path.is_file():
118
+ store = IngestStateStore(db_path)
119
+ try:
120
+ store.conn.execute("DELETE FROM ingest_state")
121
+ store.conn.commit()
122
+ result.state_cleared = True
123
+ finally:
124
+ store.close()
125
+
126
+ return result
127
+
128
+
129
+ def reset_all(*, include_episodes: bool = False) -> list[ResetResult]:
130
+ return [reset_project(s, include_episodes=include_episodes) for s in list_projects()]