memmachine-client 0.3.4__tar.gz → 0.3.6__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.
- {memmachine_client-0.3.4/src/memmachine_client.egg-info → memmachine_client-0.3.6}/PKG-INFO +2 -2
- memmachine_client-0.3.6/client_tests/test_format.py +261 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/client_tests/test_integration_complete.py +3 -2
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/pyproject.toml +1 -1
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/src/memmachine_client/__init__.py +14 -1
- memmachine_client-0.3.6/src/memmachine_client/format.py +101 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6/src/memmachine_client.egg-info}/PKG-INFO +2 -2
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/src/memmachine_client.egg-info/SOURCES.txt +2 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/src/memmachine_client.egg-info/requires.txt +1 -1
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/LICENSE +0 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/README.md +0 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/client_tests/__init__.py +0 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/client_tests/test_client.py +0 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/client_tests/test_config.py +0 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/client_tests/test_langgraph.py +0 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/client_tests/test_memory.py +0 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/setup.cfg +0 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/src/memmachine_client/client.py +0 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/src/memmachine_client/config.py +0 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/src/memmachine_client/langgraph.py +0 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/src/memmachine_client/memory.py +0 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/src/memmachine_client/project.py +0 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/src/memmachine_client.egg-info/dependency_links.txt +0 -0
- {memmachine_client-0.3.4 → memmachine_client-0.3.6}/src/memmachine_client.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memmachine-client
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: MemMachine REST Client - A lightweight Python client library for MemMachine memory system
|
|
5
5
|
Author-email: MemMachine <noreply@memmachine.ai>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -19,7 +19,7 @@ Description-Content-Type: text/markdown
|
|
|
19
19
|
License-File: LICENSE
|
|
20
20
|
Requires-Dist: memmachine-common
|
|
21
21
|
Requires-Dist: pydantic>=2.0.0
|
|
22
|
-
Requires-Dist: requests>=2.
|
|
22
|
+
Requires-Dist: requests>=2.33.0
|
|
23
23
|
Requires-Dist: typing-extensions>=4.0.0
|
|
24
24
|
Requires-Dist: urllib3>=2.6.3
|
|
25
25
|
Dynamic: license-file
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
"""Unit tests for LLM-friendly memory formatting functions."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from datetime import datetime, timezone
|
|
5
|
+
|
|
6
|
+
from memmachine_common.api.spec import (
|
|
7
|
+
Episode,
|
|
8
|
+
EpisodeResponse,
|
|
9
|
+
EpisodicSearchLongTermMemory,
|
|
10
|
+
EpisodicSearchResult,
|
|
11
|
+
EpisodicSearchShortTermMemory,
|
|
12
|
+
SearchResult,
|
|
13
|
+
SearchResultContent,
|
|
14
|
+
SemanticFeature,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
from memmachine_client.format import (
|
|
18
|
+
format_episodes,
|
|
19
|
+
format_search_result,
|
|
20
|
+
format_semantic_memories,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TestFormatEpisodes:
|
|
25
|
+
"""Tests for format_episodes."""
|
|
26
|
+
|
|
27
|
+
def test_empty(self):
|
|
28
|
+
assert format_episodes([]) == ""
|
|
29
|
+
|
|
30
|
+
def test_single_episode_response(self):
|
|
31
|
+
ep = EpisodeResponse(
|
|
32
|
+
uid="1",
|
|
33
|
+
content="Hello world",
|
|
34
|
+
producer_id="user_1",
|
|
35
|
+
producer_role="user",
|
|
36
|
+
created_at=datetime(2024, 1, 15, 13, 30, tzinfo=timezone.utc),
|
|
37
|
+
)
|
|
38
|
+
result = format_episodes([ep])
|
|
39
|
+
assert (
|
|
40
|
+
result == '[Monday, January 15, 2024 at 01:30 PM] user_1: "Hello world"\n'
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def test_multiple_episodes(self):
|
|
44
|
+
eps = [
|
|
45
|
+
EpisodeResponse(
|
|
46
|
+
uid="1",
|
|
47
|
+
content="First message",
|
|
48
|
+
producer_id="user_1",
|
|
49
|
+
producer_role="user",
|
|
50
|
+
created_at=datetime(2024, 3, 5, 9, 0, tzinfo=timezone.utc),
|
|
51
|
+
),
|
|
52
|
+
EpisodeResponse(
|
|
53
|
+
uid="2",
|
|
54
|
+
content="Second message",
|
|
55
|
+
producer_id="assistant_1",
|
|
56
|
+
producer_role="assistant",
|
|
57
|
+
created_at=datetime(2024, 3, 5, 9, 1, tzinfo=timezone.utc),
|
|
58
|
+
),
|
|
59
|
+
]
|
|
60
|
+
result = format_episodes(eps)
|
|
61
|
+
lines = result.strip().split("\n")
|
|
62
|
+
assert len(lines) == 2
|
|
63
|
+
assert "user_1" in lines[0]
|
|
64
|
+
assert "assistant_1" in lines[1]
|
|
65
|
+
|
|
66
|
+
def test_episode_without_created_at(self):
|
|
67
|
+
ep = EpisodeResponse(
|
|
68
|
+
uid="1",
|
|
69
|
+
content="No timestamp",
|
|
70
|
+
producer_id="user_1",
|
|
71
|
+
producer_role="user",
|
|
72
|
+
created_at=None,
|
|
73
|
+
)
|
|
74
|
+
result = format_episodes([ep])
|
|
75
|
+
assert result == 'user_1: "No timestamp"\n'
|
|
76
|
+
|
|
77
|
+
def test_list_episode_type(self):
|
|
78
|
+
ep = Episode(
|
|
79
|
+
uid="1",
|
|
80
|
+
content="Listed episode",
|
|
81
|
+
session_key="sess_1",
|
|
82
|
+
producer_id="user_1",
|
|
83
|
+
producer_role="user",
|
|
84
|
+
created_at=datetime(2024, 6, 1, 14, 0, tzinfo=timezone.utc),
|
|
85
|
+
)
|
|
86
|
+
result = format_episodes([ep])
|
|
87
|
+
assert (
|
|
88
|
+
result == '[Saturday, June 01, 2024 at 02:00 PM] user_1: "Listed episode"\n'
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
def test_content_json_escaped(self):
|
|
92
|
+
ep = EpisodeResponse(
|
|
93
|
+
uid="1",
|
|
94
|
+
content='She said "hello"',
|
|
95
|
+
producer_id="user_1",
|
|
96
|
+
producer_role="user",
|
|
97
|
+
created_at=datetime(2024, 1, 1, 0, 0, tzinfo=timezone.utc),
|
|
98
|
+
)
|
|
99
|
+
result = format_episodes([ep])
|
|
100
|
+
assert json.dumps('She said "hello"') in result
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class TestFormatSemanticMemories:
|
|
104
|
+
"""Tests for format_semantic_memories."""
|
|
105
|
+
|
|
106
|
+
def test_empty(self):
|
|
107
|
+
result = format_semantic_memories([])
|
|
108
|
+
assert result == "{}"
|
|
109
|
+
|
|
110
|
+
def test_single_feature(self):
|
|
111
|
+
feature = SemanticFeature(
|
|
112
|
+
category="profile",
|
|
113
|
+
tag="preferences",
|
|
114
|
+
feature_name="favorite_food",
|
|
115
|
+
value="pizza",
|
|
116
|
+
)
|
|
117
|
+
result = format_semantic_memories([feature])
|
|
118
|
+
parsed = json.loads(result)
|
|
119
|
+
assert parsed == {"preferences": {"favorite_food": "pizza"}}
|
|
120
|
+
|
|
121
|
+
def test_groups_by_tag(self):
|
|
122
|
+
features = [
|
|
123
|
+
SemanticFeature(
|
|
124
|
+
category="profile",
|
|
125
|
+
tag="preferences",
|
|
126
|
+
feature_name="food",
|
|
127
|
+
value="pizza",
|
|
128
|
+
),
|
|
129
|
+
SemanticFeature(
|
|
130
|
+
category="profile",
|
|
131
|
+
tag="preferences",
|
|
132
|
+
feature_name="color",
|
|
133
|
+
value="blue",
|
|
134
|
+
),
|
|
135
|
+
SemanticFeature(
|
|
136
|
+
category="profile",
|
|
137
|
+
tag="background",
|
|
138
|
+
feature_name="role",
|
|
139
|
+
value="engineer",
|
|
140
|
+
),
|
|
141
|
+
]
|
|
142
|
+
result = format_semantic_memories(features)
|
|
143
|
+
parsed = json.loads(result)
|
|
144
|
+
assert parsed == {
|
|
145
|
+
"preferences": {"food": "pizza", "color": "blue"},
|
|
146
|
+
"background": {"role": "engineer"},
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
def test_metadata_excluded(self):
|
|
150
|
+
feature = SemanticFeature(
|
|
151
|
+
set_id="set_1",
|
|
152
|
+
category="profile",
|
|
153
|
+
tag="info",
|
|
154
|
+
feature_name="name",
|
|
155
|
+
value="Alice",
|
|
156
|
+
metadata=SemanticFeature.Metadata(
|
|
157
|
+
id="feat_1",
|
|
158
|
+
citations=["ep_1", "ep_2"],
|
|
159
|
+
other={"source": "conversation"},
|
|
160
|
+
),
|
|
161
|
+
)
|
|
162
|
+
result = format_semantic_memories([feature])
|
|
163
|
+
parsed = json.loads(result)
|
|
164
|
+
# Only tag/feature_name/value should appear
|
|
165
|
+
assert parsed == {"info": {"name": "Alice"}}
|
|
166
|
+
assert "set_id" not in result
|
|
167
|
+
assert "citations" not in result
|
|
168
|
+
assert "feat_1" not in result
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class TestFormatSearchResult:
|
|
172
|
+
"""Tests for format_search_result."""
|
|
173
|
+
|
|
174
|
+
def test_empty_result(self):
|
|
175
|
+
result = SearchResult(
|
|
176
|
+
status=0,
|
|
177
|
+
content=SearchResultContent(
|
|
178
|
+
episodic_memory=None,
|
|
179
|
+
semantic_memory=None,
|
|
180
|
+
),
|
|
181
|
+
)
|
|
182
|
+
assert format_search_result(result) == ""
|
|
183
|
+
|
|
184
|
+
def test_episodic_only(self):
|
|
185
|
+
ep = EpisodeResponse(
|
|
186
|
+
uid="1",
|
|
187
|
+
content="Hello",
|
|
188
|
+
producer_id="user_1",
|
|
189
|
+
producer_role="user",
|
|
190
|
+
created_at=datetime(2024, 1, 1, 12, 0, tzinfo=timezone.utc),
|
|
191
|
+
)
|
|
192
|
+
result = SearchResult(
|
|
193
|
+
status=0,
|
|
194
|
+
content=SearchResultContent(
|
|
195
|
+
episodic_memory=EpisodicSearchResult(
|
|
196
|
+
long_term_memory=EpisodicSearchLongTermMemory(episodes=[ep]),
|
|
197
|
+
short_term_memory=EpisodicSearchShortTermMemory(
|
|
198
|
+
episodes=[], episode_summary=[]
|
|
199
|
+
),
|
|
200
|
+
),
|
|
201
|
+
semantic_memory=None,
|
|
202
|
+
),
|
|
203
|
+
)
|
|
204
|
+
formatted = format_search_result(result)
|
|
205
|
+
assert formatted.startswith("[Episodic Memory]\n")
|
|
206
|
+
assert "user_1" in formatted
|
|
207
|
+
assert '"Hello"' in formatted
|
|
208
|
+
assert "[Semantic Memory]" not in formatted
|
|
209
|
+
|
|
210
|
+
def test_semantic_only(self):
|
|
211
|
+
feature = SemanticFeature(
|
|
212
|
+
category="profile",
|
|
213
|
+
tag="prefs",
|
|
214
|
+
feature_name="food",
|
|
215
|
+
value="pizza",
|
|
216
|
+
)
|
|
217
|
+
result = SearchResult(
|
|
218
|
+
status=0,
|
|
219
|
+
content=SearchResultContent(
|
|
220
|
+
episodic_memory=None,
|
|
221
|
+
semantic_memory=[feature],
|
|
222
|
+
),
|
|
223
|
+
)
|
|
224
|
+
formatted = format_search_result(result)
|
|
225
|
+
assert formatted.startswith("[Semantic Memory]\n")
|
|
226
|
+
assert "[Episodic Memory]" not in formatted
|
|
227
|
+
semantic_json = formatted.removeprefix("[Semantic Memory]\n")
|
|
228
|
+
assert json.loads(semantic_json) == {"prefs": {"food": "pizza"}}
|
|
229
|
+
|
|
230
|
+
def test_combined(self):
|
|
231
|
+
ep = EpisodeResponse(
|
|
232
|
+
uid="1",
|
|
233
|
+
content="I like pizza",
|
|
234
|
+
producer_id="user_1",
|
|
235
|
+
producer_role="user",
|
|
236
|
+
created_at=datetime(2024, 1, 1, 12, 0, tzinfo=timezone.utc),
|
|
237
|
+
)
|
|
238
|
+
feature = SemanticFeature(
|
|
239
|
+
category="profile",
|
|
240
|
+
tag="prefs",
|
|
241
|
+
feature_name="food",
|
|
242
|
+
value="pizza",
|
|
243
|
+
)
|
|
244
|
+
result = SearchResult(
|
|
245
|
+
status=0,
|
|
246
|
+
content=SearchResultContent(
|
|
247
|
+
episodic_memory=EpisodicSearchResult(
|
|
248
|
+
long_term_memory=EpisodicSearchLongTermMemory(episodes=[ep]),
|
|
249
|
+
short_term_memory=EpisodicSearchShortTermMemory(
|
|
250
|
+
episodes=[], episode_summary=[]
|
|
251
|
+
),
|
|
252
|
+
),
|
|
253
|
+
semantic_memory=[feature],
|
|
254
|
+
),
|
|
255
|
+
)
|
|
256
|
+
formatted = format_search_result(result)
|
|
257
|
+
assert "[Episodic Memory]" in formatted
|
|
258
|
+
assert "[Semantic Memory]" in formatted
|
|
259
|
+
assert formatted.index("[Episodic Memory]") < formatted.index(
|
|
260
|
+
"[Semantic Memory]"
|
|
261
|
+
)
|
{memmachine_client-0.3.4 → memmachine_client-0.3.6}/client_tests/test_integration_complete.py
RENAMED
|
@@ -45,6 +45,7 @@ def check_server_available():
|
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
TEST_BASE_URL = os.environ.get("MEMORY_BACKEND_URL", "http://localhost:8080")
|
|
48
|
+
CLIENT_TIMEOUT_SECONDS = 180
|
|
48
49
|
|
|
49
50
|
|
|
50
51
|
@pytest.mark.integration
|
|
@@ -58,7 +59,7 @@ class TestMemMachineIntegration:
|
|
|
58
59
|
@pytest.fixture
|
|
59
60
|
def client(self):
|
|
60
61
|
"""Create a MemMachine client instance."""
|
|
61
|
-
return MemMachineClient(base_url=TEST_BASE_URL, timeout=
|
|
62
|
+
return MemMachineClient(base_url=TEST_BASE_URL, timeout=CLIENT_TIMEOUT_SECONDS)
|
|
62
63
|
|
|
63
64
|
@pytest.fixture
|
|
64
65
|
def unique_test_ids(self):
|
|
@@ -1644,7 +1645,7 @@ class TestConfigIntegration:
|
|
|
1644
1645
|
@pytest.fixture
|
|
1645
1646
|
def client(self):
|
|
1646
1647
|
"""Create a MemMachine client instance."""
|
|
1647
|
-
return MemMachineClient(base_url=TEST_BASE_URL, timeout=
|
|
1648
|
+
return MemMachineClient(base_url=TEST_BASE_URL, timeout=CLIENT_TIMEOUT_SECONDS)
|
|
1648
1649
|
|
|
1649
1650
|
@pytest.fixture
|
|
1650
1651
|
def config(self, client):
|
|
@@ -7,7 +7,20 @@ episodic and profile memory systems.
|
|
|
7
7
|
|
|
8
8
|
from .client import MemMachineClient
|
|
9
9
|
from .config import Config
|
|
10
|
+
from .format import (
|
|
11
|
+
format_episodes,
|
|
12
|
+
format_search_result,
|
|
13
|
+
format_semantic_memories,
|
|
14
|
+
)
|
|
10
15
|
from .memory import Memory
|
|
11
16
|
from .project import Project
|
|
12
17
|
|
|
13
|
-
__all__ = [
|
|
18
|
+
__all__ = [
|
|
19
|
+
"Config",
|
|
20
|
+
"MemMachineClient",
|
|
21
|
+
"Memory",
|
|
22
|
+
"Project",
|
|
23
|
+
"format_episodes",
|
|
24
|
+
"format_search_result",
|
|
25
|
+
"format_semantic_memories",
|
|
26
|
+
]
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""LLM-friendly formatting for memory search and list results.
|
|
2
|
+
|
|
3
|
+
These functions mirror the server's internal formatting logic so that
|
|
4
|
+
client-side consumers get the same compact representation the server
|
|
5
|
+
uses when feeding memories into language models.
|
|
6
|
+
|
|
7
|
+
Episodic format matches ``string_from_episode_context`` in the server.
|
|
8
|
+
Semantic format matches ``_features_to_llm_format`` in the server.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
from collections.abc import Iterable
|
|
15
|
+
|
|
16
|
+
from memmachine_common.api.spec import (
|
|
17
|
+
Episode,
|
|
18
|
+
EpisodeResponse,
|
|
19
|
+
SearchResult,
|
|
20
|
+
SemanticFeature,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def format_episodes(episodes: Iterable[EpisodeResponse | Episode]) -> str:
|
|
25
|
+
"""Format episodic memories as an LLM-friendly string.
|
|
26
|
+
|
|
27
|
+
Each episode is rendered as::
|
|
28
|
+
|
|
29
|
+
[Monday, January 01, 2024 at 01:30 PM] producer_id: "content"
|
|
30
|
+
|
|
31
|
+
This mirrors the server's ``string_from_episode_context`` output.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
episodes: Episodic memory entries from a search or list result.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Newline-terminated formatted string (empty string when *episodes*
|
|
38
|
+
is empty).
|
|
39
|
+
|
|
40
|
+
"""
|
|
41
|
+
result = ""
|
|
42
|
+
for episode in episodes:
|
|
43
|
+
if episode.created_at is not None:
|
|
44
|
+
date_str = episode.created_at.strftime("%A, %B %d, %Y")
|
|
45
|
+
time_str = episode.created_at.strftime("%I:%M %p")
|
|
46
|
+
result += f"[{date_str} at {time_str}] {episode.producer_id}: {json.dumps(episode.content)}\n"
|
|
47
|
+
else:
|
|
48
|
+
result += f"{episode.producer_id}: {json.dumps(episode.content)}\n"
|
|
49
|
+
return result
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def format_semantic_memories(features: Iterable[SemanticFeature]) -> str:
|
|
53
|
+
"""Format semantic memories as a compact JSON string.
|
|
54
|
+
|
|
55
|
+
Produces a ``{tag: {feature_name: value}}`` structure, omitting all
|
|
56
|
+
metadata for context efficiency. This mirrors the server's
|
|
57
|
+
``_features_to_llm_format`` output.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
features: Semantic memory entries from a search or list result.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
JSON string of the grouped features.
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
structured: dict[str, dict[str, str]] = {}
|
|
67
|
+
for feature in features:
|
|
68
|
+
structured.setdefault(feature.tag, {})[feature.feature_name] = feature.value
|
|
69
|
+
return json.dumps(structured)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def format_search_result(result: SearchResult) -> str:
|
|
73
|
+
"""Format a search result as an LLM-friendly string.
|
|
74
|
+
|
|
75
|
+
Combines episodic and semantic memories from a
|
|
76
|
+
:class:`~memmachine_common.api.spec.SearchResult` returned by
|
|
77
|
+
``Memory.search()``.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
result: A ``SearchResult`` object.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Formatted string combining both memory types.
|
|
84
|
+
|
|
85
|
+
"""
|
|
86
|
+
sections: list[str] = []
|
|
87
|
+
|
|
88
|
+
if result.content.episodic_memory is not None:
|
|
89
|
+
episodes = (
|
|
90
|
+
result.content.episodic_memory.long_term_memory.episodes
|
|
91
|
+
+ result.content.episodic_memory.short_term_memory.episodes
|
|
92
|
+
)
|
|
93
|
+
if episodes:
|
|
94
|
+
sections.append(f"[Episodic Memory]\n{format_episodes(episodes)}")
|
|
95
|
+
|
|
96
|
+
if result.content.semantic_memory:
|
|
97
|
+
sections.append(
|
|
98
|
+
f"[Semantic Memory]\n{format_semantic_memories(result.content.semantic_memory)}"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
return "\n".join(sections)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memmachine-client
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: MemMachine REST Client - A lightweight Python client library for MemMachine memory system
|
|
5
5
|
Author-email: MemMachine <noreply@memmachine.ai>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -19,7 +19,7 @@ Description-Content-Type: text/markdown
|
|
|
19
19
|
License-File: LICENSE
|
|
20
20
|
Requires-Dist: memmachine-common
|
|
21
21
|
Requires-Dist: pydantic>=2.0.0
|
|
22
|
-
Requires-Dist: requests>=2.
|
|
22
|
+
Requires-Dist: requests>=2.33.0
|
|
23
23
|
Requires-Dist: typing-extensions>=4.0.0
|
|
24
24
|
Requires-Dist: urllib3>=2.6.3
|
|
25
25
|
Dynamic: license-file
|
{memmachine_client-0.3.4 → memmachine_client-0.3.6}/src/memmachine_client.egg-info/SOURCES.txt
RENAMED
|
@@ -4,12 +4,14 @@ pyproject.toml
|
|
|
4
4
|
client_tests/__init__.py
|
|
5
5
|
client_tests/test_client.py
|
|
6
6
|
client_tests/test_config.py
|
|
7
|
+
client_tests/test_format.py
|
|
7
8
|
client_tests/test_integration_complete.py
|
|
8
9
|
client_tests/test_langgraph.py
|
|
9
10
|
client_tests/test_memory.py
|
|
10
11
|
src/memmachine_client/__init__.py
|
|
11
12
|
src/memmachine_client/client.py
|
|
12
13
|
src/memmachine_client/config.py
|
|
14
|
+
src/memmachine_client/format.py
|
|
13
15
|
src/memmachine_client/langgraph.py
|
|
14
16
|
src/memmachine_client/memory.py
|
|
15
17
|
src/memmachine_client/project.py
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{memmachine_client-0.3.4 → memmachine_client-0.3.6}/src/memmachine_client.egg-info/top_level.txt
RENAMED
|
File without changes
|