mcp-scraper 0.76.0 → 0.78.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/CHANGELOG.md +23 -0
- package/README.md +1 -1
- package/dist/{analytics-repository-AUTJK4HK.js → analytics-repository-D5LEGQG3.js} +3 -3
- package/dist/bin/api-server.js +4 -4
- package/dist/bin/mcp-scraper-cli.js +3 -3
- package/dist/bin/mcp-scraper-core.js +7 -7
- package/dist/bin/mcp-scraper-install.js +2 -2
- package/dist/bin/mcp-stdio-server.js +7 -7
- package/dist/bin/paa-harvest.js +4 -4
- package/dist/{chunk-BOGRXBH2.js → chunk-2P2ZVRPK.js} +189 -57
- package/dist/{chunk-E6Y3VCOJ.js → chunk-3PUMNEOC.js} +3 -3
- package/dist/{chunk-KIPIBPUB.js → chunk-47ZCUBM5.js} +1 -1
- package/dist/{chunk-IBQNOZ7E.js → chunk-74CCAY6T.js} +1 -1
- package/dist/{chunk-7RQULQF3.js → chunk-B6L73AO4.js} +1 -1
- package/dist/{chunk-WFQ2E4WE.js → chunk-BTQ23KCT.js} +1 -1
- package/dist/{chunk-SDX6TRJ6.js → chunk-FODYEDZK.js} +3 -3
- package/dist/{chunk-PJEEKOUM.js → chunk-FUMG43EN.js} +1 -1
- package/dist/{chunk-XSYEDC25.js → chunk-IYYRSVRQ.js} +1 -1
- package/dist/{chunk-A66DGFOU.js → chunk-KAGHJQFO.js} +1 -1
- package/dist/{chunk-CXY5WV45.js → chunk-NGLZ6UJR.js} +1 -1
- package/dist/{chunk-WEFPBAAG.js → chunk-OU4FV2RP.js} +140 -4
- package/dist/{chunk-F5TK4KMT.js → chunk-OUBH6XMY.js} +1 -1
- package/dist/{chunk-77LQV73B.js → chunk-OWF2JJKN.js} +13 -1
- package/dist/{chunk-F6MUGMRN.js → chunk-UFJJGXVO.js} +702 -165
- package/dist/{chunk-KBTUPRTF.js → chunk-VEQPA65D.js} +1 -1
- package/dist/{chunk-D2O7V2CT.js → chunk-VMWSXKUQ.js} +1 -1
- package/dist/{chunk-JNFOBQVH.js → chunk-ZUCU2A6V.js} +1 -1
- package/dist/{db-566MOHHD.js → db-TA567JLA.js} +17 -1
- package/dist/{extract-bundle-OO74L67T.js → extract-bundle-P2DTUVY3.js} +3 -3
- package/dist/{gmail-service-TIU4V5JA.js → gmail-service-HN57R2GS.js} +4 -4
- package/dist/index.cjs +714 -165
- package/dist/index.d.cts +83 -1
- package/dist/index.d.ts +83 -1
- package/dist/index.js +4 -4
- package/dist/{lead-list-enrichment-repository-WWEMJ7EN.js → lead-list-enrichment-repository-5LEWW4X7.js} +2 -2
- package/dist/{location-data-repository-H4B2BWGY.js → location-data-repository-AHKDXTEQ.js} +2 -2
- package/dist/{server-IAGYCPN6.js → server-6B2OG3NN.js} +1434 -983
- package/dist/{site-extract-repository-B47JB62U.js → site-extract-repository-XKSVXSSY.js} +2 -2
- package/dist/{worker-DR6R7J46.js → worker-2BYACLNF.js} +6 -6
- package/package.json +1 -1
|
@@ -12,13 +12,13 @@ import {
|
|
|
12
12
|
registerScheduledResultsMcpTools,
|
|
13
13
|
registerSerpIntelligenceCaptureTools,
|
|
14
14
|
resolveDeploymentProfile
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-2P2ZVRPK.js";
|
|
16
16
|
import {
|
|
17
17
|
renderInstallTerminal
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-IYYRSVRQ.js";
|
|
19
19
|
import {
|
|
20
20
|
PACKAGE_VERSION
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-ZUCU2A6V.js";
|
|
22
22
|
|
|
23
23
|
// src/mcp/stdio-runtime.ts
|
|
24
24
|
import { readFileSync } from "fs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// release-message.json
|
|
2
2
|
var release_message_default = {
|
|
3
|
-
message: "
|
|
3
|
+
message: "PAA harvests now distinguish a proven end of the question frontier from an interrupted browser, automatically resume the same durable job, and preserve captured questions, answers, AI Overview citations, and ranked SERP links."
|
|
4
4
|
};
|
|
5
5
|
|
|
6
6
|
// src/install-terminal.ts
|
|
@@ -367,6 +367,9 @@ var RequestAbortedError = class extends Error {
|
|
|
367
367
|
super(message);
|
|
368
368
|
}
|
|
369
369
|
};
|
|
370
|
+
var PaaInteractionInterruptedError = class extends Error {
|
|
371
|
+
name = "PaaInteractionInterruptedError";
|
|
372
|
+
};
|
|
370
373
|
var LocationMismatchError = class extends Error {
|
|
371
374
|
name = "LocationMismatchError";
|
|
372
375
|
constructor(message = "Google returned results for a different location than requested") {
|
|
@@ -2595,22 +2598,40 @@ async function claimPendingJob() {
|
|
|
2595
2598
|
});
|
|
2596
2599
|
return upd.rowsAffected === 0 ? void 0 : { ...job, status: "running" };
|
|
2597
2600
|
}
|
|
2601
|
+
var DURABLE_PAA_LEASE_MS = 45e3;
|
|
2598
2602
|
async function claimDurablePaaJob(id) {
|
|
2599
2603
|
const db = getDb();
|
|
2600
2604
|
const current = await getJob(id);
|
|
2601
2605
|
if (!current || current.options.executionOwner !== "direct" || current.options.serpOnly === true) return void 0;
|
|
2606
|
+
const recoveryCount = Math.max(0, Number(current.options.paaRecoveryCount ?? 0));
|
|
2602
2607
|
if (current.status === "running") return void 0;
|
|
2603
2608
|
if (current.status === "pending") {
|
|
2609
|
+
const leaseToken = randomUUID();
|
|
2610
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2611
|
+
const leaseExpiresAt = new Date(Date.now() + DURABLE_PAA_LEASE_MS).toISOString();
|
|
2604
2612
|
const updated = await db.execute({
|
|
2605
2613
|
sql: `UPDATE jobs
|
|
2606
|
-
SET status = 'running', started_at =
|
|
2614
|
+
SET status = 'running', started_at = datetime('now'), error = NULL,
|
|
2615
|
+
options = json_set(options,
|
|
2616
|
+
'$.paaLeaseToken', ?,
|
|
2617
|
+
'$.paaLeaseExpiresAt', ?,
|
|
2618
|
+
'$.paaLastDispatchAt', ?)
|
|
2607
2619
|
WHERE id = ? AND status = 'pending'`,
|
|
2608
|
-
args: [id]
|
|
2620
|
+
args: [leaseToken, leaseExpiresAt, now, id]
|
|
2609
2621
|
});
|
|
2610
2622
|
if (updated.rowsAffected === 0) return void 0;
|
|
2611
|
-
return {
|
|
2623
|
+
return {
|
|
2624
|
+
job: {
|
|
2625
|
+
...current,
|
|
2626
|
+
status: "running",
|
|
2627
|
+
started_at: now,
|
|
2628
|
+
options: { ...current.options, paaLeaseToken: leaseToken, paaLeaseExpiresAt: leaseExpiresAt, paaLastDispatchAt: now }
|
|
2629
|
+
},
|
|
2630
|
+
leaseToken,
|
|
2631
|
+
recoveryCount
|
|
2632
|
+
};
|
|
2612
2633
|
}
|
|
2613
|
-
return current;
|
|
2634
|
+
return { job: current, leaseToken: null, recoveryCount };
|
|
2614
2635
|
}
|
|
2615
2636
|
async function checkpointJob(id, result) {
|
|
2616
2637
|
const updated = await getDb().execute({
|
|
@@ -2619,6 +2640,91 @@ async function checkpointJob(id, result) {
|
|
|
2619
2640
|
});
|
|
2620
2641
|
return updated.rowsAffected === 1;
|
|
2621
2642
|
}
|
|
2643
|
+
async function checkpointDurablePaaJob(id, leaseToken, result) {
|
|
2644
|
+
const leaseExpiresAt = new Date(Date.now() + DURABLE_PAA_LEASE_MS).toISOString();
|
|
2645
|
+
const updated = await getDb().execute({
|
|
2646
|
+
sql: `UPDATE jobs SET result = ?, options = json_set(options, '$.paaLeaseExpiresAt', ?)
|
|
2647
|
+
WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,
|
|
2648
|
+
args: [JSON.stringify(result), leaseExpiresAt, id, leaseToken]
|
|
2649
|
+
});
|
|
2650
|
+
return updated.rowsAffected === 1;
|
|
2651
|
+
}
|
|
2652
|
+
async function renewDurablePaaLease(id, leaseToken) {
|
|
2653
|
+
const leaseExpiresAt = new Date(Date.now() + DURABLE_PAA_LEASE_MS).toISOString();
|
|
2654
|
+
const updated = await getDb().execute({
|
|
2655
|
+
sql: `UPDATE jobs SET options = json_set(options, '$.paaLeaseExpiresAt', ?)
|
|
2656
|
+
WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,
|
|
2657
|
+
args: [leaseExpiresAt, id, leaseToken]
|
|
2658
|
+
});
|
|
2659
|
+
return updated.rowsAffected === 1;
|
|
2660
|
+
}
|
|
2661
|
+
async function completeDurablePaaJob(id, leaseToken, result) {
|
|
2662
|
+
const updated = await getDb().execute({
|
|
2663
|
+
sql: `UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL,
|
|
2664
|
+
completed_at = datetime('now'),
|
|
2665
|
+
options = json_set(options, '$.paaLeaseExpiresAt', NULL)
|
|
2666
|
+
WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,
|
|
2667
|
+
args: [JSON.stringify(result), id, leaseToken]
|
|
2668
|
+
});
|
|
2669
|
+
return updated.rowsAffected === 1;
|
|
2670
|
+
}
|
|
2671
|
+
async function failDurablePaaJob(id, leaseToken, error, publicError) {
|
|
2672
|
+
const updated = await getDb().execute({
|
|
2673
|
+
sql: `UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now'),
|
|
2674
|
+
options = json_set(options, '$.paaLeaseExpiresAt', NULL)
|
|
2675
|
+
WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,
|
|
2676
|
+
args: [error, serializePublicErrorEnvelope(publicError), id, leaseToken]
|
|
2677
|
+
});
|
|
2678
|
+
return updated.rowsAffected === 1;
|
|
2679
|
+
}
|
|
2680
|
+
async function requeueExpiredDurablePaaJob(id, maxRecoveries) {
|
|
2681
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2682
|
+
const updated = await getDb().execute({
|
|
2683
|
+
sql: `UPDATE jobs SET status = 'pending', started_at = NULL,
|
|
2684
|
+
result = CASE WHEN json_valid(result) THEN json_set(result,
|
|
2685
|
+
'$.progress.lifecycle.discoveryStatus', 'interrupted',
|
|
2686
|
+
'$.progress.lifecycle.completionReason', 'The previous worker lease expired; the same job is recovering automatically.',
|
|
2687
|
+
'$.progress.lifecycle.automaticRetries', COALESCE(json_extract(options, '$.paaRecoveryCount'), 0) + 1)
|
|
2688
|
+
ELSE result END,
|
|
2689
|
+
options = json_set(options,
|
|
2690
|
+
'$.paaRecoveryCount', COALESCE(json_extract(options, '$.paaRecoveryCount'), 0) + 1,
|
|
2691
|
+
'$.paaLeaseToken', NULL,
|
|
2692
|
+
'$.paaLeaseExpiresAt', NULL,
|
|
2693
|
+
'$.paaRecoveryQueuedAt', ?)
|
|
2694
|
+
WHERE id = ? AND status = 'running'
|
|
2695
|
+
AND (
|
|
2696
|
+
datetime(json_extract(options, '$.paaLeaseExpiresAt')) <= datetime('now')
|
|
2697
|
+
OR (json_extract(options, '$.paaLeaseExpiresAt') IS NULL AND started_at <= datetime('now', '-15 minutes'))
|
|
2698
|
+
)
|
|
2699
|
+
AND COALESCE(json_extract(options, '$.paaRecoveryCount'), 0) < ?`,
|
|
2700
|
+
args: [now, id, Math.max(0, Math.trunc(maxRecoveries))]
|
|
2701
|
+
});
|
|
2702
|
+
return updated.rowsAffected === 1;
|
|
2703
|
+
}
|
|
2704
|
+
async function completeExpiredDurablePaaJob(id, result) {
|
|
2705
|
+
const updated = await getDb().execute({
|
|
2706
|
+
sql: `UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL, completed_at = datetime('now')
|
|
2707
|
+
WHERE id = ? AND status = 'running'
|
|
2708
|
+
AND (
|
|
2709
|
+
datetime(json_extract(options, '$.paaLeaseExpiresAt')) <= datetime('now')
|
|
2710
|
+
OR (json_extract(options, '$.paaLeaseExpiresAt') IS NULL AND started_at <= datetime('now', '-15 minutes'))
|
|
2711
|
+
)`,
|
|
2712
|
+
args: [JSON.stringify(result), id]
|
|
2713
|
+
});
|
|
2714
|
+
return updated.rowsAffected === 1;
|
|
2715
|
+
}
|
|
2716
|
+
async function failExpiredDurablePaaJob(id, error, publicError) {
|
|
2717
|
+
const updated = await getDb().execute({
|
|
2718
|
+
sql: `UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now')
|
|
2719
|
+
WHERE id = ? AND status = 'running'
|
|
2720
|
+
AND (
|
|
2721
|
+
datetime(json_extract(options, '$.paaLeaseExpiresAt')) <= datetime('now')
|
|
2722
|
+
OR (json_extract(options, '$.paaLeaseExpiresAt') IS NULL AND started_at <= datetime('now', '-15 minutes'))
|
|
2723
|
+
)`,
|
|
2724
|
+
args: [error, serializePublicErrorEnvelope(publicError), id]
|
|
2725
|
+
});
|
|
2726
|
+
return updated.rowsAffected === 1;
|
|
2727
|
+
}
|
|
2622
2728
|
async function listRecentTerminalDurablePaaJobs(limit = 25) {
|
|
2623
2729
|
const safeLimit = Math.max(1, Math.min(100, Math.floor(limit)));
|
|
2624
2730
|
const rows = await getDb().execute({
|
|
@@ -2646,6 +2752,27 @@ async function listStaleRunningDurablePaaJobs(limit = 25) {
|
|
|
2646
2752
|
});
|
|
2647
2753
|
return rows.rows.map((row) => deserialize(rowToRawJob(row)));
|
|
2648
2754
|
}
|
|
2755
|
+
async function listRecoverableDurablePaaJobs(limit = 25) {
|
|
2756
|
+
const safeLimit = Math.max(1, Math.min(100, Math.floor(limit)));
|
|
2757
|
+
const rows = await getDb().execute({
|
|
2758
|
+
sql: `SELECT * FROM jobs
|
|
2759
|
+
WHERE json_extract(options, '$.executionOwner') = 'direct'
|
|
2760
|
+
AND json_extract(options, '$.serpOnly') IS NOT 1
|
|
2761
|
+
AND (
|
|
2762
|
+
(status = 'running' AND (
|
|
2763
|
+
datetime(json_extract(options, '$.paaLeaseExpiresAt')) <= datetime('now')
|
|
2764
|
+
OR (json_extract(options, '$.paaLeaseExpiresAt') IS NULL AND started_at <= datetime('now', '-15 minutes'))
|
|
2765
|
+
))
|
|
2766
|
+
OR
|
|
2767
|
+
(status = 'pending' AND COALESCE(json_extract(options, '$.paaRecoveryCount'), 0) > 0
|
|
2768
|
+
AND datetime(COALESCE(json_extract(options, '$.paaLastDispatchAt'), '1970-01-01')) <= datetime('now', '-30 seconds'))
|
|
2769
|
+
)
|
|
2770
|
+
ORDER BY COALESCE(started_at, created_at)
|
|
2771
|
+
LIMIT ?`,
|
|
2772
|
+
args: [safeLimit]
|
|
2773
|
+
});
|
|
2774
|
+
return rows.rows.map((row) => deserialize(rowToRawJob(row)));
|
|
2775
|
+
}
|
|
2649
2776
|
async function markJobBillingSettled(id, billedMc, settledAt = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
2650
2777
|
if (!Number.isSafeInteger(billedMc) || billedMc < 0) throw new Error("job billed amount must be a non-negative integer");
|
|
2651
2778
|
const updated = await getDb().execute({
|
|
@@ -3699,6 +3826,7 @@ export {
|
|
|
3699
3826
|
ExtractionError,
|
|
3700
3827
|
MapsSearchIncompletePageError,
|
|
3701
3828
|
RequestAbortedError,
|
|
3829
|
+
PaaInteractionInterruptedError,
|
|
3702
3830
|
LocationMismatchError,
|
|
3703
3831
|
CREDIT_LOTS_EPOCH,
|
|
3704
3832
|
CORE_SCHEMA_VERSION,
|
|
@@ -3777,8 +3905,16 @@ export {
|
|
|
3777
3905
|
claimPendingJob,
|
|
3778
3906
|
claimDurablePaaJob,
|
|
3779
3907
|
checkpointJob,
|
|
3908
|
+
checkpointDurablePaaJob,
|
|
3909
|
+
renewDurablePaaLease,
|
|
3910
|
+
completeDurablePaaJob,
|
|
3911
|
+
failDurablePaaJob,
|
|
3912
|
+
requeueExpiredDurablePaaJob,
|
|
3913
|
+
completeExpiredDurablePaaJob,
|
|
3914
|
+
failExpiredDurablePaaJob,
|
|
3780
3915
|
listRecentTerminalDurablePaaJobs,
|
|
3781
3916
|
listStaleRunningDurablePaaJobs,
|
|
3917
|
+
listRecoverableDurablePaaJobs,
|
|
3782
3918
|
markJobBillingSettled,
|
|
3783
3919
|
completeJob,
|
|
3784
3920
|
completeRunningJob,
|
|
@@ -90,11 +90,23 @@ var MapsSearchOptionsSchema = z.object({
|
|
|
90
90
|
headless: z.boolean().default(true)
|
|
91
91
|
});
|
|
92
92
|
var RawPAAItemSchema = z.object({
|
|
93
|
+
questionId: z.string().min(1),
|
|
94
|
+
googleLinkId: z.string().nullable(),
|
|
95
|
+
googleEvidenceId: z.string().nullable(),
|
|
93
96
|
question: z.string().min(1),
|
|
94
97
|
answer: z.string().optional(),
|
|
95
98
|
sourceTitle: z.string().optional(),
|
|
96
99
|
sourceSite: z.string().optional(),
|
|
97
|
-
sourceCite: z.string().optional()
|
|
100
|
+
sourceCite: z.string().optional(),
|
|
101
|
+
sources: z.array(z.object({
|
|
102
|
+
title: z.string().nullable(),
|
|
103
|
+
site: z.string().nullable(),
|
|
104
|
+
url: z.string().min(1),
|
|
105
|
+
rawUrl: z.string().min(1),
|
|
106
|
+
resolvedUrl: z.string().nullable(),
|
|
107
|
+
linkType: z.enum(["plain", "google_url_redirect", "google_goto_redirect"]),
|
|
108
|
+
resolutionStatus: z.enum(["not_needed", "resolved", "unresolved", "rejected"])
|
|
109
|
+
})).default([])
|
|
98
110
|
});
|
|
99
111
|
var RawMapsOverviewSchema = z.object({
|
|
100
112
|
name: z.string().nullable(),
|