memwal 0.1.9.dev0__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.dev0 → memwal-0.1.9.dev2}/CHANGELOG.md +2 -0
  2. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/PKG-INFO +1 -1
  3. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/memwal/__init__.py +1 -1
  4. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/memwal/client.py +18 -1
  5. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/memwal/types.py +11 -7
  6. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/pyproject.toml +1 -1
  7. memwal-0.1.9.dev2/tests/test_auth_rejected_message.py +30 -0
  8. memwal-0.1.9.dev0/tests/test_auth_rejected_message.py +0 -9
  9. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/.gitignore +0 -0
  10. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/README.md +0 -0
  11. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/examples/.env.example +0 -0
  12. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/examples/.gitignore +0 -0
  13. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/examples/async_remember_demo.py +0 -0
  14. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/examples/interactive_demo.py +0 -0
  15. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/examples/verify_credentials.py +0 -0
  16. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/memwal/compatibility.py +0 -0
  17. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/memwal/middleware.py +0 -0
  18. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/memwal/mock.py +0 -0
  19. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/memwal/utils.py +0 -0
  20. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/notebooks/walrus_memory_python_sdk.ipynb +0 -0
  21. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/run_tests.py +0 -0
  22. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/tests/__init__.py +0 -0
  23. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/tests/test_client.py +0 -0
  24. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/tests/test_env_presets.py +0 -0
  25. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/tests/test_integration.py +0 -0
  26. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/tests/test_middleware.py +0 -0
  27. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/tests/test_mock.py +0 -0
  28. {memwal-0.1.9.dev0 → memwal-0.1.9.dev2}/tests/test_signing.py +0 -0
@@ -4,7 +4,9 @@
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.
9
+ - restore `truncated` docs now match WALM-431 retryable semantics.
8
10
 
9
11
  ## 0.1.8
10
12
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: memwal
3
- Version: 0.1.9.dev0
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.dev0"
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):
@@ -206,13 +206,17 @@ class RestoreResult:
206
206
  total: int
207
207
  namespace: str
208
208
  owner: str
209
- #: True when this restore is known-incomplete: either more on-chain
210
- #: blobs were missing locally than ``limit`` allowed this call to
211
- #: restore, or the sidecar's raw on-chain candidate fetch hit its own
212
- #: cap before this namespace's blobs were even filtered out of that
213
- #: set (WALM-319) -- this can be ``True`` even when ``total == 0``,
214
- #: since a cap hit elsewhere can starve this namespace's fetch
215
- #: entirely. Raising ``limit`` only helps with the first case.
209
+ #: True when this restore is known-incomplete: more on-chain blobs were
210
+ #: missing locally than ``limit`` allowed this call to restore, or the
211
+ #: sidecar's owner-wide candidate fetch hit its cap *and* raising
212
+ #: ``limit`` can still expand that fetch (``limit < 20``). Once the cap
213
+ #: is saturated, truncation follows this call's missing-blob page, not
214
+ #: on-chain ``total``, so a fully restored namespace does not loop
215
+ #: (WALM-431 / GH #762).
216
+ #:
217
+ #: ``truncated=False`` is not proof the sidecar saw every on-chain blob.
218
+ #: Blobs beyond the owner-wide sidecar candidate cap can still be
219
+ #: missing. Follow-up field: WALM-451 (``sourceCapped``).
216
220
  #:
217
221
  #: Relayers older than WALM-319 don't send this field at all; the SDK
218
222
  #: defaults it to ``False`` in that case rather than requiring it.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "memwal"
7
- version = "0.1.9.dev0"
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