memwal 0.1.9.dev1__tar.gz → 0.1.9.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.
Files changed (28) hide show
  1. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/CHANGELOG.md +1 -0
  2. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/PKG-INFO +1 -1
  3. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/memwal/__init__.py +1 -1
  4. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/memwal/client.py +18 -1
  5. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/pyproject.toml +1 -1
  6. memwal-0.1.9.dev2/tests/test_auth_rejected_message.py +30 -0
  7. memwal-0.1.9.dev1/tests/test_auth_rejected_message.py +0 -9
  8. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/.gitignore +0 -0
  9. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/README.md +0 -0
  10. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/examples/.env.example +0 -0
  11. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/examples/.gitignore +0 -0
  12. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/examples/async_remember_demo.py +0 -0
  13. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/examples/interactive_demo.py +0 -0
  14. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/examples/verify_credentials.py +0 -0
  15. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/memwal/compatibility.py +0 -0
  16. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/memwal/middleware.py +0 -0
  17. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/memwal/mock.py +0 -0
  18. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/memwal/types.py +0 -0
  19. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/memwal/utils.py +0 -0
  20. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/notebooks/walrus_memory_python_sdk.ipynb +0 -0
  21. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/run_tests.py +0 -0
  22. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/tests/__init__.py +0 -0
  23. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/tests/test_client.py +0 -0
  24. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/tests/test_env_presets.py +0 -0
  25. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/tests/test_integration.py +0 -0
  26. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/tests/test_middleware.py +0 -0
  27. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/tests/test_mock.py +0 -0
  28. {memwal-0.1.9.dev1 → memwal-0.1.9.dev2}/tests/test_signing.py +0 -0
@@ -4,6 +4,7 @@
4
4
 
5
5
  ### Fixed
6
6
 
7
+ - HTTP 503 with `x-auth-error: AUTH_UPSTREAM_UNAVAILABLE` is reported as a retryable credential-verification outage, not a sign-in failure. Other 503s keep the generic sanitized body.
7
8
  - `remember_bulk_async` rejects an empty `items` list before the request and raises when the relayer returns a `job_ids` length that does not match the batch.
8
9
  - restore `truncated` docs now match WALM-431 retryable semantics.
9
10
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: memwal
3
- Version: 0.1.9.dev1
3
+ Version: 0.1.9.dev2
4
4
  Summary: Python SDK for Walrus Memory — Privacy-first AI memory with Ed25519 signing
5
5
  Project-URL: Homepage, https://memory.walrus.xyz
6
6
  Project-URL: Documentation, https://memory.walrus.xyz
@@ -122,4 +122,4 @@ __all__ = [
122
122
  "RecallManualResult",
123
123
  ]
124
124
 
125
- __version__ = "0.1.9.dev1"
125
+ __version__ = "0.1.9.dev2"
@@ -97,6 +97,11 @@ AUTH_REJECTED_MESSAGE = (
97
97
  "and dashboard credentials. Full troubleshooting: "
98
98
  "https://docs.wal.app/walrus-memory/troubleshooting/overview#401-auth_rejected-errors"
99
99
  )
100
+ AUTH_UPSTREAM_UNAVAILABLE = "AUTH_UPSTREAM_UNAVAILABLE"
101
+ UPSTREAM_UNAVAILABLE_MESSAGE = (
102
+ "Walrus Memory temporarily cannot verify credentials (upstream unavailable). "
103
+ "Retry; this is not a sign-in failure."
104
+ )
100
105
 
101
106
 
102
107
  logger = logging.getLogger("memwal")
@@ -1285,6 +1290,8 @@ class MemWal:
1285
1290
  raise _HttpStatusError(
1286
1291
  status=response.status_code,
1287
1292
  body=err_text,
1293
+ auth_error=response.headers.get("x-auth-error"),
1294
+ retry_after=response.headers.get("retry-after"),
1288
1295
  )
1289
1296
 
1290
1297
  return response.json()
@@ -1328,15 +1335,25 @@ class _HttpStatusError(MemWalError):
1328
1335
  explicitly accepted).
1329
1336
  """
1330
1337
 
1331
- def __init__(self, status: int, body: str) -> None:
1338
+ def __init__(
1339
+ self,
1340
+ status: int,
1341
+ body: str,
1342
+ auth_error: str | None = None,
1343
+ retry_after: str | None = None,
1344
+ ) -> None:
1332
1345
  if status == 401:
1333
1346
  super().__init__(AUTH_REJECTED_MESSAGE)
1347
+ elif status == 503 and auth_error == AUTH_UPSTREAM_UNAVAILABLE:
1348
+ super().__init__(UPSTREAM_UNAVAILABLE_MESSAGE)
1334
1349
  else:
1335
1350
  super().__init__(
1336
1351
  f"Walrus Memory API error ({status}): {_redact_internal_urls(body)}"
1337
1352
  )
1338
1353
  self.status = status
1339
1354
  self.body = body
1355
+ self.auth_error = auth_error
1356
+ self.retry_after = retry_after
1340
1357
 
1341
1358
 
1342
1359
  class MemWalRememberJobNotFound(MemWalError):
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "memwal"
7
- version = "0.1.9.dev1"
7
+ version = "0.1.9.dev2"
8
8
  description = "Python SDK for Walrus Memory — Privacy-first AI memory with Ed25519 signing"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -0,0 +1,30 @@
1
+ """Tests for the AUTH_REJECTED_MESSAGE shown on a 401 from the relayer."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from memwal.client import (
6
+ AUTH_REJECTED_MESSAGE,
7
+ AUTH_UPSTREAM_UNAVAILABLE,
8
+ UPSTREAM_UNAVAILABLE_MESSAGE,
9
+ _HttpStatusError,
10
+ )
11
+
12
+
13
+ def test_auth_rejected_message_points_to_troubleshooting_guide() -> None:
14
+ assert "docs.wal.app/walrus-memory/troubleshooting/overview" in AUTH_REJECTED_MESSAGE
15
+
16
+
17
+ def test_auth_503_is_retryable_not_a_credential_failure() -> None:
18
+ err = _HttpStatusError(
19
+ 503, "upstream unavailable", auth_error=AUTH_UPSTREAM_UNAVAILABLE, retry_after="5"
20
+ )
21
+ assert str(err) == UPSTREAM_UNAVAILABLE_MESSAGE
22
+ assert "sign-in" in str(err)
23
+ assert "401" not in str(err)
24
+ assert err.retry_after == "5"
25
+
26
+
27
+ def test_non_auth_503_keeps_generic_body() -> None:
28
+ err = _HttpStatusError(503, "Rate limiter temporarily unavailable")
29
+ assert "Rate limiter temporarily unavailable" in str(err)
30
+ assert "cannot verify credentials" not in str(err)
@@ -1,9 +0,0 @@
1
- """Tests for the AUTH_REJECTED_MESSAGE shown on a 401 from the relayer."""
2
-
3
- from __future__ import annotations
4
-
5
- from memwal.client import AUTH_REJECTED_MESSAGE
6
-
7
-
8
- def test_auth_rejected_message_points_to_troubleshooting_guide() -> None:
9
- assert "docs.wal.app/walrus-memory/troubleshooting/overview" in AUTH_REJECTED_MESSAGE
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes