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.
Files changed (38) hide show
  1. package/README.md +56 -0
  2. package/dist/bin/api-server.cjs +9256 -0
  3. package/dist/bin/api-server.cjs.map +1 -0
  4. package/dist/bin/api-server.d.cts +1 -0
  5. package/dist/bin/api-server.d.ts +1 -0
  6. package/dist/bin/api-server.js +38 -0
  7. package/dist/bin/api-server.js.map +1 -0
  8. package/dist/bin/mcp-stdio-server.cjs +840 -0
  9. package/dist/bin/mcp-stdio-server.cjs.map +1 -0
  10. package/dist/bin/mcp-stdio-server.d.cts +1 -0
  11. package/dist/bin/mcp-stdio-server.d.ts +1 -0
  12. package/dist/bin/mcp-stdio-server.js +41 -0
  13. package/dist/bin/mcp-stdio-server.js.map +1 -0
  14. package/dist/bin/paa-harvest.cjs +1438 -0
  15. package/dist/bin/paa-harvest.cjs.map +1 -0
  16. package/dist/bin/paa-harvest.d.cts +1 -0
  17. package/dist/bin/paa-harvest.d.ts +1 -0
  18. package/dist/bin/paa-harvest.js +37 -0
  19. package/dist/bin/paa-harvest.js.map +1 -0
  20. package/dist/chunk-4API3ZCT.js +1387 -0
  21. package/dist/chunk-4API3ZCT.js.map +1 -0
  22. package/dist/chunk-LXZDJJXR.js +476 -0
  23. package/dist/chunk-LXZDJJXR.js.map +1 -0
  24. package/dist/chunk-ZBP4RHNW.js +805 -0
  25. package/dist/chunk-ZBP4RHNW.js.map +1 -0
  26. package/dist/db-IOYMX64U.js +87 -0
  27. package/dist/db-IOYMX64U.js.map +1 -0
  28. package/dist/index.cjs +1689 -0
  29. package/dist/index.cjs.map +1 -0
  30. package/dist/index.d.cts +210 -0
  31. package/dist/index.d.ts +210 -0
  32. package/dist/index.js +275 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/server-63DR2HE5.js +6062 -0
  35. package/dist/server-63DR2HE5.js.map +1 -0
  36. package/dist/worker-3ECJHPRE.js +88 -0
  37. package/dist/worker-3ECJHPRE.js.map +1 -0
  38. package/package.json +76 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api/server.ts","../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/services/site-architecture-auditor/site-audit-service.ts","../src/services/site-architecture-auditor/schemas.ts","../src/lib/site-architecture-auditor/rules.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-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-routes.ts","../src/api/site-audit-middleware.ts","../src/api/youtube-routes.ts","../src/api/rates.ts","../src/youtube/youtube-harvest.ts","../src/youtube/schemas.ts","../src/youtube/YouTubeExtractor.ts","../src/youtube/MP3Downloader.ts","../src/youtube/YTProgressReporter.ts","../src/youtube/CaptionFetcher.ts","../src/api/screenshot-routes.ts","../src/lib/screenshot.ts","../src/api/facebook-ad-routes.ts","../src/extractor/FacebookAdExtractor.ts","../src/api/maps-routes.ts","../src/extractor/MapsExtractor.ts","../src/mcp/mcp-routes.ts","../src/mcp/stub-mcp-tool-executor.ts","../src/api/stripe-routes.ts","../src/api/site-audit-worker.ts","../src/api/session.ts"],"sourcesContent":["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(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/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","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';\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 { 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\";\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 { 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 { 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 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","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 { 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, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')\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","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 { 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 { 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","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 { 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(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '\"').replace(/&#39;/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(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '\"').replace(/&#39;/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 { 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 { 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 { 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 { 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 { 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 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 { 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 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 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 { 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"],"mappings":"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","names":["lookup","isIP","path","UA","Hono","z","z","z","z","z","z","H1","H2","z","z","z","z","z","execFile","pLimit","pLimit","path","path","Hono","createMiddleware","path","z","execFile","promisify","path","path","path","data","createMiddleware","Hono","Hono","createMiddleware","chromium","Kernel","strips","totalH","Hono","createMiddleware","Hono","createMiddleware","el","root","libraryId","platforms","fal","createMiddleware","Hono","m","c","fmtTs","Hono","createMiddleware","createMiddleware","Hono","Hono","Hono","Hono","Hono","createMiddleware","Stripe","auth","createMiddleware","Hono","isIP","lookup","location","Stripe","secret"]}