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
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
// src/integrations/documents/docx-parser.ts
|
|
2
|
+
import mammoth from "mammoth";
|
|
3
|
+
import * as fs from "fs/promises";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
async function parseDOCX(input, options = {}) {
|
|
6
|
+
let buffer;
|
|
7
|
+
if (typeof input === "string") {
|
|
8
|
+
const absolutePath = path.isAbsolute(input) ? input : path.resolve(input);
|
|
9
|
+
buffer = await fs.readFile(absolutePath);
|
|
10
|
+
} else {
|
|
11
|
+
buffer = input;
|
|
12
|
+
}
|
|
13
|
+
const mammothOptions = {};
|
|
14
|
+
if (options.styleMap && options.styleMap.length > 0) {
|
|
15
|
+
mammothOptions.styleMap = options.styleMap;
|
|
16
|
+
}
|
|
17
|
+
if (options.includeImages) {
|
|
18
|
+
mammothOptions.convertImage = mammoth.images.imgElement((image) => {
|
|
19
|
+
return image.read("base64").then((imageBuffer) => {
|
|
20
|
+
return {
|
|
21
|
+
src: `data:${image.contentType};base64,${imageBuffer}`
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
const htmlResult = await mammoth.convertToHtml(
|
|
27
|
+
{ buffer },
|
|
28
|
+
mammothOptions
|
|
29
|
+
);
|
|
30
|
+
const textResult = await mammoth.extractRawText({ buffer });
|
|
31
|
+
let markdown = "";
|
|
32
|
+
if (options.outputMarkdown) {
|
|
33
|
+
markdown = htmlToMarkdown(htmlResult.value);
|
|
34
|
+
}
|
|
35
|
+
const text = textResult.value;
|
|
36
|
+
const wordCount = text.split(/\s+/).filter((word) => word.length > 0).length;
|
|
37
|
+
const characterCount = text.length;
|
|
38
|
+
const paragraphCount = text.split(/\n\n+/).filter((p) => p.trim().length > 0).length;
|
|
39
|
+
const messages = htmlResult.messages.map((msg) => ({
|
|
40
|
+
type: msg.type,
|
|
41
|
+
message: msg.message,
|
|
42
|
+
paragraphIndex: msg.paragraphIndex
|
|
43
|
+
}));
|
|
44
|
+
return {
|
|
45
|
+
text: textResult.value,
|
|
46
|
+
html: htmlResult.value,
|
|
47
|
+
markdown: markdown || htmlToMarkdown(htmlResult.value),
|
|
48
|
+
messages,
|
|
49
|
+
metadata: {
|
|
50
|
+
wordCount,
|
|
51
|
+
characterCount,
|
|
52
|
+
paragraphCount
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function htmlToMarkdown(html) {
|
|
57
|
+
let markdown = html;
|
|
58
|
+
markdown = markdown.replace(/<h1[^>]*>(.*?)<\/h1>/gi, "# $1\n\n");
|
|
59
|
+
markdown = markdown.replace(/<h2[^>]*>(.*?)<\/h2>/gi, "## $1\n\n");
|
|
60
|
+
markdown = markdown.replace(/<h3[^>]*>(.*?)<\/h3>/gi, "### $1\n\n");
|
|
61
|
+
markdown = markdown.replace(/<h4[^>]*>(.*?)<\/h4>/gi, "#### $1\n\n");
|
|
62
|
+
markdown = markdown.replace(/<h5[^>]*>(.*?)<\/h5>/gi, "##### $1\n\n");
|
|
63
|
+
markdown = markdown.replace(/<h6[^>]*>(.*?)<\/h6>/gi, "###### $1\n\n");
|
|
64
|
+
markdown = markdown.replace(/<strong[^>]*>(.*?)<\/strong>/gi, "**$1**");
|
|
65
|
+
markdown = markdown.replace(/<b[^>]*>(.*?)<\/b>/gi, "**$1**");
|
|
66
|
+
markdown = markdown.replace(/<em[^>]*>(.*?)<\/em>/gi, "*$1*");
|
|
67
|
+
markdown = markdown.replace(/<i[^>]*>(.*?)<\/i>/gi, "*$1*");
|
|
68
|
+
markdown = markdown.replace(
|
|
69
|
+
/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/gi,
|
|
70
|
+
"[$2]($1)"
|
|
71
|
+
);
|
|
72
|
+
markdown = markdown.replace(
|
|
73
|
+
/<img[^>]*src="([^"]*)"[^>]*alt="([^"]*)"[^>]*\/?>/gi,
|
|
74
|
+
""
|
|
75
|
+
);
|
|
76
|
+
markdown = markdown.replace(
|
|
77
|
+
/<img[^>]*src="([^"]*)"[^>]*\/?>/gi,
|
|
78
|
+
""
|
|
79
|
+
);
|
|
80
|
+
markdown = markdown.replace(/<ul[^>]*>/gi, "\n");
|
|
81
|
+
markdown = markdown.replace(/<\/ul>/gi, "\n");
|
|
82
|
+
markdown = markdown.replace(/<ol[^>]*>/gi, "\n");
|
|
83
|
+
markdown = markdown.replace(/<\/ol>/gi, "\n");
|
|
84
|
+
markdown = markdown.replace(/<li[^>]*>(.*?)<\/li>/gi, "- $1\n");
|
|
85
|
+
markdown = markdown.replace(/<p[^>]*>(.*?)<\/p>/gi, "$1\n\n");
|
|
86
|
+
markdown = markdown.replace(/<br[^>]*\/?>/gi, "\n");
|
|
87
|
+
markdown = markdown.replace(/<code[^>]*>(.*?)<\/code>/gi, "`$1`");
|
|
88
|
+
markdown = markdown.replace(/<pre[^>]*>(.*?)<\/pre>/gis, "```\n$1\n```\n");
|
|
89
|
+
markdown = markdown.replace(
|
|
90
|
+
/<blockquote[^>]*>(.*?)<\/blockquote>/gis,
|
|
91
|
+
(match, content) => {
|
|
92
|
+
return content.split("\n").map((line) => `> ${line}`).join("\n");
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
markdown = markdown.replace(/<table[^>]*>/gi, "\n");
|
|
96
|
+
markdown = markdown.replace(/<\/table>/gi, "\n");
|
|
97
|
+
markdown = markdown.replace(/<tr[^>]*>/gi, "");
|
|
98
|
+
markdown = markdown.replace(/<\/tr>/gi, "|\n");
|
|
99
|
+
markdown = markdown.replace(/<th[^>]*>(.*?)<\/th>/gi, "| **$1** ");
|
|
100
|
+
markdown = markdown.replace(/<td[^>]*>(.*?)<\/td>/gi, "| $1 ");
|
|
101
|
+
markdown = markdown.replace(/<hr[^>]*\/?>/gi, "\n---\n");
|
|
102
|
+
markdown = markdown.replace(/<[^>]+>/g, "");
|
|
103
|
+
markdown = decodeHtmlEntities(markdown);
|
|
104
|
+
markdown = markdown.replace(/\n{3,}/g, "\n\n");
|
|
105
|
+
markdown = markdown.trim();
|
|
106
|
+
return markdown;
|
|
107
|
+
}
|
|
108
|
+
function decodeHtmlEntities(text) {
|
|
109
|
+
const entities = {
|
|
110
|
+
"&": "&",
|
|
111
|
+
"<": "<",
|
|
112
|
+
">": ">",
|
|
113
|
+
""": '"',
|
|
114
|
+
"'": "'",
|
|
115
|
+
"'": "'",
|
|
116
|
+
" ": " ",
|
|
117
|
+
"–": "-",
|
|
118
|
+
"—": "--",
|
|
119
|
+
"‘": "'",
|
|
120
|
+
"’": "'",
|
|
121
|
+
"“": '"',
|
|
122
|
+
"”": '"',
|
|
123
|
+
"…": "...",
|
|
124
|
+
"©": "(c)",
|
|
125
|
+
"®": "(R)",
|
|
126
|
+
"™": "(TM)"
|
|
127
|
+
};
|
|
128
|
+
let result = text;
|
|
129
|
+
for (const [entity, char] of Object.entries(entities)) {
|
|
130
|
+
result = result.replace(new RegExp(entity, "g"), char);
|
|
131
|
+
}
|
|
132
|
+
result = result.replace(
|
|
133
|
+
/&#(\d+);/g,
|
|
134
|
+
(match, dec) => String.fromCharCode(parseInt(dec, 10))
|
|
135
|
+
);
|
|
136
|
+
result = result.replace(
|
|
137
|
+
/&#x([0-9a-fA-F]+);/g,
|
|
138
|
+
(match, hex) => String.fromCharCode(parseInt(hex, 16))
|
|
139
|
+
);
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
async function extractDOCXText(input) {
|
|
143
|
+
const result = await parseDOCX(input);
|
|
144
|
+
return result.text;
|
|
145
|
+
}
|
|
146
|
+
async function extractDOCXMarkdown(input) {
|
|
147
|
+
const result = await parseDOCX(input, { outputMarkdown: true });
|
|
148
|
+
return result.markdown;
|
|
149
|
+
}
|
|
150
|
+
async function isValidDOCX(input) {
|
|
151
|
+
try {
|
|
152
|
+
let buffer;
|
|
153
|
+
if (typeof input === "string") {
|
|
154
|
+
const absolutePath = path.isAbsolute(input) ? input : path.resolve(input);
|
|
155
|
+
buffer = await fs.readFile(absolutePath);
|
|
156
|
+
} else {
|
|
157
|
+
buffer = input;
|
|
158
|
+
}
|
|
159
|
+
const header = buffer.slice(0, 4);
|
|
160
|
+
if (header[0] !== 80 || header[1] !== 75) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
await mammoth.extractRawText({ buffer });
|
|
164
|
+
return true;
|
|
165
|
+
} catch {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async function getDOCXStats(input) {
|
|
170
|
+
const result = await parseDOCX(input);
|
|
171
|
+
return result.metadata;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export {
|
|
175
|
+
parseDOCX,
|
|
176
|
+
extractDOCXText,
|
|
177
|
+
extractDOCXMarkdown,
|
|
178
|
+
isValidDOCX,
|
|
179
|
+
getDOCXStats
|
|
180
|
+
};
|
|
181
|
+
//# sourceMappingURL=chunk-6W6PTJFT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/integrations/documents/docx-parser.ts"],"sourcesContent":["/**\r\n * DOCX Parser for OpenSentinel Document Ingestion\r\n *\r\n * Extracts text content from Word documents using mammoth.\r\n */\r\n\r\nimport mammoth from \"mammoth\";\r\nimport * as fs from \"fs/promises\";\r\nimport * as path from \"path\";\r\n\r\nexport interface DOCXParseResult {\r\n text: string;\r\n html: string;\r\n markdown: string;\r\n messages: DOCXMessage[];\r\n metadata: DOCXMetadata;\r\n}\r\n\r\nexport interface DOCXMessage {\r\n type: \"warning\" | \"error\";\r\n message: string;\r\n paragraphIndex?: number;\r\n}\r\n\r\nexport interface DOCXMetadata {\r\n /** Estimated word count */\r\n wordCount: number;\r\n /** Estimated character count */\r\n characterCount: number;\r\n /** Number of paragraphs */\r\n paragraphCount: number;\r\n}\r\n\r\nexport interface DOCXParseOptions {\r\n /** Include images as base64 data URIs */\r\n includeImages?: boolean;\r\n /** Custom style mappings for mammoth */\r\n styleMap?: string[];\r\n /** Convert to markdown instead of plain text */\r\n outputMarkdown?: boolean;\r\n}\r\n\r\n/**\r\n * Parse a DOCX file and extract its content\r\n */\r\nexport async function parseDOCX(\r\n input: string | Buffer,\r\n options: DOCXParseOptions = {}\r\n): Promise<DOCXParseResult> {\r\n let buffer: Buffer;\r\n\r\n if (typeof input === \"string\") {\r\n const absolutePath = path.isAbsolute(input) ? input : path.resolve(input);\r\n buffer = await fs.readFile(absolutePath);\r\n } else {\r\n buffer = input;\r\n }\r\n\r\n const mammothOptions: any = {};\r\n\r\n // Apply custom style mappings\r\n if (options.styleMap && options.styleMap.length > 0) {\r\n mammothOptions.styleMap = options.styleMap;\r\n }\r\n\r\n // Handle images\r\n if (options.includeImages) {\r\n mammothOptions.convertImage = mammoth.images.imgElement((image) => {\r\n return image.read(\"base64\").then((imageBuffer) => {\r\n return {\r\n src: `data:${image.contentType};base64,${imageBuffer}`,\r\n };\r\n });\r\n });\r\n }\r\n\r\n // Extract HTML\r\n const htmlResult = await mammoth.convertToHtml(\r\n { buffer },\r\n mammothOptions\r\n );\r\n\r\n // Extract plain text\r\n const textResult = await mammoth.extractRawText({ buffer });\r\n\r\n // Convert to markdown if requested\r\n let markdown = \"\";\r\n if (options.outputMarkdown) {\r\n markdown = htmlToMarkdown(htmlResult.value);\r\n }\r\n\r\n // Calculate metadata\r\n const text = textResult.value;\r\n const wordCount = text\r\n .split(/\\s+/)\r\n .filter((word) => word.length > 0).length;\r\n const characterCount = text.length;\r\n const paragraphCount = text.split(/\\n\\n+/).filter((p) => p.trim().length > 0)\r\n .length;\r\n\r\n // Map messages\r\n const messages: DOCXMessage[] = htmlResult.messages.map((msg) => ({\r\n type: msg.type as \"warning\" | \"error\",\r\n message: msg.message,\r\n paragraphIndex: (msg as any).paragraphIndex,\r\n }));\r\n\r\n return {\r\n text: textResult.value,\r\n html: htmlResult.value,\r\n markdown: markdown || htmlToMarkdown(htmlResult.value),\r\n messages,\r\n metadata: {\r\n wordCount,\r\n characterCount,\r\n paragraphCount,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Convert HTML to basic markdown\r\n */\r\nfunction htmlToMarkdown(html: string): string {\r\n let markdown = html;\r\n\r\n // Headers\r\n markdown = markdown.replace(/<h1[^>]*>(.*?)<\\/h1>/gi, \"# $1\\n\\n\");\r\n markdown = markdown.replace(/<h2[^>]*>(.*?)<\\/h2>/gi, \"## $1\\n\\n\");\r\n markdown = markdown.replace(/<h3[^>]*>(.*?)<\\/h3>/gi, \"### $1\\n\\n\");\r\n markdown = markdown.replace(/<h4[^>]*>(.*?)<\\/h4>/gi, \"#### $1\\n\\n\");\r\n markdown = markdown.replace(/<h5[^>]*>(.*?)<\\/h5>/gi, \"##### $1\\n\\n\");\r\n markdown = markdown.replace(/<h6[^>]*>(.*?)<\\/h6>/gi, \"###### $1\\n\\n\");\r\n\r\n // Bold and italic\r\n markdown = markdown.replace(/<strong[^>]*>(.*?)<\\/strong>/gi, \"**$1**\");\r\n markdown = markdown.replace(/<b[^>]*>(.*?)<\\/b>/gi, \"**$1**\");\r\n markdown = markdown.replace(/<em[^>]*>(.*?)<\\/em>/gi, \"*$1*\");\r\n markdown = markdown.replace(/<i[^>]*>(.*?)<\\/i>/gi, \"*$1*\");\r\n\r\n // Links\r\n markdown = markdown.replace(\r\n /<a[^>]*href=\"([^\"]*)\"[^>]*>(.*?)<\\/a>/gi,\r\n \"[$2]($1)\"\r\n );\r\n\r\n // Images\r\n markdown = markdown.replace(\r\n /<img[^>]*src=\"([^\"]*)\"[^>]*alt=\"([^\"]*)\"[^>]*\\/?>/gi,\r\n \"\"\r\n );\r\n markdown = markdown.replace(\r\n /<img[^>]*src=\"([^\"]*)\"[^>]*\\/?>/gi,\r\n \"\"\r\n );\r\n\r\n // Lists\r\n markdown = markdown.replace(/<ul[^>]*>/gi, \"\\n\");\r\n markdown = markdown.replace(/<\\/ul>/gi, \"\\n\");\r\n markdown = markdown.replace(/<ol[^>]*>/gi, \"\\n\");\r\n markdown = markdown.replace(/<\\/ol>/gi, \"\\n\");\r\n markdown = markdown.replace(/<li[^>]*>(.*?)<\\/li>/gi, \"- $1\\n\");\r\n\r\n // Paragraphs and line breaks\r\n markdown = markdown.replace(/<p[^>]*>(.*?)<\\/p>/gi, \"$1\\n\\n\");\r\n markdown = markdown.replace(/<br[^>]*\\/?>/gi, \"\\n\");\r\n\r\n // Code\r\n markdown = markdown.replace(/<code[^>]*>(.*?)<\\/code>/gi, \"`$1`\");\r\n markdown = markdown.replace(/<pre[^>]*>(.*?)<\\/pre>/gis, \"```\\n$1\\n```\\n\");\r\n\r\n // Blockquotes\r\n markdown = markdown.replace(\r\n /<blockquote[^>]*>(.*?)<\\/blockquote>/gis,\r\n (match, content) => {\r\n return content\r\n .split(\"\\n\")\r\n .map((line: string) => `> ${line}`)\r\n .join(\"\\n\");\r\n }\r\n );\r\n\r\n // Tables (basic support)\r\n markdown = markdown.replace(/<table[^>]*>/gi, \"\\n\");\r\n markdown = markdown.replace(/<\\/table>/gi, \"\\n\");\r\n markdown = markdown.replace(/<tr[^>]*>/gi, \"\");\r\n markdown = markdown.replace(/<\\/tr>/gi, \"|\\n\");\r\n markdown = markdown.replace(/<th[^>]*>(.*?)<\\/th>/gi, \"| **$1** \");\r\n markdown = markdown.replace(/<td[^>]*>(.*?)<\\/td>/gi, \"| $1 \");\r\n\r\n // Horizontal rule\r\n markdown = markdown.replace(/<hr[^>]*\\/?>/gi, \"\\n---\\n\");\r\n\r\n // Remove remaining HTML tags\r\n markdown = markdown.replace(/<[^>]+>/g, \"\");\r\n\r\n // Decode HTML entities\r\n markdown = decodeHtmlEntities(markdown);\r\n\r\n // Clean up whitespace\r\n markdown = markdown.replace(/\\n{3,}/g, \"\\n\\n\");\r\n markdown = markdown.trim();\r\n\r\n return markdown;\r\n}\r\n\r\n/**\r\n * Decode common HTML entities\r\n */\r\nfunction decodeHtmlEntities(text: string): string {\r\n const entities: Record<string, string> = {\r\n \"&\": \"&\",\r\n \"<\": \"<\",\r\n \">\": \">\",\r\n \""\": '\"',\r\n \"'\": \"'\",\r\n \"'\": \"'\",\r\n \" \": \" \",\r\n \"–\": \"-\",\r\n \"—\": \"--\",\r\n \"‘\": \"'\",\r\n \"’\": \"'\",\r\n \"“\": '\"',\r\n \"”\": '\"',\r\n \"…\": \"...\",\r\n \"©\": \"(c)\",\r\n \"®\": \"(R)\",\r\n \"™\": \"(TM)\",\r\n };\r\n\r\n let result = text;\r\n for (const [entity, char] of Object.entries(entities)) {\r\n result = result.replace(new RegExp(entity, \"g\"), char);\r\n }\r\n\r\n // Handle numeric entities\r\n result = result.replace(/&#(\\d+);/g, (match, dec) =>\r\n String.fromCharCode(parseInt(dec, 10))\r\n );\r\n result = result.replace(/&#x([0-9a-fA-F]+);/g, (match, hex) =>\r\n String.fromCharCode(parseInt(hex, 16))\r\n );\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Extract plain text from DOCX\r\n */\r\nexport async function extractDOCXText(input: string | Buffer): Promise<string> {\r\n const result = await parseDOCX(input);\r\n return result.text;\r\n}\r\n\r\n/**\r\n * Extract markdown from DOCX\r\n */\r\nexport async function extractDOCXMarkdown(\r\n input: string | Buffer\r\n): Promise<string> {\r\n const result = await parseDOCX(input, { outputMarkdown: true });\r\n return result.markdown;\r\n}\r\n\r\n/**\r\n * Check if a file is a valid DOCX\r\n */\r\nexport async function isValidDOCX(input: string | Buffer): Promise<boolean> {\r\n try {\r\n let buffer: Buffer;\r\n\r\n if (typeof input === \"string\") {\r\n const absolutePath = path.isAbsolute(input) ? input : path.resolve(input);\r\n buffer = await fs.readFile(absolutePath);\r\n } else {\r\n buffer = input;\r\n }\r\n\r\n // DOCX is a ZIP file, check for ZIP magic number\r\n const header = buffer.slice(0, 4);\r\n if (header[0] !== 0x50 || header[1] !== 0x4b) {\r\n return false;\r\n }\r\n\r\n // Try parsing to verify it's a valid DOCX\r\n await mammoth.extractRawText({ buffer });\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Get document statistics without full parsing\r\n */\r\nexport async function getDOCXStats(\r\n input: string | Buffer\r\n): Promise<DOCXMetadata> {\r\n const result = await parseDOCX(input);\r\n return result.metadata;\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -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-I7MNG6CL.js");
|
|
221
|
+
const { metrics } = await import("./schema-ETY7L2VA.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-I7MNG6CL.js");
|
|
268
|
+
const { metrics } = await import("./schema-ETY7L2VA.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-6ZNCY2GI.js.map
|