memwal 0.1.2.dev1__tar.gz → 0.1.2.dev3__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 (23) hide show
  1. memwal-0.1.2.dev3/CHANGELOG.md +34 -0
  2. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/PKG-INFO +8 -8
  3. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/README.md +4 -4
  4. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/examples/.env.example +2 -2
  5. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/examples/verify_credentials.py +1 -1
  6. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/memwal/__init__.py +5 -3
  7. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/memwal/client.py +23 -19
  8. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/memwal/compatibility.py +6 -6
  9. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/memwal/middleware.py +18 -18
  10. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/memwal/types.py +40 -6
  11. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/memwal/utils.py +2 -2
  12. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/pyproject.toml +4 -4
  13. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/run_tests.py +2 -2
  14. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/tests/test_client.py +34 -3
  15. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/tests/test_integration.py +1 -1
  16. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/tests/test_middleware.py +1 -1
  17. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/.gitignore +0 -0
  18. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/examples/.gitignore +0 -0
  19. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/examples/async_remember_demo.py +0 -0
  20. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/examples/interactive_demo.py +0 -0
  21. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/tests/__init__.py +0 -0
  22. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/tests/test_env_presets.py +0 -0
  23. {memwal-0.1.2.dev1 → memwal-0.1.2.dev3}/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.dev1
4
- Summary: Python SDK for MemWal — Privacy-first AI memory with Ed25519 signing
3
+ Version: 0.1.2.dev3
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: MemWal Team
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
- # memwal
40
+ # Walrus Memory Python SDK
41
41
 
42
- Python SDK for [MemWal](https://memwal.ai) — Privacy-first AI memory with Ed25519 signing.
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-memwal-account-id"
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 MemWal dashboard and
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
- # memwal
1
+ # Walrus Memory Python SDK
2
2
 
3
- Python SDK for [MemWal](https://memwal.ai) — Privacy-first AI memory with Ed25519 signing.
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-memwal-account-id"
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 MemWal dashboard and
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 MemWal dashboard.
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
- # MemWalAccount object ID on Sui (the wallet's account)
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("MemWal credentials look parseable.")
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
- memwal — Privacy-first AI memory SDK
2
+ Walrus Memory — Privacy-first AI memory SDK
3
3
 
4
4
  Ed25519 delegate key auth + server-side TEE processing.
5
5
 
@@ -32,7 +32,6 @@ from .client import (
32
32
  MemWalSync,
33
33
  )
34
34
  from .middleware import with_memwal_langchain, with_memwal_openai
35
- from .utils import delegate_key_to_sui_address, delegate_key_to_public_key
36
35
  from .types import (
37
36
  ENV_PRESETS,
38
37
  AnalyzedFact,
@@ -61,7 +60,9 @@ from .types import (
61
60
  RememberManualResult,
62
61
  RememberResult,
63
62
  RestoreResult,
63
+ ScoringWeights,
64
64
  )
65
+ from .utils import delegate_key_to_public_key, delegate_key_to_sui_address
65
66
 
66
67
  # JS-style alias for developers coming from the TypeScript SDK
67
68
  withMemWal = with_memwal_langchain
@@ -105,6 +106,7 @@ __all__ = [
105
106
  "AnalyzedFact",
106
107
  "HealthResult",
107
108
  "RestoreResult",
109
+ "ScoringWeights",
108
110
  "RememberManualOptions",
109
111
  "RememberManualResult",
110
112
  "RecallManualOptions",
@@ -112,4 +114,4 @@ __all__ = [
112
114
  "RecallManualResult",
113
115
  ]
114
116
 
115
- __version__ = "0.1.2.dev1"
117
+ __version__ = "0.1.2.dev3"
@@ -1,7 +1,7 @@
1
1
  """
2
- memwal — SDK Client
2
+ Walrus Memory — SDK Client
3
3
 
4
- Ed25519 delegate key based client that communicates with the MemWal
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
 
@@ -58,7 +58,6 @@ from .types import (
58
58
  RememberBulkResult,
59
59
  RememberBulkStatusItem,
60
60
  RememberBulkStatusResult,
61
- RememberJobStatus,
62
61
  RememberManualOptions,
63
62
  RememberManualResult,
64
63
  RememberResult,
@@ -124,7 +123,7 @@ def _is_transient_polling_status(status: int) -> bool:
124
123
 
125
124
 
126
125
  class MemWal:
127
- """Async-native MemWal client.
126
+ """Async-native Walrus Memory client.
128
127
 
129
128
  All API methods are ``async``. For synchronous usage, wrap calls with
130
129
  ``asyncio.run()`` or use the :class:`MemWalSync` convenience wrapper.
@@ -152,11 +151,11 @@ class MemWal:
152
151
  namespace: str = "default",
153
152
  env: Optional[str] = None,
154
153
  ) -> "MemWal":
155
- """Create a new MemWal client instance.
154
+ """Create a new Walrus Memory client instance.
156
155
 
157
156
  Args:
158
157
  key: Ed25519 private key hex string (the delegate key).
159
- account_id: MemWalAccount object ID on Sui.
158
+ account_id: Walrus Memory account object ID on Sui.
160
159
  server_url: Server URL (default: ``http://localhost:8000``).
161
160
  namespace: Default namespace for memory isolation (default: ``"default"``).
162
161
  env: Optional relayer preset — ``"prod"``, ``"dev"``, ``"staging"``,
@@ -728,14 +727,18 @@ class MemWal:
728
727
  Returns:
729
728
  :class:`RecallManualResult` with blob_id + distance pairs.
730
729
  """
730
+ body: Dict[str, Any] = {
731
+ "vector": opts.vector,
732
+ "limit": opts.limit,
733
+ "namespace": opts.namespace or self._namespace,
734
+ }
735
+ if opts.scoring_weights is not None:
736
+ body["scoring_weights"] = opts.scoring_weights.to_wire()
737
+
731
738
  data = await self._signed_request(
732
739
  "POST",
733
740
  "/api/recall/manual",
734
- {
735
- "vector": opts.vector,
736
- "limit": opts.limit,
737
- "namespace": opts.namespace or self._namespace,
738
- },
741
+ body,
739
742
  include_seal_session=False,
740
743
  )
741
744
  hits = [
@@ -774,14 +777,14 @@ class MemWal:
774
777
  health_response = await self._http.get(f"{self._server_url}/health")
775
778
  if health_response.status_code != 200:
776
779
  raise MemWalError(
777
- "MemWal compatibility check failed: "
780
+ "Walrus Memory compatibility check failed: "
778
781
  f"GET /version returned {version_response.status_code}, "
779
782
  f"and GET /health returned {health_response.status_code}"
780
783
  )
781
784
  metadata = health_response.json()
782
785
  else:
783
786
  raise MemWalError(
784
- "MemWal compatibility check failed: "
787
+ "Walrus Memory compatibility check failed: "
785
788
  f"GET /version returned {version_response.status_code}"
786
789
  )
787
790
 
@@ -840,7 +843,8 @@ class MemWal:
840
843
  version = obj.get("version")
841
844
  if str(version) != "1":
842
845
  raise MemWalError(
843
- f"SEAL package {package_id} must be at version 1 to build x-seal-session, got {version!r}"
846
+ f"SEAL package {package_id} must be at version 1 to build "
847
+ f"x-seal-session, got {version!r}"
844
848
  )
845
849
 
846
850
  async def _build_seal_session_inner(self) -> str:
@@ -920,7 +924,7 @@ class MemWal:
920
924
  - ``x-timestamp``: Unix seconds string
921
925
  - ``x-nonce``: UUID v4 replay-protection nonce
922
926
  - ``x-seal-session``: Base64-encoded exported session envelope
923
- - ``x-account-id``: MemWalAccount object ID
927
+ - ``x-account-id``: Walrus Memory account object ID
924
928
  - ``Content-Type``: application/json
925
929
  """
926
930
  import uuid
@@ -969,7 +973,7 @@ class MemWal:
969
973
  err_text = response.text
970
974
  if response.status_code == 426:
971
975
  raise MemWalCompatibilityError(
972
- "MemWal relayer rejected this SDK as unsupported "
976
+ "Walrus Memory relayer rejected this SDK as unsupported "
973
977
  f"(HTTP 426 Upgrade Required). Relayer response: "
974
978
  f"{err_text[:300] or 'upgrade required'}"
975
979
  )
@@ -982,7 +986,7 @@ class MemWal:
982
986
 
983
987
 
984
988
  class MemWalError(Exception):
985
- """Exception raised for MemWal API errors."""
989
+ """Exception raised for Walrus Memory API errors."""
986
990
 
987
991
  pass
988
992
 
@@ -1005,7 +1009,7 @@ class _HttpStatusError(MemWalError):
1005
1009
  if status == 401:
1006
1010
  super().__init__(AUTH_REJECTED_MESSAGE)
1007
1011
  else:
1008
- super().__init__(f"MemWal API error ({status}): {body}")
1012
+ super().__init__(f"Walrus Memory API error ({status}): {body}")
1009
1013
  self.status = status
1010
1014
  self.body = body
1011
1015
 
@@ -1068,7 +1072,7 @@ class MemWalSync:
1068
1072
  namespace: str = "default",
1069
1073
  env: Optional[str] = None,
1070
1074
  ) -> "MemWalSync":
1071
- """Create a synchronous MemWal client.
1075
+ """Create a synchronous Walrus Memory client.
1072
1076
 
1073
1077
  Same parameters as :meth:`MemWal.create` (including the ``env``
1074
1078
  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"MemWal relayer at {server_url} does not expose compatibility metadata. "
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'MemWal relayer at {server_url} returned invalid apiVersion "{api_version}".'
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 MemWal Python SDK supports relayer API "
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"MemWal relayer at {server_url} did not report minSupportedSdk.python."
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'MemWal relayer at {server_url} returned invalid '
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"MemWal relayer at {server_url} requires Python SDK >= {min_python}, "
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
- memwal — AI Middleware
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 MemWal memory management.
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: MemWalAccount object ID.
161
- server_url: MemWal 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 MemWal memory.
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"[MemWal] Found {len(relevant)} relevant memories")
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"[MemWal] Memory search failed: {e}")
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"[MemWal] Auto-save failed: {e}")
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 MemWal memory management.
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: MemWalAccount object ID.
322
- server_url: MemWal 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 MemWal.
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"[MemWal] Found {len(relevant)} relevant memories")
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"[MemWal] Memory search failed: {e}")
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"[MemWal] Auto-save failed: {e}")
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"[MemWal] Found {len(relevant)} relevant memories")
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"[MemWal] Memory search failed: {e}")
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"[MemWal] Auto-save failed: {e}")
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
- memwal — Core Types
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 MemWal Rust server (TEE).
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 MemWal client.
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,12 @@ ENV_PRESETS = {
33
33
 
34
34
  @dataclass
35
35
  class MemWalConfig:
36
- """Configuration for creating a MemWal client.
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 app.memwal.com.
40
- account_id: MemWalAccount object ID on Sui.
39
+ key: Ed25519 private key (hex string). This is the delegate key from the
40
+ Walrus Memory dashboard.
41
+ account_id: Walrus Memory account object ID on Sui.
41
42
  server_url: Server URL (default: http://localhost:8000). An explicit
42
43
  non-default value always wins over ``env``.
43
44
  namespace: Default namespace for memory isolation (default: "default").
@@ -99,6 +100,37 @@ class RecallResult:
99
100
  total: int
100
101
 
101
102
 
103
+ @dataclass
104
+ class ScoringWeights:
105
+ """Optional composite-scoring weights for recall ranking.
106
+
107
+ Attributes:
108
+ semantic: Weight applied to semantic similarity (default: 1).
109
+ recency: Weight applied to recency decay (default: 0).
110
+ recency_half_life_days: Half-life for the recency term, in days (default: 30).
111
+ importance: Weight applied to memory importance (default: 0).
112
+ """
113
+
114
+ semantic: Optional[float] = None
115
+ recency: Optional[float] = None
116
+ recency_half_life_days: Optional[float] = None
117
+ importance: Optional[float] = None
118
+
119
+ def to_wire(self) -> Dict[str, float]:
120
+ """Return the snake_case payload expected by the relayer."""
121
+
122
+ payload: Dict[str, float] = {}
123
+ if self.semantic is not None:
124
+ payload["semantic"] = self.semantic
125
+ if self.recency is not None:
126
+ payload["recency"] = self.recency
127
+ if self.recency_half_life_days is not None:
128
+ payload["recency_half_life_days"] = self.recency_half_life_days
129
+ if self.importance is not None:
130
+ payload["importance"] = self.importance
131
+ return payload
132
+
133
+
102
134
  @dataclass
103
135
  class AnalyzedFact:
104
136
  """A single extracted fact."""
@@ -212,11 +244,13 @@ class RecallManualOptions:
212
244
  vector: Pre-computed query embedding vector.
213
245
  limit: Max number of results (default: 10).
214
246
  namespace: Namespace (default: config namespace or "default").
247
+ scoring_weights: Optional composite-scoring weights applied before returning hits.
215
248
  """
216
249
 
217
250
  vector: List[float]
218
251
  limit: int = 10
219
252
  namespace: Optional[str] = None
253
+ scoring_weights: Optional[ScoringWeights] = None
220
254
 
221
255
 
222
256
  @dataclass
@@ -1,5 +1,5 @@
1
1
  """
2
- memwal — Shared Utilities
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: MemWalAccount object ID sent as ``x-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.dev1"
8
- description = "Python SDK for MemWal — Privacy-first AI memory with Ed25519 signing"
7
+ version = "0.1.2.dev3"
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 = "MemWal Team" },
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
- MemWal Python SDK — Test Runner
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} MemWal Python SDK — Test Suite{RESET}")
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()
@@ -17,7 +17,7 @@ import pytest
17
17
  import respx
18
18
 
19
19
  from memwal.client import MemWal, MemWalCompatibilityError, MemWalError
20
- from memwal.types import RecallManualOptions, RememberManualOptions
20
+ from memwal.types import RecallManualOptions, RememberManualOptions, ScoringWeights
21
21
  from memwal.utils import build_signature_message, bytes_to_hex, sha256_hex
22
22
 
23
23
  # ============================================================
@@ -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 MemWal client with a test key."""
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,
@@ -327,7 +327,11 @@ class TestRecall:
327
327
  )
328
328
  )
329
329
 
330
- result = await memwal_client.wait_for_remember_job("job-1", poll_interval_ms=0, timeout_ms=100)
330
+ result = await memwal_client.wait_for_remember_job(
331
+ "job-1",
332
+ poll_interval_ms=0,
333
+ timeout_ms=100,
334
+ )
331
335
 
332
336
  request = route.calls[0].request
333
337
  assert request.content == b""
@@ -583,6 +587,33 @@ class TestManualAPI:
583
587
  assert len(result.results) == 1
584
588
  assert result.results[0].blob_id == "b1"
585
589
 
590
+ @respx.mock
591
+ async def test_recall_manual_forwards_scoring_weights(self, memwal_client: MemWal) -> None:
592
+ _mock_version()
593
+ route = respx.post(f"{_TEST_SERVER}/api/recall/manual").mock(
594
+ return_value=httpx.Response(200, json={"results": [], "total": 0})
595
+ )
596
+
597
+ opts = RecallManualOptions(
598
+ vector=[0.1, 0.2, 0.3],
599
+ limit=5,
600
+ scoring_weights=ScoringWeights(
601
+ semantic=1.0,
602
+ recency=0.5,
603
+ recency_half_life_days=7.0,
604
+ importance=2.0,
605
+ ),
606
+ )
607
+ await memwal_client.recall_manual(opts)
608
+
609
+ body = json.loads(route.calls[0].request.content)
610
+ assert body["scoring_weights"] == {
611
+ "semantic": 1.0,
612
+ "recency": 0.5,
613
+ "recency_half_life_days": 7.0,
614
+ "importance": 2.0,
615
+ }
616
+
586
617
 
587
618
  class TestPublicKey:
588
619
  async def test_get_public_key_hex(self, memwal_client: MemWal) -> None:
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- Integration tests for the MemWal Python SDK against a live server.
3
+ Integration tests for the Walrus Memory Python SDK against a live server.
4
4
 
5
5
  Targets MEMWAL_SERVER_URL (default: https://relayer.dev.memwal.ai).
6
6
 
@@ -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 MemWal server calls are made — all network traffic is mocked
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