Add entities namespace and activate memory pipeline hooks#4
Merged
Conversation
## Summary Adds the `entities` namespace (`EntitiesClient` / `AsyncEntitiesClient`) over `/v1/entities`, activates memory pipeline hooks that were previously accepted at registration but never invoked, and introduces two narrower error subclasses for TS SDK parity. ## Changes ### Entities namespace - Add `atomicmemory/entities/` package: `types.py` (Pydantic wire models), `client.py` (sync), `async_client.py` (async), `errors.py` (`EntitiesClientError`). - Wire `client.entities` onto `AtomicMemoryClient` and `AsyncAtomicMemoryClient` using the same transport config, closed with the client. - Export all entity types and both client classes from the package root. - Operations: `profile`, `list`, `get`, `delete`, `attributes`, `memory_history`, `patch_settings`, `merge`. - Python field names match the snake_case wire 1:1 — no camelCase mapping layer. ### Memory pipeline hooks - `MemoryService` and `AsyncMemoryService` now execute registered pipeline hooks: `preprocess_ingest` (may split one input into many; per-item results merge in order), `postprocess_ingest`, `preprocess_search`, `postprocess_search`, `preprocess_get`, `postprocess_get`, and `postprocess_list`. - `delete` and `package` take no pipeline hooks, matching TS semantics. - Add `AsyncMemoryProcessingPipeline` and `NOOP_ASYNC_PIPELINE`; export from `atomicmemory.memory`. - `MemoryProcessingPipeline` hook signatures are now synchronous; the async surface uses `AsyncMemoryProcessingPipeline`. ### Error subclasses - Add `UnsupportedOperationError` (subclass of `ProviderError`) and `InvalidScopeError` (subclass of `ValidationError`); existing `except ProviderError` / `except ValidationError` handlers keep working. - Export both from the package root. ### API key handling - `api_key` fields in `AtomicMemoryClientConfig` and `EntitiesClientConfig` changed to `SecretStr` to prevent accidental logging. The secret value is extracted only at the transport call site. ### Client close semantics - `AtomicMemoryClient.close()` aligned with `AsyncAtomicMemoryClient.close()`: first-error-wins across all three namespaces; previously a later namespace's failure silently replaced an earlier one. ### CI - Add `.github/workflows/publish-pypi.yml`: manual, version-gated OIDC Trusted Publishing workflow; guarded to run only on the public repository. ## Why - The `entities` namespace is required for agent workflows that read entity profiles, inspect attribute triples, and merge duplicate entities — previously only accessible via raw HTTP. - Pipeline hooks have been part of the registration API since the initial release but had no effect; callers supplying hooks for content splitting or result logging received no errors and no execution. - `UnsupportedOperationError` and `InvalidScopeError` allow callers to catch specific failure modes without parsing error messages, matching the TS SDK's discriminated error hierarchy. - `SecretStr` ensures API keys are redacted in Pydantic repr and default logging paths without changing the external dict-based config interface. ## Validation - `tests/entities/` — 7 new test modules covering sync/async client round-trips, input validation, response validation, and type models (~1,280 lines). - `tests/test_pipeline_hooks.py` / `tests/test_pipeline_hooks_async.py` — hook invocation order, split-ingest merging, postprocess receives processed request (~460 lines). - `tests/test_error_subclasses.py` — subclass hierarchy, `isinstance` compatibility with parent handlers (~256 lines). - `tests/test_api_key_redaction.py` — `SecretStr` repr, no plaintext key in error messages (~149 lines). - `tests/_pipeline_fakes.py` — shared fake pipeline/provider infrastructure extracted from client tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the
entitiesnamespace (EntitiesClient/AsyncEntitiesClient) over/v1/entities, activates memory pipeline hooks that were previously accepted at registration but never invoked, and introduces two narrower error subclasses for TS SDK parity.Changes
Entities namespace
atomicmemory/entities/package:types.py(Pydantic wire models),client.py(sync),async_client.py(async),errors.py(EntitiesClientError).client.entitiesontoAtomicMemoryClientandAsyncAtomicMemoryClientusing the same transport config, closed with the client.profile,list,get,delete,attributes,memory_history,patch_settings,merge.Memory pipeline hooks
MemoryServiceandAsyncMemoryServicenow execute registered pipeline hooks:preprocess_ingest(may split one input into many; per-item results merge in order),postprocess_ingest,preprocess_search,postprocess_search,preprocess_get,postprocess_get, andpostprocess_list.deleteandpackagetake no pipeline hooks, matching TS semantics.AsyncMemoryProcessingPipelineandNOOP_ASYNC_PIPELINE; export fromatomicmemory.memory.MemoryProcessingPipelinehook signatures are now synchronous; the async surface usesAsyncMemoryProcessingPipeline.Error subclasses
UnsupportedOperationError(subclass ofProviderError) andInvalidScopeError(subclass ofValidationError); existingexcept ProviderError/except ValidationErrorhandlers keep working.API key handling
api_keyfields inAtomicMemoryClientConfigandEntitiesClientConfigchanged toSecretStrto prevent accidental logging. The secret value is extracted only at the transport call site.Client close semantics
AtomicMemoryClient.close()aligned withAsyncAtomicMemoryClient.close(): first-error-wins across all three namespaces; previously a later namespace's failure silently replaced an earlier one.CI
.github/workflows/publish-pypi.yml: manual, version-gated OIDC Trusted Publishing workflow; guarded to run only on the public repository.Why
entitiesnamespace is required for agent workflows that read entity profiles, inspect attribute triples, and merge duplicate entities — previously only accessible via raw HTTP.UnsupportedOperationErrorandInvalidScopeErrorallow callers to catch specific failure modes without parsing error messages, matching the TS SDK's discriminated error hierarchy.SecretStrensures API keys are redacted in Pydantic repr and default logging paths without changing the external dict-based config interface.Validation
tests/entities/— 7 new test modules covering sync/async client round-trips, input validation, response validation, and type models (~1,280 lines).tests/test_pipeline_hooks.py/tests/test_pipeline_hooks_async.py— hook invocation order, split-ingest merging, postprocess receives processed request (~460 lines).tests/test_error_subclasses.py— subclass hierarchy,isinstancecompatibility with parent handlers (~256 lines).tests/test_api_key_redaction.py—SecretStrrepr, no plaintext key in error messages (~149 lines).tests/_pipeline_fakes.py— shared fake pipeline/provider infrastructure extracted from client tests.