fix(integrations): apply the header contract the docs described
Review found the contract documented but not implemented, and one client path missed entirely. AsyncMemoryClient's custom-client branch still carried the old literal header dict, so `AsyncMemoryClient(client=...)` sent no surface identity at all — the exact asymmetry this work set out to remove. Both custom-client branches also used a blanket headers.update(), which overwrites. That is the one code path where an outer layer's identity can physically be present, and it was the one path that erased it. They now check-then-set the identity headers and append to an existing client stack, which is what set-once and append-only were supposed to mean. AGENTS.md claimed a plugin calling the Python SDK produces `mem0-plugin/0.3.1, mem0-python/2.0.19`. Nothing in the repo sets the env vars that would make that happen, so the concatenation was unreachable. Replaced with the three ways an integration can actually declare itself, in preference order. memory_core's comment said the backend reads X-Mem0-Source. That is only true from the platform release shipping alongside this, and a reader would otherwise trust it and build header-only attribution that silently does nothing — which is how vercel-ai-sdk was written in the first cut. Corrected in all seven copies, and the body value is what makes attribution work against either backend. mem0-ts hardcoded SDK_VERSION = "3.1.8" while the repo already injects __MEM0_SDK_VERSION__ via tsup, the same mechanism telemetry.ts uses. The hardcode was correct only until the next release bump. Dropped both `as never` casts in pi-agent. They suppressed an excess-property error but also disabled checking of every other option at those call sites, so a typo in filters or threshold would have compiled. SearchMemoryOptions now declares `source` instead. Stack truncation cut mid-identifier, leaving a fragment that parses as a real client name. It now drops whole entries. Claude-Session: https://claude.ai/code/session_01C7tEmH86HAr7GoAAKCEHZb
This commit is contained in:
+16
-6
@@ -60,13 +60,23 @@ and the rules on them are what keep one layer from erasing another:
|
||||
| `X-Application` | the host app it runs inside | **set-once** — write only if absent |
|
||||
| `X-Mem0-Client` | `name/version`, outermost first | **append-only** — add yourself, never replace |
|
||||
|
||||
Set-once means `setdefault`, never assignment. An integration that wraps the
|
||||
SDK is the outermost layer and sets the source; the SDK underneath must defer to
|
||||
it. Assignment is exactly how every agent plugin came to be indistinguishable
|
||||
from every other one at the platform.
|
||||
Set-once means check-then-set, never assignment. An integration that wraps the
|
||||
SDK is the outermost layer and sets the source; the SDK underneath defers to it.
|
||||
Assignment is exactly how every agent plugin came to be indistinguishable from
|
||||
every other one at the platform.
|
||||
|
||||
Append-only means a plugin calling the Python SDK produces
|
||||
`mem0-plugin/0.3.1, mem0-python/2.0.19`, so neither layer can erase the other.
|
||||
How to declare it from an integration, in order of preference:
|
||||
|
||||
1. Send the headers yourself, if you make the HTTP call directly.
|
||||
2. Pass `source` in the call options, if you go through an SDK.
|
||||
3. Set `MEM0_SOURCE` / `MEM0_APPLICATION` / `MEM0_CLIENT_STACK` in the
|
||||
environment before constructing the client. The SDKs read these and defer to
|
||||
anything already present.
|
||||
|
||||
Append-only applies where a stack can actually form: an SDK handed a client that
|
||||
already carries `X-Mem0-Client` appends itself rather than replacing. An SDK
|
||||
constructed with no outer context simply reports itself, which is correct — it
|
||||
is the outermost layer in that process.
|
||||
|
||||
The backend recognizes a fixed list of source values and buckets everything else
|
||||
into `OTHERS`. A new value has to land in the platform's `EventSource` enum, so
|
||||
|
||||
Reference in New Issue
Block a user