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