You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+10-1Lines changed: 10 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,16 @@ All notable changes to `atomicmemory` will be documented in this file.
4
4
5
5
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
7
-
## [Unreleased]
7
+
## [1.1.1] - 2026-06-11
8
+
9
+
### Added
10
+
-`UnsupportedOperationError` (subclass of `ProviderError`) and `InvalidScopeError` (subclass of `ValidationError`), raised where those parents were previously raised bare: a provider missing the `package` extension, and an operation missing required scope fields. Existing `except ProviderError` / `except ValidationError` handlers keep working; consumers can now catch the specific types, matching the TS SDK. Exported from the package root.
11
+
-`AsyncMemoryProcessingPipeline` + `NOOP_ASYNC_PIPELINE` (exported from `atomicmemory.memory` alongside the existing sync type): the async-surface pipeline type used by `AsyncProviderRegistration`.
12
+
-`EntitiesClient` / `AsyncEntitiesClient`: the `entities` namespace over `/v1/entities`, ported from the TS SDK — entity profiles, listing, detail, cascade delete, attribute triples, per-memory history, per-entity settings patching, and entity merge. Wired into `AtomicMemoryClient`/`AsyncAtomicMemoryClient` as `.entities` on the same transport config, closed with the client. Python field names match the snake_case wire directly (the TS camelCase mapping layer has no Python counterpart).
13
+
14
+
### Changed
15
+
- Registered memory pipelines now actually execute: `MemoryService`/`AsyncMemoryService` run `preprocess_ingest` (which may split one input into many; per-item results merge in order), `postprocess_ingest`, `preprocess_search`/`postprocess_search` (postprocess receives the processed request), `preprocess_get`/`postprocess_get`, and `postprocess_list`, matching the TS `MemoryService` semantics. `delete` and `package` take no pipeline. Before 1.1.1 these hooks were accepted at registration but never invoked. Hook exceptions propagate unwrapped — hooks are caller-supplied code.
16
+
-`MemoryProcessingPipeline` hook signatures are now synchronous (the async surface uses `AsyncMemoryProcessingPipeline`). Type-hint change only for code that constructed pipelines — which received no behavior before this release.
Copy file name to clipboardExpand all lines: README.md
+59-1Lines changed: 59 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,7 +21,7 @@ This is a Python port of the TypeScript [`atomicmemory-sdk`](https://github.com/
21
21
22
22
## Status
23
23
24
-
Stable release — `1.0.0` on [PyPI](https://pypi.org/project/atomicmemory/).
24
+
Stable release — `1.1.0` on [PyPI](https://pypi.org/project/atomicmemory/); `1.2.0` staged on main.
25
25
26
26
## Installation
27
27
@@ -131,6 +131,64 @@ The `client.storage` namespace mirrors the TypeScript SDK's direct storage API:
131
131
132
132
Every storage request sends `Authorization: Bearer <apiKey>` and `X-AtomicMemory-User-Id`. The SDK never sends the legacy `?user_id=` URL parameter.
133
133
134
+
135
+
## Entities
136
+
137
+
The `client.entities` namespace (on `AtomicMemoryClient` and `AsyncAtomicMemoryClient`) provides typed access to the `/v1/entities` API — profiles, attributes, memory history, settings, and entity merge.
138
+
139
+
```python
140
+
from atomicmemory import AtomicMemoryClient
141
+
142
+
with AtomicMemoryClient({
143
+
"apiUrl": "http://localhost:17350",
144
+
"apiKey": "server-api-key",
145
+
"userId": "demo",
146
+
}) as client:
147
+
# fetch the synthesized profile for a user
148
+
profile = client.entities.profile("alice")
149
+
print(profile.entity_id, profile.summary)
150
+
151
+
# list all entities (paginated)
152
+
result = client.entities.list(page=1, page_size=20)
153
+
for entity in result.entities:
154
+
print(entity.entity_id, entity.memory_count)
155
+
```
156
+
157
+
The async surface is identical — call `await client.entities.profile("alice")` on `AsyncAtomicMemoryClient`.
158
+
159
+
## Memory pipelines
160
+
161
+
`MemoryProcessingPipeline` (and its async twin `AsyncMemoryProcessingPipeline`) let you attach optional pre- and post-processing hooks to any registered provider. All hook fields are `None` by default, so a pipeline with only one hook populated is valid.
162
+
163
+
```python
164
+
from atomicmemory import AtomicMemoryClient
165
+
from atomicmemory.memory.pipeline import MemoryProcessingPipeline
166
+
from atomicmemory.memory.registry import ProviderRegistration, default_registry
167
+
168
+
defsplit_long_content(input):
169
+
# return a list of IngestInput items; here we pass through unchanged
If `preprocess_ingest` splits one input into N items and a per-item ingest raises mid-loop, earlier items are already persisted and no merged result is returned — keep splitting pipelines idempotent.
191
+
134
192
## v1 wire contract
135
193
136
194
`atomicmemory.contract.v1` is the wire codec for the v1 provider-contract encoding. The wire form is deliberately mixed-case — `Memory.createdAt`/`updatedAt` and `SearchResult.rankingScore` are camelCase; `version_id`, `observed_at`, and retrieval-receipt fields are snake_case — as pinned by the vendored `contract/CONTRACT.md`. This module is the only place that mapping lives; in-process models and provider mappers are unchanged.
0 commit comments