mcp-scraper 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +56 -0
  2. package/dist/bin/api-server.cjs +9256 -0
  3. package/dist/bin/api-server.cjs.map +1 -0
  4. package/dist/bin/api-server.d.cts +1 -0
  5. package/dist/bin/api-server.d.ts +1 -0
  6. package/dist/bin/api-server.js +38 -0
  7. package/dist/bin/api-server.js.map +1 -0
  8. package/dist/bin/mcp-stdio-server.cjs +840 -0
  9. package/dist/bin/mcp-stdio-server.cjs.map +1 -0
  10. package/dist/bin/mcp-stdio-server.d.cts +1 -0
  11. package/dist/bin/mcp-stdio-server.d.ts +1 -0
  12. package/dist/bin/mcp-stdio-server.js +41 -0
  13. package/dist/bin/mcp-stdio-server.js.map +1 -0
  14. package/dist/bin/paa-harvest.cjs +1438 -0
  15. package/dist/bin/paa-harvest.cjs.map +1 -0
  16. package/dist/bin/paa-harvest.d.cts +1 -0
  17. package/dist/bin/paa-harvest.d.ts +1 -0
  18. package/dist/bin/paa-harvest.js +37 -0
  19. package/dist/bin/paa-harvest.js.map +1 -0
  20. package/dist/chunk-4API3ZCT.js +1387 -0
  21. package/dist/chunk-4API3ZCT.js.map +1 -0
  22. package/dist/chunk-LXZDJJXR.js +476 -0
  23. package/dist/chunk-LXZDJJXR.js.map +1 -0
  24. package/dist/chunk-ZBP4RHNW.js +805 -0
  25. package/dist/chunk-ZBP4RHNW.js.map +1 -0
  26. package/dist/db-IOYMX64U.js +87 -0
  27. package/dist/db-IOYMX64U.js.map +1 -0
  28. package/dist/index.cjs +1689 -0
  29. package/dist/index.cjs.map +1 -0
  30. package/dist/index.d.cts +210 -0
  31. package/dist/index.d.ts +210 -0
  32. package/dist/index.js +275 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/server-63DR2HE5.js +6062 -0
  35. package/dist/server-63DR2HE5.js.map +1 -0
  36. package/dist/worker-3ECJHPRE.js +88 -0
  37. package/dist/worker-3ECJHPRE.js.map +1 -0
  38. package/package.json +76 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/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":";AAAA,SAAS,iBAAiB;;;ACA1B,SAAS,SAAS;AAEX,IAAM,wBAAwB;AAAA,EACnC,OAAc,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,2CAA2C;AAAA,EACpF,UAAc,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,wCAAwC;AAAA,EACrF,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS,8CAA8C;AAAA,EAClH,IAAc,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EAC/C,IAAc,EAAE,OAAO,EAAE,QAAQ,IAAI;AACvC;AAGO,IAAM,wBAAwB;AAAA,EACnC,KAAK,EAAE,OAAO,EAAE,IAAI;AACtB;AAGO,IAAM,yBAAyB;AAAA,EACpC,KAAS,EAAE,OAAO,EAAE,IAAI;AAAA,EACxB,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AACrD;AAGO,IAAM,yBAAyB;AAAA,EACpC,KAAU,EAAE,OAAO,EAAE,IAAI;AAAA,EACzB,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS;AACrD;AAGO,IAAM,4BAA4B;AAAA,EACvC,MAAe,EAAE,KAAK,CAAC,UAAU,SAAS,CAAC;AAAA,EAC3C,OAAe,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,8BAA8B;AAAA,EAC5E,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qCAAqC;AAAA,EACnF,WAAe,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE;AAC5D;AAGO,IAAM,+BAA+B;AAAA,EAC1C,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,oCAAoC;AAC1E;AAGO,IAAM,+BAA+B;AAAA,EAC1C,QAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,OAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,gDAAgD;AAAA,EAC1F,QAAW,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE;AAAA,EACtD,SAAW,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAC9C;AAGO,IAAM,8BAA8B;AAAA,EACzC,OAAY,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC5B,SAAY,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EAC7C,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE;AACxD;AAGO,IAAM,kCAAkC;AAAA,EAC7C,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,0DAA0D;AAChG;AAGO,IAAM,4BAA4B;AAAA,EACvC,cAAgB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,4CAA4C;AAAA,EACvF,UAAgB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,mCAAmC;AAAA,EAC9E,IAAgB,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EACjD,IAAgB,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EACjD,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,0CAA0C;AAAA,EAC9F,YAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS,4DAA4D;AACpI;AAGO,IAAM,yBAAyB;AAAA,EACpC,MAAe,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,8GAA8G;AAAA,EAC5J,eAAe,EAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,iDAAiD;AACtG;AAGO,IAAM,wBAAwB;AAAA,EACnC,OAAU,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,qDAAqD;AAAA,EAC1F,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,wCAAwC;AAAA,EACjF,IAAU,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,IAAI;AAAA,EAC3C,IAAU,EAAE,OAAO,EAAE,QAAQ,IAAI;AAAA,EACjC,OAAU,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,4CAAuC;AACtG;;;AClFA,SAAS,UAAU,MAAc,SAAiC;AAChE,SAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,GAAG,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC,EAAE;AACpF;AAwBA,SAAS,UAAU,KAA4E;AAC7F,QAAM,QAAQ,IAAI,QAAQ,KAAK,OAAK,EAAE,SAAS,MAAM;AACrD,QAAM,OAAQ,OAAO,SAAS,SAAS,MAAM,OAAO;AACpD,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,QAAQ,IAAI;AACtC,QAAI,OAAO,UAAU,wBAAwB;AAC3C,aAAO,EAAE,OAAO,kCAAkC,OAAO,eAAe,gCAAgC,OAAO,gBAAgB,uBAAuB,OAAO,SAAS,GAAG;AAAA,IAC3K;AACA,QAAI,IAAI,QAAS,QAAO,EAAE,OAAO,QAAQ,aAAa;AACtD,UAAM,OAAQ,OAAO,UAAsC;AAC3D,WAAO,EAAE,KAAK;AAAA,EAChB,QAAQ;AACN,QAAI,IAAI,QAAS,QAAO,EAAE,OAAO,QAAQ,aAAa;AACtD,WAAO,EAAE,OAAO,gCAAgC;AAAA,EAClD;AACF;AAEA,SAAS,iBAAiB,KAAuE;AAC/F,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,QAAkB,CAAC;AACzB,MAAI,IAAI,OAAO,OAAS,OAAM,KAAK,8BAA8B,IAAI,MAAM,KAAK,IAAI,CAAC,EAAE;AACvF,MAAI,IAAI,MAAM,OAAU,OAAM,KAAK,cAAc,IAAI,KAAK,KAAK,IAAI,CAAC,EAAE;AACtE,MAAI,IAAI,OAAO,OAAS,OAAM,KAAK,eAAe,IAAI,MAAM,KAAK,IAAI,CAAC,EAAE;AACxE,SAAO,MAAM,SAAS;AAAA;AAAA,EAAoB,MAAM,KAAK,IAAI,CAAC,KAAK;AACjE;AAEA,SAAS,qBAAqB,KAAuE;AACnG,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,QAAkB,CAAC;AACzB,MAAI,IAAI,OAAO,OAAS,OAAM,KAAK,WAAW,IAAI,MAAM,CAAC,CAAC,EAAE;AAC5D,MAAI,IAAI,MAAM,OAAU,OAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,CAAC,EAAE;AACxD,MAAI,IAAI,OAAO,OAAS,OAAM,KAAK,SAAS,IAAI,MAAM,CAAC,CAAC,EAAE;AAC1D,SAAO,MAAM,SAAS;AAAA,kBAAqB,MAAM,KAAK,QAAK,CAAC,KAAK;AACnE;AAEA,SAAS,SAAS,GAA8B,KAAqB;AACnE,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,EAAE,SAAS,MAAM,EAAE,MAAM,GAAG,GAAG,IAAI,WAAM;AAClD;AAEA,IAAM,iBAAoB;AAC1B,IAAM,oBAAoB;AAMnB,SAAS,iBACd,KACA,OACgB;AAChB,QAAM,SAAS,UAAU,GAAG;AAC5B,MAAI,WAAW,OAAQ,QAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,OAAO,MAAM,CAAC,GAAG,SAAS,KAAK;AAC/F,QAAM,IAAI,OAAO;AAEjB,QAAM,OAAa,EAAE,QAAsB,CAAC;AAC5C,QAAM,UAAa,EAAE,kBAAsC,CAAC;AAC5D,QAAM,YAAY,EAAE;AACpB,QAAM,QAAY,EAAE;AACpB,QAAM,aAAc,EAAE,OAA+C;AAErE,QAAM,UAAU,KAAK;AAAA,IAAI,CAAC,GAAG,MAC3B,KAAK,IAAI,CAAC,MAAM,EAAE,QAAQ,MAAM,SAAS,EAAE,QAAQ,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE;AAAA,EAClF,EAAE,KAAK,IAAI;AAEX,QAAM,WAAW,KAAK,SAClB,uBAAuB,KAAK,MAAM;AAAA;AAAA;AAAA,EAAwF,OAAO,KACjI;AAEJ,QAAM,WAAW,QAAQ;AAAA,IAAI,OAC3B,KAAK,EAAE,QAAQ,MAAM,EAAE,KAAK,OAAO,EAAE,MAAM,KAAK,EAAE,GAAG,OAAO,SAAS,EAAE,SAAS,GAAG,CAAC;AAAA,EACtF,EAAE,KAAK,IAAI;AAEX,QAAM,YAAY,QAAQ,SACtB;AAAA,sBAAyB,QAAQ,MAAM;AAAA;AAAA;AAAA,EAAqE,QAAQ,KACpH;AAEJ,QAAM,YAAY,OAAO,YAAY,MAAM,OACvC;AAAA;AAAA,IAAuB,SAAS,MAAM,MAAM,GAAG,CAAC,KAChD;AAEJ,QAAM,YAAY,aACd;AAAA;AAAA,eAA4B,KAAK,MAAM,oBAAiB,aAAa,KAAM,QAAQ,CAAC,CAAC,MACrF;AAEJ,QAAM,OAAO;AAAA;AAAA;AAAA,mDAAwE,MAAM,gBAAgB,EAAE;AAAA;AAAA;AAE7G,QAAM,OAAO,GAAG,cAAc,kBAAkB,MAAM,KAAK,IAAI,MAAM,WAAW,SAAM,MAAM,QAAQ,KAAK,EAAE;AAAA;AAAA,EAAO,QAAQ,GAAG,SAAS,GAAG,iBAAiB,SAAS,CAAC,GAAG,SAAS,GAAG,SAAS,GAAG,IAAI;AAEnM,QAAM,OAAO,KAAK,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,KAAK,IAAI;AACjF,QAAM,OAAO,QAAQ,MAAM,GAAG,CAAC,EAAE,IAAI,OAAK,GAAG,EAAE,QAAQ,MAAM,EAAE,KAAK,KAAK,EAAE,GAAG,YAAO,EAAE,MAAM,EAAE,EAAE,KAAK,IAAI;AAE1G,QAAM,UAAU;AAAA,IACd,GAAG,iBAAiB,WAAW,MAAM,KAAK,cAAS,KAAK,MAAM;AAAA,IAC9D,OAAO;AAAA;AAAA,EAAyB,IAAI,KAAK;AAAA,IACzC,QAAQ,SAAS;AAAA;AAAA,EAA+B,IAAI,KAAK;AAAA,IACzD,qBAAqB,SAAS;AAAA,IAC9B;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO,UAAU,MAAM,OAAO;AAChC;AAIO,SAAS,iBACd,KACA,OACgB;AAChB,QAAM,SAAS,UAAU,GAAG;AAC5B,MAAI,WAAW,OAAQ,QAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,OAAO,MAAM,CAAC,GAAG,SAAS,KAAK;AAC/F,QAAM,IAAI,OAAO;AAEjB,QAAM,UAAa,EAAE,kBAAsC,CAAC;AAC5D,QAAM,YAAa,EAAE,aAAiC,CAAC;AACvD,QAAM,YAAY,EAAE;AACpB,QAAM,QAAY,EAAE;AAEpB,QAAM,WAAW,QAAQ;AAAA,IAAI,OAC3B,KAAK,EAAE,QAAQ,MAAM,EAAE,KAAK,OAAO,EAAE,MAAM,KAAK,EAAE,GAAG,OAAO,SAAS,EAAE,SAAS,GAAG,CAAC;AAAA,EACtF,EAAE,KAAK,IAAI;AAEX,QAAM,YAAY,QAAQ,SACtB,uBAAuB,QAAQ,MAAM;AAAA;AAAA;AAAA,EAAqE,QAAQ,KAClH;AAEJ,QAAM,YAAY,UAAU;AAAA,IAAI,OAC9B,KAAK,EAAE,QAAQ,MAAM,EAAE,IAAI,MAAM,EAAE,UAAU,QAAG,KAAK,EAAE,eAAe,GAAG,OAAO,EAAE,aAAa,UAAU,EAAE,UAAU,MAAM,QAAG;AAAA,EAChI,EAAE,KAAK,IAAI;AAEX,QAAM,eAAe,UAAU,SAC3B;AAAA,iBAAoB,UAAU,MAAM;AAAA;AAAA;AAAA,EAAwE,SAAS,KACrH;AAEJ,QAAM,YAAY,OAAO,YAAY,MAAM,OACvC;AAAA;AAAA,IAAuB,SAAS,MAAM,MAAM,GAAG,CAAC,KAChD;AAEJ,QAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAEb,QAAM,OAAO,GAAG,cAAc,mBAAmB,MAAM,KAAK,IAAI,MAAM,WAAW,SAAM,MAAM,QAAQ,KAAK,EAAE;AAAA;AAAA,EAAO,SAAS,GAAG,YAAY,GAAG,iBAAiB,SAAS,CAAC,GAAG,SAAS,GAAG,IAAI;AAE5L,QAAM,OAAO,QAAQ,MAAM,GAAG,CAAC,EAAE,IAAI,OAAK,GAAG,EAAE,QAAQ,MAAM,EAAE,KAAK,KAAK,EAAE,GAAG,YAAO,EAAE,MAAM,EAAE,EAAE,KAAK,IAAI;AAE1G,QAAM,UAAU;AAAA,IACd,GAAG,iBAAiB,YAAY,MAAM,KAAK,cAAS,QAAQ,MAAM;AAAA,IAClE,OAAO;AAAA;AAAA,EAAuB,IAAI,KAAK;AAAA,IACvC,UAAU,SAAS;AAAA,kBAAqB,UAAU,IAAI,OAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC,KAAK;AAAA,IAClF,qBAAqB,SAAS;AAAA,IAC9B;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO,UAAU,MAAM,OAAO;AAChC;AASO,SAAS,iBAAiB,KAAqB,OAAwC;AAC5F,QAAM,SAAS,UAAU,GAAG;AAC5B,MAAI,WAAW,OAAQ,QAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,OAAO,MAAM,CAAC,GAAG,SAAS,KAAK;AAC/F,QAAM,IAAI,OAAO;AAEjB,QAAM,MAAY,EAAE,OAAkB,MAAM;AAC5C,QAAM,QAAY,EAAE,SAA2B;AAC/C,QAAM,WAAY,EAAE,YAA0B,CAAC;AAC/C,QAAM,MAAW,EAAE;AACnB,QAAM,SAAY,EAAE,gBAAkC;AACtD,QAAM,SAAW,EAAE;AAEnB,QAAM,UAAU,SAAS,OAAO,OAAK,EAAE,UAAU,CAAC,EAAE,IAAI,OAAK,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,IAAI;AACrF,QAAM,UAAU,SAAS,OAAO,OAAK,EAAE,UAAU,CAAC,EAAE,IAAI,OAAK,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,IAAI;AACvF,QAAM,iBAAkB,WAAW,UAC/B;AAAA;AAAA,EAA2B,CAAC,SAAS,OAAO,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,CAAC,KACxE;AAEJ,QAAM,aAAa,MAAM;AAAA,IACvB;AAAA;AAAA,IACA,IAAI,aAAa,iBAAiB,IAAI,UAAU,KAAK;AAAA,IACrD,IAAI,MAAM,SAAS,gBAAgB,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK;AAAA,IAC3D,IAAI,aAAa,SAAY,oBAAoB,IAAI,QAAQ,OAAO;AAAA,IACpE,IAAI,UAAU,kBAAkB,IAAI,OAAO,KAAK;AAAA,IAChD,IAAI,QAAQ,gBAAgB,IAAI,KAAK,KAAK;AAAA,IAC1C,IAAI,QAAQ,gBAAgB,IAAI,KAAK,KAAK;AAAA,IAC1C,IAAI,WAAW,oBAAoB,IAAI,QAAQ,KAAK;AAAA,IACpD,IAAI,QAAQ,SAAS,iBAAiB,IAAI,OAAO,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,KAAK;AAAA,IAC5E,IAAI,eAAe,SAAS;AAAA,6BAAgC,IAAI,cAAc,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,KAAK;AAAA,EAC3G,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,IAAI;AAE/B,QAAM,cAAc,SAChB;AAAA;AAAA,EAAsB,OAAO,MAAM,GAAG,GAAI,CAAC,GAAG,OAAO,SAAS,MAAO,sBAAsB,EAAE,KAC7F;AAEJ,QAAM,cAAc,MAAM,QAAQ,MAAM,IAAI,OAAO,SAAS;AAC5D,QAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,IAA2G,WAAW;AAEnI,QAAM,OAAO,GAAG,cAAc,kBAAkB,GAAG;AAAA,IAAO,KAAK;AAAA,EAAO,cAAc,GAAG,UAAU,GAAG,WAAW,GAAG,IAAI;AAEtH,QAAM,UAAU;AAAA,IACd,GAAG,iBAAiB,kBAAkB,KAAK;AAAA,IAC3C,YAAY,GAAG;AAAA,IACf,KAAK,aAAa,eAAe,IAAI,UAAU,KAAK,IAAI,MAAM,KAAK,IAAI,KAAK,SAAS,MAAM;AAAA,IAC3F,KAAK,aAAa,SAAY,kBAAkB,IAAI,QAAQ,OAAO;AAAA,IACnE,SAAS,SAAS,KAAK,SAAS,MAAM,gBAAgB;AAAA,IACtD;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO,UAAU,MAAM,OAAO;AAChC;AAKO,SAAS,kBAAkB,KAAqB,OAAwC;AAC7F,QAAM,SAAS,UAAU,GAAG;AAC5B,MAAI,WAAW,OAAQ,QAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,OAAO,MAAM,CAAC,GAAG,SAAS,KAAK;AAC/F,QAAM,IAAI,OAAO;AAEjB,QAAM,OAAY,EAAE,QAAQ,CAAC;AAC7B,QAAM,KAAY,KAAK,OAAO,QAAM,EAAE,UAAU,MAAM,QAAQ,EAAE,UAAU,KAAK,GAAG;AAClF,QAAM,SAAY,KAAK,OAAO,OAAK,EAAE,WAAW,QAAQ,EAAE,UAAU,GAAG;AACvE,QAAM,YAAY,KAAK,OAAO,OAAK,EAAE,WAAW,QAAQ,EAAE,UAAU,OAAO,EAAE,SAAS,GAAG;AAEzF,QAAM,UAAU,KAAK,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC,GAAG,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,UAAU,QAAG,IAAI,EAAE,KAAK,IAAI;AAE1G,QAAM,OAAO;AAAA,IACX,GAAG,cAAc,cAAc,MAAM,GAAG;AAAA,IACxC,KAAK,EAAE,UAAU,iBAAc,EAAE,aAAa,KAAM,QAAQ,CAAC,CAAC,IAAI,EAAE,YAAY,sBAAmB,EAAE;AAAA,IACrG;AAAA;AAAA,gBAA0B,GAAG,MAAM;AAAA,mBAAe,UAAU,MAAM;AAAA,iBAAe,OAAO,MAAM;AAAA,IAC9F;AAAA;AAAA;AAAA;AAAA,EAAmE,OAAO;AAAA,IAC1E,OAAO,SAAS;AAAA;AAAA,EAAqB,OAAO,IAAI,OAAK,KAAK,EAAE,GAAG,KAAK,EAAE,MAAM,GAAG,EAAE,KAAK,IAAI,CAAC,KAAK;AAAA,IAChG;AAAA;AAAA;AAAA;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,QAAM,UAAU;AAAA,IACd,GAAG,iBAAiB,cAAc,MAAM,GAAG;AAAA,IAC3C,GAAG,EAAE,UAAU,gBAAW,GAAG,MAAM,YAAS,OAAO,MAAM,gBAAa,UAAU,MAAM;AAAA,IACtF,OAAO,SAAS;AAAA,mBAAsB,OAAO,MAAM,GAAG,CAAC,EAAE,IAAI,OAAK,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC,KAAK;AAAA,IACxF;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO,UAAU,MAAM,OAAO;AAChC;AAKO,SAAS,kBAAkB,KAAqB,OAAwC;AAC7F,QAAM,SAAS,UAAU,GAAG;AAC5B,MAAI,WAAW,OAAQ,QAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,OAAO,MAAM,CAAC,GAAG,SAAS,KAAK;AAC/F,QAAM,IAAI,OAAO;AAEjB,QAAM,QAAQ,EAAE,SAAS,CAAC;AAE1B,QAAM,WAAW,MAAM,IAAI,CAAC,GAAG,MAAM;AACnC,UAAM,aAAa,EAAE,KAAK,MAAM,KAAK,IAAI,MAAM,MAAM,QAAQ,EAAE,MAAM,KAAK,EAAE,OAAO,SAAS,GAAG,EAAE,OAAO,MAAM,cAAc;AAC5H,WAAO,KAAK,IAAI,CAAC,MAAM,EAAE,SAAS,UAAU,MAAM,EAAE,GAAG,MAAM,UAAU;AAAA,EACzE,CAAC,EAAE,KAAK,IAAI;AAEZ,QAAM,OAAO;AAAA,IACX,GAAG,cAAc,mBAAmB,MAAM,GAAG;AAAA,IAC7C,KAAK,MAAM,MAAM,mBAAiB,EAAE,cAAc,KAAM,KAAM,QAAQ,CAAC,CAAC;AAAA,IACxE;AAAA;AAAA;AAAA;AAAA,EAA2E,QAAQ;AAAA,IACnF;AAAA;AAAA;AAAA;AAAA;AAAA,EACF,EAAE,KAAK,IAAI;AAEX,QAAM,UAAU;AAAA,IACd,GAAG,iBAAiB,mBAAmB,MAAM,GAAG,aAAQ,MAAM,MAAM;AAAA,IACpE,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,OAAK,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,KAAK,IAAI;AAAA,IAC7D,MAAM,SAAS,IAAI,gBAAW,MAAM,SAAS,CAAC,UAAU;AAAA,IACxD;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO,UAAU,MAAM,OAAO;AAChC;AAKO,SAAS,qBACd,KACA,OACgB;AAChB,QAAM,SAAS,UAAU,GAAG;AAC5B,MAAI,WAAW,OAAQ,QAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,OAAO,MAAM,CAAC,GAAG,SAAS,KAAK;AAC/F,QAAM,IAAI,OAAO;AAEjB,QAAM,SAAS,EAAE,UAAU,CAAC;AAC5B,QAAM,QAAS,MAAM,SAAS,YAAa,MAAM,iBAAiB,YAAa,IAAI,MAAM,SAAS,EAAE;AAEpG,QAAM,YAAY,OAAO;AAAA,IAAI,CAAC,GAAG,MAC/B,KAAK,IAAI,CAAC,MAAM,SAAS,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,WAAW,MAAM,EAAE,SAAS,QAAG,MAAM,EAAE,YAAY,QAAG,QAAQ,EAAE,OAAO;AAAA,EACtH,EAAE,KAAK,IAAI;AAEX,QAAM,iBAAiB,EAAE,cACrB;AAAA;AAAA,cAA6B,EAAE,YAAY,SAAS,QAAG;AAAA,qBAAwB,EAAE,YAAY,mBAAmB,QAAG,KACnH;AAEJ,QAAM,OAAO;AAAA,IACX,GAAG,cAAc,sBAAsB,KAAK;AAAA,IAC5C,KAAK,OAAO,MAAM,mBAAgB,EAAE,MAAM,aAAa,KAAM,QAAQ,CAAC,CAAC;AAAA,IACvE;AAAA,IACA;AAAA;AAAA;AAAA;AAAA,EAA8H,SAAS;AAAA,IACvI;AAAA;AAAA;AAAA;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,QAAM,OAAO,OAAO,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,OAAO,EAAE,OAAO,KAAK,EAAE,KAAK,IAAI;AAElG,QAAM,UAAU;AAAA,IACd,GAAG,iBAAiB,cAAc,KAAK,aAAQ,OAAO,MAAM;AAAA,IAC5D;AAAA;AAAA,EAAsB,IAAI;AAAA,IAC1B;AAAA;AAAA,EACF,EAAE,KAAK,IAAI;AAEX,SAAO,UAAU,MAAM,OAAO;AAChC;AAKO,SAAS,wBAAwB,KAAqB,OAA4C;AACvG,QAAM,SAAS,UAAU,GAAG;AAC5B,MAAI,WAAW,OAAQ,QAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,OAAO,MAAM,CAAC,GAAG,SAAS,KAAK;AAC/F,QAAM,IAAI,OAAO;AAEjB,QAAM,OAAS,EAAE,QAAQ;AACzB,QAAM,SAAS,EAAE,UAAU,CAAC;AAC5B,QAAM,SAAS,EAAE,cAAc,EAAE,aAAa,KAAM,QAAQ,CAAC,IAAI;AAEjE,QAAM,YAAY,OAAO,MAAM,GAAG,EAAE,EAAE,IAAI,OAAK;AAC7C,UAAM,MAAM,KAAK,MAAM,EAAE,UAAU,GAAI;AACvC,UAAM,KAAM,OAAO,KAAK,MAAM,MAAM,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;AACxD,UAAM,KAAM,OAAO,MAAM,EAAE,EAAE,SAAS,GAAG,GAAG;AAC5C,WAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,EAAE,MAAM,GAAG,CAAC;AAAA,EACjD,CAAC,EAAE,KAAK,IAAI;AAEZ,QAAM,OAAO;AAAA,IACX,GAAG,cAAc,2BAA2B,MAAM,OAAO;AAAA,IACzD,iBAAiB,MAAM,YAAS,KAAK,MAAM,GAAG,EAAE,MAAM;AAAA,IACtD;AAAA;AAAA,EAAyB,IAAI;AAAA,IAC7B,OAAO,SAAS;AAAA;AAAA;AAAA;AAAA,EAA8D,SAAS,KAAK;AAAA,IAC5F;AAAA;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,QAAM,UAAU;AAAA,IACd,GAAG,iBAAiB,2BAA2B,MAAM,OAAO,eAAU,KAAK,MAAM,GAAG,EAAE,MAAM,eAAY,MAAM;AAAA,IAC9G;AAAA;AAAA,IAAqB,SAAS,MAAM,GAAG,CAAC;AAAA,IACxC;AAAA;AAAA,EACF,EAAE,KAAK,IAAI;AAEX,SAAO,UAAU,MAAM,OAAO;AAChC;AAaO,SAAS,wBACd,KACA,OACgB;AAChB,QAAM,SAAS,UAAU,GAAG;AAC5B,MAAI,WAAW,OAAQ,QAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,OAAO,MAAM,CAAC,GAAG,SAAS,KAAK;AAC/F,QAAM,IAAI,OAAO;AAEjB,QAAM,aAAa,EAAE,kBAAkB,MAAM,SAAS,MAAM,UAAU,MAAM,aAAa;AACzF,QAAM,MAAa,EAAE,OAAO,CAAC;AAC7B,QAAM,IAAa,EAAE,WAAW,EAAE,UAAU,GAAG,aAAa,GAAG,YAAY,GAAG,YAAY,EAAE;AAE5F,QAAM,WAAW,IAAI,IAAI,CAAC,IAAI,MAAM;AAAA,IAClC,UAAU,IAAI,CAAC,GAAG,GAAG,YAAY,WAAQ,GAAG,SAAS,OAAO,EAAE,WAAM,GAAG,UAAU,QAAG,SAAM,GAAG,gBAAgB,QAAG,SAAM,GAAG,aAAa,QAAG;AAAA,IACzI,GAAG,WAAc,iBAAiB,GAAG,QAAQ,KAAK;AAAA,IAClD,GAAG,cAAc,aAAa,SAAS,GAAG,aAAa,GAAG,CAAC,KAAK;AAAA,IAChE,GAAG,MAAc,YAAY,GAAG,GAAG,KAAK;AAAA,IACxC,GAAG,WAAc,oBAAoB,GAAG,QAAQ,OAAO;AAAA,IACvD,GAAG,aAAc,mBAAmB,GAAG,UAAU,KAAK;AAAA,EACxD,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,aAAa;AAEhD,QAAM,OAAO;AAAA,IACX,GAAG,cAAc,wBAAwB,UAAU;AAAA,IACnD,KAAK,EAAE,QAAQ,eAAY,EAAE,WAAW,gBAAa,EAAE,UAAU,eAAY,EAAE,UAAU;AAAA,IACzF;AAAA,EAAK,QAAQ;AAAA,IACb;AAAA;AAAA;AAAA;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,QAAM,YAAY,IAAI,OAAO,OAAK,EAAE,QAAQ,YAAY,MAAM,QAAQ,EAAE,MAAM,GAAG,CAAC;AAClF,QAAM,YAAY,UAAU,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC,KAAK,EAAE,gBAAgB,QAAG,GAAG,EAAE,KAAK,IAAI;AACxI,QAAM,aAAa,IAAI,OAAO,OAAK,EAAE,QAAQ,EAAE;AAE/C,QAAM,UAAU;AAAA,IACd,GAAG,iBAAiB,mBAAmB,UAAU,aAAQ,EAAE,QAAQ,SAAS,EAAE,WAAW;AAAA,IACzF,YAAY;AAAA;AAAA,EAAsB,SAAS,KAAK;AAAA,IAChD,qBAAqB,EAAE,UAAU,eAAY,EAAE,UAAU;AAAA,IACzD,aAAa;AAAA,YAAQ,UAAU,oFAA+E;AAAA,EAChH,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO,UAAU,MAAM,OAAO;AAChC;AAKO,SAAS,uBAAuB,KAAqB,OAA0C;AACpG,QAAM,SAAS,UAAU,GAAG;AAC5B,MAAI,WAAW,OAAQ,QAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,OAAO,MAAM,CAAC,GAAG,SAAS,KAAK;AAC/F,QAAM,IAAI,OAAO;AAEjB,QAAM,cAAc,EAAE,WAAW,EAAE,eAAe,CAAC;AAEnD,QAAM,OAAO,YAAY;AAAA,IAAI,CAAC,GAAG,MAC/B,KAAK,IAAI,CAAC,MAAM,EAAE,IAAI,MAAM,EAAE,WAAW,QAAG,QAAQ,EAAE,aAAa,QAAG;AAAA,EACxE,EAAE,KAAK,IAAI;AAEX,QAAM,OAAO;AAAA,IACX,GAAG,cAAc,kCAAkC,MAAM,KAAK;AAAA,IAC9D,KAAK,YAAY,MAAM;AAAA,IACvB;AAAA;AAAA;AAAA;AAAA,EAAiG,IAAI;AAAA,IACrG;AAAA;AAAA;AAAA;AAAA;AAAA,EACF,EAAE,KAAK,IAAI;AAEX,QAAM,UAAU;AAAA,IACd,GAAG,iBAAiB,0BAA0B,MAAM,KAAK,cAAS,YAAY,MAAM;AAAA,IACpF,YAAY,MAAM,GAAG,CAAC,EAAE;AAAA,MAAI,CAAC,GAAG,MAC9B,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,UAAU,KAAK,EAAE,OAAO,UAAU,EAAE,aAAQ,EAAE,aAAa,QAAG;AAAA,IACxF,EAAE,KAAK,IAAI;AAAA,IACX;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO,UAAU,MAAM,OAAO;AAChC;AASO,SAAS,kBAAkB,KAAqB,OAAmE;AACxH,QAAM,SAAS,UAAU,GAAG;AAC5B,MAAI,WAAW,OAAQ,QAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,OAAO,MAAM,CAAC,GAAG,SAAS,KAAK;AAC/F,QAAM,IAAI,OAAO;AAEjB,QAAM,UAAU,EAAE;AAClB,QAAM,QAAS,EAAE,SAA2C,CAAC;AAC7D,QAAM,UAAU,EAAE;AAClB,QAAM,SAAU,EAAE,UAA8C,CAAC;AAEjE,QAAM,WAAW,MAAM,IAAI,OAAK;AAC9B,UAAM,QAAQ,EAAE,QAAQ,IAAI,EAAE,KAAK,KAAK;AACxC,WAAO,KAAK,EAAE,KAAK,MAAM,EAAE,OAAO,MAAM,EAAE,IAAI,GAAG,KAAK;AAAA,EACxD,CAAC,EAAE,KAAK,IAAI;AAEZ,QAAM,aAAa,OAAO,IAAI,SAAO;AACnC,UAAM,UAAU,IAAI,YAAY;AAChC,WAAO,KAAK,IAAI,UAAU,MAAM,IAAI,SAAS,MAAM,OAAO,MAAM,IAAI,eAAe,EAAE;AAAA,EACvF,CAAC,EAAE,KAAK,IAAI;AAEZ,QAAM,iBAAiB,UACnB;AAAA;AAAA,IAAwB,QAAQ,KAAK,OAAO,QAAQ,OAAO,YAAY,QAAQ,IAAI,GAAG,QAAQ,QAAQ;AAAA;AAAA,EAAO,QAAQ,KAAK,KAAK,EAAE,KACjI,MAAM,OACJ;AAAA;AAAA,iCAAqD,MAAM,IAAI,sCAC/D;AAEN,QAAM,OAAO;AAAA,IACX,GAAG,cAAc;AAAA,IACjB,gBAAgB,WAAW,SAAS;AAAA,IACpC;AAAA,IACA,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA,EAA0E,QAAQ,KAAK;AAAA,IACtG,OAAO,SAAS;AAAA;AAAA;AAAA;AAAA,EAAmH,UAAU,KAAK;AAAA,EACpJ,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,QAAM,UAAU;AAAA,IACd,GAAG,iBAAiB,uBAAuB,WAAW,SAAS;AAAA,IAC/D,UAAU;AAAA,IAAO,QAAQ,KAAK,OAAO,QAAQ,OAAO,YAAY,QAAQ,IAAI,KAAK;AAAA,IACjF,MAAM,iBAAiB,OAAO,SAAS;AAAA,sDAAyD;AAAA,EAClG,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO,UAAU,MAAM,OAAO;AAChC;AAEO,SAAS,qBACd,KACA,OACgB;AAChB,QAAM,SAAS,UAAU,GAAG;AAC5B,MAAI,WAAW,OAAQ,QAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,OAAO,MAAM,CAAC,GAAG,SAAS,KAAK;AAC/F,QAAM,IAAI,OAAO;AAEjB,QAAM,OAAgB,EAAE,QAA0B,MAAM;AACxD,QAAM,SAAe,EAAE;AACvB,QAAM,cAAe,EAAE;AACvB,QAAM,WAAe,EAAE;AACvB,QAAM,UAAe,EAAE;AACvB,QAAM,QAAe,EAAE;AACvB,QAAM,UAAe,EAAE;AACvB,QAAM,eAAe,EAAE;AACvB,QAAM,WAAe,EAAE;AACvB,QAAM,aAAe,EAAE;AACvB,QAAM,QAAe,EAAE;AACvB,QAAM,aAAe,EAAE;AACvB,QAAM,SAAe,EAAE;AACvB,QAAM,MAAe,EAAE;AACvB,QAAM,MAAe,EAAE;AACvB,QAAM,aAAe,EAAE;AAEvB,QAAM,YAAe,EAAE,mBAA4C,CAAC;AACpE,QAAM,SAAe,EAAE,gBAAuC,CAAC;AAC/D,QAAM,QAAe,EAAE,mBAAwC,CAAC;AAChE,QAAM,UAAe,EAAE,WAAuC,CAAC;AAE/D,QAAM,aAAc,EAAE,cAAwD,CAAC;AAE/E,QAAM,aAAa,CAAC,QAAQ,cAAc,IAAI,WAAW,cAAc,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAErG,QAAM,aAAa;AAAA,IACjB,UAAe,kBAAkB,OAAO,KAAK;AAAA,IAC7C,QAAe,gBAAgB,KAAK,KAAK;AAAA,IACzC,UAAe,kBAAkB,OAAO,KAAK;AAAA,IAC7C,eAAe,gBAAgB,YAAY,KAAK;AAAA,IAChD,WAAe,oBAAoB,QAAQ,KAAK;AAAA,IAChD,aAAe,eAAe,UAAU,KAAK;AAAA,EAC/C,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,QAAM,eAAe,WAAW,SAC5B;AAAA;AAAA;AAAA;AAAA,EAAiD,WAAW,IAAI,OAAK,KAAK,EAAE,GAAG,MAAM,EAAE,KAAK,IAAI,EAAE,KAAK,IAAI,CAAC,KAC5G;AAEJ,QAAM,cAAc,UAAU,SAC1B;AAAA;AAAA;AAAA;AAAA,EAAmE,UAAU,IAAI,OAAK,KAAK,SAAI,OAAO,EAAE,KAAK,CAAC,GAAG,SAAI,OAAO,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,KAAK,IAAI,CAAC,KACrK;AAEJ,QAAM,gBAAgB,OAAO,SACzB;AAAA;AAAA,EAAuB,OAAO,IAAI,OAAK,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,IAAI,CAAC,KAC1F;AAEJ,QAAM,iBAA2C,CAAC;AAClD,aAAW,KAAK,OAAO;AACrB,QAAI,CAAC,eAAe,EAAE,OAAO,EAAG,gBAAe,EAAE,OAAO,IAAI,CAAC;AAC7D,mBAAe,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EAC5C;AACA,QAAM,eAAe,OAAO,KAAK,cAAc,EAAE,SAC7C;AAAA;AAAA,EAAe,OAAO,QAAQ,cAAc,EAAE,IAAI,CAAC,CAAC,GAAG,KAAK,MAAM,KAAK,CAAC;AAAA,EAAO,MAAM,IAAI,OAAK,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,EAAE,KAAK,MAAM,CAAC,KAClI;AAEJ,QAAM,gBAAgB;AAAA,IACpB,QAAa,kBAAkB,KAAK,OAAO;AAAA,IAC3C,aAAa,gBAAgB,UAAU,OAAO;AAAA,IAC9C,SAAa,uBAAuB,MAAM,KAAK;AAAA,IAC/C,OAAO,QAAQ,OAAO,OAAO,sBAAsB,GAAG,KAAK,GAAG,KAAK;AAAA,EACrE,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,QAAM,iBAAiB,QAAQ,SAC3B;AAAA,cAAiB,QAAQ,MAAM;AAAA,EAAM,QAAQ,IAAI,CAAC,GAAG,MAAM;AACzD,UAAM,SAAS,SAAS,EAAE,SAAS,GAAG;AACtC,UAAM,QAAS,SAAI,OAAO,MAAM,IAAI,SAAI,OAAO,IAAI,MAAM;AACzD,WAAO,OAAO,IAAI,CAAC,KAAK,EAAE,UAAU,WAAW,WAAM,KAAK;AAAA,GAAM,EAAE,QAAQ,EAAE;AAAA;AAAA,EAAQ,EAAE,QAAQ,EAAE;AAAA,EAClG,CAAC,EAAE,KAAK,MAAM,CAAC,KACf;AAEJ,QAAM,OAAO;AAAA,IACX,GAAG,cAAc,KAAK,IAAI;AAAA,IAC1B,WAAa,IAAI,QAAQ,MAAM;AAAA,IAC/B,aAAa;AAAA,cAAiB,UAAU,KAAK;AAAA,IAC7C,aAAa;AAAA,EAAK,UAAU,KAAK;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA;AAAA,EAAoB,aAAa,KAAK;AAAA,IACtD;AAAA,IACA,cAAc,OAAO;AAAA;AAAA,iBAAyB,aAAa,KAAM,QAAQ,CAAC,CAAC,OAAO;AAAA,EACpF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,QAAM,UAAU;AAAA,IACd,GAAG,iBAAiB,KAAK,IAAI,aAAQ,YAAY,UAAU,SAAM,cAAc,WAAW;AAAA,IAC1F,UAAe,aAAM,OAAO,KAAK;AAAA,IACjC,QAAe,aAAM,KAAK,KAAK;AAAA,IAC/B,eAAe,aAAM,YAAY,KAAK;AAAA,IACtC,UAAe,aAAM,OAAO,KAAK;AAAA,IACjC,QAAQ,SAAS;AAAA,YAAQ,QAAQ,MAAM,wDAAmD;AAAA,EAC5F,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,SAAO,UAAU,MAAM,OAAO;AAChC;AAEO,SAAS,2BAA2B,KAAqB,OAA6C;AAC3G,QAAM,SAAS,UAAU,GAAG;AAC5B,MAAI,WAAW,OAAQ,QAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,OAAO,MAAM,CAAC,GAAG,SAAS,KAAK;AAC/F,QAAM,IAAI,OAAO;AAEjB,QAAM,OAAS,EAAE,QAAQ;AACzB,QAAM,SAAS,EAAE,UAAU,CAAC;AAC5B,QAAM,SAAS,EAAE,cAAc,EAAE,aAAa,KAAM,QAAQ,CAAC,IAAI;AAEjE,QAAM,YAAY,OAAO,MAAM,GAAG,EAAE,EAAE,IAAI,OAAK;AAC7C,UAAM,MAAM,KAAK,MAAM,EAAE,UAAU,GAAI;AACvC,UAAM,KAAM,OAAO,KAAK,MAAM,MAAM,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;AACxD,UAAM,KAAM,OAAO,MAAM,EAAE,EAAE,SAAS,GAAG,GAAG;AAC5C,WAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,EAAE,MAAM,GAAG,CAAC;AAAA,EACjD,CAAC,EAAE,KAAK,IAAI;AAEZ,QAAM,OAAO;AAAA,IACX,GAAG,cAAc;AAAA,IACjB,iBAAiB,MAAM,YAAS,KAAK,MAAM,GAAG,EAAE,MAAM;AAAA,IACtD;AAAA;AAAA,EAAyB,IAAI;AAAA,IAC7B,OAAO,SAAS;AAAA;AAAA;AAAA;AAAA,EAA8D,SAAS,KAAK;AAAA,IAC5F;AAAA;AAAA;AAAA,EACF,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,QAAM,UAAU;AAAA,IACd,GAAG,iBAAiB,qCAAgC,KAAK,MAAM,GAAG,EAAE,MAAM,eAAY,MAAM;AAAA,IAC5F;AAAA;AAAA,IAAqB,SAAS,MAAM,GAAG,CAAC;AAAA,IACxC;AAAA;AAAA,EACF,EAAE,KAAK,IAAI;AAEX,SAAO,UAAU,MAAM,OAAO;AAChC;;;AFjnBO,SAAS,2BAA2B,UAAuC;AAChF,QAAM,SAAS,IAAI,UAAU,EAAE,MAAM,iBAAiB,SAAS,QAAQ,CAAC;AAExE,SAAO,aAAa,eAAe;AAAA,IACjC,aAAa;AAAA,IACb,aAAa;AAAA,EACf,GAAG,OAAO,UAAU,iBAAiB,MAAM,SAAS,WAAW,KAAK,GAAG,KAAK,CAAC;AAE7E,SAAO,aAAa,eAAe;AAAA,IACjC,aAAa;AAAA,IACb,aAAa;AAAA,EACf,GAAG,OAAO,UAAU,iBAAiB,MAAM,SAAS,WAAW,KAAK,GAAG,KAAK,CAAC;AAE7E,SAAO,aAAa,eAAe;AAAA,IACjC,aAAa;AAAA,IACb,aAAa;AAAA,EACf,GAAG,OAAO,UAAU,iBAAiB,MAAM,SAAS,WAAW,KAAK,GAAG,KAAK,CAAC;AAE7E,SAAO,aAAa,iBAAiB;AAAA,IACnC,aAAa;AAAA,IACb,aAAa;AAAA,EACf,GAAG,OAAO,UAAU,kBAAkB,MAAM,SAAS,YAAY,KAAK,GAAG,KAAK,CAAC;AAE/E,SAAO,aAAa,gBAAgB;AAAA,IAClC,aAAa;AAAA,IACb,aAAa;AAAA,EACf,GAAG,OAAO,UAAU,kBAAkB,MAAM,SAAS,YAAY,KAAK,GAAG,KAAK,CAAC;AAE/E,SAAO,aAAa,mBAAmB;AAAA,IACrC,aAAa;AAAA,IACb,aAAa;AAAA,EACf,GAAG,OAAO,UAAU,qBAAqB,MAAM,SAAS,eAAe,KAAK,GAAG,KAAK,CAAC;AAErF,SAAO,aAAa,sBAAsB;AAAA,IACxC,aAAa;AAAA,IACb,aAAa;AAAA,EACf,GAAG,OAAO,UAAU,wBAAwB,MAAM,SAAS,kBAAkB,KAAK,GAAG,KAAK,CAAC;AAE3F,SAAO,aAAa,uBAAuB;AAAA,IACzC,aAAa;AAAA,IACb,aAAa;AAAA,EACf,GAAG,OAAO,UAAU,wBAAwB,MAAM,SAAS,kBAAkB,KAAK,GAAG,KAAK,CAAC;AAE3F,SAAO,aAAa,sBAAsB;AAAA,IACxC,aAAa;AAAA,IACb,aAAa;AAAA,EACf,GAAG,OAAO,UAAU,uBAAuB,MAAM,SAAS,iBAAiB,KAAK,GAAG,KAAK,CAAC;AAEzF,SAAO,aAAa,0BAA0B;AAAA,IAC5C,aAAa;AAAA,IACb,aAAa;AAAA,EACf,GAAG,OAAO,UAAU,2BAA2B,MAAM,SAAS,qBAAqB,KAAK,GAAG,KAAK,CAAC;AAEjG,SAAO,aAAa,oBAAoB;AAAA,IACtC,aAAa;AAAA,IACb,aAAa;AAAA,EACf,GAAG,OAAO,UAAU,qBAAqB,MAAM,SAAS,eAAe,KAAK,GAAG,KAAK,CAAC;AAErF,SAAO,aAAa,gBAAgB;AAAA,IAClC,aAAa;AAAA,IACb,aAAa;AAAA,EACf,GAAG,OAAO,UAAU,kBAAkB,MAAM,SAAS,YAAY,KAAK,GAAG,KAAK,CAAC;AAE/E,SAAO;AACT;;;AG9EO,IAAM,sBAAN,MAAsD;AAAA,EAC1C;AAAA,EACA;AAAA,EAEjB,YAAY,SAAiB,QAAgB;AAC3C,SAAK,UAAU,QAAQ,QAAQ,OAAO,EAAE;AACxC,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,MAAc,KAAK,MAAc,MAAwD;AACvF,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,QAChD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,aAAa,KAAK;AAAA,QACpB;AAAA,QACA,MAAM,KAAK,UAAU,IAAI;AAAA,QACzB,QAAQ,YAAY,QAAQ,IAAO;AAAA,MACrC,CAAC;AACD,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAI,CAAC,IAAI,IAAI;AACX,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,IAAI,EAAE,CAAC,GAAG,SAAS,KAAK;AAAA,MAClF;AACA,aAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,IAAI,EAAE,CAAC,EAAE;AAAA,IACnE,SAAS,KAAK;AACZ,YAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,aAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,IAAI,CAAC,GAAG,SAAS,KAAK;AAAA,IACjE;AAAA,EACF;AAAA,EAEA,WAAW,OAAiD;AAC1D,WAAO,KAAK,KAAK,iBAAiB,KAAgC;AAAA,EACpE;AAAA,EAEA,WAAW,OAAiD;AAC1D,WAAO,KAAK,KAAK,iBAAiB,EAAE,GAAG,OAAO,UAAU,KAAK,CAA4B;AAAA,EAC3F;AAAA,EAEA,WAAW,OAAiD;AAC1D,WAAO,KAAK,KAAK,gBAAgB,KAAgC;AAAA,EACnE;AAAA,EAEA,YAAY,OAAkD;AAC5D,WAAO,KAAK,KAAK,aAAa,KAAgC;AAAA,EAChE;AAAA,EAEA,YAAY,OAAkD;AAC5D,WAAO,KAAK,KAAK,iBAAiB,KAAgC;AAAA,EACpE;AAAA,EAEA,eAAe,OAAqD;AAClE,WAAO,KAAK,KAAK,oBAAoB,KAAgC;AAAA,EACvE;AAAA,EAEA,kBAAkB,OAAwD;AACxE,WAAO,KAAK,KAAK,uBAAuB,KAAgC;AAAA,EAC1E;AAAA,EAEA,kBAAkB,OAAwD;AACxE,WAAO,KAAK,KAAK,wBAAwB,KAAgC;AAAA,EAC3E;AAAA,EAEA,iBAAiB,OAAuD;AACtE,WAAO,KAAK,KAAK,oBAAoB,KAAgC;AAAA,EACvE;AAAA,EAEA,qBAAqB,OAA2D;AAC9E,WAAO,KAAK,KAAK,wBAAwB,KAAgC;AAAA,EAC3E;AAAA,EAEA,eAAe,OAAqD;AAClE,WAAO,KAAK,KAAK,eAAe,KAAgC;AAAA,EAClE;AAAA,EAEA,YAAY,OAAkD;AAC5D,WAAO,KAAK,KAAK,oBAAoB,KAAgC;AAAA,EACvE;AACF;","names":[]}
@@ -0,0 +1,87 @@
1
+ import {
2
+ SiteAuditJobRowSchema,
3
+ SiteAuditPhaseLogRowSchema,
4
+ claimPendingJob,
5
+ claimPendingKpoJob,
6
+ completeJob,
7
+ completeKpoJob,
8
+ countActiveJobsForUser,
9
+ countActiveUsers,
10
+ countJobsLast7Days,
11
+ createJob,
12
+ createKpoJob,
13
+ createRunningJob,
14
+ createUser,
15
+ creditMc,
16
+ deactivateUser,
17
+ debitMc,
18
+ failJob,
19
+ failKpoJob,
20
+ generateApiKey,
21
+ getDb,
22
+ getJob,
23
+ getKpoJob,
24
+ getKpoPhaseLog,
25
+ getLedger,
26
+ getUserByApiKey,
27
+ getUserByEmail,
28
+ getUserById,
29
+ getUserByStripeCustomerId,
30
+ getUserStats,
31
+ hashPassword,
32
+ listJobs,
33
+ listKpoJobs,
34
+ listUsers,
35
+ logKpoPhaseComplete,
36
+ migrate,
37
+ revokeApiKey,
38
+ rotateApiKey,
39
+ setPassword,
40
+ setStripeCustomerId,
41
+ updateKpoJobState,
42
+ verifyPassword
43
+ } from "./chunk-LXZDJJXR.js";
44
+ export {
45
+ SiteAuditJobRowSchema,
46
+ SiteAuditPhaseLogRowSchema,
47
+ claimPendingJob,
48
+ claimPendingKpoJob,
49
+ completeJob,
50
+ completeKpoJob,
51
+ countActiveJobsForUser,
52
+ countActiveUsers,
53
+ countJobsLast7Days,
54
+ createJob,
55
+ createKpoJob,
56
+ createRunningJob,
57
+ createUser,
58
+ creditMc,
59
+ deactivateUser,
60
+ debitMc,
61
+ failJob,
62
+ failKpoJob,
63
+ generateApiKey,
64
+ getDb,
65
+ getJob,
66
+ getKpoJob,
67
+ getKpoPhaseLog,
68
+ getLedger,
69
+ getUserByApiKey,
70
+ getUserByEmail,
71
+ getUserById,
72
+ getUserByStripeCustomerId,
73
+ getUserStats,
74
+ hashPassword,
75
+ listJobs,
76
+ listKpoJobs,
77
+ listUsers,
78
+ logKpoPhaseComplete,
79
+ migrate,
80
+ revokeApiKey,
81
+ rotateApiKey,
82
+ setPassword,
83
+ setStripeCustomerId,
84
+ updateKpoJobState,
85
+ verifyPassword
86
+ };
87
+ //# sourceMappingURL=db-IOYMX64U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}