memwal 0.2.1.dev0__tar.gz → 0.2.2__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.1.dev0 → memwal-0.2.2}/CHANGELOG.md +28 -11
- {memwal-0.2.1.dev0 → memwal-0.2.2}/PKG-INFO +14 -3
- {memwal-0.2.1.dev0 → memwal-0.2.2}/README.md +13 -2
- {memwal-0.2.1.dev0 → memwal-0.2.2}/memwal/__init__.py +5 -1
- {memwal-0.2.1.dev0 → memwal-0.2.2}/memwal/client.py +367 -59
- {memwal-0.2.1.dev0 → memwal-0.2.2}/memwal/compatibility.py +6 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/memwal/mock.py +23 -3
- {memwal-0.2.1.dev0 → memwal-0.2.2}/memwal/types.py +16 -5
- {memwal-0.2.1.dev0 → memwal-0.2.2}/memwal/utils.py +44 -10
- {memwal-0.2.1.dev0 → memwal-0.2.2}/notebooks/walrus_memory_python_sdk.ipynb +2 -2
- {memwal-0.2.1.dev0 → memwal-0.2.2}/pyproject.toml +1 -1
- {memwal-0.2.1.dev0 → memwal-0.2.2}/run_tests.py +1 -1
- memwal-0.2.2/tests/test_ask_validation.py +56 -0
- memwal-0.2.2/tests/test_destroy_and_cancel_shield.py +661 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_env_presets.py +2 -2
- memwal-0.2.2/tests/test_forget.py +91 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_integration.py +20 -19
- memwal-0.2.2/tests/test_json_body.py +310 -0
- memwal-0.2.2/tests/test_missing_response_fields.py +125 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_mock.py +24 -1
- memwal-0.2.2/tests/test_recall_validation.py +84 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/.gitignore +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/examples/.env.example +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/examples/.gitignore +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/examples/async_remember_demo.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/examples/interactive_demo.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/examples/verify_credentials.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/memwal/middleware.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/__init__.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_auth_rejected_message.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_blank_text.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_client.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_empty_namespace.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_list_namespaces.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_middleware.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_nonfinite_validation.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_normalize_server_url.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_polling_delay.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_recall_weights.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_remember_derived_key.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_retry_after_http_date.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_signing.py +0 -0
- {memwal-0.2.1.dev0 → memwal-0.2.2}/tests/test_transport_retry.py +0 -0
|
@@ -1,13 +1,30 @@
|
|
|
1
1
|
# memwal
|
|
2
2
|
|
|
3
|
+
## 0.2.2
|
|
4
|
+
|
|
5
|
+
Unreleased.
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `forget(namespace=None)` (and alias `forget_namespace(namespace=None)`) on `MemWal` and `MemWalSync` wraps `POST /api/forget` and returns `ForgetResult` (`deleted`, `namespace`, `owner`). It deletes the owner's index rows for the namespace while leaving Walrus blobs in place. `MemWalMock` and `MemWalMockSync` retain synchronous per-blob `forget(blob_id) -> bool` and add `forget_namespace(namespace=None) -> ForgetResult` for namespace erasure. (#1061)
|
|
10
|
+
- `MemWal.destroy()` and `MemWalSync.destroy()` (plus `close(clear_keys=True)`) zero the client's internal `bytearray` seed copy in place, clear `_private_key_hex`, drop `_signing_key` and cached SEAL session credentials, cancel in-flight initialization tasks, and reject any subsequent or in-flight operation with `MemWalError`. `MemWal.create()` and `MemWalSync.create()` also accept 32-byte `bytes` / `bytearray` keys and copy caller `bytearray` buffers so `destroy()` leaves the caller's buffer intact. (#975)
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- `health()`, `compatibility()`, `_fetch_server_config()`, package-version preflight probes, and `_signed_request()` raise `MemWalJsonBodyError` (a `MemWalError` subclass carrying `.status`, `.endpoint`, and `.body`) instead of Python's raw `json.JSONDecodeError` when a 2xx response has an empty or non-JSON body. (#1219)
|
|
15
|
+
- Shield shared `_build_seal_session` and `_resolve_owner` initialization tasks with `asyncio.shield`, clear the shared task slot via a completion callback that consumes exceptions on orphaned tasks, and cancel/drain in-flight initialization tasks in `close()` so cancelling one concurrent caller does not abort sibling callers or leave unretrieved task exceptions. (#1029)
|
|
16
|
+
- `health`, `ask`, `restore`, `list_namespaces`, `remember_manual`, and `recall` raise `MemWalError` naming the endpoint and field when a 2xx response omits a required field. They used to raise a bare `KeyError` that callers catching `MemWalError` never saw. (#1250, #1256)
|
|
17
|
+
- `ask()` rejects a blank `question` and a `limit` that is not a positive integer before it signs the request. A NaN `limit` used to serialize as an invalid-JSON `NaN` token, and negative or fractional values were sent as-is. (#1249, #1255)
|
|
18
|
+
- `recall()` rejects a blank `query` and a `max_distance` that is NaN, infinite, negative, or not a number before it signs the request, and `MemWalMock.recall()` rejects the same `max_distance`. A NaN or negative threshold used to return an empty page that looked like an empty namespace. (#1248, #1254)
|
|
19
|
+
|
|
3
20
|
## 0.2.1
|
|
4
21
|
|
|
5
22
|
Unreleased.
|
|
6
23
|
|
|
7
24
|
### Fixed
|
|
8
25
|
|
|
9
|
-
- `with_memwal_*` gains `save_mode` and confirmable saves: `memwal_wait_for_saves` (async and sync) polls every job the middleware enqueued, and restores the job ids if that poll raises so a retry can still confirm them. (
|
|
10
|
-
- `wait_for_remember_jobs` chunks its status reads to the relayer's 20-id `MAX_BULK_ITEMS` cap. Above it the relayer answers a non-transient 400, so a wait over 21+ jobs raised on every attempt and could never confirm — reachable from `save_mode="remember"` after 21 turns, or from two fat `analyze` extracts.
|
|
26
|
+
- `with_memwal_*` gains `save_mode` and confirmable saves: `memwal_wait_for_saves` (async and sync) polls every job the middleware enqueued, and restores the job ids if that poll raises so a retry can still confirm them. (#410, #411, #412)
|
|
27
|
+
- `wait_for_remember_jobs` chunks its status reads to the relayer's 20-id `MAX_BULK_ITEMS` cap. Above it the relayer answers a non-transient 400, so a wait over 21+ jobs raised on every attempt and could never confirm — reachable from `save_mode="remember"` after 21 turns, or from two fat `analyze` extracts.
|
|
11
28
|
|
|
12
29
|
- Save confirmation preserves unconfirmed job IDs when an async wait is cancelled or a synchronous wait is interrupted, then propagates the cancellation or interrupt. (#1303)
|
|
13
30
|
- Reject explicitly empty namespaces instead of silently writing to the default namespace. (#1265)
|
|
@@ -28,7 +45,7 @@ Unreleased.
|
|
|
28
45
|
|
|
29
46
|
### Added
|
|
30
47
|
|
|
31
|
-
- `get_remember_status(job_id)` on `MemWal` and `MemWalSync` returns `RememberJobStatus` from `GET /api/remember/{job_id}`, accepting 200 and 404 like the TypeScript SDK. (
|
|
48
|
+
- `get_remember_status(job_id)` on `MemWal` and `MemWalSync` returns `RememberJobStatus` from `GET /api/remember/{job_id}`, accepting 200 and 404 like the TypeScript SDK. (#1096)
|
|
32
49
|
- `RecallMemory` and `RecallManualHit` include `created_at` and `score`. (#1178)
|
|
33
50
|
- `RecallParams` accepts `scoring_weights` and `sort`. `recall()` forwards them on `POST /api/recall`. (#1062)
|
|
34
51
|
|
|
@@ -36,18 +53,18 @@ Unreleased.
|
|
|
36
53
|
|
|
37
54
|
- The default `server_url` is `https://relayer.memory.walrus.xyz`, matching the TypeScript SDK. `env="local"` still selects `http://127.0.0.1:8000`. (#1064)
|
|
38
55
|
- `remember` derives an idempotency key from the namespace and text inside a 30-minute bucket, matching the TypeScript SDK. A retry inside that window reuses the job. An explicit `idempotency_key` still wins. `remember_bulk_async` still sends no key. (#1094)
|
|
39
|
-
- `get_remember_status` and `wait_for_remember_job` reject a job id outside `[A-Za-z0-9_-]+` before the request. `.`, `..`, a backslash, and encoded dot-dot used to pass a denylist and be rewritten after signing. An empty id used to call `GET /api/remember/` and raise `json.JSONDecodeError`. An unparseable 404 is `not_found` / `MemWalRememberJobNotFound`, not a JSON error. `uuid.UUID` is coerced with `str()`. Valid UUID job ids are unchanged. (
|
|
56
|
+
- `get_remember_status` and `wait_for_remember_job` reject a job id outside `[A-Za-z0-9_-]+` before the request. `.`, `..`, a backslash, and encoded dot-dot used to pass a denylist and be rewritten after signing. An empty id used to call `GET /api/remember/` and raise `json.JSONDecodeError`. An unparseable 404 is `not_found` / `MemWalRememberJobNotFound`, not a JSON error. `uuid.UUID` is coerced with `str()`. Valid UUID job ids are unchanged. (#1100, #1216)
|
|
40
57
|
- `remember`, `remember_bulk`, `analyze`, and `embed` reject whitespace-only text before the request. A blank body used to be accepted and then sit until the caller timed out. (#1129)
|
|
41
58
|
- A 401 `AUTH_REJECTED` now says a wallet address is not a MemWal account ID. (#1132)
|
|
42
|
-
- `wait_for_remember_jobs` / `remember_bulk_and_wait` no longer return a batch they could not read as if it were still uploading. When every status poll is rate-limited, the wait makes one confirming read and raises `MemWalRateLimited` (`status` 429, `job_ids`, `retry_after`) if that is refused too. An item still unsettled at the deadline names its last known status, or says no read got through. (
|
|
43
|
-
- A job the bulk status response omits stays pending and is asked about again. It used to drop out and settle as `timeout`.
|
|
59
|
+
- `wait_for_remember_jobs` / `remember_bulk_and_wait` no longer return a batch they could not read as if it were still uploading. When every status poll is rate-limited, the wait makes one confirming read and raises `MemWalRateLimited` (`status` 429, `job_ids`, `retry_after`) if that is refused too. An item still unsettled at the deadline names its last known status, or says no read got through. (#967)
|
|
60
|
+
- A job the bulk status response omits stays pending and is asked about again. It used to drop out and settle as `timeout`.
|
|
44
61
|
- `wait_for_remember_job` retries a transport error and stops at the caller's deadline. `Retry-After` may be a number of seconds or an HTTP date. (#1000, #1151)
|
|
45
|
-
- `MemWalRememberJobTimeout` carries `last_status`, `server_error` and `last_refusal`, and its message names the relayer's last reported state. Under upload congestion a job stays `running` for up to ~25 minutes while the relayer retries, and the timeout used to hide that, so a job that was still retrying looked dead. (
|
|
46
|
-
- A `max_distance` filter keeps the relayer's matching `total` instead of replacing it with the number of rows left.
|
|
62
|
+
- `MemWalRememberJobTimeout` carries `last_status`, `server_error` and `last_refusal`, and its message names the relayer's last reported state. Under upload congestion a job stays `running` for up to ~25 minutes while the relayer retries, and the timeout used to hide that, so a job that was still retrying looked dead. (#966)
|
|
63
|
+
- A `max_distance` filter keeps the relayer's matching `total` instead of replacing it with the number of rows left.
|
|
47
64
|
- Middleware does not recall or auto-save on a tool-execution step. A later tool step reuses the cached recall. `flush()` raises when a background save failed, and `on_save_error` runs. The memory instruction is anchored at the start of the prompt. (#1107, #1117, #1159)
|
|
48
65
|
- `normalize_private_key` accepts an uppercase `0X` prefix. Error text redacts IPv6, `0.0.0.0`, and `localhost` subdomains. (#1172, #1161)
|
|
49
|
-
- Grow `wait_for_remember_job` / `wait_for_remember_jobs` poll delay 1.5× from the caller interval (floor 100ms) toward a 5s cap, with an immediate first poll. Backoff is disabled above the cap.
|
|
50
|
-
- A 429 during a remember-job wait is reported on the timeout. Retry-After is still clamped to the caller's remaining budget, and that remainder still buys one status read.
|
|
66
|
+
- Grow `wait_for_remember_job` / `wait_for_remember_jobs` poll delay 1.5× from the caller interval (floor 100ms) toward a 5s cap, with an immediate first poll. Backoff is disabled above the cap.
|
|
67
|
+
- A 429 during a remember-job wait is reported on the timeout. Retry-After is still clamped to the caller's remaining budget, and that remainder still buys one status read.
|
|
51
68
|
|
|
52
69
|
## 0.1.11
|
|
53
70
|
|
|
@@ -67,7 +84,7 @@ Unreleased.
|
|
|
67
84
|
|
|
68
85
|
- 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.
|
|
69
86
|
- `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.
|
|
70
|
-
- restore `truncated` docs now match
|
|
87
|
+
- restore `truncated` docs now match the relayer’s retryable-incomplete semantics.
|
|
71
88
|
- Warn when `server_url` uses plaintext `http://` against a non-localhost host, matching the TypeScript SDK `normalizeServerUrl` guard. Localhost, `127.0.0.1`, `::1`, and `*.localhost` are exempt; invalid URLs are left for the HTTP client to surface. The warning logs only scheme, host, and port so URL userinfo is not written to logs.
|
|
72
89
|
|
|
73
90
|
## 0.1.8
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: memwal
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
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
|
|
@@ -147,7 +147,7 @@ async def test_memory_flow():
|
|
|
147
147
|
assert "dark mode" in result.results[0].text
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
The mock supports remember/job polling, bulk remember, recall, analyze, embed, ask, health, restore, list_namespaces, `forget(blob_id)
|
|
150
|
+
The mock supports remember/job polling, bulk remember, recall, analyze, embed, ask, health, restore, list_namespaces, `forget(blob_id)` (synchronous per-blob deletion returning `bool`), `forget_namespace(namespace?)` (namespace erasure returning `ForgetResult`), and `clear(namespace?)`. For deterministic behavior, `analyze` stores its full input as one fact instead of invoking an LLM extractor. Its simple relevance score is for application tests, not production search-quality evaluation.
|
|
151
151
|
|
|
152
152
|
### Context Manager
|
|
153
153
|
|
|
@@ -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
|
|
@@ -254,11 +254,22 @@ Create a new async client.
|
|
|
254
254
|
| `await analyze(text, namespace?)` | Extract and store facts |
|
|
255
255
|
| `await ask(question, limit?, namespace?)` | Ask a question answered using memories |
|
|
256
256
|
| `await restore(namespace, limit?)` | Restore a namespace |
|
|
257
|
+
| `await forget(namespace?)` | Delete index rows for the namespace. Walrus blobs stay. Returns `ForgetResult`. |
|
|
257
258
|
| `await list_namespaces(cursor?, limit?)` | List namespaces that hold memories; paginate on `has_more` |
|
|
258
259
|
| `await health()` | Check server health |
|
|
259
260
|
| `await remember_manual(opts)` | Store encrypted payload + pre-computed vector |
|
|
260
261
|
| `await recall_manual(opts)` | Search with pre-computed vector |
|
|
261
262
|
| `await get_public_key_hex()` | Get Ed25519 public key |
|
|
263
|
+
| `destroy()` | Zero internal key seed buffer, drop signing credentials/session cache, and permanently invalidate the client |
|
|
264
|
+
| `await close(clear_keys=False)` | Close the underlying HTTP client (pass `clear_keys=True` to also run `destroy()`) |
|
|
265
|
+
|
|
266
|
+
### Key Lifecycle & `destroy()`
|
|
267
|
+
|
|
268
|
+
For parity with the TypeScript SDK's `destroy()`, `MemWal` and `MemWalSync` expose `destroy()` and `close(clear_keys=True)`:
|
|
269
|
+
|
|
270
|
+
- `key` may be passed as a hex string, `suiprivkey1...` string, or a 32-byte `bytes` / `bytearray`. When passed as `bytearray`, the SDK copies the bytes into its own internal buffer so `destroy()` zeroes only the client's copy and leaves the caller's `bytearray` untouched.
|
|
271
|
+
- Calling `destroy()` (or `await client.close(clear_keys=True)` / `sync_client.close(clear_keys=True)`) zero-fills the client's internal `bytearray` seed copy in place, clears `_private_key_hex`, drops the `_signing_key` and cached SEAL session references, cancels any in-flight initialization tasks, and causes subsequent or in-flight calls to raise `MemWalError`.
|
|
272
|
+
- **CPython memory semantics**: Python `str` and `bytes` objects (and PyNaCl's internal C-level `SigningKey` buffers) are immutable in CPython and cannot be overwritten in place from pure Python. `destroy()` zeroes the mutable `bytearray` copy and drops all references to immutable key objects so they become eligible for garbage collection once the caller also releases its references. To minimize plaintext `str` copies in process memory, pass a 32-byte `bytearray` to `MemWal.create()` and zero your own buffer after creation.
|
|
262
273
|
|
|
263
274
|
## Authentication
|
|
264
275
|
|
|
@@ -106,7 +106,7 @@ async def test_memory_flow():
|
|
|
106
106
|
assert "dark mode" in result.results[0].text
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
The mock supports remember/job polling, bulk remember, recall, analyze, embed, ask, health, restore, list_namespaces, `forget(blob_id)
|
|
109
|
+
The mock supports remember/job polling, bulk remember, recall, analyze, embed, ask, health, restore, list_namespaces, `forget(blob_id)` (synchronous per-blob deletion returning `bool`), `forget_namespace(namespace?)` (namespace erasure returning `ForgetResult`), and `clear(namespace?)`. For deterministic behavior, `analyze` stores its full input as one fact instead of invoking an LLM extractor. Its simple relevance score is for application tests, not production search-quality evaluation.
|
|
110
110
|
|
|
111
111
|
### Context Manager
|
|
112
112
|
|
|
@@ -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
|
|
@@ -213,11 +213,22 @@ Create a new async client.
|
|
|
213
213
|
| `await analyze(text, namespace?)` | Extract and store facts |
|
|
214
214
|
| `await ask(question, limit?, namespace?)` | Ask a question answered using memories |
|
|
215
215
|
| `await restore(namespace, limit?)` | Restore a namespace |
|
|
216
|
+
| `await forget(namespace?)` | Delete index rows for the namespace. Walrus blobs stay. Returns `ForgetResult`. |
|
|
216
217
|
| `await list_namespaces(cursor?, limit?)` | List namespaces that hold memories; paginate on `has_more` |
|
|
217
218
|
| `await health()` | Check server health |
|
|
218
219
|
| `await remember_manual(opts)` | Store encrypted payload + pre-computed vector |
|
|
219
220
|
| `await recall_manual(opts)` | Search with pre-computed vector |
|
|
220
221
|
| `await get_public_key_hex()` | Get Ed25519 public key |
|
|
222
|
+
| `destroy()` | Zero internal key seed buffer, drop signing credentials/session cache, and permanently invalidate the client |
|
|
223
|
+
| `await close(clear_keys=False)` | Close the underlying HTTP client (pass `clear_keys=True` to also run `destroy()`) |
|
|
224
|
+
|
|
225
|
+
### Key Lifecycle & `destroy()`
|
|
226
|
+
|
|
227
|
+
For parity with the TypeScript SDK's `destroy()`, `MemWal` and `MemWalSync` expose `destroy()` and `close(clear_keys=True)`:
|
|
228
|
+
|
|
229
|
+
- `key` may be passed as a hex string, `suiprivkey1...` string, or a 32-byte `bytes` / `bytearray`. When passed as `bytearray`, the SDK copies the bytes into its own internal buffer so `destroy()` zeroes only the client's copy and leaves the caller's `bytearray` untouched.
|
|
230
|
+
- Calling `destroy()` (or `await client.close(clear_keys=True)` / `sync_client.close(clear_keys=True)`) zero-fills the client's internal `bytearray` seed copy in place, clears `_private_key_hex`, drops the `_signing_key` and cached SEAL session references, cancels any in-flight initialization tasks, and causes subsequent or in-flight calls to raise `MemWalError`.
|
|
231
|
+
- **CPython memory semantics**: Python `str` and `bytes` objects (and PyNaCl's internal C-level `SigningKey` buffers) are immutable in CPython and cannot be overwritten in place from pure Python. `destroy()` zeroes the mutable `bytearray` copy and drops all references to immutable key objects so they become eligible for garbage collection once the caller also releases its references. To minimize plaintext `str` copies in process memory, pass a 32-byte `bytearray` to `MemWal.create()` and zero your own buffer after creation.
|
|
221
232
|
|
|
222
233
|
## Authentication
|
|
223
234
|
|
|
@@ -27,6 +27,7 @@ from .client import (
|
|
|
27
27
|
MemWalClockDriftError,
|
|
28
28
|
MemWalCompatibilityError,
|
|
29
29
|
MemWalError,
|
|
30
|
+
MemWalJsonBodyError,
|
|
30
31
|
MemWalRateLimited,
|
|
31
32
|
MemWalRememberJobFailed,
|
|
32
33
|
MemWalRememberJobNotFound,
|
|
@@ -43,6 +44,7 @@ from .types import (
|
|
|
43
44
|
AskMemory,
|
|
44
45
|
AskResult,
|
|
45
46
|
EmbedResult,
|
|
47
|
+
ForgetResult,
|
|
46
48
|
HealthResult,
|
|
47
49
|
MemWalConfig,
|
|
48
50
|
NamespacesResult,
|
|
@@ -83,6 +85,7 @@ __all__ = [
|
|
|
83
85
|
"MemWalError",
|
|
84
86
|
"MemWalCompatibilityError",
|
|
85
87
|
"MemWalClockDriftError",
|
|
88
|
+
"MemWalJsonBodyError",
|
|
86
89
|
"MemWalRateLimited",
|
|
87
90
|
"MemWalRememberJobFailed",
|
|
88
91
|
"MemWalRememberJobNotFound",
|
|
@@ -118,6 +121,7 @@ __all__ = [
|
|
|
118
121
|
"AnalyzedFact",
|
|
119
122
|
"HealthResult",
|
|
120
123
|
"RestoreResult",
|
|
124
|
+
"ForgetResult",
|
|
121
125
|
"NamespaceSummary",
|
|
122
126
|
"NamespacesResult",
|
|
123
127
|
"ScoringWeights",
|
|
@@ -128,4 +132,4 @@ __all__ = [
|
|
|
128
132
|
"RecallManualResult",
|
|
129
133
|
]
|
|
130
134
|
|
|
131
|
-
__version__ = "0.2.
|
|
135
|
+
__version__ = "0.2.2"
|