@langchain/langgraph-checkpoint 0.1.1 → 1.0.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.
Files changed (120) hide show
  1. package/dist/base.cjs +73 -88
  2. package/dist/base.cjs.map +1 -0
  3. package/dist/base.d.cts +94 -0
  4. package/dist/base.d.cts.map +1 -0
  5. package/dist/base.d.ts +78 -73
  6. package/dist/base.d.ts.map +1 -0
  7. package/dist/base.js +68 -80
  8. package/dist/base.js.map +1 -1
  9. package/dist/cache/base.cjs +16 -21
  10. package/dist/cache/base.cjs.map +1 -0
  11. package/dist/cache/base.d.cts +43 -0
  12. package/dist/cache/base.d.cts.map +1 -0
  13. package/dist/cache/base.d.ts +41 -36
  14. package/dist/cache/base.d.ts.map +1 -0
  15. package/dist/cache/base.js +15 -16
  16. package/dist/cache/base.js.map +1 -1
  17. package/dist/cache/index.cjs +2 -19
  18. package/dist/cache/index.js +3 -3
  19. package/dist/cache/memory.cjs +50 -58
  20. package/dist/cache/memory.cjs.map +1 -0
  21. package/dist/cache/memory.d.cts +19 -0
  22. package/dist/cache/memory.d.cts.map +1 -0
  23. package/dist/cache/memory.d.ts +18 -13
  24. package/dist/cache/memory.d.ts.map +1 -0
  25. package/dist/cache/memory.js +49 -53
  26. package/dist/cache/memory.js.map +1 -1
  27. package/dist/id.cjs +10 -16
  28. package/dist/id.cjs.map +1 -0
  29. package/dist/id.d.cts +6 -0
  30. package/dist/id.d.cts.map +1 -0
  31. package/dist/id.d.ts +6 -2
  32. package/dist/id.d.ts.map +1 -0
  33. package/dist/id.js +9 -12
  34. package/dist/id.js.map +1 -1
  35. package/dist/index.cjs +36 -27
  36. package/dist/index.d.cts +12 -0
  37. package/dist/index.d.ts +12 -8
  38. package/dist/index.js +11 -9
  39. package/dist/memory.cjs +191 -268
  40. package/dist/memory.cjs.map +1 -0
  41. package/dist/memory.d.cts +21 -0
  42. package/dist/memory.d.cts.map +1 -0
  43. package/dist/memory.d.ts +18 -12
  44. package/dist/memory.d.ts.map +1 -0
  45. package/dist/memory.js +190 -263
  46. package/dist/memory.js.map +1 -1
  47. package/dist/serde/base.d.cts +8 -0
  48. package/dist/serde/base.d.cts.map +1 -0
  49. package/dist/serde/base.d.ts +7 -3
  50. package/dist/serde/base.d.ts.map +1 -0
  51. package/dist/serde/jsonplus.cjs +90 -141
  52. package/dist/serde/jsonplus.cjs.map +1 -0
  53. package/dist/serde/jsonplus.js +89 -136
  54. package/dist/serde/jsonplus.js.map +1 -1
  55. package/dist/serde/types.cjs +14 -9
  56. package/dist/serde/types.cjs.map +1 -0
  57. package/dist/serde/types.d.cts +52 -0
  58. package/dist/serde/types.d.cts.map +1 -0
  59. package/dist/serde/types.d.ts +50 -47
  60. package/dist/serde/types.d.ts.map +1 -0
  61. package/dist/serde/types.js +9 -5
  62. package/dist/serde/types.js.map +1 -1
  63. package/dist/serde/utils/fast-safe-stringify/index.cjs +87 -208
  64. package/dist/serde/utils/fast-safe-stringify/index.cjs.map +1 -0
  65. package/dist/serde/utils/fast-safe-stringify/index.js +87 -205
  66. package/dist/serde/utils/fast-safe-stringify/index.js.map +1 -1
  67. package/dist/store/base.cjs +199 -209
  68. package/dist/store/base.cjs.map +1 -0
  69. package/dist/store/base.d.cts +391 -0
  70. package/dist/store/base.d.cts.map +1 -0
  71. package/dist/store/base.d.ts +335 -332
  72. package/dist/store/base.d.ts.map +1 -0
  73. package/dist/store/base.js +198 -204
  74. package/dist/store/base.js.map +1 -1
  75. package/dist/store/batch.cjs +114 -147
  76. package/dist/store/batch.cjs.map +1 -0
  77. package/dist/store/batch.d.cts +46 -0
  78. package/dist/store/batch.d.cts.map +1 -0
  79. package/dist/store/batch.d.ts +45 -40
  80. package/dist/store/batch.d.ts.map +1 -0
  81. package/dist/store/batch.js +114 -143
  82. package/dist/store/batch.js.map +1 -1
  83. package/dist/store/memory.cjs +256 -363
  84. package/dist/store/memory.cjs.map +1 -0
  85. package/dist/store/memory.d.cts +62 -0
  86. package/dist/store/memory.d.cts.map +1 -0
  87. package/dist/store/memory.d.ts +28 -24
  88. package/dist/store/memory.d.ts.map +1 -0
  89. package/dist/store/memory.js +255 -358
  90. package/dist/store/memory.js.map +1 -1
  91. package/dist/store/utils.cjs +137 -249
  92. package/dist/store/utils.cjs.map +1 -0
  93. package/dist/store/utils.js +137 -245
  94. package/dist/store/utils.js.map +1 -1
  95. package/dist/types.d.cts +35 -0
  96. package/dist/types.d.cts.map +1 -0
  97. package/dist/types.d.ts +29 -28
  98. package/dist/types.d.ts.map +1 -0
  99. package/package.json +33 -34
  100. package/CHANGELOG.md +0 -19
  101. package/dist/cache/index.d.ts +0 -2
  102. package/dist/cache/index.js.map +0 -1
  103. package/dist/index.js.map +0 -1
  104. package/dist/serde/base.cjs +0 -3
  105. package/dist/serde/base.js +0 -2
  106. package/dist/serde/base.js.map +0 -1
  107. package/dist/serde/jsonplus.d.ts +0 -7
  108. package/dist/serde/utils/fast-safe-stringify/index.d.ts +0 -1
  109. package/dist/store/index.cjs +0 -20
  110. package/dist/store/index.d.ts +0 -3
  111. package/dist/store/index.js +0 -4
  112. package/dist/store/index.js.map +0 -1
  113. package/dist/store/utils.d.ts +0 -26
  114. package/dist/types.cjs +0 -3
  115. package/dist/types.js +0 -2
  116. package/dist/types.js.map +0 -1
  117. package/index.cjs +0 -1
  118. package/index.d.cts +0 -1
  119. package/index.d.ts +0 -1
  120. package/index.js +0 -1
@@ -1,361 +1,258 @@
1
- import { BaseStore, } from "./base.js";
2
- import { tokenizePath, compareValues, getTextAtPath } from "./utils.js";
1
+ import { BaseStore } from "./base.js";
2
+ import { compareValues, getTextAtPath, tokenizePath } from "./utils.js";
3
+ //#region src/store/memory.ts
3
4
  /**
4
- * In-memory key-value store with optional vector search.
5
- *
6
- * A lightweight store implementation using JavaScript Maps. Supports basic
7
- * key-value operations and vector search when configured with embeddings.
8
- *
9
- * @example
10
- * ```typescript
11
- * // Basic key-value storage
12
- * const store = new InMemoryStore();
13
- * await store.put(["users", "123"], "prefs", { theme: "dark" });
14
- * const item = await store.get(["users", "123"], "prefs");
15
- *
16
- * // Vector search with embeddings
17
- * import { OpenAIEmbeddings } from "@langchain/openai";
18
- * const store = new InMemoryStore({
19
- * index: {
20
- * dims: 1536,
21
- * embeddings: new OpenAIEmbeddings({ modelName: "text-embedding-3-small" }),
22
- * }
23
- * });
24
- *
25
- * // Store documents
26
- * await store.put(["docs"], "doc1", { text: "Python tutorial" });
27
- * await store.put(["docs"], "doc2", { text: "TypeScript guide" });
28
- *
29
- * // Search by similarity
30
- * const results = await store.search(["docs"], { query: "python programming" });
31
- * ```
32
- *
33
- * @warning This store keeps all data in memory. Data is lost when the process exits.
34
- * For persistence, use a database-backed store.
35
- */
36
- export class InMemoryStore extends BaseStore {
37
- constructor(options) {
38
- super();
39
- Object.defineProperty(this, "data", {
40
- enumerable: true,
41
- configurable: true,
42
- writable: true,
43
- value: new Map()
44
- });
45
- // Namespace -> Key -> Path/field -> Vector
46
- Object.defineProperty(this, "vectors", {
47
- enumerable: true,
48
- configurable: true,
49
- writable: true,
50
- value: new Map()
51
- });
52
- Object.defineProperty(this, "_indexConfig", {
53
- enumerable: true,
54
- configurable: true,
55
- writable: true,
56
- value: void 0
57
- });
58
- if (options?.index) {
59
- this._indexConfig = {
60
- ...options.index,
61
- __tokenizedFields: (options.index.fields ?? ["$"]).map((p) => [
62
- p,
63
- p === "$" ? [p] : tokenizePath(p),
64
- ]),
65
- };
66
- }
67
- }
68
- async batch(operations) {
69
- const results = [];
70
- const putOps = new Map();
71
- const searchOps = new Map();
72
- // First pass - handle gets and prepare search/put operations
73
- for (let i = 0; i < operations.length; i += 1) {
74
- const op = operations[i];
75
- if ("key" in op && "namespace" in op && !("value" in op)) {
76
- // GetOperation
77
- results.push(this.getOperation(op));
78
- }
79
- else if ("namespacePrefix" in op) {
80
- // SearchOperation
81
- const candidates = this.filterItems(op);
82
- searchOps.set(i, [op, candidates]);
83
- results.push(null);
84
- }
85
- else if ("value" in op) {
86
- // PutOperation
87
- const key = `${op.namespace.join(":")}:${op.key}`;
88
- putOps.set(key, op);
89
- results.push(null);
90
- }
91
- else if ("matchConditions" in op) {
92
- // ListNamespacesOperation
93
- results.push(this.listNamespacesOperation(op));
94
- }
95
- }
96
- // Handle search operations with embeddings
97
- if (searchOps.size > 0) {
98
- if (this._indexConfig?.embeddings) {
99
- const queries = new Set();
100
- for (const [op] of searchOps.values()) {
101
- if (op.query)
102
- queries.add(op.query);
103
- }
104
- // Get embeddings for all queries
105
- const queryEmbeddings = queries.size > 0
106
- ? await Promise.all(Array.from(queries).map((q) => this._indexConfig.embeddings.embedQuery(q)))
107
- : [];
108
- const queryVectors = Object.fromEntries(Array.from(queries).map((q, i) => [q, queryEmbeddings[i]]));
109
- // Process each search operation
110
- for (const [i, [op, candidates]] of searchOps.entries()) {
111
- if (op.query && queryVectors[op.query]) {
112
- const queryVector = queryVectors[op.query];
113
- const scoredResults = this.scoreResults(candidates, queryVector, op.offset ?? 0, op.limit ?? 10);
114
- results[i] = scoredResults;
115
- }
116
- else {
117
- results[i] = this.paginateResults(candidates.map((item) => ({ ...item, score: undefined })), op.offset ?? 0, op.limit ?? 10);
118
- }
119
- }
120
- }
121
- else {
122
- // No embeddings - just paginate the filtered results
123
- for (const [i, [op, candidates]] of searchOps.entries()) {
124
- results[i] = this.paginateResults(candidates.map((item) => ({ ...item, score: undefined })), op.offset ?? 0, op.limit ?? 10);
125
- }
126
- }
127
- }
128
- // Handle put operations with embeddings
129
- if (putOps.size > 0 && this._indexConfig?.embeddings) {
130
- const toEmbed = this.extractTexts(Array.from(putOps.values()));
131
- if (Object.keys(toEmbed).length > 0) {
132
- const embeddings = await this._indexConfig.embeddings.embedDocuments(Object.keys(toEmbed));
133
- this.insertVectors(toEmbed, embeddings);
134
- }
135
- }
136
- // Apply all put operations
137
- for (const op of putOps.values()) {
138
- this.putOperation(op);
139
- }
140
- return results;
141
- }
142
- getOperation(op) {
143
- const namespaceKey = op.namespace.join(":");
144
- const item = this.data.get(namespaceKey)?.get(op.key);
145
- return item ?? null;
146
- }
147
- putOperation(op) {
148
- const namespaceKey = op.namespace.join(":");
149
- if (!this.data.has(namespaceKey)) {
150
- this.data.set(namespaceKey, new Map());
151
- }
152
- const namespaceMap = this.data.get(namespaceKey);
153
- if (op.value === null) {
154
- namespaceMap.delete(op.key);
155
- }
156
- else {
157
- const now = new Date();
158
- if (namespaceMap.has(op.key)) {
159
- const item = namespaceMap.get(op.key);
160
- item.value = op.value;
161
- item.updatedAt = now;
162
- }
163
- else {
164
- namespaceMap.set(op.key, {
165
- value: op.value,
166
- key: op.key,
167
- namespace: op.namespace,
168
- createdAt: now,
169
- updatedAt: now,
170
- });
171
- }
172
- }
173
- }
174
- listNamespacesOperation(op) {
175
- const allNamespaces = Array.from(this.data.keys()).map((ns) => ns.split(":"));
176
- let namespaces = allNamespaces;
177
- if (op.matchConditions && op.matchConditions.length > 0) {
178
- namespaces = namespaces.filter((ns) => op.matchConditions.every((condition) => this.doesMatch(condition, ns)));
179
- }
180
- if (op.maxDepth !== undefined) {
181
- namespaces = Array.from(new Set(namespaces.map((ns) => ns.slice(0, op.maxDepth).join(":")))).map((ns) => ns.split(":"));
182
- }
183
- namespaces.sort((a, b) => a.join(":").localeCompare(b.join(":")));
184
- return namespaces.slice(op.offset ?? 0, (op.offset ?? 0) + (op.limit ?? namespaces.length));
185
- }
186
- doesMatch(matchCondition, key) {
187
- const { matchType, path } = matchCondition;
188
- if (matchType === "prefix") {
189
- if (path.length > key.length)
190
- return false;
191
- return path.every((pElem, index) => {
192
- const kElem = key[index];
193
- return pElem === "*" || kElem === pElem;
194
- });
195
- }
196
- else if (matchType === "suffix") {
197
- if (path.length > key.length)
198
- return false;
199
- return path.every((pElem, index) => {
200
- const kElem = key[key.length - path.length + index];
201
- return pElem === "*" || kElem === pElem;
202
- });
203
- }
204
- throw new Error(`Unsupported match type: ${matchType}`);
205
- }
206
- filterItems(op) {
207
- const candidates = [];
208
- for (const [namespace, items] of this.data.entries()) {
209
- if (namespace.startsWith(op.namespacePrefix.join(":"))) {
210
- candidates.push(...items.values());
211
- }
212
- }
213
- let filteredCandidates = candidates;
214
- if (op.filter) {
215
- filteredCandidates = candidates.filter((item) => Object.entries(op.filter).every(([key, value]) => compareValues(item.value[key], value)));
216
- }
217
- return filteredCandidates;
218
- }
219
- scoreResults(candidates, queryVector, offset = 0, limit = 10) {
220
- const flatItems = [];
221
- const flatVectors = [];
222
- const scoreless = [];
223
- for (const item of candidates) {
224
- const vectors = this.getVectors(item);
225
- if (vectors.length) {
226
- for (const vector of vectors) {
227
- flatItems.push(item);
228
- flatVectors.push(vector);
229
- }
230
- }
231
- else {
232
- scoreless.push(item);
233
- }
234
- }
235
- const scores = this.cosineSimilarity(queryVector, flatVectors);
236
- const sortedResults = scores
237
- .map((score, i) => [score, flatItems[i]])
238
- .sort((a, b) => b[0] - a[0]);
239
- const seen = new Set();
240
- const kept = [];
241
- for (const [score, item] of sortedResults) {
242
- const key = `${item.namespace.join(":")}:${item.key}`;
243
- if (seen.has(key))
244
- continue;
245
- const ix = seen.size;
246
- if (ix >= offset + limit)
247
- break;
248
- if (ix < offset) {
249
- seen.add(key);
250
- continue;
251
- }
252
- seen.add(key);
253
- kept.push([score, item]);
254
- }
255
- if (scoreless.length && kept.length < limit) {
256
- for (const item of scoreless.slice(0, limit - kept.length)) {
257
- const key = `${item.namespace.join(":")}:${item.key}`;
258
- if (!seen.has(key)) {
259
- seen.add(key);
260
- kept.push([undefined, item]);
261
- }
262
- }
263
- }
264
- return kept.map(([score, item]) => ({
265
- ...item,
266
- score,
267
- }));
268
- }
269
- paginateResults(results, offset, limit) {
270
- return results.slice(offset, offset + limit);
271
- }
272
- extractTexts(ops) {
273
- if (!ops.length || !this._indexConfig) {
274
- return {};
275
- }
276
- const toEmbed = {};
277
- for (const op of ops) {
278
- if (op.value !== null && op.index !== false) {
279
- const paths = op.index === null || op.index === undefined
280
- ? this._indexConfig.__tokenizedFields ?? []
281
- : op.index.map((ix) => [ix, tokenizePath(ix)]);
282
- for (const [path, field] of paths) {
283
- const texts = getTextAtPath(op.value, field);
284
- if (texts.length) {
285
- if (texts.length > 1) {
286
- texts.forEach((text, i) => {
287
- if (!toEmbed[text])
288
- toEmbed[text] = [];
289
- toEmbed[text].push([op.namespace, op.key, `${path}.${i}`]);
290
- });
291
- }
292
- else {
293
- if (!toEmbed[texts[0]])
294
- toEmbed[texts[0]] = [];
295
- toEmbed[texts[0]].push([op.namespace, op.key, path]);
296
- }
297
- }
298
- }
299
- }
300
- }
301
- return toEmbed;
302
- }
303
- insertVectors(texts, embeddings) {
304
- for (const [text, metadata] of Object.entries(texts)) {
305
- const embedding = embeddings.shift();
306
- if (!embedding) {
307
- throw new Error(`No embedding found for text: ${text}`);
308
- }
309
- for (const [namespace, key, field] of metadata) {
310
- const namespaceKey = namespace.join(":");
311
- if (!this.vectors.has(namespaceKey)) {
312
- this.vectors.set(namespaceKey, new Map());
313
- }
314
- const namespaceMap = this.vectors.get(namespaceKey);
315
- if (!namespaceMap.has(key)) {
316
- namespaceMap.set(key, new Map());
317
- }
318
- const itemMap = namespaceMap.get(key);
319
- itemMap.set(field, embedding);
320
- }
321
- }
322
- }
323
- getVectors(item) {
324
- const namespaceKey = item.namespace.join(":");
325
- const itemKey = item.key;
326
- if (!this.vectors.has(namespaceKey)) {
327
- return [];
328
- }
329
- const namespaceMap = this.vectors.get(namespaceKey);
330
- if (!namespaceMap.has(itemKey)) {
331
- return [];
332
- }
333
- const itemMap = namespaceMap.get(itemKey);
334
- const vectors = Array.from(itemMap.values());
335
- if (!vectors.length) {
336
- return [];
337
- }
338
- return vectors;
339
- }
340
- cosineSimilarity(X, Y) {
341
- if (!Y.length)
342
- return [];
343
- // Calculate dot products for all vectors at once
344
- const dotProducts = Y.map((vector) => vector.reduce((acc, val, i) => acc + val * X[i], 0));
345
- // Calculate magnitudes
346
- const magnitude1 = Math.sqrt(X.reduce((acc, val) => acc + val * val, 0));
347
- const magnitudes2 = Y.map((vector) => Math.sqrt(vector.reduce((acc, val) => acc + val * val, 0)));
348
- // Calculate similarities
349
- return dotProducts.map((dot, i) => {
350
- const magnitude2 = magnitudes2[i];
351
- return magnitude1 && magnitude2 ? dot / (magnitude1 * magnitude2) : 0;
352
- });
353
- }
354
- get indexConfig() {
355
- return this._indexConfig;
356
- }
357
- }
5
+ * In-memory key-value store with optional vector search.
6
+ *
7
+ * A lightweight store implementation using JavaScript Maps. Supports basic
8
+ * key-value operations and vector search when configured with embeddings.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // Basic key-value storage
13
+ * const store = new InMemoryStore();
14
+ * await store.put(["users", "123"], "prefs", { theme: "dark" });
15
+ * const item = await store.get(["users", "123"], "prefs");
16
+ *
17
+ * // Vector search with embeddings
18
+ * import { OpenAIEmbeddings } from "@langchain/openai";
19
+ * const store = new InMemoryStore({
20
+ * index: {
21
+ * dims: 1536,
22
+ * embeddings: new OpenAIEmbeddings({ modelName: "text-embedding-3-small" }),
23
+ * }
24
+ * });
25
+ *
26
+ * // Store documents
27
+ * await store.put(["docs"], "doc1", { text: "Python tutorial" });
28
+ * await store.put(["docs"], "doc2", { text: "TypeScript guide" });
29
+ *
30
+ * // Search by similarity
31
+ * const results = await store.search(["docs"], { query: "python programming" });
32
+ * ```
33
+ *
34
+ * **Warning**: This store keeps all data in memory. Data is lost when the process exits.
35
+ * For persistence, use a database-backed store.
36
+ */
37
+ var InMemoryStore = class extends BaseStore {
38
+ data = /* @__PURE__ */ new Map();
39
+ vectors = /* @__PURE__ */ new Map();
40
+ _indexConfig;
41
+ constructor(options) {
42
+ super();
43
+ if (options?.index) this._indexConfig = {
44
+ ...options.index,
45
+ __tokenizedFields: (options.index.fields ?? ["$"]).map((p) => [p, p === "$" ? [p] : tokenizePath(p)])
46
+ };
47
+ }
48
+ async batch(operations) {
49
+ const results = [];
50
+ const putOps = /* @__PURE__ */ new Map();
51
+ const searchOps = /* @__PURE__ */ new Map();
52
+ for (let i = 0; i < operations.length; i += 1) {
53
+ const op = operations[i];
54
+ if ("key" in op && "namespace" in op && !("value" in op)) results.push(this.getOperation(op));
55
+ else if ("namespacePrefix" in op) {
56
+ const candidates = this.filterItems(op);
57
+ searchOps.set(i, [op, candidates]);
58
+ results.push(null);
59
+ } else if ("value" in op) {
60
+ const key = `${op.namespace.join(":")}:${op.key}`;
61
+ putOps.set(key, op);
62
+ results.push(null);
63
+ } else if ("matchConditions" in op) results.push(this.listNamespacesOperation(op));
64
+ }
65
+ if (searchOps.size > 0) if (this._indexConfig?.embeddings) {
66
+ const queries = /* @__PURE__ */ new Set();
67
+ for (const [op] of searchOps.values()) if (op.query) queries.add(op.query);
68
+ const queryEmbeddings = queries.size > 0 ? await Promise.all(Array.from(queries).map((q) => this._indexConfig.embeddings.embedQuery(q))) : [];
69
+ const queryVectors = Object.fromEntries(Array.from(queries).map((q, i) => [q, queryEmbeddings[i]]));
70
+ for (const [i, [op, candidates]] of searchOps.entries()) if (op.query && queryVectors[op.query]) {
71
+ const queryVector = queryVectors[op.query];
72
+ results[i] = this.scoreResults(candidates, queryVector, op.offset ?? 0, op.limit ?? 10);
73
+ } else results[i] = this.paginateResults(candidates.map((item) => ({
74
+ ...item,
75
+ score: void 0
76
+ })), op.offset ?? 0, op.limit ?? 10);
77
+ } else for (const [i, [op, candidates]] of searchOps.entries()) results[i] = this.paginateResults(candidates.map((item) => ({
78
+ ...item,
79
+ score: void 0
80
+ })), op.offset ?? 0, op.limit ?? 10);
81
+ if (putOps.size > 0 && this._indexConfig?.embeddings) {
82
+ const toEmbed = this.extractTexts(Array.from(putOps.values()));
83
+ if (Object.keys(toEmbed).length > 0) {
84
+ const embeddings = await this._indexConfig.embeddings.embedDocuments(Object.keys(toEmbed));
85
+ this.insertVectors(toEmbed, embeddings);
86
+ }
87
+ }
88
+ for (const op of putOps.values()) this.putOperation(op);
89
+ return results;
90
+ }
91
+ getOperation(op) {
92
+ const namespaceKey = op.namespace.join(":");
93
+ return this.data.get(namespaceKey)?.get(op.key) ?? null;
94
+ }
95
+ putOperation(op) {
96
+ const namespaceKey = op.namespace.join(":");
97
+ if (!this.data.has(namespaceKey)) this.data.set(namespaceKey, /* @__PURE__ */ new Map());
98
+ const namespaceMap = this.data.get(namespaceKey);
99
+ if (op.value === null) namespaceMap.delete(op.key);
100
+ else {
101
+ const now = /* @__PURE__ */ new Date();
102
+ if (namespaceMap.has(op.key)) {
103
+ const item = namespaceMap.get(op.key);
104
+ item.value = op.value;
105
+ item.updatedAt = now;
106
+ } else namespaceMap.set(op.key, {
107
+ value: op.value,
108
+ key: op.key,
109
+ namespace: op.namespace,
110
+ createdAt: now,
111
+ updatedAt: now
112
+ });
113
+ }
114
+ }
115
+ listNamespacesOperation(op) {
116
+ let namespaces = Array.from(this.data.keys()).map((ns) => ns.split(":"));
117
+ if (op.matchConditions && op.matchConditions.length > 0) namespaces = namespaces.filter((ns) => op.matchConditions.every((condition) => this.doesMatch(condition, ns)));
118
+ if (op.maxDepth !== void 0) namespaces = Array.from(new Set(namespaces.map((ns) => ns.slice(0, op.maxDepth).join(":")))).map((ns) => ns.split(":"));
119
+ namespaces.sort((a, b) => a.join(":").localeCompare(b.join(":")));
120
+ return namespaces.slice(op.offset ?? 0, (op.offset ?? 0) + (op.limit ?? namespaces.length));
121
+ }
122
+ doesMatch(matchCondition, key) {
123
+ const { matchType, path } = matchCondition;
124
+ if (matchType === "prefix") {
125
+ if (path.length > key.length) return false;
126
+ return path.every((pElem, index) => {
127
+ const kElem = key[index];
128
+ return pElem === "*" || kElem === pElem;
129
+ });
130
+ } else if (matchType === "suffix") {
131
+ if (path.length > key.length) return false;
132
+ return path.every((pElem, index) => {
133
+ const kElem = key[key.length - path.length + index];
134
+ return pElem === "*" || kElem === pElem;
135
+ });
136
+ }
137
+ throw new Error(`Unsupported match type: ${matchType}`);
138
+ }
139
+ filterItems(op) {
140
+ const candidates = [];
141
+ for (const [namespace, items] of this.data.entries()) if (namespace.startsWith(op.namespacePrefix.join(":"))) candidates.push(...items.values());
142
+ let filteredCandidates = candidates;
143
+ if (op.filter) filteredCandidates = candidates.filter((item) => Object.entries(op.filter).every(([key, value]) => compareValues(item.value[key], value)));
144
+ return filteredCandidates;
145
+ }
146
+ scoreResults(candidates, queryVector, offset = 0, limit = 10) {
147
+ const flatItems = [];
148
+ const flatVectors = [];
149
+ const scoreless = [];
150
+ for (const item of candidates) {
151
+ const vectors = this.getVectors(item);
152
+ if (vectors.length) for (const vector of vectors) {
153
+ flatItems.push(item);
154
+ flatVectors.push(vector);
155
+ }
156
+ else scoreless.push(item);
157
+ }
158
+ const sortedResults = this.cosineSimilarity(queryVector, flatVectors).map((score, i) => [score, flatItems[i]]).sort((a, b) => b[0] - a[0]);
159
+ const seen = /* @__PURE__ */ new Set();
160
+ const kept = [];
161
+ for (const [score, item] of sortedResults) {
162
+ const key = `${item.namespace.join(":")}:${item.key}`;
163
+ if (seen.has(key)) continue;
164
+ const ix = seen.size;
165
+ if (ix >= offset + limit) break;
166
+ if (ix < offset) {
167
+ seen.add(key);
168
+ continue;
169
+ }
170
+ seen.add(key);
171
+ kept.push([score, item]);
172
+ }
173
+ if (scoreless.length && kept.length < limit) for (const item of scoreless.slice(0, limit - kept.length)) {
174
+ const key = `${item.namespace.join(":")}:${item.key}`;
175
+ if (!seen.has(key)) {
176
+ seen.add(key);
177
+ kept.push([void 0, item]);
178
+ }
179
+ }
180
+ return kept.map(([score, item]) => ({
181
+ ...item,
182
+ score
183
+ }));
184
+ }
185
+ paginateResults(results, offset, limit) {
186
+ return results.slice(offset, offset + limit);
187
+ }
188
+ extractTexts(ops) {
189
+ if (!ops.length || !this._indexConfig) return {};
190
+ const toEmbed = {};
191
+ for (const op of ops) if (op.value !== null && op.index !== false) {
192
+ const paths = op.index === null || op.index === void 0 ? this._indexConfig.__tokenizedFields ?? [] : op.index.map((ix) => [ix, tokenizePath(ix)]);
193
+ for (const [path, field] of paths) {
194
+ const texts = getTextAtPath(op.value, field);
195
+ if (texts.length) if (texts.length > 1) texts.forEach((text, i) => {
196
+ if (!toEmbed[text]) toEmbed[text] = [];
197
+ toEmbed[text].push([
198
+ op.namespace,
199
+ op.key,
200
+ `${path}.${i}`
201
+ ]);
202
+ });
203
+ else {
204
+ if (!toEmbed[texts[0]]) toEmbed[texts[0]] = [];
205
+ toEmbed[texts[0]].push([
206
+ op.namespace,
207
+ op.key,
208
+ path
209
+ ]);
210
+ }
211
+ }
212
+ }
213
+ return toEmbed;
214
+ }
215
+ insertVectors(texts, embeddings) {
216
+ for (const [text, metadata] of Object.entries(texts)) {
217
+ const embedding = embeddings.shift();
218
+ if (!embedding) throw new Error(`No embedding found for text: ${text}`);
219
+ for (const [namespace, key, field] of metadata) {
220
+ const namespaceKey = namespace.join(":");
221
+ if (!this.vectors.has(namespaceKey)) this.vectors.set(namespaceKey, /* @__PURE__ */ new Map());
222
+ const namespaceMap = this.vectors.get(namespaceKey);
223
+ if (!namespaceMap.has(key)) namespaceMap.set(key, /* @__PURE__ */ new Map());
224
+ namespaceMap.get(key).set(field, embedding);
225
+ }
226
+ }
227
+ }
228
+ getVectors(item) {
229
+ const namespaceKey = item.namespace.join(":");
230
+ const itemKey = item.key;
231
+ if (!this.vectors.has(namespaceKey)) return [];
232
+ const namespaceMap = this.vectors.get(namespaceKey);
233
+ if (!namespaceMap.has(itemKey)) return [];
234
+ const itemMap = namespaceMap.get(itemKey);
235
+ const vectors = Array.from(itemMap.values());
236
+ if (!vectors.length) return [];
237
+ return vectors;
238
+ }
239
+ cosineSimilarity(X, Y) {
240
+ if (!Y.length) return [];
241
+ const dotProducts = Y.map((vector) => vector.reduce((acc, val, i) => acc + val * X[i], 0));
242
+ const magnitude1 = Math.sqrt(X.reduce((acc, val) => acc + val * val, 0));
243
+ const magnitudes2 = Y.map((vector) => Math.sqrt(vector.reduce((acc, val) => acc + val * val, 0)));
244
+ return dotProducts.map((dot, i) => {
245
+ const magnitude2 = magnitudes2[i];
246
+ return magnitude1 && magnitude2 ? dot / (magnitude1 * magnitude2) : 0;
247
+ });
248
+ }
249
+ get indexConfig() {
250
+ return this._indexConfig;
251
+ }
252
+ };
358
253
  /** @deprecated Alias for InMemoryStore */
359
- export class MemoryStore extends InMemoryStore {
360
- }
254
+ var MemoryStore = class extends InMemoryStore {};
255
+ //#endregion
256
+ export { InMemoryStore, MemoryStore };
257
+
361
258
  //# sourceMappingURL=memory.js.map