opensentinel 3.1.1 → 3.7.0
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.
- package/README.md +138 -83
- package/dist/agent-manager-JZ4IM7XI.js +39 -0
- package/dist/agent-processor-DDDHC2SO.js +281 -0
- package/dist/agent-processor-DDDHC2SO.js.map +1 -0
- package/dist/agent-types-2T4PXLFQ.js +12 -0
- package/dist/alerting-LK7VVYTX.js +699 -0
- package/dist/alerting-LK7VVYTX.js.map +1 -0
- package/dist/analysis-agent-JWN2GXYE.js +288 -0
- package/dist/analysis-agent-JWN2GXYE.js.map +1 -0
- package/dist/analyzer-OTWE3ARE.js +22 -0
- package/dist/{archiver-AVNBYCKQ.js → archiver-FPGKRP6P.js} +2 -2
- package/dist/{audit-logger-OBPR7CRO.js → audit-logger-CI4WZQPD.js} +6 -5
- package/dist/{auth-UOX5K2BE.js → auth-PH5IHISW.js} +2 -2
- package/dist/{autonomy-ZXDBDQUJ.js → autonomy-N7W5XPLX.js} +4 -3
- package/dist/autonomy-N7W5XPLX.js.map +1 -0
- package/dist/{aws-s3-Q4LLZZPD.js → aws-s3-QZMURYXB.js} +2 -2
- package/dist/{backup-restore-PZ7CYYB7.js → backup-restore-72OQTZO3.js} +2 -2
- package/dist/{blocks-R3PODY47.js → blocks-YOWOESDD.js} +4 -4
- package/dist/bot-VDHBGUVI.js +47 -0
- package/dist/brain-6QTXN4QP.js +66 -0
- package/dist/{camera-monitor-M5CYKUU4.js → camera-monitor-LHTUWHEL.js} +2 -2
- package/dist/{charts-V7ARZNKF.js → charts-FJ32GQK7.js} +2 -2
- package/dist/{chunk-WRAKK6K6.js → chunk-2I5QHYG6.js} +5 -3
- package/dist/chunk-2I5QHYG6.js.map +1 -0
- package/dist/{chunk-TVEWKIK3.js → chunk-2WTKTG2C.js} +2 -2
- package/dist/chunk-3AWAWRWB.js +143 -0
- package/dist/chunk-3AWAWRWB.js.map +1 -0
- package/dist/{chunk-ZLZKF2PM.js → chunk-4KIHDIXZ.js} +43 -2
- package/dist/chunk-4KIHDIXZ.js.map +1 -0
- package/dist/{chunk-EVE7MIIY.js → chunk-4WH6MFEW.js} +15 -16
- package/dist/chunk-4WH6MFEW.js.map +1 -0
- package/dist/{chunk-I6BDYQIG.js → chunk-56UJS2LA.js} +6 -6
- package/dist/chunk-56UJS2LA.js.map +1 -0
- package/dist/chunk-5BTVJR7R.js +37 -0
- package/dist/chunk-5BTVJR7R.js.map +1 -0
- package/dist/chunk-5JJTLWOR.js +1021 -0
- package/dist/chunk-5JJTLWOR.js.map +1 -0
- package/dist/chunk-66SAOZPU.js +236 -0
- package/dist/chunk-66SAOZPU.js.map +1 -0
- package/dist/chunk-6HGMRR4J.js +113 -0
- package/dist/chunk-6HGMRR4J.js.map +1 -0
- package/dist/chunk-6W6PTJFT.js +181 -0
- package/dist/chunk-6W6PTJFT.js.map +1 -0
- package/dist/chunk-6ZNCY2GI.js +418 -0
- package/dist/chunk-6ZNCY2GI.js.map +1 -0
- package/dist/chunk-7BNFELEK.js +31 -0
- package/dist/chunk-7BNFELEK.js.map +1 -0
- package/dist/chunk-ADTDYJO7.js +265 -0
- package/dist/chunk-ADTDYJO7.js.map +1 -0
- package/dist/{chunk-OCVQGBJK.js → chunk-BBN4VCNK.js} +6 -4
- package/dist/chunk-BBN4VCNK.js.map +1 -0
- package/dist/{chunk-SJSUSJ47.js → chunk-BNZHWAZC.js} +2 -2
- package/dist/chunk-C6PELIHS.js +60 -0
- package/dist/chunk-C6PELIHS.js.map +1 -0
- package/dist/{chunk-MQJ2ECQT.js → chunk-CUPEENUY.js} +3 -3
- package/dist/{chunk-NHMBTUMW.js → chunk-CWT6CAE5.js} +2 -2
- package/dist/{chunk-4GLYY4NN.js → chunk-CZTMGHUC.js} +8 -2
- package/dist/chunk-CZTMGHUC.js.map +1 -0
- package/dist/{chunk-RZ4YESBG.js → chunk-DOYGMNMK.js} +1 -1
- package/dist/chunk-DOYGMNMK.js.map +1 -0
- package/dist/chunk-DTISLIMB.js +89 -0
- package/dist/chunk-DTISLIMB.js.map +1 -0
- package/dist/{chunk-SPPMCAKG.js → chunk-GBVJTRXS.js} +2 -2
- package/dist/chunk-GBVJTRXS.js.map +1 -0
- package/dist/{chunk-AYUKPTSM.js → chunk-GJETKBOY.js} +96 -218
- package/dist/chunk-GJETKBOY.js.map +1 -0
- package/dist/{chunk-BXZ6EA52.js → chunk-GW6V4D43.js} +57 -3
- package/dist/chunk-GW6V4D43.js.map +1 -0
- package/dist/{chunk-6PMVAAA7.js → chunk-HJSEEFO3.js} +3 -3
- package/dist/{chunk-TYAGMJNV.js → chunk-HQZQFEAX.js} +5 -5
- package/dist/{chunk-MXAPLSJ5.js → chunk-J4JW73TT.js} +2 -2
- package/dist/{chunk-VEHFVBLI.js → chunk-JHYYFPKX.js} +2 -2
- package/dist/chunk-LFDXEYYB.js +150 -0
- package/dist/chunk-LFDXEYYB.js.map +1 -0
- package/dist/chunk-MIC5IBQF.js +386 -0
- package/dist/chunk-MIC5IBQF.js.map +1 -0
- package/dist/chunk-ODCFS5WD.js +463 -0
- package/dist/chunk-ODCFS5WD.js.map +1 -0
- package/dist/{chunk-XMCVRVTF.js → chunk-P64EV4YY.js} +1 -1
- package/dist/chunk-P64EV4YY.js.map +1 -0
- package/dist/chunk-PBOCSGNL.js +84 -0
- package/dist/chunk-PBOCSGNL.js.map +1 -0
- package/dist/{chunk-66OJ3WB4.js → chunk-PD3CTDO6.js} +2 -2
- package/dist/chunk-QPY3WRVM.js +647 -0
- package/dist/chunk-QPY3WRVM.js.map +1 -0
- package/dist/chunk-S2EOIVF4.js +3907 -0
- package/dist/chunk-S2EOIVF4.js.map +1 -0
- package/dist/chunk-SDLOMKCW.js +213 -0
- package/dist/chunk-SDLOMKCW.js.map +1 -0
- package/dist/chunk-TKBVW7ZJ.js +162 -0
- package/dist/chunk-TKBVW7ZJ.js.map +1 -0
- package/dist/{chunk-BRBWNV65.js → chunk-U2X2J3FI.js} +3 -3
- package/dist/chunk-U2X2J3FI.js.map +1 -0
- package/dist/{chunk-PLDDJCW6.js → chunk-UP2VWCW5.js} +1 -12
- package/dist/{chunk-SVAPX2XN.js → chunk-V3OKHQUX.js} +9 -7
- package/dist/{chunk-SVAPX2XN.js.map → chunk-V3OKHQUX.js.map} +1 -1
- package/dist/{chunk-4UOE5TUZ.js → chunk-WMDVOWN6.js} +4 -4
- package/dist/chunk-WMFYI7XC.js +564 -0
- package/dist/chunk-WMFYI7XC.js.map +1 -0
- package/dist/chunk-WZAH34TG.js +129 -0
- package/dist/chunk-WZAH34TG.js.map +1 -0
- package/dist/{chunk-H5RQOFO2.js → chunk-X6Q3K3L2.js} +6 -6
- package/dist/chunk-X6Q3K3L2.js.map +1 -0
- package/dist/chunk-XTX7EK43.js +134 -0
- package/dist/chunk-XTX7EK43.js.map +1 -0
- package/dist/chunk-YEDEAX6Y.js +194 -0
- package/dist/chunk-YEDEAX6Y.js.map +1 -0
- package/dist/{chunk-XKYRH4FM.js → chunk-ZIBRVA3Y.js} +70 -30
- package/dist/chunk-ZIBRVA3Y.js.map +1 -0
- package/dist/chunk-ZIYTHUM5.js +457 -0
- package/dist/chunk-ZIYTHUM5.js.map +1 -0
- package/dist/{chunk-766ASQWE.js → chunk-ZMML6T63.js} +2711 -2329
- package/dist/chunk-ZMML6T63.js.map +1 -0
- package/dist/chunk-ZVHG4KF2.js +380 -0
- package/dist/chunk-ZVHG4KF2.js.map +1 -0
- package/dist/chunker-K6WTR62A.js +12 -0
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/{client-ZQSFPMOB.js → client-FOIYPOZQ.js} +5 -6
- package/dist/{clipboard-manager-TEO2GEDN.js → clipboard-manager-4SBNESGZ.js} +2 -2
- package/dist/coding-agent-DESSU3AC.js +233 -0
- package/dist/coding-agent-DESSU3AC.js.map +1 -0
- package/dist/commands/setup.js +2 -2
- package/dist/commands/start.js +3 -3
- package/dist/commands/status.js +2 -2
- package/dist/commands/stop.js +2 -2
- package/dist/commands/utils.js +2 -2
- package/dist/cost-tracker-KZQSTSE2.js +11 -0
- package/dist/{cron-explain-HHQKPD3M.js → cron-explain-UOOOYWZZ.js} +2 -2
- package/dist/{crypto-4AP47IKC.js → crypto-2VG3RJR2.js} +2 -2
- package/dist/{databases-37X4CI2Y.js → databases-XDPMG5AV.js} +4 -4
- package/dist/db-I7MNG6CL.js +83 -0
- package/dist/discord-6UQHCN27.js +81 -0
- package/dist/documents-PFHSK7SZ.js +184 -0
- package/dist/documents-PFHSK7SZ.js.map +1 -0
- package/dist/docx-parser-EXL4TN5E.js +16 -0
- package/dist/{email-K7LO2IPB.js → email-6OIN4SYL.js} +34 -25
- package/dist/email-6OIN4SYL.js.map +1 -0
- package/dist/{enhanced-retrieval-DNLLEM4Z.js → enhanced-retrieval-JWX2HWU4.js} +12 -8
- package/dist/{enhanced-retrieval-DNLLEM4Z.js.map → enhanced-retrieval-JWX2HWU4.js.map} +1 -1
- package/dist/enrichment-pipeline-7FE5R5ZI.js +14 -0
- package/dist/{entity-resolution-Y3IUWEAT.js → entity-resolution-7Z6STVXX.js} +6 -5
- package/dist/env-GN5VHI43.js +12 -0
- package/dist/error-tracker-64DEH3D7.js +32 -0
- package/dist/finnhub-X7ZMQSXF.js +178 -0
- package/dist/finnhub-X7ZMQSXF.js.map +1 -0
- package/dist/fred-TMUF3J2V.js +203 -0
- package/dist/fred-TMUF3J2V.js.map +1 -0
- package/dist/github-DUWSXCNP.js +833 -0
- package/dist/github-DUWSXCNP.js.map +1 -0
- package/dist/{google-workspace-DKWUVNGC.js → google-workspace-TSZPZK5G.js} +2 -2
- package/dist/graph-client-NB475AK5.js +17 -0
- package/dist/{hash-tool-ULQYD7B5.js → hash-tool-ENAB5LWH.js} +2 -2
- package/dist/{heartbeat-monitor-GCISLXI3.js → heartbeat-monitor-KRDYTDBF.js} +2 -2
- package/dist/hooks-N4MIFBVM.js +14 -0
- package/dist/{image-generation-OSU7FP6F.js → image-generation-MDE6AVQO.js} +2 -2
- package/dist/imessage-DSGSGUZS.js +44 -0
- package/dist/inbox-summarizer-F2KAU72V.js +56 -0
- package/dist/{incident-response-C5J7Q6DT.js → incident-response-E3UGMX5G.js} +8 -6
- package/dist/incident-response-E3UGMX5G.js.map +1 -0
- package/dist/{inventory-manager-352OHXWD.js → inventory-manager-C67BSZM6.js} +2 -2
- package/dist/{jira-GSGDBMIG.js → jira-PAGZWUBJ.js} +2 -2
- package/dist/{json-tool-QE2SYHEG.js → json-tool-4FK5RNER.js} +2 -2
- package/dist/{key-rotation-DPHU4ZTB.js → key-rotation-WCC5FOYS.js} +2 -2
- package/dist/knowledge-base-5SMMOGQJ.js +46 -0
- package/dist/lib.d.ts +94 -1
- package/dist/lib.js +83 -66
- package/dist/lib.js.map +1 -1
- package/dist/{mailchimp-KKNF6QJ7.js → mailchimp-ZFYDC44J.js} +2 -2
- package/dist/{matrix-QVHG76I7.js → matrix-WYGEOZL5.js} +30 -21
- package/dist/{matrix-QVHG76I7.js.map → matrix-WYGEOZL5.js.map} +1 -1
- package/dist/{mcp-3JI6W7ZE.js → mcp-DJ2QDA6A.js} +3 -3
- package/dist/metrics-BH3ZLGEV.js +25 -0
- package/dist/{microsoft365-UCBKJHNX.js → microsoft365-6G2IJMWC.js} +2 -2
- package/dist/multi-user-XAEMB244.js +411 -0
- package/dist/multi-user-XAEMB244.js.map +1 -0
- package/dist/oauth-UPJYFOVU.js +34 -0
- package/dist/{ocr-AC7NPX33.js → ocr-UONKTQU7.js} +6 -4
- package/dist/{ollama-BOAMSPLJ.js → ollama-J7CU45WT.js} +2 -2
- package/dist/osint-agent-RL5XPBRQ.js +189 -0
- package/dist/osint-agent-RL5XPBRQ.js.map +1 -0
- package/dist/{pages-MI523RB7.js → pages-XDE7JRCA.js} +5 -5
- package/dist/{pair-JDFTERIK.js → pair-YZJFQUU5.js} +2 -2
- package/dist/{pairing-IFQYCPNS.js → pairing-77N47RAT.js} +2 -2
- package/dist/{pdf-ALQVOEJR.js → pdf-67HGXCFJ.js} +3 -3
- package/dist/pdf-parser-YLMTTYHL.js +14 -0
- package/dist/{presentations-DSV5IHG5.js → presentations-UOET2FVZ.js} +3 -3
- package/dist/presentations-UOET2FVZ.js.map +1 -0
- package/dist/{prometheus-JNT2BD4L.js → prometheus-YETCZO4I.js} +2 -2
- package/dist/prometheus-YETCZO4I.js.map +1 -0
- package/dist/{providers-J4LYPHDR.js → providers-2YQ6E3IF.js} +6 -4
- package/dist/providers-2YQ6E3IF.js.map +1 -0
- package/dist/{qr-code-WIX4PB4U.js → qr-code-6WZJHRKL.js} +2 -2
- package/dist/qr-code-6WZJHRKL.js.map +1 -0
- package/dist/{quickbooks-XB4NII2S.js → quickbooks-N675W7IK.js} +2 -2
- package/dist/{regex-tool-W4ABRKGK.js → regex-tool-6Q63LQ7B.js} +2 -2
- package/dist/regex-tool-6Q63LQ7B.js.map +1 -0
- package/dist/research-agent-WCRSY3UZ.js +168 -0
- package/dist/research-agent-WCRSY3UZ.js.map +1 -0
- package/dist/risk-engine-YKCPT5D5.js +10 -0
- package/dist/risk-engine-YKCPT5D5.js.map +1 -0
- package/dist/scheduler-6PLLAQI7.js +74 -0
- package/dist/scheduler-6PLLAQI7.js.map +1 -0
- package/dist/schema-ETY7L2VA.js +78 -0
- package/dist/schema-ETY7L2VA.js.map +1 -0
- package/dist/{search-BCLBO5E3.js → search-GMLKBHSW.js} +4 -4
- package/dist/search-GMLKBHSW.js.map +1 -0
- package/dist/{sendgrid-RNXCAFKM.js → sendgrid-QGJIVPWV.js} +2 -2
- package/dist/sharepoint-V5P4Q62L.js +30 -0
- package/dist/sharepoint-V5P4Q62L.js.map +1 -0
- package/dist/{shopify-NCXYJB4R.js → shopify-ON2PAU27.js} +2 -2
- package/dist/signal-7D5EPGVL.js +44 -0
- package/dist/signal-7D5EPGVL.js.map +1 -0
- package/dist/slack-KSS6YK5Z.js +86 -0
- package/dist/slack-KSS6YK5Z.js.map +1 -0
- package/dist/{sms-M3JIOTCW.js → sms-CSUCC7HL.js} +4 -4
- package/dist/sms-CSUCC7HL.js.map +1 -0
- package/dist/{src-VYUE6LRA.js → src-GO7GGW7O.js} +190 -52
- package/dist/src-GO7GGW7O.js.map +1 -0
- package/dist/{stocks-XXWBPOCU.js → stocks-4M4HZWZS.js} +2 -2
- package/dist/stocks-4M4HZWZS.js.map +1 -0
- package/dist/text-extractor-OAUBAW5P.js +12 -0
- package/dist/text-extractor-OAUBAW5P.js.map +1 -0
- package/dist/{text-transform-6SGUA5Z4.js → text-transform-HCLCUDFZ.js} +2 -2
- package/dist/text-transform-HCLCUDFZ.js.map +1 -0
- package/dist/token-store-SEWRX6RE.js +20 -0
- package/dist/token-store-SEWRX6RE.js.map +1 -0
- package/dist/tools-PJZ6RI4P.js +47 -0
- package/dist/tools-PJZ6RI4P.js.map +1 -0
- package/dist/{tunnel-IWMXUML4.js → tunnel-XOUVVRAK.js} +4 -2
- package/dist/tunnel-XOUVVRAK.js.map +1 -0
- package/dist/{twilio-53GEW5JT.js → twilio-3L7DUNYQ.js} +2 -2
- package/dist/{unit-converter-ZYXMEZOE.js → unit-converter-LYPAHU64.js} +2 -2
- package/dist/unit-converter-LYPAHU64.js.map +1 -0
- package/dist/whatsapp-DWXK25V2.js +44 -0
- package/dist/whatsapp-DWXK25V2.js.map +1 -0
- package/dist/{word-document-7B6SJMAY.js → word-document-AV3YB4L2.js} +4 -4
- package/dist/word-document-AV3YB4L2.js.map +1 -0
- package/dist/workflow-store-5Y56GUP7.js +373 -0
- package/dist/workflow-store-5Y56GUP7.js.map +1 -0
- package/dist/writing-agent-VDGLNOGO.js +243 -0
- package/dist/writing-agent-VDGLNOGO.js.map +1 -0
- package/dist/{xero-QYO66D45.js → xero-UHAHVYSD.js} +2 -2
- package/dist/{zapier-webhook-TBZ5YF2A.js → zapier-webhook-NIELLTXR.js} +2 -2
- package/drizzle/0002_mushy_master_mold.sql +139 -139
- package/drizzle/0003_overjoyed_rhodey.sql +46 -0
- package/drizzle/meta/0002_snapshot.json +3636 -3636
- package/drizzle/meta/0003_snapshot.json +3946 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +110 -100
- package/dist/autonomy-ZXDBDQUJ.js.map +0 -1
- package/dist/bot-QRARP4UN.js +0 -36
- package/dist/brain-7XLLM3KC.js +0 -56
- package/dist/chunk-4GLYY4NN.js.map +0 -1
- package/dist/chunk-766ASQWE.js.map +0 -1
- package/dist/chunk-AYUKPTSM.js.map +0 -1
- package/dist/chunk-BRBWNV65.js.map +0 -1
- package/dist/chunk-BXZ6EA52.js.map +0 -1
- package/dist/chunk-EVE7MIIY.js.map +0 -1
- package/dist/chunk-H5RQOFO2.js.map +0 -1
- package/dist/chunk-I6BDYQIG.js.map +0 -1
- package/dist/chunk-IZJMVV7O.js +0 -347
- package/dist/chunk-IZJMVV7O.js.map +0 -1
- package/dist/chunk-O7IH7JTI.js +0 -1898
- package/dist/chunk-O7IH7JTI.js.map +0 -1
- package/dist/chunk-OCVQGBJK.js.map +0 -1
- package/dist/chunk-RZ4YESBG.js.map +0 -1
- package/dist/chunk-SPPMCAKG.js.map +0 -1
- package/dist/chunk-VRD5CYRL.js +0 -1568
- package/dist/chunk-VRD5CYRL.js.map +0 -1
- package/dist/chunk-WRAKK6K6.js.map +0 -1
- package/dist/chunk-XKYRH4FM.js.map +0 -1
- package/dist/chunk-XMCVRVTF.js.map +0 -1
- package/dist/chunk-ZLZKF2PM.js.map +0 -1
- package/dist/discord-B3HUPGQ6.js +0 -70
- package/dist/dist-UISMLMFN.js +0 -21847
- package/dist/dist-UISMLMFN.js.map +0 -1
- package/dist/email-K7LO2IPB.js.map +0 -1
- package/dist/enrichment-pipeline-MNHNW65K.js +0 -13
- package/dist/env-IWXUVTCB.js +0 -12
- package/dist/imessage-NGA2XF2V.js +0 -35
- package/dist/inbox-summarizer-NRI4S7IF.js +0 -47
- package/dist/incident-response-C5J7Q6DT.js.map +0 -1
- package/dist/presentations-DSV5IHG5.js.map +0 -1
- package/dist/scheduler-VK4WFERV.js +0 -63
- package/dist/signal-6CGDFYL2.js +0 -35
- package/dist/slack-IZQWIKOH.js +0 -75
- package/dist/src-VYUE6LRA.js.map +0 -1
- package/dist/tools-2RLEI2N6.js +0 -38
- package/dist/tunnel-IWMXUML4.js.map +0 -1
- package/dist/whatsapp-LFX6YKCM.js +0 -35
- package/dist/word-document-7B6SJMAY.js.map +0 -1
- /package/dist/{audit-logger-OBPR7CRO.js.map → agent-manager-JZ4IM7XI.js.map} +0 -0
- /package/dist/{auth-UOX5K2BE.js.map → agent-types-2T4PXLFQ.js.map} +0 -0
- /package/dist/{backup-restore-PZ7CYYB7.js.map → analyzer-OTWE3ARE.js.map} +0 -0
- /package/dist/{archiver-AVNBYCKQ.js.map → archiver-FPGKRP6P.js.map} +0 -0
- /package/dist/{blocks-R3PODY47.js.map → audit-logger-CI4WZQPD.js.map} +0 -0
- /package/dist/{bot-QRARP4UN.js.map → auth-PH5IHISW.js.map} +0 -0
- /package/dist/{aws-s3-Q4LLZZPD.js.map → aws-s3-QZMURYXB.js.map} +0 -0
- /package/dist/{brain-7XLLM3KC.js.map → backup-restore-72OQTZO3.js.map} +0 -0
- /package/dist/{chunk-PLDDJCW6.js.map → blocks-YOWOESDD.js.map} +0 -0
- /package/dist/{client-ZQSFPMOB.js.map → bot-VDHBGUVI.js.map} +0 -0
- /package/dist/{clipboard-manager-TEO2GEDN.js.map → brain-6QTXN4QP.js.map} +0 -0
- /package/dist/{camera-monitor-M5CYKUU4.js.map → camera-monitor-LHTUWHEL.js.map} +0 -0
- /package/dist/{charts-V7ARZNKF.js.map → charts-FJ32GQK7.js.map} +0 -0
- /package/dist/{chunk-TVEWKIK3.js.map → chunk-2WTKTG2C.js.map} +0 -0
- /package/dist/{chunk-SJSUSJ47.js.map → chunk-BNZHWAZC.js.map} +0 -0
- /package/dist/{chunk-MQJ2ECQT.js.map → chunk-CUPEENUY.js.map} +0 -0
- /package/dist/{chunk-NHMBTUMW.js.map → chunk-CWT6CAE5.js.map} +0 -0
- /package/dist/{chunk-6PMVAAA7.js.map → chunk-HJSEEFO3.js.map} +0 -0
- /package/dist/{chunk-TYAGMJNV.js.map → chunk-HQZQFEAX.js.map} +0 -0
- /package/dist/{chunk-MXAPLSJ5.js.map → chunk-J4JW73TT.js.map} +0 -0
- /package/dist/{chunk-VEHFVBLI.js.map → chunk-JHYYFPKX.js.map} +0 -0
- /package/dist/{chunk-66OJ3WB4.js.map → chunk-PD3CTDO6.js.map} +0 -0
- /package/dist/{cron-explain-HHQKPD3M.js.map → chunk-UP2VWCW5.js.map} +0 -0
- /package/dist/{chunk-4UOE5TUZ.js.map → chunk-WMDVOWN6.js.map} +0 -0
- /package/dist/{crypto-4AP47IKC.js.map → chunker-K6WTR62A.js.map} +0 -0
- /package/dist/{databases-37X4CI2Y.js.map → client-FOIYPOZQ.js.map} +0 -0
- /package/dist/{discord-B3HUPGQ6.js.map → clipboard-manager-4SBNESGZ.js.map} +0 -0
- /package/dist/{enrichment-pipeline-MNHNW65K.js.map → cost-tracker-KZQSTSE2.js.map} +0 -0
- /package/dist/{entity-resolution-Y3IUWEAT.js.map → cron-explain-UOOOYWZZ.js.map} +0 -0
- /package/dist/{env-IWXUVTCB.js.map → crypto-2VG3RJR2.js.map} +0 -0
- /package/dist/{hash-tool-ULQYD7B5.js.map → databases-XDPMG5AV.js.map} +0 -0
- /package/dist/{heartbeat-monitor-GCISLXI3.js.map → db-I7MNG6CL.js.map} +0 -0
- /package/dist/{imessage-NGA2XF2V.js.map → discord-6UQHCN27.js.map} +0 -0
- /package/dist/{inbox-summarizer-NRI4S7IF.js.map → docx-parser-EXL4TN5E.js.map} +0 -0
- /package/dist/{inventory-manager-352OHXWD.js.map → enrichment-pipeline-7FE5R5ZI.js.map} +0 -0
- /package/dist/{json-tool-QE2SYHEG.js.map → entity-resolution-7Z6STVXX.js.map} +0 -0
- /package/dist/{key-rotation-DPHU4ZTB.js.map → env-GN5VHI43.js.map} +0 -0
- /package/dist/{mcp-3JI6W7ZE.js.map → error-tracker-64DEH3D7.js.map} +0 -0
- /package/dist/{google-workspace-DKWUVNGC.js.map → google-workspace-TSZPZK5G.js.map} +0 -0
- /package/dist/{ocr-AC7NPX33.js.map → graph-client-NB475AK5.js.map} +0 -0
- /package/dist/{ollama-BOAMSPLJ.js.map → hash-tool-ENAB5LWH.js.map} +0 -0
- /package/dist/{pages-MI523RB7.js.map → heartbeat-monitor-KRDYTDBF.js.map} +0 -0
- /package/dist/{pairing-IFQYCPNS.js.map → hooks-N4MIFBVM.js.map} +0 -0
- /package/dist/{image-generation-OSU7FP6F.js.map → image-generation-MDE6AVQO.js.map} +0 -0
- /package/dist/{pdf-ALQVOEJR.js.map → imessage-DSGSGUZS.js.map} +0 -0
- /package/dist/{prometheus-JNT2BD4L.js.map → inbox-summarizer-F2KAU72V.js.map} +0 -0
- /package/dist/{providers-J4LYPHDR.js.map → inventory-manager-C67BSZM6.js.map} +0 -0
- /package/dist/{jira-GSGDBMIG.js.map → jira-PAGZWUBJ.js.map} +0 -0
- /package/dist/{qr-code-WIX4PB4U.js.map → json-tool-4FK5RNER.js.map} +0 -0
- /package/dist/{regex-tool-W4ABRKGK.js.map → key-rotation-WCC5FOYS.js.map} +0 -0
- /package/dist/{scheduler-VK4WFERV.js.map → knowledge-base-5SMMOGQJ.js.map} +0 -0
- /package/dist/{mailchimp-KKNF6QJ7.js.map → mailchimp-ZFYDC44J.js.map} +0 -0
- /package/dist/{search-BCLBO5E3.js.map → mcp-DJ2QDA6A.js.map} +0 -0
- /package/dist/{signal-6CGDFYL2.js.map → metrics-BH3ZLGEV.js.map} +0 -0
- /package/dist/{microsoft365-UCBKJHNX.js.map → microsoft365-6G2IJMWC.js.map} +0 -0
- /package/dist/{slack-IZQWIKOH.js.map → oauth-UPJYFOVU.js.map} +0 -0
- /package/dist/{sms-M3JIOTCW.js.map → ocr-UONKTQU7.js.map} +0 -0
- /package/dist/{stocks-XXWBPOCU.js.map → ollama-J7CU45WT.js.map} +0 -0
- /package/dist/{text-transform-6SGUA5Z4.js.map → pages-XDE7JRCA.js.map} +0 -0
- /package/dist/{pair-JDFTERIK.js.map → pair-YZJFQUU5.js.map} +0 -0
- /package/dist/{tools-2RLEI2N6.js.map → pairing-77N47RAT.js.map} +0 -0
- /package/dist/{unit-converter-ZYXMEZOE.js.map → pdf-67HGXCFJ.js.map} +0 -0
- /package/dist/{whatsapp-LFX6YKCM.js.map → pdf-parser-YLMTTYHL.js.map} +0 -0
- /package/dist/{quickbooks-XB4NII2S.js.map → quickbooks-N675W7IK.js.map} +0 -0
- /package/dist/{sendgrid-RNXCAFKM.js.map → sendgrid-QGJIVPWV.js.map} +0 -0
- /package/dist/{shopify-NCXYJB4R.js.map → shopify-ON2PAU27.js.map} +0 -0
- /package/dist/{twilio-53GEW5JT.js.map → twilio-3L7DUNYQ.js.map} +0 -0
- /package/dist/{xero-QYO66D45.js.map → xero-UHAHVYSD.js.map} +0 -0
- /package/dist/{zapier-webhook-TBZ5YF2A.js.map → zapier-webhook-NIELLTXR.js.map} +0 -0
package/dist/chunk-O7IH7JTI.js
DELETED
|
@@ -1,1898 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
textToSpeech
|
|
3
|
-
} from "./chunk-MXAPLSJ5.js";
|
|
4
|
-
import {
|
|
5
|
-
transcribeAudio
|
|
6
|
-
} from "./chunk-SJSUSJ47.js";
|
|
7
|
-
import {
|
|
8
|
-
ImapClient,
|
|
9
|
-
SmtpClient,
|
|
10
|
-
TOOLS,
|
|
11
|
-
chat,
|
|
12
|
-
chatWithTools,
|
|
13
|
-
executeTool,
|
|
14
|
-
getAppProfile,
|
|
15
|
-
init_imap_client,
|
|
16
|
-
init_smtp_client,
|
|
17
|
-
prioritizeTools
|
|
18
|
-
} from "./chunk-766ASQWE.js";
|
|
19
|
-
import {
|
|
20
|
-
decryptField,
|
|
21
|
-
deleteMemory,
|
|
22
|
-
exportMemories,
|
|
23
|
-
getMemoryById,
|
|
24
|
-
searchMemories,
|
|
25
|
-
storeMemory,
|
|
26
|
-
updateMemory
|
|
27
|
-
} from "./chunk-IZJMVV7O.js";
|
|
28
|
-
import {
|
|
29
|
-
createPublicRecords
|
|
30
|
-
} from "./chunk-SVAPX2XN.js";
|
|
31
|
-
import {
|
|
32
|
-
resolveEntity
|
|
33
|
-
} from "./chunk-WRAKK6K6.js";
|
|
34
|
-
import {
|
|
35
|
-
getAuditChainIntegrity,
|
|
36
|
-
logAudit,
|
|
37
|
-
queryAuditLogs
|
|
38
|
-
} from "./chunk-OCVQGBJK.js";
|
|
39
|
-
import {
|
|
40
|
-
apiKeys,
|
|
41
|
-
conversations,
|
|
42
|
-
db,
|
|
43
|
-
graphEntities,
|
|
44
|
-
graphRelationships,
|
|
45
|
-
memories,
|
|
46
|
-
messages,
|
|
47
|
-
sessions
|
|
48
|
-
} from "./chunk-XKYRH4FM.js";
|
|
49
|
-
import {
|
|
50
|
-
env
|
|
51
|
-
} from "./chunk-ZLZKF2PM.js";
|
|
52
|
-
import {
|
|
53
|
-
__require
|
|
54
|
-
} from "./chunk-PLDDJCW6.js";
|
|
55
|
-
|
|
56
|
-
// src/inputs/api/server.ts
|
|
57
|
-
import { Hono as Hono5 } from "hono";
|
|
58
|
-
import { cors } from "hono/cors";
|
|
59
|
-
import { logger } from "hono/logger";
|
|
60
|
-
import { desc as desc2, eq as eq4 } from "drizzle-orm";
|
|
61
|
-
|
|
62
|
-
// src/core/security/api-key-manager.ts
|
|
63
|
-
import { eq, and, isNull } from "drizzle-orm";
|
|
64
|
-
import { randomBytes, createHash } from "crypto";
|
|
65
|
-
var KEY_PREFIX = "mb_";
|
|
66
|
-
function hashApiKey(key) {
|
|
67
|
-
return createHash("sha256").update(key).digest("hex");
|
|
68
|
-
}
|
|
69
|
-
async function validateApiKey(rawKey) {
|
|
70
|
-
if (!rawKey.startsWith(KEY_PREFIX)) {
|
|
71
|
-
return { valid: false };
|
|
72
|
-
}
|
|
73
|
-
const keyHash = hashApiKey(rawKey);
|
|
74
|
-
const now = /* @__PURE__ */ new Date();
|
|
75
|
-
const [key] = await db.select().from(apiKeys).where(
|
|
76
|
-
and(
|
|
77
|
-
eq(apiKeys.keyHash, keyHash),
|
|
78
|
-
isNull(apiKeys.revokedAt)
|
|
79
|
-
)
|
|
80
|
-
).limit(1);
|
|
81
|
-
if (!key) {
|
|
82
|
-
return { valid: false };
|
|
83
|
-
}
|
|
84
|
-
if (key.expiresAt && key.expiresAt < now) {
|
|
85
|
-
return { valid: false };
|
|
86
|
-
}
|
|
87
|
-
await db.update(apiKeys).set({ lastUsedAt: now }).where(eq(apiKeys.id, key.id));
|
|
88
|
-
return {
|
|
89
|
-
valid: true,
|
|
90
|
-
apiKey: {
|
|
91
|
-
id: key.id,
|
|
92
|
-
name: key.name,
|
|
93
|
-
prefix: key.keyPrefix,
|
|
94
|
-
permissions: key.permissions || [],
|
|
95
|
-
createdAt: key.createdAt,
|
|
96
|
-
lastUsedAt: now,
|
|
97
|
-
expiresAt: key.expiresAt,
|
|
98
|
-
isRevoked: false
|
|
99
|
-
},
|
|
100
|
-
userId: key.userId
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
function hasPermission(apiKeyPermissions, requiredPermission) {
|
|
104
|
-
if (apiKeyPermissions.includes("*")) {
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
return apiKeyPermissions.includes(requiredPermission);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// src/core/security/session-manager.ts
|
|
111
|
-
import { eq as eq2, and as and2, gt, lt } from "drizzle-orm";
|
|
112
|
-
import { randomBytes as randomBytes2, createHash as createHash2 } from "crypto";
|
|
113
|
-
var SESSION_DURATION_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
114
|
-
function hashToken(token) {
|
|
115
|
-
return createHash2("sha256").update(token).digest("hex");
|
|
116
|
-
}
|
|
117
|
-
async function validateSession(token) {
|
|
118
|
-
const tokenHash = hashToken(token);
|
|
119
|
-
const now = /* @__PURE__ */ new Date();
|
|
120
|
-
const [session] = await db.select().from(sessions).where(and2(eq2(sessions.token, tokenHash), gt(sessions.expiresAt, now))).limit(1);
|
|
121
|
-
if (!session) {
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
await db.update(sessions).set({ lastActiveAt: now }).where(eq2(sessions.id, session.id));
|
|
125
|
-
return {
|
|
126
|
-
userId: session.userId,
|
|
127
|
-
sessionId: session.id,
|
|
128
|
-
expiresAt: session.expiresAt,
|
|
129
|
-
deviceInfo: session.deviceInfo
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// src/core/security/gateway-utils.ts
|
|
134
|
-
function getGatewayToken() {
|
|
135
|
-
const token = env.GATEWAY_TOKEN;
|
|
136
|
-
return token || void 0;
|
|
137
|
-
}
|
|
138
|
-
function timingSafeEqual(a, b) {
|
|
139
|
-
if (a.length !== b.length) {
|
|
140
|
-
let result2 = 1;
|
|
141
|
-
for (let i = 0; i < b.length; i++) {
|
|
142
|
-
result2 |= b.charCodeAt(i) ^ (a.charCodeAt(i % (a.length || 1)) || 0);
|
|
143
|
-
}
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
let result = 0;
|
|
147
|
-
for (let i = 0; i < a.length; i++) {
|
|
148
|
-
result |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
149
|
-
}
|
|
150
|
-
return result === 0;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// src/core/security/auth-middleware.ts
|
|
154
|
-
var PUBLIC_ROUTES = ["/health", "/api/system/status", "/api/pair", "/api/sdk/register"];
|
|
155
|
-
var SDK_PREFIX = "/api/sdk/";
|
|
156
|
-
function authMiddleware() {
|
|
157
|
-
return async (c, next) => {
|
|
158
|
-
const path = c.req.path;
|
|
159
|
-
if (PUBLIC_ROUTES.includes(path)) {
|
|
160
|
-
return next();
|
|
161
|
-
}
|
|
162
|
-
if (path.startsWith(SDK_PREFIX) && path !== "/api/sdk/register") {
|
|
163
|
-
return next();
|
|
164
|
-
}
|
|
165
|
-
const gatewayToken = getGatewayToken();
|
|
166
|
-
if (!gatewayToken) {
|
|
167
|
-
c.set("userId", "local");
|
|
168
|
-
c.set("permissions", ["*"]);
|
|
169
|
-
c.set("authMethod", "none");
|
|
170
|
-
return next();
|
|
171
|
-
}
|
|
172
|
-
const authHeader = c.req.header("Authorization");
|
|
173
|
-
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
174
|
-
return c.json({ error: "Missing or invalid authorization header" }, 401);
|
|
175
|
-
}
|
|
176
|
-
const token = authHeader.slice(7);
|
|
177
|
-
if (timingSafeEqual(token, gatewayToken)) {
|
|
178
|
-
c.set("userId", "gateway");
|
|
179
|
-
c.set("permissions", ["*"]);
|
|
180
|
-
c.set("authMethod", "gateway");
|
|
181
|
-
logAudit({
|
|
182
|
-
userId: "gateway",
|
|
183
|
-
action: "login",
|
|
184
|
-
resource: "session",
|
|
185
|
-
details: { method: "gateway_token", path }
|
|
186
|
-
}).catch(() => {
|
|
187
|
-
});
|
|
188
|
-
return next();
|
|
189
|
-
}
|
|
190
|
-
const sessionInfo = await validateSession(token);
|
|
191
|
-
if (sessionInfo) {
|
|
192
|
-
c.set("userId", sessionInfo.userId);
|
|
193
|
-
c.set("permissions", ["*"]);
|
|
194
|
-
c.set("authMethod", "session");
|
|
195
|
-
logAudit({
|
|
196
|
-
userId: sessionInfo.userId,
|
|
197
|
-
action: "login",
|
|
198
|
-
resource: "session",
|
|
199
|
-
details: { method: "session", path }
|
|
200
|
-
}).catch(() => {
|
|
201
|
-
});
|
|
202
|
-
return next();
|
|
203
|
-
}
|
|
204
|
-
const apiKeyResult = await validateApiKey(token);
|
|
205
|
-
if (apiKeyResult.valid && apiKeyResult.apiKey && apiKeyResult.userId) {
|
|
206
|
-
c.set("userId", apiKeyResult.userId);
|
|
207
|
-
c.set("permissions", apiKeyResult.apiKey.permissions);
|
|
208
|
-
c.set("authMethod", "api_key");
|
|
209
|
-
logAudit({
|
|
210
|
-
userId: apiKeyResult.userId,
|
|
211
|
-
action: "login",
|
|
212
|
-
resource: "api_key",
|
|
213
|
-
details: { method: "api_key", keyId: apiKeyResult.apiKey.id, path }
|
|
214
|
-
}).catch(() => {
|
|
215
|
-
});
|
|
216
|
-
return next();
|
|
217
|
-
}
|
|
218
|
-
return c.json({ error: "Invalid or expired credentials" }, 401);
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
function requirePermission(...requiredPermissions) {
|
|
222
|
-
return async (c, next) => {
|
|
223
|
-
const permissions = c.get("permissions");
|
|
224
|
-
if (!permissions) {
|
|
225
|
-
return c.json({ error: "Not authenticated" }, 401);
|
|
226
|
-
}
|
|
227
|
-
if (permissions.includes("*")) {
|
|
228
|
-
return next();
|
|
229
|
-
}
|
|
230
|
-
for (const required of requiredPermissions) {
|
|
231
|
-
if (!hasPermission(permissions, required)) {
|
|
232
|
-
return c.json({ error: "Insufficient permissions" }, 403);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return next();
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
function getAuthUserId(c) {
|
|
239
|
-
return c.get("userId");
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// src/inputs/api/routes/osint.ts
|
|
243
|
-
import { Hono } from "hono";
|
|
244
|
-
import { eq as eq3, sql, desc, ilike, and as and3 } from "drizzle-orm";
|
|
245
|
-
var _publicRecords = null;
|
|
246
|
-
function getPublicRecords() {
|
|
247
|
-
if (!_publicRecords) _publicRecords = createPublicRecords();
|
|
248
|
-
return _publicRecords;
|
|
249
|
-
}
|
|
250
|
-
var osint = new Hono();
|
|
251
|
-
osint.use("*", async (c, next) => {
|
|
252
|
-
if (!env.OSINT_ENABLED) {
|
|
253
|
-
return c.json({ error: "OSINT features are disabled" }, 403);
|
|
254
|
-
}
|
|
255
|
-
await next();
|
|
256
|
-
});
|
|
257
|
-
osint.get("/graph", async (c) => {
|
|
258
|
-
try {
|
|
259
|
-
const userId = c.req.query("userId") || "system";
|
|
260
|
-
const limit = Math.min(parseInt(c.req.query("limit") || "200", 10), 1e3);
|
|
261
|
-
const entities = await db.select({
|
|
262
|
-
id: graphEntities.id,
|
|
263
|
-
name: graphEntities.name,
|
|
264
|
-
type: graphEntities.type,
|
|
265
|
-
importance: graphEntities.importance,
|
|
266
|
-
description: graphEntities.description,
|
|
267
|
-
attributes: graphEntities.attributes,
|
|
268
|
-
aliases: graphEntities.aliases
|
|
269
|
-
}).from(graphEntities).orderBy(desc(graphEntities.importance)).limit(limit);
|
|
270
|
-
const entityIds = entities.map((e) => e.id);
|
|
271
|
-
if (entityIds.length === 0) {
|
|
272
|
-
return c.json({ nodes: [], edges: [] });
|
|
273
|
-
}
|
|
274
|
-
const relationships = await db.select({
|
|
275
|
-
id: graphRelationships.id,
|
|
276
|
-
source: graphRelationships.sourceEntityId,
|
|
277
|
-
target: graphRelationships.targetEntityId,
|
|
278
|
-
type: graphRelationships.type,
|
|
279
|
-
strength: graphRelationships.strength
|
|
280
|
-
}).from(graphRelationships).where(
|
|
281
|
-
and3(
|
|
282
|
-
sql`${graphRelationships.sourceEntityId} = ANY(${sql`ARRAY[${sql.join(entityIds.map((id) => sql`${id}`), sql`, `)}]::uuid[]`})`,
|
|
283
|
-
sql`${graphRelationships.targetEntityId} = ANY(${sql`ARRAY[${sql.join(entityIds.map((id) => sql`${id}`), sql`, `)}]::uuid[]`})`
|
|
284
|
-
)
|
|
285
|
-
);
|
|
286
|
-
return c.json({
|
|
287
|
-
nodes: entities,
|
|
288
|
-
edges: relationships,
|
|
289
|
-
stats: {
|
|
290
|
-
totalEntities: entities.length,
|
|
291
|
-
totalRelationships: relationships.length,
|
|
292
|
-
totalSources: new Set(
|
|
293
|
-
entities.flatMap((e) => {
|
|
294
|
-
const srcs = e.attributes?.sources;
|
|
295
|
-
return Array.isArray(srcs) ? srcs.map((s) => s.type || "unknown") : [];
|
|
296
|
-
})
|
|
297
|
-
).size
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
} catch (error) {
|
|
301
|
-
console.error("[OSINT API] /graph error:", error);
|
|
302
|
-
return c.json({ error: "Failed to fetch graph data" }, 500);
|
|
303
|
-
}
|
|
304
|
-
});
|
|
305
|
-
osint.get("/entity/:id", async (c) => {
|
|
306
|
-
try {
|
|
307
|
-
const id = c.req.param("id");
|
|
308
|
-
const results = await db.select().from(graphEntities).where(eq3(graphEntities.id, id)).limit(1);
|
|
309
|
-
if (results.length === 0) {
|
|
310
|
-
return c.json({ error: "Entity not found" }, 404);
|
|
311
|
-
}
|
|
312
|
-
const entity = results[0];
|
|
313
|
-
const outgoing = await db.select({
|
|
314
|
-
id: graphRelationships.id,
|
|
315
|
-
sourceEntityId: graphRelationships.sourceEntityId,
|
|
316
|
-
targetEntityId: graphRelationships.targetEntityId,
|
|
317
|
-
type: graphRelationships.type,
|
|
318
|
-
strength: graphRelationships.strength,
|
|
319
|
-
context: graphRelationships.context,
|
|
320
|
-
attributes: graphRelationships.attributes,
|
|
321
|
-
targetName: graphEntities.name
|
|
322
|
-
}).from(graphRelationships).innerJoin(graphEntities, eq3(graphRelationships.targetEntityId, graphEntities.id)).where(eq3(graphRelationships.sourceEntityId, id));
|
|
323
|
-
const incoming = await db.select({
|
|
324
|
-
id: graphRelationships.id,
|
|
325
|
-
sourceEntityId: graphRelationships.sourceEntityId,
|
|
326
|
-
targetEntityId: graphRelationships.targetEntityId,
|
|
327
|
-
type: graphRelationships.type,
|
|
328
|
-
strength: graphRelationships.strength,
|
|
329
|
-
context: graphRelationships.context,
|
|
330
|
-
attributes: graphRelationships.attributes,
|
|
331
|
-
sourceName: graphEntities.name
|
|
332
|
-
}).from(graphRelationships).innerJoin(graphEntities, eq3(graphRelationships.sourceEntityId, graphEntities.id)).where(eq3(graphRelationships.targetEntityId, id));
|
|
333
|
-
return c.json({
|
|
334
|
-
entity,
|
|
335
|
-
relationships: {
|
|
336
|
-
outgoing,
|
|
337
|
-
incoming
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
} catch (error) {
|
|
341
|
-
console.error("[OSINT API] /entity/:id error:", error);
|
|
342
|
-
return c.json({ error: "Failed to fetch entity" }, 500);
|
|
343
|
-
}
|
|
344
|
-
});
|
|
345
|
-
function normalizeFECName(raw) {
|
|
346
|
-
if (!raw.includes(",")) return toTitleCase(raw);
|
|
347
|
-
const [last, ...rest] = raw.split(",").map((s) => s.trim());
|
|
348
|
-
const first = rest.join(" ").trim();
|
|
349
|
-
if (!first) return toTitleCase(last);
|
|
350
|
-
return toTitleCase(`${first} ${last}`);
|
|
351
|
-
}
|
|
352
|
-
function toTitleCase(s) {
|
|
353
|
-
return s.toLowerCase().replace(/\b\w/g, (c) => c.toUpperCase());
|
|
354
|
-
}
|
|
355
|
-
async function searchExternalAPIs(query) {
|
|
356
|
-
const pr = getPublicRecords();
|
|
357
|
-
const newEntityIds = [];
|
|
358
|
-
const [fecCandidates, fecCommittees, ocCompanies] = await Promise.all([
|
|
359
|
-
pr.fec.searchCandidates(query).then((r) => r.slice(0, 10)).catch((err) => {
|
|
360
|
-
console.warn("[OSINT API] FEC candidates search failed:", err.message);
|
|
361
|
-
return [];
|
|
362
|
-
}),
|
|
363
|
-
pr.fec.searchCommittees(query).then((r) => r.slice(0, 10)).catch((err) => {
|
|
364
|
-
console.warn("[OSINT API] FEC committees search failed:", err.message);
|
|
365
|
-
return [];
|
|
366
|
-
}),
|
|
367
|
-
pr.opencorporates.searchCompanies(query, "us").then((r) => r.slice(0, 10)).catch((err) => {
|
|
368
|
-
console.warn("[OSINT API] OpenCorporates search failed:", err.message);
|
|
369
|
-
return [];
|
|
370
|
-
})
|
|
371
|
-
]);
|
|
372
|
-
const candidates = [];
|
|
373
|
-
for (const c of fecCandidates) {
|
|
374
|
-
candidates.push({
|
|
375
|
-
name: normalizeFECName(c.name),
|
|
376
|
-
type: "person",
|
|
377
|
-
source: "fec",
|
|
378
|
-
identifiers: { fecId: c.candidateId },
|
|
379
|
-
attributes: {
|
|
380
|
-
party: c.party,
|
|
381
|
-
office: c.office,
|
|
382
|
-
state: c.state,
|
|
383
|
-
district: c.district,
|
|
384
|
-
cycles: c.cycles
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
for (const c of fecCommittees) {
|
|
389
|
-
candidates.push({
|
|
390
|
-
name: toTitleCase(c.name),
|
|
391
|
-
type: "committee",
|
|
392
|
-
source: "fec",
|
|
393
|
-
identifiers: { fecId: c.committeeId },
|
|
394
|
-
attributes: {
|
|
395
|
-
designation: c.designation,
|
|
396
|
-
committeeType: c.type,
|
|
397
|
-
party: c.party,
|
|
398
|
-
state: c.state,
|
|
399
|
-
treasurerName: c.treasurerName
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
for (const c of ocCompanies) {
|
|
404
|
-
candidates.push({
|
|
405
|
-
name: c.name,
|
|
406
|
-
type: "organization",
|
|
407
|
-
source: "opencorporates",
|
|
408
|
-
attributes: {
|
|
409
|
-
companyNumber: c.companyNumber,
|
|
410
|
-
jurisdiction: c.jurisdictionCode,
|
|
411
|
-
status: c.status,
|
|
412
|
-
companyType: c.companyType,
|
|
413
|
-
incorporationDate: c.incorporationDate,
|
|
414
|
-
registeredAddress: c.registeredAddress,
|
|
415
|
-
openCorporatesUrl: c.openCorporatesUrl
|
|
416
|
-
}
|
|
417
|
-
});
|
|
418
|
-
}
|
|
419
|
-
for (const candidate of candidates) {
|
|
420
|
-
try {
|
|
421
|
-
const resolved = await resolveEntity(candidate);
|
|
422
|
-
newEntityIds.push(resolved.entityId);
|
|
423
|
-
} catch (err) {
|
|
424
|
-
console.warn(`[OSINT API] Entity resolution failed for "${candidate.name}":`, err.message);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
return [...new Set(newEntityIds)];
|
|
428
|
-
}
|
|
429
|
-
osint.get("/search", async (c) => {
|
|
430
|
-
try {
|
|
431
|
-
const q = c.req.query("q");
|
|
432
|
-
const type = c.req.query("type");
|
|
433
|
-
const limit = Math.min(parseInt(c.req.query("limit") || "25", 10), 100);
|
|
434
|
-
if (!q) {
|
|
435
|
-
return c.json({ error: "Query parameter 'q' is required" }, 400);
|
|
436
|
-
}
|
|
437
|
-
let query = db.select().from(graphEntities).where(
|
|
438
|
-
type ? and3(ilike(graphEntities.name, `%${q}%`), eq3(graphEntities.type, type)) : ilike(graphEntities.name, `%${q}%`)
|
|
439
|
-
).orderBy(desc(graphEntities.importance)).limit(limit);
|
|
440
|
-
let results = await query;
|
|
441
|
-
let externalSearched = false;
|
|
442
|
-
if (results.length < 3 && q.length >= 2) {
|
|
443
|
-
try {
|
|
444
|
-
console.log(`[OSINT API] Local results (${results.length}) < 3 for "${q}", querying external APIs...`);
|
|
445
|
-
const externalIds = await searchExternalAPIs(q);
|
|
446
|
-
externalSearched = true;
|
|
447
|
-
if (externalIds.length > 0) {
|
|
448
|
-
const nameCondition = type ? and3(ilike(graphEntities.name, `%${q}%`), eq3(graphEntities.type, type)) : ilike(graphEntities.name, `%${q}%`);
|
|
449
|
-
const idCondition = sql`${graphEntities.id} = ANY(${sql`ARRAY[${sql.join(externalIds.map((id) => sql`${id}`), sql`, `)}]::uuid[]`})`;
|
|
450
|
-
results = await db.select().from(graphEntities).where(sql`(${nameCondition}) OR (${idCondition})`).orderBy(desc(graphEntities.importance)).limit(limit);
|
|
451
|
-
}
|
|
452
|
-
} catch (extErr) {
|
|
453
|
-
console.warn("[OSINT API] External search failed (graceful):", extErr.message);
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
const entityIds = results.map((e) => e.id);
|
|
457
|
-
let edges = [];
|
|
458
|
-
if (entityIds.length > 1) {
|
|
459
|
-
edges = await db.select({
|
|
460
|
-
id: graphRelationships.id,
|
|
461
|
-
source: graphRelationships.sourceEntityId,
|
|
462
|
-
target: graphRelationships.targetEntityId,
|
|
463
|
-
type: graphRelationships.type,
|
|
464
|
-
strength: graphRelationships.strength
|
|
465
|
-
}).from(graphRelationships).where(
|
|
466
|
-
and3(
|
|
467
|
-
sql`${graphRelationships.sourceEntityId} = ANY(${sql`ARRAY[${sql.join(entityIds.map((id) => sql`${id}`), sql`, `)}]::uuid[]`})`,
|
|
468
|
-
sql`${graphRelationships.targetEntityId} = ANY(${sql`ARRAY[${sql.join(entityIds.map((id) => sql`${id}`), sql`, `)}]::uuid[]`})`
|
|
469
|
-
)
|
|
470
|
-
);
|
|
471
|
-
}
|
|
472
|
-
return c.json({ results, edges, total: results.length, externalSearched });
|
|
473
|
-
} catch (error) {
|
|
474
|
-
console.error("[OSINT API] /search error:", error);
|
|
475
|
-
return c.json({ error: "Search failed" }, 500);
|
|
476
|
-
}
|
|
477
|
-
});
|
|
478
|
-
osint.post("/enrich", async (c) => {
|
|
479
|
-
try {
|
|
480
|
-
const body = await c.req.json();
|
|
481
|
-
if (!body.entityId) {
|
|
482
|
-
return c.json({ error: "entityId is required" }, 400);
|
|
483
|
-
}
|
|
484
|
-
const entity = await db.select().from(graphEntities).where(eq3(graphEntities.id, body.entityId)).limit(1);
|
|
485
|
-
if (entity.length === 0) {
|
|
486
|
-
return c.json({ error: "Entity not found" }, 404);
|
|
487
|
-
}
|
|
488
|
-
const { enrichEntity } = await import("./enrichment-pipeline-MNHNW65K.js");
|
|
489
|
-
const result = await enrichEntity(body.entityId, {
|
|
490
|
-
sources: body.sources,
|
|
491
|
-
depth: body.depth ?? 1
|
|
492
|
-
});
|
|
493
|
-
return c.json({ success: true, result });
|
|
494
|
-
} catch (error) {
|
|
495
|
-
if (error?.code === "MODULE_NOT_FOUND" || error?.message?.includes("Cannot find module")) {
|
|
496
|
-
return c.json({ error: "Enrichment pipeline is not available" }, 501);
|
|
497
|
-
}
|
|
498
|
-
console.error("[OSINT API] /enrich error:", error);
|
|
499
|
-
return c.json({ error: "Enrichment failed" }, 500);
|
|
500
|
-
}
|
|
501
|
-
});
|
|
502
|
-
var FINANCIAL_REL_TYPES = ["donated_to", "funded", "awarded_contract", "grant_to", "paid"];
|
|
503
|
-
osint.get("/financial-flow", async (c) => {
|
|
504
|
-
try {
|
|
505
|
-
const entityId = c.req.query("entityId");
|
|
506
|
-
if (!entityId) {
|
|
507
|
-
return c.json({ error: "Query parameter 'entityId' is required" }, 400);
|
|
508
|
-
}
|
|
509
|
-
const rootEntity = await db.select({ id: graphEntities.id, name: graphEntities.name }).from(graphEntities).where(eq3(graphEntities.id, entityId)).limit(1);
|
|
510
|
-
if (rootEntity.length === 0) {
|
|
511
|
-
return c.json({ error: "Entity not found" }, 404);
|
|
512
|
-
}
|
|
513
|
-
const outgoing = await db.select({
|
|
514
|
-
id: graphRelationships.id,
|
|
515
|
-
sourceEntityId: graphRelationships.sourceEntityId,
|
|
516
|
-
targetEntityId: graphRelationships.targetEntityId,
|
|
517
|
-
type: graphRelationships.type,
|
|
518
|
-
strength: graphRelationships.strength,
|
|
519
|
-
attributes: graphRelationships.attributes
|
|
520
|
-
}).from(graphRelationships).where(
|
|
521
|
-
and3(
|
|
522
|
-
eq3(graphRelationships.sourceEntityId, entityId),
|
|
523
|
-
sql`${graphRelationships.type} = ANY(${sql`ARRAY[${sql.join(FINANCIAL_REL_TYPES.map((t) => sql`${t}`), sql`, `)}]::text[]`})`
|
|
524
|
-
)
|
|
525
|
-
);
|
|
526
|
-
const incoming = await db.select({
|
|
527
|
-
id: graphRelationships.id,
|
|
528
|
-
sourceEntityId: graphRelationships.sourceEntityId,
|
|
529
|
-
targetEntityId: graphRelationships.targetEntityId,
|
|
530
|
-
type: graphRelationships.type,
|
|
531
|
-
strength: graphRelationships.strength,
|
|
532
|
-
attributes: graphRelationships.attributes
|
|
533
|
-
}).from(graphRelationships).where(
|
|
534
|
-
and3(
|
|
535
|
-
eq3(graphRelationships.targetEntityId, entityId),
|
|
536
|
-
sql`${graphRelationships.type} = ANY(${sql`ARRAY[${sql.join(FINANCIAL_REL_TYPES.map((t) => sql`${t}`), sql`, `)}]::text[]`})`
|
|
537
|
-
)
|
|
538
|
-
);
|
|
539
|
-
const allRels = [...outgoing, ...incoming];
|
|
540
|
-
const relatedIds = /* @__PURE__ */ new Set();
|
|
541
|
-
relatedIds.add(entityId);
|
|
542
|
-
for (const rel of allRels) {
|
|
543
|
-
relatedIds.add(rel.sourceEntityId);
|
|
544
|
-
relatedIds.add(rel.targetEntityId);
|
|
545
|
-
}
|
|
546
|
-
const relatedEntities = await db.select({
|
|
547
|
-
id: graphEntities.id,
|
|
548
|
-
name: graphEntities.name,
|
|
549
|
-
type: graphEntities.type
|
|
550
|
-
}).from(graphEntities).where(sql`${graphEntities.id} = ANY(${sql`ARRAY[${sql.join([...relatedIds].map((id) => sql`${id}`), sql`, `)}]::uuid[]`})`);
|
|
551
|
-
const entityMap = new Map(relatedEntities.map((e) => [e.id, e]));
|
|
552
|
-
const nodeValues = /* @__PURE__ */ new Map();
|
|
553
|
-
for (const rel of allRels) {
|
|
554
|
-
const attrs = rel.attributes || {};
|
|
555
|
-
const amount = attrs.amount || rel.strength || 1;
|
|
556
|
-
nodeValues.set(rel.sourceEntityId, (nodeValues.get(rel.sourceEntityId) || 0) + amount);
|
|
557
|
-
nodeValues.set(rel.targetEntityId, (nodeValues.get(rel.targetEntityId) || 0) + amount);
|
|
558
|
-
}
|
|
559
|
-
const nodes = relatedEntities.map((e) => ({
|
|
560
|
-
id: e.id,
|
|
561
|
-
name: e.name,
|
|
562
|
-
type: e.type,
|
|
563
|
-
value: nodeValues.get(e.id) || 0
|
|
564
|
-
}));
|
|
565
|
-
const links = allRels.filter((rel) => entityMap.has(rel.sourceEntityId) && entityMap.has(rel.targetEntityId)).map((rel) => {
|
|
566
|
-
const attrs = rel.attributes || {};
|
|
567
|
-
return {
|
|
568
|
-
source: rel.sourceEntityId,
|
|
569
|
-
target: rel.targetEntityId,
|
|
570
|
-
value: attrs.amount || rel.strength || 1,
|
|
571
|
-
description: `${rel.type.replace(/_/g, " ")}${attrs.period ? ` (${attrs.period})` : ""}`
|
|
572
|
-
};
|
|
573
|
-
});
|
|
574
|
-
return c.json({ nodes, links });
|
|
575
|
-
} catch (error) {
|
|
576
|
-
console.error("[OSINT API] /financial-flow error:", error);
|
|
577
|
-
return c.json({ error: "Failed to fetch financial flow data" }, 500);
|
|
578
|
-
}
|
|
579
|
-
});
|
|
580
|
-
osint.get("/duplicates", async (c) => {
|
|
581
|
-
try {
|
|
582
|
-
const threshold = parseFloat(c.req.query("threshold") || "0.85");
|
|
583
|
-
const { findDuplicates } = await import("./entity-resolution-Y3IUWEAT.js");
|
|
584
|
-
const duplicates = await findDuplicates(threshold);
|
|
585
|
-
return c.json({ duplicates, total: duplicates.length });
|
|
586
|
-
} catch (error) {
|
|
587
|
-
console.error("[OSINT API] /duplicates error:", error);
|
|
588
|
-
return c.json({ error: "Failed to find duplicates" }, 500);
|
|
589
|
-
}
|
|
590
|
-
});
|
|
591
|
-
osint.get("/stats", async (c) => {
|
|
592
|
-
try {
|
|
593
|
-
const totalEntitiesResult = await db.select({ count: sql`count(*)::int` }).from(graphEntities);
|
|
594
|
-
const totalEntities = totalEntitiesResult[0]?.count ?? 0;
|
|
595
|
-
const totalRelsResult = await db.select({ count: sql`count(*)::int` }).from(graphRelationships);
|
|
596
|
-
const totalRelationships = totalRelsResult[0]?.count ?? 0;
|
|
597
|
-
const entitiesByType = await db.select({
|
|
598
|
-
type: graphEntities.type,
|
|
599
|
-
count: sql`count(*)::int`
|
|
600
|
-
}).from(graphEntities).groupBy(graphEntities.type).orderBy(desc(sql`count(*)`));
|
|
601
|
-
const topEntities = await db.select({
|
|
602
|
-
id: graphEntities.id,
|
|
603
|
-
name: graphEntities.name,
|
|
604
|
-
type: graphEntities.type,
|
|
605
|
-
mentionCount: graphEntities.mentionCount,
|
|
606
|
-
importance: graphEntities.importance
|
|
607
|
-
}).from(graphEntities).orderBy(desc(graphEntities.mentionCount)).limit(20);
|
|
608
|
-
return c.json({
|
|
609
|
-
totalEntities,
|
|
610
|
-
totalRelationships,
|
|
611
|
-
entitiesByType,
|
|
612
|
-
topEntities
|
|
613
|
-
});
|
|
614
|
-
} catch (error) {
|
|
615
|
-
console.error("[OSINT API] /stats error:", error);
|
|
616
|
-
return c.json({ error: "Failed to fetch statistics" }, 500);
|
|
617
|
-
}
|
|
618
|
-
});
|
|
619
|
-
|
|
620
|
-
// src/inputs/api/routes/email.ts
|
|
621
|
-
import { Hono as Hono2 } from "hono";
|
|
622
|
-
init_imap_client();
|
|
623
|
-
init_smtp_client();
|
|
624
|
-
var email = new Hono2();
|
|
625
|
-
function createImapClient(emailAddress) {
|
|
626
|
-
if (env.EMAIL_MASTER_USER && env.EMAIL_MASTER_PASSWORD) {
|
|
627
|
-
return new ImapClient({
|
|
628
|
-
host: env.EMAIL_LOCAL_IMAP_HOST || "127.0.0.1",
|
|
629
|
-
port: env.EMAIL_LOCAL_IMAP_PORT || 993,
|
|
630
|
-
secure: true,
|
|
631
|
-
user: `${emailAddress}*${env.EMAIL_MASTER_USER}`,
|
|
632
|
-
password: env.EMAIL_MASTER_PASSWORD,
|
|
633
|
-
tls: { rejectUnauthorized: false }
|
|
634
|
-
});
|
|
635
|
-
} else if (env.EMAIL_USER && env.EMAIL_PASSWORD) {
|
|
636
|
-
return new ImapClient({
|
|
637
|
-
host: env.EMAIL_IMAP_HOST || "imap.gmail.com",
|
|
638
|
-
port: env.EMAIL_IMAP_PORT || 993,
|
|
639
|
-
secure: env.EMAIL_IMAP_SECURE !== false,
|
|
640
|
-
user: env.EMAIL_USER,
|
|
641
|
-
password: env.EMAIL_PASSWORD
|
|
642
|
-
});
|
|
643
|
-
}
|
|
644
|
-
throw new Error("Email not configured");
|
|
645
|
-
}
|
|
646
|
-
function createSmtpClient(fromAddress) {
|
|
647
|
-
if (env.EMAIL_MASTER_USER) {
|
|
648
|
-
return new SmtpClient(
|
|
649
|
-
{
|
|
650
|
-
host: env.EMAIL_LOCAL_SMTP_HOST || "127.0.0.1",
|
|
651
|
-
port: env.EMAIL_LOCAL_SMTP_PORT || 25,
|
|
652
|
-
secure: false,
|
|
653
|
-
auth: { user: "", pass: "" },
|
|
654
|
-
tls: { rejectUnauthorized: false }
|
|
655
|
-
},
|
|
656
|
-
fromAddress
|
|
657
|
-
);
|
|
658
|
-
} else if (env.EMAIL_USER && env.EMAIL_PASSWORD) {
|
|
659
|
-
return new SmtpClient(
|
|
660
|
-
{
|
|
661
|
-
host: env.EMAIL_SMTP_HOST || "smtp.gmail.com",
|
|
662
|
-
port: env.EMAIL_SMTP_PORT || 587,
|
|
663
|
-
secure: env.EMAIL_SMTP_SECURE === true,
|
|
664
|
-
auth: { user: env.EMAIL_USER, pass: env.EMAIL_PASSWORD }
|
|
665
|
-
},
|
|
666
|
-
fromAddress
|
|
667
|
-
);
|
|
668
|
-
}
|
|
669
|
-
throw new Error("Email not configured");
|
|
670
|
-
}
|
|
671
|
-
function serializeEmail(email2, includeBody) {
|
|
672
|
-
const serialized = {
|
|
673
|
-
id: email2.id,
|
|
674
|
-
uid: email2.uid,
|
|
675
|
-
messageId: email2.messageId,
|
|
676
|
-
subject: email2.subject,
|
|
677
|
-
from: email2.from,
|
|
678
|
-
to: email2.to,
|
|
679
|
-
cc: email2.cc,
|
|
680
|
-
bcc: email2.bcc,
|
|
681
|
-
date: email2.date.toISOString(),
|
|
682
|
-
text: includeBody ? email2.text : email2.snippet,
|
|
683
|
-
html: includeBody ? email2.html : "",
|
|
684
|
-
snippet: email2.snippet,
|
|
685
|
-
attachments: email2.attachments.map((a) => ({
|
|
686
|
-
filename: a.filename,
|
|
687
|
-
contentType: a.contentType,
|
|
688
|
-
size: a.size,
|
|
689
|
-
contentId: a.contentId,
|
|
690
|
-
hasContent: !!a.content
|
|
691
|
-
})),
|
|
692
|
-
flags: email2.flags,
|
|
693
|
-
labels: email2.labels,
|
|
694
|
-
threadId: email2.threadId,
|
|
695
|
-
inReplyTo: email2.inReplyTo,
|
|
696
|
-
references: email2.references,
|
|
697
|
-
headers: Object.fromEntries(email2.headers)
|
|
698
|
-
};
|
|
699
|
-
return serialized;
|
|
700
|
-
}
|
|
701
|
-
email.use("*", async (c, next) => {
|
|
702
|
-
if (!env.EMAIL_MASTER_USER && !env.EMAIL_USER) {
|
|
703
|
-
return c.json(
|
|
704
|
-
{ error: "Email not configured. Set EMAIL_MASTER_USER or EMAIL_USER in .env" },
|
|
705
|
-
503
|
|
706
|
-
);
|
|
707
|
-
}
|
|
708
|
-
await next();
|
|
709
|
-
});
|
|
710
|
-
email.get("/folders", async (c) => {
|
|
711
|
-
const emailAddress = c.req.query("email_address");
|
|
712
|
-
if (!emailAddress) {
|
|
713
|
-
return c.json({ error: "Query parameter 'email_address' is required" }, 400);
|
|
714
|
-
}
|
|
715
|
-
let imap = null;
|
|
716
|
-
try {
|
|
717
|
-
imap = createImapClient(emailAddress);
|
|
718
|
-
await imap.connect();
|
|
719
|
-
const folders = await imap.listFolders();
|
|
720
|
-
return c.json(folders);
|
|
721
|
-
} catch (error) {
|
|
722
|
-
console.error("[Email API] /folders error:", error);
|
|
723
|
-
return c.json(
|
|
724
|
-
{ error: error instanceof Error ? error.message : "Failed to list folders" },
|
|
725
|
-
500
|
|
726
|
-
);
|
|
727
|
-
} finally {
|
|
728
|
-
if (imap) {
|
|
729
|
-
await imap.disconnect().catch(() => {
|
|
730
|
-
});
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
});
|
|
734
|
-
email.get("/inbox", async (c) => {
|
|
735
|
-
const emailAddress = c.req.query("email_address");
|
|
736
|
-
if (!emailAddress) {
|
|
737
|
-
return c.json({ error: "Query parameter 'email_address' is required" }, 400);
|
|
738
|
-
}
|
|
739
|
-
const folder = c.req.query("folder") || "INBOX";
|
|
740
|
-
const limit = c.req.query("limit") || "20";
|
|
741
|
-
const offset = c.req.query("offset") || "0";
|
|
742
|
-
const unreadOnly = c.req.query("unread_only") === "true";
|
|
743
|
-
let imap = null;
|
|
744
|
-
try {
|
|
745
|
-
imap = createImapClient(emailAddress);
|
|
746
|
-
await imap.connect();
|
|
747
|
-
let emails;
|
|
748
|
-
if (unreadOnly) {
|
|
749
|
-
emails = await imap.searchEmails({
|
|
750
|
-
folder,
|
|
751
|
-
seen: false,
|
|
752
|
-
limit: parseInt(limit)
|
|
753
|
-
});
|
|
754
|
-
} else {
|
|
755
|
-
emails = await imap.fetchEmails(folder, {
|
|
756
|
-
limit: parseInt(limit),
|
|
757
|
-
offset: parseInt(offset)
|
|
758
|
-
});
|
|
759
|
-
}
|
|
760
|
-
return c.json({
|
|
761
|
-
emails: emails.map((e) => serializeEmail(e, false)),
|
|
762
|
-
folder
|
|
763
|
-
});
|
|
764
|
-
} catch (error) {
|
|
765
|
-
console.error("[Email API] /inbox error:", error);
|
|
766
|
-
return c.json(
|
|
767
|
-
{ error: error instanceof Error ? error.message : "Failed to fetch emails" },
|
|
768
|
-
500
|
|
769
|
-
);
|
|
770
|
-
} finally {
|
|
771
|
-
if (imap) {
|
|
772
|
-
await imap.disconnect().catch(() => {
|
|
773
|
-
});
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
});
|
|
777
|
-
email.get("/message/:uid", async (c) => {
|
|
778
|
-
const emailAddress = c.req.query("email_address");
|
|
779
|
-
if (!emailAddress) {
|
|
780
|
-
return c.json({ error: "Query parameter 'email_address' is required" }, 400);
|
|
781
|
-
}
|
|
782
|
-
const uid = parseInt(c.req.param("uid"));
|
|
783
|
-
const folder = c.req.query("folder") || "INBOX";
|
|
784
|
-
let imap = null;
|
|
785
|
-
try {
|
|
786
|
-
imap = createImapClient(emailAddress);
|
|
787
|
-
await imap.connect();
|
|
788
|
-
const emailMsg = await imap.fetchEmail(uid, folder);
|
|
789
|
-
if (!emailMsg) {
|
|
790
|
-
return c.json({ error: "Email not found" }, 404);
|
|
791
|
-
}
|
|
792
|
-
await imap.markAsRead(uid, folder);
|
|
793
|
-
return c.json(serializeEmail(emailMsg, true));
|
|
794
|
-
} catch (error) {
|
|
795
|
-
console.error("[Email API] /message/:uid error:", error);
|
|
796
|
-
return c.json(
|
|
797
|
-
{ error: error instanceof Error ? error.message : "Failed to fetch email" },
|
|
798
|
-
500
|
|
799
|
-
);
|
|
800
|
-
} finally {
|
|
801
|
-
if (imap) {
|
|
802
|
-
await imap.disconnect().catch(() => {
|
|
803
|
-
});
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
});
|
|
807
|
-
email.get("/attachment/:uid/:index", async (c) => {
|
|
808
|
-
const emailAddress = c.req.query("email_address");
|
|
809
|
-
if (!emailAddress) {
|
|
810
|
-
return c.json({ error: "Query parameter 'email_address' is required" }, 400);
|
|
811
|
-
}
|
|
812
|
-
const uid = parseInt(c.req.param("uid"));
|
|
813
|
-
const index = parseInt(c.req.param("index"));
|
|
814
|
-
const folder = c.req.query("folder") || "INBOX";
|
|
815
|
-
let imap = null;
|
|
816
|
-
try {
|
|
817
|
-
imap = createImapClient(emailAddress);
|
|
818
|
-
await imap.connect();
|
|
819
|
-
const emailMsg = await imap.fetchEmail(uid, folder);
|
|
820
|
-
if (!emailMsg) {
|
|
821
|
-
return c.json({ error: "Email not found" }, 404);
|
|
822
|
-
}
|
|
823
|
-
const attachment = emailMsg.attachments[index];
|
|
824
|
-
if (!attachment) {
|
|
825
|
-
return c.json({ error: "Attachment not found" }, 404);
|
|
826
|
-
}
|
|
827
|
-
if (!attachment.content) {
|
|
828
|
-
return c.json({ error: "Attachment content not available" }, 404);
|
|
829
|
-
}
|
|
830
|
-
return new Response(attachment.content, {
|
|
831
|
-
headers: {
|
|
832
|
-
"Content-Type": attachment.contentType || "application/octet-stream",
|
|
833
|
-
"Content-Disposition": `attachment; filename="${attachment.filename}"`,
|
|
834
|
-
"Content-Length": String(attachment.size || attachment.content.length)
|
|
835
|
-
}
|
|
836
|
-
});
|
|
837
|
-
} catch (error) {
|
|
838
|
-
console.error("[Email API] /attachment/:uid/:index error:", error);
|
|
839
|
-
return c.json(
|
|
840
|
-
{ error: error instanceof Error ? error.message : "Failed to fetch attachment" },
|
|
841
|
-
500
|
|
842
|
-
);
|
|
843
|
-
} finally {
|
|
844
|
-
if (imap) {
|
|
845
|
-
await imap.disconnect().catch(() => {
|
|
846
|
-
});
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
});
|
|
850
|
-
email.post("/send", async (c) => {
|
|
851
|
-
try {
|
|
852
|
-
const body = await c.req.json();
|
|
853
|
-
if (!body.from || !body.to || !body.subject) {
|
|
854
|
-
return c.json({ error: "Fields 'from', 'to', and 'subject' are required" }, 400);
|
|
855
|
-
}
|
|
856
|
-
const smtp = createSmtpClient(body.from);
|
|
857
|
-
const convertedAttachments = body.attachments?.map((a) => ({
|
|
858
|
-
filename: a.filename,
|
|
859
|
-
contentType: a.contentType,
|
|
860
|
-
size: Buffer.from(a.content, "base64").length,
|
|
861
|
-
content: Buffer.from(a.content, "base64")
|
|
862
|
-
}));
|
|
863
|
-
const result = await smtp.send({
|
|
864
|
-
to: body.to,
|
|
865
|
-
cc: body.cc,
|
|
866
|
-
bcc: body.bcc,
|
|
867
|
-
subject: body.subject,
|
|
868
|
-
text: body.text,
|
|
869
|
-
html: body.html,
|
|
870
|
-
attachments: convertedAttachments
|
|
871
|
-
});
|
|
872
|
-
return c.json(result);
|
|
873
|
-
} catch (error) {
|
|
874
|
-
console.error("[Email API] /send error:", error);
|
|
875
|
-
return c.json(
|
|
876
|
-
{ error: error instanceof Error ? error.message : "Failed to send email" },
|
|
877
|
-
500
|
|
878
|
-
);
|
|
879
|
-
}
|
|
880
|
-
});
|
|
881
|
-
email.post("/reply", async (c) => {
|
|
882
|
-
const body = await c.req.json();
|
|
883
|
-
if (!body.email_address || !body.email_uid || !body.body) {
|
|
884
|
-
return c.json(
|
|
885
|
-
{ error: "Fields 'email_address', 'email_uid', and 'body' are required" },
|
|
886
|
-
400
|
|
887
|
-
);
|
|
888
|
-
}
|
|
889
|
-
const folder = body.folder || "INBOX";
|
|
890
|
-
let imap = null;
|
|
891
|
-
try {
|
|
892
|
-
imap = createImapClient(body.email_address);
|
|
893
|
-
await imap.connect();
|
|
894
|
-
const originalEmail = await imap.fetchEmail(body.email_uid, folder);
|
|
895
|
-
if (!originalEmail) {
|
|
896
|
-
return c.json({ error: "Original email not found" }, 404);
|
|
897
|
-
}
|
|
898
|
-
const smtp = createSmtpClient(body.email_address);
|
|
899
|
-
const convertedAttachments = body.attachments?.map((a) => ({
|
|
900
|
-
filename: a.filename,
|
|
901
|
-
contentType: a.contentType,
|
|
902
|
-
size: Buffer.from(a.content, "base64").length,
|
|
903
|
-
content: Buffer.from(a.content, "base64")
|
|
904
|
-
}));
|
|
905
|
-
let result;
|
|
906
|
-
if (body.reply_all) {
|
|
907
|
-
result = await smtp.replyAll(
|
|
908
|
-
originalEmail,
|
|
909
|
-
{ text: body.body, html: body.html, attachments: convertedAttachments },
|
|
910
|
-
body.email_address
|
|
911
|
-
);
|
|
912
|
-
} else {
|
|
913
|
-
result = await smtp.reply(originalEmail, {
|
|
914
|
-
text: body.body,
|
|
915
|
-
html: body.html,
|
|
916
|
-
attachments: convertedAttachments
|
|
917
|
-
});
|
|
918
|
-
}
|
|
919
|
-
return c.json(result);
|
|
920
|
-
} catch (error) {
|
|
921
|
-
console.error("[Email API] /reply error:", error);
|
|
922
|
-
return c.json(
|
|
923
|
-
{ error: error instanceof Error ? error.message : "Failed to send reply" },
|
|
924
|
-
500
|
|
925
|
-
);
|
|
926
|
-
} finally {
|
|
927
|
-
if (imap) {
|
|
928
|
-
await imap.disconnect().catch(() => {
|
|
929
|
-
});
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
});
|
|
933
|
-
email.post("/search", async (c) => {
|
|
934
|
-
const body = await c.req.json();
|
|
935
|
-
if (!body.email_address) {
|
|
936
|
-
return c.json({ error: "Field 'email_address' is required" }, 400);
|
|
937
|
-
}
|
|
938
|
-
let imap = null;
|
|
939
|
-
try {
|
|
940
|
-
imap = createImapClient(body.email_address);
|
|
941
|
-
await imap.connect();
|
|
942
|
-
const searchOptions = {
|
|
943
|
-
folder: body.folder || "INBOX",
|
|
944
|
-
from: body.from,
|
|
945
|
-
to: body.to,
|
|
946
|
-
subject: body.subject,
|
|
947
|
-
body: body.body,
|
|
948
|
-
since: body.since ? new Date(body.since) : void 0,
|
|
949
|
-
before: body.before ? new Date(body.before) : void 0,
|
|
950
|
-
seen: body.unread_only ? false : void 0,
|
|
951
|
-
limit: body.limit
|
|
952
|
-
};
|
|
953
|
-
const emails = await imap.searchEmails(searchOptions);
|
|
954
|
-
return c.json({
|
|
955
|
-
emails: emails.map((e) => serializeEmail(e, false))
|
|
956
|
-
});
|
|
957
|
-
} catch (error) {
|
|
958
|
-
console.error("[Email API] /search error:", error);
|
|
959
|
-
return c.json(
|
|
960
|
-
{ error: error instanceof Error ? error.message : "Search failed" },
|
|
961
|
-
500
|
|
962
|
-
);
|
|
963
|
-
} finally {
|
|
964
|
-
if (imap) {
|
|
965
|
-
await imap.disconnect().catch(() => {
|
|
966
|
-
});
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
});
|
|
970
|
-
email.post("/flag", async (c) => {
|
|
971
|
-
const body = await c.req.json();
|
|
972
|
-
if (!body.email_address || !body.uid || !body.action) {
|
|
973
|
-
return c.json(
|
|
974
|
-
{ error: "Fields 'email_address', 'uid', and 'action' are required" },
|
|
975
|
-
400
|
|
976
|
-
);
|
|
977
|
-
}
|
|
978
|
-
const folder = body.folder || "INBOX";
|
|
979
|
-
let imap = null;
|
|
980
|
-
try {
|
|
981
|
-
imap = createImapClient(body.email_address);
|
|
982
|
-
await imap.connect();
|
|
983
|
-
switch (body.action) {
|
|
984
|
-
case "read":
|
|
985
|
-
await imap.markAsRead(body.uid, folder);
|
|
986
|
-
break;
|
|
987
|
-
case "unread":
|
|
988
|
-
await imap.markAsUnread(body.uid, folder);
|
|
989
|
-
break;
|
|
990
|
-
case "flag":
|
|
991
|
-
await imap.flagEmail(body.uid, folder);
|
|
992
|
-
break;
|
|
993
|
-
case "unflag":
|
|
994
|
-
await imap.unflagEmail(body.uid, folder);
|
|
995
|
-
break;
|
|
996
|
-
case "delete":
|
|
997
|
-
await imap.deleteEmail(body.uid, folder);
|
|
998
|
-
break;
|
|
999
|
-
default:
|
|
1000
|
-
return c.json({ error: `Unknown action: ${body.action}` }, 400);
|
|
1001
|
-
}
|
|
1002
|
-
return c.json({ success: true });
|
|
1003
|
-
} catch (error) {
|
|
1004
|
-
console.error("[Email API] /flag error:", error);
|
|
1005
|
-
return c.json(
|
|
1006
|
-
{ error: error instanceof Error ? error.message : "Failed to perform action" },
|
|
1007
|
-
500
|
|
1008
|
-
);
|
|
1009
|
-
} finally {
|
|
1010
|
-
if (imap) {
|
|
1011
|
-
await imap.disconnect().catch(() => {
|
|
1012
|
-
});
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
});
|
|
1016
|
-
|
|
1017
|
-
// src/inputs/api/routes/sdk.ts
|
|
1018
|
-
import { Hono as Hono3 } from "hono";
|
|
1019
|
-
var registeredApps = /* @__PURE__ */ new Map();
|
|
1020
|
-
function generateApiKey() {
|
|
1021
|
-
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
1022
|
-
const segments = [8, 4, 4, 4, 12];
|
|
1023
|
-
return "osk_" + segments.map((len) => Array.from({ length: len }, () => chars[Math.floor(Math.random() * chars.length)]).join("")).join("-");
|
|
1024
|
-
}
|
|
1025
|
-
async function sdkAuth(c, next) {
|
|
1026
|
-
const authHeader = c.req.header("Authorization");
|
|
1027
|
-
if (!authHeader?.startsWith("Bearer osk_")) {
|
|
1028
|
-
return c.json({ error: "Invalid or missing API key. Register at POST /api/sdk/register" }, 401);
|
|
1029
|
-
}
|
|
1030
|
-
const apiKey = authHeader.slice(7);
|
|
1031
|
-
const app2 = Array.from(registeredApps.values()).find((a) => a.apiKey === apiKey);
|
|
1032
|
-
if (!app2) {
|
|
1033
|
-
return c.json({ error: "Unknown API key. Register at POST /api/sdk/register" }, 401);
|
|
1034
|
-
}
|
|
1035
|
-
app2.lastSeen = /* @__PURE__ */ new Date();
|
|
1036
|
-
c.set("sdkApp", app2);
|
|
1037
|
-
await next();
|
|
1038
|
-
}
|
|
1039
|
-
var sdkRoutes = new Hono3();
|
|
1040
|
-
sdkRoutes.post("/register", async (c) => {
|
|
1041
|
-
try {
|
|
1042
|
-
const body = await c.req.json();
|
|
1043
|
-
if (!body.name || !body.type) {
|
|
1044
|
-
return c.json({ error: "name and type are required" }, 400);
|
|
1045
|
-
}
|
|
1046
|
-
const existing = Array.from(registeredApps.values()).find(
|
|
1047
|
-
(a) => a.name === body.name && a.type === body.type
|
|
1048
|
-
);
|
|
1049
|
-
if (existing) {
|
|
1050
|
-
return c.json({
|
|
1051
|
-
id: existing.id,
|
|
1052
|
-
apiKey: existing.apiKey,
|
|
1053
|
-
message: "App already registered"
|
|
1054
|
-
});
|
|
1055
|
-
}
|
|
1056
|
-
const id = crypto.randomUUID();
|
|
1057
|
-
const apiKey = generateApiKey();
|
|
1058
|
-
const app2 = {
|
|
1059
|
-
id,
|
|
1060
|
-
name: body.name,
|
|
1061
|
-
type: body.type,
|
|
1062
|
-
apiKey,
|
|
1063
|
-
callbackUrl: body.callbackUrl,
|
|
1064
|
-
registeredAt: /* @__PURE__ */ new Date(),
|
|
1065
|
-
lastSeen: /* @__PURE__ */ new Date()
|
|
1066
|
-
};
|
|
1067
|
-
registeredApps.set(id, app2);
|
|
1068
|
-
return c.json({
|
|
1069
|
-
id,
|
|
1070
|
-
apiKey,
|
|
1071
|
-
message: "App registered successfully. Use this API key in Authorization: Bearer header.",
|
|
1072
|
-
endpoints: {
|
|
1073
|
-
chat: "POST /api/sdk/chat",
|
|
1074
|
-
notify: "POST /api/sdk/notify",
|
|
1075
|
-
memory_store: "POST /api/sdk/memory",
|
|
1076
|
-
memory_search: "POST /api/sdk/memory/search",
|
|
1077
|
-
tools_list: "GET /api/sdk/tools",
|
|
1078
|
-
tools_execute: "POST /api/sdk/tools/execute",
|
|
1079
|
-
agent_spawn: "POST /api/sdk/agent/spawn",
|
|
1080
|
-
status: "GET /api/sdk/status"
|
|
1081
|
-
}
|
|
1082
|
-
});
|
|
1083
|
-
} catch (error) {
|
|
1084
|
-
return c.json({ error: "Registration failed" }, 500);
|
|
1085
|
-
}
|
|
1086
|
-
});
|
|
1087
|
-
sdkRoutes.use("/*", sdkAuth);
|
|
1088
|
-
sdkRoutes.post("/chat", async (c) => {
|
|
1089
|
-
try {
|
|
1090
|
-
const app2 = c.get("sdkApp");
|
|
1091
|
-
const body = await c.req.json();
|
|
1092
|
-
if (!body.message) {
|
|
1093
|
-
return c.json({ error: "message is required" }, 400);
|
|
1094
|
-
}
|
|
1095
|
-
const messages2 = [];
|
|
1096
|
-
if (body.context) {
|
|
1097
|
-
messages2.push({
|
|
1098
|
-
role: "user",
|
|
1099
|
-
content: `[Context from ${app2.name} (${app2.type})]: ${body.context}`
|
|
1100
|
-
});
|
|
1101
|
-
messages2.push({
|
|
1102
|
-
role: "assistant",
|
|
1103
|
-
content: "Understood, I have the context. How can I help?"
|
|
1104
|
-
});
|
|
1105
|
-
}
|
|
1106
|
-
messages2.push({ role: "user", content: body.message });
|
|
1107
|
-
const toolsUsed = [];
|
|
1108
|
-
const response = body.useTools !== false ? await chatWithTools(messages2, `sdk:${app2.id}`, (tool) => toolsUsed.push(tool), { appType: app2.type }) : await (await import("./brain-7XLLM3KC.js")).chat(messages2, body.systemPrompt);
|
|
1109
|
-
await storeMemory({
|
|
1110
|
-
content: `[${app2.name}] User asked: ${body.message.slice(0, 200)}`,
|
|
1111
|
-
type: "episodic",
|
|
1112
|
-
importance: 5,
|
|
1113
|
-
userId: `sdk:${app2.id}`,
|
|
1114
|
-
source: `sdk:${app2.name}`,
|
|
1115
|
-
provenance: `sdk:${app2.type}`
|
|
1116
|
-
}).catch(() => {
|
|
1117
|
-
});
|
|
1118
|
-
return c.json({
|
|
1119
|
-
content: response.content,
|
|
1120
|
-
toolsUsed,
|
|
1121
|
-
usage: {
|
|
1122
|
-
inputTokens: response.inputTokens,
|
|
1123
|
-
outputTokens: response.outputTokens
|
|
1124
|
-
},
|
|
1125
|
-
app: app2.name
|
|
1126
|
-
});
|
|
1127
|
-
} catch (error) {
|
|
1128
|
-
console.error("SDK chat error:", error);
|
|
1129
|
-
return c.json({ error: "Chat failed" }, 500);
|
|
1130
|
-
}
|
|
1131
|
-
});
|
|
1132
|
-
sdkRoutes.post("/notify", async (c) => {
|
|
1133
|
-
try {
|
|
1134
|
-
const app2 = c.get("sdkApp");
|
|
1135
|
-
const body = await c.req.json();
|
|
1136
|
-
if (!body.channel || !body.message) {
|
|
1137
|
-
return c.json({ error: "channel and message are required" }, 400);
|
|
1138
|
-
}
|
|
1139
|
-
const sent = [];
|
|
1140
|
-
const prefix = `[${app2.name}] `;
|
|
1141
|
-
const fullMessage = prefix + body.message;
|
|
1142
|
-
const channels = body.channel === "all" ? ["telegram", "discord", "slack"] : [body.channel];
|
|
1143
|
-
for (const ch of channels) {
|
|
1144
|
-
try {
|
|
1145
|
-
switch (ch) {
|
|
1146
|
-
case "telegram": {
|
|
1147
|
-
const { sendTelegramMessage } = await import("../../telegram");
|
|
1148
|
-
await sendTelegramMessage(fullMessage);
|
|
1149
|
-
sent.push("telegram");
|
|
1150
|
-
break;
|
|
1151
|
-
}
|
|
1152
|
-
case "discord": {
|
|
1153
|
-
const { sendDiscordMessage } = await import("./discord-B3HUPGQ6.js");
|
|
1154
|
-
await sendDiscordMessage(fullMessage);
|
|
1155
|
-
sent.push("discord");
|
|
1156
|
-
break;
|
|
1157
|
-
}
|
|
1158
|
-
case "slack": {
|
|
1159
|
-
const { sendSlackMessage } = await import("./slack-IZQWIKOH.js");
|
|
1160
|
-
await sendSlackMessage(fullMessage);
|
|
1161
|
-
sent.push("slack");
|
|
1162
|
-
break;
|
|
1163
|
-
}
|
|
1164
|
-
case "email": {
|
|
1165
|
-
const { sendEmail } = await import("./email-K7LO2IPB.js");
|
|
1166
|
-
await sendEmail({
|
|
1167
|
-
to: body.recipient || "",
|
|
1168
|
-
subject: `${app2.name} Notification`,
|
|
1169
|
-
text: body.message
|
|
1170
|
-
});
|
|
1171
|
-
sent.push("email");
|
|
1172
|
-
break;
|
|
1173
|
-
}
|
|
1174
|
-
}
|
|
1175
|
-
} catch (err) {
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
return c.json({ sent, message: `Notification sent via: ${sent.join(", ") || "none (no channels configured)"}` });
|
|
1179
|
-
} catch (error) {
|
|
1180
|
-
return c.json({ error: "Notification failed" }, 500);
|
|
1181
|
-
}
|
|
1182
|
-
});
|
|
1183
|
-
sdkRoutes.post("/memory", async (c) => {
|
|
1184
|
-
try {
|
|
1185
|
-
const app2 = c.get("sdkApp");
|
|
1186
|
-
const body = await c.req.json();
|
|
1187
|
-
if (!body.content) {
|
|
1188
|
-
return c.json({ error: "content is required" }, 400);
|
|
1189
|
-
}
|
|
1190
|
-
const memory = await storeMemory({
|
|
1191
|
-
content: body.content,
|
|
1192
|
-
type: body.type || "semantic",
|
|
1193
|
-
importance: body.importance || 5,
|
|
1194
|
-
userId: `sdk:${app2.id}`,
|
|
1195
|
-
source: `sdk:${app2.name}`,
|
|
1196
|
-
provenance: `sdk:${app2.type}`
|
|
1197
|
-
});
|
|
1198
|
-
return c.json(memory);
|
|
1199
|
-
} catch (error) {
|
|
1200
|
-
return c.json({ error: "Memory store failed" }, 500);
|
|
1201
|
-
}
|
|
1202
|
-
});
|
|
1203
|
-
sdkRoutes.post("/memory/search", async (c) => {
|
|
1204
|
-
try {
|
|
1205
|
-
const app2 = c.get("sdkApp");
|
|
1206
|
-
const body = await c.req.json();
|
|
1207
|
-
if (!body.query) {
|
|
1208
|
-
return c.json({ error: "query is required" }, 400);
|
|
1209
|
-
}
|
|
1210
|
-
const userId = body.crossApp ? void 0 : `sdk:${app2.id}`;
|
|
1211
|
-
const results = await searchMemories(body.query, userId, body.limit || 5);
|
|
1212
|
-
return c.json(results);
|
|
1213
|
-
} catch (error) {
|
|
1214
|
-
return c.json({ error: "Memory search failed" }, 500);
|
|
1215
|
-
}
|
|
1216
|
-
});
|
|
1217
|
-
sdkRoutes.get("/tools", (c) => {
|
|
1218
|
-
const app2 = c.get("sdkApp");
|
|
1219
|
-
const ordered = prioritizeTools(TOOLS, app2.type);
|
|
1220
|
-
const profile = getAppProfile(app2.type);
|
|
1221
|
-
const prioritySet = new Set(profile.priorityTools);
|
|
1222
|
-
const toolList = ordered.map((t) => ({
|
|
1223
|
-
name: t.name,
|
|
1224
|
-
description: t.description,
|
|
1225
|
-
priority: prioritySet.has(t.name)
|
|
1226
|
-
}));
|
|
1227
|
-
return c.json({ tools: toolList, count: toolList.length, appType: app2.type });
|
|
1228
|
-
});
|
|
1229
|
-
sdkRoutes.post("/tools/execute", async (c) => {
|
|
1230
|
-
try {
|
|
1231
|
-
const body = await c.req.json();
|
|
1232
|
-
if (!body.tool || !body.input) {
|
|
1233
|
-
return c.json({ error: "tool and input are required" }, 400);
|
|
1234
|
-
}
|
|
1235
|
-
const result = await executeTool(body.tool, body.input);
|
|
1236
|
-
return c.json({ tool: body.tool, result });
|
|
1237
|
-
} catch (error) {
|
|
1238
|
-
return c.json({ error: "Tool execution failed" }, 500);
|
|
1239
|
-
}
|
|
1240
|
-
});
|
|
1241
|
-
sdkRoutes.post("/agent/spawn", async (c) => {
|
|
1242
|
-
try {
|
|
1243
|
-
const app2 = c.get("sdkApp");
|
|
1244
|
-
const body = await c.req.json();
|
|
1245
|
-
if (!body.type || !body.task) {
|
|
1246
|
-
return c.json({ error: "type and task are required" }, 400);
|
|
1247
|
-
}
|
|
1248
|
-
const agentPrompt = `As a ${body.type} agent for ${app2.name}, complete this task: ${body.task}${body.context ? `
|
|
1249
|
-
|
|
1250
|
-
Context: ${body.context}` : ""}`;
|
|
1251
|
-
const messages2 = [{ role: "user", content: agentPrompt }];
|
|
1252
|
-
const toolsUsed = [];
|
|
1253
|
-
const response = await chatWithTools(messages2, `sdk:${app2.id}:agent:${body.type}`, (tool) => toolsUsed.push(tool), { appType: app2.type });
|
|
1254
|
-
return c.json({
|
|
1255
|
-
agent: body.type,
|
|
1256
|
-
result: response.content,
|
|
1257
|
-
toolsUsed,
|
|
1258
|
-
usage: {
|
|
1259
|
-
inputTokens: response.inputTokens,
|
|
1260
|
-
outputTokens: response.outputTokens
|
|
1261
|
-
}
|
|
1262
|
-
});
|
|
1263
|
-
} catch (error) {
|
|
1264
|
-
return c.json({ error: "Agent spawn failed" }, 500);
|
|
1265
|
-
}
|
|
1266
|
-
});
|
|
1267
|
-
sdkRoutes.get("/status", (c) => {
|
|
1268
|
-
const app2 = c.get("sdkApp");
|
|
1269
|
-
const allApps = Array.from(registeredApps.values()).map((a) => ({
|
|
1270
|
-
id: a.id,
|
|
1271
|
-
name: a.name,
|
|
1272
|
-
type: a.type,
|
|
1273
|
-
registeredAt: a.registeredAt,
|
|
1274
|
-
lastSeen: a.lastSeen
|
|
1275
|
-
}));
|
|
1276
|
-
return c.json({
|
|
1277
|
-
opensentinel: {
|
|
1278
|
-
status: "online",
|
|
1279
|
-
version: "2.2.1",
|
|
1280
|
-
uptime: process.uptime()
|
|
1281
|
-
},
|
|
1282
|
-
currentApp: {
|
|
1283
|
-
id: app2.id,
|
|
1284
|
-
name: app2.name,
|
|
1285
|
-
type: app2.type
|
|
1286
|
-
},
|
|
1287
|
-
registeredApps: allApps,
|
|
1288
|
-
tools: TOOLS.length
|
|
1289
|
-
});
|
|
1290
|
-
});
|
|
1291
|
-
|
|
1292
|
-
// src/inputs/api/routes/admin.ts
|
|
1293
|
-
import { Hono as Hono4 } from "hono";
|
|
1294
|
-
|
|
1295
|
-
// src/core/security/rate-limiter.ts
|
|
1296
|
-
import Redis from "ioredis";
|
|
1297
|
-
var redis = new Redis(env.REDIS_URL, {
|
|
1298
|
-
maxRetriesPerRequest: 3,
|
|
1299
|
-
retryDelayOnFailover: 100
|
|
1300
|
-
});
|
|
1301
|
-
var DEFAULT_LIMITS = {
|
|
1302
|
-
"api/chat": { windowMs: 6e4, maxRequests: 30 },
|
|
1303
|
-
"api/chat/tools": { windowMs: 6e4, maxRequests: 20 },
|
|
1304
|
-
"api/ask": { windowMs: 6e4, maxRequests: 30 },
|
|
1305
|
-
"tool/shell": { windowMs: 6e4, maxRequests: 10 },
|
|
1306
|
-
"tool/browser": { windowMs: 6e4, maxRequests: 10 },
|
|
1307
|
-
"tool/file_write": { windowMs: 6e4, maxRequests: 20 },
|
|
1308
|
-
"agent/spawn": { windowMs: 36e5, maxRequests: 5 },
|
|
1309
|
-
// 5 agents per hour
|
|
1310
|
-
default: { windowMs: 6e4, maxRequests: 60 }
|
|
1311
|
-
};
|
|
1312
|
-
function getKey(identifier, endpoint) {
|
|
1313
|
-
return `ratelimit:${identifier}:${endpoint}`;
|
|
1314
|
-
}
|
|
1315
|
-
async function checkRateLimit(identifier, endpoint, customConfig) {
|
|
1316
|
-
const config = customConfig || DEFAULT_LIMITS[endpoint] || DEFAULT_LIMITS.default;
|
|
1317
|
-
const { windowMs, maxRequests } = config;
|
|
1318
|
-
const key = getKey(identifier, endpoint);
|
|
1319
|
-
const now = Date.now();
|
|
1320
|
-
try {
|
|
1321
|
-
const multi = redis.multi();
|
|
1322
|
-
multi.zremrangebyscore(key, 0, now - windowMs);
|
|
1323
|
-
multi.zcard(key);
|
|
1324
|
-
multi.zadd(key, now.toString(), `${now}:${Math.random()}`);
|
|
1325
|
-
multi.pexpire(key, windowMs);
|
|
1326
|
-
const results = await multi.exec();
|
|
1327
|
-
if (!results) {
|
|
1328
|
-
console.warn("[RateLimiter] Redis transaction failed, allowing request");
|
|
1329
|
-
return {
|
|
1330
|
-
allowed: true,
|
|
1331
|
-
remaining: maxRequests,
|
|
1332
|
-
resetAt: new Date(now + windowMs)
|
|
1333
|
-
};
|
|
1334
|
-
}
|
|
1335
|
-
const currentCount = results[1]?.[1] || 0;
|
|
1336
|
-
const resetAt = new Date(now + windowMs);
|
|
1337
|
-
if (currentCount >= maxRequests) {
|
|
1338
|
-
await redis.zrem(key, `${now}:${Math.random()}`);
|
|
1339
|
-
return {
|
|
1340
|
-
allowed: false,
|
|
1341
|
-
remaining: 0,
|
|
1342
|
-
resetAt,
|
|
1343
|
-
retryAfterMs: windowMs - (now - await getWindowStart(key, now, windowMs))
|
|
1344
|
-
};
|
|
1345
|
-
}
|
|
1346
|
-
return {
|
|
1347
|
-
allowed: true,
|
|
1348
|
-
remaining: maxRequests - currentCount - 1,
|
|
1349
|
-
resetAt
|
|
1350
|
-
};
|
|
1351
|
-
} catch (error) {
|
|
1352
|
-
console.error("[RateLimiter] Error checking rate limit:", error);
|
|
1353
|
-
return {
|
|
1354
|
-
allowed: true,
|
|
1355
|
-
remaining: maxRequests,
|
|
1356
|
-
resetAt: new Date(now + windowMs)
|
|
1357
|
-
};
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
async function getWindowStart(key, now, windowMs) {
|
|
1361
|
-
const oldest = await redis.zrange(key, 0, 0, "WITHSCORES");
|
|
1362
|
-
if (oldest.length >= 2) {
|
|
1363
|
-
return parseInt(oldest[1], 10);
|
|
1364
|
-
}
|
|
1365
|
-
return now - windowMs;
|
|
1366
|
-
}
|
|
1367
|
-
|
|
1368
|
-
// src/inputs/api/routes/admin.ts
|
|
1369
|
-
var adminRouter = new Hono4();
|
|
1370
|
-
async function requireAdminKey(c, next) {
|
|
1371
|
-
const apiKey = c.req.header("x-api-key");
|
|
1372
|
-
if (!apiKey) {
|
|
1373
|
-
return c.json({ error: "API key required" }, 401);
|
|
1374
|
-
}
|
|
1375
|
-
const rateLimitResult = await checkRateLimit(apiKey, "api/admin");
|
|
1376
|
-
if (!rateLimitResult.allowed) {
|
|
1377
|
-
return c.json(
|
|
1378
|
-
{ error: "Rate limit exceeded", retryAfter: rateLimitResult.retryAfterMs },
|
|
1379
|
-
429
|
|
1380
|
-
);
|
|
1381
|
-
}
|
|
1382
|
-
await next();
|
|
1383
|
-
}
|
|
1384
|
-
adminRouter.use("*", requireAdminKey);
|
|
1385
|
-
adminRouter.get("/audit-logs", async (c) => {
|
|
1386
|
-
try {
|
|
1387
|
-
const url = new URL(c.req.url);
|
|
1388
|
-
const options = {};
|
|
1389
|
-
const userId = url.searchParams.get("userId");
|
|
1390
|
-
if (userId) options.userId = userId;
|
|
1391
|
-
const action = url.searchParams.get("action");
|
|
1392
|
-
if (action) options.action = action;
|
|
1393
|
-
const resource = url.searchParams.get("resource");
|
|
1394
|
-
if (resource) options.resource = resource;
|
|
1395
|
-
const startDate = url.searchParams.get("startDate");
|
|
1396
|
-
if (startDate) options.startDate = new Date(startDate);
|
|
1397
|
-
const endDate = url.searchParams.get("endDate");
|
|
1398
|
-
if (endDate) options.endDate = new Date(endDate);
|
|
1399
|
-
const limit = url.searchParams.get("limit");
|
|
1400
|
-
options.limit = limit ? Math.min(parseInt(limit, 10), 500) : 100;
|
|
1401
|
-
const offset = url.searchParams.get("offset");
|
|
1402
|
-
options.offset = offset ? parseInt(offset, 10) : 0;
|
|
1403
|
-
const logs = await queryAuditLogs(options);
|
|
1404
|
-
return c.json({
|
|
1405
|
-
success: true,
|
|
1406
|
-
logs,
|
|
1407
|
-
count: logs.length,
|
|
1408
|
-
limit: options.limit,
|
|
1409
|
-
offset: options.offset
|
|
1410
|
-
});
|
|
1411
|
-
} catch (err) {
|
|
1412
|
-
return c.json({ error: err.message || "Failed to query audit logs" }, 500);
|
|
1413
|
-
}
|
|
1414
|
-
});
|
|
1415
|
-
adminRouter.get("/audit-logs/integrity", async (c) => {
|
|
1416
|
-
try {
|
|
1417
|
-
const integrity = await getAuditChainIntegrity();
|
|
1418
|
-
return c.json({ success: true, ...integrity });
|
|
1419
|
-
} catch (err) {
|
|
1420
|
-
return c.json({ error: err.message || "Failed to check integrity" }, 500);
|
|
1421
|
-
}
|
|
1422
|
-
});
|
|
1423
|
-
adminRouter.get("/incidents", async (c) => {
|
|
1424
|
-
try {
|
|
1425
|
-
const url = new URL(c.req.url);
|
|
1426
|
-
const limit = Math.min(parseInt(url.searchParams.get("limit") || "50", 10), 200);
|
|
1427
|
-
const incidents = await queryAuditLogs({
|
|
1428
|
-
action: "error",
|
|
1429
|
-
limit
|
|
1430
|
-
});
|
|
1431
|
-
return c.json({
|
|
1432
|
-
success: true,
|
|
1433
|
-
incidents,
|
|
1434
|
-
count: incidents.length
|
|
1435
|
-
});
|
|
1436
|
-
} catch (err) {
|
|
1437
|
-
return c.json({ error: err.message || "Failed to query incidents" }, 500);
|
|
1438
|
-
}
|
|
1439
|
-
});
|
|
1440
|
-
var admin_default = adminRouter;
|
|
1441
|
-
|
|
1442
|
-
// src/inputs/api/server.ts
|
|
1443
|
-
var serveStatic;
|
|
1444
|
-
try {
|
|
1445
|
-
serveStatic = __require("hono/bun").serveStatic;
|
|
1446
|
-
} catch {
|
|
1447
|
-
serveStatic = () => async (_c, next) => next();
|
|
1448
|
-
}
|
|
1449
|
-
var app = new Hono5();
|
|
1450
|
-
app.use("*", logger());
|
|
1451
|
-
app.use("/api/*", cors());
|
|
1452
|
-
app.use("/api/*", authMiddleware());
|
|
1453
|
-
app.get("/health", (c) => {
|
|
1454
|
-
return c.json({ status: "ok", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
1455
|
-
});
|
|
1456
|
-
app.post("/api/chat", async (c) => {
|
|
1457
|
-
try {
|
|
1458
|
-
const body = await c.req.json();
|
|
1459
|
-
if (!body.messages || !Array.isArray(body.messages)) {
|
|
1460
|
-
return c.json({ error: "messages array is required" }, 400);
|
|
1461
|
-
}
|
|
1462
|
-
const response = await chat(body.messages, body.systemPrompt);
|
|
1463
|
-
return c.json({
|
|
1464
|
-
content: response.content,
|
|
1465
|
-
usage: {
|
|
1466
|
-
inputTokens: response.inputTokens,
|
|
1467
|
-
outputTokens: response.outputTokens
|
|
1468
|
-
}
|
|
1469
|
-
});
|
|
1470
|
-
} catch (error) {
|
|
1471
|
-
console.error("Chat API error:", error);
|
|
1472
|
-
return c.json({ error: "Internal server error" }, 500);
|
|
1473
|
-
}
|
|
1474
|
-
});
|
|
1475
|
-
app.post("/api/chat/tools", requirePermission("chat:tools"), async (c) => {
|
|
1476
|
-
try {
|
|
1477
|
-
const body = await c.req.json();
|
|
1478
|
-
if (!body.messages || !Array.isArray(body.messages)) {
|
|
1479
|
-
return c.json({ error: "messages array is required" }, 400);
|
|
1480
|
-
}
|
|
1481
|
-
const toolsUsed = [];
|
|
1482
|
-
const response = await chatWithTools(body.messages, body.userId, (tool) => {
|
|
1483
|
-
toolsUsed.push(tool);
|
|
1484
|
-
});
|
|
1485
|
-
return c.json({
|
|
1486
|
-
content: response.content,
|
|
1487
|
-
toolsUsed,
|
|
1488
|
-
usage: {
|
|
1489
|
-
inputTokens: response.inputTokens,
|
|
1490
|
-
outputTokens: response.outputTokens
|
|
1491
|
-
}
|
|
1492
|
-
});
|
|
1493
|
-
} catch (error) {
|
|
1494
|
-
console.error("Chat with tools API error:", error);
|
|
1495
|
-
return c.json({ error: "Internal server error" }, 500);
|
|
1496
|
-
}
|
|
1497
|
-
});
|
|
1498
|
-
app.post("/api/ask", async (c) => {
|
|
1499
|
-
try {
|
|
1500
|
-
const body = await c.req.json();
|
|
1501
|
-
if (!body.message) {
|
|
1502
|
-
return c.json({ error: "message is required" }, 400);
|
|
1503
|
-
}
|
|
1504
|
-
const messages2 = [{ role: "user", content: body.message }];
|
|
1505
|
-
const response = body.useTools ? await chatWithTools(messages2) : await chat(messages2, body.systemPrompt);
|
|
1506
|
-
return c.json({
|
|
1507
|
-
content: response.content,
|
|
1508
|
-
toolsUsed: response.toolsUsed,
|
|
1509
|
-
usage: {
|
|
1510
|
-
inputTokens: response.inputTokens,
|
|
1511
|
-
outputTokens: response.outputTokens
|
|
1512
|
-
}
|
|
1513
|
-
});
|
|
1514
|
-
} catch (error) {
|
|
1515
|
-
console.error("Ask API error:", error);
|
|
1516
|
-
return c.json({ error: "Internal server error" }, 500);
|
|
1517
|
-
}
|
|
1518
|
-
});
|
|
1519
|
-
app.get("/api/conversations", async (c) => {
|
|
1520
|
-
try {
|
|
1521
|
-
const convos = await db.select().from(conversations).orderBy(desc2(conversations.updatedAt)).limit(50);
|
|
1522
|
-
return c.json(convos);
|
|
1523
|
-
} catch (error) {
|
|
1524
|
-
console.error("Error fetching conversations:", error);
|
|
1525
|
-
return c.json({ error: "Internal server error" }, 500);
|
|
1526
|
-
}
|
|
1527
|
-
});
|
|
1528
|
-
app.get("/api/conversations/:id", async (c) => {
|
|
1529
|
-
try {
|
|
1530
|
-
const id = c.req.param("id");
|
|
1531
|
-
const convo = await db.select().from(conversations).where(eq4(conversations.id, id)).limit(1);
|
|
1532
|
-
if (convo.length === 0) {
|
|
1533
|
-
return c.json({ error: "Conversation not found" }, 404);
|
|
1534
|
-
}
|
|
1535
|
-
const msgs = await db.select().from(messages).where(eq4(messages.conversationId, id)).orderBy(messages.createdAt);
|
|
1536
|
-
const decryptedMsgs = msgs.map((m) => {
|
|
1537
|
-
if (m.encrypted && m.content) {
|
|
1538
|
-
try {
|
|
1539
|
-
return { ...m, content: decryptField(m.content) ?? m.content };
|
|
1540
|
-
} catch {
|
|
1541
|
-
return m;
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
return m;
|
|
1545
|
-
});
|
|
1546
|
-
return c.json({ conversation: convo[0], messages: decryptedMsgs });
|
|
1547
|
-
} catch (error) {
|
|
1548
|
-
console.error("Error fetching conversation:", error);
|
|
1549
|
-
return c.json({ error: "Internal server error" }, 500);
|
|
1550
|
-
}
|
|
1551
|
-
});
|
|
1552
|
-
app.get("/api/memories", async (c) => {
|
|
1553
|
-
try {
|
|
1554
|
-
const userId = c.req.query("userId");
|
|
1555
|
-
const limit = parseInt(c.req.query("limit") || "50");
|
|
1556
|
-
let query = db.select().from(memories).orderBy(desc2(memories.createdAt)).limit(limit);
|
|
1557
|
-
const mems = await query;
|
|
1558
|
-
return c.json(mems);
|
|
1559
|
-
} catch (error) {
|
|
1560
|
-
console.error("Error fetching memories:", error);
|
|
1561
|
-
return c.json({ error: "Internal server error" }, 500);
|
|
1562
|
-
}
|
|
1563
|
-
});
|
|
1564
|
-
app.post("/api/memories/search", async (c) => {
|
|
1565
|
-
try {
|
|
1566
|
-
const body = await c.req.json();
|
|
1567
|
-
if (!body.query) {
|
|
1568
|
-
return c.json({ error: "query is required" }, 400);
|
|
1569
|
-
}
|
|
1570
|
-
const results = await searchMemories(body.query, body.userId, body.limit || 5);
|
|
1571
|
-
return c.json(results);
|
|
1572
|
-
} catch (error) {
|
|
1573
|
-
console.error("Error searching memories:", error);
|
|
1574
|
-
return c.json({ error: "Internal server error" }, 500);
|
|
1575
|
-
}
|
|
1576
|
-
});
|
|
1577
|
-
app.post("/api/memories", async (c) => {
|
|
1578
|
-
try {
|
|
1579
|
-
const body = await c.req.json();
|
|
1580
|
-
if (!body.content) {
|
|
1581
|
-
return c.json({ error: "content is required" }, 400);
|
|
1582
|
-
}
|
|
1583
|
-
const memory = await storeMemory({
|
|
1584
|
-
content: body.content,
|
|
1585
|
-
type: body.type || "semantic",
|
|
1586
|
-
importance: body.importance || 5,
|
|
1587
|
-
userId: body.userId,
|
|
1588
|
-
source: "api",
|
|
1589
|
-
provenance: "api:manual"
|
|
1590
|
-
});
|
|
1591
|
-
return c.json(memory);
|
|
1592
|
-
} catch (error) {
|
|
1593
|
-
console.error("Error storing memory:", error);
|
|
1594
|
-
return c.json({ error: "Internal server error" }, 500);
|
|
1595
|
-
}
|
|
1596
|
-
});
|
|
1597
|
-
app.get("/api/memories/export", async (c) => {
|
|
1598
|
-
try {
|
|
1599
|
-
const userId = c.req.query("userId");
|
|
1600
|
-
const format = c.req.query("format") || "markdown";
|
|
1601
|
-
const exported = await exportMemories(userId || void 0, format);
|
|
1602
|
-
if (format === "json") {
|
|
1603
|
-
return c.json(JSON.parse(exported));
|
|
1604
|
-
}
|
|
1605
|
-
return c.text(exported);
|
|
1606
|
-
} catch (error) {
|
|
1607
|
-
console.error("Error exporting memories:", error);
|
|
1608
|
-
return c.json({ error: "Internal server error" }, 500);
|
|
1609
|
-
}
|
|
1610
|
-
});
|
|
1611
|
-
app.get("/api/memories/:id", async (c) => {
|
|
1612
|
-
try {
|
|
1613
|
-
const id = c.req.param("id");
|
|
1614
|
-
const memory = await getMemoryById(id);
|
|
1615
|
-
if (!memory) {
|
|
1616
|
-
return c.json({ error: "Memory not found" }, 404);
|
|
1617
|
-
}
|
|
1618
|
-
return c.json(memory);
|
|
1619
|
-
} catch (error) {
|
|
1620
|
-
console.error("Error fetching memory:", error);
|
|
1621
|
-
return c.json({ error: "Internal server error" }, 500);
|
|
1622
|
-
}
|
|
1623
|
-
});
|
|
1624
|
-
app.put("/api/memories/:id", async (c) => {
|
|
1625
|
-
try {
|
|
1626
|
-
const id = c.req.param("id");
|
|
1627
|
-
const body = await c.req.json();
|
|
1628
|
-
const updated = await updateMemory(id, body);
|
|
1629
|
-
if (!updated) {
|
|
1630
|
-
return c.json({ error: "Memory not found or no changes" }, 404);
|
|
1631
|
-
}
|
|
1632
|
-
return c.json(updated);
|
|
1633
|
-
} catch (error) {
|
|
1634
|
-
console.error("Error updating memory:", error);
|
|
1635
|
-
return c.json({ error: "Internal server error" }, 500);
|
|
1636
|
-
}
|
|
1637
|
-
});
|
|
1638
|
-
app.delete("/api/memories/:id", requirePermission("memories:delete"), async (c) => {
|
|
1639
|
-
try {
|
|
1640
|
-
const id = c.req.param("id");
|
|
1641
|
-
const deleted = await deleteMemory(id);
|
|
1642
|
-
if (!deleted) {
|
|
1643
|
-
return c.json({ error: "Memory not found" }, 404);
|
|
1644
|
-
}
|
|
1645
|
-
return c.json({ success: true, id });
|
|
1646
|
-
} catch (error) {
|
|
1647
|
-
console.error("Error deleting memory:", error);
|
|
1648
|
-
return c.json({ error: "Internal server error" }, 500);
|
|
1649
|
-
}
|
|
1650
|
-
});
|
|
1651
|
-
app.get("/api/autonomy", async (c) => {
|
|
1652
|
-
try {
|
|
1653
|
-
const { autonomyManager } = await import("./autonomy-ZXDBDQUJ.js");
|
|
1654
|
-
const userId = c.req.query("userId");
|
|
1655
|
-
return c.json({
|
|
1656
|
-
level: userId ? autonomyManager.getLevel(userId) : autonomyManager.getDefaultLevel(),
|
|
1657
|
-
stats: autonomyManager.getStats()
|
|
1658
|
-
});
|
|
1659
|
-
} catch (error) {
|
|
1660
|
-
return c.json({ error: "Autonomy system not available" }, 500);
|
|
1661
|
-
}
|
|
1662
|
-
});
|
|
1663
|
-
app.put("/api/autonomy", async (c) => {
|
|
1664
|
-
try {
|
|
1665
|
-
const { autonomyManager } = await import("./autonomy-ZXDBDQUJ.js");
|
|
1666
|
-
const body = await c.req.json();
|
|
1667
|
-
const level = body.level;
|
|
1668
|
-
if (!["readonly", "supervised", "autonomous"].includes(level)) {
|
|
1669
|
-
return c.json({ error: "Invalid level. Must be: readonly, supervised, or autonomous" }, 400);
|
|
1670
|
-
}
|
|
1671
|
-
if (body.userId) {
|
|
1672
|
-
autonomyManager.setLevel(body.userId, level);
|
|
1673
|
-
} else {
|
|
1674
|
-
autonomyManager.setDefaultLevel(level);
|
|
1675
|
-
}
|
|
1676
|
-
return c.json({ success: true, level });
|
|
1677
|
-
} catch (error) {
|
|
1678
|
-
return c.json({ error: "Autonomy system not available" }, 500);
|
|
1679
|
-
}
|
|
1680
|
-
});
|
|
1681
|
-
app.get("/metrics", async (c) => {
|
|
1682
|
-
try {
|
|
1683
|
-
const { prometheusExporter } = await import("./prometheus-JNT2BD4L.js");
|
|
1684
|
-
const text = prometheusExporter.toTextFormat();
|
|
1685
|
-
return c.text(text, 200, { "Content-Type": "text/plain; version=0.0.4; charset=utf-8" });
|
|
1686
|
-
} catch (error) {
|
|
1687
|
-
return c.text("# Prometheus metrics not available\n", 500);
|
|
1688
|
-
}
|
|
1689
|
-
});
|
|
1690
|
-
app.get("/api/metrics/prometheus", async (c) => {
|
|
1691
|
-
try {
|
|
1692
|
-
const { prometheusExporter } = await import("./prometheus-JNT2BD4L.js");
|
|
1693
|
-
const text = prometheusExporter.toTextFormat();
|
|
1694
|
-
return c.text(text, 200, { "Content-Type": "text/plain; version=0.0.4; charset=utf-8" });
|
|
1695
|
-
} catch (error) {
|
|
1696
|
-
return c.text("# Prometheus metrics not available\n", 500);
|
|
1697
|
-
}
|
|
1698
|
-
});
|
|
1699
|
-
app.post("/api/pair", async (c) => {
|
|
1700
|
-
try {
|
|
1701
|
-
const { pairingManager } = await import("./pairing-IFQYCPNS.js");
|
|
1702
|
-
const body = await c.req.json();
|
|
1703
|
-
if (!body.code) {
|
|
1704
|
-
return c.json({ error: "code is required" }, 400);
|
|
1705
|
-
}
|
|
1706
|
-
const result = pairingManager.pair(body.code, body.deviceInfo || "Unknown device");
|
|
1707
|
-
if (!result.success) {
|
|
1708
|
-
return c.json({ error: result.error }, 401);
|
|
1709
|
-
}
|
|
1710
|
-
return c.json({ token: result.token });
|
|
1711
|
-
} catch (error) {
|
|
1712
|
-
return c.json({ error: "Pairing system not available" }, 500);
|
|
1713
|
-
}
|
|
1714
|
-
});
|
|
1715
|
-
app.get("/api/providers", async (c) => {
|
|
1716
|
-
try {
|
|
1717
|
-
const { providerRegistry } = await import("./providers-J4LYPHDR.js");
|
|
1718
|
-
return c.json({
|
|
1719
|
-
providers: providerRegistry.listProviders(),
|
|
1720
|
-
default: providerRegistry.getDefaultId()
|
|
1721
|
-
});
|
|
1722
|
-
} catch (error) {
|
|
1723
|
-
return c.json({ error: "Provider system not available" }, 500);
|
|
1724
|
-
}
|
|
1725
|
-
});
|
|
1726
|
-
app.route("/api/osint", osint);
|
|
1727
|
-
app.route("/api/email", email);
|
|
1728
|
-
app.route("/api/sdk", sdkRoutes);
|
|
1729
|
-
app.route("/api/admin", admin_default);
|
|
1730
|
-
app.get("/api/incidents", requirePermission("admin:settings"), async (c) => {
|
|
1731
|
-
try {
|
|
1732
|
-
const { getOpenIncidents } = await import("./incident-response-C5J7Q6DT.js");
|
|
1733
|
-
const severity = c.req.query("severity");
|
|
1734
|
-
const type = c.req.query("type");
|
|
1735
|
-
const incidents = await getOpenIncidents({ severity, type, limit: 50 });
|
|
1736
|
-
return c.json(incidents);
|
|
1737
|
-
} catch (error) {
|
|
1738
|
-
return c.json({ error: "Incident system not available" }, 500);
|
|
1739
|
-
}
|
|
1740
|
-
});
|
|
1741
|
-
app.get("/api/incidents/:id", requirePermission("admin:settings"), async (c) => {
|
|
1742
|
-
try {
|
|
1743
|
-
const { generateIncidentReport } = await import("./incident-response-C5J7Q6DT.js");
|
|
1744
|
-
const id = c.req.param("id");
|
|
1745
|
-
const report = await generateIncidentReport(id);
|
|
1746
|
-
return c.json(report);
|
|
1747
|
-
} catch (error) {
|
|
1748
|
-
return c.json({ error: "Incident not found" }, 404);
|
|
1749
|
-
}
|
|
1750
|
-
});
|
|
1751
|
-
app.post("/api/incidents/:id/status", requirePermission("admin:settings"), async (c) => {
|
|
1752
|
-
try {
|
|
1753
|
-
const { updateIncidentStatus } = await import("./incident-response-C5J7Q6DT.js");
|
|
1754
|
-
const id = c.req.param("id");
|
|
1755
|
-
const body = await c.req.json();
|
|
1756
|
-
const userId = getAuthUserId(c);
|
|
1757
|
-
const updated = await updateIncidentStatus(id, body.status, userId, body.notes);
|
|
1758
|
-
return c.json(updated);
|
|
1759
|
-
} catch (error) {
|
|
1760
|
-
return c.json({ error: "Failed to update incident" }, 500);
|
|
1761
|
-
}
|
|
1762
|
-
});
|
|
1763
|
-
app.post("/api/incidents/:id/resolve", requirePermission("admin:settings"), async (c) => {
|
|
1764
|
-
try {
|
|
1765
|
-
const { resolveIncident } = await import("./incident-response-C5J7Q6DT.js");
|
|
1766
|
-
const id = c.req.param("id");
|
|
1767
|
-
const body = await c.req.json();
|
|
1768
|
-
const userId = getAuthUserId(c);
|
|
1769
|
-
const resolved = await resolveIncident(id, body.notes, userId);
|
|
1770
|
-
return c.json(resolved);
|
|
1771
|
-
} catch (error) {
|
|
1772
|
-
return c.json({ error: "Failed to resolve incident" }, 500);
|
|
1773
|
-
}
|
|
1774
|
-
});
|
|
1775
|
-
app.get("/api/audit/integrity", requirePermission("admin:settings"), async (c) => {
|
|
1776
|
-
try {
|
|
1777
|
-
const { getAuditChainIntegrity: getAuditChainIntegrity2 } = await import("./audit-logger-OBPR7CRO.js");
|
|
1778
|
-
const integrity = await getAuditChainIntegrity2();
|
|
1779
|
-
return c.json(integrity);
|
|
1780
|
-
} catch (error) {
|
|
1781
|
-
return c.json({ error: "Audit system not available" }, 500);
|
|
1782
|
-
}
|
|
1783
|
-
});
|
|
1784
|
-
app.post("/api/transcribe", async (c) => {
|
|
1785
|
-
try {
|
|
1786
|
-
const formData = await c.req.formData();
|
|
1787
|
-
const audioFile = formData.get("audio");
|
|
1788
|
-
if (!audioFile || !(audioFile instanceof File)) {
|
|
1789
|
-
return c.json({ error: "audio file is required" }, 400);
|
|
1790
|
-
}
|
|
1791
|
-
const buffer = Buffer.from(await audioFile.arrayBuffer());
|
|
1792
|
-
const text = await transcribeAudio(buffer);
|
|
1793
|
-
if (!text) {
|
|
1794
|
-
return c.json({ error: "Could not transcribe audio" }, 500);
|
|
1795
|
-
}
|
|
1796
|
-
return c.json({ text });
|
|
1797
|
-
} catch (error) {
|
|
1798
|
-
console.error("Transcribe API error:", error);
|
|
1799
|
-
return c.json({ error: "Transcription failed" }, 500);
|
|
1800
|
-
}
|
|
1801
|
-
});
|
|
1802
|
-
app.post("/api/tts", async (c) => {
|
|
1803
|
-
try {
|
|
1804
|
-
const body = await c.req.json();
|
|
1805
|
-
if (!body.text) {
|
|
1806
|
-
return c.json({ error: "text is required" }, 400);
|
|
1807
|
-
}
|
|
1808
|
-
const audioBuffer = await textToSpeech(body.text);
|
|
1809
|
-
if (!audioBuffer) {
|
|
1810
|
-
return c.json({ error: "Text-to-speech failed" }, 500);
|
|
1811
|
-
}
|
|
1812
|
-
return new Response(new Uint8Array(audioBuffer), {
|
|
1813
|
-
headers: {
|
|
1814
|
-
"Content-Type": "audio/mpeg",
|
|
1815
|
-
"Content-Length": String(audioBuffer.length)
|
|
1816
|
-
}
|
|
1817
|
-
});
|
|
1818
|
-
} catch (error) {
|
|
1819
|
-
console.error("TTS API error:", error);
|
|
1820
|
-
return c.json({ error: "TTS failed" }, 500);
|
|
1821
|
-
}
|
|
1822
|
-
});
|
|
1823
|
-
app.get("/api/system/status", async (c) => {
|
|
1824
|
-
const authHeader = c.req.header("Authorization");
|
|
1825
|
-
if (authHeader?.startsWith("Bearer ")) {
|
|
1826
|
-
return c.json({
|
|
1827
|
-
status: "online",
|
|
1828
|
-
version: "3.0.0",
|
|
1829
|
-
uptime: process.uptime(),
|
|
1830
|
-
memory: process.memoryUsage()
|
|
1831
|
-
});
|
|
1832
|
-
}
|
|
1833
|
-
return c.json({
|
|
1834
|
-
status: "online",
|
|
1835
|
-
version: "3.0.0"
|
|
1836
|
-
});
|
|
1837
|
-
});
|
|
1838
|
-
app.get("/api/callbacks/spotify", async (c) => {
|
|
1839
|
-
try {
|
|
1840
|
-
const code = c.req.query("code");
|
|
1841
|
-
const error = c.req.query("error");
|
|
1842
|
-
if (error) {
|
|
1843
|
-
return c.html(`<h1>Spotify Authorization Failed</h1><p>Error: ${error}</p><p>Go back and try again.</p>`);
|
|
1844
|
-
}
|
|
1845
|
-
if (!code) {
|
|
1846
|
-
return c.html(`<h1>Missing Authorization Code</h1><p>No code received from Spotify.</p>`);
|
|
1847
|
-
}
|
|
1848
|
-
const { env: appEnv } = await import("./env-IWXUVTCB.js");
|
|
1849
|
-
if (!appEnv.SPOTIFY_CLIENT_ID || !appEnv.SPOTIFY_CLIENT_SECRET) {
|
|
1850
|
-
return c.html(`<h1>Spotify Not Configured</h1><p>Set SPOTIFY_CLIENT_ID and SPOTIFY_CLIENT_SECRET in .env</p>`);
|
|
1851
|
-
}
|
|
1852
|
-
const { createSpotifyAuth } = await import("./auth-UOX5K2BE.js");
|
|
1853
|
-
const auth = createSpotifyAuth({
|
|
1854
|
-
clientId: appEnv.SPOTIFY_CLIENT_ID,
|
|
1855
|
-
clientSecret: appEnv.SPOTIFY_CLIENT_SECRET,
|
|
1856
|
-
redirectUri: appEnv.SPOTIFY_REDIRECT_URI || `http://localhost:${appEnv.PORT}/api/callbacks/spotify`
|
|
1857
|
-
});
|
|
1858
|
-
const tokens = await auth.exchangeCode(code);
|
|
1859
|
-
return c.html(`
|
|
1860
|
-
<html><body style="font-family: system-ui; max-width: 600px; margin: 40px auto; padding: 20px;">
|
|
1861
|
-
<h1>Spotify Connected!</h1>
|
|
1862
|
-
<p>Add this to your <code>.env</code> file:</p>
|
|
1863
|
-
<pre style="background: #f0f0f0; padding: 16px; border-radius: 8px; word-break: break-all; white-space: pre-wrap;">SPOTIFY_REFRESH_TOKEN=${tokens.refreshToken}</pre>
|
|
1864
|
-
<p>Then restart OpenSentinel. You can close this page.</p>
|
|
1865
|
-
</body></html>
|
|
1866
|
-
`);
|
|
1867
|
-
} catch (err) {
|
|
1868
|
-
console.error("Spotify callback error:", err);
|
|
1869
|
-
return c.html(`<h1>Spotify Auth Error</h1><p>${err instanceof Error ? err.message : String(err)}</p>`);
|
|
1870
|
-
}
|
|
1871
|
-
});
|
|
1872
|
-
app.get("/api/spotify/authorize", async (c) => {
|
|
1873
|
-
try {
|
|
1874
|
-
const { env: appEnv } = await import("./env-IWXUVTCB.js");
|
|
1875
|
-
if (!appEnv.SPOTIFY_CLIENT_ID || !appEnv.SPOTIFY_CLIENT_SECRET) {
|
|
1876
|
-
return c.json({ error: "Spotify not configured. Set SPOTIFY_CLIENT_ID and SPOTIFY_CLIENT_SECRET in .env" }, 400);
|
|
1877
|
-
}
|
|
1878
|
-
const { createSpotifyAuth, DEFAULT_SCOPES } = await import("./auth-UOX5K2BE.js");
|
|
1879
|
-
const auth = createSpotifyAuth({
|
|
1880
|
-
clientId: appEnv.SPOTIFY_CLIENT_ID,
|
|
1881
|
-
clientSecret: appEnv.SPOTIFY_CLIENT_SECRET,
|
|
1882
|
-
redirectUri: appEnv.SPOTIFY_REDIRECT_URI || `http://localhost:${appEnv.PORT}/api/callbacks/spotify`
|
|
1883
|
-
});
|
|
1884
|
-
const url = auth.getAuthorizationUrl(DEFAULT_SCOPES, void 0, true);
|
|
1885
|
-
return c.json({ url });
|
|
1886
|
-
} catch (err) {
|
|
1887
|
-
return c.json({ error: err instanceof Error ? err.message : String(err) }, 500);
|
|
1888
|
-
}
|
|
1889
|
-
});
|
|
1890
|
-
app.use("/*", serveStatic({ root: "./src/web/dist" }));
|
|
1891
|
-
app.get("/*", serveStatic({ path: "./src/web/dist/index.html" }));
|
|
1892
|
-
|
|
1893
|
-
export {
|
|
1894
|
-
getGatewayToken,
|
|
1895
|
-
timingSafeEqual,
|
|
1896
|
-
app
|
|
1897
|
-
};
|
|
1898
|
-
//# sourceMappingURL=chunk-O7IH7JTI.js.map
|