opensentinel 3.1.1 → 3.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +126 -83
- package/dist/agent-manager-7N7REQZQ.js +39 -0
- package/dist/agent-processor-I23VWQY3.js +280 -0
- package/dist/agent-processor-I23VWQY3.js.map +1 -0
- package/dist/agent-types-2T4PXLFQ.js +12 -0
- package/dist/alerting-4I37GG4U.js +699 -0
- package/dist/alerting-4I37GG4U.js.map +1 -0
- package/dist/analysis-agent-JWN2GXYE.js +288 -0
- package/dist/analysis-agent-JWN2GXYE.js.map +1 -0
- package/dist/{archiver-AVNBYCKQ.js → archiver-XLRIIXPY.js} +86 -17
- package/dist/archiver-XLRIIXPY.js.map +1 -0
- package/dist/{audit-logger-OBPR7CRO.js → audit-logger-AU3TMWKI.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-MU2TJQ3Y.js +46 -0
- package/dist/brain-SLA474EU.js +65 -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-6PMVAAA7.js → chunk-2RGPWU77.js} +3 -3
- package/dist/{chunk-TVEWKIK3.js → chunk-2WTKTG2C.js} +2 -2
- package/dist/{chunk-MXAPLSJ5.js → chunk-45YXODSB.js} +2 -2
- package/dist/{chunk-SJSUSJ47.js → chunk-4YJRBMMA.js} +2 -2
- package/dist/chunk-643M3AP5.js +564 -0
- package/dist/chunk-643M3AP5.js.map +1 -0
- package/dist/{chunk-766ASQWE.js → chunk-6JY4HNUH.js} +2413 -2368
- package/dist/chunk-6JY4HNUH.js.map +1 -0
- package/dist/chunk-6LTLIYAQ.js +194 -0
- package/dist/chunk-6LTLIYAQ.js.map +1 -0
- package/dist/chunk-6UZPE35A.js +724 -0
- package/dist/chunk-6UZPE35A.js.map +1 -0
- package/dist/chunk-6W6PTJFT.js +181 -0
- package/dist/chunk-6W6PTJFT.js.map +1 -0
- package/dist/chunk-7MZN73J2.js +162 -0
- package/dist/chunk-7MZN73J2.js.map +1 -0
- package/dist/{chunk-SVAPX2XN.js → chunk-A24GPVLY.js} +9 -7
- package/dist/{chunk-SVAPX2XN.js.map → chunk-A24GPVLY.js.map} +1 -1
- package/dist/chunk-AD6YEH6U.js +3408 -0
- package/dist/chunk-AD6YEH6U.js.map +1 -0
- package/dist/chunk-ADTDYJO7.js +265 -0
- package/dist/chunk-ADTDYJO7.js.map +1 -0
- package/dist/{chunk-WRAKK6K6.js → chunk-AR34B6XR.js} +5 -3
- package/dist/{chunk-WRAKK6K6.js.map → chunk-AR34B6XR.js.map} +1 -1
- package/dist/chunk-BMOUYXLX.js +418 -0
- package/dist/chunk-BMOUYXLX.js.map +1 -0
- 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-RZ4YESBG.js → chunk-DOYGMNMK.js} +1 -1
- package/dist/chunk-DOYGMNMK.js.map +1 -0
- package/dist/chunk-FFV2SXFD.js +380 -0
- package/dist/chunk-FFV2SXFD.js.map +1 -0
- package/dist/{chunk-EVE7MIIY.js → chunk-GUKKW7JI.js} +15 -16
- package/dist/chunk-GUKKW7JI.js.map +1 -0
- package/dist/{chunk-66OJ3WB4.js → chunk-H3BOLSTS.js} +2 -2
- package/dist/chunk-HKOPRRDJ.js +1021 -0
- package/dist/chunk-HKOPRRDJ.js.map +1 -0
- package/dist/{chunk-BXZ6EA52.js → chunk-HTF2GIQC.js} +57 -3
- package/dist/chunk-HTF2GIQC.js.map +1 -0
- package/dist/{chunk-TYAGMJNV.js → chunk-JOA5A3G3.js} +5 -5
- package/dist/{chunk-OCVQGBJK.js → chunk-KABG5PG3.js} +6 -4
- package/dist/{chunk-OCVQGBJK.js.map → chunk-KABG5PG3.js.map} +1 -1
- package/dist/{chunk-VEHFVBLI.js → chunk-KT7NLIXP.js} +2 -2
- package/dist/chunk-LFDXEYYB.js +150 -0
- package/dist/chunk-LFDXEYYB.js.map +1 -0
- package/dist/{chunk-I6BDYQIG.js → chunk-M7YLQHFP.js} +6 -6
- package/dist/chunk-M7YLQHFP.js.map +1 -0
- package/dist/{chunk-AYUKPTSM.js → chunk-MFK34XSY.js} +96 -218
- package/dist/chunk-MFK34XSY.js.map +1 -0
- package/dist/chunk-MIC5IBQF.js +386 -0
- package/dist/chunk-MIC5IBQF.js.map +1 -0
- package/dist/{chunk-4UOE5TUZ.js → chunk-NMSHVO5O.js} +4 -4
- package/dist/{chunk-XKYRH4FM.js → chunk-NYVBXUGD.js} +13 -32
- package/dist/chunk-NYVBXUGD.js.map +1 -0
- package/dist/chunk-ODCFS5WD.js +463 -0
- package/dist/chunk-ODCFS5WD.js.map +1 -0
- package/dist/{chunk-ZLZKF2PM.js → chunk-PUNIMPMY.js} +32 -2
- package/dist/chunk-PUNIMPMY.js.map +1 -0
- package/dist/chunk-S4NJJS5C.js +37 -0
- package/dist/chunk-S4NJJS5C.js.map +1 -0
- package/dist/{chunk-NHMBTUMW.js → chunk-TAAZB5KN.js} +2 -2
- 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-4GLYY4NN.js → chunk-UWUIJTT4.js} +8 -2
- package/dist/chunk-UWUIJTT4.js.map +1 -0
- package/dist/{chunk-SPPMCAKG.js → chunk-VKMFUIVA.js} +2 -2
- package/dist/chunk-VKMFUIVA.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-ZIYTHUM5.js +457 -0
- package/dist/chunk-ZIYTHUM5.js.map +1 -0
- package/dist/chunker-K6WTR62A.js +12 -0
- package/dist/cli.js +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 +1 -1
- package/dist/commands/start.js +2 -2
- package/dist/commands/status.js +1 -1
- package/dist/commands/stop.js +1 -1
- package/dist/commands/utils.js +1 -1
- package/dist/cost-tracker-EMOIOYH7.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-LRIOKQBO.js +77 -0
- package/dist/discord-NKR3X4AV.js +80 -0
- package/dist/documents-EYIYLZK2.js +184 -0
- package/dist/documents-EYIYLZK2.js.map +1 -0
- package/dist/docx-parser-EXL4TN5E.js +16 -0
- package/dist/{email-K7LO2IPB.js → email-EAQNULVD.js} +33 -25
- package/dist/{email-K7LO2IPB.js.map → email-EAQNULVD.js.map} +1 -1
- package/dist/{enhanced-retrieval-DNLLEM4Z.js → enhanced-retrieval-OGHT6TS5.js} +11 -8
- package/dist/{enhanced-retrieval-DNLLEM4Z.js.map → enhanced-retrieval-OGHT6TS5.js.map} +1 -1
- package/dist/enrichment-pipeline-CMUVBDC7.js +14 -0
- package/dist/{entity-resolution-Y3IUWEAT.js → entity-resolution-4X4JU43O.js} +6 -5
- package/dist/env-CHOFICED.js +12 -0
- package/dist/error-tracker-SVQSDQDW.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-KGNILDWJ.js +833 -0
- package/dist/github-KGNILDWJ.js.map +1 -0
- package/dist/{google-workspace-DKWUVNGC.js → google-workspace-TSZPZK5G.js} +2 -2
- 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-V2XNDDHT.js +43 -0
- package/dist/inbox-summarizer-DKKRYXDR.js +55 -0
- package/dist/{incident-response-C5J7Q6DT.js → incident-response-ZTIKUWEO.js} +8 -6
- package/dist/{incident-response-C5J7Q6DT.js.map → incident-response-ZTIKUWEO.js.map} +1 -1
- 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-J7PJ7MZ3.js +46 -0
- package/dist/lib.d.ts +73 -1
- package/dist/lib.js +86 -76
- package/dist/lib.js.map +1 -1
- package/dist/{mailchimp-KKNF6QJ7.js → mailchimp-ZFYDC44J.js} +2 -2
- package/dist/{matrix-QVHG76I7.js → matrix-XHTR53VQ.js} +29 -21
- package/dist/{matrix-QVHG76I7.js.map → matrix-XHTR53VQ.js.map} +1 -1
- package/dist/{mcp-3JI6W7ZE.js → mcp-3C2TN67D.js} +3 -3
- package/dist/metrics-VJDWQWU7.js +25 -0
- package/dist/{microsoft365-UCBKJHNX.js → microsoft365-6G2IJMWC.js} +2 -2
- package/dist/multi-user-S56GUD6L.js +411 -0
- package/dist/multi-user-S56GUD6L.js.map +1 -0
- package/dist/{ocr-AC7NPX33.js → ocr-LGUIPKVZ.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-HXTAMGHT.js} +3 -3
- package/dist/presentations-HXTAMGHT.js.map +1 -0
- package/dist/{prometheus-JNT2BD4L.js → prometheus-YETCZO4I.js} +2 -2
- package/dist/{providers-J4LYPHDR.js → providers-H6YIC3MG.js} +6 -4
- package/dist/{qr-code-WIX4PB4U.js → qr-code-6WZJHRKL.js} +2 -2
- 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-CA5UNHZV.js +73 -0
- package/dist/scheduler-CA5UNHZV.js.map +1 -0
- package/dist/schema-ALJ67YVG.js +72 -0
- package/dist/schema-ALJ67YVG.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/{shopify-NCXYJB4R.js → shopify-ON2PAU27.js} +2 -2
- package/dist/signal-X7IQJGRQ.js +43 -0
- package/dist/signal-X7IQJGRQ.js.map +1 -0
- package/dist/slack-P2LFUJUQ.js +85 -0
- package/dist/slack-P2LFUJUQ.js.map +1 -0
- package/dist/{sms-M3JIOTCW.js → sms-4VME2HUL.js} +4 -4
- package/dist/sms-4VME2HUL.js.map +1 -0
- package/dist/{src-VYUE6LRA.js → src-S5KX4YEV.js} +179 -48
- package/dist/src-S5KX4YEV.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/tools-FGPN522P.js +46 -0
- package/dist/tools-FGPN522P.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-KRPQ4YUX.js +43 -0
- package/dist/whatsapp-KRPQ4YUX.js.map +1 -0
- package/dist/{word-document-7B6SJMAY.js → word-document-D6N2C47N.js} +4 -4
- package/dist/word-document-D6N2C47N.js.map +1 -0
- package/dist/workflow-store-ZYAYE5P6.js +373 -0
- package/dist/workflow-store-ZYAYE5P6.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/package.json +11 -1
- package/dist/archiver-AVNBYCKQ.js.map +0 -1
- 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-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-XKYRH4FM.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/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/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-7N7REQZQ.js.map} +0 -0
- /package/dist/{auth-UOX5K2BE.js.map → agent-types-2T4PXLFQ.js.map} +0 -0
- /package/dist/{backup-restore-PZ7CYYB7.js.map → audit-logger-AU3TMWKI.js.map} +0 -0
- /package/dist/{blocks-R3PODY47.js.map → auth-PH5IHISW.js.map} +0 -0
- /package/dist/{aws-s3-Q4LLZZPD.js.map → aws-s3-QZMURYXB.js.map} +0 -0
- /package/dist/{bot-QRARP4UN.js.map → backup-restore-72OQTZO3.js.map} +0 -0
- /package/dist/{brain-7XLLM3KC.js.map → blocks-YOWOESDD.js.map} +0 -0
- /package/dist/{chunk-PLDDJCW6.js.map → bot-MU2TJQ3Y.js.map} +0 -0
- /package/dist/{client-ZQSFPMOB.js.map → brain-SLA474EU.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-6PMVAAA7.js.map → chunk-2RGPWU77.js.map} +0 -0
- /package/dist/{chunk-TVEWKIK3.js.map → chunk-2WTKTG2C.js.map} +0 -0
- /package/dist/{chunk-MXAPLSJ5.js.map → chunk-45YXODSB.js.map} +0 -0
- /package/dist/{chunk-SJSUSJ47.js.map → chunk-4YJRBMMA.js.map} +0 -0
- /package/dist/{chunk-MQJ2ECQT.js.map → chunk-CUPEENUY.js.map} +0 -0
- /package/dist/{chunk-66OJ3WB4.js.map → chunk-H3BOLSTS.js.map} +0 -0
- /package/dist/{chunk-TYAGMJNV.js.map → chunk-JOA5A3G3.js.map} +0 -0
- /package/dist/{chunk-VEHFVBLI.js.map → chunk-KT7NLIXP.js.map} +0 -0
- /package/dist/{chunk-4UOE5TUZ.js.map → chunk-NMSHVO5O.js.map} +0 -0
- /package/dist/{chunk-NHMBTUMW.js.map → chunk-TAAZB5KN.js.map} +0 -0
- /package/dist/{clipboard-manager-TEO2GEDN.js.map → chunk-UP2VWCW5.js.map} +0 -0
- /package/dist/{cron-explain-HHQKPD3M.js.map → chunker-K6WTR62A.js.map} +0 -0
- /package/dist/{crypto-4AP47IKC.js.map → client-FOIYPOZQ.js.map} +0 -0
- /package/dist/{databases-37X4CI2Y.js.map → clipboard-manager-4SBNESGZ.js.map} +0 -0
- /package/dist/{discord-B3HUPGQ6.js.map → cost-tracker-EMOIOYH7.js.map} +0 -0
- /package/dist/{enrichment-pipeline-MNHNW65K.js.map → cron-explain-UOOOYWZZ.js.map} +0 -0
- /package/dist/{entity-resolution-Y3IUWEAT.js.map → crypto-2VG3RJR2.js.map} +0 -0
- /package/dist/{env-IWXUVTCB.js.map → databases-XDPMG5AV.js.map} +0 -0
- /package/dist/{hash-tool-ULQYD7B5.js.map → db-LRIOKQBO.js.map} +0 -0
- /package/dist/{heartbeat-monitor-GCISLXI3.js.map → discord-NKR3X4AV.js.map} +0 -0
- /package/dist/{imessage-NGA2XF2V.js.map → docx-parser-EXL4TN5E.js.map} +0 -0
- /package/dist/{inbox-summarizer-NRI4S7IF.js.map → enrichment-pipeline-CMUVBDC7.js.map} +0 -0
- /package/dist/{inventory-manager-352OHXWD.js.map → entity-resolution-4X4JU43O.js.map} +0 -0
- /package/dist/{json-tool-QE2SYHEG.js.map → env-CHOFICED.js.map} +0 -0
- /package/dist/{key-rotation-DPHU4ZTB.js.map → error-tracker-SVQSDQDW.js.map} +0 -0
- /package/dist/{google-workspace-DKWUVNGC.js.map → google-workspace-TSZPZK5G.js.map} +0 -0
- /package/dist/{mcp-3JI6W7ZE.js.map → hash-tool-ENAB5LWH.js.map} +0 -0
- /package/dist/{ocr-AC7NPX33.js.map → heartbeat-monitor-KRDYTDBF.js.map} +0 -0
- /package/dist/{ollama-BOAMSPLJ.js.map → hooks-N4MIFBVM.js.map} +0 -0
- /package/dist/{image-generation-OSU7FP6F.js.map → image-generation-MDE6AVQO.js.map} +0 -0
- /package/dist/{pages-MI523RB7.js.map → imessage-V2XNDDHT.js.map} +0 -0
- /package/dist/{pairing-IFQYCPNS.js.map → inbox-summarizer-DKKRYXDR.js.map} +0 -0
- /package/dist/{pdf-ALQVOEJR.js.map → inventory-manager-C67BSZM6.js.map} +0 -0
- /package/dist/{jira-GSGDBMIG.js.map → jira-PAGZWUBJ.js.map} +0 -0
- /package/dist/{prometheus-JNT2BD4L.js.map → json-tool-4FK5RNER.js.map} +0 -0
- /package/dist/{providers-J4LYPHDR.js.map → key-rotation-WCC5FOYS.js.map} +0 -0
- /package/dist/{qr-code-WIX4PB4U.js.map → knowledge-base-J7PJ7MZ3.js.map} +0 -0
- /package/dist/{mailchimp-KKNF6QJ7.js.map → mailchimp-ZFYDC44J.js.map} +0 -0
- /package/dist/{regex-tool-W4ABRKGK.js.map → mcp-3C2TN67D.js.map} +0 -0
- /package/dist/{scheduler-VK4WFERV.js.map → metrics-VJDWQWU7.js.map} +0 -0
- /package/dist/{microsoft365-UCBKJHNX.js.map → microsoft365-6G2IJMWC.js.map} +0 -0
- /package/dist/{search-BCLBO5E3.js.map → ocr-LGUIPKVZ.js.map} +0 -0
- /package/dist/{signal-6CGDFYL2.js.map → ollama-J7CU45WT.js.map} +0 -0
- /package/dist/{slack-IZQWIKOH.js.map → pages-XDE7JRCA.js.map} +0 -0
- /package/dist/{pair-JDFTERIK.js.map → pair-YZJFQUU5.js.map} +0 -0
- /package/dist/{sms-M3JIOTCW.js.map → pairing-77N47RAT.js.map} +0 -0
- /package/dist/{stocks-XXWBPOCU.js.map → pdf-67HGXCFJ.js.map} +0 -0
- /package/dist/{text-transform-6SGUA5Z4.js.map → pdf-parser-YLMTTYHL.js.map} +0 -0
- /package/dist/{tools-2RLEI2N6.js.map → prometheus-YETCZO4I.js.map} +0 -0
- /package/dist/{unit-converter-ZYXMEZOE.js.map → providers-H6YIC3MG.js.map} +0 -0
- /package/dist/{whatsapp-LFX6YKCM.js.map → qr-code-6WZJHRKL.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
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LinearRegression
|
|
3
|
+
} from "./chunk-WZAH34TG.js";
|
|
4
|
+
|
|
5
|
+
// src/core/brain/router.ts
|
|
6
|
+
var MODEL_TIERS = {
|
|
7
|
+
fast: {
|
|
8
|
+
tier: "fast",
|
|
9
|
+
model: "claude-haiku-4-5-20251001",
|
|
10
|
+
provider: "anthropic",
|
|
11
|
+
label: "Haiku 4.5",
|
|
12
|
+
maxTokens: 2048,
|
|
13
|
+
costPerMInputToken: 0.8,
|
|
14
|
+
costPerMOutputToken: 4
|
|
15
|
+
},
|
|
16
|
+
balanced: {
|
|
17
|
+
tier: "balanced",
|
|
18
|
+
model: "claude-sonnet-4-20250514",
|
|
19
|
+
provider: "anthropic",
|
|
20
|
+
label: "Sonnet 4",
|
|
21
|
+
maxTokens: 4096,
|
|
22
|
+
costPerMInputToken: 3,
|
|
23
|
+
costPerMOutputToken: 15
|
|
24
|
+
},
|
|
25
|
+
powerful: {
|
|
26
|
+
tier: "powerful",
|
|
27
|
+
model: "claude-opus-4-20250514",
|
|
28
|
+
provider: "anthropic",
|
|
29
|
+
label: "Opus 4",
|
|
30
|
+
maxTokens: 8192,
|
|
31
|
+
costPerMInputToken: 15,
|
|
32
|
+
costPerMOutputToken: 75
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var FAST_PATTERNS = [
|
|
36
|
+
// Greetings and acknowledgments
|
|
37
|
+
/^(hi|hello|hey|thanks|thank you|ok|okay|yes|no|sure|got it|np|ty|thx|gm|gn)\b/i,
|
|
38
|
+
// Simple questions
|
|
39
|
+
/^(what time|what date|what day|how are you|who are you)\b/i,
|
|
40
|
+
// Short commands
|
|
41
|
+
/^(remind me|set timer|play|pause|stop|next|skip|mute|unmute)\b/i,
|
|
42
|
+
// Status checks
|
|
43
|
+
/^(status|check|ping|health|uptime)\b/i,
|
|
44
|
+
// Single-word queries
|
|
45
|
+
/^\w+[?!.]?$/i
|
|
46
|
+
];
|
|
47
|
+
var POWERFUL_PATTERNS = [
|
|
48
|
+
// Mathematical/formal reasoning
|
|
49
|
+
/\b(prove|theorem|derive|lemma|formal proof|mathematical induction)\b/i,
|
|
50
|
+
// Deep analysis
|
|
51
|
+
/\b(comprehensive analysis|in-depth|systematic review|research paper)\b/i,
|
|
52
|
+
// Complex coding tasks
|
|
53
|
+
/\b(architect|design pattern|refactor.{0,20}entire|rewrite.{0,20}from|full implementation)\b/i,
|
|
54
|
+
// Multi-step planning
|
|
55
|
+
/\b(step.by.step plan|detailed strategy|long.term plan|roadmap|proposal)\b/i,
|
|
56
|
+
// Compare/contrast
|
|
57
|
+
/\b(compare and contrast|pros and cons|trade.?offs|evaluate.{0,20}options)\b/i,
|
|
58
|
+
// Long-form writing
|
|
59
|
+
/\b(write.{0,15}essay|write.{0,15}report|write.{0,15}article|draft.{0,15}document)\b/i,
|
|
60
|
+
// Legal/medical/financial analysis
|
|
61
|
+
/\b(legal analysis|medical review|financial analysis|risk assessment)\b/i
|
|
62
|
+
];
|
|
63
|
+
var COMPLEX_TOOLS = /* @__PURE__ */ new Set([
|
|
64
|
+
"execute_command",
|
|
65
|
+
"write_file",
|
|
66
|
+
"generate_document",
|
|
67
|
+
"generate_spreadsheet",
|
|
68
|
+
"generate_chart",
|
|
69
|
+
"code_review",
|
|
70
|
+
"spawn_agent",
|
|
71
|
+
"create_workflow",
|
|
72
|
+
"analyze_image"
|
|
73
|
+
]);
|
|
74
|
+
var SIMPLE_TOOLS = /* @__PURE__ */ new Set([
|
|
75
|
+
"get_time",
|
|
76
|
+
"get_weather",
|
|
77
|
+
"search_web",
|
|
78
|
+
"read_file",
|
|
79
|
+
"list_files",
|
|
80
|
+
"get_system_info",
|
|
81
|
+
"get_calendar_events"
|
|
82
|
+
]);
|
|
83
|
+
var ModelRouter = class {
|
|
84
|
+
enabled;
|
|
85
|
+
defaultTier;
|
|
86
|
+
opusEnabled;
|
|
87
|
+
// Routing statistics
|
|
88
|
+
stats = { fast: 0, balanced: 0, powerful: 0 };
|
|
89
|
+
constructor(options) {
|
|
90
|
+
this.enabled = options?.enabled ?? true;
|
|
91
|
+
this.defaultTier = options?.defaultTier ?? "balanced";
|
|
92
|
+
this.opusEnabled = options?.opusEnabled ?? false;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Analyze message complexity and return recommended model config
|
|
96
|
+
*/
|
|
97
|
+
routeMessage(message, context) {
|
|
98
|
+
if (!this.enabled) {
|
|
99
|
+
this.stats[this.defaultTier]++;
|
|
100
|
+
return MODEL_TIERS[this.defaultTier];
|
|
101
|
+
}
|
|
102
|
+
const tier = this.classifyComplexity(message, context);
|
|
103
|
+
this.stats[tier]++;
|
|
104
|
+
return MODEL_TIERS[tier];
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Classify message complexity into a model tier
|
|
108
|
+
*/
|
|
109
|
+
classifyComplexity(message, context) {
|
|
110
|
+
if (context?.thinkingLevel === "extended" && this.opusEnabled) {
|
|
111
|
+
return "powerful";
|
|
112
|
+
}
|
|
113
|
+
const trimmed = message.trim();
|
|
114
|
+
if (trimmed.length < 15) {
|
|
115
|
+
return "fast";
|
|
116
|
+
}
|
|
117
|
+
for (const pattern of FAST_PATTERNS) {
|
|
118
|
+
if (pattern.test(trimmed)) {
|
|
119
|
+
return "fast";
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (this.opusEnabled) {
|
|
123
|
+
for (const pattern of POWERFUL_PATTERNS) {
|
|
124
|
+
if (pattern.test(trimmed)) {
|
|
125
|
+
return "powerful";
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (context?.toolsRequested) {
|
|
130
|
+
const hasComplexTools = context.toolsRequested.some((t) => COMPLEX_TOOLS.has(t));
|
|
131
|
+
const hasOnlySimpleTools = context.toolsRequested.every((t) => SIMPLE_TOOLS.has(t));
|
|
132
|
+
if (hasComplexTools && this.opusEnabled) {
|
|
133
|
+
return "powerful";
|
|
134
|
+
}
|
|
135
|
+
if (hasOnlySimpleTools && context.toolsRequested.length <= 2) {
|
|
136
|
+
return "fast";
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const wordCount = trimmed.split(/\s+/).length;
|
|
140
|
+
if (wordCount < 8) {
|
|
141
|
+
return "fast";
|
|
142
|
+
}
|
|
143
|
+
if (trimmed.length > 500 && this.opusEnabled) {
|
|
144
|
+
return "powerful";
|
|
145
|
+
}
|
|
146
|
+
const result = this.defaultTier;
|
|
147
|
+
if (context?.appTypeTier) {
|
|
148
|
+
const tierOrder = { fast: 0, balanced: 1, powerful: 2 };
|
|
149
|
+
if (tierOrder[context.appTypeTier] > tierOrder[result]) {
|
|
150
|
+
return context.appTypeTier;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Estimate cost for a given tier and token counts
|
|
157
|
+
*/
|
|
158
|
+
estimateCost(tier, inputTokens, outputTokens) {
|
|
159
|
+
const config = MODEL_TIERS[tier];
|
|
160
|
+
return inputTokens / 1e6 * config.costPerMInputToken + outputTokens / 1e6 * config.costPerMOutputToken;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Get info about a model tier
|
|
164
|
+
*/
|
|
165
|
+
getTierInfo(tier) {
|
|
166
|
+
return MODEL_TIERS[tier];
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Get routing statistics
|
|
170
|
+
*/
|
|
171
|
+
getStats() {
|
|
172
|
+
const total = this.stats.fast + this.stats.balanced + this.stats.powerful;
|
|
173
|
+
return { ...this.stats, total };
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Reset routing statistics
|
|
177
|
+
*/
|
|
178
|
+
resetStats() {
|
|
179
|
+
this.stats = { fast: 0, balanced: 0, powerful: 0 };
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Get estimated cost savings vs always using balanced
|
|
183
|
+
*/
|
|
184
|
+
getEstimatedSavings(avgInputTokens = 1e3, avgOutputTokens = 500) {
|
|
185
|
+
const stats = this.getStats();
|
|
186
|
+
if (stats.total === 0) return { withRouting: 0, withoutRouting: 0, savings: 0, savingsPercent: 0 };
|
|
187
|
+
const withRouting = this.estimateCost("fast", avgInputTokens * stats.fast, avgOutputTokens * stats.fast) + this.estimateCost("balanced", avgInputTokens * stats.balanced, avgOutputTokens * stats.balanced) + this.estimateCost("powerful", avgInputTokens * stats.powerful, avgOutputTokens * stats.powerful);
|
|
188
|
+
const withoutRouting = this.estimateCost("balanced", avgInputTokens * stats.total, avgOutputTokens * stats.total);
|
|
189
|
+
const savings = withoutRouting - withRouting;
|
|
190
|
+
const savingsPercent = withoutRouting > 0 ? savings / withoutRouting * 100 : 0;
|
|
191
|
+
return { withRouting, withoutRouting, savings, savingsPercent };
|
|
192
|
+
}
|
|
193
|
+
isEnabled() {
|
|
194
|
+
return this.enabled;
|
|
195
|
+
}
|
|
196
|
+
setEnabled(enabled) {
|
|
197
|
+
this.enabled = enabled;
|
|
198
|
+
}
|
|
199
|
+
isOpusEnabled() {
|
|
200
|
+
return this.opusEnabled;
|
|
201
|
+
}
|
|
202
|
+
setOpusEnabled(enabled) {
|
|
203
|
+
this.opusEnabled = enabled;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
var modelRouter = new ModelRouter();
|
|
207
|
+
|
|
208
|
+
// src/core/observability/cost-tracker.ts
|
|
209
|
+
var CostTracker = class {
|
|
210
|
+
records = [];
|
|
211
|
+
maxRecords = 1e4;
|
|
212
|
+
// Keep last 10K records in memory
|
|
213
|
+
dbLoaded = false;
|
|
214
|
+
/**
|
|
215
|
+
* Load historical cost records from the database on startup
|
|
216
|
+
*/
|
|
217
|
+
async loadFromDb() {
|
|
218
|
+
if (this.dbLoaded) return;
|
|
219
|
+
try {
|
|
220
|
+
const { db } = await import("./db-LRIOKQBO.js");
|
|
221
|
+
const { metrics } = await import("./schema-ALJ67YVG.js");
|
|
222
|
+
const { eq, desc } = await import("drizzle-orm");
|
|
223
|
+
const rows = await db.select().from(metrics).where(eq(metrics.name, "token_cost")).orderBy(desc(metrics.timestamp)).limit(this.maxRecords);
|
|
224
|
+
for (const row of rows.reverse()) {
|
|
225
|
+
const tags = row.tags || {};
|
|
226
|
+
this.records.push({
|
|
227
|
+
tier: tags.tier || "balanced",
|
|
228
|
+
inputTokens: parseInt(tags.inputTokens || "0"),
|
|
229
|
+
outputTokens: parseInt(tags.outputTokens || "0"),
|
|
230
|
+
cost: (row.value || 0) / 1e6,
|
|
231
|
+
// stored as micro-dollars
|
|
232
|
+
timestamp: new Date(row.timestamp).getTime()
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
this.dbLoaded = true;
|
|
236
|
+
if (this.records.length > 0) {
|
|
237
|
+
console.log(`[CostTracker] Loaded ${this.records.length} historical records from DB`);
|
|
238
|
+
}
|
|
239
|
+
} catch {
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Record token usage for a request
|
|
244
|
+
*/
|
|
245
|
+
recordUsage(tier, inputTokens, outputTokens) {
|
|
246
|
+
const tierConfig = MODEL_TIERS[tier] || MODEL_TIERS.balanced;
|
|
247
|
+
const inputCost = inputTokens / 1e6 * tierConfig.costPerMInputToken;
|
|
248
|
+
const outputCost = outputTokens / 1e6 * tierConfig.costPerMOutputToken;
|
|
249
|
+
const totalCost = inputCost + outputCost;
|
|
250
|
+
const record = {
|
|
251
|
+
tier,
|
|
252
|
+
inputTokens,
|
|
253
|
+
outputTokens,
|
|
254
|
+
cost: totalCost,
|
|
255
|
+
timestamp: Date.now()
|
|
256
|
+
};
|
|
257
|
+
this.records.push(record);
|
|
258
|
+
if (this.records.length > this.maxRecords) {
|
|
259
|
+
this.records = this.records.slice(-this.maxRecords);
|
|
260
|
+
}
|
|
261
|
+
this.persistRecord(record).catch(() => {
|
|
262
|
+
});
|
|
263
|
+
return record;
|
|
264
|
+
}
|
|
265
|
+
async persistRecord(record) {
|
|
266
|
+
try {
|
|
267
|
+
const { db } = await import("./db-LRIOKQBO.js");
|
|
268
|
+
const { metrics } = await import("./schema-ALJ67YVG.js");
|
|
269
|
+
await db.insert(metrics).values({
|
|
270
|
+
name: "token_cost",
|
|
271
|
+
value: Math.round(record.cost * 1e6),
|
|
272
|
+
// store as micro-dollars for integer precision
|
|
273
|
+
unit: "microdollars",
|
|
274
|
+
tags: {
|
|
275
|
+
tier: record.tier,
|
|
276
|
+
inputTokens: String(record.inputTokens),
|
|
277
|
+
outputTokens: String(record.outputTokens)
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
} catch {
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Get cost summary for a time range
|
|
285
|
+
*/
|
|
286
|
+
getCostSummary(since, until) {
|
|
287
|
+
const start = since || 0;
|
|
288
|
+
const end = until || Date.now();
|
|
289
|
+
const filtered = this.records.filter(
|
|
290
|
+
(r) => r.timestamp >= start && r.timestamp <= end
|
|
291
|
+
);
|
|
292
|
+
const costByTier = {};
|
|
293
|
+
let totalCost = 0;
|
|
294
|
+
let totalInputTokens = 0;
|
|
295
|
+
let totalOutputTokens = 0;
|
|
296
|
+
for (const record of filtered) {
|
|
297
|
+
totalCost += record.cost;
|
|
298
|
+
totalInputTokens += record.inputTokens;
|
|
299
|
+
totalOutputTokens += record.outputTokens;
|
|
300
|
+
costByTier[record.tier] = (costByTier[record.tier] || 0) + record.cost;
|
|
301
|
+
}
|
|
302
|
+
return {
|
|
303
|
+
totalCost,
|
|
304
|
+
costByTier,
|
|
305
|
+
totalInputTokens,
|
|
306
|
+
totalOutputTokens,
|
|
307
|
+
requestCount: filtered.length,
|
|
308
|
+
timeRange: { start, end }
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Get average cost per interaction
|
|
313
|
+
*/
|
|
314
|
+
getCostPerInteraction() {
|
|
315
|
+
if (this.records.length === 0) return 0;
|
|
316
|
+
const total = this.records.reduce((sum, r) => sum + r.cost, 0);
|
|
317
|
+
return total / this.records.length;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Get estimated monthly cost using Linear Regression forecasting.
|
|
321
|
+
* Fits a regression on daily cost totals from the last 14 days, then projects 30 days.
|
|
322
|
+
*/
|
|
323
|
+
getEstimatedMonthlyCost() {
|
|
324
|
+
if (this.records.length < 2) return 0;
|
|
325
|
+
const now = Date.now();
|
|
326
|
+
const dailyCosts = this.getDailyCostHistory(14);
|
|
327
|
+
if (dailyCosts.length < 2) {
|
|
328
|
+
const oneDayAgo = now - 864e5;
|
|
329
|
+
const recentRecords = this.records.filter((r) => r.timestamp >= oneDayAgo);
|
|
330
|
+
if (recentRecords.length === 0) return 0;
|
|
331
|
+
const dailyCost = recentRecords.reduce((sum, r) => sum + r.cost, 0);
|
|
332
|
+
return dailyCost * 30;
|
|
333
|
+
}
|
|
334
|
+
const predictions = LinearRegression.forecast(dailyCosts, 30);
|
|
335
|
+
return predictions.reduce((sum, p) => sum + Math.max(0, p.value), 0);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Detect spending trend: up, down, or flat.
|
|
339
|
+
*/
|
|
340
|
+
getCostTrend() {
|
|
341
|
+
const dailyCosts = this.getDailyCostHistory(14);
|
|
342
|
+
if (dailyCosts.length < 3) {
|
|
343
|
+
return { direction: "flat", strength: 0, dailyChange: 0 };
|
|
344
|
+
}
|
|
345
|
+
const trend = LinearRegression.detectTrend(dailyCosts);
|
|
346
|
+
return {
|
|
347
|
+
direction: trend.direction,
|
|
348
|
+
strength: trend.strength,
|
|
349
|
+
dailyChange: trend.slopePerUnit
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Get forecast with confidence intervals for the next N days.
|
|
354
|
+
*/
|
|
355
|
+
getForecast(daysAhead = 7) {
|
|
356
|
+
const dailyCosts = this.getDailyCostHistory(14);
|
|
357
|
+
if (dailyCosts.length < 2) return [];
|
|
358
|
+
const predictions = LinearRegression.forecast(dailyCosts, daysAhead);
|
|
359
|
+
return predictions.map((p, i) => ({
|
|
360
|
+
day: i + 1,
|
|
361
|
+
predicted: Math.max(0, p.value),
|
|
362
|
+
lower: Math.max(0, p.lower95),
|
|
363
|
+
upper: Math.max(0, p.upper95)
|
|
364
|
+
}));
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Get daily cost totals for the last N days.
|
|
368
|
+
*/
|
|
369
|
+
getDailyCostHistory(days) {
|
|
370
|
+
const now = Date.now();
|
|
371
|
+
const msPerDay = 864e5;
|
|
372
|
+
const dailyCosts = [];
|
|
373
|
+
for (let d = days - 1; d >= 0; d--) {
|
|
374
|
+
const dayStart = now - (d + 1) * msPerDay;
|
|
375
|
+
const dayEnd = now - d * msPerDay;
|
|
376
|
+
const dayCost = this.records.filter((r) => r.timestamp >= dayStart && r.timestamp < dayEnd).reduce((sum, r) => sum + r.cost, 0);
|
|
377
|
+
dailyCosts.push(dayCost);
|
|
378
|
+
}
|
|
379
|
+
return dailyCosts;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Get cost per million tokens for a tier
|
|
383
|
+
*/
|
|
384
|
+
getCostPerMillionTokens(tier) {
|
|
385
|
+
const config = MODEL_TIERS[tier] || MODEL_TIERS.balanced;
|
|
386
|
+
return {
|
|
387
|
+
input: config.costPerMInputToken,
|
|
388
|
+
output: config.costPerMOutputToken
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Get all records (for debugging/export)
|
|
393
|
+
*/
|
|
394
|
+
getRecords() {
|
|
395
|
+
return [...this.records];
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Get record count
|
|
399
|
+
*/
|
|
400
|
+
getRecordCount() {
|
|
401
|
+
return this.records.length;
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Clear all records
|
|
405
|
+
*/
|
|
406
|
+
reset() {
|
|
407
|
+
this.records = [];
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
var costTracker = new CostTracker();
|
|
411
|
+
|
|
412
|
+
export {
|
|
413
|
+
MODEL_TIERS,
|
|
414
|
+
modelRouter,
|
|
415
|
+
CostTracker,
|
|
416
|
+
costTracker
|
|
417
|
+
};
|
|
418
|
+
//# sourceMappingURL=chunk-BMOUYXLX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/brain/router.ts","../src/core/observability/cost-tracker.ts"],"sourcesContent":["// ============================================\n// Model Router — Route messages to optimal Claude model\n// ============================================\n// Routes simple queries to Haiku (fast/cheap), standard to Sonnet,\n// and complex reasoning to Opus when enabled. Saves 60-80% cost\n// on simple queries per SkillsBench research.\n\nexport type ModelTier = \"fast\" | \"balanced\" | \"powerful\";\n\nexport interface ModelConfig {\n tier: ModelTier;\n model: string;\n provider: string; // Provider ID (e.g., \"anthropic\", \"openrouter\", \"ollama\")\n label: string;\n maxTokens: number;\n costPerMInputToken: number; // USD per million input tokens\n costPerMOutputToken: number; // USD per million output tokens\n}\n\nexport const MODEL_TIERS: Record<ModelTier, ModelConfig> = {\n fast: {\n tier: \"fast\",\n model: \"claude-haiku-4-5-20251001\",\n provider: \"anthropic\",\n label: \"Haiku 4.5\",\n maxTokens: 2048,\n costPerMInputToken: 0.80,\n costPerMOutputToken: 4.00,\n },\n balanced: {\n tier: \"balanced\",\n model: \"claude-sonnet-4-20250514\",\n provider: \"anthropic\",\n label: \"Sonnet 4\",\n maxTokens: 4096,\n costPerMInputToken: 3.00,\n costPerMOutputToken: 15.00,\n },\n powerful: {\n tier: \"powerful\",\n model: \"claude-opus-4-20250514\",\n provider: \"anthropic\",\n label: \"Opus 4\",\n maxTokens: 8192,\n costPerMInputToken: 15.00,\n costPerMOutputToken: 75.00,\n },\n};\n\n// ============================================\n// Pattern matching for complexity classification\n// ============================================\n\nconst FAST_PATTERNS: RegExp[] = [\n // Greetings and acknowledgments\n /^(hi|hello|hey|thanks|thank you|ok|okay|yes|no|sure|got it|np|ty|thx|gm|gn)\\b/i,\n // Simple questions\n /^(what time|what date|what day|how are you|who are you)\\b/i,\n // Short commands\n /^(remind me|set timer|play|pause|stop|next|skip|mute|unmute)\\b/i,\n // Status checks\n /^(status|check|ping|health|uptime)\\b/i,\n // Single-word queries\n /^\\w+[?!.]?$/i,\n];\n\nconst POWERFUL_PATTERNS: RegExp[] = [\n // Mathematical/formal reasoning\n /\\b(prove|theorem|derive|lemma|formal proof|mathematical induction)\\b/i,\n // Deep analysis\n /\\b(comprehensive analysis|in-depth|systematic review|research paper)\\b/i,\n // Complex coding tasks\n /\\b(architect|design pattern|refactor.{0,20}entire|rewrite.{0,20}from|full implementation)\\b/i,\n // Multi-step planning\n /\\b(step.by.step plan|detailed strategy|long.term plan|roadmap|proposal)\\b/i,\n // Compare/contrast\n /\\b(compare and contrast|pros and cons|trade.?offs|evaluate.{0,20}options)\\b/i,\n // Long-form writing\n /\\b(write.{0,15}essay|write.{0,15}report|write.{0,15}article|draft.{0,15}document)\\b/i,\n // Legal/medical/financial analysis\n /\\b(legal analysis|medical review|financial analysis|risk assessment)\\b/i,\n];\n\n// Tools that indicate complex tasks\nconst COMPLEX_TOOLS = new Set([\n \"execute_command\", \"write_file\", \"generate_document\",\n \"generate_spreadsheet\", \"generate_chart\", \"code_review\",\n \"spawn_agent\", \"create_workflow\", \"analyze_image\",\n]);\n\n// Tools that indicate simple tasks\nconst SIMPLE_TOOLS = new Set([\n \"get_time\", \"get_weather\", \"search_web\", \"read_file\",\n \"list_files\", \"get_system_info\", \"get_calendar_events\",\n]);\n\n// ============================================\n// ModelRouter class\n// ============================================\n\nexport interface RoutingContext {\n messageCount?: number;\n toolsRequested?: string[];\n hasHistory?: boolean;\n thinkingLevel?: string;\n appTypeTier?: \"fast\" | \"balanced\" | \"powerful\";\n}\n\nexport class ModelRouter {\n private enabled: boolean;\n private defaultTier: ModelTier;\n private opusEnabled: boolean;\n\n // Routing statistics\n private stats = { fast: 0, balanced: 0, powerful: 0 };\n\n constructor(options?: {\n enabled?: boolean;\n defaultTier?: ModelTier;\n opusEnabled?: boolean;\n }) {\n this.enabled = options?.enabled ?? true;\n this.defaultTier = options?.defaultTier ?? \"balanced\";\n this.opusEnabled = options?.opusEnabled ?? false;\n }\n\n /**\n * Analyze message complexity and return recommended model config\n */\n routeMessage(message: string, context?: RoutingContext): ModelConfig {\n if (!this.enabled) {\n this.stats[this.defaultTier]++;\n return MODEL_TIERS[this.defaultTier];\n }\n\n const tier = this.classifyComplexity(message, context);\n this.stats[tier]++;\n return MODEL_TIERS[tier];\n }\n\n /**\n * Classify message complexity into a model tier\n */\n classifyComplexity(message: string, context?: RoutingContext): ModelTier {\n // If thinking level explicitly set to extended, use powerful when available\n if (context?.thinkingLevel === \"extended\" && this.opusEnabled) {\n return \"powerful\";\n }\n\n const trimmed = message.trim();\n\n // Very short messages are usually simple\n if (trimmed.length < 15) {\n return \"fast\";\n }\n\n // Check for fast patterns\n for (const pattern of FAST_PATTERNS) {\n if (pattern.test(trimmed)) {\n return \"fast\";\n }\n }\n\n // Check for powerful patterns (only if Opus is enabled)\n if (this.opusEnabled) {\n for (const pattern of POWERFUL_PATTERNS) {\n if (pattern.test(trimmed)) {\n return \"powerful\";\n }\n }\n }\n\n // Tool-based complexity analysis\n if (context?.toolsRequested) {\n const hasComplexTools = context.toolsRequested.some(t => COMPLEX_TOOLS.has(t));\n const hasOnlySimpleTools = context.toolsRequested.every(t => SIMPLE_TOOLS.has(t));\n\n if (hasComplexTools && this.opusEnabled) {\n return \"powerful\";\n }\n if (hasOnlySimpleTools && context.toolsRequested.length <= 2) {\n return \"fast\";\n }\n }\n\n // Word count heuristic — short messages can use Haiku\n const wordCount = trimmed.split(/\\s+/).length;\n if (wordCount < 8) {\n return \"fast\";\n }\n\n // Message length heuristic — very long messages suggest complexity\n if (trimmed.length > 500 && this.opusEnabled) {\n return \"powerful\";\n }\n\n // Enforce app-type minimum tier\n const result = this.defaultTier;\n if (context?.appTypeTier) {\n const tierOrder: Record<string, number> = { fast: 0, balanced: 1, powerful: 2 };\n if (tierOrder[context.appTypeTier] > tierOrder[result]) {\n return context.appTypeTier;\n }\n }\n\n // Default to balanced\n return result;\n }\n\n /**\n * Estimate cost for a given tier and token counts\n */\n estimateCost(tier: ModelTier, inputTokens: number, outputTokens: number): number {\n const config = MODEL_TIERS[tier];\n return (inputTokens / 1_000_000) * config.costPerMInputToken +\n (outputTokens / 1_000_000) * config.costPerMOutputToken;\n }\n\n /**\n * Get info about a model tier\n */\n getTierInfo(tier: ModelTier): ModelConfig {\n return MODEL_TIERS[tier];\n }\n\n /**\n * Get routing statistics\n */\n getStats(): { fast: number; balanced: number; powerful: number; total: number } {\n const total = this.stats.fast + this.stats.balanced + this.stats.powerful;\n return { ...this.stats, total };\n }\n\n /**\n * Reset routing statistics\n */\n resetStats(): void {\n this.stats = { fast: 0, balanced: 0, powerful: 0 };\n }\n\n /**\n * Get estimated cost savings vs always using balanced\n */\n getEstimatedSavings(avgInputTokens = 1000, avgOutputTokens = 500): {\n withRouting: number;\n withoutRouting: number;\n savings: number;\n savingsPercent: number;\n } {\n const stats = this.getStats();\n if (stats.total === 0) return { withRouting: 0, withoutRouting: 0, savings: 0, savingsPercent: 0 };\n\n const withRouting =\n this.estimateCost(\"fast\", avgInputTokens * stats.fast, avgOutputTokens * stats.fast) +\n this.estimateCost(\"balanced\", avgInputTokens * stats.balanced, avgOutputTokens * stats.balanced) +\n this.estimateCost(\"powerful\", avgInputTokens * stats.powerful, avgOutputTokens * stats.powerful);\n\n const withoutRouting = this.estimateCost(\"balanced\", avgInputTokens * stats.total, avgOutputTokens * stats.total);\n\n const savings = withoutRouting - withRouting;\n const savingsPercent = withoutRouting > 0 ? (savings / withoutRouting) * 100 : 0;\n\n return { withRouting, withoutRouting, savings, savingsPercent };\n }\n\n isEnabled(): boolean { return this.enabled; }\n setEnabled(enabled: boolean): void { this.enabled = enabled; }\n isOpusEnabled(): boolean { return this.opusEnabled; }\n setOpusEnabled(enabled: boolean): void { this.opusEnabled = enabled; }\n}\n\n// Singleton\nexport const modelRouter = new ModelRouter();\n","/**\r\n * Cost Tracker — Multi-model token cost tracking\r\n *\r\n * Tracks per-request token costs using MODEL_TIERS pricing from brain/router.ts.\r\n * Uses Linear Regression (Algorithm #1) for cost forecasting instead of naive projection.\r\n */\r\n\r\nimport { MODEL_TIERS, type ModelTier } from \"../brain/router\";\r\nimport { LinearRegression } from \"../ml/linear-regression\";\r\n\r\nexport interface CostRecord {\r\n tier: string;\r\n inputTokens: number;\r\n outputTokens: number;\r\n cost: number;\r\n timestamp: number;\r\n}\r\n\r\nexport interface CostSummary {\r\n totalCost: number;\r\n costByTier: Record<string, number>;\r\n totalInputTokens: number;\r\n totalOutputTokens: number;\r\n requestCount: number;\r\n timeRange: { start: number; end: number };\r\n}\r\n\r\nexport class CostTracker {\r\n private records: CostRecord[] = [];\r\n private maxRecords = 10000; // Keep last 10K records in memory\r\n private dbLoaded = false;\r\n\r\n /**\r\n * Load historical cost records from the database on startup\r\n */\r\n async loadFromDb(): Promise<void> {\r\n if (this.dbLoaded) return;\r\n try {\r\n const { db } = await import(\"../../db\");\r\n const { metrics } = await import(\"../../db/schema\");\r\n const { eq, desc } = await import(\"drizzle-orm\");\r\n const rows = await db\r\n .select()\r\n .from(metrics)\r\n .where(eq(metrics.name, \"token_cost\"))\r\n .orderBy(desc(metrics.timestamp))\r\n .limit(this.maxRecords);\r\n\r\n for (const row of rows.reverse()) {\r\n const tags = (row.tags || {}) as Record<string, string>;\r\n this.records.push({\r\n tier: tags.tier || \"balanced\",\r\n inputTokens: parseInt(tags.inputTokens || \"0\"),\r\n outputTokens: parseInt(tags.outputTokens || \"0\"),\r\n cost: (row.value || 0) / 1_000_000, // stored as micro-dollars\r\n timestamp: new Date(row.timestamp).getTime(),\r\n });\r\n }\r\n this.dbLoaded = true;\r\n if (this.records.length > 0) {\r\n console.log(`[CostTracker] Loaded ${this.records.length} historical records from DB`);\r\n }\r\n } catch {\r\n // DB may not be available yet\r\n }\r\n }\r\n\r\n /**\r\n * Record token usage for a request\r\n */\r\n recordUsage(tier: string, inputTokens: number, outputTokens: number): CostRecord {\r\n const tierConfig = MODEL_TIERS[tier as ModelTier] || MODEL_TIERS.balanced;\r\n\r\n const inputCost = (inputTokens / 1_000_000) * tierConfig.costPerMInputToken;\r\n const outputCost = (outputTokens / 1_000_000) * tierConfig.costPerMOutputToken;\r\n const totalCost = inputCost + outputCost;\r\n\r\n const record: CostRecord = {\r\n tier,\r\n inputTokens,\r\n outputTokens,\r\n cost: totalCost,\r\n timestamp: Date.now(),\r\n };\r\n\r\n this.records.push(record);\r\n\r\n // Trim old records\r\n if (this.records.length > this.maxRecords) {\r\n this.records = this.records.slice(-this.maxRecords);\r\n }\r\n\r\n // Persist to database (fire-and-forget)\r\n this.persistRecord(record).catch(() => {});\r\n\r\n return record;\r\n }\r\n\r\n private async persistRecord(record: CostRecord): Promise<void> {\r\n try {\r\n const { db } = await import(\"../../db\");\r\n const { metrics } = await import(\"../../db/schema\");\r\n await db.insert(metrics).values({\r\n name: \"token_cost\",\r\n value: Math.round(record.cost * 1_000_000), // store as micro-dollars for integer precision\r\n unit: \"microdollars\",\r\n tags: {\r\n tier: record.tier,\r\n inputTokens: String(record.inputTokens),\r\n outputTokens: String(record.outputTokens),\r\n },\r\n });\r\n } catch {\r\n // Silently fail — in-memory still works\r\n }\r\n }\r\n\r\n /**\r\n * Get cost summary for a time range\r\n */\r\n getCostSummary(since?: number, until?: number): CostSummary {\r\n const start = since || 0;\r\n const end = until || Date.now();\r\n\r\n const filtered = this.records.filter(\r\n (r) => r.timestamp >= start && r.timestamp <= end\r\n );\r\n\r\n const costByTier: Record<string, number> = {};\r\n let totalCost = 0;\r\n let totalInputTokens = 0;\r\n let totalOutputTokens = 0;\r\n\r\n for (const record of filtered) {\r\n totalCost += record.cost;\r\n totalInputTokens += record.inputTokens;\r\n totalOutputTokens += record.outputTokens;\r\n costByTier[record.tier] = (costByTier[record.tier] || 0) + record.cost;\r\n }\r\n\r\n return {\r\n totalCost,\r\n costByTier,\r\n totalInputTokens,\r\n totalOutputTokens,\r\n requestCount: filtered.length,\r\n timeRange: { start, end },\r\n };\r\n }\r\n\r\n /**\r\n * Get average cost per interaction\r\n */\r\n getCostPerInteraction(): number {\r\n if (this.records.length === 0) return 0;\r\n const total = this.records.reduce((sum, r) => sum + r.cost, 0);\r\n return total / this.records.length;\r\n }\r\n\r\n /**\r\n * Get estimated monthly cost using Linear Regression forecasting.\r\n * Fits a regression on daily cost totals from the last 14 days, then projects 30 days.\r\n */\r\n getEstimatedMonthlyCost(): number {\r\n if (this.records.length < 2) return 0;\r\n\r\n const now = Date.now();\r\n const dailyCosts = this.getDailyCostHistory(14);\r\n\r\n if (dailyCosts.length < 2) {\r\n // Fallback: simple projection if not enough daily data\r\n const oneDayAgo = now - 86400000;\r\n const recentRecords = this.records.filter((r) => r.timestamp >= oneDayAgo);\r\n if (recentRecords.length === 0) return 0;\r\n const dailyCost = recentRecords.reduce((sum, r) => sum + r.cost, 0);\r\n return dailyCost * 30;\r\n }\r\n\r\n // Use Linear Regression to forecast the next 30 days\r\n const predictions = LinearRegression.forecast(dailyCosts, 30);\r\n // Sum all predicted daily costs (clamped to 0 — cost can't go negative)\r\n return predictions.reduce((sum, p) => sum + Math.max(0, p.value), 0);\r\n }\r\n\r\n /**\r\n * Detect spending trend: up, down, or flat.\r\n */\r\n getCostTrend(): { direction: \"up\" | \"down\" | \"flat\"; strength: number; dailyChange: number } {\r\n const dailyCosts = this.getDailyCostHistory(14);\r\n if (dailyCosts.length < 3) {\r\n return { direction: \"flat\", strength: 0, dailyChange: 0 };\r\n }\r\n const trend = LinearRegression.detectTrend(dailyCosts);\r\n return {\r\n direction: trend.direction,\r\n strength: trend.strength,\r\n dailyChange: trend.slopePerUnit,\r\n };\r\n }\r\n\r\n /**\r\n * Get forecast with confidence intervals for the next N days.\r\n */\r\n getForecast(daysAhead: number = 7): Array<{ day: number; predicted: number; lower: number; upper: number }> {\r\n const dailyCosts = this.getDailyCostHistory(14);\r\n if (dailyCosts.length < 2) return [];\r\n\r\n const predictions = LinearRegression.forecast(dailyCosts, daysAhead);\r\n return predictions.map((p, i) => ({\r\n day: i + 1,\r\n predicted: Math.max(0, p.value),\r\n lower: Math.max(0, p.lower95),\r\n upper: Math.max(0, p.upper95),\r\n }));\r\n }\r\n\r\n /**\r\n * Get daily cost totals for the last N days.\r\n */\r\n private getDailyCostHistory(days: number): number[] {\r\n const now = Date.now();\r\n const msPerDay = 86400000;\r\n const dailyCosts: number[] = [];\r\n\r\n for (let d = days - 1; d >= 0; d--) {\r\n const dayStart = now - (d + 1) * msPerDay;\r\n const dayEnd = now - d * msPerDay;\r\n const dayCost = this.records\r\n .filter((r) => r.timestamp >= dayStart && r.timestamp < dayEnd)\r\n .reduce((sum, r) => sum + r.cost, 0);\r\n dailyCosts.push(dayCost);\r\n }\r\n\r\n return dailyCosts;\r\n }\r\n\r\n /**\r\n * Get cost per million tokens for a tier\r\n */\r\n getCostPerMillionTokens(tier: string): { input: number; output: number } {\r\n const config = MODEL_TIERS[tier as ModelTier] || MODEL_TIERS.balanced;\r\n return {\r\n input: config.costPerMInputToken,\r\n output: config.costPerMOutputToken,\r\n };\r\n }\r\n\r\n /**\r\n * Get all records (for debugging/export)\r\n */\r\n getRecords(): CostRecord[] {\r\n return [...this.records];\r\n }\r\n\r\n /**\r\n * Get record count\r\n */\r\n getRecordCount(): number {\r\n return this.records.length;\r\n }\r\n\r\n /**\r\n * Clear all records\r\n */\r\n reset(): void {\r\n this.records = [];\r\n }\r\n}\r\n\r\nexport const costTracker = new CostTracker();\r\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__esm,
|
|
3
|
+
__export
|
|
4
|
+
} from "./chunk-UP2VWCW5.js";
|
|
5
|
+
|
|
6
|
+
// src/integrations/notion/client.ts
|
|
7
|
+
var client_exports = {};
|
|
8
|
+
__export(client_exports, {
|
|
9
|
+
Client: () => Client,
|
|
10
|
+
getNotionClient: () => getNotionClient,
|
|
11
|
+
getRootPageId: () => getRootPageId,
|
|
12
|
+
initNotionClient: () => initNotionClient,
|
|
13
|
+
isNotionInitialized: () => isNotionInitialized,
|
|
14
|
+
resetNotionClient: () => resetNotionClient
|
|
15
|
+
});
|
|
16
|
+
import { Client } from "@notionhq/client";
|
|
17
|
+
function initNotionClient(config) {
|
|
18
|
+
notionClient = new Client({
|
|
19
|
+
auth: config.apiKey
|
|
20
|
+
});
|
|
21
|
+
rootPageId = config.rootPageId || null;
|
|
22
|
+
return notionClient;
|
|
23
|
+
}
|
|
24
|
+
function getNotionClient() {
|
|
25
|
+
if (!notionClient) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
"Notion client not initialized. Call initNotionClient() first."
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
return notionClient;
|
|
31
|
+
}
|
|
32
|
+
function getRootPageId() {
|
|
33
|
+
return rootPageId;
|
|
34
|
+
}
|
|
35
|
+
function isNotionInitialized() {
|
|
36
|
+
return notionClient !== null;
|
|
37
|
+
}
|
|
38
|
+
function resetNotionClient() {
|
|
39
|
+
notionClient = null;
|
|
40
|
+
rootPageId = null;
|
|
41
|
+
}
|
|
42
|
+
var notionClient, rootPageId;
|
|
43
|
+
var init_client = __esm({
|
|
44
|
+
"src/integrations/notion/client.ts"() {
|
|
45
|
+
notionClient = null;
|
|
46
|
+
rootPageId = null;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
export {
|
|
51
|
+
Client,
|
|
52
|
+
initNotionClient,
|
|
53
|
+
getNotionClient,
|
|
54
|
+
getRootPageId,
|
|
55
|
+
isNotionInitialized,
|
|
56
|
+
resetNotionClient,
|
|
57
|
+
client_exports,
|
|
58
|
+
init_client
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=chunk-C6PELIHS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/integrations/notion/client.ts"],"sourcesContent":["import { Client } from \"@notionhq/client\";\n\n/**\n * Notion API client wrapper\n * Provides authenticated access to Notion API\n */\n\nexport interface NotionClientConfig {\n apiKey: string;\n rootPageId?: string;\n}\n\nlet notionClient: Client | null = null;\nlet rootPageId: string | null = null;\n\n/**\n * Initialize the Notion client with API key\n */\nexport function initNotionClient(config: NotionClientConfig): Client {\n notionClient = new Client({\n auth: config.apiKey,\n });\n rootPageId = config.rootPageId || null;\n return notionClient;\n}\n\n/**\n * Get the initialized Notion client\n * @throws Error if client is not initialized\n */\nexport function getNotionClient(): Client {\n if (!notionClient) {\n throw new Error(\n \"Notion client not initialized. Call initNotionClient() first.\"\n );\n }\n return notionClient;\n}\n\n/**\n * Get the configured root page ID\n */\nexport function getRootPageId(): string | null {\n return rootPageId;\n}\n\n/**\n * Check if Notion client is initialized\n */\nexport function isNotionInitialized(): boolean {\n return notionClient !== null;\n}\n\n/**\n * Reset the Notion client (useful for testing)\n */\nexport function resetNotionClient(): void {\n notionClient = null;\n rootPageId = null;\n}\n\nexport { Client };\n"],"mappings":";;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAS,cAAc;AAkBhB,SAAS,iBAAiB,QAAoC;AACnE,iBAAe,IAAI,OAAO;AAAA,IACxB,MAAM,OAAO;AAAA,EACf,CAAC;AACD,eAAa,OAAO,cAAc;AAClC,SAAO;AACT;AAMO,SAAS,kBAA0B;AACxC,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,gBAA+B;AAC7C,SAAO;AACT;AAKO,SAAS,sBAA+B;AAC7C,SAAO,iBAAiB;AAC1B;AAKO,SAAS,oBAA0B;AACxC,iBAAe;AACf,eAAa;AACf;AA3DA,IAYI,cACA;AAbJ;AAAA;AAYA,IAAI,eAA8B;AAClC,IAAI,aAA4B;AAAA;AAAA;","names":[]}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createBlockObject,
|
|
3
3
|
markdownToBlocks
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2WTKTG2C.js";
|
|
5
5
|
import {
|
|
6
6
|
getNotionClient,
|
|
7
7
|
getRootPageId,
|
|
8
8
|
init_client
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-C6PELIHS.js";
|
|
10
10
|
|
|
11
11
|
// src/integrations/notion/pages.ts
|
|
12
12
|
init_client();
|
|
@@ -225,4 +225,4 @@ export {
|
|
|
225
225
|
appendToPage,
|
|
226
226
|
replacePageContent
|
|
227
227
|
};
|
|
228
|
-
//# sourceMappingURL=chunk-
|
|
228
|
+
//# sourceMappingURL=chunk-CUPEENUY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tools/file-generation/pdf.ts"],"sourcesContent":["import { createWriteStream } from \"fs\";\r\nimport { mkdir } from \"fs/promises\";\r\nimport { dirname, join } from \"path\";\r\nimport { tmpdir } from \"os\";\r\nimport { randomBytes } from \"crypto\";\r\nimport { isPathAllowed } from \"../../utils/paths\";\r\n\r\nexport interface PDFOptions {\r\n title?: string;\r\n author?: string;\r\n format?: \"A4\" | \"Letter\" | \"Legal\";\r\n orientation?: \"portrait\" | \"landscape\";\r\n margins?: {\r\n top: number;\r\n bottom: number;\r\n left: number;\r\n right: number;\r\n };\r\n}\r\n\r\nexport interface PDFGenerationResult {\r\n success: boolean;\r\n filePath?: string;\r\n error?: string;\r\n}\r\n\r\nconst DEFAULT_OPTIONS: PDFOptions = {\r\n format: \"A4\",\r\n orientation: \"portrait\",\r\n margins: { top: 72, bottom: 72, left: 72, right: 72 },\r\n};\r\n\r\n// Generate temp file path\r\nfunction getTempPath(): string {\r\n const id = randomBytes(8).toString(\"hex\");\r\n return join(tmpdir(), `sentinel-doc-${id}.pdf`);\r\n}\r\n\r\n// Simple markdown to text conversion (for basic PDF)\r\nfunction markdownToText(markdown: string): string {\r\n return markdown\r\n // Remove code blocks\r\n .replace(/```[\\s\\S]*?```/g, (match) => {\r\n const code = match.replace(/```\\w*\\n?/g, \"\").trim();\r\n return `\\n${code}\\n`;\r\n })\r\n // Remove inline code\r\n .replace(/`([^`]+)`/g, \"$1\")\r\n // Convert headers\r\n .replace(/^### (.+)$/gm, \"\\n$1\\n\" + \"-\".repeat(30))\r\n .replace(/^## (.+)$/gm, \"\\n$1\\n\" + \"=\".repeat(40))\r\n .replace(/^# (.+)$/gm, \"\\n$1\\n\" + \"=\".repeat(50))\r\n // Convert bold/italic\r\n .replace(/\\*\\*([^*]+)\\*\\*/g, \"$1\")\r\n .replace(/\\*([^*]+)\\*/g, \"$1\")\r\n .replace(/__([^_]+)__/g, \"$1\")\r\n .replace(/_([^_]+)_/g, \"$1\")\r\n // Convert links\r\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, \"$1\")\r\n // Convert lists\r\n .replace(/^[-*] /gm, \"• \")\r\n .replace(/^\\d+\\. /gm, \" \")\r\n // Clean up\r\n .replace(/\\n{3,}/g, \"\\n\\n\");\r\n}\r\n\r\n// Generate PDF natively using PDFKit (no browser needed)\r\nexport async function generatePDFNative(\r\n content: string,\r\n outputPath?: string,\r\n options: PDFOptions = {}\r\n): Promise<PDFGenerationResult> {\r\n const finalOptions = { ...DEFAULT_OPTIONS, ...options };\r\n const filePath = outputPath || getTempPath();\r\n\r\n if (outputPath && !isPathAllowed(outputPath)) {\r\n return { success: false, error: \"Access to this path is not allowed\" };\r\n }\r\n\r\n try {\r\n await mkdir(dirname(filePath), { recursive: true });\r\n\r\n // @ts-expect-error pdfkit has no type declarations\r\n const PDFDocument = (await import(\"pdfkit\")).default;\r\n const doc = new PDFDocument({\r\n size: finalOptions.format || \"A4\",\r\n layout: finalOptions.orientation || \"portrait\",\r\n margins: finalOptions.margins || { top: 72, bottom: 72, left: 72, right: 72 },\r\n info: {\r\n Title: finalOptions.title || \"Document\",\r\n Author: finalOptions.author || \"OpenSentinel\",\r\n },\r\n });\r\n\r\n const stream = createWriteStream(filePath);\r\n doc.pipe(stream);\r\n\r\n // Parse markdown-like content into PDF sections\r\n const lines = content.split(\"\\n\");\r\n for (const line of lines) {\r\n if (line.startsWith(\"# \")) {\r\n doc.fontSize(24).font(\"Helvetica-Bold\").text(line.slice(2), { align: \"left\" });\r\n doc.moveDown(0.5);\r\n } else if (line.startsWith(\"## \")) {\r\n doc.fontSize(18).font(\"Helvetica-Bold\").text(line.slice(3), { align: \"left\" });\r\n doc.moveDown(0.3);\r\n } else if (line.startsWith(\"### \")) {\r\n doc.fontSize(14).font(\"Helvetica-Bold\").text(line.slice(4), { align: \"left\" });\r\n doc.moveDown(0.2);\r\n } else if (line.startsWith(\"- \") || line.startsWith(\"* \")) {\r\n doc.fontSize(12).font(\"Helvetica\").text(` \\u2022 ${line.slice(2)}`, { indent: 20 });\r\n } else if (line.trim() === \"\") {\r\n doc.moveDown(0.5);\r\n } else {\r\n doc.fontSize(12).font(\"Helvetica\").text(line, { align: \"left\" });\r\n }\r\n }\r\n\r\n doc.end();\r\n await new Promise<void>((resolve, reject) => {\r\n stream.on(\"finish\", resolve);\r\n stream.on(\"error\", reject);\r\n });\r\n\r\n return { success: true, filePath };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : String(error),\r\n };\r\n }\r\n}\r\n\r\n// Generate PDF from markdown content using PDFKit\r\nexport async function generatePDFFromMarkdown(\r\n markdown: string,\r\n outputPath?: string,\r\n options: PDFOptions = {}\r\n): Promise<PDFGenerationResult> {\r\n // Use native PDFKit implementation\r\n return generatePDFNative(markdown, outputPath, options);\r\n}\r\n\r\n// Generate PDF from HTML (requires browser/puppeteer)\r\nexport async function generatePDFFromHTML(\r\n html: string,\r\n outputPath?: string,\r\n options: PDFOptions = {}\r\n): Promise<PDFGenerationResult> {\r\n const filePath = outputPath || getTempPath();\r\n\r\n // Security check\r\n if (outputPath && !isPathAllowed(outputPath)) {\r\n return {\r\n success: false,\r\n error: \"Access to this path is not allowed\",\r\n };\r\n }\r\n\r\n try {\r\n // Ensure directory exists\r\n await mkdir(dirname(filePath), { recursive: true });\r\n\r\n // Try to use Playwright if available\r\n try {\r\n const { chromium } = await import(\"playwright\");\r\n const browser = await chromium.launch({ headless: true });\r\n const page = await browser.newPage();\r\n\r\n await page.setContent(html, { waitUntil: \"networkidle\" });\r\n\r\n await page.pdf({\r\n path: filePath,\r\n format: options.format || \"A4\",\r\n landscape: options.orientation === \"landscape\",\r\n margin: options.margins\r\n ? {\r\n top: `${options.margins.top}px`,\r\n bottom: `${options.margins.bottom}px`,\r\n left: `${options.margins.left}px`,\r\n right: `${options.margins.right}px`,\r\n }\r\n : undefined,\r\n });\r\n\r\n await browser.close();\r\n\r\n return { success: true, filePath };\r\n } catch {\r\n // Fallback: save as HTML\r\n const { writeFile } = await import(\"fs/promises\");\r\n const htmlPath = filePath.replace(\".pdf\", \".html\");\r\n await writeFile(htmlPath, html, \"utf-8\");\r\n\r\n return {\r\n success: true,\r\n filePath: htmlPath,\r\n };\r\n }\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : String(error),\r\n };\r\n }\r\n}\r\n\r\n// Main function for tool use\r\nexport async function generatePDF(\r\n content: string,\r\n filename: string,\r\n options?: PDFOptions & { contentType?: \"markdown\" | \"html\" }\r\n): Promise<PDFGenerationResult> {\r\n const outputPath = isPathAllowed(filename) ? filename : join(tmpdir(), filename);\r\n const contentType = options?.contentType || \"markdown\";\r\n\r\n if (contentType === \"html\") {\r\n return generatePDFFromHTML(content, outputPath, options);\r\n }\r\n\r\n return generatePDFFromMarkdown(content, outputPath, options);\r\n}\r\n\r\nexport default {\r\n generatePDF,\r\n generatePDFNative,\r\n generatePDFFromMarkdown,\r\n generatePDFFromHTML,\r\n};\r\n"],"mappings":"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","names":[]}
|