wavemind 2.0.2__tar.gz → 2.0.3__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 (34) hide show
  1. {wavemind-2.0.2/wavemind.egg-info → wavemind-2.0.3}/PKG-INFO +17 -1
  2. {wavemind-2.0.2 → wavemind-2.0.3}/README.md +15 -0
  3. {wavemind-2.0.2 → wavemind-2.0.3}/pyproject.toml +2 -1
  4. {wavemind-2.0.2 → wavemind-2.0.3}/tests/test_api.py +40 -1
  5. {wavemind-2.0.2 → wavemind-2.0.3}/tests/test_packaging_files.py +21 -0
  6. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind/__init__.py +3 -0
  7. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind/api.py +4 -3
  8. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind/integrations/langchain.py +4 -11
  9. {wavemind-2.0.2 → wavemind-2.0.3/wavemind.egg-info}/PKG-INFO +17 -1
  10. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind.egg-info/requires.txt +1 -0
  11. {wavemind-2.0.2 → wavemind-2.0.3}/LICENSE +0 -0
  12. {wavemind-2.0.2 → wavemind-2.0.3}/setup.cfg +0 -0
  13. {wavemind-2.0.2 → wavemind-2.0.3}/tests/test_agent_memory_benchmark.py +0 -0
  14. {wavemind-2.0.2 → wavemind-2.0.3}/tests/test_api_process_persistence.py +0 -0
  15. {wavemind-2.0.2 → wavemind-2.0.3}/tests/test_cli_smoke.py +0 -0
  16. {wavemind-2.0.2 → wavemind-2.0.3}/tests/test_core_persistence.py +0 -0
  17. {wavemind-2.0.2 → wavemind-2.0.3}/tests/test_examples.py +0 -0
  18. {wavemind-2.0.2 → wavemind-2.0.3}/tests/test_import_benchmark.py +0 -0
  19. {wavemind-2.0.2 → wavemind-2.0.3}/tests/test_indexes_encoders.py +0 -0
  20. {wavemind-2.0.2 → wavemind-2.0.3}/tests/test_langchain_integration.py +0 -0
  21. {wavemind-2.0.2 → wavemind-2.0.3}/tests/test_semantic_and_latency.py +0 -0
  22. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind/__main__.py +0 -0
  23. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind/benchmark.py +0 -0
  24. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind/cli.py +0 -0
  25. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind/core.py +0 -0
  26. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind/encoders.py +0 -0
  27. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind/importers.py +0 -0
  28. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind/indexes.py +0 -0
  29. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind/integrations/__init__.py +0 -0
  30. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind/storage.py +0 -0
  31. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind.egg-info/SOURCES.txt +0 -0
  32. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind.egg-info/dependency_links.txt +0 -0
  33. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind.egg-info/entry_points.txt +0 -0
  34. {wavemind-2.0.2 → wavemind-2.0.3}/wavemind.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wavemind
3
- Version: 2.0.2
3
+ Version: 2.0.3
4
4
  Summary: Persistent dynamic memory engine with vector search and wave-field re-ranking
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/CaspianG/wavemind
@@ -27,6 +27,7 @@ Requires-Dist: langchain-classic>=1.0; extra == "langchain"
27
27
  Provides-Extra: dev
28
28
  Requires-Dist: pytest>=8; extra == "dev"
29
29
  Requires-Dist: httpx>=0.27; extra == "dev"
30
+ Requires-Dist: langchain-classic>=1.0; extra == "dev"
30
31
  Dynamic: license-file
31
32
 
32
33
  # WaveMind is persistent dynamic memory for AI agents: vector search first, wave-field priority second, SQLite as the source of truth.
@@ -87,6 +88,21 @@ wavemind --db ./agent_memory.sqlite3 remember "Andrey is a trader" --namespace d
87
88
  wavemind --db ./agent_memory.sqlite3 query "trader" --namespace demo
88
89
  ```
89
90
 
91
+ ## HTTP API
92
+
93
+ Run the local FastAPI server:
94
+
95
+ ```sh
96
+ wavemind --db ./agent_memory.sqlite3 serve --host 127.0.0.1 --port 8000
97
+ ```
98
+
99
+ Store and query memory over HTTP:
100
+
101
+ ```sh
102
+ curl -X POST http://127.0.0.1:8000/remember -H "Content-Type: application/json" -d "{\"text\":\"Andrey is a trader\",\"namespace\":\"demo\"}"
103
+ curl -X POST http://127.0.0.1:8000/query -H "Content-Type: application/json" -d "{\"query\":\"trader\",\"namespace\":\"demo\",\"top_k\":1}"
104
+ ```
105
+
90
106
  ## Install From Source
91
107
 
92
108
  For contributors installing from a local clone:
@@ -56,6 +56,21 @@ wavemind --db ./agent_memory.sqlite3 remember "Andrey is a trader" --namespace d
56
56
  wavemind --db ./agent_memory.sqlite3 query "trader" --namespace demo
57
57
  ```
58
58
 
59
+ ## HTTP API
60
+
61
+ Run the local FastAPI server:
62
+
63
+ ```sh
64
+ wavemind --db ./agent_memory.sqlite3 serve --host 127.0.0.1 --port 8000
65
+ ```
66
+
67
+ Store and query memory over HTTP:
68
+
69
+ ```sh
70
+ curl -X POST http://127.0.0.1:8000/remember -H "Content-Type: application/json" -d "{\"text\":\"Andrey is a trader\",\"namespace\":\"demo\"}"
71
+ curl -X POST http://127.0.0.1:8000/query -H "Content-Type: application/json" -d "{\"query\":\"trader\",\"namespace\":\"demo\",\"top_k\":1}"
72
+ ```
73
+
59
74
  ## Install From Source
60
75
 
61
76
  For contributors installing from a local clone:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "wavemind"
7
- version = "2.0.2"
7
+ version = "2.0.3"
8
8
  description = "Persistent dynamic memory engine with vector search and wave-field re-ranking"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -37,6 +37,7 @@ langchain = [
37
37
  dev = [
38
38
  "pytest>=8",
39
39
  "httpx>=0.27",
40
+ "langchain-classic>=1.0",
40
41
  ]
41
42
 
42
43
  [project.scripts]
@@ -1,6 +1,6 @@
1
1
  from fastapi.testclient import TestClient
2
2
 
3
- from wavemind import HashingTextEncoder, WaveMind
3
+ from wavemind import HashingTextEncoder, WaveMind, __version__
4
4
  from wavemind.api import create_app
5
5
 
6
6
 
@@ -50,3 +50,42 @@ def test_fastapi_remember_query_forget_and_stats(tmp_path):
50
50
  empty = client.post("/query", json={"text": "кошка", "namespace": "pets"})
51
51
  assert empty.json()["results"] == []
52
52
 
53
+
54
+ def test_fastapi_query_accepts_query_alias(tmp_path):
55
+ mind = WaveMind(
56
+ db_path=tmp_path / "api.sqlite3",
57
+ width=32,
58
+ height=32,
59
+ layers=2,
60
+ encoder=HashingTextEncoder(vector_dim=64),
61
+ score_threshold=0.0,
62
+ )
63
+ client = TestClient(create_app(mind=mind))
64
+
65
+ remember = client.post(
66
+ "/remember",
67
+ json={"text": "Andrey is a trader", "namespace": "demo"},
68
+ )
69
+ assert remember.status_code == 200
70
+
71
+ query = client.post(
72
+ "/query",
73
+ json={"query": "trader", "namespace": "demo", "top_k": 1},
74
+ )
75
+
76
+ assert query.status_code == 200
77
+ assert query.json()["results"][0]["text"] == "Andrey is a trader"
78
+
79
+
80
+ def test_fastapi_version_matches_package_version():
81
+ app = create_app(
82
+ mind=WaveMind(
83
+ db_path=None,
84
+ width=16,
85
+ height=16,
86
+ layers=1,
87
+ encoder=HashingTextEncoder(vector_dim=16),
88
+ )
89
+ )
90
+
91
+ assert app.version == __version__
@@ -1,4 +1,13 @@
1
1
  from pathlib import Path
2
+ import tomllib
3
+
4
+ import wavemind
5
+
6
+
7
+ def test_package_version_matches_pyproject():
8
+ pyproject = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))
9
+
10
+ assert wavemind.__version__ == pyproject["project"]["version"]
2
11
 
3
12
 
4
13
  def test_sentence_extra_is_available_for_install_scripts():
@@ -22,6 +31,18 @@ def test_langchain_extra_installs_classic_memory_api():
22
31
  assert '"langchain-classic>=1.0"' in pyproject
23
32
 
24
33
 
34
+ def test_dev_extra_runs_against_real_langchain_memory_api():
35
+ pyproject = Path("pyproject.toml").read_text(encoding="utf-8")
36
+ integration = Path("wavemind/integrations/langchain.py").read_text(
37
+ encoding="utf-8"
38
+ )
39
+
40
+ assert "dev = [" in pyproject
41
+ assert '"langchain-classic>=1.0"' in pyproject
42
+ assert "class BaseMemory" not in integration
43
+ assert 'pip install "wavemind[langchain]"' in integration
44
+
45
+
25
46
  def test_install_scripts_create_venv_and_install_sentence_extra():
26
47
  install_sh = Path("install.sh").read_text(encoding="utf-8")
27
48
  install_bat = Path("install.bat").read_text(encoding="utf-8")
@@ -8,6 +8,8 @@ from .encoders import (
8
8
  )
9
9
  from .storage import MemoryRecord, SQLiteMemoryStore
10
10
 
11
+ __version__ = "2.0.3"
12
+
11
13
  __all__ = [
12
14
  "FieldProjector",
13
15
  "HashingTextEncoder",
@@ -18,5 +20,6 @@ __all__ = [
18
20
  "TextEncoder",
19
21
  "WaveField",
20
22
  "WaveMind",
23
+ "__version__",
21
24
  "create_text_encoder",
22
25
  ]
@@ -6,8 +6,9 @@ from pathlib import Path
6
6
  from typing import Any
7
7
 
8
8
  from fastapi import Body, FastAPI, Query
9
- from pydantic import BaseModel, Field
9
+ from pydantic import AliasChoices, BaseModel, Field
10
10
 
11
+ from . import __version__
11
12
  from .core import WaveMind
12
13
  from .encoders import create_text_encoder
13
14
  from .importers import import_path
@@ -30,7 +31,7 @@ class RememberResponse(BaseModel):
30
31
 
31
32
 
32
33
  class QueryRequest(BaseModel):
33
- text: str
34
+ text: str = Field(validation_alias=AliasChoices("text", "query"))
34
35
  namespace: str = "default"
35
36
  top_k: int = 3
36
37
  tags: list[str] = Field(default_factory=list)
@@ -101,7 +102,7 @@ def build_default_mind() -> WaveMind:
101
102
 
102
103
  def create_app(mind: WaveMind | None = None) -> FastAPI:
103
104
  logging.basicConfig(level=os.environ.get("WAVEMIND_LOG_LEVEL", "INFO"))
104
- app = FastAPI(title="WaveMind", version="2.0.0")
105
+ app = FastAPI(title="WaveMind", version=__version__)
105
106
  app.state.mind = mind or build_default_mind()
106
107
 
107
108
  @app.post("/remember", response_model=RememberResponse)
@@ -11,17 +11,10 @@ from wavemind import WaveMind
11
11
 
12
12
  try:
13
13
  from langchain_classic.base_memory import BaseMemory
14
- except ImportError:
15
- try:
16
- from langchain.schema import BaseMemory
17
- except ImportError:
18
-
19
- class BaseMemory:
20
- """Small fallback so the integration can be imported without LangChain."""
21
-
22
- def __init__(self, **data: Any):
23
- for key, value in data.items():
24
- setattr(self, key, value)
14
+ except ImportError as exc: # pragma: no cover - exercised in clean installs.
15
+ raise ImportError(
16
+ 'WaveMindMemory requires LangChain. Install it with: pip install "wavemind[langchain]"'
17
+ ) from exc
25
18
 
26
19
 
27
20
  class WaveMindMemory(BaseMemory):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wavemind
3
- Version: 2.0.2
3
+ Version: 2.0.3
4
4
  Summary: Persistent dynamic memory engine with vector search and wave-field re-ranking
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/CaspianG/wavemind
@@ -27,6 +27,7 @@ Requires-Dist: langchain-classic>=1.0; extra == "langchain"
27
27
  Provides-Extra: dev
28
28
  Requires-Dist: pytest>=8; extra == "dev"
29
29
  Requires-Dist: httpx>=0.27; extra == "dev"
30
+ Requires-Dist: langchain-classic>=1.0; extra == "dev"
30
31
  Dynamic: license-file
31
32
 
32
33
  # WaveMind is persistent dynamic memory for AI agents: vector search first, wave-field priority second, SQLite as the source of truth.
@@ -87,6 +88,21 @@ wavemind --db ./agent_memory.sqlite3 remember "Andrey is a trader" --namespace d
87
88
  wavemind --db ./agent_memory.sqlite3 query "trader" --namespace demo
88
89
  ```
89
90
 
91
+ ## HTTP API
92
+
93
+ Run the local FastAPI server:
94
+
95
+ ```sh
96
+ wavemind --db ./agent_memory.sqlite3 serve --host 127.0.0.1 --port 8000
97
+ ```
98
+
99
+ Store and query memory over HTTP:
100
+
101
+ ```sh
102
+ curl -X POST http://127.0.0.1:8000/remember -H "Content-Type: application/json" -d "{\"text\":\"Andrey is a trader\",\"namespace\":\"demo\"}"
103
+ curl -X POST http://127.0.0.1:8000/query -H "Content-Type: application/json" -d "{\"query\":\"trader\",\"namespace\":\"demo\",\"top_k\":1}"
104
+ ```
105
+
90
106
  ## Install From Source
91
107
 
92
108
  For contributors installing from a local clone:
@@ -10,6 +10,7 @@ chromadb>=1.0
10
10
  [dev]
11
11
  pytest>=8
12
12
  httpx>=0.27
13
+ langchain-classic>=1.0
13
14
 
14
15
  [indexes]
15
16
  annoy>=1.17
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes