abb-opencode-local-rag 0.1.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 (233) hide show
  1. package/LICENSE +21 -0
  2. package/README.de.md +416 -0
  3. package/README.es.md +416 -0
  4. package/README.fr.md +416 -0
  5. package/README.md +491 -0
  6. package/README.pt-BR.md +416 -0
  7. package/README.zh-CN.md +416 -0
  8. package/dist/bin/install-skills.d.ts +20 -0
  9. package/dist/bin/install-skills.d.ts.map +1 -0
  10. package/dist/bin/install-skills.js +195 -0
  11. package/dist/bin/install-skills.js.map +1 -0
  12. package/dist/chunker/index.d.ts +24 -0
  13. package/dist/chunker/index.d.ts.map +1 -0
  14. package/dist/chunker/index.js +2 -0
  15. package/dist/chunker/index.js.map +1 -0
  16. package/dist/chunker/semantic-chunker.d.ts +97 -0
  17. package/dist/chunker/semantic-chunker.d.ts.map +1 -0
  18. package/dist/chunker/semantic-chunker.js +294 -0
  19. package/dist/chunker/semantic-chunker.js.map +1 -0
  20. package/dist/chunker/sentence-splitter.d.ts +28 -0
  21. package/dist/chunker/sentence-splitter.d.ts.map +1 -0
  22. package/dist/chunker/sentence-splitter.js +219 -0
  23. package/dist/chunker/sentence-splitter.js.map +1 -0
  24. package/dist/cli/common.d.ts +65 -0
  25. package/dist/cli/common.d.ts.map +1 -0
  26. package/dist/cli/common.js +138 -0
  27. package/dist/cli/common.js.map +1 -0
  28. package/dist/cli/delete.d.ts +8 -0
  29. package/dist/cli/delete.d.ts.map +1 -0
  30. package/dist/cli/delete.js +173 -0
  31. package/dist/cli/delete.js.map +1 -0
  32. package/dist/cli/file-collection.d.ts +2 -0
  33. package/dist/cli/file-collection.d.ts.map +1 -0
  34. package/dist/cli/file-collection.js +53 -0
  35. package/dist/cli/file-collection.js.map +1 -0
  36. package/dist/cli/ingest.d.ts +100 -0
  37. package/dist/cli/ingest.d.ts.map +1 -0
  38. package/dist/cli/ingest.js +363 -0
  39. package/dist/cli/ingest.js.map +1 -0
  40. package/dist/cli/list.d.ts +35 -0
  41. package/dist/cli/list.d.ts.map +1 -0
  42. package/dist/cli/list.js +210 -0
  43. package/dist/cli/list.js.map +1 -0
  44. package/dist/cli/options.d.ts +100 -0
  45. package/dist/cli/options.d.ts.map +1 -0
  46. package/dist/cli/options.js +241 -0
  47. package/dist/cli/options.js.map +1 -0
  48. package/dist/cli/query.d.ts +24 -0
  49. package/dist/cli/query.d.ts.map +1 -0
  50. package/dist/cli/query.js +191 -0
  51. package/dist/cli/query.js.map +1 -0
  52. package/dist/cli/read-neighbors.d.ts +11 -0
  53. package/dist/cli/read-neighbors.d.ts.map +1 -0
  54. package/dist/cli/read-neighbors.js +224 -0
  55. package/dist/cli/read-neighbors.js.map +1 -0
  56. package/dist/cli/status.d.ts +8 -0
  57. package/dist/cli/status.d.ts.map +1 -0
  58. package/dist/cli/status.js +80 -0
  59. package/dist/cli/status.js.map +1 -0
  60. package/dist/cli/sync.d.ts +8 -0
  61. package/dist/cli/sync.d.ts.map +1 -0
  62. package/dist/cli/sync.js +244 -0
  63. package/dist/cli/sync.js.map +1 -0
  64. package/dist/cli-main.d.ts +12 -0
  65. package/dist/cli-main.d.ts.map +1 -0
  66. package/dist/cli-main.js +63 -0
  67. package/dist/cli-main.js.map +1 -0
  68. package/dist/embedder/index.d.ts +85 -0
  69. package/dist/embedder/index.d.ts.map +1 -0
  70. package/dist/embedder/index.js +284 -0
  71. package/dist/embedder/index.js.map +1 -0
  72. package/dist/features/list.d.ts +37 -0
  73. package/dist/features/list.d.ts.map +1 -0
  74. package/dist/features/list.js +40 -0
  75. package/dist/features/list.js.map +1 -0
  76. package/dist/features/sync.d.ts +207 -0
  77. package/dist/features/sync.d.ts.map +1 -0
  78. package/dist/features/sync.js +380 -0
  79. package/dist/features/sync.js.map +1 -0
  80. package/dist/index.d.ts +3 -0
  81. package/dist/index.d.ts.map +1 -0
  82. package/dist/index.js +53 -0
  83. package/dist/index.js.map +1 -0
  84. package/dist/ingest/compute.d.ts +86 -0
  85. package/dist/ingest/compute.d.ts.map +1 -0
  86. package/dist/ingest/compute.js +177 -0
  87. package/dist/ingest/compute.js.map +1 -0
  88. package/dist/ingest/file.d.ts +27 -0
  89. package/dist/ingest/file.d.ts.map +1 -0
  90. package/dist/ingest/file.js +67 -0
  91. package/dist/ingest/file.js.map +1 -0
  92. package/dist/ingest/visual.d.ts +45 -0
  93. package/dist/ingest/visual.d.ts.map +1 -0
  94. package/dist/ingest/visual.js +234 -0
  95. package/dist/ingest/visual.js.map +1 -0
  96. package/dist/parser/docx-parser.d.ts +12 -0
  97. package/dist/parser/docx-parser.d.ts.map +1 -0
  98. package/dist/parser/docx-parser.js +328 -0
  99. package/dist/parser/docx-parser.js.map +1 -0
  100. package/dist/parser/html-parser.d.ts +18 -0
  101. package/dist/parser/html-parser.d.ts.map +1 -0
  102. package/dist/parser/html-parser.js +102 -0
  103. package/dist/parser/html-parser.js.map +1 -0
  104. package/dist/parser/index.d.ts +214 -0
  105. package/dist/parser/index.d.ts.map +1 -0
  106. package/dist/parser/index.js +454 -0
  107. package/dist/parser/index.js.map +1 -0
  108. package/dist/parser/pdf-extract.d.ts +81 -0
  109. package/dist/parser/pdf-extract.d.ts.map +1 -0
  110. package/dist/parser/pdf-extract.js +112 -0
  111. package/dist/parser/pdf-extract.js.map +1 -0
  112. package/dist/parser/pdf-filter.d.ts +117 -0
  113. package/dist/parser/pdf-filter.d.ts.map +1 -0
  114. package/dist/parser/pdf-filter.js +528 -0
  115. package/dist/parser/pdf-filter.js.map +1 -0
  116. package/dist/parser/title-extractor.d.ts +69 -0
  117. package/dist/parser/title-extractor.d.ts.map +1 -0
  118. package/dist/parser/title-extractor.js +145 -0
  119. package/dist/parser/title-extractor.js.map +1 -0
  120. package/dist/pdf-visual/captioner.d.ts +16 -0
  121. package/dist/pdf-visual/captioner.d.ts.map +1 -0
  122. package/dist/pdf-visual/captioner.js +63 -0
  123. package/dist/pdf-visual/captioner.js.map +1 -0
  124. package/dist/pdf-visual/captioners/fast.d.ts +7 -0
  125. package/dist/pdf-visual/captioners/fast.d.ts.map +1 -0
  126. package/dist/pdf-visual/captioners/fast.js +103 -0
  127. package/dist/pdf-visual/captioners/fast.js.map +1 -0
  128. package/dist/pdf-visual/captioners/quality.d.ts +7 -0
  129. package/dist/pdf-visual/captioners/quality.d.ts.map +1 -0
  130. package/dist/pdf-visual/captioners/quality.js +127 -0
  131. package/dist/pdf-visual/captioners/quality.js.map +1 -0
  132. package/dist/pdf-visual/captioners/shared.d.ts +44 -0
  133. package/dist/pdf-visual/captioners/shared.d.ts.map +1 -0
  134. package/dist/pdf-visual/captioners/shared.js +104 -0
  135. package/dist/pdf-visual/captioners/shared.js.map +1 -0
  136. package/dist/pdf-visual/detector.d.ts +9 -0
  137. package/dist/pdf-visual/detector.d.ts.map +1 -0
  138. package/dist/pdf-visual/detector.js +234 -0
  139. package/dist/pdf-visual/detector.js.map +1 -0
  140. package/dist/pdf-visual/index.d.ts +13 -0
  141. package/dist/pdf-visual/index.d.ts.map +1 -0
  142. package/dist/pdf-visual/index.js +45 -0
  143. package/dist/pdf-visual/index.js.map +1 -0
  144. package/dist/pdf-visual/renderer.d.ts +9 -0
  145. package/dist/pdf-visual/renderer.d.ts.map +1 -0
  146. package/dist/pdf-visual/renderer.js +177 -0
  147. package/dist/pdf-visual/renderer.js.map +1 -0
  148. package/dist/pdf-visual/types.d.ts +62 -0
  149. package/dist/pdf-visual/types.d.ts.map +1 -0
  150. package/dist/pdf-visual/types.js +32 -0
  151. package/dist/pdf-visual/types.js.map +1 -0
  152. package/dist/server/error-utils.d.ts +79 -0
  153. package/dist/server/error-utils.d.ts.map +1 -0
  154. package/dist/server/error-utils.js +148 -0
  155. package/dist/server/error-utils.js.map +1 -0
  156. package/dist/server/index.d.ts +258 -0
  157. package/dist/server/index.d.ts.map +1 -0
  158. package/dist/server/index.js +1104 -0
  159. package/dist/server/index.js.map +1 -0
  160. package/dist/server/list-scanner.d.ts +52 -0
  161. package/dist/server/list-scanner.d.ts.map +1 -0
  162. package/dist/server/list-scanner.js +72 -0
  163. package/dist/server/list-scanner.js.map +1 -0
  164. package/dist/server/tool-definitions.d.ts +8 -0
  165. package/dist/server/tool-definitions.d.ts.map +1 -0
  166. package/dist/server/tool-definitions.js +181 -0
  167. package/dist/server/tool-definitions.js.map +1 -0
  168. package/dist/server/tool-input.d.ts +37 -0
  169. package/dist/server/tool-input.d.ts.map +1 -0
  170. package/dist/server/tool-input.js +216 -0
  171. package/dist/server/tool-input.js.map +1 -0
  172. package/dist/server/types.d.ts +331 -0
  173. package/dist/server/types.d.ts.map +1 -0
  174. package/dist/server/types.js +3 -0
  175. package/dist/server/types.js.map +1 -0
  176. package/dist/server-main.d.ts +46 -0
  177. package/dist/server-main.d.ts.map +1 -0
  178. package/dist/server-main.js +242 -0
  179. package/dist/server-main.js.map +1 -0
  180. package/dist/utils/base-dirs.d.ts +212 -0
  181. package/dist/utils/base-dirs.d.ts.map +1 -0
  182. package/dist/utils/base-dirs.js +422 -0
  183. package/dist/utils/base-dirs.js.map +1 -0
  184. package/dist/utils/errors.d.ts +24 -0
  185. package/dist/utils/errors.d.ts.map +1 -0
  186. package/dist/utils/errors.js +53 -0
  187. package/dist/utils/errors.js.map +1 -0
  188. package/dist/utils/limits.d.ts +26 -0
  189. package/dist/utils/limits.d.ts.map +1 -0
  190. package/dist/utils/limits.js +28 -0
  191. package/dist/utils/limits.js.map +1 -0
  192. package/dist/utils/list-sources.d.ts +47 -0
  193. package/dist/utils/list-sources.d.ts.map +1 -0
  194. package/dist/utils/list-sources.js +50 -0
  195. package/dist/utils/list-sources.js.map +1 -0
  196. package/dist/utils/raw-data-utils.d.ts +131 -0
  197. package/dist/utils/raw-data-utils.d.ts.map +1 -0
  198. package/dist/utils/raw-data-utils.js +255 -0
  199. package/dist/utils/raw-data-utils.js.map +1 -0
  200. package/dist/utils/scan.d.ts +126 -0
  201. package/dist/utils/scan.d.ts.map +1 -0
  202. package/dist/utils/scan.js +221 -0
  203. package/dist/utils/scan.js.map +1 -0
  204. package/dist/utils/scope-match.d.ts +43 -0
  205. package/dist/utils/scope-match.d.ts.map +1 -0
  206. package/dist/utils/scope-match.js +87 -0
  207. package/dist/utils/scope-match.js.map +1 -0
  208. package/dist/utils/sensitive-path.d.ts +23 -0
  209. package/dist/utils/sensitive-path.d.ts.map +1 -0
  210. package/dist/utils/sensitive-path.js +91 -0
  211. package/dist/utils/sensitive-path.js.map +1 -0
  212. package/dist/utils/sync-path-key.d.ts +20 -0
  213. package/dist/utils/sync-path-key.d.ts.map +1 -0
  214. package/dist/utils/sync-path-key.js +33 -0
  215. package/dist/utils/sync-path-key.js.map +1 -0
  216. package/dist/vectordb/index.d.ts +168 -0
  217. package/dist/vectordb/index.d.ts.map +1 -0
  218. package/dist/vectordb/index.js +619 -0
  219. package/dist/vectordb/index.js.map +1 -0
  220. package/dist/vectordb/search-filters.d.ts +39 -0
  221. package/dist/vectordb/search-filters.d.ts.map +1 -0
  222. package/dist/vectordb/search-filters.js +136 -0
  223. package/dist/vectordb/search-filters.js.map +1 -0
  224. package/dist/vectordb/types.d.ts +196 -0
  225. package/dist/vectordb/types.d.ts.map +1 -0
  226. package/dist/vectordb/types.js +224 -0
  227. package/dist/vectordb/types.js.map +1 -0
  228. package/package.json +105 -0
  229. package/skills/mcp-local-rag/SKILL.md +308 -0
  230. package/skills/mcp-local-rag/references/cli-reference.md +175 -0
  231. package/skills/mcp-local-rag/references/html-ingestion.md +78 -0
  232. package/skills/mcp-local-rag/references/query-optimization.md +57 -0
  233. package/skills/mcp-local-rag/references/result-refinement.md +56 -0
@@ -0,0 +1,619 @@
1
+ // VectorStore implementation with LanceDB integration
2
+ import { connect, Index } from '@lancedb/lancedb';
3
+ import { MAX_QUERY_LIMIT, MIN_QUERY_LIMIT } from '../utils/limits.js';
4
+ import { normalizeScopePrefix } from '../utils/scope-match.js';
5
+ import { applyFileFilter, applyGrouping, applyKeywordBoost } from './search-filters.js';
6
+ import { DatabaseError, DEFAULT_HYBRID_WEIGHT, FTS_CLEANUP_THRESHOLD_MS, FTS_INDEX_NAME, HYBRID_SEARCH_CANDIDATE_MULTIPLIER, normalizeVisualAttachments, parseHydratedVisualAttachments, toChunkRow, toSearchResult, toVectorChunk, } from './types.js';
7
+ // ============================================
8
+ // VectorStore Class
9
+ // ============================================
10
+ /**
11
+ * Vector storage class using LanceDB
12
+ *
13
+ * Responsibilities:
14
+ * - LanceDB operations (insert, delete, search)
15
+ * - Transaction handling (atomicity of delete→insert)
16
+ * - Metadata management
17
+ */
18
+ export class VectorStore {
19
+ db = null;
20
+ table = null;
21
+ config;
22
+ ftsEnabled = false;
23
+ constructor(config) {
24
+ this.config = config;
25
+ }
26
+ /**
27
+ * Initialize LanceDB and create table
28
+ */
29
+ async initialize() {
30
+ try {
31
+ // Connect to LanceDB
32
+ // readConsistencyInterval: 0 ensures every read checks for external changes.
33
+ // Without this, a cached Table object becomes stale when another process
34
+ // (e.g., CLI ingestion from a different terminal) modifies the database,
35
+ // causing "Failed to search vectors" errors until restart.
36
+ this.db = await connect(this.config.dbPath, { readConsistencyInterval: 0 });
37
+ // Check table existence and create if needed
38
+ const tableNames = await this.db.tableNames();
39
+ if (tableNames.includes(this.config.tableName)) {
40
+ // Open existing table
41
+ this.table = await this.db.openTable(this.config.tableName);
42
+ console.error(`VectorStore: Opened existing table "${this.config.tableName}"`);
43
+ // Ensure FTS index exists (migration for existing databases)
44
+ await this.ensureFtsIndex();
45
+ // Ensure schema is up to date (add new columns for existing tables)
46
+ await this.ensureSchemaVersion();
47
+ }
48
+ else {
49
+ // Create new table (schema auto-defined on first data insertion)
50
+ console.error(`VectorStore: Table "${this.config.tableName}" will be created on first data insertion`);
51
+ }
52
+ console.error(`VectorStore initialized: ${this.config.dbPath}`);
53
+ }
54
+ catch (error) {
55
+ throw new DatabaseError('Failed to initialize VectorStore', error);
56
+ }
57
+ }
58
+ /**
59
+ * Delete all chunks for specified file path
60
+ *
61
+ * @param filePath - File path (absolute)
62
+ * @returns Number of chunks removed (0 when nothing matched)
63
+ */
64
+ async deleteChunks(filePath) {
65
+ if (!this.table) {
66
+ // If table doesn't exist, no deletion targets, return normally
67
+ console.error('VectorStore: Skipping deletion as table does not exist');
68
+ return 0;
69
+ }
70
+ try {
71
+ // Use LanceDB delete API to remove records matching filePath.
72
+ // Escape single quotes to prevent SQL injection.
73
+ // Note: Field names are case-sensitive, use backticks for camelCase fields.
74
+ const escapedFilePath = filePath.replace(/'/g, "''");
75
+ // delete() reports the authoritative removed count (numDeletedRows) from
76
+ // the same operation, so the total stays correct under concurrent deletes
77
+ // and we avoid a second pre-count query that materializes matching rows.
78
+ const { numDeletedRows } = await this.table.delete(`\`filePath\` = '${escapedFilePath}'`);
79
+ console.error(`VectorStore: Deleted ${numDeletedRows} chunks for file "${filePath}"`);
80
+ return numDeletedRows;
81
+ }
82
+ catch (error) {
83
+ // LanceDB's delete is a no-op (resolves normally) when no rows match the
84
+ // predicate, so reaching this catch means a genuine failure — a malformed
85
+ // predicate, or a schema/table-level error. Propagate it instead of
86
+ // swallowing based on brittle error-message string matching (which broke
87
+ // silently across LanceDB versions and could hide real delete failures
88
+ // as data-integrity bugs).
89
+ console.warn(`VectorStore: Error occurred while deleting file "${filePath}":`, error);
90
+ throw new DatabaseError(`Failed to delete chunks for file: ${filePath}`, error);
91
+ }
92
+ }
93
+ /**
94
+ * Return chunk rows for a single file whose chunkIndex is within the
95
+ * inclusive [minIdx, maxIdx] range, sorted ascending by chunkIndex.
96
+ *
97
+ * This is a feature-agnostic primitive: it knows nothing
98
+ * about before/after/isTarget semantics — those live in the handler.
99
+ * Ascending sort by chunkIndex is a contract, not incidental storage
100
+ * order.
101
+ *
102
+ * Lazy-table null returns [] (mirrors search, listFiles, deleteChunks).
103
+ * LanceDB errors are wrapped as DatabaseError with the original error
104
+ * preserved as cause.
105
+ *
106
+ * @param filePath - File path (absolute)
107
+ * @param minIdx - Minimum chunk index (inclusive)
108
+ * @param maxIdx - Maximum chunk index (inclusive)
109
+ * @returns Array of chunk rows sorted ascending by chunkIndex
110
+ */
111
+ async getChunksByRange(filePath, minIdx, maxIdx) {
112
+ if (!this.table) {
113
+ console.error('VectorStore: Skipping range read as table does not exist');
114
+ return [];
115
+ }
116
+ if (!Number.isInteger(minIdx) || !Number.isInteger(maxIdx) || minIdx < 0 || maxIdx < minIdx) {
117
+ throw new DatabaseError('getChunksByRange requires non-negative integer range bounds with minIdx <= maxIdx');
118
+ }
119
+ try {
120
+ // Escape single quotes to prevent SQL injection (mirrors deleteChunks)
121
+ const escapedFilePath = filePath.replace(/'/g, "''");
122
+ // Backtick-quoted camelCase columns; numeric literals unquoted
123
+ const predicate = `\`filePath\` = '${escapedFilePath}' AND \`chunkIndex\` >= ${minIdx} AND \`chunkIndex\` <= ${maxIdx}`;
124
+ const raw = await this.table.query().where(predicate).toArray();
125
+ const rows = raw.map((row) => toChunkRow(row));
126
+ // Contractual ascending sort; do not rely on storage order.
127
+ rows.sort((a, b) => a.chunkIndex - b.chunkIndex);
128
+ return rows;
129
+ }
130
+ catch (error) {
131
+ throw new DatabaseError('Failed to read chunks by range', error);
132
+ }
133
+ }
134
+ /**
135
+ * Return every stored chunk for a file as a full {@link VectorChunk},
136
+ * including the real embedding vector — suitable for re-insertion via
137
+ * {@link insertChunks}. Used by the ingest handler to back up existing data
138
+ * before a destructive re-ingest so a failure can be rolled back without
139
+ * data loss or vector corruption.
140
+ *
141
+ * Lazy-table null returns `[]`. LanceDB errors are wrapped as DatabaseError.
142
+ *
143
+ * @param filePath - File path (absolute)
144
+ */
145
+ async getChunksByFilePath(filePath) {
146
+ if (!this.table) {
147
+ return [];
148
+ }
149
+ try {
150
+ // Escape single quotes to prevent SQL injection (mirrors deleteChunks)
151
+ const escapedFilePath = filePath.replace(/'/g, "''");
152
+ const raw = await this.table.query().where(`\`filePath\` = '${escapedFilePath}'`).toArray();
153
+ return raw.map((row) => toVectorChunk(row));
154
+ }
155
+ catch (error) {
156
+ throw new DatabaseError(`Failed to read chunks for file: ${filePath}`, error);
157
+ }
158
+ }
159
+ /**
160
+ * Batch insert vector chunks
161
+ *
162
+ * @param chunks - Array of vector chunks
163
+ */
164
+ async insertChunks(chunks) {
165
+ if (chunks.length === 0) {
166
+ return;
167
+ }
168
+ try {
169
+ if (!this.table) {
170
+ // Create table on first insertion
171
+ if (!this.db) {
172
+ throw new DatabaseError('VectorStore is not initialized. Call initialize() first.');
173
+ }
174
+ // LanceDB's createTable API accepts data as Record<string, unknown>[]
175
+ // Note: LanceDB cannot infer Arrow type from null/absent values, so the
176
+ // nullable string columns need a non-null sample value for schema
177
+ // inference. The read converters normalize each placeholder back to
178
+ // its logical no-value state, matching what migration produces.
179
+ const records = chunks.map((chunk) => {
180
+ const record = chunk;
181
+ return {
182
+ ...record,
183
+ fileTitle: record['fileTitle'] ?? '',
184
+ contentHash: record['contentHash'] ?? '',
185
+ visualAttachments: normalizeVisualAttachments(record['visualAttachments']),
186
+ };
187
+ });
188
+ this.table = await this.db.createTable(this.config.tableName, records);
189
+ console.error(`VectorStore: Created table "${this.config.tableName}"`);
190
+ // Create FTS index for hybrid search
191
+ await this.ensureFtsIndex();
192
+ }
193
+ else {
194
+ // Add data to existing table
195
+ const records = chunks.map((chunk) => {
196
+ const record = chunk;
197
+ return {
198
+ ...record,
199
+ visualAttachments: normalizeVisualAttachments(record['visualAttachments']),
200
+ };
201
+ });
202
+ await this.table.add(records);
203
+ }
204
+ console.error(`VectorStore: Inserted ${chunks.length} chunks`);
205
+ }
206
+ catch (error) {
207
+ throw new DatabaseError('Failed to insert chunks', error);
208
+ }
209
+ }
210
+ /**
211
+ * Ensure FTS index exists for hybrid search
212
+ * Creates ngram-based index if it doesn't exist, drops old versions
213
+ * @throws DatabaseError if index creation fails (Fail-Fast principle)
214
+ */
215
+ async ensureFtsIndex() {
216
+ if (!this.table) {
217
+ return;
218
+ }
219
+ // Check existing indices
220
+ const indices = await this.table.listIndices();
221
+ const existingFtsIndices = indices.filter((idx) => idx.indexType === 'FTS');
222
+ const hasExpectedIndex = existingFtsIndices.some((idx) => idx.name === FTS_INDEX_NAME);
223
+ if (hasExpectedIndex) {
224
+ this.ftsEnabled = true;
225
+ return;
226
+ }
227
+ // Create new FTS index with ngram tokenizer for multilingual support
228
+ // - min=2: Capture Japanese bi-grams (e.g., "東京", "設計")
229
+ // - max=3: Balance between precision and index size
230
+ // - prefixOnly=false: Generate ngrams from all positions for proper CJK support
231
+ await this.table.createIndex('text', {
232
+ config: Index.fts({
233
+ baseTokenizer: 'ngram',
234
+ ngramMinLength: 2,
235
+ ngramMaxLength: 3,
236
+ prefixOnly: false,
237
+ stem: false,
238
+ }),
239
+ name: FTS_INDEX_NAME,
240
+ });
241
+ this.ftsEnabled = true;
242
+ console.error(`VectorStore: FTS index "${FTS_INDEX_NAME}" created successfully`);
243
+ // Drop old FTS indices
244
+ for (const idx of existingFtsIndices) {
245
+ if (idx.name !== FTS_INDEX_NAME) {
246
+ await this.table.dropIndex(idx.name);
247
+ console.error(`VectorStore: Dropped old FTS index "${idx.name}"`);
248
+ }
249
+ }
250
+ }
251
+ /**
252
+ * Ensure schema is up to date by adding missing columns.
253
+ * Uses table.addColumns() API for top-level column additions.
254
+ * Idempotent: checks for column existence before adding.
255
+ */
256
+ async ensureSchemaVersion() {
257
+ if (!this.table) {
258
+ return;
259
+ }
260
+ const schema = await this.table.schema();
261
+ const hasField = (name) => schema.fields.some((f) => f.name === name);
262
+ if (!hasField('fileTitle')) {
263
+ await this.table.addColumns([{ name: 'fileTitle', valueSql: 'cast(NULL as string)' }]);
264
+ console.error('VectorStore: Migrated schema - added fileTitle column');
265
+ }
266
+ if (!hasField('contentHash')) {
267
+ await this.table.addColumns([{ name: 'contentHash', valueSql: 'cast(NULL as string)' }]);
268
+ console.error('VectorStore: Migrated schema - added contentHash column');
269
+ }
270
+ if (!hasField('visualAttachments')) {
271
+ await this.table.addColumns([{ name: 'visualAttachments', valueSql: 'cast(NULL as string)' }]);
272
+ console.error('VectorStore: Migrated schema - added visualAttachments column');
273
+ }
274
+ }
275
+ /**
276
+ * Optimize table: compact fragments, update FTS index, and clean up old versions.
277
+ * LanceDB OSS requires explicit optimize() call to update FTS index.
278
+ *
279
+ * Callers are responsible for deciding when to invoke this (e.g., once per
280
+ * ingest rather than after every insert/delete) to avoid O(n²) overhead
281
+ * during bulk operations.
282
+ */
283
+ async optimize() {
284
+ if (!this.table || !this.ftsEnabled) {
285
+ return;
286
+ }
287
+ const cleanupThreshold = new Date(Date.now() - FTS_CLEANUP_THRESHOLD_MS);
288
+ await this.table.optimize({ cleanupOlderThan: cleanupThreshold });
289
+ }
290
+ /**
291
+ * Execute vector search with quality filtering
292
+ * Architecture: Semantic search → Filter (maxDistance, grouping) → Keyword boost → File filter (maxFiles)
293
+ *
294
+ * This "prefetch then rerank" approach ensures:
295
+ * - maxDistance and grouping work on meaningful vector distances
296
+ * - Keyword matching acts as a boost, not a replacement for semantic similarity
297
+ *
298
+ * @param queryVector - Query vector (dimension depends on model)
299
+ * @param options - Optional search options (queryText for keyword boost,
300
+ * limit, and scope path-prefix prefilter)
301
+ * @returns Array of search results (sorted by distance ascending, filtered by quality settings)
302
+ */
303
+ async search(queryVector, options = {}) {
304
+ const { queryText, limit = 10, scope } = options;
305
+ if (!this.table) {
306
+ console.error('VectorStore: Returning empty results as table does not exist');
307
+ return [];
308
+ }
309
+ if (limit < MIN_QUERY_LIMIT || limit > MAX_QUERY_LIMIT) {
310
+ throw new DatabaseError(`Invalid limit: expected ${MIN_QUERY_LIMIT}-${MAX_QUERY_LIMIT}, got ${limit}`);
311
+ }
312
+ try {
313
+ // Step 1: Semantic (vector) search - always the primary search
314
+ const candidateLimit = limit * HYBRID_SEARCH_CANDIDATE_MULTIPLIER;
315
+ let query = this.table
316
+ .vectorSearch(queryVector)
317
+ .distanceType('dot')
318
+ .select(['id', 'filePath', 'chunkIndex', 'text', 'metadata', 'fileTitle', '_distance'])
319
+ .limit(candidateLimit);
320
+ // Scope prefilter: restrict to chunks under the given path prefixes
321
+ // (exact-or-descendant) before ranking. Applied only when scope is
322
+ // present so scope-absent behavior is byte-for-byte unchanged.
323
+ if (scope && scope.length > 0) {
324
+ query = query.where(this.buildScopePredicate(scope));
325
+ }
326
+ // Apply distance threshold at query level
327
+ if (this.config.maxDistance !== undefined) {
328
+ query = query.distanceRange(undefined, this.config.maxDistance);
329
+ }
330
+ const vectorResults = await query.toArray();
331
+ // Convert to SearchResult format with type validation
332
+ let results = vectorResults.map((result) => toSearchResult(result));
333
+ // Step 2: Apply grouping filter on vector distances (before keyword boost)
334
+ // Grouping is meaningful only on semantic distances, not after keyword boost
335
+ if (this.config.grouping && results.length > 1) {
336
+ results = applyGrouping(results, this.config.grouping);
337
+ }
338
+ // Step 3: Apply keyword boost if enabled.
339
+ // results.length > 0 guards the FTS branch: when the (scoped) vector step
340
+ // returned zero hits, uniqueFilePaths would be empty and the IN clause
341
+ // would degrade to a malformed `filePath IN ()` that LanceDB rejects.
342
+ // Skipping is also correct — there is nothing to rerank. The FTS branch
343
+ // inherits scope through uniqueFilePaths (derived from the scoped hits),
344
+ // so no separate scope predicate is needed here.
345
+ const hybridWeight = this.config.hybridWeight ?? DEFAULT_HYBRID_WEIGHT;
346
+ if (this.ftsEnabled &&
347
+ queryText &&
348
+ queryText.trim().length > 0 &&
349
+ hybridWeight > 0 &&
350
+ results.length > 0) {
351
+ try {
352
+ // Get unique filePaths from vector results to filter FTS search
353
+ const uniqueFilePaths = [...new Set(results.map((r) => r.filePath))];
354
+ // Build WHERE clause with IN for targeted FTS search
355
+ // Use backticks for column name (required for camelCase in LanceDB)
356
+ const escapedPaths = uniqueFilePaths.map((p) => `'${p.replace(/'/g, "''")}'`);
357
+ const whereClause = `\`filePath\` IN (${escapedPaths.join(', ')})`;
358
+ const ftsResults = await this.table
359
+ .search(queryText, 'fts', 'text')
360
+ .where(whereClause)
361
+ .select(['filePath', 'chunkIndex', 'text', 'metadata', '_score'])
362
+ .limit(results.length * 2) // Enough to cover all vector results
363
+ .toArray();
364
+ results = applyKeywordBoost(results, ftsResults, hybridWeight);
365
+ }
366
+ catch (ftsError) {
367
+ // Per-request degrade only: fall back to vector-only results for THIS
368
+ // query without disabling FTS on the instance. A transient FTS error
369
+ // (e.g. a momentary index issue) must not permanently drop the server
370
+ // to vector-only until restart — the next query retries hybrid search.
371
+ console.error('VectorStore: FTS search failed, using vector-only results:', ftsError);
372
+ }
373
+ }
374
+ // Step 4: Apply file filter after keyword boost
375
+ // Unlike grouping (which depends on raw semantic distance gaps), maxFiles selects
376
+ // the "most relevant files" — this should respect the final ranking including keyword boost
377
+ if (this.config.maxFiles !== undefined && results.length > 0) {
378
+ results = applyFileFilter(results, this.config.maxFiles);
379
+ }
380
+ // Return top results after all filtering and boosting
381
+ return results.slice(0, limit);
382
+ }
383
+ catch (error) {
384
+ throw new DatabaseError('Failed to search vectors', error);
385
+ }
386
+ }
387
+ /**
388
+ * Load and validate attachments for the ordered unique final search identities.
389
+ * Candidate retrieval and ranking are deliberately complete before this one
390
+ * projected batch query runs.
391
+ */
392
+ async hydrateVisualAttachments(results) {
393
+ const ids = [];
394
+ const seen = new Set();
395
+ for (const result of results) {
396
+ if (typeof result.id !== 'string' || result.id.length === 0) {
397
+ throw new DatabaseError('Invalid final attachment hydration identity');
398
+ }
399
+ if (!seen.has(result.id)) {
400
+ seen.add(result.id);
401
+ ids.push(result.id);
402
+ }
403
+ }
404
+ if (!this.table || ids.length === 0) {
405
+ return {
406
+ rows: ids.map((id) => ({ id, attachments: [] })),
407
+ omittedCount: 0,
408
+ };
409
+ }
410
+ try {
411
+ const predicate = ids.map((id) => `\`id\` = '${this.escapeQuotes(id)}'`).join(' OR ');
412
+ const records = await this.table
413
+ .query()
414
+ .where(predicate)
415
+ .select(['id', 'visualAttachments'])
416
+ .toArray();
417
+ const recordsByIdentity = new Map();
418
+ for (const record of records) {
419
+ if (typeof record.id !== 'string')
420
+ continue;
421
+ recordsByIdentity.set(record.id, record.visualAttachments);
422
+ }
423
+ let omittedCount = 0;
424
+ const rows = ids.map((id) => {
425
+ if (!recordsByIdentity.has(id)) {
426
+ omittedCount += 1;
427
+ return { id, attachments: [] };
428
+ }
429
+ const parsed = parseHydratedVisualAttachments(recordsByIdentity.get(id));
430
+ omittedCount += parsed.omittedCount;
431
+ return { id, attachments: parsed.attachments };
432
+ });
433
+ return { rows, omittedCount };
434
+ }
435
+ catch (error) {
436
+ throw new DatabaseError('Failed to hydrate visual attachments', error);
437
+ }
438
+ }
439
+ /**
440
+ * Build a LanceDB `.where()` predicate restricting `filePath` to the
441
+ * exact-or-descendant set of the given prefixes (OR'd): `filePath = P OR
442
+ * filePath LIKE 'D%'`, where the separator boundary in D stops `/a/b` from
443
+ * matching `/a/bc`. Consumed by the vector branch only — the FTS branch
444
+ * inherits scope via its own `filePath IN (...)` over the scoped hits.
445
+ */
446
+ buildScopePredicate(prefixes) {
447
+ return prefixes.map((prefix) => this.buildPrefixPredicate(prefix)).join(' OR ');
448
+ }
449
+ /** Build the exact-or-descendant predicate for a single prefix. */
450
+ buildPrefixPredicate(prefix) {
451
+ const { exact, descendant } = normalizeScopePrefix(prefix);
452
+ const exactTerm = `\`filePath\` = '${this.escapeQuotes(exact)}'`;
453
+ const descendantTerm = `\`filePath\` LIKE '${this.escapeLike(descendant)}%' ESCAPE '\\'`;
454
+ return `(${exactTerm} OR ${descendantTerm})`;
455
+ }
456
+ /** Escape single quotes for a SQL string literal (mirrors deleteChunks). */
457
+ escapeQuotes(value) {
458
+ return value.replace(/'/g, "''");
459
+ }
460
+ /** Escape for a LIKE term with `ESCAPE '\'`: backslash first (else it double-escapes), then `%`, `_`, then quotes. */
461
+ escapeLike(value) {
462
+ return value
463
+ .replace(/\\/g, '\\\\')
464
+ .replace(/%/g, '\\%')
465
+ .replace(/_/g, '\\_')
466
+ .replace(/'/g, "''");
467
+ }
468
+ /**
469
+ * Per-chunk `(filePath, contentHash)` projection used by incremental sync.
470
+ *
471
+ * One entry per stored row rather than one per file, because a file whose
472
+ * rows disagree on the hash (or carry none) must be detectable as dirty.
473
+ * `filePath` is the verbatim stored spelling, since that is what
474
+ * {@link deleteChunks} matches. An empty-string hash — the value the
475
+ * create-path seeds for Arrow schema inference — is normalized to `null` so a
476
+ * hashless row can never read as a real hash, mirroring `toVectorChunk`.
477
+ *
478
+ * Projects only the two convergence columns so a manifest load does not
479
+ * materialize embedding vectors or attachment payloads. Lazy-table null
480
+ * returns `[]` (mirrors {@link listFiles}).
481
+ */
482
+ async listChunkHashes() {
483
+ if (!this.table) {
484
+ return [];
485
+ }
486
+ try {
487
+ const records = await this.table.query().select(['filePath', 'contentHash']).toArray();
488
+ const entries = [];
489
+ for (const record of records) {
490
+ const filePath = record.filePath;
491
+ const contentHash = record.contentHash;
492
+ // Type-guard parity with listFiles: skip rows missing the expected
493
+ // string column rather than coercing via `as string`.
494
+ if (typeof filePath !== 'string')
495
+ continue;
496
+ entries.push({
497
+ filePath,
498
+ contentHash: typeof contentHash === 'string' && contentHash.length > 0 ? contentHash : null,
499
+ });
500
+ }
501
+ return entries;
502
+ }
503
+ catch (error) {
504
+ throw new DatabaseError('Failed to list chunk content hashes', error);
505
+ }
506
+ }
507
+ /**
508
+ * Get list of ingested files
509
+ *
510
+ * @returns Array of file information
511
+ */
512
+ async listFiles() {
513
+ if (!this.table) {
514
+ return []; // Return empty array if table doesn't exist
515
+ }
516
+ try {
517
+ // Project to only the columns needed for aggregation, excluding the
518
+ // embedding vector payload. LanceDB JS has no group-by, so the per-file
519
+ // count + latest-timestamp aggregation still runs here — but over a much
520
+ // smaller row payload than a full `query().toArray()`.
521
+ const allRecords = await this.table.query().select(['filePath', 'timestamp']).toArray();
522
+ // Group by file path
523
+ const fileMap = new Map();
524
+ for (const record of allRecords) {
525
+ const filePath = record.filePath;
526
+ const timestamp = record.timestamp;
527
+ // Type-guard parity with toSearchResult/toChunkRow: skip rows missing
528
+ // the expected string columns rather than coercing via `as string`.
529
+ if (typeof filePath !== 'string' || typeof timestamp !== 'string')
530
+ continue;
531
+ if (fileMap.has(filePath)) {
532
+ const fileInfo = fileMap.get(filePath);
533
+ if (fileInfo) {
534
+ fileInfo.chunkCount += 1;
535
+ // Keep most recent timestamp
536
+ if (timestamp > fileInfo.timestamp) {
537
+ fileInfo.timestamp = timestamp;
538
+ }
539
+ }
540
+ }
541
+ else {
542
+ fileMap.set(filePath, { chunkCount: 1, timestamp });
543
+ }
544
+ }
545
+ // Convert Map to array of objects
546
+ return Array.from(fileMap.entries()).map(([filePath, info]) => ({
547
+ filePath,
548
+ chunkCount: info.chunkCount,
549
+ timestamp: info.timestamp,
550
+ }));
551
+ }
552
+ catch (error) {
553
+ throw new DatabaseError('Failed to list files', error);
554
+ }
555
+ }
556
+ /**
557
+ * Get system status
558
+ *
559
+ * @returns System status information
560
+ */
561
+ async getStatus() {
562
+ if (!this.table) {
563
+ return {
564
+ documentCount: 0,
565
+ chunkCount: 0,
566
+ memoryUsage: 0,
567
+ uptime: process.uptime(),
568
+ ftsIndexEnabled: false,
569
+ searchMode: 'vector-only',
570
+ };
571
+ }
572
+ try {
573
+ // Total chunk count comes straight from LanceDB's row count — no need to
574
+ // materialize every row just to read `.length`.
575
+ const chunkCount = await this.table.countRows();
576
+ // Distinct document count: LanceDB JS has no DISTINCT, so project to just
577
+ // the filePath column (excludes the vector payload) and dedupe here.
578
+ const records = await this.table.query().select(['filePath']).toArray();
579
+ const uniqueFilePaths = new Set();
580
+ for (const record of records) {
581
+ const filePath = record.filePath;
582
+ if (typeof filePath === 'string')
583
+ uniqueFilePaths.add(filePath);
584
+ }
585
+ const documentCount = uniqueFilePaths.size;
586
+ // Get memory usage (in MB)
587
+ const memoryUsage = process.memoryUsage().heapUsed / 1024 / 1024;
588
+ // Get uptime (in seconds)
589
+ const uptime = process.uptime();
590
+ return {
591
+ documentCount,
592
+ chunkCount,
593
+ memoryUsage,
594
+ uptime,
595
+ ftsIndexEnabled: this.ftsEnabled,
596
+ searchMode: this.ftsEnabled && (this.config.hybridWeight ?? DEFAULT_HYBRID_WEIGHT) > 0
597
+ ? 'hybrid'
598
+ : 'vector-only',
599
+ };
600
+ }
601
+ catch (error) {
602
+ throw new DatabaseError('Failed to get status', error);
603
+ }
604
+ }
605
+ /**
606
+ * Close the database connection
607
+ */
608
+ async close() {
609
+ if (this.db) {
610
+ // LanceDB Connections should be closed to release file handles
611
+ await this.db.close();
612
+ this.db = null;
613
+ this.table = null;
614
+ this.ftsEnabled = false;
615
+ console.error('VectorStore connection closed');
616
+ }
617
+ }
618
+ }
619
+ //# 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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"}