mcp-scraper 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/bin/api-server.cjs +15730 -7780
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +3 -3
- package/dist/bin/mcp-stdio-server.cjs +300 -110
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +1 -1
- package/dist/bin/paa-harvest.cjs +1537 -165
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +1 -1
- package/dist/{chunk-ZBP4RHNW.js → chunk-4743MZHT.js} +298 -106
- package/dist/chunk-4743MZHT.js.map +1 -0
- package/dist/{chunk-LXZDJJXR.js → chunk-D4CJBZBY.js} +426 -29
- package/dist/chunk-D4CJBZBY.js.map +1 -0
- package/dist/chunk-HERFK7W6.js +2781 -0
- package/dist/chunk-HERFK7W6.js.map +1 -0
- package/dist/chunk-Y74EXABN.js +295 -0
- package/dist/chunk-Y74EXABN.js.map +1 -0
- package/dist/{db-IOYMX64U.js → db-YWCNHBLH.js} +36 -4
- package/dist/index.cjs +1660 -237
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +169 -2
- package/dist/index.d.ts +169 -2
- package/dist/index.js +120 -69
- package/dist/index.js.map +1 -1
- package/dist/server-N7Q6H4OR.js +11612 -0
- package/dist/server-N7Q6H4OR.js.map +1 -0
- package/dist/{worker-3ECJHPRE.js → worker-D4D2YQTA.js} +44 -9
- package/dist/worker-D4D2YQTA.js.map +1 -0
- package/package.json +17 -5
- package/dist/chunk-4API3ZCT.js +0 -1387
- package/dist/chunk-4API3ZCT.js.map +0 -1
- package/dist/chunk-LXZDJJXR.js.map +0 -1
- package/dist/chunk-ZBP4RHNW.js.map +0 -1
- package/dist/server-63DR2HE5.js +0 -6062
- package/dist/server-63DR2HE5.js.map +0 -1
- package/dist/worker-3ECJHPRE.js.map +0 -1
- /package/dist/{db-IOYMX64U.js.map → db-YWCNHBLH.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schemas.ts","../src/driver/BrowserDriver.ts","../src/selectors.ts","../src/errors.ts","../src/locations.ts","../src/uule.ts","../src/lib/paa-answer-cleanup.ts","../src/extractor/PAAExtractor.ts","../src/output/OutputSerializer.ts","../src/output/ProgressReporter.ts","../src/harvest.ts"],"sourcesContent":["import { z } from 'zod'\n\nexport const HarvestOptionsSchema = z.object({\n query: z.string().min(1),\n location: z.string().optional(),\n gl: z.string().length(2).default('us'),\n hl: z.string().length(2).default('en'),\n depth: z.number().int().min(1).max(30).default(3),\n maxQuestions: z.number().int().min(1).max(1000).default(100),\n headless: z.boolean().default(false),\n profileDir: z.string().optional(),\n proxy: z.string().url().optional(),\n kernelApiKey: z.string().optional(),\n kernelProxyId: z.string().optional(),\n outputDir: z.string().default('./paa-output'),\n format: z.enum(['json', 'csv', 'both']).default('both'),\n serpOnly: z.boolean().default(false),\n pages: z.number().int().min(1).max(2).default(1),\n})\n\nexport const MapsPlaceOptionsSchema = z.object({\n businessName: z.string().min(1),\n location: z.string().min(1),\n gl: z.string().length(2).default('us'),\n hl: z.string().length(2).default('en'),\n includeReviews: z.boolean().default(false),\n maxReviews: z.number().int().min(1).max(500).default(50),\n kernelApiKey: z.string().optional(),\n kernelProxyId: z.string().optional(),\n headless: z.boolean().default(true),\n})\n\nexport const RawPAAItemSchema = z.object({\n question: z.string().min(1),\n answer: z.string().optional(),\n sourceTitle: z.string().optional(),\n sourceSite: z.string().optional(),\n sourceCite: z.string().optional(),\n})\n","import { chromium } from 'playwright-extra'\nimport StealthPlugin from 'puppeteer-extra-plugin-stealth'\nimport { chromium as playwrightChromium } from 'playwright'\nimport type { Browser, BrowserContext, Page } from 'playwright'\nimport Kernel from '@onkernel/sdk'\nimport { PAASelectors } from '../selectors.js'\nimport { CaptchaError, ExtractionError, RECAPTCHA_INSTRUCTIONS } from '../errors.js'\nimport type { DriverConfig, UuleString } from '../types.js'\nimport type { IBrowserDriver } from './IBrowserDriver.js'\n\nchromium.use(StealthPlugin())\n\nconst DESKTOP_USER_AGENT =\n 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'\n\nexport function buildYouTubeChannelVideosUrl(channelInput: string): string {\n const raw = channelInput.trim()\n if (!raw) throw new Error('channelHandle is required')\n\n const urlLike = /^https?:\\/\\//i.test(raw) || /^(www\\.|m\\.)?youtube\\.com\\//i.test(raw)\n if (urlLike) {\n const parsed = new URL(/^https?:\\/\\//i.test(raw) ? raw : `https://${raw}`)\n const host = parsed.hostname.replace(/^www\\./, '').replace(/^m\\./, '').toLowerCase()\n if (host !== 'youtube.com') throw new Error('channel URL must be on youtube.com')\n\n const segments = parsed.pathname.split('/').filter(Boolean)\n const first = segments[0] ?? ''\n const second = segments[1] ?? ''\n\n if (first.startsWith('@')) return `https://www.youtube.com/${first}/videos`\n if (first === 'channel' && second) return `https://www.youtube.com/channel/${second}/videos`\n if ((first === 'c' || first === 'user') && second) return `https://www.youtube.com/${first}/${second}/videos`\n\n throw new Error('channel URL must be a YouTube handle, /channel/UC..., /c/..., or /user/... URL')\n }\n\n const stripped = raw.replace(/^\\/+/, '').replace(/\\/+$/, '')\n const withoutVideos = stripped.replace(/\\/videos$/i, '')\n if (/^UC[\\w-]{20,}$/.test(withoutVideos)) {\n return `https://www.youtube.com/channel/${withoutVideos}/videos`\n }\n\n const handle = withoutVideos.startsWith('@') ? withoutVideos : `@${withoutVideos}`\n if (!/^@[\\w.-]+$/.test(handle)) {\n throw new Error('channelHandle must be an @handle, UC channel ID, or YouTube channel URL')\n }\n return `https://www.youtube.com/${handle}/videos`\n}\n\nexport class BrowserDriver implements IBrowserDriver {\n private browser: Browser | null = null\n private context: BrowserContext | null = null\n private page: Page | null = null\n private kernelClient: Kernel | null = null\n private kernelSessionId: string | null = null\n\n async launch(config: DriverConfig): Promise<void> {\n if (config.kernelApiKey) {\n this.kernelClient = new Kernel({ apiKey: config.kernelApiKey })\n const kernelBrowser = await this.kernelClient.browsers.create({\n stealth: true,\n timeout_seconds: 600,\n ...(config.kernelProxyId ? { proxy_id: config.kernelProxyId } : {}),\n })\n this.kernelSessionId = kernelBrowser.session_id\n this.browser = await playwrightChromium.connectOverCDP(kernelBrowser.cdp_ws_url)\n this.context = this.browser.contexts()[0] ?? await this.browser.newContext()\n await this.installEsbuildHelperShims(this.context)\n this.page = this.context.pages()[0] ?? await this.context.newPage()\n return\n }\n\n const launchOpts = {\n headless: config.headless,\n proxy: config.proxy ? { server: config.proxy } : undefined,\n }\n const ctxOpts = {\n viewport: config.viewport,\n locale: config.locale,\n userAgent: DESKTOP_USER_AGENT,\n }\n if (config.profileDir) {\n this.context = await chromium.launchPersistentContext(config.profileDir, {\n ...launchOpts,\n ...ctxOpts,\n })\n await this.installEsbuildHelperShims(this.context)\n this.page = await this.context.newPage()\n } else {\n this.browser = await chromium.launch(launchOpts)\n this.context = await this.browser.newContext(ctxOpts)\n await this.installEsbuildHelperShims(this.context)\n this.page = await this.context.newPage()\n }\n }\n\n private async installEsbuildHelperShims(context: BrowserContext): Promise<void> {\n await context.addInitScript(() => {\n const g = globalThis as Record<string, unknown>\n if (typeof g.__name !== 'function') g.__name = (fn: unknown) => fn\n if (typeof g.__publicField !== 'function') g.__publicField = (obj: Record<string, unknown>, key: string, value: unknown) => { obj[key] = value; return value }\n })\n }\n\n async navigateToSERP(\n query: string,\n uule: UuleString | null,\n gl: string,\n hl: string,\n ): Promise<{ hasPaa: boolean }> {\n const params = new URLSearchParams({ q: query, gl, hl })\n if (uule) params.set('uule', uule)\n const url = 'https://www.google.com/search?' + params.toString()\n\n try {\n await this.page!.goto(url, { waitUntil: 'domcontentloaded', timeout: 45_000 })\n } catch (err) {\n const diag = await this.captureDiagnostics(url)\n throw new ExtractionError(`page.goto failed: ${(err as Error).message} | ${diag}`)\n }\n\n const captchaCount = await this.page!.locator(PAASelectors.captchaMarker).count()\n if (captchaCount > 0) {\n if (this.kernelClient) {\n try {\n await this.page!.waitForSelector(PAASelectors.container, { timeout: 45_000 })\n return { hasPaa: true }\n } catch {\n throw new CaptchaError(this.captchaMessage())\n }\n }\n throw new CaptchaError(this.captchaMessage())\n }\n\n const fastFound = await this.page!.waitForSelector(PAASelectors.item, { timeout: 4_000 }).catch(() => null)\n if (fastFound) return { hasPaa: true }\n\n const captchaAfter = await this.page!.locator(PAASelectors.captchaMarker).count()\n if (captchaAfter > 0) throw new CaptchaError(this.captchaMessage())\n\n for (let i = 1; i <= 6; i++) {\n await this.page!.evaluate((f: number) => { window.scrollTo(0, document.body.scrollHeight * f) }, i / 6)\n await this.page!.waitForTimeout(600)\n const count = await this.page!.locator(PAASelectors.item).count()\n if (count > 0) return { hasPaa: true }\n }\n\n return { hasPaa: false }\n }\n\n private async captureDiagnostics(intendedUrl: string): Promise<string> {\n try {\n const finalUrl = this.page!.url()\n const title = await this.page!.title().catch(() => '')\n const bodySnippet = await this.page!.evaluate(() => {\n const t = (document.body?.innerText ?? '').replace(/\\s+/g, ' ').trim()\n return t.slice(0, 400)\n }).catch(() => '')\n const consent = /consent\\.google\\./.test(finalUrl) || /before you continue/i.test(bodySnippet)\n const recaptcha = /recaptcha|unusual traffic|are you a robot/i.test(bodySnippet)\n const flags = [\n consent ? 'CONSENT_WALL' : '',\n recaptcha ? 'BOT_CHALLENGE' : '',\n finalUrl !== intendedUrl ? 'REDIRECTED' : '',\n ].filter(Boolean).join(',')\n return `intended=${intendedUrl} | final=${finalUrl} | title=\"${title}\" | flags=[${flags}] | body=\"${bodySnippet}\"`\n } catch (e) {\n return `diagnostics-failed: ${(e as Error).message}`\n }\n }\n\n private captchaMessage(): string {\n return this.kernelClient\n ? 'Google returned a CAPTCHA on this Kernel.sh session — retrying with a fresh session.'\n : RECAPTCHA_INSTRUCTIONS\n }\n\n async navigateTo(url: string): Promise<void> {\n try {\n await this.page!.goto(url, { waitUntil: 'domcontentloaded', timeout: 45_000 })\n } catch (err) {\n const diag = await this.captureDiagnostics(url)\n throw new ExtractionError(`page.goto failed: ${(err as Error).message} | ${diag}`)\n }\n }\n\n async navigateToChannel(channelHandle: string): Promise<void> {\n const url = buildYouTubeChannelVideosUrl(channelHandle)\n try {\n await this.page!.goto(url, { waitUntil: 'networkidle', timeout: 30_000 })\n } catch (err) {\n const diag = await this.captureDiagnostics(url)\n throw new ExtractionError(`navigateToChannel failed: ${(err as Error).message} | ${diag}`)\n }\n }\n\n async evaluate<T>(fn: (...args: unknown[]) => T | Promise<T>, arg?: unknown): Promise<T> {\n return (this.page! as { evaluate(fn: unknown, arg?: unknown): Promise<T> }).evaluate(fn, arg)\n }\n\n getPage(): Page {\n return this.page!\n }\n\n async close(): Promise<void> {\n if (this.browser) {\n const b = this.browser\n const sessionId = this.kernelSessionId\n const client = this.kernelClient\n this.browser = null\n this.context = null\n this.page = null\n this.kernelSessionId = null\n this.kernelClient = null\n try {\n await b.close()\n } finally {\n if (client && sessionId) {\n await client.browsers.deleteByID(sessionId).catch((err: unknown) =>\n console.warn('Kernel session cleanup failed:', err)\n )\n }\n }\n } else if (this.context) {\n const ctx = this.context\n this.context = null\n this.page = null\n await ctx.close()\n }\n }\n}\n","export const PAASelectors = {\n container: '.eJH8qe.adDDi',\n dataInitq: '[data-initq]',\n item: '.related-question-pair',\n itemDataQ: 'data-q',\n itemDataInitQ: 'data-initq',\n itemQuestionEl: '.JlqpRe',\n answerContainer: '.bCOlv',\n sourceTitle: 'h3',\n sourceSite: '.VuuXrf',\n sourceCite: 'cite',\n clickTarget: '.JlqpRe',\n expandedClass: 'aoRk1c',\n captchaMarker: '#captcha-form, #recaptcha, form[action*=\"/sorry/\"], .g-recaptcha, [data-sitekey]',\n} as const\n\nexport const VideoSelectors = {\n container: 'div[jscontroller=\"HWk0Gf\"]',\n sectionHeading: '.mgAbYb[role=\"heading\"]',\n item: 'a.rIRoqf',\n} as const\n\nexport const ShortVideoSelectors = {\n udm: '39',\n item: 'a.rIRoqf',\n durationPattern: /^\\d+:\\d+$/,\n platforms: ['YouTube', 'TikTok', 'Instagram', 'Facebook', 'X'],\n} as const\n\nexport const ForumSelectors = {\n section: '.ULSxyf',\n item: 'a.KYg7td.INpicf',\n title: '.hyYc0c',\n source: '.K4ETW',\n} as const\n\nexport const WhatPeopleSayingSelectors = {\n sectionTag: 'g-section-with-header',\n sectionHeadingText: 'What people are saying',\n card: '.dRzkFf[role=\"listitem\"]',\n cardLink: 'a.WlydOe[jsname=\"YKoRaf\"]',\n titleH1: 'h1.WQWxe',\n titleDiv: '.eAaXgc',\n popularCommentLabel: '.qgdis',\n source: '.sTl1Td',\n platformBadge: '.appd0, .KrMNbf',\n ytChannel: '.sjVJQd',\n ytDate: '.PLq9Je',\n authorNote: '.nDgy9d',\n} as const\n\nexport const AIOverviewSelectors = {\n root: '[data-hveid=\"CBMQAA\"]',\n wrapper: '.Fgyi2e',\n citations: '.Fgyi2e [data-hveid] a[jsname=\"pxBnId\"]',\n} as const\n\nexport const AIModeSelectors = {\n root: '[data-hveid=\"CAUQAA\"]',\n wrapper: '.Fgyi2e',\n citations: '.Fgyi2e [data-hveid] a[jsname=\"pxBnId\"]',\n} as const\n\nexport const OrganicSelectors = {\n result: '.wHYlTd.tF2Cxc',\n title: 'h3.LC20lb',\n siteName: '.VuuXrf',\n cite: 'cite.tjvcx',\n snippet: '.VwiC3b',\n redditCite: 'cite.qLRx3b',\n ratingWrap: '.Y0A0hc',\n ratingValue: '.yi40Hd',\n reviewCount: '.RDApEe',\n} as const\n\nexport const LocalPackSelectors = {\n headingText: 'Businesses',\n card: '.w7Dbne',\n name: '.OSrXXb',\n ratingValue: '.yi40Hd',\n reviewCount: '.RDApEe',\n} as const\n\nexport const SELECTORS_VERSION = '2026-05-07'\n","export const RECAPTCHA_INSTRUCTIONS = 'Google returned a CAPTCHA. Run with --headless=false to re-warm the browser profile, then retry.'\n\nexport class CaptchaError extends Error {\n readonly name = 'CaptchaError'\n constructor(public readonly instructions: string) {\n super(`CAPTCHA detected. ${instructions}`)\n }\n}\n\nexport class ExtractionError extends Error {\n readonly name = 'ExtractionError'\n constructor(message: string, public readonly cause?: unknown) {\n super(message)\n }\n}\n","import type { CanonicalLocationName } from './types.js'\n\nexport const LOCATIONS: Record<string, CanonicalLocationName> = {\n 'austin': 'Austin,Texas,United States',\n 'new york': 'New York,New York,United States',\n 'new york city': 'New York,New York,United States',\n 'nyc': 'New York,New York,United States',\n 'los angeles': 'Los Angeles,California,United States',\n 'la': 'Los Angeles,California,United States',\n 'chicago': 'Chicago,Illinois,United States',\n 'houston': 'Houston,Texas,United States',\n 'phoenix': 'Phoenix,Arizona,United States',\n 'philadelphia': 'Philadelphia,Pennsylvania,United States',\n 'philly': 'Philadelphia,Pennsylvania,United States',\n 'san antonio': 'San Antonio,Texas,United States',\n 'dallas': 'Dallas,Texas,United States',\n 'miami': 'Miami,Florida,United States',\n 'seattle': 'Seattle,Washington,United States',\n 'denver': 'Denver,Colorado,United States',\n 'loveland': 'Loveland,Colorado,United States',\n 'loveland co': 'Loveland,Colorado,United States',\n 'fort collins': 'Fort Collins,Colorado,United States',\n 'boulder': 'Boulder,Colorado,United States',\n 'colorado springs': 'Colorado Springs,Colorado,United States',\n 'boston': 'Boston,Massachusetts,United States',\n 'atlanta': 'Atlanta,Georgia,United States',\n 'san francisco': 'San Francisco,California,United States',\n 'sf': 'San Francisco,California,United States',\n 'portland': 'Portland,Oregon,United States',\n 'las vegas': 'Las Vegas,Nevada,United States',\n 'minneapolis': 'Minneapolis,Minnesota,United States',\n 'detroit': 'Detroit,Michigan,United States',\n 'nashville': 'Nashville,Tennessee,United States',\n 'charlotte': 'Charlotte,North Carolina,United States',\n 'orlando': 'Orlando,Florida,United States',\n 'san diego': 'San Diego,California,United States',\n 'baltimore': 'Baltimore,Maryland,United States',\n 'sacramento': 'Sacramento,California,United States',\n 'columbus': 'Columbus,Ohio,United States',\n 'indianapolis': 'Indianapolis,Indiana,United States',\n 'san jose': 'San Jose,California,United States',\n 'fort worth': 'Fort Worth,Texas,United States',\n 'jacksonville': 'Jacksonville,Florida,United States',\n 'memphis': 'Memphis,Tennessee,United States',\n 'louisville': 'Louisville,Kentucky,United States',\n 'raleigh': 'Raleigh,North Carolina,United States',\n 'richmond': 'Richmond,Virginia,United States',\n 'salt lake city': 'Salt Lake City,Utah,United States',\n 'toronto': 'Toronto,Ontario,Canada',\n 'vancouver': 'Vancouver,British Columbia,Canada',\n 'montreal': 'Montreal,Quebec,Canada',\n 'calgary': 'Calgary,Alberta,Canada',\n 'ottawa': 'Ottawa,Ontario,Canada',\n 'london': 'London,England,United Kingdom',\n 'manchester': 'Manchester,England,United Kingdom',\n 'birmingham': 'Birmingham,England,United Kingdom',\n 'edinburgh': 'Edinburgh,Scotland,United Kingdom',\n 'glasgow': 'Glasgow,Scotland,United Kingdom',\n 'leeds': 'Leeds,England,United Kingdom',\n 'sydney': 'Sydney,New South Wales,Australia',\n 'melbourne': 'Melbourne,Victoria,Australia',\n 'brisbane': 'Brisbane,Queensland,Australia',\n 'perth': 'Perth,Western Australia,Australia',\n 'adelaide': 'Adelaide,South Australia,Australia',\n 'dublin': 'Dublin,Leinster,Ireland',\n}\n","import type { CanonicalLocationName, UuleString } from './types.js'\nimport { LOCATIONS } from './locations.js'\n\nexport function encodeUule(name: CanonicalLocationName): UuleString {\n const encoded = Buffer.from(String.fromCharCode(name.length) + name).toString('base64')\n return `w+CAIQICI${encoded}`\n}\n\nexport function normalizeLocation(input: string): CanonicalLocationName {\n const key = input.toLowerCase().trim()\n return (LOCATIONS[key] ?? input) as CanonicalLocationName\n}\n","const MAX_ANSWER_LENGTH = 1200\n\nconst BOILERPLATE_PATTERNS: RegExp[] = [\n /An AI Overview is not available for this search/gi,\n /Can't generate an AI overview right now\\.?\\s*Try again later\\.?/gi,\n /\\bAI Overview\\b/gi,\n /\\bView all\\b/gi,\n]\n\nconst CUT_MARKERS: RegExp[] = [\n /\\bRelated Links\\b/i,\n /\\bAsk anything in\\s*AI Mode\\b/i,\n /\\bAI can make mistakes\\b/i,\n /\\bThis is for informational purposes only\\b/i,\n /\\bShow more\\b/i,\n /\\b\\d+\\s+sites\\b/i,\n /\\b\\d{1,2}\\s*[msh]\\s*[A-Z][A-Za-z]/,\n /\\b(?:YouTube|Reddit|Facebook|Instagram|TikTok)·/,\n]\n\nfunction normalizeWhitespace(text: string): string {\n return text\n .replace(/\\u00a0/g, ' ')\n .replace(/([.!?])([A-Z])/g, '$1 $2')\n .replace(/([:;])([A-Z])/g, '$1 $2')\n .replace(/([a-z])([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([A-Z][a-z])/g, '$1 $2')\n .replace(/([a-z])(\\d)/g, '$1 $2')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\nfunction cutAtFirstMarker(text: string): string {\n let cutAt = -1\n for (const marker of CUT_MARKERS) {\n const match = marker.exec(text)\n marker.lastIndex = 0\n if (match && (cutAt === -1 || match.index < cutAt)) cutAt = match.index\n }\n return cutAt === -1 ? text : text.slice(0, cutAt)\n}\n\nfunction cutAtSourceTitle(text: string, sourceTitle?: string): string {\n const title = sourceTitle?.trim()\n if (!title || title.length < 8) return text\n const idx = text.toLowerCase().indexOf(title.toLowerCase())\n return idx > 40 ? text.slice(0, idx) : text\n}\n\nfunction findAttributionCut(beforeUrl: string): number {\n const dateMatch = beforeUrl.match(/[•·]\\s*(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\\.?\\s+\\d{1,2},\\s+\\d{4}/i)\n if (dateMatch?.index && dateMatch.index > 40) return dateMatch.index\n\n const start = Math.max(0, beforeUrl.length - 260)\n const tail = beforeUrl.slice(start)\n const sentenceBreaks = [...tail.matchAll(/[.!?]\\s*(?=[A-Z][A-Za-z0-9\"'$])/g)]\n for (const match of sentenceBreaks) {\n const remainder = tail.slice(match.index + 1).trim()\n const lead = remainder.slice(0, 160)\n const looksLikeTitle = /^(?:Best|Top|What|How|Why|When|Where|Which|Can|Should|Is|Are|Do|Does)\\b/i.test(remainder)\n if (\n remainder.length > 20 &&\n looksLikeTitle &&\n /(?:\\s[-|]\\s|Heating|Cooling|Company|Services|Blog|Guide|Review)/i.test(lead)\n ) {\n return start + match.index + 1\n }\n }\n const last = sentenceBreaks.at(-1)\n if (last?.index !== undefined) return start + last.index + 1\n\n return beforeUrl.length\n}\n\nfunction cutAtUrlAttribution(text: string): string {\n const urlMatch = text.match(/https?:\\/\\/\\S+/i)\n if (!urlMatch?.index) return text\n\n const beforeUrl = text.slice(0, urlMatch.index)\n return beforeUrl.slice(0, findAttributionCut(beforeUrl))\n}\n\nfunction trimToSentenceLimit(text: string): string {\n if (text.length <= MAX_ANSWER_LENGTH) return text\n const slice = text.slice(0, MAX_ANSWER_LENGTH)\n const lastSentence = Math.max(slice.lastIndexOf('.'), slice.lastIndexOf('!'), slice.lastIndexOf('?'))\n return (lastSentence > 240 ? slice.slice(0, lastSentence + 1) : slice).trim()\n}\n\nexport function cleanPAAAnswerText(\n answer: string | null | undefined,\n question?: string,\n sourceTitle?: string,\n): string | undefined {\n if (!answer) return undefined\n\n let text = normalizeWhitespace(answer)\n const normalizedQuestion = question ? normalizeWhitespace(question) : ''\n if (normalizedQuestion && text.toLowerCase().startsWith(normalizedQuestion.toLowerCase())) {\n text = text.slice(normalizedQuestion.length).trim()\n }\n\n if (/^An error has occurred\\.?\\s*Please try again later\\.?/i.test(text)) {\n return undefined\n }\n\n for (const pattern of BOILERPLATE_PATTERNS) {\n text = text.replace(pattern, ' ')\n }\n text = text\n .replace(/\\b[A-Z][A-Za-z&'\\u2019 -]{2,60}\\+\\d+\\b/g, ' ')\n .replace(/\\b(?:[a-z0-9-]+\\.)+[a-z]{2,}\\+\\d+\\b/gi, ' ')\n\n text = normalizeWhitespace(text)\n text = cutAtFirstMarker(text)\n text = cutAtSourceTitle(text, sourceTitle)\n text = cutAtUrlAttribution(text)\n text = normalizeWhitespace(text)\n text = text.replace(/\\s+(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\\.?\\s+\\d{1,2},\\s+\\d{4}$/i, '').trim()\n text = trimToSentenceLimit(text)\n\n if (!text) return undefined\n if (/^An error has occurred\\.?\\s*Please try again later\\.?$/i.test(text)) return undefined\n\n return text\n}\n","import type { Page } from 'playwright'\nimport type { IBrowserDriver } from '../driver/IBrowserDriver.js'\nimport type { IProgressReporter } from '../output/IProgressReporter.js'\nimport { PAASelectors, VideoSelectors, ForumSelectors, ShortVideoSelectors, AIOverviewSelectors, AIModeSelectors, WhatPeopleSayingSelectors, OrganicSelectors, LocalPackSelectors } from '../selectors.js'\nimport { encodeUule, normalizeLocation } from '../uule.js'\nimport { RawPAAItemSchema } from '../schemas.js'\nimport { cleanPAAAnswerText } from '../lib/paa-answer-cleanup.js'\nimport type {\n HarvestOptions, HarvestResult, HarvestStats,\n RawPAAItem, PAANode, FlatRow, NormalizedQuestionKey, DriverConfig,\n VideoResult, ForumResult, AIOverviewResult, AIModeResult, GoogleSurface,\n WhatPeopleSayingCard, EntityIds, EntityRecord,\n OrganicResult, LocalPackBusiness,\n} from '../types.js'\nimport type { IPAAExtractor } from './IPAAExtractor.js'\n\nexport class PAAExtractor implements IPAAExtractor {\n constructor(\n private readonly driver: IBrowserDriver,\n private readonly reporter: IProgressReporter,\n ) {}\n\n private normalizeQuestion(q: string): NormalizedQuestionKey {\n return q.toLowerCase().replace(/[^\\w\\s]/g, '').replace(/\\s+/g, ' ').trim() as NormalizedQuestionKey\n }\n\n private async extractVisibleItems(page: Page): Promise<RawPAAItem[]> {\n const sels = PAASelectors\n const raw = await page.evaluate((selectors) => {\n function cleanText(el: Element | null): string {\n if (!el) return ''\n const parts: string[] = []\n for (const n of el.childNodes) {\n if (n.nodeType === Node.TEXT_NODE) {\n const text = n.textContent?.trim()\n if (text) parts.push(text)\n } else if (\n (n as Element).tagName === 'STYLE' ||\n (n as Element).tagName === 'SCRIPT'\n ) {\n continue\n } else {\n const text = cleanText(n as Element)\n if (text) parts.push(text)\n }\n }\n return parts.join(' ').replace(/\\s+/g, ' ').trim()\n }\n return Array.from(document.querySelectorAll(selectors.item)).map((pair) => ({\n question: pair.getAttribute(selectors.itemDataQ) || pair.getAttribute(selectors.itemDataInitQ) || '',\n answer: cleanText(pair.querySelector(selectors.answerContainer)) || undefined,\n sourceTitle: (pair.querySelector(selectors.sourceTitle) as HTMLElement | null)?.innerText?.trim() || undefined,\n sourceSite: (pair.querySelector(selectors.sourceSite) as HTMLElement | null)?.innerText?.trim() || undefined,\n sourceCite: (pair.querySelector(selectors.sourceCite) as HTMLElement | null)?.innerText?.trim() || undefined,\n }))\n }, sels)\n\n return raw.flatMap((item) => {\n const cleaned = {\n ...item,\n answer: cleanPAAAnswerText(item.answer, item.question, item.sourceTitle),\n }\n const result = RawPAAItemSchema.safeParse(cleaned)\n if (!result.success) {\n console.warn('[PAAExtractor] item parse failed:', item.question, result.error.issues[0]?.message)\n return []\n }\n return [result.data]\n })\n }\n\n private async clickItem(page: Page, questionText: string): Promise<void> {\n try {\n const pairLocator = page.locator(\n `${PAASelectors.item}[data-q=\"${questionText}\"], ${PAASelectors.item}[data-initq=\"${questionText}\"]`\n ).first()\n await pairLocator.click()\n } catch { }\n }\n\n private toFlatRow(item: RawPAAItem, depth: number, parentQuestion: string | null, seed: string): FlatRow {\n return {\n seed_query: seed,\n question: item.question,\n answer: item.answer ?? '',\n source_title: item.sourceTitle ?? '',\n source_site: item.sourceSite ?? '',\n source_cite: item.sourceCite ?? '',\n depth,\n parent_question: parentQuestion ?? '',\n extracted_at: new Date().toISOString(),\n }\n }\n\n private async runBFS(page: Page, options: HarvestOptions): Promise<FlatRow[]> {\n const seenKeys = new Set<NormalizedQuestionKey>()\n const seenQs = new Set<string>()\n const depthMap = new Map<string, number>()\n const results: FlatRow[] = []\n\n const readAllQs = (): Promise<string[]> =>\n page.evaluate(\n ({ sel, dataQ, dataInitQ, questionEl }: { sel: string; dataQ: string; dataInitQ: string; questionEl: string }) =>\n Array.from(document.querySelectorAll(sel))\n .map(el =>\n el.getAttribute(dataQ) ||\n el.getAttribute(dataInitQ) ||\n (el.querySelector(questionEl) as HTMLElement | null)?.innerText?.trim() ||\n ''\n )\n .filter(Boolean),\n { sel: PAASelectors.item, dataQ: PAASelectors.itemDataQ, dataInitQ: PAASelectors.itemDataInitQ, questionEl: PAASelectors.itemQuestionEl },\n )\n\n const dupRates: number[] = []\n const orderedQs: string[] = []\n\n for (let round = 0; round < options.depth; round++) {\n this.reporter.onDepth(round + 1)\n\n if (seenQs.size >= options.maxQuestions) break\n\n const beforeQs = await readAllQs()\n if (beforeQs.length >= options.maxQuestions) break\n\n const unexpandedItems = await page.$$(\n `${PAASelectors.item}:not(.${PAASelectors.expandedClass})`\n )\n if (unexpandedItems.length === 0) break\n\n for (const item of unexpandedItems) {\n try {\n await item.scrollIntoViewIfNeeded()\n await item.click({ force: true })\n await page.waitForTimeout(500)\n } catch { }\n }\n await page.waitForTimeout(1500)\n\n const afterQs = await readAllQs()\n const newQs = afterQs.slice(beforeQs.length)\n\n const newDups = newQs.filter(q => seenQs.has(q)).length\n const dupRate = newQs.length > 0 ? newDups / newQs.length : 0\n dupRates.push(dupRate)\n if (dupRates.length > 2) dupRates.shift()\n const rollingDupRate = dupRates.reduce((a, b) => a + b, 0) / dupRates.length\n\n for (const q of afterQs) {\n if (!seenQs.has(q)) { seenQs.add(q); orderedQs.push(q) }\n if (!depthMap.has(q)) depthMap.set(q, round + 1)\n }\n\n if (afterQs.length === beforeQs.length) break\n if (rollingDupRate >= 0.6) break\n }\n\n const itemMap = new Map((await this.extractVisibleItems(page)).map(i => [i.question, i]))\n\n for (const q of orderedQs) {\n if (results.length >= options.maxQuestions) break\n const key = this.normalizeQuestion(q)\n if (seenKeys.has(key)) continue\n seenKeys.add(key)\n const d = depthMap.get(q) ?? 1\n const item = itemMap.get(q)\n if (item) {\n results.push(this.toFlatRow(item, d, null, options.query))\n this.reporter.onQuestion({ question: item.question, answer: item.answer ?? null, sourceTitle: item.sourceTitle ?? null, sourceSite: item.sourceSite ?? null, sourceCite: item.sourceCite ?? null, depth: d, parentQuestion: null, children: [] })\n } else {\n results.push(this.toFlatRow({ question: q, answer: undefined, sourceTitle: undefined, sourceSite: undefined, sourceCite: undefined }, d, null, options.query))\n }\n }\n\n return results\n }\n\n private async extractVideos(page: Page): Promise<VideoResult[]> {\n const vsels = VideoSelectors\n return page.evaluate((sels) => {\n const results: Array<{ type: 'video' | 'short_video'; title: string; channel: string; platform: string; duration: string; url: string }> = []\n const containers = Array.from(document.querySelectorAll(sels.container))\n for (const container of containers) {\n const headingEl = container.querySelector(sels.sectionHeading)\n const headingText = headingEl?.textContent?.trim() ?? ''\n const type: 'video' | 'short_video' = headingText.toLowerCase().includes('short') ? 'short_video' : 'video'\n const items = Array.from(container.querySelectorAll(sels.item))\n for (const a of items) {\n const href = (a as HTMLAnchorElement).href\n if (!href || (!href.includes('youtube') && !href.includes('youtu.be'))) continue\n const raw = a.textContent?.trim() ?? ''\n const ytIdx = raw.indexOf('YouTube')\n if (ytIdx === -1) continue\n const title = raw.slice(0, ytIdx).trim()\n const remainder = raw.slice(ytIdx + 7).replace(/^[·\\s·]+/, '')\n const channelMatch = remainder.match(/^([^·\\n]+)/)\n const channel = channelMatch ? channelMatch[1].trim() : ''\n if (title) results.push({ type, title, channel, platform: 'YouTube', duration: '', url: href })\n }\n }\n return results\n }, vsels)\n }\n\n private async extractForums(page: Page): Promise<ForumResult[]> {\n const fsels = ForumSelectors\n return page.evaluate((sels) => {\n const results: Array<{ title: string; source: string; url: string }> = []\n const sections = Array.from(document.querySelectorAll(sels.section))\n const forumSection = sections.find((s) => s.textContent?.includes('Discussions'))\n if (!forumSection) return results\n const items = Array.from(forumSection.querySelectorAll(sels.item))\n for (const a of items) {\n const href = (a as HTMLAnchorElement).href\n if (!href) continue\n const titleEl = a.querySelector(sels.title)\n const sourceEl = a.querySelector(sels.source)\n const title = titleEl?.textContent?.trim() ?? ''\n const source = sourceEl?.textContent?.trim() ?? ''\n if (title) results.push({ title, source, url: href })\n }\n return results\n }, fsels)\n }\n\n private async extractShortVideos(page: Page, shortUrl: string): Promise<VideoResult[]> {\n try {\n await page.goto(shortUrl, { waitUntil: 'domcontentloaded' })\n await page.waitForTimeout(1500)\n } catch {\n return []\n }\n\n const svSels = {\n item: ShortVideoSelectors.item,\n platforms: [...ShortVideoSelectors.platforms] as string[],\n }\n\n const raw = await page.evaluate((sels) => {\n const seen = new Set<string>()\n const results: Array<{ title: string; channel: string; platform: string; duration: string; url: string }> = []\n const items = Array.from(document.querySelectorAll(sels.item))\n\n const videoHosts = ['youtube.com', 'youtu.be', 'tiktok.com', 'instagram.com', 'facebook.com', 'fb.watch']\n\n const byHref = new Map<string, string[]>()\n for (const a of items) {\n const href = (a as HTMLAnchorElement).href\n if (!href) continue\n if (!videoHosts.some((h) => href.includes(h))) continue\n const text = a.textContent?.trim() ?? ''\n if (!byHref.has(href)) byHref.set(href, [])\n byHref.get(href)!.push(text)\n }\n\n for (const [href, texts] of byHref.entries()) {\n if (seen.has(href)) continue\n seen.add(href)\n\n const duration = texts.find((t) => /^\\d+:\\d+$/.test(t)) ?? ''\n const titleText = texts.find((t) => !/^\\d+:\\d+$/.test(t) && t.length > 5) ?? ''\n if (!titleText) continue\n\n let title = titleText\n let platform = ''\n let channel = ''\n\n for (const p of sels.platforms) {\n let lastIdx = -1\n let search = 0\n while (true) {\n const found = titleText.indexOf(p, search)\n if (found === -1) break\n lastIdx = found\n search = found + 1\n }\n if (lastIdx === -1) continue\n const after = titleText.slice(lastIdx + p.length)\n const isSourceTag = /^[\\s·]/.test(after) || after.trim() === ''\n if (!isSourceTag) continue\n title = titleText.slice(0, lastIdx).trim()\n platform = p\n const stripped = after.replace(/^[\\s·]+/, '')\n const dotIdx = stripped.indexOf('·')\n channel = (dotIdx === -1 ? stripped : stripped.slice(0, dotIdx)).trim()\n break\n }\n\n if (title) results.push({ title, channel, platform, duration, url: href })\n }\n\n return results\n }, svSels)\n\n return raw.map((r) => ({ type: 'short_video' as const, ...r }))\n }\n\n private async extractWhatPeopleSaying(page: Page): Promise<WhatPeopleSayingCard[]> {\n const sels = WhatPeopleSayingSelectors\n return page.evaluate((s) => {\n const section = Array.from(document.querySelectorAll(s.sectionTag))\n .find((el) => el.textContent?.includes(s.sectionHeadingText))\n ?? document.querySelector('.yG4QQe.TBC9ub.NbhJ1c')\n\n if (!section) return []\n\n return Array.from(section.querySelectorAll(s.card)).map((card) => {\n const link = card.querySelector(s.cardLink) as HTMLAnchorElement | null\n const url = link?.href ?? ''\n\n const titleH1 = card.querySelector(s.titleH1)?.textContent?.trim()\n const titleDiv = card.querySelector(s.titleDiv)?.textContent?.trim()\n const title = titleH1 ?? titleDiv ?? ''\n\n const sourceText = card.querySelector(s.source)?.textContent?.trim() ?? ''\n const platformEl = card.querySelector(s.platformBadge)\n const platformText = platformEl?.textContent?.trim() ?? ''\n\n const ytChannel = card.querySelector(s.ytChannel)?.textContent?.trim() ?? ''\n const ytDate = card.querySelector(s.ytDate)?.textContent?.trim() ?? ''\n const authorNote = card.querySelector(s.authorNote)?.textContent?.trim() ?? null\n\n const commentLabelEl = card.querySelector(s.popularCommentLabel)\n let popularComment: string | null = null\n if (commentLabelEl) {\n let next = commentLabelEl.nextSibling\n while (next) {\n const t = next.textContent?.trim()\n if (t) { popularComment = t; break }\n next = next.nextSibling\n }\n }\n\n const allSpans = Array.from(card.querySelectorAll('span'))\n const duration = allSpans.find((s) => /^\\d+:\\d+$/.test(s.textContent?.trim() ?? ''))?.textContent?.trim() ?? null\n const engagementParts = allSpans\n .map((s) => s.textContent?.trim() ?? '')\n .filter((t) =>\n /\\d/.test(t) && (\n t.includes('comment') || t.includes('reaction') ||\n t.includes('view') || t.includes('like') || t.includes('share')\n )\n )\n const engagement = engagementParts[0] ?? ''\n\n const dateCandidates = allSpans\n .map((s) => s.textContent?.trim() ?? '')\n .filter((t) => /\\d+ (day|week|month|year|hour)s? ago|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/.test(t))\n const date = ytDate || (dateCandidates[0] ?? '')\n\n const platform = platformText || (ytChannel ? 'YouTube' : '')\n const source = ytChannel || sourceText\n\n let type: 'reddit' | 'facebook' | 'youtube' | 'instagram' | 'tiktok' | 'news' | 'unknown' = 'unknown'\n const pl = platform.toLowerCase()\n const src = source.toLowerCase()\n const srcRaw = sourceText.toLowerCase()\n if (pl.includes('reddit') || src.startsWith('r/')) type = 'reddit'\n else if (pl.includes('facebook') || srcRaw.includes('facebook')) type = 'facebook'\n else if (pl.includes('instagram') || srcRaw.includes('instagram')) type = 'instagram'\n else if (pl.includes('tiktok') || srcRaw.includes('tiktok')) type = 'tiktok'\n else if (pl.includes('youtube') || !!ytChannel) type = 'youtube'\n else type = 'news'\n\n return { type, title, url, source, platform, popularComment, engagement, date, duration, authorNote }\n })\n }, sels)\n }\n\n private async extractOrganicResults(page: Page): Promise<OrganicResult[]> {\n const sels = OrganicSelectors\n return page.evaluate((s) => {\n const out: Array<{ position: number; title: string; url: string; domain: string; cite: string | null; snippet: string | null; isRedditStyle: boolean; inlineRating: { value: string; count: string } | null }> = []\n let pos = 0\n document.querySelectorAll(s.result).forEach(card => {\n const titleEl = card.querySelector(s.title)\n if (!titleEl) return\n const title = titleEl.textContent?.trim() ?? ''\n const linkEl = titleEl.closest('a') as HTMLAnchorElement | null\n const url = linkEl?.href ?? ''\n if (!title || !url) return\n pos++\n const cite = card.querySelector(s.cite)?.textContent?.trim() ?? null\n const snippet = card.querySelector(s.snippet)?.textContent?.trim() ?? null\n const isRedditStyle = !!card.querySelector(s.redditCite)\n const ratingEl = card.querySelector(s.ratingWrap)\n const inlineRating = ratingEl\n ? { value: ratingEl.querySelector(s.ratingValue)?.textContent?.trim() ?? '', count: ratingEl.querySelector(s.reviewCount)?.textContent?.trim() ?? '' }\n : null\n let domain = ''\n try { domain = new URL(url).hostname.replace(/^www\\./, '') } catch { domain = card.querySelector(s.siteName)?.textContent?.trim() ?? '' }\n out.push({ position: pos, title, url, domain, cite, snippet, isRedditStyle, inlineRating })\n })\n return out\n }, sels)\n }\n\n private async extractLocalPack(page: Page): Promise<LocalPackBusiness[]> {\n const sels = LocalPackSelectors\n return page.evaluate((s) => {\n const out: Array<{ position: number; name: string; cid: string | null; rating: string | null; reviewCount: string | null; metadata: string[]; websiteUrl: string | null; directionsUrl: string | null }> = []\n let container: Element | null = null\n document.querySelectorAll('[role=\"heading\"]').forEach(h => {\n if (!container && h.textContent?.includes(s.headingText)) container = h.closest('[data-hveid]')\n })\n if (!container) return out\n ;(container as Element).querySelectorAll(s.card).forEach((card, i) => {\n const name = card.querySelector(s.name)?.textContent?.trim() ?? ''\n if (!name) return\n const rating = card.querySelector(s.ratingValue)?.textContent?.trim() ?? null\n const reviewRaw = card.querySelector(s.reviewCount)?.textContent?.trim() ?? null\n const reviewCount = reviewRaw ? reviewRaw.replace(/[()]/g, '').trim() : null\n let cid = (card.querySelector('a[data-cid]') as HTMLAnchorElement | null)?.getAttribute('data-cid') ?? null\n if (!cid) {\n for (const link of Array.from(card.querySelectorAll('a[href]')) as HTMLAnchorElement[]) {\n const m1 = link.href.match(/[?&]cid=(\\d+)/)\n if (m1) { cid = m1[1]; break }\n const m2 = link.href.match(/!1s0x[0-9a-f]+:0x([0-9a-f]+)/i)\n if (m2) { try { cid = BigInt('0x' + m2[1]).toString() } catch { } if (cid) break }\n }\n }\n const metadata: string[] = []\n card.querySelectorAll('div, span').forEach(el => {\n const text = Array.from(el.childNodes)\n .filter(n => n.nodeType === 3)\n .map(n => n.textContent?.trim() ?? '')\n .filter(t => t.length > 1 && t.length < 120)\n .join(' ')\n if (text && !metadata.includes(text)) metadata.push(text)\n })\n const links = Array.from(card.querySelectorAll('a[href]')) as HTMLAnchorElement[]\n const directionsUrl = links.find(a => a.href.includes('google.com/maps'))?.href ?? null\n const websiteUrl = links.find(a => !a.href.includes('google.com') && a.href.startsWith('http'))?.href ?? null\n out.push({ position: i + 1, name, cid, rating, reviewCount, metadata, websiteUrl, directionsUrl })\n })\n return out\n }, sels)\n }\n\n private async extractEntityIds(page: Page): Promise<EntityIds> {\n return page.evaluate(() => {\n const kgIds = new Set<string>()\n const cids = new Set<string>()\n const gcids = new Set<string>()\n const recordMap = new Map<string, { name: string; kgId: string | null; cid: string | null; gcid: string | null }>()\n\n function nameFromWrapper(el: Element): string {\n const sel = ['.OSrXXb', '.dbg0pd', '.tzt0oe', '[role=\"heading\"]', 'h3']\n for (const s of sel) {\n const found = el.querySelector(s)\n if (found?.textContent?.trim()) return found.textContent.trim()\n }\n return ''\n }\n\n document.querySelectorAll('[id^=\"pv-/g/\"]').forEach(wrapper => {\n const raw = wrapper.getAttribute('id')\n if (!raw) return\n const kgId = raw.replace('pv-', '')\n kgIds.add(kgId)\n const name = nameFromWrapper(wrapper)\n const cidEl = wrapper.querySelector('a[data-cid]')\n const cid = cidEl?.getAttribute('data-cid') ?? null\n if (cid) cids.add(cid)\n if (name) recordMap.set(kgId, { name, kgId, cid, gcid: null })\n })\n\n document.querySelectorAll('[data-mid]').forEach(el => {\n const mid = el.getAttribute('data-mid')\n if (!mid?.startsWith('/g/')) return\n kgIds.add(mid)\n if (!recordMap.has(mid)) {\n const name = nameFromWrapper(el)\n if (name) recordMap.set(mid, { name, kgId: mid, cid: null, gcid: null })\n }\n })\n\n document.querySelectorAll('.w7Dbne').forEach(card => {\n const cidEl = card.querySelector('a[data-cid]')\n const cid = cidEl?.getAttribute('data-cid') ?? null\n if (!cid) return\n cids.add(cid)\n const name = card.querySelector('.OSrXXb')?.textContent?.trim() ?? ''\n if (!name) return\n const kgIdEl = card.querySelector('[id^=\"pv-/g/\"]')\n const kgId = kgIdEl ? kgIdEl.getAttribute('id')!.replace('pv-', '') : null\n const key = kgId ?? `cid:${cid}`\n if (recordMap.has(key)) {\n const existing = recordMap.get(key)!\n if (!existing.cid) recordMap.set(key, { ...existing, cid })\n } else {\n recordMap.set(key, { name, kgId, cid, gcid: null })\n }\n })\n\n document.querySelectorAll('a[data-cid]').forEach(el => {\n const cid = el.getAttribute('data-cid')\n if (!cid) return\n cids.add(cid)\n const alreadyNamed = [...recordMap.values()].some(r => r.cid === cid)\n if (!alreadyNamed) {\n let node: Element | null = el.parentElement\n let name = ''\n for (let i = 0; i < 8 && node; i++) {\n const h = node.querySelector('.OSrXXb, .dbg0pd, [role=\"heading\"], h3')\n if (h?.textContent?.trim()) { name = h.textContent.trim(); break }\n node = node.parentElement\n }\n if (name) recordMap.set(`cid:${cid}`, { name, kgId: null, cid, gcid: null })\n }\n })\n\n const scriptContent = Array.from(document.querySelectorAll('script:not([src])'))\n .map(s => s.textContent ?? '')\n .filter(t => t.length > 10_000)\n .join('\\n')\n\n for (const m of scriptContent.matchAll(/\\/g\\/[a-zA-Z0-9_-]{5,20}/g)) kgIds.add(m[0])\n for (const m of scriptContent.matchAll(/gcid:[a-zA-Z0-9_]+/g)) gcids.add(m[0])\n for (const m of scriptContent.matchAll(/0x[0-9a-f]+:0x([0-9a-f]+)/gi)) {\n try { cids.add(BigInt('0x' + m[1]).toString()) } catch { }\n }\n\n return { entities: [...recordMap.values()], kgIds: [...kgIds], cids: [...cids], gcids: [...gcids] }\n })\n }\n\n private mergeLocalPackIntoEntities(entityIds: EntityIds, localPack: LocalPackBusiness[]): EntityIds {\n const cidSet = new Set<string>(entityIds.cids)\n const records = entityIds.entities.map(r => ({ ...r }))\n\n for (const biz of localPack) {\n if (!biz.cid) continue\n cidSet.add(biz.cid)\n const nameNorm = biz.name.toLowerCase().trim()\n const byName = records.find(r => r.name.toLowerCase().trim() === nameNorm)\n if (byName) {\n if (!byName.cid) byName.cid = biz.cid\n } else if (!records.find(r => r.cid === biz.cid)) {\n records.push({ name: biz.name, kgId: null, cid: biz.cid, gcid: null })\n }\n }\n\n return { ...entityIds, entities: records, cids: [...cidSet] }\n }\n\n private async extractAISurfaces(page: Page): Promise<{\n surface: GoogleSurface\n aiOverview: AIOverviewResult\n aiMode: AIModeResult\n }> {\n const aioSels = AIOverviewSelectors\n const aimSels = AIModeSelectors\n\n return page.evaluate(({ aio, aim }) => {\n const sn: string = (window as unknown as { google?: { sn?: string } }).google?.sn ?? 'unknown'\n const surface: 'web' | 'aim' | 'unknown' =\n sn === 'aim' ? 'aim' : sn === 'web' ? 'web' : 'unknown'\n\n function findAIORoot(): Element | null {\n const primary = document.querySelector(aio.root)\n if (primary) return primary\n const headings = document.querySelectorAll('h1, h2, h3, [role=\"heading\"]')\n for (const h of headings) {\n if (h.textContent?.trim() === 'AI Overview') {\n let el: Element | null = h.parentElement\n for (let i = 0; i < 6 && el; i++) {\n if (el.querySelectorAll('a').length > 1) return el\n el = el.parentElement\n }\n return h.parentElement\n }\n }\n return null\n }\n\n const aioRoot = findAIORoot()\n const aioContainer = aioRoot ? (aioRoot.closest(aio.wrapper) ?? aioRoot) : null\n\n let aioText: string | null = null\n if (aioContainer) {\n const clone = aioContainer.cloneNode(true) as Element\n clone.querySelectorAll('script,style,noscript').forEach((el) => el.remove())\n clone.querySelectorAll('h1,h2,h3,h4,[role=\"heading\"]').forEach((el) => el.remove())\n clone.querySelectorAll('button,[role=\"button\"]').forEach((el) => el.remove())\n clone.querySelectorAll('a').forEach((el) => el.remove())\n const candidate = clone.textContent?.replace(/\\s+/g, ' ').trim() || null\n const isErrorState = !candidate ||\n /not available|try again|can't generate/i.test(candidate)\n aioText = isErrorState ? null : candidate\n }\n\n const aioDetected = !!aioRoot && aioText !== null\n\n const aioCitations = Array.from(aioContainer?.querySelectorAll('a[href]') ?? [])\n .filter((a) => (a as HTMLAnchorElement).href && !(a as HTMLAnchorElement).href.startsWith('javascript'))\n .map((a) => ({\n text: (a as HTMLAnchorElement).textContent?.trim() ?? '',\n href: (a as HTMLAnchorElement).href,\n }))\n .filter((c) => c.text && c.href)\n\n const aimRoot = document.querySelector(aim.root)\n const aimDetected = surface === 'aim' && !!aimRoot\n const aimContainer = aimRoot?.closest(aim.wrapper) ?? null\n\n let aimText: string | null = null\n if (aimContainer) {\n const clone = aimContainer.cloneNode(true) as Element\n clone.querySelectorAll('script,style,noscript').forEach((el) => el.remove())\n clone.querySelectorAll('h1,h2,h3,h4,[role=\"heading\"]').forEach((el) => el.remove())\n clone.querySelectorAll('button,[role=\"button\"]').forEach((el) => el.remove())\n clone.querySelectorAll('a').forEach((el) => el.remove())\n const candidate = clone.textContent?.replace(/\\s+/g, ' ').trim() || null\n const isErrorState = !candidate ||\n /not available|try again|can't generate/i.test(candidate)\n aimText = isErrorState ? null : candidate\n }\n\n const aimCitations = aimDetected\n ? Array.from(aimContainer?.querySelectorAll('a[href]') ?? [])\n .filter((a) => (a as HTMLAnchorElement).href && !(a as HTMLAnchorElement).href.startsWith('javascript'))\n .map((a) => ({\n text: (a as HTMLAnchorElement).textContent?.trim() ?? '',\n href: (a as HTMLAnchorElement).href,\n }))\n .filter((c) => c.text && c.href)\n : []\n\n return {\n surface,\n aiOverview: { detected: aioDetected, text: aioText, citations: aioCitations },\n aiMode: { detected: aimDetected, text: aimText, citations: aimCitations },\n }\n }, { aio: aioSels, aim: aimSels })\n }\n\n private buildTree(flat: FlatRow[], _seed: string): PAANode[] {\n const roots: PAANode[] = []\n const nodeMap = new Map<string, PAANode>()\n\n for (const row of flat) {\n const node: PAANode = {\n question: row.question,\n answer: row.answer || null,\n sourceTitle: row.source_title || null,\n sourceSite: row.source_site || null,\n sourceCite: row.source_cite || null,\n depth: row.depth,\n parentQuestion: row.parent_question || null,\n children: [],\n }\n nodeMap.set(row.question, node)\n }\n\n for (const node of nodeMap.values()) {\n if (node.parentQuestion && nodeMap.has(node.parentQuestion)) {\n nodeMap.get(node.parentQuestion)!.children.push(node)\n } else {\n roots.push(node)\n }\n }\n\n return roots\n }\n\n async extract(options: HarvestOptions): Promise<HarvestResult> {\n const startMs = Date.now()\n const config: DriverConfig = {\n headless: options.headless,\n profileDir: options.profileDir,\n proxy: options.proxy,\n kernelApiKey: options.kernelApiKey,\n kernelProxyId: options.kernelProxyId,\n viewport: { width: 1280, height: 800 },\n locale: `${options.hl}-${options.gl.toUpperCase()}`,\n }\n\n let errorCount = 0\n\n try {\n await this.driver.launch(config)\n const uule = options.location ? encodeUule(normalizeLocation(options.location)) : null\n const { hasPaa } = await this.driver.navigateToSERP(options.query, uule, options.gl, options.hl)\n\n const page = this.driver.getPage() as Page\n\n if (options.serpOnly) {\n const [organicResults, localPack, rawEntityIds] = await Promise.all([\n this.extractOrganicResults(page),\n this.extractLocalPack(page),\n this.extractEntityIds(page),\n ])\n const entityIds = this.mergeLocalPackIntoEntities(rawEntityIds, localPack)\n let allOrganic = organicResults\n if ((options.pages ?? 1) >= 2) {\n const p2params = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, start: '10' })\n if (uule) p2params.set('uule', uule)\n await this.driver.navigateTo('https://www.google.com/search?' + p2params.toString())\n const p2organic = await this.extractOrganicResults(page)\n allOrganic = [...organicResults, ...p2organic.map(r => ({ ...r, position: r.position + 10 }))]\n }\n const stats: HarvestStats = {\n seed: options.query, totalQuestions: 0, maxDepthReached: 0,\n durationMs: Date.now() - startMs, errorCount,\n }\n this.reporter.onComplete(stats)\n return {\n seed: options.query, location: options.location ?? null,\n extractedAt: new Date().toISOString(), totalQuestions: 0,\n surface: 'web' as const,\n aiOverview: { detected: false, text: null, citations: [] },\n aiMode: { detected: false, text: null, citations: [] },\n whatPeopleSaying: [], tree: [], flat: [], videos: [], forums: [],\n organicResults: allOrganic, localPack, entityIds, stats,\n }\n }\n\n const [videos, forums, whatPeopleSaying, rawEntityIds, organicResults, localPack] = await Promise.all([\n this.extractVideos(page),\n this.extractForums(page),\n this.extractWhatPeopleSaying(page),\n this.extractEntityIds(page),\n this.extractOrganicResults(page),\n this.extractLocalPack(page),\n ])\n const entityIds = this.mergeLocalPackIntoEntities(rawEntityIds, localPack)\n this.reporter.onVideos(videos)\n this.reporter.onForums(forums)\n\n if (!hasPaa) {\n let noPaaOrganic = organicResults\n if ((options.pages ?? 1) >= 2) {\n const p2params = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, start: '10' })\n if (uule) p2params.set('uule', uule)\n await this.driver.navigateTo('https://www.google.com/search?' + p2params.toString())\n const p2organic = await this.extractOrganicResults(page)\n noPaaOrganic = [...organicResults, ...p2organic.map(r => ({ ...r, position: r.position + 10 }))]\n }\n const aiSurfaces = await this.extractAISurfaces(page)\n const stats: HarvestStats = {\n seed: options.query, totalQuestions: 0, maxDepthReached: 0,\n durationMs: Date.now() - startMs, errorCount,\n }\n this.reporter.onComplete(stats)\n return {\n seed: options.query, location: options.location ?? null,\n extractedAt: new Date().toISOString(), totalQuestions: 0,\n surface: aiSurfaces.surface,\n aiOverview: aiSurfaces.aiOverview,\n aiMode: aiSurfaces.aiMode,\n whatPeopleSaying, tree: [], flat: [], videos, forums,\n organicResults: noPaaOrganic, localPack, entityIds, stats,\n }\n }\n\n const flat = await this.runBFS(page, options)\n const aiSurfaces = await this.extractAISurfaces(page)\n\n const shortVidsParams = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, udm: ShortVideoSelectors.udm })\n if (uule) shortVidsParams.set('uule', uule)\n const shortVideos = await this.extractShortVideos(page, 'https://www.google.com/search?' + shortVidsParams.toString())\n this.reporter.onVideos(shortVideos)\n\n let allOrganic = organicResults\n if ((options.pages ?? 1) >= 2) {\n const p2params = new URLSearchParams({ q: options.query, gl: options.gl, hl: options.hl, start: '10' })\n if (uule) p2params.set('uule', uule)\n await this.driver.navigateTo('https://www.google.com/search?' + p2params.toString())\n const p2organic = await this.extractOrganicResults(page)\n allOrganic = [...organicResults, ...p2organic.map(r => ({ ...r, position: r.position + 10 }))]\n }\n\n const allVideos = [...videos, ...shortVideos]\n const tree = this.buildTree(flat, options.query)\n\n const stats: HarvestStats = {\n seed: options.query,\n totalQuestions: flat.length,\n maxDepthReached: flat.reduce((m, r) => Math.max(m, r.depth), 0),\n durationMs: Date.now() - startMs,\n errorCount,\n }\n\n this.reporter.onComplete(stats)\n\n return {\n seed: options.query,\n location: options.location ?? null,\n extractedAt: new Date().toISOString(),\n totalQuestions: flat.length,\n surface: aiSurfaces.surface,\n aiOverview: aiSurfaces.aiOverview,\n aiMode: aiSurfaces.aiMode,\n whatPeopleSaying,\n tree,\n flat,\n videos: allVideos,\n forums,\n organicResults: allOrganic,\n localPack,\n entityIds,\n stats,\n }\n } catch (err) {\n errorCount++\n this.reporter.onError(err instanceof Error ? err : new Error(String(err)))\n throw err\n } finally {\n await this.driver.close()\n }\n }\n}\n","import { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport Papa from 'papaparse'\nimport type { HarvestResult, FlatRow, VideoResult, ForumResult, AICitation, WhatPeopleSayingCard } from '../types.js'\nimport type { IOutputSerializer } from './IOutputSerializer.js'\n\nexport class OutputSerializer implements IOutputSerializer {\n async writeJSON(result: HarvestResult, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = result.seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const filename = `${slug}-${Date.now()}.json`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, JSON.stringify(result, null, 2), 'utf8')\n return fullPath\n }\n\n async writeCSV(rows: FlatRow[], outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const seedRaw = rows[0]?.seed_query ?? 'paa'\n const slug = seedRaw.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const csv = Papa.unparse(rows, { header: true })\n const filename = `${slug}-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeVideoCSV(videos: VideoResult[], seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const csv = Papa.unparse(videos, { header: true })\n const filename = `${slug}-videos-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeForumCSV(forums: ForumResult[], seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const csv = Papa.unparse(forums, { header: true })\n const filename = `${slug}-forums-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeAIOverviewCSV(citations: AICitation[], text: string | null, seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const rows = citations.map((c, i) => ({\n seed_query: seed,\n response_text: i === 0 ? (text ?? '') : '',\n citation_text: c.text,\n citation_href: c.href,\n }))\n const csv = Papa.unparse(rows, { header: true })\n const filename = `${slug}-ai-overview-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeAIModeCSV(citations: AICitation[], text: string | null, seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const rows = citations.map((c, i) => ({\n seed_query: seed,\n response_text: i === 0 ? (text ?? '') : '',\n citation_text: c.text,\n citation_href: c.href,\n }))\n const csv = Papa.unparse(rows, { header: true })\n const filename = `${slug}-ai-mode-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n\n async writeWhatPeopleSayingCSV(cards: WhatPeopleSayingCard[], seed: string, outputDir: string): Promise<string> {\n await fs.mkdir(outputDir, { recursive: true })\n const slug = seed.toLowerCase().replace(/\\W+/g, '-').slice(0, 40)\n const rows = cards.map((c) => ({ seed_query: seed, ...c }))\n const csv = Papa.unparse(rows, { header: true })\n const filename = `${slug}-what-people-saying-${Date.now()}.csv`\n const fullPath = path.join(outputDir, filename)\n await fs.writeFile(fullPath, csv, 'utf8')\n return fullPath\n }\n}\n","import type { PAANode, HarvestStats, VideoResult, ForumResult } from '../types.js'\nimport type { IProgressReporter } from './IProgressReporter.js'\n\nexport class ProgressReporter implements IProgressReporter {\n onQuestion(node: PAANode): void {\n process.stdout.write(JSON.stringify({ event: 'question', depth: node.depth, question: node.question }) + '\\n')\n }\n\n onDepth(depth: number): void {\n process.stdout.write(JSON.stringify({ event: 'depth', depth }) + '\\n')\n }\n\n onVideos(videos: VideoResult[]): void {\n for (const v of videos) {\n process.stdout.write(JSON.stringify({ event: 'video', type: v.type, platform: v.platform, duration: v.duration, title: v.title, channel: v.channel, url: v.url }) + '\\n')\n }\n }\n\n onForums(forums: ForumResult[]): void {\n for (const f of forums) {\n process.stdout.write(JSON.stringify({ event: 'forum', title: f.title, source: f.source, url: f.url }) + '\\n')\n }\n }\n\n onComplete(stats: HarvestStats): void {\n process.stdout.write(JSON.stringify({ event: 'complete', ...stats }) + '\\n')\n }\n\n onError(err: Error): void {\n process.stderr.write(JSON.stringify({ event: 'error', type: err.constructor.name, message: err.message }) + '\\n')\n }\n}\n","import { HarvestOptionsSchema } from './schemas.js'\nimport type { HarvestOptions, HarvestResult } from './types.js'\nimport { BrowserDriver } from './driver/BrowserDriver.js'\nimport { PAAExtractor } from './extractor/PAAExtractor.js'\nimport { OutputSerializer } from './output/OutputSerializer.js'\nimport { ProgressReporter } from './output/ProgressReporter.js'\nimport { CaptchaError } from './errors.js'\n\nconst MAX_ATTEMPTS = 3\n\nasync function extractOnce(options: HarvestOptions): Promise<HarvestResult> {\n const driver = new BrowserDriver()\n const reporter = new ProgressReporter()\n const extractor = new PAAExtractor(driver, reporter)\n try {\n return await extractor.extract(options)\n } finally {\n await driver.close()\n }\n}\n\nexport async function harvest(rawOptions: unknown): Promise<HarvestResult> {\n const raw = typeof rawOptions === 'object' && rawOptions !== null ? rawOptions : {}\n const merged = {\n kernelApiKey: process.env.KERNEL_API_KEY?.trim(),\n kernelProxyId: process.env.KERNEL_PROXY_ID?.trim(),\n ...raw,\n }\n const options = HarvestOptionsSchema.parse(merged)\n const serializer = new OutputSerializer()\n\n for (let i = 0; i < MAX_ATTEMPTS; i++) {\n try {\n const result = await extractOnce(options)\n if (options.format === 'json' || options.format === 'both') {\n await serializer.writeJSON(result, options.outputDir)\n }\n if (options.format === 'csv' || options.format === 'both') {\n await Promise.all([\n serializer.writeCSV(result.flat, options.outputDir),\n result.videos.length > 0 ? serializer.writeVideoCSV(result.videos, result.seed, options.outputDir) : Promise.resolve(''),\n result.forums.length > 0 ? serializer.writeForumCSV(result.forums, result.seed, options.outputDir) : Promise.resolve(''),\n result.aiOverview.detected ? serializer.writeAIOverviewCSV(result.aiOverview.citations, result.aiOverview.text, result.seed, options.outputDir) : Promise.resolve(''),\n result.aiMode.detected ? serializer.writeAIModeCSV(result.aiMode.citations, result.aiMode.text, result.seed, options.outputDir) : Promise.resolve(''),\n result.whatPeopleSaying.length > 0 ? serializer.writeWhatPeopleSayingCSV(result.whatPeopleSaying, result.seed, options.outputDir) : Promise.resolve(''),\n ])\n }\n return result\n } catch (err) {\n if (err instanceof CaptchaError && i < MAX_ATTEMPTS - 1) {\n continue\n }\n throw err\n }\n }\n const sessionDesc = options.kernelApiKey ? `${MAX_ATTEMPTS} fresh Kernel.sh sessions` : `${MAX_ATTEMPTS} attempts`\n throw new CaptchaError(`CAPTCHA on all ${sessionDesc}. Try again in a few minutes.`)\n}\n"],"mappings":";AAAA,SAAS,SAAS;AAEX,IAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,OAAc,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC9B,UAAc,EAAE,OAAO,EAAE,SAAS;AAAA,EAClC,IAAc,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EAC/C,IAAc,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EAC/C,OAAc,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC;AAAA,EACvD,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAI,EAAE,QAAQ,GAAG;AAAA,EAC3D,UAAc,EAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EACvC,YAAc,EAAE,OAAO,EAAE,SAAS;AAAA,EAClC,OAAc,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACxC,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,EAClC,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,EACnC,WAAc,EAAE,OAAO,EAAE,QAAQ,cAAc;AAAA,EAC/C,QAAc,EAAE,KAAK,CAAC,QAAQ,OAAO,MAAM,CAAC,EAAE,QAAQ,MAAM;AAAA,EAC5D,UAAc,EAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EACvC,OAAc,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;AACxD,CAAC;AAEM,IAAM,yBAAyB,EAAE,OAAO;AAAA,EAC7C,cAAe,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC/B,UAAe,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC/B,IAAe,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EAChD,IAAe,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EAChD,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EACzC,YAAe,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE;AAAA,EAC1D,cAAe,EAAE,OAAO,EAAE,SAAS;AAAA,EACnC,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,EACnC,UAAe,EAAE,QAAQ,EAAE,QAAQ,IAAI;AACzC,CAAC;AAEM,IAAM,mBAAmB,EAAE,OAAO;AAAA,EACvC,UAAa,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC7B,QAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,YAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,YAAa,EAAE,OAAO,EAAE,SAAS;AACnC,CAAC;;;ACtCD,SAAS,gBAAgB;AACzB,OAAO,mBAAmB;AAC1B,SAAS,YAAY,0BAA0B;AAE/C,OAAO,YAAY;;;ACJZ,IAAM,eAAe;AAAA,EAC1B,WAAiB;AAAA,EACjB,WAAiB;AAAA,EACjB,MAAiB;AAAA,EACjB,WAAiB;AAAA,EACjB,eAAiB;AAAA,EACjB,gBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,aAAiB;AAAA,EACjB,YAAiB;AAAA,EACjB,YAAiB;AAAA,EACjB,aAAiB;AAAA,EACjB,eAAiB;AAAA,EACjB,eAAiB;AACnB;AAEO,IAAM,iBAAiB;AAAA,EAC5B,WAAkB;AAAA,EAClB,gBAAkB;AAAA,EAClB,MAAkB;AACpB;AAEO,IAAM,sBAAsB;AAAA,EACjC,KAAkB;AAAA,EAClB,MAAkB;AAAA,EAClB,iBAAkB;AAAA,EAClB,WAAkB,CAAC,WAAW,UAAU,aAAa,YAAY,GAAG;AACtE;AAEO,IAAM,iBAAiB;AAAA,EAC5B,SAAU;AAAA,EACV,MAAU;AAAA,EACV,OAAU;AAAA,EACV,QAAU;AACZ;AAEO,IAAM,4BAA4B;AAAA,EACvC,YAAqB;AAAA,EACrB,oBAAqB;AAAA,EACrB,MAAqB;AAAA,EACrB,UAAqB;AAAA,EACrB,SAAqB;AAAA,EACrB,UAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,QAAqB;AAAA,EACrB,eAAqB;AAAA,EACrB,WAAqB;AAAA,EACrB,QAAqB;AAAA,EACrB,YAAqB;AACvB;AAEO,IAAM,sBAAsB;AAAA,EACjC,MAAW;AAAA,EACX,SAAW;AAAA,EACX,WAAW;AACb;AAEO,IAAM,kBAAkB;AAAA,EAC7B,MAAW;AAAA,EACX,SAAW;AAAA,EACX,WAAW;AACb;AAEO,IAAM,mBAAmB;AAAA,EAC9B,QAAc;AAAA,EACd,OAAc;AAAA,EACd,UAAc;AAAA,EACd,MAAc;AAAA,EACd,SAAc;AAAA,EACd,YAAc;AAAA,EACd,YAAc;AAAA,EACd,aAAc;AAAA,EACd,aAAc;AAChB;AAEO,IAAM,qBAAqB;AAAA,EAChC,aAAc;AAAA,EACd,MAAc;AAAA,EACd,MAAc;AAAA,EACd,aAAc;AAAA,EACd,aAAc;AAChB;;;ACjFO,IAAM,yBAAyB;AAE/B,IAAM,eAAN,cAA2B,MAAM;AAAA,EAEtC,YAA4B,cAAsB;AAChD,UAAM,qBAAqB,YAAY,EAAE;AADf;AAAA,EAE5B;AAAA,EAF4B;AAAA,EADnB,OAAO;AAIlB;AAEO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAEzC,YAAY,SAAiC,OAAiB;AAC5D,UAAM,OAAO;AAD8B;AAAA,EAE7C;AAAA,EAF6C;AAAA,EADpC,OAAO;AAIlB;;;AFJA,SAAS,IAAI,cAAc,CAAC;AAE5B,IAAM,qBACJ;AAEK,SAAS,6BAA6B,cAA8B;AACzE,QAAM,MAAM,aAAa,KAAK;AAC9B,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,2BAA2B;AAErD,QAAM,UAAU,gBAAgB,KAAK,GAAG,KAAK,+BAA+B,KAAK,GAAG;AACpF,MAAI,SAAS;AACX,UAAM,SAAS,IAAI,IAAI,gBAAgB,KAAK,GAAG,IAAI,MAAM,WAAW,GAAG,EAAE;AACzE,UAAM,OAAO,OAAO,SAAS,QAAQ,UAAU,EAAE,EAAE,QAAQ,QAAQ,EAAE,EAAE,YAAY;AACnF,QAAI,SAAS,cAAe,OAAM,IAAI,MAAM,oCAAoC;AAEhF,UAAM,WAAW,OAAO,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AAC1D,UAAM,QAAQ,SAAS,CAAC,KAAK;AAC7B,UAAM,SAAS,SAAS,CAAC,KAAK;AAE9B,QAAI,MAAM,WAAW,GAAG,EAAG,QAAO,2BAA2B,KAAK;AAClE,QAAI,UAAU,aAAa,OAAQ,QAAO,mCAAmC,MAAM;AACnF,SAAK,UAAU,OAAO,UAAU,WAAW,OAAQ,QAAO,2BAA2B,KAAK,IAAI,MAAM;AAEpG,UAAM,IAAI,MAAM,gFAAgF;AAAA,EAClG;AAEA,QAAM,WAAW,IAAI,QAAQ,QAAQ,EAAE,EAAE,QAAQ,QAAQ,EAAE;AAC3D,QAAM,gBAAgB,SAAS,QAAQ,cAAc,EAAE;AACvD,MAAI,iBAAiB,KAAK,aAAa,GAAG;AACxC,WAAO,mCAAmC,aAAa;AAAA,EACzD;AAEA,QAAM,SAAS,cAAc,WAAW,GAAG,IAAI,gBAAgB,IAAI,aAAa;AAChF,MAAI,CAAC,aAAa,KAAK,MAAM,GAAG;AAC9B,UAAM,IAAI,MAAM,yEAAyE;AAAA,EAC3F;AACA,SAAO,2BAA2B,MAAM;AAC1C;AAEO,IAAM,gBAAN,MAA8C;AAAA,EAC3C,UAA0B;AAAA,EAC1B,UAAiC;AAAA,EACjC,OAAoB;AAAA,EACpB,eAA8B;AAAA,EAC9B,kBAAiC;AAAA,EAEzC,MAAM,OAAO,QAAqC;AAChD,QAAI,OAAO,cAAc;AACvB,WAAK,eAAe,IAAI,OAAO,EAAE,QAAQ,OAAO,aAAa,CAAC;AAC9D,YAAM,gBAAgB,MAAM,KAAK,aAAa,SAAS,OAAO;AAAA,QAC5D,SAAS;AAAA,QACT,iBAAiB;AAAA,QACjB,GAAI,OAAO,gBAAgB,EAAE,UAAU,OAAO,cAAc,IAAI,CAAC;AAAA,MACnE,CAAC;AACD,WAAK,kBAAkB,cAAc;AACrC,WAAK,UAAU,MAAM,mBAAmB,eAAe,cAAc,UAAU;AAC/E,WAAK,UAAU,KAAK,QAAQ,SAAS,EAAE,CAAC,KAAK,MAAM,KAAK,QAAQ,WAAW;AAC3E,YAAM,KAAK,0BAA0B,KAAK,OAAO;AACjD,WAAK,OAAO,KAAK,QAAQ,MAAM,EAAE,CAAC,KAAK,MAAM,KAAK,QAAQ,QAAQ;AAClE;AAAA,IACF;AAEA,UAAM,aAAa;AAAA,MACjB,UAAU,OAAO;AAAA,MACjB,OAAO,OAAO,QAAQ,EAAE,QAAQ,OAAO,MAAM,IAAI;AAAA,IACnD;AACA,UAAM,UAAU;AAAA,MACd,UAAU,OAAO;AAAA,MACjB,QAAQ,OAAO;AAAA,MACf,WAAW;AAAA,IACb;AACA,QAAI,OAAO,YAAY;AACrB,WAAK,UAAU,MAAM,SAAS,wBAAwB,OAAO,YAAY;AAAA,QACvE,GAAG;AAAA,QACH,GAAG;AAAA,MACL,CAAC;AACD,YAAM,KAAK,0BAA0B,KAAK,OAAO;AACjD,WAAK,OAAO,MAAM,KAAK,QAAQ,QAAQ;AAAA,IACzC,OAAO;AACL,WAAK,UAAU,MAAM,SAAS,OAAO,UAAU;AAC/C,WAAK,UAAU,MAAM,KAAK,QAAQ,WAAW,OAAO;AACpD,YAAM,KAAK,0BAA0B,KAAK,OAAO;AACjD,WAAK,OAAO,MAAM,KAAK,QAAQ,QAAQ;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,MAAc,0BAA0B,SAAwC;AAC9E,UAAM,QAAQ,cAAc,MAAM;AAChC,YAAM,IAAI;AACV,UAAI,OAAO,EAAE,WAAW,WAAmB,GAAE,SAAgB,CAAC,OAAgB;AAC9E,UAAI,OAAO,EAAE,kBAAkB,WAAY,GAAE,gBAAgB,CAAC,KAA8B,KAAa,UAAmB;AAAE,YAAI,GAAG,IAAI;AAAO,eAAO;AAAA,MAAM;AAAA,IAC/J,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,eACJ,OACA,MACA,IACA,IAC8B;AAC9B,UAAM,SAAS,IAAI,gBAAgB,EAAE,GAAG,OAAO,IAAI,GAAG,CAAC;AACvD,QAAI,KAAM,QAAO,IAAI,QAAQ,IAAI;AACjC,UAAM,MAAM,mCAAmC,OAAO,SAAS;AAE/D,QAAI;AACF,YAAM,KAAK,KAAM,KAAK,KAAK,EAAE,WAAW,oBAAoB,SAAS,KAAO,CAAC;AAAA,IAC/E,SAAS,KAAK;AACZ,YAAM,OAAO,MAAM,KAAK,mBAAmB,GAAG;AAC9C,YAAM,IAAI,gBAAgB,qBAAsB,IAAc,OAAO,MAAM,IAAI,EAAE;AAAA,IACnF;AAEA,UAAM,eAAe,MAAM,KAAK,KAAM,QAAQ,aAAa,aAAa,EAAE,MAAM;AAChF,QAAI,eAAe,GAAG;AACpB,UAAI,KAAK,cAAc;AACrB,YAAI;AACF,gBAAM,KAAK,KAAM,gBAAgB,aAAa,WAAW,EAAE,SAAS,KAAO,CAAC;AAC5E,iBAAO,EAAE,QAAQ,KAAK;AAAA,QACxB,QAAQ;AACN,gBAAM,IAAI,aAAa,KAAK,eAAe,CAAC;AAAA,QAC9C;AAAA,MACF;AACA,YAAM,IAAI,aAAa,KAAK,eAAe,CAAC;AAAA,IAC9C;AAEA,UAAM,YAAY,MAAM,KAAK,KAAM,gBAAgB,aAAa,MAAM,EAAE,SAAS,IAAM,CAAC,EAAE,MAAM,MAAM,IAAI;AAC1G,QAAI,UAAW,QAAO,EAAE,QAAQ,KAAK;AAErC,UAAM,eAAe,MAAM,KAAK,KAAM,QAAQ,aAAa,aAAa,EAAE,MAAM;AAChF,QAAI,eAAe,EAAG,OAAM,IAAI,aAAa,KAAK,eAAe,CAAC;AAElE,aAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,YAAM,KAAK,KAAM,SAAS,CAAC,MAAc;AAAE,eAAO,SAAS,GAAG,SAAS,KAAK,eAAe,CAAC;AAAA,MAAE,GAAG,IAAI,CAAC;AACtG,YAAM,KAAK,KAAM,eAAe,GAAG;AACnC,YAAM,QAAQ,MAAM,KAAK,KAAM,QAAQ,aAAa,IAAI,EAAE,MAAM;AAChE,UAAI,QAAQ,EAAG,QAAO,EAAE,QAAQ,KAAK;AAAA,IACvC;AAEA,WAAO,EAAE,QAAQ,MAAM;AAAA,EACzB;AAAA,EAEA,MAAc,mBAAmB,aAAsC;AACrE,QAAI;AACF,YAAM,WAAW,KAAK,KAAM,IAAI;AAChC,YAAM,QAAQ,MAAM,KAAK,KAAM,MAAM,EAAE,MAAM,MAAM,EAAE;AACrD,YAAM,cAAc,MAAM,KAAK,KAAM,SAAS,MAAM;AAClD,cAAM,KAAK,SAAS,MAAM,aAAa,IAAI,QAAQ,QAAQ,GAAG,EAAE,KAAK;AACrE,eAAO,EAAE,MAAM,GAAG,GAAG;AAAA,MACvB,CAAC,EAAE,MAAM,MAAM,EAAE;AACjB,YAAM,UAAU,oBAAoB,KAAK,QAAQ,KAAK,uBAAuB,KAAK,WAAW;AAC7F,YAAM,YAAY,6CAA6C,KAAK,WAAW;AAC/E,YAAM,QAAQ;AAAA,QACZ,UAAU,iBAAiB;AAAA,QAC3B,YAAY,kBAAkB;AAAA,QAC9B,aAAa,cAAc,eAAe;AAAA,MAC5C,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAC1B,aAAO,YAAY,WAAW,YAAY,QAAQ,aAAa,KAAK,cAAc,KAAK,aAAa,WAAW;AAAA,IACjH,SAAS,GAAG;AACV,aAAO,uBAAwB,EAAY,OAAO;AAAA,IACpD;AAAA,EACF;AAAA,EAEQ,iBAAyB;AAC/B,WAAO,KAAK,eACR,8FACA;AAAA,EACN;AAAA,EAEA,MAAM,WAAW,KAA4B;AAC3C,QAAI;AACF,YAAM,KAAK,KAAM,KAAK,KAAK,EAAE,WAAW,oBAAoB,SAAS,KAAO,CAAC;AAAA,IAC/E,SAAS,KAAK;AACZ,YAAM,OAAO,MAAM,KAAK,mBAAmB,GAAG;AAC9C,YAAM,IAAI,gBAAgB,qBAAsB,IAAc,OAAO,MAAM,IAAI,EAAE;AAAA,IACnF;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB,eAAsC;AAC5D,UAAM,MAAM,6BAA6B,aAAa;AACtD,QAAI;AACF,YAAM,KAAK,KAAM,KAAK,KAAK,EAAE,WAAW,eAAe,SAAS,IAAO,CAAC;AAAA,IAC1E,SAAS,KAAK;AACZ,YAAM,OAAO,MAAM,KAAK,mBAAmB,GAAG;AAC9C,YAAM,IAAI,gBAAgB,6BAA8B,IAAc,OAAO,MAAM,IAAI,EAAE;AAAA,IAC3F;AAAA,EACF;AAAA,EAEA,MAAM,SAAY,IAA4C,KAA2B;AACvF,WAAQ,KAAK,KAA+D,SAAS,IAAI,GAAG;AAAA,EAC9F;AAAA,EAEA,UAAgB;AACd,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,SAAS;AAChB,YAAM,IAAI,KAAK;AACf,YAAM,YAAY,KAAK;AACvB,YAAM,SAAS,KAAK;AACpB,WAAK,UAAU;AACf,WAAK,UAAU;AACf,WAAK,OAAO;AACZ,WAAK,kBAAkB;AACvB,WAAK,eAAe;AACpB,UAAI;AACF,cAAM,EAAE,MAAM;AAAA,MAChB,UAAE;AACA,YAAI,UAAU,WAAW;AACvB,gBAAM,OAAO,SAAS,WAAW,SAAS,EAAE;AAAA,YAAM,CAAC,QACjD,QAAQ,KAAK,kCAAkC,GAAG;AAAA,UACpD;AAAA,QACF;AAAA,MACF;AAAA,IACF,WAAW,KAAK,SAAS;AACvB,YAAM,MAAM,KAAK;AACjB,WAAK,UAAU;AACf,WAAK,OAAO;AACZ,YAAM,IAAI,MAAM;AAAA,IAClB;AAAA,EACF;AACF;;;AGpOO,IAAM,YAAmD;AAAA,EAC9D,UAAoB;AAAA,EACpB,YAAoB;AAAA,EACpB,iBAAoB;AAAA,EACpB,OAAoB;AAAA,EACpB,eAAoB;AAAA,EACpB,MAAoB;AAAA,EACpB,WAAoB;AAAA,EACpB,WAAoB;AAAA,EACpB,WAAoB;AAAA,EACpB,gBAAoB;AAAA,EACpB,UAAoB;AAAA,EACpB,eAAoB;AAAA,EACpB,UAAoB;AAAA,EACpB,SAAoB;AAAA,EACpB,WAAoB;AAAA,EACpB,UAAoB;AAAA,EACpB,YAAoB;AAAA,EACpB,eAAoB;AAAA,EACpB,gBAAoB;AAAA,EACpB,WAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,UAAoB;AAAA,EACpB,WAAoB;AAAA,EACpB,iBAAoB;AAAA,EACpB,MAAoB;AAAA,EACpB,YAAoB;AAAA,EACpB,aAAoB;AAAA,EACpB,eAAoB;AAAA,EACpB,WAAoB;AAAA,EACpB,aAAoB;AAAA,EACpB,aAAoB;AAAA,EACpB,WAAoB;AAAA,EACpB,aAAoB;AAAA,EACpB,aAAoB;AAAA,EACpB,cAAoB;AAAA,EACpB,YAAoB;AAAA,EACpB,gBAAoB;AAAA,EACpB,YAAoB;AAAA,EACpB,cAAoB;AAAA,EACpB,gBAAoB;AAAA,EACpB,WAAoB;AAAA,EACpB,cAAoB;AAAA,EACpB,WAAoB;AAAA,EACpB,YAAoB;AAAA,EACpB,kBAAoB;AAAA,EACpB,WAAoB;AAAA,EACpB,aAAoB;AAAA,EACpB,YAAoB;AAAA,EACpB,WAAoB;AAAA,EACpB,UAAoB;AAAA,EACpB,UAAoB;AAAA,EACpB,cAAoB;AAAA,EACpB,cAAoB;AAAA,EACpB,aAAoB;AAAA,EACpB,WAAoB;AAAA,EACpB,SAAoB;AAAA,EACpB,UAAoB;AAAA,EACpB,aAAoB;AAAA,EACpB,YAAoB;AAAA,EACpB,SAAoB;AAAA,EACpB,YAAoB;AAAA,EACpB,UAAoB;AACtB;;;AC9DO,SAAS,WAAW,MAAyC;AAClE,QAAM,UAAU,OAAO,KAAK,OAAO,aAAa,KAAK,MAAM,IAAI,IAAI,EAAE,SAAS,QAAQ;AACtF,SAAO,YAAY,OAAO;AAC5B;AAEO,SAAS,kBAAkB,OAAsC;AACtE,QAAM,MAAM,MAAM,YAAY,EAAE,KAAK;AACrC,SAAQ,UAAU,GAAG,KAAK;AAC5B;;;ACXA,IAAM,oBAAoB;AAE1B,IAAM,uBAAiC;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,cAAwB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,oBAAoB,MAAsB;AACjD,SAAO,KACJ,QAAQ,WAAW,GAAG,EACtB,QAAQ,mBAAmB,OAAO,EAClC,QAAQ,kBAAkB,OAAO,EACjC,QAAQ,wBAAwB,OAAO,EACvC,QAAQ,qBAAqB,OAAO,EACpC,QAAQ,gBAAgB,OAAO,EAC/B,QAAQ,QAAQ,GAAG,EACnB,KAAK;AACV;AAEA,SAAS,iBAAiB,MAAsB;AAC9C,MAAI,QAAQ;AACZ,aAAW,UAAU,aAAa;AAChC,UAAM,QAAQ,OAAO,KAAK,IAAI;AAC9B,WAAO,YAAY;AACnB,QAAI,UAAU,UAAU,MAAM,MAAM,QAAQ,OAAQ,SAAQ,MAAM;AAAA,EACpE;AACA,SAAO,UAAU,KAAK,OAAO,KAAK,MAAM,GAAG,KAAK;AAClD;AAEA,SAAS,iBAAiB,MAAc,aAA8B;AACpE,QAAM,QAAQ,aAAa,KAAK;AAChC,MAAI,CAAC,SAAS,MAAM,SAAS,EAAG,QAAO;AACvC,QAAM,MAAM,KAAK,YAAY,EAAE,QAAQ,MAAM,YAAY,CAAC;AAC1D,SAAO,MAAM,KAAK,KAAK,MAAM,GAAG,GAAG,IAAI;AACzC;AAEA,SAAS,mBAAmB,WAA2B;AACrD,QAAM,YAAY,UAAU,MAAM,yFAAyF;AAC3H,MAAI,WAAW,SAAS,UAAU,QAAQ,GAAI,QAAO,UAAU;AAE/D,QAAM,QAAQ,KAAK,IAAI,GAAG,UAAU,SAAS,GAAG;AAChD,QAAM,OAAO,UAAU,MAAM,KAAK;AAClC,QAAM,iBAAiB,CAAC,GAAG,KAAK,SAAS,kCAAkC,CAAC;AAC5E,aAAW,SAAS,gBAAgB;AAClC,UAAM,YAAY,KAAK,MAAM,MAAM,QAAQ,CAAC,EAAE,KAAK;AACnD,UAAM,OAAO,UAAU,MAAM,GAAG,GAAG;AACnC,UAAM,iBAAiB,2EAA2E,KAAK,SAAS;AAChH,QACE,UAAU,SAAS,MACnB,kBACA,mEAAmE,KAAK,IAAI,GAC5E;AACA,aAAO,QAAQ,MAAM,QAAQ;AAAA,IAC/B;AAAA,EACF;AACA,QAAM,OAAO,eAAe,GAAG,EAAE;AACjC,MAAI,MAAM,UAAU,OAAW,QAAO,QAAQ,KAAK,QAAQ;AAE3D,SAAO,UAAU;AACnB;AAEA,SAAS,oBAAoB,MAAsB;AACjD,QAAM,WAAW,KAAK,MAAM,iBAAiB;AAC7C,MAAI,CAAC,UAAU,MAAO,QAAO;AAE7B,QAAM,YAAY,KAAK,MAAM,GAAG,SAAS,KAAK;AAC9C,SAAO,UAAU,MAAM,GAAG,mBAAmB,SAAS,CAAC;AACzD;AAEA,SAAS,oBAAoB,MAAsB;AACjD,MAAI,KAAK,UAAU,kBAAmB,QAAO;AAC7C,QAAM,QAAQ,KAAK,MAAM,GAAG,iBAAiB;AAC7C,QAAM,eAAe,KAAK,IAAI,MAAM,YAAY,GAAG,GAAG,MAAM,YAAY,GAAG,GAAG,MAAM,YAAY,GAAG,CAAC;AACpG,UAAQ,eAAe,MAAM,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,OAAO,KAAK;AAC9E;AAEO,SAAS,mBACd,QACA,UACA,aACoB;AACpB,MAAI,CAAC,OAAQ,QAAO;AAEpB,MAAI,OAAO,oBAAoB,MAAM;AACrC,QAAM,qBAAqB,WAAW,oBAAoB,QAAQ,IAAI;AACtE,MAAI,sBAAsB,KAAK,YAAY,EAAE,WAAW,mBAAmB,YAAY,CAAC,GAAG;AACzF,WAAO,KAAK,MAAM,mBAAmB,MAAM,EAAE,KAAK;AAAA,EACpD;AAEA,MAAI,yDAAyD,KAAK,IAAI,GAAG;AACvE,WAAO;AAAA,EACT;AAEA,aAAW,WAAW,sBAAsB;AAC1C,WAAO,KAAK,QAAQ,SAAS,GAAG;AAAA,EAClC;AACA,SAAO,KACJ,QAAQ,2CAA2C,GAAG,EACtD,QAAQ,yCAAyC,GAAG;AAEvD,SAAO,oBAAoB,IAAI;AAC/B,SAAO,iBAAiB,IAAI;AAC5B,SAAO,iBAAiB,MAAM,WAAW;AACzC,SAAO,oBAAoB,IAAI;AAC/B,SAAO,oBAAoB,IAAI;AAC/B,SAAO,KAAK,QAAQ,wFAAwF,EAAE,EAAE,KAAK;AACrH,SAAO,oBAAoB,IAAI;AAE/B,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,0DAA0D,KAAK,IAAI,EAAG,QAAO;AAEjF,SAAO;AACT;;;AC7GO,IAAM,eAAN,MAA4C;AAAA,EACjD,YACmB,QACA,UACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA,EAGX,kBAAkB,GAAkC;AAC1D,WAAO,EAAE,YAAY,EAAE,QAAQ,YAAY,EAAE,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAAA,EAC3E;AAAA,EAEA,MAAc,oBAAoB,MAAmC;AACnE,UAAM,OAAO;AACb,UAAM,MAAM,MAAM,KAAK,SAAS,CAAC,cAAc;AAC7C,eAAS,UAAU,IAA4B;AAC7C,YAAI,CAAC,GAAI,QAAO;AAChB,cAAM,QAAkB,CAAC;AACzB,mBAAW,KAAK,GAAG,YAAY;AAC7B,cAAI,EAAE,aAAa,KAAK,WAAW;AACjC,kBAAM,OAAO,EAAE,aAAa,KAAK;AACjC,gBAAI,KAAM,OAAM,KAAK,IAAI;AAAA,UAC3B,WACG,EAAc,YAAY,WAC1B,EAAc,YAAY,UAC3B;AACA;AAAA,UACF,OAAO;AACL,kBAAM,OAAO,UAAU,CAAY;AACnC,gBAAI,KAAM,OAAM,KAAK,IAAI;AAAA,UAC3B;AAAA,QACF;AACA,eAAO,MAAM,KAAK,GAAG,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAAA,MACnD;AACA,aAAO,MAAM,KAAK,SAAS,iBAAiB,UAAU,IAAI,CAAC,EAAE,IAAI,CAAC,UAAU;AAAA,QAC1E,UAAa,KAAK,aAAa,UAAU,SAAS,KAAK,KAAK,aAAa,UAAU,aAAa,KAAK;AAAA,QACrG,QAAa,UAAU,KAAK,cAAc,UAAU,eAAe,CAAC,KAAK;AAAA,QACzE,aAAc,KAAK,cAAc,UAAU,WAAW,GAA0B,WAAW,KAAK,KAAK;AAAA,QACrG,YAAc,KAAK,cAAc,UAAU,UAAU,GAA0B,WAAW,KAAK,KAAK;AAAA,QACpG,YAAc,KAAK,cAAc,UAAU,UAAU,GAA0B,WAAW,KAAK,KAAK;AAAA,MACtG,EAAE;AAAA,IACJ,GAAG,IAAI;AAEP,WAAO,IAAI,QAAQ,CAAC,SAAS;AAC3B,YAAM,UAAU;AAAA,QACd,GAAG;AAAA,QACH,QAAQ,mBAAmB,KAAK,QAAQ,KAAK,UAAU,KAAK,WAAW;AAAA,MACzE;AACA,YAAM,SAAS,iBAAiB,UAAU,OAAO;AACjD,UAAI,CAAC,OAAO,SAAS;AACnB,gBAAQ,KAAK,qCAAqC,KAAK,UAAU,OAAO,MAAM,OAAO,CAAC,GAAG,OAAO;AAChG,eAAO,CAAC;AAAA,MACV;AACA,aAAO,CAAC,OAAO,IAAI;AAAA,IACrB,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,UAAU,MAAY,cAAqC;AACvE,QAAI;AACF,YAAM,cAAc,KAAK;AAAA,QACvB,GAAG,aAAa,IAAI,YAAY,YAAY,OAAO,aAAa,IAAI,gBAAgB,YAAY;AAAA,MAClG,EAAE,MAAM;AACR,YAAM,YAAY,MAAM;AAAA,IAC1B,QAAQ;AAAA,IAAE;AAAA,EACZ;AAAA,EAEQ,UAAU,MAAkB,OAAe,gBAA+B,MAAuB;AACvG,WAAO;AAAA,MACL,YAAiB;AAAA,MACjB,UAAiB,KAAK;AAAA,MACtB,QAAiB,KAAK,UAAU;AAAA,MAChC,cAAiB,KAAK,eAAe;AAAA,MACrC,aAAiB,KAAK,cAAc;AAAA,MACpC,aAAiB,KAAK,cAAc;AAAA,MACpC;AAAA,MACA,iBAAiB,kBAAkB;AAAA,MACnC,eAAiB,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,MAAc,OAAO,MAAY,SAA6C;AAC5E,UAAM,WAAY,oBAAI,IAA2B;AACjD,UAAM,SAAY,oBAAI,IAAY;AAClC,UAAM,WAAY,oBAAI,IAAoB;AAC1C,UAAM,UAAqB,CAAC;AAE5B,UAAM,YAAY,MAChB,KAAK;AAAA,MACH,CAAC,EAAE,KAAK,OAAO,WAAW,WAAW,MACnC,MAAM,KAAK,SAAS,iBAAiB,GAAG,CAAC,EACtC;AAAA,QAAI,QACH,GAAG,aAAa,KAAK,KACrB,GAAG,aAAa,SAAS,KACxB,GAAG,cAAc,UAAU,GAA0B,WAAW,KAAK,KACtE;AAAA,MACF,EACC,OAAO,OAAO;AAAA,MACnB,EAAE,KAAK,aAAa,MAAM,OAAO,aAAa,WAAW,WAAW,aAAa,eAAe,YAAY,aAAa,eAAe;AAAA,IAC1I;AAEF,UAAM,WAAqB,CAAC;AAC5B,UAAM,YAAsB,CAAC;AAE7B,aAAS,QAAQ,GAAG,QAAQ,QAAQ,OAAO,SAAS;AAClD,WAAK,SAAS,QAAQ,QAAQ,CAAC;AAE/B,UAAI,OAAO,QAAQ,QAAQ,aAAc;AAEzC,YAAM,WAAW,MAAM,UAAU;AACjC,UAAI,SAAS,UAAU,QAAQ,aAAc;AAE7C,YAAM,kBAAkB,MAAM,KAAK;AAAA,QACjC,GAAG,aAAa,IAAI,SAAS,aAAa,aAAa;AAAA,MACzD;AACA,UAAI,gBAAgB,WAAW,EAAG;AAElC,iBAAW,QAAQ,iBAAiB;AAClC,YAAI;AACF,gBAAM,KAAK,uBAAuB;AAClC,gBAAM,KAAK,MAAM,EAAE,OAAO,KAAK,CAAC;AAChC,gBAAM,KAAK,eAAe,GAAG;AAAA,QAC/B,QAAQ;AAAA,QAAE;AAAA,MACZ;AACA,YAAM,KAAK,eAAe,IAAI;AAE9B,YAAM,UAAU,MAAM,UAAU;AAChC,YAAM,QAAU,QAAQ,MAAM,SAAS,MAAM;AAE7C,YAAM,UAAU,MAAM,OAAO,OAAK,OAAO,IAAI,CAAC,CAAC,EAAE;AACjD,YAAM,UAAU,MAAM,SAAS,IAAI,UAAU,MAAM,SAAS;AAC5D,eAAS,KAAK,OAAO;AACrB,UAAI,SAAS,SAAS,EAAG,UAAS,MAAM;AACxC,YAAM,iBAAiB,SAAS,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,SAAS;AAEtE,iBAAW,KAAK,SAAS;AACvB,YAAI,CAAC,OAAO,IAAI,CAAC,GAAG;AAAE,iBAAO,IAAI,CAAC;AAAG,oBAAU,KAAK,CAAC;AAAA,QAAE;AACvD,YAAI,CAAC,SAAS,IAAI,CAAC,EAAG,UAAS,IAAI,GAAG,QAAQ,CAAC;AAAA,MACjD;AAEA,UAAI,QAAQ,WAAW,SAAS,OAAQ;AACxC,UAAI,kBAAkB,IAAK;AAAA,IAC7B;AAEA,UAAM,UAAU,IAAI,KAAK,MAAM,KAAK,oBAAoB,IAAI,GAAG,IAAI,OAAK,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;AAExF,eAAW,KAAK,WAAW;AACzB,UAAI,QAAQ,UAAU,QAAQ,aAAc;AAC5C,YAAM,MAAM,KAAK,kBAAkB,CAAC;AACpC,UAAI,SAAS,IAAI,GAAG,EAAG;AACvB,eAAS,IAAI,GAAG;AAChB,YAAM,IAAI,SAAS,IAAI,CAAC,KAAK;AAC7B,YAAM,OAAO,QAAQ,IAAI,CAAC;AAC1B,UAAI,MAAM;AACR,gBAAQ,KAAK,KAAK,UAAU,MAAM,GAAG,MAAM,QAAQ,KAAK,CAAC;AACzD,aAAK,SAAS,WAAW,EAAE,UAAU,KAAK,UAAU,QAAQ,KAAK,UAAU,MAAM,aAAa,KAAK,eAAe,MAAM,YAAY,KAAK,cAAc,MAAM,YAAY,KAAK,cAAc,MAAM,OAAO,GAAG,gBAAgB,MAAM,UAAU,CAAC,EAAE,CAAC;AAAA,MAClP,OAAO;AACL,gBAAQ,KAAK,KAAK,UAAU,EAAE,UAAU,GAAG,QAAQ,QAAW,aAAa,QAAW,YAAY,QAAW,YAAY,OAAU,GAAG,GAAG,MAAM,QAAQ,KAAK,CAAC;AAAA,MAC/J;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,cAAc,MAAoC;AAC9D,UAAM,QAAQ;AACd,WAAO,KAAK,SAAS,CAAC,SAAS;AAC7B,YAAM,UAAqI,CAAC;AAC5I,YAAM,aAAa,MAAM,KAAK,SAAS,iBAAiB,KAAK,SAAS,CAAC;AACvE,iBAAW,aAAa,YAAY;AAClC,cAAM,YAAY,UAAU,cAAc,KAAK,cAAc;AAC7D,cAAM,cAAc,WAAW,aAAa,KAAK,KAAK;AACtD,cAAM,OAAgC,YAAY,YAAY,EAAE,SAAS,OAAO,IAAI,gBAAgB;AACpG,cAAM,QAAQ,MAAM,KAAK,UAAU,iBAAiB,KAAK,IAAI,CAAC;AAC9D,mBAAW,KAAK,OAAO;AACrB,gBAAM,OAAQ,EAAwB;AACtC,cAAI,CAAC,QAAS,CAAC,KAAK,SAAS,SAAS,KAAK,CAAC,KAAK,SAAS,UAAU,EAAI;AACxE,gBAAM,MAAM,EAAE,aAAa,KAAK,KAAK;AACrC,gBAAM,QAAQ,IAAI,QAAQ,SAAS;AACnC,cAAI,UAAU,GAAI;AAClB,gBAAM,QAAQ,IAAI,MAAM,GAAG,KAAK,EAAE,KAAK;AACvC,gBAAM,YAAY,IAAI,MAAM,QAAQ,CAAC,EAAE,QAAQ,YAAY,EAAE;AAC7D,gBAAM,eAAe,UAAU,MAAM,YAAY;AACjD,gBAAM,UAAU,eAAe,aAAa,CAAC,EAAE,KAAK,IAAI;AACxD,cAAI,MAAO,SAAQ,KAAK,EAAE,MAAM,OAAO,SAAS,UAAU,WAAW,UAAU,IAAI,KAAK,KAAK,CAAC;AAAA,QAChG;AAAA,MACF;AACA,aAAO;AAAA,IACT,GAAG,KAAK;AAAA,EACV;AAAA,EAEA,MAAc,cAAc,MAAoC;AAC9D,UAAM,QAAQ;AACd,WAAO,KAAK,SAAS,CAAC,SAAS;AAC7B,YAAM,UAAiE,CAAC;AACxE,YAAM,WAAW,MAAM,KAAK,SAAS,iBAAiB,KAAK,OAAO,CAAC;AACnE,YAAM,eAAe,SAAS,KAAK,CAAC,MAAM,EAAE,aAAa,SAAS,aAAa,CAAC;AAChF,UAAI,CAAC,aAAc,QAAO;AAC1B,YAAM,QAAQ,MAAM,KAAK,aAAa,iBAAiB,KAAK,IAAI,CAAC;AACjE,iBAAW,KAAK,OAAO;AACrB,cAAM,OAAQ,EAAwB;AACtC,YAAI,CAAC,KAAM;AACX,cAAM,UAAU,EAAE,cAAc,KAAK,KAAK;AAC1C,cAAM,WAAW,EAAE,cAAc,KAAK,MAAM;AAC5C,cAAM,QAAQ,SAAS,aAAa,KAAK,KAAK;AAC9C,cAAM,SAAS,UAAU,aAAa,KAAK,KAAK;AAChD,YAAI,MAAO,SAAQ,KAAK,EAAE,OAAO,QAAQ,KAAK,KAAK,CAAC;AAAA,MACtD;AACA,aAAO;AAAA,IACT,GAAG,KAAK;AAAA,EACV;AAAA,EAEA,MAAc,mBAAmB,MAAY,UAA0C;AACrF,QAAI;AACF,YAAM,KAAK,KAAK,UAAU,EAAE,WAAW,mBAAmB,CAAC;AAC3D,YAAM,KAAK,eAAe,IAAI;AAAA,IAChC,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,SAAS;AAAA,MACb,MAAW,oBAAoB;AAAA,MAC/B,WAAW,CAAC,GAAG,oBAAoB,SAAS;AAAA,IAC9C;AAEA,UAAM,MAAM,MAAM,KAAK,SAAS,CAAC,SAAS;AACxC,YAAM,OAAO,oBAAI,IAAY;AAC7B,YAAM,UAAsG,CAAC;AAC7G,YAAM,QAAQ,MAAM,KAAK,SAAS,iBAAiB,KAAK,IAAI,CAAC;AAE7D,YAAM,aAAa,CAAC,eAAe,YAAY,cAAc,iBAAiB,gBAAgB,UAAU;AAExG,YAAM,SAAS,oBAAI,IAAsB;AACzC,iBAAW,KAAK,OAAO;AACrB,cAAM,OAAQ,EAAwB;AACtC,YAAI,CAAC,KAAM;AACX,YAAI,CAAC,WAAW,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,EAAG;AAC/C,cAAM,OAAO,EAAE,aAAa,KAAK,KAAK;AACtC,YAAI,CAAC,OAAO,IAAI,IAAI,EAAG,QAAO,IAAI,MAAM,CAAC,CAAC;AAC1C,eAAO,IAAI,IAAI,EAAG,KAAK,IAAI;AAAA,MAC7B;AAEA,iBAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,GAAG;AAC5C,YAAI,KAAK,IAAI,IAAI,EAAG;AACpB,aAAK,IAAI,IAAI;AAEb,cAAM,WAAW,MAAM,KAAK,CAAC,MAAM,YAAY,KAAK,CAAC,CAAC,KAAK;AAC3D,cAAM,YAAY,MAAM,KAAK,CAAC,MAAM,CAAC,YAAY,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK;AAC7E,YAAI,CAAC,UAAW;AAEhB,YAAI,QAAQ;AACZ,YAAI,WAAW;AACf,YAAI,UAAU;AAEd,mBAAW,KAAK,KAAK,WAAW;AAC9B,cAAI,UAAU;AACd,cAAI,SAAS;AACb,iBAAO,MAAM;AACX,kBAAM,QAAQ,UAAU,QAAQ,GAAG,MAAM;AACzC,gBAAI,UAAU,GAAI;AAClB,sBAAU;AACV,qBAAS,QAAQ;AAAA,UACnB;AACA,cAAI,YAAY,GAAI;AACpB,gBAAM,QAAQ,UAAU,MAAM,UAAU,EAAE,MAAM;AAChD,gBAAM,cAAc,SAAS,KAAK,KAAK,KAAK,MAAM,KAAK,MAAM;AAC7D,cAAI,CAAC,YAAa;AAClB,kBAAQ,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK;AACzC,qBAAW;AACX,gBAAM,WAAW,MAAM,QAAQ,WAAW,EAAE;AAC5C,gBAAM,SAAS,SAAS,QAAQ,MAAG;AACnC,qBAAW,WAAW,KAAK,WAAW,SAAS,MAAM,GAAG,MAAM,GAAG,KAAK;AACtE;AAAA,QACF;AAEA,YAAI,MAAO,SAAQ,KAAK,EAAE,OAAO,SAAS,UAAU,UAAU,KAAK,KAAK,CAAC;AAAA,MAC3E;AAEA,aAAO;AAAA,IACT,GAAG,MAAM;AAET,WAAO,IAAI,IAAI,CAAC,OAAO,EAAE,MAAM,eAAwB,GAAG,EAAE,EAAE;AAAA,EAChE;AAAA,EAEA,MAAc,wBAAwB,MAA6C;AACjF,UAAM,OAAO;AACb,WAAO,KAAK,SAAS,CAAC,MAAM;AAC1B,YAAM,UAAU,MAAM,KAAK,SAAS,iBAAiB,EAAE,UAAU,CAAC,EAC/D,KAAK,CAAC,OAAO,GAAG,aAAa,SAAS,EAAE,kBAAkB,CAAC,KACzD,SAAS,cAAc,uBAAuB;AAEnD,UAAI,CAAC,QAAS,QAAO,CAAC;AAEtB,aAAO,MAAM,KAAK,QAAQ,iBAAiB,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS;AAChE,cAAM,OAAO,KAAK,cAAc,EAAE,QAAQ;AAC1C,cAAM,MAAM,MAAM,QAAQ;AAE1B,cAAM,UAAU,KAAK,cAAc,EAAE,OAAO,GAAG,aAAa,KAAK;AACjE,cAAM,WAAW,KAAK,cAAc,EAAE,QAAQ,GAAG,aAAa,KAAK;AACnE,cAAM,QAAQ,WAAW,YAAY;AAErC,cAAM,aAAa,KAAK,cAAc,EAAE,MAAM,GAAG,aAAa,KAAK,KAAK;AACxE,cAAM,aAAa,KAAK,cAAc,EAAE,aAAa;AACrD,cAAM,eAAe,YAAY,aAAa,KAAK,KAAK;AAExD,cAAM,YAAY,KAAK,cAAc,EAAE,SAAS,GAAG,aAAa,KAAK,KAAK;AAC1E,cAAM,SAAY,KAAK,cAAc,EAAE,MAAM,GAAG,aAAa,KAAK,KAAK;AACvE,cAAM,aAAa,KAAK,cAAc,EAAE,UAAU,GAAG,aAAa,KAAK,KAAK;AAE5E,cAAM,iBAAiB,KAAK,cAAc,EAAE,mBAAmB;AAC/D,YAAI,iBAAgC;AACpC,YAAI,gBAAgB;AAClB,cAAI,OAAO,eAAe;AAC1B,iBAAO,MAAM;AACX,kBAAM,IAAI,KAAK,aAAa,KAAK;AACjC,gBAAI,GAAG;AAAE,+BAAiB;AAAG;AAAA,YAAM;AACnC,mBAAO,KAAK;AAAA,UACd;AAAA,QACF;AAEA,cAAM,WAAW,MAAM,KAAK,KAAK,iBAAiB,MAAM,CAAC;AACzD,cAAM,WAAW,SAAS,KAAK,CAACA,OAAM,YAAY,KAAKA,GAAE,aAAa,KAAK,KAAK,EAAE,CAAC,GAAG,aAAa,KAAK,KAAK;AAC7G,cAAM,kBAAkB,SACrB,IAAI,CAACA,OAAMA,GAAE,aAAa,KAAK,KAAK,EAAE,EACtC;AAAA,UAAO,CAAC,MACP,KAAK,KAAK,CAAC,MACT,EAAE,SAAS,SAAS,KAAK,EAAE,SAAS,UAAU,KAC9C,EAAE,SAAS,MAAM,KAAK,EAAE,SAAS,MAAM,KAAK,EAAE,SAAS,OAAO;AAAA,QAElE;AACF,cAAM,aAAa,gBAAgB,CAAC,KAAK;AAEzC,cAAM,iBAAiB,SACpB,IAAI,CAACA,OAAMA,GAAE,aAAa,KAAK,KAAK,EAAE,EACtC,OAAO,CAAC,MAAM,uFAAuF,KAAK,CAAC,CAAC;AAC/G,cAAM,OAAO,WAAW,eAAe,CAAC,KAAK;AAE7C,cAAM,WAAW,iBAAiB,YAAY,YAAY;AAC1D,cAAM,SAAS,aAAa;AAE5B,YAAI,OAAwF;AAC5F,cAAM,KAAK,SAAS,YAAY;AAChC,cAAM,MAAM,OAAO,YAAY;AAC/B,cAAM,SAAS,WAAW,YAAY;AACtC,YAAI,GAAG,SAAS,QAAQ,KAAK,IAAI,WAAW,IAAI,EAAG,QAAO;AAAA,iBACjD,GAAG,SAAS,UAAU,KAAK,OAAO,SAAS,UAAU,EAAG,QAAO;AAAA,iBAC/D,GAAG,SAAS,WAAW,KAAK,OAAO,SAAS,WAAW,EAAG,QAAO;AAAA,iBACjE,GAAG,SAAS,QAAQ,KAAK,OAAO,SAAS,QAAQ,EAAG,QAAO;AAAA,iBAC3D,GAAG,SAAS,SAAS,KAAK,CAAC,CAAC,UAAW,QAAO;AAAA,YAClD,QAAO;AAEZ,eAAO,EAAE,MAAM,OAAO,KAAK,QAAQ,UAAU,gBAAgB,YAAY,MAAM,UAAU,WAAW;AAAA,MACtG,CAAC;AAAA,IACH,GAAG,IAAI;AAAA,EACT;AAAA,EAEA,MAAc,sBAAsB,MAAsC;AACxE,UAAM,OAAO;AACb,WAAO,KAAK,SAAS,CAAC,MAAM;AAC1B,YAAM,MAA2M,CAAC;AAClN,UAAI,MAAM;AACV,eAAS,iBAAiB,EAAE,MAAM,EAAE,QAAQ,UAAQ;AAClD,cAAM,UAAU,KAAK,cAAc,EAAE,KAAK;AAC1C,YAAI,CAAC,QAAS;AACd,cAAM,QAAQ,QAAQ,aAAa,KAAK,KAAK;AAC7C,cAAM,SAAS,QAAQ,QAAQ,GAAG;AAClC,cAAM,MAAM,QAAQ,QAAQ;AAC5B,YAAI,CAAC,SAAS,CAAC,IAAK;AACpB;AACA,cAAM,OAAW,KAAK,cAAc,EAAE,IAAI,GAAG,aAAa,KAAK,KAAK;AACpE,cAAM,UAAW,KAAK,cAAc,EAAE,OAAO,GAAG,aAAa,KAAK,KAAK;AACvE,cAAM,gBAAgB,CAAC,CAAC,KAAK,cAAc,EAAE,UAAU;AACvD,cAAM,WAAW,KAAK,cAAc,EAAE,UAAU;AAChD,cAAM,eAAe,WACjB,EAAE,OAAO,SAAS,cAAc,EAAE,WAAW,GAAG,aAAa,KAAK,KAAK,IAAI,OAAO,SAAS,cAAc,EAAE,WAAW,GAAG,aAAa,KAAK,KAAK,GAAG,IACnJ;AACJ,YAAI,SAAS;AACb,YAAI;AAAE,mBAAS,IAAI,IAAI,GAAG,EAAE,SAAS,QAAQ,UAAU,EAAE;AAAA,QAAE,QAAQ;AAAE,mBAAS,KAAK,cAAc,EAAE,QAAQ,GAAG,aAAa,KAAK,KAAK;AAAA,QAAG;AACxI,YAAI,KAAK,EAAE,UAAU,KAAK,OAAO,KAAK,QAAQ,MAAM,SAAS,eAAe,aAAa,CAAC;AAAA,MAC5F,CAAC;AACD,aAAO;AAAA,IACT,GAAG,IAAI;AAAA,EACT;AAAA,EAEA,MAAc,iBAAiB,MAA0C;AACvE,UAAM,OAAO;AACb,WAAO,KAAK,SAAS,CAAC,MAAM;AAC1B,YAAM,MAAqM,CAAC;AAC5M,UAAI,YAA4B;AAChC,eAAS,iBAAiB,kBAAkB,EAAE,QAAQ,OAAK;AACzD,YAAI,CAAC,aAAa,EAAE,aAAa,SAAS,EAAE,WAAW,EAAG,aAAY,EAAE,QAAQ,cAAc;AAAA,MAChG,CAAC;AACD,UAAI,CAAC,UAAW,QAAO;AACtB,MAAC,UAAsB,iBAAiB,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,MAAM;AACpE,cAAM,OAAO,KAAK,cAAc,EAAE,IAAI,GAAG,aAAa,KAAK,KAAK;AAChE,YAAI,CAAC,KAAM;AACX,cAAM,SAAa,KAAK,cAAc,EAAE,WAAW,GAAG,aAAa,KAAK,KAAK;AAC7E,cAAM,YAAa,KAAK,cAAc,EAAE,WAAW,GAAG,aAAa,KAAK,KAAK;AAC7E,cAAM,cAAc,YAAY,UAAU,QAAQ,SAAS,EAAE,EAAE,KAAK,IAAI;AACxE,YAAI,MAAO,KAAK,cAAc,aAAa,GAAgC,aAAa,UAAU,KAAK;AACvG,YAAI,CAAC,KAAK;AACR,qBAAW,QAAQ,MAAM,KAAK,KAAK,iBAAiB,SAAS,CAAC,GAA0B;AACtF,kBAAM,KAAK,KAAK,KAAK,MAAM,eAAe;AAC1C,gBAAI,IAAI;AAAE,oBAAM,GAAG,CAAC;AAAG;AAAA,YAAM;AAC7B,kBAAM,KAAK,KAAK,KAAK,MAAM,+BAA+B;AAC1D,gBAAI,IAAI;AAAE,kBAAI;AAAE,sBAAM,OAAO,OAAO,GAAG,CAAC,CAAC,EAAE,SAAS;AAAA,cAAE,QAAQ;AAAA,cAAE;AAAE,kBAAI,IAAK;AAAA,YAAM;AAAA,UACnF;AAAA,QACF;AACA,cAAM,WAAqB,CAAC;AAC5B,aAAK,iBAAiB,WAAW,EAAE,QAAQ,QAAM;AAC/C,gBAAM,OAAO,MAAM,KAAK,GAAG,UAAU,EAClC,OAAO,OAAK,EAAE,aAAa,CAAC,EAC5B,IAAI,OAAK,EAAE,aAAa,KAAK,KAAK,EAAE,EACpC,OAAO,OAAK,EAAE,SAAS,KAAK,EAAE,SAAS,GAAG,EAC1C,KAAK,GAAG;AACX,cAAI,QAAQ,CAAC,SAAS,SAAS,IAAI,EAAG,UAAS,KAAK,IAAI;AAAA,QAC1D,CAAC;AACD,cAAM,QAAQ,MAAM,KAAK,KAAK,iBAAiB,SAAS,CAAC;AACzD,cAAM,gBAAgB,MAAM,KAAK,OAAK,EAAE,KAAK,SAAS,iBAAiB,CAAC,GAAG,QAAQ;AACnF,cAAM,aAAgB,MAAM,KAAK,OAAK,CAAC,EAAE,KAAK,SAAS,YAAY,KAAK,EAAE,KAAK,WAAW,MAAM,CAAC,GAAG,QAAQ;AAC5G,YAAI,KAAK,EAAE,UAAU,IAAI,GAAG,MAAM,KAAK,QAAQ,aAAa,UAAU,YAAY,cAAc,CAAC;AAAA,MACnG,CAAC;AACD,aAAO;AAAA,IACT,GAAG,IAAI;AAAA,EACT;AAAA,EAEA,MAAc,iBAAiB,MAAgC;AAC7D,WAAO,KAAK,SAAS,MAAM;AACzB,YAAM,QAAQ,oBAAI,IAAY;AAC9B,YAAM,OAAQ,oBAAI,IAAY;AAC9B,YAAM,QAAQ,oBAAI,IAAY;AAC9B,YAAM,YAAY,oBAAI,IAA4F;AAElH,eAAS,gBAAgB,IAAqB;AAC5C,cAAM,MAAM,CAAC,WAAW,WAAW,WAAW,oBAAoB,IAAI;AACtE,mBAAW,KAAK,KAAK;AACnB,gBAAM,QAAQ,GAAG,cAAc,CAAC;AAChC,cAAI,OAAO,aAAa,KAAK,EAAG,QAAO,MAAM,YAAY,KAAK;AAAA,QAChE;AACA,eAAO;AAAA,MACT;AAEA,eAAS,iBAAiB,gBAAgB,EAAE,QAAQ,aAAW;AAC7D,cAAM,MAAM,QAAQ,aAAa,IAAI;AACrC,YAAI,CAAC,IAAK;AACV,cAAM,OAAO,IAAI,QAAQ,OAAO,EAAE;AAClC,cAAM,IAAI,IAAI;AACd,cAAM,OAAO,gBAAgB,OAAO;AACpC,cAAM,QAAQ,QAAQ,cAAc,aAAa;AACjD,cAAM,MAAM,OAAO,aAAa,UAAU,KAAK;AAC/C,YAAI,IAAK,MAAK,IAAI,GAAG;AACrB,YAAI,KAAM,WAAU,IAAI,MAAM,EAAE,MAAM,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,MAC/D,CAAC;AAED,eAAS,iBAAiB,YAAY,EAAE,QAAQ,QAAM;AACpD,cAAM,MAAM,GAAG,aAAa,UAAU;AACtC,YAAI,CAAC,KAAK,WAAW,KAAK,EAAG;AAC7B,cAAM,IAAI,GAAG;AACb,YAAI,CAAC,UAAU,IAAI,GAAG,GAAG;AACvB,gBAAM,OAAO,gBAAgB,EAAE;AAC/B,cAAI,KAAM,WAAU,IAAI,KAAK,EAAE,MAAM,MAAM,KAAK,KAAK,MAAM,MAAM,KAAK,CAAC;AAAA,QACzE;AAAA,MACF,CAAC;AAED,eAAS,iBAAiB,SAAS,EAAE,QAAQ,UAAQ;AACnD,cAAM,QAAQ,KAAK,cAAc,aAAa;AAC9C,cAAM,MAAM,OAAO,aAAa,UAAU,KAAK;AAC/C,YAAI,CAAC,IAAK;AACV,aAAK,IAAI,GAAG;AACZ,cAAM,OAAO,KAAK,cAAc,SAAS,GAAG,aAAa,KAAK,KAAK;AACnE,YAAI,CAAC,KAAM;AACX,cAAM,SAAS,KAAK,cAAc,gBAAgB;AAClD,cAAM,OAAO,SAAS,OAAO,aAAa,IAAI,EAAG,QAAQ,OAAO,EAAE,IAAI;AACtE,cAAM,MAAM,QAAQ,OAAO,GAAG;AAC9B,YAAI,UAAU,IAAI,GAAG,GAAG;AACtB,gBAAM,WAAW,UAAU,IAAI,GAAG;AAClC,cAAI,CAAC,SAAS,IAAK,WAAU,IAAI,KAAK,EAAE,GAAG,UAAU,IAAI,CAAC;AAAA,QAC5D,OAAO;AACL,oBAAU,IAAI,KAAK,EAAE,MAAM,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,QACpD;AAAA,MACF,CAAC;AAED,eAAS,iBAAiB,aAAa,EAAE,QAAQ,QAAM;AACrD,cAAM,MAAM,GAAG,aAAa,UAAU;AACtC,YAAI,CAAC,IAAK;AACV,aAAK,IAAI,GAAG;AACZ,cAAM,eAAe,CAAC,GAAG,UAAU,OAAO,CAAC,EAAE,KAAK,OAAK,EAAE,QAAQ,GAAG;AACpE,YAAI,CAAC,cAAc;AACjB,cAAI,OAAuB,GAAG;AAC9B,cAAI,OAAO;AACX,mBAAS,IAAI,GAAG,IAAI,KAAK,MAAM,KAAK;AAClC,kBAAM,IAAI,KAAK,cAAc,wCAAwC;AACrE,gBAAI,GAAG,aAAa,KAAK,GAAG;AAAE,qBAAO,EAAE,YAAY,KAAK;AAAG;AAAA,YAAM;AACjE,mBAAO,KAAK;AAAA,UACd;AACA,cAAI,KAAM,WAAU,IAAI,OAAO,GAAG,IAAI,EAAE,MAAM,MAAM,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,QAC7E;AAAA,MACF,CAAC;AAED,YAAM,gBAAgB,MAAM,KAAK,SAAS,iBAAiB,mBAAmB,CAAC,EAC5E,IAAI,OAAK,EAAE,eAAe,EAAE,EAC5B,OAAO,OAAK,EAAE,SAAS,GAAM,EAC7B,KAAK,IAAI;AAEZ,iBAAW,KAAK,cAAc,SAAS,2BAA2B,EAAG,OAAM,IAAI,EAAE,CAAC,CAAC;AACnF,iBAAW,KAAK,cAAc,SAAS,qBAAqB,EAAU,OAAM,IAAI,EAAE,CAAC,CAAC;AACpF,iBAAW,KAAK,cAAc,SAAS,6BAA6B,GAAG;AACrE,YAAI;AAAE,eAAK,IAAI,OAAO,OAAO,EAAE,CAAC,CAAC,EAAE,SAAS,CAAC;AAAA,QAAE,QAAQ;AAAA,QAAE;AAAA,MAC3D;AAEA,aAAO,EAAE,UAAU,CAAC,GAAG,UAAU,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,KAAK,GAAG,MAAM,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,GAAG,KAAK,EAAE;AAAA,IACpG,CAAC;AAAA,EACH;AAAA,EAEQ,2BAA2B,WAAsB,WAA2C;AAClG,UAAM,SAAS,IAAI,IAAY,UAAU,IAAI;AAC7C,UAAM,UAAU,UAAU,SAAS,IAAI,QAAM,EAAE,GAAG,EAAE,EAAE;AAEtD,eAAW,OAAO,WAAW;AAC3B,UAAI,CAAC,IAAI,IAAK;AACd,aAAO,IAAI,IAAI,GAAG;AAClB,YAAM,WAAW,IAAI,KAAK,YAAY,EAAE,KAAK;AAC7C,YAAM,SAAS,QAAQ,KAAK,OAAK,EAAE,KAAK,YAAY,EAAE,KAAK,MAAM,QAAQ;AACzE,UAAI,QAAQ;AACV,YAAI,CAAC,OAAO,IAAK,QAAO,MAAM,IAAI;AAAA,MACpC,WAAW,CAAC,QAAQ,KAAK,OAAK,EAAE,QAAQ,IAAI,GAAG,GAAG;AAChD,gBAAQ,KAAK,EAAE,MAAM,IAAI,MAAM,MAAM,MAAM,KAAK,IAAI,KAAK,MAAM,KAAK,CAAC;AAAA,MACvE;AAAA,IACF;AAEA,WAAO,EAAE,GAAG,WAAW,UAAU,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE;AAAA,EAC9D;AAAA,EAEA,MAAc,kBAAkB,MAI7B;AACD,UAAM,UAAU;AAChB,UAAM,UAAU;AAEhB,WAAO,KAAK,SAAS,CAAC,EAAE,KAAK,IAAI,MAAM;AACrC,YAAM,KAAc,OAAmD,QAAQ,MAAM;AACrF,YAAM,UACJ,OAAO,QAAQ,QAAQ,OAAO,QAAQ,QAAQ;AAEhD,eAAS,cAA8B;AACrC,cAAM,UAAU,SAAS,cAAc,IAAI,IAAI;AAC/C,YAAI,QAAS,QAAO;AACpB,cAAM,WAAW,SAAS,iBAAiB,8BAA8B;AACzE,mBAAW,KAAK,UAAU;AACxB,cAAI,EAAE,aAAa,KAAK,MAAM,eAAe;AAC3C,gBAAI,KAAqB,EAAE;AAC3B,qBAAS,IAAI,GAAG,IAAI,KAAK,IAAI,KAAK;AAChC,kBAAI,GAAG,iBAAiB,GAAG,EAAE,SAAS,EAAG,QAAO;AAChD,mBAAK,GAAG;AAAA,YACV;AACA,mBAAO,EAAE;AAAA,UACX;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAEA,YAAM,UAAU,YAAY;AAC5B,YAAM,eAAe,UAAW,QAAQ,QAAQ,IAAI,OAAO,KAAK,UAAW;AAE3E,UAAI,UAAyB;AAC7B,UAAI,cAAc;AAChB,cAAM,QAAQ,aAAa,UAAU,IAAI;AACzC,cAAM,iBAAiB,uBAAuB,EAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;AAC3E,cAAM,iBAAiB,8BAA8B,EAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;AAClF,cAAM,iBAAiB,wBAAwB,EAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;AAC5E,cAAM,iBAAiB,GAAG,EAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;AACvD,cAAM,YAAY,MAAM,aAAa,QAAQ,QAAQ,GAAG,EAAE,KAAK,KAAK;AACpE,cAAM,eAAe,CAAC,aACpB,0CAA0C,KAAK,SAAS;AAC1D,kBAAU,eAAe,OAAO;AAAA,MAClC;AAEA,YAAM,cAAc,CAAC,CAAC,WAAW,YAAY;AAE7C,YAAM,eAAe,MAAM,KAAK,cAAc,iBAAiB,SAAS,KAAK,CAAC,CAAC,EAC5E,OAAO,CAAC,MAAO,EAAwB,QAAQ,CAAE,EAAwB,KAAK,WAAW,YAAY,CAAC,EACtG,IAAI,CAAC,OAAO;AAAA,QACX,MAAO,EAAwB,aAAa,KAAK,KAAK;AAAA,QACtD,MAAO,EAAwB;AAAA,MACjC,EAAE,EACD,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI;AAEjC,YAAM,UAAU,SAAS,cAAc,IAAI,IAAI;AAC/C,YAAM,cAAc,YAAY,SAAS,CAAC,CAAC;AAC3C,YAAM,eAAe,SAAS,QAAQ,IAAI,OAAO,KAAK;AAEtD,UAAI,UAAyB;AAC7B,UAAI,cAAc;AAChB,cAAM,QAAQ,aAAa,UAAU,IAAI;AACzC,cAAM,iBAAiB,uBAAuB,EAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;AAC3E,cAAM,iBAAiB,8BAA8B,EAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;AAClF,cAAM,iBAAiB,wBAAwB,EAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;AAC5E,cAAM,iBAAiB,GAAG,EAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;AACvD,cAAM,YAAY,MAAM,aAAa,QAAQ,QAAQ,GAAG,EAAE,KAAK,KAAK;AACpE,cAAM,eAAe,CAAC,aACpB,0CAA0C,KAAK,SAAS;AAC1D,kBAAU,eAAe,OAAO;AAAA,MAClC;AAEA,YAAM,eAAe,cACjB,MAAM,KAAK,cAAc,iBAAiB,SAAS,KAAK,CAAC,CAAC,EACvD,OAAO,CAAC,MAAO,EAAwB,QAAQ,CAAE,EAAwB,KAAK,WAAW,YAAY,CAAC,EACtG,IAAI,CAAC,OAAO;AAAA,QACX,MAAO,EAAwB,aAAa,KAAK,KAAK;AAAA,QACtD,MAAO,EAAwB;AAAA,MACjC,EAAE,EACD,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,IACjC,CAAC;AAEL,aAAO;AAAA,QACL;AAAA,QACA,YAAY,EAAE,UAAU,aAAa,MAAM,SAAS,WAAW,aAAa;AAAA,QAC5E,QAAY,EAAE,UAAU,aAAa,MAAM,SAAU,WAAW,aAAa;AAAA,MAC/E;AAAA,IACF,GAAG,EAAE,KAAK,SAAS,KAAK,QAAQ,CAAC;AAAA,EACnC;AAAA,EAEQ,UAAU,MAAiB,OAA0B;AAC3D,UAAM,QAAmB,CAAC;AAC1B,UAAM,UAAU,oBAAI,IAAqB;AAEzC,eAAW,OAAO,MAAM;AACtB,YAAM,OAAgB;AAAA,QACpB,UAAgB,IAAI;AAAA,QACpB,QAAgB,IAAI,UAAU;AAAA,QAC9B,aAAgB,IAAI,gBAAgB;AAAA,QACpC,YAAgB,IAAI,eAAe;AAAA,QACnC,YAAgB,IAAI,eAAe;AAAA,QACnC,OAAgB,IAAI;AAAA,QACpB,gBAAgB,IAAI,mBAAmB;AAAA,QACvC,UAAgB,CAAC;AAAA,MACnB;AACA,cAAQ,IAAI,IAAI,UAAU,IAAI;AAAA,IAChC;AAEA,eAAW,QAAQ,QAAQ,OAAO,GAAG;AACnC,UAAI,KAAK,kBAAkB,QAAQ,IAAI,KAAK,cAAc,GAAG;AAC3D,gBAAQ,IAAI,KAAK,cAAc,EAAG,SAAS,KAAK,IAAI;AAAA,MACtD,OAAO;AACL,cAAM,KAAK,IAAI;AAAA,MACjB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQ,SAAiD;AAC7D,UAAM,UAAU,KAAK,IAAI;AACzB,UAAM,SAAuB;AAAA,MAC3B,UAAe,QAAQ;AAAA,MACvB,YAAe,QAAQ;AAAA,MACvB,OAAe,QAAQ;AAAA,MACvB,cAAe,QAAQ;AAAA,MACvB,eAAe,QAAQ;AAAA,MACvB,UAAe,EAAE,OAAO,MAAM,QAAQ,IAAI;AAAA,MAC1C,QAAe,GAAG,QAAQ,EAAE,IAAI,QAAQ,GAAG,YAAY,CAAC;AAAA,IAC1D;AAEA,QAAI,aAAa;AAEjB,QAAI;AACF,YAAM,KAAK,OAAO,OAAO,MAAM;AAC/B,YAAM,OAAO,QAAQ,WAAW,WAAW,kBAAkB,QAAQ,QAAQ,CAAC,IAAI;AAClF,YAAM,EAAE,OAAO,IAAI,MAAM,KAAK,OAAO,eAAe,QAAQ,OAAO,MAAM,QAAQ,IAAI,QAAQ,EAAE;AAE/F,YAAM,OAAO,KAAK,OAAO,QAAQ;AAEjC,UAAI,QAAQ,UAAU;AACpB,cAAM,CAACC,iBAAgBC,YAAWC,aAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,UAClE,KAAK,sBAAsB,IAAI;AAAA,UAC/B,KAAK,iBAAiB,IAAI;AAAA,UAC1B,KAAK,iBAAiB,IAAI;AAAA,QAC5B,CAAC;AACD,cAAMC,aAAY,KAAK,2BAA2BD,eAAcD,UAAS;AACzE,YAAIG,cAAaJ;AACjB,aAAK,QAAQ,SAAS,MAAM,GAAG;AAC7B,gBAAM,WAAW,IAAI,gBAAgB,EAAE,GAAG,QAAQ,OAAO,IAAI,QAAQ,IAAI,IAAI,QAAQ,IAAI,OAAO,KAAK,CAAC;AACtG,cAAI,KAAM,UAAS,IAAI,QAAQ,IAAI;AACnC,gBAAM,KAAK,OAAO,WAAW,mCAAmC,SAAS,SAAS,CAAC;AACnF,gBAAM,YAAY,MAAM,KAAK,sBAAsB,IAAI;AACvD,UAAAI,cAAa,CAAC,GAAGJ,iBAAgB,GAAG,UAAU,IAAI,QAAM,EAAE,GAAG,GAAG,UAAU,EAAE,WAAW,GAAG,EAAE,CAAC;AAAA,QAC/F;AACA,cAAMK,SAAsB;AAAA,UAC1B,MAAM,QAAQ;AAAA,UAAO,gBAAgB;AAAA,UAAG,iBAAiB;AAAA,UACzD,YAAY,KAAK,IAAI,IAAI;AAAA,UAAS;AAAA,QACpC;AACA,aAAK,SAAS,WAAWA,MAAK;AAC9B,eAAO;AAAA,UACL,MAAM,QAAQ;AAAA,UAAO,UAAU,QAAQ,YAAY;AAAA,UACnD,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,UAAG,gBAAgB;AAAA,UACvD,SAAS;AAAA,UACT,YAAY,EAAE,UAAU,OAAO,MAAM,MAAM,WAAW,CAAC,EAAE;AAAA,UACzD,QAAY,EAAE,UAAU,OAAO,MAAM,MAAM,WAAW,CAAC,EAAE;AAAA,UACzD,kBAAkB,CAAC;AAAA,UAAG,MAAM,CAAC;AAAA,UAAG,MAAM,CAAC;AAAA,UAAG,QAAQ,CAAC;AAAA,UAAG,QAAQ,CAAC;AAAA,UAC/D,gBAAgBD;AAAA,UAAY,WAAAH;AAAA,UAAW,WAAAE;AAAA,UAAW,OAAAE;AAAA,QACpD;AAAA,MACF;AAEA,YAAM,CAAC,QAAQ,QAAQ,kBAAkB,cAAc,gBAAgB,SAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,QACpG,KAAK,cAAc,IAAI;AAAA,QACvB,KAAK,cAAc,IAAI;AAAA,QACvB,KAAK,wBAAwB,IAAI;AAAA,QACjC,KAAK,iBAAiB,IAAI;AAAA,QAC1B,KAAK,sBAAsB,IAAI;AAAA,QAC/B,KAAK,iBAAiB,IAAI;AAAA,MAC5B,CAAC;AACD,YAAM,YAAY,KAAK,2BAA2B,cAAc,SAAS;AACzE,WAAK,SAAS,SAAS,MAAM;AAC7B,WAAK,SAAS,SAAS,MAAM;AAE7B,UAAI,CAAC,QAAQ;AACX,YAAI,eAAe;AACnB,aAAK,QAAQ,SAAS,MAAM,GAAG;AAC7B,gBAAM,WAAW,IAAI,gBAAgB,EAAE,GAAG,QAAQ,OAAO,IAAI,QAAQ,IAAI,IAAI,QAAQ,IAAI,OAAO,KAAK,CAAC;AACtG,cAAI,KAAM,UAAS,IAAI,QAAQ,IAAI;AACnC,gBAAM,KAAK,OAAO,WAAW,mCAAmC,SAAS,SAAS,CAAC;AACnF,gBAAM,YAAY,MAAM,KAAK,sBAAsB,IAAI;AACvD,yBAAe,CAAC,GAAG,gBAAgB,GAAG,UAAU,IAAI,QAAM,EAAE,GAAG,GAAG,UAAU,EAAE,WAAW,GAAG,EAAE,CAAC;AAAA,QACjG;AACA,cAAMC,cAAa,MAAM,KAAK,kBAAkB,IAAI;AACpD,cAAMD,SAAsB;AAAA,UAC1B,MAAM,QAAQ;AAAA,UAAO,gBAAgB;AAAA,UAAG,iBAAiB;AAAA,UACzD,YAAY,KAAK,IAAI,IAAI;AAAA,UAAS;AAAA,QACpC;AACA,aAAK,SAAS,WAAWA,MAAK;AAC9B,eAAO;AAAA,UACL,MAAM,QAAQ;AAAA,UAAO,UAAU,QAAQ,YAAY;AAAA,UACnD,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,UAAG,gBAAgB;AAAA,UACvD,SAASC,YAAW;AAAA,UACpB,YAAYA,YAAW;AAAA,UACvB,QAAQA,YAAW;AAAA,UACnB;AAAA,UAAkB,MAAM,CAAC;AAAA,UAAG,MAAM,CAAC;AAAA,UAAG;AAAA,UAAQ;AAAA,UAC9C,gBAAgB;AAAA,UAAc;AAAA,UAAW;AAAA,UAAW,OAAAD;AAAA,QACtD;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,KAAK,OAAO,MAAM,OAAO;AAC5C,YAAM,aAAa,MAAM,KAAK,kBAAkB,IAAI;AAEpD,YAAM,kBAAkB,IAAI,gBAAgB,EAAE,GAAG,QAAQ,OAAO,IAAI,QAAQ,IAAI,IAAI,QAAQ,IAAI,KAAK,oBAAoB,IAAI,CAAC;AAC9H,UAAI,KAAM,iBAAgB,IAAI,QAAQ,IAAI;AAC1C,YAAM,cAAc,MAAM,KAAK,mBAAmB,MAAM,mCAAmC,gBAAgB,SAAS,CAAC;AACrH,WAAK,SAAS,SAAS,WAAW;AAElC,UAAI,aAAa;AACjB,WAAK,QAAQ,SAAS,MAAM,GAAG;AAC7B,cAAM,WAAW,IAAI,gBAAgB,EAAE,GAAG,QAAQ,OAAO,IAAI,QAAQ,IAAI,IAAI,QAAQ,IAAI,OAAO,KAAK,CAAC;AACtG,YAAI,KAAM,UAAS,IAAI,QAAQ,IAAI;AACnC,cAAM,KAAK,OAAO,WAAW,mCAAmC,SAAS,SAAS,CAAC;AACnF,cAAM,YAAY,MAAM,KAAK,sBAAsB,IAAI;AACvD,qBAAa,CAAC,GAAG,gBAAgB,GAAG,UAAU,IAAI,QAAM,EAAE,GAAG,GAAG,UAAU,EAAE,WAAW,GAAG,EAAE,CAAC;AAAA,MAC/F;AAEA,YAAM,YAAY,CAAC,GAAG,QAAQ,GAAG,WAAW;AAC5C,YAAM,OAAO,KAAK,UAAU,MAAM,QAAQ,KAAK;AAE/C,YAAM,QAAsB;AAAA,QAC1B,MAAiB,QAAQ;AAAA,QACzB,gBAAiB,KAAK;AAAA,QACtB,iBAAiB,KAAK,OAAO,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA,QAC9D,YAAiB,KAAK,IAAI,IAAI;AAAA,QAC9B;AAAA,MACF;AAEA,WAAK,SAAS,WAAW,KAAK;AAE9B,aAAO;AAAA,QACL,MAAgB,QAAQ;AAAA,QACxB,UAAgB,QAAQ,YAAY;AAAA,QACpC,cAAgB,oBAAI,KAAK,GAAE,YAAY;AAAA,QACvC,gBAAgB,KAAK;AAAA,QACrB,SAAmB,WAAW;AAAA,QAC9B,YAAmB,WAAW;AAAA,QAC9B,QAAmB,WAAW;AAAA,QAC9B;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAS;AAAA,QACT;AAAA,QACA,gBAAgB;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ;AACA,WAAK,SAAS,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;AACzE,YAAM;AAAA,IACR,UAAE;AACA,YAAM,KAAK,OAAO,MAAM;AAAA,IAC1B;AAAA,EACF;AACF;;;AC5yBA,SAAS,YAAY,UAAU;AAC/B,OAAO,UAAU;AACjB,OAAO,UAAU;AAIV,IAAM,mBAAN,MAAoD;AAAA,EACzD,MAAM,UAAU,QAAuB,WAAoC;AACzE,UAAM,GAAG,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC7C,UAAM,OAAO,OAAO,KAAK,YAAY,EAAE,QAAQ,QAAQ,GAAG,EAAE,MAAM,GAAG,EAAE;AACvE,UAAM,WAAW,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC;AACtC,UAAM,WAAW,KAAK,KAAK,WAAW,QAAQ;AAC9C,UAAM,GAAG,UAAU,UAAU,KAAK,UAAU,QAAQ,MAAM,CAAC,GAAG,MAAM;AACpE,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAS,MAAiB,WAAoC;AAClE,UAAM,GAAG,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC7C,UAAM,UAAU,KAAK,CAAC,GAAG,cAAc;AACvC,UAAM,OAAO,QAAQ,YAAY,EAAE,QAAQ,QAAQ,GAAG,EAAE,MAAM,GAAG,EAAE;AACnE,UAAM,MAAM,KAAK,QAAQ,MAAM,EAAE,QAAQ,KAAK,CAAC;AAC/C,UAAM,WAAW,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC;AACtC,UAAM,WAAW,KAAK,KAAK,WAAW,QAAQ;AAC9C,UAAM,GAAG,UAAU,UAAU,KAAK,MAAM;AACxC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,cAAc,QAAuB,MAAc,WAAoC;AAC3F,UAAM,GAAG,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC7C,UAAM,OAAO,KAAK,YAAY,EAAE,QAAQ,QAAQ,GAAG,EAAE,MAAM,GAAG,EAAE;AAChE,UAAM,MAAM,KAAK,QAAQ,QAAQ,EAAE,QAAQ,KAAK,CAAC;AACjD,UAAM,WAAW,GAAG,IAAI,WAAW,KAAK,IAAI,CAAC;AAC7C,UAAM,WAAW,KAAK,KAAK,WAAW,QAAQ;AAC9C,UAAM,GAAG,UAAU,UAAU,KAAK,MAAM;AACxC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,cAAc,QAAuB,MAAc,WAAoC;AAC3F,UAAM,GAAG,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC7C,UAAM,OAAO,KAAK,YAAY,EAAE,QAAQ,QAAQ,GAAG,EAAE,MAAM,GAAG,EAAE;AAChE,UAAM,MAAM,KAAK,QAAQ,QAAQ,EAAE,QAAQ,KAAK,CAAC;AACjD,UAAM,WAAW,GAAG,IAAI,WAAW,KAAK,IAAI,CAAC;AAC7C,UAAM,WAAW,KAAK,KAAK,WAAW,QAAQ;AAC9C,UAAM,GAAG,UAAU,UAAU,KAAK,MAAM;AACxC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,mBAAmB,WAAyB,MAAqB,MAAc,WAAoC;AACvH,UAAM,GAAG,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC7C,UAAM,OAAO,KAAK,YAAY,EAAE,QAAQ,QAAQ,GAAG,EAAE,MAAM,GAAG,EAAE;AAChE,UAAM,OAAO,UAAU,IAAI,CAAC,GAAG,OAAO;AAAA,MACpC,YAAe;AAAA,MACf,eAAe,MAAM,IAAK,QAAQ,KAAM;AAAA,MACxC,eAAe,EAAE;AAAA,MACjB,eAAe,EAAE;AAAA,IACnB,EAAE;AACF,UAAM,MAAM,KAAK,QAAQ,MAAM,EAAE,QAAQ,KAAK,CAAC;AAC/C,UAAM,WAAW,GAAG,IAAI,gBAAgB,KAAK,IAAI,CAAC;AAClD,UAAM,WAAW,KAAK,KAAK,WAAW,QAAQ;AAC9C,UAAM,GAAG,UAAU,UAAU,KAAK,MAAM;AACxC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,eAAe,WAAyB,MAAqB,MAAc,WAAoC;AACnH,UAAM,GAAG,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC7C,UAAM,OAAO,KAAK,YAAY,EAAE,QAAQ,QAAQ,GAAG,EAAE,MAAM,GAAG,EAAE;AAChE,UAAM,OAAO,UAAU,IAAI,CAAC,GAAG,OAAO;AAAA,MACpC,YAAe;AAAA,MACf,eAAe,MAAM,IAAK,QAAQ,KAAM;AAAA,MACxC,eAAe,EAAE;AAAA,MACjB,eAAe,EAAE;AAAA,IACnB,EAAE;AACF,UAAM,MAAM,KAAK,QAAQ,MAAM,EAAE,QAAQ,KAAK,CAAC;AAC/C,UAAM,WAAW,GAAG,IAAI,YAAY,KAAK,IAAI,CAAC;AAC9C,UAAM,WAAW,KAAK,KAAK,WAAW,QAAQ;AAC9C,UAAM,GAAG,UAAU,UAAU,KAAK,MAAM;AACxC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,yBAAyB,OAA+B,MAAc,WAAoC;AAC9G,UAAM,GAAG,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC7C,UAAM,OAAO,KAAK,YAAY,EAAE,QAAQ,QAAQ,GAAG,EAAE,MAAM,GAAG,EAAE;AAChE,UAAM,OAAO,MAAM,IAAI,CAAC,OAAO,EAAE,YAAY,MAAM,GAAG,EAAE,EAAE;AAC1D,UAAM,MAAM,KAAK,QAAQ,MAAM,EAAE,QAAQ,KAAK,CAAC;AAC/C,UAAM,WAAW,GAAG,IAAI,uBAAuB,KAAK,IAAI,CAAC;AACzD,UAAM,WAAW,KAAK,KAAK,WAAW,QAAQ;AAC9C,UAAM,GAAG,UAAU,UAAU,KAAK,MAAM;AACxC,WAAO;AAAA,EACT;AACF;;;ACtFO,IAAM,mBAAN,MAAoD;AAAA,EACzD,WAAW,MAAqB;AAC9B,YAAQ,OAAO,MAAM,KAAK,UAAU,EAAE,OAAO,YAAY,OAAO,KAAK,OAAO,UAAU,KAAK,SAAS,CAAC,IAAI,IAAI;AAAA,EAC/G;AAAA,EAEA,QAAQ,OAAqB;AAC3B,YAAQ,OAAO,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,MAAM,CAAC,IAAI,IAAI;AAAA,EACvE;AAAA,EAEA,SAAS,QAA6B;AACpC,eAAW,KAAK,QAAQ;AACtB,cAAQ,OAAO,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,MAAM,EAAE,MAAM,UAAU,EAAE,UAAU,UAAU,EAAE,UAAU,OAAO,EAAE,OAAO,SAAS,EAAE,SAAS,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI;AAAA,IAC1K;AAAA,EACF;AAAA,EAEA,SAAS,QAA6B;AACpC,eAAW,KAAK,QAAQ;AACtB,cAAQ,OAAO,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,OAAO,EAAE,OAAO,QAAQ,EAAE,QAAQ,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI;AAAA,IAC9G;AAAA,EACF;AAAA,EAEA,WAAW,OAA2B;AACpC,YAAQ,OAAO,MAAM,KAAK,UAAU,EAAE,OAAO,YAAY,GAAG,MAAM,CAAC,IAAI,IAAI;AAAA,EAC7E;AAAA,EAEA,QAAQ,KAAkB;AACxB,YAAQ,OAAO,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,MAAM,IAAI,YAAY,MAAM,SAAS,IAAI,QAAQ,CAAC,IAAI,IAAI;AAAA,EAClH;AACF;;;ACvBA,IAAM,eAAe;AAErB,eAAe,YAAY,SAAiD;AAC1E,QAAM,SAAS,IAAI,cAAc;AACjC,QAAM,WAAW,IAAI,iBAAiB;AACtC,QAAM,YAAY,IAAI,aAAa,QAAQ,QAAQ;AACnD,MAAI;AACF,WAAO,MAAM,UAAU,QAAQ,OAAO;AAAA,EACxC,UAAE;AACA,UAAM,OAAO,MAAM;AAAA,EACrB;AACF;AAEA,eAAsB,QAAQ,YAA6C;AACzE,QAAM,MAAM,OAAO,eAAe,YAAY,eAAe,OAAO,aAAa,CAAC;AAClF,QAAM,SAAS;AAAA,IACb,cAAc,QAAQ,IAAI,gBAAgB,KAAK;AAAA,IAC/C,eAAe,QAAQ,IAAI,iBAAiB,KAAK;AAAA,IACjD,GAAG;AAAA,EACL;AACA,QAAM,UAAU,qBAAqB,MAAM,MAAM;AACjD,QAAM,aAAa,IAAI,iBAAiB;AAExC,WAAS,IAAI,GAAG,IAAI,cAAc,KAAK;AACrC,QAAI;AACF,YAAM,SAAS,MAAM,YAAY,OAAO;AACxC,UAAI,QAAQ,WAAW,UAAU,QAAQ,WAAW,QAAQ;AAC1D,cAAM,WAAW,UAAU,QAAQ,QAAQ,SAAS;AAAA,MACtD;AACA,UAAI,QAAQ,WAAW,SAAS,QAAQ,WAAW,QAAQ;AACzD,cAAM,QAAQ,IAAI;AAAA,UAChB,WAAW,SAAS,OAAO,MAAM,QAAQ,SAAS;AAAA,UAClD,OAAO,OAAO,SAAS,IAAI,WAAW,cAAc,OAAO,QAAQ,OAAO,MAAM,QAAQ,SAAS,IAAI,QAAQ,QAAQ,EAAE;AAAA,UACvH,OAAO,OAAO,SAAS,IAAI,WAAW,cAAc,OAAO,QAAQ,OAAO,MAAM,QAAQ,SAAS,IAAI,QAAQ,QAAQ,EAAE;AAAA,UACvH,OAAO,WAAW,WAAkB,WAAW,mBAAmB,OAAO,WAAW,WAAW,OAAO,WAAW,MAAM,OAAO,MAAM,QAAQ,SAAS,IAAI,QAAQ,QAAQ,EAAE;AAAA,UAC3K,OAAO,OAAO,WAAsB,WAAW,eAAe,OAAO,OAAO,WAAW,OAAO,OAAO,MAAM,OAAO,MAAM,QAAQ,SAAS,IAAO,QAAQ,QAAQ,EAAE;AAAA,UAClK,OAAO,iBAAiB,SAAS,IAAI,WAAW,yBAAyB,OAAO,kBAAkB,OAAO,MAAM,QAAQ,SAAS,IAAe,QAAQ,QAAQ,EAAE;AAAA,QACnK,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,eAAe,gBAAgB,IAAI,eAAe,GAAG;AACvD;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACA,QAAM,cAAc,QAAQ,eAAe,GAAG,YAAY,8BAA8B,GAAG,YAAY;AACvG,QAAM,IAAI,aAAa,kBAAkB,WAAW,+BAA+B;AACrF;","names":["s","organicResults","localPack","rawEntityIds","entityIds","allOrganic","stats","aiSurfaces"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/db.ts"],"sourcesContent":["import { createClient, type Client } from '@libsql/client/http'\nimport { randomBytes, randomUUID, scryptSync, timingSafeEqual } from 'node:crypto'\nimport { z } from 'zod'\n\nconst DB_URL = process.env.TURSO_DATABASE_URL ?? 'file:./paa-api.db'\nconst DB_TOKEN = process.env.TURSO_AUTH_TOKEN\n\nlet _db: Client | null = null\n\nexport function getDb(): Client {\n if (!_db) _db = createClient({ url: DB_URL, authToken: DB_TOKEN })\n return _db\n}\n\nexport async function migrate(): Promise<void> {\n const db = getDb()\n await db.execute(`\n CREATE TABLE IF NOT EXISTS users (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n email TEXT UNIQUE NOT NULL,\n name TEXT,\n api_key TEXT UNIQUE NOT NULL,\n password_hash TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n active INTEGER NOT NULL DEFAULT 1\n )\n `)\n await db.execute(`\n CREATE TABLE IF NOT EXISTS jobs (\n id TEXT PRIMARY KEY,\n user_id INTEGER NOT NULL REFERENCES users(id),\n status TEXT NOT NULL DEFAULT 'pending',\n query TEXT NOT NULL,\n options TEXT NOT NULL,\n callback_url TEXT,\n result TEXT,\n error TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n started_at TEXT,\n completed_at TEXT\n )\n `)\n await db.execute(`CREATE INDEX IF NOT EXISTS jobs_user_id ON jobs(user_id)`)\n await db.execute(`CREATE INDEX IF NOT EXISTS jobs_status ON jobs(status)`)\n try { await db.execute(`ALTER TABLE users ADD COLUMN password_hash TEXT`) } catch {}\n try { await db.execute(`ALTER TABLE users ADD COLUMN key_active INTEGER NOT NULL DEFAULT 1`) } catch {}\n\n await db.execute(`\n CREATE TABLE IF NOT EXISTS kpo_jobs (\n id TEXT PRIMARY KEY,\n user_id INTEGER NOT NULL REFERENCES users(id),\n status TEXT NOT NULL,\n entity_name TEXT NOT NULL,\n entity_type TEXT NOT NULL,\n url TEXT,\n request TEXT NOT NULL,\n result TEXT,\n error TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `)\n await db.execute(`\n CREATE TABLE IF NOT EXISTS kpo_phase_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n job_id TEXT NOT NULL REFERENCES kpo_jobs(id),\n phase TEXT NOT NULL,\n output TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `)\n await db.execute(`CREATE INDEX IF NOT EXISTS kpo_jobs_user_id ON kpo_jobs(user_id)`)\n await db.execute(`CREATE INDEX IF NOT EXISTS kpo_jobs_status ON kpo_jobs(status)`)\n await db.execute(`CREATE INDEX IF NOT EXISTS kpo_phase_log_job_id ON kpo_phase_log(job_id)`)\n try { await db.execute(`ALTER TABLE users ADD COLUMN stripe_customer_id TEXT`) } catch {}\n try { await db.execute(`ALTER TABLE users ADD COLUMN balance_mc INTEGER NOT NULL DEFAULT 0`) } catch {}\n await db.execute(`\n CREATE TABLE IF NOT EXISTS ledger (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n user_id INTEGER NOT NULL REFERENCES users(id),\n amount_mc INTEGER NOT NULL,\n operation TEXT NOT NULL,\n description TEXT,\n stripe_pi TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `)\n await db.execute(`CREATE INDEX IF NOT EXISTS ledger_user_id ON ledger(user_id)`)\n await db.execute(`\n CREATE TABLE IF NOT EXISTS site_audit_jobs (\n id TEXT PRIMARY KEY,\n user_id INTEGER,\n status TEXT DEFAULT 'pending',\n client_domain TEXT,\n session_path TEXT,\n request TEXT,\n result TEXT,\n error TEXT,\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now'))\n )\n `)\n await db.execute(`\n CREATE TABLE IF NOT EXISTS site_audit_phase_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n job_id TEXT REFERENCES site_audit_jobs(id),\n phase TEXT,\n completed_at TEXT DEFAULT (datetime('now')),\n output_summary TEXT\n )\n `)\n await db.execute(`CREATE INDEX IF NOT EXISTS site_audit_jobs_user_id ON site_audit_jobs(user_id)`)\n await db.execute(`CREATE INDEX IF NOT EXISTS site_audit_jobs_status ON site_audit_jobs(status)`)\n await db.execute(`CREATE INDEX IF NOT EXISTS site_audit_phase_log_job_id ON site_audit_phase_log(job_id)`)\n}\n\nexport function generateApiKey(): string {\n return 'sk_' + randomBytes(24).toString('hex')\n}\n\nexport interface User {\n id: number\n email: string\n name: string | null\n api_key: string\n key_active: number\n password_hash: string | null\n created_at: string\n active: number\n stripe_customer_id: string | null\n balance_mc: number\n}\n\nexport function hashPassword(password: string): string {\n const salt = randomBytes(16).toString('hex')\n const hash = scryptSync(password, salt, 64)\n return `${salt}:${hash.toString('hex')}`\n}\n\nexport function verifyPassword(password: string, stored: string): boolean {\n const [salt, hash] = stored.split(':')\n const hashBuf = Buffer.from(hash, 'hex')\n const derived = scryptSync(password, salt, 64)\n return timingSafeEqual(hashBuf, derived)\n}\n\nfunction rowToUser(row: Record<string, unknown>): User {\n return {\n id: Number(row.id),\n email: String(row.email),\n name: row.name != null ? String(row.name) : null,\n api_key: String(row.api_key),\n key_active: Number(row.key_active ?? 1),\n password_hash: row.password_hash != null ? String(row.password_hash) : null,\n created_at: String(row.created_at),\n active: Number(row.active),\n stripe_customer_id: row.stripe_customer_id != null ? String(row.stripe_customer_id) : null,\n balance_mc: Number(row.balance_mc ?? 0),\n }\n}\n\nexport async function getUserByEmail(email: string): Promise<User | undefined> {\n const res = await getDb().execute({ sql: 'SELECT * FROM users WHERE email = ? AND active = 1', args: [email] })\n return res.rows[0] ? rowToUser(res.rows[0] as unknown as Record<string, unknown>) : undefined\n}\n\nexport async function getUserByApiKey(api_key: string): Promise<User | undefined> {\n const res = await getDb().execute({ sql: 'SELECT * FROM users WHERE api_key = ? AND active = 1 AND key_active = 1', args: [api_key] })\n return res.rows[0] ? rowToUser(res.rows[0] as unknown as Record<string, unknown>) : undefined\n}\n\nexport async function getUserById(id: number | bigint): Promise<User | undefined> {\n const res = await getDb().execute({ sql: 'SELECT * FROM users WHERE id = ? AND active = 1', args: [id] })\n return res.rows[0] ? rowToUser(res.rows[0] as unknown as Record<string, unknown>) : undefined\n}\n\nexport async function setPassword(id: number | bigint, password: string): Promise<void> {\n await getDb().execute({ sql: 'UPDATE users SET password_hash = ? WHERE id = ?', args: [hashPassword(password), id] })\n}\n\nexport async function getUserStats(userId: number | bigint): Promise<{ total: number; done: number; failed: number; totalQuestions: number; lastUsed: string | null }> {\n const db = getDb()\n const [totR, doneR, failR, tqR, luR] = await Promise.all([\n db.execute({ sql: 'SELECT COUNT(*) as n FROM jobs WHERE user_id = ?', args: [userId] }),\n db.execute({ sql: \"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'done'\", args: [userId] }),\n db.execute({ sql: \"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'failed'\", args: [userId] }),\n db.execute({ sql: \"SELECT COALESCE(SUM(json_extract(result, '$.totalQuestions')), 0) as n FROM jobs WHERE user_id = ? AND status = 'done'\", args: [userId] }),\n db.execute({ sql: 'SELECT MAX(created_at) as t FROM jobs WHERE user_id = ?', args: [userId] }),\n ])\n return {\n total: Number(totR.rows[0]?.n ?? 0),\n done: Number(doneR.rows[0]?.n ?? 0),\n failed: Number(failR.rows[0]?.n ?? 0),\n totalQuestions: Number(tqR.rows[0]?.n ?? 0),\n lastUsed: luR.rows[0]?.t != null ? String(luR.rows[0].t) : null,\n }\n}\n\nexport async function createUser(email: string, name?: string, password?: string): Promise<{ id: number | bigint; email: string; name?: string; api_key: string; password?: string }> {\n const db = getDb()\n const api_key = generateApiKey()\n const plainPassword = password ?? randomBytes(6).toString('hex')\n const password_hash = hashPassword(plainPassword)\n const result = await db.execute({\n sql: 'INSERT INTO users (email, name, api_key, password_hash) VALUES (?, ?, ?, ?)',\n args: [email, name ?? null, api_key, password_hash],\n })\n return { id: result.lastInsertRowid!, email, name, api_key, password: plainPassword }\n}\n\nexport async function rotateApiKey(userId: number | bigint): Promise<string> {\n const newKey = generateApiKey()\n await getDb().execute({ sql: 'UPDATE users SET api_key = ?, key_active = 1 WHERE id = ?', args: [newKey, userId] })\n return newKey\n}\n\nexport async function revokeApiKey(userId: number | bigint): Promise<void> {\n await getDb().execute({ sql: 'UPDATE users SET key_active = 0 WHERE id = ?', args: [userId] })\n}\n\nexport async function listUsers(): Promise<Omit<User, 'api_key'>[]> {\n const res = await getDb().execute('SELECT id, email, name, created_at, active FROM users ORDER BY created_at DESC')\n return res.rows.map(r => rowToUser({ ...r as unknown as Record<string, unknown>, api_key: '', key_active: 1 }))\n}\n\nexport async function deactivateUser(id: number): Promise<void> {\n await getDb().execute({ sql: 'UPDATE users SET active = 0 WHERE id = ?', args: [id] })\n}\n\ninterface RawJob {\n id: string\n user_id: number\n status: string\n query: string\n options: string\n callback_url: string | null\n result: string | null\n error: string | null\n created_at: string\n started_at: string | null\n completed_at: string | null\n}\n\nexport interface Job {\n id: string\n user_id: number\n status: string\n query: string\n options: Record<string, unknown>\n callback_url: string | null\n result: unknown | null\n error: string | null\n created_at: string\n started_at: string | null\n completed_at: string | null\n}\n\nfunction rowToRawJob(row: Record<string, unknown>): RawJob {\n return {\n id: String(row.id),\n user_id: Number(row.user_id),\n status: String(row.status),\n query: String(row.query),\n options: String(row.options),\n callback_url: row.callback_url != null ? String(row.callback_url) : null,\n result: row.result != null ? String(row.result) : null,\n error: row.error != null ? String(row.error) : null,\n created_at: String(row.created_at),\n started_at: row.started_at != null ? String(row.started_at) : null,\n completed_at: row.completed_at != null ? String(row.completed_at) : null,\n }\n}\n\nfunction deserialize(raw: RawJob): Job {\n return {\n ...raw,\n options: JSON.parse(raw.options) as Record<string, unknown>,\n result: raw.result ? JSON.parse(raw.result) : null,\n }\n}\n\nexport async function createJob(userId: number | bigint, query: string, options: object, callbackUrl?: string): Promise<string> {\n const id = randomUUID()\n await getDb().execute({\n sql: 'INSERT INTO jobs (id, user_id, query, options, callback_url) VALUES (?, ?, ?, ?, ?)',\n args: [id, userId, query, JSON.stringify(options), callbackUrl ?? null],\n })\n return id\n}\n\nexport async function createRunningJob(userId: number | bigint, query: string, options: object): Promise<string> {\n const id = randomUUID()\n await getDb().execute({\n sql: `INSERT INTO jobs (id, user_id, query, options, status, started_at) VALUES (?, ?, ?, ?, 'running', datetime('now'))`,\n args: [id, userId, query, JSON.stringify(options)],\n })\n return id\n}\n\nexport async function getJob(id: string, userId?: number | bigint): Promise<Job | undefined> {\n const db = getDb()\n const res = userId\n ? await db.execute({ sql: 'SELECT * FROM jobs WHERE id = ? AND user_id = ?', args: [id, userId] })\n : await db.execute({ sql: 'SELECT * FROM jobs WHERE id = ?', args: [id] })\n return res.rows[0] ? deserialize(rowToRawJob(res.rows[0] as unknown as Record<string, unknown>)) : undefined\n}\n\nexport async function listJobs(userId: number | bigint): Promise<Job[]> {\n const res = await getDb().execute({ sql: 'SELECT * FROM jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50', args: [userId] })\n return res.rows.map(r => deserialize(rowToRawJob(r as unknown as Record<string, unknown>)))\n}\n\nexport async function countActiveUsers(): Promise<number> {\n const res = await getDb().execute(`SELECT COUNT(*) as n FROM users WHERE active = 1`)\n return Number(res.rows[0]?.n ?? 0)\n}\n\nexport async function countActiveJobsForUser(userId: number | bigint): Promise<number> {\n const res = await getDb().execute({\n sql: `SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND (status = 'pending' OR (status = 'running' AND started_at > datetime('now', '-10 minutes')))`,\n args: [userId],\n })\n return Number(res.rows[0]?.n ?? 0)\n}\n\nexport async function countJobsLast7Days(userId: number | bigint): Promise<number> {\n const res = await getDb().execute({\n sql: `SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND created_at > datetime('now', '-7 days')`,\n args: [userId],\n })\n return Number(res.rows[0]?.n ?? 0)\n}\n\nexport async function claimPendingJob(): Promise<RawJob | undefined> {\n const db = getDb()\n const res = await db.execute(`SELECT * FROM jobs WHERE status = 'pending' ORDER BY created_at LIMIT 1`)\n const job = res.rows[0] ? rowToRawJob(res.rows[0] as unknown as Record<string, unknown>) : undefined\n if (!job) return undefined\n const upd = await db.execute({\n sql: `UPDATE jobs SET status = 'running', started_at = datetime('now') WHERE id = ? AND status = 'pending'`,\n args: [job.id],\n })\n return upd.rowsAffected === 0 ? undefined : { ...job, status: 'running' }\n}\n\nexport async function completeJob(id: string, result: object): Promise<void> {\n await getDb().execute({ sql: `UPDATE jobs SET status = 'done', result = ?, completed_at = datetime('now') WHERE id = ?`, args: [JSON.stringify(result), id] })\n}\n\nexport async function failJob(id: string, error: string): Promise<void> {\n await getDb().execute({ sql: `UPDATE jobs SET status = 'failed', error = ?, completed_at = datetime('now') WHERE id = ?`, args: [error, id] })\n}\n\nexport interface KpoJobRow {\n id: string\n user_id: number\n status: string\n entity_name: string\n entity_type: string\n url: string | null\n request: string\n result: string | null\n error: string | null\n created_at: string\n updated_at: string\n}\n\nexport interface KpoPhaseLogRow {\n id: number\n job_id: string\n phase: string\n output: string\n created_at: string\n}\n\nfunction rowToKpoJob(row: Record<string, unknown>): KpoJobRow {\n return {\n id: String(row.id),\n user_id: Number(row.user_id),\n status: String(row.status),\n entity_name: String(row.entity_name),\n entity_type: String(row.entity_type),\n url: row.url != null ? String(row.url) : null,\n request: String(row.request),\n result: row.result != null ? String(row.result) : null,\n error: row.error != null ? String(row.error) : null,\n created_at: String(row.created_at),\n updated_at: String(row.updated_at),\n }\n}\n\nfunction rowToKpoPhaseLog(row: Record<string, unknown>): KpoPhaseLogRow {\n return {\n id: Number(row.id),\n job_id: String(row.job_id),\n phase: String(row.phase),\n output: String(row.output),\n created_at: String(row.created_at),\n }\n}\n\nexport async function createKpoJob(jobId: string, userId: number, entityName: string, entityType: string, request: object, url?: string): Promise<void> {\n await getDb().execute({\n sql: `INSERT INTO kpo_jobs (id, user_id, status, entity_name, entity_type, url, request) VALUES (?, ?, 'pending', ?, ?, ?, ?)`,\n args: [jobId, userId, entityName, entityType, url ?? null, JSON.stringify(request)],\n })\n}\n\nexport async function claimPendingKpoJob(): Promise<KpoJobRow | null> {\n const db = getDb()\n const upd = await db.execute(\n `UPDATE kpo_jobs SET status='running', updated_at=datetime('now') WHERE id = (SELECT id FROM kpo_jobs WHERE status='pending' ORDER BY created_at ASC LIMIT 1) RETURNING *`\n )\n if (upd.rowsAffected === 0) return null\n return upd.rows[0] ? rowToKpoJob(upd.rows[0] as unknown as Record<string, unknown>) : null\n}\n\nexport async function getKpoJob(jobId: string): Promise<KpoJobRow | null> {\n const res = await getDb().execute({ sql: `SELECT * FROM kpo_jobs WHERE id = ?`, args: [jobId] })\n return res.rows[0] ? rowToKpoJob(res.rows[0] as unknown as Record<string, unknown>) : null\n}\n\nexport async function updateKpoJobState(jobId: string, status: string): Promise<void> {\n await getDb().execute({ sql: `UPDATE kpo_jobs SET status = ?, updated_at = datetime('now') WHERE id = ?`, args: [status, jobId] })\n}\n\nexport async function completeKpoJob(jobId: string, result: object): Promise<void> {\n await getDb().execute({ sql: `UPDATE kpo_jobs SET status = 'done', result = ?, updated_at = datetime('now') WHERE id = ?`, args: [JSON.stringify(result), jobId] })\n}\n\nexport async function failKpoJob(jobId: string, error: string): Promise<void> {\n await getDb().execute({ sql: `UPDATE kpo_jobs SET status = 'failed', error = ?, updated_at = datetime('now') WHERE id = ?`, args: [error, jobId] })\n}\n\nexport async function logKpoPhaseComplete(jobId: string, phase: string, output: unknown): Promise<void> {\n await getDb().execute({\n sql: `INSERT INTO kpo_phase_log (job_id, phase, output) VALUES (?, ?, ?)`,\n args: [jobId, phase, JSON.stringify(output)],\n })\n}\n\nexport async function getKpoPhaseLog(jobId: string): Promise<KpoPhaseLogRow[]> {\n const res = await getDb().execute({ sql: `SELECT * FROM kpo_phase_log WHERE job_id = ? ORDER BY created_at ASC`, args: [jobId] })\n return res.rows.map(r => rowToKpoPhaseLog(r as unknown as Record<string, unknown>))\n}\n\nexport async function listKpoJobs(userId?: number): Promise<KpoJobRow[]> {\n const res = userId != null\n ? await getDb().execute({ sql: `SELECT * FROM kpo_jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50`, args: [userId] })\n : await getDb().execute(`SELECT * FROM kpo_jobs ORDER BY created_at DESC LIMIT 50`)\n return res.rows.map(r => rowToKpoJob(r as unknown as Record<string, unknown>))\n}\n\nexport async function getUserByStripeCustomerId(customerId: string): Promise<User | undefined> {\n const res = await getDb().execute({\n sql: 'SELECT * FROM users WHERE stripe_customer_id = ? AND active = 1',\n args: [customerId],\n })\n return res.rows[0] ? rowToUser(res.rows[0] as unknown as Record<string, unknown>) : undefined\n}\n\nexport async function setStripeCustomerId(userId: number, customerId: string): Promise<void> {\n await getDb().execute({\n sql: 'UPDATE users SET stripe_customer_id = ? WHERE id = ?',\n args: [customerId, userId],\n })\n}\n\nexport async function creditMc(\n userId: number,\n mc: number,\n operation: string,\n description?: string,\n stripePaymentIntent?: string,\n): Promise<number> {\n const db = getDb()\n await db.execute({\n sql: 'UPDATE users SET balance_mc = balance_mc + ? WHERE id = ?',\n args: [mc, userId],\n })\n await db.execute({\n sql: 'INSERT INTO ledger (user_id, amount_mc, operation, description, stripe_pi) VALUES (?, ?, ?, ?, ?)',\n args: [userId, mc, operation, description ?? null, stripePaymentIntent ?? null],\n })\n const res = await db.execute({ sql: 'SELECT balance_mc FROM users WHERE id = ?', args: [userId] })\n return Number(res.rows[0]?.balance_mc ?? 0)\n}\n\nexport async function debitMc(\n userId: number,\n mc: number,\n operation: string,\n description?: string,\n): Promise<{ ok: boolean; balance_mc: number }> {\n const db = getDb()\n const res = await db.execute({ sql: 'SELECT balance_mc FROM users WHERE id = ?', args: [userId] })\n const current = Number(res.rows[0]?.balance_mc ?? 0)\n if (current < mc) return { ok: false, balance_mc: current }\n await db.execute({\n sql: 'UPDATE users SET balance_mc = balance_mc - ? WHERE id = ?',\n args: [mc, userId],\n })\n await db.execute({\n sql: 'INSERT INTO ledger (user_id, amount_mc, operation, description) VALUES (?, ?, ?, ?)',\n args: [userId, -mc, operation, description ?? null],\n })\n return { ok: true, balance_mc: current - mc }\n}\n\nexport async function getLedger(userId: number, limit = 50): Promise<LedgerRow[]> {\n const res = await getDb().execute({\n sql: 'SELECT * FROM ledger WHERE user_id = ? ORDER BY created_at DESC LIMIT ?',\n args: [userId, limit],\n })\n return res.rows.map(r => ({\n id: Number(r.id),\n user_id: Number(r.user_id),\n amount_mc: Number(r.amount_mc),\n operation: String(r.operation),\n description: r.description != null ? String(r.description) : null,\n stripe_pi: r.stripe_pi != null ? String(r.stripe_pi) : null,\n created_at: String(r.created_at),\n }))\n}\n\nexport interface LedgerRow {\n id: number\n user_id: number\n amount_mc: number\n operation: string\n description: string | null\n stripe_pi: string | null\n created_at: string\n}\n\nexport const SiteAuditJobRowSchema = z.object({\n id: z.string(),\n user_id: z.number(),\n status: z.string().default('pending'),\n client_domain: z.string(),\n session_path: z.string(),\n request: z.string(),\n result: z.string().nullable(),\n error: z.string().nullable(),\n created_at: z.string(),\n updated_at: z.string(),\n});\nexport type SiteAuditJobRow = z.infer<typeof SiteAuditJobRowSchema>;\n\nexport const SiteAuditPhaseLogRowSchema = z.object({\n id: z.number(),\n job_id: z.string(),\n phase: z.string(),\n completed_at: z.string(),\n output_summary: z.string(),\n});\nexport type SiteAuditPhaseLogRow = z.infer<typeof SiteAuditPhaseLogRowSchema>;\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/paa-mcp-server.ts","../src/mcp/mcp-tool-schemas.ts","../src/mcp/mcp-response-formatter.ts","../src/mcp/http-mcp-tool-executor.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { IMcpToolExecutor } from './IMcpToolExecutor.js'\nimport {\n HarvestPaaInputSchema,\n SearchSerpInputSchema,\n ExtractUrlInputSchema,\n MapSiteUrlsInputSchema,\n ExtractSiteInputSchema,\n YoutubeHarvestInputSchema,\n YoutubeTranscribeInputSchema,\n FacebookPageIntelInputSchema,\n FacebookAdSearchInputSchema,\n FacebookAdTranscribeInputSchema,\n MapsPlaceIntelInputSchema,\n CreditsInfoInputSchema,\n} from './mcp-tool-schemas.js'\nimport {\n formatHarvestPaa,\n formatSearchSerp,\n formatExtractUrl,\n formatMapSiteUrls,\n formatExtractSite,\n formatYoutubeHarvest,\n formatYoutubeTranscribe,\n formatFacebookPageIntel,\n formatFacebookAdSearch,\n formatFacebookAdTranscribe,\n formatMapsPlaceIntel,\n formatCreditsInfo,\n} from './mcp-response-formatter.js'\n\nexport function buildPaaExtractorMcpServer(executor: IMcpToolExecutor): McpServer {\n const server = new McpServer({ name: 'paa-extractor', version: '1.0.0' })\n\n server.registerTool('harvest_paa', {\n description: 'Extract PAA (People Also Ask) questions from Google Search. Returns full question list with answers, organic SERP, entity IDs (CID/GCID/KG MID), and AI Overview. Use maxQuestions to control volume (up to 40).',\n inputSchema: HarvestPaaInputSchema,\n }, async (input) => formatHarvestPaa(await executor.harvestPaa(input), input))\n\n server.registerTool('search_serp', {\n description: 'Fetch organic Google search results. Returns ranked URLs, titles, snippets, local pack, entity IDs (CID/GCID/KG MID), and AI Overview. Use when you need SERP positions without PAA expansion.',\n inputSchema: SearchSerpInputSchema,\n }, async (input) => formatSearchSerp(await executor.searchSerp(input), input))\n\n server.registerTool('extract_url', {\n description: 'Extract structured data from a single URL: page content as Markdown, heading structure, JSON-LD schema, entity details, NAP score, and missing schema fields. Use for SEO audits and entity validation.',\n inputSchema: ExtractUrlInputSchema,\n }, async (input) => formatExtractUrl(await executor.extractUrl(input), input))\n\n server.registerTool('map_site_urls', {\n description: 'Spider a website to build a complete URL inventory with HTTP status codes. Identifies broken links and redirect chains. Use before extract_site to understand site scope.',\n inputSchema: MapSiteUrlsInputSchema,\n }, async (input) => formatMapSiteUrls(await executor.mapSiteUrls(input), input))\n\n server.registerTool('extract_site', {\n description: 'Run multi-page extraction across an entire website. Returns schema, entity data, headings, and content from each page. Use map_site_urls first to check scope.',\n inputSchema: ExtractSiteInputSchema,\n }, async (input) => formatExtractSite(await executor.extractSite(input), input))\n\n server.registerTool('youtube_harvest', {\n description: 'Harvest YouTube video metadata by search query or channel handle. Returns titles, view counts, durations, and videoIds. Use mode \"search\" for keyword results or \"channel\" for a specific creator.',\n inputSchema: YoutubeHarvestInputSchema,\n }, async (input) => formatYoutubeHarvest(await executor.youtubeHarvest(input), input))\n\n server.registerTool('youtube_transcribe', {\n description: 'Fetch and transcribe captions from a YouTube video. Returns full transcript, timestamped chunks, and word count. Pass a videoId from youtube_harvest results.',\n inputSchema: YoutubeTranscribeInputSchema,\n }, async (input) => formatYoutubeTranscribe(await executor.youtubeTranscribe(input), input))\n\n server.registerTool('facebook_page_intel', {\n description: 'Harvest all ads from a Facebook advertiser. Returns ad copy, headlines, CTAs, creative type, status, and video URLs ready for transcription. Accepts pageId, libraryId, or a brand name as query.',\n inputSchema: FacebookPageIntelInputSchema,\n }, async (input) => formatFacebookPageIntel(await executor.facebookPageIntel(input), input))\n\n server.registerTool('facebook_ad_search', {\n description: 'Search Facebook Ad Library by keyword. Returns advertisers with ad counts and library IDs. Use to discover competitors, then pass libraryId to facebook_page_intel to get their full ad list.',\n inputSchema: FacebookAdSearchInputSchema,\n }, async (input) => formatFacebookAdSearch(await executor.facebookAdSearch(input), input))\n\n server.registerTool('facebook_ad_transcribe', {\n description: 'Transcribe audio from a Facebook ad video. Returns full transcript and timestamped chunks. Use the videoUrl value from facebook_page_intel results.',\n inputSchema: FacebookAdTranscribeInputSchema,\n }, async (input) => formatFacebookAdTranscribe(await executor.facebookAdTranscribe(input), input))\n\n server.registerTool('maps_place_intel', {\n description: 'Extract Google Maps business intelligence for a named business: rating, review count, category, address, phone, website, hours, booking URL, review histogram, review topics, about attributes, and optional review cards. Pass includeReviews: true and maxReviews to fetch individual review text.',\n inputSchema: MapsPlaceIntelInputSchema,\n }, async (input) => formatMapsPlaceIntel(await executor.mapsPlaceIntel(input), input))\n\n server.registerTool('credits_info', {\n description: 'Answer questions about MCP Scraper credits: current credit balance, what a specific tool/action costs, the full cost table, and optionally recent credit ledger entries. Does not expose payment methods or credit card information.',\n inputSchema: CreditsInfoInputSchema,\n }, async (input) => formatCreditsInfo(await executor.creditsInfo(input), input))\n\n return server\n}\n","import { z } from 'zod'\n\nexport const HarvestPaaInputSchema = {\n query: z.string().min(1).describe('Search query to harvest PAA questions for'),\n location: z.string().optional().describe('Location name for geo-targeted results'),\n maxQuestions: z.number().int().min(1).max(100).default(30).describe('Number of PAA questions to extract (max 100)'),\n gl: z.string().length(2).default('us'),\n hl: z.string().default('en'),\n}\nexport type HarvestPaaInput = z.infer<ReturnType<typeof z.object<typeof HarvestPaaInputSchema>>>\n\nexport const ExtractUrlInputSchema = {\n url: z.string().url(),\n}\nexport type ExtractUrlInput = z.infer<ReturnType<typeof z.object<typeof ExtractUrlInputSchema>>>\n\nexport const MapSiteUrlsInputSchema = {\n url: z.string().url(),\n maxUrls: z.number().int().min(1).max(500).optional(),\n}\nexport type MapSiteUrlsInput = z.infer<ReturnType<typeof z.object<typeof MapSiteUrlsInputSchema>>>\n\nexport const ExtractSiteInputSchema = {\n url: z.string().url(),\n maxPages: z.number().int().min(1).max(50).optional(),\n}\nexport type ExtractSiteInput = z.infer<ReturnType<typeof z.object<typeof ExtractSiteInputSchema>>>\n\nexport const YoutubeHarvestInputSchema = {\n mode: z.enum(['search', 'channel']),\n query: z.string().optional().describe('Required when mode is search'),\n channelHandle: z.string().optional().describe('YouTube channel handle, e.g. @mkbhd'),\n maxVideos: z.number().int().min(1).max(500).default(50),\n}\nexport type YoutubeHarvestInput = z.infer<ReturnType<typeof z.object<typeof YoutubeHarvestInputSchema>>>\n\nexport const YoutubeTranscribeInputSchema = {\n videoId: z.string().min(1).describe('YouTube video ID, e.g. dQw4w9WgXcQ'),\n}\nexport type YoutubeTranscribeInput = z.infer<ReturnType<typeof z.object<typeof YoutubeTranscribeInputSchema>>>\n\nexport const FacebookPageIntelInputSchema = {\n pageId: z.string().optional(),\n libraryId: z.string().optional(),\n query: z.string().optional().describe('One of pageId, libraryId, or query is required'),\n maxAds: z.number().int().min(1).max(200).default(50),\n country: z.string().length(2).default('US'),\n}\nexport type FacebookPageIntelInput = z.infer<ReturnType<typeof z.object<typeof FacebookPageIntelInputSchema>>>\n\nexport const FacebookAdSearchInputSchema = {\n query: z.string().min(1),\n country: z.string().length(2).default('US'),\n maxResults: z.number().int().min(1).max(20).default(10),\n}\nexport type FacebookAdSearchInput = z.infer<ReturnType<typeof z.object<typeof FacebookAdSearchInputSchema>>>\n\nexport const FacebookAdTranscribeInputSchema = {\n videoUrl: z.string().url().describe('Facebook CDN video URL from a facebook_page_intel result'),\n}\nexport type FacebookAdTranscribeInput = z.infer<ReturnType<typeof z.object<typeof FacebookAdTranscribeInputSchema>>>\n\nexport const MapsPlaceIntelInputSchema = {\n businessName: z.string().min(1).describe('Business name to search for on Google Maps'),\n location: z.string().min(1).describe('City and state, e.g. \"Denver, CO\"'),\n gl: z.string().length(2).default('us'),\n hl: z.string().length(2).default('en'),\n includeReviews: z.boolean().default(false).describe('Whether to fetch individual review cards'),\n maxReviews: z.number().int().min(1).max(500).default(50).describe('Max review cards to return (requires includeReviews: true)'),\n}\nexport type MapsPlaceIntelInput = z.infer<ReturnType<typeof z.object<typeof MapsPlaceIntelInputSchema>>>\n\nexport const CreditsInfoInputSchema = {\n item: z.string().optional().describe('Optional tool, action, or feature to look up, e.g. \"maps reviews\", \"extract_url\", or \"YouTube transcription\"'),\n includeLedger: z.boolean().default(false).describe('Whether to include recent credit ledger entries'),\n}\nexport type CreditsInfoInput = z.infer<ReturnType<typeof z.object<typeof CreditsInfoInputSchema>>>\n\nexport const SearchSerpInputSchema = {\n query: z.string().min(1).describe('Search query to retrieve organic Google results for'),\n location: z.string().optional().describe('Location name for geo-targeted results'),\n gl: z.string().length(2).default('us'),\n hl: z.string().default('en'),\n pages: z.number().int().min(1).max(2).default(1).describe('Number of result pages to fetch (1–2)'),\n}\nexport type SearchSerpInput = z.infer<ReturnType<typeof z.object<typeof SearchSerpInputSchema>>>\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\n\nfunction twoBlocks(full: string, summary: string): CallToolResult {\n return { content: [{ type: 'text', text: full }, { type: 'text', text: summary }] }\n}\n\nexport function passthrough(raw: CallToolResult): CallToolResult {\n return raw\n}\n\nfunction checkInsufficientBalance(raw: CallToolResult): CallToolResult | null {\n const first = raw.content.find(b => b.type === 'text')\n const text = first?.type === 'text' ? first.text : ''\n try {\n const body = JSON.parse(text || '{}') as Record<string, unknown>\n if (body.error === 'insufficient_balance') {\n return {\n isError: true,\n content: [{\n type: 'text',\n text: `Insufficient credits. Balance: ${body.balance_credits} credits. This call requires ${body.required_credits} credits. Top up at ${body.topup_url}`,\n }],\n }\n }\n } catch { }\n return null\n}\n\nfunction parseData(raw: CallToolResult): { data: Record<string, unknown> } | { error: string } {\n const first = raw.content.find(b => b.type === 'text')\n const text = first?.type === 'text' ? first.text : ''\n try {\n const parsed = JSON.parse(text || '{}') as Record<string, unknown>\n if (parsed.error === 'insufficient_balance') {\n return { error: `Insufficient credits. Balance: ${parsed.balance_credits} credits. This call requires ${parsed.required_credits} credits. Top up at ${parsed.topup_url}` }\n }\n if (raw.isError) return { error: text || 'Tool error' }\n const data = (parsed.result as Record<string, unknown>) ?? parsed\n return { data }\n } catch {\n if (raw.isError) return { error: text || 'Tool error' }\n return { error: 'Failed to parse tool response' }\n }\n}\n\nfunction entityIdsSection(ids?: { kgIds?: string[]; cids?: string[]; gcids?: string[] }): string {\n if (!ids) return ''\n const lines: string[] = []\n if (ids.kgIds?.length) lines.push(`- **Knowledge Graph MID:** ${ids.kgIds.join(', ')}`)\n if (ids.cids?.length) lines.push(`- **CID:** ${ids.cids.join(', ')}`)\n if (ids.gcids?.length) lines.push(`- **GCID:** ${ids.gcids.join(', ')}`)\n return lines.length ? `\\n## Entity IDs\\n${lines.join('\\n')}` : ''\n}\n\nfunction entityIdsSummaryLine(ids?: { kgIds?: string[]; cids?: string[]; gcids?: string[] }): string {\n if (!ids) return ''\n const parts: string[] = []\n if (ids.kgIds?.length) parts.push(`KG MID: ${ids.kgIds[0]}`)\n if (ids.cids?.length) parts.push(`CID: ${ids.cids[0]}`)\n if (ids.gcids?.length) parts.push(`GCID: ${ids.gcids[0]}`)\n return parts.length ? `\\n**Entity IDs:** ${parts.join(' · ')}` : ''\n}\n\nfunction truncate(s: string | null | undefined, max: number): string {\n if (!s) return ''\n return s.length > max ? s.slice(0, max) + '…' : s\n}\n\nconst DIRECTIVE_FULL = '> 📄 **FULL REPORT** — render as artifact or expandable block\\n\\n'\nconst DIRECTIVE_SUMMARY = '> 💬 **SUMMARY** — present this inline; offer the full report above as an artifact\\n\\n'\n\ninterface FlatRow { question: string; answer?: string; source_site?: string }\ninterface OrganicResult { position: number; title: string; url: string; domain: string; snippet?: string | null }\ninterface AIOverview { detected: boolean; text?: string | null }\n\nexport function formatHarvestPaa(\n raw: CallToolResult,\n input: { query: string; maxQuestions?: number; location?: string },\n): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data\n\n const flat = (d.flat as FlatRow[]) ?? []\n const organic = (d.organicResults as OrganicResult[]) ?? []\n const entityIds = d.entityIds as { kgIds?: string[]; cids?: string[]; gcids?: string[] } | undefined\n const aiOvw = d.aiOverview as AIOverview | undefined\n const durationMs = (d.stats as { durationMs?: number } | undefined)?.durationMs\n\n const paaRows = flat.map((r, i) =>\n `| ${i + 1} | ${r.question} | ${truncate(r.answer, 120)} | ${r.source_site ?? ''} |`,\n ).join('\\n')\n\n const paaTable = flat.length\n ? `## People Also Ask (${flat.length} questions)\\n| # | Question | Answer | Source |\\n|---|----------|--------|--------|\\n${paaRows}`\n : '## People Also Ask\\n*No questions extracted*'\n\n const serpRows = organic.map(r =>\n `| ${r.position} | ${r.title} | [${r.domain}](${r.url}) | ${truncate(r.snippet, 100)} |`,\n ).join('\\n')\n\n const serpTable = organic.length\n ? `\\n## Organic Results (${organic.length})\\n| # | Title | URL | Snippet |\\n|---|-------|-----|----------|\\n${serpRows}`\n : ''\n\n const aiSection = aiOvw?.detected && aiOvw.text\n ? `\\n## AI Overview\\n> ${truncate(aiOvw.text, 600)}`\n : ''\n\n const statsLine = durationMs\n ? `\\n## Stats\\n- Questions: ${flat.length} · Duration: ${(durationMs / 1000).toFixed(1)}s`\n : ''\n\n const tips = `\\n---\\n💡 **Tips**\\n- Max questions: \\`maxQuestions: 100\\` (current: ${input.maxQuestions ?? 30})\\n- Organic results only: use \\`search_serp\\`\\n- Dig into a result: use \\`extract_url\\` on any organic URL`\n\n const full = `${DIRECTIVE_FULL}# PAA Report: \"${input.query}\"${input.location ? ` · ${input.location}` : ''}\\n\\n${paaTable}${serpTable}${entityIdsSection(entityIds)}${aiSection}${statsLine}${tips}`\n\n const topQ = flat.slice(0, 10).map((r, i) => `${i + 1}. ${r.question}`).join('\\n')\n const topO = organic.slice(0, 5).map(r => `${r.position}. [${r.title}](${r.url}) — ${r.domain}`).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**PAA: \"${input.query}\"** — ${flat.length} questions extracted`,\n topQ ? `\\n**Top questions:**\\n${topQ}` : '',\n organic.length ? `\\n**Top organic results:**\\n${topO}` : '',\n entityIdsSummaryLine(entityIds),\n `\\n💡 \\`maxQuestions\\` up to 100 ·Use \\`extract_url\\` to dig into any result`,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface LocalBusiness { position: number; name: string; rating?: string | null; reviewCount?: string | null; websiteUrl?: string | null }\n\nexport function formatSearchSerp(\n raw: CallToolResult,\n input: { query: string; location?: string },\n): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data\n\n const organic = (d.organicResults as OrganicResult[]) ?? []\n const localPack = (d.localPack as LocalBusiness[]) ?? []\n const entityIds = d.entityIds as { kgIds?: string[]; cids?: string[]; gcids?: string[] } | undefined\n const aiOvw = d.aiOverview as AIOverview | undefined\n\n const serpRows = organic.map(r =>\n `| ${r.position} | ${r.title} | [${r.domain}](${r.url}) | ${truncate(r.snippet, 100)} |`,\n ).join('\\n')\n\n const serpTable = organic.length\n ? `## Organic Results (${organic.length})\\n| # | Title | URL | Snippet |\\n|---|-------|-----|----------|\\n${serpRows}`\n : '## Organic Results\\n*None found*'\n\n const localRows = localPack.map(b =>\n `| ${b.position} | ${b.name} | ${b.rating ?? '—'} (${b.reviewCount ?? '0'}) | ${b.websiteUrl ? `[link](${b.websiteUrl})` : '—'} |`,\n ).join('\\n')\n\n const localSection = localPack.length\n ? `\\n## Local Pack (${localPack.length})\\n| # | Name | Rating | Website |\\n|---|------|--------|---------|\\n${localRows}`\n : ''\n\n const aiSection = aiOvw?.detected && aiOvw.text\n ? `\\n## AI Overview\\n> ${truncate(aiOvw.text, 600)}`\n : ''\n\n const tips = `\\n---\\n💡 **Tips**\\n- Get PAA questions: use \\`harvest_paa\\` for this query\\n- Scrape any result: use \\`extract_url\\`\\n- Business entity IDs (CID/GCID/KG MID) shown above if found`\n\n const full = `${DIRECTIVE_FULL}# SERP Report: \"${input.query}\"${input.location ? ` · ${input.location}` : ''}\\n\\n${serpTable}${localSection}${entityIdsSection(entityIds)}${aiSection}${tips}`\n\n const topO = organic.slice(0, 5).map(r => `${r.position}. [${r.title}](${r.url}) — ${r.domain}`).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**SERP: \"${input.query}\"** — ${organic.length} organic results`,\n topO ? `\\n**Top results:**\\n${topO}` : '',\n localPack.length ? `\\n**Local Pack:** ${localPack.map(b => b.name).join(', ')}` : '',\n entityIdsSummaryLine(entityIds),\n `\\n💡 Use \\`harvest_paa\\` for questions · \\`extract_url\\` to scrape any result`,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface Heading { level: number; text: string }\ninterface KpoResult {\n entityName?: string | null; type?: string[]; napScore?: number\n address?: string | null; phone?: string | null; email?: string | null\n sameAs?: string[]; missingFields?: string[]; faqCount?: number\n}\n\nexport function formatExtractUrl(raw: CallToolResult, input: { url: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data\n\n const url = (d.url as string) ?? input.url\n const title = (d.title as string | null) ?? 'Untitled'\n const headings = (d.headings as Heading[]) ?? []\n const kpo = d.kpo as KpoResult | undefined\n const bodyMd = (d.bodyMarkdown as string | null) ?? ''\n const schema = d.schema as unknown[]\n\n const h1Lines = headings.filter(h => h.level === 1).map(h => `- ${h.text}`).join('\\n')\n const h2Lines = headings.filter(h => h.level === 2).map(h => ` - ${h.text}`).join('\\n')\n const headingSection = (h1Lines || h2Lines)\n ? `\\n## Heading Structure\\n${[h1Lines, h2Lines].filter(Boolean).join('\\n')}`\n : ''\n\n const kpoSection = kpo ? [\n `\\n## Entity / Schema`,\n kpo.entityName ? `- **Entity:** ${kpo.entityName}` : '',\n kpo.type?.length ? `- **@type:** ${kpo.type.join(', ')}` : '',\n kpo.napScore !== undefined ? `- **NAP Score:** ${kpo.napScore}/5` : '',\n kpo.address ? `- **Address:** ${kpo.address}` : '',\n kpo.phone ? `- **Phone:** ${kpo.phone}` : '',\n kpo.email ? `- **Email:** ${kpo.email}` : '',\n kpo.faqCount ? `- **FAQ items:** ${kpo.faqCount}` : '',\n kpo.sameAs?.length ? `- **sameAs:** ${kpo.sameAs.slice(0, 5).join(', ')}` : '',\n kpo.missingFields?.length ? `\\n**Missing schema fields:** ${kpo.missingFields.slice(0, 5).join(', ')}` : '',\n ].filter(Boolean).join('\\n') : ''\n\n const bodySection = bodyMd\n ? `\\n## Page Content\\n${bodyMd.slice(0, 3000)}${bodyMd.length > 3000 ? '\\n\\n*(truncated)*' : ''}`\n : ''\n\n const schemaCount = Array.isArray(schema) ? schema.length : 0\n const tips = `\\n---\\n💡 **Tips**\\n- Crawl entire site: use \\`extract_site\\`\\n- Map all URLs: use \\`map_site_urls\\`\\n- ${schemaCount} JSON-LD schema block(s) detected`\n\n const full = `${DIRECTIVE_FULL}# URL Extract: ${url}\\n**${title}**\\n${headingSection}${kpoSection}${bodySection}${tips}`\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**Extracted:** ${title}`,\n `**URL:** ${url}`,\n kpo?.entityName ? `**Entity:** ${kpo.entityName} (${kpo.type?.join(', ') ?? 'unknown'})` : '',\n kpo?.napScore !== undefined ? `**NAP Score:** ${kpo.napScore}/5` : '',\n headings.length ? `**${headings.length} headings**` : '',\n `\\n💡 Use \\`extract_site\\` to crawl the full domain`,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface DiscoveredUrl { url: string; status: number | null }\ninterface SpiderResult { startUrl: string; urls: DiscoveredUrl[]; totalFound: number; durationMs: number; truncated: boolean }\n\nexport function formatMapSiteUrls(raw: CallToolResult, input: { url: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as unknown as SpiderResult\n\n const urls = d.urls ?? []\n const ok = urls.filter(u => (u.status ?? 0) >= 200 && (u.status ?? 0) < 300)\n const broken = urls.filter(u => u.status !== null && u.status >= 400)\n const redirects = urls.filter(u => u.status !== null && u.status >= 300 && u.status < 400)\n\n const urlRows = urls.slice(0, 200).map((u, i) => `| ${i + 1} | ${u.url} | ${u.status ?? '—'} |`).join('\\n')\n\n const full = [\n `${DIRECTIVE_FULL}# URL Map: ${input.url}`,\n `**${d.totalFound} URLs** · ${(d.durationMs / 1000).toFixed(1)}s${d.truncated ? ' · *truncated*' : ''}`,\n `\\n## Summary\\n- ✅ 2xx: ${ok.length}\\n- 🔀 3xx: ${redirects.length}\\n- ❌ 4xx+: ${broken.length}`,\n `\\n## URL Inventory\\n| # | URL | Status |\\n|---|-----|--------|\\n${urlRows}`,\n broken.length ? `\\n## Broken URLs\\n${broken.map(u => `- ${u.url} (${u.status})`).join('\\n')}` : '',\n `\\n---\\n💡 **Tips**\\n- Extract content from all pages: use \\`extract_site\\`\\n- Scrape a single page: use \\`extract_url\\``,\n ].filter(Boolean).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**URL Map: ${input.url}**`,\n `${d.totalFound} URLs — ${ok.length} OK · ${broken.length} broken · ${redirects.length} redirects`,\n broken.length ? `\\n**Broken URLs:** ${broken.slice(0, 3).map(u => u.url).join(', ')}` : '',\n `\\n💡 Use \\`extract_site\\` to extract content from all pages`,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface SitePageResult { url: string; title?: string | null; kpo?: KpoResult; schema?: unknown[] }\ninterface ExtractSiteResult { pages: SitePageResult[]; durationMs?: number }\n\nexport function formatExtractSite(raw: CallToolResult, input: { url: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as unknown as ExtractSiteResult\n\n const pages = d.pages ?? []\n\n const pageRows = pages.map((p, i) => {\n const schemaInfo = p.kpo?.type?.join(', ') ?? (Array.isArray(p.schema) && p.schema.length ? `${p.schema.length} block(s)` : '—')\n return `| ${i + 1} | ${p.title ?? 'Untitled'} | ${p.url} | ${schemaInfo} |`\n }).join('\\n')\n\n const full = [\n `${DIRECTIVE_FULL}# Site Extract: ${input.url}`,\n `**${pages.length} pages** · ${(((d.durationMs ?? 0)) / 1000).toFixed(1)}s`,\n `\\n## Pages\\n| # | Title | URL | Schema |\\n|---|-------|-----|--------|\\n${pageRows}`,\n `\\n---\\n💡 **Tips**\\n- Map URLs first: use \\`map_site_urls\\`\\n- Inspect a single page: use \\`extract_url\\``,\n ].join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**Site Extract: ${input.url}** — ${pages.length} pages`,\n pages.slice(0, 5).map(p => `- ${p.title ?? p.url}`).join('\\n'),\n pages.length > 5 ? `- … and ${pages.length - 5} more` : '',\n `\\n💡 Use \\`extract_url\\` to inspect any individual page`,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface YTVideo { videoId: string; title: string; channelName: string; views?: string | null; duration?: string | null; url: string }\ninterface YTHarvestResult { videos: YTVideo[]; channelMeta?: { title?: string; subscriberCount?: string | null } | null; stats: { durationMs: number } }\n\nexport function formatYoutubeHarvest(\n raw: CallToolResult,\n input: { mode: string; query?: string; channelHandle?: string },\n): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as unknown as YTHarvestResult\n\n const videos = d.videos ?? []\n const label = input.mode === 'channel' ? (input.channelHandle ?? 'channel') : `\"${input.query ?? ''}\"`\n\n const videoRows = videos.map((v, i) =>\n `| ${i + 1} | ${truncate(v.title, 70)} | ${v.channelName} | ${v.views ?? '—'} | ${v.duration ?? '—'} | \\`${v.videoId}\\` |`,\n ).join('\\n')\n\n const channelSection = d.channelMeta\n ? `\\n## Channel\\n- **Name:** ${d.channelMeta.title ?? '—'}\\n- **Subscribers:** ${d.channelMeta.subscriberCount ?? '—'}`\n : ''\n\n const full = [\n `${DIRECTIVE_FULL}# YouTube Harvest: ${label}`,\n `**${videos.length} videos** · ${(d.stats.durationMs / 1000).toFixed(1)}s`,\n channelSection,\n `\\n## Videos\\n| # | Title | Channel | Views | Duration | Video ID |\\n|---|-------|---------|-------|----------|----------|\\n${videoRows}`,\n `\\n---\\n💡 **Tips**\\n- Transcribe a video: use \\`youtube_transcribe\\` with the \\`videoId\\` above\\n- Switch mode: \\`mode: \"channel\"\\` with \\`channelHandle\\` or \\`mode: \"search\"\\` with \\`query\\``,\n ].filter(Boolean).join('\\n')\n\n const top5 = videos.slice(0, 5).map((v, i) => `${i + 1}. ${v.title} (\\`${v.videoId}\\`)`).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**YouTube: ${label}** — ${videos.length} videos`,\n `\\n**Top videos:**\\n${top5}`,\n `\\n💡 Transcribe any video: \\`youtube_transcribe\\` with its videoId`,\n ].join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface TranscriptChunk { startMs: number; text: string }\ninterface TranscriptResult { text: string; chunks?: TranscriptChunk[]; durationMs?: number }\n\nexport function formatYoutubeTranscribe(raw: CallToolResult, input: { videoId: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as unknown as TranscriptResult\n\n const text = d.text ?? ''\n const chunks = d.chunks ?? []\n const durSec = d.durationMs ? (d.durationMs / 1000).toFixed(0) : '—'\n\n const chunkRows = chunks.slice(0, 50).map(c => {\n const sec = Math.floor(c.startMs / 1000)\n const mm = String(Math.floor(sec / 60)).padStart(2, '0')\n const ss = String(sec % 60).padStart(2, '0')\n return `| ${mm}:${ss} | ${truncate(c.text, 120)} |`\n }).join('\\n')\n\n const full = [\n `${DIRECTIVE_FULL}# YouTube Transcript: \\`${input.videoId}\\``,\n `**Duration:** ${durSec}s · **${text.split(' ').length} words**`,\n `\\n## Full Transcript\\n${text}`,\n chunks.length ? `\\n## Timestamped Chunks\\n| Time | Text |\\n|------|------|\\n${chunkRows}` : '',\n `\\n---\\n💡 Harvest more from this channel: use \\`youtube_harvest\\` with \\`mode: \"channel\"\\``,\n ].filter(Boolean).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**YouTube Transcript: \\`${input.videoId}\\`** — ${text.split(' ').length} words · ${durSec}s`,\n `\\n**Preview:**\\n> ${truncate(text, 300)}`,\n `\\n💡 Full transcript in artifact above`,\n ].join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface FbAd {\n libraryId?: string; status?: string; creativeType?: string\n headline?: string | null; primaryText?: string | null; cta?: string | null\n startDate?: string | null; videoUrl?: string | null; variations?: number\n}\ninterface FbPageResult {\n advertiserName?: string | null\n summary: { totalAds: number; activeCount: number; videoCount: number; imageCount: number }\n ads: FbAd[]\n}\n\nexport function formatFacebookPageIntel(\n raw: CallToolResult,\n input: { pageId?: string; libraryId?: string; query?: string },\n): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as unknown as FbPageResult\n\n const advertiser = d.advertiserName ?? input.query ?? input.pageId ?? input.libraryId ?? 'Advertiser'\n const ads = d.ads ?? []\n const s = d.summary ?? { totalAds: 0, activeCount: 0, videoCount: 0, imageCount: 0 }\n\n const adBlocks = ads.map((ad, i) => [\n `### Ad ${i + 1}${ad.libraryId ? ` · \\`${ad.libraryId}\\`` : ''} — ${ad.status ?? '—'} · ${ad.creativeType ?? '—'} · ${ad.startDate ?? '—'}`,\n ad.headline ? `**Headline:** ${ad.headline}` : '',\n ad.primaryText ? `**Copy:** ${truncate(ad.primaryText, 200)}` : '',\n ad.cta ? `**CTA:** ${ad.cta}` : '',\n ad.videoUrl ? `**Video URL:** \\`${ad.videoUrl}\\`` : '',\n ad.variations ? `**Variations:** ${ad.variations}` : '',\n ].filter(Boolean).join('\\n')).join('\\n\\n---\\n\\n')\n\n const full = [\n `${DIRECTIVE_FULL}# Facebook Ad Intel: ${advertiser}`,\n `**${s.totalAds} ads** · ${s.activeCount} active · ${s.videoCount} video · ${s.imageCount} image`,\n `\\n${adBlocks}`,\n `\\n---\\n💡 **Tips**\\n- Transcribe video ads: use \\`facebook_ad_transcribe\\` with the \\`videoUrl\\` above\\n- Find other advertisers: use \\`facebook_ad_search\\``,\n ].filter(Boolean).join('\\n')\n\n const activeAds = ads.filter(a => a.status?.toLowerCase() === 'active').slice(0, 5)\n const adSummary = activeAds.map((a, i) => `${i + 1}. ${truncate(a.headline ?? a.primaryText, 80)} (${a.creativeType ?? '—'})`).join('\\n')\n const videoCount = ads.filter(a => a.videoUrl).length\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**Facebook Ads: ${advertiser}** — ${s.totalAds} ads (${s.activeCount} active)`,\n adSummary ? `\\n**Active ads:**\\n${adSummary}` : '',\n `**Creative mix:** ${s.videoCount} video · ${s.imageCount} image`,\n videoCount ? `\\n💡 ${videoCount} video ads — transcribe with \\`facebook_ad_transcribe\\` using the videoUrl` : '',\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface FbAdvertiserResult { name: string; adCount?: number; libraryId?: string }\ninterface FbSearchResult { results?: FbAdvertiserResult[]; advertisers?: FbAdvertiserResult[] }\n\nexport function formatFacebookAdSearch(raw: CallToolResult, input: { query: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as unknown as FbSearchResult\n\n const advertisers = d.results ?? d.advertisers ?? []\n\n const rows = advertisers.map((a, i) =>\n `| ${i + 1} | ${a.name} | ${a.adCount ?? '—'} | \\`${a.libraryId ?? '—'}\\` |`,\n ).join('\\n')\n\n const full = [\n `${DIRECTIVE_FULL}# Facebook Ad Library Search: \"${input.query}\"`,\n `**${advertisers.length} advertisers found**`,\n `\\n## Advertisers\\n| # | Name | Ad Count | Library ID |\\n|---|------|----------|------------|\\n${rows}`,\n `\\n---\\n💡 **Tips**\\n- Scan all ads: use \\`facebook_page_intel\\` with \\`libraryId\\`\\n- Or pass the advertiser name as \\`query\\` in \\`facebook_page_intel\\``,\n ].join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**Facebook Ad Search: \"${input.query}\"** — ${advertisers.length} advertisers`,\n advertisers.slice(0, 5).map((a, i) =>\n `${i + 1}. ${a.name}${a.adCount ? ` (${a.adCount} ads)` : ''} — \\`${a.libraryId ?? '—'}\\``,\n ).join('\\n'),\n `\\n💡 Scan ads with \\`facebook_page_intel\\` using \\`libraryId\\``,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\ninterface MapsReviewCard { author: string | null; stars: string | null; date: string | null; text: string | null }\ninterface MapsHistogramEntry { stars: number; count: string }\ninterface MapsTopicEntry { label: string; count: string }\ninterface MapsAboutEntry { section: string; attribute: string }\ninterface CreditCostEntry { key: string; label: string; credits: number; unit: string; notes?: string }\ninterface CreditLedgerEntry { amount_mc: number; operation: string; description: string | null; created_at: string }\n\nexport function formatCreditsInfo(raw: CallToolResult, input: { item?: string; includeLedger?: boolean }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as Record<string, unknown>\n\n const balance = d.balance_credits as number | undefined\n const costs = (d.costs as CreditCostEntry[] | undefined) ?? []\n const matched = d.matched_cost as CreditCostEntry | null\n const ledger = (d.ledger as CreditLedgerEntry[] | undefined) ?? []\n\n const costRows = costs.map(c => {\n const notes = c.notes ? ` ${c.notes}` : ''\n return `| ${c.label} | ${c.credits} | ${c.unit}${notes} |`\n }).join('\\n')\n\n const ledgerRows = ledger.map(row => {\n const credits = row.amount_mc / 1000\n return `| ${row.created_at} | ${row.operation} | ${credits} | ${row.description ?? ''} |`\n }).join('\\n')\n\n const matchedSection = matched\n ? `\\n## Matched Cost\\n**${matched.label}:** ${matched.credits} credits ${matched.unit}${matched.notes ? `\\n\\n${matched.notes}` : ''}`\n : input.item\n ? `\\n## Matched Cost\\nNo exact cost match found for \"${input.item}\". See the full cost table below.`\n : ''\n\n const full = [\n `${DIRECTIVE_FULL}# Credits`,\n `**Balance:** ${balance ?? 'unknown'} credits`,\n matchedSection,\n costs.length ? `\\n## Cost Table\\n| Item | Credits | Unit |\\n|------|---------|------|\\n${costRows}` : '',\n ledger.length ? `\\n## Recent Ledger\\n| Date | Operation | Credits | Description |\\n|------|-----------|---------|-------------|\\n${ledgerRows}` : '',\n ].filter(Boolean).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**Credit balance:** ${balance ?? 'unknown'} credits`,\n matched ? `\\n**${matched.label}:** ${matched.credits} credits ${matched.unit}` : null,\n input.includeLedger && ledger.length ? `\\nRecent ledger entries included in the full report.` : null,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\nexport function formatMapsPlaceIntel(\n raw: CallToolResult,\n input: { businessName: string; location: string; includeReviews?: boolean },\n): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as Record<string, unknown>\n\n const name = (d.name as string | null) ?? input.businessName\n const rating = d.rating as string | null\n const reviewCount = d.reviewCount as string | null\n const category = d.category as string | null\n const address = d.address as string | null\n const phone = d.phoneDisplay as string | null\n const website = d.website as string | null\n const hoursSummary = d.hoursSummary as string | null\n const plusCode = d.plusCode as string | null\n const bookingUrl = d.bookingUrl as string | null\n const kgmid = d.kgmid as string | null\n const cidDecimal = d.cidDecimal as string | null\n const cidUrl = d.cidUrl as string | null\n const lat = d.lat as number | null\n const lng = d.lng as number | null\n const durationMs = d.durationMs as number | null\n\n const histogram = (d.reviewHistogram as MapsHistogramEntry[]) ?? []\n const topics = (d.reviewTopics as MapsTopicEntry[]) ?? []\n const about = (d.aboutAttributes as MapsAboutEntry[]) ?? []\n const reviews = (d.reviews as MapsReviewCard[]) ?? []\n\n const hoursTable = (d.hoursTable as Array<{ day: string; hours: string }>) ?? []\n\n const ratingLine = [rating, reviewCount ? `(${reviewCount} reviews)` : null].filter(Boolean).join(' ')\n\n const basicLines = [\n address ? `- **Address:** ${address}` : null,\n phone ? `- **Phone:** ${phone}` : null,\n website ? `- **Website:** ${website}` : null,\n hoursSummary ? `- **Hours:** ${hoursSummary}` : null,\n plusCode ? `- **Plus Code:** ${plusCode}` : null,\n bookingUrl ? `- **Book:** ${bookingUrl}` : null,\n ].filter(Boolean).join('\\n')\n\n const hoursSection = hoursTable.length\n ? `\\n## Hours\\n| Day | Hours |\\n|-----|-------|\\n${hoursTable.map(r => `| ${r.day} | ${r.hours} |`).join('\\n')}`\n : ''\n\n const histSection = histogram.length\n ? `\\n## Rating Distribution\\n| Stars | Count |\\n|-------|-------|\\n${histogram.map(r => `| ${'★'.repeat(r.stars)}${'☆'.repeat(5 - r.stars)} | ${r.count} |`).join('\\n')}`\n : ''\n\n const topicsSection = topics.length\n ? `\\n## Review Topics\\n${topics.map(t => `- **${t.label}:** ${t.count} mentions`).join('\\n')}`\n : ''\n\n const aboutBySection: Record<string, string[]> = {}\n for (const a of about) {\n if (!aboutBySection[a.section]) aboutBySection[a.section] = []\n aboutBySection[a.section].push(a.attribute)\n }\n const aboutSection = Object.keys(aboutBySection).length\n ? `\\n## About\\n${Object.entries(aboutBySection).map(([s, attrs]) => `**${s}**\\n${attrs.map(a => `- ${a}`).join('\\n')}`).join('\\n\\n')}`\n : ''\n\n const entitySection = [\n kgmid ? `- **KGMID:** \\`${kgmid}\\`` : null,\n cidDecimal ? `- **CID:** \\`${cidDecimal}\\`` : null,\n cidUrl ? `- **Maps CID URL:** ${cidUrl}` : null,\n lat != null && lng != null ? `- **Coordinates:** ${lat}, ${lng}` : null,\n ].filter(Boolean).join('\\n')\n\n const reviewsSection = reviews.length\n ? `\\n## Reviews (${reviews.length})\\n${reviews.map((r, i) => {\n const starsN = parseInt(r.stars ?? '0')\n const stars = '★'.repeat(starsN) + '☆'.repeat(5 - starsN)\n return `### ${i + 1}. ${r.author ?? 'Anonymous'} — ${stars}\\n*${r.date ?? ''}*\\n\\n${r.text ?? ''}`\n }).join('\\n\\n')}`\n : ''\n\n const full = [\n `${DIRECTIVE_FULL}# ${name}`,\n category ? `*${category}*` : null,\n ratingLine ? `\\n**Rating:** ${ratingLine}` : null,\n basicLines ? `\\n${basicLines}` : null,\n hoursSection,\n histSection,\n topicsSection,\n aboutSection,\n entitySection ? `\\n## Entity IDs\\n${entitySection}` : null,\n reviewsSection,\n durationMs != null ? `\\n---\\n*Extracted in ${(durationMs / 1000).toFixed(1)}s*` : null,\n ].filter(Boolean).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**${name}** — ${category ?? 'Business'} · ${ratingLine || 'No rating'}`,\n address ? `📍 ${address}` : null,\n phone ? `📞 ${phone}` : null,\n hoursSummary ? `🕐 ${hoursSummary}` : null,\n website ? `🌐 ${website}` : null,\n reviews.length ? `\\n💬 ${reviews.length} reviews fetched — full list in artifact above` : null,\n ].filter(Boolean).join('\\n')\n\n return twoBlocks(full, summary)\n}\n\nexport function formatFacebookAdTranscribe(raw: CallToolResult, input: { videoUrl: string }): CallToolResult {\n const parsed = parseData(raw)\n if ('error' in parsed) return { content: [{ type: 'text', text: parsed.error }], isError: true }\n const d = parsed.data as unknown as TranscriptResult\n\n const text = d.text ?? ''\n const chunks = d.chunks ?? []\n const durSec = d.durationMs ? (d.durationMs / 1000).toFixed(0) : '—'\n\n const chunkRows = chunks.slice(0, 50).map(c => {\n const sec = Math.floor(c.startMs / 1000)\n const mm = String(Math.floor(sec / 60)).padStart(2, '0')\n const ss = String(sec % 60).padStart(2, '0')\n return `| ${mm}:${ss} | ${truncate(c.text, 120)} |`\n }).join('\\n')\n\n const full = [\n `${DIRECTIVE_FULL}# Facebook Ad Transcript`,\n `**Duration:** ${durSec}s · **${text.split(' ').length} words**`,\n `\\n## Full Transcript\\n${text}`,\n chunks.length ? `\\n## Timestamped Chunks\\n| Time | Text |\\n|------|------|\\n${chunkRows}` : '',\n `\\n---\\n💡 Get more ads from this advertiser: use \\`facebook_page_intel\\``,\n ].filter(Boolean).join('\\n')\n\n const summary = [\n `${DIRECTIVE_SUMMARY}**Facebook Ad Transcript** — ${text.split(' ').length} words · ${durSec}s`,\n `\\n**Preview:**\\n> ${truncate(text, 300)}`,\n `\\n💡 Full transcript in artifact above`,\n ].join('\\n')\n\n return twoBlocks(full, summary)\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { IMcpToolExecutor } from './IMcpToolExecutor.js'\nimport type {\n HarvestPaaInput,\n SearchSerpInput,\n ExtractUrlInput,\n MapSiteUrlsInput,\n ExtractSiteInput,\n YoutubeHarvestInput,\n YoutubeTranscribeInput,\n FacebookPageIntelInput,\n FacebookAdSearchInput,\n FacebookAdTranscribeInput,\n MapsPlaceIntelInput,\n CreditsInfoInput,\n} from './mcp-tool-schemas.js'\n\nexport class HttpMcpToolExecutor implements IMcpToolExecutor {\n private readonly baseUrl: string\n private readonly apiKey: string\n\n constructor(baseUrl: string, apiKey: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n this.apiKey = apiKey\n }\n\n private async call(path: string, body: Record<string, unknown>): Promise<CallToolResult> {\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(290_000),\n })\n const data = await res.json()\n if (!res.ok) {\n return { content: [{ type: 'text', text: JSON.stringify(data) }], isError: true }\n }\n return { content: [{ type: 'text', text: JSON.stringify(data) }] }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n return { content: [{ type: 'text', text: msg }], isError: true }\n }\n }\n\n harvestPaa(input: HarvestPaaInput): Promise<CallToolResult> {\n return this.call('/harvest/sync', input as Record<string, unknown>)\n }\n\n searchSerp(input: SearchSerpInput): Promise<CallToolResult> {\n return this.call('/harvest/sync', { ...input, serpOnly: true } as Record<string, unknown>)\n }\n\n extractUrl(input: ExtractUrlInput): Promise<CallToolResult> {\n return this.call('/extract-url', input as Record<string, unknown>)\n }\n\n mapSiteUrls(input: MapSiteUrlsInput): Promise<CallToolResult> {\n return this.call('/map-urls', input as Record<string, unknown>)\n }\n\n extractSite(input: ExtractSiteInput): Promise<CallToolResult> {\n return this.call('/extract-site', input as Record<string, unknown>)\n }\n\n youtubeHarvest(input: YoutubeHarvestInput): Promise<CallToolResult> {\n return this.call('/youtube/harvest', input as Record<string, unknown>)\n }\n\n youtubeTranscribe(input: YoutubeTranscribeInput): Promise<CallToolResult> {\n return this.call('/youtube/transcribe', input as Record<string, unknown>)\n }\n\n facebookPageIntel(input: FacebookPageIntelInput): Promise<CallToolResult> {\n return this.call('/facebook/page-intel', input as Record<string, unknown>)\n }\n\n facebookAdSearch(input: FacebookAdSearchInput): Promise<CallToolResult> {\n return this.call('/facebook/search', input as Record<string, unknown>)\n }\n\n facebookAdTranscribe(input: FacebookAdTranscribeInput): Promise<CallToolResult> {\n return this.call('/facebook/transcribe', input as Record<string, unknown>)\n }\n\n mapsPlaceIntel(input: MapsPlaceIntelInput): Promise<CallToolResult> {\n return this.call('/maps/place', input as Record<string, unknown>)\n }\n\n creditsInfo(input: CreditsInfoInput): Promise<CallToolResult> {\n return this.call('/billing/credits', input as Record<string, unknown>)\n }\n}\n"],"mappings":"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","names":[]}
|