memwal 0.1.2.dev1__tar.gz → 0.1.2.dev2__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.
- memwal-0.1.2.dev2/CHANGELOG.md +34 -0
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/PKG-INFO +8 -8
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/README.md +4 -4
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/examples/.env.example +2 -2
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/examples/verify_credentials.py +1 -1
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/memwal/__init__.py +2 -2
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/memwal/client.py +12 -12
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/memwal/compatibility.py +6 -6
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/memwal/middleware.py +18 -18
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/memwal/types.py +6 -6
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/memwal/utils.py +2 -2
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/pyproject.toml +4 -4
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/run_tests.py +2 -2
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/tests/test_client.py +1 -1
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/tests/test_integration.py +1 -1
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/tests/test_middleware.py +1 -1
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/.gitignore +0 -0
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/examples/.gitignore +0 -0
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/examples/async_remember_demo.py +0 -0
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/examples/interactive_demo.py +0 -0
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/tests/__init__.py +0 -0
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/tests/test_env_presets.py +0 -0
- {memwal-0.1.2.dev1 → memwal-0.1.2.dev2}/tests/test_signing.py +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# memwal
|
|
2
|
+
|
|
3
|
+
## 0.1.2
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Added `max_distance` to async and sync `recall()`.
|
|
8
|
+
- Added credential verification helper.
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Updated docs/examples to use `MEMWAL_PRIVATE_KEY`.
|
|
13
|
+
- Rebranded package metadata and documentation from MemWal to Walrus Memory.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Made `401` relayer errors more actionable.
|
|
18
|
+
|
|
19
|
+
## 0.1.1
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- Added relayer `env` presets.
|
|
24
|
+
- Added compatibility checks and `compatibility()` helpers.
|
|
25
|
+
|
|
26
|
+
## 0.1.0
|
|
27
|
+
|
|
28
|
+
### Initial Release
|
|
29
|
+
|
|
30
|
+
- `MemWal` async client and `MemWalSync` sync wrapper
|
|
31
|
+
- Memory APIs: `remember`, `recall`, `analyze`, `ask`, `restore`, `health`
|
|
32
|
+
- Async job helpers for remember, bulk remember, and analyze
|
|
33
|
+
- LangChain/OpenAI middleware and delegate-key utilities
|
|
34
|
+
- Ed25519 delegate-key auth with namespace-scoped memory isolation
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memwal
|
|
3
|
-
Version: 0.1.2.
|
|
4
|
-
Summary: Python SDK for
|
|
3
|
+
Version: 0.1.2.dev2
|
|
4
|
+
Summary: Python SDK for Walrus Memory — Privacy-first AI memory with Ed25519 signing
|
|
5
5
|
Project-URL: Homepage, https://memwal.ai
|
|
6
6
|
Project-URL: Documentation, https://docs.memwal.ai
|
|
7
7
|
Project-URL: Repository, https://github.com/MystenLabs/MemWal
|
|
8
|
-
Author:
|
|
8
|
+
Author: Walrus Memory Team
|
|
9
9
|
License-Expression: MIT
|
|
10
|
-
Keywords: ai,ed25519,memory,memwal,privacy,sui,walrus
|
|
10
|
+
Keywords: ai,ed25519,memory,memwal,privacy,sui,walrus,walrus-memory
|
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -37,9 +37,9 @@ Provides-Extra: openai
|
|
|
37
37
|
Requires-Dist: openai>=1.0.0; extra == 'openai'
|
|
38
38
|
Description-Content-Type: text/markdown
|
|
39
39
|
|
|
40
|
-
#
|
|
40
|
+
# Walrus Memory Python SDK
|
|
41
41
|
|
|
42
|
-
Python SDK for [
|
|
42
|
+
Python SDK for [Walrus Memory](https://memwal.ai) — Privacy-first AI memory with Ed25519 signing.
|
|
43
43
|
|
|
44
44
|
All data processing (encryption, embedding, Walrus storage) happens server-side in a TEE. The SDK signs requests with your Ed25519 delegate key and sends text over HTTPS.
|
|
45
45
|
|
|
@@ -63,11 +63,11 @@ Set your environment variables first:
|
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
65
|
export MEMWAL_PRIVATE_KEY="your-ed25519-delegate-private-key-hex"
|
|
66
|
-
export MEMWAL_ACCOUNT_ID="0x-your-
|
|
66
|
+
export MEMWAL_ACCOUNT_ID="0x-your-walrus-memory-account-id"
|
|
67
67
|
export MEMWAL_SERVER_URL="https://relayer.memwal.ai"
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
`MEMWAL_PRIVATE_KEY` is the delegate private key from the
|
|
70
|
+
`MEMWAL_PRIVATE_KEY` is the delegate private key from the Walrus Memory dashboard and
|
|
71
71
|
must stay server-side.
|
|
72
72
|
|
|
73
73
|
### Async (recommended)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Walrus Memory Python SDK
|
|
2
2
|
|
|
3
|
-
Python SDK for [
|
|
3
|
+
Python SDK for [Walrus Memory](https://memwal.ai) — Privacy-first AI memory with Ed25519 signing.
|
|
4
4
|
|
|
5
5
|
All data processing (encryption, embedding, Walrus storage) happens server-side in a TEE. The SDK signs requests with your Ed25519 delegate key and sends text over HTTPS.
|
|
6
6
|
|
|
@@ -24,11 +24,11 @@ Set your environment variables first:
|
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
26
|
export MEMWAL_PRIVATE_KEY="your-ed25519-delegate-private-key-hex"
|
|
27
|
-
export MEMWAL_ACCOUNT_ID="0x-your-
|
|
27
|
+
export MEMWAL_ACCOUNT_ID="0x-your-walrus-memory-account-id"
|
|
28
28
|
export MEMWAL_SERVER_URL="https://relayer.memwal.ai"
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
`MEMWAL_PRIVATE_KEY` is the delegate private key from the
|
|
31
|
+
`MEMWAL_PRIVATE_KEY` is the delegate private key from the Walrus Memory dashboard and
|
|
32
32
|
must stay server-side.
|
|
33
33
|
|
|
34
34
|
### Async (recommended)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Local server (default) or remote relayer
|
|
2
2
|
MEMWAL_SERVER_URL=http://localhost:8000
|
|
3
|
-
# Ed25519 delegate private key (64-hex). Get from
|
|
3
|
+
# Ed25519 delegate private key (64-hex). Get from Walrus Memory dashboard.
|
|
4
4
|
MEMWAL_PRIVATE_KEY=21b423e72282dcc47805de48ef9130331b642667b7b2a5cd621767928205e360
|
|
5
5
|
# Optional: paste the dashboard delegate public key so verification can catch mismatches.
|
|
6
6
|
MEMWAL_DELEGATE_PUBLIC_KEY=
|
|
7
|
-
#
|
|
7
|
+
# Walrus Memory account object ID on Sui (the wallet's account)
|
|
8
8
|
MEMWAL_ACCOUNT_ID=0x8a1121b8f95d79e68bd07efaf71689ce6fd832b369cdb1b2a943ec7beb822392
|
|
9
9
|
# Namespace for these test memories
|
|
10
10
|
MEMWAL_NAMESPACE=python-sdk-example
|
|
@@ -47,7 +47,7 @@ def main() -> None:
|
|
|
47
47
|
"You may have pasted a public key or a key from another account."
|
|
48
48
|
)
|
|
49
49
|
|
|
50
|
-
print("
|
|
50
|
+
print("Walrus Memory credentials look parseable.")
|
|
51
51
|
print(f"Derived delegate public key: {derived_public_key}")
|
|
52
52
|
if account_id:
|
|
53
53
|
print(f"Account ID: {account_id}")
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Walrus Memory — Privacy-first AI memory SDK
|
|
3
3
|
|
|
4
4
|
Ed25519 delegate key auth + server-side TEE processing.
|
|
5
5
|
|
|
@@ -112,4 +112,4 @@ __all__ = [
|
|
|
112
112
|
"RecallManualResult",
|
|
113
113
|
]
|
|
114
114
|
|
|
115
|
-
__version__ = "0.1.2.
|
|
115
|
+
__version__ = "0.1.2.dev2"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Walrus Memory — SDK Client
|
|
3
3
|
|
|
4
|
-
Ed25519 delegate key based client that communicates with the
|
|
4
|
+
Ed25519 delegate key based client that communicates with the Walrus Memory
|
|
5
5
|
Rust server (TEE). All data processing (encryption, embedding, Walrus)
|
|
6
6
|
happens server-side -- the SDK just signs requests and sends text.
|
|
7
7
|
|
|
@@ -124,7 +124,7 @@ def _is_transient_polling_status(status: int) -> bool:
|
|
|
124
124
|
|
|
125
125
|
|
|
126
126
|
class MemWal:
|
|
127
|
-
"""Async-native
|
|
127
|
+
"""Async-native Walrus Memory client.
|
|
128
128
|
|
|
129
129
|
All API methods are ``async``. For synchronous usage, wrap calls with
|
|
130
130
|
``asyncio.run()`` or use the :class:`MemWalSync` convenience wrapper.
|
|
@@ -152,11 +152,11 @@ class MemWal:
|
|
|
152
152
|
namespace: str = "default",
|
|
153
153
|
env: Optional[str] = None,
|
|
154
154
|
) -> "MemWal":
|
|
155
|
-
"""Create a new
|
|
155
|
+
"""Create a new Walrus Memory client instance.
|
|
156
156
|
|
|
157
157
|
Args:
|
|
158
158
|
key: Ed25519 private key hex string (the delegate key).
|
|
159
|
-
account_id:
|
|
159
|
+
account_id: Walrus Memory account object ID on Sui.
|
|
160
160
|
server_url: Server URL (default: ``http://localhost:8000``).
|
|
161
161
|
namespace: Default namespace for memory isolation (default: ``"default"``).
|
|
162
162
|
env: Optional relayer preset — ``"prod"``, ``"dev"``, ``"staging"``,
|
|
@@ -774,14 +774,14 @@ class MemWal:
|
|
|
774
774
|
health_response = await self._http.get(f"{self._server_url}/health")
|
|
775
775
|
if health_response.status_code != 200:
|
|
776
776
|
raise MemWalError(
|
|
777
|
-
"
|
|
777
|
+
"Walrus Memory compatibility check failed: "
|
|
778
778
|
f"GET /version returned {version_response.status_code}, "
|
|
779
779
|
f"and GET /health returned {health_response.status_code}"
|
|
780
780
|
)
|
|
781
781
|
metadata = health_response.json()
|
|
782
782
|
else:
|
|
783
783
|
raise MemWalError(
|
|
784
|
-
"
|
|
784
|
+
"Walrus Memory compatibility check failed: "
|
|
785
785
|
f"GET /version returned {version_response.status_code}"
|
|
786
786
|
)
|
|
787
787
|
|
|
@@ -920,7 +920,7 @@ class MemWal:
|
|
|
920
920
|
- ``x-timestamp``: Unix seconds string
|
|
921
921
|
- ``x-nonce``: UUID v4 replay-protection nonce
|
|
922
922
|
- ``x-seal-session``: Base64-encoded exported session envelope
|
|
923
|
-
- ``x-account-id``:
|
|
923
|
+
- ``x-account-id``: Walrus Memory account object ID
|
|
924
924
|
- ``Content-Type``: application/json
|
|
925
925
|
"""
|
|
926
926
|
import uuid
|
|
@@ -969,7 +969,7 @@ class MemWal:
|
|
|
969
969
|
err_text = response.text
|
|
970
970
|
if response.status_code == 426:
|
|
971
971
|
raise MemWalCompatibilityError(
|
|
972
|
-
"
|
|
972
|
+
"Walrus Memory relayer rejected this SDK as unsupported "
|
|
973
973
|
f"(HTTP 426 Upgrade Required). Relayer response: "
|
|
974
974
|
f"{err_text[:300] or 'upgrade required'}"
|
|
975
975
|
)
|
|
@@ -982,7 +982,7 @@ class MemWal:
|
|
|
982
982
|
|
|
983
983
|
|
|
984
984
|
class MemWalError(Exception):
|
|
985
|
-
"""Exception raised for
|
|
985
|
+
"""Exception raised for Walrus Memory API errors."""
|
|
986
986
|
|
|
987
987
|
pass
|
|
988
988
|
|
|
@@ -1005,7 +1005,7 @@ class _HttpStatusError(MemWalError):
|
|
|
1005
1005
|
if status == 401:
|
|
1006
1006
|
super().__init__(AUTH_REJECTED_MESSAGE)
|
|
1007
1007
|
else:
|
|
1008
|
-
super().__init__(f"
|
|
1008
|
+
super().__init__(f"Walrus Memory API error ({status}): {body}")
|
|
1009
1009
|
self.status = status
|
|
1010
1010
|
self.body = body
|
|
1011
1011
|
|
|
@@ -1068,7 +1068,7 @@ class MemWalSync:
|
|
|
1068
1068
|
namespace: str = "default",
|
|
1069
1069
|
env: Optional[str] = None,
|
|
1070
1070
|
) -> "MemWalSync":
|
|
1071
|
-
"""Create a synchronous
|
|
1071
|
+
"""Create a synchronous Walrus Memory client.
|
|
1072
1072
|
|
|
1073
1073
|
Same parameters as :meth:`MemWal.create` (including the ``env``
|
|
1074
1074
|
relayer preset).
|
|
@@ -18,33 +18,33 @@ def compatibility_error(metadata: Dict[str, Any], server_url: str) -> Optional[s
|
|
|
18
18
|
|
|
19
19
|
if not api_version or not relayer_version or not isinstance(min_supported, dict):
|
|
20
20
|
return (
|
|
21
|
-
f"
|
|
21
|
+
f"Walrus Memory relayer at {server_url} does not expose compatibility metadata. "
|
|
22
22
|
"Upgrade the relayer to a version that serves GET /version, or use an older SDK."
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
api_major = _semver_major(str(api_version))
|
|
26
26
|
if api_major is None:
|
|
27
|
-
return f'
|
|
27
|
+
return f'Walrus Memory relayer at {server_url} returned invalid apiVersion "{api_version}".'
|
|
28
28
|
|
|
29
29
|
if api_major != SUPPORTED_RELAYER_API_MAJOR:
|
|
30
30
|
return (
|
|
31
|
-
"This
|
|
31
|
+
"This Walrus Memory Python SDK supports relayer API "
|
|
32
32
|
f"{SUPPORTED_RELAYER_API_MAJOR}.x, but {server_url} reports apiVersion "
|
|
33
33
|
f"{api_version}. Upgrade or downgrade the SDK/relayer pair."
|
|
34
34
|
)
|
|
35
35
|
|
|
36
36
|
min_python = min_supported.get("python")
|
|
37
37
|
if not isinstance(min_python, str):
|
|
38
|
-
return f"
|
|
38
|
+
return f"Walrus Memory relayer at {server_url} did not report minSupportedSdk.python."
|
|
39
39
|
if _parse_semver(min_python) is None:
|
|
40
40
|
return (
|
|
41
|
-
f'
|
|
41
|
+
f'Walrus Memory relayer at {server_url} returned invalid '
|
|
42
42
|
f'minSupportedSdk.python "{min_python}".'
|
|
43
43
|
)
|
|
44
44
|
|
|
45
45
|
if _compare_semver(MEMWAL_PYTHON_COMPATIBILITY_VERSION, min_python) < 0:
|
|
46
46
|
return (
|
|
47
|
-
f"
|
|
47
|
+
f"Walrus Memory relayer at {server_url} requires Python SDK >= {min_python}, "
|
|
48
48
|
f"but this package supports the {MEMWAL_PYTHON_COMPATIBILITY_VERSION} "
|
|
49
49
|
"compatibility baseline. Upgrade memwal or use an older compatible relayer."
|
|
50
50
|
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Walrus Memory — AI Middleware
|
|
3
3
|
|
|
4
4
|
Wraps LangChain and OpenAI SDK clients with automatic memory management.
|
|
5
5
|
Before each LLM call, relevant memories are recalled and injected.
|
|
@@ -145,7 +145,7 @@ def with_memwal_langchain(
|
|
|
145
145
|
debug: bool = False,
|
|
146
146
|
env: Optional[str] = None,
|
|
147
147
|
) -> "BaseChatModel":
|
|
148
|
-
"""Wrap a LangChain ``BaseChatModel`` with
|
|
148
|
+
"""Wrap a LangChain ``BaseChatModel`` with Walrus Memory management.
|
|
149
149
|
|
|
150
150
|
Before each call:
|
|
151
151
|
- Recall relevant memories for the last user message
|
|
@@ -157,8 +157,8 @@ def with_memwal_langchain(
|
|
|
157
157
|
Args:
|
|
158
158
|
llm: A LangChain ``BaseChatModel`` instance.
|
|
159
159
|
key: Ed25519 delegate key (hex).
|
|
160
|
-
account_id:
|
|
161
|
-
server_url:
|
|
160
|
+
account_id: Walrus Memory account object ID.
|
|
161
|
+
server_url: Walrus Memory server URL.
|
|
162
162
|
namespace: Default namespace.
|
|
163
163
|
max_memories: Max memories to inject per request.
|
|
164
164
|
auto_save: Auto-save new facts from conversation.
|
|
@@ -168,7 +168,7 @@ def with_memwal_langchain(
|
|
|
168
168
|
``"local"``). Same precedence as :meth:`MemWal.create`.
|
|
169
169
|
|
|
170
170
|
Returns:
|
|
171
|
-
A wrapped ``BaseChatModel`` that automatically uses
|
|
171
|
+
A wrapped ``BaseChatModel`` that automatically uses Walrus Memory.
|
|
172
172
|
"""
|
|
173
173
|
try:
|
|
174
174
|
from langchain_core.messages import HumanMessage, SystemMessage # noqa: F811
|
|
@@ -208,7 +208,7 @@ def with_memwal_langchain(
|
|
|
208
208
|
return messages
|
|
209
209
|
|
|
210
210
|
memory_context = _format_memories(relevant)
|
|
211
|
-
log(f"[
|
|
211
|
+
log(f"[Walrus Memory] Found {len(relevant)} relevant memories")
|
|
212
212
|
|
|
213
213
|
# Insert memory system message before the last user message
|
|
214
214
|
result = list(messages)
|
|
@@ -226,7 +226,7 @@ def with_memwal_langchain(
|
|
|
226
226
|
|
|
227
227
|
return result
|
|
228
228
|
except Exception as e:
|
|
229
|
-
log(f"[
|
|
229
|
+
log(f"[Walrus Memory] Memory search failed: {e}")
|
|
230
230
|
return messages
|
|
231
231
|
|
|
232
232
|
async def _post_analyze(messages: List[BaseMessage]) -> None:
|
|
@@ -238,7 +238,7 @@ def with_memwal_langchain(
|
|
|
238
238
|
try:
|
|
239
239
|
await memwal.analyze(user_text, namespace)
|
|
240
240
|
except Exception as e:
|
|
241
|
-
log(f"[
|
|
241
|
+
log(f"[Walrus Memory] Auto-save failed: {e}")
|
|
242
242
|
|
|
243
243
|
async def patched_agenerate(
|
|
244
244
|
messages: List[List[BaseMessage]], *args: Any, **kwargs: Any
|
|
@@ -304,7 +304,7 @@ def with_memwal_openai(
|
|
|
304
304
|
debug: bool = False,
|
|
305
305
|
env: Optional[str] = None,
|
|
306
306
|
) -> Any:
|
|
307
|
-
"""Wrap an OpenAI client with
|
|
307
|
+
"""Wrap an OpenAI client with Walrus Memory management.
|
|
308
308
|
|
|
309
309
|
Works with both ``openai.OpenAI`` (sync) and ``openai.AsyncOpenAI`` (async).
|
|
310
310
|
|
|
@@ -318,8 +318,8 @@ def with_memwal_openai(
|
|
|
318
318
|
Args:
|
|
319
319
|
client: An ``openai.OpenAI`` or ``openai.AsyncOpenAI`` instance.
|
|
320
320
|
key: Ed25519 delegate key (hex).
|
|
321
|
-
account_id:
|
|
322
|
-
server_url:
|
|
321
|
+
account_id: Walrus Memory account object ID.
|
|
322
|
+
server_url: Walrus Memory server URL.
|
|
323
323
|
namespace: Default namespace.
|
|
324
324
|
max_memories: Max memories to inject per request.
|
|
325
325
|
auto_save: Auto-save new facts from conversation.
|
|
@@ -329,7 +329,7 @@ def with_memwal_openai(
|
|
|
329
329
|
``"local"``). Same precedence as :meth:`MemWal.create`.
|
|
330
330
|
|
|
331
331
|
Returns:
|
|
332
|
-
The same client, with ``chat.completions.create`` wrapped to use
|
|
332
|
+
The same client, with ``chat.completions.create`` wrapped to use Walrus Memory.
|
|
333
333
|
"""
|
|
334
334
|
memwal = MemWal.create(
|
|
335
335
|
key=key,
|
|
@@ -379,14 +379,14 @@ def _wrap_async_openai(
|
|
|
379
379
|
]
|
|
380
380
|
if relevant:
|
|
381
381
|
memory_context = _format_memories(relevant)
|
|
382
|
-
log(f"[
|
|
382
|
+
log(f"[Walrus Memory] Found {len(relevant)} relevant memories")
|
|
383
383
|
messages = _inject_openai_memory(list(messages), memory_context)
|
|
384
384
|
if "messages" in kwargs:
|
|
385
385
|
kwargs["messages"] = messages
|
|
386
386
|
elif args:
|
|
387
387
|
args = (messages,) + args[1:]
|
|
388
388
|
except Exception as e:
|
|
389
|
-
log(f"[
|
|
389
|
+
log(f"[Walrus Memory] Memory search failed: {e}")
|
|
390
390
|
|
|
391
391
|
result = await original_create(*args, **kwargs)
|
|
392
392
|
|
|
@@ -396,7 +396,7 @@ def _wrap_async_openai(
|
|
|
396
396
|
try:
|
|
397
397
|
await memwal.analyze(user_text, namespace)
|
|
398
398
|
except Exception as e:
|
|
399
|
-
log(f"[
|
|
399
|
+
log(f"[Walrus Memory] Auto-save failed: {e}")
|
|
400
400
|
|
|
401
401
|
_fire_and_forget(_analyze())
|
|
402
402
|
|
|
@@ -437,14 +437,14 @@ def _wrap_sync_openai(
|
|
|
437
437
|
]
|
|
438
438
|
if relevant:
|
|
439
439
|
memory_context = _format_memories(relevant)
|
|
440
|
-
log(f"[
|
|
440
|
+
log(f"[Walrus Memory] Found {len(relevant)} relevant memories")
|
|
441
441
|
messages = _inject_openai_memory(list(messages), memory_context)
|
|
442
442
|
if "messages" in kwargs:
|
|
443
443
|
kwargs["messages"] = messages
|
|
444
444
|
elif args:
|
|
445
445
|
args = (messages,) + args[1:]
|
|
446
446
|
except Exception as e:
|
|
447
|
-
log(f"[
|
|
447
|
+
log(f"[Walrus Memory] Memory search failed: {e}")
|
|
448
448
|
|
|
449
449
|
result = original_create(*args, **kwargs)
|
|
450
450
|
|
|
@@ -454,7 +454,7 @@ def _wrap_sync_openai(
|
|
|
454
454
|
try:
|
|
455
455
|
await memwal.analyze(user_text, namespace)
|
|
456
456
|
except Exception as e:
|
|
457
|
-
log(f"[
|
|
457
|
+
log(f"[Walrus Memory] Auto-save failed: {e}")
|
|
458
458
|
|
|
459
459
|
_fire_and_forget(_analyze())
|
|
460
460
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Walrus Memory — Core Types
|
|
3
3
|
|
|
4
4
|
Dataclasses for all API request options and response types.
|
|
5
5
|
Ed25519 delegate key based SDK that communicates with
|
|
6
|
-
the
|
|
6
|
+
the Walrus Memory Rust server (TEE).
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
from __future__ import annotations
|
|
@@ -22,7 +22,7 @@ DEFAULT_SERVER_URL = "http://localhost:8000"
|
|
|
22
22
|
|
|
23
23
|
#: Named relayer environments. Mirrors the TypeScript SDK / MCP package
|
|
24
24
|
#: ``--prod`` / ``--dev`` / ``--staging`` / ``--local`` presets so the same
|
|
25
|
-
#: shorthand works across every
|
|
25
|
+
#: shorthand works across every Walrus Memory client.
|
|
26
26
|
ENV_PRESETS = {
|
|
27
27
|
"prod": "https://relayer.memwal.ai",
|
|
28
28
|
"dev": "https://relayer.dev.memwal.ai",
|
|
@@ -33,11 +33,11 @@ ENV_PRESETS = {
|
|
|
33
33
|
|
|
34
34
|
@dataclass
|
|
35
35
|
class MemWalConfig:
|
|
36
|
-
"""Configuration for creating a
|
|
36
|
+
"""Configuration for creating a Walrus Memory client.
|
|
37
37
|
|
|
38
38
|
Attributes:
|
|
39
|
-
key: Ed25519 private key (hex string). This is the delegate key from
|
|
40
|
-
account_id:
|
|
39
|
+
key: Ed25519 private key (hex string). This is the delegate key from the Walrus Memory dashboard.
|
|
40
|
+
account_id: Walrus Memory account object ID on Sui.
|
|
41
41
|
server_url: Server URL (default: http://localhost:8000). An explicit
|
|
42
42
|
non-default value always wins over ``env``.
|
|
43
43
|
namespace: Default namespace for memory isolation (default: "default").
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Walrus Memory — Shared Utilities
|
|
3
3
|
|
|
4
4
|
Crypto and encoding helpers for Ed25519 signing and SHA-256 hashing.
|
|
5
5
|
Uses PyNaCl (nacl.signing) as the primary Ed25519 implementation.
|
|
@@ -119,7 +119,7 @@ def build_signature_message(
|
|
|
119
119
|
path: URL path with query (e.g. ``"/api/remember"``).
|
|
120
120
|
body_sha256: SHA-256 hex digest of the JSON body string.
|
|
121
121
|
nonce: UUID v4 sent as the ``x-nonce`` header (required).
|
|
122
|
-
account_id:
|
|
122
|
+
account_id: Walrus Memory account object ID sent as ``x-account-id``
|
|
123
123
|
(required; empty string here will mismatch on server).
|
|
124
124
|
"""
|
|
125
125
|
return f"{timestamp}.{method}.{path}.{body_sha256}.{nonce}.{account_id}"
|
|
@@ -4,15 +4,15 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "memwal"
|
|
7
|
-
version = "0.1.2.
|
|
8
|
-
description = "Python SDK for
|
|
7
|
+
version = "0.1.2.dev2"
|
|
8
|
+
description = "Python SDK for Walrus Memory — Privacy-first AI memory with Ed25519 signing"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
11
11
|
requires-python = ">=3.9"
|
|
12
12
|
authors = [
|
|
13
|
-
{ name = "
|
|
13
|
+
{ name = "Walrus Memory Team" },
|
|
14
14
|
]
|
|
15
|
-
keywords = ["memwal", "ai", "memory", "ed25519", "privacy", "walrus", "sui"]
|
|
15
|
+
keywords = ["memwal", "walrus-memory", "ai", "memory", "ed25519", "privacy", "walrus", "sui"]
|
|
16
16
|
classifiers = [
|
|
17
17
|
"Development Status :: 4 - Beta",
|
|
18
18
|
"Intended Audience :: Developers",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""
|
|
3
|
-
|
|
3
|
+
Walrus Memory Python SDK — Test Runner
|
|
4
4
|
|
|
5
5
|
Runs all tests grouped by category and prints a clean summary.
|
|
6
6
|
|
|
@@ -77,7 +77,7 @@ def status(passed: int, failed: int) -> str:
|
|
|
77
77
|
|
|
78
78
|
def print_header() -> None:
|
|
79
79
|
print()
|
|
80
|
-
print(f"{BOLD}{CYAN}
|
|
80
|
+
print(f"{BOLD}{CYAN} Walrus Memory Python SDK — Test Suite{RESET}")
|
|
81
81
|
print(f" {DIM}Server: {SERVER_URL}{RESET}")
|
|
82
82
|
print(f" {DIM}Auth: {'✓ credentials set' if HAS_KEY else '✗ no key (integration tests skipped)'}{RESET}")
|
|
83
83
|
print()
|
|
@@ -95,7 +95,7 @@ def decode_seal_session_header(request: httpx.Request) -> dict[str, Any]:
|
|
|
95
95
|
|
|
96
96
|
@pytest.fixture
|
|
97
97
|
def memwal_client() -> MemWal:
|
|
98
|
-
"""Create a
|
|
98
|
+
"""Create a Walrus Memory client with a test key."""
|
|
99
99
|
return MemWal.create(
|
|
100
100
|
key=_TEST_KEY_HEX,
|
|
101
101
|
account_id=_TEST_ACCOUNT_ID,
|
|
@@ -9,7 +9,7 @@ Covers:
|
|
|
9
9
|
- _format_memories: output format
|
|
10
10
|
- _inject_openai_memory: insertion position
|
|
11
11
|
|
|
12
|
-
No actual LLM or
|
|
12
|
+
No actual LLM or Walrus Memory server calls are made — all network traffic is mocked
|
|
13
13
|
with ``respx`` and all LLM responses are mocked with ``unittest.mock``.
|
|
14
14
|
"""
|
|
15
15
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|