mcp-scraper 0.6.0 → 0.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.
Files changed (51) hide show
  1. package/dist/bin/api-server.cjs +296 -198
  2. package/dist/bin/api-server.cjs.map +1 -1
  3. package/dist/bin/api-server.js +2 -2
  4. package/dist/bin/mcp-scraper-cli.cjs +1 -1
  5. package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
  6. package/dist/bin/mcp-scraper-cli.js +1 -1
  7. package/dist/bin/mcp-scraper-install.cjs +1 -1
  8. package/dist/bin/mcp-scraper-install.cjs.map +1 -1
  9. package/dist/bin/mcp-scraper-install.js +1 -1
  10. package/dist/bin/mcp-stdio-server.cjs +3 -3
  11. package/dist/bin/mcp-stdio-server.cjs.map +1 -1
  12. package/dist/bin/mcp-stdio-server.js +3 -3
  13. package/dist/bin/paa-harvest.cjs +166 -74
  14. package/dist/bin/paa-harvest.cjs.map +1 -1
  15. package/dist/bin/paa-harvest.js +1 -1
  16. package/dist/chunk-EGWJ74EX.js +7 -0
  17. package/dist/chunk-EGWJ74EX.js.map +1 -0
  18. package/dist/{chunk-APJO2XV5.js → chunk-HL33CGJF.js} +3 -3
  19. package/dist/{chunk-APJO2XV5.js.map → chunk-HL33CGJF.js.map} +1 -1
  20. package/dist/{chunk-AUCXKRRH.js → chunk-RMPPYKUV.js} +167 -75
  21. package/dist/chunk-RMPPYKUV.js.map +1 -0
  22. package/dist/{chunk-BL7BBSYF.js → chunk-RUGJE5EB.js} +2 -2
  23. package/dist/{chunk-3K5GT6VG.js → chunk-YGRZU7IR.js} +3 -3
  24. package/dist/index.cjs +166 -74
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.js +1 -1
  27. package/dist/{server-WHM446IZ.js → server-JNY4XPZE.js} +81 -76
  28. package/dist/server-JNY4XPZE.js.map +1 -0
  29. package/dist/{site-extract-repository-U476J44K.js → site-extract-repository-NVSZH35Y.js} +3 -3
  30. package/dist/{worker-KJZ3ZN2N.js → worker-JQTS437L.js} +4 -4
  31. package/dist/worker-JQTS437L.js.map +1 -0
  32. package/package.json +1 -1
  33. package/dist/chunk-AUCXKRRH.js.map +0 -1
  34. package/dist/chunk-F2BXETDX.js +0 -7
  35. package/dist/chunk-F2BXETDX.js.map +0 -1
  36. package/dist/server-WHM446IZ.js.map +0 -1
  37. package/dist/worker-KJZ3ZN2N.js.map +0 -1
  38. package/docs/spec-browser-routing.md +0 -108
  39. package/docs/spec-kernel-computer-controls.md +0 -166
  40. package/docs/spec-mcp-tools.md +0 -146
  41. package/docs/spec-server-instructions.md +0 -94
  42. package/docs/specs/agent-ready-seo-packet-spec.md +0 -237
  43. package/docs/specs/audit-visual-demo.md +0 -309
  44. package/docs/specs/cli-agent-wiring-spec.md +0 -206
  45. package/docs/specs/local-competitive-audit-spec.md +0 -311
  46. package/docs/specs/scheduled-workflows-api-spec.md +0 -304
  47. package/docs/specs/seo-cli-growth-roadmap-spec.md +0 -181
  48. package/docs/specs/seo-workflow-runner-and-reports-spec.md +0 -241
  49. /package/dist/{chunk-BL7BBSYF.js.map → chunk-RUGJE5EB.js.map} +0 -0
  50. /package/dist/{chunk-3K5GT6VG.js.map → chunk-YGRZU7IR.js.map} +0 -0
  51. /package/dist/{site-extract-repository-U476J44K.js.map → site-extract-repository-NVSZH35Y.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  harvest,
3
3
  recordVendorUsage
4
- } from "./chunk-AUCXKRRH.js";
4
+ } from "./chunk-RMPPYKUV.js";
5
5
  import "./chunk-HPV4VOQX.js";
6
6
  import "./chunk-K443GQY5.js";
7
7
  import "./chunk-XGIPATLV.js";
@@ -18,7 +18,7 @@ import {
18
18
  resolveKernelProxyId,
19
19
  runWithCostContext,
20
20
  vendorCostUsd
21
- } from "./chunk-AUCXKRRH.js";
21
+ } from "./chunk-RMPPYKUV.js";
22
22
  import {
23
23
  HttpMcpToolExecutor,
24
24
  MemoryMcpToolExecutor,
@@ -33,7 +33,7 @@ import {
33
33
  registerSerpIntelligenceCaptureTools,
34
34
  sanitizeAttempts,
35
35
  sanitizeHarvestResult
36
- } from "./chunk-3K5GT6VG.js";
36
+ } from "./chunk-YGRZU7IR.js";
37
37
  import {
38
38
  auditImages,
39
39
  getBlobStore
@@ -67,7 +67,7 @@ import {
67
67
  RawMapsOverviewSchema,
68
68
  RawMapsReviewStatsSchema
69
69
  } from "./chunk-XGIPATLV.js";
70
- import "./chunk-F2BXETDX.js";
70
+ import "./chunk-EGWJ74EX.js";
71
71
  import {
72
72
  completeExtractJob,
73
73
  countSuccessfulPages,
@@ -78,7 +78,7 @@ import {
78
78
  saveExtractPages,
79
79
  setExtractJobTotal,
80
80
  settleExtractJob
81
- } from "./chunk-BL7BBSYF.js";
81
+ } from "./chunk-RUGJE5EB.js";
82
82
  import {
83
83
  BROWSER_OPEN_MIN_BALANCE_MC,
84
84
  CONCURRENCY_PRICE_ID,
@@ -101,7 +101,7 @@ import {
101
101
  browserActiveCostMc,
102
102
  concurrencySlotBillingInfo,
103
103
  insufficientBalanceResponse
104
- } from "./chunk-APJO2XV5.js";
104
+ } from "./chunk-HL33CGJF.js";
105
105
  import {
106
106
  CaptchaError,
107
107
  RECAPTCHA_INSTRUCTIONS,
@@ -4432,8 +4432,8 @@ async function downloadAsset(url, destDir, filename) {
4432
4432
  }
4433
4433
  const writer = createWriteStream(dest);
4434
4434
  await pipeline(Readable.fromWeb(res.body), writer);
4435
- const { statSync: statSync2 } = await import("fs");
4436
- const sizeBytes = statSync2(dest).size;
4435
+ const { statSync } = await import("fs");
4436
+ const sizeBytes = statSync(dest).size;
4437
4437
  return { savedPath: dest, sizeBytes, mimeType };
4438
4438
  }
4439
4439
  async function harvestPageMedia(html, pageUrl, options = {}) {
@@ -10734,6 +10734,12 @@ facebookAdApp.post("/search", createApiKeyAuth(), async (c) => {
10734
10734
  }
10735
10735
  }
10736
10736
  const results = [...advertiserMap.values()].sort((a, b) => b.adCount - a.adCount).slice(0, maxResults).map((a) => ({ name: a.pageName, pageName: a.pageName, libraryId: a.sampleLibraryId, sampleLibraryId: a.sampleLibraryId, adCount: a.adCount }));
10737
+ if (results.length === 0) {
10738
+ await creditMc(fbUser.id, MC_COSTS.fb_search, LedgerOperation.FB_SEARCH_REFUND, "empty result");
10739
+ searchRefunded = true;
10740
+ await logRequestEvent({ userId: fbUser.id, source: "facebook_search", status: "failed", query: body.query.trim(), error: "empty result refunded" });
10741
+ return c.json({ error: "no advertisers found (refunded)" }, 503);
10742
+ }
10737
10743
  const searchResult = { query: body.query.trim(), searchUrl, results };
10738
10744
  await logRequestEvent({ userId: fbUser.id, source: "facebook_search", status: "done", query: body.query.trim(), resultCount: results.length, result: searchResult });
10739
10745
  return c.json(searchResult);
@@ -11124,11 +11130,9 @@ googleAdsApp.post("/transcribe", createApiKeyAuth(), async (c) => {
11124
11130
  // src/api/instagram-routes.ts
11125
11131
  import { Hono as Hono7 } from "hono";
11126
11132
  import { z as z15 } from "zod";
11127
- import { createWriteStream as createWriteStream2, mkdirSync as mkdirSync2, statSync, writeFileSync } from "fs";
11128
- import { homedir as homedir2 } from "os";
11133
+ import { mkdtempSync, readFileSync as readFileSync2, rmSync, writeFileSync } from "fs";
11134
+ import { tmpdir } from "os";
11129
11135
  import { join as join4 } from "path";
11130
- import { Readable as Readable2 } from "stream";
11131
- import { pipeline as pipeline2 } from "stream/promises";
11132
11136
  import { spawn } from "child_process";
11133
11137
 
11134
11138
  // src/extractor/InstagramContentExtractor.ts
@@ -11552,20 +11556,15 @@ async function resolveInstagramLaunch(body) {
11552
11556
  }
11553
11557
  };
11554
11558
  }
11555
- function outputBaseDir2() {
11556
- return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || join4(homedir2(), "Downloads", "mcp-scraper");
11557
- }
11558
11559
  function safeFilePart(input) {
11559
11560
  return input.replace(/^https?:\/\//, "").replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "instagram";
11560
11561
  }
11561
- function mediaOutputDir(shortcode, sourceUrl) {
11562
+ function blobKeyPrefix(shortcode, sourceUrl) {
11562
11563
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
11563
11564
  const slug = shortcode ? `instagram-${shortcode}` : safeFilePart(sourceUrl);
11564
- const dir = join4(outputBaseDir2(), "instagram", `${stamp}-${slug}`);
11565
- mkdirSync2(dir, { recursive: true });
11566
- return dir;
11565
+ return `instagram/${stamp}-${slug}`;
11567
11566
  }
11568
- async function downloadToFile(url, destPath, referer) {
11567
+ async function fetchMediaBytes(url, referer) {
11569
11568
  const res = await fetch(url, {
11570
11569
  headers: {
11571
11570
  "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
@@ -11575,12 +11574,8 @@ async function downloadToFile(url, destPath, referer) {
11575
11574
  });
11576
11575
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
11577
11576
  if (!res.body) throw new Error("Empty response body");
11578
- await pipeline2(Readable2.fromWeb(res.body), createWriteStream2(destPath));
11579
- return {
11580
- savedPath: destPath,
11581
- sizeBytes: statSync(destPath).size,
11582
- mimeType: res.headers.get("content-type")?.split(";")[0]?.trim() ?? null
11583
- };
11577
+ const bytes = Buffer.from(await res.arrayBuffer());
11578
+ return { bytes, mimeType: res.headers.get("content-type")?.split(";")[0]?.trim() ?? null };
11584
11579
  }
11585
11580
  function extFromMime(mimeType, fallback) {
11586
11581
  const map = {
@@ -11699,55 +11694,65 @@ instagramApp.post("/media-download", createApiKeyAuth(), async (c) => {
11699
11694
  const mediaTypes = new Set(body.mediaTypes);
11700
11695
  const downloads = [];
11701
11696
  const warnings = [];
11702
- let outputDir = null;
11703
11697
  if (body.downloadMedia) {
11704
- outputDir = mediaOutputDir(extraction.shortcode, sourceUrl.href);
11705
- const textPath = join4(outputDir, `${extraction.shortcode ?? "instagram"}-text.txt`);
11706
- writeFileSync(textPath, [
11707
- `URL: ${extraction.pageUrl}`,
11708
- extraction.caption ? `Caption: ${extraction.caption}` : "",
11709
- "",
11710
- extraction.bodyText
11711
- ].filter(Boolean).join("\n"), "utf8");
11712
- downloads.push({ kind: "text", url: null, savedPath: textPath, sizeBytes: statSync(textPath).size, mimeType: "text/plain", error: null });
11713
- if (mediaTypes.has("image") && extraction.imageUrl) {
11714
- const imagePathBase = join4(outputDir, `${extraction.shortcode ?? "instagram"}-image`);
11715
- try {
11716
- const downloaded = await downloadToFile(extraction.imageUrl, imagePathBase, extraction.pageUrl);
11717
- const ext = extFromMime(downloaded.mimeType, "jpg");
11718
- const finalPath = downloaded.savedPath.endsWith(`.${ext}`) ? downloaded.savedPath : `${downloaded.savedPath}.${ext}`;
11719
- if (finalPath !== downloaded.savedPath) {
11720
- const { renameSync } = await import("fs");
11721
- renameSync(downloaded.savedPath, finalPath);
11698
+ let muxWorkDir = null;
11699
+ try {
11700
+ const store = getBlobStore();
11701
+ const prefix = blobKeyPrefix(extraction.shortcode, sourceUrl.href);
11702
+ const textContent = [
11703
+ `URL: ${extraction.pageUrl}`,
11704
+ extraction.caption ? `Caption: ${extraction.caption}` : "",
11705
+ "",
11706
+ extraction.bodyText
11707
+ ].filter(Boolean).join("\n");
11708
+ const storedText = await store.put(`${prefix}/text.txt`, textContent, "text/plain");
11709
+ downloads.push({ kind: "text", url: null, savedPath: storedText.url, sizeBytes: storedText.bytes, mimeType: "text/plain", error: null });
11710
+ if (mediaTypes.has("image") && extraction.imageUrl) {
11711
+ try {
11712
+ const { bytes, mimeType } = await fetchMediaBytes(extraction.imageUrl, extraction.pageUrl);
11713
+ const ext = extFromMime(mimeType, "jpg");
11714
+ const stored = await store.put(`${prefix}/image.${ext}`, bytes, mimeType ?? "application/octet-stream");
11715
+ downloads.push({ kind: "image", url: extraction.imageUrl, savedPath: stored.url, sizeBytes: stored.bytes, mimeType, error: null });
11716
+ } catch (err) {
11717
+ downloads.push({ kind: "image", url: extraction.imageUrl, savedPath: null, sizeBytes: null, mimeType: null, error: err instanceof Error ? err.message : String(err) });
11722
11718
  }
11723
- downloads.push({ kind: "image", url: extraction.imageUrl, savedPath: finalPath, sizeBytes: statSync(finalPath).size, mimeType: downloaded.mimeType, error: null });
11724
- } catch (err) {
11725
- downloads.push({ kind: "image", url: extraction.imageUrl, savedPath: null, sizeBytes: null, mimeType: null, error: err instanceof Error ? err.message : String(err) });
11726
11719
  }
11727
- }
11728
- const tracksToDownload = body.downloadAllTracks ? extraction.tracks : [extraction.selectedVideoTrack, extraction.selectedAudioTrack].filter((track) => Boolean(track));
11729
- const savedByUrl = /* @__PURE__ */ new Map();
11730
- for (const [index, track] of tracksToDownload.entries()) {
11731
- if (track.streamType === "video" && !mediaTypes.has("video")) continue;
11732
- if (track.streamType === "audio" && !mediaTypes.has("audio")) continue;
11733
- const kind = track.streamType === "audio" ? "audio" : "video";
11734
- const target = join4(outputDir, trackFilename(track, index, extraction.shortcode));
11735
- try {
11736
- const downloaded = await downloadToFile(track.url, target, extraction.pageUrl);
11737
- downloads.push({ kind, url: track.url, savedPath: downloaded.savedPath, sizeBytes: downloaded.sizeBytes, mimeType: downloaded.mimeType, error: null });
11738
- savedByUrl.set(track.url, downloaded.savedPath);
11739
- } catch (err) {
11740
- downloads.push({ kind, url: track.url, savedPath: null, sizeBytes: null, mimeType: null, error: err instanceof Error ? err.message : String(err) });
11720
+ const tracksToDownload = body.downloadAllTracks ? extraction.tracks : [extraction.selectedVideoTrack, extraction.selectedAudioTrack].filter((track) => Boolean(track));
11721
+ const muxEligible = Boolean(body.mux && mediaTypes.has("video") && mediaTypes.has("audio") && extraction.selectedVideoTrack && extraction.selectedAudioTrack);
11722
+ const muxInputs = /* @__PURE__ */ new Map();
11723
+ for (const [index, track] of tracksToDownload.entries()) {
11724
+ if (track.streamType === "video" && !mediaTypes.has("video")) continue;
11725
+ if (track.streamType === "audio" && !mediaTypes.has("audio")) continue;
11726
+ const kind = track.streamType === "audio" ? "audio" : "video";
11727
+ try {
11728
+ const { bytes, mimeType } = await fetchMediaBytes(track.url, extraction.pageUrl);
11729
+ const stored = await store.put(`${prefix}/${trackFilename(track, index, extraction.shortcode)}`, bytes, mimeType ?? "video/mp4");
11730
+ downloads.push({ kind, url: track.url, savedPath: stored.url, sizeBytes: stored.bytes, mimeType, error: null });
11731
+ const isMuxInput = muxEligible && (track.url === extraction.selectedVideoTrack.url || track.url === extraction.selectedAudioTrack.url);
11732
+ if (isMuxInput) {
11733
+ if (!muxWorkDir) muxWorkDir = mkdtempSync(join4(tmpdir(), "ig-mux-"));
11734
+ const localPath = join4(muxWorkDir, trackFilename(track, index, extraction.shortcode));
11735
+ writeFileSync(localPath, bytes);
11736
+ muxInputs.set(track.url, localPath);
11737
+ }
11738
+ } catch (err) {
11739
+ downloads.push({ kind, url: track.url, savedPath: null, sizeBytes: null, mimeType: null, error: err instanceof Error ? err.message : String(err) });
11740
+ }
11741
11741
  }
11742
- }
11743
- if (body.mux && mediaTypes.has("video") && mediaTypes.has("audio") && extraction.selectedVideoTrack && extraction.selectedAudioTrack && savedByUrl.has(extraction.selectedVideoTrack.url) && savedByUrl.has(extraction.selectedAudioTrack.url)) {
11744
- const outPath = join4(outputDir, `${extraction.shortcode ?? "instagram"}-muxed.mp4`);
11745
- const muxed = await runFfmpegMux(savedByUrl.get(extraction.selectedVideoTrack.url), savedByUrl.get(extraction.selectedAudioTrack.url), outPath);
11746
- if (muxed.ok) {
11747
- downloads.push({ kind: "muxed_video", url: null, savedPath: outPath, sizeBytes: statSync(outPath).size, mimeType: "video/mp4", error: null });
11748
- } else {
11749
- warnings.push(`Mux skipped/failed: ${muxed.error}`);
11742
+ if (muxEligible && muxWorkDir && muxInputs.has(extraction.selectedVideoTrack.url) && muxInputs.has(extraction.selectedAudioTrack.url)) {
11743
+ const outPath = join4(muxWorkDir, "muxed.mp4");
11744
+ const muxed = await runFfmpegMux(muxInputs.get(extraction.selectedVideoTrack.url), muxInputs.get(extraction.selectedAudioTrack.url), outPath);
11745
+ if (muxed.ok) {
11746
+ const stored = await store.put(`${prefix}/muxed.mp4`, readFileSync2(outPath), "video/mp4");
11747
+ downloads.push({ kind: "muxed_video", url: null, savedPath: stored.url, sizeBytes: stored.bytes, mimeType: "video/mp4", error: null });
11748
+ } else {
11749
+ warnings.push(`Mux skipped/failed: ${muxed.error}`);
11750
+ }
11750
11751
  }
11752
+ } catch (err) {
11753
+ warnings.push(`Media download unavailable: ${err instanceof Error ? err.message : String(err)}`);
11754
+ } finally {
11755
+ if (muxWorkDir) rmSync(muxWorkDir, { recursive: true, force: true });
11751
11756
  }
11752
11757
  }
11753
11758
  let transcript = null;
@@ -11770,7 +11775,7 @@ instagramApp.post("/media-download", createApiKeyAuth(), async (c) => {
11770
11775
  const result = {
11771
11776
  ...extraction,
11772
11777
  browser: launch.browser,
11773
- outputDir,
11778
+ outputDir: null,
11774
11779
  downloads,
11775
11780
  warnings,
11776
11781
  transcript
@@ -20079,7 +20084,7 @@ async function persistScrapeBody(user, opts) {
20079
20084
 
20080
20085
  // src/api/scrape-blob-cleanup.ts
20081
20086
  import { readdir, stat, unlink } from "fs/promises";
20082
- import { homedir as homedir3 } from "os";
20087
+ import { homedir as homedir2 } from "os";
20083
20088
  import { join as join6 } from "path";
20084
20089
  async function cleanupVercel(token, cutoff) {
20085
20090
  const { list, del } = await import("@vercel/blob");
@@ -20097,7 +20102,7 @@ async function cleanupVercel(token, cutoff) {
20097
20102
  return { deleted, store: "vercel-blob" };
20098
20103
  }
20099
20104
  async function cleanupLocal(cutoff) {
20100
- const baseDir = process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || join6(homedir3(), "Downloads", "mcp-scraper");
20105
+ const baseDir = process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || join6(homedir2(), "Downloads", "mcp-scraper");
20101
20106
  const dir = join6(baseDir, "blobs", SCRAPE_FALLBACK_PREFIX.replace(/\/$/, ""));
20102
20107
  let deleted = 0;
20103
20108
  let entries;
@@ -21881,7 +21886,7 @@ app.get("/cron/tick", async (c) => {
21881
21886
  if (!process.env.CRON_SECRET || secret2 !== `Bearer ${process.env.CRON_SECRET}`) {
21882
21887
  return c.json({ error: "Unauthorized" }, 401);
21883
21888
  }
21884
- const { drainQueue } = await import("./worker-KJZ3ZN2N.js");
21889
+ const { drainQueue } = await import("./worker-JQTS437L.js");
21885
21890
  const budget = { maxJobs: 10, deadlineMs: Date.now() + 28e4 };
21886
21891
  const workflowDispatchResult = await dispatchDueWorkflowSchedules(`${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`);
21887
21892
  const [results, sweepResult, reapResult, expiredResult, blobCleanup] = await Promise.all([
@@ -21899,7 +21904,7 @@ app.post("/api/internal/extract-refinalize/:id", async (c) => {
21899
21904
  return c.json({ error: "Unauthorized" }, 401);
21900
21905
  }
21901
21906
  const jobId = c.req.param("id");
21902
- const { getExtractJob: getExtractJob2, completeExtractJob: completeExtractJob2 } = await import("./site-extract-repository-U476J44K.js");
21907
+ const { getExtractJob: getExtractJob2, completeExtractJob: completeExtractJob2 } = await import("./site-extract-repository-NVSZH35Y.js");
21903
21908
  const { assembleExtractArtifacts } = await import("./extract-bundle-COS56ZDO.js");
21904
21909
  const job = await getExtractJob2(jobId);
21905
21910
  if (!job) return c.json({ error: "job not found" }, 404);
@@ -21907,7 +21912,7 @@ app.post("/api/internal/extract-refinalize/:id", async (c) => {
21907
21912
  await completeExtractJob2(jobId, stored);
21908
21913
  let settlement = "already_settled_or_refunded";
21909
21914
  if (job.billedMc == null && job.userId != null) {
21910
- const { settleExtractJob: settleExtractJob2, countSuccessfulPages: countSuccessfulPages2 } = await import("./site-extract-repository-U476J44K.js");
21915
+ const { settleExtractJob: settleExtractJob2, countSuccessfulPages: countSuccessfulPages2 } = await import("./site-extract-repository-NVSZH35Y.js");
21911
21916
  const heldMc = Number(job.options.heldMc ?? 0);
21912
21917
  const successful = await countSuccessfulPages2(jobId);
21913
21918
  const usedMc = Math.min(successful * MC_COSTS.page_scrape, heldMc);
@@ -22071,4 +22076,4 @@ app.get("/blog/:slug/", (c) => {
22071
22076
  export {
22072
22077
  app
22073
22078
  };
22074
- //# sourceMappingURL=server-WHM446IZ.js.map
22079
+ //# sourceMappingURL=server-JNY4XPZE.js.map