opensentinel 2.1.1 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/README.md +354 -283
  2. package/dist/archiver-AVNBYCKQ.js +15340 -0
  3. package/dist/archiver-AVNBYCKQ.js.map +1 -0
  4. package/dist/audit-logger-OBPR7CRO.js +22 -0
  5. package/dist/auth-UOX5K2BE.js +18 -0
  6. package/dist/autonomy-ZXDBDQUJ.js +86 -0
  7. package/dist/autonomy-ZXDBDQUJ.js.map +1 -0
  8. package/dist/aws-s3-Q4LLZZPD.js +146 -0
  9. package/dist/aws-s3-Q4LLZZPD.js.map +1 -0
  10. package/dist/backup-restore-PZ7CYYB7.js +16 -0
  11. package/dist/blocks-R3PODY47.js +23 -0
  12. package/dist/bot-QRARP4UN.js +36 -0
  13. package/dist/brain-7XLLM3KC.js +56 -0
  14. package/dist/camera-monitor-M5CYKUU4.js +335 -0
  15. package/dist/camera-monitor-M5CYKUU4.js.map +1 -0
  16. package/dist/{charts-MMXM6BWW.js → charts-V7ARZNKF.js} +2 -2
  17. package/dist/chunk-22VGGA7S.js +330 -0
  18. package/dist/chunk-22VGGA7S.js.map +1 -0
  19. package/dist/chunk-35WYTA3C.js +382 -0
  20. package/dist/chunk-35WYTA3C.js.map +1 -0
  21. package/dist/chunk-3E2PSU2C.js +146 -0
  22. package/dist/chunk-3E2PSU2C.js.map +1 -0
  23. package/dist/{chunk-L3F43VPB.js → chunk-4GLYY4NN.js} +2 -2
  24. package/dist/{chunk-L3F43VPB.js.map → chunk-4GLYY4NN.js.map} +1 -1
  25. package/dist/{chunk-L3PDU3XN.js → chunk-4UOE5TUZ.js} +4 -4
  26. package/dist/{chunk-6SNHU3CY.js → chunk-66OJ3WB4.js} +2 -2
  27. package/dist/chunk-6KONMXQ6.js +297 -0
  28. package/dist/chunk-6KONMXQ6.js.map +1 -0
  29. package/dist/chunk-6PMVAAA7.js +196 -0
  30. package/dist/chunk-6PMVAAA7.js.map +1 -0
  31. package/dist/chunk-766ASQWE.js +32620 -0
  32. package/dist/chunk-766ASQWE.js.map +1 -0
  33. package/dist/chunk-7WQO5J2M.js +29 -0
  34. package/dist/chunk-7WQO5J2M.js.map +1 -0
  35. package/dist/chunk-APHSRMBS.js +148 -0
  36. package/dist/chunk-APHSRMBS.js.map +1 -0
  37. package/dist/{chunk-4LVWXUNC.js → chunk-AYUKPTSM.js} +57 -39
  38. package/dist/chunk-AYUKPTSM.js.map +1 -0
  39. package/dist/chunk-BIPYADGB.js +84 -0
  40. package/dist/chunk-BIPYADGB.js.map +1 -0
  41. package/dist/chunk-BRBWNV65.js +457 -0
  42. package/dist/chunk-BRBWNV65.js.map +1 -0
  43. package/dist/chunk-BXZ6EA52.js +382 -0
  44. package/dist/chunk-BXZ6EA52.js.map +1 -0
  45. package/dist/chunk-EVE7MIIY.js +290 -0
  46. package/dist/chunk-EVE7MIIY.js.map +1 -0
  47. package/dist/chunk-F3TTNID2.js +138 -0
  48. package/dist/chunk-F3TTNID2.js.map +1 -0
  49. package/dist/chunk-H5RQOFO2.js +190 -0
  50. package/dist/chunk-H5RQOFO2.js.map +1 -0
  51. package/dist/chunk-HN3F4WSW.js +145 -0
  52. package/dist/chunk-HN3F4WSW.js.map +1 -0
  53. package/dist/{chunk-6DRDKB45.js → chunk-I6BDYQIG.js} +20 -9
  54. package/dist/chunk-I6BDYQIG.js.map +1 -0
  55. package/dist/chunk-IZJMVV7O.js +347 -0
  56. package/dist/chunk-IZJMVV7O.js.map +1 -0
  57. package/dist/chunk-KM22GV7G.js +211 -0
  58. package/dist/chunk-KM22GV7G.js.map +1 -0
  59. package/dist/chunk-MGFBLVR7.js +103 -0
  60. package/dist/chunk-MGFBLVR7.js.map +1 -0
  61. package/dist/chunk-MQJ2ECQT.js +228 -0
  62. package/dist/chunk-MQJ2ECQT.js.map +1 -0
  63. package/dist/{chunk-F6QUZQGI.js → chunk-MXAPLSJ5.js} +2 -2
  64. package/dist/{chunk-GK3E2I7A.js → chunk-NHMBTUMW.js} +2 -2
  65. package/dist/chunk-NPRTSZIF.js +131 -0
  66. package/dist/chunk-NPRTSZIF.js.map +1 -0
  67. package/dist/chunk-O7IH7JTI.js +1898 -0
  68. package/dist/chunk-O7IH7JTI.js.map +1 -0
  69. package/dist/chunk-OCVQGBJK.js +293 -0
  70. package/dist/chunk-OCVQGBJK.js.map +1 -0
  71. package/dist/chunk-P6QINGFL.js +332 -0
  72. package/dist/chunk-P6QINGFL.js.map +1 -0
  73. package/dist/chunk-PHDZKPNE.js +91 -0
  74. package/dist/chunk-PHDZKPNE.js.map +1 -0
  75. package/dist/chunk-PLDDJCW6.js +49 -0
  76. package/dist/chunk-PTGTGXV2.js +164 -0
  77. package/dist/chunk-PTGTGXV2.js.map +1 -0
  78. package/dist/chunk-REMIY4U2.js +171 -0
  79. package/dist/chunk-REMIY4U2.js.map +1 -0
  80. package/dist/chunk-RZ4YESBG.js +141 -0
  81. package/dist/chunk-RZ4YESBG.js.map +1 -0
  82. package/dist/chunk-SAX5MHK4.js +111 -0
  83. package/dist/chunk-SAX5MHK4.js.map +1 -0
  84. package/dist/{chunk-GVJVEWHI.js → chunk-SJSUSJ47.js} +2 -2
  85. package/dist/chunk-SPPMCAKG.js +777 -0
  86. package/dist/chunk-SPPMCAKG.js.map +1 -0
  87. package/dist/chunk-SVAPX2XN.js +2441 -0
  88. package/dist/chunk-SVAPX2XN.js.map +1 -0
  89. package/dist/chunk-TVEWKIK3.js +452 -0
  90. package/dist/chunk-TVEWKIK3.js.map +1 -0
  91. package/dist/{chunk-HH2HBTQM.js → chunk-TYAGMJNV.js} +5 -5
  92. package/dist/{chunk-JXUP2X7V.js → chunk-VEHFVBLI.js} +2 -2
  93. package/dist/chunk-VNX5GMTN.js +128 -0
  94. package/dist/chunk-VNX5GMTN.js.map +1 -0
  95. package/dist/chunk-VRD5CYRL.js +1568 -0
  96. package/dist/chunk-VRD5CYRL.js.map +1 -0
  97. package/dist/chunk-WLUHNG6X.js +122 -0
  98. package/dist/chunk-WLUHNG6X.js.map +1 -0
  99. package/dist/chunk-WRAKK6K6.js +265 -0
  100. package/dist/chunk-WRAKK6K6.js.map +1 -0
  101. package/dist/chunk-XKYRH4FM.js +681 -0
  102. package/dist/chunk-XKYRH4FM.js.map +1 -0
  103. package/dist/{chunk-GUBEEYDW.js → chunk-XMCVRVTF.js} +2 -2
  104. package/dist/{chunk-GUBEEYDW.js.map → chunk-XMCVRVTF.js.map} +1 -1
  105. package/dist/chunk-ZLZKF2PM.js +310 -0
  106. package/dist/chunk-ZLZKF2PM.js.map +1 -0
  107. package/dist/cli.js +5 -1
  108. package/dist/cli.js.map +1 -1
  109. package/dist/client-ZQSFPMOB.js +21 -0
  110. package/dist/clipboard-manager-TEO2GEDN.js +24 -0
  111. package/dist/commands/setup.js +3 -3
  112. package/dist/commands/setup.js.map +1 -1
  113. package/dist/commands/start.js +3 -3
  114. package/dist/commands/status.js +2 -2
  115. package/dist/commands/stop.js +2 -2
  116. package/dist/commands/utils.js +2 -2
  117. package/dist/cron-explain-HHQKPD3M.js +16 -0
  118. package/dist/crypto-4AP47IKC.js +14 -0
  119. package/dist/crypto-4AP47IKC.js.map +1 -0
  120. package/dist/databases-37X4CI2Y.js +21 -0
  121. package/dist/databases-37X4CI2Y.js.map +1 -0
  122. package/dist/discord-B3HUPGQ6.js +70 -0
  123. package/dist/discord-B3HUPGQ6.js.map +1 -0
  124. package/dist/dist-UISMLMFN.js +21847 -0
  125. package/dist/dist-UISMLMFN.js.map +1 -0
  126. package/dist/email-K7LO2IPB.js +268 -0
  127. package/dist/email-K7LO2IPB.js.map +1 -0
  128. package/dist/enhanced-retrieval-DNLLEM4Z.js +753 -0
  129. package/dist/enhanced-retrieval-DNLLEM4Z.js.map +1 -0
  130. package/dist/enrichment-pipeline-MNHNW65K.js +13 -0
  131. package/dist/enrichment-pipeline-MNHNW65K.js.map +1 -0
  132. package/dist/entity-resolution-Y3IUWEAT.js +24 -0
  133. package/dist/entity-resolution-Y3IUWEAT.js.map +1 -0
  134. package/dist/env-IWXUVTCB.js +12 -0
  135. package/dist/env-IWXUVTCB.js.map +1 -0
  136. package/dist/google-workspace-DKWUVNGC.js +169 -0
  137. package/dist/google-workspace-DKWUVNGC.js.map +1 -0
  138. package/dist/hash-tool-ULQYD7B5.js +22 -0
  139. package/dist/hash-tool-ULQYD7B5.js.map +1 -0
  140. package/dist/heartbeat-monitor-GCISLXI3.js +22 -0
  141. package/dist/heartbeat-monitor-GCISLXI3.js.map +1 -0
  142. package/dist/image-generation-OSU7FP6F.js +486 -0
  143. package/dist/image-generation-OSU7FP6F.js.map +1 -0
  144. package/dist/imessage-NGA2XF2V.js +35 -0
  145. package/dist/imessage-NGA2XF2V.js.map +1 -0
  146. package/dist/inbox-summarizer-NRI4S7IF.js +47 -0
  147. package/dist/inbox-summarizer-NRI4S7IF.js.map +1 -0
  148. package/dist/incident-response-C5J7Q6DT.js +244 -0
  149. package/dist/incident-response-C5J7Q6DT.js.map +1 -0
  150. package/dist/inventory-manager-352OHXWD.js +24 -0
  151. package/dist/inventory-manager-352OHXWD.js.map +1 -0
  152. package/dist/jira-GSGDBMIG.js +199 -0
  153. package/dist/jira-GSGDBMIG.js.map +1 -0
  154. package/dist/json-tool-QE2SYHEG.js +26 -0
  155. package/dist/json-tool-QE2SYHEG.js.map +1 -0
  156. package/dist/key-rotation-DPHU4ZTB.js +18 -0
  157. package/dist/key-rotation-DPHU4ZTB.js.map +1 -0
  158. package/dist/lib.d.ts +603 -11
  159. package/dist/lib.js +161 -35
  160. package/dist/lib.js.map +1 -1
  161. package/dist/mailchimp-KKNF6QJ7.js +152 -0
  162. package/dist/mailchimp-KKNF6QJ7.js.map +1 -0
  163. package/dist/matrix-QVHG76I7.js +279 -0
  164. package/dist/matrix-QVHG76I7.js.map +1 -0
  165. package/dist/{mcp-LS7Q3Z5W.js → mcp-3JI6W7ZE.js} +3 -3
  166. package/dist/mcp-3JI6W7ZE.js.map +1 -0
  167. package/dist/microsoft365-UCBKJHNX.js +164 -0
  168. package/dist/microsoft365-UCBKJHNX.js.map +1 -0
  169. package/dist/ocr-AC7NPX33.js +22 -0
  170. package/dist/ocr-AC7NPX33.js.map +1 -0
  171. package/dist/ollama-BOAMSPLJ.js +8 -0
  172. package/dist/ollama-BOAMSPLJ.js.map +1 -0
  173. package/dist/pages-MI523RB7.js +26 -0
  174. package/dist/pages-MI523RB7.js.map +1 -0
  175. package/dist/pair-JDFTERIK.js +24 -0
  176. package/dist/pair-JDFTERIK.js.map +1 -0
  177. package/dist/pairing-IFQYCPNS.js +10 -0
  178. package/dist/pairing-IFQYCPNS.js.map +1 -0
  179. package/dist/pdf-ALQVOEJR.js +17 -0
  180. package/dist/pdf-ALQVOEJR.js.map +1 -0
  181. package/dist/presentations-DSV5IHG5.js +1002 -0
  182. package/dist/presentations-DSV5IHG5.js.map +1 -0
  183. package/dist/prometheus-JNT2BD4L.js +10 -0
  184. package/dist/prometheus-JNT2BD4L.js.map +1 -0
  185. package/dist/providers-J4LYPHDR.js +19 -0
  186. package/dist/providers-J4LYPHDR.js.map +1 -0
  187. package/dist/qr-code-WIX4PB4U.js +16 -0
  188. package/dist/qr-code-WIX4PB4U.js.map +1 -0
  189. package/dist/quickbooks-XB4NII2S.js +190 -0
  190. package/dist/quickbooks-XB4NII2S.js.map +1 -0
  191. package/dist/regex-tool-W4ABRKGK.js +24 -0
  192. package/dist/regex-tool-W4ABRKGK.js.map +1 -0
  193. package/dist/scheduler-VK4WFERV.js +63 -0
  194. package/dist/scheduler-VK4WFERV.js.map +1 -0
  195. package/dist/search-BCLBO5E3.js +25 -0
  196. package/dist/search-BCLBO5E3.js.map +1 -0
  197. package/dist/sendgrid-RNXCAFKM.js +152 -0
  198. package/dist/sendgrid-RNXCAFKM.js.map +1 -0
  199. package/dist/shopify-NCXYJB4R.js +171 -0
  200. package/dist/shopify-NCXYJB4R.js.map +1 -0
  201. package/dist/signal-6CGDFYL2.js +35 -0
  202. package/dist/signal-6CGDFYL2.js.map +1 -0
  203. package/dist/slack-IZQWIKOH.js +75 -0
  204. package/dist/slack-IZQWIKOH.js.map +1 -0
  205. package/dist/sms-M3JIOTCW.js +23 -0
  206. package/dist/sms-M3JIOTCW.js.map +1 -0
  207. package/dist/{src-K7GASHRH.js → src-VYUE6LRA.js} +138 -32
  208. package/dist/src-VYUE6LRA.js.map +1 -0
  209. package/dist/stocks-XXWBPOCU.js +14 -0
  210. package/dist/stocks-XXWBPOCU.js.map +1 -0
  211. package/dist/text-transform-6SGUA5Z4.js +22 -0
  212. package/dist/text-transform-6SGUA5Z4.js.map +1 -0
  213. package/dist/tools-2RLEI2N6.js +38 -0
  214. package/dist/tools-2RLEI2N6.js.map +1 -0
  215. package/dist/tunnel-IWMXUML4.js +301 -0
  216. package/dist/tunnel-IWMXUML4.js.map +1 -0
  217. package/dist/twilio-53GEW5JT.js +139 -0
  218. package/dist/twilio-53GEW5JT.js.map +1 -0
  219. package/dist/unit-converter-ZYXMEZOE.js +14 -0
  220. package/dist/unit-converter-ZYXMEZOE.js.map +1 -0
  221. package/dist/whatsapp-LFX6YKCM.js +35 -0
  222. package/dist/whatsapp-LFX6YKCM.js.map +1 -0
  223. package/dist/word-document-7B6SJMAY.js +902 -0
  224. package/dist/word-document-7B6SJMAY.js.map +1 -0
  225. package/dist/xero-QYO66D45.js +162 -0
  226. package/dist/xero-QYO66D45.js.map +1 -0
  227. package/dist/zapier-webhook-TBZ5YF2A.js +106 -0
  228. package/dist/zapier-webhook-TBZ5YF2A.js.map +1 -0
  229. package/drizzle/0002_mushy_master_mold.sql +140 -0
  230. package/drizzle/meta/0002_snapshot.json +3637 -0
  231. package/drizzle/meta/_journal.json +7 -0
  232. package/package.json +100 -98
  233. package/dist/bot-KJ26BG56.js +0 -15
  234. package/dist/chunk-4LVWXUNC.js.map +0 -1
  235. package/dist/chunk-4TG2IG5K.js +0 -5249
  236. package/dist/chunk-4TG2IG5K.js.map +0 -1
  237. package/dist/chunk-6DRDKB45.js.map +0 -1
  238. package/dist/chunk-CI6Q63MM.js +0 -1613
  239. package/dist/chunk-CI6Q63MM.js.map +0 -1
  240. package/dist/chunk-KHNYJY2Z.js +0 -178
  241. package/dist/chunk-KHNYJY2Z.js.map +0 -1
  242. package/dist/chunk-NSBPE2FW.js +0 -17
  243. package/dist/discord-ZOJFTVTB.js +0 -49
  244. package/dist/imessage-JFRB6EJ7.js +0 -14
  245. package/dist/scheduler-EZ7CZMCS.js +0 -42
  246. package/dist/signal-T3MCSULM.js +0 -14
  247. package/dist/slack-N2M4FHAJ.js +0 -54
  248. package/dist/src-K7GASHRH.js.map +0 -1
  249. package/dist/tools-24GZHYRF.js +0 -16
  250. package/dist/whatsapp-VCRUPAO5.js +0 -14
  251. /package/dist/{bot-KJ26BG56.js.map → audit-logger-OBPR7CRO.js.map} +0 -0
  252. /package/dist/{chunk-NSBPE2FW.js.map → auth-UOX5K2BE.js.map} +0 -0
  253. /package/dist/{discord-ZOJFTVTB.js.map → backup-restore-PZ7CYYB7.js.map} +0 -0
  254. /package/dist/{imessage-JFRB6EJ7.js.map → blocks-R3PODY47.js.map} +0 -0
  255. /package/dist/{mcp-LS7Q3Z5W.js.map → bot-QRARP4UN.js.map} +0 -0
  256. /package/dist/{scheduler-EZ7CZMCS.js.map → brain-7XLLM3KC.js.map} +0 -0
  257. /package/dist/{charts-MMXM6BWW.js.map → charts-V7ARZNKF.js.map} +0 -0
  258. /package/dist/{chunk-L3PDU3XN.js.map → chunk-4UOE5TUZ.js.map} +0 -0
  259. /package/dist/{chunk-6SNHU3CY.js.map → chunk-66OJ3WB4.js.map} +0 -0
  260. /package/dist/{chunk-F6QUZQGI.js.map → chunk-MXAPLSJ5.js.map} +0 -0
  261. /package/dist/{chunk-GK3E2I7A.js.map → chunk-NHMBTUMW.js.map} +0 -0
  262. /package/dist/{signal-T3MCSULM.js.map → chunk-PLDDJCW6.js.map} +0 -0
  263. /package/dist/{chunk-GVJVEWHI.js.map → chunk-SJSUSJ47.js.map} +0 -0
  264. /package/dist/{chunk-HH2HBTQM.js.map → chunk-TYAGMJNV.js.map} +0 -0
  265. /package/dist/{chunk-JXUP2X7V.js.map → chunk-VEHFVBLI.js.map} +0 -0
  266. /package/dist/{slack-N2M4FHAJ.js.map → client-ZQSFPMOB.js.map} +0 -0
  267. /package/dist/{tools-24GZHYRF.js.map → clipboard-manager-TEO2GEDN.js.map} +0 -0
  268. /package/dist/{whatsapp-VCRUPAO5.js.map → cron-explain-HHQKPD3M.js.map} +0 -0
@@ -0,0 +1,753 @@
1
+ import {
2
+ generateEmbedding
3
+ } from "./chunk-IZJMVV7O.js";
4
+ import {
5
+ providerRegistry
6
+ } from "./chunk-BXZ6EA52.js";
7
+ import {
8
+ db
9
+ } from "./chunk-XKYRH4FM.js";
10
+ import {
11
+ env
12
+ } from "./chunk-ZLZKF2PM.js";
13
+ import "./chunk-35WYTA3C.js";
14
+ import "./chunk-PLDDJCW6.js";
15
+
16
+ // src/core/memory/hybrid-search.ts
17
+ import { sql } from "drizzle-orm";
18
+ var RRF_K = 60;
19
+ async function vectorSearch(query, userId, limit = 10) {
20
+ const queryEmbedding = await generateEmbedding(query);
21
+ const results = await db.execute(sql`
22
+ SELECT
23
+ id, user_id, type, content, importance, source, provenance,
24
+ created_at,
25
+ 1 - (embedding <=> ${JSON.stringify(queryEmbedding)}::vector) as similarity
26
+ FROM memories
27
+ ${userId ? sql`WHERE user_id = ${userId}` : sql``}
28
+ ORDER BY embedding <=> ${JSON.stringify(queryEmbedding)}::vector
29
+ LIMIT ${limit}
30
+ `);
31
+ return results;
32
+ }
33
+ async function keywordSearch(query, userId, limit = 10) {
34
+ const results = await db.execute(sql`
35
+ SELECT
36
+ id, user_id, type, content, importance, source, provenance,
37
+ created_at,
38
+ ts_rank(search_vector, plainto_tsquery('english', ${query})) as keyword_rank
39
+ FROM memories
40
+ WHERE search_vector IS NOT NULL
41
+ AND search_vector @@ plainto_tsquery('english', ${query})
42
+ ${userId ? sql`AND user_id = ${userId}` : sql``}
43
+ ORDER BY keyword_rank DESC
44
+ LIMIT ${limit}
45
+ `);
46
+ return results.map((r) => ({
47
+ ...r,
48
+ keywordRank: r.keyword_rank
49
+ }));
50
+ }
51
+ async function graphAugmentedSearch(query, userId, limit = 10) {
52
+ const entities = await db.execute(sql`
53
+ SELECT id, name, type
54
+ FROM graph_entities
55
+ WHERE name ILIKE ${"%" + query + "%"}
56
+ ${userId ? sql`AND user_id = ${userId}` : sql``}
57
+ LIMIT 5
58
+ `);
59
+ if (entities.length === 0) {
60
+ return [];
61
+ }
62
+ const entityIds = entities.map((e) => e.id);
63
+ const entityNames = entities.map((e) => e.name);
64
+ const namePattern = entityNames.join("|");
65
+ const results = await db.execute(sql`
66
+ SELECT
67
+ id, user_id, type, content, importance, source, provenance,
68
+ created_at,
69
+ 1.0 as graph_score
70
+ FROM memories
71
+ WHERE content ~* ${namePattern}
72
+ ${userId ? sql`AND user_id = ${userId}` : sql``}
73
+ ORDER BY importance DESC, created_at DESC
74
+ LIMIT ${limit}
75
+ `);
76
+ return results.map((r) => ({
77
+ ...r,
78
+ graphScore: r.graph_score
79
+ }));
80
+ }
81
+ function reciprocalRankFusion(rankedLists, k = RRF_K) {
82
+ const scores = /* @__PURE__ */ new Map();
83
+ for (const list of rankedLists) {
84
+ for (let rank = 0; rank < list.length; rank++) {
85
+ const id = list[rank].id;
86
+ const rrfScore = 1 / (k + rank + 1);
87
+ scores.set(id, (scores.get(id) || 0) + rrfScore);
88
+ }
89
+ }
90
+ return scores;
91
+ }
92
+ async function hybridSearch(query, options = {}) {
93
+ const {
94
+ userId,
95
+ limit = 10,
96
+ since,
97
+ until,
98
+ includeKeyword = true,
99
+ includeGraph = true
100
+ } = options;
101
+ const searchPromises = [
102
+ vectorSearch(query, userId, limit * 2)
103
+ // Fetch more for better fusion
104
+ ];
105
+ if (includeKeyword) {
106
+ searchPromises.push(keywordSearch(query, userId, limit * 2));
107
+ }
108
+ if (includeGraph) {
109
+ searchPromises.push(graphAugmentedSearch(query, userId, limit));
110
+ }
111
+ const results = await Promise.all(searchPromises);
112
+ const [vectorResults, keywordResults, graphResults] = results;
113
+ const allResults = /* @__PURE__ */ new Map();
114
+ for (const r of vectorResults || []) {
115
+ allResults.set(r.id, r);
116
+ }
117
+ for (const r of keywordResults || []) {
118
+ if (!allResults.has(r.id)) allResults.set(r.id, r);
119
+ }
120
+ for (const r of graphResults || []) {
121
+ if (!allResults.has(r.id)) allResults.set(r.id, r);
122
+ }
123
+ const rankedLists = [vectorResults || []];
124
+ if (keywordResults) rankedLists.push(keywordResults);
125
+ if (graphResults) rankedLists.push(graphResults);
126
+ const rrfScores = reciprocalRankFusion(rankedLists);
127
+ let finalResults = [];
128
+ for (const [id, rrfScore] of rrfScores) {
129
+ const data = allResults.get(id);
130
+ if (!data) continue;
131
+ finalResults.push({
132
+ id: data.id,
133
+ userId: data.user_id,
134
+ type: data.type,
135
+ content: data.content,
136
+ importance: data.importance || 5,
137
+ source: data.source,
138
+ provenance: data.provenance,
139
+ similarity: data.similarity || 0,
140
+ keywordRank: data.keywordRank || data.keyword_rank || 0,
141
+ rrfScore,
142
+ createdAt: data.created_at
143
+ });
144
+ }
145
+ if (since) {
146
+ finalResults = finalResults.filter((r) => new Date(r.createdAt) >= since);
147
+ }
148
+ if (until) {
149
+ finalResults = finalResults.filter((r) => new Date(r.createdAt) <= until);
150
+ }
151
+ return finalResults.sort((a, b) => b.rrfScore - a.rrfScore).slice(0, limit);
152
+ }
153
+
154
+ // src/core/memory/contextual-query.ts
155
+ var DEFAULT_MAX_HISTORY_MESSAGES = 4;
156
+ var MAX_TOKENS = 200;
157
+ var SYSTEM_PROMPT = "Rewrite this query to be self-contained by resolving pronouns, references, and implicit context from the conversation. Return ONLY the rewritten query, nothing else.";
158
+ async function buildContextualQuery(query, conversationHistory, opts) {
159
+ try {
160
+ if (!env.CONTEXTUAL_QUERY_ENABLED) {
161
+ return query;
162
+ }
163
+ if (!conversationHistory || conversationHistory.length < 2) {
164
+ return query;
165
+ }
166
+ const maxHistory = opts?.maxHistoryMessages ?? DEFAULT_MAX_HISTORY_MESSAGES;
167
+ const recentHistory = conversationHistory.slice(-maxHistory);
168
+ const conversationText = recentHistory.map((msg) => `${msg.role === "user" ? "User" : "Assistant"}: ${msg.content}`).join("\n");
169
+ const userPrompt = `Conversation so far:
170
+ ${conversationText}
171
+
172
+ Current query to rewrite:
173
+ ${query}`;
174
+ const provider = providerRegistry.getDefault();
175
+ const model = opts?.model ?? "claude-sonnet-4-5-20250929";
176
+ const response = await provider.createMessage({
177
+ model,
178
+ max_tokens: MAX_TOKENS,
179
+ system: SYSTEM_PROMPT,
180
+ messages: [
181
+ {
182
+ role: "user",
183
+ content: userPrompt
184
+ }
185
+ ]
186
+ });
187
+ const rewrittenQuery = response.content.filter((block) => block.type === "text" && block.text).map((block) => block.text).join("").trim();
188
+ if (!rewrittenQuery) {
189
+ return query;
190
+ }
191
+ return rewrittenQuery;
192
+ } catch {
193
+ return query;
194
+ }
195
+ }
196
+
197
+ // src/core/memory/hyde.ts
198
+ import { sql as sql2 } from "drizzle-orm";
199
+ var RRF_K2 = 60;
200
+ var DEFAULT_SYSTEM_PROMPT = "You are a helpful assistant. Generate a detailed document that would perfectly answer the following question. Write as if this document already exists in a knowledge base. Be specific and factual.";
201
+ var DEFAULT_MAX_TOKENS = 300;
202
+ async function generateHypotheticalDocument(query, opts) {
203
+ const systemPrompt = opts?.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
204
+ const maxTokens = opts?.maxTokens ?? DEFAULT_MAX_TOKENS;
205
+ const provider = providerRegistry.getDefault();
206
+ const response = await provider.createMessage({
207
+ model: "claude-sonnet-4-20250514",
208
+ max_tokens: maxTokens,
209
+ system: systemPrompt,
210
+ messages: [
211
+ {
212
+ role: "user",
213
+ content: query
214
+ }
215
+ ]
216
+ });
217
+ const text = response.content.filter((block) => block.type === "text").map((block) => block.text ?? "").join("");
218
+ return text;
219
+ }
220
+ async function vectorSearchWithEmbedding(embedding, userId, limit = 10) {
221
+ const embeddingStr = JSON.stringify(embedding);
222
+ const results = await db.execute(sql2`
223
+ SELECT
224
+ id, user_id, type, content, importance, source, provenance,
225
+ created_at,
226
+ 1 - (embedding <=> ${embeddingStr}::vector) as similarity
227
+ FROM memories
228
+ ${userId ? sql2`WHERE user_id = ${userId}` : sql2``}
229
+ ORDER BY embedding <=> ${embeddingStr}::vector
230
+ LIMIT ${limit}
231
+ `);
232
+ return results;
233
+ }
234
+ function reciprocalRankFusion2(rankedLists, k = RRF_K2) {
235
+ const scores = /* @__PURE__ */ new Map();
236
+ for (const list of rankedLists) {
237
+ for (let rank = 0; rank < list.length; rank++) {
238
+ const id = list[rank].id;
239
+ const rrfScore = 1 / (k + rank + 1);
240
+ scores.set(id, (scores.get(id) || 0) + rrfScore);
241
+ }
242
+ }
243
+ return scores;
244
+ }
245
+ async function hydeSearch(query, userId, limit = 10) {
246
+ if (!env.HYDE_ENABLED) {
247
+ const results = await hybridSearch(query, { userId, limit });
248
+ return results.map((r) => ({ ...r, hydeDocument: "" }));
249
+ }
250
+ let hydeDocument;
251
+ try {
252
+ hydeDocument = await generateHypotheticalDocument(query);
253
+ } catch (error) {
254
+ console.warn("[HyDE] LLM generation failed, falling back to hybrid search:", error);
255
+ const results = await hybridSearch(query, { userId, limit });
256
+ return results.map((r) => ({ ...r, hydeDocument: "" }));
257
+ }
258
+ if (!hydeDocument || hydeDocument.trim().length === 0) {
259
+ console.warn("[HyDE] Empty hypothetical document, falling back to hybrid search");
260
+ const results = await hybridSearch(query, { userId, limit });
261
+ return results.map((r) => ({ ...r, hydeDocument: "" }));
262
+ }
263
+ let hydeEmbedding;
264
+ try {
265
+ hydeEmbedding = await generateEmbedding(hydeDocument);
266
+ } catch (error) {
267
+ console.warn("[HyDE] Embedding generation failed, falling back to hybrid search:", error);
268
+ const results = await hybridSearch(query, { userId, limit });
269
+ return results.map((r) => ({ ...r, hydeDocument: "" }));
270
+ }
271
+ const fetchLimit = limit * 2;
272
+ const [vectorResults, kwResults] = await Promise.all([
273
+ vectorSearchWithEmbedding(hydeEmbedding, userId, fetchLimit),
274
+ keywordSearch(query, userId, fetchLimit)
275
+ ]);
276
+ const allResults = /* @__PURE__ */ new Map();
277
+ for (const r of vectorResults) {
278
+ allResults.set(r.id, r);
279
+ }
280
+ for (const r of kwResults) {
281
+ if (!allResults.has(r.id)) {
282
+ allResults.set(r.id, r);
283
+ }
284
+ }
285
+ const rrfScores = reciprocalRankFusion2([vectorResults, kwResults]);
286
+ const finalResults = [];
287
+ for (const [id, rrfScore] of rrfScores) {
288
+ const data = allResults.get(id);
289
+ if (!data) continue;
290
+ finalResults.push({
291
+ id: data.id,
292
+ userId: data.user_id,
293
+ type: data.type,
294
+ content: data.content,
295
+ importance: data.importance || 5,
296
+ source: data.source,
297
+ provenance: data.provenance,
298
+ similarity: data.similarity || 0,
299
+ keywordRank: data.keywordRank || data.keyword_rank || 0,
300
+ rrfScore,
301
+ createdAt: data.created_at,
302
+ hydeDocument
303
+ });
304
+ }
305
+ return finalResults.sort((a, b) => b.rrfScore - a.rrfScore).slice(0, limit);
306
+ }
307
+
308
+ // src/core/memory/retrieval-cache.ts
309
+ import Redis from "ioredis";
310
+ import { createHash } from "crypto";
311
+ var KEY_PREFIX = "rag:cache:";
312
+ var DEFAULT_TTL_SECONDS = 3600;
313
+ var RetrievalCache = class {
314
+ redis = null;
315
+ connecting = false;
316
+ /**
317
+ * Lazily create / return a Redis client.
318
+ * Returns null if Redis is unavailable.
319
+ */
320
+ async getClient() {
321
+ if (this.redis) return this.redis;
322
+ if (this.connecting) return null;
323
+ try {
324
+ this.connecting = true;
325
+ const client = new Redis(env.REDIS_URL, {
326
+ maxRetriesPerRequest: null,
327
+ lazyConnect: true
328
+ });
329
+ await client.connect();
330
+ this.redis = client;
331
+ return this.redis;
332
+ } catch {
333
+ this.redis = null;
334
+ return null;
335
+ } finally {
336
+ this.connecting = false;
337
+ }
338
+ }
339
+ /**
340
+ * Hash an embedding vector for use as a cache key.
341
+ *
342
+ * Rounds each component to 4 decimal places to tolerate minor
343
+ * floating-point differences, then produces a SHA-256 hex digest.
344
+ */
345
+ hashEmbedding(embedding) {
346
+ const rounded = embedding.map((v) => v.toFixed(4)).join(",");
347
+ return createHash("sha256").update(rounded).digest("hex");
348
+ }
349
+ /**
350
+ * Look up cached search results for the given embedding.
351
+ * Returns null on cache miss or if the cache is disabled / unavailable.
352
+ */
353
+ async getCachedResults(queryEmbedding) {
354
+ if (!env.RETRIEVAL_CACHE_ENABLED) return null;
355
+ try {
356
+ const client = await this.getClient();
357
+ if (!client) return null;
358
+ const hash = this.hashEmbedding(queryEmbedding);
359
+ const key = `${KEY_PREFIX}${hash}`;
360
+ const raw = await client.get(key);
361
+ if (!raw) return null;
362
+ const cached = JSON.parse(raw);
363
+ cached.results = cached.results.map((r) => ({
364
+ ...r,
365
+ createdAt: new Date(r.createdAt)
366
+ }));
367
+ return cached;
368
+ } catch {
369
+ return null;
370
+ }
371
+ }
372
+ /**
373
+ * Store search results in Redis, keyed by embedding hash.
374
+ *
375
+ * @param queryEmbedding - The embedding vector used for the search.
376
+ * @param results - The hybrid search results to cache.
377
+ * @param ttl - Time-to-live in seconds (default 3600).
378
+ */
379
+ async cacheResults(queryEmbedding, results, ttl = DEFAULT_TTL_SECONDS) {
380
+ if (!env.RETRIEVAL_CACHE_ENABLED) return;
381
+ try {
382
+ const client = await this.getClient();
383
+ if (!client) return;
384
+ const hash = this.hashEmbedding(queryEmbedding);
385
+ const key = `${KEY_PREFIX}${hash}`;
386
+ const entry = {
387
+ results,
388
+ cachedAt: Date.now(),
389
+ queryHash: hash
390
+ };
391
+ await client.set(key, JSON.stringify(entry), "EX", ttl);
392
+ } catch {
393
+ }
394
+ }
395
+ /**
396
+ * Remove cache entries matching a key pattern.
397
+ *
398
+ * @param pattern - Glob pattern appended to the key prefix.
399
+ * Defaults to `*` (all retrieval cache keys).
400
+ * @returns The number of keys deleted.
401
+ */
402
+ async invalidateCache(pattern) {
403
+ try {
404
+ const client = await this.getClient();
405
+ if (!client) return 0;
406
+ const scanPattern = `${KEY_PREFIX}${pattern ?? "*"}`;
407
+ let deleted = 0;
408
+ let cursor = "0";
409
+ do {
410
+ const [nextCursor, keys] = await client.scan(
411
+ cursor,
412
+ "MATCH",
413
+ scanPattern,
414
+ "COUNT",
415
+ 100
416
+ );
417
+ cursor = nextCursor;
418
+ if (keys.length > 0) {
419
+ deleted += await client.del(...keys);
420
+ }
421
+ } while (cursor !== "0");
422
+ return deleted;
423
+ } catch {
424
+ return 0;
425
+ }
426
+ }
427
+ };
428
+ var instance = null;
429
+ function getRetrievalCache() {
430
+ if (!instance) {
431
+ instance = new RetrievalCache();
432
+ }
433
+ return instance;
434
+ }
435
+
436
+ // src/core/memory/reranker.ts
437
+ var DEFAULT_BATCH_SIZE = 5;
438
+ var DEFAULT_MAX_TOKENS2 = 100;
439
+ var DEFAULT_SCORE = 5;
440
+ var DEFAULT_MODEL = "claude-sonnet-4-20250514";
441
+ function buildScoringPrompt(query, documents) {
442
+ const docList = documents.map((doc, i) => `${i + 1}. ${doc}`).join("\n");
443
+ return `You are a relevance judge. Given a search query and a list of retrieved documents, rate each document's relevance to the query on a scale of 0-10.
444
+
445
+ Query: ${query}
446
+
447
+ Documents:
448
+ ${docList}
449
+
450
+ Return a JSON array of scores: [score1, score2, ...]
451
+ Only return the JSON array, nothing else.`;
452
+ }
453
+ function parseScores(text, expectedCount) {
454
+ try {
455
+ const parsed = JSON.parse(text.trim());
456
+ if (Array.isArray(parsed)) {
457
+ return parsed.map((s) => {
458
+ const n = Number(s);
459
+ return Number.isFinite(n) ? Math.min(10, Math.max(0, n)) : DEFAULT_SCORE;
460
+ });
461
+ }
462
+ } catch {
463
+ }
464
+ const matches = text.match(/\d+(?:\.\d+)?/g);
465
+ if (matches && matches.length > 0) {
466
+ return matches.slice(0, expectedCount).map((m) => {
467
+ const n = Number(m);
468
+ return Number.isFinite(n) ? Math.min(10, Math.max(0, n)) : DEFAULT_SCORE;
469
+ });
470
+ }
471
+ return new Array(expectedCount).fill(DEFAULT_SCORE);
472
+ }
473
+ async function batchRerank(query, results, batchSize = DEFAULT_BATCH_SIZE, model) {
474
+ const provider = providerRegistry.getDefault();
475
+ const resolvedModel = model || DEFAULT_MODEL;
476
+ const rankedResults = [];
477
+ const batches = [];
478
+ for (let i = 0; i < results.length; i += batchSize) {
479
+ batches.push(results.slice(i, i + batchSize));
480
+ }
481
+ const batchPromises = batches.map(async (batch) => {
482
+ const documents = batch.map((r) => r.content);
483
+ const prompt = buildScoringPrompt(query, documents);
484
+ try {
485
+ const response = await provider.createMessage({
486
+ model: resolvedModel,
487
+ max_tokens: DEFAULT_MAX_TOKENS2,
488
+ system: "You are a relevance scoring assistant. Only output valid JSON.",
489
+ messages: [{ role: "user", content: prompt }]
490
+ });
491
+ const responseText = response.content.filter((block) => block.type === "text").map((block) => block.text || "").join("");
492
+ const scores = parseScores(responseText, batch.length);
493
+ return batch.map((result, idx) => ({
494
+ ...result,
495
+ rerankScore: idx < scores.length ? scores[idx] : DEFAULT_SCORE
496
+ }));
497
+ } catch (error) {
498
+ console.warn(
499
+ `[Reranker] LLM scoring failed for batch, assigning default score of ${DEFAULT_SCORE}:`,
500
+ error instanceof Error ? error.message : error
501
+ );
502
+ return batch.map((result) => ({
503
+ ...result,
504
+ rerankScore: DEFAULT_SCORE
505
+ }));
506
+ }
507
+ });
508
+ const batchResults = await Promise.all(batchPromises);
509
+ for (const batch of batchResults) {
510
+ rankedResults.push(...batch);
511
+ }
512
+ return rankedResults;
513
+ }
514
+ async function rerank(query, results, opts) {
515
+ try {
516
+ const minScore = opts?.minScore ?? env.RERANK_MIN_SCORE;
517
+ if (!env.RERANK_ENABLED) {
518
+ return results.map((r) => ({ ...r, rerankScore: DEFAULT_SCORE }));
519
+ }
520
+ if (results.length <= 1) {
521
+ return results.map((r) => ({ ...r, rerankScore: 10 }));
522
+ }
523
+ let ranked = await batchRerank(query, results, DEFAULT_BATCH_SIZE, opts?.model);
524
+ ranked = ranked.filter((r) => r.rerankScore >= minScore);
525
+ ranked.sort((a, b) => b.rerankScore - a.rerankScore);
526
+ if (opts?.topK && opts.topK > 0) {
527
+ ranked = ranked.slice(0, opts.topK);
528
+ }
529
+ return ranked;
530
+ } catch (error) {
531
+ console.error(
532
+ "[Reranker] Re-ranking failed, returning original results:",
533
+ error instanceof Error ? error.message : error
534
+ );
535
+ return results.map((r) => ({ ...r, rerankScore: DEFAULT_SCORE }));
536
+ }
537
+ }
538
+
539
+ // src/core/memory/multi-step.ts
540
+ var COMPLETENESS_MAX_TOKENS = 300;
541
+ var COMPLETENESS_MODEL = "claude-sonnet-4-5-20250929";
542
+ async function evaluateCompleteness(query, context) {
543
+ try {
544
+ const provider = providerRegistry.getDefault();
545
+ const response = await provider.createMessage({
546
+ model: COMPLETENESS_MODEL,
547
+ max_tokens: COMPLETENESS_MAX_TOKENS,
548
+ system: "You are a retrieval evaluation assistant. Only output valid JSON.",
549
+ messages: [
550
+ {
551
+ role: "user",
552
+ content: `Analyze whether the following context sufficiently answers the query. Return a JSON object with:
553
+ - "complete": boolean (true if context fully answers the query)
554
+ - "gaps": string[] (list of missing information)
555
+ - "followUpQueries": string[] (search queries to fill the gaps, max 2)
556
+
557
+ Query: ${query}
558
+
559
+ Context:
560
+ ${context}
561
+
562
+ Return only the JSON object.`
563
+ }
564
+ ]
565
+ });
566
+ const responseText = response.content.filter((block) => block.type === "text").map((block) => block.text || "").join("");
567
+ const parsed = JSON.parse(responseText.trim());
568
+ return {
569
+ complete: Boolean(parsed.complete),
570
+ gaps: Array.isArray(parsed.gaps) ? parsed.gaps : [],
571
+ followUpQueries: Array.isArray(parsed.followUpQueries) ? parsed.followUpQueries.slice(0, 2) : []
572
+ };
573
+ } catch (error) {
574
+ console.warn(
575
+ "[MultiStepRAG] Completeness evaluation failed, assuming complete:",
576
+ error instanceof Error ? error.message : error
577
+ );
578
+ return { complete: true, gaps: [], followUpQueries: [] };
579
+ }
580
+ }
581
+ async function multiStepRetrieve(query, initialResults, opts) {
582
+ if (!env.MULTISTEP_RAG_ENABLED) {
583
+ return {
584
+ results: initialResults,
585
+ steps: 0,
586
+ followUpQueries: []
587
+ };
588
+ }
589
+ const maxSteps = opts?.maxSteps ?? env.MULTISTEP_MAX_STEPS;
590
+ const userId = opts?.userId;
591
+ const limit = opts?.limit ?? 10;
592
+ const resultsById = /* @__PURE__ */ new Map();
593
+ for (const r of initialResults) {
594
+ resultsById.set(r.id, r);
595
+ }
596
+ const allFollowUpQueries = [];
597
+ let stepsPerformed = 0;
598
+ for (let step = 0; step < maxSteps; step++) {
599
+ const currentResults = Array.from(resultsById.values());
600
+ const contextText = currentResults.map((r) => r.content).join("\n\n");
601
+ const evaluation = await evaluateCompleteness(query, contextText);
602
+ if (evaluation.complete || evaluation.followUpQueries.length === 0) {
603
+ break;
604
+ }
605
+ stepsPerformed++;
606
+ const followUps = evaluation.followUpQueries.slice(0, 2);
607
+ allFollowUpQueries.push(...followUps);
608
+ const retrievalPromises = followUps.map(async (followUpQuery) => {
609
+ const searchResults = await hybridSearch(followUpQuery, {
610
+ userId,
611
+ limit
612
+ });
613
+ const rankedResults = await rerank(followUpQuery, searchResults);
614
+ return rankedResults;
615
+ });
616
+ const additionalResultSets = await Promise.all(retrievalPromises);
617
+ for (const resultSet of additionalResultSets) {
618
+ for (const r of resultSet) {
619
+ if (!resultsById.has(r.id)) {
620
+ resultsById.set(r.id, r);
621
+ }
622
+ }
623
+ }
624
+ }
625
+ const mergedResults = Array.from(resultsById.values()).sort(
626
+ (a, b) => b.rerankScore - a.rerankScore
627
+ );
628
+ return {
629
+ results: mergedResults,
630
+ steps: stepsPerformed,
631
+ followUpQueries: allFollowUpQueries
632
+ };
633
+ }
634
+
635
+ // src/core/memory/enhanced-retrieval.ts
636
+ function toRankedResults(results, defaultScore) {
637
+ return results.map((r) => ({
638
+ ...r,
639
+ rerankScore: defaultScore ?? r.rrfScore * 10
640
+ }));
641
+ }
642
+ async function enhancedRetrieve(query, opts) {
643
+ const userId = opts?.userId;
644
+ const limit = opts?.limit ?? 10;
645
+ const conversationHistory = opts?.conversationHistory;
646
+ let steps = 0;
647
+ try {
648
+ let effectiveQuery = query;
649
+ if (env.CONTEXTUAL_QUERY_ENABLED && conversationHistory && conversationHistory.length >= 2) {
650
+ console.log("[EnhancedRetrieval] Contextual query rewrite enabled, rewriting query...");
651
+ effectiveQuery = await buildContextualQuery(query, conversationHistory);
652
+ steps++;
653
+ console.log(`[EnhancedRetrieval] Rewritten query: "${effectiveQuery}"`);
654
+ }
655
+ let cached = false;
656
+ let queryEmbedding = null;
657
+ if (env.RETRIEVAL_CACHE_ENABLED) {
658
+ console.log("[EnhancedRetrieval] Cache enabled, checking for cached results...");
659
+ queryEmbedding = await generateEmbedding(effectiveQuery);
660
+ const cache = getRetrievalCache();
661
+ const cachedResult = await cache.getCachedResults(queryEmbedding);
662
+ if (cachedResult) {
663
+ console.log("[EnhancedRetrieval] Cache hit, using cached results");
664
+ cached = true;
665
+ steps++;
666
+ let rankedResults2 = toRankedResults(cachedResult.results, 5);
667
+ if (env.RERANK_ENABLED) {
668
+ console.log("[EnhancedRetrieval] Re-ranking cached results...");
669
+ rankedResults2 = await rerank(effectiveQuery, cachedResult.results);
670
+ steps++;
671
+ }
672
+ if (env.MULTISTEP_RAG_ENABLED) {
673
+ console.log("[EnhancedRetrieval] Multi-step retrieval on cached results...");
674
+ rankedResults2 = await multiStepRetrieve(effectiveQuery, rankedResults2, { userId });
675
+ steps++;
676
+ }
677
+ return {
678
+ results: rankedResults2,
679
+ cached: true,
680
+ steps,
681
+ queryUsed: effectiveQuery
682
+ };
683
+ }
684
+ console.log("[EnhancedRetrieval] Cache miss, proceeding to search");
685
+ }
686
+ let searchResults;
687
+ if (env.HYDE_ENABLED) {
688
+ console.log("[EnhancedRetrieval] HyDE enabled, generating hypothetical doc...");
689
+ searchResults = await hydeSearch(effectiveQuery, userId, limit);
690
+ steps++;
691
+ } else {
692
+ console.log("[EnhancedRetrieval] Running hybrid search...");
693
+ searchResults = await hybridSearch(effectiveQuery, { userId, limit });
694
+ steps++;
695
+ }
696
+ let rankedResults;
697
+ if (env.RERANK_ENABLED) {
698
+ console.log("[EnhancedRetrieval] Re-ranking results...");
699
+ rankedResults = await rerank(effectiveQuery, searchResults);
700
+ steps++;
701
+ } else {
702
+ rankedResults = toRankedResults(searchResults);
703
+ }
704
+ if (env.RETRIEVAL_CACHE_ENABLED && !cached) {
705
+ console.log("[EnhancedRetrieval] Storing results in cache...");
706
+ if (!queryEmbedding) {
707
+ queryEmbedding = await generateEmbedding(effectiveQuery);
708
+ }
709
+ const cache = getRetrievalCache();
710
+ await cache.cacheResults(queryEmbedding, searchResults);
711
+ }
712
+ if (env.MULTISTEP_RAG_ENABLED) {
713
+ console.log("[EnhancedRetrieval] Multi-step retrieval enabled, filling gaps...");
714
+ rankedResults = await multiStepRetrieve(effectiveQuery, rankedResults, { userId });
715
+ steps++;
716
+ }
717
+ return {
718
+ results: rankedResults,
719
+ cached,
720
+ steps,
721
+ queryUsed: effectiveQuery
722
+ };
723
+ } catch (error) {
724
+ console.error(
725
+ "[EnhancedRetrieval] Pipeline failed, falling back to plain hybrid search:",
726
+ error instanceof Error ? error.message : error
727
+ );
728
+ try {
729
+ const fallbackResults = await hybridSearch(query, { userId, limit });
730
+ return {
731
+ results: toRankedResults(fallbackResults, 5),
732
+ cached: false,
733
+ steps: 0,
734
+ queryUsed: query
735
+ };
736
+ } catch (fallbackError) {
737
+ console.error(
738
+ "[EnhancedRetrieval] Fallback hybrid search also failed:",
739
+ fallbackError instanceof Error ? fallbackError.message : fallbackError
740
+ );
741
+ return {
742
+ results: [],
743
+ cached: false,
744
+ steps: 0,
745
+ queryUsed: query
746
+ };
747
+ }
748
+ }
749
+ }
750
+ export {
751
+ enhancedRetrieve
752
+ };
753
+ //# sourceMappingURL=enhanced-retrieval-DNLLEM4Z.js.map