mcp-scraper 0.40.2 → 0.40.3
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 +1 -1
- package/dist/bin/api-server.cjs +1517 -236
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +3 -3
- package/dist/bin/mcp-scraper-cli.cjs +1 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- package/dist/bin/mcp-scraper-install.cjs +1 -1
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.cjs +155 -87
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +6 -5
- package/dist/bin/mcp-stdio-server.js.map +1 -1
- package/dist/bin/paa-harvest.cjs +31 -9
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +4 -4
- package/dist/{chunk-XORPNO3Z.js → chunk-27DUCRAZ.js} +2 -2
- package/dist/{chunk-44HZLHDV.js → chunk-5UN33CGU.js} +38 -1
- package/dist/chunk-5UN33CGU.js.map +1 -0
- package/dist/{chunk-X2LKCX6H.js → chunk-6J57U6HA.js} +3 -3
- package/dist/{chunk-LP6E462I.js → chunk-6SZ52BQ5.js} +49 -101
- package/dist/chunk-6SZ52BQ5.js.map +1 -0
- package/dist/chunk-BBI7RGOT.js +99 -0
- package/dist/chunk-BBI7RGOT.js.map +1 -0
- package/dist/{chunk-NVXNEOUQ.js → chunk-CS4HE6QY.js} +47 -11
- package/dist/chunk-CS4HE6QY.js.map +1 -0
- package/dist/{chunk-3PIWJS6Y.js → chunk-EHES33KB.js} +2 -2
- package/dist/{chunk-GUVKHCKE.js → chunk-IQTT7CAB.js} +94 -3
- package/dist/chunk-IQTT7CAB.js.map +1 -0
- package/dist/{chunk-7XBBFBYY.js → chunk-JVIW4GK2.js} +44 -12
- package/dist/chunk-JVIW4GK2.js.map +1 -0
- package/dist/chunk-XU4ZLIB2.js +7 -0
- package/dist/chunk-XU4ZLIB2.js.map +1 -0
- package/dist/{db-W3CP562I.js → db-LVVU6NOK.js} +16 -2
- package/dist/{extract-bundle-K4PG3RZJ.js → extract-bundle-SKXEDG4Z.js} +4 -4
- package/dist/index.cjs +31 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4 -4
- package/dist/{location-data-repository-RLQX6SNM.js → location-data-repository-NBTCOA7B.js} +3 -3
- package/dist/{server-KM3CFWCF.js → server-W76RUYD3.js} +1108 -66
- package/dist/server-W76RUYD3.js.map +1 -0
- package/dist/{site-extract-repository-2SMMFKKL.js → site-extract-repository-6GX72U4N.js} +4 -4
- package/dist/{worker-FXAGFYOE.js → worker-5RWLFSAJ.js} +27 -28
- package/dist/worker-5RWLFSAJ.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-44HZLHDV.js.map +0 -1
- package/dist/chunk-7XBBFBYY.js.map +0 -1
- package/dist/chunk-GUVKHCKE.js.map +0 -1
- package/dist/chunk-LP6E462I.js.map +0 -1
- package/dist/chunk-NVXNEOUQ.js.map +0 -1
- package/dist/chunk-ZUJLSICT.js +0 -7
- package/dist/chunk-ZUJLSICT.js.map +0 -1
- package/dist/server-KM3CFWCF.js.map +0 -1
- package/dist/worker-FXAGFYOE.js.map +0 -1
- /package/dist/{chunk-XORPNO3Z.js.map → chunk-27DUCRAZ.js.map} +0 -0
- /package/dist/{chunk-X2LKCX6H.js.map → chunk-6J57U6HA.js.map} +0 -0
- /package/dist/{chunk-3PIWJS6Y.js.map → chunk-EHES33KB.js.map} +0 -0
- /package/dist/{db-W3CP562I.js.map → db-LVVU6NOK.js.map} +0 -0
- /package/dist/{extract-bundle-K4PG3RZJ.js.map → extract-bundle-SKXEDG4Z.js.map} +0 -0
- /package/dist/{location-data-repository-RLQX6SNM.js.map → location-data-repository-NBTCOA7B.js.map} +0 -0
- /package/dist/{site-extract-repository-2SMMFKKL.js.map → site-extract-repository-6GX72U4N.js.map} +0 -0
|
@@ -26,10 +26,10 @@ import {
|
|
|
26
26
|
setExtractJobTotal,
|
|
27
27
|
settleExtractJob,
|
|
28
28
|
terminalExtractJobStatus
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-6J57U6HA.js";
|
|
30
30
|
import "./chunk-SBLGBZZB.js";
|
|
31
|
-
import "./chunk-
|
|
32
|
-
import "./chunk-
|
|
31
|
+
import "./chunk-5UN33CGU.js";
|
|
32
|
+
import "./chunk-IQTT7CAB.js";
|
|
33
33
|
export {
|
|
34
34
|
abandonExtractSettlement,
|
|
35
35
|
claimFailedExtractJobForRefinalize,
|
|
@@ -59,4 +59,4 @@ export {
|
|
|
59
59
|
settleExtractJob,
|
|
60
60
|
terminalExtractJobStatus
|
|
61
61
|
};
|
|
62
|
-
//# sourceMappingURL=site-extract-repository-
|
|
62
|
+
//# sourceMappingURL=site-extract-repository-6GX72U4N.js.map
|
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
import {
|
|
2
2
|
classifyHarvestProblem,
|
|
3
3
|
createHarvestAttemptRecorder,
|
|
4
|
+
deliverWebhook,
|
|
4
5
|
harvestProblemResponse,
|
|
5
6
|
serializeHarvestProblem
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-CS4HE6QY.js";
|
|
7
8
|
import {
|
|
8
9
|
harvest
|
|
9
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-JVIW4GK2.js";
|
|
11
|
+
import {
|
|
12
|
+
sanitizeAttempts,
|
|
13
|
+
sanitizeHarvestResult
|
|
14
|
+
} from "./chunk-BBI7RGOT.js";
|
|
10
15
|
import {
|
|
11
16
|
browserServiceApiKey,
|
|
12
17
|
runWithCostContext
|
|
13
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-EHES33KB.js";
|
|
14
19
|
import "./chunk-K443GQY5.js";
|
|
15
20
|
import "./chunk-CB5C3BPB.js";
|
|
16
21
|
import {
|
|
17
22
|
MC_COSTS,
|
|
18
23
|
serpActualCostMc
|
|
19
24
|
} from "./chunk-SBLGBZZB.js";
|
|
20
|
-
import "./chunk-
|
|
25
|
+
import "./chunk-5UN33CGU.js";
|
|
21
26
|
import {
|
|
22
27
|
claimPendingJob,
|
|
23
28
|
completeJob,
|
|
@@ -25,27 +30,7 @@ import {
|
|
|
25
30
|
debitMc,
|
|
26
31
|
failJob,
|
|
27
32
|
listHarvestAttempts
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
|
|
30
|
-
// src/api/webhook.ts
|
|
31
|
-
async function deliverWebhook(url, payload, retries = 3) {
|
|
32
|
-
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
33
|
-
try {
|
|
34
|
-
const res = await fetch(url, {
|
|
35
|
-
method: "POST",
|
|
36
|
-
headers: { "content-type": "application/json" },
|
|
37
|
-
body: JSON.stringify(payload),
|
|
38
|
-
signal: AbortSignal.timeout(1e4)
|
|
39
|
-
});
|
|
40
|
-
if (res.ok) return;
|
|
41
|
-
console.warn(`[webhook] attempt ${attempt} \u2192 ${res.status} from ${url}`);
|
|
42
|
-
} catch (err) {
|
|
43
|
-
console.warn(`[webhook] attempt ${attempt} failed:`, err instanceof Error ? err.message : err);
|
|
44
|
-
}
|
|
45
|
-
if (attempt < retries) await new Promise((r) => setTimeout(r, 1e3 * attempt * 2));
|
|
46
|
-
}
|
|
47
|
-
console.error(`[webhook] gave up after ${retries} attempts for ${url}`);
|
|
48
|
-
}
|
|
33
|
+
} from "./chunk-IQTT7CAB.js";
|
|
49
34
|
|
|
50
35
|
// src/api/worker.ts
|
|
51
36
|
var MAX_CONCURRENT = 2;
|
|
@@ -89,9 +74,18 @@ async function processJob(job) {
|
|
|
89
74
|
else if (diff < 0) await debitMc(job.user_id, -diff, "serp", opts.query ?? job.query);
|
|
90
75
|
}
|
|
91
76
|
if (job.callback_url) {
|
|
92
|
-
await deliverWebhook(job.callback_url, {
|
|
77
|
+
await deliverWebhook(job.callback_url, {
|
|
78
|
+
job_id: job.id,
|
|
79
|
+
status: "done",
|
|
80
|
+
result: sanitizeHarvestResult(result),
|
|
81
|
+
attempts: sanitizeAttempts(attempts)
|
|
82
|
+
});
|
|
93
83
|
}
|
|
94
84
|
} catch (err) {
|
|
85
|
+
console.error("[harvest/worker] failed", {
|
|
86
|
+
jobId: job.id,
|
|
87
|
+
error: err instanceof Error ? err.message : String(err)
|
|
88
|
+
});
|
|
95
89
|
const problem = classifyHarvestProblem(err);
|
|
96
90
|
await failJob(job.id, serializeHarvestProblem(problem));
|
|
97
91
|
const attempts = await listHarvestAttempts(job.id, job.user_id);
|
|
@@ -103,7 +97,12 @@ async function processJob(job) {
|
|
|
103
97
|
} catch {
|
|
104
98
|
}
|
|
105
99
|
if (job.callback_url) {
|
|
106
|
-
await deliverWebhook(job.callback_url, {
|
|
100
|
+
await deliverWebhook(job.callback_url, {
|
|
101
|
+
job_id: job.id,
|
|
102
|
+
status: "failed",
|
|
103
|
+
...harvestProblemResponse(problem),
|
|
104
|
+
attempts: sanitizeAttempts(attempts)
|
|
105
|
+
});
|
|
107
106
|
}
|
|
108
107
|
} finally {
|
|
109
108
|
running--;
|
|
@@ -139,4 +138,4 @@ export {
|
|
|
139
138
|
startWorker,
|
|
140
139
|
tickOnce
|
|
141
140
|
};
|
|
142
|
-
//# sourceMappingURL=worker-
|
|
141
|
+
//# sourceMappingURL=worker-5RWLFSAJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api/worker.ts"],"sourcesContent":["import { claimPendingJob, completeJob, failJob, creditMc, debitMc, listHarvestAttempts } from './db.js'\nimport { browserServiceApiKey } from '../lib/browser-service-env.js'\nimport { harvest } from '../harvest.js'\nimport { deliverWebhook } from './webhook.js'\nimport type { HarvestOptions } from '../types.js'\nimport { MC_COSTS, serpActualCostMc } from './rates.js'\nimport { classifyHarvestProblem, harvestProblemResponse, serializeHarvestProblem } from './harvest-problems.js'\nimport { createHarvestAttemptRecorder } from './harvest-attempt-events.js'\nimport { runWithCostContext } from './cost-context.js'\nimport { sanitizeAttempts, sanitizeHarvestResult } from './outbound-sanitize.js'\n\nexport type TickResult = {\n claimed: boolean\n jobId?: string\n completed?: boolean\n durationMs?: number\n}\nexport type DrainBudget = {\n maxJobs: number\n deadlineMs: number\n}\n\nconst MAX_CONCURRENT = 2\nlet running = 0\n\nfunction countPaaQuestions(result: unknown): number {\n if (!result || typeof result !== 'object') return 0\n const value = result as { totalQuestions?: unknown; flat?: unknown }\n if (typeof value.totalQuestions === 'number') return value.totalQuestions\n return Array.isArray(value.flat) ? value.flat.length : 0\n}\n\nfunction paaCostForQuestionCount(questionCount: number): number {\n return MC_COSTS.paa_base + Math.max(1, questionCount) * MC_COSTS.paa\n}\n\nasync function processJob(job: Awaited<ReturnType<typeof claimPendingJob>> & object) {\n running++\n try {\n const opts = typeof job.options === 'string' ? JSON.parse(job.options) as Partial<HarvestOptions> & { billingHoldMc?: number } : job.options as Partial<HarvestOptions> & { billingHoldMc?: number }\n const headlessSentOut: { value: boolean | null } = { value: null }\n const result = await runWithCostContext(\n { op: opts.serpOnly ? 'serp' : 'paa', userId: Number(job.user_id), headlessSentOut },\n () => harvest({\n ...opts,\n kernelApiKey: browserServiceApiKey(),\n headless: true,\n format: 'json',\n outputDir: '/tmp/paa-output-api',\n onAttemptEvent: createHarvestAttemptRecorder(job.id, job.user_id),\n }),\n )\n await completeJob(job.id, result)\n const attempts = await listHarvestAttempts(job.id, job.user_id)\n if (!opts.serpOnly && typeof opts.billingHoldMc === 'number') {\n const actualCost = paaCostForQuestionCount(countPaaQuestions(result))\n const diff = opts.billingHoldMc - actualCost\n if (diff > 0) await creditMc(job.user_id, diff, 'paa_refund', 'overestimate refund')\n else if (diff < 0) await debitMc(job.user_id, -diff, 'paa', opts.query ?? job.query)\n } else if (opts.serpOnly && typeof opts.billingHoldMc === 'number') {\n const actualCost = serpActualCostMc(headlessSentOut.value)\n const diff = opts.billingHoldMc - actualCost\n if (diff > 0) await creditMc(job.user_id, diff, 'serp_refund', 'headless-mode pricing settle')\n else if (diff < 0) await debitMc(job.user_id, -diff, 'serp', opts.query ?? job.query)\n }\n if (job.callback_url) {\n await deliverWebhook(job.callback_url, {\n job_id: job.id,\n status: 'done',\n result: sanitizeHarvestResult(result as unknown as Record<string, unknown>),\n attempts: sanitizeAttempts(attempts),\n })\n }\n } catch (err) {\n console.error('[harvest/worker] failed', {\n jobId: job.id,\n error: err instanceof Error ? err.message : String(err),\n })\n const problem = classifyHarvestProblem(err)\n await failJob(job.id, serializeHarvestProblem(problem))\n const attempts = await listHarvestAttempts(job.id, job.user_id)\n try {\n const opts = typeof job.options === 'string' ? JSON.parse(job.options) as { billingHoldMc?: number } : job.options as { billingHoldMc?: number }\n if (typeof opts.billingHoldMc === 'number' && opts.billingHoldMc > 0) {\n await creditMc(job.user_id, opts.billingHoldMc, 'refund', 'failed call')\n }\n } catch {}\n if (job.callback_url) {\n await deliverWebhook(job.callback_url, {\n job_id: job.id,\n status: 'failed',\n ...harvestProblemResponse(problem),\n attempts: sanitizeAttempts(attempts),\n })\n }\n } finally {\n running--\n }\n}\n\nexport async function tickOnce(): Promise<TickResult> {\n const job = await claimPendingJob()\n if (!job) return { claimed: false }\n const startedAt = Date.now()\n await processJob(job as NonNullable<typeof job>)\n return { claimed: true, jobId: (job as { id: string }).id, completed: true, durationMs: Date.now() - startedAt }\n}\n\nexport async function drainQueue(budget: DrainBudget): Promise<TickResult[]> {\n const results: TickResult[] = []\n for (let i = 0; i < budget.maxJobs; i++) {\n if (Date.now() >= budget.deadlineMs) break\n const r = await tickOnce()\n results.push(r)\n if (!r.claimed) break\n }\n return results\n}\n\nexport function startWorker(): void {\n setInterval(async () => {\n if (running >= MAX_CONCURRENT) return\n const job = await claimPendingJob()\n if (job) void processJob(job as NonNullable<typeof job>)\n }, 2000)\n console.log(`[worker] started — polling every 2s, max ${MAX_CONCURRENT} concurrent`)\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts"],"sourcesContent":["export const RECAPTCHA_INSTRUCTIONS = 'Google returned a CAPTCHA. Run with --headless=false to re-warm the browser profile, then retry.'\n\nexport function sanitizeVendorName(message: string): string {\n return message\n .replace(/kernel\\.sh\\s+sessions?/gi, 'sessions')\n .replace(/kernel\\.sh\\s+session/gi, 'this session')\n .replace(/kernel\\.sh/gi, 'the service')\n .replace(/kernel\\s+sessions?/gi, 'sessions')\n .replace(/kernel\\s+session/gi, 'this session')\n .replace(/\\bkernel\\b/gi, 'the service')\n .replace(/ +/g, ' ')\n .trim()\n}\n\nexport class CaptchaError extends Error {\n readonly name = 'CaptchaError'\n constructor(public readonly instructions: string) {\n super(`CAPTCHA detected. ${instructions}`)\n }\n}\n\nexport class ExtractionError extends Error {\n readonly name = 'ExtractionError'\n constructor(message: string, public readonly cause?: unknown) {\n super(message)\n }\n}\n\n/**\n * Google Maps sometimes finishes navigation without rendering either result\n * cards or its explicit no-results message. Treating that page as a genuine\n * empty search loses data, so callers should retry it with a fresh browser (and\n * a fresh proxy when location rotation is enabled).\n */\nexport class MapsSearchIncompletePageError extends Error {\n readonly name = 'MapsSearchIncompletePageError'\n\n constructor(public readonly pageState: string) {\n super(`Google Maps search did not reach a complete result state (${pageState})`)\n }\n}\n\nexport class RequestAbortedError extends Error {\n readonly name = 'RequestAbortedError'\n constructor(message = 'Request aborted before harvest completed') {\n super(message)\n }\n}\n\nexport class LocationMismatchError extends Error {\n readonly name = 'LocationMismatchError'\n constructor(message = 'Google returned results for a different location than requested') {\n super(message)\n }\n}\n"],"mappings":";AAAO,IAAM,yBAAyB;AAE/B,SAAS,mBAAmB,SAAyB;AAC1D,SAAO,QACJ,QAAQ,4BAA4B,UAAU,EAC9C,QAAQ,0BAA0B,cAAc,EAChD,QAAQ,gBAAgB,aAAa,EACrC,QAAQ,wBAAwB,UAAU,EAC1C,QAAQ,sBAAsB,cAAc,EAC5C,QAAQ,gBAAgB,aAAa,EACrC,QAAQ,QAAQ,GAAG,EACnB,KAAK;AACV;AAEO,IAAM,eAAN,cAA2B,MAAM;AAAA,EAEtC,YAA4B,cAAsB;AAChD,UAAM,qBAAqB,YAAY,EAAE;AADf;AAAA,EAE5B;AAAA,EAF4B;AAAA,EADnB,OAAO;AAIlB;AAEO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAEzC,YAAY,SAAiC,OAAiB;AAC5D,UAAM,OAAO;AAD8B;AAAA,EAE7C;AAAA,EAF6C;AAAA,EADpC,OAAO;AAIlB;AAQO,IAAM,gCAAN,cAA4C,MAAM;AAAA,EAGvD,YAA4B,WAAmB;AAC7C,UAAM,6DAA6D,SAAS,GAAG;AADrD;AAAA,EAE5B;AAAA,EAF4B;AAAA,EAFnB,OAAO;AAKlB;AAEO,IAAM,sBAAN,cAAkC,MAAM;AAAA,EACpC,OAAO;AAAA,EAChB,YAAY,UAAU,4CAA4C;AAChE,UAAM,OAAO;AAAA,EACf;AACF;AAEO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EACtC,OAAO;AAAA,EAChB,YAAY,UAAU,mEAAmE;AACvF,UAAM,OAAO;AAAA,EACf;AACF;","names":[]}
|