mcp-scraper 0.1.0 → 0.1.2
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 +5 -0
- package/dist/bin/api-server.cjs +15553 -7587
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +3 -3
- package/dist/bin/mcp-stdio-server.cjs +312 -119
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +1 -1
- package/dist/bin/paa-harvest.cjs +1537 -165
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +1 -1
- package/dist/{chunk-LXZDJJXR.js → chunk-D4CJBZBY.js} +426 -29
- package/dist/chunk-D4CJBZBY.js.map +1 -0
- package/dist/chunk-HERFK7W6.js +2781 -0
- package/dist/chunk-HERFK7W6.js.map +1 -0
- package/dist/chunk-JQKZWEON.js +1000 -0
- package/dist/chunk-JQKZWEON.js.map +1 -0
- package/dist/chunk-Y74EXABN.js +295 -0
- package/dist/chunk-Y74EXABN.js.map +1 -0
- package/dist/{db-IOYMX64U.js → db-YWCNHBLH.js} +36 -4
- package/dist/index.cjs +1660 -237
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +169 -2
- package/dist/index.d.ts +169 -2
- package/dist/index.js +120 -69
- package/dist/index.js.map +1 -1
- package/dist/server-W5NWH5KF.js +11625 -0
- package/dist/server-W5NWH5KF.js.map +1 -0
- package/dist/{worker-3ECJHPRE.js → worker-D4D2YQTA.js} +44 -9
- package/dist/worker-D4D2YQTA.js.map +1 -0
- package/package.json +17 -5
- package/dist/chunk-4API3ZCT.js +0 -1387
- package/dist/chunk-4API3ZCT.js.map +0 -1
- package/dist/chunk-LXZDJJXR.js.map +0 -1
- package/dist/chunk-ZBP4RHNW.js +0 -805
- package/dist/chunk-ZBP4RHNW.js.map +0 -1
- package/dist/server-63DR2HE5.js +0 -6062
- package/dist/server-63DR2HE5.js.map +0 -1
- package/dist/worker-3ECJHPRE.js.map +0 -1
- /package/dist/{db-IOYMX64U.js.map → db-YWCNHBLH.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli.ts","../../src/schemas.ts","../../src/driver/BrowserDriver.ts","../../src/selectors.ts","../../src/errors.ts","../../src/locations.ts","../../src/uule.ts","../../src/lib/paa-answer-cleanup.ts","../../src/extractor/PAAExtractor.ts","../../src/output/OutputSerializer.ts","../../src/output/ProgressReporter.ts","../../src/harvest.ts","../../bin/paa-harvest.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { harvest } from './harvest.js'\n\nconst program = new Command()\n\nprogram\n .name('paa-harvest')\n .description('Recursively extract Google People Also Ask questions')\n .requiredOption('-q, --query <query>', 'Seed query')\n .option('-l, --location <location>', 'Location name (e.g. \"austin\" or \"Austin,Texas,United States\")')\n .option('--gl <gl>', 'Google country code', 'us')\n .option('--hl <hl>', 'Google language code', 'en')\n .option('-d, --depth <depth>', 'BFS depth (1-30)', '3')\n .option('-m, --max-questions <n>', 'Max questions to harvest', '100')\n .option('-o, --output <dir>', 'Output directory', './paa-output')\n .option('-f, --format <format>', 'Output format: json, csv, or both', 'both')\n .option('--headless', 'Run browser in headless mode', false)\n .option('--profile <dir>', 'Persistent browser profile directory')\n .option('--proxy <url>', 'Proxy server URL')\n .option('--kernel-api-key <key>', 'Kernel.sh API key (or set KERNEL_API_KEY env var)')\n .action(async (opts) => {\n try {\n const result = await harvest({\n query: opts.query,\n location: opts.location,\n gl: opts.gl,\n hl: opts.hl,\n depth: parseInt(opts.depth, 10),\n maxQuestions: parseInt(opts.maxQuestions, 10),\n outputDir: opts.output,\n format: opts.format,\n headless: opts.headless,\n profileDir: opts.profile,\n proxy: opts.proxy,\n kernelApiKey: opts.kernelApiKey ?? process.env.KERNEL_API_KEY,\n })\n console.log(JSON.stringify({ totalQuestions: result.totalQuestions, outputDir: result.stats.seed }))\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n })\n\nexport async function runCli(): Promise<void> {\n await program.parseAsync()\n}\n","import { z } from 'zod'\n\nexport const HarvestOptionsSchema = z.object({\n query: z.string().min(1),\n location: z.string().optional(),\n gl: z.string().length(2).default('us'),\n hl: z.string().length(2).default('en'),\n depth: z.number().int().min(1).max(30).default(3),\n maxQuestions: z.number().int().min(1).max(1000).default(100),\n headless: z.boolean().default(false),\n profileDir: z.string().optional(),\n proxy: z.string().url().optional(),\n kernelApiKey: z.string().optional(),\n kernelProxyId: z.string().optional(),\n outputDir: z.string().default('./paa-output'),\n format: z.enum(['json', 'csv', 'both']).default('both'),\n serpOnly: z.boolean().default(false),\n pages: z.number().int().min(1).max(2).default(1),\n})\n\nexport const MapsPlaceOptionsSchema = z.object({\n businessName: z.string().min(1),\n location: z.string().min(1),\n gl: z.string().length(2).default('us'),\n hl: z.string().length(2).default('en'),\n includeReviews: z.boolean().default(false),\n maxReviews: z.number().int().min(1).max(500).default(50),\n kernelApiKey: z.string().optional(),\n kernelProxyId: z.string().optional(),\n headless: z.boolean().default(true),\n})\n\nexport const RawPAAItemSchema = z.object({\n question: z.string().min(1),\n answer: z.string().optional(),\n sourceTitle: z.string().optional(),\n sourceSite: z.string().optional(),\n sourceCite: z.string().optional(),\n})\n","import { chromium } from 'playwright-extra'\nimport StealthPlugin from 'puppeteer-extra-plugin-stealth'\nimport { chromium as playwrightChromium } from 'playwright'\nimport type { Browser, BrowserContext, Page } from 'playwright'\nimport Kernel from '@onkernel/sdk'\nimport { PAASelectors } from '../selectors.js'\nimport { CaptchaError, ExtractionError, RECAPTCHA_INSTRUCTIONS } from '../errors.js'\nimport type { DriverConfig, UuleString } from '../types.js'\nimport type { IBrowserDriver } from './IBrowserDriver.js'\n\nchromium.use(StealthPlugin())\n\nconst DESKTOP_USER_AGENT =\n 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'\n\nexport function buildYouTubeChannelVideosUrl(channelInput: string): string {\n const raw = channelInput.trim()\n if (!raw) throw new Error('channelHandle is required')\n\n const urlLike = /^https?:\\/\\//i.test(raw) || /^(www\\.|m\\.)?youtube\\.com\\//i.test(raw)\n if (urlLike) {\n const parsed = new URL(/^https?:\\/\\//i.test(raw) ? raw : `https://${raw}`)\n const host = parsed.hostname.replace(/^www\\./, '').replace(/^m\\./, '').toLowerCase()\n if (host !== 'youtube.com') throw new Error('channel URL must be on youtube.com')\n\n const segments = parsed.pathname.split('/').filter(Boolean)\n const first = segments[0] ?? ''\n const second = segments[1] ?? ''\n\n if (first.startsWith('@')) return `https://www.youtube.com/${first}/videos`\n if (first === 'channel' && second) return `https://www.youtube.com/channel/${second}/videos`\n if ((first === 'c' || first === 'user') && second) return `https://www.youtube.com/${first}/${second}/videos`\n\n throw new Error('channel URL must be a YouTube handle, /channel/UC..., /c/..., or /user/... URL')\n }\n\n const stripped = raw.replace(/^\\/+/, '').replace(/\\/+$/, '')\n const withoutVideos = stripped.replace(/\\/videos$/i, '')\n if (/^UC[\\w-]{20,}$/.test(withoutVideos)) {\n return `https://www.youtube.com/channel/${withoutVideos}/videos`\n }\n\n const handle = withoutVideos.startsWith('@') ? withoutVideos : `@${withoutVideos}`\n if (!/^@[\\w.-]+$/.test(handle)) {\n throw new Error('channelHandle must be an @handle, UC channel ID, or YouTube channel URL')\n }\n return `https://www.youtube.com/${handle}/videos`\n}\n\nexport class BrowserDriver implements IBrowserDriver {\n private browser: Browser | null = null\n private context: BrowserContext | null = null\n private page: Page | null = null\n private kernelClient: Kernel | null = null\n private kernelSessionId: string | null = null\n\n async launch(config: DriverConfig): Promise<void> {\n if (config.kernelApiKey) {\n this.kernelClient = new Kernel({ apiKey: config.kernelApiKey })\n const kernelBrowser = await this.kernelClient.browsers.create({\n stealth: true,\n timeout_seconds: 600,\n ...(config.kernelProxyId ? { proxy_id: config.kernelProxyId } : {}),\n })\n this.kernelSessionId = kernelBrowser.session_id\n this.browser = await playwrightChromium.connectOverCDP(kernelBrowser.cdp_ws_url)\n this.context = this.browser.contexts()[0] ?? await this.browser.newContext()\n await this.installEsbuildHelperShims(this.context)\n this.page = this.context.pages()[0] ?? await this.context.newPage()\n return\n }\n\n const launchOpts = {\n headless: config.headless,\n proxy: config.proxy ? { server: config.proxy } : undefined,\n }\n const ctxOpts = {\n viewport: config.viewport,\n locale: config.locale,\n userAgent: DESKTOP_USER_AGENT,\n }\n if (config.profileDir) {\n this.context = await chromium.launchPersistentContext(config.profileDir, {\n ...launchOpts,\n ...ctxOpts,\n })\n await this.installEsbuildHelperShims(this.context)\n this.page = await this.context.newPage()\n } else {\n this.browser = await chromium.launch(launchOpts)\n this.context = await this.browser.newContext(ctxOpts)\n await this.installEsbuildHelperShims(this.context)\n this.page = await this.context.newPage()\n }\n }\n\n private async installEsbuildHelperShims(context: BrowserContext): Promise<void> {\n await context.addInitScript(() => {\n const g = globalThis as Record<string, unknown>\n if (typeof g.__name !== 'function') g.__name = (fn: unknown) => fn\n if (typeof g.__publicField !== 'function') g.__publicField = (obj: Record<string, unknown>, key: string, value: unknown) => { obj[key] = value; return value }\n })\n }\n\n async navigateToSERP(\n query: string,\n uule: UuleString | null,\n gl: string,\n hl: string,\n ): Promise<{ hasPaa: boolean }> {\n const params = new URLSearchParams({ q: query, gl, hl })\n if (uule) params.set('uule', uule)\n const url = 'https://www.google.com/search?' + params.toString()\n\n try {\n await this.page!.goto(url, { waitUntil: 'domcontentloaded', timeout: 45_000 })\n } catch (err) {\n const diag = await this.captureDiagnostics(url)\n throw new ExtractionError(`page.goto failed: ${(err as Error).message} | ${diag}`)\n }\n\n const captchaCount = await this.page!.locator(PAASelectors.captchaMarker).count()\n if (captchaCount > 0) {\n if (this.kernelClient) {\n try {\n await this.page!.waitForSelector(PAASelectors.container, { timeout: 45_000 })\n return { hasPaa: true }\n } catch {\n throw new CaptchaError(this.captchaMessage())\n }\n }\n throw new CaptchaError(this.captchaMessage())\n }\n\n const fastFound = await this.page!.waitForSelector(PAASelectors.item, { timeout: 4_000 }).catch(() => null)\n if (fastFound) return { hasPaa: true }\n\n const captchaAfter = await this.page!.locator(PAASelectors.captchaMarker).count()\n if (captchaAfter > 0) throw new CaptchaError(this.captchaMessage())\n\n for (let i = 1; i <= 6; i++) {\n await this.page!.evaluate((f: number) => { window.scrollTo(0, document.body.scrollHeight * f) }, i / 6)\n await this.page!.waitForTimeout(600)\n const count = await this.page!.locator(PAASelectors.item).count()\n if (count > 0) return { hasPaa: true }\n }\n\n return { hasPaa: false }\n }\n\n private async captureDiagnostics(intendedUrl: string): Promise<string> {\n try {\n const finalUrl = this.page!.url()\n const title = await this.page!.title().catch(() => '')\n const bodySnippet = await this.page!.evaluate(() => {\n const t = (document.body?.innerText ?? '').replace(/\\s+/g, ' ').trim()\n return t.slice(0, 400)\n }).catch(() => '')\n const consent = /consent\\.google\\./.test(finalUrl) || /before you continue/i.test(bodySnippet)\n const recaptcha = /recaptcha|unusual traffic|are you a robot/i.test(bodySnippet)\n const flags = [\n consent ? 'CONSENT_WALL' : '',\n recaptcha ? 'BOT_CHALLENGE' : '',\n finalUrl !== intendedUrl ? 'REDIRECTED' : '',\n ].filter(Boolean).join(',')\n return `intended=${intendedUrl} | final=${finalUrl} | title=\"${title}\" | flags=[${flags}] | body=\"${bodySnippet}\"`\n } catch (e) {\n return `diagnostics-failed: ${(e as Error).message}`\n }\n }\n\n private captchaMessage(): string {\n return this.kernelClient\n ? 'Google returned a CAPTCHA on this Kernel.sh session — retrying with a fresh session.'\n : RECAPTCHA_INSTRUCTIONS\n }\n\n async navigateTo(url: string): Promise<void> {\n try {\n await this.page!.goto(url, { waitUntil: 'domcontentloaded', timeout: 45_000 })\n } catch (err) {\n const diag = await this.captureDiagnostics(url)\n throw new ExtractionError(`page.goto failed: ${(err as Error).message} | ${diag}`)\n }\n }\n\n async navigateToChannel(channelHandle: string): Promise<void> {\n const url = buildYouTubeChannelVideosUrl(channelHandle)\n try {\n await this.page!.goto(url, { waitUntil: 'networkidle', timeout: 30_000 })\n } catch (err) {\n const diag = await this.captureDiagnostics(url)\n throw new ExtractionError(`navigateToChannel failed: ${(err as Error).message} | ${diag}`)\n }\n }\n\n async evaluate<T>(fn: (...args: unknown[]) => T | Promise<T>, arg?: unknown): Promise<T> {\n return (this.page! as { evaluate(fn: unknown, arg?: unknown): Promise<T> }).evaluate(fn, arg)\n }\n\n getPage(): Page {\n return this.page!\n }\n\n async close(): Promise<void> {\n if (this.browser) {\n const b = this.browser\n const sessionId = this.kernelSessionId\n const client = this.kernelClient\n this.browser = null\n this.context = null\n this.page = null\n this.kernelSessionId = null\n this.kernelClient = null\n try {\n await b.close()\n } finally {\n if (client && sessionId) {\n await client.browsers.deleteByID(sessionId).catch((err: unknown) =>\n console.warn('Kernel session cleanup failed:', err)\n )\n }\n }\n } else if (this.context) {\n const ctx = this.context\n this.context = null\n this.page = null\n await ctx.close()\n }\n }\n}\n","export const PAASelectors = {\n container: '.eJH8qe.adDDi',\n dataInitq: '[data-initq]',\n item: '.related-question-pair',\n itemDataQ: 'data-q',\n itemDataInitQ: 'data-initq',\n itemQuestionEl: '.JlqpRe',\n answerContainer: '.bCOlv',\n sourceTitle: 'h3',\n sourceSite: '.VuuXrf',\n sourceCite: 'cite',\n clickTarget: '.JlqpRe',\n expandedClass: 'aoRk1c',\n captchaMarker: '#captcha-form, #recaptcha, form[action*=\"/sorry/\"], .g-recaptcha, [data-sitekey]',\n} as const\n\nexport const VideoSelectors = {\n container: 'div[jscontroller=\"HWk0Gf\"]',\n sectionHeading: '.mgAbYb[role=\"heading\"]',\n item: 'a.rIRoqf',\n} as const\n\nexport const ShortVideoSelectors = {\n udm: '39',\n item: 'a.rIRoqf',\n durationPattern: /^\\d+:\\d+$/,\n platforms: ['YouTube', 'TikTok', 'Instagram', 'Facebook', 'X'],\n} as const\n\nexport const ForumSelectors = {\n section: '.ULSxyf',\n item: 'a.KYg7td.INpicf',\n title: '.hyYc0c',\n source: '.K4ETW',\n} as const\n\nexport const WhatPeopleSayingSelectors = {\n sectionTag: 'g-section-with-header',\n sectionHeadingText: 'What people are saying',\n card: '.dRzkFf[role=\"listitem\"]',\n cardLink: 'a.WlydOe[jsname=\"YKoRaf\"]',\n titleH1: 'h1.WQWxe',\n titleDiv: '.eAaXgc',\n popularCommentLabel: '.qgdis',\n source: '.sTl1Td',\n platformBadge: '.appd0, .KrMNbf',\n ytChannel: '.sjVJQd',\n ytDate: '.PLq9Je',\n authorNote: '.nDgy9d',\n} as const\n\nexport const AIOverviewSelectors = {\n root: '[data-hveid=\"CBMQAA\"]',\n wrapper: '.Fgyi2e',\n citations: '.Fgyi2e [data-hveid] a[jsname=\"pxBnId\"]',\n} as const\n\nexport const AIModeSelectors = {\n root: '[data-hveid=\"CAUQAA\"]',\n wrapper: '.Fgyi2e',\n citations: '.Fgyi2e [data-hveid] a[jsname=\"pxBnId\"]',\n} as const\n\nexport const OrganicSelectors = {\n result: '.wHYlTd.tF2Cxc',\n title: 'h3.LC20lb',\n siteName: '.VuuXrf',\n cite: 'cite.tjvcx',\n snippet: '.VwiC3b',\n redditCite: 'cite.qLRx3b',\n ratingWrap: '.Y0A0hc',\n ratingValue: '.yi40Hd',\n reviewCount: '.RDApEe',\n} as const\n\nexport const LocalPackSelectors = {\n headingText: 'Businesses',\n card: '.w7Dbne',\n name: '.OSrXXb',\n ratingValue: '.yi40Hd',\n reviewCount: '.RDApEe',\n} as const\n\nexport const SELECTORS_VERSION = '2026-05-07'\n","export const RECAPTCHA_INSTRUCTIONS = 'Google returned a CAPTCHA. Run with --headless=false to re-warm the browser profile, then retry.'\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","import type { CanonicalLocationName } from './types.js'\n\nexport const LOCATIONS: Record<string, CanonicalLocationName> = {\n 'austin': 'Austin,Texas,United States',\n 'new york': 'New York,New York,United States',\n 'new york city': 'New York,New York,United States',\n 'nyc': 'New York,New York,United States',\n 'los angeles': 'Los Angeles,California,United States',\n 'la': 'Los Angeles,California,United States',\n 'chicago': 'Chicago,Illinois,United States',\n 'houston': 'Houston,Texas,United States',\n 'phoenix': 'Phoenix,Arizona,United States',\n 'philadelphia': 'Philadelphia,Pennsylvania,United States',\n 'philly': 'Philadelphia,Pennsylvania,United States',\n 'san antonio': 'San Antonio,Texas,United States',\n 'dallas': 'Dallas,Texas,United States',\n 'miami': 'Miami,Florida,United States',\n 'seattle': 'Seattle,Washington,United States',\n 'denver': 'Denver,Colorado,United States',\n 'loveland': 'Loveland,Colorado,United States',\n 'loveland co': 'Loveland,Colorado,United States',\n 'fort collins': 'Fort Collins,Colorado,United States',\n 'boulder': 'Boulder,Colorado,United States',\n 'colorado springs': 'Colorado Springs,Colorado,United States',\n 'boston': 'Boston,Massachusetts,United States',\n 'atlanta': 'Atlanta,Georgia,United States',\n 'san francisco': 'San Francisco,California,United States',\n 'sf': 'San Francisco,California,United States',\n 'portland': 'Portland,Oregon,United States',\n 'las vegas': 'Las Vegas,Nevada,United States',\n 'minneapolis': 'Minneapolis,Minnesota,United States',\n 'detroit': 'Detroit,Michigan,United States',\n 'nashville': 'Nashville,Tennessee,United States',\n 'charlotte': 'Charlotte,North Carolina,United States',\n 'orlando': 'Orlando,Florida,United States',\n 'san diego': 'San Diego,California,United States',\n 'baltimore': 'Baltimore,Maryland,United States',\n 'sacramento': 'Sacramento,California,United States',\n 'columbus': 'Columbus,Ohio,United States',\n 'indianapolis': 'Indianapolis,Indiana,United States',\n 'san jose': 'San Jose,California,United States',\n 'fort worth': 'Fort Worth,Texas,United States',\n 'jacksonville': 'Jacksonville,Florida,United States',\n 'memphis': 'Memphis,Tennessee,United States',\n 'louisville': 'Louisville,Kentucky,United States',\n 'raleigh': 'Raleigh,North Carolina,United States',\n 'richmond': 'Richmond,Virginia,United States',\n 'salt lake city': 'Salt Lake City,Utah,United States',\n 'toronto': 'Toronto,Ontario,Canada',\n 'vancouver': 'Vancouver,British Columbia,Canada',\n 'montreal': 'Montreal,Quebec,Canada',\n 'calgary': 'Calgary,Alberta,Canada',\n 'ottawa': 'Ottawa,Ontario,Canada',\n 'london': 'London,England,United Kingdom',\n 'manchester': 'Manchester,England,United Kingdom',\n 'birmingham': 'Birmingham,England,United Kingdom',\n 'edinburgh': 'Edinburgh,Scotland,United Kingdom',\n 'glasgow': 'Glasgow,Scotland,United Kingdom',\n 'leeds': 'Leeds,England,United Kingdom',\n 'sydney': 'Sydney,New South Wales,Australia',\n 'melbourne': 'Melbourne,Victoria,Australia',\n 'brisbane': 'Brisbane,Queensland,Australia',\n 'perth': 'Perth,Western Australia,Australia',\n 'adelaide': 'Adelaide,South Australia,Australia',\n 'dublin': 'Dublin,Leinster,Ireland',\n}\n","import type { CanonicalLocationName, UuleString } from './types.js'\nimport { LOCATIONS } from './locations.js'\n\nexport function encodeUule(name: CanonicalLocationName): UuleString {\n const encoded = Buffer.from(String.fromCharCode(name.length) + name).toString('base64')\n return `w+CAIQICI${encoded}`\n}\n\nexport function normalizeLocation(input: string): CanonicalLocationName {\n const key = input.toLowerCase().trim()\n return (LOCATIONS[key] ?? input) as CanonicalLocationName\n}\n","const MAX_ANSWER_LENGTH = 1200\n\nconst BOILERPLATE_PATTERNS: RegExp[] = [\n /An AI Overview is not available for this search/gi,\n /Can't generate an AI overview right now\\.?\\s*Try again later\\.?/gi,\n /\\bAI Overview\\b/gi,\n /\\bView all\\b/gi,\n]\n\nconst CUT_MARKERS: RegExp[] = [\n /\\bRelated Links\\b/i,\n /\\bAsk anything in\\s*AI Mode\\b/i,\n /\\bAI can make mistakes\\b/i,\n /\\bThis is for informational purposes only\\b/i,\n /\\bShow more\\b/i,\n /\\b\\d+\\s+sites\\b/i,\n /\\b\\d{1,2}\\s*[msh]\\s*[A-Z][A-Za-z]/,\n /\\b(?:YouTube|Reddit|Facebook|Instagram|TikTok)·/,\n]\n\nfunction normalizeWhitespace(text: string): string {\n return text\n .replace(/\\u00a0/g, ' ')\n .replace(/([.!?])([A-Z])/g, '$1 $2')\n .replace(/([:;])([A-Z])/g, '$1 $2')\n .replace(/([a-z])([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([A-Z][a-z])/g, '$1 $2')\n .replace(/([a-z])(\\d)/g, '$1 $2')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\nfunction cutAtFirstMarker(text: string): string {\n let cutAt = -1\n for (const marker of CUT_MARKERS) {\n const match = marker.exec(text)\n marker.lastIndex = 0\n if (match && (cutAt === -1 || match.index < cutAt)) cutAt = match.index\n }\n return cutAt === -1 ? text : text.slice(0, cutAt)\n}\n\nfunction cutAtSourceTitle(text: string, sourceTitle?: string): string {\n const title = sourceTitle?.trim()\n if (!title || title.length < 8) return text\n const idx = text.toLowerCase().indexOf(title.toLowerCase())\n return idx > 40 ? text.slice(0, idx) : text\n}\n\nfunction findAttributionCut(beforeUrl: string): number {\n const dateMatch = beforeUrl.match(/[•·]\\s*(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\\.?\\s+\\d{1,2},\\s+\\d{4}/i)\n if (dateMatch?.index && dateMatch.index > 40) return dateMatch.index\n\n const start = Math.max(0, beforeUrl.length - 260)\n const tail = beforeUrl.slice(start)\n const sentenceBreaks = [...tail.matchAll(/[.!?]\\s*(?=[A-Z][A-Za-z0-9\"'$])/g)]\n for (const match of sentenceBreaks) {\n const remainder = tail.slice(match.index + 1).trim()\n const lead = remainder.slice(0, 160)\n const looksLikeTitle = /^(?:Best|Top|What|How|Why|When|Where|Which|Can|Should|Is|Are|Do|Does)\\b/i.test(remainder)\n if (\n remainder.length > 20 &&\n looksLikeTitle &&\n /(?:\\s[-|]\\s|Heating|Cooling|Company|Services|Blog|Guide|Review)/i.test(lead)\n ) {\n return start + match.index + 1\n }\n }\n const last = sentenceBreaks.at(-1)\n if (last?.index !== undefined) return start + last.index + 1\n\n return beforeUrl.length\n}\n\nfunction cutAtUrlAttribution(text: string): string {\n const urlMatch = text.match(/https?:\\/\\/\\S+/i)\n if (!urlMatch?.index) return text\n\n const beforeUrl = text.slice(0, urlMatch.index)\n return beforeUrl.slice(0, findAttributionCut(beforeUrl))\n}\n\nfunction trimToSentenceLimit(text: string): string {\n if (text.length <= MAX_ANSWER_LENGTH) return text\n const slice = text.slice(0, MAX_ANSWER_LENGTH)\n const lastSentence = Math.max(slice.lastIndexOf('.'), slice.lastIndexOf('!'), slice.lastIndexOf('?'))\n return (lastSentence > 240 ? slice.slice(0, lastSentence + 1) : slice).trim()\n}\n\nexport function cleanPAAAnswerText(\n answer: string | null | undefined,\n question?: string,\n sourceTitle?: string,\n): string | undefined {\n if (!answer) return undefined\n\n let text = normalizeWhitespace(answer)\n const normalizedQuestion = question ? normalizeWhitespace(question) : ''\n if (normalizedQuestion && text.toLowerCase().startsWith(normalizedQuestion.toLowerCase())) {\n text = text.slice(normalizedQuestion.length).trim()\n }\n\n if (/^An error has occurred\\.?\\s*Please try again later\\.?/i.test(text)) {\n return undefined\n }\n\n for (const pattern of BOILERPLATE_PATTERNS) {\n text = text.replace(pattern, ' ')\n }\n text = text\n .replace(/\\b[A-Z][A-Za-z&'\\u2019 -]{2,60}\\+\\d+\\b/g, ' ')\n .replace(/\\b(?:[a-z0-9-]+\\.)+[a-z]{2,}\\+\\d+\\b/gi, ' ')\n\n text = normalizeWhitespace(text)\n text = cutAtFirstMarker(text)\n text = cutAtSourceTitle(text, sourceTitle)\n text = cutAtUrlAttribution(text)\n text = normalizeWhitespace(text)\n text = text.replace(/\\s+(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\\.?\\s+\\d{1,2},\\s+\\d{4}$/i, '').trim()\n text = trimToSentenceLimit(text)\n\n if (!text) return undefined\n if (/^An error has occurred\\.?\\s*Please try again later\\.?$/i.test(text)) return undefined\n\n return text\n}\n","import type { Page } from 'playwright'\nimport type { IBrowserDriver } from '../driver/IBrowserDriver.js'\nimport type { IProgressReporter } from '../output/IProgressReporter.js'\nimport { PAASelectors, VideoSelectors, ForumSelectors, ShortVideoSelectors, AIOverviewSelectors, AIModeSelectors, WhatPeopleSayingSelectors, OrganicSelectors, LocalPackSelectors } from '../selectors.js'\nimport { encodeUule, normalizeLocation } from '../uule.js'\nimport { RawPAAItemSchema } from '../schemas.js'\nimport { cleanPAAAnswerText } from '../lib/paa-answer-cleanup.js'\nimport type {\n HarvestOptions, HarvestResult, HarvestStats,\n RawPAAItem, PAANode, FlatRow, NormalizedQuestionKey, DriverConfig,\n VideoResult, ForumResult, AIOverviewResult, AIModeResult, GoogleSurface,\n WhatPeopleSayingCard, EntityIds, EntityRecord,\n OrganicResult, LocalPackBusiness,\n} from '../types.js'\nimport type { IPAAExtractor } from './IPAAExtractor.js'\n\nexport class PAAExtractor implements IPAAExtractor {\n constructor(\n private readonly driver: IBrowserDriver,\n private readonly reporter: IProgressReporter,\n ) {}\n\n private normalizeQuestion(q: string): NormalizedQuestionKey {\n return q.toLowerCase().replace(/[^\\w\\s]/g, '').replace(/\\s+/g, ' ').trim() as NormalizedQuestionKey\n }\n\n private async extractVisibleItems(page: Page): Promise<RawPAAItem[]> {\n const sels = PAASelectors\n const raw = await page.evaluate((selectors) => {\n function cleanText(el: Element | null): string {\n if (!el) return ''\n const parts: string[] = []\n for (const n of el.childNodes) {\n if (n.nodeType === Node.TEXT_NODE) {\n const text = n.textContent?.trim()\n if (text) parts.push(text)\n } else if (\n (n as Element).tagName === 'STYLE' ||\n (n as Element).tagName === 'SCRIPT'\n ) {\n continue\n } else {\n const text = cleanText(n as Element)\n if (text) parts.push(text)\n }\n }\n return parts.join(' ').replace(/\\s+/g, ' ').trim()\n }\n return Array.from(document.querySelectorAll(selectors.item)).map((pair) => ({\n question: pair.getAttribute(selectors.itemDataQ) || pair.getAttribute(selectors.itemDataInitQ) || '',\n answer: cleanText(pair.querySelector(selectors.answerContainer)) || undefined,\n sourceTitle: (pair.querySelector(selectors.sourceTitle) as HTMLElement | null)?.innerText?.trim() || undefined,\n sourceSite: (pair.querySelector(selectors.sourceSite) as HTMLElement | null)?.innerText?.trim() || undefined,\n sourceCite: (pair.querySelector(selectors.sourceCite) as HTMLElement | null)?.innerText?.trim() || undefined,\n }))\n }, sels)\n\n return raw.flatMap((item) => {\n const cleaned = {\n ...item,\n answer: cleanPAAAnswerText(item.answer, item.question, item.sourceTitle),\n }\n const result = RawPAAItemSchema.safeParse(cleaned)\n if (!result.success) {\n console.warn('[PAAExtractor] item parse failed:', item.question, result.error.issues[0]?.message)\n return []\n }\n return [result.data]\n })\n }\n\n private async clickItem(page: Page, questionText: string): Promise<void> {\n try {\n const pairLocator = page.locator(\n `${PAASelectors.item}[data-q=\"${questionText}\"], ${PAASelectors.item}[data-initq=\"${questionText}\"]`\n ).first()\n await pairLocator.click()\n } catch { }\n }\n\n private toFlatRow(item: RawPAAItem, depth: number, parentQuestion: string | null, seed: string): FlatRow {\n return {\n seed_query: seed,\n question: item.question,\n answer: item.answer ?? '',\n source_title: item.sourceTitle ?? '',\n source_site: item.sourceSite ?? '',\n source_cite: item.sourceCite ?? '',\n depth,\n parent_question: parentQuestion ?? '',\n extracted_at: new Date().toISOString(),\n }\n }\n\n private async runBFS(page: Page, options: HarvestOptions): Promise<FlatRow[]> {\n const seenKeys = new Set<NormalizedQuestionKey>()\n const seenQs = new Set<string>()\n const depthMap = new Map<string, number>()\n const results: FlatRow[] = []\n\n const readAllQs = (): Promise<string[]> =>\n page.evaluate(\n ({ sel, dataQ, dataInitQ, questionEl }: { sel: string; dataQ: string; dataInitQ: string; questionEl: string }) =>\n Array.from(document.querySelectorAll(sel))\n .map(el =>\n el.getAttribute(dataQ) ||\n el.getAttribute(dataInitQ) ||\n (el.querySelector(questionEl) as HTMLElement | null)?.innerText?.trim() ||\n ''\n )\n .filter(Boolean),\n { sel: PAASelectors.item, dataQ: PAASelectors.itemDataQ, dataInitQ: PAASelectors.itemDataInitQ, questionEl: PAASelectors.itemQuestionEl },\n )\n\n const dupRates: number[] = []\n const orderedQs: string[] = []\n\n for (let round = 0; round < options.depth; round++) {\n this.reporter.onDepth(round + 1)\n\n if (seenQs.size >= options.maxQuestions) break\n\n const beforeQs = await readAllQs()\n if (beforeQs.length >= options.maxQuestions) break\n\n const unexpandedItems = await page.$$(\n `${PAASelectors.item}:not(.${PAASelectors.expandedClass})`\n )\n if (unexpandedItems.length === 0) break\n\n for (const item of unexpandedItems) {\n try {\n await item.scrollIntoViewIfNeeded()\n await item.click({ force: true })\n await page.waitForTimeout(500)\n } catch { }\n }\n await page.waitForTimeout(1500)\n\n const afterQs = await readAllQs()\n const newQs = afterQs.slice(beforeQs.length)\n\n const newDups = newQs.filter(q => seenQs.has(q)).length\n const dupRate = newQs.length > 0 ? newDups / newQs.length : 0\n dupRates.push(dupRate)\n if (dupRates.length > 2) dupRates.shift()\n const rollingDupRate = dupRates.reduce((a, b) => a + b, 0) / dupRates.length\n\n for (const q of afterQs) {\n if (!seenQs.has(q)) { seenQs.add(q); orderedQs.push(q) }\n if (!depthMap.has(q)) depthMap.set(q, round + 1)\n }\n\n if (afterQs.length === beforeQs.length) break\n if (rollingDupRate >= 0.6) break\n }\n\n const itemMap = new Map((await this.extractVisibleItems(page)).map(i => [i.question, i]))\n\n for (const q of orderedQs) {\n if (results.length >= options.maxQuestions) break\n const key = this.normalizeQuestion(q)\n if (seenKeys.has(key)) continue\n seenKeys.add(key)\n const d = depthMap.get(q) ?? 1\n const item = itemMap.get(q)\n if (item) {\n results.push(this.toFlatRow(item, d, null, options.query))\n this.reporter.onQuestion({ question: item.question, answer: item.answer ?? null, sourceTitle: item.sourceTitle ?? null, sourceSite: item.sourceSite ?? null, sourceCite: item.sourceCite ?? null, depth: d, parentQuestion: null, children: [] })\n } else {\n results.push(this.toFlatRow({ question: q, answer: undefined, sourceTitle: undefined, sourceSite: undefined, sourceCite: undefined }, d, null, options.query))\n }\n }\n\n return results\n }\n\n private async extractVideos(page: Page): Promise<VideoResult[]> {\n const vsels = VideoSelectors\n return page.evaluate((sels) => {\n const results: Array<{ type: 'video' | 'short_video'; title: string; channel: string; platform: string; duration: string; url: string }> = []\n const containers = Array.from(document.querySelectorAll(sels.container))\n for (const container of containers) {\n const headingEl = container.querySelector(sels.sectionHeading)\n const headingText = headingEl?.textContent?.trim() ?? ''\n const type: 'video' | 'short_video' = headingText.toLowerCase().includes('short') ? 'short_video' : 'video'\n const items = Array.from(container.querySelectorAll(sels.item))\n for (const a of items) {\n const href = (a as HTMLAnchorElement).href\n if (!href || (!href.includes('youtube') && !href.includes('youtu.be'))) continue\n const raw = a.textContent?.trim() ?? ''\n const ytIdx = raw.indexOf('YouTube')\n if (ytIdx === -1) continue\n const title = raw.slice(0, ytIdx).trim()\n const remainder = raw.slice(ytIdx + 7).replace(/^[·\\s·]+/, '')\n const channelMatch = remainder.match(/^([^·\\n]+)/)\n const channel = channelMatch ? channelMatch[1].trim() : ''\n if (title) results.push({ type, title, channel, platform: 'YouTube', duration: '', url: href })\n }\n }\n return results\n }, vsels)\n }\n\n private async extractForums(page: Page): Promise<ForumResult[]> {\n const fsels = ForumSelectors\n return page.evaluate((sels) => {\n const results: Array<{ title: string; source: string; url: string }> = []\n const sections = Array.from(document.querySelectorAll(sels.section))\n const forumSection = sections.find((s) => s.textContent?.includes('Discussions'))\n if (!forumSection) return results\n const items = Array.from(forumSection.querySelectorAll(sels.item))\n for (const a of items) {\n const href = (a as HTMLAnchorElement).href\n if (!href) continue\n const titleEl = a.querySelector(sels.title)\n const sourceEl = a.querySelector(sels.source)\n const title = titleEl?.textContent?.trim() ?? ''\n const source = sourceEl?.textContent?.trim() ?? ''\n if (title) results.push({ title, source, url: href })\n }\n return results\n }, fsels)\n }\n\n private async extractShortVideos(page: Page, shortUrl: string): Promise<VideoResult[]> {\n try {\n await page.goto(shortUrl, { waitUntil: 'domcontentloaded' })\n await page.waitForTimeout(1500)\n } catch {\n return []\n }\n\n const svSels = {\n item: ShortVideoSelectors.item,\n platforms: [...ShortVideoSelectors.platforms] as string[],\n }\n\n const raw = await page.evaluate((sels) => {\n const seen = new Set<string>()\n const results: Array<{ title: string; channel: string; platform: string; duration: string; url: string }> = []\n const items = Array.from(document.querySelectorAll(sels.item))\n\n const videoHosts = ['youtube.com', 'youtu.be', 'tiktok.com', 'instagram.com', 'facebook.com', 'fb.watch']\n\n const byHref = new Map<string, string[]>()\n for (const a of items) {\n const href = (a as HTMLAnchorElement).href\n if (!href) continue\n if (!videoHosts.some((h) => href.includes(h))) continue\n const text = a.textContent?.trim() ?? ''\n if (!byHref.has(href)) byHref.set(href, [])\n byHref.get(href)!.push(text)\n }\n\n for (const [href, texts] of byHref.entries()) {\n if (seen.has(href)) continue\n seen.add(href)\n\n const duration = texts.find((t) => /^\\d+:\\d+$/.test(t)) ?? ''\n const titleText = texts.find((t) => !/^\\d+:\\d+$/.test(t) && t.length > 5) ?? ''\n if (!titleText) continue\n\n let title = titleText\n let platform = ''\n let channel = ''\n\n for (const p of sels.platforms) {\n let lastIdx = -1\n let search = 0\n while (true) {\n const found = titleText.indexOf(p, search)\n if (found === -1) break\n lastIdx = found\n search = found + 1\n }\n if (lastIdx === -1) continue\n const after = titleText.slice(lastIdx + p.length)\n const isSourceTag = /^[\\s·]/.test(after) || after.trim() === ''\n if (!isSourceTag) continue\n title = titleText.slice(0, lastIdx).trim()\n platform = p\n const stripped = after.replace(/^[\\s·]+/, '')\n const dotIdx = stripped.indexOf('·')\n channel = (dotIdx === -1 ? stripped : stripped.slice(0, dotIdx)).trim()\n break\n }\n\n if (title) results.push({ title, channel, platform, duration, url: href })\n }\n\n return results\n }, svSels)\n\n return raw.map((r) => ({ type: 'short_video' as const, ...r }))\n }\n\n private async extractWhatPeopleSaying(page: Page): Promise<WhatPeopleSayingCard[]> {\n const sels = WhatPeopleSayingSelectors\n return page.evaluate((s) => {\n const section = Array.from(document.querySelectorAll(s.sectionTag))\n .find((el) => el.textContent?.includes(s.sectionHeadingText))\n ?? document.querySelector('.yG4QQe.TBC9ub.NbhJ1c')\n\n if (!section) return []\n\n return Array.from(section.querySelectorAll(s.card)).map((card) => {\n const link = card.querySelector(s.cardLink) as HTMLAnchorElement | null\n const url = link?.href ?? ''\n\n const titleH1 = card.querySelector(s.titleH1)?.textContent?.trim()\n const titleDiv = card.querySelector(s.titleDiv)?.textContent?.trim()\n const title = titleH1 ?? titleDiv ?? ''\n\n const sourceText = card.querySelector(s.source)?.textContent?.trim() ?? ''\n const platformEl = card.querySelector(s.platformBadge)\n const platformText = platformEl?.textContent?.trim() ?? ''\n\n const ytChannel = card.querySelector(s.ytChannel)?.textContent?.trim() ?? ''\n const ytDate = card.querySelector(s.ytDate)?.textContent?.trim() ?? ''\n const authorNote = card.querySelector(s.authorNote)?.textContent?.trim() ?? null\n\n const commentLabelEl = card.querySelector(s.popularCommentLabel)\n let popularComment: string | null = null\n if (commentLabelEl) {\n let next = commentLabelEl.nextSibling\n while (next) {\n const t = next.textContent?.trim()\n if (t) { popularComment = t; break }\n next = next.nextSibling\n }\n }\n\n const allSpans = Array.from(card.querySelectorAll('span'))\n const duration = allSpans.find((s) => /^\\d+:\\d+$/.test(s.textContent?.trim() ?? ''))?.textContent?.trim() ?? null\n const engagementParts = allSpans\n .map((s) => s.textContent?.trim() ?? '')\n .filter((t) =>\n /\\d/.test(t) && (\n t.includes('comment') || t.includes('reaction') ||\n t.includes('view') || t.includes('like') || t.includes('share')\n )\n )\n const engagement = engagementParts[0] ?? ''\n\n const dateCandidates = allSpans\n .map((s) => s.textContent?.trim() ?? '')\n .filter((t) => /\\d+ (day|week|month|year|hour)s? ago|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/.test(t))\n const date = ytDate || (dateCandidates[0] ?? '')\n\n const platform = platformText || (ytChannel ? 'YouTube' : '')\n const source = ytChannel || sourceText\n\n let type: 'reddit' | 'facebook' | 'youtube' | 'instagram' | 'tiktok' | 'news' | 'unknown' = 'unknown'\n const pl = platform.toLowerCase()\n const src = source.toLowerCase()\n const srcRaw = sourceText.toLowerCase()\n if (pl.includes('reddit') || src.startsWith('r/')) type = 'reddit'\n else if (pl.includes('facebook') || srcRaw.includes('facebook')) type = 'facebook'\n else if (pl.includes('instagram') || srcRaw.includes('instagram')) type = 'instagram'\n else if (pl.includes('tiktok') || srcRaw.includes('tiktok')) type = 'tiktok'\n else if (pl.includes('youtube') || !!ytChannel) type = 'youtube'\n else type = 'news'\n\n return { type, title, url, source, platform, popularComment, engagement, date, duration, authorNote }\n })\n }, sels)\n }\n\n private async extractOrganicResults(page: Page): Promise<OrganicResult[]> {\n const sels = OrganicSelectors\n return page.evaluate((s) => {\n const out: Array<{ position: number; title: string; url: string; domain: string; cite: string | null; snippet: string | null; isRedditStyle: boolean; inlineRating: { value: string; count: string } | null }> = []\n let pos = 0\n document.querySelectorAll(s.result).forEach(card => {\n const titleEl = card.querySelector(s.title)\n if (!titleEl) return\n const title = titleEl.textContent?.trim() ?? ''\n const linkEl = titleEl.closest('a') as HTMLAnchorElement | null\n const url = linkEl?.href ?? ''\n if (!title || !url) return\n pos++\n const cite = card.querySelector(s.cite)?.textContent?.trim() ?? null\n const snippet = card.querySelector(s.snippet)?.textContent?.trim() ?? null\n const isRedditStyle = !!card.querySelector(s.redditCite)\n const ratingEl = card.querySelector(s.ratingWrap)\n const inlineRating = ratingEl\n ? { value: ratingEl.querySelector(s.ratingValue)?.textContent?.trim() ?? '', count: ratingEl.querySelector(s.reviewCount)?.textContent?.trim() ?? '' }\n : null\n let domain = ''\n try { domain = new URL(url).hostname.replace(/^www\\./, '') } catch { domain = card.querySelector(s.siteName)?.textContent?.trim() ?? '' }\n out.push({ position: pos, title, url, domain, cite, snippet, isRedditStyle, inlineRating })\n })\n return out\n }, sels)\n }\n\n private async extractLocalPack(page: Page): Promise<LocalPackBusiness[]> {\n const sels = LocalPackSelectors\n return page.evaluate((s) => {\n const out: Array<{ position: number; name: string; cid: string | null; rating: string | null; reviewCount: string | null; metadata: string[]; websiteUrl: string | null; directionsUrl: string | null }> = []\n let container: Element | null = null\n document.querySelectorAll('[role=\"heading\"]').forEach(h => {\n if (!container && h.textContent?.includes(s.headingText)) container = h.closest('[data-hveid]')\n })\n if (!container) return out\n ;(container as Element).querySelectorAll(s.card).forEach((card, i) => {\n const name = card.querySelector(s.name)?.textContent?.trim() ?? ''\n if (!name) return\n const rating = card.querySelector(s.ratingValue)?.textContent?.trim() ?? null\n const reviewRaw = card.querySelector(s.reviewCount)?.textContent?.trim() ?? null\n const reviewCount = reviewRaw ? reviewRaw.replace(/[()]/g, '').trim() : null\n let cid = (card.querySelector('a[data-cid]') as HTMLAnchorElement | null)?.getAttribute('data-cid') ?? null\n if (!cid) {\n for (const link of Array.from(card.querySelectorAll('a[href]')) as HTMLAnchorElement[]) {\n const m1 = link.href.match(/[?&]cid=(\\d+)/)\n if (m1) { cid = m1[1]; break }\n const m2 = link.href.match(/!1s0x[0-9a-f]+:0x([0-9a-f]+)/i)\n if (m2) { try { cid = BigInt('0x' + m2[1]).toString() } catch { } if (cid) break }\n }\n }\n const metadata: string[] = []\n card.querySelectorAll('div, span').forEach(el => {\n const text = Array.from(el.childNodes)\n .filter(n => n.nodeType === 3)\n .map(n => n.textContent?.trim() ?? '')\n .filter(t => t.length > 1 && t.length < 120)\n .join(' ')\n if (text && !metadata.includes(text)) metadata.push(text)\n })\n const links = Array.from(card.querySelectorAll('a[href]')) as HTMLAnchorElement[]\n const directionsUrl = links.find(a => a.href.includes('google.com/maps'))?.href ?? null\n const websiteUrl = links.find(a => !a.href.includes('google.com') && a.href.startsWith('http'))?.href ?? null\n out.push({ position: i + 1, name, cid, rating, reviewCount, metadata, websiteUrl, directionsUrl })\n })\n return out\n }, sels)\n }\n\n private async extractEntityIds(page: Page): Promise<EntityIds> {\n return page.evaluate(() => {\n const kgIds = new Set<string>()\n const cids = new Set<string>()\n const gcids = new Set<string>()\n const recordMap = new Map<string, { name: string; kgId: string | null; cid: string | null; gcid: string | null }>()\n\n function nameFromWrapper(el: Element): string {\n const sel = ['.OSrXXb', '.dbg0pd', '.tzt0oe', '[role=\"heading\"]', 'h3']\n for (const s of sel) {\n const found = el.querySelector(s)\n if (found?.textContent?.trim()) return found.textContent.trim()\n }\n return ''\n }\n\n document.querySelectorAll('[id^=\"pv-/g/\"]').forEach(wrapper => {\n const raw = wrapper.getAttribute('id')\n if (!raw) return\n const kgId = raw.replace('pv-', '')\n kgIds.add(kgId)\n const name = nameFromWrapper(wrapper)\n const cidEl = wrapper.querySelector('a[data-cid]')\n const cid = cidEl?.getAttribute('data-cid') ?? null\n if (cid) cids.add(cid)\n if (name) recordMap.set(kgId, { name, kgId, cid, gcid: null })\n })\n\n document.querySelectorAll('[data-mid]').forEach(el => {\n const mid = el.getAttribute('data-mid')\n if (!mid?.startsWith('/g/')) return\n kgIds.add(mid)\n if (!recordMap.has(mid)) {\n const name = nameFromWrapper(el)\n if (name) recordMap.set(mid, { name, kgId: mid, cid: null, gcid: null })\n }\n })\n\n document.querySelectorAll('.w7Dbne').forEach(card => {\n const cidEl = card.querySelector('a[data-cid]')\n const cid = cidEl?.getAttribute('data-cid') ?? null\n if (!cid) return\n cids.add(cid)\n const name = card.querySelector('.OSrXXb')?.textContent?.trim() ?? ''\n if (!name) return\n const kgIdEl = card.querySelector('[id^=\"pv-/g/\"]')\n const kgId = kgIdEl ? kgIdEl.getAttribute('id')!.replace('pv-', '') : null\n const key = kgId ?? `cid:${cid}`\n if (recordMap.has(key)) {\n const existing = recordMap.get(key)!\n if (!existing.cid) recordMap.set(key, { ...existing, cid })\n } else {\n recordMap.set(key, { name, kgId, cid, gcid: null })\n }\n })\n\n document.querySelectorAll('a[data-cid]').forEach(el => {\n const cid = el.getAttribute('data-cid')\n if (!cid) return\n cids.add(cid)\n const alreadyNamed = [...recordMap.values()].some(r => r.cid === cid)\n if (!alreadyNamed) {\n let node: Element | null = el.parentElement\n let name = ''\n for (let i = 0; i < 8 && node; i++) {\n const h = node.querySelector('.OSrXXb, .dbg0pd, [role=\"heading\"], h3')\n if (h?.textContent?.trim()) { name = h.textContent.trim(); break }\n node = node.parentElement\n }\n if (name) recordMap.set(`cid:${cid}`, { name, kgId: null, cid, gcid: null })\n }\n })\n\n const scriptContent = Array.from(document.querySelectorAll('script:not([src])'))\n .map(s => s.textContent ?? '')\n .filter(t => t.length > 10_000)\n .join('\\n')\n\n for (const m of scriptContent.matchAll(/\\/g\\/[a-zA-Z0-9_-]{5,20}/g)) kgIds.add(m[0])\n for (const m of scriptContent.matchAll(/gcid:[a-zA-Z0-9_]+/g)) gcids.add(m[0])\n for (const m of scriptContent.matchAll(/0x[0-9a-f]+:0x([0-9a-f]+)/gi)) {\n try { cids.add(BigInt('0x' + m[1]).toString()) } catch { }\n }\n\n return { entities: [...recordMap.values()], kgIds: [...kgIds], cids: [...cids], gcids: [...gcids] }\n })\n }\n\n private mergeLocalPackIntoEntities(entityIds: EntityIds, localPack: LocalPackBusiness[]): EntityIds {\n const cidSet = new Set<string>(entityIds.cids)\n const records = entityIds.entities.map(r => ({ ...r }))\n\n for (const biz of localPack) {\n if (!biz.cid) continue\n cidSet.add(biz.cid)\n const nameNorm = biz.name.toLowerCase().trim()\n const byName = records.find(r => r.name.toLowerCase().trim() === nameNorm)\n if (byName) {\n if (!byName.cid) byName.cid = biz.cid\n } else if (!records.find(r => r.cid === biz.cid)) {\n records.push({ name: biz.name, kgId: null, cid: biz.cid, gcid: null })\n }\n }\n\n return { ...entityIds, entities: records, cids: [...cidSet] }\n }\n\n private async extractAISurfaces(page: Page): Promise<{\n surface: GoogleSurface\n aiOverview: AIOverviewResult\n aiMode: AIModeResult\n }> {\n const aioSels = AIOverviewSelectors\n const aimSels = AIModeSelectors\n\n return page.evaluate(({ aio, aim }) => {\n const sn: string = (window as unknown as { google?: { sn?: string } }).google?.sn ?? 'unknown'\n const surface: 'web' | 'aim' | 'unknown' =\n sn === 'aim' ? 'aim' : sn === 'web' ? 'web' : 'unknown'\n\n function findAIORoot(): Element | null {\n const primary = document.querySelector(aio.root)\n if (primary) return primary\n const headings = document.querySelectorAll('h1, h2, h3, [role=\"heading\"]')\n for (const h of headings) {\n if (h.textContent?.trim() === 'AI Overview') {\n let el: Element | null = h.parentElement\n for (let i = 0; i < 6 && el; i++) {\n if (el.querySelectorAll('a').length > 1) return el\n el = el.parentElement\n }\n return h.parentElement\n }\n }\n return null\n }\n\n const aioRoot = findAIORoot()\n const aioContainer = aioRoot ? (aioRoot.closest(aio.wrapper) ?? aioRoot) : null\n\n let aioText: string | null = null\n if (aioContainer) {\n const clone = aioContainer.cloneNode(true) as Element\n clone.querySelectorAll('script,style,noscript').forEach((el) => el.remove())\n clone.querySelectorAll('h1,h2,h3,h4,[role=\"heading\"]').forEach((el) => el.remove())\n clone.querySelectorAll('button,[role=\"button\"]').forEach((el) => el.remove())\n clone.querySelectorAll('a').forEach((el) => el.remove())\n const candidate = clone.textContent?.replace(/\\s+/g, ' ').trim() || null\n const isErrorState = !candidate ||\n /not available|try again|can't generate/i.test(candidate)\n aioText = isErrorState ? null : candidate\n }\n\n const aioDetected = !!aioRoot && aioText !== null\n\n const aioCitations = Array.from(aioContainer?.querySelectorAll('a[href]') ?? [])\n .filter((a) => (a as HTMLAnchorElement).href && !(a as HTMLAnchorElement).href.startsWith('javascript'))\n .map((a) => ({\n text: (a as HTMLAnchorElement).textContent?.trim() ?? '',\n href: (a as HTMLAnchorElement).href,\n }))\n .filter((c) => c.text && c.href)\n\n const aimRoot = document.querySelector(aim.root)\n const aimDetected = surface === 'aim' && !!aimRoot\n const aimContainer = aimRoot?.closest(aim.wrapper) ?? null\n\n let aimText: string | null = null\n if (aimContainer) {\n const clone = aimContainer.cloneNode(true) as Element\n clone.querySelectorAll('script,style,noscript').forEach((el) => el.remove())\n clone.querySelectorAll('h1,h2,h3,h4,[role=\"heading\"]').forEach((el) => el.remove())\n clone.querySelectorAll('button,[role=\"button\"]').forEach((el) => el.remove())\n clone.querySelectorAll('a').forEach((el) => el.remove())\n const candidate = clone.textContent?.replace(/\\s+/g, ' ').trim() || null\n const isErrorState = !candidate ||\n /not available|try again|can't generate/i.test(candidate)\n aimText = isErrorState ? null : candidate\n }\n\n const aimCitations = aimDetected\n ? Array.from(aimContainer?.querySelectorAll('a[href]') ?? [])\n .filter((a) => (a as HTMLAnchorElement).href && !(a as HTMLAnchorElement).href.startsWith('javascript'))\n .map((a) => ({\n text: (a as HTMLAnchorElement).textContent?.trim() ?? '',\n href: (a as HTMLAnchorElement).href,\n }))\n .filter((c) => c.text && c.href)\n : []\n\n return {\n surface,\n aiOverview: { detected: aioDetected, text: aioText, citations: aioCitations },\n aiMode: { detected: aimDetected, text: aimText, citations: aimCitations },\n }\n }, { aio: aioSels, aim: aimSels })\n }\n\n private buildTree(flat: FlatRow[], _seed: string): PAANode[] {\n const roots: PAANode[] = []\n const nodeMap = new Map<string, PAANode>()\n\n for (const row of flat) {\n const node: PAANode = {\n question: row.question,\n answer: row.answer || null,\n sourceTitle: row.source_title || null,\n sourceSite: row.source_site || null,\n sourceCite: row.source_cite || null,\n depth: row.depth,\n parentQuestion: row.parent_question || null,\n children: [],\n }\n nodeMap.set(row.question, node)\n }\n\n for (const node of nodeMap.values()) {\n if (node.parentQuestion && nodeMap.has(node.parentQuestion)) {\n nodeMap.get(node.parentQuestion)!.children.push(node)\n } else {\n roots.push(node)\n }\n }\n\n return roots\n }\n\n async extract(options: HarvestOptions): Promise<HarvestResult> {\n const startMs = Date.now()\n const config: DriverConfig = {\n headless: options.headless,\n profileDir: options.profileDir,\n proxy: options.proxy,\n kernelApiKey: options.kernelApiKey,\n kernelProxyId: options.kernelProxyId,\n viewport: { width: 1280, height: 800 },\n locale: `${options.hl}-${options.gl.toUpperCase()}`,\n }\n\n let errorCount = 0\n\n try {\n await this.driver.launch(config)\n const uule = options.location ? encodeUule(normalizeLocation(options.location)) : null\n const { hasPaa } = await this.driver.navigateToSERP(options.query, uule, options.gl, options.hl)\n\n const page = this.driver.getPage() as Page\n\n if (options.serpOnly) {\n const [organicResults, localPack, rawEntityIds] = await Promise.all([\n this.extractOrganicResults(page),\n this.extractLocalPack(page),\n this.extractEntityIds(page),\n ])\n const entityIds = this.mergeLocalPackIntoEntities(rawEntityIds, localPack)\n let allOrganic = organicResults\n if ((options.pages ?? 1) >= 2) {\n const p2params = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, start: '10' })\n if (uule) p2params.set('uule', uule)\n await this.driver.navigateTo('https://www.google.com/search?' + p2params.toString())\n const p2organic = await this.extractOrganicResults(page)\n allOrganic = [...organicResults, ...p2organic.map(r => ({ ...r, position: r.position + 10 }))]\n }\n const stats: HarvestStats = {\n seed: options.query, totalQuestions: 0, maxDepthReached: 0,\n durationMs: Date.now() - startMs, errorCount,\n }\n this.reporter.onComplete(stats)\n return {\n seed: options.query, location: options.location ?? null,\n extractedAt: new Date().toISOString(), totalQuestions: 0,\n surface: 'web' as const,\n aiOverview: { detected: false, text: null, citations: [] },\n aiMode: { detected: false, text: null, citations: [] },\n whatPeopleSaying: [], tree: [], flat: [], videos: [], forums: [],\n organicResults: allOrganic, localPack, entityIds, stats,\n }\n }\n\n const [videos, forums, whatPeopleSaying, rawEntityIds, organicResults, localPack] = await Promise.all([\n this.extractVideos(page),\n this.extractForums(page),\n this.extractWhatPeopleSaying(page),\n this.extractEntityIds(page),\n this.extractOrganicResults(page),\n this.extractLocalPack(page),\n ])\n const entityIds = this.mergeLocalPackIntoEntities(rawEntityIds, localPack)\n this.reporter.onVideos(videos)\n this.reporter.onForums(forums)\n\n if (!hasPaa) {\n let noPaaOrganic = organicResults\n if ((options.pages ?? 1) >= 2) {\n const p2params = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, start: '10' })\n if (uule) p2params.set('uule', uule)\n await this.driver.navigateTo('https://www.google.com/search?' + p2params.toString())\n const p2organic = await this.extractOrganicResults(page)\n noPaaOrganic = [...organicResults, ...p2organic.map(r => ({ ...r, position: r.position + 10 }))]\n }\n const aiSurfaces = await this.extractAISurfaces(page)\n const stats: HarvestStats = {\n seed: options.query, totalQuestions: 0, maxDepthReached: 0,\n durationMs: Date.now() - startMs, errorCount,\n }\n this.reporter.onComplete(stats)\n return {\n seed: options.query, location: options.location ?? null,\n extractedAt: new Date().toISOString(), totalQuestions: 0,\n surface: aiSurfaces.surface,\n aiOverview: aiSurfaces.aiOverview,\n aiMode: aiSurfaces.aiMode,\n whatPeopleSaying, tree: [], flat: [], videos, forums,\n organicResults: noPaaOrganic, localPack, entityIds, stats,\n }\n }\n\n const flat = await this.runBFS(page, options)\n const aiSurfaces = await this.extractAISurfaces(page)\n\n const shortVidsParams = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, udm: ShortVideoSelectors.udm })\n if (uule) shortVidsParams.set('uule', uule)\n const shortVideos = await this.extractShortVideos(page, 'https://www.google.com/search?' + shortVidsParams.toString())\n this.reporter.onVideos(shortVideos)\n\n let allOrganic = organicResults\n if ((options.pages ?? 1) >= 2) {\n const p2params = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, start: '10' })\n if (uule) p2params.set('uule', uule)\n await this.driver.navigateTo('https://www.google.com/search?' + p2params.toString())\n const p2organic = await this.extractOrganicResults(page)\n allOrganic = [...organicResults, ...p2organic.map(r => ({ ...r, position: r.position + 10 }))]\n }\n\n const allVideos = [...videos, ...shortVideos]\n const tree = this.buildTree(flat, options.query)\n\n const stats: HarvestStats = {\n seed: options.query,\n totalQuestions: flat.length,\n maxDepthReached: flat.reduce((m, r) => Math.max(m, r.depth), 0),\n durationMs: Date.now() - startMs,\n errorCount,\n }\n\n this.reporter.onComplete(stats)\n\n return {\n seed: options.query,\n location: options.location ?? null,\n extractedAt: new Date().toISOString(),\n totalQuestions: flat.length,\n surface: aiSurfaces.surface,\n aiOverview: aiSurfaces.aiOverview,\n aiMode: aiSurfaces.aiMode,\n whatPeopleSaying,\n tree,\n flat,\n videos: allVideos,\n forums,\n organicResults: allOrganic,\n localPack,\n entityIds,\n stats,\n }\n } catch (err) {\n errorCount++\n this.reporter.onError(err instanceof Error ? err : new Error(String(err)))\n throw err\n } finally {\n await this.driver.close()\n }\n }\n}\n","import { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport Papa from 'papaparse'\nimport type { HarvestResult, FlatRow, VideoResult, ForumResult, AICitation, WhatPeopleSayingCard } from '../types.js'\nimport type { IOutputSerializer } from './IOutputSerializer.js'\n\nexport class OutputSerializer implements IOutputSerializer {\n async writeJSON(result: HarvestResult, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = result.seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const filename = `${slug}-${Date.now()}.json`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, JSON.stringify(result, null, 2), 'utf8')\n return fullPath\n }\n\n async writeCSV(rows: FlatRow[], outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const seedRaw = rows[0]?.seed_query ?? 'paa'\n const slug = seedRaw.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const csv = Papa.unparse(rows, { header: true })\n const filename = `${slug}-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeVideoCSV(videos: VideoResult[], seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const csv = Papa.unparse(videos, { header: true })\n const filename = `${slug}-videos-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeForumCSV(forums: ForumResult[], seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const csv = Papa.unparse(forums, { header: true })\n const filename = `${slug}-forums-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeAIOverviewCSV(citations: AICitation[], text: string | null, seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const rows = citations.map((c, i) => ({\n seed_query: seed,\n response_text: i === 0 ? (text ?? '') : '',\n citation_text: c.text,\n citation_href: c.href,\n }))\n const csv = Papa.unparse(rows, { header: true })\n const filename = `${slug}-ai-overview-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeAIModeCSV(citations: AICitation[], text: string | null, seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const rows = citations.map((c, i) => ({\n seed_query: seed,\n response_text: i === 0 ? (text ?? '') : '',\n citation_text: c.text,\n citation_href: c.href,\n }))\n const csv = Papa.unparse(rows, { header: true })\n const filename = `${slug}-ai-mode-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeWhatPeopleSayingCSV(cards: WhatPeopleSayingCard[], seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const rows = cards.map((c) => ({ seed_query: seed, ...c }))\n const csv = Papa.unparse(rows, { header: true })\n const filename = `${slug}-what-people-saying-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n}\n","import type { PAANode, HarvestStats, VideoResult, ForumResult } from '../types.js'\nimport type { IProgressReporter } from './IProgressReporter.js'\n\nexport class ProgressReporter implements IProgressReporter {\n onQuestion(node: PAANode): void {\n process.stdout.write(JSON.stringify({ event: 'question', depth: node.depth, question: node.question }) + '\\n')\n }\n\n onDepth(depth: number): void {\n process.stdout.write(JSON.stringify({ event: 'depth', depth }) + '\\n')\n }\n\n onVideos(videos: VideoResult[]): void {\n for (const v of videos) {\n process.stdout.write(JSON.stringify({ event: 'video', type: v.type, platform: v.platform, duration: v.duration, title: v.title, channel: v.channel, url: v.url }) + '\\n')\n }\n }\n\n onForums(forums: ForumResult[]): void {\n for (const f of forums) {\n process.stdout.write(JSON.stringify({ event: 'forum', title: f.title, source: f.source, url: f.url }) + '\\n')\n }\n }\n\n onComplete(stats: HarvestStats): void {\n process.stdout.write(JSON.stringify({ event: 'complete', ...stats }) + '\\n')\n }\n\n onError(err: Error): void {\n process.stderr.write(JSON.stringify({ event: 'error', type: err.constructor.name, message: err.message }) + '\\n')\n }\n}\n","import { HarvestOptionsSchema } from './schemas.js'\nimport type { HarvestOptions, HarvestResult } from './types.js'\nimport { BrowserDriver } from './driver/BrowserDriver.js'\nimport { PAAExtractor } from './extractor/PAAExtractor.js'\nimport { OutputSerializer } from './output/OutputSerializer.js'\nimport { ProgressReporter } from './output/ProgressReporter.js'\nimport { CaptchaError } from './errors.js'\n\nconst MAX_ATTEMPTS = 3\n\nasync function extractOnce(options: HarvestOptions): Promise<HarvestResult> {\n const driver = new BrowserDriver()\n const reporter = new ProgressReporter()\n const extractor = new PAAExtractor(driver, reporter)\n try {\n return await extractor.extract(options)\n } finally {\n await driver.close()\n }\n}\n\nexport async function harvest(rawOptions: unknown): Promise<HarvestResult> {\n const raw = typeof rawOptions === 'object' && rawOptions !== null ? rawOptions : {}\n const merged = {\n kernelApiKey: process.env.KERNEL_API_KEY?.trim(),\n kernelProxyId: process.env.KERNEL_PROXY_ID?.trim(),\n ...raw,\n }\n const options = HarvestOptionsSchema.parse(merged)\n const serializer = new OutputSerializer()\n\n for (let i = 0; i < MAX_ATTEMPTS; i++) {\n try {\n const result = await extractOnce(options)\n if (options.format === 'json' || options.format === 'both') {\n await serializer.writeJSON(result, options.outputDir)\n }\n if (options.format === 'csv' || options.format === 'both') {\n await Promise.all([\n serializer.writeCSV(result.flat, options.outputDir),\n result.videos.length > 0 ? serializer.writeVideoCSV(result.videos, result.seed, options.outputDir) : Promise.resolve(''),\n result.forums.length > 0 ? serializer.writeForumCSV(result.forums, result.seed, options.outputDir) : Promise.resolve(''),\n result.aiOverview.detected ? serializer.writeAIOverviewCSV(result.aiOverview.citations, result.aiOverview.text, result.seed, options.outputDir) : Promise.resolve(''),\n result.aiMode.detected ? serializer.writeAIModeCSV(result.aiMode.citations, result.aiMode.text, result.seed, options.outputDir) : Promise.resolve(''),\n result.whatPeopleSaying.length > 0 ? serializer.writeWhatPeopleSayingCSV(result.whatPeopleSaying, result.seed, options.outputDir) : Promise.resolve(''),\n ])\n }\n return result\n } catch (err) {\n if (err instanceof CaptchaError && i < MAX_ATTEMPTS - 1) {\n continue\n }\n throw err\n }\n }\n const sessionDesc = options.kernelApiKey ? `${MAX_ATTEMPTS} fresh Kernel.sh sessions` : `${MAX_ATTEMPTS} attempts`\n throw new CaptchaError(`CAPTCHA on all ${sessionDesc}. Try again in a few minutes.`)\n}\n","#!/usr/bin/env node\nimport { runCli } from '../src/cli.js'\nrunCli()\n"],"mappings":"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","names":["StealthPlugin","Kernel","playwrightChromium","s","organicResults","localPack","rawEntityIds","entityIds","allOrganic","stats","aiSurfaces","fs","path","Papa"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli.ts","../../src/schemas.ts","../../src/driver/BrowserDriver.ts","../../src/selectors.ts","../../src/errors.ts","../../src/locations.ts","../../src/uule.ts","../../src/serp-location-debug.ts","../../src/lib/paa-answer-cleanup.ts","../../src/extractor/ai-surfaces.ts","../../src/extractor/PAAExtractor.ts","../../src/output/OutputSerializer.ts","../../src/output/ProgressReporter.ts","../../src/kernel-proxy-resolver.ts","../../src/harvest.ts","../../bin/paa-harvest.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { harvest } from './harvest.js'\n\nconst program = new Command()\n\nprogram\n .name('paa-harvest')\n .description('Recursively extract Google People Also Ask questions')\n .requiredOption('-q, --query <query>', 'Seed query')\n .option('-l, --location <location>', 'Location name (e.g. \"austin\" or \"Austin,Texas,United States\")')\n .option('--gl <gl>', 'Google country code', 'us')\n .option('--hl <hl>', 'Google language code', 'en')\n .option('-d, --depth <depth>', 'BFS depth (1-30)', '3')\n .option('-m, --max-questions <n>', 'Max questions to harvest', '100')\n .option('-o, --output <dir>', 'Output directory', './paa-output')\n .option('-f, --format <format>', 'Output format: json, csv, or both', 'both')\n .option('--headless', 'Run browser in headless mode', false)\n .option('--profile <dir>', 'Persistent browser profile directory')\n .option('--proxy <url>', 'Proxy server URL')\n .option('--kernel-api-key <key>', 'Kernel.sh API key (or set KERNEL_API_KEY env var)')\n .action(async (opts) => {\n try {\n const result = await harvest({\n query: opts.query,\n location: opts.location,\n gl: opts.gl,\n hl: opts.hl,\n depth: parseInt(opts.depth, 10),\n maxQuestions: parseInt(opts.maxQuestions, 10),\n outputDir: opts.output,\n format: opts.format,\n headless: opts.headless,\n profileDir: opts.profile,\n proxy: opts.proxy,\n kernelApiKey: opts.kernelApiKey ?? process.env.KERNEL_API_KEY,\n })\n console.log(JSON.stringify({ totalQuestions: result.totalQuestions, outputDir: result.stats.seed }))\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n })\n\nexport async function runCli(): Promise<void> {\n await program.parseAsync()\n}\n","import { z } from 'zod'\n\nexport const HarvestOptionsSchema = z.object({\n query: z.string().min(1),\n location: z.string().optional(),\n gl: z.string().length(2).default('us'),\n hl: z.string().length(2).default('en'),\n device: z.enum(['desktop', 'mobile']).default('desktop'),\n proxyMode: z.enum(['location', 'configured', 'none']).default('location'),\n proxyZip: z.string().regex(/^\\d{5}$/).optional(),\n debug: z.boolean().default(false),\n depth: z.number().int().min(1).max(30).default(3),\n maxQuestions: z.number().int().min(1).max(1000).default(100),\n headless: z.boolean().default(false),\n profileDir: z.string().optional(),\n proxy: z.string().url().optional(),\n kernelApiKey: z.string().optional(),\n kernelProxyId: z.string().optional(),\n kernelProxyResolution: z.unknown().optional(),\n outputDir: z.string().default('./paa-output'),\n format: z.enum(['json', 'csv', 'both']).default('both'),\n serpOnly: z.boolean().default(false),\n pages: z.number().int().min(1).max(2).default(1),\n})\n\nexport const MapsPlaceOptionsSchema = z.object({\n businessName: z.string().min(1),\n location: z.string().min(1),\n gl: z.string().length(2).default('us'),\n hl: z.string().length(2).default('en'),\n includeReviews: z.boolean().default(false),\n maxReviews: z.number().int().min(1).max(500).default(50),\n kernelApiKey: z.string().optional(),\n kernelProxyId: z.string().optional(),\n headless: z.boolean().default(true),\n})\n\nexport const RawPAAItemSchema = z.object({\n question: z.string().min(1),\n answer: z.string().optional(),\n sourceTitle: z.string().optional(),\n sourceSite: z.string().optional(),\n sourceCite: z.string().optional(),\n})\n\nexport const RawMapsOverviewSchema = z.object({\n name: z.string().nullable(),\n rating: z.string().nullable(),\n reviewCount: z.string().nullable(),\n category: z.string().nullable(),\n address: z.string().nullable(),\n hoursSummary: z.string().nullable(),\n phone: z.string().nullable(),\n phoneDisplay: z.string().nullable(),\n website: z.string().nullable(),\n plusCode: z.string().nullable(),\n bookingUrl: z.string().nullable(),\n})\n\nexport const RawMapsHoursRowSchema = z.object({\n day: z.string(),\n hours: z.string(),\n})\n\nexport const RawMapsReviewStatsSchema = z.object({\n reviewHistogram: z.array(z.object({\n stars: z.number(),\n count: z.string(),\n })),\n reviewTopics: z.array(z.object({\n label: z.string(),\n count: z.string(),\n })),\n})\n\nexport const RawMapsReviewCardSchema = z.object({\n reviewId: z.string(),\n author: z.string().nullable(),\n stars: z.string().nullable(),\n date: z.string().nullable(),\n text: z.string().nullable(),\n ownerResponse: z.string().nullable(),\n})\n\nexport const RawMapsAboutAttributeSchema = z.object({\n section: z.string(),\n attribute: z.string(),\n})\n","import { chromium } from 'playwright-extra'\nimport StealthPlugin from 'puppeteer-extra-plugin-stealth'\nimport { chromium as playwrightChromium } from 'playwright'\nimport type { Browser, BrowserContext, Page } from 'playwright'\nimport Kernel from '@onkernel/sdk'\nimport { PAASelectors } from '../selectors.js'\nimport { CaptchaError, ExtractionError, RECAPTCHA_INSTRUCTIONS } from '../errors.js'\nimport type { BrowserDebugSnapshot, BrowserNetworkLocationDebug, DriverConfig, KernelSessionDebug, ProxyMode, SerpDevice, SerpNavigationDebug, UuleString } from '../types.js'\nimport type { BrowserCloseResult, IBrowserDriver } from './IBrowserDriver.js'\n\nchromium.use(StealthPlugin())\n\nconst DESKTOP_USER_AGENT =\n 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'\n\nconst MOBILE_USER_AGENT =\n 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1'\n\nconst DEFAULT_KERNEL_BROWSER_TIMEOUT_SECONDS = 180\nconst KERNEL_BROWSER_CLOSE_TIMEOUT_MS = 3_000\nconst KERNEL_SESSION_DELETE_TIMEOUT_MS = 5_000\n\nfunction positiveIntFromEnv(name: string, fallback: number): number {\n const raw = process.env[name]\n if (!raw) return fallback\n const parsed = Number(raw)\n return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback\n}\n\nfunction proxyIdSuffix(proxyId: string | null | undefined): string | null {\n return proxyId ? proxyId.slice(-6) : null\n}\n\nfunction errorText(err: unknown): string {\n return err instanceof Error ? err.message : String(err)\n}\n\nexport function rankCheckContextOptions(config: DriverConfig) {\n return {\n viewport: config.viewport,\n locale: config.locale,\n userAgent: config.userAgent ?? (config.isMobile ? MOBILE_USER_AGENT : DESKTOP_USER_AGENT),\n ...(config.deviceScaleFactor ? { deviceScaleFactor: config.deviceScaleFactor } : {}),\n ...(config.isMobile !== undefined ? { isMobile: config.isMobile } : {}),\n ...(config.hasTouch !== undefined ? { hasTouch: config.hasTouch } : {}),\n }\n}\n\nasync function withTimeout<T>(promise: Promise<T>, timeoutMs: number, label: string): Promise<T> {\n let timeout: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timeout = setTimeout(() => reject(new Error(`${label} timed out after ${timeoutMs}ms`)), timeoutMs)\n }),\n ])\n } finally {\n if (timeout) clearTimeout(timeout)\n }\n}\n\nexport function buildYouTubeChannelVideosUrl(channelInput: string): string {\n const raw = channelInput.trim()\n if (!raw) throw new Error('channelHandle is required')\n\n const urlLike = /^https?:\\/\\//i.test(raw) || /^(www\\.|m\\.)?youtube\\.com\\//i.test(raw)\n if (urlLike) {\n const parsed = new URL(/^https?:\\/\\//i.test(raw) ? raw : `https://${raw}`)\n const host = parsed.hostname.replace(/^www\\./, '').replace(/^m\\./, '').toLowerCase()\n if (host !== 'youtube.com') throw new Error('channel URL must be on youtube.com')\n\n const segments = parsed.pathname.split('/').filter(Boolean)\n const first = segments[0] ?? ''\n const second = segments[1] ?? ''\n\n if (first.startsWith('@')) return `https://www.youtube.com/${first}/videos`\n if (first === 'channel' && second) return `https://www.youtube.com/channel/${second}/videos`\n if ((first === 'c' || first === 'user') && second) return `https://www.youtube.com/${first}/${second}/videos`\n\n throw new Error('channel URL must be a YouTube handle, /channel/UC..., /c/..., or /user/... URL')\n }\n\n const stripped = raw.replace(/^\\/+/, '').replace(/\\/+$/, '')\n const withoutVideos = stripped.replace(/\\/videos$/i, '')\n if (/^UC[\\w-]{20,}$/.test(withoutVideos)) {\n return `https://www.youtube.com/channel/${withoutVideos}/videos`\n }\n\n const handle = withoutVideos.startsWith('@') ? withoutVideos : `@${withoutVideos}`\n if (!/^@[\\w.-]+$/.test(handle)) {\n throw new Error('channelHandle must be an @handle, UC channel ID, or YouTube channel URL')\n }\n return `https://www.youtube.com/${handle}/videos`\n}\n\nexport class BrowserDriver implements IBrowserDriver {\n private browser: Browser | null = null\n private context: BrowserContext | null = null\n private page: Page | null = null\n private kernelClient: Kernel | null = null\n private kernelSessionId: string | null = null\n private debugEnabled = false\n private debugSnapshot: BrowserDebugSnapshot = {\n kernel: null,\n context: null,\n networkLocation: null,\n serpNavigation: null,\n }\n\n async launch(config: DriverConfig): Promise<void> {\n this.debugEnabled = config.debug === true\n const proxyMode: ProxyMode = config.proxyMode ?? (config.kernelProxyId ? 'configured' : 'none')\n const device: SerpDevice = config.isMobile ? 'mobile' : 'desktop'\n this.debugSnapshot = {\n kernel: null,\n context: {\n viewport: config.viewport,\n locale: config.locale,\n device,\n userAgent: config.userAgent ?? (config.isMobile ? MOBILE_USER_AGENT : DESKTOP_USER_AGENT),\n deviceScaleFactor: config.deviceScaleFactor ?? null,\n isMobile: config.isMobile === true,\n hasTouch: config.hasTouch === true,\n },\n networkLocation: null,\n serpNavigation: null,\n }\n\n if (config.kernelApiKey) {\n this.kernelClient = new Kernel({ apiKey: config.kernelApiKey })\n const timeoutSeconds = positiveIntFromEnv('KERNEL_BROWSER_TIMEOUT_SECONDS', DEFAULT_KERNEL_BROWSER_TIMEOUT_SECONDS)\n const kernelBrowser = await this.kernelClient.browsers.create({\n stealth: true,\n timeout_seconds: timeoutSeconds,\n ...(config.kernelProxyId ? { proxy_id: config.kernelProxyId } : {}),\n })\n this.kernelSessionId = kernelBrowser.session_id\n let defaultProxyDisabled: boolean | null = null\n let defaultProxyDisableError: string | null = null\n if (proxyMode === 'none') {\n try {\n await withTimeout(\n this.kernelClient.browsers.update(this.kernelSessionId, { disable_default_proxy: true }),\n 5_000,\n `Kernel session ${this.kernelSessionId} disable default proxy`,\n )\n defaultProxyDisabled = true\n } catch (err) {\n defaultProxyDisabled = false\n defaultProxyDisableError = errorText(err)\n }\n }\n const kernelDebug: KernelSessionDebug = {\n sessionId: this.kernelSessionId,\n proxyMode,\n requestedProxyIdPresent: Boolean(config.kernelProxyId),\n requestedProxyIdSuffix: proxyIdSuffix(config.kernelProxyId),\n createdProxyIdPresent: typeof kernelBrowser.proxy_id === 'string' ? Boolean(kernelBrowser.proxy_id) : null,\n createdProxyIdSuffix: proxyIdSuffix(kernelBrowser.proxy_id),\n retrievedProxyIdPresent: null,\n retrievedProxyIdSuffix: null,\n retrievedProxyIdMatchesRequested: null,\n defaultProxyDisabled,\n defaultProxyDisableError,\n proxyResolution: config.kernelProxyResolution ?? null,\n timeoutSeconds,\n stealth: typeof kernelBrowser.stealth === 'boolean' ? kernelBrowser.stealth : null,\n profilePresent: null,\n poolPresent: null,\n retrieveError: null,\n }\n this.debugSnapshot.kernel = kernelDebug\n console.info(JSON.stringify({\n event: 'kernel_browser_created',\n kernel_session_id: this.kernelSessionId,\n timeout_seconds: timeoutSeconds,\n proxy_mode: proxyMode,\n proxy_id_present: Boolean(config.kernelProxyId),\n proxy_resolution_source: config.kernelProxyResolution?.source,\n }))\n if (this.debugEnabled) {\n await this.populateKernelRetrieveDebug(kernelDebug, config.kernelProxyId)\n }\n this.browser = await playwrightChromium.connectOverCDP(kernelBrowser.cdp_ws_url)\n this.context = await this.browser.newContext(rankCheckContextOptions(config))\n await this.installEsbuildHelperShims(this.context)\n this.page = await this.context.newPage()\n await this.page.setViewportSize(config.viewport)\n if (this.debugEnabled) {\n this.debugSnapshot.networkLocation = await this.captureBrowserNetworkLocation()\n }\n return\n }\n\n const launchOpts = {\n headless: config.headless,\n proxy: config.proxy ? { server: config.proxy } : undefined,\n }\n const ctxOpts = rankCheckContextOptions(config)\n if (config.profileDir) {\n this.context = await chromium.launchPersistentContext(config.profileDir, {\n ...launchOpts,\n ...ctxOpts,\n })\n await this.installEsbuildHelperShims(this.context)\n this.page = await this.context.newPage()\n } else {\n this.browser = await chromium.launch(launchOpts)\n this.context = await this.browser.newContext(ctxOpts)\n await this.installEsbuildHelperShims(this.context)\n this.page = await this.context.newPage()\n }\n if (this.debugEnabled) {\n this.debugSnapshot.networkLocation = await this.captureBrowserNetworkLocation()\n }\n }\n\n private async populateKernelRetrieveDebug(kernelDebug: KernelSessionDebug, requestedProxyId: string | undefined): Promise<void> {\n if (!this.kernelClient || !this.kernelSessionId) return\n try {\n const retrieved = await withTimeout(\n this.kernelClient.browsers.retrieve(this.kernelSessionId),\n 5_000,\n `Kernel session ${this.kernelSessionId} retrieve`,\n ) as { proxy_id?: string; timeout_seconds?: number; stealth?: boolean; profile?: unknown; pool?: unknown }\n kernelDebug.retrievedProxyIdPresent = typeof retrieved.proxy_id === 'string' ? Boolean(retrieved.proxy_id) : false\n kernelDebug.retrievedProxyIdSuffix = proxyIdSuffix(retrieved.proxy_id)\n kernelDebug.retrievedProxyIdMatchesRequested = requestedProxyId\n ? retrieved.proxy_id === requestedProxyId\n : !retrieved.proxy_id\n kernelDebug.timeoutSeconds = typeof retrieved.timeout_seconds === 'number' ? retrieved.timeout_seconds : kernelDebug.timeoutSeconds\n kernelDebug.stealth = typeof retrieved.stealth === 'boolean' ? retrieved.stealth : kernelDebug.stealth\n kernelDebug.profilePresent = Boolean(retrieved.profile)\n kernelDebug.poolPresent = Boolean(retrieved.pool)\n } catch (err) {\n kernelDebug.retrieveError = errorText(err)\n }\n }\n\n private async captureBrowserNetworkLocation(): Promise<BrowserNetworkLocationDebug> {\n const fallback = (message: string, source: BrowserNetworkLocationDebug['source'] = 'ipapi.co'): BrowserNetworkLocationDebug => ({\n source,\n ip: null,\n city: null,\n region: null,\n country: null,\n org: null,\n timezone: null,\n error: message,\n })\n if (!this.context) return fallback('browser context is not available')\n let debugPage: Page | null = null\n try {\n debugPage = await this.context.newPage()\n const ipwho = await this.loadJsonInDebugPage(debugPage, 'https://ipwho.is/')\n if (ipwho) {\n const connection = typeof ipwho.connection === 'object' && ipwho.connection !== null\n ? ipwho.connection as Record<string, unknown>\n : {}\n return {\n source: 'ipwho.is',\n ip: typeof ipwho.ip === 'string' ? ipwho.ip : null,\n city: typeof ipwho.city === 'string' ? ipwho.city : null,\n region: typeof ipwho.region === 'string' ? ipwho.region : null,\n country: typeof ipwho.country === 'string' ? ipwho.country : null,\n org: typeof connection.org === 'string' ? connection.org : null,\n timezone: typeof ipwho.timezone === 'object' && ipwho.timezone !== null && typeof (ipwho.timezone as Record<string, unknown>).id === 'string'\n ? (ipwho.timezone as Record<string, unknown>).id as string\n : null,\n error: null,\n }\n }\n\n const ipify = await this.loadJsonInDebugPage(debugPage, 'https://api64.ipify.org?format=json')\n if (ipify) {\n return {\n source: 'api64.ipify.org',\n ip: typeof ipify.ip === 'string' ? ipify.ip : null,\n city: null,\n region: null,\n country: null,\n org: null,\n timezone: null,\n error: null,\n }\n }\n\n await withTimeout(\n debugPage.goto('https://ipapi.co/json/', { waitUntil: 'domcontentloaded', timeout: 7_000 }),\n 8_000,\n 'browser network location navigation',\n )\n const body = await debugPage.locator('body').innerText({ timeout: 2_000 })\n const data = JSON.parse(body) as Record<string, unknown>\n return {\n source: 'ipapi.co',\n ip: typeof data.ip === 'string' ? data.ip : null,\n city: typeof data.city === 'string' ? data.city : null,\n region: typeof data.region === 'string' ? data.region : null,\n country: typeof data.country_name === 'string' ? data.country_name : typeof data.country === 'string' ? data.country : null,\n org: typeof data.org === 'string' ? data.org : null,\n timezone: typeof data.timezone === 'string' ? data.timezone : null,\n error: null,\n }\n } catch (err) {\n return fallback(errorText(err))\n } finally {\n await debugPage?.close().catch(() => {})\n }\n }\n\n private async loadJsonInDebugPage(debugPage: Page, url: string): Promise<Record<string, unknown> | null> {\n try {\n await withTimeout(\n debugPage.goto(url, { waitUntil: 'domcontentloaded', timeout: 7_000 }),\n 8_000,\n `browser network location navigation ${url}`,\n )\n const body = await debugPage.locator('body').innerText({ timeout: 2_000 })\n return JSON.parse(body) as Record<string, unknown>\n } catch {\n return null\n }\n }\n\n private async installEsbuildHelperShims(context: BrowserContext): Promise<void> {\n await context.addInitScript(() => {\n const g = globalThis as Record<string, unknown>\n if (typeof g.__name !== 'function') g.__name = (fn: unknown) => fn\n if (typeof g.__publicField !== 'function') g.__publicField = (obj: Record<string, unknown>, key: string, value: unknown) => { obj[key] = value; return value }\n })\n }\n\n async navigateToSERP(\n query: string,\n uule: UuleString | null,\n gl: string,\n hl: string,\n options?: { num?: number; debug?: boolean },\n ): Promise<{ hasPaa: boolean }> {\n const params = new URLSearchParams({ q: query, gl, hl, pws: '0' })\n if (options?.num) params.set('num', String(options.num))\n if (uule) params.set('uule', uule)\n const url = 'https://www.google.com/search?' + params.toString()\n const navDebug: SerpNavigationDebug | null = options?.debug\n ? {\n requestedUrl: url,\n finalUrl: null,\n title: null,\n bodySnippet: null,\n hasPaa: null,\n captchaDetected: null,\n googleSorryUrl: null,\n redirected: null,\n }\n : null\n if (navDebug) this.debugSnapshot.serpNavigation = navDebug\n\n try {\n await this.page!.goto(url, { waitUntil: 'domcontentloaded', timeout: 45_000 })\n } catch (err) {\n await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: null, captchaDetected: null })\n const diag = await this.captureDiagnostics(url)\n throw new ExtractionError(`page.goto failed: ${(err as Error).message} | ${diag}`)\n }\n\n const captchaCount = await this.page!.locator(PAASelectors.captchaMarker).count()\n if (captchaCount > 0) {\n await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: false, captchaDetected: true })\n throw new CaptchaError(this.captchaMessage())\n }\n\n const fastFound = await this.page!.waitForSelector(PAASelectors.item, { timeout: 4_000 }).catch(() => null)\n if (fastFound) {\n await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: true, captchaDetected: false })\n return { hasPaa: true }\n }\n\n const captchaAfter = await this.page!.locator(PAASelectors.captchaMarker).count()\n if (captchaAfter > 0) {\n await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: false, captchaDetected: true })\n throw new CaptchaError(this.captchaMessage())\n }\n\n for (let i = 1; i <= 6; i++) {\n await this.page!.evaluate((f: number) => { window.scrollTo(0, document.body.scrollHeight * f) }, i / 6)\n await this.page!.waitForTimeout(600)\n const count = await this.page!.locator(PAASelectors.item).count()\n if (count > 0) {\n await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: true, captchaDetected: false })\n return { hasPaa: true }\n }\n }\n\n await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: false, captchaDetected: false })\n return { hasPaa: false }\n }\n\n private async updateSerpNavigationDebug(\n navDebug: SerpNavigationDebug | null,\n requestedUrl: string,\n state: { hasPaa: boolean | null; captchaDetected: boolean | null },\n ): Promise<void> {\n if (!navDebug || !this.page) return\n try {\n const finalUrl = this.page.url()\n const title = await this.page.title().catch(() => '')\n const bodySnippet = await this.page.evaluate(() => {\n const text = (document.body?.innerText ?? '').replace(/\\s+/g, ' ').trim()\n return text.slice(0, 500)\n }).catch(() => '')\n const textCaptcha = /recaptcha|unusual traffic|are you a robot/i.test(bodySnippet)\n navDebug.finalUrl = finalUrl\n navDebug.title = title\n navDebug.bodySnippet = bodySnippet\n navDebug.hasPaa = state.hasPaa\n navDebug.captchaDetected = state.captchaDetected ?? textCaptcha\n navDebug.googleSorryUrl = /google\\.[^/]+\\/sorry\\//i.test(finalUrl)\n navDebug.redirected = finalUrl !== requestedUrl\n } catch (err) {\n navDebug.bodySnippet = `debug capture failed: ${errorText(err)}`\n }\n }\n\n private async captureDiagnostics(intendedUrl: string): Promise<string> {\n try {\n const finalUrl = this.page!.url()\n const title = await this.page!.title().catch(() => '')\n const bodySnippet = await this.page!.evaluate(() => {\n const t = (document.body?.innerText ?? '').replace(/\\s+/g, ' ').trim()\n return t.slice(0, 400)\n }).catch(() => '')\n const consent = /consent\\.google\\./.test(finalUrl) || /before you continue/i.test(bodySnippet)\n const recaptcha = /recaptcha|unusual traffic|are you a robot/i.test(bodySnippet)\n const flags = [\n consent ? 'CONSENT_WALL' : '',\n recaptcha ? 'BOT_CHALLENGE' : '',\n finalUrl !== intendedUrl ? 'REDIRECTED' : '',\n ].filter(Boolean).join(',')\n return `intended=${intendedUrl} | final=${finalUrl} | title=\"${title}\" | flags=[${flags}] | body=\"${bodySnippet}\"`\n } catch (e) {\n return `diagnostics-failed: ${(e as Error).message}`\n }\n }\n\n private captchaMessage(): string {\n return this.kernelClient\n ? 'Google returned a CAPTCHA on this session — retrying with a fresh session.'\n : RECAPTCHA_INSTRUCTIONS\n }\n\n async navigateTo(url: string): Promise<void> {\n try {\n await this.page!.goto(url, { waitUntil: 'domcontentloaded', timeout: 45_000 })\n } catch (err) {\n const diag = await this.captureDiagnostics(url)\n throw new ExtractionError(`page.goto failed: ${(err as Error).message} | ${diag}`)\n }\n }\n\n async navigateToChannel(channelHandle: string): Promise<void> {\n const url = buildYouTubeChannelVideosUrl(channelHandle)\n try {\n await this.page!.goto(url, { waitUntil: 'networkidle', timeout: 30_000 })\n } catch (err) {\n const diag = await this.captureDiagnostics(url)\n throw new ExtractionError(`navigateToChannel failed: ${(err as Error).message} | ${diag}`)\n }\n }\n\n async evaluate<T>(fn: (...args: unknown[]) => T | Promise<T>, arg?: unknown): Promise<T> {\n return (this.page! as { evaluate(fn: unknown, arg?: unknown): Promise<T> }).evaluate(fn, arg)\n }\n\n getPage(): Page {\n return this.page!\n }\n\n getKernelSessionId(): string | null {\n return this.kernelSessionId\n }\n\n getDebugSnapshot(): BrowserDebugSnapshot {\n return this.debugSnapshot\n }\n\n async close(): Promise<BrowserCloseResult> {\n if (this.browser) {\n const b = this.browser\n const sessionId = this.kernelSessionId\n const client = this.kernelClient\n this.browser = null\n this.context = null\n this.page = null\n this.kernelSessionId = null\n this.kernelClient = null\n if (client && sessionId) {\n console.info(JSON.stringify({\n event: 'kernel_browser_delete_started',\n kernel_session_id: sessionId,\n }))\n const deleteSession = withTimeout(\n client.browsers.deleteByID(sessionId),\n KERNEL_SESSION_DELETE_TIMEOUT_MS,\n `Kernel session ${sessionId} delete`,\n )\n const closeBrowser = withTimeout(\n b.close(),\n KERNEL_BROWSER_CLOSE_TIMEOUT_MS,\n `Kernel browser ${sessionId} close`,\n )\n const [deleteResult, closeResult] = await Promise.allSettled([deleteSession, closeBrowser])\n const result: BrowserCloseResult = {\n kernelSessionId: sessionId,\n kernelDeleteStarted: true,\n kernelDeleteSucceeded: deleteResult.status === 'fulfilled',\n kernelDeleteError: deleteResult.status === 'rejected'\n ? (deleteResult.reason instanceof Error ? deleteResult.reason.message : String(deleteResult.reason))\n : null,\n browserCloseSucceeded: closeResult.status === 'fulfilled',\n browserCloseError: closeResult.status === 'rejected'\n ? (closeResult.reason instanceof Error ? closeResult.reason.message : String(closeResult.reason))\n : null,\n }\n if (deleteResult.status === 'rejected') {\n console.warn(JSON.stringify({\n event: 'kernel_browser_delete_failed',\n kernel_session_id: sessionId,\n message: result.kernelDeleteError,\n }))\n console.warn(`Kernel session cleanup failed for ${sessionId}:`, deleteResult.reason)\n } else {\n console.info(JSON.stringify({\n event: 'kernel_browser_delete_succeeded',\n kernel_session_id: sessionId,\n }))\n }\n if (closeResult.status === 'rejected') {\n console.warn(JSON.stringify({\n event: 'kernel_browser_close_failed',\n kernel_session_id: sessionId,\n message: result.browserCloseError,\n }))\n console.warn(`Kernel browser close failed for ${sessionId}:`, closeResult.reason)\n }\n return result\n }\n await b.close()\n return {\n kernelSessionId: null,\n kernelDeleteStarted: false,\n kernelDeleteSucceeded: null,\n kernelDeleteError: null,\n browserCloseSucceeded: true,\n browserCloseError: null,\n }\n } else if (this.context) {\n const ctx = this.context\n this.context = null\n this.page = null\n await ctx.close()\n return {\n kernelSessionId: null,\n kernelDeleteStarted: false,\n kernelDeleteSucceeded: null,\n kernelDeleteError: null,\n browserCloseSucceeded: true,\n browserCloseError: null,\n }\n }\n return {\n kernelSessionId: null,\n kernelDeleteStarted: false,\n kernelDeleteSucceeded: null,\n kernelDeleteError: null,\n browserCloseSucceeded: null,\n browserCloseError: null,\n }\n }\n}\n","export const PAASelectors = {\n container: '.eJH8qe.adDDi',\n dataInitq: '[data-initq]',\n item: '.related-question-pair',\n itemDataQ: 'data-q',\n itemDataInitQ: 'data-initq',\n itemQuestionEl: '.JlqpRe',\n answerContainer: '.bCOlv, .hgKElc, .wDYxhc, .LGOjhe, .fo7IQd, .fmW3u',\n sourceTitle: 'h3',\n sourceSite: '.VuuXrf',\n sourceCite: 'cite',\n clickTarget: '.JlqpRe',\n expandedClass: 'aoRk1c',\n captchaMarker: '#captcha-form, #recaptcha, form[action*=\"/sorry/\"], .g-recaptcha, [data-sitekey]',\n} as const\n\nexport const VideoSelectors = {\n container: 'div[jscontroller=\"HWk0Gf\"]',\n sectionHeading: '.mgAbYb[role=\"heading\"]',\n item: 'a.rIRoqf',\n} as const\n\nexport const ShortVideoSelectors = {\n udm: '39',\n item: 'a.rIRoqf',\n durationPattern: /^\\d+:\\d+$/,\n platforms: ['YouTube', 'TikTok', 'Instagram', 'Facebook', 'X'],\n} as const\n\nexport const ForumSelectors = {\n section: '.ULSxyf',\n item: 'a.KYg7td.INpicf',\n title: '.hyYc0c',\n source: '.K4ETW',\n} as const\n\nexport const WhatPeopleSayingSelectors = {\n sectionTag: 'g-section-with-header',\n sectionHeadingText: 'What people are saying',\n card: '.dRzkFf[role=\"listitem\"]',\n cardLink: 'a.WlydOe[jsname=\"YKoRaf\"]',\n titleH1: 'h1.WQWxe',\n titleDiv: '.eAaXgc',\n popularCommentLabel: '.qgdis',\n source: '.sTl1Td',\n platformBadge: '.appd0, .KrMNbf',\n ytChannel: '.sjVJQd',\n ytDate: '.PLq9Je',\n authorNote: '.nDgy9d',\n} as const\n\nexport const AIOverviewSelectors = {\n root: '[data-lhcontainer][data-streaming-container][eid]',\n legacyRoot: '[data-hveid=\"CBMQAA\"]',\n wrapper: '.Fgyi2e',\n controller: '[jscontroller=\"AkrxPe\"]',\n contentSubtree: '[data-subtree=\"mfc\"]',\n header: '.heWuVc',\n heading: '.Fzsovc.cwYVJe.RJPOee',\n showMoreButton: '[aria-label=\"Show more AI Overview\"]',\n sourcesPanel: '.OZ9ddf.WAUd4',\n disclaimer: '.DuQANe.MSJHRb',\n} as const\n\nexport const AIModeSelectors = {\n root: '[data-hveid=\"CAUQAA\"]',\n wrapper: '.Fgyi2e',\n citations: '.Fgyi2e [data-hveid] a[jsname=\"pxBnId\"]',\n} as const\n\nexport const OrganicSelectors = {\n result: '.wHYlTd.tF2Cxc',\n title: 'h3.LC20lb',\n siteName: '.VuuXrf',\n cite: 'cite.tjvcx',\n snippet: '.VwiC3b',\n redditCite: 'cite.qLRx3b',\n ratingWrap: '.Y0A0hc',\n ratingValue: '.yi40Hd',\n reviewCount: '.RDApEe',\n} as const\n\nexport const LocalPackSelectors = {\n headingText: 'Businesses',\n card: '.w7Dbne',\n name: '.OSrXXb',\n ratingValue: '.yi40Hd',\n reviewCount: '.RDApEe',\n} as const\n\nexport const SELECTORS_VERSION = '2026-05-07'\n\nexport const MapsSelectors = {\n ratingAndCount: 'div.F7nice',\n hoursTable: 'table.eK4R0e',\n reviewScrollPane: 'div.m6QErb[tabindex=\"-1\"]',\n reviewScrollPaneFallback: '[role=\"main\"] div[tabindex=\"-1\"]',\n reviewCardAuthor: 'div.d4r55, span.d4r55, span.RPZfBb',\n reviewCardDate: 'span.rsqaWe',\n reviewCardText: 'span.wiI7pd',\n reviewCardOwnerBlock: 'div.CDe7pd',\n hoursTableAlt: 'table[aria-label*=\"Hour\"]',\n reviewCard: '[data-review-id]',\n reviewStars: '[role=\"img\"][aria-label*=\"star\"]',\n reviewTab: 'button[role=\"tab\"][aria-label*=\"Review\"]',\n aboutTab: 'button[role=\"tab\"][aria-label*=\"About\"]',\n expandReview: '[data-review-id] button[aria-label*=\"See more\"], [data-review-id] button.w8nwRe',\n} as const\n\nexport const MAPS_SELECTORS_VERSION = '2026-05-23'\n","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\nexport class RequestAbortedError extends Error {\n readonly name = 'RequestAbortedError'\n constructor(message = 'Request aborted before harvest completed') {\n super(message)\n }\n}\n","import type { CanonicalLocationName } from './types.js'\n\nexport const LOCATIONS: Record<string, CanonicalLocationName> = {\n 'austin': 'Austin,Texas,United States',\n 'new york': 'New York,New York,United States',\n 'new york city': 'New York,New York,United States',\n 'nyc': 'New York,New York,United States',\n 'los angeles': 'Los Angeles,California,United States',\n 'la': 'Los Angeles,California,United States',\n 'chicago': 'Chicago,Illinois,United States',\n 'houston': 'Houston,Texas,United States',\n 'phoenix': 'Phoenix,Arizona,United States',\n 'philadelphia': 'Philadelphia,Pennsylvania,United States',\n 'philly': 'Philadelphia,Pennsylvania,United States',\n 'san antonio': 'San Antonio,Texas,United States',\n 'dallas': 'Dallas,Texas,United States',\n 'miami': 'Miami,Florida,United States',\n 'seattle': 'Seattle,Washington,United States',\n 'denver': 'Denver,Colorado,United States',\n 'loveland': 'Loveland,Colorado,United States',\n 'loveland co': 'Loveland,Colorado,United States',\n 'fort collins': 'Fort Collins,Colorado,United States',\n 'boulder': 'Boulder,Colorado,United States',\n 'colorado springs': 'Colorado Springs,Colorado,United States',\n 'boston': 'Boston,Massachusetts,United States',\n 'atlanta': 'Atlanta,Georgia,United States',\n 'san francisco': 'San Francisco,California,United States',\n 'sf': 'San Francisco,California,United States',\n 'portland': 'Portland,Oregon,United States',\n 'las vegas': 'Las Vegas,Nevada,United States',\n 'minneapolis': 'Minneapolis,Minnesota,United States',\n 'detroit': 'Detroit,Michigan,United States',\n 'nashville': 'Nashville,Tennessee,United States',\n 'charlotte': 'Charlotte,North Carolina,United States',\n 'orlando': 'Orlando,Florida,United States',\n 'san diego': 'San Diego,California,United States',\n 'baltimore': 'Baltimore,Maryland,United States',\n 'sacramento': 'Sacramento,California,United States',\n 'columbus': 'Columbus,Ohio,United States',\n 'indianapolis': 'Indianapolis,Indiana,United States',\n 'san jose': 'San Jose,California,United States',\n 'fort worth': 'Fort Worth,Texas,United States',\n 'jacksonville': 'Jacksonville,Florida,United States',\n 'memphis': 'Memphis,Tennessee,United States',\n 'louisville': 'Louisville,Kentucky,United States',\n 'raleigh': 'Raleigh,North Carolina,United States',\n 'richmond': 'Richmond,Virginia,United States',\n 'salt lake city': 'Salt Lake City,Utah,United States',\n 'toronto': 'Toronto,Ontario,Canada',\n 'vancouver': 'Vancouver,British Columbia,Canada',\n 'montreal': 'Montreal,Quebec,Canada',\n 'calgary': 'Calgary,Alberta,Canada',\n 'ottawa': 'Ottawa,Ontario,Canada',\n 'london': 'London,England,United Kingdom',\n 'manchester': 'Manchester,England,United Kingdom',\n 'birmingham': 'Birmingham,England,United Kingdom',\n 'edinburgh': 'Edinburgh,Scotland,United Kingdom',\n 'glasgow': 'Glasgow,Scotland,United Kingdom',\n 'leeds': 'Leeds,England,United Kingdom',\n 'sydney': 'Sydney,New South Wales,Australia',\n 'melbourne': 'Melbourne,Victoria,Australia',\n 'brisbane': 'Brisbane,Queensland,Australia',\n 'perth': 'Perth,Western Australia,Australia',\n 'adelaide': 'Adelaide,South Australia,Australia',\n 'dublin': 'Dublin,Leinster,Ireland',\n}\n","import type { CanonicalLocationName, UuleString } from './types.js'\nimport { LOCATIONS } from './locations.js'\n\nfunction encodeVarint(value: number): number[] {\n const bytes: number[] = []\n let remaining = value\n do {\n let byte = remaining & 0x7f\n remaining >>>= 7\n if (remaining > 0) byte |= 0x80\n bytes.push(byte)\n } while (remaining > 0)\n return bytes\n}\n\nexport function encodeUule(name: CanonicalLocationName): UuleString {\n const locationBytes = Buffer.from(name, 'utf8')\n const payload = Buffer.concat([\n Buffer.from([0x08, 0x02, 0x10, 0x20, 0x22]),\n Buffer.from(encodeVarint(locationBytes.length)),\n locationBytes,\n ])\n return `w+${payload.toString('base64')}`\n}\n\nexport function normalizeLocation(input: string): CanonicalLocationName {\n const raw = input.toLowerCase().trim()\n if (LOCATIONS[raw]) return LOCATIONS[raw] as CanonicalLocationName\n const beforeComma = raw.split(',')[0].trim()\n if (beforeComma !== raw && LOCATIONS[beforeComma]) return LOCATIONS[beforeComma] as CanonicalLocationName\n const withoutState = raw.replace(/\\s+[a-z]{2}$/, '').trim()\n if (withoutState !== raw && LOCATIONS[withoutState]) return LOCATIONS[withoutState] as CanonicalLocationName\n return input as CanonicalLocationName\n}\n","import type { CanonicalLocationName, LocalPackBusiness, OrganicResult, SerpLocationCandidate, SerpLocationEvidence } from './types.js'\n\nconst STATE_TO_CODE: Record<string, string> = {\n alabama: 'AL', alaska: 'AK', arizona: 'AZ', arkansas: 'AR', california: 'CA',\n colorado: 'CO', connecticut: 'CT', delaware: 'DE', florida: 'FL', georgia: 'GA',\n hawaii: 'HI', idaho: 'ID', illinois: 'IL', indiana: 'IN', iowa: 'IA',\n kansas: 'KS', kentucky: 'KY', louisiana: 'LA', maine: 'ME', maryland: 'MD',\n massachusetts: 'MA', michigan: 'MI', minnesota: 'MN', mississippi: 'MS', missouri: 'MO',\n montana: 'MT', nebraska: 'NE', nevada: 'NV', 'new hampshire': 'NH', 'new jersey': 'NJ',\n 'new mexico': 'NM', 'new york': 'NY', 'north carolina': 'NC', 'north dakota': 'ND', ohio: 'OH',\n oklahoma: 'OK', oregon: 'OR', pennsylvania: 'PA', 'rhode island': 'RI', 'south carolina': 'SC',\n 'south dakota': 'SD', tennessee: 'TN', texas: 'TX', utah: 'UT', vermont: 'VT',\n virginia: 'VA', washington: 'WA', 'west virginia': 'WV', wisconsin: 'WI', wyoming: 'WY',\n 'district of columbia': 'DC',\n}\n\nconst STATE_PATTERN = [\n ...Object.keys(STATE_TO_CODE).map(s => s.replace(/\\s+/g, '\\\\s+')),\n ...Object.values(STATE_TO_CODE),\n].join('|')\n\nconst CITY_STATE_RE = new RegExp(`\\\\b([A-Z][A-Za-z]+(?:[\\\\s.-][A-Z][A-Za-z]+){0,4}),?\\\\s+(${STATE_PATTERN})\\\\b`, 'gi')\n\nfunction normalizeRegionCode(input: string | null | undefined): string | null {\n if (!input) return null\n const trimmed = input.trim()\n if (/^[A-Z]{2}$/i.test(trimmed)) return trimmed.toUpperCase()\n return STATE_TO_CODE[trimmed.toLowerCase()] ?? null\n}\n\nfunction normalizeCity(input: string): string {\n const cleaned = input\n .replace(/\\s+/g, ' ')\n .trim()\n .replace(/^.*\\b(?:in|near|around|serving)\\s+/i, '')\n return cleaned.toLowerCase().replace(/\\b[a-z]/g, char => char.toUpperCase())\n}\n\nfunction parseExpected(canonicalLocation: CanonicalLocationName | null): SerpLocationEvidence['expected'] {\n if (!canonicalLocation) return null\n const [city = '', region = ''] = canonicalLocation.split(',').map(part => part.trim())\n return {\n city: normalizeCity(city),\n regionCode: normalizeRegionCode(region),\n canonicalLocation,\n }\n}\n\nfunction addCandidate(\n candidates: Map<string, SerpLocationCandidate>,\n city: string,\n region: string,\n example: string,\n): void {\n const normalizedCity = normalizeCity(city)\n const regionCode = normalizeRegionCode(region)\n if (!normalizedCity || !regionCode) return\n const key = `${normalizedCity.toLowerCase()}|${regionCode}`\n const existing = candidates.get(key)\n if (existing) {\n existing.count++\n if (existing.examples.length < 3 && !existing.examples.includes(example)) existing.examples.push(example)\n return\n }\n candidates.set(key, { city: normalizedCity, regionCode, count: 1, examples: [example] })\n}\n\nfunction scanText(candidates: Map<string, SerpLocationCandidate>, text: string): void {\n const normalized = decodeURIComponent(text).replace(/[+/|_-]+/g, ' ')\n for (const match of normalized.matchAll(CITY_STATE_RE)) {\n addCandidate(candidates, match[1] ?? '', match[2] ?? '', normalized.slice(0, 180))\n }\n}\n\nexport function inferSerpLocationEvidence(\n canonicalLocation: CanonicalLocationName | null,\n organicResults: OrganicResult[],\n localPack: LocalPackBusiness[],\n): SerpLocationEvidence {\n const expected = parseExpected(canonicalLocation)\n const candidates = new Map<string, SerpLocationCandidate>()\n\n for (const result of organicResults) {\n scanText(candidates, [result.title, result.snippet ?? '', result.cite ?? '', result.url].join(' '))\n }\n for (const business of localPack) {\n scanText(candidates, [business.name, ...business.metadata, business.websiteUrl ?? '', business.directionsUrl ?? ''].join(' '))\n }\n\n const rankedCandidates = Array.from(candidates.values())\n .sort((a, b) => b.count - a.count || a.city.localeCompare(b.city))\n .slice(0, 8)\n\n if (!expected) {\n return { status: 'not_requested', expected: null, candidates: rankedCandidates }\n }\n if (rankedCandidates.length === 0) {\n return { status: 'unknown', expected, candidates: [] }\n }\n\n const matched = rankedCandidates.some(candidate =>\n candidate.city.toLowerCase() === expected.city.toLowerCase()\n && (expected.regionCode == null || candidate.regionCode === expected.regionCode)\n )\n\n return {\n status: matched ? 'matched' : 'mismatch',\n expected,\n candidates: rankedCandidates,\n }\n}\n","const MAX_ANSWER_LENGTH = 1200\n\nconst BOILERPLATE_PATTERNS: RegExp[] = [\n /An AI Overview is not available for this search/gi,\n /Can't generate an AI overview right now\\.?\\s*Try again later\\.?/gi,\n /\\bAI Overview\\b/gi,\n /\\bView all\\b/gi,\n]\n\nconst CUT_MARKERS: RegExp[] = [\n /\\bRelated Links\\b/i,\n /\\bAsk anything in\\s*AI Mode\\b/i,\n /\\bAI can make mistakes\\b/i,\n /\\bThis is for informational purposes only\\b/i,\n /\\bShow more\\b/i,\n /\\b\\d+\\s+sites\\b/i,\n /\\b\\d{1,2}\\s*[msh]\\s*[A-Z][A-Za-z]/,\n /\\b(?:YouTube|Reddit|Facebook|Instagram|TikTok)·/,\n]\n\nfunction normalizeWhitespace(text: string): string {\n return text\n .replace(/\\u00a0/g, ' ')\n .replace(/([.!?])([A-Z])/g, '$1 $2')\n .replace(/([:;])([A-Z])/g, '$1 $2')\n .replace(/([a-z])([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([A-Z][a-z])/g, '$1 $2')\n .replace(/([a-z])(\\d)/g, '$1 $2')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\nfunction cutAtFirstMarker(text: string): string {\n let cutAt = -1\n for (const marker of CUT_MARKERS) {\n const match = marker.exec(text)\n marker.lastIndex = 0\n if (match && (cutAt === -1 || match.index < cutAt)) cutAt = match.index\n }\n return cutAt === -1 ? text : text.slice(0, cutAt)\n}\n\nfunction cutAtSourceTitle(text: string, sourceTitle?: string): string {\n const title = sourceTitle?.trim()\n if (!title || title.length < 8) return text\n const idx = text.toLowerCase().indexOf(title.toLowerCase())\n return idx > 40 ? text.slice(0, idx) : text\n}\n\nfunction findAttributionCut(beforeUrl: string): number {\n const dateMatch = beforeUrl.match(/[•·]\\s*(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\\.?\\s+\\d{1,2},\\s+\\d{4}/i)\n if (dateMatch?.index && dateMatch.index > 40) return dateMatch.index\n\n const start = Math.max(0, beforeUrl.length - 260)\n const tail = beforeUrl.slice(start)\n const sentenceBreaks = [...tail.matchAll(/[.!?]\\s*(?=[A-Z][A-Za-z0-9\"'$])/g)]\n for (const match of sentenceBreaks) {\n const remainder = tail.slice(match.index + 1).trim()\n const lead = remainder.slice(0, 160)\n const looksLikeTitle = /^(?:Best|Top|What|How|Why|When|Where|Which|Can|Should|Is|Are|Do|Does)\\b/i.test(remainder)\n if (\n remainder.length > 20 &&\n looksLikeTitle &&\n /(?:\\s[-|]\\s|Heating|Cooling|Company|Services|Blog|Guide|Review)/i.test(lead)\n ) {\n return start + match.index + 1\n }\n }\n const last = sentenceBreaks.at(-1)\n if (last?.index !== undefined) return start + last.index + 1\n\n return beforeUrl.length\n}\n\nfunction cutAtUrlAttribution(text: string): string {\n const urlMatch = text.match(/https?:\\/\\/\\S+/i)\n if (!urlMatch?.index) return text\n\n const beforeUrl = text.slice(0, urlMatch.index)\n return beforeUrl.slice(0, findAttributionCut(beforeUrl))\n}\n\nfunction trimToSentenceLimit(text: string): string {\n if (text.length <= MAX_ANSWER_LENGTH) return text\n const slice = text.slice(0, MAX_ANSWER_LENGTH)\n const lastSentence = Math.max(slice.lastIndexOf('.'), slice.lastIndexOf('!'), slice.lastIndexOf('?'))\n return (lastSentence > 240 ? slice.slice(0, lastSentence + 1) : slice).trim()\n}\n\nexport function cleanPAAAnswerText(\n answer: string | null | undefined,\n question?: string,\n sourceTitle?: string,\n): string | undefined {\n if (!answer) return undefined\n\n let text = normalizeWhitespace(answer)\n const normalizedQuestion = question ? normalizeWhitespace(question) : ''\n if (normalizedQuestion && text.toLowerCase().startsWith(normalizedQuestion.toLowerCase())) {\n text = text.slice(normalizedQuestion.length).trim()\n }\n\n if (/^An error has occurred\\.?\\s*Please try again later\\.?/i.test(text)) {\n return undefined\n }\n\n for (const pattern of BOILERPLATE_PATTERNS) {\n text = text.replace(pattern, ' ')\n }\n text = text\n .replace(/\\b[A-Z][A-Za-z&'\\u2019 -]{2,60}\\+\\d+\\b/g, ' ')\n .replace(/\\b(?:[a-z0-9-]+\\.)+[a-z]{2,}\\+\\d+\\b/gi, ' ')\n\n text = normalizeWhitespace(text)\n text = cutAtFirstMarker(text)\n text = cutAtSourceTitle(text, sourceTitle)\n text = cutAtUrlAttribution(text)\n text = normalizeWhitespace(text)\n text = text.replace(/\\s+(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\\.?\\s+\\d{1,2},\\s+\\d{4}$/i, '').trim()\n text = trimToSentenceLimit(text)\n\n if (!text) return undefined\n if (/^An error has occurred\\.?\\s*Please try again later\\.?$/i.test(text)) return undefined\n\n return text\n}\n","export interface AISurfaceSelectorConfig {\n aio: {\n root: string\n legacyRoot?: string\n wrapper?: string\n controller: string\n contentSubtree: string\n heading: string\n header: string\n showMoreButton: string\n sourcesPanel: string\n disclaimer: string\n }\n aim: {\n root: string\n wrapper: string\n }\n expandWaitMs?: number\n}\n\nexport async function extractAISurfacesFromDocument(config?: AISurfaceSelectorConfig): Promise<{\n surface: 'web' | 'aim' | 'unknown'\n aiOverview: {\n detected: boolean\n text: string | null\n citations: Array<{ text: string; href: string }>\n expanded: boolean\n fullyExpanded: boolean\n sections: string[]\n }\n aiMode: {\n detected: boolean\n text: string | null\n citations: Array<{ text: string; href: string }>\n }\n}> {\n const selectors = config ?? {\n aio: {\n root: '[data-lhcontainer][data-streaming-container][eid]',\n legacyRoot: '[data-hveid=\"CBMQAA\"]',\n wrapper: '.Fgyi2e',\n controller: '[jscontroller=\"AkrxPe\"]',\n contentSubtree: '[data-subtree=\"mfc\"]',\n heading: '.Fzsovc.cwYVJe.RJPOee',\n header: '.heWuVc',\n showMoreButton: '[aria-label=\"Show more AI Overview\"]',\n sourcesPanel: '.OZ9ddf.WAUd4',\n disclaimer: '.DuQANe.MSJHRb',\n },\n aim: {\n root: '[data-hveid=\"CAUQAA\"]',\n wrapper: '.Fgyi2e',\n },\n expandWaitMs: 1500,\n }\n\n const sn: string = (window as unknown as { google?: { sn?: string } }).google?.sn ?? 'unknown'\n const surface: 'web' | 'aim' | 'unknown' =\n sn === 'aim' ? 'aim' : sn === 'web' ? 'web' : 'unknown'\n\n function textOf(el: Element | null): string {\n if (!el) return ''\n return ((el as HTMLElement).innerText ?? el.textContent ?? '').trim()\n }\n\n function hasAIOverviewLabel(el: Element): boolean {\n const heading = el.querySelector(selectors.aio.heading)\n if (textOf(heading) === 'AI Overview') return true\n const header = el.querySelector(selectors.aio.header)\n if (textOf(header).split(/\\n|\\s{2,}/).some(part => part.trim() === 'AI Overview')) return true\n return textOf(el).includes('AI Overview')\n }\n\n function findAIORoot(): Element | null {\n const primaryRoots = Array.from(document.querySelectorAll(selectors.aio.root))\n const labeledPrimary = primaryRoots.find(hasAIOverviewLabel)\n if (labeledPrimary) return labeledPrimary\n if (primaryRoots.length > 0) return primaryRoots[0]\n\n if (selectors.aio.legacyRoot) {\n const legacy = document.querySelector(selectors.aio.legacyRoot)\n if (legacy) return legacy\n }\n\n const headings = document.querySelectorAll(`${selectors.aio.heading}, h1, h2, h3, [role=\"heading\"]`)\n for (const h of headings) {\n if (textOf(h) !== 'AI Overview') continue\n let el: Element | null = h.parentElement\n for (let i = 0; i < 8 && el; i++) {\n if (\n el.matches(selectors.aio.root) ||\n el.querySelector(selectors.aio.controller) ||\n el.querySelector(selectors.aio.contentSubtree)\n ) {\n return el\n }\n el = el.parentElement\n }\n return h.parentElement\n }\n return null\n }\n\n function cleanText(target: Element | null): string | null {\n if (!target) return null\n const clone = target.cloneNode(true) as Element\n clone.querySelectorAll([\n 'script',\n 'style',\n 'noscript',\n 'img',\n 'picture',\n 'video',\n selectors.aio.header,\n selectors.aio.showMoreButton,\n selectors.aio.sourcesPanel,\n selectors.aio.disclaimer,\n '[data-subtree=\"dfa\"]',\n '[data-src-id]',\n '[role=\"dialog\"]',\n '.HWMcu',\n '.bTFeG',\n '.CyMdWb',\n '.MFrAxb',\n '.F0OfWd.hfWAgb',\n '.x2qcTc.fZavHb',\n '.SvjEff',\n '.sR2MY',\n '.lKuDef',\n '.GSPQcc',\n 'a[href]',\n 'button',\n '[role=\"button\"]',\n ].join(',')).forEach(el => el.remove())\n\n const holder = document.createElement('div')\n holder.style.position = 'fixed'\n holder.style.left = '-10000px'\n holder.style.top = '0'\n holder.style.width = `${Math.max(320, Math.round((target as HTMLElement).getBoundingClientRect?.().width || 960))}px`\n holder.style.opacity = '0'\n holder.style.pointerEvents = 'none'\n holder.append(clone)\n document.body.append(holder)\n\n const rendered = ((clone as HTMLElement).innerText || clone.textContent || '')\n holder.remove()\n\n const lines = rendered\n .replace(/\\r/g, '')\n .replace(/[ \\t]+\\n/g, '\\n')\n .replace(/\\n[ \\t]+/g, '\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .replace(/[ \\t]{2,}/g, ' ')\n .trim()\n .split('\\n')\n .map(line => line.replace(/\\u00a0/g, ' ').trim())\n .filter(Boolean)\n\n const filteredLines: string[] = []\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]\n const next = lines[i + 1] ?? ''\n if (line === 'AI Overview') continue\n if (line === 'Show more') continue\n if (/^AI can make mistakes/i.test(line)) continue\n if (/^Thank you\\b/i.test(line)) continue\n if (/^Your feedback helps Google improve/i.test(line)) continue\n if (/^\\+?\\d+$/.test(line)) continue\n if (/^\\+\\d+$/.test(next) && line.length <= 80) {\n i++\n continue\n }\n filteredLines.push(line)\n }\n\n const raw = filteredLines\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim()\n\n if (!raw || /not available|try again|can't generate/i.test(raw)) return null\n return raw\n }\n\n function normalizeHref(rawHref: string): string | null {\n if (!rawHref || rawHref.startsWith('javascript:')) return null\n let href = rawHref\n try {\n const absolute = new URL(rawHref, window.location.href)\n const q = absolute.searchParams.get('q') ?? absolute.searchParams.get('url')\n if (/(\\.|^)google\\./i.test(absolute.hostname) && q?.startsWith('http')) {\n href = q\n } else {\n href = absolute.href\n }\n } catch {\n return null\n }\n\n if (!/^https?:\\/\\//i.test(href)) return null\n try {\n const url = new URL(href)\n const isGoogleInternal = /(\\.|^)google\\./i.test(url.hostname)\n if (isGoogleInternal) return null\n return url.href\n } catch {\n return null\n }\n }\n\n function extractCitations(root: Element | null): Array<{ text: string; href: string }> {\n if (!root) return []\n const seen = new Set<string>()\n const citations: Array<{ text: string; href: string }> = []\n\n for (const a of Array.from(root.querySelectorAll('a[href]'))) {\n const href = normalizeHref(a.getAttribute('href') ?? '')\n if (!href || seen.has(href)) continue\n seen.add(href)\n\n let fallbackHost = ''\n try {\n fallbackHost = new URL(href).hostname.replace(/^www\\./, '')\n } catch {}\n\n citations.push({\n text: textOf(a) || fallbackHost || href,\n href,\n })\n }\n\n return citations\n }\n\n async function maybeExpand(root: Element): Promise<boolean> {\n const button = root.querySelector(selectors.aio.showMoreButton)\n if (!button || button.getAttribute('aria-expanded') !== 'false') return false\n ;(button as HTMLElement).click()\n const waitMs = selectors.expandWaitMs ?? 1500\n if (waitMs > 0) await new Promise(resolve => setTimeout(resolve, waitMs))\n return true\n }\n\n const aioRoot = findAIORoot()\n let aioText: string | null = null\n let aioCitations: Array<{ text: string; href: string }> = []\n let aioExpanded = false\n let aioFullyExpanded = false\n let aioSections: string[] = []\n\n if (aioRoot) {\n aioExpanded = await maybeExpand(aioRoot)\n const controller = aioRoot.querySelector(selectors.aio.controller)\n const contentSubtree = aioRoot.querySelector(selectors.aio.contentSubtree)\n const showMore = aioRoot.querySelector(selectors.aio.showMoreButton)\n aioFullyExpanded =\n controller?.getAttribute('data-trnct') === 'false' ||\n showMore?.getAttribute('aria-expanded') === 'true' ||\n !showMore\n\n aioText = cleanText(contentSubtree ?? controller ?? aioRoot)\n aioSections = (aioText ?? '')\n .split('\\n')\n .map(line => line.trim())\n .filter(line => /^\\d+\\.\\s+.+/.test(line))\n aioCitations = extractCitations(aioRoot)\n }\n\n const aimRoot = document.querySelector(selectors.aim.root)\n const aimDetected = surface === 'aim' && !!aimRoot\n const aimContainer = aimRoot?.closest(selectors.aim.wrapper) ?? aimRoot\n const aimText = cleanText(aimContainer)\n const aimCitations = aimDetected ? extractCitations(aimContainer) : []\n\n return {\n surface,\n aiOverview: {\n detected: !!aioRoot && aioText !== null,\n text: aioText,\n citations: aioCitations,\n expanded: aioExpanded,\n fullyExpanded: aioFullyExpanded,\n sections: aioSections,\n },\n aiMode: {\n detected: aimDetected && aimText !== null,\n text: aimText,\n citations: aimCitations,\n },\n }\n}\n","import type { Page } from 'playwright'\nimport type { IBrowserDriver } from '../driver/IBrowserDriver.js'\nimport type { IProgressReporter } from '../output/IProgressReporter.js'\nimport { PAASelectors, VideoSelectors, ForumSelectors, ShortVideoSelectors, AIOverviewSelectors, AIModeSelectors, WhatPeopleSayingSelectors, OrganicSelectors, LocalPackSelectors } from '../selectors.js'\nimport { encodeUule, normalizeLocation } from '../uule.js'\nimport { inferSerpLocationEvidence } from '../serp-location-debug.js'\nimport { RawPAAItemSchema } from '../schemas.js'\nimport { cleanPAAAnswerText } from '../lib/paa-answer-cleanup.js'\nimport { CaptchaError, RequestAbortedError } from '../errors.js'\nimport { extractAISurfacesFromDocument } from './ai-surfaces.js'\nimport type {\n HarvestOptions, HarvestResult, HarvestStats,\n RawPAAItem, PAANode, FlatRow, NormalizedQuestionKey, DriverConfig,\n VideoResult, ForumResult, AIOverviewResult, AIModeResult, GoogleSurface,\n WhatPeopleSayingCard, EntityIds, EntityRecord, HarvestDiagnosticWarning,\n OrganicResult, LocalPackBusiness, BrowserDebugSnapshot, HarvestDebugSnapshot, SerpLocationEvidence,\n} from '../types.js'\nimport type { IPAAExtractor } from './IPAAExtractor.js'\n\nconst DESKTOP_USER_AGENT =\n 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'\n\nconst MOBILE_USER_AGENT =\n 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1'\n\nexport class PAAExtractor implements IPAAExtractor {\n constructor(\n private readonly driver: IBrowserDriver,\n private readonly reporter: IProgressReporter,\n ) {}\n\n private normalizeQuestion(q: string): NormalizedQuestionKey {\n return q.toLowerCase().replace(/[^\\w\\s]/g, '').replace(/\\s+/g, ' ').trim() as NormalizedQuestionKey\n }\n\n private throwIfAborted(signal?: AbortSignal): void {\n if (!signal?.aborted) return\n if (signal.reason instanceof DOMException && signal.reason.name === 'TimeoutError') throw signal.reason\n throw new RequestAbortedError()\n }\n\n private async throwIfCaptcha(page: Page, context: string): Promise<void> {\n const captchaCount = await page.locator(PAASelectors.captchaMarker).count().catch(() => 0)\n if (captchaCount > 0) {\n throw new CaptchaError(`${context} returned a CAPTCHA — retrying with a fresh session.`)\n }\n }\n\n private async extractVisibleItems(page: Page): Promise<RawPAAItem[]> {\n const sels = PAASelectors\n const raw = await page.evaluate((selectors) => {\n function cleanText(el: Element | null): string {\n if (!el) return ''\n const parts: string[] = []\n for (const n of el.childNodes) {\n if (n.nodeType === Node.TEXT_NODE) {\n const text = n.textContent?.trim()\n if (text) parts.push(text)\n } else if (\n (n as Element).tagName === 'STYLE' ||\n (n as Element).tagName === 'SCRIPT'\n ) {\n continue\n } else {\n const text = cleanText(n as Element)\n if (text) parts.push(text)\n }\n }\n return parts.join(' ').replace(/\\s+/g, ' ').trim()\n }\n return Array.from(document.querySelectorAll(selectors.item)).map((pair) => ({\n question: pair.getAttribute(selectors.itemDataQ) || pair.getAttribute(selectors.itemDataInitQ) || '',\n answer: cleanText(pair.querySelector(selectors.answerContainer)) || undefined,\n sourceTitle: (pair.querySelector(selectors.sourceTitle) as HTMLElement | null)?.innerText?.trim() || undefined,\n sourceSite: (pair.querySelector(selectors.sourceSite) as HTMLElement | null)?.innerText?.trim() || undefined,\n sourceCite: (pair.querySelector(selectors.sourceCite) as HTMLElement | null)?.innerText?.trim() || undefined,\n }))\n }, sels)\n\n return raw.flatMap((item) => {\n const cleaned = {\n ...item,\n answer: cleanPAAAnswerText(item.answer, item.question, item.sourceTitle),\n }\n const result = RawPAAItemSchema.safeParse(cleaned)\n if (!result.success) {\n console.warn('[PAAExtractor] item parse failed:', item.question, result.error.issues[0]?.message)\n return []\n }\n return [result.data]\n })\n }\n\n private async clickItem(page: Page, questionText: string): Promise<void> {\n try {\n const pairLocator = page.locator(\n `${PAASelectors.item}[data-q=\"${questionText}\"], ${PAASelectors.item}[data-initq=\"${questionText}\"]`\n ).first()\n await pairLocator.click()\n } catch { }\n }\n\n private toFlatRow(item: RawPAAItem, depth: number, parentQuestion: string | null, seed: string): FlatRow {\n return {\n seed_query: seed,\n question: item.question,\n answer: item.answer ?? '',\n source_title: item.sourceTitle ?? '',\n source_site: item.sourceSite ?? '',\n source_cite: item.sourceCite ?? '',\n depth,\n parent_question: parentQuestion ?? '',\n extracted_at: new Date().toISOString(),\n }\n }\n\n private async runBFS(page: Page, options: HarvestOptions, signal?: AbortSignal): Promise<FlatRow[]> {\n const seenKeys = new Set<NormalizedQuestionKey>()\n const seenQs = new Set<string>()\n const orderedQs: string[] = []\n const results: FlatRow[] = []\n\n const readAllQs = (): Promise<string[]> =>\n page.evaluate(\n ({ sel, dataQ, dataInitQ, questionEl }: { sel: string; dataQ: string; dataInitQ: string; questionEl: string }) =>\n Array.from(document.querySelectorAll(sel))\n .map(el =>\n el.getAttribute(dataQ) ||\n el.getAttribute(dataInitQ) ||\n (el.querySelector(questionEl) as HTMLElement | null)?.innerText?.trim() ||\n ''\n )\n .filter(Boolean),\n { sel: PAASelectors.item, dataQ: PAASelectors.itemDataQ, dataInitQ: PAASelectors.itemDataInitQ, questionEl: PAASelectors.itemQuestionEl },\n )\n\n let round = 0\n while (seenQs.size < options.maxQuestions) {\n this.throwIfAborted(signal)\n await this.throwIfCaptcha(page, 'Google PAA expansion')\n const beforeQs = await readAllQs()\n if (beforeQs.length >= options.maxQuestions) break\n\n const unexpandedSel = `${PAASelectors.item}:not(.${PAASelectors.expandedClass}) ${PAASelectors.clickTarget}`\n const unexpandedCount = await page.locator(unexpandedSel).count()\n if (unexpandedCount === 0) break\n\n this.reporter.onDepth(++round)\n\n for (let ci = 0; ci < unexpandedCount; ci++) {\n this.throwIfAborted(signal)\n try {\n const btn = page.locator(unexpandedSel).first()\n await btn.scrollIntoViewIfNeeded()\n await btn.hover({ force: true })\n await page.waitForTimeout(100)\n await btn.click({ force: true })\n await page.waitForTimeout(500)\n } catch { }\n }\n await page.waitForFunction(\n ({ sel, min }: { sel: string; min: number }) => document.querySelectorAll(sel).length > min,\n { sel: PAASelectors.item, min: beforeQs.length },\n { timeout: 5000 },\n ).catch(() => {})\n await this.throwIfCaptcha(page, 'Google PAA expansion')\n\n const afterQs = await readAllQs()\n if (afterQs.length === beforeQs.length) break\n\n for (const q of afterQs) {\n if (!seenQs.has(q)) { seenQs.add(q); orderedQs.push(q) }\n }\n }\n\n const itemMap = new Map((await this.extractVisibleItems(page)).map(i => [i.question, i]))\n\n for (const q of orderedQs) {\n if (results.length >= options.maxQuestions) break\n const key = this.normalizeQuestion(q)\n if (seenKeys.has(key)) continue\n seenKeys.add(key)\n const item = itemMap.get(q)\n if (item) {\n results.push(this.toFlatRow(item, 1, null, options.query))\n this.reporter.onQuestion({ question: item.question, answer: item.answer ?? null, sourceTitle: item.sourceTitle ?? null, sourceSite: item.sourceSite ?? null, sourceCite: item.sourceCite ?? null, depth: 1, parentQuestion: null, children: [] })\n } else {\n results.push(this.toFlatRow({ question: q, answer: undefined, sourceTitle: undefined, sourceSite: undefined, sourceCite: undefined }, 1, null, options.query))\n }\n }\n\n return results\n }\n\n private async extractVideos(page: Page): Promise<VideoResult[]> {\n const vsels = VideoSelectors\n return page.evaluate((sels) => {\n const results: Array<{ type: 'video' | 'short_video'; title: string; channel: string; platform: string; duration: string; url: string }> = []\n const containers = Array.from(document.querySelectorAll(sels.container))\n for (const container of containers) {\n const headingEl = container.querySelector(sels.sectionHeading)\n const headingText = headingEl?.textContent?.trim() ?? ''\n const type: 'video' | 'short_video' = headingText.toLowerCase().includes('short') ? 'short_video' : 'video'\n const items = Array.from(container.querySelectorAll(sels.item))\n for (const a of items) {\n const href = (a as HTMLAnchorElement).href\n if (!href || (!href.includes('youtube') && !href.includes('youtu.be'))) continue\n const raw = a.textContent?.trim() ?? ''\n const ytIdx = raw.indexOf('YouTube')\n if (ytIdx === -1) continue\n const title = raw.slice(0, ytIdx).trim()\n const remainder = raw.slice(ytIdx + 7).replace(/^[·\\s·]+/, '')\n const channelMatch = remainder.match(/^([^·\\n]+)/)\n const channel = channelMatch ? channelMatch[1].trim() : ''\n if (title) results.push({ type, title, channel, platform: 'YouTube', duration: '', url: href })\n }\n }\n return results\n }, vsels)\n }\n\n private async extractForums(page: Page): Promise<ForumResult[]> {\n const fsels = ForumSelectors\n return page.evaluate((sels) => {\n const results: Array<{ title: string; source: string; url: string }> = []\n const sections = Array.from(document.querySelectorAll(sels.section))\n const forumSection = sections.find((s) => s.textContent?.includes('Discussions'))\n if (!forumSection) return results\n const items = Array.from(forumSection.querySelectorAll(sels.item))\n for (const a of items) {\n const href = (a as HTMLAnchorElement).href\n if (!href) continue\n const titleEl = a.querySelector(sels.title)\n const sourceEl = a.querySelector(sels.source)\n const title = titleEl?.textContent?.trim() ?? ''\n const source = sourceEl?.textContent?.trim() ?? ''\n if (title) results.push({ title, source, url: href })\n }\n return results\n }, fsels)\n }\n\n private async extractShortVideos(page: Page, shortUrl: string): Promise<VideoResult[]> {\n try {\n await page.goto(shortUrl, { waitUntil: 'domcontentloaded' })\n await page.waitForTimeout(1500)\n } catch {\n return []\n }\n await this.throwIfCaptcha(page, 'Google short video search')\n\n const svSels = {\n item: ShortVideoSelectors.item,\n platforms: [...ShortVideoSelectors.platforms] as string[],\n }\n\n const raw = await page.evaluate((sels) => {\n const seen = new Set<string>()\n const results: Array<{ title: string; channel: string; platform: string; duration: string; url: string }> = []\n const items = Array.from(document.querySelectorAll(sels.item))\n\n const videoHosts = ['youtube.com', 'youtu.be', 'tiktok.com', 'instagram.com', 'facebook.com', 'fb.watch']\n\n const byHref = new Map<string, string[]>()\n for (const a of items) {\n const href = (a as HTMLAnchorElement).href\n if (!href) continue\n if (!videoHosts.some((h) => href.includes(h))) continue\n const text = a.textContent?.trim() ?? ''\n if (!byHref.has(href)) byHref.set(href, [])\n byHref.get(href)!.push(text)\n }\n\n for (const [href, texts] of byHref.entries()) {\n if (seen.has(href)) continue\n seen.add(href)\n\n const duration = texts.find((t) => /^\\d+:\\d+$/.test(t)) ?? ''\n const titleText = texts.find((t) => !/^\\d+:\\d+$/.test(t) && t.length > 5) ?? ''\n if (!titleText) continue\n\n let title = titleText\n let platform = ''\n let channel = ''\n\n for (const p of sels.platforms) {\n let lastIdx = -1\n let search = 0\n while (true) {\n const found = titleText.indexOf(p, search)\n if (found === -1) break\n lastIdx = found\n search = found + 1\n }\n if (lastIdx === -1) continue\n const after = titleText.slice(lastIdx + p.length)\n const isSourceTag = /^[\\s·]/.test(after) || after.trim() === ''\n if (!isSourceTag) continue\n title = titleText.slice(0, lastIdx).trim()\n platform = p\n const stripped = after.replace(/^[\\s·]+/, '')\n const dotIdx = stripped.indexOf('·')\n channel = (dotIdx === -1 ? stripped : stripped.slice(0, dotIdx)).trim()\n break\n }\n\n if (title) results.push({ title, channel, platform, duration, url: href })\n }\n\n return results\n }, svSels)\n\n return raw.map((r) => ({ type: 'short_video' as const, ...r }))\n }\n\n private async extractWhatPeopleSaying(page: Page): Promise<WhatPeopleSayingCard[]> {\n const sels = WhatPeopleSayingSelectors\n return page.evaluate((s) => {\n const section = Array.from(document.querySelectorAll(s.sectionTag))\n .find((el) => el.textContent?.includes(s.sectionHeadingText))\n ?? document.querySelector('.yG4QQe.TBC9ub.NbhJ1c')\n\n if (!section) return []\n\n return Array.from(section.querySelectorAll(s.card)).map((card) => {\n const link = card.querySelector(s.cardLink) as HTMLAnchorElement | null\n const url = link?.href ?? ''\n\n const titleH1 = card.querySelector(s.titleH1)?.textContent?.trim()\n const titleDiv = card.querySelector(s.titleDiv)?.textContent?.trim()\n const title = titleH1 ?? titleDiv ?? ''\n\n const sourceText = card.querySelector(s.source)?.textContent?.trim() ?? ''\n const platformEl = card.querySelector(s.platformBadge)\n const platformText = platformEl?.textContent?.trim() ?? ''\n\n const ytChannel = card.querySelector(s.ytChannel)?.textContent?.trim() ?? ''\n const ytDate = card.querySelector(s.ytDate)?.textContent?.trim() ?? ''\n const authorNote = card.querySelector(s.authorNote)?.textContent?.trim() ?? null\n\n const commentLabelEl = card.querySelector(s.popularCommentLabel)\n let popularComment: string | null = null\n if (commentLabelEl) {\n let next = commentLabelEl.nextSibling\n while (next) {\n const t = next.textContent?.trim()\n if (t) { popularComment = t; break }\n next = next.nextSibling\n }\n }\n\n const allSpans = Array.from(card.querySelectorAll('span'))\n const duration = allSpans.find((s) => /^\\d+:\\d+$/.test(s.textContent?.trim() ?? ''))?.textContent?.trim() ?? null\n const engagementParts = allSpans\n .map((s) => s.textContent?.trim() ?? '')\n .filter((t) =>\n /\\d/.test(t) && (\n t.includes('comment') || t.includes('reaction') ||\n t.includes('view') || t.includes('like') || t.includes('share')\n )\n )\n const engagement = engagementParts[0] ?? ''\n\n const dateCandidates = allSpans\n .map((s) => s.textContent?.trim() ?? '')\n .filter((t) => /\\d+ (day|week|month|year|hour)s? ago|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/.test(t))\n const date = ytDate || (dateCandidates[0] ?? '')\n\n const platform = platformText || (ytChannel ? 'YouTube' : '')\n const source = ytChannel || sourceText\n\n let type: 'reddit' | 'facebook' | 'youtube' | 'instagram' | 'tiktok' | 'news' | 'unknown' = 'unknown'\n const pl = platform.toLowerCase()\n const src = source.toLowerCase()\n const srcRaw = sourceText.toLowerCase()\n if (pl.includes('reddit') || src.startsWith('r/')) type = 'reddit'\n else if (pl.includes('facebook') || srcRaw.includes('facebook')) type = 'facebook'\n else if (pl.includes('instagram') || srcRaw.includes('instagram')) type = 'instagram'\n else if (pl.includes('tiktok') || srcRaw.includes('tiktok')) type = 'tiktok'\n else if (pl.includes('youtube') || !!ytChannel) type = 'youtube'\n else type = 'news'\n\n return { type, title, url, source, platform, popularComment, engagement, date, duration, authorNote }\n })\n }, sels)\n }\n\n private async extractOrganicResults(page: Page): Promise<OrganicResult[]> {\n const sels = OrganicSelectors\n return page.evaluate((s) => {\n const out: Array<{ position: number; title: string; url: string; domain: string; cite: string | null; snippet: string | null; isRedditStyle: boolean; inlineRating: { value: string; count: string } | null }> = []\n let pos = 0\n document.querySelectorAll(s.result).forEach(card => {\n const titleEl = card.querySelector(s.title)\n if (!titleEl) return\n const title = titleEl.textContent?.trim() ?? ''\n const linkEl = titleEl.closest('a') as HTMLAnchorElement | null\n const url = linkEl?.href ?? ''\n if (!title || !url) return\n pos++\n const cite = card.querySelector(s.cite)?.textContent?.trim() ?? null\n const snippet = card.querySelector(s.snippet)?.textContent?.trim() ?? null\n const isRedditStyle = !!card.querySelector(s.redditCite)\n const ratingEl = card.querySelector(s.ratingWrap)\n const inlineRating = ratingEl\n ? { value: ratingEl.querySelector(s.ratingValue)?.textContent?.trim() ?? '', count: ratingEl.querySelector(s.reviewCount)?.textContent?.trim() ?? '' }\n : null\n let domain = ''\n try { domain = new URL(url).hostname.replace(/^www\\./, '') } catch { domain = card.querySelector(s.siteName)?.textContent?.trim() ?? '' }\n out.push({ position: pos, title, url, domain, cite, snippet, isRedditStyle, inlineRating })\n })\n return out\n }, sels)\n }\n\n private async extractLocalPack(page: Page): Promise<LocalPackBusiness[]> {\n const sels = LocalPackSelectors\n return page.evaluate((s) => {\n const out: Array<{ position: number; name: string; cid: string | null; rating: string | null; reviewCount: string | null; metadata: string[]; websiteUrl: string | null; directionsUrl: string | null }> = []\n let container: Element | null = null\n document.querySelectorAll('[role=\"heading\"]').forEach(h => {\n if (!container && h.textContent?.includes(s.headingText)) container = h.closest('[data-hveid]')\n })\n if (!container) return out\n ;(container as Element).querySelectorAll(s.card).forEach((card, i) => {\n const name = card.querySelector(s.name)?.textContent?.trim() ?? ''\n if (!name) return\n const rating = card.querySelector(s.ratingValue)?.textContent?.trim() ?? null\n const reviewRaw = card.querySelector(s.reviewCount)?.textContent?.trim() ?? null\n const reviewCount = reviewRaw ? reviewRaw.replace(/[()]/g, '').trim() : null\n let cid = (card.querySelector('a[data-cid]') as HTMLAnchorElement | null)?.getAttribute('data-cid') ?? null\n if (!cid) {\n for (const link of Array.from(card.querySelectorAll('a[href]')) as HTMLAnchorElement[]) {\n const m1 = link.href.match(/[?&]cid=(\\d+)/)\n if (m1) { cid = m1[1]; break }\n const m2 = link.href.match(/!1s0x[0-9a-f]+:0x([0-9a-f]+)/i)\n if (m2) { try { cid = BigInt('0x' + m2[1]).toString() } catch { } if (cid) break }\n }\n }\n const metadata: string[] = []\n card.querySelectorAll('div, span').forEach(el => {\n const text = Array.from(el.childNodes)\n .filter(n => n.nodeType === 3)\n .map(n => n.textContent?.trim() ?? '')\n .filter(t => t.length > 1 && t.length < 120)\n .join(' ')\n if (text && !metadata.includes(text)) metadata.push(text)\n })\n const links = Array.from(card.querySelectorAll('a[href]')) as HTMLAnchorElement[]\n const directionsUrl = links.find(a => a.href.includes('google.com/maps'))?.href ?? null\n const websiteUrl = links.find(a => !a.href.includes('google.com') && a.href.startsWith('http'))?.href ?? null\n out.push({ position: i + 1, name, cid, rating, reviewCount, metadata, websiteUrl, directionsUrl })\n })\n return out\n }, sels)\n }\n\n private async extractEntityIds(page: Page): Promise<EntityIds> {\n return page.evaluate(() => {\n const kgIds = new Set<string>()\n const cids = new Set<string>()\n const gcids = new Set<string>()\n const recordMap = new Map<string, { name: string; kgId: string | null; cid: string | null; gcid: string | null }>()\n\n function nameFromWrapper(el: Element): string {\n const sel = ['.OSrXXb', '.dbg0pd', '.tzt0oe', '[role=\"heading\"]', 'h3']\n for (const s of sel) {\n const found = el.querySelector(s)\n if (found?.textContent?.trim()) return found.textContent.trim()\n }\n return ''\n }\n\n document.querySelectorAll('[id^=\"pv-/g/\"]').forEach(wrapper => {\n const raw = wrapper.getAttribute('id')\n if (!raw) return\n const kgId = raw.replace('pv-', '')\n kgIds.add(kgId)\n const name = nameFromWrapper(wrapper)\n const cidEl = wrapper.querySelector('a[data-cid]')\n const cid = cidEl?.getAttribute('data-cid') ?? null\n if (cid) cids.add(cid)\n if (name) recordMap.set(kgId, { name, kgId, cid, gcid: null })\n })\n\n document.querySelectorAll('[data-mid]').forEach(el => {\n const mid = el.getAttribute('data-mid')\n if (!mid?.startsWith('/g/')) return\n kgIds.add(mid)\n if (!recordMap.has(mid)) {\n const name = nameFromWrapper(el)\n if (name) recordMap.set(mid, { name, kgId: mid, cid: null, gcid: null })\n }\n })\n\n document.querySelectorAll('.w7Dbne').forEach(card => {\n const cidEl = card.querySelector('a[data-cid]')\n const cid = cidEl?.getAttribute('data-cid') ?? null\n if (!cid) return\n cids.add(cid)\n const name = card.querySelector('.OSrXXb')?.textContent?.trim() ?? ''\n if (!name) return\n const kgIdEl = card.querySelector('[id^=\"pv-/g/\"]')\n const kgId = kgIdEl ? kgIdEl.getAttribute('id')!.replace('pv-', '') : null\n const key = kgId ?? `cid:${cid}`\n if (recordMap.has(key)) {\n const existing = recordMap.get(key)!\n if (!existing.cid) recordMap.set(key, { ...existing, cid })\n } else {\n recordMap.set(key, { name, kgId, cid, gcid: null })\n }\n })\n\n document.querySelectorAll('a[data-cid]').forEach(el => {\n const cid = el.getAttribute('data-cid')\n if (!cid) return\n cids.add(cid)\n const alreadyNamed = [...recordMap.values()].some(r => r.cid === cid)\n if (!alreadyNamed) {\n let node: Element | null = el.parentElement\n let name = ''\n for (let i = 0; i < 8 && node; i++) {\n const h = node.querySelector('.OSrXXb, .dbg0pd, [role=\"heading\"], h3')\n if (h?.textContent?.trim()) { name = h.textContent.trim(); break }\n node = node.parentElement\n }\n if (name) recordMap.set(`cid:${cid}`, { name, kgId: null, cid, gcid: null })\n }\n })\n\n const scriptContent = Array.from(document.querySelectorAll('script:not([src])'))\n .map(s => s.textContent ?? '')\n .filter(t => t.length > 10_000)\n .join('\\n')\n\n for (const m of scriptContent.matchAll(/\\/g\\/[a-zA-Z0-9_-]{5,20}/g)) kgIds.add(m[0])\n for (const m of scriptContent.matchAll(/gcid:[a-zA-Z0-9_]+/g)) gcids.add(m[0])\n for (const m of scriptContent.matchAll(/0x[0-9a-f]+:0x([0-9a-f]+)/gi)) {\n try { cids.add(BigInt('0x' + m[1]).toString()) } catch { }\n }\n\n return { entities: [...recordMap.values()], kgIds: [...kgIds], cids: [...cids], gcids: [...gcids] }\n })\n }\n\n private mergeLocalPackIntoEntities(entityIds: EntityIds, localPack: LocalPackBusiness[]): EntityIds {\n const cidSet = new Set<string>(entityIds.cids)\n const records = entityIds.entities.map(r => ({ ...r }))\n\n for (const biz of localPack) {\n if (!biz.cid) continue\n cidSet.add(biz.cid)\n const nameNorm = biz.name.toLowerCase().trim()\n const byName = records.find(r => r.name.toLowerCase().trim() === nameNorm)\n if (byName) {\n if (!byName.cid) byName.cid = biz.cid\n } else if (!records.find(r => r.cid === biz.cid)) {\n records.push({ name: biz.name, kgId: null, cid: biz.cid, gcid: null })\n }\n }\n\n return { ...entityIds, entities: records, cids: [...cidSet] }\n }\n\n private async extractAISurfaces(page: Page): Promise<{\n surface: GoogleSurface\n aiOverview: AIOverviewResult\n aiMode: AIModeResult\n }> {\n return page.evaluate(extractAISurfacesFromDocument, {\n aio: AIOverviewSelectors,\n aim: AIModeSelectors,\n expandWaitMs: 1500,\n })\n }\n\n private buildTree(flat: FlatRow[], _seed: string): PAANode[] {\n const roots: PAANode[] = []\n const nodeMap = new Map<string, PAANode>()\n\n for (const row of flat) {\n const node: PAANode = {\n question: row.question,\n answer: row.answer || null,\n sourceTitle: row.source_title || null,\n sourceSite: row.source_site || null,\n sourceCite: row.source_cite || null,\n depth: row.depth,\n parentQuestion: row.parent_question || null,\n children: [],\n }\n nodeMap.set(row.question, node)\n }\n\n for (const node of nodeMap.values()) {\n if (node.parentQuestion && nodeMap.has(node.parentQuestion)) {\n nodeMap.get(node.parentQuestion)!.children.push(node)\n } else {\n roots.push(node)\n }\n }\n\n return roots\n }\n\n private getBrowserDebugSnapshot(): BrowserDebugSnapshot {\n return this.driver.getDebugSnapshot()\n }\n\n private buildHarvestDebugSnapshot(\n options: HarvestOptions,\n canonicalLocation: string | null,\n uule: string | null,\n locationEvidence?: SerpLocationEvidence,\n ): HarvestDebugSnapshot | undefined {\n if (!options.debug) return undefined\n return {\n enabled: true,\n request: {\n query: options.query,\n locationInput: options.location ?? null,\n canonicalLocation,\n uule,\n gl: options.gl,\n hl: options.hl,\n device: options.device,\n proxyMode: options.proxyMode,\n proxyZip: options.proxyZip ?? null,\n serpOnly: options.serpOnly,\n pages: options.pages ?? 1,\n },\n browser: this.getBrowserDebugSnapshot(),\n ...(locationEvidence ? { locationEvidence } : {}),\n }\n }\n\n async extract(options: HarvestOptions, signal?: AbortSignal): Promise<HarvestResult> {\n const startMs = Date.now()\n const isMobile = options.device === 'mobile'\n const config: DriverConfig = {\n headless: options.headless,\n profileDir: options.profileDir,\n proxy: options.proxy,\n kernelApiKey: options.kernelApiKey,\n kernelProxyId: options.kernelProxyId,\n kernelProxyResolution: options.kernelProxyResolution as DriverConfig['kernelProxyResolution'],\n proxyMode: options.proxyMode,\n viewport: isMobile ? { width: 390, height: 844 } : { width: 1280, height: 800 },\n locale: `${options.hl}-${options.gl.toUpperCase()}`,\n userAgent: isMobile ? MOBILE_USER_AGENT : DESKTOP_USER_AGENT,\n deviceScaleFactor: isMobile ? 3 : 1,\n isMobile,\n hasTouch: isMobile,\n debug: options.debug,\n }\n\n let errorCount = 0\n const diagnosticWarnings: HarvestDiagnosticWarning[] = []\n\n try {\n this.throwIfAborted(signal)\n await this.driver.launch(config)\n this.throwIfAborted(signal)\n const canonicalLocation = options.location ? normalizeLocation(options.location) : null\n const uule = canonicalLocation ? encodeUule(canonicalLocation) : null\n const { hasPaa } = await this.driver.navigateToSERP(\n options.query,\n uule,\n options.gl,\n options.hl,\n {\n ...(options.serpOnly ? { num: 100 } : {}),\n debug: options.debug,\n },\n )\n this.throwIfAborted(signal)\n\n const page = this.driver.getPage() as Page\n await this.throwIfCaptcha(page, 'Google SERP')\n\n if (options.serpOnly) {\n const [organicResults, localPack, rawEntityIds] = await Promise.all([\n this.extractOrganicResults(page),\n this.extractLocalPack(page),\n this.extractEntityIds(page),\n ])\n const entityIds = this.mergeLocalPackIntoEntities(rawEntityIds, localPack)\n const aiSurfaces = await this.extractAISurfaces(page)\n let locationEvidence = options.debug\n ? inferSerpLocationEvidence(canonicalLocation, organicResults, localPack)\n : undefined\n let allOrganic = organicResults\n if ((options.pages ?? 1) >= 2) {\n const p2params = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, pws: '0', start: '10' })\n if (uule) p2params.set('uule', uule)\n await this.driver.navigateTo('https://www.google.com/search?' + p2params.toString())\n await this.throwIfCaptcha(page, 'Google SERP page 2')\n const p2organic = await this.extractOrganicResults(page)\n allOrganic = [...organicResults, ...p2organic.map(r => ({ ...r, position: r.position + 10 }))]\n if (options.debug) {\n locationEvidence = inferSerpLocationEvidence(canonicalLocation, allOrganic, localPack)\n }\n }\n const stats: HarvestStats = {\n seed: options.query, totalQuestions: 0, maxDepthReached: 0,\n durationMs: Date.now() - startMs, errorCount,\n }\n this.reporter.onComplete(stats)\n return {\n seed: options.query, location: options.location ?? null,\n extractedAt: new Date().toISOString(),\n diagnostics: {\n completionStatus: 'serp_only',\n problem: null,\n ...(options.debug ? { debug: this.buildHarvestDebugSnapshot(options, canonicalLocation, uule, locationEvidence) } : {}),\n },\n totalQuestions: 0,\n surface: aiSurfaces.surface,\n aiOverview: aiSurfaces.aiOverview,\n aiMode: aiSurfaces.aiMode,\n whatPeopleSaying: [], tree: [], flat: [], videos: [], forums: [],\n organicResults: allOrganic, localPack, entityIds, stats,\n }\n }\n\n const [videos, forums, whatPeopleSaying, rawEntityIds, organicResults, localPack] = await Promise.all([\n this.extractVideos(page),\n this.extractForums(page),\n this.extractWhatPeopleSaying(page),\n this.extractEntityIds(page),\n this.extractOrganicResults(page),\n this.extractLocalPack(page),\n ])\n const entityIds = this.mergeLocalPackIntoEntities(rawEntityIds, localPack)\n const initialLocationEvidence = options.debug\n ? inferSerpLocationEvidence(canonicalLocation, organicResults, localPack)\n : undefined\n this.reporter.onVideos(videos)\n this.reporter.onForums(forums)\n\n if (!hasPaa) {\n let noPaaOrganic = organicResults\n let locationEvidence = initialLocationEvidence\n if ((options.pages ?? 1) >= 2) {\n const p2params = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, pws: '0', start: '10' })\n if (uule) p2params.set('uule', uule)\n await this.driver.navigateTo('https://www.google.com/search?' + p2params.toString())\n await this.throwIfCaptcha(page, 'Google SERP page 2')\n const p2organic = await this.extractOrganicResults(page)\n noPaaOrganic = [...organicResults, ...p2organic.map(r => ({ ...r, position: r.position + 10 }))]\n if (options.debug) {\n locationEvidence = inferSerpLocationEvidence(canonicalLocation, noPaaOrganic, localPack)\n }\n }\n const aiSurfaces = await this.extractAISurfaces(page)\n const stats: HarvestStats = {\n seed: options.query, totalQuestions: 0, maxDepthReached: 0,\n durationMs: Date.now() - startMs, errorCount,\n }\n this.reporter.onComplete(stats)\n return {\n seed: options.query, location: options.location ?? null,\n extractedAt: new Date().toISOString(),\n diagnostics: {\n completionStatus: 'no_paa',\n problem: null,\n ...(options.debug ? { debug: this.buildHarvestDebugSnapshot(options, canonicalLocation, uule, locationEvidence) } : {}),\n },\n totalQuestions: 0,\n surface: aiSurfaces.surface,\n aiOverview: aiSurfaces.aiOverview,\n aiMode: aiSurfaces.aiMode,\n whatPeopleSaying, tree: [], flat: [], videos, forums,\n organicResults: noPaaOrganic, localPack, entityIds, stats,\n }\n }\n\n const flat = await this.runBFS(page, options, signal)\n this.throwIfAborted(signal)\n const aiSurfaces = await this.extractAISurfaces(page)\n\n const shortVidsParams = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, pws: '0', udm: ShortVideoSelectors.udm })\n if (uule) shortVidsParams.set('uule', uule)\n let shortVideos: VideoResult[] = []\n try {\n shortVideos = await this.extractShortVideos(page, 'https://www.google.com/search?' + shortVidsParams.toString())\n } catch (err) {\n if (!(err instanceof CaptchaError)) throw err\n errorCount++\n diagnosticWarnings.push({\n code: 'short_videos_captcha_skipped',\n surface: 'short_videos',\n message: err.message,\n retryable: true,\n })\n }\n this.reporter.onVideos(shortVideos)\n\n let allOrganic = organicResults\n let locationEvidence = initialLocationEvidence\n if ((options.pages ?? 1) >= 2) {\n const p2params = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, pws: '0', start: '10' })\n if (uule) p2params.set('uule', uule)\n await this.driver.navigateTo('https://www.google.com/search?' + p2params.toString())\n await this.throwIfCaptcha(page, 'Google SERP page 2')\n const p2organic = await this.extractOrganicResults(page)\n allOrganic = [...organicResults, ...p2organic.map(r => ({ ...r, position: r.position + 10 }))]\n if (options.debug) {\n locationEvidence = inferSerpLocationEvidence(canonicalLocation, allOrganic, localPack)\n }\n }\n\n const allVideos = [...videos, ...shortVideos]\n const tree = this.buildTree(flat, options.query)\n\n const stats: HarvestStats = {\n seed: options.query,\n totalQuestions: flat.length,\n maxDepthReached: flat.reduce((m, r) => Math.max(m, r.depth), 0),\n durationMs: Date.now() - startMs,\n errorCount,\n }\n\n this.reporter.onComplete(stats)\n\n return {\n seed: options.query,\n location: options.location ?? null,\n extractedAt: new Date().toISOString(),\n diagnostics: {\n completionStatus: 'paa_found',\n problem: null,\n ...(diagnosticWarnings.length > 0 ? { warnings: diagnosticWarnings } : {}),\n ...(options.debug ? { debug: this.buildHarvestDebugSnapshot(options, canonicalLocation, uule, locationEvidence) } : {}),\n },\n totalQuestions: flat.length,\n surface: aiSurfaces.surface,\n aiOverview: aiSurfaces.aiOverview,\n aiMode: aiSurfaces.aiMode,\n whatPeopleSaying,\n tree,\n flat,\n videos: allVideos,\n forums,\n organicResults: allOrganic,\n localPack,\n entityIds,\n stats,\n }\n } catch (err) {\n errorCount++\n this.reporter.onError(err instanceof Error ? err : new Error(String(err)))\n throw err\n }\n }\n}\n","import { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport Papa from 'papaparse'\nimport type { HarvestResult, FlatRow, VideoResult, ForumResult, AICitation, WhatPeopleSayingCard } from '../types.js'\nimport type { IOutputSerializer } from './IOutputSerializer.js'\n\nexport class OutputSerializer implements IOutputSerializer {\n async writeJSON(result: HarvestResult, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = result.seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const filename = `${slug}-${Date.now()}.json`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, JSON.stringify(result, null, 2), 'utf8')\n return fullPath\n }\n\n async writeCSV(rows: FlatRow[], outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const seedRaw = rows[0]?.seed_query ?? 'paa'\n const slug = seedRaw.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const csv = Papa.unparse(rows, { header: true })\n const filename = `${slug}-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeVideoCSV(videos: VideoResult[], seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const csv = Papa.unparse(videos, { header: true })\n const filename = `${slug}-videos-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeForumCSV(forums: ForumResult[], seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const csv = Papa.unparse(forums, { header: true })\n const filename = `${slug}-forums-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeAIOverviewCSV(citations: AICitation[], text: string | null, seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const rows = citations.map((c, i) => ({\n seed_query: seed,\n response_text: i === 0 ? (text ?? '') : '',\n citation_text: c.text,\n citation_href: c.href,\n }))\n const csv = Papa.unparse(rows, { header: true })\n const filename = `${slug}-ai-overview-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeAIModeCSV(citations: AICitation[], text: string | null, seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const rows = citations.map((c, i) => ({\n seed_query: seed,\n response_text: i === 0 ? (text ?? '') : '',\n citation_text: c.text,\n citation_href: c.href,\n }))\n const csv = Papa.unparse(rows, { header: true })\n const filename = `${slug}-ai-mode-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeWhatPeopleSayingCSV(cards: WhatPeopleSayingCard[], seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const rows = cards.map((c) => ({ seed_query: seed, ...c }))\n const csv = Papa.unparse(rows, { header: true })\n const filename = `${slug}-what-people-saying-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n}\n","import type { PAANode, HarvestStats, VideoResult, ForumResult } from '../types.js'\nimport type { IProgressReporter } from './IProgressReporter.js'\n\nexport class ProgressReporter implements IProgressReporter {\n onQuestion(node: PAANode): void {\n process.stdout.write(JSON.stringify({ event: 'question', depth: node.depth, question: node.question }) + '\\n')\n }\n\n onDepth(depth: number): void {\n process.stdout.write(JSON.stringify({ event: 'depth', depth }) + '\\n')\n }\n\n onVideos(videos: VideoResult[]): void {\n for (const v of videos) {\n process.stdout.write(JSON.stringify({ event: 'video', type: v.type, platform: v.platform, duration: v.duration, title: v.title, channel: v.channel, url: v.url }) + '\\n')\n }\n }\n\n onForums(forums: ForumResult[]): void {\n for (const f of forums) {\n process.stdout.write(JSON.stringify({ event: 'forum', title: f.title, source: f.source, url: f.url }) + '\\n')\n }\n }\n\n onComplete(stats: HarvestStats): void {\n process.stdout.write(JSON.stringify({ event: 'complete', ...stats }) + '\\n')\n }\n\n onError(err: Error): void {\n process.stderr.write(JSON.stringify({ event: 'error', type: err.constructor.name, message: err.message }) + '\\n')\n }\n}\n","import Kernel from '@onkernel/sdk'\nimport { normalizeLocation } from './uule.js'\nimport type { CanonicalLocationName, KernelLocationProxyTarget, KernelProxyResolutionDebug, ProxyMode } from './types.js'\n\ntype KernelProxyConfig = {\n country?: string\n state?: string\n city?: string\n zip?: string\n}\n\ntype KernelProxyListItem = {\n id?: string\n name?: string\n type?: string\n status?: string\n config?: KernelProxyConfig\n}\n\ntype KernelProxyCreateResponse = {\n id?: string\n name?: string\n type?: string\n status?: string\n config?: KernelProxyConfig\n}\n\nexport interface ResolveKernelProxyOptions {\n kernelApiKey?: string\n proxyMode: ProxyMode\n configuredKernelProxyId?: string\n location?: string\n proxyZip?: string\n gl: string\n attemptIndex?: number\n}\n\nexport interface ResolveKernelProxyResult {\n kernelProxyId?: string\n resolution: KernelProxyResolutionDebug\n}\n\nconst US_STATE_CODES: Record<string, string> = {\n alabama: 'AL',\n alaska: 'AK',\n arizona: 'AZ',\n arkansas: 'AR',\n california: 'CA',\n colorado: 'CO',\n connecticut: 'CT',\n delaware: 'DE',\n florida: 'FL',\n georgia: 'GA',\n hawaii: 'HI',\n idaho: 'ID',\n illinois: 'IL',\n indiana: 'IN',\n iowa: 'IA',\n kansas: 'KS',\n kentucky: 'KY',\n louisiana: 'LA',\n maine: 'ME',\n maryland: 'MD',\n massachusetts: 'MA',\n michigan: 'MI',\n minnesota: 'MN',\n mississippi: 'MS',\n missouri: 'MO',\n montana: 'MT',\n nebraska: 'NE',\n nevada: 'NV',\n 'new hampshire': 'NH',\n 'new jersey': 'NJ',\n 'new mexico': 'NM',\n 'new york': 'NY',\n 'north carolina': 'NC',\n 'north dakota': 'ND',\n ohio: 'OH',\n oklahoma: 'OK',\n oregon: 'OR',\n pennsylvania: 'PA',\n 'rhode island': 'RI',\n 'south carolina': 'SC',\n 'south dakota': 'SD',\n tennessee: 'TN',\n texas: 'TX',\n utah: 'UT',\n vermont: 'VT',\n virginia: 'VA',\n washington: 'WA',\n 'west virginia': 'WV',\n wisconsin: 'WI',\n wyoming: 'WY',\n}\n\nconst US_CITY_CENTER_ZIPS: Record<string, string> = {\n 'atlanta|GA': '30303',\n 'austin|TX': '78701',\n 'baltimore|MD': '21201',\n 'boston|MA': '02108',\n 'boulder|CO': '80302',\n 'charlotte|NC': '28202',\n 'chicago|IL': '60601',\n 'colorado_springs|CO': '80903',\n 'columbus|OH': '43215',\n 'dallas|TX': '75201',\n 'denver|CO': '80202',\n 'detroit|MI': '48226',\n 'fort_collins|CO': '80524',\n 'fort_worth|TX': '76102',\n 'houston|TX': '77002',\n 'indianapolis|IN': '46204',\n 'jacksonville|FL': '32202',\n 'las_vegas|NV': '89101',\n 'los_angeles|CA': '90012',\n 'louisville|KY': '40202',\n 'loveland|CO': '80537',\n 'memphis|TN': '38103',\n 'miami|FL': '33131',\n 'minneapolis|MN': '55401',\n 'nashville|TN': '37203',\n 'new_york|NY': '10001',\n 'orlando|FL': '32801',\n 'philadelphia|PA': '19103',\n 'phoenix|AZ': '85004',\n 'portland|OR': '97205',\n 'raleigh|NC': '27601',\n 'richmond|VA': '23219',\n 'sacramento|CA': '95814',\n 'salt_lake_city|UT': '84101',\n 'san_antonio|TX': '78205',\n 'san_diego|CA': '92101',\n 'san_francisco|CA': '94103',\n 'san_jose|CA': '95113',\n 'seattle|WA': '98101',\n}\n\nfunction proxyIdSuffix(proxyId: string | null | undefined): string | null {\n return proxyId ? proxyId.slice(-6) : null\n}\n\nfunction resolution(\n source: KernelProxyResolutionDebug['source'],\n proxyMode: ProxyMode,\n proxyId: string | undefined,\n target: KernelLocationProxyTarget | null,\n error: string | null,\n): ResolveKernelProxyResult {\n return {\n kernelProxyId: proxyId,\n resolution: {\n source,\n proxyMode,\n proxyIdPresent: Boolean(proxyId),\n proxyIdSuffix: proxyIdSuffix(proxyId),\n target,\n error,\n },\n }\n}\n\nfunction normalizeStateName(value: string): string {\n return value.trim().toLowerCase().replace(/\\s+/g, ' ')\n}\n\nfunction normalizeCountryName(value: string): string {\n return value.trim().toLowerCase().replace(/\\./g, '').replace(/\\s+/g, ' ')\n}\n\nfunction isUnitedStates(country: string | undefined): boolean {\n if (!country) return true\n const normalized = normalizeCountryName(country)\n return normalized === 'united states' || normalized === 'united states of america' || normalized === 'usa' || normalized === 'us'\n}\n\nfunction stateCodeFor(region: string): string | null {\n const trimmed = region.trim()\n if (/^[A-Za-z]{2}$/.test(trimmed)) return trimmed.toUpperCase()\n return US_STATE_CODES[normalizeStateName(trimmed)] ?? null\n}\n\nexport function kernelCityIdentifierCandidates(city: string): string[] {\n const ascii = city\n .normalize('NFKD')\n .replace(/[^\\x00-\\x7F]/g, '')\n .toLowerCase()\n const words = ascii.split(/[^a-z0-9]+/).filter(Boolean)\n const underscored = words.join('_')\n const compact = words.join('')\n return Array.from(new Set([underscored, compact].filter(Boolean)))\n}\n\nfunction proxyName(country: string, state: string, city?: string): string {\n return city\n ? `mcp-serp-residential-${country.toLowerCase()}-${state.toLowerCase()}-${city}`\n : `mcp-serp-residential-${country.toLowerCase()}-${state.toLowerCase()}`\n}\n\nfunction zipProxyName(zip: string): string {\n return `mcp-serp-residential-us-zip-${zip}`\n}\n\nexport function parseKernelLocationProxyTarget(location: string | undefined, gl: string): KernelLocationProxyTarget | null {\n if (!location || gl.toLowerCase() !== 'us') return null\n const canonicalLocation = normalizeLocation(location)\n let parts = canonicalLocation.split(',').map(part => part.trim()).filter(Boolean)\n if (parts.length > 1 && isUnitedStates(parts[parts.length - 1])) {\n parts = parts.slice(0, -1)\n }\n\n if (parts.length === 1) {\n const stateOnly = stateCodeFor(parts[0])\n if (!stateOnly) return null\n return {\n canonicalLocation: canonicalLocation as CanonicalLocationName,\n level: 'state',\n country: 'US',\n state: stateOnly,\n city: '',\n cityCandidates: [],\n proxyName: proxyName('US', stateOnly),\n config: {\n country: 'US',\n state: stateOnly,\n },\n }\n }\n\n const [city = '', region = ''] = parts\n if (!city || !region) return null\n const state = stateCodeFor(region)\n if (!state) return null\n const cityCandidates = kernelCityIdentifierCandidates(city)\n const primaryCity = cityCandidates[0]\n if (!primaryCity) return null\n return {\n canonicalLocation: canonicalLocation as CanonicalLocationName,\n level: 'city',\n country: 'US',\n state,\n city: primaryCity,\n cityCandidates,\n proxyName: proxyName('US', state, primaryCity),\n config: {\n country: 'US',\n state,\n city: primaryCity,\n },\n }\n}\n\nfunction cityZipKey(target: KernelLocationProxyTarget): string {\n return `${target.city}|${target.state}`\n}\n\nfunction knownZipFor(target: KernelLocationProxyTarget, explicitZip: string | undefined): string | null {\n if (explicitZip && /^\\d{5}$/.test(explicitZip)) return explicitZip\n return US_CITY_CENTER_ZIPS[cityZipKey(target)] ?? null\n}\n\nfunction zipTarget(target: KernelLocationProxyTarget, zip: string): KernelLocationProxyTarget {\n return {\n ...target,\n level: 'zip',\n zip,\n proxyName: zipProxyName(zip),\n config: {\n country: target.country,\n state: target.state,\n zip,\n },\n }\n}\n\nfunction configMatches(config: KernelProxyConfig | undefined, target: KernelLocationProxyTarget, city?: string): boolean {\n if (target.level === 'zip') {\n return config?.country?.toUpperCase() === target.country && config?.zip === target.zip\n }\n return config?.country?.toUpperCase() === target.country &&\n config?.state?.toUpperCase() === target.state &&\n (city ? config?.city === city : !config?.city)\n}\n\nfunction findExistingTargetProxy(proxies: KernelProxyListItem[], target: KernelLocationProxyTarget): KernelProxyListItem | null {\n return proxies.find(proxy => (\n proxy.type === 'residential' &&\n proxy.status !== 'unavailable' &&\n Boolean(proxy.id) &&\n (proxy.name === target.proxyName || configMatches(proxy.config, target, target.level === 'city' ? target.city : undefined))\n )) ?? null\n}\n\nfunction findExistingProxy(proxies: KernelProxyListItem[], target: KernelLocationProxyTarget): KernelProxyListItem | null {\n for (const city of target.cityCandidates) {\n const name = proxyName(target.country, target.state, city)\n const found = proxies.find(proxy => (\n proxy.type === 'residential' &&\n proxy.status !== 'unavailable' &&\n Boolean(proxy.id) &&\n (proxy.name === name || configMatches(proxy.config, target, city))\n ))\n if (found) return found\n }\n return null\n}\n\nfunction stateTarget(target: KernelLocationProxyTarget): KernelLocationProxyTarget {\n return {\n ...target,\n level: 'state',\n proxyName: proxyName(target.country, target.state),\n config: {\n country: target.country,\n state: target.state,\n },\n }\n}\n\nfunction findExistingStateProxy(proxies: KernelProxyListItem[], target: KernelLocationProxyTarget): KernelProxyListItem | null {\n const name = proxyName(target.country, target.state)\n return proxies.find(proxy => (\n proxy.type === 'residential' &&\n proxy.status !== 'unavailable' &&\n Boolean(proxy.id) &&\n (proxy.name === name || configMatches(proxy.config, target))\n )) ?? null\n}\n\nfunction escalatedTargetLevel(target: KernelLocationProxyTarget, attemptIndex: number): KernelLocationProxyTarget {\n return stateTarget(target)\n}\n\nfunction errorText(err: unknown): string {\n return err instanceof Error ? err.message : String(err)\n}\n\nexport async function resolveKernelProxyId(options: ResolveKernelProxyOptions): Promise<ResolveKernelProxyResult> {\n if (options.proxyMode === 'none') {\n return resolution('disabled', options.proxyMode, undefined, null, null)\n }\n\n if (options.proxyMode === 'configured') {\n return resolution('configured_fallback', options.proxyMode, options.configuredKernelProxyId, null, null)\n }\n\n const target = parseKernelLocationProxyTarget(options.location, options.gl)\n if (!target || !options.kernelApiKey) {\n return resolution('configured_fallback', options.proxyMode, options.configuredKernelProxyId, target, target ? null : 'location could not be normalized to a US city/state proxy target')\n }\n\n const kernel = new Kernel({ apiKey: options.kernelApiKey })\n try {\n const attemptIndex = options.attemptIndex ?? 0\n\n if (attemptIndex >= 1) {\n const escalatedTarget = escalatedTargetLevel(target, attemptIndex)\n const createErrors: string[] = []\n try {\n const created = await kernel.proxies.create({\n type: 'residential',\n name: escalatedTarget.proxyName,\n config: escalatedTarget.config,\n }) as KernelProxyCreateResponse\n if (created.id) {\n return resolution('location_created', options.proxyMode, created.id, escalatedTarget, null)\n }\n createErrors.push(`${escalatedTarget.state}: Kernel did not return a proxy id`)\n } catch (err) {\n createErrors.push(`${escalatedTarget.state}: ${errorText(err)}`)\n }\n return resolution('configured_fallback', options.proxyMode, options.configuredKernelProxyId, escalatedTarget, createErrors.join(' | '))\n }\n\n const proxies = await kernel.proxies.list() as KernelProxyListItem[]\n const zip = knownZipFor(target, options.proxyZip)\n const createErrors: string[] = []\n if (zip) {\n const targetZip = zipTarget(target, zip)\n const existingZip = findExistingTargetProxy(proxies, targetZip)\n if (existingZip?.id) {\n return resolution('location_reused', options.proxyMode, existingZip.id, targetZip, null)\n }\n try {\n const created = await kernel.proxies.create({\n type: 'residential',\n name: targetZip.proxyName,\n config: {\n country: targetZip.country,\n zip,\n },\n }) as KernelProxyCreateResponse\n if (created.id) {\n return resolution('location_created', options.proxyMode, created.id, targetZip, null)\n }\n createErrors.push(`${zip}: Kernel did not return a proxy id`)\n } catch (err) {\n createErrors.push(`${zip}: ${errorText(err)}`)\n }\n }\n\n const existing = findExistingProxy(proxies, target)\n if (existing?.id) {\n return resolution('location_reused', options.proxyMode, existing.id, target, createErrors.join(' | ') || null)\n }\n\n for (const city of target.cityCandidates) {\n try {\n const created = await kernel.proxies.create({\n type: 'residential',\n name: proxyName(target.country, target.state, city),\n config: {\n country: target.country,\n state: target.state,\n city,\n },\n }) as KernelProxyCreateResponse\n if (created.id) {\n return resolution('location_created', options.proxyMode, created.id, {\n ...target,\n level: 'city',\n city,\n proxyName: proxyName(target.country, target.state, city),\n config: {\n country: target.country,\n state: target.state,\n city,\n },\n }, null)\n }\n createErrors.push(`${city}: Kernel did not return a proxy id`)\n } catch (err) {\n createErrors.push(`${city}: ${errorText(err)}`)\n }\n }\n const fallbackTarget = stateTarget(target)\n const existingState = findExistingStateProxy(proxies, fallbackTarget)\n if (existingState?.id) {\n return resolution('location_reused', options.proxyMode, existingState.id, fallbackTarget, createErrors.join(' | '))\n }\n try {\n const created = await kernel.proxies.create({\n type: 'residential',\n name: fallbackTarget.proxyName,\n config: fallbackTarget.config,\n }) as KernelProxyCreateResponse\n if (created.id) {\n return resolution('location_created', options.proxyMode, created.id, fallbackTarget, createErrors.join(' | '))\n }\n createErrors.push(`${fallbackTarget.state}: Kernel did not return a proxy id`)\n } catch (err) {\n createErrors.push(`${fallbackTarget.state}: ${errorText(err)}`)\n }\n return resolution('configured_fallback', options.proxyMode, options.configuredKernelProxyId, target, createErrors.join(' | '))\n } catch (err) {\n return resolution('configured_fallback', options.proxyMode, options.configuredKernelProxyId, target, errorText(err))\n }\n}\n","import { HarvestOptionsSchema } from './schemas.js'\nimport type { HarvestDebugSnapshot, HarvestOptions, HarvestResult, ProxyMode } from './types.js'\nimport { BrowserDriver } from './driver/BrowserDriver.js'\nimport { PAAExtractor } from './extractor/PAAExtractor.js'\nimport { OutputSerializer } from './output/OutputSerializer.js'\nimport { ProgressReporter } from './output/ProgressReporter.js'\nimport { CaptchaError, RequestAbortedError, sanitizeVendorName } from './errors.js'\nimport type { BrowserCloseResult } from './driver/IBrowserDriver.js'\nimport { resolveKernelProxyId } from './kernel-proxy-resolver.js'\n\nconst MAX_ATTEMPTS = 3\n\nexport type HarvestAttemptOutcome =\n | 'paa_found'\n | 'paa_partial'\n | 'no_paa'\n | 'serp_only'\n | 'captcha'\n | 'request_aborted'\n | 'timeout'\n | 'error'\n\nexport type HarvestAttemptLogEvent =\n | {\n type: 'started'\n attemptNumber: number\n maxAttempts: number\n query: string\n location: string | null\n maxQuestions: number\n startedAt: string\n }\n | {\n type: 'finished'\n attemptNumber: number\n maxAttempts: number\n outcome: HarvestAttemptOutcome\n kernelSessionId: string | null\n questionCount: number\n durationMs: number\n error: string | null\n willRetry: boolean\n cleanup: BrowserCloseResult\n debug: HarvestDebugSnapshot | null\n completedAt: string\n }\n\ntype HarvestAttemptLogSink = (event: HarvestAttemptLogEvent) => void | Promise<void>\n\ntype ExtractOnceOutcome =\n | { result: HarvestResult; error: null; cleanup: BrowserCloseResult; debug: HarvestDebugSnapshot | null }\n | { result: null; error: unknown; cleanup: BrowserCloseResult; debug: HarvestDebugSnapshot | null }\n\nfunction abortReason(signal: AbortSignal): unknown {\n if (signal.reason instanceof DOMException && signal.reason.name === 'TimeoutError') return signal.reason\n return new RequestAbortedError()\n}\n\nfunction getAbortSignal(rawOptions: unknown): AbortSignal | undefined {\n if (!rawOptions || typeof rawOptions !== 'object') return undefined\n const signal = (rawOptions as { signal?: unknown }).signal\n if (signal instanceof AbortSignal) return signal\n return undefined\n}\n\nfunction getAttemptLogSink(rawOptions: unknown): HarvestAttemptLogSink | undefined {\n if (!rawOptions || typeof rawOptions !== 'object') return undefined\n const sink = (rawOptions as { onAttemptEvent?: unknown }).onAttemptEvent\n return typeof sink === 'function' ? sink as HarvestAttemptLogSink : undefined\n}\n\nasync function emitAttemptEvent(sink: HarvestAttemptLogSink | undefined, event: HarvestAttemptLogEvent): Promise<void> {\n if (!sink) return\n try {\n await sink(event)\n } catch (err) {\n console.warn(JSON.stringify({\n event: 'harvest_attempt_log_failed',\n attempt_number: event.attemptNumber,\n message: err instanceof Error ? err.message : String(err),\n }))\n }\n}\n\nfunction classifyAttemptError(err: unknown): HarvestAttemptOutcome {\n if (err instanceof CaptchaError) return 'captcha'\n if (err instanceof RequestAbortedError) return 'request_aborted'\n if (err instanceof DOMException && (err.name === 'TimeoutError' || err.name === 'AbortError')) return 'timeout'\n const message = err instanceof Error ? err.message : String(err)\n return /timeout|timed out|Timeout \\d+ms exceeded|deadline/i.test(message) ? 'timeout' : 'error'\n}\n\nfunction classifyAttemptResult(result: HarvestResult): HarvestAttemptOutcome {\n return result.diagnostics?.completionStatus ?? (result.totalQuestions > 0 ? 'paa_found' : 'no_paa')\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err)\n}\n\nasync function extractOnce(options: HarvestOptions, signal?: AbortSignal): Promise<ExtractOnceOutcome> {\n const driver = new BrowserDriver()\n const reporter = new ProgressReporter()\n const extractor = new PAAExtractor(driver, reporter)\n if (signal?.aborted) {\n return {\n result: null,\n error: abortReason(signal),\n cleanup: await driver.close(),\n debug: null,\n }\n }\n\n let onAbort: (() => void) | undefined\n const abortPromise = signal\n ? new Promise<never>((_, reject) => {\n onAbort = () => reject(abortReason(signal))\n signal.addEventListener('abort', onAbort, { once: true })\n })\n : null\n\n let result: HarvestResult | null = null\n let error: unknown = null\n let cleanup: BrowserCloseResult\n let debug: HarvestDebugSnapshot | null = null\n try {\n const extraction = extractor.extract(options, signal)\n if (abortPromise) extraction.catch(() => {})\n result = await (abortPromise ? Promise.race([extraction, abortPromise]) : extraction)\n } catch (err) {\n error = err\n } finally {\n if (signal && onAbort) signal.removeEventListener('abort', onAbort)\n debug = result?.diagnostics.debug ?? (options.debug ? {\n enabled: true,\n request: {\n query: options.query,\n locationInput: options.location ?? null,\n canonicalLocation: null,\n uule: null,\n gl: options.gl,\n hl: options.hl,\n device: options.device,\n proxyMode: options.proxyMode,\n proxyZip: options.proxyZip ?? null,\n serpOnly: options.serpOnly,\n pages: options.pages ?? 1,\n },\n browser: driver.getDebugSnapshot(),\n } : null)\n cleanup = await driver.close()\n }\n return error\n ? { result: null, error, cleanup: cleanup!, debug }\n : { result: result!, error: null, cleanup: cleanup!, debug }\n}\n\nexport async function harvest(rawOptions: unknown): Promise<HarvestResult> {\n const raw = typeof rawOptions === 'object' && rawOptions !== null ? rawOptions : {}\n const signal = getAbortSignal(rawOptions)\n const onAttemptEvent = getAttemptLogSink(rawOptions)\n const requestedProxyMode = (raw as { proxyMode?: unknown }).proxyMode\n const proxyMode = requestedProxyMode === 'none'\n ? 'none'\n : requestedProxyMode === 'configured'\n ? 'configured'\n : 'location'\n const kernelApiKey = typeof (raw as { kernelApiKey?: unknown }).kernelApiKey === 'string'\n ? ((raw as { kernelApiKey: string }).kernelApiKey).trim()\n : process.env.KERNEL_API_KEY?.trim()\n const configuredKernelProxyId = typeof (raw as { kernelProxyId?: unknown }).kernelProxyId === 'string'\n ? ((raw as { kernelProxyId: string }).kernelProxyId).trim()\n : process.env.KERNEL_PROXY_ID?.trim()\n const proxyOpts = {\n kernelApiKey,\n proxyMode: proxyMode as ProxyMode,\n configuredKernelProxyId,\n location: typeof (raw as { location?: unknown }).location === 'string' ? (raw as { location: string }).location : undefined,\n proxyZip: typeof (raw as { proxyZip?: unknown }).proxyZip === 'string' ? (raw as { proxyZip: string }).proxyZip : undefined,\n gl: typeof (raw as { gl?: unknown }).gl === 'string' ? (raw as { gl: string }).gl : 'us',\n }\n const serializer = new OutputSerializer()\n\n for (let i = 0; i < MAX_ATTEMPTS; i++) {\n const attemptNumber = i + 1\n const startedAtMs = Date.now()\n try {\n if (signal?.aborted) throw abortReason(signal)\n const resolution = await resolveKernelProxyId({ ...proxyOpts, attemptIndex: i })\n const mergedAttempt = {\n ...raw,\n kernelApiKey,\n kernelProxyId: resolution.kernelProxyId,\n kernelProxyResolution: resolution.resolution,\n proxyMode,\n }\n if (proxyMode === 'none') (mergedAttempt as Record<string, unknown>).kernelProxyId = undefined\n const attemptOptions = HarvestOptionsSchema.parse(mergedAttempt)\n await emitAttemptEvent(onAttemptEvent, {\n type: 'started',\n attemptNumber,\n maxAttempts: MAX_ATTEMPTS,\n query: attemptOptions.query,\n location: attemptOptions.location ?? null,\n maxQuestions: attemptOptions.maxQuestions,\n startedAt: new Date(startedAtMs).toISOString(),\n })\n console.info(JSON.stringify({\n event: 'harvest_attempt_started',\n attempt_number: attemptNumber,\n max_attempts: MAX_ATTEMPTS,\n query: attemptOptions.query,\n location: attemptOptions.location ?? null,\n max_questions: attemptOptions.maxQuestions,\n }))\n const attempt = await extractOnce(attemptOptions, signal)\n if (attempt.error) {\n const err = attempt.error\n if (err instanceof CaptchaError) {\n const willRetry = i < MAX_ATTEMPTS - 1\n console.warn(JSON.stringify({\n event: 'harvest_attempt_captcha',\n attempt_number: attemptNumber,\n max_attempts: MAX_ATTEMPTS,\n message: err.message,\n will_retry: willRetry,\n }))\n await emitAttemptEvent(onAttemptEvent, {\n type: 'finished',\n attemptNumber,\n maxAttempts: MAX_ATTEMPTS,\n outcome: 'captcha',\n kernelSessionId: attempt.cleanup.kernelSessionId,\n questionCount: 0,\n durationMs: Date.now() - startedAtMs,\n error: err.message,\n willRetry,\n cleanup: attempt.cleanup,\n debug: attempt.debug,\n completedAt: new Date().toISOString(),\n })\n if (willRetry) continue\n break\n }\n await emitAttemptEvent(onAttemptEvent, {\n type: 'finished',\n attemptNumber,\n maxAttempts: MAX_ATTEMPTS,\n outcome: classifyAttemptError(err),\n kernelSessionId: attempt.cleanup.kernelSessionId,\n questionCount: 0,\n durationMs: Date.now() - startedAtMs,\n error: errorMessage(err),\n willRetry: false,\n cleanup: attempt.cleanup,\n debug: attempt.debug,\n completedAt: new Date().toISOString(),\n })\n throw err\n }\n const result = attempt.result\n if (!result) throw new Error('Harvest attempt completed without a result')\n await emitAttemptEvent(onAttemptEvent, {\n type: 'finished',\n attemptNumber,\n maxAttempts: MAX_ATTEMPTS,\n outcome: classifyAttemptResult(result),\n kernelSessionId: attempt.cleanup.kernelSessionId,\n questionCount: result.totalQuestions,\n durationMs: Date.now() - startedAtMs,\n error: null,\n willRetry: false,\n cleanup: attempt.cleanup,\n debug: attempt.debug,\n completedAt: new Date().toISOString(),\n })\n if (attemptOptions.format === 'json' || attemptOptions.format === 'both') {\n await serializer.writeJSON(result, attemptOptions.outputDir)\n }\n if (attemptOptions.format === 'csv' || attemptOptions.format === 'both') {\n await Promise.all([\n serializer.writeCSV(result.flat, attemptOptions.outputDir),\n result.videos.length > 0 ? serializer.writeVideoCSV(result.videos, result.seed, attemptOptions.outputDir) : Promise.resolve(''),\n result.forums.length > 0 ? serializer.writeForumCSV(result.forums, result.seed, attemptOptions.outputDir) : Promise.resolve(''),\n result.aiOverview.detected ? serializer.writeAIOverviewCSV(result.aiOverview.citations, result.aiOverview.text, result.seed, attemptOptions.outputDir) : Promise.resolve(''),\n result.aiMode.detected ? serializer.writeAIModeCSV(result.aiMode.citations, result.aiMode.text, result.seed, attemptOptions.outputDir) : Promise.resolve(''),\n result.whatPeopleSaying.length > 0 ? serializer.writeWhatPeopleSayingCSV(result.whatPeopleSaying, result.seed, attemptOptions.outputDir) : Promise.resolve(''),\n ])\n }\n return result\n } catch (err) {\n if (err instanceof CaptchaError) {\n const willRetry = i < MAX_ATTEMPTS - 1\n console.warn(JSON.stringify({\n event: 'harvest_attempt_captcha',\n attempt_number: attemptNumber,\n max_attempts: MAX_ATTEMPTS,\n message: err.message,\n will_retry: willRetry,\n }))\n await emitAttemptEvent(onAttemptEvent, {\n type: 'finished',\n attemptNumber,\n maxAttempts: MAX_ATTEMPTS,\n outcome: 'captcha',\n kernelSessionId: null,\n questionCount: 0,\n durationMs: Date.now() - startedAtMs,\n error: err.message,\n willRetry,\n cleanup: {\n kernelSessionId: null,\n kernelDeleteStarted: false,\n kernelDeleteSucceeded: null,\n kernelDeleteError: null,\n browserCloseSucceeded: null,\n browserCloseError: null,\n },\n debug: null,\n completedAt: new Date().toISOString(),\n })\n if (willRetry) continue\n break\n }\n await emitAttemptEvent(onAttemptEvent, {\n type: 'finished',\n attemptNumber,\n maxAttempts: MAX_ATTEMPTS,\n outcome: classifyAttemptError(err),\n kernelSessionId: null,\n questionCount: 0,\n durationMs: Date.now() - startedAtMs,\n error: errorMessage(err),\n willRetry: false,\n cleanup: {\n kernelSessionId: null,\n kernelDeleteStarted: false,\n kernelDeleteSucceeded: null,\n kernelDeleteError: null,\n browserCloseSucceeded: null,\n browserCloseError: null,\n },\n debug: null,\n completedAt: new Date().toISOString(),\n })\n throw err\n }\n }\n console.warn(JSON.stringify({\n event: 'harvest_captcha_exhausted',\n max_attempts: MAX_ATTEMPTS,\n session_kind: kernelApiKey ? 'kernel' : 'local',\n }))\n throw new CaptchaError(sanitizeVendorName(`CAPTCHA on all ${MAX_ATTEMPTS} fresh sessions. Try again in a few minutes.`))\n}\n","#!/usr/bin/env node\nimport { runCli } from '../src/cli.js'\nrunCli()\n"],"mappings":"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","names":["StealthPlugin","Kernel","playwrightChromium","DESKTOP_USER_AGENT","MOBILE_USER_AGENT","s","organicResults","localPack","rawEntityIds","entityIds","aiSurfaces","locationEvidence","allOrganic","stats","fs","path","Papa","import_sdk","proxyIdSuffix","errorText","Kernel","createErrors","resolution"]}
|