@robthepcguy/rag-vault 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 (131) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +421 -0
  3. package/dist/bin/install-skills.d.ts +20 -0
  4. package/dist/bin/install-skills.d.ts.map +1 -0
  5. package/dist/bin/install-skills.js +196 -0
  6. package/dist/bin/install-skills.js.map +1 -0
  7. package/dist/chunker/index.d.ts +11 -0
  8. package/dist/chunker/index.d.ts.map +1 -0
  9. package/dist/chunker/index.js +6 -0
  10. package/dist/chunker/index.js.map +1 -0
  11. package/dist/chunker/semantic-chunker.d.ts +96 -0
  12. package/dist/chunker/semantic-chunker.d.ts.map +1 -0
  13. package/dist/chunker/semantic-chunker.js +267 -0
  14. package/dist/chunker/semantic-chunker.js.map +1 -0
  15. package/dist/chunker/sentence-splitter.d.ts +16 -0
  16. package/dist/chunker/sentence-splitter.d.ts.map +1 -0
  17. package/dist/chunker/sentence-splitter.js +114 -0
  18. package/dist/chunker/sentence-splitter.js.map +1 -0
  19. package/dist/embedder/index.d.ts +55 -0
  20. package/dist/embedder/index.d.ts.map +1 -0
  21. package/dist/embedder/index.js +146 -0
  22. package/dist/embedder/index.js.map +1 -0
  23. package/dist/errors/index.d.ts +73 -0
  24. package/dist/errors/index.d.ts.map +1 -0
  25. package/dist/errors/index.js +170 -0
  26. package/dist/errors/index.js.map +1 -0
  27. package/dist/index.d.ts +3 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +91 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/parser/html-parser.d.ts +14 -0
  32. package/dist/parser/html-parser.d.ts.map +1 -0
  33. package/dist/parser/html-parser.js +99 -0
  34. package/dist/parser/html-parser.js.map +1 -0
  35. package/dist/parser/index.d.ts +144 -0
  36. package/dist/parser/index.d.ts.map +1 -0
  37. package/dist/parser/index.js +446 -0
  38. package/dist/parser/index.js.map +1 -0
  39. package/dist/parser/pdf-filter.d.ts +89 -0
  40. package/dist/parser/pdf-filter.d.ts.map +1 -0
  41. package/dist/parser/pdf-filter.js +304 -0
  42. package/dist/parser/pdf-filter.js.map +1 -0
  43. package/dist/server/index.d.ts +144 -0
  44. package/dist/server/index.d.ts.map +1 -0
  45. package/dist/server/index.js +518 -0
  46. package/dist/server/index.js.map +1 -0
  47. package/dist/server/raw-data-utils.d.ts +81 -0
  48. package/dist/server/raw-data-utils.d.ts.map +1 -0
  49. package/dist/server/raw-data-utils.js +196 -0
  50. package/dist/server/raw-data-utils.js.map +1 -0
  51. package/dist/server/schemas.d.ts +186 -0
  52. package/dist/server/schemas.d.ts.map +1 -0
  53. package/dist/server/schemas.js +99 -0
  54. package/dist/server/schemas.js.map +1 -0
  55. package/dist/utils/config-parsers.d.ts +14 -0
  56. package/dist/utils/config-parsers.d.ts.map +1 -0
  57. package/dist/utils/config-parsers.js +47 -0
  58. package/dist/utils/config-parsers.js.map +1 -0
  59. package/dist/utils/config.d.ts +37 -0
  60. package/dist/utils/config.d.ts.map +1 -0
  61. package/dist/utils/config.js +52 -0
  62. package/dist/utils/config.js.map +1 -0
  63. package/dist/utils/logger.d.ts +36 -0
  64. package/dist/utils/logger.d.ts.map +1 -0
  65. package/dist/utils/logger.js +64 -0
  66. package/dist/utils/logger.js.map +1 -0
  67. package/dist/utils/math.d.ts +34 -0
  68. package/dist/utils/math.d.ts.map +1 -0
  69. package/dist/utils/math.js +73 -0
  70. package/dist/utils/math.js.map +1 -0
  71. package/dist/utils/process-handlers.d.ts +26 -0
  72. package/dist/utils/process-handlers.d.ts.map +1 -0
  73. package/dist/utils/process-handlers.js +69 -0
  74. package/dist/utils/process-handlers.js.map +1 -0
  75. package/dist/vectordb/index.d.ts +210 -0
  76. package/dist/vectordb/index.d.ts.map +1 -0
  77. package/dist/vectordb/index.js +613 -0
  78. package/dist/vectordb/index.js.map +1 -0
  79. package/dist/web/api-routes.d.ts +9 -0
  80. package/dist/web/api-routes.d.ts.map +1 -0
  81. package/dist/web/api-routes.js +127 -0
  82. package/dist/web/api-routes.js.map +1 -0
  83. package/dist/web/config-routes.d.ts +7 -0
  84. package/dist/web/config-routes.d.ts.map +1 -0
  85. package/dist/web/config-routes.js +54 -0
  86. package/dist/web/config-routes.js.map +1 -0
  87. package/dist/web/database-manager.d.ts +130 -0
  88. package/dist/web/database-manager.d.ts.map +1 -0
  89. package/dist/web/database-manager.js +382 -0
  90. package/dist/web/database-manager.js.map +1 -0
  91. package/dist/web/http-server.d.ts +28 -0
  92. package/dist/web/http-server.d.ts.map +1 -0
  93. package/dist/web/http-server.js +311 -0
  94. package/dist/web/http-server.js.map +1 -0
  95. package/dist/web/index.d.ts +3 -0
  96. package/dist/web/index.d.ts.map +1 -0
  97. package/dist/web/index.js +114 -0
  98. package/dist/web/index.js.map +1 -0
  99. package/dist/web/middleware/async-handler.d.ts +17 -0
  100. package/dist/web/middleware/async-handler.d.ts.map +1 -0
  101. package/dist/web/middleware/async-handler.js +26 -0
  102. package/dist/web/middleware/async-handler.js.map +1 -0
  103. package/dist/web/middleware/auth.d.ts +22 -0
  104. package/dist/web/middleware/auth.d.ts.map +1 -0
  105. package/dist/web/middleware/auth.js +81 -0
  106. package/dist/web/middleware/auth.js.map +1 -0
  107. package/dist/web/middleware/error-handler.d.ts +36 -0
  108. package/dist/web/middleware/error-handler.d.ts.map +1 -0
  109. package/dist/web/middleware/error-handler.js +68 -0
  110. package/dist/web/middleware/error-handler.js.map +1 -0
  111. package/dist/web/middleware/index.d.ts +6 -0
  112. package/dist/web/middleware/index.d.ts.map +1 -0
  113. package/dist/web/middleware/index.js +19 -0
  114. package/dist/web/middleware/index.js.map +1 -0
  115. package/dist/web/middleware/rate-limit.d.ts +38 -0
  116. package/dist/web/middleware/rate-limit.d.ts.map +1 -0
  117. package/dist/web/middleware/rate-limit.js +116 -0
  118. package/dist/web/middleware/rate-limit.js.map +1 -0
  119. package/dist/web/middleware/request-logger.d.ts +52 -0
  120. package/dist/web/middleware/request-logger.d.ts.map +1 -0
  121. package/dist/web/middleware/request-logger.js +74 -0
  122. package/dist/web/middleware/request-logger.js.map +1 -0
  123. package/dist/web/types.d.ts +6 -0
  124. package/dist/web/types.d.ts.map +1 -0
  125. package/dist/web/types.js +4 -0
  126. package/dist/web/types.js.map +1 -0
  127. package/package.json +135 -0
  128. package/skills/rag-vault/SKILL.md +111 -0
  129. package/skills/rag-vault/references/html-ingestion.md +73 -0
  130. package/skills/rag-vault/references/query-optimization.md +57 -0
  131. package/skills/rag-vault/references/result-refinement.md +54 -0
@@ -0,0 +1,613 @@
1
+ "use strict";
2
+ // VectorStore implementation with LanceDB integration
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.VectorStore = exports.DatabaseError = void 0;
5
+ const lancedb_1 = require("@lancedb/lancedb");
6
+ const index_js_1 = require("../errors/index.js");
7
+ // Re-export error class for backwards compatibility
8
+ var index_js_2 = require("../errors/index.js");
9
+ Object.defineProperty(exports, "DatabaseError", { enumerable: true, get: function () { return index_js_2.DatabaseError; } });
10
+ // ============================================
11
+ // Constants
12
+ // ============================================
13
+ /**
14
+ * Standard deviation multiplier for detecting group boundaries.
15
+ * A gap is considered a "boundary" if it exceeds mean + k*std.
16
+ * Value of 1.5 means gaps > 1.5 standard deviations above mean are boundaries.
17
+ */
18
+ const GROUPING_BOUNDARY_STD_MULTIPLIER = 1.5;
19
+ /** Multiplier for candidate count in hybrid search (to allow reranking) */
20
+ const HYBRID_SEARCH_CANDIDATE_MULTIPLIER = 2;
21
+ /** FTS index name (bump version when changing tokenizer settings) */
22
+ const FTS_INDEX_NAME = 'fts_index_v2';
23
+ /** Threshold for cleaning up old index versions (1 minute) */
24
+ const FTS_CLEANUP_THRESHOLD_MS = 60 * 1000;
25
+ /** FTS circuit breaker: max failures before disabling FTS */
26
+ const FTS_MAX_FAILURES = 3;
27
+ /** FTS circuit breaker: cooldown period before retry (5 minutes) */
28
+ const FTS_COOLDOWN_MS = 5 * 60 * 1000;
29
+ // ============================================
30
+ // Error Codes (for robust error handling)
31
+ // ============================================
32
+ /**
33
+ * Known LanceDB error patterns for delete operations
34
+ * Used instead of fragile string matching
35
+ */
36
+ const DELETE_IGNORABLE_PATTERNS = [
37
+ 'not found',
38
+ 'does not exist',
39
+ 'no matching',
40
+ 'no rows',
41
+ 'empty result',
42
+ ];
43
+ /**
44
+ * Regex for validating file paths before use in queries.
45
+ * Allows alphanumeric characters, slashes, dots, underscores, hyphens, colons (Windows), and spaces.
46
+ * Rejects paths with SQL injection attempts or path traversal.
47
+ */
48
+ const SAFE_PATH_REGEX = /^[a-zA-Z0-9\\/_.:\- ]+$/;
49
+ /**
50
+ * Validate file path to prevent SQL injection and path traversal attacks.
51
+ * @param filePath - The file path to validate
52
+ * @returns true if path is safe for use in queries
53
+ */
54
+ function isValidFilePath(filePath) {
55
+ if (!filePath || typeof filePath !== 'string')
56
+ return false;
57
+ if (filePath.includes('..'))
58
+ return false; // Path traversal
59
+ if (filePath.includes("'") || filePath.includes('"'))
60
+ return false; // Quote injection
61
+ if (filePath.includes(';'))
62
+ return false; // SQL terminator
63
+ if (filePath.includes('--'))
64
+ return false; // SQL comment
65
+ return SAFE_PATH_REGEX.test(filePath);
66
+ }
67
+ // ============================================
68
+ // Type Guards
69
+ // ============================================
70
+ /**
71
+ * Type guard for DocumentMetadata
72
+ */
73
+ function isDocumentMetadata(value) {
74
+ if (typeof value !== 'object' || value === null)
75
+ return false;
76
+ const obj = value;
77
+ return (typeof obj['fileName'] === 'string' &&
78
+ typeof obj['fileSize'] === 'number' &&
79
+ typeof obj['fileType'] === 'string');
80
+ }
81
+ /**
82
+ * Type guard for LanceDB raw search result
83
+ */
84
+ function isLanceDBRawResult(value) {
85
+ if (typeof value !== 'object' || value === null)
86
+ return false;
87
+ const obj = value;
88
+ return (typeof obj['filePath'] === 'string' &&
89
+ typeof obj['chunkIndex'] === 'number' &&
90
+ typeof obj['text'] === 'string' &&
91
+ isDocumentMetadata(obj['metadata']));
92
+ }
93
+ /**
94
+ * Convert LanceDB raw result to SearchResult with type validation
95
+ * @throws DatabaseError if the result is invalid
96
+ */
97
+ function toSearchResult(raw) {
98
+ if (!isLanceDBRawResult(raw)) {
99
+ throw new index_js_1.DatabaseError('Invalid search result format from LanceDB');
100
+ }
101
+ return {
102
+ filePath: raw.filePath,
103
+ chunkIndex: raw.chunkIndex,
104
+ text: raw.text,
105
+ score: raw._distance ?? raw._score ?? 0,
106
+ metadata: raw.metadata,
107
+ };
108
+ }
109
+ // ============================================
110
+ // VectorStore Class
111
+ // ============================================
112
+ /**
113
+ * Vector storage class using LanceDB
114
+ *
115
+ * Responsibilities:
116
+ * - LanceDB operations (insert, delete, search)
117
+ * - Transaction handling (atomicity of delete→insert)
118
+ * - Metadata management
119
+ *
120
+ * FTS Circuit Breaker:
121
+ * - Tracks FTS failures (max 3 before disabling)
122
+ * - Auto-recovers after 5-minute cooldown
123
+ * - Prevents permanent FTS disable from transient errors
124
+ */
125
+ class VectorStore {
126
+ constructor(config) {
127
+ this.db = null;
128
+ this.table = null;
129
+ this.ftsEnabled = false;
130
+ this.ftsFailureCount = 0;
131
+ this.ftsLastFailure = null;
132
+ /** Mutex to prevent race conditions in circuit breaker state transitions */
133
+ this.circuitBreakerResetting = false;
134
+ this.config = config;
135
+ }
136
+ /**
137
+ * Check if FTS should be attempted (circuit breaker logic)
138
+ * - Returns false if max failures reached and cooldown not elapsed
139
+ * - Resets failure count after successful cooldown period
140
+ * - Uses mutex to prevent race conditions during reset
141
+ */
142
+ shouldAttemptFts() {
143
+ if (!this.ftsEnabled)
144
+ return false;
145
+ // If under failure threshold, allow FTS
146
+ if (this.ftsFailureCount < FTS_MAX_FAILURES)
147
+ return true;
148
+ // Check if cooldown period has elapsed
149
+ if (this.ftsLastFailure && Date.now() - this.ftsLastFailure > FTS_COOLDOWN_MS) {
150
+ // Use mutex to prevent multiple concurrent resets (race condition protection)
151
+ if (this.circuitBreakerResetting) {
152
+ // Another call is already resetting, don't allow FTS yet
153
+ return false;
154
+ }
155
+ // Acquire mutex and reset circuit breaker (half-open state)
156
+ this.circuitBreakerResetting = true;
157
+ this.ftsFailureCount = 0;
158
+ this.ftsLastFailure = null;
159
+ this.circuitBreakerResetting = false;
160
+ console.error('VectorStore: FTS circuit breaker reset - attempting recovery');
161
+ return true;
162
+ }
163
+ return false;
164
+ }
165
+ /**
166
+ * Record FTS failure (circuit breaker)
167
+ */
168
+ recordFtsFailure(error) {
169
+ this.ftsFailureCount++;
170
+ this.ftsLastFailure = Date.now();
171
+ console.error(`VectorStore: FTS failure ${this.ftsFailureCount}/${FTS_MAX_FAILURES}: ${error.message}`);
172
+ if (this.ftsFailureCount >= FTS_MAX_FAILURES) {
173
+ console.error(`VectorStore: FTS circuit breaker OPEN - will retry after ${FTS_COOLDOWN_MS / 1000}s cooldown`);
174
+ }
175
+ }
176
+ /**
177
+ * Record FTS success (resets circuit breaker)
178
+ */
179
+ recordFtsSuccess() {
180
+ if (this.ftsFailureCount > 0) {
181
+ console.error('VectorStore: FTS recovered successfully - circuit breaker reset');
182
+ this.ftsFailureCount = 0;
183
+ this.ftsLastFailure = null;
184
+ }
185
+ }
186
+ /**
187
+ * Initialize LanceDB and create table
188
+ */
189
+ async initialize() {
190
+ try {
191
+ // Connect to LanceDB
192
+ this.db = await (0, lancedb_1.connect)(this.config.dbPath);
193
+ // Check table existence and create if needed
194
+ const tableNames = await this.db.tableNames();
195
+ if (tableNames.includes(this.config.tableName)) {
196
+ // Open existing table
197
+ this.table = await this.db.openTable(this.config.tableName);
198
+ console.error(`VectorStore: Opened existing table "${this.config.tableName}"`);
199
+ // Ensure FTS index exists (migration for existing databases)
200
+ await this.ensureFtsIndex();
201
+ }
202
+ else {
203
+ // Create new table (schema auto-defined on first data insertion)
204
+ console.error(`VectorStore: Table "${this.config.tableName}" will be created on first data insertion`);
205
+ }
206
+ console.error(`VectorStore initialized: ${this.config.dbPath}`);
207
+ }
208
+ catch (error) {
209
+ throw new index_js_1.DatabaseError('Failed to initialize VectorStore', error);
210
+ }
211
+ }
212
+ /**
213
+ * Delete all chunks for specified file path
214
+ *
215
+ * @param filePath - File path (absolute)
216
+ */
217
+ async deleteChunks(filePath) {
218
+ if (!this.table) {
219
+ // If table doesn't exist, no deletion targets, return normally
220
+ console.error('VectorStore: Skipping deletion as table does not exist');
221
+ return;
222
+ }
223
+ // Validate file path before use in query to prevent SQL injection
224
+ if (!isValidFilePath(filePath)) {
225
+ throw new index_js_1.DatabaseError(`Invalid file path: contains disallowed characters or patterns`);
226
+ }
227
+ // Escape path before try block so it's available in catch for logging
228
+ const escapedFilePath = filePath.replace(/'/g, "''");
229
+ try {
230
+ // Use LanceDB delete API to remove records matching filePath
231
+ // Path is pre-validated, escaping is belt-and-suspenders defense
232
+ // LanceDB's delete method doesn't throw errors if targets don't exist,
233
+ // so call delete directly
234
+ // Note: Field names are case-sensitive, use backticks for camelCase fields
235
+ await this.table.delete(`\`filePath\` = '${escapedFilePath}'`);
236
+ console.error(`VectorStore: Deleted chunks for file "${filePath}"`);
237
+ // Rebuild FTS index after deleting data
238
+ await this.rebuildFtsIndex();
239
+ }
240
+ catch (error) {
241
+ // Build error context for debugging
242
+ const errorContext = {
243
+ operation: 'deleteChunks',
244
+ filePath,
245
+ query: `\`filePath\` = '${escapedFilePath}'`,
246
+ errorMessage: error.message,
247
+ };
248
+ console.warn('VectorStore delete error:', errorContext);
249
+ // Check if this is a known ignorable error (no matching records)
250
+ const errorMessage = error.message.toLowerCase();
251
+ const isIgnorable = DELETE_IGNORABLE_PATTERNS.some((pattern) => errorMessage.includes(pattern));
252
+ if (!isIgnorable) {
253
+ throw new index_js_1.DatabaseError(`Failed to delete chunks for file: ${filePath}`, error);
254
+ }
255
+ // Ignorable errors (no matching records) are logged but not thrown
256
+ }
257
+ }
258
+ /**
259
+ * Batch insert vector chunks
260
+ *
261
+ * @param chunks - Array of vector chunks
262
+ */
263
+ async insertChunks(chunks) {
264
+ if (chunks.length === 0) {
265
+ return;
266
+ }
267
+ try {
268
+ if (!this.table) {
269
+ // Create table on first insertion
270
+ if (!this.db) {
271
+ throw new index_js_1.DatabaseError('VectorStore is not initialized. Call initialize() first.');
272
+ }
273
+ // LanceDB's createTable API accepts data as Record<string, unknown>[]
274
+ const records = chunks.map((chunk) => chunk);
275
+ this.table = await this.db.createTable(this.config.tableName, records);
276
+ console.error(`VectorStore: Created table "${this.config.tableName}"`);
277
+ // Create FTS index for hybrid search
278
+ await this.ensureFtsIndex();
279
+ }
280
+ else {
281
+ // Add data to existing table
282
+ const records = chunks.map((chunk) => chunk);
283
+ await this.table.add(records);
284
+ // Rebuild FTS index after adding new data
285
+ await this.rebuildFtsIndex();
286
+ }
287
+ console.error(`VectorStore: Inserted ${chunks.length} chunks`);
288
+ }
289
+ catch (error) {
290
+ throw new index_js_1.DatabaseError('Failed to insert chunks', error);
291
+ }
292
+ }
293
+ /**
294
+ * Ensure FTS index exists for hybrid search
295
+ * Creates ngram-based index if it doesn't exist, drops old versions
296
+ * @throws DatabaseError if index creation fails (Fail-Fast principle)
297
+ */
298
+ async ensureFtsIndex() {
299
+ if (!this.table) {
300
+ return;
301
+ }
302
+ // Check existing indices
303
+ const indices = await this.table.listIndices();
304
+ const existingFtsIndices = indices.filter((idx) => idx.indexType === 'FTS');
305
+ const hasExpectedIndex = existingFtsIndices.some((idx) => idx.name === FTS_INDEX_NAME);
306
+ if (hasExpectedIndex) {
307
+ this.ftsEnabled = true;
308
+ return;
309
+ }
310
+ // Create new FTS index with ngram tokenizer for multilingual support
311
+ // - min=2: Capture Japanese bi-grams (e.g., "東京", "設計")
312
+ // - max=3: Balance between precision and index size
313
+ // - prefixOnly=false: Generate ngrams from all positions for proper CJK support
314
+ await this.table.createIndex('text', {
315
+ config: lancedb_1.Index.fts({
316
+ baseTokenizer: 'ngram',
317
+ ngramMinLength: 2,
318
+ ngramMaxLength: 3,
319
+ prefixOnly: false,
320
+ stem: false,
321
+ }),
322
+ name: FTS_INDEX_NAME,
323
+ });
324
+ this.ftsEnabled = true;
325
+ console.error(`VectorStore: FTS index "${FTS_INDEX_NAME}" created successfully`);
326
+ // Drop old FTS indices
327
+ for (const idx of existingFtsIndices) {
328
+ if (idx.name !== FTS_INDEX_NAME) {
329
+ await this.table.dropIndex(idx.name);
330
+ console.error(`VectorStore: Dropped old FTS index "${idx.name}"`);
331
+ }
332
+ }
333
+ }
334
+ /**
335
+ * Rebuild FTS index after data changes (insert/delete)
336
+ * LanceDB OSS requires explicit optimize() call to update FTS index
337
+ * Also cleans up old index versions to prevent storage bloat
338
+ */
339
+ async rebuildFtsIndex() {
340
+ if (!this.table || !this.ftsEnabled) {
341
+ return;
342
+ }
343
+ // TODO(perf): optimize() after every write keeps FTS correct, but can be expensive at scale.
344
+ // If ingestion throughput becomes an issue, consider debouncing or batching optimize calls.
345
+ // Optimize table and clean up old versions
346
+ const cleanupThreshold = new Date(Date.now() - FTS_CLEANUP_THRESHOLD_MS);
347
+ await this.table.optimize({ cleanupOlderThan: cleanupThreshold });
348
+ }
349
+ /**
350
+ * Apply grouping algorithm to filter results by detecting group boundaries.
351
+ *
352
+ * Uses statistical threshold (mean + k*std) to identify significant gaps (group boundaries).
353
+ * - 'similar': Returns only the first group (cuts at first boundary)
354
+ * - 'related': Returns up to 2 groups (cuts at second boundary)
355
+ *
356
+ * @param results - Search results sorted by distance (ascending)
357
+ * @param mode - Grouping mode ('similar' = 1 group, 'related' = 2 groups)
358
+ * @returns Filtered results
359
+ */
360
+ applyGrouping(results, mode) {
361
+ if (results.length <= 1)
362
+ return results;
363
+ // Calculate gaps between consecutive results with their indices
364
+ const gaps = [];
365
+ for (let i = 0; i < results.length - 1; i++) {
366
+ const current = results[i];
367
+ const next = results[i + 1];
368
+ if (current !== undefined && next !== undefined) {
369
+ gaps.push({ index: i + 1, gap: next.score - current.score });
370
+ }
371
+ }
372
+ if (gaps.length === 0)
373
+ return results;
374
+ // Calculate statistical threshold to identify significant gaps (group boundaries)
375
+ const gapValues = gaps.map((g) => g.gap);
376
+ const mean = gapValues.reduce((a, b) => a + b, 0) / gapValues.length;
377
+ const variance = gapValues.reduce((a, b) => a + (b - mean) ** 2, 0) / gapValues.length;
378
+ const std = Math.sqrt(variance);
379
+ const threshold = mean + GROUPING_BOUNDARY_STD_MULTIPLIER * std;
380
+ // Find all significant gaps (group boundaries)
381
+ const boundaries = gaps.filter((g) => g.gap > threshold).map((g) => g.index);
382
+ // If no boundaries found, return all results
383
+ if (boundaries.length === 0)
384
+ return results;
385
+ // Determine how many groups to include based on mode
386
+ // 'similar': 1 group (cut at first boundary)
387
+ // 'related': 2 groups (cut at second boundary, or return all if only 1 boundary)
388
+ const groupsToInclude = mode === 'similar' ? 1 : 2;
389
+ const boundaryIndex = groupsToInclude - 1;
390
+ // If we don't have enough boundaries, return all results for 'related' mode
391
+ if (boundaryIndex >= boundaries.length) {
392
+ return mode === 'related' ? results : results.slice(0, boundaries[0]);
393
+ }
394
+ // Cut at the appropriate boundary
395
+ return results.slice(0, boundaries[boundaryIndex]);
396
+ }
397
+ /**
398
+ * Execute vector search with quality filtering
399
+ * Architecture: Semantic search → Filter (maxDistance, grouping) → Keyword boost
400
+ *
401
+ * This "prefetch then rerank" approach ensures:
402
+ * - maxDistance and grouping work on meaningful vector distances
403
+ * - Keyword matching acts as a boost, not a replacement for semantic similarity
404
+ *
405
+ * @param queryVector - Query vector (dimension depends on model)
406
+ * @param queryText - Optional query text for keyword boost (BM25)
407
+ * @param limit - Number of results to retrieve (default 10)
408
+ * @returns Array of search results (sorted by distance ascending, filtered by quality settings)
409
+ */
410
+ async search(queryVector, queryText, limit = 10) {
411
+ if (!this.table) {
412
+ console.error('VectorStore: Returning empty results as table does not exist');
413
+ return [];
414
+ }
415
+ if (limit < 1 || limit > 20) {
416
+ throw new index_js_1.DatabaseError(`Invalid limit: expected 1-20, got ${limit}`);
417
+ }
418
+ try {
419
+ // Step 1: Semantic (vector) search - always the primary search
420
+ const candidateLimit = limit * HYBRID_SEARCH_CANDIDATE_MULTIPLIER;
421
+ // Assumes normalized embeddings so dot behaves like cosine distance (lower is better, [0,2]).
422
+ let query = this.table.vectorSearch(queryVector).distanceType('dot').limit(candidateLimit);
423
+ // Apply distance threshold at query level
424
+ if (this.config.maxDistance !== undefined) {
425
+ query = query.distanceRange(undefined, this.config.maxDistance);
426
+ }
427
+ const vectorResults = await query.toArray();
428
+ // Convert to SearchResult format with type validation
429
+ let results = vectorResults.map((result) => toSearchResult(result));
430
+ // Step 2: Apply grouping filter on vector distances (before keyword boost)
431
+ // Grouping is meaningful only on semantic distances, not after keyword boost
432
+ if (this.config.grouping && results.length > 1) {
433
+ results = this.applyGrouping(results, this.config.grouping);
434
+ }
435
+ // Step 3: Apply keyword boost if enabled (with circuit breaker)
436
+ const hybridWeight = this.config.hybridWeight ?? 0.6;
437
+ if (this.shouldAttemptFts() && queryText && queryText.trim().length > 0 && hybridWeight > 0) {
438
+ try {
439
+ // Get unique filePaths from vector results to filter FTS search
440
+ const uniqueFilePaths = [...new Set(results.map((r) => r.filePath))];
441
+ // Build WHERE clause with IN for targeted FTS search
442
+ // Use backticks for column name (required for camelCase in LanceDB)
443
+ const escapedPaths = uniqueFilePaths.map((p) => `'${p.replace(/'/g, "''")}'`);
444
+ const whereClause = `\`filePath\` IN (${escapedPaths.join(', ')})`;
445
+ const ftsResults = await this.table
446
+ .search(queryText, 'fts', 'text')
447
+ .where(whereClause)
448
+ .select(['filePath', 'chunkIndex', 'text', 'metadata', '_score'])
449
+ .limit(results.length * 2) // Enough to cover all vector results
450
+ .toArray();
451
+ results = this.applyKeywordBoost(results, ftsResults, hybridWeight);
452
+ // FTS succeeded - reset circuit breaker
453
+ this.recordFtsSuccess();
454
+ }
455
+ catch (ftsError) {
456
+ // Record failure for circuit breaker (will auto-recover after cooldown)
457
+ this.recordFtsFailure(ftsError);
458
+ // Continue with vector-only results
459
+ }
460
+ }
461
+ // Return top results after all filtering and boosting
462
+ return results.slice(0, limit);
463
+ }
464
+ catch (error) {
465
+ throw new index_js_1.DatabaseError('Failed to search vectors', error);
466
+ }
467
+ }
468
+ /**
469
+ * Apply keyword boost to rerank vector search results
470
+ * Uses multiplicative formula: final_distance = distance / (1 + keyword_normalized * weight)
471
+ *
472
+ * This proportional boost ensures:
473
+ * - Keyword matches improve ranking without dominating semantic similarity
474
+ * - Documents without keyword matches keep their original vector distance
475
+ * - Higher weight = stronger influence of keyword matching
476
+ *
477
+ * @param vectorResults - Results from vector search (already filtered by maxDistance/grouping)
478
+ * @param ftsResults - Raw FTS results with BM25 scores
479
+ * @param weight - Boost weight (0-1, from hybridWeight config)
480
+ */
481
+ applyKeywordBoost(vectorResults, ftsResults, weight) {
482
+ // Build FTS score map with normalized scores (0-1)
483
+ let maxBm25Score = 0;
484
+ for (const result of ftsResults) {
485
+ if (!result)
486
+ continue;
487
+ const score = result['_score'] ?? 0;
488
+ if (score > maxBm25Score)
489
+ maxBm25Score = score;
490
+ }
491
+ const ftsScoreMap = new Map();
492
+ for (const result of ftsResults) {
493
+ if (!result)
494
+ continue;
495
+ const key = `${result['filePath']}:${result['chunkIndex']}`;
496
+ const rawScore = result['_score'] ?? 0;
497
+ const normalized = maxBm25Score > 0 ? rawScore / maxBm25Score : 0;
498
+ ftsScoreMap.set(key, normalized);
499
+ }
500
+ // Apply multiplicative boost to vector results
501
+ const boostedResults = vectorResults.map((result) => {
502
+ const key = `${result.filePath}:${result.chunkIndex}`;
503
+ const keywordScore = ftsScoreMap.get(key) ?? 0;
504
+ // Multiplicative boost: distance / (1 + keyword * weight)
505
+ // - If keyword matches (score=1) and weight=1: distance halved
506
+ // - If no keyword match (score=0): distance unchanged
507
+ const boostedDistance = result.score / (1 + keywordScore * weight);
508
+ return {
509
+ ...result,
510
+ score: boostedDistance,
511
+ };
512
+ });
513
+ // Re-sort by boosted distance (ascending = better)
514
+ return boostedResults.sort((a, b) => a.score - b.score);
515
+ }
516
+ /**
517
+ * Get list of ingested files
518
+ *
519
+ * @returns Array of file information
520
+ */
521
+ async listFiles() {
522
+ if (!this.table) {
523
+ return []; // Return empty array if table doesn't exist
524
+ }
525
+ try {
526
+ // Retrieve all records
527
+ const allRecords = await this.table.query().toArray();
528
+ // Group by file path
529
+ const fileMap = new Map();
530
+ for (const record of allRecords) {
531
+ const filePath = record.filePath;
532
+ const timestamp = record.timestamp;
533
+ if (fileMap.has(filePath)) {
534
+ const fileInfo = fileMap.get(filePath);
535
+ if (fileInfo) {
536
+ fileInfo.chunkCount += 1;
537
+ // Keep most recent timestamp
538
+ if (timestamp > fileInfo.timestamp) {
539
+ fileInfo.timestamp = timestamp;
540
+ }
541
+ }
542
+ }
543
+ else {
544
+ fileMap.set(filePath, { chunkCount: 1, timestamp });
545
+ }
546
+ }
547
+ // Convert Map to array of objects
548
+ return Array.from(fileMap.entries()).map(([filePath, info]) => ({
549
+ filePath,
550
+ chunkCount: info.chunkCount,
551
+ timestamp: info.timestamp,
552
+ }));
553
+ }
554
+ catch (error) {
555
+ throw new index_js_1.DatabaseError('Failed to list files', error);
556
+ }
557
+ }
558
+ /**
559
+ * Close the database connection and release resources
560
+ */
561
+ async close() {
562
+ this.db = null;
563
+ this.table = null;
564
+ this.ftsEnabled = false;
565
+ this.ftsFailureCount = 0;
566
+ this.ftsLastFailure = null;
567
+ console.error('VectorStore: Connection closed');
568
+ }
569
+ /**
570
+ * Get system status
571
+ *
572
+ * @returns System status information
573
+ */
574
+ async getStatus() {
575
+ if (!this.table) {
576
+ return {
577
+ documentCount: 0,
578
+ chunkCount: 0,
579
+ memoryUsage: 0,
580
+ uptime: process.uptime(),
581
+ ftsIndexEnabled: false,
582
+ searchMode: 'vector-only',
583
+ };
584
+ }
585
+ try {
586
+ // Retrieve all records
587
+ const allRecords = await this.table.query().toArray();
588
+ const chunkCount = allRecords.length;
589
+ // Count unique file paths
590
+ const uniqueFilePaths = new Set(allRecords.map((record) => record.filePath));
591
+ const documentCount = uniqueFilePaths.size;
592
+ // Get memory usage (in MB)
593
+ const memoryUsage = process.memoryUsage().heapUsed / 1024 / 1024;
594
+ // Get uptime (in seconds)
595
+ const uptime = process.uptime();
596
+ // Determine effective FTS state (considering circuit breaker)
597
+ const ftsEffectivelyEnabled = this.shouldAttemptFts();
598
+ return {
599
+ documentCount,
600
+ chunkCount,
601
+ memoryUsage,
602
+ uptime,
603
+ ftsIndexEnabled: this.ftsEnabled,
604
+ searchMode: ftsEffectivelyEnabled && (this.config.hybridWeight ?? 0.6) > 0 ? 'hybrid' : 'vector-only',
605
+ };
606
+ }
607
+ catch (error) {
608
+ throw new index_js_1.DatabaseError('Failed to get status', error);
609
+ }
610
+ }
611
+ }
612
+ exports.VectorStore = VectorStore;
613
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vectordb/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { Router } from 'express';
2
+ import type { RAGServer } from '../server/index.js';
3
+ import type { ServerAccessor } from './types.js';
4
+ /**
5
+ * Create API router with all endpoints
6
+ * @param serverOrAccessor - RAGServer instance or accessor function
7
+ */
8
+ export declare function createApiRouter(serverOrAccessor: RAGServer | ServerAccessor): Router;
9
+ //# sourceMappingURL=api-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-routes.d.ts","sourceRoot":"","sources":["../../src/web/api-routes.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAqB,MAAM,EAAE,MAAM,SAAS,CAAA;AAGxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAEnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAgDhD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,gBAAgB,EAAE,SAAS,GAAG,cAAc,GAAG,MAAM,CA+HpF"}