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 @@
1
+ {"version":3,"sources":["../src/integrations/notion/search.ts"],"sourcesContent":["import { getNotionClient } from \"./client\";\n\n/**\n * Search functionality for Notion workspace\n * Supports searching across pages and databases\n */\n\n// Type definitions for API responses\ninterface PageObjectResponse {\n object: \"page\";\n id: string;\n url: string;\n created_time: string;\n last_edited_time: string;\n archived: boolean;\n icon?: { type: string; emoji?: string; external?: { url: string } };\n cover?: { type: string; external?: { url: string }; file?: { url: string } };\n parent: { type: string; page_id?: string; database_id?: string };\n properties: Record<string, any>;\n}\n\ninterface DatabaseObjectResponse {\n object: \"database\";\n id: string;\n url: string;\n title: Array<{ plain_text: string }>;\n description: Array<{ plain_text: string }>;\n created_time: string;\n last_edited_time: string;\n is_inline: boolean;\n icon?: { type: string; emoji?: string; external?: { url: string } };\n cover?: { type: string; external?: { url: string }; file?: { url: string } };\n parent: { type: string; page_id?: string };\n}\n\ninterface SearchParams {\n query?: string;\n filter?: any;\n sort?: any;\n start_cursor?: string;\n page_size?: number;\n}\n\nexport type SearchObjectType = \"page\" | \"database\";\n\nexport interface SearchOptions {\n query?: string;\n filter?: {\n value: SearchObjectType;\n property: \"object\";\n };\n sort?: {\n direction: \"ascending\" | \"descending\";\n timestamp: \"last_edited_time\";\n };\n startCursor?: string;\n pageSize?: number;\n}\n\nexport interface SearchResultPage {\n type: \"page\";\n id: string;\n url: string;\n title: string;\n createdTime: string;\n lastEditedTime: string;\n archived: boolean;\n icon?: string;\n cover?: string;\n parent: {\n type: \"page\" | \"database\" | \"workspace\";\n id?: string;\n };\n}\n\nexport interface SearchResultDatabase {\n type: \"database\";\n id: string;\n url: string;\n title: string;\n description: string;\n createdTime: string;\n lastEditedTime: string;\n isInline: boolean;\n icon?: string;\n cover?: string;\n parent: {\n type: \"page\" | \"workspace\";\n id?: string;\n };\n}\n\nexport type SearchResult = SearchResultPage | SearchResultDatabase;\n\nexport interface SearchResponse {\n results: SearchResult[];\n hasMore: boolean;\n nextCursor: string | null;\n}\n\n/**\n * Extract title from page properties\n */\nfunction extractPageTitle(properties: Record<string, any>): string {\n for (const value of Object.values(properties)) {\n if (value?.type === \"title\" && Array.isArray(value.title)) {\n return value.title.map((t: any) => t.plain_text || \"\").join(\"\");\n }\n }\n return \"Untitled\";\n}\n\n/**\n * Convert page response to search result\n */\nfunction pageToSearchResult(page: PageObjectResponse): SearchResultPage {\n let parent: SearchResultPage[\"parent\"];\n\n if (page.parent.type === \"page_id\") {\n parent = { type: \"page\", id: page.parent.page_id };\n } else if (page.parent.type === \"database_id\") {\n parent = { type: \"database\", id: page.parent.database_id };\n } else {\n parent = { type: \"workspace\" };\n }\n\n return {\n type: \"page\",\n id: page.id,\n url: page.url,\n title: extractPageTitle(page.properties),\n createdTime: page.created_time,\n lastEditedTime: page.last_edited_time,\n archived: page.archived,\n icon:\n page.icon?.type === \"emoji\"\n ? page.icon.emoji\n : page.icon?.type === \"external\"\n ? page.icon.external.url\n : undefined,\n cover:\n page.cover?.type === \"external\"\n ? page.cover.external.url\n : page.cover?.type === \"file\"\n ? page.cover.file.url\n : undefined,\n parent,\n };\n}\n\n/**\n * Convert database response to search result\n */\nfunction databaseToSearchResult(\n database: DatabaseObjectResponse\n): SearchResultDatabase {\n let parent: SearchResultDatabase[\"parent\"];\n\n if (database.parent.type === \"page_id\") {\n parent = { type: \"page\", id: database.parent.page_id };\n } else {\n parent = { type: \"workspace\" };\n }\n\n return {\n type: \"database\",\n id: database.id,\n url: database.url,\n title: database.title.map((t) => t.plain_text).join(\"\"),\n description: database.description.map((t) => t.plain_text).join(\"\"),\n createdTime: database.created_time,\n lastEditedTime: database.last_edited_time,\n isInline: database.is_inline,\n icon:\n database.icon?.type === \"emoji\"\n ? database.icon.emoji\n : database.icon?.type === \"external\"\n ? database.icon.external.url\n : undefined,\n cover:\n database.cover?.type === \"external\"\n ? database.cover.external.url\n : database.cover?.type === \"file\"\n ? database.cover.file.url\n : undefined,\n parent,\n };\n}\n\n/**\n * Search across the entire Notion workspace\n */\nexport async function search(options: SearchOptions = {}): Promise<SearchResponse> {\n const notion = getNotionClient();\n\n const params: SearchParams = {};\n\n if (options.query) {\n params.query = options.query;\n }\n\n if (options.filter) {\n // Map 'database' to 'data_source' for newer SDK versions\n const filterValue = options.filter.value === \"database\" ? \"data_source\" : options.filter.value;\n params.filter = { value: filterValue, property: options.filter.property };\n }\n\n if (options.sort) {\n params.sort = options.sort;\n }\n\n if (options.startCursor) {\n params.start_cursor = options.startCursor;\n }\n\n if (options.pageSize) {\n params.page_size = options.pageSize;\n }\n\n const response = await notion.search(params as any);\n\n const results: SearchResult[] = response.results.map((item: any) => {\n if (item.object === \"page\") {\n return pageToSearchResult(item as PageObjectResponse);\n } else {\n return databaseToSearchResult(item as DatabaseObjectResponse);\n }\n });\n\n return {\n results,\n hasMore: response.has_more,\n nextCursor: response.next_cursor,\n };\n}\n\n/**\n * Search for pages only\n */\nexport async function searchPages(\n query?: string,\n options: Omit<SearchOptions, \"filter\"> = {}\n): Promise<SearchResultPage[]> {\n const response = await search({\n ...options,\n query,\n filter: { value: \"page\", property: \"object\" },\n });\n\n return response.results.filter(\n (r): r is SearchResultPage => r.type === \"page\"\n );\n}\n\n/**\n * Search for databases only\n */\nexport async function searchDatabases(\n query?: string,\n options: Omit<SearchOptions, \"filter\"> = {}\n): Promise<SearchResultDatabase[]> {\n const response = await search({\n ...options,\n query,\n filter: { value: \"database\", property: \"object\" },\n });\n\n return response.results.filter(\n (r): r is SearchResultDatabase => r.type === \"database\"\n );\n}\n\n/**\n * Search all results (handles pagination)\n */\nexport async function searchAll(\n query?: string,\n options: Omit<SearchOptions, \"startCursor\" | \"pageSize\"> = {}\n): Promise<SearchResult[]> {\n const allResults: SearchResult[] = [];\n let cursor: string | undefined;\n\n do {\n const response = await search({\n ...options,\n query,\n startCursor: cursor,\n pageSize: 100,\n });\n allResults.push(...response.results);\n cursor = response.nextCursor ?? undefined;\n } while (cursor);\n\n return allResults;\n}\n\n/**\n * Find a page by title\n */\nexport async function findPageByTitle(\n title: string,\n exactMatch: boolean = false\n): Promise<SearchResultPage | null> {\n const pages = await searchPages(title);\n\n if (exactMatch) {\n return pages.find((p) => p.title === title) || null;\n }\n\n return pages[0] || null;\n}\n\n/**\n * Find a database by title\n */\nexport async function findDatabaseByTitle(\n title: string,\n exactMatch: boolean = false\n): Promise<SearchResultDatabase | null> {\n const databases = await searchDatabases(title);\n\n if (exactMatch) {\n return databases.find((d) => d.title === title) || null;\n }\n\n return databases[0] || null;\n}\n\n/**\n * Get recently edited pages\n */\nexport async function getRecentlyEditedPages(\n limit: number = 10\n): Promise<SearchResultPage[]> {\n const response = await search({\n filter: { value: \"page\", property: \"object\" },\n sort: { direction: \"descending\", timestamp: \"last_edited_time\" },\n pageSize: limit,\n });\n\n return response.results.filter(\n (r): r is SearchResultPage => r.type === \"page\"\n );\n}\n\n/**\n * Get recently edited databases\n */\nexport async function getRecentlyEditedDatabases(\n limit: number = 10\n): Promise<SearchResultDatabase[]> {\n const response = await search({\n filter: { value: \"database\", property: \"object\" },\n sort: { direction: \"descending\", timestamp: \"last_edited_time\" },\n pageSize: limit,\n });\n\n return response.results.filter(\n (r): r is SearchResultDatabase => r.type === \"database\"\n );\n}\n\n/**\n * Full text search in workspace\n * Returns pages and databases matching the query\n */\nexport async function fullTextSearch(\n query: string,\n options: {\n objectType?: SearchObjectType;\n limit?: number;\n sortByRelevance?: boolean;\n } = {}\n): Promise<SearchResult[]> {\n const searchOptions: SearchOptions = {\n query,\n pageSize: options.limit ?? 20,\n };\n\n if (options.objectType) {\n searchOptions.filter = { value: options.objectType, property: \"object\" };\n }\n\n if (!options.sortByRelevance) {\n searchOptions.sort = {\n direction: \"descending\",\n timestamp: \"last_edited_time\",\n };\n }\n\n const response = await search(searchOptions);\n return response.results;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,145 @@
1
+ // src/tools/inventory-manager.ts
2
+ var items = /* @__PURE__ */ new Map();
3
+ var transactions = [];
4
+ var nextItemId = 1;
5
+ var nextTxId = 1;
6
+ function addItem(name, quantity, options = {}) {
7
+ const id = `item_${nextItemId++}`;
8
+ const item = {
9
+ id,
10
+ name,
11
+ quantity,
12
+ sku: options.sku,
13
+ category: options.category,
14
+ unit: options.unit || "units",
15
+ reorderPoint: options.reorderPoint,
16
+ cost: options.cost,
17
+ price: options.price,
18
+ location: options.location,
19
+ notes: options.notes,
20
+ createdAt: /* @__PURE__ */ new Date(),
21
+ updatedAt: /* @__PURE__ */ new Date()
22
+ };
23
+ items.set(id, item);
24
+ transactions.push({
25
+ id: `tx_${nextTxId++}`,
26
+ itemId: id,
27
+ type: "add",
28
+ quantity,
29
+ previousQuantity: 0,
30
+ newQuantity: quantity,
31
+ reason: "Initial stock",
32
+ timestamp: /* @__PURE__ */ new Date()
33
+ });
34
+ return item;
35
+ }
36
+ function updateQuantity(nameOrId, change, reason) {
37
+ const item = findItem(nameOrId);
38
+ if (!item) throw new Error(`Item not found: ${nameOrId}`);
39
+ const prev = item.quantity;
40
+ item.quantity = Math.max(0, item.quantity + change);
41
+ item.updatedAt = /* @__PURE__ */ new Date();
42
+ transactions.push({
43
+ id: `tx_${nextTxId++}`,
44
+ itemId: item.id,
45
+ type: change > 0 ? "add" : change < 0 ? "remove" : "adjust",
46
+ quantity: Math.abs(change),
47
+ previousQuantity: prev,
48
+ newQuantity: item.quantity,
49
+ reason,
50
+ timestamp: /* @__PURE__ */ new Date()
51
+ });
52
+ return item;
53
+ }
54
+ function setQuantity(nameOrId, quantity, reason) {
55
+ const item = findItem(nameOrId);
56
+ if (!item) throw new Error(`Item not found: ${nameOrId}`);
57
+ const prev = item.quantity;
58
+ item.quantity = Math.max(0, quantity);
59
+ item.updatedAt = /* @__PURE__ */ new Date();
60
+ transactions.push({
61
+ id: `tx_${nextTxId++}`,
62
+ itemId: item.id,
63
+ type: "adjust",
64
+ quantity: Math.abs(quantity - prev),
65
+ previousQuantity: prev,
66
+ newQuantity: item.quantity,
67
+ reason: reason || "Manual adjustment",
68
+ timestamp: /* @__PURE__ */ new Date()
69
+ });
70
+ return item;
71
+ }
72
+ function removeItem(nameOrId) {
73
+ const item = findItem(nameOrId);
74
+ if (!item) return false;
75
+ items.delete(item.id);
76
+ return true;
77
+ }
78
+ function getItem(nameOrId) {
79
+ return findItem(nameOrId);
80
+ }
81
+ function listItems(filter) {
82
+ let result = Array.from(items.values());
83
+ if (filter?.category) {
84
+ result = result.filter((i) => i.category?.toLowerCase().includes(filter.category.toLowerCase()));
85
+ }
86
+ if (filter?.lowStock) {
87
+ result = result.filter((i) => i.reorderPoint !== void 0 && i.quantity <= i.reorderPoint);
88
+ }
89
+ return result.sort((a, b) => a.name.localeCompare(b.name));
90
+ }
91
+ function getItemHistory(nameOrId) {
92
+ const item = findItem(nameOrId);
93
+ if (!item) return [];
94
+ return transactions.filter((t) => t.itemId === item.id).sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
95
+ }
96
+ function getInventorySummary() {
97
+ const all = Array.from(items.values());
98
+ const totalUnits = all.reduce((s, i) => s + i.quantity, 0);
99
+ const totalValue = all.reduce((s, i) => s + i.quantity * (i.cost || 0), 0);
100
+ const lowStock = all.filter((i) => i.reorderPoint !== void 0 && i.quantity <= i.reorderPoint && i.quantity > 0);
101
+ const outOfStock = all.filter((i) => i.quantity === 0);
102
+ const byCategory = {};
103
+ for (const item of all) {
104
+ const cat = item.category || "Uncategorized";
105
+ byCategory[cat] = (byCategory[cat] || 0) + 1;
106
+ }
107
+ return {
108
+ totalItems: all.length,
109
+ totalUnits,
110
+ totalValue,
111
+ lowStockItems: lowStock,
112
+ outOfStockItems: outOfStock,
113
+ byCategory,
114
+ summary: `${all.length} items, ${totalUnits} total units, $${totalValue.toLocaleString()} value. ${lowStock.length} low stock, ${outOfStock.length} out of stock.`
115
+ };
116
+ }
117
+ function clearInventory() {
118
+ items.clear();
119
+ transactions.length = 0;
120
+ nextItemId = 1;
121
+ nextTxId = 1;
122
+ }
123
+ function findItem(nameOrId) {
124
+ const byId = items.get(nameOrId);
125
+ if (byId) return byId;
126
+ const lower = nameOrId.toLowerCase();
127
+ for (const item of items.values()) {
128
+ if (item.name.toLowerCase() === lower) return item;
129
+ if (item.sku?.toLowerCase() === lower) return item;
130
+ }
131
+ return void 0;
132
+ }
133
+
134
+ export {
135
+ addItem,
136
+ updateQuantity,
137
+ setQuantity,
138
+ removeItem,
139
+ getItem,
140
+ listItems,
141
+ getItemHistory,
142
+ getInventorySummary,
143
+ clearInventory
144
+ };
145
+ //# sourceMappingURL=chunk-HN3F4WSW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tools/inventory-manager.ts"],"sourcesContent":["/**\n * Inventory Manager — Track items, quantities, and reorder alerts\n *\n * Lightweight in-memory inventory tracking with categories,\n * low-stock alerts, and transaction history.\n */\n\nexport interface InventoryItem {\n id: string;\n name: string;\n sku?: string;\n category?: string;\n quantity: number;\n unit?: string;\n reorderPoint?: number;\n cost?: number;\n price?: number;\n location?: string;\n notes?: string;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface InventoryTransaction {\n id: string;\n itemId: string;\n type: \"add\" | \"remove\" | \"adjust\";\n quantity: number;\n previousQuantity: number;\n newQuantity: number;\n reason?: string;\n timestamp: Date;\n}\n\nexport interface InventorySummary {\n totalItems: number;\n totalUnits: number;\n totalValue: number;\n lowStockItems: InventoryItem[];\n outOfStockItems: InventoryItem[];\n byCategory: Record<string, number>;\n summary: string;\n}\n\nconst items = new Map<string, InventoryItem>();\nconst transactions: InventoryTransaction[] = [];\nlet nextItemId = 1;\nlet nextTxId = 1;\n\nexport function addItem(\n name: string,\n quantity: number,\n options: { sku?: string; category?: string; unit?: string; reorderPoint?: number; cost?: number; price?: number; location?: string; notes?: string } = {}\n): InventoryItem {\n const id = `item_${nextItemId++}`;\n const item: InventoryItem = {\n id, name, quantity,\n sku: options.sku,\n category: options.category,\n unit: options.unit || \"units\",\n reorderPoint: options.reorderPoint,\n cost: options.cost,\n price: options.price,\n location: options.location,\n notes: options.notes,\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n items.set(id, item);\n\n transactions.push({\n id: `tx_${nextTxId++}`, itemId: id, type: \"add\",\n quantity, previousQuantity: 0, newQuantity: quantity,\n reason: \"Initial stock\", timestamp: new Date(),\n });\n\n return item;\n}\n\nexport function updateQuantity(\n nameOrId: string,\n change: number,\n reason?: string\n): InventoryItem {\n const item = findItem(nameOrId);\n if (!item) throw new Error(`Item not found: ${nameOrId}`);\n\n const prev = item.quantity;\n item.quantity = Math.max(0, item.quantity + change);\n item.updatedAt = new Date();\n\n transactions.push({\n id: `tx_${nextTxId++}`, itemId: item.id,\n type: change > 0 ? \"add\" : change < 0 ? \"remove\" : \"adjust\",\n quantity: Math.abs(change), previousQuantity: prev, newQuantity: item.quantity,\n reason, timestamp: new Date(),\n });\n\n return item;\n}\n\nexport function setQuantity(\n nameOrId: string,\n quantity: number,\n reason?: string\n): InventoryItem {\n const item = findItem(nameOrId);\n if (!item) throw new Error(`Item not found: ${nameOrId}`);\n\n const prev = item.quantity;\n item.quantity = Math.max(0, quantity);\n item.updatedAt = new Date();\n\n transactions.push({\n id: `tx_${nextTxId++}`, itemId: item.id, type: \"adjust\",\n quantity: Math.abs(quantity - prev), previousQuantity: prev, newQuantity: item.quantity,\n reason: reason || \"Manual adjustment\", timestamp: new Date(),\n });\n\n return item;\n}\n\nexport function removeItem(nameOrId: string): boolean {\n const item = findItem(nameOrId);\n if (!item) return false;\n items.delete(item.id);\n return true;\n}\n\nexport function getItem(nameOrId: string): InventoryItem | undefined {\n return findItem(nameOrId);\n}\n\nexport function listItems(filter?: { category?: string; lowStock?: boolean }): InventoryItem[] {\n let result = Array.from(items.values());\n if (filter?.category) {\n result = result.filter((i) => i.category?.toLowerCase().includes(filter.category!.toLowerCase()));\n }\n if (filter?.lowStock) {\n result = result.filter((i) => i.reorderPoint !== undefined && i.quantity <= i.reorderPoint);\n }\n return result.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function getItemHistory(nameOrId: string): InventoryTransaction[] {\n const item = findItem(nameOrId);\n if (!item) return [];\n return transactions.filter((t) => t.itemId === item.id).sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());\n}\n\nexport function getInventorySummary(): InventorySummary {\n const all = Array.from(items.values());\n const totalUnits = all.reduce((s, i) => s + i.quantity, 0);\n const totalValue = all.reduce((s, i) => s + i.quantity * (i.cost || 0), 0);\n const lowStock = all.filter((i) => i.reorderPoint !== undefined && i.quantity <= i.reorderPoint && i.quantity > 0);\n const outOfStock = all.filter((i) => i.quantity === 0);\n\n const byCategory: Record<string, number> = {};\n for (const item of all) {\n const cat = item.category || \"Uncategorized\";\n byCategory[cat] = (byCategory[cat] || 0) + 1;\n }\n\n return {\n totalItems: all.length,\n totalUnits,\n totalValue,\n lowStockItems: lowStock,\n outOfStockItems: outOfStock,\n byCategory,\n summary: `${all.length} items, ${totalUnits} total units, $${totalValue.toLocaleString()} value. ${lowStock.length} low stock, ${outOfStock.length} out of stock.`,\n };\n}\n\nexport function clearInventory(): void {\n items.clear();\n transactions.length = 0;\n nextItemId = 1;\n nextTxId = 1;\n}\n\nfunction findItem(nameOrId: string): InventoryItem | undefined {\n const byId = items.get(nameOrId);\n if (byId) return byId;\n const lower = nameOrId.toLowerCase();\n for (const item of items.values()) {\n if (item.name.toLowerCase() === lower) return item;\n if (item.sku?.toLowerCase() === lower) return item;\n }\n return undefined;\n}\n"],"mappings":"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","names":[]}
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  textToSpeech
3
- } from "./chunk-F6QUZQGI.js";
3
+ } from "./chunk-MXAPLSJ5.js";
4
4
  import {
5
5
  transcribeAudio
6
- } from "./chunk-GVJVEWHI.js";
6
+ } from "./chunk-SJSUSJ47.js";
7
7
  import {
8
8
  scheduleReminder
9
- } from "./chunk-4LVWXUNC.js";
9
+ } from "./chunk-AYUKPTSM.js";
10
10
  import {
11
11
  chatWithTools
12
- } from "./chunk-CI6Q63MM.js";
12
+ } from "./chunk-766ASQWE.js";
13
13
  import {
14
14
  env
15
- } from "./chunk-4TG2IG5K.js";
15
+ } from "./chunk-ZLZKF2PM.js";
16
16
 
17
17
  // src/inputs/telegram/bot.ts
18
18
  import { Bot, session } from "grammy";
@@ -50,9 +50,20 @@ ${response.content}`;
50
50
  );
51
51
  } catch (error) {
52
52
  console.error("Error processing message:", error);
53
- await ctx.reply(
54
- "Sorry, I encountered an error processing your message. Please try again."
55
- );
53
+ const errMsg = error instanceof Error ? error.message : String(error);
54
+ if (errMsg.includes("credit balance is too low")) {
55
+ await ctx.reply(
56
+ "\u26A0\uFE0F The AI service is temporarily unavailable due to API billing. The admin has been notified."
57
+ );
58
+ } else if (errMsg.includes("rate_limit") || errMsg.includes("429")) {
59
+ await ctx.reply(
60
+ "\u23F3 Too many requests \u2014 please wait a moment and try again."
61
+ );
62
+ } else {
63
+ await ctx.reply(
64
+ "Sorry, I encountered an error processing your message. Please try again."
65
+ );
66
+ }
56
67
  }
57
68
  }
58
69
  async function handleVoice(ctx) {
@@ -248,4 +259,4 @@ Send me a message or voice note to get started!`
248
259
  export {
249
260
  createBot
250
261
  };
251
- //# sourceMappingURL=chunk-6DRDKB45.js.map
262
+ //# sourceMappingURL=chunk-I6BDYQIG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/inputs/telegram/bot.ts","../src/inputs/telegram/handlers.ts"],"sourcesContent":["import { Bot, Context, session } from \"grammy\";\nimport { env } from \"../../config/env\";\nimport { handleMessage, handleVoice } from \"./handlers\";\nimport { scheduleReminder } from \"../../core/scheduler\";\n\nexport interface SessionData {\n messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}\n\nexport type OpenSentinelContext = Context & { session: SessionData };\n\nexport function createBot() {\n const bot = new Bot<OpenSentinelContext>(env.TELEGRAM_BOT_TOKEN);\n\n // Session middleware for conversation history\n bot.use(\n session({\n initial: (): SessionData => ({\n messages: [],\n }),\n })\n );\n\n // Only allow configured chat ID\n bot.use(async (ctx, next) => {\n const chatId = ctx.chat?.id?.toString();\n if (chatId !== env.TELEGRAM_CHAT_ID) {\n console.log(`Unauthorized access attempt from chat ID: ${chatId}`);\n return;\n }\n await next();\n });\n\n // Command handlers\n bot.command(\"start\", async (ctx) => {\n await ctx.reply(\n `Hello! I'm OpenSentinel, your personal AI assistant with JARVIS-like capabilities.\n\nI can:\n• Chat and answer questions using Claude AI\n• Execute shell commands on your system\n• Read and write files\n• Search the web\n• Remember important information\n• Set reminders\n\nSend me a message or voice note to get started!`\n );\n });\n\n bot.command(\"clear\", async (ctx) => {\n ctx.session.messages = [];\n await ctx.reply(\"✓ Conversation history cleared.\");\n });\n\n bot.command(\"remind\", async (ctx) => {\n const text = ctx.message?.text?.replace(\"/remind\", \"\").trim();\n\n if (!text) {\n await ctx.reply(\n \"Usage: /remind <time> <message>\\n\\nExamples:\\n• /remind 5m Check the oven\\n• /remind 1h Call mom\\n• /remind 30s Test reminder\"\n );\n return;\n }\n\n // Parse time and message\n const match = text.match(/^(\\d+)(s|m|h)\\s+(.+)$/i);\n if (!match) {\n await ctx.reply(\n \"Invalid format. Use: /remind <number><s/m/h> <message>\\n\\nExample: /remind 5m Check the oven\"\n );\n return;\n }\n\n const [, amount, unit, message] = match;\n const multipliers: Record<string, number> = {\n s: 1000,\n m: 60 * 1000,\n h: 60 * 60 * 1000,\n };\n const delayMs = parseInt(amount) * multipliers[unit.toLowerCase()];\n\n try {\n await scheduleReminder(message, delayMs, ctx.chat?.id?.toString());\n const timeStr = unit === \"s\" ? \"seconds\" : unit === \"m\" ? \"minutes\" : \"hours\";\n await ctx.reply(`✓ Reminder set for ${amount} ${timeStr}: \"${message}\"`);\n } catch (error) {\n await ctx.reply(\"Sorry, I couldn't set the reminder. Please try again.\");\n }\n });\n\n bot.command(\"help\", async (ctx) => {\n await ctx.reply(\n `*OpenSentinel Commands*\n\n/start - Welcome message\n/clear - Clear conversation history\n/remind <time> <message> - Set a reminder\n/help - Show this help\n\n*Features*\n• Send text messages for AI chat\n• Send voice messages for voice interaction\n• Ask me to run commands, search the web, or manage files\n\n*Examples*\n• \"What's the weather like?\"\n• \"List files in my Downloads folder\"\n• \"Search for the latest news about AI\"\n• /remind 5m Take a break`,\n { parse_mode: \"Markdown\" }\n );\n });\n\n // Message handlers\n bot.on(\"message:text\", handleMessage);\n bot.on(\"message:voice\", handleVoice);\n\n // Error handling\n bot.catch((err) => {\n console.error(\"Bot error:\", err);\n });\n\n return bot;\n}\n","import { InputFile } from \"grammy\";\nimport type { SentinelContext } from \"./bot\";\nimport { chatWithTools, type Message } from \"../../core/brain\";\nimport { transcribeAudio } from \"../../outputs/stt\";\nimport { textToSpeech } from \"../../outputs/tts\";\n\nconst MAX_HISTORY = 20; // Keep last 20 messages for context\n\nexport async function handleMessage(ctx: SentinelContext) {\n const text = ctx.message?.text;\n if (!text) return;\n\n // Add user message to history\n ctx.session.messages.push({ role: \"user\", content: text });\n\n // Trim history if too long\n if (ctx.session.messages.length > MAX_HISTORY) {\n ctx.session.messages = ctx.session.messages.slice(-MAX_HISTORY);\n }\n\n // Show typing indicator\n await ctx.replyWithChatAction(\"typing\");\n\n try {\n // Use chatWithTools for full capability\n const response = await chatWithTools(\n ctx.session.messages as Message[],\n ctx.chat?.id?.toString(),\n async () => {\n // Keep typing indicator alive during tool use\n await ctx.replyWithChatAction(\"typing\");\n }\n );\n\n // Add assistant response to history\n ctx.session.messages.push({ role: \"assistant\", content: response.content });\n\n // Build response with tool usage info\n let finalResponse = response.content;\n if (response.toolsUsed && response.toolsUsed.length > 0) {\n const toolList = [...new Set(response.toolsUsed)].join(\", \");\n finalResponse = `🔧 _Used: ${toolList}_\\n\\n${response.content}`;\n }\n\n // Send response (split if too long for Telegram)\n await sendResponse(ctx, finalResponse);\n\n console.log(\n `[Telegram] Processed message. Tokens: ${response.inputTokens}/${response.outputTokens}` +\n (response.toolsUsed ? ` Tools: ${response.toolsUsed.join(\", \")}` : \"\")\n );\n } catch (error) {\n console.error(\"Error processing message:\", error);\n const errMsg = error instanceof Error ? error.message : String(error);\n if (errMsg.includes(\"credit balance is too low\")) {\n await ctx.reply(\n \"⚠️ The AI service is temporarily unavailable due to API billing. The admin has been notified.\"\n );\n } else if (errMsg.includes(\"rate_limit\") || errMsg.includes(\"429\")) {\n await ctx.reply(\n \"⏳ Too many requests — please wait a moment and try again.\"\n );\n } else {\n await ctx.reply(\n \"Sorry, I encountered an error processing your message. Please try again.\"\n );\n }\n }\n}\n\nexport async function handleVoice(ctx: SentinelContext) {\n const voice = ctx.message?.voice;\n if (!voice) return;\n\n await ctx.replyWithChatAction(\"typing\");\n\n try {\n // Get voice file\n const file = await ctx.getFile();\n const fileUrl = `https://api.telegram.org/file/bot${process.env.TELEGRAM_BOT_TOKEN}/${file.file_path}`;\n\n // Download and transcribe\n const response = await fetch(fileUrl);\n const audioBuffer = await response.arrayBuffer();\n\n const transcription = await transcribeAudio(Buffer.from(audioBuffer));\n\n if (!transcription) {\n await ctx.reply(\"Sorry, I couldn't transcribe that voice message.\");\n return;\n }\n\n // Show what was transcribed\n await ctx.reply(`🎤 _\"${transcription}\"_`, { parse_mode: \"Markdown\" });\n\n // Process as text message\n ctx.session.messages.push({ role: \"user\", content: transcription });\n\n if (ctx.session.messages.length > MAX_HISTORY) {\n ctx.session.messages = ctx.session.messages.slice(-MAX_HISTORY);\n }\n\n await ctx.replyWithChatAction(\"typing\");\n\n const aiResponse = await chatWithTools(\n ctx.session.messages as Message[],\n ctx.chat?.id?.toString()\n );\n ctx.session.messages.push({\n role: \"assistant\",\n content: aiResponse.content,\n });\n\n // Send text response first\n await sendResponse(ctx, aiResponse.content);\n\n // Also send voice response if text is short enough\n if (aiResponse.content.length < 1000 && aiResponse.content.length > 10) {\n try {\n await ctx.replyWithChatAction(\"record_voice\");\n const audioBuffer = await textToSpeech(aiResponse.content);\n if (audioBuffer) {\n await ctx.replyWithVoice(new InputFile(audioBuffer, \"response.ogg\"));\n }\n } catch (ttsError) {\n console.error(\"TTS error:\", ttsError);\n // Don't fail if TTS fails, text was already sent\n }\n }\n\n console.log(\n `[Telegram] Processed voice message. Tokens: ${aiResponse.inputTokens}/${aiResponse.outputTokens}`\n );\n } catch (error) {\n console.error(\"Error processing voice message:\", error);\n await ctx.reply(\n \"Sorry, I encountered an error processing your voice message. Please try again.\"\n );\n }\n}\n\n// Helper to send response, handling Markdown errors\nasync function sendResponse(ctx: SentinelContext, text: string) {\n const maxLength = 4096;\n\n // Try with Markdown first\n try {\n if (text.length <= maxLength) {\n await ctx.reply(text, { parse_mode: \"Markdown\" });\n } else {\n const chunks = splitMessage(text, maxLength);\n for (const chunk of chunks) {\n await ctx.reply(chunk, { parse_mode: \"Markdown\" });\n }\n }\n } catch {\n // If Markdown fails, send as plain text\n if (text.length <= maxLength) {\n await ctx.reply(text);\n } else {\n const chunks = splitMessage(text, maxLength);\n for (const chunk of chunks) {\n await ctx.reply(chunk);\n }\n }\n }\n}\n\nfunction splitMessage(text: string, maxLength: number): string[] {\n const chunks: string[] = [];\n let remaining = text;\n\n while (remaining.length > 0) {\n if (remaining.length <= maxLength) {\n chunks.push(remaining);\n break;\n }\n\n // Find a good break point (newline or space)\n let breakPoint = remaining.lastIndexOf(\"\\n\", maxLength);\n if (breakPoint === -1 || breakPoint < maxLength / 2) {\n breakPoint = remaining.lastIndexOf(\" \", maxLength);\n }\n if (breakPoint === -1 || breakPoint < maxLength / 2) {\n breakPoint = maxLength;\n }\n\n chunks.push(remaining.slice(0, breakPoint));\n remaining = remaining.slice(breakPoint).trim();\n }\n\n return chunks;\n}\n"],"mappings":"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","names":["audioBuffer"]}
@@ -0,0 +1,347 @@
1
+ import {
2
+ archivedMemories,
3
+ db,
4
+ memories
5
+ } from "./chunk-XKYRH4FM.js";
6
+ import {
7
+ env
8
+ } from "./chunk-ZLZKF2PM.js";
9
+
10
+ // src/core/memory.ts
11
+ import { eq, desc, sql } from "drizzle-orm";
12
+ import OpenAI from "openai";
13
+
14
+ // src/core/security/field-encryption.ts
15
+ import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
16
+ var ALGORITHM = "aes-256-gcm";
17
+ var IV_LENGTH = 16;
18
+ var TAG_LENGTH = 16;
19
+ var KEY_LENGTH = 32;
20
+ var CURRENT_KEY_VERSION = 1;
21
+ var _masterKey = null;
22
+ function getMasterKey() {
23
+ if (_masterKey) return _masterKey;
24
+ const keyBase64 = env.ENCRYPTION_MASTER_KEY;
25
+ if (keyBase64) {
26
+ const key = Buffer.from(keyBase64, "base64");
27
+ if (key.length !== KEY_LENGTH) {
28
+ throw new Error(
29
+ `ENCRYPTION_MASTER_KEY must be ${KEY_LENGTH} bytes (${KEY_LENGTH * 4 / 3} base64 chars). Got ${key.length} bytes.`
30
+ );
31
+ }
32
+ _masterKey = key;
33
+ return _masterKey;
34
+ }
35
+ if (env.NODE_ENV === "production") {
36
+ throw new Error(
37
+ `ENCRYPTION_MASTER_KEY is required in production for SOC 2 compliance. Generate one with: node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"`
38
+ );
39
+ }
40
+ console.warn("[field-encryption] No ENCRYPTION_MASTER_KEY set \u2014 using ephemeral key (dev only)");
41
+ _masterKey = randomBytes(KEY_LENGTH);
42
+ return _masterKey;
43
+ }
44
+ function encryptField(plaintext) {
45
+ if (plaintext === null || plaintext === void 0) return null;
46
+ const key = getMasterKey();
47
+ const iv = randomBytes(IV_LENGTH);
48
+ const cipher = createCipheriv(ALGORITHM, key, iv);
49
+ const encrypted = Buffer.concat([
50
+ cipher.update(plaintext, "utf8"),
51
+ cipher.final()
52
+ ]);
53
+ const tag = cipher.getAuthTag();
54
+ const combined = Buffer.concat([
55
+ Buffer.from([CURRENT_KEY_VERSION]),
56
+ iv,
57
+ tag,
58
+ encrypted
59
+ ]);
60
+ return combined.toString("base64");
61
+ }
62
+ function decryptField(encryptedBase64) {
63
+ if (encryptedBase64 === null || encryptedBase64 === void 0) return null;
64
+ const combined = Buffer.from(encryptedBase64, "base64");
65
+ if (combined.length < 1 + IV_LENGTH + TAG_LENGTH + 1) {
66
+ throw new Error("Encrypted data too short");
67
+ }
68
+ const keyVersion = combined[0];
69
+ if (keyVersion !== CURRENT_KEY_VERSION) {
70
+ throw new Error(`Unsupported encryption key version: ${keyVersion}`);
71
+ }
72
+ const iv = combined.subarray(1, 1 + IV_LENGTH);
73
+ const tag = combined.subarray(1 + IV_LENGTH, 1 + IV_LENGTH + TAG_LENGTH);
74
+ const ciphertext = combined.subarray(1 + IV_LENGTH + TAG_LENGTH);
75
+ const key = getMasterKey();
76
+ const decipher = createDecipheriv(ALGORITHM, key, iv);
77
+ decipher.setAuthTag(tag);
78
+ const decrypted = Buffer.concat([
79
+ decipher.update(ciphertext),
80
+ decipher.final()
81
+ ]);
82
+ return decrypted.toString("utf8");
83
+ }
84
+ function isEncryptionAvailable() {
85
+ try {
86
+ getMasterKey();
87
+ return true;
88
+ } catch {
89
+ return false;
90
+ }
91
+ }
92
+
93
+ // src/core/memory.ts
94
+ var _openai = null;
95
+ function getOpenAI() {
96
+ if (!_openai) {
97
+ _openai = new OpenAI({ apiKey: env.OPENAI_API_KEY });
98
+ }
99
+ return _openai;
100
+ }
101
+ var openai = new Proxy({}, {
102
+ get(_target, prop) {
103
+ const instance = getOpenAI();
104
+ const value = instance[prop];
105
+ if (typeof value === "function") {
106
+ return value.bind(instance);
107
+ }
108
+ return value;
109
+ }
110
+ });
111
+ async function generateEmbedding(text) {
112
+ const response = await openai.embeddings.create({
113
+ model: "text-embedding-3-small",
114
+ input: text
115
+ });
116
+ return response.data[0].embedding;
117
+ }
118
+ async function storeMemory(memory) {
119
+ const embedding = await generateEmbedding(memory.content);
120
+ const shouldEncrypt = isEncryptionAvailable();
121
+ const contentForDb = shouldEncrypt ? encryptField(memory.content) : memory.content;
122
+ const [stored] = await db.insert(memories).values({
123
+ ...memory,
124
+ content: contentForDb,
125
+ encrypted: shouldEncrypt,
126
+ embedding,
127
+ provenance: memory.provenance || `${memory.source || "unknown"}:auto`
128
+ }).returning();
129
+ try {
130
+ await db.execute(sql`
131
+ UPDATE memories
132
+ SET search_vector = to_tsvector('english', ${memory.content})
133
+ WHERE id = ${stored.id}
134
+ `);
135
+ } catch {
136
+ }
137
+ return { ...stored, content: memory.content };
138
+ }
139
+ async function updateMemory(id, updates) {
140
+ const setClauses = [];
141
+ if (updates.content) {
142
+ const newEmbedding = await generateEmbedding(updates.content);
143
+ setClauses.push(sql`content = ${updates.content}`);
144
+ setClauses.push(sql`embedding = ${JSON.stringify(newEmbedding)}::vector`);
145
+ setClauses.push(sql`search_vector = to_tsvector('english', ${updates.content})`);
146
+ }
147
+ if (updates.type) {
148
+ setClauses.push(sql`type = ${updates.type}`);
149
+ }
150
+ if (updates.importance !== void 0) {
151
+ setClauses.push(sql`importance = ${updates.importance}`);
152
+ }
153
+ if (setClauses.length === 0) return null;
154
+ const result = await db.execute(sql`
155
+ UPDATE memories
156
+ SET ${sql.join(setClauses, sql`, `)}
157
+ WHERE id = ${id}
158
+ RETURNING *
159
+ `);
160
+ return result[0] || null;
161
+ }
162
+ async function deleteMemory(id) {
163
+ const result = await db.execute(sql`
164
+ SELECT * FROM memories WHERE id = ${id}
165
+ `);
166
+ const memory = result[0];
167
+ if (!memory) return false;
168
+ await db.insert(archivedMemories).values({
169
+ originalMemoryId: memory.id,
170
+ userId: memory.user_id,
171
+ type: memory.type,
172
+ content: memory.content,
173
+ reason: "user_request",
174
+ originalCreatedAt: memory.created_at
175
+ });
176
+ await db.execute(sql`DELETE FROM memories WHERE id = ${id}`);
177
+ return true;
178
+ }
179
+ async function exportMemories(userId, format = "markdown") {
180
+ const mems = await db.select().from(memories).where(userId ? eq(memories.userId, userId) : void 0).orderBy(desc(memories.createdAt));
181
+ for (const m of mems) {
182
+ if (m.encrypted) {
183
+ try {
184
+ m.content = decryptField(m.content) ?? m.content;
185
+ } catch {
186
+ }
187
+ }
188
+ }
189
+ if (format === "json") {
190
+ return JSON.stringify(
191
+ mems.map((m) => ({
192
+ id: m.id,
193
+ type: m.type,
194
+ content: m.content,
195
+ importance: m.importance,
196
+ source: m.source,
197
+ provenance: m.provenance,
198
+ createdAt: m.createdAt
199
+ })),
200
+ null,
201
+ 2
202
+ );
203
+ }
204
+ const lines = [
205
+ "# Memories Export",
206
+ `Exported: ${(/* @__PURE__ */ new Date()).toISOString()}`,
207
+ `Total: ${mems.length} memories`,
208
+ ""
209
+ ];
210
+ for (const m of mems) {
211
+ lines.push(`## [${m.type}] (Importance: ${m.importance}/10)`);
212
+ lines.push(m.content);
213
+ lines.push(`_Source: ${m.source || "unknown"} | Created: ${m.createdAt.toISOString()}_`);
214
+ lines.push("");
215
+ }
216
+ return lines.join("\n");
217
+ }
218
+ async function searchMemories(query, userId, limit = 5) {
219
+ const queryEmbedding = await generateEmbedding(query);
220
+ const results = await db.execute(sql`
221
+ SELECT
222
+ id, user_id, type, content, importance, source, provenance, metadata,
223
+ last_accessed, created_at,
224
+ 1 - (embedding <=> ${JSON.stringify(queryEmbedding)}::vector) as similarity
225
+ FROM memories
226
+ ${userId ? sql`WHERE user_id = ${userId}` : sql``}
227
+ ORDER BY embedding <=> ${JSON.stringify(queryEmbedding)}::vector
228
+ LIMIT ${limit}
229
+ `);
230
+ const rows = results;
231
+ const memoryIds = rows.map((r) => r.id);
232
+ if (memoryIds.length > 0) {
233
+ await db.execute(sql`
234
+ UPDATE memories
235
+ SET last_accessed = NOW()
236
+ WHERE id = ANY(${memoryIds}::uuid[])
237
+ `);
238
+ }
239
+ for (const row of rows) {
240
+ if (row.encrypted) {
241
+ try {
242
+ row.content = decryptField(row.content) ?? row.content;
243
+ } catch {
244
+ }
245
+ }
246
+ }
247
+ return rows;
248
+ }
249
+ async function getMemoryById(id) {
250
+ const result = await db.execute(sql`
251
+ SELECT * FROM memories WHERE id = ${id}
252
+ `);
253
+ const row = result[0] || null;
254
+ if (row && row.encrypted) {
255
+ try {
256
+ row.content = decryptField(row.content) ?? row.content;
257
+ } catch {
258
+ }
259
+ }
260
+ return row;
261
+ }
262
+ async function extractMemories(content, userId) {
263
+ const extractionPrompt = `Analyze this text and extract any important facts that should be remembered about the user or their preferences. Return a JSON array of objects with "content" (the fact), "type" (semantic/episodic/procedural), and "importance" (1-10).
264
+
265
+ Text: "${content}"
266
+
267
+ Return only the JSON array, no other text. If no memorable facts, return [].`;
268
+ try {
269
+ const response = await openai.chat.completions.create({
270
+ model: "gpt-4o-mini",
271
+ messages: [{ role: "user", content: extractionPrompt }],
272
+ response_format: { type: "json_object" }
273
+ });
274
+ const extracted = JSON.parse(
275
+ response.choices[0].message.content || '{"memories":[]}'
276
+ );
277
+ const memoriesToStore = extracted.memories || extracted || [];
278
+ const storedMemories = [];
279
+ for (const mem of memoriesToStore) {
280
+ if (mem.content && mem.content.length > 5) {
281
+ const stored = await storeMemory({
282
+ userId,
283
+ content: mem.content,
284
+ type: mem.type || "semantic",
285
+ importance: mem.importance || 5,
286
+ source: "conversation",
287
+ provenance: "extraction:auto"
288
+ });
289
+ storedMemories.push(stored);
290
+ }
291
+ }
292
+ return storedMemories;
293
+ } catch (error) {
294
+ console.error("Error extracting memories:", error);
295
+ return [];
296
+ }
297
+ }
298
+ async function buildMemoryContext(query, userId, conversationHistory) {
299
+ const anyAdvancedEnabled = env.HYDE_ENABLED || env.RERANK_ENABLED || env.MULTISTEP_RAG_ENABLED || env.RETRIEVAL_CACHE_ENABLED || env.CONTEXTUAL_QUERY_ENABLED;
300
+ if (anyAdvancedEnabled) {
301
+ try {
302
+ const { enhancedRetrieve } = await import("./enhanced-retrieval-DNLLEM4Z.js");
303
+ const result = await enhancedRetrieve(query, { userId, limit: 5, conversationHistory });
304
+ if (result.results.length === 0) {
305
+ return "";
306
+ }
307
+ const memoryStrings2 = result.results.map((m) => {
308
+ const provenance = m.provenance ? ` [${m.provenance}]` : "";
309
+ const score = m.rerankScore != null ? `rerank: ${m.rerankScore}/10` : `relevance: ${((m.similarity || 0) * 100).toFixed(0)}%`;
310
+ return `- [${m.type}] ${m.content} (${score})${provenance}`;
311
+ });
312
+ return `
313
+
314
+ Relevant memories about the user:
315
+ ${memoryStrings2.join("\n")}`;
316
+ } catch {
317
+ }
318
+ }
319
+ const relevantMemories = await searchMemories(query, userId, 5);
320
+ if (relevantMemories.length === 0) {
321
+ return "";
322
+ }
323
+ const memoryStrings = relevantMemories.map(
324
+ (m) => {
325
+ const provenance = m.provenance ? ` [${m.provenance}]` : "";
326
+ return `- [${m.type}] ${m.content} (relevance: ${(m.similarity * 100).toFixed(0)}%)${provenance}`;
327
+ }
328
+ );
329
+ return `
330
+
331
+ Relevant memories about the user:
332
+ ${memoryStrings.join("\n")}`;
333
+ }
334
+
335
+ export {
336
+ decryptField,
337
+ generateEmbedding,
338
+ storeMemory,
339
+ updateMemory,
340
+ deleteMemory,
341
+ exportMemories,
342
+ searchMemories,
343
+ getMemoryById,
344
+ extractMemories,
345
+ buildMemoryContext
346
+ };
347
+ //# sourceMappingURL=chunk-IZJMVV7O.js.map