@yamo/memory-mesh 2.3.2 → 3.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 (124) hide show
  1. package/README.md +8 -2
  2. package/bin/memory_mesh.js +1 -1
  3. package/lib/llm/client.d.ts +86 -0
  4. package/lib/llm/client.js +300 -357
  5. package/lib/llm/client.ts +334 -0
  6. package/lib/llm/index.d.ts +17 -0
  7. package/lib/llm/index.js +16 -8
  8. package/lib/llm/index.ts +18 -0
  9. package/lib/memory/adapters/client.d.ts +120 -0
  10. package/lib/memory/adapters/client.js +519 -0
  11. package/lib/memory/adapters/client.ts +519 -0
  12. package/lib/memory/adapters/config.d.ts +130 -0
  13. package/lib/memory/adapters/config.js +190 -0
  14. package/lib/memory/adapters/config.ts +190 -0
  15. package/lib/memory/adapters/errors.d.ts +84 -0
  16. package/lib/memory/adapters/errors.js +129 -0
  17. package/lib/memory/adapters/errors.ts +129 -0
  18. package/lib/memory/context-manager.d.ts +41 -0
  19. package/lib/memory/context-manager.js +345 -0
  20. package/lib/memory/context-manager.ts +345 -0
  21. package/lib/memory/embeddings/factory.d.ts +57 -0
  22. package/lib/memory/embeddings/factory.js +149 -0
  23. package/lib/memory/embeddings/factory.ts +149 -0
  24. package/lib/memory/embeddings/index.d.ts +2 -0
  25. package/lib/memory/embeddings/index.js +3 -0
  26. package/lib/memory/embeddings/index.ts +3 -0
  27. package/lib/memory/embeddings/service.d.ts +134 -0
  28. package/lib/memory/embeddings/service.js +516 -0
  29. package/lib/memory/embeddings/service.ts +516 -0
  30. package/lib/memory/index.d.ts +9 -0
  31. package/lib/memory/index.js +10 -1
  32. package/lib/memory/index.ts +10 -0
  33. package/lib/memory/memory-mesh.d.ts +332 -0
  34. package/lib/memory/memory-mesh.js +1470 -678
  35. package/lib/memory/memory-mesh.ts +1517 -0
  36. package/lib/memory/memory-translator.d.ts +14 -0
  37. package/lib/memory/memory-translator.js +126 -0
  38. package/lib/memory/memory-translator.ts +126 -0
  39. package/lib/memory/schema.d.ts +130 -0
  40. package/lib/memory/schema.js +184 -0
  41. package/lib/memory/schema.ts +184 -0
  42. package/lib/memory/scorer.d.ts +25 -0
  43. package/lib/memory/scorer.js +78 -0
  44. package/lib/memory/scorer.ts +78 -0
  45. package/lib/memory/search/index.d.ts +1 -0
  46. package/lib/memory/search/index.js +2 -0
  47. package/lib/memory/search/index.ts +2 -0
  48. package/lib/memory/search/keyword-search.d.ts +46 -0
  49. package/lib/memory/search/keyword-search.js +136 -0
  50. package/lib/memory/search/keyword-search.ts +136 -0
  51. package/lib/scrubber/config/defaults.d.ts +46 -0
  52. package/lib/scrubber/config/defaults.js +50 -57
  53. package/lib/scrubber/config/defaults.ts +55 -0
  54. package/lib/scrubber/errors/scrubber-error.d.ts +22 -0
  55. package/lib/scrubber/errors/scrubber-error.js +28 -32
  56. package/lib/scrubber/errors/scrubber-error.ts +44 -0
  57. package/lib/scrubber/index.d.ts +5 -0
  58. package/lib/scrubber/index.js +4 -23
  59. package/lib/scrubber/index.ts +6 -0
  60. package/lib/scrubber/scrubber.d.ts +44 -0
  61. package/lib/scrubber/scrubber.js +100 -121
  62. package/lib/scrubber/scrubber.ts +109 -0
  63. package/lib/scrubber/stages/chunker.d.ts +25 -0
  64. package/lib/scrubber/stages/chunker.js +74 -91
  65. package/lib/scrubber/stages/chunker.ts +104 -0
  66. package/lib/scrubber/stages/metadata-annotator.d.ts +17 -0
  67. package/lib/scrubber/stages/metadata-annotator.js +55 -65
  68. package/lib/scrubber/stages/metadata-annotator.ts +75 -0
  69. package/lib/scrubber/stages/normalizer.d.ts +16 -0
  70. package/lib/scrubber/stages/normalizer.js +42 -50
  71. package/lib/scrubber/stages/normalizer.ts +60 -0
  72. package/lib/scrubber/stages/semantic-filter.d.ts +16 -0
  73. package/lib/scrubber/stages/semantic-filter.js +42 -52
  74. package/lib/scrubber/stages/semantic-filter.ts +62 -0
  75. package/lib/scrubber/stages/structural-cleaner.d.ts +18 -0
  76. package/lib/scrubber/stages/structural-cleaner.js +66 -75
  77. package/lib/scrubber/stages/structural-cleaner.ts +83 -0
  78. package/lib/scrubber/stages/validator.d.ts +17 -0
  79. package/lib/scrubber/stages/validator.js +46 -56
  80. package/lib/scrubber/stages/validator.ts +67 -0
  81. package/lib/scrubber/telemetry.d.ts +29 -0
  82. package/lib/scrubber/telemetry.js +54 -58
  83. package/lib/scrubber/telemetry.ts +62 -0
  84. package/lib/scrubber/utils/hash.d.ts +14 -0
  85. package/lib/scrubber/utils/hash.js +30 -32
  86. package/lib/scrubber/utils/hash.ts +40 -0
  87. package/lib/scrubber/utils/html-parser.d.ts +14 -0
  88. package/lib/scrubber/utils/html-parser.js +32 -39
  89. package/lib/scrubber/utils/html-parser.ts +46 -0
  90. package/lib/scrubber/utils/pattern-matcher.d.ts +12 -0
  91. package/lib/scrubber/utils/pattern-matcher.js +48 -57
  92. package/lib/scrubber/utils/pattern-matcher.ts +64 -0
  93. package/lib/scrubber/utils/token-counter.d.ts +18 -0
  94. package/lib/scrubber/utils/token-counter.js +24 -25
  95. package/lib/scrubber/utils/token-counter.ts +32 -0
  96. package/lib/utils/logger.d.ts +19 -0
  97. package/lib/utils/logger.js +65 -0
  98. package/lib/utils/logger.ts +65 -0
  99. package/lib/utils/skill-metadata.d.ts +24 -0
  100. package/lib/utils/skill-metadata.js +133 -0
  101. package/lib/utils/skill-metadata.ts +133 -0
  102. package/lib/yamo/emitter.d.ts +46 -0
  103. package/lib/yamo/emitter.js +79 -143
  104. package/lib/yamo/emitter.ts +171 -0
  105. package/lib/yamo/index.d.ts +14 -0
  106. package/lib/yamo/index.js +6 -7
  107. package/lib/yamo/index.ts +16 -0
  108. package/lib/yamo/schema.d.ts +56 -0
  109. package/lib/yamo/schema.js +82 -108
  110. package/lib/yamo/schema.ts +133 -0
  111. package/package.json +13 -8
  112. package/index.d.ts +0 -111
  113. package/lib/embeddings/factory.js +0 -151
  114. package/lib/embeddings/index.js +0 -2
  115. package/lib/embeddings/service.js +0 -586
  116. package/lib/index.js +0 -6
  117. package/lib/lancedb/client.js +0 -633
  118. package/lib/lancedb/config.js +0 -215
  119. package/lib/lancedb/errors.js +0 -144
  120. package/lib/lancedb/index.js +0 -4
  121. package/lib/lancedb/schema.js +0 -217
  122. package/lib/search/index.js +0 -1
  123. package/lib/search/keyword-search.js +0 -144
  124. package/lib/utils/index.js +0 -1
@@ -0,0 +1,519 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * LanceDB Client Wrapper
4
+ *
5
+ * A comprehensive wrapper around LanceDB JavaScript SDK providing:
6
+ * - Connection management with pooling and retries
7
+ * - CRUD operations for memory entries
8
+ * - Vector similarity search with filtering
9
+ * - Database statistics and monitoring
10
+ *
11
+ * @class LanceDBClient
12
+ */
13
+ import * as lancedb from "@lancedb/lancedb";
14
+ import fs from "fs";
15
+ import path from "path";
16
+ import { createMemoryTableWithDimension, DEFAULT_VECTOR_DIMENSION, } from "../schema.js";
17
+ import { StorageError, QueryError } from "./errors.js";
18
+ import { createLogger } from "../../utils/logger.js";
19
+ const logger = createLogger("lancedb-client");
20
+ /**
21
+ * LanceDB Client wrapper class
22
+ */
23
+ export class LanceDBClient {
24
+ uri;
25
+ tableName;
26
+ maxRetries;
27
+ retryDelay;
28
+ vectorDimension;
29
+ driver;
30
+ db;
31
+ table;
32
+ isConnected;
33
+ tempDir; // Track temp dirs for cleanup
34
+ /**
35
+ * Create a new LanceDBClient instance
36
+ * @param {Object} [config={}] - Configuration object
37
+ */
38
+ constructor(config = {}) {
39
+ this.uri =
40
+ (config && config.uri) || process.env.LANCEDB_URI || "./data/lancedb";
41
+ this.tableName =
42
+ (config && config.tableName) ||
43
+ process.env.LANCEDB_MEMORY_TABLE ||
44
+ "memory_entries";
45
+ this.maxRetries = (config && config.maxRetries) || 3;
46
+ this.retryDelay = (config && config.retryDelay) || 1000;
47
+ this.vectorDimension =
48
+ (config && config.vectorDimension) || DEFAULT_VECTOR_DIMENSION;
49
+ this.driver = (config && config.driver) || lancedb;
50
+ // Connection state
51
+ this.db = null;
52
+ this.table = null;
53
+ this.isConnected = false;
54
+ }
55
+ /**
56
+ * Connect to LanceDB and initialize table
57
+ * Creates the database directory and table if they don't exist
58
+ * @returns {Promise<void>}
59
+ * @throws {StorageError} If connection fails after retries
60
+ */
61
+ async connect() {
62
+ if (this.isConnected) {
63
+ return; // Already connected
64
+ }
65
+ let lastError = null;
66
+ for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
67
+ try {
68
+ // Handle :memory: specially - LanceDB doesn't support true in-memory DBs
69
+ // Use OS temp directory for isolation
70
+ let dbPath = this.uri;
71
+ if (this.uri === ":memory:") {
72
+ const os = await import("os");
73
+ const crypto = await import("crypto");
74
+ const randomId = crypto.randomBytes(8).toString("hex");
75
+ dbPath = path.join(os.tmpdir(), `yamo-memory-${randomId}`);
76
+ this.tempDir = dbPath; // Track for cleanup
77
+ }
78
+ // Ensure database directory exists
79
+ const resolvedPath = path.resolve(dbPath);
80
+ const dbDir = path.dirname(resolvedPath);
81
+ if (!fs.existsSync(dbDir)) {
82
+ fs.mkdirSync(dbDir, { recursive: true });
83
+ }
84
+ // Connect to database
85
+ this.db = await this.driver.connect(dbPath);
86
+ // Initialize table with dynamic dimension (creates if doesn't exist, opens if it does)
87
+ if (this.db) {
88
+ this.table = await createMemoryTableWithDimension(this.db, this.tableName, this.vectorDimension);
89
+ }
90
+ this.isConnected = true;
91
+ return;
92
+ }
93
+ catch (error) {
94
+ lastError = error;
95
+ const msg = error.message.toLowerCase();
96
+ // Specific check for locking/busy errors
97
+ if (msg.includes("busy") ||
98
+ msg.includes("locked") ||
99
+ msg.includes("resource temporarily unavailable")) {
100
+ logger.warn({ attempt, maxRetries: this.maxRetries, uri: this.uri }, "Database is locked by another process, retrying");
101
+ await this._sleep(this.retryDelay * attempt + Math.random() * 1000);
102
+ continue;
103
+ }
104
+ if (attempt < this.maxRetries) {
105
+ // Wait before retrying for other errors
106
+ await this._sleep(this.retryDelay * attempt);
107
+ }
108
+ }
109
+ }
110
+ // All retries failed
111
+ const errorMessage = lastError instanceof Error ? lastError.message : String(lastError);
112
+ throw new StorageError(`Failed to connect to LanceDB after ${this.maxRetries} attempts: ${errorMessage}`, { uri: this.uri, tableName: this.tableName, originalError: lastError });
113
+ }
114
+ /**
115
+ * Disconnect from LanceDB
116
+ * @returns {Promise<void>}
117
+ */
118
+ disconnect() {
119
+ this.db = null;
120
+ this.table = null;
121
+ this.isConnected = false;
122
+ // Clean up temp directory if we created one for :memory:
123
+ if (this.tempDir && fs.existsSync(this.tempDir)) {
124
+ try {
125
+ fs.rmSync(this.tempDir, { recursive: true, force: true });
126
+ }
127
+ catch (_e) {
128
+ // Best-effort cleanup, ignore errors
129
+ }
130
+ this.tempDir = undefined;
131
+ }
132
+ }
133
+ /**
134
+ * Add a single memory entry
135
+ * @param {Object} data - Entry data
136
+ * @returns {Promise<Object>} Result with id and success status
137
+ * @throws {StorageError} If add operation fails
138
+ */
139
+ async add(data) {
140
+ if (!this.isConnected) {
141
+ await this.connect();
142
+ }
143
+ this._validateRecord(data);
144
+ return this._retryOperation(async () => {
145
+ const record = {
146
+ ...data,
147
+ created_at: new Date(),
148
+ updated_at: new Date(),
149
+ };
150
+ if (!this.table) {
151
+ throw new StorageError("Table not initialized");
152
+ }
153
+ await this.table.add([record]);
154
+ return {
155
+ id: data.id,
156
+ success: true,
157
+ };
158
+ });
159
+ }
160
+ /**
161
+ * Add multiple memory entries in batch
162
+ * @param {Array<Object>} records - Array of entry data objects
163
+ * @returns {Promise<Object>} Result with count of added records
164
+ * @throws {StorageError} If batch add fails
165
+ */
166
+ async addBatch(records) {
167
+ if (!this.isConnected) {
168
+ await this.connect();
169
+ }
170
+ if (!Array.isArray(records) || records.length === 0) {
171
+ throw new StorageError("Records must be a non-empty array");
172
+ }
173
+ // Validate all records
174
+ records.forEach((record) => this._validateRecord(record));
175
+ return this._retryOperation(async () => {
176
+ const now = new Date();
177
+ const recordsWithTimestamps = records.map((record) => ({
178
+ ...record,
179
+ created_at: now,
180
+ updated_at: now,
181
+ }));
182
+ if (!this.table) {
183
+ throw new StorageError("Table not initialized");
184
+ }
185
+ await this.table.add(recordsWithTimestamps);
186
+ return {
187
+ count: records.length,
188
+ success: true,
189
+ };
190
+ });
191
+ }
192
+ /**
193
+ * Search for similar vectors
194
+ * @param {Array<number>} vector - Query vector (384 dimensions)
195
+ * @param {Object} options - Search options
196
+ * @returns {Promise<Array<Object>>} Array of search results with scores
197
+ * @throws {QueryError} If search fails
198
+ */
199
+ async search(vector, options = {}) {
200
+ if (!this.isConnected) {
201
+ await this.connect();
202
+ }
203
+ this._validateVector(vector);
204
+ const { limit = 10, nprobes = 20, filter = null } = options;
205
+ return this._retryOperation(async () => {
206
+ if (!this.table) {
207
+ throw new StorageError("Table not initialized");
208
+ }
209
+ // Build the search query with all applicable options
210
+ let query = this.table.search(vector);
211
+ // Apply nprobes for IVF index (if supported)
212
+ if (nprobes && typeof nprobes === "number") {
213
+ try {
214
+ query = query.nprobes(nprobes);
215
+ }
216
+ catch (_e) {
217
+ // ignore
218
+ }
219
+ }
220
+ // Apply filter if provided
221
+ if (filter) {
222
+ query = query.where(filter);
223
+ }
224
+ // Execute search with limit
225
+ const resultsArray = await query.limit(limit).toArray();
226
+ return resultsArray.map((row) => ({
227
+ id: row.id,
228
+ content: row.content,
229
+ metadata: row.metadata ? JSON.parse(row.metadata) : null,
230
+ // _distance is internal LanceDB property
231
+ score: row._distance,
232
+ created_at: row.created_at,
233
+ vector: row.vector, // Include vector if returned
234
+ }));
235
+ });
236
+ }
237
+ /**
238
+ * Get a record by ID
239
+ * @param {string} id - Record ID
240
+ * @returns {Promise<Object|null>} Record object or null if not found
241
+ * @throws {QueryError} If query fails
242
+ */
243
+ async getById(id) {
244
+ if (!this.isConnected) {
245
+ await this.connect();
246
+ }
247
+ return this._retryOperation(async () => {
248
+ if (!this.table) {
249
+ throw new StorageError("Table not initialized");
250
+ }
251
+ // Use a simple filter query instead of search
252
+ const resultsArray = await this.table
253
+ .query()
254
+ .where(`id == '${this._sanitizeId(id)}'`)
255
+ .toArray();
256
+ if (resultsArray.length === 0) {
257
+ return null;
258
+ }
259
+ const record = resultsArray[0];
260
+ return {
261
+ id: record.id,
262
+ vector: record.vector,
263
+ content: record.content,
264
+ metadata: record.metadata
265
+ ? JSON.parse(record.metadata)
266
+ : null,
267
+ created_at: record.created_at,
268
+ updated_at: record.updated_at,
269
+ };
270
+ });
271
+ }
272
+ /**
273
+ * Get all records from the database
274
+ * @param {Object} options - Options
275
+ * @returns {Promise<Array<Object>>} Array of all records
276
+ */
277
+ async getAll(options = {}) {
278
+ if (!this.isConnected) {
279
+ await this.connect();
280
+ }
281
+ return this._retryOperation(async () => {
282
+ if (!this.table) {
283
+ throw new StorageError("Table not initialized");
284
+ }
285
+ let query = this.table.query();
286
+ if (options.limit) {
287
+ query = query.limit(options.limit);
288
+ }
289
+ const resultsArray = await query.toArray();
290
+ return resultsArray.map((row) => ({
291
+ id: row.id,
292
+ content: row.content,
293
+ metadata: row.metadata ? JSON.parse(row.metadata) : null,
294
+ vector: row.vector,
295
+ created_at: row.created_at,
296
+ updated_at: row.updated_at,
297
+ }));
298
+ });
299
+ }
300
+ /**
301
+ * Delete a record by ID
302
+ * @param {string} id - Record ID to delete
303
+ * @returns {Promise<Object>} Result with success status
304
+ * @throws {StorageError} If delete fails
305
+ */
306
+ async delete(id) {
307
+ if (!this.isConnected) {
308
+ await this.connect();
309
+ }
310
+ return this._retryOperation(async () => {
311
+ if (!this.table) {
312
+ throw new StorageError("Table not initialized");
313
+ }
314
+ await this.table.delete(`id == '${this._sanitizeId(id)}'`);
315
+ return {
316
+ id,
317
+ success: true,
318
+ };
319
+ });
320
+ }
321
+ /**
322
+ * Update an existing record
323
+ * @param {string} id - Record ID to update
324
+ * @param {Object} data - Updated data fields
325
+ * @returns {Promise<Object>} Result with success status
326
+ * @throws {StorageError} If update fails
327
+ */
328
+ async update(id, data) {
329
+ if (!this.isConnected) {
330
+ await this.connect();
331
+ }
332
+ return this._retryOperation(async () => {
333
+ const updateData = {
334
+ ...data,
335
+ updated_at: new Date(),
336
+ };
337
+ if (!this.table) {
338
+ throw new StorageError("Table not initialized");
339
+ }
340
+ // Update API expects filter and values separately
341
+ await this.table.update({
342
+ where: `id == '${this._sanitizeId(id)}'`,
343
+ values: updateData,
344
+ });
345
+ return {
346
+ id,
347
+ success: true,
348
+ };
349
+ });
350
+ }
351
+ /**
352
+ * Get database statistics
353
+ * @returns {Promise<Object>} Statistics including count, size, etc.
354
+ * @throws {QueryError} If stats query fails
355
+ */
356
+ async getStats() {
357
+ if (!this.isConnected) {
358
+ await this.connect();
359
+ }
360
+ return this._retryOperation(async () => {
361
+ if (!this.table) {
362
+ throw new StorageError("Table not initialized");
363
+ }
364
+ let count = 0;
365
+ try {
366
+ if (typeof this.table.count === "function") {
367
+ count = await this.table.count();
368
+ }
369
+ else {
370
+ // Fallback: use a limited query to avoid loading all records
371
+ const countResults = await this.table.query().execute();
372
+ for await (const batch of countResults) {
373
+ count += batch.numRows;
374
+ }
375
+ }
376
+ }
377
+ catch (_countError) {
378
+ count = -1;
379
+ }
380
+ return {
381
+ tableName: this.tableName,
382
+ uri: this.uri,
383
+ count: count,
384
+ isConnected: this.isConnected,
385
+ };
386
+ });
387
+ }
388
+ /**
389
+ * Sanitize an ID to prevent SQL injection
390
+ * Removes any characters that aren't alphanumeric, underscore, or hyphen
391
+ * @private
392
+ */
393
+ _sanitizeId(id) {
394
+ // Remove any characters that aren't alphanumeric, underscore, or hyphen
395
+ // This prevents SQL injection via raw string interpolation in queries
396
+ return id.replace(/[^a-zA-Z0-9_-]/g, "");
397
+ }
398
+ /**
399
+ * Validate a record object
400
+ * @private
401
+ */
402
+ _validateRecord(record) {
403
+ if (!record || typeof record !== "object") {
404
+ throw new StorageError("Record must be an object");
405
+ }
406
+ if (!record.id) {
407
+ throw new StorageError("Record must have an id field");
408
+ }
409
+ if (!record.content) {
410
+ throw new StorageError("Record must have a content field");
411
+ }
412
+ if (!record.vector) {
413
+ throw new StorageError("Record must have a vector field");
414
+ }
415
+ this._validateVector(record.vector);
416
+ }
417
+ /**
418
+ * Validate a vector array
419
+ * @private
420
+ */
421
+ _validateVector(vector) {
422
+ if (!Array.isArray(vector)) {
423
+ throw new QueryError("Vector must be an array");
424
+ }
425
+ // Expected dimension for all-MiniLM-L6-v2 model
426
+ // This should ideally match this.vectorDimension
427
+ // But keeping as is to match original logic or update to use this.vectorDimension
428
+ const expectedDim = this.vectorDimension || 384;
429
+ if (vector.length !== expectedDim) {
430
+ // Loose validation for now as different models have different dims
431
+ // throw new QueryError(`Vector must have ${expectedDim} dimensions, got ${vector.length}`);
432
+ }
433
+ // Validate all elements are numbers
434
+ for (let i = 0; i < vector.length; i++) {
435
+ if (typeof vector[i] !== "number" || isNaN(vector[i])) {
436
+ throw new QueryError(`Vector element ${i} is not a valid number`);
437
+ }
438
+ }
439
+ }
440
+ /**
441
+ * Sleep for a specified duration
442
+ * @private
443
+ */
444
+ _sleep(ms) {
445
+ return new Promise((resolve) => setTimeout(resolve, ms));
446
+ }
447
+ /**
448
+ * Check if an error is retryable (transient network/connection issues)
449
+ * @private
450
+ */
451
+ _isRetryableError(error) {
452
+ if (!error || !error.message) {
453
+ return false;
454
+ }
455
+ const message = error.message.toLowerCase();
456
+ // Network-related errors
457
+ const retryablePatterns = [
458
+ "econnreset", // Connection reset by peer
459
+ "etimedout", // Operation timed out
460
+ "enotfound", // DNS resolution failed
461
+ "econnrefused", // Connection refused
462
+ "enetunreach", // Network unreachable
463
+ "ehostunreach", // Host unreachable
464
+ "socket hang up", // Socket closed unexpectedly
465
+ "network error", // Generic network error
466
+ "failed to fetch", // Fetch/network failure
467
+ "timeout", // Timeout occurred
468
+ ];
469
+ // Check for network patterns
470
+ const hasNetworkPattern = retryablePatterns.some((pattern) => message.includes(pattern));
471
+ // Check for 5xx HTTP errors (server-side errors that may be transient)
472
+ const hasServerError = /5\d{2}/.test(message);
473
+ // Check for specific LanceDB/lancedb errors that may be transient
474
+ const lancedbRetryable = [
475
+ "connection",
476
+ "database closed",
477
+ "table not found",
478
+ "lock",
479
+ "busy",
480
+ "temporary",
481
+ ].some((pattern) => message.includes(pattern));
482
+ return hasNetworkPattern || hasServerError || lancedbRetryable;
483
+ }
484
+ /**
485
+ * Retry an operation with exponential backoff
486
+ * @private
487
+ */
488
+ async _retryOperation(operation, maxRetries, baseDelay) {
489
+ const max = maxRetries ?? this.maxRetries;
490
+ const delay = baseDelay ?? this.retryDelay;
491
+ let lastError = null;
492
+ for (let attempt = 1; attempt <= max; attempt++) {
493
+ try {
494
+ return await operation();
495
+ }
496
+ catch (error) {
497
+ lastError = error;
498
+ if (!this._isRetryableError(error)) {
499
+ throw error;
500
+ }
501
+ if (attempt === max) {
502
+ throw error;
503
+ }
504
+ const backoffMs = delay * Math.pow(2, attempt - 1);
505
+ const jitterMs = backoffMs * Math.random() * 0.25;
506
+ const message = error instanceof Error ? error.message : String(error);
507
+ logger.debug({
508
+ attempt,
509
+ max,
510
+ message,
511
+ retryDelayMs: Math.round(backoffMs + jitterMs),
512
+ }, "Retryable error, retrying");
513
+ await this._sleep(backoffMs + jitterMs);
514
+ }
515
+ }
516
+ throw lastError;
517
+ }
518
+ }
519
+ export default LanceDBClient;
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Default configuration values
3
+ */
4
+ export declare const DEFAULTS: {
5
+ LANCEDB_URI: string;
6
+ LANCEDB_MEMORY_TABLE: string;
7
+ LANCEDB_MAX_CACHE_SIZE: string;
8
+ EMBEDDING_MODEL_TYPE: string;
9
+ EMBEDDING_MODEL_NAME: string;
10
+ EMBEDDING_DIMENSION: string;
11
+ EMBEDDING_BATCH_SIZE: string;
12
+ EMBEDDING_NORMALIZE: string;
13
+ OPENAI_EMBEDDING_MODEL: string;
14
+ DEFAULT_TOP_K: string;
15
+ DEFAULT_SIMILARITY_THRESHOLD: string;
16
+ ENABLE_HYBRID_SEARCH: string;
17
+ HYBRID_SEARCH_ALPHA: string;
18
+ VECTOR_INDEX_TYPE: string;
19
+ IVF_PARTITIONS: string;
20
+ PQ_BITS: string;
21
+ ENABLE_QUERY_CACHE: string;
22
+ QUERY_CACHE_TTL: string;
23
+ };
24
+ /**
25
+ * Memory system configuration defaults
26
+ */
27
+ export declare const MEMORY_DEFAULTS: {
28
+ MEMORY_ENABLED: string;
29
+ MEMORY_AUTO_CAPTURE: string;
30
+ MEMORY_AUTO_RECALL: string;
31
+ MEMORY_MAX_CONTEXT: string;
32
+ MEMORY_RELEVANCE_THRESHOLD: string;
33
+ MEMORY_IMPORTANCE_BOOST: string;
34
+ MEMORY_RECENCY_WEIGHT: string;
35
+ MEMORY_MIN_IMPORTANCE: string;
36
+ MEMORY_DEDUP_THRESHOLD: string;
37
+ MEMORY_CAPTURE_TOOL_RESULTS: string;
38
+ MEMORY_CAPTURE_FILE_OPS: string;
39
+ MEMORY_RETENTION_ENABLED: string;
40
+ MEMORY_RETENTION_DAYS: string;
41
+ MEMORY_MAX_PER_SESSION: string;
42
+ MEMORY_MIN_IMPORTANCE_TO_KEEP: string;
43
+ MEMORY_REDACT_PII: string;
44
+ MEMORY_ENCRYPTION_ENABLED: string;
45
+ };
46
+ /**
47
+ * Load configuration with validation
48
+ */
49
+ export declare function loadConfig(): {};
50
+ /**
51
+ * Load memory-specific configuration
52
+ * @returns {Object} Memory configuration object
53
+ */
54
+ export declare function loadMemoryConfig(): {
55
+ enabled: boolean;
56
+ autoCapture: boolean;
57
+ autoRecall: boolean;
58
+ maxContext: number;
59
+ relevanceThreshold: number;
60
+ importanceBoost: number;
61
+ recencyWeight: number;
62
+ minImportance: number;
63
+ dedupThreshold: number;
64
+ captureToolResults: boolean;
65
+ captureFileOps: boolean;
66
+ retention: {
67
+ enabled: boolean;
68
+ days: number;
69
+ maxPerSession: number;
70
+ minImportanceToKeep: number;
71
+ };
72
+ privacy: {
73
+ redactPii: boolean;
74
+ encryptionEnabled: boolean;
75
+ };
76
+ };
77
+ /**
78
+ * Validate configuration
79
+ */
80
+ export declare function validateConfig(config: any): any[];
81
+ /**
82
+ * Get validated configuration
83
+ */
84
+ export declare function getConfig(): {};
85
+ declare const _default: {
86
+ loadConfig: typeof loadConfig;
87
+ validateConfig: typeof validateConfig;
88
+ getConfig: typeof getConfig;
89
+ loadMemoryConfig: typeof loadMemoryConfig;
90
+ DEFAULTS: {
91
+ LANCEDB_URI: string;
92
+ LANCEDB_MEMORY_TABLE: string;
93
+ LANCEDB_MAX_CACHE_SIZE: string;
94
+ EMBEDDING_MODEL_TYPE: string;
95
+ EMBEDDING_MODEL_NAME: string;
96
+ EMBEDDING_DIMENSION: string;
97
+ EMBEDDING_BATCH_SIZE: string;
98
+ EMBEDDING_NORMALIZE: string;
99
+ OPENAI_EMBEDDING_MODEL: string;
100
+ DEFAULT_TOP_K: string;
101
+ DEFAULT_SIMILARITY_THRESHOLD: string;
102
+ ENABLE_HYBRID_SEARCH: string;
103
+ HYBRID_SEARCH_ALPHA: string;
104
+ VECTOR_INDEX_TYPE: string;
105
+ IVF_PARTITIONS: string;
106
+ PQ_BITS: string;
107
+ ENABLE_QUERY_CACHE: string;
108
+ QUERY_CACHE_TTL: string;
109
+ };
110
+ MEMORY_DEFAULTS: {
111
+ MEMORY_ENABLED: string;
112
+ MEMORY_AUTO_CAPTURE: string;
113
+ MEMORY_AUTO_RECALL: string;
114
+ MEMORY_MAX_CONTEXT: string;
115
+ MEMORY_RELEVANCE_THRESHOLD: string;
116
+ MEMORY_IMPORTANCE_BOOST: string;
117
+ MEMORY_RECENCY_WEIGHT: string;
118
+ MEMORY_MIN_IMPORTANCE: string;
119
+ MEMORY_DEDUP_THRESHOLD: string;
120
+ MEMORY_CAPTURE_TOOL_RESULTS: string;
121
+ MEMORY_CAPTURE_FILE_OPS: string;
122
+ MEMORY_RETENTION_ENABLED: string;
123
+ MEMORY_RETENTION_DAYS: string;
124
+ MEMORY_MAX_PER_SESSION: string;
125
+ MEMORY_MIN_IMPORTANCE_TO_KEEP: string;
126
+ MEMORY_REDACT_PII: string;
127
+ MEMORY_ENCRYPTION_ENABLED: string;
128
+ };
129
+ };
130
+ export default _default;