@theokit/memory-mem0 3.0.2 → 3.0.4-next.0
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.
- package/CHANGELOG.md +134 -0
- package/LICENSE +2 -2
- package/README.md +21 -2
- package/dist/index.cjs +4 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +96 -8
- package/dist/index.d.ts +96 -8
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/package.json +16 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,139 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.0.4-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [01630ec]
|
|
8
|
+
- @theokit/sdk@4.63.4-next.0
|
|
9
|
+
|
|
10
|
+
## 3.0.3
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- e3f2a82: Public-API documentation reviewed file by file, and corrected wherever it disagreed
|
|
15
|
+
with the code. The docblocks ship in the `.d.ts`, so these read as behaviour changes
|
|
16
|
+
in an editor even though no behaviour changed.
|
|
17
|
+
|
|
18
|
+
The corrections that change what a caller would do:
|
|
19
|
+
|
|
20
|
+
- **`sdk-cache` documented its own premise backwards.** The header example labelled a
|
|
21
|
+
semantic hit as if it avoided the provider call. `asPlugin()` returns the cached
|
|
22
|
+
answer as `recalledContext`, which the agent loop injects as a `<memory-context>`
|
|
23
|
+
block _before_ the prompt — the request still goes to the provider. The two modes
|
|
24
|
+
are now labelled separately, with a table saying which one short-circuits and which
|
|
25
|
+
one seeds.
|
|
26
|
+
- **`sdk-handoff`'s five error classes said "throw".** Under the plugin wiring the
|
|
27
|
+
handler never throws; every failure becomes a tool result `{"ok":false,…}` handed
|
|
28
|
+
back to the model. Each class now says where it is actually observable. The header
|
|
29
|
+
also told readers to `import { Handoff } from "@theokit/sdk"`, from which it was
|
|
30
|
+
extracted.
|
|
31
|
+
- **`sdk-budget`'s `charge()` claimed idempotency across concurrent calls.** The mutex
|
|
32
|
+
serialises, it does not deduplicate: two identical calls record twice. Related, and
|
|
33
|
+
newly documented: with `maxUsd` set, a model missing from the pricing table denies
|
|
34
|
+
every request rather than passing it — and the table matches by exact string, so
|
|
35
|
+
`"openai/gpt-4o"` does not match `"gpt-4o"`.
|
|
36
|
+
- **The three `memory-*` adapters advertised an env-var fallback they do not read**,
|
|
37
|
+
and their peer dependencies are required rather than optional. Their behavioural
|
|
38
|
+
differences are now stated where they break the "interchangeable adapter"
|
|
39
|
+
assumption — honcho ignores `k` and always throws on `delete`; mem0 recalls across
|
|
40
|
+
sessions by design; supermemory ignores `sessionId` entirely.
|
|
41
|
+
- **`sdk-memory`'s `truncated` flag was documented as its own inverse**, and its
|
|
42
|
+
dreaming sweep claimed a mutex it never takes against the writer it names.
|
|
43
|
+
- **`sdk-tools`** corrected `run_vitest`'s unreachable `no_vitest` code, `truncation`'s
|
|
44
|
+
replacement-character claim, and two return shapes missing a live error code.
|
|
45
|
+
- **`acp`/`cli`** corrected sixteen statements including a named error class that is
|
|
46
|
+
not the one raised, a handler documented as calling `fork()` that refuses
|
|
47
|
+
unconditionally, handlers described as pure that mint ids and mutate a store, a
|
|
48
|
+
config loader credited to Zod in a package that does not import it, and a `--force`
|
|
49
|
+
scaffold described as atomic that deletes the destination before the rename.
|
|
50
|
+
|
|
51
|
+
Undocumented public symbols were documented across every package, with each claim
|
|
52
|
+
checked against the implementation rather than inferred from the name.
|
|
53
|
+
|
|
54
|
+
- e368fc1: Every published declaration file now compiles without `skipLibCheck` (#345). The
|
|
55
|
+
DTS rollup emitted symbols as a re-export from a chunk while omitting them from
|
|
56
|
+
that chunk's `import`, and dropped type-only imports from external packages —
|
|
57
|
+
leaving 51 unresolved references across ten of the twelve packages. Nothing broke
|
|
58
|
+
at runtime, and `tsc` stayed green for anyone with `skipLibCheck` on, but a
|
|
59
|
+
consumer running type-aware lint saw every type reached through one degrade to
|
|
60
|
+
`error`.
|
|
61
|
+
|
|
62
|
+
The declarations are repaired at build time from the compiler's own diagnostics.
|
|
63
|
+
No source or API change.
|
|
64
|
+
|
|
65
|
+
- 1ac974f: **`@theokit/sdk-pty` declares its licence.** Every published version up to now shipped with no `license` field in the manifest. npm reads the field, not the directory, so the tarball was all-rights-reserved to whoever installed it — the terms were sitting in the `LICENSE` file it already shipped, saying nothing. The field now says `Apache-2.0`, which is what that file has always been and what all eleven sibling packages declare.
|
|
66
|
+
|
|
67
|
+
**Four packages now ship the licence they declare.** `@theokit/cli`, `@theokit/memory-honcho`, `@theokit/memory-mem0` and `@theokit/memory-supermemory` declared `Apache-2.0` and listed `LICENSE` in `files`, and no such file existed. npm omits a declared-but-absent path in silence, so every published tarball asserted the licence while carrying none of its terms — and §4(a) requires a copy to travel with the distribution. The file is there now, byte-identical to the one the other packages ship.
|
|
68
|
+
|
|
69
|
+
**Six packages complete the rest of their published metadata.** Each field is here for what its absence costs a consumer:
|
|
70
|
+
|
|
71
|
+
- `homepage` and `bugs` — the npm page renders both; without them someone who hits a defect has no route back to the project.
|
|
72
|
+
- `engines.node` — npm warns on an unsupported runtime only when the range is declared. `@theokit/sdk-pty` declared none, so a Node 18 install failed later and somewhere unrelated.
|
|
73
|
+
- `sideEffects` — a bundler keeps every module of a package that stays silent. Declared only after checking: a clean scan of each built ESM entry found zero top-level statements, the residual hits being closing tokens of declarations. `@theokit/sdk` keeps its path-array form, which is the honest shape for a package whose agent entry registers on import.
|
|
74
|
+
- `publishConfig.access` — a scoped package defaults to `restricted`. Three declared none and reached npm public only because the release flow supplied the flag; the manifest states it now instead of depending on how it is invoked.
|
|
75
|
+
- `@theokit/sdk-pty` also ships its `CHANGELOG.md`, which existed on disk and was absent from `files`.
|
|
76
|
+
|
|
77
|
+
The gate that should have caught any of this covered three packages out of twelve, by way of a hand-written list. It now derives the list from `packages/`, asserts the whole contract, and fails when the sweep discovers nothing rather than passing by having nothing to check.
|
|
78
|
+
|
|
79
|
+
- 926a2a6: Two adapters could not work against the real vendor APIs. Both bugs were invisible to their existing
|
|
80
|
+
tests, because those tests replaced the vendor SDK with a hand-written mock and asserted against the
|
|
81
|
+
mock's shape rather than the vendor's.
|
|
82
|
+
|
|
83
|
+
**The Honcho adapter could not talk to a Honcho server at all.** It built session identifiers as
|
|
84
|
+
`userId:session`, and the vendor SDK's schema rejects every character outside letters, digits,
|
|
85
|
+
underscore and hyphen — a colon is illegal. Every `write()` and every `recall()` raised a validation
|
|
86
|
+
error before a single HTTP request left the process. The separator is now `--`. No migration is
|
|
87
|
+
needed and none is possible: because the old identifier was rejected at the boundary, no session was
|
|
88
|
+
ever created under it.
|
|
89
|
+
|
|
90
|
+
**The Mem0 adapter misclassified every vendor error.** It read `status` and `statusCode` off thrown
|
|
91
|
+
errors; the vendor sets neither, carrying the code as `errorCode: "HTTP_429"` instead. So every real
|
|
92
|
+
failure fell through to an unknown classification — rate limits never received the rate-limit
|
|
93
|
+
exemption, and server errors never counted toward the circuit breaker, which is precisely the
|
|
94
|
+
protection those classifications exist to provide. The status is now derived from the vendor's own
|
|
95
|
+
field as well.
|
|
96
|
+
|
|
97
|
+
The reason neither surfaced earlier is worth stating: the existing test mocked the vendor and
|
|
98
|
+
fabricated a `status` property on thrown errors — a value the real library never produces. The test
|
|
99
|
+
asserted the adapter reads a field the mock invented.
|
|
100
|
+
|
|
101
|
+
All three cloud memory adapters now carry a recorded-wire contract test that pins the actual request
|
|
102
|
+
put on the wire and the vendor response shape it must survive, plus a live smoke that runs when a
|
|
103
|
+
vendor key is present and reports itself as skipped, with the reason, when one is not.
|
|
104
|
+
|
|
105
|
+
- e699569: **The repository moved to the official `usetheokit` organization.** Every `repository`, `bugs` and `homepage` field now points there, along with the README, `CONTRIBUTING.md`, `SECURITY.md` and the issue templates. Existing clones and any URL already published keep working — GitHub redirects a transferred repository permanently — so this is a correctness fix for the metadata npm renders, not a break.
|
|
106
|
+
|
|
107
|
+
**The Apache-2.0 text every package ships was replaced with the official one.** The copy distributed until now had paragraph 4(d) truncated: it read "except as required for describing the origin of the Work and reproducing the content of the NOTICE file", dropping "reasonable and customary use" from the licensed clause. §4(d) governs what a redistributor must do with attribution notices, and the omission narrowed it.
|
|
108
|
+
|
|
109
|
+
That matters more than a typo would. The manifests declare the SPDX identifier `Apache-2.0`, which is an assertion that the terms are _the_ Apache-2.0 terms — a licence scanner resolves the identifier and never reads the file. A consumer's compliance review, which does read the file, would find a body that no longer matches the identifier and has no name of its own. Every `LICENSE` in this repository is now byte-identical to the canonical text, with the appendix filled in.
|
|
110
|
+
|
|
111
|
+
Nothing else about the terms changed: the licence is the same licence it has always been meant to be, and no package changes what it grants.
|
|
112
|
+
|
|
113
|
+
- c7385d2: Test runs no longer claim every core on the host.
|
|
114
|
+
|
|
115
|
+
None of the package configs capped `maxWorkers`, so vitest's default applied: `os.availableParallelism()`,
|
|
116
|
+
one fork per core, each booting a full test environment. The repo's `test` script is
|
|
117
|
+
`turbo run test --filter='./packages/*'`, so that default is paid once per package _concurrently_ —
|
|
118
|
+
nproc forks times turbo's concurrency, on nproc cores. Measured on a 12-thread machine during an
|
|
119
|
+
unrelated investigation, two vitest pools alone were enough to reach load average 33.89 with the
|
|
120
|
+
desktop unusable; a full fan-out is several times that.
|
|
121
|
+
|
|
122
|
+
`@theokit/sdk` is the interesting case. B-104 recorded on 2026-08-19 that the `poolOptions.forks.*`
|
|
123
|
+
block was 100% dead in Vitest 4, deleted it, and noted that `fileParallelism: false` was forcing
|
|
124
|
+
`maxWorkers` to 1 unconditionally, so a fork-count knob could not act. B-059 then flipped
|
|
125
|
+
`fileParallelism` to `true` on 2026-08-20, which made the knob able to act again — and nothing
|
|
126
|
+
reintroduced one, so the package silently went back to the uncapped default. That comment has been
|
|
127
|
+
corrected along with the config; it claimed no knob existed, which is no longer true.
|
|
128
|
+
|
|
129
|
+
The cap leaves 4 cores free (`Math.max(2, cpus().length - 4)`), scaling with the runner rather than
|
|
130
|
+
hard-coding one machine's core count. It costs no wall-clock: measured in `theokit-ui`, the full
|
|
131
|
+
suite ran 73.96s at 4 workers against 74.36s at 12, so the parallelism above the cap was already
|
|
132
|
+
noise. Verified as resolved config rather than as file contents — `createVitest` reports
|
|
133
|
+
`maxWorkers: 8` on a 12-thread host, which is the formula, not the default.
|
|
134
|
+
|
|
135
|
+
This changes no published behaviour; it is test tooling only. Refs usetheokit/theokit-ui#51.
|
|
136
|
+
|
|
3
137
|
## 3.0.2
|
|
4
138
|
|
|
5
139
|
### Patch Changes
|
package/LICENSE
CHANGED
|
@@ -137,8 +137,8 @@
|
|
|
137
137
|
|
|
138
138
|
6. Trademarks. This License does not grant permission to use the trade
|
|
139
139
|
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
-
except as required for
|
|
141
|
-
reproducing the content of the NOTICE file.
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
142
|
|
|
143
143
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
144
|
agreed to in writing, Licensor provides the Work (and each
|
package/README.md
CHANGED
|
@@ -88,13 +88,32 @@ const b = await Agent.create({ plugins: [sharedPlugin] });
|
|
|
88
88
|
|
|
89
89
|
## Failure modes
|
|
90
90
|
|
|
91
|
-
|
|
|
91
|
+
| What was thrown | Maps to | Trips breaker? |
|
|
92
92
|
|---|---|---|
|
|
93
93
|
| 401 / 403 | `auth_failed` | no |
|
|
94
94
|
| 429 | `rate_limited` | **no** (EC-K) |
|
|
95
95
|
| 404 | `not_found` | no |
|
|
96
96
|
| 5xx | `network` | yes |
|
|
97
|
-
|
|
|
97
|
+
| No status, message contains "network" | `network` | yes |
|
|
98
|
+
| No status, any other message (e.g. `"fetch failed"`) | `unknown` | **no** |
|
|
99
|
+
|
|
100
|
+
The status is read from `.status`, `.statusCode`, `.response.status`, or an `errorCode` of the form
|
|
101
|
+
`HTTP_<nnn>` — the last is what `mem0ai` actually attaches. Transport failures are recognised only
|
|
102
|
+
by the literal substring `network` in the message, so a DNS or connection error worded differently
|
|
103
|
+
lands in `unknown` and leaves the breaker closed.
|
|
104
|
+
|
|
105
|
+
## API reference
|
|
106
|
+
|
|
107
|
+
Every symbol this package exports, with the exact specifier to import it from, is in the generated
|
|
108
|
+
capability map that ships inside `@theokit/sdk`:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
node_modules/@theokit/sdk/docs/harness-capability-map.md # symbol -> import specifier
|
|
112
|
+
node_modules/@theokit/sdk/docs/error-codes.md # every `code` an error can carry
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Both are generated from the built type declarations, so they describe the version you installed
|
|
116
|
+
rather than the version someone wrote a page about.
|
|
98
117
|
|
|
99
118
|
## License
|
|
100
119
|
|
package/dist/index.cjs
CHANGED
|
@@ -28,7 +28,7 @@ var CircuitBreaker = class {
|
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
-
/** Increment failure counter. Trips when threshold reached.
|
|
31
|
+
/** Increment failure counter. Trips when threshold reached. Call only for provider-down errors. */
|
|
32
32
|
recordFailure() {
|
|
33
33
|
this.#failures += 1;
|
|
34
34
|
if (this.#failures >= this.threshold) {
|
|
@@ -253,7 +253,9 @@ var Mem0Adapter = class {
|
|
|
253
253
|
}
|
|
254
254
|
return err;
|
|
255
255
|
}
|
|
256
|
-
const
|
|
256
|
+
const errorCode = err?.errorCode;
|
|
257
|
+
const statusFromErrorCode = typeof errorCode === "string" && /^HTTP_(\d{3})$/.test(errorCode) ? Number(errorCode.slice(5)) : void 0;
|
|
258
|
+
const status = err?.status ?? err?.statusCode ?? err?.response?.status ?? statusFromErrorCode;
|
|
257
259
|
const message = err?.message ?? String(err);
|
|
258
260
|
if (status === 401 || status === 403) {
|
|
259
261
|
return new sdk.MemoryAdapterError(`Mem0 auth failed (${op}): ${message}`, {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/circuit-breaker.ts","../src/translate.ts","../src/adapter.ts","../src/index.ts"],"names":["MemoryAdapterError","ADAPTER_ID","mkMemoryId","extractRawId","MemoryClient","Plugin"],"mappings":";;;;;;;;;;AAYA,IAAM,UAAA,GAAa,MAAA;AAOZ,IAAM,iBAAN,MAAqB;AAAA,EACjB,SAAA;AAAA,EACA,UAAA;AAAA,EACT,SAAA,GAAY,CAAA;AAAA,EACZ,UAAA,GAAa,CAAA;AAAA,EAEb,WAAA,CAAY,IAAA,GAA8B,EAAC,EAAG;AAC5C,IAAA,IAAA,CAAK,SAAA,GAAY,KAAK,SAAA,IAAa,CAAA;AACnC,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA,CAAK,UAAA,IAAc,CAAA,GAAI,EAAA,GAAK,GAAA;AAAA,EAChD;AAAA;AAAA,EAGA,aAAa,EAAA,EAAkB;AAC7B,IAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,UAAA,EAAY;AAChC,MAAA,MAAM,WAAA,GAAc,KAAK,IAAA,CAAA,CAAM,IAAA,CAAK,aAAa,IAAA,CAAK,GAAA,MAAS,GAAI,CAAA;AACnE,MAAA,MAAM,IAAIA,sBAAA;AAAA,QACR,CAAA,2BAAA,EAA8B,EAAE,CAAA,GAAA,EAAM,WAAW,CAAA,qBAAA,CAAA;AAAA,QACjD,EAAE,SAAA,EAAW,UAAA,EAAY,IAAA,EAAM,cAAA;AAAe,OAChD;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,aAAA,GAAsB;AACpB,IAAA,IAAA,CAAK,SAAA,IAAa,CAAA;AAClB,IAAA,IAAI,IAAA,CAAK,SAAA,IAAa,IAAA,CAAK,SAAA,EAAW;AACpC,MAAA,IAAA,CAAK,UAAA,GAAa,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,UAAA;AAAA,IACtC;AAAA,EACF;AAAA;AAAA,EAGA,aAAA,GAAsB;AACpB,IAAA,IAAA,CAAK,SAAA,GAAY,CAAA;AACjB,IAAA,IAAA,CAAK,UAAA,GAAa,CAAA;AAAA,EACpB;AAAA;AAAA,EAGA,KAAA,GAAkE;AAChE,IAAA,OAAO;AAAA,MACL,UAAU,IAAA,CAAK,SAAA;AAAA,MACf,MAAA,EAAQ,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,UAAA;AAAA,MAC1B,WAAW,IAAA,CAAK;AAAA,KAClB;AAAA,EACF;AACF,CAAA;;;AC3CO,SAAS,cAAc,GAAA,EAAiC;AAC7D,EAAA,MAAM,GAAA,GAAmB,EAAE,OAAA,EAAS,GAAA,CAAI,MAAA,EAAO;AAC/C,EAAA,IAAI,GAAA,CAAI,OAAA,KAAY,MAAA,EAAW,GAAA,CAAI,WAAW,GAAA,CAAI,OAAA;AAClD,EAAA,IAAI,GAAA,CAAI,SAAA,KAAc,MAAA,EAAW,GAAA,CAAI,SAAS,GAAA,CAAI,SAAA;AAClD,EAAA,IAAI,GAAA,CAAI,QAAA,KAAa,MAAA,EAAW,GAAA,CAAI,SAAS,GAAA,CAAI,QAAA;AACjD,EAAA,IAAI,GAAA,CAAI,IAAA,KAAS,MAAA,EAAW,GAAA,CAAI,aAAa,GAAA,CAAI,IAAA;AACjD,EAAA,IAAI,GAAA,CAAI,QAAA,KAAa,MAAA,EAAW,GAAA,CAAI,WAAW,GAAA,CAAI,QAAA;AACnD,EAAA,OAAO,GAAA;AACT;;;ACcA,IAAMC,WAAAA,GAAa,MAAA;AAEnB,IAAM,IAAA,GAAkC;AAAA,EACtC,OAAA,EAAS,IAAA;AAAA;AAAA,EACT,QAAA,EAAU,IAAA;AAAA,EACV,OAAA,EAAS,IAAA;AAAA,EACT,SAAA,EAAW,KAAA;AAAA,EACX,WAAA,EAAa,IAAA;AAAA,EACb,QAAA,EAAU;AACZ,CAAA;AAGO,IAAM,cAAN,MAA2C;AAAA,EACvC,EAAA,GAAKA,WAAAA;AAAA,EACL,YAAA,GAAe,IAAA;AAAA,EACf,KAAA;AAAA,EACA,QAAA;AAAA,EACT,OAAA;AAAA,EAEA,YAAY,IAAA,EAA0B;AACpC,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AACb,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,cAAA,CAAe,IAAA,CAAK,OAAO,CAAA;AAAA,EACjD;AAAA,EAEA,WAAA,GAAuB;AACrB,IAAA,OAAO,OAAO,KAAK,KAAA,CAAM,MAAA,KAAW,YAAY,IAAA,CAAK,KAAA,CAAM,OAAO,MAAA,GAAS,CAAA;AAAA,EAC7E;AAAA,EAEA,MAAM,UAAA,GAA4B;AAAA,EAElC;AAAA,EAEA,MAAM,KAAA,CAAM,OAAA,EAAuC,GAAA,EAAuC;AACxF,IAAA,IAAA,CAAK,QAAA,CAAS,aAAa,OAAO,CAAA;AAClC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,WAAA,CAAY,OAAO,CAAA;AACzC,IAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AACzB,MAAA,MAAM,IAAID,uBAAmB,uBAAA,EAAyB;AAAA,QACpD,SAAA,EAAWC,WAAAA;AAAA,QACX,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,cAAc,GAAG,CAAA;AAC9B,MAAA,MAAM,OAAO,MAAM,IAAA,CAAK,MAAK,CAAE,GAAA,CAAI,UAAU,IAAI,CAAA;AACjD,MAAA,IAAA,CAAK,SAAS,aAAA,EAAc;AAC5B,MAAA,MAAM,KAAA,GAAQ,KAAK,CAAC,CAAA;AACpB,MAAA,MAAM,QAAQ,KAAA,EAAO,EAAA,IAAM,CAAA,KAAA,EAAQ,IAAA,CAAK,KAAK,CAAA,CAAA;AAC7C,MAAA,OAAOC,cAAA,CAAWD,aAAY,KAAK,CAAA;AAAA,IACrC,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,GAAA,EAAK,OAAO,CAAA;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,MAAM,MAAA,CAAO,KAAA,EAAe,GAAA,EAAoB,IAAI,EAAA,EAA2B;AAC7E,IAAA,IAAI,CAAA,IAAK,CAAA,EAAG,OAAO,EAAC;AACpB,IAAA,IAAA,CAAK,QAAA,CAAS,aAAa,QAAQ,CAAA;AACnC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,cAAc,GAAG,CAAA;AAC9B,MAAA,MAAM,OAAO,MAAM,IAAA,CAAK,IAAA,EAAK,CAAE,OAAO,KAAA,EAAO;AAAA;AAAA,QAE3C,GAAI,IAAA,CAAK,OAAA,KAAY,KAAA,CAAA,GAAY,EAAE,OAAA,EAAS,EAAE,OAAA,EAAS,IAAA,CAAK,OAAA,EAAQ,EAAE,GAAI,EAAC;AAAA,QAC3E,IAAA,EAAM,CAAA;AAAA,QACN,MAAA,EAAQ;AAAA,OACT,CAAA;AACD,MAAA,IAAA,CAAK,SAAS,aAAA,EAAc;AAC5B,MAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,IAAI,IAAI,IAAA,GAAS,IAAA,CAAiC,WAAW,EAAC;AACzF,MAAA,OAAQ,IAAA,CAAwC,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,QAC1D,IAAIC,cAAA,CAAWD,WAAAA,EAAY,OAAO,CAAA,CAAE,EAAA,IAAM,EAAE,CAAC,CAAA;AAAA,QAC7C,SAAS,MAAA,CAAO,CAAA,CAAE,MAAA,IAAU,CAAA,CAAE,WAAW,EAAE,CAAA;AAAA,QAC3C,GAAI,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,GAAW,EAAE,KAAA,EAAO,CAAA,CAAE,KAAA,EAAgB,GAAI,EAAC;AAAA,QAClE,GAAI,CAAA,CAAE,SAAA,KAAc,KAAA,CAAA,GAAY,EAAE,SAAA,EAAW,MAAA,CAAO,CAAA,CAAE,SAAS,CAAA,EAAE,GAAI,EAAC;AAAA,QACtE,GAAI,EAAE,QAAA,KAAa,KAAA,CAAA,GAAY,EAAE,QAAA,EAAU,CAAA,CAAE,QAAA,EAAoC,GAAI;AAAC,OACxF,CAAE,CAAA;AAAA,IACJ,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,GAAA,EAAK,QAAQ,CAAA;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,EAAA,EAA6B;AACxC,IAAA,IAAA,CAAK,QAAA,CAAS,aAAa,QAAQ,CAAA;AACnC,IAAA,MAAM,KAAA,GAAQE,gBAAA,CAAa,EAAA,EAAIF,WAAU,CAAA;AACzC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,IAAA,EAAK,CAAE,MAAA,CAAO,KAAK,CAAA;AAC9B,MAAA,IAAA,CAAK,SAAS,aAAA,EAAc;AAAA,IAC9B,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,GAAA,EAAK,QAAQ,CAAA;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,EAAA,EAAyC;AACrD,IAAA,IAAA,CAAK,QAAA,CAAS,aAAa,SAAS,CAAA;AACpC,IAAA,MAAM,KAAA,GAAQE,gBAAA,CAAa,EAAA,EAAIF,WAAU,CAAA;AACzC,IAAA,IAAI;AACF,MAAA,MAAM,OAAO,MAAM,IAAA,CAAK,IAAA,EAAK,CAAE,QAAQ,KAAK,CAAA;AAC5C,MAAA,IAAA,CAAK,SAAS,aAAA,EAAc;AAC5B,MAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,KAAM;AACxB,QAAA,MAAM,IAAK,CAAA,CAAyC,SAAA;AACpD,QAAA,MAAM,SAAA,GACJ,CAAA,YAAa,IAAA,GACT,CAAA,CAAE,WAAA,EAAY,GACd,OAAO,CAAA,KAAM,QAAA,GACX,CAAA,GAAA,iBACA,IAAI,IAAA,IAAO,WAAA,EAAY;AAC/B,QAAA,OAAO;AAAA,UACL,EAAA,EAAIC,cAAA,CAAWD,WAAAA,EAAY,CAAA,CAAE,YAAY,KAAK,CAAA;AAAA,UAC9C,SAAS,MAAA,CAAO,CAAA,CAAE,SAAA,IAAa,CAAA,CAAE,aAAa,EAAE,CAAA;AAAA,UAChD,SAAS,CAAA,GAAI,CAAA;AAAA,UACb;AAAA,SACF;AAAA,MACF,CAAC,CAAA;AAAA,IACH,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,GAAA,EAAK,SAAS,CAAA;AAAA,IAC3C;AAAA,EACF;AAAA,EAEA,cAAA,GAAqC;AACnC,IAAA,OAAO;AAAA,MACL;AAAA,QACE,IAAA,EAAM,cAAA;AAAA,QACN,WAAA,EACE,kFAAA;AAAA,QACF,UAAA,EAAY;AAAA,UACV,IAAA,EAAM,QAAA;AAAA,UACN,UAAA,EAAY;AAAA,YACV,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,uBAAA;AAAwB,WAClE;AAAA,UACA,QAAA,EAAU,CAAC,SAAS;AAAA;AACtB,OACF;AAAA,MACA;AAAA,QACE,IAAA,EAAM,eAAA;AAAA,QACN,WAAA,EAAa,8EAAA;AAAA,QACb,UAAA,EAAY;AAAA,UACV,IAAA,EAAM,QAAA;AAAA,UACN,UAAA,EAAY;AAAA,YACV,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,YACxB,GAAG,EAAE,IAAA,EAAM,WAAW,OAAA,EAAS,CAAA,EAAG,SAAS,EAAA;AAAG,WAChD;AAAA,UACA,QAAA,EAAU,CAAC,OAAO;AAAA;AACpB,OACF;AAAA,MACA;AAAA,QACE,IAAA,EAAM,gBAAA;AAAA,QACN,WAAA,EACE,iKAAA;AAAA,QAEF,UAAA,EAAY;AAAA,UACV,IAAA,EAAM,QAAA;AAAA,UACN,YAAY,EAAE,QAAA,EAAU,EAAE,IAAA,EAAM,UAAS,EAAE;AAAA,UAC3C,QAAA,EAAU,CAAC,UAAU;AAAA;AACvB;AACF,KACF;AAAA,EACF;AAAA,EAEA,MAAM,cAAA,CACJ,IAAA,EACA,IAAA,EACA,GAAA,EACiB;AACjB,IAAA,IAAI,SAAS,cAAA,EAAgB;AAC3B,MAAA,MAAM,EAAA,GAAK,MAAM,IAAA,CAAK,KAAA,CAAM,OAAO,IAAA,CAAK,OAAA,IAAW,EAAE,CAAA,EAAG,GAAG,CAAA;AAC3D,MAAA,OAAO,KAAK,SAAA,CAAU,EAAE,EAAA,EAAI,IAAA,EAAM,IAAI,CAAA;AAAA,IACxC;AACA,IAAA,IAAI,SAAS,eAAA,EAAiB;AAC5B,MAAA,MAAM,IAAI,OAAO,IAAA,CAAK,CAAA,KAAM,QAAA,GAAW,KAAK,CAAA,GAAI,EAAA;AAChD,MAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,KAAK,KAAA,IAAS,EAAE,CAAA,EAAG,GAAA,EAAK,CAAC,CAAA;AAChE,MAAA,OAAO,KAAK,SAAA,CAAU,EAAE,EAAA,EAAI,IAAA,EAAM,OAAO,CAAA;AAAA,IAC3C;AACA,IAAA,IAAI,SAAS,gBAAA,EAAkB;AAC7B,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,QAAA,IAAY,EAAE,CAAA;AACxC,MAAA,MAAM,OAAA,GAAU,KAAA,CAAM,UAAA,CAAW,CAAA,EAAGA,WAAU,GAAG,CAAA,GAC5C,KAAA,GACDC,cAAA,CAAWD,WAAAA,EAAY,KAAK,CAAA;AAChC,MAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,OAAA,CAAQ,OAAO,CAAA;AAC5C,MAAA,OAAO,KAAK,SAAA,CAAU,EAAE,EAAA,EAAI,IAAA,EAAM,WAAW,CAAA;AAAA,IAC/C;AACA,IAAA,MAAM,IAAID,sBAAAA,CAAmB,CAAA,mBAAA,EAAsB,IAAI,CAAA,CAAA,EAAI;AAAA,MACzD,SAAA,EAAWC,WAAAA;AAAA,MACX,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,QAAA,GAA0B;AAC9B,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AAAA,EACjB;AAAA;AAAA,EAGA,aAAA,GAA0E;AACxE,IAAA,OAAO,IAAA,CAAK,SAAS,KAAA,EAAM;AAAA,EAC7B;AAAA;AAAA,EAIA,YACE,OAAA,EACwD;AACxD,IAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAC/B,MAAA,OAAO,OAAA,CAAQ,IAAA,EAAK,CAAE,MAAA,KAAW,CAAA,GAAI,EAAC,GAAI,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAS,CAAA;AAAA,IACtE;AAGA,IAAA,OAAO,OAAA,CACJ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,IAAA,EAAK,CAAE,MAAA,GAAS,CAAC,CAAA,CACzC,GAAA;AAAA,MAAI,CAAC,MACJ,CAAA,CAAE,IAAA,KAAS,WACP,EAAE,IAAA,EAAM,QAAiB,OAAA,EAAS,CAAA,SAAA,EAAY,EAAE,OAAO,CAAA,CAAA,KACvD,EAAE,IAAA,EAAM,EAAE,IAAA,EAAM,OAAA,EAAS,EAAE,OAAA;AAAQ,KACzC;AAAA,EACJ;AAAA,EAEA,IAAA,GAAqB;AACnB,IAAA,IAAI,IAAA,CAAK,YAAY,MAAA,EAAW;AAC9B,MAAA,IAAA,CAAK,OAAA,GAAU,IAAIG,6BAAA,CAAa;AAAA,QAC9B,MAAA,EAAQ,KAAK,KAAA,CAAM,MAAA;AAAA,QACnB,GAAI,IAAA,CAAK,KAAA,CAAM,IAAA,KAAS,MAAA,GAAY,EAAE,IAAA,EAAM,IAAA,CAAK,KAAA,CAAM,IAAA,EAAK,GAAI,EAAC;AAAA,QACjE,GAAI,IAAA,CAAK,KAAA,CAAM,cAAA,KAAmB,MAAA,GAC9B,EAAE,cAAA,EAAgB,IAAA,CAAK,KAAA,CAAM,cAAA,EAAe,GAC5C,EAAC;AAAA,QACL,GAAI,IAAA,CAAK,KAAA,CAAM,SAAA,KAAc,MAAA,GAAY,EAAE,SAAA,EAAW,IAAA,CAAK,KAAA,CAAM,SAAA,EAAU,GAAI;AAAC,OACjF,CAAA;AAAA,IACH;AACA,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA;AAAA,EAGA,eAAA,CAAgB,KAAc,EAAA,EAAgC;AAC5D,IAAA,IAAI,eAAeJ,sBAAAA,EAAoB;AACrC,MAAA,IAAI,GAAA,CAAI,SAAS,cAAA,EAAgB,CAEjC,MAAA,IACE,IAAI,IAAA,KAAS,aAAA,IACb,IAAI,IAAA,KAAS,WAAA,IACb,GAAA,CAAI,IAAA,KAAS,eAAA,EACb,CAEF,MAAO;AACL,QAAA,IAAA,CAAK,SAAS,aAAA,EAAc;AAAA,MAC9B;AACA,MAAA,OAAO,GAAA;AAAA,IACT;AACA,IAAA,MAAM,SACH,GAAA,EAAkF,MAAA,IAClF,GAAA,EAAiC,UAAA,IACjC,KAA4C,QAAA,EAAU,MAAA;AACzD,IAAA,MAAM,OAAA,GAAW,GAAA,EAAe,OAAA,IAAW,MAAA,CAAO,GAAG,CAAA;AACrD,IAAA,IAAI,MAAA,KAAW,GAAA,IAAO,MAAA,KAAW,GAAA,EAAK;AACpC,MAAA,OAAO,IAAIA,sBAAAA,CAAmB,CAAA,kBAAA,EAAqB,EAAE,CAAA,GAAA,EAAM,OAAO,CAAA,CAAA,EAAI;AAAA,QACpE,SAAA,EAAWC,WAAAA;AAAA,QACX,IAAA,EAAM,aAAA;AAAA,QACN,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,IACH;AACA,IAAA,IAAI,WAAW,GAAA,EAAK;AAElB,MAAA,OAAO,IAAID,sBAAAA,CAAmB,CAAA,mBAAA,EAAsB,EAAE,CAAA,GAAA,EAAM,OAAO,CAAA,CAAA,EAAI;AAAA,QACrE,SAAA,EAAWC,WAAAA;AAAA,QACX,IAAA,EAAM,cAAA;AAAA,QACN,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,IACH;AACA,IAAA,IAAI,WAAW,GAAA,EAAK;AAClB,MAAA,OAAO,IAAID,sBAAAA,CAAmB,CAAA,gBAAA,EAAmB,EAAE,CAAA,GAAA,EAAM,OAAO,CAAA,CAAA,EAAI;AAAA,QAClE,SAAA,EAAWC,WAAAA;AAAA,QACX,IAAA,EAAM,WAAA;AAAA,QACN,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,IACH;AACA,IAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,IAAU,GAAA,EAAK;AAC/C,MAAA,IAAA,CAAK,SAAS,aAAA,EAAc;AAC5B,MAAA,OAAO,IAAID,sBAAAA,CAAmB,CAAA,mBAAA,EAAsB,EAAE,CAAA,GAAA,EAAM,OAAO,CAAA,CAAA,EAAI;AAAA,QACrE,SAAA,EAAWC,WAAAA;AAAA,QACX,IAAA,EAAM,SAAA;AAAA,QACN,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,IACH;AACA,IAAA,IAAI,WAAW,MAAA,IAAa,OAAA,CAAQ,aAAY,CAAE,QAAA,CAAS,SAAS,CAAA,EAAG;AACrE,MAAA,IAAA,CAAK,SAAS,aAAA,EAAc;AAC5B,MAAA,OAAO,IAAID,sBAAAA,CAAmB,CAAA,oBAAA,EAAuB,EAAE,CAAA,GAAA,EAAM,OAAO,CAAA,CAAA,EAAI;AAAA,QACtE,SAAA,EAAWC,WAAAA;AAAA,QACX,IAAA,EAAM,SAAA;AAAA,QACN,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,IACH;AACA,IAAA,OAAO,IAAID,sBAAAA,CAAmB,CAAA,YAAA,EAAe,EAAE,CAAA,GAAA,EAAM,OAAO,CAAA,CAAA,EAAI;AAAA,MAC9D,SAAA,EAAWC,WAAAA;AAAA,MACX,IAAA,EAAM,SAAA;AAAA,MACN,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,EACH;AACF,CAAA;;;ACrUO,SAAS,WAAW,OAAA,EAAqC;AAC9D,EAAA,OAAOI,WAAO,MAAA,CAAO;AAAA,IACnB,IAAA,EAAM,sBAAA;AAAA,IACN,OAAA,EAAS,OAAA;AAAA,IACT,IAAA,EAAM,QAAA;AAAA,IACN,cAAA,EAAgB,MAAM,IAAI,WAAA,CAAY,OAAO;AAAA,GAC9C,CAAA;AACH","file":"index.cjs","sourcesContent":["/**\n * In-memory circuit breaker for Mem0Adapter (T5.1, EC-K).\n *\n * Trips after `threshold` consecutive 5xx-class failures. 429 / 401 /\n * 404 / invalid_input do NOT count toward the threshold — rate limits\n * are a caller-pace signal, not a provider-down signal (EC-K).\n *\n * @internal\n */\n\nimport { MemoryAdapterError } from \"@theokit/sdk\";\n\nconst ADAPTER_ID = \"mem0\";\n\nexport interface CircuitBreakerOptions {\n threshold?: number;\n cooldownMs?: number;\n}\n\nexport class CircuitBreaker {\n readonly threshold: number;\n readonly cooldownMs: number;\n #failures = 0;\n #openUntil = 0;\n\n constructor(opts: CircuitBreakerOptions = {}) {\n this.threshold = opts.threshold ?? 5;\n this.cooldownMs = opts.cooldownMs ?? 2 * 60 * 1000;\n }\n\n /** Throws `MemoryAdapterError(code: \"rate_limited\")` if breaker is open. */\n ensureClosed(op: string): void {\n if (Date.now() < this.#openUntil) {\n const secondsLeft = Math.ceil((this.#openUntil - Date.now()) / 1000);\n throw new MemoryAdapterError(\n `Mem0 circuit breaker open (${op}): ${secondsLeft}s cooldown remaining.`,\n { adapterId: ADAPTER_ID, code: \"rate_limited\" },\n );\n }\n }\n\n /** Increment failure counter. Trips when threshold reached. Only call for 5xx-class errors. */\n recordFailure(): void {\n this.#failures += 1;\n if (this.#failures >= this.threshold) {\n this.#openUntil = Date.now() + this.cooldownMs;\n }\n }\n\n /** Reset on first success — closes the breaker (EC-K). */\n recordSuccess(): void {\n this.#failures = 0;\n this.#openUntil = 0;\n }\n\n /** Test-only inspector. @internal */\n state(): { failures: number; isOpen: boolean; openUntil: number } {\n return {\n failures: this.#failures,\n isOpen: Date.now() < this.#openUntil,\n openUntil: this.#openUntil,\n };\n }\n}\n","/**\n * `MemoryContext` → Mem0 add/search options translation (T5.1).\n *\n * Mem0 keeps `user_id`, `agent_id`, `app_id`, `run_id` orthogonal —\n * we map each `MemoryContext` field onto its native primitive.\n *\n * @internal\n */\n\nimport type { MemoryContext } from \"@theokit/sdk\";\n\ninterface Mem0Options {\n user_id?: string;\n agent_id?: string;\n run_id?: string;\n app_id?: string;\n categories?: string[];\n metadata?: Record<string, unknown>;\n}\n\nexport function toMem0Options(ctx: MemoryContext): Mem0Options {\n const out: Mem0Options = { user_id: ctx.userId };\n if (ctx.agentId !== undefined) out.agent_id = ctx.agentId;\n if (ctx.sessionId !== undefined) out.run_id = ctx.sessionId;\n if (ctx.tenantId !== undefined) out.app_id = ctx.tenantId;\n if (ctx.tags !== undefined) out.categories = ctx.tags;\n if (ctx.metadata !== undefined) out.metadata = ctx.metadata;\n return out;\n}\n","/**\n * Mem0Adapter — `@theokit/memory-mem0` core (T5.1, ADR D141 / D148).\n *\n * Wraps `mem0ai` `MemoryClient` (cloud-only per D148). Implements\n * `MemoryAdapter` with the unique `history(id)` capability — the only\n * adapter today that exposes per-memory versioning.\n *\n * Includes a circuit breaker (EC-K: 5xx counts; 429 does NOT trip).\n *\n * @public\n */\n\nimport {\n extractRawId,\n type MemoryAdapter,\n type MemoryAdapterCapabilities,\n MemoryAdapterError,\n type MemoryContext,\n type MemoryFact,\n type MemoryId,\n type MemoryRevision,\n type MemoryToolSchema,\n type MemoryTurnMessage,\n mkMemoryId,\n} from \"@theokit/sdk\";\nimport MemoryClient from \"mem0ai\";\n\nimport { CircuitBreaker, type CircuitBreakerOptions } from \"./circuit-breaker.js\";\nimport { toMem0Options } from \"./translate.js\";\n\n/** Configuration accepted by the `mem0Memory(...)` factory. @public */\nexport interface Mem0AdapterOptions {\n /** Mem0 API key. Required. */\n apiKey: string;\n /** Override host (default mem0 cloud). */\n host?: string;\n organizationId?: string;\n projectId?: string;\n /** Circuit breaker tuning (EC-K). */\n breaker?: CircuitBreakerOptions;\n}\n\nconst ADAPTER_ID = \"mem0\";\n\nconst CAPS: MemoryAdapterCapabilities = {\n history: true, // ← unique to Mem0\n sessions: true,\n tenancy: true,\n reasoning: false,\n toolSchemas: true,\n prefetch: false,\n};\n\n/** @internal */\nexport class Mem0Adapter implements MemoryAdapter {\n readonly id = ADAPTER_ID;\n readonly capabilities = CAPS;\n readonly #opts: Mem0AdapterOptions;\n readonly #breaker: CircuitBreaker;\n #client?: MemoryClient;\n\n constructor(opts: Mem0AdapterOptions) {\n this.#opts = opts;\n this.#breaker = new CircuitBreaker(opts.breaker);\n }\n\n isAvailable(): boolean {\n return typeof this.#opts.apiKey === \"string\" && this.#opts.apiKey.length > 0;\n }\n\n async initialize(): Promise<void> {\n // Lazy: client constructed on first call.\n }\n\n async write(content: string | MemoryTurnMessage[], ctx: MemoryContext): Promise<MemoryId> {\n this.#breaker.ensureClosed(\"write\");\n const messages = this.#toMessages(content);\n if (messages.length === 0) {\n throw new MemoryAdapterError(\"write: empty messages\", {\n adapterId: ADAPTER_ID,\n code: \"invalid_input\",\n });\n }\n try {\n const opts = toMem0Options(ctx);\n const resp = await this.#sdk().add(messages, opts);\n this.#breaker.recordSuccess();\n const first = resp[0];\n const rawId = first?.id ?? `mem0-${Date.now()}`;\n return mkMemoryId(ADAPTER_ID, rawId);\n } catch (err) {\n throw this.#translateError(err, \"write\");\n }\n }\n\n async recall(query: string, ctx: MemoryContext, k = 10): Promise<MemoryFact[]> {\n if (k <= 0) return [];\n this.#breaker.ensureClosed(\"recall\");\n try {\n const opts = toMem0Options(ctx);\n const resp = await this.#sdk().search(query, {\n // Read filter: cross-session recall keyed by user_id (Hermes pattern).\n ...(opts.user_id !== undefined ? { filters: { user_id: opts.user_id } } : {}),\n topK: k,\n rerank: true,\n });\n this.#breaker.recordSuccess();\n const list = Array.isArray(resp) ? resp : ((resp as { results?: unknown[] }).results ?? []);\n return (list as Array<Record<string, unknown>>).map((r) => ({\n id: mkMemoryId(ADAPTER_ID, String(r.id ?? \"\")),\n content: String(r.memory ?? r.content ?? \"\"),\n ...(typeof r.score === \"number\" ? { score: r.score as number } : {}),\n ...(r.createdAt !== undefined ? { createdAt: String(r.createdAt) } : {}),\n ...(r.metadata !== undefined ? { metadata: r.metadata as Record<string, unknown> } : {}),\n }));\n } catch (err) {\n throw this.#translateError(err, \"recall\");\n }\n }\n\n async delete(id: MemoryId): Promise<void> {\n this.#breaker.ensureClosed(\"delete\");\n const rawId = extractRawId(id, ADAPTER_ID);\n try {\n await this.#sdk().delete(rawId);\n this.#breaker.recordSuccess();\n } catch (err) {\n throw this.#translateError(err, \"delete\");\n }\n }\n\n async history(id: MemoryId): Promise<MemoryRevision[]> {\n this.#breaker.ensureClosed(\"history\");\n const rawId = extractRawId(id, ADAPTER_ID);\n try {\n const rows = await this.#sdk().history(rawId);\n this.#breaker.recordSuccess();\n return rows.map((r, i) => {\n const u = (r as unknown as { updatedAt?: unknown }).updatedAt;\n const changedAt =\n u instanceof Date\n ? u.toISOString()\n : typeof u === \"string\"\n ? u\n : new Date().toISOString();\n return {\n id: mkMemoryId(ADAPTER_ID, r.memoryId ?? rawId),\n content: String(r.newMemory ?? r.oldMemory ?? \"\"),\n version: i + 1,\n changedAt,\n };\n });\n } catch (err) {\n throw this.#translateError(err, \"history\");\n }\n }\n\n getToolSchemas(): MemoryToolSchema[] {\n return [\n {\n name: \"memory_write\",\n description:\n \"Persist a turn to Mem0 long-term memory. Server-side extraction populates facts.\",\n parameters: {\n type: \"object\",\n properties: {\n content: { type: \"string\", description: \"Turn text to persist.\" },\n },\n required: [\"content\"],\n },\n },\n {\n name: \"memory_recall\",\n description: \"Retrieve up to k semantically relevant facts from Mem0 (server-side rerank).\",\n parameters: {\n type: \"object\",\n properties: {\n query: { type: \"string\" },\n k: { type: \"integer\", minimum: 1, maximum: 50 },\n },\n required: [\"query\"],\n },\n },\n {\n name: \"memory_history\",\n description:\n \"Retrieve the version history of a specific memory by id. Mem0-unique capability — \" +\n \"shows how a fact has evolved over time (e.g., user changed preferences).\",\n parameters: {\n type: \"object\",\n properties: { memoryId: { type: \"string\" } },\n required: [\"memoryId\"],\n },\n },\n ];\n }\n\n async handleToolCall(\n name: string,\n args: Record<string, unknown>,\n ctx: MemoryContext,\n ): Promise<string> {\n if (name === \"memory_write\") {\n const id = await this.write(String(args.content ?? \"\"), ctx);\n return JSON.stringify({ ok: true, id });\n }\n if (name === \"memory_recall\") {\n const k = typeof args.k === \"number\" ? args.k : 10;\n const facts = await this.recall(String(args.query ?? \"\"), ctx, k);\n return JSON.stringify({ ok: true, facts });\n }\n if (name === \"memory_history\") {\n const rawId = String(args.memoryId ?? \"\");\n const wrapped = rawId.startsWith(`${ADAPTER_ID}:`)\n ? (rawId as MemoryId)\n : mkMemoryId(ADAPTER_ID, rawId);\n const revisions = await this.history(wrapped);\n return JSON.stringify({ ok: true, revisions });\n }\n throw new MemoryAdapterError(`Unknown tool name: ${name}`, {\n adapterId: ADAPTER_ID,\n code: \"invalid_input\",\n });\n }\n\n async shutdown(): Promise<void> {\n this.#client = undefined;\n }\n\n /** Test-only: inspect breaker state. @internal */\n _breakerState(): { failures: number; isOpen: boolean; openUntil: number } {\n return this.#breaker.state();\n }\n\n // ── helpers ────────────────────────────────────────────────────────\n\n #toMessages(\n content: string | MemoryTurnMessage[],\n ): Array<{ role: \"user\" | \"assistant\"; content: string }> {\n if (typeof content === \"string\") {\n return content.trim().length === 0 ? [] : [{ role: \"user\", content }];\n }\n // Mem0 SDK accepts only user/assistant roles. System turns are merged\n // into user content with a \"[system] \" prefix.\n return content\n .filter((m) => m.content.trim().length > 0)\n .map((m) =>\n m.role === \"system\"\n ? { role: \"user\" as const, content: `[system] ${m.content}` }\n : { role: m.role, content: m.content },\n );\n }\n\n #sdk(): MemoryClient {\n if (this.#client === undefined) {\n this.#client = new MemoryClient({\n apiKey: this.#opts.apiKey,\n ...(this.#opts.host !== undefined ? { host: this.#opts.host } : {}),\n ...(this.#opts.organizationId !== undefined\n ? { organizationId: this.#opts.organizationId }\n : {}),\n ...(this.#opts.projectId !== undefined ? { projectId: this.#opts.projectId } : {}),\n });\n }\n return this.#client;\n }\n\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: error-translation ladder maps provider error classes to typed codes + breaker policy (EC-K: 429 does NOT trip); inlining keeps the policy decisions in one place.\n #translateError(err: unknown, op: string): MemoryAdapterError {\n if (err instanceof MemoryAdapterError) {\n if (err.code === \"rate_limited\") {\n // EC-K: do NOT trip breaker on rate limit.\n } else if (\n err.code === \"auth_failed\" ||\n err.code === \"not_found\" ||\n err.code === \"invalid_input\"\n ) {\n // No trip — these are caller-side or stateful conditions.\n } else {\n this.#breaker.recordFailure();\n }\n return err;\n }\n const status =\n (err as { status?: number; statusCode?: number; response?: { status?: number } })?.status ??\n (err as { statusCode?: number })?.statusCode ??\n (err as { response?: { status?: number } })?.response?.status;\n const message = (err as Error)?.message ?? String(err);\n if (status === 401 || status === 403) {\n return new MemoryAdapterError(`Mem0 auth failed (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"auth_failed\",\n cause: err,\n });\n }\n if (status === 429) {\n // EC-K: rate-limited; do NOT increment breaker.\n return new MemoryAdapterError(`Mem0 rate limited (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"rate_limited\",\n cause: err,\n });\n }\n if (status === 404) {\n return new MemoryAdapterError(`Mem0 not found (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"not_found\",\n cause: err,\n });\n }\n if (typeof status === \"number\" && status >= 500) {\n this.#breaker.recordFailure();\n return new MemoryAdapterError(`Mem0 server error (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"network\",\n cause: err,\n });\n }\n if (status === undefined && message.toLowerCase().includes(\"network\")) {\n this.#breaker.recordFailure();\n return new MemoryAdapterError(`Mem0 network error (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"network\",\n cause: err,\n });\n }\n return new MemoryAdapterError(`Mem0 error (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"unknown\",\n cause: err,\n });\n }\n}\n","import { Plugin } from \"@theokit/sdk\";\n\nimport { Mem0Adapter, type Mem0AdapterOptions } from \"./adapter.js\";\n\nexport type { Mem0AdapterOptions } from \"./adapter.js\";\n\n/** Build a `Plugin { kind: \"memory\" }`. @public */\nexport function mem0Memory(options: Mem0AdapterOptions): Plugin {\n return Plugin.create({\n name: \"@theokit/memory-mem0\",\n version: \"0.1.0\",\n kind: \"memory\",\n createProvider: () => new Mem0Adapter(options),\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/circuit-breaker.ts","../src/translate.ts","../src/adapter.ts","../src/index.ts"],"names":["MemoryAdapterError","ADAPTER_ID","mkMemoryId","extractRawId","MemoryClient","Plugin"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * In-memory circuit breaker for Mem0Adapter (T5.1, EC-K).\n *\n * Trips after `threshold` consecutive failures that `Mem0Adapter#translateError`\n * decides are provider-down signals: an HTTP 5xx, or a status-less error whose\n * message contains \"network\". 429 / 401 / 403 / 404 / invalid_input do NOT count\n * toward the threshold — rate limits are a caller-pace signal, not a\n * provider-down signal (EC-K).\n *\n * @internal\n */\n\nimport { MemoryAdapterError } from \"@theokit/sdk\";\n\nconst ADAPTER_ID = \"mem0\";\n\n/**\n * Tuning for the Mem0 adapter's circuit breaker, passed as `mem0Memory({ breaker })`.\n *\n * @public\n */\nexport interface CircuitBreakerOptions {\n /**\n * Failures required to open the breaker. Default `5`.\n *\n * TWO kinds of failure count, not one: an HTTP 5xx, and a status-less error whose message\n * contains the substring `network` (case-insensitive) — that substring match is the only way a\n * transport failure is recognised, so a DNS/connection error surfacing as `\"fetch failed\"` maps\n * to `code: \"unknown\"` and does NOT count. 429 / 401 / 403 / 404 / `invalid_input` never count.\n *\n * Size it for transport flakiness as well as for Mem0 outages: with `threshold: 5`, five\n * consecutive `network`-shaped errors open the breaker exactly as five 500s would, and the\n * resulting error says `rate_limited`, which is not what caused it.\n *\n * A single success resets the counter to zero, so this is effectively \"consecutive counted\n * failures\" — 4 failures followed by a success followed by 4 more never trips a default breaker.\n */\n threshold?: number;\n /**\n * How long the breaker stays open, in milliseconds. Default `120000` (2 minutes).\n *\n * While open, every call fails immediately with `MemoryAdapterError(code: \"rate_limited\")`\n * without touching the network. There is no half-open probe: the breaker simply closes when the\n * cooldown elapses and the next call goes through for real.\n */\n cooldownMs?: number;\n}\n\nexport class CircuitBreaker {\n readonly threshold: number;\n readonly cooldownMs: number;\n #failures = 0;\n #openUntil = 0;\n\n constructor(opts: CircuitBreakerOptions = {}) {\n this.threshold = opts.threshold ?? 5;\n this.cooldownMs = opts.cooldownMs ?? 2 * 60 * 1000;\n }\n\n /** Throws `MemoryAdapterError(code: \"rate_limited\")` if breaker is open. */\n ensureClosed(op: string): void {\n if (Date.now() < this.#openUntil) {\n const secondsLeft = Math.ceil((this.#openUntil - Date.now()) / 1000);\n throw new MemoryAdapterError(\n `Mem0 circuit breaker open (${op}): ${secondsLeft}s cooldown remaining.`,\n { adapterId: ADAPTER_ID, code: \"rate_limited\" },\n );\n }\n }\n\n /** Increment failure counter. Trips when threshold reached. Call only for provider-down errors. */\n recordFailure(): void {\n this.#failures += 1;\n if (this.#failures >= this.threshold) {\n this.#openUntil = Date.now() + this.cooldownMs;\n }\n }\n\n /** Reset on first success — closes the breaker (EC-K). */\n recordSuccess(): void {\n this.#failures = 0;\n this.#openUntil = 0;\n }\n\n /** Test-only inspector. @internal */\n state(): { failures: number; isOpen: boolean; openUntil: number } {\n return {\n failures: this.#failures,\n isOpen: Date.now() < this.#openUntil,\n openUntil: this.#openUntil,\n };\n }\n}\n","/**\n * `MemoryContext` → Mem0 add/search options translation (T5.1).\n *\n * Mem0 keeps `user_id`, `agent_id`, `app_id`, `run_id` orthogonal —\n * we map each `MemoryContext` field onto its native primitive.\n *\n * @internal\n */\n\nimport type { MemoryContext } from \"@theokit/sdk\";\n\ninterface Mem0Options {\n user_id?: string;\n agent_id?: string;\n run_id?: string;\n app_id?: string;\n categories?: string[];\n metadata?: Record<string, unknown>;\n}\n\nexport function toMem0Options(ctx: MemoryContext): Mem0Options {\n const out: Mem0Options = { user_id: ctx.userId };\n if (ctx.agentId !== undefined) out.agent_id = ctx.agentId;\n if (ctx.sessionId !== undefined) out.run_id = ctx.sessionId;\n if (ctx.tenantId !== undefined) out.app_id = ctx.tenantId;\n if (ctx.tags !== undefined) out.categories = ctx.tags;\n if (ctx.metadata !== undefined) out.metadata = ctx.metadata;\n return out;\n}\n","/**\n * Mem0Adapter — `@theokit/memory-mem0` core (T5.1, ADR D141 / D148).\n *\n * Wraps `mem0ai` `MemoryClient` (cloud-only per D148). Implements\n * `MemoryAdapter` with the unique `history(id)` capability — the only\n * adapter today that exposes per-memory versioning.\n *\n * Includes a circuit breaker (EC-K: 5xx counts; 429 does NOT trip).\n *\n * @public\n */\n\nimport {\n extractRawId,\n type MemoryAdapter,\n type MemoryAdapterCapabilities,\n MemoryAdapterError,\n type MemoryContext,\n type MemoryFact,\n type MemoryId,\n type MemoryRevision,\n type MemoryToolSchema,\n type MemoryTurnMessage,\n mkMemoryId,\n} from \"@theokit/sdk\";\nimport MemoryClient from \"mem0ai\";\n\nimport { CircuitBreaker, type CircuitBreakerOptions } from \"./circuit-breaker.js\";\nimport { toMem0Options } from \"./translate.js\";\n\n/**\n * Configuration accepted by the `mem0Memory(...)` factory.\n *\n * @public\n */\nexport interface Mem0AdapterOptions {\n /**\n * Mem0 API key. Genuinely required — `mem0ai` reads no `MEM0_API_KEY` environment variable, so\n * there is no fallback anywhere in the chain.\n *\n * The client is built lazily on the first `write` / `recall`, so a wrong key does not fail\n * `Agent.create`; it surfaces as `MemoryAdapterError(code: \"auth_failed\")` on the first call.\n */\n apiKey: string;\n /** Alternate Mem0 API host. Omit for Mem0 cloud, which is the vendor default. */\n host?: string;\n /** Mem0 organization to scope writes to. Forwarded only when set. */\n organizationId?: string;\n /** Mem0 project to scope writes to. Forwarded only when set. */\n projectId?: string;\n /**\n * Circuit-breaker tuning. Defaults: trip after 5 failures, 2-minute cooldown.\n *\n * The breaker is PER ADAPTER INSTANCE — one `mem0Memory(...)` call, one breaker. Two agents\n * built from two separate factory calls do not share it, so one agent tripping does not\n * protect the other.\n */\n breaker?: CircuitBreakerOptions;\n}\n\nconst ADAPTER_ID = \"mem0\";\n\nconst CAPS: MemoryAdapterCapabilities = {\n history: true, // ← unique to Mem0\n sessions: true,\n tenancy: true,\n reasoning: false,\n toolSchemas: true,\n prefetch: false,\n};\n\n/** @internal */\nexport class Mem0Adapter implements MemoryAdapter {\n readonly id = ADAPTER_ID;\n readonly capabilities = CAPS;\n readonly #opts: Mem0AdapterOptions;\n readonly #breaker: CircuitBreaker;\n #client?: MemoryClient;\n\n constructor(opts: Mem0AdapterOptions) {\n this.#opts = opts;\n this.#breaker = new CircuitBreaker(opts.breaker);\n }\n\n isAvailable(): boolean {\n return typeof this.#opts.apiKey === \"string\" && this.#opts.apiKey.length > 0;\n }\n\n async initialize(): Promise<void> {\n // Lazy: client constructed on first call.\n }\n\n async write(content: string | MemoryTurnMessage[], ctx: MemoryContext): Promise<MemoryId> {\n this.#breaker.ensureClosed(\"write\");\n const messages = this.#toMessages(content);\n if (messages.length === 0) {\n throw new MemoryAdapterError(\"write: empty messages\", {\n adapterId: ADAPTER_ID,\n code: \"invalid_input\",\n });\n }\n try {\n const opts = toMem0Options(ctx);\n const resp = await this.#sdk().add(messages, opts);\n this.#breaker.recordSuccess();\n const first = resp[0];\n const rawId = first?.id ?? `mem0-${Date.now()}`;\n return mkMemoryId(ADAPTER_ID, rawId);\n } catch (err) {\n throw this.#translateError(err, \"write\");\n }\n }\n\n async recall(query: string, ctx: MemoryContext, k = 10): Promise<MemoryFact[]> {\n if (k <= 0) return [];\n this.#breaker.ensureClosed(\"recall\");\n try {\n const opts = toMem0Options(ctx);\n const resp = await this.#sdk().search(query, {\n // Read filter: cross-session recall keyed by user_id (Hermes pattern).\n ...(opts.user_id !== undefined ? { filters: { user_id: opts.user_id } } : {}),\n topK: k,\n rerank: true,\n });\n this.#breaker.recordSuccess();\n const list = Array.isArray(resp) ? resp : ((resp as { results?: unknown[] }).results ?? []);\n return (list as Array<Record<string, unknown>>).map((r) => ({\n id: mkMemoryId(ADAPTER_ID, String(r.id ?? \"\")),\n content: String(r.memory ?? r.content ?? \"\"),\n ...(typeof r.score === \"number\" ? { score: r.score as number } : {}),\n ...(r.createdAt !== undefined ? { createdAt: String(r.createdAt) } : {}),\n ...(r.metadata !== undefined ? { metadata: r.metadata as Record<string, unknown> } : {}),\n }));\n } catch (err) {\n throw this.#translateError(err, \"recall\");\n }\n }\n\n async delete(id: MemoryId): Promise<void> {\n this.#breaker.ensureClosed(\"delete\");\n const rawId = extractRawId(id, ADAPTER_ID);\n try {\n await this.#sdk().delete(rawId);\n this.#breaker.recordSuccess();\n } catch (err) {\n throw this.#translateError(err, \"delete\");\n }\n }\n\n async history(id: MemoryId): Promise<MemoryRevision[]> {\n this.#breaker.ensureClosed(\"history\");\n const rawId = extractRawId(id, ADAPTER_ID);\n try {\n const rows = await this.#sdk().history(rawId);\n this.#breaker.recordSuccess();\n return rows.map((r, i) => {\n const u = (r as unknown as { updatedAt?: unknown }).updatedAt;\n const changedAt =\n u instanceof Date\n ? u.toISOString()\n : typeof u === \"string\"\n ? u\n : new Date().toISOString();\n return {\n id: mkMemoryId(ADAPTER_ID, r.memoryId ?? rawId),\n content: String(r.newMemory ?? r.oldMemory ?? \"\"),\n version: i + 1,\n changedAt,\n };\n });\n } catch (err) {\n throw this.#translateError(err, \"history\");\n }\n }\n\n getToolSchemas(): MemoryToolSchema[] {\n return [\n {\n name: \"memory_write\",\n description:\n \"Persist a turn to Mem0 long-term memory. Server-side extraction populates facts.\",\n parameters: {\n type: \"object\",\n properties: {\n content: { type: \"string\", description: \"Turn text to persist.\" },\n },\n required: [\"content\"],\n },\n },\n {\n name: \"memory_recall\",\n description: \"Retrieve up to k semantically relevant facts from Mem0 (server-side rerank).\",\n parameters: {\n type: \"object\",\n properties: {\n query: { type: \"string\" },\n k: { type: \"integer\", minimum: 1, maximum: 50 },\n },\n required: [\"query\"],\n },\n },\n {\n name: \"memory_history\",\n description:\n \"Retrieve the version history of a specific memory by id. Mem0-unique capability — \" +\n \"shows how a fact has evolved over time (e.g., user changed preferences).\",\n parameters: {\n type: \"object\",\n properties: { memoryId: { type: \"string\" } },\n required: [\"memoryId\"],\n },\n },\n ];\n }\n\n async handleToolCall(\n name: string,\n args: Record<string, unknown>,\n ctx: MemoryContext,\n ): Promise<string> {\n if (name === \"memory_write\") {\n const id = await this.write(String(args.content ?? \"\"), ctx);\n return JSON.stringify({ ok: true, id });\n }\n if (name === \"memory_recall\") {\n const k = typeof args.k === \"number\" ? args.k : 10;\n const facts = await this.recall(String(args.query ?? \"\"), ctx, k);\n return JSON.stringify({ ok: true, facts });\n }\n if (name === \"memory_history\") {\n const rawId = String(args.memoryId ?? \"\");\n const wrapped = rawId.startsWith(`${ADAPTER_ID}:`)\n ? (rawId as MemoryId)\n : mkMemoryId(ADAPTER_ID, rawId);\n const revisions = await this.history(wrapped);\n return JSON.stringify({ ok: true, revisions });\n }\n throw new MemoryAdapterError(`Unknown tool name: ${name}`, {\n adapterId: ADAPTER_ID,\n code: \"invalid_input\",\n });\n }\n\n async shutdown(): Promise<void> {\n this.#client = undefined;\n }\n\n /** Test-only: inspect breaker state. @internal */\n _breakerState(): { failures: number; isOpen: boolean; openUntil: number } {\n return this.#breaker.state();\n }\n\n // ── helpers ────────────────────────────────────────────────────────\n\n #toMessages(\n content: string | MemoryTurnMessage[],\n ): Array<{ role: \"user\" | \"assistant\"; content: string }> {\n if (typeof content === \"string\") {\n return content.trim().length === 0 ? [] : [{ role: \"user\", content }];\n }\n // Mem0 SDK accepts only user/assistant roles. System turns are merged\n // into user content with a \"[system] \" prefix.\n return content\n .filter((m) => m.content.trim().length > 0)\n .map((m) =>\n m.role === \"system\"\n ? { role: \"user\" as const, content: `[system] ${m.content}` }\n : { role: m.role, content: m.content },\n );\n }\n\n #sdk(): MemoryClient {\n if (this.#client === undefined) {\n this.#client = new MemoryClient({\n apiKey: this.#opts.apiKey,\n ...(this.#opts.host !== undefined ? { host: this.#opts.host } : {}),\n ...(this.#opts.organizationId !== undefined\n ? { organizationId: this.#opts.organizationId }\n : {}),\n ...(this.#opts.projectId !== undefined ? { projectId: this.#opts.projectId } : {}),\n });\n }\n return this.#client;\n }\n\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: error-translation ladder maps provider error classes to typed codes + breaker policy (EC-K: 429 does NOT trip); inlining keeps the policy decisions in one place.\n #translateError(err: unknown, op: string): MemoryAdapterError {\n if (err instanceof MemoryAdapterError) {\n if (err.code === \"rate_limited\") {\n // EC-K: do NOT trip breaker on rate limit.\n } else if (\n err.code === \"auth_failed\" ||\n err.code === \"not_found\" ||\n err.code === \"invalid_input\"\n ) {\n // No trip — these are caller-side or stateful conditions.\n } else {\n this.#breaker.recordFailure();\n }\n return err;\n }\n // The real mem0ai SDK does NOT attach `.status`/`.statusCode`/`.response.status` to its\n // thrown errors (verified against mem0ai@3.0.3's `createExceptionFromResponse`, which builds\n // `RateLimitError`/`AuthenticationError`/etc. carrying only `.errorCode` as a string like\n // `\"HTTP_429\"`). Without this fallback, every real vendor error fell through to `status ===\n // undefined` and was misclassified as `code: \"unknown\"` — 429s never got the EC-K rate-limit\n // exemption and 5xx never tripped the breaker. Caught by wire-contract.test.ts running the\n // real SDK; the old hand-written `vi.mock` fabricated `.status` on its thrown errors, which\n // is why this never failed a test.\n const errorCode = (err as { errorCode?: unknown })?.errorCode;\n const statusFromErrorCode =\n typeof errorCode === \"string\" && /^HTTP_(\\d{3})$/.test(errorCode)\n ? Number(errorCode.slice(5))\n : undefined;\n const status =\n (err as { status?: number; statusCode?: number; response?: { status?: number } })?.status ??\n (err as { statusCode?: number })?.statusCode ??\n (err as { response?: { status?: number } })?.response?.status ??\n statusFromErrorCode;\n const message = (err as Error)?.message ?? String(err);\n if (status === 401 || status === 403) {\n return new MemoryAdapterError(`Mem0 auth failed (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"auth_failed\",\n cause: err,\n });\n }\n if (status === 429) {\n // EC-K: rate-limited; do NOT increment breaker.\n return new MemoryAdapterError(`Mem0 rate limited (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"rate_limited\",\n cause: err,\n });\n }\n if (status === 404) {\n return new MemoryAdapterError(`Mem0 not found (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"not_found\",\n cause: err,\n });\n }\n if (typeof status === \"number\" && status >= 500) {\n this.#breaker.recordFailure();\n return new MemoryAdapterError(`Mem0 server error (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"network\",\n cause: err,\n });\n }\n if (status === undefined && message.toLowerCase().includes(\"network\")) {\n this.#breaker.recordFailure();\n return new MemoryAdapterError(`Mem0 network error (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"network\",\n cause: err,\n });\n }\n return new MemoryAdapterError(`Mem0 error (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"unknown\",\n cause: err,\n });\n }\n}\n","import { Plugin } from \"@theokit/sdk\";\n\nimport { Mem0Adapter, type Mem0AdapterOptions } from \"./adapter.js\";\n\nexport type { Mem0AdapterOptions } from \"./adapter.js\";\n\n/**\n * Wire Mem0 cloud as the agent's long-term memory.\n *\n * ```ts\n * const agent = await Agent.create({\n * model: { id: \"openai/gpt-4o-mini\" },\n * plugins: [mem0Memory({ apiKey: process.env.MEM0_API_KEY! })],\n * });\n * ```\n *\n * Needs `mem0ai@^3.0.0` — a REQUIRED peer dependency, not an optional one; without it the import\n * throws at load time. Cloud only: `MemoryClient` talks to Mem0's hosted API, and `mem0ai` has no\n * `MEM0_API_KEY` environment fallback, so {@link Mem0AdapterOptions.apiKey} must be supplied.\n *\n * What this adapter gives you that the others do not, and what to watch for:\n *\n * - **`history(id)` works** (`capabilities.history === true`) — it is the only adapter in the\n * ecosystem that exposes per-memory versioning, and it backs the extra `memory_history` tool\n * offered to the model.\n * - **`recall` is CROSS-SESSION on purpose.** Writes carry `run_id = ctx.sessionId`, but the\n * search filter is `user_id` alone, so a recall in session B returns memories written in\n * session A. If you need per-session isolation, use distinct `ctx.userId` values — `sessionId`\n * will not give it to you.\n * - **`recall` defaults to `k = 10`** with server-side rerank; `write` returns the id of the first\n * memory Mem0's server-side extraction produced, which need not be the text you sent.\n * - **`system` turns are rewritten.** Mem0 accepts only `user` / `assistant`, so a\n * `MemoryTurnMessage` with `role: \"system\"` is sent as a `user` turn prefixed with `[system] `.\n *\n * Trap — the circuit breaker reports itself as a RATE LIMIT. After\n * {@link Mem0AdapterOptions.breaker} trips, every call throws\n * `MemoryAdapterError(code: \"rate_limited\")` with a message naming the remaining cooldown, even\n * though the cause was a 5xx or a transport failure and no request was sent. Match on the message,\n * or on the fact that the failure is instantaneous, to tell the two apart.\n *\n * Errors are always `MemoryAdapterError` with `adapterId: \"mem0\"` and one of\n * `auth_failed` (401/403) | `rate_limited` (429 or breaker open) | `not_found` (404) |\n * `network` (5xx, or a status-less error whose message contains \"network\") | `invalid_input` |\n * `unknown` (everything else, including a transport error reported as `\"fetch failed\"`).\n * Both `network` shapes count toward {@link Mem0AdapterOptions.breaker}; `unknown` does not.\n *\n * @public\n */\nexport function mem0Memory(options: Mem0AdapterOptions): Plugin {\n return Plugin.create({\n name: \"@theokit/memory-mem0\",\n version: \"0.1.0\",\n kind: \"memory\",\n createProvider: () => new Mem0Adapter(options),\n });\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -3,14 +3,43 @@ import { Plugin } from '@theokit/sdk';
|
|
|
3
3
|
/**
|
|
4
4
|
* In-memory circuit breaker for Mem0Adapter (T5.1, EC-K).
|
|
5
5
|
*
|
|
6
|
-
* Trips after `threshold` consecutive
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Trips after `threshold` consecutive failures that `Mem0Adapter#translateError`
|
|
7
|
+
* decides are provider-down signals: an HTTP 5xx, or a status-less error whose
|
|
8
|
+
* message contains "network". 429 / 401 / 403 / 404 / invalid_input do NOT count
|
|
9
|
+
* toward the threshold — rate limits are a caller-pace signal, not a
|
|
10
|
+
* provider-down signal (EC-K).
|
|
9
11
|
*
|
|
10
12
|
* @internal
|
|
11
13
|
*/
|
|
14
|
+
/**
|
|
15
|
+
* Tuning for the Mem0 adapter's circuit breaker, passed as `mem0Memory({ breaker })`.
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
12
19
|
interface CircuitBreakerOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Failures required to open the breaker. Default `5`.
|
|
22
|
+
*
|
|
23
|
+
* TWO kinds of failure count, not one: an HTTP 5xx, and a status-less error whose message
|
|
24
|
+
* contains the substring `network` (case-insensitive) — that substring match is the only way a
|
|
25
|
+
* transport failure is recognised, so a DNS/connection error surfacing as `"fetch failed"` maps
|
|
26
|
+
* to `code: "unknown"` and does NOT count. 429 / 401 / 403 / 404 / `invalid_input` never count.
|
|
27
|
+
*
|
|
28
|
+
* Size it for transport flakiness as well as for Mem0 outages: with `threshold: 5`, five
|
|
29
|
+
* consecutive `network`-shaped errors open the breaker exactly as five 500s would, and the
|
|
30
|
+
* resulting error says `rate_limited`, which is not what caused it.
|
|
31
|
+
*
|
|
32
|
+
* A single success resets the counter to zero, so this is effectively "consecutive counted
|
|
33
|
+
* failures" — 4 failures followed by a success followed by 4 more never trips a default breaker.
|
|
34
|
+
*/
|
|
13
35
|
threshold?: number;
|
|
36
|
+
/**
|
|
37
|
+
* How long the breaker stays open, in milliseconds. Default `120000` (2 minutes).
|
|
38
|
+
*
|
|
39
|
+
* While open, every call fails immediately with `MemoryAdapterError(code: "rate_limited")`
|
|
40
|
+
* without touching the network. There is no half-open probe: the breaker simply closes when the
|
|
41
|
+
* cooldown elapses and the next call goes through for real.
|
|
42
|
+
*/
|
|
14
43
|
cooldownMs?: number;
|
|
15
44
|
}
|
|
16
45
|
|
|
@@ -26,19 +55,78 @@ interface CircuitBreakerOptions {
|
|
|
26
55
|
* @public
|
|
27
56
|
*/
|
|
28
57
|
|
|
29
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Configuration accepted by the `mem0Memory(...)` factory.
|
|
60
|
+
*
|
|
61
|
+
* @public
|
|
62
|
+
*/
|
|
30
63
|
interface Mem0AdapterOptions {
|
|
31
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* Mem0 API key. Genuinely required — `mem0ai` reads no `MEM0_API_KEY` environment variable, so
|
|
66
|
+
* there is no fallback anywhere in the chain.
|
|
67
|
+
*
|
|
68
|
+
* The client is built lazily on the first `write` / `recall`, so a wrong key does not fail
|
|
69
|
+
* `Agent.create`; it surfaces as `MemoryAdapterError(code: "auth_failed")` on the first call.
|
|
70
|
+
*/
|
|
32
71
|
apiKey: string;
|
|
33
|
-
/**
|
|
72
|
+
/** Alternate Mem0 API host. Omit for Mem0 cloud, which is the vendor default. */
|
|
34
73
|
host?: string;
|
|
74
|
+
/** Mem0 organization to scope writes to. Forwarded only when set. */
|
|
35
75
|
organizationId?: string;
|
|
76
|
+
/** Mem0 project to scope writes to. Forwarded only when set. */
|
|
36
77
|
projectId?: string;
|
|
37
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* Circuit-breaker tuning. Defaults: trip after 5 failures, 2-minute cooldown.
|
|
80
|
+
*
|
|
81
|
+
* The breaker is PER ADAPTER INSTANCE — one `mem0Memory(...)` call, one breaker. Two agents
|
|
82
|
+
* built from two separate factory calls do not share it, so one agent tripping does not
|
|
83
|
+
* protect the other.
|
|
84
|
+
*/
|
|
38
85
|
breaker?: CircuitBreakerOptions;
|
|
39
86
|
}
|
|
40
87
|
|
|
41
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* Wire Mem0 cloud as the agent's long-term memory.
|
|
90
|
+
*
|
|
91
|
+
* ```ts
|
|
92
|
+
* const agent = await Agent.create({
|
|
93
|
+
* model: { id: "openai/gpt-4o-mini" },
|
|
94
|
+
* plugins: [mem0Memory({ apiKey: process.env.MEM0_API_KEY! })],
|
|
95
|
+
* });
|
|
96
|
+
* ```
|
|
97
|
+
*
|
|
98
|
+
* Needs `mem0ai@^3.0.0` — a REQUIRED peer dependency, not an optional one; without it the import
|
|
99
|
+
* throws at load time. Cloud only: `MemoryClient` talks to Mem0's hosted API, and `mem0ai` has no
|
|
100
|
+
* `MEM0_API_KEY` environment fallback, so {@link Mem0AdapterOptions.apiKey} must be supplied.
|
|
101
|
+
*
|
|
102
|
+
* What this adapter gives you that the others do not, and what to watch for:
|
|
103
|
+
*
|
|
104
|
+
* - **`history(id)` works** (`capabilities.history === true`) — it is the only adapter in the
|
|
105
|
+
* ecosystem that exposes per-memory versioning, and it backs the extra `memory_history` tool
|
|
106
|
+
* offered to the model.
|
|
107
|
+
* - **`recall` is CROSS-SESSION on purpose.** Writes carry `run_id = ctx.sessionId`, but the
|
|
108
|
+
* search filter is `user_id` alone, so a recall in session B returns memories written in
|
|
109
|
+
* session A. If you need per-session isolation, use distinct `ctx.userId` values — `sessionId`
|
|
110
|
+
* will not give it to you.
|
|
111
|
+
* - **`recall` defaults to `k = 10`** with server-side rerank; `write` returns the id of the first
|
|
112
|
+
* memory Mem0's server-side extraction produced, which need not be the text you sent.
|
|
113
|
+
* - **`system` turns are rewritten.** Mem0 accepts only `user` / `assistant`, so a
|
|
114
|
+
* `MemoryTurnMessage` with `role: "system"` is sent as a `user` turn prefixed with `[system] `.
|
|
115
|
+
*
|
|
116
|
+
* Trap — the circuit breaker reports itself as a RATE LIMIT. After
|
|
117
|
+
* {@link Mem0AdapterOptions.breaker} trips, every call throws
|
|
118
|
+
* `MemoryAdapterError(code: "rate_limited")` with a message naming the remaining cooldown, even
|
|
119
|
+
* though the cause was a 5xx or a transport failure and no request was sent. Match on the message,
|
|
120
|
+
* or on the fact that the failure is instantaneous, to tell the two apart.
|
|
121
|
+
*
|
|
122
|
+
* Errors are always `MemoryAdapterError` with `adapterId: "mem0"` and one of
|
|
123
|
+
* `auth_failed` (401/403) | `rate_limited` (429 or breaker open) | `not_found` (404) |
|
|
124
|
+
* `network` (5xx, or a status-less error whose message contains "network") | `invalid_input` |
|
|
125
|
+
* `unknown` (everything else, including a transport error reported as `"fetch failed"`).
|
|
126
|
+
* Both `network` shapes count toward {@link Mem0AdapterOptions.breaker}; `unknown` does not.
|
|
127
|
+
*
|
|
128
|
+
* @public
|
|
129
|
+
*/
|
|
42
130
|
declare function mem0Memory(options: Mem0AdapterOptions): Plugin;
|
|
43
131
|
|
|
44
132
|
export { type Mem0AdapterOptions, mem0Memory };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,14 +3,43 @@ import { Plugin } from '@theokit/sdk';
|
|
|
3
3
|
/**
|
|
4
4
|
* In-memory circuit breaker for Mem0Adapter (T5.1, EC-K).
|
|
5
5
|
*
|
|
6
|
-
* Trips after `threshold` consecutive
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Trips after `threshold` consecutive failures that `Mem0Adapter#translateError`
|
|
7
|
+
* decides are provider-down signals: an HTTP 5xx, or a status-less error whose
|
|
8
|
+
* message contains "network". 429 / 401 / 403 / 404 / invalid_input do NOT count
|
|
9
|
+
* toward the threshold — rate limits are a caller-pace signal, not a
|
|
10
|
+
* provider-down signal (EC-K).
|
|
9
11
|
*
|
|
10
12
|
* @internal
|
|
11
13
|
*/
|
|
14
|
+
/**
|
|
15
|
+
* Tuning for the Mem0 adapter's circuit breaker, passed as `mem0Memory({ breaker })`.
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
12
19
|
interface CircuitBreakerOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Failures required to open the breaker. Default `5`.
|
|
22
|
+
*
|
|
23
|
+
* TWO kinds of failure count, not one: an HTTP 5xx, and a status-less error whose message
|
|
24
|
+
* contains the substring `network` (case-insensitive) — that substring match is the only way a
|
|
25
|
+
* transport failure is recognised, so a DNS/connection error surfacing as `"fetch failed"` maps
|
|
26
|
+
* to `code: "unknown"` and does NOT count. 429 / 401 / 403 / 404 / `invalid_input` never count.
|
|
27
|
+
*
|
|
28
|
+
* Size it for transport flakiness as well as for Mem0 outages: with `threshold: 5`, five
|
|
29
|
+
* consecutive `network`-shaped errors open the breaker exactly as five 500s would, and the
|
|
30
|
+
* resulting error says `rate_limited`, which is not what caused it.
|
|
31
|
+
*
|
|
32
|
+
* A single success resets the counter to zero, so this is effectively "consecutive counted
|
|
33
|
+
* failures" — 4 failures followed by a success followed by 4 more never trips a default breaker.
|
|
34
|
+
*/
|
|
13
35
|
threshold?: number;
|
|
36
|
+
/**
|
|
37
|
+
* How long the breaker stays open, in milliseconds. Default `120000` (2 minutes).
|
|
38
|
+
*
|
|
39
|
+
* While open, every call fails immediately with `MemoryAdapterError(code: "rate_limited")`
|
|
40
|
+
* without touching the network. There is no half-open probe: the breaker simply closes when the
|
|
41
|
+
* cooldown elapses and the next call goes through for real.
|
|
42
|
+
*/
|
|
14
43
|
cooldownMs?: number;
|
|
15
44
|
}
|
|
16
45
|
|
|
@@ -26,19 +55,78 @@ interface CircuitBreakerOptions {
|
|
|
26
55
|
* @public
|
|
27
56
|
*/
|
|
28
57
|
|
|
29
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Configuration accepted by the `mem0Memory(...)` factory.
|
|
60
|
+
*
|
|
61
|
+
* @public
|
|
62
|
+
*/
|
|
30
63
|
interface Mem0AdapterOptions {
|
|
31
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* Mem0 API key. Genuinely required — `mem0ai` reads no `MEM0_API_KEY` environment variable, so
|
|
66
|
+
* there is no fallback anywhere in the chain.
|
|
67
|
+
*
|
|
68
|
+
* The client is built lazily on the first `write` / `recall`, so a wrong key does not fail
|
|
69
|
+
* `Agent.create`; it surfaces as `MemoryAdapterError(code: "auth_failed")` on the first call.
|
|
70
|
+
*/
|
|
32
71
|
apiKey: string;
|
|
33
|
-
/**
|
|
72
|
+
/** Alternate Mem0 API host. Omit for Mem0 cloud, which is the vendor default. */
|
|
34
73
|
host?: string;
|
|
74
|
+
/** Mem0 organization to scope writes to. Forwarded only when set. */
|
|
35
75
|
organizationId?: string;
|
|
76
|
+
/** Mem0 project to scope writes to. Forwarded only when set. */
|
|
36
77
|
projectId?: string;
|
|
37
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* Circuit-breaker tuning. Defaults: trip after 5 failures, 2-minute cooldown.
|
|
80
|
+
*
|
|
81
|
+
* The breaker is PER ADAPTER INSTANCE — one `mem0Memory(...)` call, one breaker. Two agents
|
|
82
|
+
* built from two separate factory calls do not share it, so one agent tripping does not
|
|
83
|
+
* protect the other.
|
|
84
|
+
*/
|
|
38
85
|
breaker?: CircuitBreakerOptions;
|
|
39
86
|
}
|
|
40
87
|
|
|
41
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* Wire Mem0 cloud as the agent's long-term memory.
|
|
90
|
+
*
|
|
91
|
+
* ```ts
|
|
92
|
+
* const agent = await Agent.create({
|
|
93
|
+
* model: { id: "openai/gpt-4o-mini" },
|
|
94
|
+
* plugins: [mem0Memory({ apiKey: process.env.MEM0_API_KEY! })],
|
|
95
|
+
* });
|
|
96
|
+
* ```
|
|
97
|
+
*
|
|
98
|
+
* Needs `mem0ai@^3.0.0` — a REQUIRED peer dependency, not an optional one; without it the import
|
|
99
|
+
* throws at load time. Cloud only: `MemoryClient` talks to Mem0's hosted API, and `mem0ai` has no
|
|
100
|
+
* `MEM0_API_KEY` environment fallback, so {@link Mem0AdapterOptions.apiKey} must be supplied.
|
|
101
|
+
*
|
|
102
|
+
* What this adapter gives you that the others do not, and what to watch for:
|
|
103
|
+
*
|
|
104
|
+
* - **`history(id)` works** (`capabilities.history === true`) — it is the only adapter in the
|
|
105
|
+
* ecosystem that exposes per-memory versioning, and it backs the extra `memory_history` tool
|
|
106
|
+
* offered to the model.
|
|
107
|
+
* - **`recall` is CROSS-SESSION on purpose.** Writes carry `run_id = ctx.sessionId`, but the
|
|
108
|
+
* search filter is `user_id` alone, so a recall in session B returns memories written in
|
|
109
|
+
* session A. If you need per-session isolation, use distinct `ctx.userId` values — `sessionId`
|
|
110
|
+
* will not give it to you.
|
|
111
|
+
* - **`recall` defaults to `k = 10`** with server-side rerank; `write` returns the id of the first
|
|
112
|
+
* memory Mem0's server-side extraction produced, which need not be the text you sent.
|
|
113
|
+
* - **`system` turns are rewritten.** Mem0 accepts only `user` / `assistant`, so a
|
|
114
|
+
* `MemoryTurnMessage` with `role: "system"` is sent as a `user` turn prefixed with `[system] `.
|
|
115
|
+
*
|
|
116
|
+
* Trap — the circuit breaker reports itself as a RATE LIMIT. After
|
|
117
|
+
* {@link Mem0AdapterOptions.breaker} trips, every call throws
|
|
118
|
+
* `MemoryAdapterError(code: "rate_limited")` with a message naming the remaining cooldown, even
|
|
119
|
+
* though the cause was a 5xx or a transport failure and no request was sent. Match on the message,
|
|
120
|
+
* or on the fact that the failure is instantaneous, to tell the two apart.
|
|
121
|
+
*
|
|
122
|
+
* Errors are always `MemoryAdapterError` with `adapterId: "mem0"` and one of
|
|
123
|
+
* `auth_failed` (401/403) | `rate_limited` (429 or breaker open) | `not_found` (404) |
|
|
124
|
+
* `network` (5xx, or a status-less error whose message contains "network") | `invalid_input` |
|
|
125
|
+
* `unknown` (everything else, including a transport error reported as `"fetch failed"`).
|
|
126
|
+
* Both `network` shapes count toward {@link Mem0AdapterOptions.breaker}; `unknown` does not.
|
|
127
|
+
*
|
|
128
|
+
* @public
|
|
129
|
+
*/
|
|
42
130
|
declare function mem0Memory(options: Mem0AdapterOptions): Plugin;
|
|
43
131
|
|
|
44
132
|
export { type Mem0AdapterOptions, mem0Memory };
|
package/dist/index.js
CHANGED
|
@@ -22,7 +22,7 @@ var CircuitBreaker = class {
|
|
|
22
22
|
);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
/** Increment failure counter. Trips when threshold reached.
|
|
25
|
+
/** Increment failure counter. Trips when threshold reached. Call only for provider-down errors. */
|
|
26
26
|
recordFailure() {
|
|
27
27
|
this.#failures += 1;
|
|
28
28
|
if (this.#failures >= this.threshold) {
|
|
@@ -247,7 +247,9 @@ var Mem0Adapter = class {
|
|
|
247
247
|
}
|
|
248
248
|
return err;
|
|
249
249
|
}
|
|
250
|
-
const
|
|
250
|
+
const errorCode = err?.errorCode;
|
|
251
|
+
const statusFromErrorCode = typeof errorCode === "string" && /^HTTP_(\d{3})$/.test(errorCode) ? Number(errorCode.slice(5)) : void 0;
|
|
252
|
+
const status = err?.status ?? err?.statusCode ?? err?.response?.status ?? statusFromErrorCode;
|
|
251
253
|
const message = err?.message ?? String(err);
|
|
252
254
|
if (status === 401 || status === 403) {
|
|
253
255
|
return new MemoryAdapterError(`Mem0 auth failed (${op}): ${message}`, {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/circuit-breaker.ts","../src/translate.ts","../src/adapter.ts","../src/index.ts"],"names":["ADAPTER_ID","MemoryAdapterError"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * In-memory circuit breaker for Mem0Adapter (T5.1, EC-K).\n *\n * Trips after `threshold` consecutive 5xx-class failures. 429 / 401 /\n * 404 / invalid_input do NOT count toward the threshold — rate limits\n * are a caller-pace signal, not a provider-down signal (EC-K).\n *\n * @internal\n */\n\nimport { MemoryAdapterError } from \"@theokit/sdk\";\n\nconst ADAPTER_ID = \"mem0\";\n\nexport interface CircuitBreakerOptions {\n threshold?: number;\n cooldownMs?: number;\n}\n\nexport class CircuitBreaker {\n readonly threshold: number;\n readonly cooldownMs: number;\n #failures = 0;\n #openUntil = 0;\n\n constructor(opts: CircuitBreakerOptions = {}) {\n this.threshold = opts.threshold ?? 5;\n this.cooldownMs = opts.cooldownMs ?? 2 * 60 * 1000;\n }\n\n /** Throws `MemoryAdapterError(code: \"rate_limited\")` if breaker is open. */\n ensureClosed(op: string): void {\n if (Date.now() < this.#openUntil) {\n const secondsLeft = Math.ceil((this.#openUntil - Date.now()) / 1000);\n throw new MemoryAdapterError(\n `Mem0 circuit breaker open (${op}): ${secondsLeft}s cooldown remaining.`,\n { adapterId: ADAPTER_ID, code: \"rate_limited\" },\n );\n }\n }\n\n /** Increment failure counter. Trips when threshold reached. Only call for 5xx-class errors. */\n recordFailure(): void {\n this.#failures += 1;\n if (this.#failures >= this.threshold) {\n this.#openUntil = Date.now() + this.cooldownMs;\n }\n }\n\n /** Reset on first success — closes the breaker (EC-K). */\n recordSuccess(): void {\n this.#failures = 0;\n this.#openUntil = 0;\n }\n\n /** Test-only inspector. @internal */\n state(): { failures: number; isOpen: boolean; openUntil: number } {\n return {\n failures: this.#failures,\n isOpen: Date.now() < this.#openUntil,\n openUntil: this.#openUntil,\n };\n }\n}\n","/**\n * `MemoryContext` → Mem0 add/search options translation (T5.1).\n *\n * Mem0 keeps `user_id`, `agent_id`, `app_id`, `run_id` orthogonal —\n * we map each `MemoryContext` field onto its native primitive.\n *\n * @internal\n */\n\nimport type { MemoryContext } from \"@theokit/sdk\";\n\ninterface Mem0Options {\n user_id?: string;\n agent_id?: string;\n run_id?: string;\n app_id?: string;\n categories?: string[];\n metadata?: Record<string, unknown>;\n}\n\nexport function toMem0Options(ctx: MemoryContext): Mem0Options {\n const out: Mem0Options = { user_id: ctx.userId };\n if (ctx.agentId !== undefined) out.agent_id = ctx.agentId;\n if (ctx.sessionId !== undefined) out.run_id = ctx.sessionId;\n if (ctx.tenantId !== undefined) out.app_id = ctx.tenantId;\n if (ctx.tags !== undefined) out.categories = ctx.tags;\n if (ctx.metadata !== undefined) out.metadata = ctx.metadata;\n return out;\n}\n","/**\n * Mem0Adapter — `@theokit/memory-mem0` core (T5.1, ADR D141 / D148).\n *\n * Wraps `mem0ai` `MemoryClient` (cloud-only per D148). Implements\n * `MemoryAdapter` with the unique `history(id)` capability — the only\n * adapter today that exposes per-memory versioning.\n *\n * Includes a circuit breaker (EC-K: 5xx counts; 429 does NOT trip).\n *\n * @public\n */\n\nimport {\n extractRawId,\n type MemoryAdapter,\n type MemoryAdapterCapabilities,\n MemoryAdapterError,\n type MemoryContext,\n type MemoryFact,\n type MemoryId,\n type MemoryRevision,\n type MemoryToolSchema,\n type MemoryTurnMessage,\n mkMemoryId,\n} from \"@theokit/sdk\";\nimport MemoryClient from \"mem0ai\";\n\nimport { CircuitBreaker, type CircuitBreakerOptions } from \"./circuit-breaker.js\";\nimport { toMem0Options } from \"./translate.js\";\n\n/** Configuration accepted by the `mem0Memory(...)` factory. @public */\nexport interface Mem0AdapterOptions {\n /** Mem0 API key. Required. */\n apiKey: string;\n /** Override host (default mem0 cloud). */\n host?: string;\n organizationId?: string;\n projectId?: string;\n /** Circuit breaker tuning (EC-K). */\n breaker?: CircuitBreakerOptions;\n}\n\nconst ADAPTER_ID = \"mem0\";\n\nconst CAPS: MemoryAdapterCapabilities = {\n history: true, // ← unique to Mem0\n sessions: true,\n tenancy: true,\n reasoning: false,\n toolSchemas: true,\n prefetch: false,\n};\n\n/** @internal */\nexport class Mem0Adapter implements MemoryAdapter {\n readonly id = ADAPTER_ID;\n readonly capabilities = CAPS;\n readonly #opts: Mem0AdapterOptions;\n readonly #breaker: CircuitBreaker;\n #client?: MemoryClient;\n\n constructor(opts: Mem0AdapterOptions) {\n this.#opts = opts;\n this.#breaker = new CircuitBreaker(opts.breaker);\n }\n\n isAvailable(): boolean {\n return typeof this.#opts.apiKey === \"string\" && this.#opts.apiKey.length > 0;\n }\n\n async initialize(): Promise<void> {\n // Lazy: client constructed on first call.\n }\n\n async write(content: string | MemoryTurnMessage[], ctx: MemoryContext): Promise<MemoryId> {\n this.#breaker.ensureClosed(\"write\");\n const messages = this.#toMessages(content);\n if (messages.length === 0) {\n throw new MemoryAdapterError(\"write: empty messages\", {\n adapterId: ADAPTER_ID,\n code: \"invalid_input\",\n });\n }\n try {\n const opts = toMem0Options(ctx);\n const resp = await this.#sdk().add(messages, opts);\n this.#breaker.recordSuccess();\n const first = resp[0];\n const rawId = first?.id ?? `mem0-${Date.now()}`;\n return mkMemoryId(ADAPTER_ID, rawId);\n } catch (err) {\n throw this.#translateError(err, \"write\");\n }\n }\n\n async recall(query: string, ctx: MemoryContext, k = 10): Promise<MemoryFact[]> {\n if (k <= 0) return [];\n this.#breaker.ensureClosed(\"recall\");\n try {\n const opts = toMem0Options(ctx);\n const resp = await this.#sdk().search(query, {\n // Read filter: cross-session recall keyed by user_id (Hermes pattern).\n ...(opts.user_id !== undefined ? { filters: { user_id: opts.user_id } } : {}),\n topK: k,\n rerank: true,\n });\n this.#breaker.recordSuccess();\n const list = Array.isArray(resp) ? resp : ((resp as { results?: unknown[] }).results ?? []);\n return (list as Array<Record<string, unknown>>).map((r) => ({\n id: mkMemoryId(ADAPTER_ID, String(r.id ?? \"\")),\n content: String(r.memory ?? r.content ?? \"\"),\n ...(typeof r.score === \"number\" ? { score: r.score as number } : {}),\n ...(r.createdAt !== undefined ? { createdAt: String(r.createdAt) } : {}),\n ...(r.metadata !== undefined ? { metadata: r.metadata as Record<string, unknown> } : {}),\n }));\n } catch (err) {\n throw this.#translateError(err, \"recall\");\n }\n }\n\n async delete(id: MemoryId): Promise<void> {\n this.#breaker.ensureClosed(\"delete\");\n const rawId = extractRawId(id, ADAPTER_ID);\n try {\n await this.#sdk().delete(rawId);\n this.#breaker.recordSuccess();\n } catch (err) {\n throw this.#translateError(err, \"delete\");\n }\n }\n\n async history(id: MemoryId): Promise<MemoryRevision[]> {\n this.#breaker.ensureClosed(\"history\");\n const rawId = extractRawId(id, ADAPTER_ID);\n try {\n const rows = await this.#sdk().history(rawId);\n this.#breaker.recordSuccess();\n return rows.map((r, i) => {\n const u = (r as unknown as { updatedAt?: unknown }).updatedAt;\n const changedAt =\n u instanceof Date\n ? u.toISOString()\n : typeof u === \"string\"\n ? u\n : new Date().toISOString();\n return {\n id: mkMemoryId(ADAPTER_ID, r.memoryId ?? rawId),\n content: String(r.newMemory ?? r.oldMemory ?? \"\"),\n version: i + 1,\n changedAt,\n };\n });\n } catch (err) {\n throw this.#translateError(err, \"history\");\n }\n }\n\n getToolSchemas(): MemoryToolSchema[] {\n return [\n {\n name: \"memory_write\",\n description:\n \"Persist a turn to Mem0 long-term memory. Server-side extraction populates facts.\",\n parameters: {\n type: \"object\",\n properties: {\n content: { type: \"string\", description: \"Turn text to persist.\" },\n },\n required: [\"content\"],\n },\n },\n {\n name: \"memory_recall\",\n description: \"Retrieve up to k semantically relevant facts from Mem0 (server-side rerank).\",\n parameters: {\n type: \"object\",\n properties: {\n query: { type: \"string\" },\n k: { type: \"integer\", minimum: 1, maximum: 50 },\n },\n required: [\"query\"],\n },\n },\n {\n name: \"memory_history\",\n description:\n \"Retrieve the version history of a specific memory by id. Mem0-unique capability — \" +\n \"shows how a fact has evolved over time (e.g., user changed preferences).\",\n parameters: {\n type: \"object\",\n properties: { memoryId: { type: \"string\" } },\n required: [\"memoryId\"],\n },\n },\n ];\n }\n\n async handleToolCall(\n name: string,\n args: Record<string, unknown>,\n ctx: MemoryContext,\n ): Promise<string> {\n if (name === \"memory_write\") {\n const id = await this.write(String(args.content ?? \"\"), ctx);\n return JSON.stringify({ ok: true, id });\n }\n if (name === \"memory_recall\") {\n const k = typeof args.k === \"number\" ? args.k : 10;\n const facts = await this.recall(String(args.query ?? \"\"), ctx, k);\n return JSON.stringify({ ok: true, facts });\n }\n if (name === \"memory_history\") {\n const rawId = String(args.memoryId ?? \"\");\n const wrapped = rawId.startsWith(`${ADAPTER_ID}:`)\n ? (rawId as MemoryId)\n : mkMemoryId(ADAPTER_ID, rawId);\n const revisions = await this.history(wrapped);\n return JSON.stringify({ ok: true, revisions });\n }\n throw new MemoryAdapterError(`Unknown tool name: ${name}`, {\n adapterId: ADAPTER_ID,\n code: \"invalid_input\",\n });\n }\n\n async shutdown(): Promise<void> {\n this.#client = undefined;\n }\n\n /** Test-only: inspect breaker state. @internal */\n _breakerState(): { failures: number; isOpen: boolean; openUntil: number } {\n return this.#breaker.state();\n }\n\n // ── helpers ────────────────────────────────────────────────────────\n\n #toMessages(\n content: string | MemoryTurnMessage[],\n ): Array<{ role: \"user\" | \"assistant\"; content: string }> {\n if (typeof content === \"string\") {\n return content.trim().length === 0 ? [] : [{ role: \"user\", content }];\n }\n // Mem0 SDK accepts only user/assistant roles. System turns are merged\n // into user content with a \"[system] \" prefix.\n return content\n .filter((m) => m.content.trim().length > 0)\n .map((m) =>\n m.role === \"system\"\n ? { role: \"user\" as const, content: `[system] ${m.content}` }\n : { role: m.role, content: m.content },\n );\n }\n\n #sdk(): MemoryClient {\n if (this.#client === undefined) {\n this.#client = new MemoryClient({\n apiKey: this.#opts.apiKey,\n ...(this.#opts.host !== undefined ? { host: this.#opts.host } : {}),\n ...(this.#opts.organizationId !== undefined\n ? { organizationId: this.#opts.organizationId }\n : {}),\n ...(this.#opts.projectId !== undefined ? { projectId: this.#opts.projectId } : {}),\n });\n }\n return this.#client;\n }\n\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: error-translation ladder maps provider error classes to typed codes + breaker policy (EC-K: 429 does NOT trip); inlining keeps the policy decisions in one place.\n #translateError(err: unknown, op: string): MemoryAdapterError {\n if (err instanceof MemoryAdapterError) {\n if (err.code === \"rate_limited\") {\n // EC-K: do NOT trip breaker on rate limit.\n } else if (\n err.code === \"auth_failed\" ||\n err.code === \"not_found\" ||\n err.code === \"invalid_input\"\n ) {\n // No trip — these are caller-side or stateful conditions.\n } else {\n this.#breaker.recordFailure();\n }\n return err;\n }\n const status =\n (err as { status?: number; statusCode?: number; response?: { status?: number } })?.status ??\n (err as { statusCode?: number })?.statusCode ??\n (err as { response?: { status?: number } })?.response?.status;\n const message = (err as Error)?.message ?? String(err);\n if (status === 401 || status === 403) {\n return new MemoryAdapterError(`Mem0 auth failed (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"auth_failed\",\n cause: err,\n });\n }\n if (status === 429) {\n // EC-K: rate-limited; do NOT increment breaker.\n return new MemoryAdapterError(`Mem0 rate limited (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"rate_limited\",\n cause: err,\n });\n }\n if (status === 404) {\n return new MemoryAdapterError(`Mem0 not found (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"not_found\",\n cause: err,\n });\n }\n if (typeof status === \"number\" && status >= 500) {\n this.#breaker.recordFailure();\n return new MemoryAdapterError(`Mem0 server error (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"network\",\n cause: err,\n });\n }\n if (status === undefined && message.toLowerCase().includes(\"network\")) {\n this.#breaker.recordFailure();\n return new MemoryAdapterError(`Mem0 network error (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"network\",\n cause: err,\n });\n }\n return new MemoryAdapterError(`Mem0 error (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"unknown\",\n cause: err,\n });\n }\n}\n","import { Plugin } from \"@theokit/sdk\";\n\nimport { Mem0Adapter, type Mem0AdapterOptions } from \"./adapter.js\";\n\nexport type { Mem0AdapterOptions } from \"./adapter.js\";\n\n/** Build a `Plugin { kind: \"memory\" }`. @public */\nexport function mem0Memory(options: Mem0AdapterOptions): Plugin {\n return Plugin.create({\n name: \"@theokit/memory-mem0\",\n version: \"0.1.0\",\n kind: \"memory\",\n createProvider: () => new Mem0Adapter(options),\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/circuit-breaker.ts","../src/translate.ts","../src/adapter.ts","../src/index.ts"],"names":["ADAPTER_ID","MemoryAdapterError"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * In-memory circuit breaker for Mem0Adapter (T5.1, EC-K).\n *\n * Trips after `threshold` consecutive failures that `Mem0Adapter#translateError`\n * decides are provider-down signals: an HTTP 5xx, or a status-less error whose\n * message contains \"network\". 429 / 401 / 403 / 404 / invalid_input do NOT count\n * toward the threshold — rate limits are a caller-pace signal, not a\n * provider-down signal (EC-K).\n *\n * @internal\n */\n\nimport { MemoryAdapterError } from \"@theokit/sdk\";\n\nconst ADAPTER_ID = \"mem0\";\n\n/**\n * Tuning for the Mem0 adapter's circuit breaker, passed as `mem0Memory({ breaker })`.\n *\n * @public\n */\nexport interface CircuitBreakerOptions {\n /**\n * Failures required to open the breaker. Default `5`.\n *\n * TWO kinds of failure count, not one: an HTTP 5xx, and a status-less error whose message\n * contains the substring `network` (case-insensitive) — that substring match is the only way a\n * transport failure is recognised, so a DNS/connection error surfacing as `\"fetch failed\"` maps\n * to `code: \"unknown\"` and does NOT count. 429 / 401 / 403 / 404 / `invalid_input` never count.\n *\n * Size it for transport flakiness as well as for Mem0 outages: with `threshold: 5`, five\n * consecutive `network`-shaped errors open the breaker exactly as five 500s would, and the\n * resulting error says `rate_limited`, which is not what caused it.\n *\n * A single success resets the counter to zero, so this is effectively \"consecutive counted\n * failures\" — 4 failures followed by a success followed by 4 more never trips a default breaker.\n */\n threshold?: number;\n /**\n * How long the breaker stays open, in milliseconds. Default `120000` (2 minutes).\n *\n * While open, every call fails immediately with `MemoryAdapterError(code: \"rate_limited\")`\n * without touching the network. There is no half-open probe: the breaker simply closes when the\n * cooldown elapses and the next call goes through for real.\n */\n cooldownMs?: number;\n}\n\nexport class CircuitBreaker {\n readonly threshold: number;\n readonly cooldownMs: number;\n #failures = 0;\n #openUntil = 0;\n\n constructor(opts: CircuitBreakerOptions = {}) {\n this.threshold = opts.threshold ?? 5;\n this.cooldownMs = opts.cooldownMs ?? 2 * 60 * 1000;\n }\n\n /** Throws `MemoryAdapterError(code: \"rate_limited\")` if breaker is open. */\n ensureClosed(op: string): void {\n if (Date.now() < this.#openUntil) {\n const secondsLeft = Math.ceil((this.#openUntil - Date.now()) / 1000);\n throw new MemoryAdapterError(\n `Mem0 circuit breaker open (${op}): ${secondsLeft}s cooldown remaining.`,\n { adapterId: ADAPTER_ID, code: \"rate_limited\" },\n );\n }\n }\n\n /** Increment failure counter. Trips when threshold reached. Call only for provider-down errors. */\n recordFailure(): void {\n this.#failures += 1;\n if (this.#failures >= this.threshold) {\n this.#openUntil = Date.now() + this.cooldownMs;\n }\n }\n\n /** Reset on first success — closes the breaker (EC-K). */\n recordSuccess(): void {\n this.#failures = 0;\n this.#openUntil = 0;\n }\n\n /** Test-only inspector. @internal */\n state(): { failures: number; isOpen: boolean; openUntil: number } {\n return {\n failures: this.#failures,\n isOpen: Date.now() < this.#openUntil,\n openUntil: this.#openUntil,\n };\n }\n}\n","/**\n * `MemoryContext` → Mem0 add/search options translation (T5.1).\n *\n * Mem0 keeps `user_id`, `agent_id`, `app_id`, `run_id` orthogonal —\n * we map each `MemoryContext` field onto its native primitive.\n *\n * @internal\n */\n\nimport type { MemoryContext } from \"@theokit/sdk\";\n\ninterface Mem0Options {\n user_id?: string;\n agent_id?: string;\n run_id?: string;\n app_id?: string;\n categories?: string[];\n metadata?: Record<string, unknown>;\n}\n\nexport function toMem0Options(ctx: MemoryContext): Mem0Options {\n const out: Mem0Options = { user_id: ctx.userId };\n if (ctx.agentId !== undefined) out.agent_id = ctx.agentId;\n if (ctx.sessionId !== undefined) out.run_id = ctx.sessionId;\n if (ctx.tenantId !== undefined) out.app_id = ctx.tenantId;\n if (ctx.tags !== undefined) out.categories = ctx.tags;\n if (ctx.metadata !== undefined) out.metadata = ctx.metadata;\n return out;\n}\n","/**\n * Mem0Adapter — `@theokit/memory-mem0` core (T5.1, ADR D141 / D148).\n *\n * Wraps `mem0ai` `MemoryClient` (cloud-only per D148). Implements\n * `MemoryAdapter` with the unique `history(id)` capability — the only\n * adapter today that exposes per-memory versioning.\n *\n * Includes a circuit breaker (EC-K: 5xx counts; 429 does NOT trip).\n *\n * @public\n */\n\nimport {\n extractRawId,\n type MemoryAdapter,\n type MemoryAdapterCapabilities,\n MemoryAdapterError,\n type MemoryContext,\n type MemoryFact,\n type MemoryId,\n type MemoryRevision,\n type MemoryToolSchema,\n type MemoryTurnMessage,\n mkMemoryId,\n} from \"@theokit/sdk\";\nimport MemoryClient from \"mem0ai\";\n\nimport { CircuitBreaker, type CircuitBreakerOptions } from \"./circuit-breaker.js\";\nimport { toMem0Options } from \"./translate.js\";\n\n/**\n * Configuration accepted by the `mem0Memory(...)` factory.\n *\n * @public\n */\nexport interface Mem0AdapterOptions {\n /**\n * Mem0 API key. Genuinely required — `mem0ai` reads no `MEM0_API_KEY` environment variable, so\n * there is no fallback anywhere in the chain.\n *\n * The client is built lazily on the first `write` / `recall`, so a wrong key does not fail\n * `Agent.create`; it surfaces as `MemoryAdapterError(code: \"auth_failed\")` on the first call.\n */\n apiKey: string;\n /** Alternate Mem0 API host. Omit for Mem0 cloud, which is the vendor default. */\n host?: string;\n /** Mem0 organization to scope writes to. Forwarded only when set. */\n organizationId?: string;\n /** Mem0 project to scope writes to. Forwarded only when set. */\n projectId?: string;\n /**\n * Circuit-breaker tuning. Defaults: trip after 5 failures, 2-minute cooldown.\n *\n * The breaker is PER ADAPTER INSTANCE — one `mem0Memory(...)` call, one breaker. Two agents\n * built from two separate factory calls do not share it, so one agent tripping does not\n * protect the other.\n */\n breaker?: CircuitBreakerOptions;\n}\n\nconst ADAPTER_ID = \"mem0\";\n\nconst CAPS: MemoryAdapterCapabilities = {\n history: true, // ← unique to Mem0\n sessions: true,\n tenancy: true,\n reasoning: false,\n toolSchemas: true,\n prefetch: false,\n};\n\n/** @internal */\nexport class Mem0Adapter implements MemoryAdapter {\n readonly id = ADAPTER_ID;\n readonly capabilities = CAPS;\n readonly #opts: Mem0AdapterOptions;\n readonly #breaker: CircuitBreaker;\n #client?: MemoryClient;\n\n constructor(opts: Mem0AdapterOptions) {\n this.#opts = opts;\n this.#breaker = new CircuitBreaker(opts.breaker);\n }\n\n isAvailable(): boolean {\n return typeof this.#opts.apiKey === \"string\" && this.#opts.apiKey.length > 0;\n }\n\n async initialize(): Promise<void> {\n // Lazy: client constructed on first call.\n }\n\n async write(content: string | MemoryTurnMessage[], ctx: MemoryContext): Promise<MemoryId> {\n this.#breaker.ensureClosed(\"write\");\n const messages = this.#toMessages(content);\n if (messages.length === 0) {\n throw new MemoryAdapterError(\"write: empty messages\", {\n adapterId: ADAPTER_ID,\n code: \"invalid_input\",\n });\n }\n try {\n const opts = toMem0Options(ctx);\n const resp = await this.#sdk().add(messages, opts);\n this.#breaker.recordSuccess();\n const first = resp[0];\n const rawId = first?.id ?? `mem0-${Date.now()}`;\n return mkMemoryId(ADAPTER_ID, rawId);\n } catch (err) {\n throw this.#translateError(err, \"write\");\n }\n }\n\n async recall(query: string, ctx: MemoryContext, k = 10): Promise<MemoryFact[]> {\n if (k <= 0) return [];\n this.#breaker.ensureClosed(\"recall\");\n try {\n const opts = toMem0Options(ctx);\n const resp = await this.#sdk().search(query, {\n // Read filter: cross-session recall keyed by user_id (Hermes pattern).\n ...(opts.user_id !== undefined ? { filters: { user_id: opts.user_id } } : {}),\n topK: k,\n rerank: true,\n });\n this.#breaker.recordSuccess();\n const list = Array.isArray(resp) ? resp : ((resp as { results?: unknown[] }).results ?? []);\n return (list as Array<Record<string, unknown>>).map((r) => ({\n id: mkMemoryId(ADAPTER_ID, String(r.id ?? \"\")),\n content: String(r.memory ?? r.content ?? \"\"),\n ...(typeof r.score === \"number\" ? { score: r.score as number } : {}),\n ...(r.createdAt !== undefined ? { createdAt: String(r.createdAt) } : {}),\n ...(r.metadata !== undefined ? { metadata: r.metadata as Record<string, unknown> } : {}),\n }));\n } catch (err) {\n throw this.#translateError(err, \"recall\");\n }\n }\n\n async delete(id: MemoryId): Promise<void> {\n this.#breaker.ensureClosed(\"delete\");\n const rawId = extractRawId(id, ADAPTER_ID);\n try {\n await this.#sdk().delete(rawId);\n this.#breaker.recordSuccess();\n } catch (err) {\n throw this.#translateError(err, \"delete\");\n }\n }\n\n async history(id: MemoryId): Promise<MemoryRevision[]> {\n this.#breaker.ensureClosed(\"history\");\n const rawId = extractRawId(id, ADAPTER_ID);\n try {\n const rows = await this.#sdk().history(rawId);\n this.#breaker.recordSuccess();\n return rows.map((r, i) => {\n const u = (r as unknown as { updatedAt?: unknown }).updatedAt;\n const changedAt =\n u instanceof Date\n ? u.toISOString()\n : typeof u === \"string\"\n ? u\n : new Date().toISOString();\n return {\n id: mkMemoryId(ADAPTER_ID, r.memoryId ?? rawId),\n content: String(r.newMemory ?? r.oldMemory ?? \"\"),\n version: i + 1,\n changedAt,\n };\n });\n } catch (err) {\n throw this.#translateError(err, \"history\");\n }\n }\n\n getToolSchemas(): MemoryToolSchema[] {\n return [\n {\n name: \"memory_write\",\n description:\n \"Persist a turn to Mem0 long-term memory. Server-side extraction populates facts.\",\n parameters: {\n type: \"object\",\n properties: {\n content: { type: \"string\", description: \"Turn text to persist.\" },\n },\n required: [\"content\"],\n },\n },\n {\n name: \"memory_recall\",\n description: \"Retrieve up to k semantically relevant facts from Mem0 (server-side rerank).\",\n parameters: {\n type: \"object\",\n properties: {\n query: { type: \"string\" },\n k: { type: \"integer\", minimum: 1, maximum: 50 },\n },\n required: [\"query\"],\n },\n },\n {\n name: \"memory_history\",\n description:\n \"Retrieve the version history of a specific memory by id. Mem0-unique capability — \" +\n \"shows how a fact has evolved over time (e.g., user changed preferences).\",\n parameters: {\n type: \"object\",\n properties: { memoryId: { type: \"string\" } },\n required: [\"memoryId\"],\n },\n },\n ];\n }\n\n async handleToolCall(\n name: string,\n args: Record<string, unknown>,\n ctx: MemoryContext,\n ): Promise<string> {\n if (name === \"memory_write\") {\n const id = await this.write(String(args.content ?? \"\"), ctx);\n return JSON.stringify({ ok: true, id });\n }\n if (name === \"memory_recall\") {\n const k = typeof args.k === \"number\" ? args.k : 10;\n const facts = await this.recall(String(args.query ?? \"\"), ctx, k);\n return JSON.stringify({ ok: true, facts });\n }\n if (name === \"memory_history\") {\n const rawId = String(args.memoryId ?? \"\");\n const wrapped = rawId.startsWith(`${ADAPTER_ID}:`)\n ? (rawId as MemoryId)\n : mkMemoryId(ADAPTER_ID, rawId);\n const revisions = await this.history(wrapped);\n return JSON.stringify({ ok: true, revisions });\n }\n throw new MemoryAdapterError(`Unknown tool name: ${name}`, {\n adapterId: ADAPTER_ID,\n code: \"invalid_input\",\n });\n }\n\n async shutdown(): Promise<void> {\n this.#client = undefined;\n }\n\n /** Test-only: inspect breaker state. @internal */\n _breakerState(): { failures: number; isOpen: boolean; openUntil: number } {\n return this.#breaker.state();\n }\n\n // ── helpers ────────────────────────────────────────────────────────\n\n #toMessages(\n content: string | MemoryTurnMessage[],\n ): Array<{ role: \"user\" | \"assistant\"; content: string }> {\n if (typeof content === \"string\") {\n return content.trim().length === 0 ? [] : [{ role: \"user\", content }];\n }\n // Mem0 SDK accepts only user/assistant roles. System turns are merged\n // into user content with a \"[system] \" prefix.\n return content\n .filter((m) => m.content.trim().length > 0)\n .map((m) =>\n m.role === \"system\"\n ? { role: \"user\" as const, content: `[system] ${m.content}` }\n : { role: m.role, content: m.content },\n );\n }\n\n #sdk(): MemoryClient {\n if (this.#client === undefined) {\n this.#client = new MemoryClient({\n apiKey: this.#opts.apiKey,\n ...(this.#opts.host !== undefined ? { host: this.#opts.host } : {}),\n ...(this.#opts.organizationId !== undefined\n ? { organizationId: this.#opts.organizationId }\n : {}),\n ...(this.#opts.projectId !== undefined ? { projectId: this.#opts.projectId } : {}),\n });\n }\n return this.#client;\n }\n\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: error-translation ladder maps provider error classes to typed codes + breaker policy (EC-K: 429 does NOT trip); inlining keeps the policy decisions in one place.\n #translateError(err: unknown, op: string): MemoryAdapterError {\n if (err instanceof MemoryAdapterError) {\n if (err.code === \"rate_limited\") {\n // EC-K: do NOT trip breaker on rate limit.\n } else if (\n err.code === \"auth_failed\" ||\n err.code === \"not_found\" ||\n err.code === \"invalid_input\"\n ) {\n // No trip — these are caller-side or stateful conditions.\n } else {\n this.#breaker.recordFailure();\n }\n return err;\n }\n // The real mem0ai SDK does NOT attach `.status`/`.statusCode`/`.response.status` to its\n // thrown errors (verified against mem0ai@3.0.3's `createExceptionFromResponse`, which builds\n // `RateLimitError`/`AuthenticationError`/etc. carrying only `.errorCode` as a string like\n // `\"HTTP_429\"`). Without this fallback, every real vendor error fell through to `status ===\n // undefined` and was misclassified as `code: \"unknown\"` — 429s never got the EC-K rate-limit\n // exemption and 5xx never tripped the breaker. Caught by wire-contract.test.ts running the\n // real SDK; the old hand-written `vi.mock` fabricated `.status` on its thrown errors, which\n // is why this never failed a test.\n const errorCode = (err as { errorCode?: unknown })?.errorCode;\n const statusFromErrorCode =\n typeof errorCode === \"string\" && /^HTTP_(\\d{3})$/.test(errorCode)\n ? Number(errorCode.slice(5))\n : undefined;\n const status =\n (err as { status?: number; statusCode?: number; response?: { status?: number } })?.status ??\n (err as { statusCode?: number })?.statusCode ??\n (err as { response?: { status?: number } })?.response?.status ??\n statusFromErrorCode;\n const message = (err as Error)?.message ?? String(err);\n if (status === 401 || status === 403) {\n return new MemoryAdapterError(`Mem0 auth failed (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"auth_failed\",\n cause: err,\n });\n }\n if (status === 429) {\n // EC-K: rate-limited; do NOT increment breaker.\n return new MemoryAdapterError(`Mem0 rate limited (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"rate_limited\",\n cause: err,\n });\n }\n if (status === 404) {\n return new MemoryAdapterError(`Mem0 not found (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"not_found\",\n cause: err,\n });\n }\n if (typeof status === \"number\" && status >= 500) {\n this.#breaker.recordFailure();\n return new MemoryAdapterError(`Mem0 server error (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"network\",\n cause: err,\n });\n }\n if (status === undefined && message.toLowerCase().includes(\"network\")) {\n this.#breaker.recordFailure();\n return new MemoryAdapterError(`Mem0 network error (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"network\",\n cause: err,\n });\n }\n return new MemoryAdapterError(`Mem0 error (${op}): ${message}`, {\n adapterId: ADAPTER_ID,\n code: \"unknown\",\n cause: err,\n });\n }\n}\n","import { Plugin } from \"@theokit/sdk\";\n\nimport { Mem0Adapter, type Mem0AdapterOptions } from \"./adapter.js\";\n\nexport type { Mem0AdapterOptions } from \"./adapter.js\";\n\n/**\n * Wire Mem0 cloud as the agent's long-term memory.\n *\n * ```ts\n * const agent = await Agent.create({\n * model: { id: \"openai/gpt-4o-mini\" },\n * plugins: [mem0Memory({ apiKey: process.env.MEM0_API_KEY! })],\n * });\n * ```\n *\n * Needs `mem0ai@^3.0.0` — a REQUIRED peer dependency, not an optional one; without it the import\n * throws at load time. Cloud only: `MemoryClient` talks to Mem0's hosted API, and `mem0ai` has no\n * `MEM0_API_KEY` environment fallback, so {@link Mem0AdapterOptions.apiKey} must be supplied.\n *\n * What this adapter gives you that the others do not, and what to watch for:\n *\n * - **`history(id)` works** (`capabilities.history === true`) — it is the only adapter in the\n * ecosystem that exposes per-memory versioning, and it backs the extra `memory_history` tool\n * offered to the model.\n * - **`recall` is CROSS-SESSION on purpose.** Writes carry `run_id = ctx.sessionId`, but the\n * search filter is `user_id` alone, so a recall in session B returns memories written in\n * session A. If you need per-session isolation, use distinct `ctx.userId` values — `sessionId`\n * will not give it to you.\n * - **`recall` defaults to `k = 10`** with server-side rerank; `write` returns the id of the first\n * memory Mem0's server-side extraction produced, which need not be the text you sent.\n * - **`system` turns are rewritten.** Mem0 accepts only `user` / `assistant`, so a\n * `MemoryTurnMessage` with `role: \"system\"` is sent as a `user` turn prefixed with `[system] `.\n *\n * Trap — the circuit breaker reports itself as a RATE LIMIT. After\n * {@link Mem0AdapterOptions.breaker} trips, every call throws\n * `MemoryAdapterError(code: \"rate_limited\")` with a message naming the remaining cooldown, even\n * though the cause was a 5xx or a transport failure and no request was sent. Match on the message,\n * or on the fact that the failure is instantaneous, to tell the two apart.\n *\n * Errors are always `MemoryAdapterError` with `adapterId: \"mem0\"` and one of\n * `auth_failed` (401/403) | `rate_limited` (429 or breaker open) | `not_found` (404) |\n * `network` (5xx, or a status-less error whose message contains \"network\") | `invalid_input` |\n * `unknown` (everything else, including a transport error reported as `\"fetch failed\"`).\n * Both `network` shapes count toward {@link Mem0AdapterOptions.breaker}; `unknown` does not.\n *\n * @public\n */\nexport function mem0Memory(options: Mem0AdapterOptions): Plugin {\n return Plugin.create({\n name: \"@theokit/memory-mem0\",\n version: \"0.1.0\",\n kind: \"memory\",\n createProvider: () => new Mem0Adapter(options),\n });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theokit/memory-mem0",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.4-next.0",
|
|
4
4
|
"description": "Mem0 cloud memory adapter for @theokit/sdk — wraps mem0ai MemoryClient with the MemoryAdapter contract (ADR D141).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
|
+
"homepage": "https://github.com/usetheokit/theokit-sdk#readme",
|
|
7
|
+
"bugs": "https://github.com/usetheokit/theokit-sdk/issues",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/usetheokit/theokit-sdk.git",
|
|
11
|
+
"directory": "packages/memory-mem0"
|
|
12
|
+
},
|
|
6
13
|
"type": "module",
|
|
14
|
+
"sideEffects": false,
|
|
7
15
|
"engines": {
|
|
8
16
|
"node": ">=22.12.0"
|
|
9
17
|
},
|
|
@@ -28,24 +36,23 @@
|
|
|
28
36
|
"LICENSE",
|
|
29
37
|
"CHANGELOG.md"
|
|
30
38
|
],
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"provenance": true,
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
31
43
|
"peerDependencies": {
|
|
32
44
|
"mem0ai": "^3.0.0",
|
|
33
|
-
"@theokit/sdk": "^4.
|
|
45
|
+
"@theokit/sdk": "^4.63.4-next.0"
|
|
34
46
|
},
|
|
35
47
|
"devDependencies": {
|
|
36
48
|
"mem0ai": "^3.0.3",
|
|
37
49
|
"tsup": "^8.5.0",
|
|
38
50
|
"typescript": "^5.8.0",
|
|
39
51
|
"vitest": "^4.1.8",
|
|
40
|
-
"@theokit/sdk": "4.
|
|
41
|
-
},
|
|
42
|
-
"repository": {
|
|
43
|
-
"type": "git",
|
|
44
|
-
"url": "git+https://github.com/usetheodev/theokit-sdk.git",
|
|
45
|
-
"directory": "packages/memory-mem0"
|
|
52
|
+
"@theokit/sdk": "4.63.4-next.0"
|
|
46
53
|
},
|
|
47
54
|
"scripts": {
|
|
48
|
-
"build": "tsup",
|
|
55
|
+
"build": "tsup && node ../../tools/repair-dts-imports.mjs .",
|
|
49
56
|
"typecheck": "tsc --noEmit",
|
|
50
57
|
"test": "vitest run"
|
|
51
58
|
}
|