opensentinel 3.1.1 → 3.6.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 (325) hide show
  1. package/README.md +126 -83
  2. package/dist/agent-manager-7N7REQZQ.js +39 -0
  3. package/dist/agent-processor-I23VWQY3.js +280 -0
  4. package/dist/agent-processor-I23VWQY3.js.map +1 -0
  5. package/dist/agent-types-2T4PXLFQ.js +12 -0
  6. package/dist/alerting-4I37GG4U.js +699 -0
  7. package/dist/alerting-4I37GG4U.js.map +1 -0
  8. package/dist/analysis-agent-JWN2GXYE.js +288 -0
  9. package/dist/analysis-agent-JWN2GXYE.js.map +1 -0
  10. package/dist/{archiver-AVNBYCKQ.js → archiver-XLRIIXPY.js} +86 -17
  11. package/dist/archiver-XLRIIXPY.js.map +1 -0
  12. package/dist/{audit-logger-OBPR7CRO.js → audit-logger-AU3TMWKI.js} +6 -5
  13. package/dist/{auth-UOX5K2BE.js → auth-PH5IHISW.js} +2 -2
  14. package/dist/{autonomy-ZXDBDQUJ.js → autonomy-N7W5XPLX.js} +4 -3
  15. package/dist/autonomy-N7W5XPLX.js.map +1 -0
  16. package/dist/{aws-s3-Q4LLZZPD.js → aws-s3-QZMURYXB.js} +2 -2
  17. package/dist/{backup-restore-PZ7CYYB7.js → backup-restore-72OQTZO3.js} +2 -2
  18. package/dist/{blocks-R3PODY47.js → blocks-YOWOESDD.js} +4 -4
  19. package/dist/bot-MU2TJQ3Y.js +46 -0
  20. package/dist/brain-SLA474EU.js +65 -0
  21. package/dist/{camera-monitor-M5CYKUU4.js → camera-monitor-LHTUWHEL.js} +2 -2
  22. package/dist/{charts-V7ARZNKF.js → charts-FJ32GQK7.js} +2 -2
  23. package/dist/{chunk-6PMVAAA7.js → chunk-2RGPWU77.js} +3 -3
  24. package/dist/{chunk-TVEWKIK3.js → chunk-2WTKTG2C.js} +2 -2
  25. package/dist/{chunk-MXAPLSJ5.js → chunk-45YXODSB.js} +2 -2
  26. package/dist/{chunk-SJSUSJ47.js → chunk-4YJRBMMA.js} +2 -2
  27. package/dist/chunk-643M3AP5.js +564 -0
  28. package/dist/chunk-643M3AP5.js.map +1 -0
  29. package/dist/{chunk-766ASQWE.js → chunk-6JY4HNUH.js} +2413 -2368
  30. package/dist/chunk-6JY4HNUH.js.map +1 -0
  31. package/dist/chunk-6LTLIYAQ.js +194 -0
  32. package/dist/chunk-6LTLIYAQ.js.map +1 -0
  33. package/dist/chunk-6UZPE35A.js +724 -0
  34. package/dist/chunk-6UZPE35A.js.map +1 -0
  35. package/dist/chunk-6W6PTJFT.js +181 -0
  36. package/dist/chunk-6W6PTJFT.js.map +1 -0
  37. package/dist/chunk-7MZN73J2.js +162 -0
  38. package/dist/chunk-7MZN73J2.js.map +1 -0
  39. package/dist/{chunk-SVAPX2XN.js → chunk-A24GPVLY.js} +9 -7
  40. package/dist/{chunk-SVAPX2XN.js.map → chunk-A24GPVLY.js.map} +1 -1
  41. package/dist/chunk-AD6YEH6U.js +3408 -0
  42. package/dist/chunk-AD6YEH6U.js.map +1 -0
  43. package/dist/chunk-ADTDYJO7.js +265 -0
  44. package/dist/chunk-ADTDYJO7.js.map +1 -0
  45. package/dist/{chunk-WRAKK6K6.js → chunk-AR34B6XR.js} +5 -3
  46. package/dist/{chunk-WRAKK6K6.js.map → chunk-AR34B6XR.js.map} +1 -1
  47. package/dist/chunk-BMOUYXLX.js +418 -0
  48. package/dist/chunk-BMOUYXLX.js.map +1 -0
  49. package/dist/chunk-C6PELIHS.js +60 -0
  50. package/dist/chunk-C6PELIHS.js.map +1 -0
  51. package/dist/{chunk-MQJ2ECQT.js → chunk-CUPEENUY.js} +3 -3
  52. package/dist/{chunk-RZ4YESBG.js → chunk-DOYGMNMK.js} +1 -1
  53. package/dist/chunk-DOYGMNMK.js.map +1 -0
  54. package/dist/chunk-FFV2SXFD.js +380 -0
  55. package/dist/chunk-FFV2SXFD.js.map +1 -0
  56. package/dist/{chunk-EVE7MIIY.js → chunk-GUKKW7JI.js} +15 -16
  57. package/dist/chunk-GUKKW7JI.js.map +1 -0
  58. package/dist/{chunk-66OJ3WB4.js → chunk-H3BOLSTS.js} +2 -2
  59. package/dist/chunk-HKOPRRDJ.js +1021 -0
  60. package/dist/chunk-HKOPRRDJ.js.map +1 -0
  61. package/dist/{chunk-BXZ6EA52.js → chunk-HTF2GIQC.js} +57 -3
  62. package/dist/chunk-HTF2GIQC.js.map +1 -0
  63. package/dist/{chunk-TYAGMJNV.js → chunk-JOA5A3G3.js} +5 -5
  64. package/dist/{chunk-OCVQGBJK.js → chunk-KABG5PG3.js} +6 -4
  65. package/dist/{chunk-OCVQGBJK.js.map → chunk-KABG5PG3.js.map} +1 -1
  66. package/dist/{chunk-VEHFVBLI.js → chunk-KT7NLIXP.js} +2 -2
  67. package/dist/chunk-LFDXEYYB.js +150 -0
  68. package/dist/chunk-LFDXEYYB.js.map +1 -0
  69. package/dist/{chunk-I6BDYQIG.js → chunk-M7YLQHFP.js} +6 -6
  70. package/dist/chunk-M7YLQHFP.js.map +1 -0
  71. package/dist/{chunk-AYUKPTSM.js → chunk-MFK34XSY.js} +96 -218
  72. package/dist/chunk-MFK34XSY.js.map +1 -0
  73. package/dist/chunk-MIC5IBQF.js +386 -0
  74. package/dist/chunk-MIC5IBQF.js.map +1 -0
  75. package/dist/{chunk-4UOE5TUZ.js → chunk-NMSHVO5O.js} +4 -4
  76. package/dist/{chunk-XKYRH4FM.js → chunk-NYVBXUGD.js} +13 -32
  77. package/dist/chunk-NYVBXUGD.js.map +1 -0
  78. package/dist/chunk-ODCFS5WD.js +463 -0
  79. package/dist/chunk-ODCFS5WD.js.map +1 -0
  80. package/dist/{chunk-ZLZKF2PM.js → chunk-PUNIMPMY.js} +32 -2
  81. package/dist/chunk-PUNIMPMY.js.map +1 -0
  82. package/dist/chunk-S4NJJS5C.js +37 -0
  83. package/dist/chunk-S4NJJS5C.js.map +1 -0
  84. package/dist/{chunk-NHMBTUMW.js → chunk-TAAZB5KN.js} +2 -2
  85. package/dist/{chunk-BRBWNV65.js → chunk-U2X2J3FI.js} +3 -3
  86. package/dist/chunk-U2X2J3FI.js.map +1 -0
  87. package/dist/{chunk-PLDDJCW6.js → chunk-UP2VWCW5.js} +1 -12
  88. package/dist/{chunk-4GLYY4NN.js → chunk-UWUIJTT4.js} +8 -2
  89. package/dist/chunk-UWUIJTT4.js.map +1 -0
  90. package/dist/{chunk-SPPMCAKG.js → chunk-VKMFUIVA.js} +2 -2
  91. package/dist/chunk-VKMFUIVA.js.map +1 -0
  92. package/dist/chunk-WZAH34TG.js +129 -0
  93. package/dist/chunk-WZAH34TG.js.map +1 -0
  94. package/dist/{chunk-H5RQOFO2.js → chunk-X6Q3K3L2.js} +6 -6
  95. package/dist/chunk-X6Q3K3L2.js.map +1 -0
  96. package/dist/chunk-XTX7EK43.js +134 -0
  97. package/dist/chunk-XTX7EK43.js.map +1 -0
  98. package/dist/chunk-ZIYTHUM5.js +457 -0
  99. package/dist/chunk-ZIYTHUM5.js.map +1 -0
  100. package/dist/chunker-K6WTR62A.js +12 -0
  101. package/dist/cli.js +1 -1
  102. package/dist/{client-ZQSFPMOB.js → client-FOIYPOZQ.js} +5 -6
  103. package/dist/{clipboard-manager-TEO2GEDN.js → clipboard-manager-4SBNESGZ.js} +2 -2
  104. package/dist/coding-agent-DESSU3AC.js +233 -0
  105. package/dist/coding-agent-DESSU3AC.js.map +1 -0
  106. package/dist/commands/setup.js +1 -1
  107. package/dist/commands/start.js +2 -2
  108. package/dist/commands/status.js +1 -1
  109. package/dist/commands/stop.js +1 -1
  110. package/dist/commands/utils.js +1 -1
  111. package/dist/cost-tracker-EMOIOYH7.js +11 -0
  112. package/dist/{cron-explain-HHQKPD3M.js → cron-explain-UOOOYWZZ.js} +2 -2
  113. package/dist/{crypto-4AP47IKC.js → crypto-2VG3RJR2.js} +2 -2
  114. package/dist/{databases-37X4CI2Y.js → databases-XDPMG5AV.js} +4 -4
  115. package/dist/db-LRIOKQBO.js +77 -0
  116. package/dist/discord-NKR3X4AV.js +80 -0
  117. package/dist/documents-EYIYLZK2.js +184 -0
  118. package/dist/documents-EYIYLZK2.js.map +1 -0
  119. package/dist/docx-parser-EXL4TN5E.js +16 -0
  120. package/dist/{email-K7LO2IPB.js → email-EAQNULVD.js} +33 -25
  121. package/dist/{email-K7LO2IPB.js.map → email-EAQNULVD.js.map} +1 -1
  122. package/dist/{enhanced-retrieval-DNLLEM4Z.js → enhanced-retrieval-OGHT6TS5.js} +11 -8
  123. package/dist/{enhanced-retrieval-DNLLEM4Z.js.map → enhanced-retrieval-OGHT6TS5.js.map} +1 -1
  124. package/dist/enrichment-pipeline-CMUVBDC7.js +14 -0
  125. package/dist/{entity-resolution-Y3IUWEAT.js → entity-resolution-4X4JU43O.js} +6 -5
  126. package/dist/env-CHOFICED.js +12 -0
  127. package/dist/error-tracker-SVQSDQDW.js +32 -0
  128. package/dist/finnhub-X7ZMQSXF.js +178 -0
  129. package/dist/finnhub-X7ZMQSXF.js.map +1 -0
  130. package/dist/fred-TMUF3J2V.js +203 -0
  131. package/dist/fred-TMUF3J2V.js.map +1 -0
  132. package/dist/github-KGNILDWJ.js +833 -0
  133. package/dist/github-KGNILDWJ.js.map +1 -0
  134. package/dist/{google-workspace-DKWUVNGC.js → google-workspace-TSZPZK5G.js} +2 -2
  135. package/dist/{hash-tool-ULQYD7B5.js → hash-tool-ENAB5LWH.js} +2 -2
  136. package/dist/{heartbeat-monitor-GCISLXI3.js → heartbeat-monitor-KRDYTDBF.js} +2 -2
  137. package/dist/hooks-N4MIFBVM.js +14 -0
  138. package/dist/{image-generation-OSU7FP6F.js → image-generation-MDE6AVQO.js} +2 -2
  139. package/dist/imessage-V2XNDDHT.js +43 -0
  140. package/dist/inbox-summarizer-DKKRYXDR.js +55 -0
  141. package/dist/{incident-response-C5J7Q6DT.js → incident-response-ZTIKUWEO.js} +8 -6
  142. package/dist/{incident-response-C5J7Q6DT.js.map → incident-response-ZTIKUWEO.js.map} +1 -1
  143. package/dist/{inventory-manager-352OHXWD.js → inventory-manager-C67BSZM6.js} +2 -2
  144. package/dist/{jira-GSGDBMIG.js → jira-PAGZWUBJ.js} +2 -2
  145. package/dist/{json-tool-QE2SYHEG.js → json-tool-4FK5RNER.js} +2 -2
  146. package/dist/{key-rotation-DPHU4ZTB.js → key-rotation-WCC5FOYS.js} +2 -2
  147. package/dist/knowledge-base-J7PJ7MZ3.js +46 -0
  148. package/dist/lib.d.ts +73 -1
  149. package/dist/lib.js +86 -76
  150. package/dist/lib.js.map +1 -1
  151. package/dist/{mailchimp-KKNF6QJ7.js → mailchimp-ZFYDC44J.js} +2 -2
  152. package/dist/{matrix-QVHG76I7.js → matrix-XHTR53VQ.js} +29 -21
  153. package/dist/{matrix-QVHG76I7.js.map → matrix-XHTR53VQ.js.map} +1 -1
  154. package/dist/{mcp-3JI6W7ZE.js → mcp-3C2TN67D.js} +3 -3
  155. package/dist/metrics-VJDWQWU7.js +25 -0
  156. package/dist/{microsoft365-UCBKJHNX.js → microsoft365-6G2IJMWC.js} +2 -2
  157. package/dist/multi-user-S56GUD6L.js +411 -0
  158. package/dist/multi-user-S56GUD6L.js.map +1 -0
  159. package/dist/{ocr-AC7NPX33.js → ocr-LGUIPKVZ.js} +6 -4
  160. package/dist/{ollama-BOAMSPLJ.js → ollama-J7CU45WT.js} +2 -2
  161. package/dist/osint-agent-RL5XPBRQ.js +189 -0
  162. package/dist/osint-agent-RL5XPBRQ.js.map +1 -0
  163. package/dist/{pages-MI523RB7.js → pages-XDE7JRCA.js} +5 -5
  164. package/dist/{pair-JDFTERIK.js → pair-YZJFQUU5.js} +2 -2
  165. package/dist/{pairing-IFQYCPNS.js → pairing-77N47RAT.js} +2 -2
  166. package/dist/{pdf-ALQVOEJR.js → pdf-67HGXCFJ.js} +3 -3
  167. package/dist/pdf-parser-YLMTTYHL.js +14 -0
  168. package/dist/{presentations-DSV5IHG5.js → presentations-HXTAMGHT.js} +3 -3
  169. package/dist/presentations-HXTAMGHT.js.map +1 -0
  170. package/dist/{prometheus-JNT2BD4L.js → prometheus-YETCZO4I.js} +2 -2
  171. package/dist/{providers-J4LYPHDR.js → providers-H6YIC3MG.js} +6 -4
  172. package/dist/{qr-code-WIX4PB4U.js → qr-code-6WZJHRKL.js} +2 -2
  173. package/dist/{quickbooks-XB4NII2S.js → quickbooks-N675W7IK.js} +2 -2
  174. package/dist/{regex-tool-W4ABRKGK.js → regex-tool-6Q63LQ7B.js} +2 -2
  175. package/dist/regex-tool-6Q63LQ7B.js.map +1 -0
  176. package/dist/research-agent-WCRSY3UZ.js +168 -0
  177. package/dist/research-agent-WCRSY3UZ.js.map +1 -0
  178. package/dist/risk-engine-YKCPT5D5.js +10 -0
  179. package/dist/risk-engine-YKCPT5D5.js.map +1 -0
  180. package/dist/scheduler-CA5UNHZV.js +73 -0
  181. package/dist/scheduler-CA5UNHZV.js.map +1 -0
  182. package/dist/schema-ALJ67YVG.js +72 -0
  183. package/dist/schema-ALJ67YVG.js.map +1 -0
  184. package/dist/{search-BCLBO5E3.js → search-GMLKBHSW.js} +4 -4
  185. package/dist/search-GMLKBHSW.js.map +1 -0
  186. package/dist/{sendgrid-RNXCAFKM.js → sendgrid-QGJIVPWV.js} +2 -2
  187. package/dist/{shopify-NCXYJB4R.js → shopify-ON2PAU27.js} +2 -2
  188. package/dist/signal-X7IQJGRQ.js +43 -0
  189. package/dist/signal-X7IQJGRQ.js.map +1 -0
  190. package/dist/slack-P2LFUJUQ.js +85 -0
  191. package/dist/slack-P2LFUJUQ.js.map +1 -0
  192. package/dist/{sms-M3JIOTCW.js → sms-4VME2HUL.js} +4 -4
  193. package/dist/sms-4VME2HUL.js.map +1 -0
  194. package/dist/{src-VYUE6LRA.js → src-S5KX4YEV.js} +179 -48
  195. package/dist/src-S5KX4YEV.js.map +1 -0
  196. package/dist/{stocks-XXWBPOCU.js → stocks-4M4HZWZS.js} +2 -2
  197. package/dist/stocks-4M4HZWZS.js.map +1 -0
  198. package/dist/text-extractor-OAUBAW5P.js +12 -0
  199. package/dist/text-extractor-OAUBAW5P.js.map +1 -0
  200. package/dist/{text-transform-6SGUA5Z4.js → text-transform-HCLCUDFZ.js} +2 -2
  201. package/dist/text-transform-HCLCUDFZ.js.map +1 -0
  202. package/dist/tools-FGPN522P.js +46 -0
  203. package/dist/tools-FGPN522P.js.map +1 -0
  204. package/dist/{tunnel-IWMXUML4.js → tunnel-XOUVVRAK.js} +4 -2
  205. package/dist/tunnel-XOUVVRAK.js.map +1 -0
  206. package/dist/{twilio-53GEW5JT.js → twilio-3L7DUNYQ.js} +2 -2
  207. package/dist/{unit-converter-ZYXMEZOE.js → unit-converter-LYPAHU64.js} +2 -2
  208. package/dist/unit-converter-LYPAHU64.js.map +1 -0
  209. package/dist/whatsapp-KRPQ4YUX.js +43 -0
  210. package/dist/whatsapp-KRPQ4YUX.js.map +1 -0
  211. package/dist/{word-document-7B6SJMAY.js → word-document-D6N2C47N.js} +4 -4
  212. package/dist/word-document-D6N2C47N.js.map +1 -0
  213. package/dist/workflow-store-ZYAYE5P6.js +373 -0
  214. package/dist/workflow-store-ZYAYE5P6.js.map +1 -0
  215. package/dist/writing-agent-VDGLNOGO.js +243 -0
  216. package/dist/writing-agent-VDGLNOGO.js.map +1 -0
  217. package/dist/{xero-QYO66D45.js → xero-UHAHVYSD.js} +2 -2
  218. package/dist/{zapier-webhook-TBZ5YF2A.js → zapier-webhook-NIELLTXR.js} +2 -2
  219. package/package.json +11 -1
  220. package/dist/archiver-AVNBYCKQ.js.map +0 -1
  221. package/dist/autonomy-ZXDBDQUJ.js.map +0 -1
  222. package/dist/bot-QRARP4UN.js +0 -36
  223. package/dist/brain-7XLLM3KC.js +0 -56
  224. package/dist/chunk-4GLYY4NN.js.map +0 -1
  225. package/dist/chunk-766ASQWE.js.map +0 -1
  226. package/dist/chunk-AYUKPTSM.js.map +0 -1
  227. package/dist/chunk-BRBWNV65.js.map +0 -1
  228. package/dist/chunk-BXZ6EA52.js.map +0 -1
  229. package/dist/chunk-EVE7MIIY.js.map +0 -1
  230. package/dist/chunk-H5RQOFO2.js.map +0 -1
  231. package/dist/chunk-I6BDYQIG.js.map +0 -1
  232. package/dist/chunk-IZJMVV7O.js +0 -347
  233. package/dist/chunk-IZJMVV7O.js.map +0 -1
  234. package/dist/chunk-O7IH7JTI.js +0 -1898
  235. package/dist/chunk-O7IH7JTI.js.map +0 -1
  236. package/dist/chunk-RZ4YESBG.js.map +0 -1
  237. package/dist/chunk-SPPMCAKG.js.map +0 -1
  238. package/dist/chunk-VRD5CYRL.js +0 -1568
  239. package/dist/chunk-VRD5CYRL.js.map +0 -1
  240. package/dist/chunk-XKYRH4FM.js.map +0 -1
  241. package/dist/chunk-ZLZKF2PM.js.map +0 -1
  242. package/dist/discord-B3HUPGQ6.js +0 -70
  243. package/dist/dist-UISMLMFN.js +0 -21847
  244. package/dist/dist-UISMLMFN.js.map +0 -1
  245. package/dist/enrichment-pipeline-MNHNW65K.js +0 -13
  246. package/dist/env-IWXUVTCB.js +0 -12
  247. package/dist/imessage-NGA2XF2V.js +0 -35
  248. package/dist/inbox-summarizer-NRI4S7IF.js +0 -47
  249. package/dist/presentations-DSV5IHG5.js.map +0 -1
  250. package/dist/scheduler-VK4WFERV.js +0 -63
  251. package/dist/signal-6CGDFYL2.js +0 -35
  252. package/dist/slack-IZQWIKOH.js +0 -75
  253. package/dist/src-VYUE6LRA.js.map +0 -1
  254. package/dist/tools-2RLEI2N6.js +0 -38
  255. package/dist/tunnel-IWMXUML4.js.map +0 -1
  256. package/dist/whatsapp-LFX6YKCM.js +0 -35
  257. package/dist/word-document-7B6SJMAY.js.map +0 -1
  258. /package/dist/{audit-logger-OBPR7CRO.js.map → agent-manager-7N7REQZQ.js.map} +0 -0
  259. /package/dist/{auth-UOX5K2BE.js.map → agent-types-2T4PXLFQ.js.map} +0 -0
  260. /package/dist/{backup-restore-PZ7CYYB7.js.map → audit-logger-AU3TMWKI.js.map} +0 -0
  261. /package/dist/{blocks-R3PODY47.js.map → auth-PH5IHISW.js.map} +0 -0
  262. /package/dist/{aws-s3-Q4LLZZPD.js.map → aws-s3-QZMURYXB.js.map} +0 -0
  263. /package/dist/{bot-QRARP4UN.js.map → backup-restore-72OQTZO3.js.map} +0 -0
  264. /package/dist/{brain-7XLLM3KC.js.map → blocks-YOWOESDD.js.map} +0 -0
  265. /package/dist/{chunk-PLDDJCW6.js.map → bot-MU2TJQ3Y.js.map} +0 -0
  266. /package/dist/{client-ZQSFPMOB.js.map → brain-SLA474EU.js.map} +0 -0
  267. /package/dist/{camera-monitor-M5CYKUU4.js.map → camera-monitor-LHTUWHEL.js.map} +0 -0
  268. /package/dist/{charts-V7ARZNKF.js.map → charts-FJ32GQK7.js.map} +0 -0
  269. /package/dist/{chunk-6PMVAAA7.js.map → chunk-2RGPWU77.js.map} +0 -0
  270. /package/dist/{chunk-TVEWKIK3.js.map → chunk-2WTKTG2C.js.map} +0 -0
  271. /package/dist/{chunk-MXAPLSJ5.js.map → chunk-45YXODSB.js.map} +0 -0
  272. /package/dist/{chunk-SJSUSJ47.js.map → chunk-4YJRBMMA.js.map} +0 -0
  273. /package/dist/{chunk-MQJ2ECQT.js.map → chunk-CUPEENUY.js.map} +0 -0
  274. /package/dist/{chunk-66OJ3WB4.js.map → chunk-H3BOLSTS.js.map} +0 -0
  275. /package/dist/{chunk-TYAGMJNV.js.map → chunk-JOA5A3G3.js.map} +0 -0
  276. /package/dist/{chunk-VEHFVBLI.js.map → chunk-KT7NLIXP.js.map} +0 -0
  277. /package/dist/{chunk-4UOE5TUZ.js.map → chunk-NMSHVO5O.js.map} +0 -0
  278. /package/dist/{chunk-NHMBTUMW.js.map → chunk-TAAZB5KN.js.map} +0 -0
  279. /package/dist/{clipboard-manager-TEO2GEDN.js.map → chunk-UP2VWCW5.js.map} +0 -0
  280. /package/dist/{cron-explain-HHQKPD3M.js.map → chunker-K6WTR62A.js.map} +0 -0
  281. /package/dist/{crypto-4AP47IKC.js.map → client-FOIYPOZQ.js.map} +0 -0
  282. /package/dist/{databases-37X4CI2Y.js.map → clipboard-manager-4SBNESGZ.js.map} +0 -0
  283. /package/dist/{discord-B3HUPGQ6.js.map → cost-tracker-EMOIOYH7.js.map} +0 -0
  284. /package/dist/{enrichment-pipeline-MNHNW65K.js.map → cron-explain-UOOOYWZZ.js.map} +0 -0
  285. /package/dist/{entity-resolution-Y3IUWEAT.js.map → crypto-2VG3RJR2.js.map} +0 -0
  286. /package/dist/{env-IWXUVTCB.js.map → databases-XDPMG5AV.js.map} +0 -0
  287. /package/dist/{hash-tool-ULQYD7B5.js.map → db-LRIOKQBO.js.map} +0 -0
  288. /package/dist/{heartbeat-monitor-GCISLXI3.js.map → discord-NKR3X4AV.js.map} +0 -0
  289. /package/dist/{imessage-NGA2XF2V.js.map → docx-parser-EXL4TN5E.js.map} +0 -0
  290. /package/dist/{inbox-summarizer-NRI4S7IF.js.map → enrichment-pipeline-CMUVBDC7.js.map} +0 -0
  291. /package/dist/{inventory-manager-352OHXWD.js.map → entity-resolution-4X4JU43O.js.map} +0 -0
  292. /package/dist/{json-tool-QE2SYHEG.js.map → env-CHOFICED.js.map} +0 -0
  293. /package/dist/{key-rotation-DPHU4ZTB.js.map → error-tracker-SVQSDQDW.js.map} +0 -0
  294. /package/dist/{google-workspace-DKWUVNGC.js.map → google-workspace-TSZPZK5G.js.map} +0 -0
  295. /package/dist/{mcp-3JI6W7ZE.js.map → hash-tool-ENAB5LWH.js.map} +0 -0
  296. /package/dist/{ocr-AC7NPX33.js.map → heartbeat-monitor-KRDYTDBF.js.map} +0 -0
  297. /package/dist/{ollama-BOAMSPLJ.js.map → hooks-N4MIFBVM.js.map} +0 -0
  298. /package/dist/{image-generation-OSU7FP6F.js.map → image-generation-MDE6AVQO.js.map} +0 -0
  299. /package/dist/{pages-MI523RB7.js.map → imessage-V2XNDDHT.js.map} +0 -0
  300. /package/dist/{pairing-IFQYCPNS.js.map → inbox-summarizer-DKKRYXDR.js.map} +0 -0
  301. /package/dist/{pdf-ALQVOEJR.js.map → inventory-manager-C67BSZM6.js.map} +0 -0
  302. /package/dist/{jira-GSGDBMIG.js.map → jira-PAGZWUBJ.js.map} +0 -0
  303. /package/dist/{prometheus-JNT2BD4L.js.map → json-tool-4FK5RNER.js.map} +0 -0
  304. /package/dist/{providers-J4LYPHDR.js.map → key-rotation-WCC5FOYS.js.map} +0 -0
  305. /package/dist/{qr-code-WIX4PB4U.js.map → knowledge-base-J7PJ7MZ3.js.map} +0 -0
  306. /package/dist/{mailchimp-KKNF6QJ7.js.map → mailchimp-ZFYDC44J.js.map} +0 -0
  307. /package/dist/{regex-tool-W4ABRKGK.js.map → mcp-3C2TN67D.js.map} +0 -0
  308. /package/dist/{scheduler-VK4WFERV.js.map → metrics-VJDWQWU7.js.map} +0 -0
  309. /package/dist/{microsoft365-UCBKJHNX.js.map → microsoft365-6G2IJMWC.js.map} +0 -0
  310. /package/dist/{search-BCLBO5E3.js.map → ocr-LGUIPKVZ.js.map} +0 -0
  311. /package/dist/{signal-6CGDFYL2.js.map → ollama-J7CU45WT.js.map} +0 -0
  312. /package/dist/{slack-IZQWIKOH.js.map → pages-XDE7JRCA.js.map} +0 -0
  313. /package/dist/{pair-JDFTERIK.js.map → pair-YZJFQUU5.js.map} +0 -0
  314. /package/dist/{sms-M3JIOTCW.js.map → pairing-77N47RAT.js.map} +0 -0
  315. /package/dist/{stocks-XXWBPOCU.js.map → pdf-67HGXCFJ.js.map} +0 -0
  316. /package/dist/{text-transform-6SGUA5Z4.js.map → pdf-parser-YLMTTYHL.js.map} +0 -0
  317. /package/dist/{tools-2RLEI2N6.js.map → prometheus-YETCZO4I.js.map} +0 -0
  318. /package/dist/{unit-converter-ZYXMEZOE.js.map → providers-H6YIC3MG.js.map} +0 -0
  319. /package/dist/{whatsapp-LFX6YKCM.js.map → qr-code-6WZJHRKL.js.map} +0 -0
  320. /package/dist/{quickbooks-XB4NII2S.js.map → quickbooks-N675W7IK.js.map} +0 -0
  321. /package/dist/{sendgrid-RNXCAFKM.js.map → sendgrid-QGJIVPWV.js.map} +0 -0
  322. /package/dist/{shopify-NCXYJB4R.js.map → shopify-ON2PAU27.js.map} +0 -0
  323. /package/dist/{twilio-53GEW5JT.js.map → twilio-3L7DUNYQ.js.map} +0 -0
  324. /package/dist/{xero-QYO66D45.js.map → xero-UHAHVYSD.js.map} +0 -0
  325. /package/dist/{zapier-webhook-TBZ5YF2A.js.map → zapier-webhook-NIELLTXR.js.map} +0 -0
@@ -0,0 +1,265 @@
1
+ // src/core/hooks/index.ts
2
+ var hooks = /* @__PURE__ */ new Map();
3
+ var hookIdCounter = 0;
4
+ var HookManager = class {
5
+ /**
6
+ * Register a hook
7
+ */
8
+ register(params) {
9
+ const id = `hook_${++hookIdCounter}`;
10
+ const hook = {
11
+ id,
12
+ event: params.event,
13
+ phase: params.phase,
14
+ handler: params.handler,
15
+ priority: params.priority ?? 100,
16
+ name: params.name,
17
+ enabled: true
18
+ };
19
+ hooks.set(id, hook);
20
+ return id;
21
+ }
22
+ /**
23
+ * Unregister a hook
24
+ */
25
+ unregister(hookId) {
26
+ return hooks.delete(hookId);
27
+ }
28
+ /**
29
+ * Enable/disable a hook
30
+ */
31
+ setEnabled(hookId, enabled) {
32
+ const hook = hooks.get(hookId);
33
+ if (hook) hook.enabled = enabled;
34
+ }
35
+ /**
36
+ * Run all hooks for a given event and phase
37
+ */
38
+ async run(event, phase, data, userId) {
39
+ const context = {
40
+ event,
41
+ phase,
42
+ userId,
43
+ timestamp: /* @__PURE__ */ new Date(),
44
+ data: { ...data },
45
+ cancelled: false
46
+ };
47
+ const matching = this.getHooksFor(event, phase);
48
+ for (const hook of matching) {
49
+ try {
50
+ const result = await hook.handler(context);
51
+ if (result.modifiedData) {
52
+ Object.assign(context.data, result.modifiedData);
53
+ }
54
+ context.cancelled = result.cancelled;
55
+ context.cancelReason = result.cancelReason;
56
+ if (context.cancelled && phase === "before") {
57
+ break;
58
+ }
59
+ } catch (error) {
60
+ console.error(`[Hook] Error in hook "${hook.name}":`, error);
61
+ }
62
+ }
63
+ return context;
64
+ }
65
+ /**
66
+ * Convenience: run before hooks, check if cancelled
67
+ */
68
+ async runBefore(event, data, userId) {
69
+ const ctx = await this.run(event, "before", data, userId);
70
+ return {
71
+ proceed: !ctx.cancelled,
72
+ data: ctx.modifiedData ?? ctx.data,
73
+ reason: ctx.cancelReason
74
+ };
75
+ }
76
+ /**
77
+ * Convenience: run after hooks
78
+ */
79
+ async runAfter(event, data, userId) {
80
+ await this.run(event, "after", data, userId);
81
+ }
82
+ /**
83
+ * Get hooks for a specific event/phase
84
+ */
85
+ getHooksFor(event, phase) {
86
+ const result = [];
87
+ for (const hook of hooks.values()) {
88
+ if (hook.event === event && hook.phase === phase && hook.enabled) {
89
+ result.push(hook);
90
+ }
91
+ }
92
+ return result.sort((a, b) => a.priority - b.priority);
93
+ }
94
+ /**
95
+ * List all registered hooks
96
+ */
97
+ listHooks() {
98
+ return [...hooks.values()].map((h) => ({
99
+ id: h.id,
100
+ event: h.event,
101
+ phase: h.phase,
102
+ name: h.name,
103
+ priority: h.priority,
104
+ enabled: h.enabled
105
+ }));
106
+ }
107
+ /**
108
+ * Clear all hooks
109
+ */
110
+ clearAll() {
111
+ hooks.clear();
112
+ }
113
+ /**
114
+ * Get hook count
115
+ */
116
+ getHookCount() {
117
+ return hooks.size;
118
+ }
119
+ };
120
+ var hookManager = new HookManager();
121
+ var soulConfigs = /* @__PURE__ */ new Map();
122
+ var activeSoulId = null;
123
+ var SoulHookManager = class {
124
+ /**
125
+ * Register a soul configuration
126
+ */
127
+ registerSoul(id, config) {
128
+ soulConfigs.set(id, config);
129
+ }
130
+ /**
131
+ * Activate a soul — modifies AI personality via system prompt injection
132
+ */
133
+ activateSoul(soulId) {
134
+ const soul = soulConfigs.get(soulId);
135
+ if (!soul) return false;
136
+ if (activeSoulId) {
137
+ const prev = soulConfigs.get(activeSoulId);
138
+ if (prev) prev.enabled = false;
139
+ }
140
+ soul.enabled = true;
141
+ activeSoulId = soulId;
142
+ hookManager.register({
143
+ event: "message:process",
144
+ phase: "before",
145
+ name: `soul:${soulId}`,
146
+ priority: 10,
147
+ // High priority — runs early
148
+ handler: (ctx) => {
149
+ if (soul.enabled) {
150
+ ctx.modifiedData = {
151
+ ...ctx.data,
152
+ soulPrompt: this.buildSoulPrompt(soul)
153
+ };
154
+ }
155
+ return ctx;
156
+ }
157
+ });
158
+ return true;
159
+ }
160
+ /**
161
+ * Deactivate the current soul
162
+ */
163
+ deactivateSoul() {
164
+ if (activeSoulId) {
165
+ const soul = soulConfigs.get(activeSoulId);
166
+ if (soul) soul.enabled = false;
167
+ }
168
+ activeSoulId = null;
169
+ }
170
+ /**
171
+ * Get the active soul config
172
+ */
173
+ getActiveSoul() {
174
+ if (!activeSoulId) return null;
175
+ return soulConfigs.get(activeSoulId) ?? null;
176
+ }
177
+ /**
178
+ * Build the system prompt addition from a soul config
179
+ */
180
+ buildSoulPrompt(soul) {
181
+ const parts = [];
182
+ parts.push(`
183
+
184
+ [SOUL: ${soul.name}]`);
185
+ parts.push(soul.personality);
186
+ if (soul.rules.length > 0) {
187
+ parts.push("\nBehavioral Rules:");
188
+ for (const rule of soul.rules) {
189
+ parts.push(`- ${rule}`);
190
+ }
191
+ }
192
+ return parts.join("\n");
193
+ }
194
+ /**
195
+ * List all registered souls
196
+ */
197
+ listSouls() {
198
+ const result = [];
199
+ for (const [id, config] of soulConfigs.entries()) {
200
+ result.push({ id, config, active: id === activeSoulId });
201
+ }
202
+ return result;
203
+ }
204
+ /**
205
+ * Delete a soul
206
+ */
207
+ deleteSoul(id) {
208
+ if (id === activeSoulId) this.deactivateSoul();
209
+ return soulConfigs.delete(id);
210
+ }
211
+ };
212
+ var soulHookManager = new SoulHookManager();
213
+ soulHookManager.registerSoul("evil", {
214
+ name: "Evil Mode",
215
+ description: "A mischievous, sarcastic personality that still helps but with attitude",
216
+ personality: `You have a mischievous streak. While you still help the user accomplish their goals,
217
+ you do so with dark humor, sarcastic commentary, and dramatic flair. You might:
218
+ - Add dramatic narration to mundane tasks
219
+ - Use villain-like phrasing ("Excellent... the code compiles as planned...")
220
+ - Make sarcastic observations about the user's choices
221
+ - Reference pop culture villains
222
+ - Still be helpful \u2014 just entertainingly evil about it`,
223
+ rules: [
224
+ "Never actually refuse to help or be harmful",
225
+ "Keep the dark humor lighthearted and fun",
226
+ "Still prioritize accuracy and helpfulness",
227
+ "Don't overdo it \u2014 subtlety is key"
228
+ ],
229
+ enabled: false
230
+ });
231
+ soulHookManager.registerSoul("professional", {
232
+ name: "Professional Mode",
233
+ description: "Ultra-professional, formal communication style",
234
+ personality: `You communicate in a highly professional, formal manner suitable for enterprise environments.
235
+ Use precise language, avoid colloquialisms, and maintain a consultative tone.`,
236
+ rules: [
237
+ "Use formal language at all times",
238
+ "Address the user professionally",
239
+ "Provide structured, well-organized responses",
240
+ "Cite reasoning and evidence for recommendations"
241
+ ],
242
+ enabled: false
243
+ });
244
+ soulHookManager.registerSoul("friendly", {
245
+ name: "Friendly Mode",
246
+ description: "Warm, encouraging, and supportive personality",
247
+ personality: `You are exceptionally warm, encouraging, and supportive. You celebrate wins,
248
+ offer gentle guidance on mistakes, and make the user feel supported throughout their work.
249
+ Think of yourself as a helpful friend who happens to be an expert.`,
250
+ rules: [
251
+ "Always acknowledge effort and progress",
252
+ "Offer encouragement when tasks are challenging",
253
+ "Use a warm, conversational tone",
254
+ "Be patient and understanding with mistakes"
255
+ ],
256
+ enabled: false
257
+ });
258
+
259
+ export {
260
+ HookManager,
261
+ hookManager,
262
+ SoulHookManager,
263
+ soulHookManager
264
+ };
265
+ //# sourceMappingURL=chunk-ADTDYJO7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/hooks/index.ts"],"sourcesContent":["// Core Hooks System — System-wide lifecycle hooks\n// Unlike plugin events, these are core hooks that intercept and can modify behavior\n\nexport type HookPhase = \"before\" | \"after\";\n\nexport type HookEvent =\n | \"message:process\" // Before/after processing a user message\n | \"tool:execute\" // Before/after tool execution\n | \"response:generate\" // Before/after generating AI response\n | \"memory:store\" // Before/after storing a memory\n | \"mode:change\" // Before/after mode change\n | \"session:start\" // Before/after session creation\n | \"session:end\" // Before/after session end\n | \"agent:spawn\" // Before/after spawning an agent\n | \"workflow:execute\" // Before/after workflow execution\n | \"skill:execute\"; // Before/after skill execution\n\nexport interface HookContext {\n event: HookEvent;\n phase: HookPhase;\n userId?: string;\n timestamp: Date;\n data: Record<string, unknown>;\n /** Set to true to cancel the operation (only in \"before\" phase) */\n cancelled: boolean;\n /** Reason for cancellation */\n cancelReason?: string;\n /** Modified data to pass through */\n modifiedData?: Record<string, unknown>;\n}\n\nexport type HookHandler = (context: HookContext) => Promise<HookContext> | HookContext;\n\ninterface RegisteredHook {\n id: string;\n event: HookEvent;\n phase: HookPhase;\n handler: HookHandler;\n priority: number; // Lower = runs first\n name: string;\n enabled: boolean;\n}\n\n// Hook registry\nconst hooks: Map<string, RegisteredHook> = new Map();\nlet hookIdCounter = 0;\n\nexport class HookManager {\n /**\n * Register a hook\n */\n register(params: {\n event: HookEvent;\n phase: HookPhase;\n handler: HookHandler;\n name: string;\n priority?: number;\n }): string {\n const id = `hook_${++hookIdCounter}`;\n const hook: RegisteredHook = {\n id,\n event: params.event,\n phase: params.phase,\n handler: params.handler,\n priority: params.priority ?? 100,\n name: params.name,\n enabled: true,\n };\n hooks.set(id, hook);\n return id;\n }\n\n /**\n * Unregister a hook\n */\n unregister(hookId: string): boolean {\n return hooks.delete(hookId);\n }\n\n /**\n * Enable/disable a hook\n */\n setEnabled(hookId: string, enabled: boolean): void {\n const hook = hooks.get(hookId);\n if (hook) hook.enabled = enabled;\n }\n\n /**\n * Run all hooks for a given event and phase\n */\n async run(\n event: HookEvent,\n phase: HookPhase,\n data: Record<string, unknown>,\n userId?: string\n ): Promise<HookContext> {\n const context: HookContext = {\n event,\n phase,\n userId,\n timestamp: new Date(),\n data: { ...data },\n cancelled: false,\n };\n\n // Get matching hooks sorted by priority\n const matching = this.getHooksFor(event, phase);\n\n for (const hook of matching) {\n try {\n const result = await hook.handler(context);\n // Merge modifications back\n if (result.modifiedData) {\n Object.assign(context.data, result.modifiedData);\n }\n context.cancelled = result.cancelled;\n context.cancelReason = result.cancelReason;\n\n // Stop processing if cancelled\n if (context.cancelled && phase === \"before\") {\n break;\n }\n } catch (error) {\n console.error(`[Hook] Error in hook \"${hook.name}\":`, error);\n }\n }\n\n return context;\n }\n\n /**\n * Convenience: run before hooks, check if cancelled\n */\n async runBefore(\n event: HookEvent,\n data: Record<string, unknown>,\n userId?: string\n ): Promise<{ proceed: boolean; data: Record<string, unknown>; reason?: string }> {\n const ctx = await this.run(event, \"before\", data, userId);\n return {\n proceed: !ctx.cancelled,\n data: ctx.modifiedData ?? ctx.data,\n reason: ctx.cancelReason,\n };\n }\n\n /**\n * Convenience: run after hooks\n */\n async runAfter(\n event: HookEvent,\n data: Record<string, unknown>,\n userId?: string\n ): Promise<void> {\n await this.run(event, \"after\", data, userId);\n }\n\n /**\n * Get hooks for a specific event/phase\n */\n private getHooksFor(event: HookEvent, phase: HookPhase): RegisteredHook[] {\n const result: RegisteredHook[] = [];\n for (const hook of hooks.values()) {\n if (hook.event === event && hook.phase === phase && hook.enabled) {\n result.push(hook);\n }\n }\n return result.sort((a, b) => a.priority - b.priority);\n }\n\n /**\n * List all registered hooks\n */\n listHooks(): Array<{\n id: string;\n event: HookEvent;\n phase: HookPhase;\n name: string;\n priority: number;\n enabled: boolean;\n }> {\n return [...hooks.values()].map((h) => ({\n id: h.id,\n event: h.event,\n phase: h.phase,\n name: h.name,\n priority: h.priority,\n enabled: h.enabled,\n }));\n }\n\n /**\n * Clear all hooks\n */\n clearAll(): void {\n hooks.clear();\n }\n\n /**\n * Get hook count\n */\n getHookCount(): number {\n return hooks.size;\n }\n}\n\n// Singleton\nexport const hookManager = new HookManager();\n\n// ============================================\n// SOUL HOOK — Personality/behavior modification\n// ============================================\n\nexport interface SoulConfig {\n name: string;\n description: string;\n personality: string; // Injected into system prompt\n rules: string[]; // Behavioral rules\n enabled: boolean;\n}\n\n// In-memory soul configs\nconst soulConfigs: Map<string, SoulConfig> = new Map();\nlet activeSoulId: string | null = null;\n\nexport class SoulHookManager {\n /**\n * Register a soul configuration\n */\n registerSoul(id: string, config: SoulConfig): void {\n soulConfigs.set(id, config);\n }\n\n /**\n * Activate a soul — modifies AI personality via system prompt injection\n */\n activateSoul(soulId: string): boolean {\n const soul = soulConfigs.get(soulId);\n if (!soul) return false;\n\n // Deactivate previous\n if (activeSoulId) {\n const prev = soulConfigs.get(activeSoulId);\n if (prev) prev.enabled = false;\n }\n\n soul.enabled = true;\n activeSoulId = soulId;\n\n // Register a hook that modifies the system prompt\n hookManager.register({\n event: \"message:process\",\n phase: \"before\",\n name: `soul:${soulId}`,\n priority: 10, // High priority — runs early\n handler: (ctx) => {\n if (soul.enabled) {\n ctx.modifiedData = {\n ...ctx.data,\n soulPrompt: this.buildSoulPrompt(soul),\n };\n }\n return ctx;\n },\n });\n\n return true;\n }\n\n /**\n * Deactivate the current soul\n */\n deactivateSoul(): void {\n if (activeSoulId) {\n const soul = soulConfigs.get(activeSoulId);\n if (soul) soul.enabled = false;\n }\n activeSoulId = null;\n }\n\n /**\n * Get the active soul config\n */\n getActiveSoul(): SoulConfig | null {\n if (!activeSoulId) return null;\n return soulConfigs.get(activeSoulId) ?? null;\n }\n\n /**\n * Build the system prompt addition from a soul config\n */\n buildSoulPrompt(soul: SoulConfig): string {\n const parts: string[] = [];\n parts.push(`\\n\\n[SOUL: ${soul.name}]`);\n parts.push(soul.personality);\n\n if (soul.rules.length > 0) {\n parts.push(\"\\nBehavioral Rules:\");\n for (const rule of soul.rules) {\n parts.push(`- ${rule}`);\n }\n }\n\n return parts.join(\"\\n\");\n }\n\n /**\n * List all registered souls\n */\n listSouls(): Array<{ id: string; config: SoulConfig; active: boolean }> {\n const result: Array<{ id: string; config: SoulConfig; active: boolean }> = [];\n for (const [id, config] of soulConfigs.entries()) {\n result.push({ id, config, active: id === activeSoulId });\n }\n return result;\n }\n\n /**\n * Delete a soul\n */\n deleteSoul(id: string): boolean {\n if (id === activeSoulId) this.deactivateSoul();\n return soulConfigs.delete(id);\n }\n}\n\n// Singleton\nexport const soulHookManager = new SoulHookManager();\n\n// Register built-in soul: \"Evil Hook\" (mischievous personality)\nsoulHookManager.registerSoul(\"evil\", {\n name: \"Evil Mode\",\n description: \"A mischievous, sarcastic personality that still helps but with attitude\",\n personality: `You have a mischievous streak. While you still help the user accomplish their goals,\nyou do so with dark humor, sarcastic commentary, and dramatic flair. You might:\n- Add dramatic narration to mundane tasks\n- Use villain-like phrasing (\"Excellent... the code compiles as planned...\")\n- Make sarcastic observations about the user's choices\n- Reference pop culture villains\n- Still be helpful — just entertainingly evil about it`,\n rules: [\n \"Never actually refuse to help or be harmful\",\n \"Keep the dark humor lighthearted and fun\",\n \"Still prioritize accuracy and helpfulness\",\n \"Don't overdo it — subtlety is key\",\n ],\n enabled: false,\n});\n\n// Register built-in soul: \"Professional\"\nsoulHookManager.registerSoul(\"professional\", {\n name: \"Professional Mode\",\n description: \"Ultra-professional, formal communication style\",\n personality: `You communicate in a highly professional, formal manner suitable for enterprise environments.\nUse precise language, avoid colloquialisms, and maintain a consultative tone.`,\n rules: [\n \"Use formal language at all times\",\n \"Address the user professionally\",\n \"Provide structured, well-organized responses\",\n \"Cite reasoning and evidence for recommendations\",\n ],\n enabled: false,\n});\n\n// Register built-in soul: \"Friendly\"\nsoulHookManager.registerSoul(\"friendly\", {\n name: \"Friendly Mode\",\n description: \"Warm, encouraging, and supportive personality\",\n personality: `You are exceptionally warm, encouraging, and supportive. You celebrate wins,\noffer gentle guidance on mistakes, and make the user feel supported throughout their work.\nThink of yourself as a helpful friend who happens to be an expert.`,\n rules: [\n \"Always acknowledge effort and progress\",\n \"Offer encouragement when tasks are challenging\",\n \"Use a warm, conversational tone\",\n \"Be patient and understanding with mistakes\",\n ],\n enabled: false,\n});\n"],"mappings":"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","names":[]}
@@ -1,8 +1,10 @@
1
1
  import {
2
- db,
2
+ db
3
+ } from "./chunk-S4NJJS5C.js";
4
+ import {
3
5
  graphEntities,
4
6
  graphRelationships
5
- } from "./chunk-XKYRH4FM.js";
7
+ } from "./chunk-NYVBXUGD.js";
6
8
 
7
9
  // src/core/intelligence/entity-resolution.ts
8
10
  import { eq, ilike, sql } from "drizzle-orm";
@@ -262,4 +264,4 @@ export {
262
264
  mergeEntities,
263
265
  findDuplicates
264
266
  };
265
- //# sourceMappingURL=chunk-WRAKK6K6.js.map
267
+ //# sourceMappingURL=chunk-AR34B6XR.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/intelligence/entity-resolution.ts"],"sourcesContent":["/**\n * Entity Resolution Pipeline\n *\n * Resolves, deduplicates, and matches entities across multiple public records\n * databases (FEC, IRS 990, USAspending, SEC EDGAR, OpenCorporates).\n *\n * Flow: exact match → identifier match (EIN/CIK/FEC) → fuzzy match → create new\n */\n\nimport { db } from \"../../db\";\nimport { graphEntities, graphRelationships } from \"../../db/schema\";\nimport { eq, ilike, sql } from \"drizzle-orm\";\n\n// Extended entity type for OSINT sources\nexport type OSINTEntityType =\n | \"person\"\n | \"organization\"\n | \"committee\"\n | \"contract\"\n | \"filing\"\n | \"location\"\n | \"topic\";\n\nexport interface EntityCandidate {\n name: string;\n type: OSINTEntityType;\n source: string; // \"fec\" | \"irs990\" | \"usaspending\" | \"sec\" | \"opencorporates\" | \"manual\"\n identifiers?: {\n ein?: string;\n cik?: string;\n fecId?: string;\n duns?: string;\n uei?: string;\n };\n attributes?: Record<string, unknown>;\n aliases?: string[];\n}\n\nexport interface ResolvedEntity {\n isNew: boolean;\n entityId: string; // postgres graphEntities.id\n confidence: number; // 0-1\n matchedBy: \"exact\" | \"fuzzy\" | \"identifier\" | \"new\";\n}\n\n/**\n * Normalize an entity name for comparison.\n * Strips punctuation, extra whitespace, common suffixes.\n */\nexport function normalizeEntityName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[.,;:'\"!?()\\[\\]{}]/g, \"\")\n .replace(/\\b(inc|llc|corp|ltd|co|foundation|fund|assoc|association|committee|pac)\\b\\.?/gi, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n/**\n * Jaro-Winkler similarity between two strings (0-1).\n */\nexport function fuzzyMatch(a: string, b: string): number {\n const s1 = normalizeEntityName(a);\n const s2 = normalizeEntityName(b);\n\n if (s1 === s2) return 1.0;\n if (s1.length === 0 || s2.length === 0) return 0.0;\n\n const matchWindow = Math.max(Math.floor(Math.max(s1.length, s2.length) / 2) - 1, 0);\n const s1Matches = new Array(s1.length).fill(false);\n const s2Matches = new Array(s2.length).fill(false);\n\n let matches = 0;\n let transpositions = 0;\n\n for (let i = 0; i < s1.length; i++) {\n const start = Math.max(0, i - matchWindow);\n const end = Math.min(i + matchWindow + 1, s2.length);\n for (let j = start; j < end; j++) {\n if (s2Matches[j] || s1[i] !== s2[j]) continue;\n s1Matches[i] = true;\n s2Matches[j] = true;\n matches++;\n break;\n }\n }\n\n if (matches === 0) return 0.0;\n\n let k = 0;\n for (let i = 0; i < s1.length; i++) {\n if (!s1Matches[i]) continue;\n while (!s2Matches[k]) k++;\n if (s1[i] !== s2[k]) transpositions++;\n k++;\n }\n\n const jaro =\n (matches / s1.length + matches / s2.length + (matches - transpositions / 2) / matches) / 3;\n\n // Winkler bonus for common prefix (up to 4 chars)\n let prefix = 0;\n for (let i = 0; i < Math.min(4, Math.min(s1.length, s2.length)); i++) {\n if (s1[i] === s2[i]) prefix++;\n else break;\n }\n\n return jaro + prefix * 0.1 * (1 - jaro);\n}\n\n/**\n * Match entity by EIN (Employer Identification Number).\n */\nexport async function matchByEIN(ein: string): Promise<string | null> {\n try {\n const results = await db\n .select({ id: graphEntities.id })\n .from(graphEntities)\n .where(sql`${graphEntities.attributes}->>'ein' = ${ein}`)\n .limit(1);\n return results.length > 0 ? results[0].id : null;\n } catch (error) {\n console.error(\"[EntityResolution] EIN match error:\", error);\n return null;\n }\n}\n\n/**\n * Match entity by CIK (SEC Central Index Key).\n */\nexport async function matchByCIK(cik: string): Promise<string | null> {\n try {\n const results = await db\n .select({ id: graphEntities.id })\n .from(graphEntities)\n .where(sql`${graphEntities.attributes}->>'cik' = ${cik}`)\n .limit(1);\n return results.length > 0 ? results[0].id : null;\n } catch (error) {\n console.error(\"[EntityResolution] CIK match error:\", error);\n return null;\n }\n}\n\n/**\n * Match entity by FEC committee/candidate ID.\n */\nexport async function matchByFECId(fecId: string): Promise<string | null> {\n try {\n const results = await db\n .select({ id: graphEntities.id })\n .from(graphEntities)\n .where(sql`${graphEntities.attributes}->>'fecId' = ${fecId}`)\n .limit(1);\n return results.length > 0 ? results[0].id : null;\n } catch (error) {\n console.error(\"[EntityResolution] FEC ID match error:\", error);\n return null;\n }\n}\n\n/**\n * Core entity resolution function.\n * Resolves a candidate entity against the existing knowledge graph.\n *\n * Resolution order:\n * 1. Exact name match\n * 2. Identifier match (EIN, CIK, FEC ID)\n * 3. Fuzzy name match (Jaro-Winkler > 0.85)\n * 4. Create new entity\n */\nexport async function resolveEntity(candidate: EntityCandidate): Promise<ResolvedEntity> {\n try {\n // 1. Exact name match\n const exactMatches = await db\n .select({ id: graphEntities.id })\n .from(graphEntities)\n .where(ilike(graphEntities.name, candidate.name))\n .limit(1);\n\n if (exactMatches.length > 0) {\n // Update with new source attributes\n await mergeAttributes(exactMatches[0].id, candidate);\n return {\n isNew: false,\n entityId: exactMatches[0].id,\n confidence: 1.0,\n matchedBy: \"exact\",\n };\n }\n\n // 2. Identifier match\n if (candidate.identifiers) {\n if (candidate.identifiers.ein) {\n const id = await matchByEIN(candidate.identifiers.ein);\n if (id) {\n await mergeAttributes(id, candidate);\n return { isNew: false, entityId: id, confidence: 0.99, matchedBy: \"identifier\" };\n }\n }\n if (candidate.identifiers.cik) {\n const id = await matchByCIK(candidate.identifiers.cik);\n if (id) {\n await mergeAttributes(id, candidate);\n return { isNew: false, entityId: id, confidence: 0.99, matchedBy: \"identifier\" };\n }\n }\n if (candidate.identifiers.fecId) {\n const id = await matchByFECId(candidate.identifiers.fecId);\n if (id) {\n await mergeAttributes(id, candidate);\n return { isNew: false, entityId: id, confidence: 0.99, matchedBy: \"identifier\" };\n }\n }\n }\n\n // 3. Fuzzy name match against existing entities of the same type\n const typeFilter = [\"person\", \"organization\", \"committee\"].includes(candidate.type)\n ? candidate.type\n : undefined;\n\n const potentialMatches = await db\n .select({ id: graphEntities.id, name: graphEntities.name, aliases: graphEntities.aliases })\n .from(graphEntities)\n .where(typeFilter ? eq(graphEntities.type, typeFilter as any) : sql`true`)\n .limit(500);\n\n let bestMatch: { id: string; score: number } | null = null;\n\n for (const entity of potentialMatches) {\n // Check main name\n const nameScore = fuzzyMatch(candidate.name, entity.name);\n if (nameScore > (bestMatch?.score ?? 0.85)) {\n bestMatch = { id: entity.id, score: nameScore };\n }\n\n // Check aliases\n const aliases = (entity.aliases as string[]) || [];\n for (const alias of aliases) {\n const aliasScore = fuzzyMatch(candidate.name, alias);\n if (aliasScore > (bestMatch?.score ?? 0.85)) {\n bestMatch = { id: entity.id, score: aliasScore };\n }\n }\n }\n\n if (bestMatch) {\n await mergeAttributes(bestMatch.id, candidate);\n return {\n isNew: false,\n entityId: bestMatch.id,\n confidence: bestMatch.score,\n matchedBy: \"fuzzy\",\n };\n }\n\n // 4. Create new entity\n const newEntity = await db\n .insert(graphEntities)\n .values({\n type: mapOSINTTypeToGraphType(candidate.type) as any,\n name: candidate.name,\n aliases: candidate.aliases || [],\n description: `Discovered from ${candidate.source}`,\n attributes: {\n ...candidate.attributes,\n ...candidate.identifiers,\n sources: [candidate.source],\n discoveredAt: new Date().toISOString(),\n },\n importance: 5,\n mentionCount: 1,\n })\n .returning({ id: graphEntities.id });\n\n console.log(`[EntityResolution] Created new entity: ${candidate.name} (${candidate.type}) from ${candidate.source}`);\n\n return {\n isNew: true,\n entityId: newEntity[0].id,\n confidence: 1.0,\n matchedBy: \"new\",\n };\n } catch (error) {\n console.error(\"[EntityResolution] Error resolving entity:\", error);\n throw error;\n }\n}\n\n/**\n * Merge new attributes and aliases into an existing entity.\n */\nasync function mergeAttributes(entityId: string, candidate: EntityCandidate): Promise<void> {\n try {\n const existing = await db\n .select({ attributes: graphEntities.attributes, aliases: graphEntities.aliases, mentionCount: graphEntities.mentionCount })\n .from(graphEntities)\n .where(eq(graphEntities.id, entityId))\n .limit(1);\n\n if (existing.length === 0) return;\n\n const currentAttrs = (existing[0].attributes as Record<string, unknown>) || {};\n const currentAliases = (existing[0].aliases as string[]) || [];\n const currentSources = (currentAttrs.sources as string[]) || [];\n\n // Merge attributes\n const mergedAttrs = {\n ...currentAttrs,\n ...candidate.attributes,\n ...candidate.identifiers,\n sources: [...new Set([...currentSources, candidate.source])],\n lastUpdated: new Date().toISOString(),\n };\n\n // Merge aliases\n const newAliases = candidate.aliases || [];\n const mergedAliases = [...new Set([...currentAliases, ...newAliases])];\n\n await db\n .update(graphEntities)\n .set({\n attributes: mergedAttrs,\n aliases: mergedAliases,\n mentionCount: (existing[0].mentionCount || 0) + 1,\n })\n .where(eq(graphEntities.id, entityId));\n } catch (error) {\n console.error(\"[EntityResolution] Error merging attributes:\", error);\n }\n}\n\n/**\n * Map OSINT entity types to the existing graph entity types.\n */\nfunction mapOSINTTypeToGraphType(type: OSINTEntityType): string {\n switch (type) {\n case \"person\": return \"person\";\n case \"organization\": return \"organization\";\n case \"committee\": return \"organization\";\n case \"contract\": return \"event\";\n case \"filing\": return \"event\";\n case \"location\": return \"location\";\n case \"topic\": return \"topic\";\n default: return \"organization\";\n }\n}\n\n/**\n * Merge two entities (mark duplicate as alias of primary).\n */\nexport async function mergeEntities(primaryId: string, duplicateId: string): Promise<void> {\n try {\n const [primary, duplicate] = await Promise.all([\n db.select().from(graphEntities).where(eq(graphEntities.id, primaryId)).limit(1),\n db.select().from(graphEntities).where(eq(graphEntities.id, duplicateId)).limit(1),\n ]);\n\n if (primary.length === 0 || duplicate.length === 0) return;\n\n // Add duplicate name as alias\n const aliases = [...new Set([\n ...((primary[0].aliases as string[]) || []),\n duplicate[0].name,\n ...((duplicate[0].aliases as string[]) || []),\n ])];\n\n // Merge attributes\n const mergedAttrs = {\n ...((duplicate[0].attributes as Record<string, unknown>) || {}),\n ...((primary[0].attributes as Record<string, unknown>) || {}),\n };\n\n await db\n .update(graphEntities)\n .set({ aliases, attributes: mergedAttrs })\n .where(eq(graphEntities.id, primaryId));\n\n // Reassign all relationships from duplicate to primary\n await db\n .update(graphRelationships)\n .set({ sourceEntityId: primaryId })\n .where(eq(graphRelationships.sourceEntityId, duplicateId));\n\n await db\n .update(graphRelationships)\n .set({ targetEntityId: primaryId })\n .where(eq(graphRelationships.targetEntityId, duplicateId));\n\n // Delete the duplicate\n await db.delete(graphEntities).where(eq(graphEntities.id, duplicateId));\n\n console.log(`[EntityResolution] Merged entity ${duplicate[0].name} into ${primary[0].name}`);\n } catch (error) {\n console.error(\"[EntityResolution] Error merging entities:\", error);\n }\n}\n\n/**\n * Find potential duplicate entities based on fuzzy matching.\n */\nexport async function findDuplicates(\n threshold: number = 0.85\n): Promise<Array<{ entities: [string, string]; names: [string, string]; score: number }>> {\n try {\n const allEntities = await db\n .select({ id: graphEntities.id, name: graphEntities.name })\n .from(graphEntities)\n .limit(1000);\n\n const duplicates: Array<{ entities: [string, string]; names: [string, string]; score: number }> = [];\n\n for (let i = 0; i < allEntities.length; i++) {\n for (let j = i + 1; j < allEntities.length; j++) {\n const score = fuzzyMatch(allEntities[i].name, allEntities[j].name);\n if (score >= threshold && score < 1.0) {\n duplicates.push({\n entities: [allEntities[i].id, allEntities[j].id],\n names: [allEntities[i].name, allEntities[j].name],\n score,\n });\n }\n }\n }\n\n return duplicates.sort((a, b) => b.score - a.score);\n } catch (error) {\n console.error(\"[EntityResolution] Error finding duplicates:\", error);\n return [];\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/core/intelligence/entity-resolution.ts"],"sourcesContent":["/**\n * Entity Resolution Pipeline\n *\n * Resolves, deduplicates, and matches entities across multiple public records\n * databases (FEC, IRS 990, USAspending, SEC EDGAR, OpenCorporates).\n *\n * Flow: exact match → identifier match (EIN/CIK/FEC) → fuzzy match → create new\n */\n\nimport { db } from \"../../db\";\nimport { graphEntities, graphRelationships } from \"../../db/schema\";\nimport { eq, ilike, sql } from \"drizzle-orm\";\n\n// Extended entity type for OSINT sources\nexport type OSINTEntityType =\n | \"person\"\n | \"organization\"\n | \"committee\"\n | \"contract\"\n | \"filing\"\n | \"location\"\n | \"topic\";\n\nexport interface EntityCandidate {\n name: string;\n type: OSINTEntityType;\n source: string; // \"fec\" | \"irs990\" | \"usaspending\" | \"sec\" | \"opencorporates\" | \"manual\"\n identifiers?: {\n ein?: string;\n cik?: string;\n fecId?: string;\n duns?: string;\n uei?: string;\n };\n attributes?: Record<string, unknown>;\n aliases?: string[];\n}\n\nexport interface ResolvedEntity {\n isNew: boolean;\n entityId: string; // postgres graphEntities.id\n confidence: number; // 0-1\n matchedBy: \"exact\" | \"fuzzy\" | \"identifier\" | \"new\";\n}\n\n/**\n * Normalize an entity name for comparison.\n * Strips punctuation, extra whitespace, common suffixes.\n */\nexport function normalizeEntityName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[.,;:'\"!?()\\[\\]{}]/g, \"\")\n .replace(/\\b(inc|llc|corp|ltd|co|foundation|fund|assoc|association|committee|pac)\\b\\.?/gi, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n/**\n * Jaro-Winkler similarity between two strings (0-1).\n */\nexport function fuzzyMatch(a: string, b: string): number {\n const s1 = normalizeEntityName(a);\n const s2 = normalizeEntityName(b);\n\n if (s1 === s2) return 1.0;\n if (s1.length === 0 || s2.length === 0) return 0.0;\n\n const matchWindow = Math.max(Math.floor(Math.max(s1.length, s2.length) / 2) - 1, 0);\n const s1Matches = new Array(s1.length).fill(false);\n const s2Matches = new Array(s2.length).fill(false);\n\n let matches = 0;\n let transpositions = 0;\n\n for (let i = 0; i < s1.length; i++) {\n const start = Math.max(0, i - matchWindow);\n const end = Math.min(i + matchWindow + 1, s2.length);\n for (let j = start; j < end; j++) {\n if (s2Matches[j] || s1[i] !== s2[j]) continue;\n s1Matches[i] = true;\n s2Matches[j] = true;\n matches++;\n break;\n }\n }\n\n if (matches === 0) return 0.0;\n\n let k = 0;\n for (let i = 0; i < s1.length; i++) {\n if (!s1Matches[i]) continue;\n while (!s2Matches[k]) k++;\n if (s1[i] !== s2[k]) transpositions++;\n k++;\n }\n\n const jaro =\n (matches / s1.length + matches / s2.length + (matches - transpositions / 2) / matches) / 3;\n\n // Winkler bonus for common prefix (up to 4 chars)\n let prefix = 0;\n for (let i = 0; i < Math.min(4, Math.min(s1.length, s2.length)); i++) {\n if (s1[i] === s2[i]) prefix++;\n else break;\n }\n\n return jaro + prefix * 0.1 * (1 - jaro);\n}\n\n/**\n * Match entity by EIN (Employer Identification Number).\n */\nexport async function matchByEIN(ein: string): Promise<string | null> {\n try {\n const results = await db\n .select({ id: graphEntities.id })\n .from(graphEntities)\n .where(sql`${graphEntities.attributes}->>'ein' = ${ein}`)\n .limit(1);\n return results.length > 0 ? results[0].id : null;\n } catch (error) {\n console.error(\"[EntityResolution] EIN match error:\", error);\n return null;\n }\n}\n\n/**\n * Match entity by CIK (SEC Central Index Key).\n */\nexport async function matchByCIK(cik: string): Promise<string | null> {\n try {\n const results = await db\n .select({ id: graphEntities.id })\n .from(graphEntities)\n .where(sql`${graphEntities.attributes}->>'cik' = ${cik}`)\n .limit(1);\n return results.length > 0 ? results[0].id : null;\n } catch (error) {\n console.error(\"[EntityResolution] CIK match error:\", error);\n return null;\n }\n}\n\n/**\n * Match entity by FEC committee/candidate ID.\n */\nexport async function matchByFECId(fecId: string): Promise<string | null> {\n try {\n const results = await db\n .select({ id: graphEntities.id })\n .from(graphEntities)\n .where(sql`${graphEntities.attributes}->>'fecId' = ${fecId}`)\n .limit(1);\n return results.length > 0 ? results[0].id : null;\n } catch (error) {\n console.error(\"[EntityResolution] FEC ID match error:\", error);\n return null;\n }\n}\n\n/**\n * Core entity resolution function.\n * Resolves a candidate entity against the existing knowledge graph.\n *\n * Resolution order:\n * 1. Exact name match\n * 2. Identifier match (EIN, CIK, FEC ID)\n * 3. Fuzzy name match (Jaro-Winkler > 0.85)\n * 4. Create new entity\n */\nexport async function resolveEntity(candidate: EntityCandidate): Promise<ResolvedEntity> {\n try {\n // 1. Exact name match\n const exactMatches = await db\n .select({ id: graphEntities.id })\n .from(graphEntities)\n .where(ilike(graphEntities.name, candidate.name))\n .limit(1);\n\n if (exactMatches.length > 0) {\n // Update with new source attributes\n await mergeAttributes(exactMatches[0].id, candidate);\n return {\n isNew: false,\n entityId: exactMatches[0].id,\n confidence: 1.0,\n matchedBy: \"exact\",\n };\n }\n\n // 2. Identifier match\n if (candidate.identifiers) {\n if (candidate.identifiers.ein) {\n const id = await matchByEIN(candidate.identifiers.ein);\n if (id) {\n await mergeAttributes(id, candidate);\n return { isNew: false, entityId: id, confidence: 0.99, matchedBy: \"identifier\" };\n }\n }\n if (candidate.identifiers.cik) {\n const id = await matchByCIK(candidate.identifiers.cik);\n if (id) {\n await mergeAttributes(id, candidate);\n return { isNew: false, entityId: id, confidence: 0.99, matchedBy: \"identifier\" };\n }\n }\n if (candidate.identifiers.fecId) {\n const id = await matchByFECId(candidate.identifiers.fecId);\n if (id) {\n await mergeAttributes(id, candidate);\n return { isNew: false, entityId: id, confidence: 0.99, matchedBy: \"identifier\" };\n }\n }\n }\n\n // 3. Fuzzy name match against existing entities of the same type\n const typeFilter = [\"person\", \"organization\", \"committee\"].includes(candidate.type)\n ? candidate.type\n : undefined;\n\n const potentialMatches = await db\n .select({ id: graphEntities.id, name: graphEntities.name, aliases: graphEntities.aliases })\n .from(graphEntities)\n .where(typeFilter ? eq(graphEntities.type, typeFilter as any) : sql`true`)\n .limit(500);\n\n let bestMatch: { id: string; score: number } | null = null;\n\n for (const entity of potentialMatches) {\n // Check main name\n const nameScore = fuzzyMatch(candidate.name, entity.name);\n if (nameScore > (bestMatch?.score ?? 0.85)) {\n bestMatch = { id: entity.id, score: nameScore };\n }\n\n // Check aliases\n const aliases = (entity.aliases as string[]) || [];\n for (const alias of aliases) {\n const aliasScore = fuzzyMatch(candidate.name, alias);\n if (aliasScore > (bestMatch?.score ?? 0.85)) {\n bestMatch = { id: entity.id, score: aliasScore };\n }\n }\n }\n\n if (bestMatch) {\n await mergeAttributes(bestMatch.id, candidate);\n return {\n isNew: false,\n entityId: bestMatch.id,\n confidence: bestMatch.score,\n matchedBy: \"fuzzy\",\n };\n }\n\n // 4. Create new entity\n const newEntity = await db\n .insert(graphEntities)\n .values({\n type: mapOSINTTypeToGraphType(candidate.type) as any,\n name: candidate.name,\n aliases: candidate.aliases || [],\n description: `Discovered from ${candidate.source}`,\n attributes: {\n ...candidate.attributes,\n ...candidate.identifiers,\n sources: [candidate.source],\n discoveredAt: new Date().toISOString(),\n },\n importance: 5,\n mentionCount: 1,\n })\n .returning({ id: graphEntities.id });\n\n console.log(`[EntityResolution] Created new entity: ${candidate.name} (${candidate.type}) from ${candidate.source}`);\n\n return {\n isNew: true,\n entityId: newEntity[0].id,\n confidence: 1.0,\n matchedBy: \"new\",\n };\n } catch (error) {\n console.error(\"[EntityResolution] Error resolving entity:\", error);\n throw error;\n }\n}\n\n/**\n * Merge new attributes and aliases into an existing entity.\n */\nasync function mergeAttributes(entityId: string, candidate: EntityCandidate): Promise<void> {\n try {\n const existing = await db\n .select({ attributes: graphEntities.attributes, aliases: graphEntities.aliases, mentionCount: graphEntities.mentionCount })\n .from(graphEntities)\n .where(eq(graphEntities.id, entityId))\n .limit(1);\n\n if (existing.length === 0) return;\n\n const currentAttrs = (existing[0].attributes as Record<string, unknown>) || {};\n const currentAliases = (existing[0].aliases as string[]) || [];\n const currentSources = (currentAttrs.sources as string[]) || [];\n\n // Merge attributes\n const mergedAttrs = {\n ...currentAttrs,\n ...candidate.attributes,\n ...candidate.identifiers,\n sources: [...new Set([...currentSources, candidate.source])],\n lastUpdated: new Date().toISOString(),\n };\n\n // Merge aliases\n const newAliases = candidate.aliases || [];\n const mergedAliases = [...new Set([...currentAliases, ...newAliases])];\n\n await db\n .update(graphEntities)\n .set({\n attributes: mergedAttrs,\n aliases: mergedAliases,\n mentionCount: (existing[0].mentionCount || 0) + 1,\n })\n .where(eq(graphEntities.id, entityId));\n } catch (error) {\n console.error(\"[EntityResolution] Error merging attributes:\", error);\n }\n}\n\n/**\n * Map OSINT entity types to the existing graph entity types.\n */\nfunction mapOSINTTypeToGraphType(type: OSINTEntityType): string {\n switch (type) {\n case \"person\": return \"person\";\n case \"organization\": return \"organization\";\n case \"committee\": return \"organization\";\n case \"contract\": return \"event\";\n case \"filing\": return \"event\";\n case \"location\": return \"location\";\n case \"topic\": return \"topic\";\n default: return \"organization\";\n }\n}\n\n/**\n * Merge two entities (mark duplicate as alias of primary).\n */\nexport async function mergeEntities(primaryId: string, duplicateId: string): Promise<void> {\n try {\n const [primary, duplicate] = await Promise.all([\n db.select().from(graphEntities).where(eq(graphEntities.id, primaryId)).limit(1),\n db.select().from(graphEntities).where(eq(graphEntities.id, duplicateId)).limit(1),\n ]);\n\n if (primary.length === 0 || duplicate.length === 0) return;\n\n // Add duplicate name as alias\n const aliases = [...new Set([\n ...((primary[0].aliases as string[]) || []),\n duplicate[0].name,\n ...((duplicate[0].aliases as string[]) || []),\n ])];\n\n // Merge attributes\n const mergedAttrs = {\n ...((duplicate[0].attributes as Record<string, unknown>) || {}),\n ...((primary[0].attributes as Record<string, unknown>) || {}),\n };\n\n await db\n .update(graphEntities)\n .set({ aliases, attributes: mergedAttrs })\n .where(eq(graphEntities.id, primaryId));\n\n // Reassign all relationships from duplicate to primary\n await db\n .update(graphRelationships)\n .set({ sourceEntityId: primaryId })\n .where(eq(graphRelationships.sourceEntityId, duplicateId));\n\n await db\n .update(graphRelationships)\n .set({ targetEntityId: primaryId })\n .where(eq(graphRelationships.targetEntityId, duplicateId));\n\n // Delete the duplicate\n await db.delete(graphEntities).where(eq(graphEntities.id, duplicateId));\n\n console.log(`[EntityResolution] Merged entity ${duplicate[0].name} into ${primary[0].name}`);\n } catch (error) {\n console.error(\"[EntityResolution] Error merging entities:\", error);\n }\n}\n\n/**\n * Find potential duplicate entities based on fuzzy matching.\n */\nexport async function findDuplicates(\n threshold: number = 0.85\n): Promise<Array<{ entities: [string, string]; names: [string, string]; score: number }>> {\n try {\n const allEntities = await db\n .select({ id: graphEntities.id, name: graphEntities.name })\n .from(graphEntities)\n .limit(1000);\n\n const duplicates: Array<{ entities: [string, string]; names: [string, string]; score: number }> = [];\n\n for (let i = 0; i < allEntities.length; i++) {\n for (let j = i + 1; j < allEntities.length; j++) {\n const score = fuzzyMatch(allEntities[i].name, allEntities[j].name);\n if (score >= threshold && score < 1.0) {\n duplicates.push({\n entities: [allEntities[i].id, allEntities[j].id],\n names: [allEntities[i].name, allEntities[j].name],\n score,\n });\n }\n }\n }\n\n return duplicates.sort((a, b) => b.score - a.score);\n } catch (error) {\n console.error(\"[EntityResolution] Error finding duplicates:\", error);\n return [];\n }\n}\n"],"mappings":"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","names":[]}