opensentinel 2.1.1 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +354 -283
- package/dist/archiver-AVNBYCKQ.js +15340 -0
- package/dist/archiver-AVNBYCKQ.js.map +1 -0
- package/dist/audit-logger-OBPR7CRO.js +22 -0
- package/dist/auth-UOX5K2BE.js +18 -0
- package/dist/autonomy-ZXDBDQUJ.js +86 -0
- package/dist/autonomy-ZXDBDQUJ.js.map +1 -0
- package/dist/aws-s3-Q4LLZZPD.js +146 -0
- package/dist/aws-s3-Q4LLZZPD.js.map +1 -0
- package/dist/backup-restore-PZ7CYYB7.js +16 -0
- package/dist/blocks-R3PODY47.js +23 -0
- package/dist/bot-QRARP4UN.js +36 -0
- package/dist/brain-7XLLM3KC.js +56 -0
- package/dist/camera-monitor-M5CYKUU4.js +335 -0
- package/dist/camera-monitor-M5CYKUU4.js.map +1 -0
- package/dist/{charts-MMXM6BWW.js → charts-V7ARZNKF.js} +2 -2
- package/dist/chunk-22VGGA7S.js +330 -0
- package/dist/chunk-22VGGA7S.js.map +1 -0
- package/dist/chunk-35WYTA3C.js +382 -0
- package/dist/chunk-35WYTA3C.js.map +1 -0
- package/dist/chunk-3E2PSU2C.js +146 -0
- package/dist/chunk-3E2PSU2C.js.map +1 -0
- package/dist/{chunk-L3F43VPB.js → chunk-4GLYY4NN.js} +2 -2
- package/dist/{chunk-L3F43VPB.js.map → chunk-4GLYY4NN.js.map} +1 -1
- package/dist/{chunk-L3PDU3XN.js → chunk-4UOE5TUZ.js} +4 -4
- package/dist/{chunk-6SNHU3CY.js → chunk-66OJ3WB4.js} +2 -2
- package/dist/chunk-6KONMXQ6.js +297 -0
- package/dist/chunk-6KONMXQ6.js.map +1 -0
- package/dist/chunk-6PMVAAA7.js +196 -0
- package/dist/chunk-6PMVAAA7.js.map +1 -0
- package/dist/chunk-766ASQWE.js +32620 -0
- package/dist/chunk-766ASQWE.js.map +1 -0
- package/dist/chunk-7WQO5J2M.js +29 -0
- package/dist/chunk-7WQO5J2M.js.map +1 -0
- package/dist/chunk-APHSRMBS.js +148 -0
- package/dist/chunk-APHSRMBS.js.map +1 -0
- package/dist/{chunk-4LVWXUNC.js → chunk-AYUKPTSM.js} +57 -39
- package/dist/chunk-AYUKPTSM.js.map +1 -0
- package/dist/chunk-BIPYADGB.js +84 -0
- package/dist/chunk-BIPYADGB.js.map +1 -0
- package/dist/chunk-BRBWNV65.js +457 -0
- package/dist/chunk-BRBWNV65.js.map +1 -0
- package/dist/chunk-BXZ6EA52.js +382 -0
- package/dist/chunk-BXZ6EA52.js.map +1 -0
- package/dist/chunk-EVE7MIIY.js +290 -0
- package/dist/chunk-EVE7MIIY.js.map +1 -0
- package/dist/chunk-F3TTNID2.js +138 -0
- package/dist/chunk-F3TTNID2.js.map +1 -0
- package/dist/chunk-H5RQOFO2.js +190 -0
- package/dist/chunk-H5RQOFO2.js.map +1 -0
- package/dist/chunk-HN3F4WSW.js +145 -0
- package/dist/chunk-HN3F4WSW.js.map +1 -0
- package/dist/{chunk-6DRDKB45.js → chunk-I6BDYQIG.js} +20 -9
- package/dist/chunk-I6BDYQIG.js.map +1 -0
- package/dist/chunk-IZJMVV7O.js +347 -0
- package/dist/chunk-IZJMVV7O.js.map +1 -0
- package/dist/chunk-KM22GV7G.js +211 -0
- package/dist/chunk-KM22GV7G.js.map +1 -0
- package/dist/chunk-MGFBLVR7.js +103 -0
- package/dist/chunk-MGFBLVR7.js.map +1 -0
- package/dist/chunk-MQJ2ECQT.js +228 -0
- package/dist/chunk-MQJ2ECQT.js.map +1 -0
- package/dist/{chunk-F6QUZQGI.js → chunk-MXAPLSJ5.js} +2 -2
- package/dist/{chunk-GK3E2I7A.js → chunk-NHMBTUMW.js} +2 -2
- package/dist/chunk-NPRTSZIF.js +131 -0
- package/dist/chunk-NPRTSZIF.js.map +1 -0
- package/dist/chunk-O7IH7JTI.js +1898 -0
- package/dist/chunk-O7IH7JTI.js.map +1 -0
- package/dist/chunk-OCVQGBJK.js +293 -0
- package/dist/chunk-OCVQGBJK.js.map +1 -0
- package/dist/chunk-P6QINGFL.js +332 -0
- package/dist/chunk-P6QINGFL.js.map +1 -0
- package/dist/chunk-PHDZKPNE.js +91 -0
- package/dist/chunk-PHDZKPNE.js.map +1 -0
- package/dist/chunk-PLDDJCW6.js +49 -0
- package/dist/chunk-PTGTGXV2.js +164 -0
- package/dist/chunk-PTGTGXV2.js.map +1 -0
- package/dist/chunk-REMIY4U2.js +171 -0
- package/dist/chunk-REMIY4U2.js.map +1 -0
- package/dist/chunk-RZ4YESBG.js +141 -0
- package/dist/chunk-RZ4YESBG.js.map +1 -0
- package/dist/chunk-SAX5MHK4.js +111 -0
- package/dist/chunk-SAX5MHK4.js.map +1 -0
- package/dist/{chunk-GVJVEWHI.js → chunk-SJSUSJ47.js} +2 -2
- package/dist/chunk-SPPMCAKG.js +777 -0
- package/dist/chunk-SPPMCAKG.js.map +1 -0
- package/dist/chunk-SVAPX2XN.js +2441 -0
- package/dist/chunk-SVAPX2XN.js.map +1 -0
- package/dist/chunk-TVEWKIK3.js +452 -0
- package/dist/chunk-TVEWKIK3.js.map +1 -0
- package/dist/{chunk-HH2HBTQM.js → chunk-TYAGMJNV.js} +5 -5
- package/dist/{chunk-JXUP2X7V.js → chunk-VEHFVBLI.js} +2 -2
- package/dist/chunk-VNX5GMTN.js +128 -0
- package/dist/chunk-VNX5GMTN.js.map +1 -0
- package/dist/chunk-VRD5CYRL.js +1568 -0
- package/dist/chunk-VRD5CYRL.js.map +1 -0
- package/dist/chunk-WLUHNG6X.js +122 -0
- package/dist/chunk-WLUHNG6X.js.map +1 -0
- package/dist/chunk-WRAKK6K6.js +265 -0
- package/dist/chunk-WRAKK6K6.js.map +1 -0
- package/dist/chunk-XKYRH4FM.js +681 -0
- package/dist/chunk-XKYRH4FM.js.map +1 -0
- package/dist/{chunk-GUBEEYDW.js → chunk-XMCVRVTF.js} +2 -2
- package/dist/{chunk-GUBEEYDW.js.map → chunk-XMCVRVTF.js.map} +1 -1
- package/dist/chunk-ZLZKF2PM.js +310 -0
- package/dist/chunk-ZLZKF2PM.js.map +1 -0
- package/dist/cli.js +5 -1
- package/dist/cli.js.map +1 -1
- package/dist/client-ZQSFPMOB.js +21 -0
- package/dist/clipboard-manager-TEO2GEDN.js +24 -0
- package/dist/commands/setup.js +3 -3
- package/dist/commands/setup.js.map +1 -1
- 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/cron-explain-HHQKPD3M.js +16 -0
- package/dist/crypto-4AP47IKC.js +14 -0
- package/dist/crypto-4AP47IKC.js.map +1 -0
- package/dist/databases-37X4CI2Y.js +21 -0
- package/dist/databases-37X4CI2Y.js.map +1 -0
- package/dist/discord-B3HUPGQ6.js +70 -0
- package/dist/discord-B3HUPGQ6.js.map +1 -0
- package/dist/dist-UISMLMFN.js +21847 -0
- package/dist/dist-UISMLMFN.js.map +1 -0
- package/dist/email-K7LO2IPB.js +268 -0
- package/dist/email-K7LO2IPB.js.map +1 -0
- package/dist/enhanced-retrieval-DNLLEM4Z.js +753 -0
- package/dist/enhanced-retrieval-DNLLEM4Z.js.map +1 -0
- package/dist/enrichment-pipeline-MNHNW65K.js +13 -0
- package/dist/enrichment-pipeline-MNHNW65K.js.map +1 -0
- package/dist/entity-resolution-Y3IUWEAT.js +24 -0
- package/dist/entity-resolution-Y3IUWEAT.js.map +1 -0
- package/dist/env-IWXUVTCB.js +12 -0
- package/dist/env-IWXUVTCB.js.map +1 -0
- package/dist/google-workspace-DKWUVNGC.js +169 -0
- package/dist/google-workspace-DKWUVNGC.js.map +1 -0
- package/dist/hash-tool-ULQYD7B5.js +22 -0
- package/dist/hash-tool-ULQYD7B5.js.map +1 -0
- package/dist/heartbeat-monitor-GCISLXI3.js +22 -0
- package/dist/heartbeat-monitor-GCISLXI3.js.map +1 -0
- package/dist/image-generation-OSU7FP6F.js +486 -0
- package/dist/image-generation-OSU7FP6F.js.map +1 -0
- package/dist/imessage-NGA2XF2V.js +35 -0
- package/dist/imessage-NGA2XF2V.js.map +1 -0
- package/dist/inbox-summarizer-NRI4S7IF.js +47 -0
- package/dist/inbox-summarizer-NRI4S7IF.js.map +1 -0
- package/dist/incident-response-C5J7Q6DT.js +244 -0
- package/dist/incident-response-C5J7Q6DT.js.map +1 -0
- package/dist/inventory-manager-352OHXWD.js +24 -0
- package/dist/inventory-manager-352OHXWD.js.map +1 -0
- package/dist/jira-GSGDBMIG.js +199 -0
- package/dist/jira-GSGDBMIG.js.map +1 -0
- package/dist/json-tool-QE2SYHEG.js +26 -0
- package/dist/json-tool-QE2SYHEG.js.map +1 -0
- package/dist/key-rotation-DPHU4ZTB.js +18 -0
- package/dist/key-rotation-DPHU4ZTB.js.map +1 -0
- package/dist/lib.d.ts +603 -11
- package/dist/lib.js +161 -35
- package/dist/lib.js.map +1 -1
- package/dist/mailchimp-KKNF6QJ7.js +152 -0
- package/dist/mailchimp-KKNF6QJ7.js.map +1 -0
- package/dist/matrix-QVHG76I7.js +279 -0
- package/dist/matrix-QVHG76I7.js.map +1 -0
- package/dist/{mcp-LS7Q3Z5W.js → mcp-3JI6W7ZE.js} +3 -3
- package/dist/mcp-3JI6W7ZE.js.map +1 -0
- package/dist/microsoft365-UCBKJHNX.js +164 -0
- package/dist/microsoft365-UCBKJHNX.js.map +1 -0
- package/dist/ocr-AC7NPX33.js +22 -0
- package/dist/ocr-AC7NPX33.js.map +1 -0
- package/dist/ollama-BOAMSPLJ.js +8 -0
- package/dist/ollama-BOAMSPLJ.js.map +1 -0
- package/dist/pages-MI523RB7.js +26 -0
- package/dist/pages-MI523RB7.js.map +1 -0
- package/dist/pair-JDFTERIK.js +24 -0
- package/dist/pair-JDFTERIK.js.map +1 -0
- package/dist/pairing-IFQYCPNS.js +10 -0
- package/dist/pairing-IFQYCPNS.js.map +1 -0
- package/dist/pdf-ALQVOEJR.js +17 -0
- package/dist/pdf-ALQVOEJR.js.map +1 -0
- package/dist/presentations-DSV5IHG5.js +1002 -0
- package/dist/presentations-DSV5IHG5.js.map +1 -0
- package/dist/prometheus-JNT2BD4L.js +10 -0
- package/dist/prometheus-JNT2BD4L.js.map +1 -0
- package/dist/providers-J4LYPHDR.js +19 -0
- package/dist/providers-J4LYPHDR.js.map +1 -0
- package/dist/qr-code-WIX4PB4U.js +16 -0
- package/dist/qr-code-WIX4PB4U.js.map +1 -0
- package/dist/quickbooks-XB4NII2S.js +190 -0
- package/dist/quickbooks-XB4NII2S.js.map +1 -0
- package/dist/regex-tool-W4ABRKGK.js +24 -0
- package/dist/regex-tool-W4ABRKGK.js.map +1 -0
- package/dist/scheduler-VK4WFERV.js +63 -0
- package/dist/scheduler-VK4WFERV.js.map +1 -0
- package/dist/search-BCLBO5E3.js +25 -0
- package/dist/search-BCLBO5E3.js.map +1 -0
- package/dist/sendgrid-RNXCAFKM.js +152 -0
- package/dist/sendgrid-RNXCAFKM.js.map +1 -0
- package/dist/shopify-NCXYJB4R.js +171 -0
- package/dist/shopify-NCXYJB4R.js.map +1 -0
- package/dist/signal-6CGDFYL2.js +35 -0
- package/dist/signal-6CGDFYL2.js.map +1 -0
- package/dist/slack-IZQWIKOH.js +75 -0
- package/dist/slack-IZQWIKOH.js.map +1 -0
- package/dist/sms-M3JIOTCW.js +23 -0
- package/dist/sms-M3JIOTCW.js.map +1 -0
- package/dist/{src-K7GASHRH.js → src-VYUE6LRA.js} +138 -32
- package/dist/src-VYUE6LRA.js.map +1 -0
- package/dist/stocks-XXWBPOCU.js +14 -0
- package/dist/stocks-XXWBPOCU.js.map +1 -0
- package/dist/text-transform-6SGUA5Z4.js +22 -0
- package/dist/text-transform-6SGUA5Z4.js.map +1 -0
- package/dist/tools-2RLEI2N6.js +38 -0
- package/dist/tools-2RLEI2N6.js.map +1 -0
- package/dist/tunnel-IWMXUML4.js +301 -0
- package/dist/tunnel-IWMXUML4.js.map +1 -0
- package/dist/twilio-53GEW5JT.js +139 -0
- package/dist/twilio-53GEW5JT.js.map +1 -0
- package/dist/unit-converter-ZYXMEZOE.js +14 -0
- package/dist/unit-converter-ZYXMEZOE.js.map +1 -0
- package/dist/whatsapp-LFX6YKCM.js +35 -0
- package/dist/whatsapp-LFX6YKCM.js.map +1 -0
- package/dist/word-document-7B6SJMAY.js +902 -0
- package/dist/word-document-7B6SJMAY.js.map +1 -0
- package/dist/xero-QYO66D45.js +162 -0
- package/dist/xero-QYO66D45.js.map +1 -0
- package/dist/zapier-webhook-TBZ5YF2A.js +106 -0
- package/dist/zapier-webhook-TBZ5YF2A.js.map +1 -0
- package/drizzle/0002_mushy_master_mold.sql +140 -0
- package/drizzle/meta/0002_snapshot.json +3637 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +100 -98
- package/dist/bot-KJ26BG56.js +0 -15
- package/dist/chunk-4LVWXUNC.js.map +0 -1
- package/dist/chunk-4TG2IG5K.js +0 -5249
- package/dist/chunk-4TG2IG5K.js.map +0 -1
- package/dist/chunk-6DRDKB45.js.map +0 -1
- package/dist/chunk-CI6Q63MM.js +0 -1613
- package/dist/chunk-CI6Q63MM.js.map +0 -1
- package/dist/chunk-KHNYJY2Z.js +0 -178
- package/dist/chunk-KHNYJY2Z.js.map +0 -1
- package/dist/chunk-NSBPE2FW.js +0 -17
- package/dist/discord-ZOJFTVTB.js +0 -49
- package/dist/imessage-JFRB6EJ7.js +0 -14
- package/dist/scheduler-EZ7CZMCS.js +0 -42
- package/dist/signal-T3MCSULM.js +0 -14
- package/dist/slack-N2M4FHAJ.js +0 -54
- package/dist/src-K7GASHRH.js.map +0 -1
- package/dist/tools-24GZHYRF.js +0 -16
- package/dist/whatsapp-VCRUPAO5.js +0 -14
- /package/dist/{bot-KJ26BG56.js.map → audit-logger-OBPR7CRO.js.map} +0 -0
- /package/dist/{chunk-NSBPE2FW.js.map → auth-UOX5K2BE.js.map} +0 -0
- /package/dist/{discord-ZOJFTVTB.js.map → backup-restore-PZ7CYYB7.js.map} +0 -0
- /package/dist/{imessage-JFRB6EJ7.js.map → blocks-R3PODY47.js.map} +0 -0
- /package/dist/{mcp-LS7Q3Z5W.js.map → bot-QRARP4UN.js.map} +0 -0
- /package/dist/{scheduler-EZ7CZMCS.js.map → brain-7XLLM3KC.js.map} +0 -0
- /package/dist/{charts-MMXM6BWW.js.map → charts-V7ARZNKF.js.map} +0 -0
- /package/dist/{chunk-L3PDU3XN.js.map → chunk-4UOE5TUZ.js.map} +0 -0
- /package/dist/{chunk-6SNHU3CY.js.map → chunk-66OJ3WB4.js.map} +0 -0
- /package/dist/{chunk-F6QUZQGI.js.map → chunk-MXAPLSJ5.js.map} +0 -0
- /package/dist/{chunk-GK3E2I7A.js.map → chunk-NHMBTUMW.js.map} +0 -0
- /package/dist/{signal-T3MCSULM.js.map → chunk-PLDDJCW6.js.map} +0 -0
- /package/dist/{chunk-GVJVEWHI.js.map → chunk-SJSUSJ47.js.map} +0 -0
- /package/dist/{chunk-HH2HBTQM.js.map → chunk-TYAGMJNV.js.map} +0 -0
- /package/dist/{chunk-JXUP2X7V.js.map → chunk-VEHFVBLI.js.map} +0 -0
- /package/dist/{slack-N2M4FHAJ.js.map → client-ZQSFPMOB.js.map} +0 -0
- /package/dist/{tools-24GZHYRF.js.map → clipboard-manager-TEO2GEDN.js.map} +0 -0
- /package/dist/{whatsapp-VCRUPAO5.js.map → cron-explain-HHQKPD3M.js.map} +0 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isPathAllowed
|
|
3
|
+
} from "./chunk-CQ4JURG7.js";
|
|
4
|
+
|
|
5
|
+
// src/tools/file-generation/pdf.ts
|
|
6
|
+
import { createWriteStream } from "fs";
|
|
7
|
+
import { mkdir } from "fs/promises";
|
|
8
|
+
import { dirname, join } from "path";
|
|
9
|
+
import { tmpdir } from "os";
|
|
10
|
+
import { randomBytes } from "crypto";
|
|
11
|
+
var DEFAULT_OPTIONS = {
|
|
12
|
+
format: "A4",
|
|
13
|
+
orientation: "portrait",
|
|
14
|
+
margins: { top: 72, bottom: 72, left: 72, right: 72 }
|
|
15
|
+
};
|
|
16
|
+
function getTempPath() {
|
|
17
|
+
const id = randomBytes(8).toString("hex");
|
|
18
|
+
return join(tmpdir(), `sentinel-doc-${id}.pdf`);
|
|
19
|
+
}
|
|
20
|
+
async function generatePDFNative(content, outputPath, options = {}) {
|
|
21
|
+
const finalOptions = { ...DEFAULT_OPTIONS, ...options };
|
|
22
|
+
const filePath = outputPath || getTempPath();
|
|
23
|
+
if (outputPath && !isPathAllowed(outputPath)) {
|
|
24
|
+
return { success: false, error: "Access to this path is not allowed" };
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
28
|
+
const PDFDocument = (await import("pdfkit")).default;
|
|
29
|
+
const doc = new PDFDocument({
|
|
30
|
+
size: finalOptions.format || "A4",
|
|
31
|
+
layout: finalOptions.orientation || "portrait",
|
|
32
|
+
margins: finalOptions.margins || { top: 72, bottom: 72, left: 72, right: 72 },
|
|
33
|
+
info: {
|
|
34
|
+
Title: finalOptions.title || "Document",
|
|
35
|
+
Author: finalOptions.author || "OpenSentinel"
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
const stream = createWriteStream(filePath);
|
|
39
|
+
doc.pipe(stream);
|
|
40
|
+
const lines = content.split("\n");
|
|
41
|
+
for (const line of lines) {
|
|
42
|
+
if (line.startsWith("# ")) {
|
|
43
|
+
doc.fontSize(24).font("Helvetica-Bold").text(line.slice(2), { align: "left" });
|
|
44
|
+
doc.moveDown(0.5);
|
|
45
|
+
} else if (line.startsWith("## ")) {
|
|
46
|
+
doc.fontSize(18).font("Helvetica-Bold").text(line.slice(3), { align: "left" });
|
|
47
|
+
doc.moveDown(0.3);
|
|
48
|
+
} else if (line.startsWith("### ")) {
|
|
49
|
+
doc.fontSize(14).font("Helvetica-Bold").text(line.slice(4), { align: "left" });
|
|
50
|
+
doc.moveDown(0.2);
|
|
51
|
+
} else if (line.startsWith("- ") || line.startsWith("* ")) {
|
|
52
|
+
doc.fontSize(12).font("Helvetica").text(` \u2022 ${line.slice(2)}`, { indent: 20 });
|
|
53
|
+
} else if (line.trim() === "") {
|
|
54
|
+
doc.moveDown(0.5);
|
|
55
|
+
} else {
|
|
56
|
+
doc.fontSize(12).font("Helvetica").text(line, { align: "left" });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
doc.end();
|
|
60
|
+
await new Promise((resolve, reject) => {
|
|
61
|
+
stream.on("finish", resolve);
|
|
62
|
+
stream.on("error", reject);
|
|
63
|
+
});
|
|
64
|
+
return { success: true, filePath };
|
|
65
|
+
} catch (error) {
|
|
66
|
+
return {
|
|
67
|
+
success: false,
|
|
68
|
+
error: error instanceof Error ? error.message : String(error)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function generatePDFFromMarkdown(markdown, outputPath, options = {}) {
|
|
73
|
+
return generatePDFNative(markdown, outputPath, options);
|
|
74
|
+
}
|
|
75
|
+
async function generatePDFFromHTML(html, outputPath, options = {}) {
|
|
76
|
+
const filePath = outputPath || getTempPath();
|
|
77
|
+
if (outputPath && !isPathAllowed(outputPath)) {
|
|
78
|
+
return {
|
|
79
|
+
success: false,
|
|
80
|
+
error: "Access to this path is not allowed"
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
85
|
+
try {
|
|
86
|
+
const { chromium } = await import("playwright");
|
|
87
|
+
const browser = await chromium.launch({ headless: true });
|
|
88
|
+
const page = await browser.newPage();
|
|
89
|
+
await page.setContent(html, { waitUntil: "networkidle" });
|
|
90
|
+
await page.pdf({
|
|
91
|
+
path: filePath,
|
|
92
|
+
format: options.format || "A4",
|
|
93
|
+
landscape: options.orientation === "landscape",
|
|
94
|
+
margin: options.margins ? {
|
|
95
|
+
top: `${options.margins.top}px`,
|
|
96
|
+
bottom: `${options.margins.bottom}px`,
|
|
97
|
+
left: `${options.margins.left}px`,
|
|
98
|
+
right: `${options.margins.right}px`
|
|
99
|
+
} : void 0
|
|
100
|
+
});
|
|
101
|
+
await browser.close();
|
|
102
|
+
return { success: true, filePath };
|
|
103
|
+
} catch {
|
|
104
|
+
const { writeFile } = await import("fs/promises");
|
|
105
|
+
const htmlPath = filePath.replace(".pdf", ".html");
|
|
106
|
+
await writeFile(htmlPath, html, "utf-8");
|
|
107
|
+
return {
|
|
108
|
+
success: true,
|
|
109
|
+
filePath: htmlPath
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
} catch (error) {
|
|
113
|
+
return {
|
|
114
|
+
success: false,
|
|
115
|
+
error: error instanceof Error ? error.message : String(error)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async function generatePDF(content, filename, options) {
|
|
120
|
+
const outputPath = isPathAllowed(filename) ? filename : join(tmpdir(), filename);
|
|
121
|
+
const contentType = options?.contentType || "markdown";
|
|
122
|
+
if (contentType === "html") {
|
|
123
|
+
return generatePDFFromHTML(content, outputPath, options);
|
|
124
|
+
}
|
|
125
|
+
return generatePDFFromMarkdown(content, outputPath, options);
|
|
126
|
+
}
|
|
127
|
+
var pdf_default = {
|
|
128
|
+
generatePDF,
|
|
129
|
+
generatePDFNative,
|
|
130
|
+
generatePDFFromMarkdown,
|
|
131
|
+
generatePDFFromHTML
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export {
|
|
135
|
+
generatePDFNative,
|
|
136
|
+
generatePDFFromMarkdown,
|
|
137
|
+
generatePDFFromHTML,
|
|
138
|
+
generatePDF,
|
|
139
|
+
pdf_default
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=chunk-RZ4YESBG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tools/file-generation/pdf.ts"],"sourcesContent":["import { createWriteStream } from \"fs\";\nimport { mkdir } from \"fs/promises\";\nimport { dirname, join } from \"path\";\nimport { tmpdir } from \"os\";\nimport { randomBytes } from \"crypto\";\nimport { isPathAllowed } from \"../../utils/paths\";\n\nexport interface PDFOptions {\n title?: string;\n author?: string;\n format?: \"A4\" | \"Letter\" | \"Legal\";\n orientation?: \"portrait\" | \"landscape\";\n margins?: {\n top: number;\n bottom: number;\n left: number;\n right: number;\n };\n}\n\nexport interface PDFGenerationResult {\n success: boolean;\n filePath?: string;\n error?: string;\n}\n\nconst DEFAULT_OPTIONS: PDFOptions = {\n format: \"A4\",\n orientation: \"portrait\",\n margins: { top: 72, bottom: 72, left: 72, right: 72 },\n};\n\n// Generate temp file path\nfunction getTempPath(): string {\n const id = randomBytes(8).toString(\"hex\");\n return join(tmpdir(), `sentinel-doc-${id}.pdf`);\n}\n\n// Simple markdown to text conversion (for basic PDF)\nfunction markdownToText(markdown: string): string {\n return markdown\n // Remove code blocks\n .replace(/```[\\s\\S]*?```/g, (match) => {\n const code = match.replace(/```\\w*\\n?/g, \"\").trim();\n return `\\n${code}\\n`;\n })\n // Remove inline code\n .replace(/`([^`]+)`/g, \"$1\")\n // Convert headers\n .replace(/^### (.+)$/gm, \"\\n$1\\n\" + \"-\".repeat(30))\n .replace(/^## (.+)$/gm, \"\\n$1\\n\" + \"=\".repeat(40))\n .replace(/^# (.+)$/gm, \"\\n$1\\n\" + \"=\".repeat(50))\n // Convert bold/italic\n .replace(/\\*\\*([^*]+)\\*\\*/g, \"$1\")\n .replace(/\\*([^*]+)\\*/g, \"$1\")\n .replace(/__([^_]+)__/g, \"$1\")\n .replace(/_([^_]+)_/g, \"$1\")\n // Convert links\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, \"$1\")\n // Convert lists\n .replace(/^[-*] /gm, \"• \")\n .replace(/^\\d+\\. /gm, \" \")\n // Clean up\n .replace(/\\n{3,}/g, \"\\n\\n\");\n}\n\n// Generate PDF natively using PDFKit (no browser needed)\nexport async function generatePDFNative(\n content: string,\n outputPath?: string,\n options: PDFOptions = {}\n): Promise<PDFGenerationResult> {\n const finalOptions = { ...DEFAULT_OPTIONS, ...options };\n const filePath = outputPath || getTempPath();\n\n if (outputPath && !isPathAllowed(outputPath)) {\n return { success: false, error: \"Access to this path is not allowed\" };\n }\n\n try {\n await mkdir(dirname(filePath), { recursive: true });\n\n const PDFDocument = (await import(\"pdfkit\")).default;\n const doc = new PDFDocument({\n size: finalOptions.format || \"A4\",\n layout: finalOptions.orientation || \"portrait\",\n margins: finalOptions.margins || { top: 72, bottom: 72, left: 72, right: 72 },\n info: {\n Title: finalOptions.title || \"Document\",\n Author: finalOptions.author || \"OpenSentinel\",\n },\n });\n\n const stream = createWriteStream(filePath);\n doc.pipe(stream);\n\n // Parse markdown-like content into PDF sections\n const lines = content.split(\"\\n\");\n for (const line of lines) {\n if (line.startsWith(\"# \")) {\n doc.fontSize(24).font(\"Helvetica-Bold\").text(line.slice(2), { align: \"left\" });\n doc.moveDown(0.5);\n } else if (line.startsWith(\"## \")) {\n doc.fontSize(18).font(\"Helvetica-Bold\").text(line.slice(3), { align: \"left\" });\n doc.moveDown(0.3);\n } else if (line.startsWith(\"### \")) {\n doc.fontSize(14).font(\"Helvetica-Bold\").text(line.slice(4), { align: \"left\" });\n doc.moveDown(0.2);\n } else if (line.startsWith(\"- \") || line.startsWith(\"* \")) {\n doc.fontSize(12).font(\"Helvetica\").text(` \\u2022 ${line.slice(2)}`, { indent: 20 });\n } else if (line.trim() === \"\") {\n doc.moveDown(0.5);\n } else {\n doc.fontSize(12).font(\"Helvetica\").text(line, { align: \"left\" });\n }\n }\n\n doc.end();\n await new Promise<void>((resolve, reject) => {\n stream.on(\"finish\", resolve);\n stream.on(\"error\", reject);\n });\n\n return { success: true, filePath };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n// Generate PDF from markdown content using PDFKit\nexport async function generatePDFFromMarkdown(\n markdown: string,\n outputPath?: string,\n options: PDFOptions = {}\n): Promise<PDFGenerationResult> {\n // Use native PDFKit implementation\n return generatePDFNative(markdown, outputPath, options);\n}\n\n// Generate PDF from HTML (requires browser/puppeteer)\nexport async function generatePDFFromHTML(\n html: string,\n outputPath?: string,\n options: PDFOptions = {}\n): Promise<PDFGenerationResult> {\n const filePath = outputPath || getTempPath();\n\n // Security check\n if (outputPath && !isPathAllowed(outputPath)) {\n return {\n success: false,\n error: \"Access to this path is not allowed\",\n };\n }\n\n try {\n // Ensure directory exists\n await mkdir(dirname(filePath), { recursive: true });\n\n // Try to use Playwright if available\n try {\n const { chromium } = await import(\"playwright\");\n const browser = await chromium.launch({ headless: true });\n const page = await browser.newPage();\n\n await page.setContent(html, { waitUntil: \"networkidle\" });\n\n await page.pdf({\n path: filePath,\n format: options.format || \"A4\",\n landscape: options.orientation === \"landscape\",\n margin: options.margins\n ? {\n top: `${options.margins.top}px`,\n bottom: `${options.margins.bottom}px`,\n left: `${options.margins.left}px`,\n right: `${options.margins.right}px`,\n }\n : undefined,\n });\n\n await browser.close();\n\n return { success: true, filePath };\n } catch {\n // Fallback: save as HTML\n const { writeFile } = await import(\"fs/promises\");\n const htmlPath = filePath.replace(\".pdf\", \".html\");\n await writeFile(htmlPath, html, \"utf-8\");\n\n return {\n success: true,\n filePath: htmlPath,\n };\n }\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n// Main function for tool use\nexport async function generatePDF(\n content: string,\n filename: string,\n options?: PDFOptions & { contentType?: \"markdown\" | \"html\" }\n): Promise<PDFGenerationResult> {\n const outputPath = isPathAllowed(filename) ? filename : join(tmpdir(), filename);\n const contentType = options?.contentType || \"markdown\";\n\n if (contentType === \"html\") {\n return generatePDFFromHTML(content, outputPath, options);\n }\n\n return generatePDFFromMarkdown(content, outputPath, options);\n}\n\nexport default {\n generatePDF,\n generatePDFNative,\n generatePDFFromMarkdown,\n generatePDFFromHTML,\n};\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// src/tools/heartbeat-monitor.ts
|
|
2
|
+
var services = /* @__PURE__ */ new Map();
|
|
3
|
+
function registerService(id, name, intervalMs = 6e4, metadata) {
|
|
4
|
+
if (services.has(id)) {
|
|
5
|
+
return { success: false, error: `Service '${id}' already registered` };
|
|
6
|
+
}
|
|
7
|
+
const service = {
|
|
8
|
+
id,
|
|
9
|
+
name,
|
|
10
|
+
intervalMs,
|
|
11
|
+
lastBeat: null,
|
|
12
|
+
status: "unknown",
|
|
13
|
+
consecutiveMisses: 0,
|
|
14
|
+
metadata
|
|
15
|
+
};
|
|
16
|
+
services.set(id, service);
|
|
17
|
+
return { success: true, service };
|
|
18
|
+
}
|
|
19
|
+
function recordBeat(id) {
|
|
20
|
+
const service = services.get(id);
|
|
21
|
+
if (!service) {
|
|
22
|
+
return { success: false, error: `Service '${id}' not found` };
|
|
23
|
+
}
|
|
24
|
+
service.lastBeat = Date.now();
|
|
25
|
+
service.consecutiveMisses = 0;
|
|
26
|
+
service.status = "healthy";
|
|
27
|
+
services.set(id, service);
|
|
28
|
+
return { success: true, service };
|
|
29
|
+
}
|
|
30
|
+
function checkHeartbeats() {
|
|
31
|
+
const now = Date.now();
|
|
32
|
+
const results = [];
|
|
33
|
+
for (const [, service] of services) {
|
|
34
|
+
if (service.lastBeat === null) {
|
|
35
|
+
service.status = "unknown";
|
|
36
|
+
} else {
|
|
37
|
+
const elapsed = now - service.lastBeat;
|
|
38
|
+
if (elapsed > service.intervalMs * 3) {
|
|
39
|
+
service.status = "down";
|
|
40
|
+
service.consecutiveMisses = Math.floor(elapsed / service.intervalMs);
|
|
41
|
+
} else if (elapsed > service.intervalMs * 1.5) {
|
|
42
|
+
service.status = "degraded";
|
|
43
|
+
service.consecutiveMisses = Math.floor(elapsed / service.intervalMs);
|
|
44
|
+
} else {
|
|
45
|
+
service.status = "healthy";
|
|
46
|
+
service.consecutiveMisses = 0;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
results.push({ ...service });
|
|
50
|
+
}
|
|
51
|
+
return { success: true, services: results };
|
|
52
|
+
}
|
|
53
|
+
function unregisterService(id) {
|
|
54
|
+
if (!services.has(id)) {
|
|
55
|
+
return { success: false, error: `Service '${id}' not found` };
|
|
56
|
+
}
|
|
57
|
+
services.delete(id);
|
|
58
|
+
return { success: true };
|
|
59
|
+
}
|
|
60
|
+
function getServiceStatus(id) {
|
|
61
|
+
const service = services.get(id);
|
|
62
|
+
if (!service) {
|
|
63
|
+
return { success: false, error: `Service '${id}' not found` };
|
|
64
|
+
}
|
|
65
|
+
return { success: true, service: { ...service } };
|
|
66
|
+
}
|
|
67
|
+
function getHeartbeatSummary() {
|
|
68
|
+
let healthy = 0, degraded = 0, down = 0, unknown = 0;
|
|
69
|
+
checkHeartbeats();
|
|
70
|
+
for (const [, service] of services) {
|
|
71
|
+
switch (service.status) {
|
|
72
|
+
case "healthy":
|
|
73
|
+
healthy++;
|
|
74
|
+
break;
|
|
75
|
+
case "degraded":
|
|
76
|
+
degraded++;
|
|
77
|
+
break;
|
|
78
|
+
case "down":
|
|
79
|
+
down++;
|
|
80
|
+
break;
|
|
81
|
+
default:
|
|
82
|
+
unknown++;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return { total: services.size, healthy, degraded, down, unknown };
|
|
87
|
+
}
|
|
88
|
+
function resetAll() {
|
|
89
|
+
services.clear();
|
|
90
|
+
}
|
|
91
|
+
var heartbeat_monitor_default = {
|
|
92
|
+
registerService,
|
|
93
|
+
recordBeat,
|
|
94
|
+
checkHeartbeats,
|
|
95
|
+
unregisterService,
|
|
96
|
+
getServiceStatus,
|
|
97
|
+
getHeartbeatSummary,
|
|
98
|
+
resetAll
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
registerService,
|
|
103
|
+
recordBeat,
|
|
104
|
+
checkHeartbeats,
|
|
105
|
+
unregisterService,
|
|
106
|
+
getServiceStatus,
|
|
107
|
+
getHeartbeatSummary,
|
|
108
|
+
resetAll,
|
|
109
|
+
heartbeat_monitor_default
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=chunk-SAX5MHK4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tools/heartbeat-monitor.ts"],"sourcesContent":["/**\r\n * Heartbeat Monitor\r\n * Track service health with periodic heartbeats\r\n */\r\n\r\nexport interface HeartbeatService {\r\n id: string;\r\n name: string;\r\n intervalMs: number;\r\n lastBeat: number | null;\r\n status: \"healthy\" | \"degraded\" | \"down\" | \"unknown\";\r\n consecutiveMisses: number;\r\n metadata?: Record<string, unknown>;\r\n}\r\n\r\nexport interface HeartbeatResult {\r\n success: boolean;\r\n service?: HeartbeatService;\r\n services?: HeartbeatService[];\r\n error?: string;\r\n}\r\n\r\n// In-memory store of registered services\r\nconst services = new Map<string, HeartbeatService>();\r\n\r\n// Register a new service to monitor\r\nexport function registerService(\r\n id: string,\r\n name: string,\r\n intervalMs: number = 60000,\r\n metadata?: Record<string, unknown>\r\n): HeartbeatResult {\r\n if (services.has(id)) {\r\n return { success: false, error: `Service '${id}' already registered` };\r\n }\r\n\r\n const service: HeartbeatService = {\r\n id,\r\n name,\r\n intervalMs,\r\n lastBeat: null,\r\n status: \"unknown\",\r\n consecutiveMisses: 0,\r\n metadata,\r\n };\r\n\r\n services.set(id, service);\r\n return { success: true, service };\r\n}\r\n\r\n// Record a heartbeat for a service\r\nexport function recordBeat(id: string): HeartbeatResult {\r\n const service = services.get(id);\r\n if (!service) {\r\n return { success: false, error: `Service '${id}' not found` };\r\n }\r\n\r\n service.lastBeat = Date.now();\r\n service.consecutiveMisses = 0;\r\n service.status = \"healthy\";\r\n services.set(id, service);\r\n\r\n return { success: true, service };\r\n}\r\n\r\n// Check all services for missed heartbeats\r\nexport function checkHeartbeats(): HeartbeatResult {\r\n const now = Date.now();\r\n const results: HeartbeatService[] = [];\r\n\r\n for (const [, service] of services) {\r\n if (service.lastBeat === null) {\r\n service.status = \"unknown\";\r\n } else {\r\n const elapsed = now - service.lastBeat;\r\n if (elapsed > service.intervalMs * 3) {\r\n service.status = \"down\";\r\n service.consecutiveMisses = Math.floor(elapsed / service.intervalMs);\r\n } else if (elapsed > service.intervalMs * 1.5) {\r\n service.status = \"degraded\";\r\n service.consecutiveMisses = Math.floor(elapsed / service.intervalMs);\r\n } else {\r\n service.status = \"healthy\";\r\n service.consecutiveMisses = 0;\r\n }\r\n }\r\n results.push({ ...service });\r\n }\r\n\r\n return { success: true, services: results };\r\n}\r\n\r\n// Remove a service from monitoring\r\nexport function unregisterService(id: string): HeartbeatResult {\r\n if (!services.has(id)) {\r\n return { success: false, error: `Service '${id}' not found` };\r\n }\r\n\r\n services.delete(id);\r\n return { success: true };\r\n}\r\n\r\n// Get status of a specific service\r\nexport function getServiceStatus(id: string): HeartbeatResult {\r\n const service = services.get(id);\r\n if (!service) {\r\n return { success: false, error: `Service '${id}' not found` };\r\n }\r\n\r\n return { success: true, service: { ...service } };\r\n}\r\n\r\n// Get summary stats\r\nexport function getHeartbeatSummary(): {\r\n total: number;\r\n healthy: number;\r\n degraded: number;\r\n down: number;\r\n unknown: number;\r\n} {\r\n let healthy = 0, degraded = 0, down = 0, unknown = 0;\r\n\r\n // Refresh statuses first\r\n checkHeartbeats();\r\n\r\n for (const [, service] of services) {\r\n switch (service.status) {\r\n case \"healthy\": healthy++; break;\r\n case \"degraded\": degraded++; break;\r\n case \"down\": down++; break;\r\n default: unknown++; break;\r\n }\r\n }\r\n\r\n return { total: services.size, healthy, degraded, down, unknown };\r\n}\r\n\r\n// Reset all services (for testing)\r\nexport function resetAll(): void {\r\n services.clear();\r\n}\r\n\r\nexport default {\r\n registerService,\r\n recordBeat,\r\n checkHeartbeats,\r\n unregisterService,\r\n getServiceStatus,\r\n getHeartbeatSummary,\r\n resetAll,\r\n};\r\n"],"mappings":";AAuBA,IAAM,WAAW,oBAAI,IAA8B;AAG5C,SAAS,gBACd,IACA,MACA,aAAqB,KACrB,UACiB;AACjB,MAAI,SAAS,IAAI,EAAE,GAAG;AACpB,WAAO,EAAE,SAAS,OAAO,OAAO,YAAY,EAAE,uBAAuB;AAAA,EACvE;AAEA,QAAM,UAA4B;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,mBAAmB;AAAA,IACnB;AAAA,EACF;AAEA,WAAS,IAAI,IAAI,OAAO;AACxB,SAAO,EAAE,SAAS,MAAM,QAAQ;AAClC;AAGO,SAAS,WAAW,IAA6B;AACtD,QAAM,UAAU,SAAS,IAAI,EAAE;AAC/B,MAAI,CAAC,SAAS;AACZ,WAAO,EAAE,SAAS,OAAO,OAAO,YAAY,EAAE,cAAc;AAAA,EAC9D;AAEA,UAAQ,WAAW,KAAK,IAAI;AAC5B,UAAQ,oBAAoB;AAC5B,UAAQ,SAAS;AACjB,WAAS,IAAI,IAAI,OAAO;AAExB,SAAO,EAAE,SAAS,MAAM,QAAQ;AAClC;AAGO,SAAS,kBAAmC;AACjD,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,UAA8B,CAAC;AAErC,aAAW,CAAC,EAAE,OAAO,KAAK,UAAU;AAClC,QAAI,QAAQ,aAAa,MAAM;AAC7B,cAAQ,SAAS;AAAA,IACnB,OAAO;AACL,YAAM,UAAU,MAAM,QAAQ;AAC9B,UAAI,UAAU,QAAQ,aAAa,GAAG;AACpC,gBAAQ,SAAS;AACjB,gBAAQ,oBAAoB,KAAK,MAAM,UAAU,QAAQ,UAAU;AAAA,MACrE,WAAW,UAAU,QAAQ,aAAa,KAAK;AAC7C,gBAAQ,SAAS;AACjB,gBAAQ,oBAAoB,KAAK,MAAM,UAAU,QAAQ,UAAU;AAAA,MACrE,OAAO;AACL,gBAAQ,SAAS;AACjB,gBAAQ,oBAAoB;AAAA,MAC9B;AAAA,IACF;AACA,YAAQ,KAAK,EAAE,GAAG,QAAQ,CAAC;AAAA,EAC7B;AAEA,SAAO,EAAE,SAAS,MAAM,UAAU,QAAQ;AAC5C;AAGO,SAAS,kBAAkB,IAA6B;AAC7D,MAAI,CAAC,SAAS,IAAI,EAAE,GAAG;AACrB,WAAO,EAAE,SAAS,OAAO,OAAO,YAAY,EAAE,cAAc;AAAA,EAC9D;AAEA,WAAS,OAAO,EAAE;AAClB,SAAO,EAAE,SAAS,KAAK;AACzB;AAGO,SAAS,iBAAiB,IAA6B;AAC5D,QAAM,UAAU,SAAS,IAAI,EAAE;AAC/B,MAAI,CAAC,SAAS;AACZ,WAAO,EAAE,SAAS,OAAO,OAAO,YAAY,EAAE,cAAc;AAAA,EAC9D;AAEA,SAAO,EAAE,SAAS,MAAM,SAAS,EAAE,GAAG,QAAQ,EAAE;AAClD;AAGO,SAAS,sBAMd;AACA,MAAI,UAAU,GAAG,WAAW,GAAG,OAAO,GAAG,UAAU;AAGnD,kBAAgB;AAEhB,aAAW,CAAC,EAAE,OAAO,KAAK,UAAU;AAClC,YAAQ,QAAQ,QAAQ;AAAA,MACtB,KAAK;AAAW;AAAW;AAAA,MAC3B,KAAK;AAAY;AAAY;AAAA,MAC7B,KAAK;AAAQ;AAAQ;AAAA,MACrB;AAAS;AAAW;AAAA,IACtB;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,SAAS,MAAM,SAAS,UAAU,MAAM,QAAQ;AAClE;AAGO,SAAS,WAAiB;AAC/B,WAAS,MAAM;AACjB;AAEA,IAAO,4BAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
env
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZLZKF2PM.js";
|
|
4
4
|
|
|
5
5
|
// src/outputs/stt.ts
|
|
6
6
|
import OpenAI from "openai";
|
|
@@ -26,4 +26,4 @@ async function transcribeAudio(audioBuffer, language) {
|
|
|
26
26
|
export {
|
|
27
27
|
transcribeAudio
|
|
28
28
|
};
|
|
29
|
-
//# sourceMappingURL=chunk-
|
|
29
|
+
//# sourceMappingURL=chunk-SJSUSJ47.js.map
|