etchmem 0.1.0__tar.gz → 0.1.2__tar.gz

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 (35) hide show
  1. etchmem-0.1.2/PKG-INFO +123 -0
  2. etchmem-0.1.2/README.md +95 -0
  3. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/models.py +1 -0
  4. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/stores/chroma_store.py +3 -1
  5. etchmem-0.1.2/etchmem.egg-info/PKG-INFO +123 -0
  6. {etchmem-0.1.0 → etchmem-0.1.2}/pyproject.toml +1 -1
  7. etchmem-0.1.0/PKG-INFO +0 -29
  8. etchmem-0.1.0/README.md +0 -1
  9. etchmem-0.1.0/etchmem.egg-info/PKG-INFO +0 -29
  10. {etchmem-0.1.0 → etchmem-0.1.2}/LICENSE +0 -0
  11. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/__init__.py +0 -0
  12. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/config.py +0 -0
  13. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/connector/__init__.py +0 -0
  14. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/connector/base.py +0 -0
  15. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/connector/remote.py +0 -0
  16. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/consolidate/__init__.py +0 -0
  17. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/consolidate/worker.py +0 -0
  18. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/engine.py +0 -0
  19. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/recall/__init__.py +0 -0
  20. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/recall/recaller.py +0 -0
  21. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/stores/__init__.py +0 -0
  22. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/stores/base.py +0 -0
  23. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/util/__init__.py +0 -0
  24. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/util/affectability.py +0 -0
  25. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem/util/hashing.py +0 -0
  26. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem.egg-info/SOURCES.txt +0 -0
  27. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem.egg-info/dependency_links.txt +0 -0
  28. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem.egg-info/requires.txt +0 -0
  29. {etchmem-0.1.0 → etchmem-0.1.2}/etchmem.egg-info/top_level.txt +0 -0
  30. {etchmem-0.1.0 → etchmem-0.1.2}/setup.cfg +0 -0
  31. {etchmem-0.1.0 → etchmem-0.1.2}/tests/test_consolidate_idempotent.py +0 -0
  32. {etchmem-0.1.0 → etchmem-0.1.2}/tests/test_formation_buckets.py +0 -0
  33. {etchmem-0.1.0 → etchmem-0.1.2}/tests/test_recall.py +0 -0
  34. {etchmem-0.1.0 → etchmem-0.1.2}/tests/test_reconsolidation.py +0 -0
  35. {etchmem-0.1.0 → etchmem-0.1.2}/tests/test_remember_recall.py +0 -0
etchmem-0.1.2/PKG-INFO ADDED
@@ -0,0 +1,123 @@
1
+ Metadata-Version: 2.4
2
+ Name: etchmem
3
+ Version: 0.1.2
4
+ Summary: A pluggable, embeddable reconsolidating skill memory engine for AI agents
5
+ Author: Andrey Olishchuk
6
+ License: MIT
7
+ Project-URL: Repository, https://github.com/andrey-olishchuk/etchmem
8
+ Keywords: llm,agent,memory,chromadb,rag,reconsolidation,skill,skills,etchmem
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Requires-Python: >=3.11
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: chromadb>=1.5.0
22
+ Requires-Dist: openai>=1.70.0
23
+ Requires-Dist: anthropic>=0.100.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=8.0; extra == "dev"
26
+ Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
27
+ Dynamic: license-file
28
+
29
+ # etchmem
30
+
31
+ A lightweight, embeddable memory engine for LLM agents. Agents remember things, recall them later, and the stored knowledge quietly matures through use — no extra plumbing required.
32
+
33
+ ```bash
34
+ pip install etchmem
35
+ ```
36
+
37
+ ---
38
+
39
+ ## What it is
40
+
41
+ `etchmem` gives your agent a persistent memory that improves over time. You deposit raw observations, retrieve them with natural-language queries, and periodically consolidate — at which point the engine synthesizes scattered signals into compact knowledge articles and rewrites anything that's been recalled against fresh context.
42
+
43
+ It is not a vector database and not an agent runtime. It sits above [ChromaDB](https://www.trychroma.com/), which handles all storage and embedding, and exposes exactly **three methods**.
44
+
45
+ ---
46
+
47
+ ## How it works
48
+
49
+ Memory is kept in three tiers:
50
+
51
+ - **Relational** — raw, append-only records with a TTL. Fresh signal lives here.
52
+ - **Buffer** — a working space for deposits and recall-events, waiting for the next consolidation run.
53
+ - **Injected** — synthesized knowledge articles, the primary search target. Only current knowledge is kept; superseded articles are hard-deleted.
54
+
55
+ The key idea is **reconsolidation**: every `recall()` call emits a recall-event into the buffer. When you later call `consolidate()`, the engine detects which injected articles were used, checks whether fresh signal changes anything, and rewrites them if needed. Knowledge that gets recalled stays current as a side-effect of being recalled. Knowledge nobody asks about simply rests.
56
+
57
+ Embeddings are computed locally by ChromaDB's built-in model — no external embedding API. Synthesis (the rewrite step inside `consolidate`) calls an LLM via `OPENAI_API_KEY` or `ANTHROPIC_API_KEY`.
58
+
59
+ ---
60
+
61
+ ## API
62
+
63
+ ```python
64
+ from etchmem import Engine
65
+ engine = Engine() # persists to .etchmem/ in the current directory
66
+ ```
67
+
68
+ ### `remember(data, hint=None, skill=None, metadata=None)`
69
+
70
+ Deposits a text record into the relational tier. No LLM call — cheap.
71
+
72
+ - `data` — the text to store.
73
+ - `hint` — optional float 0–1, your importance signal.
74
+ - `skill` — optional scope name; lets you filter recall by agent skill.
75
+ - `metadata` — arbitrary dict (source URL, tags, …).
76
+
77
+ ### `recall(query, skill=None, top_k=None, hint=None) → list[SearchResult]`
78
+
79
+ Retrieves relevant knowledge and emits a recall-event for future reconsolidation. Results are blended from injected (primary) and relational (fresh signal), ranked by a composite score.
80
+
81
+ ### `consolidate(num_records="all", method="LIFO") → dict`
82
+
83
+ Runs the consolidation worker: clusters the buffer, forms new injected articles, reconsolidates recalled articles against fresh context, hard-deletes superseded ones. Returns a summary dict with counts (`formed`, `reconsolidated`, `dropped`, `kept`, `flushed`, `superseded`). Requires an LLM API key.
84
+
85
+ ---
86
+
87
+ ## Hello world
88
+
89
+ ```python
90
+ import os
91
+ from etchmem import Engine
92
+
93
+ os.environ["ANTHROPIC_API_KEY"] = "sk-ant-..." # or OPENAI_API_KEY
94
+
95
+ engine = Engine()
96
+
97
+ # Add some facts
98
+ engine.remember("The Eiffel Tower is 330 metres tall including its antenna.")
99
+ engine.remember("The tower was completed in 1889 and was originally intended to be temporary.")
100
+ engine.remember("It receives about 7 million visitors per year, making it the world's most visited paid monument.")
101
+
102
+ # Retrieve relevant knowledge
103
+ results = engine.recall("How tall is the Eiffel Tower?")
104
+ for r in results:
105
+ print(r.score, r.content)
106
+
107
+ # Consolidate — synthesizes the raw deposits into a compact knowledge article
108
+ summary = engine.consolidate()
109
+ print(summary)
110
+ # {'formed': 1, 'reconsolidated': 0, 'dropped': 0, 'kept': 0, 'flushed': 3, 'superseded': 0}
111
+
112
+ # Subsequent recalls now hit the synthesized article,
113
+ # and any new signal deposited before the next consolidate()
114
+ # will be blended in during reconsolidation.
115
+ results = engine.recall("Eiffel Tower visitors")
116
+ print(results[0].content)
117
+ ```
118
+
119
+ ---
120
+
121
+ ## License
122
+
123
+ MIT
@@ -0,0 +1,95 @@
1
+ # etchmem
2
+
3
+ A lightweight, embeddable memory engine for LLM agents. Agents remember things, recall them later, and the stored knowledge quietly matures through use — no extra plumbing required.
4
+
5
+ ```bash
6
+ pip install etchmem
7
+ ```
8
+
9
+ ---
10
+
11
+ ## What it is
12
+
13
+ `etchmem` gives your agent a persistent memory that improves over time. You deposit raw observations, retrieve them with natural-language queries, and periodically consolidate — at which point the engine synthesizes scattered signals into compact knowledge articles and rewrites anything that's been recalled against fresh context.
14
+
15
+ It is not a vector database and not an agent runtime. It sits above [ChromaDB](https://www.trychroma.com/), which handles all storage and embedding, and exposes exactly **three methods**.
16
+
17
+ ---
18
+
19
+ ## How it works
20
+
21
+ Memory is kept in three tiers:
22
+
23
+ - **Relational** — raw, append-only records with a TTL. Fresh signal lives here.
24
+ - **Buffer** — a working space for deposits and recall-events, waiting for the next consolidation run.
25
+ - **Injected** — synthesized knowledge articles, the primary search target. Only current knowledge is kept; superseded articles are hard-deleted.
26
+
27
+ The key idea is **reconsolidation**: every `recall()` call emits a recall-event into the buffer. When you later call `consolidate()`, the engine detects which injected articles were used, checks whether fresh signal changes anything, and rewrites them if needed. Knowledge that gets recalled stays current as a side-effect of being recalled. Knowledge nobody asks about simply rests.
28
+
29
+ Embeddings are computed locally by ChromaDB's built-in model — no external embedding API. Synthesis (the rewrite step inside `consolidate`) calls an LLM via `OPENAI_API_KEY` or `ANTHROPIC_API_KEY`.
30
+
31
+ ---
32
+
33
+ ## API
34
+
35
+ ```python
36
+ from etchmem import Engine
37
+ engine = Engine() # persists to .etchmem/ in the current directory
38
+ ```
39
+
40
+ ### `remember(data, hint=None, skill=None, metadata=None)`
41
+
42
+ Deposits a text record into the relational tier. No LLM call — cheap.
43
+
44
+ - `data` — the text to store.
45
+ - `hint` — optional float 0–1, your importance signal.
46
+ - `skill` — optional scope name; lets you filter recall by agent skill.
47
+ - `metadata` — arbitrary dict (source URL, tags, …).
48
+
49
+ ### `recall(query, skill=None, top_k=None, hint=None) → list[SearchResult]`
50
+
51
+ Retrieves relevant knowledge and emits a recall-event for future reconsolidation. Results are blended from injected (primary) and relational (fresh signal), ranked by a composite score.
52
+
53
+ ### `consolidate(num_records="all", method="LIFO") → dict`
54
+
55
+ Runs the consolidation worker: clusters the buffer, forms new injected articles, reconsolidates recalled articles against fresh context, hard-deletes superseded ones. Returns a summary dict with counts (`formed`, `reconsolidated`, `dropped`, `kept`, `flushed`, `superseded`). Requires an LLM API key.
56
+
57
+ ---
58
+
59
+ ## Hello world
60
+
61
+ ```python
62
+ import os
63
+ from etchmem import Engine
64
+
65
+ os.environ["ANTHROPIC_API_KEY"] = "sk-ant-..." # or OPENAI_API_KEY
66
+
67
+ engine = Engine()
68
+
69
+ # Add some facts
70
+ engine.remember("The Eiffel Tower is 330 metres tall including its antenna.")
71
+ engine.remember("The tower was completed in 1889 and was originally intended to be temporary.")
72
+ engine.remember("It receives about 7 million visitors per year, making it the world's most visited paid monument.")
73
+
74
+ # Retrieve relevant knowledge
75
+ results = engine.recall("How tall is the Eiffel Tower?")
76
+ for r in results:
77
+ print(r.score, r.content)
78
+
79
+ # Consolidate — synthesizes the raw deposits into a compact knowledge article
80
+ summary = engine.consolidate()
81
+ print(summary)
82
+ # {'formed': 1, 'reconsolidated': 0, 'dropped': 0, 'kept': 0, 'flushed': 3, 'superseded': 0}
83
+
84
+ # Subsequent recalls now hit the synthesized article,
85
+ # and any new signal deposited before the next consolidate()
86
+ # will be blended in during reconsolidation.
87
+ results = engine.recall("Eiffel Tower visitors")
88
+ print(results[0].content)
89
+ ```
90
+
91
+ ---
92
+
93
+ ## License
94
+
95
+ MIT
@@ -112,6 +112,7 @@ class SearchResult:
112
112
  score: float # asymmetric blended score
113
113
  source: str # "injected" | "relational" | "blended"
114
114
  skill: str | None = None
115
+ created_at: float = 0.0 # unix timestamp of the original deposit
115
116
  metadata: dict[str, Any] = field(default_factory=dict)
116
117
 
117
118
 
@@ -108,13 +108,15 @@ def _result_to_search_result(
108
108
  source: str = "unknown",
109
109
  ) -> SearchResult:
110
110
  skill = metadata.get("skill") or None
111
+ created_at = float(metadata.get("created_at", 0.0))
111
112
  return SearchResult(
112
113
  id=doc_id,
113
114
  content=document,
114
115
  score=weight * (1.0 - distance), # convert distance → similarity score
115
116
  source=source,
116
117
  skill=skill,
117
- metadata={k: v for k, v in metadata.items() if k != "skill"},
118
+ created_at=created_at,
119
+ metadata={k: v for k, v in metadata.items() if k not in ("skill", "created_at")},
118
120
  )
119
121
 
120
122
 
@@ -0,0 +1,123 @@
1
+ Metadata-Version: 2.4
2
+ Name: etchmem
3
+ Version: 0.1.2
4
+ Summary: A pluggable, embeddable reconsolidating skill memory engine for AI agents
5
+ Author: Andrey Olishchuk
6
+ License: MIT
7
+ Project-URL: Repository, https://github.com/andrey-olishchuk/etchmem
8
+ Keywords: llm,agent,memory,chromadb,rag,reconsolidation,skill,skills,etchmem
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Requires-Python: >=3.11
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: chromadb>=1.5.0
22
+ Requires-Dist: openai>=1.70.0
23
+ Requires-Dist: anthropic>=0.100.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=8.0; extra == "dev"
26
+ Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
27
+ Dynamic: license-file
28
+
29
+ # etchmem
30
+
31
+ A lightweight, embeddable memory engine for LLM agents. Agents remember things, recall them later, and the stored knowledge quietly matures through use — no extra plumbing required.
32
+
33
+ ```bash
34
+ pip install etchmem
35
+ ```
36
+
37
+ ---
38
+
39
+ ## What it is
40
+
41
+ `etchmem` gives your agent a persistent memory that improves over time. You deposit raw observations, retrieve them with natural-language queries, and periodically consolidate — at which point the engine synthesizes scattered signals into compact knowledge articles and rewrites anything that's been recalled against fresh context.
42
+
43
+ It is not a vector database and not an agent runtime. It sits above [ChromaDB](https://www.trychroma.com/), which handles all storage and embedding, and exposes exactly **three methods**.
44
+
45
+ ---
46
+
47
+ ## How it works
48
+
49
+ Memory is kept in three tiers:
50
+
51
+ - **Relational** — raw, append-only records with a TTL. Fresh signal lives here.
52
+ - **Buffer** — a working space for deposits and recall-events, waiting for the next consolidation run.
53
+ - **Injected** — synthesized knowledge articles, the primary search target. Only current knowledge is kept; superseded articles are hard-deleted.
54
+
55
+ The key idea is **reconsolidation**: every `recall()` call emits a recall-event into the buffer. When you later call `consolidate()`, the engine detects which injected articles were used, checks whether fresh signal changes anything, and rewrites them if needed. Knowledge that gets recalled stays current as a side-effect of being recalled. Knowledge nobody asks about simply rests.
56
+
57
+ Embeddings are computed locally by ChromaDB's built-in model — no external embedding API. Synthesis (the rewrite step inside `consolidate`) calls an LLM via `OPENAI_API_KEY` or `ANTHROPIC_API_KEY`.
58
+
59
+ ---
60
+
61
+ ## API
62
+
63
+ ```python
64
+ from etchmem import Engine
65
+ engine = Engine() # persists to .etchmem/ in the current directory
66
+ ```
67
+
68
+ ### `remember(data, hint=None, skill=None, metadata=None)`
69
+
70
+ Deposits a text record into the relational tier. No LLM call — cheap.
71
+
72
+ - `data` — the text to store.
73
+ - `hint` — optional float 0–1, your importance signal.
74
+ - `skill` — optional scope name; lets you filter recall by agent skill.
75
+ - `metadata` — arbitrary dict (source URL, tags, …).
76
+
77
+ ### `recall(query, skill=None, top_k=None, hint=None) → list[SearchResult]`
78
+
79
+ Retrieves relevant knowledge and emits a recall-event for future reconsolidation. Results are blended from injected (primary) and relational (fresh signal), ranked by a composite score.
80
+
81
+ ### `consolidate(num_records="all", method="LIFO") → dict`
82
+
83
+ Runs the consolidation worker: clusters the buffer, forms new injected articles, reconsolidates recalled articles against fresh context, hard-deletes superseded ones. Returns a summary dict with counts (`formed`, `reconsolidated`, `dropped`, `kept`, `flushed`, `superseded`). Requires an LLM API key.
84
+
85
+ ---
86
+
87
+ ## Hello world
88
+
89
+ ```python
90
+ import os
91
+ from etchmem import Engine
92
+
93
+ os.environ["ANTHROPIC_API_KEY"] = "sk-ant-..." # or OPENAI_API_KEY
94
+
95
+ engine = Engine()
96
+
97
+ # Add some facts
98
+ engine.remember("The Eiffel Tower is 330 metres tall including its antenna.")
99
+ engine.remember("The tower was completed in 1889 and was originally intended to be temporary.")
100
+ engine.remember("It receives about 7 million visitors per year, making it the world's most visited paid monument.")
101
+
102
+ # Retrieve relevant knowledge
103
+ results = engine.recall("How tall is the Eiffel Tower?")
104
+ for r in results:
105
+ print(r.score, r.content)
106
+
107
+ # Consolidate — synthesizes the raw deposits into a compact knowledge article
108
+ summary = engine.consolidate()
109
+ print(summary)
110
+ # {'formed': 1, 'reconsolidated': 0, 'dropped': 0, 'kept': 0, 'flushed': 3, 'superseded': 0}
111
+
112
+ # Subsequent recalls now hit the synthesized article,
113
+ # and any new signal deposited before the next consolidate()
114
+ # will be blended in during reconsolidation.
115
+ results = engine.recall("Eiffel Tower visitors")
116
+ print(results[0].content)
117
+ ```
118
+
119
+ ---
120
+
121
+ ## License
122
+
123
+ MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "etchmem"
7
- version = "0.1.0"
7
+ version = "0.1.2"
8
8
  description = "A pluggable, embeddable reconsolidating skill memory engine for AI agents"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
etchmem-0.1.0/PKG-INFO DELETED
@@ -1,29 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: etchmem
3
- Version: 0.1.0
4
- Summary: A pluggable, embeddable reconsolidating skill memory engine for AI agents
5
- Author: Andrey Olishchuk
6
- License: MIT
7
- Project-URL: Repository, https://github.com/andrey-olishchuk/etchmem
8
- Keywords: llm,agent,memory,chromadb,rag,reconsolidation,skill,skills,etchmem
9
- Classifier: Development Status :: 3 - Alpha
10
- Classifier: Intended Audience :: Developers
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.11
14
- Classifier: Programming Language :: Python :: 3.12
15
- Classifier: Programming Language :: Python :: 3.13
16
- Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
- Requires-Python: >=3.11
19
- Description-Content-Type: text/markdown
20
- License-File: LICENSE
21
- Requires-Dist: chromadb>=1.5.0
22
- Requires-Dist: openai>=1.70.0
23
- Requires-Dist: anthropic>=0.100.0
24
- Provides-Extra: dev
25
- Requires-Dist: pytest>=8.0; extra == "dev"
26
- Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
27
- Dynamic: license-file
28
-
29
- # etchmem
etchmem-0.1.0/README.md DELETED
@@ -1 +0,0 @@
1
- # etchmem
@@ -1,29 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: etchmem
3
- Version: 0.1.0
4
- Summary: A pluggable, embeddable reconsolidating skill memory engine for AI agents
5
- Author: Andrey Olishchuk
6
- License: MIT
7
- Project-URL: Repository, https://github.com/andrey-olishchuk/etchmem
8
- Keywords: llm,agent,memory,chromadb,rag,reconsolidation,skill,skills,etchmem
9
- Classifier: Development Status :: 3 - Alpha
10
- Classifier: Intended Audience :: Developers
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.11
14
- Classifier: Programming Language :: Python :: 3.12
15
- Classifier: Programming Language :: Python :: 3.13
16
- Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
- Requires-Python: >=3.11
19
- Description-Content-Type: text/markdown
20
- License-File: LICENSE
21
- Requires-Dist: chromadb>=1.5.0
22
- Requires-Dist: openai>=1.70.0
23
- Requires-Dist: anthropic>=0.100.0
24
- Provides-Extra: dev
25
- Requires-Dist: pytest>=8.0; extra == "dev"
26
- Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
27
- Dynamic: license-file
28
-
29
- # etchmem
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes