mcp-scraper 0.86.5 → 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-QJJQ4OAZ.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-BA6BPDSP.js";
512
+ } from "./chunk-Y3AIFO7C.js";
513
513
  import {
514
514
  CaptchaError,
515
515
  MapsSearchIncompletePageError,
@@ -26992,6 +26992,40 @@ function flatFromRecord(record7, seedQuery) {
26992
26992
  extracted_at: record7.observedAt
26993
26993
  };
26994
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
+ }
26995
27029
  var ProgressivePaaCheckpoint = class {
26996
27030
  constructor(jobId2, durableMetadata, persist, now = Date.now, initialResult) {
26997
27031
  this.jobId = jobId2;
@@ -27061,7 +27095,7 @@ var ProgressivePaaCheckpoint = class {
27061
27095
  this.sequence += 1;
27062
27096
  if (snapshot.lifecycle) this.lifecycle = { ...snapshot.lifecycle };
27063
27097
  if (snapshot.material) {
27064
- this.material = structuredClone(snapshot.material);
27098
+ this.material = mergePaaProgressMaterial(this.material, snapshot.material);
27065
27099
  this.improvementsSinceWrite += 1;
27066
27100
  }
27067
27101
  for (const question of snapshot.clickedQuestions) if (clean2(question)) this.clickedQuestions.add(clean2(question));
@@ -27166,6 +27200,7 @@ function partialTerminalResult(job, options, maxQuestions, progress, recoveryCou
27166
27200
  resultQuality: "partial",
27167
27201
  degradedResult: false,
27168
27202
  retryRecommended: true,
27203
+ pagination: material?.pagination,
27169
27204
  paaLifecycle: {
27170
27205
  ...progress.lifecycle ?? {
27171
27206
  requestedQuestions: maxQuestions,
@@ -27267,7 +27302,7 @@ async function runPaaHarvestJob(jobId2) {
27267
27302
  };
27268
27303
  const onPaaProgress = async (snapshot) => {
27269
27304
  progress.accept(snapshot);
27270
- 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";
27271
27306
  await progress.flush(snapshot.phase === "attempt_ending" ? "failed" : "expanding", { force });
27272
27307
  };
27273
27308
  const harvestCtx = currentCostContext();
@@ -27279,6 +27314,7 @@ async function runPaaHarvestJob(jobId2) {
27279
27314
  gl: options.gl ?? "us",
27280
27315
  hl: options.hl ?? "en",
27281
27316
  maxQuestions,
27317
+ pages: options.pages ?? 1,
27282
27318
  maxAttempts: DIRECT_PAA_MAX_ATTEMPTS,
27283
27319
  proxyMode: "none",
27284
27320
  forceManagedSerp: true,
@@ -27297,9 +27333,31 @@ async function runPaaHarvestJob(jobId2) {
27297
27333
  })
27298
27334
  );
27299
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
+ }
27300
27357
  progress.mergeTerminalRows(harvestResult.flat, lastAttempt, (/* @__PURE__ */ new Date()).toISOString());
27301
27358
  await progress.flush("captured", { force: true });
27302
27359
  const terminalProgress = progress.checkpoint("captured");
27360
+ const { pagination: terminalPagination, ...terminalMaterial } = terminalProgress.material ?? {};
27303
27361
  const mergedFlat = terminalProgress.records.map((record7) => flatFromRecord(record7, options.query ?? job.query));
27304
27362
  const rawDiagnostics = harvestResult.diagnostics && typeof harvestResult.diagnostics === "object" ? harvestResult.diagnostics : {};
27305
27363
  const rawCompleteness = rawDiagnostics.completeness && typeof rawDiagnostics.completeness === "object" ? rawDiagnostics.completeness : {};
@@ -27312,11 +27370,13 @@ async function runPaaHarvestJob(jobId2) {
27312
27370
  const automaticRetries = recoveryCount + terminalProgress.interruptions.filter((value) => value.willRetry).length;
27313
27371
  const result3 = {
27314
27372
  ...harvestResult,
27373
+ ...terminalMaterial,
27315
27374
  totalQuestions: mergedFlat.length,
27316
27375
  flat: mergedFlat,
27317
27376
  stats: harvestResult.stats && typeof harvestResult.stats === "object" ? { ...harvestResult.stats, totalQuestions: mergedFlat.length } : harvestResult.stats,
27318
27377
  diagnostics: {
27319
27378
  ...rawDiagnostics,
27379
+ pagination: terminalPagination ?? rawDiagnostics.pagination,
27320
27380
  resultQuality: incomplete ? "partial" : "complete",
27321
27381
  degradedResult: false,
27322
27382
  retryRecommended: discoveryStatus === "interrupted" || discoveryStatus === "recovery_exhausted",
@@ -27446,6 +27506,34 @@ function stalePartialResult(result3, records, seedQuery, recoveryCount) {
27446
27506
  const progress = current.progress && typeof current.progress === "object" ? current.progress : {};
27447
27507
  const material = progress.material && typeof progress.material === "object" ? progress.material : {};
27448
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
+ });
27449
27537
  const completeness = diagnostics.completeness && typeof diagnostics.completeness === "object" ? diagnostics.completeness : {};
27450
27538
  const flat = records.map((record7) => ({
27451
27539
  seed_query: typeof record7.seed_query === "string" ? record7.seed_query : seedQuery,
@@ -27470,7 +27558,7 @@ function stalePartialResult(result3, records, seedQuery, recoveryCount) {
27470
27558
  tree: Array.isArray(current.tree) ? current.tree : [],
27471
27559
  videos: Array.isArray(material.videos) ? material.videos : current.videos ?? [],
27472
27560
  forums: Array.isArray(material.forums) ? material.forums : current.forums ?? [],
27473
- organicResults: Array.isArray(material.organicResults) ? material.organicResults : current.organicResults ?? [],
27561
+ organicResults: reconciledOrganic,
27474
27562
  localPack: Array.isArray(material.localPack) ? material.localPack : current.localPack ?? [],
27475
27563
  whatPeopleSaying: Array.isArray(material.whatPeopleSaying) ? material.whatPeopleSaying : current.whatPeopleSaying ?? [],
27476
27564
  aiOverview: material.aiOverview ?? current.aiOverview,
@@ -27480,6 +27568,7 @@ function stalePartialResult(result3, records, seedQuery, recoveryCount) {
27480
27568
  partial: true,
27481
27569
  diagnostics: {
27482
27570
  ...diagnostics,
27571
+ pagination: keepCurrentOrganic ? diagnostics.pagination : material.pagination ?? diagnostics.pagination,
27483
27572
  completionStatus: "paa_found",
27484
27573
  problem: null,
27485
27574
  resultQuality: "partial",
@@ -86145,7 +86234,7 @@ app.get("/cron/tick", async (c) => {
86145
86234
  return c.json({ error: "Unauthorized" }, 401);
86146
86235
  }
86147
86236
  const startedAt = Date.now();
86148
- const { drainQueue } = await import("./worker-OQSFSLNG.js");
86237
+ const { drainQueue } = await import("./worker-DAVCZ3FP.js");
86149
86238
  const budget = { maxJobs: 10, deadlineMs: startedAt + CRON_TICK_DRAIN_BUDGET_MS };
86150
86239
  const origin = `${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`;
86151
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.5",
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",