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/pages.ts"],"sourcesContent":["import { getNotionClient, getRootPageId } from \"./client\";\nimport { markdownToBlocks, createBlockObject, type BlockContent } from \"./blocks\";\nimport type {\n PageObjectResponse,\n PartialPageObjectResponse,\n CreatePageParameters,\n UpdatePageParameters,\n} from \"@notionhq/client/build/src/api-endpoints\";\n\n/**\n * Page operations for Notion\n * Handles creating, reading, updating, and archiving pages\n */\n\nexport interface NotionPageProperties {\n title?: string;\n [key: string]: string | number | boolean | string[] | Date | undefined;\n}\n\nexport interface CreatePageOptions {\n parentPageId?: string;\n parentDatabaseId?: string;\n title: string;\n content?: string | BlockContent[];\n icon?: string;\n cover?: string;\n properties?: NotionPageProperties;\n}\n\nexport interface UpdatePageOptions {\n title?: string;\n icon?: string;\n cover?: string;\n properties?: NotionPageProperties;\n archived?: boolean;\n}\n\nexport interface PageResult {\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 properties: Record<string, any>;\n}\n\n/**\n * Extract page title from properties\n */\nfunction extractTitle(properties: Record<string, any>): string {\n // Look for title property in various forms\n for (const [key, value] of Object.entries(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 Notion page to simplified result\n */\nfunction pageToResult(page: PageObjectResponse): PageResult {\n return {\n id: page.id,\n url: page.url,\n title: extractTitle(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 properties: page.properties,\n };\n}\n\n/**\n * Create a new Notion page\n */\nexport async function createPage(options: CreatePageOptions): Promise<PageResult> {\n const notion = getNotionClient();\n\n // Determine parent\n let parent: CreatePageParameters[\"parent\"];\n if (options.parentDatabaseId) {\n parent = { database_id: options.parentDatabaseId };\n } else if (options.parentPageId) {\n parent = { page_id: options.parentPageId };\n } else {\n const rootId = getRootPageId();\n if (!rootId) {\n throw new Error(\"No parent specified and no root page configured\");\n }\n parent = { page_id: rootId };\n }\n\n // Build properties\n const properties: CreatePageParameters[\"properties\"] = {\n title: {\n title: [\n {\n text: { content: options.title },\n },\n ],\n },\n ...buildProperties(options.properties),\n };\n\n // Build children blocks\n let children: ReturnType<typeof createBlockObject>[] | undefined;\n if (options.content) {\n const blocks =\n typeof options.content === \"string\"\n ? markdownToBlocks(options.content)\n : options.content;\n children = blocks.map(createBlockObject);\n }\n\n // Build page params\n const params: CreatePageParameters = {\n parent,\n properties,\n children,\n };\n\n // Add icon\n if (options.icon) {\n if (options.icon.startsWith(\"http\")) {\n params.icon = { type: \"external\", external: { url: options.icon } };\n } else {\n params.icon = { type: \"emoji\", emoji: options.icon as any };\n }\n }\n\n // Add cover\n if (options.cover) {\n params.cover = { type: \"external\", external: { url: options.cover } };\n }\n\n const response = await notion.pages.create(params);\n\n return pageToResult(response as PageObjectResponse);\n}\n\n/**\n * Get a page by ID\n */\nexport async function getPage(pageId: string): Promise<PageResult> {\n const notion = getNotionClient();\n\n const response = await notion.pages.retrieve({ page_id: pageId });\n\n if (!(\"properties\" in response)) {\n throw new Error(\"Partial page object returned - cannot extract details\");\n }\n\n return pageToResult(response as PageObjectResponse);\n}\n\n/**\n * Update a page\n */\nexport async function updatePage(\n pageId: string,\n options: UpdatePageOptions\n): Promise<PageResult> {\n const notion = getNotionClient();\n\n const params: UpdatePageParameters = {\n page_id: pageId,\n };\n\n // Update title\n if (options.title !== undefined) {\n params.properties = {\n ...params.properties,\n title: {\n title: [\n {\n text: { content: options.title },\n },\n ],\n },\n };\n }\n\n // Update other properties\n if (options.properties) {\n params.properties = {\n ...params.properties,\n ...buildProperties(options.properties),\n };\n }\n\n // Update icon\n if (options.icon !== undefined) {\n if (options.icon === null || options.icon === \"\") {\n params.icon = null;\n } else if (options.icon.startsWith(\"http\")) {\n params.icon = { type: \"external\", external: { url: options.icon } };\n } else {\n params.icon = { type: \"emoji\", emoji: options.icon as any };\n }\n }\n\n // Update cover\n if (options.cover !== undefined) {\n if (options.cover === null || options.cover === \"\") {\n params.cover = null;\n } else {\n params.cover = { type: \"external\", external: { url: options.cover } };\n }\n }\n\n // Update archived status\n if (options.archived !== undefined) {\n params.archived = options.archived;\n }\n\n const response = await notion.pages.update(params);\n\n return pageToResult(response as PageObjectResponse);\n}\n\n/**\n * Archive a page (soft delete)\n */\nexport async function archivePage(pageId: string): Promise<PageResult> {\n return updatePage(pageId, { archived: true });\n}\n\n/**\n * Restore an archived page\n */\nexport async function restorePage(pageId: string): Promise<PageResult> {\n return updatePage(pageId, { archived: false });\n}\n\n/**\n * Delete a page permanently by archiving it\n * Note: Notion API doesn't support permanent deletion, only archiving\n */\nexport async function deletePage(pageId: string): Promise<void> {\n await archivePage(pageId);\n}\n\n/**\n * Duplicate a page\n */\nexport async function duplicatePage(\n pageId: string,\n newTitle?: string,\n parentPageId?: string\n): Promise<PageResult> {\n const notion = getNotionClient();\n\n // Get original page\n const originalPage = await getPage(pageId);\n\n // Get original content blocks\n const blocksResponse = await notion.blocks.children.list({\n block_id: pageId,\n });\n\n // Create new page with same content\n const newPage = await createPage({\n parentPageId: parentPageId,\n title: newTitle || `${originalPage.title} (Copy)`,\n icon: originalPage.icon,\n cover: originalPage.cover,\n });\n\n // Copy blocks to new page (if any)\n if (blocksResponse.results.length > 0) {\n // Note: We can't directly copy blocks, we need to convert them\n // This is a simplified version that doesn't handle nested blocks\n const blocksToCopy: any[] = [];\n\n for (const block of blocksResponse.results) {\n if (\"type\" in block) {\n // Copy the block structure\n const blockCopy: any = { type: block.type };\n blockCopy[block.type] = (block as any)[block.type];\n blocksToCopy.push(blockCopy);\n }\n }\n\n if (blocksToCopy.length > 0) {\n await notion.blocks.children.append({\n block_id: newPage.id,\n children: blocksToCopy,\n });\n }\n }\n\n return newPage;\n}\n\n/**\n * Build Notion properties from simple key-value pairs\n */\nfunction buildProperties(\n props?: NotionPageProperties\n): Record<string, any> | undefined {\n if (!props) return undefined;\n\n const result: Record<string, any> = {};\n\n for (const [key, value] of Object.entries(props)) {\n if (key === \"title\") continue; // Title is handled separately\n\n if (value === undefined) continue;\n\n if (typeof value === \"string\") {\n result[key] = {\n rich_text: [{ text: { content: value } }],\n };\n } else if (typeof value === \"number\") {\n result[key] = { number: value };\n } else if (typeof value === \"boolean\") {\n result[key] = { checkbox: value };\n } else if (value instanceof Date) {\n result[key] = { date: { start: value.toISOString() } };\n } else if (Array.isArray(value)) {\n // Assume multi-select\n result[key] = {\n multi_select: value.map((v) => ({ name: v })),\n };\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\n/**\n * Add content to an existing page\n */\nexport async function appendToPage(\n pageId: string,\n content: string | BlockContent[]\n): Promise<void> {\n const notion = getNotionClient();\n\n const blocks =\n typeof content === \"string\" ? markdownToBlocks(content) : content;\n const blockObjects = blocks.map(createBlockObject);\n\n await notion.blocks.children.append({\n block_id: pageId,\n children: blockObjects,\n });\n}\n\n/**\n * Replace all content on a page\n */\nexport async function replacePageContent(\n pageId: string,\n content: string | BlockContent[]\n): Promise<void> {\n const notion = getNotionClient();\n\n // Get existing blocks\n const existingBlocks = await notion.blocks.children.list({\n block_id: pageId,\n });\n\n // Delete all existing blocks\n for (const block of existingBlocks.results) {\n await notion.blocks.delete({ block_id: block.id });\n }\n\n // Add new content\n await appendToPage(pageId, content);\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  env
3
- } from "./chunk-4TG2IG5K.js";
3
+ } from "./chunk-ZLZKF2PM.js";
4
4
 
5
5
  // src/outputs/tts.ts
6
6
  var ELEVENLABS_API_URL = "https://api.elevenlabs.io/v1";
@@ -48,4 +48,4 @@ async function textToSpeech(text, options = {}) {
48
48
  export {
49
49
  textToSpeech
50
50
  };
51
- //# sourceMappingURL=chunk-F6QUZQGI.js.map
51
+ //# sourceMappingURL=chunk-MXAPLSJ5.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  chatWithTools
3
- } from "./chunk-CI6Q63MM.js";
3
+ } from "./chunk-766ASQWE.js";
4
4
 
5
5
  // src/inputs/imessage/index.ts
6
6
  var iMessageBot = class {
@@ -213,4 +213,4 @@ export {
213
213
  iMessageBot,
214
214
  imessage_default
215
215
  };
216
- //# sourceMappingURL=chunk-GK3E2I7A.js.map
216
+ //# sourceMappingURL=chunk-NHMBTUMW.js.map
@@ -0,0 +1,131 @@
1
+ // src/tools/backup-restore.ts
2
+ import { join } from "path";
3
+ import { mkdir, readdir, stat, unlink } from "fs/promises";
4
+ import { homedir } from "os";
5
+ import { execFile } from "child_process";
6
+ import { promisify } from "util";
7
+ var execFileAsync = promisify(execFile);
8
+ var DEFAULT_BACKUP_DIR = join(homedir(), ".opensentinel", "backups");
9
+ async function createDatabaseBackup(options = {}) {
10
+ const outputDir = options.outputDir || DEFAULT_BACKUP_DIR;
11
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
12
+ const compress = options.compress ?? true;
13
+ try {
14
+ await mkdir(outputDir, { recursive: true });
15
+ const databaseUrl = process.env.DATABASE_URL;
16
+ if (!databaseUrl) {
17
+ return { success: false, error: "DATABASE_URL not set" };
18
+ }
19
+ const filename = compress ? `opensentinel-backup-${timestamp}.sql.gz` : `opensentinel-backup-${timestamp}.sql`;
20
+ const filePath = join(outputDir, filename);
21
+ if (compress) {
22
+ const { stdout } = await execFileAsync("pg_dump", [databaseUrl, "--no-owner", "--no-acl"], {
23
+ maxBuffer: 100 * 1024 * 1024
24
+ // 100MB
25
+ });
26
+ const { writeFile } = await import("fs/promises");
27
+ const { gzipSync } = await import("zlib");
28
+ await writeFile(filePath, gzipSync(Buffer.from(stdout)));
29
+ } else {
30
+ await execFileAsync("pg_dump", [databaseUrl, "--no-owner", "--no-acl", "-f", filePath], {
31
+ maxBuffer: 100 * 1024 * 1024
32
+ });
33
+ }
34
+ const stats = await stat(filePath);
35
+ if (options.maxBackups) {
36
+ await pruneOldBackups(outputDir, options.maxBackups);
37
+ }
38
+ return {
39
+ success: true,
40
+ filePath,
41
+ size: stats.size,
42
+ timestamp
43
+ };
44
+ } catch (error) {
45
+ return {
46
+ success: false,
47
+ error: error instanceof Error ? error.message : String(error)
48
+ };
49
+ }
50
+ }
51
+ async function restoreDatabase(backupPath) {
52
+ try {
53
+ const databaseUrl = process.env.DATABASE_URL;
54
+ if (!databaseUrl) {
55
+ return { success: false, error: "DATABASE_URL not set" };
56
+ }
57
+ const isCompressed = backupPath.endsWith(".gz");
58
+ if (isCompressed) {
59
+ const { readFile } = await import("fs/promises");
60
+ const { gunzipSync } = await import("zlib");
61
+ const compressed = await readFile(backupPath);
62
+ const sql = gunzipSync(compressed).toString("utf8");
63
+ await execFileAsync("psql", [databaseUrl], {
64
+ maxBuffer: 100 * 1024 * 1024
65
+ });
66
+ } else {
67
+ await execFileAsync("psql", [databaseUrl, "-f", backupPath], {
68
+ maxBuffer: 100 * 1024 * 1024
69
+ });
70
+ }
71
+ return { success: true, filePath: backupPath };
72
+ } catch (error) {
73
+ return {
74
+ success: false,
75
+ error: error instanceof Error ? error.message : String(error)
76
+ };
77
+ }
78
+ }
79
+ async function listBackups(backupDir) {
80
+ const dir = backupDir || DEFAULT_BACKUP_DIR;
81
+ try {
82
+ await mkdir(dir, { recursive: true });
83
+ const files = await readdir(dir);
84
+ const backups = [];
85
+ for (const file of files) {
86
+ if (file.startsWith("opensentinel-backup-") && (file.endsWith(".sql") || file.endsWith(".sql.gz"))) {
87
+ const filePath = join(dir, file);
88
+ const stats = await stat(filePath);
89
+ backups.push({
90
+ filename: file,
91
+ path: filePath,
92
+ size: stats.size,
93
+ created: stats.birthtime
94
+ });
95
+ }
96
+ }
97
+ return backups.sort((a, b) => b.created.getTime() - a.created.getTime());
98
+ } catch {
99
+ return [];
100
+ }
101
+ }
102
+ async function pruneOldBackups(dir, keep) {
103
+ const backups = await listBackups(dir);
104
+ if (backups.length <= keep) return;
105
+ const toDelete = backups.slice(keep);
106
+ for (const backup of toDelete) {
107
+ await unlink(backup.path).catch(() => {
108
+ });
109
+ }
110
+ }
111
+ function getBackupStatus() {
112
+ return {
113
+ hasDatabaseUrl: !!process.env.DATABASE_URL,
114
+ defaultDir: DEFAULT_BACKUP_DIR
115
+ };
116
+ }
117
+ var backup_restore_default = {
118
+ createDatabaseBackup,
119
+ restoreDatabase,
120
+ listBackups,
121
+ getBackupStatus
122
+ };
123
+
124
+ export {
125
+ createDatabaseBackup,
126
+ restoreDatabase,
127
+ listBackups,
128
+ getBackupStatus,
129
+ backup_restore_default
130
+ };
131
+ //# sourceMappingURL=chunk-NPRTSZIF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tools/backup-restore.ts"],"sourcesContent":["/**\r\n * Backup & Restore Module\r\n * Database backup, restore, and scheduling\r\n */\r\n\r\nimport { join } from \"path\";\r\nimport { mkdir, readdir, stat, unlink } from \"fs/promises\";\r\nimport { tmpdir, homedir } from \"os\";\r\nimport { execFile } from \"child_process\";\r\nimport { promisify } from \"util\";\r\n\r\nconst execFileAsync = promisify(execFile);\r\n\r\nexport interface BackupResult {\r\n success: boolean;\r\n filePath?: string;\r\n size?: number;\r\n timestamp?: string;\r\n error?: string;\r\n}\r\n\r\nexport interface BackupOptions {\r\n outputDir?: string;\r\n compress?: boolean;\r\n includeRedis?: boolean;\r\n maxBackups?: number;\r\n}\r\n\r\nexport interface BackupInfo {\r\n filename: string;\r\n path: string;\r\n size: number;\r\n created: Date;\r\n}\r\n\r\nconst DEFAULT_BACKUP_DIR = join(homedir(), \".opensentinel\", \"backups\");\r\n\r\n// Create a PostgreSQL backup using pg_dump\r\nexport async function createDatabaseBackup(\r\n options: BackupOptions = {}\r\n): Promise<BackupResult> {\r\n const outputDir = options.outputDir || DEFAULT_BACKUP_DIR;\r\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\r\n const compress = options.compress ?? true;\r\n\r\n try {\r\n await mkdir(outputDir, { recursive: true });\r\n\r\n const databaseUrl = process.env.DATABASE_URL;\r\n if (!databaseUrl) {\r\n return { success: false, error: \"DATABASE_URL not set\" };\r\n }\r\n\r\n const filename = compress\r\n ? `opensentinel-backup-${timestamp}.sql.gz`\r\n : `opensentinel-backup-${timestamp}.sql`;\r\n const filePath = join(outputDir, filename);\r\n\r\n if (compress) {\r\n // pg_dump | gzip\r\n const { stdout } = await execFileAsync(\"pg_dump\", [databaseUrl, \"--no-owner\", \"--no-acl\"], {\r\n maxBuffer: 100 * 1024 * 1024, // 100MB\r\n });\r\n\r\n const { writeFile } = await import(\"fs/promises\");\r\n const { gzipSync } = await import(\"zlib\");\r\n await writeFile(filePath, gzipSync(Buffer.from(stdout)));\r\n } else {\r\n await execFileAsync(\"pg_dump\", [databaseUrl, \"--no-owner\", \"--no-acl\", \"-f\", filePath], {\r\n maxBuffer: 100 * 1024 * 1024,\r\n });\r\n }\r\n\r\n const stats = await stat(filePath);\r\n\r\n // Prune old backups if maxBackups is set\r\n if (options.maxBackups) {\r\n await pruneOldBackups(outputDir, options.maxBackups);\r\n }\r\n\r\n return {\r\n success: true,\r\n filePath,\r\n size: stats.size,\r\n timestamp,\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : String(error),\r\n };\r\n }\r\n}\r\n\r\n// Restore a PostgreSQL backup\r\nexport async function restoreDatabase(\r\n backupPath: string\r\n): Promise<BackupResult> {\r\n try {\r\n const databaseUrl = process.env.DATABASE_URL;\r\n if (!databaseUrl) {\r\n return { success: false, error: \"DATABASE_URL not set\" };\r\n }\r\n\r\n const isCompressed = backupPath.endsWith(\".gz\");\r\n\r\n if (isCompressed) {\r\n const { readFile } = await import(\"fs/promises\");\r\n const { gunzipSync } = await import(\"zlib\");\r\n const compressed = await readFile(backupPath);\r\n const sql = gunzipSync(compressed).toString(\"utf8\");\r\n\r\n await execFileAsync(\"psql\", [databaseUrl], {\r\n maxBuffer: 100 * 1024 * 1024,\r\n });\r\n } else {\r\n await execFileAsync(\"psql\", [databaseUrl, \"-f\", backupPath], {\r\n maxBuffer: 100 * 1024 * 1024,\r\n });\r\n }\r\n\r\n return { success: true, filePath: backupPath };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : String(error),\r\n };\r\n }\r\n}\r\n\r\n// List available backups\r\nexport async function listBackups(\r\n backupDir?: string\r\n): Promise<BackupInfo[]> {\r\n const dir = backupDir || DEFAULT_BACKUP_DIR;\r\n\r\n try {\r\n await mkdir(dir, { recursive: true });\r\n const files = await readdir(dir);\r\n const backups: BackupInfo[] = [];\r\n\r\n for (const file of files) {\r\n if (file.startsWith(\"opensentinel-backup-\") && (file.endsWith(\".sql\") || file.endsWith(\".sql.gz\"))) {\r\n const filePath = join(dir, file);\r\n const stats = await stat(filePath);\r\n backups.push({\r\n filename: file,\r\n path: filePath,\r\n size: stats.size,\r\n created: stats.birthtime,\r\n });\r\n }\r\n }\r\n\r\n return backups.sort((a, b) => b.created.getTime() - a.created.getTime());\r\n } catch {\r\n return [];\r\n }\r\n}\r\n\r\n// Prune old backups, keeping only the most recent N\r\nasync function pruneOldBackups(dir: string, keep: number): Promise<void> {\r\n const backups = await listBackups(dir);\r\n if (backups.length <= keep) return;\r\n\r\n const toDelete = backups.slice(keep);\r\n for (const backup of toDelete) {\r\n await unlink(backup.path).catch(() => {});\r\n }\r\n}\r\n\r\n// Get backup status summary\r\nexport function getBackupStatus(): {\r\n hasDatabaseUrl: boolean;\r\n defaultDir: string;\r\n} {\r\n return {\r\n hasDatabaseUrl: !!process.env.DATABASE_URL,\r\n defaultDir: DEFAULT_BACKUP_DIR,\r\n };\r\n}\r\n\r\nexport default {\r\n createDatabaseBackup,\r\n restoreDatabase,\r\n listBackups,\r\n getBackupStatus,\r\n};\r\n"],"mappings":"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","names":[]}