total-agent-memory 12.0.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 (184) hide show
  1. claude_total_memory/__init__.py +24 -0
  2. claude_total_memory/lookup.py +12 -0
  3. claude_total_memory/server.py +6 -0
  4. src/__init__.py +0 -0
  5. src/active_context.py +205 -0
  6. src/ai_layer/__init__.py +77 -0
  7. src/ai_layer/answerability.py +386 -0
  8. src/ai_layer/contradiction_detector.py +37 -0
  9. src/ai_layer/coref_resolver.py +21 -0
  10. src/ai_layer/enrichment_jobs.py +129 -0
  11. src/ai_layer/enrichment_worker.py +44 -0
  12. src/ai_layer/iterative_retriever.py +469 -0
  13. src/ai_layer/keyword_extractor.py +51 -0
  14. src/ai_layer/quality_gate.py +23 -0
  15. src/ai_layer/query_rewriter.py +22 -0
  16. src/ai_layer/question_generator.py +53 -0
  17. src/ai_layer/reflection.py +30 -0
  18. src/ai_layer/relation_extractor.py +64 -0
  19. src/ai_layer/reranker.py +28 -0
  20. src/ai_layer/self_improve.py +30 -0
  21. src/ai_layer/summarizer.py +39 -0
  22. src/ai_layer/verifier.py +506 -0
  23. src/analogy.py +157 -0
  24. src/associative/__init__.py +0 -0
  25. src/associative/activation.py +244 -0
  26. src/associative/composition.py +338 -0
  27. src/associative/recall.py +383 -0
  28. src/ast_ingest/__init__.py +5 -0
  29. src/ast_ingest/ingester.py +401 -0
  30. src/auto_episode_capture.py +416 -0
  31. src/auto_extract_active.py +219 -0
  32. src/auto_self_improve.py +317 -0
  33. src/auto_session_save.py +104 -0
  34. src/autofilter.py +191 -0
  35. src/cache.py +237 -0
  36. src/cache_layer.py +528 -0
  37. src/canonical_tags.py +390 -0
  38. src/choose_embed.py +201 -0
  39. src/cognitive/__init__.py +1 -0
  40. src/cognitive/engine.py +979 -0
  41. src/config.py +896 -0
  42. src/content_filter.py +270 -0
  43. src/context_expander.py +179 -0
  44. src/contradiction_detector.py +476 -0
  45. src/coref_resolver.py +302 -0
  46. src/dashboard.py +4560 -0
  47. src/dashboard_v6.py +1417 -0
  48. src/decisions.py +320 -0
  49. src/deep_enricher.py +286 -0
  50. src/deep_enrichment_queue.py +169 -0
  51. src/embed_provider.py +441 -0
  52. src/enrichment_filter.py +108 -0
  53. src/enrichment_worker.py +483 -0
  54. src/entity_dedup.py +354 -0
  55. src/episodic.py +328 -0
  56. src/error_capture.py +248 -0
  57. src/eval_harness.py +234 -0
  58. src/extract_transcript.py +411 -0
  59. src/fact_index.py +510 -0
  60. src/fact_merger.py +245 -0
  61. src/fact_synthesizer.py +375 -0
  62. src/file_context.py +338 -0
  63. src/fusion.py +138 -0
  64. src/graph/__init__.py +8 -0
  65. src/graph/auto_link.py +81 -0
  66. src/graph/enricher.py +505 -0
  67. src/graph/indexer.py +872 -0
  68. src/graph/query.py +470 -0
  69. src/graph/store.py +731 -0
  70. src/graph_expander.py +395 -0
  71. src/ingestion/__init__.py +13 -0
  72. src/ingestion/chunker.py +271 -0
  73. src/ingestion/enricher.py +249 -0
  74. src/ingestion/extractor.py +541 -0
  75. src/ingestion/file_watcher.py +322 -0
  76. src/ingestion/gateway.py +345 -0
  77. src/ingestion/ocr.py +264 -0
  78. src/intents.py +194 -0
  79. src/llm_provider.py +404 -0
  80. src/memory_core/__init__.py +33 -0
  81. src/memory_core/answer_router.py +359 -0
  82. src/memory_core/cache.py +123 -0
  83. src/memory_core/calibration.py +401 -0
  84. src/memory_core/chunker.py +438 -0
  85. src/memory_core/classifier.py +406 -0
  86. src/memory_core/dedup.py +87 -0
  87. src/memory_core/embedding_cache.py +232 -0
  88. src/memory_core/embedding_spaces.py +127 -0
  89. src/memory_core/embeddings.py +173 -0
  90. src/memory_core/entity_resolver.py +601 -0
  91. src/memory_core/episodes/__init__.py +27 -0
  92. src/memory_core/episodes/extractor.py +469 -0
  93. src/memory_core/episodes/retriever.py +383 -0
  94. src/memory_core/episodes/schema.py +90 -0
  95. src/memory_core/graph_links.py +131 -0
  96. src/memory_core/health.py +77 -0
  97. src/memory_core/idk_router.py +214 -0
  98. src/memory_core/negative_retrieval.py +510 -0
  99. src/memory_core/storage.py +64 -0
  100. src/memory_core/telemetry.py +91 -0
  101. src/memory_core/temporal/__init__.py +80 -0
  102. src/memory_core/temporal/allen.py +406 -0
  103. src/memory_core/temporal/arithmetic.py +281 -0
  104. src/memory_core/temporal/normalizer.py +581 -0
  105. src/memory_core/vector_store.py +254 -0
  106. src/memory_systems/__init__.py +0 -0
  107. src/memory_systems/episode_store.py +278 -0
  108. src/memory_systems/self_model.py +476 -0
  109. src/memory_systems/signals.py +246 -0
  110. src/memory_systems/skill_store.py +391 -0
  111. src/metrics/__init__.py +0 -0
  112. src/migrate_knowledge_to_graph.py +337 -0
  113. src/models.py +1296 -0
  114. src/multi_repr_search.py +334 -0
  115. src/multi_repr_store.py +202 -0
  116. src/outbox.py +325 -0
  117. src/paths.py +163 -0
  118. src/privacy_filter.py +19 -0
  119. src/procedural.py +356 -0
  120. src/project_wiki.py +430 -0
  121. src/quality_gate.py +460 -0
  122. src/query_rewriter.py +300 -0
  123. src/query_router.py +285 -0
  124. src/recall_modes.py +278 -0
  125. src/reembed.py +308 -0
  126. src/reflection/__init__.py +1 -0
  127. src/reflection/agent.py +688 -0
  128. src/reflection/digest.py +484 -0
  129. src/reflection/scheduler.py +2202 -0
  130. src/reflection/synthesize.py +463 -0
  131. src/representations.py +231 -0
  132. src/representations_queue.py +204 -0
  133. src/reranker.py +672 -0
  134. src/server.py +6800 -0
  135. src/session_continuity.py +413 -0
  136. src/subject_predicate_retriever.py +184 -0
  137. src/task_classifier.py +181 -0
  138. src/task_phases.py +299 -0
  139. src/temporal_filter.py +199 -0
  140. src/temporal_index.py +368 -0
  141. src/temporal_kg.py +348 -0
  142. src/tools/__init__.py +0 -0
  143. src/tools/analyze_project.py +396 -0
  144. src/tools/backfill_orphan_edges.py +159 -0
  145. src/tools/backfill_v6.py +84 -0
  146. src/tools/benchmark.py +940 -0
  147. src/tools/brain_autonomy.py +614 -0
  148. src/tools/brain_health.py +489 -0
  149. src/tools/check_updates.py +166 -0
  150. src/tools/context_layers.py +472 -0
  151. src/tools/cross_project.py +1021 -0
  152. src/tools/dependency_monitor.py +285 -0
  153. src/tools/export_knowledge.py +314 -0
  154. src/tools/git_observer.py +968 -0
  155. src/tools/graph_enrichment.py +1103 -0
  156. src/tools/idea_engine.py +1215 -0
  157. src/tools/import_projects_now.py +312 -0
  158. src/tools/improve_search.py +877 -0
  159. src/tools/llm_router.py +397 -0
  160. src/tools/merge_duplicate_nodes.py +491 -0
  161. src/tools/obsidian_sync.py +399 -0
  162. src/tools/predictive.py +1176 -0
  163. src/tools/run_reflection.py +193 -0
  164. src/tools/task_manager.py +816 -0
  165. src/tools/tech_radar.py +275 -0
  166. src/tools/version_status.py +141 -0
  167. src/triple_extraction_queue.py +208 -0
  168. src/v11_handlers.py +236 -0
  169. src/validator.py +235 -0
  170. src/verbosity.py +49 -0
  171. src/version.py +10 -0
  172. src/workers/__init__.py +34 -0
  173. src/workers/consolidation_daemon.py +849 -0
  174. src/workers/project_activity.py +193 -0
  175. total_agent_memory/__init__.py +3 -0
  176. total_agent_memory/lookup.py +191 -0
  177. total_agent_memory/paths.py +10 -0
  178. total_agent_memory/server.py +25 -0
  179. total_agent_memory-12.0.0.dist-info/METADATA +1310 -0
  180. total_agent_memory-12.0.0.dist-info/RECORD +184 -0
  181. total_agent_memory-12.0.0.dist-info/WHEEL +5 -0
  182. total_agent_memory-12.0.0.dist-info/entry_points.txt +7 -0
  183. total_agent_memory-12.0.0.dist-info/licenses/LICENSE +21 -0
  184. total_agent_memory-12.0.0.dist-info/top_level.txt +3 -0
@@ -0,0 +1,24 @@
1
+ """Backward-compat shim: the package was renamed to ``total_agent_memory``.
2
+
3
+ The legacy import path keeps working so existing user scripts and sub-agent
4
+ prompts that do ``from claude_total_memory import ...`` do not break on
5
+ upgrade. Every import emits a DeprecationWarning so callers know to switch.
6
+
7
+ Migration:
8
+ from claude_total_memory import x # old
9
+ from total_agent_memory import x # new
10
+ """
11
+ from __future__ import annotations
12
+
13
+ import warnings as _warnings
14
+
15
+ _warnings.warn(
16
+ "The 'claude_total_memory' module has been renamed to 'total_agent_memory'. "
17
+ "Update your imports: `from total_agent_memory import ...`. "
18
+ "The legacy alias will be removed in a future release.",
19
+ DeprecationWarning,
20
+ stacklevel=2,
21
+ )
22
+
23
+ from total_agent_memory import * # noqa: E402, F401, F403
24
+ from total_agent_memory import __version__ # noqa: E402, F401
@@ -0,0 +1,12 @@
1
+ """Backward-compat shim. Real entry-point: ``total_agent_memory.lookup``.
2
+
3
+ Replaces this module in ``sys.modules`` with the real implementation so
4
+ every attribute (including private helpers like ``_fts_query``) resolves
5
+ transparently. This keeps third-party tests and sub-agent scripts that do
6
+ ``import claude_total_memory.lookup as lookup`` working.
7
+ """
8
+ import sys as _sys
9
+
10
+ from total_agent_memory import lookup as _impl
11
+
12
+ _sys.modules[__name__] = _impl
@@ -0,0 +1,6 @@
1
+ """Backward-compat shim. Real entry-point: ``total_agent_memory.server``."""
2
+ import sys as _sys
3
+
4
+ from total_agent_memory import server as _impl
5
+
6
+ _sys.modules[__name__] = _impl
src/__init__.py ADDED
File without changes
src/active_context.py ADDED
@@ -0,0 +1,205 @@
1
+ """
2
+ Active Context — live-doc projection of session_continuity.
3
+
4
+ Maintains a human-readable markdown file (`activeContext.md`) per project
5
+ inside the Obsidian vault. The file is a symlink-style projection of the
6
+ latest session summary/next_steps/pitfalls — a dumb Read can pick it up
7
+ without going through MCP.
8
+
9
+ Round-trips with `read_active_context` so integration code can detect
10
+ staleness between the DB row and the markdown file.
11
+
12
+ Env:
13
+ MEMORY_ACTIVECONTEXT_VAULT — vault root (default ~/Documents/project/Projects)
14
+ MEMORY_ACTIVECONTEXT_DISABLE — "1"/"true"/"yes" disables markdown writes
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import os
20
+ import re
21
+ from datetime import datetime, timezone
22
+ from pathlib import Path
23
+ from typing import Any
24
+
25
+
26
+ DEFAULT_VAULT = Path.home() / "Documents" / "project" / "Projects"
27
+
28
+ _UPDATED_RE = re.compile(r"^\*\*Updated:\*\*\s*(.+?)\s*$")
29
+ _SESSION_RE = re.compile(r"^\*\*Session:\*\*\s*(.+?)\s*$")
30
+ _SECTION_RE = re.compile(r"^##\s+(.+?)\s*$")
31
+ _BULLET_RE = re.compile(r"^-\s+(.*?)\s*$")
32
+
33
+
34
+ def _now_iso() -> str:
35
+ """Return current UTC time as ISO-8601 with trailing Z."""
36
+ return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
37
+
38
+
39
+ def _resolve_vault_root(vault_root: Path | None) -> Path:
40
+ """Pick vault root: explicit arg > env var > default."""
41
+ if vault_root is not None:
42
+ return Path(vault_root).expanduser()
43
+ raw = os.environ.get("MEMORY_ACTIVECONTEXT_VAULT")
44
+ if raw:
45
+ return Path(raw).expanduser()
46
+ return DEFAULT_VAULT
47
+
48
+
49
+ def active_context_path(project: str, vault_root: Path | None = None) -> Path:
50
+ """Absolute path to the activeContext.md for the given project."""
51
+ if not project:
52
+ raise ValueError("project required")
53
+ root = _resolve_vault_root(vault_root)
54
+ return root / project / "activeContext.md"
55
+
56
+
57
+ def _render_section(title: str, items: list[str]) -> str:
58
+ """Render a markdown section with bullet items (empty list → '- _(none)_')."""
59
+ clean = [s for s in (items or []) if s is not None and str(s).strip()]
60
+ if not clean:
61
+ return f"## {title}\n- _(none)_\n"
62
+ lines = [f"## {title}"]
63
+ for it in clean:
64
+ lines.append(f"- {it}")
65
+ return "\n".join(lines) + "\n"
66
+
67
+
68
+ def write_active_context(
69
+ project: str,
70
+ summary: str,
71
+ next_steps: list[str],
72
+ pitfalls: list[str],
73
+ *,
74
+ vault_root: Path | None = None,
75
+ session_id: str | None = None,
76
+ ) -> Path:
77
+ """Write markdown live-doc. Overwrites existing file.
78
+
79
+ Creates parent directories. Returns the path written.
80
+ """
81
+ if not project:
82
+ raise ValueError("project required")
83
+ if summary is None:
84
+ summary = ""
85
+
86
+ path = active_context_path(project, vault_root=vault_root)
87
+ path.parent.mkdir(parents=True, exist_ok=True)
88
+
89
+ updated = _now_iso()
90
+ sess = session_id or "n/a"
91
+
92
+ # Normalize summary: keep multiline intact, strip trailing whitespace
93
+ summary_body = (summary or "").rstrip()
94
+ if not summary_body:
95
+ summary_body = "_(none)_"
96
+
97
+ parts = [
98
+ f"# {project} — Active Context\n",
99
+ f"\n**Updated:** {updated}\n",
100
+ f"**Session:** {sess}\n",
101
+ "\n## Summary\n",
102
+ f"{summary_body}\n",
103
+ "\n",
104
+ _render_section("Next Steps", next_steps or []),
105
+ "\n",
106
+ _render_section("Pitfalls", pitfalls or []),
107
+ ]
108
+ path.write_text("".join(parts), encoding="utf-8")
109
+ return path
110
+
111
+
112
+ def _parse_bullets(lines: list[str]) -> list[str]:
113
+ """Extract bullet content. Filter the '(none)' placeholder."""
114
+ out: list[str] = []
115
+ for ln in lines:
116
+ m = _BULLET_RE.match(ln)
117
+ if not m:
118
+ continue
119
+ val = m.group(1).strip()
120
+ if not val:
121
+ continue
122
+ # Drop placeholder from empty section
123
+ if val in ("_(none)_", "*(none)*", "(none)"):
124
+ continue
125
+ out.append(val)
126
+ return out
127
+
128
+
129
+ def read_active_context(
130
+ project: str,
131
+ vault_root: Path | None = None,
132
+ ) -> dict[str, Any] | None:
133
+ """Parse markdown back into a dict.
134
+
135
+ Returns ``None`` when the file does not exist. Returns a dict with at
136
+ least the keys ``summary`` / ``next_steps`` / ``pitfalls`` / ``updated_at``
137
+ even when the file is partly malformed (best-effort).
138
+ """
139
+ path = active_context_path(project, vault_root=vault_root)
140
+ if not path.exists():
141
+ return None
142
+
143
+ try:
144
+ text = path.read_text(encoding="utf-8")
145
+ except OSError:
146
+ return None
147
+
148
+ if not text.strip():
149
+ return None
150
+
151
+ lines = text.splitlines()
152
+
153
+ updated_at: str | None = None
154
+ session_id: str | None = None
155
+ sections: dict[str, list[str]] = {}
156
+
157
+ current: str | None = None
158
+ buf: list[str] = []
159
+
160
+ def _flush() -> None:
161
+ if current is not None:
162
+ sections[current] = buf.copy()
163
+
164
+ for raw in lines:
165
+ m_upd = _UPDATED_RE.match(raw)
166
+ if m_upd and updated_at is None:
167
+ updated_at = m_upd.group(1).strip()
168
+ continue
169
+ m_sess = _SESSION_RE.match(raw)
170
+ if m_sess and session_id is None:
171
+ session_id = m_sess.group(1).strip()
172
+ continue
173
+ m_sec = _SECTION_RE.match(raw)
174
+ if m_sec:
175
+ _flush()
176
+ current = m_sec.group(1).strip().lower()
177
+ buf = []
178
+ continue
179
+ if current is not None:
180
+ buf.append(raw)
181
+ _flush()
182
+
183
+ # Summary is free text; trim surrounding blank lines
184
+ summary_lines = sections.get("summary", [])
185
+ while summary_lines and not summary_lines[0].strip():
186
+ summary_lines.pop(0)
187
+ while summary_lines and not summary_lines[-1].strip():
188
+ summary_lines.pop()
189
+ summary_text = "\n".join(summary_lines).strip()
190
+ if summary_text in ("_(none)_", "*(none)*"):
191
+ summary_text = ""
192
+
193
+ next_steps = _parse_bullets(sections.get("next steps", []))
194
+ pitfalls = _parse_bullets(sections.get("pitfalls", []))
195
+
196
+ if session_id in (None, "", "n/a"):
197
+ session_id = None
198
+
199
+ return {
200
+ "summary": summary_text,
201
+ "next_steps": next_steps,
202
+ "pitfalls": pitfalls,
203
+ "updated_at": updated_at,
204
+ "session_id": session_id,
205
+ }
@@ -0,0 +1,77 @@
1
+ """v11.0 AI Layer — every LLM/Ollama/CrossEncoder code path lives here.
2
+
3
+ Hot-path code in `memory_core` MUST NOT import this package. The
4
+ asymmetry is intentional:
5
+
6
+ memory_core → deterministic, sync, zero LLM, zero network.
7
+ ai_layer → may import llm_provider, ollama, anthropic,
8
+ cross-encoder, FlagEmbedding, etc.
9
+
10
+ The async enrichment worker (`ai_layer.enrichment_worker`) is the only
11
+ path through which an LLM/Ollama call may be triggered as a side-effect
12
+ of a `memory_save`. Direct callers of LLM helpers (representations,
13
+ deep_enricher, contradiction_detector, reflection, self_improve) live
14
+ here too so that grep/AST tools can answer "what touches the LLM?" with
15
+ a single directory walk.
16
+
17
+ The regression suite (`tests/test_v11_layer_separation.py`) enforces the
18
+ import wall: any `from ai_layer.*` reference inside `src/memory_core/`
19
+ will fail CI.
20
+
21
+ Submodules
22
+ ----------
23
+
24
+ enrichment_worker v10.1 inbox/outbox worker (drain, enqueue, run_pending)
25
+ enrichment_jobs unified enqueue() shim across the three v10 queues
26
+ summarizer representations.summary
27
+ keyword_extractor representations.keywords
28
+ question_generator representations.utility_questions
29
+ relation_extractor deep_enricher concept/triple extraction
30
+ contradiction_detector auto-supersession of decisions/solutions
31
+ reflection ReflectionAgent + run_full
32
+ self_improve error/fix logging + pattern checks
33
+
34
+ The following four LLM-touching modules are also reachable through this
35
+ package so the layer-separation test sees them:
36
+
37
+ quality_gate, coref_resolver, reranker, query_rewriter
38
+
39
+ They are imported by `enrichment_worker` (quality_gate, coref_resolver)
40
+ or by Recall (reranker, query_rewriter) but, by living under `ai_layer`,
41
+ they are guaranteed to be invisible to anything that imports
42
+ `memory_core`.
43
+ """
44
+
45
+ from __future__ import annotations
46
+
47
+ from . import ( # noqa: F401 (re-export entry points)
48
+ contradiction_detector,
49
+ coref_resolver,
50
+ enrichment_jobs,
51
+ enrichment_worker,
52
+ keyword_extractor,
53
+ quality_gate,
54
+ query_rewriter,
55
+ question_generator,
56
+ reflection,
57
+ relation_extractor,
58
+ reranker,
59
+ self_improve,
60
+ summarizer,
61
+ )
62
+
63
+ __all__ = [
64
+ "contradiction_detector",
65
+ "coref_resolver",
66
+ "enrichment_jobs",
67
+ "enrichment_worker",
68
+ "keyword_extractor",
69
+ "quality_gate",
70
+ "query_rewriter",
71
+ "question_generator",
72
+ "reflection",
73
+ "relation_extractor",
74
+ "reranker",
75
+ "self_improve",
76
+ "summarizer",
77
+ ]