mnemocyte 0.4.0 → 0.5.1

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/README.md CHANGED
@@ -12,6 +12,8 @@ logs, and duplicate-consolidation tools on top of your existing infrastructure.
12
12
 
13
13
  - In-memory backend for tests and demos.
14
14
  - Postgres + pgvector backend for persistent storage.
15
+ - Caller-owned postgres.js Drizzle instances through
16
+ `mnemocyte/stores/drizzle`.
15
17
  - User-supplied `Embedder` interface.
16
18
  - Hybrid recall with vector similarity, lexical matching, recency, confidence,
17
19
  access count, and importance.
@@ -19,7 +21,9 @@ logs, and duplicate-consolidation tools on top of your existing infrastructure.
19
21
  - Provider retries, per-attempt timeouts, and caller `AbortSignal` cancellation.
20
22
  - Pruning, duplicate detection, audit logs, and experimental consolidation.
21
23
 
22
- Mnemocyte is ESM-only. Use `import`, not CommonJS `require`.
24
+ Mnemocyte ships as ES modules. CommonJS code can load it with `require()` on
25
+ the supported Node versions (22.18 and newer); `require()` returns the
26
+ module's named exports.
23
27
 
24
28
  ## Install
25
29
 
@@ -65,8 +69,8 @@ const context = await client.buildContext({
65
69
  await client.close();
66
70
  ```
67
71
 
68
- When `databaseUrl` is omitted, Mnemocyte uses the in-memory backend.
69
- That backend is intended for development, tests, and prototyping. For
72
+ When both `databaseUrl` and `store` are omitted, Mnemocyte uses the in-memory
73
+ backend. That backend is intended for development, tests, and prototyping. For
70
74
  persistent or larger workloads, use Postgres.
71
75
 
72
76
  ## Embedder
@@ -114,7 +118,21 @@ boundary.
114
118
  ## Postgres
115
119
 
116
120
  For persistent storage, enable pgvector in your Postgres database, apply the
117
- bundled migrations, then pass `databaseUrl`.
121
+ appropriate bundled schema file, then pass `databaseUrl`. The commands below
122
+ use `psql` and assume `DATABASE_URL` points at the target database.
123
+ `-v ON_ERROR_STOP=1 --single-transaction` makes `psql` stop at the first error
124
+ and roll the whole file back, so a failed migration never leaves a partial
125
+ schema.
126
+
127
+ Enable pgvector before applying any Mnemocyte schema file:
128
+
129
+ ```bash
130
+ psql "$DATABASE_URL" -c 'CREATE EXTENSION IF NOT EXISTS vector;'
131
+ ```
132
+
133
+ The database role running that command must be allowed to install the
134
+ extension. Mnemocyte does not create extensions, tables, or indexes from the
135
+ client constructor.
118
136
 
119
137
  ```ts
120
138
  const client = createMnemocyte({
@@ -123,6 +141,42 @@ const client = createMnemocyte({
123
141
  });
124
142
  ```
125
143
 
144
+ Applications that already own a postgres.js Drizzle instance can pass it
145
+ through the `mnemocyte/stores/drizzle` subpath:
146
+
147
+ ```ts
148
+ import { createMnemocyte } from "mnemocyte";
149
+ import { drizzleStore } from "mnemocyte/stores/drizzle";
150
+ import { drizzle } from "drizzle-orm/postgres-js";
151
+ import postgres from "postgres";
152
+ import * as applicationSchema from "./db/schema.js";
153
+
154
+ const sql = postgres(process.env.DATABASE_URL!);
155
+ const db = drizzle(sql, { schema: applicationSchema });
156
+
157
+ const client = createMnemocyte({
158
+ store: drizzleStore(db),
159
+ embedder,
160
+ });
161
+
162
+ try {
163
+ await client.remember({
164
+ entityId: "user_123",
165
+ content: "Uses the application's existing Drizzle connection.",
166
+ });
167
+ } finally {
168
+ await client.close(); // does not close db or sql
169
+ await sql.end(); // the caller retains connection ownership
170
+ }
171
+ ```
172
+
173
+ `drizzleStore(db)` v1 accepts only Drizzle instances backed by postgres.js. It
174
+ uses Mnemocyte's fixed tables in the `public` schema; the bundled migrations
175
+ must already have been applied, and the adapter does not create or migrate
176
+ tables. The caller's Drizzle schema map does not need to include Mnemocyte's
177
+ tables. Supplying both `databaseUrl` and `store` is ambiguous and throws
178
+ synchronously with `MnemocyteError` code `"CONFIG"`.
179
+
126
180
  `databaseUrl` must use the `postgres:` or `postgresql:` protocol. Other URL
127
181
  protocols reject synchronously with `MnemocyteError` code `"CONFIG"`; detailed
128
182
  host, database, and credential validation remains the driver's responsibility.
@@ -130,6 +184,7 @@ host, database, and credential validation remains the driver's responsibility.
130
184
  The package includes:
131
185
 
132
186
  ```txt
187
+ migrations/fresh-install.sql
133
188
  migrations/0000_initial.sql
134
189
  migrations/0001_add_mnemocyte_meta.sql
135
190
  migrations/0002_add_embedding_model.sql
@@ -137,28 +192,44 @@ migrations/0000_initial.sql.template
137
192
  migrations/render-initial.mjs
138
193
  ```
139
194
 
140
- For the default 1536-dimensional schema on a fresh install, apply these in
141
- order:
195
+ For a brand-new installation using the default 1536 dimensions, apply the
196
+ consolidated fresh-install file:
142
197
 
143
- ```txt
144
- migrations/0000_initial.sql
145
- migrations/0001_add_mnemocyte_meta.sql
146
- migrations/0002_add_embedding_model.sql
198
+ ```bash
199
+ psql "$DATABASE_URL" -v ON_ERROR_STOP=1 --single-transaction -f node_modules/mnemocyte/migrations/fresh-install.sql
147
200
  ```
148
201
 
149
- For an existing 0.1.x Postgres install, apply
150
- `migrations/0001_add_mnemocyte_meta.sql` and then
151
- `migrations/0002_add_embedding_model.sql`. Existing 0.2.x or 0.3.x installs
152
- only need `0002_add_embedding_model.sql`.
202
+ `fresh-install.sql` is generated from `0000_initial.sql.template` and combines
203
+ the final empty-database effects of `0000`, `0001`, and `0002`. It is only for
204
+ a brand-new installation and is not part of the Drizzle migration journal.
205
+
206
+ Existing installations must continue to use the numbered migration series.
207
+ The `0000` / `0001` / `0002` files remain the correct upgrade source; do not
208
+ apply `fresh-install.sql` over an existing Mnemocyte schema.
209
+
210
+ For an existing 0.1.x Postgres installation, apply `0001` and then `0002` in
211
+ the same order as before:
212
+
213
+ ```bash
214
+ psql "$DATABASE_URL" -v ON_ERROR_STOP=1 --single-transaction -f node_modules/mnemocyte/migrations/0001_add_mnemocyte_meta.sql
215
+ psql "$DATABASE_URL" -v ON_ERROR_STOP=1 --single-transaction -f node_modules/mnemocyte/migrations/0002_add_embedding_model.sql
216
+ ```
217
+
218
+ For an existing 0.2.x or 0.3.x installation, apply only `0002`:
219
+
220
+ ```bash
221
+ psql "$DATABASE_URL" -v ON_ERROR_STOP=1 --single-transaction -f node_modules/mnemocyte/migrations/0002_add_embedding_model.sql
222
+ ```
153
223
 
154
224
  For a different embedding dimension on a fresh installation, render an explicit
155
- initial migration from the template and apply that rendered file instead of the
156
- default `0000_initial.sql`. The rendered initial migration includes the
157
- matching `mnemocyte_meta` dimensions and the installation-model column, so it
158
- does not also need `0001` or `0002`.
225
+ initial migration from the template, then apply that rendered file instead of
226
+ `fresh-install.sql` or any numbered migration. The rendered initial migration
227
+ includes the matching `mnemocyte_meta` dimensions and the installation-model
228
+ column, so it does not also need `0000`, `0001`, or `0002`.
159
229
 
160
230
  ```bash
161
231
  node node_modules/mnemocyte/migrations/render-initial.mjs --dimensions 768 --out migrations/0000_initial.768.sql
232
+ psql "$DATABASE_URL" -v ON_ERROR_STOP=1 --single-transaction -f migrations/0000_initial.768.sql
162
233
  ```
163
234
 
164
235
  Inside this repository, the equivalent development shortcut is:
@@ -429,7 +500,15 @@ requested loser already points to a different survivor, the call rejects with
429
500
  `"CONFLICT"`. Mixed batches are atomic: no newly eligible loser is changed, no
430
501
  tags are merged, and no consolidation audit event is written when any item
431
502
  conflicts. Concurrent calls follow the same target-specific rule in both
432
- backends.
503
+ backends. `supersededIds` must contain distinct IDs; duplicates reject with
504
+ `"VALIDATION"` before either store is accessed.
505
+
506
+ The store re-reads and protects the survivor in the same atomic boundary as
507
+ the loser updates, tag merge, and enabled audit events. If the survivor is
508
+ deleted or becomes superseded after initial validation but before that
509
+ boundary, the call rejects with `"CONFLICT"` without a partial mutation. Tag
510
+ merges start from the survivor's state inside that boundary, so concurrent
511
+ successful consolidations preserve every committed tag.
433
512
 
434
513
  The survivor cannot later be deleted while any such reference remains:
435
514
  `forget`, `forgetAll`, and matching non-dry-run `prune` calls reject with
@@ -521,125 +600,27 @@ must be positive finite numbers, and `candidateMultiplier` must be an integer
521
600
  of at least 1. Invalid tuning is rejected at client construction with
522
601
  `MnemocyteError` code `"CONFIG"`.
523
602
 
524
- ## Roadmap
525
-
526
- Planned larger milestones:
527
-
528
- - public `MemoryStore` adapter surface
529
- - `drizzleStore(db)` for caller-owned Drizzle clients
530
- - `@mnemocyte/mcp`
531
-
532
- See [ROADMAP.md](./docs/ROADMAP.md).
533
-
534
- ## Pre-v1 Notes
535
-
536
- Current behavior:
537
-
538
- - `createMnemocyte()` selects either the in-memory backend or the
539
- Postgres/pgvector backend.
540
- - Both backends run through an internal `MemoryStore` boundary and shared
541
- client orchestration; `MemoryStore` is not exported as a public adapter API
542
- yet.
543
- - Postgres schema setup is explicit; the client does not create tables or
544
- indexes for you.
545
- - `findDuplicates`, audit-log workflows, and `experimental.consolidate` are
546
- available before v1 but still subject to API refinement.
547
-
548
- Known limitations before v1:
549
-
550
- - The internal `MemoryStore` boundary is not a public adapter API yet.
551
- `drizzleStore(db)` is the planned first public store adapter.
552
- - Configured provider timeouts abort the per-attempt `AbortSignal`; the
553
- underlying provider request only stops promptly when the embedder honors that
554
- signal.
555
- - Postgres model and dimension metadata are installation-wide. Mixed embedding
556
- vector spaces in one database are intentionally unsupported.
557
-
558
- Planned v1 direction:
559
-
560
- - Keep storage adapters behind `MemoryStore` while shared core code owns
561
- validation, embedding, scoring, observability, resilience, and context
562
- building.
563
- - Keep root `mnemocyte` imports provider-SDK-free.
564
- - Keep migrations, dimensions, and production index choices explicit.
565
-
566
- ## Development
567
-
568
- ### Prerequisites
569
-
570
- - Node.js 22.18 or newer. CI tests the minimum 22.18 release and Node 24.
571
- - pnpm 11.1.1, matching the `packageManager` field in `package.json`.
572
- - Postgres with pgvector only when you want to run the integration suite.
573
-
574
- Clone the repository and install its locked dependencies:
575
-
576
- ```bash
577
- git clone https://github.com/Meenic/mnemocyte.git
578
- cd mnemocyte
579
- pnpm install --frozen-lockfile
580
- ```
581
-
582
- Mnemocyte is a library, not a standalone server. Use the quick-start example
583
- from a consuming TypeScript project, or run the repository build in watch mode
584
- while developing:
585
-
586
- ```bash
587
- pnpm dev
588
- ```
589
-
590
- Create the publishable ESM artifacts in `dist/` with:
591
-
592
- ```bash
593
- pnpm build
594
- ```
595
-
596
- ### Validation
597
-
598
- Run the same main gates used by CI before committing:
599
-
600
- ```bash
601
- pnpm checktypes
602
- pnpm lint
603
- pnpm test
604
- pnpm run pack:check
605
- ```
606
-
607
- `pnpm test` builds the package, runs unit behavior, verifies package exports,
608
- and type-checks the public declarations. `pnpm lint` is a read-only formatting,
609
- lint, and import-order check; use `pnpm lint:fix` to apply its safe fixes. The
610
- Postgres suite is separate:
611
-
612
- ```bash
613
- DATABASE_URL=postgres://... pnpm run test:integration
614
- ```
615
-
616
- On PowerShell, set the environment variable for the current process first:
617
-
618
- ```powershell
619
- $env:DATABASE_URL = "postgres://..."
620
- pnpm run test:integration
621
- ```
622
-
623
- `test:integration` skips when `DATABASE_URL` is not set. The database must have
624
- pgvector available; the test applies the bundled migrations.
603
+ ## Limitations
625
604
 
626
- ### Where changes belong
605
+ Mnemocyte is pre-1.0. Today:
627
606
 
628
- - Public exports and types: `src/index.ts`, `src/types.ts`, and `src/errors.ts`.
629
- - Shared client behavior: `src/memory/client-core.ts`; backend mechanics stay
630
- in `src/memory/in-memory.ts` or `src/memory/postgres.ts`.
631
- - Postgres schema and SQL: `src/db/schema.ts` and `src/db/queries/`. Schema
632
- changes require an explicit file under `migrations/`.
633
- - Provider helpers: `src/embedders/`; keep the root package provider-SDK-free.
634
- - Retrieval and context rendering: `src/retrieval/` and `src/context/`.
635
- - Tests: mirror the affected responsibility under `test/`; package boundary
636
- checks live under `test/package/`, and real Postgres coverage under
637
- `test/integration/`.
607
+ - Postgres stores one embedding model and dimension per installation; mixed
608
+ vector spaces in one database are not supported.
609
+ - The bundled HNSW index supports at most 2,000 dimensions. Rendering a
610
+ larger dimension produces a migration that fails at `CREATE INDEX`.
611
+ - `drizzleStore(db)` supports only postgres.js-backed Drizzle instances, the
612
+ `public` schema and pre-applied migrations.
613
+ - Without `entityId`, `prune` applies to every entity in the database.
614
+ - `forgetAll` rejects with `"CONFLICT"` after a consolidation until the
615
+ superseded memories are pruned first (`prune({ entityId, superseded: true
616
+ })`).
617
+ - Provider timeouts abort the attempt's `AbortSignal`; the request stops
618
+ promptly only if the embedder forwards that signal.
638
619
 
639
- See [AGENTS.md](./AGENTS.md) for repository rules and the validation/release
640
- policy. Read [ARCHITECTURE.md](./docs/ARCHITECTURE.md) before changing module
641
- boundaries or the public surface.
620
+ The planned 0.6 release changes the API; see the
621
+ [roadmap](./docs/ROADMAP.md).
642
622
 
643
- ## Architecture
623
+ ## Contributing
644
624
 
645
- See [ARCHITECTURE.md](./docs/ARCHITECTURE.md).
625
+ See [docs/DEVELOPMENT.md](./docs/DEVELOPMENT.md) for setup, structure,
626
+ testing and releases, and [AGENTS.md](./AGENTS.md) for repository rules.
@@ -1,2 +1 @@
1
- import { openaiEmbedder } from "./openai.mjs";
2
- export { openaiEmbedder };
1
+ export { openaiEmbedder } from "./openai.mjs";
@@ -1,7 +1,5 @@
1
- import { l as Embedder } from "../types-DH0inEay.mjs";
2
-
3
- //#region src/embedders/openai.d.ts
4
- interface OpenAIEmbedderOptions {
1
+ import { l as Embedder } from "../types-DXYtLiOT.mjs";
2
+ export interface OpenAIEmbedderOptions {
5
3
  /**
6
4
  * OpenAI API key. Defaults to `process.env.OPENAI_API_KEY`.
7
5
  */
@@ -25,7 +23,4 @@ interface OpenAIEmbedderOptions {
25
23
  * Create an OpenAI-backed {@link Embedder}. This adapter uses `fetch`
26
24
  * directly so provider SDKs never become part of Mnemocyte's dependency graph.
27
25
  */
28
- declare function openaiEmbedder(options: OpenAIEmbedderOptions): Embedder;
29
- //#endregion
30
- export { OpenAIEmbedderOptions, openaiEmbedder };
31
- //# sourceMappingURL=openai.d.mts.map
26
+ export declare function openaiEmbedder(options: OpenAIEmbedderOptions): Embedder;
@@ -1,11 +1,11 @@
1
- import { t as MnemocyteError } from "../errors-B_7ZdjEO.mjs";
2
- //#region src/embedders/openai.ts
1
+ import { t as MnemocyteError } from "../errors-Dgt2nAs1.mjs";
2
+ // src/embedders/openai.ts
3
3
  const KNOWN_MODEL_DIMENSIONS = {
4
4
  "text-embedding-3-small": 1536,
5
5
  "text-embedding-3-large": 3072,
6
6
  "text-embedding-ada-002": 1536
7
7
  };
8
- const CONFIGURABLE_DIMENSION_MODELS = new Set(["text-embedding-3-small", "text-embedding-3-large"]);
8
+ const CONFIGURABLE_DIMENSION_MODELS = /* @__PURE__ */ new Set(["text-embedding-3-small", "text-embedding-3-large"]);
9
9
  function isRecord(value) {
10
10
  return typeof value === "object" && value !== null && !Array.isArray(value);
11
11
  }
@@ -87,7 +87,6 @@ function openaiEmbedder(options) {
87
87
  }
88
88
  };
89
89
  }
90
- //#endregion
91
90
  export { openaiEmbedder };
92
91
 
93
92
  //# sourceMappingURL=openai.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"openai.mjs","names":[],"sources":["../../src/embedders/openai.ts"],"sourcesContent":["import { MnemocyteError } from \"../errors.js\";\nimport type { Embedder } from \"../types.js\";\n\nconst KNOWN_MODEL_DIMENSIONS: Record<string, number> = {\n\t\"text-embedding-3-small\": 1536,\n\t\"text-embedding-3-large\": 3072,\n\t\"text-embedding-ada-002\": 1536,\n};\n\nconst CONFIGURABLE_DIMENSION_MODELS = new Set([\n\t\"text-embedding-3-small\",\n\t\"text-embedding-3-large\",\n]);\n\nexport interface OpenAIEmbedderOptions {\n\t/**\n\t * OpenAI API key. Defaults to `process.env.OPENAI_API_KEY`.\n\t */\n\treadonly apiKey?: string;\n\t/**\n\t * OpenAI embedding model name.\n\t */\n\treadonly model: string;\n\t/**\n\t * Output dimensions. Required for unknown/future model names and accepted\n\t * only for OpenAI models that support configurable dimensions.\n\t */\n\treadonly dimensions?: number;\n\t/**\n\t * Override the OpenAI API base URL. Intended for tests and compatible\n\t * deployments; defaults to `https://api.openai.com/v1`.\n\t */\n\treadonly baseUrl?: string;\n}\n\ninterface OpenAIEmbeddingItem {\n\treadonly embedding: number[];\n\treadonly index: number;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validateEmbeddingResponse(\n\tbody: unknown,\n\texpectedCount: number,\n): OpenAIEmbeddingItem[] {\n\tif (!isRecord(body) || !Array.isArray(body.data)) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"OpenAI returned malformed embedding response data.\",\n\t\t\t\"EMBEDDING\",\n\t\t);\n\t}\n\tif (body.data.length !== expectedCount) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"OpenAI returned an unexpected number of embeddings.\",\n\t\t\t\"EMBEDDING\",\n\t\t);\n\t}\n\n\tconst indices = new Set<number>();\n\tconst items: OpenAIEmbeddingItem[] = [];\n\tfor (const item of body.data) {\n\t\tif (!isRecord(item)) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t\"OpenAI returned a malformed embedding item.\",\n\t\t\t\t\"EMBEDDING\",\n\t\t\t);\n\t\t}\n\t\tconst { embedding, index } = item;\n\t\tif (\n\t\t\ttypeof index !== \"number\" ||\n\t\t\t!Number.isInteger(index) ||\n\t\t\tindex < 0 ||\n\t\t\tindex >= expectedCount\n\t\t) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t\"OpenAI returned an embedding with an invalid index.\",\n\t\t\t\t\"EMBEDDING\",\n\t\t\t);\n\t\t}\n\t\tif (indices.has(index)) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t\"OpenAI returned a duplicate embedding index.\",\n\t\t\t\t\"EMBEDDING\",\n\t\t\t);\n\t\t}\n\t\tif (!Array.isArray(embedding)) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t\"OpenAI returned an embedding that is not an array.\",\n\t\t\t\t\"EMBEDDING\",\n\t\t\t);\n\t\t}\n\t\tindices.add(index);\n\t\titems.push({ embedding: embedding as number[], index });\n\t}\n\treturn items;\n}\n\nfunction assertDimensions(dimensions: number): void {\n\tif (!Number.isInteger(dimensions) || dimensions < 1) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"openaiEmbedder dimensions must be a positive integer.\",\n\t\t\t\"CONFIG\",\n\t\t);\n\t}\n}\n\nfunction resolveApiKey(apiKey: string | undefined): string {\n\tconst resolved = apiKey ?? process.env.OPENAI_API_KEY;\n\tif (!resolved || resolved.trim().length === 0) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"openaiEmbedder requires an API key. Pass apiKey or set OPENAI_API_KEY.\",\n\t\t\t\"CONFIG\",\n\t\t);\n\t}\n\treturn resolved;\n}\n\nfunction resolveDimensions(options: OpenAIEmbedderOptions): {\n\tembedderDimensions: number;\n\trequestDimensions?: number;\n} {\n\tconst defaultDimensions = KNOWN_MODEL_DIMENSIONS[options.model];\n\tif (defaultDimensions === undefined) {\n\t\tif (options.dimensions === undefined) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t`openaiEmbedder requires dimensions for unknown model \"${options.model}\".`,\n\t\t\t\t\"CONFIG\",\n\t\t\t);\n\t\t}\n\t\tassertDimensions(options.dimensions);\n\t\treturn {\n\t\t\tembedderDimensions: options.dimensions,\n\t\t\trequestDimensions: options.dimensions,\n\t\t};\n\t}\n\n\tif (\n\t\toptions.dimensions !== undefined &&\n\t\t!CONFIGURABLE_DIMENSION_MODELS.has(options.model)\n\t) {\n\t\tthrow new MnemocyteError(\n\t\t\t`openaiEmbedder does not support a dimensions override for \"${options.model}\".`,\n\t\t\t\"CONFIG\",\n\t\t);\n\t}\n\n\tif (options.dimensions !== undefined) {\n\t\tassertDimensions(options.dimensions);\n\t\treturn {\n\t\t\tembedderDimensions: options.dimensions,\n\t\t\trequestDimensions: options.dimensions,\n\t\t};\n\t}\n\n\treturn { embedderDimensions: defaultDimensions };\n}\n\n/**\n * Create an OpenAI-backed {@link Embedder}. This adapter uses `fetch`\n * directly so provider SDKs never become part of Mnemocyte's dependency graph.\n */\nexport function openaiEmbedder(options: OpenAIEmbedderOptions): Embedder {\n\tconst apiKey = resolveApiKey(options.apiKey);\n\tconst { embedderDimensions, requestDimensions } = resolveDimensions(options);\n\tconst baseUrl = options.baseUrl ?? \"https://api.openai.com/v1\";\n\n\treturn {\n\t\tmodel: options.model,\n\t\tdimensions: embedderDimensions,\n\t\tasync embed(texts, embedOptions) {\n\t\t\tconst response = await fetch(`${baseUrl}/embeddings`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tauthorization: `Bearer ${apiKey}`,\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tmodel: options.model,\n\t\t\t\t\tinput: [...texts],\n\t\t\t\t\tencoding_format: \"float\",\n\t\t\t\t\t...(requestDimensions === undefined\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: { dimensions: requestDimensions }),\n\t\t\t\t}),\n\t\t\t\t...(embedOptions?.signal === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { signal: embedOptions.signal }),\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow Object.assign(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`OpenAI embeddings request failed with status ${response.status}.`,\n\t\t\t\t\t),\n\t\t\t\t\t{ status: response.status },\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst items = validateEmbeddingResponse(\n\t\t\t\tawait response.json(),\n\t\t\t\ttexts.length,\n\t\t\t);\n\t\t\treturn items\n\t\t\t\t.sort((left, right) => left.index - right.index)\n\t\t\t\t.map((item) => item.embedding);\n\t\t},\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"openai.mjs","names":[],"sources":["../../src/embedders/openai.ts"],"sourcesContent":["import { MnemocyteError } from \"../errors.js\";\nimport type { Embedder } from \"../types.js\";\n\nconst KNOWN_MODEL_DIMENSIONS: Record<string, number> = {\n\t\"text-embedding-3-small\": 1536,\n\t\"text-embedding-3-large\": 3072,\n\t\"text-embedding-ada-002\": 1536,\n};\n\nconst CONFIGURABLE_DIMENSION_MODELS = new Set([\n\t\"text-embedding-3-small\",\n\t\"text-embedding-3-large\",\n]);\n\nexport interface OpenAIEmbedderOptions {\n\t/**\n\t * OpenAI API key. Defaults to `process.env.OPENAI_API_KEY`.\n\t */\n\treadonly apiKey?: string;\n\t/**\n\t * OpenAI embedding model name.\n\t */\n\treadonly model: string;\n\t/**\n\t * Output dimensions. Required for unknown/future model names and accepted\n\t * only for OpenAI models that support configurable dimensions.\n\t */\n\treadonly dimensions?: number;\n\t/**\n\t * Override the OpenAI API base URL. Intended for tests and compatible\n\t * deployments; defaults to `https://api.openai.com/v1`.\n\t */\n\treadonly baseUrl?: string;\n}\n\ninterface OpenAIEmbeddingItem {\n\treadonly embedding: number[];\n\treadonly index: number;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validateEmbeddingResponse(\n\tbody: unknown,\n\texpectedCount: number,\n): OpenAIEmbeddingItem[] {\n\tif (!isRecord(body) || !Array.isArray(body.data)) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"OpenAI returned malformed embedding response data.\",\n\t\t\t\"EMBEDDING\",\n\t\t);\n\t}\n\tif (body.data.length !== expectedCount) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"OpenAI returned an unexpected number of embeddings.\",\n\t\t\t\"EMBEDDING\",\n\t\t);\n\t}\n\n\tconst indices = new Set<number>();\n\tconst items: OpenAIEmbeddingItem[] = [];\n\tfor (const item of body.data) {\n\t\tif (!isRecord(item)) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t\"OpenAI returned a malformed embedding item.\",\n\t\t\t\t\"EMBEDDING\",\n\t\t\t);\n\t\t}\n\t\tconst { embedding, index } = item;\n\t\tif (\n\t\t\ttypeof index !== \"number\" ||\n\t\t\t!Number.isInteger(index) ||\n\t\t\tindex < 0 ||\n\t\t\tindex >= expectedCount\n\t\t) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t\"OpenAI returned an embedding with an invalid index.\",\n\t\t\t\t\"EMBEDDING\",\n\t\t\t);\n\t\t}\n\t\tif (indices.has(index)) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t\"OpenAI returned a duplicate embedding index.\",\n\t\t\t\t\"EMBEDDING\",\n\t\t\t);\n\t\t}\n\t\tif (!Array.isArray(embedding)) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t\"OpenAI returned an embedding that is not an array.\",\n\t\t\t\t\"EMBEDDING\",\n\t\t\t);\n\t\t}\n\t\tindices.add(index);\n\t\titems.push({ embedding: embedding as number[], index });\n\t}\n\treturn items;\n}\n\nfunction assertDimensions(dimensions: number): void {\n\tif (!Number.isInteger(dimensions) || dimensions < 1) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"openaiEmbedder dimensions must be a positive integer.\",\n\t\t\t\"CONFIG\",\n\t\t);\n\t}\n}\n\nfunction resolveApiKey(apiKey: string | undefined): string {\n\tconst resolved = apiKey ?? process.env.OPENAI_API_KEY;\n\tif (!resolved || resolved.trim().length === 0) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"openaiEmbedder requires an API key. Pass apiKey or set OPENAI_API_KEY.\",\n\t\t\t\"CONFIG\",\n\t\t);\n\t}\n\treturn resolved;\n}\n\nfunction resolveDimensions(options: OpenAIEmbedderOptions): {\n\tembedderDimensions: number;\n\trequestDimensions?: number;\n} {\n\tconst defaultDimensions = KNOWN_MODEL_DIMENSIONS[options.model];\n\tif (defaultDimensions === undefined) {\n\t\tif (options.dimensions === undefined) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t`openaiEmbedder requires dimensions for unknown model \"${options.model}\".`,\n\t\t\t\t\"CONFIG\",\n\t\t\t);\n\t\t}\n\t\tassertDimensions(options.dimensions);\n\t\treturn {\n\t\t\tembedderDimensions: options.dimensions,\n\t\t\trequestDimensions: options.dimensions,\n\t\t};\n\t}\n\n\tif (\n\t\toptions.dimensions !== undefined &&\n\t\t!CONFIGURABLE_DIMENSION_MODELS.has(options.model)\n\t) {\n\t\tthrow new MnemocyteError(\n\t\t\t`openaiEmbedder does not support a dimensions override for \"${options.model}\".`,\n\t\t\t\"CONFIG\",\n\t\t);\n\t}\n\n\tif (options.dimensions !== undefined) {\n\t\tassertDimensions(options.dimensions);\n\t\treturn {\n\t\t\tembedderDimensions: options.dimensions,\n\t\t\trequestDimensions: options.dimensions,\n\t\t};\n\t}\n\n\treturn { embedderDimensions: defaultDimensions };\n}\n\n/**\n * Create an OpenAI-backed {@link Embedder}. This adapter uses `fetch`\n * directly so provider SDKs never become part of Mnemocyte's dependency graph.\n */\nexport function openaiEmbedder(options: OpenAIEmbedderOptions): Embedder {\n\tconst apiKey = resolveApiKey(options.apiKey);\n\tconst { embedderDimensions, requestDimensions } = resolveDimensions(options);\n\tconst baseUrl = options.baseUrl ?? \"https://api.openai.com/v1\";\n\n\treturn {\n\t\tmodel: options.model,\n\t\tdimensions: embedderDimensions,\n\t\tasync embed(texts, embedOptions) {\n\t\t\tconst response = await fetch(`${baseUrl}/embeddings`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tauthorization: `Bearer ${apiKey}`,\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tmodel: options.model,\n\t\t\t\t\tinput: [...texts],\n\t\t\t\t\tencoding_format: \"float\",\n\t\t\t\t\t...(requestDimensions === undefined\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: { dimensions: requestDimensions }),\n\t\t\t\t}),\n\t\t\t\t...(embedOptions?.signal === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { signal: embedOptions.signal }),\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow Object.assign(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`OpenAI embeddings request failed with status ${response.status}.`,\n\t\t\t\t\t),\n\t\t\t\t\t{ status: response.status },\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst items = validateEmbeddingResponse(\n\t\t\t\tawait response.json(),\n\t\t\t\ttexts.length,\n\t\t\t);\n\t\t\treturn items\n\t\t\t\t.sort((left, right) => left.index - right.index)\n\t\t\t\t.map((item) => item.embedding);\n\t\t},\n\t};\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- //#region src/errors.ts
1
+ // src/errors.ts
2
2
  /**
3
3
  * Error type thrown by every public Mnemocyte API.
4
4
  *
@@ -48,7 +48,6 @@ var MnemocyteError = class extends Error {
48
48
  function isMnemocyteError(error) {
49
49
  return error instanceof MnemocyteError;
50
50
  }
51
- //#endregion
52
51
  export { isMnemocyteError as n, MnemocyteError as t };
53
52
 
54
- //# sourceMappingURL=errors-B_7ZdjEO.mjs.map
53
+ //# sourceMappingURL=errors-Dgt2nAs1.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors-B_7ZdjEO.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Stable, machine-readable error code attached to every {@link MnemocyteError}.\n *\n * - `\"CONFIG\"` — invalid client configuration (e.g. missing or malformed embedder).\n * - `\"VALIDATION\"` — invalid argument passed to a client method.\n * - `\"DB\"` — Postgres or driver-level failure.\n * - `\"EMBEDDING\"` — embedder threw or returned an invalid vector.\n * - `\"NOT_FOUND\"` — referenced memory or entity does not exist.\n * - `\"CONFLICT\"` — the requested mutation conflicts with stored relationships.\n * - `\"MIGRATION\"` — schema/migration check failed against the target database.\n * - `\"TIMEOUT\"` — a provider call exceeded its configured timeout.\n * - `\"ABORTED\"` — the operation was cancelled via an `AbortSignal`.\n */\nexport type MnemocyteErrorCode =\n\t| \"CONFIG\"\n\t| \"VALIDATION\"\n\t| \"DB\"\n\t| \"EMBEDDING\"\n\t| \"NOT_FOUND\"\n\t| \"CONFLICT\"\n\t| \"MIGRATION\"\n\t| \"TIMEOUT\"\n\t| \"ABORTED\";\n\n/**\n * Error type thrown by every public Mnemocyte API.\n *\n * Use the {@link MnemocyteError.code} property — not the message — to branch\n * on failure modes, or call {@link isMnemocyteError} as a type guard when\n * working with `unknown` errors.\n *\n * @example\n * ```ts\n * try {\n * await client.recall({ entityId: \"u1\", query: \"hi\" });\n * } catch (err) {\n * if (isMnemocyteError(err) && err.code === \"DB\") {\n * // handle database failure\n * }\n * throw err;\n * }\n * ```\n */\nexport class MnemocyteError extends Error {\n\t/** Stable, machine-readable failure code. See {@link MnemocyteErrorCode}. */\n\treadonly code: MnemocyteErrorCode;\n\t/** Underlying cause, if any (e.g. an original driver or embedder error). */\n\toverride readonly cause?: unknown;\n\n\t/**\n\t * @param message - Human-readable error message.\n\t * @param code - Stable failure code; see {@link MnemocyteErrorCode}.\n\t * @param cause - Optional underlying cause (driver error, network error, etc.).\n\t */\n\tconstructor(message: string, code: MnemocyteErrorCode, cause?: unknown) {\n\t\tsuper(message);\n\t\tthis.name = \"MnemocyteError\";\n\t\tthis.code = code;\n\t\tthis.cause = cause;\n\t}\n}\n\n/**\n * Type guard for {@link MnemocyteError}.\n *\n * This guard uses `instanceof` and recognizes errors created by the same loaded\n * Mnemocyte class. It does not recognize structurally similar errors or errors\n * created by another installed copy of the package.\n *\n * @param error - Value to test (typically a caught `unknown`).\n * @returns `true` if `error` is a {@link MnemocyteError}.\n */\nexport function isMnemocyteError(error: unknown): error is MnemocyteError {\n\treturn error instanceof MnemocyteError;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA2CA,IAAa,iBAAb,cAAoC,MAAM;;CAEzC;;CAEA;;;;;;CAOA,YAAY,SAAiB,MAA0B,OAAiB;EACvE,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,KAAK,QAAQ;CACd;AACD;;;;;;;;;;;AAYA,SAAgB,iBAAiB,OAAyC;CACzE,OAAO,iBAAiB;AACzB"}
1
+ {"version":3,"file":"errors-Dgt2nAs1.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Stable, machine-readable error code attached to every {@link MnemocyteError}.\n *\n * - `\"CONFIG\"` — invalid client configuration (e.g. missing or malformed embedder).\n * - `\"VALIDATION\"` — invalid argument passed to a client method.\n * - `\"DB\"` — Postgres or driver-level failure.\n * - `\"EMBEDDING\"` — embedder threw or returned an invalid vector.\n * - `\"NOT_FOUND\"` — referenced memory or entity does not exist.\n * - `\"CONFLICT\"` — the requested mutation conflicts with stored relationships.\n * - `\"MIGRATION\"` — schema/migration check failed against the target database.\n * - `\"TIMEOUT\"` — a provider call exceeded its configured timeout.\n * - `\"ABORTED\"` — the operation was cancelled via an `AbortSignal`.\n */\nexport type MnemocyteErrorCode =\n\t| \"CONFIG\"\n\t| \"VALIDATION\"\n\t| \"DB\"\n\t| \"EMBEDDING\"\n\t| \"NOT_FOUND\"\n\t| \"CONFLICT\"\n\t| \"MIGRATION\"\n\t| \"TIMEOUT\"\n\t| \"ABORTED\";\n\n/**\n * Error type thrown by every public Mnemocyte API.\n *\n * Use the {@link MnemocyteError.code} property — not the message — to branch\n * on failure modes, or call {@link isMnemocyteError} as a type guard when\n * working with `unknown` errors.\n *\n * @example\n * ```ts\n * try {\n * await client.recall({ entityId: \"u1\", query: \"hi\" });\n * } catch (err) {\n * if (isMnemocyteError(err) && err.code === \"DB\") {\n * // handle database failure\n * }\n * throw err;\n * }\n * ```\n */\nexport class MnemocyteError extends Error {\n\t/** Stable, machine-readable failure code. See {@link MnemocyteErrorCode}. */\n\treadonly code: MnemocyteErrorCode;\n\t/** Underlying cause, if any (e.g. an original driver or embedder error). */\n\toverride readonly cause?: unknown;\n\n\t/**\n\t * @param message - Human-readable error message.\n\t * @param code - Stable failure code; see {@link MnemocyteErrorCode}.\n\t * @param cause - Optional underlying cause (driver error, network error, etc.).\n\t */\n\tconstructor(message: string, code: MnemocyteErrorCode, cause?: unknown) {\n\t\tsuper(message);\n\t\tthis.name = \"MnemocyteError\";\n\t\tthis.code = code;\n\t\tthis.cause = cause;\n\t}\n}\n\n/**\n * Type guard for {@link MnemocyteError}.\n *\n * This guard uses `instanceof` and recognizes errors created by the same loaded\n * Mnemocyte class. It does not recognize structurally similar errors or errors\n * created by another installed copy of the package.\n *\n * @param error - Value to test (typically a caught `unknown`).\n * @returns `true` if `error` is a {@link MnemocyteError}.\n */\nexport function isMnemocyteError(error: unknown): error is MnemocyteError {\n\treturn error instanceof MnemocyteError;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA2CA,IAAa,iBAAb,cAAoC,MAAM;;CAEzC;;CAEA;;;;;;CAOA,YAAY,SAAiB,MAA0B,OAAiB;EACvE,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,KAAK,QAAQ;CACd;AACD;;;;;;;;;;;AAYA,SAAgB,iBAAiB,OAAyC;CACzE,OAAO,iBAAiB;AACzB"}
package/dist/index.d.mts CHANGED
@@ -1,24 +1,24 @@
1
- import { A as PruneResult, C as MnemocyteConfig, D as ObservabilityConfig, E as MnemocyteOperation, F as RetrievalExplanation, I as RetrievalScoreWeights, L as RetrievalScores, M as RememberInput, N as RememberManyInput, O as ProviderResilienceConfig, P as RetrievalConfig, R as TokenCounter, S as MnemocyteClient, T as MnemocyteObservationPhase, _ as ListAuditLogInput, a as ConsolidateInput, b as MemoryWithScore, c as DuplicatePair, d as ExperimentalMnemocyteClient, f as FindDuplicatesInput, g as JsonValue, h as JsonObject, i as BuildContextInput, j as RecallInput, k as PruneInput, l as Embedder, m as ImportanceLevel, n as AuditEvent, o as ConsolidateResult, p as GlobalStats, r as AuditLogCursor, s as ContextFormat, t as AuditConfig, u as EntityStats, v as Memory, w as MnemocyteObservation, x as MnemocyteBackend, y as MemoryType } from "./types-DH0inEay.mjs";
2
-
3
- //#region src/client.d.ts
1
+ import { A as PruneInput, C as MnemocyteConfig, D as MnemocyteStoreConfig, E as MnemocyteOperation, F as RetrievalConfig, I as RetrievalExplanation, L as RetrievalScoreWeights, M as RecallInput, N as RememberInput, O as ObservabilityConfig, P as RememberManyInput, R as RetrievalScores, S as MnemocyteClient, T as MnemocyteObservationPhase, _ as ListAuditLogInput, a as ConsolidateInput, b as MemoryWithScore, c as DuplicatePair, d as ExperimentalMnemocyteClient, f as FindDuplicatesInput, g as JsonValue, h as JsonObject, i as BuildContextInput, j as PruneResult, k as ProviderResilienceConfig, l as Embedder, m as ImportanceLevel, n as AuditEvent, o as ConsolidateResult, p as GlobalStats, r as AuditLogCursor, s as ContextFormat, t as AuditConfig, u as EntityStats, v as Memory, w as MnemocyteObservation, x as MnemocyteBackend, y as MemoryType, z as TokenCounter } from "./types-DXYtLiOT.mjs";
4
2
  /**
5
3
  * Create a Mnemocyte client.
6
4
  *
7
- * When {@link MnemocyteConfig.databaseUrl} is provided, a Postgres-backed
8
- * client is returned (requires the `pgvector` extension and the bundled
9
- * migration applied). Otherwise an in-memory client is returned, intended
10
- * for tests, demos, and short-lived processes.
5
+ * When {@link MnemocyteConfig.store} is provided, that adapter is used. When
6
+ * {@link MnemocyteConfig.databaseUrl} is provided, a URL-owned Postgres client
7
+ * is used (requires the `pgvector` extension and the bundled migrations).
8
+ * When neither is supplied, an in-memory client is returned for tests, demos,
9
+ * and short-lived processes.
11
10
  *
12
- * The returned client owns any underlying resources (e.g. the Postgres
13
- * connection pool). Call {@link MnemocyteClient.close} when finished to
14
- * release them.
11
+ * Call {@link MnemocyteClient.close} when finished. URL-created database
12
+ * resources are owned and closed by Mnemocyte; resources behind a supplied
13
+ * store retain the ownership policy documented by that adapter.
15
14
  *
16
15
  * @param config - Client configuration. {@link MnemocyteConfig.embedder} is required.
17
16
  * @returns A {@link MnemocyteClient} instance.
18
17
  * @throws {MnemocyteError} With code `"CONFIG"` if `embedder`, retrieval
19
18
  * tuning, provider resilience, or the database URL is malformed or does not
20
- * use the `postgres:` / `postgresql:` protocol, or `"VALIDATION"` if
21
- * `databaseUrl` is explicitly empty.
19
+ * use the `postgres:` / `postgresql:` protocol, or if `databaseUrl` and
20
+ * `store` are both provided; or `"VALIDATION"` if `databaseUrl` is explicitly
21
+ * empty.
22
22
  *
23
23
  * @example Postgres-backed client
24
24
  * ```ts
@@ -28,9 +28,7 @@ import { A as PruneResult, C as MnemocyteConfig, D as ObservabilityConfig, E as
28
28
  * });
29
29
  * ```
30
30
  */
31
- declare function createMnemocyte(config: MnemocyteConfig): MnemocyteClient;
32
- //#endregion
33
- //#region src/errors.d.ts
31
+ export declare function createMnemocyte(config: MnemocyteConfig): MnemocyteClient;
34
32
  /**
35
33
  * Stable, machine-readable error code attached to every {@link MnemocyteError}.
36
34
  *
@@ -64,7 +62,7 @@ type MnemocyteErrorCode = "CONFIG" | "VALIDATION" | "DB" | "EMBEDDING" | "NOT_FO
64
62
  * }
65
63
  * ```
66
64
  */
67
- declare class MnemocyteError extends Error {
65
+ export declare class MnemocyteError extends Error {
68
66
  /** Stable, machine-readable failure code. See {@link MnemocyteErrorCode}. */
69
67
  readonly code: MnemocyteErrorCode;
70
68
  /** Underlying cause, if any (e.g. an original driver or embedder error). */
@@ -86,7 +84,5 @@ declare class MnemocyteError extends Error {
86
84
  * @param error - Value to test (typically a caught `unknown`).
87
85
  * @returns `true` if `error` is a {@link MnemocyteError}.
88
86
  */
89
- declare function isMnemocyteError(error: unknown): error is MnemocyteError;
90
- //#endregion
91
- export { type AuditConfig, type AuditEvent, type AuditLogCursor, type BuildContextInput, type ConsolidateInput, type ConsolidateResult, type ContextFormat, type DuplicatePair, type Embedder, type EntityStats, type ExperimentalMnemocyteClient, type FindDuplicatesInput, type GlobalStats, type ImportanceLevel, type JsonObject, type JsonValue, type ListAuditLogInput, type Memory, type MemoryType, type MemoryWithScore, type MnemocyteBackend, type MnemocyteClient, type MnemocyteConfig, MnemocyteError, type MnemocyteErrorCode, type MnemocyteObservation, type MnemocyteObservationPhase, type MnemocyteOperation, type ObservabilityConfig, type ProviderResilienceConfig, type PruneInput, type PruneResult, type RecallInput, type RememberInput, type RememberManyInput, type RetrievalConfig, type RetrievalExplanation, type RetrievalScoreWeights, type RetrievalScores, type TokenCounter, createMnemocyte, isMnemocyteError };
92
- //# sourceMappingURL=index.d.mts.map
87
+ export declare function isMnemocyteError(error: unknown): error is MnemocyteError;
88
+ export type { AuditConfig, AuditEvent, AuditLogCursor, BuildContextInput, ConsolidateInput, ConsolidateResult, ContextFormat, DuplicatePair, Embedder, EntityStats, ExperimentalMnemocyteClient, FindDuplicatesInput, GlobalStats, ImportanceLevel, JsonObject, JsonValue, ListAuditLogInput, Memory, MemoryType, MemoryWithScore, MnemocyteBackend, MnemocyteClient, MnemocyteConfig, MnemocyteErrorCode, MnemocyteObservation, MnemocyteObservationPhase, MnemocyteOperation, MnemocyteStoreConfig, ObservabilityConfig, ProviderResilienceConfig, PruneInput, PruneResult, RecallInput, RememberInput, RememberManyInput, RetrievalConfig, RetrievalExplanation, RetrievalScoreWeights, RetrievalScores, TokenCounter };