wavemind 2.1.0__tar.gz → 2.2.0__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 (112) hide show
  1. {wavemind-2.1.0 → wavemind-2.2.0}/CONTRIBUTING.md +2 -0
  2. {wavemind-2.1.0 → wavemind-2.2.0}/MANIFEST.in +6 -0
  3. {wavemind-2.1.0 → wavemind-2.2.0}/PKG-INFO +273 -125
  4. {wavemind-2.1.0 → wavemind-2.2.0}/README.md +272 -124
  5. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/ann_index_curve_benchmark.py +7 -4
  6. {wavemind-2.1.0 → wavemind-2.2.0}/docker-compose.yml +1 -1
  7. wavemind-2.2.0/docs/CHROMA_MIGRATION.md +412 -0
  8. wavemind-2.2.0/docs/DEMO_SCRIPT.md +116 -0
  9. wavemind-2.2.0/docs/LAUNCH_KIT.md +361 -0
  10. {wavemind-2.1.0 → wavemind-2.2.0}/docs/PROJECT_BOARD.md +6 -1
  11. {wavemind-2.1.0 → wavemind-2.2.0}/docs/ROADMAP.md +4 -2
  12. wavemind-2.2.0/docs/RU_LAUNCH_POSTS.md +192 -0
  13. wavemind-2.2.0/docs/USE_CASES.md +274 -0
  14. wavemind-2.2.0/docs/assets/wavemind-social-card.svg +104 -0
  15. {wavemind-2.1.0 → wavemind-2.2.0}/examples/demo.py +2 -2
  16. wavemind-2.2.0/examples/dynamic_memory_demo.py +134 -0
  17. {wavemind-2.1.0 → wavemind-2.2.0}/pyproject.toml +1 -1
  18. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_api.py +77 -0
  19. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_cli_smoke.py +31 -0
  20. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_core_persistence.py +26 -0
  21. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_examples.py +25 -3
  22. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_indexes_encoders.py +17 -0
  23. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_packaging_files.py +7 -0
  24. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/__init__.py +1 -1
  25. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/api.py +47 -1
  26. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/cli.py +95 -1
  27. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/core.py +101 -0
  28. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/indexes.py +199 -0
  29. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/storage.py +51 -0
  30. wavemind-2.2.0/wavemind/studio.py +703 -0
  31. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind.egg-info/PKG-INFO +273 -125
  32. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind.egg-info/SOURCES.txt +8 -0
  33. {wavemind-2.1.0 → wavemind-2.2.0}/Dockerfile +0 -0
  34. {wavemind-2.1.0 → wavemind-2.2.0}/LICENSE +0 -0
  35. {wavemind-2.1.0 → wavemind-2.2.0}/SECURITY.md +0 -0
  36. {wavemind-2.1.0 → wavemind-2.2.0}/SUPPORT.md +0 -0
  37. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/BENCHMARK_REPORT.md +0 -0
  38. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/agent_memory_benchmark.py +0 -0
  39. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/agent_memory_results.json +0 -0
  40. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/ann_index_curve_results.json +0 -0
  41. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/benchmark_matrix_results.json +0 -0
  42. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/benchmark_registry.py +0 -0
  43. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/dynamic_memory_benchmark.py +0 -0
  44. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/dynamic_memory_results.json +0 -0
  45. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/field_memory_dynamics_benchmark.py +0 -0
  46. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/field_memory_dynamics_results.json +0 -0
  47. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/locomo_evidence_results.json +0 -0
  48. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/locomo_memory_benchmark.py +0 -0
  49. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/locomo_sentence_evidence_results.json +0 -0
  50. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/long_memory_evidence_benchmark.py +0 -0
  51. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/long_memory_evidence_results.json +0 -0
  52. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/longmemeval_answer_benchmark.py +0 -0
  53. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/longmemeval_answer_extractive_20_results.json +0 -0
  54. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/longmemeval_evidence_50_results.json +0 -0
  55. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/longmemeval_evidence_results.json +0 -0
  56. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/longmemeval_memory_benchmark.py +0 -0
  57. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/open_retrieval_benchmark.py +0 -0
  58. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/open_retrieval_scifact_results.json +0 -0
  59. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/render_benchmark_charts.py +0 -0
  60. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/render_benchmark_report.py +0 -0
  61. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/ru_sentences_benchmark.py +0 -0
  62. {wavemind-2.1.0 → wavemind-2.2.0}/benchmarks/wavemind_capacity_results.json +0 -0
  63. {wavemind-2.1.0 → wavemind-2.2.0}/docs/RELEASE.md +0 -0
  64. {wavemind-2.1.0 → wavemind-2.2.0}/docs/assets/benchmark-summary.svg +0 -0
  65. {wavemind-2.1.0 → wavemind-2.2.0}/examples/agent_with_memory.py +0 -0
  66. {wavemind-2.1.0 → wavemind-2.2.0}/examples/framework_integrations.py +0 -0
  67. {wavemind-2.1.0 → wavemind-2.2.0}/examples/langchain_memory.py +0 -0
  68. {wavemind-2.1.0 → wavemind-2.2.0}/examples/sharded_memory.py +0 -0
  69. {wavemind-2.1.0 → wavemind-2.2.0}/install.bat +0 -0
  70. {wavemind-2.1.0 → wavemind-2.2.0}/install.sh +0 -0
  71. {wavemind-2.1.0 → wavemind-2.2.0}/requirements-optional.txt +0 -0
  72. {wavemind-2.1.0 → wavemind-2.2.0}/requirements.txt +0 -0
  73. {wavemind-2.1.0 → wavemind-2.2.0}/setup.cfg +0 -0
  74. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_agent_memory_benchmark.py +0 -0
  75. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_ann_index_curve_benchmark.py +0 -0
  76. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_api_process_persistence.py +0 -0
  77. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_benchmark_charts.py +0 -0
  78. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_benchmark_registry.py +0 -0
  79. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_benchmark_report.py +0 -0
  80. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_dynamic_memory_benchmark.py +0 -0
  81. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_field_graph.py +0 -0
  82. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_field_graph_integration.py +0 -0
  83. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_field_memory_dynamics_benchmark.py +0 -0
  84. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_framework_adapters.py +0 -0
  85. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_import_benchmark.py +0 -0
  86. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_langchain_integration.py +0 -0
  87. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_locomo_memory_benchmark.py +0 -0
  88. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_long_memory_evidence_benchmark.py +0 -0
  89. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_longmemeval_answer_benchmark.py +0 -0
  90. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_longmemeval_memory_benchmark.py +0 -0
  91. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_observability.py +0 -0
  92. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_open_retrieval_benchmark.py +0 -0
  93. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_postgres_storage.py +0 -0
  94. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_semantic_and_latency.py +0 -0
  95. {wavemind-2.1.0 → wavemind-2.2.0}/tests/test_sharding.py +0 -0
  96. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/__main__.py +0 -0
  97. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/benchmark.py +0 -0
  98. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/encoders.py +0 -0
  99. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/field_graph.py +0 -0
  100. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/importers.py +0 -0
  101. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/integrations/__init__.py +0 -0
  102. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/integrations/autogen.py +0 -0
  103. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/integrations/crewai.py +0 -0
  104. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/integrations/langchain.py +0 -0
  105. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/integrations/langgraph.py +0 -0
  106. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/integrations/llamaindex.py +0 -0
  107. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/observability.py +0 -0
  108. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind/sharding.py +0 -0
  109. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind.egg-info/dependency_links.txt +0 -0
  110. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind.egg-info/entry_points.txt +0 -0
  111. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind.egg-info/requires.txt +0 -0
  112. {wavemind-2.1.0 → wavemind-2.2.0}/wavemind.egg-info/top_level.txt +0 -0
@@ -92,6 +92,8 @@ Current scale roadmap:
92
92
 
93
93
  See [`docs/ROADMAP.md`](docs/ROADMAP.md) for the full roadmap.
94
94
  See [`docs/RELEASE.md`](docs/RELEASE.md) for release mechanics.
95
+ See [`docs/LAUNCH_KIT.md`](docs/LAUNCH_KIT.md) for public positioning,
96
+ benchmark-claim guardrails, and community launch drafts.
95
97
 
96
98
  ## Pull Request Style
97
99
 
@@ -12,7 +12,13 @@ include requirements-optional.txt
12
12
  include docs/ROADMAP.md
13
13
  include docs/RELEASE.md
14
14
  include docs/PROJECT_BOARD.md
15
+ include docs/DEMO_SCRIPT.md
16
+ include docs/LAUNCH_KIT.md
17
+ include docs/CHROMA_MIGRATION.md
18
+ include docs/RU_LAUNCH_POSTS.md
19
+ include docs/USE_CASES.md
15
20
  include docs/assets/benchmark-summary.svg
21
+ include docs/assets/wavemind-social-card.svg
16
22
  include benchmarks/*.py
17
23
  include benchmarks/*.json
18
24
  include benchmarks/*.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wavemind
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: Local-first dynamic memory field with vector search and wave-field re-ranking
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/CaspianG/wavemind
@@ -52,25 +52,29 @@ Dynamic: license-file
52
52
 
53
53
  # WaveMind
54
54
 
55
- **A local-first dynamic memory field for software that needs to remember.**
55
+ **Local-first dynamic memory for apps, agents, notebooks, and tools.**
56
56
 
57
- Most storage systems answer one question: "what record is closest to this
58
- query?" WaveMind adds a second question: "what information still matters right
59
- now?"
60
-
61
- It stores text, vectors, metadata, and recall state in SQLite. A wave-field
62
- priority layer then reinforces useful memories, lets stale facts fade, respects
63
- namespaces, and keeps the final recall set small enough for real applications.
57
+ WaveMind stores memories in SQLite, finds relevant candidates with vector
58
+ search, then uses a wave-field priority layer to decide what still matters:
59
+ hot facts rise, stale facts fade, temporary facts expire, and namespaces keep
60
+ users or projects isolated.
64
61
 
65
62
  ![Python](https://img.shields.io/badge/python-3.10%2B-blue)
66
63
  [![PyPI](https://img.shields.io/pypi/v/wavemind.svg)](https://pypi.org/project/wavemind/)
67
64
  [![Tests](https://github.com/CaspianG/wavemind/actions/workflows/tests.yml/badge.svg)](https://github.com/CaspianG/wavemind/actions/workflows/tests.yml)
68
65
  ![License](https://img.shields.io/badge/license-MIT-green)
69
66
 
70
- [Concept](#concept) |
67
+ <img src="https://raw.githubusercontent.com/CaspianG/wavemind/main/docs/assets/wavemind-social-card.svg" alt="WaveMind dynamic memory overview" width="820">
68
+
71
69
  [Quick Start](#quick-start) |
70
+ [CLI](#cli-cheat-sheet) |
71
+ [Studio](#wavemind-studio) |
72
+ [Python Example](#python-example) |
73
+ [HTTP Example](#http-example) |
74
+ [Where Data Lives](#where-data-lives) |
72
75
  [LangChain](#langchain-memory) |
73
- [OpenClaw](#openclaw-integration) |
76
+ [Chroma Migration](docs/CHROMA_MIGRATION.md) |
77
+ [Use Cases](docs/USE_CASES.md) |
74
78
  [HTTP API](#http-api) |
75
79
  [Benchmarks](#benchmark) |
76
80
  [Roadmap](#roadmap) |
@@ -79,38 +83,246 @@ namespaces, and keeps the final recall set small enough for real applications.
79
83
 
80
84
  </div>
81
85
 
82
- ## Concept
86
+ ## What Is WaveMind?
87
+
88
+ WaveMind is a dynamic memory engine you can embed in a product.
83
89
 
84
- WaveMind is not a replacement for every database. It is a memory layer for
85
- information that changes in importance over time: preferences, decisions,
86
- corrections, notes, research snippets, support history, agent context, or any
87
- small-to-medium knowledge stream where "latest", "repeated", "expired", and
88
- "scoped to this user/project" matter.
90
+ Use it when your app needs to remember things like user preferences, decisions,
91
+ corrections, notes, research snippets, support history, agent context, or
92
+ temporary facts.
89
93
 
90
- The simple version:
94
+ The short version:
91
95
 
92
96
  ```text
93
- ordinary vector search: find the nearest text
94
- WaveMind: find the nearest useful memory
97
+ normal vector search: find the nearest text
98
+ WaveMind: find the nearest useful memory
95
99
  ```
96
100
 
97
- Under the hood, WaveMind still starts with normal vector search. The difference
98
- is the memory state around it: hotness, priority, decay, TTL, tags, namespaces,
99
- and optional memory-to-memory graph dynamics. That state is why the same stored
100
- fact can become stronger after repeated use, weaker after time passes, or
101
- disappear from recall after expiry.
101
+ WaveMind is not trying to replace every vector database. It is the memory layer
102
+ around retrieval: persistence, namespaces, TTL, hotness, priority, decay,
103
+ explicit forgetting, audit events, and optional graph dynamics.
104
+
105
+ ## 60-Second Version
106
+
107
+ | Question | Answer |
108
+ |---|---|
109
+ | What does it store? | Text memories, vectors, metadata, tags, TTL, priority, and recall state. |
110
+ | Where does it store data? | A local SQLite file by default; Postgres is available for production state. |
111
+ | How do I use it? | CLI, Python API, FastAPI HTTP server, LangChain memory, or framework adapters. |
112
+ | What is different from Chroma/Qdrant? | WaveMind adds memory policy: hotness, decay, TTL, correction handling, and scoped recall. |
113
+ | When should I not use it? | For huge static document search where a mature vector DB is already the right tool. |
114
+ | What is the simplest install? | `python -m pip install wavemind` |
102
115
 
103
- ## At a Glance
116
+ ## Why Use It?
104
117
 
105
118
  | If you need... | WaveMind gives you... |
106
119
  |---|---|
107
- | Memory that survives restarts | SQLite-backed `remember()`, `query()`, and `forget()`. |
108
- | Scoped recall per user, app, agent, or project | Namespaces and tags on every record. |
109
- | Information that changes importance over time | Hotness, priority, TTL, and decay-aware ranking. |
110
- | A local data source you can inspect and back up | One SQLite file is the source of truth. |
111
- | Easy integration | Python API, CLI, FastAPI server, and LangChain memory class. |
112
- | Honest benchmarks | Public LoCoMo, LongMemEval, BEIR/SciFact, and local policy checks. |
113
- | Production hooks | API keys, rate limits, audit log, Prometheus metrics, OpenTelemetry traces, backups, and optional external indexes. |
120
+ | Memory that survives restarts | One SQLite file stores text, vectors, metadata, TTL, and recall state. |
121
+ | Per-user or per-project recall | Namespaces and tags keep memories separated. |
122
+ | Temporary facts | `ttl_seconds` lets facts expire automatically. |
123
+ | Corrections and changing preferences | Newer or reinforced memories can outrank stale ones. |
124
+ | A simple integration path | Python API, CLI, FastAPI server, and LangChain memory class. |
125
+ | Production hygiene | Backups, audit log, API keys, rate limits, Prometheus metrics, and OpenTelemetry traces. |
126
+
127
+ ## Quick Start
128
+
129
+ The shortest path from install to first recall:
130
+
131
+ ```sh
132
+ python -m pip install wavemind
133
+ wavemind remember "Andrey is a trader" --namespace demo
134
+ wavemind query "What does Andrey do?" --namespace demo
135
+ ```
136
+
137
+ Need a reminder after install?
138
+
139
+ ```sh
140
+ wavemind quickstart
141
+ ```
142
+
143
+ Want to see and manage memory in a browser?
144
+
145
+ ```sh
146
+ wavemind studio
147
+ ```
148
+
149
+ By default, WaveMind creates `wavemind.sqlite3` in the current working
150
+ directory. That file is the local source of truth. Keep it out of git and back
151
+ it up like application state.
152
+
153
+ ## CLI Cheat Sheet
154
+
155
+ Start here if you only want to use WaveMind from the terminal:
156
+
157
+ | Goal | Command |
158
+ |---|---|
159
+ | Show first-run help | `wavemind quickstart` |
160
+ | Store a memory | `wavemind remember "Andrey prefers short answers" --namespace user:42` |
161
+ | Search memory | `wavemind query "answer style" --namespace user:42` |
162
+ | Open local dashboard | `wavemind studio` |
163
+ | See stored state | `wavemind stats --namespace user:42` |
164
+ | Delete a namespace | `wavemind forget --namespace user:42` |
165
+ | Import notes | `wavemind import ./notes.txt --namespace project:alpha` |
166
+ | Use another database file | `wavemind --db ./state/memory.sqlite3 query "budget" --namespace user:42` |
167
+ | Start the HTTP API | `wavemind --db ./state/memory.sqlite3 serve --host 127.0.0.1 --port 8000` |
168
+
169
+ After this point, choose the integration path you need: Python, HTTP, LangChain,
170
+ framework adapters, benchmarks, or production deployment.
171
+
172
+ ## WaveMind Studio
173
+
174
+ WaveMind Studio is the built-in local dashboard. It runs on top of the same
175
+ FastAPI app and SQLite database as the CLI:
176
+
177
+ ```sh
178
+ wavemind studio
179
+ ```
180
+
181
+ It opens `http://127.0.0.1:8000/studio` and gives you:
182
+
183
+ | View | What it is for |
184
+ |---|---|
185
+ | Memory map | See field energy as a heatmap. |
186
+ | Namespace explorer | Inspect memories per user, project, agent, or tenant. |
187
+ | Live query tester | Test recall before wiring it into an app. |
188
+ | Feedback buttons | Mark recalled memories as useful or not useful. |
189
+ | Import/export | Import local files and export a namespace snapshot. |
190
+ | Backup | Create SQLite backups from the browser. |
191
+ | Conflict visualizer | Inspect correction groups when memories disagree. |
192
+
193
+ For a server-safe local bind:
194
+
195
+ ```sh
196
+ wavemind --db ./state/wavemind.sqlite3 studio --host 127.0.0.1 --port 8000
197
+ ```
198
+
199
+ ## Python Example
200
+
201
+ ```python
202
+ from wavemind import WaveMind
203
+
204
+ memory = WaveMind(db_path="./state/wavemind.sqlite3")
205
+
206
+ memory.remember(
207
+ "The user prefers short practical answers.",
208
+ namespace="user:42",
209
+ tags=["preference"],
210
+ )
211
+
212
+ hits = memory.query("How should I answer this user?", namespace="user:42", top_k=3)
213
+ for hit in hits:
214
+ print(hit.score, hit.text)
215
+ ```
216
+
217
+ The integration pattern is intentionally small:
218
+
219
+ 1. Call `query()` before your app, agent, tool, or UI needs context.
220
+ 2. Pass the returned memories into your prompt, screen, search result, or
221
+ decision function.
222
+ 3. Call `remember()` after something worth keeping happens.
223
+
224
+ ## HTTP Example
225
+
226
+ The FastAPI server is included in the base install:
227
+
228
+ ```sh
229
+ wavemind --db ./state/wavemind.sqlite3 serve --host 127.0.0.1 --port 8000
230
+ ```
231
+
232
+ Then use WaveMind from any language:
233
+
234
+ ```sh
235
+ curl -X POST http://127.0.0.1:8000/remember \
236
+ -H "Content-Type: application/json" \
237
+ -d "{\"text\":\"Andrey prefers short answers\",\"namespace\":\"user:42\",\"tags\":[\"preference\"]}"
238
+
239
+ curl -X POST http://127.0.0.1:8000/query \
240
+ -H "Content-Type: application/json" \
241
+ -d "{\"query\":\"How should I answer?\",\"namespace\":\"user:42\",\"top_k\":3}"
242
+ ```
243
+
244
+ ## Where Data Lives
245
+
246
+ WaveMind is local-first. The SQLite database stores memories, vectors, metadata,
247
+ namespaces, tags, TTL, hotness, priority, and audit events.
248
+
249
+ | runtime | Suggested database path |
250
+ |---|---|
251
+ | quick CLI experiment | `./wavemind.sqlite3` |
252
+ | Python app or agent | `./state/wavemind.sqlite3` |
253
+ | desktop app | user data directory, for example `%APPDATA%` or `~/.local/share` |
254
+ | server daemon | `/var/lib/wavemind/wavemind.sqlite3` |
255
+ | Docker | mounted volume, for example `/data/wavemind.sqlite3` |
256
+
257
+ Explicit path:
258
+
259
+ ```sh
260
+ wavemind --db ./state/app_memory.sqlite3 remember "Andrey prefers short answers" --namespace user:42
261
+ wavemind --db ./state/app_memory.sqlite3 query "answer style" --namespace user:42
262
+ ```
263
+
264
+ ## Common Ways To Use It
265
+
266
+ | You are building... | Start with... |
267
+ |---|---|
268
+ | Python app | `from wavemind import WaveMind` |
269
+ | LangChain agent | `WaveMindMemory` from `wavemind.integrations.langchain` |
270
+ | LangGraph workflow | `make_recall_node()` and `make_persist_node()` |
271
+ | LlamaIndex pipeline | `WaveMindRetriever` |
272
+ | CrewAI or AutoGen loop | The adapters in `wavemind.integrations` |
273
+ | Node, Go, Ruby, PHP, or no-code app | `wavemind serve` and the HTTP API |
274
+ | Personal knowledge base | Store notes by project namespace and query locally |
275
+ | Support or CRM workflow | Store customer issues, resolutions, preferences, and corrections |
276
+ | Research or trading notebook | Store observations with source metadata and TTL for temporary hypotheses |
277
+
278
+ For migrations from existing local vector memory, start with
279
+ [`docs/CHROMA_MIGRATION.md`](docs/CHROMA_MIGRATION.md).
280
+
281
+ ## Minimal Agent Loop
282
+
283
+ ```python
284
+ from wavemind import WaveMind
285
+
286
+ memory = WaveMind(db_path="./state/agent.sqlite3")
287
+
288
+ def run_turn(user_id: str, user_text: str) -> str:
289
+ namespace = f"user:{user_id}"
290
+ hits = memory.query(user_text, namespace=namespace, top_k=5, min_score=0.25)
291
+ recalled = "\n".join(f"- {hit.text}" for hit in hits)
292
+
293
+ answer = call_your_llm(f"Relevant memory:\n{recalled}\n\nUser: {user_text}")
294
+
295
+ memory.remember(f"User said: {user_text}", namespace=namespace, tags=["conversation"])
296
+ memory.remember(f"Assistant answered: {answer}", namespace=namespace, tags=["conversation"])
297
+ return answer
298
+ ```
299
+
300
+ ## Terminal Demo
301
+
302
+ From a cloned repository:
303
+
304
+ ```text
305
+ $ python examples/demo.py
306
+ [ok] Remembered: "Andrey is a trader who tracks market breakouts."
307
+ [ok] Remembered: "Andrey prefers short practical answers about product decisions."
308
+
309
+ Query: "Andrey trader preferences"
310
+ -> Result 1 (0.60): "Andrey is a trader who tracks market breakouts."
311
+ -> Result 2 (0.30): "Andrey prefers short practical answers about product decisions."
312
+ ```
313
+
314
+ The demo is offline, keyless, and uses the built-in hash encoder.
315
+
316
+ To see the behavior that plain vector search does not provide:
317
+
318
+ ```sh
319
+ python examples/dynamic_memory_demo.py
320
+ ```
321
+
322
+ That demo shows corrected facts outranking stale facts, temporary memory
323
+ expiring, namespace isolation, and index-health reporting.
324
+
325
+ ## How The Memory Field Works
114
326
 
115
327
  ```mermaid
116
328
  flowchart LR
@@ -125,10 +337,9 @@ flowchart LR
125
337
  F --> D
126
338
  ```
127
339
 
128
- ## What The Wave Field Does
129
-
130
- The "field" is the dynamic layer around stored memories. It is not just a
131
- marketing name for embeddings.
340
+ The wave field is the dynamic layer around stored memories. It is not a
341
+ replacement for embeddings; it is the policy that decides which candidate
342
+ memories should still matter.
132
343
 
133
344
  | signal | Plain meaning | Effect |
134
345
  |---|---|---|
@@ -145,39 +356,6 @@ memories, not a continuous mathematical physics field. That honesty matters:
145
356
  WaveMind is useful today as a dynamic memory engine, while the research path is
146
357
  to make the field dynamics more explicit, measurable, and scalable.
147
358
 
148
- ## Terminal Demo
149
-
150
- From a cloned repository:
151
-
152
- ```text
153
- $ python examples/demo.py
154
- [ok] Remembered: "Andrey is a trader who tracks market breakouts."
155
- [ok] Remembered: "Andrey prefers short practical answers about product decisions."
156
-
157
- Query: "Andrey trader preferences"
158
- -> Result 1 (0.60): "Andrey is a trader who tracks market breakouts."
159
- -> Result 2 (0.30): "Andrey prefers short practical answers about product decisions."
160
- ```
161
-
162
- The demo is offline, keyless, and uses the built-in hash encoder.
163
-
164
- ## Quick Start
165
-
166
- Install from PyPI and create your first local memory:
167
-
168
- ```sh
169
- python -m pip install wavemind
170
- wavemind remember "Andrey is a trader" --namespace demo
171
- wavemind query "trader" --namespace demo
172
- ```
173
-
174
- What happens here:
175
-
176
- - `remember` writes the text and its vector pattern into a local SQLite database.
177
- - By default, the database file is `wavemind.sqlite3` in your current working directory.
178
- - `--namespace demo` keeps this memory separate from other users, agents, or projects.
179
- - `query` reads from the same SQLite file and returns the closest remembered texts.
180
-
181
359
  ## Optional Embeddings
182
360
 
183
361
  For sentence-transformer embeddings:
@@ -215,6 +393,16 @@ wavemind --index faiss-persisted query "trader" --namespace demo
215
393
  SQLite or Postgres remains the source of truth. The persisted FAISS files are a
216
394
  candidate-index snapshot and are validated against the current memory ids on
217
395
  load. If the snapshot does not match the stored memories, WaveMind rebuilds it.
396
+ You can also check and rebuild the candidate index explicitly:
397
+
398
+ ```sh
399
+ wavemind --index faiss-persisted index-health --json
400
+ wavemind --index faiss-persisted rebuild-index
401
+ ```
402
+
403
+ Index health compares durable memory ids against the candidate index. Local
404
+ indexes report exact missing/extra ids; service backends report exact ids when
405
+ the backend exposes an id scan and otherwise fall back to count-based health.
218
406
 
219
407
  pgvector setup:
220
408
 
@@ -250,38 +438,6 @@ production latency and durability should be measured against a real Qdrant
250
438
  service. If `WAVEMIND_QDRANT_URL` is missing, WaveMind raises a clear error
251
439
  instead of silently falling back to another backend.
252
440
 
253
- ## Data Location
254
-
255
- For an explicit database path, put global options before the command:
256
-
257
- ```sh
258
- wavemind --db ./app_memory.sqlite3 remember "Andrey is a trader" --namespace demo
259
- wavemind --db ./app_memory.sqlite3 query "trader" --namespace demo
260
- ```
261
-
262
- WaveMind is local-first. One SQLite file is the source of truth for texts,
263
- metadata, vectors, namespaces, tags, TTL, and recall state. For real agents,
264
- prefer an explicit path under your application's state directory:
265
-
266
- ```python
267
- from wavemind import WaveMind
268
-
269
- memory = WaveMind(db_path="./state/wavemind.sqlite3")
270
- memory.remember("The user prefers short answers.", namespace="user:42", tags=["preference"])
271
- ```
272
-
273
- Useful storage patterns:
274
-
275
- | runtime | Suggested database path |
276
- |---|---|
277
- | local CLI experiment | `./wavemind.sqlite3` |
278
- | Python app or agent | `./state/wavemind.sqlite3` |
279
- | OpenClaw sidecar | `~/.openclaw/wavemind/<agent-id>.sqlite3` |
280
- | server daemon | `/var/lib/wavemind/wavemind.sqlite3` |
281
- | Docker | mounted volume, for example `/data/wavemind.sqlite3` |
282
-
283
- Keep the SQLite file out of git. Back it up like any other application state.
284
-
285
441
  ## Storage Backends
286
442
 
287
443
  SQLite is the default source of truth. For multi-tenant production deployments,
@@ -355,6 +511,8 @@ curl http://127.0.0.1:8000/stats?namespace=demo
355
511
  curl http://127.0.0.1:8000/audit?namespace=demo
356
512
  curl http://127.0.0.1:8000/metrics
357
513
  curl http://127.0.0.1:8000/observability
514
+ curl http://127.0.0.1:8000/index/health
515
+ curl -X POST http://127.0.0.1:8000/index/rebuild
358
516
  curl -X POST http://127.0.0.1:8000/backup -H "Content-Type: application/json" -d '{"path":"./backups","keep_last":7}'
359
517
  ```
360
518
 
@@ -362,6 +520,9 @@ curl -X POST http://127.0.0.1:8000/backup -H "Content-Type: application/json" -d
362
520
  `purge_expired`. Query audit is opt-in with `WAVEMIND_AUDIT_QUERIES=1` because
363
521
  writing an audit row for every query changes latency. `/metrics` returns a
364
522
  Prometheus-compatible text payload without adding a required dependency.
523
+ `/index/health` reports source-of-truth versus candidate-index consistency.
524
+ `/index/rebuild` rebuilds the candidate index from stored active memories and
525
+ logs an `index_rebuild` audit event.
365
526
 
366
527
  OpenTelemetry traces are optional and off by default:
367
528
 
@@ -392,9 +553,9 @@ Role behavior:
392
553
 
393
554
  | role | Env var | Allows |
394
555
  |---|---|---|
395
- | read | `WAVEMIND_READ_KEYS` | `/query`, `/stats`, `/metrics` |
556
+ | read | `WAVEMIND_READ_KEYS` | `/query`, `/stats`, `/metrics`, `/index/health` |
396
557
  | write | `WAVEMIND_WRITE_KEYS` | read actions plus `/remember` and `/import` |
397
- | admin | `WAVEMIND_ADMIN_KEYS` or `WAVEMIND_API_KEYS` | all actions, including `/audit`, `/backup`, and `/forget` |
558
+ | admin | `WAVEMIND_ADMIN_KEYS` or `WAVEMIND_API_KEYS` | all actions, including `/audit`, `/backup`, `/index/rebuild`, and `/forget` |
398
559
 
399
560
  Keys are accepted through `Authorization: Bearer <key>` or `X-API-Key: <key>`.
400
561
  If no key env vars are set, authentication is disabled for local development.
@@ -442,7 +603,7 @@ Offline runnable example from a cloned repository:
442
603
  python examples/langchain_memory.py
443
604
  ```
444
605
 
445
- ## Integration Patterns
606
+ ## Framework Integrations
446
607
 
447
608
  WaveMind only needs two touch points in an agent, service, notebook, or app:
448
609
 
@@ -471,6 +632,9 @@ That makes it usable in more than LangChain:
471
632
  | Preference/profile memory | Store with tags such as `profile`, `preference`, `project`, `decision`. |
472
633
  | Corrections/privacy | Use `forget()` or namespace deletion workflows. |
473
634
 
635
+ More examples: [`docs/USE_CASES.md`](docs/USE_CASES.md).
636
+ Migrating from a Chroma memory store: [`docs/CHROMA_MIGRATION.md`](docs/CHROMA_MIGRATION.md).
637
+
474
638
  Framework examples in this repository:
475
639
 
476
640
  | Framework / pattern | Example |
@@ -483,26 +647,6 @@ Framework examples in this repository:
483
647
  | AutoGen-style hooks | `wavemind.integrations.autogen`, `examples/framework_integrations.py` |
484
648
  | Namespace sharding | `examples/sharded_memory.py` |
485
649
 
486
- Minimal custom agent loop:
487
-
488
- ```python
489
- from wavemind import WaveMind
490
-
491
- memory = WaveMind(db_path="./state/wavemind.sqlite3")
492
-
493
- def run_turn(user_id: str, user_text: str, history: list[str]) -> str:
494
- namespace = f"user:{user_id}"
495
- hits = memory.query(user_text, namespace=namespace, top_k=5, min_score=0.25)
496
- recalled = "\n".join(f"- {hit.text}" for hit in hits)
497
-
498
- prompt = f"Relevant memory:\n{recalled}\n\nUser: {user_text}"
499
- answer = call_your_llm(prompt, history)
500
-
501
- memory.remember(f"User said: {user_text}", namespace=namespace, tags=["conversation"])
502
- memory.remember(f"Assistant answered: {answer}", namespace=namespace, tags=["conversation"])
503
- return answer
504
- ```
505
-
506
650
  ## OpenClaw Integration
507
651
 
508
652
  [OpenClaw memory](https://docs.openclaw.ai/concepts/memory) is file-centered:
@@ -1071,6 +1215,9 @@ python benchmarks/dynamic_memory_benchmark.py --engines wavemind chroma --memori
1071
1215
 
1072
1216
  WaveMind is not trying to replace dedicated vector databases at scale. The intended product gap is dynamic priority: frequently used memories can become hotter while old or low-priority memories fade. For static RAG over large document collections, use a mature vector database. For memory that needs persistence, scoped recall, TTL, forgetting, and reinforcement, WaveMind is designed to sit above or beside the vector index.
1073
1217
 
1218
+ If you already use Chroma for local memory, see the practical migration guide:
1219
+ [`docs/CHROMA_MIGRATION.md`](docs/CHROMA_MIGRATION.md).
1220
+
1074
1221
  ## Known Limitations
1075
1222
 
1076
1223
  - Optimal capacity on the current NumPy exact index is up to 1000 records.
@@ -1107,6 +1254,7 @@ WaveMind is not trying to replace dedicated vector databases at scale. The inten
1107
1254
  ## Roadmap
1108
1255
 
1109
1256
  Full roadmap: [`docs/ROADMAP.md`](docs/ROADMAP.md).
1257
+ Launch and positioning kit: [`docs/LAUNCH_KIT.md`](docs/LAUNCH_KIT.md).
1110
1258
 
1111
1259
  Near-term priorities:
1112
1260