codevault 1.7.3 → 1.7.5

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 (227) hide show
  1. package/README.md +18 -5
  2. package/dist/chunking/semantic-chunker.d.ts.map +1 -1
  3. package/dist/chunking/semantic-chunker.js +21 -8
  4. package/dist/chunking/semantic-chunker.js.map +1 -1
  5. package/dist/chunking/token-counter.js +3 -3
  6. package/dist/chunking/token-counter.js.map +1 -1
  7. package/dist/cli/commands/chat-cmd.js +2 -1
  8. package/dist/cli/commands/chat-cmd.js.map +1 -1
  9. package/dist/cli/commands/config-cmd.js +4 -4
  10. package/dist/cli/commands/config-cmd.js.map +1 -1
  11. package/dist/cli/commands/index-cmd.d.ts +3 -0
  12. package/dist/cli/commands/index-cmd.d.ts.map +1 -0
  13. package/dist/cli/commands/index-cmd.js +118 -0
  14. package/dist/cli/commands/index-cmd.js.map +1 -0
  15. package/dist/cli/commands/info-cmd.d.ts +3 -0
  16. package/dist/cli/commands/info-cmd.d.ts.map +1 -0
  17. package/dist/cli/commands/info-cmd.js +47 -0
  18. package/dist/cli/commands/info-cmd.js.map +1 -0
  19. package/dist/cli/commands/interactive-config.js +1 -1
  20. package/dist/cli/commands/interactive-config.js.map +1 -1
  21. package/dist/cli/commands/mcp-cmd.d.ts +3 -0
  22. package/dist/cli/commands/mcp-cmd.d.ts.map +1 -0
  23. package/dist/cli/commands/mcp-cmd.js +33 -0
  24. package/dist/cli/commands/mcp-cmd.js.map +1 -0
  25. package/dist/cli/commands/search-cmd.d.ts +3 -0
  26. package/dist/cli/commands/search-cmd.d.ts.map +1 -0
  27. package/dist/cli/commands/search-cmd.js +52 -0
  28. package/dist/cli/commands/search-cmd.js.map +1 -0
  29. package/dist/cli/commands/search-with-code-cmd.d.ts +3 -0
  30. package/dist/cli/commands/search-with-code-cmd.d.ts.map +1 -0
  31. package/dist/cli/commands/search-with-code-cmd.js +74 -0
  32. package/dist/cli/commands/search-with-code-cmd.js.map +1 -0
  33. package/dist/cli/commands/update-cmd.d.ts +3 -0
  34. package/dist/cli/commands/update-cmd.d.ts.map +1 -0
  35. package/dist/cli/commands/update-cmd.js +24 -0
  36. package/dist/cli/commands/update-cmd.js.map +1 -0
  37. package/dist/cli/commands/watch-cmd.d.ts +3 -0
  38. package/dist/cli/commands/watch-cmd.d.ts.map +1 -0
  39. package/dist/cli/commands/watch-cmd.js +48 -0
  40. package/dist/cli/commands/watch-cmd.js.map +1 -0
  41. package/dist/cli/index.d.ts +3 -0
  42. package/dist/cli/index.d.ts.map +1 -0
  43. package/dist/cli/index.js +47 -0
  44. package/dist/cli/index.js.map +1 -0
  45. package/dist/cli.d.ts +1 -1
  46. package/dist/cli.d.ts.map +1 -1
  47. package/dist/cli.js +4 -398
  48. package/dist/cli.js.map +1 -1
  49. package/dist/codemap/io.d.ts +1 -0
  50. package/dist/codemap/io.d.ts.map +1 -1
  51. package/dist/codemap/io.js.map +1 -1
  52. package/dist/config/constants.d.ts +11 -0
  53. package/dist/config/constants.d.ts.map +1 -1
  54. package/dist/config/constants.js +9 -0
  55. package/dist/config/constants.js.map +1 -1
  56. package/dist/config/loader.d.ts.map +1 -1
  57. package/dist/config/loader.js +9 -2
  58. package/dist/config/loader.js.map +1 -1
  59. package/dist/core/IndexerEngine.d.ts +9 -17
  60. package/dist/core/IndexerEngine.d.ts.map +1 -1
  61. package/dist/core/IndexerEngine.js +72 -347
  62. package/dist/core/IndexerEngine.js.map +1 -1
  63. package/dist/core/SearchService.d.ts +13 -13
  64. package/dist/core/SearchService.d.ts.map +1 -1
  65. package/dist/core/SearchService.js +133 -325
  66. package/dist/core/SearchService.js.map +1 -1
  67. package/dist/core/batch-indexer.d.ts +5 -0
  68. package/dist/core/batch-indexer.d.ts.map +1 -1
  69. package/dist/core/batch-indexer.js +22 -23
  70. package/dist/core/batch-indexer.js.map +1 -1
  71. package/dist/core/indexer.d.ts +13 -0
  72. package/dist/core/indexer.d.ts.map +1 -1
  73. package/dist/core/indexer.js +13 -0
  74. package/dist/core/indexer.js.map +1 -1
  75. package/dist/core/indexing/FileProcessor.d.ts +42 -0
  76. package/dist/core/indexing/FileProcessor.d.ts.map +1 -0
  77. package/dist/core/indexing/FileProcessor.js +245 -0
  78. package/dist/core/indexing/FileProcessor.js.map +1 -0
  79. package/dist/core/indexing/IndexContext.d.ts +42 -0
  80. package/dist/core/indexing/IndexContext.d.ts.map +1 -0
  81. package/dist/core/indexing/IndexContext.js +133 -0
  82. package/dist/core/indexing/IndexContext.js.map +1 -0
  83. package/dist/core/indexing/IndexFinalizationStage.d.ts +39 -0
  84. package/dist/core/indexing/IndexFinalizationStage.d.ts.map +1 -0
  85. package/dist/core/indexing/IndexFinalizationStage.js +114 -0
  86. package/dist/core/indexing/IndexFinalizationStage.js.map +1 -0
  87. package/dist/core/indexing/IndexState.d.ts +50 -0
  88. package/dist/core/indexing/IndexState.d.ts.map +1 -0
  89. package/dist/core/indexing/IndexState.js +66 -0
  90. package/dist/core/indexing/IndexState.js.map +1 -0
  91. package/dist/core/indexing/chunk-pipeline.d.ts +39 -3
  92. package/dist/core/indexing/chunk-pipeline.d.ts.map +1 -1
  93. package/dist/core/indexing/chunk-pipeline.js +59 -24
  94. package/dist/core/indexing/chunk-pipeline.js.map +1 -1
  95. package/dist/core/metadata.js +2 -2
  96. package/dist/core/metadata.js.map +1 -1
  97. package/dist/core/search/CandidateRetriever.d.ts +51 -0
  98. package/dist/core/search/CandidateRetriever.d.ts.map +1 -0
  99. package/dist/core/search/CandidateRetriever.js +119 -0
  100. package/dist/core/search/CandidateRetriever.js.map +1 -0
  101. package/dist/core/search/HybridFusion.d.ts +89 -0
  102. package/dist/core/search/HybridFusion.d.ts.map +1 -0
  103. package/dist/core/search/HybridFusion.js +263 -0
  104. package/dist/core/search/HybridFusion.js.map +1 -0
  105. package/dist/core/search/ResultMapper.d.ts +31 -0
  106. package/dist/core/search/ResultMapper.d.ts.map +1 -0
  107. package/dist/core/search/ResultMapper.js +131 -0
  108. package/dist/core/search/ResultMapper.js.map +1 -0
  109. package/dist/core/search/SearchContextManager.d.ts +69 -0
  110. package/dist/core/search/SearchContextManager.d.ts.map +1 -0
  111. package/dist/core/search/SearchContextManager.js +139 -0
  112. package/dist/core/search/SearchContextManager.js.map +1 -0
  113. package/dist/core/search.d.ts +31 -0
  114. package/dist/core/search.d.ts.map +1 -1
  115. package/dist/core/search.js +33 -0
  116. package/dist/core/search.js.map +1 -1
  117. package/dist/core/types.d.ts +13 -0
  118. package/dist/core/types.d.ts.map +1 -1
  119. package/dist/database/db.d.ts +36 -18
  120. package/dist/database/db.d.ts.map +1 -1
  121. package/dist/database/db.js +151 -24
  122. package/dist/database/db.js.map +1 -1
  123. package/dist/indexer/ChangeQueue.d.ts +67 -0
  124. package/dist/indexer/ChangeQueue.d.ts.map +1 -0
  125. package/dist/indexer/ChangeQueue.js +182 -0
  126. package/dist/indexer/ChangeQueue.js.map +1 -0
  127. package/dist/indexer/ProviderManager.d.ts +33 -0
  128. package/dist/indexer/ProviderManager.d.ts.map +1 -0
  129. package/dist/indexer/ProviderManager.js +75 -0
  130. package/dist/indexer/ProviderManager.js.map +1 -0
  131. package/dist/indexer/WatchService.d.ts +68 -0
  132. package/dist/indexer/WatchService.d.ts.map +1 -0
  133. package/dist/indexer/WatchService.js +155 -0
  134. package/dist/indexer/WatchService.js.map +1 -0
  135. package/dist/indexer/merkle.d.ts +5 -0
  136. package/dist/indexer/merkle.d.ts.map +1 -1
  137. package/dist/indexer/merkle.js +37 -12
  138. package/dist/indexer/merkle.js.map +1 -1
  139. package/dist/indexer/update.d.ts +14 -2
  140. package/dist/indexer/update.d.ts.map +1 -1
  141. package/dist/indexer/update.js +11 -0
  142. package/dist/indexer/update.js.map +1 -1
  143. package/dist/indexer/watch.d.ts +15 -20
  144. package/dist/indexer/watch.d.ts.map +1 -1
  145. package/dist/indexer/watch.js +14 -223
  146. package/dist/indexer/watch.js.map +1 -1
  147. package/dist/mcp/handlers/project.d.ts.map +1 -1
  148. package/dist/mcp/handlers/project.js +17 -1
  149. package/dist/mcp/handlers/project.js.map +1 -1
  150. package/dist/mcp-server.d.ts +6 -0
  151. package/dist/mcp-server.d.ts.map +1 -1
  152. package/dist/mcp-server.js +67 -8
  153. package/dist/mcp-server.js.map +1 -1
  154. package/dist/providers/base.d.ts +3 -0
  155. package/dist/providers/base.d.ts.map +1 -1
  156. package/dist/providers/base.js.map +1 -1
  157. package/dist/providers/index.d.ts +7 -0
  158. package/dist/providers/index.d.ts.map +1 -1
  159. package/dist/providers/index.js +15 -0
  160. package/dist/providers/index.js.map +1 -1
  161. package/dist/providers/mock.d.ts +16 -0
  162. package/dist/providers/mock.d.ts.map +1 -0
  163. package/dist/providers/mock.js +46 -0
  164. package/dist/providers/mock.js.map +1 -0
  165. package/dist/providers/openai.d.ts.map +1 -1
  166. package/dist/providers/openai.js +4 -8
  167. package/dist/providers/openai.js.map +1 -1
  168. package/dist/ranking/api-reranker.d.ts.map +1 -1
  169. package/dist/ranking/api-reranker.js +9 -5
  170. package/dist/ranking/api-reranker.js.map +1 -1
  171. package/dist/search/bm25.d.ts.map +1 -1
  172. package/dist/search/bm25.js +21 -1
  173. package/dist/search/bm25.js.map +1 -1
  174. package/dist/search/scope.d.ts +1 -1
  175. package/dist/search/scope.d.ts.map +1 -1
  176. package/dist/search/scope.js +3 -3
  177. package/dist/search/scope.js.map +1 -1
  178. package/dist/storage/encrypted-chunks.d.ts +7 -1
  179. package/dist/storage/encrypted-chunks.d.ts.map +1 -1
  180. package/dist/storage/encrypted-chunks.js +187 -75
  181. package/dist/storage/encrypted-chunks.js.map +1 -1
  182. package/dist/symbols/extract.d.ts +2 -1
  183. package/dist/symbols/extract.d.ts.map +1 -1
  184. package/dist/symbols/extract.js +3 -3
  185. package/dist/symbols/extract.js.map +1 -1
  186. package/dist/symbols/graph.d.ts.map +1 -1
  187. package/dist/symbols/graph.js.map +1 -1
  188. package/dist/synthesis/conversational-synthesizer.d.ts.map +1 -1
  189. package/dist/synthesis/conversational-synthesizer.js +68 -76
  190. package/dist/synthesis/conversational-synthesizer.js.map +1 -1
  191. package/dist/synthesis/prompt-builder.d.ts +2 -0
  192. package/dist/synthesis/prompt-builder.d.ts.map +1 -1
  193. package/dist/synthesis/prompt-builder.js +81 -81
  194. package/dist/synthesis/prompt-builder.js.map +1 -1
  195. package/dist/synthesis/synthesizer.d.ts +11 -0
  196. package/dist/synthesis/synthesizer.d.ts.map +1 -1
  197. package/dist/synthesis/synthesizer.js +30 -2
  198. package/dist/synthesis/synthesizer.js.map +1 -1
  199. package/dist/tests/helpers/test-repo.d.ts +7 -0
  200. package/dist/tests/helpers/test-repo.d.ts.map +1 -0
  201. package/dist/tests/helpers/test-repo.js +21 -0
  202. package/dist/tests/helpers/test-repo.js.map +1 -0
  203. package/dist/tests/integration/index-search.integration.test.d.ts +2 -0
  204. package/dist/tests/integration/index-search.integration.test.d.ts.map +1 -0
  205. package/dist/tests/integration/index-search.integration.test.js +163 -0
  206. package/dist/tests/integration/index-search.integration.test.js.map +1 -0
  207. package/dist/tests/simple-lru.test.js +22 -10
  208. package/dist/tests/simple-lru.test.js.map +1 -1
  209. package/dist/utils/cli-ui.d.ts.map +1 -1
  210. package/dist/utils/cli-ui.js +10 -4
  211. package/dist/utils/cli-ui.js.map +1 -1
  212. package/dist/utils/logger.d.ts +6 -3
  213. package/dist/utils/logger.d.ts.map +1 -1
  214. package/dist/utils/logger.js.map +1 -1
  215. package/dist/utils/path-helpers.d.ts.map +1 -1
  216. package/dist/utils/path-helpers.js +17 -1
  217. package/dist/utils/path-helpers.js.map +1 -1
  218. package/dist/utils/rate-limiter.js +2 -2
  219. package/dist/utils/rate-limiter.js.map +1 -1
  220. package/dist/utils/scan-patterns.d.ts.map +1 -1
  221. package/dist/utils/scan-patterns.js +1 -2
  222. package/dist/utils/scan-patterns.js.map +1 -1
  223. package/dist/utils/simple-lru.d.ts +21 -2
  224. package/dist/utils/simple-lru.d.ts.map +1 -1
  225. package/dist/utils/simple-lru.js +126 -19
  226. package/dist/utils/simple-lru.js.map +1 -1
  227. package/package.json +13 -4
@@ -0,0 +1,119 @@
1
+ import { decodeEmbedding } from '../../database/db.js';
2
+ import { DOC_BOOST, DOC_BOOST_CONSTANTS } from '../../config/constants.js';
3
+ import { logger } from '../../utils/logger.js';
4
+ /**
5
+ * CandidateRetriever handles:
6
+ * - Vector similarity computation
7
+ * - Tag/intent/doc boosting
8
+ * - Building ranked candidate pools
9
+ */
10
+ export class CandidateRetriever {
11
+ /**
12
+ * Build a pool of search candidates from chunks using vector similarity
13
+ */
14
+ async buildVectorPool(chunks, provider, query) {
15
+ const chunkInfoById = new Map();
16
+ const results = [];
17
+ // Generate query embedding
18
+ let queryEmbedding = null;
19
+ if (chunks.length > 0) {
20
+ queryEmbedding = await provider.generateEmbedding(query);
21
+ }
22
+ // Score each chunk
23
+ for (const chunk of chunks) {
24
+ const embedding = this.decodeEmbedding(chunk);
25
+ const vectorSimilarity = queryEmbedding
26
+ ? this.cosineSimilarity(queryEmbedding, embedding)
27
+ : 0;
28
+ // Calculate boost scores
29
+ let boostScore = 0;
30
+ // Intent boost
31
+ if (chunk.codevault_intent && query.includes(chunk.codevault_intent.toLowerCase())) {
32
+ boostScore += DOC_BOOST_CONSTANTS.INTENT_MATCH_BOOST;
33
+ }
34
+ // Tag boost
35
+ if (chunk.codevault_tags) {
36
+ try {
37
+ const tags = JSON.parse(chunk.codevault_tags || '[]');
38
+ tags.forEach((tag) => {
39
+ if (typeof tag === 'string' && query.includes(tag.toLowerCase())) {
40
+ boostScore += DOC_BOOST_CONSTANTS.TAG_MATCH_BOOST;
41
+ }
42
+ });
43
+ }
44
+ catch (error) {
45
+ logger.warn('Failed to parse codevault_tags for chunk', {
46
+ chunkId: chunk.id,
47
+ error: error instanceof Error ? error.message : String(error)
48
+ });
49
+ }
50
+ }
51
+ // Documentation file boost
52
+ let docBoost = 0;
53
+ const filePath = chunk.file_path.toLowerCase();
54
+ if (filePath.includes('readme') ||
55
+ filePath.includes('/docs/') ||
56
+ filePath.startsWith('docs/') ||
57
+ filePath.includes('changelog') ||
58
+ filePath.includes('contributing') ||
59
+ filePath.endsWith('.md')) {
60
+ docBoost = DOC_BOOST;
61
+ }
62
+ // Final score (capped at 1.0)
63
+ const finalScore = Math.min(1, Math.max(0, vectorSimilarity + boostScore + docBoost));
64
+ const candidate = {
65
+ id: chunk.id,
66
+ file_path: chunk.file_path,
67
+ symbol: chunk.symbol,
68
+ sha: chunk.sha,
69
+ lang: chunk.lang,
70
+ chunk_type: chunk.chunk_type,
71
+ codevault_intent: chunk.codevault_intent,
72
+ codevault_description: chunk.codevault_description,
73
+ score: finalScore,
74
+ vectorScore: vectorSimilarity,
75
+ boostScore: boostScore
76
+ };
77
+ chunkInfoById.set(chunk.id, candidate);
78
+ results.push(candidate);
79
+ }
80
+ // Sort by score (highest first)
81
+ results.sort((a, b) => b.score - a.score);
82
+ return { chunkInfoById, vectorPool: results };
83
+ }
84
+ /**
85
+ * Cosine similarity between two vectors
86
+ */
87
+ cosineSimilarity(a, b) {
88
+ if (a.length !== b.length)
89
+ return 0;
90
+ let dotProduct = 0;
91
+ let normA = 0;
92
+ let normB = 0;
93
+ for (let i = 0; i < a.length; i++) {
94
+ dotProduct += a[i] * b[i];
95
+ normA += a[i] * a[i];
96
+ normB += b[i] * b[i];
97
+ }
98
+ if (normA === 0 || normB === 0) {
99
+ return 0;
100
+ }
101
+ return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
102
+ }
103
+ /**
104
+ * Decode and cache embedding to avoid repeated JSON parsing
105
+ */
106
+ decodeEmbedding(chunk) {
107
+ const cached = chunk.__cachedEmbedding;
108
+ if (cached) {
109
+ return cached;
110
+ }
111
+ const vector = decodeEmbedding(chunk.embedding, chunk.embedding_dimensions || undefined);
112
+ if (vector.length === 0 && chunk.embedding && chunk.embedding.length > 0) {
113
+ logger.warn('Embedding decoded to empty vector', { chunkId: chunk.id });
114
+ }
115
+ chunk.__cachedEmbedding = vector;
116
+ return vector;
117
+ }
118
+ }
119
+ //# sourceMappingURL=CandidateRetriever.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CandidateRetriever.js","sourceRoot":"","sources":["../../../src/core/search/CandidateRetriever.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAsB,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AA4B/C;;;;;GAKG;AACH,MAAM,OAAO,kBAAkB;IAC7B;;OAEG;IACH,KAAK,CAAC,eAAe,CACnB,MAAuB,EACvB,QAA2B,EAC3B,KAAa;QAEb,MAAM,aAAa,GAAG,IAAI,GAAG,EAA2B,CAAC;QACzD,MAAM,OAAO,GAAsB,EAAE,CAAC;QAEtC,2BAA2B;QAC3B,IAAI,cAAc,GAA6B,IAAI,CAAC;QACpD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,cAAc,GAAG,MAAM,QAAQ,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAC3D,CAAC;QAED,mBAAmB;QACnB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YAC9C,MAAM,gBAAgB,GAAG,cAAc;gBACrC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,cAAc,EAAE,SAAS,CAAC;gBAClD,CAAC,CAAC,CAAC,CAAC;YAEN,yBAAyB;YACzB,IAAI,UAAU,GAAG,CAAC,CAAC;YAEnB,eAAe;YACf,IAAI,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBACnF,UAAU,IAAI,mBAAmB,CAAC,kBAAkB,CAAC;YACvD,CAAC;YAED,YAAY;YACZ,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;gBACzB,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,IAAI,IAAI,CAAC,CAAC;oBACtD,IAAI,CAAC,OAAO,CAAC,CAAC,GAAW,EAAE,EAAE;wBAC3B,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;4BACjE,UAAU,IAAI,mBAAmB,CAAC,eAAe,CAAC;wBACpD,CAAC;oBACH,CAAC,CAAC,CAAC;gBACL,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,IAAI,CAAC,0CAA0C,EAAE;wBACtD,OAAO,EAAE,KAAK,CAAC,EAAE;wBACjB,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;qBAC9D,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,2BAA2B;YAC3B,IAAI,QAAQ,GAAG,CAAC,CAAC;YACjB,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;YAC/C,IACE,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAC3B,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAC3B,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;gBAC5B,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAC9B,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC;gBACjC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EACxB,CAAC;gBACD,QAAQ,GAAG,SAAS,CAAC;YACvB,CAAC;YAED,8BAA8B;YAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,gBAAgB,GAAG,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC;YAEtF,MAAM,SAAS,GAAoB;gBACjC,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;gBACxC,qBAAqB,EAAE,KAAK,CAAC,qBAAqB;gBAClD,KAAK,EAAE,UAAU;gBACjB,WAAW,EAAE,gBAAgB;gBAC7B,UAAU,EAAE,UAAU;aACvB,CAAC;YAEF,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;YACvC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1B,CAAC;QAED,gCAAgC;QAChC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QAE1C,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;IAChD,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,CAAoB,EAAE,CAAoB;QACjE,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;YAAE,OAAO,CAAC,CAAC;QAEpC,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,KAAK,GAAG,CAAC,CAAC;QAEd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAClC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1B,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACrB,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC;QAED,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,CAAC;QACX,CAAC;QAED,OAAO,UAAU,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,KAAoB;QAC1C,MAAM,MAAM,GAAI,KAAa,CAAC,iBAA6C,CAAC;QAC5E,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,MAAM,GAAG,eAAe,CAC5B,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,oBAAoB,IAAI,SAAS,CACxC,CAAC;QACF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzE,MAAM,CAAC,IAAI,CAAC,mCAAmC,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1E,CAAC;QACA,KAAa,CAAC,iBAAiB,GAAG,MAAM,CAAC;QAC1C,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
@@ -0,0 +1,89 @@
1
+ import type { DatabaseChunk } from '../../database/db.js';
2
+ import type { SearchCandidate } from './CandidateRetriever.js';
3
+ /**
4
+ * HybridFusion handles:
5
+ * - BM25 index management with caching
6
+ * - Reciprocal Rank Fusion of vector + BM25 results
7
+ * - Symbol boosting
8
+ * - Result sorting
9
+ */
10
+ export declare class HybridFusion {
11
+ private bm25Cache;
12
+ private chunkCache;
13
+ private chunkLoadingStats;
14
+ constructor();
15
+ /**
16
+ * Use BM25 to prefilter candidates before vector scoring
17
+ */
18
+ prefilterCandidates(params: {
19
+ hybridEnabled: boolean;
20
+ bm25Enabled: boolean;
21
+ query: string;
22
+ providerName: string;
23
+ providerDimensions: number;
24
+ chunkDir: string;
25
+ basePath: string;
26
+ scopedChunks: DatabaseChunk[];
27
+ limit: number;
28
+ }): {
29
+ candidateIds: Set<string>;
30
+ bm25Results: Array<{
31
+ id: string;
32
+ score: number;
33
+ }>;
34
+ };
35
+ /**
36
+ * Attempt hybrid fusion of vector and BM25 results
37
+ */
38
+ fuseResults(params: {
39
+ hybridEnabled: boolean;
40
+ bm25Enabled: boolean;
41
+ selectionBudget: number;
42
+ query: string;
43
+ providerName: string;
44
+ providerDimensions: number;
45
+ chunkDir: string;
46
+ basePath: string;
47
+ scopedChunks: DatabaseChunk[];
48
+ chunkInfoById: Map<string, SearchCandidate>;
49
+ vectorPool: SearchCandidate[];
50
+ bm25ResultsOverride?: Array<{
51
+ id: string;
52
+ score: number;
53
+ }>;
54
+ }): {
55
+ fusedResults: SearchCandidate[];
56
+ bm25Fused: boolean;
57
+ bm25CandidateCount: number;
58
+ };
59
+ /**
60
+ * Sort results with symbol boost priority
61
+ */
62
+ sortWithSymbolBoost(results: SearchCandidate[], symbolBoostEnabled: boolean): SearchCandidate[];
63
+ /**
64
+ * Clear caches
65
+ */
66
+ clearCaches(): void;
67
+ /**
68
+ * Get chunk loading failure statistics
69
+ */
70
+ getChunkLoadingFailures(): {
71
+ totalAttempted: number;
72
+ failed: number;
73
+ reasons: any;
74
+ } | undefined;
75
+ /**
76
+ * Build warning messages from chunk loading failures
77
+ */
78
+ buildWarnings(): string[] | undefined;
79
+ /**
80
+ * Reset chunk loading statistics
81
+ */
82
+ resetChunkLoadingStats(): void;
83
+ private ensureBm25IndexForChunks;
84
+ private readChunkTextCached;
85
+ private buildBm25Document;
86
+ private getBm25CacheKey;
87
+ private getChunkCacheKey;
88
+ }
89
+ //# sourceMappingURL=HybridFusion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HybridFusion.d.ts","sourceRoot":"","sources":["../../../src/core/search/HybridFusion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAiB/D;;;;;;GAMG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,SAAS,CAA8D;IAC/E,OAAO,CAAC,UAAU,CAAmC;IACrD,OAAO,CAAC,iBAAiB,CAIvB;;IAQF;;OAEG;IACH,mBAAmB,CAAC,MAAM,EAAE;QAC1B,aAAa,EAAE,OAAO,CAAC;QACvB,WAAW,EAAE,OAAO,CAAC;QACrB,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,MAAM,CAAC;QACrB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,aAAa,EAAE,CAAC;QAC9B,KAAK,EAAE,MAAM,CAAC;KACf,GAAG;QAAE,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAAC,WAAW,EAAE,KAAK,CAAC;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE;IAqCpF;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE;QAClB,aAAa,EAAE,OAAO,CAAC;QACvB,WAAW,EAAE,OAAO,CAAC;QACrB,eAAe,EAAE,MAAM,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,MAAM,CAAC;QACrB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,aAAa,EAAE,CAAC;QAC9B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QAC5C,UAAU,EAAE,eAAe,EAAE,CAAC;QAC9B,mBAAmB,CAAC,EAAE,KAAK,CAAC;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC5D,GAAG;QACF,YAAY,EAAE,eAAe,EAAE,CAAC;QAChC,SAAS,EAAE,OAAO,CAAC;QACnB,kBAAkB,EAAE,MAAM,CAAC;KAC5B;IA0ED;;OAEG;IACH,mBAAmB,CACjB,OAAO,EAAE,eAAe,EAAE,EAC1B,kBAAkB,EAAE,OAAO,GAC1B,eAAe,EAAE;IAiCpB;;OAEG;IACH,WAAW,IAAI,IAAI;IAMnB;;OAEG;IACH,uBAAuB;;;;;IAiBvB;;OAEG;IACH,aAAa,IAAI,MAAM,EAAE,GAAG,SAAS;IA4CrC;;OAEG;IACH,sBAAsB,IAAI,IAAI;IAU9B,OAAO,CAAC,wBAAwB;IAoChC,OAAO,CAAC,mBAAmB;IA8C3B,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,gBAAgB;CAGzB"}
@@ -0,0 +1,263 @@
1
+ import { BM25Index } from '../../search/bm25.js';
2
+ import { reciprocalRankFusion } from '../../search/hybrid.js';
3
+ import { SimpleLRU } from '../../utils/simple-lru.js';
4
+ import { readChunkFromDisk } from '../../storage/encrypted-chunks.js';
5
+ import { RRF_K, CACHE_CONSTANTS } from '../../config/constants.js';
6
+ import { logger } from '../../utils/logger.js';
7
+ /**
8
+ * HybridFusion handles:
9
+ * - BM25 index management with caching
10
+ * - Reciprocal Rank Fusion of vector + BM25 results
11
+ * - Symbol boosting
12
+ * - Result sorting
13
+ */
14
+ export class HybridFusion {
15
+ bm25Cache;
16
+ chunkCache;
17
+ chunkLoadingStats = {
18
+ totalAttempted: 0,
19
+ failed: 0,
20
+ reasons: new Map()
21
+ };
22
+ constructor() {
23
+ this.bm25Cache = new SimpleLRU(CACHE_CONSTANTS.MAX_BM25_CACHE_SIZE);
24
+ this.chunkCache = new SimpleLRU(CACHE_CONSTANTS.MAX_CHUNK_TEXT_CACHE_SIZE);
25
+ this.resetChunkLoadingStats();
26
+ }
27
+ /**
28
+ * Use BM25 to prefilter candidates before vector scoring
29
+ */
30
+ prefilterCandidates(params) {
31
+ const { hybridEnabled, bm25Enabled, query, providerName, providerDimensions, chunkDir, basePath, scopedChunks, limit } = params;
32
+ if (!hybridEnabled || !bm25Enabled) {
33
+ return { candidateIds: new Set(), bm25Results: [] };
34
+ }
35
+ const bm25Index = this.ensureBm25IndexForChunks(basePath, chunkDir, providerName, providerDimensions, scopedChunks);
36
+ if (!bm25Index) {
37
+ return { candidateIds: new Set(), bm25Results: [] };
38
+ }
39
+ const allowedIds = new Set(scopedChunks.map(chunk => chunk.id));
40
+ const bm25RawResults = bm25Index.search(query, limit);
41
+ const bm25Results = bm25RawResults.filter(result => allowedIds.has(result.id));
42
+ const candidateIds = new Set(bm25Results.map(result => result.id));
43
+ return { candidateIds, bm25Results };
44
+ }
45
+ /**
46
+ * Attempt hybrid fusion of vector and BM25 results
47
+ */
48
+ fuseResults(params) {
49
+ const { hybridEnabled, bm25Enabled, selectionBudget, query, providerName, providerDimensions, chunkDir, basePath, scopedChunks, chunkInfoById, vectorPool, bm25ResultsOverride } = params;
50
+ let fusedResults = [];
51
+ let bm25Fused = false;
52
+ let bm25CandidateCount = 0;
53
+ if (hybridEnabled && bm25Enabled) {
54
+ const bm25Index = this.ensureBm25IndexForChunks(basePath, chunkDir, providerName, providerDimensions, scopedChunks);
55
+ if (bm25Index) {
56
+ const allowedIds = new Set(scopedChunks.map(chunk => chunk.id));
57
+ const bm25RawResults = bm25ResultsOverride && bm25ResultsOverride.length > 0
58
+ ? bm25ResultsOverride
59
+ : bm25Index.search(query, selectionBudget);
60
+ const bm25Results = bm25RawResults.filter(result => allowedIds.has(result.id));
61
+ bm25CandidateCount = bm25Results.length;
62
+ const bm25ResultsForFusion = bm25Results.slice(0, selectionBudget);
63
+ if (bm25ResultsForFusion.length > 0) {
64
+ const fused = reciprocalRankFusion({
65
+ vectorResults: vectorPool
66
+ .slice(0, selectionBudget)
67
+ .map(item => ({ id: item.id, score: item.score })),
68
+ bm25Results: bm25ResultsForFusion.map(item => ({
69
+ id: item.id,
70
+ score: item.score
71
+ })),
72
+ limit: selectionBudget,
73
+ k: RRF_K
74
+ });
75
+ if (fused.length > 0) {
76
+ bm25Fused = true;
77
+ fusedResults = fused
78
+ .map(entry => {
79
+ const info = chunkInfoById.get(entry.id);
80
+ if (!info)
81
+ return null;
82
+ info.hybridScore = entry.score;
83
+ info.bm25Score = entry.bm25Score;
84
+ info.bm25Rank = entry.bm25Rank;
85
+ info.vectorRank = entry.vectorRank;
86
+ return info;
87
+ })
88
+ .filter((item) => item !== null);
89
+ }
90
+ }
91
+ }
92
+ }
93
+ return { fusedResults, bm25Fused, bm25CandidateCount };
94
+ }
95
+ /**
96
+ * Sort results with symbol boost priority
97
+ */
98
+ sortWithSymbolBoost(results, symbolBoostEnabled) {
99
+ const hasSymbolBoost = symbolBoostEnabled &&
100
+ results.some(candidate => typeof candidate.symbolBoost === 'number' && candidate.symbolBoost > 0);
101
+ if (hasSymbolBoost && results.length > 1) {
102
+ return [...results].sort((a, b) => {
103
+ const scoreA = typeof a.score === 'number' ? a.score : 0;
104
+ const scoreB = typeof b.score === 'number' ? b.score : 0;
105
+ if (scoreB !== scoreA)
106
+ return scoreB - scoreA;
107
+ const boostA = typeof a.symbolBoost === 'number' ? a.symbolBoost : 0;
108
+ const boostB = typeof b.symbolBoost === 'number' ? b.symbolBoost : 0;
109
+ if (boostB !== boostA)
110
+ return boostB - boostA;
111
+ const hybridA = typeof a.hybridScore === 'number'
112
+ ? a.hybridScore
113
+ : Number.NEGATIVE_INFINITY;
114
+ const hybridB = typeof b.hybridScore === 'number'
115
+ ? b.hybridScore
116
+ : Number.NEGATIVE_INFINITY;
117
+ return hybridB - hybridA;
118
+ });
119
+ }
120
+ return results;
121
+ }
122
+ /**
123
+ * Clear caches
124
+ */
125
+ clearCaches() {
126
+ logger.debug('Clearing hybrid fusion caches');
127
+ this.bm25Cache.clear();
128
+ this.chunkCache.clear();
129
+ }
130
+ /**
131
+ * Get chunk loading failure statistics
132
+ */
133
+ getChunkLoadingFailures() {
134
+ if (this.chunkLoadingStats.failed === 0) {
135
+ return undefined;
136
+ }
137
+ const reasons = {};
138
+ for (const [reason, count] of this.chunkLoadingStats.reasons.entries()) {
139
+ reasons[reason] = count;
140
+ }
141
+ return {
142
+ totalAttempted: this.chunkLoadingStats.totalAttempted,
143
+ failed: this.chunkLoadingStats.failed,
144
+ reasons
145
+ };
146
+ }
147
+ /**
148
+ * Build warning messages from chunk loading failures
149
+ */
150
+ buildWarnings() {
151
+ if (this.chunkLoadingStats.failed === 0) {
152
+ return undefined;
153
+ }
154
+ const warnings = [];
155
+ const stats = this.chunkLoadingStats;
156
+ if (stats.reasons.has('encryption_key_required')) {
157
+ const count = stats.reasons.get('encryption_key_required');
158
+ warnings.push(`Could not load ${count} encrypted chunk(s). Set CODEVAULT_ENCRYPTION_KEY environment variable to access encrypted chunks.`);
159
+ }
160
+ if (stats.reasons.has('encryption_auth_failed')) {
161
+ const count = stats.reasons.get('encryption_auth_failed');
162
+ warnings.push(`Failed to decrypt ${count} chunk(s). The encryption key may be incorrect.`);
163
+ }
164
+ if (stats.reasons.has('file_not_found')) {
165
+ const count = stats.reasons.get('file_not_found');
166
+ warnings.push(`${count} chunk file(s) not found. The index may be out of sync. Try re-indexing.`);
167
+ }
168
+ const otherFailures = stats.failed -
169
+ (stats.reasons.get('encryption_key_required') || 0) -
170
+ (stats.reasons.get('encryption_auth_failed') || 0) -
171
+ (stats.reasons.get('file_not_found') || 0);
172
+ if (otherFailures > 0) {
173
+ warnings.push(`${otherFailures} chunk(s) failed to load due to other errors. Check logs for details.`);
174
+ }
175
+ return warnings.length > 0 ? warnings : undefined;
176
+ }
177
+ /**
178
+ * Reset chunk loading statistics
179
+ */
180
+ resetChunkLoadingStats() {
181
+ this.chunkLoadingStats = {
182
+ totalAttempted: 0,
183
+ failed: 0,
184
+ reasons: new Map()
185
+ };
186
+ }
187
+ // Private helpers
188
+ ensureBm25IndexForChunks(basePath, chunkDir, providerName, dimensions, chunks) {
189
+ if (!Array.isArray(chunks) || chunks.length === 0)
190
+ return null;
191
+ const key = this.getBm25CacheKey(basePath, providerName, dimensions);
192
+ let entry = this.bm25Cache.get(key);
193
+ if (!entry) {
194
+ entry = { index: new BM25Index(), added: new Set() };
195
+ this.bm25Cache.set(key, entry);
196
+ }
197
+ const toAdd = [];
198
+ for (const chunk of chunks) {
199
+ if (!chunk || !chunk.id || entry.added.has(chunk.id))
200
+ continue;
201
+ const codeText = this.readChunkTextCached(chunk.sha, chunkDir, basePath);
202
+ const docText = this.buildBm25Document(chunk, codeText);
203
+ if (docText && docText.trim().length > 0) {
204
+ toAdd.push({ id: chunk.id, text: docText });
205
+ }
206
+ entry.added.add(chunk.id);
207
+ }
208
+ if (toAdd.length > 0)
209
+ entry.index.addDocuments(toAdd);
210
+ entry.index.consolidate();
211
+ return entry.index;
212
+ }
213
+ readChunkTextCached(sha, chunkDir, basePath) {
214
+ if (!sha)
215
+ return null;
216
+ const cacheKey = this.getChunkCacheKey(basePath, sha);
217
+ const cached = this.chunkCache.get(cacheKey);
218
+ if (cached !== undefined)
219
+ return cached;
220
+ this.chunkLoadingStats.totalAttempted++;
221
+ try {
222
+ const result = readChunkFromDisk({ chunkDir, sha });
223
+ const code = result ? result.code : null;
224
+ this.chunkCache.set(cacheKey, code);
225
+ if (!result) {
226
+ this.chunkLoadingStats.failed++;
227
+ const reason = 'file_not_found';
228
+ this.chunkLoadingStats.reasons.set(reason, (this.chunkLoadingStats.reasons.get(reason) || 0) + 1);
229
+ }
230
+ return code;
231
+ }
232
+ catch (error) {
233
+ this.chunkLoadingStats.failed++;
234
+ const reason = error.code ? String(error.code).toLowerCase() : 'unknown_error';
235
+ this.chunkLoadingStats.reasons.set(reason, (this.chunkLoadingStats.reasons.get(reason) || 0) + 1);
236
+ logger.warn(`Failed to load chunk ${sha}`, {
237
+ error: error.message,
238
+ code: error.code
239
+ });
240
+ this.chunkCache.set(cacheKey, null);
241
+ return null;
242
+ }
243
+ }
244
+ buildBm25Document(chunk, codeText) {
245
+ if (!chunk)
246
+ return '';
247
+ const parts = [
248
+ chunk.symbol,
249
+ chunk.file_path,
250
+ chunk.codevault_description,
251
+ chunk.codevault_intent,
252
+ codeText
253
+ ].filter(value => typeof value === 'string' && value.trim().length > 0);
254
+ return parts.join('\n');
255
+ }
256
+ getBm25CacheKey(basePath, providerName, dimensions) {
257
+ return `${basePath}::${providerName}::${dimensions}`;
258
+ }
259
+ getChunkCacheKey(basePath, sha) {
260
+ return `${basePath}::${sha}`;
261
+ }
262
+ }
263
+ //# sourceMappingURL=HybridFusion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HybridFusion.js","sourceRoot":"","sources":["../../../src/core/search/HybridFusion.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAW/C;;;;;;GAMG;AACH,MAAM,OAAO,YAAY;IACf,SAAS,CAA8D;IACvE,UAAU,CAAmC;IAC7C,iBAAiB,GAAsB;QAC7C,cAAc,EAAE,CAAC;QACjB,MAAM,EAAE,CAAC;QACT,OAAO,EAAE,IAAI,GAAG,EAAE;KACnB,CAAC;IAEF;QACE,IAAI,CAAC,SAAS,GAAG,IAAI,SAAS,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC;QACpE,IAAI,CAAC,UAAU,GAAG,IAAI,SAAS,CAAC,eAAe,CAAC,yBAAyB,CAAC,CAAC;QAC3E,IAAI,CAAC,sBAAsB,EAAE,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,MAUnB;QACC,MAAM,EACJ,aAAa,EACb,WAAW,EACX,KAAK,EACL,YAAY,EACZ,kBAAkB,EAClB,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,KAAK,EACN,GAAG,MAAM,CAAC;QAEX,IAAI,CAAC,aAAa,IAAI,CAAC,WAAW,EAAE,CAAC;YACnC,OAAO,EAAE,YAAY,EAAE,IAAI,GAAG,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;QACtD,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,wBAAwB,CAC7C,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,kBAAkB,EAClB,YAAY,CACb,CAAC;QAEF,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,EAAE,YAAY,EAAE,IAAI,GAAG,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;QACtD,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAChE,MAAM,cAAc,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACtD,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/E,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAEnE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,MAaX;QAKC,MAAM,EACJ,aAAa,EACb,WAAW,EACX,eAAe,EACf,KAAK,EACL,YAAY,EACZ,kBAAkB,EAClB,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,UAAU,EACV,mBAAmB,EACpB,GAAG,MAAM,CAAC;QAEX,IAAI,YAAY,GAAsB,EAAE,CAAC;QACzC,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAI,kBAAkB,GAAG,CAAC,CAAC;QAE3B,IAAI,aAAa,IAAI,WAAW,EAAE,CAAC;YACjC,MAAM,SAAS,GAAG,IAAI,CAAC,wBAAwB,CAC7C,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,kBAAkB,EAClB,YAAY,CACb,CAAC;YAEF,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;gBAChE,MAAM,cAAc,GAClB,mBAAmB,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC;oBACnD,CAAC,CAAC,mBAAmB;oBACrB,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;gBAE/C,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC/E,kBAAkB,GAAG,WAAW,CAAC,MAAM,CAAC;gBACxC,MAAM,oBAAoB,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC;gBAEnE,IAAI,oBAAoB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACpC,MAAM,KAAK,GAAG,oBAAoB,CAAC;wBACjC,aAAa,EAAE,UAAU;6BACtB,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC;6BACzB,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;wBACpD,WAAW,EAAE,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;4BAC7C,EAAE,EAAE,IAAI,CAAC,EAAE;4BACX,KAAK,EAAE,IAAI,CAAC,KAAK;yBAClB,CAAC,CAAC;wBACH,KAAK,EAAE,eAAe;wBACtB,CAAC,EAAE,KAAK;qBACT,CAAC,CAAC;oBAEH,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACrB,SAAS,GAAG,IAAI,CAAC;wBACjB,YAAY,GAAG,KAAK;6BACjB,GAAG,CAAC,KAAK,CAAC,EAAE;4BACX,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;4BACzC,IAAI,CAAC,IAAI;gCAAE,OAAO,IAAI,CAAC;4BACvB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC;4BAC/B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;4BACjC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;4BAC/B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;4BACnC,OAAO,IAAI,CAAC;wBACd,CAAC,CAAC;6BACD,MAAM,CAAC,CAAC,IAAI,EAA2B,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;oBAC9D,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;IACzD,CAAC;IAED;;OAEG;IACH,mBAAmB,CACjB,OAA0B,EAC1B,kBAA2B;QAE3B,MAAM,cAAc,GAClB,kBAAkB;YAClB,OAAO,CAAC,IAAI,CACV,SAAS,CAAC,EAAE,CACV,OAAO,SAAS,CAAC,WAAW,KAAK,QAAQ,IAAI,SAAS,CAAC,WAAW,GAAG,CAAC,CACzE,CAAC;QAEJ,IAAI,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBAChC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBACzD,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBACzD,IAAI,MAAM,KAAK,MAAM;oBAAE,OAAO,MAAM,GAAG,MAAM,CAAC;gBAE9C,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;gBACrE,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;gBACrE,IAAI,MAAM,KAAK,MAAM;oBAAE,OAAO,MAAM,GAAG,MAAM,CAAC;gBAE9C,MAAM,OAAO,GACX,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ;oBAC/B,CAAC,CAAC,CAAC,CAAC,WAAW;oBACf,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;gBAC/B,MAAM,OAAO,GACX,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ;oBAC/B,CAAC,CAAC,CAAC,CAAC,WAAW;oBACf,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;gBAC/B,OAAO,OAAO,GAAG,OAAO,CAAC;YAC3B,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,WAAW;QACT,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC9C,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,uBAAuB;QACrB,IAAI,IAAI,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,OAAO,GAAQ,EAAE,CAAC;QACxB,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YACvE,OAAO,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;QAC1B,CAAC;QAED,OAAO;YACL,cAAc,EAAE,IAAI,CAAC,iBAAiB,CAAC,cAAc;YACrD,MAAM,EAAE,IAAI,CAAC,iBAAiB,CAAC,MAAM;YACrC,OAAO;SACR,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,aAAa;QACX,IAAI,IAAI,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC;QAErC,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;YAC3D,QAAQ,CAAC,IAAI,CACX,kBAAkB,KAAK,oGAAoG,CAC5H,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,EAAE,CAAC;YAChD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;YAC1D,QAAQ,CAAC,IAAI,CACX,qBAAqB,KAAK,iDAAiD,CAC5E,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACxC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAClD,QAAQ,CAAC,IAAI,CACX,GAAG,KAAK,0EAA0E,CACnF,CAAC;QACJ,CAAC;QAED,MAAM,aAAa,GACjB,KAAK,CAAC,MAAM;YACZ,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC;YACnD,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC;YAClD,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;QAE7C,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;YACtB,QAAQ,CAAC,IAAI,CACX,GAAG,aAAa,uEAAuE,CACxF,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IACpD,CAAC;IAED;;OAEG;IACH,sBAAsB;QACpB,IAAI,CAAC,iBAAiB,GAAG;YACvB,cAAc,EAAE,CAAC;YACjB,MAAM,EAAE,CAAC;YACT,OAAO,EAAE,IAAI,GAAG,EAAE;SACnB,CAAC;IACJ,CAAC;IAED,kBAAkB;IAEV,wBAAwB,CAC9B,QAAgB,EAChB,QAAgB,EAChB,YAAoB,EACpB,UAAkB,EAClB,MAAuB;QAEvB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAE/D,MAAM,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;QACrE,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEpC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,EAAE,KAAK,EAAE,IAAI,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;YACrD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC;QAED,MAAM,KAAK,GAAwC,EAAE,CAAC;QACtD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBAAE,SAAS;YAE/D,MAAM,QAAQ,GAAG,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACzE,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAExD,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAC9C,CAAC;YACD,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5B,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACtD,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QAE1B,OAAO,KAAK,CAAC,KAAK,CAAC;IACrB,CAAC;IAEO,mBAAmB,CACzB,GAAW,EACX,QAAgB,EAChB,QAAgB;QAEhB,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QAEtB,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC;QAExC,IAAI,CAAC,iBAAiB,CAAC,cAAc,EAAE,CAAC;QAExC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,iBAAiB,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;YACpD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YACzC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAEpC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,CAAC;gBAChC,MAAM,MAAM,GAAG,gBAAgB,CAAC;gBAChC,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAChC,MAAM,EACN,CAAC,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CACtD,CAAC;YACJ,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC;YAC/E,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAChC,MAAM,EACN,CAAC,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CACtD,CAAC;YAEF,MAAM,CAAC,IAAI,CAAC,wBAAwB,GAAG,EAAE,EAAE;gBACzC,KAAK,EAAE,KAAK,CAAC,OAAO;gBACpB,IAAI,EAAE,KAAK,CAAC,IAAI;aACjB,CAAC,CAAC;YAEH,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACpC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAEO,iBAAiB,CAAC,KAAU,EAAE,QAAuB;QAC3D,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,CAAC;QAEtB,MAAM,KAAK,GAAG;YACZ,KAAK,CAAC,MAAM;YACZ,KAAK,CAAC,SAAS;YACf,KAAK,CAAC,qBAAqB;YAC3B,KAAK,CAAC,gBAAgB;YACtB,QAAQ;SACT,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAExE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAEO,eAAe,CACrB,QAAgB,EAChB,YAAoB,EACpB,UAAkB;QAElB,OAAO,GAAG,QAAQ,KAAK,YAAY,KAAK,UAAU,EAAE,CAAC;IACvD,CAAC;IAEO,gBAAgB,CAAC,QAAgB,EAAE,GAAW;QACpD,OAAO,GAAG,QAAQ,KAAK,GAAG,EAAE,CAAC;IAC/B,CAAC;CACF"}
@@ -0,0 +1,31 @@
1
+ import type { SearchCandidate } from './CandidateRetriever.js';
2
+ import type { SearchResult } from '../types.js';
3
+ import { resolveProviderContext } from '../../config/resolver.js';
4
+ /**
5
+ * ResultMapper handles:
6
+ * - API reranking of results
7
+ * - Mapping candidates to search results
8
+ * - Building result metadata
9
+ * - Score normalization
10
+ */
11
+ export declare class ResultMapper {
12
+ /**
13
+ * Map search candidates to formatted search results
14
+ */
15
+ mapResults(candidates: SearchCandidate[], searchType: string): SearchResult[];
16
+ /**
17
+ * Apply API reranking to results
18
+ */
19
+ applyReranker(query: string, candidates: SearchCandidate[], chunkDir: string, basePath: string, providerContext: ReturnType<typeof resolveProviderContext>): Promise<SearchCandidate[]>;
20
+ /**
21
+ * Enforce score bounds on results
22
+ */
23
+ enforceScoreBounds(candidates: SearchCandidate[]): SearchCandidate[];
24
+ /**
25
+ * Sort results by reranker score, then by regular score
26
+ */
27
+ sortByScore(results: SearchResult[]): SearchResult[];
28
+ private readChunkText;
29
+ private buildBm25Document;
30
+ }
31
+ //# sourceMappingURL=ResultMapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResultMapper.d.ts","sourceRoot":"","sources":["../../../src/core/search/ResultMapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAKhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE;;;;;;GAMG;AACH,qBAAa,YAAY;IACvB;;OAEG;IACH,UAAU,CACR,UAAU,EAAE,eAAe,EAAE,EAC7B,UAAU,EAAE,MAAM,GACjB,YAAY,EAAE;IA8CjB;;OAEG;IACG,aAAa,CACjB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,eAAe,EAAE,EAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,GACzD,OAAO,CAAC,eAAe,EAAE,CAAC;IA6B7B;;OAEG;IACH,kBAAkB,CAAC,UAAU,EAAE,eAAe,EAAE,GAAG,eAAe,EAAE;IAOpE;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE;IAcpD,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,iBAAiB;CAa1B"}
@@ -0,0 +1,131 @@
1
+ import { rerankWithAPI } from '../../ranking/api-reranker.js';
2
+ import { readChunkFromDisk } from '../../storage/encrypted-chunks.js';
3
+ import { SEARCH_CONSTANTS } from '../../config/constants.js';
4
+ import { logger } from '../../utils/logger.js';
5
+ /**
6
+ * ResultMapper handles:
7
+ * - API reranking of results
8
+ * - Mapping candidates to search results
9
+ * - Building result metadata
10
+ * - Score normalization
11
+ */
12
+ export class ResultMapper {
13
+ /**
14
+ * Map search candidates to formatted search results
15
+ */
16
+ mapResults(candidates, searchType) {
17
+ return candidates.map(result => {
18
+ const meta = {
19
+ id: result.id,
20
+ symbol: result.symbol,
21
+ score: Math.min(1, Math.max(result.score || 0, 0)),
22
+ intent: result.codevault_intent,
23
+ description: result.codevault_description,
24
+ searchType: searchType,
25
+ vectorScore: result.vectorScore
26
+ };
27
+ // Add hybrid fusion scores
28
+ if (typeof result.hybridScore === 'number')
29
+ meta.hybridScore = result.hybridScore;
30
+ if (typeof result.bm25Score === 'number')
31
+ meta.bm25Score = result.bm25Score;
32
+ if (typeof result.bm25Rank === 'number')
33
+ meta.bm25Rank = result.bm25Rank;
34
+ if (typeof result.vectorRank === 'number')
35
+ meta.vectorRank = result.vectorRank;
36
+ // Add reranker scores
37
+ if (typeof result.rerankerScore === 'number')
38
+ meta.rerankerScore = result.rerankerScore;
39
+ if (typeof result.rerankerRank === 'number')
40
+ meta.rerankerRank = result.rerankerRank;
41
+ // Add symbol boost scores
42
+ if (typeof result.symbolBoost === 'number' && result.symbolBoost > 0) {
43
+ meta.symbolBoost = result.symbolBoost;
44
+ if (Array.isArray(result.symbolBoostSources))
45
+ meta.symbolBoostSources = result.symbolBoostSources;
46
+ }
47
+ // Include raw score if it exceeded 1.0
48
+ if (typeof result.score === 'number' && result.score > 1)
49
+ meta.scoreRaw = result.score;
50
+ return {
51
+ type: 'code',
52
+ lang: result.lang,
53
+ path: result.file_path,
54
+ sha: result.sha,
55
+ data: null,
56
+ meta
57
+ };
58
+ });
59
+ }
60
+ /**
61
+ * Apply API reranking to results
62
+ */
63
+ async applyReranker(query, candidates, chunkDir, basePath, providerContext) {
64
+ try {
65
+ const reranked = await rerankWithAPI(query, candidates, {
66
+ max: Math.min(SEARCH_CONSTANTS.RERANKER_MAX_CANDIDATES, candidates.length),
67
+ getText: candidate => {
68
+ const codeText = this.readChunkText(candidate.sha, chunkDir) || '';
69
+ return this.buildBm25Document(candidate, codeText);
70
+ },
71
+ apiUrl: providerContext.reranker.apiUrl,
72
+ apiKey: providerContext.reranker.apiKey,
73
+ model: providerContext.reranker.model,
74
+ maxTokens: providerContext.reranker.maxTokens
75
+ });
76
+ if (Array.isArray(reranked) && reranked.length === candidates.length) {
77
+ return reranked;
78
+ }
79
+ }
80
+ catch (error) {
81
+ logger.warn('API reranking failed, falling back to original ranking', {
82
+ error: error instanceof Error ? error.message : String(error)
83
+ });
84
+ }
85
+ return candidates;
86
+ }
87
+ /**
88
+ * Enforce score bounds on results
89
+ */
90
+ enforceScoreBounds(candidates) {
91
+ return candidates.map(candidate => ({
92
+ ...candidate,
93
+ score: Math.min(1, Math.max(candidate.score ?? 0, 0))
94
+ }));
95
+ }
96
+ /**
97
+ * Sort results by reranker score, then by regular score
98
+ */
99
+ sortByScore(results) {
100
+ return [...results].sort((a, b) => {
101
+ if (typeof a.meta?.rerankerScore === 'number' &&
102
+ typeof b.meta?.rerankerScore === 'number') {
103
+ return b.meta.rerankerScore - a.meta.rerankerScore;
104
+ }
105
+ return (b.meta?.score ?? 0) - (a.meta?.score ?? 0);
106
+ });
107
+ }
108
+ // Private helpers
109
+ readChunkText(sha, chunkDir) {
110
+ try {
111
+ const result = readChunkFromDisk({ chunkDir, sha });
112
+ return result ? result.code : null;
113
+ }
114
+ catch (error) {
115
+ return null;
116
+ }
117
+ }
118
+ buildBm25Document(chunk, codeText) {
119
+ if (!chunk)
120
+ return '';
121
+ const parts = [
122
+ chunk.symbol,
123
+ chunk.file_path,
124
+ chunk.codevault_description,
125
+ chunk.codevault_intent,
126
+ codeText
127
+ ].filter(value => typeof value === 'string' && value.trim().length > 0);
128
+ return parts.join('\n');
129
+ }
130
+ }
131
+ //# sourceMappingURL=ResultMapper.js.map