vectra 0.12.3 → 0.14.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 (375) hide show
  1. package/README.md +92 -100
  2. package/lib/BrowserWebFetcher.d.ts +75 -0
  3. package/lib/BrowserWebFetcher.d.ts.map +1 -0
  4. package/lib/BrowserWebFetcher.js +290 -0
  5. package/lib/BrowserWebFetcher.js.map +1 -0
  6. package/lib/FileFetcher.d.ts.map +1 -1
  7. package/lib/FileFetcher.js +25 -15
  8. package/lib/FileFetcher.js.map +1 -1
  9. package/lib/FileFetcher.spec.d.ts +2 -0
  10. package/lib/FileFetcher.spec.d.ts.map +1 -0
  11. package/lib/FileFetcher.spec.js +244 -0
  12. package/lib/FileFetcher.spec.js.map +1 -0
  13. package/lib/FolderWatcher.d.ts +91 -0
  14. package/lib/FolderWatcher.d.ts.map +1 -0
  15. package/lib/FolderWatcher.js +304 -0
  16. package/lib/FolderWatcher.js.map +1 -0
  17. package/lib/FolderWatcher.spec.d.ts +2 -0
  18. package/lib/FolderWatcher.spec.d.ts.map +1 -0
  19. package/lib/FolderWatcher.spec.js +308 -0
  20. package/lib/FolderWatcher.spec.js.map +1 -0
  21. package/lib/GPT3Tokenizer.spec.d.ts +2 -0
  22. package/lib/GPT3Tokenizer.spec.d.ts.map +1 -0
  23. package/lib/GPT3Tokenizer.spec.js +45 -0
  24. package/lib/GPT3Tokenizer.spec.js.map +1 -0
  25. package/lib/ItemSelector.d.ts.map +1 -1
  26. package/lib/ItemSelector.js +19 -8
  27. package/lib/ItemSelector.js.map +1 -1
  28. package/lib/ItemSelector.spec.d.ts +2 -0
  29. package/lib/ItemSelector.spec.d.ts.map +1 -0
  30. package/lib/ItemSelector.spec.js +204 -0
  31. package/lib/ItemSelector.spec.js.map +1 -0
  32. package/lib/LocalDocument.d.ts +1 -1
  33. package/lib/LocalDocument.d.ts.map +1 -1
  34. package/lib/LocalDocument.js +5 -45
  35. package/lib/LocalDocument.js.map +1 -1
  36. package/lib/LocalDocument.spec.d.ts +2 -0
  37. package/lib/LocalDocument.spec.d.ts.map +1 -0
  38. package/lib/LocalDocument.spec.js +214 -0
  39. package/lib/LocalDocument.spec.js.map +1 -0
  40. package/lib/LocalDocumentIndex.d.ts +20 -0
  41. package/lib/LocalDocumentIndex.d.ts.map +1 -1
  42. package/lib/LocalDocumentIndex.js +16 -52
  43. package/lib/LocalDocumentIndex.js.map +1 -1
  44. package/lib/LocalDocumentIndex.spec.d.ts +2 -0
  45. package/lib/LocalDocumentIndex.spec.d.ts.map +1 -0
  46. package/lib/LocalDocumentIndex.spec.js +494 -0
  47. package/lib/LocalDocumentIndex.spec.js.map +1 -0
  48. package/lib/LocalDocumentResult.d.ts +32 -11
  49. package/lib/LocalDocumentResult.d.ts.map +1 -1
  50. package/lib/LocalDocumentResult.js +305 -257
  51. package/lib/LocalDocumentResult.js.map +1 -1
  52. package/lib/LocalDocumentResult.spec.d.ts +2 -0
  53. package/lib/LocalDocumentResult.spec.d.ts.map +1 -0
  54. package/lib/LocalDocumentResult.spec.js +373 -0
  55. package/lib/LocalDocumentResult.spec.js.map +1 -0
  56. package/lib/LocalEmbeddings.d.ts +59 -0
  57. package/lib/LocalEmbeddings.d.ts.map +1 -0
  58. package/lib/LocalEmbeddings.js +101 -0
  59. package/lib/LocalEmbeddings.js.map +1 -0
  60. package/lib/LocalEmbeddings.spec.d.ts +2 -0
  61. package/lib/LocalEmbeddings.spec.d.ts.map +1 -0
  62. package/lib/LocalEmbeddings.spec.js +155 -0
  63. package/lib/LocalEmbeddings.spec.js.map +1 -0
  64. package/lib/LocalIndex.d.ts +27 -18
  65. package/lib/LocalIndex.d.ts.map +1 -1
  66. package/lib/LocalIndex.js +109 -105
  67. package/lib/LocalIndex.js.map +1 -1
  68. package/lib/LocalIndex.spec.js +434 -43
  69. package/lib/LocalIndex.spec.js.map +1 -1
  70. package/lib/OpenAIEmbeddings.d.ts +4 -6
  71. package/lib/OpenAIEmbeddings.d.ts.map +1 -1
  72. package/lib/OpenAIEmbeddings.js +16 -24
  73. package/lib/OpenAIEmbeddings.js.map +1 -1
  74. package/lib/OpenAIEmbeddings.spec.d.ts +2 -0
  75. package/lib/OpenAIEmbeddings.spec.d.ts.map +1 -0
  76. package/lib/OpenAIEmbeddings.spec.js +298 -0
  77. package/lib/OpenAIEmbeddings.spec.js.map +1 -0
  78. package/lib/TextSplitter.d.ts +2 -0
  79. package/lib/TextSplitter.d.ts.map +1 -1
  80. package/lib/TextSplitter.js +154 -111
  81. package/lib/TextSplitter.js.map +1 -1
  82. package/lib/TextSplitter.spec.js +289 -61
  83. package/lib/TextSplitter.spec.js.map +1 -1
  84. package/lib/TransformersEmbeddings.d.ts +121 -0
  85. package/lib/TransformersEmbeddings.d.ts.map +1 -0
  86. package/lib/TransformersEmbeddings.js +176 -0
  87. package/lib/TransformersEmbeddings.js.map +1 -0
  88. package/lib/TransformersEmbeddings.spec.d.ts +2 -0
  89. package/lib/TransformersEmbeddings.spec.d.ts.map +1 -0
  90. package/lib/TransformersEmbeddings.spec.js +198 -0
  91. package/lib/TransformersEmbeddings.spec.js.map +1 -0
  92. package/lib/TransformersTokenizer.d.ts +33 -0
  93. package/lib/TransformersTokenizer.d.ts.map +1 -0
  94. package/lib/TransformersTokenizer.js +44 -0
  95. package/lib/TransformersTokenizer.js.map +1 -0
  96. package/lib/TransformersTokenizer.spec.d.ts +2 -0
  97. package/lib/TransformersTokenizer.spec.d.ts.map +1 -0
  98. package/lib/TransformersTokenizer.spec.js +112 -0
  99. package/lib/TransformersTokenizer.spec.js.map +1 -0
  100. package/lib/WebFetcher.d.ts +1 -2
  101. package/lib/WebFetcher.d.ts.map +1 -1
  102. package/lib/WebFetcher.js +58 -54
  103. package/lib/WebFetcher.js.map +1 -1
  104. package/lib/WebFetcher.spec.d.ts +2 -0
  105. package/lib/WebFetcher.spec.d.ts.map +1 -0
  106. package/lib/WebFetcher.spec.js +263 -0
  107. package/lib/WebFetcher.spec.js.map +1 -0
  108. package/lib/browser.d.ts +30 -0
  109. package/lib/browser.d.ts.map +1 -0
  110. package/lib/browser.js +52 -0
  111. package/lib/browser.js.map +1 -0
  112. package/lib/codecs/IndexCodec.d.ts +37 -0
  113. package/lib/codecs/IndexCodec.d.ts.map +1 -0
  114. package/lib/codecs/IndexCodec.js +3 -0
  115. package/lib/codecs/IndexCodec.js.map +1 -0
  116. package/lib/codecs/JsonCodec.d.ts +19 -0
  117. package/lib/codecs/JsonCodec.d.ts.map +1 -0
  118. package/lib/codecs/JsonCodec.js +35 -0
  119. package/lib/codecs/JsonCodec.js.map +1 -0
  120. package/lib/codecs/JsonCodec.spec.d.ts +2 -0
  121. package/lib/codecs/JsonCodec.spec.d.ts.map +1 -0
  122. package/lib/codecs/JsonCodec.spec.js +66 -0
  123. package/lib/codecs/JsonCodec.spec.js.map +1 -0
  124. package/lib/codecs/LocalIndex.protobuf.spec.d.ts +2 -0
  125. package/lib/codecs/LocalIndex.protobuf.spec.d.ts.map +1 -0
  126. package/lib/codecs/LocalIndex.protobuf.spec.js +108 -0
  127. package/lib/codecs/LocalIndex.protobuf.spec.js.map +1 -0
  128. package/lib/codecs/ProtobufCodec.d.ts +20 -0
  129. package/lib/codecs/ProtobufCodec.d.ts.map +1 -0
  130. package/lib/codecs/ProtobufCodec.js +225 -0
  131. package/lib/codecs/ProtobufCodec.js.map +1 -0
  132. package/lib/codecs/ProtobufCodec.spec.d.ts +2 -0
  133. package/lib/codecs/ProtobufCodec.spec.d.ts.map +1 -0
  134. package/lib/codecs/ProtobufCodec.spec.js +155 -0
  135. package/lib/codecs/ProtobufCodec.spec.js.map +1 -0
  136. package/lib/codecs/index.d.ts +5 -0
  137. package/lib/codecs/index.d.ts.map +1 -0
  138. package/lib/codecs/index.js +21 -0
  139. package/lib/codecs/index.js.map +1 -0
  140. package/lib/codecs/migrateIndex.d.ts +24 -0
  141. package/lib/codecs/migrateIndex.d.ts.map +1 -0
  142. package/lib/codecs/migrateIndex.js +119 -0
  143. package/lib/codecs/migrateIndex.js.map +1 -0
  144. package/lib/codecs/migrateIndex.spec.d.ts +2 -0
  145. package/lib/codecs/migrateIndex.spec.d.ts.map +1 -0
  146. package/lib/codecs/migrateIndex.spec.js +151 -0
  147. package/lib/codecs/migrateIndex.spec.js.map +1 -0
  148. package/lib/codecs/schemas/index.proto +34 -0
  149. package/lib/index.d.ts +9 -1
  150. package/lib/index.d.ts.map +1 -1
  151. package/lib/index.js +9 -1
  152. package/lib/index.js.map +1 -1
  153. package/lib/internals/Colorize.d.ts.map +1 -1
  154. package/lib/internals/Colorize.js +20 -15
  155. package/lib/internals/Colorize.js.map +1 -1
  156. package/lib/server/IndexManager.d.ts +78 -0
  157. package/lib/server/IndexManager.d.ts.map +1 -0
  158. package/lib/server/IndexManager.js +259 -0
  159. package/lib/server/IndexManager.js.map +1 -0
  160. package/lib/server/VectraServer.d.ts +40 -0
  161. package/lib/server/VectraServer.d.ts.map +1 -0
  162. package/lib/server/VectraServer.js +151 -0
  163. package/lib/server/VectraServer.js.map +1 -0
  164. package/lib/server/VectraServer.spec.d.ts +2 -0
  165. package/lib/server/VectraServer.spec.d.ts.map +1 -0
  166. package/lib/server/VectraServer.spec.js +322 -0
  167. package/lib/server/VectraServer.spec.js.map +1 -0
  168. package/lib/server/handlers/documentHandlers.d.ts +15 -0
  169. package/lib/server/handlers/documentHandlers.d.ts.map +1 -0
  170. package/lib/server/handlers/documentHandlers.js +95 -0
  171. package/lib/server/handlers/documentHandlers.js.map +1 -0
  172. package/lib/server/handlers/helpers.d.ts +23 -0
  173. package/lib/server/handlers/helpers.d.ts.map +1 -0
  174. package/lib/server/handlers/helpers.js +138 -0
  175. package/lib/server/handlers/helpers.js.map +1 -0
  176. package/lib/server/handlers/index.d.ts +8 -0
  177. package/lib/server/handlers/index.d.ts.map +1 -0
  178. package/lib/server/handlers/index.js +22 -0
  179. package/lib/server/handlers/index.js.map +1 -0
  180. package/lib/server/handlers/indexHandlers.d.ts +14 -0
  181. package/lib/server/handlers/indexHandlers.d.ts.map +1 -0
  182. package/lib/server/handlers/indexHandlers.js +85 -0
  183. package/lib/server/handlers/indexHandlers.js.map +1 -0
  184. package/lib/server/handlers/itemHandlers.d.ts +34 -0
  185. package/lib/server/handlers/itemHandlers.d.ts.map +1 -0
  186. package/lib/server/handlers/itemHandlers.js +166 -0
  187. package/lib/server/handlers/itemHandlers.js.map +1 -0
  188. package/lib/server/handlers/lifecycleHandlers.d.ts +11 -0
  189. package/lib/server/handlers/lifecycleHandlers.d.ts.map +1 -0
  190. package/lib/server/handlers/lifecycleHandlers.js +31 -0
  191. package/lib/server/handlers/lifecycleHandlers.js.map +1 -0
  192. package/lib/server/handlers/queryHandlers.d.ts +27 -0
  193. package/lib/server/handlers/queryHandlers.d.ts.map +1 -0
  194. package/lib/server/handlers/queryHandlers.js +135 -0
  195. package/lib/server/handlers/queryHandlers.js.map +1 -0
  196. package/lib/server/handlers/statsHandlers.d.ts +17 -0
  197. package/lib/server/handlers/statsHandlers.d.ts.map +1 -0
  198. package/lib/server/handlers/statsHandlers.js +81 -0
  199. package/lib/server/handlers/statsHandlers.js.map +1 -0
  200. package/lib/server/index.d.ts +4 -0
  201. package/lib/server/index.d.ts.map +1 -0
  202. package/lib/server/index.js +23 -0
  203. package/lib/server/index.js.map +1 -0
  204. package/lib/storage/FileStorage.d.ts +92 -0
  205. package/lib/storage/FileStorage.d.ts.map +1 -0
  206. package/lib/storage/FileStorage.js +3 -0
  207. package/lib/storage/FileStorage.js.map +1 -0
  208. package/lib/storage/FileStorageUtilities.d.ts +36 -0
  209. package/lib/storage/FileStorageUtilities.d.ts.map +1 -0
  210. package/lib/storage/FileStorageUtilities.js +91 -0
  211. package/lib/storage/FileStorageUtilities.js.map +1 -0
  212. package/lib/storage/FileStorageUtilities.spec.d.ts +2 -0
  213. package/lib/storage/FileStorageUtilities.spec.d.ts.map +1 -0
  214. package/lib/storage/FileStorageUtilities.spec.js +98 -0
  215. package/lib/storage/FileStorageUtilities.spec.js.map +1 -0
  216. package/lib/storage/FileType.d.ts +29 -0
  217. package/lib/storage/FileType.d.ts.map +1 -0
  218. package/lib/storage/FileType.js +38 -0
  219. package/lib/storage/FileType.js.map +1 -0
  220. package/lib/storage/IndexedDBStorage.d.ts +47 -0
  221. package/lib/storage/IndexedDBStorage.d.ts.map +1 -0
  222. package/lib/storage/IndexedDBStorage.js +347 -0
  223. package/lib/storage/IndexedDBStorage.js.map +1 -0
  224. package/lib/storage/LocalFileStorage.browser.d.ts +19 -0
  225. package/lib/storage/LocalFileStorage.browser.d.ts.map +1 -0
  226. package/lib/storage/LocalFileStorage.browser.js +43 -0
  227. package/lib/storage/LocalFileStorage.browser.js.map +1 -0
  228. package/lib/storage/LocalFileStorage.d.ts +23 -0
  229. package/lib/storage/LocalFileStorage.d.ts.map +1 -0
  230. package/lib/storage/LocalFileStorage.js +152 -0
  231. package/lib/storage/LocalFileStorage.js.map +1 -0
  232. package/lib/storage/LocalFileStorage.spec.d.ts +2 -0
  233. package/lib/storage/LocalFileStorage.spec.d.ts.map +1 -0
  234. package/lib/storage/LocalFileStorage.spec.js +249 -0
  235. package/lib/storage/LocalFileStorage.spec.js.map +1 -0
  236. package/lib/storage/VirtualFileStorage.d.ts +18 -0
  237. package/lib/storage/VirtualFileStorage.d.ts.map +1 -0
  238. package/lib/storage/VirtualFileStorage.js +178 -0
  239. package/lib/storage/VirtualFileStorage.js.map +1 -0
  240. package/lib/storage/VirtualFileStorage.spec.d.ts +2 -0
  241. package/lib/storage/VirtualFileStorage.spec.d.ts.map +1 -0
  242. package/lib/storage/VirtualFileStorage.spec.js +302 -0
  243. package/lib/storage/VirtualFileStorage.spec.js.map +1 -0
  244. package/lib/storage/index.d.ts +6 -0
  245. package/lib/storage/index.d.ts.map +1 -0
  246. package/lib/storage/index.js +22 -0
  247. package/lib/storage/index.js.map +1 -0
  248. package/lib/templates/templates/csharp/README.md +48 -0
  249. package/lib/templates/templates/csharp/VectraClient.cs +234 -0
  250. package/lib/templates/templates/go/README.md +71 -0
  251. package/lib/templates/templates/go/vectra_client.go +322 -0
  252. package/lib/templates/templates/java/README.md +81 -0
  253. package/lib/templates/templates/java/VectraClient.java +232 -0
  254. package/lib/templates/templates/python/README.md +37 -0
  255. package/lib/templates/templates/python/vectra_client.py +279 -0
  256. package/lib/templates/templates/rust/Cargo.toml +14 -0
  257. package/lib/templates/templates/rust/README.md +39 -0
  258. package/lib/templates/templates/rust/build.rs +4 -0
  259. package/lib/templates/templates/rust/lib.rs +284 -0
  260. package/lib/templates/templates/typescript/README.md +96 -0
  261. package/lib/templates/templates/typescript/VectraClient.ts +374 -0
  262. package/lib/templates/typescript/VectraClient.d.ts +114 -0
  263. package/lib/templates/typescript/VectraClient.d.ts.map +1 -0
  264. package/lib/templates/typescript/VectraClient.js +328 -0
  265. package/lib/templates/typescript/VectraClient.js.map +1 -0
  266. package/lib/types.d.ts +7 -0
  267. package/lib/types.d.ts.map +1 -1
  268. package/lib/utils/index.d.ts +2 -0
  269. package/lib/utils/index.d.ts.map +1 -0
  270. package/lib/utils/index.js +18 -0
  271. package/lib/utils/index.js.map +1 -0
  272. package/lib/utils/pathUtils.d.ts +40 -0
  273. package/lib/utils/pathUtils.d.ts.map +1 -0
  274. package/lib/utils/pathUtils.js +98 -0
  275. package/lib/utils/pathUtils.js.map +1 -0
  276. package/lib/vectra-cli.d.ts.map +1 -1
  277. package/lib/vectra-cli.generate.spec.d.ts +2 -0
  278. package/lib/vectra-cli.generate.spec.d.ts.map +1 -0
  279. package/lib/vectra-cli.generate.spec.js +112 -0
  280. package/lib/vectra-cli.generate.spec.js.map +1 -0
  281. package/lib/vectra-cli.js +446 -9
  282. package/lib/vectra-cli.js.map +1 -1
  283. package/lib/vectra-cli.spec.d.ts +1 -0
  284. package/lib/vectra-cli.spec.d.ts.map +1 -0
  285. package/lib/vectra-cli.spec.js +2 -0
  286. package/lib/vectra-cli.spec.js.map +1 -0
  287. package/package.json +89 -16
  288. package/proto/vectra_service.proto +276 -0
  289. package/src/BrowserWebFetcher.ts +345 -0
  290. package/src/FileFetcher.spec.ts +234 -0
  291. package/src/FileFetcher.ts +37 -25
  292. package/src/FolderWatcher.spec.ts +288 -0
  293. package/src/FolderWatcher.ts +304 -0
  294. package/src/GPT3Tokenizer.spec.ts +50 -0
  295. package/src/ItemSelector.spec.ts +252 -0
  296. package/src/ItemSelector.ts +163 -150
  297. package/src/LocalDocument.spec.ts +211 -0
  298. package/src/LocalDocument.ts +88 -94
  299. package/src/LocalDocumentIndex.spec.ts +481 -0
  300. package/src/LocalDocumentIndex.ts +39 -40
  301. package/src/LocalDocumentResult.spec.ts +373 -0
  302. package/src/LocalDocumentResult.ts +489 -319
  303. package/src/LocalEmbeddings.spec.ts +138 -0
  304. package/src/LocalEmbeddings.ts +120 -0
  305. package/src/LocalIndex.spec.ts +808 -323
  306. package/src/LocalIndex.ts +479 -430
  307. package/src/OpenAIEmbeddings.spec.ts +354 -0
  308. package/src/OpenAIEmbeddings.ts +26 -27
  309. package/src/TextSplitter.spec.ts +320 -65
  310. package/src/TextSplitter.ts +172 -115
  311. package/src/TransformersEmbeddings.spec.ts +188 -0
  312. package/src/TransformersEmbeddings.ts +232 -0
  313. package/src/TransformersTokenizer.spec.ts +143 -0
  314. package/src/TransformersTokenizer.ts +45 -0
  315. package/src/WebFetcher.spec.ts +288 -0
  316. package/src/WebFetcher.ts +184 -186
  317. package/src/browser.ts +69 -0
  318. package/src/codecs/IndexCodec.ts +40 -0
  319. package/src/codecs/JsonCodec.spec.ts +70 -0
  320. package/src/codecs/JsonCodec.ts +37 -0
  321. package/src/codecs/LocalIndex.protobuf.spec.ts +115 -0
  322. package/src/codecs/ProtobufCodec.spec.ts +166 -0
  323. package/src/codecs/ProtobufCodec.ts +193 -0
  324. package/src/codecs/index.ts +4 -0
  325. package/src/codecs/migrateIndex.spec.ts +176 -0
  326. package/src/codecs/migrateIndex.ts +125 -0
  327. package/src/codecs/schemas/index.proto +34 -0
  328. package/src/index.ts +9 -1
  329. package/src/internals/Colorize.ts +19 -16
  330. package/src/server/IndexManager.ts +243 -0
  331. package/src/server/VectraServer.spec.ts +303 -0
  332. package/src/server/VectraServer.ts +156 -0
  333. package/src/server/handlers/documentHandlers.ts +59 -0
  334. package/src/server/handlers/helpers.ts +93 -0
  335. package/src/server/handlers/index.ts +7 -0
  336. package/src/server/handlers/indexHandlers.ts +44 -0
  337. package/src/server/handlers/itemHandlers.ts +140 -0
  338. package/src/server/handlers/lifecycleHandlers.ts +26 -0
  339. package/src/server/handlers/queryHandlers.ts +96 -0
  340. package/src/server/handlers/statsHandlers.ts +38 -0
  341. package/src/server/index.ts +3 -0
  342. package/src/storage/FileStorage.ts +105 -0
  343. package/src/storage/FileStorageUtilities.spec.ts +106 -0
  344. package/src/storage/FileStorageUtilities.ts +77 -0
  345. package/src/storage/FileType.ts +61 -0
  346. package/src/storage/IndexedDBStorage.ts +365 -0
  347. package/src/storage/LocalFileStorage.browser.ts +52 -0
  348. package/src/storage/LocalFileStorage.spec.ts +292 -0
  349. package/src/storage/LocalFileStorage.ts +98 -0
  350. package/src/storage/VirtualFileStorage.spec.ts +307 -0
  351. package/src/storage/VirtualFileStorage.ts +169 -0
  352. package/src/storage/index.ts +5 -0
  353. package/src/templates/csharp/README.md +48 -0
  354. package/src/templates/csharp/VectraClient.cs +234 -0
  355. package/src/templates/go/README.md +71 -0
  356. package/src/templates/go/vectra_client.go +322 -0
  357. package/src/templates/java/README.md +81 -0
  358. package/src/templates/java/VectraClient.java +232 -0
  359. package/src/templates/python/README.md +37 -0
  360. package/src/templates/python/vectra_client.py +279 -0
  361. package/src/templates/rust/Cargo.toml +14 -0
  362. package/src/templates/rust/README.md +39 -0
  363. package/src/templates/rust/build.rs +4 -0
  364. package/src/templates/rust/lib.rs +284 -0
  365. package/src/templates/typescript/README.md +96 -0
  366. package/src/templates/typescript/VectraClient.ts +374 -0
  367. package/src/types.ts +131 -123
  368. package/src/utils/index.ts +1 -0
  369. package/src/utils/pathUtils.ts +106 -0
  370. package/src/vectra-cli.generate.spec.ts +72 -0
  371. package/src/vectra-cli.spec.ts +0 -0
  372. package/src/vectra-cli.ts +687 -246
  373. package/README.draft.md +0 -499
  374. package/README.draft.outline.md +0 -160
  375. package/README.research.md +0 -2159
@@ -17,6 +17,8 @@ const sinon_1 = __importDefault(require("sinon"));
17
17
  const LocalIndex_1 = require("./LocalIndex");
18
18
  const promises_1 = __importDefault(require("fs/promises"));
19
19
  const path_1 = __importDefault(require("path"));
20
+ const storage_1 = require("./storage");
21
+ const LocalDocument_1 = require("./LocalDocument");
20
22
  describe('LocalIndex', () => {
21
23
  const testIndexDir = path_1.default.join(__dirname, 'test_index');
22
24
  const basicIndexItems = [
@@ -38,23 +40,26 @@ describe('LocalIndex', () => {
38
40
  node_assert_1.default.equal(created, true);
39
41
  node_assert_1.default.equal(index.folderPath, testIndexDir);
40
42
  }));
43
+ it('exposes getters indexName and storage', () => __awaiter(void 0, void 0, void 0, function* () {
44
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
45
+ node_assert_1.default.equal(index.indexName, 'index.json');
46
+ node_assert_1.default.ok(index.storage);
47
+ }));
41
48
  it('blocks concurrent operations when lock is held', () => __awaiter(void 0, void 0, void 0, function* () {
42
49
  const index = new LocalIndex_1.LocalIndex(testIndexDir);
43
50
  yield index.createIndex();
44
- yield index.beginUpdate(); // grab lock for a big update!
51
+ yield index.beginUpdate();
45
52
  yield node_assert_1.default.rejects(() => __awaiter(void 0, void 0, void 0, function* () {
46
- yield index.beginUpdate(); // try to grab lock again. should fail!
53
+ yield index.beginUpdate();
47
54
  }), new Error('Update already in progress'));
48
55
  }));
49
56
  describe('createIndex', () => {
50
57
  it('checks for existing index on creation', () => __awaiter(void 0, void 0, void 0, function* () {
51
58
  const index = new LocalIndex_1.LocalIndex(testIndexDir);
52
- yield index.createIndex(); // create first index.json
53
- // create without deleteIfExists. Will reject
59
+ yield index.createIndex();
54
60
  yield node_assert_1.default.rejects(() => __awaiter(void 0, void 0, void 0, function* () {
55
61
  yield index.createIndex();
56
62
  }), new Error('Index already exists'));
57
- // create with deleteIfExists. Should remove old data
58
63
  yield index.insertItem({ id: '1', vector: [1, 2, 3] });
59
64
  const lengthBefore = (yield index.listItems()).length;
60
65
  node_assert_1.default.equal(lengthBefore, 1);
@@ -72,6 +77,88 @@ describe('LocalIndex', () => {
72
77
  yield index.listItems();
73
78
  }));
74
79
  }));
80
+ it('persists version and metadata_config', () => __awaiter(void 0, void 0, void 0, function* () {
81
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
82
+ yield index.createIndex({ deleteIfExists: true, version: 2, metadata_config: { indexed: [] } });
83
+ const stats = yield index.getIndexStats();
84
+ node_assert_1.default.deepStrictEqual(stats, { version: 2, metadata_config: { indexed: [] }, items: 0 });
85
+ }));
86
+ });
87
+ describe('deleteIndex and load guard', () => {
88
+ it('listItems before createIndex rejects with not-exist error', () => __awaiter(void 0, void 0, void 0, function* () {
89
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
90
+ yield node_assert_1.default.rejects(() => __awaiter(void 0, void 0, void 0, function* () { return index.listItems(); }), new Error('Index does not exist'));
91
+ }));
92
+ it('deleteIndex removes the index and prevents further reads', () => __awaiter(void 0, void 0, void 0, function* () {
93
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
94
+ yield index.createIndex();
95
+ yield index.insertItem({ id: 'a', vector: [1] });
96
+ node_assert_1.default.equal(yield index.isIndexCreated(), true);
97
+ yield index.deleteIndex();
98
+ node_assert_1.default.equal(yield index.isIndexCreated(), false);
99
+ yield node_assert_1.default.rejects(() => __awaiter(void 0, void 0, void 0, function* () { return index.listItems(); }), new Error('Index does not exist'));
100
+ }));
101
+ });
102
+ describe('insert/upsert validation and behavior', () => {
103
+ it('insertItem validation: requires vector', () => __awaiter(void 0, void 0, void 0, function* () {
104
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
105
+ yield index.createIndex();
106
+ yield index.beginUpdate();
107
+ yield node_assert_1.default.rejects(() => __awaiter(void 0, void 0, void 0, function* () { return index.insertItem({ id: 'x' }); }), new Error('Vector is required'));
108
+ yield index.cancelUpdate();
109
+ }));
110
+ it('upsertItem inserts when not existing', () => __awaiter(void 0, void 0, void 0, function* () {
111
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
112
+ yield index.createIndex();
113
+ const inserted = yield index.upsertItem({ id: 'up', vector: [9, 9] });
114
+ node_assert_1.default.equal(inserted.id, 'up');
115
+ node_assert_1.default.deepStrictEqual(inserted.vector, [9, 9]);
116
+ const all = yield index.listItems();
117
+ node_assert_1.default.equal(all.length, 1);
118
+ node_assert_1.default.equal(all[0].id, 'up');
119
+ }));
120
+ it('upsertItem replaces existing item contents', () => __awaiter(void 0, void 0, void 0, function* () {
121
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
122
+ yield index.createIndex();
123
+ yield index.insertItem({ id: 'same', vector: [1], metadata: { a: 1 } });
124
+ const updated = yield index.upsertItem({ id: 'same', vector: [2], metadata: { a: 2 } });
125
+ node_assert_1.default.equal(updated.id, 'same');
126
+ node_assert_1.default.deepStrictEqual(updated.vector, [2]);
127
+ node_assert_1.default.deepStrictEqual(updated.metadata, { a: 2 });
128
+ const reread = yield index.getItem('same');
129
+ node_assert_1.default.deepStrictEqual(reread === null || reread === void 0 ? void 0 : reread.vector, [2]);
130
+ node_assert_1.default.deepStrictEqual(reread === null || reread === void 0 ? void 0 : reread.metadata, { a: 2 });
131
+ }));
132
+ it('auto-generates id when not provided and does not create metadataFile with no metadata even if indexed config exists', () => __awaiter(void 0, void 0, void 0, function* () {
133
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
134
+ yield index.createIndex({ version: 1, metadata_config: { indexed: ['keep'] } });
135
+ const inserted = yield index.insertItem({ vector: [1, 2, 3] });
136
+ node_assert_1.default.ok(inserted.id && typeof inserted.id === 'string');
137
+ const reread = yield index.getItem(inserted.id);
138
+ node_assert_1.default.deepStrictEqual(reread === null || reread === void 0 ? void 0 : reread.metadata, {});
139
+ node_assert_1.default.equal(reread.metadataFile, undefined);
140
+ }));
141
+ });
142
+ describe('cancelUpdate', () => {
143
+ it('discards staged changes', () => __awaiter(void 0, void 0, void 0, function* () {
144
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
145
+ yield index.createIndex();
146
+ yield index.beginUpdate();
147
+ yield index.insertItem({ id: 'temp', vector: [1, 1, 1] });
148
+ index.cancelUpdate();
149
+ const items = yield index.listItems();
150
+ node_assert_1.default.deepStrictEqual(items, []);
151
+ }));
152
+ });
153
+ describe('isIndexCreated transitions', () => {
154
+ it('reports false -> true -> false across lifecycle', () => __awaiter(void 0, void 0, void 0, function* () {
155
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
156
+ node_assert_1.default.equal(yield index.isIndexCreated(), false);
157
+ yield index.createIndex();
158
+ node_assert_1.default.equal(yield index.isIndexCreated(), true);
159
+ yield index.deleteIndex();
160
+ node_assert_1.default.equal(yield index.isIndexCreated(), false);
161
+ }));
75
162
  });
76
163
  describe('deleteItem', () => {
77
164
  it('does nothing when id not found', () => __awaiter(void 0, void 0, void 0, function* () {
@@ -104,14 +191,30 @@ describe('LocalIndex', () => {
104
191
  { id: '2', vector: [] },
105
192
  { id: '3', vector: [] },
106
193
  { id: '4', vector: [] },
107
- { id: '5', vector: [] },
194
+ { id: '5', vector: [] }
108
195
  ]);
109
196
  yield index.beginUpdate();
110
197
  yield index.deleteItem('1');
111
198
  yield index.deleteItem('3');
112
199
  yield index.deleteItem('5');
113
200
  yield index.endUpdate();
114
- node_assert_1.default.deepStrictEqual(yield index.listItems(), [{ id: '2', vector: [], metadata: {}, norm: 0 }, { id: '4', vector: [], metadata: {}, norm: 0 }]);
201
+ node_assert_1.default.deepStrictEqual(yield index.listItems(), [
202
+ { id: '2', vector: [], metadata: {}, norm: 0 },
203
+ { id: '4', vector: [], metadata: {}, norm: 0 }
204
+ ]);
205
+ }));
206
+ it('no-op delete while update active when id missing', () => __awaiter(void 0, void 0, void 0, function* () {
207
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
208
+ yield index.createIndex();
209
+ yield index.batchInsertItems([
210
+ { id: '1', vector: [1] },
211
+ { id: '2', vector: [2] }
212
+ ]);
213
+ yield index.beginUpdate();
214
+ yield node_assert_1.default.doesNotReject(() => __awaiter(void 0, void 0, void 0, function* () { return index.deleteItem('missing'); }));
215
+ yield index.endUpdate();
216
+ const items = yield index.listItems();
217
+ node_assert_1.default.deepStrictEqual(items.map(i => i.id), ['1', '2']);
115
218
  }));
116
219
  });
117
220
  describe('endUpdate', () => {
@@ -122,7 +225,7 @@ describe('LocalIndex', () => {
122
225
  }), new Error('No update in progress'));
123
226
  }));
124
227
  it('throws an error if the index could not be saved', () => __awaiter(void 0, void 0, void 0, function* () {
125
- const index = new LocalIndex_1.LocalIndex(testIndexDir, 'index.json');
228
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
126
229
  yield index.createIndex();
127
230
  yield index.beginUpdate();
128
231
  sinon_1.default.stub(promises_1.default, 'writeFile').rejects(new Error('fs error'));
@@ -164,7 +267,7 @@ describe('LocalIndex', () => {
164
267
  yield index.batchInsertItems(basicIndexItems);
165
268
  const item2 = yield index.getItem('2');
166
269
  node_assert_1.default.equal(item2 === null || item2 === void 0 ? void 0 : item2.id, basicIndexItems[1].id);
167
- node_assert_1.default.equal(item2 === null || item2 === void 0 ? void 0 : item2.vector, basicIndexItems[1].vector);
270
+ node_assert_1.default.deepStrictEqual(item2 === null || item2 === void 0 ? void 0 : item2.vector, basicIndexItems[1].vector);
168
271
  node_assert_1.default.equal((yield index.listItems()).length, 3);
169
272
  }));
170
273
  });
@@ -181,14 +284,12 @@ describe('LocalIndex', () => {
181
284
  const index = new LocalIndex_1.LocalIndex(testIndexDir);
182
285
  yield index.createIndex();
183
286
  yield index.insertItem({ id: '2', vector: [9, 9, 9] });
184
- // ensures insert error is bubbled up to batchIndexItems caller
185
287
  yield node_assert_1.default.rejects(() => __awaiter(void 0, void 0, void 0, function* () {
186
288
  yield index.batchInsertItems(basicIndexItems);
187
289
  }), {
188
290
  name: 'Error',
189
291
  message: 'Item with id 2 already exists'
190
292
  });
191
- // ensures no partial update is applied
192
293
  const storedItems = yield index.listItems();
193
294
  node_assert_1.default.equal(storedItems.length, 1);
194
295
  }));
@@ -202,13 +303,13 @@ describe('LocalIndex', () => {
202
303
  { id: '2', vector: [], metadata: { category: 'food' } },
203
304
  { id: '3', vector: [], metadata: { category: 'electronics' } },
204
305
  { id: '4', vector: [], metadata: { category: 'drink' } },
205
- { id: '5', vector: [], metadata: { category: 'food' } },
306
+ { id: '5', vector: [], metadata: { category: 'food' } }
206
307
  ]);
207
- const foodItems = yield index.listItemsByMetadata({ category: { '$eq': 'food' } });
208
- node_assert_1.default.deepStrictEqual(foodItems.map((item) => item.id), ["1", "2", "5"]);
209
- const drinkItems = yield index.listItemsByMetadata({ category: { '$eq': 'drink' } });
210
- node_assert_1.default.deepStrictEqual(drinkItems.map((item) => item.id), ["4"]);
211
- const clothingItems = yield index.listItemsByMetadata({ category: { '$eq': 'clothes' } });
308
+ const foodItems = yield index.listItemsByMetadata({ category: { $eq: 'food' } });
309
+ node_assert_1.default.deepStrictEqual(foodItems.map(item => item.id), ['1', '2', '5']);
310
+ const drinkItems = yield index.listItemsByMetadata({ category: { $eq: 'drink' } });
311
+ node_assert_1.default.deepStrictEqual(drinkItems.map(item => item.id), ['4']);
312
+ const clothingItems = yield index.listItemsByMetadata({ category: { $eq: 'clothes' } });
212
313
  node_assert_1.default.deepStrictEqual(clothingItems, []);
213
314
  }));
214
315
  it('returns nothing when no items in index', () => __awaiter(void 0, void 0, void 0, function* () {
@@ -217,58 +318,348 @@ describe('LocalIndex', () => {
217
318
  const items = yield index.listItemsByMetadata({});
218
319
  node_assert_1.default.deepStrictEqual(items, []);
219
320
  }));
321
+ it('empty filter {} with items returns all', () => __awaiter(void 0, void 0, void 0, function* () {
322
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
323
+ yield index.createIndex();
324
+ yield index.batchInsertItems([
325
+ { id: 'a', vector: [1] },
326
+ { id: 'b', vector: [2] }
327
+ ]);
328
+ const items = yield index.listItemsByMetadata({});
329
+ node_assert_1.default.deepStrictEqual(items.map(i => i.id), ['a', 'b']);
330
+ }));
331
+ });
332
+ describe('metadata indexing behavior', () => {
333
+ it('stores only indexed metadata in index and writes full metadata to external file', () => __awaiter(void 0, void 0, void 0, function* () {
334
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
335
+ yield index.createIndex({ version: 1, metadata_config: { indexed: ['keep'] } });
336
+ const realWriteFile = promises_1.default.writeFile.bind(promises_1.default);
337
+ const writes = [];
338
+ sinon_1.default.stub(promises_1.default, 'writeFile').callsFake((file, data, options) => __awaiter(void 0, void 0, void 0, function* () {
339
+ writes.push({ file, data });
340
+ return realWriteFile(file, data, options);
341
+ }));
342
+ yield index.insertItem({ id: 'm1', vector: [1], metadata: { keep: 'x', drop: 'y' } });
343
+ const items = yield index.listItems();
344
+ const stored = items.find(i => i.id === 'm1');
345
+ node_assert_1.default.deepStrictEqual(stored.metadata, { keep: 'x' });
346
+ node_assert_1.default.ok(stored.metadataFile);
347
+ const textPayloads = writes
348
+ .map(w => { var _a, _b; return (typeof w.data === 'string' ? w.data : (_b = (_a = w.data) === null || _a === void 0 ? void 0 : _a.toString) === null || _b === void 0 ? void 0 : _b.call(_a)); })
349
+ .filter(Boolean);
350
+ const hasFullMetadata = textPayloads.some(t => {
351
+ try {
352
+ const obj = JSON.parse(t);
353
+ return obj && obj.keep === 'x' && obj.drop === 'y';
354
+ }
355
+ catch (_a) {
356
+ return false;
357
+ }
358
+ });
359
+ node_assert_1.default.equal(hasFullMetadata, true);
360
+ }));
361
+ it('does not write external file when metadata only contains indexed keys', () => __awaiter(void 0, void 0, void 0, function* () {
362
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
363
+ yield index.createIndex({ version: 1, metadata_config: { indexed: ['only'] } });
364
+ yield index.insertItem({ id: 'm2', vector: [1], metadata: { only: 'ok' } });
365
+ const item = yield index.getItem('m2');
366
+ node_assert_1.default.deepStrictEqual(item === null || item === void 0 ? void 0 : item.metadata, { only: 'ok' });
367
+ node_assert_1.default.equal(item.metadataFile, undefined);
368
+ }));
220
369
  });
221
- describe("queryItems", () => {
222
- it("returns empty array on empty index search", () => __awaiter(void 0, void 0, void 0, function* () {
370
+ describe('queryItems', () => {
371
+ it('upsertItem uses the in-progress update path when _update is present', () => __awaiter(void 0, void 0, void 0, function* () {
372
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
373
+ yield index.createIndex();
374
+ yield index.beginUpdate();
375
+ // goes through the if (this._update) early return branch in upsertItem
376
+ const up = yield index.upsertItem({ id: 'inplace', vector: [7, 7], metadata: { k: 'v' } });
377
+ // not persisted until endUpdate
378
+ let items = yield index.listItems();
379
+ node_assert_1.default.equal(items.length, 0);
380
+ yield index.endUpdate();
381
+ items = yield index.listItems();
382
+ node_assert_1.default.equal(items.length, 1);
383
+ node_assert_1.default.equal(items[0].id, 'inplace');
384
+ node_assert_1.default.deepStrictEqual(items[0].metadata, { k: 'v' });
385
+ }));
386
+ it('with no indexed config, full metadata is stored inline and no metadataFile is written', () => __awaiter(void 0, void 0, void 0, function* () {
387
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
388
+ yield index.createIndex({ version: 1 /* metadata_config undefined => inline */ });
389
+ yield index.insertItem({ id: 'fullMd', vector: [1], metadata: { a: 1, b: 2 } });
390
+ const item = yield index.getItem('fullMd');
391
+ node_assert_1.default.deepStrictEqual(item === null || item === void 0 ? void 0 : item.metadata, { a: 1, b: 2 });
392
+ node_assert_1.default.equal(item.metadataFile, undefined);
393
+ }));
394
+ it('BM25 uses the default docReader (LocalDocument.loadText) when not injected', () => __awaiter(void 0, void 0, void 0, function* () {
395
+ // stub LocalDocument.loadText so default docReader path runs without touching disk
396
+ const stub = sinon_1.default.stub(LocalDocument_1.LocalDocument.prototype, 'loadText').resolves('Hello default docReader text');
397
+ const addDocSpy = sinon_1.default.spy();
398
+ const fakeEngine = {
399
+ defineConfig: sinon_1.default.stub(),
400
+ definePrepTasks: sinon_1.default.stub(),
401
+ addDoc: (...a) => addDocSpy(...a),
402
+ consolidate: sinon_1.default.stub(),
403
+ search: (_q) => []
404
+ };
405
+ const index = new LocalIndex_1.LocalIndex(testIndexDir, undefined, undefined, undefined, { bm25Factory: () => fakeEngine /* no docReader injected */ });
406
+ yield index.createIndex();
407
+ yield index.batchInsertItems([
408
+ { id: 'a', vector: [1, 0, 0], metadata: { documentId: 'docA', startPos: 0, endPos: 4 } },
409
+ { id: 'b', vector: [0, 1, 0], metadata: { documentId: 'docB', startPos: 0, endPos: 4 } }
410
+ ]);
411
+ yield index.queryItems([1, 0, 0], 'kw', 1, undefined, true);
412
+ node_assert_1.default.ok(addDocSpy.called); // default docReader loaded and chunks added
413
+ stub.restore();
414
+ }));
415
+ it('executes the prepTask defined in setupBm25 to cover tokenization/negation pipeline', () => __awaiter(void 0, void 0, void 0, function* () {
416
+ let capturedTasks = [];
417
+ const fakeEngine = {
418
+ defineConfig: sinon_1.default.stub(),
419
+ definePrepTasks: (arr) => { capturedTasks = arr; },
420
+ addDoc: sinon_1.default.stub(),
421
+ consolidate: sinon_1.default.stub(),
422
+ search: (_q) => []
423
+ };
424
+ const index = new LocalIndex_1.LocalIndex(testIndexDir, undefined, undefined, undefined, { bm25Factory: () => fakeEngine, docReader: () => __awaiter(void 0, void 0, void 0, function* () { return 'text'; }) });
425
+ yield index.createIndex();
426
+ // trigger setupBm25 via a BM25 query
427
+ yield index.batchInsertItems([{ id: 'x', vector: [1], metadata: { documentId: 'd', startPos: 0, endPos: 0 } }]);
428
+ yield index.queryItems([1], 'q', 1, undefined, true);
429
+ node_assert_1.default.ok(Array.isArray(capturedTasks) && capturedTasks.length === 1);
430
+ const tokens = capturedTasks[0]("I don't like complicated tokens!");
431
+ // ensure pipeline ran: non-empty tokens, punctuation removed, possible negation handling
432
+ node_assert_1.default.ok(Array.isArray(tokens) && tokens.length > 0);
433
+ }));
434
+ it('upsertItem uses the in-progress update path when _update is present', () => __awaiter(void 0, void 0, void 0, function* () {
435
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
436
+ yield index.createIndex();
437
+ yield index.beginUpdate();
438
+ yield index.upsertItem({ id: 'inplace', vector: [7, 7], metadata: { k: 'v' } });
439
+ // Not persisted yet because endUpdate not called
440
+ let items = yield index.listItems();
441
+ node_assert_1.default.equal(items.length, 0);
442
+ yield index.endUpdate();
443
+ items = yield index.listItems();
444
+ node_assert_1.default.equal(items.length, 1);
445
+ node_assert_1.default.equal(items[0].id, 'inplace');
446
+ node_assert_1.default.deepStrictEqual(items[0].metadata, { k: 'v' });
447
+ }));
448
+ it('with no indexed config, full metadata is stored inline and no metadataFile is written', () => __awaiter(void 0, void 0, void 0, function* () {
223
449
  const index = new LocalIndex_1.LocalIndex(testIndexDir);
450
+ yield index.createIndex({ version: 1 }); // metadata_config undefined => inline
451
+ yield index.insertItem({ id: 'fullMd', vector: [1], metadata: { a: 1, b: 2 } });
452
+ const item = yield index.getItem('fullMd');
453
+ node_assert_1.default.deepStrictEqual(item === null || item === void 0 ? void 0 : item.metadata, { a: 1, b: 2 });
454
+ node_assert_1.default.equal(item.metadataFile, undefined);
455
+ }));
456
+ it('BM25 uses the default docReader (LocalDocument.loadText) when not injected', () => __awaiter(void 0, void 0, void 0, function* () {
457
+ const stub = sinon_1.default.stub(LocalDocument_1.LocalDocument.prototype, 'loadText').resolves('Hello default docReader text');
458
+ const addDocSpy = sinon_1.default.spy();
459
+ const fakeEngine = {
460
+ defineConfig: sinon_1.default.stub(),
461
+ definePrepTasks: sinon_1.default.stub(),
462
+ addDoc: (...a) => addDocSpy(...a),
463
+ consolidate: sinon_1.default.stub(),
464
+ search: (_q) => []
465
+ };
466
+ const index = new LocalIndex_1.LocalIndex(testIndexDir, undefined, undefined, undefined, { bm25Factory: () => fakeEngine });
224
467
  yield index.createIndex();
225
- const result = yield index.queryItems([1, 2, 3], "", 10);
468
+ yield index.batchInsertItems([
469
+ { id: 'a', vector: [1, 0, 0], metadata: { documentId: 'docA', startPos: 0, endPos: 4 } },
470
+ { id: 'b', vector: [0, 1, 0], metadata: { documentId: 'docB', startPos: 0, endPos: 4 } }
471
+ ]);
472
+ yield index.queryItems([1, 0, 0], 'kw', 1, undefined, true);
473
+ node_assert_1.default.ok(addDocSpy.called);
474
+ stub.restore();
475
+ }));
476
+ it('executes the prepTask defined in setupBm25 to cover tokenization/negation pipeline', () => __awaiter(void 0, void 0, void 0, function* () {
477
+ let capturedTasks = [];
478
+ const fakeEngine = {
479
+ defineConfig: sinon_1.default.stub(),
480
+ definePrepTasks: (arr) => { capturedTasks = arr; },
481
+ addDoc: sinon_1.default.stub(),
482
+ consolidate: sinon_1.default.stub(),
483
+ search: (_q) => []
484
+ };
485
+ const index = new LocalIndex_1.LocalIndex(testIndexDir, undefined, undefined, undefined, { bm25Factory: () => fakeEngine, docReader: () => __awaiter(void 0, void 0, void 0, function* () { return 'text'; }) });
486
+ yield index.createIndex();
487
+ yield index.batchInsertItems([{ id: 'x', vector: [1], metadata: { documentId: 'd', startPos: 0, endPos: 0 } }]);
488
+ yield index.queryItems([1], 'q', 1, undefined, true);
489
+ node_assert_1.default.ok(Array.isArray(capturedTasks) && capturedTasks.length === 1);
490
+ const tokens = capturedTasks[0]("I don't like complicated tokens!");
491
+ node_assert_1.default.ok(Array.isArray(tokens) && tokens.length > 0);
492
+ }));
493
+ it('returns empty array on empty index search', () => __awaiter(void 0, void 0, void 0, function* () {
494
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
495
+ yield index.createIndex();
496
+ const result = yield index.queryItems([1, 2, 3], '', 10);
226
497
  node_assert_1.default.deepStrictEqual(result, []);
227
498
  }));
228
- it("returns bad match when no better match exists", () => __awaiter(void 0, void 0, void 0, function* () {
499
+ it('returns bad match when no better match exists', () => __awaiter(void 0, void 0, void 0, function* () {
229
500
  var _a, _b;
230
501
  const index = new LocalIndex_1.LocalIndex(testIndexDir);
231
502
  yield index.createIndex();
232
- yield index.insertItem({ id: "1", vector: [0.9, 0, 0, 0, 0] });
233
- const result = yield index.queryItems([0, 0, 0, 0, 0.1], "", 1);
503
+ yield index.insertItem({ id: '1', vector: [0.9, 0, 0, 0, 0] });
504
+ const result = yield index.queryItems([0, 0, 0, 0, 0.1], '', 1);
234
505
  node_assert_1.default.equal((_a = result[0]) === null || _a === void 0 ? void 0 : _a.score, 0);
235
- node_assert_1.default.equal((_b = result[0]) === null || _b === void 0 ? void 0 : _b.item.id, "1");
506
+ node_assert_1.default.equal((_b = result[0]) === null || _b === void 0 ? void 0 : _b.item.id, '1');
236
507
  }));
237
- it("returns all vectors when fewer than topK exist", () => __awaiter(void 0, void 0, void 0, function* () {
508
+ it('returns all vectors when fewer than topK exist', () => __awaiter(void 0, void 0, void 0, function* () {
238
509
  const index = new LocalIndex_1.LocalIndex(testIndexDir);
239
510
  yield index.createIndex();
240
511
  yield index.batchInsertItems(basicIndexItems);
241
- const result = yield index.queryItems([0, 0, 1], "", 10);
512
+ const result = yield index.queryItems([0, 0, 1], '', 10);
242
513
  node_assert_1.default.equal(result.length, 3);
243
- node_assert_1.default.deepStrictEqual(result.map(({ item }) => item.id), basicIndexItems.map((item) => item.id));
514
+ node_assert_1.default.deepStrictEqual(result.map(({ item }) => item.id), basicIndexItems.map(item => item.id));
515
+ }));
516
+ it('limits results to topK when more items exist', () => __awaiter(void 0, void 0, void 0, function* () {
517
+ const index = new LocalIndex_1.LocalIndex(testIndexDir);
518
+ yield index.createIndex();
519
+ yield index.batchInsertItems([
520
+ { id: 'a', vector: [1, 0, 0] },
521
+ { id: 'b', vector: [0, 1, 0] },
522
+ { id: 'c', vector: [0, 0, 1] },
523
+ { id: 'd', vector: [1, 1, 0] },
524
+ { id: 'e', vector: [0, 1, 1] }
525
+ ]);
526
+ const result = yield index.queryItems([1, 0, 0], '', 2);
527
+ node_assert_1.default.equal(result.length, 2);
244
528
  }));
245
- it("filters by metadata when filter provided", () => __awaiter(void 0, void 0, void 0, function* () {
529
+ it('filters by metadata when filter provided', () => __awaiter(void 0, void 0, void 0, function* () {
246
530
  const index = new LocalIndex_1.LocalIndex(testIndexDir);
247
531
  yield index.createIndex();
248
532
  yield index.batchInsertItems([
249
- { id: "1", vector: [1, 0, 0], metadata: { category: "food" } },
250
- { id: "2", vector: [0, 0, 1], metadata: { category: "drink" } },
533
+ { id: '1', vector: [1, 0, 0], metadata: { category: 'food' } },
534
+ { id: '2', vector: [0, 0, 1], metadata: { category: 'drink' } }
251
535
  ]);
252
- const bestGeneralMatch = yield index.queryItems([1, 0, 0], "", 1);
253
- const bestDrinkMatch = yield index.queryItems([1, 0, 0], "", 1, {
254
- category: { $eq: "drink" },
536
+ const bestGeneralMatch = yield index.queryItems([1, 0, 0], '', 1);
537
+ const bestDrinkMatch = yield index.queryItems([1, 0, 0], '', 1, {
538
+ category: { $eq: 'drink' }
255
539
  });
256
- node_assert_1.default.equal(bestGeneralMatch[0].item.id, "1");
257
- node_assert_1.default.equal(bestDrinkMatch[0].item.id, "2");
540
+ node_assert_1.default.equal(bestGeneralMatch[0].item.id, '1');
541
+ node_assert_1.default.equal(bestDrinkMatch[0].item.id, '2');
258
542
  }));
259
- it("reads item metadata file when provided", () => __awaiter(void 0, void 0, void 0, function* () {
543
+ it('reads item metadata file when provided', () => __awaiter(void 0, void 0, void 0, function* () {
260
544
  const index = new LocalIndex_1.LocalIndex(testIndexDir);
261
545
  yield index.createIndex({ version: 1, metadata_config: { indexed: ['category'] } });
262
546
  yield index.batchInsertItems([
263
- { id: "1", vector: [1, 0, 0] },
264
- { id: "2", vector: [0, 0, 1], metadata: { category: 'drink' } },
547
+ { id: '1', vector: [1, 0, 0] },
548
+ { id: '2', vector: [0, 0, 1], metadata: { category: 'drink', extra: 'x' } }
265
549
  ]);
266
- sinon_1.default
267
- .stub(promises_1.default, "readFile")
268
- .resolves(JSON.stringify({ category: "drink" }));
269
- const bestDrinkMatch = yield index.queryItems([1, 0, 0], "", 2, { category: { '$eq': 'drink' } });
550
+ sinon_1.default.stub(promises_1.default, 'readFile').resolves(JSON.stringify({ category: 'drink', extra: 'x' }));
551
+ const bestDrinkMatch = yield index.queryItems([1, 0, 0], '', 2, { category: { $eq: 'drink' } });
270
552
  node_assert_1.default.notEqual(bestDrinkMatch[0].item.metadataFile, undefined);
271
- node_assert_1.default.equal(bestDrinkMatch[0].item.id, "2");
553
+ node_assert_1.default.equal(bestDrinkMatch[0].item.id, '2');
554
+ }));
555
+ it('appends BM25 results when isBm25=true (tuple results)', () => __awaiter(void 0, void 0, void 0, function* () {
556
+ // Inject a fake BM25 engine and docReader
557
+ const addDocSpy = sinon_1.default.spy();
558
+ const consolidateSpy = sinon_1.default.spy();
559
+ const fakeEngine = {
560
+ defineConfig: sinon_1.default.stub(),
561
+ definePrepTasks: sinon_1.default.stub(),
562
+ addDoc: (...a) => addDocSpy(...a),
563
+ consolidate: (...a) => consolidateSpy(...a),
564
+ search: (q) => {
565
+ void q;
566
+ // results as tuples [index, score]
567
+ return [[0, 0.123], [1, 0.122]];
568
+ }
569
+ };
570
+ const index = new LocalIndex_1.LocalIndex(testIndexDir, undefined, undefined, undefined, {
571
+ bm25Factory: () => fakeEngine,
572
+ docReader: (_docId) => __awaiter(void 0, void 0, void 0, function* () { return 'SAMPLETEXT'; })
573
+ });
574
+ yield index.createIndex();
575
+ yield index.batchInsertItems([
576
+ { id: 's1', vector: [1, 0, 0], metadata: { category: 'alpha', documentId: 'd1', startPos: 0, endPos: 3 } },
577
+ { id: 's2', vector: [0, 1, 0], metadata: { category: 'beta', documentId: 'd2', startPos: 0, endPos: 3 } },
578
+ { id: 's3', vector: [0, 0, 1], metadata: { category: 'gamma', documentId: 'd3', startPos: 0, endPos: 3 } }
579
+ ]);
580
+ const topK = 1;
581
+ const results = yield index.queryItems([1, 0, 0], 'keyword', topK, undefined, true);
582
+ node_assert_1.default.ok(results.length >= 1);
583
+ node_assert_1.default.ok(results.some(r => { var _a; return ((_a = r.item.metadata) === null || _a === void 0 ? void 0 : _a.isBm25) === true; }));
584
+ node_assert_1.default.ok(consolidateSpy.calledOnce);
585
+ // only non-top items should have been offered to addDoc (top item excluded)
586
+ node_assert_1.default.ok(addDocSpy.callCount >= 1);
587
+ }));
588
+ it('BM25 indexes only non-top items with document metadata, calls consolidate, and swallows load errors', () => __awaiter(void 0, void 0, void 0, function* () {
589
+ // docReader returns text for docB, throws for docC
590
+ const addDocSpy = sinon_1.default.spy();
591
+ const consolidateSpy = sinon_1.default.spy();
592
+ const fakeEngine = {
593
+ defineConfig: sinon_1.default.stub(),
594
+ definePrepTasks: sinon_1.default.stub(),
595
+ addDoc: (...a) => addDocSpy(...a),
596
+ consolidate: (...a) => consolidateSpy(...a),
597
+ search: (_q) => {
598
+ // invalid tuple index is ignored
599
+ return [[999, 0.77]];
600
+ }
601
+ };
602
+ const docReader = (docId) => __awaiter(void 0, void 0, void 0, function* () {
603
+ if (docId === 'docB')
604
+ return 'ABCDEFGHIJ';
605
+ if (docId === 'docC')
606
+ throw new Error('load failed');
607
+ return '';
608
+ });
609
+ const index = new LocalIndex_1.LocalIndex(testIndexDir, undefined, undefined, undefined, { bm25Factory: () => fakeEngine, docReader });
610
+ yield index.createIndex();
611
+ yield index.batchInsertItems([
612
+ { id: 'sTop', vector: [1, 0, 0], metadata: { documentId: 'docA', startPos: 0, endPos: 4 } },
613
+ { id: 'd1', vector: [0, 1, 0], metadata: { documentId: 'docB', startPos: 0, endPos: 4 } },
614
+ { id: 'd2', vector: [0, 0, 1], metadata: { documentId: 'docC', startPos: 0, endPos: 4 } }
615
+ ]);
616
+ const res = yield index.queryItems([1, 0, 0], 'kw', 1, undefined, true);
617
+ node_assert_1.default.equal(addDocSpy.callCount, 1); // only d1 added; d2 threw; sTop excluded
618
+ node_assert_1.default.equal(consolidateSpy.callCount, 1);
619
+ node_assert_1.default.ok(res.length >= 1);
620
+ }));
621
+ it('BM25 object results are appended and marked isBm25 even if item is undefined', () => __awaiter(void 0, void 0, void 0, function* () {
622
+ const fakeEngine = {
623
+ defineConfig: sinon_1.default.stub(),
624
+ definePrepTasks: sinon_1.default.stub(),
625
+ addDoc: sinon_1.default.stub(),
626
+ consolidate: sinon_1.default.stub(),
627
+ search: (_q) => [{ item: undefined, score: 0.55 }]
628
+ };
629
+ const index = new LocalIndex_1.LocalIndex(testIndexDir, undefined, undefined, undefined, { bm25Factory: () => fakeEngine, docReader: () => __awaiter(void 0, void 0, void 0, function* () { return 'YY'; }) });
630
+ yield index.createIndex();
631
+ yield index.batchInsertItems([
632
+ { id: 'x1', vector: [1, 0], metadata: { documentId: 'doc1', startPos: 0, endPos: 1 } },
633
+ { id: 'x2', vector: [0, 1], metadata: { documentId: 'doc2', startPos: 0, endPos: 1 } }
634
+ ]);
635
+ const res = yield index.queryItems([1, 0], 'any', 1, undefined, true);
636
+ node_assert_1.default.ok(res.some(r => { var _a; return ((_a = r.item.metadata) === null || _a === void 0 ? void 0 : _a.isBm25) === true; }));
637
+ }));
638
+ it('BM25 engine missing addDoc/consolidate does not throw and returns semantic results', () => __awaiter(void 0, void 0, void 0, function* () {
639
+ const fakeEngine = {
640
+ defineConfig: sinon_1.default.stub(),
641
+ definePrepTasks: sinon_1.default.stub(),
642
+ search: (_q) => []
643
+ };
644
+ const index = new LocalIndex_1.LocalIndex(testIndexDir, undefined, undefined, undefined, { bm25Factory: () => fakeEngine, docReader: () => __awaiter(void 0, void 0, void 0, function* () { return 'YY'; }) });
645
+ yield index.createIndex();
646
+ yield index.batchInsertItems([
647
+ { id: 's1', vector: [1, 0], metadata: { documentId: 'doc1', startPos: 0, endPos: 1 } },
648
+ { id: 's2', vector: [0, 1], metadata: { documentId: 'doc2', startPos: 0, endPos: 1 } }
649
+ ]);
650
+ const res = yield index.queryItems([1, 0], 'kw', 1, undefined, true);
651
+ node_assert_1.default.ok(res.length >= 1);
652
+ node_assert_1.default.ok(res.every(r => { var _a; return !((_a = r.item.metadata) === null || _a === void 0 ? void 0 : _a.isBm25); }));
653
+ }));
654
+ });
655
+ describe('VirtualFileStorage (in-memory)', () => {
656
+ it('works end-to-end in-memory without touching disk', () => __awaiter(void 0, void 0, void 0, function* () {
657
+ const storage = new storage_1.VirtualFileStorage();
658
+ const index = new LocalIndex_1.LocalIndex('mem://idx', undefined, storage);
659
+ yield index.createIndex({ version: 3, metadata_config: { indexed: ['t'] } });
660
+ yield index.insertItem({ vector: [1], metadata: { t: 'x', other: 'y' } });
661
+ const stats = yield index.getIndexStats();
662
+ node_assert_1.default.deepStrictEqual(stats, { version: 3, metadata_config: { indexed: ['t'] }, items: 1 });
272
663
  }));
273
664
  });
274
665
  });