mcp-scraper 0.33.6 → 0.34.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/README.md +2 -2
- package/dist/bin/api-server.cjs +13558 -12516
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +3 -3
- package/dist/bin/mcp-scraper-cli.cjs +13 -2
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +14 -4
- package/dist/bin/mcp-scraper-cli.js.map +1 -1
- package/dist/bin/mcp-scraper-install.cjs +2 -2
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +2 -2
- package/dist/bin/mcp-stdio-server.cjs +117 -7
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +7 -7
- package/dist/bin/paa-harvest.cjs +128 -13
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +4 -4
- package/dist/{chunk-DUS4ENOY.js → chunk-2EDFOQD7.js} +2 -2
- package/dist/{chunk-DUS4ENOY.js.map → chunk-2EDFOQD7.js.map} +1 -1
- package/dist/{chunk-C2OD4ELT.js → chunk-3HBPKR5G.js} +2 -2
- package/dist/{chunk-A54ELKJK.js → chunk-4KQVIYIH.js} +139 -17
- package/dist/chunk-4KQVIYIH.js.map +1 -0
- package/dist/{chunk-AIK7WQD5.js → chunk-62DQAWPF.js} +141 -3
- package/dist/chunk-62DQAWPF.js.map +1 -0
- package/dist/{chunk-V73MPRU6.js → chunk-CB5C3BPB.js} +17 -1
- package/dist/chunk-CB5C3BPB.js.map +1 -0
- package/dist/{chunk-6ZUK4H66.js → chunk-J32XSMJI.js} +117 -8
- package/dist/chunk-J32XSMJI.js.map +1 -0
- package/dist/{chunk-LKIP7VDN.js → chunk-JBSGBSGT.js} +46 -3
- package/dist/chunk-JBSGBSGT.js.map +1 -0
- package/dist/chunk-NFMIHEYE.js +7 -0
- package/dist/chunk-NFMIHEYE.js.map +1 -0
- package/dist/{chunk-XL6YIWJ3.js → chunk-SUOHUXQS.js} +3 -3
- package/dist/{chunk-WJJTGRK4.js → chunk-V36LS5YV.js} +2 -2
- package/dist/{chunk-AT2PFWHW.js → chunk-ZID3WQID.js} +2 -2
- package/dist/{db-5SZQUI7A.js → db-YAI5AQOI.js} +16 -2
- package/dist/{extract-bundle-YNXTFCC3.js → extract-bundle-GPZRLBVY.js} +2 -2
- package/dist/index.cjs +128 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -4
- package/dist/{server-SHOYO52X.js → server-LKVPEQFE.js} +1386 -778
- package/dist/server-LKVPEQFE.js.map +1 -0
- package/dist/{site-extract-repository-ZDTO7ODZ.js → site-extract-repository-JHMVHENZ.js} +4 -4
- package/dist/{worker-BJ64GCDE.js → worker-ZZHSYI3Y.js} +7 -7
- package/docs/mcp-tool-manifest.generated.json +213 -3
- package/package.json +1 -1
- package/dist/chunk-6ZUK4H66.js.map +0 -1
- package/dist/chunk-A54ELKJK.js.map +0 -1
- package/dist/chunk-AIK7WQD5.js.map +0 -1
- package/dist/chunk-F65IIUHI.js +0 -7
- package/dist/chunk-F65IIUHI.js.map +0 -1
- package/dist/chunk-LKIP7VDN.js.map +0 -1
- package/dist/chunk-V73MPRU6.js.map +0 -1
- package/dist/server-SHOYO52X.js.map +0 -1
- /package/dist/{chunk-C2OD4ELT.js.map → chunk-3HBPKR5G.js.map} +0 -0
- /package/dist/{chunk-XL6YIWJ3.js.map → chunk-SUOHUXQS.js.map} +0 -0
- /package/dist/{chunk-WJJTGRK4.js.map → chunk-V36LS5YV.js.map} +0 -0
- /package/dist/{chunk-AT2PFWHW.js.map → chunk-ZID3WQID.js.map} +0 -0
- /package/dist/{db-5SZQUI7A.js.map → db-YAI5AQOI.js.map} +0 -0
- /package/dist/{extract-bundle-YNXTFCC3.js.map → extract-bundle-GPZRLBVY.js.map} +0 -0
- /package/dist/{site-extract-repository-ZDTO7ODZ.js.map → site-extract-repository-JHMVHENZ.js.map} +0 -0
- /package/dist/{worker-BJ64GCDE.js.map → worker-ZZHSYI3Y.js.map} +0 -0
package/dist/bin/paa-harvest.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
harvest
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-4KQVIYIH.js";
|
|
5
5
|
import {
|
|
6
6
|
browserServiceApiKey
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-V36LS5YV.js";
|
|
8
8
|
import "../chunk-K443GQY5.js";
|
|
9
|
-
import "../chunk-
|
|
9
|
+
import "../chunk-CB5C3BPB.js";
|
|
10
10
|
import "../chunk-M2S27J6Z.js";
|
|
11
|
-
import "../chunk-
|
|
11
|
+
import "../chunk-62DQAWPF.js";
|
|
12
12
|
|
|
13
13
|
// src/cli.ts
|
|
14
14
|
import { Command } from "commander";
|
|
@@ -50,7 +50,7 @@ function renderInstallTerminal(options) {
|
|
|
50
50
|
"1/1 install surfaces ready",
|
|
51
51
|
colorize("Newest: any approved connection read can become an indexed Memory snapshot in one call. OAuth stays tenant-isolated and provider content is redacted and marked untrusted.", "lime", color),
|
|
52
52
|
"",
|
|
53
|
-
`${colorize("Tools", "cyan", color)} ${colorize("(
|
|
53
|
+
`${colorize("Tools", "cyan", color)} ${colorize("(166 MCP tools)", "muted", color)}`,
|
|
54
54
|
toolRow("search", ["harvest_paa", "search_serp", "maps_search", "maps_place_intel"], color),
|
|
55
55
|
toolRow("extract", ["extract_url", "map_site_urls", "extract_site", "audit_site", "directory_workflow"], color),
|
|
56
56
|
toolRow("build", ["rank_tracker_workflow", "cron plan", "database prompt"], color),
|
|
@@ -105,4 +105,4 @@ function renderInstallTerminal(options) {
|
|
|
105
105
|
export {
|
|
106
106
|
renderInstallTerminal
|
|
107
107
|
};
|
|
108
|
-
//# sourceMappingURL=chunk-
|
|
108
|
+
//# sourceMappingURL=chunk-2EDFOQD7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/install-terminal.ts"],"sourcesContent":["export interface InstallTerminalOptions {\n color?: boolean\n version: string\n apiKeyConfigured?: boolean\n}\n\ntype Tone = 'cyan' | 'lime' | 'amber' | 'red' | 'muted' | 'bold'\n\nconst CODES: Record<Tone | 'reset', string> = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n lime: '\\x1b[32m',\n amber: '\\x1b[33m',\n red: '\\x1b[31m',\n muted: '\\x1b[90m',\n bold: '\\x1b[1m',\n}\n\nfunction colorize(value: string, tone: Tone, enabled: boolean): string {\n if (!enabled) return value\n return `${CODES[tone]}${value}${CODES.reset}`\n}\n\nfunction toolRow(label: string, tools: string[], enabled: boolean): string {\n const padded = label.padEnd(9, ' ')\n return ` ${colorize(padded, 'muted', enabled)} ${tools.join(colorize(' . ', 'muted', enabled))}`\n}\n\nexport function renderInstallTerminal(options: InstallTerminalOptions): string {\n const color = options.color ?? true\n const apiKeyValue = options.apiKeyConfigured ? '$MCP_SCRAPER_API_KEY' : 'sk_live_your_key'\n const ascii = String.raw`\n __ __ ____ ____ \n| \\/ |/ ___| _ \\\n| |\\/| | | | |_) |\n| | | | |___| __/\n|_| |_|\\____|_|\n\n ____ ____ ____ _ ____ _____ ____\n/ ___| / ___| _ \\ / \\ | _ \\| ____| _ \\\n\\___ \\| | | |_) | / _ \\ | |_) | _| | |_) |\n ___) | |___| _ < / ___ \\| __/| |___| _ <\n|____/ \\____|_| \\_\\/_/ \\_\\_| |_____|_| \\_\\\n`\n\n const claudeCommand = [\n `MCP_SCRAPER_API_KEY=${apiKeyValue} npx -y -p mcp-scraper@latest \\\\`,\n ' mcp-scraper-cli agent install claude --apply',\n ].join('\\n')\n\n const codexConfig = [\n '[mcp_servers.mcp-scraper]',\n 'command = \"npx\"',\n 'args = [\"-y\", \"-p\", \"mcp-scraper@latest\", \"mcp-scraper\"]',\n `env = { MCP_SCRAPER_API_KEY = \"${apiKeyValue}\" }`,\n ].join('\\n')\n\n return [\n colorize(`mcp-scraper v${options.version}`, 'bold', color),\n colorize('> mcp-scraper-install', 'muted', color),\n colorize(ascii, 'amber', color),\n `${colorize('MCP Scraper Agent', 'cyan', color)} . v${options.version} . mcpscraper.dev`,\n '1/1 install surfaces ready',\n colorize('Newest: any approved connection read can become an indexed Memory snapshot in one call. OAuth stays tenant-isolated and provider content is redacted and marked untrusted.', 'lime', color),\n '',\n `${colorize('Tools', 'cyan', color)} ${colorize('(
|
|
1
|
+
{"version":3,"sources":["../src/install-terminal.ts"],"sourcesContent":["export interface InstallTerminalOptions {\n color?: boolean\n version: string\n apiKeyConfigured?: boolean\n}\n\ntype Tone = 'cyan' | 'lime' | 'amber' | 'red' | 'muted' | 'bold'\n\nconst CODES: Record<Tone | 'reset', string> = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n lime: '\\x1b[32m',\n amber: '\\x1b[33m',\n red: '\\x1b[31m',\n muted: '\\x1b[90m',\n bold: '\\x1b[1m',\n}\n\nfunction colorize(value: string, tone: Tone, enabled: boolean): string {\n if (!enabled) return value\n return `${CODES[tone]}${value}${CODES.reset}`\n}\n\nfunction toolRow(label: string, tools: string[], enabled: boolean): string {\n const padded = label.padEnd(9, ' ')\n return ` ${colorize(padded, 'muted', enabled)} ${tools.join(colorize(' . ', 'muted', enabled))}`\n}\n\nexport function renderInstallTerminal(options: InstallTerminalOptions): string {\n const color = options.color ?? true\n const apiKeyValue = options.apiKeyConfigured ? '$MCP_SCRAPER_API_KEY' : 'sk_live_your_key'\n const ascii = String.raw`\n __ __ ____ ____ \n| \\/ |/ ___| _ \\\n| |\\/| | | | |_) |\n| | | | |___| __/\n|_| |_|\\____|_|\n\n ____ ____ ____ _ ____ _____ ____\n/ ___| / ___| _ \\ / \\ | _ \\| ____| _ \\\n\\___ \\| | | |_) | / _ \\ | |_) | _| | |_) |\n ___) | |___| _ < / ___ \\| __/| |___| _ <\n|____/ \\____|_| \\_\\/_/ \\_\\_| |_____|_| \\_\\\n`\n\n const claudeCommand = [\n `MCP_SCRAPER_API_KEY=${apiKeyValue} npx -y -p mcp-scraper@latest \\\\`,\n ' mcp-scraper-cli agent install claude --apply',\n ].join('\\n')\n\n const codexConfig = [\n '[mcp_servers.mcp-scraper]',\n 'command = \"npx\"',\n 'args = [\"-y\", \"-p\", \"mcp-scraper@latest\", \"mcp-scraper\"]',\n `env = { MCP_SCRAPER_API_KEY = \"${apiKeyValue}\" }`,\n ].join('\\n')\n\n return [\n colorize(`mcp-scraper v${options.version}`, 'bold', color),\n colorize('> mcp-scraper-install', 'muted', color),\n colorize(ascii, 'amber', color),\n `${colorize('MCP Scraper Agent', 'cyan', color)} . v${options.version} . mcpscraper.dev`,\n '1/1 install surfaces ready',\n colorize('Newest: any approved connection read can become an indexed Memory snapshot in one call. OAuth stays tenant-isolated and provider content is redacted and marked untrusted.', 'lime', color),\n '',\n `${colorize('Tools', 'cyan', color)} ${colorize('(166 MCP tools)', 'muted', color)}`,\n toolRow('search', ['harvest_paa', 'search_serp', 'maps_search', 'maps_place_intel'], color),\n toolRow('extract', ['extract_url', 'map_site_urls', 'extract_site', 'audit_site', 'directory_workflow'], color),\n toolRow('build', ['rank_tracker_workflow', 'cron plan', 'database prompt'], color),\n toolRow('media', ['youtube_harvest', 'youtube_transcribe', 'facebook_ad_search', 'facebook_page_intel', 'facebook_ad_transcribe', 'facebook_video_transcribe', 'instagram_profile_content', 'instagram_media_download', 'reddit_thread'], color),\n toolRow('browser', ['browser_open', 'browser_profile_connect', 'browser_profile_list', 'browser_close', 'browser_screenshot', 'browser_read', 'browser_locate', 'browser_replay_mark', 'browser_replay_annotate'], color),\n toolRow('connect', ['list_service_connections', 'describe_service_connection_tool', 'import_service_connection_to_memory', 'export_connected_service_data', 'renew_connected_data_download', 'read_service_connection', 'call_service_connection_action'], color),\n toolRow('account', ['credits_info', 'reports', 'MCP resources'], color),\n toolRow('memory', ['memory-put', 'memory-get', 'memory-search', 'list-vaults', 'record-fact', 'list-scheduled-actions'], color),\n `${colorize('Workflows', 'cyan', color)} ${colorize('(MCP + CLI + API)', 'muted', color)}`,\n toolRow('route', ['workflow_list', 'workflow_suggest', 'workflow_run', 'workflow_step', 'workflow_status', 'workflow_artifact_read'], color),\n toolRow('seo', ['directory', 'agent-packet', 'competitive audit', 'map/serp comparison', 'PAA/AIO briefs', 'scheduled runs'], color),\n '',\n colorize('Usage tips:', 'amber', color),\n 'Run mcp-scraper-install for this visible card. Run mcp-scraper-cli for setup utilities and subcommands.',\n 'Run mcp-scraper in a human terminal to print this card; MCP clients get the same command as a silent stdio server.',\n 'Explicit card command: npx -y -p mcp-scraper@latest mcp-scraper-install',\n 'Hosted browser sessions use direct/no-proxy egress by default.',\n 'Customer auth setup: run browser_profile_connect, send the watch_url, let the user sign in, then call browser_profile_list until AUTHENTICATED.',\n 'Connected account ranges: call export_connected_service_data once. It handles Gmail, Calendar, Zoom, and Resend pagination; do not loop read_service_connection over individual records.',\n 'Connected account RAG: call import_service_connection_to_memory for one bounded approved read. It writes a redacted, untrusted snapshot to a stable Memory path and embeds it for search.',\n 'Stack logins / reconnect: run browser_profile_connect again with the same profile name and another domain to add accounts or refresh a login.',\n 'Start with workflow_suggest for broad jobs like market analysis, ICP research, CRO audits, brand briefs, content gaps, and AI visibility.',\n 'For MCP clients, use mcp-scraper so one install can mix SERP, Maps, browser, reports, and saved MCP resources.',\n 'If you hit the concurrency limit, add an extra slot for $5/month with mcp-scraper-cli billing concurrency checkout.',\n '',\n `${colorize('Ready.', 'lime', color)} Install the combined MCP server with one command:`,\n '',\n colorize('Setup doctor', 'amber', color),\n 'npx -y -p mcp-scraper@latest mcp-scraper-cli doctor',\n '',\n colorize('Hosted profile setup', 'amber', color),\n 'In your MCP client, call browser_profile_connect with email=\"seo@example.com\" and domain=\"chatgpt.com\".',\n 'Give the returned watch_url to the user. After they sign in, call browser_profile_list, then browser_open with the returned profile. Add more logins by calling browser_profile_connect again with the same profile and a new domain.',\n '',\n colorize('Claude Code one-command setup', 'amber', color),\n claudeCommand,\n 'Then fully exit Claude Code and open a new Claude terminal. Check with: claude mcp list',\n '',\n colorize('Codex config', 'amber', color),\n codexConfig,\n '',\n colorize('Claude Desktop Extension', 'amber', color),\n 'Download: https://mcpscraper.dev/downloads/mcp-scraper.mcpb',\n '',\n colorize('Safety note:', 'muted', color),\n 'mcp-scraper prints this card only when stdin/stdout are an interactive TTY. In MCP clients it writes only JSON-RPC to stdout.',\n 'Use --stdio or MCP_SCRAPER_FORCE_STDIO=1 to force server mode from a terminal.',\n '',\n ].join('\\n')\n}\n"],"mappings":"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","names":[]}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
finishHarvestAttempt,
|
|
8
8
|
startHarvestAttempt
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-62DQAWPF.js";
|
|
10
10
|
|
|
11
11
|
// src/api/harvest-problems.ts
|
|
12
12
|
function errorMessage(err) {
|
|
@@ -155,4 +155,4 @@ export {
|
|
|
155
155
|
harvestProblemResponse,
|
|
156
156
|
createHarvestAttemptRecorder
|
|
157
157
|
};
|
|
158
|
-
//# sourceMappingURL=chunk-
|
|
158
|
+
//# sourceMappingURL=chunk-3HBPKR5G.js.map
|
|
@@ -5,15 +5,16 @@ import {
|
|
|
5
5
|
currentCostContext,
|
|
6
6
|
recordKernelSession,
|
|
7
7
|
runWithCostContext
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-V36LS5YV.js";
|
|
9
9
|
import {
|
|
10
10
|
postToMemoryLibrary
|
|
11
11
|
} from "./chunk-K443GQY5.js";
|
|
12
12
|
import {
|
|
13
13
|
DEFAULT_PROXY_MODE,
|
|
14
14
|
HarvestOptionsSchema,
|
|
15
|
-
RawPAAItemSchema
|
|
16
|
-
|
|
15
|
+
RawPAAItemSchema,
|
|
16
|
+
recencyToTbs
|
|
17
|
+
} from "./chunk-CB5C3BPB.js";
|
|
17
18
|
import {
|
|
18
19
|
CaptchaError,
|
|
19
20
|
ExtractionError,
|
|
@@ -484,6 +485,7 @@ var BrowserDriver = class {
|
|
|
484
485
|
async navigateToSERP(query, uule, gl, hl, options) {
|
|
485
486
|
const params = new URLSearchParams({ q: query, gl, hl, pws: "0" });
|
|
486
487
|
if (options?.num) params.set("num", String(options.num));
|
|
488
|
+
if (options?.tbs) params.set("tbs", options.tbs);
|
|
487
489
|
if (uule) params.set("uule", uule);
|
|
488
490
|
const url = "https://www.google.com/search?" + params.toString();
|
|
489
491
|
const navUrl = serpArrivalUrl(url);
|
|
@@ -2050,6 +2052,7 @@ var PAAExtractor = class {
|
|
|
2050
2052
|
options.hl,
|
|
2051
2053
|
{
|
|
2052
2054
|
...options.serpOnly ? { num: 100 } : {},
|
|
2055
|
+
...recencyToTbs(options.recency) ? { tbs: recencyToTbs(options.recency) } : {},
|
|
2053
2056
|
debug: options.debug
|
|
2054
2057
|
}
|
|
2055
2058
|
);
|
|
@@ -2069,6 +2072,8 @@ var PAAExtractor = class {
|
|
|
2069
2072
|
let allOrganic2 = organicResults2;
|
|
2070
2073
|
if ((options.pages ?? 1) >= 2) {
|
|
2071
2074
|
const p2params = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, pws: "0", start: "10" });
|
|
2075
|
+
if (recencyToTbs(options.recency)) p2params.set("tbs", recencyToTbs(options.recency));
|
|
2076
|
+
if (recencyToTbs(options.recency)) p2params.set("tbs", recencyToTbs(options.recency));
|
|
2072
2077
|
if (uule) p2params.set("uule", uule);
|
|
2073
2078
|
await this.driver.navigateTo("https://www.google.com/search?" + p2params.toString());
|
|
2074
2079
|
await this.throwIfCaptcha(page, "Google SERP page 2");
|
|
@@ -2128,6 +2133,8 @@ var PAAExtractor = class {
|
|
|
2128
2133
|
let locationEvidence2 = initialLocationEvidence;
|
|
2129
2134
|
if ((options.pages ?? 1) >= 2) {
|
|
2130
2135
|
const p2params = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, pws: "0", start: "10" });
|
|
2136
|
+
if (recencyToTbs(options.recency)) p2params.set("tbs", recencyToTbs(options.recency));
|
|
2137
|
+
if (recencyToTbs(options.recency)) p2params.set("tbs", recencyToTbs(options.recency));
|
|
2131
2138
|
if (uule) p2params.set("uule", uule);
|
|
2132
2139
|
await this.driver.navigateTo("https://www.google.com/search?" + p2params.toString());
|
|
2133
2140
|
await this.throwIfCaptcha(page, "Google SERP page 2");
|
|
@@ -2194,6 +2201,7 @@ var PAAExtractor = class {
|
|
|
2194
2201
|
let locationEvidence = initialLocationEvidence;
|
|
2195
2202
|
if ((options.pages ?? 1) >= 2) {
|
|
2196
2203
|
const p2params = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, pws: "0", start: "10" });
|
|
2204
|
+
if (recencyToTbs(options.recency)) p2params.set("tbs", recencyToTbs(options.recency));
|
|
2197
2205
|
if (uule) p2params.set("uule", uule);
|
|
2198
2206
|
await this.driver.navigateTo("https://www.google.com/search?" + p2params.toString());
|
|
2199
2207
|
await this.throwIfCaptcha(page, "Google SERP page 2");
|
|
@@ -2357,7 +2365,92 @@ var ProgressReporter = class {
|
|
|
2357
2365
|
};
|
|
2358
2366
|
|
|
2359
2367
|
// src/kernel-proxy-resolver.ts
|
|
2368
|
+
import Kernel3 from "@onkernel/sdk";
|
|
2369
|
+
|
|
2370
|
+
// src/backup-proxy.ts
|
|
2371
|
+
import { randomInt } from "crypto";
|
|
2360
2372
|
import Kernel2 from "@onkernel/sdk";
|
|
2373
|
+
var BACKUP_PROXY_HOST = "pr.oxylabs.io";
|
|
2374
|
+
var BACKUP_PROXY_PORT = 7777;
|
|
2375
|
+
var BACKUP_STICKY_SESSION_MINUTES = 10;
|
|
2376
|
+
var BACKUP_LAST_RESORT_ATTEMPTS = 2;
|
|
2377
|
+
function backupProxyUsername() {
|
|
2378
|
+
const value = process.env.OXYLABS_USERNAME?.trim();
|
|
2379
|
+
return value || void 0;
|
|
2380
|
+
}
|
|
2381
|
+
function backupProxyPassword() {
|
|
2382
|
+
const value = process.env.OXYLABS_PASSWORD?.trim();
|
|
2383
|
+
return value || void 0;
|
|
2384
|
+
}
|
|
2385
|
+
function backupProxyCountry() {
|
|
2386
|
+
const value = process.env.OXYLABS_COUNTRY?.trim();
|
|
2387
|
+
return (value || "US").toUpperCase();
|
|
2388
|
+
}
|
|
2389
|
+
function backupProxyAvailable() {
|
|
2390
|
+
return Boolean(backupProxyUsername() && backupProxyPassword());
|
|
2391
|
+
}
|
|
2392
|
+
function randomStickySessionId() {
|
|
2393
|
+
let digits = "";
|
|
2394
|
+
for (let i = 0; i < 10; i++) digits += String(randomInt(0, 10));
|
|
2395
|
+
return digits;
|
|
2396
|
+
}
|
|
2397
|
+
function buildBackupUsername(opts = {}) {
|
|
2398
|
+
const user = backupProxyUsername();
|
|
2399
|
+
if (!user) return void 0;
|
|
2400
|
+
const base = user.startsWith("customer-") ? user : `customer-${user}`;
|
|
2401
|
+
const country = (opts.country?.trim() || backupProxyCountry()).toUpperCase();
|
|
2402
|
+
const sticky = opts.sticky ? `-sessid-${randomStickySessionId()}-sesstime-${BACKUP_STICKY_SESSION_MINUTES}` : "";
|
|
2403
|
+
return `${base}-cc-${country}${sticky}`;
|
|
2404
|
+
}
|
|
2405
|
+
function scrubBackupProxyText(message) {
|
|
2406
|
+
return message.replace(/pr\.oxylabs\.io(:\d+)?/gi, "backup proxy").replace(/oxylabs/gi, "backup proxy");
|
|
2407
|
+
}
|
|
2408
|
+
function backupProxyName(attemptIndex) {
|
|
2409
|
+
const stamp = `${Date.now()}-${attemptIndex ?? 0}-${Math.random().toString(36).slice(2, 8)}`;
|
|
2410
|
+
return `mcp-backup-custom-${stamp}`;
|
|
2411
|
+
}
|
|
2412
|
+
async function createBackupProxyId(kernelApiKey, opts = {}) {
|
|
2413
|
+
const username = buildBackupUsername({ sticky: opts.sticky });
|
|
2414
|
+
const password = backupProxyPassword();
|
|
2415
|
+
if (!username || !password) throw new Error("backup proxy pool is not configured");
|
|
2416
|
+
const kernel = new Kernel2({ apiKey: kernelApiKey });
|
|
2417
|
+
try {
|
|
2418
|
+
const created = await kernel.proxies.create({
|
|
2419
|
+
type: "custom",
|
|
2420
|
+
name: backupProxyName(opts.attemptIndex),
|
|
2421
|
+
protocol: "http",
|
|
2422
|
+
config: {
|
|
2423
|
+
host: BACKUP_PROXY_HOST,
|
|
2424
|
+
port: BACKUP_PROXY_PORT,
|
|
2425
|
+
username,
|
|
2426
|
+
password
|
|
2427
|
+
}
|
|
2428
|
+
});
|
|
2429
|
+
if (!created.id) throw new Error("backup proxy creation did not return a proxy id");
|
|
2430
|
+
return created.id;
|
|
2431
|
+
} catch (err) {
|
|
2432
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2433
|
+
throw new Error(scrubBackupProxyText(message));
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
async function createBackupProxyIdSafe(kernelApiKey, attemptIndex) {
|
|
2437
|
+
if (!kernelApiKey || !backupProxyAvailable()) return void 0;
|
|
2438
|
+
try {
|
|
2439
|
+
return await createBackupProxyId(kernelApiKey, { attemptIndex });
|
|
2440
|
+
} catch {
|
|
2441
|
+
return void 0;
|
|
2442
|
+
}
|
|
2443
|
+
}
|
|
2444
|
+
async function cleanupBackupProxyId(kernelApiKey, proxyId) {
|
|
2445
|
+
if (!kernelApiKey || !proxyId) return;
|
|
2446
|
+
try {
|
|
2447
|
+
const kernel = new Kernel2({ apiKey: kernelApiKey });
|
|
2448
|
+
await kernel.proxies.delete(proxyId);
|
|
2449
|
+
} catch {
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
// src/kernel-proxy-resolver.ts
|
|
2361
2454
|
var US_STATE_CODES = {
|
|
2362
2455
|
alabama: "AL",
|
|
2363
2456
|
alaska: "AK",
|
|
@@ -2455,7 +2548,7 @@ function proxyIdSuffix2(proxyId) {
|
|
|
2455
2548
|
return proxyId ? proxyId.slice(-6) : null;
|
|
2456
2549
|
}
|
|
2457
2550
|
function resolution(source, proxyMode, proxyId, target, error, disposable = false) {
|
|
2458
|
-
const proxyType = source === "disabled" ? "none" : source === "configured_fallback" ? "configured" : source === "isp_created" ? "isp" : source === "location_created" || source === "location_reused" ? "residential" : "unknown";
|
|
2551
|
+
const proxyType = source === "disabled" ? "none" : source === "configured_fallback" ? "configured" : source === "isp_created" ? "isp" : source === "backup_custom" ? "custom" : source === "location_created" || source === "location_reused" ? "residential" : "unknown";
|
|
2459
2552
|
return {
|
|
2460
2553
|
kernelProxyId: proxyId,
|
|
2461
2554
|
...disposable && proxyId ? { disposableProxyId: proxyId } : {},
|
|
@@ -2639,6 +2732,26 @@ function freshTargetCandidates(target, explicitZip, attemptIndex) {
|
|
|
2639
2732
|
out.push(withProxyName(fallbackTarget, freshProxyName(fallbackTarget.proxyName, attemptIndex)));
|
|
2640
2733
|
return out;
|
|
2641
2734
|
}
|
|
2735
|
+
async function settleCreateExhaustion(options, target, createErrors) {
|
|
2736
|
+
if (options.backupOnExhaustion && createErrors.length > 0 && options.kernelApiKey && backupProxyAvailable()) {
|
|
2737
|
+
try {
|
|
2738
|
+
const backupId = await createBackupProxyId(options.kernelApiKey, { attemptIndex: options.attemptIndex });
|
|
2739
|
+
return resolution("backup_custom", options.proxyMode, backupId, target, null, true);
|
|
2740
|
+
} catch (err) {
|
|
2741
|
+
createErrors.push(`backup: ${scrubBackupProxyText(errorText2(err))}`);
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
return resolution("configured_fallback", options.proxyMode, options.configuredKernelProxyId, target, createErrors.join(" | "));
|
|
2745
|
+
}
|
|
2746
|
+
async function resolveBackupKernelProxyId(options) {
|
|
2747
|
+
if (!options.kernelApiKey || !backupProxyAvailable()) return null;
|
|
2748
|
+
try {
|
|
2749
|
+
const backupId = await createBackupProxyId(options.kernelApiKey, { attemptIndex: options.attemptIndex });
|
|
2750
|
+
return resolution("backup_custom", options.proxyMode, backupId, null, null, true);
|
|
2751
|
+
} catch {
|
|
2752
|
+
return null;
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2642
2755
|
async function createFreshLocationProxy(kernel, options, target) {
|
|
2643
2756
|
const createErrors = [];
|
|
2644
2757
|
for (const candidate of freshTargetCandidates(target, options.proxyZip, options.attemptIndex)) {
|
|
@@ -2672,11 +2785,11 @@ async function createFreshLocationProxy(kernel, options, target) {
|
|
|
2672
2785
|
createErrors.push(`isp: ${errorText2(err)}`);
|
|
2673
2786
|
}
|
|
2674
2787
|
}
|
|
2675
|
-
return
|
|
2788
|
+
return settleCreateExhaustion(options, target, createErrors);
|
|
2676
2789
|
}
|
|
2677
2790
|
async function deleteKernelProxyId(kernelApiKey, proxyId) {
|
|
2678
2791
|
if (!kernelApiKey || !proxyId) return;
|
|
2679
|
-
const kernel = new
|
|
2792
|
+
const kernel = new Kernel3({ apiKey: kernelApiKey });
|
|
2680
2793
|
await kernel.proxies.delete(proxyId);
|
|
2681
2794
|
}
|
|
2682
2795
|
async function resolveKernelProxyId(options) {
|
|
@@ -2690,7 +2803,7 @@ async function resolveKernelProxyId(options) {
|
|
|
2690
2803
|
if (!target || !options.kernelApiKey) {
|
|
2691
2804
|
return resolution("configured_fallback", options.proxyMode, options.configuredKernelProxyId, target, target ? null : "location could not be normalized to a US city/state proxy target");
|
|
2692
2805
|
}
|
|
2693
|
-
const kernel = new
|
|
2806
|
+
const kernel = new Kernel3({ apiKey: options.kernelApiKey });
|
|
2694
2807
|
try {
|
|
2695
2808
|
const attemptIndex = options.attemptIndex ?? 0;
|
|
2696
2809
|
if (options.fresh) {
|
|
@@ -2712,7 +2825,7 @@ async function resolveKernelProxyId(options) {
|
|
|
2712
2825
|
} catch (err) {
|
|
2713
2826
|
createErrors2.push(`${escalatedTarget.state}: ${errorText2(err)}`);
|
|
2714
2827
|
}
|
|
2715
|
-
return
|
|
2828
|
+
return settleCreateExhaustion(options, escalatedTarget, createErrors2);
|
|
2716
2829
|
}
|
|
2717
2830
|
const proxies = await kernel.proxies.list();
|
|
2718
2831
|
const zip = knownZipFor(target, options.proxyZip);
|
|
@@ -2791,7 +2904,7 @@ async function resolveKernelProxyId(options) {
|
|
|
2791
2904
|
} catch (err) {
|
|
2792
2905
|
createErrors.push(`${fallbackTarget.state}: ${errorText2(err)}`);
|
|
2793
2906
|
}
|
|
2794
|
-
return
|
|
2907
|
+
return settleCreateExhaustion(options, target, createErrors);
|
|
2795
2908
|
} catch (err) {
|
|
2796
2909
|
return resolution("configured_fallback", options.proxyMode, options.configuredKernelProxyId, target, errorText2(err));
|
|
2797
2910
|
}
|
|
@@ -2956,7 +3069,9 @@ async function harvest(rawOptions) {
|
|
|
2956
3069
|
const requestedDebug = typeof raw.debug === "boolean" ? raw.debug : false;
|
|
2957
3070
|
const needsLocationEvidence = proxyMode === "location" && Boolean(proxyOpts.location);
|
|
2958
3071
|
const requestedMaxAttempts = raw.maxAttempts;
|
|
2959
|
-
const
|
|
3072
|
+
const baseMaxAttempts = typeof requestedMaxAttempts === "number" && Number.isInteger(requestedMaxAttempts) && requestedMaxAttempts >= 1 ? requestedMaxAttempts : maxAttemptsForProxyMode(proxyMode) + 1;
|
|
3073
|
+
const maxAttempts = baseMaxAttempts + (backupProxyAvailable() ? BACKUP_LAST_RESORT_ATTEMPTS : 0);
|
|
3074
|
+
const softDeadlineMs = typeof raw.softDeadlineMs === "number" ? raw.softDeadlineMs : null;
|
|
2960
3075
|
const serializer = new OutputSerializer();
|
|
2961
3076
|
let lastError = null;
|
|
2962
3077
|
let effectiveProxyMode = proxyMode;
|
|
@@ -2966,12 +3081,16 @@ async function harvest(rawOptions) {
|
|
|
2966
3081
|
const startedAtMs = Date.now();
|
|
2967
3082
|
try {
|
|
2968
3083
|
if (signal?.aborted) throw abortReason(signal);
|
|
2969
|
-
const
|
|
3084
|
+
const isBackupAttempt = i >= baseMaxAttempts;
|
|
3085
|
+
if (isBackupAttempt && softDeadlineMs !== null && Date.now() >= softDeadlineMs) break;
|
|
3086
|
+
const resolution2 = isBackupAttempt ? await resolveBackupKernelProxyId({ kernelApiKey, proxyMode: effectiveProxyMode, attemptIndex: i }) : await resolveKernelProxyId({
|
|
2970
3087
|
...proxyOpts,
|
|
2971
3088
|
proxyMode: effectiveProxyMode,
|
|
2972
3089
|
attemptIndex: i,
|
|
2973
|
-
fresh: effectiveProxyMode === "location"
|
|
3090
|
+
fresh: effectiveProxyMode === "location",
|
|
3091
|
+
backupOnExhaustion: true
|
|
2974
3092
|
});
|
|
3093
|
+
if (!resolution2) break;
|
|
2975
3094
|
const mergedAttempt = {
|
|
2976
3095
|
...raw,
|
|
2977
3096
|
kernelApiKey,
|
|
@@ -2980,7 +3099,7 @@ async function harvest(rawOptions) {
|
|
|
2980
3099
|
proxyMode: effectiveProxyMode,
|
|
2981
3100
|
debug: requestedDebug || needsLocationEvidence
|
|
2982
3101
|
};
|
|
2983
|
-
if (effectiveProxyMode === "none") mergedAttempt.kernelProxyId = void 0;
|
|
3102
|
+
if (effectiveProxyMode === "none" && !isBackupAttempt) mergedAttempt.kernelProxyId = void 0;
|
|
2984
3103
|
const attemptOptions = HarvestOptionsSchema.parse(mergedAttempt);
|
|
2985
3104
|
await emitAttemptEvent(onAttemptEvent, {
|
|
2986
3105
|
type: "started",
|
|
@@ -2999,10 +3118,8 @@ async function harvest(rawOptions) {
|
|
|
2999
3118
|
location: attemptOptions.location ?? null,
|
|
3000
3119
|
max_questions: attemptOptions.maxQuestions
|
|
3001
3120
|
}));
|
|
3002
|
-
const isHeadfulEscalation = i === maxAttempts - 1;
|
|
3003
|
-
const needHeadful = isHeadfulEscalation || !attemptOptions.serpOnly;
|
|
3004
3121
|
const baseCtx = currentCostContext();
|
|
3005
|
-
const attempt =
|
|
3122
|
+
const attempt = baseCtx ? await runWithCostContext({ ...baseCtx, forceHeadful: true }, () => extractOnce(attemptOptions, signal)) : await extractOnce(attemptOptions, signal);
|
|
3006
3123
|
if (attempt.error) {
|
|
3007
3124
|
const err = attempt.error;
|
|
3008
3125
|
const outcome = classifyAttemptError(err);
|
|
@@ -3175,8 +3292,13 @@ export {
|
|
|
3175
3292
|
serpArrivalUrl,
|
|
3176
3293
|
buildYouTubeChannelVideosUrl,
|
|
3177
3294
|
BrowserDriver,
|
|
3295
|
+
BACKUP_LAST_RESORT_ATTEMPTS,
|
|
3296
|
+
backupProxyAvailable,
|
|
3297
|
+
createBackupProxyIdSafe,
|
|
3298
|
+
cleanupBackupProxyId,
|
|
3299
|
+
resolveBackupKernelProxyId,
|
|
3178
3300
|
deleteKernelProxyId,
|
|
3179
3301
|
resolveKernelProxyId,
|
|
3180
3302
|
harvest
|
|
3181
3303
|
};
|
|
3182
|
-
//# sourceMappingURL=chunk-
|
|
3304
|
+
//# sourceMappingURL=chunk-4KQVIYIH.js.map
|