mcp-scraper 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -0
- package/dist/bin/api-server.cjs +9256 -0
- package/dist/bin/api-server.cjs.map +1 -0
- package/dist/bin/api-server.d.cts +1 -0
- package/dist/bin/api-server.d.ts +1 -0
- package/dist/bin/api-server.js +38 -0
- package/dist/bin/api-server.js.map +1 -0
- package/dist/bin/mcp-stdio-server.cjs +840 -0
- package/dist/bin/mcp-stdio-server.cjs.map +1 -0
- package/dist/bin/mcp-stdio-server.d.cts +1 -0
- package/dist/bin/mcp-stdio-server.d.ts +1 -0
- package/dist/bin/mcp-stdio-server.js +41 -0
- package/dist/bin/mcp-stdio-server.js.map +1 -0
- package/dist/bin/paa-harvest.cjs +1438 -0
- package/dist/bin/paa-harvest.cjs.map +1 -0
- package/dist/bin/paa-harvest.d.cts +1 -0
- package/dist/bin/paa-harvest.d.ts +1 -0
- package/dist/bin/paa-harvest.js +37 -0
- package/dist/bin/paa-harvest.js.map +1 -0
- package/dist/chunk-4API3ZCT.js +1387 -0
- package/dist/chunk-4API3ZCT.js.map +1 -0
- package/dist/chunk-LXZDJJXR.js +476 -0
- package/dist/chunk-LXZDJJXR.js.map +1 -0
- package/dist/chunk-ZBP4RHNW.js +805 -0
- package/dist/chunk-ZBP4RHNW.js.map +1 -0
- package/dist/db-IOYMX64U.js +87 -0
- package/dist/db-IOYMX64U.js.map +1 -0
- package/dist/index.cjs +1689 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +210 -0
- package/dist/index.d.ts +210 -0
- package/dist/index.js +275 -0
- package/dist/index.js.map +1 -0
- package/dist/server-63DR2HE5.js +6062 -0
- package/dist/server-63DR2HE5.js.map +1 -0
- package/dist/worker-3ECJHPRE.js +88 -0
- package/dist/worker-3ECJHPRE.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/api/kernel-fetch.ts","../../src/api/site-mapper.ts","../../src/api/site-extractor.ts","../../src/inngest/client.ts","../../src/lib/llm-parse-with-retry.ts","../../src/lib/http-client.ts","../../src/lib/site-architecture-auditor/rules.ts","../../src/services/site-architecture-auditor/schemas.ts","../../src/services/site-architecture-auditor/prompts/ingest-validate.ts","../../src/services/site-architecture-auditor/prompts/enrich-competitor.ts","../../src/services/site-architecture-auditor/prompts/build-graph-per-site.ts","../../src/services/site-architecture-auditor/prompts/metrics-classify.ts","../../src/services/site-architecture-auditor/prompts/compare-recommend.ts","../../src/services/site-architecture-auditor/prompts/score-synthesize.ts","../../src/services/site-architecture-auditor/site-audit-service.ts","../../src/api/db.ts","../../src/services/site-architecture-auditor/site-audit-repository.ts","../../src/services/site-architecture-auditor/python/graph-runner.ts","../../src/services/site-architecture-auditor/factory.ts","../../src/services/site-architecture-auditor/phases.ts","../../src/inngest/functions/site-audit.ts","../../src/api/site-audit-middleware.ts","../../src/api/site-audit-routes.ts","../../src/api/rates.ts","../../src/youtube/schemas.ts","../../src/selectors.ts","../../src/errors.ts","../../src/driver/BrowserDriver.ts","../../src/youtube/YouTubeExtractor.ts","../../src/youtube/MP3Downloader.ts","../../src/youtube/YTProgressReporter.ts","../../src/youtube/youtube-harvest.ts","../../src/youtube/CaptionFetcher.ts","../../src/api/youtube-routes.ts","../../src/lib/screenshot.ts","../../src/api/screenshot-routes.ts","../../src/extractor/FacebookAdExtractor.ts","../../src/api/facebook-ad-routes.ts","../../src/extractor/MapsExtractor.ts","../../src/schemas.ts","../../src/api/maps-routes.ts","../../src/mcp/mcp-tool-schemas.ts","../../src/mcp/mcp-response-formatter.ts","../../src/mcp/paa-mcp-server.ts","../../src/mcp/stub-mcp-tool-executor.ts","../../src/mcp/http-mcp-tool-executor.ts","../../src/mcp/mcp-routes.ts","../../src/api/stripe-routes.ts","../../src/api/site-audit-worker.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","../../src/api/session.ts","../../src/api/webhook.ts","../../src/api/worker.ts","../../src/api/server.ts","../../bin/api-server.ts"],"sourcesContent":["import Kernel from '@onkernel/sdk'\nimport { chromium } from 'playwright'\n\nexport async function fetchWithKernel(url: string): Promise<string> {\n const apiKey = process.env.KERNEL_API_KEY\n if (!apiKey) throw new Error('KERNEL_API_KEY not set')\n\n const client = new Kernel({ apiKey })\n const kb = await client.browsers.create({ stealth: true, timeout_seconds: 60 })\n const browser = await chromium.connectOverCDP(kb.cdp_ws_url)\n\n try {\n const context = browser.contexts()[0] ?? await browser.newContext({\n userAgent: '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 })\n const page = context.pages()[0] ?? await context.newPage()\n await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30_000 })\n await page.waitForTimeout(2500)\n return await page.content()\n } finally {\n await browser.close().catch(() => {})\n await client.browsers.deleteByID(kb.session_id).catch(() => {})\n }\n}\n","import { fetchWithKernel } from './kernel-fetch.js'\n\nconst SKIP_EXTENSIONS = new Set([\n 'jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'ico', 'avif', 'bmp', 'tiff',\n 'css', 'js', 'mjs', 'map', 'woff', 'woff2', 'ttf', 'otf', 'eot',\n 'pdf', 'zip', 'tar', 'gz', 'rar', 'dmg', 'exe', 'apk',\n 'mp4', 'webm', 'mov', 'avi', 'mkv', 'mp3', 'wav', 'ogg', 'flac',\n 'xml', 'json', 'csv', 'txt', 'rss', 'atom',\n])\n\nconst SKIP_PATH_SEGMENTS = new Set([\n 'wp-login.php', 'wp-admin', 'wp-content', 'wp-includes', 'wp-json',\n 'login', 'logout', 'signin', 'sign-in', 'sign-up', 'signup', 'register',\n 'cart', 'checkout', 'my-account', 'account', 'dashboard', 'profile',\n 'feed', 'rss', 'sitemap.xml', 'robots.txt',\n 'cdn-cgi', '__', 'static', 'assets', 'dist', 'build',\n 'api', 'graphql', 'admin',\n])\n\nconst SKIP_PATH_PREFIXES = [\n '/wp-content/', '/wp-includes/', '/wp-json/', '/wp-admin/',\n '/cdn-cgi/', '/__/',\n '/feed/', '/rss/',\n '/api/', '/graphql/',\n]\n\nconst SKIP_QUERY_PARAMS = ['replytocom', 'p', 'preview', 'ver', 'v']\n\nconst KERNEL_RETRY_LIMIT = 15\nconst UA = 'Mozilla/5.0 (compatible; ThorbitBot/1.0; +https://thorbit.ai)'\n\nexport interface SpiderOptions {\n startUrl: string\n maxUrls?: number\n concurrency?: number\n timeoutMs?: number\n kernelApiKey?: string\n}\n\nexport interface DiscoveredUrl {\n url: string\n status: number | null\n linkedFrom: string\n via?: 'fetch' | 'kernel'\n}\n\nexport interface SpiderResult {\n startUrl: string\n urls: DiscoveredUrl[]\n totalFound: number\n durationMs: number\n truncated: boolean\n kernelRetries: number\n}\n\nexport function normalizeUrl(href: string, base: string): string | null {\n try {\n const u = new URL(href.trim(), base)\n if (u.protocol !== 'http:' && u.protocol !== 'https:') return null\n\n u.hash = ''\n\n const ext = u.pathname.split('.').pop()?.toLowerCase() ?? ''\n if (SKIP_EXTENSIONS.has(ext)) return null\n\n for (const prefix of SKIP_PATH_PREFIXES) {\n if (u.pathname.toLowerCase().startsWith(prefix)) return null\n }\n\n const segments = u.pathname.toLowerCase().split('/')\n for (const seg of segments) {\n if (SKIP_PATH_SEGMENTS.has(seg)) return null\n }\n\n for (const param of SKIP_QUERY_PARAMS) {\n u.searchParams.delete(param)\n }\n\n if (u.searchParams.has('s')) return null\n\n return u.href\n } catch {\n return null\n }\n}\n\nexport function extractLinks(html: string, base: string): string[] {\n const seen = new Set<string>()\n const links: string[] = []\n for (const m of html.matchAll(/href\\s*=\\s*[\"']([^\"'\\s>]+)/gi)) {\n const normalized = normalizeUrl(m[1], base)\n if (normalized && !seen.has(normalized)) {\n seen.add(normalized)\n links.push(normalized)\n }\n }\n return links\n}\n\nasync function fetchText(url: string, timeoutMs = 10_000): Promise<string | null> {\n try {\n const res = await fetch(url, {\n headers: { 'User-Agent': UA },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (!res.ok) return null\n return await res.text()\n } catch {\n return null\n }\n}\n\nfunction extractSitemapLocs(xml: string): string[] {\n const locs: string[] = []\n for (const m of xml.matchAll(/<loc>\\s*(https?:\\/\\/[^<\\s]+)\\s*<\\/loc>/gi)) {\n locs.push(m[1].trim())\n }\n return locs\n}\n\nasync function parseSitemap(url: string, startDomain: string, depth = 0): Promise<string[]> {\n if (depth > 3) return []\n const xml = await fetchText(url)\n if (!xml) return []\n\n if (xml.includes('<sitemapindex')) {\n const subUrls = extractSitemapLocs(xml)\n const nested = await Promise.all(\n subUrls.slice(0, 20).map(u => parseSitemap(u, startDomain, depth + 1))\n )\n return nested.flat()\n }\n\n return extractSitemapLocs(xml).filter(loc => baseDomain(loc) === startDomain)\n}\n\nasync function discoverSitemapUrls(startUrl: string, startDomain: string): Promise<string[]> {\n const origin = new URL(startUrl).origin\n const candidates: string[] = []\n\n const robotsTxt = await fetchText(`${origin}/robots.txt`)\n if (robotsTxt) {\n for (const m of robotsTxt.matchAll(/^Sitemap:\\s*(.+)$/gim)) {\n candidates.push(m[1].trim())\n }\n }\n\n for (const path of ['/sitemap.xml', '/wp-sitemap.xml', '/sitemap_index.xml']) {\n const u = `${origin}${path}`\n if (!candidates.includes(u)) candidates.push(u)\n }\n\n const allLocs = await Promise.all(\n candidates.slice(0, 8).map(u => parseSitemap(u, startDomain))\n )\n const seen = new Set<string>()\n const urls: string[] = []\n for (const loc of allLocs.flat()) {\n const normalized = normalizeUrl(loc, loc)\n if (normalized && !seen.has(normalized)) {\n seen.add(normalized)\n urls.push(normalized)\n }\n }\n return urls\n}\n\nasync function fetchPage(url: string, timeoutMs: number): Promise<{ html: string | null; status: number | null; finalUrl?: string }> {\n try {\n const res = await fetch(url, {\n headers: { 'User-Agent': UA, 'Accept': 'text/html,application/xhtml+xml' },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (!res.ok) return { html: null, status: res.status }\n const ct = res.headers.get('content-type') ?? ''\n if (!ct.includes('html')) return { html: null, status: res.status }\n const html = await res.text()\n return { html, status: res.status, finalUrl: res.url }\n } catch {\n return { html: null, status: null }\n }\n}\n\nfunction baseDomain(url: string): string {\n try { return new URL(url).hostname.replace(/^www\\./, '') } catch { return '' }\n}\n\nexport async function spiderSite(opts: SpiderOptions): Promise<SpiderResult> {\n const startMs = Date.now()\n const maxUrls = Math.min(opts.maxUrls ?? 500, 2000)\n const concurrency = Math.min(opts.concurrency ?? 12, 20)\n const timeoutMs = opts.timeoutMs ?? 8_000\n\n const startNorm = normalizeUrl(opts.startUrl, opts.startUrl) ?? opts.startUrl\n const startDomain = baseDomain(opts.startUrl)\n\n const visited = new Set<string>()\n const queue: Array<{ url: string; from: string }> = [{ url: startNorm, from: startNorm }]\n const results: DiscoveredUrl[] = []\n\n visited.add(startNorm)\n\n const sitemapUrls = await discoverSitemapUrls(opts.startUrl, startDomain)\n for (const loc of sitemapUrls) {\n if (!visited.has(loc)) {\n visited.add(loc)\n queue.push({ url: loc, from: 'sitemap' })\n }\n }\n\n while (queue.length > 0 && results.length < maxUrls) {\n const batch = queue.splice(0, concurrency)\n\n const settled = await Promise.all(\n batch.map(async ({ url, from }) => {\n const { html, status } = await fetchPage(url, timeoutMs)\n const discovered: DiscoveredUrl = { url, status, linkedFrom: from, via: 'fetch' }\n const children: Array<{ url: string; from: string }> = []\n\n if (html) {\n for (const link of extractLinks(html, url)) {\n if (baseDomain(link) !== startDomain) continue\n if (!visited.has(link)) {\n visited.add(link)\n children.push({ url: link, from: url })\n }\n }\n }\n\n return { discovered, children }\n }),\n )\n\n for (const { discovered, children } of settled) {\n results.push(discovered)\n for (const child of children) {\n if (results.length + queue.length < maxUrls * 2) {\n queue.push(child)\n }\n }\n }\n }\n\n let kernelRetries = 0\n\n if (opts.kernelApiKey) {\n const retryTargets = results\n .filter(r => r.status === null || r.status === 403 || r.status === 429)\n .slice(0, KERNEL_RETRY_LIMIT)\n\n for (const target of retryTargets) {\n try {\n const html = await fetchWithKernel(target.url)\n target.status = 200\n target.via = 'kernel'\n kernelRetries++\n\n for (const link of extractLinks(html, target.url)) {\n if (baseDomain(link) !== startDomain) continue\n if (!visited.has(link) && results.length < maxUrls) {\n visited.add(link)\n results.push({ url: link, status: null, linkedFrom: target.url, via: 'fetch' })\n }\n }\n } catch { /**/ }\n }\n }\n\n return {\n startUrl: opts.startUrl,\n urls: results,\n totalFound: results.length,\n durationMs: Date.now() - startMs,\n truncated: queue.length > 0 || results.length >= maxUrls,\n kernelRetries,\n }\n}\n","import { spiderSite, extractLinks } from './site-mapper.js'\nimport { fetchWithKernel } from './kernel-fetch.js'\nimport type { SpiderResult } from './site-mapper.js'\n\nconst UA = 'Mozilla/5.0 (compatible; ThorbitBot/1.0; +https://thorbit.ai)'\nconst EXTRACT_CONCURRENCY = 6\n\nexport interface PageData {\n url: string\n status: number | null\n via: 'fetch' | 'kernel'\n title: string | null\n metaDescription: string | null\n h1: string | null\n headings: Array<{ level: number; text: string }>\n wordCount: number\n schemaTypes: string[]\n canonicalUrl: string | null\n internalLinks: number\n externalLinks: number\n}\n\nexport interface ExtractResult {\n startUrl: string\n pages: PageData[]\n totalPages: number\n spider: SpiderResult\n durationMs: number\n truncated: boolean\n kernelRetries: number\n}\n\nexport interface ExtractOptions {\n startUrl: string\n maxPages?: number\n concurrency?: number\n kernelApiKey?: string\n}\n\nfunction parsePageData(url: string, html: string, status: number, via: 'fetch' | 'kernel'): PageData {\n const origin = new URL(url).origin\n\n const title = html.match(/<title[^>]*>([^<]*)<\\/title>/i)?.[1]?.trim() ?? null\n const metaDescription = html.match(/<meta[^>]+name=[\"']description[\"'][^>]+content=[\"']([^\"']*)[\"']/i)?.[1]?.trim()\n ?? html.match(/<meta[^>]+content=[\"']([^\"']*)[\"'][^>]+name=[\"']description[\"']/i)?.[1]?.trim()\n ?? null\n const canonicalUrl = html.match(/<link[^>]+rel=[\"']canonical[\"'][^>]+href=[\"']([^\"']*)[\"']/i)?.[1]?.trim()\n ?? html.match(/<link[^>]+href=[\"']([^\"']*)[\"'][^>]+rel=[\"']canonical[\"']/i)?.[1]?.trim()\n ?? null\n\n const headings: Array<{ level: number; text: string }> = []\n for (const m of html.matchAll(/<h([1-6])[^>]*>([\\s\\S]*?)<\\/h\\1>/gi)) {\n const text = m[2].replace(/<[^>]+>/g, '').trim()\n if (text) headings.push({ level: Number(m[1]), text: text.slice(0, 200) })\n }\n\n const h1 = headings.find(h => h.level === 1)?.text ?? null\n\n const bodyText = html.replace(/<script[\\s\\S]*?<\\/script>/gi, '')\n .replace(/<style[\\s\\S]*?<\\/style>/gi, '')\n .replace(/<[^>]+>/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim()\n const wordCount = bodyText.split(' ').filter(w => w.length > 2).length\n\n const schemaTypes: string[] = []\n for (const m of html.matchAll(/<script[^>]+type=[\"']application\\/ld\\+json[\"'][^>]*>([\\s\\S]*?)<\\/script>/gi)) {\n try {\n const parsed: unknown = JSON.parse(m[1])\n const collect = (obj: unknown) => {\n if (!obj || typeof obj !== 'object') return\n const o = obj as Record<string, unknown>\n if (typeof o['@type'] === 'string') schemaTypes.push(o['@type'])\n else if (Array.isArray(o['@type'])) schemaTypes.push(...o['@type'].filter((t): t is string => typeof t === 'string'))\n if (Array.isArray(o['@graph'])) o['@graph'].forEach(collect)\n }\n collect(parsed)\n } catch { /**/ }\n }\n\n let internalLinks = 0\n let externalLinks = 0\n for (const m of html.matchAll(/href\\s*=\\s*[\"']([^\"'\\s>]+)/gi)) {\n try {\n const abs = new URL(m[1], url)\n if (abs.origin === origin) internalLinks++\n else externalLinks++\n } catch { /**/ }\n }\n\n return { url, status, via, title, metaDescription, h1, headings, wordCount, schemaTypes, canonicalUrl, internalLinks, externalLinks }\n}\n\nasync function fetchAndParse(url: string, kernelApiKey?: string): Promise<PageData> {\n try {\n const res = await fetch(url, {\n headers: { 'User-Agent': UA, 'Accept': 'text/html,application/xhtml+xml' },\n signal: AbortSignal.timeout(10_000),\n redirect: 'manual',\n })\n if (res.ok) {\n const ct = res.headers.get('content-type') ?? ''\n if (ct.includes('html')) {\n const html = await res.text()\n return parsePageData(url, html, res.status, 'fetch')\n }\n return { url, status: res.status, via: 'fetch', title: null, metaDescription: null, h1: null, headings: [], wordCount: 0, schemaTypes: [], canonicalUrl: null, internalLinks: 0, externalLinks: 0 }\n }\n\n if ((res.status === 403 || res.status === 429) && kernelApiKey) {\n const html = await fetchWithKernel(url)\n return parsePageData(url, html, 200, 'kernel')\n }\n\n return { url, status: res.status, via: 'fetch', title: null, metaDescription: null, h1: null, headings: [], wordCount: 0, schemaTypes: [], canonicalUrl: null, internalLinks: 0, externalLinks: 0 }\n } catch {\n if (kernelApiKey) {\n try {\n const html = await fetchWithKernel(url)\n return parsePageData(url, html, 200, 'kernel')\n } catch { /**/ }\n }\n return { url, status: null, via: 'fetch', title: null, metaDescription: null, h1: null, headings: [], wordCount: 0, schemaTypes: [], canonicalUrl: null, internalLinks: 0, externalLinks: 0 }\n }\n}\n\nasync function runWithConcurrency<T>(items: T[], concurrency: number, fn: (item: T) => Promise<unknown>): Promise<void> {\n let i = 0\n const workers = Array.from({ length: concurrency }, async () => {\n while (i < items.length) {\n const item = items[i++]\n await fn(item)\n }\n })\n await Promise.all(workers)\n}\n\nexport async function extractSite(opts: ExtractOptions): Promise<ExtractResult> {\n const startMs = Date.now()\n const maxPages = Math.min(opts.maxPages ?? 100, 200)\n const concurrency = Math.min(opts.concurrency ?? EXTRACT_CONCURRENCY, 10)\n\n const spider = await spiderSite({\n startUrl: opts.startUrl,\n maxUrls: maxPages,\n concurrency: 12,\n kernelApiKey: opts.kernelApiKey,\n })\n\n const urlsToExtract = spider.urls\n .filter(u => u.status === 200 || u.status === null)\n .slice(0, maxPages)\n .map(u => u.url)\n\n const pages: PageData[] = []\n let kernelRetries = spider.kernelRetries\n\n await runWithConcurrency(urlsToExtract, concurrency, async (url) => {\n const data = await fetchAndParse(url, opts.kernelApiKey)\n if (data.via === 'kernel') kernelRetries++\n pages.push(data)\n })\n\n return {\n startUrl: opts.startUrl,\n pages,\n totalPages: pages.length,\n spider,\n durationMs: Date.now() - startMs,\n truncated: spider.truncated || pages.length >= maxPages,\n kernelRetries,\n }\n}\n","import { Inngest } from 'inngest';\n\nexport const inngest = new Inngest({ id: 'mcp-scraper' });\n","import Anthropic from '@anthropic-ai/sdk';\nimport { z } from 'zod';\n\nexport function extractJson(raw: string): string {\n let text = raw.replace(/<think>[\\s\\S]*?<\\/think>/gi, '').trim()\n text = text.replace(/^```(?:json)?\\s*/i, '').replace(/\\s*```\\s*$/, '').trim()\n if (text.startsWith('{') || text.startsWith('[')) return text\n\n const objStart = text.indexOf('{')\n const arrStart = text.indexOf('[')\n let start = -1\n let open: string, close: string\n\n if (objStart === -1 && arrStart === -1) return text\n if (objStart === -1) { start = arrStart; open = '['; close = ']' }\n else if (arrStart === -1) { start = objStart; open = '{'; close = '}' }\n else if (arrStart < objStart) { start = arrStart; open = '['; close = ']' }\n else { start = objStart; open = '{'; close = '}' }\n\n let depth = 0; let inStr = false; let escape = false\n for (let i = start; i < text.length; i++) {\n const ch = text[i]\n if (escape) { escape = false; continue }\n if (ch === '\\\\' && inStr){ escape = true; continue }\n if (ch === '\"') { inStr = !inStr; continue }\n if (inStr) continue\n if (ch === open) depth++\n else if (ch === close) { if (--depth === 0) return text.slice(start, i + 1) }\n }\n return text.slice(start)\n}\n\nexport interface ILlmClient {\n completeJson(prompt: string): Promise<unknown>;\n complete(prompt: string): Promise<string>;\n}\n\nexport class AnthropicLlmClient implements ILlmClient {\n private client: Anthropic;\n\n constructor() {\n this.client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });\n }\n\n async complete(prompt: string): Promise<string> {\n const response = await this.client.messages.create({\n model: 'claude-opus-4-7',\n max_tokens: 8192,\n messages: [{ role: 'user', content: prompt }],\n });\n const content = response.content[0];\n if (content.type !== 'text') {\n throw new Error('Unexpected non-text response from LLM');\n }\n return content.text;\n }\n\n async completeJson(prompt: string): Promise<unknown> {\n const raw = await this.complete(prompt);\n try {\n return JSON.parse(extractJson(raw));\n } catch {\n const coerced = await this.complete(\n `Convert the following text to a valid JSON object. Output ONLY the JSON, no markdown, no explanation:\\n\\n${raw}`\n );\n return JSON.parse(extractJson(coerced));\n }\n }\n}\n\nexport class DeepInfraLlmClient implements ILlmClient {\n private apiKey: string;\n private model: string;\n\n constructor(apiKey: string, model = 'Qwen/Qwen3.6-35B-A3B') {\n this.apiKey = apiKey;\n this.model = model;\n }\n\n async complete(prompt: string): Promise<string> {\n const resp = await fetch('https://api.deepinfra.com/v1/openai/chat/completions', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}` },\n body: JSON.stringify({ model: this.model, messages: [{ role: 'user', content: prompt }], max_tokens: 8192 }),\n });\n if (!resp.ok) throw new Error(`DeepInfra error ${resp.status}: ${await resp.text()}`);\n const data = await resp.json() as { choices: Array<{ message: { content: string } }> };\n return data.choices[0].message.content;\n }\n\n async completeJson(prompt: string): Promise<unknown> {\n const raw = await this.complete(prompt);\n try {\n return JSON.parse(extractJson(raw));\n } catch {\n const coerced = await this.complete(\n `Convert the following text to a valid JSON object. Output ONLY the JSON, no markdown, no explanation:\\n\\n${raw}`\n );\n return JSON.parse(extractJson(coerced));\n }\n }\n}\n\nexport class OpenRouterLlmClient implements ILlmClient {\n private apiKey: string;\n private model: string;\n\n constructor(apiKey: string, model = 'qwen/qwen3-235b-a22b') {\n this.apiKey = apiKey;\n this.model = model;\n }\n\n async complete(prompt: string): Promise<string> {\n const resp = await fetch('https://openrouter.ai/api/v1/chat/completions', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}` },\n body: JSON.stringify({ model: this.model, messages: [{ role: 'user', content: prompt }], max_tokens: 8192 }),\n });\n if (!resp.ok) throw new Error(`OpenRouter error ${resp.status}: ${await resp.text()}`);\n const data = await resp.json() as { choices: Array<{ message: { content: string } }> };\n return data.choices[0].message.content;\n }\n\n async completeJson(prompt: string): Promise<unknown> {\n const raw = await this.complete(prompt);\n try {\n return JSON.parse(extractJson(raw));\n } catch {\n const coerced = await this.complete(\n `Convert the following text to a valid JSON object. Output ONLY the JSON, no markdown, no explanation:\\n\\n${raw}`\n );\n return JSON.parse(extractJson(coerced));\n }\n }\n}\n\nexport class FallbackLlmClient implements ILlmClient {\n constructor(private primary: ILlmClient, private secondary: ILlmClient) {}\n\n async complete(prompt: string): Promise<string> {\n try {\n return await this.primary.complete(prompt);\n } catch {\n return this.secondary.complete(prompt);\n }\n }\n\n async completeJson(prompt: string): Promise<unknown> {\n try {\n return await this.primary.completeJson(prompt);\n } catch {\n return this.secondary.completeJson(prompt);\n }\n }\n}\n\nexport async function llmParseWithRetry<T>(\n schema: z.ZodSchema<T>,\n promptFn: (attempt: number, error?: string) => string,\n llm: ILlmClient,\n): Promise<T> {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt < 3; attempt++) {\n const prompt = attempt === 0\n ? promptFn(attempt)\n : promptFn(attempt, lastError?.message);\n\n let raw: unknown;\n try {\n raw = await llm.completeJson(prompt);\n } catch (e) {\n lastError = e instanceof Error ? e : new Error(String(e));\n continue;\n }\n\n const result = schema.safeParse(raw);\n if (result.success) return result.data;\n lastError = result.error;\n }\n\n const detail = lastError?.message?.slice(0, 200) ?? 'unknown error'\n throw new Error(`LLM failed to produce valid output after 3 attempts: ${detail}`)\n}\n\nexport async function llmParseWithMarkdownRescue<T>(\n schema: z.ZodSchema<T>,\n promptFn: (attempt: number, error?: string) => string,\n llm: ILlmClient,\n): Promise<T> {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt < 3; attempt++) {\n const prompt = attempt === 0\n ? promptFn(attempt)\n : promptFn(attempt, lastError?.message);\n\n let rawText: string;\n try {\n rawText = await llm.complete(prompt);\n } catch (e) {\n lastError = e instanceof Error ? e : new Error(String(e));\n continue;\n }\n\n const stripped = rawText.replace(/<think>[\\s\\S]*?<\\/think>/gi, '').trim()\n\n let candidate: Record<string, unknown>;\n try {\n candidate = JSON.parse(extractJson(stripped)) as Record<string, unknown>\n } catch {\n candidate = { markdown: stripped }\n }\n\n if (candidate.markdown === undefined || candidate.markdown === null) {\n const jsonStart = stripped.indexOf('{')\n const jsonEnd = stripped.lastIndexOf('}')\n if (jsonStart > 0) {\n const before = stripped.slice(0, jsonStart).trim()\n if (before.length >= 50) candidate.markdown = before\n }\n if ((candidate.markdown === undefined || (candidate.markdown as string).length < 50) && jsonEnd !== -1 && jsonEnd < stripped.length - 1) {\n const after = stripped.slice(jsonEnd + 1).trim()\n if (after.length >= 50) candidate.markdown = after\n }\n if (candidate.markdown === undefined) candidate.markdown = stripped\n }\n\n const result = schema.safeParse(candidate)\n if (result.success) return result.data\n lastError = result.error\n }\n\n const detail = lastError?.message?.slice(0, 200) ?? 'unknown error'\n throw new Error(`LLM failed to produce valid output after 3 attempts: ${detail}`)\n}\n","export interface IHttpClient {\n get(url: string, headers?: Record<string, string>): Promise<{ status: number; body: string }>;\n post(url: string, body: unknown, headers?: Record<string, string>): Promise<{ status: number; body: string }>;\n}\n\nexport class FetchHttpClient implements IHttpClient {\n async get(url: string, headers?: Record<string, string>): Promise<{ status: number; body: string }> {\n const response = await fetch(url, { headers });\n const body = await response.text();\n return { status: response.status, body };\n }\n\n async post(url: string, body: unknown, headers?: Record<string, string>): Promise<{ status: number; body: string }> {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...headers },\n body: JSON.stringify(body),\n });\n const responseBody = await response.text();\n return { status: response.status, body: responseBody };\n }\n}\n","import { z } from \"zod\";\n\nexport const PageTypeSchema = z.enum([\n \"homepage\",\n \"core_service\",\n \"sub_service\",\n \"location\",\n \"service_location\",\n \"industry\",\n \"product\",\n \"pricing\",\n \"faq\",\n \"blog_post\",\n \"guide_resource\",\n \"case_study\",\n \"comparison\",\n \"competitor\",\n \"about\",\n \"contact\",\n \"team\",\n \"careers\",\n \"privacy_policy\",\n \"terms\",\n \"html_sitemap\",\n \"login_portal\",\n \"support_help_center\",\n]);\n\nexport type PageType = z.infer<typeof PageTypeSchema>;\n\nexport const MONEY_PAGE_ELIGIBLE_TYPES: readonly PageType[] = [\n \"core_service\",\n \"sub_service\",\n \"service_location\",\n \"product\",\n \"pricing\",\n \"comparison\",\n \"competitor\",\n \"industry\",\n] as const;\n\nexport const ClassificationConfidenceSchema = z.enum([\n \"high\",\n \"medium\",\n \"low\",\n \"uncertain\",\n]);\n\nexport type ClassificationConfidence = z.infer<\n typeof ClassificationConfidenceSchema\n>;\n\nexport const ARCHITECTURE_SCORE_WEIGHTS = {\n url_inventory_health: 0.20,\n crawlability: 0.20,\n important_page_depth: 0.20,\n page_type_coverage: 0.15,\n topical_cluster_completeness: 0.15,\n ux_nav_clarity: 0.10,\n} as const satisfies Record<string, number>;\n\nexport const ILES_WEIGHTS = {\n target_page_internal_pagerank: 0.30,\n content_inlinks: 0.20,\n anchor_relevance: 0.15,\n link_position_quality: 0.15,\n support_cluster_strength: 0.10,\n low_value_link_waste_reduction: 0.10,\n} as const satisfies Record<string, number>;\n\nexport const PriorityTierSchema = z.enum([\"P0\", \"P1\", \"P2\"]);\n\nexport type PriorityTier = z.infer<typeof PriorityTierSchema>;\n\nexport function computePriorityScore(factors: Record<string, number>): number {\n const {\n business_value,\n competitor_consensus,\n seo_leverage,\n implementation_ease,\n confidence,\n risk,\n } = factors;\n\n const safeRisk = risk === 0 ? 0.1 : risk;\n\n return (\n (business_value *\n competitor_consensus *\n seo_leverage *\n implementation_ease *\n confidence) /\n safeRisk\n );\n}\n\nexport function assignPriorityTier(\n score: number,\n allScores: number[]\n): PriorityTier {\n if (allScores.length === 0) return \"P2\";\n\n const sorted = [...allScores].sort((a, b) => a - b);\n const n = sorted.length;\n\n const p80Index = Math.floor(n * 0.8);\n const p50Index = Math.floor(n * 0.5);\n\n const p80Threshold = sorted[p80Index] ?? sorted[n - 1];\n const p50Threshold = sorted[p50Index] ?? sorted[n - 1];\n\n if (score >= p80Threshold) return \"P0\";\n if (score >= p50Threshold) return \"P1\";\n return \"P2\";\n}\n\nexport const POSITION_WEIGHTS: Readonly<Record<string, number>> = {\n Content: 1.0,\n Breadcrumb: 0.7,\n Navigation: 0.6,\n \"Navigation > Secondary\": 0.5,\n Sidebar: 0.5,\n Footer: 0.25,\n Sitewide: 0.15,\n} as const;\n\nexport const EXCESSIVE_OUTLINKS_THRESHOLD = 100;\n\nexport const VAGUE_ANCHOR_BLOCKLIST: readonly string[] = [\n \"click here\",\n \"read more\",\n \"learn more\",\n \"here\",\n \"this page\",\n] as const;\n\nexport const GuardrailFlagNameSchema = z.enum([\n \"seo_only_link\",\n \"vague_anchor\",\n \"exact_match_repetition\",\n \"excessive_outlinks\",\n \"orphaned_support_page\",\n \"crawl_depth_regression\",\n \"low_content_source\",\n \"circular_authority_trap\",\n]);\n\nexport type GuardrailFlagName = z.infer<typeof GuardrailFlagNameSchema>;\n\nexport function applyGuardrailRules(\n raw: unknown[],\n context: unknown\n): {\n passed: unknown[];\n flagged: Array<{ item: unknown; flags: GuardrailFlagName[] }>;\n} {\n const passed: unknown[] = [];\n const flagged: Array<{ item: unknown; flags: GuardrailFlagName[] }> = [];\n\n for (const item of raw) {\n const flags: GuardrailFlagName[] = [];\n const rec = item as Record<string, unknown>;\n\n const anchor =\n typeof rec[\"anchor_text\"] === \"string\"\n ? rec[\"anchor_text\"].trim().toLowerCase()\n : null;\n\n if (anchor !== null) {\n const isVague = VAGUE_ANCHOR_BLOCKLIST.some(\n (blocked) => blocked.toLowerCase() === anchor\n );\n if (isVague) flags.push(\"vague_anchor\");\n }\n\n const outlinks =\n typeof rec[\"outlink_count\"] === \"number\" ? rec[\"outlink_count\"] : null;\n\n if (outlinks !== null && outlinks >= EXCESSIVE_OUTLINKS_THRESHOLD) {\n flags.push(\"excessive_outlinks\");\n }\n\n if (\n context !== null &&\n context !== undefined &&\n typeof (context as Record<string, unknown>)[\"resolveFlags\"] === \"function\"\n ) {\n const resolveFlags = (context as Record<string, unknown>)[\n \"resolveFlags\"\n ] as (\n item: unknown,\n candidates: GuardrailFlagName[]\n ) => GuardrailFlagName[];\n\n const contextualCandidates: GuardrailFlagName[] = [\n \"seo_only_link\",\n \"exact_match_repetition\",\n \"orphaned_support_page\",\n \"crawl_depth_regression\",\n \"low_content_source\",\n \"circular_authority_trap\",\n ];\n\n const contextFlags = resolveFlags(item, contextualCandidates);\n flags.push(...contextFlags);\n }\n\n if (flags.length === 0) {\n passed.push(item);\n } else {\n flagged.push({ item, flags });\n }\n }\n\n return { passed, flagged };\n}\n\nexport const RequiredReportSectionSchema = z.enum([\n \"executive_summary\",\n \"url_inventory\",\n \"competitor_page_gap_matrix\",\n \"internal_link_graph\",\n \"architecture_score\",\n \"reverse_silo_plan\",\n \"implementation_backlog\",\n \"guardrail_flag_summary\",\n \"graph_visualization_views\",\n]);\n\nexport type RequiredReportSection = z.infer<typeof RequiredReportSectionSchema>;\n\nexport const LINK_RECOMMENDATION_REQUIRED_FIELDS: readonly string[] = [\n \"target_url\",\n \"source_url\",\n \"anchor_text\",\n \"placement\",\n \"reason\",\n] as const;\n\nexport const BACKLOG_ITEM_REQUIRED_FIELDS: readonly string[] = [\n \"priority_tier\",\n \"priority_score\",\n \"task\",\n \"owner\",\n \"input_needed\",\n \"output\",\n \"confidence\",\n \"confidence_basis\",\n \"business_value\",\n \"competitor_consensus\",\n \"seo_leverage\",\n \"implementation_ease\",\n \"risk\",\n \"formula\",\n] as const;\n\nexport const LocationArchitecturePatternSchema = z.enum([\n \"pattern_a_location_hub_only\",\n \"pattern_b_service_city_pages\",\n \"pattern_c_city_hub_nested_services\",\n \"pattern_d_state_first_hierarchy\",\n \"pattern_e_near_me_landing_strategy\",\n \"pattern_none_generic_service_pages\",\n]);\n\nexport type LocationArchitecturePattern = z.infer<\n typeof LocationArchitecturePatternSchema\n>;\n\nexport const NEAR_ME_PATTERNS: readonly string[] = [\n \"-near-me\",\n \"near-me-\",\n \"/near-me\",\n \"nearme\",\n] as const;\n\nexport const AMBIGUOUS_CITIES: readonly string[] = [\n \"mobile\",\n \"orange\",\n \"commerce\",\n \"industry\",\n \"normal\",\n \"reading\",\n \"frisco\",\n \"enterprise\",\n \"concord\",\n \"spring\",\n \"page\",\n \"cary\",\n \"dublin\",\n \"paris\",\n \"oxford\",\n \"clinton\",\n \"franklin\",\n \"madison\",\n \"portland\",\n \"aurora\",\n \"florence\",\n \"lincoln\",\n \"jackson\",\n \"monroe\",\n \"jefferson\",\n \"washington\",\n] as const;\n\nexport const AMBIGUOUS_STATE_ABBRS: readonly string[] = [\n \"me\",\n \"in\",\n \"or\",\n \"pa\",\n \"la\",\n \"ok\",\n] as const;\n\nexport const CONFIDENCE_THRESHOLDS_LOCATION = {\n very_high: 80,\n high: 60,\n medium: 40,\n} as const;\n","import { z } from 'zod';\nimport {\n PageTypeSchema,\n ClassificationConfidenceSchema,\n GuardrailFlagNameSchema,\n PriorityTierSchema,\n LocationArchitecturePatternSchema,\n} from '../../lib/site-architecture-auditor/rules.js';\n\nexport {\n PageTypeSchema,\n ClassificationConfidenceSchema,\n GuardrailFlagNameSchema,\n PriorityTierSchema,\n LocationArchitecturePatternSchema,\n};\n\nexport const SiteAuditJobStatusSchema = z.enum([\n 'pending',\n 'running',\n 'complete',\n 'failed',\n]);\nexport type SiteAuditJobStatus = z.infer<typeof SiteAuditJobStatusSchema>;\n\nexport const SiteAuditPhaseSchema = z.enum([\n 'phase1-ingest',\n 'phase2-build-graph',\n 'phase3-classify',\n 'phase4-compare',\n 'phase5-synthesize',\n]);\nexport type SiteAuditPhase = z.infer<typeof SiteAuditPhaseSchema>;\n\nexport const SiteAuditJobStateSchema = z.object({\n jobId: z.string(),\n userId: z.number(),\n status: SiteAuditJobStatusSchema,\n currentPhase: SiteAuditPhaseSchema.nullable(),\n clientDomain: z.string(),\n sessionPath: z.string(),\n});\nexport type SiteAuditJobState = z.infer<typeof SiteAuditJobStateSchema>;\n\nexport const SiteAuditPhaseLogEntrySchema = z.object({\n jobId: z.string(),\n phase: SiteAuditPhaseSchema,\n completedAt: z.string(),\n outputSummary: z.unknown(),\n});\nexport type SiteAuditPhaseLogEntry = z.infer<typeof SiteAuditPhaseLogEntrySchema>;\n\nexport const SiteAuditStartRequestSchema = z.object({\n clientDomain: z.string(),\n sessionPath: z.string(),\n sfInternalPath: z.string(),\n sfInlinksPath: z.string(),\n sfOutlinksPath: z.string(),\n sitemapPath: z.string(),\n competitorDomainsCsvPath: z.string(),\n visualSitemapsPath: z.string().optional(),\n gscPath: z.string().optional(),\n ga4Path: z.string().optional(),\n ahrefsPath: z.string().optional(),\n businessContext: z.string().optional(),\n priorAuditMemoryEnabled: z.boolean().default(false),\n});\nexport type SiteAuditStartRequest = z.infer<typeof SiteAuditStartRequestSchema>;\n\nexport const SiteAuditIngestRequestSchema = z.object({\n jobId: z.string(),\n});\nexport type SiteAuditIngestRequest = z.infer<typeof SiteAuditIngestRequestSchema>;\n\nexport const SiteAuditBuildGraphRequestSchema = z.object({\n jobId: z.string(),\n});\nexport type SiteAuditBuildGraphRequest = z.infer<typeof SiteAuditBuildGraphRequestSchema>;\n\nexport const SiteAuditClassifyRequestSchema = z.object({\n jobId: z.string(),\n});\nexport type SiteAuditClassifyRequest = z.infer<typeof SiteAuditClassifyRequestSchema>;\n\nexport const SiteAuditCompareRequestSchema = z.object({\n jobId: z.string(),\n});\nexport type SiteAuditCompareRequest = z.infer<typeof SiteAuditCompareRequestSchema>;\n\nexport const SiteAuditScoreRequestSchema = z.object({\n jobId: z.string(),\n});\nexport type SiteAuditScoreRequest = z.infer<typeof SiteAuditScoreRequestSchema>;\n\nexport const SiteAuditReportRequestSchema = z.object({\n jobId: z.string(),\n});\nexport type SiteAuditReportRequest = z.infer<typeof SiteAuditReportRequestSchema>;\n\nexport const SiteAuditIngestPayloadSchema = z.object({\n jobId: z.string(),\n request: SiteAuditStartRequestSchema,\n});\nexport type SiteAuditIngestPayload = z.infer<typeof SiteAuditIngestPayloadSchema>;\n\nexport const SiteAuditBuildGraphPayloadSchema = z.object({\n jobId: z.string(),\n});\nexport type SiteAuditBuildGraphPayload = z.infer<typeof SiteAuditBuildGraphPayloadSchema>;\n\nexport const SiteAuditClassifyPayloadSchema = z.object({\n jobId: z.string(),\n});\nexport type SiteAuditClassifyPayload = z.infer<typeof SiteAuditClassifyPayloadSchema>;\n\nexport const SiteAuditComparePayloadSchema = z.object({\n jobId: z.string(),\n});\nexport type SiteAuditComparePayload = z.infer<typeof SiteAuditComparePayloadSchema>;\n\nexport const SiteAuditSynthesizePayloadSchema = z.object({\n jobId: z.string(),\n scoringOnly: z.boolean().default(false),\n reportOnly: z.boolean().default(false),\n});\nexport type SiteAuditSynthesizePayload = z.infer<typeof SiteAuditSynthesizePayloadSchema>;\n\nexport const ValidatedFileManifestSchema = z.object({\n clientDomain: z.string(),\n sites: z.array(\n z.object({\n site_id: z.string(),\n role: z.enum(['client', 'competitor']),\n domain: z.string(),\n sf_internal_path: z.string().nullable(),\n sf_inlinks_path: z.string().nullable(),\n sf_outlinks_path: z.string().nullable(),\n sitemap_path: z.string().nullable(),\n has_screaming_frog: z.boolean(),\n has_sitemap: z.boolean(),\n schema_version: z.string(),\n url_count_sitemap: z.number(),\n requires_firecrawl_enrichment: z.boolean(),\n })\n ),\n blocking_errors: z.array(z.string()),\n warnings: z.array(z.string()),\n python_deps_verified: z.boolean(),\n});\nexport type ValidatedFileManifest = z.infer<typeof ValidatedFileManifestSchema>;\n\nexport const EnrichCompetitorOutputSchema = z.object({\n domain: z.string(),\n pages: z.array(\n z.object({\n url: z.string(),\n title: z.string().optional(),\n depth: z.number().optional(),\n page_type: z.string().optional(),\n })\n ),\n});\nexport type EnrichCompetitorOutput = z.infer<typeof EnrichCompetitorOutputSchema>;\n\nexport const MasterUrlInventoryItemSchema = z.object({\n site_id: z.string(),\n url: z.string(),\n normalized_url: z.string(),\n status_code: z.number(),\n indexability: z.string(),\n canonical_url: z.string().nullable(),\n title: z.string().optional(),\n h1: z.string().optional(),\n meta_description: z.string().optional(),\n crawl_depth: z.number().optional(),\n sitemap_present: z.boolean(),\n visual_sitemap_present: z.boolean(),\n page_type: PageTypeSchema.nullable(),\n topic_cluster: z.string().nullable(),\n orphan_status: z.boolean(),\n internal_pagerank: z.number().optional(),\n screaming_frog_link_score: z.number().optional(),\n inlink_count: z.number().default(0),\n content_inlink_count: z.number().default(0),\n});\nexport type MasterUrlInventoryItem = z.infer<typeof MasterUrlInventoryItemSchema>;\n\nexport const DirectedLinkGraphEdgeSchema = z.object({\n site_id: z.string(),\n source_url: z.string(),\n target_url: z.string(),\n anchor_text: z.string(),\n follow: z.boolean(),\n link_type: z.string(),\n link_position: z.string(),\n weight: z.number().default(1.0),\n is_sitewide: z.boolean().default(false),\n is_duplicate_edge: z.boolean().default(false),\n});\nexport type DirectedLinkGraphEdge = z.infer<typeof DirectedLinkGraphEdgeSchema>;\n\nexport const UrlMetricRowSchema = z.object({\n url: z.string(),\n site_id: z.string(),\n internal_pagerank: z.number(),\n crawl_depth: z.number(),\n cluster_cohesion: z.number().optional(),\n inlink_count: z.number(),\n content_inlink_count: z.number(),\n});\nexport type UrlMetricRow = z.infer<typeof UrlMetricRowSchema>;\n\nexport const PageTypeClassificationRowSchema = z.object({\n url: z.string(),\n page_type: PageTypeSchema,\n confidence: ClassificationConfidenceSchema,\n _classification_label: z.enum([\n '[COMPUTED:python/location-classifier]',\n '[INTERPRETED:claude]',\n ]),\n topic_cluster: z.string().nullable(),\n location_signals: z.array(z.string()).optional(),\n});\nexport type PageTypeClassificationRow = z.infer<typeof PageTypeClassificationRowSchema>;\n\nexport const TopicClusterAssignmentSchema = z.object({\n url: z.string(),\n topic_cluster: z.string(),\n money_page_candidate: z.boolean(),\n});\nexport type TopicClusterAssignment = z.infer<typeof TopicClusterAssignmentSchema>;\n\nexport const MoneyPageItemSchema = z.object({\n url: z.string(),\n site_id: z.string(),\n page_type: PageTypeSchema,\n topic_cluster: z.string(),\n business_value: z.number().min(0).max(5),\n current_inlink_count: z.number(),\n current_internal_pagerank: z.number(),\n});\nexport type MoneyPageItem = z.infer<typeof MoneyPageItemSchema>;\n\nexport const LinkRecommendationItemSchema = z.object({\n target_url: z.string(),\n target_page_type: PageTypeSchema,\n source_url: z.string(),\n anchor_text: z.string(),\n placement: z.string(),\n reason: z.string(),\n estimated_pagerank_lift: z.number().optional(),\n});\nexport type LinkRecommendationItem = z.infer<typeof LinkRecommendationItemSchema>;\n\nexport const NewPageCreationItemSchema = z.object({\n url_slug: z.string(),\n page_type: PageTypeSchema,\n priority: PriorityTierSchema,\n topic_cluster: z.string(),\n links_to: z.array(z.string()),\n});\nexport type NewPageCreationItem = z.infer<typeof NewPageCreationItemSchema>;\n\nexport const GuardrailFlagItemSchema = z.object({\n item: z.unknown(),\n flags: z.array(GuardrailFlagNameSchema),\n});\nexport type GuardrailFlagItem = z.infer<typeof GuardrailFlagItemSchema>;\n\nexport const ArchitectureScoreSchema = z.object({\n total: z.number().min(0).max(100),\n components: z.record(z.string(), z.number()),\n});\nexport type ArchitectureScore = z.infer<typeof ArchitectureScoreSchema>;\n\nexport const IlesScoreSchema = z.object({\n total: z.number().min(0).max(100),\n components: z.record(z.string(), z.number()),\n});\nexport type IlesScore = z.infer<typeof IlesScoreSchema>;\n\nexport const RankedBacklogItemSchema = z.object({\n priority: PriorityTierSchema,\n task: z.string(),\n owner: z.string().optional(),\n confidence: z.string(),\n priority_score: z.number(),\n});\nexport type RankedBacklogItem = z.infer<typeof RankedBacklogItemSchema>;\n\nexport const SiteAuditResultSchema = z.object({\n jobId: z.string(),\n clientDomain: z.string(),\n architectureScore: ArchitectureScoreSchema,\n ilesScore: IlesScoreSchema,\n rankedBacklog: z.array(RankedBacklogItemSchema),\n linkRecommendations: z.array(LinkRecommendationItemSchema),\n newPagesRecommended: z.array(NewPageCreationItemSchema),\n guardrailFlags: z.array(GuardrailFlagItemSchema),\n reportMarkdown: z.string().optional(),\n});\nexport type SiteAuditResult = z.infer<typeof SiteAuditResultSchema>;\n\nexport const PythonGraphInputSchema = z.object({\n directedLinkGraphPath: z.string(),\n masterUrlInventoryPath: z.string(),\n outputPath: z.string(),\n});\nexport type PythonGraphInput = z.infer<typeof PythonGraphInputSchema>;\n\nexport const PythonGraphOutputSchema = z.object({\n pagerank: z.record(z.string(), z.number()),\n crawlDepth: z.record(z.string(), z.number()),\n clusterCohesion: z.record(z.string(), z.number()),\n success: z.boolean(),\n error: z.string().optional(),\n});\nexport type PythonGraphOutput = z.infer<typeof PythonGraphOutputSchema>;\n\nexport const LocationClassifierInputSchema = z.object({\n urls: z.array(z.string()),\n usZipsCsvPath: z.string(),\n});\nexport type LocationClassifierInput = z.infer<typeof LocationClassifierInputSchema>;\n\nexport const LocationClassifierOutputSchema = z.object({\n classified: z.array(\n z.object({\n url: z.string(),\n pageType: z.string(),\n confidence: z.number(),\n locationSignals: z.array(z.string()),\n })\n ),\n unclassified: z.array(z.string()),\n success: z.boolean(),\n errorMessage: z.string().nullable(),\n});\nexport type LocationClassifierOutput = z.infer<typeof LocationClassifierOutputSchema>;\n\nexport const SiteAuditAuthAndDeductRequestSchema = z.object({\n operation: z.literal('site-audit'),\n userId: z.number(),\n email: z.string().optional(),\n});\nexport type SiteAuditAuthAndDeductRequest = z.infer<typeof SiteAuditAuthAndDeductRequestSchema>;\n","import { z } from 'zod';\nimport { ValidatedFileManifestSchema } from '../schemas.js';\n\nexport { ValidatedFileManifestSchema };\n\nexport const IngestValidateInputSchema = z.object({\n clientDomain: z.string(),\n sfInternalPath: z.string(),\n sfInlinksPath: z.string(),\n sfOutlinksPath: z.string(),\n sitemapPath: z.string(),\n competitorDomainsCsvPath: z.string(),\n visualSitemapsPath: z.string().optional(),\n gscPath: z.string().optional(),\n ga4Path: z.string().optional(),\n ahrefsPath: z.string().optional(),\n businessContext: z.string().optional(),\n priorAuditMemoryEnabled: z.boolean().default(false),\n});\n\nexport type IngestValidateInput = z.infer<typeof IngestValidateInputSchema>;\n\nconst H1 = '#';\nconst H2 = '##';\nconst H3 = '###';\n\nexport function buildIngestValidatePrompt(input: IngestValidateInput): string {\n const sessionPath = `<session-path-from-job>`;\n const outputPath = `${sessionPath}/phase1`;\n const memoryPath = `${sessionPath}/memory/${input.clientDomain}.json`;\n\n const lines: string[] = [\n `${H1} Phase 1: File Ingestion and Validation`,\n ``,\n `You are the **ingest-validate agent** for the **Site Architecture Auditor** skill ecosystem.`,\n ``,\n `This is a sequential phase. You run once per audit session and are the hard gate for all downstream phases.`,\n ``,\n `Output path: ${outputPath}`,\n `Session: ${sessionPath}`,\n `Client domain: ${input.clientDomain}`,\n ``,\n `Input files:`,\n `- SF Internal CSV: ${input.sfInternalPath}`,\n `- SF All Inlinks CSV: ${input.sfInlinksPath}`,\n `- SF All Outlinks CSV: ${input.sfOutlinksPath}`,\n `- XML Sitemap: ${input.sitemapPath}`,\n `- Competitor domains CSV: ${input.competitorDomainsCsvPath}`,\n `- VisualSitemaps (optional): ${input.visualSitemapsPath ?? 'null'}`,\n `- GSC export (optional): ${input.gscPath ?? 'null'}`,\n `- GA4 export (optional): ${input.ga4Path ?? 'null'}`,\n `- Ahrefs export (optional): ${input.ahrefsPath ?? 'null'}`,\n `- Business context (optional): ${input.businessContext ?? 'null'}`,\n `- Prior audit memory enabled: ${input.priorAuditMemoryEnabled}`,\n ``,\n `---`,\n ``,\n `${H2} Reference`,\n ``,\n `No external reference files required for this phase.`,\n ``,\n `---`,\n ``,\n `${H2} Task`,\n ``,\n `Validate all user-uploaded files for this audit session, detect the Screaming Frog schema version per file, verify required Python dependencies are installed, query memory for prior audit records for this client domain, and emit three outputs: \\`validated_file_manifest.json\\`, \\`schema_version_map.json\\`, and \\`ingestion_error_log.jsonl\\`. Good output means every required column is confirmed present for each file type, every site has a schema version recorded, the manifest accurately reflects which optional sources are available, and any blocking errors halt the process immediately with a clear remediation message. Missing this phase produces incorrect cross-source comparisons, bad URL normalization, and silent graph construction failures downstream.`,\n ``,\n `---`,\n ``,\n `${H2} Step 1 — Verify Python Environment`,\n ``,\n `Run the following Python check using the Bash tool:`,\n ``,\n `\\`\\`\\`bash`,\n `python3 -c \"import networkx, pandas, lxml; print('deps:ok')\"`,\n `\\`\\`\\``,\n ``,\n `If the command fails or returns an import error, write one entry to \\`ingestion_error_log.jsonl\\`:`,\n ``,\n `\\`\\`\\`json`,\n `{\"error_severity\":\"blocking\",\"error_code\":\"dep-001\",\"message\":\"Required Python package missing: {package}. Install with: pip install networkx pandas lxml\",\"file\":null,\"remediation\":\"Run: pip install networkx pandas lxml\"}`,\n `\\`\\`\\``,\n ``,\n `Also verify uszips.csv is accessible (required for Phase 3 location classification):`,\n ``,\n `\\`\\`\\`bash`,\n `python3 -c \"`,\n `import csv, os`,\n `path = '/Users/vilovieta/Downloads/sales-magician-api-leads-magician-01c6cff78e31/tools/analytics/data/uszips.csv'`,\n `if not os.path.exists(path):`,\n ` print('uszips:missing')`,\n `else:`,\n ` with open(path) as f:`,\n ` cols = next(csv.reader(f))`,\n ` expected = ['state_fips','state','state_abbr','zipcode','county','city']`,\n ` print('uszips:ok' if cols == expected else f'uszips:schema-mismatch:{cols}')`,\n `\"`,\n `\\`\\`\\``,\n ``,\n `If \\`uszips:missing\\`, write a **warning** (non-blocking) to \\`ingestion_error_log.jsonl\\`:`,\n ``,\n `\\`\\`\\`json`,\n `{\"error_severity\":\"warning\",\"error_code\":\"dep-002\",\"message\":\"uszips.csv not found at expected path. Location classifier will be disabled — all URL classification will use Claude. Phase 3 LLM costs will be higher.\",\"file\":\"/Users/vilovieta/Downloads/sales-magician-api-leads-magician-01c6cff78e31/tools/analytics/data/uszips.csv\",\"remediation\":\"Verify the sales-magician codebase is present at the expected path. See reference/05-location-classifier.md.\"}`,\n `\\`\\`\\``,\n ``,\n `If \\`uszips:schema-mismatch\\`, write the same warning with the mismatch detail in the message. The audit continues without the location classifier — all URLs fall through to Claude classification.`,\n ``,\n `Proceed only if the check passes.`,\n ``,\n `---`,\n ``,\n `${H2} Step 2 — Validate Screaming Frog Internal CSV`,\n ``,\n `Read the file at ${input.sfInternalPath}.`,\n ``,\n `**Required columns (must all be present):**`,\n `- \\`Address\\``,\n `- \\`Status Code\\``,\n `- \\`Indexability\\``,\n ``,\n `**Schema version detection — inspect the header row:**`,\n `- If column \\`Canonicalised URL\\` is present → schema version \\`v3.17+\\``,\n `- If column \\`Link Score\\` is present → schema version \\`v3.15–3.16\\``,\n `- If neither advanced column is present → schema version \\`v3.x-legacy\\``,\n ``,\n `Record the detected version. If any required column is absent, add a blocking error to the error log:`,\n ``,\n `\\`\\`\\`json`,\n `{\"error_severity\":\"blocking\",\"error_code\":\"sf-internal-001\",\"message\":\"SF Internal CSV missing required column: {column}\",\"file\":\"${input.sfInternalPath}\",\"remediation\":\"Re-export from Screaming Frog: Internal tab → Export after crawl analysis completes\"}`,\n `\\`\\`\\``,\n ``,\n `---`,\n ``,\n `${H2} Step 3 — Validate Screaming Frog Inlinks CSV`,\n ``,\n `Read the file at ${input.sfInlinksPath}.`,\n ``,\n `**Required columns (must all be present):**`,\n `- \\`Source\\``,\n `- \\`Destination\\``,\n `- \\`Anchor\\``,\n `- \\`Follow\\``,\n `- \\`Type\\``,\n `- \\`Position\\``,\n ``,\n `If any are missing, add a blocking error using code \\`sf-inlinks-001\\`. If the \\`Position\\` column is present but contains only \\`N/A\\` values throughout, add a warning (non-blocking):`,\n ``,\n `\\`\\`\\`json`,\n `{\"error_severity\":\"warning\",\"error_code\":\"sf-inlinks-002\",\"message\":\"Position column present but all values are N/A — edge weight assignment will default to Content weight for all links\",\"file\":\"${input.sfInlinksPath}\",\"remediation\":\"Re-crawl with Screaming Frog Crawl Analysis enabled to populate link positions\"}`,\n `\\`\\`\\``,\n ``,\n `---`,\n ``,\n `${H2} Step 4 — Validate Screaming Frog Outlinks CSV`,\n ``,\n `Read the file at ${input.sfOutlinksPath}.`,\n ``,\n `**Required columns (must all be present):**`,\n `- \\`Source\\``,\n `- \\`Destination\\``,\n `- \\`Anchor\\``,\n `- \\`Follow\\``,\n `- \\`Type\\``,\n `- \\`Position\\``,\n ``,\n `If any are missing, add a blocking error using code \\`sf-outlinks-001\\`.`,\n ``,\n `---`,\n ``,\n `${H2} Step 5 — Validate XML Sitemap`,\n ``,\n `Read the file at ${input.sitemapPath}.`,\n ``,\n `Parse the XML. Accept either of two root element types:`,\n `- \\`<urlset>\\` — standard sitemap`,\n `- \\`<sitemapindex>\\` — sitemap index referencing child sitemaps`,\n ``,\n `If the file is not valid XML, add a blocking error:`,\n ``,\n `\\`\\`\\`json`,\n `{\"error_severity\":\"blocking\",\"error_code\":\"sitemap-001\",\"message\":\"XML sitemap is not parseable XML\",\"file\":\"${input.sitemapPath}\",\"remediation\":\"Validate XML at https://www.xmlvalidation.com/ and fix malformed tags\"}`,\n `\\`\\`\\``,\n ``,\n `If the root element is neither \\`<urlset>\\` nor \\`<sitemapindex>\\`, add a blocking error with code \\`sitemap-002\\`.`,\n ``,\n `If valid, record: root element type, URL count (count of \\`<loc>\\` elements), and whether any \\`<loc>\\` values return HTTP redirects or 4xx (do not fetch at this stage — flag for Phase 2 detection).`,\n ``,\n `---`,\n ``,\n `${H2} Step 6 — Validate Optional Files (if paths provided)`,\n ``,\n `For each optional file path that is not empty or null:`,\n ``,\n `**VisualSitemaps (${input.visualSitemapsPath ?? 'not provided'}):**`,\n `- Accept \\`.csv\\` or \\`.json\\` extension`,\n `- If CSV: confirm \\`URL\\` column present`,\n `- If JSON: confirm top-level array with \\`url\\` field in first element`,\n `- On failure: add warning (non-blocking), code \\`vs-001\\``,\n ``,\n `**GSC export (${input.gscPath ?? 'not provided'}):**`,\n `- Confirm \\`Page\\` or \\`URL\\` column present plus at least one metric column (\\`Clicks\\`, \\`Impressions\\`, \\`CTR\\`, \\`Position\\`)`,\n `- On failure: add warning (non-blocking), code \\`gsc-001\\``,\n ``,\n `**GA4 export (${input.ga4Path ?? 'not provided'}):**`,\n `- Confirm \\`Page path\\` or \\`Landing page\\` column present`,\n `- On failure: add warning (non-blocking), code \\`ga4-001\\``,\n ``,\n `**Ahrefs export (${input.ahrefsPath ?? 'not provided'}):**`,\n `- Confirm \\`URL\\` column present`,\n `- On failure: add warning (non-blocking), code \\`ahrefs-001\\``,\n ``,\n `---`,\n ``,\n `${H2} Step 7 — Parse Competitor Domains`,\n ``,\n `Read ${input.competitorDomainsCsvPath}. Extract all competitor domains (one per row or comma-separated in a single field — detect which format is used).`,\n ``,\n `For each competitor domain:`,\n `- Check whether an SF Internal CSV, Inlinks CSV, and Outlinks CSV have been uploaded for that domain in \\`${sessionPath}\\``,\n `- Set \\`has_screaming_frog: true\\` if all three SF files are present, \\`false\\` otherwise`,\n `- Set \\`requires_firecrawl_enrichment: true\\` if \\`has_screaming_frog\\` is \\`false\\``,\n `- Check for companion sitemap file`,\n `- Set \\`has_sitemap: true\\` if an XML sitemap for this domain is present`,\n ``,\n `Competitor entries with no SF exports and no sitemap will be flagged for Firecrawl enrichment in the manifest.`,\n ``,\n `---`,\n ``,\n `${H2} Step 8 — Query Prior Audit Memory`,\n ``,\n `If \\`${input.priorAuditMemoryEnabled}\\` is \\`true\\`, read the memory file for this domain at \\`${memoryPath}\\`.`,\n ``,\n `Extract:`,\n `- \\`last_audit_date\\` (ISO date string)`,\n `- \\`architecture_score\\` (float)`,\n `- \\`link_equity_score\\` (float)`,\n `- \\`top_findings\\` (array, up to 5 strings)`,\n ``,\n `If no prior record is found, set \\`prior_audit_delta: null\\` in the manifest.`,\n ``,\n `If a prior record is found, set \\`prior_audit_delta\\` with those fields so Phase 5 can compute improvement deltas.`,\n ``,\n `---`,\n ``,\n `${H2} Step 9 — Hard Gate Check`,\n ``,\n `Collect all entries in the error log where \\`error_severity\\` is \\`\"blocking\"\\`.`,\n ``,\n `If the blocking errors array is non-empty:`,\n ``,\n `\\`\\`\\``,\n `GATE BLOCKED: The following blocking errors prevent Phase 2 from starting:`,\n ` - [error_code]: [message]`,\n ` - [error_code]: [message]`,\n ``,\n `Remediation steps:`,\n ` 1. [remediation for first error]`,\n ` 2. [remediation for second error]`,\n ``,\n `Re-run /site-architecture-auditor ingest after correcting these files.`,\n `\\`\\`\\``,\n ``,\n `Print this message and stop. Do not write a \\`validated_file_manifest.json\\` with \\`status: complete\\`. Write \\`ingestion_error_log.jsonl\\` and \\`schema_version_map.json\\` only.`,\n ``,\n `---`,\n ``,\n `${H2} Step 10 — Write Outputs`,\n ``,\n `${H3} \\`${outputPath}/validated_file_manifest.json\\``,\n ``,\n `Write a single JSON object (not JSONL) with this structure:`,\n ``,\n `\\`\\`\\`json`,\n `{`,\n ` \"client_domain\": \"${input.clientDomain}\",`,\n ` \"session_path\": \"${sessionPath}\",`,\n ` \"audit_timestamp\": \"<ISO timestamp>\",`,\n ` \"prior_audit_delta\": null,`,\n ` \"sites\": [`,\n ` {`,\n ` \"site_id\": \"client\",`,\n ` \"role\": \"client\",`,\n ` \"domain\": \"${input.clientDomain}\",`,\n ` \"sf_internal_path\": \"${input.sfInternalPath}\",`,\n ` \"sf_inlinks_path\": \"${input.sfInlinksPath}\",`,\n ` \"sf_outlinks_path\": \"${input.sfOutlinksPath}\",`,\n ` \"sitemap_path\": \"${input.sitemapPath}\",`,\n ` \"visual_sitemap_path\": null,`,\n ` \"gsc_path\": null,`,\n ` \"ga4_path\": null,`,\n ` \"ahrefs_path\": null,`,\n ` \"has_screaming_frog\": true,`,\n ` \"has_sitemap\": true,`,\n ` \"has_visual_sitemap\": false,`,\n ` \"has_gsc\": false,`,\n ` \"schema_version\": \"<detected version>\",`,\n ` \"url_count_sitemap\": 0,`,\n ` \"requires_firecrawl_enrichment\": false`,\n ` }`,\n ` ],`,\n ` \"blocking_errors\": [],`,\n ` \"warnings\": [],`,\n ` \"python_deps_verified\": true`,\n `}`,\n `\\`\\`\\``,\n ``,\n `Add one entry per competitor domain to the \\`sites\\` array using the data collected in Step 7.`,\n ``,\n `Fill optional path fields with the validated path if the file was provided and passed validation, or \\`null\\` if not provided or failed validation.`,\n ``,\n `${H3} \\`${outputPath}/schema_version_map.json\\``,\n ``,\n `Write a JSON object mapping each site domain to its detected SF schema version:`,\n ``,\n `\\`\\`\\`json`,\n `{`,\n ` \"${input.clientDomain}\": \"v3.17+\",`,\n ` \"competitor1.com\": \"v3.15-3.16\"`,\n `}`,\n `\\`\\`\\``,\n ``,\n `Competitors with \\`has_screaming_frog: false\\` map to \\`\"none\"\\`.`,\n ``,\n `${H3} \\`${outputPath}/ingestion_error_log.jsonl\\``,\n ``,\n `Write one JSON object per line for every error and warning collected across all steps. End with a summary record:`,\n ``,\n `\\`\\`\\`json`,\n `{\"_summary\":true,\"entry_type\":\"ingestion_error\",\"total_count\":<N>,\"blocking_count\":<B>,\"warning_count\":<W>,\"status\":\"complete\"}`,\n `\\`\\`\\``,\n ``,\n `Where \\`N\\` is total error+warning count (not including the summary line), \\`B\\` is count of blocking errors, \\`W\\` is count of warnings.`,\n ``,\n `---`,\n ``,\n `Status: COMPLETE`,\n ];\n\n return lines.join('\\n');\n}\n","import { z } from 'zod';\n\nexport const EnrichCompetitorInputSchema = z.object({\n domain: z.string(),\n sessionPath: z.string(),\n});\n\nexport type EnrichCompetitorInput = z.infer<typeof EnrichCompetitorInputSchema>;\n\nconst H1 = '#';\nconst H2 = '##';\n\nexport function buildEnrichCompetitorPrompt(input: EnrichCompetitorInput): string {\n const outputPath = `${input.sessionPath}/phase1`;\n const validatedFileManifestPath = `${input.sessionPath}/phase1/validated_file_manifest.json`;\n const competitorIndex = `<competitor-index>`;\n\n const lines: string[] = [\n `${H1} Phase 1 (Conditional): Competitor Firecrawl Enrichment`,\n ``,\n `You are the **enrich-competitor agent** for the **Site Architecture Auditor** skill ecosystem.`,\n ``,\n `This template runs **only when** \\`validated_file_manifest.json\\` marks a competitor with \\`requires_firecrawl_enrichment: true\\`. One invocation per affected competitor. You build a partial page inventory using Firecrawl in place of a Screaming Frog export. All output is annotated as partial quality — downstream agents must treat this data as incomplete relative to a full SF crawl.`,\n ``,\n `Output path: ${outputPath}`,\n `Session: ${input.sessionPath}`,\n `Competitor domain: ${input.domain}`,\n `Competitor index: ${competitorIndex}`,\n `Validated file manifest: ${validatedFileManifestPath}`,\n ``,\n `---`,\n ``,\n `${H2} Reference`,\n ``,\n `Read before acting:`,\n `- \\`~/.claude/skills/site-architecture-auditor/reference/01-page-type-taxonomy.md\\``,\n ``,\n `Use the 22-type taxonomy for preliminary page type hints only. Do not classify with high confidence from Firecrawl data — all classifications from this output carry \\`enrichment_quality: \"partial\"\\`.`,\n ``,\n `---`,\n ``,\n `${H2} Task`,\n ``,\n `Use Firecrawl to crawl the competitor site and extract all discoverable URLs, page titles, H1 headings, and meta descriptions, building a partial URL inventory that Phase 3 can use for page type classification. This enrichment substitutes for a Screaming Frog export where SF data was not provided — it will not produce link graph edges, status codes, or crawl depth data, so all downstream agents that consume this output must treat it as incomplete. Good output covers the homepage, all top-level navigation destinations, and as many service/product/content pages as possible within the 20-page limit. Poor output would silently omit major page categories or fail to annotate the data quality gap.`,\n ``,\n `**Page budget cap: 20 pages maximum.** Do not exceed 20 total pages scraped across all steps.`,\n ``,\n `---`,\n ``,\n `${H2} Step 1 — Read and Confirm Manifest Entry`,\n ``,\n `Read \\`${validatedFileManifestPath}\\`.`,\n ``,\n `Locate the entry in the \\`sites\\` array where \\`domain\\` matches \\`${input.domain}\\`.`,\n ``,\n `Confirm:`,\n `- \\`requires_firecrawl_enrichment\\` is \\`true\\``,\n `- \\`has_screaming_frog\\` is \\`false\\``,\n ``,\n `If the entry shows \\`has_screaming_frog: true\\`, stop immediately and print:`,\n ``,\n `\\`\\`\\``,\n `ENRICHMENT SKIPPED: ${input.domain} has Screaming Frog data. No Firecrawl enrichment needed.`,\n `\\`\\`\\``,\n ``,\n `Do not write any output file.`,\n ``,\n `---`,\n ``,\n `${H2} Step 2 — Scrape Homepage`,\n ``,\n `Use the Bash tool to invoke Firecrawl scrape on the competitor homepage:`,\n ``,\n `\\`\\`\\`bash`,\n `uv run --with firecrawl-py ~/.claude/skills/research/scripts/scrape.py \"https://${input.domain}\"`,\n `\\`\\`\\``,\n ``,\n `If the homepage returns a 404 or connection error, fall back to Firecrawl search:`,\n ``,\n `\\`\\`\\`bash`,\n `uv run --with firecrawl-py ~/.claude/skills/research/scripts/scrape.py \"site:${input.domain}\"`,\n `\\`\\`\\``,\n ``,\n `From the homepage response extract:`,\n `- \\`url\\` — canonical URL found in response headers or \\`<link rel=\"canonical\">\\`; fall back to the requested URL`,\n `- \\`title\\` — \\`<title>\\` tag content`,\n `- \\`h1\\` — first \\`<h1>\\` text content; null if absent`,\n `- \\`meta_description\\` — \\`<meta name=\"description\">\\` content; null if absent`,\n `- \\`depth_estimate\\` — 0 (homepage is always depth 0)`,\n `- Navigation links — all \\`<a href>\\` values in \\`<nav>\\`, header, and primary menu elements. These seed the crawl queue in Step 3.`,\n ``,\n `Record this as one JSONL entry with \\`page_type_hint: \"homepage\"\\`.`,\n ``,\n `**Running page budget:** 1 of 20 used.`,\n ``,\n `---`,\n ``,\n `${H2} Step 3 — Crawl Top Navigation Pages`,\n ``,\n `From the navigation links discovered in Step 2, identify up to 10 distinct internal URLs (same domain, non-hash, non-anchor-only).`,\n ``,\n `Prioritize in this order:`,\n `1. URLs that appear to be service or product pages (contain \\`/services/\\`, \\`/products/\\`, \\`/solutions/\\`, \\`/what-we-do/\\` in path)`,\n `2. URLs that appear to be location pages (contain \\`/location/\\`, \\`/areas/\\`, city/state patterns)`,\n `3. URLs that appear to be pricing pages (contain \\`/pricing/\\`, \\`/plans/\\`, \\`/cost/\\`)`,\n `4. Remaining nav URLs in order of appearance`,\n ``,\n `For each selected URL, invoke Firecrawl scrape:`,\n ``,\n `\\`\\`\\`bash`,\n `uv run --with firecrawl-py ~/.claude/skills/research/scripts/scrape.py \"https://${input.domain}{path}\"`,\n `\\`\\`\\``,\n ``,\n `Extract per page: \\`url\\`, \\`title\\`, \\`h1\\`, \\`meta_description\\`. Set \\`depth_estimate: 1\\`.`,\n ``,\n `Stop when budget reaches 11 pages (1 homepage + 10 nav pages) or nav links are exhausted.`,\n ``,\n `**Running page budget:** up to 11 of 20 used after this step.`,\n ``,\n `---`,\n ``,\n `${H2} Step 4 — Discover Additional Pages via Firecrawl Search`,\n ``,\n `Use Firecrawl search to discover indexed pages not found through navigation:`,\n ``,\n `\\`\\`\\`bash`,\n `uv run --with firecrawl-py ~/.claude/skills/research/scripts/scrape.py \"site:${input.domain} -inurl:(login OR cart OR checkout OR account)\"`,\n `\\`\\`\\``,\n ``,\n `From search results, extract URLs not already collected. Scrape each unique URL not yet in inventory up to the remaining budget (20 − pages already collected).`,\n ``,\n `For each page scraped: extract \\`url\\`, \\`title\\`, \\`h1\\`, \\`meta_description\\`. Set \\`depth_estimate: 2\\` (approximate — these are search-discovered, not navigation-discovered).`,\n ``,\n `Stop when total page count reaches 20.`,\n ``,\n `---`,\n ``,\n `${H2} Step 5 — Assign Preliminary Page Type Hints`,\n ``,\n `For each collected URL, assign a \\`page_type_hint\\` using URL path patterns and title signals from \\`01-page-type-taxonomy.md\\`.`,\n ``,\n `Rules:`,\n `- Do not use high-confidence classification — these are hints only`,\n `- Set \\`classification_confidence: \"low\"\\` on every record (Firecrawl data lacks status codes, link context, and crawl depth)`,\n `- Use path-pattern matching first (e.g., \\`/blog/\\` → \\`blog_post\\`, \\`/about\\` → \\`about\\`)`,\n `- Use title matching second (e.g., title contains \"pricing\" → \\`pricing\\`)`,\n `- If neither pattern matches: set \\`page_type_hint: \"unknown\"\\``,\n ``,\n `---`,\n ``,\n `${H2} Step 6 — Write Output`,\n ``,\n `Write \\`${input.sessionPath}/phase1/competitor-${competitorIndex}-enrichment.jsonl\\`.`,\n ``,\n `One JSON object per line. Every record must include these fields:`,\n ``,\n `\\`\\`\\`json`,\n `{`,\n ` \"competitor_domain\": \"${input.domain}\",`,\n ` \"competitor_index\": ${competitorIndex},`,\n ` \"url\": \"https://${input.domain}/example-page/\",`,\n ` \"title\": \"Example Page Title\",`,\n ` \"h1\": \"Example H1 Heading\",`,\n ` \"meta_description\": \"Page meta description text.\",`,\n ` \"depth_estimate\": 1,`,\n ` \"page_type_hint\": \"service_page\",`,\n ` \"classification_confidence\": \"low\",`,\n ` \"source\": \"firecrawl\",`,\n ` \"data_quality\": \"partial — firecrawl enrichment\",`,\n ` \"enrichment_quality\": \"partial\"`,\n `}`,\n `\\`\\`\\``,\n ``,\n `Set \\`h1\\` and \\`meta_description\\` to \\`null\\` if not found. Do not omit these fields.`,\n ``,\n `After all page records, write the summary line:`,\n ``,\n `\\`\\`\\`json`,\n `{\"_summary\":true,\"entry_type\":\"competitor_enrichment\",\"total_count\":<N>,\"competitor_domain\":\"${input.domain}\",\"competitor_index\":${competitorIndex},\"enrichment_quality\":\"partial\",\"pages_scraped\":<N>,\"budget_limit\":20,\"source\":\"firecrawl\",\"status\":\"complete\"}`,\n `\\`\\`\\``,\n ``,\n `Where \\`total_count\\` and \\`pages_scraped\\` equal the number of page records written (not including the summary line).`,\n ``,\n `---`,\n ``,\n `${H2} Step 7 — Print Completion Notice`,\n ``,\n `Print:`,\n ``,\n `\\`\\`\\``,\n `Competitor enrichment complete: ${input.domain} (index ${competitorIndex})`,\n ` Pages scraped: <N> / 20`,\n ` Output: ${input.sessionPath}/phase1/competitor-${competitorIndex}-enrichment.jsonl`,\n ` Data quality: partial — firecrawl enrichment`,\n ` NOTE: This competitor has no Screaming Frog data. Phase 3 classification will run`,\n ` with reduced confidence. Phase 4 recommendations involving this competitor`,\n ` will carry data_quality: partial annotations.`,\n `\\`\\`\\``,\n ``,\n `---`,\n ``,\n `Status: COMPLETE`,\n ];\n\n return lines.join('\\n');\n}\n","import { z } from 'zod';\n\nexport const BuildGraphPerSiteInputSchema = z.object({\n siteId: z.string(),\n domain: z.string(),\n urlInventory: z.array(\n z.object({\n url: z.string(),\n sitemap_present: z.boolean(),\n crawl_depth: z.number().optional(),\n })\n ),\n directedEdgeCount: z.number(),\n});\nexport type BuildGraphPerSiteInput = z.infer<typeof BuildGraphPerSiteInputSchema>;\n\nexport function buildGraphPerSitePrompt(input: BuildGraphPerSiteInput): string {\n const orphanCandidates = input.urlInventory.filter(\n (u) => !u.sitemap_present && (u.crawl_depth === undefined || u.crawl_depth === null)\n );\n\n const inventoryBlock = input.urlInventory\n .map((u) => {\n const depth =\n u.crawl_depth !== undefined && u.crawl_depth !== null\n ? `crawl_depth=${u.crawl_depth}`\n : 'crawl_depth=MISSING';\n const sitemap = u.sitemap_present ? 'in_sitemap=true' : 'in_sitemap=false';\n return ` - ${u.url} [${depth}, ${sitemap}]`;\n })\n .join('\\n');\n\n const orphanBlock =\n orphanCandidates.length > 0\n ? orphanCandidates.map((u) => ` - ${u.url}`).join('\\n')\n : ' (none identified from input data)';\n\n return `You are a site architecture graph analyst performing Phase 2 orphan annotation for the Site Architecture Auditor.\n\nSITE: ${input.domain} (site_id: ${input.siteId})\nDIRECTED EDGES IN GRAPH: ${input.directedEdgeCount}\nTOTAL URLS IN INVENTORY: ${input.urlInventory.length}\n\n---\n\nTASK: Confirm orphan candidates using the two-source rule.\n\nTWO-SOURCE RULE (definitive):\nA URL is confirmed orphaned if and only if ALL of the following hold:\n1. It is NOT reachable from the crawl (crawl_depth is absent or undefined)\n2. It is NOT present in the XML sitemap (in_sitemap=false)\nA URL present in at least one of those two sources (crawl OR sitemap) is NOT an orphan.\n\nIMPORTANT: Do NOT use graph metrics for this determination. Orphan status is a structural\nreachability question, not a PageRank or link-count question. Python handles all numeric\ngraph computation. Your only job here is to apply the two-source rule to the inventory below.\n\n---\n\nURL INVENTORY:\n${inventoryBlock}\n\n---\n\nPRE-IDENTIFIED ORPHAN CANDIDATES (absent from both crawl and sitemap):\n${orphanBlock}\n\n---\n\nINSTRUCTIONS:\n1. Review the pre-identified orphan candidates above.\n2. For each candidate, confirm or reject orphan status by re-applying the two-source rule.\n - Confirm: crawl_depth is MISSING and in_sitemap=false -> confirmed orphan\n - Reject: if either crawl_depth is present OR in_sitemap=true -> not an orphan (re-check source data)\n3. Note any URLs where the inventory data appears inconsistent (e.g. has a crawl_depth but also flagged as candidate).\n4. Do NOT modify PageRank, crawl_depth, or any numeric field — those are [COMPUTED:python/networkx].\n5. Do NOT classify page types here — that is Phase 3.\n\n---\n\nOUTPUT FORMAT:\nReturn ONLY a valid JSON object — no markdown fences, no commentary.\n\n{\n \"site_id\": \"${input.siteId}\",\n \"domain\": \"${input.domain}\",\n \"confirmed_orphans\": [\n {\n \"url\": \"https://example.com/orphaned-page/\",\n \"reason\": \"absent from crawl and sitemap\"\n }\n ],\n \"rejected_candidates\": [\n {\n \"url\": \"https://example.com/not-really-orphaned/\",\n \"reason\": \"present in sitemap despite missing crawl_depth\"\n }\n ],\n \"data_quality_notes\": [\n \"Optional: note any inventory inconsistencies found during review\"\n ],\n \"orphan_count\": 0,\n \"_annotation_label\": \"[INTERPRETED:claude]\"\n}\n\nRULES:\n- confirmed_orphans must be a subset of the pre-identified candidates above — do not add new orphans not in that list.\n- rejected_candidates may be empty array if all candidates are confirmed.\n- data_quality_notes may be empty array if no issues found.\n- orphan_count must equal confirmed_orphans.length.\n- All decisions must be based solely on the two-source rule — do not infer orphan status from URL path patterns.`;\n}\n","import { z } from 'zod';\n\nexport const MetricsClassifyInputSchema = z.object({\n urls: z.array(\n z.object({\n url: z.string(),\n title: z.string().optional(),\n h1: z.string().optional(),\n meta_description: z.string().optional(),\n _location_hint: z.unknown().optional(),\n })\n ),\n siteDomain: z.string(),\n});\nexport type MetricsClassifyInput = z.infer<typeof MetricsClassifyInputSchema>;\n\nexport function buildMetricsClassifyPrompt(input: MetricsClassifyInput): string {\n const urlsBlock = input.urls\n .map((u) => {\n const lines: string[] = [` \"url\": \"${u.url}\"`];\n if (u.title) lines.push(` \"title\": ${JSON.stringify(u.title.slice(0, 160))}`);\n if (u.h1) lines.push(` \"h1\": ${JSON.stringify(u.h1.slice(0, 100))}`);\n if (u.meta_description)\n lines.push(` \"meta_description\": ${JSON.stringify(u.meta_description.slice(0, 160))}`);\n if (u._location_hint !== undefined && u._location_hint !== null) {\n lines.push(` \"_location_hint\": ${JSON.stringify(u._location_hint)}`);\n }\n return ` {\\n${lines.join(',\\n')}\\n }`;\n })\n .join(',\\n');\n\n const locationHintPresent = input.urls.some(\n (u) => u._location_hint !== undefined && u._location_hint !== null\n );\n const locationHintNote = locationHintPresent\n ? `\nLOCATION HINTS: Some URLs include a \"_location_hint\" field. This is a partial result from the\ndeterministic location classifier that could not reach high-confidence classification on its own.\nUse the hint as supporting context — it may indicate a likely location-related page type — but\napply your own judgment from the full 22-type taxonomy. The hint does not override your analysis.\n`\n : '';\n\n return `You are classifying URLs for a site architecture audit of ${input.siteDomain}.\nApply the 22-type taxonomy exactly as defined below. Return one JSON object per URL.\n\nBatch constraints enforced by caller: max 50 URLs per call, total payload <=8000 chars\n(url + title + h1 + meta_description per record).\n\nNote: location/service_location URLs already classified deterministically by the Python location\nclassifier are excluded from this batch. Only non-location or low-confidence location URLs appear here.\n${locationHintNote}\nTAXONOMY TYPES (22 canonical slugs):\n homepage, core_service, sub_service, location, service_location, industry, product, pricing,\n faq, blog_article, guide_resource, case_study, comparison, about, contact, team, careers,\n privacy_policy, terms, html_sitemap, login_portal, support_help_center\n\nDISAMBIGUATION RULES:\n- Apply the 22-type taxonomy exactly. Do NOT infer page type from URL path alone when title/h1 contradict the path.\n- A URL with \"blog\" in the path but a service-focused title and no article date is core_service or sub_service, not blog_article.\n- service_location = a page targeting a specific service in a specific city/area (e.g. \"Emergency Plumbing Dallas TX\").\n- location = a pure location hub page with no specific service focus (e.g. \"We Serve Dallas\").\n- core_service = primary service offered; sub_service = a more specific variant of a core service.\n- pricing = page whose primary purpose is showing pricing, costs, or quotes.\n- comparison = page comparing the business to competitors or comparing service options.\n- industry = page targeting a vertical/industry audience (e.g. \"Plumbing for Commercial Buildings\").\n- guide_resource = long-form educational content; faq = question-answer format page.\n- case_study = project or customer story with specific outcome data.\n- support_help_center = post-sale support, troubleshooting, or knowledge base content.\n- login_portal = login, account, dashboard, or authenticated app pages.\n- html_sitemap = a human-readable HTML sitemap page (not XML sitemap).\n- about, contact, team, careers, privacy_policy, terms = exactly as labeled.\n- homepage = the site root URL only.\n- If uncertain between two types, pick the one that best matches the primary conversion intent of the page.\n\nMONEY PAGE DEFINITION:\nA money page is any URL where the primary purpose is to generate revenue or capture a service lead.\nSet is_money_page=true for: core_service, sub_service, service_location, pricing, product, comparison.\nSet is_money_page=false for all others unless the content clearly contradicts the type assignment.\n\nCLASSIFICATION CONFIDENCE:\n- high: clear signals from URL + title + h1 all agree on the same type\n- medium: URL and one signal agree; other signals absent or ambiguous\n- low: signals conflict or all metadata is absent (URL path only)\n\nTOPIC CLUSTER:\nAssign a lowercase hyphenated topic cluster name that groups semantically related pages.\nExamples: \"emergency-plumbing\", \"commercial-roofing\", \"hvac-installation\", \"location-dallas-tx\".\nUse the service or topic focus — not the page type — as the cluster name.\nFor utility pages (contact, about, privacy_policy, etc.), use \"site-utility\".\n\n---\n\nURLS TO CLASSIFY:\n[\n${urlsBlock}\n]\n\n---\n\nOUTPUT FORMAT:\nReturn ONLY a valid JSON array — no markdown fences, no commentary, no trailing commas.\n\n[\n {\n \"url\": \"https://example.com/services/emergency-plumbing/\",\n \"page_type\": \"core_service\",\n \"topic_cluster_name\": \"emergency-plumbing\",\n \"is_money_page\": true,\n \"classification_confidence\": \"high\",\n \"_classification_label\": \"[INTERPRETED:claude]\"\n }\n]\n\nRULES:\n- Return exactly one object per input URL — same count, same order.\n- page_type must be one of the 22 canonical slugs listed above — no custom values.\n- topic_cluster_name must be lowercase, hyphenated, and descriptive — no spaces.\n- _classification_label must always be \"[INTERPRETED:claude]\" for every record in your output.\n- Do NOT include any field not listed in the output format above.\n- Do NOT include _location_hint in your output — it is input context only.`;\n}\n","import { z } from 'zod';\n\nexport const CompareRecommendInputSchema = z.object({\n clientDomain: z.string(),\n clientMoneyPages: z.array(z.unknown()),\n competitorSites: z.array(\n z.object({\n domain: z.string(),\n role: z.string(),\n urlInventory: z.array(z.unknown()),\n })\n ),\n clientUrlMetrics: z.array(z.unknown()),\n clientPageTypes: z.array(z.unknown()),\n});\nexport type CompareRecommendInput = z.infer<typeof CompareRecommendInputSchema>;\n\nconst GUARDRAIL_NOTICE =\n 'GUARDRAIL NOTICE: Do NOT recommend a link solely because it passes PageRank or ' +\n 'link equity to a target page, or for any SEO manipulation purpose. Every ' +\n 'recommendation must have a genuine topical relevance or user-value rationale. ' +\n 'Do NOT apply guardrail rule filtering inside your response — the caller ' +\n '(handleComparePhase) runs applyGuardrailRules() on your output before persisting. ' +\n 'Generate the full candidate set; the caller filters violations.';\n\nconst SECTION_GUIDE = [\n '## Step 5 — Topic Cluster Gap Analysis',\n 'For each client money page, identify its topic cluster and the number of support pages in that cluster.',\n 'Compare client support page count against the competitor median for the same cluster.',\n 'For each cluster where the gap > 0, write one sentence explaining the ranking impact.',\n 'Label computed values [COMPUTED:python] and your interpretation [INTERPRETED:claude].',\n '',\n '## Step 6 — UX/Nav Pattern Comparison',\n 'Identify primary navigation pages for each site (link_position includes \"Primary Navigation\", crawl_depth ≤ 2).',\n 'Compare which money page types are in competitor nav but absent from client nav.',\n 'Identify location architecture patterns and gaps.',\n 'Write one summary paragraph per site describing nav pattern and location architecture differences.',\n 'Label all LLM-generated prose [INTERPRETED:claude].',\n '',\n '## Step 8 — Link Recommendations',\n 'For each target page, identify existing client pages in the same topic cluster that do NOT currently link to it.',\n 'For each candidate source, write:',\n ' - A specific anchor text (not vague: avoid \"click here\", \"read more\", \"learn more\", \"here\", \"this page\")',\n ' - A specific placement instruction (section, position within page, after which element)',\n ' - A clear reason citing topical overlap and the inlink gap',\n 'All 5 required fields must be present: target_url, source_url, anchor_text, placement, reason.',\n 'Label anchor text [INTERPRETED:claude].',\n '',\n '## Step 9 — New Page Creation List',\n 'For each page type present in ≥2 competitors but absent from the client:',\n ' - Propose a specific url_slug following the client site\\'s URL pattern',\n ' - Assign nav_placement based on the client\\'s existing nav structure',\n ' - Identify which money page this new page will support (supports_target_url)',\n 'Label placement decisions [INTERPRETED:claude].',\n '',\n '## Output Format',\n 'Return a valid JSON object with these top-level keys:',\n ' \"topicClusterGapAnalysis\": array of records per money page',\n ' \"uxNavPatternComparison\": array of records per site',\n ' \"linkRecommendations\": array of link-add recommendations (all 5 fields required each)',\n ' \"newPageCreationList\": array of new page recommendations',\n '',\n 'Every link recommendation record must include:',\n ' target_url, source_url, anchor_text, placement, reason, topic_similarity_score, confidence',\n '',\n 'Every new page creation record must include:',\n ' url_slug, page_type, competitor_count, nav_placement, supports_target_url',\n].join('\\n');\n\nexport function buildCompareRecommendPrompt(input: CompareRecommendInput): string {\n const truncate = (s: string, n: number) =>\n s.length > n ? s.slice(0, n) + '\\n[...truncated...]' : s;\n\n const competitorSummary = input.competitorSites\n .map((c) => ` - ${c.domain} (${c.role}): ${(c.urlInventory as unknown[]).length} URLs`)\n .join('\\n');\n\n const moneyPageUrls = (input.clientMoneyPages as Array<{ url?: string }>)\n .map((p) => p.url ?? '(unknown)')\n .slice(0, 20)\n .join('\\n ');\n\n const pageTypeSummary = truncate(JSON.stringify(input.clientPageTypes), 4000);\n const metricsSummary = truncate(JSON.stringify(input.clientUrlMetrics), 4000);\n\n const parts = [\n 'You are a senior site architecture analyst performing Phase 4 of a Site Architecture Audit.',\n '',\n `Client domain: ${input.clientDomain}`,\n '',\n 'COMPETITOR SITES:',\n competitorSummary,\n '',\n 'CLIENT MONEY PAGES (up to 20 shown):',\n ` ${moneyPageUrls}`,\n '',\n 'CLIENT PAGE TYPE CLASSIFICATIONS:',\n pageTypeSummary,\n '',\n 'CLIENT URL METRICS (PageRank, depth, inlink counts):',\n metricsSummary,\n '',\n 'YOUR TASK:',\n '',\n 'Perform steps 5, 6, 8, and 9 of the Site Architecture Phase 4 analysis.',\n 'The page_type_coverage_matrix, architecture_depth_comparison, and target_page_list are',\n 'pre-computed by Python and provided as context. Your role is to add the interpretation',\n 'and recommendation layers that require natural language reasoning.',\n '',\n GUARDRAIL_NOTICE,\n '',\n SECTION_GUIDE,\n '',\n 'RULES:',\n '- Return ONLY a valid JSON object — no markdown fences, no commentary.',\n '- Every link recommendation must have all 5 required fields: target_url, source_url, anchor_text, placement, reason.',\n '- Anchor text must not be from the vague blocklist: \"click here\", \"read more\", \"learn more\", \"here\", \"this page\".',\n '- Label your interpretations [INTERPRETED:claude] and Python-computed values [COMPUTED:python].',\n '- Do not recompute PageRank, crawl depth, or inlink counts — use the values provided.',\n '- Do not hallucinate URLs — only use URLs present in the client URL metrics or competitor inventories.',\n ];\n\n return parts.join('\\n');\n}\n","import { z } from 'zod';\n\nexport const ScoreSynthesizeInputSchema = z.object({\n preComputedArchitectureScore: z.unknown(),\n preComputedIlesScore: z.unknown(),\n rankedBacklog: z.array(z.unknown()),\n clientDomain: z.string(),\n sessionPath: z.string(),\n});\nexport type ScoreSynthesizeInput = z.infer<typeof ScoreSynthesizeInputSchema>;\n\nconst REPORT_SECTIONS = [\n '## Executive Summary',\n 'Write the top 5 architecture gaps, top 5 internal link opportunities, top 5 pages to create,',\n 'top 5 pages to elevate in navigation, and top 5 orphan/crawl coverage issues.',\n 'Each entry is one sentence with the impact and the action. Label [INTERPRETED:claude].',\n '',\n '## Architecture Score: {score}/100 [COMPUTED:python]',\n 'Present the pre-computed score in a table with all 6 sub-dimensions:',\n 'url_inventory_health (20%), crawlability (20%), important_page_depth (20%),',\n 'page_type_coverage (15%), topical_cluster_completeness (15%), ux_nav_clarity (10%).',\n 'Columns: Sub-dimension | Weight | Raw Score | Weighted | Data Source.',\n 'Add a 2-3 sentence interpretation of what the score reveals. Label [INTERPRETED:claude].',\n 'Do NOT recompute the score — use the preComputedArchitectureScore values exactly.',\n '',\n '## Internal Link Equity Score: {score}/100 [COMPUTED:python]',\n 'Present the pre-computed ILES in a table with all 6 sub-dimensions:',\n 'target_page_internal_pagerank (30%), content_inlinks_to_target_pages (20%),',\n 'anchor_relevance (15%), link_position_quality (15%), support_cluster_strength (10%),',\n 'low_value_link_waste_reduction (10%).',\n 'Columns: Sub-dimension | Weight | Raw Score | Weighted | Data Source.',\n 'Add a 2-3 sentence interpretation of the biggest leverage points. Label [INTERPRETED:claude].',\n 'Do NOT recompute the score — use the preComputedIlesScore values exactly.',\n '',\n '## URL Inventory',\n 'Present a summary table: total crawled, indexable, non-indexable, sitemap URLs, orphan candidates,',\n 'sitemap-only (not crawled), crawl-only (not in sitemap), non-indexable in sitemap, canonical conflicts,',\n 'redirects in sitemap, 404s in sitemap.',\n 'Source each row from the pre-computed phase data. Add 1-2 sentences on notable inventory patterns.',\n '',\n '## Competitor Page Gap Matrix',\n 'Present all 22 page types in a table. Columns: Page Type | Client | Competitor 1 | Competitor 2 | Gap Flag | Recommendation.',\n 'Values: present / absent. Gap Flag: GAP (absent for client, present in ≥1 competitor),',\n 'PARTIAL GAP, or — (no gap). Source: pre-computed phase-4 coverage matrix.',\n '',\n '## Architecture Depth Comparison',\n 'Present a table with columns: Page Type | Client Median Depth | Competitor Median Depth | Delta | Action.',\n 'Positive delta = client pages are buried deeper. Source: pre-computed phase-4 depth comparison.',\n '',\n '## Topic Cluster Analysis',\n 'For each client money page, write a subsection with: page type, topic cluster, current content inlinks,',\n 'competitor median content inlinks, crawl depth, internal PageRank, current support pages,',\n 'support gap, gap interpretation, and recommended new support pages.',\n 'Label computed values [COMPUTED:python] and interpretations [INTERPRETED:claude].',\n '',\n '## Internal Link Recommendations',\n 'For each item in the link recommendations (ordered by confidence descending), write a subsection:',\n '→ {target_url}, Add link from: {source_url}, Anchor text, Placement, Reason,',\n 'Topic similarity score, Confidence.',\n 'All 5 required fields must appear. Label anchor and placement [INTERPRETED:claude].',\n '',\n '## New Page Creation Plan',\n 'For each item in the new page creation list (P0 first, then P1, then P2), write a subsection:',\n '{url_slug} — Priority: {tier}. Include: page type, competitor consensus, gap priority score',\n 'with all 5 formula factors shown, nav placement, supports target URL, required inbound link.',\n '',\n '## Guardrail Flags',\n 'Present a table of all rejected recommendations with columns:',\n 'Rule # | Rule Triggered | Item Type | Target URL | Source URL | Reason Excluded.',\n 'Do NOT silently omit this section even if the flag list is empty (write \"No guardrail flags.\").',\n '',\n '## Implementation Backlog',\n 'Present all backlog tasks ranked by priority score (descending). P0 = execute immediately,',\n 'P1 = next sprint, P2 = roadmap. Columns:',\n 'Priority | Tier | Task | Owner | Input Needed | Output | Confidence | Gap Score.',\n 'Each row must name a specific URL and specific deliverable. Source: rankedBacklog.',\n].join('\\n');\n\nexport function buildScoreSynthesizePrompt(input: ScoreSynthesizeInput): string {\n const truncate = (s: string, n: number) =>\n s.length > n ? s.slice(0, n) + '\\n[...truncated...]' : s;\n\n const architectureScoreJson = truncate(JSON.stringify(input.preComputedArchitectureScore, null, 2), 3000);\n const ilesScoreJson = truncate(JSON.stringify(input.preComputedIlesScore, null, 2), 3000);\n const backlogJson = truncate(JSON.stringify(input.rankedBacklog), 5000);\n\n const parts = [\n 'You are the synthesis agent for the Site Architecture Auditor.',\n 'All numeric scoring is pre-computed. Your task is to assemble the 9-section',\n 'Site Architecture Intelligence Report as a Markdown document.',\n '',\n 'CRITICAL: Do NOT recompute the Architecture Score or the Internal Link Equity Score.',\n 'Use the preComputedArchitectureScore and preComputedIlesScore values exactly as provided.',\n '',\n `Client domain: ${input.clientDomain}`,\n `Session path: ${input.sessionPath}`,\n '',\n 'PRE-COMPUTED ARCHITECTURE SCORE:',\n architectureScoreJson,\n '',\n 'PRE-COMPUTED INTERNAL LINK EQUITY SCORE (ILES):',\n ilesScoreJson,\n '',\n 'RANKED IMPLEMENTATION BACKLOG:',\n backlogJson,\n '',\n 'YOUR TASK:',\n '',\n 'Write the complete Site Architecture Intelligence Report in Markdown.',\n 'The report must contain all 9 sections listed below, in exact order.',\n 'Each section must have a level-2 heading (##) matching the name shown.',\n 'The report ends with the line: Status: COMPLETE',\n '',\n REPORT_SECTIONS,\n '',\n 'OUTPUT RULES:',\n '- Output ONLY the Markdown report. No preamble, no trailing commentary.',\n '- Section headings must match exactly as shown above.',\n '- Use the pre-computed scores as the sole source of numeric facts. Do not hallucinate metrics.',\n '- Label all LLM-generated prose [INTERPRETED:claude].',\n '- Label all formula/graph outputs [COMPUTED:python] or [COMPUTED:python/formula].',\n '- The report must end with: Status: COMPLETE',\n '- The report must be at least 1000 words.',\n '',\n 'Begin the report now.',\n ];\n\n return parts.join('\\n');\n}\n","import { z } from 'zod';\nimport pLimit from 'p-limit';\nimport { llmParseWithRetry, type ILlmClient } from '../../lib/llm-parse-with-retry.js';\nimport { type IHttpClient } from '../../lib/http-client.js';\nimport { type ISiteAuditRepository } from './site-audit-repository.js';\nimport { type ISiteAuditPythonRunner } from './python/graph-runner.js';\nimport {\n ValidatedFileManifestSchema,\n EnrichCompetitorOutputSchema,\n PageTypeClassificationRowSchema,\n SiteAuditResultSchema,\n type SiteAuditStartRequest,\n type SiteAuditPhase,\n type SiteAuditResult,\n type SiteAuditIngestPayload,\n type SiteAuditBuildGraphPayload,\n type SiteAuditClassifyPayload,\n type SiteAuditComparePayload,\n type SiteAuditSynthesizePayload,\n} from './schemas.js';\nimport type { SiteAuditJobRow } from '../../api/db.js';\nimport { buildIngestValidatePrompt } from './prompts/ingest-validate.js';\nimport { buildEnrichCompetitorPrompt } from './prompts/enrich-competitor.js';\nimport { buildGraphPerSitePrompt } from './prompts/build-graph-per-site.js';\nimport { buildMetricsClassifyPrompt } from './prompts/metrics-classify.js';\nimport { buildCompareRecommendPrompt } from './prompts/compare-recommend.js';\nimport { buildScoreSynthesizePrompt } from './prompts/score-synthesize.js';\nimport { ARCHITECTURE_SCORE_WEIGHTS, ILES_WEIGHTS } from '../../lib/site-architecture-auditor/rules.js';\n\nconst OrphanAnnotationOutputSchema = z.object({\n site_id: z.string(),\n domain: z.string(),\n confirmed_orphans: z.array(\n z.object({\n url: z.string(),\n reason: z.string(),\n })\n ),\n rejected_candidates: z.array(\n z.object({\n url: z.string(),\n reason: z.string(),\n })\n ),\n data_quality_notes: z.array(z.string()),\n orphan_count: z.number(),\n _annotation_label: z.string(),\n});\n\nconst CompareRecommendOutputSchema = z.object({\n topicClusterGapAnalysis: z.array(z.unknown()).optional(),\n uxNavPatternComparison: z.array(z.unknown()).optional(),\n linkRecommendations: z.array(\n z.object({\n target_url: z.string(),\n source_url: z.string(),\n anchor_text: z.string(),\n placement: z.string(),\n reason: z.string(),\n topic_similarity_score: z.unknown().optional(),\n confidence: z.unknown().optional(),\n })\n ).optional(),\n newPageCreationList: z.array(z.unknown()).optional(),\n});\n\nexport type CompareRecommendOutput = z.infer<typeof CompareRecommendOutputSchema>;\n\nexport interface ISiteAuditService {\n startAudit(userId: number, request: SiteAuditStartRequest): Promise<string>;\n getJob(jobId: string): Promise<SiteAuditJobRow | null>;\n getJobsForUser(userId: number): Promise<SiteAuditJobRow[]>;\n runIngestPhase(jobId: string, payload: SiteAuditIngestPayload): Promise<void>;\n runEnrichPhase(jobId: string, payload: SiteAuditIngestPayload): Promise<void>;\n runBuildGraphPhase(jobId: string, payload: SiteAuditBuildGraphPayload): Promise<void>;\n runClassifyPhase(jobId: string, payload: SiteAuditClassifyPayload): Promise<void>;\n runComparePhase(jobId: string, payload: SiteAuditComparePayload): Promise<CompareRecommendOutput>;\n runSynthesizePhase(jobId: string, payload: SiteAuditSynthesizePayload): Promise<void>;\n dispatchPhase(phase: SiteAuditPhase, jobId: string, payload: unknown): Promise<void>;\n}\n\nexport interface SiteAuditServiceDeps {\n repo: ISiteAuditRepository;\n llm: ILlmClient;\n http: IHttpClient;\n python: ISiteAuditPythonRunner;\n}\n\nexport class SiteAuditService implements ISiteAuditService {\n constructor(private deps: SiteAuditServiceDeps) {}\n\n async startAudit(userId: number, request: SiteAuditStartRequest): Promise<string> {\n const jobId = `saa-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n await this.deps.repo.createSiteAuditJob(jobId, userId, request);\n return jobId;\n }\n\n async getJob(jobId: string): Promise<SiteAuditJobRow | null> {\n return this.deps.repo.getSiteAuditJob(jobId);\n }\n\n async getJobsForUser(userId: number): Promise<SiteAuditJobRow[]> {\n return this.deps.repo.listSiteAuditJobs(userId);\n }\n\n async runIngestPhase(jobId: string, payload: SiteAuditIngestPayload): Promise<void> {\n const { request } = payload;\n const input = {\n clientDomain: request.clientDomain,\n sfInternalPath: request.sfInternalPath,\n sfInlinksPath: request.sfInlinksPath,\n sfOutlinksPath: request.sfOutlinksPath,\n sitemapPath: request.sitemapPath,\n competitorDomainsCsvPath: request.competitorDomainsCsvPath,\n visualSitemapsPath: request.visualSitemapsPath,\n gscPath: request.gscPath,\n ga4Path: request.ga4Path,\n ahrefsPath: request.ahrefsPath,\n businessContext: request.businessContext,\n priorAuditMemoryEnabled: request.priorAuditMemoryEnabled,\n };\n const result = await llmParseWithRetry(\n ValidatedFileManifestSchema,\n (attempt, error) => {\n void attempt;\n void error;\n return buildIngestValidatePrompt(input);\n },\n this.deps.llm,\n );\n await this.deps.repo.logSiteAuditPhaseComplete(jobId, 'phase1-ingest', result);\n }\n\n async runEnrichPhase(jobId: string, payload: SiteAuditIngestPayload): Promise<void> {\n const { request } = payload;\n const limit = pLimit(3);\n const job = await this.deps.repo.getSiteAuditJob(jobId);\n if (!job) throw new Error(`[site-audit-service] runEnrichPhase: job ${jobId} not found`);\n\n const sessionPath = request.sessionPath;\n const competitorDomain = request.clientDomain;\n void competitorDomain;\n\n const competitorDomainsCsvPath = request.competitorDomainsCsvPath;\n void competitorDomainsCsvPath;\n\n const competitors: string[] = await this._readCompetitorDomains(request);\n\n const results = await Promise.all(\n competitors.map((domain, idx) =>\n limit(async () => {\n const competitorIndex = idx + 1;\n const rawPrompt = buildEnrichCompetitorPrompt({ domain, sessionPath });\n const prompt = rawPrompt.replace('<competitor-index>', String(competitorIndex));\n const result = await llmParseWithRetry(\n EnrichCompetitorOutputSchema,\n (attempt, error) => {\n void attempt;\n void error;\n return prompt;\n },\n this.deps.llm,\n );\n return result;\n })\n )\n );\n\n await this.deps.repo.logSiteAuditPhaseComplete(jobId, 'phase1-ingest', { competitors: results });\n }\n\n async runBuildGraphPhase(jobId: string, payload: SiteAuditBuildGraphPayload): Promise<void> {\n void payload;\n const job = await this.deps.repo.getSiteAuditJob(jobId);\n if (!job) throw new Error(`[site-audit-service] runBuildGraphPhase: job ${jobId} not found`);\n\n const request = JSON.parse(job.request) as SiteAuditStartRequest;\n const sessionPath = request.sessionPath;\n const clientDomain = request.clientDomain;\n\n const urlInventory: Array<{ url: string; sitemap_present: boolean; crawl_depth?: number }> = [];\n const directedEdgeCount = 0;\n\n const orphanAnnotation = await llmParseWithRetry(\n OrphanAnnotationOutputSchema,\n (attempt, error) => {\n void attempt;\n void error;\n return buildGraphPerSitePrompt({\n siteId: 'client',\n domain: clientDomain,\n urlInventory,\n directedEdgeCount,\n });\n },\n this.deps.llm,\n );\n\n const graphMetrics = await this.deps.python.runGraphMetrics({\n directedLinkGraphPath: `${sessionPath}/phase1/directed_link_graph.json`,\n masterUrlInventoryPath: `${sessionPath}/phase1/master_url_inventory.json`,\n outputPath: `${sessionPath}/phase2/graph_metrics.json`,\n });\n\n await this.deps.repo.logSiteAuditPhaseComplete(jobId, 'phase2-build-graph', {\n orphanAnnotation,\n graphMetrics,\n });\n }\n\n async runClassifyPhase(jobId: string, payload: SiteAuditClassifyPayload): Promise<void> {\n void payload;\n const job = await this.deps.repo.getSiteAuditJob(jobId);\n if (!job) throw new Error(`[site-audit-service] runClassifyPhase: job ${jobId} not found`);\n\n const request = JSON.parse(job.request) as SiteAuditStartRequest;\n const sessionPath = request.sessionPath;\n const clientDomain = request.clientDomain;\n\n const allUrls: Array<{\n url: string;\n title?: string;\n h1?: string;\n meta_description?: string;\n }> = [];\n\n const BATCH_SIZE = 50;\n const MAX_PAYLOAD_CHARS = 8000;\n const allClassifications: z.infer<typeof PageTypeClassificationRowSchema>[] = [];\n\n const trimmedUrls = allUrls.map(u => ({\n ...u,\n h1: u.h1 ? u.h1.slice(0, 100) : u.h1,\n meta_description: u.meta_description ? u.meta_description.slice(0, 160) : u.meta_description,\n }));\n\n const batches: typeof trimmedUrls[] = [];\n let currentBatch: typeof trimmedUrls = [];\n let currentPayloadChars = 0;\n\n for (const urlItem of trimmedUrls) {\n const itemChars =\n urlItem.url.length +\n (urlItem.title?.length ?? 0) +\n (urlItem.h1?.length ?? 0) +\n (urlItem.meta_description?.length ?? 0);\n\n const wouldExceedBatchSize = currentBatch.length >= BATCH_SIZE;\n const wouldExceedPayloadLimit = currentPayloadChars + itemChars > MAX_PAYLOAD_CHARS;\n\n if ((wouldExceedBatchSize || wouldExceedPayloadLimit) && currentBatch.length > 0) {\n batches.push(currentBatch);\n currentBatch = [];\n currentPayloadChars = 0;\n }\n\n currentBatch.push(urlItem);\n currentPayloadChars += itemChars;\n }\n if (currentBatch.length > 0) batches.push(currentBatch);\n\n const usZipsCsvPath = process.env['US_ZIPS_CSV_PATH'] ?? '/Users/vilovieta/Downloads/sales-magician-api-leads-magician-01c6cff78e31/tools/analytics/data/uszips.csv';\n\n for (const batch of batches) {\n let classified: Array<{ url: string; pageType: string; confidence: number; locationSignals: string[] }> = [];\n let unclassifiedUrls: string[] = batch.map(u => u.url);\n\n try {\n const pythonResult = await this.deps.python.runLocationClassifier({\n urls: batch.map(u => u.url),\n usZipsCsvPath,\n });\n classified = pythonResult.classified;\n unclassifiedUrls = pythonResult.unclassified;\n } catch (err) {\n console.warn(\n '[site-audit-service] runClassifyPhase: python.runLocationClassifier failed (falling back to LLM):',\n err instanceof Error ? err.message : String(err)\n );\n unclassifiedUrls = batch.map(u => u.url);\n }\n\n for (const c of classified) {\n allClassifications.push({\n url: c.url,\n page_type: c.pageType as z.infer<typeof PageTypeClassificationRowSchema>['page_type'],\n confidence: c.confidence > 0.6 ? 'high' : c.confidence > 0.4 ? 'medium' : 'low',\n _classification_label: '[COMPUTED:python/location-classifier]',\n topic_cluster: null,\n location_signals: c.locationSignals,\n });\n }\n\n if (unclassifiedUrls.length > 0) {\n const unclassifiedBatch = batch.filter(u => unclassifiedUrls.includes(u.url));\n const llmResults = await llmParseWithRetry(\n z.array(PageTypeClassificationRowSchema),\n (attempt, error) => {\n void attempt;\n void error;\n return buildMetricsClassifyPrompt({\n urls: unclassifiedBatch,\n siteDomain: clientDomain,\n });\n },\n this.deps.llm,\n );\n allClassifications.push(...llmResults);\n }\n }\n\n void sessionPath;\n\n await this.deps.repo.logSiteAuditPhaseComplete(jobId, 'phase3-classify', {\n classifications: allClassifications,\n totalClassified: allClassifications.length,\n });\n }\n\n async runComparePhase(jobId: string, payload: SiteAuditComparePayload): Promise<CompareRecommendOutput> {\n void payload;\n const job = await this.deps.repo.getSiteAuditJob(jobId);\n if (!job) throw new Error(`[site-audit-service] runComparePhase: job ${jobId} not found`);\n\n const request = JSON.parse(job.request) as SiteAuditStartRequest;\n const clientDomain = request.clientDomain;\n\n const result = await llmParseWithRetry(\n CompareRecommendOutputSchema,\n (attempt, error) => {\n void attempt;\n void error;\n return buildCompareRecommendPrompt({\n clientDomain,\n clientMoneyPages: [],\n competitorSites: [],\n clientUrlMetrics: [],\n clientPageTypes: [],\n });\n },\n this.deps.llm,\n );\n\n await this.deps.repo.logSiteAuditPhaseComplete(jobId, 'phase4-compare', result);\n return result;\n }\n\n async runSynthesizePhase(jobId: string, payload: SiteAuditSynthesizePayload): Promise<void> {\n void payload;\n const job = await this.deps.repo.getSiteAuditJob(jobId);\n if (!job) throw new Error(`[site-audit-service] runSynthesizePhase: job ${jobId} not found`);\n\n const request = JSON.parse(job.request) as SiteAuditStartRequest;\n const clientDomain = request.clientDomain;\n const sessionPath = request.sessionPath;\n\n const architectureScoreComponents: Record<string, number> = {};\n for (const [dim, weight] of Object.entries(ARCHITECTURE_SCORE_WEIGHTS)) {\n architectureScoreComponents[dim] = weight * 50;\n }\n const architectureTotal = Object.values(architectureScoreComponents).reduce((s, v) => s + v, 0);\n\n const ilesComponents: Record<string, number> = {};\n for (const [dim, weight] of Object.entries(ILES_WEIGHTS)) {\n ilesComponents[dim] = weight * 50;\n }\n const ilesTotal = Object.values(ilesComponents).reduce((s, v) => s + v, 0);\n\n const preComputedArchitectureScore = {\n total: architectureTotal,\n components: architectureScoreComponents,\n };\n const preComputedIlesScore = {\n total: ilesTotal,\n components: ilesComponents,\n };\n\n const reportMarkdown = await llmParseWithRetry(\n z.string(),\n (attempt, error) => {\n void attempt;\n void error;\n return buildScoreSynthesizePrompt({\n preComputedArchitectureScore,\n preComputedIlesScore,\n rankedBacklog: [],\n clientDomain,\n sessionPath,\n });\n },\n this.deps.llm,\n );\n\n const auditResult: SiteAuditResult = SiteAuditResultSchema.parse({\n jobId,\n clientDomain,\n architectureScore: preComputedArchitectureScore,\n ilesScore: preComputedIlesScore,\n rankedBacklog: [],\n linkRecommendations: [],\n newPagesRecommended: [],\n guardrailFlags: [],\n reportMarkdown,\n });\n\n await this.deps.repo.completeSiteAuditJob(jobId, auditResult);\n await this.deps.repo.logSiteAuditPhaseComplete(jobId, 'phase5-synthesize', {\n architectureScore: auditResult.architectureScore,\n ilesScore: auditResult.ilesScore,\n });\n }\n\n dispatchPhase(_phase: SiteAuditPhase, _jobId: string, _payload: unknown): Promise<void> {\n throw new Error('dispatchPhase delegates to phases.ts — see saa-011');\n }\n\n private async _readCompetitorDomains(request: SiteAuditStartRequest): Promise<string[]> {\n try {\n const response = await this.deps.http.get(`file://${request.competitorDomainsCsvPath}`);\n const lines = response.body\n .split('\\n')\n .map(l => l.trim())\n .filter(l => l.length > 0 && !l.startsWith('#'));\n const domains: string[] = [];\n for (const line of lines) {\n if (line.includes(',')) {\n domains.push(...line.split(',').map(d => d.trim()).filter(d => d.length > 0));\n } else {\n domains.push(line);\n }\n }\n return domains.filter(d => d.includes('.'));\n } catch {\n return [];\n }\n }\n}\n","import { createClient, type Client } from '@libsql/client/http'\nimport { randomBytes, randomUUID, scryptSync, timingSafeEqual } from 'node:crypto'\nimport { z } from 'zod'\n\nconst DB_URL = process.env.TURSO_DATABASE_URL ?? 'file:./paa-api.db'\nconst DB_TOKEN = process.env.TURSO_AUTH_TOKEN\n\nlet _db: Client | null = null\n\nexport function getDb(): Client {\n if (!_db) _db = createClient({ url: DB_URL, authToken: DB_TOKEN })\n return _db\n}\n\nexport async function migrate(): Promise<void> {\n const db = getDb()\n await db.execute(`\n CREATE TABLE IF NOT EXISTS users (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n email TEXT UNIQUE NOT NULL,\n name TEXT,\n api_key TEXT UNIQUE NOT NULL,\n password_hash TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n active INTEGER NOT NULL DEFAULT 1\n )\n `)\n await db.execute(`\n CREATE TABLE IF NOT EXISTS jobs (\n id TEXT PRIMARY KEY,\n user_id INTEGER NOT NULL REFERENCES users(id),\n status TEXT NOT NULL DEFAULT 'pending',\n query TEXT NOT NULL,\n options TEXT NOT NULL,\n callback_url TEXT,\n result TEXT,\n error TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n started_at TEXT,\n completed_at TEXT\n )\n `)\n await db.execute(`CREATE INDEX IF NOT EXISTS jobs_user_id ON jobs(user_id)`)\n await db.execute(`CREATE INDEX IF NOT EXISTS jobs_status ON jobs(status)`)\n try { await db.execute(`ALTER TABLE users ADD COLUMN password_hash TEXT`) } catch {}\n try { await db.execute(`ALTER TABLE users ADD COLUMN key_active INTEGER NOT NULL DEFAULT 1`) } catch {}\n\n await db.execute(`\n CREATE TABLE IF NOT EXISTS kpo_jobs (\n id TEXT PRIMARY KEY,\n user_id INTEGER NOT NULL REFERENCES users(id),\n status TEXT NOT NULL,\n entity_name TEXT NOT NULL,\n entity_type TEXT NOT NULL,\n url TEXT,\n request TEXT NOT NULL,\n result TEXT,\n error TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `)\n await db.execute(`\n CREATE TABLE IF NOT EXISTS kpo_phase_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n job_id TEXT NOT NULL REFERENCES kpo_jobs(id),\n phase TEXT NOT NULL,\n output TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `)\n await db.execute(`CREATE INDEX IF NOT EXISTS kpo_jobs_user_id ON kpo_jobs(user_id)`)\n await db.execute(`CREATE INDEX IF NOT EXISTS kpo_jobs_status ON kpo_jobs(status)`)\n await db.execute(`CREATE INDEX IF NOT EXISTS kpo_phase_log_job_id ON kpo_phase_log(job_id)`)\n try { await db.execute(`ALTER TABLE users ADD COLUMN stripe_customer_id TEXT`) } catch {}\n try { await db.execute(`ALTER TABLE users ADD COLUMN balance_mc INTEGER NOT NULL DEFAULT 0`) } catch {}\n await db.execute(`\n CREATE TABLE IF NOT EXISTS ledger (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n user_id INTEGER NOT NULL REFERENCES users(id),\n amount_mc INTEGER NOT NULL,\n operation TEXT NOT NULL,\n description TEXT,\n stripe_pi TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `)\n await db.execute(`CREATE INDEX IF NOT EXISTS ledger_user_id ON ledger(user_id)`)\n await db.execute(`\n CREATE TABLE IF NOT EXISTS site_audit_jobs (\n id TEXT PRIMARY KEY,\n user_id INTEGER,\n status TEXT DEFAULT 'pending',\n client_domain TEXT,\n session_path TEXT,\n request TEXT,\n result TEXT,\n error TEXT,\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now'))\n )\n `)\n await db.execute(`\n CREATE TABLE IF NOT EXISTS site_audit_phase_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n job_id TEXT REFERENCES site_audit_jobs(id),\n phase TEXT,\n completed_at TEXT DEFAULT (datetime('now')),\n output_summary TEXT\n )\n `)\n await db.execute(`CREATE INDEX IF NOT EXISTS site_audit_jobs_user_id ON site_audit_jobs(user_id)`)\n await db.execute(`CREATE INDEX IF NOT EXISTS site_audit_jobs_status ON site_audit_jobs(status)`)\n await db.execute(`CREATE INDEX IF NOT EXISTS site_audit_phase_log_job_id ON site_audit_phase_log(job_id)`)\n}\n\nexport function generateApiKey(): string {\n return 'sk_' + randomBytes(24).toString('hex')\n}\n\nexport interface User {\n id: number\n email: string\n name: string | null\n api_key: string\n key_active: number\n password_hash: string | null\n created_at: string\n active: number\n stripe_customer_id: string | null\n balance_mc: number\n}\n\nexport function hashPassword(password: string): string {\n const salt = randomBytes(16).toString('hex')\n const hash = scryptSync(password, salt, 64)\n return `${salt}:${hash.toString('hex')}`\n}\n\nexport function verifyPassword(password: string, stored: string): boolean {\n const [salt, hash] = stored.split(':')\n const hashBuf = Buffer.from(hash, 'hex')\n const derived = scryptSync(password, salt, 64)\n return timingSafeEqual(hashBuf, derived)\n}\n\nfunction rowToUser(row: Record<string, unknown>): User {\n return {\n id: Number(row.id),\n email: String(row.email),\n name: row.name != null ? String(row.name) : null,\n api_key: String(row.api_key),\n key_active: Number(row.key_active ?? 1),\n password_hash: row.password_hash != null ? String(row.password_hash) : null,\n created_at: String(row.created_at),\n active: Number(row.active),\n stripe_customer_id: row.stripe_customer_id != null ? String(row.stripe_customer_id) : null,\n balance_mc: Number(row.balance_mc ?? 0),\n }\n}\n\nexport async function getUserByEmail(email: string): Promise<User | undefined> {\n const res = await getDb().execute({ sql: 'SELECT * FROM users WHERE email = ? AND active = 1', args: [email] })\n return res.rows[0] ? rowToUser(res.rows[0] as unknown as Record<string, unknown>) : undefined\n}\n\nexport async function getUserByApiKey(api_key: string): Promise<User | undefined> {\n const res = await getDb().execute({ sql: 'SELECT * FROM users WHERE api_key = ? AND active = 1 AND key_active = 1', args: [api_key] })\n return res.rows[0] ? rowToUser(res.rows[0] as unknown as Record<string, unknown>) : undefined\n}\n\nexport async function getUserById(id: number | bigint): Promise<User | undefined> {\n const res = await getDb().execute({ sql: 'SELECT * FROM users WHERE id = ? AND active = 1', args: [id] })\n return res.rows[0] ? rowToUser(res.rows[0] as unknown as Record<string, unknown>) : undefined\n}\n\nexport async function setPassword(id: number | bigint, password: string): Promise<void> {\n await getDb().execute({ sql: 'UPDATE users SET password_hash = ? WHERE id = ?', args: [hashPassword(password), id] })\n}\n\nexport async function getUserStats(userId: number | bigint): Promise<{ total: number; done: number; failed: number; totalQuestions: number; lastUsed: string | null }> {\n const db = getDb()\n const [totR, doneR, failR, tqR, luR] = await Promise.all([\n db.execute({ sql: 'SELECT COUNT(*) as n FROM jobs WHERE user_id = ?', args: [userId] }),\n db.execute({ sql: \"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'done'\", args: [userId] }),\n db.execute({ sql: \"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'failed'\", args: [userId] }),\n db.execute({ sql: \"SELECT COALESCE(SUM(json_extract(result, '$.totalQuestions')), 0) as n FROM jobs WHERE user_id = ? AND status = 'done'\", args: [userId] }),\n db.execute({ sql: 'SELECT MAX(created_at) as t FROM jobs WHERE user_id = ?', args: [userId] }),\n ])\n return {\n total: Number(totR.rows[0]?.n ?? 0),\n done: Number(doneR.rows[0]?.n ?? 0),\n failed: Number(failR.rows[0]?.n ?? 0),\n totalQuestions: Number(tqR.rows[0]?.n ?? 0),\n lastUsed: luR.rows[0]?.t != null ? String(luR.rows[0].t) : null,\n }\n}\n\nexport async function createUser(email: string, name?: string, password?: string): Promise<{ id: number | bigint; email: string; name?: string; api_key: string; password?: string }> {\n const db = getDb()\n const api_key = generateApiKey()\n const plainPassword = password ?? randomBytes(6).toString('hex')\n const password_hash = hashPassword(plainPassword)\n const result = await db.execute({\n sql: 'INSERT INTO users (email, name, api_key, password_hash) VALUES (?, ?, ?, ?)',\n args: [email, name ?? null, api_key, password_hash],\n })\n return { id: result.lastInsertRowid!, email, name, api_key, password: plainPassword }\n}\n\nexport async function rotateApiKey(userId: number | bigint): Promise<string> {\n const newKey = generateApiKey()\n await getDb().execute({ sql: 'UPDATE users SET api_key = ?, key_active = 1 WHERE id = ?', args: [newKey, userId] })\n return newKey\n}\n\nexport async function revokeApiKey(userId: number | bigint): Promise<void> {\n await getDb().execute({ sql: 'UPDATE users SET key_active = 0 WHERE id = ?', args: [userId] })\n}\n\nexport async function listUsers(): Promise<Omit<User, 'api_key'>[]> {\n const res = await getDb().execute('SELECT id, email, name, created_at, active FROM users ORDER BY created_at DESC')\n return res.rows.map(r => rowToUser({ ...r as unknown as Record<string, unknown>, api_key: '', key_active: 1 }))\n}\n\nexport async function deactivateUser(id: number): Promise<void> {\n await getDb().execute({ sql: 'UPDATE users SET active = 0 WHERE id = ?', args: [id] })\n}\n\ninterface RawJob {\n id: string\n user_id: number\n status: string\n query: string\n options: string\n callback_url: string | null\n result: string | null\n error: string | null\n created_at: string\n started_at: string | null\n completed_at: string | null\n}\n\nexport interface Job {\n id: string\n user_id: number\n status: string\n query: string\n options: Record<string, unknown>\n callback_url: string | null\n result: unknown | null\n error: string | null\n created_at: string\n started_at: string | null\n completed_at: string | null\n}\n\nfunction rowToRawJob(row: Record<string, unknown>): RawJob {\n return {\n id: String(row.id),\n user_id: Number(row.user_id),\n status: String(row.status),\n query: String(row.query),\n options: String(row.options),\n callback_url: row.callback_url != null ? String(row.callback_url) : null,\n result: row.result != null ? String(row.result) : null,\n error: row.error != null ? String(row.error) : null,\n created_at: String(row.created_at),\n started_at: row.started_at != null ? String(row.started_at) : null,\n completed_at: row.completed_at != null ? String(row.completed_at) : null,\n }\n}\n\nfunction deserialize(raw: RawJob): Job {\n return {\n ...raw,\n options: JSON.parse(raw.options) as Record<string, unknown>,\n result: raw.result ? JSON.parse(raw.result) : null,\n }\n}\n\nexport async function createJob(userId: number | bigint, query: string, options: object, callbackUrl?: string): Promise<string> {\n const id = randomUUID()\n await getDb().execute({\n sql: 'INSERT INTO jobs (id, user_id, query, options, callback_url) VALUES (?, ?, ?, ?, ?)',\n args: [id, userId, query, JSON.stringify(options), callbackUrl ?? null],\n })\n return id\n}\n\nexport async function createRunningJob(userId: number | bigint, query: string, options: object): Promise<string> {\n const id = randomUUID()\n await getDb().execute({\n sql: `INSERT INTO jobs (id, user_id, query, options, status, started_at) VALUES (?, ?, ?, ?, 'running', datetime('now'))`,\n args: [id, userId, query, JSON.stringify(options)],\n })\n return id\n}\n\nexport async function getJob(id: string, userId?: number | bigint): Promise<Job | undefined> {\n const db = getDb()\n const res = userId\n ? await db.execute({ sql: 'SELECT * FROM jobs WHERE id = ? AND user_id = ?', args: [id, userId] })\n : await db.execute({ sql: 'SELECT * FROM jobs WHERE id = ?', args: [id] })\n return res.rows[0] ? deserialize(rowToRawJob(res.rows[0] as unknown as Record<string, unknown>)) : undefined\n}\n\nexport async function listJobs(userId: number | bigint): Promise<Job[]> {\n const res = await getDb().execute({ sql: 'SELECT * FROM jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50', args: [userId] })\n return res.rows.map(r => deserialize(rowToRawJob(r as unknown as Record<string, unknown>)))\n}\n\nexport async function countActiveUsers(): Promise<number> {\n const res = await getDb().execute(`SELECT COUNT(*) as n FROM users WHERE active = 1`)\n return Number(res.rows[0]?.n ?? 0)\n}\n\nexport async function countActiveJobsForUser(userId: number | bigint): Promise<number> {\n const res = await getDb().execute({\n sql: `SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND (status = 'pending' OR (status = 'running' AND started_at > datetime('now', '-10 minutes')))`,\n args: [userId],\n })\n return Number(res.rows[0]?.n ?? 0)\n}\n\nexport async function countJobsLast7Days(userId: number | bigint): Promise<number> {\n const res = await getDb().execute({\n sql: `SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND created_at > datetime('now', '-7 days')`,\n args: [userId],\n })\n return Number(res.rows[0]?.n ?? 0)\n}\n\nexport async function claimPendingJob(): Promise<RawJob | undefined> {\n const db = getDb()\n const res = await db.execute(`SELECT * FROM jobs WHERE status = 'pending' ORDER BY created_at LIMIT 1`)\n const job = res.rows[0] ? rowToRawJob(res.rows[0] as unknown as Record<string, unknown>) : undefined\n if (!job) return undefined\n const upd = await db.execute({\n sql: `UPDATE jobs SET status = 'running', started_at = datetime('now') WHERE id = ? AND status = 'pending'`,\n args: [job.id],\n })\n return upd.rowsAffected === 0 ? undefined : { ...job, status: 'running' }\n}\n\nexport async function completeJob(id: string, result: object): Promise<void> {\n await getDb().execute({ sql: `UPDATE jobs SET status = 'done', result = ?, completed_at = datetime('now') WHERE id = ?`, args: [JSON.stringify(result), id] })\n}\n\nexport async function failJob(id: string, error: string): Promise<void> {\n await getDb().execute({ sql: `UPDATE jobs SET status = 'failed', error = ?, completed_at = datetime('now') WHERE id = ?`, args: [error, id] })\n}\n\nexport interface KpoJobRow {\n id: string\n user_id: number\n status: string\n entity_name: string\n entity_type: string\n url: string | null\n request: string\n result: string | null\n error: string | null\n created_at: string\n updated_at: string\n}\n\nexport interface KpoPhaseLogRow {\n id: number\n job_id: string\n phase: string\n output: string\n created_at: string\n}\n\nfunction rowToKpoJob(row: Record<string, unknown>): KpoJobRow {\n return {\n id: String(row.id),\n user_id: Number(row.user_id),\n status: String(row.status),\n entity_name: String(row.entity_name),\n entity_type: String(row.entity_type),\n url: row.url != null ? String(row.url) : null,\n request: String(row.request),\n result: row.result != null ? String(row.result) : null,\n error: row.error != null ? String(row.error) : null,\n created_at: String(row.created_at),\n updated_at: String(row.updated_at),\n }\n}\n\nfunction rowToKpoPhaseLog(row: Record<string, unknown>): KpoPhaseLogRow {\n return {\n id: Number(row.id),\n job_id: String(row.job_id),\n phase: String(row.phase),\n output: String(row.output),\n created_at: String(row.created_at),\n }\n}\n\nexport async function createKpoJob(jobId: string, userId: number, entityName: string, entityType: string, request: object, url?: string): Promise<void> {\n await getDb().execute({\n sql: `INSERT INTO kpo_jobs (id, user_id, status, entity_name, entity_type, url, request) VALUES (?, ?, 'pending', ?, ?, ?, ?)`,\n args: [jobId, userId, entityName, entityType, url ?? null, JSON.stringify(request)],\n })\n}\n\nexport async function claimPendingKpoJob(): Promise<KpoJobRow | null> {\n const db = getDb()\n const upd = await db.execute(\n `UPDATE kpo_jobs SET status='running', updated_at=datetime('now') WHERE id = (SELECT id FROM kpo_jobs WHERE status='pending' ORDER BY created_at ASC LIMIT 1) RETURNING *`\n )\n if (upd.rowsAffected === 0) return null\n return upd.rows[0] ? rowToKpoJob(upd.rows[0] as unknown as Record<string, unknown>) : null\n}\n\nexport async function getKpoJob(jobId: string): Promise<KpoJobRow | null> {\n const res = await getDb().execute({ sql: `SELECT * FROM kpo_jobs WHERE id = ?`, args: [jobId] })\n return res.rows[0] ? rowToKpoJob(res.rows[0] as unknown as Record<string, unknown>) : null\n}\n\nexport async function updateKpoJobState(jobId: string, status: string): Promise<void> {\n await getDb().execute({ sql: `UPDATE kpo_jobs SET status = ?, updated_at = datetime('now') WHERE id = ?`, args: [status, jobId] })\n}\n\nexport async function completeKpoJob(jobId: string, result: object): Promise<void> {\n await getDb().execute({ sql: `UPDATE kpo_jobs SET status = 'done', result = ?, updated_at = datetime('now') WHERE id = ?`, args: [JSON.stringify(result), jobId] })\n}\n\nexport async function failKpoJob(jobId: string, error: string): Promise<void> {\n await getDb().execute({ sql: `UPDATE kpo_jobs SET status = 'failed', error = ?, updated_at = datetime('now') WHERE id = ?`, args: [error, jobId] })\n}\n\nexport async function logKpoPhaseComplete(jobId: string, phase: string, output: unknown): Promise<void> {\n await getDb().execute({\n sql: `INSERT INTO kpo_phase_log (job_id, phase, output) VALUES (?, ?, ?)`,\n args: [jobId, phase, JSON.stringify(output)],\n })\n}\n\nexport async function getKpoPhaseLog(jobId: string): Promise<KpoPhaseLogRow[]> {\n const res = await getDb().execute({ sql: `SELECT * FROM kpo_phase_log WHERE job_id = ? ORDER BY created_at ASC`, args: [jobId] })\n return res.rows.map(r => rowToKpoPhaseLog(r as unknown as Record<string, unknown>))\n}\n\nexport async function listKpoJobs(userId?: number): Promise<KpoJobRow[]> {\n const res = userId != null\n ? await getDb().execute({ sql: `SELECT * FROM kpo_jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50`, args: [userId] })\n : await getDb().execute(`SELECT * FROM kpo_jobs ORDER BY created_at DESC LIMIT 50`)\n return res.rows.map(r => rowToKpoJob(r as unknown as Record<string, unknown>))\n}\n\nexport async function getUserByStripeCustomerId(customerId: string): Promise<User | undefined> {\n const res = await getDb().execute({\n sql: 'SELECT * FROM users WHERE stripe_customer_id = ? AND active = 1',\n args: [customerId],\n })\n return res.rows[0] ? rowToUser(res.rows[0] as unknown as Record<string, unknown>) : undefined\n}\n\nexport async function setStripeCustomerId(userId: number, customerId: string): Promise<void> {\n await getDb().execute({\n sql: 'UPDATE users SET stripe_customer_id = ? WHERE id = ?',\n args: [customerId, userId],\n })\n}\n\nexport async function creditMc(\n userId: number,\n mc: number,\n operation: string,\n description?: string,\n stripePaymentIntent?: string,\n): Promise<number> {\n const db = getDb()\n await db.execute({\n sql: 'UPDATE users SET balance_mc = balance_mc + ? WHERE id = ?',\n args: [mc, userId],\n })\n await db.execute({\n sql: 'INSERT INTO ledger (user_id, amount_mc, operation, description, stripe_pi) VALUES (?, ?, ?, ?, ?)',\n args: [userId, mc, operation, description ?? null, stripePaymentIntent ?? null],\n })\n const res = await db.execute({ sql: 'SELECT balance_mc FROM users WHERE id = ?', args: [userId] })\n return Number(res.rows[0]?.balance_mc ?? 0)\n}\n\nexport async function debitMc(\n userId: number,\n mc: number,\n operation: string,\n description?: string,\n): Promise<{ ok: boolean; balance_mc: number }> {\n const db = getDb()\n const res = await db.execute({ sql: 'SELECT balance_mc FROM users WHERE id = ?', args: [userId] })\n const current = Number(res.rows[0]?.balance_mc ?? 0)\n if (current < mc) return { ok: false, balance_mc: current }\n await db.execute({\n sql: 'UPDATE users SET balance_mc = balance_mc - ? WHERE id = ?',\n args: [mc, userId],\n })\n await db.execute({\n sql: 'INSERT INTO ledger (user_id, amount_mc, operation, description) VALUES (?, ?, ?, ?)',\n args: [userId, -mc, operation, description ?? null],\n })\n return { ok: true, balance_mc: current - mc }\n}\n\nexport async function getLedger(userId: number, limit = 50): Promise<LedgerRow[]> {\n const res = await getDb().execute({\n sql: 'SELECT * FROM ledger WHERE user_id = ? ORDER BY created_at DESC LIMIT ?',\n args: [userId, limit],\n })\n return res.rows.map(r => ({\n id: Number(r.id),\n user_id: Number(r.user_id),\n amount_mc: Number(r.amount_mc),\n operation: String(r.operation),\n description: r.description != null ? String(r.description) : null,\n stripe_pi: r.stripe_pi != null ? String(r.stripe_pi) : null,\n created_at: String(r.created_at),\n }))\n}\n\nexport interface LedgerRow {\n id: number\n user_id: number\n amount_mc: number\n operation: string\n description: string | null\n stripe_pi: string | null\n created_at: string\n}\n\nexport const SiteAuditJobRowSchema = z.object({\n id: z.string(),\n user_id: z.number(),\n status: z.string().default('pending'),\n client_domain: z.string(),\n session_path: z.string(),\n request: z.string(),\n result: z.string().nullable(),\n error: z.string().nullable(),\n created_at: z.string(),\n updated_at: z.string(),\n});\nexport type SiteAuditJobRow = z.infer<typeof SiteAuditJobRowSchema>;\n\nexport const SiteAuditPhaseLogRowSchema = z.object({\n id: z.number(),\n job_id: z.string(),\n phase: z.string(),\n completed_at: z.string(),\n output_summary: z.string(),\n});\nexport type SiteAuditPhaseLogRow = z.infer<typeof SiteAuditPhaseLogRowSchema>;\n","import { type Client } from '@libsql/client/http'\nimport { getDb } from '../../api/db.js'\nimport { SiteAuditJobRowSchema } from '../../api/db.js'\nimport type { SiteAuditJobRow } from '../../api/db.js'\nimport type {\n SiteAuditStartRequest,\n SiteAuditJobStatus,\n SiteAuditResult,\n SiteAuditPhase,\n} from './schemas.js'\n\nexport interface ISiteAuditRepository {\n createSiteAuditJob(jobId: string, userId: number, request: SiteAuditStartRequest): Promise<void>\n claimPendingSiteAuditJob(): Promise<SiteAuditJobRow | null>\n getSiteAuditJob(jobId: string): Promise<SiteAuditJobRow | null>\n listSiteAuditJobs(userId?: number): Promise<SiteAuditJobRow[]>\n updateSiteAuditJobState(jobId: string, status: SiteAuditJobStatus): Promise<void>\n completeSiteAuditJob(jobId: string, result: SiteAuditResult): Promise<void>\n failSiteAuditJob(jobId: string, error: string): Promise<void>\n logSiteAuditPhaseComplete(jobId: string, phase: SiteAuditPhase, output: unknown): Promise<void>\n}\n\nfunction rowToSiteAuditJobRow(row: Record<string, unknown>): SiteAuditJobRow {\n return SiteAuditJobRowSchema.parse({\n id: String(row.id),\n user_id: Number(row.user_id),\n status: row.status != null ? String(row.status) : 'pending',\n client_domain: String(row.client_domain),\n session_path: String(row.session_path),\n request: String(row.request),\n result: row.result != null ? String(row.result) : null,\n error: row.error != null ? String(row.error) : null,\n created_at: String(row.created_at),\n updated_at: String(row.updated_at),\n })\n}\n\nexport class SiteAuditRepository implements ISiteAuditRepository {\n private db: Client\n\n constructor() {\n this.db = getDb()\n }\n\n async createSiteAuditJob(jobId: string, userId: number, request: SiteAuditStartRequest): Promise<void> {\n await this.db.execute({\n sql: `INSERT INTO site_audit_jobs\n (id, user_id, status, client_domain, session_path, request, created_at, updated_at)\n VALUES (?, ?, 'pending', ?, ?, ?, datetime('now'), datetime('now'))`,\n args: [\n jobId,\n userId,\n request.clientDomain,\n request.sessionPath,\n JSON.stringify(request),\n ],\n })\n }\n\n async claimPendingSiteAuditJob(): Promise<SiteAuditJobRow | null> {\n const upd = await this.db.execute(\n `UPDATE site_audit_jobs\n SET status = 'running', updated_at = datetime('now')\n WHERE id = (\n SELECT id FROM site_audit_jobs\n WHERE status = 'pending'\n ORDER BY created_at ASC\n LIMIT 1\n )\n RETURNING *`\n )\n if (upd.rowsAffected === 0) return null\n const raw = upd.rows[0]\n if (!raw) return null\n return rowToSiteAuditJobRow(raw as unknown as Record<string, unknown>)\n }\n\n async getSiteAuditJob(jobId: string): Promise<SiteAuditJobRow | null> {\n const res = await this.db.execute({\n sql: `SELECT * FROM site_audit_jobs WHERE id = ?`,\n args: [jobId],\n })\n const raw = res.rows[0]\n if (!raw) return null\n return rowToSiteAuditJobRow(raw as unknown as Record<string, unknown>)\n }\n\n async listSiteAuditJobs(userId?: number): Promise<SiteAuditJobRow[]> {\n const res = userId != null\n ? await this.db.execute({\n sql: `SELECT * FROM site_audit_jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50`,\n args: [userId],\n })\n : await this.db.execute(\n `SELECT * FROM site_audit_jobs ORDER BY created_at DESC LIMIT 50`\n )\n return res.rows.map(r => rowToSiteAuditJobRow(r as unknown as Record<string, unknown>))\n }\n\n async updateSiteAuditJobState(jobId: string, status: SiteAuditJobStatus): Promise<void> {\n await this.db.execute({\n sql: `UPDATE site_audit_jobs SET status = ?, updated_at = datetime('now') WHERE id = ?`,\n args: [status, jobId],\n })\n }\n\n async completeSiteAuditJob(jobId: string, result: SiteAuditResult): Promise<void> {\n await this.db.execute({\n sql: `UPDATE site_audit_jobs\n SET status = 'complete', result = ?, updated_at = datetime('now')\n WHERE id = ?`,\n args: [JSON.stringify(result), jobId],\n })\n }\n\n async failSiteAuditJob(jobId: string, error: string): Promise<void> {\n await this.db.execute({\n sql: `UPDATE site_audit_jobs\n SET status = 'failed', error = ?, updated_at = datetime('now')\n WHERE id = ?`,\n args: [error, jobId],\n })\n }\n\n async logSiteAuditPhaseComplete(jobId: string, phase: SiteAuditPhase, output: unknown): Promise<void> {\n await this.db.execute({\n sql: `INSERT OR IGNORE INTO site_audit_phase_log (job_id, phase, output_summary, completed_at)\n VALUES (?, ?, ?, datetime('now'))`,\n args: [jobId, phase, JSON.stringify(output)],\n }).catch((err: unknown) => {\n console.warn(\n '[site-audit-repository] logSiteAuditPhaseComplete failed:',\n err instanceof Error ? err.message : String(err)\n )\n })\n }\n}\n","import * as childProcess from 'node:child_process';\nimport * as path from 'node:path';\nimport * as util from 'node:util';\nimport { fileURLToPath } from 'node:url';\nimport {\n PythonGraphInputSchema,\n PythonGraphOutputSchema,\n LocationClassifierInputSchema,\n LocationClassifierOutputSchema,\n type PythonGraphInput,\n type PythonGraphOutput,\n type LocationClassifierInput,\n type LocationClassifierOutput,\n} from '../schemas.js';\n\nconst execFile = util.promisify(childProcess.execFile);\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface ISiteAuditPythonRunner {\n runGraphMetrics(input: PythonGraphInput): Promise<PythonGraphOutput>;\n runLocationClassifier(input: LocationClassifierInput): Promise<LocationClassifierOutput>;\n}\n\nexport class SiteAuditPythonRunner implements ISiteAuditPythonRunner {\n private readonly graphMetricsScript: string;\n private readonly locationClassifierScript: string;\n\n constructor() {\n try {\n childProcess.execFileSync('python3', ['-c', 'import networkx']);\n } catch {\n throw new Error('SiteAuditPythonRunner: networkx not available');\n }\n\n this.graphMetricsScript = path.join(__dirname, 'scripts', 'compute_graph_metrics.py');\n this.locationClassifierScript = path.join(__dirname, 'scripts', 'location_classifier.py');\n }\n\n async runGraphMetrics(input: PythonGraphInput): Promise<PythonGraphOutput> {\n const validatedInput = PythonGraphInputSchema.parse(input);\n\n let stdout: string;\n let stderr: string;\n\n try {\n ({ stdout, stderr } = await execFile(\n 'python3',\n [this.graphMetricsScript, '--input', JSON.stringify(validatedInput)],\n { timeout: 120_000 },\n ));\n } catch (err: unknown) {\n const execError = err as { stderr?: string; code?: number | string };\n throw new Error(`python-subprocess-001: ${execError.stderr ?? String(err)}`);\n }\n\n void stderr;\n\n return PythonGraphOutputSchema.parse(JSON.parse(stdout));\n }\n\n async runLocationClassifier(input: LocationClassifierInput): Promise<LocationClassifierOutput> {\n const validatedInput = LocationClassifierInputSchema.parse(input);\n\n let stdout: string;\n let stderr: string;\n\n try {\n ({ stdout, stderr } = await execFile(\n 'python3',\n [this.locationClassifierScript, '--input', JSON.stringify(validatedInput)],\n { timeout: 120_000 },\n ));\n } catch (err: unknown) {\n const execError = err as { stderr?: string; code?: number | string };\n throw new Error(`python-subprocess-001: ${execError.stderr ?? String(err)}`);\n }\n\n void stderr;\n\n return LocationClassifierOutputSchema.parse(JSON.parse(stdout));\n }\n}\n","import { DeepInfraLlmClient, OpenRouterLlmClient, FallbackLlmClient } from '../../lib/llm-parse-with-retry.js';\nimport { FetchHttpClient } from '../../lib/http-client.js';\nimport { type ISiteAuditService, SiteAuditService } from './site-audit-service.js';\nimport { SiteAuditRepository } from './site-audit-repository.js';\nimport { SiteAuditPythonRunner } from './python/graph-runner.js';\n\nexport function makeSiteAuditService(): ISiteAuditService {\n const deepInfraKey = process.env['DEEPINFRA_API_KEY'];\n if (!deepInfraKey) throw new Error('DEEPINFRA_API_KEY is required');\n const primary = new DeepInfraLlmClient(deepInfraKey);\n const llm = process.env['OPENROUTER_API_KEY']\n ? new FallbackLlmClient(primary, new OpenRouterLlmClient(process.env['OPENROUTER_API_KEY']))\n : primary;\n\n const repo = new SiteAuditRepository();\n const http = new FetchHttpClient();\n const python = new SiteAuditPythonRunner();\n\n return new SiteAuditService({ repo, llm, http, python });\n}\n","import pLimit from 'p-limit';\nimport { type ISiteAuditService, type CompareRecommendOutput } from './site-audit-service.js';\nimport {\n type SiteAuditPhase,\n SiteAuditIngestPayloadSchema,\n SiteAuditBuildGraphPayloadSchema,\n SiteAuditClassifyPayloadSchema,\n SiteAuditComparePayloadSchema,\n SiteAuditSynthesizePayloadSchema,\n} from './schemas.js';\nimport { applyGuardrailRules, type GuardrailFlagName } from '../../lib/site-architecture-auditor/rules.js';\n\nexport async function dispatchSiteAuditPhase(\n service: ISiteAuditService,\n phase: SiteAuditPhase,\n raw: unknown,\n): Promise<void> {\n switch (phase) {\n case 'phase1-ingest':\n return handleIngestPhase(service, raw);\n case 'phase2-build-graph':\n return handleBuildGraphPhase(service, raw);\n case 'phase3-classify':\n return handleClassifyPhase(service, raw);\n case 'phase4-compare':\n return handleComparePhase(service, raw);\n case 'phase5-synthesize':\n return handleSynthesizePhase(service, raw);\n default: {\n const _exhaustive: never = phase;\n throw new Error('Unknown phase: ' + String(_exhaustive));\n }\n }\n}\n\nexport async function handleIngestPhase(\n service: ISiteAuditService,\n raw: unknown,\n): Promise<void> {\n const payload = SiteAuditIngestPayloadSchema.parse(raw);\n await service.runIngestPhase(payload.jobId, payload);\n await service.runEnrichPhase(payload.jobId, payload);\n}\n\nexport async function handleBuildGraphPhase(\n service: ISiteAuditService,\n raw: unknown,\n): Promise<void> {\n const payload = SiteAuditBuildGraphPayloadSchema.parse(raw);\n const limit = pLimit(3);\n const tasks = [\n limit(() => service.runBuildGraphPhase(payload.jobId, payload)),\n ];\n const results = await Promise.allSettled(tasks);\n for (const result of results) {\n if (result.status === 'rejected') {\n console.warn(\n '[phases] handleBuildGraphPhase: phase failed for job',\n payload.jobId,\n result.reason instanceof Error ? result.reason.message : String(result.reason),\n );\n }\n }\n}\n\nexport async function handleClassifyPhase(\n service: ISiteAuditService,\n raw: unknown,\n): Promise<void> {\n const payload = SiteAuditClassifyPayloadSchema.parse(raw);\n const limit = pLimit(3);\n const tasks = [\n limit(() => service.runClassifyPhase(payload.jobId, payload)),\n ];\n const results = await Promise.allSettled(tasks);\n for (const result of results) {\n if (result.status === 'rejected') {\n console.warn(\n '[phases] handleClassifyPhase: phase failed for job',\n payload.jobId,\n result.reason instanceof Error ? result.reason.message : String(result.reason),\n );\n }\n }\n}\n\nexport async function handleComparePhase(\n service: ISiteAuditService,\n raw: unknown,\n): Promise<void> {\n const payload = SiteAuditComparePayloadSchema.parse(raw);\n const compareResult: CompareRecommendOutput = await service.runComparePhase(payload.jobId, payload);\n\n const rawRecommendations: unknown[] = compareResult.linkRecommendations ?? [];\n\n const resolveFlagsStub = (_item: unknown, _candidates: GuardrailFlagName[]): GuardrailFlagName[] => {\n return [];\n };\n\n const guardrailResult = applyGuardrailRules(rawRecommendations, { resolveFlags: resolveFlagsStub });\n console.warn(\n '[phases] handleComparePhase: guardrail check complete — passed:',\n guardrailResult.passed.length,\n 'flagged:',\n guardrailResult.flagged.length,\n '(context-dependent flags require site-graph state not yet exposed by runComparePhase)',\n );\n}\n\nexport async function handleSynthesizePhase(\n service: ISiteAuditService,\n raw: unknown,\n): Promise<void> {\n const payload = SiteAuditSynthesizePayloadSchema.parse(raw);\n await service.runSynthesizePhase(payload.jobId, payload);\n}\n","import { type InngestFunction } from 'inngest';\nimport { inngest } from '../client.js';\nimport { makeSiteAuditService } from '../../services/site-architecture-auditor/factory.js';\nimport { dispatchSiteAuditPhase } from '../../services/site-architecture-auditor/phases.js';\nimport { type SiteAuditPhase } from '../../services/site-architecture-auditor/schemas.js';\n\nexport const siteAuditFn: InngestFunction<any, any, any, any, any> = inngest.createFunction(\n { id: 'site-audit', triggers: [{ event: 'site-architecture-auditor/audit.requested' }] },\n async ({ event, step }: { event: { data: { phase: SiteAuditPhase; payload: unknown } }; step: any }) => {\n const { phase, payload } = event.data;\n\n await step.run('dispatch-phase', async () => {\n const service = makeSiteAuditService();\n await dispatchSiteAuditPhase(service, phase, payload);\n });\n\n return { phase, status: 'done' };\n },\n);\n","import { createMiddleware } from 'hono/factory'\nimport { getUserByApiKey } from './db.js'\n\nexport type SiteAuditEnv = {\n Variables: {\n siteAuditUserId: number\n siteAuditEmail?: string\n }\n}\n\nexport const siteAuditAuth = createMiddleware<SiteAuditEnv>(async (c, next) => {\n const apiKey = c.req.header('x-api-key')\n\n if (apiKey) {\n const user = await getUserByApiKey(apiKey)\n if (!user) return c.json({ error: 'Unauthorized' }, 401)\n c.set('siteAuditUserId', user.id)\n return next()\n }\n\n return c.json({ error: 'Unauthorized' }, 401)\n})\n","import path from 'node:path';\nimport os from 'node:os';\nimport { Hono } from 'hono';\nimport { ZodError } from 'zod';\nimport { siteAuditAuth, type SiteAuditEnv } from './site-audit-middleware.js';\nimport { makeSiteAuditService } from '../services/site-architecture-auditor/factory.js';\nimport { dispatchSiteAuditPhase } from '../services/site-architecture-auditor/phases.js';\nimport {\n SiteAuditStartRequestSchema,\n SiteAuditIngestRequestSchema,\n SiteAuditBuildGraphRequestSchema,\n SiteAuditClassifyRequestSchema,\n SiteAuditCompareRequestSchema,\n SiteAuditScoreRequestSchema,\n SiteAuditReportRequestSchema,\n} from '../services/site-architecture-auditor/schemas.js';\n\nexport const siteAuditApp = new Hono<SiteAuditEnv>();\n\nsiteAuditApp.onError((err, c) => {\n if (err instanceof ZodError) {\n return c.json({ error: 'Invalid request body', issues: err.issues }, 400);\n }\n const msg = err instanceof Error ? err.message : String(err);\n return c.json({ error: msg }, 500);\n});\n\nsiteAuditApp.use('*', siteAuditAuth);\n\nfunction isPathInside(root: string, target: string): boolean {\n const relative = path.relative(root, target);\n return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));\n}\n\nsiteAuditApp.post('/audit', async (c) => {\n const body = SiteAuditStartRequestSchema.parse(await c.req.json());\n\n const allowedRoot = path.resolve(process.env['SESSION_ROOT'] ?? os.tmpdir());\n const sessionPath = path.resolve(body.sessionPath);\n if (!isPathInside(allowedRoot, sessionPath)) {\n return c.json({ error: 'sessionPath must be inside the configured session root' }, 400);\n }\n\n const pathFields: Array<string | undefined> = [\n body.sessionPath,\n body.sfInternalPath,\n body.sfInlinksPath,\n body.sfOutlinksPath,\n body.sitemapPath,\n body.competitorDomainsCsvPath,\n body.visualSitemapsPath,\n body.gscPath,\n body.ga4Path,\n body.ahrefsPath,\n ];\n\n for (const filePath of pathFields) {\n if (filePath != null && !isPathInside(allowedRoot, path.resolve(filePath))) {\n return c.json({ error: 'Path traversal attempt' }, 400);\n }\n }\n\n const userId = c.get('siteAuditUserId');\n const service = makeSiteAuditService();\n const jobId = await service.startAudit(userId, body);\n\n void dispatchSiteAuditPhase(service, 'phase1-ingest', { jobId, request: body }).catch(\n (err: unknown) => {\n console.error(\n '[site-audit-routes] phase1-ingest dispatch failed for job',\n jobId,\n err instanceof Error ? err.message : String(err),\n );\n },\n );\n\n return c.json({ jobId }, 202);\n});\n\nsiteAuditApp.post('/ingest', async (c) => {\n const body = SiteAuditIngestRequestSchema.parse(await c.req.json());\n const service = makeSiteAuditService();\n const job = await service.getJob(body.jobId);\n if (!job) return c.json({ error: 'Not found' }, 404);\n if (job.user_id !== c.get('siteAuditUserId')) return c.json({ error: 'Not found' }, 404);\n\n void dispatchSiteAuditPhase(service, 'phase1-ingest', {\n jobId: body.jobId,\n request: JSON.parse(job.request) as unknown,\n }).catch((err: unknown) => {\n console.error(\n '[site-audit-routes] phase1-ingest re-dispatch failed for job',\n body.jobId,\n err instanceof Error ? err.message : String(err),\n );\n });\n\n return c.json({ jobId: body.jobId }, 202);\n});\n\nsiteAuditApp.post('/build-graph', async (c) => {\n const body = SiteAuditBuildGraphRequestSchema.parse(await c.req.json());\n const service = makeSiteAuditService();\n const job = await service.getJob(body.jobId);\n if (!job) return c.json({ error: 'Not found' }, 404);\n if (job.user_id !== c.get('siteAuditUserId')) return c.json({ error: 'Not found' }, 404);\n\n void dispatchSiteAuditPhase(service, 'phase2-build-graph', { jobId: body.jobId }).catch(\n (err: unknown) => {\n console.error(\n '[site-audit-routes] phase2-build-graph failed for job',\n body.jobId,\n err instanceof Error ? err.message : String(err),\n );\n },\n );\n\n return c.json({ jobId: body.jobId }, 202);\n});\n\nsiteAuditApp.post('/classify', async (c) => {\n const body = SiteAuditClassifyRequestSchema.parse(await c.req.json());\n const service = makeSiteAuditService();\n const job = await service.getJob(body.jobId);\n if (!job) return c.json({ error: 'Not found' }, 404);\n if (job.user_id !== c.get('siteAuditUserId')) return c.json({ error: 'Not found' }, 404);\n\n void dispatchSiteAuditPhase(service, 'phase3-classify', { jobId: body.jobId }).catch(\n (err: unknown) => {\n console.error(\n '[site-audit-routes] phase3-classify failed for job',\n body.jobId,\n err instanceof Error ? err.message : String(err),\n );\n },\n );\n\n return c.json({ jobId: body.jobId }, 202);\n});\n\nsiteAuditApp.post('/compare', async (c) => {\n const body = SiteAuditCompareRequestSchema.parse(await c.req.json());\n const service = makeSiteAuditService();\n const job = await service.getJob(body.jobId);\n if (!job) return c.json({ error: 'Not found' }, 404);\n if (job.user_id !== c.get('siteAuditUserId')) return c.json({ error: 'Not found' }, 404);\n\n void dispatchSiteAuditPhase(service, 'phase4-compare', { jobId: body.jobId }).catch(\n (err: unknown) => {\n console.error(\n '[site-audit-routes] phase4-compare failed for job',\n body.jobId,\n err instanceof Error ? err.message : String(err),\n );\n },\n );\n\n return c.json({ jobId: body.jobId }, 202);\n});\n\nsiteAuditApp.post('/score', async (c) => {\n const body = SiteAuditScoreRequestSchema.parse(await c.req.json());\n const service = makeSiteAuditService();\n const job = await service.getJob(body.jobId);\n if (!job) return c.json({ error: 'Not found' }, 404);\n if (job.user_id !== c.get('siteAuditUserId')) return c.json({ error: 'Not found' }, 404);\n\n void dispatchSiteAuditPhase(service, 'phase5-synthesize', {\n jobId: body.jobId,\n scoringOnly: true,\n reportOnly: false,\n }).catch((err: unknown) => {\n console.error(\n '[site-audit-routes] phase5-synthesize(scoringOnly) failed for job',\n body.jobId,\n err instanceof Error ? err.message : String(err),\n );\n });\n\n return c.json({ jobId: body.jobId }, 202);\n});\n\nsiteAuditApp.post('/report', async (c) => {\n const body = SiteAuditReportRequestSchema.parse(await c.req.json());\n const service = makeSiteAuditService();\n const job = await service.getJob(body.jobId);\n if (!job) return c.json({ error: 'Not found' }, 404);\n if (job.user_id !== c.get('siteAuditUserId')) return c.json({ error: 'Not found' }, 404);\n\n void dispatchSiteAuditPhase(service, 'phase5-synthesize', {\n jobId: body.jobId,\n scoringOnly: false,\n reportOnly: true,\n }).catch((err: unknown) => {\n console.error(\n '[site-audit-routes] phase5-synthesize(reportOnly) failed for job',\n body.jobId,\n err instanceof Error ? err.message : String(err),\n );\n });\n\n return c.json({ jobId: body.jobId }, 202);\n});\n\nsiteAuditApp.get('/jobs/:id', async (c) => {\n const jobId = c.req.param('id');\n const userId = c.get('siteAuditUserId');\n const service = makeSiteAuditService();\n const job = await service.getJob(jobId);\n if (!job) return c.json({ error: 'Not found' }, 404);\n if (job.user_id !== userId) return c.json({ error: 'Not found' }, 404);\n return c.json(job);\n});\n\nsiteAuditApp.get('/jobs', async (c) => {\n const userId = c.get('siteAuditUserId');\n const service = makeSiteAuditService();\n const jobs = await service.getJobsForUser(userId);\n return c.json(jobs);\n});\n","export const MC_COSTS = {\n serp: 1_000,\n paa: 1_000,\n page_scrape: 2_000,\n yt_channel: 1_000,\n fb_ad: 2_000,\n maps_place: 2_000,\n url_map: 500,\n transcription: 250,\n} as const\n\nexport type McCostKey = keyof typeof MC_COSTS\n\nexport const CREDIT_COST_CATALOG: Array<{\n key: McCostKey\n label: string\n aliases: string[]\n credits: number\n unit: string\n notes?: string\n}> = [\n {\n key: 'serp',\n label: 'Search SERP',\n aliases: ['search_serp', 'serp', 'google search', 'organic results'],\n credits: mcToCredits(MC_COSTS.serp),\n unit: 'per search',\n },\n {\n key: 'paa',\n label: 'PAA harvest',\n aliases: ['harvest_paa', 'paa', 'people also ask', 'questions'],\n credits: mcToCredits(MC_COSTS.paa),\n unit: 'per crawl',\n },\n {\n key: 'page_scrape',\n label: 'URL extraction',\n aliases: ['extract_url', 'page scrape', 'url scrape', 'single page'],\n credits: mcToCredits(MC_COSTS.page_scrape),\n unit: 'per URL',\n },\n {\n key: 'url_map',\n label: 'Site URL map',\n aliases: ['map_site_urls', 'url map', 'site map', 'crawl urls'],\n credits: mcToCredits(MC_COSTS.url_map),\n unit: 'per discovered URL',\n notes: 'A 10-URL hold is taken first, then unused credits are refunded.',\n },\n {\n key: 'page_scrape',\n label: 'Site extraction',\n aliases: ['extract_site', 'site extraction', 'full site scrape'],\n credits: mcToCredits(MC_COSTS.page_scrape),\n unit: 'per extracted page',\n notes: 'A 10-page hold is taken first, then unused credits are refunded.',\n },\n {\n key: 'yt_channel',\n label: 'YouTube harvest',\n aliases: ['youtube_harvest', 'youtube search', 'youtube channel'],\n credits: mcToCredits(MC_COSTS.yt_channel),\n unit: 'per harvest',\n },\n {\n key: 'transcription',\n label: 'YouTube transcription',\n aliases: ['youtube_transcribe', 'youtube transcript', 'transcription'],\n credits: mcToCredits(MC_COSTS.transcription),\n unit: 'per started minute',\n notes: 'A duration hold is taken first, then unused credits are refunded.',\n },\n {\n key: 'fb_ad',\n label: 'Facebook ad intel',\n aliases: ['facebook_page_intel', 'facebook_ad_search', 'facebook ads', 'fb ads'],\n credits: mcToCredits(MC_COSTS.fb_ad),\n unit: 'per call',\n },\n {\n key: 'maps_place',\n label: 'Google Maps place intel',\n aliases: ['maps_place_intel', 'google maps', 'maps reviews', 'reviews', 'place intel'],\n credits: mcToCredits(MC_COSTS.maps_place),\n unit: 'per place lookup',\n notes: 'Includes optional review cards when includeReviews is true.',\n },\n]\n\nexport const FREE_SIGNUP_MC = 2_200_000\n\nexport const BALANCE_PRICE_IDS: Record<string, number> = {\n 'price_1TZx6rS8aAcsk3TGNMc1Vgpo': 11_000_000,\n 'price_1TZx6sS8aAcsk3TGxgqB7khO': 27_500_000,\n 'price_1TZx6tS8aAcsk3TG8PnJqHlG': 60_500_000,\n 'price_1TZx6tS8aAcsk3TGNgRMpy0e': 121_000_000,\n}\n\nexport const BALANCE_PACK_LABELS: Record<string, string> = {\n 'price_1TZx6rS8aAcsk3TGNMc1Vgpo': '$10',\n 'price_1TZx6sS8aAcsk3TGxgqB7khO': '$25',\n 'price_1TZx6tS8aAcsk3TG8PnJqHlG': '$50',\n 'price_1TZx6tS8aAcsk3TGNgRMpy0e': '$100',\n}\n\nexport function mcToCredits(mc: number): number {\n return mc / 1_000\n}\n\nexport function insufficientBalanceResponse(balanceMc: number, requiredMc: number) {\n const topupUrl = process.env.TOPUP_URL ?? 'https://mcpscraper.dev/billing'\n return {\n error: 'insufficient_balance',\n balance_credits: mcToCredits(balanceMc),\n required_credits: mcToCredits(requiredMc),\n topup_url: topupUrl,\n }\n}\n","import { z } from 'zod'\n\nexport const YouTubeHarvestOptionsSchema = z.object({\n mode: z.enum(['search', 'channel']),\n query: z.string().optional(),\n channelHandle: z.string().optional(),\n maxVideos: z.number().int().min(1).max(5000).default(100),\n downloadMp3: z.boolean().default(false),\n outputDir: z.string().default('./yt-output'),\n kernelApiKey: z.string().optional(),\n headless: z.boolean().default(false),\n}).refine(\n (o) => o.mode === 'search' ? !!o.query : !!o.channelHandle,\n { message: 'search mode requires query; channel mode requires channelHandle' },\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 { 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","import type { Page } from 'playwright'\nimport type { IBrowserDriver } from '../driver/IBrowserDriver.js'\nimport type { IYTProgressReporter } from './YTProgressReporter.js'\nimport { CaptchaError } from '../errors.js'\nimport type { DriverConfig } from '../types.js'\nimport type {\n YTVideoResult, YTChannelResult, YTChannelMeta,\n YTHarvestResult, YTHarvestStats, YTInnerTubeContext, YouTubeHarvestOptions,\n} from './types.js'\n\nexport class YouTubeExtractor {\n constructor(\n private readonly driver: IBrowserDriver,\n private readonly reporter: IYTProgressReporter,\n ) {}\n\n private async waitForInitialData(page: Page): Promise<unknown> {\n try {\n await page.waitForFunction(\n () => !!(window as unknown as { ytInitialData?: unknown }).ytInitialData,\n { timeout: 20_000 },\n )\n } catch {\n const url = page.url()\n const title = await page.title().catch(() => '')\n const isBlocked = /consent\\.youtube\\.|accounts\\.google\\.|sorry\\.google\\./i.test(url)\n || /before you continue|sign in|unusual traffic|are you a robot/i.test(title)\n if (isBlocked) {\n throw new CaptchaError('YouTube blocked the Kernel session — retrying with a fresh session.')\n }\n throw new CaptchaError(`ytInitialData not found after 20s (url=${url}, title=\"${title}\") — retrying.`)\n }\n return page.evaluate(() => (window as unknown as { ytInitialData: unknown }).ytInitialData)\n }\n\n private async getInnerTubeContext(page: Page): Promise<YTInnerTubeContext> {\n return page.evaluate(() => {\n const cfg = (window as unknown as { ytcfg?: { data_?: Record<string, unknown> } }).ytcfg?.data_ ?? {}\n return {\n clientName: (cfg.INNERTUBE_CLIENT_NAME as string | undefined) ?? 'WEB',\n clientVersion: (cfg.INNERTUBE_CLIENT_VERSION as string | undefined) ?? '2.20260515.01.00',\n hl: (cfg.HL as string | undefined) ?? 'en',\n gl: (cfg.GL as string | undefined) ?? 'US',\n visitorData: (cfg.VISITOR_DATA as string | undefined) ?? '',\n }\n })\n }\n\n private parseVideoRenderer(v: Record<string, unknown>): YTVideoResult | null {\n const videoId = v.videoId as string | undefined\n if (!videoId) return null\n\n const titleRuns = (v.title as { runs?: Array<{ text: string }> } | undefined)?.runs ?? []\n const title = titleRuns[0]?.text ?? ''\n\n const ownerRuns = (v.ownerText as { runs?: Array<{\n text: string\n navigationEndpoint?: { browseEndpoint?: { browseId?: string; canonicalBaseUrl?: string } }\n }> } | undefined)?.runs ?? []\n const channelName = ownerRuns[0]?.text ?? ''\n const channelId = ownerRuns[0]?.navigationEndpoint?.browseEndpoint?.browseId ?? null\n const channelHandle = ownerRuns[0]?.navigationEndpoint?.browseEndpoint?.canonicalBaseUrl ?? null\n\n const lengthText = v.lengthText as { simpleText?: string } | undefined\n const viewCount = v.viewCountText as { simpleText?: string } | undefined\n const publishedAt = v.publishedTimeText as { simpleText?: string } | undefined\n\n const snippetRuns = (v.detailedMetadataSnippets as Array<{ snippetText?: { runs?: Array<{ text: string }> } }> | undefined)\n ?.[0]?.snippetText?.runs?.map((r) => r.text).join('') ?? null\n\n const thumbs = (v.thumbnail as { thumbnails?: Array<{ url: string }> } | undefined)?.thumbnails ?? []\n const thumbnailUrl = thumbs[thumbs.length - 1]?.url ?? null\n\n return {\n videoId,\n url: `https://www.youtube.com/watch?v=${videoId}`,\n title,\n channelName,\n channelId,\n channelHandle,\n duration: lengthText?.simpleText ?? null,\n views: viewCount?.simpleText ?? null,\n publishedAt: publishedAt?.simpleText ?? null,\n descriptionSnippet: snippetRuns,\n thumbnailUrl,\n }\n }\n\n private parseLockupViewModel(lockup: Record<string, unknown>): YTVideoResult | null {\n const videoId = lockup.contentId as string | undefined\n if (!videoId || (lockup.contentType as string | undefined) !== 'LOCKUP_CONTENT_TYPE_VIDEO') return null\n\n const meta = lockup.metadata as {\n lockupMetadataViewModel?: {\n title?: { content?: string }\n metadata?: {\n contentMetadataViewModel?: {\n metadataRows?: Array<{ metadataParts?: Array<{ text?: { content?: string } }> }>\n }\n }\n }\n } | undefined\n const vmMeta = meta?.lockupMetadataViewModel\n const title = vmMeta?.title?.content ?? ''\n const rows = vmMeta?.metadata?.contentMetadataViewModel?.metadataRows ?? []\n const parts = rows[0]?.metadataParts ?? []\n\n const thumbVM = (lockup.contentImage as Record<string, unknown> | undefined)\n ?.thumbnailViewModel as Record<string, unknown> | undefined\n const overlays = (thumbVM?.overlays as unknown[] | undefined) ?? []\n const badges = (\n (overlays[0] as Record<string, unknown> | undefined)\n ?.thumbnailBottomOverlayViewModel as Record<string, unknown> | undefined\n )?.badges as unknown[] | undefined\n const duration = (\n (badges?.[0] as Record<string, unknown> | undefined)\n ?.thumbnailBadgeViewModel as Record<string, unknown> | undefined\n )?.text as string | null ?? null\n\n return {\n videoId,\n url: `https://www.youtube.com/watch?v=${videoId}`,\n title,\n channelName: '',\n channelId: null,\n channelHandle: null,\n duration,\n views: parts[0]?.text?.content ?? null,\n publishedAt: parts[1]?.text?.content ?? null,\n descriptionSnippet: null,\n thumbnailUrl: null,\n }\n }\n\n private parseChannelRenderer(c: Record<string, unknown>): YTChannelResult | null {\n const channelId = c.channelId as string | undefined\n if (!channelId) return null\n\n const titleText = (c.title as { simpleText?: string } | undefined)?.simpleText ?? ''\n const subsText = (c.subscriberCountText as { simpleText?: string } | undefined)?.simpleText ?? null\n const descText = (c.descriptionSnippet as { runs?: Array<{ text: string }> } | undefined)\n ?.runs?.map((r) => r.text).join('') ?? null\n const canonical = (c.navigationEndpoint as { browseEndpoint?: { canonicalBaseUrl?: string } } | undefined)\n ?.browseEndpoint?.canonicalBaseUrl ?? null\n\n return {\n channelId,\n channelHandle: canonical,\n title: titleText,\n subscriberCount: subsText,\n description: descText,\n channelUrl: `https://www.youtube.com${canonical ?? '/channel/' + channelId}`,\n }\n }\n\n private extractContinuationToken(items: unknown[]): string | null {\n for (const item of items) {\n const rec = item as Record<string, unknown>\n const cont = rec.continuationItemRenderer as Record<string, unknown> | undefined\n if (!cont) continue\n const ep = cont.continuationEndpoint as Record<string, unknown> | undefined\n const cmd = ep?.continuationCommand as Record<string, unknown> | undefined\n if (cmd?.token) return cmd.token as string\n }\n return null\n }\n\n async extractSearchResults(page: Page): Promise<{\n videos: YTVideoResult[]\n channels: YTChannelResult[]\n continuationToken: string | null\n }> {\n const data = await this.waitForInitialData(page)\n const d = data as Record<string, unknown>\n\n const slr = (\n (d.contents as Record<string, unknown> | undefined)\n ?.twoColumnSearchResultsRenderer as Record<string, unknown> | undefined\n )?.primaryContents\n ? (\n (\n (d.contents as Record<string, unknown>)\n .twoColumnSearchResultsRenderer as Record<string, unknown>\n ).primaryContents as Record<string, unknown>\n ).sectionListRenderer as Record<string, unknown> | undefined\n : undefined\n\n const sections: unknown[] = (slr?.contents as unknown[] | undefined) ?? []\n const videos: YTVideoResult[] = []\n const channels: YTChannelResult[] = []\n\n for (const section of sections) {\n const contents: unknown[] = (\n (section as Record<string, unknown>).itemSectionRenderer as Record<string, unknown> | undefined\n )?.contents as unknown[] ?? []\n for (const item of contents) {\n const rec = item as Record<string, unknown>\n if (rec.videoRenderer) {\n const v = this.parseVideoRenderer(rec.videoRenderer as Record<string, unknown>)\n if (v) videos.push(v)\n }\n if (rec.channelRenderer) {\n const c = this.parseChannelRenderer(rec.channelRenderer as Record<string, unknown>)\n if (c) channels.push(c)\n }\n }\n }\n\n return { videos, channels, continuationToken: this.extractContinuationToken(sections) }\n }\n\n async extractChannelVideos(page: Page): Promise<{\n videos: YTVideoResult[]\n channelMeta: YTChannelMeta | null\n continuationToken: string | null\n }> {\n const data = await this.waitForInitialData(page)\n const d = data as Record<string, unknown>\n\n const channelMetaRaw = (\n (d.metadata as Record<string, unknown> | undefined)?.channelMetadataRenderer\n ) as Record<string, unknown> | undefined\n\n const channelMeta: YTChannelMeta | null = channelMetaRaw\n ? {\n externalId: (channelMetaRaw.externalId as string | undefined) ?? '',\n title: (channelMetaRaw.title as string | undefined) ?? '',\n description: (channelMetaRaw.description as string | undefined) ?? null,\n channelUrl: (channelMetaRaw.channelUrl as string | undefined) ?? '',\n vanityChannelUrl: (channelMetaRaw.vanityChannelUrl as string | undefined) ?? null,\n rssUrl: (channelMetaRaw.rssUrl as string | undefined) ?? null,\n }\n : null\n\n const tabs: unknown[] = (\n (d.contents as Record<string, unknown> | undefined)\n ?.twoColumnBrowseResultsRenderer as Record<string, unknown> | undefined\n )?.tabs as unknown[] ?? []\n\n const videosTab = tabs.find(\n (t) => ((t as Record<string, unknown>).tabRenderer as Record<string, unknown> | undefined)?.title === 'Videos',\n ) as Record<string, unknown> | undefined\n\n const richGrid = (\n (videosTab?.tabRenderer as Record<string, unknown> | undefined)\n ?.content as Record<string, unknown> | undefined\n )?.richGridRenderer as Record<string, unknown> | undefined\n\n const gridContents: unknown[] = (richGrid?.contents as unknown[] | undefined) ?? []\n\n const videos: YTVideoResult[] = []\n for (const item of gridContents) {\n const rec = item as Record<string, unknown>\n const inner = (rec.richItemRenderer as Record<string, unknown> | undefined)\n ?.content as Record<string, unknown> | undefined\n if (inner?.lockupViewModel) {\n const v = this.parseLockupViewModel(inner.lockupViewModel as Record<string, unknown>)\n if (v) videos.push(v)\n }\n }\n\n return { videos, channelMeta, continuationToken: this.extractContinuationToken(gridContents) }\n }\n\n private async fetchContinuation(\n page: Page,\n endpoint: 'search' | 'browse',\n contToken: string,\n context: YTInnerTubeContext,\n ): Promise<{ items: unknown[]; nextToken: string | null }> {\n const result = await page.evaluate(\n async ({ ep, token, ctx }) => {\n const body = {\n continuation: token,\n context: {\n client: {\n clientName: ctx.clientName,\n clientVersion: ctx.clientVersion,\n hl: ctx.hl,\n gl: ctx.gl,\n visitorData: ctx.visitorData,\n },\n },\n }\n const resp = await fetch(`/youtubei/v1/${ep}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-YouTube-Client-Name': '1',\n 'X-YouTube-Client-Version': ctx.clientVersion,\n },\n body: JSON.stringify(body),\n })\n return resp.json()\n },\n { ep: endpoint, token: contToken, ctx: context },\n ) as Record<string, unknown>\n\n const actionKey = endpoint === 'search' ? 'onResponseReceivedCommands' : 'onResponseReceivedActions'\n const actions = (result[actionKey] as unknown[] | undefined) ?? []\n const firstAction = (actions[0] as Record<string, unknown> | undefined) ?? {}\n const appendAction = firstAction.appendContinuationItemsAction as Record<string, unknown> | undefined\n const items: unknown[] = (appendAction?.continuationItems as unknown[] | undefined) ?? []\n\n return { items, nextToken: this.extractContinuationToken(items) }\n }\n\n private parseSearchContinuationItems(items: unknown[]): { videos: YTVideoResult[]; channels: YTChannelResult[] } {\n const videos: YTVideoResult[] = []\n const channels: YTChannelResult[] = []\n for (const item of items) {\n const rec = item as Record<string, unknown>\n const contents: unknown[] = (\n rec.itemSectionRenderer as Record<string, unknown> | undefined\n )?.contents as unknown[] ?? [rec]\n for (const c of contents) {\n const ci = c as Record<string, unknown>\n if (ci.videoRenderer) {\n const v = this.parseVideoRenderer(ci.videoRenderer as Record<string, unknown>)\n if (v) videos.push(v)\n }\n if (ci.channelRenderer) {\n const ch = this.parseChannelRenderer(ci.channelRenderer as Record<string, unknown>)\n if (ch) channels.push(ch)\n }\n }\n }\n return { videos, channels }\n }\n\n private parseChannelContinuationItems(items: unknown[]): YTVideoResult[] {\n const videos: YTVideoResult[] = []\n for (const item of items) {\n const rec = item as Record<string, unknown>\n const inner = (rec.richItemRenderer as Record<string, unknown> | undefined)\n ?.content as Record<string, unknown> | undefined\n if (inner?.videoRenderer) {\n const v = this.parseVideoRenderer(inner.videoRenderer as Record<string, unknown>)\n if (v) videos.push(v)\n }\n if (inner?.lockupViewModel) {\n const v = this.parseLockupViewModel(inner.lockupViewModel as Record<string, unknown>)\n if (v) videos.push(v)\n }\n }\n return videos\n }\n\n async extract(options: YouTubeHarvestOptions): Promise<YTHarvestResult> {\n const startMs = Date.now()\n const config: DriverConfig = {\n headless: options.headless,\n kernelApiKey: options.kernelApiKey,\n viewport: { width: 1280, height: 800 },\n locale: 'en-US',\n }\n\n try {\n await this.driver.launch(config)\n const page = this.driver.getPage() as Page\n\n const allVideos: YTVideoResult[] = []\n const allChannels: YTChannelResult[] = []\n let channelMeta: YTChannelMeta | null = null\n\n if (options.mode === 'search') {\n const url = `https://www.youtube.com/results?search_query=${encodeURIComponent(options.query!)}`\n await this.driver.navigateTo(url)\n\n const first = await this.extractSearchResults(page)\n allVideos.push(...first.videos)\n allChannels.push(...first.channels)\n this.reporter.onVideos(first.videos)\n\n let contToken: string | null = first.continuationToken\n const ctx = await this.getInnerTubeContext(page)\n\n while (contToken && allVideos.length < options.maxVideos) {\n const { items, nextToken } = await this.fetchContinuation(page, 'search', contToken, ctx)\n const parsed = this.parseSearchContinuationItems(items)\n allVideos.push(...parsed.videos)\n allChannels.push(...parsed.channels)\n this.reporter.onVideos(parsed.videos)\n contToken = nextToken\n await page.waitForTimeout(500)\n }\n } else {\n await this.driver.navigateToChannel(options.channelHandle!)\n\n const first = await this.extractChannelVideos(page)\n allVideos.push(...first.videos)\n channelMeta = first.channelMeta\n this.reporter.onVideos(first.videos)\n\n let contToken: string | null = first.continuationToken\n const ctx = await this.getInnerTubeContext(page)\n\n while (contToken && allVideos.length < options.maxVideos) {\n await page.waitForTimeout(750)\n const { items, nextToken } = await this.fetchContinuation(page, 'browse', contToken, ctx)\n const parsed = this.parseChannelContinuationItems(items)\n allVideos.push(...parsed)\n this.reporter.onVideos(parsed)\n contToken = nextToken\n }\n }\n\n const capped = allVideos.slice(0, options.maxVideos)\n const stats: YTHarvestStats = {\n mode: options.mode,\n target: options.mode === 'search' ? options.query! : options.channelHandle!,\n totalVideos: capped.length,\n totalDownloads: 0,\n durationMs: Date.now() - startMs,\n }\n this.reporter.onComplete(stats)\n\n return {\n mode: options.mode,\n target: stats.target,\n extractedAt: new Date().toISOString(),\n channelMeta,\n videos: capped,\n channels: allChannels,\n downloads: [],\n stats,\n }\n } catch (err) {\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 { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport { mkdir } from 'node:fs/promises'\nimport path from 'node:path'\nimport type { YTVideoResult, YTDownloadResult } from './types.js'\nimport type { IYTProgressReporter } from './YTProgressReporter.js'\n\nconst execFileAsync = promisify(execFile)\n\nexport class MP3Downloader {\n constructor(\n private readonly outputDir: string,\n private readonly reporter: IYTProgressReporter,\n private readonly concurrency = 3,\n ) {}\n\n private async ensureYtDlp(): Promise<void> {\n try {\n await execFileAsync('yt-dlp', ['--version'])\n } catch {\n throw new Error(\n 'yt-dlp not found. Install it: brew install yt-dlp or pip install yt-dlp',\n )\n }\n }\n\n async downloadOne(video: YTVideoResult): Promise<YTDownloadResult> {\n const url = video.url\n const outputTemplate = path.join(this.outputDir, '%(title)s.%(ext)s')\n\n try {\n const { stdout } = await execFileAsync('yt-dlp', [\n '--extract-audio',\n '--audio-format', 'mp3',\n '--audio-quality', '0',\n '--embed-thumbnail',\n '--add-metadata',\n '--output', outputTemplate,\n '--print', 'after_move:filepath',\n '--no-playlist',\n '--no-warnings',\n url,\n ])\n\n const outputPath = stdout.trim().split('\\n').pop() ?? null\n this.reporter.onDownload(video.videoId, true, outputPath)\n return { videoId: video.videoId, title: video.title, outputPath, success: true, error: null }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n this.reporter.onDownload(video.videoId, false, null)\n return { videoId: video.videoId, title: video.title, outputPath: null, success: false, error: message }\n }\n }\n\n async downloadAll(videos: YTVideoResult[]): Promise<YTDownloadResult[]> {\n await mkdir(this.outputDir, { recursive: true })\n await this.ensureYtDlp()\n\n const results: YTDownloadResult[] = []\n for (let i = 0; i < videos.length; i += this.concurrency) {\n const batch = videos.slice(i, i + this.concurrency)\n const batchResults = await Promise.all(batch.map((v) => this.downloadOne(v)))\n results.push(...batchResults)\n }\n return results\n }\n}\n","import type { YTVideoResult, YTHarvestStats } from './types.js'\n\nexport interface IYTProgressReporter {\n onVideos(videos: YTVideoResult[]): void\n onDownload(videoId: string, success: boolean, path: string | null): void\n onComplete(stats: YTHarvestStats): void\n onError(err: Error): void\n}\n\nexport class YTProgressReporter implements IYTProgressReporter {\n onVideos(videos: YTVideoResult[]): void {\n for (const v of videos) {\n process.stdout.write(\n JSON.stringify({ event: 'video', videoId: v.videoId, title: v.title, channel: v.channelName, views: v.views, publishedAt: v.publishedAt, url: v.url }) + '\\n',\n )\n }\n }\n\n onDownload(videoId: string, success: boolean, path: string | null): void {\n process.stdout.write(\n JSON.stringify({ event: 'download', videoId, success, path }) + '\\n',\n )\n }\n\n onComplete(stats: YTHarvestStats): 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 { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport Papa from 'papaparse'\nimport { YouTubeHarvestOptionsSchema } from './schemas.js'\nimport type { YTHarvestResult, YouTubeHarvestOptions } from './types.js'\nimport { BrowserDriver } from '../driver/BrowserDriver.js'\nimport { YouTubeExtractor } from './YouTubeExtractor.js'\nimport { MP3Downloader } from './MP3Downloader.js'\nimport { YTProgressReporter } from './YTProgressReporter.js'\nimport { CaptchaError } from '../errors.js'\n\nconst MAX_ATTEMPTS = 3\nconst RETRY_DELAY_MS = 1_000\n\nasync function extractOnce(options: YouTubeHarvestOptions): Promise<YTHarvestResult> {\n const driver = new BrowserDriver()\n const reporter = new YTProgressReporter()\n const extractor = new YouTubeExtractor(driver, reporter)\n return extractor.extract(options)\n}\n\nasync function writeOutputs(result: YTHarvestResult, outputDir: string): Promise<void> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = result.target.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const ts = Date.now()\n\n await fs.writeFile(\n path.join(outputDir, `${slug}-${ts}.json`),\n JSON.stringify(result, null, 2),\n 'utf8',\n )\n\n if (result.videos.length > 0) {\n await fs.writeFile(\n path.join(outputDir, `${slug}-videos-${ts}.csv`),\n Papa.unparse(result.videos, { header: true }),\n 'utf8',\n )\n }\n\n if (result.downloads.length > 0) {\n await fs.writeFile(\n path.join(outputDir, `${slug}-downloads-${ts}.csv`),\n Papa.unparse(result.downloads, { header: true }),\n 'utf8',\n )\n }\n}\n\nexport async function ytHarvest(rawOptions: unknown): Promise<YTHarvestResult> {\n const kernelApiKey = process.env.KERNEL_API_KEY\n if (!kernelApiKey) {\n throw new Error('KERNEL_API_KEY env var is required — YouTube harvesting runs on Kernel stealth sessions only.')\n }\n\n const raw = typeof rawOptions === 'object' && rawOptions !== null ? rawOptions : {}\n const options = YouTubeHarvestOptionsSchema.parse({ kernelApiKey, ...raw })\n\n for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {\n try {\n const result = await extractOnce(options)\n\n if (options.downloadMp3 && result.videos.length > 0) {\n const reporter = new YTProgressReporter()\n const downloader = new MP3Downloader(options.outputDir, reporter)\n result.downloads = await downloader.downloadAll(result.videos)\n result.stats.totalDownloads = result.downloads.filter((d) => d.success).length\n }\n\n await writeOutputs(result, options.outputDir)\n return result\n } catch (err) {\n if (err instanceof CaptchaError && attempt < MAX_ATTEMPTS) {\n await new Promise((r) => setTimeout(r, RETRY_DELAY_MS))\n continue\n }\n throw err\n }\n }\n\n throw new CaptchaError(\n `YouTube blocked all ${MAX_ATTEMPTS} Kernel sessions. Try again in a few minutes.`,\n )\n}\n","import { BrowserDriver } from '../driver/BrowserDriver.js'\nimport { fal } from '@fal-ai/client'\n\nexport interface CaptionChunk {\n timestamp: [number, number]\n text: string\n}\n\nexport interface CaptionResult {\n videoId: string\n text: string\n chunks: CaptionChunk[]\n durationMs: number\n method: 'youtube-transcript' | 'kernel-innertube' | 'kernel-whisper'\n}\n\nasync function fetchViaYoutubeTranscript(videoId: string): Promise<CaptionResult | null> {\n try {\n const { YoutubeTranscript } = await import('youtube-transcript')\n const entries = await YoutubeTranscript.fetchTranscript(videoId, { lang: 'en' })\n .catch(() => YoutubeTranscript.fetchTranscript(videoId))\n if (!entries?.length) return null\n const chunks: CaptionChunk[] = entries.map((e) => ({\n timestamp: [e.offset / 1000, (e.offset + e.duration) / 1000] as [number, number],\n text: e.text.trim(),\n }))\n const text = chunks.map((c) => c.text).join(' ')\n const last = chunks[chunks.length - 1]\n return { videoId, text, chunks, durationMs: last ? last.timestamp[1] * 1000 : 0, method: 'youtube-transcript' }\n } catch {\n return null\n }\n}\n\nfunction parseTimedtextXml(xml: string): Array<{ start: number; dur: number; text: string }> {\n const results: Array<{ start: number; dur: number; text: string }> = []\n\n const pRegex = /<p\\s+t=\"(\\d+)\"\\s+d=\"(\\d+)\"[^>]*>([\\s\\S]*?)<\\/p>/g\n let m: RegExpExecArray | null\n while ((m = pRegex.exec(xml)) !== null) {\n const startMs = parseInt(m[1], 10)\n const durMs = parseInt(m[2], 10)\n const inner = m[3]\n let text = inner.replace(/<[^>]+>/g, '').trim()\n if (!text) {\n const sMatch = /<s[^>]*>([^<]*)<\\/s>/g\n let sm: RegExpExecArray | null\n const parts: string[] = []\n while ((sm = sMatch.exec(inner)) !== null) parts.push(sm[1])\n text = parts.join('').trim()\n }\n text = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '\"').replace(/'/g, \"'\")\n if (text) results.push({ start: startMs, dur: durMs, text })\n }\n if (results.length > 0) return results\n\n const classicRegex = /<text start=\"([^\"]*)\" dur=\"([^\"]*)\">([^<]*)<\\/text>/g\n while ((m = classicRegex.exec(xml)) !== null) {\n const text = m[3].replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '\"').replace(/'/g, \"'\")\n results.push({ start: parseFloat(m[1]) * 1000, dur: parseFloat(m[2]) * 1000, text })\n }\n return results\n}\n\nasync function fetchViaKernelInnertube(videoId: string): Promise<CaptionResult | null> {\n const kernelApiKey = process.env.KERNEL_API_KEY\n if (!kernelApiKey) return null\n\n const driver = new BrowserDriver()\n const start = Date.now()\n\n try {\n await driver.launch({ kernelApiKey, headless: true, viewport: { width: 1280, height: 800 }, locale: 'en-US' })\n const page = driver.getPage()\n\n await driver.navigateTo(`https://www.youtube.com/watch?v=${videoId}`)\n await page.waitForFunction(\n () => !!(window as unknown as { ytcfg?: unknown }).ytcfg,\n { timeout: 20_000 },\n )\n\n const xml = await page.evaluate(async (vid: string) => {\n const ANDROID_VERSION = '20.10.38'\n const resp = await fetch('/youtubei/v1/player?prettyPrint=false', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': `com.google.android.youtube/${ANDROID_VERSION} (Linux; U; Android 14)`,\n },\n body: JSON.stringify({\n context: { client: { clientName: 'ANDROID', clientVersion: ANDROID_VERSION } },\n videoId: vid,\n }),\n })\n if (!resp.ok) return null\n const data = await resp.json() as {\n captions?: { playerCaptionsTracklistRenderer?: { captionTracks?: Array<{ languageCode: string; baseUrl: string }> } }\n }\n const tracks = data?.captions?.playerCaptionsTracklistRenderer?.captionTracks ?? []\n if (tracks.length === 0) return null\n const track = tracks.find((t) => t.languageCode === 'en') ?? tracks[0]\n const xmlResp = await fetch(track.baseUrl)\n return xmlResp.ok ? xmlResp.text() : null\n }, videoId)\n\n if (!xml) return null\n\n const entries = parseTimedtextXml(xml)\n if (entries.length === 0) return null\n\n const chunks: CaptionChunk[] = entries.map((e) => ({\n timestamp: [e.start / 1000, (e.start + e.dur) / 1000] as [number, number],\n text: e.text,\n }))\n const text = chunks.map((c) => c.text).join(' ')\n const last = chunks[chunks.length - 1]\n\n return { videoId, text, chunks, durationMs: Date.now() - start, method: 'kernel-innertube' }\n } catch {\n return null\n } finally {\n await driver.close()\n }\n}\n\nasync function fetchViaKernelWhisper(videoId: string): Promise<CaptionResult | null> {\n const kernelApiKey = process.env.KERNEL_API_KEY\n const falKey = process.env.FAL_KEY\n if (!kernelApiKey || !falKey) return null\n\n const driver = new BrowserDriver()\n const start = Date.now()\n\n try {\n await driver.launch({ kernelApiKey, headless: true, viewport: { width: 1280, height: 800 }, locale: 'en-US' })\n const page = driver.getPage()\n\n await driver.navigateTo(`https://www.youtube.com/watch?v=${videoId}`)\n await page.waitForFunction(\n () => !!(window as unknown as { ytcfg?: unknown }).ytcfg,\n { timeout: 20_000 },\n )\n\n const audioInfo = await page.evaluate(async (vid: string) => {\n const ANDROID_VERSION = '20.10.38'\n const resp = await fetch('/youtubei/v1/player?prettyPrint=false', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': `com.google.android.youtube/${ANDROID_VERSION} (Linux; U; Android 14)`,\n },\n body: JSON.stringify({\n context: { client: { clientName: 'ANDROID', clientVersion: ANDROID_VERSION } },\n videoId: vid,\n }),\n })\n if (!resp.ok) return null\n const data = await resp.json() as {\n streamingData?: {\n adaptiveFormats?: Array<{ mimeType: string; bitrate: number; url: string }>\n }\n }\n const formats = data?.streamingData?.adaptiveFormats ?? []\n const audio = formats\n .filter((f) => f.mimeType.startsWith('audio/') && f.url)\n .sort((a, b) => a.bitrate - b.bitrate)[0]\n if (!audio) return null\n return { url: audio.url, mimeType: audio.mimeType.split(';')[0].trim() }\n }, videoId)\n\n await driver.close()\n\n if (!audioInfo) return null\n\n const audioResp = await fetch(audioInfo.url, {\n headers: { 'User-Agent': 'Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36' },\n signal: AbortSignal.timeout(120_000),\n })\n if (!audioResp.ok) return null\n const audioBuffer = Buffer.from(await audioResp.arrayBuffer())\n\n fal.config({ credentials: falKey })\n const ext = audioInfo.mimeType.includes('mp4') ? 'm4a' : 'webm'\n const audioFile = new File([new Uint8Array(audioBuffer)], `audio.${ext}`, { type: audioInfo.mimeType })\n const uploadedUrl = await fal.storage.upload(audioFile)\n\n const result = await fal.subscribe('fal-ai/wizper', {\n input: { audio_url: uploadedUrl, task: 'transcribe', language: 'en' },\n logs: false,\n pollInterval: 3000,\n })\n\n const data = result.data as unknown as {\n text?: string\n chunks?: Array<{ timestamp: [number, number]; text: string }>\n }\n const chunks: CaptionChunk[] = (data.chunks ?? []).map((c) => ({\n timestamp: c.timestamp,\n text: c.text.trim(),\n }))\n const text = data.text ?? chunks.map((c) => c.text).join(' ')\n\n return { videoId, text, chunks, durationMs: Date.now() - start, method: 'kernel-whisper' }\n } catch {\n await driver.close()\n return null\n }\n}\n\nexport async function fetchCaptions(videoId: string): Promise<CaptionResult> {\n const primary = await fetchViaYoutubeTranscript(videoId)\n if (primary) return primary\n\n const kernel = await fetchViaKernelInnertube(videoId)\n if (kernel) return kernel\n\n const whisper = await fetchViaKernelWhisper(videoId)\n if (whisper) return whisper\n\n throw new Error(`No captions available for ${videoId} — all three tiers failed`)\n}\n","import { Hono } from 'hono'\nimport { createMiddleware } from 'hono/factory'\nimport { getUserByApiKey, debitMc, creditMc } from './db.js'\nimport { MC_COSTS, insufficientBalanceResponse } from './rates.js'\nimport { ytHarvest } from '../youtube/youtube-harvest.js'\nimport { fetchCaptions } from '../youtube/CaptionFetcher.js'\nimport { buildYouTubeChannelVideosUrl } from '../driver/BrowserDriver.js'\nimport { CaptchaError } from '../errors.js'\nimport type { User } from './db.js'\n\ntype YTEnv = { Variables: { user: User } }\n\nconst ytAuth = createMiddleware<YTEnv>(async (c, next) => {\n const key = c.req.header('x-api-key')\n if (!key) return c.json({ error: 'Missing API key' }, 401)\n const user = await getUserByApiKey(key)\n if (!user) return c.json({ error: 'Invalid or inactive API key' }, 401)\n c.set('user', user)\n return next()\n})\n\nexport const youtubeApp = new Hono<YTEnv>()\n\nyoutubeApp.post('/harvest', ytAuth, async (c) => {\n const body = await c.req.json().catch(() => ({}))\n const { mode, query, channelHandle, maxVideos = 50 } = body as {\n mode?: string\n query?: string\n channelHandle?: string\n maxVideos?: number\n }\n\n if (mode !== 'search' && mode !== 'channel') {\n return c.json({ error: 'mode must be \"search\" or \"channel\"' }, 400)\n }\n if (mode === 'search' && !query?.trim()) {\n return c.json({ error: 'search mode requires query' }, 400)\n }\n if (mode === 'channel' && !channelHandle?.trim()) {\n return c.json({ error: 'channel mode requires channelHandle (@handle or UC... ID)' }, 400)\n }\n if (typeof maxVideos !== 'number' || maxVideos < 1 || maxVideos > 500) {\n return c.json({ error: 'maxVideos must be 1–500' }, 400)\n }\n\n const user = c.get('user')\n const { ok: ytOk, balance_mc: ytBal } = await debitMc(user.id, MC_COSTS.yt_channel, 'yt_channel', query ?? channelHandle ?? '')\n if (!ytOk) return c.json(insufficientBalanceResponse(ytBal, MC_COSTS.yt_channel), 402)\n\n try {\n const normalizedChannelUrl = mode === 'channel'\n ? buildYouTubeChannelVideosUrl(channelHandle!.trim())\n : undefined\n const result = await ytHarvest({\n mode,\n query: query?.trim(),\n channelHandle: normalizedChannelUrl,\n maxVideos,\n downloadMp3: false,\n outputDir: '/tmp/yt-output',\n })\n return c.json(result)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.startsWith('channel ') || msg.includes('channelHandle')) {\n return c.json({ error: msg }, 400)\n }\n if (err instanceof CaptchaError || msg.includes('CAPTCHA') || msg.includes('blocked')) {\n await creditMc(user.id, MC_COSTS.yt_channel, 'refund', 'failed call')\n return c.json({ error: msg }, 503)\n }\n await creditMc(user.id, MC_COSTS.yt_channel, 'refund', 'failed call')\n return c.json({ error: msg }, 500)\n }\n})\n\nyoutubeApp.post('/transcribe', ytAuth, async (c) => {\n const body = await c.req.json().catch(() => ({}))\n const { videoId } = body as { videoId?: string }\n\n if (!videoId?.trim()) {\n return c.json({ error: 'videoId is required' }, 400)\n }\n\n const id = videoId.trim()\n const user = c.get('user')\n const holdMins = 5\n const holdMc = MC_COSTS.transcription * holdMins\n const { ok: trOk, balance_mc: trBal } = await debitMc(user.id, holdMc, 'transcription_hold', id)\n if (!trOk) return c.json(insufficientBalanceResponse(trBal, holdMc), 402)\n\n try {\n const result = await fetchCaptions(id)\n const lastChunk = result.chunks?.[result.chunks.length - 1]\n const videoSecs = lastChunk ? lastChunk.timestamp[1] : 60\n const actualMins = Math.max(1, Math.ceil(videoSecs / 60))\n const actualMc = MC_COSTS.transcription * actualMins\n const diff = holdMc - actualMc\n if (diff > 0) await creditMc(user.id, diff, 'transcription_refund', 'overestimate refund')\n else if (diff < 0) await debitMc(user.id, -diff, 'transcription', id)\n return c.json({\n ...result,\n markdown: buildTranscriptMarkdown(result),\n html: buildTranscriptHtml(result),\n })\n } catch (err) {\n await creditMc(user.id, holdMc, 'refund', 'failed call')\n const msg = err instanceof Error ? err.message : String(err)\n return c.json({ error: msg }, 500)\n }\n})\n\nfunction buildTranscriptMarkdown(result: {\n videoId: string\n text: string\n chunks: Array<{ timestamp: [number, number]; text: string }>\n durationMs: number\n}): string {\n const lines: string[] = []\n lines.push(`# Transcript — ${result.videoId}`)\n lines.push('')\n lines.push(`*Extracted in ${(result.durationMs / 1000).toFixed(1)}s*`)\n lines.push('')\n lines.push('## Full Text')\n lines.push('')\n lines.push(result.text)\n lines.push('')\n if (result.chunks?.length) {\n lines.push('## Timestamped Segments')\n lines.push('')\n for (const chunk of result.chunks) {\n const start = fmtTs(chunk.timestamp[0])\n const end = fmtTs(chunk.timestamp[1])\n lines.push(`**[${start} → ${end}]** ${chunk.text.trim()}`)\n lines.push('')\n }\n }\n return lines.join('\\n')\n}\n\nfunction buildTranscriptHtml(result: {\n videoId: string\n text: string\n chunks: Array<{ timestamp: [number, number]; text: string }>\n durationMs: number\n}): string {\n const esc = (s: string) => s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')\n const fmtSecs = (n: number) => `${Math.floor(n / 60)}:${String(Math.floor(n % 60)).padStart(2, '0')}`\n\n const chunks = (result.chunks ?? []).map(ch =>\n `<div class=\"chunk\"><span class=\"ts\">${fmtSecs(ch.timestamp[0])} → ${fmtSecs(ch.timestamp[1])}</span><span class=\"ct\">${esc(ch.text.trim())}</span></div>`\n ).join('\\n')\n\n return `<!doctype html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<style>body{font-family:system-ui,sans-serif;max-width:800px;margin:1.5rem auto;padding:0 1rem;color:#111;line-height:1.7}\nh1{font-size:1.2rem;margin-bottom:.25rem}.meta{color:#666;font-size:.85rem;margin-bottom:1.5rem}\n.full-text{background:#f5f5f3;border-radius:8px;padding:1rem 1.25rem;font-size:.875rem;white-space:pre-wrap;margin-bottom:2rem;word-break:break-word}\n.chunk{padding:.5rem 0;border-bottom:1px solid #eee;display:flex;gap:.75rem;flex-wrap:wrap}\n.ts{font-family:monospace;font-size:.75rem;color:#888;white-space:nowrap;flex-shrink:0}\n.ct{font-size:.875rem;flex:1;min-width:0;word-break:break-word}\n</style></head><body>\n<h1>Transcript — ${esc(result.videoId)}</h1>\n<div class=\"meta\">Transcribed in ${(result.durationMs / 1000).toFixed(1)}s</div>\n<h2 style=\"font-size:1.05rem\">Full Text</h2>\n<div class=\"full-text\">${esc(result.text)}</div>\n${chunks.length ? `<h2 style=\"font-size:1.05rem\">Timestamped Segments</h2>\\n${chunks}` : ''}\n</body></html>`\n}\n\nfunction fmtTs(secs: number): string {\n return `${Math.floor(secs / 60)}:${String(Math.floor(secs % 60)).padStart(2, '0')}`\n}\n","import { chromium } from 'playwright'\nimport Kernel from '@onkernel/sdk'\nimport type { Page } from 'playwright'\n\nconst VIEWPORT_W = 1440\nconst VIEWPORT_H = 900\nconst SCROLL_STEP = VIEWPORT_H\nconst SETTLE_MS = 400\n\nexport async function scrollAndStitch(page: Page): Promise<Buffer> {\n await page.setViewportSize({ width: VIEWPORT_W, height: VIEWPORT_H })\n\n await page.evaluate(() => {\n for (const img of Array.from(document.querySelectorAll('img[loading=\"lazy\"]')) as HTMLImageElement[]) {\n img.loading = 'eager'\n }\n })\n\n const totalH: number = await page.evaluate(() =>\n Math.max(document.body.scrollHeight, document.documentElement.scrollHeight)\n )\n\n const strips: string[] = []\n let scrollY = 0\n\n while (scrollY < totalH) {\n await page.evaluate(y => window.scrollTo(0, y), scrollY)\n await page.waitForTimeout(SETTLE_MS)\n\n const remaining = totalH - scrollY\n const stripH = Math.min(VIEWPORT_H, remaining)\n\n const buf = await page.screenshot({\n type: 'png',\n clip: { x: 0, y: 0, width: VIEWPORT_W, height: stripH },\n })\n strips.push(buf.toString('base64'))\n\n scrollY += SCROLL_STEP\n }\n\n await page.evaluate(() => window.scrollTo(0, 0))\n\n const base64 = await page.evaluate(\n async ({ strips, W, totalH, stripH }: { strips: string[]; W: number; totalH: number; stripH: number }) => {\n const canvas = document.createElement('canvas')\n canvas.width = W\n canvas.height = totalH\n const ctx = canvas.getContext('2d')!\n\n for (let i = 0; i < strips.length; i++) {\n const img = new Image()\n img.src = 'data:image/png;base64,' + strips[i]\n await new Promise<void>(r => { img.onload = () => r() })\n ctx.drawImage(img, 0, i * stripH)\n }\n\n return canvas.toDataURL('image/png').replace('data:image/png;base64,', '')\n },\n { strips, W: VIEWPORT_W, totalH, stripH: SCROLL_STEP }\n )\n\n return Buffer.from(base64, 'base64')\n}\n\nasync function captureLocal(url: string): Promise<Buffer> {\n const browser = await chromium.launch({ headless: true })\n const context = await browser.newContext({\n viewport: { width: VIEWPORT_W, height: VIEWPORT_H },\n locale: 'en-US',\n userAgent: '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 })\n const page = await context.newPage()\n try {\n await page.goto(url, { waitUntil: 'networkidle', timeout: 60000 })\n await page.waitForTimeout(1500)\n return await scrollAndStitch(page)\n } finally {\n await browser.close()\n }\n}\n\nasync function captureKernel(url: string, kernelApiKey: string): Promise<Buffer> {\n const kernel = new Kernel({ apiKey: kernelApiKey })\n const session = await kernel.browsers.create({ stealth: true, timeout_seconds: 240 })\n const browser = await chromium.connectOverCDP(session.cdp_ws_url)\n const context = browser.contexts()[0] ?? await browser.newContext()\n const page = context.pages()[0] ?? await context.newPage()\n try {\n await page.goto(url, { waitUntil: 'networkidle', timeout: 60000 })\n await page.waitForTimeout(1500)\n return await scrollAndStitch(page)\n } finally {\n await browser.close()\n }\n}\n\nexport async function captureScreenshot(url: string, kernelApiKey?: string): Promise<Buffer> {\n try {\n return await captureLocal(url)\n } catch (localErr) {\n const msg = localErr instanceof Error ? localErr.message : String(localErr)\n if (!kernelApiKey) throw new Error(`Local capture failed (${msg}) and KERNEL_API_KEY is not set`)\n return await captureKernel(url, kernelApiKey)\n }\n}\n","import { Hono } from 'hono'\nimport { createMiddleware } from 'hono/factory'\nimport { isIP } from 'node:net'\nimport { lookup } from 'node:dns/promises'\nimport { captureScreenshot } from '../lib/screenshot.js'\nimport { getUserByApiKey } from './db.js'\nimport type { User } from './db.js'\n\ntype Env = { Variables: { user: User } }\n\nexport const screenshotApp = new Hono<Env>()\n\nconst auth = createMiddleware<Env>(async (c, next) => {\n const key = c.req.header('x-api-key')\n if (!key) return c.json({ error: 'Missing API key' }, 401)\n const user = await getUserByApiKey(key)\n if (!user) return c.json({ error: 'Invalid or inactive API key' }, 401)\n c.set('user', user)\n return next()\n})\n\nscreenshotApp.use('*', auth)\n\nfunction isPrivateIp(address: string): boolean {\n const kind = isIP(address)\n if (kind === 4) {\n const parts = address.split('.').map(Number)\n const [a, b] = parts\n return (\n a === 0 || a === 10 || a === 127 ||\n (a === 169 && b === 254) ||\n (a === 172 && b >= 16 && b <= 31) ||\n (a === 192 && b === 168)\n )\n }\n if (kind === 6) {\n const lower = address.toLowerCase()\n return lower === '::1' || lower.startsWith('fc') || lower.startsWith('fd') || lower.startsWith('fe80:')\n }\n return false\n}\n\nasync function isPrivateHost(hostname: string): Promise<boolean> {\n const host = hostname.toLowerCase()\n if (host === 'localhost' || host.endsWith('.localhost') || host.endsWith('.local')) return true\n if (isPrivateIp(host)) return true\n try {\n const addrs = await lookup(host, { all: true, verbatim: true })\n return addrs.some(e => isPrivateIp(e.address))\n } catch {\n return false\n }\n}\n\nscreenshotApp.post('/', async (c) => {\n const body = await c.req.json<{ url?: string }>()\n if (!body.url?.trim()) return c.json({ error: 'url is required' }, 400)\n\n let parsed: URL\n try {\n parsed = new URL(body.url.trim())\n } catch {\n return c.json({ error: 'Invalid url' }, 400)\n }\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n return c.json({ error: 'url must use http or https' }, 400)\n }\n\n if (await isPrivateHost(parsed.hostname)) {\n return c.json({ error: 'url must resolve to a public internet host' }, 400)\n }\n\n try {\n const buf = await captureScreenshot(parsed.href, process.env.KERNEL_API_KEY?.trim())\n return new Response(new Uint8Array(buf), {\n status: 200,\n headers: {\n 'Content-Type': 'image/png',\n 'Content-Length': String(buf.length),\n 'Cache-Control': 'no-store',\n },\n })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n return c.json({ error: msg }, 502)\n }\n})\n","import type { Page } from 'playwright'\nimport type { IBrowserDriver } from '../driver/IBrowserDriver.js'\nimport type { FacebookAdResult, FacebookAdVariation } from '../types.js'\n\nconst SPRITE_Y_TO_PLATFORM: Record<number, string> = {\n [-766]: 'Facebook',\n [-805]: 'Instagram',\n [-818]: 'Messenger',\n [-831]: 'Threads',\n [-779]: 'WhatsApp',\n [-792]: 'Audience Network',\n}\n\nfunction gcd(a: number, b: number): number {\n return b === 0 ? a : gcd(b, a % b)\n}\n\nfunction aspectRatioStr(w: number, h: number): string {\n const d = gcd(Math.abs(w), Math.abs(h))\n return `${w / d}:${h / d}`\n}\n\nfunction parseLibraryId(input: string): string | null {\n const m = input.match(/[?&]id=(\\d+)/) ?? input.match(/^(\\d{10,20})$/)\n return m ? m[1] : null\n}\n\nexport class FacebookAdExtractor {\n constructor(private readonly driver: IBrowserDriver) {}\n\n static resolveLibraryId(input: string): string | null {\n return parseLibraryId(input.trim())\n }\n\n async extract(libraryId: string, opts: { openModal?: boolean } = {}): Promise<FacebookAdResult> {\n const adLibraryUrl = `https://www.facebook.com/ads/library/?id=${libraryId}`\n const page = this.driver.getPage() as Page\n\n await this.driver.navigateTo(adLibraryUrl)\n await this.waitForHydration(page, libraryId)\n\n const cardData = await page.evaluate(\n ({ spriteMap, targetId }) => {\n const KNOWN_PLATFORMS = ['Facebook', 'Instagram', 'Messenger', 'Threads', 'WhatsApp', 'Audience Network']\n const CTA_LABELS = [\n 'Learn more', 'Shop now', 'Sign up', 'Subscribe', 'Get offer', 'Book now',\n 'Contact us', 'Apply now', 'Get quote', 'Download', 'Order now', 'Watch more',\n 'See menu', 'See offers', 'Listen now', 'Get directions', 'Send message', 'Call now',\n ]\n const SKIP_PREFIXES = [\n 'active', 'inactive', 'library id', 'started running', 'ran from', 'platforms',\n 'learn more', 'shop now', 'sign up', 'subscribe', 'get offer', 'book now',\n 'contact us', 'apply now', 'get quote', 'download', 'order now', 'watch more',\n ]\n if (!document.body) return null\n const root = findAdCard(targetId) ?? document.body\n return extractCard(root, spriteMap, KNOWN_PLATFORMS, CTA_LABELS, SKIP_PREFIXES)\n\n function findAdCard(id: string): Element | null {\n const allLeaves = Array.from(document.querySelectorAll('span,div')).filter(el => el.children.length === 0)\n const lidEl = allLeaves.find(el => (el.textContent ?? '').includes(id))\n if (!lidEl) return null\n let el: Element | null = lidEl.parentElement\n let best: Element | null = null\n while (el && el !== document.body) {\n const txt = (el as HTMLElement).innerText ?? ''\n const hasMedia = el.querySelector('video, img[src*=\"fbcdn.net\"]')\n const hasCTA = el.querySelector('a[role=\"button\"],button,[role=\"button\"]')\n const hasDomain = /\\b[A-Z0-9]{3,}\\.[A-Z]{2,}\\b/.test(txt)\n if (hasMedia && hasCTA && hasDomain) return el\n if ((hasMedia || hasCTA) && txt.length > 200) best = el\n el = el.parentElement\n }\n return best\n }\n\n function t(el: Element | null): string {\n return el ? ((el as HTMLElement).innerText ?? el.textContent ?? '').replace(/\\s+/g, ' ').trim() : ''\n }\n\n function extractCard(\n root: Element,\n sm: Record<number, string>,\n knownPlatforms: string[],\n ctaLabels: string[],\n skipPrefixes: string[],\n ) {\n const bodyText = (root as HTMLElement).innerText ?? root.textContent ?? ''\n\n let libraryId: string | null = null\n const lidM = bodyText.match(/Library ID[:\\s]+([0-9]{10,20})/)\n if (lidM) libraryId = lidM[1]\n\n let status: string | null = null\n const allEls = Array.from(root.querySelectorAll('span,div'))\n const activeEl = allEls.find(el => t(el) === 'Active' && el.children.length === 0)\n if (activeEl) status = 'Active'\n const inactiveEl = allEls.find(el => t(el) === 'Inactive' && el.children.length === 0)\n if (inactiveEl) status = 'Inactive'\n\n let started: string | null = null, ranFromDate: string | null = null, ranToDate: string | null = null\n const startM = bodyText.match(/Started running on\\s+([A-Za-z]+\\.?\\s+\\d{1,2},?\\s*\\d{4})/i)\n if (startM) started = startM[1].replace(/\\s+/g, ' ').trim()\n const ranM = bodyText.match(/Ran from\\s+([A-Za-z]+\\.?\\s+\\d{1,2},?\\s*\\d{4})\\s+to\\s+([A-Za-z]+\\.?\\s+\\d{1,2},?\\s*\\d{4})/i)\n if (ranM) { ranFromDate = ranM[1].trim(); ranToDate = ranM[2].trim() }\n\n let pageName: string | null = null, pageId: string | null = null, pageUrl: string | null = null\n const pageLinks = Array.from(root.querySelectorAll('a[href*=\"facebook.com\"]')).filter(a => {\n const href = (a as HTMLAnchorElement).href ?? ''\n return !href.includes('/ads/library') && !href.includes('l.facebook.com/l.php') &&\n !href.includes('facebook.com/help') && !href.includes('facebook.com/legal') &&\n !href.includes('facebook.com/policies')\n })\n if (pageLinks.length > 0) {\n const lnk = pageLinks[0] as HTMLAnchorElement\n const candidate = t(lnk)\n if (candidate && candidate.length < 80) pageName = candidate\n try {\n const u = new URL(lnk.href)\n const idParam = u.searchParams.get('id')\n if (idParam) { pageId = idParam; pageUrl = lnk.href }\n else {\n const seg = u.pathname.replace(/^\\//, '').split('/')[0]\n if (seg && seg !== 'ads') {\n pageUrl = 'https://www.facebook.com/' + seg\n if (/^\\d+$/.test(seg)) pageId = seg\n }\n if (!pageId) pageId = lnk.getAttribute('data-store-id') ?? lnk.getAttribute('data-profileid') ?? null\n }\n } catch {}\n }\n\n const platforms: string[] = []\n for (const icon of Array.from(root.querySelectorAll('[style*=\"mask\"],[style*=\"-webkit-mask\"],[style*=\"background-position\"]'))) {\n const st = window.getComputedStyle(icon)\n const pos = st.getPropertyValue('mask-position') || st.getPropertyValue('-webkit-mask-position') || st.getPropertyValue('background-position') || ''\n const m = pos.match(/(-?\\d+)px\\s+(-?\\d+)px/)\n if (!m) continue\n const platform = sm[parseInt(m[2])]\n if (platform && !platforms.includes(platform)) platforms.push(platform)\n }\n for (const el of Array.from(root.querySelectorAll('span,div'))) {\n const txt = t(el)\n if (el.children.length === 0 && knownPlatforms.includes(txt) && !platforms.includes(txt)) platforms.push(txt)\n }\n\n let multipleVersions = false, clusterCount: number | null = null\n const multiM = bodyText.match(/(\\d+)\\s+ad[s]?\\s+use[s]?\\s+this/i)\n if (multiM) { multipleVersions = true; clusterCount = parseInt(multiM[1]) }\n if (!multipleVersions && /multiple versions/i.test(bodyText)) multipleVersions = true\n\n let primaryText: string | null = null\n const textCandidates = Array.from(root.querySelectorAll('div,p,span'))\n .filter(el => {\n const txt = t(el)\n return txt.length > 30 && el.children.length === 0 &&\n !skipPrefixes.some(s => txt.toLowerCase().startsWith(s))\n })\n .sort((a, b) => t(b).length - t(a).length)\n if (textCandidates.length > 0) primaryText = t(textCandidates[0])\n\n let domain: string | null = null, headline: string | null = null\n let description: string | null = null, cta: string | null = null, landingUrl: string | null = null\n\n const domainEl = Array.from(root.querySelectorAll('span,div')).find(el => {\n const txt = t(el)\n return el.children.length === 0 && txt.length >= 4 && txt.length <= 60 &&\n txt === txt.toUpperCase() && /^[A-Z0-9.\\-]+$/.test(txt)\n })\n if (domainEl) {\n domain = t(domainEl)\n const container = domainEl.closest('div[role=\"link\"],a,[role=\"link\"]') ?? domainEl.parentElement\n if (container) {\n const bolds = container.querySelectorAll('strong,b')\n if (bolds.length > 0) {\n headline = t(bolds[0] as Element)\n } else {\n const candidates = Array.from(container.querySelectorAll('span,div')).filter(el => {\n const txt = t(el)\n return el.children.length === 0 && txt.length > 4 && txt.length < 120 && txt !== domain\n })\n if (candidates.length > 0) headline = t(candidates[0])\n }\n const descEls = Array.from(container.querySelectorAll('span,div')).filter(el => {\n const txt = t(el)\n return el.children.length === 0 && txt.length > 10 && txt !== domain && txt !== headline\n })\n if (descEls.length > 0) description = t(descEls[0])\n const lphpLinks = Array.from(container.querySelectorAll('a[href*=\"l.facebook.com/l.php\"],a[href*=\"l.instagram.com/l.php\"]'))\n if (lphpLinks.length > 0) {\n try { landingUrl = decodeURIComponent(new URL((lphpLinks[0] as HTMLAnchorElement).href).searchParams.get('u') ?? '') }\n catch { landingUrl = (lphpLinks[0] as HTMLAnchorElement).href }\n }\n }\n }\n if (!landingUrl) {\n const anyLphp = root.querySelector('a[href*=\"l.facebook.com/l.php\"],a[href*=\"l.instagram.com/l.php\"]')\n if (anyLphp) {\n try { landingUrl = decodeURIComponent(new URL((anyLphp as HTMLAnchorElement).href).searchParams.get('u') ?? '') }\n catch { landingUrl = (anyLphp as HTMLAnchorElement).href }\n }\n }\n\n const ctaEl = Array.from(root.querySelectorAll('a[role=\"button\"],button,[role=\"button\"],a')).find(el => {\n const txt = t(el)\n return ctaLabels.some(c => c.toLowerCase() === txt.toLowerCase())\n })\n if (ctaEl) cta = t(ctaEl)\n\n let videoSrc: string | null = null, videoPoster: string | null = null\n let videoDurationSec: number | null = null, videoWidth: number | null = null, videoHeight: number | null = null\n const videoEl = root.querySelector('video') as HTMLVideoElement | null\n if (videoEl) {\n videoSrc = videoEl.currentSrc || videoEl.src || (videoEl.querySelector('source') as HTMLSourceElement | null)?.src || null\n videoPoster = videoEl.poster || null\n if (isFinite(videoEl.duration) && videoEl.duration > 0) videoDurationSec = Math.round(videoEl.duration * 100) / 100\n videoWidth = videoEl.videoWidth > 0 ? videoEl.videoWidth : null\n videoHeight = videoEl.videoHeight > 0 ? videoEl.videoHeight : null\n }\n\n let imageSrc: string | null = null\n if (!videoSrc) {\n const imgs = Array.from(root.querySelectorAll('img')).filter(img => {\n const src = (img as HTMLImageElement).src ?? ''\n return (src.includes('fbcdn.net') || src.includes('cdninstagram.com')) && (img as HTMLImageElement).width > 100\n })\n if (imgs.length > 0) imageSrc = (imgs[0] as HTMLImageElement).src\n }\n\n return {\n libraryId, status, started, ranFromDate, ranToDate,\n platforms, pageName, pageId, pageUrl,\n multipleVersions, clusterCount,\n primaryText, domain, headline, description, cta, landingUrl,\n videoSrc, videoPoster, videoDurationSec, videoWidth, videoHeight, imageSrc,\n }\n }\n },\n { spriteMap: SPRITE_Y_TO_PLATFORM, targetId: libraryId },\n )\n\n if (!cardData) throw new Error('Page body was null after hydration — possible redirect or consent wall')\n\n let platforms = cardData.platforms\n let variations: FacebookAdVariation[] = []\n let modalOverrides: Partial<typeof cardData> = {}\n\n if (opts.openModal !== false) {\n const modal = await this.openModal(page)\n if (modal) {\n if (modal.platforms.length > platforms.length) platforms = modal.platforms\n if (modal.variations.length > 0) variations = modal.variations\n modalOverrides = modal.overrides\n }\n }\n\n const merged = { ...cardData, ...Object.fromEntries(Object.entries(modalOverrides).filter(([, v]) => v != null)) }\n\n const videoAspectRatio = (merged.videoWidth && merged.videoHeight)\n ? aspectRatioStr(merged.videoWidth, merged.videoHeight)\n : null\n\n return {\n libraryId,\n adLibraryUrl,\n status: merged.status ?? null,\n started: merged.started ?? null,\n ranFromDate: merged.ranFromDate ?? null,\n ranToDate: merged.ranToDate ?? null,\n platforms,\n pageName: merged.pageName ?? null,\n pageId: merged.pageId ?? null,\n pageUrl: merged.pageUrl ?? null,\n multipleVersions: merged.multipleVersions ?? false,\n clusterCount: merged.clusterCount ?? null,\n primaryText: merged.primaryText ?? null,\n domain: merged.domain ?? null,\n headline: merged.headline ?? null,\n description: merged.description ?? null,\n cta: merged.cta ?? null,\n landingUrl: merged.landingUrl ?? null,\n videoSrc: merged.videoSrc ?? null,\n videoPoster: merged.videoPoster ?? null,\n videoDurationSec: merged.videoDurationSec ?? null,\n videoWidth: merged.videoWidth ?? null,\n videoHeight: merged.videoHeight ?? null,\n videoAspectRatio,\n imageSrc: merged.imageSrc ?? null,\n variations,\n extractedAt: new Date().toISOString(),\n }\n }\n\n private async waitForHydration(page: Page, libraryId: string): Promise<void> {\n try {\n await page.waitForFunction(\n (id: string) => {\n const bt = document.body ? (document.body.innerText ?? '') : ''\n return (bt.includes('Library ID: ' + id) || bt.includes('Library ID:' + id)) &&\n (!!document.querySelector('a[href*=\"l.facebook.com/l.php\"]') ||\n !!document.querySelector('video') ||\n !!document.querySelector('img[src*=\"fbcdn.net\"]'))\n },\n libraryId,\n { timeout: 30_000, polling: 500 },\n )\n } catch {}\n await page.waitForTimeout(800)\n }\n\n private async openModal(page: Page): Promise<{\n platforms: string[]\n variations: FacebookAdVariation[]\n overrides: Record<string, unknown>\n } | null> {\n const trigger = page.locator('text=\"See ad details\", text=\"See summary details\"').first()\n if (await trigger.count() === 0) return null\n\n try {\n await trigger.click()\n await page.waitForSelector('[role=\"dialog\"]', { timeout: 8_000 })\n await page.waitForTimeout(800)\n } catch {\n return null\n }\n\n const raw = await page.evaluate(() => {\n const modal = document.querySelector('[role=\"dialog\"]') ?? document.body\n const KNOWN = ['Facebook', 'Instagram', 'Messenger', 'Threads', 'WhatsApp', 'Audience Network']\n const CTA_LABELS = [\n 'Learn more', 'Shop now', 'Sign up', 'Subscribe', 'Get offer', 'Book now',\n 'Contact us', 'Apply now', 'Get quote', 'Download', 'Order now', 'Watch more',\n 'See menu', 'See offers', 'Listen now', 'Get directions', 'Send message', 'Call now',\n ]\n\n function t(el: Element | null): string {\n return el ? ((el as HTMLElement).innerText ?? el.textContent ?? '').replace(/\\s+/g, ' ').trim() : ''\n }\n\n const platforms = Array.from(modal.querySelectorAll('span,div'))\n .filter(el => el.children.length === 0 && KNOWN.includes(t(el)))\n .map(el => t(el))\n .filter((v, i, a) => a.indexOf(v) === i)\n\n const variationCardEls = Array.from(\n modal.querySelectorAll('[data-visualcompletion=\"ad_variation_card\"], .xh8yej3, [data-ad-preview]')\n )\n\n const variations = variationCardEls.map(card => {\n let primaryText: string | null = null\n const textEls = Array.from(card.querySelectorAll('div,p,span'))\n .filter(el => {\n const txt = t(el)\n return txt.length > 60 && el.children.length < 4\n })\n .sort((a, b) => t(b).length - t(a).length)\n if (textEls.length > 0) primaryText = t(textEls[0])\n\n const domainEl = Array.from(card.querySelectorAll('span,div')).find(el => {\n const txt = t(el)\n return el.children.length === 0 && txt.length >= 4 && txt.length <= 60 &&\n txt === txt.toUpperCase() && /^[A-Z0-9.\\-]+$/.test(txt)\n })\n const domain = domainEl ? t(domainEl) : null\n\n let headline: string | null = null\n if (domainEl) {\n const container = domainEl.closest('div[role=\"link\"],a,[role=\"link\"]') ?? domainEl.parentElement\n if (container) {\n const bolds = container.querySelectorAll('strong,b')\n if (bolds.length > 0) headline = t(bolds[0] as Element)\n }\n }\n\n let landingUrl: string | null = null\n const lphp = card.querySelector('a[href*=\"l.facebook.com/l.php\"],a[href*=\"l.instagram.com/l.php\"]')\n if (lphp) {\n try { landingUrl = decodeURIComponent(new URL((lphp as HTMLAnchorElement).href).searchParams.get('u') ?? '') }\n catch { landingUrl = (lphp as HTMLAnchorElement).href }\n }\n\n const ctaEl = Array.from(card.querySelectorAll('a[role=\"button\"],button,[role=\"button\"],a')).find(el => {\n const txt = t(el)\n return CTA_LABELS.some(c => c.toLowerCase() === txt.toLowerCase())\n })\n const cta = ctaEl ? t(ctaEl) : null\n\n const videoEl = card.querySelector('video') as HTMLVideoElement | null\n const videoSrc = videoEl ? (videoEl.currentSrc || videoEl.src || null) : null\n const videoPoster = videoEl?.poster ?? null\n const videoDurationSec = videoEl && isFinite(videoEl.duration) && videoEl.duration > 0\n ? Math.round(videoEl.duration * 100) / 100 : null\n const videoWidth = (videoEl && videoEl.videoWidth > 0) ? videoEl.videoWidth : null\n const videoHeight = (videoEl && videoEl.videoHeight > 0) ? videoEl.videoHeight : null\n\n let imageSrc: string | null = null\n if (!videoSrc) {\n const imgs = Array.from(card.querySelectorAll('img')).filter(img => {\n const src = (img as HTMLImageElement).src ?? ''\n return (src.includes('fbcdn.net') || src.includes('cdninstagram.com')) && (img as HTMLImageElement).width > 100\n })\n if (imgs.length > 0) imageSrc = (imgs[0] as HTMLImageElement).src\n }\n\n return { primaryText, domain, headline, landingUrl, cta, videoSrc, videoPoster,\n videoDurationSec, videoWidth, videoHeight, imageSrc }\n })\n\n const overrides: Record<string, unknown> = {}\n if (platforms.length > 0) overrides['platforms'] = platforms\n\n const avtLink = modal.querySelector('a[href*=\"facebook.com\"]:not([href*=\"/ads/library\"]):not([href*=\"l.php\"])')\n if (avtLink) { const c = t(avtLink); if (c && c.length < 80) overrides['pageName'] = c }\n\n const activeEl = Array.from(modal.querySelectorAll('span,div')).find(el => t(el) === 'Active' && el.children.length === 0)\n if (activeEl) overrides['status'] = 'Active'\n\n const startM = ((modal as HTMLElement).innerText ?? '').match(/Started running on\\s+([A-Za-z]+\\.?\\s+\\d{1,2},?\\s*\\d{4})/i)\n if (startM) overrides['started'] = startM[1].replace(/\\s+/g, ' ').trim()\n\n return { platforms, variations, overrides }\n })\n\n return {\n platforms: raw.platforms,\n overrides: raw.overrides,\n variations: raw.variations.map((v): FacebookAdVariation => ({\n primaryText: v.primaryText ?? null,\n domain: v.domain ?? null,\n headline: v.headline ?? null,\n description: null,\n cta: v.cta ?? null,\n landingUrl: v.landingUrl ?? null,\n videoSrc: v.videoSrc ?? null,\n videoPoster: v.videoPoster ?? null,\n videoDurationSec: v.videoDurationSec ?? null,\n videoWidth: v.videoWidth ?? null,\n videoHeight: v.videoHeight ?? null,\n imageSrc: v.imageSrc ?? null,\n })),\n }\n }\n}\n","import { Hono } from 'hono'\nimport { createMiddleware } from 'hono/factory'\nimport { getUserByApiKey, debitMc, creditMc } from './db.js'\nimport { MC_COSTS, insufficientBalanceResponse } from './rates.js'\nimport { BrowserDriver } from '../driver/BrowserDriver.js'\nimport { FacebookAdExtractor } from '../extractor/FacebookAdExtractor.js'\nimport { fal } from '@fal-ai/client'\nimport type { User } from './db.js'\n\ntype FbEnv = { Variables: { user: User } }\n\nconst fbAuth = createMiddleware<FbEnv>(async (c, next) => {\n const key = c.req.header('x-api-key')\n if (!key) return c.json({ error: 'Missing API key' }, 401)\n const user = await getUserByApiKey(key)\n if (!user) return c.json({ error: 'Invalid or inactive API key' }, 401)\n c.set('user', user)\n return next()\n})\n\nexport const facebookAdApp = new Hono<FbEnv>()\n\nfacebookAdApp.post('/ad', fbAuth, async (c) => {\n const body = await c.req.json().catch(() => ({})) as {\n url?: string\n libraryId?: string\n openModal?: boolean\n }\n\n const raw = body.url?.trim() ?? body.libraryId?.trim() ?? ''\n if (!raw) return c.json({ error: 'url or libraryId is required' }, 400)\n\n const libraryId = FacebookAdExtractor.resolveLibraryId(raw)\n if (!libraryId) return c.json({ error: 'Could not resolve a valid Facebook Ad Library ID from the provided input' }, 400)\n\n const driver = new BrowserDriver()\n try {\n await driver.launch({\n headless: true,\n kernelApiKey: process.env.KERNEL_API_KEY?.trim(),\n kernelProxyId: process.env.KERNEL_PROXY_ID?.trim(),\n viewport: { width: 1280, height: 900 },\n locale: 'en-US',\n })\n const extractor = new FacebookAdExtractor(driver)\n const result = await extractor.extract(libraryId, { openModal: body.openModal !== false })\n return c.json(result)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.toLowerCase().includes('blocked') || msg.toLowerCase().includes('captcha')) {\n return c.json({ error: msg }, 503)\n }\n return c.json({ error: msg }, 500)\n } finally {\n await driver.close()\n }\n})\n\nfacebookAdApp.post('/page-intel', fbAuth, async (c) => {\n const body = await c.req.json().catch(() => ({})) as {\n pageId?: string\n query?: string\n libraryId?: string\n maxAds?: number\n country?: string\n }\n\n if (!body.pageId?.trim() && !body.query?.trim() && !body.libraryId?.trim()) {\n return c.json({ error: 'pageId, libraryId, or query is required' }, 400)\n }\n\n const maxAds = Math.min(200, Math.max(1, body.maxAds ?? 50))\n const country = body.country?.trim().toUpperCase() ?? 'US'\n\n const fbUser = c.get('user')\n const { ok: fbOk, balance_mc: fbBal } = await debitMc(fbUser.id, MC_COSTS.fb_ad, 'fb_ad', body.pageId ?? body.query ?? body.libraryId ?? '')\n if (!fbOk) return c.json(insufficientBalanceResponse(fbBal, MC_COSTS.fb_ad), 402)\n\n const listingUrl = body.libraryId?.trim()\n ? `https://www.facebook.com/ads/library/?id=${FacebookAdExtractor.resolveLibraryId(body.libraryId.trim()) ?? body.libraryId.trim()}`\n : (body.pageId?.trim()\n ? `https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=${country}&is_targeted_country=false&media_type=all&search_type=page&view_all_page_id=${body.pageId.trim()}`\n : `https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=${country}&q=${encodeURIComponent(body.query!.trim())}&search_type=keyword_unordered`)\n\n const driver = new BrowserDriver()\n try {\n await driver.launch({\n headless: true,\n kernelApiKey: process.env.KERNEL_API_KEY?.trim(),\n kernelProxyId: process.env.KERNEL_PROXY_ID?.trim(),\n viewport: { width: 1280, height: 900 },\n locale: 'en-US',\n })\n\n const page = driver.getPage() as import('playwright').Page\n await driver.navigateTo(listingUrl)\n\n try {\n await page.waitForFunction(\n () => {\n const bt = document.body ? (document.body.innerText ?? '') : ''\n return bt.includes('Library ID') || bt.includes('No ads')\n },\n { timeout: 25_000, polling: 600 },\n )\n } catch {}\n await page.waitForTimeout(1500)\n\n let prevCount = 0\n for (let scroll = 0; scroll < 20; scroll++) {\n const count = await page.evaluate(() => {\n const bt = document.body ? (document.body.innerText ?? '') : ''\n return [...bt.matchAll(/Library ID/g)].length\n })\n if (count >= maxAds) break\n if (count === prevCount && scroll > 0) break\n prevCount = count\n await page.evaluate(() => { if (document.body) window.scrollTo(0, document.body.scrollHeight) })\n await page.waitForTimeout(1200)\n }\n\n type AdVisual = { imageSrc: string | null; videoSrc: string | null; videoPoster: string | null }\n const adVisuals: Record<string, AdVisual> = await page.evaluate(() => {\n const out: { [lid: string]: { imageSrc: string | null; videoSrc: string | null; videoPoster: string | null } } = {}\n const walker = document.createTreeWalker(document.body ?? document.documentElement, NodeFilter.SHOW_TEXT)\n let node: Node | null\n let processed = 0\n while ((node = walker.nextNode()) && processed < 12000) {\n processed++\n const t = node.textContent ?? ''\n if (!t.includes('Library ID')) continue\n const m = t.match(/Library ID[:\\s]+(\\d{10,20})/)\n if (!m) continue\n const lid = m[1]\n if (out[lid]) continue\n let el: Element | null = node.parentElement\n let found = false\n for (let i = 0; i < 22 && el && !found; i++) {\n const vid = el.querySelector('video') as HTMLVideoElement | null\n if (vid) {\n out[lid] = { imageSrc: null, videoSrc: vid.currentSrc || vid.src || null, videoPoster: vid.poster || null }\n found = true\n } else {\n const img = el.querySelector('img[src*=\"fbcdn.net\"],img[src*=\"cdninstagram\"]') as HTMLImageElement | null\n if (img && img.width > 60) {\n out[lid] = { imageSrc: img.src, videoSrc: null, videoPoster: null }\n found = true\n }\n }\n el = el.parentElement\n }\n if (!found) out[lid] = { imageSrc: null, videoSrc: null, videoPoster: null }\n }\n return out\n }).catch(() => ({} as Record<string, AdVisual>))\n\n const rawBodyText: string = await page.evaluate(() =>\n document.body ? (document.body.innerText ?? '') : ''\n )\n\n const bodyText = rawBodyText.replace(//g, ' ').replace(/\\s+/g, ' ')\n\n const CTA_LABELS = [\n 'Learn more', 'Shop now', 'Sign up', 'Subscribe', 'Get offer', 'Book now',\n 'Contact us', 'Apply now', 'Get quote', 'Download', 'Order now', 'Watch more',\n 'See menu', 'See offers', 'Listen now', 'Get directions', 'Send message', 'Call now',\n ]\n const adChunks: string[] = []\n const splitRe = /(?=(?:Active|Inactive)\\s+Library ID[:\\s]+\\d{10,20})/g\n let last = 0\n let m: RegExpExecArray | null\n while ((m = splitRe.exec(bodyText)) !== null) {\n if (m.index > last) adChunks.push(bodyText.slice(last, m.index))\n last = m.index\n if (splitRe.lastIndex === m.index) splitRe.lastIndex++\n }\n if (last < bodyText.length) adChunks.push(bodyText.slice(last))\n\n const ads = adChunks\n .filter(c => /Library ID[:\\s]+\\d{10,20}/i.test(c))\n .slice(0, maxAds)\n .map(chunk => {\n const lidM = chunk.match(/Library ID[:\\s]+([0-9]{10,20})/i)\n const libraryId = lidM ? lidM[1] : null\n\n const statusM = chunk.match(/^(Active|Inactive)/i)\n const status = statusM ? statusM[1] : null\n\n const startM = chunk.match(/Started running on\\s+([A-Za-z]+\\.?\\s+\\d{1,2},?\\s*\\d{4})/i)\n const started = startM ? startM[1].replace(/\\s+/g, ' ').trim() : null\n\n const visual = adVisuals[libraryId ?? ''] ?? { imageSrc: null, videoSrc: null, videoPoster: null }\n const hasVideoText = /0:00\\s*\\/\\s*0:00|\\d+:\\d+\\s*\\/\\s*\\d+:\\d+/.test(chunk)\n const creativeType: 'video' | 'image' | 'unknown' = (visual.videoSrc || hasVideoText) ? 'video' : (visual.imageSrc ? 'image' : 'unknown')\n\n let domain: string | null = null\n const domainRe = /\\b([A-Z0-9]{2,}(?:\\.[A-Z]{2,})+)\\b/g\n let dm: RegExpExecArray | null\n while ((dm = domainRe.exec(chunk)) !== null) {\n const c = dm[1]\n if (c.length >= 6 && c !== 'LIBRARY') { domain = c; break }\n }\n\n let primaryText: string | null = null\n let headline: string | null = null\n const sponsoredIdx = chunk.search(/\\bSponsored\\b/i)\n if (sponsoredIdx >= 0) {\n let afterSponsored = chunk.slice(sponsoredIdx + 'Sponsored'.length).trim()\n afterSponsored = afterSponsored.replace(/\\s*\\d*:?\\d+\\s*\\/\\s*\\d*:?\\d+.*$/, '')\n if (domain) {\n const di = afterSponsored.indexOf(domain)\n if (di >= 0) afterSponsored = afterSponsored.slice(0, di)\n }\n const pt = afterSponsored.trim()\n if (pt.length >= 30) primaryText = pt\n }\n const ctaRe2 = new RegExp('\\\\b(' + CTA_LABELS.map(l => l.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|') + ')\\\\b', 'i')\n if (domain) {\n const di = chunk.indexOf(domain)\n if (di >= 0) {\n let afterDomain = chunk.slice(di + domain.length).trim()\n const ctaMatch = afterDomain.search(ctaRe2)\n if (ctaMatch >= 0) afterDomain = afterDomain.slice(0, ctaMatch).trim()\n if (afterDomain.length > 3 && afterDomain.length < 120) headline = afterDomain\n }\n }\n if (!headline) {\n const ctaIdx = chunk.search(ctaRe2)\n if (ctaIdx > 0) {\n const beforeCta = chunk.slice(0, ctaIdx).trimEnd()\n const sentenceEnd = Math.max(beforeCta.lastIndexOf('. '), beforeCta.lastIndexOf('! '), beforeCta.lastIndexOf('? '))\n if (sentenceEnd >= 0) {\n const candidate = beforeCta.slice(sentenceEnd + 2).trim()\n if (candidate.length > 3 && candidate.length < 120) headline = candidate\n } else if (beforeCta.length > 3 && beforeCta.length < 120) {\n headline = beforeCta.trim()\n }\n }\n }\n\n let cta: string | null = null\n for (const lbl of CTA_LABELS) {\n if (chunk.toLowerCase().includes(lbl.toLowerCase())) { cta = lbl; break }\n }\n\n const multiM = chunk.match(/(\\d+)\\s+ad[s]?\\s+use[s]?\\s+this/i)\n const clusterCount = multiM ? parseInt(multiM[1]) : null\n\n return {\n libraryId, status, started, creativeType, headline, primaryText, cta, clusterCount,\n imageSrc: visual.imageSrc, videoSrc: visual.videoSrc, videoPoster: visual.videoPoster,\n }\n })\n .filter((ad, idx, arr) => ad.libraryId && arr.findIndex(a => a.libraryId === ad.libraryId) === idx)\n\n const totalAds = ads.length\n const activeCount = ads.filter(a => a.status === 'Active').length\n const videoCount = ads.filter(a => a.creativeType === 'video').length\n const imageCount = ads.filter(a => a.creativeType === 'image').length\n const unknownCreativeCount = ads.filter(a => a.creativeType === 'unknown').length\n\n const advertiserPageId = new URL(page.url()).searchParams.get('view_all_page_id') ?? null\n\n const nameFreq = new Map<string, number>()\n for (const chunk of adChunks) {\n const detailsParts = chunk.split('See ad details ')\n if (detailsParts.length < 2) continue\n const sponsoredIdx = detailsParts[1].indexOf(' Sponsored')\n if (sponsoredIdx < 0) continue\n const n = detailsParts[1].slice(0, sponsoredIdx).trim()\n if (n) nameFreq.set(n, (nameFreq.get(n) ?? 0) + 1)\n }\n const advertiserName = nameFreq.size\n ? [...nameFreq.entries()].sort((a, b) => b[1] - a[1])[0][0]\n : null\n\n return c.json({\n listingUrl,\n scannedAt: new Date().toISOString(),\n advertiserPageId,\n advertiserName,\n summary: {\n totalAds,\n activeCount,\n inactiveCount: totalAds - activeCount,\n videoCount,\n imageCount,\n unknownCreativeCount,\n },\n ads,\n })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n await creditMc(fbUser.id, MC_COSTS.fb_ad, 'refund', 'failed call')\n if (msg.toLowerCase().includes('blocked') || msg.toLowerCase().includes('captcha')) {\n return c.json({ error: msg }, 503)\n }\n return c.json({ error: msg }, 500)\n } finally {\n await driver.close()\n }\n})\n\nfacebookAdApp.post('/transcribe', fbAuth, async (c) => {\n const body = await c.req.json().catch(() => ({})) as { videoUrl?: string }\n const videoUrl = body.videoUrl?.trim()\n if (!videoUrl) return c.json({ error: 'videoUrl is required' }, 400)\n\n fal.config({ credentials: process.env.FAL_KEY })\n\n try {\n const startMs = Date.now()\n const result = await fal.subscribe('fal-ai/wizper', {\n input: { audio_url: videoUrl, task: 'transcribe', language: 'en' },\n logs: false,\n pollInterval: 3000,\n })\n\n const data = result.data as unknown as {\n text?: string\n chunks?: Array<{ timestamp: [number, number]; text: string }>\n }\n const text = data.text ?? ''\n const chunks = data.chunks ?? []\n const durationMs = Date.now() - startMs\n\n const fmtTs = (s: number) => `${Math.floor(s / 60)}:${String(Math.floor(s % 60)).padStart(2, '0')}`\n const lines = ['# Facebook Ad Transcript', '', `*Transcribed in ${(durationMs / 1000).toFixed(1)}s*`, '', '## Full Text', '', text, '']\n if (chunks.length) {\n lines.push('## Timestamped Segments', '')\n for (const ch of chunks) {\n lines.push(`**[${fmtTs(ch.timestamp[0])} → ${fmtTs(ch.timestamp[1])}]** ${ch.text.trim()}`, '')\n }\n }\n\n return c.json({ text, chunks, durationMs, markdown: lines.join('\\n') })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n return c.json({ error: msg }, 500)\n }\n})\n\nfacebookAdApp.post('/search', fbAuth, async (c) => {\n const body = await c.req.json().catch(() => ({})) as {\n query?: string\n country?: string\n maxResults?: number\n }\n\n if (!body.query?.trim()) return c.json({ error: 'query is required' }, 400)\n\n const country = body.country?.trim().toUpperCase() ?? 'US'\n const maxResults = Math.min(20, Math.max(1, body.maxResults ?? 10))\n const searchUrl = `https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=${country}&q=${encodeURIComponent(body.query.trim())}&search_type=keyword_unordered`\n\n const driver = new BrowserDriver()\n try {\n await driver.launch({\n headless: true,\n kernelApiKey: process.env.KERNEL_API_KEY?.trim(),\n kernelProxyId: process.env.KERNEL_PROXY_ID?.trim(),\n viewport: { width: 1280, height: 900 },\n locale: 'en-US',\n })\n\n const page = driver.getPage() as import('playwright').Page\n await driver.navigateTo(searchUrl)\n\n try {\n await page.waitForFunction(\n () => {\n const bt = document.body ? (document.body.innerText ?? '') : ''\n return bt.includes('Library ID') || bt.includes('No results')\n },\n { timeout: 20_000, polling: 500 },\n )\n } catch {}\n await page.waitForTimeout(1500)\n\n for (let scroll = 0; scroll < 3; scroll++) {\n await page.evaluate(() => { if (document.body) window.scrollTo(0, document.body.scrollHeight) })\n await page.waitForTimeout(1000)\n }\n\n const rawBodyText: string = await page.evaluate(() => document.body?.innerText ?? '')\n\n const bodyText = rawBodyText.replace(//g, ' ').replace(/\\s+/g, ' ')\n\n const adChunks: string[] = []\n const splitRe = /(?=(?:Active|Inactive)\\s+Library ID[:\\s]+\\d{10,20})/g\n let last = 0\n let m: RegExpExecArray | null\n while ((m = splitRe.exec(bodyText)) !== null) {\n if (m.index > last) adChunks.push(bodyText.slice(last, m.index))\n last = m.index\n if (splitRe.lastIndex === m.index) splitRe.lastIndex++\n }\n if (last < bodyText.length) adChunks.push(bodyText.slice(last))\n\n const advertiserMap = new Map<string, { pageName: string; sampleLibraryId: string; adCount: number }>()\n\n for (const chunk of adChunks) {\n const lidM = chunk.match(/Library ID[:\\s]+([0-9]{10,20})/i)\n if (!lidM) continue\n const libraryId = lidM[1]\n\n const detailsParts = chunk.split('See ad details ')\n if (detailsParts.length < 2) continue\n const afterDetails = detailsParts[1]\n const sponsoredIdx = afterDetails.indexOf(' Sponsored')\n if (sponsoredIdx < 0) continue\n const pageName = afterDetails.slice(0, sponsoredIdx).trim()\n if (!pageName) continue\n\n const existing = advertiserMap.get(pageName)\n if (existing) {\n existing.adCount++\n } else {\n advertiserMap.set(pageName, { pageName, sampleLibraryId: libraryId, adCount: 1 })\n }\n }\n\n const results = [...advertiserMap.values()]\n .sort((a, b) => b.adCount - a.adCount)\n .slice(0, maxResults)\n\n return c.json({ query: body.query.trim(), searchUrl, results })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.toLowerCase().includes('blocked') || msg.toLowerCase().includes('captcha')) {\n return c.json({ error: msg }, 503)\n }\n return c.json({ error: msg }, 500)\n } finally {\n await driver.close()\n }\n})\n\nconst ALLOWED_MEDIA_HOSTS = ['fbcdn.net', 'cdninstagram.com', 'scontent.facebook.com', 'scontent.cdninstagram.com']\n\nfacebookAdApp.post('/media', fbAuth, async (c) => {\n const body = await c.req.json().catch(() => ({})) as {\n url?: string\n filename?: string\n }\n\n if (!body.url?.trim()) return c.json({ error: 'url is required' }, 400)\n\n let parsed: URL\n try {\n parsed = new URL(body.url.trim())\n } catch {\n return c.json({ error: 'Invalid URL' }, 400)\n }\n\n const hostname = parsed.hostname.toLowerCase()\n if (!ALLOWED_MEDIA_HOSTS.some(h => hostname === h || hostname.endsWith('.' + h))) {\n return c.json({ error: 'URL must be a Facebook or Instagram CDN media URL (fbcdn.net or cdninstagram.com)' }, 400)\n }\n\n let res: Response\n try {\n res = await fetch(parsed.href, {\n headers: {\n 'User-Agent': '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 'Referer': 'https://www.facebook.com/',\n },\n signal: AbortSignal.timeout(60_000),\n })\n } catch (err) {\n return c.json({ error: `Fetch failed: ${err instanceof Error ? err.message : String(err)}` }, 502)\n }\n\n if (!res.ok) {\n return c.json({ error: `CDN returned ${res.status}` }, 502)\n }\n\n const contentType = res.headers.get('content-type') ?? 'application/octet-stream'\n const ext = contentType.includes('video') ? 'mp4'\n : contentType.includes('jpeg') ? 'jpg'\n : contentType.includes('png') ? 'png'\n : contentType.includes('webp') ? 'webp'\n : 'bin'\n\n const filename = body.filename?.trim() ?? `fb-media.${ext}`\n\n return new Response(res.body, {\n status: 200,\n headers: {\n 'Content-Type': contentType,\n 'Content-Disposition': `attachment; filename=\"${filename}\"`,\n 'Cache-Control': 'no-store',\n },\n })\n})\n","import type { Page } from 'playwright'\nimport type { IBrowserDriver } from '../driver/IBrowserDriver.js'\nimport type { MapsPlaceResult, MapsHoursDay, MapsReviewCard, DriverConfig } from '../types.js'\nimport { MapsPlaceOptionsSchema } from '../schemas.js'\nimport { z } from 'zod'\n\ntype MapsPlaceOptions = z.infer<typeof MapsPlaceOptionsSchema>\n\nexport class MapsExtractor {\n constructor(private readonly driver: IBrowserDriver) {}\n\n async extract(options: MapsPlaceOptions): Promise<MapsPlaceResult> {\n const startMs = Date.now()\n const config: DriverConfig = {\n headless: options.headless,\n kernelApiKey: options.kernelApiKey,\n kernelProxyId: options.kernelProxyId,\n viewport: { width: 1280, height: 900 },\n locale: `${options.hl}-${options.gl.toUpperCase()}`,\n }\n\n try {\n await this.driver.launch(config)\n const page = this.driver.getPage() as Page\n\n const searchQuery = `${options.businessName} ${options.location}`\n const searchUrl = `https://www.google.com/maps/search/${encodeURIComponent(searchQuery)}`\n await page.goto(searchUrl, { waitUntil: 'domcontentloaded', timeout: 45_000 })\n\n const onPlacePage = await page.evaluate(() => /\\/maps\\/place\\//.test(location.href))\n if (!onPlacePage) {\n await this.navigateToFirstResult(page)\n }\n await page.waitForSelector('h1', { timeout: 20_000 })\n\n const placeUrl = page.url()\n const identifiers = this.parseUrlIdentifiers(placeUrl)\n\n const overview = await this.extractOverview(page)\n const hoursTable = await this.extractFullHours(page)\n const aboutAttributes = await this.extractAbout(page)\n\n const reviewsUrl = this.buildReviewsUrl(placeUrl)\n let reviewStats: { reviewHistogram: Array<{ stars: number; count: string }>; reviewTopics: Array<{ label: string; count: string }> } =\n { reviewHistogram: [], reviewTopics: [] }\n let reviews: MapsReviewCard[] = []\n\n if (reviewsUrl) {\n try {\n await page.goto(reviewsUrl, { waitUntil: 'domcontentloaded', timeout: 45_000 })\n await page.waitForSelector('[role=\"tab\"]', { timeout: 20_000 })\n await page.waitForTimeout(1500)\n reviewStats = await this.extractReviewStats(page)\n if (options.includeReviews) {\n reviews = await this.extractReviews(page, options.maxReviews)\n }\n } catch {\n }\n }\n\n const reviewCountFinal = overview.reviewCount\n ?? (reviewStats.reviewHistogram.length > 0\n ? reviewStats.reviewHistogram.reduce((s, r) => s + parseInt(r.count, 10), 0).toString()\n : null)\n\n return {\n businessName: options.businessName,\n location: options.location,\n extractedAt: new Date().toISOString(),\n placeUrl,\n ...identifiers,\n ...overview,\n reviewCount: reviewCountFinal,\n hoursTable,\n reviewHistogram: reviewStats.reviewHistogram,\n reviewTopics: reviewStats.reviewTopics,\n aboutAttributes,\n reviews,\n durationMs: Date.now() - startMs,\n }\n } finally {\n await this.driver.close()\n }\n }\n\n private buildReviewsUrl(placeUrl: string): string | null {\n const fid = placeUrl.match(/!1s(0x[0-9a-f]+:0x[0-9a-f]+)/i)\n const pin = placeUrl.match(/!3d(-?\\d+\\.\\d+)!4d(-?\\d+\\.\\d+)/)\n const kg = placeUrl.match(/!16s([^!?&]+)/)\n const at = placeUrl.match(/@(-?\\d+\\.\\d+),(-?\\d+\\.\\d+),(\\d+(?:\\.\\d+)?z)/)\n const name = placeUrl.match(/\\/place\\/([^/@]+)/)\n if (!fid || !pin || !at || !name) return null\n const kgPart = kg ? `!16s${kg[1]}` : ''\n return (\n `https://www.google.com/maps/place/${name[1]}` +\n `/@${at[1]},${at[2]},${at[3]}` +\n `/data=!4m8!3m7!1s${fid[1]}!8m2!3d${pin[1]}!4d${pin[2]}!9m1!1b1${kgPart}`\n )\n }\n\n private async navigateToFirstResult(page: Page): Promise<void> {\n const firstResult = await page.waitForSelector(\n '[role=\"feed\"] a[href*=\"/maps/place/\"]',\n { timeout: 15_000 }\n ).catch(() => null)\n if (firstResult) {\n const href = await firstResult.getAttribute('href')\n if (href) {\n const fullUrl = href.startsWith('http') ? href : `https://www.google.com${href}`\n await page.goto(fullUrl, { waitUntil: 'domcontentloaded', timeout: 45_000 })\n return\n }\n await firstResult.click()\n } else {\n const fallback = await page.$('[data-result-index=\"0\"]')\n if (fallback) await fallback.click()\n }\n await page.waitForTimeout(2500)\n }\n\n private parseUrlIdentifiers(url: string): {\n cid: string | null\n cidDecimal: string | null\n cidUrl: string | null\n kgmid: string | null\n lat: number | null\n lng: number | null\n } {\n const pin = url.match(/!3d(-?\\d+\\.\\d+)!4d(-?\\d+\\.\\d+)/)\n const fid = url.match(/!1s(0x[0-9a-f]+):(0x[0-9a-f]+)/i)\n const kg = decodeURIComponent(url).match(/!16s(\\/g\\/[a-z0-9_]+)/i)\n\n let cidDecimal: string | null = null\n if (fid) {\n try { cidDecimal = BigInt(fid[2]).toString() } catch { }\n }\n\n return {\n cid: fid ? `${fid[1]}:${fid[2]}` : null,\n cidDecimal,\n cidUrl: cidDecimal ? `https://www.google.com/maps?cid=${cidDecimal}` : null,\n kgmid: kg ? kg[1] : null,\n lat: pin ? parseFloat(pin[1]) : null,\n lng: pin ? parseFloat(pin[2]) : null,\n }\n }\n\n private async extractOverview(page: Page): Promise<{\n name: string | null\n rating: string | null\n reviewCount: string | null\n category: string | null\n address: string | null\n hoursSummary: string | null\n phone: string | null\n phoneDisplay: string | null\n website: string | null\n plusCode: string | null\n bookingUrl: string | null\n }> {\n return page.evaluate(() => {\n const f7 = document.querySelector('div.F7nice') as HTMLElement | null\n const f7Text = f7?.innerText ?? ''\n const rating = f7Text.match(/^(\\d+\\.\\d+|\\d+)/)?.[1] ?? null\n const countFromF7 = f7Text.match(/\\(([\\d,]+)\\)/)?.[1]?.replace(/,/g, '') ?? null\n const countFromTab = (() => {\n const btn = Array.from(document.querySelectorAll('button[role=\"tab\"]')).find(el =>\n /review/i.test((el as HTMLElement).innerText)\n )\n const m = btn?.getAttribute('aria-label')?.match(/(\\d[\\d,]*)\\s*reviews?/i)\n ?? (btn as HTMLElement | null)?.innerText?.match(/(\\d[\\d,]*)\\s*reviews?/i)\n return m ? m[1].replace(/,/g, '') : null\n })()\n const reviewCount = countFromF7 ?? countFromTab\n\n const phoneBtn = document.querySelector('button[data-item-id^=\"phone:tel:\"]')\n const phoneId = phoneBtn?.getAttribute('data-item-id') ?? null\n const phone = phoneId ? phoneId.replace('phone:tel:', '') : null\n const phoneAria = phoneBtn?.getAttribute('aria-label') ?? null\n const phoneDisplay = phoneAria ? phoneAria.replace(/^Phone:\\s*/i, '').trim() : null\n\n const addressBtn = document.querySelector('button[data-item-id=\"address\"]')\n const addressLabel = addressBtn?.getAttribute('aria-label') ?? null\n const address = addressLabel ? addressLabel.replace(/^Address:\\s*/i, '').trim() : null\n\n const hoursBtn = document.querySelector('button[data-item-id=\"oh\"]')\n const hoursLabel = hoursBtn?.getAttribute('aria-label') ?? null\n const hoursSummary = hoursLabel ? hoursLabel.replace(/\\s*·\\s*See more hours.*$/i, '').trim() : null\n\n const websiteEl = document.querySelector('a[data-item-id=\"authority\"]') as HTMLAnchorElement | null\n const plusBtn = document.querySelector('button[data-item-id=\"oloc\"]')\n const plusAria = plusBtn?.getAttribute('aria-label') ?? null\n const plusCode = plusAria ? plusAria.replace(/^Plus code:\\s*/i, '').trim() : null\n const bookingEl = document.querySelector('a[data-item-id^=\"action:\"]') as HTMLAnchorElement | null\n const catBtn = document.querySelector('button[jsaction*=\"category\"]')\n const h1El = document.querySelector('h1')\n\n const catRaw = (catBtn as HTMLElement | null)?.innerText ?? ''\n const category = catRaw.split('\\n').map((s: string) => s.trim()).find(Boolean) ?? null\n\n return {\n name: (h1El as HTMLElement | null)?.innerText?.trim() ?? null,\n rating,\n reviewCount,\n category,\n address,\n hoursSummary,\n phone,\n phoneDisplay,\n website: websiteEl?.href ?? null,\n plusCode,\n bookingUrl: bookingEl?.href ?? null,\n }\n })\n }\n\n private async extractFullHours(page: Page): Promise<MapsHoursDay[]> {\n const hoursBtn = await page.$('button[data-item-id=\"oh\"]')\n if (hoursBtn) {\n await hoursBtn.click().catch(() => {})\n await page.waitForSelector('table.eK4R0e tr, table[aria-label*=\"Hour\"] tr', { timeout: 3000 }).catch(() => {})\n }\n\n return page.evaluate(() => {\n const seen = new Set<string>()\n const rows: { day: string; hours: string }[] = []\n document.querySelectorAll('table.eK4R0e tr, table[aria-label*=\"Hour\"] tr').forEach(tr => {\n const cells = tr.querySelectorAll('td')\n const day = (cells[0] as HTMLElement | undefined)?.innerText?.replace(/\\n/g, ' ').trim()\n const hrs = (cells[1] as HTMLElement | undefined)?.innerText?.replace(/\\n/g, ' ').trim()\n if (day && hrs && !seen.has(day)) {\n seen.add(day)\n rows.push({ day, hours: hrs })\n }\n })\n return rows\n })\n }\n\n private async extractReviewStats(page: Page): Promise<{\n reviewHistogram: Array<{ stars: number; count: string }>\n reviewTopics: Array<{ label: string; count: string }>\n }> {\n const activeTab = await page.$('button[role=\"tab\"][aria-selected=\"true\"]')\n const activeText = activeTab ? await activeTab.evaluate(el => (el as HTMLElement).innerText) : ''\n if (!/review/i.test(activeText)) {\n const reviewsTab = await page.$('button[role=\"tab\"][aria-label*=\"Review\"]')\n if (reviewsTab) {\n await reviewsTab.click().catch(() => {})\n await page.waitForSelector('[data-review-id]', { timeout: 10_000 }).catch(() => {})\n }\n }\n\n return page.evaluate(() => {\n const histogram: Array<{ stars: number; count: string }> = []\n document.querySelectorAll('[aria-label*=\"stars,\"], [aria-label*=\"star,\"]').forEach(el => {\n const label = el.getAttribute('aria-label') ?? ''\n const m = label.match(/^(\\d+)\\s+stars?,\\s*([\\d,]+)\\s+reviews?/i)\n if (m) histogram.push({ stars: parseInt(m[1], 10), count: m[2].replace(/,/g, '') })\n })\n\n const firstReview = document.querySelector('[data-review-id]')\n const topics = Array.from(document.querySelectorAll('button[jsaction]'))\n .filter(btn => {\n if (!firstReview) return false\n return btn.compareDocumentPosition(firstReview) & Node.DOCUMENT_POSITION_FOLLOWING\n })\n .flatMap(btn => {\n const lines = ((btn as HTMLElement).innerText?.trim() ?? '').split(/\\n/)\n if (lines.length === 2 && /^\\d+$/.test(lines[1].trim()) && lines[0].length > 2) {\n return [{ label: lines[0].trim(), count: lines[1].trim() }]\n }\n return []\n })\n\n return { reviewHistogram: histogram, reviewTopics: topics }\n })\n }\n\n private async extractAbout(page: Page): Promise<Array<{ section: string; attribute: string }>> {\n const aboutTab = await page.$('button[role=\"tab\"][aria-label*=\"About\"]')\n if (!aboutTab) return []\n\n const tabText = await aboutTab.evaluate(el => (el as HTMLElement).innerText)\n if (!/about/i.test(tabText)) return []\n\n await aboutTab.click().catch(() => {})\n await page.waitForSelector('[role=\"main\"] h2', { timeout: 5_000 }).catch(() => {})\n\n return page.evaluate(() => {\n const results: Array<{ section: string; attribute: string }> = []\n const seen = new Set<string>()\n const main = document.querySelector('[role=\"main\"]')\n if (!main) return results\n\n let currentSection = 'General'\n main.querySelectorAll('h2, li').forEach(el => {\n if (el.tagName === 'H2') {\n currentSection = (el as HTMLElement).innerText?.trim() || currentSection\n } else if (el.tagName === 'LI') {\n const text = (el as HTMLElement).innerText?.replace(/^[\\s\\S]*?\\n/, '').trim()\n const key = `${currentSection}|${text}`\n if (text && !seen.has(key)) {\n seen.add(key)\n results.push({ section: currentSection, attribute: text })\n }\n }\n })\n\n main.querySelectorAll('[href*=\"businessownership\"], [data-item-id^=\"place-info-links:\"]').forEach(el => {\n const text = (el as HTMLElement).innerText?.trim()\n const key = `Ownership|${text}`\n if (text && !seen.has(key)) {\n seen.add(key)\n results.push({ section: 'Ownership', attribute: text })\n }\n })\n\n return results\n })\n }\n\n private async extractReviews(page: Page, maxReviews: number): Promise<MapsReviewCard[]> {\n const activeTab = await page.$('button[role=\"tab\"][aria-selected=\"true\"]')\n const activeText = activeTab ? await activeTab.evaluate(el => (el as HTMLElement).innerText) : ''\n if (!/review/i.test(activeText)) {\n const reviewsTab = await page.$('button[role=\"tab\"][aria-label*=\"Review\"]')\n if (reviewsTab) {\n await reviewsTab.click().catch(() => {})\n await page.waitForSelector('[data-review-id]', { timeout: 10_000 }).catch(() => {})\n }\n }\n\n const outerReviewCount = () => page.evaluate(() =>\n Array.from(document.querySelectorAll('[data-review-id]'))\n .filter(el => !el.parentElement?.closest('[data-review-id]')).length\n )\n\n let prevCount = 0\n let staleRounds = 0\n while (staleRounds < 3) {\n const count = await outerReviewCount()\n if (count >= maxReviews) break\n if (count === prevCount) {\n staleRounds++\n } else {\n staleRounds = 0\n prevCount = count\n }\n await page.evaluate(() => {\n const pane = [...document.querySelectorAll('div.m6QErb')]\n .find(el => el.scrollHeight > el.clientHeight + 100) as HTMLElement | undefined\n if (!pane) { window.scrollTo(0, document.body.scrollHeight); return }\n pane.scrollTop = pane.scrollHeight\n })\n await page.waitForTimeout(1500)\n }\n\n await page.evaluate(() => {\n document.querySelectorAll(\n '[data-review-id] button[aria-label*=\"See more\"], [data-review-id] button.w8nwRe'\n ).forEach(b => (b as HTMLElement).click())\n })\n await page.waitForTimeout(400)\n\n return page.evaluate((max: unknown) => {\n const maxN = max as number\n const cards = Array.from(document.querySelectorAll('[data-review-id]'))\n .filter(el => !el.parentElement?.closest('[data-review-id]'))\n .slice(0, maxN)\n return cards.map(card => {\n const reviewId = card.getAttribute('data-review-id') ?? ''\n const authorNameEl = card.querySelector('div.d4r55, span.d4r55, span.RPZfBb') as HTMLElement | null\n const authorBtnEl = card.querySelector('button[jsaction*=\"reviewerLink\"], a[jsaction*=\"reviewerLink\"]') as HTMLElement | null\n const author = authorNameEl?.innerText?.replace(/^[\\s\\S]*?\\n/, '').trim()\n || authorBtnEl?.getAttribute('aria-label')?.replace(/\\s*['']s\\s*(profile|review).*$/i, '').trim()\n || null\n const starsEl = card.querySelector('[role=\"img\"][aria-label*=\"star\"]')\n const stars = starsEl?.getAttribute('aria-label') ?? null\n const date = (card.querySelector('span.rsqaWe, [class*=\"rsqaWe\"]') as HTMLElement | null)?.innerText?.trim() ?? null\n const textEl = card.querySelector('span.wiI7pd, [class*=\"wiI7pd\"]') as HTMLElement | null\n const text = textEl?.innerText?.trim() ?? null\n const ownerContainer = card.querySelector('div.CDe7pd, [class*=\"CDe7pd\"]')\n const ownerTextEl = ownerContainer?.querySelector('.wiI7pd, [class*=\"wiI7pd\"]') as HTMLElement | null\n const ownerResponse = ownerTextEl?.innerText?.trim() ?? null\n return { reviewId, author, stars, date, text, ownerResponse }\n })\n }, maxReviews)\n }\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 { Hono } from 'hono'\nimport { createMiddleware } from 'hono/factory'\nimport { creditMc, debitMc, getUserByApiKey } from './db.js'\nimport { MC_COSTS, insufficientBalanceResponse } from './rates.js'\nimport { MapsExtractor } from '../extractor/MapsExtractor.js'\nimport { BrowserDriver } from '../driver/BrowserDriver.js'\nimport { MapsPlaceOptionsSchema } from '../schemas.js'\nimport type { User } from './db.js'\n\ntype MapsEnv = { Variables: { user: User } }\n\nconst mapsAuth = createMiddleware<MapsEnv>(async (c, next) => {\n const key = c.req.header('x-api-key')\n if (!key) return c.json({ error: 'Missing API key' }, 401)\n const user = await getUserByApiKey(key)\n if (!user) return c.json({ error: 'Invalid or inactive API key' }, 401)\n c.set('user', user)\n return next()\n})\n\nexport const mapsApp = new Hono<MapsEnv>()\n\nmapsApp.post('/place', mapsAuth, async (c) => {\n const user = c.get('user')\n const body = await c.req.json().catch(() => ({}))\n const parsed = MapsPlaceOptionsSchema.safeParse({\n kernelApiKey: process.env.KERNEL_API_KEY,\n ...body,\n })\n if (!parsed.success) {\n return c.json({ error: parsed.error.issues[0]?.message ?? 'Invalid request' }, 400)\n }\n\n const { ok, balance_mc } = await debitMc(\n user.id,\n MC_COSTS.maps_place,\n 'maps_place',\n `${parsed.data.businessName} ${parsed.data.location}`,\n )\n if (!ok) return c.json(insufficientBalanceResponse(balance_mc, MC_COSTS.maps_place), 402)\n\n try {\n const driver = new BrowserDriver()\n const extractor = new MapsExtractor(driver)\n const result = await extractor.extract(parsed.data)\n return c.json(result)\n } catch (err) {\n await creditMc(user.id, MC_COSTS.maps_place, 'refund', 'failed maps_place call')\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.includes('CAPTCHA') || msg.includes('blocked')) {\n return c.json({ error: msg }, 503)\n }\n return c.json({ error: msg }, 500)\n }\n})\n","import { z } from 'zod'\n\nexport const HarvestPaaInputSchema = {\n query: z.string().min(1).describe('Search query to harvest PAA questions for'),\n location: z.string().optional().describe('Location name for geo-targeted results'),\n maxQuestions: z.number().int().min(1).max(100).default(30).describe('Number of PAA questions to extract (max 100)'),\n gl: z.string().length(2).default('us'),\n hl: z.string().default('en'),\n}\nexport type HarvestPaaInput = z.infer<ReturnType<typeof z.object<typeof HarvestPaaInputSchema>>>\n\nexport const ExtractUrlInputSchema = {\n url: z.string().url(),\n}\nexport type ExtractUrlInput = z.infer<ReturnType<typeof z.object<typeof ExtractUrlInputSchema>>>\n\nexport const MapSiteUrlsInputSchema = {\n url: z.string().url(),\n maxUrls: z.number().int().min(1).max(500).optional(),\n}\nexport type MapSiteUrlsInput = z.infer<ReturnType<typeof z.object<typeof MapSiteUrlsInputSchema>>>\n\nexport const ExtractSiteInputSchema = {\n url: z.string().url(),\n maxPages: z.number().int().min(1).max(50).optional(),\n}\nexport type ExtractSiteInput = z.infer<ReturnType<typeof z.object<typeof ExtractSiteInputSchema>>>\n\nexport const YoutubeHarvestInputSchema = {\n mode: z.enum(['search', 'channel']),\n query: z.string().optional().describe('Required when mode is search'),\n channelHandle: z.string().optional().describe('YouTube channel handle, e.g. @mkbhd'),\n maxVideos: z.number().int().min(1).max(500).default(50),\n}\nexport type YoutubeHarvestInput = z.infer<ReturnType<typeof z.object<typeof YoutubeHarvestInputSchema>>>\n\nexport const YoutubeTranscribeInputSchema = {\n videoId: z.string().min(1).describe('YouTube video ID, e.g. dQw4w9WgXcQ'),\n}\nexport type YoutubeTranscribeInput = z.infer<ReturnType<typeof z.object<typeof YoutubeTranscribeInputSchema>>>\n\nexport const FacebookPageIntelInputSchema = {\n pageId: z.string().optional(),\n libraryId: z.string().optional(),\n query: z.string().optional().describe('One of pageId, libraryId, or query is required'),\n maxAds: z.number().int().min(1).max(200).default(50),\n country: z.string().length(2).default('US'),\n}\nexport type FacebookPageIntelInput = z.infer<ReturnType<typeof z.object<typeof FacebookPageIntelInputSchema>>>\n\nexport const FacebookAdSearchInputSchema = {\n query: z.string().min(1),\n country: z.string().length(2).default('US'),\n maxResults: z.number().int().min(1).max(20).default(10),\n}\nexport type FacebookAdSearchInput = z.infer<ReturnType<typeof z.object<typeof FacebookAdSearchInputSchema>>>\n\nexport const FacebookAdTranscribeInputSchema = {\n videoUrl: z.string().url().describe('Facebook CDN video URL from a facebook_page_intel result'),\n}\nexport type FacebookAdTranscribeInput = z.infer<ReturnType<typeof z.object<typeof FacebookAdTranscribeInputSchema>>>\n\nexport const MapsPlaceIntelInputSchema = {\n businessName: z.string().min(1).describe('Business name to search for on Google Maps'),\n location: z.string().min(1).describe('City and state, e.g. \"Denver, CO\"'),\n gl: z.string().length(2).default('us'),\n hl: z.string().length(2).default('en'),\n includeReviews: z.boolean().default(false).describe('Whether to fetch individual review cards'),\n maxReviews: z.number().int().min(1).max(500).default(50).describe('Max review cards to return (requires includeReviews: true)'),\n}\nexport type MapsPlaceIntelInput = z.infer<ReturnType<typeof z.object<typeof MapsPlaceIntelInputSchema>>>\n\nexport const CreditsInfoInputSchema = {\n item: z.string().optional().describe('Optional tool, action, or feature to look up, e.g. \"maps reviews\", \"extract_url\", or \"YouTube transcription\"'),\n includeLedger: z.boolean().default(false).describe('Whether to include recent credit ledger entries'),\n}\nexport type CreditsInfoInput = z.infer<ReturnType<typeof z.object<typeof CreditsInfoInputSchema>>>\n\nexport const SearchSerpInputSchema = {\n query: z.string().min(1).describe('Search query to retrieve organic Google results for'),\n location: z.string().optional().describe('Location name for geo-targeted results'),\n gl: z.string().length(2).default('us'),\n hl: z.string().default('en'),\n pages: z.number().int().min(1).max(2).default(1).describe('Number of result pages to fetch (1–2)'),\n}\nexport type SearchSerpInput = z.infer<ReturnType<typeof z.object<typeof SearchSerpInputSchema>>>\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\n\nfunction twoBlocks(full: string, summary: string): CallToolResult {\n return { content: [{ type: 'text', text: full }, { type: 'text', text: summary }] }\n}\n\nexport function passthrough(raw: CallToolResult): CallToolResult {\n return raw\n}\n\nfunction checkInsufficientBalance(raw: CallToolResult): CallToolResult | null {\n const first = raw.content.find(b => b.type === 'text')\n const text = first?.type === 'text' ? first.text : ''\n try {\n const body = JSON.parse(text || '{}') as Record<string, unknown>\n if (body.error === 'insufficient_balance') {\n return {\n isError: true,\n content: [{\n type: 'text',\n text: `Insufficient credits. Balance: ${body.balance_credits} credits. This call requires ${body.required_credits} credits. Top up at ${body.topup_url}`,\n }],\n }\n }\n } catch { }\n return null\n}\n\nfunction parseData(raw: CallToolResult): { data: Record<string, unknown> } | { error: string } {\n const first = raw.content.find(b => b.type === 'text')\n const text = first?.type === 'text' ? first.text : ''\n try {\n const parsed = JSON.parse(text || '{}') as Record<string, unknown>\n if (parsed.error === 'insufficient_balance') {\n return { error: `Insufficient credits. Balance: ${parsed.balance_credits} credits. This call requires ${parsed.required_credits} credits. Top up at ${parsed.topup_url}` }\n }\n if (raw.isError) return { error: text || 'Tool error' }\n const data = (parsed.result as Record<string, unknown>) ?? parsed\n return { data }\n } catch {\n if (raw.isError) return { error: text || 'Tool error' }\n return { error: 'Failed to parse tool response' }\n }\n}\n\nfunction entityIdsSection(ids?: { kgIds?: string[]; cids?: string[]; gcids?: string[] }): string {\n if (!ids) return ''\n const lines: string[] = []\n if (ids.kgIds?.length) lines.push(`- **Knowledge Graph MID:** ${ids.kgIds.join(', ')}`)\n if (ids.cids?.length) lines.push(`- **CID:** ${ids.cids.join(', ')}`)\n if (ids.gcids?.length) lines.push(`- **GCID:** ${ids.gcids.join(', ')}`)\n return lines.length ? `\\n## Entity IDs\\n${lines.join('\\n')}` : ''\n}\n\nfunction entityIdsSummaryLine(ids?: { kgIds?: string[]; cids?: string[]; gcids?: string[] }): string {\n if (!ids) return ''\n const parts: string[] = []\n if (ids.kgIds?.length) parts.push(`KG MID: ${ids.kgIds[0]}`)\n if (ids.cids?.length) parts.push(`CID: ${ids.cids[0]}`)\n if (ids.gcids?.length) parts.push(`GCID: ${ids.gcids[0]}`)\n return parts.length ? `\\n**Entity IDs:** ${parts.join(' · ')}` : ''\n}\n\nfunction truncate(s: string | null | undefined, max: number): string {\n if (!s) return ''\n return s.length > max ? s.slice(0, max) + '…' : s\n}\n\nconst DIRECTIVE_FULL = '> 📄 **FULL REPORT** — render as artifact or expandable block\\n\\n'\nconst DIRECTIVE_SUMMARY = '> 💬 **SUMMARY** — present this inline; offer the full report above as an artifact\\n\\n'\n\ninterface FlatRow { question: string; answer?: string; source_site?: string }\ninterface OrganicResult { position: number; title: string; url: string; domain: string; snippet?: string | null }\ninterface AIOverview { detected: boolean; text?: string | null }\n\nexport function formatHarvestPaa(\n raw: CallToolResult,\n input: { query: string; maxQuestions?: number; location?: string },\n): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data\n\n const flat = (d.flat as FlatRow[]) ?? []\n const organic = (d.organicResults as OrganicResult[]) ?? []\n const entityIds = d.entityIds as { kgIds?: string[]; cids?: string[]; gcids?: string[] } | undefined\n const aiOvw = d.aiOverview as AIOverview | undefined\n const durationMs = (d.stats as { durationMs?: number } | undefined)?.durationMs\n\n const paaRows = flat.map((r, i) =>\n `| ${i + 1} | ${r.question} | ${truncate(r.answer, 120)} | ${r.source_site ?? ''} |`,\n ).join('\\n')\n\n const paaTable = flat.length\n ? `## People Also Ask (${flat.length} questions)\\n| # | Question | Answer | Source |\\n|---|----------|--------|--------|\\n${paaRows}`\n : '## People Also Ask\\n*No questions extracted*'\n\n const serpRows = organic.map(r =>\n `| ${r.position} | ${r.title} | [${r.domain}](${r.url}) | ${truncate(r.snippet, 100)} |`,\n ).join('\\n')\n\n const serpTable = organic.length\n ? `\\n## Organic Results (${organic.length})\\n| # | Title | URL | Snippet |\\n|---|-------|-----|----------|\\n${serpRows}`\n : ''\n\n const aiSection = aiOvw?.detected && aiOvw.text\n ? `\\n## AI Overview\\n> ${truncate(aiOvw.text, 600)}`\n : ''\n\n const statsLine = durationMs\n ? `\\n## Stats\\n- Questions: ${flat.length} · Duration: ${(durationMs / 1000).toFixed(1)}s`\n : ''\n\n const tips = `\\n---\\n💡 **Tips**\\n- Max questions: \\`maxQuestions: 100\\` (current: ${input.maxQuestions ?? 30})\\n- Organic results only: use \\`search_serp\\`\\n- Dig into a result: use \\`extract_url\\` on any organic URL`\n\n const full = `${DIRECTIVE_FULL}# PAA Report: \"${input.query}\"${input.location ? ` · ${input.location}` : ''}\\n\\n${paaTable}${serpTable}${entityIdsSection(entityIds)}${aiSection}${statsLine}${tips}`\n\n const topQ = flat.slice(0, 10).map((r, i) => `${i + 1}. ${r.question}`).join('\\n')\n const topO = organic.slice(0, 5).map(r => `${r.position}. [${r.title}](${r.url}) — ${r.domain}`).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**PAA: \"${input.query}\"** — ${flat.length} questions extracted`,\n topQ ? `\\n**Top questions:**\\n${topQ}` : '',\n organic.length ? `\\n**Top organic results:**\\n${topO}` : '',\n entityIdsSummaryLine(entityIds),\n `\\n💡 \\`maxQuestions\\` up to 100 ·Use \\`extract_url\\` to dig into any result`,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface LocalBusiness { position: number; name: string; rating?: string | null; reviewCount?: string | null; websiteUrl?: string | null }\n\nexport function formatSearchSerp(\n raw: CallToolResult,\n input: { query: string; location?: string },\n): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data\n\n const organic = (d.organicResults as OrganicResult[]) ?? []\n const localPack = (d.localPack as LocalBusiness[]) ?? []\n const entityIds = d.entityIds as { kgIds?: string[]; cids?: string[]; gcids?: string[] } | undefined\n const aiOvw = d.aiOverview as AIOverview | undefined\n\n const serpRows = organic.map(r =>\n `| ${r.position} | ${r.title} | [${r.domain}](${r.url}) | ${truncate(r.snippet, 100)} |`,\n ).join('\\n')\n\n const serpTable = organic.length\n ? `## Organic Results (${organic.length})\\n| # | Title | URL | Snippet |\\n|---|-------|-----|----------|\\n${serpRows}`\n : '## Organic Results\\n*None found*'\n\n const localRows = localPack.map(b =>\n `| ${b.position} | ${b.name} | ${b.rating ?? '—'} (${b.reviewCount ?? '0'}) | ${b.websiteUrl ? `[link](${b.websiteUrl})` : '—'} |`,\n ).join('\\n')\n\n const localSection = localPack.length\n ? `\\n## Local Pack (${localPack.length})\\n| # | Name | Rating | Website |\\n|---|------|--------|---------|\\n${localRows}`\n : ''\n\n const aiSection = aiOvw?.detected && aiOvw.text\n ? `\\n## AI Overview\\n> ${truncate(aiOvw.text, 600)}`\n : ''\n\n const tips = `\\n---\\n💡 **Tips**\\n- Get PAA questions: use \\`harvest_paa\\` for this query\\n- Scrape any result: use \\`extract_url\\`\\n- Business entity IDs (CID/GCID/KG MID) shown above if found`\n\n const full = `${DIRECTIVE_FULL}# SERP Report: \"${input.query}\"${input.location ? ` · ${input.location}` : ''}\\n\\n${serpTable}${localSection}${entityIdsSection(entityIds)}${aiSection}${tips}`\n\n const topO = organic.slice(0, 5).map(r => `${r.position}. [${r.title}](${r.url}) — ${r.domain}`).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**SERP: \"${input.query}\"** — ${organic.length} organic results`,\n topO ? `\\n**Top results:**\\n${topO}` : '',\n localPack.length ? `\\n**Local Pack:** ${localPack.map(b => b.name).join(', ')}` : '',\n entityIdsSummaryLine(entityIds),\n `\\n💡 Use \\`harvest_paa\\` for questions · \\`extract_url\\` to scrape any result`,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface Heading { level: number; text: string }\ninterface KpoResult {\n entityName?: string | null; type?: string[]; napScore?: number\n address?: string | null; phone?: string | null; email?: string | null\n sameAs?: string[]; missingFields?: string[]; faqCount?: number\n}\n\nexport function formatExtractUrl(raw: CallToolResult, input: { url: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data\n\n const url = (d.url as string) ?? input.url\n const title = (d.title as string | null) ?? 'Untitled'\n const headings = (d.headings as Heading[]) ?? []\n const kpo = d.kpo as KpoResult | undefined\n const bodyMd = (d.bodyMarkdown as string | null) ?? ''\n const schema = d.schema as unknown[]\n\n const h1Lines = headings.filter(h => h.level === 1).map(h => `- ${h.text}`).join('\\n')\n const h2Lines = headings.filter(h => h.level === 2).map(h => ` - ${h.text}`).join('\\n')\n const headingSection = (h1Lines || h2Lines)\n ? `\\n## Heading Structure\\n${[h1Lines, h2Lines].filter(Boolean).join('\\n')}`\n : ''\n\n const kpoSection = kpo ? [\n `\\n## Entity / Schema`,\n kpo.entityName ? `- **Entity:** ${kpo.entityName}` : '',\n kpo.type?.length ? `- **@type:** ${kpo.type.join(', ')}` : '',\n kpo.napScore !== undefined ? `- **NAP Score:** ${kpo.napScore}/5` : '',\n kpo.address ? `- **Address:** ${kpo.address}` : '',\n kpo.phone ? `- **Phone:** ${kpo.phone}` : '',\n kpo.email ? `- **Email:** ${kpo.email}` : '',\n kpo.faqCount ? `- **FAQ items:** ${kpo.faqCount}` : '',\n kpo.sameAs?.length ? `- **sameAs:** ${kpo.sameAs.slice(0, 5).join(', ')}` : '',\n kpo.missingFields?.length ? `\\n**Missing schema fields:** ${kpo.missingFields.slice(0, 5).join(', ')}` : '',\n ].filter(Boolean).join('\\n') : ''\n\n const bodySection = bodyMd\n ? `\\n## Page Content\\n${bodyMd.slice(0, 3000)}${bodyMd.length > 3000 ? '\\n\\n*(truncated)*' : ''}`\n : ''\n\n const schemaCount = Array.isArray(schema) ? schema.length : 0\n const tips = `\\n---\\n💡 **Tips**\\n- Crawl entire site: use \\`extract_site\\`\\n- Map all URLs: use \\`map_site_urls\\`\\n- ${schemaCount} JSON-LD schema block(s) detected`\n\n const full = `${DIRECTIVE_FULL}# URL Extract: ${url}\\n**${title}**\\n${headingSection}${kpoSection}${bodySection}${tips}`\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**Extracted:** ${title}`,\n `**URL:** ${url}`,\n kpo?.entityName ? `**Entity:** ${kpo.entityName} (${kpo.type?.join(', ') ?? 'unknown'})` : '',\n kpo?.napScore !== undefined ? `**NAP Score:** ${kpo.napScore}/5` : '',\n headings.length ? `**${headings.length} headings**` : '',\n `\\n💡 Use \\`extract_site\\` to crawl the full domain`,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface DiscoveredUrl { url: string; status: number | null }\ninterface SpiderResult { startUrl: string; urls: DiscoveredUrl[]; totalFound: number; durationMs: number; truncated: boolean }\n\nexport function formatMapSiteUrls(raw: CallToolResult, input: { url: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as unknown as SpiderResult\n\n const urls = d.urls ?? []\n const ok = urls.filter(u => (u.status ?? 0) >= 200 && (u.status ?? 0) < 300)\n const broken = urls.filter(u => u.status !== null && u.status >= 400)\n const redirects = urls.filter(u => u.status !== null && u.status >= 300 && u.status < 400)\n\n const urlRows = urls.slice(0, 200).map((u, i) => `| ${i + 1} | ${u.url} | ${u.status ?? '—'} |`).join('\\n')\n\n const full = [\n `${DIRECTIVE_FULL}# URL Map: ${input.url}`,\n `**${d.totalFound} URLs** · ${(d.durationMs / 1000).toFixed(1)}s${d.truncated ? ' · *truncated*' : ''}`,\n `\\n## Summary\\n- ✅ 2xx: ${ok.length}\\n- 🔀 3xx: ${redirects.length}\\n- ❌ 4xx+: ${broken.length}`,\n `\\n## URL Inventory\\n| # | URL | Status |\\n|---|-----|--------|\\n${urlRows}`,\n broken.length ? `\\n## Broken URLs\\n${broken.map(u => `- ${u.url} (${u.status})`).join('\\n')}` : '',\n `\\n---\\n💡 **Tips**\\n- Extract content from all pages: use \\`extract_site\\`\\n- Scrape a single page: use \\`extract_url\\``,\n ].filter(Boolean).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**URL Map: ${input.url}**`,\n `${d.totalFound} URLs — ${ok.length} OK · ${broken.length} broken · ${redirects.length} redirects`,\n broken.length ? `\\n**Broken URLs:** ${broken.slice(0, 3).map(u => u.url).join(', ')}` : '',\n `\\n💡 Use \\`extract_site\\` to extract content from all pages`,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface SitePageResult { url: string; title?: string | null; kpo?: KpoResult; schema?: unknown[] }\ninterface ExtractSiteResult { pages: SitePageResult[]; durationMs?: number }\n\nexport function formatExtractSite(raw: CallToolResult, input: { url: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as unknown as ExtractSiteResult\n\n const pages = d.pages ?? []\n\n const pageRows = pages.map((p, i) => {\n const schemaInfo = p.kpo?.type?.join(', ') ?? (Array.isArray(p.schema) && p.schema.length ? `${p.schema.length} block(s)` : '—')\n return `| ${i + 1} | ${p.title ?? 'Untitled'} | ${p.url} | ${schemaInfo} |`\n }).join('\\n')\n\n const full = [\n `${DIRECTIVE_FULL}# Site Extract: ${input.url}`,\n `**${pages.length} pages** · ${(((d.durationMs ?? 0)) / 1000).toFixed(1)}s`,\n `\\n## Pages\\n| # | Title | URL | Schema |\\n|---|-------|-----|--------|\\n${pageRows}`,\n `\\n---\\n💡 **Tips**\\n- Map URLs first: use \\`map_site_urls\\`\\n- Inspect a single page: use \\`extract_url\\``,\n ].join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**Site Extract: ${input.url}** — ${pages.length} pages`,\n pages.slice(0, 5).map(p => `- ${p.title ?? p.url}`).join('\\n'),\n pages.length > 5 ? `- … and ${pages.length - 5} more` : '',\n `\\n💡 Use \\`extract_url\\` to inspect any individual page`,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface YTVideo { videoId: string; title: string; channelName: string; views?: string | null; duration?: string | null; url: string }\ninterface YTHarvestResult { videos: YTVideo[]; channelMeta?: { title?: string; subscriberCount?: string | null } | null; stats: { durationMs: number } }\n\nexport function formatYoutubeHarvest(\n raw: CallToolResult,\n input: { mode: string; query?: string; channelHandle?: string },\n): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as unknown as YTHarvestResult\n\n const videos = d.videos ?? []\n const label = input.mode === 'channel' ? (input.channelHandle ?? 'channel') : `\"${input.query ?? ''}\"`\n\n const videoRows = videos.map((v, i) =>\n `| ${i + 1} | ${truncate(v.title, 70)} | ${v.channelName} | ${v.views ?? '—'} | ${v.duration ?? '—'} | \\`${v.videoId}\\` |`,\n ).join('\\n')\n\n const channelSection = d.channelMeta\n ? `\\n## Channel\\n- **Name:** ${d.channelMeta.title ?? '—'}\\n- **Subscribers:** ${d.channelMeta.subscriberCount ?? '—'}`\n : ''\n\n const full = [\n `${DIRECTIVE_FULL}# YouTube Harvest: ${label}`,\n `**${videos.length} videos** · ${(d.stats.durationMs / 1000).toFixed(1)}s`,\n channelSection,\n `\\n## Videos\\n| # | Title | Channel | Views | Duration | Video ID |\\n|---|-------|---------|-------|----------|----------|\\n${videoRows}`,\n `\\n---\\n💡 **Tips**\\n- Transcribe a video: use \\`youtube_transcribe\\` with the \\`videoId\\` above\\n- Switch mode: \\`mode: \"channel\"\\` with \\`channelHandle\\` or \\`mode: \"search\"\\` with \\`query\\``,\n ].filter(Boolean).join('\\n')\n\n const top5 = videos.slice(0, 5).map((v, i) => `${i + 1}. ${v.title} (\\`${v.videoId}\\`)`).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**YouTube: ${label}** — ${videos.length} videos`,\n `\\n**Top videos:**\\n${top5}`,\n `\\n💡 Transcribe any video: \\`youtube_transcribe\\` with its videoId`,\n ].join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface TranscriptChunk { startMs: number; text: string }\ninterface TranscriptResult { text: string; chunks?: TranscriptChunk[]; durationMs?: number }\n\nexport function formatYoutubeTranscribe(raw: CallToolResult, input: { videoId: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as unknown as TranscriptResult\n\n const text = d.text ?? ''\n const chunks = d.chunks ?? []\n const durSec = d.durationMs ? (d.durationMs / 1000).toFixed(0) : '—'\n\n const chunkRows = chunks.slice(0, 50).map(c => {\n const sec = Math.floor(c.startMs / 1000)\n const mm = String(Math.floor(sec / 60)).padStart(2, '0')\n const ss = String(sec % 60).padStart(2, '0')\n return `| ${mm}:${ss} | ${truncate(c.text, 120)} |`\n }).join('\\n')\n\n const full = [\n `${DIRECTIVE_FULL}# YouTube Transcript: \\`${input.videoId}\\``,\n `**Duration:** ${durSec}s · **${text.split(' ').length} words**`,\n `\\n## Full Transcript\\n${text}`,\n chunks.length ? `\\n## Timestamped Chunks\\n| Time | Text |\\n|------|------|\\n${chunkRows}` : '',\n `\\n---\\n💡 Harvest more from this channel: use \\`youtube_harvest\\` with \\`mode: \"channel\"\\``,\n ].filter(Boolean).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**YouTube Transcript: \\`${input.videoId}\\`** — ${text.split(' ').length} words · ${durSec}s`,\n `\\n**Preview:**\\n> ${truncate(text, 300)}`,\n `\\n💡 Full transcript in artifact above`,\n ].join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface FbAd {\n libraryId?: string; status?: string; creativeType?: string\n headline?: string | null; primaryText?: string | null; cta?: string | null\n startDate?: string | null; videoUrl?: string | null; variations?: number\n}\ninterface FbPageResult {\n advertiserName?: string | null\n summary: { totalAds: number; activeCount: number; videoCount: number; imageCount: number }\n ads: FbAd[]\n}\n\nexport function formatFacebookPageIntel(\n raw: CallToolResult,\n input: { pageId?: string; libraryId?: string; query?: string },\n): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as unknown as FbPageResult\n\n const advertiser = d.advertiserName ?? input.query ?? input.pageId ?? input.libraryId ?? 'Advertiser'\n const ads = d.ads ?? []\n const s = d.summary ?? { totalAds: 0, activeCount: 0, videoCount: 0, imageCount: 0 }\n\n const adBlocks = ads.map((ad, i) => [\n `### Ad ${i + 1}${ad.libraryId ? ` · \\`${ad.libraryId}\\`` : ''} — ${ad.status ?? '—'} · ${ad.creativeType ?? '—'} · ${ad.startDate ?? '—'}`,\n ad.headline ? `**Headline:** ${ad.headline}` : '',\n ad.primaryText ? `**Copy:** ${truncate(ad.primaryText, 200)}` : '',\n ad.cta ? `**CTA:** ${ad.cta}` : '',\n ad.videoUrl ? `**Video URL:** \\`${ad.videoUrl}\\`` : '',\n ad.variations ? `**Variations:** ${ad.variations}` : '',\n ].filter(Boolean).join('\\n')).join('\\n\\n---\\n\\n')\n\n const full = [\n `${DIRECTIVE_FULL}# Facebook Ad Intel: ${advertiser}`,\n `**${s.totalAds} ads** · ${s.activeCount} active · ${s.videoCount} video · ${s.imageCount} image`,\n `\\n${adBlocks}`,\n `\\n---\\n💡 **Tips**\\n- Transcribe video ads: use \\`facebook_ad_transcribe\\` with the \\`videoUrl\\` above\\n- Find other advertisers: use \\`facebook_ad_search\\``,\n ].filter(Boolean).join('\\n')\n\n const activeAds = ads.filter(a => a.status?.toLowerCase() === 'active').slice(0, 5)\n const adSummary = activeAds.map((a, i) => `${i + 1}. ${truncate(a.headline ?? a.primaryText, 80)} (${a.creativeType ?? '—'})`).join('\\n')\n const videoCount = ads.filter(a => a.videoUrl).length\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**Facebook Ads: ${advertiser}** — ${s.totalAds} ads (${s.activeCount} active)`,\n adSummary ? `\\n**Active ads:**\\n${adSummary}` : '',\n `**Creative mix:** ${s.videoCount} video · ${s.imageCount} image`,\n videoCount ? `\\n💡 ${videoCount} video ads — transcribe with \\`facebook_ad_transcribe\\` using the videoUrl` : '',\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface FbAdvertiserResult { name: string; adCount?: number; libraryId?: string }\ninterface FbSearchResult { results?: FbAdvertiserResult[]; advertisers?: FbAdvertiserResult[] }\n\nexport function formatFacebookAdSearch(raw: CallToolResult, input: { query: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as unknown as FbSearchResult\n\n const advertisers = d.results ?? d.advertisers ?? []\n\n const rows = advertisers.map((a, i) =>\n `| ${i + 1} | ${a.name} | ${a.adCount ?? '—'} | \\`${a.libraryId ?? '—'}\\` |`,\n ).join('\\n')\n\n const full = [\n `${DIRECTIVE_FULL}# Facebook Ad Library Search: \"${input.query}\"`,\n `**${advertisers.length} advertisers found**`,\n `\\n## Advertisers\\n| # | Name | Ad Count | Library ID |\\n|---|------|----------|------------|\\n${rows}`,\n `\\n---\\n💡 **Tips**\\n- Scan all ads: use \\`facebook_page_intel\\` with \\`libraryId\\`\\n- Or pass the advertiser name as \\`query\\` in \\`facebook_page_intel\\``,\n ].join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**Facebook Ad Search: \"${input.query}\"** — ${advertisers.length} advertisers`,\n advertisers.slice(0, 5).map((a, i) =>\n `${i + 1}. ${a.name}${a.adCount ? ` (${a.adCount} ads)` : ''} — \\`${a.libraryId ?? '—'}\\``,\n ).join('\\n'),\n `\\n💡 Scan ads with \\`facebook_page_intel\\` using \\`libraryId\\``,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface MapsReviewCard { author: string | null; stars: string | null; date: string | null; text: string | null }\ninterface MapsHistogramEntry { stars: number; count: string }\ninterface MapsTopicEntry { label: string; count: string }\ninterface MapsAboutEntry { section: string; attribute: string }\ninterface CreditCostEntry { key: string; label: string; credits: number; unit: string; notes?: string }\ninterface CreditLedgerEntry { amount_mc: number; operation: string; description: string | null; created_at: string }\n\nexport function formatCreditsInfo(raw: CallToolResult, input: { item?: string; includeLedger?: boolean }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as Record<string, unknown>\n\n const balance = d.balance_credits as number | undefined\n const costs = (d.costs as CreditCostEntry[] | undefined) ?? []\n const matched = d.matched_cost as CreditCostEntry | null\n const ledger = (d.ledger as CreditLedgerEntry[] | undefined) ?? []\n\n const costRows = costs.map(c => {\n const notes = c.notes ? ` ${c.notes}` : ''\n return `| ${c.label} | ${c.credits} | ${c.unit}${notes} |`\n }).join('\\n')\n\n const ledgerRows = ledger.map(row => {\n const credits = row.amount_mc / 1000\n return `| ${row.created_at} | ${row.operation} | ${credits} | ${row.description ?? ''} |`\n }).join('\\n')\n\n const matchedSection = matched\n ? `\\n## Matched Cost\\n**${matched.label}:** ${matched.credits} credits ${matched.unit}${matched.notes ? `\\n\\n${matched.notes}` : ''}`\n : input.item\n ? `\\n## Matched Cost\\nNo exact cost match found for \"${input.item}\". See the full cost table below.`\n : ''\n\n const full = [\n `${DIRECTIVE_FULL}# Credits`,\n `**Balance:** ${balance ?? 'unknown'} credits`,\n matchedSection,\n costs.length ? `\\n## Cost Table\\n| Item | Credits | Unit |\\n|------|---------|------|\\n${costRows}` : '',\n ledger.length ? `\\n## Recent Ledger\\n| Date | Operation | Credits | Description |\\n|------|-----------|---------|-------------|\\n${ledgerRows}` : '',\n ].filter(Boolean).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**Credit balance:** ${balance ?? 'unknown'} credits`,\n matched ? `\\n**${matched.label}:** ${matched.credits} credits ${matched.unit}` : null,\n input.includeLedger && ledger.length ? `\\nRecent ledger entries included in the full report.` : null,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\nexport function formatMapsPlaceIntel(\n raw: CallToolResult,\n input: { businessName: string; location: string; includeReviews?: boolean },\n): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as Record<string, unknown>\n\n const name = (d.name as string | null) ?? input.businessName\n const rating = d.rating as string | null\n const reviewCount = d.reviewCount as string | null\n const category = d.category as string | null\n const address = d.address as string | null\n const phone = d.phoneDisplay as string | null\n const website = d.website as string | null\n const hoursSummary = d.hoursSummary as string | null\n const plusCode = d.plusCode as string | null\n const bookingUrl = d.bookingUrl as string | null\n const kgmid = d.kgmid as string | null\n const cidDecimal = d.cidDecimal as string | null\n const cidUrl = d.cidUrl as string | null\n const lat = d.lat as number | null\n const lng = d.lng as number | null\n const durationMs = d.durationMs as number | null\n\n const histogram = (d.reviewHistogram as MapsHistogramEntry[]) ?? []\n const topics = (d.reviewTopics as MapsTopicEntry[]) ?? []\n const about = (d.aboutAttributes as MapsAboutEntry[]) ?? []\n const reviews = (d.reviews as MapsReviewCard[]) ?? []\n\n const hoursTable = (d.hoursTable as Array<{ day: string; hours: string }>) ?? []\n\n const ratingLine = [rating, reviewCount ? `(${reviewCount} reviews)` : null].filter(Boolean).join(' ')\n\n const basicLines = [\n address ? `- **Address:** ${address}` : null,\n phone ? `- **Phone:** ${phone}` : null,\n website ? `- **Website:** ${website}` : null,\n hoursSummary ? `- **Hours:** ${hoursSummary}` : null,\n plusCode ? `- **Plus Code:** ${plusCode}` : null,\n bookingUrl ? `- **Book:** ${bookingUrl}` : null,\n ].filter(Boolean).join('\\n')\n\n const hoursSection = hoursTable.length\n ? `\\n## Hours\\n| Day | Hours |\\n|-----|-------|\\n${hoursTable.map(r => `| ${r.day} | ${r.hours} |`).join('\\n')}`\n : ''\n\n const histSection = histogram.length\n ? `\\n## Rating Distribution\\n| Stars | Count |\\n|-------|-------|\\n${histogram.map(r => `| ${'★'.repeat(r.stars)}${'☆'.repeat(5 - r.stars)} | ${r.count} |`).join('\\n')}`\n : ''\n\n const topicsSection = topics.length\n ? `\\n## Review Topics\\n${topics.map(t => `- **${t.label}:** ${t.count} mentions`).join('\\n')}`\n : ''\n\n const aboutBySection: Record<string, string[]> = {}\n for (const a of about) {\n if (!aboutBySection[a.section]) aboutBySection[a.section] = []\n aboutBySection[a.section].push(a.attribute)\n }\n const aboutSection = Object.keys(aboutBySection).length\n ? `\\n## About\\n${Object.entries(aboutBySection).map(([s, attrs]) => `**${s}**\\n${attrs.map(a => `- ${a}`).join('\\n')}`).join('\\n\\n')}`\n : ''\n\n const entitySection = [\n kgmid ? `- **KGMID:** \\`${kgmid}\\`` : null,\n cidDecimal ? `- **CID:** \\`${cidDecimal}\\`` : null,\n cidUrl ? `- **Maps CID URL:** ${cidUrl}` : null,\n lat != null && lng != null ? `- **Coordinates:** ${lat}, ${lng}` : null,\n ].filter(Boolean).join('\\n')\n\n const reviewsSection = reviews.length\n ? `\\n## Reviews (${reviews.length})\\n${reviews.map((r, i) => {\n const starsN = parseInt(r.stars ?? '0')\n const stars = '★'.repeat(starsN) + '☆'.repeat(5 - starsN)\n return `### ${i + 1}. ${r.author ?? 'Anonymous'} — ${stars}\\n*${r.date ?? ''}*\\n\\n${r.text ?? ''}`\n }).join('\\n\\n')}`\n : ''\n\n const full = [\n `${DIRECTIVE_FULL}# ${name}`,\n category ? `*${category}*` : null,\n ratingLine ? `\\n**Rating:** ${ratingLine}` : null,\n basicLines ? `\\n${basicLines}` : null,\n hoursSection,\n histSection,\n topicsSection,\n aboutSection,\n entitySection ? `\\n## Entity IDs\\n${entitySection}` : null,\n reviewsSection,\n durationMs != null ? `\\n---\\n*Extracted in ${(durationMs / 1000).toFixed(1)}s*` : null,\n ].filter(Boolean).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**${name}** — ${category ?? 'Business'} · ${ratingLine || 'No rating'}`,\n address ? `📍 ${address}` : null,\n phone ? `📞 ${phone}` : null,\n hoursSummary ? `🕐 ${hoursSummary}` : null,\n website ? `🌐 ${website}` : null,\n reviews.length ? `\\n💬 ${reviews.length} reviews fetched — full list in artifact above` : null,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\nexport function formatFacebookAdTranscribe(raw: CallToolResult, input: { videoUrl: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as unknown as TranscriptResult\n\n const text = d.text ?? ''\n const chunks = d.chunks ?? []\n const durSec = d.durationMs ? (d.durationMs / 1000).toFixed(0) : '—'\n\n const chunkRows = chunks.slice(0, 50).map(c => {\n const sec = Math.floor(c.startMs / 1000)\n const mm = String(Math.floor(sec / 60)).padStart(2, '0')\n const ss = String(sec % 60).padStart(2, '0')\n return `| ${mm}:${ss} | ${truncate(c.text, 120)} |`\n }).join('\\n')\n\n const full = [\n `${DIRECTIVE_FULL}# Facebook Ad Transcript`,\n `**Duration:** ${durSec}s · **${text.split(' ').length} words**`,\n `\\n## Full Transcript\\n${text}`,\n chunks.length ? `\\n## Timestamped Chunks\\n| Time | Text |\\n|------|------|\\n${chunkRows}` : '',\n `\\n---\\n💡 Get more ads from this advertiser: use \\`facebook_page_intel\\``,\n ].filter(Boolean).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**Facebook Ad Transcript** — ${text.split(' ').length} words · ${durSec}s`,\n `\\n**Preview:**\\n> ${truncate(text, 300)}`,\n `\\n💡 Full transcript in artifact above`,\n ].join('\\n')\n\n return twoBlocks(full, summary)\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { IMcpToolExecutor } from './IMcpToolExecutor.js'\nimport {\n HarvestPaaInputSchema,\n SearchSerpInputSchema,\n ExtractUrlInputSchema,\n MapSiteUrlsInputSchema,\n ExtractSiteInputSchema,\n YoutubeHarvestInputSchema,\n YoutubeTranscribeInputSchema,\n FacebookPageIntelInputSchema,\n FacebookAdSearchInputSchema,\n FacebookAdTranscribeInputSchema,\n MapsPlaceIntelInputSchema,\n CreditsInfoInputSchema,\n} from './mcp-tool-schemas.js'\nimport {\n formatHarvestPaa,\n formatSearchSerp,\n formatExtractUrl,\n formatMapSiteUrls,\n formatExtractSite,\n formatYoutubeHarvest,\n formatYoutubeTranscribe,\n formatFacebookPageIntel,\n formatFacebookAdSearch,\n formatFacebookAdTranscribe,\n formatMapsPlaceIntel,\n formatCreditsInfo,\n} from './mcp-response-formatter.js'\n\nexport function buildPaaExtractorMcpServer(executor: IMcpToolExecutor): McpServer {\n const server = new McpServer({ name: 'paa-extractor', version: '1.0.0' })\n\n server.registerTool('harvest_paa', {\n description: 'Extract PAA (People Also Ask) questions from Google Search. Returns full question list with answers, organic SERP, entity IDs (CID/GCID/KG MID), and AI Overview. Use maxQuestions to control volume (up to 40).',\n inputSchema: HarvestPaaInputSchema,\n }, async (input) => formatHarvestPaa(await executor.harvestPaa(input), input))\n\n server.registerTool('search_serp', {\n description: 'Fetch organic Google search results. Returns ranked URLs, titles, snippets, local pack, entity IDs (CID/GCID/KG MID), and AI Overview. Use when you need SERP positions without PAA expansion.',\n inputSchema: SearchSerpInputSchema,\n }, async (input) => formatSearchSerp(await executor.searchSerp(input), input))\n\n server.registerTool('extract_url', {\n description: 'Extract structured data from a single URL: page content as Markdown, heading structure, JSON-LD schema, entity details, NAP score, and missing schema fields. Use for SEO audits and entity validation.',\n inputSchema: ExtractUrlInputSchema,\n }, async (input) => formatExtractUrl(await executor.extractUrl(input), input))\n\n server.registerTool('map_site_urls', {\n description: 'Spider a website to build a complete URL inventory with HTTP status codes. Identifies broken links and redirect chains. Use before extract_site to understand site scope.',\n inputSchema: MapSiteUrlsInputSchema,\n }, async (input) => formatMapSiteUrls(await executor.mapSiteUrls(input), input))\n\n server.registerTool('extract_site', {\n description: 'Run multi-page extraction across an entire website. Returns schema, entity data, headings, and content from each page. Use map_site_urls first to check scope.',\n inputSchema: ExtractSiteInputSchema,\n }, async (input) => formatExtractSite(await executor.extractSite(input), input))\n\n server.registerTool('youtube_harvest', {\n description: 'Harvest YouTube video metadata by search query or channel handle. Returns titles, view counts, durations, and videoIds. Use mode \"search\" for keyword results or \"channel\" for a specific creator.',\n inputSchema: YoutubeHarvestInputSchema,\n }, async (input) => formatYoutubeHarvest(await executor.youtubeHarvest(input), input))\n\n server.registerTool('youtube_transcribe', {\n description: 'Fetch and transcribe captions from a YouTube video. Returns full transcript, timestamped chunks, and word count. Pass a videoId from youtube_harvest results.',\n inputSchema: YoutubeTranscribeInputSchema,\n }, async (input) => formatYoutubeTranscribe(await executor.youtubeTranscribe(input), input))\n\n server.registerTool('facebook_page_intel', {\n description: 'Harvest all ads from a Facebook advertiser. Returns ad copy, headlines, CTAs, creative type, status, and video URLs ready for transcription. Accepts pageId, libraryId, or a brand name as query.',\n inputSchema: FacebookPageIntelInputSchema,\n }, async (input) => formatFacebookPageIntel(await executor.facebookPageIntel(input), input))\n\n server.registerTool('facebook_ad_search', {\n description: 'Search Facebook Ad Library by keyword. Returns advertisers with ad counts and library IDs. Use to discover competitors, then pass libraryId to facebook_page_intel to get their full ad list.',\n inputSchema: FacebookAdSearchInputSchema,\n }, async (input) => formatFacebookAdSearch(await executor.facebookAdSearch(input), input))\n\n server.registerTool('facebook_ad_transcribe', {\n description: 'Transcribe audio from a Facebook ad video. Returns full transcript and timestamped chunks. Use the videoUrl value from facebook_page_intel results.',\n inputSchema: FacebookAdTranscribeInputSchema,\n }, async (input) => formatFacebookAdTranscribe(await executor.facebookAdTranscribe(input), input))\n\n server.registerTool('maps_place_intel', {\n description: 'Extract Google Maps business intelligence for a named business: rating, review count, category, address, phone, website, hours, booking URL, review histogram, review topics, about attributes, and optional review cards. Pass includeReviews: true and maxReviews to fetch individual review text.',\n inputSchema: MapsPlaceIntelInputSchema,\n }, async (input) => formatMapsPlaceIntel(await executor.mapsPlaceIntel(input), input))\n\n server.registerTool('credits_info', {\n description: 'Answer questions about MCP Scraper credits: current credit balance, what a specific tool/action costs, the full cost table, and optionally recent credit ledger entries. Does not expose payment methods or credit card information.',\n inputSchema: CreditsInfoInputSchema,\n }, async (input) => formatCreditsInfo(await executor.creditsInfo(input), input))\n\n return server\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { IMcpToolExecutor } from './IMcpToolExecutor.js'\nimport type {\n HarvestPaaInput,\n SearchSerpInput,\n ExtractUrlInput,\n MapSiteUrlsInput,\n ExtractSiteInput,\n YoutubeHarvestInput,\n YoutubeTranscribeInput,\n FacebookPageIntelInput,\n FacebookAdSearchInput,\n FacebookAdTranscribeInput,\n MapsPlaceIntelInput,\n CreditsInfoInput,\n} from './mcp-tool-schemas.js'\n\nconst STUB_TEXT: Record<string, object> = {\n harvest_paa: { questions: ['What is SEO?'], count: 1 },\n search_serp: { organicResults: [{ position: 1, title: 'Example', url: 'https://example.com', domain: 'example.com', snippet: 'An example.' }], count: 1 },\n extract_url: { url: 'https://example.com', title: 'Example', schema: [] },\n map_site_urls: { urls: ['https://example.com'], count: 1 },\n extract_site: { pages: [{ url: 'https://example.com' }], count: 1 },\n youtube_harvest: { videos: [{ videoId: 'abc', title: 'Test' }], count: 1 },\n youtube_transcribe: { text: 'Hello world', chunks: [], durationMs: 1000 },\n facebook_page_intel: { ads: [], summary: { totalAds: 0 } },\n facebook_ad_search: { results: [], query: 'test' },\n facebook_ad_transcribe: { text: 'Buy now', chunks: [], durationMs: 500 },\n maps_place_intel: { name: 'Example Business', rating: '4.5', reviewCount: '100', category: 'Contractor', address: '123 Main St', phone: '+15555555555', website: 'https://example.com', reviews: [] },\n credits_info: { balance_credits: 100, matched_cost: null, costs: [{ label: 'PAA harvest', credits: 1, unit: 'per crawl' }] },\n}\n\nfunction stubResult(toolName: string): CallToolResult {\n return { content: [{ type: 'text', text: JSON.stringify(STUB_TEXT[toolName]) }] }\n}\n\nexport class StubMcpToolExecutor implements IMcpToolExecutor {\n harvestPaa(_: HarvestPaaInput): Promise<CallToolResult> { return Promise.resolve(stubResult('harvest_paa')) }\n searchSerp(_: SearchSerpInput): Promise<CallToolResult> { return Promise.resolve(stubResult('search_serp')) }\n extractUrl(_: ExtractUrlInput): Promise<CallToolResult> { return Promise.resolve(stubResult('extract_url')) }\n mapSiteUrls(_: MapSiteUrlsInput): Promise<CallToolResult> { return Promise.resolve(stubResult('map_site_urls')) }\n extractSite(_: ExtractSiteInput): Promise<CallToolResult> { return Promise.resolve(stubResult('extract_site')) }\n youtubeHarvest(_: YoutubeHarvestInput): Promise<CallToolResult> { return Promise.resolve(stubResult('youtube_harvest')) }\n youtubeTranscribe(_: YoutubeTranscribeInput): Promise<CallToolResult> { return Promise.resolve(stubResult('youtube_transcribe')) }\n facebookPageIntel(_: FacebookPageIntelInput): Promise<CallToolResult> { return Promise.resolve(stubResult('facebook_page_intel')) }\n facebookAdSearch(_: FacebookAdSearchInput): Promise<CallToolResult> { return Promise.resolve(stubResult('facebook_ad_search')) }\n facebookAdTranscribe(_: FacebookAdTranscribeInput): Promise<CallToolResult> { return Promise.resolve(stubResult('facebook_ad_transcribe')) }\n mapsPlaceIntel(_: MapsPlaceIntelInput): Promise<CallToolResult> { return Promise.resolve(stubResult('maps_place_intel')) }\n creditsInfo(_: CreditsInfoInput): Promise<CallToolResult> { return Promise.resolve(stubResult('credits_info')) }\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { IMcpToolExecutor } from './IMcpToolExecutor.js'\nimport type {\n HarvestPaaInput,\n SearchSerpInput,\n ExtractUrlInput,\n MapSiteUrlsInput,\n ExtractSiteInput,\n YoutubeHarvestInput,\n YoutubeTranscribeInput,\n FacebookPageIntelInput,\n FacebookAdSearchInput,\n FacebookAdTranscribeInput,\n MapsPlaceIntelInput,\n CreditsInfoInput,\n} from './mcp-tool-schemas.js'\n\nexport class HttpMcpToolExecutor implements IMcpToolExecutor {\n private readonly baseUrl: string\n private readonly apiKey: string\n\n constructor(baseUrl: string, apiKey: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n this.apiKey = apiKey\n }\n\n private async call(path: string, body: Record<string, unknown>): Promise<CallToolResult> {\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(290_000),\n })\n const data = await res.json()\n if (!res.ok) {\n return { content: [{ type: 'text', text: JSON.stringify(data) }], isError: true }\n }\n return { content: [{ type: 'text', text: JSON.stringify(data) }] }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n return { content: [{ type: 'text', text: msg }], isError: true }\n }\n }\n\n harvestPaa(input: HarvestPaaInput): Promise<CallToolResult> {\n return this.call('/harvest/sync', input as Record<string, unknown>)\n }\n\n searchSerp(input: SearchSerpInput): Promise<CallToolResult> {\n return this.call('/harvest/sync', { ...input, serpOnly: true } as Record<string, unknown>)\n }\n\n extractUrl(input: ExtractUrlInput): Promise<CallToolResult> {\n return this.call('/extract-url', input as Record<string, unknown>)\n }\n\n mapSiteUrls(input: MapSiteUrlsInput): Promise<CallToolResult> {\n return this.call('/map-urls', input as Record<string, unknown>)\n }\n\n extractSite(input: ExtractSiteInput): Promise<CallToolResult> {\n return this.call('/extract-site', input as Record<string, unknown>)\n }\n\n youtubeHarvest(input: YoutubeHarvestInput): Promise<CallToolResult> {\n return this.call('/youtube/harvest', input as Record<string, unknown>)\n }\n\n youtubeTranscribe(input: YoutubeTranscribeInput): Promise<CallToolResult> {\n return this.call('/youtube/transcribe', input as Record<string, unknown>)\n }\n\n facebookPageIntel(input: FacebookPageIntelInput): Promise<CallToolResult> {\n return this.call('/facebook/page-intel', input as Record<string, unknown>)\n }\n\n facebookAdSearch(input: FacebookAdSearchInput): Promise<CallToolResult> {\n return this.call('/facebook/search', input as Record<string, unknown>)\n }\n\n facebookAdTranscribe(input: FacebookAdTranscribeInput): Promise<CallToolResult> {\n return this.call('/facebook/transcribe', input as Record<string, unknown>)\n }\n\n mapsPlaceIntel(input: MapsPlaceIntelInput): Promise<CallToolResult> {\n return this.call('/maps/place', input as Record<string, unknown>)\n }\n\n creditsInfo(input: CreditsInfoInput): Promise<CallToolResult> {\n return this.call('/billing/credits', input as Record<string, unknown>)\n }\n}\n","import { Hono } from 'hono'\nimport { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js'\nimport { buildPaaExtractorMcpServer } from './paa-mcp-server.js'\nimport { StubMcpToolExecutor } from './stub-mcp-tool-executor.js'\nimport { HttpMcpToolExecutor } from './http-mcp-tool-executor.js'\nimport type { IMcpToolExecutor } from './IMcpToolExecutor.js'\n\nfunction buildExecutor(): IMcpToolExecutor {\n const apiKey = (process.env.MCP_SCRAPER_API_KEY ?? process.env.MCP_API_KEY)?.trim()\n if (!apiKey) return new StubMcpToolExecutor()\n const baseUrl = process.env.MCP_SCRAPER_BASE_URL?.trim() ?? process.env.MCP_BASE_URL?.trim() ?? 'https://mcpscraper.dev'\n return new HttpMcpToolExecutor(baseUrl, apiKey)\n}\n\nexport const mcpApp = new Hono()\n\nmcpApp.all('/', async (c) => {\n try {\n const transport = new WebStandardStreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n enableJsonResponse: true,\n })\n const server = buildPaaExtractorMcpServer(buildExecutor())\n await server.connect(transport)\n return transport.handleRequest(c.req.raw)\n } catch {\n return c.json({ error: 'Internal Server Error' }, 500)\n }\n})\n","import Stripe from 'stripe'\nimport { Hono } from 'hono'\nimport { getUserByStripeCustomerId, getUserByEmail, setStripeCustomerId, creditMc } from './db.js'\nimport { BALANCE_PRICE_IDS, BALANCE_PACK_LABELS } from './rates.js'\n\nconst stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, { apiVersion: '2026-04-22.dahlia' })\nexport const stripeApp = new Hono()\n\nstripeApp.post('/webhooks', async (c) => {\n const sig = c.req.header('stripe-signature')\n const body = await c.req.text()\n let event: Stripe.Event\n try {\n event = stripe.webhooks.constructEvent(body, sig!, process.env.STRIPE_WEBHOOK_SECRET!)\n } catch {\n return c.json({ error: 'Invalid signature' }, 400)\n }\n\n if (event.type === 'checkout.session.completed') {\n const session = event.data.object as Stripe.Checkout.Session\n if (session.payment_status !== 'paid') return c.json({ received: true })\n\n const customerId = session.customer as string\n const lineItems = await stripe.checkout.sessions.listLineItems(session.id)\n const priceId = lineItems.data[0]?.price?.id\n if (!priceId || !(priceId in BALANCE_PRICE_IDS)) return c.json({ received: true })\n\n const mc = BALANCE_PRICE_IDS[priceId]\n const label = BALANCE_PACK_LABELS[priceId] ?? 'unknown'\n\n let user = await getUserByStripeCustomerId(customerId)\n if (!user) {\n const email = session.customer_details?.email\n if (!email) return c.json({ received: true })\n user = await getUserByEmail(email)\n if (!user) return c.json({ received: true })\n await setStripeCustomerId(user.id, customerId)\n }\n\n await creditMc(\n user.id,\n mc,\n 'topup',\n `${label} balance top-up`,\n session.payment_intent as string,\n )\n }\n\n return c.json({ received: true })\n})\n","import { makeSiteAuditService } from '../services/site-architecture-auditor/factory.js'\nimport { dispatchSiteAuditPhase } from '../services/site-architecture-auditor/phases.js'\nimport { SiteAuditRepository } from '../services/site-architecture-auditor/site-audit-repository.js'\nimport type { SiteAuditPhase } from '../services/site-architecture-auditor/schemas.js'\n\nexport const MAX_CONCURRENT_SITE_AUDIT = 1\n\nexport async function drainSiteAuditQueue(budget: { maxJobs: number; deadlineMs: number }): Promise<string[]> {\n const processedIds: string[] = []\n\n while (true) {\n if (processedIds.length >= budget.maxJobs) break\n if (Date.now() >= budget.deadlineMs) break\n\n const repo = new SiteAuditRepository()\n const job = await repo.claimPendingSiteAuditJob()\n if (!job) break\n\n const service = makeSiteAuditService()\n\n try {\n const parsed = JSON.parse(job.request) as { phase: SiteAuditPhase; payload: unknown }\n await dispatchSiteAuditPhase(service, parsed.phase, parsed.payload)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n await repo.failSiteAuditJob(job.id, msg)\n }\n\n processedIds.push(job.id)\n }\n\n return processedIds\n}\n\nexport function startSiteAuditWorker(): NodeJS.Timeout | undefined {\n if (process.env.INNGEST_EVENT_KEY) {\n console.log('[site-audit-worker] Inngest active — polling worker disabled')\n return\n }\n console.log(`[site-audit-worker] started — polling every 5s, max ${MAX_CONCURRENT_SITE_AUDIT} concurrent`)\n return setInterval(() => {\n void drainSiteAuditQueue({ maxJobs: 1, deadlineMs: Date.now() + 4000 })\n }, 5000)\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","import { createHmac, timingSafeEqual } from 'node:crypto'\n\nconst isProduction = () => process.env.NODE_ENV === 'production' || process.env.VERCEL === '1'\n\nconst secret = () => {\n const configured = process.env.SESSION_SECRET?.trim()\n if (configured) return configured\n if (isProduction()) throw new Error('SESSION_SECRET is required in production')\n return 'dev-secret-change-me'\n}\n\nfunction safeEqualHex(a: string, b: string): boolean {\n if (a.length !== b.length) return false\n try {\n return timingSafeEqual(Buffer.from(a, 'hex'), Buffer.from(b, 'hex'))\n } catch {\n return false\n }\n}\n\nexport function signSession(userId: number | bigint): string {\n const payload = String(userId)\n const sig = createHmac('sha256', secret()).update(payload).digest('hex')\n return `${payload}.${sig}`\n}\n\nexport function verifySession(token: string): number | null {\n const dot = token.lastIndexOf('.')\n if (dot === -1) return null\n const payload = token.slice(0, dot)\n const sig = token.slice(dot + 1)\n const expected = createHmac('sha256', secret()).update(payload).digest('hex')\n if (!safeEqualHex(sig, expected)) return null\n const id = parseInt(payload)\n return isNaN(id) ? null : id\n}\n\nexport function sessionCookie(token: string): string {\n const secure = isProduction() ? '; Secure' : ''\n return `session=${token}; HttpOnly${secure}; Path=/; SameSite=Strict; Max-Age=${60 * 60 * 24 * 30}`\n}\n\nexport function clearCookie(): string {\n return 'session=; HttpOnly; Path=/; Max-Age=0'\n}\n","export async function deliverWebhook(url: string, payload: object, retries = 3): Promise<void> {\n for (let attempt = 1; attempt <= retries; attempt++) {\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n signal: AbortSignal.timeout(10_000),\n })\n if (res.ok) return\n console.warn(`[webhook] attempt ${attempt} → ${res.status} from ${url}`)\n } catch (err) {\n console.warn(`[webhook] attempt ${attempt} failed:`, err instanceof Error ? err.message : err)\n }\n if (attempt < retries) await new Promise((r) => setTimeout(r, 1000 * attempt * 2))\n }\n console.error(`[webhook] gave up after ${retries} attempts for ${url}`)\n}\n","import { claimPendingJob, completeJob, failJob } from './db.js'\nimport { harvest } from '../harvest.js'\nimport { deliverWebhook } from './webhook.js'\nimport type { HarvestOptions } from '../types.js'\n\nexport type TickResult = {\n claimed: boolean\n jobId?: string\n completed?: boolean\n durationMs?: number\n}\nexport type DrainBudget = {\n maxJobs: number\n deadlineMs: number\n}\n\nconst MAX_CONCURRENT = 2\nlet running = 0\n\nasync function processJob(job: Awaited<ReturnType<typeof claimPendingJob>> & object) {\n running++\n try {\n const opts = typeof job.options === 'string' ? JSON.parse(job.options) as Partial<HarvestOptions> : job.options as Partial<HarvestOptions>\n const result = await harvest({\n ...opts,\n kernelApiKey: process.env.KERNEL_API_KEY,\n headless: true,\n format: 'json',\n outputDir: '/tmp/paa-output-api',\n })\n await completeJob(job.id, result)\n if (job.callback_url) {\n await deliverWebhook(job.callback_url, { job_id: job.id, status: 'done', result })\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n await failJob(job.id, msg)\n if (job.callback_url) {\n await deliverWebhook(job.callback_url, { job_id: job.id, status: 'failed', error: msg })\n }\n } finally {\n running--\n }\n}\n\nexport async function tickOnce(): Promise<TickResult> {\n const job = await claimPendingJob()\n if (!job) return { claimed: false }\n const startedAt = Date.now()\n await processJob(job as NonNullable<typeof job>)\n return { claimed: true, jobId: (job as { id: string }).id, completed: true, durationMs: Date.now() - startedAt }\n}\n\nexport async function drainQueue(budget: DrainBudget): Promise<TickResult[]> {\n const results: TickResult[] = []\n for (let i = 0; i < budget.maxJobs; i++) {\n if (Date.now() >= budget.deadlineMs) break\n const r = await tickOnce()\n results.push(r)\n if (!r.claimed) break\n }\n return results\n}\n\nexport function startWorker(): void {\n setInterval(async () => {\n if (running >= MAX_CONCURRENT) return\n const job = await claimPendingJob()\n if (job) void processJob(job as NonNullable<typeof job>)\n }, 2000)\n console.log(`[worker] started — polling every 2s, max ${MAX_CONCURRENT} concurrent`)\n}\n","import TurndownService from 'turndown'\nimport { lookup } from 'node:dns/promises'\nimport { isIP } from 'node:net'\nimport { fetchWithKernel } from './kernel-fetch.js'\nimport { spiderSite } from './site-mapper.js'\nimport { extractSite } from './site-extractor.js'\nimport { Hono } from 'hono'\nimport { serve as serveInngest } from 'inngest/hono'\nimport { inngest } from '../inngest/client.js'\nimport { siteAuditFn } from '../inngest/functions/site-audit.js'\nimport type { KpoExtractUrlResult } from './schemas.js'\nimport { siteAuditApp } from './site-audit-routes.js'\nimport { youtubeApp } from './youtube-routes.js'\nimport { screenshotApp } from './screenshot-routes.js'\nimport { facebookAdApp } from './facebook-ad-routes.js'\nimport { mapsApp } from './maps-routes.js'\nimport { mcpApp } from '../mcp/mcp-routes.js'\nimport { stripeApp } from './stripe-routes.js'\nimport { startSiteAuditWorker } from './site-audit-worker.js'\nimport { createMiddleware } from 'hono/factory'\nimport { getCookie, setCookie, deleteCookie } from 'hono/cookie'\nimport {\n getUserByApiKey, getUserById, createUser, listUsers, deactivateUser,\n createJob, createRunningJob, getJob, listJobs, getUserStats,\n rotateApiKey, revokeApiKey, verifyPassword, getUserByEmail,\n completeJob, failJob,\n countActiveJobsForUser, countJobsLast7Days, countActiveUsers,\n creditMc, debitMc, getLedger, setStripeCustomerId,\n} from './db.js'\nimport Stripe from 'stripe'\nimport { MC_COSTS, FREE_SIGNUP_MC, BALANCE_PRICE_IDS, CREDIT_COST_CATALOG, insufficientBalanceResponse } from './rates.js'\nimport { harvest } from '../harvest.js'\nimport { verifySession, signSession } from './session.js'\nimport type { User } from './db.js'\n\ntype Env = { Variables: { user: User } }\ntype SessEnv = { Variables: { sessionUser: User } }\n\nconst secureCookies = process.env.NODE_ENV === 'production' || process.env.VERCEL === '1'\nconst sessionCookieOptions = {\n httpOnly: true,\n secure: secureCookies,\n path: '/',\n maxAge: 60 * 60 * 24 * 30,\n sameSite: 'Strict' as const,\n}\n\nconst auth = createMiddleware<Env>(async (c, next) => {\n const key = c.req.header('x-api-key')\n if (!key) return c.json({ error: 'Missing API key' }, 401)\n const user = await getUserByApiKey(key)\n if (!user) return c.json({ error: 'Invalid or inactive API key' }, 401)\n c.set('user', user)\n return next()\n})\n\nconst adminAuth = createMiddleware(async (c, next) => {\n const configured = process.env.ADMIN_KEY?.trim()\n const key = c.req.header('x-admin-key')?.trim()\n if (!configured) return c.json({ error: 'Admin access disabled' }, 503)\n if (!key || key !== configured) return c.json({ error: 'Unauthorized' }, 401)\n return next()\n})\n\nconst sessionAuth = createMiddleware<SessEnv>(async (c, next) => {\n const token = getCookie(c, 'session')\n if (!token) return c.json({ error: 'Not authenticated' }, 401)\n const userId = verifySession(token)\n if (!userId) return c.json({ error: 'Session expired' }, 401)\n const user = await getUserById(userId)\n if (!user) return c.json({ error: 'User not found' }, 401)\n c.set('sessionUser', user)\n return next()\n})\n\nconst app = new Hono<Env>()\n\napp.use('*', async (c, next) => {\n await next()\n c.header('Cache-Control', 'no-store')\n c.header('X-Content-Type-Options', 'nosniff')\n c.header('Referrer-Policy', 'same-origin')\n})\n\nfunction isPrivateIpAddress(address: string): boolean {\n const kind = isIP(address)\n if (kind === 4) {\n const parts = address.split('.').map(Number)\n const [a, b] = parts\n return (\n a === 0 ||\n a === 10 ||\n a === 127 ||\n (a === 169 && b === 254) ||\n (a === 172 && b >= 16 && b <= 31) ||\n (a === 192 && b === 168)\n )\n }\n if (kind === 6) {\n const lower = address.toLowerCase()\n return lower === '::1' || lower.startsWith('fc') || lower.startsWith('fd') || lower.startsWith('fe80:')\n }\n return false\n}\n\nasync function resolvesToPrivateAddress(hostname: string): Promise<boolean> {\n const host = hostname.toLowerCase()\n if (host === 'localhost' || host.endsWith('.localhost') || host.endsWith('.local')) return true\n if (isPrivateIpAddress(host)) return true\n try {\n const addresses = await lookup(host, { all: true, verbatim: true })\n return addresses.some((entry) => isPrivateIpAddress(entry.address))\n } catch {\n return false\n }\n}\n\nasync function validatePublicHttpUrl(raw: string, opts: { field: string; requireHttps?: boolean }): Promise<{ parsed?: URL; error?: string }> {\n let parsed: URL\n try {\n parsed = new URL(raw.trim())\n } catch {\n return { error: `Invalid ${opts.field}` }\n }\n\n const allowedProtocols = opts.requireHttps ? ['https:'] : ['http:', 'https:']\n if (!allowedProtocols.includes(parsed.protocol)) {\n return { error: opts.requireHttps ? `${opts.field} must use https` : `${opts.field} must use http or https` }\n }\n if (await resolvesToPrivateAddress(parsed.hostname)) {\n return { error: `${opts.field} must resolve to a public internet host` }\n }\n return { parsed }\n}\n\napp.post('/auth/register', async (c) => {\n const { email, password } = await c.req.json<{ email?: string; password?: string }>()\n if (!email?.trim() || !password) return c.json({ error: 'Email and password required' }, 400)\n if (password.length < 8) return c.json({ error: 'Password must be at least 8 characters' }, 400)\n try {\n const user = await createUser(email.trim(), undefined, password)\n const newKey = await rotateApiKey(user.id)\n await creditMc(user.id as number, FREE_SIGNUP_MC, 'signup_grant', 'Welcome to MCP Scraper')\n const token = signSession(user.id as number)\n setCookie(c, 'session', token, sessionCookieOptions)\n return c.json({ email: user.email, api_key: newKey }, 201)\n } catch (err) {\n const msg = err instanceof Error ? err.message : ''\n if (msg.includes('UNIQUE')) return c.json({ error: 'Email already registered' }, 409)\n throw err\n }\n})\n\napp.post('/auth/login', async (c) => {\n const { email, password } = await c.req.json<{ email?: string; password?: string }>()\n if (!email || !password) return c.json({ error: 'Email and password required' }, 400)\n const user = await getUserByEmail(email)\n if (!user || !user.password_hash || !verifyPassword(password, user.password_hash)) {\n return c.json({ error: 'Invalid email or password' }, 401)\n }\n const token = signSession(user.id)\n setCookie(c, 'session', token, sessionCookieOptions)\n return c.json({ email: user.email, api_key: user.key_active ? user.api_key : null })\n})\n\napp.post('/auth/logout', (c) => {\n deleteCookie(c, 'session', { path: '/', secure: secureCookies, sameSite: 'Strict' })\n return c.json({ ok: true })\n})\n\napp.get('/stats/spots', async (c) => {\n const taken = await countActiveUsers()\n return c.json({ taken, open: true })\n})\n\napp.get('/me', async (c) => {\n const token = getCookie(c, 'session')\n if (!token) return c.json({ authenticated: false })\n\n const userId = verifySession(token)\n if (!userId) {\n deleteCookie(c, 'session', { path: '/', secure: secureCookies, sameSite: 'Strict' })\n return c.json({ authenticated: false })\n }\n\n const user = await getUserById(userId)\n if (!user) {\n deleteCookie(c, 'session', { path: '/', secure: secureCookies, sameSite: 'Strict' })\n return c.json({ authenticated: false })\n }\n\n const stats = await getUserStats(user.id)\n return c.json({\n authenticated: true,\n email: user.email,\n api_key: user.key_active ? user.api_key : null,\n created_at: user.created_at,\n balance_mc: user.balance_mc,\n balance_credits: user.balance_mc / 1_000,\n ...stats,\n })\n})\n\napp.post('/api-key/rotate', sessionAuth, async (c) => {\n const user = c.get('sessionUser')\n const newKey = await rotateApiKey(user.id)\n return c.json({ api_key: newKey })\n})\n\napp.delete('/api-key', sessionAuth, async (c) => {\n const user = c.get('sessionUser')\n await revokeApiKey(user.id)\n return c.json({ ok: true })\n})\n\nconst BYPASS_EMAILS = new Set(\n (process.env.HARVEST_LIMIT_BYPASS_EMAILS ?? '').split(',').map(e => e.trim()).filter(Boolean)\n)\n\nasync function checkHarvestLimits(userId: number | bigint, email: string): Promise<{ error: string } | null> {\n if (BYPASS_EMAILS.has(email)) return null\n const [active, recent] = await Promise.all([\n countActiveJobsForUser(userId),\n countJobsLast7Days(userId),\n ])\n if (active > 0) return { error: 'A harvest is already in progress. Wait for it to finish before starting another.' }\n if (recent >= 50) return { error: 'Weekly limit reached: 50 harvests per 7-day rolling window.' }\n return null\n}\n\napp.post('/harvest', auth, async (c) => {\n const user = c.get('user')\n const body = await c.req.json<{\n query?: string\n location?: string\n depth?: number\n maxQuestions?: number\n callback_url?: string\n gl?: string\n hl?: string\n serpOnly?: boolean\n pages?: number\n }>()\n\n if (!body.query?.trim()) return c.json({ error: 'query is required' }, 400)\n const callback = body.callback_url?.trim()\n if (callback) {\n const checked = await validatePublicHttpUrl(callback, { field: 'callback_url', requireHttps: true })\n if (checked.error) return c.json({ error: checked.error }, 400)\n body.callback_url = checked.parsed?.href\n }\n\n const limitErr = await checkHarvestLimits(user.id, user.email)\n if (limitErr) return c.json(limitErr, 429)\n\n const options = {\n query: body.query.trim(),\n location: body.location,\n depth: Math.min(4, Math.max(1, body.depth ?? 4)),\n maxQuestions: Math.min(100, Math.max(1, body.maxQuestions ?? 30)),\n gl: body.gl ?? 'us',\n hl: body.hl ?? 'en',\n serpOnly: body.serpOnly ?? false,\n pages: Math.min(2, Math.max(1, body.pages ?? 1)),\n }\n\n const harvestCost = options.serpOnly ? MC_COSTS.serp : MC_COSTS.paa\n const { ok: harvestOk, balance_mc: harvestBal } = await debitMc(user.id, harvestCost, options.serpOnly ? 'serp' : 'paa', options.query)\n if (!harvestOk) return c.json(insufficientBalanceResponse(harvestBal, harvestCost), 402)\n\n const jobId = await createJob(user.id, options.query, options, body.callback_url)\n\n if (process.env.CRON_SECRET) {\n const url = new URL(c.req.url)\n void fetch(`${url.origin}/cron/tick`, {\n headers: { Authorization: `Bearer ${process.env.CRON_SECRET}` },\n }).catch(() => {})\n await new Promise((r) => setTimeout(r, 80))\n }\n\n return c.json({ job_id: jobId, status: 'pending' }, 202)\n})\n\napp.post('/harvest/sync', auth, async (c) => {\n const user = c.get('user')\n const body = await c.req.json<{\n query?: string\n location?: string\n depth?: number\n maxQuestions?: number\n gl?: string\n hl?: string\n serpOnly?: boolean\n pages?: number\n }>()\n\n if (!body.query?.trim()) return c.json({ error: 'query is required' }, 400)\n\n const limitErr = await checkHarvestLimits(user.id, user.email)\n if (limitErr) return c.json(limitErr, 429)\n\n const options = {\n query: body.query.trim(),\n location: body.location,\n depth: Math.min(4, Math.max(1, body.depth ?? 4)),\n maxQuestions: Math.min(100, Math.max(1, body.maxQuestions ?? 30)),\n gl: body.gl ?? 'us',\n hl: body.hl ?? 'en',\n serpOnly: body.serpOnly ?? false,\n pages: Math.min(2, Math.max(1, body.pages ?? 1)),\n }\n\n const syncCost = options.serpOnly ? MC_COSTS.serp : MC_COSTS.paa\n const { ok: syncOk, balance_mc: syncBal } = await debitMc(user.id, syncCost, options.serpOnly ? 'serp' : 'paa', options.query)\n if (!syncOk) return c.json(insufficientBalanceResponse(syncBal, syncCost), 402)\n\n const jobId = await createRunningJob(user.id, options.query, options)\n\n try {\n const result = await harvest({\n ...options,\n kernelApiKey: process.env.KERNEL_API_KEY?.trim(),\n headless: true,\n format: 'json',\n outputDir: '/tmp/paa-output-api',\n })\n await completeJob(jobId, result)\n return c.json({ job_id: jobId, status: 'done', result })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n await failJob(jobId, msg)\n await creditMc(user.id, syncCost, 'refund', 'failed call')\n return c.json({ job_id: jobId, status: 'failed', error: msg }, 500)\n }\n})\n\napp.get('/jobs/:id', auth, async (c) => {\n const job = await getJob(c.req.param('id'), c.get('user').id)\n if (!job) return c.json({ error: 'Job not found' }, 404)\n return c.json(job)\n})\n\napp.get('/jobs', auth, async (c) => {\n return c.json(await listJobs(c.get('user').id))\n})\n\napp.get('/ledger', auth, async (c) => {\n return c.json(await getLedger(c.get('user').id, 100))\n})\n\napp.post('/admin/users', adminAuth, async (c) => {\n const { email, name, password } = await c.req.json<{ email?: string; name?: string; password?: string }>()\n if (!email?.trim()) return c.json({ error: 'email is required' }, 400)\n try {\n return c.json(await createUser(email.trim(), name?.trim(), password?.trim()), 201)\n } catch (err) {\n const msg = err instanceof Error ? err.message : ''\n if (msg.includes('UNIQUE')) return c.json({ error: 'Email already registered' }, 409)\n throw err\n }\n})\n\napp.get('/admin/users', adminAuth, async (c) => c.json(await listUsers()))\n\napp.delete('/admin/users/:id', adminAuth, async (c) => {\n await deactivateUser(parseInt(c.req.param('id') ?? '0'))\n return c.json({ ok: true })\n})\n\napp.post('/extract-url', auth, async (c) => {\n const { url } = await c.req.json<{ url?: string }>()\n if (!url?.trim()) return c.json({ error: 'url is required' }, 400)\n const checked = await validatePublicHttpUrl(url, { field: 'URL' })\n if (checked.error || !checked.parsed) return c.json({ error: checked.error ?? 'Invalid URL' }, 400)\n const parsed = checked.parsed\n const user = c.get('user')\n const { ok: euOk, balance_mc: euBal } = await debitMc(user.id, MC_COSTS.page_scrape, 'page_scrape', parsed.hostname)\n if (!euOk) return c.json(insufficientBalanceResponse(euBal, MC_COSTS.page_scrape), 402)\n\n let html: string\n let fetchedVia: 'fetch' | 'kernel' = 'fetch'\n\n const tryPlainFetch = async (): Promise<string | null> => {\n try {\n let target = parsed.href\n for (let redirects = 0; redirects < 5; redirects++) {\n const res = await fetch(target, {\n headers: { 'User-Agent': 'Mozilla/5.0 (compatible; ThorbitBot/1.0)' },\n signal: AbortSignal.timeout(15_000),\n redirect: 'manual',\n })\n if (res.status >= 300 && res.status < 400) {\n const location = res.headers.get('location')\n if (!location) return null\n const next = new URL(location, target).href\n const checkedRedirect = await validatePublicHttpUrl(next, { field: 'redirect URL' })\n if (checkedRedirect.error || !checkedRedirect.parsed) return null\n target = checkedRedirect.parsed.href\n continue\n }\n if (!res.ok) return null\n const text = await res.text()\n return text.length < 2000 ? null : text\n }\n return null\n } catch {\n return null\n }\n }\n\n const plainHtml = await tryPlainFetch()\n if (plainHtml) {\n html = plainHtml\n } else if (process.env.KERNEL_API_KEY) {\n try {\n html = await fetchWithKernel(parsed.href)\n fetchedVia = 'kernel'\n } catch (err) {\n return c.json({ error: `Fetch failed (plain + kernel): ${err instanceof Error ? err.message : String(err)}` }, 502)\n }\n } else {\n return c.json({ error: 'Fetch failed: site blocked plain HTTP and KERNEL_API_KEY is not configured' }, 502)\n }\n\n const stripTags = (s: string) => s.replace(/<[^>]+>/g, ' ').replace(/\\s+/g, ' ').trim()\n const attr = (tag: string, name: string) => {\n const m = tag.match(new RegExp(`${name}\\\\s*=\\\\s*(?:\"([^\"]*?)\"|'([^']*?)'|([^\\\\s>]+))`, 'i'))\n return m ? (m[1] ?? m[2] ?? m[3] ?? '') : null\n }\n\n const titleMatch = html.match(/<title[^>]*>([\\s\\S]*?)<\\/title>/i)\n const title = titleMatch ? stripTags(titleMatch[1]) : null\n\n const meta: Record<string, string> = {}\n for (const m of html.matchAll(/<meta\\s[^>]+>/gi)) {\n const tag = m[0]\n const name = attr(tag, 'name') || attr(tag, 'property')\n const content = attr(tag, 'content')\n if (name && content) meta[name.toLowerCase()] = content\n }\n\n const headings: { level: number; text: string }[] = []\n for (const m of html.matchAll(/<(h[1-6])[^>]*>([\\s\\S]*?)<\\/\\1>/gi)) {\n const level = parseInt(m[1].slice(1))\n const text = stripTags(m[2])\n if (text) headings.push({ level, text })\n }\n\n const sanitizeJsonLd = (s: string) => s.replace(/[\\x00-\\x09\\x0b\\x0c\\x0e-\\x1f]/g, ' ')\n\n const parseJsonLd = (s: string): unknown | null => {\n const clean = sanitizeJsonLd(s.trim())\n try {\n return JSON.parse(clean)\n } catch (e) {\n const pos = /at position (\\d+)/.exec((e as Error).message)?.[1]\n if (pos) {\n try { return JSON.parse(clean.slice(0, Number(pos))) } catch { }\n }\n return null\n }\n }\n\n const schema: unknown[] = []\n for (const m of html.matchAll(/<script[^>]+type\\s*=\\s*[\"']application\\/ld\\+json[\"'][^>]*>([\\s\\S]*?)<\\/script>/gi)) {\n const raw = parseJsonLd(m[1])\n if (raw === null) continue\n if (Array.isArray(raw)) schema.push(...raw)\n else schema.push(raw)\n }\n\n const SOCIAL_DOMAINS = [\n 'facebook.com', 'fb.com', 'twitter.com', 'x.com', 'linkedin.com',\n 'instagram.com', 'youtube.com', 'tiktok.com', 'pinterest.com',\n 'yelp.com', 'bbb.org', 'alignable.com', 'nextdoor.com',\n 'thumbtack.com', 'angi.com', 'angieslist.com', 'houzz.com',\n 'tripadvisor.com', 'google.com/maps', 'maps.google.com',\n 'trustpilot.com', 'mapquest.com', 'apple.com/maps', 'waze.com',\n 'about.me', 'crunchbase.com', 'sites.google.com',\n ]\n\n const htmlSocialLinks: string[] = []\n for (const m of html.matchAll(/<a\\s[^>]*href\\s*=\\s*[\"']([^\"']+)[\"'][^>]*>/gi)) {\n const href = m[1]\n if (SOCIAL_DOMAINS.some(d => href.includes(d))) {\n try {\n const u = new URL(href)\n if ((u.protocol === 'http:' || u.protocol === 'https:') && !htmlSocialLinks.includes(href)) {\n htmlSocialLinks.push(href)\n }\n } catch { }\n }\n }\n\n type SchemaNode = Record<string, unknown>\n const flatNodes: SchemaNode[] = schema.flatMap((s: unknown) => {\n const obj = s as SchemaNode\n return (obj?.['@graph'] as SchemaNode[] | undefined) ?? [obj]\n })\n\n const ENTITY_TYPES = [\n 'LocalBusiness', 'Organization', 'Person', 'Corporation',\n 'MedicalOrganization', 'ProfessionalService', 'LegalService',\n 'HealthAndBeautyBusiness', 'HomeAndConstructionBusiness',\n 'FoodEstablishment', 'Store', 'Hotel', 'AutomotiveBusiness',\n 'MarketingAgency', 'Plumber', 'HVACBusiness', 'ElectricalContractor',\n 'Dentist', 'Physician', 'LodgingBusiness', 'AutoDealer',\n 'RealEstateAgent', 'FinancialService', 'InsuranceAgency', 'Accountant',\n 'AccountingService', 'Attorney', 'EducationalOrganization',\n 'GovernmentOrganization', 'NGO', 'SportsOrganization',\n ]\n\n const entityNode = flatNodes.find((n: SchemaNode) => {\n const t = [n['@type']].flat() as string[]\n return t.some(x => ENTITY_TYPES.includes(x))\n }) ?? null\n\n const str = (v: unknown): string | null => typeof v === 'string' && v ? v : null\n const strs = (v: unknown): string[] => [v].flat().filter((x): x is string => typeof x === 'string' && !!x)\n\n const presentSchemaTypes = [...new Set(\n flatNodes.flatMap(n => ([n['@type']].flat() as string[]).filter(Boolean))\n )]\n const microdataTypes = [...new Set(\n [...html.matchAll(/itemtype\\s*=\\s*[\"']https?:\\/\\/schema\\.org\\/([^\"'\\s]+)[\"']/gi)].map((m) => m[1])\n )]\n\n const faqNode = flatNodes.find(n => ([n['@type']].flat() as string[]).includes('FAQPage')) ?? null\n const ratingNode = flatNodes.find(n =>\n ([n['@type']].flat() as string[]).some(t => t === 'AggregateRating' || t === 'Rating')\n ) ?? null\n const faqCount = faqNode ? ((faqNode.mainEntity as unknown[]) ?? []).length : 0\n const aggregateRating = ratingNode ? {\n value: str(ratingNode.ratingValue),\n best: str(ratingNode.bestRating) ?? null,\n count: str(ratingNode.reviewCount) ?? str(ratingNode.ratingCount) ?? null,\n } : null\n\n const canonicalMatch =\n html.match(/<link[^>]+rel\\s*=\\s*[\"']canonical[\"'][^>]+href\\s*=\\s*[\"']([^\"']+)[\"']/i) ??\n html.match(/<link[^>]+href\\s*=\\s*[\"']([^\"']+)[\"'][^>]+rel\\s*=\\s*[\"']canonical[\"']/i)\n const canonicalUrl = canonicalMatch ? canonicalMatch[1] : null\n\n const websiteNode = flatNodes.find(n => ([n['@type']].flat() as string[]).includes('WebSite')) ?? null\n const hasSearchAction = websiteNode\n ? ([websiteNode.potentialAction].flat().filter(Boolean) as SchemaNode[])\n .some(a => ([a['@type']].flat() as string[]).some(t => t.includes('SearchAction')))\n : false\n\n const nodeAreaServed = (node: SchemaNode): string[] => {\n const v = node.areaServed\n if (!v) return []\n if (typeof v === 'string') return [v]\n if (Array.isArray(v)) return v.map(x => (typeof x === 'string' ? x : str((x as SchemaNode).name) ?? '')).filter(Boolean)\n if (typeof v === 'object') return [str((v as SchemaNode).name) ?? str((v as SchemaNode)['@type']) ?? ''].filter(Boolean)\n return []\n }\n const unescape = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/&#(\\d+);/g, (_, n) => String.fromCharCode(parseInt(n)))\n\n let kpo: KpoExtractUrlResult\n\n if (entityNode) {\n const addrNode = (entityNode.address ?? {}) as SchemaNode\n const address = addrNode.streetAddress\n ? [addrNode.streetAddress, addrNode.addressLocality, addrNode.addressRegion, addrNode.postalCode, addrNode.addressCountry]\n .filter(Boolean).map(x => unescape(String(x))).join(', ')\n : str(entityNode.address)\n\n const logoNode = (entityNode.logo ?? {}) as SchemaNode\n const logoUrl = str(logoNode.url) ?? str(logoNode.contentUrl) ?? str(entityNode.logo)\n\n const sameAsSchema = strs(entityNode.sameAs).map(unescape)\n const sameAsMerged = [...new Set([...sameAsSchema, ...htmlSocialLinks])]\n\n const people: { name: string; role: string }[] = []\n for (const key of ['founders', 'founder', 'employee', 'member'] as const) {\n const entries = [entityNode[key]].flat().filter(Boolean) as SchemaNode[]\n for (const f of entries) {\n const name = str(f.name) ?? (typeof f === 'string' ? f : null)\n if (name && !people.find(p => p.name === name)) people.push({ name: unescape(name), role: key })\n }\n }\n\n const types = strs(entityNode['@type'])\n const schemaId = str(entityNode['@id'])\n const schemaUrl = str(entityNode.url)\n const areaServed = nodeAreaServed(entityNode)\n const hasWikipedia = sameAsMerged.some(u => u.includes('wikipedia.org'))\n const hasWikidata = sameAsMerged.some(u => u.includes('wikidata.org'))\n const napScore = [str(entityNode.name), address, str(entityNode.telephone)].filter(Boolean).length\n\n const missing: string[] = []\n if (!str(entityNode.name)) missing.push('name')\n if (!str(entityNode.foundingDate)) missing.push('foundingDate')\n if (!address) missing.push('address')\n if (!str(entityNode.telephone)) missing.push('telephone')\n if (!str(entityNode.email)) missing.push('email')\n if (!logoUrl) missing.push('logo')\n if (!people.length) missing.push('founders / key people')\n if (!schemaId) missing.push('add @id to entity schema — e.g. https://yourdomain.com/#Organization')\n if (!areaServed.length) missing.push('add areaServed to define geographic service scope')\n if (!hasWikipedia) missing.push('no Wikipedia in sameAs — add when eligible coverage exists')\n if (!hasWikidata) missing.push('no Wikidata in sameAs — create a Wikidata item and add its URL')\n if (!hasSearchAction) missing.push('add WebSite schema with SearchAction for sitelinks searchbox eligibility')\n\n kpo = {\n entityName: str(entityNode.name) ? unescape(str(entityNode.name)!) : null,\n type: types,\n foundingDate: str(entityNode.foundingDate) ?? str((entityNode as SchemaNode).foundingYear) ?? null,\n address,\n phone: str(entityNode.telephone) ?? null,\n email: str(entityNode.email) ? unescape(str(entityNode.email)!) : null,\n logo: logoUrl,\n sameAs: sameAsMerged,\n socialLinks: htmlSocialLinks,\n keyPeople: people,\n openingHours: strs(entityNode.openingHours),\n description: str(entityNode.description) ? unescape(str(entityNode.description)!) : (meta['description'] ?? null),\n schemaId,\n schemaUrl,\n areaServed: areaServed.length ? areaServed : null,\n hasWikipedia,\n hasWikidata,\n napScore,\n canonicalUrl,\n hasSearchAction,\n missingFields: missing,\n schemaTypes: presentSchemaTypes,\n microdataTypes,\n faqCount,\n aggregateRating,\n } satisfies KpoExtractUrlResult\n } else {\n const mdEntityType = microdataTypes.find(t => ENTITY_TYPES.includes(t)) ?? null\n const hasAnySchema = presentSchemaTypes.length > 0 || microdataTypes.length > 0\n let entitySchemaMsg: string\n if (mdEntityType) {\n entitySchemaMsg = `microdata @type ${mdEntityType} found — add matching JSON-LD for full eligibility`\n } else if (hasAnySchema) {\n const found = [...presentSchemaTypes, ...microdataTypes].join(', ')\n entitySchemaMsg = `schema found (${found}) but no entity type — add @type LocalBusiness or ProfessionalService`\n } else {\n entitySchemaMsg = 'no schema found — add JSON-LD with @type LocalBusiness or ProfessionalService'\n }\n const elseType = mdEntityType ? [mdEntityType] : []\n const elseSameAs = htmlSocialLinks\n kpo = {\n entityName: str(meta['og:site_name']) ?? null,\n type: elseType,\n foundingDate: null,\n address: null,\n phone: null,\n email: null,\n logo: str(meta['og:image']) ?? null,\n sameAs: elseSameAs,\n socialLinks: htmlSocialLinks,\n keyPeople: [],\n openingHours: [],\n description: str(meta['description']) ?? null,\n schemaId: null,\n schemaUrl: null,\n areaServed: null,\n hasWikipedia: elseSameAs.some(u => u.includes('wikipedia.org')),\n hasWikidata: elseSameAs.some(u => u.includes('wikidata.org')),\n napScore: 0,\n canonicalUrl,\n hasSearchAction,\n missingFields: [\n entitySchemaMsg,\n 'foundingDate', 'address', 'telephone', 'email', 'logo', 'founders / key people',\n 'add @id to entity schema — e.g. https://yourdomain.com/#Organization',\n 'add areaServed to define geographic service scope',\n 'no Wikipedia in sameAs — add when eligible coverage exists',\n 'no Wikidata in sameAs — create a Wikidata item and add its URL',\n ...(!hasSearchAction ? ['add WebSite schema with SearchAction for sitelinks searchbox eligibility'] : []),\n ],\n schemaTypes: presentSchemaTypes,\n microdataTypes,\n faqCount,\n aggregateRating,\n } satisfies KpoExtractUrlResult\n }\n\n const extractContentHtml = (raw: string): string => {\n const stripped = raw\n .replace(/<(script|style|noscript|svg|iframe|canvas)[^>]*>[\\s\\S]*?<\\/\\1>/gi, '')\n .replace(/<(nav|header|footer|aside)[^>]*>[\\s\\S]*?<\\/\\1>/gi, '')\n const main = stripped.match(/<main[^>]*>([\\s\\S]*?)<\\/main>/i)\n if (main) return main[1]\n const article = stripped.match(/<article[^>]*>([\\s\\S]*?)<\\/article>/i)\n if (article) return article[1]\n const body = stripped.match(/<body[^>]*>([\\s\\S]*?)<\\/body>/i)\n return body ? body[1] : stripped\n }\n\n const resolveImages = (fragment: string): string =>\n fragment.replace(/<img([^>]*?)\\/?>/gi, (_m, attrs) => {\n const src = (attrs.match(/\\bsrc\\s*=\\s*[\"']([^\"']*)[\"']/i) ?? [])[1] ?? ''\n if (src && !src.startsWith('data:')) return `<img${attrs}>`\n const real = (attrs.match(/data-(?:lazy-)?src\\s*=\\s*[\"']([^\"']+)[\"']/i) ?? [])[1]\n return real ? `<img src=\"${real}\">` : ''\n })\n\n const td = new TurndownService({ headingStyle: 'atx', bulletListMarker: '-', codeBlockStyle: 'fenced' })\n const bodyHtml = resolveImages(extractContentHtml(html))\n const bodyMarkdown = td.turndown(bodyHtml)\n .replace(/!\\[[^\\]]*\\]\\([^)]*\\)/g, '')\n .replace(/\\[([^\\]]*)\\]\\([^)]*\\)/g, '$1')\n .replace(/\\[]\\([^)]*\\)/g, '')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim()\n\n return c.json({ url: parsed.href, fetchedVia, title, meta, headings, schema, kpo, bodyHtml, bodyMarkdown })\n})\n\napp.post('/map-urls', auth, async (c) => {\n const body = await c.req.json<{ url?: string; maxUrls?: number; concurrency?: number; kernelFallback?: boolean }>()\n if (!body.url?.trim()) return c.json({ error: 'url is required' }, 400)\n const checked = await validatePublicHttpUrl(body.url, { field: 'URL' })\n if (checked.error || !checked.parsed) return c.json({ error: checked.error ?? 'Invalid URL' }, 400)\n const parsed = checked.parsed\n const user = c.get('user')\n const mapHoldMc = MC_COSTS.url_map * 10\n const { ok: mapOk, balance_mc: mapBal } = await debitMc(user.id, mapHoldMc, 'url_map_hold', parsed.hostname)\n if (!mapOk) return c.json(insufficientBalanceResponse(mapBal, mapHoldMc), 402)\n const result = await spiderSite({\n startUrl: parsed.href,\n maxUrls: Math.min(2000, Math.max(1, body.maxUrls ?? 500)),\n concurrency: Math.min(20, Math.max(1, body.concurrency ?? 12)),\n kernelApiKey: body.kernelFallback ? process.env.KERNEL_API_KEY : undefined,\n })\n const actualMc = (result.urls?.length ?? 1) * MC_COSTS.url_map\n const diff = mapHoldMc - actualMc\n if (diff > 0) await creditMc(user.id, diff, 'url_map_refund', 'overestimate refund')\n else if (diff < 0) await debitMc(user.id, -diff, 'url_map', parsed.hostname)\n return c.json(result)\n})\n\napp.post('/extract-site', auth, async (c) => {\n const body = await c.req.json<{ url?: string; maxPages?: number; kernelFallback?: boolean }>()\n if (!body.url?.trim()) return c.json({ error: 'url is required' }, 400)\n const checked = await validatePublicHttpUrl(body.url, { field: 'URL' })\n if (checked.error || !checked.parsed) return c.json({ error: checked.error ?? 'Invalid URL' }, 400)\n const parsed = checked.parsed\n const user = c.get('user')\n const siteHoldMc = MC_COSTS.page_scrape * 10\n const { ok: siteOk, balance_mc: siteBal } = await debitMc(user.id, siteHoldMc, 'extract_site_hold', parsed.hostname)\n if (!siteOk) return c.json(insufficientBalanceResponse(siteBal, siteHoldMc), 402)\n const result = await extractSite({\n startUrl: parsed.href,\n maxPages: Math.min(200, Math.max(1, body.maxPages ?? 100)),\n kernelApiKey: body.kernelFallback ? process.env.KERNEL_API_KEY : undefined,\n })\n const pageCount = (result as { pages?: unknown[] }).pages?.length ?? 1\n const actualSiteMc = pageCount * MC_COSTS.page_scrape\n const siteDiff = siteHoldMc - actualSiteMc\n if (siteDiff > 0) await creditMc(user.id, siteDiff, 'extract_site_refund', 'overestimate refund')\n else if (siteDiff < 0) await debitMc(user.id, -siteDiff, 'extract_site', parsed.hostname)\n return c.json(result)\n})\n\napp.post('/billing/checkout', sessionAuth, async (c) => {\n const user = c.get('sessionUser')\n const { priceId } = await c.req.json<{ priceId: string }>()\n if (!(priceId in BALANCE_PRICE_IDS)) return c.json({ error: 'Invalid price' }, 400)\n\n const stripeClient = new Stripe(process.env.STRIPE_SECRET_KEY!, { apiVersion: '2026-04-22.dahlia' })\n\n let customerId = user.stripe_customer_id\n if (!customerId) {\n const customer = await stripeClient.customers.create({ email: user.email })\n customerId = customer.id\n await setStripeCustomerId(user.id, customerId)\n }\n\n const origin = c.req.header('origin') ?? 'https://mcpscraper.dev'\n const session = await stripeClient.checkout.sessions.create({\n customer: customerId,\n mode: 'payment',\n line_items: [{ price: priceId, quantity: 1 }],\n ui_mode: 'embedded' as any,\n return_url: `${origin}/billing?session_id={CHECKOUT_SESSION_ID}`,\n automatic_tax: { enabled: true },\n })\n\n return c.json({ clientSecret: session.client_secret })\n})\n\napp.get('/billing/balance', auth, async (c) => {\n const user = c.get('user')\n const ledger = await getLedger(user.id, 20)\n return c.json({\n balance_mc: user.balance_mc,\n balance_credits: user.balance_mc / 1_000,\n ledger,\n })\n})\n\napp.post('/billing/credits', auth, async (c) => {\n const user = c.get('user')\n const body = await c.req.json().catch(() => ({})) as { item?: string; includeLedger?: boolean }\n const query = body.item?.trim().toLowerCase()\n const costs = CREDIT_COST_CATALOG.map(({ aliases, ...cost }) => cost)\n const matchedCost = query\n ? CREDIT_COST_CATALOG.find(cost =>\n cost.label.toLowerCase().includes(query)\n || cost.key.toLowerCase() === query\n || cost.aliases.some(alias => alias.toLowerCase().includes(query) || query.includes(alias.toLowerCase())),\n )\n : undefined\n const ledger = body.includeLedger\n ? (await getLedger(user.id, 10)).map(row => ({\n amount_mc: row.amount_mc,\n operation: row.operation,\n description: row.description,\n created_at: row.created_at,\n }))\n : undefined\n\n return c.json({\n balance_mc: user.balance_mc,\n balance_credits: user.balance_mc / 1_000,\n item: body.item ?? null,\n matched_cost: matchedCost ? (({ aliases, ...cost }) => cost)(matchedCost) : null,\n costs,\n ledger,\n })\n})\n\napp.get('/cron/tick', async (c) => {\n const secret = c.req.header('authorization')\n if (!process.env.CRON_SECRET || secret !== `Bearer ${process.env.CRON_SECRET}`) {\n return c.json({ error: 'Unauthorized' }, 401)\n }\n const { drainQueue } = await import('./worker.js')\n const budget = { maxJobs: 10, deadlineMs: Date.now() + 280_000 }\n const [results] = await Promise.all([\n drainQueue(budget),\n ])\n return c.json({ drained: results.length, results })\n})\n\napp.on(['GET', 'POST', 'PUT'], '/api/inngest', serveInngest({ client: inngest, functions: [siteAuditFn] }))\napp.route('/api/internal/site-architecture-auditor', siteAuditApp)\napp.route('/youtube', youtubeApp)\napp.route('/screenshot', screenshotApp)\napp.route('/facebook', facebookAdApp)\napp.route('/maps', mapsApp)\napp.route('/mcp', mcpApp)\napp.route('/stripe', stripeApp)\n\nif (!process.env.INNGEST_EVENT_KEY) {\n startSiteAuditWorker()\n}\n\nexport { app }\n","#!/usr/bin/env node\nimport { readFileSync } from 'node:fs'\n\nfunction loadDotEnv(): void {\n try {\n for (const line of readFileSync('.env', 'utf8').split('\\n')) {\n const eq = line.indexOf('=')\n if (eq < 1 || line.trimStart().startsWith('#')) continue\n const k = line.slice(0, eq).trim()\n if (!process.env[k]) process.env[k] = line.slice(eq + 1).trim()\n }\n } catch {}\n}\n\nloadDotEnv()\n\nasync function main(): Promise<void> {\n const [{ serve }, { app }, { startWorker }, { migrate }] = await Promise.all([\n import('@hono/node-server'),\n import('../src/api/server.js'),\n import('../src/api/worker.js'),\n import('../src/api/db.js'),\n ])\n\n const PORT = parseInt(process.env.PORT ?? '3001')\n\n try {\n await migrate()\n startWorker()\n serve({ fetch: app.fetch, port: PORT }, (info) => {\n console.log(`[server] http://localhost:${info.port}`)\n console.log(`[server] admin key: ${process.env.ADMIN_KEY ?? '(not set — ADMIN_KEY env var required)'}`)\n })\n } catch (err) {\n console.error('[startup] migration failed', err)\n process.exit(1)\n }\n}\n\nvoid main()\n"],"mappings":"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","names":["Kernel","path","UA","import_sdk","import_zod","import_zod","H1","H2","import_zod","import_zod","import_zod","truncate","import_zod","truncate","import_zod","import_zod","pLimit","import_zod","execFile","pLimit","import_p_limit","import_factory","path","import_zod","os","import_zod","init_schemas","import_playwright","import_sdk","StealthPlugin","Kernel","playwrightChromium","import_node_path","path","path","fs","path","Papa","import_node_path","init_schemas","data","import_client","import_hono","import_factory","strips","totalH","Kernel","import_playwright","import_sdk","import_hono","import_factory","import_promises","el","root","libraryId","platforms","import_hono","import_factory","import_client","m","c","fmtTs","main","import_zod","init_schemas","import_hono","import_factory","init_schemas","import_zod","path","import_hono","import_hono","Stripe","init_schemas","s","organicResults","localPack","rawEntityIds","entityIds","allOrganic","stats","aiSurfaces","import_node_fs","import_node_path","import_papaparse","fs","path","Papa","extractOnce","MAX_ATTEMPTS","init_schemas","import_node_crypto","import_promises","import_node_net","import_hono","import_factory","import_stripe","auth","location","main","TurndownService","Stripe","secret","drainQueue","serveInngest","import_node_fs","app","startWorker","migrate"]}
|