memwal 0.2.2.dev2__tar.gz → 0.2.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.
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/PKG-INFO +2 -2
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/README.md +1 -1
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/memwal/__init__.py +1 -1
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/memwal/types.py +1 -1
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/notebooks/walrus_memory_python_sdk.ipynb +2 -2
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/pyproject.toml +1 -1
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/run_tests.py +1 -1
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_env_presets.py +2 -2
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_integration.py +20 -19
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/.gitignore +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/CHANGELOG.md +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/examples/.env.example +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/examples/.gitignore +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/examples/async_remember_demo.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/examples/interactive_demo.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/examples/verify_credentials.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/memwal/client.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/memwal/compatibility.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/memwal/middleware.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/memwal/mock.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/memwal/utils.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/__init__.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_ask_validation.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_auth_rejected_message.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_blank_text.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_client.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_destroy_and_cancel_shield.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_empty_namespace.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_list_namespaces.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_middleware.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_missing_response_fields.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_mock.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_nonfinite_validation.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_normalize_server_url.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_polling_delay.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_recall_validation.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_recall_weights.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_remember_derived_key.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_retry_after_http_date.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_signing.py +0 -0
- {memwal-0.2.2.dev2 → memwal-0.2.2.dev3}/tests/test_transport_retry.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: memwal
|
|
3
|
-
Version: 0.2.2.
|
|
3
|
+
Version: 0.2.2.dev3
|
|
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
|
|
@@ -181,7 +181,7 @@ memwal = MemWal.create(
|
|
|
181
181
|
|-------|-------------|
|
|
182
182
|
| `prod` | `https://relayer.memory.walrus.xyz` |
|
|
183
183
|
| `dev` | `https://relayer.dev.memwal.ai` |
|
|
184
|
-
| `staging` | `https://relayer
|
|
184
|
+
| `staging` | `https://relayer.dev.memwal.ai` |
|
|
185
185
|
|
|
186
186
|
Precedence: any explicit **`server_url` wins over `env`**, including the hosted
|
|
187
187
|
default. `env` applies only when `server_url` is omitted (`None`). An unknown
|
|
@@ -140,7 +140,7 @@ memwal = MemWal.create(
|
|
|
140
140
|
|-------|-------------|
|
|
141
141
|
| `prod` | `https://relayer.memory.walrus.xyz` |
|
|
142
142
|
| `dev` | `https://relayer.dev.memwal.ai` |
|
|
143
|
-
| `staging` | `https://relayer
|
|
143
|
+
| `staging` | `https://relayer.dev.memwal.ai` |
|
|
144
144
|
|
|
145
145
|
Precedence: any explicit **`server_url` wins over `env`**, including the hosted
|
|
146
146
|
default. `env` applies only when `server_url` is omitted (`None`). An unknown
|
|
@@ -24,7 +24,7 @@ DEFAULT_SERVER_URL = "https://relayer.memory.walrus.xyz"
|
|
|
24
24
|
ENV_PRESETS = {
|
|
25
25
|
"prod": "https://relayer.memory.walrus.xyz",
|
|
26
26
|
"dev": "https://relayer.dev.memwal.ai",
|
|
27
|
-
"staging": "https://relayer
|
|
27
|
+
"staging": "https://relayer.dev.memwal.ai",
|
|
28
28
|
"local": "http://127.0.0.1:8000",
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"- optional OpenAI and LangChain middleware examples\n",
|
|
31
31
|
"- cleanup and troubleshooting\n",
|
|
32
32
|
"\n",
|
|
33
|
-
"The notebook defaults to `staging` for test credentials and uses Railway-backed Walrus Memory domains: `https://relayer
|
|
33
|
+
"The notebook defaults to `staging` for test credentials and uses Railway-backed Walrus Memory domains: `https://relayer.dev.memwal.ai` for staging and `https://relayer.memory.walrus.xyz` for production. You can switch to `prod` when you have production credentials.\n"
|
|
34
34
|
]
|
|
35
35
|
},
|
|
36
36
|
{
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"\n",
|
|
92
92
|
"ALLOWED_ENVS = {\"staging\", \"prod\"}\n",
|
|
93
93
|
"SERVER_URL_PRESETS = {\n",
|
|
94
|
-
" \"staging\": \"https://relayer
|
|
94
|
+
" \"staging\": \"https://relayer.dev.memwal.ai\",\n",
|
|
95
95
|
" \"prod\": \"https://relayer.memory.walrus.xyz\",\n",
|
|
96
96
|
"}\n",
|
|
97
97
|
"DEFAULT_ENV = \"staging\"\n",
|
|
@@ -26,7 +26,7 @@ BOLD = "\033[1m"
|
|
|
26
26
|
DIM = "\033[2m"
|
|
27
27
|
RESET = "\033[0m"
|
|
28
28
|
|
|
29
|
-
SERVER_URL = os.environ.get("MEMWAL_SERVER_URL", "https://relayer
|
|
29
|
+
SERVER_URL = os.environ.get("MEMWAL_SERVER_URL", "https://relayer.dev.memwal.ai")
|
|
30
30
|
PRIVATE_KEY = os.environ.get("MEMWAL_PRIVATE_KEY", "")
|
|
31
31
|
ACCOUNT_ID = os.environ.get("MEMWAL_ACCOUNT_ID", "")
|
|
32
32
|
HAS_KEY = bool(PRIVATE_KEY and ACCOUNT_ID)
|
|
@@ -19,7 +19,7 @@ ACCOUNT = "0x" + "ab" * 32
|
|
|
19
19
|
[
|
|
20
20
|
("prod", "https://relayer.memory.walrus.xyz"),
|
|
21
21
|
("dev", "https://relayer.dev.memwal.ai"),
|
|
22
|
-
("staging", "https://relayer
|
|
22
|
+
("staging", "https://relayer.dev.memwal.ai"),
|
|
23
23
|
("local", "http://127.0.0.1:8000"),
|
|
24
24
|
],
|
|
25
25
|
)
|
|
@@ -52,7 +52,7 @@ def test_unknown_env_raises():
|
|
|
52
52
|
|
|
53
53
|
def test_create_threads_env_through_to_client():
|
|
54
54
|
client = MemWal.create(key=KEY, account_id=ACCOUNT, env="staging")
|
|
55
|
-
assert client._server_url == "https://relayer
|
|
55
|
+
assert client._server_url == "https://relayer.dev.memwal.ai"
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
def test_sync_create_threads_env_through():
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"""
|
|
3
3
|
Integration tests for the Walrus Memory Python SDK against a live server.
|
|
4
4
|
|
|
5
|
-
Targets MEMWAL_SERVER_URL (default: https://relayer
|
|
5
|
+
Targets MEMWAL_SERVER_URL (default: https://relayer.dev.memwal.ai).
|
|
6
6
|
|
|
7
7
|
No-auth tests (always run, no env vars needed):
|
|
8
8
|
- /health endpoint
|
|
@@ -31,7 +31,7 @@ Usage:
|
|
|
31
31
|
# Run against staging using env vars
|
|
32
32
|
export MEMWAL_PRIVATE_KEY="<your-ed25519-delegate-private-key-hex>"
|
|
33
33
|
export MEMWAL_ACCOUNT_ID="0x-your-walrus-memory-account-id"
|
|
34
|
-
export MEMWAL_SERVER_URL="https://relayer
|
|
34
|
+
export MEMWAL_SERVER_URL="https://relayer.dev.memwal.ai"
|
|
35
35
|
python -m pytest tests/test_integration.py -v
|
|
36
36
|
"""
|
|
37
37
|
|
|
@@ -54,7 +54,7 @@ pytestmark = pytest.mark.integration
|
|
|
54
54
|
|
|
55
55
|
# ── Config ───────────────────────────────────────────────────────────────────
|
|
56
56
|
|
|
57
|
-
SERVER_URL = os.environ.get("MEMWAL_SERVER_URL", "https://relayer
|
|
57
|
+
SERVER_URL = os.environ.get("MEMWAL_SERVER_URL", "https://relayer.dev.memwal.ai")
|
|
58
58
|
PRIVATE_KEY_HEX = os.environ.get("MEMWAL_PRIVATE_KEY", "")
|
|
59
59
|
ACCOUNT_ID = os.environ.get("MEMWAL_ACCOUNT_ID", "")
|
|
60
60
|
|
|
@@ -98,6 +98,9 @@ def _async_client(namespace: str = _E2E_NAMESPACE) -> MemWal:
|
|
|
98
98
|
# ── Helpers ───────────────────────────────────────────────────────────────────
|
|
99
99
|
|
|
100
100
|
|
|
101
|
+
_HTTP_CLIENT = httpx.Client(timeout=30, transport=httpx.HTTPTransport(retries=3))
|
|
102
|
+
|
|
103
|
+
|
|
101
104
|
def _raw_signed_request(
|
|
102
105
|
method: str,
|
|
103
106
|
path: str,
|
|
@@ -125,20 +128,19 @@ def _raw_signed_request(
|
|
|
125
128
|
signature_hex = signed.signature.hex()
|
|
126
129
|
pub_key_hex = pub_key_override or signing_key.verify_key.encode().hex()
|
|
127
130
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
)
|
|
131
|
+
return _HTTP_CLIENT.request(
|
|
132
|
+
method,
|
|
133
|
+
f"{base_url}{path}",
|
|
134
|
+
content=body_bytes,
|
|
135
|
+
headers={
|
|
136
|
+
"Content-Type": "application/json",
|
|
137
|
+
"x-public-key": pub_key_hex,
|
|
138
|
+
"x-signature": signature_hex,
|
|
139
|
+
"x-timestamp": timestamp,
|
|
140
|
+
"x-nonce": nonce,
|
|
141
|
+
"x-account-id": ACCOUNT_ID or "0x0",
|
|
142
|
+
},
|
|
143
|
+
)
|
|
142
144
|
|
|
143
145
|
|
|
144
146
|
# ── No-auth tests (always run) ────────────────────────────────────────────────
|
|
@@ -168,8 +170,7 @@ class TestAuthRejection:
|
|
|
168
170
|
|
|
169
171
|
def test_unsigned_request_rejected(self) -> None:
|
|
170
172
|
"""Request with no auth headers → 401."""
|
|
171
|
-
|
|
172
|
-
resp = client.post(f"{SERVER_URL}/api/remember", json=self._body)
|
|
173
|
+
resp = _HTTP_CLIENT.post(f"{SERVER_URL}/api/remember", json=self._body)
|
|
173
174
|
assert resp.status_code == 401, f"Expected 401, got {resp.status_code}: {resp.text}"
|
|
174
175
|
|
|
175
176
|
def test_wrong_signature_rejected(self) -> None:
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|