mcp-scraper 0.86.4 → 0.87.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.
@@ -240,7 +240,7 @@ import {
240
240
  serpArrivalUrl,
241
241
  validateProviderSessionId,
242
242
  withRuntimeUserAgent
243
- } from "./chunk-NH4QAH3X.js";
243
+ } from "./chunk-R2HRN2FW.js";
244
244
  import {
245
245
  ANALYTICS_REST_GENERIC_EXEMPTIONS,
246
246
  ASSISTANT_COMMAND_SCHEMA_VERSION,
@@ -388,7 +388,7 @@ import {
388
388
  transcribeMediaUrl,
389
389
  transitionAnalyticsExperiment,
390
390
  validateAnalyticsRestResponseForRequest
391
- } from "./chunk-FHLNW4L6.js";
391
+ } from "./chunk-XX6XUZQM.js";
392
392
  import {
393
393
  auditImageUrls,
394
394
  auditImages,
@@ -509,7 +509,7 @@ import {
509
509
  } from "./chunk-GGZEC22A.js";
510
510
  import {
511
511
  PACKAGE_VERSION
512
- } from "./chunk-CM62EJ3S.js";
512
+ } from "./chunk-Y3AIFO7C.js";
513
513
  import {
514
514
  CaptchaError,
515
515
  MapsSearchIncompletePageError,
@@ -21650,8 +21650,8 @@ var BLOCKED_RESOURCE_TYPES = /* @__PURE__ */ new Set(["image", "media", "font",
21650
21650
  var BLOCKED_HOSTS = /* @__PURE__ */ new Set(["styles.redditmedia.com", "preview.redd.it"]);
21651
21651
  var REQUIRED_HOSTS = /* @__PURE__ */ new Set(["external-preview.redd.it", "googletagmanager.com"]);
21652
21652
  var MAX_COMMENTS = 25;
21653
- var TELEMETRY_RETRY_DELAYS_MS = [0, 1500];
21654
- var BRIGHT_DATA_REDDIT_ATTEMPT_MS = 14e3;
21653
+ var INLINE_TELEMETRY_TIMEOUT_MS = 500;
21654
+ var BRIGHT_DATA_REDDIT_ATTEMPT_MS = 17e3;
21655
21655
  var CLEANUP_TIMEOUT_MS2 = 1e3;
21656
21656
  function remainingTimeout2(deadlineAt, maximumMs) {
21657
21657
  const remaining = deadlineAt - Date.now();
@@ -21693,18 +21693,9 @@ function isAcceptedRedditThread(thread, requestedComments) {
21693
21693
  function hashSessionId(sessionId) {
21694
21694
  return sessionId ? createHash6("sha256").update(sessionId).digest("hex").slice(0, 16) : null;
21695
21695
  }
21696
- async function sleep(ms) {
21697
- if (ms > 0) await new Promise((resolve3) => setTimeout(resolve3, ms));
21698
- }
21699
21696
  async function reconcileSession(sessionId) {
21700
21697
  if (!sessionId) return null;
21701
- let latest = null;
21702
- for (const delayMs of TELEMETRY_RETRY_DELAYS_MS) {
21703
- await sleep(delayMs);
21704
- latest = await lookupBrightDataSession(sessionId);
21705
- if (latest.lookupStatus === "complete") break;
21706
- if (latest.lookupStatus === "unavailable_credentials" || latest.lookupStatus === "invalid_payload") break;
21707
- }
21698
+ const latest = await lookupBrightDataSession(sessionId, { timeoutMs: INLINE_TELEMETRY_TIMEOUT_MS });
21708
21699
  await recordPendingBrightDataRedditUsage(sessionId, latest);
21709
21700
  return latest;
21710
21701
  }
@@ -27001,6 +26992,40 @@ function flatFromRecord(record7, seedQuery) {
27001
26992
  extracted_at: record7.observedAt
27002
26993
  };
27003
26994
  }
26995
+ function mergePaaProgressMaterial(existing, incoming) {
26996
+ if (!existing) return structuredClone(incoming);
26997
+ const merged = structuredClone(incoming);
26998
+ const keepOrganic = existing.pagination?.page2Status === "captured" && incoming.pagination?.page2Status !== "captured" || existing.pagination?.page2Status === incoming.pagination?.page2Status && existing.organicResults.length > incoming.organicResults.length || existing.organicResults.length > 0 && incoming.organicResults.length === 0;
26999
+ if (keepOrganic) {
27000
+ merged.organicResults = structuredClone(existing.organicResults);
27001
+ merged.pagination = existing.pagination ? structuredClone(existing.pagination) : incoming.pagination;
27002
+ }
27003
+ const resolvedLinks = /* @__PURE__ */ new Map();
27004
+ for (const row of [...existing.organicResults, ...incoming.organicResults]) {
27005
+ if (row.resolutionStatus !== "resolved" || !row.resolvedUrl) continue;
27006
+ for (const identity of [row.rawUrl, row.url, row.resolvedUrl]) {
27007
+ if (identity) resolvedLinks.set(identity, row);
27008
+ }
27009
+ }
27010
+ merged.organicResults = merged.organicResults.map((row) => {
27011
+ if (row.resolutionStatus !== "unresolved" && row.resolutionStatus !== void 0) return row;
27012
+ const resolved = [row.rawUrl, row.url].filter(Boolean).map((identity) => resolvedLinks.get(identity)).find(Boolean);
27013
+ if (!resolved) return row;
27014
+ return {
27015
+ ...row,
27016
+ url: resolved.url,
27017
+ resolvedUrl: resolved.resolvedUrl,
27018
+ resolutionStatus: resolved.resolutionStatus,
27019
+ domain: resolved.domain
27020
+ };
27021
+ });
27022
+ for (const key3 of ["videos", "forums", "localPack", "whatPeopleSaying"]) {
27023
+ if (!merged[key3].length && existing[key3].length) Object.assign(merged, { [key3]: structuredClone(existing[key3]) });
27024
+ }
27025
+ if (!merged.aiOverview.detected && existing.aiOverview.detected) merged.aiOverview = structuredClone(existing.aiOverview);
27026
+ if (!merged.aiMode.detected && existing.aiMode.detected) merged.aiMode = structuredClone(existing.aiMode);
27027
+ return merged;
27028
+ }
27004
27029
  var ProgressivePaaCheckpoint = class {
27005
27030
  constructor(jobId2, durableMetadata, persist, now = Date.now, initialResult) {
27006
27031
  this.jobId = jobId2;
@@ -27070,7 +27095,7 @@ var ProgressivePaaCheckpoint = class {
27070
27095
  this.sequence += 1;
27071
27096
  if (snapshot.lifecycle) this.lifecycle = { ...snapshot.lifecycle };
27072
27097
  if (snapshot.material) {
27073
- this.material = structuredClone(snapshot.material);
27098
+ this.material = mergePaaProgressMaterial(this.material, snapshot.material);
27074
27099
  this.improvementsSinceWrite += 1;
27075
27100
  }
27076
27101
  for (const question of snapshot.clickedQuestions) if (clean2(question)) this.clickedQuestions.add(clean2(question));
@@ -27175,6 +27200,7 @@ function partialTerminalResult(job, options, maxQuestions, progress, recoveryCou
27175
27200
  resultQuality: "partial",
27176
27201
  degradedResult: false,
27177
27202
  retryRecommended: true,
27203
+ pagination: material?.pagination,
27178
27204
  paaLifecycle: {
27179
27205
  ...progress.lifecycle ?? {
27180
27206
  requestedQuestions: maxQuestions,
@@ -27276,7 +27302,7 @@ async function runPaaHarvestJob(jobId2) {
27276
27302
  };
27277
27303
  const onPaaProgress = async (snapshot) => {
27278
27304
  progress.accept(snapshot);
27279
- const force = snapshot.phase === "attempt_ending" || snapshot.phase === "click_observed" || snapshot.phase === "expansion_finished";
27305
+ const force = snapshot.phase === "serp_captured" || snapshot.phase === "attempt_ending" || snapshot.phase === "click_observed" || snapshot.phase === "expansion_finished";
27280
27306
  await progress.flush(snapshot.phase === "attempt_ending" ? "failed" : "expanding", { force });
27281
27307
  };
27282
27308
  const harvestCtx = currentCostContext();
@@ -27288,6 +27314,7 @@ async function runPaaHarvestJob(jobId2) {
27288
27314
  gl: options.gl ?? "us",
27289
27315
  hl: options.hl ?? "en",
27290
27316
  maxQuestions,
27317
+ pages: options.pages ?? 1,
27291
27318
  maxAttempts: DIRECT_PAA_MAX_ATTEMPTS,
27292
27319
  proxyMode: "none",
27293
27320
  forceManagedSerp: true,
@@ -27306,9 +27333,31 @@ async function runPaaHarvestJob(jobId2) {
27306
27333
  })
27307
27334
  );
27308
27335
  const harvestResult = harvested;
27336
+ if (Array.isArray(harvested.organicResults)) {
27337
+ progress.accept({
27338
+ sequence: 0,
27339
+ observedAt: (/* @__PURE__ */ new Date()).toISOString(),
27340
+ clickedQuestions: [],
27341
+ records: [],
27342
+ phase: "attempt_ending",
27343
+ material: {
27344
+ surface: harvested.surface ?? "unknown",
27345
+ organicResults: harvested.organicResults,
27346
+ videos: harvested.videos ?? [],
27347
+ forums: harvested.forums ?? [],
27348
+ localPack: harvested.localPack ?? [],
27349
+ whatPeopleSaying: harvested.whatPeopleSaying ?? [],
27350
+ aiOverview: harvested.aiOverview ?? { detected: false, text: null, citations: [] },
27351
+ aiMode: harvested.aiMode ?? { detected: false, text: null, citations: [] },
27352
+ entityIds: harvested.entityIds ?? { entities: [], kgIds: [], cids: [], gcids: [] },
27353
+ pagination: harvested.diagnostics?.pagination
27354
+ }
27355
+ });
27356
+ }
27309
27357
  progress.mergeTerminalRows(harvestResult.flat, lastAttempt, (/* @__PURE__ */ new Date()).toISOString());
27310
27358
  await progress.flush("captured", { force: true });
27311
27359
  const terminalProgress = progress.checkpoint("captured");
27360
+ const { pagination: terminalPagination, ...terminalMaterial } = terminalProgress.material ?? {};
27312
27361
  const mergedFlat = terminalProgress.records.map((record7) => flatFromRecord(record7, options.query ?? job.query));
27313
27362
  const rawDiagnostics = harvestResult.diagnostics && typeof harvestResult.diagnostics === "object" ? harvestResult.diagnostics : {};
27314
27363
  const rawCompleteness = rawDiagnostics.completeness && typeof rawDiagnostics.completeness === "object" ? rawDiagnostics.completeness : {};
@@ -27321,11 +27370,13 @@ async function runPaaHarvestJob(jobId2) {
27321
27370
  const automaticRetries = recoveryCount + terminalProgress.interruptions.filter((value) => value.willRetry).length;
27322
27371
  const result3 = {
27323
27372
  ...harvestResult,
27373
+ ...terminalMaterial,
27324
27374
  totalQuestions: mergedFlat.length,
27325
27375
  flat: mergedFlat,
27326
27376
  stats: harvestResult.stats && typeof harvestResult.stats === "object" ? { ...harvestResult.stats, totalQuestions: mergedFlat.length } : harvestResult.stats,
27327
27377
  diagnostics: {
27328
27378
  ...rawDiagnostics,
27379
+ pagination: terminalPagination ?? rawDiagnostics.pagination,
27329
27380
  resultQuality: incomplete ? "partial" : "complete",
27330
27381
  degradedResult: false,
27331
27382
  retryRecommended: discoveryStatus === "interrupted" || discoveryStatus === "recovery_exhausted",
@@ -27455,6 +27506,34 @@ function stalePartialResult(result3, records, seedQuery, recoveryCount) {
27455
27506
  const progress = current.progress && typeof current.progress === "object" ? current.progress : {};
27456
27507
  const material = progress.material && typeof progress.material === "object" ? progress.material : {};
27457
27508
  const diagnostics = current.diagnostics && typeof current.diagnostics === "object" ? current.diagnostics : {};
27509
+ const currentPagination = diagnostics.pagination && typeof diagnostics.pagination === "object" ? diagnostics.pagination : {};
27510
+ const materialPagination = material.pagination && typeof material.pagination === "object" ? material.pagination : {};
27511
+ const currentOrganic = Array.isArray(current.organicResults) ? current.organicResults : [];
27512
+ const materialOrganic = Array.isArray(material.organicResults) ? material.organicResults : [];
27513
+ const capturesPageTwo = (pagination, rows) => pagination.requestedPages === 2 && pagination.capturedPages === 2 && pagination.page2Status === "captured" && typeof pagination.page1OrganicCount === "number" && typeof pagination.page2OrganicCount === "number" && pagination.page2OrganicCount > 0 && rows.length >= pagination.page1OrganicCount + pagination.page2OrganicCount;
27514
+ const currentCaptured = capturesPageTwo(currentPagination, currentOrganic);
27515
+ const materialCaptured = capturesPageTwo(materialPagination, materialOrganic);
27516
+ const keepCurrentOrganic = currentCaptured && !materialCaptured || currentCaptured === materialCaptured && currentOrganic.length > materialOrganic.length;
27517
+ const selectedOrganic = keepCurrentOrganic ? currentOrganic : materialOrganic.length ? materialOrganic : currentOrganic;
27518
+ const fallbackOrganic = keepCurrentOrganic ? materialOrganic : currentOrganic;
27519
+ const resolvedByIdentity = /* @__PURE__ */ new Map();
27520
+ for (const row of [...fallbackOrganic, ...selectedOrganic]) {
27521
+ if (row.resolutionStatus !== "resolved" || typeof row.resolvedUrl !== "string" || !row.resolvedUrl) continue;
27522
+ for (const identity of [row.rawUrl, row.url, row.resolvedUrl]) {
27523
+ if (typeof identity === "string" && identity) resolvedByIdentity.set(identity, row);
27524
+ }
27525
+ }
27526
+ const reconciledOrganic = selectedOrganic.map((row) => {
27527
+ if (row.resolutionStatus !== "unresolved" && row.resolutionStatus !== void 0) return row;
27528
+ const resolved = [row.rawUrl, row.url].filter((identity) => typeof identity === "string" && Boolean(identity)).map((identity) => resolvedByIdentity.get(identity)).find(Boolean);
27529
+ return resolved ? {
27530
+ ...row,
27531
+ url: resolved.url,
27532
+ resolvedUrl: resolved.resolvedUrl,
27533
+ resolutionStatus: resolved.resolutionStatus,
27534
+ domain: resolved.domain
27535
+ } : row;
27536
+ });
27458
27537
  const completeness = diagnostics.completeness && typeof diagnostics.completeness === "object" ? diagnostics.completeness : {};
27459
27538
  const flat = records.map((record7) => ({
27460
27539
  seed_query: typeof record7.seed_query === "string" ? record7.seed_query : seedQuery,
@@ -27479,7 +27558,7 @@ function stalePartialResult(result3, records, seedQuery, recoveryCount) {
27479
27558
  tree: Array.isArray(current.tree) ? current.tree : [],
27480
27559
  videos: Array.isArray(material.videos) ? material.videos : current.videos ?? [],
27481
27560
  forums: Array.isArray(material.forums) ? material.forums : current.forums ?? [],
27482
- organicResults: Array.isArray(material.organicResults) ? material.organicResults : current.organicResults ?? [],
27561
+ organicResults: reconciledOrganic,
27483
27562
  localPack: Array.isArray(material.localPack) ? material.localPack : current.localPack ?? [],
27484
27563
  whatPeopleSaying: Array.isArray(material.whatPeopleSaying) ? material.whatPeopleSaying : current.whatPeopleSaying ?? [],
27485
27564
  aiOverview: material.aiOverview ?? current.aiOverview,
@@ -27489,6 +27568,7 @@ function stalePartialResult(result3, records, seedQuery, recoveryCount) {
27489
27568
  partial: true,
27490
27569
  diagnostics: {
27491
27570
  ...diagnostics,
27571
+ pagination: keepCurrentOrganic ? diagnostics.pagination : material.pagination ?? diagnostics.pagination,
27492
27572
  completionStatus: "paa_found",
27493
27573
  problem: null,
27494
27574
  resultQuality: "partial",
@@ -40026,13 +40106,13 @@ function validateNewRecord(vault, props) {
40026
40106
  function shouldRetryMemoryRead(error) {
40027
40107
  return /deadlock|timeout|timed out|temporar|econnreset|fetch failed/i.test(error ?? "");
40028
40108
  }
40029
- function sleep2(ms) {
40109
+ function sleep(ms) {
40030
40110
  return new Promise((resolve3) => setTimeout(resolve3, ms));
40031
40111
  }
40032
40112
  async function readMemory(tool, args, token7) {
40033
40113
  let result3 = await memoryCall(tool, args, token7);
40034
40114
  for (let attempt = 1; !result3.ok && attempt < MAX_MEMORY_READ_ATTEMPTS && shouldRetryMemoryRead(result3.error); attempt += 1) {
40035
- await sleep2(attempt * 150);
40115
+ await sleep(attempt * 150);
40036
40116
  result3 = await memoryCall(tool, args, token7);
40037
40117
  }
40038
40118
  return result3;
@@ -86154,7 +86234,7 @@ app.get("/cron/tick", async (c) => {
86154
86234
  return c.json({ error: "Unauthorized" }, 401);
86155
86235
  }
86156
86236
  const startedAt = Date.now();
86157
- const { drainQueue } = await import("./worker-OQSFSLNG.js");
86237
+ const { drainQueue } = await import("./worker-DAVCZ3FP.js");
86158
86238
  const budget = { maxJobs: 10, deadlineMs: startedAt + CRON_TICK_DRAIN_BUDGET_MS };
86159
86239
  const origin = `${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`;
86160
86240
  const unfinished = [];
@@ -9,7 +9,7 @@ import {
9
9
  import "./chunk-OZJMVCDK.js";
10
10
  import {
11
11
  harvest
12
- } from "./chunk-NH4QAH3X.js";
12
+ } from "./chunk-R2HRN2FW.js";
13
13
  import {
14
14
  sanitizeAttempts,
15
15
  sanitizeHarvestResult
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-scraper",
3
- "version": "0.86.4",
3
+ "version": "0.87.0",
4
4
  "description": "MCP server for MCP Scraper web intelligence tools",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",